From: bbahnsen Date: Fri, 21 Apr 2006 22:54:32 +0000 (+0000) Subject: Initial import. X-Git-Tag: edk2-stable201903~25606 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=878ddf1fc3540a715f63594ed22b6929e881afb4 Initial import. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@3 6f19259b-4bc3-4df7-8a09-765794883524 --- 878ddf1fc3540a715f63594ed22b6929e881afb4 diff --git a/DeveloperManual.doc b/DeveloperManual.doc new file mode 100644 index 0000000000..f8a6b90c1c Binary files /dev/null and b/DeveloperManual.doc differ diff --git a/EdkFatBinPkg/EdkFatBinPkg.spd b/EdkFatBinPkg/EdkFatBinPkg.spd new file mode 100644 index 0000000000..3a739581a5 --- /dev/null +++ b/EdkFatBinPkg/EdkFatBinPkg.spd @@ -0,0 +1,40 @@ + + + + + EdkFatBinPkg + 0fd7197b-9bde-44fe-a7e4-d2177a9922e5 + 0 + This is the Binary Package for the FAT dirver + This package provides FAT drivers which are not licensed under BSD. + Copyright (c) 2004, 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. + + 2006-03-05 09:49 + 2006-03-19 16:18 + http://www.TianoCore.org + BINARY + true + false + + + + Fat.msa + + + diff --git a/EdkFatBinPkg/Fat.mbd b/EdkFatBinPkg/Fat.mbd new file mode 100644 index 0000000000..ab6d27094d --- /dev/null +++ b/EdkFatBinPkg/Fat.mbd @@ -0,0 +1,34 @@ + + + + + Fat + 5058F21C-BC34-11d4-BD18-0080C73C8881 + 0 + This is the FAT 32 EFI/Tiano Driver + + Copyright 2004, 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. + + 2006-03-17 20:56 + 2006-03-19 16:17 + + + + + diff --git a/EdkFatBinPkg/Fat.msa b/EdkFatBinPkg/Fat.msa new file mode 100644 index 0000000000..71a0739b16 --- /dev/null +++ b/EdkFatBinPkg/Fat.msa @@ -0,0 +1,53 @@ + + + + + Fat + PEIM + BS_DRIVER + 5058F21C-BC34-11d4-BD18-0080C73C8881 + 0 + Make a FFS section for an FV that contains the FAT driver.*.FFS files are compressed FFS sections. + This is the FAT 32 EFI/Tiano Driver + Copyright 2004, 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. + + 0 + 2006-03-17 20:56 + 2006-03-19 16:17 + + + + Fat.FFS + + + Fat.FFS + + + Fat.FFS + + + + + + + + + + + diff --git a/EdkFatBinPkg/Fat_build.xml b/EdkFatBinPkg/Fat_build.xml new file mode 100644 index 0000000000..e99c13ffac --- /dev/null +++ b/EdkFatBinPkg/Fat_build.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EdkFatBinPkg/Ia32/Fat.FFS b/EdkFatBinPkg/Ia32/Fat.FFS new file mode 100644 index 0000000000..ccb9b6609b Binary files /dev/null and b/EdkFatBinPkg/Ia32/Fat.FFS differ diff --git a/EdkFatBinPkg/Ipf/Fat.FFS b/EdkFatBinPkg/Ipf/Fat.FFS new file mode 100644 index 0000000000..5989987b62 Binary files /dev/null and b/EdkFatBinPkg/Ipf/Fat.FFS differ diff --git a/EdkFatBinPkg/X64/Fat.FFS b/EdkFatBinPkg/X64/Fat.FFS new file mode 100644 index 0000000000..fa76edc599 Binary files /dev/null and b/EdkFatBinPkg/X64/Fat.FFS differ diff --git a/EdkFatBinPkg/build.xml b/EdkFatBinPkg/build.xml new file mode 100644 index 0000000000..e3d4dc4e95 --- /dev/null +++ b/EdkFatBinPkg/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkFatBinPkg/genbuildfile.xml b/EdkFatBinPkg/genbuildfile.xml new file mode 100644 index 0000000000..4b60c0cbe5 --- /dev/null +++ b/EdkFatBinPkg/genbuildfile.xml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/EdkModulePkg/Application/HelloWorld/HelloWorld.c b/EdkModulePkg/Application/HelloWorld/HelloWorld.c new file mode 100644 index 0000000000..f3eda071e4 --- /dev/null +++ b/EdkModulePkg/Application/HelloWorld/HelloWorld.c @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + HelloWorld.c + +Abstract: + + This driver supports platform security service + +--*/ + +VOID +Print ( + IN CONST CHAR16 *Format, + ... + ) +{ + CHAR16 PrintBuffer[0x100]; + VA_LIST Marker; + + VA_START (Marker, Format); + UnicodeVSPrint (PrintBuffer, sizeof (PrintBuffer), Format, Marker); + gST->ConOut->OutputString (gST->ConOut, PrintBuffer); + return; +} + +EFI_STATUS +EFIAPI +UefiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + +{ + Print ((CHAR16 *)L"UEFI Hello World!\n"); + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Application/HelloWorld/HelloWorld.mbd b/EdkModulePkg/Application/HelloWorld/HelloWorld.mbd new file mode 100644 index 0000000000..6d44bac022 --- /dev/null +++ b/EdkModulePkg/Application/HelloWorld/HelloWorld.mbd @@ -0,0 +1,43 @@ + + + + + HelloWorld + 6987936E-ED34-44db-AE97-1FA5E4ED2116 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-20 20:41 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDebugLibStdErr + BasePrintLib + + + _ModuleEntryPoint + + + diff --git a/EdkModulePkg/Application/HelloWorld/HelloWorld.msa b/EdkModulePkg/Application/HelloWorld/HelloWorld.msa new file mode 100644 index 0000000000..92fca0ff91 --- /dev/null +++ b/EdkModulePkg/Application/HelloWorld/HelloWorld.msa @@ -0,0 +1,51 @@ + + + + + HelloWorld + DXE_DRIVER + APPLICATION + 6987936E-ED34-44db-AE97-1FA5E4ED2116 + 0 + Component description file for SecurityStub module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-20 20:41 + + + PrintLib + DebugLib + UefiBootServicesTableLib + UefiDriverEntryPoint + + + HelloWorld.c + + + MdePkg + + + + UefiMain + + + diff --git a/EdkModulePkg/Application/HelloWorld/build.xml b/EdkModulePkg/Application/HelloWorld/build.xml new file mode 100644 index 0000000000..d8531c33e2 --- /dev/null +++ b/EdkModulePkg/Application/HelloWorld/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.c b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.c new file mode 100644 index 0000000000..6fe81d1521 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.c @@ -0,0 +1,2226 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + AtapiPassThru.c + +Abstract: + + +Revision History +--*/ + +#include "AtapiPassThru.h" + +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// IDE registers' fixed address +// +static IDE_BASE_REGISTERS gAtapiIoPortRegisters[2] = { + { 0x1f0, { 0x1f1 }, 0x1f2, 0x1f3, 0x1f4, 0x1f5, 0x1f6, { 0x1f7 }, { 0x3f6 }, 0x3f7, 0 }, + { 0x170, { 0x171 }, 0x172, 0x173, 0x174, 0x175, 0x176, { 0x177 }, { 0x376 }, 0x377, 0 } +}; + +static SCSI_COMMAND_SET gEndTable = { 0xff, 0xff }; + +// +// This table contains all the supported ATAPI commands. +// +static SCSI_COMMAND_SET gSupportedATAPICommands[] = { + { OP_INQUIRY, DataIn }, + { OP_LOAD_UNLOAD_CD, NoData }, + { OP_MECHANISM_STATUS, DataIn }, + { OP_MODE_SELECT_10, DataOut }, + { OP_MODE_SENSE_10, DataIn }, + { OP_PAUSE_RESUME, NoData }, + { OP_PLAY_AUDIO_10, DataIn }, + { OP_PLAY_AUDIO_MSF, DataIn }, + { OP_PLAY_CD, DataIn }, + { OP_PLAY_CD_MSF, DataIn }, + { OP_PREVENT_ALLOW_MEDIUM_REMOVAL,NoData }, + { OP_READ_10, DataIn }, + { OP_READ_12, DataIn }, + { OP_READ_CAPACITY, DataIn }, + { OP_READ_CD, DataIn }, + { OP_READ_CD_MSF, DataIn }, + { OP_READ_HEADER, DataIn }, + { OP_READ_SUB_CHANNEL, DataIn }, + { OP_READ_TOC, DataIn }, + { OP_REQUEST_SENSE, DataIn }, + { OP_SCAN, NoData }, + { OP_SEEK_10, NoData }, + { OP_SET_CD_SPEED, DataOut }, + { OP_STOPPLAY_SCAN, NoData }, + { OP_START_STOP_UNIT, NoData }, + { OP_TEST_UNIT_READY, NoData }, + { OP_FORMAT_UNIT, DataOut }, + { OP_READ_FORMAT_CAPACITIES, DataIn }, + { OP_VERIFY, DataOut }, + { OP_WRITE_10, DataOut }, + { OP_WRITE_12, DataOut }, + { OP_WRITE_AND_VERIFY, DataOut }, + { 0xff, 0xff } +}; + +static CHAR16 *gControllerNameString = (CHAR16 *) L"ATAPI Controller"; +static CHAR16 *gAtapiChannelString = (CHAR16 *) L"ATAPI Channel"; + +EFI_DRIVER_BINDING_PROTOCOL gAtapiScsiPassThruDriverBinding = { + AtapiScsiPassThruDriverBindingSupported, + AtapiScsiPassThruDriverBindingStart, + AtapiScsiPassThruDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Supported. + + Arguments: + (Standard DriverBinding Protocol Supported() function) + + Returns: + EFI_STATUS + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Use the PCI I/O Protocol to see if Controller is a IDE Controller that + // can be managed by this driver. Read the PCI Configuration Header + // for this device. + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_UNSUPPORTED; + } + + if (Pci.Hdr.ClassCode[2] != PCI_CLASS_MASS_STORAGE || Pci.Hdr.ClassCode[1] != PCI_CLASS_IDE) { + + Status = EFI_UNSUPPORTED; + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Create handles for IDE channels specified by RemainingDevicePath. + Install SCSI Pass Thru Protocol onto each created handle. + + Arguments: + (Standard DriverBinding Protocol Start() function) + + Returns: + EFI_STATUS + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + + PciIo = NULL; + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE, + NULL + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Create SCSI Pass Thru instance for the IDE channel. + // + Status = RegisterAtapiScsiPassThru (This, Controller, PciIo); + +Done: + if (EFI_ERROR (Status)) { + if (PciIo) { + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE, + NULL + ); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop. + + Arguments: + (Standard DriverBinding Protocol Stop() function) + + Returns: + EFI_STATUS + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: NumberOfChildren - add argument and description to function comment +// TODO: ChildHandleBuffer - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + (VOID **) &ScsiPassThru, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (ScsiPassThru); + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiScsiPassThruProtocolGuid, + &AtapiScsiPrivate->ScsiPassThru + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Release Pci Io protocol on the controller handle. + // + AtapiScsiPrivate->PciIo->Attributes ( + AtapiScsiPrivate->PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE, + NULL + ); + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->FreePool (AtapiScsiPrivate); + + return EFI_SUCCESS; +} + +EFI_STATUS +RegisterAtapiScsiPassThru ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +/*++ + + Routine Description: + Attaches SCSI Pass Thru Protocol for specified IDE channel. + + Arguments: + Controller: Parent device handle to the IDE channel. + PciIo: PCI I/O protocol attached on the "Controller". + + Returns: + Always return EFI_SUCCESS unless installing SCSI Pass Thru Protocol failed. +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: PciIo - add argument and description to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +{ + EFI_STATUS Status; + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + UINT64 Attributes; + + AtapiScsiPrivate = AllocateZeroPool (sizeof (ATAPI_SCSI_PASS_THRU_DEV)); + if (AtapiScsiPrivate == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Attributes = EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE; + CopyMem (AtapiScsiPrivate->ChannelName, gAtapiChannelString, sizeof (gAtapiChannelString)); + + // + // Enable channel + // + PciIo->Attributes (PciIo, EfiPciIoAttributeOperationSet, Attributes, NULL); + + AtapiScsiPrivate->Signature = ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE; + AtapiScsiPrivate->Handle = Controller; + + // + // will reset the IoPort inside each API function. + // + AtapiScsiPrivate->IoPort = gAtapiIoPortRegisters; + AtapiScsiPrivate->PciIo = PciIo; + + // + // initialize SCSI Pass Thru Protocol interface + // + AtapiScsiPrivate->ScsiPassThru.Mode = &AtapiScsiPrivate->ScsiPassThruMode; + AtapiScsiPrivate->ScsiPassThru.PassThru = AtapiScsiPassThruFunction; + AtapiScsiPrivate->ScsiPassThru.GetNextDevice = AtapiScsiPassThruGetNextDevice; + AtapiScsiPrivate->ScsiPassThru.BuildDevicePath = AtapiScsiPassThruBuildDevicePath; + AtapiScsiPrivate->ScsiPassThru.GetTargetLun = AtapiScsiPassThruGetTargetLun; + AtapiScsiPrivate->ScsiPassThru.ResetChannel = AtapiScsiPassThruResetChannel; + AtapiScsiPrivate->ScsiPassThru.ResetTarget = AtapiScsiPassThruResetTarget; + + // + // Set Mode + // + CopyMem (AtapiScsiPrivate->ControllerName, gControllerNameString, sizeof (gControllerNameString)); + + AtapiScsiPrivate->ScsiPassThruMode.ControllerName = AtapiScsiPrivate->ControllerName; + AtapiScsiPrivate->ScsiPassThruMode.ChannelName = AtapiScsiPrivate->ChannelName; + AtapiScsiPrivate->ScsiPassThruMode.AdapterId = 4; + // + // non-RAID SCSI controllers should set both physical and logical attributes + // + AtapiScsiPrivate->ScsiPassThruMode.Attributes = EFI_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL | + EFI_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL; + AtapiScsiPrivate->ScsiPassThruMode.IoAlign = 0; + + // + // Initialize the LatestTargetId to 0xFFFFFFFF (for the GetNextDevice() call). + // + AtapiScsiPrivate->LatestTargetId = 0xFFFFFFFF; + AtapiScsiPrivate->LatestLun = 0; + + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiScsiPassThruProtocolGuid, + EFI_NATIVE_INTERFACE, + &AtapiScsiPrivate->ScsiPassThru + ); + return Status; +} + +EFI_STATUS +EFIAPI +AtapiScsiPassThruFunction ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ) +/*++ + + Routine Description: + Implements EFI_SCSI_PASS_THRU_PROTOCOL.PassThru() function. + + Arguments: + This: The EFI_SCSI_PASS_THRU_PROTOCOL instance. + Target: The Target ID of the ATAPI device to send the SCSI + Request Packet. To ATAPI devices attached on an IDE + Channel, Target ID 0 indicates Master device;Target + ID 1 indicates Slave device. + Lun: The LUN of the ATAPI device to send the SCSI Request + Packet. To the ATAPI device, Lun is always 0. + Packet: The SCSI Request Packet to send to the ATAPI device + specified by Target and Lun. + Event: If non-blocking I/O is not supported then Event is ignored, + and blocking I/O is performed. + If Event is NULL, then blocking I/O is performed. + If Event is not NULL and non blocking I/O is supported, + then non-blocking I/O is performed, and Event will be signaled + when the SCSI Request Packet completes. + + Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + EFI_STATUS Status; + + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); + + // + // Target is not allowed beyond MAX_TARGET_ID + // + if (Target > MAX_TARGET_ID) { + return EFI_INVALID_PARAMETER; + } + + // + // check the data fields in Packet parameter. + // + Status = CheckSCSIRequestPacket (Packet); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If Request Packet targets at the IDE channel itself, + // do nothing. + // + if (Target == This->Mode->AdapterId) { + Packet->TransferLength = 0; + return EFI_SUCCESS; + } + + // + // According to Target ID, reset the Atapi I/O Register mapping + // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0], + // Target Id in [2,3] area, using gAtapiIoPortRegisters[1] + // + if ((Target / 2) == 0) { + AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0]; + } else { + AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1]; + } + + // + // the ATAPI SCSI interface does not support non-blocking I/O + // ignore the Event parameter + // + // Performs blocking I/O. + // + Status = SubmitBlockingIoCommand (AtapiScsiPrivate, Target, Packet); + return Status; +} + +EFI_STATUS +EFIAPI +AtapiScsiPassThruGetNextDevice ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT32 *Target, + IN OUT UINT64 *Lun + ) +/*++ + + Routine Description: + Used to retrieve the list of legal Target IDs for SCSI devices + on a SCSI channel. + + Arguments: + This - Protocol instance pointer. + Target - On input, a pointer to the Target ID of a SCSI + device present on the SCSI channel. On output, + a pointer to the Target ID of the next SCSI device + present on a SCSI channel. An input value of + 0xFFFFFFFF retrieves the Target ID of the first + SCSI device present on a SCSI channel. + Lun - On input, a pointer to the LUN of a SCSI device + present on the SCSI channel. On output, a pointer + to the LUN of the next SCSI device present on + a SCSI channel. + + Returns: + EFI_SUCCESS - The Target ID and Lun of the next SCSI device + on the SCSI channel was returned in Target and Lun. + EFI_NOT_FOUND - There are no more SCSI devices on this SCSI channel. + EFI_INVALID_PARAMETER - Target is not 0xFFFFFFFF,and Target and Lun were not + returned on a previous call to GetNextDevice(). +--*/ +{ + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + + // + // Retrieve Device Private Data Structure. + // + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); + + // + // Check whether Target is valid. + // + if (Target == NULL || Lun == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((*Target != 0xFFFFFFFF) && + ((*Target != AtapiScsiPrivate->LatestTargetId) || + (*Lun != AtapiScsiPrivate->LatestLun))) { + return EFI_INVALID_PARAMETER; + } + + if (*Target == MAX_TARGET_ID) { + return EFI_NOT_FOUND; + } + + if (*Target == 0xFFFFFFFF) { + *Target = 0; + } else { + *Target = AtapiScsiPrivate->LatestTargetId + 1; + } + + *Lun = 0; + + // + // Update the LatestTargetId. + // + AtapiScsiPrivate->LatestTargetId = *Target; + AtapiScsiPrivate->LatestLun = *Lun; + + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +AtapiScsiPassThruBuildDevicePath ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +/*++ + + Routine Description: + Used to allocate and build a device path node for a SCSI device + on a SCSI channel. Would not build device path for a SCSI Host Controller. + + Arguments: + This - Protocol instance pointer. + Target - The Target ID of the SCSI device for which + a device path node is to be allocated and built. + Lun - The LUN of the SCSI device for which a device + path node is to be allocated and built. + DevicePath - A pointer to a single device path node that + describes the SCSI device specified by + Target and Lun. This function is responsible + for allocating the buffer DevicePath with the boot + service AllocatePool(). It is the caller's + responsibility to free DevicePath when the caller + is finished with DevicePath. + Returns: + EFI_SUCCESS - The device path node that describes the SCSI device + specified by Target and Lun was allocated and + returned in DevicePath. + EFI_NOT_FOUND - The SCSI devices specified by Target and Lun does + not exist on the SCSI channel. + EFI_INVALID_PARAMETER - DevicePath is NULL. + EFI_OUT_OF_RESOURCES - There are not enough resources to allocate + DevicePath. +--*/ +{ + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + EFI_DEV_PATH *Node; + + // + // Retrieve Device Private Data Structure. + // + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); + + // + // Validate parameters passed in. + // + + if (DevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // can not build device path for the SCSI Host Controller. + // + if ((Target > (MAX_TARGET_ID - 1)) || (Lun != 0)) { + return EFI_NOT_FOUND; + } + + Node = AllocateZeroPool (sizeof (EFI_DEV_PATH)); + if (Node == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Node->DevPath.Type = MESSAGING_DEVICE_PATH; + Node->DevPath.SubType = MSG_ATAPI_DP; + SetDevicePathNodeLength (&Node->DevPath, sizeof (ATAPI_DEVICE_PATH)); + + Node->Atapi.PrimarySecondary = (UINT8) (Target / 2); + Node->Atapi.SlaveMaster = (UINT8) (Target % 2); + Node->Atapi.Lun = (UINT16) Lun; + + *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Node; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +AtapiScsiPassThruGetTargetLun ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT32 *Target, + OUT UINT64 *Lun + ) +/*++ + + Routine Description: + Used to translate a device path node to a Target ID and LUN. + + Arguments: + This - Protocol instance pointer. + DevicePath - A pointer to the device path node that + describes a SCSI device on the SCSI channel. + Target - A pointer to the Target ID of a SCSI device + on the SCSI channel. + Lun - A pointer to the LUN of a SCSI device on + the SCSI channel. + Returns: + EFI_SUCCESS - DevicePath was successfully translated to a + Target ID and LUN, and they were returned + in Target and Lun. + EFI_INVALID_PARAMETER - DevicePath is NULL. + EFI_INVALID_PARAMETER - Target is NULL. + EFI_INVALID_PARAMETER - Lun is NULL. + EFI_UNSUPPORTED - This driver does not support the device path + node type in DevicePath. + EFI_NOT_FOUND - A valid translation from DevicePath to a + Target ID and LUN does not exist. +--*/ +{ + EFI_DEV_PATH *Node; + + // + // Validate parameters passed in. + // + if (DevicePath == NULL || Target == NULL || Lun == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check whether the DevicePath belongs to SCSI_DEVICE_PATH + // + if ((DevicePath->Type != MESSAGING_DEVICE_PATH) || + (DevicePath->SubType != MSG_ATAPI_DP) || + (DevicePathNodeLength(DevicePath) != sizeof(ATAPI_DEVICE_PATH))) { + return EFI_UNSUPPORTED; + } + + Node = (EFI_DEV_PATH *) DevicePath; + + *Target = Node->Atapi.PrimarySecondary * 2 + Node->Atapi.SlaveMaster; + *Lun = Node->Atapi.Lun; + + if (*Target > (MAX_TARGET_ID - 1) || *Lun != 0) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +AtapiScsiPassThruResetChannel ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This + ) +/*++ + + Routine Description: + Resets a SCSI channel.This operation resets all the + SCSI devices connected to the SCSI channel. + + Arguments: + This - Protocol instance pointer. + + Returns: + EFI_SUCCESS - The SCSI channel was reset. + EFI_UNSUPPORTED - The SCSI channel does not support + a channel reset operation. + EFI_DEVICE_ERROR - A device error occurred while + attempting to reset the SCSI channel. + EFI_TIMEOUT - A timeout occurred while attempting + to reset the SCSI channel. +--*/ +{ + UINT8 DeviceControlValue; + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + UINT8 Index; + + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); + + // + // Reset both Primary channel and Secondary channel. + // so, the IoPort pointer must point to the right I/O Register group + // + for (Index = 0; Index < 2; Index++) { + // + // Reset + // + AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[Index]; + + DeviceControlValue = 0; + // + // set SRST bit to initiate soft reset + // + DeviceControlValue |= SRST; + // + // disable Interrupt + // + DeviceControlValue |= bit (1); + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.DeviceControl, + DeviceControlValue + ); + + // + // Wait 10us + // + gBS->Stall (10); + + // + // Clear SRST bit + // 0xfb:1111,1011 + // + DeviceControlValue &= 0xfb; + + WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Alt.DeviceControl, DeviceControlValue); + + // + // slave device needs at most 31s to clear BSY + // + if (StatusWaitForBSYClear (AtapiScsiPrivate, 31000) == EFI_TIMEOUT) { + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +AtapiScsiPassThruResetTarget ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun + ) +/*++ + + Routine Description: + Resets a SCSI device that is connected to a SCSI channel. + + Arguments: + This - Protocol instance pointer. + Target - The Target ID of the SCSI device to reset. + Lun - The LUN of the SCSI device to reset. + + Returns: + EFI_SUCCESS - The SCSI device specified by Target and + Lun was reset. + EFI_UNSUPPORTED - The SCSI channel does not support a target + reset operation. + EFI_INVALID_PARAMETER - Target or Lun are invalid. + EFI_DEVICE_ERROR - A device error occurred while attempting + to reset the SCSI device specified by Target + and Lun. + EFI_TIMEOUT - A timeout occurred while attempting to reset + the SCSI device specified by Target and Lun. +--*/ +{ + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate; + UINT8 Command; + UINT8 DeviceSelect; + + AtapiScsiPrivate = ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS (This); + + if (Target > MAX_TARGET_ID) { + return EFI_INVALID_PARAMETER; + } + // + // Directly return EFI_SUCCESS if want to reset the host controller + // + if (Target == This->Mode->AdapterId) { + return EFI_SUCCESS; + } + + // + // According to Target ID, reset the Atapi I/O Register mapping + // (Target Id in [0,1] area, using gAtapiIoPortRegisters[0], + // Target Id in [2,3] area, using gAtapiIoPortRegisters[1] + // + if ((Target / 2) == 0) { + AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[0]; + } else { + AtapiScsiPrivate->IoPort = &gAtapiIoPortRegisters[1]; + } + + // + // for ATAPI device, no need to wait DRDY ready after device selecting. + // + // bit7 and bit5 are both set to 1 for backward compatibility + // + DeviceSelect = (UINT8) (((bit (7) | bit (5)) | (Target << 4))); + WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Head, DeviceSelect); + + Command = ATAPI_SOFT_RESET_CMD; + WritePortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Reg.Command, Command); + + // + // BSY clear is the only status return to the host by the device + // when reset is complete. + // slave device needs at most 31s to clear BSY + // + if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, 31000))) { + return EFI_DEVICE_ERROR; + } + + // + // stall 5 seconds to make the device status stable + // + gBS->Stall (5000000); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CheckSCSIRequestPacket ( + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +/*++ + + Checks the parameters in the SCSI Request Packet to make sure + they are valid for a SCSI Pass Thru request. + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: Packet - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + if (Packet == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!ValidCdbLength (Packet->CdbLength)) { + return EFI_INVALID_PARAMETER; + } + + if (Packet->Cdb == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Checks whether the request command is supported. + // + if (!IsCommandValid (Packet)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +BOOLEAN +IsCommandValid ( + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +/*++ + + Checks the requested SCSI command: + Is it supported by this driver? + Is the Data transfer direction reasonable? + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: Packet - add argument and description to function comment +{ + UINT8 Index; + UINT8 *OpCode; + + OpCode = (UINT8 *) (Packet->Cdb); + + for (Index = 0; CompareMem (&gSupportedATAPICommands[Index], &gEndTable, sizeof (SCSI_COMMAND_SET)); Index++) { + + if (*OpCode == gSupportedATAPICommands[Index].OpCode) { + // + // Check whether the requested Command is supported by this driver + // + if (Packet->DataDirection == DataIn) { + // + // Check whether the requested data direction conforms to + // what it should be. + // + if (gSupportedATAPICommands[Index].Direction == DataOut) { + return FALSE; + } + } + + if (Packet->DataDirection == DataOut) { + // + // Check whether the requested data direction conforms to + // what it should be. + // + if (gSupportedATAPICommands[Index].Direction == DataIn) { + return FALSE; + } + } + + return TRUE; + } + } + + return FALSE; +} + +EFI_STATUS +SubmitBlockingIoCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +/*++ + +Routine Description: + Performs blocking I/O request. + + Arguments: + AtapiScsiPrivate: Private data structure for the specified channel. + Target: The Target ID of the ATAPI device to send the SCSI + Request Packet. To ATAPI devices attached on an IDE + Channel, Target ID 0 indicates Master device;Target + ID 1 indicates Slave device. + Packet: The SCSI Request Packet to send to the ATAPI device + specified by Target. + + Returns: + +--*/ +// TODO: AtapiScsiPrivate - add argument and description to function comment +{ + UINT8 PacketCommand[12]; + UINT64 TimeoutInMicroSeconds; + EFI_STATUS PacketCommandStatus; + + // + // Fill ATAPI Command Packet according to CDB + // + ZeroMem (&PacketCommand, 12); + CopyMem (&PacketCommand, Packet->Cdb, Packet->CdbLength); + + // + // Timeout is 100ns unit, convert it to 1000ns (1us) unit. + // + TimeoutInMicroSeconds = DivU64x32 (Packet->Timeout, (UINT32) 10); + + // + // Submit ATAPI Command Packet + // + PacketCommandStatus = AtapiPacketCommand ( + AtapiScsiPrivate, + Target, + PacketCommand, + Packet->DataBuffer, + &(Packet->TransferLength), + Packet->DataDirection, + TimeoutInMicroSeconds + ); + if (!EFI_ERROR (PacketCommandStatus) || (Packet->SenseData == NULL)) { + Packet->SenseDataLength = 0; + return PacketCommandStatus; + } + // + // Return SenseData if PacketCommandStatus matches + // the following return codes. + // + if ((PacketCommandStatus == EFI_WARN_BUFFER_TOO_SMALL) || + (PacketCommandStatus == EFI_DEVICE_ERROR) || + (PacketCommandStatus == EFI_TIMEOUT)) { + + // + // avoid submit request sense command continuously. + // + if (PacketCommand[0] == OP_REQUEST_SENSE) { + Packet->SenseDataLength = 0; + return PacketCommandStatus; + } + + RequestSenseCommand ( + AtapiScsiPrivate, + Target, + Packet->Timeout, + Packet->SenseData, + &Packet->SenseDataLength + ); + } + + return PacketCommandStatus; +} + +EFI_STATUS +RequestSenseCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + UINT64 Timeout, + VOID *SenseData, + UINT8 *SenseDataLength + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + Target - TODO: add argument description + Timeout - TODO: add argument description + SenseData - TODO: add argument description + SenseDataLength - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET Packet; + UINT8 Cdb[12]; + EFI_STATUS Status; + + ZeroMem (&Packet, sizeof (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, 12); + + Cdb[0] = OP_REQUEST_SENSE; + Cdb[4] = (UINT8) (*SenseDataLength); + + Packet.Timeout = Timeout; + Packet.DataBuffer = SenseData; + Packet.SenseData = NULL; + Packet.Cdb = Cdb; + Packet.TransferLength = *SenseDataLength; + Packet.CdbLength = 12; + Packet.DataDirection = DataIn; + + Status = SubmitBlockingIoCommand (AtapiScsiPrivate, Target, &Packet); + *SenseDataLength = (UINT8) (Packet.TransferLength); + return Status; +} + +EFI_STATUS +AtapiPacketCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + UINT8 *PacketCommand, + VOID *Buffer, + UINT32 *ByteCount, + DATA_DIRECTION Direction, + UINT64 TimeoutInMicroSeconds + ) +/*++ + + Routine Description: + Submits ATAPI command packet to the specified ATAPI device. + + Arguments: + AtapiScsiPrivate: Private data structure for the specified channel. + Target: The Target ID of the ATAPI device to send the SCSI + Request Packet. To ATAPI devices attached on an IDE + Channel, Target ID 0 indicates Master device;Target + ID 1 indicates Slave device. + PacketCommand: Points to the ATAPI command packet. + Buffer: Points to the transferred data. + ByteCount: When input,indicates the buffer size; when output, + indicates the actually transferred data size. + Direction: Indicates the data transfer direction. + TimeoutInMicroSeconds: + The timeout, in micro second units, to use for the + execution of this ATAPI command. + A TimeoutInMicroSeconds value of 0 means that + this function will wait indefinitely for the ATAPI + command to execute. + If TimeoutInMicroSeconds is greater than zero, then + this function will return EFI_TIMEOUT if the time + required to execute the ATAPI command is greater + than TimeoutInMicroSeconds. + + Returns: + + +--*/ +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: PacketCommand - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: ByteCount - add argument and description to function comment +// TODO: Direction - add argument and description to function comment +{ + + UINT16 *CommandIndex; + UINT8 Count; + EFI_STATUS Status; + + // + // Set all the command parameters by fill related registers. + // Before write to all the following registers, BSY and DRQ must be 0. + // + Status = StatusDRQClear (AtapiScsiPrivate, TimeoutInMicroSeconds); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + Status = EFI_DEVICE_ERROR; + } + + *ByteCount = 0; + return Status; + } + // + // Select device via Device/Head Register. + // "Target = 0" indicates device 0; "Target = 1" indicates device 1 + // + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Head, + (UINT8) ((Target << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000) + ); + + // + // No OVL; No DMA (by setting feature register) + // + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Feature, + 0x00 + ); + + // + // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device + // determine how much data should be transfered. + // + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->CylinderLsb, + (UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff) + ); + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->CylinderMsb, + (UINT8) (MAX_ATAPI_BYTE_COUNT >> 8) + ); + + // + // DEFAULT_CTL:0x0a (0000,1010) + // Disable interrupt + // + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.DeviceControl, + DEFAULT_CTL + ); + + // + // Send Packet command to inform device + // that the following data bytes are command packet. + // + WritePortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Command, + PACKET_CMD + ); + + // + // Before data transfer, BSY should be 0 and DRQ should be 1. + // if they are not in specified time frame, + // retrieve Sense Key from Error Register before return. + // + Status = StatusDRQReady (AtapiScsiPrivate, TimeoutInMicroSeconds); + if (EFI_ERROR (Status)) { + if (Status == EFI_ABORTED) { + Status = EFI_DEVICE_ERROR; + } + + *ByteCount = 0; + return Status; + } + + // + // Send out command packet + // + CommandIndex = (UINT16 *) PacketCommand; + for (Count = 0; Count < 6; Count++, CommandIndex++) { + WritePortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data, *CommandIndex); + } + + // + // call AtapiPassThruPioReadWriteData() function to get + // requested transfer data form device. + // + return AtapiPassThruPioReadWriteData ( + AtapiScsiPrivate, + Buffer, + ByteCount, + Direction, + TimeoutInMicroSeconds + ); +} + +EFI_STATUS +AtapiPassThruPioReadWriteData ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT16 *Buffer, + UINT32 *ByteCount, + DATA_DIRECTION Direction, + UINT64 TimeoutInMicroSeconds + ) +/*++ + + Routine Description: + Performs data transfer between ATAPI device and host after the + ATAPI command packet is sent. + + Arguments: + AtapiScsiPrivate: Private data structure for the specified channel. + Buffer: Points to the transferred data. + ByteCount: When input,indicates the buffer size; when output, + indicates the actually transferred data size. + Direction: Indicates the data transfer direction. + TimeoutInMicroSeconds: + The timeout, in micro second units, to use for the + execution of this ATAPI command. + A TimeoutInMicroSeconds value of 0 means that + this function will wait indefinitely for the ATAPI + command to execute. + If TimeoutInMicroSeconds is greater than zero, then + this function will return EFI_TIMEOUT if the time + required to execute the ATAPI command is greater + than TimeoutInMicroSeconds. + + Returns: + + +--*/ +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: ByteCount - add argument and description to function comment +// TODO: Direction - add argument and description to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_WARN_BUFFER_TOO_SMALL - add return value to function comment +{ + UINT32 Index; + UINT32 RequiredWordCount; + UINT32 ActualWordCount; + + UINT32 WordCount; + EFI_STATUS Status; + UINT16 *ptrBuffer; + + Status = EFI_SUCCESS; + + // + // Non Data transfer request is also supported. + // + if (*ByteCount == 0 || Buffer == NULL) { + *ByteCount = 0; + if (EFI_ERROR (StatusWaitForBSYClear (AtapiScsiPrivate, TimeoutInMicroSeconds))) { + return EFI_DEVICE_ERROR; + } + } + + ptrBuffer = Buffer; + RequiredWordCount = *ByteCount / 2; + + // + // ActuralWordCount means the word count of data really transfered. + // + ActualWordCount = 0; + + while (ActualWordCount < RequiredWordCount) { + // + // before each data transfer stream, the host should poll DRQ bit ready, + // which indicates device's ready for data transfer . + // + Status = StatusDRQReady (AtapiScsiPrivate, TimeoutInMicroSeconds); + if (EFI_ERROR (Status)) { + *ByteCount = ActualWordCount * 2; + + AtapiPassThruCheckErrorStatus (AtapiScsiPrivate); + + if (ActualWordCount == 0) { + return EFI_DEVICE_ERROR; + } + // + // ActualWordCount > 0 + // + if (ActualWordCount < RequiredWordCount) { + return EFI_WARN_BUFFER_TOO_SMALL; + } + } + // + // get current data transfer size from Cylinder Registers. + // + WordCount = + ( + (ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->CylinderMsb) << 8) | + ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->CylinderLsb) + ) & 0xffff; + WordCount /= 2; + + // + // perform a series data In/Out. + // + for (Index = 0; (Index < WordCount) && (ActualWordCount < RequiredWordCount); Index++, ActualWordCount++) { + + if (Direction == DataIn) { + + *ptrBuffer = ReadPortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data); + } else { + + WritePortW (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Data, *ptrBuffer); + } + + ptrBuffer++; + + } + } + // + // After data transfer is completed, normally, DRQ bit should clear. + // + StatusDRQClear (AtapiScsiPrivate, TimeoutInMicroSeconds); + + // + // read status register to check whether error happens. + // + Status = AtapiPassThruCheckErrorStatus (AtapiScsiPrivate); + + *ByteCount = ActualWordCount * 2; + + return Status; +} + + +UINT8 +ReadPortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +/*++ + Read one byte from a specified I/O port. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: PciIo - add argument and description to function comment +// TODO: Port - add argument and description to function comment +{ + UINT8 Data; + + Data = 0; + PciIo->Io.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); + return Data; +} + + +UINT16 +ReadPortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +/*++ + Read one word from a specified I/O port. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: PciIo - add argument and description to function comment +// TODO: Port - add argument and description to function comment +{ + UINT16 Data; + + Data = 0; + PciIo->Io.Read ( + PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); + return Data; +} + + +VOID +WritePortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT8 Data + ) +/*++ + Write one byte to a specified I/O port. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: PciIo - add argument and description to function comment +// TODO: Port - add argument and description to function comment +// TODO: Data - add argument and description to function comment +{ + + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); + +} + + +VOID +WritePortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT16 Data + ) +/*++ + Write one word to a specified I/O port. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: PciIo - add argument and description to function comment +// TODO: Port - add argument and description to function comment +// TODO: Data - add argument and description to function comment +{ + + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); +} + +EFI_STATUS +StatusDRQClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + Check whether DRQ is clear in the Status Register. (BSY must also be cleared) + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: TimeoutInMicroSeconds - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +// TODO: EFI_TIMEOUT - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Delay; + UINT8 StatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + + StatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Status + ); + + // + // wait for BSY == 0 and DRQ == 0 + // + if ((StatusRegister & (DRQ | BSY)) == 0) { + break; + } + // + // check whether the command is aborted by the device + // + if ((StatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + + return EFI_ABORTED; + } + } + // + // Stall for 30 us + // + gBS->Stall (30); + + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AltStatusDRQClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + Check whether DRQ is clear in the Alternate Status Register. + (BSY must also be cleared). + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRQ clear. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: TimeoutInMicroSeconds - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +// TODO: EFI_TIMEOUT - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Delay; + UINT8 AltStatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + + AltStatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.AltStatus + ); + + // + // wait for BSY == 0 and DRQ == 0 + // + if ((AltStatusRegister & (DRQ | BSY)) == 0) { + break; + } + + if ((AltStatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + + return EFI_ABORTED; + } + } + // + // Stall for 30 us + // + gBS->Stall (30); + + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +StatusDRQReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + Check whether DRQ is ready in the Status Register. (BSY must also be cleared) + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: TimeoutInMicroSeconds - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +// TODO: EFI_TIMEOUT - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Delay; + UINT8 StatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + // + // read Status Register will clear interrupt + // + StatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Status + ); + + // + // BSY==0,DRQ==1 + // + if ((StatusRegister & (BSY | DRQ)) == DRQ) { + break; + } + + if ((StatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AltStatusDRQReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + Check whether DRQ is ready in the Alternate Status Register. + (BSY must also be cleared) + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRQ ready. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: TimeoutInMicroSeconds - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +// TODO: EFI_TIMEOUT - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Delay; + UINT8 AltStatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + // + // read Status Register will clear interrupt + // + AltStatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.AltStatus + ); + // + // BSY==0,DRQ==1 + // + if ((AltStatusRegister & (BSY | DRQ)) == DRQ) { + break; + } + + if ((AltStatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +StatusWaitForBSYClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + Check whether BSY is clear in the Status Register. + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: TimeoutInMicroSeconds - add argument and description to function comment +// TODO: EFI_TIMEOUT - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Delay; + UINT8 StatusRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + + StatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Status + ); + if ((StatusRegister & BSY) == 0x00) { + break; + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AltStatusWaitForBSYClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + Check whether BSY is clear in the Alternate Status Register. + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + BSY clear. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: TimeoutInMicroSeconds - add argument and description to function comment +// TODO: EFI_TIMEOUT - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Delay; + UINT8 AltStatusRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + + AltStatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.AltStatus + ); + if ((AltStatusRegister & BSY) == 0x00) { + break; + } + + // + // Stall for 30 us + // + gBS->Stall (30); + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +StatusDRDYReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + Check whether DRDY is ready in the Status Register. + (BSY must also be cleared) + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: TimeoutInMicroSeconds - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +// TODO: EFI_TIMEOUT - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Delay; + UINT8 StatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + StatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Status + ); + // + // BSY == 0 , DRDY == 1 + // + if ((StatusRegister & (DRDY | BSY)) == DRDY) { + break; + } + + if ((StatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AltStatusDRDYReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + Check whether DRDY is ready in the Alternate Status Register. + (BSY must also be cleared) + If TimeoutInMicroSeconds is zero, this routine should wait infinitely for + DRDY ready. Otherwise, it will return EFI_TIMEOUT when specified time is + elapsed. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: TimeoutInMicroSeconds - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +// TODO: EFI_TIMEOUT - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Delay; + UINT8 AltStatusRegister; + UINT8 ErrRegister; + + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } else { + Delay = DivU64x32 (TimeoutInMicroSeconds, (UINT32) 30) + 1; + } + + do { + AltStatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Alt.AltStatus + ); + // + // BSY == 0 , DRDY == 1 + // + if ((AltStatusRegister & (DRDY | BSY)) == DRDY) { + break; + } + + if ((AltStatusRegister & (BSY | ERR)) == ERR) { + + ErrRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg1.Error + ); + if ((ErrRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + // + // Loop infinitely if not meeting expected condition + // + if (TimeoutInMicroSeconds == 0) { + Delay = 2; + } + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AtapiPassThruCheckErrorStatus ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate + ) +/*++ + Check Error Register for Error Information. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: AtapiScsiPrivate - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + UINT8 StatusRegister; + +//#ifdef EFI_DEBUG + + UINT8 ErrorRegister; + +//#endif + + StatusRegister = ReadPortB ( + AtapiScsiPrivate->PciIo, + AtapiScsiPrivate->IoPort->Reg.Status + ); + DEBUG_CODE ( + + if (StatusRegister & DWF) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Write Fault\n", + StatusRegister) + ); + } + + if (StatusRegister & CORR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Corrected Data\n", + StatusRegister) + ); + } + + if (StatusRegister & ERR) { + ErrorRegister = ReadPortB (AtapiScsiPrivate->PciIo, AtapiScsiPrivate->IoPort->Reg1.Error); + + if (ErrorRegister & BBK_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Bad Block Detected\n", + ErrorRegister) + ); + } + + if (ErrorRegister & UNC_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Uncorrectable Data\n", + ErrorRegister) + ); + } + + if (ErrorRegister & MC_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Media Change\n", + ErrorRegister) + ); + } + + if (ErrorRegister & ABRT_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Abort\n", + ErrorRegister) + ); + } + + if (ErrorRegister & TK0NF_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Track 0 Not Found\n", + ErrorRegister) + ); + } + + if (ErrorRegister & AMNF_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "AtapiPassThruCheckErrorStatus()-- %02x : Error : Address Mark Not Found\n", + ErrorRegister) + ); + } + + } + ); + + if ((StatusRegister & (ERR | DWF | CORR)) == 0) { + + return EFI_SUCCESS; + } + + return EFI_DEVICE_ERROR; + +} diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.h b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.h new file mode 100644 index 0000000000..486fd2dd0e --- /dev/null +++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.h @@ -0,0 +1,916 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + AtapiPassThru.h + +Abstract: + + +Revision History +--*/ + +#ifndef _APT_H +#define _APT_H + + +#include + +// +// bit definition +// +#define bit(a) 1 << (a) + +#define MAX_TARGET_ID 4 +// +// IDE Registers +// +typedef union { + UINT16 Command; /* when write */ + UINT16 Status; /* when read */ +} IDE_CMD_OR_STATUS; + +typedef union { + UINT16 Error; /* when read */ + UINT16 Feature; /* when write */ +} IDE_ERROR_OR_FEATURE; + +typedef union { + UINT16 AltStatus; /* when read */ + UINT16 DeviceControl; /* when write */ +} IDE_AltStatus_OR_DeviceControl; + +// +// IDE registers set +// +typedef struct { + UINT16 Data; + IDE_ERROR_OR_FEATURE Reg1; + UINT16 SectorCount; + UINT16 SectorNumber; + UINT16 CylinderLsb; + UINT16 CylinderMsb; + UINT16 Head; + IDE_CMD_OR_STATUS Reg; + + IDE_AltStatus_OR_DeviceControl Alt; + UINT16 DriveAddress; + + UINT16 MasterSlave; +} IDE_BASE_REGISTERS; + +#define ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE EFI_SIGNATURE_32 ('a', 's', 'p', 't') + +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_SCSI_PASS_THRU_PROTOCOL ScsiPassThru; + EFI_SCSI_PASS_THRU_MODE ScsiPassThruMode; + EFI_PCI_IO_PROTOCOL *PciIo; + + // + // Local Data goes here + // + IDE_BASE_REGISTERS *IoPort; + + CHAR16 ControllerName[100]; + CHAR16 ChannelName[100]; + + UINT32 LatestTargetId; + UINT64 LatestLun; + +} ATAPI_SCSI_PASS_THRU_DEV; + +#define ATAPI_SCSI_PASS_THRU_DEV_FROM_THIS(a) \ + CR (a, \ + ATAPI_SCSI_PASS_THRU_DEV, \ + ScsiPassThru, \ + ATAPI_SCSI_PASS_THRU_DEV_SIGNATURE \ + ) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gAtapiScsiPassThruDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gAtapiScsiPassThruComponentName; + +// +// ATAPI Command op code +// +#define OP_INQUIRY 0x12 +#define OP_LOAD_UNLOAD_CD 0xa6 +#define OP_MECHANISM_STATUS 0xbd +#define OP_MODE_SELECT_10 0x55 +#define OP_MODE_SENSE_10 0x5a +#define OP_PAUSE_RESUME 0x4b +#define OP_PLAY_AUDIO_10 0x45 +#define OP_PLAY_AUDIO_MSF 0x47 +#define OP_PLAY_CD 0xbc +#define OP_PLAY_CD_MSF 0xb4 +#define OP_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e +#define OP_READ_10 0x28 +#define OP_READ_12 0xa8 +#define OP_READ_CAPACITY 0x25 +#define OP_READ_CD 0xbe +#define OP_READ_CD_MSF 0xb9 +#define OP_READ_HEADER 0x44 +#define OP_READ_SUB_CHANNEL 0x42 +#define OP_READ_TOC 0x43 +#define OP_REQUEST_SENSE 0x03 +#define OP_SCAN 0xba +#define OP_SEEK_10 0x2b +#define OP_SET_CD_SPEED 0xbb +#define OP_STOPPLAY_SCAN 0x4e +#define OP_START_STOP_UNIT 0x1b +#define OP_TEST_UNIT_READY 0x00 + +#define OP_FORMAT_UNIT 0x04 +#define OP_READ_FORMAT_CAPACITIES 0x23 +#define OP_VERIFY 0x2f +#define OP_WRITE_10 0x2a +#define OP_WRITE_12 0xaa +#define OP_WRITE_AND_VERIFY 0x2e + +// +// ATA Command +// +#define ATAPI_SOFT_RESET_CMD 0x08 + +typedef enum { + DataIn = 0, + DataOut = 1, + NoData = 2, + End = 0xff +} DATA_DIRECTION; + +typedef struct { + UINT8 OpCode; + DATA_DIRECTION Direction; +} SCSI_COMMAND_SET; + +#define MAX_CHANNEL 2 + +#define ValidCdbLength(Len) ((Len) == 6 || (Len) == 10 || (Len) == 12) ? 1 : 0 + +// +// IDE registers bit definitions +// +// ATA Err Reg bitmap +// +#define BBK_ERR bit (7) /* Bad block detected */ +#define UNC_ERR bit (6) /* Uncorrectable Data */ +#define MC_ERR bit (5) /* Media Change */ +#define IDNF_ERR bit (4) /* ID Not Found */ +#define MCR_ERR bit (3) /* Media Change Requested */ +#define ABRT_ERR bit (2) /* Aborted Command */ +#define TK0NF_ERR bit (1) /* Track 0 Not Found */ +#define AMNF_ERR bit (0) /* Address Mark Not Found */ + +// +// ATAPI Err Reg bitmap +// +#define SENSE_KEY_ERR (bit (7) | bit (6) | bit (5) | bit (4)) +#define EOM_ERR bit (1) /* End of Media Detected */ +#define ILI_ERR bit (0) /* Illegal Length Indication */ + +// +// Device/Head Reg +// +#define LBA_MODE bit (6) +#define DEV bit (4) +#define HS3 bit (3) +#define HS2 bit (2) +#define HS1 bit (1) +#define HS0 bit (0) +#define CHS_MODE (0) +#define DRV0 (0) +#define DRV1 (1) +#define MST_DRV DRV0 +#define SLV_DRV DRV1 + +// +// Status Reg +// +#define BSY bit (7) /* Controller Busy */ +#define DRDY bit (6) /* Drive Ready */ +#define DWF bit (5) /* Drive Write Fault */ +#define DSC bit (4) /* Disk Seek Complete */ +#define DRQ bit (3) /* Data Request */ +#define CORR bit (2) /* Corrected Data */ +#define IDX bit (1) /* Index */ +#define ERR bit (0) /* Error */ +#define CHECK bit (0) /* Check bit for ATAPI Status Reg */ + +// +// Device Control Reg +// +#define SRST bit (2) /* Software Reset */ +#define IEN_L bit (1) /* Interrupt Enable #*/ + +// +// ATAPI Feature Register +// +#define OVERLAP bit (1) +#define DMA bit (0) + +// +// ATAPI Interrupt Reason Reson Reg (ATA Sector Count Register) +// +#define RELEASE bit (2) +#define IO bit (1) +#define CoD bit (0) + +#define PACKET_CMD 0xA0 + +#define DEFAULT_CMD (0xa0) +// +// default content of device control register, disable INT +// +#define DEFAULT_CTL (0x0a) +#define MAX_ATAPI_BYTE_COUNT (0xfffe) + +// +// function prototype +// +EFI_STATUS +EFIAPI +AtapiScsiPassThruDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) + /*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + SystemTable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +RegisterAtapiScsiPassThru ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Controller - TODO: add argument description + PciIo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +AtapiScsiPassThruFunction ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Target - TODO: add argument description + Lun - TODO: add argument description + Packet - TODO: add argument description + Event - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +AtapiScsiPassThruGetNextDevice ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT32 *Target, + IN OUT UINT64 *Lun + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Target - TODO: add argument description + Lun - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +AtapiScsiPassThruBuildDevicePath ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Target - TODO: add argument description + Lun - TODO: add argument description + DevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +AtapiScsiPassThruGetTargetLun ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT32 *Target, + OUT UINT64 *Lun + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + DevicePath - TODO: add argument description + Target - TODO: add argument description + Lun - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +AtapiScsiPassThruResetChannel ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +AtapiScsiPassThruResetTarget ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Target - TODO: add argument description + Lun - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CheckSCSIRequestPacket ( + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Packet - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SubmitBlockingIoCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + Target - TODO: add argument description + Packet - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsCommandValid ( + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet + ) + /*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Packet - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +RequestSenseCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + UINT64 Timeout, + VOID *SenseData, + UINT8 *SenseDataLength + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + Target - TODO: add argument description + Timeout - TODO: add argument description + SenseData - TODO: add argument description + SenseDataLength - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiPacketCommand ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT32 Target, + UINT8 *PacketCommand, + VOID *Buffer, + UINT32 *ByteCount, + DATA_DIRECTION Direction, + UINT64 TimeOutInMicroSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + Target - TODO: add argument description + PacketCommand - TODO: add argument description + Buffer - TODO: add argument description + ByteCount - TODO: add argument description + Direction - TODO: add argument description + TimeOutInMicroSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + + +UINT8 +ReadPortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + + +UINT16 +ReadPortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + + +VOID +WritePortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT8 Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + + +VOID +WritePortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT16 Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +StatusDRQClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeOutInMicroSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + TimeOutInMicroSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AltStatusDRQClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeOutInMicroSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + TimeOutInMicroSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +StatusDRQReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeOutInMicroSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + TimeOutInMicroSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AltStatusDRQReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeOutInMicroSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + TimeOutInMicroSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +StatusWaitForBSYClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + TimeoutInMicroSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AltStatusWaitForBSYClear ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + TimeoutInMicroSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +StatusDRDYReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + TimeoutInMicroSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AltStatusDRDYReady ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT64 TimeoutInMicroSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + TimeoutInMicroSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiPassThruPioReadWriteData ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate, + UINT16 *Buffer, + UINT32 *ByteCount, + DATA_DIRECTION Direction, + UINT64 TimeOutInMicroSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + Buffer - TODO: add argument description + ByteCount - TODO: add argument description + Direction - TODO: add argument description + TimeOutInMicroSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiPassThruCheckErrorStatus ( + ATAPI_SCSI_PASS_THRU_DEV *AtapiScsiPrivate + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AtapiScsiPrivate - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; +#endif diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.mbd b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.mbd new file mode 100644 index 0000000000..903a092439 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.mbd @@ -0,0 +1,42 @@ + + + + + AtapiPassThru + E49061CE-99A7-41d3-AB3A-36E5CFBAD63E + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa new file mode 100644 index 0000000000..1c13016bcf --- /dev/null +++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa @@ -0,0 +1,65 @@ + + + + + AtapiPassThru + UEFI_DRIVER + BS_DRIVER + E49061CE-99A7-41d3-AB3A-36E5CFBAD63E + 0 + Description file for the Atapi Passthru component. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + AtapiPassThru.h + AtapiPassThru.c + ComponentName.c + + + MdePkg + + + PciIo + ScsiPassThru + + + + + + + gAtapiScsiPassThruDriverBinding + gAtapiScsiPassThruComponentName + + + diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/ComponentName.c new file mode 100644 index 0000000000..14658b0ace --- /dev/null +++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/ComponentName.c @@ -0,0 +1,154 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ +#include "AtapiPassThru.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +AtapiScsiPassThruComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +AtapiScsiPassThruComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gAtapiScsiPassThruComponentName = { + AtapiScsiPassThruComponentNameGetDriverName, + AtapiScsiPassThruComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mAtapiScsiPassThruDriverNameTable[] = { + { "eng", (CHAR16 *) L"ATAPI SCSI Pass Thru Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +AtapiScsiPassThruComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gAtapiScsiPassThruComponentName.SupportedLanguages, + mAtapiScsiPassThruDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +AtapiScsiPassThruComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/build.xml b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/build.xml new file mode 100644 index 0000000000..d9b2b666b2 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/AtapiPassThru/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.c b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.c new file mode 100644 index 0000000000..91d6accd99 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.c @@ -0,0 +1,346 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CirrusLogic5430.c + +Abstract: + + Cirrus Logic 5430 Controller Driver. + This driver is a sample implementation of the UGA Draw Protocol for the + Cirrus Logic 5430 family of PCI video controllers. This driver is only + usable in the EFI pre-boot environment. This sample is intended to show + how the UGA Draw Protocol is able to function. The UGA I/O Protocol is not + implemented in this sample. A fully compliant EFI UGA driver requires both + the UGA Draw and the UGA I/O Protocol. Please refer to Microsoft's + documentation on UGA for details on how to write a UGA driver that is able + to function both in the EFI pre-boot environment and from the OS runtime. + +Revision History: + +--*/ + +// +// Cirrus Logic 5430 Controller Driver +// + +#include "CirrusLogic5430.h" + +EFI_DRIVER_BINDING_PROTOCOL gCirrusLogic5430DriverBinding = { + CirrusLogic5430ControllerDriverSupported, + CirrusLogic5430ControllerDriverStart, + CirrusLogic5430ControllerDriverStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +CirrusLogic5430ControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + // + // Open the PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Read the PCI Configuration Header from the PCI Device + // + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint32, + 0, + sizeof (Pci) / sizeof (UINT32), + &Pci + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = EFI_UNSUPPORTED; + // + // See if the I/O enable is on. Most systems only allow one VGA device to be turned on + // at a time, so see if this is one that is turned on. + // + // if (((Pci.Hdr.Command & 0x01) == 0x01)) { + // + // See if this is a Cirrus Logic PCI controller + // + if (Pci.Hdr.VendorId == CIRRUS_LOGIC_VENDOR_ID) { + // + // See if this is a 5430 or a 5446 PCI controller + // + if (Pci.Hdr.DeviceId == CIRRUS_LOGIC_5430_DEVICE_ID) { + Status = EFI_SUCCESS; + } + + if (Pci.Hdr.DeviceId == CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID) { + Status = EFI_SUCCESS; + } + + if (Pci.Hdr.DeviceId == CIRRUS_LOGIC_5446_DEVICE_ID) { + Status = EFI_SUCCESS; + } + } + +Done: + // + // Close the PCI I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +CirrusLogic5430ControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private; + + // + // Allocate Private context data for UGA Draw inteface. + // + Private = NULL; + Private = AllocateZeroPool (sizeof (CIRRUS_LOGIC_5430_PRIVATE_DATA)); + if (Private == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + // + // Set up context record + // + Private->Signature = CIRRUS_LOGIC_5430_PRIVATE_DATA_SIGNATURE; + Private->Handle = Controller; + + // + // Open PCI I/O Protocol + // + Status = gBS->OpenProtocol ( + Private->Handle, + &gEfiPciIoProtocolGuid, + (VOID **) &Private->PciIo, + This->DriverBindingHandle, + Private->Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Status = Private->PciIo->Attributes ( + Private->PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Start the UGA Draw software stack. + // + Status = CirrusLogic5430UgaDrawConstructor (Private); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Publish the UGA Draw interface to the world + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->Handle, + &gEfiUgaDrawProtocolGuid, + &Private->UgaDraw, + NULL + ); + +Error: + if (EFI_ERROR (Status)) { + if (Private) { + if (Private->PciIo) { + Private->PciIo->Attributes ( + Private->PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, + NULL + ); + } + } + + // + // Close the PCI I/O Protocol + // + gBS->CloseProtocol ( + Private->Handle, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Private->Handle + ); + if (Private) { + gBS->FreePool (Private); + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +CirrusLogic5430ControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: NumberOfChildren - add argument and description to function comment +// TODO: ChildHandleBuffer - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_STATUS Status; + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + // + // If the UGA Draw interface does not exist the driver is not started + // + return Status; + } + + // + // Get our private context information + // + Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (UgaDraw); + + // + // Remove the UGA Draw interface from the system + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->Handle, + &gEfiUgaDrawProtocolGuid, + &Private->UgaDraw, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Shutdown the hardware + // + CirrusLogic5430UgaDrawDestructor (Private); + + Private->PciIo->Attributes ( + Private->PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO, + NULL + ); + + // + // Close the PCI I/O Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Free our instance data + // + gBS->FreePool (Private); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.h b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.h new file mode 100644 index 0000000000..5eba0190f2 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.h @@ -0,0 +1,254 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CirrusLogic5430.h + +Abstract: + + Cirrus Logic 5430 Controller Driver + +Revision History + +--*/ + +// +// Cirrus Logic 5430 Controller Driver +// + +#ifndef _CIRRUS_LOGIC_5430_H_ +#define _CIRRUS_LOGIC_5430_H_ + + +#include +// +// Cirrus Logic 5430 PCI Configuration Header values +// +#define CIRRUS_LOGIC_VENDOR_ID 0x1013 +#define CIRRUS_LOGIC_5430_DEVICE_ID 0x00a8 +#define CIRRUS_LOGIC_5430_ALTERNATE_DEVICE_ID 0x00a0 +#define CIRRUS_LOGIC_5446_DEVICE_ID 0x00b8 + +// +// Cirrus Logic Graphical Mode Data +// +#define CIRRUS_LOGIC_5430_UGA_DRAW_MODE_COUNT 3 + +typedef struct { + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; +} CIRRUS_LOGIC_5430_UGA_DRAW_MODE_DATA; + +// +// Cirrus Logic 5440 Private Data Structure +// +#define CIRRUS_LOGIC_5430_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('C', 'L', '5', '4') + +typedef struct { + UINT64 Signature; + EFI_HANDLE Handle; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_UGA_DRAW_PROTOCOL UgaDraw; + + // + // UGA Draw Private Data + // + BOOLEAN HardwareNeedsStarting; + UINTN CurrentMode; + UINTN MaxMode; + CIRRUS_LOGIC_5430_UGA_DRAW_MODE_DATA ModeData[CIRRUS_LOGIC_5430_UGA_DRAW_MODE_COUNT]; + UINT8 *LineBuffer; +} CIRRUS_LOGIC_5430_PRIVATE_DATA; + +#define CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS(a) \ + CR(a, CIRRUS_LOGIC_5430_PRIVATE_DATA, UgaDraw, CIRRUS_LOGIC_5430_PRIVATE_DATA_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gCirrusLogic5430DriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gCirrusLogic5430ComponentName; + +// +// Io Registers defined by VGA +// +#define CRTC_ADDRESS_REGISTER 0x3d4 +#define CRTC_DATA_REGISTER 0x3d5 +#define SEQ_ADDRESS_REGISTER 0x3c4 +#define SEQ_DATA_REGISTER 0x3c5 +#define GRAPH_ADDRESS_REGISTER 0x3ce +#define GRAPH_DATA_REGISTER 0x3cf +#define ATT_ADDRESS_REGISTER 0x3c0 +#define MISC_OUTPUT_REGISTER 0x3c2 +#define INPUT_STATUS_1_REGISTER 0x3da +#define DAC_PIXEL_MASK_REGISTER 0x3c6 +#define PALETTE_INDEX_REGISTER 0x3c8 +#define PALETTE_DATA_REGISTER 0x3c9 + +// +// UGA Draw Hardware abstraction internal worker functions +// +EFI_STATUS +CirrusLogic5430UgaDrawConstructor ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CirrusLogic5430UgaDrawDestructor ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// EFI 1.1 driver model prototypes for Cirrus Logic 5430 UGA Draw +// +EFI_STATUS +EFIAPI +CirrusLogic5430DriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + SystemTable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// EFI_DRIVER_BINDING_PROTOCOL Protocol Interface +// +EFI_STATUS +EFIAPI +CirrusLogic5430ControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Controller - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +CirrusLogic5430ControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Controller - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +CirrusLogic5430ControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Controller - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.mbd b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.mbd new file mode 100644 index 0000000000..16bc2891b6 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.mbd @@ -0,0 +1,42 @@ + + + + + CirrusLogic5430UgaDraw + 555F76EA-785F-40d7-9174-153C43636C68 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.msa b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.msa new file mode 100644 index 0000000000..bbc9c2ee24 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.msa @@ -0,0 +1,66 @@ + + + + + CirrusLogic5430UgaDraw + UEFI_DRIVER + BS_DRIVER + 555F76EA-785F-40d7-9174-153C43636C68 + 0 + Component description file for CirrusLogic5430 module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + CirrusLogic5430.h + CirrusLogic5430.c + CirrusLogic5430UgaDraw.c + ComponentName.c + + + MdePkg + + + PciIo + UgaDraw + + + + + + + gCirrusLogic5430DriverBinding + gCirrusLogic5430ComponentName + + + diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430UgaDraw.c b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430UgaDraw.c new file mode 100644 index 0000000000..c33918b675 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430UgaDraw.c @@ -0,0 +1,1036 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CirrusLogic5430UgaDraw.c + +Abstract: + + This file produces the graphics abstration of UGA Draw. It is called by + CirrusLogic5430.c file which deals with the EFI 1.1 driver model. + This file just does graphics. + +--*/ + +#include "CirrusLogic5430.h" + +// +// Video Mode structure +// +typedef struct { + UINT32 Width; + UINT32 Height; + UINT32 ColorDepth; + UINT32 RefreshRate; + UINT8 *CrtcSettings; + UINT16 *SeqSettings; + UINT8 MiscSetting; +} CIRRUS_LOGIC_5430_VIDEO_MODES; + +// +// Generic Attribute Controller Register Settings +// +static UINT8 AttributeController[21] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x41, 0x00, 0x0F, 0x00, 0x00 +}; + +// +// Generic Graphics Controller Register Settings +// +static UINT8 GraphicsController[9] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF +}; + +// +// 640 x 480 x 256 color @ 60 Hertz +// +static UINT8 Crtc_640_480_256_60[28] = { + 0x5d, 0x4f, 0x50, 0x82, 0x53, 0x9f, 0x00, 0x3e, + 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xe1, 0x83, 0xdf, 0x50, 0x00, 0xe7, 0x04, 0xe3, + 0xff, 0x00, 0x00, 0x22 +}; + +static UINT16 Seq_640_480_256_60[15] = { + 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b, + 0x5b0c, 0x450d, 0x7e0e, 0x2b1b, 0x2f1c, 0x301d, 0x331e +}; + +// +// 800 x 600 x 256 color @ 60 Hertz +// +static UINT8 Crtc_800_600_256_60[28] = { + 0x7F, 0x63, 0x64, 0x80, 0x6B, 0x1B, 0x72, 0xF0, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x8C, 0x57, 0x64, 0x00, 0x5F, 0x91, 0xE3, + 0xFF, 0x00, 0x00, 0x22 +}; + +static UINT16 Seq_800_600_256_60[15] = { + 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b, + 0x5b0c, 0x450d, 0x510e, 0x2b1b, 0x2f1c, 0x301d, 0x3a1e +}; + +// +// 1024 x 768 x 256 color @ 60 Hertz +// +static UINT8 Crtc_1024_768_256_60[28] = { + 0xA3, 0x7F, 0x80, 0x86, 0x85, 0x96, 0x24, 0xFD, + 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02, 0x88, 0xFF, 0x80, 0x00, 0x00, 0x24, 0xE3, + 0xFF, 0x4A, 0x00, 0x22 +}; + +static UINT16 Seq_1024_768_256_60[15] = { + 0x0100, 0x0101, 0x0f02, 0x0003, 0x0e04, 0x1107, 0x0008, 0x4a0b, + 0x5b0c, 0x450d, 0x760e, 0x2b1b, 0x2f1c, 0x301d, 0x341e +}; + +// +// Table of supported video modes +// +static CIRRUS_LOGIC_5430_VIDEO_MODES CirrusLogic5430VideoModes[] = { + { 640, 480, 8, 60, Crtc_640_480_256_60, Seq_640_480_256_60, 0xe3 }, + { 800, 600, 8, 60, Crtc_800_600_256_60, Seq_800_600_256_60, 0xef }, + { 1024, 768, 8, 60, Crtc_1024_768_256_60, Seq_1024_768_256_60, 0xef } +}; + +// +// Local Function Prototypes +// +VOID +InitializeGraphicsMode ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + CIRRUS_LOGIC_5430_VIDEO_MODES *ModeData + ); + +VOID +SetPaletteColor ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + UINTN Index, + UINT8 Red, + UINT8 Green, + UINT8 Blue + ); + +VOID +SetDefaultPalette ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private + ); + +STATIC +VOID +ClearScreen ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private + ); + +VOID +DrawLogo ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private + ); + +VOID +outb ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + UINTN Address, + UINT8 Data + ); + +VOID +outw ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + UINTN Address, + UINT16 Data + ); + +UINT8 +inb ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + UINTN Address + ); + +UINT16 +inw ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + UINTN Address + ); + +// +// UGA Draw Protocol Member Functions +// +EFI_STATUS +EFIAPI +CirrusLogic5430UgaDrawGetMode ( + IN EFI_UGA_DRAW_PROTOCOL *This, + OUT UINT32 *HorizontalResolution, + OUT UINT32 *VerticalResolution, + OUT UINT32 *ColorDepth, + OUT UINT32 *RefreshRate + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + HorizontalResolution - TODO: add argument description + VerticalResolution - TODO: add argument description + ColorDepth - TODO: add argument description + RefreshRate - TODO: add argument description + +Returns: + + EFI_NOT_STARTED - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private; + + Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This); + + if (Private->HardwareNeedsStarting) { + return EFI_NOT_STARTED; + } + + if ((HorizontalResolution == NULL) || + (VerticalResolution == NULL) || + (ColorDepth == NULL) || + (RefreshRate == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *HorizontalResolution = Private->ModeData[Private->CurrentMode].HorizontalResolution; + *VerticalResolution = Private->ModeData[Private->CurrentMode].VerticalResolution; + *ColorDepth = Private->ModeData[Private->CurrentMode].ColorDepth; + *RefreshRate = Private->ModeData[Private->CurrentMode].RefreshRate; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CirrusLogic5430UgaDrawSetMode ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + HorizontalResolution - TODO: add argument description + VerticalResolution - TODO: add argument description + ColorDepth - TODO: add argument description + RefreshRate - TODO: add argument description + +Returns: + + EFI_OUT_OF_RESOURCES - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_NOT_FOUND - TODO: Add description for return value + +--*/ +{ + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private; + UINTN Index; + + Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This); + + for (Index = 0; Index < Private->MaxMode; Index++) { + + if (HorizontalResolution != Private->ModeData[Index].HorizontalResolution) { + continue; + } + + if (VerticalResolution != Private->ModeData[Index].VerticalResolution) { + continue; + } + + if (ColorDepth != Private->ModeData[Index].ColorDepth) { + continue; + } + + if (RefreshRate != Private->ModeData[Index].RefreshRate) { + continue; + } + + if (Private->LineBuffer) { + gBS->FreePool (Private->LineBuffer); + } + + Private->LineBuffer = NULL; + Private->LineBuffer = AllocatePool (HorizontalResolution); + if (Private->LineBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + InitializeGraphicsMode (Private, &CirrusLogic5430VideoModes[Index]); + + Private->CurrentMode = Index; + + Private->HardwareNeedsStarting = FALSE; + + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +CirrusLogic5430UgaDrawBlt ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + BltBuffer - TODO: add argument description + BltOperation - TODO: add argument description + SourceX - TODO: add argument description + SourceY - TODO: add argument description + DestinationX - TODO: add argument description + DestinationY - TODO: add argument description + Width - TODO: add argument description + Height - TODO: add argument description + Delta - TODO: add argument description + +Returns: + + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private; + EFI_TPL OriginalTPL; + UINTN DstY; + UINTN SrcY; + EFI_UGA_PIXEL *Blt; + UINTN X; + UINT8 Pixel; + UINT32 WidePixel; + UINTN ScreenWidth; + UINTN Offset; + UINTN SourceOffset; + + Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (This); + + if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) { + return EFI_INVALID_PARAMETER; + } + + if (Width == 0 || Height == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // If Delta is zero, then the entire BltBuffer is being used, so Delta + // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size, + // the number of bytes in each row can be computed. + // + if (Delta == 0) { + Delta = Width * sizeof (EFI_UGA_PIXEL); + } + + // + // We need to fill the Virtual Screen buffer with the blt data. + // The virtual screen is upside down, as the first row is the bootom row of + // the image. + // + + // + // Make sure the SourceX, SourceY, DestinationX, DestinationY, Width, and Height parameters + // are valid for the operation and the current screen geometry. + // + if (BltOperation == EfiUgaVideoToBltBuffer) { + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if (SourceY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (SourceX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > Private->ModeData[Private->CurrentMode].VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > Private->ModeData[Private->CurrentMode].HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + } + // + // We have to raise to TPL Notify, so we make an atomic write the frame buffer. + // We would not want a timer based event (Cursor, ...) to come in while we are + // doing this operation. + // + OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + switch (BltOperation) { + case EfiUgaVideoToBltBuffer: + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) { + + Offset = (SrcY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + SourceX; + if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) { + Private->PciIo->Mem.Read ( + Private->PciIo, + EfiPciIoWidthUint32, + 0, + Offset, + Width >> 2, + Private->LineBuffer + ); + } else { + Private->PciIo->Mem.Read ( + Private->PciIo, + EfiPciIoWidthUint8, + 0, + Offset, + Width, + Private->LineBuffer + ); + } + + for (X = 0; X < Width; X++) { + Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + (DestinationX + X) * sizeof (EFI_UGA_PIXEL)); + + Blt->Red = (UINT8) (Private->LineBuffer[X] & 0xe0); + Blt->Green = (UINT8) ((Private->LineBuffer[X] & 0x1c) << 3); + Blt->Blue = (UINT8) ((Private->LineBuffer[X] & 0x03) << 6); + } + } + break; + + case EfiUgaVideoToVideo: + // + // Perform hardware acceleration for Video to Video operations + // + ScreenWidth = Private->ModeData[Private->CurrentMode].HorizontalResolution; + SourceOffset = (SourceY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (SourceX); + Offset = (DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + (DestinationX); + + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0000); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0010); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0012); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0014); + + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0001); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0011); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0013); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0015); + + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Width << 8) & 0xff00) | 0x20)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Width & 0xff00) | 0x21)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((Height << 8) & 0xff00) | 0x22)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((Height & 0xff00) | 0x23)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x24)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x25)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) (((ScreenWidth << 8) & 0xff00) | 0x26)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((ScreenWidth & 0xff00) | 0x27)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) << 8) & 0xff00) | 0x28)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 0) & 0xff00) | 0x29)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((Offset) >> 8) & 0xff00) | 0x2a)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) << 8) & 0xff00) | 0x2c)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 0) & 0xff00) | 0x2d)); + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((((SourceOffset) >> 8) & 0xff00) | 0x2e)); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x002f); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0030); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0d32); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0033); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0034); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0035); + + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0231); + + outb (Private, GRAPH_ADDRESS_REGISTER, 0x31); + while ((inb (Private, GRAPH_DATA_REGISTER) & 0x01) == 0x01) + ; + break; + + case EfiUgaVideoFill: + Blt = BltBuffer; + Pixel = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03)); + WidePixel = (Pixel << 8) | Pixel; + WidePixel = (WidePixel << 16) | WidePixel; + + if (DestinationX == 0 && Width == Private->ModeData[Private->CurrentMode].HorizontalResolution) { + Offset = DestinationY * Private->ModeData[Private->CurrentMode].HorizontalResolution; + if (((Offset & 0x03) == 0) && (((Width * Height) & 0x03) == 0)) { + Private->PciIo->Mem.Write ( + Private->PciIo, + EfiPciIoWidthFillUint32, + 0, + Offset, + (Width * Height) >> 2, + &WidePixel + ); + } else { + Private->PciIo->Mem.Write ( + Private->PciIo, + EfiPciIoWidthFillUint8, + 0, + Offset, + Width * Height, + &Pixel + ); + } + } else { + for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) { + Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX; + if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) { + Private->PciIo->Mem.Write ( + Private->PciIo, + EfiPciIoWidthFillUint32, + 0, + Offset, + Width >> 2, + &WidePixel + ); + } else { + Private->PciIo->Mem.Write ( + Private->PciIo, + EfiPciIoWidthFillUint8, + 0, + Offset, + Width, + &Pixel + ); + } + } + } + break; + + case EfiUgaBltBufferToVideo: + for (SrcY = SourceY, DstY = DestinationY; SrcY < (Height + SourceY); SrcY++, DstY++) { + + for (X = 0; X < Width; X++) { + Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + (SourceX + X) * sizeof (EFI_UGA_PIXEL)); + Private->LineBuffer[X] = (UINT8) ((Blt->Red & 0xe0) | ((Blt->Green >> 3) & 0x1c) | ((Blt->Blue >> 6) & 0x03)); + } + + Offset = (DstY * Private->ModeData[Private->CurrentMode].HorizontalResolution) + DestinationX; + + if (((Offset & 0x03) == 0) && ((Width & 0x03) == 0)) { + Private->PciIo->Mem.Write ( + Private->PciIo, + EfiPciIoWidthUint32, + 0, + Offset, + Width >> 2, + Private->LineBuffer + ); + } else { + Private->PciIo->Mem.Write ( + Private->PciIo, + EfiPciIoWidthUint8, + 0, + Offset, + Width, + Private->LineBuffer + ); + } + } + break; + + default: + break; + } + + gBS->RestoreTPL (OriginalTPL); + + return EFI_SUCCESS; +} + +// +// Construction and Destruction functions +// + +EFI_STATUS +CirrusLogic5430UgaDrawConstructor ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Private - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + UINTN Index; + + // + // Fill in Private->UgaDraw protocol + // + UgaDraw = &Private->UgaDraw; + + UgaDraw->GetMode = CirrusLogic5430UgaDrawGetMode; + UgaDraw->SetMode = CirrusLogic5430UgaDrawSetMode; + UgaDraw->Blt = CirrusLogic5430UgaDrawBlt; + + // + // Initialize the private data + // + Private->MaxMode = CIRRUS_LOGIC_5430_UGA_DRAW_MODE_COUNT; + Private->CurrentMode = 0; + for (Index = 0; Index < Private->MaxMode; Index++) { + Private->ModeData[Index].HorizontalResolution = CirrusLogic5430VideoModes[Index].Width; + Private->ModeData[Index].VerticalResolution = CirrusLogic5430VideoModes[Index].Height; + Private->ModeData[Index].ColorDepth = 32; + Private->ModeData[Index].RefreshRate = CirrusLogic5430VideoModes[Index].RefreshRate; + } + + Private->HardwareNeedsStarting = TRUE; + Private->LineBuffer = NULL; + + // + // Initialize the hardware + // + UgaDraw->SetMode ( + UgaDraw, + Private->ModeData[Private->CurrentMode].HorizontalResolution, + Private->ModeData[Private->CurrentMode].VerticalResolution, + Private->ModeData[Private->CurrentMode].ColorDepth, + Private->ModeData[Private->CurrentMode].RefreshRate + ); + DrawLogo (Private); + + return EFI_SUCCESS; +} + +EFI_STATUS +CirrusLogic5430UgaDrawDestructor ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Private - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + return EFI_SUCCESS; +} + +VOID +outb ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + UINTN Address, + UINT8 Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + Address - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + Private->PciIo->Io.Write ( + Private->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Address, + 1, + &Data + ); +} + +VOID +outw ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + UINTN Address, + UINT16 Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + Address - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + Private->PciIo->Io.Write ( + Private->PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + Address, + 1, + &Data + ); +} + +UINT8 +inb ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + UINTN Address + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + Address - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT8 Data; + + Private->PciIo->Io.Read ( + Private->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + Address, + 1, + &Data + ); + return Data; +} + +UINT16 +inw ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + UINTN Address + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + Address - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT16 Data; + + Private->PciIo->Io.Read ( + Private->PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + Address, + 1, + &Data + ); + return Data; +} + +VOID +SetPaletteColor ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + UINTN Index, + UINT8 Red, + UINT8 Green, + UINT8 Blue + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + Index - TODO: add argument description + Red - TODO: add argument description + Green - TODO: add argument description + Blue - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + outb (Private, PALETTE_INDEX_REGISTER, (UINT8) Index); + outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Red >> 2)); + outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Green >> 2)); + outb (Private, PALETTE_DATA_REGISTER, (UINT8) (Blue >> 2)); +} + +VOID +SetDefaultPalette ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINTN Index; + UINTN RedIndex; + UINTN GreenIndex; + UINTN BlueIndex; + + Index = 0; + for (RedIndex = 0; RedIndex < 8; RedIndex++) { + for (GreenIndex = 0; GreenIndex < 8; GreenIndex++) { + for (BlueIndex = 0; BlueIndex < 4; BlueIndex++) { + SetPaletteColor (Private, Index, (UINT8) (RedIndex << 5), (UINT8) (GreenIndex << 5), (UINT8) (BlueIndex << 6)); + Index++; + } + } + } +} + +STATIC +VOID +ClearScreen ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT32 Color; + + Color = 0; + Private->PciIo->Mem.Write ( + Private->PciIo, + EfiPciIoWidthFillUint32, + 0, + 0, + 0x100000 >> 2, + &Color + ); +} + +VOID +DrawLogo ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINTN Offset; + UINTN X; + UINTN Y; + UINTN ScreenWidth; + UINTN ScreenHeight; + UINT8 Color; + + ScreenWidth = Private->ModeData[Private->CurrentMode].HorizontalResolution; + ScreenHeight = Private->ModeData[Private->CurrentMode].VerticalResolution; + + Offset = 0; + for (Y = 0; Y < ScreenHeight; Y++) { + for (X = 0; X < ScreenWidth; X++) { + Color = (UINT8) (256 * (X + Y) / (ScreenWidth + ScreenHeight)); + Private->LineBuffer[X] = Color; + } + + Private->PciIo->Mem.Write ( + Private->PciIo, + EfiPciIoWidthUint32, + 0, + Offset + (Y * ScreenWidth), + ScreenWidth >> 2, + Private->LineBuffer + ); + } +} + +VOID +InitializeGraphicsMode ( + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private, + CIRRUS_LOGIC_5430_VIDEO_MODES *ModeData + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + ModeData - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT8 Byte; + UINTN Index; + + outw (Private, SEQ_ADDRESS_REGISTER, 0x1206); + outw (Private, SEQ_ADDRESS_REGISTER, 0x0012); + + for (Index = 0; Index < 15; Index++) { + outw (Private, SEQ_ADDRESS_REGISTER, ModeData->SeqSettings[Index]); + } + + outb (Private, SEQ_ADDRESS_REGISTER, 0x0f); + Byte = (UINT8) ((inb (Private, SEQ_DATA_REGISTER) & 0xc7) ^ 0x30); + outb (Private, SEQ_DATA_REGISTER, Byte); + + outb (Private, MISC_OUTPUT_REGISTER, ModeData->MiscSetting); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0506); + outw (Private, SEQ_ADDRESS_REGISTER, 0x0300); + outw (Private, CRTC_ADDRESS_REGISTER, 0x2011); + + for (Index = 0; Index < 28; Index++) { + outw (Private, CRTC_ADDRESS_REGISTER, (UINT16) ((ModeData->CrtcSettings[Index] << 8) | Index)); + } + + for (Index = 0; Index < 9; Index++) { + outw (Private, GRAPH_ADDRESS_REGISTER, (UINT16) ((GraphicsController[Index] << 8) | Index)); + } + + inb (Private, INPUT_STATUS_1_REGISTER); + + for (Index = 0; Index < 21; Index++) { + outb (Private, ATT_ADDRESS_REGISTER, (UINT8) Index); + outb (Private, ATT_ADDRESS_REGISTER, AttributeController[Index]); + } + + outb (Private, ATT_ADDRESS_REGISTER, 0x20); + + outw (Private, GRAPH_ADDRESS_REGISTER, 0x0009); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x000a); + outw (Private, GRAPH_ADDRESS_REGISTER, 0x000b); + outb (Private, DAC_PIXEL_MASK_REGISTER, 0xff); + + SetDefaultPalette (Private); + ClearScreen (Private); +} diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/ComponentName.c new file mode 100644 index 0000000000..5c10b6d7b4 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/ComponentName.c @@ -0,0 +1,222 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "CirrusLogic5430.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +CirrusLogic5430ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +CirrusLogic5430ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gCirrusLogic5430ComponentName = { + CirrusLogic5430ComponentNameGetDriverName, + CirrusLogic5430ComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mCirrusLogic5430DriverNameTable[] = { + { "eng", (CHAR16 *) L"Cirrus Logic 5430 UGA Driver" }, + { NULL , NULL } +}; + +static EFI_UNICODE_STRING_TABLE mCirrusLogic5430ControllerNameTable[] = { + { "eng", (CHAR16 *) L"Cirrus Logic 5430 PCI Adapter" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +CirrusLogic5430ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gCirrusLogic5430ComponentName.SupportedLanguages, + mCirrusLogic5430DriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +CirrusLogic5430ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_STATUS Status; + CIRRUS_LOGIC_5430_PRIVATE_DATA *Private; + EFI_PCI_IO_PROTOCOL *PciIoProtocol; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Check Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIoProtocol, + gCirrusLogic5430DriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + gCirrusLogic5430DriverBinding.DriverBindingHandle, + ControllerHandle + ); + + return EFI_UNSUPPORTED; + } + + if (Status != EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } + + // + // Get the UGA Draw Protocol on Controller + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw, + gCirrusLogic5430DriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the Cirrus Logic 5430's Device structure + // + Private = CIRRUS_LOGIC_5430_PRIVATE_DATA_FROM_UGA_DRAW_THIS (UgaDraw); + + return LookupUnicodeString ( + Language, + gCirrusLogic5430ComponentName.SupportedLanguages, + mCirrusLogic5430ControllerNameTable, + ControllerName + ); +} diff --git a/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/build.xml b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/build.xml new file mode 100644 index 0000000000..c8e44b1e6c --- /dev/null +++ b/EdkModulePkg/Bus/Pci/CirrusLogic/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.c new file mode 100644 index 0000000000..8008527dd1 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.c @@ -0,0 +1,224 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "IDEBus.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName = { + IDEBusComponentNameGetDriverName, + IDEBusComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mIDEBusDriverNameTable[] = { + { "eng", (CHAR16 *) L"PCI IDE/ATAPI Bus Driver" }, + { NULL , NULL } +}; + +STATIC EFI_UNICODE_STRING_TABLE mIDEBusControllerNameTable[] = { + { "eng", (CHAR16 *) L"PCI IDE/ATAPI Controller" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +IDEBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gIDEBusComponentName.SupportedLanguages, + mIDEBusDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +IDEBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + IDE_BLK_IO_DEV *IdeBlkIoDevice; + + // + // Get the controller context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiCallerIdGuid, + NULL, + gIDEBusDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (ChildHandle == NULL) { + return LookupUnicodeString ( + Language, + gIDEBusComponentName.SupportedLanguages, + mIDEBusControllerNameTable, + ControllerName + ); + } + + // + // Get the child context + // + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gIDEBusDriverBinding.DriverBindingHandle, + ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlockIo); + + return LookupUnicodeString ( + Language, + gIDEBusComponentName.SupportedLanguages, + IdeBlkIoDevice->ControllerNameTable, + ControllerName + ); +} + +VOID +AddName ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevicePtr + ) +/*++ + + Routine Description: + Add the component name for the IDE/ATAPI device + + Arguments: + IdeBlkIoDevicePtr - A pointer to the IDE_BLK_IO_DEV instance. + + Returns: + +--*/ +{ + UINTN StringIndex; + CHAR16 ModelName[41]; + + // + // Add Component Name for the IDE/ATAPI device that was discovered. + // + IdeBlkIoDevicePtr->ControllerNameTable = NULL; + for (StringIndex = 0; StringIndex < 41; StringIndex++) { + ModelName[StringIndex] = IdeBlkIoDevicePtr->ModelName[StringIndex]; + } + + AddUnicodeString ( + "eng", + gIDEBusComponentName.SupportedLanguages, + &IdeBlkIoDevicePtr->ControllerNameTable, + ModelName + ); +} diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.h new file mode 100644 index 0000000000..f6c3feb436 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ComponentName.h @@ -0,0 +1,118 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.h + +Abstract: + + +Revision History +--*/ + +#ifndef _IDE_BUS_COMPONENT_NAME_H +#define _IDE_BUS_COMPONENT_NAME_H + + +#ifndef EFI_SIZE_REDUCTION_APPLIED + +#define ADD_NAME(x) AddName ((x)); + +extern EFI_COMPONENT_NAME_PROTOCOL gIDEBusComponentName; + +#else + +#define ADD_NAME(x) + +#endif + + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +IDEBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Language - TODO: add argument description + DriverName - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ControllerHandle - TODO: add argument description + ChildHandle - TODO: add argument description + Language - TODO: add argument description + ControllerName - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +AddName ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevicePtr + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeBlkIoDevicePtr - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverConfiguration.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverConfiguration.c new file mode 100644 index 0000000000..b8f71fdc8d --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverConfiguration.c @@ -0,0 +1,378 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DriverConfiguration.c + +Abstract: + +--*/ + +#include "IDEBus.h" + +CHAR16 *OptionString[4] = { + L"Enable Primary Master (Y/N)? -->", + L"Enable Primary Slave (Y/N)? -->", + L"Enable Secondary Master (Y/N)? -->", + L"Enable Secondary Slave (Y/N)? -->" +}; +// +// EFI Driver Configuration Functions +// +EFI_STATUS +IDEBusDriverConfigurationSetOptions ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + +EFI_STATUS +IDEBusDriverConfigurationOptionsValid ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL + ); + +EFI_STATUS +IDEBusDriverConfigurationForceDefaults ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN UINT32 DefaultType, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + +// +// EFI Driver Configuration Protocol +// +EFI_DRIVER_CONFIGURATION_PROTOCOL gIDEBusDriverConfiguration = { + IDEBusDriverConfigurationSetOptions, + IDEBusDriverConfigurationOptionsValid, + IDEBusDriverConfigurationForceDefaults, + "eng" +}; + +EFI_STATUS +GetResponse ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + EFI_ABORTED - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_NOT_FOUND - TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + + while (TRUE) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (!EFI_ERROR (Status)) { + if (Key.ScanCode == SCAN_ESC) { + return EFI_ABORTED; + } + + switch (Key.UnicodeChar) { + + // + // fall through + // + case L'y': + case L'Y': + gST->ConOut->OutputString (gST->ConOut, L"Y\n"); + return EFI_SUCCESS; + + // + // fall through + // + case L'n': + case L'N': + gST->ConOut->OutputString (gST->ConOut, L"N\n"); + return EFI_NOT_FOUND; + } + + } + } +} + +EFI_STATUS +IDEBusDriverConfigurationSetOptions ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ) +/*++ + + Routine Description: + Allows the user to set controller specific options for a controller that a + driver is currently managing. + + Arguments: + This - A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL + instance. + ControllerHandle - The handle of the controller to set options on. + ChildHandle - The handle of the child controller to set options on. + This is an optional parameter that may be NULL. + It will be NULL for device drivers, and for a bus drivers + that wish to set options for the bus controller. + It will not be NULL for a bus driver that wishes to set + options for one of its child controllers. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the user interface + that should be presented to the user, and it must match + one of the languages specified in SupportedLanguages. + The number of languages supported by a driver is up to + the driver writer. + ActionRequired - A pointer to the action that the calling agent is + required to perform when this function returns. + See "Related Definitions" for a list of the actions that + the calling agent is required to perform prior to + accessing ControllerHandle again. + + Returns: + EFI_SUCCESS - The driver specified by This successfully set the + configuration options for the controller specified + by ControllerHandle.. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a + valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ActionRequired is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support + setting configuration options for the controller + specified by ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + EFI_DEVICE_ERROR - A device error occurred while attempt to set the + configuration options for the controller specified + by ControllerHandle and ChildHandle. + EFI_OUT_RESOURCES - There are not enough resources available to set the + configuration options for the controller specified + by ControllerHandle and ChildHandle. + +--*/ +{ + EFI_STATUS Status; + UINT8 Value; + UINT8 NewValue; + UINTN DataSize; + UINTN Index; + UINT32 Attributes; + + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + *ActionRequired = EfiDriverConfigurationActionNone; + + DataSize = sizeof (Value); + Status = gRT->GetVariable ( + L"Configuration", + &gEfiCallerIdGuid, + &Attributes, + &DataSize, + &Value + ); + + gST->ConOut->OutputString (gST->ConOut, L"IDE Bus Driver Configuration\n"); + gST->ConOut->OutputString (gST->ConOut, L"===============================\n"); + + NewValue = 0; + for (Index = 0; Index < 4; Index++) { + gST->ConOut->OutputString (gST->ConOut, OptionString[Index]); + + Status = GetResponse (); + if (Status == EFI_ABORTED) { + return EFI_SUCCESS; + } + + if (!EFI_ERROR (Status)) { + NewValue |= (UINT8) (1 << Index); + } + } + + if (EFI_ERROR (Status) || (NewValue != Value)) { + gRT->SetVariable ( + L"Configuration", + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (NewValue), + &NewValue + ); + + *ActionRequired = EfiDriverConfigurationActionRestartController; + } else { + *ActionRequired = EfiDriverConfigurationActionNone; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +IDEBusDriverConfigurationOptionsValid ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL + ) +/*++ + + Routine Description: + Tests to see if a controller's current configuration options are valid. + + Arguments: + This - A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL + instance. + ControllerHandle - The handle of the controller to test if it's current + configuration options are valid. + ChildHandle - The handle of the child controller to test if it's + current + configuration options are valid. This is an optional + parameter that may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers that + wish to test the configuration options for the bus + controller. It will not be NULL for a bus driver that + wishes to test configuration options for one of + its child controllers. + + Returns: + EFI_SUCCESS - The controller specified by ControllerHandle and + ChildHandle that is being managed by the driver + specified by This has a valid set of configuration + options. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_DEVICE_ERROR - The controller specified by ControllerHandle and + ChildHandle that is being managed by the driver + specified by This has an invalid set of + configuration options. + +--*/ +{ + EFI_STATUS Status; + UINT8 Value; + UINTN DataSize; + UINT32 Attributes; + + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + DataSize = sizeof (Value); + Status = gRT->GetVariable ( + L"Configuration", + &gEfiCallerIdGuid, + &Attributes, + &DataSize, + &Value + ); + if (EFI_ERROR (Status) || Value > 0x0f) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +IDEBusDriverConfigurationForceDefaults ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN UINT32 DefaultType, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ) +/*++ + + Routine Description: + Forces a driver to set the default configuration options for a controller. + + Arguments: + This - A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL + instance. + ControllerHandle - The handle of the controller to force default + configuration options on. + ChildHandle - The handle of the child controller to force default + configuration options on This is an optional parameter + that may be NULL. It will be NULL for device drivers. + It will also be NULL for a bus drivers that wish to + force default configuration options for the bus + controller. It will not be NULL for a bus driver that + wishes to force default configuration options for one + of its child controllers. + DefaultType - The type of default configuration options to force on + the controller specified by ControllerHandle and + ChildHandle. See Table 9-1 for legal values. + A DefaultType of 0x00000000 must be supported + by this protocol. + ActionRequired - A pointer to the action that the calling agent + is required to perform when this function returns. + + + Returns: + EFI_SUCCESS - The driver specified by This successfully forced + the default configuration options on the + controller specified by ControllerHandle and + ChildHandle. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a + valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ActionRequired is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support + forcing the default configuration options on + the controller specified by ControllerHandle + and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support + the configuration type specified by DefaultType. + EFI_DEVICE_ERROR - A device error occurred while attempt to force + the default configuration options on the controller + specified by ControllerHandle and ChildHandle. + EFI_OUT_RESOURCES - There are not enough resources available to force + the default configuration options on the controller + specified by ControllerHandle and ChildHandle. + +--*/ +{ + UINT8 Value; + + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + Value = 0x0f; + gRT->SetVariable ( + L"Configuration", + &gEfiCallerIdGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (Value), + &Value + ); + *ActionRequired = EfiDriverConfigurationActionRestartController; + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverDiagnostics.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverDiagnostics.c new file mode 100644 index 0000000000..ce3be14234 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/DriverDiagnostics.c @@ -0,0 +1,225 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DriverDiagnostics.c + +Abstract: + +--*/ + +#include "IDEBus.h" + +#define IDE_BUS_DIAGNOSTIC_ERROR L"PCI IDE/ATAPI Driver Diagnostics Failed" + +// +// EFI Driver Diagnostics Functions +// +EFI_STATUS +IDEBusDriverDiagnosticsRunDiagnostics ( + IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, + IN CHAR8 *Language, + OUT EFI_GUID **ErrorType, + OUT UINTN *BufferSize, + OUT CHAR16 **Buffer + ); + +// +// EFI Driver Diagnostics Protocol +// +EFI_DRIVER_DIAGNOSTICS_PROTOCOL gIDEBusDriverDiagnostics = { + IDEBusDriverDiagnosticsRunDiagnostics, + "eng" +}; + +EFI_STATUS +IDEBusDriverDiagnosticsRunDiagnostics ( + IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, + IN CHAR8 *Language, + OUT EFI_GUID **ErrorType, + OUT UINTN *BufferSize, + OUT CHAR16 **Buffer + ) +/*++ + + Routine Description: + Runs diagnostics on a controller. + + Arguments: + This - A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOL + instance. + ControllerHandle - The handle of the controller to run diagnostics on. + ChildHandle - The handle of the child controller to run diagnostics on + This is an optional parameter that may be NULL. It will + be NULL for device drivers. It will also be NULL for a + bus drivers that wish to run diagnostics on the bus + controller. It will not be NULL for a bus driver that + wishes to run diagnostics on one of its child + controllers. + DiagnosticType - Indicates type of diagnostics to perform on the + controller specified by ControllerHandle and ChildHandle. + See "Related Definitions" for the list of supported + types. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language in which the optional + error message should be returned in Buffer, and it must + match one of the languages specified in + SupportedLanguages. The number of languages supported by + a driver is up to the driver writer. + ErrorType - A GUID that defines the format of the data returned in + Buffer. + BufferSize - The size, in bytes, of the data returned in Buffer. + Buffer - A buffer that contains a Null-terminated Unicode string + plus some additional data whose format is defined by + ErrorType. Buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility + to free it with a call to FreePool(). + + Returns: + EFI_SUCCESS - The controller specified by ControllerHandle and + ChildHandle passed the diagnostic. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ErrorType is NULL. + EFI_INVALID_PARAMETER - BufferType is NULL. + EFI_INVALID_PARAMETER - Buffer is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support + running diagnostics for the controller specified + by ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + type of diagnostic specified by DiagnosticType. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + EFI_OUT_OF_RESOURCES - There are not enough resources available to complete + the diagnostics. + EFI_OUT_OF_RESOURCES - There are not enough resources available to return + the status information in ErrorType, BufferSize, + and Buffer. + EFI_DEVICE_ERROR - The controller specified by ControllerHandle and + ChildHandle did not pass the diagnostic. + +--*/ +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + IDE_BLK_IO_DEV *IdeBlkIoDevice; + UINT32 VendorDeviceId; + VOID *BlockBuffer; + + *ErrorType = NULL; + *BufferSize = 0; + + if (ChildHandle == NULL) { + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiCallerIdGuid, + NULL, + gIDEBusDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + gIDEBusDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Use services of PCI I/O Protocol to test the PCI IDE/ATAPI Controller + // The following test simply reads the Device ID and Vendor ID. + // It should never fail. A real test would perform more advanced + // diagnostics. + // + + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &VendorDeviceId); + if (EFI_ERROR (Status) || VendorDeviceId == 0xffffffff) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + } + + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo, + gIDEBusDriverBinding.DriverBindingHandle, + ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); + + // + // Use services available from IdeBlkIoDevice to test the IDE/ATAPI device + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + IdeBlkIoDevice->BlkMedia.BlockSize, + (VOID **) &BlockBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = IdeBlkIoDevice->BlkIo.ReadBlocks ( + &IdeBlkIoDevice->BlkIo, + IdeBlkIoDevice->BlkMedia.MediaId, + 0, + IdeBlkIoDevice->BlkMedia.BlockSize, + BlockBuffer + ); + + if (EFI_ERROR (Status)) { + *ErrorType = &gEfiCallerIdGuid; + *BufferSize = sizeof (IDE_BUS_DIAGNOSTIC_ERROR); + + Status = gBS->AllocatePool ( + EfiBootServicesData, + (UINTN) (*BufferSize), + (VOID **) Buffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + EfiCopyMem (*Buffer, IDE_BUS_DIAGNOSTIC_ERROR, *BufferSize); + + Status = EFI_DEVICE_ERROR; + } + + gBS->FreePool (BlockBuffer); + + return Status; +} diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c new file mode 100644 index 0000000000..88e81c0ada --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ata.c @@ -0,0 +1,3690 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ata.c + +Abstract: + +Revision History + + 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including + update - ATAIdentity() func + update - AtaBlockIoReadBlocks() func + update - AtaBlockIoWriteBlocks() func + add - AtaAtapi6Identify() func + add - AtaReadSectorsExt() func + add - AtaWriteSectorsExt() func + add - AtaPioDataInExt() func + add - AtaPioDataOutExt() func + +--*/ + +#include "idebus.h" + + +EFI_STATUS +AtaReadSectorsExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN OUT VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ); + +EFI_STATUS +AtaWriteSectorsExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ); + +EFI_STATUS +AtaPioDataInExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN OUT VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN EFI_LBA StartLba, + IN UINT16 SectorCount + ); + +EFI_STATUS +AtaPioDataOutExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN EFI_LBA StartLba, + IN UINT16 SectorCount + ); + +EFI_STATUS +ATAIdentify ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + ATAIdentify + + + Purpose: + This function is called by DiscoverIdeDevice() during its device + identification. It sends out the ATA Identify Command to the + specified device. Only ATA device responses to this command. If + the command succeeds, it returns the Identify data structure which + contains information about the device. This function extracts the + information it needs to fill the IDE_BLK_IO_DEV data structure, + including device type, media block size, media capacity, and etc. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure,used + to record all the information of the IDE device. + + + Returns: + EFI_SUCCESS + Identify ATA device successfully. + + EFI_DEVICE_ERROR + ATA Identify Device Command failed or device is not + ATA device. + + + Notes: + parameter IdeDev will be updated in this function. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_IDENTIFY_DATA *AtaIdentifyPointer; + UINT32 Capacity; + UINT8 DeviceSelect; + + // + // AtaIdentifyPointer is used for accommodating returned IDENTIFY data of + // the ATA Identify command + // + AtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA)); + + // + // use ATA PIO Data In protocol to send ATA Identify command + // and receive data from device + // + DeviceSelect = 0; + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + Status = AtaPioDataIn ( + IdeDev, + (VOID *) AtaIdentifyPointer, + sizeof (EFI_IDENTIFY_DATA), + IDENTIFY_DRIVE_CMD, + DeviceSelect, + 0, + 0, + 0, + 0 + ); + // + // If ATA Identify command succeeds, then according to the received + // IDENTIFY data, + // identify the device type ( ATA or not ). + // If ATA device, fill the information in IdeDev. + // If not ATA device, return IDE_DEVICE_ERROR + // + if (!EFI_ERROR (Status)) { + + IdeDev->pIdData = AtaIdentifyPointer; + + // + // Print ATA Module Name + // + PrintAtaModuleName (IdeDev); + + // + // bit 15 of pAtaIdentify->config is used to identify whether device is + // ATA device or ATAPI device. + // if 0, means ATA device; if 1, means ATAPI device. + // + if ((AtaIdentifyPointer->AtaData.config & 0x8000) == 0x00) { + // + // Detect if support S.M.A.R.T. If yes, enable it as default + // + AtaSMARTSupport (IdeDev); + + // + // Check whether this device needs 48-bit addressing (ATAPI-6 ata device) + // + Status = AtaAtapi6Identify (IdeDev); + if (!EFI_ERROR (Status)) { + // + // It's a disk with >120GB capacity, initialized in AtaAtapi6Identify() + // + return EFI_SUCCESS; + } + // + // This is a hard disk <= 120GB capacity, treat it as normal hard disk + // + IdeDev->Type = IdeHardDisk; + + // + // Block Media Information: + // Media->LogicalPartition , Media->WriteCaching will be filled + // in the DiscoverIdeDevcie() function. + // + IdeDev->BlkIo.Media->IoAlign = 4; + IdeDev->BlkIo.Media->MediaId = 1; + IdeDev->BlkIo.Media->RemovableMedia = FALSE; + IdeDev->BlkIo.Media->MediaPresent = TRUE; + IdeDev->BlkIo.Media->ReadOnly = FALSE; + IdeDev->BlkIo.Media->BlockSize = 0x200; + + // + // Calculate device capacity + // + Capacity = ((UINT32)AtaIdentifyPointer->AtaData.user_addressable_sectors_hi << 16) | + AtaIdentifyPointer->AtaData.user_addressable_sectors_lo ; + IdeDev->BlkIo.Media->LastBlock = Capacity - 1; + + return EFI_SUCCESS; + + } + } + + gBS->FreePool (AtaIdentifyPointer); + // + // Make sure the pIdData will not be freed again. + // + IdeDev->pIdData = NULL; + + return EFI_DEVICE_ERROR; +} + + +EFI_STATUS +AtaAtapi6Identify ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + + AtaAtapi6Identify + + Purpose: + + This function is called by ATAIdentify() to identity whether this disk + supports ATA/ATAPI6 48bit addressing, ie support >120G capacity + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + Returns: + + EFI_SUCCESS - The disk specified by IdeDev is a Atapi6 supported one + and 48-bit addressing must be used + + EFI_UNSUPPORTED - The disk dosn't not support Atapi6 or it supports but + the capacity is below 120G, 48bit addressing is not + needed + + Notes: + + This function must be called after DEVICE_IDENTITY command has been + successfully returned +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +{ + UINT8 Index; + EFI_LBA TmpLba; + EFI_LBA Capacity; + EFI_IDENTIFY_DATA *Atapi6IdentifyStruct; + + if (IdeDev->pIdData == NULL) { + return EFI_UNSUPPORTED; + } + + Atapi6IdentifyStruct = IdeDev->pIdData; + + if ((Atapi6IdentifyStruct->AtapiData.cmd_set_support_83 & bit10) == 0) { + // + // The device dosn't support 48 bit addressing + // + return EFI_UNSUPPORTED; + } + + // + // 48 bit address feature set is supported, get maximum capacity + // + Capacity = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[0]; + for (Index = 1; Index < 4; Index++) { + // + // Lower byte goes first: word[100] is the lowest word, word[103] is highest + // + TmpLba = Atapi6IdentifyStruct->AtapiData.max_user_lba_for_48bit_addr[Index]; + Capacity |= LShiftU64 (TmpLba, 16 * Index); + } + + if (Capacity > MAX_28BIT_ADDRESSING_CAPACITY) { + // + // Capacity exceeds 120GB. 48-bit addressing is really needed + // + IdeDev->Type = Ide48bitAddressingHardDisk; + + // + // Fill block media information:Media->LogicalPartition , + // Media->WriteCaching will be filledin the DiscoverIdeDevcie() function. + // + IdeDev->BlkIo.Media->IoAlign = 4; + IdeDev->BlkIo.Media->MediaId = 1; + IdeDev->BlkIo.Media->RemovableMedia = FALSE; + IdeDev->BlkIo.Media->MediaPresent = TRUE; + IdeDev->BlkIo.Media->ReadOnly = FALSE; + IdeDev->BlkIo.Media->BlockSize = 0x200; + IdeDev->BlkIo.Media->LastBlock = Capacity - 1; + + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + +VOID +PrintAtaModuleName ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + PrintAtaModuleName + + + Purpose: + This function is called by ATAIdentify() or ATAPIIdentify() + to print device's module name. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + Returns: + no returns. + + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +{ + if (IdeDev->pIdData == NULL) { + return ; + } + + SwapStringChars (IdeDev->ModelName, IdeDev->pIdData->AtaData.ModelName, 40); + IdeDev->ModelName[40] = 0x00; +} + +EFI_STATUS +AtaPioDataIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN UINT8 Head, + IN UINT8 SectorCount, + IN UINT8 SectorNumber, + IN UINT8 CylinderLsb, + IN UINT8 CylinderMsb + ) +/*++ + Name: + AtaPioDataIn + + + Purpose: + This function is used to send out ATA commands conforms to the + PIO Data In Protocol. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *Buffer + buffer contained data transferred from device to host. + + UINT32 IN ByteCount + data size in byte unit of the buffer. + + UINT8 IN AtaCommand + value of the Command Register + + UINT8 IN Head + value of the Head/Device Register + + UINT8 IN SectorCount + value of the Sector Count Register + + UINT8 IN SectorNumber + value of the Sector Number Register + + UINT8 IN CylinderLsb + value of the low byte of the Cylinder Register + + UINT8 IN CylinderMsb + value of the high byte of the Cylinder Register + + + Returns: + EFI_SUCCESS + send out the ATA command and device send required + data successfully. + + EFI_DEVICE_ERROR + command sent failed. + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: ByteCount - add argument and description to function comment +// TODO: AtaCommand - add argument and description to function comment +// TODO: Head - add argument and description to function comment +// TODO: SectorCount - add argument and description to function comment +// TODO: SectorNumber - add argument and description to function comment +// TODO: CylinderLsb - add argument and description to function comment +// TODO: CylinderMsb - add argument and description to function comment +{ + UINTN WordCount; + UINTN Increment; + UINT16 *Buffer16; + EFI_STATUS Status; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // e0:1110,0000-- bit7 and bit5 are reserved bits. + // bit6 set means LBA mode + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head) + ); + + // + // All ATAPI device's ATA commands can be issued regardless of the + // state of the DRDY + // + if (IdeDev->Type == IdeHardDisk) { + + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + } + // + // set all the command parameters + // Before write to all the following registers, BSY and DRQ must be 0. + // + Status = DRQClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (AtaCommand == SET_FEATURES_CMD) { + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); + } + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb); + + // + // send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + Buffer16 = (UINT16 *) Buffer; + + // + // According to PIO data in protocol, host can perform a series of reads to + // the data register after each time device set DRQ ready; + // The data size of "a series of read" is command specific. + // For most ATA command, data size received from device will not exceed + // 1 sector, hence the data size for "a series of read" can be the whole data + // size of one command request. + // For ATA command such as Read Sector command, the data size of one ATA + // command request is often larger than 1 sector, according to the + // Read Sector command, the data size of "a series of read" is exactly 1 + // sector. + // Here for simplification reason, we specify the data size for + // "a series of read" to 1 sector (256 words) if data size of one ATA command + // request is larger than 256 words. + // + Increment = 256; + + // + // used to record bytes of currently transfered data + // + WordCount = 0; + + while (WordCount < ByteCount / 2) { + // + // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. + // + Status = DRQReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = CheckErrorStatus (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Get the byte count for one series of read + // + if ((WordCount + Increment) > ByteCount / 2) { + Increment = ByteCount / 2 - WordCount; + } + + IDEReadPortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + Increment, + Buffer16 + ); + + WordCount += Increment; + Buffer16 += Increment; + + } + + DRQClear (IdeDev, ATATIMEOUT); + + return CheckErrorStatus (IdeDev); +} + +EFI_STATUS +AtaPioDataOut ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN UINT8 Head, + IN UINT8 SectorCount, + IN UINT8 SectorNumber, + IN UINT8 CylinderLsb, + IN UINT8 CylinderMsb + ) +/*++ + Name: + AtaPioDataOut + + + Purpose: + This function is used to send out ATA commands conforms to the + PIO Data Out Protocol. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *Buffer + buffer contained data transferred from host to device. + + UINT32 IN ByteCount + data size in byte unit of the buffer. + + UINT8 IN AtaCommand + value of the Command Register + + UINT8 IN Head + value of the Head/Device Register + + UINT8 IN SectorCount + value of the Sector Count Register + + UINT8 IN SectorNumber + value of the Sector Number Register + + UINT8 IN CylinderLsb + value of the low byte of the Cylinder Register + + UINT8 IN CylinderMsb + value of the high byte of the Cylinder Register + + + Returns: + EFI_SUCCESS + send out the ATA command and device received required + data successfully. + + EFI_DEVICE_ERROR + command sent failed. + + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: ByteCount - add argument and description to function comment +// TODO: AtaCommand - add argument and description to function comment +// TODO: Head - add argument and description to function comment +// TODO: SectorCount - add argument and description to function comment +// TODO: SectorNumber - add argument and description to function comment +// TODO: CylinderLsb - add argument and description to function comment +// TODO: CylinderMsb - add argument and description to function comment +{ + UINTN WordCount; + UINTN Increment; + UINT16 *Buffer16; + EFI_STATUS Status; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // select device via Head/Device register. + // Before write Head/Device register, BSY and DRQ must be 0. + // + Status = DRQClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // e0:1110,0000-- bit7 and bit5 are reserved bits. + // bit6 set means LBA mode + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0 | Head) + ); + + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // set all the command parameters + // Before write to all the following registers, BSY and DRQ must be 0. + // + Status = DRQClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, SectorNumber); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, CylinderLsb); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, CylinderMsb); + + // + // send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + Buffer16 = (UINT16 *) Buffer; + + // + // According to PIO data out protocol, host can perform a series of + // writes to the data register after each time device set DRQ ready; + // The data size of "a series of read" is command specific. + // For most ATA command, data size written to device will not exceed 1 sector, + // hence the data size for "a series of write" can be the data size of one + // command request. + // For ATA command such as Write Sector command, the data size of one + // ATA command request is often larger than 1 sector, according to the + // Write Sector command, the data size of "a series of read" is exactly + // 1 sector. + // Here for simplification reason, we specify the data size for + // "a series of write" to 1 sector (256 words) if data size of one ATA command + // request is larger than 256 words. + // + Increment = 256; + WordCount = 0; + + while (WordCount < ByteCount / 2) { + + // + // DRQReady2-- read Alternate Status Register to determine the DRQ bit + // data transfer can be performed only when DRQ is ready. + // + Status = DRQReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = CheckErrorStatus (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Check the remaining byte count is less than 512 bytes + // + if ((WordCount + Increment) > ByteCount / 2) { + Increment = ByteCount / 2 - WordCount; + } + // + // perform a series of write without check DRQ ready + // + + IDEWritePortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + Increment, + Buffer16 + ); + WordCount += Increment; + Buffer16 += Increment; + + } + + DRQClear (IdeDev, ATATIMEOUT); + + return CheckErrorStatus (IdeDev); +} + +EFI_STATUS +CheckErrorStatus ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + CheckErrorStatus + + + Purpose: + This function is used to analyze the Status Register and print out + some debug information and if there is ERR bit set in the Status + Register, the Error Register's value is also be parsed and print out. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + Returns: + EFI_SUCCESS + No err information in the Status Register. + + EFI_DEVICE_ERROR + Any err information in the Status Register. + + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +{ + UINT8 StatusRegister; + +//#ifdef EFI_DEBUG + + UINT8 ErrorRegister; + +//#endif + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + DEBUG_CODE ( + + if (StatusRegister & DWF) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Write Fault\n", + StatusRegister) + ); + } + + if (StatusRegister & CORR) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Corrected Data\n", + StatusRegister) + ); + } + + if (StatusRegister & ERR) { + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + + if (ErrorRegister & BBK_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Bad Block Detected\n", + ErrorRegister) + ); + } + + if (ErrorRegister & UNC_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Uncorrectable Data\n", + ErrorRegister) + ); + } + + if (ErrorRegister & MC_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Media Change\n", + ErrorRegister) + ); + } + + if (ErrorRegister & ABRT_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Abort\n", + ErrorRegister) + ); + } + + if (ErrorRegister & TK0NF_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Track 0 Not Found\n", + ErrorRegister) + ); + } + + if (ErrorRegister & AMNF_ERR) { + DEBUG ( + (EFI_D_BLKIO, + "CheckErrorStatus()-- %02x : Error : Address Mark Not Found\n", + ErrorRegister) + ); + } + + } + ); + + if ((StatusRegister & (ERR | DWF | CORR)) == 0) { + return EFI_SUCCESS; + } + + return EFI_DEVICE_ERROR; + +} + +EFI_STATUS +AtaReadSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +/*++ + Name: + AtaReadSectors + + + Purpose: + This function is called by the AtaBlkIoReadBlocks() to perform + reading from media in block unit. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *DataBuffer + A pointer to the destination buffer for the data. + + EFI_LBA IN Lba + The starting logical block address to read from + on the device media. + + UINTN IN NumberOfBlocks + The number of transfer data blocks. + + Returns: + return status is fully dependent on the return status + of AtaPioDataIn() function. + + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: DataBuffer - add argument and description to function comment +// TODO: Lba - add argument and description to function comment +// TODO: NumberOfBlocks - add argument and description to function comment +{ + EFI_STATUS Status; + UINTN BlocksRemaining; + UINT32 Lba32; + UINT8 Lba0; + UINT8 Lba1; + UINT8 Lba2; + UINT8 Lba3; + UINT8 AtaCommand; + UINT8 SectorCount8; + UINT16 SectorCount; + UINTN ByteCount; + VOID *Buffer; + + Buffer = DataBuffer; + + // + // Using ATA Read Sector(s) command (opcode=0x20) with PIO DATA IN protocol + // + AtaCommand = READ_SECTORS_CMD; + + + BlocksRemaining = NumberOfBlocks; + + Lba32 = (UINT32) Lba; + + Status = EFI_SUCCESS; + + while (BlocksRemaining > 0) { + + // + // in ATA-3 spec, LBA is in 28 bit width + // + Lba0 = (UINT8) Lba32; + Lba1 = (UINT8) (Lba32 >> 8); + Lba2 = (UINT8) (Lba32 >> 16); + // + // low 4 bit of Lba3 stands for LBA bit24~bit27. + // + Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f); + + if (BlocksRemaining >= 0x100) { + + // + // SectorCount8 is sent to Sector Count register, 0x00 means 256 + // sectors to be read + // + SectorCount8 = 0x00; + // + // SectorCount is used to record the number of sectors to be read + // + SectorCount = 256; + } else { + + SectorCount8 = (UINT8) BlocksRemaining; + SectorCount = (UINT16) BlocksRemaining; + } + + // + // ByteCount is the number of bytes that will be read + // + ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); + + // + // call AtaPioDataIn() to send Read Sector Command and receive data read + // + Status = AtaPioDataIn ( + IdeDev, + Buffer, + (UINT32) ByteCount, + AtaCommand, + Lba3, + SectorCount8, + Lba0, + Lba1, + Lba2 + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba32 += SectorCount; + Buffer = ((UINT8 *) Buffer + ByteCount); + BlocksRemaining -= SectorCount; + } + + return Status; +} + +EFI_STATUS +AtaWriteSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *BufferData, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +/*++ + Name: + AtaWriteSectors + + + Purpose: + This function is called by the AtaBlkIoWriteBlocks() to perform + writing onto media in block unit. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure,used + to record all the information of the IDE device. + + VOID IN *BufferData + A pointer to the source buffer for the data. + + EFI_LBA IN Lba + The starting logical block address to write onto + the device media. + + UINTN IN NumberOfBlocks + The number of transfer data blocks. + + + Returns: + return status is fully dependent on the return status + of AtaPioDataOut() function. + + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: BufferData - add argument and description to function comment +// TODO: Lba - add argument and description to function comment +// TODO: NumberOfBlocks - add argument and description to function comment +{ + EFI_STATUS Status; + UINTN BlocksRemaining; + UINT32 Lba32; + UINT8 Lba0; + UINT8 Lba1; + UINT8 Lba2; + UINT8 Lba3; + UINT8 AtaCommand; + UINT8 SectorCount8; + UINT16 SectorCount; + UINTN ByteCount; + VOID *Buffer; + + Buffer = BufferData; + + // + // Using Write Sector(s) command (opcode=0x30) with PIO DATA OUT protocol + // + AtaCommand = WRITE_SECTORS_CMD; + + BlocksRemaining = NumberOfBlocks; + + Lba32 = (UINT32) Lba; + + Status = EFI_SUCCESS; + + while (BlocksRemaining > 0) { + + Lba0 = (UINT8) Lba32; + Lba1 = (UINT8) (Lba32 >> 8); + Lba2 = (UINT8) (Lba32 >> 16); + Lba3 = (UINT8) ((Lba32 >> 24) & 0x0f); + + if (BlocksRemaining >= 0x100) { + + // + // SectorCount8 is sent to Sector Count register, 0x00 means 256 sectors + // to be written + // + SectorCount8 = 0x00; + // + // SectorCount is used to record the number of sectors to be written + // + SectorCount = 256; + } else { + + SectorCount8 = (UINT8) BlocksRemaining; + SectorCount = (UINT16) BlocksRemaining; + } + + ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); + + Status = AtaPioDataOut ( + IdeDev, + Buffer, + (UINT32) ByteCount, + AtaCommand, + Lba3, + SectorCount8, + Lba0, + Lba1, + Lba2 + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba32 += SectorCount; + Buffer = ((UINT8 *) Buffer + ByteCount); + BlocksRemaining -= SectorCount; + } + + return Status; +} + +EFI_STATUS +AtaSoftReset ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + AtaSoftReset + + Purpose: + This function is used to implement the Soft Reset on the specified + device. But, the ATA Soft Reset mechanism is so strong a reset method + that it will force resetting on both devices connected to the + same cable. + It is called by IdeBlkIoReset(), a interface function of Block + I/O protocol. + This function can also be used by the ATAPI device to perform reset when + ATAPI Reset command is failed. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + Returns: + EFI_SUCCESS + Soft reset completes successfully. + + EFI_DEVICE_ERROR + Any step during the reset process is failed. + Notes: + The registers initial values after ATA soft reset are different + to the ATA device and ATAPI device. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +{ + + UINT8 DeviceControl; + + DeviceControl = 0; + // + // set SRST bit to initiate soft reset + // + DeviceControl |= SRST; + + // + // disable Interrupt + // + DeviceControl |= bit1; + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + gBS->Stall (10); + + // + // Enable interrupt to support UDMA, and clear SRST bit + // + DeviceControl = 0; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + // + // slave device needs at most 31s to clear BSY + // + if (WaitForBSYClear (IdeDev, 31000) == EFI_TIMEOUT) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AtaBlkIoReadBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + Name: + AtaBlkIoReadBlocks + + + Purpose: + This function is the ATA implementation for ReadBlocks in the + Block I/O Protocol interface. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeBlkIoDevice + Indicates the calling context. + + UINT32 IN MediaId + The media id that the read request is for. + + EFI_LBA IN LBA + The starting logical block address to read from + on the device. + + UINTN IN BufferSize + The size of the Buffer in bytes. This must be a + multiple of the intrinsic block size of the device. + + VOID OUT *Buffer + A pointer to the destination buffer for the data. + The caller is responsible for either having implicit + or explicit ownership of the memory that data is read into. + + Returns: + EFI_SUCCESS + Read Blocks successfully. + + EFI_DEVICE_ERROR + Read Blocks failed. + + EFI_NO_MEDIA + There is no media in the device. + + EFI_MEDIA_CHANGE + The MediaId is not for the current media. + + EFI_BAD_BUFFER_SIZE + The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + + EFI_INVALID_PARAMETER + The read request contains LBAs that are not valid, + or the data buffer is not valid. + + Notes: + If Read Block error because of device error, this function will call + AtaSoftReset() function to reset device. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeBlkIoDevice - add argument and description to function comment +// TODO: MediaId - add argument and description to function comment +// TODO: LBA - add argument and description to function comment +// TODO: BufferSize - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: EFI_MEDIA_CHANGED - add return value to function comment +{ + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + EFI_STATUS Status; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + Status = EFI_SUCCESS; + + // + // Get the intrinsic block size + // + Media = IdeBlkIoDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + + NumberOfBlocks = BufferSize / BlockSize; + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (!(Media->MediaPresent)) { + return EFI_NO_MEDIA; + } + + if (LBA > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { + // + // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 read block mechanism + // + Status = AtaUdmaReadExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + if (EFI_ERROR (Status)) { + Status = AtaReadSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + } + } else { + // + // For ATA-3 compatible device, use ATA-3 read block mechanism + // Notice DMA operation can only handle 32bit address + // + if ((UINTN) Buffer <= 0xFFFFFFFF) { + Status = AtaUdmaRead (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + } + + if (EFI_ERROR (Status) || ((UINTN) Buffer > 0xFFFFFFFF)) { + Status = AtaReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + } + } + + if (EFI_ERROR (Status)) { + AtaSoftReset (IdeBlkIoDevice); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +AtaBlkIoWriteBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + Name: + AtaBlkIoWriteBlocks + + + Purpose: + This function is the ATA implementation for WriteBlocks in the + Block I/O Protocol interface. + + Parameters: + IDE_BLK_IO_DEV IN *IdeBlkIoDevice + Indicates the calling context. + + UINT32 IN MediaId + The media id that the write request is for. + + EFI_LBA IN LBA + The starting logical block address to write onto + the device. + + UINTN IN BufferSize + The size of the Buffer in bytes. This must be a + multiple of the intrinsic block size of the device. + + VOID OUT *Buffer + A pointer to the source buffer for the data. + The caller is responsible for either having implicit + or explicit ownership of the memory that data is + written from. + + + Returns: + EFI_SUCCESS + Write Blocks successfully. + + EFI_DEVICE_ERROR + Write Blocks failed. + + EFI_NO_MEDIA + There is no media in the device. + + EFI_MEDIA_CHANGE + The MediaId is not for the current media. + + EFI_BAD_BUFFER_SIZE + The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + + EFI_INVALID_PARAMETER + The write request contains LBAs that are not valid, + or the data buffer is not valid. + + Notes: + If Write Block error because of device error, this function will call + AtaSoftReset() function to reset device. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeBlkIoDevice - add argument and description to function comment +// TODO: MediaId - add argument and description to function comment +// TODO: LBA - add argument and description to function comment +// TODO: BufferSize - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: EFI_MEDIA_CHANGED - add return value to function comment +{ + + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + EFI_STATUS Status; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + Status = EFI_SUCCESS; + + // + // Get the intrinsic block size + // + Media = IdeBlkIoDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + NumberOfBlocks = BufferSize / BlockSize; + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (LBA > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + if (IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { + // + // For ATA/ATAPI-6 device(capcity > 120GB), use ATA-6 write block mechanism + // + Status = AtaUdmaWriteExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + if (EFI_ERROR (Status)) { + Status = AtaWriteSectorsExt (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + } + } else { + // + // For ATA-3 compatible device, use ATA-3 write block mechanism + // + Status = AtaUdmaWrite (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + if (EFI_ERROR (Status) || ((UINTN) Buffer > 0xFFFFFFFF)) { + Status = AtaWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + } + } + + if (EFI_ERROR (Status)) { + AtaSoftReset (IdeBlkIoDevice); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AtaReadSectorsExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + Name: + + AtaReadSectorsExt + + Purpose: + + This function is called by the AtaBlkIoReadBlocks() to perform + reading from media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + Parameters: + + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *DataBuffer + A pointer to the destination buffer for the data. + + EFI_LBA IN StartLba + The starting logical block address to read from + on the device media. + + UINTN IN NumberOfBlocks + The number of transfer data blocks. + + Returns: + + return status is fully dependent on the return status + of AtaPioDataInExt() function. + + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: DataBuffer - add argument and description to function comment +// TODO: StartLba - add argument and description to function comment +// TODO: NumberOfBlocks - add argument and description to function comment +{ + EFI_STATUS Status; + UINTN BlocksRemaining; + EFI_LBA Lba64; + UINT8 AtaCommand; + UINT16 SectorCount; + UINT32 ByteCount; + VOID *Buffer; + + // + // Using ATA "Read Sectors Ext" command(opcode=0x24) with PIO DATA IN protocol + // + AtaCommand = READ_SECTORS_EXT_CMD; + Buffer = DataBuffer; + BlocksRemaining = NumberOfBlocks; + Lba64 = StartLba; + Status = EFI_SUCCESS; + + while (BlocksRemaining > 0) { + + if (BlocksRemaining >= 0x10000) { + // + // SectorCount is used to record the number of sectors to be read + // Max 65536 sectors can be transfered at a time. + // + SectorCount = 0xffff; + } else { + SectorCount = (UINT16) BlocksRemaining; + } + + // + // ByteCount is the number of bytes that will be read + // + ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); + + // + // call AtaPioDataInExt() to send Read Sector Command and receive data read + // + Status = AtaPioDataInExt ( + IdeDev, + Buffer, + ByteCount, + AtaCommand, + Lba64, + SectorCount + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba64 += SectorCount; + Buffer = ((UINT8 *) Buffer + ByteCount); + BlocksRemaining -= SectorCount; + } + + return Status; +} + +EFI_STATUS +AtaWriteSectorsExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + Name: + + AtaWriteSectorsExt + + Purpose: + + This function is called by the AtaBlkIoWriteBlocks() to perform + writing onto media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + Parameters: + + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure,used + to record all the information of the IDE device. + + VOID IN *DataBuffer + A pointer to the source buffer for the data. + + EFI_LBA IN Lba + The starting logical block address to write onto + the device media. + + UINTN IN NumberOfBlocks + The number of transfer data blocks. + + Returns: + + return status is fully dependent on the return status + of AtaPioDataOutExt() function. + + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: DataBuffer - add argument and description to function comment +// TODO: StartLba - add argument and description to function comment +// TODO: NumberOfBlocks - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_LBA Lba64; + UINTN BlocksRemaining; + UINT8 AtaCommand; + UINT16 SectorCount; + UINT32 ByteCount; + VOID *Buffer; + + // + // Using ATA "Write Sectors Ext" cmd(opcode=0x24) with PIO DATA OUT protocol + // + AtaCommand = WRITE_SECTORS_EXT_CMD; + Lba64 = StartLba; + Buffer = DataBuffer; + BlocksRemaining = NumberOfBlocks; + + Status = EFI_SUCCESS; + + while (BlocksRemaining > 0) { + + if (BlocksRemaining >= 0x10000) { + // + // SectorCount is used to record the number of sectors to be written. + // Max 65536 sectors can be transfered at a time. + // + SectorCount = 0xffff; + } else { + SectorCount = (UINT16) BlocksRemaining; + } + + // + // ByteCount is the number of bytes that will be written + // + ByteCount = SectorCount * (IdeDev->BlkIo.Media->BlockSize); + + // + // Call AtaPioDataOutExt() to send "Write Sectors Ext" Command + // + Status = AtaPioDataOutExt ( + IdeDev, + Buffer, + ByteCount, + AtaCommand, + Lba64, + SectorCount + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba64 += SectorCount; + Buffer = ((UINT8 *) Buffer + ByteCount); + BlocksRemaining -= SectorCount; + } + + return Status; +} + +EFI_STATUS +AtaPioDataInExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN OUT VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN EFI_LBA StartLba, + IN UINT16 SectorCount + ) +/*++ + Name: + + AtaPioDataInExt + + Purpose: + + This function is used to send out ATA commands conforms to the + PIO Data In Protocol, supporting ATA/ATAPI-6 standard + + Comparing with ATA-3 data in protocol, we have two differents here: + 1. Do NOT wait for DRQ clear before sending command into IDE device.(the + wait will frequently fail... cause writing function return error) + + 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly + slow down writing performance by 100 times!) + + + Parameters: + + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN OUT *Buffer + buffer contained data transferred from device to host. + + UINT32 IN ByteCount + data size in byte unit of the buffer. + + UINT8 IN AtaCommand + value of the Command Register + + EFI_LBA IN StartLba + the start LBA of this transaction + + UINT16 IN SectorCount + the count of sectors to be transfered + + Returns: + + EFI_SUCCESS + send out the ATA command and device send required + data successfully. + + EFI_DEVICE_ERROR + command sent failed. + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: ByteCount - add argument and description to function comment +// TODO: AtaCommand - add argument and description to function comment +// TODO: StartLba - add argument and description to function comment +// TODO: SectorCount - add argument and description to function comment +{ + UINT8 DevSel; + UINT8 SectorCount8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; + UINTN WordCount; + UINTN Increment; + UINT16 *Buffer16; + EFI_STATUS Status; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device, set bit6 as 1 to indicate LBA mode is used + // + DevSel = (UINT8) (IdeDev->Device << 4); + DevSel |= 0x40; + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + DevSel + ); + + // + // Wait for DRDY singnal asserting. ATAPI device needn't wait + // + if ( (IdeDev->Type == IdeHardDisk) || + (IdeDev->Type == Ide48bitAddressingHardDisk)) { + + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + } + + // + // Fill feature register if needed + // + if (AtaCommand == SET_FEATURES_CMD) { + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); + } + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (StartLba, 24); + LbaMid = (UINT8) RShiftU64 (StartLba, 32); + LbaHigh = (UINT8) RShiftU64 (StartLba, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + LbaLow = (UINT8) StartLba; + LbaMid = (UINT8) RShiftU64 (StartLba, 8); + LbaHigh = (UINT8) RShiftU64 (StartLba, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Send command via Command Register, invoking the processing of this command + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + Buffer16 = (UINT16 *) Buffer; + + // + // According to PIO data in protocol, host can perform a series of reads to + // the data register after each time device set DRQ ready; + // + + // + // 256 words + // + Increment = 256; + + // + // used to record bytes of currently transfered data + // + WordCount = 0; + + while (WordCount < ByteCount / 2) { + // + // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. + // + Status = DRQReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = CheckErrorStatus (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Get the byte count for one series of read + // + if ((WordCount + Increment) > ByteCount / 2) { + Increment = ByteCount / 2 - WordCount; + } + + IDEReadPortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + Increment, + Buffer16 + ); + + WordCount += Increment; + Buffer16 += Increment; + + } + + return CheckErrorStatus (IdeDev); +} + +EFI_STATUS +AtaPioDataOutExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN EFI_LBA StartLba, + IN UINT16 SectorCount + ) +/*++ + Name: + + AtaPioDataOutExt + + Purpose: + + This function is used to send out ATA commands conforms to the + PIO Data Out Protocol, supporting ATA/ATAPI-6 standard + + Comparing with ATA-3 data out protocol, we have two differents here: + 1. Do NOT wait for DRQ clear before sending command into IDE device.(the + wait will frequently fail... cause writing function return error) + + 2. Do NOT wait for DRQ clear after all data readed.(the wait greatly + slow down writing performance by 100 times!) + + Parameters: + + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *Buffer + buffer contained data transferred from host to device. + + UINT32 IN ByteCount + data size in byte unit of the buffer. + + UINT8 IN AtaCommand + value of the Command Register + + EFI_LBA IN StartLba + the start LBA of this transaction + + UINT16 IN SectorCount + the count of sectors to be transfered + + Returns: + + EFI_SUCCESS + send out the ATA command and device receive required + data successfully. + + EFI_DEVICE_ERROR + command sent failed. + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: ByteCount - add argument and description to function comment +// TODO: AtaCommand - add argument and description to function comment +// TODO: StartLba - add argument and description to function comment +// TODO: SectorCount - add argument and description to function comment +{ + UINT8 DevSel; + UINT8 SectorCount8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; + UINTN WordCount; + UINTN Increment; + UINT16 *Buffer16; + EFI_STATUS Status; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device. Set bit6 as 1 to indicate LBA mode is used + // + DevSel = (UINT8) (IdeDev->Device << 4); + DevSel |= 0x40; + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + DevSel + ); + + // + // Wait for DRDY singnal asserting. + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Fill feature register if needed + // + if (AtaCommand == SET_FEATURES_CMD) { + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x03); + } + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (StartLba, 24); + LbaMid = (UINT8) RShiftU64 (StartLba, 32); + LbaHigh = (UINT8) RShiftU64 (StartLba, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + LbaLow = (UINT8) StartLba; + LbaMid = (UINT8) RShiftU64 (StartLba, 8); + LbaHigh = (UINT8) RShiftU64 (StartLba, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Send command via Command Register, invoking the processing of this command + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + Buffer16 = (UINT16 *) Buffer; + + // + // According to PIO Data Out protocol, host can perform a series of writes to + // the data register after each time device set DRQ ready; + // + Increment = 256; + + // + // used to record bytes of currently transfered data + // + WordCount = 0; + + while (WordCount < ByteCount / 2) { + // + // Poll DRQ bit set, data transfer can be performed only when DRQ is ready. + // + Status = DRQReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = CheckErrorStatus (IdeDev); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Write data into device by one series of writing to data register + // + if ((WordCount + Increment) > ByteCount / 2) { + Increment = ByteCount / 2 - WordCount; + } + + IDEWritePortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + Increment, + Buffer16 + ); + + WordCount += Increment; + Buffer16 += Increment; + + } + // + // while + // + + return CheckErrorStatus (IdeDev); +} + + +VOID +AtaSMARTSupport ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + AtaSMARTSupport + + Purpose: + + Enable SMART of the disk if supported + + Parameters: + + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure,used + to record all the information of the IDE device. + + Returns: + + NONE +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +{ + EFI_STATUS Status; + BOOLEAN SMARTSupported; + UINT8 Device; + EFI_IDENTIFY_DATA *TmpAtaIdentifyPointer; + UINT8 DeviceSelect; + UINT8 LBAMid; + UINT8 LBAHigh; + + // + // Detect if the device supports S.M.A.R.T. + // + if ((IdeDev->pIdData->AtaData.command_set_supported_83 & 0xc000) != 0x4000) { + // + // Data in word 82 is not valid (bit15 shall be zero and bit14 shall be to one) + // + return ; + } else { + if ((IdeDev->pIdData->AtaData.command_set_supported_82 & 0x0001) != 0x0001) { + // + // S.M.A.R.T is not supported by the device + // + SMARTSupported = FALSE; + } else { + SMARTSupported = TRUE; + } + } + + if (!SMARTSupported) { + // + // Report nonsupport status code + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED) + ); + } else { + // + // Enable this feature + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_ENABLE) + ); + + Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); + Status = AtaNonDataCommandIn ( + IdeDev, + ATA_SMART_CMD, + Device, + ATA_SMART_ENABLE_OPERATION, + 0, + 0, + ATA_CONSTANT_4F, + ATA_CONSTANT_C2 + ); + // + // Detect if this feature is enabled + // + TmpAtaIdentifyPointer = (EFI_IDENTIFY_DATA *) AllocateZeroPool (sizeof (EFI_IDENTIFY_DATA)); + + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + Status = AtaPioDataIn ( + IdeDev, + (VOID *) TmpAtaIdentifyPointer, + sizeof (EFI_IDENTIFY_DATA), + IDENTIFY_DRIVE_CMD, + DeviceSelect, + 0, + 0, + 0, + 0 + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (TmpAtaIdentifyPointer); + return ; + } + + // + // Check if the feature is enabled + // + if ((TmpAtaIdentifyPointer->AtaData.command_set_feature_enb_85 & 0x0001) == 0x0001) { + // + // Read status data + // + AtaNonDataCommandIn ( + IdeDev, + ATA_SMART_CMD, + Device, + ATA_SMART_RETURN_STATUS, + 0, + 0, + ATA_CONSTANT_4F, + ATA_CONSTANT_C2 + ); + LBAMid = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb); + LBAHigh = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb); + + if ((LBAMid == 0x4f) && (LBAHigh == 0xc2)) { + // + // The threshold exceeded condition is not detected by the device + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD) + ); + + } else if ((LBAMid == 0xf4) && (LBAHigh == 0x2c)) { + // + // The threshold exceeded condition is detected by the device + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD) + ); + } + + } else { + // + // Report disabled status code + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_ATA_BUS_SMART_DISABLED) + ); + } + + gBS->FreePool (TmpAtaIdentifyPointer); + } + + return ; +} + +EFI_STATUS +AtaCommandIssueExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ) +/*++ + +Routine Description: + + Send ATA Ext command into device with NON_DATA protocol + +Arguments: + + IdeDev - Standard IDE device private data structure + AtaCommand - The ATA command to be sent + Device - The value in Device register + Feature - The value in Feature register + SectorCount - The value in SectorCount register + LbaAddress - The LBA address in 48-bit mode + +Returns: + + EFI_SUCCESS - Reading succeed + EFI_DEVICE_ERROR - Error executing commands on this device + +--*/ +{ + EFI_STATUS Status; + UINT8 SectorCount8; + UINT8 Feature8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + // + // Fill the feature register, which is a two-byte FIFO. Need write twice. + // + Feature8 = (UINT8) (Feature >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + Feature8 = (UINT8) Feature; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (LbaAddress, 24); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + LbaLow = (UINT8) LbaAddress; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + + LbaMid = (UINT8) RShiftU64 (LbaAddress, 32); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + LbaMid = (UINT8) RShiftU64 (LbaAddress, 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Work around for Segate 160G disk writing + // + gBS->Stall (1800); + + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + // + // Stall at least 400ns + // + gBS->Stall (100); + + return EFI_SUCCESS; +} + +EFI_STATUS +AtaCommandIssue ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ) +/*++ + +Routine Description: + + Send ATA Ext command into device with NON_DATA protocol + +Arguments: + + IdeDev - Standard IDE device private data structure + AtaCommand - The ATA command to be sent + Device - The value in Device register + Feature - The value in Feature register + SectorCount - The value in SectorCount register + LbaAddress - The LBA address in 48-bit mode + +Returns: + + EFI_SUCCESS - Reading succeed + EFI_DEVICE_ERROR - Error executing commands on this device + +--*/ +{ + EFI_STATUS Status; + UINT8 SectorCount8; + UINT8 Feature8; + UINT8 Lba0; + UINT8 Lba1; + UINT8 Lba2; + UINT8 Lba3; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Lba0 = (UINT8) LbaAddress; + Lba1 = (UINT8) RShiftU64 (LbaAddress, 8); + Lba2 = (UINT8) RShiftU64 (LbaAddress, 16); + Lba3 = (UINT8) RShiftU64 (LbaAddress, 24); + Device |= Lba3; + + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + // + // Fill the feature register, which is a two-byte FIFO. Need write twice. + // + Feature8 = (UINT8) Feature; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, Lba0); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, Lba1); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, Lba2); + + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + // + // Stall at least 400ns + // + gBS->Stall (100); + + return EFI_SUCCESS; +} + +EFI_STATUS +AtaUdmaReadExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + Name: + + AtaUdmaReadExt + + Purpose: + + This function is called by the AtaBlkIoReadBlocks() to perform + reading from media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + Parameters: + + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *DataBuffer + A pointer to the destination buffer for the data. + + EFI_LBA IN StartLba + The starting logical block address to read from + on the device media. + + UINTN IN NumberOfBlocks + The number of transfer data blocks. + + Returns: + + The device status of UDMA operation. If the operation is + successful, return EFI_SUCCESS. + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: DataBuffer - add argument and description to function comment +// TODO: StartLba - add argument and description to function comment +// TODO: NumberOfBlocks - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + IDE_DMA_PRD *PrdAddr; + IDE_DMA_PRD *UsedPrdAddr; + IDE_DMA_PRD *TempPrdAddr; + UINT8 RegisterValue; + UINT8 Device; + UINT64 IoPortForBmic; + UINT64 IoPortForBmis; + UINT64 IoPortForBmid; + EFI_STATUS Status; + UINTN PrdTableNum; + UINTN ByteCount; + UINTN ByteAvailable; + UINT8 *PrdBuffer; + UINTN RemainBlockNum; + UINT8 DeviceControl; + + // + // Channel and device differential. Select device. + // + Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); + + // + // Enable interrupt to support UDMA and Select device + // + DeviceControl = 0; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + if (IdePrimary == IdeDev->Channel) { + IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET; + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; + IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET; + } else { + if (IdeSecondary == IdeDev->Channel) { + IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET; + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; + IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET; + } else { + return EFI_UNSUPPORTED; + } + } + + RemainBlockNum = NumberOfBlocks; + while (RemainBlockNum > 0) { + + if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) { + // + // SectorCount is used to record the number of sectors to be read + // Max 65536 sectors can be transfered at a time. + // + NumberOfBlocks = MAX_DMA_EXT_COMMAND_SECTORS; + RemainBlockNum -= MAX_DMA_EXT_COMMAND_SECTORS; + } else { + NumberOfBlocks = (UINT16) RemainBlockNum; + RemainBlockNum = 0; + } + + // + // Calculate the number of PRD table to make sure the memory region + // not cross 64K boundary + // + ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + PrdTableNum = ((ByteCount >> 16) + 1) + 1; + + // + // Build PRD table + // + PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD))); + + // + // To make sure PRD is allocated in one 64K page + // + if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) { + UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000); + } else { + if ((UINTN) PrdAddr & 0x03) { + UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC); + } else { + UsedPrdAddr = PrdAddr; + } + } + + // + // Build the PRD table + // + PrdBuffer = DataBuffer; + TempPrdAddr = UsedPrdAddr; + while (TRUE) { + + ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF); + + if (ByteCount <= ByteAvailable) { + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteCount; + TempPrdAddr->EndOfTable = 0x8000; + break; + } + + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteAvailable; + + ByteCount -= ByteAvailable; + PrdBuffer += ByteAvailable; + TempPrdAddr++; + } + + // + // Set the base address to BMID register + // + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmid, + 1, + &UsedPrdAddr + ); + + // + // Set BMIC register to identify the operation direction + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue |= BMIC_nREAD; + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + // + // Read BMIS register and clear ERROR and INTR bit + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + RegisterValue |= BMIS_INTERRUPT | BMIS_ERROR; + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + // + // Issue READ DMA EXT command + // + Status = AtaCommandIssueExt ( + IdeDev, + READ_DMA_EXT_CMD, + Device, + 0, + (UINT16) NumberOfBlocks, + StartLba + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (PrdAddr); + return EFI_DEVICE_ERROR; + } + + // + // Set START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue |= BMIC_START; + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + // + // Check the INTERRUPT and ERROR bit of BMIS + // + while (TRUE) { + + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) { + if (RegisterValue & BMIS_ERROR) { + gBS->FreePool (PrdAddr); + return EFI_DEVICE_ERROR; + } + break; + } + + gBS->Stall (1000); + } + + gBS->FreePool (PrdAddr); + + // + // Set START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue &= ~((UINT8) BMIC_START); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + if (RegisterValue & BMIS_ERROR) { + return EFI_DEVICE_ERROR; + } + + DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + StartLba += NumberOfBlocks; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AtaUdmaRead ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + Name: + + AtaUdmaRead + + Purpose: + + This function is called by the AtaBlkIoReadBlocks() to perform + reading from media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + Parameters: + + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *DataBuffer + A pointer to the destination buffer for the data. + + EFI_LBA IN StartLba + The starting logical block address to read from + on the device media. + + UINTN IN NumberOfBlocks + The number of transfer data blocks. + + Returns: + + The device status of UDMA operation. If the operation is + successful, return EFI_SUCCESS. + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: DataBuffer - add argument and description to function comment +// TODO: StartLba - add argument and description to function comment +// TODO: NumberOfBlocks - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + IDE_DMA_PRD *PrdAddr; + IDE_DMA_PRD *UsedPrdAddr; + IDE_DMA_PRD *TempPrdAddr; + UINT8 RegisterValue; + UINT8 Device; + UINT64 IoPortForBmic; + UINT64 IoPortForBmis; + UINT64 IoPortForBmid; + EFI_STATUS Status; + UINTN PrdTableNum; + UINTN ByteCount; + UINTN ByteAvailable; + UINT8 *PrdBuffer; + UINTN RemainBlockNum; + UINT8 DeviceControl; + + // + // Channel and device differential + // + Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); + + // + // Enable interrupt to support UDMA and Select device + // + DeviceControl = 0; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + if (IdePrimary == IdeDev->Channel) { + IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET; + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; + IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET; + } else { + if (IdeSecondary == IdeDev->Channel) { + IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET; + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; + IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET; + } else { + return EFI_UNSUPPORTED; + } + } + + RemainBlockNum = NumberOfBlocks; + while (RemainBlockNum > 0) { + + if (RemainBlockNum >= MAX_DMA_COMMAND_SECTORS) { + // + // SectorCount is used to record the number of sectors to be read + // Max 256 sectors can be transfered at a time. + // + NumberOfBlocks = MAX_DMA_COMMAND_SECTORS; + RemainBlockNum -= MAX_DMA_COMMAND_SECTORS; + } else { + NumberOfBlocks = (UINT16) RemainBlockNum; + RemainBlockNum = 0; + } + + // + // Calculate the number of PRD table to make sure the memory region + // not cross 64K boundary + // + ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + PrdTableNum = ((ByteCount >> 16) + 1) + 1; + + // + // Build PRD table + // + PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD))); + // + // To make sure PRD is allocated in one 64K page + // + if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) { + UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000); + } else { + if ((UINTN) PrdAddr & 0x03) { + UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC); + } else { + UsedPrdAddr = PrdAddr; + } + } + + // + // Build the PRD table + // + PrdBuffer = DataBuffer; + TempPrdAddr = UsedPrdAddr; + while (TRUE) { + + ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF); + + if (ByteCount <= ByteAvailable) { + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteCount; + TempPrdAddr->EndOfTable = 0x8000; + break; + } + + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteAvailable; + + ByteCount -= ByteAvailable; + PrdBuffer += ByteAvailable; + TempPrdAddr++; + } + + // + // Set the base address to BMID register + // + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmid, + 1, + &UsedPrdAddr + ); + + // + // Set BMIC register to identify the operation direction + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue |= BMIC_nREAD; + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + // + // Read BMIS register and clear ERROR and INTR bit + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + // + // Issue READ DMA command + // + Status = AtaCommandIssue ( + IdeDev, + READ_DMA_CMD, + Device, + 0, + (UINT16) NumberOfBlocks, + StartLba + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (PrdAddr); + return EFI_DEVICE_ERROR; + } + + // + // Set START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue |= BMIC_START; + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + // + // Check the INTERRUPT and ERROR bit of BMIS + // + while (TRUE) { + + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) { + if (RegisterValue & BMIS_ERROR) { + gBS->FreePool (PrdAddr); + return EFI_DEVICE_ERROR; + } + break; + } + + gBS->Stall (1000); + } + + gBS->FreePool (PrdAddr); + + // + // Set START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue &= ~((UINT8) BMIC_START); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + if (RegisterValue & BMIS_ERROR) { + return EFI_DEVICE_ERROR; + } + + DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + StartLba += NumberOfBlocks; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AtaUdmaWriteExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + Name: + + AtaUdmaWriteExt + + Purpose: + + This function is called by the AtaBlkIoWriteBlocks() to perform + writing to media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + Parameters: + + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *DataBuffer + A pointer to the source buffer for the data. + + EFI_LBA IN StartLba + The starting logical block address to write to + on the device media. + + UINTN IN NumberOfBlocks + The number of transfer data blocks. + + Returns: + + The device status of UDMA operation. If the operation is + successful, return EFI_SUCCESS. + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: DataBuffer - add argument and description to function comment +// TODO: StartLba - add argument and description to function comment +// TODO: NumberOfBlocks - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + IDE_DMA_PRD *PrdAddr; + IDE_DMA_PRD *UsedPrdAddr; + IDE_DMA_PRD *TempPrdAddr; + UINT8 RegisterValue; + UINT8 Device; + UINT64 IoPortForBmic; + UINT64 IoPortForBmis; + UINT64 IoPortForBmid; + EFI_STATUS Status; + UINTN PrdTableNum; + UINTN ByteCount; + UINTN ByteAvailable; + UINT8 *PrdBuffer; + UINTN RemainBlockNum; + UINT8 DeviceControl; + + // + // Channel and device differential + // + Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); + + // + // Enable interrupt to support UDMA and Select device + // + DeviceControl = 0; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + if (IdePrimary == IdeDev->Channel) { + IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET; + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; + IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET; + } else { + if (IdeSecondary == IdeDev->Channel) { + IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET; + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; + IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET; + } else { + return EFI_UNSUPPORTED; + } + } + + RemainBlockNum = NumberOfBlocks; + while (RemainBlockNum > 0) { + + if (RemainBlockNum >= MAX_DMA_EXT_COMMAND_SECTORS) { + // + // SectorCount is used to record the number of sectors to be read + // Max 65536 sectors can be transfered at a time. + // + NumberOfBlocks = MAX_DMA_EXT_COMMAND_SECTORS; + RemainBlockNum -= MAX_DMA_EXT_COMMAND_SECTORS; + } else { + NumberOfBlocks = (UINT16) RemainBlockNum; + RemainBlockNum = 0; + } + + // + // Calculate the number of PRD table to make sure the memory region + // not cross 64K boundary + // + ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + PrdTableNum = ((ByteCount >> 16) + 1) + 1; + + // + // Build PRD table + // + PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD))); + // + // To make sure PRD is allocated in one 64K page + // + if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) { + UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000); + } else { + if ((UINTN) PrdAddr & 0x03) { + UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC); + } else { + UsedPrdAddr = PrdAddr; + } + } + + // + // Build the PRD table + // + PrdBuffer = DataBuffer; + TempPrdAddr = UsedPrdAddr; + while (TRUE) { + + ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF); + + if (ByteCount <= ByteAvailable) { + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteCount; + TempPrdAddr->EndOfTable = 0x8000; + break; + } + + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteAvailable; + + ByteCount -= ByteAvailable; + PrdBuffer += ByteAvailable; + TempPrdAddr++; + } + + // + // Set the base address to BMID register + // + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmid, + 1, + &UsedPrdAddr + ); + + // + // Set BMIC register to identify the operation direction + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + // + // 0000 1000 + // + RegisterValue &= ~((UINT8) BMIC_nREAD); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + // + // Read BMIS register and clear ERROR and INTR bit + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + // + // Issue WRITE DMA EXT command + // + Status = AtaCommandIssueExt ( + IdeDev, + WRITE_DMA_EXT_CMD, + Device, + 0, + (UINT16) NumberOfBlocks, + StartLba + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (PrdAddr); + return EFI_DEVICE_ERROR; + } + + // + // Set START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue |= BMIC_START; + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + // + // Check the INTERRUPT and ERROR bit of BMIS + // + while (TRUE) { + + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) { + if (RegisterValue & BMIS_ERROR) { + gBS->FreePool (PrdAddr); + return EFI_DEVICE_ERROR; + } + break; + } + + gBS->Stall (1000); + } + + gBS->FreePool (PrdAddr); + + // + // Set START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue &= ~((UINT8) BMIC_START); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + StartLba += NumberOfBlocks; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AtaUdmaWrite ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + Name: + + AtaUdmaWrite + + Purpose: + + This function is called by the AtaBlkIoWriteBlocks() to perform + writing to media in block unit. The function has been enhanced to + support >120GB access and transfer at most 65536 blocks per command + + Parameters: + + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *DataBuffer + A pointer to the source buffer for the data. + + EFI_LBA IN StartLba + The starting logical block address to write to + on the device media. + + UINTN IN NumberOfBlocks + The number of transfer data blocks. + + Returns: + + The device status of UDMA operation. If the operation is + successful, return EFI_SUCCESS. + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: DataBuffer - add argument and description to function comment +// TODO: StartLba - add argument and description to function comment +// TODO: NumberOfBlocks - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + IDE_DMA_PRD *PrdAddr; + IDE_DMA_PRD *UsedPrdAddr; + IDE_DMA_PRD *TempPrdAddr; + UINT8 RegisterValue; + UINT8 Device; + UINT64 IoPortForBmic; + UINT64 IoPortForBmis; + UINT64 IoPortForBmid; + EFI_STATUS Status; + UINTN PrdTableNum; + UINTN ByteCount; + UINTN ByteAvailable; + UINT8 *PrdBuffer; + UINTN RemainBlockNum; + UINT8 DeviceControl; + + // + // Channel and device differential + // + Device = (UINT8) ((IdeDev->Device << 4) | 0xe0); + + // + // Enable interrupt to support UDMA + // + DeviceControl = 0; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + if (IdePrimary == IdeDev->Channel) { + IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICP_OFFSET; + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISP_OFFSET; + IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDP_OFFSET; + } else { + if (IdeSecondary == IdeDev->Channel) { + IoPortForBmic = IdeDev->IoPort->BusMasterBaseAddr + BMICS_OFFSET; + IoPortForBmis = IdeDev->IoPort->BusMasterBaseAddr + BMISS_OFFSET; + IoPortForBmid = IdeDev->IoPort->BusMasterBaseAddr + BMIDS_OFFSET; + } else { + return EFI_UNSUPPORTED; + } + } + + RemainBlockNum = NumberOfBlocks; + while (RemainBlockNum > 0) { + + if (RemainBlockNum >= MAX_DMA_COMMAND_SECTORS) { + // + // SectorCount is used to record the number of sectors to be read + // Max 256 sectors can be transfered at a time. + // + NumberOfBlocks = MAX_DMA_COMMAND_SECTORS; + RemainBlockNum -= MAX_DMA_COMMAND_SECTORS; + } else { + NumberOfBlocks = (UINT16) RemainBlockNum; + RemainBlockNum = 0; + } + + // + // Calculate the number of PRD table to make sure the memory region + // not cross 64K boundary + // + ByteCount = NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + PrdTableNum = ((ByteCount >> 16) + 1) + 1; + + // + // Build PRD table + // + PrdAddr = (IDE_DMA_PRD *) AllocateZeroPool ((2 * PrdTableNum * sizeof (IDE_DMA_PRD))); + + // + // To make sure PRD is allocated in one 64K page + // + if (((UINTN) PrdAddr & 0x0FFFF) > (((UINTN) PrdAddr + PrdTableNum * sizeof (IDE_DMA_PRD) - 1) & 0x0FFFF)) { + UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x10000) & 0xFFFF0000); + } else { + if ((UINTN) PrdAddr & 0x03) { + UsedPrdAddr = (IDE_DMA_PRD *) ((UINTN) ((UINT8 *) PrdAddr + 0x04) & 0xFFFFFFFC); + } else { + UsedPrdAddr = PrdAddr; + } + } + + // + // Build the PRD table + // + PrdBuffer = DataBuffer; + TempPrdAddr = UsedPrdAddr; + while (TRUE) { + + ByteAvailable = 0x10000 - ((UINTN) PrdBuffer & 0xFFFF); + + if (ByteCount <= ByteAvailable) { + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteCount; + TempPrdAddr->EndOfTable = 0x8000; + break; + } + + TempPrdAddr->RegionBaseAddr = (UINT32) ((UINTN) PrdBuffer); + TempPrdAddr->ByteCount = (UINT16) ByteAvailable; + + ByteCount -= ByteAvailable; + PrdBuffer += ByteAvailable; + TempPrdAddr++; + } + + // + // Set the base address to BMID register + // + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint32, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmid, + 1, + &UsedPrdAddr + ); + + // + // Set BMIC register to identify the operation direction + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + // + // 0000 1000 + // + RegisterValue &= ~((UINT8) BMIC_nREAD); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + // + // Read BMIS register and clear ERROR and INTR bit + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + RegisterValue |= (BMIS_INTERRUPT | BMIS_ERROR); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + + // + // Issue WRITE DMA command + // + Status = AtaCommandIssue ( + IdeDev, + WRITE_DMA_CMD, + Device, + 0, + (UINT16) NumberOfBlocks, + StartLba + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (PrdAddr); + return EFI_DEVICE_ERROR; + } + + // + // Set START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue |= BMIC_START; + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + // + // Check the INTERRUPT and ERROR bit of BMIS + // + while (TRUE) { + + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmis, + 1, + &RegisterValue + ); + if (RegisterValue & (BMIS_INTERRUPT | BMIS_ERROR)) { + if (RegisterValue & BMIS_ERROR) { + gBS->FreePool (PrdAddr); + return EFI_DEVICE_ERROR; + } + break; + } + + gBS->Stall (1000); + } + + gBS->FreePool (PrdAddr); + + // + // Set START bit of BMIC register + // + IdeDev->PciIo->Io.Read ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + RegisterValue &= ~((UINT8) BMIC_START); + + IdeDev->PciIo->Io.Write ( + IdeDev->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + IoPortForBmic, + 1, + &RegisterValue + ); + + DataBuffer = (UINT8 *) DataBuffer + NumberOfBlocks * IdeDev->BlkIo.Media->BlockSize; + StartLba += NumberOfBlocks; + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c new file mode 100644 index 0000000000..fa004e3d7f --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/atapi.c @@ -0,0 +1,2591 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + atapi.c + +Abstract: + + +Revision History +--*/ + +#include "idebus.h" + +STATIC +EFI_STATUS +LS120GetMediaStatus ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + LS120GetMediaStatus + + Purpose: + This function is used to get the current status of the media residing + in the LS-120 drive or ZIP drive. The media status is returned in the + Error Status. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + Returns: + EFI_SUCCESS + The media status is achieved successfully and the media + can be read/written. + + EFI_DEVICE_ERROR + Get Media Status Command is failed. + + EFI_NO_MEDIA + There is no media in the drive. + + EFI_WRITE_PROTECTED + The media is writing protected. + + Notes: + This function must be called after the LS120EnableMediaStatus() + with second parameter set to TRUE + (means enable media status notification) is called. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +{ + UINT8 DeviceSelect; + UINT8 StatusValue; + EFI_STATUS EfiStatus; + // + // Poll Alternate Register for BSY clear within timeout. + // + EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (EfiStatus)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device via Device/Head Register. + // + DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect); + + // + // Poll Alternate Register for DRDY set within timeout. + // After device is selected, DRDY set indicates the device is ready to + // accept command. + // + EfiStatus = DRDYReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (EfiStatus)) { + return EFI_DEVICE_ERROR; + } + + // + // Get Media Status Command is sent + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xDA); + + // + // BSY bit will clear after command is complete. + // + EfiStatus = WaitForBSYClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (EfiStatus)) { + return EFI_DEVICE_ERROR; + } + + // + // the media status is returned by the command in the ERROR register + // + StatusValue = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + + if (StatusValue & bit1) { + return EFI_NO_MEDIA; + } + + if (StatusValue & bit6) { + return EFI_WRITE_PROTECTED; + } else { + return EFI_SUCCESS; + } +} + +STATIC +EFI_STATUS +LS120EnableMediaStatus ( + IN IDE_BLK_IO_DEV *IdeDev, + IN BOOLEAN Enable + ) +/*++ + Name: + LS120EnableMediaStatus + + Purpose: + This function is used to send Enable Media Status Notification Command + or Disable Media Status Notification Command. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + BOOLEAN IN Enable + a flag that indicates whether enable or disable media + status notification. + + Returns: + EFI_SUCCESS + If command completes successfully. + + EFI_DEVICE_ERROR + If command failed. + + + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: Enable - add argument and description to function comment +{ + UINT8 DeviceSelect; + EFI_STATUS Status; + + // + // Poll Alternate Register for BSY clear within timeout. + // + Status = WaitForBSYClear2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device via Device/Head Register. + // + DeviceSelect = (UINT8) ((IdeDev->Device) << 4 | 0xe0); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect); + + // + // Poll Alternate Register for DRDY set within timeout. + // After device is selected, DRDY set indicates the device is ready to + // accept command. + // + Status = DRDYReady2 (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (Enable) { + // + // 0x95: Enable media status notification + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x95); + } else { + // + // 0x31: Disable media status notification + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x31); + } + // + // Set Feature Command is sent + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0xEF); + + // + // BSY bit will clear after command is complete. + // + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ATAPIIdentify ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + ATAPIIdentify + + + Purpose: + This function is called by DiscoverIdeDevice() during its device + identification. + + Its main purpose is to get enough information for the device media + to fill in the Media data structure of the Block I/O Protocol interface. + + There are 5 steps to reach such objective: + + 1. Sends out the ATAPI Identify Command to the specified device. + Only ATAPI device responses to this command. If the command succeeds, + it returns the Identify data structure which filled with information + about the device. Since the ATAPI device contains removable media, + the only meaningful information is the device module name. + + 2. Sends out ATAPI Inquiry Packet Command to the specified device. + This command will return inquiry data of the device, which contains + the device type information. + + 3. Allocate sense data space for future use. We don't detect the media + presence here to improvement boot performance, especially when CD + media is present. The media detection will be performed just before + each BLK_IO read/write + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + Returns: + EFI_SUCCESS + Identify ATAPI device successfully. + + EFI_DEVICE_ERROR + ATAPI Identify Device Command failed or device type + is not supported by this IDE driver. + + Notes: + Parameter "IdeDev" will be updated in this function. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +{ + EFI_IDENTIFY_DATA *AtapiIdentifyPointer; + UINT8 DeviceSelect; + EFI_STATUS Status; + + // + // device select bit + // + DeviceSelect = 0; + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + + AtapiIdentifyPointer = AllocatePool (sizeof (EFI_IDENTIFY_DATA)); + if (AtapiIdentifyPointer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Send ATAPI Identify Command to get IDENTIFY data. + // + Status = AtaPioDataIn ( + IdeDev, + (VOID *) AtapiIdentifyPointer, + sizeof (EFI_IDENTIFY_DATA), + ATAPI_IDENTIFY_DEVICE_CMD, + DeviceSelect, + 0, + 0, + 0, + 0 + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (AtapiIdentifyPointer); + return EFI_DEVICE_ERROR; + } + + IdeDev->pIdData = AtapiIdentifyPointer; + PrintAtaModuleName (IdeDev); + + // + // Send ATAPI Inquiry Packet Command to get INQUIRY data. + // + Status = AtapiInquiry (IdeDev); + if (EFI_ERROR (Status)) { + gBS->FreePool (IdeDev->pIdData); + // + // Make sure the pIdData will not be freed again. + // + IdeDev->pIdData = NULL; + return EFI_DEVICE_ERROR; + } + // + // Get media removable info from INQUIRY data. + // + IdeDev->BlkIo.Media->RemovableMedia = (UINT8) ((IdeDev->pInquiryData->RMB & 0x80) == 0x80); + + // + // Identify device type via INQUIRY data. + // + switch (IdeDev->pInquiryData->peripheral_type & 0x1f) { + + // + // Magnetic Disk + // + case 0x00: + + // + // device is LS120 or ZIP drive. + // + IdeDev->Type = IdeMagnetic; + + IdeDev->BlkIo.Media->MediaId = 0; + // + // Give initial value + // + IdeDev->BlkIo.Media->MediaPresent = FALSE; + + IdeDev->BlkIo.Media->LastBlock = 0; + IdeDev->BlkIo.Media->BlockSize = 0x200; + break; + + // + // CD-ROM + // + case 0x05: + + IdeDev->Type = IdeCdRom; + IdeDev->BlkIo.Media->MediaId = 0; + // + // Give initial value + // + IdeDev->BlkIo.Media->MediaPresent = FALSE; + + IdeDev->BlkIo.Media->LastBlock = 0; + IdeDev->BlkIo.Media->BlockSize = 0x800; + IdeDev->BlkIo.Media->ReadOnly = TRUE; + break; + + // + // Tape + // + case 0x01: + + // + // WORM + // + case 0x04: + + // + // Optical + // + case 0x07: + + default: + IdeDev->Type = IdeUnknown; + gBS->FreePool (IdeDev->pIdData); + gBS->FreePool (IdeDev->pInquiryData); + // + // Make sure the pIdData and pInquiryData will not be freed again. + // + IdeDev->pIdData = NULL; + IdeDev->pInquiryData = NULL; + return EFI_DEVICE_ERROR; + } + + // + // original sense data numbers + // + IdeDev->SenseDataNumber = 20; + + IdeDev->SenseData = AllocatePool (IdeDev->SenseDataNumber * sizeof (REQUEST_SENSE_DATA)); + if (IdeDev->SenseData == NULL) { + gBS->FreePool (IdeDev->pIdData); + gBS->FreePool (IdeDev->pInquiryData); + // + // Make sure the pIdData and pInquiryData will not be freed again. + // + IdeDev->pIdData = NULL; + IdeDev->pInquiryData = NULL; + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AtapiInquiry ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + AtapiInquiry + + Purpose: + Sends out ATAPI Inquiry Packet Command to the specified device. + This command will return INQUIRY data of the device. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + Returns: + EFI_SUCCESS + Inquiry command completes successfully. + + EFI_DEVICE_ERROR + Inquiry command failed. + Notes: + Parameter "IdeDev" will be updated in this function. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +{ + ATAPI_PACKET_COMMAND Packet; + EFI_STATUS Status; + INQUIRY_DATA *InquiryData; + + // + // prepare command packet for the ATAPI Inquiry Packet Command. + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.Inquiry.opcode = INQUIRY; + Packet.Inquiry.page_code = 0; + Packet.Inquiry.allocation_length = sizeof (INQUIRY_DATA); + + InquiryData = AllocatePool (sizeof (INQUIRY_DATA)); + if (InquiryData == NULL) { + return EFI_DEVICE_ERROR; + } + + // + // Send command packet and get requested Inquiry data. + // + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + (UINT16 *) InquiryData, + sizeof (INQUIRY_DATA), + ATAPITIMEOUT + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (InquiryData); + return EFI_DEVICE_ERROR; + } + + IdeDev->pInquiryData = InquiryData; + + return EFI_SUCCESS; +} + +EFI_STATUS +AtapiPacketCommandIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATAPI_PACKET_COMMAND *Packet, + IN UINT16 *Buffer, + IN UINT32 ByteCount, + IN UINTN TimeOut + ) +/*++ + Name: + AtapiPacketCommandIn + + Purpose: + This function is used to send out ATAPI commands conforms to the + Packet Command with PIO Data In Protocol. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + ATAPI_PACKET_COMMAND IN *Packet + pointer pointing to ATAPI_PACKET_COMMAND data structure + which contains the contents of the command. + + UINT16 IN *Buffer + buffer contained data transferred from device to host. + + UINT32 IN ByteCount + data size in byte unit of the buffer. + + UINTN IN TimeOut + this parameter is used to specify the timeout + value for the PioReadWriteData() function. + + Returns: + EFI_SUCCESS + send out the ATAPI packet command successfully + and device sends data successfully. + + EFI_DEVICE_ERROR + the device failed to send data. + + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: Packet - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: ByteCount - add argument and description to function comment +// TODO: TimeOut - add argument and description to function comment +{ + UINT16 *CommandIndex; + EFI_STATUS Status; + UINT32 Count; + + // + // Set all the command parameters by fill related registers. + // Before write to all the following registers, BSY and DRQ must be 0. + // + Status = DRQClear2 (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select device via Device/Head Register. + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000) + ); + + // + // No OVL; No DMA + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00); + + // + // set the transfersize to MAX_ATAPI_BYTE_COUNT to let the device + // determine how many data should be transferred. + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderLsb, + (UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff) + ); + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderMsb, + (UINT8) (MAX_ATAPI_BYTE_COUNT >> 8) + ); + + // + // DEFAULT_CTL:0x0a (0000,1010) + // Disable interrupt + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DEFAULT_CTL); + + // + // Send Packet command to inform device + // that the following data bytes are command packet. + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, PACKET_CMD); + + Status = DRQReady (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Send out command packet + // + CommandIndex = Packet->Data16; + for (Count = 0; Count < 6; Count++, CommandIndex++) { + + IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex); + gBS->Stall (10); + } + + // + // call PioReadWriteData() function to get + // requested transfer data form device. + // + return PioReadWriteData (IdeDev, Buffer, ByteCount, 1, TimeOut); +} + +EFI_STATUS +AtapiPacketCommandOut ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATAPI_PACKET_COMMAND *Packet, + IN UINT16 *Buffer, + IN UINT32 ByteCount, + IN UINTN TimeOut + ) +/*++ + Name: + AtapiPacketCommandOut + + Purpose: + This function is used to send out ATAPI commands conforms to the + Packet Command with PIO Data Out Protocol. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + ATAPI_PACKET_COMMAND IN *Packet + pointer pointing to ATAPI_PACKET_COMMAND data structure + which contains the contents of the command. + + VOID IN *Buffer + buffer contained data transferred from host to device. + + UINT32 IN ByteCount + data size in byte unit of the buffer. + + UINTN IN TimeOut + this parameter is used to specify the timeout + value for the PioReadWriteData() function. + + Returns: + EFI_SUCCESS + send out the ATAPI packet command successfully + and device received data successfully. + + EFI_DEVICE_ERROR + the device failed to send data. + + Notes: + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: Packet - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: ByteCount - add argument and description to function comment +// TODO: TimeOut - add argument and description to function comment +{ + UINT16 *CommandIndex; + EFI_STATUS Status; + UINT32 Count; + + // + // set all the command parameters + // Before write to all the following registers, BSY and DRQ must be 0. + // + Status = DRQClear2 (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Select device via Device/Head Register. + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | DEFAULT_CMD) // DEFAULT_CMD: 0xa0 (1010,0000) + ); + + // + // No OVL; No DMA + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, 0x00); + + // + // set the transfersize to MAX_ATAPI_BYTE_COUNT to + // let the device determine how many data should be transferred. + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderLsb, + (UINT8) (MAX_ATAPI_BYTE_COUNT & 0x00ff) + ); + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->CylinderMsb, + (UINT8) (MAX_ATAPI_BYTE_COUNT >> 8) + ); + + // + // DEFAULT_CTL:0x0a (0000,1010) + // Disable interrupt + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DEFAULT_CTL); + + // + // Send Packet command to inform device + // that the following data bytes are command packet. + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, PACKET_CMD); + + Status = DRQReady2 (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Send out command packet + // + CommandIndex = Packet->Data16; + for (Count = 0; Count < 6; Count++, CommandIndex++) { + IDEWritePortW (IdeDev->PciIo, IdeDev->IoPort->Data, *CommandIndex); + gBS->Stall (10); + } + + // + // call PioReadWriteData() function to send requested transfer data to device. + // + return PioReadWriteData (IdeDev, Buffer, ByteCount, 0, TimeOut); +} + +EFI_STATUS +PioReadWriteData ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT16 *Buffer, + IN UINT32 ByteCount, + IN BOOLEAN Read, + IN UINTN TimeOut + ) +/*++ + Name: + PioReadWriteData + + Purpose: + This function is called by either AtapiPacketCommandIn() or + AtapiPacketCommandOut(). It is used to transfer data between + host and device. The data direction is specified by the fourth + parameter. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *Buffer + buffer contained data transferred between host and device. + + UINT32 IN ByteCount + data size in byte unit of the buffer. + + BOOLEAN IN Read + flag used to determine the data transfer direction. + Read equals 1, means data transferred from device to host; + Read equals 0, means data transferred from host to device. + + UINTN IN TimeOut + timeout value for wait DRQ ready before each data + stream's transfer. + + Returns: + EFI_SUCCESS + data is transferred successfully. + + EFI_DEVICE_ERROR + the device failed to transfer data. + + Notes: + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: ByteCount - add argument and description to function comment +// TODO: Read - add argument and description to function comment +// TODO: TimeOut - add argument and description to function comment +{ + // + // required transfer data in word unit. + // + UINT32 RequiredWordCount; + + // + // actual transfer data in word unit. + // + UINT32 ActualWordCount; + UINT32 WordCount; + EFI_STATUS Status; + UINT16 *PtrBuffer; + + // + // containing status byte read from Status Register. + // + UINT8 StatusRegister; + + // + // No data transfer is premitted. + // + if (ByteCount == 0) { + return EFI_SUCCESS; + } + // + // for performance, we assert the ByteCount is an even number + // which is actually a resonable assumption + ASSERT((ByteCount%2) == 0); + + PtrBuffer = Buffer; + RequiredWordCount = ByteCount / 2; + // + // ActuralWordCount means the word count of data really transferred. + // + ActualWordCount = 0; + + while (ActualWordCount < RequiredWordCount) { + + // + // before each data transfer stream, the host should poll DRQ bit ready, + // to see whether indicates device is ready to transfer data. + // + Status = DRQReady2 (IdeDev, TimeOut); + if (EFI_ERROR (Status)) { + return CheckErrorStatus (IdeDev); + } + + // + // read Status Register will clear interrupt + // + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + // + // get current data transfer size from Cylinder Registers. + // + WordCount = + ( + (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) << 8) | + IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb) + ) & 0xffff; + WordCount /= 2; + + WordCount = EFI_MIN (WordCount, (RequiredWordCount - ActualWordCount)); + + if (Read) { + IDEReadPortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + WordCount, + PtrBuffer + ); + } else { + IDEWritePortWMultiple ( + IdeDev->PciIo, + IdeDev->IoPort->Data, + WordCount, + PtrBuffer + ); + } + + PtrBuffer += WordCount; + ActualWordCount += WordCount; + } + + // + // After data transfer is completed, normally, DRQ bit should clear. + // + Status = DRQClear2 (IdeDev, ATAPITIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // read status register to check whether error happens. + // + return CheckErrorStatus (IdeDev); +} + +EFI_STATUS +AtapiTestUnitReady ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + AtapiTestUnitReady + + Purpose: + Sends out ATAPI Test Unit Ready Packet Command to the specified device + to find out whether device is accessible. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + Returns: + EFI_SUCCESS + device is accessible. + + EFI_DEVICE_ERROR + device is not accessible. + + Notes: + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +{ + ATAPI_PACKET_COMMAND Packet; + EFI_STATUS Status; + + // + // fill command packet + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.TestUnitReady.opcode = TEST_UNIT_READY; + + // + // send command packet + // + Status = AtapiPacketCommandIn (IdeDev, &Packet, NULL, 0, ATAPITIMEOUT); + return Status; +} + +EFI_STATUS +AtapiRequestSense ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT UINTN *SenseCounts + ) +/*++ + Name: + AtapiRequestSense + + Purpose: + Sends out ATAPI Request Sense Packet Command to the specified device. + This command will return all the current Sense data in the device. + This function will pack all the Sense data in one single buffer. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + UINT16 OUT **SenseBuffers + allocated in this function, and freed by the calling function. + This buffer is used to accommodate all the sense data returned + by the device. + + UINTN OUT *BufUnit + record the unit size of the sense data block in the SenseBuffers, + + UINTN OUT *BufNumbers + record the number of units in the SenseBuffers. + + Returns: + EFI_SUCCESS + Request Sense command completes successfully. + + EFI_DEVICE_ERROR + Request Sense command failed. + + Notes: + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: SenseCounts - add argument and description to function comment +{ + EFI_STATUS Status; + REQUEST_SENSE_DATA *Sense; + UINT16 *Ptr; + BOOLEAN FetchSenseData; + ATAPI_PACKET_COMMAND Packet; + + *SenseCounts = 0; + + ZeroMem (IdeDev->SenseData, sizeof (REQUEST_SENSE_DATA) * (IdeDev->SenseDataNumber)); + // + // fill command packet for Request Sense Packet Command + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.RequestSence.opcode = REQUEST_SENSE; + Packet.RequestSence.allocation_length = sizeof (REQUEST_SENSE_DATA); + + // + // initialize pointer + // + Ptr = (UINT16 *) IdeDev->SenseData; + // + // request sense data from device continuously until no sense data + // exists in the device. + // + for (FetchSenseData = TRUE; FetchSenseData;) { + + Sense = (REQUEST_SENSE_DATA *) Ptr; + + // + // send out Request Sense Packet Command and get one Sense data form device + // + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + Ptr, + sizeof (REQUEST_SENSE_DATA), + ATAPITIMEOUT + ); + // + // failed to get Sense data + // + if (EFI_ERROR (Status)) { + if (*SenseCounts == 0) { + return EFI_DEVICE_ERROR; + } else { + return EFI_SUCCESS; + } + } + + (*SenseCounts)++; + // + // We limit MAX sense data count to 20 in order to avoid dead loop. Some + // incompatible ATAPI devices don't retrive NO_SENSE when there is no media. + // In this case, dead loop occurs if we don't have a gatekeeper. 20 is + // supposed to be large enough for any ATAPI device. + // + if ((Sense->sense_key != SK_NO_SENSE) && ((*SenseCounts) < 20)) { + // + // Ptr is word-based pointer + // + Ptr += sizeof (REQUEST_SENSE_DATA) / 2; + + } else { + // + // when no sense key, skip out the loop + // + FetchSenseData = FALSE; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AtapiReadCapacity ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + AtapiReadCapacity + + Purpose: + Sends out ATAPI Read Capacity Packet Command to the specified device. + This command will return the information regarding the capacity of the + media in the device. + + Current device status will impact device's response to the Read Capacity + Command. For example, if the device once reset, the Read Capacity + Command will fail. The Sense data record the current device status, so + if the Read Capacity Command failed, the Sense data must be requested + and be analyzed to determine if the Read Capacity Command should retry. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + Returns: + EFI_SUCCESS + Read Capacity Command finally completes successfully. + + EFI_DEVICE_ERROR + Read Capacity Command failed because of device error. + + Notes: + parameter "IdeDev" will be updated in this function. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: EFI_NOT_READY - add return value to function comment +{ + // + // status returned by Read Capacity Packet Command + // + EFI_STATUS Status; + ATAPI_PACKET_COMMAND Packet; + + // + // used for capacity data returned from ATAPI device + // + READ_CAPACITY_DATA Data; + READ_FORMAT_CAPACITY_DATA FormatData; + + ZeroMem (&Data, sizeof (Data)); + ZeroMem (&FormatData, sizeof (FormatData)); + + if (IdeDev->Type == IdeCdRom) { + + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.Inquiry.opcode = READ_CAPACITY; + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + (UINT16 *) &Data, + sizeof (READ_CAPACITY_DATA), + ATAPITIMEOUT + ); + + } else { + // + // Type == IdeMagnetic + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY; + Packet.ReadFormatCapacity.allocation_length_lo = 12; + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + (UINT16 *) &FormatData, + sizeof (READ_FORMAT_CAPACITY_DATA), + ATAPITIMEOUT + ); + } + + if (!EFI_ERROR (Status)) { + + if (IdeDev->Type == IdeCdRom) { + + IdeDev->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) | + (Data.LastLba2 << 16) | + (Data.LastLba1 << 8) | + Data.LastLba0; + + if (IdeDev->BlkIo.Media->LastBlock != 0) { + + IdeDev->BlkIo.Media->BlockSize = (Data.BlockSize3 << 24) | + (Data.BlockSize2 << 16) | + (Data.BlockSize1 << 8) | + Data.BlockSize0; + + IdeDev->BlkIo.Media->MediaPresent = TRUE; + } else { + IdeDev->BlkIo.Media->MediaPresent = FALSE; + return EFI_DEVICE_ERROR; + } + + IdeDev->BlkIo.Media->ReadOnly = TRUE; + + // + // Because the user data portion in the sector of the Data CD supported + // is always 0x800 + // + IdeDev->BlkIo.Media->BlockSize = 0x800; + } + + if (IdeDev->Type == IdeMagnetic) { + + if (FormatData.DesCode == 3) { + IdeDev->BlkIo.Media->MediaPresent = FALSE; + IdeDev->BlkIo.Media->LastBlock = 0; + } else { + + IdeDev->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) | + (FormatData.LastLba2 << 16) | + (FormatData.LastLba1 << 8) | + FormatData.LastLba0; + if (IdeDev->BlkIo.Media->LastBlock != 0) { + IdeDev->BlkIo.Media->LastBlock--; + + IdeDev->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) | + (FormatData.BlockSize1 << 8) | + FormatData.BlockSize0; + + IdeDev->BlkIo.Media->MediaPresent = TRUE; + } else { + IdeDev->BlkIo.Media->MediaPresent = FALSE; + // + // Return EFI_NOT_READY operation succeeds but returned capacity is 0 + // + return EFI_NOT_READY; + } + + IdeDev->BlkIo.Media->BlockSize = 0x200; + + } + } + + return EFI_SUCCESS; + + } else { + + return EFI_DEVICE_ERROR; + } +} + +EFI_STATUS +AtapiDetectMedia ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT BOOLEAN *MediaChange + ) +/*++ + Name: + AtapiDetectMedia + + Purpose: + Used before read/write blocks from/to ATAPI device media. + Since ATAPI device media is removable, it is necessary to detect + whether media is present and get current present media's + information, and if media has been changed, Block I/O Protocol + need to be reinstalled. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + BOOLEAN OUT *MediaChange + return value that indicates if the media of the device has been + changed. + + Returns: + EFI_SUCCESS + media found successfully. + + EFI_DEVICE_ERROR + any error encounters during media detection. + + EFI_NO_MEDIA + media not found. + + Notes: + parameter IdeDev may be updated in this function. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: MediaChange - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_STATUS ReadCapacityStatus; + EFI_BLOCK_IO_MEDIA OldMediaInfo; + UINTN SenseCounts; + UINTN RetryIndex; + UINTN RetryTimes; + UINTN MaximumRetryTimes; + UINTN ReadyWaitFactor; + BOOLEAN NeedRetry; + // + // a flag used to determine whether need to perform Read Capacity command. + // + BOOLEAN NeedReadCapacity; + BOOLEAN WriteProtected; + + // + // init + // + CopyMem (&OldMediaInfo, IdeDev->BlkIo.Media, sizeof (OldMediaInfo)); + // OldMediaInfo = *(IdeDev->BlkIo.Media); + *MediaChange = FALSE; + ReadCapacityStatus = EFI_DEVICE_ERROR; + + // + // if there is no media, or media is not changed, + // the request sense command will detect faster than read capacity command. + // read capacity command can be bypassed, thus improve performance. + // + + // + // Test Unit Ready command is used to detect whether device is accessible, + // the device will produce corresponding Sense data. + // + for (RetryIndex = 0; RetryIndex < 2; RetryIndex++) { + + Status = AtapiTestUnitReady (IdeDev); + if (!EFI_ERROR (Status)) { + // + // skip the loop if test unit command succeeds. + // + break; + } + + Status = AtapiSoftReset (IdeDev); + + if (EFI_ERROR (Status)) { + AtaSoftReset (IdeDev); + } + } + + SenseCounts = 0; + NeedReadCapacity = TRUE; + + // + // at most retry 5 times + // + MaximumRetryTimes = 5; + RetryTimes = 1; + + for (RetryIndex = 0; + (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes); + RetryIndex++) { + + Status = AtapiRequestSense (IdeDev, &SenseCounts); + + if (!EFI_ERROR (Status)) { + // + // if first time there is no Sense Key, no need to read capacity any more + // + if (!HaveSenseKey (IdeDev->SenseData, SenseCounts) && + (IdeDev->BlkIo.Media->MediaPresent)) { + + if (RetryIndex == 0) { + NeedReadCapacity = FALSE; + } + + } else { + // + // No Media + // + if (IsNoMedia (IdeDev->SenseData, SenseCounts)) { + NeedReadCapacity = FALSE; + IdeDev->BlkIo.Media->MediaPresent = FALSE; + IdeDev->BlkIo.Media->LastBlock = 0; + } else { + // + // Media Changed + // + if (IsMediaChange (IdeDev->SenseData, SenseCounts)) { + NeedReadCapacity = TRUE; + IdeDev->BlkIo.Media->MediaId++; + } + // + // Media Error + // + if (IsMediaError (IdeDev->SenseData, SenseCounts)) { + return EFI_DEVICE_ERROR; + } + } + } + } else { + // + // retry once more, if request sense command met errors. + // + RetryTimes++; + } + } + + if (NeedReadCapacity) { + // + // at most retry 5 times + // + MaximumRetryTimes = 5; + // + // initial retry twice + // + RetryTimes = 2; + ReadyWaitFactor = 2; + + for (RetryIndex = 0; + (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes); + RetryIndex++) { + + ReadCapacityStatus = AtapiReadCapacity (IdeDev); + + SenseCounts = 0; + + if (!EFI_ERROR (ReadCapacityStatus)) { + // + // Read Capacity succeeded + // + break; + + } else { + + if (ReadCapacityStatus == EFI_NOT_READY) { + // + // If device not ready, wait here... waiting time increases by retry + // times. + // + gBS->Stall (ReadyWaitFactor * 2000 * STALL_1_MILLI_SECOND); + ReadyWaitFactor++; + // + // retry once more + // + RetryTimes++; + continue; + } + + // + // Other errors returned, requery sense data + // + Status = AtapiRequestSense (IdeDev, &SenseCounts); + + // + // If Request Sense data failed, reset the device and retry. + // + if (EFI_ERROR (Status)) { + + Status = AtapiSoftReset (IdeDev); + + // + // if ATAPI soft reset fail, + // use stronger reset mechanism -- ATA soft reset. + // + if (EFI_ERROR (Status)) { + AtaSoftReset (IdeDev); + } + // + // retry once more + // + RetryTimes++; + continue; + } + + // + // No Media + // + if (IsNoMedia (IdeDev->SenseData, SenseCounts)) { + + IdeDev->BlkIo.Media->MediaPresent = FALSE; + IdeDev->BlkIo.Media->LastBlock = 0; + return EFI_NO_MEDIA; + } + + if (IsMediaError (IdeDev->SenseData, SenseCounts)) { + return EFI_DEVICE_ERROR; + } + + // + // Media Changed + // + if (IsMediaChange (IdeDev->SenseData, SenseCounts)) { + IdeDev->BlkIo.Media->MediaId++; + } + + if (!IsDriveReady (IdeDev->SenseData, SenseCounts, &NeedRetry)) { + + // + // Drive not ready: if NeedRetry, then retry once more; + // else return error + // + if (NeedRetry) { + // + // Stall 1 second to wait for drive becoming ready + // + gBS->Stall (1000 * STALL_1_MILLI_SECOND); + // + // reset retry variable to zero, + // to make it retry for "drive in progress of becoming ready". + // + RetryIndex = 0; + continue; + } else { + AtapiSoftReset (IdeDev); + return EFI_DEVICE_ERROR; + } + } + // + // if read capacity fail not for above reasons, retry once more + // + RetryTimes++; + } + + } + + // + // tell whether the readcapacity process is successful or not in the end + // + if (EFI_ERROR (ReadCapacityStatus)) { + return EFI_DEVICE_ERROR; + } + } + + // + // the following code is to check the write-protected for LS120 media + // + if ((IdeDev->BlkIo.Media->MediaPresent) && (IdeDev->Type == IdeMagnetic)) { + + Status = IsLS120orZipWriteProtected (IdeDev, &WriteProtected); + if (!EFI_ERROR (Status)) { + + if (WriteProtected) { + + IdeDev->BlkIo.Media->ReadOnly = TRUE; + } else { + + IdeDev->BlkIo.Media->ReadOnly = FALSE; + } + + } + } + + if (IdeDev->BlkIo.Media->MediaId != OldMediaInfo.MediaId) { + // + // Media change information got from the device + // + *MediaChange = TRUE; + } + + if (IdeDev->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) { + *MediaChange = TRUE; + IdeDev->BlkIo.Media->MediaId += 1; + } + + if (IdeDev->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) { + *MediaChange = TRUE; + IdeDev->BlkIo.Media->MediaId += 1; + } + + if (IdeDev->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) { + *MediaChange = TRUE; + IdeDev->BlkIo.Media->MediaId += 1; + } + + if (IdeDev->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) { + if (IdeDev->BlkIo.Media->MediaPresent) { + // + // when change from no media to media present, reset the MediaId to 1. + // + IdeDev->BlkIo.Media->MediaId = 1; + } else { + // + // when no media, reset the MediaId to zero. + // + IdeDev->BlkIo.Media->MediaId = 0; + } + + *MediaChange = TRUE; + } + + // + // if any change on current existing media, + // the Block I/O protocol need to be reinstalled. + // + if (*MediaChange) { + gBS->ReinstallProtocolInterface ( + IdeDev->Handle, + &gEfiBlockIoProtocolGuid, + &IdeDev->BlkIo, + &IdeDev->BlkIo + ); + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +AtapiReadSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +/*++ + Name: + AtapiReadSectors + + Purpose: + This function is called by the AtapiBlkIoReadBlocks() to perform + read from media in block unit. + + The main command used to access media here is READ(10) Command. + READ(10) Command requests that the ATAPI device media transfer + specified data to the host. Data is transferred in block(sector) + unit. The maximum number of blocks that can be transferred once is + 65536. This is the main difference between READ(10) and READ(12) + Command. The maximum number of blocks in READ(12) is 2 power 32. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *Buffer + A pointer to the destination buffer for the data. + + EFI_LBA IN Lba + The starting logical block address to read from + on the device media. + + UINTN IN NumberOfBlocks + The number of transfer data blocks. + + Returns: + return status is fully dependent on the return status + of AtapiPacketCommandIn() function. + + Notes: + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: Lba - add argument and description to function comment +// TODO: NumberOfBlocks - add argument and description to function comment +{ + + ATAPI_PACKET_COMMAND Packet; + READ10_CMD *Read10Packet; + EFI_STATUS Status; + UINTN BlocksRemaining; + UINT32 Lba32; + UINT32 BlockSize; + UINT32 ByteCount; + UINT16 SectorCount; + VOID *PtrBuffer; + UINT16 MaxBlock; + UINTN TimeOut; + + // + // fill command packet for Read(10) command + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Read10Packet = &Packet.Read10; + Lba32 = (UINT32) Lba; + PtrBuffer = Buffer; + + BlockSize = IdeDev->BlkIo.Media->BlockSize; + + // + // limit the data bytes that can be transferred by one Read(10) Command + // + MaxBlock = (UINT16) (65536 / BlockSize); + + BlocksRemaining = NumberOfBlocks; + + Status = EFI_SUCCESS; + while (BlocksRemaining > 0) { + + if (BlocksRemaining <= MaxBlock) { + + SectorCount = (UINT16) BlocksRemaining; + } else { + + SectorCount = MaxBlock; + } + + // + // fill the Packet data structure + // + + Read10Packet->opcode = READ_10; + + // + // Lba0 ~ Lba3 specify the start logical block address of the data transfer. + // Lba0 is MSB, Lba3 is LSB + // + Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff); + Read10Packet->Lba2 = (UINT8) (Lba32 >> 8); + Read10Packet->Lba1 = (UINT8) (Lba32 >> 16); + Read10Packet->Lba0 = (UINT8) (Lba32 >> 24); + + // + // TranLen0 ~ TranLen1 specify the transfer length in block unit. + // TranLen0 is MSB, TranLen is LSB + // + Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff); + Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8); + + ByteCount = SectorCount * BlockSize; + + if (IdeDev->Type == IdeCdRom) { + TimeOut = CDROMLONGTIMEOUT; + } else { + TimeOut = ATAPILONGTIMEOUT; + } + + Status = AtapiPacketCommandIn ( + IdeDev, + &Packet, + (UINT16 *) PtrBuffer, + ByteCount, + TimeOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba32 += SectorCount; + PtrBuffer = (UINT8 *) PtrBuffer + SectorCount * BlockSize; + BlocksRemaining -= SectorCount; + } + + return Status; +} + +EFI_STATUS +AtapiWriteSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +/*++ + Name: + AtapiWriteSectors + + Purpose: + This function is called by the AtapiBlkIoWriteBlocks() to perform + write onto media in block unit. + The main command used to access media here is Write(10) Command. + Write(10) Command requests that the ATAPI device media transfer + specified data to the host. Data is transferred in block (sector) + unit. The maximum number of blocks that can be transferred once is + 65536. + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + VOID IN *Buffer + A pointer to the source buffer for the data. + + EFI_LBA IN Lba + The starting logical block address to write onto + the device media. + + UINTN IN NumberOfBlocks + The number of transfer data blocks. + + Returns: + return status is fully dependent on the return status + of AtapiPacketCommandOut() function. + + Notes: + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: Lba - add argument and description to function comment +// TODO: NumberOfBlocks - add argument and description to function comment +{ + + ATAPI_PACKET_COMMAND Packet; + READ10_CMD *Read10Packet; + + EFI_STATUS Status; + UINTN BlocksRemaining; + UINT32 Lba32; + UINT32 BlockSize; + UINT32 ByteCount; + UINT16 SectorCount; + VOID *PtrBuffer; + UINT16 MaxBlock; + + // + // fill command packet for Write(10) command + // Write(10) command packet has the same data structure as + // Read(10) command packet, + // so here use the Read10Packet data structure + // for the Write(10) command packet. + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Read10Packet = &Packet.Read10; + + Lba32 = (UINT32) Lba; + PtrBuffer = Buffer; + + BlockSize = IdeDev->BlkIo.Media->BlockSize; + + // + // limit the data bytes that can be transferred by one Read(10) Command + // + MaxBlock = (UINT16) (65536 / BlockSize); + + BlocksRemaining = NumberOfBlocks; + + Status = EFI_SUCCESS; + while (BlocksRemaining > 0) { + + if (BlocksRemaining >= MaxBlock) { + SectorCount = MaxBlock; + } else { + SectorCount = (UINT16) BlocksRemaining; + } + + // + // Command code is WRITE_10. + // + Read10Packet->opcode = WRITE_10; + + // + // Lba0 ~ Lba3 specify the start logical block address of the data transfer. + // Lba0 is MSB, Lba3 is LSB + // + Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff); + Read10Packet->Lba2 = (UINT8) (Lba32 >> 8); + Read10Packet->Lba1 = (UINT8) (Lba32 >> 16); + Read10Packet->Lba0 = (UINT8) (Lba32 >> 24); + + // + // TranLen0 ~ TranLen1 specify the transfer length in block unit. + // TranLen0 is MSB, TranLen is LSB + // + Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff); + Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8); + + ByteCount = SectorCount * BlockSize; + + Status = AtapiPacketCommandOut ( + IdeDev, + &Packet, + (UINT16 *) PtrBuffer, + ByteCount, + ATAPILONGTIMEOUT + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Lba32 += SectorCount; + PtrBuffer = ((UINT8 *) PtrBuffer + SectorCount * BlockSize); + BlocksRemaining -= SectorCount; + } + + return Status; +} + +EFI_STATUS +AtapiSoftReset ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Name: + AtapiSoftReset + + Purpose: + This function is used to implement the Soft Reset on the specified + ATAPI device. Different from the AtaSoftReset(), here reset is a ATA + Soft Reset Command special for ATAPI device, and it only take effects + on the specified ATAPI device, not on the whole IDE bus. + Since the ATAPI soft reset is needed when device is in exceptional + condition (such as BSY bit is always set ), I think the Soft Reset + command should be sent without waiting for the BSY clear and DRDY + set. + This function is called by IdeBlkIoReset(), + a interface function of Block I/O protocol. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + Returns: + EFI_SUCCESS + Soft reset completes successfully. + + EFI_DEVICE_ERROR + Any step during the reset process is failed. + + Notes: + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +{ + UINT8 Command; + UINT8 DeviceSelect; + EFI_STATUS Status; + + // + // for ATAPI device, no need to wait DRDY ready after device selecting. + // (bit7 and bit5 are both set to 1 for backward compatibility) + // + DeviceSelect = (UINT8) (((bit7 | bit5) | (IdeDev->Device << 4))); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, DeviceSelect); + + Command = ATAPI_SOFT_RESET_CMD; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, Command); + + // + // BSY cleared is the only status return to the host by the device + // when reset is completed. + // slave device needs at most 31s to clear BSY + // + Status = WaitForBSYClear (IdeDev, 31000); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // stall 5 seconds to make the device status stable + // + gBS->Stall (5000000); + + return EFI_SUCCESS; +} + +EFI_STATUS +AtapiBlkIoReadBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + Name: + AtapiBlkIoReadBlocks + + Purpose: + This function is the ATAPI implementation for ReadBlocks in the + Block I/O Protocol interface. + + Parameters: + IDE_BLK_IO_DEV IN *IdeBlkIoDev + Indicates the calling context. + + UINT32 IN MediaId + The media id that the read request is for. + + EFI_LBA IN LBA + The starting logical block address to read from + on the device. + + UINTN IN BufferSize + The size of the Buffer in bytes. This must be a + multiple of the intrinsic block size of the device. + + VOID OUT *Buffer + A pointer to the destination buffer for the data. + The caller is responsible for either having implicit + or explicit ownership of the memory that data is read into. + + Returns: + EFI_SUCCESS + Read Blocks successfully. + + EFI_DEVICE_ERROR + Read Blocks failed. + + EFI_NO_MEDIA + There is no media in the device. + + EFI_MEDIA_CHANGED + The MediaId is not for the current media. + + EFI_BAD_BUFFER_SIZE + The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + + EFI_INVALID_PARAMETER + The read request contains LBAs that are not valid, + or the data buffer is not valid. + + Notes: + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeBlkIoDevice - add argument and description to function comment +// TODO: MediaId - add argument and description to function comment +// TODO: LBA - add argument and description to function comment +// TODO: BufferSize - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +{ + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + EFI_STATUS Status; + + BOOLEAN MediaChange; + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + // + // ATAPI device media is removable, so it is a must + // to detect media first before read operation + // + MediaChange = FALSE; + Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange); + if (EFI_ERROR (Status)) { + + if (IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + + return Status; + } + // + // Get the intrinsic block size + // + Media = IdeBlkIoDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + + NumberOfBlocks = BufferSize / BlockSize; + + if (!(Media->MediaPresent)) { + + if (IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + return EFI_NO_MEDIA; + + } + + if ((MediaId != Media->MediaId) || MediaChange) { + + if (IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + return EFI_MEDIA_CHANGED; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (LBA > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + // + // if all the parameters are valid, then perform read sectors command + // to transfer data from device to host. + // + Status = AtapiReadSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Read blocks succeeded + // + + // + // save the first block to the cache for performance + // + if (LBA == 0 && !IdeBlkIoDevice->Cache) { + IdeBlkIoDevice->Cache = AllocatePool (BlockSize); + if (IdeBlkIoDevice != NULL) { + CopyMem ((UINT8 *) IdeBlkIoDevice->Cache, (UINT8 *) Buffer, BlockSize); + } + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +AtapiBlkIoWriteBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + Name: + AtapiBlkIoWriteBlocks + + Purpose: + This function is the ATAPI implementation for WriteBlocks in the + Block I/O Protocol interface. + + Parameters: + EFI_BLOCK_IO IN *This + Indicates the calling context. + + UINT32 IN MediaId + The media id that the write request is for. + + EFI_LBA IN LBA + The starting logical block address to write onto + the device. + + UINTN IN BufferSize + The size of the Buffer in bytes. This must be a + multiple of the intrinsic block size of the device. + + VOID OUT *Buffer + A pointer to the source buffer for the data. + The caller is responsible for either having implicit + or explicit ownership of the memory that data is + written from. + + Returns: + EFI_SUCCESS + Write Blocks successfully. + + EFI_DEVICE_ERROR + Write Blocks failed. + + EFI_NO_MEDIA + There is no media in the device. + + EFI_MEDIA_CHANGE + The MediaId is not for the current media. + + EFI_BAD_BUFFER_SIZE + The BufferSize parameter is not a multiple of the + intrinsic block size of the device. + + EFI_INVALID_PARAMETER + The write request contains LBAs that are not valid, + or the data buffer is not valid. + + Notes: + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeBlkIoDevice - add argument and description to function comment +// TODO: MediaId - add argument and description to function comment +// TODO: LBA - add argument and description to function comment +// TODO: BufferSize - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: EFI_MEDIA_CHANGED - add return value to function comment +// TODO: EFI_WRITE_PROTECTED - add return value to function comment +{ + + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + EFI_STATUS Status; + BOOLEAN MediaChange; + + if (LBA == 0 && IdeBlkIoDevice->Cache) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + // + // ATAPI device media is removable, + // so it is a must to detect media first before write operation + // + MediaChange = FALSE; + Status = AtapiDetectMedia (IdeBlkIoDevice, &MediaChange); + if (EFI_ERROR (Status)) { + + if (LBA == 0 && IdeBlkIoDevice->Cache) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + return Status; + } + + // + // Get the intrinsic block size + // + Media = IdeBlkIoDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + NumberOfBlocks = BufferSize / BlockSize; + + if (!(Media->MediaPresent)) { + + if (LBA == 0 && IdeBlkIoDevice->Cache) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + return EFI_NO_MEDIA; + } + + if ((MediaId != Media->MediaId) || MediaChange) { + + if (LBA == 0 && IdeBlkIoDevice->Cache) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + return EFI_MEDIA_CHANGED; + } + + if (Media->ReadOnly) { + return EFI_WRITE_PROTECTED; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (LBA > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + // + // if all the parameters are valid, + // then perform write sectors command to transfer data from host to device. + // + Status = AtapiWriteSectors (IdeBlkIoDevice, Buffer, LBA, NumberOfBlocks); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + +} + +// +// The following functions are a set of helper functions, +// which are used to parse sense key returned by the device. +// + +BOOLEAN +IsNoMedia ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + REQUEST_SENSE_DATA *SensePointer; + UINTN Index; + BOOLEAN NoMedia; + + NoMedia = FALSE; + SensePointer = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + // + // Sense Key is SK_NOT_READY (0x2), + // Additional Sense Code is ASC_NO_MEDIA (0x3A) + // + if ((SensePointer->sense_key == SK_NOT_READY) && + (SensePointer->addnl_sense_code == ASC_NO_MEDIA)) { + + NoMedia = TRUE; + } + + SensePointer++; + } + + return NoMedia; +} + +BOOLEAN +IsMediaError ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + Name: + IsMediaError + + Purpose: + Test if the device meets a media error after media changed + + Parameters: + EQUEST_SENSE_DATA IN *SenseData + pointer pointing to ATAPI device sense data list. + UINTN IN SenseCounts + sense data number of the list + + Returns: + TRUE + Device meets a media error + + FALSE + No media error +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: SenseData - add argument and description to function comment +// TODO: SenseCounts - add argument and description to function comment +{ + REQUEST_SENSE_DATA *SensePointer; + UINTN Index; + BOOLEAN IsError; + + IsError = FALSE; + SensePointer = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + switch (SensePointer->sense_key) { + + case SK_MEDIUM_ERROR: + // + // Sense Key is SK_MEDIUM_ERROR (0x3) + // + switch (SensePointer->addnl_sense_code) { + case ASC_MEDIA_ERR1: + case ASC_MEDIA_ERR2: + case ASC_MEDIA_ERR3: + case ASC_MEDIA_ERR4: + IsError = TRUE; + break; + + default: + break; + } + + break; + + case SK_NOT_READY: + // + // Sense Key is SK_NOT_READY (0x2) + // + switch (SensePointer->addnl_sense_code) { + // + // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6) + // + case ASC_MEDIA_UPSIDE_DOWN: + IsError = TRUE; + break; + + default: + break; + } + break; + + default: + break; + } + + SensePointer++; + } + + return IsError; +} + +BOOLEAN +IsMediaChange ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + REQUEST_SENSE_DATA *SensePointer; + UINTN Index; + BOOLEAN IsMediaChange; + + IsMediaChange = FALSE; + SensePointer = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + // + // Sense Key is SK_UNIT_ATTENTION (0x6) + // + if ((SensePointer->sense_key == SK_UNIT_ATTENTION) && + (SensePointer->addnl_sense_code == ASC_MEDIA_CHANGE)) { + + IsMediaChange = TRUE; + } + + SensePointer++; + } + + return IsMediaChange; +} + +BOOLEAN +IsDriveReady ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts, + OUT BOOLEAN *NeedRetry + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + NeedRetry - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + REQUEST_SENSE_DATA *SensePointer; + UINTN Index; + BOOLEAN IsReady; + + IsReady = TRUE; + *NeedRetry = FALSE; + SensePointer = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + switch (SensePointer->sense_key) { + + case SK_NOT_READY: + // + // Sense Key is SK_NOT_READY (0x2) + // + switch (SensePointer->addnl_sense_code) { + case ASC_NOT_READY: + // + // Additional Sense Code is ASC_NOT_READY (0x4) + // + switch (SensePointer->addnl_sense_code_qualifier) { + case ASCQ_IN_PROGRESS: + // + // Additional Sense Code Qualifier is ASCQ_IN_PROGRESS (0x1) + // + IsReady = FALSE; + *NeedRetry = TRUE; + break; + + default: + IsReady = FALSE; + *NeedRetry = FALSE; + break; + } + break; + + default: + break; + } + break; + + default: + break; + } + + SensePointer++; + } + + return IsReady; +} + +BOOLEAN +HaveSenseKey ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + BOOLEAN Have; + + Have = TRUE; + + // + // if first sense key in the Sense Data Array is SK_NO_SENSE, + // it indicates there is no more sense key in the Sense Data Array. + // + if (SenseData->sense_key == SK_NO_SENSE) { + Have = FALSE; + } + + return Have; +} + +EFI_STATUS +IsLS120orZipWriteProtected ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT BOOLEAN *WriteProtected + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + WriteProtected - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + + *WriteProtected = FALSE; + + Status = LS120EnableMediaStatus (IdeDev, TRUE); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // the Get Media Status Command is only valid + // if a Set Features/Enable Media Status Command has been priviously issued. + // + if (LS120GetMediaStatus (IdeDev) == EFI_WRITE_PROTECTED) { + + *WriteProtected = TRUE; + } else { + + *WriteProtected = FALSE; + } + + // + // After Get Media Status Command completes, + // Set Features/Disable Media Command should be sent. + // + Status = LS120EnableMediaStatus (IdeDev, FALSE); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/build.xml b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/build.xml new file mode 100644 index 0000000000..3a33a2b3a9 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/build.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c new file mode 100644 index 0000000000..d318fd23df --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.c @@ -0,0 +1,1964 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ide.c + +Abstract: + + +Revision History +--*/ + +#include "idebus.h" + +BOOLEAN SlaveDeviceExist = FALSE; +BOOLEAN MasterDeviceExist = FALSE; + +UINT8 +IDEReadPortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT8 Data; + + Data = 0; + // + // perform 1-byte data read from register + // + PciIo->Io.Read ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); + return Data; +} + +VOID +IDEReadPortWMultiple ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINTN Count, + IN VOID *Buffer + ) +/*++ + +Routine Description: + Reads multiple words of data from the IDE data port. + Call the IO abstraction once to do the complete read, + not one word at a time + + +Arguments: + PciIo - Pointer to the EFI_PCI_IO instance + Port - IO port to read + Count - No. of UINT16's to read + Buffer - Pointer to the data buffer for read + +++*/ +// TODO: function comment should end with '--*/' +// TODO: function comment is missing 'Returns:' +{ + UINT16 *AlignedBuffer; + UINT16 *WorkingBuffer; + UINTN Size; + + // + // Prepare an 16-bit alligned working buffer. CpuIo will return failure and + // not perform actual I/O operations if buffer pointer passed in is not at + // natural boundary. The "Buffer" argument is passed in by user and may not + // at 16-bit natural boundary. + // + Size = sizeof (UINT16) * Count; + + gBS->AllocatePool ( + EfiBootServicesData, + Size + 1, + (VOID**)&WorkingBuffer + ); + + AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1))); + + // + // Perform UINT16 data read from FIFO + // + PciIo->Io.Read ( + PciIo, + EfiPciIoWidthFifoUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + Count, + (UINT16*)AlignedBuffer + ); + + // + // Copy data to user buffer + // + CopyMem (Buffer, (UINT16*)AlignedBuffer, Size); + gBS->FreePool (WorkingBuffer); +} + +VOID +IDEWritePortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT8 Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + // + // perform 1-byte data write to register + // + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint8, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); + +} + +VOID +IDEWritePortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT16 Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + // + // perform 1-word data write to register + // + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + 1, + &Data + ); +} + +VOID +IDEWritePortWMultiple ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINTN Count, + IN VOID *Buffer + ) +/*++ + +Routine Description: + Write multiple words of data to the IDE data port. + Call the IO abstraction once to do the complete read, + not one word at a time + + +Arguments: + PciIo - Pointer to the EFI_PCI_IO instance + Port - IO port to read + Count - No. of UINT16's to read + Buffer - Pointer to the data buffer for read + +++*/ +// TODO: function comment should end with '--*/' +// TODO: function comment is missing 'Returns:' +{ + UINT16 *AlignedBuffer; + UINT32 *WorkingBuffer; + UINTN Size; + + // + // Prepare an 16-bit alligned working buffer. CpuIo will return failure and + // not perform actual I/O operations if buffer pointer passed in is not at + // natural boundary. The "Buffer" argument is passed in by user and may not + // at 16-bit natural boundary. + // + Size = sizeof (UINT16) * Count; + + gBS->AllocatePool ( + EfiBootServicesData, + Size + 1, + (VOID **) &WorkingBuffer + ); + + AlignedBuffer = (UINT16 *) ((UINTN)(((UINTN) WorkingBuffer + 0x1) & (~0x1))); + + // + // Copy data from user buffer to working buffer + // + CopyMem ((UINT16 *) AlignedBuffer, Buffer, Size); + + // + // perform UINT16 data write to the FIFO + // + PciIo->Io.Write ( + PciIo, + EfiPciIoWidthFifoUint16, + EFI_PCI_IO_PASS_THROUGH_BAR, + (UINT64) Port, + Count, + (UINT16 *) AlignedBuffer + ); + + gBS->FreePool (WorkingBuffer); +} + +BOOLEAN +BadIdeDeviceCheck ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + // + // check whether all registers return 0xff, + // if so, deem the channel is disabled. + // +#ifdef EFI_DEBUG + + if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Data) != 0xff) { + return FALSE; + } + + if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature) != 0xff) { + return FALSE; + } + + if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount) != 0xff) { + return FALSE; + } + + if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber) != 0xff) { + return FALSE; + } + + if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb) != 0xff) { + return FALSE; + } + + if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb) != 0xff) { + return FALSE; + } + + if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Head) != 0xff) { + return FALSE; + } + + if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command) != 0xff) { + return FALSE; + } + + if (IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus) != 0xff) { + return FALSE; + } + + return TRUE; + +#else + + return FALSE; + +#endif +} + +// +// GetIdeRegistersBaseAddr +// +EFI_STATUS +GetIdeRegistersBaseAddr ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr + ) +/*++ + +Routine Description: + Get IDE IO port registers' base addresses by mode. In 'Compatibility' mode, + use fixed addresses. In Native-PCI mode, get base addresses from BARs in + the PCI IDE controller's Configuration Space. + + The steps to get IDE IO port registers' base addresses for each channel + as follows: + + 1. Examine the Programming Interface byte of the Class Code fields in PCI IDE + controller's Configuration Space to determine the operating mode. + + 2. a) In 'Compatibility' mode, use fixed addresses shown in the Table 1 below. + ___________________________________________ + | | Command Block | Control Block | + | Channel | Registers | Registers | + |___________|_______________|_______________| + | Primary | 1F0h - 1F7h | 3F6h - 3F7h | + |___________|_______________|_______________| + | Secondary | 170h - 177h | 376h - 377h | + |___________|_______________|_______________| + + Table 1. Compatibility resource mappings + + b) In Native-PCI mode, IDE registers are mapped into IO space using the BARs + in IDE controller's PCI Configuration Space, shown in the Table 2 below. + ___________________________________________________ + | | Command Block | Control Block | + | Channel | Registers | Registers | + |___________|___________________|___________________| + | Primary | BAR at offset 0x10| BAR at offset 0x14| + |___________|___________________|___________________| + | Secondary | BAR at offset 0x18| BAR at offset 0x1C| + |___________|___________________|___________________| + + Table 2. BARs for Register Mapping + Note: Refer to Intel ICH4 datasheet, Control Block Offset: 03F4h for + primary, 0374h for secondary. So 2 bytes extra offset should be + added to the base addresses read from BARs. + + For more details, please refer to PCI IDE Controller Specification and Intel + ICH4 Datasheet. + +Arguments: + PciIo - Pointer to the EFI_PCI_IO_PROTOCOL instance + IdeRegsBaseAddr - Pointer to IDE_REGISTERS_BASE_ADDR to + receive IDE IO port registers' base addresses + +Returns: + +--*/ +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + PCI_TYPE00 PciData; + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + 0, + sizeof (PciData), + &PciData + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if ((PciData.Hdr.ClassCode[0] & IDE_PRIMARY_OPERATING_MODE) == 0) { + IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = 0x1f0; + IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = 0x3f6; + IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr = + (UINT16)((PciData.Device.Bar[4] & 0x0000fff0)); + } else { + // + // The BARs should be of IO type + // + if ((PciData.Device.Bar[0] & bit0) == 0 || + (PciData.Device.Bar[1] & bit0) == 0) { + return EFI_UNSUPPORTED; + } + + IdeRegsBaseAddr[IdePrimary].CommandBlockBaseAddr = + (UINT16) (PciData.Device.Bar[0] & 0x0000fff8); + IdeRegsBaseAddr[IdePrimary].ControlBlockBaseAddr = + (UINT16) ((PciData.Device.Bar[1] & 0x0000fffc) + 2); + IdeRegsBaseAddr[IdePrimary].BusMasterBaseAddr = + (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); + } + + if ((PciData.Hdr.ClassCode[0] & IDE_SECONDARY_OPERATING_MODE) == 0) { + IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = 0x170; + IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = 0x376; + IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr = + (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); + } else { + // + // The BARs should be of IO type + // + if ((PciData.Device.Bar[2] & bit0) == 0 || + (PciData.Device.Bar[3] & bit0) == 0) { + return EFI_UNSUPPORTED; + } + + IdeRegsBaseAddr[IdeSecondary].CommandBlockBaseAddr = + (UINT16) (PciData.Device.Bar[2] & 0x0000fff8); + IdeRegsBaseAddr[IdeSecondary].ControlBlockBaseAddr = + (UINT16) ((PciData.Device.Bar[3] & 0x0000fffc) + 2); + IdeRegsBaseAddr[IdeSecondary].BusMasterBaseAddr = + (UINT16) ((PciData.Device.Bar[4] & 0x0000fff0)); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ReassignIdeResources ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + This function is used to requery IDE resources. The IDE controller will + probably switch between native and legacy modes during the EFI->CSM->OS + transfer. We do this everytime before an BlkIo operation to ensure its + succeess. + +Arguments: + IdeDev - The BLK_IO private data which specifies the IDE device + +++*/ +// TODO: function comment should end with '--*/' +// TODO: function comment is missing 'Returns:' +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel]; + UINT16 CommandBlockBaseAddr; + UINT16 ControlBlockBaseAddr; + + // + // Requery IDE IO port registers' base addresses in case of the switch of + // native and legacy modes + // + Status = GetIdeRegistersBaseAddr (IdeDev->PciIo, IdeRegsBaseAddr); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (IdeDev->IoPort, sizeof (IDE_BASE_REGISTERS)); + CommandBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].CommandBlockBaseAddr; + ControlBlockBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].ControlBlockBaseAddr; + + IdeDev->IoPort->Data = CommandBlockBaseAddr; + (*(UINT16 *) &IdeDev->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01); + IdeDev->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); + IdeDev->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); + IdeDev->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); + IdeDev->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); + IdeDev->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06); + + (*(UINT16 *) &IdeDev->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07); + (*(UINT16 *) &IdeDev->IoPort->Alt) = ControlBlockBaseAddr; + IdeDev->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01); + IdeDev->IoPort->MasterSlave = (UINT16) ((IdeDev->Device == IdeMaster) ? 1 : 0); + + IdeDev->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeDev->Channel].BusMasterBaseAddr; + return EFI_SUCCESS; +} + +EFI_STATUS +CheckPowerMode ( + IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Routine Description: + + Read SATA registers to detect SATA disks + + Arguments: + + IdeDev - The BLK_IO private data which specifies the IDE device + +++*/ +// TODO: function comment should end with '--*/' +// TODO: function comment is missing 'Returns:' +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + UINT8 ErrorRegister; + EFI_STATUS Status; + + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + + // + // Wait 31 seconds for BSY clear. BSY should be in clear state if there exists + // a device (initial state). Normally, BSY is also in clear state if there is + // no device + // + Status = WaitForBSYClear (IdeDev, 31000); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // select device, read error register + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + Status = DRDYReady (IdeDev, 200); + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister == 0x01) || (ErrorRegister == 0x81)) { + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } +} + +// +// DiscoverIdeDevice +// +EFI_STATUS +DiscoverIdeDevice ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + Routine Description: + + Detect if there is disk connected to this port + + Arguments: + + IdeDev - The BLK_IO private data which specifies the IDE device + +++*/ +// TODO: function comment should end with '--*/' +// TODO: function comment is missing 'Returns:' +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + BOOLEAN SataFlag; + + SataFlag = FALSE; + // + // This extra detection is for SATA disks + // + Status = CheckPowerMode (IdeDev); + if (Status == EFI_SUCCESS) { + SataFlag = TRUE; + } + + // + // If a channel has not been checked, check it now. Then set it to "checked" state + // After this step, all devices in this channel have been checked. + // + Status = DetectIDEController (IdeDev); + + if ((EFI_ERROR (Status)) && !SataFlag) { + return EFI_NOT_FOUND; + } + + // + // Device exists. test if it is an ATA device + // + Status = ATAIdentify (IdeDev); + if (EFI_ERROR (Status)) { + // + // if not ATA device, test if it is an ATAPI device + // + Status = ATAPIIdentify (IdeDev); + if (EFI_ERROR (Status)) { + // + // if not ATAPI device either, return error. + // + return EFI_NOT_FOUND; + } + } + + // + // Init Block I/O interface + // + IdeDev->BlkIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; + IdeDev->BlkIo.Reset = IDEBlkIoReset; + IdeDev->BlkIo.ReadBlocks = IDEBlkIoReadBlocks; + IdeDev->BlkIo.WriteBlocks = IDEBlkIoWriteBlocks; + IdeDev->BlkIo.FlushBlocks = IDEBlkIoFlushBlocks; + + IdeDev->BlkMedia.LogicalPartition = FALSE; + IdeDev->BlkMedia.WriteCaching = FALSE; + + // + // Init Disk Info interface + // + gBS->CopyMem (&IdeDev->DiskInfo.Interface, &gEfiDiskInfoIdeInterfaceGuid, sizeof (EFI_GUID)); + IdeDev->DiskInfo.Inquiry = IDEDiskInfoInquiry; + IdeDev->DiskInfo.Identify = IDEDiskInfoIdentify; + IdeDev->DiskInfo.SenseData = IDEDiskInfoSenseData; + IdeDev->DiskInfo.WhichIde = IDEDiskInfoWhichIde; + + return EFI_SUCCESS; +} + +EFI_STATUS +DetectIDEController ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + + Name: DetectIDEController + + + Purpose: + This function is called by DiscoverIdeDevice(). It is used for detect + whether the IDE device exists in the specified Channel as the specified + Device Number. + + There is two IDE channels: one is Primary Channel, the other is + Secondary Channel.(Channel is the logical name for the physical "Cable".) + Different channel has different register group. + + On each IDE channel, at most two IDE devices attach, + one is called Device 0 (Master device), the other is called Device 1 + (Slave device). The devices on the same channel co-use the same register + group, so before sending out a command for a specified device via command + register, it is a must to select the current device to accept the command + by set the device number in the Head/Device Register. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + + Returns: + TRUE + successfully detects device. + + FALSE + any failure during detection process will return this + value. + + + Notes: +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + EFI_STATUS Status; + UINT8 ErrorReg; + UINT8 StatusReg; + UINT8 InitStatusReg; + EFI_STATUS DeviceStatus; + + // + // Slave device has been detected with master device. + // + if ((IdeDev->Device) == 1) { + if (SlaveDeviceExist) { + // + // If master not exists but slave exists, slave have to wait a while + // + if (!MasterDeviceExist) { + // + // if single slave can't be detected, add delay 4s here. + // + gBS->Stall (4000000); + } + + return EFI_SUCCESS; + } else { + return EFI_NOT_FOUND; + } + } + + // + // Select slave device + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((1 << 4) | 0xe0) + ); + gBS->Stall (100); + + // + // Save the init slave status register + // + InitStatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + // + // Select master back + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((0 << 4) | 0xe0) + ); + gBS->Stall (100); + // + // Send ATA Device Execut Diagnostic command. + // This command should work no matter DRDY is ready or not + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, 0x90); + + Status = WaitForBSYClear (IdeDev, 3500); + + ErrorReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + + // + // Master Error register is 0x01. D0 passed, D1 passed or not present. + // Master Error register is 0x81. D0 passed, D1 failed. Return. + // Master Error register is other value. D0 failed, D1 passed or not present.. + // + if (ErrorReg == 0x01) { + MasterDeviceExist = TRUE; + DeviceStatus = EFI_SUCCESS; + } else if (ErrorReg == 0x81) { + + MasterDeviceExist = TRUE; + DeviceStatus = EFI_SUCCESS; + SlaveDeviceExist = FALSE; + + return DeviceStatus; + } else { + MasterDeviceExist = FALSE; + DeviceStatus = EFI_NOT_FOUND; + } + + // + // Master Error register is not 0x81, Go on check Slave + // + + // + // select slave + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((1 << 4) | 0xe0) + ); + + gBS->Stall (300); + ErrorReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + + // + // Slave Error register is not 0x01, D1 failed. Return. + // + if (ErrorReg != 0x01) { + SlaveDeviceExist = FALSE; + return DeviceStatus; + } + + StatusReg = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + // + // Most ATAPI devices don't set DRDY bit, so test with a slow but accurate + // "ATAPI TEST UNIT READY" command + // + if (((StatusReg & DRDY) == 0) && ((InitStatusReg & DRDY) == 0)) { + Status = AtapiTestUnitReady (IdeDev); + + // + // Still fail, Slave doesn't exist. + // + if (EFI_ERROR (Status)) { + SlaveDeviceExist = FALSE; + return DeviceStatus; + } + } + + // + // Error reg is 0x01 and DRDY is ready, + // or ATAPI test unit ready success, + // or init Slave status DRDY is ready + // Slave exists. + // + SlaveDeviceExist = TRUE; + + return DeviceStatus; + +} + +EFI_STATUS +DRQClear ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + Name: DRQClear + + + Purpose: + This function is used to poll for the DRQ bit clear in the Status + Register. DRQ is cleared when the device is finished transferring data. + So this function is called after data transfer is finished. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + UINTN IN TimeoutInMilliSeconds + used to designate the timeout for the DRQ clear. + + Returns: + EFI_SUCCESS + DRQ bit clear within the time out. + + EFI_TIMEOUT + DRQ bit not clear within the time out. + + + Notes: + Read Status Register will clear interrupt status. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: TimeoutInMilliSeconds - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +{ + UINT32 Delay; + UINT8 StatusRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + // + // wait for BSY == 0 and DRQ == 0 + // + if ((StatusRegister & (DRQ | BSY)) == 0) { + break; + } + + if ((StatusRegister & (BSY | ERR)) == ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DRQClear2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + Name: DRQClear2 + + + Purpose: + This function is used to poll for the DRQ bit clear in the Alternate + Status Register. DRQ is cleared when the device is finished + transferring data. So this function is called after data transfer + is finished. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + UINTN IN TimeoutInMilliSeconds + used to designate the timeout for the DRQ clear. + + Returns: + EFI_SUCCESS + DRQ bit clear within the time out. + + EFI_TIMEOUT + DRQ bit not clear within the time out. + + + Notes: + Read Alternate Status Register will not clear interrupt status. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: TimeoutInMilliSeconds - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +{ + UINT32 Delay; + UINT8 AltRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + + AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); + + // + // wait for BSY == 0 and DRQ == 0 + // + if ((AltRegister & (DRQ | BSY)) == 0) { + break; + } + + if ((AltRegister & (BSY | ERR)) == ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DRQReady ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + Name: DRQReady + + + Purpose: + This function is used to poll for the DRQ bit set in the + Status Register. + DRQ is set when the device is ready to transfer data. So this function + is called after the command is sent to the device and before required + data is transferred. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure,used + to record all the information of the IDE device. + + UINTN IN TimeoutInMilliSeconds + used to designate the timeout for the DRQ ready. + + + Returns: + EFI_SUCCESS + DRQ bit set within the time out. + + EFI_TIMEOUT + DRQ bit not set within the time out. + + EFI_ABORTED + DRQ bit not set caused by the command abort. + + Notes: + Read Status Register will clear interrupt status. + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: TimeoutInMilliSeconds - add argument and description to function comment +{ + UINT32 Delay; + UINT8 StatusRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + // + // read Status Register will clear interrupt + // + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + + // + // BSY==0,DRQ==1 + // + if ((StatusRegister & (BSY | DRQ)) == DRQ) { + break; + } + + if ((StatusRegister & (BSY | ERR)) == ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DRQReady2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + Name: DRQReady2 + + + Purpose: + This function is used to poll for the DRQ bit set in the + Alternate Status Register. DRQ is set when the device is ready to + transfer data. So this function is called after the command + is sent to the device and before required data is transferred. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + UINTN IN TimeoutInMilliSeconds + used to designate the timeout for the DRQ ready. + + Returns: + EFI_SUCCESS + DRQ bit set within the time out. + + EFI_TIMEOUT + DRQ bit not set within the time out. + + EFI_ABORTED + DRQ bit not set caused by the command abort. + + Notes: + Read Alternate Status Register will not clear interrupt status. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: TimeoutInMilliSeconds - add argument and description to function comment +{ + UINT32 Delay; + UINT8 AltRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + + do { + // + // Read Alternate Status Register will not clear interrupt status + // + AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); + // + // BSY == 0 , DRQ == 1 + // + if ((AltRegister & (BSY | DRQ)) == DRQ) { + break; + } + + if ((AltRegister & (BSY | ERR)) == ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +WaitForBSYClear ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + Name: + WaitForBSYClear + + + Purpose: + This function is used to poll for the BSY bit clear in the + Status Register. BSY is clear when the device is not busy. + Every command must be sent after device is not busy. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + UINTN IN TimeoutInMilliSeconds + used to designate the timeout for the DRQ ready. + + Returns: + EFI_SUCCESS + BSY bit clear within the time out. + + EFI_TIMEOUT + BSY bit not clear within the time out. + + + Notes: + Read Status Register will clear interrupt status. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: TimeoutInMilliSeconds - add argument and description to function comment +{ + UINT32 Delay; + UINT8 StatusRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + if ((StatusRegister & BSY) == 0x00) { + break; + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} +// +// WaitForBSYClear2 +// +EFI_STATUS +WaitForBSYClear2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + Name: + WaitForBSYClear2 + + + Purpose: + This function is used to poll for the BSY bit clear in the + Alternate Status Register. BSY is clear when the device is not busy. + Every command must be sent after device is not busy. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + UINTN IN TimeoutInMilliSeconds + used to designate the timeout for the DRQ ready. + + Returns: + EFI_SUCCESS + BSY bit clear within the time out. + + EFI_TIMEOUT + BSY bit not clear within the time out. + + + Notes: + Read Alternate Status Register will not clear interrupt status. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: TimeoutInMilliSeconds - add argument and description to function comment +{ + UINT32 Delay; + UINT8 AltRegister; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); + if ((AltRegister & BSY) == 0x00) { + break; + } + + gBS->Stall (30); + + Delay--; + + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +// +// DRDYReady +// +EFI_STATUS +DRDYReady ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN DelayInMilliSeconds + ) +/*++ + Name: + DRDYReady + + + Purpose: + This function is used to poll for the DRDY bit set in the + Status Register. DRDY bit is set when the device is ready + to accept command. Most ATA commands must be sent after + DRDY set except the ATAPI Packet Command. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + UINTN IN TimeoutInMilliSeconds + used to designate the timeout for the DRQ ready. + + Returns: + EFI_SUCCESS + DRDY bit set within the time out. + + EFI_TIMEOUT + DRDY bit not set within the time out. + + + Notes: + Read Status Register will clear interrupt status. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: DelayInMilliSeconds - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +{ + UINT32 Delay; + UINT8 StatusRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + // + // BSY == 0 , DRDY == 1 + // + if ((StatusRegister & (DRDY | BSY)) == DRDY) { + break; + } + + if ((StatusRegister & (BSY | ERR)) == ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + gBS->Stall (15); + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +// +// DRDYReady2 +// +EFI_STATUS +DRDYReady2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN DelayInMilliSeconds + ) +/*++ + Name: + DRDYReady2 + + + Purpose: + This function is used to poll for the DRDY bit set in the + Alternate Status Register. DRDY bit is set when the device is ready + to accept command. Most ATA commands must be sent after + DRDY set except the ATAPI Packet Command. + + + Parameters: + IDE_BLK_IO_DEV IN *IdeDev + pointer pointing to IDE_BLK_IO_DEV data structure, used + to record all the information of the IDE device. + + UINTN IN TimeoutInMilliSeconds + used to designate the timeout for the DRQ ready. + + Returns: + EFI_SUCCESS + DRDY bit set within the time out. + + EFI_TIMEOUT + DRDY bit not set within the time out. + + + Notes: + Read Alternate Status Register will clear interrupt status. +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: IdeDev - add argument and description to function comment +// TODO: DelayInMilliSeconds - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +{ + UINT32 Delay; + UINT8 AltRegister; + UINT8 ErrorRegister; + + Delay = (UINT32) (((DelayInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + AltRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Alt.AltStatus); + // + // BSY == 0 , DRDY == 1 + // + if ((AltRegister & (DRDY | BSY)) == DRDY) { + break; + } + + if ((AltRegister & (BSY | ERR)) == ERR) { + + ErrorRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Error); + if ((ErrorRegister & ABRT_ERR) == ABRT_ERR) { + return EFI_ABORTED; + } + } + + gBS->Stall (30); + + Delay--; + } while (Delay); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +// +// SwapStringChars +// +VOID +SwapStringChars ( + IN CHAR8 *Destination, + IN CHAR8 *Source, + IN UINT32 Size + ) +/*++ + Name: + SwapStringChars + + + Purpose: + This function is a helper function used to change the char order in a + string. It is designed specially for the PrintAtaModuleName() function. + After the IDE device is detected, the IDE driver gets the device module + name by sending ATA command called ATA Identify Command or ATAPI + Identify Command to the specified IDE device. The module name returned + is a string of ASCII characters: the first character is bit8--bit15 + of the first word, the second character is bit0--bit7 of the first word + and so on. Thus the string can not be print directly before it is + preprocessed by this func to change the order of characters in + each word in the string. + + + Parameters: + CHAR8 IN *Destination + Indicates the destination string. + + CHAR8 IN *Source + Indicates the source string. + + UINT8 IN Size + the length of the string + + + Returns: + none + + Notes: + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: Destination - add argument and description to function comment +// TODO: Source - add argument and description to function comment +// TODO: Size - add argument and description to function comment +{ + UINT32 Index; + CHAR8 Temp; + + for (Index = 0; Index < Size; Index += 2) { + + Temp = Source[Index + 1]; + Destination[Index + 1] = Source[Index]; + Destination[Index] = Temp; + } +} + +// +// ReleaseIdeResources +// +VOID +ReleaseIdeResources ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice + ) +/*++ +Routing Description: + + Release resources of an IDE device before stopping it. + +Arguments: + + IdeBlkIoDevice -- Standard IDE device private data structure + + +Returns: + + NONE + +---*/ +// TODO: function comment is missing 'Routine Description:' +{ + if (IdeBlkIoDevice == NULL) { + return ; + } + + // + // Release all the resourses occupied by the IDE_BLK_IO_DEV + // + + if (IdeBlkIoDevice->SenseData != NULL) { + gBS->FreePool (IdeBlkIoDevice->SenseData); + IdeBlkIoDevice->SenseData = NULL; + } + + if (IdeBlkIoDevice->Cache != NULL) { + gBS->FreePool (IdeBlkIoDevice->Cache); + IdeBlkIoDevice->Cache = NULL; + } + + if (IdeBlkIoDevice->pIdData != NULL) { + gBS->FreePool (IdeBlkIoDevice->pIdData); + IdeBlkIoDevice->pIdData = NULL; + } + + if (IdeBlkIoDevice->pInquiryData != NULL) { + gBS->FreePool (IdeBlkIoDevice->pInquiryData); + IdeBlkIoDevice->pInquiryData = NULL; + } + + if (IdeBlkIoDevice->ControllerNameTable != NULL) { + FreeUnicodeStringTable (IdeBlkIoDevice->ControllerNameTable); + IdeBlkIoDevice->ControllerNameTable = NULL; + } + + if (IdeBlkIoDevice->IoPort != NULL) { + gBS->FreePool (IdeBlkIoDevice->IoPort); + } + + if (IdeBlkIoDevice->DevicePath != NULL) { + gBS->FreePool (IdeBlkIoDevice->DevicePath); + } + + gBS->FreePool (IdeBlkIoDevice); + IdeBlkIoDevice = NULL; + + return ; +} + +// +// SetDeviceTransferMode +// +EFI_STATUS +SetDeviceTransferMode ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATA_TRANSFER_MODE *TransferMode + ) +/*++ +Routing Description: + + Set the calculated Best transfer mode to a detected device + +Arguments: + + IdeDev -- Standard IDE device private data structure + TransferMode -- The device transfer mode to be set + +Returns: + + Set transfer mode Command execute status + +---*/ +// TODO: function comment is missing 'Routine Description:' +{ + EFI_STATUS Status; + UINT8 DeviceSelect; + UINT8 SectorCount; + + DeviceSelect = 0; + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + SectorCount = *((UINT8 *) TransferMode); + + // + // Send SET FEATURE command (sub command 0x03) to set pio mode. + // + Status = AtaNonDataCommandIn ( + IdeDev, + SET_FEATURES_CMD, + DeviceSelect, + 0x03, + SectorCount, + 0, + 0, + 0 + ); + + return Status; +} + +EFI_STATUS +AtaNonDataCommandIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT8 Feature, + IN UINT8 SectorCount, + IN UINT8 LbaLow, + IN UINT8 LbaMiddle, + IN UINT8 LbaHigh + ) +/*++ + +Routine Description: + + Send ATA command into device with NON_DATA protocol + +Arguments: + + IdeDev - Standard IDE device private data structure + AtaCommand - The ATA command to be sent + Device - The value in Device register + Feature - The value in Feature register + SectorCount - The value in SectorCount register + LbaLow - The value in LBA_LOW register + LbaMiddle - The value in LBA_MIDDLE register + LbaHigh - The value in LBA_HIGH register + +Returns: + + EFI_SUCCESS - Reading succeed + EFI_ABORTED - Command failed + EFI_DEVICE_ERROR - Device status error + +--*/ +{ + EFI_STATUS Status; + UINT8 StatusRegister; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMiddle); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + // + // Wait for command completion + // + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + if ((StatusRegister & ERR) == ERR) { + // + // Failed to execute command, abort operation + // + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AtaNonDataCommandInExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ) +/*++ + +Routine Description: + + Send ATA Ext command into device with NON_DATA protocol + +Arguments: + + IdeDev - Standard IDE device private data structure + AtaCommand - The ATA command to be sent + Device - The value in Device register + Feature - The value in Feature register + SectorCount - The value in SectorCount register + LbaAddress - The LBA address in 48-bit mode + +Returns: + + EFI_SUCCESS - Reading succeed + EFI_ABORTED - Command failed + EFI_DEVICE_ERROR - Device status error + +--*/ +{ + EFI_STATUS Status; + UINT8 StatusRegister; + UINT8 SectorCount8; + UINT8 Feature8; + UINT8 LbaLow; + UINT8 LbaMid; + UINT8 LbaHigh; + + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Select device (bit4), set LBA mode(bit6) (use 0xe0 for compatibility) + // + IDEWritePortB ( + IdeDev->PciIo, + IdeDev->IoPort->Head, + (UINT8) ((IdeDev->Device << 4) | 0xe0) + ); + + // + // ATA commands for ATA device must be issued when DRDY is set + // + Status = DRDYReady (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Pass parameter into device register block + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Head, Device); + + // + // Fill the feature register, which is a two-byte FIFO. Need write twice. + // + Feature8 = (UINT8) (Feature >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + Feature8 = (UINT8) Feature; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg1.Feature, Feature8); + + // + // Fill the sector count register, which is a two-byte FIFO. Need write twice. + // + SectorCount8 = (UINT8) (SectorCount >> 8); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + SectorCount8 = (UINT8) SectorCount; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorCount, SectorCount8); + + // + // Fill the start LBA registers, which are also two-byte FIFO + // + LbaLow = (UINT8) RShiftU64 (LbaAddress, 24); + LbaMid = (UINT8) RShiftU64 (LbaAddress, 32); + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 40); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + LbaLow = (UINT8) LbaAddress; + LbaMid = (UINT8) RShiftU64 (LbaAddress, 8); + LbaHigh = (UINT8) RShiftU64 (LbaAddress, 16); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->SectorNumber, LbaLow); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderLsb, LbaMid); + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->CylinderMsb, LbaHigh); + + // + // Send command via Command Register + // + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Command, AtaCommand); + + // + // Wait for command completion + // + Status = WaitForBSYClear (IdeDev, ATATIMEOUT); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + StatusRegister = IDEReadPortB (IdeDev->PciIo, IdeDev->IoPort->Reg.Status); + if ((StatusRegister & ERR) == ERR) { + // + // Failed to execute command, abort operation + // + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +// +// SetDriveParameters +// +EFI_STATUS +SetDriveParameters ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATA_DRIVE_PARMS *DriveParameters + ) +/*++ +Routine Description: + + Set drive parameters for devices not support PACKETS command + +Arguments: + + IdeDev -- Standard IDE device private data structure + DriveParameters -- The device parameters to be set into the disk + +Returns: + + SetParameters Command execute status + +--*/ +{ + EFI_STATUS Status; + UINT8 DeviceSelect; + + DeviceSelect = 0; + DeviceSelect = (UINT8) ((IdeDev->Device) << 4); + + // + // Send Init drive parameters + // + Status = AtaPioDataIn ( + IdeDev, + NULL, + 0, + INIT_DRIVE_PARAM_CMD, + (UINT8) (DeviceSelect + DriveParameters->Heads), + DriveParameters->Sector, + 0, + 0, + 0 + ); + + // + // Send Set Multiple parameters + // + Status = AtaPioDataIn ( + IdeDev, + NULL, + 0, + SET_MULTIPLE_MODE_CMD, + DeviceSelect, + DriveParameters->MultipleSector, + 0, + 0, + 0 + ); + + return Status; +} + +EFI_STATUS +EnableInterrupt ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + UINT8 DeviceControl; + + // + // Enable interrupt for DMA operation + // + DeviceControl = 0; + IDEWritePortB (IdeDev->PciIo, IdeDev->IoPort->Alt.DeviceControl, DeviceControl); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h new file mode 100644 index 0000000000..4c43ab94cd --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/ide.h @@ -0,0 +1,1806 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + ide.h + +Abstract: + + Header file for IDE Bus Driver, containing the helper functions' + entire prototype. + +Revision History + + 2002-6: Add Atapi6 enhancement, support >120GB hard disk, including + Add - IDEBlkIoReadBlocksExt() func definition + Add - IDEBlkIoWriteBlocksExt() func definition + +++*/ + +// TODO: fix comment to end with --*/ +#ifndef _IDE_H +#define _IDE_H + +// +// Helper functions Prototype +// +EFI_STATUS +DeRegisterIdeDevice ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_HANDLE Handle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Controller - TODO: add argument description + Handle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EnableIdeDevice ( + IN EFI_HANDLE Controller, + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + PciIo - TODO: add argument description + ParentDevicePath - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +UINT8 +IDEReadPortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +IDEReadPortWMultiple ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINTN Count, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + Count - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +IDEWritePortB ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT8 Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +IDEWritePortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINT16 Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +IDEWritePortWMultiple ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT16 Port, + IN UINTN Count, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Port - TODO: add argument description + Count - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetIdeRegistersBaseAddr ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + OUT IDE_REGISTERS_BASE_ADDR *IdeRegsBaseAddr + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + IdeRegsBaseAddr - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ReassignIdeResources ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DiscoverIdeDevice ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DetectIDEController ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DRQClear ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + TimeoutInMilliSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DRQClear2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + TimeoutInMilliSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DRQReady ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + TimeoutInMilliSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DRQReady2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + TimeoutInMilliSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +WaitForBSYClear ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + TimeoutInMilliSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +WaitForBSYClear2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN TimeoutInMilliSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + TimeoutInMilliSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DRDYReady ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN DelayInMilliSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + DelayInMilliSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DRDYReady2 ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINTN DelayInMilliSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + DelayInMilliSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +SwapStringChars ( + IN CHAR8 *Destination, + IN CHAR8 *Source, + IN UINT32 Size + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Destination - TODO: add argument description + Source - TODO: add argument description + Size - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// ATA device functions' prototype +// +EFI_STATUS +ATAIdentify ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +PrintAtaModuleName ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaPioDataIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN UINT8 Head, + IN UINT8 SectorCount, + IN UINT8 SectorNumber, + IN UINT8 CylinderLsb, + IN UINT8 CylinderMsb + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + Buffer - TODO: add argument description + ByteCount - TODO: add argument description + AtaCommand - TODO: add argument description + Head - TODO: add argument description + SectorCount - TODO: add argument description + SectorNumber - TODO: add argument description + CylinderLsb - TODO: add argument description + CylinderMsb - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaPioDataOut ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN UINT8 Head, + IN UINT8 SectorCount, + IN UINT8 SectorNumber, + IN UINT8 CylinderLsb, + IN UINT8 CylinderMsb + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + Buffer - TODO: add argument description + ByteCount - TODO: add argument description + AtaCommand - TODO: add argument description + Head - TODO: add argument description + SectorCount - TODO: add argument description + SectorNumber - TODO: add argument description + CylinderLsb - TODO: add argument description + CylinderMsb - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CheckErrorStatus ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaReadSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + DataBuffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaWriteSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *BufferData, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + BufferData - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaSoftReset ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaBlkIoReadBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeBlkIoDevice - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaBlkIoWriteBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeBlkIoDevice - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// ATAPI device functions' prototype +// +EFI_STATUS +ATAPIIdentify ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiInquiry ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiPacketCommandIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATAPI_PACKET_COMMAND *Packet, + IN UINT16 *Buffer, + IN UINT32 ByteCount, + IN UINTN TimeOut + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + Packet - TODO: add argument description + Buffer - TODO: add argument description + ByteCount - TODO: add argument description + TimeOut - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiPacketCommandOut ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATAPI_PACKET_COMMAND *Packet, + IN UINT16 *Buffer, + IN UINT32 ByteCount, + IN UINTN TimeOut + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + Packet - TODO: add argument description + Buffer - TODO: add argument description + ByteCount - TODO: add argument description + TimeOut - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PioReadWriteData ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT16 *Buffer, + IN UINT32 ByteCount, + IN BOOLEAN Read, + IN UINTN TimeOut + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + Buffer - TODO: add argument description + ByteCount - TODO: add argument description + Read - TODO: add argument description + TimeOut - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiTestUnitReady ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiRequestSense ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT UINTN *SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiReadCapacity ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiDetectMedia ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT BOOLEAN *MediaChange + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + MediaChange - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiReadSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + Buffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiWriteSectors ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + Buffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiSoftReset ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiBlkIoReadBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeBlkIoDevice - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtapiBlkIoWriteBlocks ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeBlkIoDevice - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsNoMedia ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsMediaError ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsMediaChange ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsDriveReady ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts, + OUT BOOLEAN *NeedRetry + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + NeedRetry - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +HaveSenseKey ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +IsLS120orZipWriteProtected ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT BOOLEAN *WriteProtected + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + WriteProtected - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +ReleaseIdeResources ( + IN IDE_BLK_IO_DEV *IdeBlkIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeBlkIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SetDeviceTransferMode ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATA_TRANSFER_MODE *TransferMode + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + TransferMode - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ReadNativeMaxAddress ( + IN IDE_BLK_IO_DEV *IdeDev, + OUT EFI_LBA *NativeMaxAddress + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + NativeMaxAddress - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SetMaxAddress ( + IN IDE_BLK_IO_DEV *IdeDev, + IN EFI_LBA MaxAddress, + IN BOOLEAN bVolatile + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + MaxAddress - TODO: add argument description + bVolatile - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaNonDataCommandIn ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT8 Feature, + IN UINT8 SectorCount, + IN UINT8 LbaLow, + IN UINT8 LbaMiddle, + IN UINT8 LbaHigh + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + AtaCommand - TODO: add argument description + Device - TODO: add argument description + Feature - TODO: add argument description + SectorCount - TODO: add argument description + LbaLow - TODO: add argument description + LbaMiddle - TODO: add argument description + LbaHigh - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaNonDataCommandInExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + AtaCommand - TODO: add argument description + Device - TODO: add argument description + Feature - TODO: add argument description + SectorCount - TODO: add argument description + LbaAddress - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaReadSectorsExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + DataBuffer - TODO: add argument description + StartLba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaWriteSectorsExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + DataBuffer - TODO: add argument description + StartLba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaUdmaReadExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + DataBuffer - TODO: add argument description + StartLba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaUdmaRead ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + DataBuffer - TODO: add argument description + StartLba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaUdmaWriteExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + DataBuffer - TODO: add argument description + StartLba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaUdmaWrite ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *DataBuffer, + IN EFI_LBA StartLba, + IN UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + DataBuffer - TODO: add argument description + StartLba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaCommandIssueExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + AtaCommand - TODO: add argument description + Device - TODO: add argument description + Feature - TODO: add argument description + SectorCount - TODO: add argument description + LbaAddress - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaCommandIssue ( + IN IDE_BLK_IO_DEV *IdeDev, + IN UINT8 AtaCommand, + IN UINT8 Device, + IN UINT16 Feature, + IN UINT16 SectorCount, + IN EFI_LBA LbaAddress + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + AtaCommand - TODO: add argument description + Device - TODO: add argument description + Feature - TODO: add argument description + SectorCount - TODO: add argument description + LbaAddress - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaAtapi6Identify ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + + +VOID +AtaSMARTSupport ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaPioDataInExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN OUT VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN EFI_LBA StartLba, + IN UINT16 SectorCount + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + Buffer - TODO: add argument description + ByteCount - TODO: add argument description + AtaCommand - TODO: add argument description + StartLba - TODO: add argument description + SectorCount - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AtaPioDataOutExt ( + IN IDE_BLK_IO_DEV *IdeDev, + IN VOID *Buffer, + IN UINT32 ByteCount, + IN UINT8 AtaCommand, + IN EFI_LBA StartLba, + IN UINT16 SectorCount + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + Buffer - TODO: add argument description + ByteCount - TODO: add argument description + AtaCommand - TODO: add argument description + StartLba - TODO: add argument description + SectorCount - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SetDriveParameters ( + IN IDE_BLK_IO_DEV *IdeDev, + IN ATA_DRIVE_PARMS *DriveParameters + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + DriveParameters - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EnableInterrupt ( + IN IDE_BLK_IO_DEV *IdeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IdeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.c b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.c new file mode 100644 index 0000000000..2b8f52aa54 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.c @@ -0,0 +1,1400 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + idebus.c + +Abstract: + + +Revision History + This module is modified from DXE\IDE module for Ide Contriller Init support + +--*/ + +#include "idebus.h" + +#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_SUB_CLASS_IDE 0x01 + + +// +// IDE Bus Driver Binding Protocol Instance +// +EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding = { + IDEBusDriverBindingSupported, + IDEBusDriverBindingStart, + IDEBusDriverBindingStop, + 0x10, + NULL, + NULL +}; + +// +// *********************************************************************************** +// IDEBusDriverBindingSupported +// *********************************************************************************** +// +EFI_STATUS +EFIAPI +IDEBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Register Driver Binding protocol for this driver. + +Arguments: + This -- A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + ControllerHandle -- The handle of the controller to test. + RemainingDevicePath -- A pointer to the remaining portion of a device path. + +Returns: + EFI_SUCCESS - Driver loaded. + other - Driver not loaded. +--*/ +// TODO: Controller - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_DEV_PATH *Node; + EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit; + + if (RemainingDevicePath != NULL) { + Node = (EFI_DEV_PATH *) RemainingDevicePath; + if (Node->DevPath.Type != MESSAGING_DEVICE_PATH || + Node->DevPath.SubType != MSG_ATAPI_DP || + DevicePathNodeLength(&Node->DevPath) != sizeof(ATAPI_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Clsoe protocol, don't use device path protocol in the .Support() function + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Verify the Ide Controller Init Protocol, which installed by the + // IdeController module. + // Note 1: PciIo protocol has been opened BY_DRIVER by ide_init, so We can't + // open BY_DRIVER here) That's why we don't check pciio protocol + // Note 2: ide_init driver check ide controller's pci config space, so we dont + // check here any more to save code size + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIdeControllerInitProtocolGuid, + (VOID **) &IdeInit, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + // + // If protocols were opened normally, closed it + // + gBS->CloseProtocol ( + Controller, + &gEfiIdeControllerInitProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +// +// *********************************************************************************** +// IDEBusDriverBindingStart +// *********************************************************************************** +// +EFI_STATUS +EFIAPI +IDEBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Start this driver on Controller by detecting all disks and installing + BlockIo protocol on them. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to bind driver to. + RemainingDevicePath - Not used, always produce all possible children. + + Returns: + EFI_SUCCESS - This driver is added to ControllerHandle. + EFI_ALREADY_STARTED - This driver is already running on ControllerHandle. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS SavedStatus; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_DEV_PATH *Node; + UINT8 IdeChannel; + UINT8 BeginningIdeChannel; + UINT8 EndIdeChannel; + UINT8 IdeDevice; + UINT8 BeginningIdeDevice; + UINT8 EndIdeDevice; + IDE_BLK_IO_DEV *IdeBlkIoDevice[IdeMaxChannel][IdeMaxDevice]; + IDE_BLK_IO_DEV *IdeBlkIoDevicePtr; + IDE_REGISTERS_BASE_ADDR IdeRegsBaseAddr[IdeMaxChannel]; + ATA_TRANSFER_MODE TransferMode; + ATA_DRIVE_PARMS DriveParameters; + EFI_DEV_PATH NewNode; + UINT8 ConfigurationOptions; + UINT16 CommandBlockBaseAddr; + UINT16 ControlBlockBaseAddr; + UINTN DataSize; + UINT32 Attributes; + IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; + + // + // Local variables declaration for IdeControllerInit support + // + EFI_IDE_CONTROLLER_INIT_PROTOCOL *IdeInit; + BOOLEAN EnumAll; + BOOLEAN ChannelEnabled; + UINT8 ChannelCount; + UINT8 MaxDevices; + EFI_IDENTIFY_DATA IdentifyData; + EFI_ATA_COLLECTIVE_MODE *SupportedModes; + + IdeBusDriverPrivateData = NULL; + SupportedModes = NULL; + + // + // Perform IdeBus initialization + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { + return Status; + } + + // + // Now open the IDE_CONTROLLER_INIT protocol. Step7.1 + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiIdeControllerInitProtocolGuid, + (VOID **) &IdeInit, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + // + // The following OpenProtocol function with _GET_PROTOCOL attribute and + // will not return EFI_ALREADY_STARTED, so save it for now + // + SavedStatus = Status; + + if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) { + DEBUG ((EFI_D_ERROR, "Open Init, Status=%x", Status)); + // + // open protocol is not SUCCESS or not ALREADY_STARTED, error exit + // + goto ErrorExit; + } + + // + // Save Enumall and ChannelCount. Step7.2 + // + EnumAll = IdeInit->EnumAll; + ChannelCount = IdeInit->ChannelCount; + + // + // Consume PCI I/O protocol. Note that the OpenProtocol with _GET_PROTOCOL + // attribute will not return EFI_ALREADY_STARTED + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Open PciIo, Status=%x", Status)); + goto ErrorExit; + } + + // + // We must check EFI_ALREADY_STARTED because many ATAPI devices are removable + // + if (SavedStatus != EFI_ALREADY_STARTED) { + IdeBusDriverPrivateData = AllocatePool (sizeof (IDE_BUS_DRIVER_PRIVATE_DATA)); + if (IdeBusDriverPrivateData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + ZeroMem (IdeBusDriverPrivateData, sizeof (IDE_BUS_DRIVER_PRIVATE_DATA)); + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiCallerIdGuid, + IdeBusDriverPrivateData, + NULL + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + } else { + Status = gBS->OpenProtocol ( + Controller, + &gEfiCallerIdGuid, + (VOID **) &IdeBusDriverPrivateData, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + IdeBusDriverPrivateData = NULL; + goto ErrorExit; + } + } + + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + // + // Read the environment variable that contains the IDEBus Driver's + // Config options that were set by the Driver Configuration Protocol + // + DataSize = sizeof (ConfigurationOptions); + Status = gRT->GetVariable ( + (CHAR16 *) L"Configuration", + &gEfiCallerIdGuid, + &Attributes, + &DataSize, + &ConfigurationOptions + ); + if (EFI_ERROR (Status)) { + ConfigurationOptions = 0x0f; + } + + if (EnumAll) { + // + // If IdeInit->EnumAll is TRUE, must enumerate all IDE device anyway + // + BeginningIdeChannel = IdePrimary; + EndIdeChannel = IdeSecondary; + BeginningIdeDevice = IdeMaster; + EndIdeDevice = IdeSlave; + } else if (RemainingDevicePath == NULL) { + // + // RemainingDevicePath is NULL, scan IDE bus for each device; + // + BeginningIdeChannel = IdePrimary; + EndIdeChannel = IdeSecondary; + BeginningIdeDevice = IdeMaster; + // + // default, may be redefined by IdeInit + // + EndIdeDevice = IdeSlave; + } else { + // + // RemainingDevicePath is not NULL, only scan the specified device. + // + Node = (EFI_DEV_PATH *) RemainingDevicePath; + BeginningIdeChannel = Node->Atapi.PrimarySecondary; + EndIdeChannel = BeginningIdeChannel; + BeginningIdeDevice = Node->Atapi.SlaveMaster; + EndIdeDevice = BeginningIdeDevice; + } + + // + // Obtain IDE IO port registers' base addresses + // + Status = GetIdeRegistersBaseAddr (PciIo, IdeRegsBaseAddr); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + // + // Report status code: begin IdeBus initialization + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_PC_RESET), + ParentDevicePath + ); + + // + // Strictly follow the enumeration based on IDE_CONTROLLER_INIT protocol + // + for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) { + + IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelEnumeration, IdeChannel); + + // + // now obtain channel information fron IdeControllerInit protocol. Step9 + // + Status = IdeInit->GetChannelInfo ( + IdeInit, + IdeChannel, + &ChannelEnabled, + &MaxDevices + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[GetChannel, Status=%x]", Status)); + continue; + } + + if (!ChannelEnabled) { + continue; + } + + EndIdeDevice = (UINT8) EFI_MIN ((MaxDevices - 1), EndIdeDevice); + + // + // Now inform the IDE Controller Init Module. Sept10 + // + IdeInit->NotifyPhase (IdeInit, EfiIdeBeforeChannelReset, IdeChannel); + + // + // No reset channel function implemented. Sept11 + // + IdeInit->NotifyPhase (IdeInit, EfiIdeAfterChannelReset, IdeChannel); + + // + // Step13 + // + IdeInit->NotifyPhase ( + IdeInit, + EfiIdeBusBeforeDevicePresenceDetection, + IdeChannel + ); + // + // -- 1st inner loop --- Master/Slave ------------ Step14 + // + for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) { + // + // Check whether the configuration options allow this device + // + if (!(ConfigurationOptions & (1 << (IdeChannel * 2 + IdeDevice)))) { + continue; + } + + // + // The device has been scanned in another Start(), No need to scan it again + // for perf optimization. + // + if (IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice]) { + continue; + } + + // + // create child handle for the detected device. + // + IdeBlkIoDevice[IdeChannel][IdeDevice] = AllocatePool (sizeof (IDE_BLK_IO_DEV)); + if (IdeBlkIoDevice[IdeChannel][IdeDevice] == NULL) { + continue; + } + + IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; + + ZeroMem (IdeBlkIoDevicePtr, sizeof (IDE_BLK_IO_DEV)); + + IdeBlkIoDevicePtr->Signature = IDE_BLK_IO_DEV_SIGNATURE; + IdeBlkIoDevicePtr->Channel = IdeChannel; + IdeBlkIoDevicePtr->Device = IdeDevice; + + // + // initialize Block IO interface's Media pointer + // + IdeBlkIoDevicePtr->BlkIo.Media = &IdeBlkIoDevicePtr->BlkMedia; + + // + // Initialize IDE IO port addresses, including Command Block registers + // and Control Block registers + // + IdeBlkIoDevicePtr->IoPort = AllocatePool (sizeof (IDE_BASE_REGISTERS)); + if (IdeBlkIoDevicePtr->IoPort == NULL) { + continue; + } + + ZeroMem (IdeBlkIoDevicePtr->IoPort, sizeof (IDE_BASE_REGISTERS)); + CommandBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].CommandBlockBaseAddr; + ControlBlockBaseAddr = IdeRegsBaseAddr[IdeChannel].ControlBlockBaseAddr; + + IdeBlkIoDevicePtr->IoPort->Data = CommandBlockBaseAddr; + (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg1) = (UINT16) (CommandBlockBaseAddr + 0x01); + IdeBlkIoDevicePtr->IoPort->SectorCount = (UINT16) (CommandBlockBaseAddr + 0x02); + IdeBlkIoDevicePtr->IoPort->SectorNumber = (UINT16) (CommandBlockBaseAddr + 0x03); + IdeBlkIoDevicePtr->IoPort->CylinderLsb = (UINT16) (CommandBlockBaseAddr + 0x04); + IdeBlkIoDevicePtr->IoPort->CylinderMsb = (UINT16) (CommandBlockBaseAddr + 0x05); + IdeBlkIoDevicePtr->IoPort->Head = (UINT16) (CommandBlockBaseAddr + 0x06); + (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Reg) = (UINT16) (CommandBlockBaseAddr + 0x07); + + (*(UINT16 *) &IdeBlkIoDevicePtr->IoPort->Alt) = ControlBlockBaseAddr; + IdeBlkIoDevicePtr->IoPort->DriveAddress = (UINT16) (ControlBlockBaseAddr + 0x01); + + IdeBlkIoDevicePtr->IoPort->MasterSlave = (UINT16) ((IdeDevice == IdeMaster) ? 1 : 0); + + IdeBlkIoDevicePtr->PciIo = PciIo; + IdeBlkIoDevicePtr->IdeBusDriverPrivateData = IdeBusDriverPrivateData; + IdeBlkIoDevicePtr->IoPort->BusMasterBaseAddr = IdeRegsBaseAddr[IdeChannel].BusMasterBaseAddr; + + // + // Report Status code: is about to detect IDE drive + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_PRESENCE_DETECT), + IdeBlkIoDevicePtr->DevicePath + ); + + // + // Discover device, now! + // + PERF_START (0, "DiscoverIdeDevice", "IDE", 0); + Status = DiscoverIdeDevice (IdeBlkIoDevicePtr); + PERF_END (0, "DiscoverIdeDevice", "IDE", 0); + + IdeBusDriverPrivateData->HaveScannedDevice[IdeChannel * 2 + IdeDevice] = TRUE; + IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = FALSE; + + if (!EFI_ERROR (Status)) { + // + // Set Device Path + // + ZeroMem (&NewNode, sizeof (NewNode)); + NewNode.DevPath.Type = MESSAGING_DEVICE_PATH; + NewNode.DevPath.SubType = MSG_ATAPI_DP; + SetDevicePathNodeLength (&NewNode.DevPath, sizeof (ATAPI_DEVICE_PATH)); + + NewNode.Atapi.PrimarySecondary = (UINT8) IdeBlkIoDevicePtr->Channel; + NewNode.Atapi.SlaveMaster = (UINT8) IdeBlkIoDevicePtr->Device; + NewNode.Atapi.Lun = IdeBlkIoDevicePtr->Lun; + IdeBlkIoDevicePtr->DevicePath = AppendDevicePathNode ( + ParentDevicePath, + &NewNode.DevPath + ); + if (IdeBlkIoDevicePtr->DevicePath == NULL) { + ReleaseIdeResources (IdeBlkIoDevicePtr); + continue; + } + + // + // Submit identify data to IDE controller init driver + // + CopyMem (&IdentifyData, IdeBlkIoDevicePtr->pIdData, sizeof (IdentifyData)); + // IdentifyData = *IdeBlkIoDevicePtr->pIdData; + IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = TRUE; + IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, &IdentifyData); + } else { + // + // Device detection failed + // + IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; + IdeInit->SubmitData (IdeInit, IdeChannel, IdeDevice, NULL); + ReleaseIdeResources (IdeBlkIoDevicePtr); + IdeBlkIoDevicePtr = NULL; + } + // + // end of 1st inner loop --- + // + } + // + // end of 1st outer loop ========= + // + } + + // + // = 2nd outer loop == Primary/Secondary ================= + // + for (IdeChannel = BeginningIdeChannel; IdeChannel <= EndIdeChannel; IdeChannel++) { + + // + // -- 2nd inner loop --- Master/Slave -------- + // + for (IdeDevice = BeginningIdeDevice; IdeDevice <= EndIdeDevice; IdeDevice++) { + + if (IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice]) { + continue; + } + + if (!IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice]) { + continue; + } + + Status = IdeInit->CalculateMode ( + IdeInit, + IdeChannel, + IdeDevice, + &SupportedModes + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "[bStStp20S=%x]", Status)); + continue; + } + + IdeBlkIoDevicePtr = IdeBlkIoDevice[IdeChannel][IdeDevice]; + + // + // Set best supported PIO mode on this IDE device + // + if (SupportedModes->PioMode.Mode <= ATA_PIO_MODE_2) { + TransferMode.ModeCategory = ATA_MODE_CATEGORY_DEFAULT_PIO; + } else { + TransferMode.ModeCategory = ATA_MODE_CATEGORY_FLOW_PIO; + } + + TransferMode.ModeNumber = (UINT8) (SupportedModes->PioMode.Mode); + + if (SupportedModes->ExtModeCount == 0){ + Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); + + if (EFI_ERROR (Status)) { + IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; + ReleaseIdeResources (IdeBlkIoDevicePtr); + IdeBlkIoDevicePtr = NULL; + continue; + } + } + + // + // Set supported DMA mode on this IDE device. Note that UDMA & MDMA cann't + // be set together. Only one DMA mode can be set to a device. If setting + // DMA mode operation fails, we can continue moving on because we only use + // PIO mode at boot time. DMA modes are used by certain kind of OS booting + // + if (SupportedModes->UdmaMode.Valid) { + + TransferMode.ModeCategory = ATA_MODE_CATEGORY_UDMA; + TransferMode.ModeNumber = (UINT8) (SupportedModes->UdmaMode.Mode); + Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); + + if (EFI_ERROR (Status)) { + IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; + ReleaseIdeResources (IdeBlkIoDevicePtr); + IdeBlkIoDevicePtr = NULL; + continue; + } + + EnableInterrupt (IdeBlkIoDevicePtr); + } else if (SupportedModes->MultiWordDmaMode.Valid) { + + TransferMode.ModeCategory = ATA_MODE_CATEGORY_MDMA; + TransferMode.ModeNumber = (UINT8) SupportedModes->MultiWordDmaMode.Mode; + Status = SetDeviceTransferMode (IdeBlkIoDevicePtr, &TransferMode); + + if (EFI_ERROR (Status)) { + IdeBusDriverPrivateData->DeviceFound[IdeChannel * 2 + IdeDevice] = FALSE; + ReleaseIdeResources (IdeBlkIoDevicePtr); + IdeBlkIoDevicePtr = NULL; + continue; + } + + EnableInterrupt (IdeBlkIoDevicePtr); + } + // + // Init driver parameters + // + DriveParameters.Sector = (UINT8) IdeBlkIoDevicePtr->pIdData->AtaData.sectors_per_track; + DriveParameters.Heads = (UINT8) (IdeBlkIoDevicePtr->pIdData->AtaData.heads - 1); + DriveParameters.MultipleSector = (UINT8) IdeBlkIoDevicePtr->pIdData->AtaData.multi_sector_cmd_max_sct_cnt; + // + // Set Parameters for the device: + // 1) Init + // 2) Establish the block count for READ/WRITE MULTIPLE (EXT) command + // + if ((IdeBlkIoDevicePtr->Type == IdeHardDisk) || (IdeBlkIoDevicePtr->Type == Ide48bitAddressingHardDisk)) { + Status = SetDriveParameters (IdeBlkIoDevicePtr, &DriveParameters); + } + + // + // Record PIO mode used in private data + // + IdeBlkIoDevicePtr->PioMode = SupportedModes->PioMode.Mode; + + // + // Set IDE controller Timing Blocks in the PCI Configuration Space + // + IdeInit->SetTiming (IdeInit, IdeChannel, IdeDevice, SupportedModes); + + // + // Add Component Name for the IDE/ATAPI device that was discovered. + // + IdeBlkIoDevicePtr->ControllerNameTable = NULL; + ADD_NAME (IdeBlkIoDevicePtr); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &IdeBlkIoDevicePtr->Handle, + &gEfiDevicePathProtocolGuid, + IdeBlkIoDevicePtr->DevicePath, + &gEfiBlockIoProtocolGuid, + &IdeBlkIoDevicePtr->BlkIo, + &gEfiDiskInfoProtocolGuid, + &IdeBlkIoDevicePtr->DiskInfo, + NULL + ); + + if (EFI_ERROR (Status)) { + ReleaseIdeResources (IdeBlkIoDevicePtr); + } + + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + IdeBlkIoDevicePtr->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + + IdeBusDriverPrivateData->DeviceProcessed[IdeChannel * 2 + IdeDevice] = TRUE; + + // + // Report status code: device eanbled! + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_ENABLE), + IdeBlkIoDevicePtr->DevicePath + ); + // + // end of 2nd inner loop ---- + // + } + // + // end of 2nd outer loop ========== + // + } + + // + // All configurations done! Notify IdeController to do post initialization + // work such as saving IDE controller PCI settings for S3 resume + // + IdeInit->NotifyPhase (IdeInit, EfiIdeBusPhaseMaximum, 0); + + if (SupportedModes != NULL) { + gBS->FreePool (SupportedModes); + } + + PERF_START (0, "Finish IDE detection", "IDE", 1); + PERF_END (0, "Finish IDE detection", "IDE", 0); + + return EFI_SUCCESS; + +ErrorExit: + + // + // Report error code: controller error + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_IO_BUS_ATA_ATAPI | EFI_IOB_EC_CONTROLLER_ERROR), + ParentDevicePath + ); + + gBS->CloseProtocol ( + Controller, + &gEfiIdeControllerInitProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiCallerIdGuid, + IdeBusDriverPrivateData, + NULL + ); + + if (IdeBusDriverPrivateData != NULL) { + gBS->FreePool (IdeBusDriverPrivateData); + } + + if (SupportedModes != NULL) { + gBS->FreePool (SupportedModes); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; + +} + +// +// *********************************************************************************** +// IDEBusDriverBindingStop +// *********************************************************************************** +// +EFI_STATUS +EFIAPI +IDEBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on Controller Handle. + + Arguments: + This - Protocol instance pointer. + DeviceHandle - Handle of device to stop driver on + NumberOfChildren - Not used + ChildHandleBuffer - Not used + + Returns: + EFI_SUCCESS - This driver is removed DeviceHandle + other - This driver was not removed from this device + +--*/ +// TODO: Controller - add argument and description to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + BOOLEAN AllChildrenStopped; + UINTN Index; + IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; + + IdeBusDriverPrivateData = NULL; + + if (NumberOfChildren == 0) { + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO | EFI_PCI_DEVICE_ENABLE, + NULL + ); + } + + gBS->OpenProtocol ( + Controller, + &gEfiCallerIdGuid, + (VOID **) &IdeBusDriverPrivateData, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiCallerIdGuid, + IdeBusDriverPrivateData, + NULL + ); + + if (IdeBusDriverPrivateData != NULL) { + gBS->FreePool (IdeBusDriverPrivateData); + } + // + // Close the bus driver + // + gBS->CloseProtocol ( + Controller, + &gEfiIdeControllerInitProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = DeRegisterIdeDevice (This, Controller, ChildHandleBuffer[Index]); + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +// +// *********************************************************************************** +// DeRegisterIdeDevice +// *********************************************************************************** +// +EFI_STATUS +DeRegisterIdeDevice ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_HANDLE Handle + ) +/*++ + +Routine Description: + + Deregister an IDE device and free resources + +Arguments: + + This - Protocol instance pointer. + Controller - Ide device handle + Handle - Handle of device to deregister driver on + +Returns: + + EFI_STATUS + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + IDE_BLK_IO_DEV *IdeBlkIoDevice; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Index; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo); + + // + // Report Status code: Device disabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_IO_BUS_ATA_ATAPI | EFI_P_PC_DISABLE), + IdeBlkIoDevice->DevicePath + ); + + // + // Close the child handle + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Handle, + &gEfiDevicePathProtocolGuid, + IdeBlkIoDevice->DevicePath, + &gEfiBlockIoProtocolGuid, + &IdeBlkIoDevice->BlkIo, + &gEfiDiskInfoProtocolGuid, + &IdeBlkIoDevice->DiskInfo, + NULL + ); + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + return Status; + } + + // + // Release allocated resources + // + Index = IdeBlkIoDevice->Channel * 2 + IdeBlkIoDevice->Device; + IdeBlkIoDevice->IdeBusDriverPrivateData->HaveScannedDevice[Index] = FALSE; + + ReleaseIdeResources (IdeBlkIoDevice); + + return EFI_SUCCESS; +} + +// +// *********************************************************************************** +// IDEBlkIoReset +// *********************************************************************************** +// +EFI_STATUS +EFIAPI +IDEBlkIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: ExtendedVerification - add argument and description to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + EFI_STATUS Status; + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); + // + // Requery IDE IO resources in case of the switch of native and legacy modes + // + ReassignIdeResources (IdeBlkIoDevice); + + // + // for ATA device, using ATA reset method + // + if (IdeBlkIoDevice->Type == IdeHardDisk) { + return AtaSoftReset (IdeBlkIoDevice); + } + + if (IdeBlkIoDevice->Type == IdeUnknown) { + return EFI_DEVICE_ERROR; + } + + // + // for ATAPI device, using ATAPI reset method + // + Status = AtapiSoftReset (IdeBlkIoDevice); + if (ExtendedVerification) { + Status = AtaSoftReset (IdeBlkIoDevice); + } + + return Status; +} + +EFI_STATUS +EFIAPI +IDEBlkIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Read data from block io device + +Arguments: + + This - Protocol instance pointer. + MediaId - The media ID of the device + LBA - Starting LBA address to read data + BufferSize - The size of data to be read + Buffer - Caller supplied buffer to save data + +Returns: + + read data status + +--*/ +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); + + // + // Requery IDE IO resources in case of the switch of native and legacy modes + // + ReassignIdeResources (IdeBlkIoDevice); + + // + // For ATA compatible device, use ATA read block's mechanism + // + if (IdeBlkIoDevice->Type == IdeHardDisk || + IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { + return AtaBlkIoReadBlocks ( + IdeBlkIoDevice, + MediaId, + LBA, + BufferSize, + Buffer + ); + } + + if (IdeBlkIoDevice->Type == IdeUnknown) { + return EFI_DEVICE_ERROR; + } + + // + // for ATAPI device, using ATAPI read block's mechanism + // + return AtapiBlkIoReadBlocks ( + IdeBlkIoDevice, + MediaId, + LBA, + BufferSize, + Buffer + ); + +} + +EFI_STATUS +EFIAPI +IDEBlkIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Write data to block io device + +Arguments: + + This - Protocol instance pointer. + MediaId - The media ID of the device + LBA - Starting LBA address to write data + BufferSize - The size of data to be written + Buffer - Caller supplied buffer to save data + +Returns: + + write data status + +--*/ +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (This); + // + // Requery IDE IO resources in case of the switch of native and legacy modes + // + ReassignIdeResources (IdeBlkIoDevice); + + // + // for ATA device, using ATA write block's mechanism + // + if (IdeBlkIoDevice->Type == IdeHardDisk || + IdeBlkIoDevice->Type == Ide48bitAddressingHardDisk) { + + return AtaBlkIoWriteBlocks ( + IdeBlkIoDevice, + MediaId, + LBA, + BufferSize, + Buffer + ); + } + + if (IdeBlkIoDevice->Type == IdeUnknown) { + return EFI_DEVICE_ERROR; + } + + // + // for ATAPI device, using ATAPI write block's mechanism + // + return AtapiBlkIoWriteBlocks ( + IdeBlkIoDevice, + MediaId, + LBA, + BufferSize, + Buffer + ); +} + +// +// *********************************************************************************** +// IDEBlkIoFlushBlocks +// *********************************************************************************** +// +EFI_STATUS +EFIAPI +IDEBlkIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + // + // return directly + // + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IDEDiskInfoInquiry ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *InquiryData, + IN OUT UINT32 *InquiryDataSize + ) +/*++ + + Routine Description: + Return the results of the Inquiry command to a drive in InquiryData. + Data format of Inquiry data is defined by the Interface GUID. + + Arguments: + This - Protocol instance pointer. + InquiryData - Results of Inquiry command to device + InquiryDataSize - Size of InquiryData in bytes. + + Returns: + EFI_SUCCESS - InquiryData valid + EFI_NOT_FOUND - Device does not support this data class + EFI_DEVICE_ERROR - Error reading InquiryData from device + EFI_BUFFER_TOO_SMALL - IntquiryDataSize not big enough + +--*/ +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); + + if (*InquiryDataSize < sizeof (INQUIRY_DATA)) { + *InquiryDataSize = sizeof (INQUIRY_DATA); + return EFI_BUFFER_TOO_SMALL; + } + + if (IdeBlkIoDevice->pInquiryData == NULL) { + return EFI_NOT_FOUND; + } + + gBS->CopyMem (InquiryData, IdeBlkIoDevice->pInquiryData, sizeof (INQUIRY_DATA)); + *InquiryDataSize = sizeof (INQUIRY_DATA); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IDEDiskInfoIdentify ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *IdentifyData, + IN OUT UINT32 *IdentifyDataSize + ) +/*++ + + Routine Description: + Return the results of the Identify command to a drive in IdentifyData. + Data format of Identify data is defined by the Interface GUID. + + Arguments: + This - Protocol instance pointer. + IdentifyData - Results of Identify command to device + IdentifyDataSize - Size of IdentifyData in bytes. + + Returns: + EFI_SUCCESS - IdentifyData valid + EFI_NOT_FOUND - Device does not support this data class + EFI_DEVICE_ERROR - Error reading IdentifyData from device + EFI_BUFFER_TOO_SMALL - IdentifyDataSize not big enough + +--*/ +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); + + if (*IdentifyDataSize < sizeof (EFI_IDENTIFY_DATA)) { + *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA); + return EFI_BUFFER_TOO_SMALL; + } + + if (IdeBlkIoDevice->pIdData == NULL) { + return EFI_NOT_FOUND; + } + + gBS->CopyMem (IdentifyData, IdeBlkIoDevice->pIdData, sizeof (EFI_IDENTIFY_DATA)); + *IdentifyDataSize = sizeof (EFI_IDENTIFY_DATA); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +IDEDiskInfoSenseData ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *SenseData, + IN OUT UINT32 *SenseDataSize, + OUT UINT8 *SenseDataNumber + ) +/*++ + + Routine Description: + Return the results of the Request Sense command to a drive in SenseData. + Data format of Sense data is defined by the Interface GUID. + + Arguments: + This - Protocol instance pointer. + SenseData - Results of Request Sense command to device + SenseDataSize - Size of SenseData in bytes. + SenseDataNumber - Type of SenseData + + Returns: + EFI_SUCCESS - InquiryData valid + EFI_NOT_FOUND - Device does not support this data class + EFI_DEVICE_ERROR - Error reading InquiryData from device + EFI_BUFFER_TOO_SMALL - SenseDataSize not big enough + +--*/ +{ + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +IDEDiskInfoWhichIde ( + IN EFI_DISK_INFO_PROTOCOL *This, + OUT UINT32 *IdeChannel, + OUT UINT32 *IdeDevice + ) +/*++ + + Routine Description: + Return the results of the Request Sense command to a drive in SenseData. + Data format of Sense data is defined by the Interface GUID. + + Arguments: + This - Protocol instance pointer. + IdeChannel - Primary or Secondary + IdeDevice - Master or Slave + + Returns: + EFI_SUCCESS - IdeChannel and IdeDevice are valid + EFI_UNSUPPORTED - This is not an IDE device + +--*/ +{ + IDE_BLK_IO_DEV *IdeBlkIoDevice; + + IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS (This); + *IdeChannel = IdeBlkIoDevice->Channel; + *IdeDevice = IdeBlkIoDevice->Device; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h new file mode 100644 index 0000000000..2e3caaf1b7 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.h @@ -0,0 +1,439 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + idebus.h + +Abstract: + + Header file for IDE Bus Driver. + +Revision History +++*/ + +// TODO: fix comment to end with --*/ +#ifndef _IDE_BUS_H +#define _IDE_BUS_H + + +#include +#include "idedata.h" + +// +// Extra Definition to porting +// +#define EFI_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +#define MAX_IDE_DEVICE 4 +#define MAX_IDE_CHANNELS 2 +#define MAX_IDE_DRIVES 2 + +typedef struct { + BOOLEAN HaveScannedDevice[MAX_IDE_DEVICE]; + BOOLEAN DeviceFound[MAX_IDE_DEVICE]; + BOOLEAN DeviceProcessed[MAX_IDE_DEVICE]; +} IDE_BUS_DRIVER_PRIVATE_DATA; + +#define IDE_BLK_IO_DEV_SIGNATURE EFI_SIGNATURE_32 ('i', 'b', 'i', 'd') + +typedef struct { + UINT32 Signature; + + EFI_HANDLE Handle; + EFI_BLOCK_IO_PROTOCOL BlkIo; + EFI_BLOCK_IO_MEDIA BlkMedia; + EFI_DISK_INFO_PROTOCOL DiskInfo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_IO_PROTOCOL *PciIo; + IDE_BUS_DRIVER_PRIVATE_DATA *IdeBusDriverPrivateData; + + // + // Local Data for IDE interface goes here + // + EFI_IDE_CHANNEL Channel; + EFI_IDE_DEVICE Device; + UINT16 Lun; + IDE_DEVICE_TYPE Type; + + IDE_BASE_REGISTERS *IoPort; + UINT16 AtapiError; + + INQUIRY_DATA *pInquiryData; + EFI_IDENTIFY_DATA *pIdData; + ATA_PIO_MODE PioMode; + ATA_UDMA_MODE UDma_Mode; + CHAR8 ModelName[41]; + REQUEST_SENSE_DATA *SenseData; + UINT8 SenseDataNumber; + UINT8 *Cache; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} IDE_BLK_IO_DEV; + +#include "ComponentName.h" + +#define IDE_BLOCK_IO_DEV_FROM_THIS(a) CR (a, IDE_BLK_IO_DEV, BlkIo, IDE_BLK_IO_DEV_SIGNATURE) +#define IDE_BLOCK_IO_DEV_FROM_DISK_INFO_THIS(a) CR (a, IDE_BLK_IO_DEV, DiskInfo, IDE_BLK_IO_DEV_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gIDEBusDriverBinding; + +#include "ide.h" + +// +// Prototypes +// Driver model protocol interface +// +EFI_STATUS +EFIAPI +IDEBusControllerDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + SystemTable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Controller - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Controller - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Controller - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// Block I/O Protocol Interface +// +EFI_STATUS +EFIAPI +IDEBlkIoReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEBlkIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEBlkIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEBlkIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +IDERegisterDecodeEnableorDisable ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN BOOLEAN Enable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIo - TODO: add argument description + Enable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEDiskInfoInquiry ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *InquiryData, + IN OUT UINT32 *IntquiryDataSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + InquiryData - TODO: add argument description + IntquiryDataSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEDiskInfoIdentify ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *IdentifyData, + IN OUT UINT32 *IdentifyDataSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + IdentifyData - TODO: add argument description + IdentifyDataSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEDiskInfoSenseData ( + IN EFI_DISK_INFO_PROTOCOL *This, + IN OUT VOID *SenseData, + IN OUT UINT32 *SenseDataSize, + OUT UINT8 *SenseDataNumber + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + SenseData - TODO: add argument description + SenseDataSize - TODO: add argument description + SenseDataNumber - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +IDEDiskInfoWhichIde ( + IN EFI_DISK_INFO_PROTOCOL *This, + OUT UINT32 *IdeChannel, + OUT UINT32 *IdeDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + IdeChannel - TODO: add argument description + IdeDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.mbd b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.mbd new file mode 100644 index 0000000000..f6e3ba1c8a --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.mbd @@ -0,0 +1,45 @@ + + + + + IdeBus + 69FD8E47-A161-4550-B01A-5594CEB2B2B2 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-22 16:27 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + DxeMemoryAllocationLib + UefiDevicePathLib + BasePerformanceLibNull + + diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa new file mode 100644 index 0000000000..1b303c6823 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebus.msa @@ -0,0 +1,90 @@ + + + + + IdeBus + DXE_DRIVER + BS_DRIVER + 69FD8E47-A161-4550-B01A-5594CEB2B2B2 + 0 + Component description file for PS2 keyboard module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-22 16:27 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + ReportStatusCodeLib + MemoryAllocationLib + PerformanceLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DevicePathLib + + + idebus.h + ide.h + idedata.h + idebus.c + ide.c + ata.c + atapi.c + ComponentName.c + ComponentName.h + + + MdePkg + EdkModulePkg + + + DevicePath + PciIo + IdeControllerInit + BlockIo + DiskInfo + + + + Configuration + 0x69fd8e47, 0xa161, 0x4550, 0xb0, 0x1a, 0x55, 0x94, 0xce, 0xb2, 0xb2, 0xb2 + + + + + DiskInfoIde + + + + + + + + gIDEBusDriverBinding + gIDEBusComponentName + + + diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.mbd b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.mbd new file mode 100644 index 0000000000..fa4bc333d4 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.mbd @@ -0,0 +1,44 @@ + + + + + IdeBusLite + 69FD8E47-A161-4550-B01A-5594CEB2B2B2 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibNull + EdkDxePrintLib + BaseLib + UefiDevicePathLib + BasePerformanceLibNull + + diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.msa b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.msa new file mode 100644 index 0000000000..71fc18ddce --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idebusLite.msa @@ -0,0 +1,86 @@ + + + + + IdeBusLite + DXE_DRIVER + BS_DRIVER + 69FD8E47-A161-4550-B01A-5594CEB2B2B2 + 0 + Component description file for PS2 keyboard module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + PerformanceLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DevicePathLib + + + idebus.h + ide.h + idedata.h + idebus.c + ide.c + ata.c + atapi.c + + + MdePkg + EdkModulePkg + + + DevicePath + PciIo + IdeControllerInit + BlockIo + DiskInfo + + + + DiskInfoIde + + + DiskInfoScsi + + + DiskInfoUsb + + + + + + + + gIDEBusDriverBinding + gIDEBusComponentName + + + diff --git a/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h new file mode 100644 index 0000000000..50b1f05a47 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/IdeBus/Dxe/idedata.h @@ -0,0 +1,879 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + idedata.h + +Abstract: + + Header file for IDE Bus Driver's Data Structures + +Revision History +++*/ + +// TODO: fix comment to end with --*/ +#ifndef _IDE_DATA_H +#define _IDE_DATA_H + +// +// bit definition +// +#define bit0 (1 << 0) +#define bit1 (1 << 1) +#define bit2 (1 << 2) +#define bit3 (1 << 3) +#define bit4 (1 << 4) +#define bit5 (1 << 5) +#define bit6 (1 << 6) +#define bit7 (1 << 7) +#define bit8 (1 << 8) +#define bit9 (1 << 9) +#define bit10 (1 << 10) +#define bit11 (1 << 11) +#define bit12 (1 << 12) +#define bit13 (1 << 13) +#define bit14 (1 << 14) +#define bit15 (1 << 15) +#define bit16 (1 << 16) +#define bit17 (1 << 17) +#define bit18 (1 << 18) +#define bit19 (1 << 19) +#define bit20 (1 << 20) +#define bit21 (1 << 21) +#define bit22 (1 << 22) +#define bit23 (1 << 23) +#define bit24 (1 << 24) +#define bit25 (1 << 25) +#define bit26 (1 << 26) +#define bit27 (1 << 27) +#define bit28 (1 << 28) +#define bit29 (1 << 29) +#define bit30 (1 << 30) +#define bit31 (1 << 31) + +// +// common constants +// +#define STALL_1_MILLI_SECOND 1000 // stall 1 ms +#define STALL_1_SECOND 1000000 // stall 1 second +typedef enum { + IdePrimary = 0, + IdeSecondary = 1, + IdeMaxChannel = 2 +} EFI_IDE_CHANNEL; + +typedef enum { + IdeMaster = 0, + IdeSlave = 1, + IdeMaxDevice = 2 +} EFI_IDE_DEVICE; + +typedef enum { + IdeMagnetic, /* ZIP Drive or LS120 Floppy Drive */ + IdeCdRom, /* ATAPI CDROM */ + IdeHardDisk, /* Hard Disk */ + Ide48bitAddressingHardDisk, /* Hard Disk larger than 120GB */ + IdeUnknown +} IDE_DEVICE_TYPE; + +// +// IDE Registers +// +typedef union { + UINT16 Command; /* when write */ + UINT16 Status; /* when read */ +} IDE_CMD_OR_STATUS; + +typedef union { + UINT16 Error; /* when read */ + UINT16 Feature; /* when write */ +} IDE_ERROR_OR_FEATURE; + +typedef union { + UINT16 AltStatus; /* when read */ + UINT16 DeviceControl; /* when write */ +} IDE_AltStatus_OR_DeviceControl; + +// +// IDE registers set +// +typedef struct { + UINT16 Data; + IDE_ERROR_OR_FEATURE Reg1; + UINT16 SectorCount; + UINT16 SectorNumber; + UINT16 CylinderLsb; + UINT16 CylinderMsb; + UINT16 Head; + IDE_CMD_OR_STATUS Reg; + + IDE_AltStatus_OR_DeviceControl Alt; + UINT16 DriveAddress; + + UINT16 MasterSlave; + UINT16 BusMasterBaseAddr; +} IDE_BASE_REGISTERS; + +// +// IDE registers' base addresses +// +typedef struct { + UINT16 CommandBlockBaseAddr; + UINT16 ControlBlockBaseAddr; + UINT16 BusMasterBaseAddr; +} IDE_REGISTERS_BASE_ADDR; + +// +// Bit definitions in Programming Interface byte of the Class Code field +// in PCI IDE controller's Configuration Space +// +#define IDE_PRIMARY_OPERATING_MODE bit0 +#define IDE_PRIMARY_PROGRAMMABLE_INDICATOR bit1 +#define IDE_SECONDARY_OPERATING_MODE bit2 +#define IDE_SECONDARY_PROGRAMMABLE_INDICATOR bit3 + +// +// IDE registers bit definitions +// + +// +// Err Reg +// +#define BBK_ERR bit7 /* Bad block detected */ +#define UNC_ERR bit6 /* Uncorrectable Data */ +#define MC_ERR bit5 /* Media Change */ +#define IDNF_ERR bit4 /* ID Not Found */ +#define MCR_ERR bit3 /* Media Change Requested */ +#define ABRT_ERR bit2 /* Aborted Command */ +#define TK0NF_ERR bit1 /* Track 0 Not Found */ +#define AMNF_ERR bit0 /* Address Mark Not Found */ + +// +// Device/Head Reg +// +#define LBA_MODE bit6 +#define DEV bit4 +#define HS3 bit3 +#define HS2 bit2 +#define HS1 bit1 +#define HS0 bit0 +#define CHS_MODE (0) +#define DRV0 (0) +#define DRV1 (1) +#define MST_DRV DRV0 +#define SLV_DRV DRV1 + +// +// Status Reg +// +#define BSY bit7 /* Controller Busy */ +#define DRDY bit6 /* Drive Ready */ +#define DWF bit5 /* Drive Write Fault */ +#define DSC bit4 /* Disk Seek Complete */ +#define DRQ bit3 /* Data Request */ +#define CORR bit2 /* Corrected Data */ +#define IDX bit1 /* Index */ +#define ERR bit0 /* Error */ + +// +// Device Control Reg +// +#define SRST bit2 /* Software Reset */ +#define IEN_L bit1 /* Interrupt Enable #*/ + +// +// Bus Master Reg +// +#define BMIC_nREAD bit3 +#define BMIC_START bit0 +#define BMIS_INTERRUPT bit2 +#define BMIS_ERROR bit1 + +#define BMICP_OFFSET 0x00 +#define BMISP_OFFSET 0x02 +#define BMIDP_OFFSET 0x04 +#define BMICS_OFFSET 0x08 +#define BMISS_OFFSET 0x0A +#define BMIDS_OFFSET 0x0C + +// +// Time Out Value For IDE Device Polling +// + +// +// ATATIMEOUT is used for waiting time out for ATA device +// + +// +// 1 second +// +#define ATATIMEOUT 1000 + +// +// ATAPITIMEOUT is used for waiting operation +// except read and write time out for ATAPI device +// + +// +// 1 second +// +#define ATAPITIMEOUT 1000 + +// +// ATAPILONGTIMEOUT is used for waiting read and +// write operation timeout for ATAPI device +// + +// +// 2 seconds +// +#define CDROMLONGTIMEOUT 2000 + +// +// 5 seconds +// +#define ATAPILONGTIMEOUT 5000 + +// +// ATA Commands Code +// +#define ATA_INITIALIZE_DEVICE 0x91 + +// +// Class 1 +// +#define IDENTIFY_DRIVE_CMD 0xec +#define READ_BUFFER_CMD 0xe4 +#define READ_SECTORS_CMD 0x20 +#define READ_SECTORS_WITH_RETRY_CMD 0x21 +#define READ_LONG_CMD 0x22 +#define READ_LONG_WITH_RETRY_CMD 0x23 +// +// Class 1 - Atapi6 enhanced commands +// +#define READ_SECTORS_EXT_CMD 0x24 + +// +// Class 2 +// +#define FORMAT_TRACK_CMD 0x50 +#define WRITE_BUFFER_CMD 0xe8 +#define WRITE_SECTORS_CMD 0x30 +#define WRITE_SECTORS_WITH_RETRY_CMD 0x31 +#define WRITE_LONG_CMD 0x32 +#define WRITE_LONG_WITH_RETRY_CMD 0x33 +#define WRITE_VERIFY_CMD 0x3c +// +// Class 2 - Atapi6 enhanced commands +// +#define WRITE_SECTORS_EXT_CMD 0x34 + +// +// Class 3 +// +#define ACK_MEDIA_CHANGE_CMD 0xdb +#define BOOT_POST_BOOT_CMD 0xdc +#define BOOT_PRE_BOOT_CMD 0xdd +#define CHECK_POWER_MODE_CMD 0x98 +#define CHECK_POWER_MODE_CMD_ALIAS 0xe5 +#define DOOR_LOCK_CMD 0xde +#define DOOR_UNLOCK_CMD 0xdf +#define EXEC_DRIVE_DIAG_CMD 0x90 +#define IDLE_CMD_ALIAS 0x97 +#define IDLE_CMD 0xe3 +#define IDLE_IMMEDIATE_CMD 0x95 +#define IDLE_IMMEDIATE_CMD_ALIAS 0xe1 +#define INIT_DRIVE_PARAM_CMD 0x91 +#define RECALIBRATE_CMD 0x10 /* aliased to 1x */ +#define READ_DRIVE_STATE_CMD 0xe9 +#define SET_MULTIPLE_MODE_CMD 0xC6 +#define READ_DRIVE_STATE_CMD 0xe9 +#define READ_VERIFY_CMD 0x40 +#define READ_VERIFY_WITH_RETRY_CMD 0x41 +#define SEEK_CMD 0x70 /* aliased to 7x */ +#define SET_FEATURES_CMD 0xef +#define STANDBY_CMD 0x96 +#define STANDBY_CMD_ALIAS 0xe2 +#define STANDBY_IMMEDIATE_CMD 0x94 +#define STANDBY_IMMEDIATE_CMD_ALIAS 0xe0 + +// +// Class 4 +// +#define READ_DMA_CMD 0xc8 +#define READ_DMA_WITH_RETRY_CMD 0xc9 +#define READ_DMA_EXT_CMD 0x25 +#define WRITE_DMA_CMD 0xca +#define WRITE_DMA_WITH_RETRY_CMD 0xcb +#define WRITE_DMA_EXT_CMD 0x35 + +// +// Class 5 +// +#define READ_MULTIPLE_CMD 0xc4 +#define REST_CMD 0xe7 +#define RESTORE_DRIVE_STATE_CMD 0xea +#define SET_SLEEP_MODE_CMD 0x99 +#define SET_SLEEP_MODE_CMD_ALIAS 0xe6 +#define WRITE_MULTIPLE_CMD 0xc5 +#define WRITE_SAME_CMD 0xe9 + +// +// Class 6 - Host protected area access feature set +// +#define READ_NATIVE_MAX_ADDRESS_CMD 0xf8 +#define SET_MAX_ADDRESS_CMD 0xf9 + +// +// Class 6 - ATA/ATAPI-6 enhanced commands +// +#define READ_NATIVE_MAX_ADDRESS_EXT_CMD 0x27 +#define SET_MAX_ADDRESS_CMD_EXT 0x37 + +// +// Class 6 - SET_MAX related sub command (in feature register) +// +#define PARTIES_SET_MAX_ADDRESS_SUB_CMD 0x00 +#define PARTIES_SET_PASSWORD_SUB_CMD 0x01 +#define PARTIES_LOCK_SUB_CMD 0x02 +#define PARTIES_UNLOCK_SUB_CMD 0x03 +#define PARTIES_FREEZE_SUB_CMD 0x04 + +// +// S.M.A.R.T +// +#define ATA_SMART_CMD 0xb0 +#define ATA_CONSTANT_C2 0xc2 +#define ATA_CONSTANT_4F 0x4f +#define ATA_SMART_ENABLE_OPERATION 0xd8 +#define ATA_SMART_RETURN_STATUS 0xda + +// +// Error codes for Exec Drive Diag +// +#define DRIV_DIAG_NO_ERROR (0x01) +#define DRIV_DIAG_FORMATTER_ERROR (0x02) +#define DRIV_DIAG_DATA_BUFFER_ERROR (0x03) +#define DRIV_DIAG_ECC_CKT_ERRROR (0x04) +#define DRIV_DIAG_UP_ERROR (0x05) +#define DRIV_DIAG_SLAVE_DRV_ERROR (0x80) /* aliased to 0x8x */ + +// +// Codes for Format Track +// +#define FORMAT_GOOD_SECTOR (0x00) +#define FORMAT_SUSPEND_ALLOC (0x01) +#define FORMAT_REALLOC_SECTOR (0x02) +#define FORMAT_MARK_SECTOR_DEFECTIVE (0x03) + +// +// IDE_IDENTIFY bits +// config bits : +// +#define ID_CONFIG_RESERVED0 bit0 +#define ID_CONFIG_HARD_SECTORED_DRIVE bit1 +#define ID_CONFIG_SOFT_SECTORED_DRIVE bit2 +#define ID_CONFIG_NON_MFM bit3 +#define ID_CONFIG_15uS_HEAD_SWITCHING bit4 +#define ID_CONFIG_SPINDLE_MOTOR_CONTROL bit5 +#define ID_CONFIG_HARD_DRIVE bit6 +#define ID_CONFIG_CHANGEABLE_MEDIUM bit7 +#define ID_CONFIG_DATA_RATE_TO_5MHZ bit8 +#define ID_CONFIG_DATA_RATE_5_TO_10MHZ bit9 +#define ID_CONFIG_DATA_RATE_ABOVE_10MHZ bit10 +#define ID_CONFIG_MOTOR_SPEED_TOLERANCE_ABOVE_0_5_PERC bit11 +#define ID_CONFIG_DATA_CLK_OFFSET_AVAIL bit12 +#define ID_CONFIG_TRACK_OFFSET_AVAIL bit13 +#define ID_CONFIG_SPEED_TOLERANCE_GAP_NECESSARY bit14 +#define ID_CONFIG_RESERVED1 bit15 + +#define ID_DOUBLE_WORD_IO_POSSIBLE bit01 +#define ID_LBA_SUPPORTED bit9 +#define ID_DMA_SUPPORTED bit8 + +#define SET_FEATURE_ENABLE_8BIT_TRANSFER (0x01) +#define SET_FEATURE_ENABLE_WRITE_CACHE (0x02) +#define SET_FEATURE_TRANSFER_MODE (0x03) +#define SET_FEATURE_WRITE_SAME_WRITE_SPECIFIC_AREA (0x22) +#define SET_FEATURE_DISABLE_RETRIES (0x33) +// +// for Read & Write Longs +// +#define SET_FEATURE_VENDOR_SPEC_ECC_LENGTH (0x44) +#define SET_FEATURE_PLACE_NO_OF_CACHE_SEGMENTS_IN_SECTOR_NO_REG (0x54) +#define SET_FEATURE_DISABLE_READ_AHEAD (0x55) +#define SET_FEATURE_MAINTAIN_PARAM_AFTER_RESET (0x66) +#define SET_FEATURE_DISABLE_ECC (0x77) +#define SET_FEATURE_DISABLE_8BIT_TRANSFER (0x81) +#define SET_FEATURE_DISABLE_WRITE_CACHE (0x82) +#define SET_FEATURE_ENABLE_ECC (0x88) +#define SET_FEATURE_ENABLE_RETRIES (0x99) +#define SET_FEATURE_ENABLE_READ_AHEAD (0xaa) +#define SET_FEATURE_SET_SECTOR_CNT_REG_AS_NO_OF_READ_AHEAD_SECTORS (0xab) +#define SET_FEATURE_ALLOW_REST_MODE (0xac) +// +// for Read & Write Longs +// +#define SET_FEATURE_4BYTE_ECC (0xbb) +#define SET_FEATURE_DEFALUT_FEATURES_ON_SOFTWARE_RESET (0xcc) +#define SET_FEATURE_WRITE_SAME_TO_WRITE_ENTIRE_MEDIUM (0xdd) + +#define BLOCK_TRANSFER_MODE (0x00) +#define SINGLE_WORD_DMA_TRANSFER_MODE (0x10) +#define MULTI_WORD_DMA_TRANSFER_MODE (0x20) +#define TRANSFER_MODE_MASK (0x07) // 3 LSBs + +// +// Drive 0 - Head 0 +// +#define DEFAULT_DRIVE (0x00) +#define DEFAULT_CMD (0xa0) +// +// default content of device control register, disable INT +// +#define DEFAULT_CTL (0x0a) +#define DEFAULT_IDE_BM_IO_BASE_ADR (0xffa0) + +// +// ATAPI6 related data structure definition +// + +// +// The maximum sectors count in 28 bit addressing mode +// +#define MAX_28BIT_ADDRESSING_CAPACITY 0xfffffff + +// +// Move the IDENTIFY section to DXE\Protocol\IdeControllerInit +// + +// +// ATAPI Command +// +#define ATAPI_SOFT_RESET_CMD 0x08 +#define ATAPI_PACKET_CMD 0xA0 +#define PACKET_CMD 0xA0 +#define ATAPI_IDENTIFY_DEVICE_CMD 0xA1 +#define ATAPI_SERVICE_CMD 0xA2 + +// +// ATAPI Packet Command +// +#pragma pack(1) + +typedef struct { + UINT8 opcode; + UINT8 reserved_1; + UINT8 reserved_2; + UINT8 reserved_3; + UINT8 reserved_4; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 reserved_8; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} TEST_UNIT_READY_CMD; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 4; + UINT8 lun : 4; + UINT8 page_code; + UINT8 reserved_3; + UINT8 allocation_length; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 reserved_8; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} INQUIRY_CMD; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 4; + UINT8 lun : 4; + UINT8 reserved_2; + UINT8 reserved_3; + UINT8 allocation_length; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 reserved_8; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} REQUEST_SENSE_CMD; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 4; + UINT8 lun : 4; + UINT8 page_code : 4; + UINT8 page_control : 4; + UINT8 reserved_3; + UINT8 reserved_4; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 parameter_list_length_hi; + UINT8 parameter_list_length_lo; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} MODE_SENSE_CMD; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 5; + UINT8 lun : 3; + UINT8 Lba0; + UINT8 Lba1; + UINT8 Lba2; + UINT8 Lba3; + UINT8 reserved_6; + UINT8 TranLen0; + UINT8 TranLen1; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} READ10_CMD; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1; + UINT8 reserved_2; + UINT8 reserved_3; + UINT8 reserved_4; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 allocation_length_hi; + UINT8 allocation_length_lo; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} READ_FORMAT_CAP_CMD; + +typedef union { + UINT16 Data16[6]; + TEST_UNIT_READY_CMD TestUnitReady; + READ10_CMD Read10; + REQUEST_SENSE_CMD RequestSence; + INQUIRY_CMD Inquiry; + MODE_SENSE_CMD ModeSense; + READ_FORMAT_CAP_CMD ReadFormatCapacity; +} ATAPI_PACKET_COMMAND; + +typedef struct { + UINT32 RegionBaseAddr; + UINT16 ByteCount; + UINT16 EndOfTable; +} IDE_DMA_PRD; + +#define MAX_DMA_EXT_COMMAND_SECTORS 0x10000 +#define MAX_DMA_COMMAND_SECTORS 0x100 + +#pragma pack() + +// +// Packet Command Code +// +#define TEST_UNIT_READY 0x00 +#define REZERO 0x01 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define REASSIGN_BLOCKS 0x07 +#define INQUIRY 0x12 +#define START_STOP_UNIT 0x1B +#define PREVENT_ALLOW_MEDIA_REMOVAL 0x1E +#define READ_FORMAT_CAPACITY 0x23 +#define OLD_FORMAT_UNIT 0x24 +#define READ_CAPACITY 0x25 +#define READ_10 0x28 +#define WRITE_10 0x2A +#define SEEK 0x2B +#define SEND_DIAGNOSTICS 0x3D +#define WRITE_VERIFY 0x2E +#define VERIFY 0x2F +#define READ_DEFECT_DATA 0x37 +#define WRITE_BUFFER 0x38 +#define READ_BUFFER 0x3C +#define READ_LONG 0x3E +#define WRITE_LONG 0x3F +#define MODE_SELECT 0x55 +#define MODE_SENSE 0x5A +#define READ_12 0xA8 +#define WRITE_12 0xAA +#define MAX_ATAPI_BYTE_COUNT (0xfffe) + +// +// Sense Key +// +#define REQUEST_SENSE_ERROR (0x70) +#define SK_NO_SENSE (0x0) +#define SK_RECOVERY_ERROR (0x1) +#define SK_NOT_READY (0x2) +#define SK_MEDIUM_ERROR (0x3) +#define SK_HARDWARE_ERROR (0x4) +#define SK_ILLEGAL_REQUEST (0x5) +#define SK_UNIT_ATTENTION (0x6) +#define SK_DATA_PROTECT (0x7) +#define SK_BLANK_CHECK (0x8) +#define SK_VENDOR_SPECIFIC (0x9) +#define SK_RESERVED_A (0xA) +#define SK_ABORT (0xB) +#define SK_RESERVED_C (0xC) +#define SK_OVERFLOW (0xD) +#define SK_MISCOMPARE (0xE) +#define SK_RESERVED_F (0xF) + +// +// Additional Sense Codes +// +#define ASC_NOT_READY (0x04) +#define ASC_MEDIA_ERR1 (0x10) +#define ASC_MEDIA_ERR2 (0x11) +#define ASC_MEDIA_ERR3 (0x14) +#define ASC_MEDIA_ERR4 (0x30) +#define ASC_MEDIA_UPSIDE_DOWN (0x06) +#define ASC_INVALID_CMD (0x20) +#define ASC_LBA_OUT_OF_RANGE (0x21) +#define ASC_INVALID_FIELD (0x24) +#define ASC_WRITE_PROTECTED (0x27) +#define ASC_MEDIA_CHANGE (0x28) +#define ASC_RESET (0x29) /* Power On Reset or Bus Reset occurred */ +#define ASC_ILLEGAL_FIELD (0x26) +#define ASC_NO_MEDIA (0x3A) +#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK (0x64) + +// +// Additional Sense Code Qualifier +// +#define ASCQ_IN_PROGRESS (0x01) + +#define SETFEATURE TRUE +#define CLEARFEATURE FALSE + +// +// ATAPI Data structure +// +#pragma pack(1) + +typedef struct { + UINT8 peripheral_type; + UINT8 RMB; + UINT8 version; + UINT8 response_data_format; + UINT8 addnl_length; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 vendor_info[8]; + UINT8 product_id[12]; + UINT8 eeprom_product_code[4]; + UINT8 firmware_rev_level[4]; + UINT8 firmware_sub_rev_level[1]; + UINT8 reserved_37; + UINT8 reserved_38; + UINT8 reserved_39; + UINT8 max_capacity_hi; + UINT8 max_capacity_mid; + UINT8 max_capacity_lo; + UINT8 reserved_43_95[95 - 43 + 1]; +} INQUIRY_DATA; + +typedef struct { + UINT8 peripheral_type; + UINT8 RMB; + UINT8 version; + UINT8 response_data_format; + UINT8 addnl_length; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 vendor_info[8]; + UINT8 product_id[16]; + UINT8 product_revision_level[4]; + UINT8 vendor_specific[20]; + UINT8 reserved_56_95[40]; +} CDROM_INQUIRY_DATA; + +typedef struct { + UINT8 error_code : 7; + UINT8 valid : 1; + UINT8 reserved_1; + UINT8 sense_key : 4; + UINT8 reserved_21 : 1; + UINT8 ILI : 1; + UINT8 reserved_22 : 2; + UINT8 vendor_specific_3; + UINT8 vendor_specific_4; + UINT8 vendor_specific_5; + UINT8 vendor_specific_6; + UINT8 addnl_sense_length; // n - 7 + UINT8 vendor_specific_8; + UINT8 vendor_specific_9; + UINT8 vendor_specific_10; + UINT8 vendor_specific_11; + UINT8 addnl_sense_code; // mandatory + UINT8 addnl_sense_code_qualifier; // mandatory + UINT8 field_replaceable_unit_code; // optional + UINT8 reserved_15; + UINT8 reserved_16; + UINT8 reserved_17; + // + // Followed by additional sense bytes : FIXME + // +} REQUEST_SENSE_DATA; + +typedef struct { + UINT8 LastLba3; + UINT8 LastLba2; + UINT8 LastLba1; + UINT8 LastLba0; + UINT8 BlockSize3; + UINT8 BlockSize2; + UINT8 BlockSize1; + UINT8 BlockSize0; +} READ_CAPACITY_DATA; + +typedef struct { + UINT8 reserved_0; + UINT8 reserved_1; + UINT8 reserved_2; + UINT8 Capacity_Length; + UINT8 LastLba3; + UINT8 LastLba2; + UINT8 LastLba1; + UINT8 LastLba0; + UINT8 DesCode : 2; + UINT8 reserved_9 : 6; + UINT8 BlockSize2; + UINT8 BlockSize1; + UINT8 BlockSize0; +} READ_FORMAT_CAPACITY_DATA; + +#pragma pack() + +// +// PIO mode definition +// +typedef enum { + ATA_PIO_MODE_BELOW_2, + ATA_PIO_MODE_2, + ATA_PIO_MODE_3, + ATA_PIO_MODE_4 +} ATA_PIO_MODE; + +// +// Multi word DMA definition +// +typedef enum { + ATA_MDMA_MODE_0, + ATA_MDMA_MODE_1, + ATA_MDMA_MODE_2 +} ATA_MDMA_MODE; + +// +// UDMA mode definition +// +typedef enum { + ATA_UDMA_MODE_0, + ATA_UDMA_MODE_1, + ATA_UDMA_MODE_2, + ATA_UDMA_MODE_3, + ATA_UDMA_MODE_4, + ATA_UDMA_MODE_5 +} ATA_UDMA_MODE; + +#define ATA_MODE_CATEGORY_DEFAULT_PIO 0x00 +#define ATA_MODE_CATEGORY_FLOW_PIO 0x01 +#define ATA_MODE_CATEGORY_MDMA 0x04 +#define ATA_MODE_CATEGORY_UDMA 0x08 + +#pragma pack(1) + +typedef struct { + UINT8 ModeNumber : 3; + UINT8 ModeCategory : 5; +} ATA_TRANSFER_MODE; + +typedef struct { + UINT8 Sector; + UINT8 Heads; + UINT8 MultipleSector; +} ATA_DRIVE_PARMS; + +#pragma pack() +// +// IORDY Sample Point field value +// +#define ISP_5_CLK 0 +#define ISP_4_CLK 1 +#define ISP_3_CLK 2 +#define ISP_2_CLK 3 + +// +// Recovery Time field value +// +#define RECVY_4_CLK 0 +#define RECVY_3_CLK 1 +#define RECVY_2_CLK 2 +#define RECVY_1_CLK 3 + +// +// Slave IDE Timing Register Enable +// +#define SITRE bit14 + +// +// DMA Timing Enable Only Select 1 +// +#define DTE1 bit7 + +// +// Pre-fetch and Posting Enable Select 1 +// +#define PPE1 bit6 + +// +// IORDY Sample Point Enable Select 1 +// +#define IE1 bit5 + +// +// Fast Timing Bank Drive Select 1 +// +#define TIME1 bit4 + +// +// DMA Timing Enable Only Select 0 +// +#define DTE0 bit3 + +// +// Pre-fetch and Posting Enable Select 0 +// +#define PPE0 bit2 + +// +// IOREY Sample Point Enable Select 0 +// +#define IE0 bit1 + +// +// Fast Timing Bank Drive Select 0 +// +#define TIME0 bit0 + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.c new file mode 100644 index 0000000000..ba7ec08c4e --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.c @@ -0,0 +1,133 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "PciBus.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName = { + PciBusComponentNameGetDriverName, + PciBusComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mPciBusDriverNameTable[] = { + { "eng", (CHAR16 *) L"PCI Bus Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +PciBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gPciBusComponentName.SupportedLanguages, + mPciBusDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +PciBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.h new file mode 100644 index 0000000000..87d44c8427 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/ComponentName.h @@ -0,0 +1,91 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.h + +Abstract: + + +Revision History + +--*/ + +#ifndef _EFI_PCI_BUS_COMPONENT_NAME_H +#define _EFI_PCI_BUS_COMPONENT_NAME_H + +#ifndef EFI_SIZE_REDUCTION_APPLIED + +extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName; + +#endif + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +PciBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Language - TODO: add argument description + DriverName - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ControllerHandle - TODO: add argument description + ChildHandle - TODO: add argument description + Language - TODO: add argument description + ControllerName - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.mbd b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.mbd new file mode 100644 index 0000000000..eea4971cbf --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.mbd @@ -0,0 +1,43 @@ + + + + + LightPciBusPciBus + C0734D12-7927-432b-986B-A7E3A35BA005 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + UefiDevicePathLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.msa b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.msa new file mode 100644 index 0000000000..eec5c3c069 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciBus.msa @@ -0,0 +1,112 @@ + + + + + LightPciBusPciBus + DXE_DRIVER + BS_DRIVER + C0734D12-7927-432b-986B-A7E3A35BA005 + 0 + Component description file for LightPciBus module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + ReportStatusCodeLib + UefiBootServicesTableLib + DevicePathLib + MemoryAllocationLib + + + PciBus.h + PciIo.h + PciCommand.h + PciDeviceSupport.h + PciResourceSupport.h + PciEnumerator.h + PciEnumeratorSupport.h + PciOptionRomSupport.h + PciRomTable.h + PciLib.h + PciRomTable.c + PciDriverOverride.h + PciPowerManagement.h + PciPowerManagement.c + PciDriverOverride.c + PciOptionRomSupport.c + PciEnumerator.c + PciEnumeratorSupport.c + PciResourceSupport.c + PciCOmmand.c + ComponentName.c + PciDeviceSupport.c + PciHotPlugSupport.c + PciBus.c + PciIo.c + LightPciLib.c + + + MdePkg + EdkModulePkg + + + DevicePath + PciRootBridgeIo + Decompress + UgaIo + PciPlatform + PciIo + BusSpecificDriverOverride + PciHotPlugRequest + IncompatiblePciDeviceSupport + PciHotPlugInit + PciHostBridgeResourceAllocation + LoadedImage + + + + PciOptionRomTable + + + PciHotplugDevice + + + StatusCodeSpecificData + + + + + PciBusEntryPoint + + + gPciBusDriverBinding + gPciBusComponentName + + + diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciLib.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciLib.c new file mode 100644 index 0000000000..28c8a794d4 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/LightPciLib.c @@ -0,0 +1,881 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + LightPciLib.c + +Abstract: + + Light PCI Bus Driver Lib file + It abstracts some functions that can be different + between light PCI bus driver and full PCI bus driver + +Revision History + +--*/ + +#include "pcibus.h" + +// +// Light PCI bus driver woundn't support hotplug device +// So just return +// +VOID +InstallHotPlugRequestProtocol ( + IN EFI_STATUS *Status + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +// TODO: Status - add argument and description to function comment +{ + return ; +} + +// +// Light PCI bus driver woundn't support hotplug device +// So just skip install this GUID +// +VOID +InstallPciHotplugGuid ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +{ + return ; +} + +// +// Light PCI bus driver woundn't support hotplug device +// So just skip uninstall the GUID +// +VOID +UninstallPciHotplugGuid ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +{ + return ; +} + +// +// Light PCI bus driver woundn't support PCCard +// So it needn't get the bar of CardBus +// +VOID +GetBackPcCardBar ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + return ; +} + +// +// Light PCI bus driver woundn't support resource reallocation +// So just return +// +EFI_STATUS +RemoveRejectedPciDevices ( + EFI_HANDLE RootBridgeHandle, + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeHandle - TODO: add argument description + Bridge - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + return EFI_SUCCESS; +} + +// +// Light PCI bus driver woundn't support resource reallocation +// Simplified the code +// +EFI_STATUS +PciHostBridgeResourceAllocator ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciResAlloc - add argument and description to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *RootBridgeDev; + EFI_HANDLE RootBridgeHandle; + VOID *AcpiConfig; + EFI_STATUS Status; + UINT64 IoBase; + UINT64 Mem32Base; + UINT64 PMem32Base; + UINT64 Mem64Base; + UINT64 PMem64Base; + UINT64 MaxOptionRomSize; + PCI_RESOURCE_NODE *IoBridge; + PCI_RESOURCE_NODE *Mem32Bridge; + PCI_RESOURCE_NODE *PMem32Bridge; + PCI_RESOURCE_NODE *Mem64Bridge; + PCI_RESOURCE_NODE *PMem64Bridge; + PCI_RESOURCE_NODE IoPool; + PCI_RESOURCE_NODE Mem32Pool; + PCI_RESOURCE_NODE PMem32Pool; + PCI_RESOURCE_NODE Mem64Pool; + PCI_RESOURCE_NODE PMem64Pool; + REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA ExtendedData; + + // + // Initialize resource pool + // + + InitializeResourcePool (&IoPool, PciBarTypeIo16); + InitializeResourcePool (&Mem32Pool, PciBarTypeMem32); + InitializeResourcePool (&PMem32Pool, PciBarTypePMem32); + InitializeResourcePool (&Mem64Pool, PciBarTypeMem64); + InitializeResourcePool (&PMem64Pool, PciBarTypePMem64); + + RootBridgeDev = NULL; + RootBridgeHandle = 0; + + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + // + // Get RootBridg Device by handle + // + RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_NOT_FOUND; + } + + // + // Get host bridge handle for status report + // + ExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle; + + // + // Create the entire system resource map from the information collected by + // enumerator. Several resource tree was created + // + + IoBridge = CreateResourceNode ( + RootBridgeDev, + 0, + 0xFFF, + 0, + PciBarTypeIo16, + PciResUsageTypical + ); + + Mem32Bridge = CreateResourceNode ( + RootBridgeDev, + 0, + 0xFFFFF, + 0, + PciBarTypeMem32, + PciResUsageTypical + ); + + PMem32Bridge = CreateResourceNode ( + RootBridgeDev, + 0, + 0xFFFFF, + 0, + PciBarTypePMem32, + PciResUsageTypical + ); + + Mem64Bridge = CreateResourceNode ( + RootBridgeDev, + 0, + 0xFFFFF, + 0, + PciBarTypeMem64, + PciResUsageTypical + ); + + PMem64Bridge = CreateResourceNode ( + RootBridgeDev, + 0, + 0xFFFFF, + 0, + PciBarTypePMem64, + PciResUsageTypical + ); + + // + // Create resourcemap by going through all the devices subject to this root bridge + // + Status = CreateResourceMap ( + RootBridgeDev, + IoBridge, + Mem32Bridge, + PMem32Bridge, + Mem64Bridge, + PMem64Bridge + ); + + // + // Get the max ROM size that the root bridge can process + // + RootBridgeDev->RomSize = Mem32Bridge->Length; + + // + // Get Max Option Rom size for current root bridge + // + MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev); + + // + // Enlarger the mem32 resource to accomdate the option rom + // if the mem32 resource is not enough to hold the rom + // + if (MaxOptionRomSize > Mem32Bridge->Length) { + + Mem32Bridge->Length = MaxOptionRomSize; + RootBridgeDev->RomSize = MaxOptionRomSize; + + // + // Alignment should be adjusted as well + // + if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) { + Mem32Bridge->Alignment = MaxOptionRomSize - 1; + } + } + + // + // Based on the all the resource tree, contruct ACPI resource node to + // submit the resource aperture to pci host bridge protocol + // + Status = ConstructAcpiResourceRequestor ( + RootBridgeDev, + IoBridge, + Mem32Bridge, + PMem32Bridge, + Mem64Bridge, + PMem64Bridge, + &AcpiConfig + ); + + // + // Insert these resource nodes into the database + // + InsertResourceNode (&IoPool, IoBridge); + InsertResourceNode (&Mem32Pool, Mem32Bridge); + InsertResourceNode (&PMem32Pool, PMem32Bridge); + InsertResourceNode (&Mem64Pool, Mem64Bridge); + InsertResourceNode (&PMem64Pool, PMem64Bridge); + + if (Status == EFI_SUCCESS) { + // + // Submit the resource requirement + // + Status = PciResAlloc->SubmitResources ( + PciResAlloc, + RootBridgeDev->Handle, + AcpiConfig + ); + } + // + // Free acpi resource node + // + if (AcpiConfig) { + gBS->FreePool (AcpiConfig); + } + + if (EFI_ERROR (Status)) { + // + // Destroy all the resource tree + // + DestroyResourceTree (&IoPool); + DestroyResourceTree (&Mem32Pool); + DestroyResourceTree (&PMem32Pool); + DestroyResourceTree (&Mem64Pool); + DestroyResourceTree (&PMem64Pool); + return Status; + } + } + // + // End while + // + + // + // Notify pci bus driver starts to program the resource + // + Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources); + + if (EFI_ERROR (Status)) { + // + // Allocation failed, then return + // + return EFI_OUT_OF_RESOURCES; + } + // + // Raise the EFI_IOB_PCI_RES_ALLOC status code + // + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_PROGRESS_CODE, + EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC, + (VOID *) &ExtendedData, + sizeof (ExtendedData) + ); + + // + // Notify pci bus driver starts to program the resource + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources); + + RootBridgeDev = NULL; + + RootBridgeHandle = 0; + + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + // + // Get RootBridg Device by handle + // + RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_NOT_FOUND; + } + + // + // Get acpi resource node for all the resource types + // + AcpiConfig = NULL; + Status = PciResAlloc->GetProposedResources ( + PciResAlloc, + RootBridgeDev->Handle, + &AcpiConfig + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the resource base by interpreting acpi resource node + // + // + GetResourceBase ( + AcpiConfig, + &IoBase, + &Mem32Base, + &PMem32Base, + &Mem64Base, + &PMem64Base + ); + + // + // Process option rom for this root bridge + // + Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize); + + // + // Create the entire system resource map from the information collected by + // enumerator. Several resource tree was created + // + Status = GetResourceMap ( + RootBridgeDev, + &IoBridge, + &Mem32Bridge, + &PMem32Bridge, + &Mem64Bridge, + &PMem64Bridge, + &IoPool, + &Mem32Pool, + &PMem32Pool, + &Mem64Pool, + &PMem64Pool + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Program IO resources + // + ProgramResource ( + IoBase, + IoBridge + ); + + // + // Program Mem32 resources + // + ProgramResource ( + Mem32Base, + Mem32Bridge + ); + + // + // Program PMem32 resources + // + ProgramResource ( + PMem32Base, + PMem32Bridge + ); + + // + // Program Mem64 resources + // + ProgramResource ( + Mem64Base, + Mem64Bridge + ); + + // + // Program PMem64 resources + // + ProgramResource ( + PMem64Base, + PMem64Bridge + ); + + if (AcpiConfig != NULL) { + gBS->FreePool (AcpiConfig); + } + } + + // + // Destroy all the resource tree + // + DestroyResourceTree (&IoPool); + DestroyResourceTree (&Mem32Pool); + DestroyResourceTree (&PMem32Pool); + DestroyResourceTree (&Mem64Pool); + DestroyResourceTree (&PMem64Pool); + + // + // Notify the resource allocation phase is to end + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation); + + return EFI_SUCCESS; +} + +EFI_STATUS +PciScanBus ( + IN PCI_IO_DEVICE *Bridge, + IN UINT8 StartBusNumber, + OUT UINT8 *SubBusNumber, + OUT UINT8 *PaddedBusRange + ) +/*++ + +Routine Description: + + This routine is used to assign bus number to the given PCI bus system + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: StartBusNumber - add argument and description to function comment +// TODO: SubBusNumber - add argument and description to function comment +// TODO: PaddedBusRange - add argument and description to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + PCI_TYPE00 Pci; + UINT8 Device; + UINT8 Func; + UINT64 Address; + UINTN SecondBus; + UINT16 Register; + PCI_IO_DEVICE *PciDevice; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + PciRootBridgeIo = Bridge->PciRootBridgeIo; + SecondBus = 0; + Register = 0; + + ResetAllPpbBusReg (Bridge, StartBusNumber); + + for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { + for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { + + // + // Check to see whether a pci device is present + // + Status = PciDevicePresent ( + PciRootBridgeIo, + &Pci, + StartBusNumber, + Device, + Func + ); + + if (!EFI_ERROR (Status) && + (IS_PCI_BRIDGE (&Pci) || + IS_CARDBUS_BRIDGE (&Pci))) { + + // + // Get the bridge information + // + Status = PciSearchDevice ( + Bridge, + &Pci, + StartBusNumber, + Device, + Func, + &PciDevice + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + (*SubBusNumber)++; + + SecondBus = (*SubBusNumber); + + Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber); + + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18); + + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint16, + Address, + 1, + &Register + ); + + // + // Initialize SubBusNumber to SecondBus + // + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A); + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + SubBusNumber + ); + // + // If it is PPB, resursively search down this bridge + // + if (IS_PCI_BRIDGE (&Pci)) { + // + // Temporarily initialize SubBusNumber to maximum bus number to ensure the + // PCI configuration transaction to go through any PPB + // + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A); + Register = 0xFF; + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + &Register + ); + + PreprocessController ( + PciDevice, + PciDevice->BusNumber, + PciDevice->DeviceNumber, + PciDevice->FunctionNumber, + EfiPciBeforeChildBusEnumeration + ); + + Status = PciScanBus ( + PciDevice, + (UINT8) (SecondBus), + SubBusNumber, + PaddedBusRange + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + } + + // + // Set the current maximum bus number under the PPB + // + + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A); + + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + SubBusNumber + ); + + } + + if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { + + // + // Skip sub functions, this is not a multi function device + // + + Func = PCI_MAX_FUNC; + } + } + } + + return EFI_SUCCESS; +} + +// +// Light PCI bus driver woundn't support P2C +// Return instead +// +EFI_STATUS +PciHostBridgeP2CProcess ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciResAlloc - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + return EFI_SUCCESS; +} + +// +// Light PCI bus driver woundn't support hotplug device +// Simplified the code +// +EFI_STATUS +PciHostBridgeEnumerator ( + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + + This function is used to enumerate the entire host bridge + in a given platform + +Arguments: + + PciResAlloc A pointer to the protocol to allocate resource. + +Returns: + + None + +--*/ +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_HANDLE RootBridgeHandle; + PCI_IO_DEVICE *RootBridgeDev; + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + UINT16 MinBus; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + + InitializeHotPlugSupport (); + + // + // Notify the bus allocation phase is about to start + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation); + + RootBridgeHandle = NULL; + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + + // + // if a root bridge instance is found, create root bridge device for it + // + + RootBridgeDev = CreateRootBridge (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Enumerate all the buses under this root bridge + // + + Status = PciRootBridgeEnumerator ( + PciResAlloc, + RootBridgeDev + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + DestroyRootBridge (RootBridgeDev); + + // + // Error proccess here + // + } + + // + // Notify the bus allocation phase is to end + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation); + + // + // Notify the resource allocation phase is to start + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation); + + RootBridgeHandle = NULL; + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + + // + // if a root bridge instance is found, create root bridge device for it + // + + RootBridgeDev = CreateRootBridge (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = StartManagingRootBridge (RootBridgeDev); + + if (EFI_ERROR (Status)) { + return Status; + } + + PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo; + Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Determine root bridge attribute by calling interface of Pcihostbridge + // protocol + // + DetermineRootBridgeAttributes ( + PciResAlloc, + RootBridgeDev + ); + + // + // Collect all the resource information under this root bridge + // A database that records all the information about pci device subject to this + // root bridge will then be created + // + Status = PciPciDeviceInfoCollector ( + RootBridgeDev, + (UINT8) MinBus + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + InsertRootBridge (RootBridgeDev); + + // + // Record the hostbridge handle + // + AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle); + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.mbd b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.mbd new file mode 100644 index 0000000000..41543f7832 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.mbd @@ -0,0 +1,43 @@ + + + + + PciBus + 93B80004-9FB3-11d4-9A3A-0090273FC14D + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + DxeMemoryAllocationLib + UefiDevicePathLib + + diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa new file mode 100644 index 0000000000..bf5c3698ef --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBus.msa @@ -0,0 +1,121 @@ + + + + + PciBus + DXE_DRIVER + BS_DRIVER + 93B80004-9FB3-11d4-9A3A-0090273FC14D + 0 + Component description file for PciBus module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + ReportStatusCodeLib + MemoryAllocationLib + UefiBootServicesTableLib + DevicePathLib + + + PciBus.h + PciIo.h + PciCommand.h + PciDeviceSupport.h + PciResourceSupport.h + PciEnumerator.h + PciEnumeratorSupport.h + PciOptionRomSupport.h + PciRomTable.h + PciHotPlugSupport.h + PciLib.h + PciHotPlugSupport.c + PciRomTable.c + PciDriverOverride.h + PciPowerManagement.h + PciPowerManagement.c + PciDriverOverride.c + PciOptionRomSupport.c + PciEnumerator.c + PciEnumeratorSupport.c + PciResourceSupport.c + PciCOmmand.c + ComponentName.c + PciDeviceSupport.c + PciBus.c + PciIo.c + PciLib.c + + + MdePkg + EdkModulePkg + + + DevicePath + PciRootBridgeIo + PciPlatform + IncompatiblePciDeviceSupport + PciHostBridgeResourceAllocation + PciHotPlugInit + Decompress + LoadedImage + UgaIo + PciIo + BusSpecificDriverOverride + PciHotPlugRequest + + + + gEfiUgaIoProtocolGuid + + + gEfiPciOptionRomTableGuid + + + + + PciOptionRomTable + + + StatusCodeSpecificData + + + PciHotplugDevice + + + + + PciBusEntryPoint + + + gPciBusDriverBinding + gPciBusComponentName + + + diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.mbd b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.mbd new file mode 100644 index 0000000000..c02965265c --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.mbd @@ -0,0 +1,43 @@ + + + + + PciBusPciBusLite + C0734D12-7927-432b-986B-A7E3A35BA005 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + UefiDevicePathLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.msa b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.msa new file mode 100644 index 0000000000..1568b31e31 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciBusLite.msa @@ -0,0 +1,111 @@ + + + + + PciBusPciBusLite + DXE_DRIVER + BS_DRIVER + C0734D12-7927-432b-986B-A7E3A35BA005 + 0 + Component description file for LightPciBus module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + ReportStatusCodeLib + UefiBootServicesTableLib + DevicePathLib + MemoryAllocationLib + + + PciBus.h + PciIo.h + PciCommand.h + PciDeviceSupport.h + PciResourceSupport.h + PciEnumerator.h + PciEnumeratorSupport.h + PciOptionRomSupport.h + PciRomTable.h + PciLib.h + PciRomTable.c + PciDriverOverride.h + PciPowerManagement.h + PciPowerManagement.c + PciDriverOverride.c + PciOptionRomSupport.c + PciEnumerator.c + PciEnumeratorSupport.c + PciResourceSupport.c + PciCOmmand.c + PciDeviceSupport.c + PciHotPlugSupport.c + PciBus.c + PciIo.c + LightPciLib.c + + + MdePkg + EdkModulePkg + + + DevicePath + PciRootBridgeIo + Decompress + UgaIo + PciPlatform + PciIo + BusSpecificDriverOverride + PciHotPlugRequest + IncompatiblePciDeviceSupport + PciHotPlugInit + PciHostBridgeResourceAllocation + LoadedImage + + + + PciOptionRomTable + + + PciHotplugDevice + + + StatusCodeSpecificData + + + + + PciBusEntryPoint + + + gPciBusDriverBinding + gPciBusComponentName + + + diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.c new file mode 100644 index 0000000000..90712338f0 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.c @@ -0,0 +1,207 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciCommand.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "Pcibus.h" + +EFI_STATUS +PciOperateRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command, + IN UINT8 Offset, + IN UINT8 Operation, + OUT UINT16 *PtrCommand + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: Command - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: Operation - add argument and description to function comment +// TODO: PtrCommand - add argument and description to function comment +{ + UINT16 OldCommand; + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + + OldCommand = 0; + PciIo = &PciIoDevice->PciIo; + + if (Operation != EFI_SET_REGISTER) { + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &OldCommand + ); + + if (Operation == EFI_GET_REGISTER) { + *PtrCommand = OldCommand; + return Status; + } + } + + if (Operation == EFI_ENABLE_REGISTER) { + OldCommand |= Command; + } else if (Operation == EFI_DISABLE_REGISTER) { + OldCommand &= ~(Command); + } else { + OldCommand = Command; + } + + return PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + Offset, + 1, + &OldCommand + ); +} + +BOOLEAN +PciCapabilitySupport ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +{ + + if (PciIoDevice->Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) { + return TRUE; + } + + return FALSE; +} + +EFI_STATUS +LocateCapabilityRegBlock ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT8 CapId, + IN OUT UINT8 *Offset, + OUT UINT8 *NextRegBlock OPTIONAL + ) +/*++ + +Routine Description: + Locate cap reg. + +Arguments: + PciIoDevice - A pointer to the PCI_IO_DEVICE. + CapId - The cap ID. + Offset - A pointer to the offset. + NextRegBlock - A pointer to the next block. + +Returns: + + None + +--*/ +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + UINT8 CapabilityPtr; + UINT16 CapabilityEntry; + UINT8 CapabilityID; + + // + // To check the cpability of this device supports + // + if (!PciCapabilitySupport (PciIoDevice)) { + return EFI_UNSUPPORTED; + } + + if (*Offset != 0) { + CapabilityPtr = *Offset; + } else { + + CapabilityPtr = 0; + if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { + + PciIoDevice->PciIo.Pci.Read ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR, + 1, + &CapabilityPtr + ); + } else { + + PciIoDevice->PciIo.Pci.Read ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint8, + EFI_PCI_CAPABILITY_PTR, + 1, + &CapabilityPtr + ); + } + } + + while (CapabilityPtr > 0x3F) { + // + // Mask it to DWORD alignment per PCI spec + // + CapabilityPtr &= 0xFC; + PciIoDevice->PciIo.Pci.Read ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint16, + CapabilityPtr, + 1, + &CapabilityEntry + ); + + CapabilityID = (UINT8) CapabilityEntry; + + if (CapabilityID == CapId) { + *Offset = CapabilityPtr; + if (NextRegBlock != NULL) { + *NextRegBlock = (UINT8) (CapabilityEntry >> 8); + } + + return EFI_SUCCESS; + } + + CapabilityPtr = (UINT8) (CapabilityEntry >> 8); + } + + return EFI_NOT_FOUND; +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.h new file mode 100644 index 0000000000..56f632e8da --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciCommand.h @@ -0,0 +1,134 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciCommand.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_COMMAND_H +#define _EFI_PCI_COMMAND_H + +#define EFI_GET_REGISTER 1 +#define EFI_SET_REGISTER 2 +#define EFI_ENABLE_REGISTER 3 +#define EFI_DISABLE_REGISTER 4 + +EFI_STATUS +PciOperateRegister ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command, + IN UINT8 Offset, + IN UINT8 Operation, + OUT UINT16 *PtrCommand + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + Command - TODO: add argument description + Offset - TODO: add argument description + Operation - TODO: add argument description + PtrCommand - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +PciCapabilitySupport ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +LocateCapabilityRegBlock ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT8 CapId, + IN OUT UINT8 *Offset, + OUT UINT8 *NextRegBlock OPTIONAL + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + CapId - TODO: add argument description + Offset - TODO: add argument description + NextRegBlock - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + + +#define PciReadCommandRegister(a,b) \ + PciOperateRegister (a,0, PCI_COMMAND_OFFSET, EFI_GET_REGISTER, b) + +#define PciSetCommandRegister(a,b) \ + PciOperateRegister (a,b, PCI_COMMAND_OFFSET, EFI_SET_REGISTER, NULL) + +#define PciEnableCommandRegister(a,b) \ + PciOperateRegister (a,b, PCI_COMMAND_OFFSET, EFI_ENABLE_REGISTER, NULL) + +#define PciDisableCommandRegister(a,b) \ + PciOperateRegister (a,b, PCI_COMMAND_OFFSET, EFI_DISABLE_REGISTER, NULL) + +#define PciReadBridgeControlRegister(a,b) \ + PciOperateRegister (a,0, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_GET_REGISTER, b) + +#define PciSetBridgeControlRegister(a,b) \ + PciOperateRegister (a,b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_SET_REGISTER, NULL) + +#define PciEnableBridgeControlRegister(a,b) \ + PciOperateRegister (a,b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_ENABLE_REGISTER, NULL) + +#define PciDisableBridgeControlRegister(a,b) \ + PciOperateRegister (a,b, PCI_BRIDGE_CONTROL_REGISTER_OFFSET, EFI_DISABLE_REGISTER, NULL) + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.c new file mode 100644 index 0000000000..c24d1b5e59 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.c @@ -0,0 +1,1345 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciDeviceSupport.c + +Abstract: + + This file provides routine to support Pci device node manipulation + +Revision History + +--*/ + +#include "Pcibus.h" +#include "PciDeviceSupport.h" + +// +// This device structure is serviced as a header. +// Its Next field points to the first root bridge device node +// +LIST_ENTRY gPciDevicePool; + +EFI_STATUS +InitializePciDevicePool ( + VOID + ) +/*++ + +Routine Description: + + Initialize the gPciDevicePool + +Arguments: + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + InitializeListHead (&gPciDevicePool); + + return EFI_SUCCESS; +} + +EFI_STATUS +InsertRootBridge ( + PCI_IO_DEVICE *RootBridge + ) +/*++ + +Routine Description: + + Insert a root bridge into PCI device pool + +Arguments: + + RootBridge - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + + InsertTailList (&gPciDevicePool, &(RootBridge->Link)); + + return EFI_SUCCESS; +} + +EFI_STATUS +InsertPciDevice ( + PCI_IO_DEVICE *Bridge, + PCI_IO_DEVICE *PciDeviceNode + ) +/*++ + +Routine Description: + + This function is used to insert a PCI device node under + a bridge + +Arguments: + Bridge - A pointer to the PCI_IO_DEVICE. + PciDeviceNode - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + + InsertTailList (&Bridge->ChildList, &(PciDeviceNode->Link)); + PciDeviceNode->Parent = Bridge; + + return EFI_SUCCESS; +} + +EFI_STATUS +DestroyRootBridge ( + IN PCI_IO_DEVICE *RootBridge + ) +/*++ + +Routine Description: + + +Arguments: + + RootBridge - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + DestroyPciDeviceTree (RootBridge); + + FreePciDevice (RootBridge); + + return EFI_SUCCESS; +} + +EFI_STATUS +FreePciDevice ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + Destroy a pci device node. + Also all direct or indirect allocated resource for this node will be freed. + +Arguments: + + PciIoDevice - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + + // + // Assume all children have been removed underneath this device + // + if (PciIoDevice->ResourcePaddingDescriptors != NULL) { + gBS->FreePool (PciIoDevice->ResourcePaddingDescriptors); + } + + if (PciIoDevice->DevicePath != NULL) { + gBS->FreePool (PciIoDevice->DevicePath); + } + + gBS->FreePool (PciIoDevice); + + return EFI_SUCCESS; +} + +EFI_STATUS +DestroyPciDeviceTree ( + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + Destroy all the pci device node under the bridge. + Bridge itself is not included. + +Arguments: + + Bridge - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + + while (!IsListEmpty (&Bridge->ChildList)) { + + CurrentLink = Bridge->ChildList.ForwardLink; + + // + // Remove this node from the linked list + // + RemoveEntryList (CurrentLink); + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (!IsListEmpty (&Temp->ChildList)) { + DestroyPciDeviceTree (Temp); + } + + FreePciDevice (Temp); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DestroyRootBridgeByHandle ( + EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + Destroy all device nodes under the root bridge + specified by Controller. + The root bridge itself is also included. + +Arguments: + + Controller - An efi handle. + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + + CurrentLink = gPciDevicePool.ForwardLink; + + while (CurrentLink && CurrentLink != &gPciDevicePool) { + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (Temp->Handle == Controller) { + + RemoveEntryList (CurrentLink); + + DestroyPciDeviceTree (Temp); + + FreePciDevice (Temp); + + return EFI_SUCCESS; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +RegisterPciDevice ( + IN EFI_HANDLE Controller, + IN PCI_IO_DEVICE *PciIoDevice, + OUT EFI_HANDLE *Handle OPTIONAL + ) +/*++ + +Routine Description: + + This function is used to register the PCI device to the EFI, + create a handle for this PCI device,then attach apporpriate protocols + onto the handle. + +Arguments: + + Controller - An efi handle. + PciIoDevice - A pointer to the PCI_IO_DEVICE. + Handle - A pointer to a efi handle. + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + VOID *PlatformOpRomBuffer; + UINTN PlatformOpRomSize; + UINT8 PciExpressCapRegOffset; + EFI_PCI_IO_PROTOCOL *PciIo; + + // + // Install the pciio protocol, device path protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &PciIoDevice->Handle, + &gEfiDevicePathProtocolGuid, + PciIoDevice->DevicePath, + &gEfiPciIoProtocolGuid, + &PciIoDevice->PciIo, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Detect if PCI Express Device + // + PciExpressCapRegOffset = 0; + Status = LocateCapabilityRegBlock ( + PciIoDevice, + EFI_PCI_CAPABILITY_ID_PCIEXP, + &PciExpressCapRegOffset, + NULL + ); + if (!EFI_ERROR (Status)) { + PciIoDevice->IsPciExp = TRUE; + } + + // + // Force Interrupt line to zero for cards that come up randomly + // + PciIo = &(PciIoDevice->PciIo); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero); + // + // Process Platform OpRom + // + if (gPciPlatformProtocol != NULL && !PciIoDevice->AllOpRomProcessed) { + PciIoDevice->AllOpRomProcessed = TRUE; + + Status = gPciPlatformProtocol->GetPciRom ( + gPciPlatformProtocol, + PciIoDevice->Handle, + &PlatformOpRomBuffer, + &PlatformOpRomSize + ); + + if (!EFI_ERROR (Status)) { + + // + // Have Platform OpRom + // + PciIoDevice->RomSize = PlatformOpRomSize; + PciIoDevice->PciIo.RomSize = PlatformOpRomSize; + PciIoDevice->PciIo.RomImage = PlatformOpRomBuffer; + + // + // Process Image + // + ProcessOpRomImage (PciIoDevice); + } + } + + if (PciIoDevice->BusOverride) { + // + // Install BusSpecificDriverOverride Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &PciIoDevice->Handle, + &gEfiBusSpecificDriverOverrideProtocolGuid, + &PciIoDevice->PciDriverOverride, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->UninstallMultipleProtocolInterfaces ( + &PciIoDevice->Handle, + &gEfiDevicePathProtocolGuid, + PciIoDevice->DevicePath, + &gEfiPciIoProtocolGuid, + &PciIoDevice->PciIo, + NULL + ); + + return Status; + } + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &(PciIoDevice->PciRootBridgeIo), + gPciBusDriverBinding.DriverBindingHandle, + PciIoDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Install Pccard Hotplug GUID for Pccard device so that + // to notify CardBus driver to stop the device when de-register happens + // + InstallPciHotplugGuid (PciIoDevice); + + if (Handle != NULL) { + *Handle = PciIoDevice->Handle; + } + + // + // Indicate the pci device is registered + // + PciIoDevice->Registered = TRUE; + + return EFI_SUCCESS; +} + +EFI_STATUS +RemoveAllPciDeviceOnBridge ( + EFI_HANDLE RootBridgeHandle, + PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + This function is used to remove the whole PCI devices from the bridge. + +Arguments: + + RootBridgeHandle - An efi handle. + Bridge - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + + while (!IsListEmpty (&Bridge->ChildList)) { + + CurrentLink = Bridge->ChildList.ForwardLink; + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + // + // Check if the current node has been deregistered before + // If it is not, then deregister it + // + if (Temp->Registered) { + DeRegisterPciDevice (RootBridgeHandle, Temp->Handle); + } + + // + // Remove this node from the linked list + // + RemoveEntryList (CurrentLink); + + if (!IsListEmpty (&Temp->ChildList)) { + RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp); + } + + FreePciDevice (Temp); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DeRegisterPciDevice ( + IN EFI_HANDLE Controller, + IN EFI_HANDLE Handle + ) +/*++ + +Routine Description: + + This function is used to de-register the PCI device from the EFI, + That includes un-installing PciIo protocol from the specified PCI + device handle. + +Arguments: + + Controller - An efi handle. + Handle - An efi handle. + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + PCI_IO_DEVICE *Node; + LIST_ENTRY *CurrentLink; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + gPciBusDriverBinding.DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo); + + // + // If it is already de-registered + // + if (!PciIoDevice->Registered) { + return EFI_SUCCESS; + } + + // + // If it is PPB, first de-register its children + // + + if (!IsListEmpty (&PciIoDevice->ChildList)) { + + CurrentLink = PciIoDevice->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) { + Node = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + Status = DeRegisterPciDevice (Controller, Node->Handle); + + if (EFI_ERROR (Status)) { + return Status; + } + + CurrentLink = CurrentLink->ForwardLink; + } + } + // + // Uninstall Pccard Hotplug GUID for Pccard device + // + UninstallPciHotplugGuid (PciIoDevice); + + // + // Close the child handle + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + gPciBusDriverBinding.DriverBindingHandle, + Handle + ); + + // + // Un-install the device path protocol and pci io protocol + // + if (PciIoDevice->BusOverride) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + Handle, + &gEfiDevicePathProtocolGuid, + PciIoDevice->DevicePath, + &gEfiPciIoProtocolGuid, + &PciIoDevice->PciIo, + &gEfiBusSpecificDriverOverrideProtocolGuid, + &PciIoDevice->PciDriverOverride, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + Handle, + &gEfiDevicePathProtocolGuid, + PciIoDevice->DevicePath, + &gEfiPciIoProtocolGuid, + &PciIoDevice->PciIo, + NULL + ); + } + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo, + gPciBusDriverBinding.DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + return Status; + } + + // + // The Device Driver should disable this device after disconnect + // so the Pci Bus driver will not touch this device any more. + // Restore the register field to the original value + // + PciIoDevice->Registered = FALSE; + PciIoDevice->Handle = NULL; + } else { + + // + // Handle may be closed before + // + return EFI_SUCCESS; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +StartPciDevicesOnBridge ( + IN EFI_HANDLE Controller, + IN PCI_IO_DEVICE *RootBridge, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, + IN OUT UINT8 *NumberOfChildren, + IN OUT EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + Start to manage the PCI device on specified the root bridge or PCI-PCI Bridge + +Arguments: + + Controller - An efi handle. + RootBridge - A pointer to the PCI_IO_DEVICE. + RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL. + NumberOfChildren - Children number. + ChildHandleBuffer - A pointer to the child handle buffer. + +Returns: + + None + +--*/ +// TODO: EFI_NOT_READY - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + PCI_IO_DEVICE *Temp; + PCI_IO_DEVICE *PciIoDevice; + EFI_DEV_PATH_PTR Node; + EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath; + EFI_STATUS Status; + LIST_ENTRY *CurrentLink; + UINT64 Supports; + + CurrentLink = RootBridge->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &RootBridge->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + if (RemainingDevicePath != NULL) { + + Node.DevPath = RemainingDevicePath; + + if (Node.Pci->Device != Temp->DeviceNumber || + Node.Pci->Function != Temp->FunctionNumber) { + CurrentLink = CurrentLink->ForwardLink; + continue; + } + + // + // Check if the device has been assigned with required resource + // + if (!Temp->Allocated) { + return EFI_NOT_READY; + } + + // + // Check if the current node has been registered before + // If it is not, register it + // + if (!Temp->Registered) { + PciIoDevice = Temp; + + Status = RegisterPciDevice ( + Controller, + PciIoDevice, + NULL + ); + + } + + if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && Temp->Registered) { + ChildHandleBuffer[*NumberOfChildren] = Temp->Handle; + (*NumberOfChildren)++; + } + + // + // Get the next device path + // + CurrentDevicePath = EfiNextDevicePathNode (RemainingDevicePath); + if (EfiIsDevicePathEnd (CurrentDevicePath)) { + return EFI_SUCCESS; + } + + // + // If it is a PPB + // + if (!IsListEmpty (&Temp->ChildList)) { + Status = StartPciDevicesOnBridge ( + Controller, + Temp, + CurrentDevicePath, + NumberOfChildren, + ChildHandleBuffer + ); + + Temp->PciIo.Attributes ( + &(Temp->PciIo), + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + Supports &= EFI_PCI_DEVICE_ENABLE; + Temp->PciIo.Attributes ( + &(Temp->PciIo), + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + + return Status; + } else { + + // + // Currently, the PCI bus driver only support PCI-PCI bridge + // + return EFI_UNSUPPORTED; + } + + } else { + + // + // If remaining device path is NULL, + // try to enable all the pci devices under this bridge + // + + if (!Temp->Registered && Temp->Allocated) { + + PciIoDevice = Temp; + + Status = RegisterPciDevice ( + Controller, + PciIoDevice, + NULL + ); + + } + + if (NumberOfChildren != NULL && ChildHandleBuffer != NULL && Temp->Registered) { + ChildHandleBuffer[*NumberOfChildren] = Temp->Handle; + (*NumberOfChildren)++; + } + + if (!IsListEmpty (&Temp->ChildList)) { + Status = StartPciDevicesOnBridge ( + Controller, + Temp, + RemainingDevicePath, + NumberOfChildren, + ChildHandleBuffer + ); + + Temp->PciIo.Attributes ( + &(Temp->PciIo), + EfiPciIoAttributeOperationSupported, + 0, + &Supports + ); + Supports &= EFI_PCI_DEVICE_ENABLE; + Temp->PciIo.Attributes ( + &(Temp->PciIo), + EfiPciIoAttributeOperationEnable, + Supports, + NULL + ); + + } + + CurrentLink = CurrentLink->ForwardLink; + continue; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +StartPciDevices ( + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Start to manage the PCI device according to RemainingDevicePath + If RemainingDevicePath == NULL, the PCI bus driver will start + to manage all the PCI devices it found previously + +Arguments: + Controller - An efi handle. + RemainingDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL. + +Returns: + + None + +--*/ +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_DEV_PATH_PTR Node; + PCI_IO_DEVICE *RootBridge; + LIST_ENTRY *CurrentLink; + + if (RemainingDevicePath != NULL) { + + // + // Check if the RemainingDevicePath is valid + // + Node.DevPath = RemainingDevicePath; + if ((Node.DevPath->Type != HARDWARE_DEVICE_PATH) || + ((Node.DevPath->SubType != HW_PCI_DP) && + (DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH))) + ) { + return EFI_UNSUPPORTED; + } + } + + CurrentLink = gPciDevicePool.ForwardLink; + + while (CurrentLink && CurrentLink != &gPciDevicePool) { + + RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + // + // Locate the right root bridge to start + // + if (RootBridge->Handle == Controller) { + StartPciDevicesOnBridge ( + Controller, + RootBridge, + RemainingDevicePath, + NULL, + NULL + ); + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_SUCCESS; +} + +PCI_IO_DEVICE * +CreateRootBridge ( + IN EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + +Arguments: + RootBridgeHandle - An efi handle. + +Returns: + + None + +--*/ +{ + + EFI_STATUS Status; + PCI_IO_DEVICE *Dev; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + Dev = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (PCI_IO_DEVICE), + (VOID **) &Dev + ); + + if (EFI_ERROR (Status)) { + return NULL; + } + + ZeroMem (Dev, sizeof (PCI_IO_DEVICE)); + Dev->Signature = PCI_IO_DEVICE_SIGNATURE; + Dev->Handle = RootBridgeHandle; + InitializeListHead (&Dev->ChildList); + + Status = gBS->OpenProtocol ( + RootBridgeHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + gPciBusDriverBinding.DriverBindingHandle, + RootBridgeHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (Dev); + return NULL; + } + + // + // Record the root bridge parent device path + // + Dev->DevicePath = DuplicateDevicePath (ParentDevicePath); + + // + // Get the pci root bridge io protocol + // + Status = gBS->OpenProtocol ( + RootBridgeHandle, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo, + gPciBusDriverBinding.DriverBindingHandle, + RootBridgeHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + FreePciDevice (Dev); + return NULL; + } + + Dev->PciRootBridgeIo = PciRootBridgeIo; + + // + // Initialize the PCI I/O instance structure + // + Status = InitializePciIoInstance (Dev); + Status = InitializePciDriverOverrideInstance (Dev); + + // + // Initialize reserved resource list and + // option rom driver list + // + InitializeListHead (&Dev->ReservedResourceList); + InitializeListHead (&Dev->OptionRomDriverList); + + return Dev; +} + +PCI_IO_DEVICE * +GetRootBridgeByHandle ( + EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + +Arguments: + + RootBridgeHandle - An efi handle. + +Returns: + + None + +--*/ +{ + PCI_IO_DEVICE *RootBridgeDev; + LIST_ENTRY *CurrentLink; + + CurrentLink = gPciDevicePool.ForwardLink; + + while (CurrentLink && CurrentLink != &gPciDevicePool) { + + RootBridgeDev = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + if (RootBridgeDev->Handle == RootBridgeHandle) { + return RootBridgeDev; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return NULL; +} + +BOOLEAN +RootBridgeExisted ( + IN EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + This function searches if RootBridgeHandle has already existed + in current device pool. + + If so, it means the given root bridge has been already enumerated. + +Arguments: + + RootBridgeHandle - An efi handle. + +Returns: + + None + +--*/ +{ + PCI_IO_DEVICE *Bridge; + + Bridge = GetRootBridgeByHandle (RootBridgeHandle); + + if (Bridge != NULL) { + return TRUE; + } + + return FALSE; +} + +BOOLEAN +PciDeviceExisted ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + + Bridge - A pointer to the PCI_IO_DEVICE. + PciIoDevice - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + + PCI_IO_DEVICE *Temp; + LIST_ENTRY *CurrentLink; + + CurrentLink = Bridge->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &Bridge->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (Temp == PciIoDevice) { + return TRUE; + } + + if (!IsListEmpty (&Temp->ChildList)) { + if (PciDeviceExisted (Temp, PciIoDevice)) { + return TRUE; + } + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return FALSE; +} + +PCI_IO_DEVICE * +ActiveVGADeviceOnTheSameSegment ( + IN PCI_IO_DEVICE *VgaDevice + ) +/*++ + +Routine Description: + +Arguments: + + VgaDevice - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + + CurrentLink = gPciDevicePool.ForwardLink; + + while (CurrentLink && CurrentLink != &gPciDevicePool) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (Temp->PciRootBridgeIo->SegmentNumber == VgaDevice->PciRootBridgeIo->SegmentNumber) { + + Temp = ActiveVGADeviceOnTheRootBridge (Temp); + + if (Temp != NULL) { + return Temp; + } + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return NULL; +} + +PCI_IO_DEVICE * +ActiveVGADeviceOnTheRootBridge ( + IN PCI_IO_DEVICE *RootBridge + ) +/*++ + +Routine Description: + +Arguments: + + RootBridge - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + + CurrentLink = RootBridge->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &RootBridge->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (IS_PCI_VGA(&Temp->Pci) && + (Temp->Attributes & (EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_IO))) { + return Temp; + } + + if (IS_PCI_BRIDGE (&Temp->Pci)) { + + Temp = ActiveVGADeviceOnTheRootBridge (Temp); + + if (Temp != NULL) { + return Temp; + } + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return NULL; +} + +EFI_STATUS +GetHpcPciAddress ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + OUT UINT64 *PciAddress + ) +/*++ + +Routine Description: + +Arguments: + + PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL. + PciAddress - A pointer to the pci address. + +Returns: + + None + +--*/ +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath; + EFI_DEV_PATH_PTR Node; + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *RootBridge; + EFI_STATUS Status; + + CurrentDevicePath = HpcDevicePath; + + // + // Get the remaining device path for this PCI device, if it is a PCI device + // + while (!EfiIsDevicePathEnd (CurrentDevicePath)) { + + Node.DevPath = CurrentDevicePath; + + // + // Check if it is PCI device Path? + // + if ((Node.DevPath->Type != HARDWARE_DEVICE_PATH) || + ((Node.DevPath->SubType != HW_PCI_DP) && + (DevicePathNodeLength (Node.DevPath) != sizeof (PCI_DEVICE_PATH)))) { + CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath); + continue; + } + + break; + } + + // + // Check if it is not PCI device path + // + if (EfiIsDevicePathEnd (CurrentDevicePath)) { + return EFI_NOT_FOUND; + } + + CurrentLink = gPciDevicePool.ForwardLink; + + while (CurrentLink && CurrentLink != &gPciDevicePool) { + + RootBridge = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + // + // Locate the right root bridge to start + // + if (RootBridge->PciRootBridgeIo == PciRootBridgeIo) { + Status = GetHpcPciAddressFromRootBridge ( + RootBridge, + CurrentDevicePath, + PciAddress + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; + + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +GetHpcPciAddressFromRootBridge ( + IN PCI_IO_DEVICE *RootBridge, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, + OUT UINT64 *PciAddress + ) +/*++ + +Routine Description: + +Arguments: + + PciRootBridgeIo - A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL. + HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCL. + PciAddress - A pointer to the pci address. + +Returns: + + None + +--*/ +// TODO: RootBridge - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_DEV_PATH_PTR Node; + PCI_IO_DEVICE *Temp; + EFI_DEVICE_PATH_PROTOCOL *CurrentDevicePath; + LIST_ENTRY *CurrentLink; + BOOLEAN MisMatch; + + MisMatch = FALSE; + + CurrentDevicePath = RemainingDevicePath; + Node.DevPath = CurrentDevicePath; + Temp = NULL; + + while (!EfiIsDevicePathEnd (CurrentDevicePath)) { + + CurrentLink = RootBridge->ChildList.ForwardLink; + Node.DevPath = CurrentDevicePath; + + while (CurrentLink && CurrentLink != &RootBridge->ChildList) { + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (Node.Pci->Device == Temp->DeviceNumber && + Node.Pci->Function == Temp->FunctionNumber) { + RootBridge = Temp; + break; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + // + // Check if we find the bridge + // + if (CurrentLink == &RootBridge->ChildList) { + + MisMatch = TRUE; + break; + + } + + CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath); + } + + if (MisMatch) { + + CurrentDevicePath = EfiNextDevicePathNode (CurrentDevicePath); + + if (EfiIsDevicePathEnd (CurrentDevicePath)) { + *PciAddress = EFI_PCI_ADDRESS (RootBridge->BusNumber, Node.Pci->Device, Node.Pci->Function, 0); + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; + } + + *PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0); + + return EFI_SUCCESS; + +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.h new file mode 100644 index 0000000000..374f4dfad3 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDeviceSupport.h @@ -0,0 +1,477 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciDeviceSupport.h + +Abstract: + + + +Revision History + +--*/ + +#ifndef _EFI_PCI_DEVICE_SUPPORT_H +#define _EFI_PCI_DEVICE_SUPPORT_H + +EFI_STATUS +InitializePciDevicePool ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +InsertRootBridge ( + PCI_IO_DEVICE *RootBridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +InsertPciDevice ( + PCI_IO_DEVICE *Bridge, + PCI_IO_DEVICE *PciDeviceNode + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + PciDeviceNode - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DestroyRootBridge ( + IN PCI_IO_DEVICE *RootBridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DestroyPciDeviceTree ( + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DestroyRootBridgeByHandle ( + EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +RegisterPciDevice ( + IN EFI_HANDLE Controller, + IN PCI_IO_DEVICE *PciIoDevice, + OUT EFI_HANDLE *Handle OPTIONAL + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + PciIoDevice - TODO: add argument description + Handle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +RemoveAllPciDeviceOnBridge ( + EFI_HANDLE RootBridgeHandle, + PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeHandle - TODO: add argument description + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DeRegisterPciDevice ( + IN EFI_HANDLE Controller, + IN EFI_HANDLE Handle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + Handle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +StartPciDevicesOnBridge ( + IN EFI_HANDLE Controller, + IN PCI_IO_DEVICE *RootBridge, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, + IN OUT UINT8 *NumberOfChildren, + IN OUT EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + RootBridge - TODO: add argument description + RemainingDevicePath - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +StartPciDevices ( + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +CreateRootBridge ( + IN EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +GetRootBridgeByHandle ( + EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +RootBridgeExisted ( + IN EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +PciDeviceExisted ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +ActiveVGADeviceOnTheSameSegment ( + IN PCI_IO_DEVICE *VgaDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + VgaDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +ActiveVGADeviceOnTheRootBridge ( + IN PCI_IO_DEVICE *RootBridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetHpcPciAddress ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + OUT UINT64 *PciAddress + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciRootBridgeIo - TODO: add argument description + HpcDevicePath - TODO: add argument description + PciAddress - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetHpcPciAddressFromRootBridge ( + IN PCI_IO_DEVICE *RootBridge, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, + OUT UINT64 *PciAddress + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridge - TODO: add argument description + RemainingDevicePath - TODO: add argument description + PciAddress - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +FreePciDevice ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c new file mode 100644 index 0000000000..76c5a20784 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.c @@ -0,0 +1,290 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciDriverOverride.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "pcibus.h" + +EFI_STATUS +InitializePciDriverOverrideInstance ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + Initializes a PCI Driver Override Instance + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PciIoDevice->PciDriverOverride.GetDriver = GetDriver; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GetDriver ( + IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This, + IN OUT EFI_HANDLE *DriverImageHandle + ) +/*++ + +Routine Description: + + Get a overriding driver image + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: DriverImageHandle - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + PCI_IO_DEVICE *PciIoDevice; + LIST_ENTRY *CurrentLink; + PCI_DRIVER_OVERRIDE_LIST *Node; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS (This); + + CurrentLink = PciIoDevice->OptionRomDriverList.ForwardLink; + + while (CurrentLink && CurrentLink != &PciIoDevice->OptionRomDriverList) { + + Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink); + + if (*DriverImageHandle == NULL) { + + *DriverImageHandle = Node->DriverImageHandle; + return EFI_SUCCESS; + } + + if (*DriverImageHandle == Node->DriverImageHandle) { + + if (CurrentLink->ForwardLink == &PciIoDevice->OptionRomDriverList || + CurrentLink->ForwardLink == NULL) { + return EFI_NOT_FOUND; + } + + // + // Get next node + // + Node = DRIVER_OVERRIDE_FROM_LINK (CurrentLink->ForwardLink); + *DriverImageHandle = Node->DriverImageHandle; + return EFI_SUCCESS; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS +AddDriver ( + IN PCI_IO_DEVICE *PciIoDevice, + IN EFI_HANDLE DriverImageHandle + ) +/*++ + +Routine Description: + + Add a overriding driver image + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: DriverImageHandle - add argument and description to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + PCI_DRIVER_OVERRIDE_LIST *Node; + EFI_DRIVER_OS_HANDOFF_HEADER *DriverOsHandoffHeader; + EFI_DRIVER_OS_HANDOFF_HEADER *NewDriverOsHandoffHeader; + EFI_DRIVER_OS_HANDOFF *DriverOsHandoff; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE DeviceHandle; + UINTN NumberOfEntries; + UINTN Size; + UINTN Index; + + Status = gBS->HandleProtocol (DriverImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &LoadedImage); + if (EFI_ERROR (Status)) { + return Status; + } + + Node = AllocatePool (sizeof (PCI_DRIVER_OVERRIDE_LIST)); + if (Node == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Node->Signature = DRIVER_OVERRIDE_SIGNATURE; + Node->DriverImageHandle = DriverImageHandle; + + InsertTailList (&PciIoDevice->OptionRomDriverList, &(Node->Link)); + + PciIoDevice->BusOverride = TRUE; + + DosHdr = (EFI_IMAGE_DOS_HEADER *) LoadedImage->ImageBase; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + return EFI_SUCCESS; + } + + PeHdr = (EFI_IMAGE_NT_HEADERS *) ((UINTN) LoadedImage->ImageBase + DosHdr->e_lfanew); + + if (PeHdr->FileHeader.Machine != EFI_IMAGE_MACHINE_EBC) { + return EFI_SUCCESS; + } + + DriverOsHandoffHeader = NULL; + Status = EfiGetSystemConfigurationTable (&gEfiUgaIoProtocolGuid, (VOID **) &DriverOsHandoffHeader); + if (!EFI_ERROR (Status) && DriverOsHandoffHeader != NULL) { + for (Index = 0; Index < DriverOsHandoffHeader->NumberOfEntries; Index++) { + DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)(DriverOsHandoffHeader) + + DriverOsHandoffHeader->HeaderSize + + Index * DriverOsHandoffHeader->SizeOfEntries); + DevicePath = DriverOsHandoff->DevicePath; + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle); + if (!EFI_ERROR (Status) && DeviceHandle != NULL && IsDevicePathEnd (DevicePath)) { + if (DeviceHandle == PciIoDevice->Handle) { + return EFI_SUCCESS; + } + } + } + + NumberOfEntries = DriverOsHandoffHeader->NumberOfEntries + 1; + } else { + NumberOfEntries = 1; + } + + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (EFI_DRIVER_OS_HANDOFF_HEADER) + NumberOfEntries * sizeof (EFI_DRIVER_OS_HANDOFF), + (VOID **) &NewDriverOsHandoffHeader + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (DriverOsHandoffHeader == NULL) { + NewDriverOsHandoffHeader->Version = 0; + NewDriverOsHandoffHeader->HeaderSize = sizeof (EFI_DRIVER_OS_HANDOFF_HEADER); + NewDriverOsHandoffHeader->SizeOfEntries = sizeof (EFI_DRIVER_OS_HANDOFF); + NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries; + } else { + gBS->CopyMem ( + NewDriverOsHandoffHeader, + DriverOsHandoffHeader, + DriverOsHandoffHeader->HeaderSize + (NumberOfEntries - 1) * DriverOsHandoffHeader->SizeOfEntries + ); + NewDriverOsHandoffHeader->NumberOfEntries = (UINT32) NumberOfEntries; + } + + DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *)((UINTN)NewDriverOsHandoffHeader + + NewDriverOsHandoffHeader->HeaderSize + + (NumberOfEntries - 1) * NewDriverOsHandoffHeader->SizeOfEntries); + + // + // Fill in the EFI_DRIVER_OS_HANDOFF structure + // + DriverOsHandoff->Type = EfiUgaDriverFromPciRom; + + // + // Compute the size of the device path + // + Size = GetDevicePathSize (PciIoDevice->DevicePath); + if (Size == 0) { + DriverOsHandoff->DevicePath = NULL; + } else { + + // + // Allocate space for duplicate device path + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + Size, + (VOID **) &DriverOsHandoff->DevicePath + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (NewDriverOsHandoffHeader); + return Status; + } + + // + // Make copy of device path + // + CopyMem (DriverOsHandoff->DevicePath, PciIoDevice->DevicePath, Size); + } + + DriverOsHandoff->PciRomSize = (UINT64) PciIoDevice->PciIo.RomSize; + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + (UINTN) DriverOsHandoff->PciRomSize, + (VOID **) &DriverOsHandoff->PciRomImage + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (NewDriverOsHandoffHeader); + return Status; + } + + gBS->CopyMem ( + DriverOsHandoff->PciRomImage, + PciIoDevice->PciIo.RomImage, + (UINTN) DriverOsHandoff->PciRomSize + ); + + Status = gBS->InstallConfigurationTable (&gEfiUgaIoProtocolGuid, NewDriverOsHandoffHeader); + if (EFI_ERROR (Status)) { + return Status; + } + + if (DriverOsHandoffHeader != NULL) { + gBS->FreePool (DriverOsHandoffHeader); + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.h new file mode 100644 index 0000000000..5992df9eb7 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciDriverOverride.h @@ -0,0 +1,108 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciDriverOverride.h + +Abstract: + + + +Revision History + +--*/ + +#ifndef _EFI_PCI_DRIVER_OVERRRIDE_H +#define _EFI_PCI_DRIVER_OVERRRIDE_H + +#define DRIVER_OVERRIDE_SIGNATURE EFI_SIGNATURE_32 ('d', 'r', 'o', 'v') + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + EFI_HANDLE DriverImageHandle; +} PCI_DRIVER_OVERRIDE_LIST; + + +#define DRIVER_OVERRIDE_FROM_LINK(a) \ + CR (a, PCI_DRIVER_OVERRIDE_LIST, Link, DRIVER_OVERRIDE_SIGNATURE) + + +EFI_STATUS +InitializePciDriverOverrideInstance ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AddDriver ( + IN PCI_IO_DEVICE *PciIoDevice, + IN EFI_HANDLE DriverImageHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + DriverImageHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +GetDriver ( + IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This, + IN OUT EFI_HANDLE *DriverImageHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + DriverImageHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c new file mode 100644 index 0000000000..d3566a1600 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.c @@ -0,0 +1,2164 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciEnumerator.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "Pcibus.h" +#include "PciEnumerator.h" +#include "PciResourceSupport.h" +#include "PciOptionRomSupport.h" + +EFI_STATUS +PciEnumerator ( + IN EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + This routine is used to enumerate entire pci bus system + in a given platform + +Arguments: + +Returns: + + None + +--*/ +// TODO: Controller - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + EFI_HANDLE HostBridgeHandle; + EFI_STATUS Status; + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + // + // If PCI bus has already done the full enumeration, never do it again + // + if (!gFullEnumeration) { + return PciEnumeratorLight (Controller); + } + + // + // If this host bridge has been already enumerated, then return successfully + // + if (RootBridgeExisted (Controller)) { + return EFI_SUCCESS; + } + + // + // Get the rootbridge Io protocol to find the host bridge handle + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo, + gPciBusDriverBinding.DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the host bridge handle + // + HostBridgeHandle = PciRootBridgeIo->ParentHandle; + + // + // Get the pci host bridge resource allocation protocol + // + Status = gBS->OpenProtocol ( + HostBridgeHandle, + &gEfiPciHostBridgeResourceAllocationProtocolGuid, + (VOID **) &PciResAlloc, + gPciBusDriverBinding.DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Notify the pci bus enumeration is about to begin + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginEnumeration); + + // + // Start the bus allocation phase + // + Status = PciHostBridgeEnumerator (PciResAlloc); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Submit the resource request + // + Status = PciHostBridgeResourceAllocator (PciResAlloc); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Process P2C + // + Status = PciHostBridgeP2CProcess (PciResAlloc); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Process attributes for devices on this host bridge + // + Status = PciHostBridgeDeviceAttribute (PciResAlloc); + if (EFI_ERROR (Status)) { + return Status; + } + + gFullEnumeration = FALSE; + + return EFI_SUCCESS; +} + +EFI_STATUS +PciRootBridgeEnumerator ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc, + IN PCI_IO_DEVICE *RootBridgeDev + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciResAlloc - add argument and description to function comment +// TODO: RootBridgeDev - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *pConfiguration; + UINT8 SubBusNumber; + UINT8 StartBusNumber; + UINT8 PaddedBusRange; + EFI_HANDLE RootBridgeHandle; + + SubBusNumber = 0; + StartBusNumber = 0; + PaddedBusRange = 0; + + // + // Get the root bridge handle + // + RootBridgeHandle = RootBridgeDev->Handle; + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_BUS_ENUM, + RootBridgeDev->DevicePath + ); + + // + // Get the Bus information + // + Status = PciResAlloc->StartBusEnumeration ( + PciResAlloc, + RootBridgeHandle, + (VOID **) &pConfiguration + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the bus number to start with + // + StartBusNumber = (UINT8) (pConfiguration->AddrRangeMin); + + // + // Initialize the subordinate bus number + // + SubBusNumber = StartBusNumber; + + // + // Assign bus number + // + Status = PciScanBus ( + RootBridgeDev, + (UINT8) (pConfiguration->AddrRangeMin), + &SubBusNumber, + &PaddedBusRange + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + + // + // Assign max bus number scanned + // + pConfiguration->AddrLen = SubBusNumber - StartBusNumber + 1 + PaddedBusRange; + + // + // Set bus number + // + Status = PciResAlloc->SetBusNumbers ( + PciResAlloc, + RootBridgeHandle, + pConfiguration + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ProcessOptionRom ( + IN PCI_IO_DEVICE *Bridge, + IN UINT64 RomBase, + IN UINT64 MaxLength + ) +/*++ + +Routine Description: + + This routine is used to process option rom on a certain root bridge + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: RomBase - add argument and description to function comment +// TODO: MaxLength - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + EFI_STATUS Status; + + // + // Go through bridges to reach all devices + // + CurrentLink = Bridge->ChildList.ForwardLink; + while (CurrentLink && CurrentLink != &Bridge->ChildList) { + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + if (!IsListEmpty (&Temp->ChildList)) { + + // + // Go further to process the option rom under this bridge + // + Status = ProcessOptionRom (Temp, RomBase, MaxLength); + } + + if (Temp->RomSize != 0 && Temp->RomSize <= MaxLength) { + + // + // Load and process the option rom + // + Status = LoadOpRomImage (Temp, RomBase); + if (Status == EFI_SUCCESS) { + Status = ProcessOpRomImage (Temp); + } + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciAssignBusNumber ( + IN PCI_IO_DEVICE *Bridge, + IN UINT8 StartBusNumber, + OUT UINT8 *SubBusNumber + ) +/*++ + +Routine Description: + + This routine is used to assign bus number to the given PCI bus system + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: StartBusNumber - add argument and description to function comment +// TODO: SubBusNumber - add argument and description to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + PCI_TYPE00 Pci; + UINT8 Device; + UINT8 Func; + UINT64 Address; + UINTN SecondBus; + UINT16 Register; + UINT8 Register8; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + PciRootBridgeIo = Bridge->PciRootBridgeIo; + + SecondBus = 0; + Register = 0; + + *SubBusNumber = StartBusNumber; + + // + // First check to see whether the parent is ppb + // + for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { + for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { + + // + // Check to see whether a pci device is present + // + + Status = PciDevicePresent ( + PciRootBridgeIo, + &Pci, + StartBusNumber, + Device, + Func + ); + + if (!EFI_ERROR (Status) && + (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) { + + // + // Reserved one bus for cardbus bridge + // + SecondBus = ++(*SubBusNumber); + + Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber); + + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18); + + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint16, + Address, + 1, + &Register + ); + + // + // Initialize SubBusNumber to SecondBus + // + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A); + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + SubBusNumber + ); + // + // If it is PPB, resursively search down this bridge + // + if (IS_PCI_BRIDGE (&Pci)) { + + Register8 = 0xFF; + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + &Register8 + ); + + Status = PciAssignBusNumber ( + Bridge, + (UINT8) (SecondBus), + SubBusNumber + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + } + + // + // Set the current maximum bus number under the PPB + // + + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A); + + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + SubBusNumber + ); + + } + + if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { + + // + // Skip sub functions, this is not a multi function device + // + + Func = PCI_MAX_FUNC; + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DetermineRootBridgeAttributes ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc, + IN PCI_IO_DEVICE *RootBridgeDev + ) +/*++ + +Routine Description: + + This routine is used to determine the root bridge attribute by interfacing + the host bridge resource allocation protocol. + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciResAlloc - add argument and description to function comment +// TODO: RootBridgeDev - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Attributes; + EFI_STATUS Status; + EFI_HANDLE RootBridgeHandle; + + Attributes = 0; + RootBridgeHandle = RootBridgeDev->Handle; + + // + // Get root bridge attribute by calling into pci host bridge resource allocation protocol + // + Status = PciResAlloc->GetAllocAttributes ( + PciResAlloc, + RootBridgeHandle, + &Attributes + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Here is the point where PCI bus driver calls HOST bridge allocation protocol + // Currently we hardcoded for ea815 + // + + if (Attributes & EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM) { + RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED; + } + + if (Attributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) { + RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED; + } + + RootBridgeDev->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED; + RootBridgeDev->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; + RootBridgeDev->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED; + + return EFI_SUCCESS; +} + +UINT64 +GetMaxOptionRomSize ( + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + Get Max Option Rom size on this bridge + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +{ + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + UINT64 MaxOptionRomSize; + UINT64 TempOptionRomSize; + + MaxOptionRomSize = 0; + + // + // Go through bridges to reach all devices + // + CurrentLink = Bridge->ChildList.ForwardLink; + while (CurrentLink && CurrentLink != &Bridge->ChildList) { + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + if (!IsListEmpty (&Temp->ChildList)) { + + // + // Get max option rom size under this bridge + // + TempOptionRomSize = GetMaxOptionRomSize (Temp); + + // + // Compare with the option rom size of the bridge + // Get the larger one + // + if (Temp->RomSize > TempOptionRomSize) { + TempOptionRomSize = Temp->RomSize; + } + + } else { + + // + // For devices get the rom size directly + // + TempOptionRomSize = Temp->RomSize; + } + + // + // Get the largest rom size on this bridge + // + if (TempOptionRomSize > MaxOptionRomSize) { + MaxOptionRomSize = TempOptionRomSize; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return MaxOptionRomSize; +} + +EFI_STATUS +PciHostBridgeDeviceAttribute ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + + Process attributes of devices on this host bridge + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciResAlloc - add argument and description to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_HANDLE RootBridgeHandle; + PCI_IO_DEVICE *RootBridgeDev; + EFI_STATUS Status; + + RootBridgeHandle = NULL; + + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + + // + // Get RootBridg Device by handle + // + RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_NOT_FOUND; + } + + // + // Set the attributes for devcies behind the Root Bridge + // + Status = DetermineDeviceAttribute (RootBridgeDev); + if (EFI_ERROR (Status)) { + return Status; + } + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetResourceAllocationStatus ( + VOID *AcpiConfig, + OUT UINT64 *IoResStatus, + OUT UINT64 *Mem32ResStatus, + OUT UINT64 *PMem32ResStatus, + OUT UINT64 *Mem64ResStatus, + OUT UINT64 *PMem64ResStatus + ) +/*++ + +Routine Description: + + Get resource allocation status from the ACPI pointer + +Arguments: + +Returns: + + None + +--*/ +// TODO: AcpiConfig - add argument and description to function comment +// TODO: IoResStatus - add argument and description to function comment +// TODO: Mem32ResStatus - add argument and description to function comment +// TODO: PMem32ResStatus - add argument and description to function comment +// TODO: Mem64ResStatus - add argument and description to function comment +// TODO: PMem64ResStatus - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + UINT8 *Temp; + UINT64 ResStatus; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ptr; + + Temp = (UINT8 *) AcpiConfig; + + while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) { + + ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp; + ResStatus = ptr->AddrTranslationOffset; + + switch (ptr->ResType) { + case 0: + if (ptr->AddrSpaceGranularity == 32) { + if (ptr->SpecificFlag == 0x06) { + // + // Pmem32 + // + *PMem32ResStatus = ResStatus; + } else { + // + // Mem32 + // + *Mem32ResStatus = ResStatus; + } + } + + if (ptr->AddrSpaceGranularity == 64) { + if (ptr->SpecificFlag == 0x06) { + // + // PMem64 + // + *PMem64ResStatus = ResStatus; + } else { + // + // Mem64 + // + *Mem64ResStatus = ResStatus; + } + } + + break; + + case 1: + // + // Io + // + *IoResStatus = ResStatus; + break; + + default: + break; + } + + Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +RejectPciDevice ( + IN PCI_IO_DEVICE *PciDevice + ) +/*++ + +Routine Description: + + Remove a PCI device from device pool and mark its bar + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_ABORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_ABORTED - add return value to function comment +{ + PCI_IO_DEVICE *Bridge; + PCI_IO_DEVICE *Temp; + LIST_ENTRY *CurrentLink; + + // + // Remove the padding resource from a bridge + // + if ( IS_PCI_BRIDGE(&PciDevice->Pci) && \ + PciDevice->ResourcePaddingDescriptors ) { + gBS->FreePool (PciDevice->ResourcePaddingDescriptors); + PciDevice->ResourcePaddingDescriptors = NULL; + return EFI_SUCCESS; + } + + // + // Skip RB and PPB + // + if (IS_PCI_BRIDGE (&PciDevice->Pci) || (!PciDevice->Parent)) { + return EFI_ABORTED; + } + + if (IS_CARDBUS_BRIDGE (&PciDevice->Pci)) { + // + // Get the root bridge device + // + Bridge = PciDevice; + while (Bridge->Parent) { + Bridge = Bridge->Parent; + } + + RemoveAllPciDeviceOnBridge (Bridge->Handle, PciDevice); + + // + // Mark its bar + // + InitializeP2C (PciDevice); + } + + // + // Remove the device + // + Bridge = PciDevice->Parent; + CurrentLink = Bridge->ChildList.ForwardLink; + while (CurrentLink && CurrentLink != &Bridge->ChildList) { + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + if (Temp == PciDevice) { + InitializePciDevice (Temp); + RemoveEntryList (CurrentLink); + FreePciDevice (Temp); + return EFI_SUCCESS; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_ABORTED; +} + +BOOLEAN +IsRejectiveDevice ( + IN PCI_RESOURCE_NODE *PciResNode + ) +/*++ + +Routine Description: + + Determine whethter a PCI device can be rejected + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciResNode - add argument and description to function comment +{ + PCI_IO_DEVICE *Temp; + + Temp = PciResNode->PciDev; + + // + // Ensure the device is present + // + if (!Temp) { + return FALSE; + } + + // + // PPB and RB should go ahead + // + if (IS_PCI_BRIDGE (&Temp->Pci) || (!Temp->Parent)) { + return TRUE; + } + + // + // Skip device on Bus0 + // + if ((Temp->Parent) && (Temp->BusNumber == 0)) { + return FALSE; + } + + // + // Skip VGA + // + if (IS_PCI_VGA (&Temp->Pci)) { + return FALSE; + } + + return TRUE; +} + +PCI_RESOURCE_NODE * +GetLargerConsumerDevice ( + IN PCI_RESOURCE_NODE *PciResNode1, + IN PCI_RESOURCE_NODE *PciResNode2 + ) +/*++ + +Routine Description: + + Get the larger resource consumer + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciResNode1 - add argument and description to function comment +// TODO: PciResNode2 - add argument and description to function comment +{ + if (!PciResNode2) { + return PciResNode1; + } + + if ((IS_PCI_BRIDGE(&(PciResNode2->PciDev->Pci)) || !(PciResNode2->PciDev->Parent)) \ + && (PciResNode2->ResourceUsage != PciResUsagePadding) ) + { + return PciResNode1; + } + + if (!PciResNode1) { + return PciResNode2; + } + + if ((PciResNode1->Length) > (PciResNode2->Length)) { + return PciResNode1; + } + + return PciResNode2; + +} + +PCI_RESOURCE_NODE * +GetMaxResourceConsumerDevice ( + IN PCI_RESOURCE_NODE *ResPool + ) +/*++ + +Routine Description: + + Get the max resource consumer in the host resource pool + +Arguments: + +Returns: + + None + +--*/ +// TODO: ResPool - add argument and description to function comment +{ + PCI_RESOURCE_NODE *Temp; + LIST_ENTRY *CurrentLink; + PCI_RESOURCE_NODE *PciResNode; + PCI_RESOURCE_NODE *PPBResNode; + + PciResNode = NULL; + + CurrentLink = ResPool->ChildList.ForwardLink; + while (CurrentLink && CurrentLink != &ResPool->ChildList) { + + Temp = RESOURCE_NODE_FROM_LINK (CurrentLink); + + if (!IsRejectiveDevice (Temp)) { + CurrentLink = CurrentLink->ForwardLink; + continue; + } + + if ((IS_PCI_BRIDGE (&(Temp->PciDev->Pci)) || (!Temp->PciDev->Parent)) \ + && (Temp->ResourceUsage != PciResUsagePadding)) + { + PPBResNode = GetMaxResourceConsumerDevice (Temp); + PciResNode = GetLargerConsumerDevice (PciResNode, PPBResNode); + } else { + PciResNode = GetLargerConsumerDevice (PciResNode, Temp); + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return PciResNode; +} + +EFI_STATUS +PciHostBridgeAdjustAllocation ( + IN PCI_RESOURCE_NODE *IoPool, + IN PCI_RESOURCE_NODE *Mem32Pool, + IN PCI_RESOURCE_NODE *PMem32Pool, + IN PCI_RESOURCE_NODE *Mem64Pool, + IN PCI_RESOURCE_NODE *PMem64Pool, + IN UINT64 IoResStatus, + IN UINT64 Mem32ResStatus, + IN UINT64 PMem32ResStatus, + IN UINT64 Mem64ResStatus, + IN UINT64 PMem64ResStatus + ) +/*++ + +Routine Description: + + Adjust host bridge allocation so as to reduce resource requirement + +Arguments: + +Returns: + + None + +--*/ +// TODO: IoPool - add argument and description to function comment +// TODO: Mem32Pool - add argument and description to function comment +// TODO: PMem32Pool - add argument and description to function comment +// TODO: Mem64Pool - add argument and description to function comment +// TODO: PMem64Pool - add argument and description to function comment +// TODO: IoResStatus - add argument and description to function comment +// TODO: Mem32ResStatus - add argument and description to function comment +// TODO: PMem32ResStatus - add argument and description to function comment +// TODO: Mem64ResStatus - add argument and description to function comment +// TODO: PMem64ResStatus - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_ABORTED - add return value to function comment +{ + BOOLEAN AllocationAjusted; + PCI_RESOURCE_NODE *PciResNode; + PCI_RESOURCE_NODE *ResPool[5]; + PCI_IO_DEVICE *RemovedPciDev[5]; + UINT64 ResStatus[5]; + UINTN RemovedPciDevNum; + UINTN DevIndex; + UINTN ResType; + EFI_STATUS Status; + REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData; + + PciResNode = NULL; + ZeroMem (RemovedPciDev, 5 * sizeof (PCI_IO_DEVICE *)); + RemovedPciDevNum = 0; + + ResPool[0] = IoPool; + ResPool[1] = Mem32Pool; + ResPool[2] = PMem32Pool; + ResPool[3] = Mem64Pool; + ResPool[4] = PMem64Pool; + + ResStatus[0] = IoResStatus; + ResStatus[1] = Mem32ResStatus; + ResStatus[2] = PMem32ResStatus; + ResStatus[3] = Mem64ResStatus; + ResStatus[4] = PMem64ResStatus; + + AllocationAjusted = FALSE; + + for (ResType = 0; ResType < 5; ResType++) { + + if (ResStatus[ResType] == EFI_RESOURCE_SATISFIED) { + continue; + } + + if (ResStatus[ResType] == EFI_RESOURCE_NONEXISTENT) { + // + // Hostbridge hasn't this resource type + // + return EFI_ABORTED; + } + + // + // Hostbridge hasn't enough resource + // + PciResNode = GetMaxResourceConsumerDevice (ResPool[ResType]); + if (!PciResNode) { + continue; + } + + // + // Check if the device has been removed before + // + for (DevIndex = 0; DevIndex < RemovedPciDevNum; DevIndex++) { + if (PciResNode->PciDev == RemovedPciDev[DevIndex]) { + continue; + } + } + + // + // Remove the device if it isn't in the array + // + Status = RejectPciDevice (PciResNode->PciDev); + if (Status == EFI_SUCCESS) { + + // + // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code + // + // + // Have no way to get ReqRes, AllocRes & Bar here + // + ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData)); + AllocFailExtendedData.DevicePathSize = sizeof (EFI_DEVICE_PATH_PROTOCOL); + AllocFailExtendedData.DevicePath = (UINT8 *) PciResNode->PciDev->DevicePath; + AllocFailExtendedData.Bar = PciResNode->Bar; + + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_PROGRESS_CODE, + EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT, + (VOID *) &AllocFailExtendedData, + sizeof (AllocFailExtendedData) + ); + + // + // Add it to the array and indicate at least a device has been rejected + // + RemovedPciDev[RemovedPciDevNum++] = PciResNode->PciDev; + AllocationAjusted = TRUE; + } + } + // + // End for + // + + if (AllocationAjusted) { + return EFI_SUCCESS; + } else { + return EFI_ABORTED; + } +} + +EFI_STATUS +ConstructAcpiResourceRequestor ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_RESOURCE_NODE *IoNode, + IN PCI_RESOURCE_NODE *Mem32Node, + IN PCI_RESOURCE_NODE *PMem32Node, + IN PCI_RESOURCE_NODE *Mem64Node, + IN PCI_RESOURCE_NODE *PMem64Node, + OUT VOID **pConfig + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: IoNode - add argument and description to function comment +// TODO: Mem32Node - add argument and description to function comment +// TODO: PMem32Node - add argument and description to function comment +// TODO: Mem64Node - add argument and description to function comment +// TODO: PMem64Node - add argument and description to function comment +// TODO: pConfig - add argument and description to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT8 NumConfig; + UINT8 Aperture; + UINT8 *Configuration; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; + EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd; + + NumConfig = 0; + Aperture = 0; + + *pConfig = NULL; + + // + // if there is io request, add to the io aperture + // + if (ResourceRequestExisted (IoNode)) { + NumConfig++; + Aperture |= 0x01; + } + + // + // if there is mem32 request, add to the mem32 aperture + // + if (ResourceRequestExisted (Mem32Node)) { + NumConfig++; + Aperture |= 0x02; + } + + // + // if there is pmem32 request, add to the pmem32 aperture + // + if (ResourceRequestExisted (PMem32Node)) { + NumConfig++; + Aperture |= 0x04; + } + + // + // if there is mem64 request, add to the mem64 aperture + // + if (ResourceRequestExisted (Mem64Node)) { + NumConfig++; + Aperture |= 0x08; + } + + // + // if there is pmem64 request, add to the pmem64 aperture + // + if (ResourceRequestExisted (PMem64Node)) { + NumConfig++; + Aperture |= 0x10; + } + + if (NumConfig != 0) { + + // + // If there is at least one type of resource request, + // allocate a acpi resource node + // + Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); + if (Configuration == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem ( + Configuration, + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR) + ); + + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; + + // + // Deal with io aperture + // + if (Aperture & 0x01) { + Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; + // + // Io + // + Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO; + // + // non ISA range + // + Ptr->SpecificFlag = 1; + Ptr->AddrLen = IoNode->Length; + Ptr->AddrRangeMax = IoNode->Alignment; + + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)); + } + // + // Deal with mem32 aperture + // + if (Aperture & 0x02) { + Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; + // + // Mem + // + Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // Nonprefechable + // + Ptr->SpecificFlag = 0; + // + // 32 bit + // + Ptr->AddrSpaceGranularity = 32; + Ptr->AddrLen = Mem32Node->Length; + Ptr->AddrRangeMax = Mem32Node->Alignment; + + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)); + } + + // + // Deal with Pmem32 aperture + // + if (Aperture & 0x04) { + Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; + // + // Mem + // + Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // prefechable + // + Ptr->SpecificFlag = 0x6; + // + // 32 bit + // + Ptr->AddrSpaceGranularity = 32; + Ptr->AddrLen = PMem32Node->Length; + Ptr->AddrRangeMax = PMem32Node->Alignment; + + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)); + } + // + // Deal with mem64 aperture + // + if (Aperture & 0x08) { + Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; + // + // Mem + // + Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // nonprefechable + // + Ptr->SpecificFlag = 0; + // + // 64 bit + // + Ptr->AddrSpaceGranularity = 64; + Ptr->AddrLen = Mem64Node->Length; + Ptr->AddrRangeMax = Mem64Node->Alignment; + + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)); + } + // + // Deal with Pmem64 aperture + // + if (Aperture & 0x10) { + Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; + // + // Mem + // + Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // prefechable + // + Ptr->SpecificFlag = 0x06; + // + // 64 bit + // + Ptr->AddrSpaceGranularity = 64; + Ptr->AddrLen = PMem64Node->Length; + Ptr->AddrRangeMax = PMem64Node->Alignment; + + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)); + } + + // + // put the checksum + // + PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr); + + PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR; + PtrEnd->Checksum = 0; + + } else { + + // + // If there is no resource request + // + Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); + if (Configuration == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem (Configuration, sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); + + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) (Configuration); + Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + + PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) (Configuration + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)); + PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR; + PtrEnd->Checksum = 0; + } + + *pConfig = Configuration; + + return EFI_SUCCESS; +} + +EFI_STATUS +GetResourceBase ( + IN VOID *pConfig, + OUT UINT64 *IoBase, + OUT UINT64 *Mem32Base, + OUT UINT64 *PMem32Base, + OUT UINT64 *Mem64Base, + OUT UINT64 *PMem64Base + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: pConfig - add argument and description to function comment +// TODO: IoBase - add argument and description to function comment +// TODO: Mem32Base - add argument and description to function comment +// TODO: PMem32Base - add argument and description to function comment +// TODO: Mem64Base - add argument and description to function comment +// TODO: PMem64Base - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT8 *Temp; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; + UINT64 ResStatus; + + *IoBase = 0xFFFFFFFFFFFFFFFFULL; + *Mem32Base = 0xFFFFFFFFFFFFFFFFULL; + *PMem32Base = 0xFFFFFFFFFFFFFFFFULL; + *Mem64Base = 0xFFFFFFFFFFFFFFFFULL; + *PMem64Base = 0xFFFFFFFFFFFFFFFFULL; + + Temp = (UINT8 *) pConfig; + + while (*Temp == ACPI_ADDRESS_SPACE_DESCRIPTOR) { + + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Temp; + ResStatus = Ptr->AddrTranslationOffset; + + if (ResStatus == EFI_RESOURCE_SATISFIED) { + + switch (Ptr->ResType) { + + // + // Memory type aperture + // + case 0: + + // + // Check to see the granularity + // + if (Ptr->AddrSpaceGranularity == 32) { + if (Ptr->SpecificFlag & 0x06) { + *PMem32Base = Ptr->AddrRangeMin; + } else { + *Mem32Base = Ptr->AddrRangeMin; + } + } + + if (Ptr->AddrSpaceGranularity == 64) { + if (Ptr->SpecificFlag & 0x06) { + *PMem64Base = Ptr->AddrRangeMin; + } else { + *Mem64Base = Ptr->AddrRangeMin; + } + } + break; + + case 1: + + // + // Io type aperture + // + *IoBase = Ptr->AddrRangeMin; + break; + + default: + break; + + } + // + // End switch + // + } + // + // End for + // + Temp += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciBridgeEnumerator ( + IN PCI_IO_DEVICE *BridgeDev + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: BridgeDev - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT8 SubBusNumber; + UINT8 StartBusNumber; + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_STATUS Status; + + SubBusNumber = 0; + StartBusNumber = 0; + PciIo = &(BridgeDev->PciIo); + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &StartBusNumber); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciAssignBusNumber ( + BridgeDev, + StartBusNumber, + &SubBusNumber + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciPciDeviceInfoCollector (BridgeDev, StartBusNumber); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciBridgeResourceAllocator (BridgeDev); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = DetermineDeviceAttribute (BridgeDev); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +PciBridgeResourceAllocator ( + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_RESOURCE_NODE *IoBridge; + PCI_RESOURCE_NODE *Mem32Bridge; + PCI_RESOURCE_NODE *PMem32Bridge; + PCI_RESOURCE_NODE *Mem64Bridge; + PCI_RESOURCE_NODE *PMem64Bridge; + UINT64 IoBase; + UINT64 Mem32Base; + UINT64 PMem32Base; + UINT64 Mem64Base; + UINT64 PMem64Base; + EFI_STATUS Status; + + IoBridge = CreateResourceNode ( + Bridge, + 0, + 0xFFF, + 0, + PciBarTypeIo16, + PciResUsageTypical + ); + + Mem32Bridge = CreateResourceNode ( + Bridge, + 0, + 0xFFFFF, + 0, + PciBarTypeMem32, + PciResUsageTypical + ); + + PMem32Bridge = CreateResourceNode ( + Bridge, + 0, + 0xFFFFF, + 0, + PciBarTypePMem32, + PciResUsageTypical + ); + + Mem64Bridge = CreateResourceNode ( + Bridge, + 0, + 0xFFFFF, + 0, + PciBarTypeMem64, + PciResUsageTypical + ); + + PMem64Bridge = CreateResourceNode ( + Bridge, + 0, + 0xFFFFF, + 0, + PciBarTypePMem64, + PciResUsageTypical + ); + + // + // Create resourcemap by going through all the devices subject to this root bridge + // + Status = CreateResourceMap ( + Bridge, + IoBridge, + Mem32Bridge, + PMem32Bridge, + Mem64Bridge, + PMem64Bridge + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetResourceBaseFromBridge ( + Bridge, + &IoBase, + &Mem32Base, + &PMem32Base, + &Mem64Base, + &PMem64Base + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Program IO resources + // + ProgramResource ( + IoBase, + IoBridge + ); + + // + // Program Mem32 resources + // + ProgramResource ( + Mem32Base, + Mem32Bridge + ); + + // + // Program PMem32 resources + // + ProgramResource ( + PMem32Base, + PMem32Bridge + ); + + // + // Program Mem64 resources + // + ProgramResource ( + Mem64Base, + Mem64Bridge + ); + + // + // Program PMem64 resources + // + ProgramResource ( + PMem64Base, + PMem64Bridge + ); + + DestroyResourceTree (IoBridge); + DestroyResourceTree (Mem32Bridge); + DestroyResourceTree (PMem32Bridge); + DestroyResourceTree (PMem64Bridge); + DestroyResourceTree (Mem64Bridge); + + gBS->FreePool (IoBridge); + gBS->FreePool (Mem32Bridge); + gBS->FreePool (PMem32Bridge); + gBS->FreePool (PMem64Bridge); + gBS->FreePool (Mem64Bridge); + + return EFI_SUCCESS; +} + +EFI_STATUS +GetResourceBaseFromBridge ( + IN PCI_IO_DEVICE *Bridge, + OUT UINT64 *IoBase, + OUT UINT64 *Mem32Base, + OUT UINT64 *PMem32Base, + OUT UINT64 *Mem64Base, + OUT UINT64 *PMem64Base + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: IoBase - add argument and description to function comment +// TODO: Mem32Base - add argument and description to function comment +// TODO: PMem32Base - add argument and description to function comment +// TODO: Mem64Base - add argument and description to function comment +// TODO: PMem64Base - add argument and description to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + if (!Bridge->Allocated) { + return EFI_OUT_OF_RESOURCES; + } + + *IoBase = gAllOne; + *Mem32Base = gAllOne; + *PMem32Base = gAllOne; + *Mem64Base = gAllOne; + *PMem64Base = gAllOne; + + if (IS_PCI_BRIDGE (&Bridge->Pci)) { + + if (Bridge->PciBar[PPB_IO_RANGE].Length) { + *IoBase = Bridge->PciBar[PPB_IO_RANGE].BaseAddress; + } + + if (Bridge->PciBar[PPB_MEM32_RANGE].Length) { + *Mem32Base = Bridge->PciBar[PPB_MEM32_RANGE].BaseAddress; + } + + if (Bridge->PciBar[PPB_PMEM32_RANGE].Length) { + *PMem32Base = Bridge->PciBar[PPB_PMEM32_RANGE].BaseAddress; + } + + if (Bridge->PciBar[PPB_PMEM64_RANGE].Length) { + *PMem64Base = Bridge->PciBar[PPB_PMEM64_RANGE].BaseAddress; + } else { + *PMem64Base = gAllOne; + } + + } + + if (IS_CARDBUS_BRIDGE (&Bridge->Pci)) { + if (Bridge->PciBar[P2C_IO_1].Length) { + *IoBase = Bridge->PciBar[P2C_IO_1].BaseAddress; + } else { + if (Bridge->PciBar[P2C_IO_2].Length) { + *IoBase = Bridge->PciBar[P2C_IO_2].BaseAddress; + } + } + + if (Bridge->PciBar[P2C_MEM_1].Length) { + if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypePMem32) { + *PMem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress; + } + + if (Bridge->PciBar[P2C_MEM_1].BarType == PciBarTypeMem32) { + *Mem32Base = Bridge->PciBar[P2C_MEM_1].BaseAddress; + } + } + + if (Bridge->PciBar[P2C_MEM_2].Length) { + if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypePMem32) { + *PMem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress; + } + + if (Bridge->PciBar[P2C_MEM_2].BarType == PciBarTypeMem32) { + *Mem32Base = Bridge->PciBar[P2C_MEM_2].BaseAddress; + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +NotifyPhase ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc, + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciResAlloc - add argument and description to function comment +// TODO: Phase - add argument and description to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_HANDLE HostBridgeHandle; + EFI_HANDLE RootBridgeHandle; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_STATUS Status; + + HostBridgeHandle = NULL; + RootBridgeHandle = NULL; + if (gPciPlatformProtocol != NULL) { + // + // Get Host Bridge Handle. + // + PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle); + + // + // Get the rootbridge Io protocol to find the host bridge handle + // + Status = gBS->HandleProtocol ( + RootBridgeHandle, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo + ); + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + HostBridgeHandle = PciRootBridgeIo->ParentHandle; + + // + // Call PlatformPci::PhaseNotify() if the protocol is present. + // + gPciPlatformProtocol->PhaseNotify ( + gPciPlatformProtocol, + HostBridgeHandle, + Phase, + ChipsetEntry + ); + } + + Status = PciResAlloc->NotifyPhase ( + PciResAlloc, + Phase + ); + + if (gPciPlatformProtocol != NULL) { + // + // Call PlatformPci::PhaseNotify() if the protocol is present. + // + gPciPlatformProtocol->PhaseNotify ( + gPciPlatformProtocol, + HostBridgeHandle, + Phase, + ChipsetExit + ); + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PreprocessController ( + IN PCI_IO_DEVICE *Bridge, + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 Func, + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: Bus - add argument and description to function comment +// TODO: Device - add argument and description to function comment +// TODO: Func - add argument and description to function comment +// TODO: Phase - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS RootBridgePciAddress; + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc; + EFI_HANDLE RootBridgeHandle; + EFI_HANDLE HostBridgeHandle; + EFI_STATUS Status; + + // + // Get the host bridge handle + // + HostBridgeHandle = Bridge->PciRootBridgeIo->ParentHandle; + + // + // Get the pci host bridge resource allocation protocol + // + Status = gBS->OpenProtocol ( + HostBridgeHandle, + &gEfiPciHostBridgeResourceAllocationProtocolGuid, + (VOID **) &PciResAlloc, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Get Root Brige Handle + // + while (Bridge->Parent) { + Bridge = Bridge->Parent; + } + + RootBridgeHandle = Bridge->Handle; + + RootBridgePciAddress.Register = 0; + RootBridgePciAddress.Function = Func; + RootBridgePciAddress.Device = Device; + RootBridgePciAddress.Bus = Bus; + RootBridgePciAddress.ExtendedRegister = 0; + + if (gPciPlatformProtocol != NULL) { + // + // Call PlatformPci::PrepController() if the protocol is present. + // + gPciPlatformProtocol->PlatformPrepController ( + gPciPlatformProtocol, + HostBridgeHandle, + RootBridgeHandle, + RootBridgePciAddress, + Phase, + ChipsetEntry + ); + } + + Status = PciResAlloc->PreprocessController ( + PciResAlloc, + RootBridgeHandle, + RootBridgePciAddress, + Phase + ); + + if (gPciPlatformProtocol != NULL) { + // + // Call PlatformPci::PrepController() if the protocol is present. + // + gPciPlatformProtocol->PlatformPrepController ( + gPciPlatformProtocol, + HostBridgeHandle, + RootBridgeHandle, + RootBridgePciAddress, + Phase, + ChipsetExit + ); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciHotPlugRequestNotify ( + IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This, + IN EFI_PCI_HOTPLUG_OPERATION Operation, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL, + IN OUT UINT8 *NumberOfChildren, + IN OUT EFI_HANDLE * ChildHandleBuffer + ) +/*++ + +Routine Description: + + Hot plug request notify. + +Arguments: + + This - A pointer to the hot plug request protocol. + Operation - The operation. + Controller - A pointer to the controller. + RemainningDevicePath - A pointer to the device path. + NumberOfChildren - A the number of child handle in the ChildHandleBuffer. + ChildHandleBuffer - A pointer to the array contain the child handle. + +Returns: + + Status code. + +--*/ +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *Bridge; + PCI_IO_DEVICE *Temp; + EFI_PCI_IO_PROTOCOL *PciIo; + UINTN Index; + EFI_HANDLE RootBridgeHandle; + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + gPciBusDriverBinding.DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + Bridge = PCI_IO_DEVICE_FROM_PCI_IO_THIS (PciIo); + + // + // Get root bridge handle + // + Temp = Bridge; + while (Temp->Parent) { + Temp = Temp->Parent; + } + + RootBridgeHandle = Temp->Handle; + + if (Operation == EfiPciHotPlugRequestAdd) { + + if (NumberOfChildren != NULL) { + *NumberOfChildren = 0; + } + + if (IsListEmpty (&Bridge->ChildList)) { + + Status = PciBridgeEnumerator (Bridge); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + Status = StartPciDevicesOnBridge ( + RootBridgeHandle, + Bridge, + RemainingDevicePath, + NumberOfChildren, + ChildHandleBuffer + ); + + return EFI_SUCCESS; + } + + if (Operation == EfiPciHotplugRequestRemove) { + + if (*NumberOfChildren == 0) { + // + // Remove all devices on the bridge + // + Status = RemoveAllPciDeviceOnBridge (RootBridgeHandle, Bridge); + return Status; + + } + + for (Index = 0; Index < *NumberOfChildren; Index++) { + // + // De register all the pci device + // + Status = DeRegisterPciDevice (RootBridgeHandle, ChildHandleBuffer[Index]); + + if (EFI_ERROR (Status)) { + return Status; + } + + } + // + // End for + // + return EFI_SUCCESS; + } + + return EFI_SUCCESS; +} + +BOOLEAN +SearchHostBridgeHandle ( + IN EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: RootBridgeHandle - add argument and description to function comment +{ + EFI_HANDLE HostBridgeHandle; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + UINTN Index; + EFI_STATUS Status; + + // + // Get the rootbridge Io protocol to find the host bridge handle + // + Status = gBS->OpenProtocol ( + RootBridgeHandle, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo, + gPciBusDriverBinding.DriverBindingHandle, + RootBridgeHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return FALSE; + } + + HostBridgeHandle = PciRootBridgeIo->ParentHandle; + for (Index = 0; Index < gPciHostBridgeNumber; Index++) { + if (HostBridgeHandle == gPciHostBrigeHandles[Index]) { + return TRUE; + } + } + + return FALSE; +} + +EFI_STATUS +AddHostBridgeEnumerator ( + IN EFI_HANDLE HostBridgeHandle + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: HostBridgeHandle - add argument and description to function comment +// TODO: EFI_ABORTED - add return value to function comment +// TODO: EFI_ABORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINTN Index; + + if (!HostBridgeHandle) { + return EFI_ABORTED; + } + + for (Index = 0; Index < gPciHostBridgeNumber; Index++) { + if (HostBridgeHandle == gPciHostBrigeHandles[Index]) { + return EFI_ABORTED; + } + } + + if (Index < PCI_MAX_HOST_BRIDGE_NUM) { + gPciHostBrigeHandles[Index] = HostBridgeHandle; + gPciHostBridgeNumber++; + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.h new file mode 100644 index 0000000000..e7667d5c49 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumerator.h @@ -0,0 +1,628 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciEnumerator.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_ENUMERATOR_H +#define _EFI_PCI_ENUMERATOR_H + +#include "PciResourceSupport.h" + +EFI_STATUS +PciEnumerator ( + IN EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciRootBridgeEnumerator ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc, + IN PCI_IO_DEVICE *RootBridgeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciResAlloc - TODO: add argument description + RootBridgeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ProcessOptionRom ( + IN PCI_IO_DEVICE *Bridge, + IN UINT64 RomBase, + IN UINT64 MaxLength + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + RomBase - TODO: add argument description + MaxLength - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciAssignBusNumber ( + IN PCI_IO_DEVICE *Bridge, + IN UINT8 StartBusNumber, + OUT UINT8 *SubBusNumber + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + StartBusNumber - TODO: add argument description + SubBusNumber - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DetermineRootBridgeAttributes ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc, + IN PCI_IO_DEVICE *RootBridgeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciResAlloc - TODO: add argument description + RootBridgeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +UINT64 +GetMaxOptionRomSize ( + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciHostBridgeDeviceAttribute ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciResAlloc - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetResourceAllocationStatus ( + VOID *AcpiConfig, + OUT UINT64 *IoResStatus, + OUT UINT64 *Mem32ResStatus, + OUT UINT64 *PMem32ResStatus, + OUT UINT64 *Mem64ResStatus, + OUT UINT64 *PMem64ResStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AcpiConfig - TODO: add argument description + IoResStatus - TODO: add argument description + Mem32ResStatus - TODO: add argument description + PMem32ResStatus - TODO: add argument description + Mem64ResStatus - TODO: add argument description + PMem64ResStatus - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +RejectPciDevice ( + IN PCI_IO_DEVICE *PciDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsRejectiveDevice ( + IN PCI_RESOURCE_NODE *PciResNode + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciResNode - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_RESOURCE_NODE * +GetLargerConsumerDevice ( + IN PCI_RESOURCE_NODE *PciResNode1, + IN PCI_RESOURCE_NODE *PciResNode2 + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciResNode1 - TODO: add argument description + PciResNode2 - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_RESOURCE_NODE * +GetMaxResourceConsumerDevice ( + IN PCI_RESOURCE_NODE *ResPool + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ResPool - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciHostBridgeAdjustAllocation ( + IN PCI_RESOURCE_NODE *IoPool, + IN PCI_RESOURCE_NODE *Mem32Pool, + IN PCI_RESOURCE_NODE *PMem32Pool, + IN PCI_RESOURCE_NODE *Mem64Pool, + IN PCI_RESOURCE_NODE *PMem64Pool, + IN UINT64 IoResStatus, + IN UINT64 Mem32ResStatus, + IN UINT64 PMem32ResStatus, + IN UINT64 Mem64ResStatus, + IN UINT64 PMem64ResStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + IoPool - TODO: add argument description + Mem32Pool - TODO: add argument description + PMem32Pool - TODO: add argument description + Mem64Pool - TODO: add argument description + PMem64Pool - TODO: add argument description + IoResStatus - TODO: add argument description + Mem32ResStatus - TODO: add argument description + PMem32ResStatus - TODO: add argument description + Mem64ResStatus - TODO: add argument description + PMem64ResStatus - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ConstructAcpiResourceRequestor ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_RESOURCE_NODE *IoNode, + IN PCI_RESOURCE_NODE *Mem32Node, + IN PCI_RESOURCE_NODE *PMem32Node, + IN PCI_RESOURCE_NODE *Mem64Node, + IN PCI_RESOURCE_NODE *PMem64Node, + OUT VOID **pConfig + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + IoNode - TODO: add argument description + Mem32Node - TODO: add argument description + PMem32Node - TODO: add argument description + Mem64Node - TODO: add argument description + PMem64Node - TODO: add argument description + pConfig - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetResourceBase ( + IN VOID *pConfig, + OUT UINT64 *IoBase, + OUT UINT64 *Mem32Base, + OUT UINT64 *PMem32Base, + OUT UINT64 *Mem64Base, + OUT UINT64 *PMem64Base + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + pConfig - TODO: add argument description + IoBase - TODO: add argument description + Mem32Base - TODO: add argument description + PMem32Base - TODO: add argument description + Mem64Base - TODO: add argument description + PMem64Base - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciBridgeEnumerator ( + IN PCI_IO_DEVICE *BridgeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + BridgeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciBridgeResourceAllocator ( + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetResourceBaseFromBridge ( + IN PCI_IO_DEVICE *Bridge, + OUT UINT64 *IoBase, + OUT UINT64 *Mem32Base, + OUT UINT64 *PMem32Base, + OUT UINT64 *Mem64Base, + OUT UINT64 *PMem64Base + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + IoBase - TODO: add argument description + Mem32Base - TODO: add argument description + PMem32Base - TODO: add argument description + Mem64Base - TODO: add argument description + PMem64Base - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciHostBridgeP2CProcess ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciResAlloc - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +NotifyPhase ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc, + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciResAlloc - TODO: add argument description + Phase - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PreprocessController ( + IN PCI_IO_DEVICE *Bridge, + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 Func, + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + Bus - TODO: add argument description + Device - TODO: add argument description + Func - TODO: add argument description + Phase - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciHotPlugRequestNotify ( + IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL * This, + IN EFI_PCI_HOTPLUG_OPERATION Operation, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL, + IN OUT UINT8 *NumberOfChildren, + IN OUT EFI_HANDLE * ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Operation - TODO: add argument description + Controller - TODO: add argument description + RemainingDevicePath - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +SearchHostBridgeHandle ( + IN EFI_HANDLE RootBridgeHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AddHostBridgeEnumerator ( + IN EFI_HANDLE HostBridgeHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + HostBridgeHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c new file mode 100644 index 0000000000..2c54897953 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.c @@ -0,0 +1,2261 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciEnumeratorSupport.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "Pcibus.h" +#include "PciEnumeratorSupport.h" +#include "PciCommand.h" +#include "PciIo.h" + +EFI_STATUS +PciDevicePresent ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + + This routine is used to check whether the pci device is present + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciRootBridgeIo - add argument and description to function comment +// TODO: Pci - add argument and description to function comment +// TODO: Bus - add argument and description to function comment +// TODO: Device - add argument and description to function comment +// TODO: Func - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + UINT64 Address; + EFI_STATUS Status; + + // + // Create PCI address map in terms of Bus, Device and Func + // + Address = EFI_PCI_ADDRESS (Bus, Device, Func, 0); + + // + // Read the Vendor Id register + // + Status = PciRootBridgeIo->Pci.Read ( + PciRootBridgeIo, + EfiPciWidthUint32, + Address, + 1, + Pci + ); + + if (!EFI_ERROR (Status) && (Pci->Hdr).VendorId != 0xffff) { + + // + // Read the entire config header for the device + // + + Status = PciRootBridgeIo->Pci.Read ( + PciRootBridgeIo, + EfiPciWidthUint32, + Address, + sizeof (PCI_TYPE00) / sizeof (UINT32), + Pci + ); + + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +PciPciDeviceInfoCollector ( + IN PCI_IO_DEVICE *Bridge, + UINT8 StartBusNumber + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: StartBusNumber - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + PCI_TYPE00 Pci; + UINT8 Device; + UINT8 Func; + UINT8 SecBus; + PCI_IO_DEVICE *PciIoDevice; + EFI_PCI_IO_PROTOCOL *PciIo; + + Status = EFI_SUCCESS; + SecBus = 0; + + for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { + + for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { + + // + // Check to see whether PCI device is present + // + + Status = PciDevicePresent ( + Bridge->PciRootBridgeIo, + &Pci, + (UINT8) StartBusNumber, + (UINT8) Device, + (UINT8) Func + ); + + if (!EFI_ERROR (Status)) { + + // + // Call back to host bridge function + // + PreprocessController (Bridge, (UINT8) StartBusNumber, Device, Func, EfiPciBeforeResourceCollection); + + // + // Collect all the information about the PCI device discovered + // + Status = PciSearchDevice ( + Bridge, + &Pci, + (UINT8) StartBusNumber, + Device, + Func, + &PciIoDevice + ); + + // + // Recursively scan PCI busses on the other side of PCI-PCI bridges + // + // + + if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci))) { + + // + // If it is PPB, we need to get the secondary bus to continue the enumeration + // + PciIo = &(PciIoDevice->PciIo); + + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x19, 1, &SecBus); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get resource padding for PPB + // + GetResourcePaddingPpb (PciIoDevice); + + // + // Deep enumerate the next level bus + // + Status = PciPciDeviceInfoCollector ( + PciIoDevice, + (UINT8) (SecBus) + ); + + } + + if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { + + // + // Skip sub functions, this is not a multi function device + // + Func = PCI_MAX_FUNC; + } + } + + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciSearchDevice ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_TYPE00 *Pci, + IN UINT8 Bus, + IN UINT8 Device, + IN UINT8 Func, + OUT PCI_IO_DEVICE **PciDevice + ) +/*++ + +Routine Description: + + Search required device. + +Arguments: + + Bridge - A pointer to the PCI_IO_DEVICE. + Pci - A pointer to the PCI_TYPE00. + Bus - Bus number. + Device - Device number. + Func - Function number. + PciDevice - The Required pci device. + +Returns: + + Status code. + +--*/ +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = NULL; + + if (!IS_PCI_BRIDGE (Pci)) { + + if (IS_CARDBUS_BRIDGE (Pci)) { + PciIoDevice = GatherP2CInfo ( + Bridge, + Pci, + Bus, + Device, + Func + ); + if (gFullEnumeration) { + InitializeP2C (PciIoDevice); + } + } else { + + // + // Create private data for Pci Device + // + PciIoDevice = GatherDeviceInfo ( + Bridge, + Pci, + Bus, + Device, + Func + ); + + } + + } else { + + // + // Create private data for PPB + // + PciIoDevice = GatherPpbInfo ( + Bridge, + Pci, + Bus, + Device, + Func + ); + + // + // Special initialization for PPB including making the PPB quiet + // + if (gFullEnumeration) { + InitializePpb (PciIoDevice); + } + } + + if (!PciIoDevice) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Update the bar information for this PCI device so as to support some specific device + // + UpdatePciInfo (PciIoDevice); + + if (PciIoDevice->DevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Detect this function has option rom + // + if (gFullEnumeration) { + + if (!IS_CARDBUS_BRIDGE (Pci)) { + + GetOpRomInfo (PciIoDevice); + + } + + ResetPowerManagementFeature (PciIoDevice); + + } + + // + // Insert it into a global tree for future reference + // + InsertPciDevice (Bridge, PciIoDevice); + + // + // Determine PCI device attributes + // + + if (PciDevice != NULL) { + *PciDevice = PciIoDevice; + } + + return EFI_SUCCESS; +} + +PCI_IO_DEVICE * +GatherDeviceInfo ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: Pci - add argument and description to function comment +// TODO: Bus - add argument and description to function comment +// TODO: Device - add argument and description to function comment +// TODO: Func - add argument and description to function comment +{ + UINTN Offset; + UINTN BarIndex; + PCI_IO_DEVICE *PciIoDevice; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + PciRootBridgeIo = Bridge->PciRootBridgeIo; + PciIoDevice = CreatePciIoDevice ( + PciRootBridgeIo, + Pci, + Bus, + Device, + Func + ); + + if (!PciIoDevice) { + return NULL; + } + + // + // Create a device path for this PCI device and store it into its private data + // + CreatePciDevicePath ( + Bridge->DevicePath, + PciIoDevice + ); + + // + // If it is a full enumeration, disconnect the device in advance + // + if (gFullEnumeration) { + + PciSetCommandRegister (PciIoDevice, 0); + + } + + // + // Start to parse the bars + // + for (Offset = 0x10, BarIndex = 0; Offset <= 0x24; BarIndex++) { + Offset = PciParseBar (PciIoDevice, Offset, BarIndex); + } + + return PciIoDevice; +} + +PCI_IO_DEVICE * +GatherPpbInfo ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: Pci - add argument and description to function comment +// TODO: Bus - add argument and description to function comment +// TODO: Device - add argument and description to function comment +// TODO: Func - add argument and description to function comment +{ + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + PCI_IO_DEVICE *PciIoDevice; + EFI_STATUS Status; + UINT32 Value; + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Temp; + + PciRootBridgeIo = Bridge->PciRootBridgeIo; + PciIoDevice = CreatePciIoDevice ( + PciRootBridgeIo, + Pci, + Bus, + Device, + Func + ); + + if (!PciIoDevice) { + return NULL; + } + + // + // Create a device path for this PCI device and store it into its private data + // + CreatePciDevicePath ( + Bridge->DevicePath, + PciIoDevice + ); + + if (gFullEnumeration) { + PciSetCommandRegister (PciIoDevice, 0); + + // + // Initalize the bridge control register + // + PciSetBridgeControlRegister (PciIoDevice, 0); + + } + + // + // PPB can have two BARs + // + if (PciParseBar (PciIoDevice, 0x10, PPB_BAR_0) == 0x14) { + // + // Not 64-bit bar + // + PciParseBar (PciIoDevice, 0x14, PPB_BAR_1); + } + + PciIo = &PciIoDevice->PciIo; + + // + // Test whether it support 32 decode or not + // + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne); + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Value); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &Temp); + + if (Value) { + if (Value & 0x01) { + PciIoDevice->Decodes |= EFI_BRIDGE_IO32_DECODE_SUPPORTED; + } else { + PciIoDevice->Decodes |= EFI_BRIDGE_IO16_DECODE_SUPPORTED; + } + } + + Status = BarExisted ( + PciIoDevice, + 0x24, + NULL, + NULL + ); + + // + // test if it supports 64 memory or not + // + if (!EFI_ERROR (Status)) { + + Status = BarExisted ( + PciIoDevice, + 0x28, + NULL, + NULL + ); + + if (!EFI_ERROR (Status)) { + PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; + PciIoDevice->Decodes |= EFI_BRIDGE_PMEM64_DECODE_SUPPORTED; + } else { + PciIoDevice->Decodes |= EFI_BRIDGE_PMEM32_DECODE_SUPPORTED; + } + } + + // + // Memory 32 code is required for ppb + // + PciIoDevice->Decodes |= EFI_BRIDGE_MEM32_DECODE_SUPPORTED; + + GetResourcePaddingPpb (PciIoDevice); + + return PciIoDevice; +} + +PCI_IO_DEVICE * +GatherP2CInfo ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: Pci - add argument and description to function comment +// TODO: Bus - add argument and description to function comment +// TODO: Device - add argument and description to function comment +// TODO: Func - add argument and description to function comment +{ + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + PCI_IO_DEVICE *PciIoDevice; + + PciRootBridgeIo = Bridge->PciRootBridgeIo; + PciIoDevice = CreatePciIoDevice ( + PciRootBridgeIo, + Pci, + Bus, + Device, + Func + ); + + if (!PciIoDevice) { + return NULL; + } + + // + // Create a device path for this PCI device and store it into its private data + // + CreatePciDevicePath ( + Bridge->DevicePath, + PciIoDevice + ); + + if (gFullEnumeration) { + PciSetCommandRegister (PciIoDevice, 0); + + // + // Initalize the bridge control register + // + PciSetBridgeControlRegister (PciIoDevice, 0); + + } + // + // P2C only has one bar that is in 0x10 + // + PciParseBar (PciIoDevice, 0x10, P2C_BAR_0); + + // + // Read PciBar information from the bar register + // + GetBackPcCardBar (PciIoDevice); + PciIoDevice->Decodes = EFI_BRIDGE_MEM32_DECODE_SUPPORTED | + EFI_BRIDGE_PMEM32_DECODE_SUPPORTED | + EFI_BRIDGE_IO32_DECODE_SUPPORTED; + + return PciIoDevice; +} + +EFI_DEVICE_PATH_PROTOCOL * +CreatePciDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: ParentDevicePath - add argument and description to function comment +// TODO: PciIoDevice - add argument and description to function comment +{ + + PCI_DEVICE_PATH PciNode; + + // + // Create PCI device path + // + PciNode.Header.Type = HARDWARE_DEVICE_PATH; + PciNode.Header.SubType = HW_PCI_DP; + SetDevicePathNodeLength (&PciNode.Header, sizeof (PciNode)); + + PciNode.Device = PciIoDevice->DeviceNumber; + PciNode.Function = PciIoDevice->FunctionNumber; + PciIoDevice->DevicePath = AppendDevicePathNode (ParentDevicePath, &PciNode.Header); + + return PciIoDevice->DevicePath; +} + +EFI_STATUS +BarExisted ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINTN Offset, + OUT UINT32 *BarLengthValue, + OUT UINT32 *OriginalBarValue + ) +/*++ + +Routine Description: + + Check the bar is existed or not. + +Arguments: + + PciIoDevice - A pointer to the PCI_IO_DEVICE. + Offset - The offset. + BarLengthValue - The bar length value. + OriginalBarValue - The original bar value. + +Returns: + + EFI_NOT_FOUND - The bar don't exist. + EFI_SUCCESS - The bar exist. + +--*/ +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINT32 OriginalValue; + UINT32 Value; + EFI_TPL OldTpl; + + PciIo = &PciIoDevice->PciIo; + + // + // Preserve the original value + // + + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue); + + // + // Raise TPL to high level to disable timer interrupt while the BAR is probed + // + OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &gAllOne); + PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &Value); + + // + // Write back the original value + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, (UINT8) Offset, 1, &OriginalValue); + + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (BarLengthValue != NULL) { + *BarLengthValue = Value; + } + + if (OriginalBarValue != NULL) { + *OriginalBarValue = OriginalValue; + } + + if (Value == 0) { + return EFI_NOT_FOUND; + } else { + return EFI_SUCCESS; + } +} + +EFI_STATUS +PciTestSupportedAttribute ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 *Command, + IN UINT16 *BridgeControl, + IN UINT16 *OldCommand, + IN UINT16 *OldBridgeControl + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: Command - add argument and description to function comment +// TODO: BridgeControl - add argument and description to function comment +// TODO: OldCommand - add argument and description to function comment +// TODO: OldBridgeControl - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_TPL OldTpl; + + // + // Preserve the original value + // + PciReadCommandRegister (PciIoDevice, OldCommand); + + // + // Raise TPL to high level to disable timer interrupt while the BAR is probed + // + OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + + PciSetCommandRegister (PciIoDevice, *Command); + PciReadCommandRegister (PciIoDevice, Command); + + // + // Write back the original value + // + PciSetCommandRegister (PciIoDevice, *OldCommand); + + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { + + // + // Preserve the original value + // + PciReadBridgeControlRegister (PciIoDevice, OldBridgeControl); + + // + // Raise TPL to high level to disable timer interrupt while the BAR is probed + // + OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + + PciSetBridgeControlRegister (PciIoDevice, *BridgeControl); + PciReadBridgeControlRegister (PciIoDevice, BridgeControl); + + // + // Write back the original value + // + PciSetBridgeControlRegister (PciIoDevice, *OldBridgeControl); + + // + // Restore TPL to its original level + // + gBS->RestoreTPL (OldTpl); + + } else { + *OldBridgeControl = 0; + *BridgeControl = 0; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciSetDeviceAttribute ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command, + IN UINT16 BridgeControl, + IN UINTN Option + ) +/*++ + + Routine Description: + Set the supported or current attributes of a PCI device + + Arguments: + PciIoDevice - Structure pointer for PCI device. + Command - Command register value. + BridgeControl - Bridge control value for PPB or P2C. + Option - Make a choice of EFI_SET_SUPPORTS or EFI_SET_ATTRIBUTES. + + Returns: + +--*/ + +/*++ + +Routine Description: + + + +Arguments: + + +Returns: + + EFI_SUCCESS Always success + + +--*/ +{ + UINT64 Attributes; + + Attributes = 0; + + if (Command & EFI_PCI_COMMAND_IO_SPACE) { + Attributes |= EFI_PCI_IO_ATTRIBUTE_IO; + } + + if (Command & EFI_PCI_COMMAND_MEMORY_SPACE) { + Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY; + } + + if (Command & EFI_PCI_COMMAND_BUS_MASTER) { + Attributes |= EFI_PCI_IO_ATTRIBUTE_BUS_MASTER; + } + + if (Command & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) { + Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; + } + + if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_ISA) { + Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO; + } + + if (BridgeControl & EFI_PCI_BRIDGE_CONTROL_VGA) { + Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO; + Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY; + Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; + } + + if (Option == EFI_SET_SUPPORTS) { + + Attributes |= EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE | + EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED | + EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE | + EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE | + EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM | + EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE; + + if (Attributes & EFI_PCI_IO_ATTRIBUTE_IO) { + Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO; + Attributes |= EFI_PCI_IO_ATTRIBUTE_ISA_IO; + } + + if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { + // + // For bridge, it should support IDE attributes + // + Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO; + Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO; + } else { + + if (IS_PCI_IDE (&PciIoDevice->Pci)) { + Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO; + Attributes |= EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO; + } + + if (IS_PCI_VGA (&PciIoDevice->Pci)) { + Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY; + Attributes |= EFI_PCI_IO_ATTRIBUTE_VGA_IO; + } + } + + PciIoDevice->Supports = Attributes; + PciIoDevice->Supports &= ( (PciIoDevice->Parent->Supports) | \ + EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | \ + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER ); + + } else { + PciIoDevice->Attributes = Attributes; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetFastBackToBackSupport ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT8 StatusIndex + ) +/*++ + +Routine Description: + + Determine if the device can support Fast Back to Back attribute + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: StatusIndex - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_PCI_IO_PROTOCOL *PciIo; + EFI_STATUS Status; + UINT32 StatusRegister; + + // + // Read the status register + // + PciIo = &PciIoDevice->PciIo; + Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, StatusIndex, 1, &StatusRegister); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Check the Fast B2B bit + // + if (StatusRegister & EFI_PCI_FAST_BACK_TO_BACK_CAPABLE) { + return EFI_SUCCESS; + } else { + return EFI_UNSUPPORTED; + } + +} + +EFI_STATUS +ProcessOptionRomLight ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + Process the option ROM for all the children of the specified parent PCI device. + It can only be used after the first full Option ROM process. + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *Temp; + LIST_ENTRY *CurrentLink; + + // + // For RootBridge, PPB , P2C, go recursively to traverse all its children + // + CurrentLink = PciIoDevice->ChildList.ForwardLink; + while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (!IsListEmpty (&Temp->ChildList)) { + ProcessOptionRomLight (Temp); + } + + PciRomGetImageMapping (Temp); + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DetermineDeviceAttribute ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + Determine the related attributes of all devices under a Root Bridge + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT16 Command; + UINT16 BridgeControl; + UINT16 OldCommand; + UINT16 OldBridgeControl; + BOOLEAN FastB2BSupport; + + /* + UINT8 IdePI; + EFI_PCI_IO_PROTOCOL *PciIo; + */ + PCI_IO_DEVICE *Temp; + LIST_ENTRY *CurrentLink; + EFI_STATUS Status; + + // + // For Root Bridge, just copy it by RootBridgeIo proctocol + // so as to keep consistent with the actual attribute + // + if (!PciIoDevice->Parent) { + Status = PciIoDevice->PciRootBridgeIo->GetAttributes ( + PciIoDevice->PciRootBridgeIo, + &PciIoDevice->Supports, + &PciIoDevice->Attributes + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + + // + // Set the attributes to be checked for common PCI devices and PPB or P2C + // Since some devices only support part of them, it is better to set the + // attribute according to its command or bridge control register + // + Command = EFI_PCI_COMMAND_IO_SPACE | + EFI_PCI_COMMAND_MEMORY_SPACE | + EFI_PCI_COMMAND_BUS_MASTER | + EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + + BridgeControl = EFI_PCI_BRIDGE_CONTROL_ISA | EFI_PCI_BRIDGE_CONTROL_VGA; + + // + // Test whether the device can support attributes above + // + PciTestSupportedAttribute (PciIoDevice, &Command, &BridgeControl, &OldCommand, &OldBridgeControl); + + // + // Set the supported attributes for specified PCI device + // + PciSetDeviceAttribute (PciIoDevice, Command, BridgeControl, EFI_SET_SUPPORTS); + + // + // Set the current attributes for specified PCI device + // + PciSetDeviceAttribute (PciIoDevice, OldCommand, OldBridgeControl, EFI_SET_ATTRIBUTES); + + // + // Enable other supported attributes but not defined in PCI_IO_PROTOCOL + // + PciEnableCommandRegister (PciIoDevice, EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE); + + // + // Enable IDE native mode + // + /* + if (IS_PCI_IDE(&PciIoDevice->Pci)) { + + PciIo = &PciIoDevice->PciIo; + + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + 0x09, + 1, + &IdePI + ); + + // + // Set native mode if it can be supported + // + IdePI |= (((IdePI & 0x0F) >> 1) & 0x05); + + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint8, + 0x09, + 1, + &IdePI + ); + + } + */ + } + + FastB2BSupport = TRUE; + + // + // P2C can not support FB2B on the secondary side + // + if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { + FastB2BSupport = FALSE; + } + + // + // For RootBridge, PPB , P2C, go recursively to traverse all its children + // + CurrentLink = PciIoDevice->ChildList.ForwardLink; + while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + Status = DetermineDeviceAttribute (Temp); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Detect Fast Bact to Bact support for the device under the bridge + // + Status = GetFastBackToBackSupport (Temp, PCI_PRIMARY_STATUS_OFFSET); + if (FastB2BSupport && EFI_ERROR (Status)) { + FastB2BSupport = FALSE; + } + + CurrentLink = CurrentLink->ForwardLink; + } + // + // Set or clear Fast Back to Back bit for the whole bridge + // + if (!IsListEmpty (&PciIoDevice->ChildList)) { + + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { + + Status = GetFastBackToBackSupport (PciIoDevice, PCI_BRIDGE_STATUS_REGISTER_OFFSET); + + if (EFI_ERROR (Status) || (!FastB2BSupport)) { + FastB2BSupport = FALSE; + PciDisableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK); + } else { + PciEnableBridgeControlRegister (PciIoDevice, EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK); + } + } + + CurrentLink = PciIoDevice->ChildList.ForwardLink; + while (CurrentLink && CurrentLink != &PciIoDevice->ChildList) { + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + if (FastB2BSupport) { + PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK); + } else { + PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_FAST_BACK_TO_BACK); + } + + CurrentLink = CurrentLink->ForwardLink; + } + } + // + // End for IsListEmpty + // + return EFI_SUCCESS; +} + +EFI_STATUS +UpdatePciInfo ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + This routine is used to update the bar information for those incompatible PCI device + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + UINTN BarIndex; + UINTN BarEndIndex; + BOOLEAN SetFlag; + VOID *Configuration; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; + + Configuration = NULL; + + // + // It can only be supported after the Incompatible PCI Device + // Support Protocol has been installed + // + if (gEfiIncompatiblePciDeviceSupport == NULL) { + + Status = gBS->LocateProtocol ( + &gEfiIncompatiblePciDeviceSupportProtocolGuid, + NULL, + (VOID **) &gEfiIncompatiblePciDeviceSupport + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + } + + // + // Check whether the device belongs to incompatible devices or not + // If it is , then get its special requirement in the ACPI table + // + Status = gEfiIncompatiblePciDeviceSupport->CheckDevice ( + gEfiIncompatiblePciDeviceSupport, + PciIoDevice->Pci.Hdr.VendorId, + PciIoDevice->Pci.Hdr.DeviceId, + PciIoDevice->Pci.Hdr.RevisionID, + PciIoDevice->Pci.Device.SubsystemVendorID, + PciIoDevice->Pci.Device.SubsystemID, + &Configuration + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Update PCI device information from the ACPI table + // + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; + + while (Ptr->Desc != ACPI_END_TAG_DESCRIPTOR) { + + if (Ptr->Desc != ACPI_ADDRESS_SPACE_DESCRIPTOR) { + // + // The format is not support + // + break; + } + + BarIndex = (UINTN) Ptr->AddrTranslationOffset; + BarEndIndex = BarIndex; + + // + // Update all the bars in the device + // + if (BarIndex == PCI_BAR_ALL) { + BarIndex = 0; + BarEndIndex = PCI_MAX_BAR - 1; + } + + if (BarIndex >= PCI_MAX_BAR) { + Ptr++; + continue; + } + + for (; BarIndex <= BarEndIndex; BarIndex++) { + SetFlag = FALSE; + switch (Ptr->ResType) { + case ACPI_ADDRESS_SPACE_TYPE_MEM: + + // + // Make sure the bar is memory type + // + if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeMem)) { + SetFlag = TRUE; + } + break; + + case ACPI_ADDRESS_SPACE_TYPE_IO: + + // + // Make sure the bar is IO type + // + if (CheckBarType (PciIoDevice, (UINT8) BarIndex, PciBarTypeIo)) { + SetFlag = TRUE; + } + break; + } + + if (SetFlag) { + + // + // Update the new alignment for the device + // + SetNewAlign (&(PciIoDevice->PciBar[BarIndex].Alignment), Ptr->AddrRangeMax); + + // + // Update the new length for the device + // + if (Ptr->AddrLen != PCI_BAR_NOCHANGE) { + PciIoDevice->PciBar[BarIndex].Length = Ptr->AddrLen; + } + } + } + + Ptr++; + } + + gBS->FreePool (Configuration); + return Status; + +} + +VOID +SetNewAlign ( + IN UINT64 *Alignment, + IN UINT64 NewAlignment + ) +/*++ + +Routine Description: + + This routine will update the alignment with the new alignment + +Arguments: + +Returns: + + None + +--*/ +// TODO: Alignment - add argument and description to function comment +// TODO: NewAlignment - add argument and description to function comment +{ + UINT64 OldAlignment; + UINTN ShiftBit; + + // + // The new alignment is the same as the original, + // so skip it + // + if (NewAlignment == PCI_BAR_OLD_ALIGN) { + return ; + } + // + // Check the validity of the parameter + // + if (NewAlignment != PCI_BAR_EVEN_ALIGN && + NewAlignment != PCI_BAR_SQUAD_ALIGN && + NewAlignment != PCI_BAR_DQUAD_ALIGN ) { + *Alignment = NewAlignment; + return ; + } + + OldAlignment = (*Alignment) + 1; + ShiftBit = 0; + + // + // Get the first non-zero hex value of the length + // + while ((OldAlignment & 0x0F) == 0x00) { + OldAlignment = RShiftU64 (OldAlignment, 4); + ShiftBit += 4; + } + + // + // Adjust the alignment to even, quad or double quad boundary + // + if (NewAlignment == PCI_BAR_EVEN_ALIGN) { + if (OldAlignment & 0x01) { + OldAlignment = OldAlignment + 2 - (OldAlignment & 0x01); + } + } else if (NewAlignment == PCI_BAR_SQUAD_ALIGN) { + if (OldAlignment & 0x03) { + OldAlignment = OldAlignment + 4 - (OldAlignment & 0x03); + } + } else if (NewAlignment == PCI_BAR_DQUAD_ALIGN) { + if (OldAlignment & 0x07) { + OldAlignment = OldAlignment + 8 - (OldAlignment & 0x07); + } + } + + // + // Update the old value + // + NewAlignment = LShiftU64 (OldAlignment, ShiftBit) - 1; + *Alignment = NewAlignment; + + return ; +} + +UINTN +PciParseBar ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINTN Offset, + IN UINTN BarIndex + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +{ + UINT32 Value; + UINT64 BarValue64; + UINT32 OriginalValue; + UINT32 Mask; + UINT32 Data; + UINT8 Index; + EFI_STATUS Status; + + OriginalValue = 0; + Value = 0; + BarValue64 = 0; + + Status = BarExisted ( + PciIoDevice, + Offset, + &Value, + &OriginalValue + ); + + if (EFI_ERROR (Status)) { + PciIoDevice->PciBar[BarIndex].BaseAddress = 0; + PciIoDevice->PciBar[BarIndex].Length = 0; + PciIoDevice->PciBar[BarIndex].Alignment = 0; + + // + // Some devices don't fully comply to PCI spec 2.2. So be to scan all the BARs anyway + // + PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset; + return Offset + 4; + } + + PciIoDevice->PciBar[BarIndex].Offset = (UINT8) Offset; + if (Value & 0x01) { + // + // Device I/Os + // + Mask = 0xfffffffc; + + if (Value & 0xFFFF0000) { + // + // It is a IO32 bar + // + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo32; + PciIoDevice->PciBar[BarIndex].Length = ((~(Value & Mask)) + 1); + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + } else { + // + // It is a IO16 bar + // + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeIo16; + PciIoDevice->PciBar[BarIndex].Length = 0x0000FFFF & ((~(Value & Mask)) + 1); + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + } + // + // Workaround. Some platforms inplement IO bar with 0 length + // Need to treat it as no-bar + // + if (PciIoDevice->PciBar[BarIndex].Length == 0) { + PciIoDevice->PciBar[BarIndex].BarType = 0; + } + + PciIoDevice->PciBar[BarIndex].Prefetchable = FALSE; + PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask; + + } else { + + Mask = 0xfffffff0; + + PciIoDevice->PciBar[BarIndex].BaseAddress = OriginalValue & Mask; + + switch (Value & 0x07) { + + // + //memory space; anywhere in 32 bit address space + // + case 0x00: + if (Value & 0x08) { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem32; + } else { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem32; + } + + PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1; + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + break; + + // + // memory space; anywhere in 64 bit address space + // + case 0x04: + if (Value & 0x08) { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypePMem64; + } else { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeMem64; + } + + // + // According to PCI 2.2,if the bar indicates a memory 64 decoding, next bar + // is regarded as an extension for the first bar. As a result + // the sizing will be conducted on combined 64 bit value + // Here just store the masked first 32bit value for future size + // calculation + // + PciIoDevice->PciBar[BarIndex].Length = Value & Mask; + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + // + // Increment the offset to point to next DWORD + // + Offset += 4; + + Status = BarExisted ( + PciIoDevice, + Offset, + &Value, + &OriginalValue + ); + + if (EFI_ERROR (Status)) { + return Offset + 4; + } + + // + // Fix the length to support some spefic 64 bit BAR + // + Data = Value; + Index = 0; + for (Data = Value; Data != 0; Data >>= 1) { + Index ++; + } + Value |= ((UINT32)(-1) << Index); + + // + // Calculate the size of 64bit bar + // + PciIoDevice->PciBar[BarIndex].BaseAddress |= LShiftU64 ((UINT64) OriginalValue, 32); + + PciIoDevice->PciBar[BarIndex].Length = PciIoDevice->PciBar[BarIndex].Length | LShiftU64 ((UINT64) Value, 32); + PciIoDevice->PciBar[BarIndex].Length = (~(PciIoDevice->PciBar[BarIndex].Length)) + 1; + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + break; + + // + // reserved + // + default: + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; + PciIoDevice->PciBar[BarIndex].Length = (~(Value & Mask)) + 1; + PciIoDevice->PciBar[BarIndex].Alignment = PciIoDevice->PciBar[BarIndex].Length - 1; + + break; + } + } + + // + // Check the length again so as to keep compatible with some special bars + // + if (PciIoDevice->PciBar[BarIndex].Length == 0) { + PciIoDevice->PciBar[BarIndex].BarType = PciBarTypeUnknown; + PciIoDevice->PciBar[BarIndex].BaseAddress = 0; + PciIoDevice->PciBar[BarIndex].Alignment = 0; + } + + // + // Increment number of bar + // + return Offset + 4; +} + +EFI_STATUS +InitializePciDevice ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + This routine is used to initialize the bar of a PCI device + It can be called typically when a device is going to be rejected + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINT8 Offset; + + PciIo = &(PciIoDevice->PciIo); + + // + // Put all the resource apertures + // Resource base is set to all ones so as to indicate its resource + // has not been alloacted + // + for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) { + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllOne); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +InitializePpb ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_PCI_IO_PROTOCOL *PciIo; + + PciIo = &(PciIoDevice->PciIo); + + // + // Put all the resource apertures including IO16 + // Io32, pMem32, pMem64 to quiescent state + // Resource base all ones, Resource limit all zeros + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1C, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x1D, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x20, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x22, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x24, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x26, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2C, 1, &gAllZero); + + // + // don't support use io32 as for now + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x30, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint16, 0x32, 1, &gAllZero); + + // + // Force Interrupt line to zero for cards that come up randomly + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero); + + return EFI_SUCCESS; +} + +EFI_STATUS +InitializeP2C ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_PCI_IO_PROTOCOL *PciIo; + + PciIo = &(PciIoDevice->PciIo); + + // + // Put all the resource apertures including IO16 + // Io32, pMem32, pMem64 to quiescent state( + // Resource base all ones, Resource limit all zeros + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x1c, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x20, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x24, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x28, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x2c, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x30, 1, &gAllZero); + + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x34, 1, &gAllOne); + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, 0x38, 1, &gAllZero); + + // + // Force Interrupt line to zero for cards that come up randomly + // + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero); + return EFI_SUCCESS; +} + +PCI_IO_DEVICE * +CreatePciIoDevice ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciRootBridgeIo - add argument and description to function comment +// TODO: Pci - add argument and description to function comment +// TODO: Bus - add argument and description to function comment +// TODO: Device - add argument and description to function comment +// TODO: Func - add argument and description to function comment +{ + + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = NULL; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (PCI_IO_DEVICE), + (VOID **) &PciIoDevice + ); + + if (EFI_ERROR (Status)) { + return NULL; + } + + ZeroMem (PciIoDevice, sizeof (PCI_IO_DEVICE)); + + PciIoDevice->Signature = PCI_IO_DEVICE_SIGNATURE; + PciIoDevice->Handle = NULL; + PciIoDevice->PciRootBridgeIo = PciRootBridgeIo; + PciIoDevice->DevicePath = NULL; + PciIoDevice->BusNumber = Bus; + PciIoDevice->DeviceNumber = Device; + PciIoDevice->FunctionNumber = Func; + PciIoDevice->Decodes = 0; + if (gFullEnumeration) { + PciIoDevice->Allocated = FALSE; + } else { + PciIoDevice->Allocated = TRUE; + } + + PciIoDevice->Registered = FALSE; + PciIoDevice->Attributes = 0; + PciIoDevice->Supports = 0; + PciIoDevice->BusOverride = FALSE; + PciIoDevice->AllOpRomProcessed = FALSE; + + PciIoDevice->IsPciExp = FALSE; + + CopyMem (&(PciIoDevice->Pci), Pci, sizeof (PCI_TYPE01)); + + // + // Initialize the PCI I/O instance structure + // + + Status = InitializePciIoInstance (PciIoDevice); + Status = InitializePciDriverOverrideInstance (PciIoDevice); + + if (EFI_ERROR (Status)) { + gBS->FreePool (PciIoDevice); + return NULL; + } + + // + // Initialize the reserved resource list + // + InitializeListHead (&PciIoDevice->ReservedResourceList); + + // + // Initialize the driver list + // + InitializeListHead (&PciIoDevice->OptionRomDriverList); + + // + // Initialize the child list + // + InitializeListHead (&PciIoDevice->ChildList); + + return PciIoDevice; +} + +EFI_STATUS +PciEnumeratorLight ( + IN EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + This routine is used to enumerate entire pci bus system + in a given platform + +Arguments: + +Returns: + + None + +--*/ +// TODO: Controller - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + PCI_IO_DEVICE *RootBridgeDev; + UINT16 MinBus; + UINT16 MaxBus; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + + MinBus = 0; + MaxBus = PCI_MAX_BUS; + Descriptors = NULL; + + // + // If this host bridge has been already enumerated, then return successfully + // + if (RootBridgeExisted (Controller)) { + return EFI_SUCCESS; + } + + // + // Open pci root bridge io protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo, + gPciBusDriverBinding.DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); + + if (EFI_ERROR (Status)) { + return Status; + } + + while (PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL) == EFI_SUCCESS) { + + // + // Create a device node for root bridge device with a NULL host bridge controller handle + // + RootBridgeDev = CreateRootBridge (Controller); + + if (!RootBridgeDev) { + Descriptors++; + continue; + } + + // + // Record the root bridge io protocol + // + RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo; + + Status = PciPciDeviceInfoCollector ( + RootBridgeDev, + (UINT8) MinBus + ); + + if (!EFI_ERROR (Status)) { + + // + // Remove those PCI devices which are rejected when full enumeration + // + RemoveRejectedPciDevices (RootBridgeDev->Handle, RootBridgeDev); + + // + // Process option rom light + // + ProcessOptionRomLight (RootBridgeDev); + + // + // Determine attributes for all devices under this root bridge + // + DetermineDeviceAttribute (RootBridgeDev); + + // + // If successfully, insert the node into device pool + // + InsertRootBridge (RootBridgeDev); + } else { + + // + // If unsuccessly, destroy the entire node + // + DestroyRootBridge (RootBridgeDev); + } + + Descriptors++; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciGetBusRange ( + IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, + OUT UINT16 *MinBus, + OUT UINT16 *MaxBus, + OUT UINT16 *BusRange + ) +/*++ + +Routine Description: + + Get the bus range. + +Arguments: + + Descriptors - A pointer to the address space descriptor. + MinBus - The min bus. + MaxBus - The max bus. + BusRange - The bus range. + +Returns: + + Status Code. + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + + while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) { + if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) { + if (MinBus != NULL) { + *MinBus = (UINT16) (*Descriptors)->AddrRangeMin; + } + + if (MaxBus != NULL) { + *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax; + } + + if (BusRange != NULL) { + *BusRange = (UINT16) (*Descriptors)->AddrLen; + } + + return EFI_SUCCESS; + } + + (*Descriptors)++; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +StartManagingRootBridge ( + IN PCI_IO_DEVICE *RootBridgeDev + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +// TODO: RootBridgeDev - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_HANDLE RootBridgeHandle; + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + // + // Get the root bridge handle + // + RootBridgeHandle = RootBridgeDev->Handle; + PciRootBridgeIo = NULL; + + // + // Get the pci root bridge io protocol + // + Status = gBS->OpenProtocol ( + RootBridgeHandle, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo, + gPciBusDriverBinding.DriverBindingHandle, + RootBridgeHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + // + // Store the PciRootBridgeIo protocol into root bridge private data + // + RootBridgeDev->PciRootBridgeIo = PciRootBridgeIo; + + return EFI_SUCCESS; + +} + +BOOLEAN +IsPciDeviceRejected ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + This routine can be used to check whether a PCI device should be rejected when light enumeration + +Arguments: + +Returns: + + TRUE This device should be rejected + FALSE This device shouldn't be rejected + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +{ + EFI_STATUS Status; + UINT32 TestValue; + UINT32 OldValue; + UINT32 Mask; + UINT8 BarOffset; + + // + // PPB should be skip! + // + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { + return FALSE; + } + + if (IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { + // + // Only test base registers for P2C + // + for (BarOffset = 0x1C; BarOffset <= 0x38; BarOffset += 2 * sizeof (UINT32)) { + + Mask = (BarOffset < 0x2C) ? 0xFFFFF000 : 0xFFFFFFFC; + Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue); + if (EFI_ERROR (Status)) { + continue; + } + + TestValue = TestValue & Mask; + if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { + // + // The bar isn't programed, so it should be rejected + // + return TRUE; + } + } + + return FALSE; + } + + for (BarOffset = 0x14; BarOffset <= 0x24; BarOffset += sizeof (UINT32)) { + // + // Test PCI devices + // + Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue); + if (EFI_ERROR (Status)) { + continue; + } + + if (TestValue & 0x01) { + + // + // IO Bar + // + + Mask = 0xFFFFFFFC; + TestValue = TestValue & Mask; + if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { + return TRUE; + } + + } else { + + // + // Mem Bar + // + + Mask = 0xFFFFFFF0; + TestValue = TestValue & Mask; + + if ((TestValue & 0x07) == 0x04) { + + // + // Mem64 or PMem64 + // + BarOffset += sizeof (UINT32); + if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { + + // + // Test its high 32-Bit BAR + // + + Status = BarExisted (PciIoDevice, BarOffset, &TestValue, &OldValue); + if (TestValue == OldValue) { + return TRUE; + } + } + + } else { + + // + // Mem32 or PMem32 + // + if ((TestValue != 0) && (TestValue == (OldValue & Mask))) { + return TRUE; + } + } + } + } + + return FALSE; +} + +EFI_STATUS +ResetAllPpbBusReg ( + IN PCI_IO_DEVICE *Bridge, + IN UINT8 StartBusNumber + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + StartBusNumber - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + PCI_TYPE00 Pci; + UINT8 Device; + UINT32 Register; + UINT8 Func; + UINT64 Address; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + PciRootBridgeIo = Bridge->PciRootBridgeIo; + + for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { + for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { + + // + // Check to see whether a pci device is present + // + Status = PciDevicePresent ( + PciRootBridgeIo, + &Pci, + StartBusNumber, + Device, + Func + ); + + if (!EFI_ERROR (Status) && (IS_PCI_BRIDGE (&Pci))) { + Register = 0; + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18); + Status = PciRootBridgeIo->Pci.Read ( + PciRootBridgeIo, + EfiPciWidthUint32, + Address, + 1, + &Register + ); + // + // Reset register 18h, 19h, 1Ah on PCI Bridge + // + Register &= 0xFF000000; + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint32, + Address, + 1, + &Register + ); + } + + if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { + // + // Skip sub functions, this is not a multi function device + // + Func = PCI_MAX_FUNC; + } + } + } + + return EFI_SUCCESS; +} + diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.h new file mode 100644 index 0000000000..41d6efb102 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciEnumeratorSupport.h @@ -0,0 +1,598 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciEnumeratorSupport.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_ENUMERATOR_SUPPORT_H +#define _EFI_PCI_ENUMERATOR_SUPPORT_H + +EFI_STATUS +PciDevicePresent ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciRootBridgeIo - TODO: add argument description + Pci - TODO: add argument description + Bus - TODO: add argument description + Device - TODO: add argument description + Func - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciPciDeviceInfoCollector ( + IN PCI_IO_DEVICE *Bridge, + UINT8 StartBusNumber + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + StartBusNumber - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciSearchDevice ( + IN PCI_IO_DEVICE *Bridge, + PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func, + PCI_IO_DEVICE **PciDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + Pci - TODO: add argument description + Bus - TODO: add argument description + Device - TODO: add argument description + Func - TODO: add argument description + PciDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +GatherDeviceInfo ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + Pci - TODO: add argument description + Bus - TODO: add argument description + Device - TODO: add argument description + Func - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +GatherPpbInfo ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + Pci - TODO: add argument description + Bus - TODO: add argument description + Device - TODO: add argument description + Func - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +GatherP2CInfo ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + Pci - TODO: add argument description + Bus - TODO: add argument description + Device - TODO: add argument description + Func - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +CreatePciDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ParentDevicePath - TODO: add argument description + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +BarExisted ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINTN Offset, + OUT UINT32 *BarLengthValue, + OUT UINT32 *OriginalBarValue + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + Offset - TODO: add argument description + BarLengthValue - TODO: add argument description + OriginalBarValue - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciTestSupportedAttribute ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 *Command, + IN UINT16 *BridgeControl, + IN UINT16 *OldCommand, + IN UINT16 *OldBridgeControl + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + Command - TODO: add argument description + BridgeControl - TODO: add argument description + OldCommand - TODO: add argument description + OldBridgeControl - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciSetDeviceAttribute ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT16 Command, + IN UINT16 BridgeControl, + IN UINTN Option + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + Command - TODO: add argument description + BridgeControl - TODO: add argument description + Option - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetFastBackToBackSupport ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT8 StatusIndex + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + StatusIndex - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DetermineDeviceAttribute ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +UpdatePciInfo ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +SetNewAlign ( + IN UINT64 *Alignment, + IN UINT64 NewAlignment + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Alignment - TODO: add argument description + NewAlignment - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +UINTN +PciParseBar ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINTN Offset, + IN UINTN BarIndex + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + Offset - TODO: add argument description + BarIndex - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +InitializePciDevice ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +InitializePpb ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +InitializeP2C ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_IO_DEVICE * +CreatePciIoDevice ( + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + IN PCI_TYPE00 *Pci, + UINT8 Bus, + UINT8 Device, + UINT8 Func + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciRootBridgeIo - TODO: add argument description + Pci - TODO: add argument description + Bus - TODO: add argument description + Device - TODO: add argument description + Func - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciEnumeratorLight ( + IN EFI_HANDLE Controller + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Controller - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciGetBusRange ( + IN EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors, + OUT UINT16 *MinBus, + OUT UINT16 *MaxBus, + OUT UINT16 *BusRange + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Descriptors - TODO: add argument description + MinBus - TODO: add argument description + MaxBus - TODO: add argument description + BusRange - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +StartManagingRootBridge ( + IN PCI_IO_DEVICE *RootBridgeDev + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeDev - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsPciDeviceRejected ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c new file mode 100644 index 0000000000..4ebf9a7afc --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.c @@ -0,0 +1,462 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciHotPlugSupport.c + +Abstract: + + + +Revision History + +--*/ + +#include "Pcibus.h" +#include "PciHotPlugSupport.h" + +EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit; +EFI_HPC_LOCATION *gPciRootHpcPool; +UINTN gPciRootHpcCount; +ROOT_HPC_DATA *gPciRootHpcData; + +VOID +EFIAPI +PciHPCInitialized ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Event - add argument and description to function comment +// TODO: Context - add argument and description to function comment +{ + ROOT_HPC_DATA *HpcData; + + HpcData = (ROOT_HPC_DATA *) Context; + HpcData->Initialized = TRUE; + +} + +BOOLEAN +EfiCompareDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: DevicePath1 - add argument and description to function comment +// TODO: DevicePath2 - add argument and description to function comment +{ + UINTN Size1; + UINTN Size2; + + Size1 = GetDevicePathSize (DevicePath1); + Size2 = GetDevicePathSize (DevicePath2); + + if (Size1 != Size2) { + return FALSE; + } + + if (CompareMem (DevicePath1, DevicePath2, Size1)) { + return FALSE; + } + + return TRUE; +} + +EFI_STATUS +InitializeHotPlugSupport ( + VOID + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_HPC_LOCATION *HpcList; + UINTN HpcCount; + + // + // Locate the PciHotPlugInit Protocol + // If it doesn't exist, that means there is no + // hot plug controller supported on the platform + // the PCI Bus driver is running on. HotPlug Support + // is an optional feature, so absence of the protocol + // won't incur the penalty + // + gPciHotPlugInit = NULL; + gPciRootHpcPool = NULL; + gPciRootHpcCount = 0; + gPciRootHpcData = NULL; + + Status = gBS->LocateProtocol ( + &gEfiPciHotPlugInitProtocolGuid, + NULL, + (VOID **) &gPciHotPlugInit + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = gPciHotPlugInit->GetRootHpcList ( + gPciHotPlugInit, + &HpcCount, + &HpcList + ); + + if (!EFI_ERROR (Status)) { + + gPciRootHpcPool = HpcList; + gPciRootHpcCount = HpcCount; + gPciRootHpcData = AllocateZeroPool (sizeof (ROOT_HPC_DATA) * gPciRootHpcCount); + if (gPciRootHpcData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + + return EFI_SUCCESS; +} + +BOOLEAN +IsRootPciHotPlugBus ( + IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath, + OUT UINTN *HpIndex + ) +/*++ + +Routine Description: + +Arguments: + + HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL. + HpIndex - A pointer to the Index. + +Returns: + + None + +--*/ +// TODO: HpbDevicePath - add argument and description to function comment +{ + UINTN Index; + + for (Index = 0; Index < gPciRootHpcCount; Index++) { + + if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpbDevicePath, HpbDevicePath)) { + + if (HpIndex != NULL) { + *HpIndex = Index; + } + + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN +IsRootPciHotPlugController ( + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + OUT UINTN *HpIndex + ) +/*++ + +Routine Description: + +Arguments: + + HpcDevicePath - A pointer to the EFI_DEVICE_PATH_PROTOCOL. + HpIndex - A pointer to the Index. + +Returns: + + None + +--*/ +{ + UINTN Index; + + for (Index = 0; Index < gPciRootHpcCount; Index++) { + + if (EfiCompareDevicePath (gPciRootHpcPool[Index].HpcDevicePath, HpcDevicePath)) { + + if (HpIndex != NULL) { + *HpIndex = Index; + } + + return TRUE; + } + } + + return FALSE; +} + +EFI_STATUS +CreateEventForHpc ( + IN UINTN HpIndex, + OUT EFI_EVENT *Event + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: HpIndex - add argument and description to function comment +// TODO: Event - add argument and description to function comment +{ + EFI_STATUS Status; + + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + PciHPCInitialized, + gPciRootHpcData + HpIndex, + &((gPciRootHpcData + HpIndex)->Event) + ); + + if (!EFI_ERROR (Status)) { + *Event = (gPciRootHpcData + HpIndex)->Event; + } + + return Status; +} + +EFI_STATUS +AllRootHPCInitialized ( + IN UINTN TimeoutInMilliSeconds + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: TimeoutInMilliSeconds - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_TIMEOUT - add return value to function comment +{ + UINT32 Delay; + UINTN Index; + + Delay = (UINT32) (((TimeoutInMilliSeconds * STALL_1_MILLI_SECOND) / 30) + 1); + do { + + for (Index = 0; Index < gPciRootHpcCount; Index++) { + + if (!gPciRootHpcData[Index].Initialized) { + break; + } + } + + if (Index == gPciRootHpcCount) { + return EFI_SUCCESS; + } + + // + // Stall for 30 us + // + gBS->Stall (30); + + Delay--; + + } while (Delay); + + return EFI_TIMEOUT; +} + +EFI_STATUS +IsSHPC ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + + EFI_STATUS Status; + UINT8 Offset; + + if (!PciIoDevice) { + return EFI_NOT_FOUND; + } + + Offset = 0; + Status = LocateCapabilityRegBlock ( + PciIoDevice, + EFI_PCI_CAPABILITY_ID_HOTPLUG, + &Offset, + NULL + ); + + // + // If the PPB has the hot plug controller build-in, + // then return TRUE; + // + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +GetResourcePaddingForHpb ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + EFI_STATUS Status; + EFI_HPC_STATE State; + UINT64 PciAddress; + EFI_HPC_PADDING_ATTRIBUTES Attributes; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + + Status = IsPciHotPlugBus (PciIoDevice); + + if (!EFI_ERROR (Status)) { + PciAddress = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0); + Status = gPciHotPlugInit->GetResourcePadding ( + gPciHotPlugInit, + PciIoDevice->DevicePath, + PciAddress, + &State, + (VOID **) &Descriptors, + &Attributes + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if ((State & EFI_HPC_STATE_ENABLED) && (State & EFI_HPC_STATE_INITIALIZED)) { + PciIoDevice->ResourcePaddingDescriptors = Descriptors; + PciIoDevice->PaddingAttributes = Attributes; + } + + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +IsPciHotPlugBus ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + BOOLEAN Result; + EFI_STATUS Status; + + Status = IsSHPC (PciIoDevice); + + // + // If the PPB has the hot plug controller build-in, + // then return TRUE; + // + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // + // Otherwise, see if it is a Root HPC + // + Result = IsRootPciHotPlugBus (PciIoDevice->DevicePath, NULL); + + if (Result) { + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.h new file mode 100644 index 0000000000..df49ebaf56 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciHotPlugSupport.h @@ -0,0 +1,269 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciHotPlugSupport.h + +Abstract: + + + +Revision History + +--*/ + +#ifndef _EFI_PCI_HOT_PLUG_SUPPORT_H +#define _EFI_PCI_HOT_PLUG_SUPPORT_H + +// +// stall 1 ms +// +#define STALL_1_MILLI_SECOND 1000 + +// +// stall 1 second +// +#define STALL_1_SECOND 1000000 + +typedef struct { + EFI_EVENT Event; + BOOLEAN Initialized; + VOID *Padding; +} ROOT_HPC_DATA; + +extern EFI_PCI_HOT_PLUG_INIT_PROTOCOL *gPciHotPlugInit; +extern EFI_HPC_LOCATION *gPciRootHpcPool; +extern UINTN gPciRootHpcCount; +extern ROOT_HPC_DATA *gPciRootHpcData; + +VOID +EFIAPI +PciHPCInitialized ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Event - TODO: add argument description + Context - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +EfiCompareDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2 + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + DevicePath1 - TODO: add argument description + DevicePath2 - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +InitializeHotPlugSupport ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +IsPciHotPlugBus ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsRootPciHotPlugBus ( + IN EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath, + OUT UINTN *HpIndex + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + HpbDevicePath - TODO: add argument description + HpIndex - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsRootPciHotPlugController ( + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + OUT UINTN *HpIndex + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + HpcDevicePath - TODO: add argument description + HpIndex - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CreateEventForHpc ( + IN UINTN HpIndex, + OUT EFI_EVENT *Event + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + HpIndex - TODO: add argument description + Event - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AllRootHPCInitialized ( + IN UINTN TimeoutInMilliSeconds + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + TimeoutInMilliSeconds - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +IsSHPC ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetResourcePaddingForHpb ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.c new file mode 100644 index 0000000000..4f1737f5af --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.c @@ -0,0 +1,1964 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciIo.c + +Abstract: + + PCI I/O Abstraction Driver + +Revision History + +--*/ + +#include "Pcibus.h" + +// +// Internal use only +// +STATIC +EFI_STATUS +ReportErrorStatusCode ( + IN PCI_IO_DEVICE *PciIoDevice, + IN EFI_STATUS_CODE_VALUE Code + ); + +// +// PCI I/O Support Function Prototypes +// +// +// +// Pci Io Protocol Interface +// +static EFI_PCI_IO_PROTOCOL PciIoInterface = { + PciIoPollMem, + PciIoPollIo, + { + PciIoMemRead, + PciIoMemWrite + }, + { + PciIoIoRead, + PciIoIoWrite + }, + { + PciIoConfigRead, + PciIoConfigWrite + }, + PciIoCopyMem, + PciIoMap, + PciIoUnmap, + PciIoAllocateBuffer, + PciIoFreeBuffer, + PciIoFlush, + PciIoGetLocation, + PciIoAttributes, + PciIoGetBarAttributes, + PciIoSetBarAttributes, + 0, + NULL +}; + +STATIC +EFI_STATUS +ReportErrorStatusCode ( + IN PCI_IO_DEVICE *PciIoDevice, + IN EFI_STATUS_CODE_VALUE Code + ) +/*++ + +Routine Description: + + report a error Status code of PCI bus driver controller + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: Code - add argument and description to function comment +{ + return REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + Code, + PciIoDevice->DevicePath + ); +} + +EFI_STATUS +InitializePciIoInstance ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + Initializes a PCI I/O Instance + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + CopyMem (&PciIoDevice->PciIo, &PciIoInterface, sizeof (EFI_PCI_IO_PROTOCOL)); + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoVerifyBarAccess ( + PCI_IO_DEVICE *PciIoDevice, + UINT8 BarIndex, + PCI_BAR_TYPE Type, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + UINT64 *Offset + ) +/*++ + +Routine Description: + + Verifies access to a PCI Base Address Register (BAR) + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +// TODO: Type - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: Count - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + if (Width < 0 || Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (BarIndex == EFI_PCI_IO_PASS_THROUGH_BAR) { + return EFI_SUCCESS; + } + + // + // BarIndex 0-5 is legal + // + if (BarIndex >= PCI_MAX_BAR) { + return EFI_INVALID_PARAMETER; + } + + if (!CheckBarType (PciIoDevice, BarIndex, Type)) { + return EFI_INVALID_PARAMETER; + } + + // + // If Width is EfiPciIoWidthFifoUintX then convert to EfiPciIoWidthUintX + // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX + // + if (Width >= EfiPciWidthFifoUint8 && Width <= EfiPciWidthFifoUint64) { + Count = 1; + } + + Width &= 0x03; + + if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PciIoDevice->PciBar[BarIndex].Length) { + return EFI_INVALID_PARAMETER; + } + + *Offset = *Offset + PciIoDevice->PciBar[BarIndex].BaseAddress; + + return EFI_SUCCESS; +} + +EFI_STATUS +PciIoVerifyConfigAccess ( + PCI_IO_DEVICE *PciIoDevice, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN UINT64 *Offset + ) +/*++ + +Routine Description: + + Verifies access to a PCI Config Header + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: Count - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 ExtendOffset; + + if (Width < 0 || Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + // + // If Width is EfiPciIoWidthFillUintX then convert to EfiPciIoWidthUintX + // + Width &= 0x03; + + if (PciIoDevice->IsPciExp) { + if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_EXP_MAX_CONFIG_OFFSET) { + return EFI_UNSUPPORTED; + } + + ExtendOffset = LShiftU64 (*Offset, 32); + *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, 0); + *Offset = (*Offset) | ExtendOffset; + + } else { + if ((*Offset + Count * (UINTN)(1 << Width)) - 1 >= PCI_MAX_CONFIG_OFFSET) { + return EFI_UNSUPPORTED; + } + + *Offset = EFI_PCI_ADDRESS (PciIoDevice->BusNumber, PciIoDevice->DeviceNumber, PciIoDevice->FunctionNumber, *Offset); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciIoPollMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +/*++ + +Routine Description: + + Poll PCI Memmory + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: Mask - add argument and description to function comment +// TODO: Value - add argument and description to function comment +// TODO: Delay - add argument and description to function comment +// TODO: Result - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Width < 0 || Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, 1, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + if (Width > EfiPciIoWidthUint64) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoDevice->PciRootBridgeIo->PollMem ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Mask, + Value, + Delay, + Result + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoPollIo ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +/*++ + +Routine Description: + + Poll PCI IO + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: Mask - add argument and description to function comment +// TODO: Value - add argument and description to function comment +// TODO: Delay - add argument and description to function comment +// TODO: Result - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Width < 0 || Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, 1, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + if (Width > EfiPciIoWidthUint64) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoDevice->PciRootBridgeIo->PollIo ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Mask, + Value, + Delay, + Result + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoMemRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI Memory Read Cycle + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: Count - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Width < 0 || Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->Mem.Read ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoMemWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI Memory Write Cycle + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: Count - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Width < 0 || Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeMem, Width, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->Mem.Write ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoIoRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI I/O Read Cycle + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: Count - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Width < 0 || Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->Io.Read ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoIoWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI I/O Write Cycle + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: Count - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Width < 0 || Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, BarIndex, PciBarTypeIo, Width, Count, &Offset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->Io.Write ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Offset, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoConfigRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI Configuration Read Cycle + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: Count - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + UINT64 Address; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + Address = Offset; + Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciIoDevice->PciRootBridgeIo->Pci.Read ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_READ_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoConfigWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Performs a PCI Configuration Write Cycle + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: Count - add argument and description to function comment +// TODO: Buffer - add argument and description to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + UINT64 Address; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + Address = Offset; + Status = PciIoVerifyConfigAccess (PciIoDevice, Width, Count, &Address); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciIoDevice->PciRootBridgeIo->Pci.Write ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + Address, + Count, + Buffer + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_WRITE_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoCopyMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count + ) +/*++ + +Routine Description: + + Copy PCI Memory + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Width - add argument and description to function comment +// TODO: DestBarIndex - add argument and description to function comment +// TODO: DestOffset - add argument and description to function comment +// TODO: SrcBarIndex - add argument and description to function comment +// TODO: SrcOffset - add argument and description to function comment +// TODO: Count - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Width < 0 || Width >= EfiPciIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (Width == EfiPciIoWidthFifoUint8 || + Width == EfiPciIoWidthFifoUint16 || + Width == EfiPciIoWidthFifoUint32 || + Width == EfiPciIoWidthFifoUint64 || + Width == EfiPciIoWidthFillUint8 || + Width == EfiPciIoWidthFillUint16 || + Width == EfiPciIoWidthFillUint32 || + Width == EfiPciIoWidthFillUint64) { + return EFI_INVALID_PARAMETER; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, DestBarIndex, PciBarTypeMem, Width, Count, &DestOffset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoVerifyBarAccess (PciIoDevice, SrcBarIndex, PciBarTypeMem, Width, Count, &SrcOffset); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciRootBridgeIo->CopyMem ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH) Width, + DestOffset, + SrcOffset, + Count + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoMap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +/*++ + +Routine Description: + + Maps a memory region for DMA + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Operation - add argument and description to function comment +// TODO: HostAddress - add argument and description to function comment +// TODO: NumberOfBytes - add argument and description to function comment +// TODO: DeviceAddress - add argument and description to function comment +// TODO: Mapping - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Operation < 0 || Operation >= EfiPciIoOperationMaximum) { + return EFI_INVALID_PARAMETER; + } + + if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) { + Operation = Operation + EfiPciOperationBusMasterRead64; + } + + Status = PciIoDevice->PciRootBridgeIo->Map ( + PciIoDevice->PciRootBridgeIo, + (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION) Operation, + HostAddress, + NumberOfBytes, + DeviceAddress, + Mapping + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ) +/*++ + +Routine Description: + + Unmaps a memory region for DMA + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Mapping - add argument and description to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + Status = PciIoDevice->PciRootBridgeIo->Unmap ( + PciIoDevice->PciRootBridgeIo, + Mapping + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoAllocateBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + Allocates a common buffer for DMA + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Type - add argument and description to function comment +// TODO: MemoryType - add argument and description to function comment +// TODO: Pages - add argument and description to function comment +// TODO: HostAddress - add argument and description to function comment +// TODO: Attributes - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + if (Attributes & + (~(EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE | EFI_PCI_ATTRIBUTE_MEMORY_CACHED))) { + return EFI_UNSUPPORTED; + } + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (PciIoDevice->Attributes & EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE) { + Attributes |= EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE; + } + + Status = PciIoDevice->PciRootBridgeIo->AllocateBuffer ( + PciIoDevice->PciRootBridgeIo, + Type, + MemoryType, + Pages, + HostAddress, + Attributes + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoFreeBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +/*++ + +Routine Description: + + Frees a common buffer + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Pages - add argument and description to function comment +// TODO: HostAddress - add argument and description to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + Status = PciIoDevice->PciRootBridgeIo->FreeBuffer ( + PciIoDevice->PciRootBridgeIo, + Pages, + HostAddress + ); + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoFlush ( + IN EFI_PCI_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + Flushes a DMA buffer + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + Status = PciIoDevice->PciRootBridgeIo->Flush ( + PciIoDevice->PciRootBridgeIo + ); + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoGetLocation ( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *Segment, + OUT UINTN *Bus, + OUT UINTN *Device, + OUT UINTN *Function + ) +/*++ + +Routine Description: + + Gets a PCI device's current bus number, device number, and function number. + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Segment - add argument and description to function comment +// TODO: Bus - add argument and description to function comment +// TODO: Device - add argument and description to function comment +// TODO: Function - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *PciIoDevice; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Segment == NULL || Bus == NULL || Device == NULL || Function == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Segment = PciIoDevice->PciRootBridgeIo->SegmentNumber; + *Bus = PciIoDevice->BusNumber; + *Device = PciIoDevice->DeviceNumber; + *Function = PciIoDevice->FunctionNumber; + + return EFI_SUCCESS; +} + +BOOLEAN +CheckBarType ( + IN PCI_IO_DEVICE *PciIoDevice, + UINT8 BarIndex, + PCI_BAR_TYPE BarType + ) +/*++ + +Routine Description: + + Sets a PCI controllers attributes on a resource range + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +// TODO: BarType - add argument and description to function comment +{ + switch (BarType) { + + case PciBarTypeMem: + + if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem32 && + PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem32 && + PciIoDevice->PciBar[BarIndex].BarType != PciBarTypePMem64 && + PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeMem64 ) { + return FALSE; + } + + return TRUE; + + case PciBarTypeIo: + if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo32 && + PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeIo16){ + return FALSE; + } + + return TRUE; + + default: + break; + } + + return FALSE; +} + +EFI_STATUS +ModifyRootBridgeAttributes ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT64 Attributes, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation + ) +/*++ + +Routine Description: + + Set new attributes to a Root Bridge + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: Attributes - add argument and description to function comment +// TODO: Operation - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 PciRootBridgeSupports; + UINT64 PciRootBridgeAttributes; + UINT64 NewPciRootBridgeAttributes; + EFI_STATUS Status; + + // + // Get the current attributes of this PCI device's PCI Root Bridge + // + Status = PciIoDevice->PciRootBridgeIo->GetAttributes ( + PciIoDevice->PciRootBridgeIo, + &PciRootBridgeSupports, + &PciRootBridgeAttributes + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Record the new attribute of the Root Bridge + // + if (Operation == EfiPciIoAttributeOperationEnable) { + NewPciRootBridgeAttributes = PciRootBridgeAttributes | Attributes; + } else { + NewPciRootBridgeAttributes = PciRootBridgeAttributes & (~Attributes); + } + + // + // Call the PCI Root Bridge to attempt to modify the attributes + // + if (NewPciRootBridgeAttributes ^ PciRootBridgeAttributes) { + + Status = PciIoDevice->PciRootBridgeIo->SetAttributes ( + PciIoDevice->PciRootBridgeIo, + NewPciRootBridgeAttributes, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + // + // The PCI Root Bridge could not modify the attributes, so return the error. + // + return EFI_UNSUPPORTED; + } + } + + // + // Also update the attributes for this Root Bridge structure + // + PciIoDevice->Attributes = NewPciRootBridgeAttributes; + return EFI_SUCCESS; + +} + +EFI_STATUS +SupportPaletteSnoopAttributes ( + IN PCI_IO_DEVICE *PciIoDevice, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation + ) +/*++ + +Routine Description: + + Check whether this device can be enable/disable to snoop + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: Operation - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *Temp; + UINT16 VGACommand; + + // + // Snoop attribute can be only modified by GFX + // + if (!IS_PCI_GFX (&PciIoDevice->Pci)) { + return EFI_UNSUPPORTED; + } + + // + // Get the boot VGA on the same segement + // + Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice); + + if (!Temp) { + // + // If there is no VGA device on the segement, set + // this graphics card to decode the palette range + // + return EFI_SUCCESS; + } + + // + // Check these two agents are on the same path + // + if (!PciDevicesOnTheSamePath (Temp, PciIoDevice)) { + // + // they are not on the same path, so snoop can be enabled or disabled + // + return EFI_SUCCESS; + } + // + // Check if they are on the same bus + // + if (Temp->Parent == PciIoDevice->Parent) { + + PciReadCommandRegister (Temp, &VGACommand); + + // + // If they are on the same bus, either one can + // be set to snoop, the other set to decode + // + if (VGACommand & EFI_PCI_COMMAND_VGA_PALETTE_SNOOP) { + // + // VGA has set to snoop, so GFX can be only set to disable snoop + // + if (Operation == EfiPciIoAttributeOperationEnable) { + return EFI_UNSUPPORTED; + } + } else { + // + // VGA has disabled to snoop, so GFX can be only enabled + // + if (Operation == EfiPciIoAttributeOperationDisable) { + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; + } + + // + // If they are on the same path but on the different bus + // The first agent is set to snoop, the second one set to + // decode + // + + if (Temp->BusNumber > PciIoDevice->BusNumber) { + // + // GFX should be set to decode + // + if (Operation == EfiPciIoAttributeOperationDisable) { + PciEnableCommandRegister (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP); + Temp->Attributes |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + } else { + return EFI_UNSUPPORTED; + } + + } else { + // + // GFX should be set to snoop + // + if (Operation == EfiPciIoAttributeOperationEnable) { + PciDisableCommandRegister (Temp, EFI_PCI_COMMAND_VGA_PALETTE_SNOOP); + Temp->Attributes &= (~EFI_PCI_COMMAND_VGA_PALETTE_SNOOP); + } else { + return EFI_UNSUPPORTED; + } + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciIoAttributes ( + IN EFI_PCI_IO_PROTOCOL * This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Operation - add argument and description to function comment +// TODO: Attributes - add argument and description to function comment +// TODO: Result - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + + PCI_IO_DEVICE *PciIoDevice; + PCI_IO_DEVICE *UpStreamBridge; + PCI_IO_DEVICE *Temp; + + UINT64 Supports; + UINT64 UpStreamAttributes; + UINT16 BridgeControl; + UINT16 Command; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + switch (Operation) { + case EfiPciIoAttributeOperationGet: + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Result = PciIoDevice->Attributes; + return EFI_SUCCESS; + + case EfiPciIoAttributeOperationSupported: + if (Result == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Result = PciIoDevice->Supports; + return EFI_SUCCESS; + + case EfiPciIoAttributeOperationSet: + Status = PciIoDevice->PciIo.Attributes ( + &(PciIoDevice->PciIo), + EfiPciIoAttributeOperationEnable, + Attributes, + NULL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = PciIoDevice->PciIo.Attributes ( + &(PciIoDevice->PciIo), + EfiPciIoAttributeOperationDisable, + (~Attributes) & (PciIoDevice->Supports), + NULL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; + + case EfiPciIoAttributeOperationEnable: + case EfiPciIoAttributeOperationDisable: + break; + + default: + return EFI_INVALID_PARAMETER; + } + // + // Just a trick for ENABLE attribute + // + if ((Attributes & EFI_PCI_DEVICE_ENABLE) == EFI_PCI_DEVICE_ENABLE) { + Attributes &= (PciIoDevice->Supports); + + // + // Raise the EFI_P_PC_ENABLE Status code + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_IO_BUS_PCI | EFI_P_PC_ENABLE, + PciIoDevice->DevicePath + ); + } + + // + // If no attributes can be supported, then return. + // Otherwise, set the attributes that it can support. + // + Supports = (PciIoDevice->Supports) & Attributes; + if (Supports != Attributes) { + return EFI_UNSUPPORTED; + } + + // + // For Root Bridge, just call RootBridgeIo to set attributes; + // + if (!PciIoDevice->Parent) { + Status = ModifyRootBridgeAttributes (PciIoDevice, Attributes, Operation); + return Status; + } + + Command = 0; + BridgeControl = 0; + + // + // For PPB & P2C, set relevant attribute bits + // + if (IS_PCI_BRIDGE (&PciIoDevice->Pci) || IS_CARDBUS_BRIDGE (&PciIoDevice->Pci)) { + + if (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) { + BridgeControl |= EFI_PCI_BRIDGE_CONTROL_VGA; + } + + if (Attributes & EFI_PCI_IO_ATTRIBUTE_ISA_IO) { + BridgeControl |= EFI_PCI_BRIDGE_CONTROL_ISA; + } + + if (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) { + Command |= EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO; + } + + } else { + // + // Do with the attributes on VGA + // + if ((Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_IO) || + (IS_PCI_VGA(&PciIoDevice->Pci) && + ((Attributes & EFI_PCI_IO_ATTRIBUTE_IO) || + (Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY)))) { + // + // Check if a VGA has been enabled before enabling a new one + // + if (Operation == EfiPciIoAttributeOperationEnable) { + // + // Check if there have been an active VGA device on the same segment + // + Temp = ActiveVGADeviceOnTheSameSegment (PciIoDevice); + if (Temp && Temp != PciIoDevice) { + // + // An active VGA has been detected, so can not enable another + // + return EFI_UNSUPPORTED; + } + } + } + + // + // Do with the attributes on GFX + // + if (Attributes & EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO) { + + if (Operation == EfiPciIoAttributeOperationEnable) { + // + // Check if snoop can be enabled in current configuration + // + Status = SupportPaletteSnoopAttributes (PciIoDevice, Operation); + + if (EFI_ERROR (Status)) { + + // + // Enable operation is forbidden, so mask the bit in attributes + // so as to keep consistent with the actual Status + // + // Attributes &= (~EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO); + // + // + // + return EFI_UNSUPPORTED; + + } + } + + // + // It can be supported, so get ready to set the bit + // + Command |= EFI_PCI_COMMAND_VGA_PALETTE_SNOOP; + } + } + + if (Attributes & EFI_PCI_IO_ATTRIBUTE_IO) { + Command |= EFI_PCI_COMMAND_IO_SPACE; + } + + if (Attributes & EFI_PCI_IO_ATTRIBUTE_MEMORY) { + Command |= EFI_PCI_COMMAND_MEMORY_SPACE; + } + + if (Attributes & EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) { + Command |= EFI_PCI_COMMAND_BUS_MASTER; + } + // + // The upstream bridge should be also set to revelant attribute + // expect for IO, Mem and BusMaster + // + UpStreamAttributes = Attributes & + (~(EFI_PCI_IO_ATTRIBUTE_IO | + EFI_PCI_IO_ATTRIBUTE_MEMORY | + EFI_PCI_IO_ATTRIBUTE_BUS_MASTER + ) + ); + UpStreamBridge = PciIoDevice->Parent; + + if (Operation == EfiPciIoAttributeOperationEnable) { + // + // Enable relevant attributes to command register and bridge control register + // + Status = PciEnableCommandRegister (PciIoDevice, Command); + if (BridgeControl) { + Status = PciEnableBridgeControlRegister (PciIoDevice, BridgeControl); + } + + PciIoDevice->Attributes |= Attributes; + + // + // Enable attributes of the upstream bridge + // + Status = UpStreamBridge->PciIo.Attributes ( + &(UpStreamBridge->PciIo), + EfiPciIoAttributeOperationEnable, + UpStreamAttributes, + NULL + ); + } else { + + // + // Disable relevant attributes to command register and bridge control register + // + Status = PciDisableCommandRegister (PciIoDevice, Command); + if (BridgeControl) { + Status = PciDisableBridgeControlRegister (PciIoDevice, BridgeControl); + } + + PciIoDevice->Attributes &= (~Attributes); + Status = EFI_SUCCESS; + + } + + if (EFI_ERROR (Status)) { + ReportErrorStatusCode (PciIoDevice, EFI_IO_BUS_PCI | EFI_IOB_EC_CONTROLLER_ERROR); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PciIoGetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL * This, + IN UINT8 BarIndex, + OUT UINT64 *Supports, OPTIONAL + OUT VOID **Resources OPTIONAL + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +// TODO: Supports - add argument and description to function comment +// TODO: Resources - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + UINT8 *Configuration; + UINT8 NumConfig; + PCI_IO_DEVICE *PciIoDevice; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; + EFI_ACPI_END_TAG_DESCRIPTOR *PtrEnd; + + NumConfig = 0; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + if (Supports == NULL && Resources == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BarIndex >= PCI_MAX_BAR) { + return EFI_UNSUPPORTED; + } + + // + // This driver does not support modifications to the WRITE_COMBINE or + // CACHED attributes for BAR ranges. + // + if (Supports != NULL) { + *Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE; + } + + if (Resources != NULL) { + + if (PciIoDevice->PciBar[BarIndex].BarType != PciBarTypeUnknown) { + NumConfig = 1; + } + + Configuration = AllocatePool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR)); + if (Configuration == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem ( + Configuration, + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) * NumConfig + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR) + ); + + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration; + + if (NumConfig == 1) { + Ptr->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; + Ptr->Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3; + + Ptr->AddrRangeMin = PciIoDevice->PciBar[BarIndex].BaseAddress; + Ptr->AddrLen = PciIoDevice->PciBar[BarIndex].Length; + Ptr->AddrRangeMax = PciIoDevice->PciBar[BarIndex].Alignment; + + switch (PciIoDevice->PciBar[BarIndex].BarType) { + case PciBarTypeIo16: + case PciBarTypeIo32: + // + // Io + // + Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_IO; + break; + + case PciBarTypeMem32: + // + // Mem + // + Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // 32 bit + // + Ptr->AddrSpaceGranularity = 32; + break; + + case PciBarTypePMem32: + // + // Mem + // + Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // prefechable + // + Ptr->SpecificFlag = 0x6; + // + // 32 bit + // + Ptr->AddrSpaceGranularity = 32; + break; + + case PciBarTypeMem64: + // + // Mem + // + Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // 64 bit + // + Ptr->AddrSpaceGranularity = 64; + break; + + case PciBarTypePMem64: + // + // Mem + // + Ptr->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM; + // + // prefechable + // + Ptr->SpecificFlag = 0x6; + // + // 64 bit + // + Ptr->AddrSpaceGranularity = 64; + break; + + default: + break; + } + + Ptr = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) ((UINT8 *) Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR)); + } + + // + // put the checksum + // + PtrEnd = (EFI_ACPI_END_TAG_DESCRIPTOR *) ((UINT8 *) Ptr); + PtrEnd->Desc = ACPI_END_TAG_DESCRIPTOR; + PtrEnd->Checksum = 0; + + *Resources = Configuration; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciIoSetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Attributes - add argument and description to function comment +// TODO: BarIndex - add argument and description to function comment +// TODO: Offset - add argument and description to function comment +// TODO: Length - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + PCI_IO_DEVICE *PciIoDevice; + UINT64 NonRelativeOffset; + UINT64 Supports; + + PciIoDevice = PCI_IO_DEVICE_FROM_PCI_IO_THIS (This); + + // + // Make sure Offset and Length are not NULL + // + if (Offset == NULL || Length == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (PciIoDevice->PciBar[BarIndex].BarType == PciBarTypeUnknown) { + return EFI_UNSUPPORTED; + } + // + // This driver does not support setting the WRITE_COMBINE or the CACHED attributes. + // If Attributes is not 0, then return EFI_UNSUPPORTED. + // + Supports = PciIoDevice->Supports & EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED & EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE; + + if (Attributes != (Attributes & Supports)) { + return EFI_UNSUPPORTED; + } + // + // Attributes must be supported. Make sure the BAR range describd by BarIndex, Offset, and + // Length are valid for this PCI device. + // + NonRelativeOffset = *Offset; + Status = PciIoVerifyBarAccess ( + PciIoDevice, + BarIndex, + PciBarTypeMem, + EfiPciIoWidthUint8, + (UINT32) *Length, + &NonRelativeOffset + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +UpStreamBridgesAttributes ( + IN PCI_IO_DEVICE *PciIoDevice, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: Operation - add argument and description to function comment +// TODO: Attributes - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *Parent; + EFI_PCI_IO_PROTOCOL *PciIo; + + Parent = PciIoDevice->Parent; + + while (Parent && IS_PCI_BRIDGE (&Parent->Pci)) { + + // + // Get the PciIo Protocol + // + PciIo = &Parent->PciIo; + + PciIo->Attributes (PciIo, Operation, Attributes, NULL); + + Parent = Parent->Parent; + } + + return EFI_SUCCESS; +} + +BOOLEAN +PciDevicesOnTheSamePath ( + IN PCI_IO_DEVICE *PciDevice1, + IN PCI_IO_DEVICE *PciDevice2 + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciDevice1 - add argument and description to function comment +// TODO: PciDevice2 - add argument and description to function comment +{ + + if (PciDevice1->Parent == PciDevice2->Parent) { + return TRUE; + } + + if (PciDevice1->BusNumber > PciDevice2->BusNumber) { + return PciDeviceExisted (PciDevice1->Parent, PciDevice2); + } + + return PciDeviceExisted (PciDevice2->Parent, PciDevice1); +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.h new file mode 100644 index 0000000000..5733f592e3 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciIo.h @@ -0,0 +1,773 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciIo.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_IO_PROTOCOL_H +#define _EFI_PCI_IO_PROTOCOL_H + +EFI_STATUS +InitializePciIoInstance ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciIoVerifyBarAccess ( + PCI_IO_DEVICE *PciIoDevice, + UINT8 BarIndex, + PCI_BAR_TYPE Type, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + UINT64 *Offset + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + BarIndex - TODO: add argument description + Type - TODO: add argument description + Width - TODO: add argument description + Count - TODO: add argument description + Offset - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciIoVerifyConfigAccess ( + PCI_IO_DEVICE *PciIoDevice, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINTN Count, + IN UINT64 *Offset + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + Width - TODO: add argument description + Count - TODO: add argument description + Offset - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoPollMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Width - TODO: add argument description + BarIndex - TODO: add argument description + Offset - TODO: add argument description + Mask - TODO: add argument description + Value - TODO: add argument description + Delay - TODO: add argument description + Result - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoPollIo ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Width - TODO: add argument description + BarIndex - TODO: add argument description + Offset - TODO: add argument description + Mask - TODO: add argument description + Value - TODO: add argument description + Delay - TODO: add argument description + Result - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoMemRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Width - TODO: add argument description + BarIndex - TODO: add argument description + Offset - TODO: add argument description + Count - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoMemWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Width - TODO: add argument description + BarIndex - TODO: add argument description + Offset - TODO: add argument description + Count - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoIoRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Width - TODO: add argument description + BarIndex - TODO: add argument description + Offset - TODO: add argument description + Count - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoIoWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Width - TODO: add argument description + BarIndex - TODO: add argument description + Offset - TODO: add argument description + Count - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoConfigRead ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Width - TODO: add argument description + Offset - TODO: add argument description + Count - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoConfigWrite ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Width - TODO: add argument description + Offset - TODO: add argument description + Count - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoCopyMem ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Width - TODO: add argument description + DestBarIndex - TODO: add argument description + DestOffset - TODO: add argument description + SrcBarIndex - TODO: add argument description + SrcOffset - TODO: add argument description + Count - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoMap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_OPERATION Operation, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Operation - TODO: add argument description + HostAddress - TODO: add argument description + NumberOfBytes - TODO: add argument description + DeviceAddress - TODO: add argument description + Mapping - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoUnmap ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Mapping - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoAllocateBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Type - TODO: add argument description + MemoryType - TODO: add argument description + Pages - TODO: add argument description + HostAddress - TODO: add argument description + Attributes - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoFreeBuffer ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Pages - TODO: add argument description + HostAddress - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoFlush ( + IN EFI_PCI_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoGetLocation ( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *Segment, + OUT UINTN *Bus, + OUT UINTN *Device, + OUT UINTN *Function + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Segment - TODO: add argument description + Bus - TODO: add argument description + Device - TODO: add argument description + Function - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +CheckBarType ( + IN PCI_IO_DEVICE *PciIoDevice, + UINT8 BarIndex, + PCI_BAR_TYPE BarType + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + BarIndex - TODO: add argument description + BarType - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ModifyRootBridgeAttributes ( + IN PCI_IO_DEVICE *PciIoDevice, + IN UINT64 Attributes, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + Attributes - TODO: add argument description + Operation - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SupportPaletteSnoopAttributes ( + IN PCI_IO_DEVICE *PciIoDevice, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + Operation - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoAttributes ( + IN EFI_PCI_IO_PROTOCOL * This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Operation - TODO: add argument description + Attributes - TODO: add argument description + Result - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoGetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL * This, + IN UINT8 BarIndex, + OUT UINT64 *Supports, OPTIONAL + OUT VOID **Resources OPTIONAL + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + BarIndex - TODO: add argument description + Supports - TODO: add argument description + Resources - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PciIoSetBarAttributes ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Attributes - TODO: add argument description + BarIndex - TODO: add argument description + Offset - TODO: add argument description + Length - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +UpStreamBridgesAttributes ( + IN PCI_IO_DEVICE *PciIoDevice, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + Operation - TODO: add argument description + Attributes - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +PciDevicesOnTheSamePath ( + IN PCI_IO_DEVICE *PciDevice1, + IN PCI_IO_DEVICE *PciDevice2 + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDevice1 - TODO: add argument description + PciDevice2 - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c new file mode 100644 index 0000000000..11a0c29210 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.c @@ -0,0 +1,1398 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciLib.c + +Abstract: + + PCI Bus Driver Lib file + It abstracts some functions that can be different + between light PCI bus driver and full PCI bus driver + +Revision History + +--*/ + +#include "pcibus.h" + +EFI_PCI_HOTPLUG_REQUEST_PROTOCOL gPciHotPlugRequest = { + PciHotPlugRequestNotify +}; + + +VOID +InstallHotPlugRequestProtocol ( + IN EFI_STATUS *Status + ) +/*++ + +Routine Description: + +Arguments: + Status - A pointer to the status. + +Returns: + + None + +--*/ +{ + EFI_HANDLE Handle; + + Handle = NULL; + *Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiPciHotPlugRequestProtocolGuid, + EFI_NATIVE_INTERFACE, + &gPciHotPlugRequest + ); +} + +VOID +InstallPciHotplugGuid ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + + PciIoDevice - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + + if (IS_CARDBUS_BRIDGE (&PciIoDevice->Parent->Pci)) { + + Status = gBS->InstallProtocolInterface ( + &PciIoDevice->Handle, + &gEfiPciHotplugDeviceGuid, + EFI_NATIVE_INTERFACE, + NULL + ); + } +} + +VOID +UninstallPciHotplugGuid ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + + PciIoDevice - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( + PciIoDevice->Handle, + &gEfiPciHotplugDeviceGuid, + NULL, + NULL, + NULL, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + + if (Status == EFI_SUCCESS) { + // + // This may triger CardBus driver to stop for + // Pccard devices opened the GUID via BY_DRIVER + // + Status = gBS->UninstallProtocolInterface ( + PciIoDevice->Handle, + &gEfiPciHotplugDeviceGuid, + NULL + ); + } +} + +VOID +GetBackPcCardBar ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + +Arguments: + + PciIoDevice - A pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +{ + UINT32 Address; + + // + // Read PciBar information from the bar register + // + if (!gFullEnumeration) { + + Address = 0; + PciIoDevice->PciIo.Pci.Read ( + &(PciIoDevice->PciIo), + EfiPciIoWidthUint32, + 0x1c, + 1, + &Address + ); + + (PciIoDevice->PciBar)[P2C_MEM_1].BaseAddress = (UINT64) (Address); + (PciIoDevice->PciBar)[P2C_MEM_1].Length = 0x2000000; + (PciIoDevice->PciBar)[P2C_MEM_1].BarType = PciBarTypeMem32; + + Address = 0; + PciIoDevice->PciIo.Pci.Read ( + &(PciIoDevice->PciIo), + EfiPciIoWidthUint32, + 0x20, + 1, + &Address + ); + (PciIoDevice->PciBar)[P2C_MEM_2].BaseAddress = (UINT64) (Address); + (PciIoDevice->PciBar)[P2C_MEM_2].Length = 0x2000000; + (PciIoDevice->PciBar)[P2C_MEM_2].BarType = PciBarTypePMem32; + + Address = 0; + PciIoDevice->PciIo.Pci.Read ( + &(PciIoDevice->PciIo), + EfiPciIoWidthUint32, + 0x2c, + 1, + &Address + ); + (PciIoDevice->PciBar)[P2C_IO_1].BaseAddress = (UINT64) (Address); + (PciIoDevice->PciBar)[P2C_IO_1].Length = 0x100; + (PciIoDevice->PciBar)[P2C_IO_1].BarType = PciBarTypeIo16; + + Address = 0; + PciIoDevice->PciIo.Pci.Read ( + &(PciIoDevice->PciIo), + EfiPciIoWidthUint32, + 0x34, + 1, + &Address + ); + (PciIoDevice->PciBar)[P2C_IO_2].BaseAddress = (UINT64) (Address); + (PciIoDevice->PciBar)[P2C_IO_2].Length = 0x100; + (PciIoDevice->PciBar)[P2C_IO_2].BarType = PciBarTypeIo16; + + } + + if (gPciHotPlugInit != NULL) { + GetResourcePaddingForHpb (PciIoDevice); + } +} + +EFI_STATUS +RemoveRejectedPciDevices ( + EFI_HANDLE RootBridgeHandle, + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + +Arguments: + + RootBridgeHandle - An efi handle. + Bridge - An pointer to the PCI_IO_DEVICE. + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *Temp; + LIST_ENTRY *CurrentLink; + LIST_ENTRY *LastLink; + + CurrentLink = Bridge->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &Bridge->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (IS_PCI_BRIDGE (&Temp->Pci)) { + // + // Remove rejected devices recusively + // + RemoveRejectedPciDevices (RootBridgeHandle, Temp); + } else { + // + // Skip rejection for all PPBs, while detect rejection for others + // + if (IsPciDeviceRejected (Temp)) { + + // + // For P2C, remove all devices on it + // + + if (!IsListEmpty (&Temp->ChildList)) { + RemoveAllPciDeviceOnBridge (RootBridgeHandle, Temp); + } + + // + // Finally remove itself + // + + LastLink = CurrentLink->BackLink; + RemoveEntryList (CurrentLink); + FreePciDevice (Temp); + + CurrentLink = LastLink; + } + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciHostBridgeResourceAllocator ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + + Host brige resource allocator. + +Arguments: + + PciResAlloc - A pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL. + +Returns: + + EFI Status. + +--*/ +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *RootBridgeDev; + EFI_HANDLE RootBridgeHandle; + VOID *AcpiConfig; + EFI_STATUS Status; + UINT64 IoBase; + UINT64 Mem32Base; + UINT64 PMem32Base; + UINT64 Mem64Base; + UINT64 PMem64Base; + UINT64 IoResStatus; + UINT64 Mem32ResStatus; + UINT64 PMem32ResStatus; + UINT64 Mem64ResStatus; + UINT64 PMem64ResStatus; + UINT64 MaxOptionRomSize; + PCI_RESOURCE_NODE *IoBridge; + PCI_RESOURCE_NODE *Mem32Bridge; + PCI_RESOURCE_NODE *PMem32Bridge; + PCI_RESOURCE_NODE *Mem64Bridge; + PCI_RESOURCE_NODE *PMem64Bridge; + PCI_RESOURCE_NODE IoPool; + PCI_RESOURCE_NODE Mem32Pool; + PCI_RESOURCE_NODE PMem32Pool; + PCI_RESOURCE_NODE Mem64Pool; + PCI_RESOURCE_NODE PMem64Pool; + BOOLEAN ReAllocate; + REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA HandleExtendedData; + REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA AllocFailExtendedData; + + // + // Reallocate flag + // + ReAllocate = FALSE; + + // + // It will try several times if the resource allocation fails + // + while (TRUE) { + + // + // Initialize resource pool + // + InitializeResourcePool (&IoPool, PciBarTypeIo16); + InitializeResourcePool (&Mem32Pool, PciBarTypeMem32); + InitializeResourcePool (&PMem32Pool, PciBarTypePMem32); + InitializeResourcePool (&Mem64Pool, PciBarTypeMem64); + InitializeResourcePool (&PMem64Pool, PciBarTypePMem64); + + RootBridgeDev = NULL; + RootBridgeHandle = 0; + + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + + // + // Get RootBridg Device by handle + // + RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_NOT_FOUND; + } + + // + // Create the entire system resource map from the information collected by + // enumerator. Several resource tree was created + // + + IoBridge = CreateResourceNode ( + RootBridgeDev, + 0, + 0xFFF, + 0, + PciBarTypeIo16, + PciResUsageTypical + ); + + Mem32Bridge = CreateResourceNode ( + RootBridgeDev, + 0, + 0xFFFFF, + 0, + PciBarTypeMem32, + PciResUsageTypical + ); + + PMem32Bridge = CreateResourceNode ( + RootBridgeDev, + 0, + 0xFFFFF, + 0, + PciBarTypePMem32, + PciResUsageTypical + ); + + Mem64Bridge = CreateResourceNode ( + RootBridgeDev, + 0, + 0xFFFFF, + 0, + PciBarTypeMem64, + PciResUsageTypical + ); + + PMem64Bridge = CreateResourceNode ( + RootBridgeDev, + 0, + 0xFFFFF, + 0, + PciBarTypePMem64, + PciResUsageTypical + ); + + // + // Create resourcemap by going through all the devices subject to this root bridge + // + Status = CreateResourceMap ( + RootBridgeDev, + IoBridge, + Mem32Bridge, + PMem32Bridge, + Mem64Bridge, + PMem64Bridge + ); + + // + // Get the max ROM size that the root bridge can process + // + RootBridgeDev->RomSize = Mem32Bridge->Length; + + // + // Skip to enlarge the resource request during realloction + // + if (!ReAllocate) { + // + // Get Max Option Rom size for current root bridge + // + MaxOptionRomSize = GetMaxOptionRomSize (RootBridgeDev); + + // + // Enlarger the mem32 resource to accomdate the option rom + // if the mem32 resource is not enough to hold the rom + // + if (MaxOptionRomSize > Mem32Bridge->Length) { + + Mem32Bridge->Length = MaxOptionRomSize; + RootBridgeDev->RomSize = MaxOptionRomSize; + + // + // Alignment should be adjusted as well + // + if (Mem32Bridge->Alignment < MaxOptionRomSize - 1) { + Mem32Bridge->Alignment = MaxOptionRomSize - 1; + } + } + } + + // + // Based on the all the resource tree, contruct ACPI resource node to + // submit the resource aperture to pci host bridge protocol + // + Status = ConstructAcpiResourceRequestor ( + RootBridgeDev, + IoBridge, + Mem32Bridge, + PMem32Bridge, + Mem64Bridge, + PMem64Bridge, + &AcpiConfig + ); + + // + // Insert these resource nodes into the database + // + InsertResourceNode (&IoPool, IoBridge); + InsertResourceNode (&Mem32Pool, Mem32Bridge); + InsertResourceNode (&PMem32Pool, PMem32Bridge); + InsertResourceNode (&Mem64Pool, Mem64Bridge); + InsertResourceNode (&PMem64Pool, PMem64Bridge); + + if (Status == EFI_SUCCESS) { + // + // Submit the resource requirement + // + Status = PciResAlloc->SubmitResources ( + PciResAlloc, + RootBridgeDev->Handle, + AcpiConfig + ); + } + + // + // Free acpi resource node + // + if (AcpiConfig != NULL) { + gBS->FreePool (AcpiConfig); + } + + if (EFI_ERROR (Status)) { + // + // Destroy all the resource tree + // + DestroyResourceTree (&IoPool); + DestroyResourceTree (&Mem32Pool); + DestroyResourceTree (&PMem32Pool); + DestroyResourceTree (&Mem64Pool); + DestroyResourceTree (&PMem64Pool); + return Status; + } + } + + // + // Notify pci bus driver starts to program the resource + // + + Status = NotifyPhase (PciResAlloc, EfiPciHostBridgeAllocateResources); + + if (!EFI_ERROR (Status)) { + // + // Allocation succeed, then continue the following + // + break; + } + + // + // If the resource allocation is unsuccessful, free resources on bridge + // + + RootBridgeDev = NULL; + RootBridgeHandle = 0; + + IoResStatus = EFI_RESOURCE_SATISFIED; + Mem32ResStatus = EFI_RESOURCE_SATISFIED; + PMem32ResStatus = EFI_RESOURCE_SATISFIED; + Mem64ResStatus = EFI_RESOURCE_SATISFIED; + PMem64ResStatus = EFI_RESOURCE_SATISFIED; + + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + // + // Get RootBridg Device by handle + // + RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle); + if (RootBridgeDev == NULL) { + return EFI_NOT_FOUND; + } + + // + // Get host bridge handle for status report + // + HandleExtendedData.Handle = RootBridgeDev->PciRootBridgeIo->ParentHandle; + + // + // Get acpi resource node for all the resource types + // + AcpiConfig = NULL; + + Status = PciResAlloc->GetProposedResources ( + PciResAlloc, + RootBridgeDev->Handle, + &AcpiConfig + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if (AcpiConfig != NULL) { + // + // Adjust resource allocation policy for each RB + // + GetResourceAllocationStatus ( + AcpiConfig, + &IoResStatus, + &Mem32ResStatus, + &PMem32ResStatus, + &Mem64ResStatus, + &PMem64ResStatus + ); + gBS->FreePool (AcpiConfig); + } + } + // + // End while + // + + // + // Raise the EFI_IOB_EC_RESOURCE_CONFLICT status code + // + // + // It is very difficult to follow the spec here + // Device path , Bar index can not be get here + // + ZeroMem (&AllocFailExtendedData, sizeof (AllocFailExtendedData)); + + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_PROGRESS_CODE, + EFI_IO_BUS_PCI | EFI_IOB_EC_RESOURCE_CONFLICT, + (VOID *) &AllocFailExtendedData, + sizeof (AllocFailExtendedData) + ); + + Status = PciHostBridgeAdjustAllocation ( + &IoPool, + &Mem32Pool, + &PMem32Pool, + &Mem64Pool, + &PMem64Pool, + IoResStatus, + Mem32ResStatus, + PMem32ResStatus, + Mem64ResStatus, + PMem64ResStatus + ); + + // + // Destroy all the resource tree + // + DestroyResourceTree (&IoPool); + DestroyResourceTree (&Mem32Pool); + DestroyResourceTree (&PMem32Pool); + DestroyResourceTree (&Mem64Pool); + DestroyResourceTree (&PMem64Pool); + + NotifyPhase (PciResAlloc, EfiPciHostBridgeFreeResources); + + if (EFI_ERROR (Status)) { + return Status; + } + + ReAllocate = TRUE; + + } + // + // End main while + // + + // + // Raise the EFI_IOB_PCI_RES_ALLOC status code + // + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_PROGRESS_CODE, + EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_RES_ALLOC, + (VOID *) &HandleExtendedData, + sizeof (HandleExtendedData) + ); + + // + // Notify pci bus driver starts to program the resource + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeSetResources); + + RootBridgeDev = NULL; + + RootBridgeHandle = 0; + + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + + // + // Get RootBridg Device by handle + // + RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_NOT_FOUND; + } + + // + // Get acpi resource node for all the resource types + // + AcpiConfig = NULL; + Status = PciResAlloc->GetProposedResources ( + PciResAlloc, + RootBridgeDev->Handle, + &AcpiConfig + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get the resource base by interpreting acpi resource node + // + // + GetResourceBase ( + AcpiConfig, + &IoBase, + &Mem32Base, + &PMem32Base, + &Mem64Base, + &PMem64Base + ); + + // + // Process option rom for this root bridge + // + Status = ProcessOptionRom (RootBridgeDev, Mem32Base, RootBridgeDev->RomSize); + + // + // Create the entire system resource map from the information collected by + // enumerator. Several resource tree was created + // + Status = GetResourceMap ( + RootBridgeDev, + &IoBridge, + &Mem32Bridge, + &PMem32Bridge, + &Mem64Bridge, + &PMem64Bridge, + &IoPool, + &Mem32Pool, + &PMem32Pool, + &Mem64Pool, + &PMem64Pool + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Program IO resources + // + ProgramResource ( + IoBase, + IoBridge + ); + + // + // Program Mem32 resources + // + ProgramResource ( + Mem32Base, + Mem32Bridge + ); + + // + // Program PMem32 resources + // + ProgramResource ( + PMem32Base, + PMem32Bridge + ); + + // + // Program Mem64 resources + // + ProgramResource ( + Mem64Base, + Mem64Bridge + ); + + // + // Program PMem64 resources + // + ProgramResource ( + PMem64Base, + PMem64Bridge + ); + + if (AcpiConfig != NULL) { + gBS->FreePool (AcpiConfig); + } + } + + // + // Destroy all the resource tree + // + DestroyResourceTree (&IoPool); + DestroyResourceTree (&Mem32Pool); + DestroyResourceTree (&PMem32Pool); + DestroyResourceTree (&Mem64Pool); + DestroyResourceTree (&PMem64Pool); + + // + // Notify the resource allocation phase is to end + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeEndResourceAllocation); + + return EFI_SUCCESS; +} + +EFI_STATUS +PciScanBus ( + IN PCI_IO_DEVICE *Bridge, + IN UINT8 StartBusNumber, + OUT UINT8 *SubBusNumber, + OUT UINT8 *PaddedBusRange + ) +/*++ + +Routine Description: + + This routine is used to assign bus number to the given PCI bus system + +Arguments: + + Bridge - A pointer to the PCI_IO_DEVICE structure. + StartBusNumber - The start bus number. + SubBusNumber - A pointer to the sub bus number. + PaddedBusRange - A pointer to the padded bus range. + +Returns: + + None + +--*/ +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + PCI_TYPE00 Pci; + UINT8 Device; + UINT8 Func; + UINT64 Address; + UINTN SecondBus; + UINT16 Register; + UINTN HpIndex; + PCI_IO_DEVICE *PciDevice; + EFI_EVENT Event; + EFI_HPC_STATE State; + UINT64 PciAddress; + EFI_HPC_PADDING_ATTRIBUTES Attributes; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + UINT16 BusRange; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + BOOLEAN BusPadding; + + PciRootBridgeIo = Bridge->PciRootBridgeIo; + SecondBus = 0; + Register = 0; + State = 0; + Attributes = 0; + BusRange = 0; + + ResetAllPpbBusReg (Bridge, StartBusNumber); + + for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) { + for (Func = 0; Func <= PCI_MAX_FUNC; Func++) { + + // + // Check to see whether a pci device is present + // + Status = PciDevicePresent ( + PciRootBridgeIo, + &Pci, + StartBusNumber, + Device, + Func + ); + + if (EFI_ERROR (Status)) { + if (Func == 0) { + // + // Skip sub functions, this is not a multi function device + // + Func = PCI_MAX_FUNC; + } + + continue; + } + + // + // Get the PCI device information + // + Status = PciSearchDevice ( + Bridge, + &Pci, + StartBusNumber, + Device, + Func, + &PciDevice + ); + + ASSERT (!EFI_ERROR (Status)); + + PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0); + + if (!IS_PCI_BRIDGE (&Pci)) { + // + // PCI bridges will be called later + // Here just need for PCI device or PCI to cardbus controller + // EfiPciBeforeChildBusEnumeration for PCI Device Node + // + PreprocessController ( + PciDevice, + PciDevice->BusNumber, + PciDevice->DeviceNumber, + PciDevice->FunctionNumber, + EfiPciBeforeChildBusEnumeration + ); + } + + // + // For Pci Hotplug controller devcie only + // + if (gPciHotPlugInit != NULL) { + // + // Check if it is a Hotplug PCI controller + // + if (IsRootPciHotPlugController (PciDevice->DevicePath, &HpIndex)) { + + if (!gPciRootHpcData[HpIndex].Initialized) { + + Status = CreateEventForHpc (HpIndex, &Event); + + ASSERT (!EFI_ERROR (Status)); + + Status = gPciHotPlugInit->InitializeRootHpc ( + gPciHotPlugInit, + gPciRootHpcPool[HpIndex].HpcDevicePath, + PciAddress, + Event, + &State + ); + + PreprocessController ( + PciDevice, + PciDevice->BusNumber, + PciDevice->DeviceNumber, + PciDevice->FunctionNumber, + EfiPciBeforeChildBusEnumeration + ); + continue; + } + } + } + + if (IS_PCI_BRIDGE (&Pci) || IS_CARDBUS_BRIDGE (&Pci)) { + // + // For PPB + // Get the bridge information + // + BusPadding = FALSE; + if (gPciHotPlugInit != NULL) { + + if (IsRootPciHotPlugBus (PciDevice->DevicePath, &HpIndex)) { + + // + // If it is initialized, get the padded bus range + // + Status = gPciHotPlugInit->GetResourcePadding ( + gPciHotPlugInit, + gPciRootHpcPool[HpIndex].HpbDevicePath, + PciAddress, + &State, + (VOID **) &Descriptors, + &Attributes + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + BusRange = 0; + Status = PciGetBusRange ( + &Descriptors, + NULL, + NULL, + &BusRange + ); + + gBS->FreePool (Descriptors); + + if (EFI_ERROR (Status)) { + return Status; + } + + BusPadding = TRUE; + } + } + + (*SubBusNumber)++; + SecondBus = *SubBusNumber; + + Register = (UINT16) ((SecondBus << 8) | (UINT16) StartBusNumber); + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x18); + + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint16, + Address, + 1, + &Register + ); + + + // + // If it is PPB, resursively search down this bridge + // + if (IS_PCI_BRIDGE (&Pci)) { + + // + // Initialize SubBusNumber to Maximum bus number + // + Register = 0xFF; + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A); + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + &Register + ); + + // + // Nofify EfiPciBeforeChildBusEnumeration for PCI Brige + // + PreprocessController ( + PciDevice, + PciDevice->BusNumber, + PciDevice->DeviceNumber, + PciDevice->FunctionNumber, + EfiPciBeforeChildBusEnumeration + ); + + Status = PciScanBus ( + PciDevice, + (UINT8) (SecondBus), + SubBusNumber, + PaddedBusRange + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + } + + if (BusPadding) { + // + // Ensure the device is enabled and initialized + // + if ((Attributes == EfiPaddingPciRootBridge) && + (State & EFI_HPC_STATE_ENABLED) && + (State & EFI_HPC_STATE_INITIALIZED) ) { + *PaddedBusRange = (UINT8) ((UINT8) (BusRange) +*PaddedBusRange); + } else { + *SubBusNumber = (UINT8) ((UINT8) (BusRange) +*SubBusNumber); + } + } + + // + // Set the current maximum bus number under the PPB + // + Address = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0x1A); + + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint8, + Address, + 1, + SubBusNumber + ); + } + + if (Func == 0 && !IS_PCI_MULTI_FUNC (&Pci)) { + + // + // Skip sub functions, this is not a multi function device + // + Func = PCI_MAX_FUNC; + } + + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciRootBridgeP2CProcess ( + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + Process Option Rom on this host bridge + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + LIST_ENTRY *CurrentLink; + PCI_IO_DEVICE *Temp; + EFI_HPC_STATE State; + UINT64 PciAddress; + EFI_STATUS Status; + + CurrentLink = Bridge->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &Bridge->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + if (IS_CARDBUS_BRIDGE (&Temp->Pci)) { + + if (gPciHotPlugInit && Temp->Allocated) { + + // + // Raise the EFI_IOB_PCI_HPC_INIT status code + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_IO_BUS_PCI | EFI_IOB_PCI_PC_HPC_INIT, + Temp->DevicePath + ); + + PciAddress = EFI_PCI_ADDRESS (Temp->BusNumber, Temp->DeviceNumber, Temp->FunctionNumber, 0); + Status = gPciHotPlugInit->InitializeRootHpc ( + gPciHotPlugInit, + Temp->DevicePath, + PciAddress, + NULL, + &State + ); + + if (!EFI_ERROR (Status)) { + Status = PciBridgeEnumerator (Temp); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + CurrentLink = CurrentLink->ForwardLink; + continue; + + } + } + + if (!IsListEmpty (&Temp->ChildList)) { + Status = PciRootBridgeP2CProcess (Temp); + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciHostBridgeP2CProcess ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciResAlloc - add argument and description to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_HANDLE RootBridgeHandle; + PCI_IO_DEVICE *RootBridgeDev; + EFI_STATUS Status; + + RootBridgeHandle = NULL; + + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + + // + // Get RootBridg Device by handle + // + RootBridgeDev = GetRootBridgeByHandle (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_NOT_FOUND; + } + + Status = PciRootBridgeP2CProcess (RootBridgeDev); + + if (EFI_ERROR (Status)) { + return Status; + } + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciHostBridgeEnumerator ( + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + + This function is used to enumerate the entire host bridge + in a given platform + +Arguments: + + PciResAlloc - A pointer to the resource allocate protocol. + +Returns: + + None + +--*/ +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_HANDLE RootBridgeHandle; + PCI_IO_DEVICE *RootBridgeDev; + EFI_STATUS Status; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + UINT16 MinBus; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + + InitializeHotPlugSupport (); + + // + // Notify the bus allocation phase is about to start + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation); + + RootBridgeHandle = NULL; + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + + // + // if a root bridge instance is found, create root bridge device for it + // + + RootBridgeDev = CreateRootBridge (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Enumerate all the buses under this root bridge + // + + Status = PciRootBridgeEnumerator ( + PciResAlloc, + RootBridgeDev + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + DestroyRootBridge (RootBridgeDev); + + // + // Error proccess here + // + } + + // + // Notify the bus allocation phase is finished for the first time + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation); + + + if (gPciHotPlugInit != NULL) { + // + // Wait for all HPC initialized + // + Status = AllRootHPCInitialized (STALL_1_SECOND * 15); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Notify the bus allocation phase is about to start for the 2nd time + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginBusAllocation); + + RootBridgeHandle = NULL; + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + + // + // if a root bridge instance is found, create root bridge device for it + // + + RootBridgeDev = CreateRootBridge (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Enumerate all the buses under this root bridge + // + + Status = PciRootBridgeEnumerator ( + PciResAlloc, + RootBridgeDev + ); + + DestroyRootBridge (RootBridgeDev); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Notify the bus allocation phase is to end + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeEndBusAllocation); + } + + // + // Notify the resource allocation phase is to start + // + NotifyPhase (PciResAlloc, EfiPciHostBridgeBeginResourceAllocation); + + RootBridgeHandle = NULL; + while (PciResAlloc->GetNextRootBridge (PciResAlloc, &RootBridgeHandle) == EFI_SUCCESS) { + + // + // if a root bridge instance is found, create root bridge device for it + // + + RootBridgeDev = CreateRootBridge (RootBridgeHandle); + + if (RootBridgeDev == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = StartManagingRootBridge (RootBridgeDev); + + if (EFI_ERROR (Status)) { + return Status; + } + + PciRootBridgeIo = RootBridgeDev->PciRootBridgeIo; + Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciGetBusRange (&Descriptors, &MinBus, NULL, NULL); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Determine root bridge attribute by calling interface of Pcihostbridge + // protocol + // + DetermineRootBridgeAttributes ( + PciResAlloc, + RootBridgeDev + ); + + // + // Collect all the resource information under this root bridge + // A database that records all the information about pci device subject to this + // root bridge will then be created + // + Status = PciPciDeviceInfoCollector ( + RootBridgeDev, + (UINT8) MinBus + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + InsertRootBridge (RootBridgeDev); + + // + // Record the hostbridge handle + // + AddHostBridgeEnumerator (RootBridgeDev->PciRootBridgeIo->ParentHandle); + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.h new file mode 100644 index 0000000000..1e89445df6 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciLib.h @@ -0,0 +1,247 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciLib.h + +Abstract: + + PCI Bus Driver Lib header file + It abstracts some functions that can be different + between light PCI bus driver and full PCI bus driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_LIB_H +#define _EFI_PCI_LIB_H + +VOID +InstallHotPlugRequestProtocol ( + IN EFI_STATUS *Status + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Status - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +InstallPciHotplugGuid ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +UninstallPciHotplugGuid ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +GetBackPcCardBar ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +RemoveRejectedPciDevices ( + EFI_HANDLE RootBridgeHandle, + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootBridgeHandle - TODO: add argument description + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciHostBridgeResourceAllocator ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciResAlloc - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciScanBus ( + IN PCI_IO_DEVICE *Bridge, + IN UINT8 StartBusNumber, + OUT UINT8 *SubBusNumber, + OUT UINT8 *PaddedBusRange + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + StartBusNumber - TODO: add argument description + SubBusNumber - TODO: add argument description + PaddedBusRange - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciRootBridgeP2CProcess ( + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciHostBridgeP2CProcess ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciResAlloc - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciHostBridgeEnumerator ( + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *PciResAlloc + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciResAlloc - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.c new file mode 100644 index 0000000000..324ad62827 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.c @@ -0,0 +1,543 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciOptionRomSupport.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "PciBus.h" +#include "PciResourceSupport.h" + +EFI_STATUS +GetOpRomInfo ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT8 RomBarIndex; + UINT32 AllOnes; + UINT64 Address; + EFI_STATUS Status; + UINT8 Bus; + UINT8 Device; + UINT8 Function; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + Bus = PciIoDevice->BusNumber; + Device = PciIoDevice->DeviceNumber; + Function = PciIoDevice->FunctionNumber; + + PciRootBridgeIo = PciIoDevice->PciRootBridgeIo; + + // + // offset is 48 if is not ppb + // + + // + // 0x30 + // + RomBarIndex = PCI_DEVICE_ROMBAR; + + if (IS_PCI_BRIDGE (&PciIoDevice->Pci)) { + // + // if is ppb + // + + // + // 0x38 + // + RomBarIndex = PCI_BRIDGE_ROMBAR; + } + // + // the bit0 is 0 to prevent the enabling of the Rom address decoder + // + AllOnes = 0xfffffffe; + Address = EFI_PCI_ADDRESS (Bus, Device, Function, RomBarIndex); + + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint32, + Address, + 1, + &AllOnes + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // read back + // + Status = PciRootBridgeIo->Pci.Read ( + PciRootBridgeIo, + EfiPciWidthUint32, + Address, + 1, + &AllOnes + ); + if (EFI_ERROR (Status)) { + return Status; + } + + AllOnes &= 0xFFFFFFFC; + if ((AllOnes == 0) || (AllOnes == 0xFFFFFFFC)) { + return EFI_NOT_FOUND; + } + + PciIoDevice->RomSize = (UINT64) ((~AllOnes) + 1); + return EFI_SUCCESS; + +} + +EFI_STATUS +LoadOpRomImage ( + IN PCI_IO_DEVICE *PciDevice, + IN UINT64 RomBase + ) +/*++ + +Routine Description: + + Load option rom image for specified PCI device + +Arguments: + +Returns: + +--*/ +// TODO: PciDevice - add argument and description to function comment +// TODO: RomBase - add argument and description to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +{ + UINT8 RomBarIndex; + UINT8 Indicator; + UINT16 OffsetPcir; + UINT32 RomBarOffset; + UINT32 RomBar; + UINT64 Temp; + EFI_STATUS retStatus; + BOOLEAN FirstCheck; + UINT8 *Image; + PCI_EXPANSION_ROM_HEADER *RomHeader; + PCI_DATA_STRUCTURE *RomPcir; + UINT64 RomSize; + UINT64 RomImageSize; + UINT8 *RomInMemory; + + RomSize = PciDevice->RomSize; + + Indicator = 0; + RomImageSize = 0; + RomInMemory = NULL; + Temp = 0; + + // + // Get the RomBarIndex + // + + // + // 0x30 + // + RomBarIndex = PCI_DEVICE_ROMBAR; + if (IS_PCI_BRIDGE (&(PciDevice->Pci))) { + // + // if is ppb + // + + // + // 0x38 + // + RomBarIndex = PCI_BRIDGE_ROMBAR; + } + // + // Allocate memory for Rom header and PCIR + // + RomHeader = AllocatePool (sizeof (PCI_EXPANSION_ROM_HEADER)); + if (RomHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + RomPcir = AllocatePool (sizeof (PCI_DATA_STRUCTURE)); + if (RomPcir == NULL) { + gBS->FreePool (RomHeader); + return EFI_OUT_OF_RESOURCES; + } + + RomBar = (UINT32) RomBase; + + // + // Enable RomBar + // + RomDecode (PciDevice, RomBarIndex, RomBar, TRUE); + + RomBarOffset = RomBar; + retStatus = EFI_NOT_FOUND; + FirstCheck = TRUE; + + do { + PciDevice->PciRootBridgeIo->Mem.Read ( + PciDevice->PciRootBridgeIo, + EfiPciWidthUint8, + RomBarOffset, + sizeof (PCI_EXPANSION_ROM_HEADER), + (UINT8 *) RomHeader + ); + + if (RomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { + RomBarOffset = RomBarOffset + 512; + if (FirstCheck) { + break; + } else { + RomImageSize = RomImageSize + 512; + continue; + } + } + + FirstCheck = FALSE; + OffsetPcir = RomHeader->PcirOffset; + PciDevice->PciRootBridgeIo->Mem.Read ( + PciDevice->PciRootBridgeIo, + EfiPciWidthUint8, + RomBarOffset + OffsetPcir, + sizeof (PCI_DATA_STRUCTURE), + (UINT8 *) RomPcir + ); + Indicator = RomPcir->Indicator; + RomImageSize = RomImageSize + RomPcir->ImageLength * 512; + RomBarOffset = RomBarOffset + RomPcir->ImageLength * 512; + } while (((Indicator & 0x80) == 0x00) && ((RomBarOffset - RomBar) < RomSize)); + + if (RomImageSize > 0) { + retStatus = EFI_SUCCESS; + Image = AllocatePool ((UINT32) RomImageSize); + if (Image == NULL) { + RomDecode (PciDevice, RomBarIndex, RomBar, FALSE); + gBS->FreePool (RomHeader); + gBS->FreePool (RomPcir); + return EFI_OUT_OF_RESOURCES; + } + + // + // Copy Rom image into memory + // + PciDevice->PciRootBridgeIo->Mem.Read ( + PciDevice->PciRootBridgeIo, + EfiPciWidthUint8, + RomBar, + (UINT32) RomImageSize, + Image + ); + RomInMemory = Image; + } + + RomDecode (PciDevice, RomBarIndex, RomBar, FALSE); + + PciDevice->PciIo.RomSize = RomImageSize; + PciDevice->PciIo.RomImage = RomInMemory; + + PciRomAddImageMapping ( + NULL, + PciDevice->PciRootBridgeIo->SegmentNumber, + PciDevice->BusNumber, + PciDevice->DeviceNumber, + PciDevice->FunctionNumber, + (UINT64) (UINTN) PciDevice->PciIo.RomImage, + PciDevice->PciIo.RomSize + ); + + // + // Free allocated memory + // + gBS->FreePool (RomHeader); + gBS->FreePool (RomPcir); + + return retStatus; +} + +EFI_STATUS +RomDecode ( + IN PCI_IO_DEVICE *PciDevice, + IN UINT8 RomBarIndex, + IN UINT32 RomBar, + IN BOOLEAN Enable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +// TODO: PciDevice - add argument and description to function comment +// TODO: RomBarIndex - add argument and description to function comment +// TODO: RomBar - add argument and description to function comment +// TODO: Enable - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT32 Value32; + UINT32 Offset; + EFI_PCI_IO_PROTOCOL *PciIo; + + PciIo = &PciDevice->PciIo; + if (Enable) { + // + // Clear all bars + // + for (Offset = 0x10; Offset <= 0x24; Offset += sizeof (UINT32)) { + PciIo->Pci.Write (PciIo, EfiPciIoWidthUint32, Offset, 1, &gAllZero); + } + + // + // set the Rom base address: now is hardcode + // enable its decoder + // + Value32 = RomBar | 0x1; + PciIo->Pci.Write ( + PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32, + RomBarIndex, + 1, + &Value32 + ); + + // + // Programe all upstream bridge + // + ProgrameUpstreamBridgeForRom(PciDevice, RomBar, TRUE); + + // + // Setting the memory space bit in the function's command register + // + PciEnableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE); + + } else { + + // + // disable command register decode to memory + // + PciDisableCommandRegister(PciDevice, EFI_PCI_COMMAND_MEMORY_SPACE); + + // + // Destroy the programmed bar in all the upstream bridge. + // + ProgrameUpstreamBridgeForRom(PciDevice, RomBar, FALSE); + + // + // disable rom decode + // + Value32 = 0xFFFFFFFE; + PciIo->Pci.Write ( + PciIo, + (EFI_PCI_IO_PROTOCOL_WIDTH) EfiPciWidthUint32, + RomBarIndex, + 1, + &Value32 + ); + + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +ProcessOpRomImage ( + PCI_IO_DEVICE *PciDevice + ) +/*++ + +Routine Description: + + Process the oprom image. + +Arguments: + PciDevice A pointer to a pci device. + +Returns: + + EFI Status. + +--*/ +{ + UINT8 Indicator; + UINT32 ImageSize; + UINT16 ImageOffset; + VOID *RomBar; + UINT8 *RomBarOffset; + EFI_HANDLE ImageHandle; + EFI_STATUS Status; + EFI_STATUS retStatus; + BOOLEAN FirstCheck; + BOOLEAN SkipImage; + UINT32 DestinationSize; + UINT32 ScratchSize; + UINT8 *Scratch; + VOID *ImageBuffer; + VOID *DecompressedImageBuffer; + UINT32 ImageLength; + EFI_DECOMPRESS_PROTOCOL *Decompress; + EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader; + PCI_DATA_STRUCTURE *Pcir; + + Indicator = 0; + + // + // Get the Address of the Rom image + // + RomBar = PciDevice->PciIo.RomImage; + RomBarOffset = (UINT8 *) RomBar; + retStatus = EFI_NOT_FOUND; + FirstCheck = TRUE; + + do { + EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) RomBarOffset; + if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { + RomBarOffset = RomBarOffset + 512; + if (FirstCheck) { + break; + } else { + continue; + } + } + + FirstCheck = FALSE; + Pcir = (PCI_DATA_STRUCTURE *) (RomBarOffset + EfiRomHeader->PcirOffset); + ImageSize = (UINT32) (Pcir->ImageLength * 512); + Indicator = Pcir->Indicator; + + if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && + (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE)) { + + if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) || + (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)) { + + ImageOffset = EfiRomHeader->EfiImageHeaderOffset; + ImageSize = (UINT32) (EfiRomHeader->InitializationSize * 512); + + ImageBuffer = (VOID *) (RomBarOffset + ImageOffset); + ImageLength = ImageSize - (UINT32)ImageOffset; + DecompressedImageBuffer = NULL; + + // + // decompress here if needed + // + SkipImage = FALSE; + if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { + SkipImage = TRUE; + } + + if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { + Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress); + if (EFI_ERROR (Status)) { + SkipImage = TRUE; + } else { + SkipImage = TRUE; + Status = Decompress->GetInfo ( + Decompress, + ImageBuffer, + ImageLength, + &DestinationSize, + &ScratchSize + ); + if (!EFI_ERROR (Status)) { + DecompressedImageBuffer = NULL; + DecompressedImageBuffer = AllocatePool (DestinationSize); + if (DecompressedImageBuffer != NULL) { + Scratch = AllocatePool (ScratchSize); + if (Scratch != NULL) { + Status = Decompress->Decompress ( + Decompress, + ImageBuffer, + ImageLength, + DecompressedImageBuffer, + DestinationSize, + Scratch, + ScratchSize + ); + if (!EFI_ERROR (Status)) { + ImageBuffer = DecompressedImageBuffer; + ImageLength = DestinationSize; + SkipImage = FALSE; + } + + gBS->FreePool (Scratch); + } + } + } + } + } + + if (!SkipImage) { + // + // load image and start image + // + Status = gBS->LoadImage ( + FALSE, + gPciBusDriverBinding.DriverBindingHandle, + PciDevice->Handle, + ImageBuffer, + ImageLength, + &ImageHandle + ); + if (!EFI_ERROR (Status)) { + Status = gBS->StartImage (ImageHandle, NULL, NULL); + if (!EFI_ERROR (Status)) { + AddDriver (PciDevice, ImageHandle); + PciRomAddImageMapping ( + ImageHandle, + PciDevice->PciRootBridgeIo->SegmentNumber, + PciDevice->BusNumber, + PciDevice->DeviceNumber, + PciDevice->FunctionNumber, + (UINT64) (UINTN) PciDevice->PciIo.RomImage, + PciDevice->PciIo.RomSize + ); + retStatus = EFI_SUCCESS; + } + } + } + + RomBarOffset = RomBarOffset + ImageSize; + } else { + RomBarOffset = RomBarOffset + ImageSize; + } + } else { + RomBarOffset = RomBarOffset + ImageSize; + } + + } while (((Indicator & 0x80) == 0x00) && ((UINTN) (RomBarOffset - (UINT8 *) RomBar) < PciDevice->RomSize)); + + return retStatus; + +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.h new file mode 100644 index 0000000000..2bb11bf3d3 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciOptionRomSupport.h @@ -0,0 +1,119 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciOptionRomSupport.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_OP_ROM_SUPPORT_H +#define _EFI_PCI_OP_ROM_SUPPORT_H + +EFI_STATUS +GetOpRomInfo ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +LoadOpRomImage ( + IN PCI_IO_DEVICE *PciDevice, + IN UINT64 RomBase + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDevice - TODO: add argument description + RomBase - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +RomDecode ( + IN PCI_IO_DEVICE *PciDevice, + IN UINT8 RomBarIndex, + IN UINT32 RomBar, + IN BOOLEAN Enable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDevice - TODO: add argument description + RomBarIndex - TODO: add argument description + RomBar - TODO: add argument description + Enable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ProcessOpRomImage ( + PCI_IO_DEVICE *PciDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.c new file mode 100644 index 0000000000..1760c3946b --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.c @@ -0,0 +1,83 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciPowerManagement.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "Pcibus.h" + +EFI_STATUS +ResetPowerManagementFeature ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + This function is intended to turn off PWE assertion and + put the device to D0 state if the device supports + PCI Power Management. + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + UINT8 PowerManagementRegBlock; + UINT16 PMCSR; + + PowerManagementRegBlock = 0; + + Status = LocateCapabilityRegBlock ( + PciIoDevice, + EFI_PCI_CAPABILITY_ID_PMI, + &PowerManagementRegBlock, + NULL + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Turn off the PWE assertion and put the device into D0 State + // + PMCSR = 0x8000; + + // + // Write PMCSR + // + PciIoDevice->PciIo.Pci.Write ( + &PciIoDevice->PciIo, + EfiPciIoWidthUint16, + PowerManagementRegBlock + 4, + 1, + &PMCSR + ); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.h new file mode 100644 index 0000000000..f33f7ab0de --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciPowerManagement.h @@ -0,0 +1,48 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciPowerManagement.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_POWER_MANAGEMENT_H +#define _EFI_PCI_POWER_MANAGEMENT_H + +EFI_STATUS +ResetPowerManagementFeature ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c new file mode 100644 index 0000000000..8f89e8983a --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.c @@ -0,0 +1,2276 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciResourceSupport.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "PciBus.h" +#include "PciResourceSupport.h" +#include "PciCommand.h" + +EFI_STATUS +SkipVGAAperture ( + OUT UINT64 *Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + The function is used to skip VGA range + +Arguments: + +Returns: + + None + +--*/ +// TODO: Start - add argument and description to function comment +// TODO: Length - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Original; + UINT64 Mask; + UINT64 StartOffset; + UINT64 LimitOffset; + + // + // For legacy VGA, bit 10 to bit 15 is not decoded + // + Mask = 0x3FF; + + Original = *Start; + StartOffset = Original & Mask; + LimitOffset = ((*Start) + Length - 1) & Mask; + if (LimitOffset >= VGABASE1) { + *Start = *Start - StartOffset + VGALIMIT2 + 1; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +SkipIsaAliasAperture ( + OUT UINT64 *Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + This function is used to skip ISA aliasing aperture + +Arguments: + +Returns: + + None + +--*/ +// TODO: Start - add argument and description to function comment +// TODO: Length - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + UINT64 Original; + UINT64 Mask; + UINT64 StartOffset; + UINT64 LimitOffset; + + // + // For legacy ISA, bit 10 to bit 15 is not decoded + // + Mask = 0x3FF; + + Original = *Start; + StartOffset = Original & Mask; + LimitOffset = ((*Start) + Length - 1) & Mask; + + if (LimitOffset >= ISABASE) { + *Start = *Start - StartOffset + ISALIMIT + 1; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +InsertResourceNode ( + PCI_RESOURCE_NODE *Bridge, + PCI_RESOURCE_NODE *ResNode + ) +/*++ + +Routine Description: + + This function inserts a resource node into the resource list. + The resource list is sorted in descend order. + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: ResNode - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + LIST_ENTRY *CurrentLink; + PCI_RESOURCE_NODE *Temp; + UINT64 ResNodeAlignRest; + UINT64 TempAlignRest; + + InsertHeadList (&Bridge->ChildList, &ResNode->Link); + + CurrentLink = Bridge->ChildList.ForwardLink->ForwardLink; + while (CurrentLink != &Bridge->ChildList) { + Temp = RESOURCE_NODE_FROM_LINK (CurrentLink); + + if (ResNode->Alignment > Temp->Alignment) { + break; + } else if (ResNode->Alignment == Temp->Alignment) { + ResNodeAlignRest = ResNode->Length & ResNode->Alignment; + TempAlignRest = Temp->Length & Temp->Alignment; + if ((ResNodeAlignRest == 0) || (ResNodeAlignRest >= TempAlignRest)) { + break; + } + } + + SwapListEntries (&ResNode->Link, CurrentLink); + + CurrentLink = ResNode->Link.ForwardLink; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +MergeResourceTree ( + PCI_RESOURCE_NODE *Dst, + PCI_RESOURCE_NODE *Res, + BOOLEAN TypeMerge + ) +/*++ + +Routine Description: + + This routine is used to merge two different resource tree in need of + resoure degradation. For example, if a upstream PPB doesn't support, + prefetchable memory decoding, the PCI bus driver will choose to call this function + to merge prefectchable memory resource list into normal memory list. + + If the TypeMerge is TRUE, Res resource type is changed to the type of destination resource + type. + +Arguments: + +Returns: + + None + +--*/ +// TODO: Dst - add argument and description to function comment +// TODO: Res - add argument and description to function comment +// TODO: TypeMerge - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + LIST_ENTRY *CurrentLink; + PCI_RESOURCE_NODE *Temp; + + while (!IsListEmpty (&Res->ChildList)) { + CurrentLink = Res->ChildList.ForwardLink; + + Temp = RESOURCE_NODE_FROM_LINK (CurrentLink); + + if (TypeMerge) { + Temp->ResType = Dst->ResType; + } + + RemoveEntryList (CurrentLink); + InsertResourceNode (Dst, Temp); + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CalculateApertureIo16 ( + IN PCI_RESOURCE_NODE *Bridge + ) +/*++ + +Routine Description: + + This function is used to calculate the IO16 aperture + for a bridge. + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + UINT64 Aperture; + LIST_ENTRY *CurrentLink; + PCI_RESOURCE_NODE *Node; + UINT64 offset; + + // + // Always assume there is ISA device and VGA device on the platform + // will be customized later + // + Aperture = 0; + + if (!Bridge) { + return EFI_SUCCESS; + } + + CurrentLink = Bridge->ChildList.ForwardLink; + + // + // Assume the bridge is aligned + // + while (CurrentLink != &Bridge->ChildList) { + + Node = RESOURCE_NODE_FROM_LINK (CurrentLink); + + // + // Consider the aperture alignment + // + offset = Aperture & (Node->Alignment); + + if (offset) { + + Aperture = Aperture + (Node->Alignment + 1) - offset; + + } + + // + // IsaEnable and VGAEnable can not be implemented now. + // If both of them are enabled, then the IO resource would + // become too limited to meet the requirement of most of devices. + // + + Node->Offset = Aperture; + + // + // Increment aperture by the length of node + // + Aperture += Node->Length; + + CurrentLink = CurrentLink->ForwardLink; + } + + // + // At last, adjust the aperture with the bridge's + // alignment + // + offset = Aperture & (Bridge->Alignment); + + if (offset) { + Aperture = Aperture + (Bridge->Alignment + 1) - offset; + } + + Bridge->Length = Aperture; + // + // At last, adjust the bridge's alignment to the first child's alignment + // if the bridge has at least one child + // + CurrentLink = Bridge->ChildList.ForwardLink; + if (CurrentLink != &Bridge->ChildList) { + Node = RESOURCE_NODE_FROM_LINK (CurrentLink); + if (Node->Alignment > Bridge->Alignment) { + Bridge->Alignment = Node->Alignment; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CalculateResourceAperture ( + IN PCI_RESOURCE_NODE *Bridge + ) +/*++ + +Routine Description: + + This function is used to calculate the resource aperture + for a given bridge device + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT64 Aperture; + LIST_ENTRY *CurrentLink; + PCI_RESOURCE_NODE *Node; + + UINT64 offset; + + Aperture = 0; + + if (!Bridge) { + return EFI_SUCCESS; + } + + if (Bridge->ResType == PciBarTypeIo16) { + return CalculateApertureIo16 (Bridge); + } + + CurrentLink = Bridge->ChildList.ForwardLink; + + // + // Assume the bridge is aligned + // + while (CurrentLink != &Bridge->ChildList) { + + Node = RESOURCE_NODE_FROM_LINK (CurrentLink); + + // + // Apply padding resource if available + // + + offset = Aperture & (Node->Alignment); + + if (offset) { + + Aperture = Aperture + (Node->Alignment + 1) - offset; + + } + + // + // Recode current aperture as a offset + // this offset will be used in future real allocation + // + Node->Offset = Aperture; + + // + // Increment aperture by the length of node + // + Aperture += Node->Length; + + // + // Consider the aperture alignment + // + + CurrentLink = CurrentLink->ForwardLink; + } + + // + // At last, adjust the aperture with the bridge's + // alignment + // + offset = Aperture & (Bridge->Alignment); + if (offset) { + Aperture = Aperture + (Bridge->Alignment + 1) - offset; + } + + // + // If the bridge has already padded the resource and the + // amount of padded resource is larger, then keep the + // padded resource + // + if (Bridge->Length < Aperture) { + Bridge->Length = Aperture; + } + + // + // At last, adjust the bridge's alignment to the first child's alignment + // if the bridge has at least one child + // + CurrentLink = Bridge->ChildList.ForwardLink; + if (CurrentLink != &Bridge->ChildList) { + Node = RESOURCE_NODE_FROM_LINK (CurrentLink); + if (Node->Alignment > Bridge->Alignment) { + Bridge->Alignment = Node->Alignment; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetResourceFromDevice ( + PCI_IO_DEVICE *PciDev, + PCI_RESOURCE_NODE *IoNode, + PCI_RESOURCE_NODE *Mem32Node, + PCI_RESOURCE_NODE *PMem32Node, + PCI_RESOURCE_NODE *Mem64Node, + PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciDev - add argument and description to function comment +// TODO: IoNode - add argument and description to function comment +// TODO: Mem32Node - add argument and description to function comment +// TODO: PMem32Node - add argument and description to function comment +// TODO: Mem64Node - add argument and description to function comment +// TODO: PMem64Node - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + UINT8 Index; + PCI_RESOURCE_NODE *Node; + BOOLEAN ResourceRequested; + + Node = NULL; + ResourceRequested = FALSE; + + for (Index = 0; Index < PCI_MAX_BAR; Index++) { + + switch ((PciDev->PciBar)[Index].BarType) { + + case PciBarTypeMem32: + + Node = CreateResourceNode ( + PciDev, + (PciDev->PciBar)[Index].Length, + (PciDev->PciBar)[Index].Alignment, + Index, + PciBarTypeMem32, + PciResUsageTypical + ); + + InsertResourceNode ( + Mem32Node, + Node + ); + + ResourceRequested = TRUE; + break; + + case PciBarTypeMem64: + + Node = CreateResourceNode ( + PciDev, + (PciDev->PciBar)[Index].Length, + (PciDev->PciBar)[Index].Alignment, + Index, + PciBarTypeMem64, + PciResUsageTypical + ); + + InsertResourceNode ( + Mem64Node, + Node + ); + + ResourceRequested = TRUE; + break; + + case PciBarTypePMem64: + + Node = CreateResourceNode ( + PciDev, + (PciDev->PciBar)[Index].Length, + (PciDev->PciBar)[Index].Alignment, + Index, + PciBarTypePMem64, + PciResUsageTypical + ); + + InsertResourceNode ( + PMem64Node, + Node + ); + + ResourceRequested = TRUE; + break; + + case PciBarTypePMem32: + + Node = CreateResourceNode ( + PciDev, + (PciDev->PciBar)[Index].Length, + (PciDev->PciBar)[Index].Alignment, + Index, + PciBarTypePMem32, + PciResUsageTypical + ); + + InsertResourceNode ( + PMem32Node, + Node + ); + ResourceRequested = TRUE; + break; + + case PciBarTypeIo16: + case PciBarTypeIo32: + + Node = CreateResourceNode ( + PciDev, + (PciDev->PciBar)[Index].Length, + (PciDev->PciBar)[Index].Alignment, + Index, + PciBarTypeIo16, + PciResUsageTypical + ); + + InsertResourceNode ( + IoNode, + Node + ); + ResourceRequested = TRUE; + break; + + case PciBarTypeUnknown: + break; + + default: + break; + } + } + + // + // If there is no resource requested from this device, + // then we indicate this device has been allocated naturally. + // + if (!ResourceRequested) { + PciDev->Allocated = TRUE; + } + + return EFI_SUCCESS; +} + +PCI_RESOURCE_NODE * +CreateResourceNode ( + IN PCI_IO_DEVICE *PciDev, + IN UINT64 Length, + IN UINT64 Alignment, + IN UINT8 Bar, + IN PCI_BAR_TYPE ResType, + IN PCI_RESOURCE_USAGE ResUsage + ) +/*++ + +Routine Description: + + This function is used to create a resource node + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciDev - add argument and description to function comment +// TODO: Length - add argument and description to function comment +// TODO: Alignment - add argument and description to function comment +// TODO: Bar - add argument and description to function comment +// TODO: ResType - add argument and description to function comment +// TODO: ResUsage - add argument and description to function comment +{ + EFI_STATUS Status; + PCI_RESOURCE_NODE *Node; + + Status = 0; + Node = NULL; + + Node = AllocatePool (sizeof (PCI_RESOURCE_NODE)); + if (Node == NULL) { + return NULL; + } + + ZeroMem (Node, sizeof (PCI_RESOURCE_NODE)); + + Node->Signature = PCI_RESOURCE_SIGNATURE; + Node->PciDev = PciDev; + Node->Length = Length; + Node->Alignment = Alignment; + Node->Bar = Bar; + Node->ResType = ResType; + Node->Reserved = FALSE; + Node->ResourceUsage = ResUsage; + InitializeListHead (&Node->ChildList); + return Node; +} + +EFI_STATUS +CreateResourceMap ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_RESOURCE_NODE *IoNode, + IN PCI_RESOURCE_NODE *Mem32Node, + IN PCI_RESOURCE_NODE *PMem32Node, + IN PCI_RESOURCE_NODE *Mem64Node, + IN PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + + This routine is used to extract resource request from + device node list. + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: IoNode - add argument and description to function comment +// TODO: Mem32Node - add argument and description to function comment +// TODO: PMem32Node - add argument and description to function comment +// TODO: Mem64Node - add argument and description to function comment +// TODO: PMem64Node - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *Temp; + EFI_STATUS Status; + PCI_RESOURCE_NODE *IoBridge; + PCI_RESOURCE_NODE *Mem32Bridge; + PCI_RESOURCE_NODE *PMem32Bridge; + PCI_RESOURCE_NODE *Mem64Bridge; + PCI_RESOURCE_NODE *PMem64Bridge; + LIST_ENTRY *CurrentLink; + + CurrentLink = Bridge->ChildList.ForwardLink; + + while (CurrentLink && CurrentLink != &Bridge->ChildList) { + + Temp = PCI_IO_DEVICE_FROM_LINK (CurrentLink); + + // + // Create resource nodes for this device by scanning the + // Bar array in the device private data + // If the upstream bridge doesn't support this device, + // no any resource node will be created for this device + // + GetResourceFromDevice ( + Temp, + IoNode, + Mem32Node, + PMem32Node, + Mem64Node, + PMem64Node + ); + + if (IS_PCI_BRIDGE (&Temp->Pci)) { + + // + // If the device has children, create a bridge resource node for this PPB + // Note: For PPB, memory aperture is aligned with 1MB and IO aperture + // is aligned with 4KB + // This device is typically a bridge device like PPB and P2C + // + IoBridge = CreateResourceNode ( + Temp, + 0, + 0xFFF, + PPB_IO_RANGE, + PciBarTypeIo16, + PciResUsageTypical + ); //0x1000 aligned + + Mem32Bridge = CreateResourceNode ( + Temp, + 0, + 0xFFFFF, + PPB_MEM32_RANGE, + PciBarTypeMem32, + PciResUsageTypical + ); + + PMem32Bridge = CreateResourceNode ( + Temp, + 0, + 0xFFFFF, + PPB_PMEM32_RANGE, + PciBarTypePMem32, + PciResUsageTypical + ); + + Mem64Bridge = CreateResourceNode ( + Temp, + 0, + 0xFFFFF, + PPB_MEM64_RANGE, + PciBarTypeMem64, + PciResUsageTypical + ); + + PMem64Bridge = CreateResourceNode ( + Temp, + 0, + 0xFFFFF, + PPB_PMEM64_RANGE, + PciBarTypePMem64, + PciResUsageTypical + ); + + // + // Recursively create resouce map on this bridge + // + Status = CreateResourceMap ( + Temp, + IoBridge, + Mem32Bridge, + PMem32Bridge, + Mem64Bridge, + PMem64Bridge + ); + + if (ResourceRequestExisted (IoBridge)) { + InsertResourceNode ( + IoNode, + IoBridge + ); + } else { + gBS->FreePool (IoBridge); + IoBridge = NULL; + } + + // + // If there is node under this resource bridge, + // then calculate bridge's aperture of this type + // and insert it into the respective resource tree. + // If no, delete this resource bridge + // + if (ResourceRequestExisted (Mem32Bridge)) { + InsertResourceNode ( + Mem32Node, + Mem32Bridge + ); + } else { + gBS->FreePool (Mem32Bridge); + Mem32Bridge = NULL; + } + + // + // If there is node under this resource bridge, + // then calculate bridge's aperture of this type + // and insert it into the respective resource tree. + // If no, delete this resource bridge + // + if (ResourceRequestExisted (PMem32Bridge)) { + InsertResourceNode ( + PMem32Node, + PMem32Bridge + ); + } else { + gBS->FreePool (PMem32Bridge); + PMem32Bridge = NULL; + } + + // + // If there is node under this resource bridge, + // then calculate bridge's aperture of this type + // and insert it into the respective resource tree. + // If no, delete this resource bridge + // + if (ResourceRequestExisted (Mem64Bridge)) { + InsertResourceNode ( + Mem64Node, + Mem64Bridge + ); + } else { + gBS->FreePool (Mem64Bridge); + Mem64Bridge = NULL; + } + + // + // If there is node under this resource bridge, + // then calculate bridge's aperture of this type + // and insert it into the respective resource tree. + // If no, delete this resource bridge + // + if (ResourceRequestExisted (PMem64Bridge)) { + InsertResourceNode ( + PMem64Node, + PMem64Bridge + ); + } else { + gBS->FreePool (PMem64Bridge); + PMem64Bridge = NULL; + } + + } + + // + // If it is P2C, apply hard coded resource padding + // + // + if (IS_CARDBUS_BRIDGE (&Temp->Pci)) { + ResourcePaddingForCardBusBridge ( + Temp, + IoNode, + Mem32Node, + PMem32Node, + Mem64Node, + PMem64Node + ); + } + + CurrentLink = CurrentLink->ForwardLink; + } + // + // + // To do some platform specific resource padding ... + // + Status = ResourcePaddingPolicy ( + Bridge, + IoNode, + Mem32Node, + PMem32Node, + Mem64Node, + PMem64Node + ); + + // + // Degrade resource if necessary + // + DegradeResource ( + Bridge, + Mem32Node, + PMem32Node, + Mem64Node, + PMem64Node + ); + + // + // Calculate resource aperture for this bridge device + // + CalculateResourceAperture (Mem32Node); + CalculateResourceAperture (PMem32Node); + CalculateResourceAperture (Mem64Node); + CalculateResourceAperture (PMem64Node); + CalculateResourceAperture (IoNode); + + return EFI_SUCCESS; + +} + +EFI_STATUS +ResourcePaddingPolicy ( + PCI_IO_DEVICE *PciDev, + PCI_RESOURCE_NODE *IoNode, + PCI_RESOURCE_NODE *Mem32Node, + PCI_RESOURCE_NODE *PMem32Node, + PCI_RESOURCE_NODE *Mem64Node, + PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + + This function is used to do the resource padding for a specific platform + +Arguments: + + PciDev - A pointer to the PCI_IO_DEVICE structrue. + IoNode - A pointer to the PCI_RESOURCE_NODE structrue. + Mem32Node - A pointer to the PCI_RESOURCE_NODE structrue. + PMem32Node - A pointer to the PCI_RESOURCE_NODE structrue. + Mem64Node - A pointer to the PCI_RESOURCE_NODE structrue. + PMem64Node - A pointer to the PCI_RESOURCE_NODE structrue. + +Returns: + Status code + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + // + // Create padding resource node + // + if (PciDev->ResourcePaddingDescriptors != NULL) { + ApplyResourcePadding ( + PciDev, + IoNode, + Mem32Node, + PMem32Node, + Mem64Node, + PMem64Node + ); + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +DegradeResource ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_RESOURCE_NODE *Mem32Node, + IN PCI_RESOURCE_NODE *PMem32Node, + IN PCI_RESOURCE_NODE *Mem64Node, + IN PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + + This function is used to degrade resource if the upstream bridge + doesn't support certain resource. Degradation path is + PMEM64 -> MEM64 -> MEM32 + PMEM64 -> PMEM32 -> MEM32 + IO32 -> IO16 + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: Mem32Node - add argument and description to function comment +// TODO: PMem32Node - add argument and description to function comment +// TODO: Mem64Node - add argument and description to function comment +// TODO: PMem64Node - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + // + // If bridge doesn't support Prefetchable + // memory64, degrade it to Mem64 + // + if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM64_DECODE_SUPPORTED)) { + MergeResourceTree ( + PMem32Node, + PMem64Node, + TRUE + ); + } else { + // + // if no PMem32 request, still keep PMem64. Otherwise degrade to PMem32 + // + if (PMem32Node != NULL) { + MergeResourceTree ( + PMem32Node, + PMem64Node, + TRUE + ); + } + } + + + // + // If bridge doesn't support Mem64 + // degrade it to mem32 + // + if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_MEM64_DECODE_SUPPORTED)) { + MergeResourceTree ( + Mem32Node, + Mem64Node, + TRUE + ); + } + + // + // If bridge doesn't support Pmem32 + // degrade it to mem32 + // + if (!BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM32_DECODE_SUPPORTED)) { + MergeResourceTree ( + Mem32Node, + PMem32Node, + TRUE + ); + } + + // + // if bridge supports combined Pmem Mem decoding + // merge these two type of resource + // + if (BridgeSupportResourceDecode (Bridge, EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED)) { + MergeResourceTree ( + Mem32Node, + PMem32Node, + FALSE + ); + + MergeResourceTree ( + Mem64Node, + PMem64Node, + FALSE + ); + } + + return EFI_SUCCESS; +} + +BOOLEAN +BridgeSupportResourceDecode ( + IN PCI_IO_DEVICE *Bridge, + IN UINT32 Decode + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + Decode - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + /*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ + if ((Bridge->Decodes) & Decode) { + return TRUE; + } + + return FALSE; +} + +EFI_STATUS +ProgramResource ( + IN UINT64 Base, + IN PCI_RESOURCE_NODE *Bridge + ) +/*++ + +Routine Description: + + This function is used to program the resource allocated + for each resource node + +Arguments: + +Returns: + + None + +--*/ +// TODO: Base - add argument and description to function comment +// TODO: Bridge - add argument and description to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + LIST_ENTRY *CurrentLink; + PCI_RESOURCE_NODE *Node; + EFI_STATUS Status; + + if (Base == gAllOne) { + return EFI_OUT_OF_RESOURCES; + } + + CurrentLink = Bridge->ChildList.ForwardLink; + + while (CurrentLink != &Bridge->ChildList) { + + Node = RESOURCE_NODE_FROM_LINK (CurrentLink); + + if (!IS_PCI_BRIDGE (&(Node->PciDev->Pci))) { + + if (IS_CARDBUS_BRIDGE (&(Node->PciDev->Pci))) { + ProgramP2C (Base, Node); + } else { + ProgramBar (Base, Node); + } + } else { + Status = ProgramResource (Base + Node->Offset, Node); + + if (EFI_ERROR (Status)) { + return Status; + } + + ProgramPpbApperture (Base, Node); + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ProgramBar ( + IN UINT64 Base, + IN PCI_RESOURCE_NODE *Node + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Base - add argument and description to function comment +// TODO: Node - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 Address; + UINT32 Address32; + + Address = 0; + PciIo = &(Node->PciDev->PciIo); + + Address = Base + Node->Offset; + + // + // Indicate pci bus driver has allocated + // resource for this device + // It might be a temporary solution here since + // pci device could have multiple bar + // + Node->PciDev->Allocated = TRUE; + + switch ((Node->PciDev->PciBar[Node->Bar]).BarType) { + + case PciBarTypeIo16: + case PciBarTypeIo32: + case PciBarTypeMem32: + case PciBarTypePMem32: + + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + (Node->PciDev->PciBar[Node->Bar]).Offset, + 1, + &Address + ); + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + + break; + + case PciBarTypeMem64: + case PciBarTypePMem64: + + Address32 = (UINT32) (Address & 0x00000000FFFFFFFF); + + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + (Node->PciDev->PciBar[Node->Bar]).Offset, + 1, + &Address32 + ); + + Address32 = (UINT32) RShiftU64 (Address, 32); + + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + (UINT8) ((Node->PciDev->PciBar[Node->Bar]).Offset + 4), + 1, + &Address32 + ); + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + + break; + + default: + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ProgramPpbApperture ( + IN UINT64 Base, + IN PCI_RESOURCE_NODE *Node + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Base - add argument and description to function comment +// TODO: Node - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 Address; + UINT32 Address32; + + Address = 0; + // + // if no device south of this PPB, return anyway + // Apperture is set default in the initialization code + // + if (Node->Length == 0 || Node->ResourceUsage == PciResUsagePadding) { + // + // For padding resource node, just ignore when programming + // + return EFI_SUCCESS; + } + + PciIo = &(Node->PciDev->PciIo); + Address = Base + Node->Offset; + + // + // Indicate the PPB resource has been allocated + // + Node->PciDev->Allocated = TRUE; + + switch (Node->Bar) { + + case PPB_BAR_0: + case PPB_BAR_1: + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + (Node->PciDev->PciBar[Node->Bar]).Offset, + 1, + &Address + ); + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + Node->PciDev->PciBar[Node->Bar].Length = Node->Length; + + break; + + case PPB_IO_RANGE: + + Address32 = ((UINT32) (Address)) >> 8; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint8, + 0x1C, + 1, + &Address32 + ); + + Address32 >>= 8; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x30, + 1, + &Address32 + ); + + Address32 = (UINT32) (Address + Node->Length - 1); + Address32 = ((UINT32) (Address32)) >> 8; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint8, + 0x1D, + 1, + &Address32 + ); + + Address32 >>= 8; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x32, + 1, + &Address32 + ); + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + Node->PciDev->PciBar[Node->Bar].Length = Node->Length; + break; + + case PPB_MEM32_RANGE: + + Address32 = ((UINT32) (Address)) >> 16; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x20, + 1, + &Address32 + ); + + Address32 = (UINT32) (Address + Node->Length - 1); + Address32 = ((UINT32) (Address32)) >> 16; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x22, + 1, + &Address32 + ); + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + Node->PciDev->PciBar[Node->Bar].Length = Node->Length; + break; + + case PPB_PMEM32_RANGE: + case PPB_PMEM64_RANGE: + + Address32 = ((UINT32) (Address)) >> 16; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x24, + 1, + &Address32 + ); + + Address32 = (UINT32) (Address + Node->Length - 1); + Address32 = ((UINT32) (Address32)) >> 16; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x26, + 1, + &Address32 + ); + + Address32 = (UINT32) RShiftU64 (Address, 32); + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x28, + 1, + &Address32 + ); + + Address32 = (UINT32) RShiftU64 ((Address + Node->Length - 1), 32); + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x2C, + 1, + &Address32 + ); + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + Node->PciDev->PciBar[Node->Bar].Length = Node->Length; + break; + + default: + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ProgrameUpstreamBridgeForRom ( + IN PCI_IO_DEVICE *PciDevice, + IN UINT32 OptionRomBase, + IN BOOLEAN Enable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +// TODO: PciDevice - add argument and description to function comment +// TODO: OptionRomBase - add argument and description to function comment +// TODO: Enable - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_IO_DEVICE *Parent; + PCI_RESOURCE_NODE Node; + // + // For root bridge, just return. + // + Parent = PciDevice->Parent; + ZeroMem (&Node, sizeof (Node)); + while (Parent) { + if (!IS_PCI_BRIDGE (&Parent->Pci)) { + break; + } + + Node.PciDev = Parent; + Node.Length = PciDevice->RomSize; + Node.Alignment = 0; + Node.Bar = PPB_MEM32_RANGE; + Node.ResType = PciBarTypeMem32; + Node.Offset = 0; + + // + // Program PPB to only open a single <= 16Parent; + } + + return EFI_SUCCESS; +} + +BOOLEAN +ResourceRequestExisted ( + IN PCI_RESOURCE_NODE *Bridge + ) +/*++ + +Routine Description: + +Arguments: + + Bridge - A pointer to the PCI_RESOURCE_NODE. + +Returns: + + None + +--*/ +{ + if (Bridge != NULL) { + if (!IsListEmpty (&Bridge->ChildList) || Bridge->Length != 0) { + return TRUE; + } + } + + return FALSE; +} + +EFI_STATUS +InitializeResourcePool ( + PCI_RESOURCE_NODE *ResourcePool, + PCI_BAR_TYPE ResourceType + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: ResourcePool - add argument and description to function comment +// TODO: ResourceType - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + ZeroMem (ResourcePool, sizeof (PCI_RESOURCE_NODE)); + ResourcePool->ResType = ResourceType; + ResourcePool->Signature = PCI_RESOURCE_SIGNATURE; + InitializeListHead (&ResourcePool->ChildList); + + return EFI_SUCCESS; +} + +EFI_STATUS +GetResourceMap ( + PCI_IO_DEVICE *PciDev, + PCI_RESOURCE_NODE **IoBridge, + PCI_RESOURCE_NODE **Mem32Bridge, + PCI_RESOURCE_NODE **PMem32Bridge, + PCI_RESOURCE_NODE **Mem64Bridge, + PCI_RESOURCE_NODE **PMem64Bridge, + PCI_RESOURCE_NODE *IoPool, + PCI_RESOURCE_NODE *Mem32Pool, + PCI_RESOURCE_NODE *PMem32Pool, + PCI_RESOURCE_NODE *Mem64Pool, + PCI_RESOURCE_NODE *PMem64Pool + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciDev - add argument and description to function comment +// TODO: IoBridge - add argument and description to function comment +// TODO: Mem32Bridge - add argument and description to function comment +// TODO: PMem32Bridge - add argument and description to function comment +// TODO: Mem64Bridge - add argument and description to function comment +// TODO: PMem64Bridge - add argument and description to function comment +// TODO: IoPool - add argument and description to function comment +// TODO: Mem32Pool - add argument and description to function comment +// TODO: PMem32Pool - add argument and description to function comment +// TODO: Mem64Pool - add argument and description to function comment +// TODO: PMem64Pool - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + PCI_RESOURCE_NODE *Temp; + LIST_ENTRY *CurrentLink; + + CurrentLink = IoPool->ChildList.ForwardLink; + + // + // Get Io resource map + // + while (CurrentLink != &IoPool->ChildList) { + + Temp = RESOURCE_NODE_FROM_LINK (CurrentLink); + + if (Temp->PciDev == PciDev) { + *IoBridge = Temp; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + // + // Get Mem32 resource map + // + CurrentLink = Mem32Pool->ChildList.ForwardLink; + + while (CurrentLink != &Mem32Pool->ChildList) { + + Temp = RESOURCE_NODE_FROM_LINK (CurrentLink); + + if (Temp->PciDev == PciDev) { + *Mem32Bridge = Temp; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + // + // Get Pmem32 resource map + // + CurrentLink = PMem32Pool->ChildList.ForwardLink; + + while (CurrentLink != &PMem32Pool->ChildList) { + + Temp = RESOURCE_NODE_FROM_LINK (CurrentLink); + + if (Temp->PciDev == PciDev) { + *PMem32Bridge = Temp; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + // + // Get Mem64 resource map + // + CurrentLink = Mem64Pool->ChildList.ForwardLink; + + while (CurrentLink != &Mem64Pool->ChildList) { + + Temp = RESOURCE_NODE_FROM_LINK (CurrentLink); + + if (Temp->PciDev == PciDev) { + *Mem64Bridge = Temp; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + // + // Get Pmem64 resource map + // + CurrentLink = PMem64Pool->ChildList.ForwardLink; + + while (CurrentLink != &PMem64Pool->ChildList) { + + Temp = RESOURCE_NODE_FROM_LINK (CurrentLink); + + if (Temp->PciDev == PciDev) { + *PMem64Bridge = Temp; + } + + CurrentLink = CurrentLink->ForwardLink; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DestroyResourceTree ( + IN PCI_RESOURCE_NODE *Bridge + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Bridge - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_RESOURCE_NODE *Temp; + LIST_ENTRY *CurrentLink; + + while (!IsListEmpty (&Bridge->ChildList)) { + + CurrentLink = Bridge->ChildList.ForwardLink; + + Temp = RESOURCE_NODE_FROM_LINK (CurrentLink); + + RemoveEntryList (CurrentLink); + + if (IS_PCI_BRIDGE (&(Temp->PciDev->Pci))) { + DestroyResourceTree (Temp); + } + + gBS->FreePool (Temp); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +RecordReservedResource ( + IN UINT64 Base, + IN UINT64 Length, + IN PCI_BAR_TYPE ResType, + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Base - add argument and description to function comment +// TODO: Length - add argument and description to function comment +// TODO: ResType - add argument and description to function comment +// TODO: Bridge - add argument and description to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_RESERVED_RESOURCE_LIST *ReservedNode; + + ReservedNode = AllocatePool (sizeof (PCI_RESERVED_RESOURCE_LIST)); + if (ReservedNode == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + ReservedNode->Signature = RESERVED_RESOURCE_SIGNATURE; + ReservedNode->Node.Base = Base; + ReservedNode->Node.Length = Length; + ReservedNode->Node.ResType = ResType; + + InsertTailList (&Bridge->ReservedResourceList, &(ReservedNode->Link)); + + return EFI_SUCCESS; +} + +EFI_STATUS +ResourcePaddingForCardBusBridge ( + PCI_IO_DEVICE *PciDev, + PCI_RESOURCE_NODE *IoNode, + PCI_RESOURCE_NODE *Mem32Node, + PCI_RESOURCE_NODE *PMem32Node, + PCI_RESOURCE_NODE *Mem64Node, + PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciDev - add argument and description to function comment +// TODO: IoNode - add argument and description to function comment +// TODO: Mem32Node - add argument and description to function comment +// TODO: PMem32Node - add argument and description to function comment +// TODO: Mem64Node - add argument and description to function comment +// TODO: PMem64Node - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + PCI_RESOURCE_NODE *Node; + + Node = NULL; + + // + // Memory Base/Limit Register 0 + // Bar 1 denodes memory range 0 + // + Node = CreateResourceNode ( + PciDev, + 0x2000000, + 0x1ffffff, + 1, + PciBarTypeMem32, + PciResUsagePadding + ); + + InsertResourceNode ( + Mem32Node, + Node + ); + + // + // Memory Base/Limit Register 1 + // Bar 2 denodes memory range1 + // + Node = CreateResourceNode ( + PciDev, + 0x2000000, + 0x1ffffff, + 2, + PciBarTypePMem32, + PciResUsagePadding + ); + + InsertResourceNode ( + PMem32Node, + Node + ); + + // + // Io Base/Limit + // Bar 3 denodes io range 0 + // + Node = CreateResourceNode ( + PciDev, + 0x100, + 0xff, + 3, + PciBarTypeIo16, + PciResUsagePadding + ); + + InsertResourceNode ( + IoNode, + Node + ); + + // + // Io Base/Limit + // Bar 4 denodes io range 0 + // + Node = CreateResourceNode ( + PciDev, + 0x100, + 0xff, + 4, + PciBarTypeIo16, + PciResUsagePadding + ); + + InsertResourceNode ( + IoNode, + Node + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +ProgramP2C ( + IN UINT64 Base, + IN PCI_RESOURCE_NODE *Node + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Base - add argument and description to function comment +// TODO: Node - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_PCI_IO_PROTOCOL *PciIo; + UINT64 Address; + UINT64 TempAddress; + UINT16 BridgeControl; + + Address = 0; + PciIo = &(Node->PciDev->PciIo); + + Address = Base + Node->Offset; + + // + // Indicate pci bus driver has allocated + // resource for this device + // It might be a temporary solution here since + // pci device could have multiple bar + // + Node->PciDev->Allocated = TRUE; + + switch (Node->Bar) { + + case P2C_BAR_0: + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + (Node->PciDev->PciBar[Node->Bar]).Offset, + 1, + &Address + ); + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + Node->PciDev->PciBar[Node->Bar].Length = Node->Length; + break; + + case P2C_MEM_1: + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x1c, + 1, + &Address + ); + + TempAddress = Address + Node->Length - 1; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x20, + 1, + &TempAddress + ); + + if (Node->ResType == PciBarTypeMem32) { + + // + // Set non-prefetchable bit + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + 0x3e, + 1, + &BridgeControl + ); + + BridgeControl &= 0xfeff; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x3e, + 1, + &BridgeControl + ); + + } else { + + // + // Set pre-fetchable bit + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + 0x3e, + 1, + &BridgeControl + ); + + BridgeControl |= 0x0100; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x3e, + 1, + &BridgeControl + ); + } + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + Node->PciDev->PciBar[Node->Bar].Length = Node->Length; + Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType; + + break; + + case P2C_MEM_2: + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x24, + 1, + &Address + ); + + TempAddress = Address + Node->Length - 1; + + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x28, + 1, + &TempAddress + ); + + if (Node->ResType == PciBarTypeMem32) { + + // + // Set non-prefetchable bit + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + 0x3e, + 1, + &BridgeControl + ); + + BridgeControl &= 0xfdff; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x3e, + 1, + &BridgeControl + ); + } else { + + // + // Set pre-fetchable bit + // + PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint16, + 0x3e, + 1, + &BridgeControl + ); + + BridgeControl |= 0x0200; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + 0x3e, + 1, + &BridgeControl + ); + } + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + Node->PciDev->PciBar[Node->Bar].Length = Node->Length; + Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType; + break; + + case P2C_IO_1: + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x2c, + 1, + &Address + ); + TempAddress = Address + Node->Length - 1; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x30, + 1, + &TempAddress + ); + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + Node->PciDev->PciBar[Node->Bar].Length = Node->Length; + Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType; + + break; + + case P2C_IO_2: + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x34, + 1, + &Address + ); + + TempAddress = Address + Node->Length - 1; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint32, + 0x38, + 1, + &TempAddress + ); + + Node->PciDev->PciBar[Node->Bar].BaseAddress = Address; + Node->PciDev->PciBar[Node->Bar].Length = Node->Length; + Node->PciDev->PciBar[Node->Bar].BarType = Node->ResType; + break; + + default: + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ApplyResourcePadding ( + PCI_IO_DEVICE *PciDev, + PCI_RESOURCE_NODE *IoNode, + PCI_RESOURCE_NODE *Mem32Node, + PCI_RESOURCE_NODE *PMem32Node, + PCI_RESOURCE_NODE *Mem64Node, + PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: PciDev - add argument and description to function comment +// TODO: IoNode - add argument and description to function comment +// TODO: Mem32Node - add argument and description to function comment +// TODO: PMem32Node - add argument and description to function comment +// TODO: Mem64Node - add argument and description to function comment +// TODO: PMem64Node - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Ptr; + PCI_RESOURCE_NODE *Node; + UINT8 DummyBarIndex; + + DummyBarIndex = 0; + Ptr = PciDev->ResourcePaddingDescriptors; + + while (((EFI_ACPI_END_TAG_DESCRIPTOR *) Ptr)->Desc != ACPI_END_TAG_DESCRIPTOR) { + + if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) { + if (Ptr->AddrLen != 0) { + + Node = CreateResourceNode ( + PciDev, + Ptr->AddrLen, + Ptr->AddrRangeMax, + DummyBarIndex, + PciBarTypeIo16, + PciResUsagePadding + ); + InsertResourceNode ( + IoNode, + Node + ); + } + + Ptr++; + continue; + } + + if (Ptr->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR && Ptr->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) { + + if (Ptr->AddrSpaceGranularity == 32) { + + // + // prefechable + // + if (Ptr->SpecificFlag == 0x6) { + if (Ptr->AddrLen) { + Node = CreateResourceNode ( + PciDev, + Ptr->AddrLen, + Ptr->AddrRangeMax, + DummyBarIndex, + PciBarTypePMem32, + PciResUsagePadding + ); + InsertResourceNode ( + PMem32Node, + Node + ); + } + + Ptr++; + continue; + } + + // + // Non-prefechable + // + if (Ptr->SpecificFlag == 0) { + if (Ptr->AddrLen) { + Node = CreateResourceNode ( + PciDev, + Ptr->AddrLen, + Ptr->AddrRangeMax, + DummyBarIndex, + PciBarTypeMem32, + PciResUsagePadding + ); + InsertResourceNode ( + Mem32Node, + Node + ); + } + + Ptr++; + continue; + } + } + + if (Ptr->AddrSpaceGranularity == 64) { + + // + // prefechable + // + if (Ptr->SpecificFlag == 0x6) { + if (Ptr->AddrLen) { + Node = CreateResourceNode ( + PciDev, + Ptr->AddrLen, + Ptr->AddrRangeMax, + DummyBarIndex, + PciBarTypePMem64, + PciResUsagePadding + ); + InsertResourceNode ( + PMem64Node, + Node + ); + } + + Ptr++; + continue; + } + + // + // Non-prefechable + // + if (Ptr->SpecificFlag == 0) { + if (Ptr->AddrLen) { + Node = CreateResourceNode ( + PciDev, + Ptr->AddrLen, + Ptr->AddrRangeMax, + DummyBarIndex, + PciBarTypeMem64, + PciResUsagePadding + ); + InsertResourceNode ( + Mem64Node, + Node + ); + } + + Ptr++; + continue; + } + } + } + + Ptr++; + } + + return EFI_SUCCESS; +} + +// +// Light PCI bus driver woundn't support hotplug root device +// So no need to pad resource for them +// +VOID +GetResourcePaddingPpb ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + Get resource. + +Arguments: + + PciIoDevice A pointer to a pci device. + +Returns: + + None + +--*/ +{ + if (gPciHotPlugInit) { + if (PciIoDevice->ResourcePaddingDescriptors == NULL) { + GetResourcePaddingForHpb (PciIoDevice); + } + } +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.h new file mode 100644 index 0000000000..61ec29f7ec --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciResourceSupport.h @@ -0,0 +1,740 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciResourceSupport.h + +Abstract: + + + +Revision History + +--*/ + +#ifndef _EFI_PCI_RESOURCE_SUPPORT_H +#define _EFI_PCI_RESOURCE_SUPPORT_H + +#define RESERVED_RESOURCE_SIGNATURE EFI_SIGNATURE_32 ('r', 's', 'v', 'd') + +typedef struct { + UINT64 Base; + UINT64 Length; + PCI_BAR_TYPE ResType; +} PCI_RESERVED_RESOURCE_NODE; + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + PCI_RESERVED_RESOURCE_NODE Node; +} PCI_RESERVED_RESOURCE_LIST; + +#define RESOURCED_LIST_FROM_NODE(a) \ + CR (a, PCI_RESERVED_RESOURCE_LIST, Node, RESERVED_RESOURCE_SIGNATURE) + +#define RESOURCED_LIST_FROM_LINK(a) \ + CR (a, PCI_RESERVED_RESOURCE_LIST, Link, RESERVED_RESOURCE_SIGNATURE) + +typedef enum { + PciResUsageTypical = 0, + PciResUsagePadding, + PciResUsageOptionRomProcessing +} PCI_RESOURCE_USAGE; + +#define PCI_RESOURCE_SIGNATURE EFI_SIGNATURE_32 ('p', 'c', 'r', 'c') + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + LIST_ENTRY ChildList; + PCI_IO_DEVICE *PciDev; + UINT64 Alignment; + UINT64 Offset; + UINT8 Bar; + PCI_BAR_TYPE ResType; + UINT64 Length; + BOOLEAN Reserved; + PCI_RESOURCE_USAGE ResourceUsage; +} PCI_RESOURCE_NODE; + +#define RESOURCE_NODE_FROM_LINK(a) \ + CR (a, PCI_RESOURCE_NODE, Link, PCI_RESOURCE_SIGNATURE) + +EFI_STATUS +SkipVGAAperture ( + OUT UINT64 *Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Start - TODO: add argument description + Length - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SkipIsaAliasAperture ( + OUT UINT64 *Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Start - TODO: add argument description + Length - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +InsertResourceNode ( + PCI_RESOURCE_NODE *Bridge, + PCI_RESOURCE_NODE *ResNode + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + ResNode - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +MergeResourceTree ( + PCI_RESOURCE_NODE *Dst, + PCI_RESOURCE_NODE *Res, + BOOLEAN TypeMerge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Dst - TODO: add argument description + Res - TODO: add argument description + TypeMerge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CalculateApertureIo16 ( + IN PCI_RESOURCE_NODE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CalculateResourceAperture ( + IN PCI_RESOURCE_NODE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetResourceFromDevice ( + PCI_IO_DEVICE *PciDev, + PCI_RESOURCE_NODE *IoNode, + PCI_RESOURCE_NODE *Mem32Node, + PCI_RESOURCE_NODE *PMem32Node, + PCI_RESOURCE_NODE *Mem64Node, + PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDev - TODO: add argument description + IoNode - TODO: add argument description + Mem32Node - TODO: add argument description + PMem32Node - TODO: add argument description + Mem64Node - TODO: add argument description + PMem64Node - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +PCI_RESOURCE_NODE * +CreateResourceNode ( + IN PCI_IO_DEVICE *PciDev, + IN UINT64 Length, + IN UINT64 Alignment, + IN UINT8 Bar, + IN PCI_BAR_TYPE ResType, + IN PCI_RESOURCE_USAGE ResUsage + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDev - TODO: add argument description + Length - TODO: add argument description + Alignment - TODO: add argument description + Bar - TODO: add argument description + ResType - TODO: add argument description + ResUsage - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CreateResourceMap ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_RESOURCE_NODE *IoNode, + IN PCI_RESOURCE_NODE *Mem32Node, + IN PCI_RESOURCE_NODE *PMem32Node, + IN PCI_RESOURCE_NODE *Mem64Node, + IN PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + IoNode - TODO: add argument description + Mem32Node - TODO: add argument description + PMem32Node - TODO: add argument description + Mem64Node - TODO: add argument description + PMem64Node - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ResourcePaddingPolicy ( + PCI_IO_DEVICE *PciDev, + PCI_RESOURCE_NODE *IoNode, + PCI_RESOURCE_NODE *Mem32Node, + PCI_RESOURCE_NODE *PMem32Node, + PCI_RESOURCE_NODE *Mem64Node, + PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDev - TODO: add argument description + IoNode - TODO: add argument description + Mem32Node - TODO: add argument description + PMem32Node - TODO: add argument description + Mem64Node - TODO: add argument description + PMem64Node - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DegradeResource ( + IN PCI_IO_DEVICE *Bridge, + IN PCI_RESOURCE_NODE *Mem32Node, + IN PCI_RESOURCE_NODE *PMem32Node, + IN PCI_RESOURCE_NODE *Mem64Node, + IN PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + Mem32Node - TODO: add argument description + PMem32Node - TODO: add argument description + Mem64Node - TODO: add argument description + PMem64Node - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +BridgeSupportResourceDecode ( + IN PCI_IO_DEVICE *Bridge, + IN UINT32 Decode + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + Decode - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ProgramResource ( + IN UINT64 Base, + IN PCI_RESOURCE_NODE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Base - TODO: add argument description + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ProgramBar ( + IN UINT64 Base, + IN PCI_RESOURCE_NODE *Node + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Base - TODO: add argument description + Node - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ProgramPpbApperture ( + IN UINT64 Base, + IN PCI_RESOURCE_NODE *Node + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Base - TODO: add argument description + Node - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ProgrameUpstreamBridgeForRom ( + IN PCI_IO_DEVICE *PciDevice, + IN UINT32 OptionRomBase, + IN BOOLEAN Enable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDevice - TODO: add argument description + OptionRomBase - TODO: add argument description + Enable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ResourceRequestExisted ( + IN PCI_RESOURCE_NODE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +InitializeResourcePool ( + PCI_RESOURCE_NODE *ResourcePool, + PCI_BAR_TYPE ResourceType + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ResourcePool - TODO: add argument description + ResourceType - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetResourceMap ( + PCI_IO_DEVICE *PciDev, + PCI_RESOURCE_NODE **IoBridge, + PCI_RESOURCE_NODE **Mem32Bridge, + PCI_RESOURCE_NODE **PMem32Bridge, + PCI_RESOURCE_NODE **Mem64Bridge, + PCI_RESOURCE_NODE **PMem64Bridge, + PCI_RESOURCE_NODE *IoPool, + PCI_RESOURCE_NODE *Mem32Pool, + PCI_RESOURCE_NODE *PMem32Pool, + PCI_RESOURCE_NODE *Mem64Pool, + PCI_RESOURCE_NODE *PMem64Pool + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDev - TODO: add argument description + IoBridge - TODO: add argument description + Mem32Bridge - TODO: add argument description + PMem32Bridge - TODO: add argument description + Mem64Bridge - TODO: add argument description + PMem64Bridge - TODO: add argument description + IoPool - TODO: add argument description + Mem32Pool - TODO: add argument description + PMem32Pool - TODO: add argument description + Mem64Pool - TODO: add argument description + PMem64Pool - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DestroyResourceTree ( + IN PCI_RESOURCE_NODE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +RecordReservedResource ( + IN UINT64 Base, + IN UINT64 Length, + IN PCI_BAR_TYPE ResType, + IN PCI_IO_DEVICE *Bridge + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Base - TODO: add argument description + Length - TODO: add argument description + ResType - TODO: add argument description + Bridge - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ResourcePaddingForCardBusBridge ( + PCI_IO_DEVICE *PciDev, + PCI_RESOURCE_NODE *IoNode, + PCI_RESOURCE_NODE *Mem32Node, + PCI_RESOURCE_NODE *PMem32Node, + PCI_RESOURCE_NODE *Mem64Node, + PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDev - TODO: add argument description + IoNode - TODO: add argument description + Mem32Node - TODO: add argument description + PMem32Node - TODO: add argument description + Mem64Node - TODO: add argument description + PMem64Node - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ProgramP2C ( + IN UINT64 Base, + IN PCI_RESOURCE_NODE *Node + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Base - TODO: add argument description + Node - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ApplyResourcePadding ( + PCI_IO_DEVICE *PciDev, + PCI_RESOURCE_NODE *IoNode, + PCI_RESOURCE_NODE *Mem32Node, + PCI_RESOURCE_NODE *PMem32Node, + PCI_RESOURCE_NODE *Mem64Node, + PCI_RESOURCE_NODE *PMem64Node + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciDev - TODO: add argument description + IoNode - TODO: add argument description + Mem32Node - TODO: add argument description + PMem32Node - TODO: add argument description + Mem64Node - TODO: add argument description + PMem64Node - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +GetResourcePaddingPpb ( + IN PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ResetAllPpbBusReg ( + IN PCI_IO_DEVICE *Bridge, + IN UINT8 StartBusNumber + ) +/*++ + +Routine Description: + + Reset bus register + +Arguments: + + Bridge - a pointer to the PCI_IO_DEVICE + StartBusNumber - the number of bus + +Returns: + + None + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c new file mode 100644 index 0000000000..a1e16a0eea --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.c @@ -0,0 +1,457 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciRomTable.c + +Abstract: + + Option Rom Support for PCI Bus Driver + +Revision History + +--*/ + +#include "pcibus.h" +#include "PciRomTable.h" + +typedef struct { + EFI_HANDLE ImageHandle; + UINTN Seg; + UINT8 Bus; + UINT8 Dev; + UINT8 Func; + UINT64 RomAddress; + UINT64 RomLength; +} EFI_PCI_ROM_IMAGE_MAPPING; + +static UINTN mNumberOfPciRomImages = 0; +static UINTN mMaxNumberOfPciRomImages = 0; +static EFI_PCI_ROM_IMAGE_MAPPING *mRomImageTable = NULL; + +VOID +PciRomAddImageMapping ( + IN EFI_HANDLE ImageHandle, + IN UINTN Seg, + IN UINT8 Bus, + IN UINT8 Dev, + IN UINT8 Func, + IN UINT64 RomAddress, + IN UINT64 RomLength + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + Seg - TODO: add argument description + Bus - TODO: add argument description + Dev - TODO: add argument description + Func - TODO: add argument description + RomAddress - TODO: add argument description + RomLength - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_PCI_ROM_IMAGE_MAPPING *TempMapping; + + if (mNumberOfPciRomImages >= mMaxNumberOfPciRomImages) { + + mMaxNumberOfPciRomImages += 0x20; + + TempMapping = NULL; + TempMapping = AllocatePool (mMaxNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING)); + if (TempMapping == NULL) { + return ; + } + + CopyMem (TempMapping, mRomImageTable, mNumberOfPciRomImages * sizeof (EFI_PCI_ROM_IMAGE_MAPPING)); + + if (mRomImageTable != NULL) { + gBS->FreePool (mRomImageTable); + } + + mRomImageTable = TempMapping; + } + + mRomImageTable[mNumberOfPciRomImages].ImageHandle = ImageHandle; + mRomImageTable[mNumberOfPciRomImages].Seg = Seg; + mRomImageTable[mNumberOfPciRomImages].Bus = Bus; + mRomImageTable[mNumberOfPciRomImages].Dev = Dev; + mRomImageTable[mNumberOfPciRomImages].Func = Func; + mRomImageTable[mNumberOfPciRomImages].RomAddress = RomAddress; + mRomImageTable[mNumberOfPciRomImages].RomLength = RomLength; + mNumberOfPciRomImages++; +} + +VOID +HexToString ( + CHAR16 *String, + UINTN Value, + UINTN Digits + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + String - TODO: add argument description + Value - TODO: add argument description + Digits - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + for (; Digits > 0; Digits--, String++) { + *String = (CHAR16) ((Value >> (4 * (Digits - 1))) & 0x0f); + if (*String > 9) { + (*String) += ('A' - 10); + } else { + (*String) += '0'; + } + } +} +EFI_STATUS +PciRomLoadEfiDriversFromRomImage ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: PciOptionRomDescriptor - add argument and description to function comment +{ + VOID *RomBar; + UINTN RomSize; + CHAR16 *FileName; + EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader; + PCI_DATA_STRUCTURE *Pcir; + UINTN ImageIndex; + UINTN RomBarOffset; + UINT32 ImageSize; + UINT16 ImageOffset; + EFI_HANDLE ImageHandle; + EFI_STATUS Status; + EFI_STATUS retStatus; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + BOOLEAN SkipImage; + UINT32 DestinationSize; + UINT32 ScratchSize; + UINT8 *Scratch; + VOID *ImageBuffer; + VOID *DecompressedImageBuffer; + UINT32 ImageLength; + EFI_DECOMPRESS_PROTOCOL *Decompress; + + RomBar = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress; + RomSize = (UINTN) PciOptionRomDescriptor->RomLength; + FileName = L"PciRom Seg=00000000 Bus=00 Dev=00 Func=00 Image=0000"; + + HexToString (&FileName[11], PciOptionRomDescriptor->Seg, 8); + HexToString (&FileName[24], PciOptionRomDescriptor->Bus, 2); + HexToString (&FileName[31], PciOptionRomDescriptor->Dev, 2); + HexToString (&FileName[39], PciOptionRomDescriptor->Func, 2); + + ImageIndex = 0; + retStatus = EFI_NOT_FOUND; + RomBarOffset = (UINTN) RomBar; + + do { + + EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset; + + if (EfiRomHeader->Signature != 0xaa55) { + return retStatus; + } + + Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset); + ImageSize = Pcir->ImageLength * 512; + + if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) && + (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) ) { + + if ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) || + (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) ) { + + ImageOffset = EfiRomHeader->EfiImageHeaderOffset; + ImageSize = EfiRomHeader->InitializationSize * 512; + + ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset); + ImageLength = ImageSize - ImageOffset; + DecompressedImageBuffer = NULL; + + // + // decompress here if needed + // + SkipImage = FALSE; + if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { + SkipImage = TRUE; + } + + if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { + Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID **) &Decompress); + if (EFI_ERROR (Status)) { + SkipImage = TRUE; + } else { + SkipImage = TRUE; + Status = Decompress->GetInfo ( + Decompress, + ImageBuffer, + ImageLength, + &DestinationSize, + &ScratchSize + ); + if (!EFI_ERROR (Status)) { + DecompressedImageBuffer = NULL; + DecompressedImageBuffer = AllocatePool (DestinationSize); + if (DecompressedImageBuffer != NULL) { + Scratch = AllocatePool (ScratchSize); + if (Scratch != NULL) { + Status = Decompress->Decompress ( + Decompress, + ImageBuffer, + ImageLength, + DecompressedImageBuffer, + DestinationSize, + Scratch, + ScratchSize + ); + if (!EFI_ERROR (Status)) { + ImageBuffer = DecompressedImageBuffer; + ImageLength = DestinationSize; + SkipImage = FALSE; + } + + gBS->FreePool (Scratch); + } + } + } + } + } + + if (!SkipImage) { + + // + // load image and start image + // + + HexToString (&FileName[48], ImageIndex, 4); + FilePath = FileDevicePath (NULL, FileName); + + Status = gBS->LoadImage ( + FALSE, + This->ImageHandle, + FilePath, + ImageBuffer, + ImageLength, + &ImageHandle + ); + if (!EFI_ERROR (Status)) { + Status = gBS->StartImage (ImageHandle, NULL, NULL); + if (!EFI_ERROR (Status)) { + PciRomAddImageMapping ( + ImageHandle, + PciOptionRomDescriptor->Seg, + PciOptionRomDescriptor->Bus, + PciOptionRomDescriptor->Dev, + PciOptionRomDescriptor->Func, + PciOptionRomDescriptor->RomAddress, + PciOptionRomDescriptor->RomLength + ); + retStatus = Status; + } + } + } + + if (DecompressedImageBuffer != NULL) { + gBS->FreePool (DecompressedImageBuffer); + } + + } + } + + RomBarOffset = RomBarOffset + ImageSize; + ImageIndex++; + } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize)); + + return retStatus; +} + +EFI_STATUS +PciRomLoadEfiDriversFromOptionRomTable ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: PciRootBridgeIo - add argument and description to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + EFI_STATUS Status; + EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable; + EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor; + UINTN Index; + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors; + UINT16 MinBus; + UINT16 MaxBus; + + Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + Status = EFI_NOT_FOUND; + + for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) { + PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index]; + if (!PciOptionRomDescriptor->DontLoadEfiRom) { + if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber) { + Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Descriptors); + if (EFI_ERROR (Status)) { + return Status; + } + + PciGetBusRange (&Descriptors, &MinBus, &MaxBus, NULL); + if ((MinBus <= PciOptionRomDescriptor->Bus) && (PciOptionRomDescriptor->Bus <= MaxBus)) { + Status = PciRomLoadEfiDriversFromRomImage (This, PciOptionRomDescriptor); + PciOptionRomDescriptor->DontLoadEfiRom |= 2; + } + } + } + } + + return Status; +} + +EFI_STATUS +PciRomGetRomResourceFromPciOptionRomTable ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: PciRootBridgeIo - add argument and description to function comment +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_PCI_OPTION_ROM_TABLE *PciOptionRomTable; + EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptor; + UINTN Index; + + Status = EfiGetSystemConfigurationTable (&gEfiPciOptionRomTableGuid, (VOID **) &PciOptionRomTable); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + for (Index = 0; Index < PciOptionRomTable->PciOptionRomCount; Index++) { + PciOptionRomDescriptor = &PciOptionRomTable->PciOptionRomDescriptors[Index]; + if (PciOptionRomDescriptor->Seg == PciRootBridgeIo->SegmentNumber && + PciOptionRomDescriptor->Bus == PciIoDevice->BusNumber && + PciOptionRomDescriptor->Dev == PciIoDevice->DeviceNumber && + PciOptionRomDescriptor->Func == PciIoDevice->FunctionNumber ) { + + PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) PciOptionRomDescriptor->RomAddress; + PciIoDevice->PciIo.RomSize = (UINTN) PciOptionRomDescriptor->RomLength; + } + } + + for (Index = 0; Index < mNumberOfPciRomImages; Index++) { + if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber && + mRomImageTable[Index].Bus == PciIoDevice->BusNumber && + mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber && + mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) { + + AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PciRomGetImageMapping ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +// TODO: PciIoDevice - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + UINTN Index; + + PciRootBridgeIo = PciIoDevice->PciRootBridgeIo; + + for (Index = 0; Index < mNumberOfPciRomImages; Index++) { + if (mRomImageTable[Index].Seg == PciRootBridgeIo->SegmentNumber && + mRomImageTable[Index].Bus == PciIoDevice->BusNumber && + mRomImageTable[Index].Dev == PciIoDevice->DeviceNumber && + mRomImageTable[Index].Func == PciIoDevice->FunctionNumber ) { + + if (mRomImageTable[Index].ImageHandle != NULL) { + AddDriver (PciIoDevice, mRomImageTable[Index].ImageHandle); + } else { + PciIoDevice->PciIo.RomImage = (VOID *) (UINTN) mRomImageTable[Index].RomAddress; + PciIoDevice->PciIo.RomSize = (UINTN) mRomImageTable[Index].RomLength; + } + } + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.h new file mode 100644 index 0000000000..bb20c70156 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/PciRomTable.h @@ -0,0 +1,107 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciRomTable.h + +Abstract: + + Option Rom Support for PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_ROM_TABLE_H +#define _EFI_PCI_ROM_TABLE_H + +VOID +PciRomAddImageMapping ( + IN EFI_HANDLE ImageHandle, + IN UINTN Seg, + IN UINT8 Bus, + IN UINT8 Dev, + IN UINT8 Func, + IN UINT64 RomAddress, + IN UINT64 RomLength + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + Seg - TODO: add argument description + Bus - TODO: add argument description + Dev - TODO: add argument description + Func - TODO: add argument description + RomAddress - TODO: add argument description + RomLength - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + + +EFI_STATUS +PciRomGetRomResourceFromPciOptionRomTable ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo, + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + PciRootBridgeIo - TODO: add argument description + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +PciRomGetImageMapping ( + PCI_IO_DEVICE *PciIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PciIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/build.xml b/EdkModulePkg/Bus/Pci/PciBus/Dxe/build.xml new file mode 100644 index 0000000000..ee051c7231 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/build.xml @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.c b/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.c new file mode 100644 index 0000000000..16a33010e4 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.c @@ -0,0 +1,375 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciBus.c + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#include "PciBus.h" + +// +// PCI Bus Support Function Prototypes +// + +EFI_STATUS +EFIAPI +PciBusEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +PciBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +PciBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +PciBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// PCI Bus Driver Global Variables +// + +EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding = { + PciBusDriverBindingSupported, + PciBusDriverBindingStart, + PciBusDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *gEfiIncompatiblePciDeviceSupport = NULL; +EFI_HANDLE gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM]; +UINTN gPciHostBridgeNumber; +BOOLEAN gFullEnumeration; +UINT64 gAllOne = 0xFFFFFFFFFFFFFFFFULL; +UINT64 gAllZero = 0; + +EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol; + +// +// PCI Bus Driver Support Functions +// +EFI_STATUS +EFIAPI +PciBusEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initialize the global variables + publish the driver binding protocol + +Arguments: + + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + +Returns: + + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +// TODO: ImageHandle - add argument and description to function comment +// TODO: SystemTable - add argument and description to function comment +{ + EFI_STATUS Status; + + InitializePciDevicePool (); + + gFullEnumeration = TRUE; + + gPciHostBridgeNumber = 0; + + InstallHotPlugRequestProtocol (&Status); + return Status; +} + +EFI_STATUS +EFIAPI +PciBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Check to see if pci bus driver supports the given controller + +Arguments: + + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + +Returns: + + EFI_SUCCESS + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_DEV_PATH_PTR Node; + + if (RemainingDevicePath != NULL) { + Node.DevPath = RemainingDevicePath; + if (Node.DevPath->Type != HARDWARE_DEVICE_PATH || + Node.DevPath->SubType != HW_PCI_DP || + DevicePathNodeLength(Node.DevPath) != sizeof(PCI_DEVICE_PATH)) { + return EFI_UNSUPPORTED; + } + } + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + (VOID **) &PciRootBridgeIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Start to management the controller passed in + +Arguments: + + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + +Returns: + + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEfiIncompatiblePciDeviceSupportProtocolGuid, + NULL, + (VOID **) &gEfiIncompatiblePciDeviceSupport + ); + + // + // If PCI Platform protocol is available, get it now. + // If the platform implements this, it must be installed before BDS phase + // + gPciPlatformProtocol = NULL; + gBS->LocateProtocol ( + &gEfiPciPlatformProtocolGuid, + NULL, + (VOID **) &gPciPlatformProtocol + ); + + gFullEnumeration = (BOOLEAN) ((SearchHostBridgeHandle (Controller) ? FALSE : TRUE)); + + // + // Enumerate the entire host bridge + // After enumeration, a database that records all the device information will be created + // + // + Status = PciEnumerator (Controller); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Enable PCI device specified by remaining device path. BDS or other driver can call the + // start more than once. + // + + StartPciDevices (Controller, RemainingDevicePath); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PciBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + Stop one or more children created at start of pci bus driver + if all the the children get closed, close the protocol + +Arguments: + + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + +Returns: + + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: NumberOfChildren - add argument and description to function comment +// TODO: ChildHandleBuffer - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + UINTN Index; + BOOLEAN AllChildrenStopped; + + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiPciRootBridgeIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + DestroyRootBridgeByHandle ( + Controller + ); + + return EFI_SUCCESS; + } + + // + // Stop all the children + // + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + // + // De register all the pci device + // + Status = DeRegisterPciDevice (Controller, ChildHandleBuffer[Index]); + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.h b/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.h new file mode 100644 index 0000000000..170a4e278a --- /dev/null +++ b/EdkModulePkg/Bus/Pci/PciBus/Dxe/pcibus.h @@ -0,0 +1,243 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciBus.h + +Abstract: + + PCI Bus Driver + +Revision History + +--*/ + +#ifndef _EFI_PCI_BUS_H +#define _EFI_PCI_BUS_H + + +#include +#include +#include "ComponentName.h" + +// +// Driver Produced Protocol Prototypes +// + +#define VGABASE1 0x3B0 +#define VGALIMIT1 0x3BB + +#define VGABASE2 0x3C0 +#define VGALIMIT2 0x3DF + +#define ISABASE 0x100 +#define ISALIMIT 0x3FF + +typedef enum { + PciBarTypeUnknown = 0, + PciBarTypeIo16, + PciBarTypeIo32, + PciBarTypeMem32, + PciBarTypePMem32, + PciBarTypeMem64, + PciBarTypePMem64, + PciBarTypeIo, + PciBarTypeMem, + PciBarTypeMaxType +} PCI_BAR_TYPE; + +typedef struct { + UINT64 BaseAddress; + UINT64 Length; + UINT64 Alignment; + PCI_BAR_TYPE BarType; + BOOLEAN Prefetchable; + UINT8 MemType; + UINT8 Offset; +} PCI_BAR; + +#define PPB_BAR_0 0 +#define PPB_BAR_1 1 +#define PPB_IO_RANGE 2 +#define PPB_MEM32_RANGE 3 +#define PPB_PMEM32_RANGE 4 +#define PPB_PMEM64_RANGE 5 +#define PPB_MEM64_RANGE 0xFF + +#define P2C_BAR_0 0 +#define P2C_MEM_1 1 +#define P2C_MEM_2 2 +#define P2C_IO_1 3 +#define P2C_IO_2 4 + +#define PCI_IO_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('p', 'c', 'i', 'o') + +#define EFI_BRIDGE_IO32_DECODE_SUPPORTED 0x0001 +#define EFI_BRIDGE_PMEM32_DECODE_SUPPORTED 0x0002 +#define EFI_BRIDGE_PMEM64_DECODE_SUPPORTED 0x0004 +#define EFI_BRIDGE_IO16_DECODE_SUPPORTED 0x0008 +#define EFI_BRIDGE_PMEM_MEM_COMBINE_SUPPORTED 0x0010 +#define EFI_BRIDGE_MEM64_DECODE_SUPPORTED 0x0020 +#define EFI_BRIDGE_MEM32_DECODE_SUPPORTED 0x0040 + +#define PCI_MAX_HOST_BRIDGE_NUM 0x0010 +// +// Define resource status constant +// +#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL +#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL +#define EFI_RESOURCE_SATISFIED 0x0000000000000000ULL + +// +// Define option for attribute +// +#define EFI_SET_SUPPORTS 0 +#define EFI_SET_ATTRIBUTES 1 + +typedef struct _PCI_IO_DEVICE { + UINT32 Signature; + EFI_HANDLE Handle; + EFI_PCI_IO_PROTOCOL PciIo; + LIST_ENTRY Link; + + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL PciDriverOverride; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + // + // PCI configuration space header type + // + PCI_TYPE00 Pci; + + // + // Bus number, Device number, Function number + // + UINT8 BusNumber; + UINT8 DeviceNumber; + UINT8 FunctionNumber; + + // + // BAR for this PCI Device + // + PCI_BAR PciBar[PCI_MAX_BAR]; + + // + // The bridge device this pci device is subject to + // + struct _PCI_IO_DEVICE *Parent; + + // + // A linked list for children Pci Device if it is bridge device + // + LIST_ENTRY ChildList; + + // + // TURE if the PCI bus driver creates the handle for this PCI device + // + BOOLEAN Registered; + + // + // TRUE if the PCI bus driver successfully allocates the resource required by + // this PCI device + // + BOOLEAN Allocated; + + // + // The attribute this PCI device currently set + // + UINT64 Attributes; + + // + // The attributes this PCI device actually supports + // + UINT64 Supports; + + // + // The resource decode the bridge supports + // + UINT32 Decodes; + + // + // The OptionRom Size + // + UINT64 RomSize; + + // + // The OptionRom Size + // + UINT64 RomBase; + + // + // TRUE if all OpROM (in device or in platform specific position) have been processed + // + BOOLEAN AllOpRomProcessed; + + // + // TRUE if there is any EFI driver in the OptionRom + // + BOOLEAN BusOverride; + + // + // A list tracking reserved resource on a bridge device + // + LIST_ENTRY ReservedResourceList; + + // + // A list tracking image handle of platform specific overriding driver + // + LIST_ENTRY OptionRomDriverList; + + EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *ResourcePaddingDescriptors; + EFI_HPC_PADDING_ATTRIBUTES PaddingAttributes; + + BOOLEAN IsPciExp; + +} PCI_IO_DEVICE; + + +#define PCI_IO_DEVICE_FROM_PCI_IO_THIS(a) \ + CR (a, PCI_IO_DEVICE, PciIo, PCI_IO_DEVICE_SIGNATURE) + +#define PCI_IO_DEVICE_FROM_PCI_DRIVER_OVERRIDE_THIS(a) \ + CR (a, PCI_IO_DEVICE, PciDriverOverride, PCI_IO_DEVICE_SIGNATURE) + +#define PCI_IO_DEVICE_FROM_LINK(a) \ + CR (a, PCI_IO_DEVICE, Link, PCI_IO_DEVICE_SIGNATURE) + +// +// Global Variables +// +extern EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *gEfiIncompatiblePciDeviceSupport; +extern EFI_DRIVER_BINDING_PROTOCOL gPciBusDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gPciBusComponentName; +extern LIST_ENTRY gPciDevicePool; +extern BOOLEAN gFullEnumeration; +extern UINTN gPciHostBridgeNumber; +extern EFI_HANDLE gPciHostBrigeHandles[PCI_MAX_HOST_BRIDGE_NUM]; +extern UINT64 gAllOne; +extern UINT64 gAllZero; + +extern EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol; + +#include "PciIo.h" +#include "PciCommand.h" +#include "PciDeviceSupport.h" +#include "PciEnumerator.h" +#include "PciEnumeratorSupport.h" +#include "PciDriverOverride.h" +#include "PciRomTable.h" +#include "PciOptionRomSupport.h" +#include "PciPowerManagement.h" +#include "PciHotPlugSupport.h" +#include "PciLib.h" + +#endif diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/ComponentName.c b/EdkModulePkg/Bus/Pci/Uhci/Dxe/ComponentName.c new file mode 100644 index 0000000000..71d9339a8f --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/ComponentName.c @@ -0,0 +1,189 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "uhci.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +UhciComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UhciComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, OPTIONAL + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gUhciComponentName = { + UhciComponentNameGetDriverName, + UhciComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mUhciDriverNameTable[] = { + { "eng", (CHAR16 *) L"Usb Uhci Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +UhciComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gUhciComponentName.SupportedLanguages, + mUhciDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +UhciComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, OPTIONAL + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + USB_HC_DEV *UhciDev; + EFI_USB_HC_PROTOCOL *UsbHc; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbHcProtocolGuid, + (VOID **) &UsbHc, + gUhciDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + UhciDev = USB_HC_DEV_FROM_THIS (UsbHc); + + return LookupUnicodeString ( + Language, + gUhciComponentName.SupportedLanguages, + UhciDev->ControllerNameTable, + ControllerName + ); + +} diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.mbd b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.mbd new file mode 100644 index 0000000000..76d35e7455 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.mbd @@ -0,0 +1,42 @@ + + + + + Uhci + 2FB92EFA-2EE0-4bae-9EB6-7464125E1EF7 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa new file mode 100644 index 0000000000..9e91154fc0 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/Uhci.msa @@ -0,0 +1,66 @@ + + + + + Uhci + UEFI_DRIVER + BS_DRIVER + 2FB92EFA-2EE0-4bae-9EB6-7464125E1EF7 + 0 + Component description file for Uhci module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + uhci.c + uhchlp.c + ComponentName.c + uhci.h + + + MdePkg + + + PciIo + UsbHc + + + + + + + gUhciDriverBinding + gUhciComponentName + + + diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/build.xml b/EdkModulePkg/Bus/Pci/Uhci/Dxe/build.xml new file mode 100644 index 0000000000..37bb3c32e6 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c new file mode 100644 index 0000000000..62d58eed78 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhchlp.c @@ -0,0 +1,4237 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + UhcHlp.c + +Abstract: + + +Revision History +--*/ + +#include "uhci.h" + +EFI_STATUS +USBReadPortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 PortOffset, + IN OUT UINT16 *Data + ) +/*++ + +Routine Description: + + USBReadPort Word + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + PortOffset - Port offset + Data - Data to reutrn + +Returns: + + EFI_SUCCESS + +--*/ +{ + // + // Perform 16bit Read in PCI IO Space + // + return PciIo->Io.Read ( + PciIo, + EfiPciIoWidthUint16, + USB_BAR_INDEX, + (UINT64) PortOffset, + 1, + Data + ); +} + +EFI_STATUS +USBReadPortDW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 PortOffset, + IN OUT UINT32 *Data + ) +/*++ + +Routine Description: + + USBReadPort DWord + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + PortOffset - Port offset + Data - Data to reutrn + +Returns: + + EFI_SUCCESS + +--*/ +{ + // + // Perform 32bit Read in PCI IO Space + // + return PciIo->Io.Read ( + PciIo, + EfiPciIoWidthUint32, + USB_BAR_INDEX, + (UINT64) PortOffset, + 1, + Data + ); +} + +EFI_STATUS +USBWritePortW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 PortOffset, + IN UINT16 Data + ) +/*++ + +Routine Description: + + USB Write Port Word + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + PortOffset - Port offset + Data - Data to write + +Returns: + + EFI_SUCCESS + +--*/ +{ + // + // Perform 16bit Write in PCI IO Space + // + return PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint16, + USB_BAR_INDEX, + (UINT64) PortOffset, + 1, + &Data + ); +} + +EFI_STATUS +USBWritePortDW ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 PortOffset, + IN UINT32 Data + ) +/*++ + +Routine Description: + + USB Write Port DWord + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + PortOffset - Port offset + Data - Data to write + +Returns: + + EFI_SUCCESS + +--*/ +{ + // + // Perform 32bit Write in PCI IO Space + // + return PciIo->Io.Write ( + PciIo, + EfiPciIoWidthUint32, + USB_BAR_INDEX, + (UINT64) PortOffset, + 1, + &Data + ); +} +// +// USB register-base helper functions +// +EFI_STATUS +WriteUHCCommandReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 CmdAddrOffset, + IN UINT16 UsbCmd + ) +/*++ + +Routine Description: + + Write UHCI Command Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + CmdAddrOffset - Command address offset + UsbCmd - Data to write + +Returns: + + EFI_SUCCESS + +--*/ +{ + // + // Write to UHC's Command Register + // + return USBWritePortW (PciIo, CmdAddrOffset, UsbCmd); +} + +EFI_STATUS +ReadUHCCommandReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 CmdAddrOffset, + IN OUT UINT16 *Data + ) +/*++ + +Routine Description: + + Read UHCI Command Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + CmdAddrOffset - Command address offset + Data - Data to return + +Returns: + + EFI_SUCCESS + +--*/ +{ + // + // Read from UHC's Command Register + // + return USBReadPortW (PciIo, CmdAddrOffset, Data); +} + +EFI_STATUS +WriteUHCStatusReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusAddrOffset, + IN UINT16 UsbSts + ) +/*++ + +Routine Description: + + Write UHCI Staus Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusAddrOffset - Status address offset + UsbSts - Data to write + +Returns: + + EFI_SUCCESS + +--*/ +{ + // + // Write to UHC's Status Register + // + return USBWritePortW (PciIo, StatusAddrOffset, UsbSts); +} + +EFI_STATUS +ReadUHCStatusReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusAddrOffset, + IN OUT UINT16 *Data + ) +/*++ + +Routine Description: + + Read UHCI Staus Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusAddrOffset - Status address offset + UsbSts - Data to return + +Returns: + + EFI_SUCCESS + +--*/ +{ + // + // Read from UHC's Status Register + // + return USBReadPortW (PciIo, StatusAddrOffset, Data); +} + + +EFI_STATUS +ClearStatusReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusAddrOffset + ) +/*++ + +Routine Description: + + Clear the content of UHC's Status Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusAddrOffset - Status address offset + +Returns: + + EFI_SUCCESS + +--*/ +{ + + return WriteUHCStatusReg (PciIo, StatusAddrOffset, 0x003F); +} + +EFI_STATUS +ReadUHCFrameNumberReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 FrameNumAddrOffset, + IN OUT UINT16 *Data + ) +/*++ + +Routine Description: + + Read from UHC's Frame Number Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + FrameNumAddrOffset - Frame number register offset + Data - Data to return +Returns: + + EFI_SUCCESS + +--*/ +{ + + return USBReadPortW (PciIo, FrameNumAddrOffset, Data); +} + +EFI_STATUS +WriteUHCFrameListBaseReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 FlBaseAddrOffset, + IN UINT32 UsbFrameListBaseAddr + ) +/*++ + +Routine Description: + + Write to UHC's Frame List Base Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + FlBaseAddrOffset - Frame Base address register + UsbFrameListBaseAddr - Address to write + +Returns: + + EFI_SUCCESS + +--*/ +{ + + return USBWritePortDW (PciIo, FlBaseAddrOffset, UsbFrameListBaseAddr); +} + +EFI_STATUS +ReadRootPortReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 PortAddrOffset, + IN OUT UINT16 *Data + ) +/*++ + +Routine Description: + + Read from UHC's Root Port Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + PortAddrOffset - Port Addrress Offset, + Data - Data to return +Returns: + + EFI_SUCCESS + +--*/ +{ + + return USBReadPortW (PciIo, PortAddrOffset, Data); +} + +EFI_STATUS +WriteRootPortReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 PortAddrOffset, + IN UINT16 ControlBits + ) +/*++ + +Routine Description: + + Write to UHC's Root Port Register + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + PortAddrOffset - Port Addrress Offset, + ControlBits - Data to write +Returns: + + EFI_SUCCESS + +--*/ +{ + + return USBWritePortW (PciIo, PortAddrOffset, ControlBits); +} + + + +EFI_STATUS +WaitForUHCHalt ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusRegAddr, + IN UINTN Timeout + ) +/*++ + +Routine Description: + + Wait until UHCI halt or timeout + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusRegAddr - Status Register Address + Timeout - Time out value in us + +Returns: + + EFI_DEVICE_ERROR - Unable to read the status register + EFI_TIMEOUT - Time out + EFI_SUCCESS - Success + +--*/ +{ + UINTN Delay; + EFI_STATUS Status; + UINT16 HcStatus; + + // + // Timeout is in us unit + // + Delay = (Timeout / 50) + 1; + do { + Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if ((HcStatus & USBSTS_HCH) == USBSTS_HCH) { + break; + } + // + // Stall for 50 us + // + gBS->Stall (50); + + } while (Delay--); + + if (Delay == 0) { + return EFI_TIMEOUT; + } + + return EFI_SUCCESS; +} + +BOOLEAN +IsStatusOK ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusRegAddr + ) +/*++ + +Routine Description: + + Judge whether the host controller operates well + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusRegAddr - Status register address + +Returns: + + TRUE - Status is good + FALSE - Status is bad + +--*/ +{ + EFI_STATUS Status; + UINT16 HcStatus; + // + // Detect whether the interrupt is caused by fatal error. + // see "UHCI Design Guid". + // + Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus); + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (HcStatus & (USBSTS_HCPE | USBSTS_HSE | USBSTS_HCH)) { + return FALSE; + } else { + return TRUE; + } + +} + + +BOOLEAN +IsHostSysOrProcessErr ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusRegAddr + ) +/*++ + +Routine Description: + + Judge the status is HostSys,ProcessErr error or good + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + StatusRegAddr - Status register address + +Returns: + + TRUE - Status is good + FALSE - Status is bad + +--*/ +{ + EFI_STATUS Status; + UINT16 HcStatus; + // + // Detect whether the interrupt is caused by serious error. + // see "UHCI Design Guid". + // + Status = ReadUHCStatusReg (PciIo, StatusRegAddr, &HcStatus); + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (HcStatus & (USBSTS_HSE | USBSTS_HCPE)) { + return TRUE; + } else { + return FALSE; + } +} + + +UINT16 +GetCurrentFrameNumber ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 FrameNumAddrOffset + ) +/*++ + +Routine Description: + + Get Current Frame Number + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + FrameNumAddrOffset - FrameNum register AddrOffset + +Returns: + + Frame number + +--*/ +{ + // + // Gets value in the USB frame number register. + // + UINT16 FrameNumber; + + ReadUHCFrameNumberReg (PciIo, FrameNumAddrOffset, &FrameNumber); + + return (UINT16) (FrameNumber & 0x03FF); +} + +EFI_STATUS +SetFrameListBaseAddress ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 FlBaseAddrReg, + IN UINT32 Addr + ) +/*++ + +Routine Description: + + Set FrameListBase Address + +Arguments: + + PciIo - EFI_PCI_IO_PROTOCOL + FlBaseAddrReg - FrameListBase register + Addr - Address to set + +Returns: + + EFI_SUCCESS + +--*/ +{ + // + // Sets value in the USB Frame List Base Address register. + // + return WriteUHCFrameListBaseReg (PciIo, FlBaseAddrReg, (UINT32) (Addr & 0xFFFFF000)); +} + +VOID +EnableMaxPacketSize ( + IN USB_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Enable Max Packet Size + +Arguments: + + HcDev - USB_HC_DEV + +Returns: + + VOID + +--*/ +{ + UINT16 CommandContent; + EFI_STATUS Status; + + Status = ReadUHCCommandReg ( + HcDev->PciIo, + (UINT32) (USBCMD), + &CommandContent + ); + + if ((CommandContent & USBCMD_MAXP) != USBCMD_MAXP) { + CommandContent |= USBCMD_MAXP; + WriteUHCCommandReg ( + HcDev->PciIo, + (UINT32) (USBCMD), + CommandContent + ); + } + + return ; +} + +EFI_STATUS +CreateFrameList ( + IN USB_HC_DEV *HcDev, + IN UINT32 FlBaseAddrReg + ) +/*++ + +Routine Description: + + CreateFrameList + +Arguments: + + HcDev - USB_HC_DEV + FlBaseAddrReg - Frame List register + +Returns: + + EFI_OUT_OF_RESOURCES - Can't allocate memory resources + EFI_UNSUPPORTED - Map memory fail + EFI_SUCCESS - Success + +--*/ +{ + EFI_STATUS Status; + VOID *CommonBuffer; + EFI_PHYSICAL_ADDRESS MappedAddress; + VOID *Mapping; + UINTN BufferSizeInPages; + UINTN BufferSizeInBytes; + + // + // The Frame List is a common buffer that will be + // accessed by both the cpu and the usb bus master + // at the same time. + // The Frame List ocupies 4K bytes, + // and must be aligned on 4-Kbyte boundaries. + // + BufferSizeInBytes = 4096; + BufferSizeInPages = EFI_SIZE_TO_PAGES (BufferSizeInBytes); + Status = HcDev->PciIo->AllocateBuffer ( + HcDev->PciIo, + AllocateAnyPages, + EfiBootServicesData, + BufferSizeInPages, + &CommonBuffer, + 0 + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterCommonBuffer, + CommonBuffer, + &BufferSizeInBytes, + &MappedAddress, + &Mapping + ); + if (EFI_ERROR (Status) || (BufferSizeInBytes != 4096)) { + HcDev->PciIo->FreeBuffer (HcDev->PciIo, BufferSizeInPages, CommonBuffer); + return EFI_UNSUPPORTED; + } + + HcDev->FrameListEntry = (FRAMELIST_ENTRY *) ((UINTN) MappedAddress); + + HcDev->FrameListMapping = Mapping; + + InitFrameList (HcDev); + + // + // Tell the Host Controller where the Frame List lies, + // by set the Frame List Base Address Register. + // + SetFrameListBaseAddress ( + HcDev->PciIo, + FlBaseAddrReg, + (UINT32) ((UINTN) HcDev->FrameListEntry) + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +FreeFrameListEntry ( + IN USB_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Free FrameList buffer + +Arguments: + + HcDev - USB_HC_DEV + +Returns: + + EFI_SUCCESS - success + +--*/ +{ + // + // Unmap the common buffer for framelist entry, + // and free the common buffer. + // Uhci's frame list occupy 4k memory. + // + HcDev->PciIo->Unmap (HcDev->PciIo, HcDev->FrameListMapping); + HcDev->PciIo->FreeBuffer ( + HcDev->PciIo, + EFI_SIZE_TO_PAGES (4096), + (VOID *) (HcDev->FrameListEntry) + ); + return EFI_SUCCESS; +} + +VOID +InitFrameList ( + IN USB_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Initialize FrameList + +Arguments: + + HcDev - USB_HC_DEV + +Returns: + VOID + +--*/ +{ + FRAMELIST_ENTRY *FrameListPtr; + UINTN Index; + + // + // Validate each Frame List Entry + // + FrameListPtr = HcDev->FrameListEntry; + for (Index = 0; Index < 1024; Index++) { + FrameListPtr->FrameListPtrTerminate = 1; + FrameListPtr->FrameListPtr = 0; + FrameListPtr->FrameListPtrQSelect = 0; + FrameListPtr->FrameListRsvd = 0; + FrameListPtr++; + } +} +// +// ////////////////////////////////////////////////////////////// +// +// QH TD related Helper Functions +// +//////////////////////////////////////////////////////////////// +// +// functions for QH +// +EFI_STATUS +AllocateQHStruct ( + IN USB_HC_DEV *HcDev, + OUT QH_STRUCT **ppQHStruct + ) +/*++ + +Routine Description: + + Allocate QH Struct + +Arguments: + + HcDev - USB_HC_DEV + ppQHStruct - QH_STRUCT content to return +Returns: + + EFI_SUCCESS + +--*/ +{ + *ppQHStruct = NULL; + + // + // QH must align on 16 bytes alignment, + // since the memory allocated by UhciAllocatePool () + // is aligned on 32 bytes, it is no need to adjust + // the allocated memory returned. + // + return UhciAllocatePool (HcDev, (UINT8 **) ppQHStruct, sizeof (QH_STRUCT)); +} + + +EFI_STATUS +CreateQH ( + IN USB_HC_DEV *HcDev, + OUT QH_STRUCT **pptrQH + ) +/*++ + +Routine Description: + + CreateQH + +Arguments: + + HcDev - USB_HC_DEV + ppQHStruct - QH_STRUCT content to return +Returns: + + EFI_SUCCESS - Success + EFI_OUT_OF_RESOURCES - Can't allocate memory +--*/ +{ + EFI_STATUS Status; + + // + // allocate align memory for QH_STRUCT + // + Status = AllocateQHStruct (HcDev, pptrQH); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // init each field of the QH_STRUCT + // + // + // Make QH ready + // + SetQHHorizontalValidorInvalid (*pptrQH, FALSE); + SetQHVerticalValidorInvalid (*pptrQH, FALSE); + + return EFI_SUCCESS; +} + +VOID +SetQHHorizontalLinkPtr ( + IN QH_STRUCT *PtrQH, + IN VOID *ptrNext + ) +/*++ + +Routine Description: + + Set QH Horizontal Link Pointer + +Arguments: + + PtrQH - QH_STRUCT + ptrNext - Data to write + +Returns: + + VOID + +--*/ +{ + // + // Since the QH_STRUCT is aligned on 16-byte boundaries, + // Only the highest 28bit of the address is valid + // (take 32bit address as an example). + // + PtrQH->QH.QHHorizontalPtr = (UINT32) ((UINTN) ptrNext >> 4); +} + +VOID * +GetQHHorizontalLinkPtr ( + IN QH_STRUCT *PtrQH + ) +/*++ + +Routine Description: + + Get QH Horizontal Link Pointer + +Arguments: + + PtrQH - QH_STRUCT + + +Returns: + + Data to return + +--*/ +{ + // + // Restore the 28bit address to 32bit address + // (take 32bit address as an example) + // + return (VOID *) ((UINTN) (PtrQH->QH.QHHorizontalPtr << 4)); +} + +VOID +SetQHHorizontalQHorTDSelect ( + IN QH_STRUCT *PtrQH, + IN BOOLEAN bQH + ) +/*++ + +Routine Description: + + Set QH Horizontal QH or TD + +Arguments: + + PtrQH - QH_STRUCT + bQH - TRUE is QH FALSE is TD + +Returns: + VOID + +--*/ +{ + // + // if QH is connected, the specified bit is set, + // if TD is connected, the specified bit is cleared. + // + PtrQH->QH.QHHorizontalQSelect = bQH ? 1 : 0; +} + + +VOID +SetQHHorizontalValidorInvalid ( + IN QH_STRUCT *PtrQH, + IN BOOLEAN bValid + ) +/*++ + +Routine Description: + + Set QH Horizontal Valid or Invalid + +Arguments: + + PtrQH - QH_STRUCT + bValid - TRUE is Valid FALSE is Invalid + +Returns: + VOID + +--*/ +{ + // + // Valid means the horizontal link pointer is valid, + // else, it's invalid. + // + PtrQH->QH.QHHorizontalTerminate = bValid ? 0 : 1; +} + +VOID +SetQHVerticalLinkPtr ( + IN QH_STRUCT *PtrQH, + IN VOID *ptrNext + ) +/*++ + +Routine Description: + + Set QH Vertical Link Pointer + +Arguments: + + PtrQH - QH_STRUCT + ptrNext - Data to write +Returns: + + VOID + +--*/ +{ + // + // Since the QH_STRUCT is aligned on 16-byte boundaries, + // Only the highest 28bit of the address is valid + // (take 32bit address as an example). + // + PtrQH->QH.QHVerticalPtr = (UINT32) ((UINTN) ptrNext >> 4); +} + +VOID * +GetQHVerticalLinkPtr ( + IN QH_STRUCT *PtrQH + ) +/*++ + +Routine Description: + + Get QH Vertical Link Pointer + +Arguments: + + PtrQH - QH_STRUCT + +Returns: + + Data to return + +--*/ +{ + // + // Restore the 28bit address to 32bit address + // (take 32bit address as an example) + // + return (VOID *) ((UINTN) (PtrQH->QH.QHVerticalPtr << 4)); +} + +VOID +SetQHVerticalQHorTDSelect ( + IN QH_STRUCT *PtrQH, + IN BOOLEAN bQH + ) +/*++ + +Routine Description: + + Set QH Vertical QH or TD + +Arguments: + + PtrQH - QH_STRUCT + bQH - TRUE is QH FALSE is TD + +Returns: + + VOID + +--*/ +{ + // + // Set the specified bit if the Vertical Link Pointer pointing to a QH, + // Clear the specified bit if the Vertical Link Pointer pointing to a TD. + // + PtrQH->QH.QHVerticalQSelect = bQH ? 1 : 0; +} + +BOOLEAN +IsQHHorizontalQHSelect ( + IN QH_STRUCT *PtrQH + ) +/*++ + +Routine Description: + + Is QH Horizontal QH Select + +Arguments: + + PtrQH - QH_STRUCT + +Returns: + + TRUE - QH + FALSE - TD + +--*/ +{ + // + // Retrieve the information about whether the Horizontal Link Pointer + // pointing to a QH or TD. + // + return (BOOLEAN) (PtrQH->QH.QHHorizontalQSelect ? TRUE : FALSE); +} + +VOID +SetQHVerticalValidorInvalid ( + IN QH_STRUCT *PtrQH, + IN BOOLEAN IsValid + ) +/*++ + +Routine Description: + + Set QH Vertical Valid or Invalid + +Arguments: + + PtrQH - QH_STRUCT + IsValid - TRUE is valid FALSE is invalid + +Returns: + + VOID + +--*/ +{ + // + // If TRUE, indicates the Vertical Link Pointer field is valid, + // else, the field is invalid. + // + PtrQH->QH.QHVerticalTerminate = IsValid ? 0 : 1; +} + + +BOOLEAN +GetQHVerticalValidorInvalid ( + IN QH_STRUCT *PtrQH + ) +/*++ + +Routine Description: + + Get QH Vertical Valid or Invalid + +Arguments: + + PtrQH - QH_STRUCT + +Returns: + + TRUE - Valid + FALSE - Invalid + +--*/ +{ + // + // If TRUE, indicates the Vertical Link Pointer field is valid, + // else, the field is invalid. + // + return (BOOLEAN) (!(PtrQH->QH.QHVerticalTerminate)); +} + +BOOLEAN +GetQHHorizontalValidorInvalid ( + IN QH_STRUCT *PtrQH + ) +/*++ + +Routine Description: + + Get QH Horizontal Valid or Invalid + +Arguments: + + PtrQH - QH_STRUCT + +Returns: + + TRUE - Valid + FALSE - Invalid + +--*/ +{ + // + // If TRUE, meaning the Horizontal Link Pointer field is valid, + // else, the field is invalid. + // + return (BOOLEAN) (!(PtrQH->QH.QHHorizontalTerminate)); +} +// +// functions for TD +// +EFI_STATUS +AllocateTDStruct ( + IN USB_HC_DEV *HcDev, + OUT TD_STRUCT **ppTDStruct + ) +/*++ + +Routine Description: + + Allocate TD Struct + +Arguments: + + HcDev - USB_HC_DEV + ppTDStruct - place to store TD_STRUCT pointer +Returns: + + EFI_SUCCESS + +--*/ +{ + *ppTDStruct = NULL; + + // + // TD must align on 16 bytes alignment, + // since the memory allocated by UhciAllocatePool () + // is aligned on 32 bytes, it is no need to adjust + // the allocated memory returned. + // + return UhciAllocatePool ( + HcDev, + (UINT8 **) ppTDStruct, + sizeof (TD_STRUCT) + ); +} + +EFI_STATUS +CreateTD ( + IN USB_HC_DEV *HcDev, + OUT TD_STRUCT **pptrTD + ) +/*++ + +Routine Description: + + Create TD + +Arguments: + + HcDev - USB_HC_DEV + pptrTD - TD_STRUCT pointer to store + +Returns: + + EFI_OUT_OF_RESOURCES - Can't allocate resources + EFI_SUCCESS - Success + +--*/ +{ + EFI_STATUS Status; + // + // create memory for TD_STRUCT, and align the memory. + // + Status = AllocateTDStruct (HcDev, pptrTD); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Make TD ready. + // + SetTDLinkPtrValidorInvalid (*pptrTD, FALSE); + + + return EFI_SUCCESS; +} + +EFI_STATUS +GenSetupStageTD ( + IN USB_HC_DEV *HcDev, + IN UINT8 DevAddr, + IN UINT8 Endpoint, + IN BOOLEAN bSlow, + IN UINT8 *pDevReq, + IN UINT8 RequestLen, + OUT TD_STRUCT **ppTD + ) +/*++ + +Routine Description: + + Generate Setup Stage TD + +Arguments: + + HcDev - USB_HC_DEV + DevAddr - Device address + Endpoint - Endpoint number + bSlow - Full speed or low speed + pDevReq - Device request + RequestLen - Request length + ppTD - TD_STRUCT to return +Returns: + + EFI_OUT_OF_RESOURCES - Can't allocate memory + EFI_SUCCESS - Success + +--*/ +{ + EFI_STATUS Status; + TD_STRUCT *pTDStruct; + + Status = CreateTD (HcDev, &pTDStruct); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + SetTDLinkPtr (pTDStruct, NULL); + + // + // Depth first fashion + // + SetTDLinkPtrDepthorBreadth (pTDStruct, TRUE); + + // + // initialize as the last TD in the QH context, + // this field will be updated in the TD linkage process. + // + SetTDLinkPtrValidorInvalid (pTDStruct, FALSE); + + // + // Disable Short Packet Detection by default + // + EnableorDisableTDShortPacket (pTDStruct, FALSE); + + // + // Max error counter is 3, retry 3 times when error encountered. + // + SetTDControlErrorCounter (pTDStruct, 3); + + // + // set device speed attribute + // (TRUE - Slow Device; FALSE - Full Speed Device) + // + SetTDLoworFullSpeedDevice (pTDStruct, bSlow); + + // + // Non isochronous transfer TD + // + SetTDControlIsochronousorNot (pTDStruct, FALSE); + + // + // Interrupt On Complete bit be set to zero, + // Disable IOC interrupt. + // + SetorClearTDControlIOC (pTDStruct, FALSE); + + // + // Set TD Active bit + // + SetTDStatusActiveorInactive (pTDStruct, TRUE); + + SetTDTokenMaxLength (pTDStruct, RequestLen); + + SetTDTokenDataToggle0 (pTDStruct); + + SetTDTokenEndPoint (pTDStruct, Endpoint); + + SetTDTokenDeviceAddress (pTDStruct, DevAddr); + + SetTDTokenPacketID (pTDStruct, SETUP_PACKET_ID); + + pTDStruct->pTDBuffer = (UINT8 *) pDevReq; + pTDStruct->TDBufferLength = RequestLen; + SetTDDataBuffer (pTDStruct); + + *ppTD = pTDStruct; + + return EFI_SUCCESS; +} + +EFI_STATUS +GenDataTD ( + IN USB_HC_DEV *HcDev, + IN UINT8 DevAddr, + IN UINT8 Endpoint, + IN UINT8 *pData, + IN UINT8 Len, + IN UINT8 PktID, + IN UINT8 Toggle, + IN BOOLEAN bSlow, + OUT TD_STRUCT **ppTD + ) +/*++ + +Routine Description: + + Generate Data Stage TD + +Arguments: + + HcDev - USB_HC_DEV + DevAddr - Device address + Endpoint - Endpoint number + pData - Data buffer + Len - Data length + PktID - Packet ID + Toggle - Data toggle value + bSlow - Full speed or low speed + ppTD - TD_STRUCT to return +Returns: + + EFI_OUT_OF_RESOURCES - Can't allocate memory + EFI_SUCCESS - Success + +--*/ +{ + TD_STRUCT *pTDStruct; + EFI_STATUS Status; + + Status = CreateTD (HcDev, &pTDStruct); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + SetTDLinkPtr (pTDStruct, NULL); + + // + // Depth first fashion + // + SetTDLinkPtrDepthorBreadth (pTDStruct, TRUE); + + // + // Link pointer pointing to TD struct + // + SetTDLinkPtrQHorTDSelect (pTDStruct, FALSE); + + // + // initialize as the last TD in the QH context, + // this field will be updated in the TD linkage process. + // + SetTDLinkPtrValidorInvalid (pTDStruct, FALSE); + + // + // Disable short packet detect + // + EnableorDisableTDShortPacket (pTDStruct, FALSE); + // + // Max error counter is 3 + // + SetTDControlErrorCounter (pTDStruct, 3); + + // + // set device speed attribute + // (TRUE - Slow Device; FALSE - Full Speed Device) + // + SetTDLoworFullSpeedDevice (pTDStruct, bSlow); + + // + // Non isochronous transfer TD + // + SetTDControlIsochronousorNot (pTDStruct, FALSE); + + // + // Disable Interrupt On Complete + // Disable IOC interrupt. + // + SetorClearTDControlIOC (pTDStruct, FALSE); + + // + // Set Active bit + // + SetTDStatusActiveorInactive (pTDStruct, TRUE); + + SetTDTokenMaxLength (pTDStruct, Len); + + if (Toggle) { + SetTDTokenDataToggle1 (pTDStruct); + } else { + SetTDTokenDataToggle0 (pTDStruct); + } + + SetTDTokenEndPoint (pTDStruct, Endpoint); + + SetTDTokenDeviceAddress (pTDStruct, DevAddr); + + SetTDTokenPacketID (pTDStruct, PktID); + + pTDStruct->pTDBuffer = (UINT8 *) pData; + pTDStruct->TDBufferLength = Len; + SetTDDataBuffer (pTDStruct); + *ppTD = pTDStruct; + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateStatusTD ( + IN USB_HC_DEV *HcDev, + IN UINT8 DevAddr, + IN UINT8 Endpoint, + IN UINT8 PktID, + IN BOOLEAN bSlow, + OUT TD_STRUCT **ppTD + ) +/*++ + +Routine Description: + + Generate Status Stage TD + +Arguments: + + HcDev - USB_HC_DEV + DevAddr - Device address + Endpoint - Endpoint number + PktID - Packet ID + bSlow - Full speed or low speed + ppTD - TD_STRUCT to return +Returns: + + EFI_OUT_OF_RESOURCES - Can't allocate memory + EFI_SUCCESS - Success + +--*/ +{ + TD_STRUCT *ptrTDStruct; + EFI_STATUS Status; + + Status = CreateTD (HcDev, &ptrTDStruct); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + SetTDLinkPtr (ptrTDStruct, NULL); + + // + // Depth first fashion + // + SetTDLinkPtrDepthorBreadth (ptrTDStruct, TRUE); + + // + // initialize as the last TD in the QH context, + // this field will be updated in the TD linkage process. + // + SetTDLinkPtrValidorInvalid (ptrTDStruct, FALSE); + + // + // Disable short packet detect + // + EnableorDisableTDShortPacket (ptrTDStruct, FALSE); + + // + // Max error counter is 3 + // + SetTDControlErrorCounter (ptrTDStruct, 3); + + // + // set device speed attribute + // (TRUE - Slow Device; FALSE - Full Speed Device) + // + SetTDLoworFullSpeedDevice (ptrTDStruct, bSlow); + + // + // Non isochronous transfer TD + // + SetTDControlIsochronousorNot (ptrTDStruct, FALSE); + + // + // Disable Interrupt On Complete + // Disable IOC interrupt. + // + SetorClearTDControlIOC (ptrTDStruct, FALSE); + + // + // Set TD Active bit + // + SetTDStatusActiveorInactive (ptrTDStruct, TRUE); + + SetTDTokenMaxLength (ptrTDStruct, 0); + + SetTDTokenDataToggle1 (ptrTDStruct); + + SetTDTokenEndPoint (ptrTDStruct, Endpoint); + + SetTDTokenDeviceAddress (ptrTDStruct, DevAddr); + + SetTDTokenPacketID (ptrTDStruct, PktID); + + ptrTDStruct->pTDBuffer = NULL; + ptrTDStruct->TDBufferLength = 0; + SetTDDataBuffer (ptrTDStruct); + + *ppTD = ptrTDStruct; + + return EFI_SUCCESS; +} + + +VOID +SetTDLinkPtrValidorInvalid ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bValid + ) +/*++ + +Routine Description: + + Set TD Link Pointer Valid or Invalid + +Arguments: + + ptrTDStruct - TD_STRUCT + bValid - TRUE is valid FALSE is invalid + +Returns: + + VOID + +--*/ +{ + // + // Valid means the link pointer is valid, + // else, it's invalid. + // + ptrTDStruct->TDData.TDLinkPtrTerminate = (bValid ? 0 : 1); +} + +VOID +SetTDLinkPtrQHorTDSelect ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bQH + ) +/*++ + +Routine Description: + + Set TD Link Pointer QH or TD Select + +Arguments: + + ptrTDStruct - TD_STRUCT + bQH - TRUE is QH FALSE is TD + +Returns: + + VOID + +--*/ +{ + // + // Indicate whether the Link Pointer pointing to a QH or TD + // + ptrTDStruct->TDData.TDLinkPtrQSelect = (bQH ? 1 : 0); +} + +VOID +SetTDLinkPtrDepthorBreadth ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bDepth + ) +/*++ + +Routine Description: + + Set TD Link Pointer depth or bread priority + +Arguments: + + ptrTDStruct - TD_STRUCT + bDepth - TRUE is Depth FALSE is Breadth + +Returns: + + VOID + +--*/ +{ + // + // If TRUE, indicating the host controller should process in depth first + // fashion, + // else, the host controller should process in breadth first fashion + // + ptrTDStruct->TDData.TDLinkPtrDepthSelect = (bDepth ? 1 : 0); +} + +VOID +SetTDLinkPtr ( + IN TD_STRUCT *ptrTDStruct, + IN VOID *ptrNext + ) +/*++ + +Routine Description: + + Set TD Link Pointer + +Arguments: + + ptrTDStruct - TD_STRUCT + ptrNext - Pointer to set + +Returns: + + VOID + +--*/ +{ + // + // Set TD Link Pointer. Since QH,TD align on 16-byte boundaries, + // only the highest 28 bits are valid. (if take 32bit address as an example) + // + ptrTDStruct->TDData.TDLinkPtr = (UINT32) ((UINTN) ptrNext >> 4); +} + +VOID * +GetTDLinkPtr ( + IN TD_STRUCT *ptrTDStruct + ) +/*++ + +Routine Description: + + Get TD Link Pointer + +Arguments: + + ptrTDStruct - TD_STRUCT + +Returns: + + Pointer to get + +--*/ +{ + // + // Get TD Link Pointer. Restore it back to 32bit + // (if take 32bit address as an example) + // + return (VOID *) ((UINTN) (ptrTDStruct->TDData.TDLinkPtr << 4)); +} + +BOOLEAN +IsTDLinkPtrQHOrTD ( + IN TD_STRUCT *ptrTDStruct + ) +/*++ + +Routine Description: + + Is TD Link Pointer is QH Or TD + +Arguments: + + ptrTDStruct - TODO: add argument description + +Returns: + + TRUE - QH + FALSE - TD + +--*/ +{ + // + // Get the information about whether the Link Pointer field pointing to + // a QH or a TD. + // + return (BOOLEAN) (ptrTDStruct->TDData.TDLinkPtrQSelect); +} + +VOID +EnableorDisableTDShortPacket ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bEnable + ) +/*++ + +Routine Description: + + Enable or Disable TD ShortPacket + +Arguments: + + ptrTDStruct - TD_STRUCT + bEnable - TRUE is Enanble FALSE is Disable + +Returns: + + VOID + +--*/ +{ + // + // TRUE means enable short packet detection mechanism. + // + ptrTDStruct->TDData.TDStatusSPD = (bEnable ? 1 : 0); +} + +VOID +SetTDControlErrorCounter ( + IN TD_STRUCT *ptrTDStruct, + IN UINT8 nMaxErrors + ) +/*++ + +Routine Description: + + Set TD Control ErrorCounter + +Arguments: + + ptrTDStruct - TD_STRUCT + nMaxErrors - Error counter number + +Returns: + + VOID + +--*/ +{ + // + // valid value of nMaxErrors is 0,1,2,3 + // + if (nMaxErrors > 3) { + nMaxErrors = 3; + } + + ptrTDStruct->TDData.TDStatusErr = nMaxErrors; +} + + +VOID +SetTDLoworFullSpeedDevice ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bLowSpeedDevice + ) +{ + // + // TRUE means the TD is targeting at a Low-speed device + // + ptrTDStruct->TDData.TDStatusLS = (bLowSpeedDevice ? 1 : 0); +} + +VOID +SetTDControlIsochronousorNot ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN IsIsochronous + ) +{ + // + // TRUE means the TD belongs to Isochronous transfer type. + // + ptrTDStruct->TDData.TDStatusIOS = (IsIsochronous ? 1 : 0); +} + +VOID +SetorClearTDControlIOC ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN IsSet + ) +{ + // + // If this bit is set, it indicates that the host controller should issue + // an interrupt on completion of the frame in which this TD is executed. + // + ptrTDStruct->TDData.TDStatusIOC = IsSet ? 1 : 0; +} + +VOID +SetTDStatusActiveorInactive ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN IsActive + ) +{ + // + // If this bit is set, it indicates that the TD is active and can be + // executed. + // + if (IsActive) { + ptrTDStruct->TDData.TDStatus |= 0x80; + } else { + ptrTDStruct->TDData.TDStatus &= 0x7F; + } +} + +UINT16 +SetTDTokenMaxLength ( + IN TD_STRUCT *ptrTDStruct, + IN UINT16 MaximumLength + ) +{ + // + // Specifies the maximum number of data bytes allowed for the transfer. + // the legal value extent is 0 ~ 0x500. + // + if (MaximumLength > 0x500) { + MaximumLength = 0x500; + } + ptrTDStruct->TDData.TDTokenMaxLen = MaximumLength - 1; + + return MaximumLength; +} + +VOID +SetTDTokenDataToggle1 ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Set the data toggle bit to DATA1 + // + ptrTDStruct->TDData.TDTokenDataToggle = 1; +} + +VOID +SetTDTokenDataToggle0 ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Set the data toggle bit to DATA0 + // + ptrTDStruct->TDData.TDTokenDataToggle = 0; +} + +UINT8 +GetTDTokenDataToggle ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Get the data toggle value. + // + return (UINT8) (ptrTDStruct->TDData.TDTokenDataToggle); +} + +VOID +SetTDTokenEndPoint ( + IN TD_STRUCT *ptrTDStruct, + IN UINTN EndPoint + ) +{ + // + // Set EndPoint Number the TD is targeting at. + // + ptrTDStruct->TDData.TDTokenEndPt = (UINT8) EndPoint; +} + +VOID +SetTDTokenDeviceAddress ( + IN TD_STRUCT *ptrTDStruct, + IN UINTN DeviceAddress + ) +{ + // + // Set Device Address the TD is targeting at. + // + ptrTDStruct->TDData.TDTokenDevAddr = (UINT8) DeviceAddress; +} + +VOID +SetTDTokenPacketID ( + IN TD_STRUCT *ptrTDStruct, + IN UINT8 PID + ) +{ + // + // Set the Packet Identification to be used for this transaction. + // + ptrTDStruct->TDData.TDTokenPID = PID; +} + +VOID +SetTDDataBuffer ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Set the beginning address of the data buffer that will be used + // during the transaction. + // + ptrTDStruct->TDData.TDBufferPtr = (UINT32) ((UINTN) (ptrTDStruct->pTDBuffer)); +} + +BOOLEAN +IsTDStatusActive ( + IN TD_STRUCT *ptrTDStruct + ) +{ + UINT8 TDStatus; + + // + // Detect whether the TD is active. + // + TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus); + return (BOOLEAN) (TDStatus & 0x80); +} + +BOOLEAN +IsTDStatusStalled ( + IN TD_STRUCT *ptrTDStruct + ) +{ + UINT8 TDStatus; + + // + // Detect whether the device/endpoint addressed by this TD is stalled. + // + TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus); + return (BOOLEAN) (TDStatus & 0x40); +} + +BOOLEAN +IsTDStatusBufferError ( + IN TD_STRUCT *ptrTDStruct + ) +{ + UINT8 TDStatus; + // + // Detect whether Data Buffer Error is happened. + // + TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus); + return (BOOLEAN) (TDStatus & 0x20); +} + +BOOLEAN +IsTDStatusBabbleError ( + IN TD_STRUCT *ptrTDStruct + ) +{ + UINT8 TDStatus; + + // + // Detect whether Babble Error is happened. + // + TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus); + return (BOOLEAN) (TDStatus & 0x10); +} + +BOOLEAN +IsTDStatusNAKReceived ( + IN TD_STRUCT *ptrTDStruct + ) +{ + UINT8 TDStatus; + + // + // Detect whether NAK is received. + // + TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus); + return (BOOLEAN) (TDStatus & 0x08); +} + +BOOLEAN +IsTDStatusCRCTimeOutError ( + IN TD_STRUCT *ptrTDStruct + ) +{ + UINT8 TDStatus; + + // + // Detect whether CRC/Time Out Error is encountered. + // + TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus); + return (BOOLEAN) (TDStatus & 0x04); +} + +BOOLEAN +IsTDStatusBitStuffError ( + IN TD_STRUCT *ptrTDStruct + ) +{ + UINT8 TDStatus; + + // + // Detect whether Bitstuff Error is received. + // + TDStatus = (UINT8) (ptrTDStruct->TDData.TDStatus); + return (BOOLEAN) (TDStatus & 0x02); +} + +UINT16 +GetTDStatusActualLength ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Retrieve the actual number of bytes that were tansferred. + // the value is encoded as n-1. so return the decoded value. + // + return (UINT16) ((ptrTDStruct->TDData.TDStatusActualLength) + 1); +} + +UINT16 +GetTDTokenMaxLength ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Retrieve the maximum number of data bytes allowed for the trnasfer. + // + return (UINT16) ((ptrTDStruct->TDData.TDTokenMaxLen) + 1); +} + +UINT8 +GetTDTokenEndPoint ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Retrieve the endpoint number the transaction is targeting at. + // + return (UINT8) (ptrTDStruct->TDData.TDTokenEndPt); +} + +UINT8 +GetTDTokenDeviceAddress ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Retrieve the device address the transaction is targeting at. + // + return (UINT8) (ptrTDStruct->TDData.TDTokenDevAddr); +} + +UINT8 +GetTDTokenPacketID ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Retrieve the Packet Identification information. + // + return (UINT8) (ptrTDStruct->TDData.TDTokenPID); +} + +UINT8 * +GetTDDataBuffer ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Retrieve the beginning address of the data buffer + // that involved in this transaction. + // + return ptrTDStruct->pTDBuffer; +} + +BOOLEAN +GetTDLinkPtrValidorInvalid ( + IN TD_STRUCT *ptrTDStruct + ) +{ + // + // Retrieve the information of whether the Link Pointer field + // is valid or not. + // + if (ptrTDStruct->TDData.TDLinkPtrTerminate) { + return FALSE; + } else { + return TRUE; + } + +} + +UINTN +CountTDsNumber ( + IN TD_STRUCT *PtrFirstTD + ) +{ + UINTN Number; + TD_STRUCT *ptr; + // + // Count the queued TDs number. + // + Number = 0; + ptr = PtrFirstTD; + while (ptr) { + ptr = (TD_STRUCT *) ptr->ptrNextTD; + Number++; + } + + return Number; +} + + + +VOID +LinkTDToQH ( + IN QH_STRUCT *PtrQH, + IN TD_STRUCT *PtrTD + ) +/*++ + +Routine Description: + + Link TD To QH + +Arguments: + + PtrQH - QH_STRUCT + PtrTD - TD_STRUCT +Returns: + + VOID + +--*/ +{ + if (PtrQH == NULL || PtrTD == NULL) { + return ; + } + // + // Validate QH Vertical Ptr field + // + SetQHVerticalValidorInvalid (PtrQH, TRUE); + + // + // Vertical Ptr pointing to TD structure + // + SetQHVerticalQHorTDSelect (PtrQH, FALSE); + + SetQHVerticalLinkPtr (PtrQH, (VOID *) PtrTD); + + PtrQH->ptrDown = (VOID *) PtrTD; +} + +VOID +LinkTDToTD ( + IN TD_STRUCT *ptrPreTD, + IN TD_STRUCT *PtrTD + ) +/*++ + +Routine Description: + + Link TD To TD + +Arguments: + + ptrPreTD - Previous TD_STRUCT to be linked + PtrTD - TD_STRUCT to link +Returns: + + VOID + +--*/ +{ + if (ptrPreTD == NULL || PtrTD == NULL) { + return ; + } + // + // Depth first fashion + // + SetTDLinkPtrDepthorBreadth (ptrPreTD, TRUE); + + // + // Link pointer pointing to TD struct + // + SetTDLinkPtrQHorTDSelect (ptrPreTD, FALSE); + + // + // Validate the link pointer valid bit + // + SetTDLinkPtrValidorInvalid (ptrPreTD, TRUE); + + SetTDLinkPtr (ptrPreTD, PtrTD); + + ptrPreTD->ptrNextTD = (VOID *) PtrTD; +} +// +// Transfer Schedule related Helper Functions +// +VOID +SetorClearCurFrameListTerminate ( + IN FRAMELIST_ENTRY *pCurEntry, + IN BOOLEAN IsSet + ) +{ + // + // If TRUE, empty the frame. If FALSE, indicate the Pointer field is valid. + // + pCurEntry->FrameListPtrTerminate = (IsSet ? 1 : 0); +} + +VOID +SetCurFrameListQHorTD ( + IN FRAMELIST_ENTRY *pCurEntry, + IN BOOLEAN IsQH + ) +{ + // + // This bit indicates to the hardware whether the item referenced by the + // link pointer is a TD or a QH. + // + pCurEntry->FrameListPtrQSelect = (IsQH ? 1 : 0); +} + +BOOLEAN +IsCurFrameListQHorTD ( + IN FRAMELIST_ENTRY *pCurEntry + ) +{ + // + // TRUE is QH + // FALSE is TD + // + return (BOOLEAN) (pCurEntry->FrameListPtrQSelect); +} + +BOOLEAN +GetCurFrameListTerminate ( + IN FRAMELIST_ENTRY *pCurEntry + ) +{ + // + // TRUE means the frame is empty, + // FALSE means the link pointer field is valid. + // + return (BOOLEAN) (pCurEntry->FrameListPtrTerminate); +} + +VOID +SetCurFrameListPointer ( + IN FRAMELIST_ENTRY *pCurEntry, + IN UINT8 *ptr + ) +{ + // + // Set the pointer field of the frame. + // + pCurEntry->FrameListPtr = (UINT32) ((UINTN) ptr >> 4); +} + +VOID * +GetCurFrameListPointer ( + IN FRAMELIST_ENTRY *pCurEntry + ) +{ + // + // Get the link pointer of the frame. + // + return (VOID *) ((UINTN) (pCurEntry->FrameListPtr << 4)); + +} + +VOID +LinkQHToFrameList ( + IN FRAMELIST_ENTRY *pEntry, + IN UINT16 FrameListIndex, + IN QH_STRUCT *PtrQH + ) +/*++ + +Routine Description: + + Link QH To Frame List + +Arguments: + + pEntry - FRAMELIST_ENTRY + FrameListIndex - Frame List Index + PtrQH - QH to link +Returns: + + VOID + +--*/ +{ + FRAMELIST_ENTRY *pCurFrame; + QH_STRUCT *TempQH; + QH_STRUCT *NextTempQH; + TD_STRUCT *TempTD; + BOOLEAN LINK; + + // + // Get frame list entry that the link process will begin from. + // + pCurFrame = pEntry + FrameListIndex; + + // + // if current frame is empty + // then link the specified QH directly to the Frame List. + // + if (GetCurFrameListTerminate (pCurFrame)) { + + // + // Link new QH to the frame list entry. + // + SetCurFrameListQHorTD (pCurFrame, TRUE); + + SetCurFrameListPointer (pCurFrame, (UINT8 *) PtrQH); + + // + // clear T bit in the Frame List, indicating that the frame list entry + // is no longer empty. + // + SetorClearCurFrameListTerminate (pCurFrame, FALSE); + + return ; + + } else { + // + // current frame list has link pointer + // + if (!IsCurFrameListQHorTD (pCurFrame)) { + // + // a TD is linked to the framelist entry + // + TempTD = (TD_STRUCT *) GetCurFrameListPointer (pCurFrame); + + while (GetTDLinkPtrValidorInvalid (TempTD)) { + + if (IsTDLinkPtrQHOrTD (TempTD)) { + // + // QH linked next to the TD + // + break; + } + + TempTD = (TD_STRUCT *) GetTDLinkPtr (TempTD); + } + + // + // either no ptr linked next to the TD or QH is linked next to the TD + // + if (!GetTDLinkPtrValidorInvalid (TempTD)) { + + // + // no ptr linked next to the TD + // + TempTD->ptrNextQH = PtrQH; + SetTDLinkPtrQHorTDSelect (TempTD, TRUE); + SetTDLinkPtr (TempTD, PtrQH); + SetTDLinkPtrValidorInvalid (TempTD, TRUE); + return ; + + } else { + // + // QH is linked next to the TD + // + TempQH = (QH_STRUCT *) GetTDLinkPtr (TempTD); + } + } else { + // + // a QH is linked to the framelist entry + // + TempQH = (QH_STRUCT *) GetCurFrameListPointer (pCurFrame); + } + + // + // Set up Flag + // + LINK = TRUE; + + // + // Avoid the same qh repeated linking in one frame entry + // + if (TempQH == PtrQH) { + LINK = FALSE; + return ; + } + // + // if current QH has next QH connected + // + while (GetQHHorizontalValidorInvalid (TempQH)) { + // + // Get next QH pointer + // + NextTempQH = (QH_STRUCT *) GetQHHorizontalLinkPtr (TempQH); + + // + // Bulk transfer qh may be self-linked, + // so, the code below is to aVOID dead-loop when meeting self-linked qh + // + if (NextTempQH == TempQH) { + LINK = FALSE; + break; + } + + TempQH = NextTempQH; + + // + // Avoid the same qh repeated linking in one frame entry + // + if (TempQH == PtrQH) { + LINK = FALSE; + } + } + + if (LINK) { + TempQH->ptrNext = PtrQH; + SetQHHorizontalQHorTDSelect (TempQH, TRUE); + SetQHHorizontalLinkPtr (TempQH, PtrQH); + SetQHHorizontalValidorInvalid (TempQH, TRUE); + } + + return ; + } +} + +EFI_STATUS +ExecuteControlTransfer ( + IN USB_HC_DEV *HcDev, + IN TD_STRUCT *PtrTD, + IN UINT32 wIndex, + OUT UINTN *ActualLen, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +/*++ + +Routine Description: + + Execute Control Transfer + +Arguments: + + HcDev - USB_HC_DEV + PtrTD - TD_STRUCT + wIndex - No use + ActualLen - Actual transfered Len + TimeOut - TimeOut value in milliseconds + TransferResult - Transfer result +Returns: + + EFI_SUCCESS - Sucess + EFI_DEVICE_ERROR - Error + + +--*/ +{ + UINTN ErrTDPos; + UINTN Delay; + UINTN RequiredLen; + BOOLEAN TransferFinished; + + ErrTDPos = 0; + *TransferResult = EFI_USB_NOERROR; + RequiredLen = *ActualLen; + *ActualLen = 0; + + Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1; + + do { + TransferFinished = CheckTDsResults ( + PtrTD, + RequiredLen, + TransferResult, + &ErrTDPos, + ActualLen + ); + + if (TransferFinished) { + break; + } + + // + // TD is inactive, which means the control transfer is end. + // + if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) { + break; + } + + gBS->Stall (50); + + } while (Delay--); + + if (*TransferResult != EFI_USB_NOERROR) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ExecBulkorSyncInterruptTransfer ( + IN USB_HC_DEV *HcDev, + IN TD_STRUCT *PtrTD, + IN UINT32 wIndex, + OUT UINTN *ActualLen, + OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +/*++ + +Routine Description: + + Execute Bulk or SyncInterrupt Transfer + +Arguments: + + HcDev - USB_HC_DEV + PtrTD - TD_STRUCT + wIndex - No use + ActualLen - Actual transfered Len + DataToggle - Data Toggle + TimeOut - TimeOut value in milliseconds + TransferResult - Transfer result +Returns: + + EFI_SUCCESS - Sucess + EFI_DEVICE_ERROR - Error +--*/ +{ + UINTN ErrTDPos; + UINTN ScrollNum; + UINTN Delay; + UINTN RequiredLen; + BOOLEAN TransferFinished; + + ErrTDPos = 0; + *TransferResult = EFI_USB_NOERROR; + RequiredLen = *ActualLen; + *ActualLen = 0; + + Delay = (TimeOut * STALL_1_MILLI_SECOND / 50) + 1; + + do { + + TransferFinished = CheckTDsResults ( + PtrTD, + RequiredLen, + TransferResult, + &ErrTDPos, + ActualLen + ); + + if (TransferFinished) { + break; + } + + // + // TD is inactive, which means bulk or interrupt transfer's end. + // + if ((*TransferResult & EFI_USB_ERR_NOTEXECUTE) != EFI_USB_ERR_NOTEXECUTE) { + break; + } + + gBS->Stall (50); + + } while (Delay--); + + // + // has error + // + if (*TransferResult != EFI_USB_NOERROR) { + + // + // scroll the Data Toggle back to the last success TD + // + ScrollNum = CountTDsNumber (PtrTD) - ErrTDPos; + if (ScrollNum & 0x1) { + *DataToggle ^= 1; + } + + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +VOID +DelLinkSingleQH ( + IN USB_HC_DEV *HcDev, + IN QH_STRUCT *PtrQH, + IN UINT16 FrameListIndex, + IN BOOLEAN SearchOther, + IN BOOLEAN Delete + ) +/*++ + +Routine Description: + + Unlink from frame list and delete single QH +Arguments: + + HcDev - USB_HC_DEV + PtrQH - QH_STRUCT + FrameListIndex - Frame List Index + SearchOther - Search Other QH + Delete - TRUE is to delete the QH +Returns: + VOID +--*/ +{ + FRAMELIST_ENTRY *pCurFrame; + UINTN Index; + UINTN BeginFrame; + UINTN EndFrame; + QH_STRUCT *CurrentQH; + QH_STRUCT *NextQH; + TD_STRUCT *CurrentTD; + VOID *PtrPreQH; + BOOLEAN Found; + + NextQH = NULL; + PtrPreQH = NULL; + Found = FALSE; + + if (PtrQH == NULL) { + return ; + } + + if (SearchOther) { + BeginFrame = 0; + EndFrame = 1024; + } else { + BeginFrame = FrameListIndex; + EndFrame = FrameListIndex + 1; + } + + for (Index = BeginFrame; Index < EndFrame; Index++) { + + pCurFrame = HcDev->FrameListEntry + (Index & 0x3FF); + + if (GetCurFrameListTerminate (pCurFrame)) { + // + // current frame list is empty,search next frame list entry + // + continue; + } + + if (!IsCurFrameListQHorTD (pCurFrame)) { + // + // TD linked to current framelist + // + CurrentTD = (TD_STRUCT *) GetCurFrameListPointer (pCurFrame); + + while (GetTDLinkPtrValidorInvalid (CurrentTD)) { + + if (IsTDLinkPtrQHOrTD (CurrentTD)) { + // + // QH linked next to the TD,break while () + // + break; + } + + CurrentTD = (TD_STRUCT *) GetTDLinkPtr (CurrentTD); + } + + if (!GetTDLinkPtrValidorInvalid (CurrentTD)) { + // + // no QH linked next to the last TD, + // search next frame list + // + continue; + } + + // + // a QH linked next to the last TD + // + CurrentQH = (QH_STRUCT *) GetTDLinkPtr (CurrentTD); + + PtrPreQH = CurrentTD; + + } else { + // + // a QH linked to current framelist + // + CurrentQH = (QH_STRUCT *) GetCurFrameListPointer (pCurFrame); + + PtrPreQH = NULL; + } + + if (CurrentQH == PtrQH) { + + if (GetQHHorizontalValidorInvalid (PtrQH)) { + // + // there is QH connected after the QH found + // + // + // retrieve nex qh pointer of the qh found. + // + NextQH = GetQHHorizontalLinkPtr (PtrQH); + } else { + NextQH = NULL; + } + + if (PtrPreQH) { + // + // QH linked to a TD struct + // + CurrentTD = (TD_STRUCT *) PtrPreQH; + + SetTDLinkPtrValidorInvalid (CurrentTD, (BOOLEAN) ((NextQH == NULL) ? FALSE : TRUE)); + SetTDLinkPtr (CurrentTD, NextQH); + CurrentTD->ptrNextQH = NextQH; + + } else { + // + // QH linked directly to current framelist entry + // + SetorClearCurFrameListTerminate (pCurFrame, (BOOLEAN) ((NextQH == NULL) ? TRUE : FALSE)); + SetCurFrameListPointer (pCurFrame, (UINT8 *) NextQH); + } + + Found = TRUE; + // + // search next framelist entry + // + continue; + } + + while (GetQHHorizontalValidorInvalid (CurrentQH)) { + + PtrPreQH = CurrentQH; + // + // Get next horizontal linked QH + // + CurrentQH = (QH_STRUCT *) GetQHHorizontalLinkPtr (CurrentQH); + // + // the qh is found + // + if (CurrentQH == PtrQH) { + break; + } + } + + // + // search next frame list entry + // + if (CurrentQH != PtrQH) { + // + // Not find the QH + // + continue; + } + // + // find the specified qh, then delink it from + // the horizontal QH list in the frame entry. + // + + if (GetQHHorizontalValidorInvalid (PtrQH)) { + // + // there is QH connected after the QH found + // + // + // retrieve nex qh pointer of the qh found. + // + NextQH = GetQHHorizontalLinkPtr (PtrQH); + + } else { + // + // NO QH connected after the QH found + // + NextQH = NULL; + // + // NULL the previous QH's link ptr and set Terminate field. + // + SetQHHorizontalValidorInvalid ((QH_STRUCT *) PtrPreQH, FALSE); + } + + SetQHHorizontalLinkPtr ((QH_STRUCT *) PtrPreQH, NextQH); + ((QH_STRUCT *) PtrPreQH)->ptrNext = NextQH; + + Found = TRUE; + } + + if (Found && Delete) { + // + // free memory once used by the specific QH + // + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + } + + return ; +} + + +VOID +DeleteQueuedTDs ( + IN USB_HC_DEV *HcDev, + IN TD_STRUCT *PtrFirstTD + ) +/*++ +Routine Description: + + Delete Queued TDs +Arguments: + + HcDev - USB_HC_DEV + PtrFirstTD - TD link list head + +Returns: + VOID + +--*/ +{ + TD_STRUCT *Tptr1; + TD_STRUCT *Tptr2; + + Tptr1 = PtrFirstTD; + // + // Delete all the TDs in a queue. + // + while (Tptr1) { + + Tptr2 = Tptr1; + + if (!GetTDLinkPtrValidorInvalid (Tptr2)) { + Tptr1 = NULL; + } else { + + Tptr1 = GetTDLinkPtr (Tptr2); + + // + // TD link to itself + // + if (Tptr1 == Tptr2) { + Tptr1 = NULL; + } + } + + UhciFreePool (HcDev, (UINT8 *) Tptr2, sizeof (TD_STRUCT)); + } + + return ; +} + +VOID +InsertQHTDToINTList ( + IN USB_HC_DEV *HcDev, + IN QH_STRUCT *PtrQH, + IN TD_STRUCT *PtrFirstTD, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DataToggle, + IN UINTN DataLength, + IN UINTN PollingInterval, + IN VOID *Mapping, + IN UINT8 *DataBuffer, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, + IN VOID *Context + ) +/*++ +Routine Description: + Insert QH and TD To Interrupt List +Arguments: + + HcDev - USB_HC_DEV + PtrQH - QH_STRUCT + PtrFirstTD - First TD_STRUCT + DeviceAddress - Device Address + EndPointAddress - EndPoint Address + DataToggle - Data Toggle + DataLength - Data length + PollingInterval - Polling Interval when inserted to frame list + Mapping - Mapping alue + DataBuffer - Data buffer + CallBackFunction- CallBackFunction after interrupt transfeer + Context - CallBackFunction Context passed as function parameter +Returns: + EFI_SUCCESS - Sucess + EFI_INVALID_PARAMETER - Paremeter is error + +--*/ +{ + INTERRUPT_LIST *Node; + + Node = AllocatePool (sizeof (INTERRUPT_LIST)); + if (Node == NULL) { + return ; + } + + // + // Fill Node field + // + Node->Signature = INTERRUPT_LIST_SIGNATURE; + Node->DevAddr = DeviceAddress; + Node->EndPoint = EndPointAddress; + Node->PtrQH = PtrQH; + Node->PtrFirstTD = PtrFirstTD; + Node->DataToggle = DataToggle; + Node->DataLen = DataLength; + Node->PollInterval = PollingInterval; + Node->Mapping = Mapping; + // + // DataBuffer is allocated host memory, not mapped memory + // + Node->DataBuffer = DataBuffer; + Node->InterruptCallBack = CallBackFunction; + Node->InterruptContext = Context; + + // + // insert the new interrupt transfer to the head of the list. + // The interrupt transfer's monitor function scans the whole list from head + // to tail. The new interrupt transfer MUST be added to the head of the list + // for the sake of error recovery. + // + InsertHeadList (&(HcDev->InterruptListHead), &(Node->Link)); + + return ; +} + + +EFI_STATUS +DeleteAsyncINTQHTDs ( + IN USB_HC_DEV *HcDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + OUT UINT8 *DataToggle + ) +/*++ +Routine Description: + + Delete Async INT QH and TDs +Arguments: + + HcDev - USB_HC_DEV + DeviceAddress - Device Address + EndPointAddress - EndPoint Address + DataToggle - Data Toggle + +Returns: + EFI_SUCCESS - Sucess + EFI_INVALID_PARAMETER - Paremeter is error + +--*/ +{ + QH_STRUCT *MatchQH; + QH_STRUCT *ptrNextQH; + TD_STRUCT *MatchTD; + LIST_ENTRY *Link; + INTERRUPT_LIST *MatchList; + INTERRUPT_LIST *PtrList; + BOOLEAN Found; + + UINT32 Result; + UINTN ErrTDPos; + UINTN ActualLen; + + MatchQH = NULL; + MatchTD = NULL; + MatchList = NULL; + + // + // no interrupt transaction exists + // + if (IsListEmpty (&(HcDev->InterruptListHead))) { + return EFI_INVALID_PARAMETER; + } + // + // find the correct QH-TD that need to delete + // (by matching Device address and EndPoint number to match QH-TD ) + // + Found = FALSE; + Link = &(HcDev->InterruptListHead); + do { + + Link = Link->ForwardLink; + PtrList = INTERRUPT_LIST_FROM_LINK (Link); + + if ((PtrList->DevAddr == DeviceAddress) && ((PtrList->EndPoint & 0x0f) == (EndPointAddress & 0x0f))) { + MatchList = PtrList; + + Found = TRUE; + break; + } + + } while (Link->ForwardLink != &(HcDev->InterruptListHead)); + + if (!Found) { + return EFI_INVALID_PARAMETER; + } + // + // get current endpoint's data toggle bit and save. + // + ExecuteAsyncINTTDs (HcDev, MatchList, &Result, &ErrTDPos, &ActualLen); + UpdateAsyncINTQHTDs (MatchList, Result, (UINT32) ErrTDPos); + *DataToggle = MatchList->DataToggle; + + MatchTD = MatchList->PtrFirstTD; + MatchQH = MatchList->PtrQH; + // + // find the first matching QH position in the FrameList + // + while (MatchQH) { + + ptrNextQH = MatchQH->ptrNextIntQH; + + // + // Search all the entries + // + DelLinkSingleQH (HcDev, MatchQH, 0, TRUE, TRUE); + + MatchQH = ptrNextQH; + } + + // + // Call PciIo->Unmap() to unmap the busmaster read/write + // + HcDev->PciIo->Unmap (HcDev->PciIo, MatchList->Mapping); + + // + // free host data buffer allocated, + // mapped data buffer is freed by Unmap + // + if (MatchList->DataBuffer != NULL) { + gBS->FreePool (MatchList->DataBuffer); + } + + // + // at last delete the TDs, to aVOID problems + // + DeleteQueuedTDs (HcDev, MatchTD); + + // + // remove Match node from interrupt list + // + RemoveEntryList (&(MatchList->Link)); + gBS->FreePool (MatchList); + return EFI_SUCCESS; +} + +BOOLEAN +CheckTDsResults ( + IN TD_STRUCT *PtrTD, + IN UINTN RequiredLen, + OUT UINT32 *Result, + OUT UINTN *ErrTDPos, + OUT UINTN *ActualTransferSize + ) +/*++ + +Routine Description: + + Check TDs Results + +Arguments: + + PtrTD - TD_STRUCT to check + RequiredLen - Required Len + Result - Transfer result + ErrTDPos - Error TD Position + ActualTransferSize - Actual Transfer Size + +Returns: + + TRUE - Sucess + FALSE - Fail + +--*/ +{ + UINTN Len; + + *Result = EFI_USB_NOERROR; + *ErrTDPos = 0; + + // + // Init to zero. + // + *ActualTransferSize = 0; + + while (PtrTD) { + + if (IsTDStatusActive (PtrTD)) { + *Result |= EFI_USB_ERR_NOTEXECUTE; + } + + if (IsTDStatusStalled (PtrTD)) { + *Result |= EFI_USB_ERR_STALL; + } + + if (IsTDStatusBufferError (PtrTD)) { + *Result |= EFI_USB_ERR_BUFFER; + } + + if (IsTDStatusBabbleError (PtrTD)) { + *Result |= EFI_USB_ERR_BABBLE; + } + + if (IsTDStatusNAKReceived (PtrTD)) { + *Result |= EFI_USB_ERR_NAK; + } + + if (IsTDStatusCRCTimeOutError (PtrTD)) { + *Result |= EFI_USB_ERR_TIMEOUT; + } + + if (IsTDStatusBitStuffError (PtrTD)) { + *Result |= EFI_USB_ERR_BITSTUFF; + } + + // + // if any error encountered, stop processing the left TDs. + // + if (*Result) { + return FALSE; + } + + Len = GetTDStatusActualLength (PtrTD) & 0x7FF; + *ActualTransferSize += Len; + + if (*ActualTransferSize <= RequiredLen && Len < PtrTD->TDData.TDTokenMaxLen) { + // + // transter finished and actural length less than required length + // + goto Done; + } + // + // Accumulate actual transferred data length in each TD. + // + PtrTD = (TD_STRUCT *) (PtrTD->ptrNextTD); + // + // Record the first Error TD's position in the queue, + // this value is zero-based. + // + (*ErrTDPos)++; + } + +Done: + return TRUE; +} + + +VOID +ExecuteAsyncINTTDs ( + IN USB_HC_DEV *HcDev, + IN INTERRUPT_LIST *PtrList, + OUT UINT32 *Result, + OUT UINTN *ErrTDPos, + OUT UINTN *ActualLen + ) +/*++ + +Routine Description: + + Execute Async Interrupt TDs + +Arguments: + + HcDev - USB_HC_DEV + PtrList - INTERRUPT_LIST + Result - Transfer result + ErrTDPos - Error TD Position + ActualTransferSize - Actual Transfer Size + +Returns: + + VOID + +--*/ +{ + // + // *ErrTDPos is zero-based value, indicating the first error TD's position + // in the TDs' sequence. + // *ErrTDPos value is only valid when *Result is not equal NOERROR. + // + UINTN RequiredLen; + + RequiredLen = *ActualLen; + CheckTDsResults (PtrList->PtrFirstTD, RequiredLen, Result, ErrTDPos, ActualLen); + + return ; +} + + +VOID +UpdateAsyncINTQHTDs ( + IN INTERRUPT_LIST *PtrList, + IN UINT32 Result, + IN UINT32 ErrTDPos + ) +/*++ + +Routine Description: + + Update Async Interrupt QH and TDs + +Arguments: + + PtrList - INTERRUPT_LIST + Result - Transfer reslut + ErrTDPos - Error TD Position + +Returns: + + VOID + +--*/ +{ + QH_STRUCT *PtrFirstQH; + QH_STRUCT *PtrQH; + TD_STRUCT *PtrFirstTD; + TD_STRUCT *PtrTD; + UINT8 DataToggle; + UINT32 Index; + + PtrFirstQH = PtrList->PtrQH; + PtrFirstTD = PtrList->PtrFirstTD; + + DataToggle = 0; + + if (Result == EFI_USB_NOERROR) { + + PtrTD = PtrFirstTD; + while (PtrTD) { + DataToggle = GetTDTokenDataToggle (PtrTD); + PtrTD = PtrTD->ptrNextTD; + } + + // + // save current DataToggle value to interrupt list. + // this value is used for tracing the interrupt endpoint DataToggle. + // when this interrupt transfer is deleted, the last DataToggle is saved + // + PtrList->DataToggle = DataToggle; + + PtrTD = PtrFirstTD; + + // + // Since DataToggle bit should toggle after each success transaction, + // the First TD's DataToggle bit will be updated to XOR of Last TD's + // DataToggle bit. If the First TD's DataToggle bit is not equal Last + // TD's DataToggle bit, that means it already be the XOR of Last TD's, + // so no update is needed. + // + if (DataToggle == GetTDTokenDataToggle (PtrFirstTD)) { + PtrTD = PtrFirstTD; + while (PtrTD) { + + DataToggle ^= 1; + if (DataToggle) { + SetTDTokenDataToggle1 (PtrTD); + } else { + SetTDTokenDataToggle0 (PtrTD); + } + + PtrTD = PtrTD->ptrNextTD; + } + } + // + // restore Link Pointer of QH to First TD + // (because QH's Link Pointer will change during TD execution) + // + PtrQH = PtrFirstQH; + while (PtrQH) { + + LinkTDToQH (PtrQH, PtrFirstTD); + PtrQH = PtrQH->ptrNextIntQH; + } + + // + // set all the TDs active + // + PtrTD = PtrFirstTD; + while (PtrTD) { + SetTDStatusActiveorInactive (PtrTD, TRUE); + PtrTD = PtrTD->ptrNextTD; + } + + } else if (((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE) || + ((Result & EFI_USB_ERR_NAK) == EFI_USB_ERR_NAK) + ) { + // + // no update + // + } else { + // + // Have Errors + // + PtrTD = PtrFirstTD; + // + // not first TD error + // + if (ErrTDPos != 0) { + // + // get the last success TD + // + for (Index = 1; Index < ErrTDPos; Index++) { + PtrTD = PtrTD->ptrNextTD; + } + // + // update Data Toggle in the interrupt list node + // + PtrList->DataToggle = GetTDTokenDataToggle (PtrTD); + + // + // get the error TD + // + PtrTD = PtrTD->ptrNextTD; + + } else { + PtrList->DataToggle = GetTDTokenDataToggle (PtrTD); + } + // + // do not restore the QH's vertical link pointer, + // let the callback function do the rest of error handling. + // + } + + return ; +} + +VOID +ReleaseInterruptList ( + IN USB_HC_DEV *HcDev, + IN LIST_ENTRY *ListHead + ) +/*++ + +Routine Description: + + Release Interrupt List +Arguments: + + HcDev - USB_HC_DEV + ListHead - List head + +Returns: + + VOID + +--*/ +{ + LIST_ENTRY *Link; + LIST_ENTRY *SavedLink; + INTERRUPT_LIST *pNode; + TD_STRUCT *PtrTD; + TD_STRUCT *ptrNextTD; + QH_STRUCT *PtrQH; + QH_STRUCT *SavedQH; + + if (ListHead == NULL) { + return ; + } + + Link = ListHead; + + // + // Free all the resources in the interrupt list + // + SavedLink = Link->ForwardLink; + while (!IsListEmpty (ListHead)) { + + Link = SavedLink; + + SavedLink = Link->ForwardLink; + + pNode = INTERRUPT_LIST_FROM_LINK (Link); + + RemoveEntryList (&pNode->Link); + + SavedQH = pNode->PtrQH; + for (PtrQH = SavedQH; PtrQH != NULL; PtrQH = SavedQH) { + SavedQH = PtrQH->ptrNextIntQH; + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + } + + PtrTD = pNode->PtrFirstTD; + while (PtrTD != NULL) { + + ptrNextTD = PtrTD->ptrNextTD; + UhciFreePool (HcDev, (UINT8 *) PtrTD, sizeof (TD_STRUCT)); + PtrTD = ptrNextTD; + } + + gBS->FreePool (pNode); + } +} + + +EFI_STATUS +InitializeMemoryManagement ( + IN USB_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Initialize Memory Management + +Arguments: + + HcDev - USB_HC_DEV + +Returns: + + EFI_SUCCESS - Success +--*/ +{ + MEMORY_MANAGE_HEADER *MemoryHeader; + EFI_STATUS Status; + UINTN MemPages; + + MemPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES; + Status = CreateMemoryBlock (HcDev, &MemoryHeader, MemPages); + if (EFI_ERROR (Status)) { + return Status; + } + + HcDev->MemoryHeader = MemoryHeader; + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateMemoryBlock ( + IN USB_HC_DEV *HcDev, + OUT MEMORY_MANAGE_HEADER **MemoryHeader, + IN UINTN MemoryBlockSizeInPages + ) +/*++ + +Routine Description: + + Use PciIo->AllocateBuffer to allocate common buffer for the memory block, + and use PciIo->Map to map the common buffer for Bus Master Read/Write. + + +Arguments: + + HcDev - USB_HC_DEV + MemoryHeader - MEMORY_MANAGE_HEADER to output + MemoryBlockSizeInPages - MemoryBlockSizeInPages +Returns: + + EFI_SUCCESS - Success +--*/ +{ + EFI_STATUS Status; + VOID *CommonBuffer; + EFI_PHYSICAL_ADDRESS MappedAddress; + UINTN MemoryBlockSizeInBytes; + VOID *Mapping; + + // + // Allocate memory for MemoryHeader + // + *MemoryHeader = AllocateZeroPool (sizeof (MEMORY_MANAGE_HEADER)); + if (*MemoryHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + (*MemoryHeader)->Next = NULL; + + // + // set Memory block size + // + (*MemoryHeader)->MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages); + + // + // each bit in Bit Array will manage 32 bytes memory in memory block + // + (*MemoryHeader)->BitArraySizeInBytes = ((*MemoryHeader)->MemoryBlockSizeInBytes / 32) / 8; + + // + // Allocate memory for BitArray + // + (*MemoryHeader)->BitArrayPtr = AllocateZeroPool ((*MemoryHeader)->BitArraySizeInBytes); + if ((*MemoryHeader)->BitArrayPtr == NULL) { + gBS->FreePool (*MemoryHeader); + return EFI_OUT_OF_RESOURCES; + } + + // + // Memory Block uses MemoryBlockSizeInPages pages, + // and it is allocated as common buffer use. + // + Status = HcDev->PciIo->AllocateBuffer ( + HcDev->PciIo, + AllocateAnyPages, + EfiBootServicesData, + MemoryBlockSizeInPages, + &CommonBuffer, + 0 + ); + if (EFI_ERROR (Status)) { + gBS->FreePool ((*MemoryHeader)->BitArrayPtr); + gBS->FreePool (*MemoryHeader); + return Status; + } + + MemoryBlockSizeInBytes = EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages); + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterCommonBuffer, + CommonBuffer, + &MemoryBlockSizeInBytes, + &MappedAddress, + &Mapping + ); + // + // if returned Mapped size is less than the size we request,do not support. + // + if (EFI_ERROR (Status) || (MemoryBlockSizeInBytes != EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages))) { + HcDev->PciIo->FreeBuffer (HcDev->PciIo, MemoryBlockSizeInPages, CommonBuffer); + gBS->FreePool ((*MemoryHeader)->BitArrayPtr); + gBS->FreePool (*MemoryHeader); + return EFI_UNSUPPORTED; + } + // + // Set Memory block initial address + // + (*MemoryHeader)->MemoryBlockPtr = (UINT8 *) ((UINTN) MappedAddress); + (*MemoryHeader)->Mapping = Mapping; + + ZeroMem ( + (*MemoryHeader)->MemoryBlockPtr, + EFI_PAGES_TO_SIZE (MemoryBlockSizeInPages) + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +FreeMemoryHeader ( + IN USB_HC_DEV *HcDev, + IN MEMORY_MANAGE_HEADER *MemoryHeader + ) +/*++ + +Routine Description: + + Free Memory Header + +Arguments: + + HcDev - USB_HC_DEV + MemoryHeader - MemoryHeader to be freed + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + +--*/ +{ + if ((MemoryHeader == NULL) || (HcDev == NULL)) { + return EFI_INVALID_PARAMETER; + } + // + // unmap the common buffer used by the memory block + // + HcDev->PciIo->Unmap (HcDev->PciIo, MemoryHeader->Mapping); + + // + // free common buffer + // + HcDev->PciIo->FreeBuffer ( + HcDev->PciIo, + EFI_SIZE_TO_PAGES (MemoryHeader->MemoryBlockSizeInBytes), + MemoryHeader->MemoryBlockPtr + ); + // + // free bit array + // + gBS->FreePool (MemoryHeader->BitArrayPtr); + // + // free memory header + // + gBS->FreePool (MemoryHeader); + + return EFI_SUCCESS; +} + +EFI_STATUS +UhciAllocatePool ( + IN USB_HC_DEV *HcDev, + OUT UINT8 **Pool, + IN UINTN AllocSize + ) +/*++ + +Routine Description: + + Uhci Allocate Pool + +Arguments: + + HcDev - USB_HC_DEV + Pool - Place to store pointer to the memory buffer + AllocSize - Alloc Size + +Returns: + + EFI_SUCCESS - Success + +--*/ +{ + MEMORY_MANAGE_HEADER *MemoryHeader; + MEMORY_MANAGE_HEADER *TempHeaderPtr; + MEMORY_MANAGE_HEADER *NewMemoryHeader; + UINTN RealAllocSize; + UINTN MemoryBlockSizeInPages; + EFI_STATUS Status; + + *Pool = NULL; + + MemoryHeader = HcDev->MemoryHeader; + ASSERT (MemoryHeader != NULL); + + // + // allocate unit is 32 bytes (align on 32 byte) + // + if (AllocSize & 0x1F) { + RealAllocSize = (AllocSize / 32 + 1) * 32; + } else { + RealAllocSize = AllocSize; + } + + // + // There may be linked MemoryHeaders. + // To allocate a free pool in Memory blocks, + // must search in the MemoryHeader link list + // until enough free pool is found. + // + Status = EFI_NOT_FOUND; + for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; + TempHeaderPtr = TempHeaderPtr->Next) { + + Status = AllocMemInMemoryBlock ( + TempHeaderPtr, + (VOID **) Pool, + RealAllocSize / 32 + ); + if (!EFI_ERROR (Status)) { + ZeroMem (*Pool, AllocSize); + return EFI_SUCCESS; + } + } + + // + // There is no enough memory, + // Create a new Memory Block + // + + // + // if pool size is larger than NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES, + // just allocate a large enough memory block. + // + if (RealAllocSize > EFI_PAGES_TO_SIZE (NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES)) { + MemoryBlockSizeInPages = EFI_SIZE_TO_PAGES (RealAllocSize) + 1; + } else { + MemoryBlockSizeInPages = NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES; + } + + Status = CreateMemoryBlock (HcDev, &NewMemoryHeader, MemoryBlockSizeInPages); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Link the new Memory Block to the Memory Header list + // + InsertMemoryHeaderToList (MemoryHeader, NewMemoryHeader); + + Status = AllocMemInMemoryBlock ( + NewMemoryHeader, + (VOID **) Pool, + RealAllocSize / 32 + ); + + if (!EFI_ERROR (Status)) { + ZeroMem (*Pool, AllocSize); + } + + return Status; +} + +VOID +UhciFreePool ( + IN USB_HC_DEV *HcDev, + IN UINT8 *Pool, + IN UINTN AllocSize + ) +/*++ + +Routine Description: + + Uhci Free Pool + +Arguments: + + HcDev - USB_HC_DEV + Pool - Pool to free + AllocSize - Pool size + +Returns: + + VOID + +--*/ +{ + MEMORY_MANAGE_HEADER *MemoryHeader; + MEMORY_MANAGE_HEADER *TempHeaderPtr; + UINTN StartBytePos; + UINTN Index; + UINT8 StartBitPos; + UINT8 Index2; + UINTN Count; + UINTN RealAllocSize; + + MemoryHeader = HcDev->MemoryHeader; + + // + // allocate unit is 32 byte (align on 32 byte) + // + if (AllocSize & 0x1F) { + RealAllocSize = (AllocSize / 32 + 1) * 32; + } else { + RealAllocSize = AllocSize; + } + // + // scan the memory header linked list for + // the asigned memory to free. + // + for (TempHeaderPtr = MemoryHeader;TempHeaderPtr != NULL; + TempHeaderPtr = TempHeaderPtr->Next) { + + if ((Pool >= TempHeaderPtr->MemoryBlockPtr) && + ((Pool + RealAllocSize) <= (TempHeaderPtr->MemoryBlockPtr + TempHeaderPtr->MemoryBlockSizeInBytes)) + ) { + // + // Pool is in the Memory Block area, + // find the start byte and bit in the bit array + // + StartBytePos = ((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) / 8; + StartBitPos = (UINT8) (((Pool - TempHeaderPtr->MemoryBlockPtr) / 32) & 0x7); + + // + // reset associated bits in bit arry + // + for (Index = StartBytePos, Index2 = StartBitPos, Count = 0; Count < (RealAllocSize / 32); Count++) { + + TempHeaderPtr->BitArrayPtr[Index] ^= (UINT8) (bit (Index2)); + Index2++; + if (Index2 == 8) { + Index += 1; + Index2 = 0; + } + } + // + // break the loop + // + break; + } + } + + // + // Release emptied memory blocks (only if the memory block is not + // the first one in the memory header list + // + for (TempHeaderPtr = MemoryHeader->Next; TempHeaderPtr != NULL;) { + // + // Debug + // + ASSERT (MemoryHeader->Next != NULL); + + if (IsMemoryBlockEmptied (TempHeaderPtr)) { + + DelinkMemoryBlock (MemoryHeader, TempHeaderPtr); + // + // when the TempHeaderPtr is freed in FreeMemoryHeader(), + // the TempHeaderPtr is pointing to nonsense content. + // + FreeMemoryHeader (HcDev, TempHeaderPtr); + // + // reset the TempHeaderPtr, continue search for + // another empty memory block. + // + TempHeaderPtr = MemoryHeader->Next; + continue; + } + + TempHeaderPtr = TempHeaderPtr->Next; + } +} + +VOID +InsertMemoryHeaderToList ( + IN MEMORY_MANAGE_HEADER *MemoryHeader, + IN MEMORY_MANAGE_HEADER *NewMemoryHeader + ) +/*++ + +Routine Description: + + Insert Memory Header To List + +Arguments: + + MemoryHeader - MEMORY_MANAGE_HEADER + NewMemoryHeader - MEMORY_MANAGE_HEADER + +Returns: + + VOID + +--*/ +{ + MEMORY_MANAGE_HEADER *TempHeaderPtr; + + for (TempHeaderPtr = MemoryHeader; TempHeaderPtr != NULL; + TempHeaderPtr = TempHeaderPtr->Next) { + if (TempHeaderPtr->Next == NULL) { + TempHeaderPtr->Next = NewMemoryHeader; + break; + } + } +} + +EFI_STATUS +AllocMemInMemoryBlock ( + IN MEMORY_MANAGE_HEADER *MemoryHeader, + OUT VOID **Pool, + IN UINTN NumberOfMemoryUnit + ) +/*++ + +Routine Description: + + Alloc Memory In MemoryBlock + +Arguments: + + MemoryHeader - MEMORY_MANAGE_HEADER + Pool - Place to store pointer to memory + NumberOfMemoryUnit - Number Of Memory Unit + +Returns: + + EFI_NOT_FOUND - Can't find the free memory + EFI_SUCCESS - Success + +--*/ +{ + UINTN TempBytePos; + UINTN FoundBytePos; + UINT8 Index; + UINT8 FoundBitPos; + UINT8 ByteValue; + UINT8 BitValue; + UINTN NumberOfZeros; + UINTN Count; + + FoundBytePos = 0; + FoundBitPos = 0; + ByteValue = MemoryHeader->BitArrayPtr[0]; + NumberOfZeros = 0; + Index = 0; + + for (TempBytePos = 0; TempBytePos < MemoryHeader->BitArraySizeInBytes;) { + + // + // Pop out BitValue from a byte in TempBytePos. + // + BitValue = (UINT8) (ByteValue & 0x1); + // + // right shift the byte + // + ByteValue /= 2; + + if (BitValue == 0) { + // + // Found a free bit, the NumberOfZeros only record the number + // of those consecutive zeros + // + NumberOfZeros++; + // + // Found enough consecutive free space, break the loop + // + if (NumberOfZeros >= NumberOfMemoryUnit) { + break; + } + } else { + // + // Encountering a '1', meant the bit is ocupied. + // + if (NumberOfZeros >= NumberOfMemoryUnit) { + // + // Found enough consecutive free space,break the loop + // + break; + } else { + // + // the NumberOfZeros only record the number of those consecutive zeros, + // so reset the NumberOfZeros to 0 when encountering '1' before finding + // enough consecutive '0's + // + NumberOfZeros = 0; + // + // reset the (FoundBytePos,FoundBitPos) to the position of '1' + // + FoundBytePos = TempBytePos; + FoundBitPos = Index; + } + } + // + // step forward a bit + // + Index++; + if (Index == 8) { + // + // step forward a byte, getting the byte value, + // and reset the bit pos. + // + TempBytePos += 1; + ByteValue = MemoryHeader->BitArrayPtr[TempBytePos]; + Index = 0; + } + } + + if (NumberOfZeros < NumberOfMemoryUnit) { + return EFI_NOT_FOUND; + } + + // + // Found enough free space. + // + + // + // The values recorded in (FoundBytePos,FoundBitPos) have two conditions: + // 1)(FoundBytePos,FoundBitPos) record the position + // of the last '1' before the consecutive '0's, it must + // be adjusted to the start position of the consecutive '0's. + // 2)the start address of the consecutive '0's is just the start of + // the bitarray. so no need to adjust the values of + // (FoundBytePos,FoundBitPos). + // + if ((MemoryHeader->BitArrayPtr[0] & bit (0)) != 0) { + FoundBitPos += 1; + } + + // + // Have the (FoundBytePos,FoundBitPos) make sense. + // + if (FoundBitPos > 7) { + FoundBytePos += 1; + FoundBitPos -= 8; + } + + // + // Set the memory as allocated + // + for (TempBytePos = FoundBytePos, Index = FoundBitPos,Count = 0; + Count < NumberOfMemoryUnit; Count ++) { + + MemoryHeader->BitArrayPtr[TempBytePos] |= bit (Index); + Index++; + if (Index == 8) { + TempBytePos += 1; + Index = 0; + } + } + + *Pool = MemoryHeader->MemoryBlockPtr + (FoundBytePos * 8 + FoundBitPos) * 32; + + return EFI_SUCCESS; +} + +BOOLEAN +IsMemoryBlockEmptied ( + IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr + ) +/*++ + +Routine Description: + + Is Memory Block Emptied + +Arguments: + + MemoryHeaderPtr - MEMORY_MANAGE_HEADER + +Returns: + + TRUE - Empty + FALSE - Not Empty + +--*/ +{ + UINTN Index; + + for (Index = 0; Index < MemoryHeaderPtr->BitArraySizeInBytes; Index++) { + if (MemoryHeaderPtr->BitArrayPtr[Index] != 0) { + return FALSE; + } + } + + return TRUE; +} + +VOID +DelinkMemoryBlock ( + IN MEMORY_MANAGE_HEADER *FirstMemoryHeader, + IN MEMORY_MANAGE_HEADER *NeedFreeMemoryHeader + ) +/*++ + +Routine Description: + + Delink Memory Block + +Arguments: + + FirstMemoryHeader - MEMORY_MANAGE_HEADER + NeedFreeMemoryHeader - MEMORY_MANAGE_HEADER + +Returns: + + VOID + +--*/ +{ + MEMORY_MANAGE_HEADER *TempHeaderPtr; + + if ((FirstMemoryHeader == NULL) || (NeedFreeMemoryHeader == NULL)) { + return ; + } + for (TempHeaderPtr = FirstMemoryHeader; TempHeaderPtr != NULL; + TempHeaderPtr = TempHeaderPtr->Next) { + + if (TempHeaderPtr->Next == NeedFreeMemoryHeader) { + // + // Link the before and after + // + TempHeaderPtr->Next = NeedFreeMemoryHeader->Next; + break; + } + } +} + +EFI_STATUS +DelMemoryManagement ( + IN USB_HC_DEV *HcDev + ) +/*++ + +Routine Description: + + Delete Memory Management + +Arguments: + + HcDev - USB_HC_DEV + +Returns: + + EFI_SUCCESS - Success + +--*/ +{ + MEMORY_MANAGE_HEADER *TempHeaderPtr; + + for (TempHeaderPtr = HcDev->MemoryHeader->Next; TempHeaderPtr != NULL;) { + + DelinkMemoryBlock (HcDev->MemoryHeader, TempHeaderPtr); + // + // when the TempHeaderPtr is freed in FreeMemoryHeader(), + // the TempHeaderPtr is pointing to nonsense content. + // + FreeMemoryHeader (HcDev, TempHeaderPtr); + // + // reset the TempHeaderPtr,continue free another memory block. + // + TempHeaderPtr = HcDev->MemoryHeader->Next; + } + + FreeMemoryHeader (HcDev, HcDev->MemoryHeader); + + return EFI_SUCCESS; +} + + +VOID +CleanUsbTransactions ( + IN USB_HC_DEV *HcDev + ) +{ + // + // only asynchronous interrupt transfers are always alive on the bus + // + ReleaseInterruptList (HcDev, &(HcDev->InterruptListHead)); +} + +VOID +TurnOffUSBEmulation ( + IN EFI_PCI_IO_PROTOCOL *PciIo + ) +/*++ + + Routine Description: + Disable USB Emulation + Arguments: + PciIo - EFI_PCI_IO_PROTOCOL + Returns: + VOID +--*/ +{ + UINT16 Command; + + // + // Disable USB Emulation + // + Command = 0; + PciIo->Pci.Write ( + PciIo, + EfiPciIoWidthUint16, + USB_EMULATION, + 1, + &Command + ); + + return ; +} diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c new file mode 100644 index 0000000000..1eba8bed5b --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.c @@ -0,0 +1,3498 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Uhci.c + +Abstract: + + +Revision History +--*/ + +#include "uhci.h" + +// +// Prototypes +// Driver model protocol interface +// + +EFI_STATUS +EFIAPI +UHCIDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +UHCIDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +UHCIDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +UHCIDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// UHCI interface functions +// + +EFI_STATUS +EFIAPI +UHCIReset ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT16 Attributes + ); + +EFI_STATUS +EFIAPI +UHCIGetState ( + IN EFI_USB_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ); + +EFI_STATUS +EFIAPI +UHCISetState ( + IN EFI_USB_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ); + +EFI_STATUS +EFIAPI +UHCIControlTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataLength, OPTIONAL + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +UHCIBulkTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +UHCIAsyncInterruptTransfer ( + IN EFI_USB_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaxiumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval, OPTIONAL + IN UINTN DataLength, OPTIONAL + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL + IN VOID *Context OPTIONAL + ); + +EFI_STATUS +EFIAPI +UHCISyncInterruptTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +UHCIIsochronousTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN UINTN DataLength, + OUT UINT32 *TransferResult + ); + +EFI_STATUS +EFIAPI +UHCIAsyncIsochronousTransfer ( + IN EFI_USB_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ); + +EFI_STATUS +EFIAPI +UHCIGetRootHubPortNumber ( + IN EFI_USB_HC_PROTOCOL *This, + OUT UINT8 *PortNumber + ); + +EFI_STATUS +EFIAPI +UHCIGetRootHubPortStatus ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ); + +EFI_STATUS +EFIAPI +UHCISetRootHubPortFeature ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + +EFI_STATUS +EFIAPI +UHCIClearRootHubPortFeature ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + +// +// Asynchronous interrupt transfer monitor function +// +VOID +EFIAPI +MonitorInterruptTrans ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// UHCI Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding = { + UHCIDriverBindingSupported, + UHCIDriverBindingStart, + UHCIDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +UHCIDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + that has UsbHcProtocol installed will be supported. + + Arguments: + This - Protocol instance pointer. + Controller, - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_UNSUPPORTED - This driver does not support this device. + +--*/ +{ + EFI_STATUS OpenStatus; + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + USB_CLASSC UsbClassCReg; + + // + // Test whether there is PCI IO Protocol attached on the controller handle. + // + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (OpenStatus)) { + return OpenStatus; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + CLASSC, + sizeof (USB_CLASSC) / sizeof (UINT8), + &UsbClassCReg + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_UNSUPPORTED; + } + // + // Test whether the controller belongs to UHCI type + // + if ((UsbClassCReg.BaseCode != PCI_CLASS_SERIAL) || + (UsbClassCReg.SubClassCode != PCI_CLASS_SERIAL_USB) || + (UsbClassCReg.PI != PCI_CLASSC_PI_UHCI)) { + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_UNSUPPORTED; + } + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +UHCIDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Starting the Usb UHCI Driver + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_UNSUPPORTED - This driver does not support this device. + EFI_DEVICE_ERROR - This driver cannot be started due to device + Error + EFI_OUT_OF_RESOURCES + +--*/ +{ + EFI_STATUS Status; + UINTN FlBaseAddrReg; + EFI_PCI_IO_PROTOCOL *PciIo; + USB_HC_DEV *HcDev; + + HcDev = NULL; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Turn off USB emulation + // + TurnOffUSBEmulation (PciIo); + + // + // Enable the USB Host Controller + // + Status = PciIo->Attributes ( + PciIo, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_UNSUPPORTED; + } + + // + // allocate memory for UHC private data structure + // + HcDev = AllocateZeroPool (sizeof (USB_HC_DEV)); + if (HcDev == NULL) { + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_OUT_OF_RESOURCES; + } + + // + // init EFI_USB_HC_PROTOCOL protocol interface and install the protocol + // + HcDev->UsbHc.Reset = UHCIReset; + HcDev->UsbHc.GetState = UHCIGetState; + HcDev->UsbHc.SetState = UHCISetState; + HcDev->UsbHc.ControlTransfer = UHCIControlTransfer; + HcDev->UsbHc.BulkTransfer = UHCIBulkTransfer; + HcDev->UsbHc.AsyncInterruptTransfer = UHCIAsyncInterruptTransfer; + HcDev->UsbHc.SyncInterruptTransfer = UHCISyncInterruptTransfer; + HcDev->UsbHc.IsochronousTransfer = UHCIIsochronousTransfer; + HcDev->UsbHc.AsyncIsochronousTransfer = UHCIAsyncIsochronousTransfer; + HcDev->UsbHc.GetRootHubPortNumber = UHCIGetRootHubPortNumber; + HcDev->UsbHc.GetRootHubPortStatus = UHCIGetRootHubPortStatus; + HcDev->UsbHc.SetRootHubPortFeature = UHCISetRootHubPortFeature; + HcDev->UsbHc.ClearRootHubPortFeature = UHCIClearRootHubPortFeature; + + HcDev->UsbHc.MajorRevision = 0x1; + HcDev->UsbHc.MinorRevision = 0x1; + + // + // Init UHCI private data structures + // + HcDev->Signature = USB_HC_DEV_SIGNATURE; + HcDev->PciIo = PciIo; + + FlBaseAddrReg = USBFLBASEADD; + + // + // Allocate and Init Host Controller's Frame List Entry + // + Status = CreateFrameList (HcDev, (UINT32) FlBaseAddrReg); + if (EFI_ERROR (Status)) { + + if (HcDev != NULL) { + gBS->FreePool (HcDev); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_OUT_OF_RESOURCES; + } + + // + // Init interrupt list head in the HcDev structure. + // + InitializeListHead (&(HcDev->InterruptListHead)); + + // + // Create timer for interrupt transfer result polling + // + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_NOTIFY, + MonitorInterruptTrans, + HcDev, + &HcDev->InterruptTransTimer + ); + if (EFI_ERROR (Status)) { + + FreeFrameListEntry (HcDev); + + if (HcDev != NULL) { + gBS->FreePool (HcDev); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_UNSUPPORTED; + } + + // + // Here set interrupt transfer polling timer in 50ms unit. + // + Status = gBS->SetTimer ( + HcDev->InterruptTransTimer, + TimerPeriodic, + INTERRUPT_POLLING_TIME + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (HcDev->InterruptTransTimer); + + FreeFrameListEntry (HcDev); + + if (HcDev != NULL) { + gBS->FreePool (HcDev); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_UNSUPPORTED; + } + + // + // QH,TD structures must in common buffer that will be + // accessed by both cpu and usb bus master at the same time. + // so, there must has memory management for QH,TD structures. + // + Status = InitializeMemoryManagement (HcDev); + if (EFI_ERROR (Status)) { + + gBS->CloseEvent (HcDev->InterruptTransTimer); + + FreeFrameListEntry (HcDev); + + if (HcDev != NULL) { + gBS->FreePool (HcDev); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + // + // Install Host Controller Protocol + // + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiUsbHcProtocolGuid, + EFI_NATIVE_INTERFACE, + &HcDev->UsbHc + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (HcDev->InterruptTransTimer); + FreeFrameListEntry (HcDev); + DelMemoryManagement (HcDev); + + if (HcDev != NULL) { + gBS->FreePool (HcDev); + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + // + // component name protocol. + // + HcDev->ControllerNameTable = NULL; + AddUnicodeString ( + "eng", + gUhciComponentName.SupportedLanguages, + &HcDev->ControllerNameTable, + (CHAR16 *) L"Usb Universal Host Controller" + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +UnInstallUHCInterface ( + IN EFI_HANDLE Controller, + IN EFI_USB_HC_PROTOCOL *This + ) +/*++ + Routine Description: + UnInstall UHCInterface + Arguments: + Controller - Controller handle + This - Protocol instance pointer. + Returns: + EFI_SUCCESS + others +--*/ +{ + USB_HC_DEV *HcDev; + + HcDev = USB_HC_DEV_FROM_THIS (This); + + gBS->UninstallProtocolInterface ( + Controller, + &gEfiUsbHcProtocolGuid, + &HcDev->UsbHc + ); + + // + // first stop USB Host Controller + // + This->SetState (This, EfiUsbHcStateHalt); + + // + // Delete interrupt transfer polling timer + // + gBS->CloseEvent (HcDev->InterruptTransTimer); + + // + // Delete all the asynchronous interrupt transfers in the interrupt list + // and free associated memory + // + ReleaseInterruptList (HcDev, &(HcDev->InterruptListHead)); + + // + // free Frame List Entry. + // + FreeFrameListEntry (HcDev); + + // + // Free common buffer allocated for QH,TD structures + // + DelMemoryManagement (HcDev); + + if (HcDev->ControllerNameTable) { + FreeUnicodeStringTable (HcDev->ControllerNameTable); + } + // + // Disable the USB Host Controller + // + HcDev->PciIo->Attributes ( + HcDev->PciIo, + EfiPciIoAttributeOperationDisable, + EFI_PCI_DEVICE_ENABLE, + NULL + ); + + gBS->FreePool (HcDev); + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +UHCIDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + EFI_SUCCESS + others + +--*/ +{ + EFI_USB_HC_PROTOCOL *UsbHc; + EFI_STATUS OpenStatus; + + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + (VOID **) &UsbHc, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + // + // Test whether the Controller handler passed in is a valid + // Usb controller handle that should be supported, if not, + // return the error status directly + // + if (EFI_ERROR (OpenStatus)) { + return OpenStatus; + } + // + // free all the controller related memory and uninstall UHCI Protocol. + // + UnInstallUHCInterface (Controller, UsbHc); + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; + +} + + +EFI_STATUS +EFIAPI +UHCIReset ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT16 Attributes + ) +/*++ + + Routine Description: + Provides software reset for the USB host controller. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL instance. + + Attributes A bit mask of the reset operation to perform. + See below for a list of the supported bit mask values. + + #define EFI_USB_HC_RESET_GLOBAL 0x0001 + #define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002 + + EFI_USB_HC_RESET_GLOBAL + If this bit is set, a global reset signal will be sent to the USB bus. + This resets all of the USB bus logic, including the USB host + controller hardware and all the devices attached on the USB bus. + EFI_USB_HC_RESET_HOST_CONTROLLER + If this bit is set, the USB host controller hardware will be reset. + No reset signal will be sent to the USB bus. + + Returns: + EFI_SUCCESS + The reset operation succeeded. + EFI_INVALID_PARAMETER + Attributes is not valid. + EFI_DEVICE_ERROR + An error was encountered while attempting to perform + the reset operation. +--*/ +{ + BOOLEAN Match; + USB_HC_DEV *HcDev; + UINT32 CommandRegAddr; + UINT32 FlBaseAddrReg; + UINT16 Command; + EFI_STATUS Status; + + Match = FALSE; + HcDev = USB_HC_DEV_FROM_THIS (This); + + CommandRegAddr = (UINT32) (USBCMD); + FlBaseAddrReg = (UINT32) (USBFLBASEADD); + + if ((Attributes & EFI_USB_HC_RESET_GLOBAL) != 0) { + Match = TRUE; + // + // set the Global Reset bit in the command register + // + Status = ReadUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + &Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Command |= USBCMD_GRESET; + Status = WriteUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Wait 50ms for root port to let reset complete + // See UHCI spec page122 Reset signaling + // + gBS->Stall (ROOT_PORT_REST_TIME); + + // + // Clear the Global Reset bit to zero. + // + Command &= ~USBCMD_GRESET; + Status = WriteUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // UHCI spec page120 reset recovery time + // + gBS->Stall (PORT_RESET_RECOVERY_TIME); + } + + if ((Attributes & EFI_USB_HC_RESET_HOST_CONTROLLER) != 0) { + Match = TRUE; + // + // set Host Controller Reset bit to 1 + // + Status = ReadUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + &Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Command |= USBCMD_HCRESET; + Status = WriteUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // this bit will be reset by Host Controller when reset is completed. + // wait 10ms to let reset complete + // + gBS->Stall (PORT_RESET_RECOVERY_TIME); + } + + if (!Match) { + return EFI_INVALID_PARAMETER; + } + + // + // Delete all old transactions on the USB bus + // + CleanUsbTransactions (HcDev); + + // + // Initialize Universal Host Controller's Frame List Data Structure + // + InitFrameList (HcDev); + + // + // Reset may cause Frame List Base Address Register reset to zero, + // so set the original value back again. + // + SetFrameListBaseAddress ( + HcDev->PciIo, + FlBaseAddrReg, + (UINT32) ((UINTN) HcDev->FrameListEntry) + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UHCIGetState ( + IN EFI_USB_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ) +/*++ + + Routine Description: + Retrieves current state of the USB host controller. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL instance. + + State A pointer to the EFI_USB_HC_STATE data structure that + indicates current state of the USB host controller. + Type EFI_USB_HC_STATE is defined below. + + typedef enum { + EfiUsbHcStateHalt, + EfiUsbHcStateOperational, + EfiUsbHcStateSuspend, + EfiUsbHcStateMaximum + } EFI_USB_HC_STATE; + + Returns: + EFI_SUCCESS + The state information of the host controller was returned in State. + EFI_INVALID_PARAMETER + State is NULL. + EFI_DEVICE_ERROR + An error was encountered while attempting to retrieve the + host controller's current state. +--*/ +{ + USB_HC_DEV *HcDev; + UINT32 CommandRegAddr; + UINT32 StatusRegAddr; + UINT16 UhcCommand; + UINT16 UhcStatus; + EFI_STATUS Status; + + if (State == NULL) { + return EFI_INVALID_PARAMETER; + } + + HcDev = USB_HC_DEV_FROM_THIS (This); + + CommandRegAddr = (UINT32) (USBCMD); + StatusRegAddr = (UINT32) (USBSTS); + + Status = ReadUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + &UhcCommand + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = ReadUHCCommandReg ( + HcDev->PciIo, + StatusRegAddr, + &UhcStatus + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (UhcCommand & USBCMD_EGSM) { + *State = EfiUsbHcStateSuspend; + return EFI_SUCCESS; + } + + if ((UhcStatus & USBSTS_HCH) == 0) { + *State = EfiUsbHcStateOperational; + } else { + *State = EfiUsbHcStateHalt; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +UHCISetState ( + IN EFI_USB_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ) +/*++ + + Routine Description: + Sets the USB host controller to a specific state. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL instance. + + State Indicates the state of the host controller that will be set. + + Returns: + EFI_SUCCESS + The USB host controller was successfully placed in the state + specified by State. + EFI_INVALID_PARAMETER + State is invalid. + EFI_DEVICE_ERROR + Failed to set the state specified by State due to device error. +--*/ +{ + USB_HC_DEV *HcDev; + UINT32 CommandRegAddr; + UINT32 StatusRegAddr; + UINT16 Command; + EFI_USB_HC_STATE CurrentState; + EFI_STATUS Status; + + HcDev = USB_HC_DEV_FROM_THIS (This); + + CommandRegAddr = (UINT32) (USBCMD); + StatusRegAddr = (UINT32) (USBSTS); + + Status = UHCIGetState (This, &CurrentState); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + switch (State) { + + case EfiUsbHcStateHalt: + if (CurrentState == EfiUsbHcStateHalt) { + return EFI_SUCCESS; + } + + Status = ReadUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + &Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Command &= ~USBCMD_RS; + + Status = WriteUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + StatusRegAddr = (UINT32) (USBSTS); + // + // ensure the HC is in halt status after send the stop command + // + if (WaitForUHCHalt (HcDev->PciIo, StatusRegAddr, STALL_1_SECOND) == EFI_TIMEOUT) { + return EFI_DEVICE_ERROR; + } + break; + + case EfiUsbHcStateOperational: + if (IsHostSysOrProcessErr (HcDev->PciIo, StatusRegAddr)) { + return EFI_DEVICE_ERROR; + } + + switch (CurrentState) { + + case EfiUsbHcStateOperational: + return EFI_SUCCESS; + + case EfiUsbHcStateHalt: + // + // Set Run/Stop bit to 1. + // + Status = ReadUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + &Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Command |= USBCMD_RS | USBCMD_MAXP; + Status = WriteUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + break; + + case EfiUsbHcStateSuspend: + Status = ReadUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + &Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // FGR(Force Global Resume) bit is 0 + // + if ((Command | (~USBCMD_FGR)) != 0xFF) { + // + // Write FGR bit to 1 + // + Command |= USBCMD_FGR; + WriteUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + Command + ); + } + + // + // wait 20ms to let resume complete + // (20ms is specified by UHCI spec) + // + gBS->Stall (FORCE_GLOBAL_RESUME_TIME); + + // + // Write FGR bit to 0 and EGSM(Enter Global Suspend Mode) bit to 0 + // + Command &= ~USBCMD_FGR; + Command &= ~USBCMD_EGSM; + Command |= USBCMD_RS; + WriteUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + Command + ); + break; + + default: + break; + } + break; + + case EfiUsbHcStateSuspend: + if (CurrentState == EfiUsbHcStateSuspend) { + return EFI_SUCCESS; + } + + Status = UHCISetState (This, EfiUsbHcStateHalt); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Set Enter Global Suspend Mode bit to 1. + // + Status = ReadUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + &Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Command |= USBCMD_EGSM; + Status = WriteUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + break; + + default: + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UHCIGetRootHubPortNumber ( + IN EFI_USB_HC_PROTOCOL *This, + OUT UINT8 *PortNumber + ) +/*++ + + Routine Description: + Retrieves the number of root hub ports. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL instance. + + PortNumber A pointer to the number of the root hub ports. + + Returns: + EFI_SUCCESS + The port number was retrieved successfully. + EFI_INVALID_PARAMETER + PortNumber is NULL. + EFI_DEVICE_ERROR + An error was encountered while attempting to + retrieve the port number. +--*/ +{ + USB_HC_DEV *HcDev; + UINT32 PSAddr; + UINT16 RHPortControl; + UINT32 Index; + EFI_STATUS Status; + + HcDev = USB_HC_DEV_FROM_THIS (This); + + if (PortNumber == NULL) { + return EFI_INVALID_PARAMETER; + } + + *PortNumber = 0; + + for (Index = 0; Index < 2; Index++) { + PSAddr = (UINT32) (USBPORTSC1 + Index * 2); + Status = ReadRootPortReg ( + HcDev->PciIo, + PSAddr, + &RHPortControl + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Port Register content is valid + // + if (RHPortControl != 0xff) { + (*PortNumber)++; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UHCIGetRootHubPortStatus ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ) +/*++ + + Routine Description: + Retrieves the current status of a USB root hub port. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL. + + PortNumber Specifies the root hub port from which the status + is to be retrieved. This value is zero-based. For example, + if a root hub has two ports, then the first port is numbered 0, + and the second port is numbered 1. + + PortStatus A pointer to the current port status bits and + port status change bits. + + Returns: + EFI_SUCCESS + The status of the USB root hub port specified by PortNumber + was returned in PortStatus. + EFI_INVALID_PARAMETER + PortNumber is invalid. + EFI_DEVICE_ERROR - Can't read register +--*/ +{ + USB_HC_DEV *HcDev; + UINT32 PSAddr; + UINT16 RHPortStatus; + UINT8 TotalPortNumber; + EFI_STATUS Status; + + if (PortStatus == NULL) { + return EFI_INVALID_PARAMETER; + } + + UHCIGetRootHubPortNumber (This, &TotalPortNumber); + if (PortNumber >= TotalPortNumber) { + return EFI_INVALID_PARAMETER; + } + + HcDev = USB_HC_DEV_FROM_THIS (This); + PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2); + + // + // Clear port status + // + PortStatus->PortStatus = 0; + PortStatus->PortChangeStatus = 0; + + Status = ReadRootPortReg ( + HcDev->PciIo, + PSAddr, + &RHPortStatus + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Fill Port Status bits + // + + // + // Current Connect Status + // + if (RHPortStatus & USBPORTSC_CCS) { + PortStatus->PortStatus |= USB_PORT_STAT_CONNECTION; + } + // + // Port Enabled/Disabled + // + if (RHPortStatus & USBPORTSC_PED) { + PortStatus->PortStatus |= USB_PORT_STAT_ENABLE; + } + + // + // Port Suspend + // + if (RHPortStatus & USBPORTSC_SUSP) { + PortStatus->PortStatus |= USB_PORT_STAT_SUSPEND; + } + + // + // Port Reset + // + if (RHPortStatus & USBPORTSC_PR) { + PortStatus->PortStatus |= USB_PORT_STAT_RESET; + } + + // + // Low Speed Device Attached + // + if (RHPortStatus & USBPORTSC_LSDA) { + PortStatus->PortStatus |= USB_PORT_STAT_LOW_SPEED; + } + // + // Fill Port Status Change bits + // + + // + // Connect Status Change + // + if (RHPortStatus & USBPORTSC_CSC) { + PortStatus->PortChangeStatus |= USB_PORT_STAT_C_CONNECTION; + } + + // + // Port Enabled/Disabled Change + // + if (RHPortStatus & USBPORTSC_PEDC) { + PortStatus->PortChangeStatus |= USB_PORT_STAT_C_ENABLE; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UHCISetRootHubPortFeature ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +/*++ + + Routine Description: + Sets a feature for the specified root hub port. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL. + + PortNumber Specifies the root hub port whose feature + is requested to be set. + + PortFeature Indicates the feature selector associated + with the feature set request. + + Returns: + EFI_SUCCESS + The feature specified by PortFeature was set for the + USB root hub port specified by PortNumber. + EFI_INVALID_PARAMETER + PortNumber is invalid or PortFeature is invalid. + EFI_DEVICE_ERROR + Can't read register +--*/ +{ + USB_HC_DEV *HcDev; + UINT32 PSAddr; + UINT32 CommandRegAddr; + // + // root hub port status + // + UINT16 RHPortControl; + UINT16 Command; + UINT8 TotalPortNumber; + EFI_STATUS Status; + + UHCIGetRootHubPortNumber (This, &TotalPortNumber); + if (PortNumber >= TotalPortNumber) { + return EFI_INVALID_PARAMETER; + } + + HcDev = USB_HC_DEV_FROM_THIS (This); + + PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2); + CommandRegAddr = (UINT32) (USBCMD); + + Status = ReadRootPortReg ( + HcDev->PciIo, + PSAddr, + &RHPortControl + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + switch (PortFeature) { + + case EfiUsbPortSuspend: + Status = ReadUHCCommandReg ( + HcDev->PciIo, + CommandRegAddr, + &Command + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (!(Command & USBCMD_EGSM)) { + // + // if global suspend is not active, can set port suspend + // + RHPortControl &= 0xfff5; + RHPortControl |= USBPORTSC_SUSP; + } + break; + + case EfiUsbPortReset: + RHPortControl &= 0xfff5; + // + // Set the reset bit + // + RHPortControl |= USBPORTSC_PR; + break; + + case EfiUsbPortPower: + break; + + case EfiUsbPortEnable: + RHPortControl &= 0xfff5; + RHPortControl |= USBPORTSC_PED; + break; + + default: + return EFI_INVALID_PARAMETER; + } + + WriteRootPortReg ( + HcDev->PciIo, + PSAddr, + RHPortControl + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UHCIClearRootHubPortFeature ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +/*++ + + Routine Description: + Clears a feature for the specified root hub port. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL instance. + + PortNumber Specifies the root hub port whose feature + is requested to be cleared. + + PortFeature Indicates the feature selector associated with the + feature clear request. + + Returns: + EFI_SUCCESS + The feature specified by PortFeature was cleared for the + USB root hub port specified by PortNumber. + EFI_INVALID_PARAMETER + PortNumber is invalid or PortFeature is invalid. + EFI_DEVICE_ERROR + Can't read register +--*/ +{ + USB_HC_DEV *HcDev; + UINT32 PSAddr; + UINT16 RHPortControl; + UINT8 TotalPortNumber; + EFI_STATUS Status; + + UHCIGetRootHubPortNumber (This, &TotalPortNumber); + + if (PortNumber >= TotalPortNumber) { + return EFI_INVALID_PARAMETER; + } + + HcDev = USB_HC_DEV_FROM_THIS (This); + PSAddr = (UINT32) (USBPORTSC1 + PortNumber * 2); + + Status = ReadRootPortReg ( + HcDev->PciIo, + PSAddr, + &RHPortControl + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + switch (PortFeature) { + // + // clear PORT_ENABLE feature means disable port. + // + case EfiUsbPortEnable: + RHPortControl &= 0xfff5; + RHPortControl &= ~USBPORTSC_PED; + break; + + // + // clear PORT_SUSPEND feature means resume the port. + // (cause a resume on the specified port if in suspend mode) + // + case EfiUsbPortSuspend: + RHPortControl &= 0xfff5; + RHPortControl &= ~USBPORTSC_SUSP; + break; + + // + // no operation + // + case EfiUsbPortPower: + break; + + // + // clear PORT_RESET means clear the reset signal. + // + case EfiUsbPortReset: + RHPortControl &= 0xfff5; + RHPortControl &= ~USBPORTSC_PR; + break; + + // + // clear connect status change + // + case EfiUsbPortConnectChange: + RHPortControl &= 0xfff5; + RHPortControl |= USBPORTSC_CSC; + break; + + // + // clear enable/disable status change + // + case EfiUsbPortEnableChange: + RHPortControl &= 0xfff5; + RHPortControl |= USBPORTSC_PEDC; + break; + + // + // root hub does not support this request + // + case EfiUsbPortSuspendChange: + break; + + // + // root hub does not support this request + // + case EfiUsbPortOverCurrentChange: + break; + + // + // root hub does not support this request + // + case EfiUsbPortResetChange: + break; + + default: + return EFI_INVALID_PARAMETER; + } + + WriteRootPortReg ( + HcDev->PciIo, + PSAddr, + RHPortControl + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UHCIControlTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataLength, OPTIONAL + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + Submits control transfer to a target USB device. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL instance. + + DeviceAddress Represents the address of the target device on the USB, + which is assigned during USB enumeration. + + IsSlowDevice Indicates whether the target device is slow device + or full-speed device. + + MaximumPacketLength Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + + Request A pointer to the USB device request that will be sent + to the USB device. + + TransferDirection Specifies the data direction for the transfer. + There are three values available, DataIn, DataOut + and NoData. + + Data A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + + DataLength Indicates the size, in bytes, of the data buffer + specified by Data. + + TimeOut Indicates the maximum time, in microseconds, + which the transfer is allowed to complete. + + TransferResult A pointer to the detailed result information generated + by this control transfer. + + Returns: + EFI_SUCCESS + The control transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The control transfer could not be completed due to a lack of resources. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The control transfer failed due to timeout. + EFI_DEVICE_ERROR + The control transfer failed due to host controller or device error. + Caller should check TranferResult for detailed error information. + +--*/ +{ + USB_HC_DEV *HcDev; + UINT32 StatusReg; + UINT32 FrameNumReg; + UINT8 PktID; + QH_STRUCT *PtrQH; + TD_STRUCT *PtrTD; + TD_STRUCT *PtrPreTD; + TD_STRUCT *PtrSetupTD; + TD_STRUCT *PtrStatusTD; + EFI_STATUS Status; + UINTN Index; + UINTN DataLen; + UINT8 *PtrDataSource; + UINT8 *Ptr; + UINT8 DataToggle; + UINT16 LoadFrameListIndex; + UINT8 PktSize; + + UINT8 *RequestMappedAddress; + VOID *RequestMapping; + UINTN RequestLen; + + EFI_PHYSICAL_ADDRESS TempPtr; + VOID *Mapping; + + TD_STRUCT *PtrFirstDataTD; + TD_STRUCT *ptrLastDataTD; + BOOLEAN FirstTD; + + FirstTD = FALSE; + RequestMappedAddress = NULL; + RequestMapping = NULL; + Mapping = NULL; + PtrFirstDataTD = NULL; + ptrLastDataTD = NULL; + PktID = INPUT_PACKET_ID; + Mapping = NULL; + HcDev = USB_HC_DEV_FROM_THIS (This); + StatusReg = (UINT32) (USBSTS); + FrameNumReg = (UINT32) (USBFRNUM); + PtrPreTD = NULL; + PtrTD = NULL; + + // + // Parameters Checking + // + if (Request == NULL || TransferResult == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // if errors exist that cause host controller halt, + // then return EFI_DEVICE_ERROR. + // + if (!IsStatusOK (HcDev->PciIo, StatusReg)) { + + ClearStatusReg (HcDev->PciIo, StatusReg); + *TransferResult = EFI_USB_ERR_SYSTEM; + return EFI_DEVICE_ERROR; + } + + // + // low speed usb devices are limited to only an eight-byte + // maximum data payload size + // + if (IsSlowDevice && (MaximumPacketLength != 8)) { + return EFI_INVALID_PARAMETER; + } + + if (MaximumPacketLength != 8 && + MaximumPacketLength != 16 && + MaximumPacketLength != 32 && + MaximumPacketLength != 64) { + return EFI_INVALID_PARAMETER; + } + + if ((TransferDirection != EfiUsbNoData) && (DataLength == NULL)) { + return EFI_INVALID_PARAMETER; + } + + switch (TransferDirection) { + + case EfiUsbDataIn: + PktID = INPUT_PACKET_ID; + PtrDataSource = Data; + DataLen = *DataLength; + + // + // map the source data buffer for bus master access. + // BusMasterWrite means cpu read + // + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterWrite, + PtrDataSource, + &DataLen, + &TempPtr, + &Mapping + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Ptr = (UINT8 *) ((UINTN) TempPtr); + break; + + case EfiUsbDataOut: + PktID = OUTPUT_PACKET_ID; + PtrDataSource = Data; + DataLen = *DataLength; + + // + // map the source data buffer for bus master access. + // BusMasterRead means cpu write + // + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterRead, + PtrDataSource, + &DataLen, + &TempPtr, + &Mapping + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Ptr = (UINT8 *) ((UINTN) TempPtr); + break; + + // + // no data stage + // + case EfiUsbNoData: + if ((DataLength != NULL) && (*DataLength != 0)) { + return EFI_INVALID_PARAMETER; + } + + PktID = OUTPUT_PACKET_ID; + PtrDataSource = NULL; + DataLen = 0; + Ptr = NULL; + break; + + default: + return EFI_INVALID_PARAMETER; + } + + Status = ClearStatusReg (HcDev->PciIo, StatusReg); + if (EFI_ERROR (Status)) { + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + return EFI_DEVICE_ERROR; + } + // + // create QH structure and init + // + Status = CreateQH (HcDev, &PtrQH); + if (EFI_ERROR (Status)) { + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + return Status; + } + + // + // map the Request for bus master access. + // BusMasterRead means cpu write + // + RequestLen = sizeof (EFI_USB_DEVICE_REQUEST); + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterRead, + (UINT8 *) Request, + &RequestLen, + &TempPtr, + &RequestMapping + ); + + if (EFI_ERROR (Status)) { + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + return Status; + } + + RequestMappedAddress = (UINT8 *) ((UINTN) TempPtr); + + // + // generate Setup Stage TD + // + Status = GenSetupStageTD ( + HcDev, + DeviceAddress, + 0, + IsSlowDevice, + (UINT8 *) RequestMappedAddress, + sizeof (EFI_USB_DEVICE_REQUEST), + &PtrSetupTD + ); + + if (EFI_ERROR (Status)) { + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping); + return Status; + } + + // + // Data Stage of Control Transfer + // + DataToggle = 1; + FirstTD = TRUE; + while (DataLen > 0) { + // + // create TD structures and link together + // + + // + // PktSize is the data load size that each TD carries. + // + PktSize = (UINT8) DataLen; + if (DataLen > MaximumPacketLength) { + PktSize = MaximumPacketLength; + } + + Status = GenDataTD ( + HcDev, + DeviceAddress, + 0, + Ptr, + PktSize, + PktID, + DataToggle, + IsSlowDevice, + &PtrTD + ); + + if (EFI_ERROR (Status)) { + // + // free all resources occupied + // + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping); + DeleteQueuedTDs (HcDev, PtrSetupTD); + DeleteQueuedTDs (HcDev, PtrFirstDataTD); + return Status; + } + + // + // Link two TDs in vertical depth + // + if (FirstTD) { + PtrFirstDataTD = PtrTD; + PtrFirstDataTD->ptrNextTD = NULL; + FirstTD = FALSE; + } else { + LinkTDToTD (PtrPreTD, PtrTD); + } + + PtrPreTD = PtrTD; + + DataToggle ^= 1; + Ptr += PktSize; + DataLen -= PktSize; + } + + ptrLastDataTD = PtrTD; + + // + // Status Stage of Control Transfer + // + if (PktID == OUTPUT_PACKET_ID) { + PktID = INPUT_PACKET_ID; + } else { + PktID = OUTPUT_PACKET_ID; + } + + // + // create Status Stage TD structure + // + Status = CreateStatusTD ( + HcDev, + DeviceAddress, + 0, + PktID, + IsSlowDevice, + &PtrStatusTD + ); + + if (EFI_ERROR (Status)) { + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping); + DeleteQueuedTDs (HcDev, PtrSetupTD); + DeleteQueuedTDs (HcDev, PtrFirstDataTD); + return Status; + } + + if (IsSlowDevice) { + // + // link setup TD structures to QH structure + // + LinkTDToQH (PtrQH, PtrSetupTD); + + LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF); + + // + // link QH-TDs to total 100 frame list entry to speed up the execution. + // + for (Index = 0; Index < 100; Index++) { + LinkQHToFrameList ( + HcDev->FrameListEntry, + (UINT16) ((LoadFrameListIndex + Index) & 0x3FF), + PtrQH + ); + } + // + // Poll QH-TDs execution and get result. + // detail status is returned + // + Status = ExecuteControlTransfer ( + HcDev, + PtrSetupTD, + LoadFrameListIndex, + DataLength, + TimeOut, + TransferResult + ); + // + // Remove Control Transfer QH-TDs structure from the frame list + // and update the pointers in the Frame List + // and other pointers in other related QH structures. + // + for (Index = 0; Index < 100; Index++) { + DelLinkSingleQH ( + HcDev, + PtrQH, + (UINT16) ((LoadFrameListIndex + Index) & 0x3FF), + FALSE, + FALSE + ); + } + // + // delete setup stage TD; the QH is reserved for the next stages. + // + DeleteQueuedTDs (HcDev, PtrSetupTD); + + // + // if setup stage error, return error + // + if (EFI_ERROR (Status)) { + goto Done; + } + // + // some control transfers do not have Data Stage + // + if (PtrFirstDataTD != NULL) { + + LinkTDToQH (PtrQH, PtrFirstDataTD); + LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF); + + for (Index = 0; Index < 500; Index++) { + LinkQHToFrameList ( + HcDev->FrameListEntry, + (UINT16) ((LoadFrameListIndex + Index) & 0x3FF), + PtrQH + ); + } + + Status = ExecuteControlTransfer ( + HcDev, + PtrFirstDataTD, + LoadFrameListIndex, + DataLength, + TimeOut, + TransferResult + ); + + for (Index = 0; Index < 500; Index++) { + DelLinkSingleQH ( + HcDev, + PtrQH, + (UINT16) ((LoadFrameListIndex + Index) & 0x3FF), + FALSE, + FALSE + ); + } + // + // delete data stage TD; the QH is reserved for the next stage. + // + DeleteQueuedTDs (HcDev, PtrFirstDataTD); + } + // + // if data stage error, goto done and return error + // + if (EFI_ERROR (Status)) { + goto Done; + } + + LinkTDToQH (PtrQH, PtrStatusTD); + // + // get the frame list index that the QH-TDs will be linked to. + // + LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF); + + for (Index = 0; Index < 100; Index++) { + // + // put the QH-TDs directly or indirectly into the proper place + // in the Frame List + // + LinkQHToFrameList ( + HcDev->FrameListEntry, + (UINT16) ((LoadFrameListIndex + Index) & 0x3FF), + PtrQH + ); + } + // + // Poll QH-TDs execution and get result. + // detail status is returned + // + Status = ExecuteControlTransfer ( + HcDev, + PtrStatusTD, + LoadFrameListIndex, + DataLength, + TimeOut, + TransferResult + ); + + // + // Delete Control Transfer QH-TDs structure + // and update the pointers in the Frame List + // and other pointers in other related QH structures. + // + // TRUE means must search other framelistindex + // + for (Index = 0; Index < 100; Index++) { + DelLinkSingleQH ( + HcDev, + PtrQH, + (UINT16) ((LoadFrameListIndex + Index) & 0x3FF), + FALSE, + FALSE + ); + } + + DeleteQueuedTDs (HcDev, PtrStatusTD); + + } else { + // + // link setup stage TD with data stage TD + // + PtrPreTD = PtrSetupTD; + if (PtrFirstDataTD != NULL) { + LinkTDToTD (PtrSetupTD, PtrFirstDataTD); + PtrPreTD = ptrLastDataTD; + } + // + // link status TD with previous TD + // + LinkTDToTD (PtrPreTD, PtrStatusTD); + + // + // link QH with TD + // + LinkTDToQH (PtrQH, PtrSetupTD); + + LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF); + for (Index = 0; Index < 500; Index++) { + // + // put the QH-TDs directly or indirectly into the proper place + // in the Frame List + // + LinkQHToFrameList ( + HcDev->FrameListEntry, + (UINT16) ((LoadFrameListIndex + Index) & 0x3FF), + PtrQH + ); + } + // + // Poll QH-TDs execution and get result. + // detail status is returned + // + Status = ExecuteControlTransfer ( + HcDev, + PtrSetupTD, + LoadFrameListIndex, + DataLength, + TimeOut, + TransferResult + ); + // + // Remove Control Transfer QH-TDs structure from the frame list + // and update the pointers in the Frame List + // and other pointers in other related QH structures. + // + for (Index = 0; Index < 500; Index++) { + DelLinkSingleQH ( + HcDev, + PtrQH, + (UINT16) ((LoadFrameListIndex + Index) & 0x3FF), + FALSE, + FALSE + ); + } + + DeleteQueuedTDs (HcDev, PtrSetupTD); + } + +Done: + + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + + if (Mapping != NULL) { + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + } + + if (RequestMapping != NULL) { + HcDev->PciIo->Unmap (HcDev->PciIo, RequestMapping); + } + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (!IsStatusOK (HcDev->PciIo, StatusReg)) { + + ClearStatusReg (HcDev->PciIo, StatusReg); + *TransferResult |= EFI_USB_ERR_SYSTEM; + return EFI_DEVICE_ERROR; + } + + ClearStatusReg (HcDev->PciIo, StatusReg); + HcDev->PciIo->Flush (HcDev->PciIo); + return Status; +} + +EFI_STATUS +EFIAPI +UHCIBulkTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + Submits bulk transfer to a bulk endpoint of a USB device. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL instance. + + DeviceAddress Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress The combination of an endpoint number and an + endpoint direction of the target USB device. + Each endpoint address supports data transfer in + one direction except the control endpoint + (whose default endpoint address is 0). + It is the caller's responsibility to make sure that + the EndPointAddress represents a bulk endpoint. + + MaximumPacketLength Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + + Data A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + DataLength When input, indicates the size, in bytes, of the data buffer + specified by Data. When output, indicates the actually + transferred data size. + + DataToggle A pointer to the data toggle value. On input, it indicates + the initial data toggle value the bulk transfer should adopt; + on output, it is updated to indicate the data toggle value + of the subsequent bulk transfer. + + TimeOut Indicates the maximum time, in microseconds, which the + transfer is allowed to complete. + + TransferResult A pointer to the detailed result information of the + bulk transfer. + + Returns: + EFI_SUCCESS + The bulk transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The bulk transfer could not be submitted due to lack of resource. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The bulk transfer failed due to timeout. + EFI_DEVICE_ERROR + The bulk transfer failed due to host controller or device error. + Caller should check TranferResult for detailed error information. + +--*/ +{ + USB_HC_DEV *HcDev; + UINT32 StatusReg; + UINT32 FrameNumReg; + UINTN DataLen; + QH_STRUCT *PtrQH; + TD_STRUCT *PtrFirstTD; + TD_STRUCT *PtrTD; + TD_STRUCT *PtrPreTD; + UINT16 LoadFrameListIndex; + UINT16 SavedFrameListIndex; + UINT8 PktID; + UINT8 *PtrDataSource; + UINT8 *Ptr; + BOOLEAN IsFirstTD; + EFI_STATUS Status; + UINT32 Index; + UINT8 PktSize; + + EFI_USB_DATA_DIRECTION TransferDirection; + // + // Used to calculate how many entries are linked to the + // specified bulk transfer QH-TDs + // + UINT32 LinkTimes; + + BOOLEAN ShortPacketEnable; + EFI_PHYSICAL_ADDRESS TempPtr; + VOID *Mapping; + + HcDev = USB_HC_DEV_FROM_THIS (This); + StatusReg = (UINT32) (USBSTS); + FrameNumReg = (UINT32) (USBFRNUM); + PktID = INPUT_PACKET_ID; + PtrTD = NULL; + PtrFirstTD = NULL; + PtrPreTD = NULL; + LinkTimes = 1; + DataLen = 0; + Ptr = NULL; + ShortPacketEnable = FALSE; + Mapping = NULL; + + // + // Parameters Checking + // + + if ((DataLength == NULL) || + (Data == NULL) || + (TransferResult == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (!IsStatusOK (HcDev->PciIo, StatusReg)) { + + ClearStatusReg (HcDev->PciIo, StatusReg); + *TransferResult = EFI_USB_ERR_SYSTEM; + return EFI_DEVICE_ERROR; + } + + if (*DataLength == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((*DataToggle != 1) && (*DataToggle != 0)) { + return EFI_INVALID_PARAMETER; + } + + if (MaximumPacketLength != 8 && + MaximumPacketLength != 16 && + MaximumPacketLength != 32 && + MaximumPacketLength != 64) { + return EFI_INVALID_PARAMETER; + } + + // + // Enable the maximum packet size (64bytes) + // that can be used for full speed bandwidth reclamation + // at the end of a frame. + // + EnableMaxPacketSize (HcDev); + + Status = ClearStatusReg (HcDev->PciIo, StatusReg); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // construct QH and TD data structures, + // and link them together + // + if (EndPointAddress & 0x80) { + TransferDirection = EfiUsbDataIn; + } else { + TransferDirection = EfiUsbDataOut; + } + + switch (TransferDirection) { + + case EfiUsbDataIn: + ShortPacketEnable = TRUE; + PktID = INPUT_PACKET_ID; + PtrDataSource = Data; + DataLen = *DataLength; + + // + // BusMasterWrite means cpu read + // + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterWrite, + PtrDataSource, + &DataLen, + &TempPtr, + &Mapping + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Ptr = (UINT8 *) ((UINTN) TempPtr); + break; + + case EfiUsbDataOut: + PktID = OUTPUT_PACKET_ID; + PtrDataSource = Data; + DataLen = *DataLength; + + // + // BusMasterRead means cpu write + // + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterRead, + PtrDataSource, + &DataLen, + &TempPtr, + &Mapping + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Ptr = (UINT8 *) ((UINTN) TempPtr); + break; + + default: + return EFI_INVALID_PARAMETER; + } + + // + // create QH structure and init + // + Status = CreateQH (HcDev, &PtrQH); + if (EFI_ERROR (Status)) { + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + return Status; + } + + // + // i is used to calculate the total number of TDs. + // + Index = 0; + + IsFirstTD = TRUE; + while (DataLen > 0) { + + // + // create TD structures and link together + // + + PktSize = (UINT8) DataLen; + if (DataLen > MaximumPacketLength) { + PktSize = MaximumPacketLength; + } + + Status = GenDataTD ( + HcDev, + DeviceAddress, + EndPointAddress, + Ptr, + PktSize, + PktID, + *DataToggle, + FALSE, + &PtrTD + ); + + if (EFI_ERROR (Status)) { + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + DeleteQueuedTDs (HcDev, PtrFirstTD); + return Status; + } + + // + // Enable short packet detection. + // (default action is disabling short packet detection) + // + if (ShortPacketEnable) { + EnableorDisableTDShortPacket (PtrTD, TRUE); + } + + if (IsFirstTD) { + PtrFirstTD = PtrTD; + PtrFirstTD->ptrNextTD = NULL; + IsFirstTD = FALSE; + } else { + // + // Link two TDs in vertical depth + // + LinkTDToTD (PtrPreTD, PtrTD); + } + + Index++; + + PtrPreTD = PtrTD; + + *DataToggle ^= 1; + Ptr += PktSize; + DataLen -= PktSize; + } + + // + // link TD structures to QH structure + // + LinkTDToQH (PtrQH, PtrFirstTD); + + // + // calculate how many entries are linked to the specified bulk transfer QH-TDs + // the below values are referred to the USB spec revision1.1. + // + switch (MaximumPacketLength) { + case 8: + LinkTimes = Index / 71 + 1; + break; + + case 16: + LinkTimes = Index / 51 + 1; + break; + + case 32: + LinkTimes = Index / 33 + 1; + break; + + case 64: + LinkTimes = Index / 19 + 1; + break; + } + + LinkTimes += 500; + + // + // put QH-TDs into Frame list + // + LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF); + SavedFrameListIndex = LoadFrameListIndex; + + for (Index = 0; Index <= LinkTimes; Index++) { + + // + // put the QH-TD directly or indirectly into the proper place + // in the Frame List + // + LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH); + + LoadFrameListIndex += 1; + LoadFrameListIndex &= 0x3FF; + } + + LoadFrameListIndex = SavedFrameListIndex; + + // + // Execute QH-TD and get result + // + // + // detail status is put into the Result field in the pIRP + // the Data Toggle value is also re-updated to the value + // of the last successful TD + // + Status = ExecBulkorSyncInterruptTransfer ( + HcDev, + PtrFirstTD, + LoadFrameListIndex, + DataLength, + DataToggle, + TimeOut, + TransferResult + ); + + // + // Delete Bulk transfer QH-TD structure + // and maitain the pointers in the Frame List + // and other pointers in related QH structure + // + // TRUE means must search other framelistindex + // + for (Index = 0; Index <= LinkTimes; Index++) { + DelLinkSingleQH ( + HcDev, + PtrQH, + LoadFrameListIndex, + FALSE, + FALSE + ); + LoadFrameListIndex += 1; + LoadFrameListIndex &= 0x3FF; + } + + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + + DeleteQueuedTDs (HcDev, PtrFirstTD); + + if (Mapping != NULL) { + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + } + + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (!IsStatusOK (HcDev->PciIo, StatusReg)) { + + ClearStatusReg (HcDev->PciIo, StatusReg); + *TransferResult |= EFI_USB_ERR_SYSTEM; + return EFI_DEVICE_ERROR; + } + + ClearStatusReg (HcDev->PciIo, StatusReg); + + HcDev->PciIo->Flush (HcDev->PciIo); + + return Status; +} + +EFI_STATUS +EFIAPI +UHCIAsyncInterruptTransfer ( + IN EFI_USB_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaxiumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval, OPTIONAL + IN UINTN DataLength, OPTIONAL + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, OPTIONAL + IN VOID *Context OPTIONAL + ) +/*++ + + Routine Description: + Submits an asynchronous interrupt transfer to an + interrupt endpoint of a USB device. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL instance. + + DeviceAddress Represents the address of the target device on the USB, + which is assigned during USB enumeration. + + EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint address + supports data transfer in one direction except the + control endpoint (whose default endpoint address is 0). + It is the caller's responsibility to make sure that + the EndPointAddress represents an interrupt endpoint. + + IsSlowDevice Indicates whether the target device is slow device + or full-speed device. + + MaxiumPacketLength Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + + IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between + the host and the target interrupt endpoint. + If FALSE, the specified asynchronous interrupt pipe + is canceled. + + DataToggle A pointer to the data toggle value. On input, it is valid + when IsNewTransfer is TRUE, and it indicates the initial + data toggle value the asynchronous interrupt transfer + should adopt. + On output, it is valid when IsNewTransfer is FALSE, + and it is updated to indicate the data toggle value of + the subsequent asynchronous interrupt transfer. + + PollingInterval Indicates the interval, in milliseconds, that the + asynchronous interrupt transfer is polled. + This parameter is required when IsNewTransfer is TRUE. + + DataLength Indicates the length of data to be received at the + rate specified by PollingInterval from the target + asynchronous interrupt endpoint. This parameter + is only required when IsNewTransfer is TRUE. + + CallBackFunction The Callback function.This function is called at the + rate specified by PollingInterval.This parameter is + only required when IsNewTransfer is TRUE. + + Context The context that is passed to the CallBackFunction. + This is an optional parameter and may be NULL. + + Returns: + EFI_SUCCESS + The asynchronous interrupt transfer request has been successfully + submitted or canceled. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_OUT_OF_RESOURCES + The request could not be completed due to a lack of resources. + EFI_DEVICE_ERROR + Can't read register +--*/ +{ + USB_HC_DEV *HcDev; + UINT32 StatusReg; + UINT32 FrameNumReg; + UINTN DataLen; + QH_STRUCT *ptrFirstQH; + QH_STRUCT *PtrQH; + QH_STRUCT *ptrPreQH; + TD_STRUCT *PtrFirstTD; + TD_STRUCT *PtrTD; + TD_STRUCT *PtrPreTD; + UINT16 LoadFrameListIndex; + UINT16 Index; + UINT8 PktID; + UINT8 *Ptr; + UINT8 *MappedPtr; + BOOLEAN IsFirstTD; + BOOLEAN IsFirstQH; + EFI_STATUS Status; + BOOLEAN ShortPacketEnable; + UINT8 CurrentDataToggle; + EFI_PHYSICAL_ADDRESS TempPtr; + VOID *Mapping; + UINT8 PktSize; + QH_STRUCT *TempQH; + EFI_TPL OldTpl; + + HcDev = USB_HC_DEV_FROM_THIS (This); + StatusReg = (UINT32) (USBSTS); + FrameNumReg = (UINT32) (USBFRNUM); + Mapping = NULL; + ShortPacketEnable = FALSE; + + PktID = INPUT_PACKET_ID; + PtrTD = NULL; + PtrFirstTD = NULL; + PtrPreTD = NULL; + Ptr = NULL; + PtrQH = NULL; + ptrPreQH = NULL; + ptrFirstQH = NULL; + + if ((EndPointAddress & 0x80) == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // delete Async interrupt transfer request + // + if (!IsNewTransfer) { + + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + Status = DeleteAsyncINTQHTDs ( + HcDev, + DeviceAddress, + EndPointAddress, + DataToggle + ); + + gBS->RestoreTPL (OldTpl); + + return Status; + } + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (!IsStatusOK (HcDev->PciIo, StatusReg)) { + + ClearStatusReg (HcDev->PciIo, StatusReg); + return EFI_DEVICE_ERROR; + } + + ClearStatusReg (HcDev->PciIo, StatusReg); + + // + // submit Async interrupt transfer request + // + if (PollingInterval < 1 || PollingInterval > 255) { + return EFI_INVALID_PARAMETER; + } + + if (DataLength == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((*DataToggle != 1) && (*DataToggle != 0)) { + return EFI_INVALID_PARAMETER; + } + + ShortPacketEnable = TRUE; + PktID = INPUT_PACKET_ID; + DataLen = DataLength; + Ptr = AllocatePool (DataLen); + if (Ptr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // BusMasterWrite means cpu read + // + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterWrite, + Ptr, + &DataLen, + &TempPtr, + &Mapping + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Ptr); + return Status; + } + + MappedPtr = (UINT8 *) ((UINTN) TempPtr); + + CurrentDataToggle = *DataToggle; + + IsFirstTD = TRUE; + + while (DataLen > 0) { + // + // create TD structures and link together + // + + PktSize = (UINT8) DataLen; + if (DataLen > MaxiumPacketLength) { + PktSize = MaxiumPacketLength; + } + + Status = GenDataTD ( + HcDev, + DeviceAddress, + EndPointAddress, + MappedPtr, + PktSize, + PktID, + CurrentDataToggle, + IsSlowDevice, + &PtrTD + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Ptr); + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + DeleteQueuedTDs (HcDev, PtrFirstTD); + return Status; + } + // + // Enable short packet detection. + // + if (ShortPacketEnable) { + EnableorDisableTDShortPacket (PtrTD, TRUE); + } + + if (IsFirstTD) { + PtrFirstTD = PtrTD; + PtrFirstTD->ptrNextTD = NULL; + IsFirstTD = FALSE; + } else { + // + // Link two TDs in vertical depth + // + LinkTDToTD (PtrPreTD, PtrTD); + } + + PtrPreTD = PtrTD; + + CurrentDataToggle ^= 1; + MappedPtr += PktSize; + DataLen -= PktSize; + } + + // + // roll one value back + // + CurrentDataToggle ^= 1; + + // + // create a list of QH structures and init, + // link TDs to all the QHs, and link all the QHs together using internal + // defined pointer of the QH_STRUCT. + // + IsFirstQH = TRUE; + ptrPreQH = NULL; + for (Index = 0; Index < 1024;) { + + Status = CreateQH (HcDev, &PtrQH); + if (EFI_ERROR (Status)) { + gBS->FreePool (Ptr); + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + DeleteQueuedTDs (HcDev, PtrFirstTD); + PtrQH = ptrFirstQH; + while (PtrQH) { + TempQH = PtrQH; + PtrQH = TempQH->ptrNextIntQH; + UhciFreePool (HcDev, (UINT8 *) TempQH, sizeof (QH_STRUCT)); + } + + return Status; + } + + // + // link TD structures to QH structure + // + LinkTDToQH (PtrQH, PtrFirstTD); + + if (IsFirstQH) { + ptrFirstQH = PtrQH; + ptrFirstQH->ptrNextIntQH = NULL; + IsFirstQH = FALSE; + } else { + // + // link neighbor QH structures together + // + ptrPreQH->ptrNextIntQH = PtrQH; + } + + ptrPreQH = PtrQH; + + Index = (UINT16) (PollingInterval + Index); + } + // + // last QH in QH list should set its next QH pointer to NULL. + // + PtrQH->ptrNextIntQH = NULL; + + // + // Save QH-TD structures in Interrupt transfer list, + // for monitor interrupt transfer execution routine use. + // + InsertQHTDToINTList ( + HcDev, + ptrFirstQH, + PtrFirstTD, + DeviceAddress, + EndPointAddress, + CurrentDataToggle, + DataLength, + PollingInterval, + Mapping, + Ptr, + CallBackFunction, + Context + ); + + // + // put QHs-TDs into Frame list + // + LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF); + + PtrQH = ptrFirstQH; + + for (Index = LoadFrameListIndex; Index < (1024 + LoadFrameListIndex);) { + + // + // put the QH-TD directly or indirectly into the proper place + // in the Frame List + // + LinkQHToFrameList (HcDev->FrameListEntry, (UINT16) (Index & 0x3FF), PtrQH); + + Index = (UINT16) (PollingInterval + Index); + + PtrQH = PtrQH->ptrNextIntQH; + } + + HcDev->PciIo->Flush (HcDev->PciIo); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UHCISyncInterruptTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + Submits synchronous interrupt transfer to an interrupt endpoint + of a USB device. + + Arguments: + + This A pointer to the EFI_USB_HC_PROTOCOL instance. + + DeviceAddress Represents the address of the target device on the USB, + which is assigned during USB enumeration. + + EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. Each endpoint + address supports data transfer in one direction + except the control endpoint (whose default + endpoint address is 0). It is the caller's responsibility + to make sure that the EndPointAddress represents + an interrupt endpoint. + + IsSlowDevice Indicates whether the target device is slow device + or full-speed device. + + MaximumPacketLength Indicates the maximum packet size the target endpoint + is capable of sending or receiving. + + Data A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + + DataLength On input, the size, in bytes, of the data buffer specified + by Data. On output, the number of bytes transferred. + + DataToggle A pointer to the data toggle value. On input, it indicates + the initial data toggle value the synchronous interrupt + transfer should adopt; + on output, it is updated to indicate the data toggle value + of the subsequent synchronous interrupt transfer. + + TimeOut Indicates the maximum time, in microseconds, which the + transfer is allowed to complete. + + TransferResult A pointer to the detailed result information from + the synchronous interrupt transfer. + + Returns: + EFI_SUCCESS + The synchronous interrupt transfer was completed successfully. + EFI_OUT_OF_RESOURCES + The synchronous interrupt transfer could not be submitted due + to lack of resource. + EFI_INVALID_PARAMETER + Some parameters are invalid. + EFI_TIMEOUT + The synchronous interrupt transfer failed due to timeout. + EFI_DEVICE_ERROR + The synchronous interrupt transfer failed due to host controller + or device error. Caller should check TranferResult for detailed + error information. +--*/ +{ + USB_HC_DEV *HcDev; + UINT32 StatusReg; + UINT32 FrameNumReg; + UINTN DataLen; + QH_STRUCT *PtrQH; + TD_STRUCT *PtrFirstTD; + TD_STRUCT *PtrTD; + TD_STRUCT *PtrPreTD; + UINT16 LoadFrameListIndex; + UINT16 SavedFrameListIndex; + UINT32 Index; + UINT32 LinkTimes; + UINT8 PktID; + UINT8 *PtrDataSource; + UINT8 *Ptr; + BOOLEAN IsFirstTD; + EFI_STATUS Status; + BOOLEAN ShortPacketEnable; + EFI_PHYSICAL_ADDRESS TempPtr; + VOID *Mapping; + UINT8 PktSize; + + HcDev = USB_HC_DEV_FROM_THIS (This); + StatusReg = (UINT32) (USBSTS); + FrameNumReg = (UINT32) (USBFRNUM); + ShortPacketEnable = FALSE; + Mapping = NULL; + PktID = INPUT_PACKET_ID; + PtrTD = NULL; + PtrFirstTD = NULL; + PtrPreTD = NULL; + DataLen = 0; + Ptr = NULL; + Index = 0; + LinkTimes = 0; + + // + // Parameters Checking + // + + if ((DataLength == NULL) || + (Data == NULL) || + (TransferResult == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (!IsStatusOK (HcDev->PciIo, StatusReg)) { + + ClearStatusReg (HcDev->PciIo, StatusReg); + *TransferResult = EFI_USB_ERR_SYSTEM; + return EFI_DEVICE_ERROR; + } + + if ((EndPointAddress & 0x80) == 0) { + return EFI_INVALID_PARAMETER; + } + + if (*DataLength == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((*DataToggle != 1) && (*DataToggle != 0)) { + return EFI_INVALID_PARAMETER; + } + + if (MaximumPacketLength > 64) { + return EFI_INVALID_PARAMETER; + } + + if (IsSlowDevice && (MaximumPacketLength > 8)) { + return EFI_INVALID_PARAMETER; + } + + ClearStatusReg (HcDev->PciIo, StatusReg); + + // + // submit Sync interrupt transfer request + // + ShortPacketEnable = TRUE; + PktID = INPUT_PACKET_ID; + DataLen = *DataLength; + PtrDataSource = Data; + + // + // create QH structure and init + // + Status = CreateQH (HcDev, &PtrQH); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // BusMasterWrite means cpu read + // + Status = HcDev->PciIo->Map ( + HcDev->PciIo, + EfiPciIoOperationBusMasterWrite, + PtrDataSource, + &DataLen, + &TempPtr, + &Mapping + ); + if (EFI_ERROR (Status)) { + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + return Status; + } + + Ptr = (UINT8 *) ((UINTN) TempPtr); + + IsFirstTD = TRUE; + while (DataLen > 0) { + // + // create TD structures and link together + // + PktSize = (UINT8) DataLen; + if (DataLen > MaximumPacketLength) { + PktSize = MaximumPacketLength; + } + + Status = GenDataTD ( + HcDev, + DeviceAddress, + EndPointAddress, + Ptr, + PktSize, + PktID, + *DataToggle, + IsSlowDevice, + &PtrTD + ); + if (EFI_ERROR (Status)) { + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + DeleteQueuedTDs (HcDev, PtrFirstTD); + return Status; + } + // + // Enable short packet detection. + // + if (ShortPacketEnable) { + EnableorDisableTDShortPacket (PtrTD, TRUE); + } + + if (IsFirstTD) { + PtrFirstTD = PtrTD; + PtrFirstTD->ptrNextTD = NULL; + IsFirstTD = FALSE; + } else { + // + // Link two TDs in vertical depth + // + LinkTDToTD (PtrPreTD, PtrTD); + } + + Index++; + + PtrPreTD = PtrTD; + + *DataToggle ^= 1; + Ptr += PktSize; + DataLen -= PktSize; + } + + // + // link TD structures to QH structure + // + LinkTDToQH (PtrQH, PtrFirstTD); + + switch (MaximumPacketLength) { + case 8: + LinkTimes = Index / 71 + 1; + break; + + case 16: + LinkTimes = Index / 51 + 1; + break; + + case 32: + LinkTimes = Index / 33 + 1; + break; + + case 64: + LinkTimes = Index / 19 + 1; + break; + } + + LinkTimes += 100; + + LoadFrameListIndex = (UINT16) ((GetCurrentFrameNumber (HcDev->PciIo, FrameNumReg)) & 0x3FF); + SavedFrameListIndex = LoadFrameListIndex; + + for (Index = 0; Index < LinkTimes; Index++) { + + // + // put the QH-TD directly or indirectly into the proper place + // in the Frame List + // + LinkQHToFrameList (HcDev->FrameListEntry, LoadFrameListIndex, PtrQH); + + LoadFrameListIndex += 1; + LoadFrameListIndex &= 0x3FF; + } + + LoadFrameListIndex = SavedFrameListIndex; + // + // detail status is put into the Result field in the pIRP + // the Data Toggle value is also re-updated to the value + // of the last successful TD + // + Status = ExecBulkorSyncInterruptTransfer ( + HcDev, + PtrFirstTD, + LoadFrameListIndex, + DataLength, + DataToggle, + TimeOut, + TransferResult + ); + // + // Delete Sync Interrupt transfer QH-TD structure + // and maintain the pointers in the Frame List + // and other pointers in related QH structure + // + // TRUE means must search other framelistindex + // + for (Index = 0; Index <= LinkTimes; Index++) { + DelLinkSingleQH ( + HcDev, + PtrQH, + LoadFrameListIndex, + FALSE, + FALSE + ); + LoadFrameListIndex += 1; + LoadFrameListIndex &= 0x3FF; + } + + UhciFreePool (HcDev, (UINT8 *) PtrQH, sizeof (QH_STRUCT)); + + DeleteQueuedTDs (HcDev, PtrFirstTD); + + HcDev->PciIo->Unmap (HcDev->PciIo, Mapping); + + // + // if has errors that cause host controller halt, + // then return EFI_DEVICE_ERROR directly. + // + if (!IsStatusOK (HcDev->PciIo, StatusReg)) { + + ClearStatusReg (HcDev->PciIo, StatusReg); + *TransferResult |= EFI_USB_ERR_SYSTEM; + return EFI_DEVICE_ERROR; + } + + ClearStatusReg (HcDev->PciIo, StatusReg); + + HcDev->PciIo->Flush (HcDev->PciIo); + + return Status; +} + +EFI_STATUS +EFIAPI +UHCIIsochronousTransfer ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN UINTN DataLength, + OUT UINT32 *TransferResult + ) +/*++ + + Routine Description: + Submits isochronous transfer to a target USB device. + + Arguments: + + This - A pointer to the EFI_USB_HC_PROTOCOL instance. + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + EndPointAddress - End point address + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + DataLength - Indicates the size, in bytes, of the data buffer + specified by Data. + TransferResult - A pointer to the detailed result information generated + by this control transfer. + Returns: + EFI_UNSUPPORTED + +--*/ +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +UHCIAsyncIsochronousTransfer ( + IN EFI_USB_HC_PROTOCOL * This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ) +/*++ + + Routine Description: + Submits Async isochronous transfer to a target USB device. + + Arguments: + + This - A pointer to the EFI_USB_HC_PROTOCOL instance. + + DeviceAddress - Represents the address of the target device on the USB, + which is assigned during USB enumeration. + + EndPointAddress - End point address + + MaximumPacketLength - Indicates the maximum packet size that the + default control transfer endpoint is capable of + sending or receiving. + + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + + IsochronousCallBack - When the transfer complete, the call back function will be called + + Context - Pass to the call back function as parameter + + Returns: + EFI_UNSUPPORTED + +--*/ +{ + return EFI_UNSUPPORTED; +} + +VOID +EFIAPI +MonitorInterruptTrans ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + Routine Description: + Interrupt transfer periodic check handler + Arguments: + Event - Interrupt event + Contex - Pointer to USB_HC_DEV + Returns: + None +--*/ +{ + + USB_HC_DEV *HcDev; + INTERRUPT_LIST *PtrList; + LIST_ENTRY *Link; + UINT32 Result; + VOID *DataBuffer; + UINTN DataLen; + UINTN ActualLen; + UINTN ErrTDPos; + UINT32 StatusAddr; + LIST_ENTRY *NextLink; + + HcDev = (USB_HC_DEV *) Context; + StatusAddr = (UINT32) (USBSTS); + + // + // interrupt transfer list is empty, means that no interrupt transfer + // is submitted by far. + // + if (IsListEmpty (&(HcDev->InterruptListHead))) { + return ; + } + + NextLink = HcDev->InterruptListHead.ForwardLink; + do { + + Link = NextLink; + NextLink = Link->ForwardLink; + + PtrList = INTERRUPT_LIST_FROM_LINK (Link); + + // + // get TD execution results. + // ErrTDPos is zero-based value indicating the first error TD's position + // in the TDs' list. + // This value is only valid when Result not equal NOERROR. + // + ExecuteAsyncINTTDs ( + HcDev, + PtrList, + &Result, + &ErrTDPos, + &ActualLen + ); + + // + // interrupt transfer has not been executed yet. + // + if (((Result & EFI_USB_ERR_NAK) == EFI_USB_ERR_NAK) || + ((Result & EFI_USB_ERR_NOTEXECUTE) == EFI_USB_ERR_NOTEXECUTE)) { + continue; + } + // + // get actual data length transferred data and its data length. + // + DataLen = ActualLen; + DataBuffer = AllocatePool (DataLen); + if (DataBuffer == NULL) { + return ; + } + + CopyMem ( + DataBuffer, + PtrList->PtrFirstTD->pTDBuffer, + DataLen + ); + + // + // only if interrupt endpoint responds + // and the interrupt transfer stops because of completion + // or error, then we will call callback function. + // + if (Result == EFI_USB_NOERROR) { + // + // add for real platform debug + // + if (PtrList->InterruptCallBack != NULL) { + (PtrList->InterruptCallBack) ( + DataBuffer, + DataLen, + PtrList->InterruptContext, + Result + ); + } + + if (DataBuffer) { + gBS->FreePool (DataBuffer); + } + + // + // update should done after data buffer got. + // + UpdateAsyncINTQHTDs (PtrList, Result, (UINT32) ErrTDPos); + + } else { + + DEBUG ((EFI_D_ERROR, "interrupt transfer error code is %x\n", Result)); + + if (DataBuffer) { + gBS->FreePool (DataBuffer); + } + // + // leave error recovery to its related device driver. + // A common case of the error recovery is to re-submit the interrupt + // transfer. + // When an interrupt transfer is re-submitted, its position in the linked + // list is changed. It is inserted to the head of the linked list, while + // this function scans the whole list from head to tail. Thus, the + // re-submitted interrupt transfer's callback function will not be called + // again in this round. + // + if (PtrList->InterruptCallBack != NULL) { + (PtrList->InterruptCallBack) ( + NULL, + 0, + PtrList->InterruptContext, + Result + ); + } + } + } while (NextLink != &(HcDev->InterruptListHead)); + +} diff --git a/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h new file mode 100644 index 0000000000..93da46c9ca --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Uhci/Dxe/uhci.h @@ -0,0 +1,1187 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Uhci.h + +Abstract: + + +Revision History +--*/ + +#ifndef _UHCI_H +#define _UHCI_H + +/* + * Universal Host Controller Interface data structures and defines + */ + +#include + +#define EFI_D_UHCI EFI_D_INFO + +// +// stall time +// +#define STALL_1_MILLI_SECOND 1000 +#define STALL_1_SECOND 1000 * STALL_1_MILLI_SECOND + +#define FORCE_GLOBAL_RESUME_TIME 20 * STALL_1_MILLI_SECOND + +#define ROOT_PORT_REST_TIME 50 * STALL_1_MILLI_SECOND + +#define PORT_RESET_RECOVERY_TIME 10 * STALL_1_MILLI_SECOND + +// +// 50 ms +// +#define INTERRUPT_POLLING_TIME 50 * 1000 * 10 + +// +// UHCI IO Space Address Register Register locates at +// offset 20 ~ 23h of PCI Configuration Space (UHCI spec, Revision 1.1), +// so, its BAR Index is 4. +// +#define USB_BAR_INDEX 4 + +// +// One memory block uses 1 page (common buffer for QH,TD use.) +// +#define NORMAL_MEMORY_BLOCK_UNIT_IN_PAGES 1 + + +#define bit(a) 1 << (a) + +// +// //////////////////////////////////////////////////////////////////////// +// +// Universal Host Controller Registers Definitions +// +////////////////////////////////////////////////////////////////////////// +extern UINT16 USBBaseAddr; + +/* Command register */ +#define USBCMD 0 /* Command Register Offset 00-01h */ +#define USBCMD_RS bit (0) /* Run/Stop */ +#define USBCMD_HCRESET bit (1) /* Host reset */ +#define USBCMD_GRESET bit (2) /* Global reset */ +#define USBCMD_EGSM bit (3) /* Global Suspend Mode */ +#define USBCMD_FGR bit (4) /* Force Global Resume */ +#define USBCMD_SWDBG bit (5) /* SW Debug mode */ +#define USBCMD_CF bit (6) /* Config Flag (sw only) */ +#define USBCMD_MAXP bit (7) /* Max Packet (0 = 32, 1 = 64) */ + +/* Status register */ +#define USBSTS 2 /* Status Register Offset 02-03h */ +#define USBSTS_USBINT bit (0) /* Interrupt due to IOC */ +#define USBSTS_ERROR bit (1) /* Interrupt due to error */ +#define USBSTS_RD bit (2) /* Resume Detect */ +#define USBSTS_HSE bit (3) /* Host System Error*/ +#define USBSTS_HCPE bit (4) /* Host Controller Process Error*/ +#define USBSTS_HCH bit (5) /* HC Halted */ + +/* Interrupt enable register */ +#define USBINTR 4 /* Interrupt Enable Register 04-05h */ +#define USBINTR_TIMEOUT bit (0) /* Timeout/CRC error enable */ +#define USBINTR_RESUME bit (1) /* Resume interrupt enable */ +#define USBINTR_IOC bit (2) /* Interrupt On Complete enable */ +#define USBINTR_SP bit (3) /* Short packet interrupt enable */ + +/* Frame Number Register Offset 06-08h */ +#define USBFRNUM 6 + +/* Frame List Base Address Register Offset 08-0Bh */ +#define USBFLBASEADD 8 + +/* Start of Frame Modify Register Offset 0Ch */ +#define USBSOF 0x0c + +/* USB port status and control registers */ +#define USBPORTSC1 0x10 /*Port 1 offset 10-11h */ +#define USBPORTSC2 0x12 /*Port 2 offset 12-13h */ + +#define USBPORTSC_CCS bit (0) /* Current Connect Status*/ +#define USBPORTSC_CSC bit (1) /* Connect Status Change */ +#define USBPORTSC_PED bit (2) /* Port Enable / Disable */ +#define USBPORTSC_PEDC bit (3) /* Port Enable / Disable Change */ +#define USBPORTSC_LSL bit (4) /* Line Status Low bit*/ +#define USBPORTSC_LSH bit (5) /* Line Status High bit*/ +#define USBPORTSC_RD bit (6) /* Resume Detect */ +#define USBPORTSC_LSDA bit (8) /* Low Speed Device Attached */ +#define USBPORTSC_PR bit (9) /* Port Reset */ +#define USBPORTSC_SUSP bit (12) /* Suspend */ + +/* PCI Configuration Registers for USB */ + +// +// Class Code Register offset +// +#define CLASSC 0x09 +// +// USB IO Space Base Address Register offset +// +#define USBBASE 0x20 + +// +// USB legacy Support +// +#define USB_EMULATION 0xc0 + +// +// USB Base Class Code,Sub-Class Code and Programming Interface. +// +#define PCI_CLASSC_PI_UHCI 0x00 + +#define SETUP_PACKET_ID 0x2D +#define INPUT_PACKET_ID 0x69 +#define OUTPUT_PACKET_ID 0xE1 +#define ERROR_PACKET_ID 0x55 + +// +// //////////////////////////////////////////////////////////////////////// +// +// USB Transfer Mechanism Data Structures +// +////////////////////////////////////////////////////////////////////////// +#pragma pack(1) +// +// USB Class Code structure +// +typedef struct { + UINT8 PI; + UINT8 SubClassCode; + UINT8 BaseCode; +} USB_CLASSC; + +typedef struct { + UINT32 QHHorizontalTerminate : 1; + UINT32 QHHorizontalQSelect : 1; + UINT32 QHHorizontalRsvd : 2; + UINT32 QHHorizontalPtr : 28; + UINT32 QHVerticalTerminate : 1; + UINT32 QHVerticalQSelect : 1; + UINT32 QHVerticalRsvd : 2; + UINT32 QHVerticalPtr : 28; +} QUEUE_HEAD; + +typedef struct { + UINT32 TDLinkPtrTerminate : 1; + UINT32 TDLinkPtrQSelect : 1; + UINT32 TDLinkPtrDepthSelect : 1; + UINT32 TDLinkPtrRsvd : 1; + UINT32 TDLinkPtr : 28; + UINT32 TDStatusActualLength : 11; + UINT32 TDStatusRsvd : 5; + UINT32 TDStatus : 8; + UINT32 TDStatusIOC : 1; + UINT32 TDStatusIOS : 1; + UINT32 TDStatusLS : 1; + UINT32 TDStatusErr : 2; + UINT32 TDStatusSPD : 1; + UINT32 TDStatusRsvd2 : 2; + UINT32 TDTokenPID : 8; + UINT32 TDTokenDevAddr : 7; + UINT32 TDTokenEndPt : 4; + UINT32 TDTokenDataToggle : 1; + UINT32 TDTokenRsvd : 1; + UINT32 TDTokenMaxLen : 11; + UINT32 TDBufferPtr; +} TD; + +#pragma pack() + +typedef struct { + QUEUE_HEAD QH; + VOID *ptrNext; + VOID *ptrDown; + VOID *ptrNextIntQH; // for interrupt transfer's special use + VOID *LoopPtr; +} QH_STRUCT; + +typedef struct { + TD TDData; + UINT8 *pTDBuffer; + VOID *ptrNextTD; + VOID *ptrNextQH; + UINT16 TDBufferLength; + UINT16 reserved; +} TD_STRUCT; + +// +// //////////////////////////////////////////////////////////////////////// +// +// Universal Host Controller Device Data Structure +// +////////////////////////////////////////////////////////////////////////// +#define USB_HC_DEV_FROM_THIS(a) CR (a, USB_HC_DEV, UsbHc, USB_HC_DEV_SIGNATURE) + +#define USB_HC_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'h', 'c', 'i') +#define INTERRUPT_LIST_SIGNATURE EFI_SIGNATURE_32 ('i', 'n', 't', 's') +typedef struct { + UINTN Signature; + + LIST_ENTRY Link; + UINT8 DevAddr; + UINT8 EndPoint; + UINT8 DataToggle; + UINT8 Reserved[5]; + TD_STRUCT *PtrFirstTD; + QH_STRUCT *PtrQH; + UINTN DataLen; + UINTN PollInterval; + VOID *Mapping; + UINT8 *DataBuffer; // allocated host memory, not mapped memory + EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack; + VOID *InterruptContext; +} INTERRUPT_LIST; + +#define INTERRUPT_LIST_FROM_LINK(a) CR (a, INTERRUPT_LIST, Link, INTERRUPT_LIST_SIGNATURE) + +typedef struct { + UINT32 FrameListPtrTerminate : 1; + UINT32 FrameListPtrQSelect : 1; + UINT32 FrameListRsvd : 2; + UINT32 FrameListPtr : 28; + +} FRAMELIST_ENTRY; + +typedef struct _MEMORY_MANAGE_HEADER { + UINT8 *BitArrayPtr; + UINTN BitArraySizeInBytes; + UINT8 *MemoryBlockPtr; + UINTN MemoryBlockSizeInBytes; + VOID *Mapping; + struct _MEMORY_MANAGE_HEADER *Next; +} MEMORY_MANAGE_HEADER; + +typedef struct { + UINTN Signature; + EFI_USB_HC_PROTOCOL UsbHc; + EFI_PCI_IO_PROTOCOL *PciIo; + + // + // local data + // + LIST_ENTRY InterruptListHead; + FRAMELIST_ENTRY *FrameListEntry; + VOID *FrameListMapping; + MEMORY_MANAGE_HEADER *MemoryHeader; + EFI_EVENT InterruptTransTimer; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + +} USB_HC_DEV; + +extern EFI_DRIVER_BINDING_PROTOCOL gUhciDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gUhciComponentName; + +EFI_STATUS +WriteUHCCommandReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 CmdAddrOffset, + IN UINT16 UsbCmd + ); + +EFI_STATUS +ReadUHCCommandReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 CmdAddrOffset, + IN OUT UINT16 *Data + ); + +EFI_STATUS +WriteUHCStatusReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusAddrOffset, + IN UINT16 UsbSts + ); + +EFI_STATUS +ReadUHCStatusReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusAddrOffset, + IN OUT UINT16 *Data + ); + +EFI_STATUS +ClearStatusReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusAddrOffset + ); + +EFI_STATUS +ReadUHCFrameNumberReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 FrameNumAddrOffset, + IN OUT UINT16 *Data + ); + +EFI_STATUS +WriteUHCFrameListBaseReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 FlBaseAddrOffset, + IN UINT32 UsbFrameListBaseAddr + ); + +EFI_STATUS +ReadRootPortReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 PortAddrOffset, + IN OUT UINT16 *Data + ); + +EFI_STATUS +WriteRootPortReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 PortAddrOffset, + IN UINT16 ControlBits + ); + +EFI_STATUS +WaitForUHCHalt ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusRegAddr, + IN UINTN Timeout + ); + +BOOLEAN +IsStatusOK ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusRegAddr + ); + +BOOLEAN +IsHostSysOrProcessErr ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 StatusRegAddr + ); + +// +// This routine programs the USB frame number register. We assume that the +// HC schedule execution is stopped. +// +EFI_STATUS +SetFrameNumberReg ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 FRNUMAddr, + IN UINT16 Index + ); + +UINT16 +GetCurrentFrameNumber ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 FRNUMAddr + ); + +EFI_STATUS +SetFrameListBaseAddress ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 FLBASEADDRReg, + IN UINT32 Addr + ); + +UINT32 +GetFrameListBaseAddress ( + IN EFI_PCI_IO_PROTOCOL *PciIo, + IN UINT32 FLBAddr + ); + +EFI_STATUS +CreateFrameList ( + IN USB_HC_DEV *HcDev, + IN UINT32 FLBASEADDRReg + ); + +EFI_STATUS +FreeFrameListEntry ( + IN USB_HC_DEV *UhcDev + ); + +VOID +InitFrameList ( + IN USB_HC_DEV *HcDev + ); + + +EFI_STATUS +CreateQH ( + IN USB_HC_DEV *HcDev, + OUT QH_STRUCT **pptrQH + ); + +VOID +SetQHHorizontalLinkPtr ( + IN QH_STRUCT *ptrQH, + IN VOID *ptrNext + ); + +VOID * +GetQHHorizontalLinkPtr ( + IN QH_STRUCT *ptrQH + ); + +VOID +SetQHHorizontalQHorTDSelect ( + IN QH_STRUCT *ptrQH, + IN BOOLEAN bQH + ); + +VOID +SetQHHorizontalValidorInvalid ( + IN QH_STRUCT *ptrQH, + IN BOOLEAN bValid + ); + +VOID +SetQHVerticalLinkPtr ( + IN QH_STRUCT *ptrQH, + IN VOID *ptrNext + ); + +VOID * +GetQHVerticalLinkPtr ( + IN QH_STRUCT *ptrQH + ); + +VOID +SetQHVerticalQHorTDSelect ( + IN QH_STRUCT *ptrQH, + IN BOOLEAN bQH + ); + +BOOLEAN +IsQHHorizontalQHSelect ( + IN QH_STRUCT *ptrQH + ); + +VOID +SetQHVerticalValidorInvalid ( + IN QH_STRUCT *ptrQH, + IN BOOLEAN bValid + ); + +BOOLEAN +GetQHVerticalValidorInvalid ( + IN QH_STRUCT *ptrQH + ); + +EFI_STATUS +AllocateTDStruct ( + IN USB_HC_DEV *HcDev, + OUT TD_STRUCT **ppTDStruct + ); +/*++ + +Routine Description: + + Allocate TD Struct + +Arguments: + + HcDev - USB_HC_DEV + ppTDStruct - place to store TD_STRUCT pointer +Returns: + + EFI_SUCCESS + +--*/ + +EFI_STATUS +CreateTD ( + IN USB_HC_DEV *HcDev, + OUT TD_STRUCT **pptrTD + ); +/*++ + +Routine Description: + + Create TD + +Arguments: + + HcDev - USB_HC_DEV + pptrTD - TD_STRUCT pointer to store + +Returns: + + EFI_OUT_OF_RESOURCES - Can't allocate resources + EFI_SUCCESS - Success + +--*/ + + +EFI_STATUS +GenSetupStageTD ( + IN USB_HC_DEV *HcDev, + IN UINT8 DevAddr, + IN UINT8 Endpoint, + IN BOOLEAN bSlow, + IN UINT8 *pDevReq, + IN UINT8 RequestLen, + OUT TD_STRUCT **ppTD + ); +/*++ + +Routine Description: + + Generate Setup Stage TD + +Arguments: + + HcDev - USB_HC_DEV + DevAddr - Device address + Endpoint - Endpoint number + bSlow - Full speed or low speed + pDevReq - Device request + RequestLen - Request length + ppTD - TD_STRUCT to return +Returns: + + EFI_OUT_OF_RESOURCES - Can't allocate memory + EFI_SUCCESS - Success + +--*/ + +EFI_STATUS +GenDataTD ( + IN USB_HC_DEV *HcDev, + IN UINT8 DevAddr, + IN UINT8 Endpoint, + IN UINT8 *pData, + IN UINT8 Len, + IN UINT8 PktID, + IN UINT8 Toggle, + IN BOOLEAN bSlow, + OUT TD_STRUCT **ppTD + ); +/*++ + +Routine Description: + + Generate Data Stage TD + +Arguments: + + HcDev - USB_HC_DEV + DevAddr - Device address + Endpoint - Endpoint number + pData - Data buffer + Len - Data length + PktID - Packet ID + Toggle - Data toggle value + bSlow - Full speed or low speed + ppTD - TD_STRUCT to return +Returns: + + EFI_OUT_OF_RESOURCES - Can't allocate memory + EFI_SUCCESS - Success + +--*/ + +EFI_STATUS +CreateStatusTD ( + IN USB_HC_DEV *HcDev, + IN UINT8 DevAddr, + IN UINT8 Endpoint, + IN UINT8 PktID, + IN BOOLEAN bSlow, + OUT TD_STRUCT **ppTD + ); +/*++ + +Routine Description: + + Generate Setup Stage TD + +Arguments: + + HcDev - USB_HC_DEV + DevAddr - Device address + Endpoint - Endpoint number + bSlow - Full speed or low speed + pDevReq - Device request + RequestLen - Request length + ppTD - TD_STRUCT to return +Returns: + + EFI_OUT_OF_RESOURCES - Can't allocate memory + EFI_SUCCESS - Success + +--*/ + +VOID +SetTDLinkPtrValidorInvalid ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bValid + ); + +VOID +SetTDLinkPtrQHorTDSelect ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bQH + ); + +VOID +SetTDLinkPtrDepthorBreadth ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bDepth + ); + +VOID +SetTDLinkPtr ( + IN TD_STRUCT *ptrTDStruct, + IN VOID *ptrNext + ); + +VOID * +GetTDLinkPtr ( + IN TD_STRUCT *ptrTDStruct + ); + +VOID +EnableorDisableTDShortPacket ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bEnable + ); + +VOID +SetTDControlErrorCounter ( + IN TD_STRUCT *ptrTDStruct, + IN UINT8 nMaxErrors + ); + +VOID +SetTDLoworFullSpeedDevice ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bLowSpeedDevice + ); + +VOID +SetTDControlIsochronousorNot ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bIsochronous + ); + +VOID +SetorClearTDControlIOC ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bSet + ); + +VOID +SetTDStatusActiveorInactive ( + IN TD_STRUCT *ptrTDStruct, + IN BOOLEAN bActive + ); + +UINT16 +SetTDTokenMaxLength ( + IN TD_STRUCT *ptrTDStruct, + IN UINT16 nMaxLen + ); + +VOID +SetTDTokenDataToggle1 ( + IN TD_STRUCT *ptrTDStruct + ); + +VOID +SetTDTokenDataToggle0 ( + IN TD_STRUCT *ptrTDStruct + ); + +UINT8 +GetTDTokenDataToggle ( + IN TD_STRUCT *ptrTDStruct + ); + +VOID +SetTDTokenEndPoint ( + IN TD_STRUCT *ptrTDStruct, + IN UINTN nEndPoint + ); + +VOID +SetTDTokenDeviceAddress ( + IN TD_STRUCT *ptrTDStruct, + IN UINTN nDevAddr + ); + +VOID +SetTDTokenPacketID ( + IN TD_STRUCT *ptrTDStruct, + IN UINT8 nPID + ); + +VOID +SetTDDataBuffer ( + IN TD_STRUCT *ptrTDStruct + ); + +BOOLEAN +IsTDStatusActive ( + IN TD_STRUCT *ptrTDStruct + ); + +BOOLEAN +IsTDStatusStalled ( + IN TD_STRUCT *ptrTDStruct + ); + +BOOLEAN +IsTDStatusBufferError ( + IN TD_STRUCT *ptrTDStruct + ); + +BOOLEAN +IsTDStatusBabbleError ( + IN TD_STRUCT *ptrTDStruct + ); + +BOOLEAN +IsTDStatusNAKReceived ( + IN TD_STRUCT *ptrTDStruct + ); + +BOOLEAN +IsTDStatusCRCTimeOutError ( + IN TD_STRUCT *ptrTDStruct + ); + +BOOLEAN +IsTDStatusBitStuffError ( + IN TD_STRUCT *ptrTDStruct + ); + +UINT16 +GetTDStatusActualLength ( + IN TD_STRUCT *ptrTDStruct + ); + +UINT16 +GetTDTokenMaxLength ( + IN TD_STRUCT *ptrTDStruct + ); + +UINT8 +GetTDTokenEndPoint ( + IN TD_STRUCT *ptrTDStruct + ); + +UINT8 +GetTDTokenDeviceAddress ( + IN TD_STRUCT *ptrTDStruct + ); + +UINT8 +GetTDTokenPacketID ( + IN TD_STRUCT *ptrTDStruct + ); + +UINT8 * +GetTDDataBuffer ( + IN TD_STRUCT *ptrTDStruct + ); + +BOOLEAN +GetTDLinkPtrValidorInvalid ( + IN TD_STRUCT *ptrTDStruct + ); + +UINTN +CountTDsNumber ( + IN TD_STRUCT *ptrFirstTD + ); + +VOID +LinkTDToQH ( + IN QH_STRUCT *ptrQH, + IN TD_STRUCT *ptrTD + ); + +VOID +LinkTDToTD ( + IN TD_STRUCT *ptrPreTD, + IN TD_STRUCT *ptrTD + ); + +VOID +SetorClearCurFrameListTerminate ( + IN FRAMELIST_ENTRY *pCurEntry, + IN BOOLEAN bSet + ); + +VOID +SetCurFrameListQHorTD ( + IN FRAMELIST_ENTRY *pCurEntry, + IN BOOLEAN bQH + ); + +BOOLEAN +GetCurFrameListTerminate ( + IN FRAMELIST_ENTRY *pCurEntry + ); + +VOID +SetCurFrameListPointer ( + IN FRAMELIST_ENTRY *pCurEntry, + IN UINT8 *ptr + ); + +VOID * +GetCurFrameListPointer ( + IN FRAMELIST_ENTRY *pCurEntry + ); + +VOID +LinkQHToFrameList ( + IN FRAMELIST_ENTRY *pEntry, + IN UINT16 FrameListIndex, + IN QH_STRUCT *ptrQH + ); +/*++ + +Routine Description: + + Link QH To Frame List + +Arguments: + + pEntry - FRAMELIST_ENTRY + FrameListIndex - Frame List Index + PtrQH - QH to link +Returns: + + VOID + +--*/ +VOID +DeleteQHTDs ( + IN FRAMELIST_ENTRY *pEntry, + IN QH_STRUCT *ptrQH, + IN TD_STRUCT *ptrFirstTD, + IN UINT16 FrameListIndex, + IN BOOLEAN SearchOther + ); + +VOID +DelLinkSingleQH ( + IN USB_HC_DEV *HcDev, + IN QH_STRUCT *ptrQH, + IN UINT16 FrameListIndex, + IN BOOLEAN SearchOther, + IN BOOLEAN Delete + ); + +VOID +DeleteQueuedTDs ( + IN USB_HC_DEV *HcDev, + IN TD_STRUCT *ptrFirstTD + ); + +VOID +InsertQHTDToINTList ( + IN USB_HC_DEV *HcDev, + IN QH_STRUCT *ptrQH, + IN TD_STRUCT *ptrFirstTD, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DataToggle, + IN UINTN DataLength, + IN UINTN PollingInterval, + IN VOID *Mapping, + IN UINT8 *DataBuffer, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction, + IN VOID *Context + ); +/*++ +Routine Description: + Insert QH and TD To Interrupt List +Arguments: + + HcDev - USB_HC_DEV + PtrQH - QH_STRUCT + PtrFirstTD - First TD_STRUCT + DeviceAddress - Device Address + EndPointAddress - EndPoint Address + DataToggle - Data Toggle + DataLength - Data length + PollingInterval - Polling Interval when inserted to frame list + Mapping - Mapping alue + DataBuffer - Data buffer + CallBackFunction- CallBackFunction after interrupt transfeer + Context - CallBackFunction Context passed as function parameter +Returns: + EFI_SUCCESS - Sucess + EFI_INVALID_PARAMETER - Paremeter is error + +--*/ + +EFI_STATUS +DeleteAsyncINTQHTDs ( + IN USB_HC_DEV *HcDev, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + OUT UINT8 *DataToggle + ); +/*++ +Routine Description: + + Delete Async INT QH and TDs +Arguments: + + HcDev - USB_HC_DEV + DeviceAddress - Device Address + EndPointAddress - EndPoint Address + DataToggle - Data Toggle + +Returns: + EFI_SUCCESS - Sucess + EFI_INVALID_PARAMETER - Paremeter is error + +--*/ +BOOLEAN +CheckTDsResults ( + IN TD_STRUCT *ptrTD, + IN UINTN RequiredLen, + OUT UINT32 *Result, + OUT UINTN *ErrTDPos, + OUT UINTN *ActualTransferSize + ); +/*++ + +Routine Description: + + Check TDs Results + +Arguments: + + PtrTD - TD_STRUCT to check + RequiredLen - Required Len + Result - Transfer result + ErrTDPos - Error TD Position + ActualTransferSize - Actual Transfer Size + +Returns: + + TRUE - Sucess + FALSE - Fail + +--*/ +VOID +ExecuteAsyncINTTDs ( + IN USB_HC_DEV *HcDev, + IN INTERRUPT_LIST *ptrList, + OUT UINT32 *Result, + OUT UINTN *ErrTDPos, + OUT UINTN *ActualLen + ) ; +/*++ + +Routine Description: + + Execute Async Interrupt TDs + +Arguments: + + HcDev - USB_HC_DEV + PtrList - INTERRUPT_LIST + Result - Transfer result + ErrTDPos - Error TD Position + ActualTransferSize - Actual Transfer Size + +Returns: + + VOID + +--*/ +VOID +UpdateAsyncINTQHTDs ( + IN INTERRUPT_LIST *ptrList, + IN UINT32 Result, + IN UINT32 ErrTDPos + ); +/*++ + +Routine Description: + + Update Async Interrupt QH and TDs + +Arguments: + + PtrList - INTERRUPT_LIST + Result - Transfer reslut + ErrTDPos - Error TD Position + +Returns: + + VOID + +--*/ +VOID +ReleaseInterruptList ( + IN USB_HC_DEV *HcDev, + IN LIST_ENTRY *ListHead + ); +/*++ + +Routine Description: + + Release Interrupt List +Arguments: + + HcDev - USB_HC_DEV + ListHead - List head + +Returns: + + VOID + +--*/ +EFI_STATUS +ExecuteControlTransfer ( + IN USB_HC_DEV *HcDev, + IN TD_STRUCT *ptrTD, + IN UINT32 wIndex, + OUT UINTN *ActualLen, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); +/*++ + +Routine Description: + + Execute Control Transfer + +Arguments: + + HcDev - USB_HC_DEV + PtrTD - TD_STRUCT + wIndex - No use + ActualLen - Actual transfered Len + TimeOut - TimeOut value in milliseconds + TransferResult - Transfer result +Returns: + + EFI_SUCCESS - Sucess + EFI_DEVICE_ERROR - Error + + +--*/ +EFI_STATUS +ExecBulkorSyncInterruptTransfer ( + IN USB_HC_DEV *HcDev, + IN TD_STRUCT *ptrTD, + IN UINT32 wIndex, + OUT UINTN *ActualLen, + OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); +/*++ + +Routine Description: + + Execute Bulk or SyncInterrupt Transfer + +Arguments: + + HcDev - USB_HC_DEV + PtrTD - TD_STRUCT + wIndex - No use + ActualLen - Actual transfered Len + DataToggle - Data Toggle + TimeOut - TimeOut value in milliseconds + TransferResult - Transfer result +Returns: + + EFI_SUCCESS - Sucess + EFI_DEVICE_ERROR - Error +--*/ + +EFI_STATUS +InitializeMemoryManagement ( + IN USB_HC_DEV *HcDev + ); + +EFI_STATUS +CreateMemoryBlock ( + IN USB_HC_DEV *HcDev, + IN MEMORY_MANAGE_HEADER **MemoryHeader, + IN UINTN MemoryBlockSizeInPages + ); + +EFI_STATUS +FreeMemoryHeader ( + IN USB_HC_DEV *HcDev, + IN MEMORY_MANAGE_HEADER *MemoryHeader + ); + +EFI_STATUS +UhciAllocatePool ( + IN USB_HC_DEV *UhcDev, + IN UINT8 **Pool, + IN UINTN AllocSize + ); + +VOID +UhciFreePool ( + IN USB_HC_DEV *HcDev, + IN UINT8 *Pool, + IN UINTN AllocSize + ); + +VOID +InsertMemoryHeaderToList ( + IN MEMORY_MANAGE_HEADER *MemoryHeader, + IN MEMORY_MANAGE_HEADER *NewMemoryHeader + ); + +EFI_STATUS +AllocMemInMemoryBlock ( + IN MEMORY_MANAGE_HEADER *MemoryHeader, + IN VOID **Pool, + IN UINTN NumberOfMemoryUnit + ); + +BOOLEAN +IsMemoryBlockEmptied ( + IN MEMORY_MANAGE_HEADER *MemoryHeaderPtr + ); + +VOID +DelinkMemoryBlock ( + IN MEMORY_MANAGE_HEADER *FirstMemoryHeader, + IN MEMORY_MANAGE_HEADER *FreeMemoryHeader + ); + +EFI_STATUS +DelMemoryManagement ( + IN USB_HC_DEV *HcDev + ); + +VOID +EnableMaxPacketSize ( + IN USB_HC_DEV *HcDev + ); + +VOID +CleanUsbTransactions ( + IN USB_HC_DEV *HcDev + ); + +VOID +TurnOffUSBEmulation ( + IN EFI_PCI_IO_PROTOCOL *PciIo + ); + +#endif diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Decode.c b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Decode.c new file mode 100644 index 0000000000..f851b9b961 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Decode.c @@ -0,0 +1,1661 @@ +/*++ + +Copyright (c) 2006, 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. + +Module name: + decode.c + +Abstract: + +Revision history: + +--*/ + +// TODO: fix comment to add: Module Name: DECODE.C +#include "undi32.h" + + +#pragma data_seg("rtdata") + +// +// Global variables defined outside this file +// +extern PXE_SW_UNDI *pxe; // !pxe structure +extern PXE_SW_UNDI *pxe_31; // !pxe structure for 3.1 drivers +extern UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES]; + +// +// Global variables defined in this file +// +UNDI_CALL_TABLE api_table[PXE_OPCODE_LAST_VALID+1] = { \ + {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,0, (UINT16)(ANY_STATE),UNDI_GetState },\ + {(UINT16)(DONT_CHECK),PXE_DBSIZE_NOT_USED,0,(UINT16)(ANY_STATE),UNDI_Start },\ + {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,0,MUST_BE_STARTED,UNDI_Stop },\ + {PXE_CPBSIZE_NOT_USED,sizeof(PXE_DB_GET_INIT_INFO),0,MUST_BE_STARTED, UNDI_GetInitInfo },\ + {PXE_CPBSIZE_NOT_USED,sizeof(PXE_DB_GET_CONFIG_INFO),0,MUST_BE_STARTED, UNDI_GetConfigInfo },\ + {sizeof(PXE_CPB_INITIALIZE),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),MUST_BE_STARTED,UNDI_Initialize },\ + {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED,UNDI_Reset },\ + {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,0, MUST_BE_INITIALIZED,UNDI_Shutdown },\ + {PXE_CPBSIZE_NOT_USED,PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED,UNDI_Interrupt },\ + {(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_RecFilter },\ + {(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_StnAddr },\ + {PXE_CPBSIZE_NOT_USED, (UINT16)(DONT_CHECK), (UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_Statistics },\ + {sizeof(PXE_CPB_MCAST_IP_TO_MAC),sizeof(PXE_DB_MCAST_IP_TO_MAC), (UINT16)(DONT_CHECK),MUST_BE_INITIALIZED, UNDI_ip2mac },\ + {(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_NVData },\ + {PXE_CPBSIZE_NOT_USED,(UINT16)(DONT_CHECK),(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_Status },\ + {(UINT16)(DONT_CHECK),PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_FillHeader },\ + {(UINT16)(DONT_CHECK),PXE_DBSIZE_NOT_USED,(UINT16)(DONT_CHECK), MUST_BE_INITIALIZED, UNDI_Transmit },\ + {sizeof(PXE_CPB_RECEIVE),sizeof(PXE_DB_RECEIVE),0,MUST_BE_INITIALIZED, UNDI_Receive } \ +}; + +// +// end of global variables +// + +VOID +UNDI_GetState ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine determines the operational state of the UNDI. It updates the state flags in the + Command Descriptor Block based on information derived from the AdapterInfo instance data. + + To ensure the command has completed successfully, CdbPtr->StatCode will contain the result of + the command execution. + + The CdbPtr->StatFlags will contain a STOPPED, STARTED, or INITIALIZED state once the command + has successfully completed. + + Keep in mind the AdapterInfo->State is the active state of the adapter (based on software + interrogation), and the CdbPtr->StateFlags is the passed back information that is reflected + to the caller of the UNDI API. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + CdbPtr->StatFlags |= AdapterInfo->State; + return ; +} + +VOID +UNDI_Start ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to change the operational state of the UNDI from stopped to started. + It will do this as long as the adapter's state is PXE_STATFLAGS_GET_STATE_STOPPED, otherwise + the CdbPtr->StatFlags will reflect a command failure, and the CdbPtr->StatCode will reflect the + UNDI as having already been started. + + This routine is modified to reflect the undi 1.1 specification changes. The + changes in the spec are mainly in the callback routines, the new spec adds + 3 more callbacks and a unique id. + Since this UNDI supports both old and new undi specifications, + The NIC's data structure is filled in with the callback routines (depending + on the version) pointed to in the caller's CpbPtr. This seeds the Delay, + Virt2Phys, Block, and Mem_IO for old and new versions and Map_Mem, UnMap_Mem + and Sync_Mem routines and a unique id variable for the new version. + This is the function which an external entity (SNP, O/S, etc) would call + to provide it's I/O abstraction to the UNDI. + + It's final action is to change the AdapterInfo->State to PXE_STATFLAGS_GET_STATE_STARTED. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + PXE_CPB_START_30 *CpbPtr; + PXE_CPB_START_31 *CpbPtr_31; + + // + // check if it is already started. + // + if (AdapterInfo->State != PXE_STATFLAGS_GET_STATE_STOPPED) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_ALREADY_STARTED; + return ; + } + + if (CdbPtr->CPBsize != sizeof(PXE_CPB_START_30) && + CdbPtr->CPBsize != sizeof(PXE_CPB_START_31)) { + + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + CpbPtr = (PXE_CPB_START_30 *) (UINTN) (CdbPtr->CPBaddr); + CpbPtr_31 = (PXE_CPB_START_31 *) (UINTN) (CdbPtr->CPBaddr); + + if (AdapterInfo->VersionFlag == 0x30) { + AdapterInfo->Delay_30 = (bsptr_30) (UINTN) CpbPtr->Delay; + AdapterInfo->Virt2Phys_30 = (virtphys_30) (UINTN) CpbPtr->Virt2Phys; + AdapterInfo->Block_30 = (block_30) (UINTN) CpbPtr->Block; + // + // patch for old buggy 3.0 code: + // In EFI1.0 undi used to provide the full (absolute) I/O address to the + // i/o calls and SNP used to provide a callback that used GlobalIoFncs and + // everything worked fine! In EFI 1.1, UNDI is not using the full + // i/o or memory address to access the device, The base values for the i/o + // and memory address is abstracted by the device specific PciIoFncs and + // UNDI only uses the offset values. Since UNDI3.0 cannot provide any + // identification to SNP, SNP cannot use nic specific PciIoFncs callback! + // + // To fix this and make undi3.0 work with SNP in EFI1.1 we + // use a TmpMemIo function that is defined in init.c + // This breaks the runtime driver feature of undi, but what to do + // if we have to provide the 3.0 compatibility (including the 3.0 bugs) + // + // This TmpMemIo function also takes a UniqueId parameter + // (as in undi3.1 design) and so initialize the UniqueId as well here + // Note: AdapterInfo->Mem_Io_30 is just filled for consistency with other + // parameters but never used, we only use Mem_Io field in the In/Out routines + // inside e100b.c. + // + AdapterInfo->Mem_Io_30 = (mem_io_30) (UINTN) CpbPtr->Mem_IO; + AdapterInfo->Mem_Io = (mem_io) (UINTN) TmpMemIo; + AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo; + + } else { + AdapterInfo->Delay = (bsptr) (UINTN) CpbPtr_31->Delay; + AdapterInfo->Virt2Phys = (virtphys) (UINTN) CpbPtr_31->Virt2Phys; + AdapterInfo->Block = (block) (UINTN) CpbPtr_31->Block; + AdapterInfo->Mem_Io = (mem_io) (UINTN) CpbPtr_31->Mem_IO; + + AdapterInfo->Map_Mem = (map_mem) (UINTN) CpbPtr_31->Map_Mem; + AdapterInfo->UnMap_Mem = (unmap_mem) (UINTN) CpbPtr_31->UnMap_Mem; + AdapterInfo->Sync_Mem = (sync_mem) (UINTN) CpbPtr_31->Sync_Mem; + AdapterInfo->Unique_ID = CpbPtr_31->Unique_ID; + } + + AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STARTED; + + return ; +} + +VOID +UNDI_Stop ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to change the operational state of the UNDI from started to stopped. + It will not do this if the adapter's state is PXE_STATFLAGS_GET_STATE_INITIALIZED, otherwise + the CdbPtr->StatFlags will reflect a command failure, and the CdbPtr->StatCode will reflect the + UNDI as having already not been shut down. + + The NIC's data structure will have the Delay, Virt2Phys, and Block, pointers zero'd out.. + + It's final action is to change the AdapterInfo->State to PXE_STATFLAGS_GET_STATE_STOPPED. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_NOT_SHUTDOWN; + return ; + } + + AdapterInfo->Delay_30 = 0; + AdapterInfo->Virt2Phys_30 = 0; + AdapterInfo->Block_30 = 0; + + AdapterInfo->Delay = 0; + AdapterInfo->Virt2Phys = 0; + AdapterInfo->Block = 0; + + AdapterInfo->Map_Mem = 0; + AdapterInfo->UnMap_Mem = 0; + AdapterInfo->Sync_Mem = 0; + + AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STOPPED; + + return ; +} + +VOID +UNDI_GetInitInfo ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to retrieve the initialization information that is needed by drivers and + applications to initialize the UNDI. This will fill in data in the Data Block structure that is + pointed to by the caller's CdbPtr->DBaddr. The fields filled in are as follows: + + MemoryRequired, FrameDataLen, LinkSpeeds[0-3], NvCount, NvWidth, MediaHeaderLen, HWaddrLen, + MCastFilterCnt, TxBufCnt, TxBufSize, RxBufCnt, RxBufSize, IFtype, Duplex, and LoopBack. + + In addition, the CdbPtr->StatFlags ORs in that this NIC supports cable detection. (APRIORI knowledge) + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + PXE_DB_GET_INIT_INFO *DbPtr; + + DbPtr = (PXE_DB_GET_INIT_INFO *) (UINTN) (CdbPtr->DBaddr); + + DbPtr->MemoryRequired = MEMORY_NEEDED; + DbPtr->FrameDataLen = PXE_MAX_TXRX_UNIT_ETHER; + DbPtr->LinkSpeeds[0] = 10; + DbPtr->LinkSpeeds[1] = 100; + DbPtr->LinkSpeeds[2] = DbPtr->LinkSpeeds[3] = 0; + DbPtr->NvCount = MAX_EEPROM_LEN; + DbPtr->NvWidth = 4; + DbPtr->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER; + DbPtr->HWaddrLen = PXE_HWADDR_LEN_ETHER; + DbPtr->MCastFilterCnt = MAX_MCAST_ADDRESS_CNT; + + DbPtr->TxBufCnt = TX_BUFFER_COUNT; + DbPtr->TxBufSize = sizeof (TxCB); + DbPtr->RxBufCnt = RX_BUFFER_COUNT; + DbPtr->RxBufSize = sizeof (RxFD); + + DbPtr->IFtype = PXE_IFTYPE_ETHERNET; + DbPtr->SupportedDuplexModes = PXE_DUPLEX_ENABLE_FULL_SUPPORTED | + PXE_DUPLEX_FORCE_FULL_SUPPORTED; + DbPtr->SupportedLoopBackModes = PXE_LOOPBACK_INTERNAL_SUPPORTED | + PXE_LOOPBACK_EXTERNAL_SUPPORTED; + + CdbPtr->StatFlags |= PXE_STATFLAGS_CABLE_DETECT_SUPPORTED; + return ; +} + +VOID +UNDI_GetConfigInfo ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to retrieve the configuration information about the NIC being controlled by + this driver. This will fill in data in the Data Block structure that is pointed to by the caller's CdbPtr->DBaddr. + The fields filled in are as follows: + + DbPtr->pci.BusType, DbPtr->pci.Bus, DbPtr->pci.Device, and DbPtr->pci. + + In addition, the DbPtr->pci.Config.Dword[0-63] grabs a copy of this NIC's PCI configuration space. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + UINT16 Index; + PXE_DB_GET_CONFIG_INFO *DbPtr; + + DbPtr = (PXE_DB_GET_CONFIG_INFO *) (UINTN) (CdbPtr->DBaddr); + + DbPtr->pci.BusType = PXE_BUSTYPE_PCI; + DbPtr->pci.Bus = AdapterInfo->Bus; + DbPtr->pci.Device = AdapterInfo->Device; + DbPtr->pci.Function = AdapterInfo->Function; + + for (Index = 0; Index < MAX_PCI_CONFIG_LEN; Index++) { + DbPtr->pci.Config.Dword[Index] = AdapterInfo->Config[Index]; + } + + return ; +} + +VOID +UNDI_Initialize ( + IN PXE_CDB *CdbPtr, + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine resets the network adapter and initializes the UNDI using the parameters supplied in + the CPB. This command must be issued before the network adapter can be setup to transmit and + receive packets. + + Once the memory requirements of the UNDI are obtained by using the GetInitInfo command, a block + of non-swappable memory may need to be allocated. The address of this memory must be passed to + UNDI during the Initialize in the CPB. This memory is used primarily for transmit and receive buffers. + + The fields CableDetect, LinkSpeed, Duplex, LoopBack, MemoryPtr, and MemoryLength are set with information + that was passed in the CPB and the NIC is initialized. + + If the NIC initialization fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED + Otherwise, AdapterInfo->State is updated with PXE_STATFLAGS_GET_STATE_INITIALIZED showing the state of + the UNDI is now initialized. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + PXE_CPB_INITIALIZE *CpbPtr; + PXE_DB_INITIALIZE *DbPtr; + + if ((CdbPtr->OpFlags != PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) && + (CdbPtr->OpFlags != PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE)) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + // + // check if it is already initialized + // + if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_INITIALIZED) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_ALREADY_INITIALIZED; + return ; + } + + CpbPtr = (PXE_CPB_INITIALIZE *) (UINTN) CdbPtr->CPBaddr; + DbPtr = (PXE_DB_INITIALIZE *) (UINTN) CdbPtr->DBaddr; + + if (CpbPtr->MemoryLength < (UINT32) MEMORY_NEEDED) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB; + return ; + } + + // + // default behaviour is to detect the cable, if the 3rd param is 1, + // do not do that + // + AdapterInfo->CableDetect = (UINT8) ((CdbPtr->OpFlags == (UINT16) PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE) ? (UINT8) 0 : (UINT8) 1); + AdapterInfo->LinkSpeedReq = (UINT16) CpbPtr->LinkSpeed; + AdapterInfo->DuplexReq = CpbPtr->DuplexMode; + AdapterInfo->LoopBack = CpbPtr->LoopBackMode; + AdapterInfo->MemoryPtr = CpbPtr->MemoryAddr; + AdapterInfo->MemoryLength = CpbPtr->MemoryLength; + + CdbPtr->StatCode = (PXE_STATCODE) E100bInit (AdapterInfo); + + if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + } else { + AdapterInfo->State = PXE_STATFLAGS_GET_STATE_INITIALIZED; + } + + return ; +} + +VOID +UNDI_Reset ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine resets the network adapter and initializes the UNDI using the parameters supplied in + the CPB. The transmit and receive queues are emptied and any pending interrupts are cleared. + + If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + if (CdbPtr->OpFlags != PXE_OPFLAGS_NOT_USED && + CdbPtr->OpFlags != PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS && + CdbPtr->OpFlags != PXE_OPFLAGS_RESET_DISABLE_FILTERS ) { + + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + CdbPtr->StatCode = (UINT16) E100bReset (AdapterInfo, CdbPtr->OpFlags); + + if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + } +} + +VOID +UNDI_Shutdown ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine resets the network adapter and leaves it in a safe state for another driver to + initialize. Any pending transmits or receives are lost. Receive filters and external + interrupt enables are disabled. Once the UNDI has been shutdown, it can then be stopped + or initialized again. + + If the NIC reset fails, the CdbPtr->StatFlags are updated with PXE_STATFLAGS_COMMAND_FAILED + + Otherwise, AdapterInfo->State is updated with PXE_STATFLAGS_GET_STATE_STARTED showing the state of + the NIC as being started. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + // + // do the shutdown stuff here + // + CdbPtr->StatCode = (UINT16) E100bShutdown (AdapterInfo); + + if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + } else { + AdapterInfo->State = PXE_STATFLAGS_GET_STATE_STARTED; + } + + return ; +} + +VOID +UNDI_Interrupt ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine can be used to read and/or change the current external interrupt enable + settings. Disabling an external interrupt enable prevents and external (hardware) + interrupt from being signaled by the network device. Internally the interrupt events + can still be polled by using the UNDI_GetState command. + + The resulting information on the interrupt state will be passed back in the CdbPtr->StatFlags. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + UINT8 IntMask; + + IntMask = (UINT8)(UINTN)(CdbPtr->OpFlags & (PXE_OPFLAGS_INTERRUPT_RECEIVE | + PXE_OPFLAGS_INTERRUPT_TRANSMIT | + PXE_OPFLAGS_INTERRUPT_COMMAND | + PXE_OPFLAGS_INTERRUPT_SOFTWARE)); + + switch (CdbPtr->OpFlags & PXE_OPFLAGS_INTERRUPT_OPMASK) { + case PXE_OPFLAGS_INTERRUPT_READ: + break; + + case PXE_OPFLAGS_INTERRUPT_ENABLE: + if (IntMask == 0) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + AdapterInfo->int_mask = IntMask; + E100bSetInterruptState (AdapterInfo); + break; + + case PXE_OPFLAGS_INTERRUPT_DISABLE: + if (IntMask != 0) { + AdapterInfo->int_mask &= ~(IntMask); + E100bSetInterruptState (AdapterInfo); + break; + } + + // + // else fall thru. + // + default: + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_RECEIVE) != 0) { + CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_RECEIVE; + + } + + if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_TRANSMIT) != 0) { + CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_TRANSMIT; + + } + + if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_COMMAND) != 0) { + CdbPtr->StatFlags |= PXE_STATFLAGS_INTERRUPT_COMMAND; + + } + + return ; +} + +VOID +UNDI_RecFilter ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to read and change receive filters and, if supported, read + and change multicast MAC address filter list. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + UINT16 NewFilter; + UINT16 OpFlags; + PXE_DB_RECEIVE_FILTERS *DbPtr; + UINT8 *MacAddr; + UINTN MacCount; + UINT16 Index; + UINT16 copy_len; + UINT8 *ptr1; + UINT8 *ptr2; + OpFlags = CdbPtr->OpFlags; + NewFilter = (UINT16) (OpFlags & 0x1F); + + switch (OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_OPMASK) { + case PXE_OPFLAGS_RECEIVE_FILTER_READ: + + // + // not expecting a cpb, not expecting any filter bits + // + if ((NewFilter != 0) || (CdbPtr->CPBsize != 0)) { + goto BadCdb; + + } + + if ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) == 0) { + goto JustRead; + + } + + NewFilter |= AdapterInfo->Rx_Filter; + // + // all other flags are ignored except mcast_reset + // + break; + + case PXE_OPFLAGS_RECEIVE_FILTER_ENABLE: + // + // there should be atleast one other filter bit set. + // + if (NewFilter == 0) { + // + // nothing to enable + // + goto BadCdb; + } + + if (CdbPtr->CPBsize != 0) { + // + // this must be a multicast address list! + // don't accept the list unless selective_mcast is set + // don't accept confusing mcast settings with this + // + if (((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) == 0) || + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) || + ((NewFilter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) || + ((CdbPtr->CPBsize % sizeof (PXE_MAC_ADDR)) != 0) ) { + goto BadCdb; + } + + MacAddr = (UINT8 *) ((UINTN) (CdbPtr->CPBaddr)); + MacCount = CdbPtr->CPBsize / sizeof (PXE_MAC_ADDR); + + for (; MacCount-- != 0; MacAddr += sizeof (PXE_MAC_ADDR)) { + if (MacAddr[0] != 0x01 || MacAddr[1] != 0x00 || MacAddr[2] != 0x5E || (MacAddr[3] & 0x80) != 0) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB; + return ; + } + } + } + + // + // check selective mcast case enable case + // + if ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) { + if (((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) || + ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) ) { + goto BadCdb; + + } + // + // if no cpb, make sure we have an old list + // + if ((CdbPtr->CPBsize == 0) && (AdapterInfo->mcast_list.list_len == 0)) { + goto BadCdb; + } + } + // + // if you want to enable anything, you got to have unicast + // and you have what you already enabled! + // + NewFilter |= (PXE_OPFLAGS_RECEIVE_FILTER_UNICAST | AdapterInfo->Rx_Filter); + + break; + + case PXE_OPFLAGS_RECEIVE_FILTER_DISABLE: + + // + // mcast list not expected, i.e. no cpb here! + // + if (CdbPtr->CPBsize != PXE_CPBSIZE_NOT_USED) { + goto BadCdb; + } + + NewFilter = (UINT16) ((~(CdbPtr->OpFlags & 0x1F)) & AdapterInfo->Rx_Filter); + + break; + + default: + goto BadCdb; + } + + if ((OpFlags & PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST) != 0) { + AdapterInfo->mcast_list.list_len = 0; + NewFilter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST); + } + + E100bSetfilter (AdapterInfo, NewFilter, CdbPtr->CPBaddr, CdbPtr->CPBsize); + +JustRead: + // + // give the current mcast list + // + if ((CdbPtr->DBsize != 0) && (AdapterInfo->mcast_list.list_len != 0)) { + // + // copy the mc list to db + // + + DbPtr = (PXE_DB_RECEIVE_FILTERS *) (UINTN) CdbPtr->DBaddr; + ptr1 = (UINT8 *) (&DbPtr->MCastList[0]); + + // + // DbPtr->mc_count = AdapterInfo->mcast_list.list_len; + // + copy_len = (UINT16) (AdapterInfo->mcast_list.list_len * PXE_MAC_LENGTH); + + if (copy_len > CdbPtr->DBsize) { + copy_len = CdbPtr->DBsize; + + } + + ptr2 = (UINT8 *) (&AdapterInfo->mcast_list.mc_list[0]); + for (Index = 0; Index < copy_len; Index++) { + ptr1[Index] = ptr2[Index]; + } + } + // + // give the stat flags here + // + if (AdapterInfo->Receive_Started) { + CdbPtr->StatFlags |= AdapterInfo->Rx_Filter; + + } + + return ; + +BadCdb: + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; +} + +VOID +UNDI_StnAddr ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to get the current station and broadcast MAC addresses, and to change the + current station MAC address. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + PXE_CPB_STATION_ADDRESS *CpbPtr; + PXE_DB_STATION_ADDRESS *DbPtr; + UINT16 Index; + + if (CdbPtr->OpFlags == PXE_OPFLAGS_STATION_ADDRESS_RESET) { + // + // configure the permanent address. + // change the AdapterInfo->CurrentNodeAddress field. + // + if (CompareMem ( + &AdapterInfo->CurrentNodeAddress[0], + &AdapterInfo->PermNodeAddress[0], + PXE_MAC_LENGTH + ) != 0) { + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { + AdapterInfo->CurrentNodeAddress[Index] = AdapterInfo->PermNodeAddress[Index]; + } + + E100bSetupIAAddr (AdapterInfo); + } + } + + if (CdbPtr->CPBaddr != (UINT64) 0) { + CpbPtr = (PXE_CPB_STATION_ADDRESS *) (UINTN) (CdbPtr->CPBaddr); + // + // configure the new address + // + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { + AdapterInfo->CurrentNodeAddress[Index] = CpbPtr->StationAddr[Index]; + } + + E100bSetupIAAddr (AdapterInfo); + } + + if (CdbPtr->DBaddr != (UINT64) 0) { + DbPtr = (PXE_DB_STATION_ADDRESS *) (UINTN) (CdbPtr->DBaddr); + // + // fill it with the new values + // + for (Index = 0; Index < PXE_MAC_LENGTH; Index++) { + DbPtr->StationAddr[Index] = AdapterInfo->CurrentNodeAddress[Index]; + DbPtr->BroadcastAddr[Index] = AdapterInfo->BroadcastNodeAddress[Index]; + DbPtr->PermanentAddr[Index] = AdapterInfo->PermNodeAddress[Index]; + } + } + + return ; +} + +VOID +UNDI_Statistics ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to read and clear the NIC traffic statistics. This command is supported only + if the !PXE structure's Implementation flags say so. + + Results will be parsed out in the following manner: + CdbPtr->DBaddr.Data[0] R Total Frames (Including frames with errors and dropped frames) + CdbPtr->DBaddr.Data[1] R Good Frames (All frames copied into receive buffer) + CdbPtr->DBaddr.Data[2] R Undersize Frames (Frames below minimum length for media <64 for ethernet) + CdbPtr->DBaddr.Data[4] R Dropped Frames (Frames that were dropped because receive buffers were full) + CdbPtr->DBaddr.Data[8] R CRC Error Frames (Frames with alignment or CRC errors) + CdbPtr->DBaddr.Data[A] T Total Frames (Including frames with errors and dropped frames) + CdbPtr->DBaddr.Data[B] T Good Frames (All frames copied into transmit buffer) + CdbPtr->DBaddr.Data[C] T Undersize Frames (Frames below minimum length for media <64 for ethernet) + CdbPtr->DBaddr.Data[E] T Dropped Frames (Frames that were dropped because of collisions) + CdbPtr->DBaddr.Data[14] T Total Collision Frames (Total collisions on this subnet) + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + if ((CdbPtr->OpFlags &~(PXE_OPFLAGS_STATISTICS_RESET)) != 0) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + if ((CdbPtr->OpFlags & PXE_OPFLAGS_STATISTICS_RESET) != 0) { + // + // Reset the statistics + // + CdbPtr->StatCode = (UINT16) E100bStatistics (AdapterInfo, 0, 0); + } else { + CdbPtr->StatCode = (UINT16) E100bStatistics (AdapterInfo, CdbPtr->DBaddr, CdbPtr->DBsize); + } + + return ; +} + +VOID +UNDI_ip2mac ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to translate a multicast IP address to a multicast MAC address. + + This results in a MAC address composed of 25 bits of fixed data with the upper 23 bits of the IP + address being appended to it. Results passed back in the equivalent of CdbPtr->DBaddr->MAC[0-5]. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + PXE_CPB_MCAST_IP_TO_MAC *CpbPtr; + PXE_DB_MCAST_IP_TO_MAC *DbPtr; + UINT8 *TmpPtr; + + CpbPtr = (PXE_CPB_MCAST_IP_TO_MAC *) (UINTN) CdbPtr->CPBaddr; + DbPtr = (PXE_DB_MCAST_IP_TO_MAC *) (UINTN) CdbPtr->DBaddr; + + if ((CdbPtr->OpFlags & PXE_OPFLAGS_MCAST_IPV6_TO_MAC) != 0) { + // + // for now this is not supported + // + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_UNSUPPORTED; + return ; + } + + TmpPtr = (UINT8 *) (&CpbPtr->IP.IPv4); + // + // check if the ip given is a mcast IP + // + if ((TmpPtr[0] & 0xF0) != 0xE0) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CPB; + } + // + // take the last 23 bits in IP. + // be very careful. accessing word on a non-word boundary will hang motherboard codenamed Big Sur + // casting the mac array (in the middle) to a UINT32 pointer and accessing + // the UINT32 content hung the system... + // + DbPtr->MAC[0] = 0x01; + DbPtr->MAC[1] = 0x00; + DbPtr->MAC[2] = 0x5e; + DbPtr->MAC[3] = (UINT8) (TmpPtr[1] & 0x7f); + DbPtr->MAC[4] = (UINT8) TmpPtr[2]; + DbPtr->MAC[5] = (UINT8) TmpPtr[3]; + + return ; +} + +VOID +UNDI_NVData ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to read and write non-volatile storage on the NIC (if supported). The NVRAM + could be EEPROM, FLASH, or battery backed RAM. + + This is an optional function according to the UNDI specification (or will be......) + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + PXE_DB_NVDATA *DbPtr; + UINT16 Index; + + if ((CdbPtr->OpFlags == PXE_OPFLAGS_NVDATA_READ) != 0) { + + if ((CdbPtr->DBsize == PXE_DBSIZE_NOT_USED) != 0) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + DbPtr = (PXE_DB_NVDATA *) (UINTN) CdbPtr->DBaddr; + + for (Index = 0; Index < MAX_PCI_CONFIG_LEN; Index++) { + DbPtr->Data.Dword[Index] = AdapterInfo->NVData[Index]; + + } + + } else { + // + // no write for now + // + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_UNSUPPORTED; + } + + return ; +} + +VOID +UNDI_Status ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine returns the current interrupt status and/or the transmitted buffer addresses. + If the current interrupt status is returned, pending interrupts will be acknowledged by this + command. Transmitted buffer addresses that are written to the DB are removed from the transmit + buffer queue. + + Normally, this command would be polled with interrupts disabled. + + The transmit buffers are returned in CdbPtr->DBaddr->TxBufer[0 - NumEntries]. + The interrupt status is returned in CdbPtr->StatFlags. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + PXE_DB_GET_STATUS *DbPtr; + PXE_DB_GET_STATUS TmpGetStatus; + UINT16 Index; + UINT16 Status; + UINT16 NumEntries; + RxFD *RxPtr; + + // + // Fill in temporary GetStatus storage. + // + RxPtr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind]; + + if ((RxPtr->cb_header.status & RX_COMPLETE) != 0) { + TmpGetStatus.RxFrameLen = RxPtr->ActualCount & 0x3fff; + } else { + TmpGetStatus.RxFrameLen = 0; + } + + TmpGetStatus.reserved = 0; + + // + // Fill in size of next available receive packet and + // reserved field in caller's DB storage. + // + DbPtr = (PXE_DB_GET_STATUS *) (UINTN) CdbPtr->DBaddr; + + if (CdbPtr->DBsize > 0 && CdbPtr->DBsize < sizeof (UINT32) * 2) { + CopyMem (DbPtr, &TmpGetStatus, CdbPtr->DBsize); + } else { + CopyMem (DbPtr, &TmpGetStatus, sizeof (UINT32) * 2); + } + + // + // + // + if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS) != 0) { + // + // DBsize of zero is invalid if Tx buffers are requested. + // + if (CdbPtr->DBsize == 0) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + // + // remember this b4 we overwrite + // + NumEntries = (UINT16) (CdbPtr->DBsize - sizeof (UINT64)); + + // + // We already filled in 2 UINT32s. + // + CdbPtr->DBsize = sizeof (UINT32) * 2; + + // + // will claim any hanging free CBs + // + CheckCBList (AdapterInfo); + + if (AdapterInfo->xmit_done_head == AdapterInfo->xmit_done_tail) { + CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY; + } else { + for (Index = 0; NumEntries >= sizeof (UINT64); Index++, NumEntries -= sizeof (UINT64)) { + if (AdapterInfo->xmit_done_head != AdapterInfo->xmit_done_tail) { + DbPtr->TxBuffer[Index] = AdapterInfo->xmit_done[AdapterInfo->xmit_done_head]; + AdapterInfo->xmit_done_head = next (AdapterInfo->xmit_done_head); + CdbPtr->DBsize += sizeof (UINT64); + } else { + break; + } + } + } + + if (AdapterInfo->xmit_done_head != AdapterInfo->xmit_done_tail) { + CdbPtr->StatFlags |= PXE_STATFLAGS_DB_WRITE_TRUNCATED; + + } + // + // check for a receive buffer and give it's size in db + // + } + // + // + // + if ((CdbPtr->OpFlags & PXE_OPFLAGS_GET_INTERRUPT_STATUS) != 0) { + + Status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus); + AdapterInfo->Int_Status |= Status; + + // + // acknoledge the interrupts + // + OutWord (AdapterInfo, (UINT16) (Status & 0xfc00), (UINT32) (AdapterInfo->ioaddr + SCBStatus)); + + // + // report all the outstanding interrupts + // + Status = AdapterInfo->Int_Status; + if ((Status & SCB_STATUS_FR) != 0) { + CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_RECEIVE; + } + + if ((Status & SCB_STATUS_SWI) != 0) { + CdbPtr->StatFlags |= PXE_STATFLAGS_GET_STATUS_SOFTWARE; + } + } + + return ; +} + +VOID +UNDI_FillHeader ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to fill media header(s) in transmit packet(s). + Copies the MAC address into the media header whether it is dealing + with fragmented or non-fragmented packets. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + PXE_CPB_FILL_HEADER *Cpb; + PXE_CPB_FILL_HEADER_FRAGMENTED *Cpbf; + EtherHeader *MacHeader; + UINTN Index; + + if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + if ((CdbPtr->OpFlags & PXE_OPFLAGS_FILL_HEADER_FRAGMENTED) != 0) { + Cpbf = (PXE_CPB_FILL_HEADER_FRAGMENTED *) (UINTN) CdbPtr->CPBaddr; + + // + // assume 1st fragment is big enough for the mac header + // + if ((Cpbf->FragCnt == 0) || (Cpbf->FragDesc[0].FragLen < PXE_MAC_HEADER_LEN_ETHER)) { + // + // no buffers given + // + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + MacHeader = (EtherHeader *) (UINTN) Cpbf->FragDesc[0].FragAddr; + // + // we don't swap the protocol bytes + // + MacHeader->type = Cpbf->Protocol; + + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { + MacHeader->dest_addr[Index] = Cpbf->DestAddr[Index]; + MacHeader->src_addr[Index] = Cpbf->SrcAddr[Index]; + } + } else { + Cpb = (PXE_CPB_FILL_HEADER *) (UINTN) CdbPtr->CPBaddr; + + MacHeader = (EtherHeader *) (UINTN) Cpb->MediaHeader; + // + // we don't swap the protocol bytes + // + MacHeader->type = Cpb->Protocol; + + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { + MacHeader->dest_addr[Index] = Cpb->DestAddr[Index]; + MacHeader->src_addr[Index] = Cpb->SrcAddr[Index]; + } + } + + return ; +} + +VOID +UNDI_Transmit ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine is used to place a packet into the transmit queue. The data buffers given to + this command are to be considered locked and the application or network driver loses + ownership of these buffers and must not free or relocate them until the ownership returns. + + When the packets are transmitted, a transmit complete interrupt is generated (if interrupts + are disabled, the transmit interrupt status is still set and can be checked using the UNDI_Status + command. + + Some implementations and adapters support transmitting multiple packets with one transmit + command. If this feature is supported, the transmit CPBs can be linked in one transmit + command. + + All UNDIs support fragmented frames, now all network devices or protocols do. If a fragmented + frame CPB is given to UNDI and the network device does not support fragmented frames + (see !PXE.Implementation flag), the UNDI will have to copy the fragments into a local buffer + before transmitting. + + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + + if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + CdbPtr->StatCode = (PXE_STATCODE) E100bTransmit (AdapterInfo, CdbPtr->CPBaddr, CdbPtr->OpFlags); + + if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + } + + return ; +} + +VOID +UNDI_Receive ( + IN PXE_CDB *CdbPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + When the network adapter has received a frame, this command is used to copy the frame + into the driver/application storage location. Once a frame has been copied, it is + removed from the receive queue. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + PXE_CPB_RECEIVE *cpbptr; + + // + // check if RU has started... + // + if (!AdapterInfo->Receive_Started) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_NOT_INITIALIZED; + return ; + } + + cpbptr = (PXE_CPB_RECEIVE *) (UINTN) CdbPtr->CPBaddr; + + CdbPtr->StatCode = (UINT16) E100bReceive (AdapterInfo, CdbPtr->CPBaddr, CdbPtr->DBaddr); + if (CdbPtr->StatCode != PXE_STATCODE_SUCCESS) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + + } + + return ; +} + +VOID +UNDI_APIEntry_old ( + IN UINT64 cdb + ) +/*++ + +Routine Description: + This is the main SW UNDI API entry using the older nii protocol. + The parameter passed in is a 64 bit flat model virtual + address of the cdb. We then jump into the common routine for both old and + new nii protocol entries. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +// TODO: cdb - add argument and description to function comment +{ + PXE_CDB *CdbPtr; + NIC_DATA_INSTANCE *AdapterInfo; + + if (cdb == (UINT64) 0) { + return ; + + } + + CdbPtr = (PXE_CDB *) (UINTN) cdb; + + if (CdbPtr->IFnum >= pxe->IFcnt) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo); + + // + // entering from older entry point + // + AdapterInfo->VersionFlag = 0x30; + UNDI_APIEntry_Common (cdb); +} + +VOID +UNDI_APIEntry_new ( + IN UINT64 cdb + ) +/*++ + +Routine Description: + This is the main SW UNDI API entry using the newer nii protocol. + The parameter passed in is a 64 bit flat model virtual + address of the cdb. We then jump into the common routine for both old and + new nii protocol entries. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +// TODO: cdb - add argument and description to function comment +{ + PXE_CDB *CdbPtr; + NIC_DATA_INSTANCE *AdapterInfo; + + if (cdb == (UINT64) 0) { + return ; + + } + + CdbPtr = (PXE_CDB *) (UINTN) cdb; + + if (CdbPtr->IFnum >= pxe_31->IFcnt) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; + } + + AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo); + // + // entering from older entry point + // + AdapterInfo->VersionFlag = 0x31; + UNDI_APIEntry_Common (cdb); +} + +VOID +UNDI_APIEntry_Common ( + IN UINT64 cdb + ) +/*++ + +Routine Description: + This is the common routine for both old and new entry point procedures. + The parameter passed in is a 64 bit flat model virtual + address of the cdb. We then jump into the service routine pointed to by the + Api_Table[OpCode]. + +Arguments: + CdbPtr - Pointer to the command descriptor block. + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +// TODO: cdb - add argument and description to function comment +{ + PXE_CDB *CdbPtr; + NIC_DATA_INSTANCE *AdapterInfo; + UNDI_CALL_TABLE *tab_ptr; + + CdbPtr = (PXE_CDB *) (UINTN) cdb; + + // + // check the OPCODE range + // + if ((CdbPtr->OpCode > PXE_OPCODE_LAST_VALID) || + (CdbPtr->StatCode != PXE_STATCODE_INITIALIZE) || + (CdbPtr->StatFlags != PXE_STATFLAGS_INITIALIZE) || + (CdbPtr->IFnum >= pxe_31->IFcnt) ) { + goto badcdb; + + } + + if (CdbPtr->CPBsize == PXE_CPBSIZE_NOT_USED) { + if (CdbPtr->CPBaddr != PXE_CPBADDR_NOT_USED) { + goto badcdb; + } + } else if (CdbPtr->CPBaddr == PXE_CPBADDR_NOT_USED) { + goto badcdb; + } + + if (CdbPtr->DBsize == PXE_DBSIZE_NOT_USED) { + if (CdbPtr->DBaddr != PXE_DBADDR_NOT_USED) { + goto badcdb; + } + } else if (CdbPtr->DBaddr == PXE_DBADDR_NOT_USED) { + goto badcdb; + } + + // + // check if cpbsize and dbsize are as needed + // check if opflags are as expected + // + tab_ptr = &api_table[CdbPtr->OpCode]; + + if (tab_ptr->cpbsize != (UINT16) (DONT_CHECK) && tab_ptr->cpbsize != CdbPtr->CPBsize) { + goto badcdb; + } + + if (tab_ptr->dbsize != (UINT16) (DONT_CHECK) && tab_ptr->dbsize != CdbPtr->DBsize) { + goto badcdb; + } + + if (tab_ptr->opflags != (UINT16) (DONT_CHECK) && tab_ptr->opflags != CdbPtr->OpFlags) { + goto badcdb; + + } + + AdapterInfo = &(UNDI32DeviceList[CdbPtr->IFnum]->NicInfo); + + // + // check if UNDI_State is valid for this call + // + if (tab_ptr->state != (UINT16) (-1)) { + // + // should atleast be started + // + if (AdapterInfo->State == PXE_STATFLAGS_GET_STATE_STOPPED) { + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_NOT_STARTED; + return ; + } + // + // check if it should be initialized + // + if (tab_ptr->state == 2) { + if (AdapterInfo->State != PXE_STATFLAGS_GET_STATE_INITIALIZED) { + CdbPtr->StatCode = PXE_STATCODE_NOT_INITIALIZED; + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + return ; + } + } + } + // + // set the return variable for success case here + // + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_COMPLETE; + CdbPtr->StatCode = PXE_STATCODE_SUCCESS; + + tab_ptr->api_ptr (CdbPtr, AdapterInfo); + return ; + // + // %% AVL - check for command linking + // +badcdb: + CdbPtr->StatFlags = PXE_STATFLAGS_COMMAND_FAILED; + CdbPtr->StatCode = PXE_STATCODE_INVALID_CDB; + return ; +} + +UINT8 +ChkSum ( + IN VOID *Buffer, + IN UINT16 Len + ) +/*++ + +Routine Description: + This does an 8 bit check sum of the passed in buffer for Len bytes. + This is primarily used to update the check sum in the SW UNDI header. + +Arguments: + Buffer - Pointer to the passed in buffer to check sum + Len - Length of buffer to be check summed in bytes. + +Returns: + None + +--*/ +{ + UINT8 Chksum; + INT8 *Bp; + + Chksum = 0; + if ((Bp = Buffer) != NULL) { + while (Len--) { + Chksum = (UINT8) (Chksum +*Bp++); + + } + + } + + return Chksum; +} + +VOID +PxeUpdate ( + IN NIC_DATA_INSTANCE *NicPtr, + IN PXE_SW_UNDI *PxePtr + ) +/*++ + +Routine Description: + When called with a null NicPtr, this routine decrements the number of NICs + this UNDI is supporting and removes the NIC_DATA_POINTER from the array. + Otherwise, it increments the number of NICs this UNDI is supported and + updates the pxe.Fudge to ensure a proper check sum results. + +Arguments: + NicPtr - Pointer to the NIC data structure. + +Returns: + None + +--*/ +// TODO: PxePtr - add argument and description to function comment +{ + if (NicPtr == NULL) { + if (PxePtr->IFcnt > 0) { + // + // number of NICs this undi supports + // + PxePtr->IFcnt--; + } + + PxePtr->Fudge = (UINT8) (PxePtr->Fudge - ChkSum ((VOID *) PxePtr, PxePtr->Len)); + return ; + } + + // + // number of NICs this undi supports + // + PxePtr->IFcnt++; + PxePtr->Fudge = (UINT8) (PxePtr->Fudge - ChkSum ((VOID *) PxePtr, PxePtr->Len)); + + return ; +} + +VOID +PxeStructInit ( + IN PXE_SW_UNDI *PxePtr, + IN UINTN VersionFlag + ) +/*++ + +Routine Description: + Initialize the !PXE structure + +Arguments: + RemainingDevicePath - Not used, always produce all possible children. + +Returns: + EFI_SUCCESS - This driver is added to Controller. + other - This driver does not support this device. + +--*/ +// TODO: PxePtr - add argument and description to function comment +// TODO: VersionFlag - add argument and description to function comment +{ + // + // Initialize the !PXE structure + // + PxePtr->Signature = PXE_ROMID_SIGNATURE; + PxePtr->Len = sizeof (PXE_SW_UNDI); + // + // cksum + // + PxePtr->Fudge = 0; + // + // number of NICs this undi supports + // + PxePtr->IFcnt = 0; + PxePtr->Rev = PXE_ROMID_REV; + PxePtr->MajorVer = PXE_ROMID_MAJORVER; + PxePtr->MinorVer = PXE_ROMID_MINORVER; + PxePtr->reserved1 = 0; + + PxePtr->Implementation = PXE_ROMID_IMP_SW_VIRT_ADDR | + PXE_ROMID_IMP_FRAG_SUPPORTED | + PXE_ROMID_IMP_CMD_LINK_SUPPORTED | + PXE_ROMID_IMP_NVDATA_READ_ONLY | + PXE_ROMID_IMP_STATION_ADDR_SETTABLE | + PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED | + PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED | + PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED | + PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED | + PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED | + PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED; + + if (VersionFlag == 0x30) { + PxePtr->EntryPoint = (UINT64) UNDI_APIEntry_old; + } else { + PxePtr->EntryPoint = (UINT64) UNDI_APIEntry_new; + PxePtr->MinorVer = PXE_ROMID_MINORVER_31; + } + + PxePtr->reserved2[0] = 0; + PxePtr->reserved2[1] = 0; + PxePtr->reserved2[2] = 0; + PxePtr->BusCnt = 1; + PxePtr->BusType[0] = PXE_BUSTYPE_PCI; + + PxePtr->Fudge = (UINT8) (PxePtr->Fudge - ChkSum ((VOID *) PxePtr, PxePtr->Len)); +} + +#pragma data_seg() diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.c b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.c new file mode 100644 index 0000000000..5b69a46ac4 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.c @@ -0,0 +1,3772 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + + E100B.C + +Abstract: + + +Revision History + +--*/ + +#include "undi32.h" + +static UINT8 basic_config_cmd[22] = { + 22, 0x08, + 0, 0, + 0, (UINT8)0x80, + 0x32, 0x03, + 1, 0, + 0x2E, 0, + 0x60, 0, + (UINT8)0xf2, 0x48, + 0, 0x40, + (UINT8)0xf2, (UINT8)0x80, // 0x40=Force full-duplex + 0x3f, 0x05, +}; + +// +// How to wait for the command unit to accept a command. +// Typically this takes 0 ticks. +// +#define wait_for_cmd_done(cmd_ioaddr) \ +{ \ + INT16 wait = 2000; \ + while ((InByte (AdapterInfo, cmd_ioaddr) != 0) && --wait >= 0) \ + DelayIt (AdapterInfo, 10); \ + if (wait == 0) \ + DelayIt (AdapterInfo, 50); \ +} + +UINT8 +InByte ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT32 Port + ) +/*++ + +Routine Description: + This function calls the MemIo callback to read a byte from the device's + address space + Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) + which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have + to make undi3.0 a special case + +Arguments: + Port - Which port to read from. + +Returns: + Results - The data read from the port. + +--*/ +// TODO: AdapterInfo - add argument and description to function comment +{ + UINT8 Results; + + (*AdapterInfo->Mem_Io) ( + AdapterInfo->Unique_ID, + PXE_MEM_READ, + 1, + (UINT64)Port, + (UINT64) (UINTN) &Results + ); + return Results; +} + +UINT16 +InWord ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT32 Port + ) +/*++ + +Routine Description: + This function calls the MemIo callback to read a word from the device's + address space + Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) + which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have + to make undi3.0 a special case + +Arguments: + Port - Which port to read from. + +Returns: + Results - The data read from the port. + +--*/ +// TODO: AdapterInfo - add argument and description to function comment +{ + UINT16 Results; + + (*AdapterInfo->Mem_Io) ( + AdapterInfo->Unique_ID, + PXE_MEM_READ, + 2, + (UINT64)Port, + (UINT64)(UINTN)&Results + ); + return Results; +} + +UINT32 +InLong ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT32 Port + ) +/*++ + +Routine Description: + This function calls the MemIo callback to read a dword from the device's + address space + Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) + which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have + to make undi3.0 a special case + +Arguments: + Port - Which port to read from. + +Returns: + Results - The data read from the port. + +--*/ +// TODO: AdapterInfo - add argument and description to function comment +{ + UINT32 Results; + + (*AdapterInfo->Mem_Io) ( + AdapterInfo->Unique_ID, + PXE_MEM_READ, + 4, + (UINT64)Port, + (UINT64)(UINTN)&Results + ); + return Results; +} + +VOID +OutByte ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT8 Data, + IN UINT32 Port + ) +/*++ + +Routine Description: + This function calls the MemIo callback to write a byte from the device's + address space + Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) + which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have + to make undi3.0 a special case + +Arguments: + Data - Data to write to Port. + Port - Which port to write to. + +Returns: + none + +--*/ +// TODO: AdapterInfo - add argument and description to function comment +{ + UINT8 Val; + + Val = Data; + (*AdapterInfo->Mem_Io) ( + AdapterInfo->Unique_ID, + PXE_MEM_WRITE, + 1, + (UINT64)Port, + (UINT64)(UINTN)(UINTN)&Val + ); + return ; +} + +VOID +OutWord ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT16 Data, + IN UINT32 Port + ) +/*++ + +Routine Description: + This function calls the MemIo callback to write a word from the device's + address space + Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) + which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have + to make undi3.0 a special case + +Arguments: + Data - Data to write to Port. + Port - Which port to write to. + +Returns: + none + +--*/ +// TODO: AdapterInfo - add argument and description to function comment +{ + UINT16 Val; + + Val = Data; + (*AdapterInfo->Mem_Io) ( + AdapterInfo->Unique_ID, + PXE_MEM_WRITE, + 2, + (UINT64)Port, + (UINT64)(UINTN)&Val + ); + return ; +} + +VOID +OutLong ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT32 Data, + IN UINT32 Port + ) +/*++ + +Routine Description: + This function calls the MemIo callback to write a dword from the device's + address space + Since UNDI3.0 uses the TmpMemIo function (instead of the callback routine) + which also takes the UniqueId parameter (as in UNDI3.1 spec) we don't have + to make undi3.0 a special case + +Arguments: + Data - Data to write to Port. + Port - Which port to write to. + +Returns: + none + +--*/ +// TODO: AdapterInfo - add argument and description to function comment +{ + UINT32 Val; + + Val = Data; + (*AdapterInfo->Mem_Io) ( + AdapterInfo->Unique_ID, + PXE_MEM_WRITE, + 4, + (UINT64)Port, + (UINT64)(UINTN)&Val + ); + return ; +} + +UINTN +MapIt ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT64 MemAddr, + IN UINT32 Size, + IN UINT32 Direction, + OUT UINT64 MappedAddr + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + MemAddr - TODO: add argument description + Size - TODO: add argument description + Direction - TODO: add argument description + MappedAddr - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT64 *PhyAddr; + + PhyAddr = (UINT64 *) (UINTN) MappedAddr; + // + // mapping is different for theold and new NII protocols + // + if (AdapterInfo->VersionFlag == 0x30) { + if (AdapterInfo->Virt2Phys_30 == (VOID *) NULL) { + *PhyAddr = (UINT64) AdapterInfo->MemoryPtr; + } else { + (*AdapterInfo->Virt2Phys_30) (MemAddr, (UINT64) (UINTN) PhyAddr); + } + + if (*PhyAddr > FOUR_GIGABYTE) { + return PXE_STATCODE_INVALID_PARAMETER; + } + } else { + if (AdapterInfo->Map_Mem == (VOID *) NULL) { + // + // this UNDI cannot handle addresses beyond 4 GB without a map routine + // + if (MemAddr > FOUR_GIGABYTE) { + return PXE_STATCODE_INVALID_PARAMETER; + } else { + *PhyAddr = MemAddr; + } + } else { + (*AdapterInfo->Map_Mem) ( + AdapterInfo->Unique_ID, + MemAddr, + Size, + Direction, + MappedAddr + ); + } + } + + return PXE_STATCODE_SUCCESS; +} + +VOID +UnMapIt ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT64 MemAddr, + IN UINT32 Size, + IN UINT32 Direction, + IN UINT64 MappedAddr + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + MemAddr - TODO: add argument description + Size - TODO: add argument description + Direction - TODO: add argument description + MappedAddr - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + if (AdapterInfo->VersionFlag > 0x30) { + // + // no mapping service + // + if (AdapterInfo->UnMap_Mem != (VOID *) NULL) { + (*AdapterInfo->UnMap_Mem) ( + AdapterInfo->Unique_ID, + MemAddr, + Size, + Direction, + MappedAddr + ); + + } + } + + return ; +} + +VOID +DelayIt ( + IN NIC_DATA_INSTANCE *AdapterInfo, + UINT16 MicroSeconds + ) +/*++ + +Routine Description: + +Arguments: + AdapterInfo - Pointer to the NIC data structure information + which the UNDI driver is layering on.. + +Returns: + +--*/ +// TODO: MicroSeconds - add argument and description to function comment +{ + if (AdapterInfo->VersionFlag == 0x30) { + (*AdapterInfo->Delay_30) (MicroSeconds); + } else { + (*AdapterInfo->Delay) (AdapterInfo->Unique_ID, MicroSeconds); + } +} + +VOID +BlockIt ( + IN NIC_DATA_INSTANCE *AdapterInfo, + UINT32 flag + ) +/*++ + +Routine Description: + +Arguments: + AdapterInfo - Pointer to the NIC data structure information + which the UNDI driver is layering on.. + +Returns: + +--*/ +// TODO: flag - add argument and description to function comment +{ + if (AdapterInfo->VersionFlag == 0x30) { + (*AdapterInfo->Block_30) (flag); + } else { + (*AdapterInfo->Block) (AdapterInfo->Unique_ID, flag); + } +} + +UINT8 +Load_Base_Regs ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + // + // we will use the linear (flat) memory model and fill our base registers + // with 0's so that the entire physical address is our offset + // + // + // we reset the statistics totals here because this is where we are loading stats addr + // + AdapterInfo->RxTotals = 0; + AdapterInfo->TxTotals = 0; + + // + // Load the statistics block address. + // + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + OutLong (AdapterInfo, (UINT32) AdapterInfo->stat_phy_addr, AdapterInfo->ioaddr + SCBPointer); + OutByte (AdapterInfo, CU_STATSADDR, AdapterInfo->ioaddr + SCBCmd); + AdapterInfo->statistics->done_marker = 0; + + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + OutLong (AdapterInfo, 0, AdapterInfo->ioaddr + SCBPointer); + OutByte (AdapterInfo, RX_ADDR_LOAD, AdapterInfo->ioaddr + SCBCmd); + + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + OutLong (AdapterInfo, 0, AdapterInfo->ioaddr + SCBPointer); + OutByte (AdapterInfo, CU_CMD_BASE, AdapterInfo->ioaddr + SCBCmd); + + return 0; +} + +UINT8 +IssueCB ( + NIC_DATA_INSTANCE *AdapterInfo, + TxCB *cmd_ptr + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + cmd_ptr - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT16 status; + + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + + // + // read the CU status, if it is idle, write the address of cb_ptr + // in the scbpointer and issue a cu_start, + // if it is suspended, remove the suspend bit in the previous command + // block and issue a resume + // + // Ensure that the CU Active Status bit is not on from previous CBs. + // + status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus); + + // + // Skip acknowledging the interrupt if it is not already set + // + + // + // ack only the cna the integer + // + if ((status & SCB_STATUS_CNA) != 0) { + OutWord (AdapterInfo, SCB_STATUS_CNA, AdapterInfo->ioaddr + SCBStatus); + + } + + if ((status & SCB_STATUS_CU_MASK) == SCB_STATUS_CU_IDLE) { + // + // give a cu_start + // + OutLong (AdapterInfo, cmd_ptr->PhysTCBAddress, AdapterInfo->ioaddr + SCBPointer); + OutByte (AdapterInfo, CU_START, AdapterInfo->ioaddr + SCBCmd); + } else { + // + // either active or suspended, give a resume + // + + cmd_ptr->PrevTCBVirtualLinkPtr->cb_header.command &= ~(CmdSuspend | CmdIntr); + OutByte (AdapterInfo, CU_RESUME, AdapterInfo->ioaddr + SCBCmd); + } + + return 0; +} + +UINT8 +Configure ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + // + // all command blocks are of TxCB format + // + TxCB *cmd_ptr; + UINT8 *data_ptr; + INT16 Index; + UINT8 my_filter; + + cmd_ptr = GetFreeCB (AdapterInfo); + data_ptr = (UINT8 *) (&cmd_ptr->PhysTBDArrayAddres); + + // + // start the config data right after the command header + // + for (Index = 0; Index < sizeof (basic_config_cmd); Index++) { + data_ptr[Index] = basic_config_cmd[Index]; + } + + my_filter = (UINT8) ((AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS) ? 1 : 0); + my_filter |= (AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST) ? 0 : 2; + + data_ptr[15] |= my_filter; + data_ptr[19] = (UINT8) (AdapterInfo->Duplex ? 0xC0 : 0x80); + data_ptr[21] = (UINT8) ((AdapterInfo->Rx_Filter & PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST) ? 0x0D : 0x05); + + // + // check if we have to use the AUI port instead + // + if ((AdapterInfo->PhyRecord[0] & 0x8000) != 0) { + data_ptr[15] |= 0x80; + data_ptr[8] = 0; + } + + BlockIt (AdapterInfo, TRUE); + cmd_ptr->cb_header.command = CmdSuspend | CmdConfigure; + + IssueCB (AdapterInfo, cmd_ptr); + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + + BlockIt (AdapterInfo, FALSE); + + CommandWaitForCompletion (cmd_ptr, AdapterInfo); + + // + // restore the cb values for tx + // + cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr; + cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0; + // + // fields beyond the immediatedata are assumed to be safe + // add the CB to the free list again + // + SetFreeCB (AdapterInfo, cmd_ptr); + return 0; +} + +UINT8 +E100bSetupIAAddr ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + // + // all command blocks are of TxCB format + // + TxCB *cmd_ptr; + UINT16 *data_ptr; + UINT16 *eaddrs; + + eaddrs = (UINT16 *) AdapterInfo->CurrentNodeAddress; + + cmd_ptr = GetFreeCB (AdapterInfo); + data_ptr = (UINT16 *) (&cmd_ptr->PhysTBDArrayAddres); + + // + // AVOID a bug (?!) here by marking the command already completed. + // + cmd_ptr->cb_header.command = (CmdSuspend | CmdIASetup); + cmd_ptr->cb_header.status = 0; + data_ptr[0] = eaddrs[0]; + data_ptr[1] = eaddrs[1]; + data_ptr[2] = eaddrs[2]; + + BlockIt (AdapterInfo, TRUE); + IssueCB (AdapterInfo, cmd_ptr); + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + BlockIt (AdapterInfo, FALSE); + + CommandWaitForCompletion (cmd_ptr, AdapterInfo); + + // + // restore the cb values for tx + // + cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr; + cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0; + // + // fields beyond the immediatedata are assumed to be safe + // add the CB to the free list again + // + SetFreeCB (AdapterInfo, cmd_ptr); + return 0; +} + +VOID +StopRU ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + Instructs the NIC to stop receiving packets. + +Arguments: + AdapterInfo - Pointer to the NIC data structure information + which the UNDI driver is layering on.. +Returns: + +--*/ +{ + if (AdapterInfo->Receive_Started) { + + // + // Todo: verify that we must wait for previous command completion. + // + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + + // + // Disable interrupts, and stop the chip's Rx process. + // + OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd); + OutWord (AdapterInfo, INT_MASK | RX_ABORT, AdapterInfo->ioaddr + SCBCmd); + + AdapterInfo->Receive_Started = FALSE; + } + + return ; +} + +INT8 +StartRU ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + Instructs the NIC to start receiving packets. + +Arguments: + AdapterInfo - Pointer to the NIC data structure information + which the UNDI driver is layering on.. +Returns: + 0 - Successful + -1 - Already Started +--*/ +{ + + if (AdapterInfo->Receive_Started) { + // + // already started + // + return -1; + } + + AdapterInfo->cur_rx_ind = 0; + AdapterInfo->Int_Status = 0; + + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + + OutLong (AdapterInfo, (UINT32) AdapterInfo->rx_phy_addr, AdapterInfo->ioaddr + SCBPointer); + OutByte (AdapterInfo, RX_START, AdapterInfo->ioaddr + SCBCmd); + + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + + AdapterInfo->Receive_Started = TRUE; + return 0; +} + +UINTN +E100bInit ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + Configures the chip. This routine expects the NIC_DATA_INSTANCE structure to be filled in. + +Arguments: + AdapterInfo - Pointer to the NIC data structure information + which the UNDI driver is layering on.. + +Returns: + 0 - Successful + PXE_STATCODE_NOT_ENOUGH_MEMORY - Insufficient length of locked memory + other - Failure initializing chip +--*/ +{ + PCI_CONFIG_HEADER *CfgHdr; + UINTN stat; + UINTN rx_size; + UINTN tx_size; + + if (AdapterInfo->MemoryLength < MEMORY_NEEDED) { + return PXE_STATCODE_NOT_ENOUGH_MEMORY; + } + + stat = MapIt ( + AdapterInfo, + AdapterInfo->MemoryPtr, + AdapterInfo->MemoryLength, + TO_AND_FROM_DEVICE, + (UINT64)(UINTN) &AdapterInfo->Mapped_MemoryPtr + ); + + if (stat != 0) { + return stat; + } + + CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]); + + // + // fill in the ioaddr, int... from the config space + // + AdapterInfo->int_num = CfgHdr->int_line; + + // + // we don't need to validate integer number, what if they don't want to assign one? + // if (AdapterInfo->int_num == 0 || AdapterInfo->int_num == 0xff) + // return PXE_STATCODE_DEVICE_FAILURE; + // + AdapterInfo->ioaddr = 0; + AdapterInfo->VendorID = CfgHdr->VendorID; + AdapterInfo->DeviceID = CfgHdr->DeviceID; + AdapterInfo->RevID = CfgHdr->RevID; + AdapterInfo->SubVendorID = CfgHdr->SubVendorID; + AdapterInfo->SubSystemID = CfgHdr->SubSystemID; + AdapterInfo->flash_addr = 0; + + // + // Read the station address EEPROM before doing the reset. + // Perhaps this should even be done before accepting the device, + // then we wouldn't have a device name with which to report the error. + // + if (E100bReadEepromAndStationAddress (AdapterInfo) != 0) { + return PXE_STATCODE_DEVICE_FAILURE; + + } + // + // ## calculate the buffer #s depending on memory given + // ## calculate the rx and tx ring pointers + // + + AdapterInfo->TxBufCnt = TX_BUFFER_COUNT; + AdapterInfo->RxBufCnt = RX_BUFFER_COUNT; + rx_size = (AdapterInfo->RxBufCnt * sizeof (RxFD)); + tx_size = (AdapterInfo->TxBufCnt * sizeof (TxCB)); + AdapterInfo->rx_ring = (RxFD *) (UINTN) (AdapterInfo->MemoryPtr); + AdapterInfo->tx_ring = (TxCB *) (UINTN) (AdapterInfo->MemoryPtr + rx_size); + AdapterInfo->statistics = (struct speedo_stats *) (UINTN) (AdapterInfo->MemoryPtr + rx_size + tx_size); + + AdapterInfo->rx_phy_addr = AdapterInfo->Mapped_MemoryPtr; + AdapterInfo->tx_phy_addr = AdapterInfo->Mapped_MemoryPtr + rx_size; + AdapterInfo->stat_phy_addr = AdapterInfo->tx_phy_addr + tx_size; + + // + // auto detect. + // + AdapterInfo->PhyAddress = 0xFF; + AdapterInfo->Rx_Filter = PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; + AdapterInfo->Receive_Started = FALSE; + AdapterInfo->mcast_list.list_len = 0; + return InitializeChip (AdapterInfo); +} + +UINT8 +E100bSetInterruptState ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + Sets the interrupt state for the NIC. + +Arguments: + AdapterInfo - Pointer to the NIC data structure information + which the UNDI driver is layering on.. +Returns: + 0 - Successful +--*/ +{ + // + // don't set receive interrupt if receiver is disabled... + // + UINT16 cmd_word; + + if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_RECEIVE) != 0) { + cmd_word = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCmd); + cmd_word &= ~INT_MASK; + OutWord (AdapterInfo, cmd_word, AdapterInfo->ioaddr + SCBCmd); + } else { + // + // disable ints, should not be given for SW Int. + // + OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd); + } + + if ((AdapterInfo->int_mask & PXE_OPFLAGS_INTERRUPT_SOFTWARE) != 0) { + // + // reset the bit in our mask, it is only one time!! + // + AdapterInfo->int_mask &= ~(PXE_OPFLAGS_INTERRUPT_SOFTWARE); + cmd_word = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCmd); + cmd_word |= DRVR_INT; + OutWord (AdapterInfo, cmd_word, AdapterInfo->ioaddr + SCBCmd); + } + + return 0; +} +// +// we are not going to disable broadcast for the WOL's sake! +// +UINTN +E100bSetfilter ( + NIC_DATA_INSTANCE *AdapterInfo, + UINT16 new_filter, + UINT64 cpb, + UINT32 cpbsize + ) +/*++ + +Routine Description: + Instructs the NIC to start receiving packets. + +Arguments: + AdapterInfo - Pointer to the NIC data structure information + which the UNDI driver is layering on.. + new_filter - + cpb - + cpbsize - + +Returns: + 0 - Successful + -1 - Already Started +--*/ +{ + PXE_CPB_RECEIVE_FILTERS *mc_list = (PXE_CPB_RECEIVE_FILTERS *) (UINTN)cpb; + UINT16 cfg_flt; + UINT16 old_filter; + UINT16 Index; + UINT16 Index2; + UINT16 mc_count; + TxCB *cmd_ptr; + struct MC_CB_STRUCT *data_ptr; + UINT16 mc_byte_cnt; + + old_filter = AdapterInfo->Rx_Filter; + + // + // only these bits need a change in the configuration + // actually change in bcast requires configure but we ignore that change + // + cfg_flt = PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS | + PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; + + if ((old_filter & cfg_flt) != (new_filter & cfg_flt)) { + XmitWaitForCompletion (AdapterInfo); + + if (AdapterInfo->Receive_Started) { + StopRU (AdapterInfo); + } + + AdapterInfo->Rx_Filter = (UINT8) (new_filter | PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST); + Configure (AdapterInfo); + } + + // + // check if mcast setting changed + // + if ( ((new_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != + (old_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) ) || + (mc_list != NULL) ) { + + + if (mc_list != NULL) { + mc_count = AdapterInfo->mcast_list.list_len = (UINT16) (cpbsize / PXE_MAC_LENGTH); + + for (Index = 0; (Index < mc_count && Index < MAX_MCAST_ADDRESS_CNT); Index++) { + for (Index2 = 0; Index2 < PXE_MAC_LENGTH; Index2++) { + AdapterInfo->mcast_list.mc_list[Index][Index2] = mc_list->MCastList[Index][Index2]; + } + } + } + + // + // are we setting the list or resetting?? + // + if ((new_filter & PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) { + // + // we are setting a new list! + // + mc_count = AdapterInfo->mcast_list.list_len; + // + // count should be the actual # of bytes in the list + // so multiply this with 6 + // + mc_byte_cnt = (UINT16) ((mc_count << 2) + (mc_count << 1)); + AdapterInfo->Rx_Filter |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; + } else { + // + // disabling the list in the NIC. + // + mc_byte_cnt = mc_count = 0; + AdapterInfo->Rx_Filter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST); + } + + // + // before issuing any new command! + // + XmitWaitForCompletion (AdapterInfo); + + if (AdapterInfo->Receive_Started) { + StopRU (AdapterInfo); + + } + + cmd_ptr = GetFreeCB (AdapterInfo); + if (cmd_ptr == NULL) { + return PXE_STATCODE_QUEUE_FULL; + } + // + // fill the command structure and issue + // + data_ptr = (struct MC_CB_STRUCT *) (&cmd_ptr->PhysTBDArrayAddres); + // + // first 2 bytes are the count; + // + data_ptr->count = mc_byte_cnt; + for (Index = 0; Index < mc_count; Index++) { + for (Index2 = 0; Index2 < PXE_HWADDR_LEN_ETHER; Index2++) { + data_ptr->m_list[Index][Index2] = AdapterInfo->mcast_list.mc_list[Index][Index2]; + } + } + + cmd_ptr->cb_header.command = CmdSuspend | CmdMulticastList; + cmd_ptr->cb_header.status = 0; + + BlockIt (AdapterInfo, TRUE); + IssueCB (AdapterInfo, cmd_ptr); + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + + BlockIt (AdapterInfo, FALSE); + + CommandWaitForCompletion (cmd_ptr, AdapterInfo); + + cmd_ptr->PhysTBDArrayAddres = cmd_ptr->PhysArrayAddr; + cmd_ptr->ByteCount = cmd_ptr->Threshold = cmd_ptr->TBDCount = 0; + // + // fields beyond the immediatedata are assumed to be safe + // add the CB to the free list again + // + SetFreeCB (AdapterInfo, cmd_ptr); + } + + if (new_filter != 0) { + // + // enable unicast and start the RU + // + AdapterInfo->Rx_Filter |= (new_filter | PXE_OPFLAGS_RECEIVE_FILTER_UNICAST); + StartRU (AdapterInfo); + } else { + // + // may be disabling everything! + // + if (AdapterInfo->Receive_Started) { + StopRU (AdapterInfo); + } + + AdapterInfo->Rx_Filter |= (~PXE_OPFLAGS_RECEIVE_FILTER_UNICAST); + } + + return 0; +} + +UINTN +E100bTransmit ( + NIC_DATA_INSTANCE *AdapterInfo, + UINT64 cpb, + UINT16 opflags + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + cpb - TODO: add argument description + opflags - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + PXE_CPB_TRANSMIT_FRAGMENTS *tx_ptr_f; + PXE_CPB_TRANSMIT *tx_ptr_1; + TxCB *tcb_ptr; + UINT64 Tmp_ptr; + UINTN stat; + INT32 Index; + UINT16 wait_sec; + + tx_ptr_1 = (PXE_CPB_TRANSMIT *) (UINTN) cpb; + tx_ptr_f = (PXE_CPB_TRANSMIT_FRAGMENTS *) (UINTN) cpb; + + // + // stop reentrancy here + // + if (AdapterInfo->in_transmit) { + return PXE_STATCODE_BUSY; + + } + + AdapterInfo->in_transmit = TRUE; + + // + // Prevent interrupts from changing the Tx ring from underneath us. + // + // Calculate the Tx descriptor entry. + // + if ((tcb_ptr = GetFreeCB (AdapterInfo)) == NULL) { + AdapterInfo->in_transmit = FALSE; + return PXE_STATCODE_QUEUE_FULL; + } + + AdapterInfo->TxTotals++; + + tcb_ptr->cb_header.command = (CmdSuspend | CmdTx | CmdTxFlex); + tcb_ptr->cb_header.status = 0; + + // + // no immediate data, set EOF in the ByteCount + // + tcb_ptr->ByteCount = 0x8000; + + // + // The data region is always in one buffer descriptor, Tx FIFO + // threshold of 256. + // 82557 multiplies the threashold value by 8, so give 256/8 + // + tcb_ptr->Threshold = 32; + if ((opflags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) { + + if (tx_ptr_f->FragCnt > MAX_XMIT_FRAGMENTS) { + SetFreeCB (AdapterInfo, tcb_ptr); + AdapterInfo->in_transmit = FALSE; + return PXE_STATCODE_INVALID_PARAMETER; + } + + tcb_ptr->TBDCount = (UINT8) tx_ptr_f->FragCnt; + + for (Index = 0; Index < tx_ptr_f->FragCnt; Index++) { + stat = MapIt ( + AdapterInfo, + tx_ptr_f->FragDesc[Index].FragAddr, + tx_ptr_f->FragDesc[Index].FragLen, + TO_DEVICE, + (UINT64)(UINTN) &Tmp_ptr + ); + if (stat != 0) { + SetFreeCB (AdapterInfo, tcb_ptr); + AdapterInfo->in_transmit = FALSE; + return PXE_STATCODE_INVALID_PARAMETER; + } + + tcb_ptr->TBDArray[Index].phys_buf_addr = (UINT32) Tmp_ptr; + tcb_ptr->TBDArray[Index].buf_len = tx_ptr_f->FragDesc[Index].FragLen; + } + + tcb_ptr->free_data_ptr = tx_ptr_f->FragDesc[0].FragAddr; + + } else { + // + // non fragmented case + // + tcb_ptr->TBDCount = 1; + stat = MapIt ( + AdapterInfo, + tx_ptr_1->FrameAddr, + tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen, + TO_DEVICE, + (UINT64)(UINTN) &Tmp_ptr + ); + if (stat != 0) { + SetFreeCB (AdapterInfo, tcb_ptr); + AdapterInfo->in_transmit = FALSE; + return PXE_STATCODE_INVALID_PARAMETER; + } + + tcb_ptr->TBDArray[0].phys_buf_addr = (UINT32) (Tmp_ptr); + tcb_ptr->TBDArray[0].buf_len = tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen; + tcb_ptr->free_data_ptr = tx_ptr_1->FrameAddr; + } + + // + // must wait for previous command completion only if it was a non-transmit + // + BlockIt (AdapterInfo, TRUE); + IssueCB (AdapterInfo, tcb_ptr); + BlockIt (AdapterInfo, FALSE); + + // + // see if we need to wait for completion here + // + if ((opflags & PXE_OPFLAGS_TRANSMIT_BLOCK) != 0) { + // + // don't wait for more than 1 second!!! + // + wait_sec = 1000; + while (tcb_ptr->cb_header.status == 0) { + DelayIt (AdapterInfo, 10); + wait_sec--; + if (wait_sec == 0) { + break; + } + } + // + // we need to un-map any mapped buffers here + // + if ((opflags & PXE_OPFLAGS_TRANSMIT_FRAGMENTED) != 0) { + + for (Index = 0; Index < tx_ptr_f->FragCnt; Index++) { + Tmp_ptr = tcb_ptr->TBDArray[Index].phys_buf_addr; + UnMapIt ( + AdapterInfo, + tx_ptr_f->FragDesc[Index].FragAddr, + tx_ptr_f->FragDesc[Index].FragLen, + TO_DEVICE, + (UINT64) Tmp_ptr + ); + } + } else { + Tmp_ptr = tcb_ptr->TBDArray[0].phys_buf_addr; + UnMapIt ( + AdapterInfo, + tx_ptr_1->FrameAddr, + tx_ptr_1->DataLen + tx_ptr_1->MediaheaderLen, + TO_DEVICE, + (UINT64) Tmp_ptr + ); + } + + if (tcb_ptr->cb_header.status == 0) { + SetFreeCB (AdapterInfo, tcb_ptr); + AdapterInfo->in_transmit = FALSE; + return PXE_STATCODE_DEVICE_FAILURE; + } + + SetFreeCB (AdapterInfo, tcb_ptr); + } + // + // CB will be set free later in get_status (or when we run out of xmit buffers + // + AdapterInfo->in_transmit = FALSE; + + return 0; +} + +UINTN +E100bReceive ( + NIC_DATA_INSTANCE *AdapterInfo, + UINT64 cpb, + UINT64 db + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + cpb - TODO: add argument description + db - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + PXE_CPB_RECEIVE *rx_cpbptr; + PXE_DB_RECEIVE *rx_dbptr; + RxFD *rx_ptr; + INT32 status; + INT32 Index; + UINT16 pkt_len; + UINT16 ret_code; + PXE_FRAME_TYPE pkt_type; + UINT16 Tmp_len; + EtherHeader *hdr_ptr; + ret_code = PXE_STATCODE_NO_DATA; + pkt_type = PXE_FRAME_TYPE_NONE; + status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus); + AdapterInfo->Int_Status |= status; + // + // acknoledge the interrupts + // + OutWord (AdapterInfo, (UINT16) (status & 0xfc00), (UINT32) (AdapterInfo->ioaddr + SCBStatus)); + + // + // include the prev ints as well + // + status = AdapterInfo->Int_Status; + rx_cpbptr = (PXE_CPB_RECEIVE *) (UINTN) cpb; + rx_dbptr = (PXE_DB_RECEIVE *) (UINTN) db; + + rx_ptr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind]; + + // + // be in a loop just in case (we may drop a pkt) + // + while ((status = rx_ptr->cb_header.status) & RX_COMPLETE) { + + AdapterInfo->RxTotals++; + // + // If we own the next entry, it's a new packet. Send it up. + // + if (rx_ptr->forwarded) { + goto FreeRFD; + + } + + // + // discard bad frames + // + + // + // crc, align, dma overrun, too short, receive error (v22 no coll) + // + if ((status & 0x0D90) != 0) { + goto FreeRFD; + + } + + // + // make sure the status is OK + // + if ((status & 0x02000) == 0) { + goto FreeRFD; + } + + pkt_len = (UINT16) (rx_ptr->ActualCount & 0x3fff); + + if (pkt_len != 0) { + + Tmp_len = pkt_len; + if (pkt_len > rx_cpbptr->BufferLen) { + Tmp_len = (UINT16) rx_cpbptr->BufferLen; + } + + CopyMem ((INT8 *) (UINTN) rx_cpbptr->BufferAddr, (INT8 *) &rx_ptr->RFDBuffer, Tmp_len); + + hdr_ptr = (EtherHeader *) &rx_ptr->RFDBuffer; + // + // fill the CDB and break the loop + // + + // + // includes header + // + rx_dbptr->FrameLen = pkt_len; + rx_dbptr->MediaHeaderLen = PXE_MAC_HEADER_LEN_ETHER; + + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { + if (hdr_ptr->dest_addr[Index] != AdapterInfo->CurrentNodeAddress[Index]) { + break; + } + } + + if (Index >= PXE_HWADDR_LEN_ETHER) { + pkt_type = PXE_FRAME_TYPE_UNICAST; + } else { + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { + if (hdr_ptr->dest_addr[Index] != AdapterInfo->BroadcastNodeAddress[Index]) { + break; + } + } + + if (Index >= PXE_HWADDR_LEN_ETHER) { + pkt_type = PXE_FRAME_TYPE_BROADCAST; + } else { + if ((hdr_ptr->dest_addr[0] & 1) == 1) { + // + // mcast + // + + pkt_type = PXE_FRAME_TYPE_MULTICAST; + } else { + pkt_type = PXE_FRAME_TYPE_PROMISCUOUS; + } + } + } + + rx_dbptr->Type = pkt_type; + rx_dbptr->Protocol = hdr_ptr->type; + + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { + rx_dbptr->SrcAddr[Index] = hdr_ptr->src_addr[Index]; + rx_dbptr->DestAddr[Index] = hdr_ptr->dest_addr[Index]; + } + + rx_ptr->forwarded = TRUE; + // + // success + // + ret_code = 0; + Recycle_RFD (AdapterInfo, AdapterInfo->cur_rx_ind); + AdapterInfo->cur_rx_ind++; + if (AdapterInfo->cur_rx_ind == AdapterInfo->RxBufCnt) { + AdapterInfo->cur_rx_ind = 0; + } + break; + } + +FreeRFD: + Recycle_RFD (AdapterInfo, AdapterInfo->cur_rx_ind); + AdapterInfo->cur_rx_ind++; + if (AdapterInfo->cur_rx_ind == AdapterInfo->RxBufCnt) { + AdapterInfo->cur_rx_ind = 0; + } + + rx_ptr = &AdapterInfo->rx_ring[AdapterInfo->cur_rx_ind]; + } + + if (pkt_type == PXE_FRAME_TYPE_NONE) { + AdapterInfo->Int_Status &= (~SCB_STATUS_FR); + } + + status = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBStatus); + if ((status & SCB_RUS_NO_RESOURCES) != 0) { + // + // start the receive unit here! + // leave all the filled frames, + // + SetupReceiveQueues (AdapterInfo); + OutLong (AdapterInfo, (UINT32) AdapterInfo->rx_phy_addr, AdapterInfo->ioaddr + SCBPointer); + OutWord (AdapterInfo, RX_START, AdapterInfo->ioaddr + SCBCmd); + AdapterInfo->cur_rx_ind = 0; + } + + return ret_code; +} + +INT16 +E100bReadEepromAndStationAddress ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + INT32 Index; + INT32 Index2; + UINT16 sum; + UINT16 eeprom_len; + UINT8 addr_len; + UINT16 *eedata; + + eedata = (UINT16 *) (&AdapterInfo->NVData[0]); + + sum = 0; + addr_len = E100bGetEepromAddrLen (AdapterInfo); + + // + // in words + // + AdapterInfo->NVData_Len = eeprom_len = (UINT16) (1 << addr_len); + for (Index2 = 0, Index = 0; Index < eeprom_len; Index++) { + UINT16 value; + value = E100bReadEeprom (AdapterInfo, Index, addr_len); + eedata[Index] = value; + sum = (UINT16) (sum + value); + if (Index < 3) { + AdapterInfo->PermNodeAddress[Index2++] = (UINT8) value; + AdapterInfo->PermNodeAddress[Index2++] = (UINT8) (value >> 8); + } + } + + if (sum != 0xBABA) { + return -1; + } + + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { + AdapterInfo->CurrentNodeAddress[Index] = AdapterInfo->PermNodeAddress[Index]; + } + + for (Index = 0; Index < PXE_HWADDR_LEN_ETHER; Index++) { + AdapterInfo->BroadcastNodeAddress[Index] = 0xff; + } + + for (Index = PXE_HWADDR_LEN_ETHER; Index < PXE_MAC_LENGTH; Index++) { + AdapterInfo->CurrentNodeAddress[Index] = 0; + AdapterInfo->PermNodeAddress[Index] = 0; + AdapterInfo->BroadcastNodeAddress[Index] = 0; + } + + return 0; +} + +// +// CBList is a circular linked list +// 1) When all are free, Tail->next == Head and FreeCount == # allocated +// 2) When none are free, Tail == Head and FreeCount == 0 +// 3) when one is free, Tail == Head and Freecount == 1 +// 4) First non-Free frame is always at Tail->next +// +UINT8 +SetupCBlink ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + TxCB *head_ptr; + TxCB *tail_ptr; + TxCB *cur_ptr; + INT32 Index; + UINTN array_off; + + cur_ptr = &(AdapterInfo->tx_ring[0]); + array_off = (UINTN) (&cur_ptr->TBDArray) - (UINTN) cur_ptr; + for (Index = 0; Index < AdapterInfo->TxBufCnt; Index++) { + cur_ptr[Index].cb_header.status = 0; + cur_ptr[Index].cb_header.command = 0; + + cur_ptr[Index].PhysTCBAddress = + (UINT32) AdapterInfo->tx_phy_addr + (Index * sizeof (TxCB)); + + cur_ptr[Index].PhysArrayAddr = (UINT32)(cur_ptr[Index].PhysTCBAddress + array_off); + cur_ptr[Index].PhysTBDArrayAddres = (UINT32)(cur_ptr[Index].PhysTCBAddress + array_off); + + cur_ptr->free_data_ptr = (UINT64) 0; + + if (Index < AdapterInfo->TxBufCnt - 1) { + cur_ptr[Index].cb_header.link = cur_ptr[Index].PhysTCBAddress + sizeof (TxCB); + cur_ptr[Index].NextTCBVirtualLinkPtr = &cur_ptr[Index + 1]; + cur_ptr[Index + 1].PrevTCBVirtualLinkPtr = &cur_ptr[Index]; + } + } + + head_ptr = &cur_ptr[0]; + tail_ptr = &cur_ptr[AdapterInfo->TxBufCnt - 1]; + tail_ptr->cb_header.link = head_ptr->PhysTCBAddress; + tail_ptr->NextTCBVirtualLinkPtr = head_ptr; + head_ptr->PrevTCBVirtualLinkPtr = tail_ptr; + + AdapterInfo->FreeCBCount = AdapterInfo->TxBufCnt; + AdapterInfo->FreeTxHeadPtr = head_ptr; + // + // set tail of the free list, next to this would be either in use + // or the head itself + // + AdapterInfo->FreeTxTailPtr = tail_ptr; + + AdapterInfo->xmit_done_head = AdapterInfo->xmit_done_tail = 0; + + return 0; +} + +TxCB * +GetFreeCB ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + TxCB *free_cb_ptr; + + // + // claim any hanging free CBs + // + if (AdapterInfo->FreeCBCount <= 1) { + CheckCBList (AdapterInfo); + } + + // + // don't use up the last CB problem if the previous CB that the CU used + // becomes the last CB we submit because of the SUSPEND bit we set. + // the CU thinks it was never cleared. + // + + if (AdapterInfo->FreeCBCount <= 1) { + return NULL; + } + + BlockIt (AdapterInfo, TRUE); + free_cb_ptr = AdapterInfo->FreeTxHeadPtr; + AdapterInfo->FreeTxHeadPtr = free_cb_ptr->NextTCBVirtualLinkPtr; + --AdapterInfo->FreeCBCount; + BlockIt (AdapterInfo, FALSE); + return free_cb_ptr; +} + +VOID +SetFreeCB ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN TxCB *cb_ptr + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + cb_ptr - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + // + // here we assume cb are returned in the order they are taken out + // and we link the newly freed cb at the tail of free cb list + // + cb_ptr->cb_header.status = 0; + cb_ptr->free_data_ptr = (UINT64) 0; + + AdapterInfo->FreeTxTailPtr = cb_ptr; + ++AdapterInfo->FreeCBCount; + return ; +} + +UINT16 +next ( + IN UINT16 ind + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ind - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT16 Tmp; + + Tmp = (UINT16) (ind + 1); + if (Tmp >= (TX_BUFFER_COUNT << 1)) { + Tmp = 0; + } + + return Tmp; +} + +UINT16 +CheckCBList ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + TxCB *Tmp_ptr; + UINT16 cnt; + + cnt = 0; + while (1) { + Tmp_ptr = AdapterInfo->FreeTxTailPtr->NextTCBVirtualLinkPtr; + if ((Tmp_ptr->cb_header.status & CMD_STATUS_MASK) != 0) { + // + // check if Q is full + // + if (next (AdapterInfo->xmit_done_tail) != AdapterInfo->xmit_done_head) { + AdapterInfo->xmit_done[AdapterInfo->xmit_done_tail] = Tmp_ptr->free_data_ptr; + + UnMapIt ( + AdapterInfo, + Tmp_ptr->free_data_ptr, + Tmp_ptr->TBDArray[0].buf_len, + TO_DEVICE, + (UINT64) Tmp_ptr->TBDArray[0].phys_buf_addr + ); + + AdapterInfo->xmit_done_tail = next (AdapterInfo->xmit_done_tail); + } + + SetFreeCB (AdapterInfo, Tmp_ptr); + } else { + break; + } + } + + return cnt; +} +// +// Description : Initialize the RFD list list by linking each element together +// in a circular list. The simplified memory model is used. +// All data is in the RFD. The RFDs are linked together and the +// last one points back to the first one. When the current RFD +// is processed (frame received), its EL bit is set and the EL +// bit in the previous RXFD is cleared. +// Allocation done during INIT, this is making linked list. +// +UINT8 +SetupReceiveQueues ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + RxFD *rx_ptr; + RxFD *head_ptr; + RxFD *tail_ptr; + UINT16 Index; + + AdapterInfo->cur_rx_ind = 0; + rx_ptr = (&AdapterInfo->rx_ring[0]); + + for (Index = 0; Index < AdapterInfo->RxBufCnt; Index++) { + rx_ptr[Index].cb_header.status = 0; + rx_ptr[Index].cb_header.command = 0; + rx_ptr[Index].RFDSize = RX_BUFFER_SIZE; + rx_ptr[Index].ActualCount = 0; + // + // RBDs not used, simple memory model + // + rx_ptr[Index].rx_buf_addr = (UINT32) (-1); + + // + // RBDs not used, simple memory model + // + rx_ptr[Index].forwarded = FALSE; + + // + // don't use Tmp_ptr if it is beyond the last one + // + if (Index < AdapterInfo->RxBufCnt - 1) { + rx_ptr[Index].cb_header.link = (UINT32) AdapterInfo->rx_phy_addr + ((Index + 1) * sizeof (RxFD)); + } + } + + head_ptr = (&AdapterInfo->rx_ring[0]); + tail_ptr = (&AdapterInfo->rx_ring[AdapterInfo->RxBufCnt - 1]); + tail_ptr->cb_header.link = (UINT32) AdapterInfo->rx_phy_addr; + + // + // set the EL bit + // + tail_ptr->cb_header.command = 0xC000; + AdapterInfo->RFDTailPtr = tail_ptr; + return 0; +} + +VOID +Recycle_RFD ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT16 rx_index + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + rx_index - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + RxFD *rx_ptr; + RxFD *tail_ptr; + // + // change the EL bit and change the AdapterInfo->RxTailPtr + // rx_ptr is assumed to be the head of the Q + // AdapterInfo->rx_forwarded[rx_index] = FALSE; + // + rx_ptr = &AdapterInfo->rx_ring[rx_index]; + tail_ptr = AdapterInfo->RFDTailPtr; + // + // set el_bit and suspend bit + // + rx_ptr->cb_header.command = 0xc000; + rx_ptr->cb_header.status = 0; + rx_ptr->ActualCount = 0; + rx_ptr->forwarded = FALSE; + AdapterInfo->RFDTailPtr = rx_ptr; + // + // resetting the el_bit. + // + tail_ptr->cb_header.command = 0; + // + // check the receive unit, fix if there is any problem + // + return ; +} +// +// Serial EEPROM section. +// +// EEPROM_Ctrl bits. +// +#define EE_SHIFT_CLK 0x01 /* EEPROM shift clock. */ +#define EE_CS 0x02 /* EEPROM chip select. */ +#define EE_DI 0x04 /* EEPROM chip data in. */ +#define EE_WRITE_0 0x01 +#define EE_WRITE_1 0x05 +#define EE_DO 0x08 /* EEPROM chip data out. */ +#define EE_ENB (0x4800 | EE_CS) + +// +// Delay between EEPROM clock transitions. +// This will actually work with no delay on 33Mhz PCI. +// +#define eeprom_delay(nanosec) DelayIt (AdapterInfo, nanosec); + +// +// The EEPROM commands include the alway-set leading bit. +// +#define EE_WRITE_CMD 5 // 101b +#define EE_READ_CMD 6 // 110b +#define EE_ERASE_CMD (7 << 6) + +VOID +shift_bits_out ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT16 val, + IN UINT8 num_bits + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + val - TODO: add argument description + num_bits - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + INT32 Index; + UINT8 Tmp; + UINT32 EEAddr; + + EEAddr = AdapterInfo->ioaddr + SCBeeprom; + + for (Index = num_bits; Index >= 0; Index--) { + INT16 dataval; + + // + // will be 0 or 4 + // + dataval = (INT16) ((val & (1 << Index)) ? EE_DI : 0); + + // + // mask off the data_in bit + // + Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) &~EE_DI); + Tmp |= dataval; + OutByte (AdapterInfo, Tmp, EEAddr); + eeprom_delay (100); + // + // raise the eeprom clock + // + OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr); + eeprom_delay (150); + // + // lower the eeprom clock + // + OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr); + eeprom_delay (150); + } +} + +UINT16 +shift_bits_in ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT8 Tmp; + INT32 Index; + UINT16 retval; + UINT32 EEAddr; + + EEAddr = AdapterInfo->ioaddr + SCBeeprom; + + retval = 0; + for (Index = 15; Index >= 0; Index--) { + // + // raise the clock + // + + // + // mask off the data_in bit + // + Tmp = InByte (AdapterInfo, EEAddr); + OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr); + eeprom_delay (100); + Tmp = InByte (AdapterInfo, EEAddr); + retval = (UINT16) ((retval << 1) | ((Tmp & EE_DO) ? 1 : 0)); + // + // lower the clock + // + OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr); + eeprom_delay (100); + } + + return retval; +} + +BOOLEAN +E100bSetEepromLockOut ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine sets the EEPROM lockout bit to gain exclusive access to the + eeprom. the access bit is the most significant bit in the General Control + Register 2 in the SCB space. + +Arguments: + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + TRUE - if it got the access + FALSE - if it fails to get the exclusive access + +--*/ +{ + UINTN wait; + UINT8 tmp; + + if ((AdapterInfo->DeviceID == D102_DEVICE_ID) || + (AdapterInfo->RevID >= D102_REVID)) { + + wait = 500; + + while (wait--) { + + tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2); + tmp |= GCR2_EEPROM_ACCESS_SEMAPHORE; + OutByte (AdapterInfo, tmp, AdapterInfo->ioaddr + SCBGenCtrl2); + + DelayIt (AdapterInfo, 50); + tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2); + + if (tmp & GCR2_EEPROM_ACCESS_SEMAPHORE) { + return TRUE; + } + } + + return FALSE; + } + + return TRUE; +} + +VOID +E100bReSetEepromLockOut ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine Resets the EEPROM lockout bit to giveup access to the + eeprom. the access bit is the most significant bit in the General Control + Register 2 in the SCB space. + +Arguments: + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + None + +--*/ +{ + UINT8 tmp; + + if ((AdapterInfo->DeviceID == D102_DEVICE_ID) || + (AdapterInfo->RevID >= D102_REVID)) { + + tmp = InByte (AdapterInfo, AdapterInfo->ioaddr + SCBGenCtrl2); + tmp &= ~(GCR2_EEPROM_ACCESS_SEMAPHORE); + OutByte (AdapterInfo, tmp, AdapterInfo->ioaddr + SCBGenCtrl2); + + DelayIt (AdapterInfo, 50); + } +} + +UINT16 +E100bReadEeprom ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN INT32 Location, + IN UINT8 AddrLen + ) +/*++ + +Routine Description: + Using the NIC data structure information, read the EEPROM to get a Word of data for the MAC address. + +Arguments: + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + Location - Word offset into the MAC address to read. + AddrLen - Number of bits of address length. + +Returns: + RetVal - The word read from the EEPROM. + +--*/ +{ + UINT16 RetVal; + UINT8 Tmp; + + UINT32 EEAddr; + UINT16 ReadCmd; + + EEAddr = AdapterInfo->ioaddr + SCBeeprom; + ReadCmd = (UINT16) (Location | (EE_READ_CMD << AddrLen)); + + RetVal = 0; + + // + // get exclusive access to the eeprom first! + // + E100bSetEepromLockOut (AdapterInfo); + + // + // eeprom control reg bits: x,x,x,x,DO,DI,CS,SK + // to write the opcode+data value out one bit at a time in DI starting at msb + // and then out a 1 to sk, wait, out 0 to SK and wait + // repeat this for all the bits to be written + // + + // + // 11110010b + // + Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) & 0xF2); + OutByte (AdapterInfo, (UINT8) (Tmp | EE_CS), EEAddr); + + // + // 3 for the read opcode 110b + // + shift_bits_out (AdapterInfo, ReadCmd, (UINT8) (3 + AddrLen)); + + // + // read the eeprom word one bit at a time + // + RetVal = shift_bits_in (AdapterInfo); + + // + // Terminate the EEPROM access and leave eeprom in a clean state. + // + Tmp = InByte (AdapterInfo, EEAddr); + Tmp &= ~(EE_CS | EE_DI); + OutByte (AdapterInfo, Tmp, EEAddr); + + // + // raise the clock and lower the eeprom shift clock + // + OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr); + eeprom_delay (100); + + OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr); + eeprom_delay (100); + + // + // giveup access to the eeprom + // + E100bReSetEepromLockOut (AdapterInfo); + + return RetVal; +} + +UINT8 +E100bGetEepromAddrLen ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + Using the NIC data structure information, read the EEPROM to determine how many bits of address length + this EEPROM is in Words. + +Arguments: + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + RetVal - The word read from the EEPROM. + +--*/ +{ + UINT8 Tmp; + UINT8 AddrLen; + UINT32 EEAddr; + // + // assume 64word eeprom (so,6 bits of address_length) + // + UINT16 ReadCmd; + + EEAddr = AdapterInfo->ioaddr + SCBeeprom; + ReadCmd = (EE_READ_CMD << 6); + + // + // get exclusive access to the eeprom first! + // + E100bSetEepromLockOut (AdapterInfo); + + // + // address we are trying to read is 0 + // eeprom control reg bits: x,x,x,x,DO,,DI,,CS,SK + // to write the opcode+data value out one bit at a time in DI starting at msb + // and then out a 1 to sk, wait, out 0 to SK and wait + // repeat this for all the bits to be written + // + Tmp = (UINT8) (InByte (AdapterInfo, EEAddr) & 0xF2); + + // + // enable eeprom access + // + OutByte (AdapterInfo, (UINT8) (Tmp | EE_CS), EEAddr); + + // + // 3 for opcode, 6 for the default address len + // + shift_bits_out (AdapterInfo, ReadCmd, (UINT8) (3 + 6)); + + // + // (in case of a 64 word eeprom). + // read the "dummy zero" from EE_DO to say that the address we wrote + // (six 0s) is accepted, write more zeros (until 8) to get a "dummy zero" + // + + // + // assume the smallest + // + AddrLen = 6; + Tmp = InByte (AdapterInfo, EEAddr); + while ((AddrLen < 8) && ((Tmp & EE_DO) != 0)) { + OutByte (AdapterInfo, (UINT8) (Tmp &~EE_DI), EEAddr); + eeprom_delay (100); + + // + // raise the eeprom clock + // + OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr); + eeprom_delay (150); + + // + // lower the eeprom clock + // + OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr); + eeprom_delay (150); + Tmp = InByte (AdapterInfo, EEAddr); + AddrLen++; + } + + // + // read the eeprom word, even though we don't need this + // + shift_bits_in (AdapterInfo); + + // + // Terminate the EEPROM access. + // + Tmp = InByte (AdapterInfo, EEAddr); + Tmp &= ~(EE_CS | EE_DI); + OutByte (AdapterInfo, Tmp, EEAddr); + + // + // raise the clock and lower the eeprom shift clock + // + OutByte (AdapterInfo, (UINT8) (Tmp | EE_SHIFT_CLK), EEAddr); + eeprom_delay (100); + + OutByte (AdapterInfo, (UINT8) (Tmp &~EE_SHIFT_CLK), EEAddr); + eeprom_delay (100); + + // + // giveup access to the eeprom! + // + E100bReSetEepromLockOut (AdapterInfo); + + return AddrLen; +} + +UINTN +E100bStatistics ( + NIC_DATA_INSTANCE *AdapterInfo, + UINT64 DBaddr, + UINT16 DBsize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + DBaddr - TODO: add argument description + DBsize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + PXE_DB_STATISTICS db; + // + // wait upto one second (each wait is 100 micro s) + // + UINT32 Wait; + Wait = 10000; + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + + // + // Clear statistics done marker. + // + AdapterInfo->statistics->done_marker = 0; + + // + // Issue statistics dump (or dump w/ reset) command. + // + OutByte ( + AdapterInfo, + (UINT8) (DBsize ? CU_SHOWSTATS : CU_DUMPSTATS), + (UINT32) (AdapterInfo->ioaddr + SCBCmd) + ); + + // + // Wait for command to complete. + // + // zero the db here just to chew up a little more time. + // + + ZeroMem ((VOID *) &db, sizeof db); + + while (Wait != 0) { + // + // Wait a bit before checking. + // + + DelayIt (AdapterInfo, 100); + + // + // Look for done marker at end of statistics. + // + + switch (AdapterInfo->statistics->done_marker) { + case 0xA005: + case 0xA007: + break; + + default: + Wait--; + continue; + } + + // + // if we did not "continue" from the above switch, we are done, + // + break; + } + + // + // If this is a reset, we are out of here! + // + if (DBsize == 0) { + return PXE_STATCODE_SUCCESS; + } + + // + // Convert NIC statistics counter format to EFI/UNDI + // specification statistics counter format. + // + + // + // 54 3210 fedc ba98 7654 3210 + // db.Supported = 01 0000 0100 1101 0001 0111; + // + db.Supported = 0x104D17; + + // + // Statistics from the NIC + // + + db.Data[0x01] = AdapterInfo->statistics->rx_good_frames; + + db.Data[0x02] = AdapterInfo->statistics->rx_runt_errs; + + db.Data[0x08] = AdapterInfo->statistics->rx_crc_errs + + AdapterInfo->statistics->rx_align_errs; + + db.Data[0x04] = db.Data[0x02] + + db.Data[0x08] + + AdapterInfo->statistics->rx_resource_errs + + AdapterInfo->statistics->rx_overrun_errs; + + db.Data[0x00] = db.Data[0x01] + db.Data[0x04]; + + db.Data[0x0B] = AdapterInfo->statistics->tx_good_frames; + + db.Data[0x0E] = AdapterInfo->statistics->tx_coll16_errs + + AdapterInfo->statistics->tx_late_colls + + AdapterInfo->statistics->tx_underruns + + AdapterInfo->statistics->tx_one_colls + + AdapterInfo->statistics->tx_multi_colls; + + db.Data[0x14] = AdapterInfo->statistics->tx_total_colls; + + db.Data[0x0A] = db.Data[0x0B] + + db.Data[0x0E] + + AdapterInfo->statistics->tx_lost_carrier; + + if (DBsize > sizeof db) { + DBsize = sizeof db; + } + + CopyMem ((VOID *) (UINTN) DBaddr, (VOID *) &db, (UINTN) DBsize); + + return PXE_STATCODE_SUCCESS; +} + +UINTN +E100bReset ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN INT32 OpFlags + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + OpFlags - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + + UINT16 save_filter; + // + // disable the interrupts + // + OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd); + + // + // wait for the tx queue to complete + // + CheckCBList (AdapterInfo); + + XmitWaitForCompletion (AdapterInfo); + + if (AdapterInfo->Receive_Started) { + StopRU (AdapterInfo); + } + + InitializeChip (AdapterInfo); + + // + // check the opflags and restart receive filters + // + if ((OpFlags & PXE_OPFLAGS_RESET_DISABLE_FILTERS) == 0) { + + save_filter = AdapterInfo->Rx_Filter; + // + // if we give the filter same as Rx_Filter, + // this routine will not set mcast list (it thinks there is no change) + // to force it, we will reset that flag in the Rx_Filter + // + AdapterInfo->Rx_Filter &= (~PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST); + E100bSetfilter (AdapterInfo, save_filter, (UINT64) 0, (UINT32) 0); + } + + if ((OpFlags & PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS) != 0) { + // + // disable the interrupts + // + AdapterInfo->int_mask = 0; + } + // + // else leave the interrupt in the pre-set state!!! + // + E100bSetInterruptState (AdapterInfo); + + return 0; +} + +UINTN +E100bShutdown ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + // + // disable the interrupts + // + OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd); + + // + // stop the receive unit + // + if (AdapterInfo->Receive_Started) { + StopRU (AdapterInfo); + } + + // + // wait for the tx queue to complete + // + CheckCBList (AdapterInfo); + if (AdapterInfo->FreeCBCount != AdapterInfo->TxBufCnt) { + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + } + + // + // we do not want to reset the phy, it takes a long time to renegotiate the + // link after that (3-4 seconds) + // + InitializeChip (AdapterInfo); + SelectiveReset (AdapterInfo); + return 0; +} + +VOID +MdiWrite ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT8 RegAddress, + IN UINT8 PhyAddress, + IN UINT16 DataValue + ) +/*++ + +Routine Description: + This routine will write a value to the specified MII register + of an external MDI compliant device (e.g. PHY 100). The command will + execute in polled mode. + +Arguments: + AdapterInfo - pointer to the structure that contains the NIC's context. + RegAddress - The MII register that we are writing to + PhyAddress - The MDI address of the Phy component. + DataValue - The value that we are writing to the MII register. + +Returns: + nothing +--*/ +{ + UINT32 WriteCommand; + + WriteCommand = ((UINT32) DataValue) | + ((UINT32)(RegAddress << 16)) | + ((UINT32)(PhyAddress << 21)) | + ((UINT32)(MDI_WRITE << 26)); + + // + // Issue the write command to the MDI control register. + // + OutLong (AdapterInfo, WriteCommand, AdapterInfo->ioaddr + SCBCtrlMDI); + + // + // wait 20usec before checking status + // + DelayIt (AdapterInfo, 20); + + // + // poll for the mdi write to complete + while ((InLong (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI) & + MDI_PHY_READY) == 0){ + DelayIt (AdapterInfo, 20); + } +} + +VOID +MdiRead ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT8 RegAddress, + IN UINT8 PhyAddress, + IN OUT UINT16 *DataValue + ) +/*++ + +Routine Description: + This routine will read a value from the specified MII register + of an external MDI compliant device (e.g. PHY 100), and return + it to the calling routine. The command will execute in polled mode. + +Arguments: + AdapterInfo - pointer to the structure that contains the NIC's context. + RegAddress - The MII register that we are reading from + PhyAddress - The MDI address of the Phy component. + DataValue - pointer to the value that we read from the MII register. + +Returns: + +--*/ +{ + UINT32 ReadCommand; + + ReadCommand = ((UINT32) (RegAddress << 16)) | + ((UINT32) (PhyAddress << 21)) | + ((UINT32) (MDI_READ << 26)); + + // + // Issue the read command to the MDI control register. + // + OutLong (AdapterInfo, ReadCommand, AdapterInfo->ioaddr + SCBCtrlMDI); + + // + // wait 20usec before checking status + // + DelayIt (AdapterInfo, 20); + + // + // poll for the mdi read to complete + // + while ((InLong (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI) & + MDI_PHY_READY) == 0) { + DelayIt (AdapterInfo, 20); + + } + + *DataValue = InWord (AdapterInfo, AdapterInfo->ioaddr + SCBCtrlMDI); +} + +VOID +PhyReset ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine will reset the PHY that the adapter is currently + configured to use. + +Arguments: + AdapterInfo - pointer to the structure that contains the NIC's context. + +Returns: + +--*/ +{ + UINT16 MdiControlReg; + + MdiControlReg = (MDI_CR_AUTO_SELECT | + MDI_CR_RESTART_AUTO_NEG | + MDI_CR_RESET); + + // + // Write the MDI control register with our new Phy configuration + // + MdiWrite ( + AdapterInfo, + MDI_CONTROL_REG, + AdapterInfo->PhyAddress, + MdiControlReg + ); + + return ; +} + +BOOLEAN +PhyDetect ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine will detect what phy we are using, set the line + speed, FDX or HDX, and configure the phy if necessary. + + The following combinations are supported: + - TX or T4 PHY alone at PHY address 1 + - T4 or TX PHY at address 1 and MII PHY at address 0 + - 82503 alone (10Base-T mode, no full duplex support) + - 82503 and MII PHY (TX or T4) at address 0 + + The sequence / priority of detection is as follows: + - PHY 1 with cable termination + - PHY 0 with cable termination + - PHY 1 (if found) without cable termination + - 503 interface + + Additionally auto-negotiation capable (NWAY) and parallel + detection PHYs are supported. The flow-chart is described in + the 82557 software writer's manual. + + NOTE: 1. All PHY MDI registers are read in polled mode. + 2. The routines assume that the 82557 has been RESET and we have + obtained the virtual memory address of the CSR. + 3. PhyDetect will not RESET the PHY. + 4. If FORCEFDX is set, SPEED should also be set. The driver will + check the values for inconsistency with the detected PHY + technology. + 5. PHY 1 (the PHY on the adapter) may have an address in the range + 1 through 31 inclusive. The driver will accept addresses in + this range. + 6. Driver ignores FORCEFDX and SPEED overrides if a 503 interface + is detected. + +Arguments: + AdapterInfo - pointer to the structure that contains the NIC's context. + +Returns: + TRUE - If a Phy was detected, and configured correctly. + FALSE - If a valid phy could not be detected and configured. + +--*/ +{ + UINT16 *eedata; + UINT16 MdiControlReg; + UINT16 MdiStatusReg; + BOOLEAN FoundPhy1; + UINT8 ReNegotiateTime; + + eedata = (UINT16 *) (&AdapterInfo->NVData[0]); + + FoundPhy1 = FALSE; + ReNegotiateTime = 35; + // + // EEPROM word [6] contains the Primary PHY record in which the least 3 bits + // indicate the PHY address + // and word [7] contains the secondary PHY record + // + AdapterInfo->PhyRecord[0] = eedata[6]; + AdapterInfo->PhyRecord[1] = eedata[7]; + AdapterInfo->PhyAddress = (UINT8) (AdapterInfo->PhyRecord[0] & 7); + + // + // Check for a phy address over-ride of 32 which indicates force use of 82503 + // not detecting the link in this case + // + if (AdapterInfo->PhyAddress == 32) { + // + // 503 interface over-ride + // Record the current speed and duplex. We will be in half duplex + // mode unless the user used the force full duplex over-ride. + // + AdapterInfo->LinkSpeed = 10; + return (TRUE); + } + + // + // If the Phy Address is between 1-31 then we must first look for phy 1, + // at that address. + // + if ((AdapterInfo->PhyAddress > 0) && (AdapterInfo->PhyAddress < 32)) { + + // + // Read the MDI control and status registers at phy 1 + // and check if we found a valid phy + // + MdiRead ( + AdapterInfo, + MDI_CONTROL_REG, + AdapterInfo->PhyAddress, + &MdiControlReg + ); + + MdiRead ( + AdapterInfo, + MDI_STATUS_REG, + AdapterInfo->PhyAddress, + &MdiStatusReg + ); + + if (!((MdiControlReg == 0xffff) || + ((MdiStatusReg == 0) && (MdiControlReg == 0)))) { + + // + // we have a valid phy1 + // Read the status register again because of sticky bits + // + FoundPhy1 = TRUE; + MdiRead ( + AdapterInfo, + MDI_STATUS_REG, + AdapterInfo->PhyAddress, + &MdiStatusReg + ); + + // + // If there is a valid link then use this Phy. + // + if (MdiStatusReg & MDI_SR_LINK_STATUS) { + return (SetupPhy(AdapterInfo)); + } + } + } + + // + // Next try to detect a PHY at address 0x00 because there was no Phy 1, + // or Phy 1 didn't have link, or we had a phy 0 over-ride + // + + // + // Read the MDI control and status registers at phy 0 + // + MdiRead (AdapterInfo, MDI_CONTROL_REG, 0, &MdiControlReg); + MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg); + + // + // check if we found a valid phy 0 + // + if (((MdiControlReg == 0xffff) || + ((MdiStatusReg == 0) && (MdiControlReg == 0)))) { + + // + // we don't have a valid phy at address 0 + // if phy address was forced to 0, then error out because we + // didn't find a phy at that address + // + if (AdapterInfo->PhyAddress == 0x0000) { + return (FALSE); + } else { + // + // at this point phy1 does not have link and there is no phy 0 at all + // if we are forced to detect the cable, error out here! + // + if (AdapterInfo->CableDetect != 0) { + return FALSE; + + } + + if (FoundPhy1) { + // + // no phy 0, but there is a phy 1 (no link I guess), so use phy 1 + // + return SetupPhy (AdapterInfo); + } else { + // + // didn't find phy 0 or phy 1, so assume a 503 interface + // + AdapterInfo->PhyAddress = 32; + + // + // Record the current speed and duplex. We'll be in half duplex + // mode unless the user used the force full duplex over-ride. + // + AdapterInfo->LinkSpeed = 10; + return (TRUE); + } + } + } else { + // + // We have a valid phy at address 0. If phy 0 has a link then we use + // phy 0. If Phy 0 doesn't have a link then we use Phy 1 (no link) + // if phy 1 is present, or phy 0 if phy 1 is not present + // If phy 1 was present, then we must isolate phy 1 before we enable + // phy 0 to see if Phy 0 has a link. + // + if (FoundPhy1) { + // + // isolate phy 1 + // + MdiWrite ( + AdapterInfo, + MDI_CONTROL_REG, + AdapterInfo->PhyAddress, + MDI_CR_ISOLATE + ); + + // + // wait 100 microseconds for the phy to isolate. + // + DelayIt (AdapterInfo, 100); + } + + // + // Since this Phy is at address 0, we must enable it. So clear + // the isolate bit, and set the auto-speed select bit + // + MdiWrite ( + AdapterInfo, + MDI_CONTROL_REG, + 0, + MDI_CR_AUTO_SELECT + ); + + // + // wait 100 microseconds for the phy to be enabled. + // + DelayIt (AdapterInfo, 100); + + // + // restart the auto-negotion process + // + MdiWrite ( + AdapterInfo, + MDI_CONTROL_REG, + 0, + MDI_CR_RESTART_AUTO_NEG | MDI_CR_AUTO_SELECT + ); + + // + // wait no more than 3.5 seconds for auto-negotiation to complete + // + while (ReNegotiateTime) { + // + // Read the status register twice because of sticky bits + // + MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg); + MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg); + + if (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE) { + break; + } + + DelayIt (AdapterInfo, 100); + ReNegotiateTime--; + } + + // + // Read the status register again because of sticky bits + // + MdiRead (AdapterInfo, MDI_STATUS_REG, 0, &MdiStatusReg); + + // + // If the link was not set + // + if ((MdiStatusReg & MDI_SR_LINK_STATUS) == 0) { + // + // PHY1 does not have a link and phy 0 does not have a link + // do not proceed if we need to detect the link! + // + if (AdapterInfo->CableDetect != 0) { + return FALSE; + } + + // + // the link wasn't set, so use phy 1 if phy 1 was present + // + if (FoundPhy1) { + // + // isolate phy 0 + // + MdiWrite (AdapterInfo, MDI_CONTROL_REG, 0, MDI_CR_ISOLATE); + + // + // wait 100 microseconds for the phy to isolate. + // + DelayIt (AdapterInfo, 100); + + // + // Now re-enable PHY 1 + // + MdiWrite ( + AdapterInfo, + MDI_CONTROL_REG, + AdapterInfo->PhyAddress, + MDI_CR_AUTO_SELECT + ); + + // + // wait 100 microseconds for the phy to be enabled + // + DelayIt (AdapterInfo, 100); + + // + // restart the auto-negotion process + // + MdiWrite ( + AdapterInfo, + MDI_CONTROL_REG, + AdapterInfo->PhyAddress, + MDI_CR_RESTART_AUTO_NEG | MDI_CR_AUTO_SELECT + ); + + // + // Don't wait for it to complete (we didn't have link earlier) + // + return (SetupPhy (AdapterInfo)); + } + } + + // + // Definitely using Phy 0 + // + AdapterInfo->PhyAddress = 0; + return (SetupPhy(AdapterInfo)); + } +} + +BOOLEAN +SetupPhy ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + This routine will setup phy 1 or phy 0 so that it is configured + to match a speed and duplex over-ride option. If speed or + duplex mode is not explicitly specified in the registry, the + driver will skip the speed and duplex over-ride code, and + assume the adapter is automatically setting the line speed, and + the duplex mode. At the end of this routine, any truly Phy + specific code will be executed (each Phy has its own quirks, + and some require that certain special bits are set). + + NOTE: The driver assumes that SPEED and FORCEFDX are specified at the + same time. If FORCEDPX is set without speed being set, the driver + will encouter a fatal error and log a message into the event viewer. + +Arguments: + AdapterInfo - pointer to the structure that contains the NIC's context. + +Returns: + TRUE - If the phy could be configured correctly + FALSE - If the phy couldn't be configured correctly, because an + unsupported over-ride option was used + +--*/ +{ + UINT16 MdiControlReg; + UINT16 MdiStatusReg; + UINT16 MdiIdLowReg; + UINT16 MdiIdHighReg; + UINT16 MdiMiscReg; + UINT32 PhyId; + BOOLEAN ForcePhySetting; + + ForcePhySetting = FALSE; + + // + // If we are NOT forcing a setting for line speed or full duplex, then + // we won't force a link setting, and we'll jump down to the phy + // specific code. + // + if (((AdapterInfo->LinkSpeedReq) || (AdapterInfo->DuplexReq))) { + // + // Find out what kind of technology this Phy is capable of. + // + MdiRead ( + AdapterInfo, + MDI_STATUS_REG, + AdapterInfo->PhyAddress, + &MdiStatusReg + ); + + // + // Read the MDI control register at our phy + // + MdiRead ( + AdapterInfo, + MDI_CONTROL_REG, + AdapterInfo->PhyAddress, + &MdiControlReg + ); + + // + // Now check the validity of our forced option. If the force option is + // valid, then force the setting. If the force option is not valid, + // we'll set a flag indicating that we should error out. + // + + // + // If speed is forced to 10mb + // + if (AdapterInfo->LinkSpeedReq == 10) { + // + // If half duplex is forced + // + if ((AdapterInfo->DuplexReq & PXE_FORCE_HALF_DUPLEX) != 0) { + if (MdiStatusReg & MDI_SR_10T_HALF_DPX) { + + MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF); + ForcePhySetting = TRUE; + } + } else if ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) != 0) { + + // + // If full duplex is forced + // + if (MdiStatusReg & MDI_SR_10T_FULL_DPX) { + + MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT); + MdiControlReg |= MDI_CR_FULL_HALF; + ForcePhySetting = TRUE; + } + } else { + // + // If auto duplex (we actually set phy to 1/2) + // + if (MdiStatusReg & (MDI_SR_10T_FULL_DPX | MDI_SR_10T_HALF_DPX)) { + + MdiControlReg &= ~(MDI_CR_10_100 | MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF); + ForcePhySetting = TRUE; + } + } + } + + // + // If speed is forced to 100mb + // + else if (AdapterInfo->LinkSpeedReq == 100) { + // + // If half duplex is forced + // + if ((AdapterInfo->DuplexReq & PXE_FORCE_HALF_DUPLEX) != 0) { + if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE)) { + + MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF); + MdiControlReg |= MDI_CR_10_100; + ForcePhySetting = TRUE; + } + } else if ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) != 0) { + // + // If full duplex is forced + // + if (MdiStatusReg & MDI_SR_TX_FULL_DPX) { + MdiControlReg &= ~MDI_CR_AUTO_SELECT; + MdiControlReg |= (MDI_CR_10_100 | MDI_CR_FULL_HALF); + ForcePhySetting = TRUE; + } + } else { + // + // If auto duplex (we set phy to 1/2) + // + if (MdiStatusReg & (MDI_SR_TX_HALF_DPX | MDI_SR_T4_CAPABLE)) { + + MdiControlReg &= ~(MDI_CR_AUTO_SELECT | MDI_CR_FULL_HALF); + MdiControlReg |= MDI_CR_10_100; + ForcePhySetting = TRUE; + } + } + } + + if (!ForcePhySetting) { + return (FALSE); + } + + // + // Write the MDI control register with our new Phy configuration + // + MdiWrite ( + AdapterInfo, + MDI_CONTROL_REG, + AdapterInfo->PhyAddress, + MdiControlReg + ); + + // + // wait 100 milliseconds for auto-negotiation to complete + // + DelayIt (AdapterInfo, 100); + } + + // + // Find out specifically what Phy this is. We do this because for certain + // phys there are specific bits that must be set so that the phy and the + // 82557 work together properly. + // + + MdiRead ( + AdapterInfo, + PHY_ID_REG_1, + AdapterInfo->PhyAddress, + &MdiIdLowReg + ); + MdiRead ( + AdapterInfo, + PHY_ID_REG_2, + AdapterInfo->PhyAddress, + &MdiIdHighReg + ); + + PhyId = ((UINT32) MdiIdLowReg | ((UINT32) MdiIdHighReg << 16)); + + // + // And out the revsion field of the Phy ID so that we'll be able to detect + // future revs of the same Phy. + // + PhyId &= PHY_MODEL_REV_ID_MASK; + + // + // Handle the National TX + // + if (PhyId == PHY_NSC_TX) { + + MdiRead ( + AdapterInfo, + NSC_CONG_CONTROL_REG, + AdapterInfo->PhyAddress, + &MdiMiscReg + ); + + MdiMiscReg |= (NSC_TX_CONG_TXREADY | NSC_TX_CONG_F_CONNECT); + +#if CONGESTION_CONTROL + // + // If we are configured to do congestion control, then enable the + // congestion control bit in the National Phy + // + if (AdapterInfo->Congest) { + MdiMiscReg |= NSC_TX_CONG_ENABLE; + } else { + MdiMiscReg &= ~NSC_TX_CONG_ENABLE; + } +#endif + MdiWrite ( + AdapterInfo, + NSC_CONG_CONTROL_REG, + AdapterInfo->PhyAddress, + MdiMiscReg + ); + } + + FindPhySpeedAndDpx (AdapterInfo, PhyId); + + // + // We put a hardware fix on to our adapters to work-around the PHY_100 errata + // described below. The following code is only compiled in, if we wanted + // to attempt a software workaround to the PHY_100 A/B step problem. + // + +#if DO_PHY_100B_SOFTWARE_FIX + // + // Handle the Intel PHY_100 (A and B steps) + // + if ((PhyId == PHY_100_A) && (AdapterInfo->LinkSpeed == 100)) { + // + // The PHY_100 is very sensitive to collisions at 100mb, so increase + // the Adaptive IFS value with the intention of reducing the number of + // collisions that the adapter generates. + // + AdapterInfo->CurrentIFSValue = 0x18; + AdapterInfo->AdaptiveIFS = 0; + } +#endif + + return (TRUE); +} + +VOID +FindPhySpeedAndDpx ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT32 PhyId + ) +/*++ + +Routine Description: + This routine will figure out what line speed and duplex mode + the PHY is currently using. + +Arguments: + AdapterInfo - pointer to the structure that contains the NIC's context. + PhyId - The ID of the PHY in question. + +Returns: + NOTHING +--*/ +{ + UINT16 MdiStatusReg; + UINT16 MdiMiscReg; + UINT16 MdiOwnAdReg; + UINT16 MdiLinkPartnerAdReg; + + // + // If there was a speed and/or duplex override, then set our current + // value accordingly + // + AdapterInfo->LinkSpeed = AdapterInfo->LinkSpeedReq; + AdapterInfo->Duplex = (UINT8) ((AdapterInfo->DuplexReq & PXE_FORCE_FULL_DUPLEX) ? + FULL_DUPLEX : HALF_DUPLEX); + + // + // If speed and duplex were forced, then we know our current settings, so + // we'll just return. Otherwise, we'll need to figure out what NWAY set + // us to. + // + if (AdapterInfo->LinkSpeed && AdapterInfo->Duplex) { + return ; + + } + // + // If we didn't have a valid link, then we'll assume that our current + // speed is 10mb half-duplex. + // + + // + // Read the status register twice because of sticky bits + // + MdiRead ( + AdapterInfo, + MDI_STATUS_REG, + AdapterInfo->PhyAddress, + &MdiStatusReg + ); + MdiRead ( + AdapterInfo, + MDI_STATUS_REG, + AdapterInfo->PhyAddress, + &MdiStatusReg + ); + + // + // If there wasn't a valid link then use default speed & duplex + // + if (!(MdiStatusReg & MDI_SR_LINK_STATUS)) { + + AdapterInfo->LinkSpeed = 10; + AdapterInfo->Duplex = HALF_DUPLEX; + return ; + } + + // + // If this is an Intel PHY (a T4 PHY_100 or a TX PHY_TX), then read bits + // 1 and 0 of extended register 0, to get the current speed and duplex + // settings. + // + if ((PhyId == PHY_100_A) || (PhyId == PHY_100_C) || (PhyId == PHY_TX_ID)) { + // + // Read extended register 0 + // + MdiRead ( + AdapterInfo, + EXTENDED_REG_0, + AdapterInfo->PhyAddress, + &MdiMiscReg + ); + + // + // Get current speed setting + // + if (MdiMiscReg & PHY_100_ER0_SPEED_INDIC) { + AdapterInfo->LinkSpeed = 100; + } else { + AdapterInfo->LinkSpeed = 10; + } + + // + // Get current duplex setting -- if bit is set then FDX is enabled + // + if (MdiMiscReg & PHY_100_ER0_FDX_INDIC) { + AdapterInfo->Duplex = FULL_DUPLEX; + } else { + AdapterInfo->Duplex = HALF_DUPLEX; + } + + return ; + } + // + // Read our link partner's advertisement register + // + MdiRead ( + AdapterInfo, + AUTO_NEG_LINK_PARTNER_REG, + AdapterInfo->PhyAddress, + &MdiLinkPartnerAdReg + ); + + // + // See if Auto-Negotiation was complete (bit 5, reg 1) + // + MdiRead ( + AdapterInfo, + MDI_STATUS_REG, + AdapterInfo->PhyAddress, + &MdiStatusReg + ); + + // + // If a True NWAY connection was made, then we can detect speed/duplex by + // ANDing our adapter's advertised abilities with our link partner's + // advertised ablilities, and then assuming that the highest common + // denominator was chosed by NWAY. + // + if ((MdiLinkPartnerAdReg & NWAY_LP_ABILITY) && + (MdiStatusReg & MDI_SR_AUTO_NEG_COMPLETE)) { + + // + // Read our advertisement register + // + MdiRead ( + AdapterInfo, + AUTO_NEG_ADVERTISE_REG, + AdapterInfo->PhyAddress, + &MdiOwnAdReg + ); + + // + // AND the two advertisement registers together, and get rid of any + // extraneous bits. + // + MdiOwnAdReg &= (MdiLinkPartnerAdReg & NWAY_LP_ABILITY); + + // + // Get speed setting + // + if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX | NWAY_AD_TX_FULL_DPX | NWAY_AD_T4_CAPABLE)) { + AdapterInfo->LinkSpeed = 100; + } else { + AdapterInfo->LinkSpeed = 10; + } + + // + // Get duplex setting -- use priority resolution algorithm + // + if (MdiOwnAdReg & (NWAY_AD_T4_CAPABLE)) { + AdapterInfo->Duplex = HALF_DUPLEX; + return ; + } else if (MdiOwnAdReg & (NWAY_AD_TX_FULL_DPX)) { + AdapterInfo->Duplex = FULL_DUPLEX; + return ; + } else if (MdiOwnAdReg & (NWAY_AD_TX_HALF_DPX)) { + AdapterInfo->Duplex = HALF_DUPLEX; + return ; + } else if (MdiOwnAdReg & (NWAY_AD_10T_FULL_DPX)) { + AdapterInfo->Duplex = FULL_DUPLEX; + return ; + } else { + AdapterInfo->Duplex = HALF_DUPLEX; + return ; + } + } + + // + // If we are connected to a dumb (non-NWAY) repeater or hub, and the line + // speed was determined automatically by parallel detection, then we have + // no way of knowing exactly what speed the PHY is set to unless that PHY + // has a propietary register which indicates speed in this situation. The + // NSC TX PHY does have such a register. Also, since NWAY didn't establish + // the connection, the duplex setting should HALF duplex. + // + AdapterInfo->Duplex = HALF_DUPLEX; + + if (PhyId == PHY_NSC_TX) { + // + // Read register 25 to get the SPEED_10 bit + // + MdiRead ( + AdapterInfo, + NSC_SPEED_IND_REG, + AdapterInfo->PhyAddress, + &MdiMiscReg + ); + + // + // If bit 6 was set then we're at 10mb + // + if (MdiMiscReg & NSC_TX_SPD_INDC_SPEED) { + AdapterInfo->LinkSpeed = 10; + } else { + AdapterInfo->LinkSpeed = 100; + } + } + + // + // If we don't know what line speed we are set at, then we'll default to + // 10mbs + // + else { + AdapterInfo->LinkSpeed = 10; + } +} + +VOID +XmitWaitForCompletion ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + TxCB *TxPtr; + + if (AdapterInfo->FreeCBCount == AdapterInfo->TxBufCnt) { + return ; + } + + // + // used xmit cb list starts right after the free tail (ends before the + // free head ptr) + // + TxPtr = AdapterInfo->FreeTxTailPtr->NextTCBVirtualLinkPtr; + while (TxPtr != AdapterInfo->FreeTxHeadPtr) { + CommandWaitForCompletion (TxPtr, AdapterInfo); + SetFreeCB (AdapterInfo, TxPtr); + TxPtr = TxPtr->NextTCBVirtualLinkPtr; + } +} + +INT8 +CommandWaitForCompletion ( + TxCB *cmd_ptr, + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + cmd_ptr - TODO: add argument description + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + INT16 wait; + wait = 5000; + while ((cmd_ptr->cb_header.status == 0) && (--wait > 0)) { + DelayIt (AdapterInfo, 10); + } + + if (cmd_ptr->cb_header.status == 0) { + return -1; + } + + return 0; +} + +INT8 +SoftwareReset ( + NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT8 tco_stat; + UINT16 wait; + + tco_stat = 0; + + // + // Reset the chip: stop Tx and Rx processes and clear counters. + // This takes less than 10usec and will easily finish before the next + // action. + // + + OutLong (AdapterInfo, PORT_RESET, AdapterInfo->ioaddr + SCBPort); + // + // wait for 5 milli seconds here! + // + DelayIt (AdapterInfo, 5000); + // + // TCO Errata work around for 559s only + // ----------------------------------------------------------------------------------- + // TCO Workaround Code + // haifa workaround + // ----------------------------------------------------------------------------------- + // 1. Issue SW-RST ^^^ (already done above) + // 2. Issue a redundant Set CU Base CMD immediately + // Do not set the General Pointer before the Set CU Base cycle + // Do not check the SCB CMD before the Set CU Base cycle + // 3. Wait for the SCB-CMD to be cleared + // this indicates the transition to post-driver + // 4. Poll the TCO-Req bit in the PMDR to be cleared + // this indicates the tco activity has stopped for real + // 5. Proceed with the nominal Driver Init: + // Actual Set CU & RU Base ... + // + // Check for ICH2 device ID. If this is an ICH2, + // do the TCO workaround code. + // + if (AdapterInfo->VendorID == D102_DEVICE_ID || + AdapterInfo->VendorID == ICH3_DEVICE_ID_1 || + AdapterInfo->VendorID == ICH3_DEVICE_ID_2 || + AdapterInfo->VendorID == ICH3_DEVICE_ID_3 || + AdapterInfo->VendorID == ICH3_DEVICE_ID_4 || + AdapterInfo->VendorID == ICH3_DEVICE_ID_5 || + AdapterInfo->VendorID == ICH3_DEVICE_ID_6 || + AdapterInfo->VendorID == ICH3_DEVICE_ID_7 || + AdapterInfo->VendorID == ICH3_DEVICE_ID_8 || + AdapterInfo->RevID >= 8) { // do the TCO fix + // + // donot load the scb pointer but just give load_cu cmd. + // + OutByte (AdapterInfo, CU_CMD_BASE, AdapterInfo->ioaddr + SCBCmd); + // + // wait for command to be accepted. + // + wait_for_cmd_done (AdapterInfo->ioaddr + SCBCmd); + // + // read PMDR register and check bit 1 in it to see if TCO is active + // + + // + // wait for 5 milli seconds + // + wait = 5000; + while (wait) { + tco_stat = InByte (AdapterInfo, AdapterInfo->ioaddr + 0x1b); + if ((tco_stat & 2) == 0) { + // + // is the activity bit clear?? + // + break; + } + + wait--; + DelayIt (AdapterInfo, 1); + } + + if ((tco_stat & 2) != 0) { + // + // not zero?? + // + return -1; + } + } + + return 0; +} + +UINT8 +SelectiveReset ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT16 wait; + UINT32 stat; + + wait = 10; + stat = 0; + OutLong (AdapterInfo, POR_SELECTIVE_RESET, AdapterInfo->ioaddr + SCBPort); + // + // wait for this to complete + // + + // + // wait for 2 milli seconds here! + // + DelayIt (AdapterInfo, 2000); + while (wait > 0) { + wait--; + stat = InLong (AdapterInfo, AdapterInfo->ioaddr + SCBPort); + if (stat == 0) { + break; + } + + // + // wait for 1 milli second + // + DelayIt (AdapterInfo, 1000); + } + + if (stat != 0) { + return PXE_STATCODE_DEVICE_FAILURE; + } + + return 0; +} + +UINT16 +InitializeChip ( + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + AdapterInfo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT16 ret_val; + if (SoftwareReset (AdapterInfo) != 0) { + return PXE_STATCODE_DEVICE_FAILURE; + } + + // + // disable interrupts + // + OutWord (AdapterInfo, INT_MASK, AdapterInfo->ioaddr + SCBCmd); + + // + // Load the base registers with 0s (we will give the complete address as + // offset later when we issue any command + // + if ((ret_val = Load_Base_Regs (AdapterInfo)) != 0) { + return ret_val; + } + + if ((ret_val = SetupCBlink (AdapterInfo)) != 0) { + return ret_val; + } + + if ((ret_val = SetupReceiveQueues (AdapterInfo)) != 0) { + return ret_val; + } + + // + // detect the PHY only if we need to detect the cable as requested by the + // initialize parameters + // + AdapterInfo->PhyAddress = 0xFF; + + if (AdapterInfo->CableDetect != 0) { + if (!PhyDetect (AdapterInfo)) { + return PXE_STATCODE_DEVICE_FAILURE; + } + } + + if ((ret_val = E100bSetupIAAddr (AdapterInfo)) != 0) { + return ret_val; + } + + if ((ret_val = Configure (AdapterInfo)) != 0) { + return ret_val; + } + + return 0; +} + +#pragma data_seg() diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.h b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.h new file mode 100644 index 0000000000..3a4127c4e5 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/E100b.h @@ -0,0 +1,668 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + E100B.H + +Abstract: + + +Revision History + +--*/ +// pci config offsets: + +#define RX_BUFFER_COUNT 32 +#define TX_BUFFER_COUNT 32 + +#define PCI_VENDOR_ID_INTEL 0x8086 +#define PCI_DEVICE_ID_INTEL_82557 0x1229 +#define D100_VENDOR_ID 0x8086 +#define D100_DEVICE_ID 0x1229 +#define D102_DEVICE_ID 0x2449 + +#define ICH3_DEVICE_ID_1 0x1031 +#define ICH3_DEVICE_ID_2 0x1032 +#define ICH3_DEVICE_ID_3 0x1033 +#define ICH3_DEVICE_ID_4 0x1034 +#define ICH3_DEVICE_ID_5 0x1035 +#define ICH3_DEVICE_ID_6 0x1036 +#define ICH3_DEVICE_ID_7 0x1037 +#define ICH3_DEVICE_ID_8 0x1038 + +#define SPEEDO_DEVICE_ID 0x1227 +#define SPLASH1_DEVICE_ID 0x1226 + + +// bit fields for the command +#define PCI_COMMAND_MASTER 0x04 // bit 2 +#define PCI_COMMAND_IO 0x01 // bit 0 +#define PCI_COMMAND 0x04 +#define PCI_LATENCY_TIMER 0x0D + +#define ETHER_MAC_ADDR_LEN 6 +#ifdef AVL_XXX +#define ETHER_HEADER_LEN 14 +// media interface type +// #define INTERFACE_TYPE " + +// Hardware type values +#define HW_ETHER_TYPE 1 +#define HW_EXPERIMENTAL_ETHER_TYPE 2 +#define HW_IEEE_TYPE 6 +#define HW_ARCNET_TYPE 7 + +#endif // AVL_XXX + +#define MAX_ETHERNET_PKT_SIZE 1514 // including eth header +#define RX_BUFFER_SIZE 1536 // including crc and padding +#define TX_BUFFER_SIZE 64 +#define ETH_MTU 1500 // does not include ethernet header length + +#define SPEEDO3_TOTAL_SIZE 0x20 + +#pragma pack(1) + +typedef struct eth { + UINT8 dest_addr[PXE_HWADDR_LEN_ETHER]; + UINT8 src_addr[PXE_HWADDR_LEN_ETHER]; + UINT16 type; +} EtherHeader; + +#pragma pack(1) +typedef struct CONFIG_HEADER { + UINT16 VendorID; + UINT16 DeviceID; + UINT16 Command; + UINT16 Status; + UINT16 RevID; + UINT16 ClassID; + UINT8 CacheLineSize; + UINT8 LatencyTimer; + UINT8 HeaderType; // must be zero to impose this structure... + UINT8 BIST; // built-in self test + UINT32 BaseAddressReg_0; // memory mapped address + UINT32 BaseAddressReg_1; //io mapped address, Base IO address + UINT32 BaseAddressReg_2; // option rom address + UINT32 BaseAddressReg_3; + UINT32 BaseAddressReg_4; + UINT32 BaseAddressReg_5; + UINT32 CardBusCISPtr; + UINT16 SubVendorID; + UINT16 SubSystemID; + UINT32 ExpansionROMBaseAddr; + UINT8 CapabilitiesPtr; + UINT8 reserved1; + UINT16 Reserved2; + UINT32 Reserved3; + UINT8 int_line; + UINT8 int_pin; + UINT8 Min_gnt; + UINT8 Max_lat; +} PCI_CONFIG_HEADER; +#pragma pack() + +//------------------------------------------------------------------------- +// Offsets to the various registers. +// All accesses need not be longword aligned. +//------------------------------------------------------------------------- +enum speedo_offsets { + SCBStatus = 0, SCBCmd = 2, // Rx/Command Unit command and status. + SCBPointer = 4, // General purpose pointer. + SCBPort = 8, // Misc. commands and operands. + SCBflash = 12, SCBeeprom = 14, // EEPROM and flash memory control. + SCBCtrlMDI = 16, // MDI interface control. + SCBEarlyRx = 20, // Early receive byte count. + SCBEarlyRxInt = 24, SCBFlowCtrlReg = 25, SCBPmdr = 27, + // offsets for general control registers (GCRs) + SCBGenCtrl = 28, SCBGenStatus = 29, SCBGenCtrl2 = 30, SCBRsvd = 31, +}; + +#define GCR2_EEPROM_ACCESS_SEMAPHORE 0x80 // bit offset into the gcr2 + +//------------------------------------------------------------------------- +// Action commands - Commands that can be put in a command list entry. +//------------------------------------------------------------------------- +enum commands { + CmdNOp = 0, CmdIASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, + CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7, + CmdSuspend = 0x4000, /* Suspend after completion. */ + CmdIntr = 0x2000, /* Interrupt after completion. */ + CmdTxFlex = 0x0008, /* Use "Flexible mode" for CmdTx command. */ +}; + +//------------------------------------------------------------------------- +// port commands +//------------------------------------------------------------------------- +#define PORT_RESET 0 +#define PORT_SELF_TEST 1 +#define POR_SELECTIVE_RESET 2 +#define PORT_DUMP_POINTER 2 + +//------------------------------------------------------------------------- +// SCB Command Word bit definitions +//------------------------------------------------------------------------- +//- CUC fields +#define CU_START 0x0010 +#define CU_RESUME 0x0020 +#define CU_STATSADDR 0x0040 +#define CU_SHOWSTATS 0x0050 /* Dump statistics counters. */ +#define CU_CMD_BASE 0x0060 /* Base address to add to add CU commands. */ +#define CU_DUMPSTATS 0x0070 /* Dump then reset stats counters. */ + +//- RUC fields +#define RX_START 0x0001 +#define RX_RESUME 0x0002 +#define RX_ABORT 0x0004 +#define RX_ADDR_LOAD 0x0006 /* load ru_base_reg */ +#define RX_RESUMENR 0x0007 + +// Interrupt fields (assuming byte addressing) +#define INT_MASK 0x0100 +#define DRVR_INT 0x0200 /* Driver generated interrupt. */ + +//- CB Status Word +#define CMD_STATUS_COMPLETE 0x8000 +#define RX_STATUS_COMPLETE 0x8000 +#define CMD_STATUS_MASK 0xF000 + +//------------------------------------------------------------------------- +//- SCB Status bits: +// Interrupts are ACKed by writing to the upper 6 interrupt bits +//------------------------------------------------------------------------- +#define SCB_STATUS_MASK 0xFC00 // bits 2-7 - STATUS/ACK Mask +#define SCB_STATUS_CX_TNO 0x8000 // BIT_15 - CX or TNO Interrupt +#define SCB_STATUS_FR 0x4000 // BIT_14 - FR Interrupt +#define SCB_STATUS_CNA 0x2000 // BIT_13 - CNA Interrupt +#define SCB_STATUS_RNR 0x1000 // BIT_12 - RNR Interrupt +#define SCB_STATUS_MDI 0x0800 // BIT_11 - MDI R/W Done Interrupt +#define SCB_STATUS_SWI 0x0400 // BIT_10 - SWI Interrupt + +// CU STATUS: bits 6 & 7 +#define SCB_STATUS_CU_MASK 0x00C0 // bits 6 & 7 +#define SCB_STATUS_CU_IDLE 0x0000 // 00 +#define SCB_STATUS_CU_SUSPEND 0x0040 // 01 +#define SCB_STATUS_CU_ACTIVE 0x0080 // 10 + +// RU STATUS: bits 2-5 +#define SCB_RUS_IDLE 0x0000 +#define SCB_RUS_SUSPENDED 0x0004 // bit 2 +#define SCB_RUS_NO_RESOURCES 0x0008 // bit 3 +#define SCB_RUS_READY 0x0010 // bit 4 + +//------------------------------------------------------------------------- +// Bit Mask definitions +//------------------------------------------------------------------------- +#define BIT_0 0x0001 +#define BIT_1 0x0002 +#define BIT_2 0x0004 +#define BIT_3 0x0008 +#define BIT_4 0x0010 +#define BIT_5 0x0020 +#define BIT_6 0x0040 +#define BIT_7 0x0080 +#define BIT_8 0x0100 +#define BIT_9 0x0200 +#define BIT_10 0x0400 +#define BIT_11 0x0800 +#define BIT_12 0x1000 +#define BIT_13 0x2000 +#define BIT_14 0x4000 +#define BIT_15 0x8000 +#define BIT_24 0x01000000 +#define BIT_28 0x10000000 + + +//------------------------------------------------------------------------- +// MDI Control register bit definitions +//------------------------------------------------------------------------- +#define MDI_DATA_MASK BIT_0_15 // MDI Data port +#define MDI_REG_ADDR BIT_16_20 // which MDI register to read/write +#define MDI_PHY_ADDR BIT_21_25 // which PHY to read/write +#define MDI_PHY_OPCODE BIT_26_27 // which PHY to read/write +#define MDI_PHY_READY BIT_28 // PHY is ready for another MDI cycle +#define MDI_PHY_INT_ENABLE BIT_29 // Assert INT at MDI cycle completion + +#define BIT_0_2 0x0007 +#define BIT_0_3 0x000F +#define BIT_0_4 0x001F +#define BIT_0_5 0x003F +#define BIT_0_6 0x007F +#define BIT_0_7 0x00FF +#define BIT_0_8 0x01FF +#define BIT_0_13 0x3FFF +#define BIT_0_15 0xFFFF +#define BIT_1_2 0x0006 +#define BIT_1_3 0x000E +#define BIT_2_5 0x003C +#define BIT_3_4 0x0018 +#define BIT_4_5 0x0030 +#define BIT_4_6 0x0070 +#define BIT_4_7 0x00F0 +#define BIT_5_7 0x00E0 +#define BIT_5_9 0x03E0 +#define BIT_5_12 0x1FE0 +#define BIT_5_15 0xFFE0 +#define BIT_6_7 0x00c0 +#define BIT_7_11 0x0F80 +#define BIT_8_10 0x0700 +#define BIT_9_13 0x3E00 +#define BIT_12_15 0xF000 + +#define BIT_16_20 0x001F0000 +#define BIT_21_25 0x03E00000 +#define BIT_26_27 0x0C000000 + +//------------------------------------------------------------------------- +// MDI Control register opcode definitions +//------------------------------------------------------------------------- +#define MDI_WRITE 1 // Phy Write +#define MDI_READ 2 // Phy read + +//------------------------------------------------------------------------- +// PHY 100 MDI Register/Bit Definitions +//------------------------------------------------------------------------- +// MDI register set +#define MDI_CONTROL_REG 0x00 // MDI control register +#define MDI_STATUS_REG 0x01 // MDI Status regiser +#define PHY_ID_REG_1 0x02 // Phy indentification reg (word 1) +#define PHY_ID_REG_2 0x03 // Phy indentification reg (word 2) +#define AUTO_NEG_ADVERTISE_REG 0x04 // Auto-negotiation advertisement +#define AUTO_NEG_LINK_PARTNER_REG 0x05 // Auto-negotiation link partner ability +#define AUTO_NEG_EXPANSION_REG 0x06 // Auto-negotiation expansion +#define AUTO_NEG_NEXT_PAGE_REG 0x07 // Auto-negotiation next page transmit +#define EXTENDED_REG_0 0x10 // Extended reg 0 (Phy 100 modes) +#define EXTENDED_REG_1 0x14 // Extended reg 1 (Phy 100 error indications) +#define NSC_CONG_CONTROL_REG 0x17 // National (TX) congestion control +#define NSC_SPEED_IND_REG 0x19 // National (TX) speed indication + +// MDI Control register bit definitions +#define MDI_CR_COLL_TEST_ENABLE BIT_7 // Collision test enable +#define MDI_CR_FULL_HALF BIT_8 // FDX =1, half duplex =0 +#define MDI_CR_RESTART_AUTO_NEG BIT_9 // Restart auto negotiation +#define MDI_CR_ISOLATE BIT_10 // Isolate PHY from MII +#define MDI_CR_POWER_DOWN BIT_11 // Power down +#define MDI_CR_AUTO_SELECT BIT_12 // Auto speed select enable +#define MDI_CR_10_100 BIT_13 // 0 = 10Mbs, 1 = 100Mbs +#define MDI_CR_LOOPBACK BIT_14 // 0 = normal, 1 = loopback +#define MDI_CR_RESET BIT_15 // 0 = normal, 1 = PHY reset + +// MDI Status register bit definitions +#define MDI_SR_EXT_REG_CAPABLE BIT_0 // Extended register capabilities +#define MDI_SR_JABBER_DETECT BIT_1 // Jabber detected +#define MDI_SR_LINK_STATUS BIT_2 // Link Status -- 1 = link +#define MDI_SR_AUTO_SELECT_CAPABLE BIT_3 // Auto speed select capable +#define MDI_SR_REMOTE_FAULT_DETECT BIT_4 // Remote fault detect +#define MDI_SR_AUTO_NEG_COMPLETE BIT_5 // Auto negotiation complete +#define MDI_SR_10T_HALF_DPX BIT_11 // 10BaseT Half Duplex capable +#define MDI_SR_10T_FULL_DPX BIT_12 // 10BaseT full duplex capable +#define MDI_SR_TX_HALF_DPX BIT_13 // TX Half Duplex capable +#define MDI_SR_TX_FULL_DPX BIT_14 // TX full duplex capable +#define MDI_SR_T4_CAPABLE BIT_15 // T4 capable + +// Auto-Negotiation advertisement register bit definitions +#define NWAY_AD_SELCTOR_FIELD BIT_0_4 // identifies supported protocol +#define NWAY_AD_ABILITY BIT_5_12 // technologies that are supported +#define NWAY_AD_10T_HALF_DPX BIT_5 // 10BaseT Half Duplex capable +#define NWAY_AD_10T_FULL_DPX BIT_6 // 10BaseT full duplex capable +#define NWAY_AD_TX_HALF_DPX BIT_7 // TX Half Duplex capable +#define NWAY_AD_TX_FULL_DPX BIT_8 // TX full duplex capable +#define NWAY_AD_T4_CAPABLE BIT_9 // T4 capable +#define NWAY_AD_REMOTE_FAULT BIT_13 // indicates local remote fault +#define NWAY_AD_RESERVED BIT_14 // reserved +#define NWAY_AD_NEXT_PAGE BIT_15 // Next page (not supported) + +// Auto-Negotiation link partner ability register bit definitions +#define NWAY_LP_SELCTOR_FIELD BIT_0_4 // identifies supported protocol +#define NWAY_LP_ABILITY BIT_5_9 // technologies that are supported +#define NWAY_LP_REMOTE_FAULT BIT_13 // indicates partner remote fault +#define NWAY_LP_ACKNOWLEDGE BIT_14 // acknowledge +#define NWAY_LP_NEXT_PAGE BIT_15 // Next page (not supported) + +// Auto-Negotiation expansion register bit definitions +#define NWAY_EX_LP_NWAY BIT_0 // link partner is NWAY +#define NWAY_EX_PAGE_RECEIVED BIT_1 // link code word received +#define NWAY_EX_NEXT_PAGE_ABLE BIT_2 // local is next page able +#define NWAY_EX_LP_NEXT_PAGE_ABLE BIT_3 // partner is next page able +#define NWAY_EX_PARALLEL_DET_FLT BIT_4 // parallel detection fault +#define NWAY_EX_RESERVED BIT_5_15 // reserved + + +// PHY 100 Extended Register 0 bit definitions +#define PHY_100_ER0_FDX_INDIC BIT_0 // 1 = FDX, 0 = half duplex +#define PHY_100_ER0_SPEED_INDIC BIT_1 // 1 = 100mbs, 0= 10mbs +#define PHY_100_ER0_WAKE_UP BIT_2 // Wake up DAC +#define PHY_100_ER0_RESERVED BIT_3_4 // Reserved +#define PHY_100_ER0_REV_CNTRL BIT_5_7 // Revsion control (A step = 000) +#define PHY_100_ER0_FORCE_FAIL BIT_8 // Force Fail is enabled +#define PHY_100_ER0_TEST BIT_9_13 // Revsion control (A step = 000) +#define PHY_100_ER0_LINKDIS BIT_14 // Link integrity test is disabled +#define PHY_100_ER0_JABDIS BIT_15 // Jabber function is disabled + + +// PHY 100 Extended Register 1 bit definitions +#define PHY_100_ER1_RESERVED BIT_0_8 // Reserved +#define PHY_100_ER1_CH2_DET_ERR BIT_9 // Channel 2 EOF detection error +#define PHY_100_ER1_MANCH_CODE_ERR BIT_10 // Manchester code error +#define PHY_100_ER1_EOP_ERR BIT_11 // EOP error +#define PHY_100_ER1_BAD_CODE_ERR BIT_12 // bad code error +#define PHY_100_ER1_INV_CODE_ERR BIT_13 // invalid code error +#define PHY_100_ER1_DC_BAL_ERR BIT_14 // DC balance error +#define PHY_100_ER1_PAIR_SKEW_ERR BIT_15 // Pair skew error + +// National Semiconductor TX phy congestion control register bit definitions +#define NSC_TX_CONG_TXREADY BIT_10 // Makes TxReady an input +#define NSC_TX_CONG_ENABLE BIT_8 // Enables congestion control +#define NSC_TX_CONG_F_CONNECT BIT_5 // Enables congestion control + +// National Semiconductor TX phy speed indication register bit definitions +#define NSC_TX_SPD_INDC_SPEED BIT_6 // 0 = 100mb, 1=10mb + +//------------------------------------------------------------------------- +// Phy related constants +//------------------------------------------------------------------------- +#define PHY_503 0 +#define PHY_100_A 0x000003E0 +#define PHY_100_C 0x035002A8 +#define PHY_TX_ID 0x015002A8 +#define PHY_NSC_TX 0x5c002000 +#define PHY_OTHER 0xFFFF + +#define PHY_MODEL_REV_ID_MASK 0xFFF0FFFF +#define PARALLEL_DETECT 0 +#define N_WAY 1 + +#define RENEGOTIATE_TIME 35 // (3.5 Seconds) + +#define CONNECTOR_AUTO 0 +#define CONNECTOR_TPE 1 +#define CONNECTOR_MII 2 + +//------------------------------------------------------------------------- + +/* The Speedo3 Rx and Tx frame/buffer descriptors. */ +#pragma pack(1) +struct CB_Header { /* A generic descriptor. */ + UINT16 status; /* Offset 0. */ + UINT16 command; /* Offset 2. */ + UINT32 link; /* struct descriptor * */ +}; + +/* transmit command block structure */ +#pragma pack(1) +typedef struct s_TxCB { + struct CB_Header cb_header; + UINT32 PhysTBDArrayAddres; /* address of an array that contains + physical TBD pointers */ + UINT16 ByteCount; /* immediate data count = 0 always */ + UINT8 Threshold; + UINT8 TBDCount; + UINT8 ImmediateData[TX_BUFFER_SIZE]; + /* following fields are not seen by the 82557 */ + struct TBD { + UINT32 phys_buf_addr; + UINT32 buf_len; + } TBDArray[MAX_XMIT_FRAGMENTS]; + UINT32 PhysArrayAddr; /* in case the one in the header is lost */ + UINT32 PhysTCBAddress; /* for this TCB */ + struct s_TxCB *NextTCBVirtualLinkPtr; + struct s_TxCB *PrevTCBVirtualLinkPtr; + UINT64 free_data_ptr; // to be given to the upper layer when this xmit completes1 +}TxCB; + +/* The Speedo3 Rx and Tx buffer descriptors. */ +#pragma pack(1) +typedef struct s_RxFD { /* Receive frame descriptor. */ + struct CB_Header cb_header; + UINT32 rx_buf_addr; /* VOID * */ + UINT16 ActualCount; + UINT16 RFDSize; + UINT8 RFDBuffer[RX_BUFFER_SIZE]; + UINT8 forwarded; + UINT8 junk[3]; +}RxFD; + +/* Elements of the RxFD.status word. */ +#define RX_COMPLETE 0x8000 +#define RX_FRAME_OK 0x2000 + +/* Elements of the dump_statistics block. This block must be lword aligned. */ +#pragma pack(1) +struct speedo_stats { + UINT32 tx_good_frames; + UINT32 tx_coll16_errs; + UINT32 tx_late_colls; + UINT32 tx_underruns; + UINT32 tx_lost_carrier; + UINT32 tx_deferred; + UINT32 tx_one_colls; + UINT32 tx_multi_colls; + UINT32 tx_total_colls; + UINT32 rx_good_frames; + UINT32 rx_crc_errs; + UINT32 rx_align_errs; + UINT32 rx_resource_errs; + UINT32 rx_overrun_errs; + UINT32 rx_colls_errs; + UINT32 rx_runt_errs; + UINT32 done_marker; +}; +#pragma pack() + + +struct Krn_Mem{ + RxFD rx_ring[RX_BUFFER_COUNT]; + TxCB tx_ring[TX_BUFFER_COUNT]; + struct speedo_stats statistics; +}; +#define MEMORY_NEEDED sizeof(struct Krn_Mem) + +/* The parameters for a CmdConfigure operation. + There are so many options that it would be difficult to document each bit. + We mostly use the default or recommended settings. +*/ + +/* + *-------------------------------------------------------------------------- + * Configuration CB Parameter Bit Definitions + *-------------------------------------------------------------------------- + */ +// - Byte 0 (Default Value = 16h) +#define CFIG_BYTE_COUNT 0x16 // 22 Configuration Bytes + +//- Byte 1 (Default Value = 88h) +#define CFIG_TXRX_FIFO_LIMIT 0x88 + +//- Byte 2 (Default Value = 0) +#define CFIG_ADAPTIVE_IFS 0 + +//- Byte 3 (Default Value = 0, ALWAYS. This byte is RESERVED) +#define CFIG_RESERVED 0 + +//- Byte 4 (Default Value = 0. Default implies that Rx DMA cannot be +//- preempted). +#define CFIG_RXDMA_BYTE_COUNT 0 + +//- Byte 5 (Default Value = 80h. Default implies that Tx DMA cannot be +//- preempted. However, setting these counters is enabled.) +#define CFIG_DMBC_ENABLE 0x80 + +//- Byte 6 (Default Value = 33h. Late SCB enabled, No TNO interrupts, +//- CNA interrupts and do not save bad frames.) +#define CFIG_LATE_SCB 1 // BIT 0 +#define CFIG_TNO_INTERRUPT 0x4 // BIT 2 +#define CFIG_CI_INTERRUPT 0x8 // BIT 3 +#define CFIG_SAVE_BAD_FRAMES 0x80 // BIT_7 + +//- Byte 7 (Default Value = 7h. Discard short frames automatically and +//- attempt upto 3 retries on transmit.) +#define CFIG_DISCARD_SHORTRX 0x00001 +#define CFIG_URUN_RETRY BIT_1 OR BIT_2 + +//- Byte 8 (Default Value = 1. Enable MII mode.) +#define CFIG_503_MII BIT_0 + +//- Byte 9 (Default Value = 0, ALWAYS) + +//- Byte 10 (Default Value = 2Eh) +#define CFIG_NSAI BIT_3 +#define CFIG_PREAMBLE_LENGTH BIT_5 ;- Bit 5-4 = 1-0 +#define CFIG_NO_LOOPBACK 0 +#define CFIG_INTERNAL_LOOPBACK BIT_6 +#define CFIG_EXT_LOOPBACK BIT_7 +#define CFIG_EXT_PIN_LOOPBACK BIT_6 OR BIT_7 + +//- Byte 11 (Default Value = 0) +#define CFIG_LINEAR_PRIORITY 0 + +//- Byte 12 (Default Value = 60h) +#define CFIG_LPRIORITY_MODE 0 +#define CFIG_IFS 6 ;- 6 * 16 = 96 + +//- Byte 13 (Default Value = 0, ALWAYS) + +//- Byte 14 (Default Value = 0F2h, ALWAYS) + +//- Byte 15 (Default Value = E8h) +#define CFIG_PROMISCUOUS_MODE BIT_0 +#define CFIG_BROADCAST_DISABLE BIT_1 +#define CFIG_CRS_CDT BIT_7 + +//- Byte 16 (Default Value = 0, ALWAYS) + +//- Byte 17 (Default Value = 40h, ALWAYS) + +//- Byte 18 (Default Value = F2h) +#define CFIG_STRIPPING BIT_0 +#define CFIG_PADDING BIT_1 +#define CFIG_RX_CRC_TRANSFER BIT_2 + +//- Byte 19 (Default Value = 80h) +#define CFIG_FORCE_FDX BIT_6 +#define CFIG_FDX_PIN_ENABLE BIT_7 + +//- Byte 20 (Default Value = 3Fh) +#define CFIG_MULTI_IA BIT_6 + +//- Byte 21 (Default Value = 05) +#define CFIG_MC_ALL BIT_3 + +/*-----------------------------------------------------------------------*/ +#define D102_REVID 0x0b + +#define HALF_DUPLEX 1 +#define FULL_DUPLEX 2 + +typedef struct s_data_instance { + + UINT16 State; // stopped, started or initialized + UINT16 Bus; + UINT8 Device; + UINT8 Function; + UINT16 VendorID; + UINT16 DeviceID; + UINT16 RevID; + UINT16 SubVendorID; + UINT16 SubSystemID; + + UINT8 PermNodeAddress[PXE_MAC_LENGTH]; + UINT8 CurrentNodeAddress[PXE_MAC_LENGTH]; + UINT8 BroadcastNodeAddress[PXE_MAC_LENGTH]; + UINT32 Config[MAX_PCI_CONFIG_LEN]; + UINT32 NVData[MAX_EEPROM_LEN]; + + UINT32 ioaddr; + UINT32 flash_addr; + + UINT16 LinkSpeed; // actual link speed setting + UINT16 LinkSpeedReq; // requested (forced) link speed + UINT8 DuplexReq; // requested duplex + UINT8 Duplex; // Duplex set + UINT8 CableDetect; // 1 to detect and 0 not to detect the cable + UINT8 LoopBack; + + UINT16 TxBufCnt; + UINT16 TxBufSize; + UINT16 RxBufCnt; + UINT16 RxBufSize; + UINT32 RxTotals; + UINT32 TxTotals; + + UINT16 int_mask; + UINT16 Int_Status; + UINT16 PhyRecord[2]; // primary and secondary PHY record registers from eeprom + UINT8 PhyAddress; + UINT8 int_num; + UINT16 NVData_Len; + UINT32 MemoryLength; + + RxFD *rx_ring; // array of rx buffers + TxCB *tx_ring; // array of tx buffers + struct speedo_stats *statistics; + TxCB *FreeTxHeadPtr; + TxCB *FreeTxTailPtr; + RxFD *RFDTailPtr; + + UINT64 rx_phy_addr; // physical addresses + UINT64 tx_phy_addr; + UINT64 stat_phy_addr; + UINT64 MemoryPtr; + UINT64 Mapped_MemoryPtr; + + UINT64 xmit_done[TX_BUFFER_COUNT << 1]; // circular buffer + UINT16 xmit_done_head; // index into the xmit_done array + UINT16 xmit_done_tail; // where are we filling now (index into xmit_done) + UINT16 cur_rx_ind; // current RX Q head index + UINT16 FreeCBCount; + + BOOLEAN in_interrupt; + BOOLEAN in_transmit; + BOOLEAN Receive_Started; + UINT8 Rx_Filter; + UINT8 VersionFlag; // UNDI30 or UNDI31?? + UINT8 rsvd[3]; + + struct mc{ + UINT16 reserved [3]; // padding for this structure to make it 8 byte aligned + UINT16 list_len; + UINT8 mc_list[MAX_MCAST_ADDRESS_CNT][PXE_MAC_LENGTH]; // 8*32 is the size + } mcast_list; + + UINT64 Unique_ID; + + EFI_PCI_IO_PROTOCOL *Io_Function; + + VOID (*Delay_30)(UINTN); // call back routine + VOID (*Virt2Phys_30)(UINT64 virtual_addr, UINT64 physical_ptr); // call back routine + VOID (*Block_30)(UINT32 enable); // call back routine + VOID (*Mem_Io_30)(UINT8 read_write, UINT8 len, UINT64 port, UINT64 buf_addr); + VOID (*Delay)(UINT64, UINTN); // call back routine + VOID (*Virt2Phys)(UINT64 unq_id, UINT64 virtual_addr, UINT64 physical_ptr); // call back routine + VOID (*Block)(UINT64 unq_id, UINT32 enable); // call back routine + VOID (*Mem_Io)(UINT64 unq_id, UINT8 read_write, UINT8 len, UINT64 port, + UINT64 buf_addr); + VOID (*Map_Mem)(UINT64 unq_id, UINT64 virtual_addr, UINT32 size, + UINT32 Direction, UINT64 mapped_addr); + VOID (*UnMap_Mem)(UINT64 unq_id, UINT64 virtual_addr, UINT32 size, + UINT32 Direction, UINT64 mapped_addr); + VOID (*Sync_Mem)(UINT64 unq_id, UINT64 virtual_addr, + UINT32 size, UINT32 Direction, UINT64 mapped_addr); +} NIC_DATA_INSTANCE; + +#pragma pack(1) +struct MC_CB_STRUCT{ + UINT16 count; + UINT8 m_list[MAX_MCAST_ADDRESS_CNT][ETHER_MAC_ADDR_LEN]; +}; +#pragma pack() + +#define FOUR_GIGABYTE (UINT64)0x100000000ULL diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Init.c b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Init.c new file mode 100644 index 0000000000..70982cba45 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Init.c @@ -0,0 +1,1162 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + init.c + +Abstract: + + Initialization functions for EFI UNDI32 driver + +Revision History + +--*/ + +#include "undi32.h" + +// +// Global Variables +// +PXE_SW_UNDI *pxe = 0; // 3.0 entry point +PXE_SW_UNDI *pxe_31 = 0; // 3.1 entry +UNDI32_DEV *UNDI32DeviceList[MAX_NIC_INTERFACES]; + +NII_TABLE *UnidiDataPointer=NULL; +// +// external Global Variables +// +extern UNDI_CALL_TABLE api_table[]; + +// +// function prototypes +// +EFI_STATUS +InstallConfigTable ( + IN VOID + ); + +EFI_STATUS +EFIAPI +InitializeUNDIDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +VOID +UNDI_notify_virtual ( + EFI_EVENT event, + VOID *context + ); + +VOID +EFIAPI +UndiNotifyExitBs ( + EFI_EVENT Event, + VOID *Context + ); + +EFI_STATUS +EFIAPI +UndiDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +UndiDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +UndiDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_STATUS +AppendMac2DevPath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr, + IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ); +// +// end function prototypes +// +VOID +EFIAPI +UndiNotifyVirtual ( + EFI_EVENT Event, + VOID *Context + ) +/*++ + +Routine Description: + + When address mapping changes to virtual this should make the appropriate + address conversions. + +Arguments: + + (Standard Event handler) + +Returns: + + None + +--*/ +// TODO: Context - add argument and description to function comment +{ + UINT16 Index; + VOID *Pxe31Pointer; + + if (pxe_31 != NULL) { + Pxe31Pointer = (VOID *) pxe_31; + + EfiConvertPointer ( + EFI_OPTIONAL_POINTER, + (void **) &Pxe31Pointer + ); + + // + // UNDI32DeviceList is an array of pointers + // + for (Index = 0; Index < pxe_31->IFcnt; Index++) { + UNDI32DeviceList[Index]->NIIProtocol_31.ID = (UINT64) (UINTN) Pxe31Pointer; + EfiConvertPointer ( + EFI_OPTIONAL_POINTER, + (void **) &(UNDI32DeviceList[Index]) + ); + } + + EfiConvertPointer ( + EFI_OPTIONAL_POINTER, + (void **) &(pxe_31->EntryPoint) + ); + pxe_31 = Pxe31Pointer; + } + + for (Index = 0; Index <= PXE_OPCODE_LAST_VALID; Index++) { + EfiConvertPointer ( + EFI_OPTIONAL_POINTER, + (void **) &api_table[Index].api_ptr + ); + } +} + +VOID +EFIAPI +UndiNotifyExitBs ( + EFI_EVENT Event, + VOID *Context + ) +/*++ + +Routine Description: + + When EFI is shuting down the boot services, we need to install a + configuration table for UNDI to work at runtime! + +Arguments: + + (Standard Event handler) + +Returns: + + None + +--*/ +// TODO: Context - add argument and description to function comment +{ + InstallConfigTable (); +} +// +// UNDI Class Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gUndiDriverBinding = { + UndiDriverSupported, + UndiDriverStart, + UndiDriverStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +InitializeUNDIDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Register Driver Binding protocol for this driver. + +Arguments: + + ImageHandle - Image Handle + + SystemTable - Pointer to system table + +Returns: + + EFI_SUCCESS - Driver loaded. + + other - Driver not loaded. + +--*/ +{ + EFI_STATUS Status; + EFI_EVENT Event; + + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES, + EFI_TPL_NOTIFY, + UndiNotifyExitBs, + NULL, + &Event + ); + + return Status; +} + +EFI_STATUS +EFIAPI +UndiDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a DevicePath, PciIo protocol, Class code of 2, Vendor ID of 0x8086, + and DeviceId of (D100_DEVICE_ID || D102_DEVICE_ID || ICH3_DEVICE_ID_1 || + ICH3_DEVICE_ID_2 || ICH3_DEVICE_ID_3 || ICH3_DEVICE_ID_4 || ICH3_DEVICE_ID_5 || + ICH3_DEVICE_ID_6 || ICH3_DEVICE_ID_7 || ICH3_DEVICE_ID_8) can be supported. + +Arguments: + + This - Protocol instance pointer. + + Controller - Handle of device to test. + + RemainingDevicePath - Not used. + +Returns: + + EFI_SUCCESS - This driver supports this device. + + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_PCI_IO_PROTOCOL *PciIo; + PCI_TYPE00 Pci; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PciIo->Pci.Read ( + PciIo, + EfiPciIoWidthUint8, + 0, + sizeof (PCI_CONFIG_HEADER), + &Pci + ); + + if (!EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + + if (Pci.Hdr.ClassCode[2] == 0x02 && Pci.Hdr.VendorId == PCI_VENDOR_ID_INTEL) { + switch (Pci.Hdr.DeviceId) { + case D100_DEVICE_ID: + case D102_DEVICE_ID: + case ICH3_DEVICE_ID_1: + case ICH3_DEVICE_ID_2: + case ICH3_DEVICE_ID_3: + case ICH3_DEVICE_ID_4: + case ICH3_DEVICE_ID_5: + case ICH3_DEVICE_ID_6: + case ICH3_DEVICE_ID_7: + case ICH3_DEVICE_ID_8: + case 0x1039: + case 0x103A: + case 0x103B: + case 0x103C: + case 0x103D: + case 0x103E: + case 0x1050: + case 0x1051: + case 0x1052: + case 0x1053: + case 0x1054: + case 0x1055: + case 0x1056: + case 0x1057: + case 0x1059: + case 0x1064: + Status = EFI_SUCCESS; + } + } + } + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +UndiDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Start this driver on Controller by opening PciIo and DevicePath protocol. + Initialize PXE structures, create a copy of the Controller Device Path with the + NIC's MAC address appended to it, install the NetworkInterfaceIdentifier protocol + on the newly created Device Path. + +Arguments: + + This - Protocol instance pointer. + + Controller - Handle of device to work with. + + RemainingDevicePath - Not used, always produce all possible children. + +Returns: + + EFI_SUCCESS - This driver is added to Controller. + + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *UndiDevicePath; + PCI_CONFIG_HEADER *CfgHdr; + UNDI32_DEV *UNDI32Device; + UINT16 NewCommand; + UINT8 *TmpPxePointer; + EFI_PCI_IO_PROTOCOL *PciIoFncs; + UINTN Len; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIoFncs, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &UndiDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; + } + + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (UNDI32_DEV), + (VOID **) &UNDI32Device + ); + + if (EFI_ERROR (Status)) { + goto UndiError; + } + + ZeroMem ((CHAR8 *) UNDI32Device, sizeof (UNDI32_DEV)); + + // + // allocate and initialize both (old and new) the !pxe structures here, + // there should only be one copy of each of these structure for any number + // of NICs this undi supports. Also, these structures need to be on a + // paragraph boundary as per the spec. so, while allocating space for these, + // make sure that there is space for 2 !pxe structures (old and new) and a + // 32 bytes padding for alignment adjustment (in case) + // + TmpPxePointer = NULL; + if (pxe_31 == NULL) { + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + (sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32), + (VOID **) &TmpPxePointer + ); + + if (EFI_ERROR (Status)) { + goto UndiErrorDeleteDevice; + } + + ZeroMem ( + TmpPxePointer, + sizeof (PXE_SW_UNDI) + sizeof (PXE_SW_UNDI) + 32 + ); + // + // check for paragraph alignment here, assuming that the pointer is + // already 8 byte aligned. + // + if (((UINTN) TmpPxePointer & 0x0F) != 0) { + pxe_31 = (PXE_SW_UNDI *) ((UINTN) (TmpPxePointer + 8)); + } else { + pxe_31 = (PXE_SW_UNDI *) TmpPxePointer; + } + // + // assuming that the sizeof pxe_31 is a 16 byte multiple + // + pxe = (PXE_SW_UNDI *) ((CHAR8 *) (pxe_31) + sizeof (PXE_SW_UNDI)); + + PxeStructInit (pxe, 0x30); + PxeStructInit (pxe_31, 0x31); + } + + UNDI32Device->NIIProtocol.ID = (UINT64) (UINTN) (pxe); + UNDI32Device->NIIProtocol_31.ID = (UINT64) (UINTN) (pxe_31); + + Status = PciIoFncs->Attributes ( + PciIoFncs, + EfiPciIoAttributeOperationEnable, + EFI_PCI_DEVICE_ENABLE | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER, + NULL + ); + // + // Read all the registers from device's PCI Configuration space + // + Status = PciIoFncs->Pci.Read ( + PciIoFncs, + EfiPciIoWidthUint32, + 0, + MAX_PCI_CONFIG_LEN, + &UNDI32Device->NicInfo.Config + ); + + CfgHdr = (PCI_CONFIG_HEADER *) &(UNDI32Device->NicInfo.Config[0]); + + // + // make sure that this device is a PCI bus master + // + + NewCommand = (UINT16) (CfgHdr->Command | PCI_COMMAND_MASTER | PCI_COMMAND_IO); + if (CfgHdr->Command != NewCommand) { + PciIoFncs->Pci.Write ( + PciIoFncs, + EfiPciIoWidthUint16, + PCI_COMMAND, + 1, + &NewCommand + ); + CfgHdr->Command = NewCommand; + } + + // + // make sure that the latency timer is at least 32 + // + if (CfgHdr->LatencyTimer < 32) { + CfgHdr->LatencyTimer = 32; + PciIoFncs->Pci.Write ( + PciIoFncs, + EfiPciIoWidthUint8, + PCI_LATENCY_TIMER, + 1, + &CfgHdr->LatencyTimer + ); + } + // + // the IfNum index for the current interface will be the total number + // of interfaces initialized so far + // + UNDI32Device->NIIProtocol.IfNum = pxe->IFcnt; + UNDI32Device->NIIProtocol_31.IfNum = pxe_31->IFcnt; + + PxeUpdate (&UNDI32Device->NicInfo, pxe); + PxeUpdate (&UNDI32Device->NicInfo, pxe_31); + + UNDI32Device->NicInfo.Io_Function = PciIoFncs; + UNDI32DeviceList[UNDI32Device->NIIProtocol.IfNum] = UNDI32Device; + UNDI32Device->Undi32BaseDevPath = UndiDevicePath; + + Status = AppendMac2DevPath ( + &UNDI32Device->Undi32DevPath, + UNDI32Device->Undi32BaseDevPath, + &UNDI32Device->NicInfo + ); + + if (Status != 0) { + goto UndiErrorDeletePxe; + } + + UNDI32Device->Signature = UNDI_DEV_SIGNATURE; + + UNDI32Device->NIIProtocol.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION; + UNDI32Device->NIIProtocol.Type = EfiNetworkInterfaceUndi; + UNDI32Device->NIIProtocol.MajorVer = PXE_ROMID_MAJORVER; + UNDI32Device->NIIProtocol.MinorVer = PXE_ROMID_MINORVER; + UNDI32Device->NIIProtocol.ImageSize = 0; + UNDI32Device->NIIProtocol.ImageAddr = 0; + UNDI32Device->NIIProtocol.Ipv6Supported = FALSE; + + UNDI32Device->NIIProtocol.StringId[0] = 'U'; + UNDI32Device->NIIProtocol.StringId[1] = 'N'; + UNDI32Device->NIIProtocol.StringId[2] = 'D'; + UNDI32Device->NIIProtocol.StringId[3] = 'I'; + + UNDI32Device->NIIProtocol_31.Revision = EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31; + UNDI32Device->NIIProtocol_31.Type = EfiNetworkInterfaceUndi; + UNDI32Device->NIIProtocol_31.MajorVer = PXE_ROMID_MAJORVER; + UNDI32Device->NIIProtocol_31.MinorVer = PXE_ROMID_MINORVER_31; + UNDI32Device->NIIProtocol_31.ImageSize = 0; + UNDI32Device->NIIProtocol_31.ImageAddr = 0; + UNDI32Device->NIIProtocol_31.Ipv6Supported = FALSE; + + UNDI32Device->NIIProtocol_31.StringId[0] = 'U'; + UNDI32Device->NIIProtocol_31.StringId[1] = 'N'; + UNDI32Device->NIIProtocol_31.StringId[2] = 'D'; + UNDI32Device->NIIProtocol_31.StringId[3] = 'I'; + + UNDI32Device->DeviceHandle = NULL; + + // + // install both the 3.0 and 3.1 NII protocols. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &UNDI32Device->DeviceHandle, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + &UNDI32Device->NIIProtocol_31, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + &UNDI32Device->NIIProtocol, + &gEfiDevicePathProtocolGuid, + UNDI32Device->Undi32DevPath, + NULL + ); + + if (EFI_ERROR (Status)) { + goto UndiErrorDeleteDevicePath; + } + + // + // if the table exists, free it and alloc again, or alloc it directly + // + if (UnidiDataPointer != NULL) { + Status = gBS->FreePool(UnidiDataPointer); + } + if (EFI_ERROR (Status)) { + goto UndiErrorDeleteDevicePath; + } + + Len = (pxe_31->IFcnt * sizeof (NII_ENTRY)) + sizeof (UnidiDataPointer); + Status = gBS->AllocatePool (EfiRuntimeServicesData, Len, (VOID **) &UnidiDataPointer); + + if (EFI_ERROR (Status)) { + goto UndiErrorAllocDataPointer; + } + + // + // Open For Child Device + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIoFncs, + This->DriverBindingHandle, + UNDI32Device->DeviceHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + + return EFI_SUCCESS; +UndiErrorAllocDataPointer: + gBS->UninstallMultipleProtocolInterfaces ( + &UNDI32Device->DeviceHandle, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + &UNDI32Device->NIIProtocol_31, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + &UNDI32Device->NIIProtocol, + &gEfiDevicePathProtocolGuid, + UNDI32Device->Undi32DevPath, + NULL + ); + +UndiErrorDeleteDevicePath: + UNDI32DeviceList[UNDI32Device->NIIProtocol.IfNum] = NULL; + gBS->FreePool (UNDI32Device->Undi32DevPath); + +UndiErrorDeletePxe: + PxeUpdate (NULL, pxe); + PxeUpdate (NULL, pxe_31); + if (TmpPxePointer != NULL) { + gBS->FreePool (TmpPxePointer); + + } + +UndiErrorDeleteDevice: + gBS->FreePool (UNDI32Device); + +UndiError: + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +UndiDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + Stop this driver on Controller by removing NetworkInterfaceIdentifier protocol and + closing the DevicePath and PciIo protocols on Controller. + +Arguments: + This - Protocol instance pointer. + Controller - Handle of device to stop driver on. + NumberOfChildren - How many children need to be stopped. + ChildHandleBuffer - Not used. + +Returns: + EFI_SUCCESS - This driver is removed Controller. + other - This driver was not removed from this device. + +--*/ +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + EFI_STATUS Status; + BOOLEAN AllChildrenStopped; + UINTN Index; + UNDI32_DEV *UNDI32Device; + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NIIProtocol; + EFI_PCI_IO_PROTOCOL *PciIo; + + // + // Complete all outstanding transactions to Controller. + // Don't allow any new transaction to Controller to be started. + // + if (NumberOfChildren == 0) { + + // + // Close the bus driver + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiNetworkInterfaceIdentifierProtocolGuid, + (VOID **) &NIIProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + + UNDI32Device = UNDI_DEV_FROM_THIS (NIIProtocol); + + Status = gBS->CloseProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + UNDI32Device->Undi32DevPath, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + &UNDI32Device->NIIProtocol_31, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + &UNDI32Device->NIIProtocol, + NULL + ); + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiPciIoProtocolGuid, + (VOID **) &PciIo, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + gBS->FreePool (UNDI32Device->Undi32DevPath); + gBS->FreePool (UNDI32Device); + } + } + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + +} + +VOID +TmpDelay ( + IN UINT64 UnqId, + IN UINTN MicroSeconds + ) +/*++ + +Routine Description: + + Use the EFI boot services to produce a pause. This is also the routine which + gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can + do it's own pause. + +Arguments: + + UnqId - Runtime O/S routine might use this, this temp routine does not use it + + MicroSeconds - Determines the length of pause. + +Returns: + + none + +--*/ +{ + gBS->Stall ((UINT32) MicroSeconds); +} + +VOID +TmpMemIo ( + IN UINT64 UnqId, + IN UINT8 ReadWrite, + IN UINT8 Len, + IN UINT64 Port, + IN UINT64 BuffAddr + ) +/*++ + +Routine Description: + + Use the PCI IO abstraction to issue memory or I/O reads and writes. This is also the routine which + gets replaced during RunTime by the O/S in the NIC_DATA_INSTANCE so it can do it's own I/O abstractions. + +Arguments: + + UnqId - Runtime O/S routine may use this field, this temp routine does not. + + ReadWrite - Determine if it is an I/O or Memory Read/Write Operation. + + Len - Determines the width of the data operation. + + Port - What port to Read/Write from. + + BuffAddr - Address to read to or write from. + +Returns: + + none + +--*/ +{ + EFI_PCI_IO_PROTOCOL_WIDTH Width; + NIC_DATA_INSTANCE *AdapterInfo; + + Width = 0; + AdapterInfo = (NIC_DATA_INSTANCE *) (UINTN) UnqId; + switch (Len) { + case 2: + Width = 1; + break; + + case 4: + Width = 2; + break; + + case 8: + Width = 3; + break; + } + + switch (ReadWrite) { + case PXE_IO_READ: + AdapterInfo->Io_Function->Io.Read ( + AdapterInfo->Io_Function, + Width, + 1, + Port, + 1, + (VOID *) (UINTN) (BuffAddr) + ); + break; + + case PXE_IO_WRITE: + AdapterInfo->Io_Function->Io.Write ( + AdapterInfo->Io_Function, + Width, + 1, + Port, + 1, + (VOID *) (UINTN) (BuffAddr) + ); + break; + + case PXE_MEM_READ: + AdapterInfo->Io_Function->Mem.Read ( + AdapterInfo->Io_Function, + Width, + 0, + Port, + 1, + (VOID *) (UINTN) (BuffAddr) + ); + break; + + case PXE_MEM_WRITE: + AdapterInfo->Io_Function->Mem.Write ( + AdapterInfo->Io_Function, + Width, + 0, + Port, + 1, + (VOID *) (UINTN) (BuffAddr) + ); + break; + } + + return ; +} + +EFI_STATUS +AppendMac2DevPath ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPtr, + IN EFI_DEVICE_PATH_PROTOCOL *BaseDevPtr, + IN NIC_DATA_INSTANCE *AdapterInfo + ) +/*++ + +Routine Description: + + Using the NIC data structure information, read the EEPROM to get the MAC address and then allocate space + for a new devicepath (**DevPtr) which will contain the original device path the NIC was found on (*BaseDevPtr) + and an added MAC node. + +Arguments: + + DevPtr - Pointer which will point to the newly created device path with the MAC node attached. + + BaseDevPtr - Pointer to the device path which the UNDI device driver is latching on to. + + AdapterInfo - Pointer to the NIC data structure information which the UNDI driver is layering on.. + +Returns: + + EFI_SUCCESS - A MAC address was successfully appended to the Base Device Path. + + other - Not enough resources available to create new Device Path node. + +--*/ +{ + EFI_MAC_ADDRESS MACAddress; + PCI_CONFIG_HEADER *CfgHdr; + INT32 Val; + INT32 Index; + INT32 Index2; + UINT8 AddrLen; + MAC_ADDR_DEVICE_PATH MacAddrNode; + EFI_DEVICE_PATH_PROTOCOL *EndNode; + UINT8 *DevicePtr; + UINT16 TotalPathLen; + UINT16 BasePathLen; + EFI_STATUS Status; + + // + // set the environment ready (similar to UNDI_Start call) so that we can + // execute the other UNDI_ calls to get the mac address + // we are using undi 3.1 style + // + AdapterInfo->Delay = TmpDelay; + AdapterInfo->Virt2Phys = (VOID *) 0; + AdapterInfo->Block = (VOID *) 0; + AdapterInfo->Map_Mem = (VOID *) 0; + AdapterInfo->UnMap_Mem = (VOID *) 0; + AdapterInfo->Sync_Mem = (VOID *) 0; + AdapterInfo->Mem_Io = TmpMemIo; + // + // these tmp call-backs follow 3.1 undi style + // i.e. they have the unique_id parameter. + // + AdapterInfo->VersionFlag = 0x31; + AdapterInfo->Unique_ID = (UINT64) (UINTN) AdapterInfo; + + // + // undi init portion + // + CfgHdr = (PCI_CONFIG_HEADER *) &(AdapterInfo->Config[0]); + AdapterInfo->ioaddr = 0; + AdapterInfo->RevID = CfgHdr->RevID; + + AddrLen = E100bGetEepromAddrLen (AdapterInfo); + + for (Index = 0, Index2 = 0; Index < 3; Index++) { + Val = E100bReadEeprom (AdapterInfo, Index, AddrLen); + MACAddress.Addr[Index2++] = (UINT8) Val; + MACAddress.Addr[Index2++] = (UINT8) (Val >> 8); + } + + SetMem (MACAddress.Addr + Index2, sizeof (EFI_MAC_ADDRESS) - Index2, 0); + //for (; Index2 < sizeof (EFI_MAC_ADDRESS); Index2++) { + // MACAddress.Addr[Index2] = 0; + //} + // + // stop undi + // + AdapterInfo->Delay = (VOID *) 0; + AdapterInfo->Mem_Io = (VOID *) 0; + + // + // fill the mac address node first + // + ZeroMem ((CHAR8 *) &MacAddrNode, sizeof MacAddrNode); + CopyMem ( + (CHAR8 *) &MacAddrNode.MacAddress, + (CHAR8 *) &MACAddress, + sizeof (EFI_MAC_ADDRESS) + ); + + MacAddrNode.Header.Type = MESSAGING_DEVICE_PATH; + MacAddrNode.Header.SubType = MSG_MAC_ADDR_DP; + MacAddrNode.Header.Length[0] = sizeof (MacAddrNode); + MacAddrNode.Header.Length[1] = 0; + + // + // find the size of the base dev path. + // + EndNode = BaseDevPtr; + + while (!IsDevicePathEnd (EndNode)) { + EndNode = NextDevicePathNode (EndNode); + } + + BasePathLen = (UINT16) ((UINTN) (EndNode) - (UINTN) (BaseDevPtr)); + + // + // create space for full dev path + // + TotalPathLen = (UINT16) (BasePathLen + sizeof (MacAddrNode) + sizeof (EFI_DEVICE_PATH_PROTOCOL)); + + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + TotalPathLen, + (VOID **) &DevicePtr + ); + + if (Status != EFI_SUCCESS) { + return Status; + } + // + // copy the base path, mac addr and end_dev_path nodes + // + *DevPtr = (EFI_DEVICE_PATH_PROTOCOL *) DevicePtr; + CopyMem (DevicePtr, (CHAR8 *) BaseDevPtr, BasePathLen); + DevicePtr += BasePathLen; + CopyMem (DevicePtr, (CHAR8 *) &MacAddrNode, sizeof (MacAddrNode)); + DevicePtr += sizeof (MacAddrNode); + CopyMem (DevicePtr, (CHAR8 *) EndNode, sizeof (EFI_DEVICE_PATH_PROTOCOL)); + + return EFI_SUCCESS; +} + +EFI_STATUS +InstallConfigTable ( + IN VOID + ) +/*++ + +Routine Description: + + Install a GUID/Pointer pair into the system's configuration table. + +Arguments: + + none + +Returns: + + EFI_SUCCESS - Install a GUID/Pointer pair into the system's configuration table. + + other - Did not successfully install the GUID/Pointer pair into the configuration table. + +--*/ +// TODO: VOID - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_CONFIGURATION_TABLE *CfgPtr; + NII_TABLE *TmpData; + UINT16 Index; + NII_TABLE *UndiData; + + if (pxe_31 == NULL) { + return EFI_SUCCESS; + } + + if(UnidiDataPointer == NULL) { + return EFI_SUCCESS; + } + + UndiData = (NII_TABLE *)UnidiDataPointer; + + UndiData->NumEntries = pxe_31->IFcnt; + UndiData->NextLink = NULL; + + for (Index = 0; Index < pxe_31->IFcnt; Index++) { + UndiData->NiiEntry[Index].InterfacePointer = &UNDI32DeviceList[Index]->NIIProtocol_31; + UndiData->NiiEntry[Index].DevicePathPointer = UNDI32DeviceList[Index]->Undi32DevPath; + } + + // + // see if there is an entry in the config table already + // + CfgPtr = gST->ConfigurationTable; + + for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { + Status = CompareGuid ( + &CfgPtr->VendorGuid, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31 + ); + if (Status != EFI_SUCCESS) { + break; + } + + CfgPtr++; + } + + if (Index < gST->NumberOfTableEntries) { + TmpData = (NII_TABLE *) CfgPtr->VendorTable; + + // + // go to the last link + // + while (TmpData->NextLink != NULL) { + TmpData = TmpData->NextLink; + } + + TmpData->NextLink = UndiData; + + // + // 1st one in chain + // + UndiData = (NII_TABLE *) CfgPtr->VendorTable; + } + + // + // create an entry in the configuration table for our GUID + // + Status = gBS->InstallConfigurationTable ( + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + UndiData + ); + return Status; +} diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.mbd b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.mbd new file mode 100644 index 0000000000..d486d63165 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.mbd @@ -0,0 +1,47 @@ + + + + + Undi + A1f436EA-A127-4EF8-957C-8048606FF670 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + BaseLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibNull + BasePrintLib + EdkDxeRuntimeDriverLib + UefiDriverModelLib + DxeHobLib + DxeMemoryAllocationLib + + EdkDxeSalLib + + + diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.msa b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.msa new file mode 100644 index 0000000000..dcf0238680 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi.msa @@ -0,0 +1,92 @@ + + + + + Undi + DXE_RUNTIME_DRIVER + RT_DRIVER + A1f436EA-A127-4EF8-957C-8048606FF670 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + BaseLib + DxeRuntimeDriverLib + DebugLib + HobLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + Init.c + Decode.c + E100b.c + E100b.h + Undi32.h + + + MdePkg + EdkModulePkg + + + DevicePath + PciIo + NetworkInterfaceIdentifier + NetworkInterfaceIdentifier31 + + + + + gEfiEventVirtualAddressChangeGuid + 0x13fa7698, 0xc831, 0x49c7, 0x87, 0xea, 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96 + + + gEfiEventExitBootServicesGuid + 0x27abf055, 0xb1b8, 0x4c26, 0x80, 0x48, 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf + + + + + + gEfiNetworkInterfaceIdentifierProtocolGuid_31 + + + + + InitializeUNDIDriver + + + gUndiDriverBinding + + + UndiNotifyVirtual + + + + diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi32.h b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi32.h new file mode 100644 index 0000000000..5e0044398f --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/Undi32.h @@ -0,0 +1,208 @@ + +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + undi32.h + +Abstract: + + EFI internal structures for the EFI UNDI driver + + + +Revision History + +--*/ + +#ifndef _UNDI_32_H_ +#define _UNDI_32_H_ + + +#include "E100b.h" +#include + +#define MAX_NIC_INTERFACES 16 + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION_31 0x00010001 +#define PXE_ROMID_MINORVER_31 0x10 +#define PXE_STATFLAGS_DB_WRITE_TRUNCATED 0x2000 + +// +// UNDI_CALL_TABLE.state can have the following values +// +#define DONT_CHECK -1 +#define ANY_STATE -1 +#define MUST_BE_STARTED 1 +#define MUST_BE_INITIALIZED 2 + +#define UNDI_DEV_SIGNATURE EFI_SIGNATURE_32('u','n','d','i') +#define UNDI_DEV_FROM_THIS(a) CR(a, UNDI32_DEV, NIIProtocol, UNDI_DEV_SIGNATURE) +#define UNDI_DEV_FROM_NIC(a) CR(a, UNDI32_DEV, NicInfo, UNDI_DEV_SIGNATURE) + +typedef struct { + UINTN Signature; + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL NIIProtocol; + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL NIIProtocol_31; + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *Undi32BaseDevPath; + EFI_DEVICE_PATH_PROTOCOL *Undi32DevPath; + NIC_DATA_INSTANCE NicInfo; +} UNDI32_DEV; + +typedef struct { + UINT16 cpbsize; + UINT16 dbsize; + UINT16 opflags; + UINT16 state; + VOID (*api_ptr)(); +} UNDI_CALL_TABLE; + +typedef struct { + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *InterfacePointer; + EFI_DEVICE_PATH_PROTOCOL *DevicePathPointer; +} NII_ENTRY; + +typedef struct NII_CONFIG_ENTRY { + UINT32 NumEntries; + UINT32 Reserved; // padding for alignment + struct NII_CONFIG_ENTRY *NextLink; + NII_ENTRY NiiEntry[1]; +} NII_TABLE; + +typedef VOID (*ptr)(VOID); +typedef VOID (*bsptr_30)(UINTN); +typedef VOID (*virtphys_30)(UINT64, UINT64); +typedef VOID (*block_30)(UINT32); +typedef VOID (*mem_io_30)(UINT8, UINT8, UINT64, UINT64); + +typedef VOID (*bsptr)(UINT64, UINTN); +typedef VOID (*virtphys)(UINT64, UINT64, UINT64); +typedef VOID (*block)(UINT64, UINT32); +typedef VOID (*mem_io)(UINT64, UINT8, UINT8, UINT64, UINT64); + +typedef VOID (*map_mem)(UINT64, UINT64, UINT32, UINT32, UINT64); +typedef VOID (*unmap_mem)(UINT64, UINT64, UINT32, UINT32, UINT64); +typedef VOID (*sync_mem)(UINT64, UINT64, UINT32, UINT32, UINT64); + +// +// functions defined in e100b.c +// +UINT8 InByte (NIC_DATA_INSTANCE *AdapterInfo, UINT32 Port); +UINT16 InWord (NIC_DATA_INSTANCE *AdapterInfo, UINT32 Port); +UINT32 InLong (NIC_DATA_INSTANCE *AdapterInfo, UINT32 Port); +VOID OutByte (NIC_DATA_INSTANCE *AdapterInfo, UINT8 Data, UINT32 Port); +VOID OutWord (NIC_DATA_INSTANCE *AdapterInfo, UINT16 Data, UINT32 Port); +VOID OutLong (NIC_DATA_INSTANCE *AdapterInfo, UINT32 Data, UINT32 Port); + +UINTN E100bInit (NIC_DATA_INSTANCE *AdapterInfo); +UINTN E100bReset (NIC_DATA_INSTANCE *AdapterInfo, INT32 OpFlags); +UINTN E100bShutdown (NIC_DATA_INSTANCE *AdapterInfo); +UINTN E100bTransmit (NIC_DATA_INSTANCE *AdapterInfo, UINT64 cpb, UINT16 opflags); +UINTN E100bReceive (NIC_DATA_INSTANCE *AdapterInfo, UINT64 cpb, UINT64 db); +UINTN E100bSetfilter (NIC_DATA_INSTANCE *AdapterInfo, UINT16 New_filter, + UINT64 cpb, UINT32 cpbsize); +UINTN E100bStatistics(NIC_DATA_INSTANCE *AdapterInfo, UINT64 db, UINT16 dbsize); +UINT8 E100bSetupIAAddr (NIC_DATA_INSTANCE *AdapterInfo); +UINT8 E100bSetInterruptState (NIC_DATA_INSTANCE *AdapterInfo); + +UINT8 E100bGetEepromAddrLen (NIC_DATA_INSTANCE *AdapterInfo); +UINT16 E100bReadEeprom (NIC_DATA_INSTANCE *AdapterInfo, INT32 Location, UINT8 address_len); +INT16 E100bReadEepromAndStationAddress (NIC_DATA_INSTANCE *AdapterInfo); + +UINT16 next(UINT16); +UINT8 SetupCBlink (NIC_DATA_INSTANCE *AdapterInfo); +VOID SetFreeCB (NIC_DATA_INSTANCE *AdapterInfo,TxCB *); +TxCB *GetFreeCB (NIC_DATA_INSTANCE *AdapterInfo); +UINT16 CheckCBList (NIC_DATA_INSTANCE *AdapterInfo); + +UINT8 SelectiveReset (NIC_DATA_INSTANCE *AdapterInfo); +UINT16 InitializeChip (NIC_DATA_INSTANCE *AdapterInfo); +UINT8 SetupReceiveQueues (NIC_DATA_INSTANCE *AdapterInfo); +VOID Recycle_RFD (NIC_DATA_INSTANCE *AdapterInfo, UINT16); +VOID XmitWaitForCompletion (NIC_DATA_INSTANCE *AdapterInfo); +INT8 CommandWaitForCompletion (TxCB *cmd_ptr, NIC_DATA_INSTANCE *AdapterInfo); + +BOOLEAN PhyDetect (NIC_DATA_INSTANCE *AdapterInfo); +VOID PhyReset (NIC_DATA_INSTANCE *AdapterInfo); +VOID +MdiWrite ( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT8 RegAddress, + IN UINT8 PhyAddress, + IN UINT16 DataValue + ); + +VOID +MdiRead( + IN NIC_DATA_INSTANCE *AdapterInfo, + IN UINT8 RegAddress, + IN UINT8 PhyAddress, + IN OUT UINT16 *DataValue + ); + +BOOLEAN SetupPhy (NIC_DATA_INSTANCE *AdapterInfo); +VOID FindPhySpeedAndDpx (NIC_DATA_INSTANCE *AdapterInfo, UINT32 PhyId); + + + +// +// functions defined in init.c +// +VOID +TmpDelay ( + IN UINT64 UnqId, + IN UINTN MicroSeconds + ); + +VOID +TmpMemIo ( + IN UINT64 UnqId, + IN UINT8 ReadWrite, + IN UINT8 Len, + IN UINT64 Port, + IN UINT64 BufAddr + ); + +// +// functions defined in decode.c +// +VOID UNDI_GetState(); +VOID UNDI_Start(); +VOID UNDI_Stop(); +VOID UNDI_GetInitInfo(); +VOID UNDI_GetConfigInfo(); +VOID UNDI_Initialize(); +VOID UNDI_Reset(); +VOID UNDI_Shutdown(); +VOID UNDI_Interrupt(); +VOID UNDI_RecFilter(); +VOID UNDI_StnAddr(); +VOID UNDI_Statistics(); +VOID UNDI_ip2mac(); +VOID UNDI_NVData(); +VOID UNDI_Status(); +VOID UNDI_FillHeader(); +VOID UNDI_Transmit(); +VOID UNDI_Receive(); + +VOID UNDI_APIEntry_new(UINT64); +VOID UNDI_APIEntry_old(UINT64); +VOID UNDI_APIEntry_Common(UINT64); + +PXE_IPV4 convert_mcip(PXE_MAC_ADDR *); +INT32 validate_mcip (PXE_MAC_ADDR *MCastAddr); + +VOID PxeStructInit (PXE_SW_UNDI *PxePtr, UINTN VersionFlag); +VOID PxeUpdate (NIC_DATA_INSTANCE *NicPtr, PXE_SW_UNDI *PxePtr); + +#endif diff --git a/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/build.xml b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/build.xml new file mode 100644 index 0000000000..2375cd7820 --- /dev/null +++ b/EdkModulePkg/Bus/Pci/Undi/RuntimeDxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ComponentName.c b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ComponentName.c new file mode 100644 index 0000000000..3f61c46d54 --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ComponentName.c @@ -0,0 +1,155 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "ScsiBus.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +ScsiBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +ScsiBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gScsiBusComponentName = { + ScsiBusComponentNameGetDriverName, + ScsiBusComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mScsiBusDriverNameTable[] = { + { "eng", (CHAR16 *) L"SCSI Bus Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +ScsiBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gScsiBusComponentName.SupportedLanguages, + mScsiBusDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +ScsiBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.c b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.c new file mode 100644 index 0000000000..3aa31a812f --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.c @@ -0,0 +1,751 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + scsibus.c + +Abstract: + + +Revision History +--*/ + +#include "scsibus.h" + +EFI_STATUS +EFIAPI +SCSIBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +SCSIBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +SCSIBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_DRIVER_BINDING_PROTOCOL gSCSIBusDriverBinding = { + SCSIBusDriverBindingSupported, + SCSIBusDriverBindingStart, + SCSIBusDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +SCSIBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Arguments: + + Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + + // + // If RemainingDevicePath is not NULL, it should verify that the first device + // path node in RemainingDevicePath is an ATAPI Device path node. + // + if (RemainingDevicePath != NULL) { + if ((RemainingDevicePath->Type != MESSAGING_DEVICE_PATH) || + (RemainingDevicePath->SubType != MSG_ATAPI_DP) || + (DevicePathNodeLength (RemainingDevicePath) != sizeof(ATAPI_DEVICE_PATH))) { + return EFI_UNSUPPORTED; + } + } + // + // check for the existence of SCSI Pass Thru Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SCSIBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Arguments: + + Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; + UINT32 StartPun; + UINT64 StartLun; + UINT32 Pun; + UINT64 Lun; + BOOLEAN ScanOtherPuns; + + StartPun = 0; + StartLun = 0; + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + // + // Consume SCSI Pass Thru protocol. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + (VOID **) &ScsiPassThru, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + if (RemainingDevicePath == NULL) { + StartPun = 0xFFFFFFFF; + StartLun = 0; + } else { + ScsiPassThru->GetTargetLun (ScsiPassThru, RemainingDevicePath, &StartPun, &StartLun); + } + + for (Pun = StartPun, ScanOtherPuns = TRUE; ScanOtherPuns;) { + + if (StartPun == 0xFFFFFFFF) { + // + // Remaining Device Path is NULL, scan all the possible Puns in the + // SCSI Channel. + // + Status = ScsiPassThru->GetNextDevice (ScsiPassThru, &Pun, &Lun); + if (EFI_ERROR (Status)) { + // + // no legal Pun and Lun found any more + // + break; + } + } else { + // + // Remaining Device Path is not NULL, only scan the specified Pun. + // + Pun = StartPun; + Lun = StartLun; + ScanOtherPuns = FALSE; + } + + // + // Avoid creating handle for the host adapter. + // + if (Pun == ScsiPassThru->Mode->AdapterId) { + continue; + } + + // + // Scan for the scsi device, if it attaches to the scsi bus, + // then create handle and install scsi i/o protocol. + // + Status = ScsiScanCreateDevice (This, Controller, Pun, Lun, ScsiPassThru, ParentDevicePath); + } + + return Status; +} + +EFI_STATUS +EFIAPI +SCSIBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + + Arguments: + + Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: NumberOfChildren - add argument and description to function comment +// TODO: ChildHandleBuffer - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + BOOLEAN AllChildrenStopped; + UINTN Index; + EFI_SCSI_IO_PROTOCOL *ScsiIo; + SCSI_IO_DEV *ScsiIoDevice; + EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; + + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + gBS->CloseProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiScsiIoProtocolGuid, + (VOID **) &ScsiIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + continue; + } + + ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (ScsiIo); + // + // Close the child handle + // + Status = gBS->CloseProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + ScsiIoDevice->DevicePath, + &gEfiScsiIoProtocolGuid, + &ScsiIoDevice->ScsiIo, + NULL + ); + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + gBS->OpenProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + (VOID **) &ScsiPassThru, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + gBS->FreePool (ScsiIoDevice); + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ScsiGetDeviceType ( + IN EFI_SCSI_IO_PROTOCOL *This, + OUT UINT8 *DeviceType + ) +/*++ + + Routine Description: + Retrieves the device type information of the SCSI Controller. + + Arguments: + This - Protocol instance pointer. + DeviceType - A pointer to the device type information + retrieved from the SCSI Controller. + + Returns: + EFI_SUCCESS - Retrieves the device type information successfully. + EFI_INVALID_PARAMETER - The DeviceType is NULL. +--*/ +{ + SCSI_IO_DEV *ScsiIoDevice; + + if (DeviceType == NULL) { + return EFI_INVALID_PARAMETER; + } + + ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); + *DeviceType = ScsiIoDevice->ScsiDeviceType; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ScsiGetDeviceLocation ( + IN EFI_SCSI_IO_PROTOCOL *This, + OUT UINT8 **Target, + OUT UINT64 *Lun + ) +/*++ + Routine Description: + Retrieves the device location in the SCSI channel. + + Arguments: + This - Protocol instance pointer. + Target - A pointer to the Target ID of a SCSI device + on the SCSI channel. + Lun - A pointer to the LUN of the SCSI device on + the SCSI channel. + + Returns: + EFI_SUCCESS - Retrieves the device location successfully. + EFI_INVALID_PARAMETER - The Target or Lun is NULL. +--*/ +{ + SCSI_IO_DEV *ScsiIoDevice; + + if (Target == NULL || Lun == NULL) { + return EFI_INVALID_PARAMETER; + } + + ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); + + *Target = (UINT8 *) (UINTN) ScsiIoDevice->Pun; + *Lun = ScsiIoDevice->Lun; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ScsiResetBus ( + IN EFI_SCSI_IO_PROTOCOL *This + ) +/*++ + + Routine Description: + Resets the SCSI Bus that the SCSI Controller is attached to. + + Arguments: + This - Protocol instance pointer. + + Returns: + EFI_SUCCESS - The SCSI bus is reset successfully. + EFI_DEVICE_ERROR - Errors encountered when resetting the SCSI bus. + EFI_UNSUPPORTED - The bus reset operation is not supported by the + SCSI Host Controller. + EFI_TIMEOUT - A timeout occurred while attempting to reset + the SCSI bus. +--*/ +{ + SCSI_IO_DEV *ScsiIoDevice; + + ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); + + return ScsiIoDevice->ScsiPassThru->ResetChannel (ScsiIoDevice->ScsiPassThru); + +} + +EFI_STATUS +EFIAPI +ScsiResetDevice ( + IN EFI_SCSI_IO_PROTOCOL *This + ) +/*++ + + Routine Description: + Resets the SCSI Controller that the device handle specifies. + + Arguments: + This - Protocol instance pointer. + + + Returns: + EFI_SUCCESS - Reset the SCSI controller successfully. + EFI_DEVICE_ERROR - Errors are encountered when resetting the + SCSI Controller. + EFI_UNSUPPORTED - The SCSI bus does not support a device + reset operation. + EFI_TIMEOUT - A timeout occurred while attempting to + reset the SCSI Controller. +--*/ +{ + SCSI_IO_DEV *ScsiIoDevice; + + ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); + + return ScsiIoDevice->ScsiPassThru->ResetTarget ( + ScsiIoDevice->ScsiPassThru, + ScsiIoDevice->Pun, + ScsiIoDevice->Lun + ); +} + +EFI_STATUS +EFIAPI +ScsiExecuteSCSICommand ( + IN EFI_SCSI_IO_PROTOCOL *This, + IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ) +/*++ + + Routine Description: + Sends a SCSI Request Packet to the SCSI Controller for execution. + + Arguments: + This - Protocol instance pointer. + Packet - The SCSI request packet to send to the SCSI + Controller specified by the device handle. + Event - If the SCSI bus where the SCSI device is attached + does not support non-blocking I/O, then Event is + ignored, and blocking I/O is performed. + If Event is NULL, then blocking I/O is performed. + If Event is not NULL and non-blocking I/O is + supported, then non-blocking I/O is performed, + and Event will be signaled when the SCSI Request + Packet completes. + Returns: + EFI_SUCCESS - The SCSI Request Packet was sent by the host + successfully, and TransferLength bytes were + transferred to/from DataBuffer.See + HostAdapterStatus, TargetStatus, + SenseDataLength, and SenseData in that order + for additional status information. + EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, + but the entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in TransferLength. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + EFI_NOT_READY - The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued.The caller may retry again later. + EFI_DEVICE_ERROR - A device error occurred while attempting to send + the SCSI Request Packet. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. + The SCSI Request Packet was not sent, so no + additional status information is available. + EFI_UNSUPPORTED - The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). The SCSI Request Packet was not + sent, so no additional status information is + available. + EFI_TIMEOUT - A timeout occurred while waiting for the SCSI + Request Packet to execute. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. +--*/ +{ + SCSI_IO_DEV *ScsiIoDevice; + EFI_STATUS Status; + + EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *RequestPacket; + + if (Packet == NULL) { + return EFI_INVALID_PARAMETER; + } + + ScsiIoDevice = SCSI_IO_DEV_FROM_THIS (This); + + RequestPacket = (EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *) Packet; + + Status = ScsiIoDevice->ScsiPassThru->PassThru ( + ScsiIoDevice->ScsiPassThru, + ScsiIoDevice->Pun, + ScsiIoDevice->Lun, + RequestPacket, + Event + ); + return Status; +} + +EFI_STATUS +ScsiScanCreateDevice ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + UINT32 Pun, + UINT64 Lun, + EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru, + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Controller - TODO: add argument description + Pun - TODO: add argument description + Lun - TODO: add argument description + ScsiPassThru - TODO: add argument description + ParentDevicePath - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_OUT_OF_RESOURCES - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + SCSI_IO_DEV *ScsiIoDevice; + EFI_DEVICE_PATH_PROTOCOL *ScsiDevicePath; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (SCSI_IO_DEV), + (VOID **) &ScsiIoDevice + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (ScsiIoDevice, sizeof (SCSI_IO_DEV)); + + ScsiIoDevice->Signature = SCSI_IO_DEV_SIGNATURE; + ScsiIoDevice->ScsiPassThru = ScsiPassThru; + ScsiIoDevice->Pun = Pun; + ScsiIoDevice->Lun = Lun; + + ScsiIoDevice->ScsiIo.GetDeviceType = ScsiGetDeviceType; + ScsiIoDevice->ScsiIo.GetDeviceLocation = ScsiGetDeviceLocation; + ScsiIoDevice->ScsiIo.ResetBus = ScsiResetBus; + ScsiIoDevice->ScsiIo.ResetDevice = ScsiResetDevice; + ScsiIoDevice->ScsiIo.ExecuteSCSICommand = ScsiExecuteSCSICommand; + + if (!DiscoverScsiDevice (ScsiIoDevice)) { + gBS->FreePool (ScsiIoDevice); + return EFI_SUCCESS; + } + + // + // Set Device Path + // + Status = ScsiIoDevice->ScsiPassThru->BuildDevicePath ( + ScsiIoDevice->ScsiPassThru, + ScsiIoDevice->Pun, + ScsiIoDevice->Lun, + &ScsiDevicePath + ); + if (Status == EFI_OUT_OF_RESOURCES) { + gBS->FreePool (ScsiIoDevice); + return Status; + } + + ScsiIoDevice->DevicePath = AppendDevicePathNode ( + ParentDevicePath, + ScsiDevicePath + ); + // + // The memory space for ScsiDevicePath is allocated in + // ScsiPassThru->BuildDevicePath() function; It is no longer used + // after EfiAppendDevicePathNode,so free the memory it occupies. + // + gBS->FreePool (ScsiDevicePath); + + if (ScsiIoDevice->DevicePath == NULL) { + gBS->FreePool (ScsiIoDevice); + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ScsiIoDevice->Handle, + &gEfiDevicePathProtocolGuid, + ScsiIoDevice->DevicePath, + &gEfiScsiIoProtocolGuid, + &ScsiIoDevice->ScsiIo, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (ScsiIoDevice); + } else { + gBS->OpenProtocol ( + Controller, + &gEfiScsiPassThruProtocolGuid, + (VOID **) &ScsiPassThru, + This->DriverBindingHandle, + ScsiIoDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } + + return EFI_SUCCESS; +} + +BOOLEAN +DiscoverScsiDevice ( + SCSI_IO_DEV *ScsiIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_STATUS Status; + EFI_SCSI_INQUIRY_DATA InquiryData; + UINT32 InquiryDataLength; + EFI_SCSI_SENSE_DATA SenseData; + UINT8 SenseDataLength; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + + HostAdapterStatus = 0; + TargetStatus = 0; + // + // Using Inquiry command to scan for the device + // + InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA); + SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA); + + Status = SubmitInquiryCommand ( + &ScsiIoDevice->ScsiIo, + EfiScsiStallSeconds (1), + (VOID *) &SenseData, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus, + (VOID *) &InquiryData, + &InquiryDataLength, + FALSE + ); + if (EFI_ERROR (Status)) { + // + // ParseSenseData (&SenseData,SenseDataLength); + // + return FALSE; + } + // + // Retrieved inquiry data successfully + // + if ((InquiryData.Peripheral_Qualifier != 0) && + (InquiryData.Peripheral_Qualifier != 3)) { + return FALSE; + } + + if (InquiryData.Peripheral_Qualifier == 3) { + if (InquiryData.Peripheral_Type != 0x1f) { + return FALSE; + } + } + + if ((0x1e >= InquiryData.Peripheral_Type) && (InquiryData.Peripheral_Type >= 0xa)) { + return FALSE; + } + + // + // valid device type and peripheral qualifier combination. + // + ScsiIoDevice->ScsiDeviceType = InquiryData.Peripheral_Type; + ScsiIoDevice->RemovableDevice = InquiryData.RMB; + if (InquiryData.Version == 0) { + ScsiIoDevice->ScsiVersion = 0; + } else { + // + // ANSI-approved version + // + ScsiIoDevice->ScsiVersion = (UINT8) (InquiryData.Version & 0x03); + } + + return TRUE; +} diff --git a/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.h b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.h new file mode 100644 index 0000000000..da1fa23bfa --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.h @@ -0,0 +1,266 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + scsibus.h + +Abstract: + + Header file for SCSI Bus Driver. + +Revision History +++*/ + +// TODO: fix comment to end with --*/ +#ifndef _SCSI_BUS_H +#define _SCSI_BUS_H + + +#include +// +// 1000 * 1000 * 10 +// +#define ONE_SECOND_TIMER 10000000 + +#define SCSI_IO_DEV_SIGNATURE EFI_SIGNATURE_32 ('s', 'c', 'i', 'o') + +typedef struct { + UINT32 Signature; + + EFI_HANDLE Handle; + EFI_SCSI_IO_PROTOCOL ScsiIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru; + + UINT32 Pun; + UINT64 Lun; + UINT8 ScsiDeviceType; + UINT8 ScsiVersion; + BOOLEAN RemovableDevice; +} SCSI_IO_DEV; + +#define SCSI_IO_DEV_FROM_THIS(a) CR (a, SCSI_IO_DEV, ScsiIo, SCSI_IO_DEV_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gScsiBusDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gScsiBusComponentName; + +EFI_STATUS +EFIAPI +ScsiGetDeviceType ( + IN EFI_SCSI_IO_PROTOCOL *This, + OUT UINT8 *DeviceType + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + DeviceType - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +ScsiResetBus ( + IN EFI_SCSI_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +ScsiResetDevice ( + IN EFI_SCSI_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +ScsiExecuteSCSICommand ( + IN EFI_SCSI_IO_PROTOCOL *This, + IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *CommandPacket, + IN EFI_EVENT Event + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + CommandPacket - TODO: add argument description + Event - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiScanCreateDevice ( + EFI_DRIVER_BINDING_PROTOCOL *This, + EFI_HANDLE Controller, + UINT32 Pun, + UINT64 Lun, + EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru, + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Controller - TODO: add argument description + Pun - TODO: add argument description + Lun - TODO: add argument description + ScsiPassThru - TODO: add argument description + ParentDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +DiscoverScsiDevice ( + SCSI_IO_DEV *ScsiIoDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiIoDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetLunList ( + EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru, + UINT32 Target, + UINT64 **LunArray, + UINTN *NumberOfLuns + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiPassThru - TODO: add argument description + Target - TODO: add argument description + LunArray - TODO: add argument description + NumberOfLuns - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiBusSubmitReportLunCommand ( + EFI_SCSI_PASS_THRU_PROTOCOL *ScsiPassThru, + UINT32 Target, + UINTN AllocationLength, + VOID *Buffer, + EFI_SCSI_SENSE_DATA *SenseData, + UINT8 *SenseDataLength, + UINT8 *HostAdapterStatus, + UINT8 *TargetStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiPassThru - TODO: add argument description + Target - TODO: add argument description + AllocationLength - TODO: add argument description + Buffer - TODO: add argument description + SenseData - TODO: add argument description + SenseDataLength - TODO: add argument description + HostAdapterStatus - TODO: add argument description + TargetStatus - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; +#endif diff --git a/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.mbd b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.mbd new file mode 100644 index 0000000000..0254903cd1 --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.mbd @@ -0,0 +1,44 @@ + + + + + ScsiBus + 0167CCC4-D0F7-4f21-A3EF-9E64B7CDCE8B + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkScsiLib + DxeMemoryAllocationLib + UefiDevicePathLib + + diff --git a/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.msa b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.msa new file mode 100644 index 0000000000..c4c0b4566b --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/ScsiBus.msa @@ -0,0 +1,68 @@ + + + + + ScsiBus + DXE_DRIVER + BS_DRIVER + 0167CCC4-D0F7-4f21-A3EF-9E64B7CDCE8B + 0 + Component description file for Scsi Bus module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseMemoryLib + EdkScsiLib + MemoryAllocationLib + UefiBootServicesTableLib + DevicePathLib + + + ScsiBus.h + ScsiBus.c + ComponentName.c + + + MdePkg + EdkModulePkg + + + ScsiPassThru + DevicePath + ScsiIo + + + + + + + gSCSIBusDriverBinding + gScsiBusComponentName + + + diff --git a/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/build.xml b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/build.xml new file mode 100644 index 0000000000..9942471bb9 --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiBus/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ComponentName.c b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ComponentName.c new file mode 100644 index 0000000000..15f02d6c41 --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ComponentName.c @@ -0,0 +1,190 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "ScsiDisk.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +ScsiDiskComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +ScsiDiskComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gScsiDiskComponentName = { + ScsiDiskComponentNameGetDriverName, + ScsiDiskComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mScsiDiskDriverNameTable[] = { + { "eng", (CHAR16 *) L"Scsi Disk Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +ScsiDiskComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gScsiDiskComponentName.SupportedLanguages, + mScsiDiskDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +ScsiDiskComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + SCSI_DISK_DEV *ScsiDiskDevice; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + gScsiDiskDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (BlockIo); + + return LookupUnicodeString ( + Language, + gScsiDiskComponentName.SupportedLanguages, + ScsiDiskDevice->ControllerNameTable, + ControllerName + ); + +} diff --git a/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.c b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.c new file mode 100644 index 0000000000..2c6fd29d37 --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.c @@ -0,0 +1,2414 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ScsiDisk.c + +Abstract: + +--*/ + +#include "scsidisk.h" + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding = { + ScsiDiskDriverBindingSupported, + ScsiDiskDriverBindingStart, + ScsiDiskDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Arguments: + + Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_SCSI_IO_PROTOCOL *ScsiIo; + UINT8 DeviceType; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + (VOID **) &ScsiIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ScsiIo->GetDeviceType (ScsiIo, &DeviceType); + if (!EFI_ERROR (Status)) { + if ((DeviceType == EFI_SCSI_TYPE_DISK) || (DeviceType == EFI_SCSI_TYPE_CDROM)) { + Status = EFI_SUCCESS; + } else { + Status = EFI_UNSUPPORTED; + } + } + + gBS->CloseProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; +} + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Arguments: + + Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_SCSI_IO_PROTOCOL *ScsiIo; + SCSI_DISK_DEV *ScsiDiskDevice; + BOOLEAN Temp; + UINT8 Index; + UINT8 MaxRetry; + BOOLEAN NeedRetry; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (SCSI_DISK_DEV), + (VOID **) &ScsiDiskDevice + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (ScsiDiskDevice, sizeof (SCSI_DISK_DEV)); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + (VOID **) &ScsiIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (ScsiDiskDevice); + return Status; + } + + ScsiDiskDevice->Signature = SCSI_DISK_DEV_SIGNATURE; + ScsiDiskDevice->ScsiIo = ScsiIo; + ScsiDiskDevice->BlkIo.Media = &ScsiDiskDevice->BlkIoMedia; + ScsiDiskDevice->BlkIo.Reset = ScsiDiskReset; + ScsiDiskDevice->BlkIo.ReadBlocks = ScsiDiskReadBlocks; + ScsiDiskDevice->BlkIo.WriteBlocks = ScsiDiskWriteBlocks; + ScsiDiskDevice->BlkIo.FlushBlocks = ScsiDiskFlushBlocks; + ScsiDiskDevice->Handle = Controller; + + ScsiIo->GetDeviceType (ScsiIo, &(ScsiDiskDevice->DeviceType)); + switch (ScsiDiskDevice->DeviceType) { + case EFI_SCSI_TYPE_DISK: + ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200; + break; + + case EFI_SCSI_TYPE_CDROM: + ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800; + break; + } + // + // The Sense Data Array's initial size is 6 + // + ScsiDiskDevice->SenseDataNumber = 6; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber, + (VOID **) &(ScsiDiskDevice->SenseData) + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (ScsiDiskDevice); + return Status; + } + + ZeroMem ( + ScsiDiskDevice->SenseData, + sizeof (EFI_SCSI_SENSE_DATA) * ScsiDiskDevice->SenseDataNumber + ); + + // + // Retrive device information + // + MaxRetry = 2; + for (Index = 0; Index < MaxRetry; Index++) { + Status = ScsiDiskInquiryDevice (ScsiDiskDevice, &NeedRetry); + if (!EFI_ERROR (Status)) { + break; + } + + if (!NeedRetry) { + gBS->FreePool (ScsiDiskDevice->SenseData); + gBS->CloseProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (ScsiDiskDevice); + return EFI_DEVICE_ERROR; + } + } + // + // The second parameter "TRUE" means must + // retrieve media capacity + // + Status = ScsiDiskDetectMedia (ScsiDiskDevice, TRUE, &Temp); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiBlockIoProtocolGuid, + &ScsiDiskDevice->BlkIo, + NULL + ); + } + + if (EFI_ERROR (Status)) { + gBS->FreePool (ScsiDiskDevice->SenseData); + gBS->CloseProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (ScsiDiskDevice); + return Status; + } + + ScsiDiskDevice->ControllerNameTable = NULL; + AddUnicodeString ( + "eng", + gScsiDiskComponentName.SupportedLanguages, + &ScsiDiskDevice->ControllerNameTable, + (CHAR16 *) L"SCSI Disk Device" + ); + + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +ScsiDiskDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + + Arguments: + + Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Controller - add argument and description to function comment +// TODO: NumberOfChildren - add argument and description to function comment +// TODO: ChildHandleBuffer - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_BLOCK_IO_PROTOCOL *BlkIo; + SCSI_DISK_DEV *ScsiDiskDevice; + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (BlkIo); + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiBlockIoProtocolGuid, + &ScsiDiskDevice->BlkIo + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiScsiIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + ReleaseScsiDiskDeviceResources (ScsiDiskDevice); + + return EFI_SUCCESS; + } + // + // errors met + // + return Status; +} + +// +// Block I/O Protocol Interface +// + +EFI_STATUS +EFIAPI +ScsiDiskReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + SCSI_DISK_DEV *ScsiDiskDevice; + EFI_STATUS Status; + + ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This); + + Status = ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo); + + if (!ExtendedVerification) { + return Status; + } + + Status = ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo); + + return Status; +} + +EFI_STATUS +EFIAPI +ScsiDiskReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_NO_MEDIA - TODO: Add description for return value + EFI_MEDIA_CHANGED - TODO: Add description for return value + EFI_BAD_BUFFER_SIZE - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + +--*/ +{ + SCSI_DISK_DEV *ScsiDiskDevice; + EFI_BLOCK_IO_MEDIA *Media; + EFI_STATUS Status; + UINTN BlockSize; + UINTN NumberOfBlocks; + BOOLEAN MediaChange; + + MediaChange = FALSE; + if (!Buffer) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This); + + if (!IsDeviceFixed (ScsiDiskDevice)) { + + Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (MediaChange) { + gBS->ReinstallProtocolInterface ( + ScsiDiskDevice->Handle, + &gEfiBlockIoProtocolGuid, + &ScsiDiskDevice->BlkIo, + &ScsiDiskDevice->BlkIo + ); + } + } + // + // Get the intrinsic block size + // + Media = ScsiDiskDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + + NumberOfBlocks = BufferSize / BlockSize; + + if (!(Media->MediaPresent)) { + return EFI_NO_MEDIA; + } + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (LBA > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + + // + // if all the parameters are valid, then perform read sectors command + // to transfer data from device to host. + // + Status = ScsiDiskReadSectors (ScsiDiskDevice, Buffer, LBA, NumberOfBlocks); + + return Status; +} + +EFI_STATUS +EFIAPI +ScsiDiskWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_NO_MEDIA - TODO: Add description for return value + EFI_MEDIA_CHANGED - TODO: Add description for return value + EFI_BAD_BUFFER_SIZE - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + +--*/ +{ + SCSI_DISK_DEV *ScsiDiskDevice; + EFI_BLOCK_IO_MEDIA *Media; + EFI_STATUS Status; + UINTN BlockSize; + UINTN NumberOfBlocks; + BOOLEAN MediaChange; + + MediaChange = FALSE; + if (!Buffer) { + return EFI_INVALID_PARAMETER; + } + + if (BufferSize == 0) { + return EFI_SUCCESS; + } + + ScsiDiskDevice = SCSI_DISK_DEV_FROM_THIS (This); + + if (!IsDeviceFixed (ScsiDiskDevice)) { + + Status = ScsiDiskDetectMedia (ScsiDiskDevice, FALSE, &MediaChange); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (MediaChange) { + gBS->ReinstallProtocolInterface ( + ScsiDiskDevice->Handle, + &gEfiBlockIoProtocolGuid, + &ScsiDiskDevice->BlkIo, + &ScsiDiskDevice->BlkIo + ); + } + } + // + // Get the intrinsic block size + // + Media = ScsiDiskDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + + NumberOfBlocks = BufferSize / BlockSize; + + if (!(Media->MediaPresent)) { + return EFI_NO_MEDIA; + } + + if (MediaId != Media->MediaId) { + return EFI_MEDIA_CHANGED; + } + + if (BufferSize % BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + if (LBA > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + return EFI_INVALID_PARAMETER; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + return EFI_INVALID_PARAMETER; + } + // + // if all the parameters are valid, then perform read sectors command + // to transfer data from device to host. + // + Status = ScsiDiskWriteSectors (ScsiDiskDevice, Buffer, LBA, NumberOfBlocks); + + return Status; +} + +EFI_STATUS +EFIAPI +ScsiDiskFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + // + // return directly + // + return EFI_SUCCESS; +} + +EFI_STATUS +ScsiDiskDetectMedia ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN MustReadCapacity, + BOOLEAN *MediaChange + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + MustReadCapacity - TODO: add argument description + MediaChange - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReadCapacityStatus; + EFI_SCSI_SENSE_DATA *SenseData; + UINTN NumberOfSenseKeys; + BOOLEAN NeedRetry; + BOOLEAN NeedReadCapacity; + UINT8 Index; + UINT8 MaxRetry; + EFI_BLOCK_IO_MEDIA OldMedia; + UINTN Action; + + Status = EFI_SUCCESS; + ReadCapacityStatus = EFI_SUCCESS; + SenseData = NULL; + NumberOfSenseKeys = 0; + NeedReadCapacity = FALSE; + CopyMem (&OldMedia, ScsiDiskDevice->BlkIo.Media, sizeof (OldMedia)); + // OldMedia = *(ScsiDiskDevice->BlkIo.Media); + + *MediaChange = FALSE; + + MaxRetry = 3; + for (Index = 0; Index < MaxRetry; Index++) { + Status = ScsiDiskTestUnitReady ( + ScsiDiskDevice, + &NeedRetry, + &SenseData, + &NumberOfSenseKeys + ); + if (!EFI_ERROR (Status)) { + break; + } + + if (!NeedRetry) { + return Status; + } + } + + if ((Index == MaxRetry) && EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = DetectMediaParsingSenseKeys ( + ScsiDiskDevice, + SenseData, + NumberOfSenseKeys, + &Action + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // ACTION_NO_ACTION: need not read capacity + // other action code: need read capacity + // + if (Action == ACTION_NO_ACTION) { + NeedReadCapacity = FALSE; + } else { + NeedReadCapacity = TRUE; + } + + // + // either NeedReadCapacity is TRUE, or MustReadCapacity is TRUE, + // retrieve capacity via Read Capacity command + // + if (NeedReadCapacity || MustReadCapacity) { + + // + // retrieve media information + // + MaxRetry = 3; + for (Index = 0; Index < MaxRetry; Index++) { + + ReadCapacityStatus = ScsiDiskReadCapacity ( + ScsiDiskDevice, + &NeedRetry, + &SenseData, + &NumberOfSenseKeys + ); + if (EFI_ERROR (ReadCapacityStatus) && !NeedRetry) { + return EFI_DEVICE_ERROR; + } + // + // analyze sense key to action + // + Status = DetectMediaParsingSenseKeys ( + ScsiDiskDevice, + SenseData, + NumberOfSenseKeys, + &Action + ); + // + // if Status is error, it may indicate crisis error, + // so return without retry. + // + if (EFI_ERROR (Status)) { + return Status; + } + + switch (Action) { + case ACTION_NO_ACTION: + // + // no retry + // + Index = MaxRetry; + break; + + case ACTION_RETRY_COMMAND_LATER: + // + // retry the ReadCapacity later and continuously, until the condition + // no longer emerges. + // stall time is 100000us, or say 0.1 second. + // + gBS->Stall (100000); + Index = 0; + break; + + default: + // + // other cases, just retry the command + // + break; + } + } + + if ((Index == MaxRetry) && EFI_ERROR (ReadCapacityStatus)) { + return EFI_DEVICE_ERROR; + } + } + + if (ScsiDiskDevice->BlkIo.Media->MediaId != OldMedia.MediaId) { + // + // Media change information got from the device + // + *MediaChange = TRUE; + } + + if (ScsiDiskDevice->BlkIo.Media->ReadOnly != OldMedia.ReadOnly) { + *MediaChange = TRUE; + ScsiDiskDevice->BlkIo.Media->MediaId += 1; + } + + if (ScsiDiskDevice->BlkIo.Media->BlockSize != OldMedia.BlockSize) { + *MediaChange = TRUE; + ScsiDiskDevice->BlkIo.Media->MediaId += 1; + } + + if (ScsiDiskDevice->BlkIo.Media->LastBlock != OldMedia.LastBlock) { + *MediaChange = TRUE; + ScsiDiskDevice->BlkIo.Media->MediaId += 1; + } + + if (ScsiDiskDevice->BlkIo.Media->MediaPresent != OldMedia.MediaPresent) { + if (ScsiDiskDevice->BlkIo.Media->MediaPresent) { + // + // when change from no media to media present, reset the MediaId to 1. + // + ScsiDiskDevice->BlkIo.Media->MediaId = 1; + } else { + // + // when no media, reset the MediaId to zero. + // + ScsiDiskDevice->BlkIo.Media->MediaId = 0; + } + + *MediaChange = TRUE; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ScsiDiskInquiryDevice ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + +--*/ +{ + UINT32 InquiryDataLength; + UINT8 SenseDataLength; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + EFI_SCSI_SENSE_DATA *SenseDataArray; + UINTN NumberOfSenseKeys; + EFI_STATUS Status; + UINT8 MaxRetry; + UINT8 Index; + + InquiryDataLength = sizeof (EFI_SCSI_INQUIRY_DATA); + SenseDataLength = 0; + + Status = SubmitInquiryCommand ( + ScsiDiskDevice->ScsiIo, + EfiScsiStallSeconds (1), + NULL, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus, + (VOID *) &(ScsiDiskDevice->InquiryData), + &InquiryDataLength, + FALSE + ); + switch (Status) { + // + // no need to check HostAdapterStatus and TargetStatus + // + case EFI_SUCCESS: + case EFI_WARN_BUFFER_TOO_SMALL: + ParseInquiryData (ScsiDiskDevice); + return EFI_SUCCESS; + + case EFI_NOT_READY: + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + + case EFI_INVALID_PARAMETER: + case EFI_UNSUPPORTED: + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + + // + // go ahead to check HostAdapterStatus and TargetStatus + // (EFI_TIMEOUT, EFI_DEVICE_ERROR) + // + default: + break; + } + + Status = CheckHostAdapterStatus (HostAdapterStatus); + switch (Status) { + case EFI_SUCCESS: + break; + + case EFI_TIMEOUT: + case EFI_NOT_READY: + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + + case EFI_DEVICE_ERROR: + // + // reset the scsi channel + // + ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo); + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + Status = CheckTargetStatus (TargetStatus); + switch (Status) { + case EFI_SUCCESS: + break; + + case EFI_NOT_READY: + // + // reset the scsi device + // + ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo); + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + + case EFI_DEVICE_ERROR: + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + // + // if goes here, meant SubmitInquiryCommand() failed. + // if ScsiDiskRequestSenseKeys() succeeds at last, + // better retry SubmitInquiryCommand(). (by setting *NeedRetry = TRUE) + // + MaxRetry = 3; + for (Index = 0; Index < MaxRetry; Index++) { + + Status = ScsiDiskRequestSenseKeys ( + ScsiDiskDevice, + NeedRetry, + &SenseDataArray, + &NumberOfSenseKeys, + TRUE + ); + if (!EFI_ERROR (Status)) { + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } + + if (!*NeedRetry) { + return EFI_DEVICE_ERROR; + } + } + // + // ScsiDiskRequestSenseKeys() failed after several rounds of retry. + // set *NeedRetry = FALSE to avoid the outside caller try again. + // + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +ScsiDiskTestUnitReady ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys + ) +// TODO: function comment should start with '/*++' +/* + When Test Unit Ready command succeeds, + retrieve Sense Keys via Request Sense; + When Test Unit Ready command encounters any error caused by host adapter or + target, return error without retrieving Sense Keys. +*/ +// TODO: function comment should end with '--*/' +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: ScsiDiskDevice - add argument and description to function comment +// TODO: NeedRetry - add argument and description to function comment +// TODO: SenseDataArray - add argument and description to function comment +// TODO: NumberOfSenseKeys - add argument and description to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + EFI_STATUS Status; + UINT8 SenseDataLength; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + UINT8 Index; + UINT8 MaxRetry; + + SenseDataLength = 0; + *NumberOfSenseKeys = 0; + + // + // Parameter 3 and 4: do not require sense data, retrieve it when needed. + // + Status = SubmitTestUnitReadyCommand ( + ScsiDiskDevice->ScsiIo, + EfiScsiStallSeconds (1), + NULL, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus + ); + switch (Status) { + // + // no need to check HostAdapterStatus and TargetStatus + // + case EFI_NOT_READY: + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + + case EFI_INVALID_PARAMETER: + case EFI_UNSUPPORTED: + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + + // + // go ahead to check HostAdapterStatus and TargetStatus + // + default: + break; + } + + Status = CheckHostAdapterStatus (HostAdapterStatus); + switch (Status) { + case EFI_SUCCESS: + break; + + case EFI_TIMEOUT: + case EFI_NOT_READY: + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + + case EFI_DEVICE_ERROR: + // + // reset the scsi channel + // + ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo); + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + Status = CheckTargetStatus (TargetStatus); + switch (Status) { + case EFI_SUCCESS: + break; + + case EFI_NOT_READY: + // + // reset the scsi device + // + ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo); + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + + case EFI_DEVICE_ERROR: + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + MaxRetry = 3; + for (Index = 0; Index < MaxRetry; Index++) { + + Status = ScsiDiskRequestSenseKeys ( + ScsiDiskDevice, + NeedRetry, + SenseDataArray, + NumberOfSenseKeys, + FALSE + ); + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + if (!*NeedRetry) { + return EFI_DEVICE_ERROR; + } + } + // + // ScsiDiskRequestSenseKeys() failed after several rounds of retry. + // set *NeedRetry = FALSE to avoid the outside caller try again. + // + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +DetectMediaParsingSenseKeys ( + SCSI_DISK_DEV *ScsiDiskDevice, + EFI_SCSI_SENSE_DATA *SenseData, + UINTN NumberOfSenseKeys, + UINTN *Action + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + SenseData - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Action - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + BOOLEAN RetryLater; + + // + // Default is to read capacity, unless.. + // + *Action = ACTION_READ_CAPACITY; + + if (NumberOfSenseKeys == 0) { + *Action = ACTION_NO_ACTION; + return EFI_SUCCESS; + } + + if (!ScsiDiskHaveSenseKey (SenseData, NumberOfSenseKeys)) { + // + // No Sense Key returned from last submitted command + // + *Action = ACTION_NO_ACTION; + return EFI_SUCCESS; + } + + if (ScsiDiskIsNoMedia (SenseData, NumberOfSenseKeys)) { + ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE; + ScsiDiskDevice->BlkIo.Media->LastBlock = 0; + *Action = ACTION_NO_ACTION; + return EFI_SUCCESS; + } + + if (ScsiDiskIsMediaChange (SenseData, NumberOfSenseKeys)) { + ScsiDiskDevice->BlkIo.Media->MediaId++; + return EFI_SUCCESS; + } + + if (ScsiDiskIsMediaError (SenseData, NumberOfSenseKeys)) { + ScsiDiskDevice->BlkIo.Media->MediaPresent = FALSE; + ScsiDiskDevice->BlkIo.Media->LastBlock = 0; + return EFI_DEVICE_ERROR; + } + + if (ScsiDiskIsHardwareError (SenseData, NumberOfSenseKeys)) { + return EFI_DEVICE_ERROR; + } + + if (!ScsiDiskIsDriveReady (SenseData, NumberOfSenseKeys, &RetryLater)) { + if (RetryLater) { + *Action = ACTION_RETRY_COMMAND_LATER; + return EFI_SUCCESS; + } + + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ScsiDiskReadCapacity ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + +--*/ +{ + EFI_SCSI_DISK_CAPACITY_DATA CapacityData; + UINT32 DataLength; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + EFI_STATUS CommandStatus; + EFI_STATUS Status; + UINT8 Index; + UINT8 MaxRetry; + UINT8 SenseDataLength; + + SenseDataLength = 0; + ZeroMem (&CapacityData, sizeof (EFI_SCSI_DISK_CAPACITY_DATA)); + DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA); + + *NumberOfSenseKeys = 0; + *NeedRetry = FALSE; + // + // submit Read Capacity Command. in this call,not request sense data + // + CommandStatus = SubmitReadCapacityCommand ( + ScsiDiskDevice->ScsiIo, + EfiScsiStallSeconds (1), + NULL, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus, + (VOID *) &CapacityData, + &DataLength, + FALSE + ); + switch (CommandStatus) { + // + // no need to check HostAdapterStatus and TargetStatus + // + case EFI_SUCCESS: + GetMediaInfo (ScsiDiskDevice, &CapacityData); + return EFI_SUCCESS; + + case EFI_NOT_READY: + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + + case EFI_INVALID_PARAMETER: + case EFI_UNSUPPORTED: + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + + // + // go ahead to check HostAdapterStatus and TargetStatus + // (EFI_TIMEOUT, EFI_DEVICE_ERROR, EFI_WARN_BUFFER_TOO_SMALL) + // + default: + break; + } + + Status = CheckHostAdapterStatus (HostAdapterStatus); + switch (Status) { + case EFI_SUCCESS: + break; + + case EFI_TIMEOUT: + case EFI_NOT_READY: + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + + case EFI_DEVICE_ERROR: + // + // reset the scsi channel + // + ScsiDiskDevice->ScsiIo->ResetBus (ScsiDiskDevice->ScsiIo); + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + Status = CheckTargetStatus (TargetStatus); + switch (Status) { + case EFI_SUCCESS: + break; + + case EFI_NOT_READY: + // + // reset the scsi device + // + ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo); + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + + case EFI_DEVICE_ERROR: + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; + } + + // + // if goes here, meant SubmitReadCapacityCommand() failed. + // if ScsiDiskRequestSenseKeys() succeeds at last, + // better retry SubmitReadCapacityCommand(). (by setting *NeedRetry = TRUE) + // + MaxRetry = 3; + for (Index = 0; Index < MaxRetry; Index++) { + + Status = ScsiDiskRequestSenseKeys ( + ScsiDiskDevice, + NeedRetry, + SenseDataArray, + NumberOfSenseKeys, + TRUE + ); + if (!EFI_ERROR (Status)) { + *NeedRetry = TRUE; + return EFI_DEVICE_ERROR; + } + + if (!*NeedRetry) { + return EFI_DEVICE_ERROR; + } + } + // + // ScsiDiskRequestSenseKeys() failed after several rounds of retry. + // set *NeedRetry = FALSE to avoid the outside caller try again. + // + *NeedRetry = FALSE; + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +CheckHostAdapterStatus ( + UINT8 HostAdapterStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + HostAdapterStatus - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_TIMEOUT - TODO: Add description for return value + EFI_NOT_READY - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + switch (HostAdapterStatus) { + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK: + return EFI_SUCCESS; + + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND: + return EFI_TIMEOUT; + + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET: + return EFI_NOT_READY; + + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE: + case EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR: + return EFI_DEVICE_ERROR; + + default: + return EFI_SUCCESS; + } +} + +EFI_STATUS +CheckTargetStatus ( + UINT8 TargetStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + TargetStatus - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + EFI_NOT_READY - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + switch (TargetStatus) { + case EFI_SCSI_IO_STATUS_TARGET_GOOD: + case EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION: + case EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET: + return EFI_SUCCESS; + + case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE: + case EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET: + case EFI_SCSI_IO_STATUS_TARGET_BUSY: + case EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED: + case EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL: + return EFI_NOT_READY; + + case EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT: + return EFI_DEVICE_ERROR; + break; + + default: + return EFI_SUCCESS; + } +} + +EFI_STATUS +ScsiDiskRequestSenseKeys ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + BOOLEAN AskResetIfError + ) +// TODO: function comment should start with '/*++' +/* + Retrieve all sense keys from the device. + When encountering error during the process, + if retrieve sense keys before error encounterred, + return the sense keys with return status set to EFI_SUCCESS, + and NeedRetry set to FALSE; otherwize, return the proper return + status. +*/ +// TODO: function comment should end with '--*/' +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: ScsiDiskDevice - add argument and description to function comment +// TODO: NeedRetry - add argument and description to function comment +// TODO: SenseDataArray - add argument and description to function comment +// TODO: NumberOfSenseKeys - add argument and description to function comment +// TODO: AskResetIfError - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_SCSI_SENSE_DATA *PtrSenseData; + UINT8 SenseDataLength; + BOOLEAN SenseReq; + EFI_STATUS Status; + EFI_STATUS FallStatus; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + + FallStatus = EFI_SUCCESS; + SenseDataLength = sizeof (EFI_SCSI_SENSE_DATA); + + ZeroMem ( + ScsiDiskDevice->SenseData, + sizeof (EFI_SCSI_SENSE_DATA) * (ScsiDiskDevice->SenseDataNumber) + ); + + *NumberOfSenseKeys = 0; + *SenseDataArray = ScsiDiskDevice->SenseData; + PtrSenseData = ScsiDiskDevice->SenseData; + + for (SenseReq = TRUE; SenseReq;) { + + Status = SubmitRequestSenseCommand ( + ScsiDiskDevice->ScsiIo, + EfiScsiStallSeconds (2), + PtrSenseData, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus + ); + switch (Status) { + + case EFI_SUCCESS: + + // + // fall through + // + case EFI_WARN_BUFFER_TOO_SMALL: + FallStatus = EFI_SUCCESS; + break; + + case EFI_TIMEOUT: + + // + // fall through + // + case EFI_NOT_READY: + *NeedRetry = TRUE; + FallStatus = EFI_DEVICE_ERROR; + break; + + case EFI_INVALID_PARAMETER: + case EFI_UNSUPPORTED: + *NeedRetry = FALSE; + FallStatus = EFI_DEVICE_ERROR; + break; + + case EFI_DEVICE_ERROR: + if (AskResetIfError) { + ScsiDiskDevice->ScsiIo->ResetDevice (ScsiDiskDevice->ScsiIo); + } + + FallStatus = EFI_DEVICE_ERROR; + break; + } + + if (EFI_ERROR (FallStatus)) { + if (*NumberOfSenseKeys != 0) { + *NeedRetry = FALSE; + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; + } + } + + (*NumberOfSenseKeys) += 1; + + // + // no more sense key or number of sense keys exceeds predefined, + // skip the loop. + // + if ((PtrSenseData->Sense_Key == EFI_SCSI_SK_NO_SENSE) || + (*NumberOfSenseKeys == ScsiDiskDevice->SenseDataNumber)) { + SenseReq = FALSE; + } + + PtrSenseData += 1; + + } + + return EFI_SUCCESS; +} + +VOID +GetMediaInfo ( + SCSI_DISK_DEV *ScsiDiskDevice, + EFI_SCSI_DISK_CAPACITY_DATA *Capacity + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Capacity - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + ScsiDiskDevice->BlkIo.Media->LastBlock = (Capacity->LastLba3 << 24) | + (Capacity->LastLba2 << 16) | + (Capacity->LastLba1 << 8) | + Capacity->LastLba0; + + ScsiDiskDevice->BlkIo.Media->MediaPresent = TRUE; + ScsiDiskDevice->BlkIo.Media->BlockSize = (Capacity->BlockSize3 << 24) | + (Capacity->BlockSize2 << 16) | + (Capacity->BlockSize1 << 8) | + Capacity->BlockSize0; + if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_DISK) { + ScsiDiskDevice->BlkIo.Media->BlockSize = 0x200; + } + + if (ScsiDiskDevice->DeviceType == EFI_SCSI_TYPE_CDROM) { + ScsiDiskDevice->BlkIo.Media->BlockSize = 0x800; + } +} + +VOID +ParseInquiryData ( + SCSI_DISK_DEV *ScsiDiskDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + ScsiDiskDevice->FixedDevice = (BOOLEAN) (ScsiDiskDevice->InquiryData.RMB ? 0 : 1); + ScsiDiskDevice->BlkIoMedia.RemovableMedia = (BOOLEAN) (!ScsiDiskDevice->FixedDevice); +} + +EFI_STATUS +ScsiDiskReadSectors ( + SCSI_DISK_DEV *ScsiDiskDevice, + VOID *Buffer, + EFI_LBA Lba, + UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Buffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + UINTN BlocksRemaining; + UINT32 Lba32; + UINT8 *PtrBuffer; + UINT32 BlockSize; + UINT32 ByteCount; + UINT32 MaxBlock; + UINT32 SectorCount; + UINT64 Timeout; + EFI_STATUS Status; + UINT8 Index; + UINT8 MaxRetry; + BOOLEAN NeedRetry; + EFI_SCSI_SENSE_DATA *SenseData; + UINT8 SenseDataLength; + UINTN NumberOfSenseKeys; + + SenseData = NULL; + SenseDataLength = 0; + NumberOfSenseKeys = 0; + + Status = EFI_SUCCESS; + + BlocksRemaining = NumberOfBlocks; + BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize; + // + // limit the data bytes that can be transferred by one Read(10) Command + // + MaxBlock = 65536; + + PtrBuffer = Buffer; + Lba32 = (UINT32) Lba; + + while (BlocksRemaining > 0) { + + if (BlocksRemaining <= MaxBlock) { + + SectorCount = (UINT16) BlocksRemaining; + } else { + + SectorCount = MaxBlock; + } + + ByteCount = SectorCount * BlockSize; + Timeout = EfiScsiStallSeconds (2); + + MaxRetry = 2; + for (Index = 0; Index < MaxRetry; Index++) { + + Status = ScsiDiskRead10 ( + ScsiDiskDevice, + &NeedRetry, + &SenseData, + &NumberOfSenseKeys, + Timeout, + PtrBuffer, + &ByteCount, + Lba32, + SectorCount + ); + if (!EFI_ERROR (Status)) { + break; + } + + if (!NeedRetry) { + return EFI_DEVICE_ERROR; + } + + } + + if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) { + return EFI_DEVICE_ERROR; + } + + // + // actual transferred sectors + // + SectorCount = ByteCount / BlockSize; + + Lba32 += SectorCount; + PtrBuffer = PtrBuffer + SectorCount * BlockSize; + BlocksRemaining -= SectorCount; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ScsiDiskWriteSectors ( + SCSI_DISK_DEV *ScsiDiskDevice, + VOID *Buffer, + EFI_LBA Lba, + UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Buffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + UINTN BlocksRemaining; + UINT32 Lba32; + UINT8 *PtrBuffer; + UINT32 BlockSize; + UINT32 ByteCount; + UINT32 MaxBlock; + UINT32 SectorCount; + UINT64 Timeout; + EFI_STATUS Status; + UINT8 Index; + UINT8 MaxRetry; + BOOLEAN NeedRetry; + EFI_SCSI_SENSE_DATA *SenseData; + UINT8 SenseDataLength; + UINTN NumberOfSenseKeys; + + SenseData = NULL; + SenseDataLength = 0; + NumberOfSenseKeys = 0; + + Status = EFI_SUCCESS; + + BlocksRemaining = NumberOfBlocks; + BlockSize = ScsiDiskDevice->BlkIo.Media->BlockSize; + // + // limit the data bytes that can be transferred by one Write(10) Command + // + MaxBlock = 65536; + + PtrBuffer = Buffer; + Lba32 = (UINT32) Lba; + + while (BlocksRemaining > 0) { + + if (BlocksRemaining <= MaxBlock) { + + SectorCount = (UINT16) BlocksRemaining; + } else { + + SectorCount = MaxBlock; + } + + ByteCount = SectorCount * BlockSize; + Timeout = EfiScsiStallSeconds (2); + MaxRetry = 2; + for (Index = 0; Index < MaxRetry; Index++) { + Status = ScsiDiskWrite10 ( + ScsiDiskDevice, + &NeedRetry, + &SenseData, + &NumberOfSenseKeys, + Timeout, + PtrBuffer, + &ByteCount, + Lba32, + SectorCount + ); + if (!EFI_ERROR (Status)) { + break; + } + + if (!NeedRetry) { + return EFI_DEVICE_ERROR; + } + } + + if ((Index == MaxRetry) && (Status != EFI_SUCCESS)) { + return EFI_DEVICE_ERROR; + } + // + // actual transferred sectors + // + SectorCount = ByteCount / BlockSize; + + Lba32 += SectorCount; + PtrBuffer = PtrBuffer + SectorCount * BlockSize; + BlocksRemaining -= SectorCount; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ScsiDiskRead10 ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + UINT64 Timeout, + UINT8 *DataBuffer, + UINT32 *DataLength, + UINT32 StartLba, + UINT32 SectorSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Timeout - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + StartLba - TODO: add argument description + SectorSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UINT8 SenseDataLength; + EFI_STATUS Status; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + + *NeedRetry = FALSE; + *NumberOfSenseKeys = 0; + SenseDataLength = 0; + Status = SubmitRead10Command ( + ScsiDiskDevice->ScsiIo, + Timeout, + NULL, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus, + DataBuffer, + DataLength, + StartLba, + SectorSize + ); + return Status; +} + +EFI_STATUS +ScsiDiskWrite10 ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + UINT64 Timeout, + UINT8 *DataBuffer, + UINT32 *DataLength, + UINT32 StartLba, + UINT32 SectorSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Timeout - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + StartLba - TODO: add argument description + SectorSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_STATUS Status; + UINT8 SenseDataLength; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + + *NeedRetry = FALSE; + *NumberOfSenseKeys = 0; + SenseDataLength = 0; + Status = SubmitWrite10Command ( + ScsiDiskDevice->ScsiIo, + Timeout, + NULL, + &SenseDataLength, + &HostAdapterStatus, + &TargetStatus, + DataBuffer, + DataLength, + StartLba, + SectorSize + ); + return Status; +} + +BOOLEAN +ScsiDiskIsNoMedia ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsNoMedia; + + IsNoMedia = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + // + // Sense Key is EFI_SCSI_SK_NOT_READY (0x2), + // Additional Sense Code is ASC_NO_MEDIA (0x3A) + // + if ((SensePtr->Sense_Key == EFI_SCSI_SK_NOT_READY) && + (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA)) { + IsNoMedia = TRUE; + } + + SensePtr++; + } + + return IsNoMedia; +} + +BOOLEAN +ScsiDiskIsMediaError ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsError; + + IsError = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + switch (SensePtr->Sense_Key) { + + case EFI_SCSI_SK_MEDIUM_ERROR: + // + // Sense Key is EFI_SCSI_SK_MEDIUM_ERROR (0x3) + // + switch (SensePtr->Addnl_Sense_Code) { + + // + // fall through + // + case EFI_SCSI_ASC_MEDIA_ERR1: + + // + // fall through + // + case EFI_SCSI_ASC_MEDIA_ERR2: + + // + // fall through + // + case EFI_SCSI_ASC_MEDIA_ERR3: + case EFI_SCSI_ASC_MEDIA_ERR4: + IsError = TRUE; + break; + + default: + break; + } + + break; + + case EFI_SCSI_SK_NOT_READY: + // + // Sense Key is EFI_SCSI_SK_NOT_READY (0x2) + // + switch (SensePtr->Addnl_Sense_Code) { + // + // Additional Sense Code is ASC_MEDIA_UPSIDE_DOWN (0x6) + // + case EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN: + IsError = TRUE; + break; + + default: + break; + } + break; + + default: + break; + } + + SensePtr++; + } + + return IsError; +} + +BOOLEAN +ScsiDiskIsHardwareError ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsError; + + IsError = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + // + // Sense Key is EFI_SCSI_SK_HARDWARE_ERROR (0x4) + // + if (SensePtr->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) { + IsError = TRUE; + } + + SensePtr++; + } + + return IsError; +} + +BOOLEAN +ScsiDiskIsMediaChange ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsMediaChanged; + + IsMediaChanged = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + // + // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6), + // Additional sense code is EFI_SCSI_ASC_MEDIA_CHANGE (0x28) + // + if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) && + (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE)) { + IsMediaChanged = TRUE; + } + + SensePtr++; + } + + return IsMediaChanged; +} + +BOOLEAN +ScsiDiskIsResetBefore ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsResetBefore; + + IsResetBefore = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + // + // Sense Key is EFI_SCSI_SK_UNIT_ATTENTION (0x6) + // Additional Sense Code is EFI_SCSI_ASC_RESET (0x29) + // + if ((SensePtr->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) && + (SensePtr->Addnl_Sense_Code == EFI_SCSI_ASC_RESET)) { + IsResetBefore = TRUE; + } + + SensePtr++; + } + + return IsResetBefore; +} + +BOOLEAN +ScsiDiskIsDriveReady ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts, + OUT BOOLEAN *RetryLater + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + RetryLater - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsReady; + + IsReady = TRUE; + *RetryLater = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + switch (SensePtr->Sense_Key) { + + case EFI_SCSI_SK_NOT_READY: + // + // Sense Key is EFI_SCSI_SK_NOT_READY (0x2) + // + switch (SensePtr->Addnl_Sense_Code) { + case EFI_SCSI_ASC_NOT_READY: + // + // Additional Sense Code is EFI_SCSI_ASC_NOT_READY (0x4) + // + switch (SensePtr->Addnl_Sense_Code_Qualifier) { + case EFI_SCSI_ASCQ_IN_PROGRESS: + // + // Additional Sense Code Qualifier is + // EFI_SCSI_ASCQ_IN_PROGRESS (0x1) + // + IsReady = FALSE; + *RetryLater = TRUE; + break; + + default: + IsReady = FALSE; + *RetryLater = FALSE; + break; + } + break; + + default: + break; + } + break; + + default: + break; + } + + SensePtr++; + } + + return IsReady; +} + +BOOLEAN +ScsiDiskHaveSenseKey ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SCSI_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN HaveSenseKey; + + if (SenseCounts == 0) { + HaveSenseKey = FALSE; + } else { + HaveSenseKey = TRUE; + } + + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + // + // Sense Key is SK_NO_SENSE (0x0) + // + if ((SensePtr->Sense_Key == EFI_SCSI_SK_NO_SENSE) && + (Index == 0)) { + HaveSenseKey = FALSE; + } + + SensePtr++; + } + + return HaveSenseKey; +} + +VOID +ReleaseScsiDiskDeviceResources ( + IN SCSI_DISK_DEV *ScsiDiskDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + if (ScsiDiskDevice == NULL) { + return ; + } + + if (ScsiDiskDevice->SenseData != NULL) { + gBS->FreePool (ScsiDiskDevice->SenseData); + ScsiDiskDevice->SenseData = NULL; + } + + if (ScsiDiskDevice->ControllerNameTable != NULL) { + FreeUnicodeStringTable (ScsiDiskDevice->ControllerNameTable); + ScsiDiskDevice->ControllerNameTable = NULL; + } + + gBS->FreePool (ScsiDiskDevice); + + ScsiDiskDevice = NULL; +} diff --git a/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.h b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.h new file mode 100644 index 0000000000..96d1da4f90 --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.h @@ -0,0 +1,728 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ScsiDisk.h + +Abstract: + + Header file for SCSI Disk Driver. + +--*/ + +#ifndef _SCSI_DISK_H +#define _SCSI_DISK_H + + +#include + +#define IsDeviceFixed(a) (a)->FixedDevice ? 1 : 0 + +#define SCSI_DISK_DEV_SIGNATURE EFI_SIGNATURE_32 ('s', 'c', 'd', 'k') + +typedef struct { + UINT32 Signature; + + EFI_HANDLE Handle; + + EFI_BLOCK_IO_PROTOCOL BlkIo; + EFI_BLOCK_IO_MEDIA BlkIoMedia; + EFI_SCSI_IO_PROTOCOL *ScsiIo; + UINT8 DeviceType; + BOOLEAN FixedDevice; + UINT16 Reserved; + + EFI_SCSI_SENSE_DATA *SenseData; + UINTN SenseDataNumber; + EFI_SCSI_INQUIRY_DATA InquiryData; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + +} SCSI_DISK_DEV; + +#define SCSI_DISK_DEV_FROM_THIS(a) CR (a, SCSI_DISK_DEV, BlkIo, SCSI_DISK_DEV_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gScsiDiskDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gScsiDiskComponentName; +// +// action code used in detect media process +// +#define ACTION_NO_ACTION 0x00 +#define ACTION_READ_CAPACITY 0x01 +#define ACTION_RETRY_COMMAND_LATER 0x02 + +EFI_STATUS +EFIAPI +ScsiDiskReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +ScsiDiskReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +ScsiDiskWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + LBA - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +ScsiDiskFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskDetectMedia ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN MustReadCap, + BOOLEAN *MediaChange + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + MustReadCap - TODO: add argument description + MediaChange - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskTestUnitReady ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +DetectMediaParsingSenseKeys ( + SCSI_DISK_DEV *ScsiDiskDevice, + EFI_SCSI_SENSE_DATA *SenseData, + UINTN NumberOfSenseKeys, + UINTN *Action + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + SenseData - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Action - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskReadCapacity ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CheckHostAdapterStatus ( + UINT8 HostAdapterStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + HostAdapterStatus - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +CheckTargetStatus ( + UINT8 TargetStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + TargetStatus - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskRequestSenseKeys ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + BOOLEAN AskResetIfError + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + AskResetIfError - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskInquiryDevice ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +ParseInquiryData ( + SCSI_DISK_DEV *ScsiDiskDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskReadSectors ( + SCSI_DISK_DEV *ScsiDiskDevice, + VOID *Buffer, + EFI_LBA Lba, + UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Buffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskWriteSectors ( + SCSI_DISK_DEV *ScsiDiskDevice, + VOID *Buffer, + EFI_LBA Lba, + UINTN NumberOfBlocks + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Buffer - TODO: add argument description + Lba - TODO: add argument description + NumberOfBlocks - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskRead10 ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + UINT64 Timeout, + UINT8 *DataBuffer, + UINT32 *DataLength, + UINT32 StartLba, + UINT32 SectorSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Timeout - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + StartLba - TODO: add argument description + SectorSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +ScsiDiskWrite10 ( + SCSI_DISK_DEV *ScsiDiskDevice, + BOOLEAN *NeedRetry, + EFI_SCSI_SENSE_DATA **SenseDataArray, + UINTN *NumberOfSenseKeys, + UINT64 Timeout, + UINT8 *DataBuffer, + UINT32 *DataLength, + UINT32 StartLba, + UINT32 SectorSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + NeedRetry - TODO: add argument description + SenseDataArray - TODO: add argument description + NumberOfSenseKeys - TODO: add argument description + Timeout - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + StartLba - TODO: add argument description + SectorSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +GetMediaInfo ( + SCSI_DISK_DEV *ScsiDiskDevice, + EFI_SCSI_DISK_CAPACITY_DATA *Capacity + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + Capacity - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsNoMedia ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsMediaError ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsHardwareError ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsMediaChange ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsResetBefore ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskIsDriveReady ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts, + OUT BOOLEAN *NeedRetry + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + NeedRetry - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +ScsiDiskHaveSenseKey ( + IN EFI_SCSI_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SenseData - TODO: add argument description + SenseCounts - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +ReleaseScsiDiskDeviceResources ( + IN SCSI_DISK_DEV *ScsiDiskDevice + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiDiskDevice - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.mbd b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.mbd new file mode 100644 index 0000000000..ec19f96872 --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.mbd @@ -0,0 +1,43 @@ + + + + + ScsiDisk + 0A66E322-3740-4cce-AD62-BD172CECCA35 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkScsiLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.msa b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.msa new file mode 100644 index 0000000000..d81af71b53 --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.msa @@ -0,0 +1,67 @@ + + + + + ScsiDisk + DXE_DRIVER + BS_DRIVER + 0A66E322-3740-4cce-AD62-BD172CECCA35 + 0 + Component description file for Scsi Disk module.Revision History + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + EdkScsiLib + MemoryAllocationLib + UefiBootServicesTableLib + + + ScsiDisk.h + ScsiDisk.c + ComponentName.c + + + MdePkg + EdkModulePkg + + + ScsiIo + BlockIo + + + + + + + gScsiDiskDriverBinding + gScsiDiskComponentName + + + diff --git a/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/build.xml b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/build.xml new file mode 100644 index 0000000000..5d5f4d83b7 --- /dev/null +++ b/EdkModulePkg/Bus/Scsi/ScsiDisk/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/ComponentName.c new file mode 100644 index 0000000000..6a9cf13456 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/ComponentName.c @@ -0,0 +1,190 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "bot.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +UsbBotComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UsbBotComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gUsbBotComponentName = { + UsbBotComponentNameGetDriverName, + UsbBotComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mUsbBotDriverNameTable[] = { + { "eng", (CHAR16 *) L"Usb Bot Mass Storage Driver" }, + { NULL , NULL } +}; + + +EFI_STATUS +EFIAPI +UsbBotComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gUsbBotComponentName.SupportedLanguages, + mUsbBotDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +UsbBotComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + USB_BOT_DEVICE *UsbBotDev; + EFI_USB_ATAPI_PROTOCOL *UsbAtapi; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + (VOID **) &UsbAtapi, + gUsbBotDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + UsbBotDev = USB_BOT_DEVICE_FROM_THIS (UsbAtapi); + + return LookupUnicodeString ( + Language, + gUsbBotComponentName.SupportedLanguages, + UsbBotDev->ControllerNameTable, + ControllerName + ); + +} diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.mbd b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.mbd new file mode 100644 index 0000000000..1d18c75266 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.mbd @@ -0,0 +1,43 @@ + + + + + UsbBot + B40612B9-A063-11d4-9A3A-0090273FC14D + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkUsbLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.msa b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.msa new file mode 100644 index 0000000000..c00bebdce5 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/UsbBot.msa @@ -0,0 +1,69 @@ + + + + + UsbBot + DXE_DRIVER + BS_DRIVER + B40612B9-A063-11d4-9A3A-0090273FC14D + 0 + Component description file for UsbBot module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + EdkUsbLib + ReportStatusCodeLib + MemoryAllocationLib + UefiBootServicesTableLib + + + bot.h + bot.c + ComponentName.c + + + MdePkg + EdkModulePkg + + + DevicePath + UsbIo + UsbAtapi + + + + + + + gUsbBotDriverBinding + gUsbBotComponentName + + + diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c new file mode 100644 index 0000000000..0aa0507c2a --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.c @@ -0,0 +1,1088 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BOT.c + +Abstract: + +--*/ + +#include "bot.h" + +// +// Function prototypes +// +EFI_STATUS +EFIAPI +UsbBotDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// Bot Driver Binding Protocol +// +EFI_STATUS +EFIAPI +BotDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +BotDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +BotDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + + +EFI_DRIVER_BINDING_PROTOCOL gUsbBotDriverBinding = { + BotDriverBindingSupported, + BotDriverBindingStart, + BotDriverBindingStop, + 0x10, + NULL, + NULL +}; + +// +// Bot Protocol +// +STATIC +EFI_STATUS +BotCommandPhase ( + IN USB_BOT_DEVICE *UsbBotDev, + IN VOID *Command, + IN UINT8 CommandSize, + IN UINT32 DataTransferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout + ); + +STATIC +EFI_STATUS +BotDataPhase ( + IN USB_BOT_DEVICE *UsbBotDev, + IN UINT32 *DataSize, + IN OUT VOID *DataBuffer, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout + ); + +STATIC +EFI_STATUS +BotStatusPhase ( + IN USB_BOT_DEVICE *UsbBotDev, + OUT UINT8 *TransferStatus, + IN UINT16 Timeout + ); + +// +// USB Atapi protocol prototype +// +STATIC +EFI_STATUS +EFIAPI +BotAtapiCommand ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds + ); + +STATIC +EFI_STATUS +EFIAPI +BotMassStorageReset ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +VOID +BotReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ); + +STATIC EFI_USB_ATAPI_PROTOCOL BotAtapiProtocol = { + BotAtapiCommand, + BotMassStorageReset, + 0 +}; + +EFI_STATUS +EFIAPI +BotDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a BlockIo and DiskIo protocol can be supported. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device + EFI_ALREADY_STARTED - This driver is already running on this device + other - This driver does not support this device + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + + // + // Check if the Controller supports USB IO protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the Default interface descriptor, now we only + // suppose interface 1 + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + // + // Check if it is a BOT type Mass Storage Device + // + if ((InterfaceDescriptor.InterfaceClass != 0x08) || + (InterfaceDescriptor.InterfaceProtocol != BOT)) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + +Exit: + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; +} + +EFI_STATUS +EFIAPI +BotDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Start this driver on ControllerHandle by opening a Block IO and Disk IO + protocol, reading Device Path, and creating a child handle with a + Disk IO and device path protocol. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to bind driver to + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver is added to DeviceHandle + EFI_ALREADY_STARTED - This driver is already running on DeviceHandle + EFI_OUT_OF_RESOURCES- Can't allocate the memory resource + other - This driver does not support this device + +--*/ +{ + USB_BOT_DEVICE *UsbBotDev; + UINT8 Index; + EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor; + EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + + // + // Check if the Controller supports USB IO protocol + // + UsbBotDev = NULL; + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + InterfaceDescriptor = AllocateZeroPool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR)); + if (InterfaceDescriptor == NULL) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return EFI_OUT_OF_RESOURCES; + } + // + // Get the controller interface descriptor, + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + InterfaceDescriptor + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (InterfaceDescriptor); + goto ErrorExit; + } + + BotAtapiProtocol.CommandProtocol = InterfaceDescriptor->InterfaceSubClass; + + UsbBotDev = AllocateZeroPool (sizeof (USB_BOT_DEVICE)); + if (UsbBotDev == NULL) { + Status = EFI_OUT_OF_RESOURCES; + gBS->FreePool (InterfaceDescriptor); + goto ErrorExit; + } + + UsbBotDev->Signature = USB_BOT_DEVICE_SIGNATURE; + UsbBotDev->UsbIo = UsbIo; + UsbBotDev->InterfaceDescriptor = InterfaceDescriptor; + CopyMem (&UsbBotDev->UsbAtapiProtocol, &BotAtapiProtocol, sizeof (BotAtapiProtocol)); + + // + // Get the Device Path Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &UsbBotDev->DevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + for (Index = 0; Index < InterfaceDescriptor->NumEndpoints; Index++) { + EndpointDescriptor = AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR)); + if (EndpointDescriptor == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + UsbIo->UsbGetEndpointDescriptor ( + UsbIo, + Index, + EndpointDescriptor + ); + + // + // We parse bulk endpoint + // + if ((EndpointDescriptor->Attributes & 0x03) == 0x02) { + if ((EndpointDescriptor->EndpointAddress & 0x80) != 0) { + UsbBotDev->BulkInEndpointDescriptor = EndpointDescriptor; + } else { + UsbBotDev->BulkOutEndpointDescriptor = EndpointDescriptor; + } + + continue; + } + + gBS->FreePool (EndpointDescriptor); + } + // + // Double check we have these endpoint descriptors + // + if (!(UsbBotDev->BulkInEndpointDescriptor && + UsbBotDev->BulkOutEndpointDescriptor)) { + Status = EFI_DEVICE_ERROR; + goto ErrorExit; + } + // + // After installing Usb-Atapi protocol onto this handle + // it will be called by upper layer drivers such as Fat + // + BotReportStatusCode ( + UsbBotDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE) + ); + + // + // Install Usb-Atapi Protocol onto the handle + // + Status = gBS->InstallProtocolInterface ( + &ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + EFI_NATIVE_INTERFACE, + &UsbBotDev->UsbAtapiProtocol + ); + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + UsbBotDev->ControllerNameTable = NULL; + AddUnicodeString ( + "eng", + gUsbBotComponentName.SupportedLanguages, + &UsbBotDev->ControllerNameTable, + (CHAR16 *) L"Usb Bot Mass Storage" + ); + + return EFI_SUCCESS; + +ErrorExit: + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + if (UsbBotDev != NULL) { + if (UsbBotDev->InterfaceDescriptor != NULL) { + gBS->FreePool (UsbBotDev->InterfaceDescriptor); + } + + if (UsbBotDev->BulkInEndpointDescriptor != NULL) { + gBS->FreePool (UsbBotDev->BulkInEndpointDescriptor); + } + + if (UsbBotDev->BulkOutEndpointDescriptor != NULL) { + gBS->FreePool (UsbBotDev->BulkOutEndpointDescriptor); + } + + gBS->FreePool (UsbBotDev); + } + + return Status; +} + +EFI_STATUS +EFIAPI +BotDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + EFI_SUCCESS - This driver is removed DeviceHandle + EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocl + other - This driver was not removed from this device + +--*/ +{ + EFI_STATUS Status; + EFI_USB_ATAPI_PROTOCOL *BotAtapiProtocol; + USB_BOT_DEVICE *UsbBotDev; + + EFI_USB_IO_PROTOCOL *UsbIo; + + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + (VOID **) &BotAtapiProtocol, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + UsbBotDev = USB_BOT_DEVICE_FROM_THIS (BotAtapiProtocol); + + // + // After installing Usb-Atapi protocol onto this handle + // it will be called by upper layer drivers such as Fat + // + UsbIo = UsbBotDev->UsbIo; + + BotReportStatusCode ( + UsbBotDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE) + ); + + // + // Uninstall protocol + // + Status = gBS->UninstallProtocolInterface ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + &UsbBotDev->UsbAtapiProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + // + // Free all allocated resources + // + if (UsbBotDev->InterfaceDescriptor != NULL) { + gBS->FreePool (UsbBotDev->InterfaceDescriptor); + } + + if (UsbBotDev->BulkInEndpointDescriptor != NULL) { + gBS->FreePool (UsbBotDev->BulkInEndpointDescriptor); + } + + if (UsbBotDev->BulkOutEndpointDescriptor != NULL) { + gBS->FreePool (UsbBotDev->BulkOutEndpointDescriptor); + } + + if (UsbBotDev->ControllerNameTable) { + FreeUnicodeStringTable (UsbBotDev->ControllerNameTable); + } + + gBS->FreePool (UsbBotDev); + + return Status; +} + +STATIC +EFI_STATUS +BotRecoveryReset ( + IN USB_BOT_DEVICE *UsbBotDev + ) +/*++ + +Routine Description: + + Bot reset routine + +Arguments: + + UsbBotDev - USB_BOT_DEVICE pointer + +Returns: + EFI_SUCCESS - Success the operation + +--*/ +{ + EFI_STATUS Status; + UINT32 Result; + EFI_USB_DEVICE_REQUEST Request; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointAddr; + + UsbIo = UsbBotDev->UsbIo; + + BotReportStatusCode ( + UsbBotDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET) + ); + + ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // See BOT specification + // + Request.RequestType = 0x21; + Request.Request = 0xFF; + + Status = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbNoData, + TIMEOUT_VALUE, + NULL, + 0, + &Result + ); + + gBS->Stall (100 * 1000); + + if (!EFI_ERROR (Status)) { + // + // clear bulk in endpoint stall feature + // + EndpointAddr = UsbBotDev->BulkInEndpointDescriptor->EndpointAddress; + + Status = UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + &Result + ); + + // + // clear bulk out endpoint stall feature + // + EndpointAddr = UsbBotDev->BulkOutEndpointDescriptor->EndpointAddress; + Status = UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + &Result + ); + } + + return Status; +} +// +// Bot Protocol Implementation +// +STATIC +EFI_STATUS +BotCommandPhase ( + IN USB_BOT_DEVICE *UsbBotDev, + IN VOID *Command, + IN UINT8 CommandSize, + IN UINT32 DataTransferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout + ) +/*++ + + Routine Description: + Send ATAPI command through BOT interface. + + Parameters: + UsbBotDev - USB_BOT_DEVICE + Command - command packet + CommandSize - Command size + DataTransferLength - Data Transfer Length + Direction - Data IN/OUT/NODATA + Timeout - Time out value in milliseconds + Return Values: + EFI_SUCCESS + Others + +--*/ +{ + CBW cbw; + EFI_STATUS Status; + UINT32 Result; + EFI_USB_IO_PROTOCOL *UsbIo; + UINTN DataSize; + + UsbIo = UsbBotDev->UsbIo; + + ZeroMem (&cbw, sizeof (CBW)); + + // + // Fill the command block, detailed see BOT spec + // + cbw.dCBWSignature = CBWSIG; + cbw.dCBWTag = 0x01; + cbw.dCBWDataTransferLength = DataTransferLength; + cbw.bmCBWFlags = (UINT8) (Direction << 7); + cbw.bCBWCBLength = CommandSize; + + CopyMem (cbw.CBWCB, Command, CommandSize); + + DataSize = sizeof (CBW); + + Status = UsbIo->UsbBulkTransfer ( + UsbIo, + (UsbBotDev->BulkOutEndpointDescriptor)->EndpointAddress, + &cbw, + &DataSize, + Timeout, + &Result + ); + if (EFI_ERROR (Status)) { + // + // Command phase fail, we need to recovery reset this device + // + BotRecoveryReset (UsbBotDev); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +BotDataPhase ( + IN USB_BOT_DEVICE *UsbBotDev, + IN UINT32 *DataSize, + IN OUT VOID *DataBuffer, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout + ) +/*++ + + Routine Description: + Get/Send Data through BOT interface + + Parameters: + UsbBotDev - USB_BOT_DEVICE pointer + DataSize - Data size + DataBuffer - Data buffer pointer + Direction - IN/OUT/NODATA + Timeout - Time out value in milliseconds + Return Value: + EFI_SUCCESS + Others + +--*/ +{ + EFI_STATUS Status; + UINT32 Result; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointAddr; + UINTN Remain; + UINTN Increment; + UINT32 MaxPacketLen; + UINT8 *BufferPtr; + UINTN TransferredSize; + UINTN RetryTimes; + UINTN MaxRetry; + UINTN BlockSize; + UINTN PackageNum; + + UsbIo = UsbBotDev->UsbIo; + Remain = *DataSize; + BufferPtr = (UINT8 *) DataBuffer; + TransferredSize = 0; + MaxRetry = 10; + PackageNum = 15; + + // + // retrieve the the max packet length of the given endpoint + // + if (Direction == EfiUsbDataIn) { + MaxPacketLen = (UsbBotDev->BulkInEndpointDescriptor)->MaxPacketSize; + EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress; + } else { + MaxPacketLen = (UsbBotDev->BulkOutEndpointDescriptor)->MaxPacketSize; + EndpointAddr = (UsbBotDev->BulkOutEndpointDescriptor)->EndpointAddress; + } + + RetryTimes = MaxRetry; + BlockSize = PackageNum * MaxPacketLen; + while (Remain > 0) { + // + // Using 15 packets to aVOID Bitstuff error + // + if (Remain > PackageNum * MaxPacketLen) { + Increment = BlockSize; + } else { + Increment = Remain; + } + + Status = UsbIo->UsbBulkTransfer ( + UsbIo, + EndpointAddr, + BufferPtr, + &Increment, + Timeout, + &Result + ); + + TransferredSize += Increment; + + if (EFI_ERROR (Status)) { + RetryTimes--; + if ((RetryTimes == 0) || ((Result & EFI_USB_ERR_TIMEOUT) == 0)) { + goto ErrorExit; + } + + TransferredSize -= Increment; + continue; + } else { + // + // we try MaxTetry times for every bulk transfer + // + RetryTimes = MaxRetry; + } + + BufferPtr += Increment; + Remain -= Increment; + if (Increment < BlockSize && TransferredSize <= *DataSize) { + // + // we get to the end of transter and transter size is + // less than requriedsize + // + break; + } + } + + *DataSize = (UINT32) TransferredSize; + + return EFI_SUCCESS; + +ErrorExit: + if (Direction == EfiUsbDataIn) { + BotReportStatusCode ( + UsbBotDev->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR) + ); + } else { + BotReportStatusCode ( + UsbBotDev->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR) + ); + } + + if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + // + // just endpoint stall happens + // + UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + &Result + ); + } + + *DataSize = (UINT32) TransferredSize; + + return Status; + +} + +STATIC +EFI_STATUS +BotStatusPhase ( + IN USB_BOT_DEVICE *UsbBotDev, + OUT UINT8 *TransferStatus, + IN UINT16 Timeout + ) +/*++ + + Routine Description: + Get transfer status through BOT interface + + Parameters: + UsbBotDev - USB_BOT_DEVICE pointer + TransferStatus - TransferStatus + Timeout - Time out value in milliseconds + Return Value: + EFI_SUCCESS + Others + +--*/ +{ + CSW csw; + EFI_STATUS Status; + UINT32 Result; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointAddr; + UINTN DataSize; + + UsbIo = UsbBotDev->UsbIo; + + ZeroMem (&csw, sizeof (CSW)); + + EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress; + + DataSize = sizeof (CSW); + + // + // Get the status field from bulk transfer + // + Status = UsbIo->UsbBulkTransfer ( + UsbIo, + EndpointAddr, + &csw, + &DataSize, + Timeout, + &Result + ); + if (EFI_ERROR (Status)) { + if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + // + // just endpoint stall happens + // + UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + &Result + ); + } + + ZeroMem (&csw, sizeof (CSW)); + + EndpointAddr = (UsbBotDev->BulkInEndpointDescriptor)->EndpointAddress; + + DataSize = sizeof (CSW); + Status = UsbIo->UsbBulkTransfer ( + UsbIo, + EndpointAddr, + &csw, + &DataSize, + Timeout, + &Result + ); + if (EFI_ERROR (Status)) { + if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + &Result + ); + } + + return Status; + } + } + + if (csw.dCSWSignature == CSWSIG) { + *TransferStatus = csw.bCSWStatus; + } else { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} +// +// Usb Atapi Protocol implementation +// +EFI_STATUS +EFIAPI +BotAtapiCommand ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds + ) +/*++ + + Routine Description: + Send ATAPI command using BOT protocol. + + Arguments: + This - Protocol instance pointer. + Command - Command buffer + CommandSize - Size of Command Buffer + DataBuffer - Data buffer + BufferLength - Length of Data buffer + Direction - Data direction of this command + TimeoutInMilliSeconds - Timeout value in ms + + Returns: + EFI_SUCCESS - Command succeeded. + EFI_DEVICE_ERROR - Command failed. + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS BotDataStatus; + UINT8 TransferStatus; + USB_BOT_DEVICE *UsbBotDev; + UINT32 BufferSize; + + BotDataStatus = EFI_SUCCESS; + TransferStatus = 0; + + // + // Get the context + // + UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This); + + // + // First send ATAPI command through Bot + // + Status = BotCommandPhase ( + UsbBotDev, + Command, + CommandSize, + BufferLength, + Direction, + TimeOutInMilliSeconds + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Send/Get Data if there is a Data Stage + // + switch (Direction) { + + case EfiUsbDataIn: + case EfiUsbDataOut: + BufferSize = BufferLength; + + BotDataStatus = BotDataPhase ( + UsbBotDev, + &BufferSize, + DataBuffer, + Direction, + (UINT16) (TimeOutInMilliSeconds) + ); + + break; + + case EfiUsbNoData: + break; + } + + // + // Status Phase + // + Status = BotStatusPhase ( + UsbBotDev, + &TransferStatus, + TimeOutInMilliSeconds + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (TransferStatus == 0x02) { + // + // Phase error + // + BotRecoveryReset (UsbBotDev); + return EFI_DEVICE_ERROR; + } + + if (TransferStatus == 0x01) { + return EFI_DEVICE_ERROR; + } + + return BotDataStatus; +} + +EFI_STATUS +EFIAPI +BotMassStorageReset ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset Bot Devices + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - TRUE if we need to do strictly reset. + + Returns: + EFI_SUCCESS - Command succeeded. + EFI_DEVICE_ERROR - Command failed. + +--*/ +{ + EFI_STATUS Status; + USB_BOT_DEVICE *UsbBotDev; + EFI_USB_IO_PROTOCOL *UsbIo; + + UsbBotDev = USB_BOT_DEVICE_FROM_THIS (This); + UsbIo = UsbBotDev->UsbIo; + + if (ExtendedVerification) { + // + // If we need to do strictly reset, reset its parent hub port + // + Status = UsbIo->UsbPortReset (UsbIo); + if (EFI_ERROR (Status)) { + return Status; + } + } + + Status = BotRecoveryReset (UsbBotDev); + + return Status; +} + +VOID +BotReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ) +/*++ + + Routine Description: + Report Status Code in Usb Bot Driver + + Arguments: + DevicePath - Use this to get Device Path + CodeType - Status Code Type + CodeValue - Status Code Value + + Returns: + None + +--*/ +{ + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + CodeType, + Value, + DevicePath + ); +} diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.h b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.h new file mode 100644 index 0000000000..575dfbea05 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/bot.h @@ -0,0 +1,78 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BOT.h + +Abstract: + +--*/ + +#ifndef _BOT_H +#define _BOT_H + + +#include + +#pragma pack(1) +// +// Bulk Only device protocol +// +typedef struct { + UINT32 dCBWSignature; + UINT32 dCBWTag; + UINT32 dCBWDataTransferLength; + UINT8 bmCBWFlags; + UINT8 bCBWLUN; + UINT8 bCBWCBLength; + UINT8 CBWCB[16]; +} CBW; + +typedef struct { + UINT32 dCSWSignature; + UINT32 dCSWTag; + UINT32 dCSWDataResidue; + UINT8 bCSWStatus; +} CSW; + +#pragma pack() + +#define USB_BOT_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('u', 'b', 'o', 't') + +typedef struct { + UINTN Signature; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_USB_ATAPI_PROTOCOL UsbAtapiProtocol; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR *BulkInEndpointDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR *BulkOutEndpointDescriptor; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} USB_BOT_DEVICE; + +#define USB_BOT_DEVICE_FROM_THIS(a) \ + CR(a, USB_BOT_DEVICE, UsbAtapiProtocol, USB_BOT_DEVICE_SIGNATURE) + +// +// Status code, see Usb Bot device spec +// +#define CSWSIG 0x53425355 +#define CBWSIG 0x43425355 + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gUsbBotDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gUsbBotComponentName; +extern EFI_GUID gUsbBotDriverGuid; + +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbBot/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/build.xml new file mode 100644 index 0000000000..aab054b222 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBot/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/ComponentName.c new file mode 100644 index 0000000000..347a0003f4 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/ComponentName.c @@ -0,0 +1,154 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "UsbBus.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +UsbBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UsbBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, OPTIONAL + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gUsbBusComponentName = { + UsbBusComponentNameGetDriverName, + UsbBusComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mUsbBusDriverNameTable[] = { + { "eng", (CHAR16 *) L"USB Bus Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +UsbBusComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gUsbBusComponentName.SupportedLanguages, + mUsbBusDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +UsbBusComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle, OPTIONAL + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.mbd b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.mbd new file mode 100644 index 0000000000..4e46c13f97 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.mbd @@ -0,0 +1,44 @@ + + + + + UsbBus + 240612B7-A063-11d4-9A3A-0090273FC14D + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkUsbLib + DxeMemoryAllocationLib + UefiDevicePathLib + + diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa new file mode 100644 index 0000000000..f035473c61 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/UsbBus.msa @@ -0,0 +1,76 @@ + + + + + UsbBus + DXE_DRIVER + BS_DRIVER + 240612B7-A063-11d4-9A3A-0090273FC14D + 0 + Component description file for UsbBus module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + EdkUsbLib + ReportStatusCodeLib + MemoryAllocationLib + UefiBootServicesTableLib + DevicePathLib + + + UsbBus.h + usbutil.h + hub.h + UsbBus.c + UsbIo.c + usb.c + usbutil.c + Hub.c + ComponentName.c + + + MdePkg + EdkModulePkg + + + UsbIo + UsbHc + DevicePath + + + + + + + gUsbBusDriverBinding + gUsbBusComponentName + + + diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/build.xml new file mode 100644 index 0000000000..508c7582b3 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.c new file mode 100644 index 0000000000..fd9e673b6c --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.c @@ -0,0 +1,507 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + + Hub.c + + Abstract: + + Usb Hub Request + + Revision History + +--*/ + +#include "usbbus.h" + +EFI_STATUS +HubGetPortStatus ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Port, + OUT UINT32 *PortStatus + ) +/*++ + + Routine Description: + Get a given hub port status + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL instance + Port - Usb hub port number (starting from 1). + PortStatus - Current Hub port status and change status. + + Returns: + EFI_SUCCESS + EFI_DEVICE + EFI_TIME_OUT + EFI_INVALID_PARAMETER + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + EFI_STATUS EfiStatus; + UINT32 UsbStatus; + UINT32 Timeout; + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Fill Device request packet + // + DevReq.RequestType = HUB_GET_PORT_STATUS_REQ_TYPE; + DevReq.Request = HUB_GET_PORT_STATUS; + DevReq.Value = 0; + DevReq.Index = Port; + DevReq.Length = sizeof (UINT32); + + Timeout = 3000; + + EfiStatus = UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + Timeout, + PortStatus, + sizeof (UINT32), + &UsbStatus + ); + + return EfiStatus; +} + +EFI_STATUS +HubSetPortFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Port, + IN UINT8 Value + ) +/*++ + + Routine Description: + Set specified feature to a give hub port + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL instance + Port - Usb hub port number (starting from 1). + Value - New feature value. + + Returns: + EFI_SUCCESS + EFI_DEVICE + EFI_TIME_OUT + EFI_INVALID_PARAMETER + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + EFI_STATUS EfiStatus; + UINT32 UsbStatus; + UINT32 Timeout; + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Fill Device request packet + // + DevReq.RequestType = HUB_SET_PORT_FEATURE_REQ_TYPE; + DevReq.Request = HUB_SET_PORT_FEATURE; + DevReq.Value = Value; + DevReq.Index = Port; + DevReq.Length = 0; + + Timeout = 3000; + EfiStatus = UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + Timeout, + NULL, + 0, + &UsbStatus + ); + + return EfiStatus; +} + +EFI_STATUS +HubClearPortFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Port, + IN UINT8 Value + ) +/*++ + + Routine Description: + Clear a specified feature of a given hub port + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL instance + Port - Usb hub port number (starting from 1). + Value - Feature value that will be cleared from + that hub port. + + Returns: + EFI_SUCCESS + EFI_DEVICE + EFI_TIME_OUT + EFI_INVALID_PARAMETER + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + EFI_STATUS EfiStatus; + UINT32 UsbStatus; + UINT32 Timeout; + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Fill Device request packet + // + DevReq.RequestType = HUB_CLEAR_FEATURE_PORT_REQ_TYPE; + DevReq.Request = HUB_CLEAR_FEATURE_PORT; + DevReq.Value = Value; + DevReq.Index = Port; + DevReq.Length = 0; + + Timeout = 3000; + EfiStatus = UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + Timeout, + NULL, + 0, + &UsbStatus + ); + + return EfiStatus; +} + +EFI_STATUS +HubGetHubStatus ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT UINT32 *HubStatus + ) +/*++ + + Routine Description: + Get Hub Status + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL instance + HubStatus - Current Hub status and change status. + + Returns: + EFI_SUCCESS + EFI_DEVICE + EFI_TIME_OUT + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + EFI_STATUS EfiStatus; + UINT32 UsbStatus; + UINT32 Timeout; + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Fill Device request packet + // + DevReq.RequestType = HUB_GET_HUB_STATUS_REQ_TYPE; + DevReq.Request = HUB_GET_HUB_STATUS; + DevReq.Value = 0; + DevReq.Index = 0; + DevReq.Length = sizeof (UINT32); + + Timeout = 3000; + EfiStatus = UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + Timeout, + HubStatus, + sizeof (UINT32), + &UsbStatus + ); + + return EfiStatus; +} + +EFI_STATUS +HubSetHubFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Value + ) +/*++ + + Routine Description: + Set a specified feature to the hub + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL instance + Value - Feature value that will be set to the hub. + + Returns: + EFI_SUCCESS + EFI_DEVICE + EFI_TIME_OUT + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + EFI_STATUS EfiStatus; + UINT32 UsbStatus; + UINT32 Timeout; + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Fill Device request packet + // + DevReq.RequestType = HUB_SET_HUB_FEATURE_REQ_TYPE; + DevReq.Request = HUB_SET_HUB_FEATURE; + DevReq.Value = Value; + DevReq.Index = 0; + DevReq.Length = 0; + + Timeout = 3000; + EfiStatus = UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + Timeout, + NULL, + 0, + &UsbStatus + ); + + return EfiStatus; +} + +EFI_STATUS +HubClearHubFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Value + ) +/*++ + + Routine Description: + Set a specified feature to the hub + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL instance + Value - Feature value that will be cleared from the hub. + + Returns: + EFI_SUCCESS + EFI_DEVICE + EFI_TIME_OUT + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + EFI_STATUS EfiStatus; + UINT32 UsbStatus; + UINT32 Timeout; + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Fill Device request packet + // + DevReq.RequestType = HUB_CLEAR_FEATURE_REQ_TYPE; + DevReq.Request = HUB_CLEAR_FEATURE; + DevReq.Value = Value; + DevReq.Index = 0; + DevReq.Length = 0; + + Timeout = 3000; + EfiStatus = UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + Timeout, + NULL, + 0, + &UsbStatus + ); + + return EfiStatus; + +} + +EFI_STATUS +GetHubDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINTN DescriptorSize, + OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor + ) +/*++ + + Routine Description: + Get the hub descriptor + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL instance + DescriptorSize - The length of Hub Descriptor buffer. + HubDescriptor - Caller allocated buffer to store the hub descriptor + if successfully returned. + + Returns: + EFI_SUCCESS + EFI_DEVICE + EFI_TIME_OUT + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + EFI_STATUS EfiStatus; + UINT32 UsbStatus; + UINT32 Timeout; + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Fill Device request packet + // + DevReq.RequestType = USB_RT_HUB | 0x80; + DevReq.Request = HUB_GET_DESCRIPTOR; + DevReq.Value = USB_DT_HUB << 8; + DevReq.Index = 0; + DevReq.Length = (UINT16) DescriptorSize; + + Timeout = 3000; + EfiStatus = UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + Timeout, + HubDescriptor, + (UINT16) DescriptorSize, + &UsbStatus + ); + + return EfiStatus; + +} + +EFI_STATUS +DoHubConfig ( + IN USB_IO_CONTROLLER_DEVICE *HubController + ) +/*++ + + Routine Description: + Configure the hub + + Arguments: + HubController - Indicating the hub controller device that + will be configured + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_HUB_DESCRIPTOR HubDescriptor; + EFI_STATUS Status; + EFI_USB_HUB_STATUS HubStatus; + UINTN Index; + UINT32 PortStatus; + + UsbIo = &HubController->UsbIo; + + ZeroMem (&HubDescriptor, sizeof (HubDescriptor)); + + // + // First get the hub descriptor length + // + Status = GetHubDescriptor (UsbIo, 2, &HubDescriptor); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // First get the whole descriptor, then + // get the number of hub ports + // + Status = GetHubDescriptor ( + UsbIo, + HubDescriptor.Length, + &HubDescriptor + ); + if (EFI_ERROR (Status)) { + DEBUG ((gUSBErrorLevel, "Get hub descriptor fail\n")); + return EFI_DEVICE_ERROR; + } + + HubController->DownstreamPorts = HubDescriptor.NbrPorts; + + Status = HubGetHubStatus (UsbIo, (UINT32 *) &HubStatus); + if (EFI_ERROR (Status)) { + DEBUG ((gUSBErrorLevel, "Get hub status fail when configure\n")); + return EFI_DEVICE_ERROR; + } + + // + // Get all hub ports status + // + for (Index = 0; Index < HubController->DownstreamPorts; Index++) { + + Status = HubGetPortStatus (UsbIo, (UINT8) (Index + 1), &PortStatus); + if (EFI_ERROR (Status)) { + continue; + } + } + // + // Power all the hub ports + // + for (Index = 0; Index < HubController->DownstreamPorts; Index++) { + Status = HubSetPortFeature ( + UsbIo, + (UINT8) (Index + 1), + EfiUsbPortPower + ); + if (EFI_ERROR (Status)) { + continue; + } + } + + // + // Clear Hub Status Change + // + Status = HubGetHubStatus (UsbIo, (UINT32 *) &HubStatus); + if (EFI_ERROR (Status)) { + DEBUG ((gUSBErrorLevel, "Get hub status fail\n")); + return EFI_DEVICE_ERROR; + } else { + // + // Hub power supply change happens + // + if (HubStatus.HubChange & HUB_CHANGE_LOCAL_POWER) { + HubClearHubFeature (UsbIo, C_HUB_LOCAL_POWER); + } + // + // Hub change overcurrent happens + // + if (HubStatus.HubChange & HUB_CHANGE_OVERCURRENT) { + HubClearHubFeature (UsbIo, C_HUB_OVER_CURRENT); + } + } + + return EFI_SUCCESS; + +} diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.h b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.h new file mode 100644 index 0000000000..4545d71c6a --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/hub.h @@ -0,0 +1,138 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + + Hub.h + + Abstract: + + Constants definitions for Usb Hub + + Revision History + +--*/ + +#ifndef _HUB_H +#define _HUB_H + +// +// Hub feature numbers +// +#define C_HUB_LOCAL_POWER 0 +#define C_HUB_OVER_CURRENT 1 + +// +// Hub class code & sub class code +// +#define CLASS_CODE_HUB 0x09 +#define SUB_CLASS_CODE_HUB 0 + +// +// Hub Status & Hub Change bit masks +// +#define HUB_STATUS_LOCAL_POWER 0x0001 +#define HUB_STATUS_OVERCURRENT 0x0002 + +#define HUB_CHANGE_LOCAL_POWER 0x0001 +#define HUB_CHANGE_OVERCURRENT 0x0002 + +// +// Hub Characteristics +// +#define HUB_CHAR_LPSM 0x0003 +#define HUB_CHAR_COMPOUND 0x0004 +#define HUB_CHAR_OCPM 0x0018 + +// +// Hub specific request +// +#define HUB_CLEAR_FEATURE 0x01 +#define HUB_CLEAR_FEATURE_REQ_TYPE 0x20 + +#define HUB_CLEAR_FEATURE_PORT 0x01 +#define HUB_CLEAR_FEATURE_PORT_REQ_TYPE 0x23 + +#define HUB_GET_BUS_STATE 0x02 +#define HUB_GET_BUS_STATE_REQ_TYPE 0xA3 + +#define HUB_GET_DESCRIPTOR 0x06 +#define HUB_GET_DESCRIPTOR_REQ_TYPE 0xA0 + +#define HUB_GET_HUB_STATUS 0x00 +#define HUB_GET_HUB_STATUS_REQ_TYPE 0xA0 + +#define HUB_GET_PORT_STATUS 0x00 +#define HUB_GET_PORT_STATUS_REQ_TYPE 0xA3 + +#define HUB_SET_DESCRIPTOR 0x07 +#define HUB_SET_DESCRIPTOR_REQ_TYPE 0x20 + +#define HUB_SET_HUB_FEATURE 0x03 +#define HUB_SET_HUB_FEATURE_REQ_TYPE 0x20 + +#define HUB_SET_PORT_FEATURE 0x03 +#define HUB_SET_PORT_FEATURE_REQ_TYPE 0x23 + +#pragma pack(1) +typedef struct usb_hub_status { + UINT16 HubStatus; + UINT16 HubChange; +} EFI_USB_HUB_STATUS; +#pragma pack() + +EFI_STATUS +HubGetPortStatus ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Port, + OUT UINT32 *PortStatus + ); + +EFI_STATUS +HubSetPortFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Port, + IN UINT8 Value + ); + +EFI_STATUS +HubSetHubFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Value + ); + +EFI_STATUS +HubGetHubStatus ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT UINT32 *HubStatus + ); + +EFI_STATUS +HubClearPortFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Port, + IN UINT8 Value + ); + +EFI_STATUS +HubClearHubFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Value + ); + +EFI_STATUS +GetHubDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINTN DescriptorSize, + OUT EFI_USB_HUB_DESCRIPTOR *HubDescriptor + ); + +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usb.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usb.c new file mode 100644 index 0000000000..474e38829e --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usb.c @@ -0,0 +1,825 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + + Usb.c + + Abstract: + + Parse usb device configurations. + + Revision History + +--*/ + +#include "usbbus.h" + +// +// Here are some internal helper functions +// +STATIC +EFI_STATUS +GetExpectedDescriptor ( + IN UINT8 *Buffer, + IN UINTN Length, + IN UINT8 DescType, + IN UINT8 DescLength, + OUT UINTN *ParsedBytes + ); + +STATIC +EFI_STATUS +ParseThisEndpoint ( + IN ENDPOINT_DESC_LIST_ENTRY *EndpointEntry, + IN UINT8 *Buffer, + IN UINTN BufferLength, + OUT UINTN *ParsedBytes + ); + +STATIC +EFI_STATUS +ParseThisInterface ( + IN INTERFACE_DESC_LIST_ENTRY *InterfaceEntry, + IN UINT8 *Buffer, + IN UINTN *BufferLen, + OUT UINTN *ParsedBytes + ); + +STATIC +EFI_STATUS +ParseThisConfig ( + IN CONFIG_DESC_LIST_ENTRY *ConfigDescEntry, + IN UINT8 *Buffer, + IN UINTN Length + ); + +// +// Implementations +// +BOOLEAN +IsHub ( + IN USB_IO_CONTROLLER_DEVICE *Dev + ) +/*++ + + Routine Description: + Tell if a usb controller is a hub controller. + + Arguments: + Dev - UsbIoController device structure. + + Returns: + TRUE/FALSE +--*/ +{ + EFI_USB_INTERFACE_DESCRIPTOR Interface; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + UINT8 Index; + + if (Dev == NULL) { + return FALSE; + } + + UsbIo = &Dev->UsbIo; + + UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &Interface + ); + + // + // Check classcode + // + if (Interface.InterfaceClass != 0x09) { + return FALSE; + } + + // + // Check protocol + // + if (Interface.InterfaceProtocol != 0x0) { + return FALSE; + } + + for (Index = 0; Index < Interface.NumEndpoints; Index++) { + UsbIo->UsbGetEndpointDescriptor ( + UsbIo, + Index, + &EndpointDescriptor + ); + + if ((EndpointDescriptor.EndpointAddress & 0x80) == 0) { + continue; + } + + if (EndpointDescriptor.Attributes != 0x03) { + continue; + } + + Dev->HubEndpointAddress = EndpointDescriptor.EndpointAddress; + return TRUE; + } + + return FALSE; +} + +EFI_STATUS +UsbGetStringtable ( + IN USB_IO_DEVICE *Dev + ) +/*++ + + Routine Description: + Get the string table stored in a usb device. + + Arguments: + Dev - UsbIoController device structure. + + Returns: + EFI_SUCCESS + EFI_UNSUPPORTED + EFI_OUT_OF_RESOURCES + +--*/ +{ + EFI_STATUS Result; + UINT32 Status; + EFI_USB_SUPPORTED_LANGUAGES *LanguageTable; + UINT8 *Buffer; + UINT8 *ptr; + UINTN Index; + UINTN LangTableSize; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT16 TempBuffer; + + UsbIo = &(Dev->UsbController[0]->UsbIo); + + // + // We get first 2 byte of langID table, + // so we can have the whole table length + // + Result = UsbGetString ( + UsbIo, + 0, + 0, + &TempBuffer, + 2, + &Status + ); + if (EFI_ERROR (Result)) { + return EFI_UNSUPPORTED; + } + + LanguageTable = (EFI_USB_SUPPORTED_LANGUAGES *) &TempBuffer; + + if (LanguageTable->Length == 0) { + return EFI_UNSUPPORTED; + } + // + // If length is 2, then there is no string table + // + if (LanguageTable->Length == 2) { + return EFI_UNSUPPORTED; + } + + Buffer = AllocateZeroPool (LanguageTable->Length); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Now we get the whole LangID table + // + Result = UsbGetString ( + UsbIo, + 0, + 0, + Buffer, + LanguageTable->Length, + &Status + ); + if (EFI_ERROR (Result)) { + gBS->FreePool (Buffer); + return EFI_UNSUPPORTED; + } + + LanguageTable = (EFI_USB_SUPPORTED_LANGUAGES *) Buffer; + + // + // ptr point to the LangID table + // + ptr = Buffer + 2; + LangTableSize = (LanguageTable->Length - 2) / 2; + + for (Index = 0; Index < LangTableSize && Index < USB_MAXLANID; Index++) { + Dev->LangID[Index] = *((UINT16 *) ptr); + ptr += 2; + } + + gBS->FreePool (Buffer); + LanguageTable = NULL; + + return EFI_SUCCESS; +} + + +EFI_STATUS +UsbGetAllConfigurations ( + IN USB_IO_DEVICE *UsbIoDevice + ) +/*++ + + Routine Description: + This function is to parse all the configuration descriptor. + + Arguments: + UsbIoDevice - USB_IO_DEVICE device structure. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_OUT_OF_RESOURCES + +--*/ +{ + EFI_STATUS Result; + UINT32 Status; + UINTN Index; + UINTN TotalLength; + UINT8 *Buffer; + CONFIG_DESC_LIST_ENTRY *ConfigDescEntry; + EFI_USB_IO_PROTOCOL *UsbIo; + + InitializeListHead (&UsbIoDevice->ConfigDescListHead); + UsbIo = &(UsbIoDevice->UsbController[0]->UsbIo); + + for (Index = 0; Index < UsbIoDevice->DeviceDescriptor.NumConfigurations; Index++) { + ConfigDescEntry = NULL; + + ConfigDescEntry = AllocateZeroPool (sizeof (CONFIG_DESC_LIST_ENTRY)); + if (ConfigDescEntry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // 1st only get 1st 4 bytes config descriptor, + // so we can know the whole length + // + Result = UsbGetDescriptor ( + UsbIo, + (UINT16) ((USB_DT_CONFIG << 8) | Index), + 0, + 4, + &ConfigDescEntry->CongfigDescriptor, + &Status + ); + if (EFI_ERROR (Result)) { + DEBUG ((gUSBErrorLevel, "First get config descriptor error\n")); + gBS->FreePool (ConfigDescEntry); + return EFI_DEVICE_ERROR; + } + + TotalLength = ConfigDescEntry->CongfigDescriptor.TotalLength; + + Buffer = AllocateZeroPool (TotalLength); + if (Buffer == NULL) { + gBS->FreePool (ConfigDescEntry); + return EFI_OUT_OF_RESOURCES; + } + // + // Then we get the total descriptors for this configuration + // + Result = UsbGetDescriptor ( + UsbIo, + (UINT16) ((USB_DT_CONFIG << 8) | Index), + 0, + (UINT16) TotalLength, + Buffer, + &Status + ); + if (EFI_ERROR (Result)) { + DEBUG ((gUSBErrorLevel, "Get whole config descriptor error\n")); + gBS->FreePool (ConfigDescEntry); + gBS->FreePool (Buffer); + return EFI_DEVICE_ERROR; + } + + InitializeListHead (&ConfigDescEntry->InterfaceDescListHead); + + // + // Parse this whole configuration + // + Result = ParseThisConfig (ConfigDescEntry, Buffer, TotalLength); + + if (EFI_ERROR (Result)) { + // + // Ignore this configuration, parse next one + // + gBS->FreePool (ConfigDescEntry); + gBS->FreePool (Buffer); + continue; + } + + InsertTailList (&UsbIoDevice->ConfigDescListHead, &ConfigDescEntry->Link); + + gBS->FreePool (Buffer); + + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetExpectedDescriptor ( + IN UINT8 *Buffer, + IN UINTN Length, + IN UINT8 DescType, + IN UINT8 DescLength, + OUT UINTN *ParsedBytes + ) +/*++ + + Routine Description: + Get the start position of next wanted descriptor. + + Arguments: + Buffer - Buffer to parse + Length - Buffer length + DescType - Descriptor type + DescLength - Descriptor length + ParsedBytes - Parsed Bytes to return + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + UINT16 DescriptorHeader; + UINT8 Len; + UINT8 *ptr; + UINTN Parsed; + + Parsed = 0; + ptr = Buffer; + + while (TRUE) { + // + // Buffer length should not less than Desc length + // + if (Length < DescLength) { + return EFI_DEVICE_ERROR; + } + // + // DescriptorHeader = *((UINT16 *)ptr), compatible with IPF + // + DescriptorHeader = (UINT16) ((*(ptr + 1) << 8) | *ptr); + + Len = ptr[0]; + + // + // Check to see if it is a start of expected descriptor + // + if (DescriptorHeader == ((DescType << 8) | DescLength)) { + break; + } + + if ((UINT8) (DescriptorHeader >> 8) == DescType) { + if (Len > DescLength) { + return EFI_DEVICE_ERROR; + } + } + // + // Descriptor length should be at least 2 + // and should not exceed the buffer length + // + if (Len < 2) { + return EFI_DEVICE_ERROR; + } + + if (Len > Length) { + return EFI_DEVICE_ERROR; + } + // + // Skip this mismatch descriptor + // + Length -= Len; + ptr += Len; + Parsed += Len; + } + + *ParsedBytes = Parsed; + + return EFI_SUCCESS; +} + + +STATIC +EFI_STATUS +ParseThisEndpoint ( + IN ENDPOINT_DESC_LIST_ENTRY *EndpointEntry, + IN UINT8 *Buffer, + IN UINTN BufferLength, + OUT UINTN *ParsedBytes + ) +/*++ + + Routine Description: + Get the start position of next wanted endpoint descriptor. + + Arguments: + EndpointEntry - ENDPOINT_DESC_LIST_ENTRY + Buffer - Buffer to parse + BufferLength - Buffer Length + ParsedBytes - Parsed Bytes to return + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + UINT8 *ptr; + EFI_STATUS Status; + UINTN SkipBytes; + + // + // Skip some data for this interface + // + Status = GetExpectedDescriptor ( + Buffer, + BufferLength, + USB_DT_ENDPOINT, + sizeof (EFI_USB_ENDPOINT_DESCRIPTOR), + &SkipBytes + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + ptr = Buffer + SkipBytes; + *ParsedBytes = SkipBytes; + + CopyMem ( + &EndpointEntry->EndpointDescriptor, + ptr, + sizeof (EFI_USB_ENDPOINT_DESCRIPTOR) + ); + + *ParsedBytes += sizeof (EFI_USB_ENDPOINT_DESCRIPTOR); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ParseThisInterface ( + IN INTERFACE_DESC_LIST_ENTRY *InterfaceEntry, + IN UINT8 *Buffer, + IN UINTN *BufferLen, + OUT UINTN *ParsedBytes + ) +/*++ + + Routine Description: + Get the start position of next wanted interface descriptor. + + Arguments: + InterfaceEntry - INTERFACE_DESC_LIST_ENTRY + Buffer - Buffer to parse + BufferLength - Buffer Length + ParsedBytes - Parsed Bytes to return + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + UINT8 *ptr; + UINTN SkipBytes; + UINTN Index; + UINTN Length; + UINTN Parsed; + ENDPOINT_DESC_LIST_ENTRY *EndpointEntry; + EFI_STATUS Status; + + Parsed = 0; + + // + // Skip some data for this interface + // + Status = GetExpectedDescriptor ( + Buffer, + *BufferLen, + USB_DT_INTERFACE, + sizeof (EFI_USB_INTERFACE_DESCRIPTOR), + &SkipBytes + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + ptr = Buffer + SkipBytes; + *ParsedBytes = SkipBytes; + + // + // Copy the interface descriptor + // + CopyMem ( + &InterfaceEntry->InterfaceDescriptor, + ptr, + sizeof (EFI_USB_INTERFACE_DESCRIPTOR) + ); + + ptr = Buffer + sizeof (EFI_USB_INTERFACE_DESCRIPTOR); + *ParsedBytes += sizeof (EFI_USB_INTERFACE_DESCRIPTOR); + + InitializeListHead (&InterfaceEntry->EndpointDescListHead); + + Length = *BufferLen - SkipBytes - sizeof (EFI_USB_INTERFACE_DESCRIPTOR); + + for (Index = 0; Index < InterfaceEntry->InterfaceDescriptor.NumEndpoints; Index++) { + EndpointEntry = AllocateZeroPool (sizeof (ENDPOINT_DESC_LIST_ENTRY)); + if (EndpointEntry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Parses all the endpoint descriptors within this interface. + // + Status = ParseThisEndpoint (EndpointEntry, ptr, Length, &Parsed); + + if (EFI_ERROR (Status)) { + gBS->FreePool (EndpointEntry); + return Status; + } + + InsertTailList ( + &InterfaceEntry->EndpointDescListHead, + &EndpointEntry->Link + ); + + Length -= Parsed; + ptr += Parsed; + *ParsedBytes += Parsed; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ParseThisConfig ( + IN CONFIG_DESC_LIST_ENTRY *ConfigDescEntry, + IN UINT8 *Buffer, + IN UINTN Length + ) +/*++ + + Routine Description: + Parse the current configuration descriptior. + + Arguments: + ConfigDescEntry - CONFIG_DESC_LIST_ENTRY + Buffer - Buffer to parse + Length - Buffer Length + + Returns + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + UINT8 *ptr; + UINT8 NumInterface; + UINTN Index; + INTERFACE_DESC_LIST_ENTRY *InterfaceEntry; + UINTN SkipBytes; + UINTN Parsed; + EFI_STATUS Status; + UINTN LengthLeft; + + Parsed = 0; + + // + // First skip the current config descriptor; + // + Status = GetExpectedDescriptor ( + Buffer, + Length, + USB_DT_CONFIG, + sizeof (EFI_USB_CONFIG_DESCRIPTOR), + &SkipBytes + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + ptr = Buffer + SkipBytes; + + CopyMem ( + &ConfigDescEntry->CongfigDescriptor, + ptr, + sizeof (EFI_USB_CONFIG_DESCRIPTOR) + ); + + NumInterface = ConfigDescEntry->CongfigDescriptor.NumInterfaces; + + // + // Skip size of Configuration Descriptor + // + ptr += sizeof (EFI_USB_CONFIG_DESCRIPTOR); + + LengthLeft = Length - SkipBytes - sizeof (EFI_USB_CONFIG_DESCRIPTOR); + + for (Index = 0; Index < NumInterface; Index++) { + // + // Parse all Interface + // + InterfaceEntry = AllocateZeroPool (sizeof (INTERFACE_DESC_LIST_ENTRY)); + if (InterfaceEntry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = ParseThisInterface (InterfaceEntry, ptr, &LengthLeft, &Parsed); + if (EFI_ERROR (Status)) { + gBS->FreePool (InterfaceEntry); + return Status; + } + + InsertTailList ( + &ConfigDescEntry->InterfaceDescListHead, + &InterfaceEntry->Link + ); + + // + // Parsed for next interface + // + LengthLeft -= Parsed; + ptr += Parsed; + } + // + // Parse for additional alt setting; + // + return EFI_SUCCESS; +} + +EFI_STATUS +UsbSetConfiguration ( + IN USB_IO_DEVICE *UsbIoDev, + IN UINTN ConfigurationValue + ) +/*++ + + Routine Description: + Set the device to a configuration value. + + Arguments: + UsbIoDev - USB_IO_DEVICE to be set configuration + ConfigrationValue - The configuration value to be set to that device + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + LIST_ENTRY *NextEntry; + CONFIG_DESC_LIST_ENTRY *ConfigEntry; + UINT32 Status; + EFI_STATUS Result; + EFI_USB_IO_PROTOCOL *UsbIo; + + UsbIo = &(UsbIoDev->UsbController[0]->UsbIo); + NextEntry = UsbIoDev->ConfigDescListHead.ForwardLink; + + while (NextEntry != &UsbIoDev->ConfigDescListHead) { + // + // Get one entry + // + ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) NextEntry; + if (ConfigEntry->CongfigDescriptor.ConfigurationValue == ConfigurationValue) { + // + // Find one, set to the active configuration + // + UsbIoDev->ActiveConfig = ConfigEntry; + break; + } + + NextEntry = NextEntry->ForwardLink; + } + // + // Next Entry should not be null + // + Result = UsbSetDeviceConfiguration ( + UsbIo, + (UINT16) ConfigurationValue, + &Status + ); + + return Result; +} + +EFI_STATUS +UsbSetDefaultConfiguration ( + IN USB_IO_DEVICE *UsbIoDev + ) +/*++ + + Routine Description: + Set the device to a default configuration value. + + Arguments: + UsbIoDev - USB_IO_DEVICE to be set configuration + + Returns + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + CONFIG_DESC_LIST_ENTRY *ConfigEntry; + UINT16 ConfigValue; + LIST_ENTRY *NextEntry; + + if (IsListEmpty (&UsbIoDev->ConfigDescListHead)) { + return EFI_DEVICE_ERROR; + } + + NextEntry = UsbIoDev->ConfigDescListHead.ForwardLink; + + ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) NextEntry; + ConfigValue = ConfigEntry->CongfigDescriptor.ConfigurationValue; + + return UsbSetConfiguration (UsbIoDev, ConfigValue); +} + +VOID +UsbDestroyAllConfiguration ( + IN USB_IO_DEVICE *UsbIoDevice + ) +/*++ + + Routine Description: + Delete all configuration data when device is not used. + + Arguments: + UsbIoDevice - USB_IO_DEVICE to be set configuration + + Returns: + N/A + +--*/ +{ + CONFIG_DESC_LIST_ENTRY *ConfigEntry; + INTERFACE_DESC_LIST_ENTRY *InterfaceEntry; + ENDPOINT_DESC_LIST_ENTRY *EndpointEntry; + LIST_ENTRY *NextEntry; + + // + // Delete all configuration descriptor data + // + ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) UsbIoDevice->ConfigDescListHead.ForwardLink; + + while (ConfigEntry != (CONFIG_DESC_LIST_ENTRY *) &UsbIoDevice->ConfigDescListHead) { + // + // Delete all its interface descriptors + // + InterfaceEntry = (INTERFACE_DESC_LIST_ENTRY *) ConfigEntry->InterfaceDescListHead.ForwardLink; + + while (InterfaceEntry != (INTERFACE_DESC_LIST_ENTRY *) &ConfigEntry->InterfaceDescListHead) { + // + // Delete all its endpoint descriptors + // + EndpointEntry = (ENDPOINT_DESC_LIST_ENTRY *) InterfaceEntry->EndpointDescListHead.ForwardLink; + while (EndpointEntry != (ENDPOINT_DESC_LIST_ENTRY *) &InterfaceEntry->EndpointDescListHead) { + NextEntry = ((LIST_ENTRY *) EndpointEntry)->ForwardLink; + RemoveEntryList ((LIST_ENTRY *) EndpointEntry); + gBS->FreePool (EndpointEntry); + EndpointEntry = (ENDPOINT_DESC_LIST_ENTRY *) NextEntry; + } + + NextEntry = ((LIST_ENTRY *) InterfaceEntry)->ForwardLink; + RemoveEntryList ((LIST_ENTRY *) InterfaceEntry); + gBS->FreePool (InterfaceEntry); + InterfaceEntry = (INTERFACE_DESC_LIST_ENTRY *) NextEntry; + } + + NextEntry = ((LIST_ENTRY *) ConfigEntry)->ForwardLink; + RemoveEntryList ((LIST_ENTRY *) ConfigEntry); + gBS->FreePool (ConfigEntry); + ConfigEntry = (CONFIG_DESC_LIST_ENTRY *) NextEntry; + } +} diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c new file mode 100644 index 0000000000..f4ac69e13f --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.c @@ -0,0 +1,2305 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + + UsbBus.c + + Abstract: + + USB Bus Driver + + Revision History + +--*/ + +#include "usbbus.h" + +//#ifdef EFI_DEBUG +UINTN gUSBDebugLevel = EFI_D_ERROR; +UINTN gUSBErrorLevel = EFI_D_ERROR; +//#endif +// +// The UsbBusProtocol is just used to locate USB_BUS_CONTROLLER +// structure in the UsbBusDriverControllerDriverStop(). Then we can +// Close all opened protocols and release this structure. +// +STATIC EFI_GUID mUsbBusProtocolGuid = EFI_USB_BUS_PROTOCOL_GUID; + + + +// +// EFI_DRIVER_BINDING_PROTOCOL Protocol Interface +// +EFI_STATUS +EFIAPI +UsbBusControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +UsbBusControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +UsbBusControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_DRIVER_BINDING_PROTOCOL gUsbBusDriverBinding = { + UsbBusControllerDriverSupported, + UsbBusControllerDriverStart, + UsbBusControllerDriverStop, + 0x10, + NULL, + NULL +}; + +// +// Internal use only +// +STATIC +EFI_STATUS +ReportUsbStatusCode ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusController, + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Code + ); + +// +// Supported function +// +VOID +InitializeUsbIoInstance ( + IN USB_IO_CONTROLLER_DEVICE *UsbIoController + ); + +STATIC +USB_IO_CONTROLLER_DEVICE * +CreateUsbIoControllerDevice ( + VOID + ); + +STATIC +EFI_STATUS +InitUsbIoController ( + IN USB_IO_CONTROLLER_DEVICE *UsbIoController + ); + +// +// USB Device Configuration / Deconfiguration +// +STATIC +EFI_STATUS +UsbDeviceConfiguration ( + IN USB_IO_CONTROLLER_DEVICE *ParentHubController, + IN EFI_HANDLE HostController, + IN UINT8 ParentPort, + IN USB_IO_DEVICE *UsbIoDevice + ); + +// +// Usb Bus enumeration function +// +STATIC +VOID +EFIAPI +UsbEnumeration ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +EFI_STATUS +ResetRootPort ( + IN EFI_USB_HC_PROTOCOL *UsbHCInterface, + IN UINT8 PortNum, + IN UINT8 RetryTimes + ); + +EFI_STATUS +ResetHubPort ( + IN USB_IO_CONTROLLER_DEVICE *UsbIoController, + IN UINT8 PortIndex + ); + +EFI_STATUS +ClearRootPortConnectionChangeStatus ( + IN UINT8 PortNum, + IN EFI_USB_HC_PROTOCOL *UsbHCInterface + ); + +STATIC +EFI_STATUS +ParentPortReset ( + IN USB_IO_CONTROLLER_DEVICE *UsbIoController, + IN BOOLEAN ReConfigure, + IN UINT8 RetryTimes + ); + +// +// Following are address allocate and free functions +// +STATIC +UINT8 +UsbAllocateAddress ( + IN UINT8 *AddressPool + ) +{ + UINT8 ByteIndex; + UINT8 BitIndex; + + for (ByteIndex = 0; ByteIndex < 16; ByteIndex++) { + for (BitIndex = 0; BitIndex < 8; BitIndex++) { + if ((AddressPool[ByteIndex] & (1 << BitIndex)) == 0) { + // + // Found one, covert to address, and mark it use + // + AddressPool[ByteIndex] |= (1 << BitIndex); + return (UINT8) (ByteIndex * 8 + BitIndex); + } + } + } + + return 0; + +} + +STATIC +VOID +UsbFreeAddress ( + IN UINT8 DevAddress, + IN UINT8 *AddressPool + ) +{ + UINT8 WhichByte; + UINT8 WhichBit; + // + // Locate the position + // + WhichByte = (UINT8) (DevAddress / 8); + WhichBit = (UINT8) (DevAddress & 0x7); + + AddressPool[WhichByte] &= (~(1 << WhichBit)); +} + +EFI_STATUS +EFIAPI +UsbBusControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + that has UsbHcProtocol installed will be supported. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_UNSUPPORTED - This driver does not support this device. + +--*/ +{ + EFI_STATUS OpenStatus; + + // + // Check whether USB Host Controller Protocol is already + // installed on this handle. If it is installed, we can start + // USB Bus Driver now. + // + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + + if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) { + return EFI_UNSUPPORTED; + } + + return OpenStatus; +} + + +EFI_STATUS +EFIAPI +UsbBusControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Starting the Usb Bus Driver + + Arguments: + + This - Protocol instance pointer. + Controller - Handle of device to test + RemainingDevicePath - Not used + + Returns: + + EFI_SUCCESS - This driver supports this device. + EFI_UNSUPPORTED - This driver does not support this device. + EFI_DEVICE_ERROR - This driver cannot be started due to device + Error + EFI_OUT_OF_RESOURCES- Can't allocate memory resources + EFI_ALREADY_STARTED - This driver has been started + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS OpenStatus; + USB_BUS_CONTROLLER_DEVICE *UsbBusDev; + USB_IO_DEVICE *RootHub; + USB_IO_CONTROLLER_DEVICE *RootHubController; + EFI_USB_HC_PROTOCOL *UsbHCInterface; + + // + // Allocate USB_BUS_CONTROLLER_DEVICE structure + // + UsbBusDev = NULL; + UsbBusDev = AllocateZeroPool (sizeof (USB_BUS_CONTROLLER_DEVICE)); + if (UsbBusDev == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + UsbBusDev->Signature = USB_BUS_DEVICE_SIGNATURE; + UsbBusDev->AddressPool[0] = 1; + + // + // Get the Device Path Protocol on Controller's handle + // + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &UsbBusDev->DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (OpenStatus)) { + gBS->FreePool (UsbBusDev); + return EFI_UNSUPPORTED; + } + // + // Locate the Host Controller Interface + // + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + (VOID **) &UsbHCInterface, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) { + + // + // Report Status Code here since we will reset the host controller + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_USB | EFI_IOB_EC_CONTROLLER_ERROR, + UsbBusDev->DevicePath + ); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (UsbBusDev); + return EFI_UNSUPPORTED; + } + + if (OpenStatus == EFI_ALREADY_STARTED) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (UsbBusDev); + return EFI_ALREADY_STARTED; + } + + UsbBusDev->UsbHCInterface = UsbHCInterface; + + // + // Attach EFI_USB_BUS_PROTOCOL to controller handle, + // for locate UsbBusDev later + // + Status = gBS->InstallProtocolInterface ( + &Controller, + &mUsbBusProtocolGuid, + EFI_NATIVE_INTERFACE, + &UsbBusDev->BusIdentify + ); + + if (EFI_ERROR (Status)) { + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (UsbBusDev); + return Status; + } + // + // Add root hub to the tree + // + RootHub = NULL; + RootHub = AllocateZeroPool (sizeof (USB_IO_DEVICE)); + if (RootHub == NULL) { + gBS->UninstallProtocolInterface ( + Controller, + &mUsbBusProtocolGuid, + &UsbBusDev->BusIdentify + ); + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (UsbBusDev); + return EFI_OUT_OF_RESOURCES; + } + + RootHub->BusController = UsbBusDev; + RootHub->DeviceAddress = UsbAllocateAddress (UsbBusDev->AddressPool); + + UsbBusDev->Root = RootHub; + + // + // Allocate Root Hub Controller + // + RootHubController = CreateUsbIoControllerDevice (); + if (RootHubController == NULL) { + gBS->UninstallProtocolInterface ( + Controller, + &mUsbBusProtocolGuid, + &UsbBusDev->BusIdentify + ); + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + gBS->FreePool (UsbBusDev); + gBS->FreePool (RootHub); + return EFI_OUT_OF_RESOURCES; + } + + UsbHCInterface->GetRootHubPortNumber ( + UsbHCInterface, + &RootHubController->DownstreamPorts + ); + RootHubController->UsbDevice = RootHub; + RootHubController->IsUsbHub = TRUE; + RootHubController->DevicePath = UsbBusDev->DevicePath; + RootHubController->HostController = Controller; + + RootHub->NumOfControllers = 1; + RootHub->UsbController[0] = RootHubController; + + // + // Report Status Code here since we will reset the host controller + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_IO_BUS_USB | EFI_IOB_PC_RESET, + UsbBusDev->DevicePath + ); + + // + // Reset USB Host Controller + // + UsbHCInterface->Reset ( + UsbHCInterface, + EFI_USB_HC_RESET_GLOBAL + ); + + // + // Report Status Code while we are going to bring up the Host Controller + // and start bus enumeration + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_IO_BUS_USB | EFI_IOB_PC_ENABLE, + UsbBusDev->DevicePath + ); + + // + // Start USB Host Controller + // + UsbHCInterface->SetState ( + UsbHCInterface, + EfiUsbHcStateOperational + ); + + // + // Create a timer to query root ports periodically + // + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + UsbEnumeration, + RootHubController, + &RootHubController->HubNotify + ); + if (EFI_ERROR (Status)) { + gBS->UninstallProtocolInterface ( + Controller, + &mUsbBusProtocolGuid, + &UsbBusDev->BusIdentify + ); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->FreePool (RootHubController); + gBS->FreePool (RootHub); + gBS->FreePool (UsbBusDev); + return EFI_UNSUPPORTED; + } + + // + // Before depending on the timer to check root ports periodically, + // here we should check them immediately for the first time, or + // there will be an interval between bus start and devices start. + // + gBS->SignalEvent (RootHubController->HubNotify); + + Status = gBS->SetTimer ( + RootHubController->HubNotify, + TimerPeriodic, + BUSPOLLING_PERIOD + ); + if (EFI_ERROR (Status)) { + gBS->UninstallProtocolInterface ( + Controller, + &mUsbBusProtocolGuid, + &UsbBusDev->BusIdentify + ); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseEvent (RootHubController->HubNotify); + gBS->FreePool (RootHubController); + gBS->FreePool (RootHub); + gBS->FreePool (UsbBusDev); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} +// +// Stop the bus controller +// +EFI_STATUS +EFIAPI +UsbBusControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + others + +--*/ +{ + EFI_STATUS Status; + USB_IO_DEVICE *Root; + USB_IO_CONTROLLER_DEVICE *RootHubController; + USB_BUS_CONTROLLER_DEVICE *UsbBusController; + EFI_USB_BUS_PROTOCOL *UsbIdentifier; + UINT8 Index2; + EFI_USB_HC_PROTOCOL *UsbHCInterface; + USB_IO_CONTROLLER_DEVICE *UsbController; + USB_IO_DEVICE *UsbIoDevice; + USB_IO_CONTROLLER_DEVICE *HubController; + UINTN Index; + EFI_USB_IO_PROTOCOL *UsbIo; + + if (NumberOfChildren > 0) { + + for (Index = 0; Index < NumberOfChildren; Index++) { + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + // + // We are here since the handle passed in does not support + // UsbIo protocol. There are several reasons that will cause + // this. + // For combo device such as keyboard, it may have 2 devices + // in one, namely, keyboard and mouse. If we deconfigure one + // of them, the other will be freed at the same time. This will + // cause the status error. But this is the correct behavior. + // For hub device, if we deconfigure hub first, the other chile + // device will be disconnected also, this will also provide us + // a status error. Now we will only report EFI_SUCCESS since Uhc + // driver will be disconnected at the second time.(pls see + // CoreDisconnectController for details) + // + continue; + } + + UsbController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (UsbIo); + UsbIoDevice = UsbController->UsbDevice; + HubController = UsbController->Parent; + UsbDeviceDeConfiguration (UsbIoDevice); + for (Index2 = 0; Index2 < HubController->DownstreamPorts; Index2++) { + if (HubController->Children[Index2] == UsbIoDevice) { + HubController->Children[Index2] = NULL; + } + } + } + + return EFI_SUCCESS; + } + // + // Get the USB_BUS_CONTROLLER_DEVICE + // + Status = gBS->OpenProtocol ( + Controller, + &mUsbBusProtocolGuid, + (VOID **) &UsbIdentifier, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + UsbBusController = USB_BUS_CONTROLLER_DEVICE_FROM_THIS (UsbIdentifier); + + // + // Stop USB Host Controller + // + UsbHCInterface = UsbBusController->UsbHCInterface; + + // + // Report Status Code here since we will reset the host controller + // + ReportUsbStatusCode ( + UsbBusController, + EFI_PROGRESS_CODE, + EFI_IO_BUS_USB | EFI_IOB_PC_RESET + ); + + UsbHCInterface->SetState ( + UsbHCInterface, + EfiUsbHcStateHalt + ); + + // + // Deconfiguration all its devices + // + Root = UsbBusController->Root; + RootHubController = Root->UsbController[0]; + + gBS->CloseEvent (RootHubController->HubNotify); + + for (Index2 = 0; Index2 < RootHubController->DownstreamPorts; Index2++) { + if (RootHubController->Children[Index2]) { + UsbDeviceDeConfiguration (RootHubController->Children[Index2]); + RootHubController->Children[Index2] = NULL; + } + } + + gBS->FreePool (RootHubController); + gBS->FreePool (Root); + + // + // Uninstall USB Bus Protocol + // + gBS->UninstallProtocolInterface ( + Controller, + &mUsbBusProtocolGuid, + &UsbBusController->BusIdentify + ); + + // + // Close USB_HC_PROTOCOL & DEVICE_PATH_PROTOCOL + // Opened by this Controller + // + gBS->CloseProtocol ( + Controller, + &gEfiUsbHcProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->FreePool (UsbBusController); + + return EFI_SUCCESS; +} +// +// USB Device Configuration +// +STATIC +EFI_STATUS +UsbDeviceConfiguration ( + IN USB_IO_CONTROLLER_DEVICE *ParentHubController, + IN EFI_HANDLE HostController, + IN UINT8 ParentPort, + IN USB_IO_DEVICE *UsbIoDevice + ) +/*++ + + Routine Description: + Configurate a new device attached to the usb bus + + Arguments: + ParentHubController - Parent Hub which this device is connected. + HostController - Host Controller handle + ParentPort - Parent Hub port which this device is connected. + UsbIoDevice - The device to be configured. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_OUT_OF_RESOURCES + +--*/ +{ + UINT8 DevAddress; + UINT8 Index; + EFI_STATUS Result; + UINT32 Status; + CHAR16 *StrManufacturer; + CHAR16 *StrProduct; + CHAR16 *StrSerialNumber; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 NumOfInterface; + USB_IO_CONTROLLER_DEVICE *FirstController; + USB_BUS_CONTROLLER_DEVICE *UsbBusDev; + USB_IO_CONTROLLER_DEVICE *UsbIoController; + + UsbBusDev = UsbIoDevice->BusController; + // + // Since a USB device must have at least on interface, + // so create this instance first + // + FirstController = CreateUsbIoControllerDevice (); + FirstController->UsbDevice = UsbIoDevice; + UsbIoDevice->UsbController[0] = FirstController; + FirstController->InterfaceNumber = 0; + FirstController->ParentPort = ParentPort; + FirstController->Parent = ParentHubController; + FirstController->HostController = HostController; + + InitializeUsbIoInstance (FirstController); + + DEBUG ((gUSBDebugLevel, "Configuration Usb Device at 0x%x...\n", ParentPort)); + + // + // Ensure we used the correctly USB I/O instance + // + UsbIo = &FirstController->UsbIo; + + // + // First retrieve the 1st 8 bytes of + // in order to get the MaxPacketSize for Endpoint 0 + // + for (Index = 0; Index < 3; Index++) { + + UsbIoDevice->DeviceDescriptor.MaxPacketSize0 = 8; + + ParentPortReset (FirstController, FALSE, Index); + + Result = UsbGetDescriptor ( + UsbIo, + (USB_DT_DEVICE << 8), + 0, + 8, + &UsbIoDevice->DeviceDescriptor, + &Status + ); + if (!EFI_ERROR (Result)) { + DEBUG ((gUSBDebugLevel, + "Get Device Descriptor Success, MaxPacketSize0 = 0x%x\n", + UsbIoDevice->DeviceDescriptor.MaxPacketSize0) + ); + break; + } + + } + + if (Index == 3) { + ReportUsbStatusCode ( + UsbBusDev, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR + ); + DEBUG ((gUSBErrorLevel, "Get Device Descriptor Fail when configing\n")); + gBS->FreePool (FirstController); + return EFI_DEVICE_ERROR; + } + + DevAddress = UsbAllocateAddress (UsbIoDevice->BusController->AddressPool); + if (DevAddress == 0) { + DEBUG ((gUSBErrorLevel, "Cannot allocate address\n")); + gBS->FreePool (FirstController); + return EFI_OUT_OF_RESOURCES; + } + + Result = UsbSetDeviceAddress (UsbIo, DevAddress, &Status); + + if (EFI_ERROR (Result)) { + DEBUG ((gUSBErrorLevel, "Set address error\n")); + ReportUsbStatusCode ( + UsbBusDev, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR + ); + + UsbFreeAddress ( + DevAddress, + UsbIoDevice->BusController->AddressPool + ); + + gBS->FreePool (FirstController); + return EFI_DEVICE_ERROR; + } + + UsbIoDevice->DeviceAddress = DevAddress; + + // + // Get the whole device descriptor + // + Result = UsbGetDescriptor ( + UsbIo, + (USB_DT_DEVICE << 8), + 0, + sizeof (EFI_USB_DEVICE_DESCRIPTOR), + &UsbIoDevice->DeviceDescriptor, + &Status + ); + + if (EFI_ERROR (Result)) { + DEBUG ((gUSBErrorLevel, "Get whole Device Descriptor error\n")); + ReportUsbStatusCode ( + UsbBusDev, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR + ); + UsbFreeAddress ( + DevAddress, + UsbIoDevice->BusController->AddressPool + ); + + gBS->FreePool (FirstController); + return EFI_DEVICE_ERROR; + } + // + // Get & parse all configurations for this device, including + // all configuration descriptors, all interface descriptors, all + // endpoint descriptors + // + Result = UsbGetAllConfigurations (UsbIoDevice); + + if (EFI_ERROR (Result)) { + DEBUG ((gUSBErrorLevel, "Failed to get device configuration\n")); + ReportUsbStatusCode ( + UsbBusDev, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_USB | EFI_IOB_EC_READ_ERROR + ); + UsbFreeAddress ( + DevAddress, + UsbIoDevice->BusController->AddressPool + ); + + gBS->FreePool (FirstController); + return EFI_DEVICE_ERROR; + } + // + // Set the 1st configuration value + // + Result = UsbSetDefaultConfiguration (UsbIoDevice); + if (EFI_ERROR (Result)) { + DEBUG ((gUSBErrorLevel, "Failed to set device configuration\n")); + ReportUsbStatusCode ( + UsbBusDev, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_USB | EFI_IOB_EC_WRITE_ERROR + ); + UsbFreeAddress ( + DevAddress, + UsbIoDevice->BusController->AddressPool + ); + + gBS->FreePool (FirstController); + return EFI_DEVICE_ERROR; + } + + UsbIoDevice->IsConfigured = TRUE; + + // + // Get all string table if applicable + // + Result = UsbGetStringtable (UsbIoDevice); + if (EFI_ERROR (Result)) { + DEBUG ((gUSBDebugLevel, "Device doesn't support string table\n")); + } else { + + StrManufacturer = NULL; + UsbIo->UsbGetStringDescriptor ( + UsbIo, + UsbIoDevice->LangID[0], + (UsbIoDevice->DeviceDescriptor).StrManufacturer, + &StrManufacturer + ); + + StrProduct = NULL; + UsbIo->UsbGetStringDescriptor ( + UsbIo, + UsbIoDevice->LangID[0], + (UsbIoDevice->DeviceDescriptor).StrProduct, + &StrProduct + ); + + StrSerialNumber = NULL; + UsbIo->UsbGetStringDescriptor ( + UsbIo, + UsbIoDevice->LangID[0], + (UsbIoDevice->DeviceDescriptor).StrSerialNumber, + &StrSerialNumber + ); + + if (StrManufacturer) { + gBS->FreePool (StrManufacturer); + } + + if (StrProduct) { + gBS->FreePool (StrProduct); + } + + if (StrSerialNumber) { + gBS->FreePool (StrSerialNumber); + } + } + // + // Create USB_IO_CONTROLLER_DEVICE for + // each detected interface + // + FirstController->CurrentConfigValue = + UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue; + + NumOfInterface = + UsbIoDevice->ActiveConfig->CongfigDescriptor.NumInterfaces; + UsbIoDevice->NumOfControllers = NumOfInterface; + + Result = InitUsbIoController (FirstController); + if (EFI_ERROR (Result)) { + ReportUsbStatusCode ( + UsbBusDev, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR + ); + gBS->FreePool (FirstController); + UsbIoDevice->UsbController[0] = NULL; + return EFI_DEVICE_ERROR; + } + + for (Index = 1; Index < NumOfInterface; Index++) { + UsbIoController = CreateUsbIoControllerDevice (); + UsbIoController->UsbDevice = UsbIoDevice; + UsbIoController->CurrentConfigValue = + UsbIoDevice->ActiveConfig->CongfigDescriptor.ConfigurationValue; + UsbIoController->InterfaceNumber = Index; + UsbIoDevice->UsbController[Index] = UsbIoController; + UsbIoController->ParentPort = ParentPort; + UsbIoController->Parent = ParentHubController; + UsbIoController->HostController = HostController; + + // + // First copy the USB_IO Protocol instance + // + CopyMem ( + &UsbIoController->UsbIo, + UsbIo, + sizeof (EFI_USB_IO_PROTOCOL) + ); + + Result = InitUsbIoController (UsbIoController); + if (EFI_ERROR (Result)) { + ReportUsbStatusCode ( + UsbBusDev, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_IO_BUS_USB | EFI_IOB_EC_INTERFACE_ERROR + ); + gBS->FreePool (UsbIoController); + UsbIoDevice->UsbController[Index] = NULL; + } + } + + return EFI_SUCCESS; +} +// +// USB Device DeConfiguration +// + +EFI_STATUS +UsbDeviceDeConfiguration ( + IN USB_IO_DEVICE *UsbIoDevice + ) +/*++ + + Routine Description: + Remove Device, Device Handles, Uninstall Protocols. + + Arguments: + UsbIoDevice - The device to be deconfigured. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + USB_IO_CONTROLLER_DEVICE *UsbController; + UINT8 index; + USB_IO_DEVICE *ChildDevice; + UINT8 Index; + EFI_USB_IO_PROTOCOL *UsbIo; + + DEBUG ((gUSBDebugLevel, "Enter Usb Device Deconfiguration\n")); + + // + // Double check UsbIoDevice exists + // + if (UsbIoDevice == NULL) { + return EFI_SUCCESS; + } + + for (index = 0; index < UsbIoDevice->NumOfControllers; index++) { + // + // Check if it is a hub, if so, de configuration all its + // downstream ports + // + UsbController = UsbIoDevice->UsbController[index]; + + // + // Check the controller pointer + // + if (UsbController == NULL) { + continue; + } + + if (UsbController->IsUsbHub) { + + DEBUG ((gUSBDebugLevel, "Hub Deconfig, First Deconfig its downstream ports\n")); + + // + // First Remove interrupt transfer request for the status + // change port + // + UsbIo = &UsbController->UsbIo; + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + UsbController->HubEndpointAddress, + FALSE, + 0, + 0, + NULL, + NULL + ); + + if (NULL != UsbController->HubNotify) { + gBS->CloseEvent (UsbController->HubNotify); + } + + for (Index = 0; Index < UsbController->DownstreamPorts; Index++) { + if (UsbController->Children[Index]) { + ChildDevice = UsbController->Children[Index]; + UsbDeviceDeConfiguration (ChildDevice); + UsbController->Children[Index] = NULL; + } + } + } + // + // If the controller is managed by a device driver, we need to + // disconnect them + // + if (UsbController->IsManagedByDriver) { + gBS->DisconnectController ( + UsbController->Handle, + NULL, + NULL + ); + } + + // + // remove child handle reference to the USB_HC_PROTOCOL + // + gBS->CloseProtocol ( + UsbController->HostController, + &gEfiUsbHcProtocolGuid, + gUsbBusDriverBinding.DriverBindingHandle, + UsbController->Handle + ); + + // + // Uninstall EFI_USB_IO_PROTOCOL & DEVICE_PATH_PROTOCOL + // installed on this handle + // + gBS->UninstallMultipleProtocolInterfaces ( + UsbController->Handle, + &gEfiDevicePathProtocolGuid, + UsbController->DevicePath, + &gEfiUsbIoProtocolGuid, + &UsbController->UsbIo, + NULL + ); + + if (UsbController->DevicePath != NULL) { + gBS->FreePool (UsbController->DevicePath); + } + + gBS->FreePool (UsbController); + UsbIoDevice->UsbController[index] = NULL; + } + // + // Free address for later use + // + UsbFreeAddress ( + UsbIoDevice->DeviceAddress, + UsbIoDevice->BusController->AddressPool + ); + + // + // Free all resouces allocated for all its configurations + // + UsbDestroyAllConfiguration (UsbIoDevice); + + if (UsbIoDevice) { + gBS->FreePool (UsbIoDevice); + UsbIoDevice = NULL; + } + + return EFI_SUCCESS; +} +// +// After interrupt complete, this function will be called, +// This function need to be well-defined later +// +STATIC +EFI_STATUS +EFIAPI +OnHubInterruptComplete ( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context, + IN UINT32 Result + ) +/*++ + + Routine Description: + Whenever hub interrupt occurs, this routine will be called to check + which event happens. + + Arguments: + Data - Hub interrupt transfer data. + DataLength - The length of the Data. + Context - Hub Controller Device. + Result - Hub interrupt transfer status. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + USB_IO_CONTROLLER_DEVICE *HubController; + UINT8 Index; + UINT8 *ptr; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT32 UsbResult; + BOOLEAN Disconnected; + EFI_STATUS Status; + + HubController = (USB_IO_CONTROLLER_DEVICE *) Context; + UsbIo = &HubController->UsbIo; + + // + // If something error in this interrupt transfer, + // + if (Result != EFI_USB_NOERROR) { + if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + UsbClearEndpointHalt ( + UsbIo, + HubController->HubEndpointAddress, + &UsbResult + ); + } + + // + // Delete & Submit this interrupt again + // + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + HubController->HubEndpointAddress, + FALSE, + 0, + 0, + NULL, + NULL + ); + + // + // try to detect if the hub itself was disconnected or not + // + Status = IsDeviceDisconnected ( + HubController, + &Disconnected + ); + + if (!EFI_ERROR (Status) && Disconnected == TRUE) { + DEBUG ((gUSBErrorLevel, "Hub is disconnected\n")); + return EFI_DEVICE_ERROR; + } + // + // Hub ports < 7 + // + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + HubController->HubEndpointAddress, + TRUE, + 100, + 1, + OnHubInterruptComplete, + HubController + ); + + return EFI_DEVICE_ERROR; + } + + if (DataLength == 0 || Data == NULL) { + return EFI_SUCCESS; + } + + // + // Scan which port has status change + // Bit 0 stands for hub itself, other bit stands for + // the corresponding port + // + for (Index = 0; Index < DataLength * 8; Index++) { + ptr = (UINT8 *) Data + Index / 8; + if ((*ptr) & (1 << (Index & 0x7))) { + HubController->StatusChangePort = Index; + break; + } + } + // + // Signal hub notify event + // + gBS->SignalEvent (HubController->HubNotify); + + return EFI_SUCCESS; +} +// +// USB Root Hub Enumerator +// +STATIC +VOID +EFIAPI +UsbEnumeration ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + + Routine Description: + This is USB enumerator + + Arguments: + Event - Indicating which event is signaled + Context - actually it is a USB_IO_DEVICE + + Returns: + EFI_SUCCESS + Others + +--*/ +{ + USB_IO_CONTROLLER_DEVICE *HubController; + EFI_USB_PORT_STATUS HubPortStatus; + EFI_STATUS Status; + UINT8 Index; + EFI_USB_HC_PROTOCOL *UsbHCInterface; + USB_IO_DEVICE *UsbIoDev; + USB_BUS_CONTROLLER_DEVICE *UsbBusDev; + EFI_HANDLE HostController; + USB_IO_DEVICE *OldUsbIoDevice; + USB_IO_DEVICE *NewDevice; + USB_IO_CONTROLLER_DEVICE *NewController; + UINT8 Index2; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 StatusChangePort; + + HubController = (USB_IO_CONTROLLER_DEVICE *) Context; + HostController = HubController->HostController; + UsbBusDev = HubController->UsbDevice->BusController; + + if (HubController->UsbDevice->DeviceAddress == 1) { + // + // Root hub has the address 1 + // + UsbIoDev = HubController->UsbDevice; + UsbHCInterface = UsbIoDev->BusController->UsbHCInterface; + + for (Index = 0; Index < HubController->DownstreamPorts; Index++) { + UsbHCInterface->GetRootHubPortStatus ( + UsbHCInterface, + Index, + (EFI_USB_PORT_STATUS *) &HubPortStatus + ); + + if (!IsPortConnectChange (HubPortStatus.PortChangeStatus)) { + continue; + } + // + // Clear root hub status change status + // + ClearRootPortConnectionChangeStatus ( + Index, + UsbHCInterface + ); + + gBS->Stall (100 * 1000); + + UsbHCInterface->GetRootHubPortStatus ( + UsbHCInterface, + Index, + (EFI_USB_PORT_STATUS *) &HubPortStatus + ); + + if (IsPortConnect (HubPortStatus.PortStatus)) { + + // + // There is something connected to this port + // + DEBUG ((gUSBDebugLevel, "Something attached from Root Hub in 0x%x\n", Index)); + + ReportUsbStatusCode ( + UsbBusDev, + EFI_PROGRESS_CODE, + EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG + ); + // + // if there is something physically detached, but still logically + // attached... + // + OldUsbIoDevice = HubController->Children[Index]; + + if (NULL != OldUsbIoDevice) { + UsbDeviceDeConfiguration (OldUsbIoDevice); + HubController->Children[Index] = NULL; + } + + NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE)); + if (NewDevice == NULL) { + return ; + } + // + // Initialize some fields by copying data from + // its parents + // + NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus); + + DEBUG ((gUSBDebugLevel, "DeviceSpeed 0x%x\n", NewDevice->IsSlowDevice)); + + NewDevice->BusController = UsbIoDev->BusController; + + // + // Configure that device + // + Status = UsbDeviceConfiguration ( + HubController, + HostController, + Index, + NewDevice + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (NewDevice); + return ; + } + // + // Add this device to the usb bus tree + // + HubController->Children[Index] = NewDevice; + + for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) { + // + // If this device is hub, add to the hub index + // + NewController = NewDevice->UsbController[Index2]; + + Status = gBS->ConnectController ( + NewController->Handle, + NULL, + NULL, + TRUE + ); + // + // If connect success, we need to disconnect when + // stop the controller, otherwise we need not call + // gBS->DisconnectController () + // This is used by those usb devices we don't plan + // to support. We can allocate + // controller handles for them, but we don't have + // device drivers to manage them. + // + NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status)); + + if (IsHub (NewController)) { + + NewController->IsUsbHub = TRUE; + + // + // Configure Hub Controller + // + Status = DoHubConfig (NewController); + if (EFI_ERROR (Status)) { + continue; + } + // + // Create an event to do hub enumeration + // + gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + UsbEnumeration, + NewController, + &NewController->HubNotify + ); + + // + // Add request to do query hub status + // change endpoint + // Hub ports < 7 + // + UsbIo = &NewController->UsbIo; + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + NewController->HubEndpointAddress, + TRUE, + 100, + 1, + OnHubInterruptComplete, + NewController + ); + + } + } + } else { + // + // Something disconnected from USB root hub + // + DEBUG ((gUSBDebugLevel, "Something deteached from Root Hub\n")); + + OldUsbIoDevice = HubController->Children[Index]; + + UsbDeviceDeConfiguration (OldUsbIoDevice); + + HubController->Children[Index] = NULL; + + UsbHCInterface->ClearRootHubPortFeature ( + UsbHCInterface, + Index, + EfiUsbPortEnableChange + ); + + UsbHCInterface->GetRootHubPortStatus ( + UsbHCInterface, + Index, + (EFI_USB_PORT_STATUS *) &HubPortStatus + ); + + } + } + + return ; + } else { + // + // Event from Hub, Get the hub controller handle + // + // + // Get the status change endpoint + // + StatusChangePort = HubController->StatusChangePort; + + // + // Clear HubController Status Change Bit + // + HubController->StatusChangePort = 0; + + if (StatusChangePort == 0) { + // + // Hub changes, we don't handle here + // + return ; + } + // + // Check which event took place at that port + // + UsbIo = &HubController->UsbIo; + Status = HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + + if (EFI_ERROR (Status)) { + return ; + } + // + // Clear some change status + // + if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) { + // + // Clear Hub port enable change + // + DEBUG ((gUSBDebugLevel, "Port Enable Change\n")); + HubClearPortFeature ( + UsbIo, + StatusChangePort, + EfiUsbPortEnableChange + ); + + HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + } + + if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) { + // + // Clear Hub reset change + // + DEBUG ((gUSBDebugLevel, "Port Reset Change\n")); + HubClearPortFeature ( + UsbIo, + StatusChangePort, + EfiUsbPortResetChange + ); + + HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + } + + if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_OVERCURRENT) { + // + // Clear Hub overcurrent change + // + DEBUG ((gUSBDebugLevel, "Port Overcurrent Change\n")); + HubClearPortFeature ( + UsbIo, + StatusChangePort, + EfiUsbPortOverCurrentChange + ); + + HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + } + + if (IsPortConnectChange (HubPortStatus.PortChangeStatus)) { + // + // First clear port connection change + // + DEBUG ((gUSBDebugLevel, "Port Connection Change\n")); + HubClearPortFeature ( + UsbIo, + StatusChangePort, + EfiUsbPortConnectChange + ); + + HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + + if (IsPortConnect (HubPortStatus.PortStatus)) { + + DEBUG ((gUSBDebugLevel, "New Device Connect on Hub port \n")); + + ReportUsbStatusCode ( + UsbBusDev, + EFI_PROGRESS_CODE, + EFI_IO_BUS_USB | EFI_IOB_PC_HOTPLUG + ); + + // + // if there is something physically detached, but still logically + // attached... + // + OldUsbIoDevice = HubController->Children[StatusChangePort - 1]; + + if (NULL != OldUsbIoDevice) { + UsbDeviceDeConfiguration (OldUsbIoDevice); + HubController->Children[StatusChangePort - 1] = NULL; + } + + NewDevice = AllocateZeroPool (sizeof (USB_IO_DEVICE)); + if (NewDevice == NULL) { + return ; + } + + ResetHubPort (HubController, StatusChangePort); + + HubGetPortStatus ( + UsbIo, + StatusChangePort, + (UINT32 *) &HubPortStatus + ); + + // + // Initialize some fields + // + NewDevice->IsSlowDevice = IsPortLowSpeedDeviceAttached (HubPortStatus.PortStatus); + + NewDevice->BusController = HubController->UsbDevice->BusController; + + // + // Configure that device + // + Status = UsbDeviceConfiguration ( + HubController, + HostController, + (UINT8) (StatusChangePort - 1), + NewDevice + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (NewDevice); + return ; + } + // + // Add this device to the usb bus tree + // StatusChangePort is begin from 1, + // + HubController->Children[StatusChangePort - 1] = NewDevice; + + for (Index2 = 0; Index2 < NewDevice->NumOfControllers; Index2++) { + // + // If this device is hub, add to the hub index + // + NewController = NewDevice->UsbController[Index2]; + + // + // Connect the controller to the driver image + // + Status = gBS->ConnectController ( + NewController->Handle, + NULL, + NULL, + TRUE + ); + // + // If connect success, we need to disconnect when + // stop the controller, otherwise we need not call + // gBS->DisconnectController () + // This is used by those usb devices we don't plan + // to support. We can allocate + // controller handles for them, but we don't have + // device drivers to manage them. + // + NewController->IsManagedByDriver = (BOOLEAN) (!EFI_ERROR (Status)); + + // + // If this device is hub, add to the hub index + // + if (IsHub (NewController)) { + + NewController->IsUsbHub = TRUE; + + // + // Configure Hub + // + Status = DoHubConfig (NewController); + + if (EFI_ERROR (Status)) { + continue; + } + // + // Create an event to do hub enumeration + // + gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + UsbEnumeration, + NewController, + &NewController->HubNotify + ); + + // + // Add request to do query hub status + // change endpoint + // + UsbIo = &NewController->UsbIo; + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + NewController->HubEndpointAddress, // Hub endpoint address + TRUE, + 100, + 1, // Hub ports < 7 + OnHubInterruptComplete, + NewController + ); + } + } + } else { + // + // Something disconnected from USB hub + // + DEBUG ((gUSBDebugLevel, "Something Device Detached on Hub port\n")); + + OldUsbIoDevice = HubController->Children[StatusChangePort - 1]; + + UsbDeviceDeConfiguration (OldUsbIoDevice); + + HubController->Children[StatusChangePort - 1] = NULL; + + } + + return ; + } + + return ; + } +} +// +// Clear port connection change status over a given root hub port +// +EFI_STATUS +ClearRootPortConnectionChangeStatus ( + UINT8 PortNum, + EFI_USB_HC_PROTOCOL *UsbHCInterface + ) +/*++ + + Routine Description: + Clear port connection change status over a given root hub port + + Arguments: + PortNum - The given port. + UsbHCInterface - The EFI_USB_HC_PROTOCOL instance. + + Returns: + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + Status = UsbHCInterface->ClearRootHubPortFeature ( + UsbHCInterface, + PortNum, + EfiUsbPortConnectChange + ); + return Status; +} + +STATIC +USB_IO_CONTROLLER_DEVICE * +CreateUsbIoControllerDevice ( + VOID + ) +/*++ + + Routine Description: + Allocate a structure for USB_IO_CONTROLLER_DEVICE + + Arguments: + N/A + + Returns: + A pointer to a USB_IO_CONTROLLER_DEVICE structure, + Or NULL. + +--*/ +{ + USB_IO_CONTROLLER_DEVICE *UsbIoControllerDev; + + // + // Allocate USB_IO_CONTROLLER_DEVICE structure + // + UsbIoControllerDev = NULL; + UsbIoControllerDev = AllocateZeroPool (sizeof (USB_IO_CONTROLLER_DEVICE)); + + if (UsbIoControllerDev == NULL) { + return NULL; + } + + UsbIoControllerDev->Signature = USB_IO_CONTROLLER_SIGNATURE; + + return UsbIoControllerDev; +} + +STATIC +EFI_STATUS +InitUsbIoController ( + IN USB_IO_CONTROLLER_DEVICE *UsbIoController + ) +/*++ + + Routine Description: + Init and install EFI_USB_IO_PROTOCOL onto that controller. + + Arguments: + UsbIoController - The Controller to be operated. + + Returns: + EFI_SUCCESS + Others + +--*/ +{ + USB_DEVICE_PATH UsbNode; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_USB_HC_PROTOCOL *UsbHcProtocol; + + // + // Build the child device path for each new USB_IO device + // + ZeroMem (&UsbNode, sizeof (UsbNode)); + UsbNode.Header.Type = MESSAGING_DEVICE_PATH; + UsbNode.Header.SubType = MSG_USB_DP; + SetDevicePathNodeLength (&UsbNode.Header, sizeof (UsbNode)); + UsbNode.InterfaceNumber = UsbIoController->InterfaceNumber; + UsbNode.ParentPortNumber = UsbIoController->ParentPort; + ParentDevicePath = UsbIoController->Parent->DevicePath; + + UsbIoController->DevicePath = + AppendDevicePathNode (ParentDevicePath, &UsbNode.Header); + if (UsbIoController->DevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->InstallMultipleProtocolInterfaces ( + &UsbIoController->Handle, + &gEfiDevicePathProtocolGuid, + UsbIoController->DevicePath, + &gEfiUsbIoProtocolGuid, + &UsbIoController->UsbIo, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + UsbIoController->HostController, + &gEfiUsbHcProtocolGuid, + (VOID **) &UsbHcProtocol, + gUsbBusDriverBinding.DriverBindingHandle, + UsbIoController->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + + return Status; +} + +STATIC +EFI_STATUS +ParentPortReset ( + IN USB_IO_CONTROLLER_DEVICE *UsbIoController, + IN BOOLEAN ReConfigure, + IN UINT8 RetryTimes + ) +/*++ + + Routine Description: + Reset parent hub port to which this device is connected. + + Arguments: + UsbIoController - Indicating the Usb Controller Device. + Reconfigure - Do we need to reconfigure it. + RetryTimes - Retry Times when failed + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + USB_IO_DEVICE *ParentIoDev; + USB_IO_DEVICE *UsbIoDev; + USB_IO_CONTROLLER_DEVICE *ParentController; + UINT8 HubPort; + UINT32 Status; + EFI_STATUS Result; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 Address; + + ParentController = UsbIoController->Parent; + ParentIoDev = ParentController->UsbDevice; + UsbIoDev = UsbIoController->UsbDevice; + HubPort = UsbIoController->ParentPort; + + gBS->Stall (100 * 1000); + + if (ParentIoDev->DeviceAddress == 1) { + DEBUG ((gUSBDebugLevel, "Reset from Root Hub 0x%x\n", HubPort)); + ResetRootPort (ParentIoDev->BusController->UsbHCInterface, HubPort, RetryTimes); + } else { + DEBUG ((gUSBDebugLevel, "Reset from Hub, Addr 0x%x\n", ParentIoDev->DeviceAddress)); + ResetHubPort (ParentController, HubPort + 1); + } + // + // If we only need port reset, just return + // + if (!ReConfigure) { + return EFI_SUCCESS; + } + // + // Re-config that USB device + // + UsbIo = &UsbIoController->UsbIo; + + // + // Assign a unique address to this device + // + Address = UsbIoDev->DeviceAddress; + UsbIoDev->DeviceAddress = 0; + + Result = UsbSetDeviceAddress (UsbIo, Address, &Status); + UsbIoDev->DeviceAddress = Address; + + if (EFI_ERROR (Result)) { + return EFI_DEVICE_ERROR; + } + // + // Set the device to the default configuration + // + Result = UsbSetDefaultConfiguration (UsbIoDev); + if (EFI_ERROR (Result)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +UsbPortReset ( + IN EFI_USB_IO_PROTOCOL *This + ) +/*++ + + Routine Description: + Resets and reconfigures the USB controller. This function will + work for all USB devices except USB Hub Controllers. + + Arguments: + This - Indicates the calling context. + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + EFI_DEVICE_ERROR + +--*/ +{ + USB_IO_CONTROLLER_DEVICE *UsbIoController; + EFI_STATUS Status; + + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + + // + // Since at this time, this device has already been configured, + // it needs to be re-configured. + // + Status = ParentPortReset (UsbIoController, TRUE, 0); + + return Status; +} + +EFI_STATUS +ResetRootPort ( + IN EFI_USB_HC_PROTOCOL *UsbHCInterface, + IN UINT8 PortNum, + IN UINT8 RetryTimes + ) +/*++ + + Routine Description: + Reset Root Hub port. + + Arguments: + UsbHCInterface - The EFI_USB_HC_PROTOCOL instance. + PortNum - The given port to be reset. + RetryTimes - RetryTimes when failed + Returns: + N/A + +--*/ +{ + EFI_STATUS Status; + + // + // reset root port + // + Status = UsbHCInterface->SetRootHubPortFeature ( + UsbHCInterface, + PortNum, + EfiUsbPortReset + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + gBS->Stall (50 * 1000); + + // + // clear reset root port + // + Status = UsbHCInterface->ClearRootHubPortFeature ( + UsbHCInterface, + PortNum, + EfiUsbPortReset + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + gBS->Stall (1000); + + Status = ClearRootPortConnectionChangeStatus (PortNum, UsbHCInterface); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Set port enable + // + Status = UsbHCInterface->SetRootHubPortFeature ( + UsbHCInterface, + PortNum, + EfiUsbPortEnable + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = UsbHCInterface->ClearRootHubPortFeature ( + UsbHCInterface, + PortNum, + EfiUsbPortEnableChange + ); + gBS->Stall ((1 + RetryTimes) * 50 * 1000); + + return EFI_SUCCESS; +} + + +EFI_STATUS +ResetHubPort ( + IN USB_IO_CONTROLLER_DEVICE *UsbIoController, + IN UINT8 PortIndex + ) +/*++ + + Routine Description: + Reset Hub port. + + Arguments: + UsbIoController - The USB_IO_CONTROLLER_DEVICE instance. + PortIndex - The given port to be reset. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_PORT_STATUS HubPortStatus; + UINT8 Number; + + ASSERT (UsbIoController->IsUsbHub == TRUE); + + UsbIo = &UsbIoController->UsbIo; + + HubSetPortFeature ( + UsbIo, + PortIndex, + EfiUsbPortReset + ); + + gBS->Stall (10 * 1000); + + // + // Wait for port reset complete + // + Number = 10; + do { + HubGetPortStatus ( + UsbIo, + PortIndex, + (UINT32 *) &HubPortStatus + ); + gBS->Stall (10 * 100); + Number -= 1; + } while ((HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) == 0 && Number > 0); + + if (Number == 0) { + // + // Cannot reset port, return error + // + return EFI_DEVICE_ERROR; + } + + gBS->Stall (1000); + + HubGetPortStatus ( + UsbIo, + PortIndex, + (UINT32 *) &HubPortStatus + ); + // + // reset port will cause some bits change, clear them + // + if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_ENABLE) { + DEBUG ((gUSBDebugLevel, "Port Enable Change\n")); + HubClearPortFeature ( + UsbIo, + PortIndex, + EfiUsbPortEnableChange + ); + } + + if (HubPortStatus.PortChangeStatus & USB_PORT_STAT_C_RESET) { + DEBUG ((gUSBDebugLevel, "Port Reset Change\n")); + HubClearPortFeature ( + UsbIo, + PortIndex, + EfiUsbPortResetChange + ); + } + + return EFI_SUCCESS; +} + + + + + +STATIC +EFI_STATUS +ReportUsbStatusCode ( + IN USB_BUS_CONTROLLER_DEVICE *UsbBusController, + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Code + ) +/*++ + +Routine Description: + + report a error Status code of USB bus driver controller + + Arguments: + UsbBusController - USB_BUS_CONTROLLER_DEVICE + Type - EFI_STATUS_CODE_TYPE + Code - EFI_STATUS_CODE_VALUE + Returns: + + None + +--*/ +{ + return REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + Type, + Code, + UsbBusController->DevicePath + ); +} + + +EFI_STATUS +IsDeviceDisconnected ( + IN USB_IO_CONTROLLER_DEVICE *UsbIoController, + IN OUT BOOLEAN *Disconnected + ) +/*++ + + Routine Description: + Reset if the device is disconencted or not + + Arguments: + UsbIoController - Indicating the Usb Controller Device. + Disconnected - Indicate whether the device is disconencted or not + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + USB_IO_DEVICE *ParentIoDev; + USB_IO_DEVICE *UsbIoDev; + USB_IO_CONTROLLER_DEVICE *ParentController; + UINT8 HubPort; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_PORT_STATUS PortStatus; + EFI_USB_HC_PROTOCOL *UsbHCInterface; + + ParentController = UsbIoController->Parent; + ParentIoDev = ParentController->UsbDevice; + UsbIoDev = UsbIoController->UsbDevice; + HubPort = UsbIoController->ParentPort; + + if (ParentIoDev->DeviceAddress == 1) { + // + // Connected to the root hub + // + UsbHCInterface = ParentIoDev->BusController->UsbHCInterface; + Status = UsbHCInterface->GetRootHubPortStatus ( + UsbHCInterface, + HubPort, + &PortStatus + ); + + } else { + UsbIo = &UsbIoController->UsbIo; + Status = HubGetPortStatus ( + &ParentController->UsbIo, + HubPort + 1, + (UINT32 *) &PortStatus + ); + + if (EFI_ERROR (Status)) { + return IsDeviceDisconnected (ParentController, Disconnected); + } + } + + *Disconnected = FALSE; + + if (!IsPortConnect (PortStatus.PortStatus)) { + *Disconnected = TRUE; + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h new file mode 100644 index 0000000000..b32620342c --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbbus.h @@ -0,0 +1,261 @@ +/*++ +Copyright (c) 2006, 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. + + Module Name: + + usbbus.h + + Abstract: + + Header file for USB bus driver Interface + + Revision History + + + +--*/ + +#ifndef _EFI_USB_BUS_H +#define _EFI_USB_BUS_H + + +#include +#include "Hub.h" +#include "Usbutil.h" + +//#ifdef EFI_DEBUG +extern UINTN gUSBDebugLevel; +extern UINTN gUSBErrorLevel; +//#endif + +#define MICROSECOND 10000 +#define ONESECOND (1000 * MICROSECOND) +#define BUSPOLLING_PERIOD ONESECOND +// +// We define some maximun value here +// +#define USB_MAXCONFIG 8 +#define USB_MAXALTSETTING 4 +#define USB_MAXINTERFACES 32 +#define USB_MAXENDPOINTS 16 +#define USB_MAXSTRINGS 16 +#define USB_MAXLANID 16 +#define USB_MAXCHILDREN 8 +#define USB_MAXCONTROLLERS 4 + +#define USB_IO_CONTROLLER_SIGNATURE EFI_SIGNATURE_32 ('u', 's', 'b', 'd') + +typedef struct { + LIST_ENTRY Link; + UINT16 StringIndex; + CHAR16 *String; +} STR_LIST_ENTRY; + +typedef struct { + LIST_ENTRY Link; + UINT16 Toggle; + EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; +} ENDPOINT_DESC_LIST_ENTRY; + +typedef struct { + LIST_ENTRY Link; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + LIST_ENTRY EndpointDescListHead; +} INTERFACE_DESC_LIST_ENTRY; + +typedef struct { + LIST_ENTRY Link; + EFI_USB_CONFIG_DESCRIPTOR CongfigDescriptor; + LIST_ENTRY InterfaceDescListHead; + UINTN ActiveInterface; +} CONFIG_DESC_LIST_ENTRY; + +// +// Forward declaring +// +struct usb_io_device; + +// +// This is used to form the USB Controller Handle +// +typedef struct usb_io_controller_device { + UINTN Signature; + EFI_HANDLE Handle; + EFI_USB_IO_PROTOCOL UsbIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_HANDLE HostController; + UINT8 CurrentConfigValue; + UINT8 InterfaceNumber; + struct usb_io_device *UsbDevice; + + BOOLEAN IsUsbHub; + BOOLEAN IsManagedByDriver; + + // + // Fields specified for USB Hub + // + EFI_EVENT HubNotify; + UINT8 HubEndpointAddress; + UINT8 StatusChangePort; + UINT8 DownstreamPorts; + + UINT8 ParentPort; + struct usb_io_controller_device *Parent; + struct usb_io_device *Children[USB_MAXCHILDREN]; +} USB_IO_CONTROLLER_DEVICE; + +#define USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS(a) \ + CR(a, USB_IO_CONTROLLER_DEVICE, UsbIo, USB_IO_CONTROLLER_SIGNATURE) + +// +// This is used to keep the topology of USB bus +// +struct _usb_bus_controller_device; + +typedef struct usb_io_device { + UINT8 DeviceAddress; + BOOLEAN IsConfigured; + BOOLEAN IsSlowDevice; + EFI_USB_DEVICE_DESCRIPTOR DeviceDescriptor; + LIST_ENTRY ConfigDescListHead; + CONFIG_DESC_LIST_ENTRY *ActiveConfig; + UINT16 LangID[USB_MAXLANID]; + + struct _usb_bus_controller_device *BusController; + + // + // Track the controller handle + // + UINT8 NumOfControllers; + USB_IO_CONTROLLER_DEVICE *UsbController[USB_MAXCONTROLLERS]; + +} USB_IO_DEVICE; + +// +// Usb Bus Controller device strcuture +// +#define EFI_USB_BUS_PROTOCOL_GUID \ + { 0x2B2F68CC, 0x0CD2, 0x44cf, { 0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 } } + +typedef struct _EFI_USB_BUS_PROTOCOL { + UINT64 Reserved; +} EFI_USB_BUS_PROTOCOL; + +#define USB_BUS_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('u', 'b', 'u', 's') + +typedef struct _usb_bus_controller_device { + UINTN Signature; + + EFI_USB_BUS_PROTOCOL BusIdentify; + EFI_USB_HC_PROTOCOL *UsbHCInterface; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINT8 AddressPool[16]; + USB_IO_DEVICE *Root; +} USB_BUS_CONTROLLER_DEVICE; + +#define USB_BUS_CONTROLLER_DEVICE_FROM_THIS(a) \ + CR(a, USB_BUS_CONTROLLER_DEVICE, BusIdentify, USB_BUS_DEVICE_SIGNATURE) + + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gUsbBusDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gUsbBusComponentName; +extern EFI_GUID gUSBBusDriverGuid; + +// +// Usb Device Configuration functions +// +BOOLEAN +IsHub ( + IN USB_IO_CONTROLLER_DEVICE *Dev + ); + +EFI_STATUS +UsbGetStringtable ( + IN USB_IO_DEVICE *UsbIoDevice + ); + +EFI_STATUS +UsbGetAllConfigurations ( + IN USB_IO_DEVICE *UsbIoDevice + ); + +EFI_STATUS +UsbSetConfiguration ( + IN USB_IO_DEVICE *Dev, + IN UINTN ConfigurationValue + ); + +EFI_STATUS +UsbSetDefaultConfiguration ( + IN USB_IO_DEVICE *Dev + ); + +// +// Device Deconfiguration functions +// +VOID +UsbDestroyAllConfiguration ( + IN USB_IO_DEVICE *UsbIoDevice + ); + +EFI_STATUS +DoHubConfig ( + IN USB_IO_CONTROLLER_DEVICE *HubIoDevice + ); + +VOID +GetDeviceEndPointMaxPacketLength ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 EndpointAddr, + OUT UINT8 *MaxPacketLength + ); + +VOID +GetDataToggleBit ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 EndpointAddr, + OUT UINT8 *DataToggle + ); + +VOID +SetDataToggleBit ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 EndpointAddr, + IN UINT8 DataToggle + ); + +INTERFACE_DESC_LIST_ENTRY * +FindInterfaceListEntry ( + IN EFI_USB_IO_PROTOCOL *This + ); + +ENDPOINT_DESC_LIST_ENTRY * +FindEndPointListEntry ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 EndPointAddress + ); + + +EFI_STATUS +IsDeviceDisconnected ( + IN USB_IO_CONTROLLER_DEVICE *UsbIoController, + IN OUT BOOLEAN *Disconnected + ); + +EFI_STATUS +UsbDeviceDeConfiguration ( + IN USB_IO_DEVICE *UsbIoDevice + ); + + +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c new file mode 100644 index 0000000000..bd87c5ca2e --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbio.c @@ -0,0 +1,1176 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + + UsbIo.c + + Abstract: + + USB I/O Abstraction Driver + + Revision History + +--*/ + +#include "usbbus.h" + +// +// USB I/O Support Function Prototypes +// +STATIC +EFI_STATUS +EFIAPI +UsbControlTransfer ( + IN EFI_USB_IO_PROTOCOL *This, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT32 Timeout, + IN OUT VOID *Data, OPTIONAL + IN UINTN DataLength, OPTIONAL + OUT UINT32 *Status + ); + +STATIC +EFI_STATUS +EFIAPI +UsbBulkTransfer ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout, + OUT UINT32 *Status + ); + +STATIC +EFI_STATUS +EFIAPI +UsbAsyncInterruptTransfer ( + IN EFI_USB_IO_PROTOCOL * This, + IN UINT8 DeviceEndpoint, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval, OPTIONAL + IN UINTN DataLength, OPTIONAL + IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack, OPTIONAL + IN VOID *Context OPTIONAL + ); + +STATIC +EFI_STATUS +EFIAPI +UsbSyncInterruptTransfer ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout, + OUT UINT32 *Status + ); + +STATIC +EFI_STATUS +EFIAPI +UsbIsochronousTransfer ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN UINTN DataLength, + OUT UINT32 *Status + ); + +STATIC +EFI_STATUS +EFIAPI +UsbAsyncIsochronousTransfer ( + IN EFI_USB_IO_PROTOCOL * This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ); + +extern +EFI_STATUS +EFIAPI +UsbPortReset ( + IN EFI_USB_IO_PROTOCOL *This + ); + +STATIC +EFI_STATUS +EFIAPI +UsbGetDeviceDescriptor ( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_DEVICE_DESCRIPTOR *DeviceDescriptor + ); + +STATIC +EFI_STATUS +EFIAPI +UsbGetActiveConfigDescriptor ( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_CONFIG_DESCRIPTOR *ConfigurationDescriptor + ); + +STATIC +EFI_STATUS +EFIAPI +UsbGetInterfaceDescriptor ( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor + ); + +STATIC +EFI_STATUS +EFIAPI +UsbGetEndpointDescriptor ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + OUT EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor + ); + +STATIC +EFI_STATUS +EFIAPI +UsbGetStringDescriptor ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT16 LangID, + IN UINT8 StringIndex, + OUT CHAR16 **String + ); + +STATIC +EFI_STATUS +EFIAPI +UsbGetSupportedLanguages ( + IN EFI_USB_IO_PROTOCOL *This, + OUT UINT16 **LangIDTable, + OUT UINT16 *TableSize + ); + +// +// USB I/O Interface structure +// +STATIC EFI_USB_IO_PROTOCOL UsbIoInterface = { + UsbControlTransfer, + UsbBulkTransfer, + UsbAsyncInterruptTransfer, + UsbSyncInterruptTransfer, + UsbIsochronousTransfer, + UsbAsyncIsochronousTransfer, + UsbGetDeviceDescriptor, + UsbGetActiveConfigDescriptor, + UsbGetInterfaceDescriptor, + UsbGetEndpointDescriptor, + UsbGetStringDescriptor, + UsbGetSupportedLanguages, + UsbPortReset +}; + +VOID +InitializeUsbIoInstance ( + IN USB_IO_CONTROLLER_DEVICE *UsbIoController + ) +{ + // + // Copy EFI_USB_IO protocol instance + // + CopyMem ( + &UsbIoController->UsbIo, + &UsbIoInterface, + sizeof (EFI_USB_IO_PROTOCOL) + ); +} +// +// Implementation +// +STATIC +EFI_STATUS +EFIAPI +UsbControlTransfer ( + IN EFI_USB_IO_PROTOCOL *This, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT32 Timeout, + IN OUT VOID *Data, OPTIONAL + IN UINTN DataLength, OPTIONAL + OUT UINT32 *Status + ) +/*++ + + Routine Description: + This function is used to manage a USB device with a control transfer pipe. + + Arguments: + This - Indicates calling context. + Request - A pointer to the USB device request that will be sent to + the USB device. + Direction - Indicates the data direction. + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + Timeout - Indicates the transfer should be completed within this time + frame. + DataLength - The size, in bytes, of the data buffer specified by Data. + Status - A pointer to the result of the USB transfer. + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + EFI_OUT_OF_RESOURCES + EFI_TIMEOUT + EFI_DEVICE_ERROR + +--*/ +{ + USB_IO_CONTROLLER_DEVICE *UsbIoController; + EFI_USB_HC_PROTOCOL *UsbHCInterface; + EFI_STATUS RetStatus; + USB_IO_DEVICE *UsbIoDevice; + UINT8 MaxPacketLength; + UINT32 TransferResult; + BOOLEAN Disconnected; + // + // Parameters Checking + // + if (Status == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // leave the HostController's ControlTransfer + // to perform other parameters checking + // + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + UsbIoDevice = UsbIoController->UsbDevice; + UsbHCInterface = UsbIoDevice->BusController->UsbHCInterface; + MaxPacketLength = UsbIoDevice->DeviceDescriptor.MaxPacketSize0; + + + if (Request->Request == USB_DEV_CLEAR_FEATURE && + Request->RequestType == 0x02 && + Request->Value == EfiUsbEndpointHalt) { + // + //Reduce the remove delay time for system response + // + IsDeviceDisconnected (UsbIoController, &Disconnected); + if (!EFI_ERROR (Status) && Disconnected == TRUE) { + DEBUG ((gUSBErrorLevel, "Device is disconnected when trying reset\n")); + return EFI_DEVICE_ERROR; + } + } + + + + // + // using HostController's ControlTransfer to complete the request + // + RetStatus = UsbHCInterface->ControlTransfer ( + UsbHCInterface, + UsbIoDevice->DeviceAddress, + UsbIoDevice->IsSlowDevice, + MaxPacketLength, + Request, + Direction, + Data, + &DataLength, + (UINTN) Timeout, + &TransferResult + ); + *Status = TransferResult; + + if (Request->Request == USB_DEV_CLEAR_FEATURE && + Request->RequestType == 0x02 && + Request->Value == EfiUsbEndpointHalt) { + // + // This is a UsbClearEndpointHalt request + // Need to clear data toggle + // Request.Index == EndpointAddress + // + if (!EFI_ERROR (RetStatus) && TransferResult == EFI_USB_NOERROR) { + SetDataToggleBit ( + This, + (UINT8) Request->Index, + 0 + ); + } + } + return RetStatus; +} + +STATIC +EFI_STATUS +EFIAPI +UsbBulkTransfer ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout, + OUT UINT32 *Status + ) +/*++ + + Routine Description: + This function is used to manage a USB device with the bulk transfer pipe. + + Arguments: + This - Indicates calling context. + DeviceEndpoint - The destination USB device endpoint to which the device + request is being sent. + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + DataLength - On input, the size, in bytes, of the data buffer + specified by Data. On output, the number of bytes that + were actually transferred. + Timeout - Indicates the transfer should be completed within this + time frame. + Status - This parameter indicates the USB transfer status. + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + EFI_OUT_OF_RESOURCES + EFI_TIMEOUT + EFI_DEVICE_ERROR + +--*/ +{ + USB_IO_DEVICE *UsbIoDev; + UINT8 MaxPacketLength; + UINT8 DataToggle; + UINT8 OldToggle; + EFI_STATUS RetStatus; + EFI_USB_HC_PROTOCOL *UsbHCInterface; + USB_IO_CONTROLLER_DEVICE *UsbIoController; + ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry; + UINT32 TransferResult; + + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + UsbIoDev = UsbIoController->UsbDevice; + UsbHCInterface = UsbIoDev->BusController->UsbHCInterface; + + // + // Parameters Checking + // + if ((DeviceEndpoint & 0x7F) == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((DeviceEndpoint & 0x7F) > 15) { + return EFI_INVALID_PARAMETER; + } + + if (Status == NULL) { + return EFI_INVALID_PARAMETER; + } + + EndPointListEntry = FindEndPointListEntry ( + This, + DeviceEndpoint + ); + + if (EndPointListEntry == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((EndPointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x02) { + return EFI_INVALID_PARAMETER; + } + + // + // leave the HostController's BulkTransfer + // to perform other parameters checking + // + GetDeviceEndPointMaxPacketLength ( + This, + DeviceEndpoint, + &MaxPacketLength + ); + + GetDataToggleBit ( + This, + DeviceEndpoint, + &DataToggle + ); + + OldToggle = DataToggle; + + // + // using HostController's BulkTransfer to complete the request + // + RetStatus = UsbHCInterface->BulkTransfer ( + UsbHCInterface, + UsbIoDev->DeviceAddress, + DeviceEndpoint, + MaxPacketLength, + Data, + DataLength, + &DataToggle, + Timeout, + &TransferResult + ); + + if (OldToggle != DataToggle) { + // + // Write the toggle back + // + SetDataToggleBit ( + This, + DeviceEndpoint, + DataToggle + ); + } + + *Status = TransferResult; + + return RetStatus; +} + +STATIC +EFI_STATUS +EFIAPI +UsbSyncInterruptTransfer ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout, + OUT UINT32 *Status + ) +/*++ + + Routine Description: + Usb Sync Interrupt Transfer + + Arguments: + This - Indicates calling context. + DeviceEndpoint - The destination USB device endpoint to which the device + request is being sent. + Data - A pointer to the buffer of data that will be transmitted + to USB device or received from USB device. + DataLength - On input, the size, in bytes, of the data buffer + specified by Data. On output, the number of bytes that + were actually transferred. + Timeout - Indicates the transfer should be completed within this + time frame. + Status - This parameter indicates the USB transfer status. + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + EFI_OUT_OF_RESOURCES + EFI_TIMEOUT + EFI_DEVICE_ERROR + +--*/ +{ + USB_IO_DEVICE *UsbIoDev; + UINT8 MaxPacketLength; + UINT8 DataToggle; + UINT8 OldToggle; + EFI_STATUS RetStatus; + EFI_USB_HC_PROTOCOL *UsbHCInterface; + USB_IO_CONTROLLER_DEVICE *UsbIoController; + ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry; + + // + // Parameters Checking + // + if ((DeviceEndpoint & 0x7F) == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((DeviceEndpoint & 0x7F) > 15) { + return EFI_INVALID_PARAMETER; + } + + if (Status == NULL) { + return EFI_INVALID_PARAMETER; + } + + EndPointListEntry = FindEndPointListEntry ( + This, + DeviceEndpoint + ); + + if (EndPointListEntry == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((EndPointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x03) { + return EFI_INVALID_PARAMETER; + } + + // + // leave the HostController's SyncInterruptTransfer + // to perform other parameters checking + // + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + UsbIoDev = UsbIoController->UsbDevice; + UsbHCInterface = UsbIoDev->BusController->UsbHCInterface; + + GetDeviceEndPointMaxPacketLength ( + This, + DeviceEndpoint, + &MaxPacketLength + ); + + GetDataToggleBit ( + This, + DeviceEndpoint, + &DataToggle + ); + + OldToggle = DataToggle; + // + // using HostController's SyncInterruptTransfer to complete the request + // + RetStatus = UsbHCInterface->SyncInterruptTransfer ( + UsbHCInterface, + UsbIoDev->DeviceAddress, + DeviceEndpoint, + UsbIoDev->IsSlowDevice, + MaxPacketLength, + Data, + DataLength, + &DataToggle, + Timeout, + Status + ); + + if (OldToggle != DataToggle) { + // + // Write the toggle back + // + SetDataToggleBit ( + This, + DeviceEndpoint, + DataToggle + ); + } + + return RetStatus; +} + +STATIC +EFI_STATUS +EFIAPI +UsbAsyncInterruptTransfer ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval, OPTIONAL + IN UINTN DataLength, OPTIONAL + IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack, OPTIONAL + IN VOID *Context OPTIONAL + ) +/*++ + + Routine Description: + Usb Async Interrput Transfer + + Arguments: + This - Indicates calling context. + DeviceEndpoint - The destination USB device endpoint to which the + device request is being sent. + IsNewTransfer - If TRUE, a new transfer will be submitted to USB + controller. If FALSE, the interrupt transfer is + deleted from the device's interrupt transfer queue. + PollingInterval - Indicates the periodic rate, in milliseconds, that + the transfer is to be executed. + DataLength - Specifies the length, in bytes, of the data to be + received from the USB device. + InterruptCallback - The Callback function. This function is called if + the asynchronous interrupt transfer is completed. + Context - Passed to InterruptCallback + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + EFI_OUT_OF_RESOURCES + +--*/ +{ + USB_IO_DEVICE *UsbIoDev; + UINT8 MaxPacketLength; + UINT8 DataToggle; + EFI_USB_HC_PROTOCOL *UsbHCInterface; + EFI_STATUS RetStatus; + USB_IO_CONTROLLER_DEVICE *UsbIoController; + ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry; + + // + // Check endpoint + // + if ((DeviceEndpoint & 0x7F) == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((DeviceEndpoint & 0x7F) > 15) { + return EFI_INVALID_PARAMETER; + } + + EndpointListEntry = FindEndPointListEntry ( + This, + DeviceEndpoint + ); + + if (EndpointListEntry == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((EndpointListEntry->EndpointDescriptor.Attributes & 0x03) != 0x03) { + return EFI_INVALID_PARAMETER; + } + + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + UsbIoDev = UsbIoController->UsbDevice; + UsbHCInterface = UsbIoDev->BusController->UsbHCInterface; + + if (!IsNewTransfer) { + // + // Delete this transfer + // + UsbHCInterface->AsyncInterruptTransfer ( + UsbHCInterface, + UsbIoDev->DeviceAddress, + DeviceEndpoint, + UsbIoDev->IsSlowDevice, + 0, + FALSE, + &DataToggle, + PollingInterval, + DataLength, + NULL, + NULL + ); + + // + // We need to store the toggle value + // + SetDataToggleBit ( + This, + DeviceEndpoint, + DataToggle + ); + + return EFI_SUCCESS; + } + + GetDeviceEndPointMaxPacketLength ( + This, + DeviceEndpoint, + &MaxPacketLength + ); + + GetDataToggleBit ( + This, + DeviceEndpoint, + &DataToggle + ); + + RetStatus = UsbHCInterface->AsyncInterruptTransfer ( + UsbHCInterface, + UsbIoDev->DeviceAddress, + DeviceEndpoint, + UsbIoDev->IsSlowDevice, + MaxPacketLength, + TRUE, + &DataToggle, + PollingInterval, + DataLength, + InterruptCallBack, + Context + ); + + return RetStatus; +} + +STATIC +EFI_STATUS +EFIAPI +UsbIsochronousTransfer ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN UINTN DataLength, + OUT UINT32 *Status + ) +/*++ + + Routine Description: + Usb Isochronous Transfer + + Arguments: + This - Indicates calling context. + DeviceEndpoint - The destination USB device endpoint to which the + device request is being sent. + Data - A pointer to the buffer of data that will be + transmitted to USB device or received from USB device. + DataLength - The size, in bytes, of the data buffer specified by + Data. + Status - This parameter indicates the USB transfer status. + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + EFI_OUT_OF_RESOURCES + EFI_TIMEOUT + EFI_DEVICE_ERROR + EFI_UNSUPPORTED +--*/ +{ + // + // Currently we don't support this transfer + // + return EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +UsbAsyncIsochronousTransfer ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ) +/*++ + +Routine Description: + + Usb Async Isochronous Transfer + +Arguments: + + This - EFI_USB_IO_PROTOCOL + DeviceEndpoint - DeviceEndpoint number + Data - Data to transfer + DataLength - DataLength + IsochronousCallBack - Isochronous CallBack function + Context - Passed to IsochronousCallBack function +Returns: + + EFI_UNSUPPORTED - Unsupported now + +--*/ +{ + // + // Currently we don't support this transfer + // + return EFI_UNSUPPORTED; +} +// +// Here is new definitions +// +STATIC +EFI_STATUS +EFIAPI +UsbGetDeviceDescriptor ( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_DEVICE_DESCRIPTOR *DeviceDescriptor + ) +/*++ + + Routine Description: + Retrieves the USB Device Descriptor. + + Arguments: + This - Indicates the calling context. + DeviceDescriptor - A pointer to the caller allocated USB Device + Descriptor. + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + EFI_NOT_FOUND + +--*/ +{ + USB_IO_CONTROLLER_DEVICE *UsbIoController; + USB_IO_DEVICE *UsbIoDev; + + // + // This function just wrapps UsbGetDeviceDescriptor. + // + + if (DeviceDescriptor == NULL) { + return EFI_INVALID_PARAMETER; + } + + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + UsbIoDev = UsbIoController->UsbDevice; + + if (!UsbIoDev->IsConfigured) { + return EFI_NOT_FOUND; + } + + CopyMem ( + DeviceDescriptor, + &UsbIoDev->DeviceDescriptor, + sizeof (EFI_USB_DEVICE_DESCRIPTOR) + ); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +UsbGetActiveConfigDescriptor ( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_CONFIG_DESCRIPTOR *ConfigurationDescriptor + ) +/*++ + + Routine Description: + Retrieves the current USB configuration Descriptor. + + Arguments: + This - Indicates the calling context. + ConfigurationDescriptor - A pointer to the caller allocated USB active + Configuration Descriptor. + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + EFI_NOT_FOUND + +--*/ +{ + USB_IO_DEVICE *UsbIoDev; + USB_IO_CONTROLLER_DEVICE *UsbIoController; + + // + // This function just wrapps UsbGetActiveConfigDescriptor. + // + if (ConfigurationDescriptor == NULL) { + return EFI_INVALID_PARAMETER; + } + + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + UsbIoDev = UsbIoController->UsbDevice; + + if (!UsbIoDev->IsConfigured) { + return EFI_NOT_FOUND; + } + + CopyMem ( + ConfigurationDescriptor, + &(UsbIoDev->ActiveConfig->CongfigDescriptor), + sizeof (EFI_USB_CONFIG_DESCRIPTOR) + ); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +UsbGetInterfaceDescriptor ( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor + ) +/*++ + + Routine Description: + Retrieves the interface Descriptor for that controller. + + Arguments: + This - Indicates the calling context. + InterfaceDescriptor - A pointer to the caller allocated USB interface + Descriptor. + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + EFI_NOT_FOUND + +--*/ +{ + INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry; + + if (InterfaceDescriptor == NULL) { + return EFI_INVALID_PARAMETER; + } + + InterfaceListEntry = FindInterfaceListEntry (This); + + if (InterfaceListEntry == NULL) { + return EFI_NOT_FOUND; + } + + CopyMem ( + InterfaceDescriptor, + &(InterfaceListEntry->InterfaceDescriptor), + sizeof (EFI_USB_INTERFACE_DESCRIPTOR) + ); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +UsbGetEndpointDescriptor ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + OUT EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor + ) +/*++ + + Routine Description: + Retrieves the endpoint Descriptor for a given endpoint. + + Arguments: + This - Indicates the calling context. + EndpointIndex - Indicates which endpoint descriptor to retrieve. + The valid range is 0..15. + EndpointDescriptor - A pointer to the caller allocated USB Endpoint + Descriptor of a USB controller. + + Returns: + EFI_SUCCESS - The endpoint descriptor was retrieved successfully. + EFI_INVALID_PARAMETER - EndpointIndex is not valid. + - EndpointDescriptor is NULL. + EFI_NOT_FOUND - The endpoint descriptor cannot be found. + The device may not be correctly configured. + +--*/ +{ + INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry; + LIST_ENTRY *EndpointListHead; + ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry; + + if (EndpointDescriptor == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (EndpointIndex > 15) { + return EFI_INVALID_PARAMETER; + } + + InterfaceListEntry = FindInterfaceListEntry (This); + + if (InterfaceListEntry == NULL) { + return EFI_NOT_FOUND; + } + + EndpointListHead = (LIST_ENTRY *) (&InterfaceListEntry->EndpointDescListHead); + EndpointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) (EndpointListHead->ForwardLink); + + if (EndpointIndex >= InterfaceListEntry->InterfaceDescriptor.NumEndpoints) { + return EFI_NOT_FOUND; + } + // + // Loop all endpoint descriptor to get match one. + // + while (EndpointIndex != 0) { + EndpointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) (EndpointListEntry->Link.ForwardLink); + EndpointIndex--; + } + + CopyMem ( + EndpointDescriptor, + &EndpointListEntry->EndpointDescriptor, + sizeof (EFI_USB_ENDPOINT_DESCRIPTOR) + ); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +UsbGetSupportedLanguages ( + IN EFI_USB_IO_PROTOCOL *This, + OUT UINT16 **LangIDTable, + OUT UINT16 *TableSize + ) +/*++ + + Routine Description: + Get all the languages that the USB device supports + + Arguments: + This - Indicates the calling context. + LangIDTable - Language ID for the string the caller wants to get. + TableSize - The size, in bytes, of the table LangIDTable. + + Returns: + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + USB_IO_DEVICE *UsbIoDev; + USB_IO_CONTROLLER_DEVICE *UsbIoController; + UINTN Index; + BOOLEAN Found; + + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + UsbIoDev = UsbIoController->UsbDevice; + + Found = FALSE; + Index = 0; + // + // Loop language table + // + while (UsbIoDev->LangID[Index]) { + Found = TRUE; + Index++; + } + + if (!Found) { + return EFI_NOT_FOUND; + } + + *LangIDTable = UsbIoDev->LangID; + *TableSize = (UINT16) Index; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +UsbGetStringDescriptor ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT16 LangID, + IN UINT8 StringIndex, + OUT CHAR16 **String + ) +/*++ + + Routine Description: + Get a given string descriptor + + Arguments: + This - Indicates the calling context. + LangID - The Language ID for the string being retrieved. + StringIndex - The ID of the string being retrieved. + String - A pointer to a buffer allocated by this function + with AllocatePool() to store the string. If this + function returns EFI_SUCCESS, it stores the string + the caller wants to get. The caller should release + the string buffer with FreePool() after the string + is not used any more. + Returns: + EFI_SUCCESS + EFI_NOT_FOUND + EFI_OUT_OF_RESOURCES + +--*/ +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_STRING_DESCRIPTOR *StrDescriptor; + UINT8 *Buffer; + CHAR16 *UsbString; + UINT16 TempBuffer; + USB_IO_DEVICE *UsbIoDev; + UINT8 Index; + BOOLEAN Found; + USB_IO_CONTROLLER_DEVICE *UsbIoController; + + if (StringIndex == 0) { + return EFI_NOT_FOUND; + } + // + // Search LanguageID, check if it is supported by this device + // + if (LangID == 0) { + return EFI_NOT_FOUND; + } + + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + UsbIoDev = UsbIoController->UsbDevice; + + Found = FALSE; + Index = 0; + while (UsbIoDev->LangID[Index]) { + if (UsbIoDev->LangID[Index] == LangID) { + Found = TRUE; + break; + } + + Index++; + } + + if (!Found) { + return EFI_NOT_FOUND; + } + // + // Get String Length + // + Result = UsbGetString ( + This, + LangID, + StringIndex, + &TempBuffer, + 2, + &Status + ); + if (EFI_ERROR (Result)) { + return EFI_NOT_FOUND; + } + + StrDescriptor = (EFI_USB_STRING_DESCRIPTOR *) &TempBuffer; + + if (StrDescriptor->Length == 0) { + return EFI_UNSUPPORTED; + } + + Buffer = AllocateZeroPool (StrDescriptor->Length); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Result = UsbGetString ( + This, + LangID, + StringIndex, + Buffer, + StrDescriptor->Length, + &Status + ); + + if (EFI_ERROR (Result)) { + gBS->FreePool (Buffer); + return EFI_NOT_FOUND; + } + + StrDescriptor = (EFI_USB_STRING_DESCRIPTOR *) Buffer; + + // + // UsbString is a UNICODE string + // + UsbString = AllocateZeroPool (StrDescriptor->Length); + if (UsbString == NULL) { + gBS->FreePool (Buffer); + return EFI_OUT_OF_RESOURCES; + } + + CopyMem ( + (VOID *) UsbString, + Buffer + 2, + StrDescriptor->Length - 2 + ); + + *String = UsbString; + + gBS->FreePool (Buffer); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c new file mode 100644 index 0000000000..07eb5805e9 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.c @@ -0,0 +1,556 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + usbutil.c + + Abstract: + + Helper functions for USB + + Revision History + +--*/ + +#include "usbbus.h" + +// +// Following APIs are used to query Port Status +// +BOOLEAN +IsPortConnect ( + IN UINT16 PortStatus + ) +/*++ + + Routine Description: + Tell if there is a device connected to that port according to + the Port Status. + + Parameters: + PortStatus - The status value of that port. + + Return Value: + TRUE + FALSE + +--*/ +{ + // + // return the bit 0 value of PortStatus + // + if ((PortStatus & USB_PORT_STAT_CONNECTION) != 0) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsPortEnable ( + IN UINT16 PortStatus + ) +/*++ + + Routine Description: + Tell if Port is enabled. + + Arguments: + PortStatus - The status value of that port. + + Returns: + TRUE - Port is enable + FALSE - Port is disable + +--*/ +{ + // + // return the bit 1 value of PortStatus + // + if ((PortStatus & USB_PORT_STAT_ENABLE) != 0) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsPortInReset ( + IN UINT16 PortStatus + ) +/*++ + + Routine Description: + Tell if the port is being reset. + + Arguments: + PortStatus - The status value of that port. + + Returns: + TRUE + FALSE + +--*/ +{ + // + // return the bit 4 value of PortStatus + // + if ((PortStatus & USB_PORT_STAT_RESET) != 0) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsPortPowerApplied ( + IN UINT16 PortStatus + ) +/*++ + + Routine Description: + Tell if there is power applied to that port. + + Arguments: + PortStatus - The status value of that port. + + Returns: + TRUE + FALSE + +--*/ +{ + // + // return the bit 8 value of PortStatus + // + if ((PortStatus & USB_PORT_STAT_POWER) != 0) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsPortLowSpeedDeviceAttached ( + IN UINT16 PortStatus + ) +/*++ + + Routine Description: + Tell if the connected device is a low device. + + Arguments: + PortStatus - The status value of that port. + + Returns: + TRUE + FALSE + +--*/ +{ + // + // return the bit 9 value of PortStatus + // + if ((PortStatus & USB_PORT_STAT_LOW_SPEED) != 0) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsPortSuspend ( + IN UINT16 PortStatus + ) +/*++ + + Routine Description: + Tell if the port is suspend. + + Arguments: + PortStatus - The status value of that port. + + Returns: + TRUE + FALSE + +--*/ +{ + // + // return the bit 2 value of PortStatus + // + if ((PortStatus & USB_PORT_STAT_SUSPEND) != 0) { + return TRUE; + } else { + return FALSE; + } +} +// +// Following APIs are used to query Port Change Status +// +BOOLEAN +IsPortConnectChange ( + IN UINT16 PortChangeStatus + ) +/*++ + + Routine Description: + Tell if there is a Connect Change status in that port. + + Arguments: + PortChangeStatus - The status value of that port. + + Returns: + TRUE + FALSE + +--*/ +{ + // + // return the bit 0 value of PortChangeStatus + // + if ((PortChangeStatus & USB_PORT_STAT_C_CONNECTION) != 0) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsPortEnableDisableChange ( + IN UINT16 PortChangeStatus + ) +/*++ + + Routine Description: + Tell if there is a Enable/Disable change in that port. + + Arguments: + PortChangeStatus - The status value of that port. + + Returns: + TRUE + FALSE + +--*/ +{ + // + // return the bit 1 value of PortChangeStatus + // + if ((PortChangeStatus & USB_PORT_STAT_C_ENABLE) != 0) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsPortResetChange ( + IN UINT16 PortChangeStatus + ) +/*++ + + Routine Description: + Tell if there is a Port Reset Change status in that port. + + Arguments: + PortChangeStatus - The status value of that port. + + Returns: + TRUE + FALSE + +--*/ +{ + // + // return the bit 4 value of PortChangeStatus + // + if ((PortChangeStatus & USB_PORT_STAT_C_RESET) != 0) { + return TRUE; + } else { + return FALSE; + } +} + + +BOOLEAN +IsPortSuspendChange ( + IN UINT16 PortChangeStatus + ) +/*++ + + Routine Description: + Tell if there is a Suspend Change Status in that port. + + Arguments: + PortChangeStatus - The status value of that port. + + Returns: + TRUE + FALSE + +--*/ +{ + // + // return the bit 2 value of PortChangeStatus + // + if ((PortChangeStatus & USB_PORT_STAT_C_SUSPEND) != 0) { + return TRUE; + } else { + return FALSE; + } +} + + +INTERFACE_DESC_LIST_ENTRY* +FindInterfaceListEntry ( + IN EFI_USB_IO_PROTOCOL *This + ) +/*++ + + Routine Description: + Find Interface ListEntry. + + Arguments: + This - EFI_USB_IO_PROTOCOL + + Returns: + INTERFACE_DESC_LIST_ENTRY pointer + +--*/ +{ + USB_IO_CONTROLLER_DEVICE *UsbIoController; + USB_IO_DEVICE *UsbIoDev; + LIST_ENTRY *InterfaceListHead; + INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry; + + UsbIoController = USB_IO_CONTROLLER_DEVICE_FROM_USB_IO_THIS (This); + UsbIoDev = UsbIoController->UsbDevice; + + if (!UsbIoDev->IsConfigured) { + return NULL; + } + + InterfaceListHead = &UsbIoDev->ActiveConfig->InterfaceDescListHead; + InterfaceListEntry = (INTERFACE_DESC_LIST_ENTRY *) (InterfaceListHead->ForwardLink); + + // + // Loop all interface descriptor to get match one. + // + while (InterfaceListEntry != (INTERFACE_DESC_LIST_ENTRY *) InterfaceListHead) { + if (InterfaceListEntry->InterfaceDescriptor.InterfaceNumber == UsbIoController->InterfaceNumber) { + return InterfaceListEntry; + } + + InterfaceListEntry = (INTERFACE_DESC_LIST_ENTRY *) InterfaceListEntry->Link.ForwardLink; + } + + return NULL; +} + +ENDPOINT_DESC_LIST_ENTRY* +FindEndPointListEntry ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 EndPointAddress + ) +/*++ + + Routine Description: + Find EndPoint ListEntry. + + Arguments: + This - EFI_USB_IO_PROTOCOL + EndpointAddr - Endpoint address. + + Returns: + ENDPOINT_DESC_LIST_ENTRY pointer + +--*/ +{ + INTERFACE_DESC_LIST_ENTRY *InterfaceListEntry; + LIST_ENTRY *EndpointDescListHead; + ENDPOINT_DESC_LIST_ENTRY *EndPointListEntry; + + InterfaceListEntry = FindInterfaceListEntry (This); + if (InterfaceListEntry != NULL) { + EndpointDescListHead = &InterfaceListEntry->EndpointDescListHead; + EndPointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) (EndpointDescListHead->ForwardLink); + + // + // Loop all interface descriptor to get match one. + // + while (EndPointListEntry != (ENDPOINT_DESC_LIST_ENTRY *) EndpointDescListHead) { + if (EndPointListEntry->EndpointDescriptor.EndpointAddress == EndPointAddress) { + return EndPointListEntry; + } + + EndPointListEntry = (ENDPOINT_DESC_LIST_ENTRY *) EndPointListEntry->Link.ForwardLink; + } + } + + return NULL; +} + +VOID +GetDataToggleBit ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 EndpointAddr, + OUT UINT8 *DataToggle + ) +/*++ + + Routine Description: + Get the datatoggle of a specified endpoint. + + Arguments: + UsbIo - Given Usb Controller device. + EndpointAddr - Given Endpoint address. + DataToggle - The current data toggle of that endpoint + + Returns: + N/A + +--*/ +{ + + ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry; + + *DataToggle = 0; + + EndpointListEntry = FindEndPointListEntry (UsbIo, EndpointAddr); + if (EndpointListEntry == NULL) { + return ; + } + + *DataToggle = (UINT8) (EndpointListEntry->Toggle); + return ; +} + +VOID +SetDataToggleBit ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 EndpointAddr, + IN UINT8 DataToggle + ) +/*++ + + Routine Description: + Set the datatoggle of a specified endpoint + + Arguments: + UsbIo - Given Usb Controller device. + EndpointAddr - Given Endpoint address. + DataToggle - The current data toggle of that endpoint to be set + + Returns: + N/A + +--*/ +{ + + ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry; + + EndpointListEntry = FindEndPointListEntry (UsbIo, EndpointAddr); + if (EndpointListEntry == NULL) { + return ; + } + + EndpointListEntry->Toggle = DataToggle; + return ; +} + +VOID +GetDeviceEndPointMaxPacketLength ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 EndpointAddr, + OUT UINT8 *MaxPacketLength + ) +/*++ + + Routine Description: + Get the Max Packet Length of the speified Endpoint. + + Arguments: + UsbIo - Given Usb Controller device. + EndpointAddr - Given Endpoint address. + MaxPacketLength - The max packet length of that endpoint + + Returns: + N/A + +--*/ +{ + + ENDPOINT_DESC_LIST_ENTRY *EndpointListEntry; + + *MaxPacketLength = 0; + + EndpointListEntry = FindEndPointListEntry (UsbIo, EndpointAddr); + if (EndpointListEntry == NULL) { + return ; + } + + *MaxPacketLength = (UINT8) (EndpointListEntry->EndpointDescriptor.MaxPacketSize); + + return ; +} + + +EFI_STATUS +UsbSetDeviceAddress ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 AddressValue, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Set Device Address + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + AddressValue - Device address + Status - Transfer status + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_SET_ADDRESS_REQ_TYPE; + DevReq.Request = USB_DEV_SET_ADDRESS; + DevReq.Value = AddressValue; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + TIMEOUT_VALUE, + NULL, + 0, + Status + ); +} + diff --git a/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.h b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.h new file mode 100644 index 0000000000..259276cbaf --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbBus/Dxe/usbutil.h @@ -0,0 +1,94 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + usbutil.h + + Abstract: + + Helper functions for USB + + Revision History + + +--*/ + +#ifndef _USB_UTIL_H +#define _USB_UTIL_H + +// +// Following APIs are used to query Port Status +// +BOOLEAN +IsPortConnect ( + IN UINT16 PortStatus + ); + +BOOLEAN +IsPortEnable ( + IN UINT16 PortStatus + ); + +BOOLEAN +IsPortInReset ( + IN UINT16 PortStatus + ); + +BOOLEAN +IsPortPowerApplied ( + IN UINT16 PortStatus + ); + +BOOLEAN +IsPortLowSpeedDeviceAttached ( + IN UINT16 PortStatus + ); + +BOOLEAN +IsPortSuspend ( + IN UINT16 PortStatus + ); + +// +// Following APIs are used to query Port Change Status +// +BOOLEAN +IsPortConnectChange ( + IN UINT16 PortChangeStatus + ); + +BOOLEAN +IsPortEnableDisableChange ( + IN UINT16 PortChangeStatus + ); + +BOOLEAN +IsPortResetChange ( + IN UINT16 PortChangeStatus + ); + +BOOLEAN +IsPortSuspendChange ( + IN UINT16 PortChangeStatus + ); + +// +// Set device address; +// +EFI_STATUS +UsbSetDeviceAddress ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 AddressValue, + OUT UINT32 *Status + ); + + +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c new file mode 100644 index 0000000000..5bd8728fcf --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/Cbi0.c @@ -0,0 +1,1042 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Cbi0.c + +Abstract: + +--*/ + +#include "../cbi.h" + +extern EFI_COMPONENT_NAME_PROTOCOL gUsbCbi0ComponentName; +// +// Function prototypes +// +EFI_STATUS +EFIAPI +UsbCbi0DriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// Bot Driver Binding Protocol +// +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +VOID +Cbi0ReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ); + + +EFI_DRIVER_BINDING_PROTOCOL gUsbCbi0DriverBinding = { + Cbi0DriverBindingSupported, + Cbi0DriverBindingStart, + Cbi0DriverBindingStop, + 0x10, + NULL, + NULL +}; + +STATIC +EFI_STATUS +Cbi0RecoveryReset ( + IN USB_CBI_DEVICE *UsbCbiDev + ); + +STATIC +EFI_STATUS +Cbi0CommandPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN VOID *Command, + IN UINT8 CommandSize, + IN UINT16 Timeout + ); + +STATIC +EFI_STATUS +Cbi0DataPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN UINT32 *DataSize, + IN OUT VOID *DataBuffer, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout + ); + +STATIC +EFI_STATUS +Cbi0StatusPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock, + IN UINT16 Timeout + ); + +// +// USB Atapi protocol prototype +// +STATIC +EFI_STATUS +EFIAPI +Cbi0AtapiCommand ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds + ); + +STATIC +EFI_STATUS +EFIAPI +Cbi0MassStorageReset ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +STATIC EFI_USB_ATAPI_PROTOCOL Cbi0AtapiProtocol = { + Cbi0AtapiCommand, + Cbi0MassStorageReset, + 0 +}; + +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a BlockIo and DiskIo protocol can be supported. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device + EFI_ALREADY_STARTED - This driver is already running on this device + other - This driver does not support this device + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + + // + // Check if the Controller supports USB IO protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the Default interface descriptor, now we only + // suppose interface 1 + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + } + // + // Check if it is a Cbi0 Type Mass Storage Device + // + if((InterfaceDescriptor.InterfaceClass != MASS_STORAGE_CLASS) || + (InterfaceDescriptor.InterfaceProtocol != CBI0_INTERFACE_PROTOCOL)) { + Status = EFI_UNSUPPORTED; + } else { + Status = EFI_SUCCESS; + } + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Start this driver on ControllerHandle by opening a Block IO and Disk IO + protocol, reading Device Path, and creating a child handle with a + Disk IO and device path protocol. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to bind driver to + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver is added to DeviceHandle + EFI_ALREADY_STARTED - This driver is already running on DeviceHandle + other - This driver does not support this device + EFI_OUT_OF_RESOURCES- Can't allocate memory + EFI_UNSUPPORTED - Endpoint is not as expected +--*/ +{ + USB_CBI_DEVICE *UsbCbiDev; + UINT8 Index; + EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointExistMask; + + // + // Check if the Controller supports USB IO protocol + // + UsbCbiDev = NULL; + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the controller interface descriptor + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + } + + Cbi0AtapiProtocol.CommandProtocol = InterfaceDescriptor.InterfaceSubClass; + + UsbCbiDev = AllocateZeroPool (sizeof (USB_CBI_DEVICE)); + if (UsbCbiDev == NULL) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return EFI_OUT_OF_RESOURCES; + } + + UsbCbiDev->Signature = USB_CBI_DEVICE_SIGNATURE; + UsbCbiDev->UsbIo = UsbIo; + CopyMem (&UsbCbiDev->InterfaceDescriptor, &InterfaceDescriptor, sizeof (InterfaceDescriptor)); + CopyMem (&UsbCbiDev->UsbAtapiProtocol, &Cbi0AtapiProtocol, sizeof (Cbi0AtapiProtocol)); + + // + // Get the Device Path Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &UsbCbiDev->DevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + if (UsbCbiDev != NULL) { + gBS->FreePool (UsbCbiDev); + } + + return Status; + } + // + // Mask used to see whether all three kinds of endpoints exist, + // Mask value: + // bit0: bulk in endpoint; + // bit1: bulk out endpoint; + // bit2: interrupt in endpoint; + // + EndpointExistMask = 0; + for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) { + UsbIo->UsbGetEndpointDescriptor ( + UsbIo, + Index, + &EndpointDescriptor + ); + + // + // We parse bulk endpoint + // + if (EndpointDescriptor.Attributes == 0x02) { + if (EndpointDescriptor.EndpointAddress & 0x80) { + CopyMem (&UsbCbiDev->BulkInEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + // UsbCbiDev->BulkInEndpointDescriptor = EndpointDescriptor; + EndpointExistMask |= bit (0); + } else { + CopyMem (&UsbCbiDev->BulkOutEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + // UsbCbiDev->BulkOutEndpointDescriptor = EndpointDescriptor; + EndpointExistMask |= bit (1); + } + } + // + // We parse interrupt endpoint + // + if (EndpointDescriptor.Attributes == 0x03) { + CopyMem (&UsbCbiDev->InterruptEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + // UsbCbiDev->InterruptEndpointDescriptor = EndpointDescriptor; + EndpointExistMask |= bit (2); + } + + } + // + // Double check we have all endpoints needed + // + if (EndpointExistMask != (bit (0) | bit (1) | bit (2))) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + if (UsbCbiDev != NULL) { + gBS->FreePool (UsbCbiDev); + } + + return EFI_UNSUPPORTED; + } + // + // After installing Usb-Atapi protocol onto this handle + // it will be called by upper layer drivers such as Fat + // + Cbi0ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE) + ); + + Status = gBS->InstallProtocolInterface ( + &ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + EFI_NATIVE_INTERFACE, + &UsbCbiDev->UsbAtapiProtocol + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + if (UsbCbiDev != NULL) { + gBS->FreePool (UsbCbiDev); + } + + return Status; + } + + UsbCbiDev->ControllerNameTable = NULL; + AddUnicodeString ( + "eng", + gUsbCbi0ComponentName.SupportedLanguages, + &UsbCbiDev->ControllerNameTable, + (CHAR16 *) L"Usb Cbi0 Mass Storage" + ); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +Cbi0DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + EFI_SUCCESS - This driver is removed DeviceHandle + EFI_UNSUPPORTED - This driver was not removed from this device + +--*/ +{ + EFI_STATUS Status; + EFI_USB_ATAPI_PROTOCOL *Cbi0AtapiProtocol; + USB_CBI_DEVICE *UsbCbiDev; + EFI_USB_IO_PROTOCOL *UsbIo; + + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + (VOID **) &Cbi0AtapiProtocol, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (Cbi0AtapiProtocol); + + UsbIo = UsbCbiDev->UsbIo; + + Cbi0ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE) + ); + + // + // Uninstall protocol + // + Status = gBS->UninstallProtocolInterface ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + &UsbCbiDev->UsbAtapiProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + // + // Free all allocated resources + // + if (UsbCbiDev->ControllerNameTable) { + FreeUnicodeStringTable (UsbCbiDev->ControllerNameTable); + } + + gBS->FreePool (UsbCbiDev); + + return Status; +} + + +STATIC +EFI_STATUS +Cbi0RecoveryReset ( + IN USB_CBI_DEVICE *UsbCbiDev + ) +/*++ + +Routine Description: + + Cbi0 Recovery Reset routine + +Arguments: + + UsbCbiDev - Cbi0RecoveryReset + +Returns: + + EFI_SUCCESS - Success + +--*/ +{ + UINT8 ResetCommand[12]; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointAddress; + UINT32 Result; + UINT16 Timeout; + + UsbIo = UsbCbiDev->UsbIo; + + Cbi0ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET) + ); + // + // CBI reset command protocol + // + SetMem (ResetCommand, sizeof (ResetCommand), 0xff); + ResetCommand[0] = 0x1d; + ResetCommand[1] = 0x04; + + // + // (in millisecond unit) + // + Timeout = STALL_1_SECOND; + + Status = Cbi0AtapiCommand ( + &UsbCbiDev->UsbAtapiProtocol, + ResetCommand, + 12, + NULL, + 0, + EfiUsbNoData, + Timeout + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->Stall (100 * 1000); + // + // clear bulk in endpoint stall feature + // + EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress; + Status = UsbClearEndpointHalt ( + UsbIo, + EndpointAddress, + &Result + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // clear bulk out endpoint stall feature + // + EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress; + Status = UsbClearEndpointHalt ( + UsbIo, + EndpointAddress, + &Result + ); + // + // according to CBI spec, no need to clear interrupt endpoint feature. + // + return Status; +} + +STATIC +EFI_STATUS +Cbi0CommandPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN VOID *Command, + IN UINT8 CommandSize, + IN UINT16 Timeout + ) +/*++ + + Routine Description: + Send ATAPI command through CBI0 interface. + + Arguments: + UsbCbiDev - USB_CBI_DEVICE + Command - Command to send + CommandSize - Command size + Timeout - Time out value in milliseconds + Returns: + EFI_SUCCESS - Success + EFI_DEVICE_ERROR - Fail + Others + +--*/ +{ + EFI_STATUS Status; + UINT32 Result; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_DEVICE_REQUEST Request; + + UsbIo = UsbCbiDev->UsbIo; + + ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Device request see CBI specification + // + Request.RequestType = 0x21; + Request.Request = 0x00; + Request.Value = 0; + Request.Index = 0; + Request.Length = CommandSize; + + Status = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataOut, + Timeout, + Command, + CommandSize, + &Result + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +Cbi0DataPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN UINT32 *DataSize, + IN OUT VOID *DataBuffer, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout + ) +/*++ + + Routine Description: + Get/Send Data through CBI0 interface + + Arguments: + UsbCbiDev - USB_CBI_DEVICE + DataSize - Data size + DataBuffer - Data buffer + Direction - IN/OUT/NODATA + Timeout - Time out value in milliseconds + Returns: + EFI_SUCCESS + Others + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointAddress; + UINTN Remain; + UINTN Increment; + UINT32 MaxPacketLength; + UINT8 *BufferPtr; + UINT32 Result; + UINTN TransferredSize; + + UsbIo = UsbCbiDev->UsbIo; + + Remain = *DataSize; + BufferPtr = (UINT8 *) DataBuffer; + TransferredSize = 0; + // + // retrieve the the max packet length of the given endpoint + // + if (Direction == EfiUsbDataIn) { + MaxPacketLength = UsbCbiDev->BulkInEndpointDescriptor.MaxPacketSize; + EndpointAddress = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress; + } else { + MaxPacketLength = UsbCbiDev->BulkOutEndpointDescriptor.MaxPacketSize; + EndpointAddress = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress; + } + + while (Remain > 0) { + + if (Remain > 16 * MaxPacketLength) { + Increment = 16 * MaxPacketLength; + } else { + Increment = Remain; + } + + Status = UsbIo->UsbBulkTransfer ( + UsbIo, + EndpointAddress, + BufferPtr, + &Increment, + Timeout, + &Result + ); + TransferredSize += Increment; + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + BufferPtr += Increment; + Remain -= Increment; + } + + return EFI_SUCCESS; + +ErrorExit: + + if (Direction == EfiUsbDataIn) { + Cbi0ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR) + ); + } else { + Cbi0ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR) + ); + } + + if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + Status = Cbi0RecoveryReset (UsbCbiDev); + } + + *DataSize = (UINT32) TransferredSize; + return Status; +} + +STATIC +EFI_STATUS +Cbi0StatusPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + OUT INTERRUPT_DATA_BLOCK *InterruptDataBlock, + IN UINT16 Timeout + ) +/*++ + + Routine Description: + Get transfer status through BOT interface + + Arguments: + UsbCbiDev - USB_CBI_DEVICE + InterruptDataBlock - Interrupt Data Block for interrupt transfer + Timeout - Time out value in milliseconds + Returns: + EFI_SUCCESS + Others + +--*/ +{ + UINT8 EndpointAddress; + UINTN InterruptDataBlockLength; + UINT32 Result; + EFI_STATUS Status; + + ZeroMem (InterruptDataBlock, sizeof (INTERRUPT_DATA_BLOCK)); + + EndpointAddress = UsbCbiDev->InterruptEndpointDescriptor.EndpointAddress; + InterruptDataBlockLength = sizeof (INTERRUPT_DATA_BLOCK); + + Status = UsbCbiDev->UsbIo->UsbSyncInterruptTransfer ( + UsbCbiDev->UsbIo, + EndpointAddress, + InterruptDataBlock, + &InterruptDataBlockLength, + Timeout, + &Result + ); + if (EFI_ERROR (Status)) { + if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + // + // just endpoint stall happens + // + UsbClearEndpointHalt ( + UsbCbiDev->UsbIo, + EndpointAddress, + &Result + ); + gBS->Stall (100 * 1000); + } + + return Status; + } + + return EFI_SUCCESS; +} +// +// Cbi0 Atapi Protocol Implementation +// +STATIC +EFI_STATUS +EFIAPI +Cbi0MassStorageReset ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset CBI Devices + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - TRUE if we need to do strictly reset. + + Returns: + EFI_SUCCESS - Command succeeded. + EFI_DEVICE_ERROR - Command failed. + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + USB_CBI_DEVICE *UsbCbiDev; + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This); + UsbIo = UsbCbiDev->UsbIo; + + if (ExtendedVerification) { + // + // UsbIo->UsbPortReset (UsbIo); + // + } + + Status = Cbi0RecoveryReset (UsbCbiDev); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +Cbi0AtapiCommand ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds + ) +/*++ + + Routine Description: + Send ATAPI command using BOT protocol. + + Arguments: + This - Protocol instance pointer. + Command - Command buffer + CommandSize - Size of Command Buffer + DataBuffer - Data buffer + BufferLength - Length of Data buffer + Direction - Data direction of this command + TimeOutInMilliSeconds - Timeout value in ms + + Returns: + EFI_SUCCESS - Command succeeded. + EFI_DEVICE_ERROR - Command failed. + EFI_INVALID_PARAMETER - Invalidate parameter +--*/ +{ + EFI_STATUS Status; + USB_CBI_DEVICE *UsbCbiDev; + UINT32 BufferSize; + INTERRUPT_DATA_BLOCK InterruptDataBlock; + EFI_STATUS DataPhaseStatus; + + if (Direction != EfiUsbNoData) { + if (DataBuffer == NULL || BufferLength == 0) { + return EFI_INVALID_PARAMETER; + } + } + + DataPhaseStatus = EFI_SUCCESS; + // + // Get the context + // + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This); + + // + // First send ATAPI command through Cbi + // + Status = Cbi0CommandPhase ( + UsbCbiDev, + Command, + CommandSize, + TimeOutInMilliSeconds + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Send/Get Data if there is a Data Stage + // + switch (Direction) { + + case EfiUsbDataIn: + case EfiUsbDataOut: + BufferSize = BufferLength; + + DataPhaseStatus = Cbi0DataPhase ( + UsbCbiDev, + &BufferSize, + DataBuffer, + Direction, + TimeOutInMilliSeconds + ); + break; + + case EfiUsbNoData: + break; + } + + if (EFI_ERROR (DataPhaseStatus)) { + return EFI_DEVICE_ERROR; + } + + // + // Status Phase + // + Status = Cbi0StatusPhase ( + UsbCbiDev, + &InterruptDataBlock, + TimeOutInMilliSeconds + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (This->CommandProtocol != EFI_USB_SUBCLASS_UFI) { + + if (InterruptDataBlock.bType == 0) { + // + // indicates command completion + // + switch (InterruptDataBlock.bValue & 0x03) { + + case 0: + Status = EFI_SUCCESS; + break; + + case 1: + Status = EFI_DEVICE_ERROR; + break; + + case 2: + Status = Cbi0RecoveryReset (UsbCbiDev); + if (EFI_ERROR (Status)) { + UsbCbiDev->UsbIo->UsbPortReset (UsbCbiDev->UsbIo); + } + + Status = EFI_DEVICE_ERROR; + break; + + case 3: + Status = EFI_DEVICE_ERROR; + } + } else { + Status = DataPhaseStatus; + } + + } else { + // + // UFI device, InterruptDataBlock.bType: ASC (Additional Sense Code) + // InterruptDataBlock.bValue: ASCQ (Additional Snese Code Qualifier) + // + Status = DataPhaseStatus; + } + + return Status; +} + +VOID +Cbi0ReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ) +/*++ + + Routine Description: + Report Status Code in Usb Cbi0 Driver + + Arguments: + DevicePath - Use this to get Device Path + CodeType - Status Code Type + CodeValue - Status Code Value + + Returns: + None + +--*/ +{ + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + CodeType, + Value, + DevicePath + ); +} diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c new file mode 100644 index 0000000000..0692c7fee5 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/ComponentName.c @@ -0,0 +1,192 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "../cbi.h" + +extern EFI_DRIVER_BINDING_PROTOCOL gUsbCbi0DriverBinding; + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +UsbCbi0ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UsbCbi0ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gUsbCbi0ComponentName = { + UsbCbi0ComponentNameGetDriverName, + UsbCbi0ComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mUsbCbi0DriverNameTable[] = { + { "eng", (CHAR16 *) L"Usb Cbi0 Mass Storage Driver" }, + { NULL , NULL } +}; + + +EFI_STATUS +EFIAPI +UsbCbi0ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gUsbCbi0ComponentName.SupportedLanguages, + mUsbCbi0DriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +UsbCbi0ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + USB_CBI_DEVICE *UsbCbiDev; + EFI_USB_ATAPI_PROTOCOL *UsbAtapi; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + (VOID **) &UsbAtapi, + gUsbCbi0DriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (UsbAtapi); + + return LookupUnicodeString ( + Language, + gUsbCbi0ComponentName.SupportedLanguages, + UsbCbiDev->ControllerNameTable, + ControllerName + ); + +} diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd new file mode 100644 index 0000000000..17a63f9b21 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.mbd @@ -0,0 +1,43 @@ + + + + + UsbCbi0 + A3527D16-E6CC-42f5-BADB-BF3DE177742B + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkUsbLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa new file mode 100644 index 0000000000..a128159e12 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa @@ -0,0 +1,68 @@ + + + + + UsbCbi0 + DXE_DRIVER + BS_DRIVER + A3527D16-E6CC-42f5-BADB-BF3DE177742B + 0 + Component description file for UsbCbi1 module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + EdkUsbLib + ReportStatusCodeLib + MemoryAllocationLib + UefiBootServicesTableLib + + + cbi0.c + componentname.c + + + MdePkg + EdkModulePkg + + + DevicePath + UsbIo + UsbAtapi + + + + + + + gUsbCbi0DriverBinding + gUsbCbi0ComponentName + + + diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml new file mode 100644 index 0000000000..e406abee8b --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi0/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd new file mode 100644 index 0000000000..e48251eb07 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.mbd @@ -0,0 +1,43 @@ + + + + + UsbCbi1 + B40612B2-A063-11d4-9A3A-0090273FC14D + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkUsbLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa new file mode 100644 index 0000000000..057585689e --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa @@ -0,0 +1,66 @@ + + + + + UsbCbi1 + DXE_DRIVER + BS_DRIVER + B40612B2-A063-11d4-9A3A-0090273FC14D + 0 + Component description file for UsbCbi1 module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + EdkUsbLib + ReportStatusCodeLib + MemoryAllocationLib + UefiBootServicesTableLib + + + cbi1.c + + + MdePkg + EdkModulePkg + + + DevicePath + UsbIo + UsbAtapi + + + + + + + gCBI1DriverBinding + + + diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml new file mode 100644 index 0000000000..132e52237c --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c new file mode 100644 index 0000000000..71644acef8 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/Cbi1/cbi1.c @@ -0,0 +1,854 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + cbi1.c + +Abstract: + cbi1 transportation protocol implementation files + +--*/ + +#include "../cbi.h" + +EFI_STATUS +EFIAPI +UsbCBI1DriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +// +// CBI Function prototypes +// +STATIC +EFI_STATUS +CBI1CommandPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN VOID *Command, + IN UINT8 CommandSize, + OUT UINT32 *Result + ); + +STATIC +EFI_STATUS +CBI1DataPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN UINT32 DataSize, + IN OUT VOID *DataBuffer, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout, + OUT UINT32 *Result + ); + +// +// USB Atapi implementation +// +STATIC +EFI_STATUS +EFIAPI +CBI1AtapiCommand ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds + ); + +STATIC +EFI_STATUS +EFIAPI +CBI1MassStorageReset ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +// +// CBI1 Driver Binding Protocol +// +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +VOID +Cbi1ReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ); + + +EFI_DRIVER_BINDING_PROTOCOL gCBI1DriverBinding = { + CBI1DriverBindingSupported, + CBI1DriverBindingStart, + CBI1DriverBindingStop, + 0x10, + NULL, + NULL +}; + +STATIC EFI_USB_ATAPI_PROTOCOL CBI1AtapiProtocol = { + CBI1AtapiCommand, + CBI1MassStorageReset, + 0 +}; + +// +// CBI1 Driver Binding implementation +// +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a BlockIo and DiskIo protocol can be supported. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device + EFI_ALREADY_STARTED - This driver is already running on this device + other - This driver does not support this device + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + + // + // Check if the Controller supports USB IO protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the Controller interface descriptor + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Status)) { + goto Exit; + } + // + // Bug here: just let Vendor specific CBI protocol get supported + // + if (!((InterfaceDescriptor.InterfaceClass == 0xFF) && + (InterfaceDescriptor.InterfaceProtocol == 0))) { + Status = EFI_UNSUPPORTED; + goto Exit; + } + +Exit: + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + +} + +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Start this driver on ControllerHandle by opening a Block IO and Disk IO + protocol, reading Device Path, and creating a child handle with a + Disk IO and device path protocol. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to bind driver to + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver is added to DeviceHandle + EFI_ALREADY_STARTED - This driver is already running on DeviceHandle + other - This driver does not support this device + +--*/ +{ + USB_CBI_DEVICE *UsbCbiDev; + UINT8 Index; + EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + BOOLEAN Found; + + Found = FALSE; + // + // Check if the Controller supports USB IO protocol + // + UsbCbiDev = NULL; + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the controller interface descriptor + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + CBI1AtapiProtocol.CommandProtocol = InterfaceDescriptor.InterfaceSubClass; + + UsbCbiDev = AllocateZeroPool (sizeof (USB_CBI_DEVICE)); + if (UsbCbiDev == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + UsbCbiDev->Signature = USB_CBI_DEVICE_SIGNATURE; + UsbCbiDev->UsbIo = UsbIo; + CopyMem (&UsbCbiDev->InterfaceDescriptor, &InterfaceDescriptor, sizeof (InterfaceDescriptor)); + CopyMem (&UsbCbiDev->UsbAtapiProtocol , &CBI1AtapiProtocol, sizeof (CBI1AtapiProtocol)); + + // + // Get the Device Path Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &UsbCbiDev->DevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) { + UsbIo->UsbGetEndpointDescriptor ( + UsbIo, + Index, + &EndpointDescriptor + ); + + // + // We parse bulk endpoint + // + if (EndpointDescriptor.Attributes == 0x02) { + if (EndpointDescriptor.EndpointAddress & 0x80) { + CopyMem (&UsbCbiDev->BulkInEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + //UsbCbiDev->BulkInEndpointDescriptor = EndpointDescriptor; + } else { + CopyMem (&UsbCbiDev->BulkOutEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + //UsbCbiDev->BulkOutEndpointDescriptor = EndpointDescriptor; + } + + Found = TRUE; + } + // + // We parse interrupt endpoint + // + if (EndpointDescriptor.Attributes == 0x03) { + CopyMem (&UsbCbiDev->InterruptEndpointDescriptor, &EndpointDescriptor, sizeof(EndpointDescriptor)); + //UsbCbiDev->InterruptEndpointDescriptor = EndpointDescriptor; + Found = TRUE; + } + + } + // + // Double check we have these + // + if (!Found) { + goto ErrorExit; + } + // + // After installing Usb-Atapi protocol onto this handle + // it will be called by upper layer drivers such as Fat + // + Cbi1ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_ENABLE) + ); + + Status = gBS->InstallProtocolInterface ( + &ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + EFI_NATIVE_INTERFACE, + &UsbCbiDev->UsbAtapiProtocol + ); + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + return EFI_SUCCESS; + +ErrorExit: + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + if (UsbCbiDev != NULL) { + gBS->FreePool (UsbCbiDev); + } + + return Status; + +} + +STATIC +EFI_STATUS +EFIAPI +CBI1DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + EFI_SUCCESS - This driver is removed DeviceHandle + EFI_UNSUPPORTED - Can't open the gEfiUsbAtapiProtocolGuid protocol + other - This driver was not removed from this device + +--*/ +{ + EFI_STATUS Status; + EFI_USB_ATAPI_PROTOCOL *CBI1AtapiProtocol; + USB_CBI_DEVICE *UsbCbiDev; + EFI_USB_IO_PROTOCOL *UsbIo; + + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + (VOID **) &CBI1AtapiProtocol, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (CBI1AtapiProtocol); + + UsbIo = UsbCbiDev->UsbIo; + + Cbi1ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_DISABLE) + ); + + Status = gBS->UninstallProtocolInterface ( + ControllerHandle, + &gEfiUsbAtapiProtocolGuid, + &UsbCbiDev->UsbAtapiProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + gBS->FreePool (UsbCbiDev); + + return Status; + +} +// +// CBI1 command +// +STATIC +EFI_STATUS +CBI1CommandPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN VOID *Command, + IN UINT8 CommandSize, + OUT UINT32 *Result + ) +/*++ + + Routine Description: + In order to make consistence, CBI transportation protocol does only use + the first 3 parameters. Other parameters are not used here. + + Arguments: + UsbCbiDev - USB_CBI_DEVICE + Command - Command to send + CommandSize - Command Size + Result - Result to return + + Returns: + EFI_SUCCESS - This driver is removed DeviceHandle + other - This driver was not removed from this device +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_DEVICE_REQUEST Request; + UINT32 TimeOutInMilliSeconds; + + UsbIo = UsbCbiDev->UsbIo; + + ZeroMem (&Request, sizeof (EFI_USB_DEVICE_REQUEST)); + + // + // Device request see CBI specification + // + Request.RequestType = 0x21; + Request.Length = CommandSize; + + TimeOutInMilliSeconds = 1000; + + Status = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataOut, + TimeOutInMilliSeconds, + Command, + CommandSize, + Result + ); + + return Status; +} + +STATIC +EFI_STATUS +CBI1DataPhase ( + IN USB_CBI_DEVICE *UsbCbiDev, + IN UINT32 DataSize, + IN OUT VOID *DataBuffer, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 Timeout, + OUT UINT32 *Result + ) +/*++ + +Routine Description: + + CBI1 Data Phase + +Arguments: + + UsbCbiDev - USB_CBI_DEVICE + DataSize - Data Size + DataBuffer - Data Buffer + Direction - IN/OUT/NODATA + Timeout - Time out value in milliseconds + Result - Transfer result + +Returns: + + EFI_SUCCESS - Success + +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointAddr; + UINTN Remain; + UINTN Increment; + UINT32 MaxPacketLen; + UINT8 *BufferPtr; + + UsbIo = UsbCbiDev->UsbIo; + + Remain = DataSize; + BufferPtr = (UINT8 *) DataBuffer; + + // + // retrieve the the max packet length of the given endpoint + // + if (Direction == EfiUsbDataIn) { + MaxPacketLen = (UsbCbiDev->BulkInEndpointDescriptor).MaxPacketSize; + EndpointAddr = (UsbCbiDev->BulkInEndpointDescriptor).EndpointAddress; + } else { + MaxPacketLen = (UsbCbiDev->BulkOutEndpointDescriptor).MaxPacketSize; + EndpointAddr = (UsbCbiDev->BulkOutEndpointDescriptor).EndpointAddress; + } + + while (Remain > 0) { + // + // Using 15 packets to aVOID Bitstuff error + // + if (Remain > 15 * MaxPacketLen) { + Increment = 15 * MaxPacketLen; + } else { + Increment = Remain; + } + + Status = UsbIo->UsbBulkTransfer ( + UsbIo, + EndpointAddr, + BufferPtr, + &Increment, + Timeout, + Result + ); + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + BufferPtr += Increment; + Remain -= Increment; + } + + return EFI_SUCCESS; + +ErrorExit: + + if (Direction == EfiUsbDataIn) { + Cbi1ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_INPUT_ERROR) + ); + } else { + Cbi1ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_EC_OUTPUT_ERROR) + ); + } + + if (((*Result) & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + // + // just endpoint stall happens + // + UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + Result + ); + } + + return Status; +} +// +// CBI1 USB ATAPI Protocol +// +STATIC +EFI_STATUS +EFIAPI +CBI1MassStorageReset ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset CBI Devices + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - TRUE if we need to do strictly reset. + + Returns: + EFI_SUCCESS - Command succeeded. + EFI_DEVICE_ERROR - Command failed. + +--*/ +{ + UINT8 ResetCommand[12]; + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + USB_CBI_DEVICE *UsbCbiDev; + UINT8 EndpointAddr; + UINT32 Result; + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This); + UsbIo = UsbCbiDev->UsbIo; + + Cbi1ReportStatusCode ( + UsbCbiDev->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOVABLE_MEDIA | EFI_P_PC_RESET) + ); + + if (ExtendedVerification) { + UsbIo->UsbPortReset (UsbIo); + } + // + // CBI reset command protocol + // + SetMem (ResetCommand, sizeof (ResetCommand), 0xff); + ResetCommand[0] = 0x1d; + ResetCommand[1] = 0x04; + + Status = CBI1CommandPhase ( + UsbCbiDev, + ResetCommand, + 12, + &Result + ); + + // + // clear bulk in endpoint stall feature + // + EndpointAddr = UsbCbiDev->BulkInEndpointDescriptor.EndpointAddress; + UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + &Result + ); + + // + // clear bulk out endpoint stall feature + // + EndpointAddr = UsbCbiDev->BulkOutEndpointDescriptor.EndpointAddress; + UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + &Result + ); + + return EFI_SUCCESS; + +} + +STATIC +EFI_STATUS +EFIAPI +CBI1AtapiCommand ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds + ) +/*++ + + Routine Description: + Send ATAPI command using CBI1 protocol. + + Arguments: + This - Protocol instance pointer. + Command - Command buffer + CommandSize - Size of Command Buffer + DataBuffer - Data buffer + BufferLength - Length of Data buffer + Direction - Data direction of this command + TimeOutInMilliSeconds - Timeout value in ms + + Returns: + EFI_SUCCESS - Command succeeded. + EFI_DEVICE_ERROR - Command failed. + +--*/ +{ + EFI_STATUS Status; + USB_CBI_DEVICE *UsbCbiDev; + UINT32 Result; + UINT8 Index; + UINT8 MaxRetryNum; + + UsbCbiDev = USB_CBI_DEVICE_FROM_THIS (This); + + MaxRetryNum = 3; + + for (Index = 0; Index < MaxRetryNum; Index++) { + + // + // First send ATAPI command through CBI1 + // + Status = CBI1CommandPhase ( + UsbCbiDev, + Command, + CommandSize, + &Result + ); + if (EFI_ERROR (Status)) { + + switch (Result) { + + case EFI_USB_NOERROR: + case EFI_USB_ERR_STALL: + case EFI_USB_ERR_SYSTEM: + return EFI_DEVICE_ERROR; + + default: + continue; + break; + } + } else { + break; + } + } + + if (Index == MaxRetryNum) { + return EFI_DEVICE_ERROR; + } + + for (Index = 0; Index < MaxRetryNum; Index++) { + // + // Send/Get Data if there is a Data Stage + // + switch (Direction) { + + case EfiUsbDataIn: + case EfiUsbDataOut: + Status = CBI1DataPhase ( + UsbCbiDev, + BufferLength, + DataBuffer, + Direction, + TimeOutInMilliSeconds, + &Result + ); + + if (EFI_ERROR (Status)) { + switch (Result) { + + case EFI_USB_NOERROR: + case EFI_USB_ERR_STALL: + case EFI_USB_ERR_SYSTEM: + return EFI_DEVICE_ERROR; + + default: + continue; + break; + } + + } else { + + return EFI_SUCCESS; + } + break; + + case EfiUsbNoData: + return EFI_SUCCESS; + } + } + // + // If goes here, means met error. + // + return EFI_DEVICE_ERROR; +} + +VOID +Cbi1ReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ) +/*++ + + Routine Description: + Report Status Code in Usb Cbi1 Driver + + Arguments: + DevicePath - Use this to get Device Path + CodeType - Status Code Type + CodeValue - Status Code Value + + Returns: + None + +--*/ +{ + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + CodeType, + Value, + DevicePath + ); + +} diff --git a/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h new file mode 100644 index 0000000000..dfbe4d9886 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbCbi/Dxe/cbi.h @@ -0,0 +1,70 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + cbi.h + +Abstract: + + USB CBI transportation protocol definitions. +--*/ + +#ifndef _CBI_H +#define _CBI_H + + +#include + +#define bit(a) (1 << (a)) + +#define MASS_STORAGE_CLASS 0x08 +#define CBI0_INTERFACE_PROTOCOL 0x00 +#define CBI1_INTERFACE_PROTOCOL 0x01 + +// +// in millisecond unit +// +#define STALL_1_SECOND 1000 + +#pragma pack(1) +// +// Data block definition for transportation through interrupt endpoint +// +typedef struct { + UINT8 bType; + UINT8 bValue; +} INTERRUPT_DATA_BLOCK; + +#pragma pack() + +#define USB_CBI_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('u', 'c', 'b', 'i') + +// +// Device structure for CBI, interrupt endpoint may be not used in +// CBI1 Protocol +// +typedef struct { + UINT32 Signature; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_USB_ATAPI_PROTOCOL UsbAtapiProtocol; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR BulkInEndpointDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR BulkOutEndpointDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR InterruptEndpointDescriptor; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} USB_CBI_DEVICE; + +#define USB_CBI_DEVICE_FROM_THIS(a) \ + CR(a, USB_CBI_DEVICE, UsbAtapiProtocol, USB_CBI_DEVICE_SIGNATURE) + +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/ComponentName.c new file mode 100644 index 0000000000..3e139f9d9a --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/ComponentName.c @@ -0,0 +1,215 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "keyboard.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +UsbKeyboardComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UsbKeyboardComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gUsbKeyboardComponentName = { + UsbKeyboardComponentNameGetDriverName, + UsbKeyboardComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mUsbKeyboardDriverNameTable[] = { + { "eng", (CHAR16 *) L"Usb Keyboard Driver" }, + { NULL , NULL } +}; + + +EFI_STATUS +EFIAPI +UsbKeyboardComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gUsbKeyboardComponentName.SupportedLanguages, + mUsbKeyboardDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +UsbKeyboardComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + USB_KB_DEV *UsbKbDev; + EFI_SIMPLE_TEXT_IN_PROTOCOL *SimpleTxtIn; + EFI_USB_IO_PROTOCOL *UsbIoProtocol; + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Check Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIoProtocol, + gUsbKeyboardDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + gUsbKeyboardDriverBinding.DriverBindingHandle, + ControllerHandle + ); + + return EFI_UNSUPPORTED; + } + + if (Status != EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &SimpleTxtIn, + gUsbKeyboardDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + UsbKbDev = USB_KB_DEV_FROM_THIS (SimpleTxtIn); + + return LookupUnicodeString ( + Language, + gUsbKeyboardComponentName.SupportedLanguages, + UsbKbDev->ControllerNameTable, + ControllerName + ); + +} diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.mbd b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.mbd new file mode 100644 index 0000000000..ecb6af6c96 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.mbd @@ -0,0 +1,44 @@ + + + + + UsbKb + 2D2E62CF-9ECF-43b7-8219-94E7FC713DFE + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkUsbLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.msa b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.msa new file mode 100644 index 0000000000..0ff6464825 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/UsbKb.msa @@ -0,0 +1,77 @@ + + + + + UsbKb + DXE_DRIVER + BS_DRIVER + 2D2E62CF-9ECF-43b7-8219-94E7FC713DFE + 0 + Component description file for UsbKb module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + EdkUsbLib + ReportStatusCodeLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + + + efikey.h + keyboard.h + efikey.c + keyboard.c + ComponentName.c + + + MdePkg + EdkModulePkg + + + DevicePath + UsbIo + SimpleTextIn + + + + HotPlugDevice + + + + + + + + gUsbKeyboardDriverBinding + gUsbKeyboardComponentName + + + diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/build.xml new file mode 100644 index 0000000000..2608381d96 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.c b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.c new file mode 100644 index 0000000000..a9cdbc8760 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.c @@ -0,0 +1,772 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EfiKey.c + +Abstract: + + USB Keyboard Driver + +Revision History + +--*/ + +#include "efikey.h" +#include "keyboard.h" + +// +// Prototypes +// Driver model protocol interface +// +EFI_STATUS +EFIAPI +USBKeyboardDriverBindingEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +USBKeyboardDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +USBKeyboardDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +USBKeyboardDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Simple Text In Protocol Interface +// +STATIC +EFI_STATUS +EFIAPI +USBKeyboardReset ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +STATIC +EFI_STATUS +EFIAPI +USBKeyboardReadKeyStroke ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ); + +STATIC +VOID +EFIAPI +USBKeyboardWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// Helper functions +// +STATIC +EFI_STATUS +USBKeyboardCheckForKey ( + IN USB_KB_DEV *UsbKeyboardDevice + ); + +// +// USB Keyboard Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding = { + USBKeyboardDriverBindingSupported, + USBKeyboardDriverBindingStart, + USBKeyboardDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +USBKeyboardDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Supported. + + Arguments: + This - EFI_DRIVER_BINDING_PROTOCOL + Controller - Controller handle + RemainingDevicePath - EFI_DEVICE_PATH_PROTOCOL + Returns: + EFI_STATUS + +--*/ +{ + EFI_STATUS OpenStatus; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_STATUS Status; + + // + // Check if USB_IO protocol is attached on the controller handle. + // + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (OpenStatus)) { + return OpenStatus; + } + + // + // Use the USB I/O protocol interface to check whether the Controller is + // the Keyboard controller that can be managed by this driver. + // + Status = EFI_SUCCESS; + + if (!IsUSBKeyboard (UsbIo)) { + Status = EFI_UNSUPPORTED; + } + + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +USBKeyboardDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Start. + + Arguments: + This - EFI_DRIVER_BINDING_PROTOCOL + Controller - Controller handle + RemainingDevicePath - EFI_DEVICE_PATH_PROTOCOL + Returns: + EFI_SUCCESS - Success + EFI_OUT_OF_RESOURCES - Can't allocate memory + EFI_UNSUPPORTED - The Start routine fail +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + USB_KB_DEV *UsbKeyboardDevice; + UINT8 EndpointNumber; + EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + UINT8 Index; + UINT8 EndpointAddr; + UINT8 PollingInterval; + UINT8 PacketSize; + BOOLEAN Found; + + UsbKeyboardDevice = NULL; + Found = FALSE; + + // + // Open USB_IO Protocol + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + UsbKeyboardDevice = AllocateZeroPool (sizeof (USB_KB_DEV)); + if (UsbKeyboardDevice == NULL) { + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_OUT_OF_RESOURCES; + } + // + // Get the Device Path Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &UsbKeyboardDevice->DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (UsbKeyboardDevice); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + // + // Report that the usb keyboard is being enabled + // + KbdReportStatusCode ( + UsbKeyboardDevice->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_ENABLE) + ); + + // + // This is pretty close to keyboard detection, so log progress + // + KbdReportStatusCode ( + UsbKeyboardDevice->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_PRESENCE_DETECT) + ); + + // + // Initialize UsbKeyboardDevice + // + UsbKeyboardDevice->UsbIo = UsbIo; + + // + // Get interface & endpoint descriptor + // + UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &UsbKeyboardDevice->InterfaceDescriptor + ); + + EndpointNumber = UsbKeyboardDevice->InterfaceDescriptor.NumEndpoints; + + for (Index = 0; Index < EndpointNumber; Index++) { + + UsbIo->UsbGetEndpointDescriptor ( + UsbIo, + Index, + &EndpointDescriptor + ); + + if ((EndpointDescriptor.Attributes & 0x03) == 0x03) { + // + // We only care interrupt endpoint here + // + CopyMem (&UsbKeyboardDevice->IntEndpointDescriptor, &EndpointDescriptor, sizeof (EndpointDescriptor)); + //UsbKeyboardDevice->IntEndpointDescriptor = EndpointDescriptor; + Found = TRUE; + } + } + + if (!Found) { + // + // No interrupt endpoint found, then return unsupported. + // + gBS->FreePool (UsbKeyboardDevice); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return EFI_UNSUPPORTED; + } + + UsbKeyboardDevice->Signature = USB_KB_DEV_SIGNATURE; + UsbKeyboardDevice->SimpleInput.Reset = USBKeyboardReset; + UsbKeyboardDevice->SimpleInput.ReadKeyStroke = USBKeyboardReadKeyStroke; + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_WAIT, + EFI_TPL_NOTIFY, + USBKeyboardWaitForKey, + UsbKeyboardDevice, + &(UsbKeyboardDevice->SimpleInput.WaitForKey) + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (UsbKeyboardDevice); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + // + // Install simple txt in protocol interface + // for the usb keyboard device. + // Usb keyboard is a hot plug device, and expected to work immediately + // when plugging into system, so a HotPlugDeviceGuid is installed onto + // the usb keyboard device handle, to distinguish it from other conventional + // console devices. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimpleTextInProtocolGuid, + &UsbKeyboardDevice->SimpleInput, + &gEfiHotPlugDeviceGuid, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey); + gBS->FreePool (UsbKeyboardDevice); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + // + // Reset USB Keyboard Device + // + Status = UsbKeyboardDevice->SimpleInput.Reset ( + &UsbKeyboardDevice->SimpleInput, + TRUE + ); + if (EFI_ERROR (Status)) { + gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiSimpleTextInProtocolGuid, + &UsbKeyboardDevice->SimpleInput, + &gEfiHotPlugDeviceGuid, + NULL, + NULL + ); + gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey); + gBS->FreePool (UsbKeyboardDevice); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + // + // submit async interrupt transfer + // + EndpointAddr = UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress; + PollingInterval = UsbKeyboardDevice->IntEndpointDescriptor.Interval; + PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize); + + Status = UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + EndpointAddr, + TRUE, + PollingInterval, + PacketSize, + KeyboardHandler, + UsbKeyboardDevice + ); + + if (EFI_ERROR (Status)) { + + gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiSimpleTextInProtocolGuid, + &UsbKeyboardDevice->SimpleInput, + &gEfiHotPlugDeviceGuid, + NULL, + NULL + ); + gBS->CloseEvent (UsbKeyboardDevice->SimpleInput.WaitForKey); + gBS->FreePool (UsbKeyboardDevice); + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + UsbKeyboardDevice->ControllerNameTable = NULL; + AddUnicodeString ( + "eng", + gUsbKeyboardComponentName.SupportedLanguages, + &UsbKeyboardDevice->ControllerNameTable, + (CHAR16 *) L"Generic Usb Keyboard" + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +USBKeyboardDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop. + + Arguments: + This - EFI_DRIVER_BINDING_PROTOCOL + Controller - Controller handle + NumberOfChildren - Child handle number + ChildHandleBuffer - Child handle buffer + Returns: + EFI_SUCCESS - Success + EFI_UNSUPPORTED - Can't support +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_IN_PROTOCOL *SimpleInput; + USB_KB_DEV *UsbKeyboardDevice; + EFI_USB_IO_PROTOCOL *UsbIo; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &SimpleInput, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Get USB_KB_DEV instance. + // + UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (SimpleInput); + + gBS->CloseProtocol ( + Controller, + &gEfiSimpleTextInProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + UsbIo = UsbKeyboardDevice->UsbIo; + // + // Uninstall the Asyn Interrupt Transfer from this device + // will disable the key data input from this device + // + KbdReportStatusCode ( + UsbKeyboardDevice->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_DISABLE) + ); + + // + // Destroy asynchronous interrupt transfer + // + UsbKeyboardDevice->UsbIo->UsbAsyncInterruptTransfer ( + UsbKeyboardDevice->UsbIo, + UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress, + FALSE, + UsbKeyboardDevice->IntEndpointDescriptor.Interval, + 0, + NULL, + NULL + ); + + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiSimpleTextInProtocolGuid, + &UsbKeyboardDevice->SimpleInput, + &gEfiHotPlugDeviceGuid, + NULL, + NULL + ); + // + // free all the resources. + // + gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer); + gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent); + gBS->CloseEvent ((UsbKeyboardDevice->SimpleInput).WaitForKey); + + if (UsbKeyboardDevice->ControllerNameTable != NULL) { + FreeUnicodeStringTable (UsbKeyboardDevice->ControllerNameTable); + } + + gBS->FreePool (UsbKeyboardDevice); + + return Status; + +} + + +EFI_STATUS +EFIAPI +USBKeyboardReset ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Implements EFI_SIMPLE_TEXT_IN_PROTOCOL.Reset() function. + + Arguments: + This The EFI_SIMPLE_TEXT_IN_PROTOCOL instance. + ExtendedVerification + Indicates that the driver may perform a more exhaustive + verification operation of the device during reset. + + Returns: + EFI_SUCCESS - Success + EFI_DEVICE_ERROR - Hardware Error +--*/ +{ + EFI_STATUS Status; + USB_KB_DEV *UsbKeyboardDevice; + EFI_USB_IO_PROTOCOL *UsbIo; + + UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This); + + UsbIo = UsbKeyboardDevice->UsbIo; + + KbdReportStatusCode ( + UsbKeyboardDevice->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_KEYBOARD | EFI_P_PC_RESET) + ); + + // + // Non Exhaustive reset: + // only reset private data structures. + // + if (!ExtendedVerification) { + // + // Clear the key buffer of this Usb keyboard + // + KbdReportStatusCode ( + UsbKeyboardDevice->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_CLEAR_BUFFER) + ); + + InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer)); + UsbKeyboardDevice->CurKeyChar = 0; + return EFI_SUCCESS; + } + + // + // Exhaustive reset + // + Status = InitUSBKeyboard (UsbKeyboardDevice); + UsbKeyboardDevice->CurKeyChar = 0; + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +USBKeyboardReadKeyStroke ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +/*++ + + Routine Description: + Implements EFI_SIMPLE_TEXT_IN_PROTOCOL.ReadKeyStroke() function. + + Arguments: + This The EFI_SIMPLE_TEXT_IN_PROTOCOL instance. + Key A pointer to a buffer that is filled in with the keystroke + information for the key that was pressed. + + Returns: + EFI_SUCCESS - Success +--*/ +{ + USB_KB_DEV *UsbKeyboardDevice; + EFI_STATUS Status; + UINT8 KeyChar; + + UsbKeyboardDevice = USB_KB_DEV_FROM_THIS (This); + + // + // if there is no saved ASCII byte, fetch it + // by calling USBKeyboardCheckForKey(). + // + if (UsbKeyboardDevice->CurKeyChar == 0) { + Status = USBKeyboardCheckForKey (UsbKeyboardDevice); + if (EFI_ERROR (Status)) { + return Status; + } + } + + Key->UnicodeChar = 0; + Key->ScanCode = SCAN_NULL; + + KeyChar = UsbKeyboardDevice->CurKeyChar; + + UsbKeyboardDevice->CurKeyChar = 0; + + // + // Translate saved ASCII byte into EFI_INPUT_KEY + // + Status = USBKeyCodeToEFIScanCode (UsbKeyboardDevice, KeyChar, Key); + + return Status; + +} + +STATIC +VOID +EFIAPI +USBKeyboardWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + + Routine Description: + Handler function for WaitForKey event. + + Arguments: + Event Event to be signaled when a key is pressed. + Context Points to USB_KB_DEV instance. + + Returns: + VOID +--*/ +{ + USB_KB_DEV *UsbKeyboardDevice; + + UsbKeyboardDevice = (USB_KB_DEV *) Context; + + if (UsbKeyboardDevice->CurKeyChar == 0) { + + if (EFI_ERROR (USBKeyboardCheckForKey (UsbKeyboardDevice))) { + return ; + } + } + // + // If has key pending, signal the event. + // + gBS->SignalEvent (Event); +} + + +STATIC +EFI_STATUS +USBKeyboardCheckForKey ( + IN USB_KB_DEV *UsbKeyboardDevice + ) +/*++ + + Routine Description: + Check whether there is key pending. + + Arguments: + UsbKeyboardDevice The USB_KB_DEV instance. + + Returns: + EFI_SUCCESS - Success +--*/ +{ + EFI_STATUS Status; + UINT8 KeyChar; + + // + // Fetch raw data from the USB keyboard input, + // and translate it into ASCII data. + // + Status = USBParseKey (UsbKeyboardDevice, &KeyChar); + if (EFI_ERROR (Status)) { + return Status; + } + + UsbKeyboardDevice->CurKeyChar = KeyChar; + return EFI_SUCCESS; +} + +VOID +KbdReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ) +/*++ + + Routine Description: + Report Status Code in Usb Bot Driver + + Arguments: + DevicePath - Use this to get Device Path + CodeType - Status Code Type + CodeValue - Status Code Value + + Returns: + None + +--*/ +{ + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + CodeType, + Value, + DevicePath + ); +} diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.h b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.h new file mode 100644 index 0000000000..bf9f47732d --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/efikey.h @@ -0,0 +1,118 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + EfiKey.h + +Abstract: + + Header file for USB Keyboard Driver's Data Structures + +Revision History +--*/ +#ifndef _USB_KB_H +#define _USB_KB_H + + +#include + +#define MAX_KEY_ALLOWED 32 + +#define HZ 1000 * 1000 * 10 +#define USBKBD_REPEAT_DELAY ((HZ) / 2) +#define USBKBD_REPEAT_RATE ((HZ) / 50) + +#define CLASS_HID 3 +#define SUBCLASS_BOOT 1 +#define PROTOCOL_KEYBOARD 1 + +#define BOOT_PROTOCOL 0 +#define REPORT_PROTOCOL 1 + +typedef struct { + UINT8 Down; + UINT8 KeyCode; +} USB_KEY; + +typedef struct { + USB_KEY buffer[MAX_KEY_ALLOWED + 1]; + UINT8 bHead; + UINT8 bTail; +} USB_KB_BUFFER; + +#define USB_KB_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'k', 'b', 'd') +typedef struct { + UINTN Signature; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_EVENT DelayedRecoveryEvent; + EFI_SIMPLE_TEXT_IN_PROTOCOL SimpleInput; + EFI_USB_IO_PROTOCOL *UsbIo; + + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR IntEndpointDescriptor; + + USB_KB_BUFFER KeyboardBuffer; + UINT8 CtrlOn; + UINT8 AltOn; + UINT8 ShiftOn; + UINT8 NumLockOn; + UINT8 CapsOn; + UINT8 LastKeyCodeArray[8]; + UINT8 CurKeyChar; + + UINT8 RepeatKey; + EFI_EVENT RepeatTimer; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + +} USB_KB_DEV; + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gUsbKeyboardDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gUsbKeyboardComponentName; +extern EFI_GUID gEfiUsbKeyboardDriverGuid; + +VOID +KbdReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ); + +#define USB_KB_DEV_FROM_THIS(a) \ + CR(a, USB_KB_DEV, SimpleInput, USB_KB_DEV_SIGNATURE) + +#define MOD_CONTROL_L 0x01 +#define MOD_CONTROL_R 0x10 +#define MOD_SHIFT_L 0x02 +#define MOD_SHIFT_R 0x20 +#define MOD_ALT_L 0x04 +#define MOD_ALT_R 0x40 +#define MOD_WIN_L 0x08 +#define MOD_WIN_R 0x80 + +typedef struct { + UINT8 Mask; + UINT8 Key; +} KB_MODIFIER; + +#define USB_KEYCODE_MAX_MAKE 0x64 + +#define USBKBD_VALID_KEYCODE(key) ((UINT8) (key) > 3) + +typedef struct { + UINT8 NumLock : 1; + UINT8 CapsLock : 1; + UINT8 Resrvd : 6; +} LED_MAP; +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.c b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.c new file mode 100644 index 0000000000..1328e6a098 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.c @@ -0,0 +1,1150 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Keyboard.c + +Abstract: + + Helper functions for USB Keyboard Driver + +Revision History + +--*/ + +#include "keyboard.h" + +// +// USB Key Code to Efi key mapping table +// Format:, , +// +STATIC +UINT8 KeyConvertionTable[USB_KEYCODE_MAX_MAKE][3] = { + { SCAN_NULL, 'a', 'A' }, // 0x04 + { SCAN_NULL, 'b', 'B' }, // 0x05 + { SCAN_NULL, 'c', 'C' }, // 0x06 + { SCAN_NULL, 'd', 'D' }, // 0x07 + { SCAN_NULL, 'e', 'E' }, // 0x08 + { SCAN_NULL, 'f', 'F' }, // 0x09 + { SCAN_NULL, 'g', 'G' }, // 0x0A + { SCAN_NULL, 'h', 'H' }, // 0x0B + { SCAN_NULL, 'i', 'I' }, // 0x0C + { SCAN_NULL, 'j', 'J' }, // 0x0D + { SCAN_NULL, 'k', 'K' }, // 0x0E + { SCAN_NULL, 'l', 'L' }, // 0x0F + { SCAN_NULL, 'm', 'M' }, // 0x10 + { SCAN_NULL, 'n', 'N' }, // 0x11 + { SCAN_NULL, 'o', 'O' }, // 0x12 + { SCAN_NULL, 'p', 'P' }, // 0x13 + { SCAN_NULL, 'q', 'Q' }, // 0x14 + { SCAN_NULL, 'r', 'R' }, // 0x15 + { SCAN_NULL, 's', 'S' }, // 0x16 + { SCAN_NULL, 't', 'T' }, // 0x17 + { SCAN_NULL, 'u', 'U' }, // 0x18 + { SCAN_NULL, 'v', 'V' }, // 0x19 + { SCAN_NULL, 'w', 'W' }, // 0x1A + { SCAN_NULL, 'x', 'X' }, // 0x1B + { SCAN_NULL, 'y', 'Y' }, // 0x1C + { SCAN_NULL, 'z', 'Z' }, // 0x1D + { SCAN_NULL, '1', '!' }, // 0x1E + { SCAN_NULL, '2', '@' }, // 0x1F + { SCAN_NULL, '3', '#' }, // 0x20 + { SCAN_NULL, '4', '$' }, // 0x21 + { SCAN_NULL, '5', '%' }, // 0x22 + { SCAN_NULL, '6', '^' }, // 0x23 + { SCAN_NULL, '7', '&' }, // 0x24 + { SCAN_NULL, '8', '*' }, // 0x25 + { SCAN_NULL, '9', '(' }, // 0x26 + { SCAN_NULL, '0', ')' }, // 0x27 + { SCAN_NULL, 0x0d, 0x0d }, // 0x28 Enter + { SCAN_ESC, 0x00, 0x00 }, // 0x29 Esc + { SCAN_NULL, 0x08, 0x08 }, // 0x2A Backspace + { SCAN_NULL, 0x09, 0x09 }, // 0x2B Tab + { SCAN_NULL, ' ', ' ' }, // 0x2C Spacebar + { SCAN_NULL, '-', '_' }, // 0x2D + { SCAN_NULL, '=', '+' }, // 0x2E + { SCAN_NULL, '[', '{' }, // 0x2F + { SCAN_NULL, ']', '}' }, // 0x30 + { SCAN_NULL, '\\', '|' }, // 0x31 + { SCAN_NULL, '\\', '|' }, // 0x32 Keyboard US \ and | + { SCAN_NULL, ';', ':' }, // 0x33 + { SCAN_NULL, '\'', '"' }, // 0x34 + { SCAN_NULL, '`', '~' }, // 0x35 Keyboard Grave Accent and Tlide + { SCAN_NULL, ',', '<' }, // 0x36 + { SCAN_NULL, '.', '>' }, // 0x37 + { SCAN_NULL, '/', '?' }, // 0x38 + { SCAN_NULL, 0x00, 0x00 }, // 0x39 CapsLock + { SCAN_F1, 0x00, 0x00 }, // 0x3A + { SCAN_F2, 0x00, 0x00 }, // 0x3B + { SCAN_F3, 0x00, 0x00 }, // 0x3C + { SCAN_F4, 0x00, 0x00 }, // 0x3D + { SCAN_F5, 0x00, 0x00 }, // 0x3E + { SCAN_F6, 0x00, 0x00 }, // 0x3F + { SCAN_F7, 0x00, 0x00 }, // 0x40 + { SCAN_F8, 0x00, 0x00 }, // 0x41 + { SCAN_F9, 0x00, 0x00 }, // 0x42 + { SCAN_F10, 0x00, 0x00 }, // 0x43 + { SCAN_NULL, 0x00, 0x00 }, // 0x44 F11 + { SCAN_NULL, 0x00, 0x00 }, // 0x45 F12 + { SCAN_NULL, 0x00, 0x00 }, // 0x46 PrintScreen + { SCAN_NULL, 0x00, 0x00 }, // 0x47 Scroll Lock + { SCAN_NULL, 0x00, 0x00 }, // 0x48 Pause + { SCAN_INSERT, 0x00, 0x00 }, // 0x49 + { SCAN_HOME, 0x00, 0x00 }, // 0x4A + { SCAN_PAGE_UP, 0x00, 0x00 }, // 0x4B + { SCAN_DELETE, 0x00, 0x00 }, // 0x4C + { SCAN_END, 0x00, 0x00 }, // 0x4D + { SCAN_PAGE_DOWN, 0x00, 0x00 }, // 0x4E + { SCAN_RIGHT, 0x00, 0x00 }, // 0x4F + { SCAN_LEFT, 0x00, 0x00 }, // 0x50 + { SCAN_DOWN, 0x00, 0x00 }, // 0x51 + { SCAN_UP, 0x00, 0x00 }, // 0x52 + { SCAN_NULL, 0x00, 0x00 }, // 0x53 NumLock + { SCAN_NULL, '/', '/' }, // 0x54 + { SCAN_NULL, '*', '*' }, // 0x55 + { SCAN_NULL, '-', '-' }, // 0x56 + { SCAN_NULL, '+', '+' }, // 0x57 + { SCAN_NULL, 0x0d, 0x0d }, // 0x58 + { SCAN_END, '1', '1' }, // 0x59 + { SCAN_DOWN, '2', '2' }, // 0x5A + { SCAN_PAGE_DOWN, '3', '3' }, // 0x5B + { SCAN_LEFT, '4', '4' }, // 0x5C + { SCAN_NULL, '5', '5' }, // 0x5D + { SCAN_RIGHT, '6', '6' }, // 0x5E + { SCAN_HOME, '7', '7' }, // 0x5F + { SCAN_UP, '8', '8' }, // 0x60 + { SCAN_PAGE_UP, '9', '9' }, // 0x61 + { SCAN_INSERT, '0', '0' }, // 0x62 + { SCAN_DELETE, '.', '.' }, // 0x63 + { SCAN_NULL, '\\', '|' }, // 0x64 Keyboard Non-US \ and | + { SCAN_NULL, 0x00, 0x00 }, // 0x65 Keyboard Application + { SCAN_NULL, 0x00, 0x00 }, // 0x66 Keyboard Power + { SCAN_NULL, '=' , '=' } // 0x67 Keypad = +}; + +STATIC KB_MODIFIER KB_Mod[8] = { + { MOD_CONTROL_L, 0xe0 }, // 11100000 + { MOD_CONTROL_R, 0xe4 }, // 11100100 + { MOD_SHIFT_L, 0xe1 }, // 11100001 + { MOD_SHIFT_R, 0xe5 }, // 11100101 + { MOD_ALT_L, 0xe2 }, // 11100010 + { MOD_ALT_R, 0xe6 }, // 11100110 + { MOD_WIN_L, 0xe3 }, // 11100011 + { MOD_WIN_R, 0xe7 } // 11100111 +}; + + +BOOLEAN +IsUSBKeyboard ( + IN EFI_USB_IO_PROTOCOL *UsbIo + ) +/*++ + + Routine Description: + Uses USB I/O to check whether the device is a USB Keyboard device. + + Arguments: + UsbIo: Points to a USB I/O protocol instance. + + Returns: + +--*/ +{ + EFI_STATUS Status; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + + // + // Get the Default interface descriptor, currently we + // assume it is interface 1 + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + + if (EFI_ERROR (Status)) { + return FALSE; + } + + if (InterfaceDescriptor.InterfaceClass == CLASS_HID && + InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT && + InterfaceDescriptor.InterfaceProtocol == PROTOCOL_KEYBOARD + ) { + + return TRUE; + } + + return FALSE; +} + + +EFI_STATUS +InitUSBKeyboard ( + IN USB_KB_DEV *UsbKeyboardDevice + ) +/*++ + + Routine Description: + Initialize USB Keyboard device and all private data structures. + + Arguments: + UsbKeyboardDevice The USB_KB_DEV instance. + + Returns: + EFI_SUCCESS - Success + EFI_DEVICE_ERROR - Hardware Error +--*/ +{ + UINT8 ConfigValue; + UINT8 Protocol; + UINT8 ReportId; + UINT8 Duration; + EFI_STATUS Status; + UINT32 TransferResult; + EFI_USB_IO_PROTOCOL *UsbIo; + + UsbIo = UsbKeyboardDevice->UsbIo; + + KbdReportStatusCode ( + UsbKeyboardDevice->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_KEYBOARD | EFI_P_KEYBOARD_PC_SELF_TEST) + ); + + InitUSBKeyBuffer (&(UsbKeyboardDevice->KeyboardBuffer)); + + // + // default configurations + // + ConfigValue = 0x01; + + // + // Uses default configuration to configure the USB Keyboard device. + // + Status = UsbSetDeviceConfiguration ( + UsbKeyboardDevice->UsbIo, + (UINT16) ConfigValue, + &TransferResult + ); + if (EFI_ERROR (Status)) { + // + // If configuration could not be set here, it means + // the keyboard interface has some errors and could + // not be initialized + // + KbdReportStatusCode ( + UsbKeyboardDevice->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INTERFACE_ERROR) + ); + + return EFI_DEVICE_ERROR; + } + + UsbGetProtocolRequest ( + UsbKeyboardDevice->UsbIo, + UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber, + &Protocol + ); + // + // Sets boot protocol for the USB Keyboard. + // This driver only supports boot protocol. + // !!BugBug: How about the device that does not support boot protocol? + // + if (Protocol != BOOT_PROTOCOL) { + UsbSetProtocolRequest ( + UsbKeyboardDevice->UsbIo, + UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber, + BOOT_PROTOCOL + ); + } + // + // the duration is indefinite, so the endpoint will inhibit reporting forever, + // and only reporting when a change is detected in the report data. + // + + // + // idle value for all report ID + // + ReportId = 0; + // + // idle forever until there is a key pressed and released. + // + Duration = 0; + UsbSetIdleRequest ( + UsbKeyboardDevice->UsbIo, + UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber, + ReportId, + Duration + ); + + UsbKeyboardDevice->CtrlOn = 0; + UsbKeyboardDevice->AltOn = 0; + UsbKeyboardDevice->ShiftOn = 0; + UsbKeyboardDevice->NumLockOn = 0; + UsbKeyboardDevice->CapsOn = 0; + ZeroMem (UsbKeyboardDevice->LastKeyCodeArray, sizeof (UINT8) * 8); + + // + // Set a timer for repeat keys' generation. + // + if (UsbKeyboardDevice->RepeatTimer) { + gBS->CloseEvent (UsbKeyboardDevice->RepeatTimer); + UsbKeyboardDevice->RepeatTimer = 0; + } + + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_NOTIFY, + USBKeyboardRepeatHandler, + UsbKeyboardDevice, + &UsbKeyboardDevice->RepeatTimer + ); + + if (UsbKeyboardDevice->DelayedRecoveryEvent) { + gBS->CloseEvent (UsbKeyboardDevice->DelayedRecoveryEvent); + UsbKeyboardDevice->DelayedRecoveryEvent = 0; + } + + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_NOTIFY, + USBKeyboardRecoveryHandler, + UsbKeyboardDevice, + &UsbKeyboardDevice->DelayedRecoveryEvent + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +KeyboardHandler ( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context, + IN UINT32 Result + ) +/*++ + + Routine Description: + Handler function for USB Keyboard's asynchronous interrupt transfer. + + Arguments: + Data A pointer to a buffer that is filled with key data which is + retrieved via asynchronous interrupt transfer. + DataLength Indicates the size of the data buffer. + Context Pointing to USB_KB_DEV instance. + Result Indicates the result of the asynchronous interrupt transfer. + + Returns: + EFI_SUCCESS - Success + EFI_DEVICE_ERROR - Hardware Error +--*/ +{ + USB_KB_DEV *UsbKeyboardDevice; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 *CurKeyCodeBuffer; + UINT8 *OldKeyCodeBuffer; + UINT8 CurModifierMap; + UINT8 OldModifierMap; + UINT8 Index; + UINT8 Index2; + BOOLEAN Down; + EFI_STATUS Status; + BOOLEAN KeyRelease; + BOOLEAN KeyPress; + UINT8 SavedTail; + USB_KEY UsbKey; + UINT8 NewRepeatKey; + UINT32 UsbStatus; + UINT8 *DataPtr; + + ASSERT (Context); + + NewRepeatKey = 0; + DataPtr = (UINT8 *) Data; + UsbKeyboardDevice = (USB_KB_DEV *) Context; + UsbIo = UsbKeyboardDevice->UsbIo; + + // + // Analyzes the Result and performs corresponding action. + // + if (Result != EFI_USB_NOERROR) { + // + // Some errors happen during the process + // + KbdReportStatusCode ( + UsbKeyboardDevice->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_KEYBOARD | EFI_P_EC_INPUT_ERROR) + ); + + // + // stop the repeat key generation if any + // + UsbKeyboardDevice->RepeatKey = 0; + + gBS->SetTimer ( + UsbKeyboardDevice->RepeatTimer, + TimerCancel, + USBKBD_REPEAT_RATE + ); + + if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + UsbClearEndpointHalt ( + UsbIo, + UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress, + &UsbStatus + ); + } + + // + // Delete & Submit this interrupt again + // + + Status = UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress, + FALSE, + 0, + 0, + NULL, + NULL + ); + + gBS->SetTimer ( + UsbKeyboardDevice->DelayedRecoveryEvent, + TimerRelative, + EFI_USB_INTERRUPT_DELAY + ); + + return EFI_DEVICE_ERROR; + } + + if (DataLength == 0 || Data == NULL) { + return EFI_SUCCESS; + } + + CurKeyCodeBuffer = (UINT8 *) Data; + OldKeyCodeBuffer = UsbKeyboardDevice->LastKeyCodeArray; + + // + // checks for new key stroke. + // if no new key got, return immediately. + // + for (Index = 0; Index < 8; Index++) { + if (OldKeyCodeBuffer[Index] != CurKeyCodeBuffer[Index]) { + break; + } + } + + if (Index == 8) { + return EFI_SUCCESS; + } + + // + // Parse the modifier key + // + CurModifierMap = CurKeyCodeBuffer[0]; + OldModifierMap = OldKeyCodeBuffer[0]; + + // + // handle modifier key's pressing or releasing situation. + // + for (Index = 0; Index < 8; Index++) { + + if ((CurModifierMap & KB_Mod[Index].Mask) != (OldModifierMap & KB_Mod[Index].Mask)) { + // + // if current modifier key is up, then + // CurModifierMap & KB_Mod[Index].Mask = 0; + // otherwize it is a non-zero value. + // Inserts the pressed modifier key into key buffer. + // + Down = (UINT8) (CurModifierMap & KB_Mod[Index].Mask); + InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), KB_Mod[Index].Key, Down); + } + } + + // + // handle normal key's releasing situation + // + KeyRelease = FALSE; + for (Index = 2; Index < 8; Index++) { + + if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index])) { + continue; + } + + KeyRelease = TRUE; + for (Index2 = 2; Index2 < 8; Index2++) { + + if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index2])) { + continue; + } + + if (OldKeyCodeBuffer[Index] == CurKeyCodeBuffer[Index2]) { + KeyRelease = FALSE; + break; + } + } + + if (KeyRelease) { + InsertKeyCode ( + &(UsbKeyboardDevice->KeyboardBuffer), + OldKeyCodeBuffer[Index], + 0 + ); + // + // the original reapeat key is released. + // + if (OldKeyCodeBuffer[Index] == UsbKeyboardDevice->RepeatKey) { + UsbKeyboardDevice->RepeatKey = 0; + } + } + } + + // + // original repeat key is released, cancel the repeat timer + // + if (UsbKeyboardDevice->RepeatKey == 0) { + gBS->SetTimer ( + UsbKeyboardDevice->RepeatTimer, + TimerCancel, + USBKBD_REPEAT_RATE + ); + } + + // + // handle normal key's pressing situation + // + KeyPress = FALSE; + for (Index = 2; Index < 8; Index++) { + + if (!USBKBD_VALID_KEYCODE (CurKeyCodeBuffer[Index])) { + continue; + } + + KeyPress = TRUE; + for (Index2 = 2; Index2 < 8; Index2++) { + + if (!USBKBD_VALID_KEYCODE (OldKeyCodeBuffer[Index2])) { + continue; + } + + if (CurKeyCodeBuffer[Index] == OldKeyCodeBuffer[Index2]) { + KeyPress = FALSE; + break; + } + } + + if (KeyPress) { + InsertKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), CurKeyCodeBuffer[Index], 1); + // + // NumLock pressed or CapsLock pressed + // + if (CurKeyCodeBuffer[Index] == 0x53 || CurKeyCodeBuffer[Index] == 0x39) { + UsbKeyboardDevice->RepeatKey = 0; + } else { + NewRepeatKey = CurKeyCodeBuffer[Index]; + // + // do not repeat the original repeated key + // + UsbKeyboardDevice->RepeatKey = 0; + } + } + } + + // + // Update LastKeycodeArray[] buffer in the + // Usb Keyboard Device data structure. + // + for (Index = 0; Index < 8; Index++) { + UsbKeyboardDevice->LastKeyCodeArray[Index] = CurKeyCodeBuffer[Index]; + } + + // + // pre-process KeyboardBuffer, pop out the ctrl,alt,del key in sequence + // and judge whether it will invoke reset event. + // + SavedTail = UsbKeyboardDevice->KeyboardBuffer.bTail; + Index = UsbKeyboardDevice->KeyboardBuffer.bHead; + while (Index != SavedTail) { + RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey); + + switch (UsbKey.KeyCode) { + + case 0xe0: + case 0xe4: + if (UsbKey.Down) { + UsbKeyboardDevice->CtrlOn = 1; + } else { + UsbKeyboardDevice->CtrlOn = 0; + } + break; + + case 0xe2: + case 0xe6: + if (UsbKey.Down) { + UsbKeyboardDevice->AltOn = 1; + } else { + UsbKeyboardDevice->AltOn = 0; + } + break; + + // + // Del Key Code + // + case 0x4c: + case 0x63: + if (UsbKey.Down) { + if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) { + gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); + } + } + break; + + default: + break; + } + + // + // insert the key back to the buffer. + // so the key sequence will not be destroyed. + // + InsertKeyCode ( + &(UsbKeyboardDevice->KeyboardBuffer), + UsbKey.KeyCode, + UsbKey.Down + ); + Index = UsbKeyboardDevice->KeyboardBuffer.bHead; + + } + // + // If have new key pressed, update the RepeatKey value, and set the + // timer to repeate delay timer + // + if (NewRepeatKey != 0) { + // + // sets trigger time to "Repeat Delay Time", + // to trigger the repeat timer when the key is hold long + // enough time. + // + gBS->SetTimer ( + UsbKeyboardDevice->RepeatTimer, + TimerRelative, + USBKBD_REPEAT_DELAY + ); + UsbKeyboardDevice->RepeatKey = NewRepeatKey; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +USBParseKey ( + IN OUT USB_KB_DEV *UsbKeyboardDevice, + OUT UINT8 *KeyChar + ) +/*++ + + Routine Description: + Retrieves a key character after parsing the raw data in keyboard buffer. + + Arguments: + UsbKeyboardDevice The USB_KB_DEV instance. + KeyChar Points to the Key character after key parsing. + + Returns: + EFI_SUCCESS - Success + EFI_NOT_READY - Device is not ready +--*/ +{ + USB_KEY UsbKey; + + *KeyChar = 0; + + while (!IsUSBKeyboardBufferEmpty (&UsbKeyboardDevice->KeyboardBuffer)) { + // + // pops one raw data off. + // + RemoveKeyCode (&(UsbKeyboardDevice->KeyboardBuffer), &UsbKey); + + if (!UsbKey.Down) { + switch (UsbKey.KeyCode) { + + case 0xe0: + case 0xe4: + UsbKeyboardDevice->CtrlOn = 0; + break; + + case 0xe1: + case 0xe5: + UsbKeyboardDevice->ShiftOn = 0; + break; + + case 0xe2: + case 0xe6: + UsbKeyboardDevice->AltOn = 0; + break; + + default: + break; + } + + continue; + } + + // + // Analyzes key pressing situation + // + switch (UsbKey.KeyCode) { + + case 0xe0: + case 0xe4: + UsbKeyboardDevice->CtrlOn = 1; + continue; + break; + + case 0xe1: + case 0xe5: + UsbKeyboardDevice->ShiftOn = 1; + continue; + break; + + case 0xe2: + case 0xe6: + UsbKeyboardDevice->AltOn = 1; + continue; + break; + + case 0xe3: + case 0xe7: + continue; + break; + + case 0x53: + UsbKeyboardDevice->NumLockOn ^= 1; + SetKeyLED (UsbKeyboardDevice); + continue; + break; + + case 0x39: + UsbKeyboardDevice->CapsOn ^= 1; + SetKeyLED (UsbKeyboardDevice); + continue; + break; + + // + // F11,F12,PrintScreen,ScrollLock,Pause,Application,Power + // keys are not valid EFI key + // + case 0x44: + // + // fall through + // + case 0x45: + // + // fall through + // + case 0x46: + // + // fall through + // + case 0x47: + // + // fall through + // + case 0x48: + // + // fall through + // + case 0x65: + case 0x66: + continue; + break; + + default: + break; + } + + // + // When encountered Del Key... + // + if (UsbKey.KeyCode == 0x4c || UsbKey.KeyCode == 0x63) { + if (UsbKeyboardDevice->CtrlOn && UsbKeyboardDevice->AltOn) { + gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); + } + } + + *KeyChar = UsbKey.KeyCode; + return EFI_SUCCESS; + } + + return EFI_NOT_READY; + +} + + +EFI_STATUS +USBKeyCodeToEFIScanCode ( + IN USB_KB_DEV *UsbKeyboardDevice, + IN UINT8 KeyChar, + OUT EFI_INPUT_KEY *Key + ) +/*++ + + Routine Description: + Converts USB Keyboard code to EFI Scan Code. + + Arguments: + UsbKeyboardDevice The USB_KB_DEV instance. + KeyChar Indicates the key code that will be interpreted. + Key A pointer to a buffer that is filled in with + the keystroke information for the key that + was pressed. + Returns: + EFI_NOT_READY - Device is not ready + EFI_SUCCESS - Success +--*/ +{ + UINT8 Index; + + if (!USBKBD_VALID_KEYCODE (KeyChar)) { + return EFI_NOT_READY; + } + + // + // valid USB Key Code starts from 4 + // + Index = (UINT8) (KeyChar - 4); + + if (Index >= USB_KEYCODE_MAX_MAKE) { + return EFI_NOT_READY; + } + + Key->ScanCode = KeyConvertionTable[Index][0]; + + if (UsbKeyboardDevice->ShiftOn) { + + Key->UnicodeChar = KeyConvertionTable[Index][2]; + + } else { + + Key->UnicodeChar = KeyConvertionTable[Index][1]; + } + + if (UsbKeyboardDevice->CapsOn) { + + if (Key->UnicodeChar >= 'a' && Key->UnicodeChar <= 'z') { + + Key->UnicodeChar = KeyConvertionTable[Index][2]; + + } else if (Key->UnicodeChar >= 'A' && Key->UnicodeChar <= 'Z') { + + Key->UnicodeChar = KeyConvertionTable[Index][1]; + + } + } + + if (KeyChar >= 0x59 && KeyChar <= 0x63) { + + if (UsbKeyboardDevice->NumLockOn && !UsbKeyboardDevice->ShiftOn) { + + Key->ScanCode = SCAN_NULL; + + } else { + + Key->UnicodeChar = 0x00; + } + } + + if (Key->UnicodeChar == 0 && Key->ScanCode == SCAN_NULL) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; + +} + + +EFI_STATUS +InitUSBKeyBuffer ( + IN OUT USB_KB_BUFFER *KeyboardBuffer + ) +/*++ + + Routine Description: + Resets USB Keyboard Buffer. + + Arguments: + KeyboardBuffer - Points to the USB Keyboard Buffer. + + Returns: + EFI_SUCCESS - Success +--*/ +{ + ZeroMem (KeyboardBuffer, sizeof (USB_KB_BUFFER)); + + KeyboardBuffer->bHead = KeyboardBuffer->bTail; + + return EFI_SUCCESS; +} + +BOOLEAN +IsUSBKeyboardBufferEmpty ( + IN USB_KB_BUFFER *KeyboardBuffer + ) +/*++ + + Routine Description: + Check whether USB Keyboard buffer is empty. + + Arguments: + KeyboardBuffer - USB Keyboard Buffer. + + Returns: + +--*/ +{ + // + // meet FIFO empty condition + // + return (BOOLEAN) (KeyboardBuffer->bHead == KeyboardBuffer->bTail); +} + + +BOOLEAN +IsUSBKeyboardBufferFull ( + IN USB_KB_BUFFER *KeyboardBuffer + ) +/*++ + + Routine Description: + Check whether USB Keyboard buffer is full. + + Arguments: + KeyboardBuffer - USB Keyboard Buffer. + + Returns: + +--*/ +{ + return (BOOLEAN)(((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)) == + KeyboardBuffer->bHead); +} + + +EFI_STATUS +InsertKeyCode ( + IN OUT USB_KB_BUFFER *KeyboardBuffer, + IN UINT8 Key, + IN UINT8 Down + ) +/*++ + + Routine Description: + Inserts a key code into keyboard buffer. + + Arguments: + KeyboardBuffer - Points to the USB Keyboard Buffer. + Key - Key code + Down - Special key + Returns: + EFI_SUCCESS - Success +--*/ +{ + USB_KEY UsbKey; + + // + // if keyboard buffer is full, throw the + // first key out of the keyboard buffer. + // + if (IsUSBKeyboardBufferFull (KeyboardBuffer)) { + RemoveKeyCode (KeyboardBuffer, &UsbKey); + } + + KeyboardBuffer->buffer[KeyboardBuffer->bTail].KeyCode = Key; + KeyboardBuffer->buffer[KeyboardBuffer->bTail].Down = Down; + + // + // adjust the tail pointer of the FIFO keyboard buffer. + // + KeyboardBuffer->bTail = (UINT8) ((KeyboardBuffer->bTail + 1) % (MAX_KEY_ALLOWED + 1)); + + return EFI_SUCCESS; +} + +EFI_STATUS +RemoveKeyCode ( + IN OUT USB_KB_BUFFER *KeyboardBuffer, + OUT USB_KEY *UsbKey + ) +/*++ + + Routine Description: + Pops a key code off from keyboard buffer. + + Arguments: + KeyboardBuffer - Points to the USB Keyboard Buffer. + UsbKey - Points to the buffer that contains a usb key code. + + Returns: + EFI_SUCCESS - Success + EFI_DEVICE_ERROR - Hardware Error +--*/ +{ + if (IsUSBKeyboardBufferEmpty (KeyboardBuffer)) { + return EFI_DEVICE_ERROR; + } + + UsbKey->KeyCode = KeyboardBuffer->buffer[KeyboardBuffer->bHead].KeyCode; + UsbKey->Down = KeyboardBuffer->buffer[KeyboardBuffer->bHead].Down; + + // + // adjust the head pointer of the FIFO keyboard buffer. + // + KeyboardBuffer->bHead = (UINT8) ((KeyboardBuffer->bHead + 1) % (MAX_KEY_ALLOWED + 1)); + + return EFI_SUCCESS; +} + +EFI_STATUS +SetKeyLED ( + IN USB_KB_DEV *UsbKeyboardDevice + ) +/*++ + + Routine Description: + Sets USB Keyboard LED state. + + Arguments: + UsbKeyboardDevice - The USB_KB_DEV instance. + + Returns: + EFI_SUCCESS - Success +--*/ +{ + LED_MAP Led; + UINT8 ReportId; + + // + // Set each field in Led map. + // + Led.NumLock = (UINT8) UsbKeyboardDevice->NumLockOn; + Led.CapsLock = (UINT8) UsbKeyboardDevice->CapsOn; + Led.Resrvd = 0; + + ReportId = 0; + // + // call Set Report Request to lighten the LED. + // + UsbSetReportRequest ( + UsbKeyboardDevice->UsbIo, + UsbKeyboardDevice->InterfaceDescriptor.InterfaceNumber, + ReportId, + HID_OUTPUT_REPORT, + 1, + (UINT8 *) &Led + ); + + return EFI_SUCCESS; +} + +VOID +EFIAPI +USBKeyboardRepeatHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + + Routine Description: + Timer handler for Repeat Key timer. + + Arguments: + Event - The Repeat Key event. + Context - Points to the USB_KB_DEV instance. + + Returns: + +--*/ +{ + USB_KB_DEV *UsbKeyboardDevice; + + UsbKeyboardDevice = (USB_KB_DEV *) Context; + + // + // Do nothing when there is no repeat key. + // + if (UsbKeyboardDevice->RepeatKey != 0) { + // + // Inserts one Repeat key into keyboard buffer, + // + InsertKeyCode ( + &(UsbKeyboardDevice->KeyboardBuffer), + UsbKeyboardDevice->RepeatKey, + 1 + ); + + // + // set repeate rate for repeat key generation. + // + gBS->SetTimer ( + UsbKeyboardDevice->RepeatTimer, + TimerRelative, + USBKBD_REPEAT_RATE + ); + + } +} + +VOID +EFIAPI +USBKeyboardRecoveryHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + + Routine Description: + Timer handler for Delayed Recovery timer. + + Arguments: + Event - The Delayed Recovery event. + Context - Points to the USB_KB_DEV instance. + + Returns: + +--*/ +{ + + USB_KB_DEV *UsbKeyboardDevice; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 PacketSize; + + UsbKeyboardDevice = (USB_KB_DEV *) Context; + + UsbIo = UsbKeyboardDevice->UsbIo; + + PacketSize = (UINT8) (UsbKeyboardDevice->IntEndpointDescriptor.MaxPacketSize); + + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + UsbKeyboardDevice->IntEndpointDescriptor.EndpointAddress, + TRUE, + UsbKeyboardDevice->IntEndpointDescriptor.Interval, + PacketSize, + KeyboardHandler, + UsbKeyboardDevice + ); +} diff --git a/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.h b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.h new file mode 100644 index 0000000000..a01fda3ca4 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbKb/Dxe/keyboard.h @@ -0,0 +1,106 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + Keyboard.h + +Abstract: + + Function prototype for USB Keyboard Driver + +Revision History +--*/ + +#ifndef _KEYBOARD_H +#define _KEYBOARD_H + +#include "efikey.h" + +BOOLEAN +IsUSBKeyboard ( + IN EFI_USB_IO_PROTOCOL *UsbIo + ); + +EFI_STATUS +InitUSBKeyboard ( + IN USB_KB_DEV *UsbKeyboardDevice + ); + +EFI_STATUS +EFIAPI +KeyboardHandler ( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context, + IN UINT32 Result + ); + +VOID +EFIAPI +USBKeyboardRecoveryHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +EFI_STATUS +USBParseKey ( + IN OUT USB_KB_DEV *UsbKeyboardDevice, + OUT UINT8 *KeyChar + ); + +EFI_STATUS +USBKeyCodeToEFIScanCode ( + IN USB_KB_DEV *UsbKeyboardDevice, + IN UINT8 KeyChar, + OUT EFI_INPUT_KEY *Key + ); + +EFI_STATUS +InitUSBKeyBuffer ( + IN OUT USB_KB_BUFFER *KeyboardBuffer + ); + +BOOLEAN +IsUSBKeyboardBufferEmpty ( + IN USB_KB_BUFFER *KeyboardBuffer + ); + +BOOLEAN +IsUSBKeyboardBufferFull ( + IN USB_KB_BUFFER *KeyboardBuffer + ); + +EFI_STATUS +InsertKeyCode ( + IN OUT USB_KB_BUFFER *KeyboardBuffer, + IN UINT8 Key, + IN UINT8 Down + ); + +EFI_STATUS +RemoveKeyCode ( + IN OUT USB_KB_BUFFER *KeyboardBuffer, + OUT USB_KEY *UsbKey + ); + +VOID +EFIAPI +USBKeyboardRepeatHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +EFI_STATUS +SetKeyLED ( + IN USB_KB_DEV *UsbKeyboardDevice + ); + +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c new file mode 100644 index 0000000000..a021d95389 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/ComponentName.c @@ -0,0 +1,154 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "UsbMassStorage.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +UsbMassStorageComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UsbMassStorageComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gUsbMassStorageComponentName = { + UsbMassStorageComponentNameGetDriverName, + UsbMassStorageComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mUsbMassStorageDriverNameTable[] = { + { "eng", (CHAR16 *) L"Generic USB Mass Storage Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +UsbMassStorageComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gUsbMassStorageComponentName.SupportedLanguages, + mUsbMassStorageDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +UsbMassStorageComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c new file mode 100644 index 0000000000..932b8c5ed9 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.c @@ -0,0 +1,727 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + UsbMassStorage.c + +Abstract: + + USB Mass Storage Driver + +Revision History + +--*/ + +#include "UsbMassStorage.h" +#include "UsbMassStorageHelper.h" + +extern EFI_COMPONENT_NAME_PROTOCOL gUsbMassStorageComponentName; + +// +// Prototypes +// Driver model protocol interface +// +EFI_STATUS +EFIAPI +USBMassStorageDriverBindingEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +USBFloppyDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +USBFloppyDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +USBFloppyDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Block I/O Protocol Interface +// +STATIC +EFI_STATUS +EFIAPI +USBFloppyReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +STATIC +EFI_STATUS +EFIAPI +USBFloppyReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +USBFloppyWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +STATIC +EFI_STATUS +EFIAPI +USBFloppyFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ); + +// +// USB Floppy Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gUSBFloppyDriverBinding = { + USBFloppyDriverBindingSupported, + USBFloppyDriverBindingStart, + USBFloppyDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +USBFloppyDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + that has UsbHcProtocol installed will be supported. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_UNSUPPORTED - This driver does not support this device. + +--*/ +{ + EFI_STATUS OpenStatus; + EFI_USB_ATAPI_PROTOCOL *AtapiProtocol; + + // + // check whether EFI_USB_ATAPI_PROTOCOL exists, if it does, + // then the controller must be a USB Mass Storage Controller + // + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiUsbAtapiProtocolGuid, + (VOID **) &AtapiProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (OpenStatus)) { + return OpenStatus; + } + + gBS->CloseProtocol ( + Controller, + &gEfiUsbAtapiProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +USBFloppyDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Starting the Usb Bus Driver + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_UNSUPPORTED - This driver does not support this device. + EFI_DEVICE_ERROR - This driver cannot be started due to device + Error + EFI_OUT_OF_RESOURCES- Can't allocate memory resources + EFI_ALREADY_STARTED - Thios driver has been started +--*/ +{ + EFI_STATUS Status; + EFI_USB_ATAPI_PROTOCOL *AtapiProtocol; + USB_FLOPPY_DEV *UsbFloppyDevice; + + UsbFloppyDevice = NULL; + // + // Check whether Usb Atapi Protocol attached on the controller handle. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiUsbAtapiProtocolGuid, + (VOID **) &AtapiProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (USB_FLOPPY_DEV), + (VOID **) &UsbFloppyDevice + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiUsbAtapiProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + ZeroMem (UsbFloppyDevice, sizeof (USB_FLOPPY_DEV)); + + UsbFloppyDevice->Handle = Controller; + UsbFloppyDevice->BlkIo.Media = &UsbFloppyDevice->BlkMedia; + UsbFloppyDevice->Signature = USB_FLOPPY_DEV_SIGNATURE; + UsbFloppyDevice->BlkIo.Reset = USBFloppyReset; + UsbFloppyDevice->BlkIo.ReadBlocks = USBFloppyReadBlocks; + UsbFloppyDevice->BlkIo.WriteBlocks = USBFloppyWriteBlocks; + UsbFloppyDevice->BlkIo.FlushBlocks = USBFloppyFlushBlocks; + UsbFloppyDevice->AtapiProtocol = AtapiProtocol; + + // + // Identify drive type and retrieve media information. + // + Status = USBFloppyIdentify (UsbFloppyDevice); + if (EFI_ERROR (Status)) { + if (UsbFloppyDevice->SenseData != NULL) { + gBS->FreePool (UsbFloppyDevice->SenseData); + } + + gBS->FreePool (UsbFloppyDevice); + gBS->CloseProtocol ( + Controller, + &gEfiUsbAtapiProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + // + // Install Block I/O protocol for the usb floppy device. + // + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiBlockIoProtocolGuid, + EFI_NATIVE_INTERFACE, + &UsbFloppyDevice->BlkIo + ); + if (EFI_ERROR (Status)) { + if (UsbFloppyDevice->SenseData != NULL) { + gBS->FreePool (UsbFloppyDevice->SenseData); + } + + gBS->FreePool (UsbFloppyDevice); + gBS->CloseProtocol ( + Controller, + &gEfiUsbAtapiProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + return EFI_SUCCESS; + +} + + +EFI_STATUS +EFIAPI +USBFloppyDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + others + +--*/ +{ + EFI_STATUS Status; + USB_FLOPPY_DEV *UsbFloppyDevice; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + + // + // First find USB_FLOPPY_DEV + // + gBS->OpenProtocol ( + Controller, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (BlkIo); + + // + // Uninstall Block I/O protocol from the device handle + // + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiBlockIoProtocolGuid, + &UsbFloppyDevice->BlkIo + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Stop using EFI_USB_ATAPI_PROTOCOL + // + gBS->CloseProtocol ( + Controller, + &gEfiUsbAtapiProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if (UsbFloppyDevice->SenseData != NULL) { + gBS->FreePool (UsbFloppyDevice->SenseData); + } + + gBS->FreePool (UsbFloppyDevice); + + return EFI_SUCCESS; +} + + +STATIC +EFI_STATUS +EFIAPI +USBFloppyReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Implements EFI_BLOCK_IO_PROTOCOL.Reset() function. + + Arguments: + This The EFI_BLOCK_IO_PROTOCOL instance. + ExtendedVerification + Indicates that the driver may perform a more exhaustive + verification operation of the device during reset. + (This parameter is ingored in this driver.) + + Returns: + EFI_SUCCESS - Success +--*/ +{ + USB_FLOPPY_DEV *UsbFloppyDevice; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + EFI_STATUS Status; + + UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This); + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + // + // directly calling EFI_USB_ATAPI_PROTOCOL.Reset() to implement reset. + // + Status = UsbAtapiInterface->UsbAtapiReset (UsbAtapiInterface, TRUE); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +USBFloppyReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + + Routine Description: + Implements EFI_BLOCK_IO_PROTOCOL.ReadBlocks() function. + + Arguments: + This The EFI_BLOCK_IO_PROTOCOL instance. + MediaId The media id that the read request is for. + LBA The starting logical block address to read from on the device. + BufferSize + The size of the Buffer in bytes. This must be a multiple of + the intrinsic block size of the device. + Buffer A pointer to the destination buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + + Returns: + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_DEVICE_ERROR - Hardware Error + EFI_NO_MEDIA - No media + EFI_MEDIA_CHANGED - Media Change + EFI_BAD_BUFFER_SIZE - Buffer size is bad + --*/ +{ + USB_FLOPPY_DEV *UsbFloppyDevice; + EFI_STATUS Status; + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + BOOLEAN MediaChange; + EFI_TPL OldTpl; + UINT32 Retry; + + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + Status = EFI_SUCCESS; + MediaChange = FALSE; + Retry = 0; + + UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This); + + // + // Check parameters + // + if (!Buffer) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if (BufferSize == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + UsbFloppyTestUnitReady (UsbFloppyDevice); + + Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange); + if (EFI_ERROR (Status)) { + + Status = EFI_DEVICE_ERROR; + goto Done; + } + + if (MediaChange) { + gBS->RestoreTPL (OldTpl); + gBS->ReinstallProtocolInterface ( + UsbFloppyDevice->Handle, + &gEfiBlockIoProtocolGuid, + &UsbFloppyDevice->BlkIo, + &UsbFloppyDevice->BlkIo + ); + gBS->RaiseTPL (EFI_TPL_NOTIFY); + } + + Media = UsbFloppyDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + NumberOfBlocks = BufferSize / BlockSize; + + if (!(Media->MediaPresent)) { + Status = EFI_NO_MEDIA; + goto Done; + } + + if (MediaId != Media->MediaId) { + Status = EFI_MEDIA_CHANGED; + goto Done; + } + + if (BufferSize % BlockSize != 0) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + if (LBA > Media->LastBlock) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if (!EFI_ERROR (Status)) { + + Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, 1); + if (EFI_ERROR (Status)) { + This->Reset (This, TRUE); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + LBA += 1; + NumberOfBlocks -= 1; + Buffer = (UINT8 *) Buffer + This->Media->BlockSize; + + if (NumberOfBlocks == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + Status = USBFloppyRead10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks); + if (EFI_ERROR (Status)) { + This->Reset (This, TRUE); + Status = EFI_DEVICE_ERROR; + } + } + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +USBFloppyWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA LBA, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + + Routine Description: + Implements EFI_BLOCK_IO_PROTOCOL.WriteBlocks() function. + + Arguments: + This The EFI_BLOCK_IO_PROTOCOL instance. + MediaId The media id that the write request is for. + LBA The starting logical block address to be written. + The caller is responsible for writing to only + legitimate locations. + BufferSize + The size of the Buffer in bytes. This must be a multiple of + the intrinsic block size of the device. + Buffer A pointer to the source buffer for the data. The caller + is responsible for either having implicit or explicit ownership + of the buffer. + + Returns: + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_DEVICE_ERROR - Hardware Error + EFI_NO_MEDIA - No media + EFI_MEDIA_CHANGED - Media Change + EFI_BAD_BUFFER_SIZE - Buffer size is bad + +--*/ +{ + USB_FLOPPY_DEV *UsbFloppyDevice; + EFI_STATUS Status; + EFI_BLOCK_IO_MEDIA *Media; + UINTN BlockSize; + UINTN NumberOfBlocks; + BOOLEAN MediaChange; + EFI_TPL OldTpl; + UINT32 Retry; + + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + Status = EFI_SUCCESS; + MediaChange = FALSE; + Retry = 0; + + UsbFloppyDevice = USB_FLOPPY_DEV_FROM_THIS (This); + + // + // Check parameters + // + if (!Buffer) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if (BufferSize == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + UsbFloppyTestUnitReady (UsbFloppyDevice); + + Status = UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange); + if (EFI_ERROR (Status)) { + + Status = EFI_DEVICE_ERROR; + goto Done; + } + + if (MediaChange) { + gBS->RestoreTPL (OldTpl); + gBS->ReinstallProtocolInterface ( + UsbFloppyDevice->Handle, + &gEfiBlockIoProtocolGuid, + &UsbFloppyDevice->BlkIo, + &UsbFloppyDevice->BlkIo + ); + gBS->RaiseTPL (EFI_TPL_NOTIFY); + } + + Media = UsbFloppyDevice->BlkIo.Media; + BlockSize = Media->BlockSize; + NumberOfBlocks = BufferSize / BlockSize; + + if (!(Media->MediaPresent)) { + Status = EFI_NO_MEDIA; + goto Done; + } + + if (MediaId != Media->MediaId) { + Status = EFI_MEDIA_CHANGED; + goto Done; + } + + if (BufferSize % BlockSize != 0) { + Status = EFI_BAD_BUFFER_SIZE; + goto Done; + } + + if (LBA > Media->LastBlock) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if ((LBA + NumberOfBlocks - 1) > Media->LastBlock) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if ((Media->IoAlign > 1) && (((UINTN) Buffer & (Media->IoAlign - 1)) != 0)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + if (UsbFloppyDevice->BlkMedia.ReadOnly) { + Status = EFI_WRITE_PROTECTED; + goto Done; + } + + if (!EFI_ERROR (Status)) { + Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, 1); + if (EFI_ERROR (Status)) { + This->Reset (This, TRUE); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + LBA += 1; + NumberOfBlocks -= 1; + Buffer = (UINT8 *) Buffer + This->Media->BlockSize; + + if (NumberOfBlocks == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + Status = USBFloppyWrite10 (UsbFloppyDevice, Buffer, LBA, NumberOfBlocks); + if (EFI_ERROR (Status)) { + This->Reset (This, TRUE); + Status = EFI_DEVICE_ERROR; + } + } + +Done: + gBS->RestoreTPL (OldTpl); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +USBFloppyFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + + Routine Description: + Implements EFI_BLOCK_IO_PROTOCOL.FlushBlocks() function. + (In this driver, this function just returns EFI_SUCCESS.) + + Arguments: + This The EFI_BLOCK_IO_PROTOCOL instance. + + Returns: + EFI_SUCCESS - Success +--*/ +{ + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h new file mode 100644 index 0000000000..4874bb08cc --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.h @@ -0,0 +1,59 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + UsbMassStorage.h + +Abstract: + + Header file for USB Mass Storage Driver's Data Structures + +Revision History +--*/ + +#ifndef _USB_FLP_H +#define _USB_FLP_H + + +#include +#include "UsbMassStorageData.h" + +#define CLASS_MASSTORAGE 8 +#define SUBCLASS_UFI 4 +#define SUBCLASS_8070 5 +#define PROTOCOL_BOT 0x50 +#define PROTOCOL_CBI0 0 +#define PROTOCOL_CBI1 1 + +#define USBFLOPPY 1 +#define USBFLOPPY2 2 // for those that use ReadCapacity(0x25) command to retrieve media capacity +#define USBCDROM 3 + +#define USB_FLOPPY_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'f', 'l', 'p') + +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + EFI_BLOCK_IO_PROTOCOL BlkIo; + EFI_BLOCK_IO_MEDIA BlkMedia; + EFI_USB_ATAPI_PROTOCOL *AtapiProtocol; + + REQUEST_SENSE_DATA *SenseData; + UINT8 SenseDataNumber; + UINT8 DeviceType; + +} USB_FLOPPY_DEV; + +#define USB_FLOPPY_DEV_FROM_THIS(a) \ + CR(a, USB_FLOPPY_DEV, BlkIo, USB_FLOPPY_DEV_SIGNATURE) + +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd new file mode 100644 index 0000000000..c9c9b5c73b --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.mbd @@ -0,0 +1,43 @@ + + + + + UsbMassStorage + A5C6D68B-E78A-4426-9278-A8F0D9EB4D8F + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkUsbLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa new file mode 100644 index 0000000000..d071c9f656 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa @@ -0,0 +1,70 @@ + + + + + UsbMassStorage + DXE_DRIVER + BS_DRIVER + A5C6D68B-E78A-4426-9278-A8F0D9EB4D8F + 0 + Component description file for UsbMassStorage module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + EdkUsbLib + MemoryAllocationLib + UefiBootServicesTableLib + + + UsbMassStorage.h + UsbMassStorageData.h + UsbMassStorageHelper.h + UsbMassStorage.c + UsbMassStorageHelper.c + ComponentName.c + + + MdePkg + EdkModulePkg + + + UsbAtapi + BlockIo + + + + + + + gUSBFloppyDriverBinding + gUsbMassStorageComponentName + + + diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h new file mode 100644 index 0000000000..598c82e220 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageData.h @@ -0,0 +1,394 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + UsbMassStorageData.h + +Abstract: + + Header file for USB Mass Storage Device related Data Structures + +Revision History +--*/ + +#ifndef _USB_FLP_DATA_H +#define _USB_FLP_DATA_H + +// +// bit definition +// +#define bit(a) 1 << (a) + +// +// timeout unit is in millisecond. +// +#define USBFLPTIMEOUT 2000 +#define STALL_1_MILLI_SECOND 1000 + +// +// ATAPI Packet Command +// +#pragma pack(1) + +typedef struct { + UINT8 opcode; + UINT8 reserved_1; + UINT8 reserved_2; + UINT8 reserved_3; + UINT8 reserved_4; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 reserved_8; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} TEST_UNIT_READY_CMD; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 4; + UINT8 lun : 4; + UINT8 page_code; + UINT8 reserved_3; + UINT8 allocation_length; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 reserved_8; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} INQUIRY_CMD; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 4; + UINT8 lun : 4; + UINT8 reserved_2; + UINT8 reserved_3; + UINT8 allocation_length; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 reserved_8; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} REQUEST_SENSE_CMD; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 4; + UINT8 lun : 4; + UINT8 page_code : 6; + UINT8 page_control : 2; + UINT8 reserved_3; + UINT8 reserved_4; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 parameter_list_length_hi; + UINT8 parameter_list_length_lo; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} MODE_SENSE_CMD_UFI; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 3; + UINT8 dbd : 1; + UINT8 reserved_2 : 1; + UINT8 lun : 3; + UINT8 page_code : 6; + UINT8 page_control : 2; + UINT8 reserved_3; + UINT8 allocation_length; + UINT8 control; +} MODE_SENSE_CMD_SCSI; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1 : 5; + UINT8 lun : 3; + UINT8 Lba0; + UINT8 Lba1; + UINT8 Lba2; + UINT8 Lba3; + UINT8 reserved_6; + UINT8 TranLen0; + UINT8 TranLen1; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} READ10_CMD; + +typedef struct { + UINT8 opcode; + UINT8 reserved_1; + UINT8 reserved_2; + UINT8 reserved_3; + UINT8 reserved_4; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 allocation_length_hi; + UINT8 allocation_length_lo; + UINT8 reserved_9; + UINT8 reserved_10; + UINT8 reserved_11; +} READ_FORMAT_CAP_CMD; + +typedef union { + UINT16 Data16[6]; + TEST_UNIT_READY_CMD TestUnitReady; + READ10_CMD Read10; + REQUEST_SENSE_CMD RequestSense; + INQUIRY_CMD Inquiry; + MODE_SENSE_CMD_UFI ModeSenseUFI; + READ_FORMAT_CAP_CMD ReadFormatCapacity; + MODE_SENSE_CMD_SCSI ModeSenseSCSI; +} ATAPI_PACKET_COMMAND; + +#pragma pack() +// +// Packet Command Code +// +#define TEST_UNIT_READY 0x00 +#define REZERO 0x01 +#define REQUEST_SENSE 0x03 +#define FORMAT_UNIT 0x04 +#define REASSIGN_BLOCKS 0x07 +#define INQUIRY 0x12 +#define START_STOP_UNIT 0x1B +#define PREVENT_ALLOW_MEDIA_REMOVAL 0x1E +#define READ_FORMAT_CAPACITY 0x23 +#define OLD_FORMAT_UNIT 0x24 +#define READ_CAPACITY 0x25 +#define READ_10 0x28 +#define WRITE_10 0x2A +#define SEEK 0x2B +#define SEND_DIAGNOSTICS 0x3D +#define WRITE_VERIFY 0x2E +#define VERIFY 0x2F +#define READ_DEFECT_DATA 0x37 +#define WRITE_BUFFER 0x38 +#define READ_BUFFER 0x3C +#define READ_LONG 0x3E +#define WRITE_LONG 0x3F +#define MODE_SELECT 0x55 +#define UFI_MODE_SENSE5A 0x5A +#define SCSI_MODE_SENSE1A 0x1A +#define READ_12 0xA8 +#define WRITE_12 0xAA +#define MAX_ATAPI_BYTE_COUNT (0xfffe) + +// +// Sense Key +// +#define REQUEST_SENSE_ERROR (0x70) +#define SK_NO_SENSE (0x0) +#define SK_RECOVERY_ERROR (0x1) +#define SK_NOT_READY (0x2) +#define SK_MEDIUM_ERROR (0x3) +#define SK_HARDWARE_ERROR (0x4) +#define SK_ILLEGAL_REQUEST (0x5) +#define SK_UNIT_ATTENTION (0x6) +#define SK_DATA_PROTECT (0x7) +#define SK_BLANK_CHECK (0x8) +#define SK_VENDOR_SPECIFIC (0x9) +#define SK_RESERVED_A (0xA) +#define SK_ABORT (0xB) +#define SK_RESERVED_C (0xC) +#define SK_OVERFLOW (0xD) +#define SK_MISCOMPARE (0xE) +#define SK_RESERVED_F (0xF) + +// +// Additional Sense Codes +// +#define ASC_NOT_READY (0x04) +#define ASC_MEDIA_ERR1 (0x10) +#define ASC_MEDIA_ERR2 (0x11) +#define ASC_MEDIA_ERR3 (0x14) +#define ASC_MEDIA_ERR4 (0x30) +#define ASC_MEDIA_UPSIDE_DOWN (0x06) +#define ASC_INVALID_CMD (0x20) +#define ASC_LBA_OUT_OF_RANGE (0x21) +#define ASC_INVALID_FIELD (0x24) +#define ASC_WRITE_PROTECTED (0x27) +#define ASC_MEDIA_CHANGE (0x28) +#define ASC_RESET (0x29) /* Power On Reset or Bus Reset occurred */ +#define ASC_ILLEGAL_FIELD (0x26) +#define ASC_NO_MEDIA (0x3A) +#define ASC_ILLEGAL_MODE_FOR_THIS_TRACK (0x64) +#define ASC_LOGICAL_UNIT_STATUS (0x08) + +// +// Additional Sense Code Qualifier +// +#define ASCQ_IN_PROGRESS (0x01) +#define ASCQ_DEVICE_BUSY (0xff) +#define ASCQ_LOGICAL_UNIT_FAILURE (0x00) +#define ASCQ_LOGICAL_UNIT_TIMEOUT (0x01) +#define ASCQ_LOGICAL_UNIT_OVERRUN (0x80) + +#define SETFEATURE TRUE +#define CLEARFEATURE FALSE + +// +// ATAPI Data structure +// +#pragma pack(1) + +typedef struct { + UINT8 peripheral_type; + UINT8 RMB; + UINT8 version; + UINT8 response_data_format; + UINT8 addnl_length; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; + UINT8 vendor_info[8]; + UINT8 product_id[12]; + UINT8 eeprom_product_code[4]; + UINT8 firmware_rev_level[4]; +} USB_INQUIRY_DATA; + +typedef struct { + UINT8 error_code : 7; + UINT8 valid : 1; + UINT8 reserved_1; + UINT8 sense_key : 4; + UINT8 reserved_21 : 1; + UINT8 ILI : 1; + UINT8 reserved_22 : 2; + UINT8 vendor_specific_3; + UINT8 vendor_specific_4; + UINT8 vendor_specific_5; + UINT8 vendor_specific_6; + UINT8 addnl_sense_length; // n - 7 + UINT8 vendor_specific_8; + UINT8 vendor_specific_9; + UINT8 vendor_specific_10; + UINT8 vendor_specific_11; + UINT8 addnl_sense_code; // mandatory + UINT8 addnl_sense_code_qualifier; // mandatory + UINT8 field_replaceable_unit_code; // optional + UINT8 reserved_15; + UINT8 reserved_16; + UINT8 reserved_17; + // + // Followed by additional sense bytes : FIXME + // +} REQUEST_SENSE_DATA; + +typedef struct { + UINT8 LastLba3; + UINT8 LastLba2; + UINT8 LastLba1; + UINT8 LastLba0; + UINT8 BlockSize3; + UINT8 BlockSize2; + UINT8 BlockSize1; + UINT8 BlockSize0; +} READ_CAPACITY_DATA; + +typedef struct { + UINT8 reserved_0; + UINT8 reserved_1; + UINT8 reserved_2; + UINT8 Capacity_Length; + UINT8 LastLba3; + UINT8 LastLba2; + UINT8 LastLba1; + UINT8 LastLba0; + UINT8 DesCode : 2; + UINT8 reserved_9 : 6; + UINT8 BlockSize2; + UINT8 BlockSize1; + UINT8 BlockSize0; +} READ_FORMAT_CAPACITY_DATA; + +typedef struct { + UINT8 mode_data_len_hi; + UINT8 mode_data_len_lo; + UINT8 media_type_code; + UINT8 reserved_3_0 : 4; + UINT8 dpofua : 1; + UINT8 reserved_3_1 : 2; + UINT8 write_protected : 1; + UINT8 reserved_4; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; +} UFI_MODE_PARAMETER_HEADER; + +typedef struct { + UINT8 mode_data_len; + UINT8 media_type_code; + UINT8 speed : 4; + UINT8 buffered_mode : 3; + UINT8 write_protected : 1; + UINT8 block_descritptor_length; +} SCSI_MODE_PARAMETER_HEADER6; + +typedef struct { + UINT8 page_code : 6; + UINT8 reserved_0 : 1; + UINT8 parameter_savable : 1; + UINT8 page_length; + UINT8 transfer_rate_msb; + UINT8 transfer_rate_lsb; + UINT8 number_of_heads; + UINT8 sectors_per_track; + UINT8 databytes_per_sector_msb; + UINT8 databytes_per_sector_lsb; + UINT8 number_of_cylinders_msb; + UINT8 number_of_cylinders_lsb; + UINT8 reserved_10_18[9]; + UINT8 motor_on_delay; + UINT8 motor_off_delay; + UINT8 reserved_21_27[7]; + UINT8 medium_rotation_rate_msb; + UINT8 medium_rotation_rate_lsb; + UINT8 reserved_30_31[2]; +} FLEXIBLE_DISK_PAGE; + +typedef struct { + UFI_MODE_PARAMETER_HEADER mode_param_header; + FLEXIBLE_DISK_PAGE flex_disk_page; +} UFI_MODE_PARAMETER_PAGE_5; + +typedef struct { + UINT8 page_code : 6; + UINT8 reserved_0 : 1; + UINT8 parameter_savable : 1; + UINT8 page_length; + UINT8 reserved_2; + UINT8 inactive_time_multplier : 4; + UINT8 reserved_3 : 4; + UINT8 software_write_protect : 1; + UINT8 disable_media_access : 1; + UINT8 reserved_4 : 6; + UINT8 reserved_5; + UINT8 reserved_6; + UINT8 reserved_7; +} TIMER_AND_PROTECT_PAGE; + +typedef struct { + UFI_MODE_PARAMETER_HEADER mode_param_header; + TIMER_AND_PROTECT_PAGE time_and_protect_page; +} UFI_MODE_PARAMETER_PAGE_1C; + +#pragma pack() + +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c new file mode 100644 index 0000000000..b8ed813ea2 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.c @@ -0,0 +1,1653 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + UsbMassStorageHelper.c + +Abstract: + + Helper functions for USB Mass Storage Driver + +Revision History + +--*/ + +#include "UsbMassStorageHelper.h" + +STATIC +BOOLEAN +IsNoMedia ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ); + +STATIC +BOOLEAN +IsMediaError ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ); + +STATIC +BOOLEAN +IsMediaChange ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ); + +STATIC +BOOLEAN +IsDriveReady ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts, + OUT BOOLEAN *NeedRetry + ); + +STATIC +BOOLEAN +IsMediaWriteProtected ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ); + +STATIC +BOOLEAN +IsLogicalUnitCommunicationOverRun ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ); + +EFI_STATUS +USBFloppyPacketCommand ( + USB_FLOPPY_DEV *UsbFloppyDevice, + VOID *Command, + UINT8 CommandSize, + VOID *DataBuffer, + UINT32 BufferLength, + EFI_USB_DATA_DIRECTION Direction, + UINT16 TimeOutInMilliSeconds + ) +/*++ + + Routine Description: + Sends Packet Command to USB Floppy Drive. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + Command - A pointer to the command packet. + CommandSize - Indicates the size of the command packet. + DataBuffer - A pointer to the buffer for the data transfer + after the command packet. + BufferLength - Indicates the size of the Data Buffer. + Direction - Transfer Direction + TimeOutInMilliSeconds - Timeout Value + Returns: + EFI_SUCCESS - Success +--*/ +{ + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + EFI_STATUS Status; + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + // + // Directly calling EFI_USB_ATAPI_PROTOCOL.UsbAtapiPacketCmd() + // to perform the command request. + // + Status = UsbAtapiInterface->UsbAtapiPacketCmd ( + UsbAtapiInterface, + Command, + CommandSize, + DataBuffer, + BufferLength, + Direction, + TimeOutInMilliSeconds + ); + + return Status; +} + +EFI_STATUS +USBFloppyIdentify ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ) +/*++ + + Routine Description: + Retrieves device information to tell the device type. + + Arguments: + UsbFloppyDevice The USB_FLOPPY_DEV instance. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success +--*/ +{ + + EFI_STATUS Status; + USB_INQUIRY_DATA *Idata; + BOOLEAN MediaChange; + + // + // Send Inquiry Packet Command to get INQUIRY data. + // + Status = USBFloppyInquiry (UsbFloppyDevice, &Idata); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // Get media removable info from INQUIRY data. + // + UsbFloppyDevice->BlkIo.Media->RemovableMedia = (UINT8) ((Idata->RMB & 0x80) == 0x80); + + // + // Identify device type via INQUIRY data. + // + switch ((Idata->peripheral_type) & 0x1f) { + // + // Floppy + // + case 0x00: + UsbFloppyDevice->DeviceType = USBFLOPPY; + UsbFloppyDevice->BlkIo.Media->MediaId = 0; + UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE; + UsbFloppyDevice->BlkIo.Media->LastBlock = 0; + UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200; + break; + + // + // CD-ROM + // + case 0x05: + UsbFloppyDevice->DeviceType = USBCDROM; + UsbFloppyDevice->BlkIo.Media->MediaId = 0; + UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE; + UsbFloppyDevice->BlkIo.Media->LastBlock = 0; + UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800; + UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE; + break; + + default: + gBS->FreePool (Idata); + return EFI_DEVICE_ERROR; + }; + + // + // Initialize some device specific data. + // + // + // original sense data numbers + // + UsbFloppyDevice->SenseDataNumber = 6; + + if (UsbFloppyDevice->SenseData != NULL) { + gBS->FreePool (UsbFloppyDevice->SenseData); + UsbFloppyDevice->SenseData = NULL; + } + + UsbFloppyDevice->SenseData = AllocatePool (UsbFloppyDevice->SenseDataNumber * sizeof (REQUEST_SENSE_DATA)); + + if (UsbFloppyDevice->SenseData == NULL) { + gBS->FreePool (Idata); + return EFI_DEVICE_ERROR; + } + + // + // Get media information. + // + UsbFloppyDetectMedia (UsbFloppyDevice, &MediaChange); + + gBS->FreePool (Idata); + + return EFI_SUCCESS; +} + +EFI_STATUS +USBFloppyInquiry ( + IN USB_FLOPPY_DEV *UsbFloppyDevice, + OUT USB_INQUIRY_DATA **Idata + ) +/*++ + + Routine Description: + Send Inquiry Packet Command to device and retrieve Inquiry Data. + + Arguments: + UsbFloppyDevice The USB_FLOPPY_DEV instance. + Idata A pointer pointing to the address of + Inquiry Data. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success +--*/ +{ + ATAPI_PACKET_COMMAND Packet; + EFI_STATUS Status; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + // + // prepare command packet for the Inquiry Packet Command. + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.Inquiry.opcode = INQUIRY; + Packet.Inquiry.page_code = 0; + Packet.Inquiry.allocation_length = sizeof (USB_INQUIRY_DATA); + + *Idata = AllocateZeroPool (sizeof (USB_INQUIRY_DATA)); + if (*Idata == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Send command packet and retrieve requested Inquiry Data. + // + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + (VOID *) (*Idata), + sizeof (USB_INQUIRY_DATA), + EfiUsbDataIn, + USBFLPTIMEOUT * 3 + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (*Idata); + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +USBFloppyRead10 ( + IN USB_FLOPPY_DEV *UsbFloppyDevice, + IN VOID *Buffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +/*++ + + Routine Description: + Sends Read10 Packet Command to device to perform data transfer + from device to host. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + Buffer - A pointer to the destination buffer for the data. + The caller is responsible for either having implicit + or explicit ownership of the buffer. + Lba - The starting logical block address to read from + on the device. + NumberOfBlocks - Indicates the number of blocks that the read + operation requests. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success +--*/ +{ + ATAPI_PACKET_COMMAND Packet; + READ10_CMD *Read10Packet; + UINT16 MaxBlock; + UINT16 BlocksRemaining; + UINT16 SectorCount; + UINT32 Lba32; + UINT32 BlockSize; + UINT32 ByteCount; + VOID *ptrBuffer; + EFI_STATUS Status; + UINT16 TimeOut; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + UINTN SenseCounts; + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + // + // prepare command packet for the Inquiry Packet Command. + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Read10Packet = &Packet.Read10; + Lba32 = (UINT32) Lba; + ptrBuffer = Buffer; + BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize; + + MaxBlock = (UINT16) (65536 / BlockSize); + BlocksRemaining = (UINT16) NumberOfBlocks; + + Status = EFI_SUCCESS; + while (BlocksRemaining > 0) { + if (BlocksRemaining <= MaxBlock) { + SectorCount = BlocksRemaining; + } else { + SectorCount = MaxBlock; + } + // + // fill the Packet data structure + // + Read10Packet->opcode = READ_10; + + // + // Lba0 ~ Lba3 specify the start logical block address of the data transfer. + // Lba0 is MSB, Lba3 is LSB + // + Read10Packet->Lba3 = (UINT8) (Lba32 & 0xff); + Read10Packet->Lba2 = (UINT8) (Lba32 >> 8); + Read10Packet->Lba1 = (UINT8) (Lba32 >> 16); + Read10Packet->Lba0 = (UINT8) (Lba32 >> 24); + + // + // TranLen0 ~ TranLen1 specify the transfer length in block unit. + // TranLen0 is MSB, TranLen is LSB + // + Read10Packet->TranLen1 = (UINT8) (SectorCount & 0xff); + Read10Packet->TranLen0 = (UINT8) (SectorCount >> 8); + + ByteCount = SectorCount * BlockSize; + + TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT); + + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + (VOID *) ptrBuffer, + ByteCount, + EfiUsbDataIn, + TimeOut + ); + if (EFI_ERROR (Status)) { + + Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts); + if (!EFI_ERROR (Status)) { + if (IsLogicalUnitCommunicationOverRun ( + UsbFloppyDevice->SenseData, + SenseCounts + )) { + Lba32 = (UINT32) Lba; + ptrBuffer = Buffer; + BlocksRemaining = (UINT16) NumberOfBlocks; + MaxBlock = (UINT16) (MaxBlock / 4); + if (MaxBlock < 1) { + MaxBlock = 1; + } + + continue; + } + } else { + return EFI_DEVICE_ERROR; + } + // + // retry read10 command + // + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + (VOID *) ptrBuffer, + ByteCount, + EfiUsbDataIn, + TimeOut + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + } + + Lba32 += SectorCount; + ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize; + BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount); + } + + return Status; +} + +EFI_STATUS +USBFloppyReadCapacity ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ) +/*++ + + Routine Description: + Retrieves media capacity information via + sending Read Capacity Packet Command. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success +--*/ +{ + // + // status returned by Read Capacity Packet Command + // + EFI_STATUS Status; + ATAPI_PACKET_COMMAND Packet; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + + // + // used for capacity data returned from Usb Floppy + // + READ_CAPACITY_DATA Data; + + ZeroMem (&Data, sizeof (Data)); + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.Inquiry.opcode = READ_CAPACITY; + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + (VOID *) &Data, + sizeof (READ_CAPACITY_DATA), + EfiUsbDataIn, + USBFLPTIMEOUT + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + UsbFloppyDevice->BlkIo.Media->LastBlock = (Data.LastLba3 << 24) | + (Data.LastLba2 << 16) | + (Data.LastLba1 << 8) | + Data.LastLba0; + + UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE; + + UsbFloppyDevice->BlkIo.Media->BlockSize = 0x800; + + return EFI_SUCCESS; + +} + +EFI_STATUS +USBFloppyReadFormatCapacity ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ) +/*++ + + Routine Description: + Retrieves media capacity information via sending Read Format + Capacity Packet Command. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success +--*/ +{ + // + // status returned by Read Capacity Packet Command + // + EFI_STATUS Status; + ATAPI_PACKET_COMMAND Packet; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + + // + // used for capacity data returned from Usb Floppy + // + READ_FORMAT_CAPACITY_DATA FormatData; + + ZeroMem (&FormatData, sizeof (FormatData)); + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.ReadFormatCapacity.opcode = READ_FORMAT_CAPACITY; + Packet.ReadFormatCapacity.allocation_length_lo = 12; + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + (VOID *) &FormatData, + sizeof (READ_FORMAT_CAPACITY_DATA), + EfiUsbDataIn, + USBFLPTIMEOUT + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (FormatData.DesCode == 3) { + // + // Media is not present + // + UsbFloppyDevice->BlkIo.Media->MediaId = 0; + UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE; + UsbFloppyDevice->BlkIo.Media->LastBlock = 0; + } else { + + UsbFloppyDevice->BlkIo.Media->LastBlock = (FormatData.LastLba3 << 24) | + (FormatData.LastLba2 << 16) | + (FormatData.LastLba1 << 8) | + FormatData.LastLba0; + + UsbFloppyDevice->BlkIo.Media->LastBlock--; + + UsbFloppyDevice->BlkIo.Media->BlockSize = (FormatData.BlockSize2 << 16) | + (FormatData.BlockSize1 << 8) | + FormatData.BlockSize0; + + UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE; + + UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200; + + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +UsbFloppyRequestSense ( + IN USB_FLOPPY_DEV *UsbFloppyDevice, + OUT UINTN *SenseCounts + ) +/*++ + + Routine Description: + Retrieves Sense Data from device via + sending Request Sense Packet Command. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + SenseCounts - A pointer to the number of Sense Data returned. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success +--*/ +{ + EFI_STATUS Status; + REQUEST_SENSE_DATA *Sense; + UINT8 *Ptr; + BOOLEAN SenseReq; + ATAPI_PACKET_COMMAND Packet; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + *SenseCounts = 0; + + ZeroMem ( + UsbFloppyDevice->SenseData, + sizeof (REQUEST_SENSE_DATA) * (UsbFloppyDevice->SenseDataNumber) + ); + // + // fill command packet for Request Sense Packet Command + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.RequestSense.opcode = REQUEST_SENSE; + Packet.RequestSense.allocation_length = sizeof (REQUEST_SENSE_DATA); + + // + // initialize pointer + // + Ptr = (UINT8 *) (UsbFloppyDevice->SenseData); + + // + // request sense data from device continuously + // until no sense data exists in the device. + // + for (SenseReq = TRUE; SenseReq;) { + + Sense = (REQUEST_SENSE_DATA *) Ptr; + + // + // send out Request Sense Packet Command and get one Sense + // data from device. + // + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + (VOID *) Ptr, + sizeof (REQUEST_SENSE_DATA), + EfiUsbDataIn, + USBFLPTIMEOUT + ); + // + // failed to get Sense data + // + if (EFI_ERROR (Status)) { + // + // Recovery the device back to normal state. + // + UsbFloppyDevice->AtapiProtocol->UsbAtapiReset ( + UsbFloppyDevice->AtapiProtocol, + TRUE + ); + + if (*SenseCounts == 0) { + // + // never retrieved any sense data from device, + // just return error. + // + return EFI_DEVICE_ERROR; + } else { + // + // has retrieved some sense data from device, + // so return success. + // + return EFI_SUCCESS; + } + } + + if (Sense->sense_key != SK_NO_SENSE) { + // + // Ptr is byte based pointer + // + Ptr += sizeof (REQUEST_SENSE_DATA); + + (*SenseCounts)++; + + } else { + // + // when no sense key, skip out the loop + // + SenseReq = FALSE; + } + + // + // If the sense key numbers exceed Sense Data Buffer size, + // just skip the loop and do not fetch the sense key in this function. + // + if (*SenseCounts == UsbFloppyDevice->SenseDataNumber) { + SenseReq = FALSE; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +UsbFloppyTestUnitReady ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ) +/*++ + + Routine Description: + Sends Test Unit ReadyPacket Command to the device. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success +--*/ +{ + ATAPI_PACKET_COMMAND Packet; + EFI_STATUS Status; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + UINT32 RetryIndex; + UINT32 MaximumRetryTimes; + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + MaximumRetryTimes = 2; + // + // fill command packet + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.TestUnitReady.opcode = TEST_UNIT_READY; + + // + // send command packet + // + Status = EFI_DEVICE_ERROR; + + for (RetryIndex = 0; RetryIndex < MaximumRetryTimes && EFI_ERROR (Status); RetryIndex++) { + + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + NULL, + 0, + EfiUsbNoData, + USBFLPTIMEOUT + ); + + if (EFI_ERROR (Status)) { + gBS->Stall (100 * STALL_1_MILLI_SECOND); + } + } + + return Status; +} + +EFI_STATUS +USBFloppyWrite10 ( + IN USB_FLOPPY_DEV *UsbFloppyDevice, + IN VOID *Buffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ) +/*++ + + Routine Description: + Sends Write10 Packet Command to device to perform data transfer + from host to device. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + Buffer - A pointer to the source buffer for the data. + The caller is responsible for either having implicit + or explicit ownership of the buffer. + Lba - The starting logical block address to written to + the device. + NumberOfBlocks - Indicates the number of blocks that the write + operation requests. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success +--*/ +{ + ATAPI_PACKET_COMMAND Packet; + READ10_CMD *Write10Packet; + UINT16 MaxBlock; + UINT16 BlocksRemaining; + UINT16 SectorCount; + UINT32 Lba32; + UINT32 BlockSize; + UINT32 ByteCount; + VOID *ptrBuffer; + EFI_STATUS Status; + UINT16 TimeOut; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + UINTN SenseCounts; + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + // + // prepare command packet for the Write10 Packet Command. + // + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Write10Packet = &Packet.Read10; + Lba32 = (UINT32) Lba; + ptrBuffer = Buffer; + BlockSize = UsbFloppyDevice->BlkIo.Media->BlockSize; + + MaxBlock = (UINT16) (65536 / BlockSize); + BlocksRemaining = (UINT16) NumberOfBlocks; + + Status = EFI_SUCCESS; + while (BlocksRemaining > 0) { + + if (BlocksRemaining <= MaxBlock) { + + SectorCount = BlocksRemaining; + } else { + + SectorCount = MaxBlock; + } + // + // fill the Packet data structure + // + Write10Packet->opcode = WRITE_10; + + // + // Lba0 ~ Lba3 specify the start logical block address + // of the data transfer. + // Lba0 is MSB, Lba3 is LSB + // + Write10Packet->Lba3 = (UINT8) (Lba32 & 0xff); + Write10Packet->Lba2 = (UINT8) (Lba32 >> 8); + Write10Packet->Lba1 = (UINT8) (Lba32 >> 16); + Write10Packet->Lba0 = (UINT8) (Lba32 >> 24); + + // + // TranLen0 ~ TranLen1 specify the transfer length in block unit. + // TranLen0 is MSB, TranLen is LSB + // + Write10Packet->TranLen1 = (UINT8) (SectorCount & 0xff); + Write10Packet->TranLen0 = (UINT8) (SectorCount >> 8); + + ByteCount = SectorCount * BlockSize; + + TimeOut = (UINT16) (SectorCount * USBFLPTIMEOUT); + + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + (VOID *) ptrBuffer, + ByteCount, + EfiUsbDataOut, + TimeOut + ); + if (EFI_ERROR (Status)) { + Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts); + if (!EFI_ERROR (Status)) { + if (IsLogicalUnitCommunicationOverRun ( + UsbFloppyDevice->SenseData, + SenseCounts + )) { + Lba32 = (UINT32) Lba; + ptrBuffer = Buffer; + BlocksRemaining = (UINT16) NumberOfBlocks; + MaxBlock = (UINT16) (MaxBlock / 4); + if (MaxBlock < 1) { + MaxBlock = 1; + } + + continue; + } + } + // + // retry write10 command + // + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + (VOID *) ptrBuffer, + ByteCount, + EfiUsbDataOut, + TimeOut + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + } + + Lba32 += SectorCount; + ptrBuffer = (UINT8 *) ptrBuffer + SectorCount * BlockSize; + BlocksRemaining = (UINT16) (BlocksRemaining - SectorCount); + } + + return Status; +} + +EFI_STATUS +UsbFloppyDetectMedia ( + IN USB_FLOPPY_DEV *UsbFloppyDevice, + OUT BOOLEAN *MediaChange + ) +/*++ + + Routine Description: + Retrieves media information. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + MediaChange - Indicates whether media was changed. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success + EFI_INVALID_PARAMETER - Parameter is error +--*/ +{ + EFI_STATUS Status; + EFI_STATUS FloppyStatus; + // + // the following variables are used to record previous media information + // + EFI_BLOCK_IO_MEDIA OldMediaInfo; + UINTN SenseCounts; + UINTN RetryIndex; + UINTN RetryTimes; + UINTN MaximumRetryTimes; + BOOLEAN NeedRetry; + + // + // a flag used to determine whether need to perform Read Capacity command. + // + BOOLEAN NeedReadCapacity; + + REQUEST_SENSE_DATA *SensePtr; + + // + // init + // + Status = EFI_SUCCESS; + FloppyStatus = EFI_SUCCESS; + CopyMem (&OldMediaInfo, UsbFloppyDevice->BlkIo.Media, sizeof (OldMediaInfo)); + //OldMediaInfo = *UsbFloppyDevice->BlkIo.Media; + *MediaChange = FALSE; + NeedReadCapacity = TRUE; + + // + // if there is no media present,or media not changed, + // the request sense command will detect faster than read capacity command. + // read capacity command can be bypassed, thus improve performance. + // + SenseCounts = 0; + Status = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts); + + if (!EFI_ERROR (Status)) { + + SensePtr = UsbFloppyDevice->SenseData; + + // + // No Media + // + if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) { + + NeedReadCapacity = FALSE; + UsbFloppyDevice->BlkIo.Media->MediaId = 0; + UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE; + UsbFloppyDevice->BlkIo.Media->LastBlock = 0; + } else { + // + // Media Changed + // + if (IsMediaChange (UsbFloppyDevice->SenseData, SenseCounts)) { + UsbFloppyDevice->BlkIo.Media->MediaId++; + } + + // + // Media Write-protected + // + if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) { + UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE; + } + + // + // Media Error + // + if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) { + // + // if media error encountered, make it look like no media present. + // + UsbFloppyDevice->BlkIo.Media->MediaId = 0; + UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE; + UsbFloppyDevice->BlkIo.Media->LastBlock = 0; + } + + } + + } + + if (NeedReadCapacity) { + // + // at most retry 5 times + // + MaximumRetryTimes = 5; + // + // initial retry twice + // + RetryTimes = 2; + + for (RetryIndex = 0; (RetryIndex < RetryTimes) && (RetryIndex < MaximumRetryTimes); RetryIndex++) { + // + // Using different command to retrieve media capacity. + // + switch (UsbFloppyDevice->DeviceType) { + + case USBCDROM: + Status = USBFloppyReadCapacity (UsbFloppyDevice); + break; + + case USBFLOPPY: + UsbMassStorageModeSense (UsbFloppyDevice); + Status = USBFloppyReadFormatCapacity (UsbFloppyDevice); + if (EFI_ERROR (Status) || !UsbFloppyDevice->BlkMedia.MediaPresent) { + // + // retry the ReadCapacity command + // + UsbFloppyDevice->DeviceType = USBFLOPPY2; + Status = EFI_DEVICE_ERROR; + } + break; + + case USBFLOPPY2: + UsbMassStorageModeSense (UsbFloppyDevice); + Status = USBFloppyReadCapacity (UsbFloppyDevice); + if (EFI_ERROR (Status)) { + // + // retry the ReadFormatCapacity command + // + UsbFloppyDevice->DeviceType = USBFLOPPY; + } + // + // force the BlockSize to be 0x200. + // + UsbFloppyDevice->BlkIo.Media->BlockSize = 0x200; + break; + + default: + return EFI_INVALID_PARAMETER; + } + + if (!EFI_ERROR (Status)) { + // + // skip the loop when read capacity succeeds. + // + break; + } + + SenseCounts = 0; + + FloppyStatus = UsbFloppyRequestSense (UsbFloppyDevice, &SenseCounts); + + // + // If Request Sense data failed,retry. + // + if (EFI_ERROR (FloppyStatus)) { + // + // retry once more + // + RetryTimes++; + continue; + } + // + // No Media + // + if (IsNoMedia (UsbFloppyDevice->SenseData, SenseCounts)) { + + UsbFloppyDevice->BlkIo.Media->MediaId = 0; + UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE; + UsbFloppyDevice->BlkIo.Media->LastBlock = 0; + break; + } + + if (IsMediaError (UsbFloppyDevice->SenseData, SenseCounts)) { + // + // if media error encountered, make it look like no media present. + // + UsbFloppyDevice->BlkIo.Media->MediaId = 0; + UsbFloppyDevice->BlkIo.Media->MediaPresent = FALSE; + UsbFloppyDevice->BlkIo.Media->LastBlock = 0; + break; + } + + if (IsMediaWriteProtected (UsbFloppyDevice->SenseData, SenseCounts)) { + UsbFloppyDevice->BlkIo.Media->ReadOnly = TRUE; + continue; + } + + if (!IsDriveReady (UsbFloppyDevice->SenseData, SenseCounts, &NeedRetry)) { + + // + // Drive not ready: if NeedRetry, then retry once more; + // else return error + // + if (NeedRetry) { + // + // Stall 0.1 second to wait for drive becoming ready + // + gBS->Stall (100 * STALL_1_MILLI_SECOND); + // + // reset retry variable to zero, + // to make it retry for "drive in progress of becoming ready". + // + RetryIndex = 0; + continue; + } else { + return EFI_DEVICE_ERROR; + } + } + // + // if read capacity fail not for above reasons, retry once more + // + RetryTimes++; + + } + // + // ENDFOR + // + + // + // tell whether the readcapacity process is successful or not + // ("Status" variable record the latest status returned + // by ReadCapacity AND "FloppyStatus" record the latest status + // returned by RequestSense) + // + if (EFI_ERROR (Status) && EFI_ERROR (FloppyStatus)) { + return EFI_DEVICE_ERROR; + } + + } + + if (UsbFloppyDevice->BlkIo.Media->MediaPresent != OldMediaInfo.MediaPresent) { + + if (UsbFloppyDevice->BlkIo.Media->MediaPresent) { + UsbFloppyDevice->BlkIo.Media->MediaId = 1; + } + + *MediaChange = TRUE; + } + + if (UsbFloppyDevice->BlkIo.Media->ReadOnly != OldMediaInfo.ReadOnly) { + *MediaChange = TRUE; + UsbFloppyDevice->BlkIo.Media->MediaId += 1; + } + + if (UsbFloppyDevice->BlkIo.Media->BlockSize != OldMediaInfo.BlockSize) { + *MediaChange = TRUE; + UsbFloppyDevice->BlkIo.Media->MediaId += 1; + } + + if (UsbFloppyDevice->BlkIo.Media->LastBlock != OldMediaInfo.LastBlock) { + *MediaChange = TRUE; + UsbFloppyDevice->BlkIo.Media->MediaId += 1; + } + + if (UsbFloppyDevice->BlkIo.Media->MediaId != OldMediaInfo.MediaId) { + *MediaChange = TRUE; + } + + return EFI_SUCCESS; +} + + + +EFI_STATUS +UsbFloppyModeSense5APage5 ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ) +/*++ + + Routine Description: + Retrieves media capacity information via sending Read Format + Capacity Packet Command. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success + +--*/ +{ + // + // status returned by Read Capacity Packet Command + // + EFI_STATUS Status; + ATAPI_PACKET_COMMAND Packet; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + UFI_MODE_PARAMETER_PAGE_5 ModePage5; + EFI_LBA LastBlock; + UINT32 SectorsPerTrack; + UINT32 NumberOfCylinders; + UINT32 NumberOfHeads; + UINT32 DataBytesPerSector; + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + ZeroMem (&ModePage5, sizeof (UFI_MODE_PARAMETER_PAGE_5)); + + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A; + // + // Flexible Disk Page + // + Packet.ModeSenseUFI.page_code = 5; + // + // current values + // + Packet.ModeSenseUFI.page_control = 0; + Packet.ModeSenseUFI.parameter_list_length_hi = 0; + Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_5); + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + (VOID *) &ModePage5, + sizeof (UFI_MODE_PARAMETER_PAGE_5), + EfiUsbDataIn, + USBFLPTIMEOUT + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + NumberOfHeads = ModePage5.flex_disk_page.number_of_heads; + SectorsPerTrack = ModePage5.flex_disk_page.sectors_per_track; + NumberOfCylinders = ModePage5.flex_disk_page.number_of_cylinders_msb << 8 | + ModePage5.flex_disk_page.number_of_cylinders_lsb; + + LastBlock = SectorsPerTrack * NumberOfHeads * NumberOfCylinders; + DataBytesPerSector = ModePage5.flex_disk_page.databytes_per_sector_msb << 8 | + ModePage5.flex_disk_page.databytes_per_sector_lsb; + + UsbFloppyDevice->BlkIo.Media->LastBlock = LastBlock; + + UsbFloppyDevice->BlkIo.Media->LastBlock--; + + UsbFloppyDevice->BlkIo.Media->BlockSize = DataBytesPerSector; + + UsbFloppyDevice->BlkIo.Media->MediaPresent = TRUE; + + UsbFloppyDevice->BlkIo.Media->ReadOnly = + ModePage5.mode_param_header.write_protected; + + return EFI_SUCCESS; + +} + +EFI_STATUS +UsbFloppyModeSense5APage1C ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ) +/*++ + + Routine Description: + Retrieves media capacity information via sending Read Format + Capacity Packet Command. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success + +--*/ +{ + // + // status returned by Read Capacity Packet Command + // + EFI_STATUS Status; + ATAPI_PACKET_COMMAND Packet; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + UFI_MODE_PARAMETER_PAGE_1C ModePage1C; + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + ZeroMem (&ModePage1C, sizeof (UFI_MODE_PARAMETER_PAGE_1C)); + + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A; + // + // Flexible Disk Page + // + Packet.ModeSenseUFI.page_code = 0x1C; + // + // current values + // + Packet.ModeSenseUFI.page_control = 0; + Packet.ModeSenseUFI.parameter_list_length_hi = 0; + Packet.ModeSenseUFI.parameter_list_length_lo = sizeof (UFI_MODE_PARAMETER_PAGE_1C); + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + (VOID *) &ModePage1C, + sizeof (UFI_MODE_PARAMETER_PAGE_1C), + EfiUsbDataIn, + USBFLPTIMEOUT + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + UsbFloppyDevice->BlkIo.Media->ReadOnly = ModePage1C.mode_param_header.write_protected; + + return EFI_SUCCESS; + +} + +EFI_STATUS +UsbMassStorageModeSense ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ) +{ + if (UsbFloppyDevice->AtapiProtocol->CommandProtocol == EFI_USB_SUBCLASS_SCSI) { + return UsbSCSIModeSense1APage3F (UsbFloppyDevice); + } else { + return UsbFloppyModeSense5APage3F (UsbFloppyDevice); + } +} + +EFI_STATUS +UsbFloppyModeSense5APage3F ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ) +/*++ + + Routine Description: + Retrieves mode sense information via sending Mode Sense + Packet Command. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success + +--*/ +{ + // + // status returned by Read Capacity Packet Command + // + EFI_STATUS Status; + ATAPI_PACKET_COMMAND Packet; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + UFI_MODE_PARAMETER_HEADER Header; + UINT32 Size; + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + Size = sizeof (UFI_MODE_PARAMETER_HEADER); + + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.ModeSenseUFI.opcode = UFI_MODE_SENSE5A; + Packet.ModeSenseUFI.page_code = 0x3F; + Packet.ModeSenseUFI.page_control = 0; + Packet.ModeSenseUFI.parameter_list_length_hi = 0; + Packet.ModeSenseUFI.parameter_list_length_lo = (UINT8) Size; + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (ATAPI_PACKET_COMMAND), + &Header, + Size, + EfiUsbDataIn, + USBFLPTIMEOUT + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected; + + return EFI_SUCCESS; + +} + +EFI_STATUS +UsbSCSIModeSense1APage3F ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ) +/*++ + + Routine Description: + Retrieves mode sense information via sending Mode Sense + Packet Command. + + Arguments: + UsbFloppyDevice - The USB_FLOPPY_DEV instance. + + Returns: + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success + +--*/ +{ + // + // status returned by Read Capacity Packet Command + // + EFI_STATUS Status; + ATAPI_PACKET_COMMAND Packet; + EFI_USB_ATAPI_PROTOCOL *UsbAtapiInterface; + SCSI_MODE_PARAMETER_HEADER6 Header; + UINT32 Size; + + UsbAtapiInterface = UsbFloppyDevice->AtapiProtocol; + + Size = sizeof (SCSI_MODE_PARAMETER_HEADER6); + + ZeroMem (&Packet, sizeof (ATAPI_PACKET_COMMAND)); + Packet.ModeSenseSCSI.opcode = SCSI_MODE_SENSE1A; + Packet.ModeSenseSCSI.page_code = 0x3F; + Packet.ModeSenseSCSI.page_control = 0; + Packet.ModeSenseSCSI.allocation_length = (UINT8) Size; + Status = USBFloppyPacketCommand ( + UsbFloppyDevice, + &Packet, + sizeof (MODE_SENSE_CMD_SCSI), + &Header, + Size, + EfiUsbDataIn, + USBFLPTIMEOUT + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + UsbFloppyDevice->BlkIo.Media->ReadOnly = Header.write_protected; + return EFI_SUCCESS; + +} + +/*++ + + The following functions are a set of helper functions, + which are used to parse sense key returned by the device. + +--*/ +BOOLEAN +IsNoMedia ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +{ + REQUEST_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN NoMedia; + + NoMedia = FALSE; + + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + if ((SensePtr->sense_key == SK_NOT_READY) && + (SensePtr->addnl_sense_code == ASC_NO_MEDIA)) { + + NoMedia = TRUE; + } + + SensePtr++; + } + + return NoMedia; +} + + +BOOLEAN +IsMediaError ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +{ + REQUEST_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsError; + + IsError = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + switch (SensePtr->sense_key) { + + // + // Medium error case + // + case SK_MEDIUM_ERROR: + switch (SensePtr->addnl_sense_code) { + + case ASC_MEDIA_ERR1: + case ASC_MEDIA_ERR2: + case ASC_MEDIA_ERR3: + case ASC_MEDIA_ERR4: + IsError = TRUE; + break; + + default: + break; + } + + break; + + // + // Medium upside-down case + // + case SK_NOT_READY: + switch (SensePtr->addnl_sense_code) { + case ASC_MEDIA_UPSIDE_DOWN: + IsError = TRUE; + break; + + default: + break; + } + break; + + default: + break; + } + + SensePtr++; + } + + return IsError; +} + +BOOLEAN +IsMediaChange ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +{ + REQUEST_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN MediaChanged; + + MediaChanged = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + if ((SensePtr->sense_key == SK_UNIT_ATTENTION) && + (SensePtr->addnl_sense_code == ASC_MEDIA_CHANGE)) { + + MediaChanged = TRUE; + } + + SensePtr++; + } + + return MediaChanged; +} + +BOOLEAN +IsDriveReady ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts, + OUT BOOLEAN *NeedRetry + ) +{ + REQUEST_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsReady; + + IsReady = TRUE; + *NeedRetry = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + if ((SensePtr->sense_key == SK_NOT_READY) && + (SensePtr->addnl_sense_code == ASC_NOT_READY)) { + + switch (SensePtr->addnl_sense_code_qualifier) { + + case ASCQ_IN_PROGRESS: + case ASCQ_DEVICE_BUSY: + IsReady = FALSE; + *NeedRetry = TRUE; + break; + + default: + // + // Drive is in error condition, + // no need to retry. + // + IsReady = FALSE; + *NeedRetry = FALSE; + break; + } + } + + SensePtr++; + } + + return IsReady; +} + +BOOLEAN +IsMediaWriteProtected ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +{ + REQUEST_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsWriteProtected; + + IsWriteProtected = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + // + // catch media write-protected condition. + // + if ((SensePtr->sense_key == SK_DATA_PROTECT) && + (SensePtr->addnl_sense_code == ASC_WRITE_PROTECTED)) { + + IsWriteProtected = TRUE; + } + + SensePtr++; + } + + return IsWriteProtected; +} + +BOOLEAN +IsLogicalUnitCommunicationOverRun ( + IN REQUEST_SENSE_DATA *SenseData, + IN UINTN SenseCounts + ) +{ + REQUEST_SENSE_DATA *SensePtr; + UINTN Index; + BOOLEAN IsOverRun; + + IsOverRun = FALSE; + SensePtr = SenseData; + + for (Index = 0; Index < SenseCounts; Index++) { + + if ((SensePtr->sense_key == SK_NOT_READY) && + (SensePtr->addnl_sense_code == ASC_LOGICAL_UNIT_STATUS) && + (SensePtr->addnl_sense_code_qualifier == ASCQ_LOGICAL_UNIT_OVERRUN)) { + IsOverRun = TRUE; + } + + SensePtr++; + } + + return IsOverRun; +} diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h new file mode 100644 index 0000000000..f41241adc4 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/UsbMassStorageHelper.h @@ -0,0 +1,111 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + UsbMassStorageHelper.h + +Abstract: + + Function prototype for USB Mass Storage Driver + +Revision History +--*/ +#ifndef _USB_FLPHLP_H +#define _USB_FLPHLP_H + +#include "UsbMassStorage.h" + +EFI_STATUS +USBFloppyIdentify ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ); + +EFI_STATUS +USBFloppyPacketCommand ( + USB_FLOPPY_DEV *UsbFloppyDevice, + VOID *Command, + UINT8 CommandSize, + VOID *DataBuffer, + UINT32 BufferLength, + EFI_USB_DATA_DIRECTION Direction, + UINT16 TimeOutInMilliSeconds + ); + +EFI_STATUS +USBFloppyInquiry ( + IN USB_FLOPPY_DEV *UsbFloppyDevice, + OUT USB_INQUIRY_DATA **Idata + ); + +EFI_STATUS +USBFloppyRead10 ( + IN USB_FLOPPY_DEV *UsbFloppyDevice, + IN VOID *Buffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ); + +EFI_STATUS +USBFloppyReadFormatCapacity ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ); + +EFI_STATUS +UsbFloppyRequestSense ( + IN USB_FLOPPY_DEV *UsbFloppyDevice, + OUT UINTN *SenseCounts + ); + +EFI_STATUS +UsbFloppyTestUnitReady ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ); + +EFI_STATUS +USBFloppyWrite10 ( + IN USB_FLOPPY_DEV *UsbFloppyDevice, + IN VOID *Buffer, + IN EFI_LBA Lba, + IN UINTN NumberOfBlocks + ); + +EFI_STATUS +UsbFloppyDetectMedia ( + IN USB_FLOPPY_DEV *UsbFloppyDevice, + OUT BOOLEAN *MediaChange + ); + +EFI_STATUS +UsbFloppyModeSense5APage5 ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ); + +EFI_STATUS +UsbFloppyModeSense5APage1C ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ); + +EFI_STATUS +UsbFloppyModeSense5APage3F ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ); + +EFI_STATUS +UsbSCSIModeSense1APage3F ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ); + +EFI_STATUS +UsbMassStorageModeSense ( + IN USB_FLOPPY_DEV *UsbFloppyDevice + ); + +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml new file mode 100644 index 0000000000..d2e48d3027 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMassStorage/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/ComponentName.c b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/ComponentName.c new file mode 100644 index 0000000000..5b01cea9d4 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/ComponentName.c @@ -0,0 +1,216 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "usbmouse.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +UsbMouseComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +UsbMouseComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gUsbMouseComponentName = { + UsbMouseComponentNameGetDriverName, + UsbMouseComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mUsbMouseDriverNameTable[] = { + { "eng", (CHAR16 *) L"Usb Mouse Driver" }, + { NULL , NULL } +}; + + +EFI_STATUS +EFIAPI +UsbMouseComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gUsbMouseComponentName.SupportedLanguages, + mUsbMouseDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +UsbMouseComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + USB_MOUSE_DEV *UsbMouseDev; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol; + EFI_USB_IO_PROTOCOL *UsbIoProtocol; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Check Controller's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIoProtocol, + gUsbMouseDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiUsbIoProtocolGuid, + gUsbMouseDriverBinding.DriverBindingHandle, + ControllerHandle + ); + + return EFI_UNSUPPORTED; + } + + if (Status != EFI_ALREADY_STARTED) { + return EFI_UNSUPPORTED; + } + // + // Get the device context + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointerProtocol, + gUsbMouseDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + UsbMouseDev = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (SimplePointerProtocol); + + return LookupUnicodeString ( + Language, + gUsbMouseComponentName.SupportedLanguages, + UsbMouseDev->ControllerNameTable, + ControllerName + ); + +} diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.mbd b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.mbd new file mode 100644 index 0000000000..88b3e47a97 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.mbd @@ -0,0 +1,43 @@ + + + + + UsbMouse + 2D2E62AA-9ECF-43b7-8219-94E7FC713DFE + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + EdkUsbLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.msa b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.msa new file mode 100644 index 0000000000..8d2e1a2999 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/UsbMouse.msa @@ -0,0 +1,71 @@ + + + + + UsbMouse + DXE_DRIVER + BS_DRIVER + 2D2E62AA-9ECF-43b7-8219-94E7FC713DFE + 0 + Component description file for UsbMouse module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + EdkUsbLib + ReportStatusCodeLib + MemoryAllocationLib + UefiBootServicesTableLib + + + usbmouse.h + usbmouse.c + mousehid.h + mousehid.c + ComponentName.c + + + MdePkg + EdkModulePkg + + + DevicePath + UsbIo + SimplePointer + + + + + + + gUsbMouseDriverBinding + gUsbMouseComponentName + + + diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/build.xml b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/build.xml new file mode 100644 index 0000000000..081a9e0582 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.c b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.c new file mode 100644 index 0000000000..cbe0970484 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.c @@ -0,0 +1,395 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Mousehid.c + +Abstract: + Parse mouse hid descriptor + +--*/ + +#include "usbmouse.h" +#include "mousehid.h" + +// +// Get an item from report descriptor +// +STATIC +UINT8 * +GetNextItem ( + IN UINT8 *StartPos, + IN UINT8 *EndPos, + OUT HID_ITEM *HidItem + ) +/*++ + +Routine Description: + + Get Next Item + +Arguments: + + StartPos - Start Position + EndPos - End Position + HidItem - HidItem to return + +Returns: + Position + +--*/ +{ + UINT8 Temp; + + if ((EndPos - StartPos) <= 0) { + return NULL; + } + + Temp = *StartPos; + StartPos++; + // + // bit 2,3 + // + HidItem->Type = (UINT8) ((Temp >> 2) & 0x03); + // + // bit 4-7 + // + HidItem->Tag = (UINT8) ((Temp >> 4) & 0x0F); + + if (HidItem->Tag == HID_ITEM_TAG_LONG) { + // + // Long Items are not supported by HID rev1.0, + // although we try to parse it. + // + HidItem->Format = HID_ITEM_FORMAT_LONG; + + if ((EndPos - StartPos) >= 2) { + HidItem->Size = *StartPos++; + HidItem->Tag = *StartPos++; + + if ((EndPos - StartPos) >= HidItem->Size) { + HidItem->Data.LongData = StartPos; + StartPos += HidItem->Size; + return StartPos; + } + } + } else { + HidItem->Format = HID_ITEM_FORMAT_SHORT; + // + // bit 0, 1 + // + HidItem->Size = (UINT8) (Temp & 0x03); + switch (HidItem->Size) { + + case 0: + // + // No data + // + return StartPos; + + case 1: + // + // One byte data + // + if ((EndPos - StartPos) >= 1) { + HidItem->Data.U8 = *StartPos++; + return StartPos; + } + + case 2: + // + // Two byte data + // + if ((EndPos - StartPos) >= 2) { + CopyMem (&HidItem->Data.U16, StartPos, sizeof (UINT16)); + StartPos += 2; + return StartPos; + } + + case 3: + // + // 4 byte data, adjust size + // + HidItem->Size++; + if ((EndPos - StartPos) >= 4) { + CopyMem (&HidItem->Data.U32, StartPos, sizeof (UINT32)); + StartPos += 4; + return StartPos; + } + } + } + + return NULL; +} + +STATIC +UINT32 +GetItemData ( + IN HID_ITEM *HidItem + ) +/*++ + +Routine Description: + + Get Item Data + +Arguments: + + HidItem - HID_ITEM + +Returns: + HidItem Data + + +--*/ +{ + // + // Get Data from HID_ITEM structure + // + switch (HidItem->Size) { + + case 1: + return HidItem->Data.U8; + + case 2: + return HidItem->Data.U16; + + case 4: + return HidItem->Data.U32; + } + + return 0; +} + +STATIC +VOID +ParseLocalItem ( + IN USB_MOUSE_DEV *UsbMouse, + IN HID_ITEM *LocalItem + ) +/*++ + +Routine Description: + + Parse Local Item + +Arguments: + + UsbMouse - USB_MOUSE_DEV + LocalItem - Local Item + +Returns: + +--*/ +{ + UINT32 Data; + + if (LocalItem->Size == 0) { + // + // No expected data for local item + // + return ; + } + + Data = GetItemData (LocalItem); + + switch (LocalItem->Tag) { + + case HID_LOCAL_ITEM_TAG_DELIMITER: + // + // we don't support delimiter here + // + return ; + + case HID_LOCAL_ITEM_TAG_USAGE: + return ; + + case HID_LOCAL_ITEM_TAG_USAGE_MINIMUM: + if (UsbMouse->PrivateData.ButtonDetected) { + UsbMouse->PrivateData.ButtonMinIndex = (UINT8) Data; + } + + return ; + + case HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM: + { + if (UsbMouse->PrivateData.ButtonDetected) { + UsbMouse->PrivateData.ButtonMaxIndex = (UINT8) Data; + } + + return ; + } + } +} + +STATIC +VOID +ParseGlobalItem ( + IN USB_MOUSE_DEV *UsbMouse, + IN HID_ITEM *GlobalItem + ) +{ + UINT8 UsagePage; + + switch (GlobalItem->Tag) { + case HID_GLOBAL_ITEM_TAG_USAGE_PAGE: + { + UsagePage = (UINT8) GetItemData (GlobalItem); + + // + // We only care Button Page here + // + if (UsagePage == 0x09) { + // + // Button Page + // + UsbMouse->PrivateData.ButtonDetected = TRUE; + return ; + } + break; + } + + } +} + + +STATIC +VOID +ParseMainItem ( + IN USB_MOUSE_DEV *UsbMouse, + IN HID_ITEM *MainItem + ) +/*++ + +Routine Description: + + Parse Main Item + +Arguments: + + UsbMouse - TODO: add argument description + MainItem - HID_ITEM to parse + +Returns: + + VOID + +--*/ +{ + // + // we don't care any main items, just skip + // + return ; +} + +STATIC +VOID +ParseHidItem ( + IN USB_MOUSE_DEV *UsbMouse, + IN HID_ITEM *HidItem + ) +/*++ + +Routine Description: + + Parse Hid Item + +Arguments: + + UsbMouse - USB_MOUSE_DEV + HidItem - HidItem to parse + +Returns: + + VOID + +--*/ +{ + switch (HidItem->Type) { + + case HID_ITEM_TYPE_MAIN: + // + // For Main Item, parse main item + // + ParseMainItem (UsbMouse, HidItem); + break; + + case HID_ITEM_TYPE_GLOBAL: + // + // For global Item, parse global item + // + ParseGlobalItem (UsbMouse, HidItem); + break; + + case HID_ITEM_TYPE_LOCAL: + // + // For Local Item, parse local item + // + ParseLocalItem (UsbMouse, HidItem); + break; + } +} +// +// A simple parse just read some field we are interested in +// +EFI_STATUS +ParseMouseReportDescriptor ( + IN USB_MOUSE_DEV *UsbMouse, + IN UINT8 *ReportDescriptor, + IN UINTN ReportSize + ) +/*++ + +Routine Description: + + Parse Mouse Report Descriptor + +Arguments: + + UsbMouse - USB_MOUSE_DEV + ReportDescriptor - Report descriptor to parse + ReportSize - Report descriptor size + +Returns: + + EFI_DEVICE_ERROR - Report descriptor error + EFI_SUCCESS - Success + +--*/ +{ + UINT8 *DescriptorEnd; + UINT8 *ptr; + HID_ITEM HidItem; + + DescriptorEnd = ReportDescriptor + ReportSize; + + ptr = GetNextItem (ReportDescriptor, DescriptorEnd, &HidItem); + + while (ptr != NULL) { + if (HidItem.Format != HID_ITEM_FORMAT_SHORT) { + // + // Long Format Item is not supported at current HID revision + // + return EFI_DEVICE_ERROR; + } + + ParseHidItem (UsbMouse, &HidItem); + + ptr = GetNextItem (ptr, DescriptorEnd, &HidItem); + } + + UsbMouse->NumberOfButtons = (UINT8) (UsbMouse->PrivateData.ButtonMaxIndex - UsbMouse->PrivateData.ButtonMinIndex + 1); + UsbMouse->XLogicMax = UsbMouse->YLogicMax = 127; + UsbMouse->XLogicMin = UsbMouse->YLogicMin = -127; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.h b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.h new file mode 100644 index 0000000000..ccce8354ea --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/mousehid.h @@ -0,0 +1,84 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MouseHid.h + +Abstract: + +--*/ + +#ifndef __MOUSE_HID_H +#define __MOUSE_HID_H + +#include "usbmouse.h" + +// +// HID Item general structure +// +typedef struct _hid_item { + UINT16 Format; + UINT8 Size; + UINT8 Type; + UINT8 Tag; + union { + UINT8 U8; + UINT16 U16; + UINT32 U32; + INT8 I8; + INT16 I16; + INT32 I32; + UINT8 *LongData; + } Data; +} HID_ITEM; + +typedef struct { + UINT16 UsagePage; + INT32 LogicMin; + INT32 LogicMax; + INT32 PhysicalMin; + INT32 PhysicalMax; + UINT16 UnitExp; + UINT16 UINT; + UINT16 ReportId; + UINT16 ReportSize; + UINT16 ReportCount; +} HID_GLOBAL; + +typedef struct { + UINT16 Usage[16]; /* usage array */ + UINT16 UsageIndex; + UINT16 UsageMin; +} HID_LOCAL; + +typedef struct { + UINT16 Type; + UINT16 Usage; +} HID_COLLECTION; + +typedef struct { + HID_GLOBAL Global; + HID_GLOBAL GlobalStack[8]; + UINT32 GlobalStackPtr; + HID_LOCAL Local; + HID_COLLECTION CollectionStack[8]; + UINT32 CollectionStackPtr; +} HID_PARSER; + +EFI_STATUS +ParseMouseReportDescriptor ( + IN USB_MOUSE_DEV *UsbMouse, + IN UINT8 *ReportDescriptor, + IN UINTN ReportSize + ); + +#endif diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.c b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.c new file mode 100644 index 0000000000..81da0205a4 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.c @@ -0,0 +1,1028 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + + UsbMouse.c + + Abstract: + +--*/ + +#include "usbmouse.h" +#include "mousehid.h" + +// +// Prototypes +// Driver model protocol interface +// +EFI_STATUS +EFIAPI +USBMouseDriverBindingEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +USBMouseDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +USBMouseDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +USBMouseDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + + +EFI_DRIVER_BINDING_PROTOCOL gUsbMouseDriverBinding = { + USBMouseDriverBindingSupported, + USBMouseDriverBindingStart, + USBMouseDriverBindingStop, + 0x10, + NULL, + NULL +}; + +// +// helper functions +// +STATIC +BOOLEAN +IsUsbMouse ( + IN EFI_USB_IO_PROTOCOL *UsbIo + ); + +STATIC +EFI_STATUS +InitializeUsbMouseDevice ( + IN USB_MOUSE_DEV *UsbMouseDev + ); + +STATIC +VOID +EFIAPI +UsbMouseWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// Mouse interrupt handler +// +STATIC +EFI_STATUS +EFIAPI +OnMouseInterruptComplete ( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context, + IN UINT32 Result + ); + +// +// Mouse Protocol +// +STATIC +EFI_STATUS +EFIAPI +GetMouseState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + OUT EFI_SIMPLE_POINTER_STATE *MouseState + ); + +STATIC +EFI_STATUS +EFIAPI +UsbMouseReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +EFI_STATUS +EFIAPI +USBMouseDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + that has UsbHcProtocol installed will be supported. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_UNSUPPORTED - This driver does not support this device. + +--*/ +{ + EFI_STATUS OpenStatus; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_STATUS Status; + + OpenStatus = gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (OpenStatus) && (OpenStatus != EFI_ALREADY_STARTED)) { + return EFI_UNSUPPORTED; + } + + if (OpenStatus == EFI_ALREADY_STARTED) { + return EFI_ALREADY_STARTED; + } + + // + // Use the USB I/O protocol interface to see the Controller is + // the Mouse controller that can be managed by this driver. + // + Status = EFI_SUCCESS; + if (!IsUsbMouse (UsbIo)) { + Status = EFI_UNSUPPORTED; + } + + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; +} + +EFI_STATUS +EFIAPI +USBMouseDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Starting the Usb Bus Driver + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_UNSUPPORTED - This driver does not support this device. + EFI_DEVICE_ERROR - This driver cannot be started due to device + Error + EFI_OUT_OF_RESOURCES- Can't allocate memory resources + EFI_ALREADY_STARTED - Thios driver has been started +--*/ +{ + EFI_STATUS Status; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDesc; + USB_MOUSE_DEV *UsbMouseDevice; + UINT8 EndpointNumber; + UINT8 Index; + UINT8 EndpointAddr; + UINT8 PollingInterval; + UINT8 PacketSize; + + UsbMouseDevice = NULL; + Status = EFI_SUCCESS; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + (VOID **) &UsbIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + UsbMouseDevice = AllocateZeroPool (sizeof (USB_MOUSE_DEV)); + if (UsbMouseDevice == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + UsbMouseDevice->UsbIo = UsbIo; + + UsbMouseDevice->Signature = USB_MOUSE_DEV_SIGNATURE; + + UsbMouseDevice->InterfaceDescriptor = AllocatePool (sizeof (EFI_USB_INTERFACE_DESCRIPTOR)); + if (UsbMouseDevice->InterfaceDescriptor == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + + EndpointDesc = AllocatePool (sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)); + if (EndpointDesc == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Get the Device Path Protocol on Controller's handle + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &UsbMouseDevice->DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + // + // Get interface & endpoint descriptor + // + UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + UsbMouseDevice->InterfaceDescriptor + ); + + EndpointNumber = UsbMouseDevice->InterfaceDescriptor->NumEndpoints; + + for (Index = 0; Index < EndpointNumber; Index++) { + UsbIo->UsbGetEndpointDescriptor ( + UsbIo, + Index, + EndpointDesc + ); + + if ((EndpointDesc->Attributes & 0x03) == 0x03) { + + // + // We only care interrupt endpoint here + // + UsbMouseDevice->IntEndpointDescriptor = EndpointDesc; + } + } + + if (UsbMouseDevice->IntEndpointDescriptor == NULL) { + // + // No interrupt endpoint, then error + // + Status = EFI_UNSUPPORTED; + goto ErrorExit; + } + + Status = InitializeUsbMouseDevice (UsbMouseDevice); + if (EFI_ERROR (Status)) { + MouseReportStatusCode ( + UsbMouseDevice->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INTERFACE_ERROR) + ); + + goto ErrorExit; + } + + UsbMouseDevice->SimplePointerProtocol.GetState = GetMouseState; + UsbMouseDevice->SimplePointerProtocol.Reset = UsbMouseReset; + UsbMouseDevice->SimplePointerProtocol.Mode = &UsbMouseDevice->Mode; + + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_WAIT, + EFI_TPL_NOTIFY, + UsbMouseWaitForInput, + UsbMouseDevice, + &((UsbMouseDevice->SimplePointerProtocol).WaitForInput) + ); + if (EFI_ERROR (Status)) { + goto ErrorExit; + } + + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiSimplePointerProtocolGuid, + EFI_NATIVE_INTERFACE, + &UsbMouseDevice->SimplePointerProtocol + ); + + if (EFI_ERROR (Status)) { + Status = EFI_DEVICE_ERROR; + goto ErrorExit; + } + + // + // After Enabling Async Interrupt Transfer on this mouse Device + // we will be able to get key data from it. Thus this is deemed as + // the enable action of the mouse + // + + MouseReportStatusCode ( + UsbMouseDevice->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_MOUSE | EFI_P_PC_ENABLE) + ); + + // + // submit async interrupt transfer + // + EndpointAddr = UsbMouseDevice->IntEndpointDescriptor->EndpointAddress; + PollingInterval = UsbMouseDevice->IntEndpointDescriptor->Interval; + PacketSize = (UINT8) (UsbMouseDevice->IntEndpointDescriptor->MaxPacketSize); + + Status = UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + EndpointAddr, + TRUE, + PollingInterval, + PacketSize, + OnMouseInterruptComplete, + UsbMouseDevice + ); + + if (!EFI_ERROR (Status)) { + + UsbMouseDevice->ControllerNameTable = NULL; + AddUnicodeString ( + "eng", + gUsbMouseComponentName.SupportedLanguages, + &UsbMouseDevice->ControllerNameTable, + (CHAR16 *) L"Generic Usb Mouse" + ); + + return EFI_SUCCESS; + } + + // + // If submit error, uninstall that interface + // + Status = EFI_DEVICE_ERROR; + gBS->UninstallProtocolInterface ( + Controller, + &gEfiSimplePointerProtocolGuid, + &UsbMouseDevice->SimplePointerProtocol + ); + +ErrorExit: + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + if (UsbMouseDevice != NULL) { + if (UsbMouseDevice->InterfaceDescriptor != NULL) { + gBS->FreePool (UsbMouseDevice->InterfaceDescriptor); + } + + if (UsbMouseDevice->IntEndpointDescriptor != NULL) { + gBS->FreePool (UsbMouseDevice->IntEndpointDescriptor); + } + + if ((UsbMouseDevice->SimplePointerProtocol).WaitForInput != NULL) { + gBS->CloseEvent ((UsbMouseDevice->SimplePointerProtocol).WaitForInput); + } + + gBS->FreePool (UsbMouseDevice); + UsbMouseDevice = NULL; + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +USBMouseDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + others + +--*/ +{ + EFI_STATUS Status; + USB_MOUSE_DEV *UsbMouseDevice; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointerProtocol; + EFI_USB_IO_PROTOCOL *UsbIo; + + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointerProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (SimplePointerProtocol); + + gBS->CloseProtocol ( + Controller, + &gEfiSimplePointerProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + UsbIo = UsbMouseDevice->UsbIo; + + // + // Uninstall the Asyn Interrupt Transfer from this device + // will disable the mouse data input from this device + // + MouseReportStatusCode ( + UsbMouseDevice->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_MOUSE | EFI_P_PC_DISABLE) + ); + + // + // Delete Mouse Async Interrupt Transfer + // + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + UsbMouseDevice->IntEndpointDescriptor->EndpointAddress, + FALSE, + UsbMouseDevice->IntEndpointDescriptor->Interval, + 0, + NULL, + NULL + ); + + gBS->CloseEvent (UsbMouseDevice->SimplePointerProtocol.WaitForInput); + + if (UsbMouseDevice->DelayedRecoveryEvent) { + gBS->CloseEvent (UsbMouseDevice->DelayedRecoveryEvent); + UsbMouseDevice->DelayedRecoveryEvent = 0; + } + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiSimplePointerProtocolGuid, + &UsbMouseDevice->SimplePointerProtocol + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiUsbIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->FreePool (UsbMouseDevice->InterfaceDescriptor); + gBS->FreePool (UsbMouseDevice->IntEndpointDescriptor); + + if (UsbMouseDevice->ControllerNameTable) { + FreeUnicodeStringTable (UsbMouseDevice->ControllerNameTable); + } + + gBS->FreePool (UsbMouseDevice); + + return EFI_SUCCESS; + +} + +BOOLEAN +IsUsbMouse ( + IN EFI_USB_IO_PROTOCOL *UsbIo + ) +/*++ + + Routine Description: + Tell if a Usb Controller is a mouse + + Arguments: + UsbIo - Protocol instance pointer. + + Returns: + TRUE - It is a mouse + FALSE - It is not a mouse +--*/ +{ + EFI_STATUS Status; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + + // + // Get the Default interface descriptor, now we only + // suppose it is interface 1 + // + Status = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + + if (EFI_ERROR (Status)) { + return FALSE; + } + + if ((InterfaceDescriptor.InterfaceClass == CLASS_HID) && + (InterfaceDescriptor.InterfaceSubClass == SUBCLASS_BOOT) && + (InterfaceDescriptor.InterfaceProtocol == PROTOCOL_MOUSE) + ) { + return TRUE; + } + + return FALSE; +} + +STATIC +EFI_STATUS +InitializeUsbMouseDevice ( + IN USB_MOUSE_DEV *UsbMouseDev + ) +/*++ + + Routine Description: + Initialize the Usb Mouse Device. + + Arguments: + UsbMouseDev - Device instance to be initialized + + Returns: + EFI_SUCCESS - Success + EFI_DEVICE_ERROR - Init error. + EFI_OUT_OF_RESOURCES- Can't allocate memory +--*/ +{ + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 Protocol; + EFI_STATUS Status; + EFI_USB_HID_DESCRIPTOR MouseHidDesc; + UINT8 *ReportDesc; + + UsbIo = UsbMouseDev->UsbIo; + + // + // Get HID descriptor + // + Status = UsbGetHidDescriptor ( + UsbIo, + UsbMouseDev->InterfaceDescriptor->InterfaceNumber, + &MouseHidDesc + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get Report descriptor + // + if (MouseHidDesc.HidClassDesc[0].DescriptorType != 0x22) { + return EFI_UNSUPPORTED; + } + + ReportDesc = AllocateZeroPool (MouseHidDesc.HidClassDesc[0].DescriptorLength); + if (ReportDesc == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = UsbGetReportDescriptor ( + UsbIo, + UsbMouseDev->InterfaceDescriptor->InterfaceNumber, + MouseHidDesc.HidClassDesc[0].DescriptorLength, + ReportDesc + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (ReportDesc); + return Status; + } + + // + // Parse report descriptor + // + Status = ParseMouseReportDescriptor ( + UsbMouseDev, + ReportDesc, + MouseHidDesc.HidClassDesc[0].DescriptorLength + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (ReportDesc); + return Status; + } + + if (UsbMouseDev->NumberOfButtons >= 1) { + UsbMouseDev->Mode.LeftButton = TRUE; + } + + if (UsbMouseDev->NumberOfButtons > 1) { + UsbMouseDev->Mode.RightButton = TRUE; + } + + UsbMouseDev->Mode.ResolutionX = 8; + UsbMouseDev->Mode.ResolutionY = 8; + UsbMouseDev->Mode.ResolutionZ = 0; + // + // Here we just assume interface 0 is the mouse interface + // + UsbGetProtocolRequest ( + UsbIo, + 0, + &Protocol + ); + + if (Protocol != BOOT_PROTOCOL) { + Status = UsbSetProtocolRequest ( + UsbIo, + 0, + BOOT_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (ReportDesc); + return EFI_DEVICE_ERROR; + } + } + + // + // Set indefinite Idle rate for USB Mouse + // + UsbSetIdleRequest ( + UsbIo, + 0, + 0, + 0 + ); + + gBS->FreePool (ReportDesc); + + if (UsbMouseDev->DelayedRecoveryEvent) { + gBS->CloseEvent (UsbMouseDev->DelayedRecoveryEvent); + UsbMouseDev->DelayedRecoveryEvent = 0; + } + + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_NOTIFY, + USBMouseRecoveryHandler, + UsbMouseDev, + &UsbMouseDev->DelayedRecoveryEvent + ); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +OnMouseInterruptComplete ( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context, + IN UINT32 Result + ) +/*++ + + Routine Description: + It is called whenever there is data received from async interrupt + transfer. + + Arguments: + Data - Data received. + DataLength - Length of Data + Context - Passed in context + Result - Async Interrupt Transfer result + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + +--*/ +{ + USB_MOUSE_DEV *UsbMouseDevice; + EFI_USB_IO_PROTOCOL *UsbIo; + UINT8 EndpointAddr; + UINT32 UsbResult; + + UsbMouseDevice = (USB_MOUSE_DEV *) Context; + UsbIo = UsbMouseDevice->UsbIo; + + if (Result != EFI_USB_NOERROR) { + // + // Some errors happen during the process + // + MouseReportStatusCode ( + UsbMouseDevice->DevicePath, + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_MOUSE | EFI_P_EC_INPUT_ERROR) + ); + + if ((Result & EFI_USB_ERR_STALL) == EFI_USB_ERR_STALL) { + EndpointAddr = UsbMouseDevice->IntEndpointDescriptor->EndpointAddress; + + UsbClearEndpointHalt ( + UsbIo, + EndpointAddr, + &UsbResult + ); + } + + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + UsbMouseDevice->IntEndpointDescriptor->EndpointAddress, + FALSE, + 0, + 0, + NULL, + NULL + ); + + gBS->SetTimer ( + UsbMouseDevice->DelayedRecoveryEvent, + TimerRelative, + EFI_USB_INTERRUPT_DELAY + ); + return EFI_DEVICE_ERROR; + } + + if (DataLength == 0 || Data == NULL) { + return EFI_SUCCESS; + } + + UsbMouseDevice->StateChanged = TRUE; + + // + // Check mouse Data + // + UsbMouseDevice->State.LeftButton = (BOOLEAN) (*(UINT8 *) Data & 0x01); + UsbMouseDevice->State.RightButton = (BOOLEAN) (*(UINT8 *) Data & 0x02); + UsbMouseDevice->State.RelativeMovementX += *((INT8 *) Data + 1); + UsbMouseDevice->State.RelativeMovementY += *((INT8 *) Data + 2); + + if (DataLength > 3) { + UsbMouseDevice->State.RelativeMovementZ += *((INT8 *) Data + 3); + } + + return EFI_SUCCESS; +} + +/* +STATIC VOID +PrintMouseState( + IN EFI_MOUSE_STATE *MouseState + ) +{ + Aprint("(%x: %x, %x)\n", + MouseState->ButtonStates, + MouseState->dx, + MouseState->dy + ); +} +*/ +STATIC +EFI_STATUS +EFIAPI +GetMouseState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + OUT EFI_SIMPLE_POINTER_STATE *MouseState + ) +/*++ + + Routine Description: + Get the mouse state, see SIMPLE POINTER PROTOCOL. + + Arguments: + This - Protocol instance pointer. + MouseState - Current mouse state + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_NOT_READY + +--*/ +{ + USB_MOUSE_DEV *MouseDev; + + if (MouseState == NULL) { + return EFI_DEVICE_ERROR; + } + + MouseDev = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This); + + if (!MouseDev->StateChanged) { + return EFI_NOT_READY; + } + + CopyMem ( + MouseState, + &MouseDev->State, + sizeof (EFI_SIMPLE_POINTER_STATE) + ); + + // + // Clear previous move state + // + MouseDev->State.RelativeMovementX = 0; + MouseDev->State.RelativeMovementY = 0; + MouseDev->State.RelativeMovementZ = 0; + + MouseDev->StateChanged = FALSE; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +UsbMouseReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the mouse device, see SIMPLE POINTER PROTOCOL. + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Ignored here/ + + Returns: + EFI_SUCCESS + +--*/ +{ + USB_MOUSE_DEV *UsbMouseDevice; + EFI_USB_IO_PROTOCOL *UsbIo; + + UsbMouseDevice = USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL (This); + + UsbIo = UsbMouseDevice->UsbIo; + + MouseReportStatusCode ( + UsbMouseDevice->DevicePath, + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_MOUSE | EFI_P_PC_RESET) + ); + + ZeroMem ( + &UsbMouseDevice->State, + sizeof (EFI_SIMPLE_POINTER_STATE) + ); + UsbMouseDevice->StateChanged = FALSE; + + return EFI_SUCCESS; +} + +STATIC +VOID +EFIAPI +UsbMouseWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Event notification function for SIMPLE_POINTER.WaitForInput event + Signal the event if there is input from mouse + +Arguments: + Event - Wait Event + Context - Passed parameter to event handler +Returns: + VOID +--*/ +{ + USB_MOUSE_DEV *UsbMouseDev; + + UsbMouseDev = (USB_MOUSE_DEV *) Context; + + // + // Someone is waiting on the mouse event, if there's + // input from mouse, signal the event + // + if (UsbMouseDev->StateChanged) { + gBS->SignalEvent (Event); + } +} + +VOID +EFIAPI +USBMouseRecoveryHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + + Routine Description: + Timer handler for Delayed Recovery timer. + + Arguments: + Event - The Delayed Recovery event. + Context - Points to the USB_KB_DEV instance. + + Returns: + +--*/ +{ + USB_MOUSE_DEV *UsbMouseDev; + EFI_USB_IO_PROTOCOL *UsbIo; + + UsbMouseDev = (USB_MOUSE_DEV *) Context; + + UsbIo = UsbMouseDev->UsbIo; + + UsbIo->UsbAsyncInterruptTransfer ( + UsbIo, + UsbMouseDev->IntEndpointDescriptor->EndpointAddress, + TRUE, + UsbMouseDev->IntEndpointDescriptor->Interval, + UsbMouseDev->IntEndpointDescriptor->MaxPacketSize, + OnMouseInterruptComplete, + UsbMouseDev + ); +} + +VOID +MouseReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ) +/*++ + + Routine Description: + Report Status Code in Usb Bot Driver + + Arguments: + DevicePath - Use this to get Device Path + CodeType - Status Code Type + CodeValue - Status Code Value + + Returns: + None + +--*/ +{ + + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + CodeType, + Value, + DevicePath + ); +} diff --git a/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.h b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.h new file mode 100644 index 0000000000..8a7dd753b1 --- /dev/null +++ b/EdkModulePkg/Bus/Usb/UsbMouse/Dxe/usbmouse.h @@ -0,0 +1,85 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + + UsbMouse.h + + Abstract: + +--*/ + +#ifndef _USB_MOUSE_H +#define _USB_MOUSE_H + +#include + +#define CLASS_HID 3 +#define SUBCLASS_BOOT 1 +#define PROTOCOL_MOUSE 2 + +#define BOOT_PROTOCOL 0 +#define REPORT_PROTOCOL 1 + +#define USB_MOUSE_DEV_SIGNATURE EFI_SIGNATURE_32 ('u', 'm', 'o', 'u') + +typedef struct { + BOOLEAN ButtonDetected; + UINT8 ButtonMinIndex; + UINT8 ButtonMaxIndex; + UINT8 Reserved; +} PRIVATE_DATA; + +typedef struct { + UINTN Signature; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_EVENT DelayedRecoveryEvent; + EFI_USB_IO_PROTOCOL *UsbIo; + EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor; + EFI_USB_ENDPOINT_DESCRIPTOR *IntEndpointDescriptor; + UINT8 NumberOfButtons; + INT32 XLogicMax; + INT32 XLogicMin; + INT32 YLogicMax; + INT32 YLogicMin; + EFI_SIMPLE_POINTER_PROTOCOL SimplePointerProtocol; + EFI_SIMPLE_POINTER_STATE State; + EFI_SIMPLE_POINTER_MODE Mode; + BOOLEAN StateChanged; + PRIVATE_DATA PrivateData; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} USB_MOUSE_DEV; + +#define USB_MOUSE_DEV_FROM_MOUSE_PROTOCOL(a) \ + CR(a, USB_MOUSE_DEV, SimplePointerProtocol, USB_MOUSE_DEV_SIGNATURE) + +VOID +EFIAPI +USBMouseRecoveryHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gUsbMouseDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gUsbMouseComponentName; +extern EFI_GUID gEfiUsbMouseDriverGuid; + +VOID +MouseReportStatusCode ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value + ); + +#endif diff --git a/EdkModulePkg/Core/Dxe/DebugImageInfo.h b/EdkModulePkg/Core/Dxe/DebugImageInfo.h new file mode 100644 index 0000000000..be1d1f1908 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/DebugImageInfo.h @@ -0,0 +1,126 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugImageInfo.h + +Abstract: + + Support functions for managing debug image info table when loading and unloading + images. + +--*/ + +#ifndef __DEBUG_IMAGE_INFO_H__ +#define __DEBUG_IMAGE_INFO_H__ + +#define FOUR_MEG_PAGES 0x400 +#define FOUR_MEG_MASK ((FOUR_MEG_PAGES * EFI_PAGE_SIZE) - 1) + +#define EFI_DEBUG_TABLE_ENTRY_SIZE (sizeof (VOID *)) + +VOID +CoreInitializeDebugImageInfoTable ( + VOID + ) +/*++ + +Routine Description: + + Creates and initializes the DebugImageInfo Table. Also creates the configuration + table and registers it into the system table. + +Arguments: + None + +Returns: + NA + +Notes: + This function allocates memory, frees it, and then allocates memory at an + address within the initial allocation. Since this function is called early + in DXE core initialization (before drivers are dispatched), this should not + be a problem. + +--*/ +; + +VOID +CoreUpdateDebugTableCrc32 ( + VOID + ) +/*++ + +Routine Description: + + Update the CRC32 in the Debug Table. + Since the CRC32 service is made available by the Runtime driver, we have to + wait for the Runtime Driver to be installed before the CRC32 can be computed. + This function is called elsewhere by the core when the runtime architectural + protocol is produced. + +Arguments: + None + +Returns: + NA + +--*/ +; + +VOID +CoreNewDebugImageInfoEntry ( + UINTN ImageInfoType, + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, + EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates + the table if it's not large enough to accomidate another entry. + +Arguments: + + ImageInfoType - type of debug image information + LoadedImage - pointer to the loaded image protocol for the image being loaded + ImageHandle - image handle for the image being loaded + +Returns: + NA + +--*/ +; + +VOID +CoreRemoveDebugImageInfoEntry ( + EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Removes and frees an entry from the DebugImageInfo Table. + +Arguments: + + ImageHandle - image handle for the image being unloaded + +Returns: + + NA + +--*/ +; + +#endif diff --git a/EdkModulePkg/Core/Dxe/Dispatcher/Dispatcher.c b/EdkModulePkg/Core/Dxe/Dispatcher/Dispatcher.c new file mode 100644 index 0000000000..32ba23a957 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Dispatcher/Dispatcher.c @@ -0,0 +1,1159 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Dispatcher.c + +Abstract: + + Tiano DXE Dispatcher. + + Step #1 - When a FV protocol is added to the system every driver in the FV + is added to the mDiscoveredList. The SOR, Before, and After Depex are + pre-processed as drivers are added to the mDiscoveredList. If an Apriori + file exists in the FV those drivers are addeded to the + mScheduledQueue. The mFvHandleList is used to make sure a + FV is only processed once. + + Step #2 - Dispatch. Remove driver from the mScheduledQueue and load and + start it. After mScheduledQueue is drained check the + mDiscoveredList to see if any item has a Depex that is ready to + be placed on the mScheduledQueue. + + Step #3 - Adding to the mScheduledQueue requires that you process Before + and After dependencies. This is done recursively as the call to add + to the mScheduledQueue checks for Before and recursively adds + all Befores. It then addes the item that was passed in and then + processess the After dependecies by recursively calling the routine. + + Dispatcher Rules: + The rules for the dispatcher are in chapter 10 of the DXE CIS. Figure 10-3 + is the state diagram for the DXE dispatcher + + Depex - Dependency Expresion. + SOR - Schedule On Request - Don't schedule if this bit is set. + +--*/ + +#include + +// +// The Driver List contains one copy of every driver that has been discovered. +// Items are never removed from the driver list. List of EFI_CORE_DRIVER_ENTRY +// +LIST_ENTRY mDiscoveredList = INITIALIZE_LIST_HEAD_VARIABLE (mDiscoveredList); + +// +// Queue of drivers that are ready to dispatch. This queue is a subset of the +// mDiscoveredList.list of EFI_CORE_DRIVER_ENTRY. +// +LIST_ENTRY mScheduledQueue = INITIALIZE_LIST_HEAD_VARIABLE (mScheduledQueue); + +// +// List of handles who's Fv's have been parsed and added to the mFwDriverList. +// +LIST_ENTRY mFvHandleList = INITIALIZE_LIST_HEAD_VARIABLE (mFvHandleList); // list of KNOWN_HANDLE + +// +// Lock for mDiscoveredList, mScheduledQueue, gDispatcherRunning. +// +EFI_LOCK mDispatcherLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL); + + +// +// Flag for the DXE Dispacher. TRUE if dispatcher is execuing. +// +BOOLEAN gDispatcherRunning = FALSE; + +// +// Module globals to manage the FwVol registration notification event +// +EFI_EVENT mFwVolEvent; +VOID *mFwVolEventRegistration; + +// +// List of file types supported by dispatcher +// +static EFI_FV_FILETYPE mDxeFileTypes[] = { + EFI_FV_FILETYPE_DRIVER, + EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER, + EFI_FV_FILETYPE_DXE_CORE, + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +}; + +typedef struct { + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH File; + EFI_DEVICE_PATH_PROTOCOL End; +} FV_FILEPATH_DEVICE_PATH; + +FV_FILEPATH_DEVICE_PATH mFvDevicePath; + + +// +// Function Prototypes +// +VOID +CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter ( + IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry + ); + +VOID +EFIAPI +CoreFwVolEventProtocolNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +EFI_DEVICE_PATH_PROTOCOL * +CoreFvToDevicePath ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, + IN EFI_HANDLE FvHandle, + IN EFI_GUID *DriverName + ); + +STATIC +EFI_STATUS +CoreAddToDriverList ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, + IN EFI_HANDLE FvHandle, + IN EFI_GUID *DriverName + ); + +STATIC +EFI_STATUS +CoreProcessFvImageFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, + IN EFI_HANDLE FvHandle, + IN EFI_GUID *DriverName + ); + + +VOID +CoreAcquireDispatcherLock ( + VOID + ) +/*++ + +Routine Description: + + Enter critical section by gaining lock on mDispatcherLock + +Arguments: + + None + +Returns: + + None + +--*/ + +{ + CoreAcquireLock (&mDispatcherLock); +} + +VOID +CoreReleaseDispatcherLock ( + VOID + ) +/*++ + +Routine Description: + + Exit critical section by releasing lock on mDispatcherLock + +Arguments: + + None + +Returns: + + None + +--*/ +{ + CoreReleaseLock (&mDispatcherLock); +} + + +EFI_STATUS +CoreGetDepexSectionAndPreProccess ( + IN EFI_CORE_DRIVER_ENTRY *DriverEntry + ) +/*++ + +Routine Description: + + Read Depex and pre-process the Depex for Before and After. If Section Extraction + protocol returns an error via ReadSection defer the reading of the Depex. + +Arguments: + + DriverEntry - Driver to work on. + +Returns: + + EFI_SUCCESS - Depex read and preprossesed + + EFI_PROTOCOL_ERROR - The section extraction protocol returned an error and + Depex reading needs to be retried. + + Other Error - DEPEX not found. + +--*/ +{ + EFI_STATUS Status; + EFI_SECTION_TYPE SectionType; + UINT32 AuthenticationStatus; + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + + + Fv = DriverEntry->Fv; + + // + // Grab Depex info, it will never be free'ed. + // + SectionType = EFI_SECTION_DXE_DEPEX; + Status = Fv->ReadSection ( + DriverEntry->Fv, + &DriverEntry->FileName, + SectionType, + 0, + &DriverEntry->Depex, + (UINTN *)&DriverEntry->DepexSize, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + if (Status == EFI_PROTOCOL_ERROR) { + // + // The section extraction protocol failed so set protocol error flag + // + DriverEntry->DepexProtocolError = TRUE; + } else { + // + // If no Depex assume EFI 1.1 driver model + // + DriverEntry->Depex = NULL; + DriverEntry->Dependent = TRUE; + DriverEntry->DepexProtocolError = FALSE; + } + } else { + // + // Set Before, After, and Unrequested state information based on Depex + // Driver will be put in Dependent or Unrequested state + // + CorePreProcessDepex (DriverEntry); + DriverEntry->DepexProtocolError = FALSE; + } + + return Status; +} + +EFI_DXESERVICE +EFI_STATUS +EFIAPI +CoreSchedule ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ) +/*++ + +Routine Description: + + Check every driver and locate a matching one. If the driver is found, the Unrequested + state flag is cleared. + +Arguments: + + FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware + file specified by DriverName. + + DriverName - The Driver name to put in the Dependent state. + +Returns: + + EFI_SUCCESS - The DriverName was found and it's SOR bit was cleared + + EFI_NOT_FOUND - The DriverName does not exist or it's SOR bit was not set. + +--*/ +{ + LIST_ENTRY *Link; + EFI_CORE_DRIVER_ENTRY *DriverEntry; + + // + // Check every driver + // + for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) { + DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE); + if (DriverEntry->FvHandle == FirmwareVolumeHandle && + DriverEntry->Unrequested && + CompareGuid (DriverName, &DriverEntry->FileName)) { + // + // Move the driver from the Unrequested to the Dependent state + // + CoreAcquireDispatcherLock (); + DriverEntry->Unrequested = FALSE; + DriverEntry->Dependent = TRUE; + CoreReleaseDispatcherLock (); + + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + + +EFI_DXESERVICE +EFI_STATUS +EFIAPI +CoreTrust ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ) +/*++ + +Routine Description: + + Convert a driver from the Untrused back to the Scheduled state + +Arguments: + + FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware + file specified by DriverName. + + DriverName - The Driver name to put in the Scheduled state + +Returns: + + EFI_SUCCESS - The file was found in the untrusted state, and it was promoted + to the trusted state. + + EFI_NOT_FOUND - The file was not found in the untrusted state. + +--*/ +{ + LIST_ENTRY *Link; + EFI_CORE_DRIVER_ENTRY *DriverEntry; + + // + // Check every driver + // + for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) { + DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE); + if (DriverEntry->FvHandle == FirmwareVolumeHandle && + DriverEntry->Untrusted && + CompareGuid (DriverName, &DriverEntry->FileName)) { + // + // Transition driver from Untrusted to Scheduled state. + // + CoreAcquireDispatcherLock (); + DriverEntry->Untrusted = FALSE; + DriverEntry->Scheduled = TRUE; + InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink); + CoreReleaseDispatcherLock (); + + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + + +EFI_DXESERVICE +EFI_STATUS +EFIAPI +CoreDispatcher ( + VOID + ) +/*++ + +Routine Description: + + This is the main Dispatcher for DXE and it exits when there are no more + drivers to run. Drain the mScheduledQueue and load and start a PE + image for each driver. Search the mDiscoveredList to see if any driver can + be placed on the mScheduledQueue. If no drivers are placed on the + mScheduledQueue exit the function. On exit it is assumed the Bds() + will be called, and when the Bds() exits the Dispatcher will be called + again. + +Arguments: + + NONE + +Returns: + + EFI_ALREADY_STARTED - The DXE Dispatcher is already running + + EFI_NOT_FOUND - No DXE Drivers were dispatched + + EFI_SUCCESS - One or more DXE Drivers were dispatched + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + LIST_ENTRY *Link; + EFI_CORE_DRIVER_ENTRY *DriverEntry; + BOOLEAN ReadyToRun; + + if (gDispatcherRunning) { + // + // If the dispatcher is running don't let it be restarted. + // + return EFI_ALREADY_STARTED; + } + + gDispatcherRunning = TRUE; + + + ReturnStatus = EFI_NOT_FOUND; + do { + // + // Drain the Scheduled Queue + // + while (!IsListEmpty (&mScheduledQueue)) { + DriverEntry = CR ( + mScheduledQueue.ForwardLink, + EFI_CORE_DRIVER_ENTRY, + ScheduledLink, + EFI_CORE_DRIVER_ENTRY_SIGNATURE + ); + + // + // Load the DXE Driver image into memory. If the Driver was transitioned from + // Untrused to Scheduled it would have already been loaded so we may need to + // skip the LoadImage + // + if (DriverEntry->ImageHandle == NULL) { + Status = CoreLoadImage ( + TRUE, + gDxeCoreImageHandle, + DriverEntry->FvFileDevicePath, + NULL, + 0, + &DriverEntry->ImageHandle + ); + + // + // Update the driver state to reflect that it's been loaded + // + if (EFI_ERROR (Status)) { + CoreAcquireDispatcherLock (); + + if (Status == EFI_SECURITY_VIOLATION) { + // + // Take driver from Scheduled to Untrused state + // + DriverEntry->Untrusted = TRUE; + } else { + // + // The DXE Driver could not be loaded, and do not attempt to load or start it again. + // Take driver from Scheduled to Initialized. + // + // This case include the Never Trusted state if EFI_ACCESS_DENIED is returned + // + DriverEntry->Initialized = TRUE; + } + + DriverEntry->Scheduled = FALSE; + RemoveEntryList (&DriverEntry->ScheduledLink); + + CoreReleaseDispatcherLock (); + + // + // If it's an error don't try the StartImage + // + continue; + } + } + + CoreAcquireDispatcherLock (); + + DriverEntry->Scheduled = FALSE; + DriverEntry->Initialized = TRUE; + RemoveEntryList (&DriverEntry->ScheduledLink); + + CoreReleaseDispatcherLock (); + + + CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_BEGIN, DriverEntry->ImageHandle); + Status = CoreStartImage (DriverEntry->ImageHandle, NULL, NULL); + CoreReportProgressCodeSpecific (EFI_SOFTWARE_DXE_CORE | EFI_SW_PC_INIT_END, DriverEntry->ImageHandle); + + ReturnStatus = EFI_SUCCESS; + } + + // + // Search DriverList for items to place on Scheduled Queue + // + ReadyToRun = FALSE; + for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) { + DriverEntry = CR (Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE); + + if (DriverEntry->DepexProtocolError){ + // + // If Section Extraction Protocol did not let the Depex be read before retry the read + // + Status = CoreGetDepexSectionAndPreProccess (DriverEntry); + } + + if (DriverEntry->Dependent) { + if (CoreIsSchedulable (DriverEntry)) { + CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry); + ReadyToRun = TRUE; + } + } + } + } while (ReadyToRun); + + gDispatcherRunning = FALSE; + + return ReturnStatus; +} + + +VOID +CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter ( + IN EFI_CORE_DRIVER_ENTRY *InsertedDriverEntry + ) +/*++ + +Routine Description: + + Insert InsertedDriverEntry onto the mScheduledQueue. To do this you + must add any driver with a before dependency on InsertedDriverEntry first. + You do this by recursively calling this routine. After all the Befores are + processed you can add InsertedDriverEntry to the mScheduledQueue. + Then you can add any driver with an After dependency on InsertedDriverEntry + by recursively calling this routine. + +Arguments: + + InsertedDriverEntry - The driver to insert on the ScheduledLink Queue + +Returns: + + NONE + +--*/ +{ + LIST_ENTRY *Link; + EFI_CORE_DRIVER_ENTRY *DriverEntry; + + // + // Process Before Dependency + // + for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) { + DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE); + if (DriverEntry->Before && DriverEntry->Dependent) { + if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) { + // + // Recursively process BEFORE + // + CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry); + } + } + } + + // + // Convert driver from Dependent to Scheduled state + // + CoreAcquireDispatcherLock (); + + InsertedDriverEntry->Dependent = FALSE; + InsertedDriverEntry->Scheduled = TRUE; + InsertTailList (&mScheduledQueue, &InsertedDriverEntry->ScheduledLink); + + CoreReleaseDispatcherLock (); + + // + // Process After Dependency + // + for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) { + DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE); + if (DriverEntry->After && DriverEntry->Dependent) { + if (CompareGuid (&InsertedDriverEntry->FileName, &DriverEntry->BeforeAfterGuid)) { + // + // Recursively process AFTER + // + CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter (DriverEntry); + } + } + } +} + + +BOOLEAN +FvHasBeenProcessed ( + IN EFI_HANDLE FvHandle + ) +/*++ + +Routine Description: + + Return TRUE if the Fv has been processed, FALSE if not. + +Arguments: + + FvHandle - The handle of a FV that's being tested + +Returns: + + TRUE - Fv protocol on FvHandle has been processed + + FALSE - Fv protocol on FvHandle has not yet been processed + +--*/ +{ + LIST_ENTRY *Link; + KNOWN_HANDLE *KnownHandle; + + for (Link = mFvHandleList.ForwardLink; Link != &mFvHandleList; Link = Link->ForwardLink) { + KnownHandle = CR(Link, KNOWN_HANDLE, Link, KNOWN_HANDLE_SIGNATURE); + if (KnownHandle->Handle == FvHandle) { + return TRUE; + } + } + return FALSE; +} + + +VOID +FvIsBeingProcesssed ( + IN EFI_HANDLE FvHandle + ) +/*++ + +Routine Description: + + Remember that Fv protocol on FvHandle has had it's drivers placed on the + mDiscoveredList. This fucntion adds entries on the mFvHandleList. Items are + never removed/freed from the mFvHandleList. + +Arguments: + + FvHandle - The handle of a FV that has been processed + +Returns: + + None + +--*/ +{ + KNOWN_HANDLE *KnownHandle; + + KnownHandle = CoreAllocateBootServicesPool (sizeof (KNOWN_HANDLE)); + ASSERT (KnownHandle != NULL); + + KnownHandle->Signature = KNOWN_HANDLE_SIGNATURE; + KnownHandle->Handle = FvHandle; + InsertTailList (&mFvHandleList, &KnownHandle->Link); +} + + + + +EFI_DEVICE_PATH_PROTOCOL * +CoreFvToDevicePath ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, + IN EFI_HANDLE FvHandle, + IN EFI_GUID *DriverName + ) +/*++ + +Routine Description: + + Convert FvHandle and DriverName into an EFI device path + +Arguments: + + Fv - Fv protocol, needed to read Depex info out of FLASH. + + FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the + PE image can be read out of the FV at a later time. + + DriverName - Name of driver to add to mDiscoveredList. + +Returns: + + Pointer to device path constructed from FvHandle and DriverName + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *FvDevicePath; + EFI_DEVICE_PATH_PROTOCOL *FileNameDevicePath; + + // + // Remember the device path of the FV + // + Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath); + if (EFI_ERROR (Status)) { + FileNameDevicePath = NULL; + } else { + // + // Build a device path to the file in the FV to pass into gBS->LoadImage + // + EfiInitializeFwVolDevicepathNode (&mFvDevicePath.File, DriverName); + mFvDevicePath.End.Type = EFI_END_ENTIRE_DEVICE_PATH; + mFvDevicePath.End.SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; + SetDevicePathNodeLength (&mFvDevicePath.End, sizeof (EFI_DEVICE_PATH_PROTOCOL)); + + FileNameDevicePath = CoreAppendDevicePath ( + FvDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath + ); + } + + return FileNameDevicePath; +} + + + +EFI_STATUS +CoreAddToDriverList ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, + IN EFI_HANDLE FvHandle, + IN EFI_GUID *DriverName + ) +/*++ + +Routine Description: + + Add an entry to the mDiscoveredList. Allocate memory to store the DriverEntry, + and initilize any state variables. Read the Depex from the FV and store it + in DriverEntry. Pre-process the Depex to set the SOR, Before and After state. + The Discovered list is never free'ed and contains booleans that represent the + other possible DXE driver states. + +Arguments: + + Fv - Fv protocol, needed to read Depex info out of FLASH. + + FvHandle - Handle for Fv, needed in the EFI_CORE_DRIVER_ENTRY so that the + PE image can be read out of the FV at a later time. + + DriverName - Name of driver to add to mDiscoveredList. + +Returns: + + EFI_SUCCESS - If driver was added to the mDiscoveredList. + + EFI_ALREADY_STARTED - The driver has already been started. Only one DriverName + may be active in the system at any one time. + +--*/ +{ + EFI_CORE_DRIVER_ENTRY *DriverEntry; + + + // + // Create the Driver Entry for the list. ZeroPool initializes lots of variables to + // NULL or FALSE. + // + DriverEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_CORE_DRIVER_ENTRY)); + ASSERT (DriverEntry != NULL); + + DriverEntry->Signature = EFI_CORE_DRIVER_ENTRY_SIGNATURE; + CopyMem (&DriverEntry->FileName, DriverName, sizeof (EFI_GUID)); + DriverEntry->FvHandle = FvHandle; + DriverEntry->Fv = Fv; + DriverEntry->FvFileDevicePath = CoreFvToDevicePath (Fv, FvHandle, DriverName); + + CoreGetDepexSectionAndPreProccess (DriverEntry); + + CoreAcquireDispatcherLock (); + + InsertTailList (&mDiscoveredList, &DriverEntry->Link); + + CoreReleaseDispatcherLock (); + + return EFI_SUCCESS; +} + + + +EFI_STATUS +CoreProcessFvImageFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *Fv, + IN EFI_HANDLE FvHandle, + IN EFI_GUID *DriverName + ) +/*++ + +Routine Description: + + Get the driver from the FV through driver name, and produce a FVB protocol on FvHandle. + +Arguments: + + Fv - The FIRMWARE_VOLUME protocol installed on the FV. + FvHandle - The handle which FVB protocol installed on. + DriverName - The driver guid specified. + +Returns: + + EFI_OUT_OF_RESOURCES - No enough memory or other resource. + + EFI_VOLUME_CORRUPTED - Corrupted volume. + + EFI_SUCCESS - Function successfully returned. + + +--*/ +{ + EFI_STATUS Status; + EFI_SECTION_TYPE SectionType; + UINT32 AuthenticationStatus; + VOID *Buffer; + UINTN BufferSize; + + // + // Read the first (and only the first) firmware volume section + // + SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; + Buffer = NULL; + BufferSize = 0; + Status = Fv->ReadSection ( + Fv, + DriverName, + SectionType, + 0, + &Buffer, + &BufferSize, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + // + // Produce a FVB protocol for the file + // + Status = ProduceFVBProtocolOnBuffer ( + (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, + (UINT64)BufferSize, + FvHandle, + NULL + ); + } + + if (EFI_ERROR (Status) && (Buffer != NULL)) { + // + // ReadSection or Produce FVB failed, Free data buffer + // + CoreFreePool (Buffer); + + } + + return Status; +} + + +VOID +EFIAPI +CoreFwVolEventProtocolNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Event notification that is fired every time a FV dispatch protocol is added. + More than one protocol may have been added when this event is fired, so you + must loop on CoreLocateHandle () to see how many protocols were added and + do the following to each FV: + + If the Fv has already been processed, skip it. If the Fv has not been + processed then mark it as being processed, as we are about to process it. + + Read the Fv and add any driver in the Fv to the mDiscoveredList.The + mDiscoveredList is never free'ed and contains variables that define + the other states the DXE driver transitions to.. + + While you are at it read the A Priori file into memory. + Place drivers in the A Priori list onto the mScheduledQueue. + +Arguments: + + Event - The Event that is being processed, not used. + + Context - Event Context, not used. + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS GetNextFileStatus; + EFI_STATUS SecurityStatus; + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + EFI_DEVICE_PATH_PROTOCOL *FvDevicePath; + EFI_HANDLE FvHandle; + UINTN BufferSize; + EFI_GUID NameGuid; + UINTN Key; + EFI_FV_FILETYPE Type; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN Size; + EFI_CORE_DRIVER_ENTRY *DriverEntry; + EFI_GUID *AprioriFile; + UINTN AprioriEntryCount; + UINTN Index; + LIST_ENTRY *Link; + UINT32 AuthenticationStatus; + UINTN SizeOfBuffer; + + + while (TRUE) { + BufferSize = sizeof (EFI_HANDLE); + Status = CoreLocateHandle ( + ByRegisterNotify, + NULL, + mFwVolEventRegistration, + &BufferSize, + &FvHandle + ); + if (EFI_ERROR (Status)) { + // + // If no more notification events exit + // + return; + } + + if (FvHasBeenProcessed (FvHandle)) { + // + // This Fv has already been processed so lets skip it! + // + continue; + } + + Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeDispatchProtocolGuid, (VOID **)&Fv); + if (EFI_ERROR (Status)) { + // + // If no dispatch protocol then skip, but do not marked as being processed as it + // may show up later. + // + continue; + } + + // + // Since we are about to process this Fv mark it as processed. + // + FvIsBeingProcesssed (FvHandle); + + + Status = CoreHandleProtocol (FvHandle, &gEfiFirmwareVolumeProtocolGuid, (VOID **)&Fv); + if (EFI_ERROR (Status)) { + // + // The Handle has a FirmwareVolumeDispatch protocol and should also contiain + // a FirmwareVolume protocol thus we should never get here. + // + ASSERT (FALSE); + continue; + } + + Status = CoreHandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath); + if (EFI_ERROR (Status)) { + // + // The Firmware volume doesn't have device path, can't be dispatched. + // + continue; + } + + // + // Evaluate the authentication status of the Firmware Volume through + // Security Architectural Protocol + // + if (gSecurity != NULL) { + SecurityStatus = gSecurity->FileAuthenticationState ( + gSecurity, + 0, + FvDevicePath + ); + if (SecurityStatus != EFI_SUCCESS) { + // + // Security check failed. The firmware volume should not be used for any purpose. + // + continue; + } + } + + // + // Discover Drivers in FV and add them to the Discovered Driver List. + // Process EFI_FV_FILETYPE_DRIVER type and then EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER + // EFI_FV_FILETYPE_DXE_CORE is processed to produce a Loaded Image protocol for the core + // EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE is processed to create a Fvb + // + for (Index = 0; Index < sizeof (mDxeFileTypes)/sizeof (EFI_FV_FILETYPE); Index++) { + // + // Initialize the search key + // + Key = 0; + do { + Type = mDxeFileTypes[Index]; + GetNextFileStatus = Fv->GetNextFile ( + Fv, + &Key, + &Type, + &NameGuid, + &Attributes, + &Size + ); + if (!EFI_ERROR (GetNextFileStatus)) { + if (Type == EFI_FV_FILETYPE_DXE_CORE) { + // + // If this is the DXE core fill in it's DevicePath & DeviceHandle + // + if (gDxeCoreLoadedImage->FilePath == NULL) { + if (CompareGuid (&NameGuid, gDxeCoreFileName)) { + CopyGuid (&mFvDevicePath.File.NameGuid, &NameGuid); + + gDxeCoreLoadedImage->FilePath = CoreDuplicateDevicePath ( + (EFI_DEVICE_PATH_PROTOCOL *)&mFvDevicePath + ); + gDxeCoreLoadedImage->DeviceHandle = FvHandle; + } + } + } else if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { + // + // Found a firmware volume image. Produce a firmware volume block + // protocol for it so it gets dispatched from. This is usually a + // capsule. + // + CoreProcessFvImageFile (Fv, FvHandle, &NameGuid); + } else { + // + // Transition driver from Undiscovered to Discovered state + // + CoreAddToDriverList (Fv, FvHandle, &NameGuid); + } + } + } while (!EFI_ERROR (GetNextFileStatus)); + } + + // + // Read the array of GUIDs from the Apriori file if it is present in the firmware volume + // + AprioriFile = NULL; + Status = Fv->ReadSection ( + Fv, + &gAprioriGuid, + EFI_SECTION_RAW, + 0, + (VOID **)&AprioriFile, + &SizeOfBuffer, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + AprioriEntryCount = SizeOfBuffer / sizeof (EFI_GUID); + } else { + AprioriEntryCount = 0; + } + + // + // Put drivers on Apriori List on the Scheduled queue. The Discovered List includes + // drivers not in the current FV and these must be skipped since the a priori list + // is only valid for the FV that it resided in. + // + CoreAcquireDispatcherLock (); + + for (Index = 0; Index < AprioriEntryCount; Index++) { + for (Link = mDiscoveredList.ForwardLink; Link != &mDiscoveredList; Link = Link->ForwardLink) { + DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE); + if (CompareGuid (&DriverEntry->FileName, &AprioriFile[Index]) && + (FvHandle == DriverEntry->FvHandle)) { + DriverEntry->Dependent = FALSE; + DriverEntry->Scheduled = TRUE; + InsertTailList (&mScheduledQueue, &DriverEntry->ScheduledLink); + break; + } + } + } + + CoreReleaseDispatcherLock (); + + // + // Free data allocated by Fv->ReadSection () + // + CoreFreePool (AprioriFile); + } +} + + +VOID +CoreInitializeDispatcher ( + VOID + ) +/*++ + +Routine Description: + + Initialize the dispatcher. Initialize the notification function that runs when + a FV protocol is added to the system. + +Arguments: + + NONE + +Returns: + + NONE + +--*/ +{ + mFwVolEvent = CoreCreateProtocolNotifyEvent ( + &gEfiFirmwareVolumeProtocolGuid, + EFI_TPL_CALLBACK, + CoreFwVolEventProtocolNotify, + NULL, + &mFwVolEventRegistration, + TRUE + ); +} + +// +// Function only used in debug buils +// +VOID +CoreDisplayDiscoveredNotDispatched ( + VOID + ) +/*++ + +Routine Description: + + Traverse the discovered list for any drivers that were discovered but not loaded + because the dependency experessions evaluated to false + +Arguments: + + NONE + +Returns: + + NONE + +--*/ +{ + LIST_ENTRY *Link; + EFI_CORE_DRIVER_ENTRY *DriverEntry; + + for (Link = mDiscoveredList.ForwardLink;Link !=&mDiscoveredList; Link = Link->ForwardLink) { + DriverEntry = CR(Link, EFI_CORE_DRIVER_ENTRY, Link, EFI_CORE_DRIVER_ENTRY_SIGNATURE); + if (DriverEntry->Dependent) { + DEBUG ((EFI_D_LOAD, "Driver %g was discovered but not loaded!!\n", &DriverEntry->FileName)); + } + } +} diff --git a/EdkModulePkg/Core/Dxe/Dispatcher/dependency.c b/EdkModulePkg/Core/Dxe/Dispatcher/dependency.c new file mode 100644 index 0000000000..e6dc3282e6 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Dispatcher/dependency.c @@ -0,0 +1,450 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + dependency.c + +Abstract: + + DXE Dispatcher Dependency Evaluator + + This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine + if a driver can be scheduled for execution. The criteria for + schedulability is that the dependency expression is satisfied. + +--*/ + +#include + +// +// Global stack used to evaluate dependency expressions +// +BOOLEAN *mDepexEvaluationStack = NULL; +BOOLEAN *mDepexEvaluationStackEnd = NULL; +BOOLEAN *mDepexEvaluationStackPointer = NULL; + +// +// Worker functions +// + +STATIC +EFI_STATUS +GrowDepexStack ( + VOID + ) +/*++ + +Routine Description: + + Grow size of the Depex stack + +Arguments: + + Stack - Old stack on the way in and new stack on the way out + + StackSize - New size of the stack + +Returns: + + EFI_SUCCESS - Stack successfully growed. + + EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack. + + + +--*/ +{ + BOOLEAN *NewStack; + UINTN Size; + + Size = DEPEX_STACK_SIZE_INCREMENT; + if (mDepexEvaluationStack != NULL) { + Size = Size + (mDepexEvaluationStackEnd - mDepexEvaluationStack); + } + + NewStack = CoreAllocateBootServicesPool (Size * sizeof (BOOLEAN)); + if (NewStack == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (mDepexEvaluationStack != NULL) { + // + // Copy to Old Stack to the New Stack + // + CopyMem ( + NewStack, + mDepexEvaluationStack, + (mDepexEvaluationStackEnd - mDepexEvaluationStack) * sizeof (BOOLEAN) + ); + + // + // Free The Old Stack + // + CoreFreePool (mDepexEvaluationStack); + } + + // + // Make the Stack pointer point to the old data in the new stack + // + mDepexEvaluationStackPointer = NewStack + (mDepexEvaluationStackPointer - mDepexEvaluationStack); + mDepexEvaluationStack = NewStack; + mDepexEvaluationStackEnd = NewStack + Size; + + return EFI_SUCCESS; +} + + +STATIC +EFI_STATUS +PushBool ( + IN BOOLEAN Value + ) +/*++ + +Routine Description: + + Push an element onto the Boolean Stack + +Arguments: + + Value - BOOLEAN to push. + +Returns: + + EFI_SUCCESS - The value was pushed onto the stack. + + EFI_OUT_OF_RESOURCES - There is not enough system memory to grow the stack. + +--*/ +{ + EFI_STATUS Status; + + // + // Check for a stack overflow condition + // + if (mDepexEvaluationStackPointer == mDepexEvaluationStackEnd) { + // + // Grow the stack + // + Status = GrowDepexStack (); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // Push the item onto the stack + // + *mDepexEvaluationStackPointer = Value; + mDepexEvaluationStackPointer++; + + return EFI_SUCCESS; +} + + +STATIC +EFI_STATUS +PopBool ( + OUT BOOLEAN *Value + ) +/*++ + +Routine Description: + + Pop an element from the Boolean stack. + +Arguments: + + Value - BOOLEAN to pop. + +Returns: + + EFI_SUCCESS - The value was popped onto the stack. + + EFI_ACCESS_DENIED - The pop operation underflowed the stack + +--*/ +{ + // + // Check for a stack underflow condition + // + if (mDepexEvaluationStackPointer == mDepexEvaluationStack) { + return EFI_ACCESS_DENIED; + } + + // + // Pop the item off the stack + // + mDepexEvaluationStackPointer--; + *Value = *mDepexEvaluationStackPointer; + return EFI_SUCCESS; +} + + +EFI_STATUS +CorePreProcessDepex ( + IN EFI_CORE_DRIVER_ENTRY *DriverEntry + ) +/*++ + +Routine Description: + + Preprocess dependency expression and update DriverEntry to reflect the + state of Before, After, and SOR dependencies. If DriverEntry->Before + or DriverEntry->After is set it will never be cleared. If SOR is set + it will be cleared by CoreSchedule(), and then the driver can be + dispatched. + +Arguments: + + DriverEntry - DriverEntry element to update + +Returns: + + EFI_SUCCESS - It always works. + +--*/ +{ + UINT8 *Iterator; + + Iterator = DriverEntry->Depex; + if (*Iterator == EFI_DEP_SOR) { + DriverEntry->Unrequested = TRUE; + } else { + DriverEntry->Dependent = TRUE; + } + + if (*Iterator == EFI_DEP_BEFORE) { + DriverEntry->Before = TRUE; + } else if (*Iterator == EFI_DEP_AFTER) { + DriverEntry->After = TRUE; + } + + if (DriverEntry->Before || DriverEntry->After) { + CopyMem (&DriverEntry->BeforeAfterGuid, Iterator + 1, sizeof (EFI_GUID)); + } + + return EFI_SUCCESS; +} + + +BOOLEAN +CoreIsSchedulable ( + IN EFI_CORE_DRIVER_ENTRY *DriverEntry + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. This code does + not need to handle Before or After, as it is not valid to call this + routine in this case. The SOR is just ignored and is a nop in the grammer. + + POSTFIX means all the math is done on top of the stack. + +Arguments: + + DriverEntry - DriverEntry element to update + +Returns: + + TRUE - If driver is ready to run. + + FALSE - If driver is not ready to run or some fatal error was found. + +--*/ +{ + EFI_STATUS Status; + UINT8 *Iterator; + BOOLEAN Operator; + BOOLEAN Operator2; + EFI_GUID DriverGuid; + VOID *Interface; + + if (DriverEntry->After || DriverEntry->Before) { + // + // If Before or After Depex skip as CoreInsertOnScheduledQueueWhileProcessingBeforeAndAfter () + // processes them. + // + return FALSE; + } + + if (DriverEntry->Depex == NULL) { + // + // A NULL Depex means treat the driver like an EFI 1.0 thing. + // + Status = CoreAllEfiServicesAvailable (); + if (EFI_ERROR (Status)) { + return FALSE; + } + return TRUE; + } + + // + // Clean out memory leaks in Depex Boolean stack. Leaks are only caused by + // incorrectly formed DEPEX expressions + // + mDepexEvaluationStackPointer = mDepexEvaluationStack; + + + Iterator = DriverEntry->Depex; + + while (TRUE) { + // + // Check to see if we are attempting to fetch dependency expression instructions + // past the end of the dependency expression. + // + if (((UINTN)Iterator - (UINTN)DriverEntry->Depex) > DriverEntry->DepexSize) { + return FALSE; + } + + // + // Look at the opcode of the dependency expression instruction. + // + switch (*Iterator) { + case EFI_DEP_BEFORE: + case EFI_DEP_AFTER: + // + // For a well-formed Dependency Expression, the code should never get here. + // The BEFORE and AFTER are processed prior to this routine's invocation. + // If the code flow arrives at this point, there was a BEFORE or AFTER + // that were not the first opcodes. + // + ASSERT (FALSE); + case EFI_DEP_SOR: + // + // These opcodes can only appear once as the first opcode. If it is found + // at any other location, then the dependency expression evaluates to FALSE + // + if (Iterator != DriverEntry->Depex) { + return FALSE; + } + // + // Otherwise, it is the first opcode and should be treated as a NOP. + // + break; + + case EFI_DEP_PUSH: + // + // Push operator is followed by a GUID. Test to see if the GUID protocol + // is installed and push the boolean result on the stack. + // + CopyMem (&DriverGuid, Iterator + 1, sizeof (EFI_GUID)); + + Status = CoreLocateProtocol (&DriverGuid, NULL, &Interface); + + if (EFI_ERROR (Status)) { + Status = PushBool (FALSE); + } else { + *Iterator = EFI_DEP_REPLACE_TRUE; + Status = PushBool (TRUE); + } + if (EFI_ERROR (Status)) { + return FALSE; + } + + Iterator += sizeof (EFI_GUID); + break; + + case EFI_DEP_AND: + Status = PopBool (&Operator); + if (EFI_ERROR (Status)) { + return FALSE; + } + + Status = PopBool (&Operator2); + if (EFI_ERROR (Status)) { + return FALSE; + } + + Status = PushBool ((BOOLEAN)(Operator && Operator2)); + if (EFI_ERROR (Status)) { + return FALSE; + } + break; + + case EFI_DEP_OR: + Status = PopBool (&Operator); + if (EFI_ERROR (Status)) { + return FALSE; + } + + Status = PopBool (&Operator2); + if (EFI_ERROR (Status)) { + return FALSE; + } + + Status = PushBool ((BOOLEAN)(Operator || Operator2)); + if (EFI_ERROR (Status)) { + return FALSE; + } + break; + + case EFI_DEP_NOT: + Status = PopBool (&Operator); + if (EFI_ERROR (Status)) { + return FALSE; + } + + Status = PushBool ((BOOLEAN)(!Operator)); + if (EFI_ERROR (Status)) { + return FALSE; + } + break; + + case EFI_DEP_TRUE: + Status = PushBool (TRUE); + if (EFI_ERROR (Status)) { + return FALSE; + } + break; + + case EFI_DEP_FALSE: + Status = PushBool (FALSE); + if (EFI_ERROR (Status)) { + return FALSE; + } + break; + + case EFI_DEP_END: + Status = PopBool (&Operator); + if (EFI_ERROR (Status)) { + return FALSE; + } + return Operator; + + case EFI_DEP_REPLACE_TRUE: + Status = PushBool (TRUE); + if (EFI_ERROR (Status)) { + return FALSE; + } + + Iterator += sizeof (EFI_GUID); + break; + + default: + return FALSE; + } + + // + // Skip over the Dependency Op Code we just processed in the switch. + // The math is done out of order, but it should not matter. That is + // we may add in the sizeof (EFI_GUID) before we account for the OP Code. + // This is not an issue, since we just need the correct end result. You + // need to be careful using Iterator in the loop as it's intermediate value + // may be strange. + // + Iterator++; + } + return FALSE; +} + diff --git a/EdkModulePkg/Core/Dxe/DxeMain.h b/EdkModulePkg/Core/Dxe/DxeMain.h new file mode 100644 index 0000000000..9a9ba683e7 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/DxeMain.h @@ -0,0 +1,2539 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeMain.h + +Abstract: + +Revision History + +--*/ + +#ifndef _DXE_MAIN_H_ +#define _DXE_MAIN_H_ + + +#include "DebugImageInfo.h" +#include "Library.h" +#include "FwVolBlock.h" +#include "FwVolDriver.h" +#include "gcd.h" +#include "imem.h" +#include "Image.h" +#include "Exec.h" +#include "hand.h" + +typedef struct { + EFI_GUID *ProtocolGuid; + VOID **Protocol; + EFI_EVENT Event; + VOID *Registration; + BOOLEAN Present; +} ARCHITECTURAL_PROTOCOL_ENTRY; + + +// +// DXE Dispatcher Data structures +// + +#define KNOWN_HANDLE_SIGNATURE EFI_SIGNATURE_32('k','n','o','w') +typedef struct { + UINTN Signature; + LIST_ENTRY Link; // mFvHandleList + EFI_HANDLE Handle; +} KNOWN_HANDLE; + + +#define EFI_CORE_DRIVER_ENTRY_SIGNATURE EFI_SIGNATURE_32('d','r','v','r') +typedef struct { + UINTN Signature; + LIST_ENTRY Link; // mDriverList + + LIST_ENTRY ScheduledLink; // mScheduledQueue + + EFI_HANDLE FvHandle; + EFI_GUID FileName; + EFI_DEVICE_PATH_PROTOCOL *FvFileDevicePath; + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + + VOID *Depex; + UINTN DepexSize; + + BOOLEAN Before; + BOOLEAN After; + EFI_GUID BeforeAfterGuid; + + BOOLEAN Dependent; + BOOLEAN Unrequested; + BOOLEAN Scheduled; + BOOLEAN Untrusted; + BOOLEAN Initialized; + BOOLEAN DepexProtocolError; + + EFI_HANDLE ImageHandle; + +} EFI_CORE_DRIVER_ENTRY; + +// +//The data structure of GCD memory map entry +// +#define EFI_GCD_MAP_SIGNATURE EFI_SIGNATURE_32('g','c','d','m') +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 EndAddress; + UINT64 Capabilities; + UINT64 Attributes; + EFI_GCD_MEMORY_TYPE GcdMemoryType; + EFI_GCD_IO_TYPE GcdIoType; + EFI_HANDLE ImageHandle; + EFI_HANDLE DeviceHandle; +} EFI_GCD_MAP_ENTRY; + +// +// DXE Core Global Variables +// +extern EFI_SYSTEM_TABLE *gST; +extern EFI_BOOT_SERVICES *gBS; +extern EFI_RUNTIME_SERVICES *gRT; +extern EFI_DXE_SERVICES *gDS; +extern EFI_HANDLE gDxeCoreImageHandle; + +extern EFI_DECOMPRESS_PROTOCOL gEfiDecompress; +extern EFI_PEI_PE_COFF_LOADER_PROTOCOL *gEfiPeiPeCoffLoader; + +extern EFI_RUNTIME_ARCH_PROTOCOL *gRuntime; +extern EFI_CPU_ARCH_PROTOCOL *gCpu; +extern EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *gWatchdogTimer; +extern EFI_METRONOME_ARCH_PROTOCOL *gMetronome; +extern EFI_TIMER_ARCH_PROTOCOL *gTimer; +extern EFI_SECURITY_ARCH_PROTOCOL *gSecurity; +extern EFI_BDS_ARCH_PROTOCOL *gBds; +extern EFI_STATUS_CODE_PROTOCOL *gStatusCode; + +extern EFI_TPL gEfiCurrentTpl; + +extern EFI_GUID *gDxeCoreFileName; +extern EFI_LOADED_IMAGE_PROTOCOL *gDxeCoreLoadedImage; + +extern EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1]; + +extern BOOLEAN gDispatcherRunning; + +// +// Service Initialization Functions +// + + +VOID +CoreInitializePool ( + VOID + ) +/*++ + +Routine Description: + + Called to initialize the pool. + +Arguments: + + None + +Returns: + + None + +--*/ +; + +VOID +CoreAddMemoryDescriptor ( + IN EFI_MEMORY_TYPE Type, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 NumberOfPages, + IN UINT64 Attribute + ) +/*++ + +Routine Description: + + Called to initialize the memory map and add descriptors to + the current descriptor list. + + The first descriptor that is added must be general usable + memory as the addition allocates heap. + +Arguments: + + Type - The type of memory to add + + Start - The starting address in the memory range + Must be page aligned + + NumberOfPages - The number of pages in the range + + Attribute - Attributes of the memory to add + +Returns: + + None. The range is added to the memory map + +--*/ +; + +VOID +CoreReleaseGcdMemoryLock ( + VOID + ) +/*++ + +Routine Description: + Release memory lock on mGcdMemorySpaceLock + +Arguments: + None + +Returns: + None + +--*/ +; + +VOID +CoreAcquireGcdMemoryLock ( + VOID + ) +/*++ + +Routine Description: + Acquire memory lock on mGcdMemorySpaceLock + +Arguments: + None + +Returns: + None + +--*/ +; + +EFI_STATUS +CoreInitializeMemoryServices ( + IN VOID **HobStart, + IN EFI_PHYSICAL_ADDRESS *MemoryBaseAddress, + IN UINT64 *MemoryLength + ) +/*++ + +Routine Description: + + External function. Initializes the GCD and memory services based on the memory + descriptor HOBs. This function is responsible for priming the GCD map and the + memory map, so memory allocations and resource allocations can be made. The first + part of this function can not depend on any memory services until at least one + memory descriptor is provided to the memory services. Then the memory services + can be used to intialize the GCD map. + +Arguments: + + HobStart - The start address of the HOB. + + MemoryBaseAddress - Start address of memory region found to init DXE core. + + MemoryLength - Length of memory region found to init DXE core. + +Returns: + + EFI_SUCCESS - Memory services successfully initialized. + +--*/ +; + + +EFI_STATUS +CoreInitializeGcdServices ( + IN VOID **HobStart, + IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + External function. Initializes the GCD and memory services based on the memory + descriptor HOBs. This function is responsible for priming the GCD map and the + memory map, so memory allocations and resource allocations can be made. The first + part of this function can not depend on any memory services until at least one + memory descriptor is provided to the memory services. Then the memory services + can be used to intialize the GCD map. + +Arguments: + + HobStart - The start address of the HOB + + MemoryBaseAddress - Start address of memory region found to init DXE core. + + MemoryLength - Length of memory region found to init DXE core. + + +Returns: + + EFI_SUCCESS - GCD services successfully initialized. + +--*/ +; + +EFI_STATUS +CoreInitializeEventServices ( + VOID + ) +/*++ + +Routine Description: + + Initializes "event" support and populates parts of the System and Runtime Table. + +Arguments: + + None + +Returns: + + EFI_SUCCESS - Always return success + +--*/ +; + +EFI_STATUS +CoreShutdownEventServices ( + VOID + ) +/*++ + +Routine Description: + + Register all runtime events to make sure they are still available after ExitBootService. + +Arguments: + + None + +Returns: + + EFI_SUCCESS - Always return success + +--*/ +; + +EFI_STATUS +CoreInitializeImageServices ( + IN VOID *HobStart + ) +/*++ + +Routine Description: + + Add the Image Services to EFI Boot Services Table and install the protocol + interfaces for this image. + +Arguments: + + HobStart - The HOB to initialize + +Returns: + + Status code. + +--*/ +; + +EFI_STATUS +CoreShutdownImageServices ( + VOID + ) +/*++ + +Routine Description: + + Transfer control of runtime images to runtime service + +Arguments: + + None + +Returns: + + EFI_SUCCESS - Function successfully returned + +--*/ +; + +VOID +CoreNotifyOnArchProtocolInstallation ( + VOID + ) +/*++ + +Routine Description: + Creates an event that is fired everytime a Protocol of a specific type is installed + +Arguments: + NONE + +Returns: + NONE + +--*/ +; + +EFI_STATUS +CoreAllEfiServicesAvailable ( + VOID + ) +/*++ + +Routine Description: + Return TRUE if all AP services are availible. + +Arguments: + NONE + +Returns: + EFI_SUCCESS - All AP services are available + EFI_NOT_FOUND - At least one AP service is not available + +--*/ +; + +VOID +CalculateEfiHdrCrc ( + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Calcualte the 32-bit CRC in a EFI table using the service provided by the + gRuntime service. + +Arguments: + + Hdr - Pointer to an EFI standard header + +Returns: + + None + +--*/ +; + +VOID +EFIAPI +CoreTimerTick ( + IN UINT64 Duration + ) +/*++ + +Routine Description: + + Called by the platform code to process a tick. + +Arguments: + + Duration - The number of 100ns elasped since the last call to TimerTick + +Returns: + + None + +--*/ +; + +VOID +CoreInitializeDispatcher ( + VOID + ) +/*++ + +Routine Description: + + Initialize the dispatcher. Initialize the notification function that runs when + a FV protocol is added to the system. + +Arguments: + + NONE + +Returns: + + NONE + +--*/ +; + +BOOLEAN +CoreIsSchedulable ( + IN EFI_CORE_DRIVER_ENTRY *DriverEntry + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. This code does + not need to handle Before or After, as it is not valid to call this + routine in this case. The SOR is just ignored and is a nop in the grammer. + + POSTFIX means all the math is done on top of the stack. + +Arguments: + + DriverEntry - DriverEntry element to update + +Returns: + + TRUE - If driver is ready to run. + + FALSE - If driver is not ready to run or some fatal error was found. + +--*/ +; + +EFI_STATUS +CorePreProcessDepex ( + IN EFI_CORE_DRIVER_ENTRY *DriverEntry + ) +/*++ + +Routine Description: + + Preprocess dependency expression and update DriverEntry to reflect the + state of Before, After, and SOR dependencies. If DriverEntry->Before + or DriverEntry->After is set it will never be cleared. If SOR is set + it will be cleared by CoreSchedule(), and then the driver can be + dispatched. + +Arguments: + + DriverEntry - DriverEntry element to update + +Returns: + + EFI_SUCCESS - It always works. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreExitBootServices ( + IN EFI_HANDLE ImageHandle, + IN UINTN MapKey + ) +/*++ + +Routine Description: + + EFI 1.0 API to terminate Boot Services + +Arguments: + + ImageHandle - Handle that represents the identity of the calling image + + MapKey -Key to the latest memory map. + +Returns: + + EFI_SUCCESS - Boot Services terminated + EFI_INVALID_PARAMETER - MapKey is incorrect. + +--*/ +; + +EFI_STATUS +CoreTerminateMemoryMap ( + IN UINTN MapKey + ) +/*++ + +Routine Description: + + Make sure the memory map is following all the construction rules, + it is the last time to check memory map error before exit boot services. + +Arguments: + + MapKey - Memory map key + +Returns: + + EFI_INVALID_PARAMETER - Memory map not consistent with construction rules. + + EFI_SUCCESS - Valid memory map. + +--*/ +; + +VOID +CoreNotifySignalList ( + IN EFI_GUID *EventGroup + ) +/*++ + +Routine Description: + + Signals all events on the requested list + +Arguments: + + SignalType - The list to signal + +Returns: + + None + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreInstallConfigurationTable ( + IN EFI_GUID *Guid, + IN VOID *Table + ) +/*++ + +Routine Description: + + Boot Service called to add, modify, or remove a system configuration table from + the EFI System Table. + +Arguments: + + Guid: Pointer to the GUID for the entry to add, update, or remove + Table: Pointer to the configuration table for the entry to add, update, or + remove, may be NULL. + +Returns: + + EFI_SUCCESS Guid, Table pair added, updated, or removed. + EFI_INVALID_PARAMETER Input GUID not valid. + EFI_NOT_FOUND Attempted to delete non-existant entry + EFI_OUT_OF_RESOURCES Not enough memory available + +--*/ +; + + +EFI_TPL +EFIAPI +CoreRaiseTpl ( + IN EFI_TPL NewTpl + ) +/*++ + +Routine Description: + + Raise the task priority level to the new level. + High level is implemented by disabling processor interrupts. + +Arguments: + + NewTpl - New task priority level + +Returns: + + The previous task priority level + +--*/ +; + + +VOID +EFIAPI +CoreRestoreTpl ( + IN EFI_TPL NewTpl + ) +/*++ + +Routine Description: + + Lowers the task priority to the previous value. If the new + priority unmasks events at a higher priority, they are dispatched. + +Arguments: + + NewTpl - New, lower, task priority + +Returns: + + None + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreStall ( + IN UINTN Microseconds + ) +/*++ + +Routine Description: + + Introduces a fine-grained stall. + +Arguments: + + Microseconds The number of microseconds to stall execution + +Returns: + + EFI_SUCCESS - Execution was stalled for at least the requested amount + of microseconds. + + EFI_NOT_AVAILABLE_YET - gMetronome is not available yet + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreSetWatchdogTimer ( + IN UINTN Timeout, + IN UINT64 WatchdogCode, + IN UINTN DataSize, + IN CHAR16 *WatchdogData OPTIONAL + ) +/*++ + +Routine Description: + + Sets the system's watchdog timer. + +Arguments: + + Timeout The number of seconds. Zero disables the timer. + + ///////following three parameters are left for platform specific using + + WatchdogCode The numberic code to log. 0x0 to 0xffff are firmware + DataSize Size of the optional data + WatchdogData Optional Null terminated unicode string followed by binary + data. + +Returns: + + EFI_SUCCESS Timeout has been set + EFI_NOT_AVAILABLE_YET WatchdogTimer is not available yet + EFI_UNSUPPORTED System does not have a timer (currently not used) + EFI_DEVICE_ERROR Could not complete due to hardware error + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreInstallProtocolInterface ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface + ) +/*++ + +Routine Description: + + Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which + Calls the private one which contains a BOOLEAN parameter for notifications + +Arguments: + + UserHandle - The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + + Protocol - The protocol to add to the handle + + InterfaceType - Indicates whether Interface is supplied in native form. + + Interface - The interface for the protocol being added + +Returns: + + Status code + +--*/ +; + +EFI_STATUS +CoreInstallProtocolInterfaceNotify ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface, + IN BOOLEAN Notify + ) +/*++ + +Routine Description: + + Installs a protocol interface into the boot services environment. + +Arguments: + + UserHandle - The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + + Protocol - The protocol to add to the handle + + InterfaceType - Indicates whether Interface is supplied in native form. + + Interface - The interface for the protocol being added + + Notify - Whether to notify the notification list for this protocol + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Protocol interface successfully installed + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreInstallMultipleProtocolInterfaces ( + IN OUT EFI_HANDLE *Handle, + ... + ) +/*++ + +Routine Description: + + Installs a list of protocol interface into the boot services environment. + This function calls InstallProtocolInterface() in a loop. If any error + occures all the protocols added by this function are removed. This is + basically a lib function to save space. + +Arguments: + + Handle - The handle to install the protocol handlers on, + or NULL if a new handle is to be allocated + ... - EFI_GUID followed by protocol instance. A NULL terminates the + list. The pairs are the arguments to InstallProtocolInterface(). + All the protocols are added to Handle. + +Returns: + + EFI_INVALID_PARAMETER - Handle is NULL. + + EFI_SUCCESS - Protocol interfaces successfully installed. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreUninstallMultipleProtocolInterfaces ( + IN EFI_HANDLE Handle, + ... + ) +/*++ + +Routine Description: + + Uninstalls a list of protocol interface in the boot services environment. + This function calls UnisatllProtocolInterface() in a loop. This is + basically a lib function to save space. + +Arguments: + + Handle - The handle to uninstall the protocol + + ... - EFI_GUID followed by protocol instance. A NULL terminates the + list. The pairs are the arguments to UninstallProtocolInterface(). + All the protocols are added to Handle. + +Returns: + + Status code + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreReinstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *OldInterface, + IN VOID *NewInterface + ) +/*++ + +Routine Description: + + Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface. + +Arguments: + + UserHandle - Handle on which the interface is to be reinstalled + Protocol - The numeric ID of the interface + OldInterface - A pointer to the old interface + NewInterface - A pointer to the new interface + + +Returns: + + Status code. + + On EFI_SUCCESS The protocol interface was installed + On EFI_NOT_FOUND The OldInterface on the handle was not found + On EFI_INVALID_PARAMETER One of the parameters has an invalid value + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreUninstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +/*++ + +Routine Description: + + Uninstalls all instances of a protocol:interfacer from a handle. + If the last protocol interface is remove from the handle, the + handle is freed. + +Arguments: + + UserHandle - The handle to remove the protocol handler from + + Protocol - The protocol, of protocol:interface, to remove + + Interface - The interface, of protocol:interface, to remove + +Returns: + + EFI_INVALID_PARAMETER - Protocol is NULL. + + EFI_SUCCESS - Protocol interface successfully uninstalled. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreHandleProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface + ) +/*++ + +Routine Description: + + Queries a handle to determine if it supports a specified protocol. + +Arguments: + + UserHandle - The handle being queried. + + Protocol - The published unique identifier of the protocol. + + Interface - Supplies the address where a pointer to the corresponding Protocol + Interface is returned. + +Returns: + + The requested protocol interface for the handle + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreOpenProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface OPTIONAL, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE ControllerHandle, + IN UINT32 Attributes + ) +/*++ + +Routine Description: + + Locates the installed protocol handler for the handle, and + invokes it to obtain the protocol interface. Usage information + is registered in the protocol data base. + +Arguments: + + UserHandle - The handle to obtain the protocol interface on + + Protocol - The ID of the protocol + + Interface - The location to return the protocol interface + + ImageHandle - The handle of the Image that is opening the protocol interface + specified by Protocol and Interface. + + ControllerHandle - The controller handle that is requiring this interface. + + Attributes - The open mode of the protocol interface specified by Handle + and Protocol. + +Returns: + + EFI_INVALID_PARAMETER - Protocol is NULL. + + EFI_SUCCESS - Get the protocol interface. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreOpenProtocolInformation ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + OUT UINTN *EntryCount + ) +/*++ + +Routine Description: + + Return information about Opened protocols in the system + +Arguments: + + UserHandle - The handle to close the protocol interface on + + Protocol - The ID of the protocol + + EntryBuffer - A pointer to a buffer of open protocol information in the form of + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures. + + EntryCount - Number of EntryBuffer entries + +Returns: + + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreCloseProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE ControllerHandle + ) +/*++ + +Routine Description: + + Close Protocol + +Arguments: + + UserHandle - The handle to close the protocol interface on + + Protocol - The ID of the protocol + + ImageHandle - The user of the protocol to close + + ControllerHandle - The user of the protocol to close + +Returns: + + EFI_INVALID_PARAMETER - Protocol is NULL. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreProtocolsPerHandle ( + IN EFI_HANDLE UserHandle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount + ) +/*++ + +Routine Description: + + Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated + from pool. + +Arguments: + + UserHandle - The handle from which to retrieve the list of protocol interface + GUIDs. + + ProtocolBuffer - A pointer to the list of protocol interface GUID pointers that are + installed on Handle. + + ProtocolBufferCount - A pointer to the number of GUID pointers present in + ProtocolBuffer. + +Returns: + EFI_SUCCESS - The list of protocol interface GUIDs installed on Handle was returned in + ProtocolBuffer. The number of protocol interface GUIDs was + returned in ProtocolBufferCount. + EFI_INVALID_PARAMETER - Handle is NULL. + EFI_INVALID_PARAMETER - Handle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ProtocolBuffer is NULL. + EFI_INVALID_PARAMETER - ProtocolBufferCount is NULL. + EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the results. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreRegisterProtocolNotify ( + IN EFI_GUID *Protocol, + IN EFI_EVENT Event, + OUT VOID **Registration + ) +/*++ + +Routine Description: + + Add a new protocol notification record for the request protocol. + +Arguments: + + Protocol - The requested protocol to add the notify registration + + Event - The event to signal + + Registration - Returns the registration record + + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_SUCCESS - Successfully returned the registration record that has been added + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer + ) +/*++ + +Routine Description: + + Locates the requested handle(s) and returns them in Buffer. + +Arguments: + + SearchType - The type of search to perform to locate the handles + + Protocol - The protocol to search for + + SearchKey - Dependant on SearchType + + BufferSize - On input the size of Buffer. On output the + size of data returned. + + Buffer - The buffer to return the results in + + +Returns: + + EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize. + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreLocateDevicePath ( + IN EFI_GUID *Protocol, + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, + OUT EFI_HANDLE *Device + ) +/*++ + +Routine Description: + + Locates the handle to a device on the device path that supports the specified protocol. + +Arguments: + + Protocol - The protocol to search for. + FilePath - On input, a pointer to a pointer to the device path. On output, the device + path pointer is modified to point to the remaining part of the devicepath. + Device - A pointer to the returned device handle. + +Returns: + + EFI_SUCCESS - The resulting handle was returned. + EFI_NOT_FOUND - No handles matched the search. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreLocateHandleBuffer ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NumberHandles, + OUT EFI_HANDLE **Buffer + ) +/*++ + +Routine Description: + + Function returns an array of handles that support the requested protocol + in a buffer allocated from pool. This is a version of CoreLocateHandle() + that allocates a buffer for the caller. + +Arguments: + + SearchType - Specifies which handle(s) are to be returned. + Protocol - Provides the protocol to search by. + This parameter is only valid for SearchType ByProtocol. + SearchKey - Supplies the search key depending on the SearchType. + NumberHandles - The number of handles returned in Buffer. + Buffer - A pointer to the buffer to return the requested array of + handles that support Protocol. + +Returns: + + EFI_SUCCESS - The result array of handles was returned. + EFI_NOT_FOUND - No handles match the search. + EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results. + EFI_INVALID_PARAMETER - Invalid parameter + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreLocateProtocol ( + IN EFI_GUID *Protocol, + IN VOID *Registration OPTIONAL, + OUT VOID **Interface + ) +/*++ + +Routine Description: + + Return the first Protocol Interface that matches the Protocol GUID. If + Registration is pasased in return a Protocol Instance that was just add + to the system. If Retistration is NULL return the first Protocol Interface + you find. + +Arguments: + + Protocol - The protocol to search for + + Registration - Optional Registration Key returned from RegisterProtocolNotify() + + Interface - Return the Protocol interface (instance). + +Returns: + + EFI_SUCCESS - If a valid Interface is returned + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_NOT_FOUND - Protocol interface not found + +--*/ +; + +UINT64 +CoreGetHandleDatabaseKey ( + VOID + ) +/*++ + +Routine Description: + + return handle database key. + +Arguments: + + None + +Returns: + + Handle database key. + +--*/ +; + +VOID +CoreConnectHandlesByKey ( + UINT64 Key + ) +/*++ + +Routine Description: + + Go connect any handles that were created or modified while a image executed. + +Arguments: + + Key - The Key to show that the handle has been created/modified + +Returns: + + None +--*/ +; + + +EFI_STATUS +EFIAPI +CoreConnectController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *DriverImageHandle OPTIONAL, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, + IN BOOLEAN Recursive + ) +/*++ + +Routine Description: + + Connects one or more drivers to a controller. + +Arguments: + + ControllerHandle - Handle of the controller to be connected. + + DriverImageHandle - DriverImageHandle A pointer to an ordered list of driver image handles. + + RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child of the + controller specified by ControllerHandle. + + Recursive - - Whether the function would be called recursively or not. + +Returns: + + Status code. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreDisconnectController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverImageHandle OPTIONAL, + IN EFI_HANDLE ChildHandle OPTIONAL + ) +/*++ + +Routine Description: + + Disonnects a controller from a driver + +Arguments: + + ControllerHandle - ControllerHandle The handle of the controller from which driver(s) + are to be disconnected. + DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle. + ChildHandle - ChildHandle The handle of the child to destroy. + +Returns: + + EFI_SUCCESS - One or more drivers were disconnected from the controller. + EFI_SUCCESS - On entry, no drivers are managing ControllerHandle. + EFI_SUCCESS - DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL, and it is not a valid EFI_HANDLE. + EFI_OUT_OF_RESOURCES - There are not enough resources available to disconnect any drivers from ControllerHandle. + EFI_DEVICE_ERROR - The controller could not be disconnected because of a device error. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreAllocatePages ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ) +/*++ + +Routine Description: + + Allocates pages from the memory map. + +Arguments: + + Type - The type of allocation to perform + + MemoryType - The type of memory to turn the allocated pages into + + NumberOfPages - The number of pages to allocate + + Memory - A pointer to receive the base allocated memory address + +Returns: + + Status. On success, Memory is filled in with the base address allocated + + EFI_INVALID_PARAMETER - Parameters violate checking rules defined in spec. + + EFI_NOT_FOUND - Could not allocate pages match the requirement. + + EFI_OUT_OF_RESOURCES - No enough pages to allocate. + + EFI_SUCCESS - Pages successfully allocated. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreFreePages ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages + ) +/*++ + +Routine Description: + + Frees previous allocated pages. + +Arguments: + + Memory - Base address of memory being freed + + NumberOfPages - The number of pages to free + +Returns: + + EFI_NOT_FOUND - Could not find the entry that covers the range + + EFI_INVALID_PARAMETER - Address not aligned + + EFI_SUCCESS -Pages successfully freed. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreGetMemoryMap ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *Desc, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ) +/*++ + +Routine Description: + + Returns the current memory map. + +Arguments: + + MemoryMapSize - On input the buffer size of MemoryMap allocated by caller + On output the required buffer size to contain the memory map + + Desc - The buffer to return the current memory map + + MapKey - The address to return the current map key + + DescriptorSize - The size in bytes for an individual EFI_MEMORY_DESCRIPTOR + + DescriptorVersion - The version number associated with the EFI_MEMORY_DESCRIPTOR + +Returns: + + EFI_SUCCESS The current memory map was returned successfully + + EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small + + EFI_INVALID_PARAMETER One of the parameters has an invalid value + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreAllocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Allocate pool of a particular type. + +Arguments: + + PoolType - Type of pool to allocate + + Size - The amount of pool to allocate + + Buffer - The address to return a pointer to the allocated pool + +Returns: + + EFI_INVALID_PARAMETER - PoolType not valid + + EFI_OUT_OF_RESOURCES - Size exceeds max pool size or allocation failed. + + EFI_SUCCESS - Pool successfully allocated. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreFreePool ( + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Frees pool. + +Arguments: + + Buffer - The allocated pool entry to free + +Returns: + + EFI_INVALID_PARAMETER - Buffer is not a valid value. + + EFI_SUCCESS - Pool successfully freed. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreLoadImage ( + IN BOOLEAN BootPolicy, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + OUT EFI_HANDLE *ImageHandle + ) +/*++ + +Routine Description: + + Loads an EFI image into memory and returns a handle to the image. + +Arguments: + + BootPolicy - If TRUE, indicates that the request originates from the boot manager, + and that the boot manager is attempting to load FilePath as a boot selection. + ParentImageHandle - The caller's image handle. + FilePath - The specific file path from which the image is loaded. + SourceBuffer - If not NULL, a pointer to the memory location containing a copy of + the image to be loaded. + SourceSize - The size in bytes of SourceBuffer. + ImageHandle - Pointer to the returned image handle that is created when the image + is successfully loaded. + +Returns: + + EFI_SUCCESS - The image was loaded into memory. + EFI_NOT_FOUND - The FilePath was not found. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be + parsed to locate the proper protocol for loading the file. + EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources. +--*/ +; + + +EFI_STATUS +EFIAPI +CoreUnloadImage ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Unload the specified image. + +Arguments: + + ImageHandle - The specified image handle. + +Returns: + + EFI_INVALID_PARAMETER - Image handle is NULL. + + EFI_UNSUPPORTED - Attempt to unload an unsupported image. + + EFI_SUCCESS - Image successfully unloaded. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreStartImage ( + IN EFI_HANDLE ImageHandle, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ) +/*++ + +Routine Description: + + Transfer control to a loaded image's entry point. + +Arguments: + + ImageHandle - Handle of image to be started. + + ExitDataSize - Pointer of the size to ExitData + + ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated + Unicode string, optionally followed by additional binary data. The string + is a description that the caller may use to further indicate the reason for + the image¡¯s exit. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Successfully transfer control to the image's entry point. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreExit ( + IN EFI_HANDLE ImageHandle, + IN EFI_STATUS Status, + IN UINTN ExitDataSize, + IN CHAR16 *ExitData OPTIONAL + ) +/*++ + +Routine Description: + + Terminates the currently loaded EFI image and returns control to boot services. + +Arguments: + + ImageHandle - Handle that identifies the image. This parameter is passed to the image + on entry. + Status - The image¡¯s exit code. + ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is + EFI_SUCCESS. + ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string, + optionally followed by additional binary data. The string is a + description that the caller may use to further indicate the reason for + the image¡¯s exit. + +Returns: + + EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image. + + EFI_SUCCESS - Successfully terminates the currently loaded EFI image. + + EFI_ACCESS_DENIED - Should never reach there. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreCreateEvent ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + OUT EFI_EVENT *pEvent + ) +/*++ + +Routine Description: + + Creates a general-purpose event structure + +Arguments: + + Type - The type of event to create and its mode and attributes + NotifyTpl - The task priority level of event notifications + NotifyFunction - Pointer to the event’s notification function + NotifyContext - Pointer to the notification function’s context; corresponds to + parameter "Context" in the notification function + pEvent - Pointer to the newly created event if the call succeeds; undefined otherwise + +Returns: + + EFI_SUCCESS - The event structure was created + EFI_INVALID_PARAMETER - One of the parameters has an invalid value + EFI_OUT_OF_RESOURCES - The event could not be allocated + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreCreateEventEx ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL + IN CONST VOID *NotifyContext, OPTIONAL + IN CONST EFI_GUID *EventGroup, OPTIONAL + OUT EFI_EVENT *Event + ) +/*++ + +Routine Description: + Creates a general-purpose event structure + +Arguments: + Type - The type of event to create and its mode and attributes + NotifyTpl - The task priority level of event notifications + NotifyFunction - Pointer to the events notification function + NotifyContext - Pointer to the notification functions context; corresponds to + parameter "Context" in the notification function + EventGrout - GUID for EventGroup if NULL act the same as gBS->CreateEvent(). + Event - Pointer to the newly created event if the call succeeds; undefined otherwise + +Returns: + EFI_SUCCESS - The event structure was created + EFI_INVALID_PARAMETER - One of the parameters has an invalid value + EFI_OUT_OF_RESOURCES - The event could not be allocated + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreSetTimer ( + IN EFI_EVENT Event, + IN EFI_TIMER_DELAY Type, + IN UINT64 TriggerTime + ) +/*++ + +Routine Description: + + Sets the type of timer and the trigger time for a timer event. + +Arguments: + + UserEvent - The timer event that is to be signaled at the specified time + Type - The type of time that is specified in TriggerTime + TriggerTime - The number of 100ns units until the timer expires + +Returns: + + EFI_SUCCESS - The event has been set to be signaled at the requested time + EFI_INVALID_PARAMETER - Event or Type is not valid + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreSignalEvent ( + IN EFI_EVENT Event + ) +/*++ + +Routine Description: + + Signals the event. Queues the event to be notified if needed + +Arguments: + + Event - The event to signal + +Returns: + + EFI_INVALID_PARAMETER - Parameters are not valid. + + EFI_SUCCESS - The event was signaled. + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreWaitForEvent ( + IN UINTN NumberOfEvents, + IN EFI_EVENT *UserEvents, + OUT UINTN *UserIndex + ) +/*++ + +Routine Description: + + Stops execution until an event is signaled. + +Arguments: + + NumberOfEvents - The number of events in the UserEvents array + UserEvents - An array of EFI_EVENT + UserIndex - Pointer to the index of the event which satisfied the wait condition + +Returns: + + EFI_SUCCESS - The event indicated by Index was signaled. + EFI_INVALID_PARAMETER - The event indicated by Index has a notification function or + Event was not a valid type + EFI_UNSUPPORTED - The current TPL is not TPL_APPLICATION + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreCloseEvent ( + IN EFI_EVENT Event + ) +/*++ + +Routine Description: + + Closes an event and frees the event structure. + +Arguments: + + UserEvent - Event to close + +Returns: + + EFI_INVALID_PARAMETER - Parameters are not valid. + + EFI_SUCCESS - The event has been closed + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreCheckEvent ( + IN EFI_EVENT Event + ) +/*++ + +Routine Description: + + Check the status of an event + +Arguments: + + UserEvent - The event to check + +Returns: + + EFI_SUCCESS - The event is in the signaled state + EFI_NOT_READY - The event is not in the signaled state + EFI_INVALID_PARAMETER - Event is of type EVT_NOTIFY_SIGNAL + +--*/ +; + +EFI_STATUS +CoreAddMemorySpace ( + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ) +/*++ + +Routine Description: + + Add a segment of memory space to GCD map and add all available pages in this segment + as memory descriptors. + +Arguments: + + GcdMemoryType - Memory type of the segment. + + BaseAddress - Base address of the segment. + + Length - Length of the segment. + + Capabilities - alterable attributes of the segment. + +Returns: + + EFI_SUCCESS - Merged this segment into GCD map. + +--*/ +; + +EFI_STATUS +CoreAllocateMemorySpace ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ) +/*++ + +Routine Description: + + Allocate memory space on GCD map. + +Arguments: + + GcdAllocateType - The type of allocate operation + + GcdMemoryType - The desired memory type + + Alignment - Align with 2^Alignment + + Length - Length to allocate + + BaseAddress - Base address to allocate + + ImageHandle - The image handle consume the allocated space. + + DeviceHandle - The device handle consume the allocated space. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter. + + EFI_NOT_FOUND - No descriptor contains the desired space. + + EFI_SUCCESS - Memory space successfully allocated. + +--*/ +; + +EFI_STATUS +CoreFreeMemorySpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description:Routine Description: + + Free a segment of memory space in GCD map. + +Arguments: + + BaseAddress - Base address of the segment. + + Length - Length of the segment. + +Returns: + + EFI_SUCCESS - Space successfully freed. + +--*/ +; + +EFI_STATUS +CoreRemoveMemorySpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description:Routine Description: + + Remove a segment of memory space in GCD map. + +Arguments: + + BaseAddress - Base address of the segment. + + Length - Length of the segment. + +Returns: + + EFI_SUCCESS - Successfully a segment of memory space. + +--*/ +; + +EFI_STATUS +CoreGetMemorySpaceDescriptor ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor + ) +/*++ + +Routine Description: + + Search all entries in GCD map which contains specified segment and build it to a descriptor. + +Arguments: + + BaseAddress - Specified start address + + Descriptor - Specified length + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_SUCCESS - Successfully get memory space descriptor. + +--*/ +; + +EFI_STATUS +CoreSetMemorySpaceAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + Set memory space with specified attributes. + +Arguments: + + BaseAddress - Specified start address + + Length - Specified length + + Attributes - Specified attributes + +Returns: + + EFI_SUCCESS - Successfully set attribute of a segment of memory space. + +--*/ +; + +EFI_STATUS +CoreGetMemorySpaceMap ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap + ) +/*++ + +Routine Description: + + Transer all entries of GCD memory map into memory descriptors and pass to caller. + +Arguments: + + NumberOfDescriptors - Number of descriptors. + + MemorySpaceMap - Descriptor array + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Successfully get memory space map. + +--*/ +; + +EFI_STATUS +CoreAddIoSpace ( + IN EFI_GCD_IO_TYPE GcdIoType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Add a segment of IO space to GCD map. + +Arguments: + + GcdIoType - IO type of the segment. + + BaseAddress - Base address of the segment. + + Length - Length of the segment. + +Returns: + + EFI_SUCCESS - Merged this segment into GCD map. + +--*/ +; + +EFI_STATUS +CoreAllocateIoSpace ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ) +/*++ + +Routine Description: + + Allocate IO space on GCD map. + +Arguments: + + GcdAllocateType - The type of allocate operation + + GcdIoType - The desired IO type + + Alignment - Align with 2^Alignment + + Length - Length to allocate + + BaseAddress - Base address to allocate + + ImageHandle - The image handle consume the allocated space. + + DeviceHandle - The device handle consume the allocated space. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter. + + EFI_NOT_FOUND - No descriptor contains the desired space. + + EFI_SUCCESS - IO space successfully allocated. + +--*/ +; + +EFI_STATUS +CoreFreeIoSpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description:Routine Description: + + Free a segment of IO space in GCD map. + +Arguments: + + BaseAddress - Base address of the segment. + + Length - Length of the segment. + +Returns: + + EFI_SUCCESS - Space successfully freed. + +--*/ +; + +EFI_STATUS +CoreRemoveIoSpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description:Routine Description: + + Remove a segment of IO space in GCD map. + +Arguments: + + BaseAddress - Base address of the segment. + + Length - Length of the segment. + +Returns: + + EFI_SUCCESS - Successfully removed a segment of IO space. + +--*/ +; + +EFI_STATUS +CoreGetIoSpaceDescriptor ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor + ) +/*++ + +Routine Description: + + Search all entries in GCD map which contains specified segment and build it to a descriptor. + +Arguments: + + BaseAddress - Specified start address + + Descriptor - Specified length + +Returns: + + EFI_INVALID_PARAMETER - Descriptor is NULL. + + EFI_SUCCESS - Successfully get the IO space descriptor. + +--*/ +; + +EFI_STATUS +CoreGetIoSpaceMap ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap + ) +/*++ + +Routine Description: + + Transer all entries of GCD IO map into IO descriptors and pass to caller. + +Arguments: + + NumberOfDescriptors - Number of descriptors. + + IoSpaceMap - Descriptor array + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Successfully get IO space map. + +--*/ +; + +EFI_DXESERVICE +EFI_STATUS +EFIAPI +CoreDispatcher ( + VOID + ) +/*++ + +Routine Description: + + This is the main Dispatcher for DXE and it exits when there are no more + drivers to run. Drain the mScheduledQueue and load and start a PE + image for each driver. Search the mDiscoveredList to see if any driver can + be placed on the mScheduledQueue. If no drivers are placed on the + mScheduledQueue exit the function. On exit it is assumed the Bds() + will be called, and when the Bds() exits the Dispatcher will be called + again. + +Arguments: + + NONE + +Returns: + + EFI_ALREADY_STARTED - The DXE Dispatcher is already running + + EFI_NOT_FOUND - No DXE Drivers were dispatched + + EFI_SUCCESS - One or more DXE Drivers were dispatched + +--*/ +; +EFI_DXESERVICE +EFI_STATUS +EFIAPI +CoreSchedule ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ) +/*++ + +Routine Description: + + Check every driver and locate a matching one. If the driver is found, the Unrequested + state flag is cleared. + +Arguments: + + FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware + file specified by DriverName. + + DriverName - The Driver name to put in the Dependent state. + +Returns: + + EFI_SUCCESS - The DriverName was found and it's SOR bit was cleared + + EFI_NOT_FOUND - The DriverName does not exist or it's SOR bit was not set. + +--*/ +; + +EFI_DXESERVICE +EFI_STATUS +EFIAPI +CoreTrust ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ) +/*++ + +Routine Description: + + Convert a driver from the Untrused back to the Scheduled state + +Arguments: + + FirmwareVolumeHandle - The handle of the Firmware Volume that contains the firmware + file specified by DriverName. + + DriverName - The Driver name to put in the Scheduled state + +Returns: + + EFI_SUCCESS - The file was found in the untrusted state, and it was promoted + to the trusted state. + + EFI_NOT_FOUND - The file was not found in the untrusted state. + +--*/ +; + +BOOLEAN +CoreGrowBuffer ( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + Helper function called as part of the code needed + to allocate the proper sized buffer for various + EFI interfaces. + +Arguments: + + Status - Current status + + Buffer - Current allocated buffer, or NULL + + BufferSize - Current buffer size needed + +Returns: + + TRUE - if the buffer was reallocated and the caller + should try the API again. + + FALSE - buffer could not be allocated and the caller + should not try the API again. + +--*/ +; + +EFI_STATUS +EFIAPI +FwVolDriverInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This routine is the driver initialization entry point. It initializes the + libraries, and registers two notification functions. These notification + functions are responsible for building the FV stack dynamically. + +Arguments: + ImageHandle - The image handle. + SystemTable - The system table. + +Returns: + EFI_SUCCESS - Function successfully returned. + +--*/ +; + +EFI_STATUS +EFIAPI +InitializeSectionExtraction ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Entry point of the section extraction code. Initializes an instance of the + section extraction interface and installs it on a new handle. + +Arguments: + ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver + SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table + +Returns: + EFI_SUCCESS: Driver initialized successfully + EFI_OUT_OF_RESOURCES: Could not allocate needed resources + +--*/ +; + +EFI_STATUS +CoreProcessFirmwareVolume ( + IN VOID *FvHeader, + IN UINTN Size, + OUT EFI_HANDLE *FVProtocolHandle + ) +/*++ + +Routine Description: + This DXE service routine is used to process a firmware volume. In + particular, it can be called by BDS to process a single firmware + volume found in a capsule. + +Arguments: + FvHeader - pointer to a firmware volume header + Size - the size of the buffer pointed to by FvHeader + FVProtocolHandle - the handle on which a firmware volume protocol + was produced for the firmware volume passed in. + +Returns: + EFI_OUT_OF_RESOURCES - if an FVB could not be produced due to lack of + system resources + EFI_VOLUME_CORRUPTED - if the volume was corrupted + EFI_SUCCESS - a firmware volume protocol was produced for the + firmware volume + +--*/ +; + +// +//Functions used during debug buils +// +VOID +CoreDisplayMissingArchProtocols ( + VOID + ) +/*++ + + Routine Description: + Displays Architectural protocols that were not loaded and are required for DXE core to function + Only used in Debug Builds + + Arguments: + NONE + + Returns: + NONE + +--*/; + +VOID +CoreDisplayDiscoveredNotDispatched ( + VOID + ) +/*++ + + Routine Description: + + Traverse the discovered list for any drivers that were discovered but not loaded + because the dependency experessions evaluated to false + + Arguments: + + NONE + + Returns: + + NONE + +--*/; +#endif diff --git a/EdkModulePkg/Core/Dxe/DxeMain.mbd b/EdkModulePkg/Core/Dxe/DxeMain.mbd new file mode 100644 index 0000000000..ec084b5c56 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/DxeMain.mbd @@ -0,0 +1,42 @@ + + + + + DxeMain + D6A2CB7F-6A18-4e2f-B43B-9920A733700A + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + 2006-03-12 17:09 + 2006-03-19 15:18 + + + BaseLib + BaseCacheMaintenanceLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeCoreUefiDecompressLibFromHob + DxeCoreTianoDecompressLibFromHob + DxeCoreCustomDecompressLibFromHob + EdkDxePeCoffLoaderFromHobLib + DxeCoreHobLib + DxeCoreEntryPoint + BaseMemoryLib + UefiLib + BasePerformanceLibNull + + + _ModuleEntryPoint + + + diff --git a/EdkModulePkg/Core/Dxe/DxeMain.msa b/EdkModulePkg/Core/Dxe/DxeMain.msa new file mode 100644 index 0000000000..42531812df --- /dev/null +++ b/EdkModulePkg/Core/Dxe/DxeMain.msa @@ -0,0 +1,164 @@ + + + + + DxeMain + DXE_CORE + BS_DRIVER + D6A2CB7F-6A18-4e2f-B43B-9920A733700A + 0 + Component description file for DxeMain. + FIX ME! + Copyright (c) 2004-2006, 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. + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DxeCoreEntryPoint + DebugLib + UefiLib + BaseLib + HobLib + PerformanceLib + UefiDecompressLib + TianoDecompressLib + CustomDecompressLib + EdkPeCoffLoaderLib + CacheMaintenanceLib + BaseMemoryLib + + + DxeMain\DxeMain.c + DxeMain\DxeProtocolNotify.c + Dispatcher\Dispatcher.c + Dispatcher\Dependency.c + Event\ExecData.c + Event\Event.c + Event\Timer.c + Event\Tpl.c + FwVol\FwVol.c + FwVol\Ffs.c + FwVol\FwVolAttrib.c + FwVol\FwVolRead.c + FwVol\FwVolWrite.c + FwVolBlock\FwVolBlock.c + Mem\MemData.c + Mem\Page.c + Mem\Pool.c + Gcd\Gcd.c + Hand\Handle.c + Hand\Locate.c + Hand\Notify.c + Hand\DriverSupport.c + Library\Library.c + Misc\InstallConfigurationTable.c + Misc\SetWatchdogTimer.c + Misc\Stall.c + Misc\DebugImageInfo.c + Image\Image.c + Image\ImageFile.c + SectionExtraction\CoreSectionExtraction.c + DebugImageInfo.h + DebugMask.h + DxeMain.h + Exec.h + FwVolBlock.h + FwVolDriver.h + Gcd.h + Hand.h + Image.h + Imem.h + Library.h + + + MdePkg + EdkModulePkg + + + Ebc + LoadedImage + DevicePath + Cpu + FirmwareVolume + FirmwareVolumeDispatch + FirmwareVolumeBlock + SectionExtraction + DriverBinding + PlatformDriverOverride + BusSpecificDriverOverride + Timer + Metronome + MonotonicCounter + VariableWrite + Bds + Variable + Security + WatchdogTimer + Runtime + RealTimeClock + Reset + LoadFile + SimpleFileSystem + LoadPeImage + + + + MemoryTypeInformation + + + DxeServicesTable + + + HobList + + + DebugImageInfoTable + + + Apriori + + + FirmwareFileSystem + + + FileInfo + + + HobMemoryAllocModule + + + PeiPeCoffLoader + + + LoadPeImage + + + EventExitBootServices + + + EventVirtualAddressChange + + + EventMemoryMapChange + + + + + DxeMain + + + + + + diff --git a/EdkModulePkg/Core/Dxe/DxeMain/DxeMain.c b/EdkModulePkg/Core/Dxe/DxeMain/DxeMain.c new file mode 100644 index 0000000000..f98f0541ff --- /dev/null +++ b/EdkModulePkg/Core/Dxe/DxeMain/DxeMain.c @@ -0,0 +1,1083 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeMain.c + +Abstract: + + DXE Core Main Entry Point + +--*/ + +#include + +VOID +EFIAPI +DxeMain ( + IN VOID *HobStart + ); + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg0 ( + VOID + ); + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg1 ( + UINTN Arg1 + ); + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg2 ( + UINTN Arg1, + UINTN Arg2 + ); + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg3 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3 + ); + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg4 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4 + ); + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg5 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4, + UINTN Arg5 + ); + +EFI_STATUS +CoreGetPeiProtocol ( + IN EFI_GUID *ProtocolGuid, + IN VOID **Interface + ); + +EFI_STATUS +DxeMainUefiDecompressGetInfo ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +EFI_STATUS +EFIAPI +DxeMainUefiDecompress ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + IN OUT VOID *Destination, + IN UINT32 DestinationSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +EFI_STATUS +DxeMainTianoDecompressGetInfo ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +EFI_STATUS +EFIAPI +DxeMainTianoDecompress ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + IN OUT VOID *Destination, + IN UINT32 DestinationSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +EFI_STATUS +DxeMainCustomDecompressGetInfo ( + IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +EFI_STATUS +EFIAPI +DxeMainCustomDecompress ( + IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + IN OUT VOID *Destination, + IN UINT32 DestinationSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +// +// DXE Core Global Variables for Protocols from PEI +// +EFI_HANDLE mDecompressHandle = NULL; +EFI_PEI_PE_COFF_LOADER_PROTOCOL *gEfiPeiPeCoffLoader = NULL; + +// +// DXE Core globals for Architecture Protocols +// +EFI_SECURITY_ARCH_PROTOCOL *gSecurity = NULL; +EFI_CPU_ARCH_PROTOCOL *gCpu = NULL; +EFI_METRONOME_ARCH_PROTOCOL *gMetronome = NULL; +EFI_TIMER_ARCH_PROTOCOL *gTimer = NULL; +EFI_BDS_ARCH_PROTOCOL *gBds = NULL; +EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *gWatchdogTimer = NULL; +EFI_RUNTIME_ARCH_PROTOCOL *gRuntime = NULL; + +// +// BugBug: I'n not runtime, but is the PPI? +// +EFI_STATUS_CODE_PROTOCOL gStatusCodeInstance = { + NULL +}; + +EFI_STATUS_CODE_PROTOCOL *gStatusCode = &gStatusCodeInstance; + + +// +// DXE Core Global used to update core loaded image protocol handle +// +EFI_GUID *gDxeCoreFileName; +EFI_LOADED_IMAGE_PROTOCOL *gDxeCoreLoadedImage; + + + +// +// DXE Core Module Variables +// + +EFI_BOOT_SERVICES mBootServices = { + { + EFI_BOOT_SERVICES_SIGNATURE, // Signature + EFI_BOOT_SERVICES_REVISION, // Revision + sizeof (EFI_BOOT_SERVICES), // HeaderSize + 0, // CRC32 + 0 // Reserved + }, + (EFI_RAISE_TPL) CoreRaiseTpl, // RaiseTPL + (EFI_RESTORE_TPL) CoreRestoreTpl, // RestoreTPL + (EFI_ALLOCATE_PAGES) CoreAllocatePages, // AllocatePages + (EFI_FREE_PAGES) CoreFreePages, // FreePages + (EFI_GET_MEMORY_MAP) CoreGetMemoryMap, // GetMemoryMap + (EFI_ALLOCATE_POOL) CoreAllocatePool, // AllocatePool + (EFI_FREE_POOL) CoreFreePool, // FreePool + (EFI_CREATE_EVENT) CoreCreateEvent, // CreateEvent + (EFI_SET_TIMER) CoreSetTimer, // SetTimer + (EFI_WAIT_FOR_EVENT) CoreWaitForEvent, // WaitForEvent + (EFI_SIGNAL_EVENT) CoreSignalEvent, // SignalEvent + (EFI_CLOSE_EVENT) CoreCloseEvent, // CloseEvent + (EFI_CHECK_EVENT) CoreCheckEvent, // CheckEvent + (EFI_INSTALL_PROTOCOL_INTERFACE) CoreInstallProtocolInterface, // InstallProtocolInterface + (EFI_REINSTALL_PROTOCOL_INTERFACE) CoreReinstallProtocolInterface, // ReinstallProtocolInterface + (EFI_UNINSTALL_PROTOCOL_INTERFACE) CoreUninstallProtocolInterface, // UninstallProtocolInterface + (EFI_HANDLE_PROTOCOL) CoreHandleProtocol, // HandleProtocol + (VOID *) NULL, // Reserved + (EFI_REGISTER_PROTOCOL_NOTIFY) CoreRegisterProtocolNotify, // RegisterProtocolNotify + (EFI_LOCATE_HANDLE) CoreLocateHandle, // LocateHandle + (EFI_LOCATE_DEVICE_PATH) CoreLocateDevicePath, // LocateDevicePath + (EFI_INSTALL_CONFIGURATION_TABLE) CoreInstallConfigurationTable, // InstallConfigurationTable + (EFI_IMAGE_LOAD) CoreLoadImage, // LoadImage + (EFI_IMAGE_START) CoreStartImage, // StartImage + (EFI_EXIT) CoreExit, // Exit + (EFI_IMAGE_UNLOAD) CoreUnloadImage, // UnloadImage + (EFI_EXIT_BOOT_SERVICES) CoreExitBootServices, // ExitBootServices + (EFI_GET_NEXT_MONOTONIC_COUNT) CoreEfiNotAvailableYetArg1, // GetNextMonotonicCount + (EFI_STALL) CoreStall, // Stall + (EFI_SET_WATCHDOG_TIMER) CoreSetWatchdogTimer, // SetWatchdogTimer + (EFI_CONNECT_CONTROLLER) CoreConnectController, // ConnectController + (EFI_DISCONNECT_CONTROLLER) CoreDisconnectController, // DisconnectController + (EFI_OPEN_PROTOCOL) CoreOpenProtocol, // OpenProtocol + (EFI_CLOSE_PROTOCOL) CoreCloseProtocol, // CloseProtocol + (EFI_OPEN_PROTOCOL_INFORMATION) CoreOpenProtocolInformation, // OpenProtocolInformation + (EFI_PROTOCOLS_PER_HANDLE) CoreProtocolsPerHandle, // ProtocolsPerHandle + (EFI_LOCATE_HANDLE_BUFFER) CoreLocateHandleBuffer, // LocateHandleBuffer + (EFI_LOCATE_PROTOCOL) CoreLocateProtocol, // LocateProtocol + (EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES) CoreInstallMultipleProtocolInterfaces, // InstallMultipleProtocolInterfaces + (EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES) CoreUninstallMultipleProtocolInterfaces, // UninstallMultipleProtocolInterfaces + (EFI_CALCULATE_CRC32) CoreEfiNotAvailableYetArg3, // CalculateCrc32 + (EFI_COPY_MEM) CopyMem, // CopyMem + (EFI_SET_MEM) SetMem // SetMem +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + , + (EFI_CREATE_EVENT_EX) CoreCreateEventEx // CreateEventEx +#endif +}; + +EFI_DXE_SERVICES mDxeServices = { + { + EFI_DXE_SERVICES_SIGNATURE, // Signature + EFI_DXE_SERVICES_REVISION, // Revision + sizeof (EFI_DXE_SERVICES), // HeaderSize + 0, // CRC32 + 0 // Reserved + }, + (EFI_ADD_MEMORY_SPACE) CoreAddMemorySpace, // AddMemorySpace + (EFI_ALLOCATE_MEMORY_SPACE) CoreAllocateMemorySpace, // AllocateMemorySpace + (EFI_FREE_MEMORY_SPACE) CoreFreeMemorySpace, // FreeMemorySpace + (EFI_REMOVE_MEMORY_SPACE) CoreRemoveMemorySpace, // RemoveMemorySpace + (EFI_GET_MEMORY_SPACE_DESCRIPTOR) CoreGetMemorySpaceDescriptor, // GetMemorySpaceDescriptor + (EFI_SET_MEMORY_SPACE_ATTRIBUTES) CoreSetMemorySpaceAttributes, // SetMemorySpaceAttributes + (EFI_GET_MEMORY_SPACE_MAP) CoreGetMemorySpaceMap, // GetMemorySpaceMap + (EFI_ADD_IO_SPACE) CoreAddIoSpace, // AddIoSpace + (EFI_ALLOCATE_IO_SPACE) CoreAllocateIoSpace, // AllocateIoSpace + (EFI_FREE_IO_SPACE) CoreFreeIoSpace, // FreeIoSpace + (EFI_REMOVE_IO_SPACE) CoreRemoveIoSpace, // RemoveIoSpace + (EFI_GET_IO_SPACE_DESCRIPTOR) CoreGetIoSpaceDescriptor, // GetIoSpaceDescriptor + (EFI_GET_IO_SPACE_MAP) CoreGetIoSpaceMap, // GetIoSpaceMap + (EFI_DISPATCH) CoreDispatcher, // Dispatch + (EFI_SCHEDULE) CoreSchedule, // Schedule + (EFI_TRUST) CoreTrust, // Trust + (EFI_PROCESS_FIRMWARE_VOLUME) CoreProcessFirmwareVolume, // ProcessFirmwareVolume +}; + +EFI_SYSTEM_TABLE mEfiSystemTableTemplate = { + { + EFI_SYSTEM_TABLE_SIGNATURE, // Signature + EFI_SYSTEM_TABLE_REVISION, // Revision + sizeof (EFI_SYSTEM_TABLE), // HeaderSize + 0, // CRC32 + 0 // Reserved + }, + NULL, // FirmwareVendor + 0, // FirmwareRevision + NULL, // ConsoleInHandle + NULL, // ConIn + NULL, // ConsoleOutHandle + NULL, // ConOut + NULL, // StandardErrorHandle + NULL, // StdErr + NULL, // RuntimeServices + &mBootServices, // BootServices + 0, // NumberOfConfigurationTableEntries + NULL // ConfigurationTable +}; + +EFI_RUNTIME_SERVICES mEfiRuntimeServicesTableTemplate = { + { + EFI_RUNTIME_SERVICES_SIGNATURE, // Signature + EFI_RUNTIME_SERVICES_REVISION, // Revision + sizeof (EFI_RUNTIME_SERVICES), // HeaderSize + 0, // CRC32 + 0 // Reserved + }, + (EFI_GET_TIME) CoreEfiNotAvailableYetArg2, // GetTime + (EFI_SET_TIME) CoreEfiNotAvailableYetArg1, // SetTime + (EFI_GET_WAKEUP_TIME) CoreEfiNotAvailableYetArg3, // GetWakeupTime + (EFI_SET_WAKEUP_TIME) CoreEfiNotAvailableYetArg2, // SetWakeupTime + (EFI_SET_VIRTUAL_ADDRESS_MAP) CoreEfiNotAvailableYetArg4, // SetVirtualAddressMap + (EFI_CONVERT_POINTER) CoreEfiNotAvailableYetArg2, // ConvertPointer + (EFI_GET_VARIABLE) CoreEfiNotAvailableYetArg5, // GetVariable + (EFI_GET_NEXT_VARIABLE_NAME) CoreEfiNotAvailableYetArg3, // GetNextVariableName + (EFI_SET_VARIABLE) CoreEfiNotAvailableYetArg5, // SetVariable + (EFI_GET_NEXT_HIGH_MONO_COUNT) CoreEfiNotAvailableYetArg1, // GetNextHighMonotonicCount + (EFI_RESET_SYSTEM) CoreEfiNotAvailableYetArg4 // ResetSystem +#if ((EDK_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000)) + , + (TIANO_REPORT_STATUS_CODE) CoreEfiNotAvailableYetArg5 // ReportStatusCode +#elif (EFI_SPECIFICATION_VERSION >= 0x00020000) + , + (EFI_UPDATE_CAPSULE) CoreEfiNotAvailableYetArg3, // UpdateCapsule + (EFI_QUERY_CAPSULE_CAPABILITIES) CoreEfiNotAvailableYetArg4, // QueryCapsuleCapabilities + (EFI_QUERY_VARIABLE_INFO) CoreEfiNotAvailableYetArg4 // QueryVariableInfo +#endif +}; + +// +// DXE Core Global Variables for the EFI System Table, Boot Services Table, +// DXE Services Table, and Runtime Services Table +// +EFI_BOOT_SERVICES *gBS = &mBootServices; +EFI_DXE_SERVICES *gDS = &mDxeServices; +EFI_SYSTEM_TABLE *gST = NULL; + +// +// For debug initialize gRT to template. gRT must be allocated from RT memory +// but gRT is used for ASSERT () and DEBUG () type macros so lets give it +// a value that will not cause debug infrastructure to crash early on. +// +EFI_RUNTIME_SERVICES *gRT = &mEfiRuntimeServicesTableTemplate; +EFI_HANDLE gDxeCoreImageHandle = NULL; + +VOID *mHobStart; + +// +// EFI Decompress Protocol +// +EFI_DECOMPRESS_PROTOCOL gEfiDecompress = { + DxeMainUefiDecompressGetInfo, + DxeMainUefiDecompress +}; + +// +// Tiano Decompress Protocol +// +EFI_TIANO_DECOMPRESS_PROTOCOL gEfiTianoDecompress = { + DxeMainTianoDecompressGetInfo, + DxeMainTianoDecompress +}; + +// +// Customized Decompress Protocol +// +EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL gEfiCustomizedDecompress = { + DxeMainCustomDecompressGetInfo, + DxeMainCustomDecompress +}; + +// +// Main entry point to the DXE Core +// +VOID +EFIAPI +DxeMain ( + IN VOID *HobStart + ) +/*++ + +Routine Description: + + Main entry point to DXE Core. + +Arguments: + + HobStart - Pointer to the beginning of the HOB List from PEI + +Returns: + + This function should never return + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS MemoryBaseAddress; + UINT64 MemoryLength; + +#ifdef EFI_DXE_PERFORMANCE + UINT64 Tick; + + GetTimerValue (&Tick); +#endif + + mHobStart = HobStart; + + // + // Initialize Memory Services + // + CoreInitializeMemoryServices (&HobStart, &MemoryBaseAddress, &MemoryLength); + + // + // Allocate the EFI System Table and EFI Runtime Service Table from EfiRuntimeServicesData + // Use the templates to initialize the contents of the EFI System Table and EFI Runtime Services Table + // + gST = CoreAllocateRuntimeCopyPool (sizeof (EFI_SYSTEM_TABLE), &mEfiSystemTableTemplate); + ASSERT (gST != NULL); + + gRT = CoreAllocateRuntimeCopyPool (sizeof (EFI_RUNTIME_SERVICES), &mEfiRuntimeServicesTableTemplate); + ASSERT (gRT != NULL); + + gST->RuntimeServices = gRT; + + // + // Start the Image Services. + // + Status = CoreInitializeImageServices (HobStart); + ASSERT_EFI_ERROR (Status); + + // + // Call constructor for all libraries + // + ProcessLibraryConstructorList (gDxeCoreImageHandle, gST); + + // + // Initialize the Global Coherency Domain Services + // + Status = CoreInitializeGcdServices (&HobStart, MemoryBaseAddress, MemoryLength); + ASSERT_EFI_ERROR (Status); + + // + // Install the DXE Services Table into the EFI System Tables's Configuration Table + // + Status = CoreInstallConfigurationTable (&gEfiDxeServicesTableGuid, gDS); + ASSERT_EFI_ERROR (Status); + + // + // Install the HOB List into the EFI System Tables's Configuration Table + // + Status = CoreInstallConfigurationTable (&gEfiHobListGuid, HobStart); + ASSERT_EFI_ERROR (Status); + + // + // Install Memory Type Information Table into the EFI System Tables's Configuration Table + // + Status = CoreInstallConfigurationTable (&gEfiMemoryTypeInformationGuid, &gMemoryTypeInformation); + ASSERT_EFI_ERROR (Status); + + // + // Initialize the ReportStatusCode with PEI version, if availible + // + CoreGetPeiProtocol (&gEfiStatusCodeRuntimeProtocolGuid, (VOID **)&gStatusCode->ReportStatusCode); +#if ((EDK_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000)) + gRT->ReportStatusCode = gStatusCode->ReportStatusCode; +#endif + + // + // Report Status Code here for DXE_ENTRY_POINT once it is available + // + CoreReportProgressCode ((EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_ENTRY_POINT)); + + // + // Create the aligned system table pointer structure that is used by external + // debuggers to locate the system table... Also, install debug image info + // configuration table. + // + CoreInitializeDebugImageInfoTable (); + CoreNewDebugImageInfoEntry ( + EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, + gDxeCoreLoadedImage, + gDxeCoreImageHandle + ); + + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "HOBLIST address in DXE = 0x%08x\n", HobStart)); + + // + // Initialize the Event Services + // + Status = CoreInitializeEventServices (); + ASSERT_EFI_ERROR (Status); + + + // + // Get the Protocols that were passed in from PEI to DXE through GUIDed HOBs + // + // These Protocols are not architectural. This implementation is sharing code between + // PEI and DXE in order to save FLASH space. These Protocols could also be implemented + // as part of the DXE Core. However, that would also require the DXE Core to be ported + // each time a different CPU is used, a different Decompression algorithm is used, or a + // different Image type is used. By placing these Protocols in PEI, the DXE Core remains + // generic, and only PEI and the Arch Protocols need to be ported from Platform to Platform, + // and from CPU to CPU. + // + + // + // Publish the EFI, Tiano, and Custom Decompress protocols for use by other DXE components + // + Status = CoreInstallMultipleProtocolInterfaces ( + &mDecompressHandle, + &gEfiDecompressProtocolGuid, &gEfiDecompress, + &gEfiTianoDecompressProtocolGuid, &gEfiTianoDecompress, + &gEfiCustomizedDecompressProtocolGuid, &gEfiCustomizedDecompress, + NULL + ); + ASSERT_EFI_ERROR (Status); + + gEfiPeiPeCoffLoader = GetPeCoffLoaderProtocol (); + ASSERT (gEfiPeiPeCoffLoader != NULL); + + // + // Register for the GUIDs of the Architectural Protocols, so the rest of the + // EFI Boot Services and EFI Runtime Services tables can be filled in. + // + CoreNotifyOnArchProtocolInstallation (); + + // + // Produce Firmware Volume Protocols, one for each FV in the HOB list. + // + Status = FwVolBlockDriverInit (gDxeCoreImageHandle, gST); + ASSERT_EFI_ERROR (Status); + + Status = FwVolDriverInit (gDxeCoreImageHandle, gST); + ASSERT_EFI_ERROR (Status); + + // + // Produce the Section Extraction Protocol + // + Status = InitializeSectionExtraction (gDxeCoreImageHandle, gST); + ASSERT_EFI_ERROR (Status); + + // + // Initialize the DXE Dispatcher + // + PERF_START (0,"CoreInitializeDispatcher", "DxeMain", 0) ; + CoreInitializeDispatcher (); + PERF_END (0,"CoreInitializeDispatcher", "DxeMain", 0) ; + + // + // Invoke the DXE Dispatcher + // + PERF_START (0, "CoreDispatcher", "DxeMain", 0); + CoreDispatcher (); + PERF_END (0, "CoreDispatcher", "DxeMain", 0); + + // + // Display Architectural protocols that were not loaded if this is DEBUG build + // + DEBUG_CODE ( + CoreDisplayMissingArchProtocols (); + ); + + // + // Assert if the Architectural Protocols are not present. + // + ASSERT_EFI_ERROR (CoreAllEfiServicesAvailable ()); + + // + // Report Status code before transfer control to BDS + // + CoreReportProgressCode ((EFI_SOFTWARE_DXE_CORE | EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT)); + // + // Display any drivers that were not dispatched because dependency expression + // evaluated to false if this is a debug build + // + DEBUG_CODE ( + CoreDisplayDiscoveredNotDispatched (); + ); + + // + // Transfer control to the BDS Architectural Protocol + // + gBds->Entry (gBds); + + // + // BDS should never return + // + ASSERT (FALSE); + CpuDeadLoop (); +} + + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg0 ( + VOID + ) +/*++ + +Routine Description: + + Place holder function until all the Boot Services and Runtime Services are available + +Arguments: + + None + +Returns: + + EFI_NOT_AVAILABLE_YET + +--*/ +{ + // + // This function should never be executed. If it does, then the architectural protocols + // have not been designed correctly. The CpuBreakpoint () is commented out for now until the + // DXE Core and all the Architectural Protocols are complete. + // + + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg1 ( + UINTN Arg1 + ) +/*++ + +Routine Description: + + Place holder function until all the Boot Services and Runtime Services are available + +Arguments: + + Arg1 - Undefined + +Returns: + + EFI_NOT_AVAILABLE_YET + +--*/ +{ + // + // This function should never be executed. If it does, then the architectural protocols + // have not been designed correctly. The CpuBreakpoint () is commented out for now until the + // DXE Core and all the Architectural Protocols are complete. + // + + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg2 ( + UINTN Arg1, + UINTN Arg2 + ) +/*++ + +Routine Description: + + Place holder function until all the Boot Services and Runtime Services are available + +Arguments: + + Arg1 - Undefined + + Arg2 - Undefined + +Returns: + + EFI_NOT_AVAILABLE_YET + +--*/ +{ + // + // This function should never be executed. If it does, then the architectural protocols + // have not been designed correctly. The CpuBreakpoint () is commented out for now until the + // DXE Core and all the Architectural Protocols are complete. + // + + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg3 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3 + ) +/*++ + +Routine Description: + + Place holder function until all the Boot Services and Runtime Services are available + +Arguments: + + Arg1 - Undefined + + Arg2 - Undefined + + Arg3 - Undefined + +Returns: + + EFI_NOT_AVAILABLE_YET + +--*/ +{ + // + // This function should never be executed. If it does, then the architectural protocols + // have not been designed correctly. The CpuBreakpoint () is commented out for now until the + // DXE Core and all the Architectural Protocols are complete. + // + + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg4 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4 + ) +/*++ + +Routine Description: + + Place holder function until all the Boot Services and Runtime Services are available + +Arguments: + + Arg1 - Undefined + + Arg2 - Undefined + + Arg3 - Undefined + + Arg4 - Undefined + +Returns: + + EFI_NOT_AVAILABLE_YET + +--*/ +{ + // + // This function should never be executed. If it does, then the architectural protocols + // have not been designed correctly. The CpuBreakpoint () is commented out for now until the + // DXE Core and all the Architectural Protocols are complete. + // + + return EFI_NOT_AVAILABLE_YET; +} + +EFI_STATUS +EFIAPI +CoreEfiNotAvailableYetArg5 ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4, + UINTN Arg5 + ) +/*++ + +Routine Description: + + Place holder function until all the Boot Services and Runtime Services are available + +Arguments: + + Arg1 - Undefined + + Arg2 - Undefined + + Arg3 - Undefined + + Arg4 - Undefined + + Arg5 - Undefined + +Returns: + + EFI_NOT_AVAILABLE_YET + +--*/ +{ + // + // This function should never be executed. If it does, then the architectural protocols + // have not been designed correctly. The CpuBreakpoint () is commented out for now until the + // DXE Core and all the Architectural Protocols are complete. + // + + return EFI_NOT_AVAILABLE_YET; +} + + +EFI_STATUS +CoreGetPeiProtocol ( + IN EFI_GUID *ProtocolGuid, + IN VOID **Interface + ) +/*++ + +Routine Description: + + Searches for a Protocol Interface passed from PEI through a HOB + +Arguments: + + ProtocolGuid - The Protocol GUID to search for in the HOB List + + Interface - A pointer to the interface for the Protocol GUID + +Returns: + + EFI_SUCCESS - The Protocol GUID was found and its interface is returned in Interface + + EFI_NOT_FOUND - The Protocol GUID was not found in the HOB List + +--*/ +{ + EFI_HOB_GUID_TYPE *GuidHob; + VOID *Buffer; + + GuidHob = GetNextGuidHob (ProtocolGuid, mHobStart); + if (GuidHob == NULL) { + return EFI_NOT_FOUND; + } + + Buffer = GET_GUID_HOB_DATA (GuidHob); + ASSERT (Buffer != NULL); + + *Interface = (VOID *)(*(UINTN *)(Buffer)); + + return EFI_SUCCESS; +} + + +VOID +CalculateEfiHdrCrc ( + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Calcualte the 32-bit CRC in a EFI table using the service provided by the + gRuntime service. + +Arguments: + + Hdr - Pointer to an EFI standard header + +Returns: + + None + +--*/ +{ + UINT32 Crc; + + Hdr->CRC32 = 0; + + // + // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then + // Crc will come back as zero if we set it to zero here + // + Crc = 0; + gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc); + Hdr->CRC32 = Crc; +} + + + +EFI_STATUS +EFIAPI +CoreExitBootServices ( + IN EFI_HANDLE ImageHandle, + IN UINTN MapKey + ) +/*++ + +Routine Description: + + EFI 1.0 API to terminate Boot Services + +Arguments: + + ImageHandle - Handle that represents the identity of the calling image + + MapKey -Key to the latest memory map. + +Returns: + + EFI_SUCCESS - Boot Services terminated + EFI_INVALID_PARAMETER - MapKey is incorrect. + +--*/ +{ + EFI_STATUS Status; + + // + // Terminate memory services if the MapKey matches + // + Status = CoreTerminateMemoryMap (MapKey); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Notify other drivers that we are exiting boot services. + // + CoreNotifySignalList (&gEfiEventExitBootServicesGuid); + + // + // Disable Timer + // + gTimer->SetTimerPeriod (gTimer, 0); + + // + // Disable CPU Interrupts + // + gCpu->DisableInterrupt (gCpu); + + // + // Register Runtime events with the Runtime Architectural Protocol + // + CoreShutdownEventServices (); + + // + // Register Runtime images with the Runtime Architectural Protocol + // + CoreShutdownImageServices (); + + // + // Report that ExitBootServices() has been called + // + // We are using gEfiDxeServicesTableGuid as the caller ID for Dxe Core + // + CoreReportProgressCode ((EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_BS_PC_EXIT_BOOT_SERVICES)); + + // + // Clear the non-runtime values of the EFI System Table + // + gST->BootServices = NULL; + gST->ConIn = NULL; + gST->ConsoleInHandle = NULL; + gST->ConOut = NULL; + gST->ConsoleOutHandle = NULL; + gST->StdErr = NULL; + gST->StandardErrorHandle = NULL; + + // + // Recompute the 32-bit CRC of the EFI System Table + // + CalculateEfiHdrCrc (&gST->Hdr); + + // + // Zero out the Boot Service Table + // + SetMem (gBS, sizeof (EFI_BOOT_SERVICES), 0); + gBS = NULL; + + return Status; +} + +EFI_STATUS +DxeMainUefiDecompressGetInfo ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +{ + return UefiDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize); +} + +EFI_STATUS +EFIAPI +DxeMainUefiDecompress ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + IN OUT VOID *Destination, + IN UINT32 DestinationSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +{ + EFI_STATUS Status; + UINT32 TestDestinationSize; + UINT32 TestScratchSize; + + Status = UefiDecompressGetInfo (Source, SourceSize, &TestDestinationSize, &TestScratchSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (ScratchSize < TestScratchSize || DestinationSize < TestDestinationSize) { + return RETURN_INVALID_PARAMETER; + } + + return UefiDecompress (Source, Destination, Scratch); +} + +EFI_STATUS +DxeMainTianoDecompressGetInfo ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +{ + return TianoDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize); +} + +EFI_STATUS +EFIAPI +DxeMainTianoDecompress ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + IN OUT VOID *Destination, + IN UINT32 DestinationSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +{ + EFI_STATUS Status; + UINT32 TestDestinationSize; + UINT32 TestScratchSize; + + Status = TianoDecompressGetInfo (Source, SourceSize, &TestDestinationSize, &TestScratchSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (ScratchSize < TestScratchSize || DestinationSize < TestDestinationSize) { + return RETURN_INVALID_PARAMETER; + } + + return TianoDecompress (Source, Destination, Scratch); +} + +EFI_STATUS +DxeMainCustomDecompressGetInfo ( + IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +{ + return CustomDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize); +} + +EFI_STATUS +EFIAPI +DxeMainCustomDecompress ( + IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + IN OUT VOID *Destination, + IN UINT32 DestinationSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +{ + EFI_STATUS Status; + UINT32 TestDestinationSize; + UINT32 TestScratchSize; + + Status = CustomDecompressGetInfo (Source, SourceSize, &TestDestinationSize, &TestScratchSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (ScratchSize < TestScratchSize || DestinationSize < TestDestinationSize) { + return RETURN_INVALID_PARAMETER; + } + + return CustomDecompress (Source, Destination, Scratch); +} + diff --git a/EdkModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c b/EdkModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c new file mode 100644 index 0000000000..7e49423fb4 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/DxeMain/DxeProtocolNotify.c @@ -0,0 +1,266 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeProtocolNotify.c + +Abstract: + + This file deals with Architecture Protocol (AP) registration in + the Dxe Core. The mArchProtocols[] array represents a list of + events that represent the Architectural Protocols. + +--*/ + +#include + + +// +// DXE Core Global Variables for all of the Architectural Protocols. +// If a protocol is installed mArchProtocols[].Present will be TRUE. +// +// CoreNotifyOnArchProtocolInstallation () fills in mArchProtocols[].Event +// and mArchProtocols[].Registration as it creates events for every array +// entry. +// + +ARCHITECTURAL_PROTOCOL_ENTRY mArchProtocols[] = { + { &gEfiSecurityArchProtocolGuid, (VOID **)&gSecurity, NULL, NULL, FALSE }, + { &gEfiCpuArchProtocolGuid, (VOID **)&gCpu, NULL, NULL, FALSE }, + { &gEfiMetronomeArchProtocolGuid, (VOID **)&gMetronome, NULL, NULL, FALSE }, + { &gEfiTimerArchProtocolGuid, (VOID **)&gTimer, NULL, NULL, FALSE }, + { &gEfiBdsArchProtocolGuid, (VOID **)&gBds, NULL, NULL, FALSE }, + { &gEfiWatchdogTimerArchProtocolGuid, (VOID **)&gWatchdogTimer, NULL, NULL, FALSE }, + { &gEfiRuntimeArchProtocolGuid, (VOID **)&gRuntime, NULL, NULL, FALSE }, + { &gEfiVariableArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE }, + { &gEfiVariableWriteArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE }, + { &gEfiMonotonicCounterArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE }, + { &gEfiResetArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE }, +// { &gEfiStatusCodeRuntimeProtocolGuid, (VOID **)&gStatusCode, NULL, NULL, FALSE }, + { &gEfiRealTimeClockArchProtocolGuid, (VOID **)NULL, NULL, NULL, FALSE }, + { NULL, (VOID **)NULL, NULL, NULL, FALSE } +}; + + +EFI_STATUS +CoreAllEfiServicesAvailable ( + VOID + ) +/*++ + +Routine Description: + Return TRUE if all AP services are availible. + +Arguments: + NONE + +Returns: + EFI_SUCCESS - All AP services are available + EFI_NOT_FOUND - At least one AP service is not available + +--*/ +{ + ARCHITECTURAL_PROTOCOL_ENTRY *Entry; + + for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) { + if (!Entry->Present) { + return EFI_NOT_FOUND; + } + } + + return EFI_SUCCESS; +} + + +VOID +EFIAPI +GenericArchProtocolNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + Notification event handler registered by CoreNotifyOnArchProtocolInstallation (). + This notify function is registered for every architectural protocol. This handler + updates mArchProtocol[] array entry with protocol instance data and sets it's + present flag to TRUE. If any constructor is required it is executed. The EFI + System Table headers are updated. + +Arguments: + + Event - The Event that is being processed, not used. + + Context - Event Context, not used. + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + ARCHITECTURAL_PROTOCOL_ENTRY *Entry; + VOID *Protocol; + BOOLEAN Found; + + Found = FALSE; + for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) { + + Status = CoreLocateProtocol (Entry->ProtocolGuid, Entry->Registration, &Protocol); + if (EFI_ERROR (Status)) { + continue; + } + + Found = TRUE; + Entry->Present = TRUE; + + // + // Update protocol global variable if one exists. Entry->Protocol points to a global variable + // if one exists in the DXE core for this Architectural Protocol + // + if (Entry->Protocol != NULL) { + *(Entry->Protocol) = Protocol; + } + + if (CompareGuid (Entry->ProtocolGuid, &gEfiTimerArchProtocolGuid)) { + // + // Register the Core timer tick handler with the Timer AP + // + gTimer->RegisterHandler (gTimer, CoreTimerTick); + } + + if (CompareGuid (Entry->ProtocolGuid, &gEfiRuntimeArchProtocolGuid)) { + // + // When runtime architectural protocol is available, updates CRC32 in the Debug Table + // + CoreUpdateDebugTableCrc32 (); + } + } + + // + // It's over kill to do them all every time, but it saves a lot of code. + // + if (Found) { + CalculateEfiHdrCrc (&gRT->Hdr); + CalculateEfiHdrCrc (&gBS->Hdr); + CalculateEfiHdrCrc (&gST->Hdr); + CalculateEfiHdrCrc (&gDS->Hdr); + } +} + + + +VOID +CoreNotifyOnArchProtocolInstallation ( + VOID + ) +/*++ + +Routine Description: + Creates an event that is fired everytime a Protocol of a specific type is installed + +Arguments: + NONE + +Returns: + NONE + +--*/ +{ + EFI_STATUS Status; + ARCHITECTURAL_PROTOCOL_ENTRY *Entry; + + for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) { + + // + // Create the event + // + Status = CoreCreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + GenericArchProtocolNotify, + NULL, + &Entry->Event + ); + ASSERT_EFI_ERROR(Status); + + // + // Register for protocol notifactions on this event + // + Status = CoreRegisterProtocolNotify ( + Entry->ProtocolGuid, + Entry->Event, + &Entry->Registration + ); + ASSERT_EFI_ERROR(Status); + + } +} + +// +// Following is needed to display missing architectural protocols in debug builds +// +typedef struct { + EFI_GUID *ProtocolGuid; + CHAR16 *GuidString; +} GUID_TO_STRING_PROTOCOL_ENTRY; + +static const GUID_TO_STRING_PROTOCOL_ENTRY MissingProtocols[] = { + { &gEfiSecurityArchProtocolGuid, (CHAR16 *)L"Security" }, + { &gEfiCpuArchProtocolGuid, (CHAR16 *)L"CPU" }, + { &gEfiMetronomeArchProtocolGuid, (CHAR16 *)L"Metronome" }, + { &gEfiTimerArchProtocolGuid, (CHAR16 *)L"Timer" }, + { &gEfiBdsArchProtocolGuid, (CHAR16 *)L"Bds" }, + { &gEfiWatchdogTimerArchProtocolGuid, (CHAR16 *)L"Watchdog Timer" }, + { &gEfiRuntimeArchProtocolGuid, (CHAR16 *)L"Runtime" }, + { &gEfiVariableArchProtocolGuid, (CHAR16 *)L"Variable" }, + { &gEfiVariableWriteArchProtocolGuid, (CHAR16 *)L"Variable Write" }, + { &gEfiMonotonicCounterArchProtocolGuid, (CHAR16 *)L"Monotonic Counter" }, + { &gEfiResetArchProtocolGuid, (CHAR16 *)L"Reset" }, +// { &gEfiStatusCodeRuntimeProtocolGuid, (CHAR16 *)L"Status Code" }, + { &gEfiRealTimeClockArchProtocolGuid, (CHAR16 *)L"Real Time Clock" } +}; + +VOID +CoreDisplayMissingArchProtocols ( + VOID + ) +/*++ + +Routine Description: + Displays Architectural protocols that were not loaded and are required for DXE core to function + Only used in Debug Builds + +Arguments: + NONE + +Returns: + NONE + +--*/ +{ + const GUID_TO_STRING_PROTOCOL_ENTRY *MissingEntry; + ARCHITECTURAL_PROTOCOL_ENTRY *Entry; + + for (Entry = mArchProtocols; Entry->ProtocolGuid != NULL; Entry++) { + if (!Entry->Present) { + MissingEntry = MissingProtocols; + for (MissingEntry = MissingProtocols; TRUE ; MissingEntry++) { + if (CompareGuid (Entry->ProtocolGuid, MissingEntry->ProtocolGuid)) { + DEBUG ((EFI_D_ERROR, "\n%s Arch Protocol not present!!\n", MissingEntry->GuidString)); + break; + } + } + } + } +} diff --git a/EdkModulePkg/Core/Dxe/Event/event.c b/EdkModulePkg/Core/Dxe/Event/event.c new file mode 100644 index 0000000000..e8391419ab --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Event/event.c @@ -0,0 +1,862 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + event.c + +Abstract: + + EFI Event support + +--*/ + + +#include + +// +// Enumerate the valid types +// +UINT32 mEventTable[] = { + // + // 0x80000200 Timer event with a notification function that is + // queue when the event is signaled with SignalEvent() + // + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + // + // 0x80000000 Timer event without a notification function. It can be + // signaled with SignalEvent() and checked with CheckEvent() or WaitForEvent(). + // + EFI_EVENT_TIMER, + // + // 0x00000100 Generic event with a notification function that + // can be waited on with CheckEvent() or WaitForEvent() + // + EFI_EVENT_NOTIFY_WAIT, + // + // 0x00000200 Generic event with a notification function that + // is queue when the event is signaled with SignalEvent() + // + EFI_EVENT_NOTIFY_SIGNAL, + // + // 0x00000201 ExitBootServicesEvent. + // + EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES, + // + // 0x60000202 SetVirtualAddressMapEvent. + // + EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) + // + // 0x00000203 ReadyToBootEvent. + // + EFI_EVENT_SIGNAL_READY_TO_BOOT, + // + // 0x00000204 LegacyBootEvent. + // + EFI_EVENT_SIGNAL_LEGACY_BOOT, + // + // 0x00000603 Signal all ReadyToBootEvents. + // + EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_READY_TO_BOOT, + // + // 0x00000604 Signal all LegacyBootEvents. + // + EFI_EVENT_NOTIFY_SIGNAL_ALL | EFI_EVENT_SIGNAL_LEGACY_BOOT, +#endif + + // + // 0x00000000 Generic event without a notification function. + // It can be signaled with SignalEvent() and checked with CheckEvent() + // or WaitForEvent(). + // + 0x00000000, + // + // 0x80000100 Timer event with a notification function that can be + // waited on with CheckEvent() or WaitForEvent() + // + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_WAIT, +}; + + +VOID +CoreAcquireEventLock ( + VOID + ) +/*++ + +Routine Description: + + Enter critical section by acquiring the lock on gEventQueueLock. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + CoreAcquireLock (&gEventQueueLock); +} + + +VOID +CoreReleaseEventLock ( + VOID + ) +/*++ + +Routine Description: + + Exit critical section by releasing the lock on gEventQueueLock. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + CoreReleaseLock (&gEventQueueLock); +} + + +EFI_STATUS +CoreInitializeEventServices ( + VOID + ) +/*++ + +Routine Description: + + Initializes "event" support and populates parts of the System and Runtime Table. + +Arguments: + + None + +Returns: + + EFI_SUCCESS - Always return success + +--*/ +{ + UINTN Index; + + for (Index=0; Index <= EFI_TPL_HIGH_LEVEL; Index++) { + InitializeListHead (&gEventQueue[Index]); + } + + CoreInitializeTimer (); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CoreShutdownEventServices ( + VOID + ) +/*++ + +Routine Description: + + Register all runtime events to make sure they are still available after ExitBootService. + +Arguments: + + None + +Returns: + + EFI_SUCCESS - Always return success. + +--*/ +{ + LIST_ENTRY *Link; + IEVENT *Event; + + // + // The Runtime AP is required for the core to function! + // + ASSERT (gRuntime != NULL); + + for (Link = mRuntimeEventList.ForwardLink; Link != &mRuntimeEventList; Link = Link->ForwardLink) { + Event = CR (Link, IEVENT, RuntimeLink, EVENT_SIGNATURE); + gRuntime->RegisterEvent ( + gRuntime, + Event->Type, + Event->NotifyTpl, + Event->NotifyFunction, + Event->NotifyContext, + (VOID **)Event + ); + } + + return EFI_SUCCESS; +} + + +VOID +CoreDispatchEventNotifies ( + IN EFI_TPL Priority + ) +/*++ + +Routine Description: + + Dispatches all pending events. + +Arguments: + + Priority - The task priority level of event notifications to dispatch + +Returns: + + None + +--*/ +{ + IEVENT *Event; + LIST_ENTRY *Head; + + CoreAcquireEventLock (); + ASSERT (gEventQueueLock.OwnerTpl == Priority); + Head = &gEventQueue[Priority]; + + // + // Dispatch all the pending notifications + // + while (!IsListEmpty (Head)) { + + Event = CR (Head->ForwardLink, IEVENT, NotifyLink, EVENT_SIGNATURE); + RemoveEntryList (&Event->NotifyLink); + + Event->NotifyLink.ForwardLink = NULL; + + // + // Only clear the SIGNAL status if it is a SIGNAL type event. + // WAIT type events are only cleared in CheckEvent() + // + if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) { + Event->SignalCount = 0; + } + + CoreReleaseEventLock (); + + // + // Notify this event + // + ASSERT (Event->NotifyFunction != NULL); + Event->NotifyFunction (Event, Event->NotifyContext); + + // + // Check for next pending event + // + CoreAcquireEventLock (); + } + + gEventPending &= ~(1 << Priority); + CoreReleaseEventLock (); +} + + +VOID +STATIC +CoreNotifyEvent ( + IN IEVENT *Event + ) +/*++ + +Routine Description: + + Queues the event's notification function to fire + +Arguments: + + Event - The Event to notify + +Returns: + + None + +--*/ +{ + + // + // Event database must be locked + // + ASSERT_LOCKED (&gEventQueueLock); + + // + // If the event is queued somewhere, remove it + // + + if (Event->NotifyLink.ForwardLink != NULL) { + RemoveEntryList (&Event->NotifyLink); + Event->NotifyLink.ForwardLink = NULL; + } + + // + // Queue the event to the pending notification list + // + + InsertTailList (&gEventQueue[Event->NotifyTpl], &Event->NotifyLink); + gEventPending |= (UINTN)(1 << Event->NotifyTpl); +} + + + +VOID +CoreNotifySignalList ( + IN EFI_GUID *EventGroup + ) +/*++ + +Routine Description: + Signals all events in the EventGroup + +Arguments: + EventGroup - The list to signal + +Returns: + + None + +--*/ +{ + LIST_ENTRY *Link; + LIST_ENTRY *Head; + IEVENT *Event; + + CoreAcquireEventLock (); + + Head = &gEventSignalQueue; + for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { + Event = CR (Link, IEVENT, SignalLink, EVENT_SIGNATURE); + if (CompareGuid (&Event->EventGroup, EventGroup)) { + CoreNotifyEvent (Event); + } + } + + CoreReleaseEventLock (); +} + + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) + +static +VOID +EFIAPI +EventNofitySignalAllNullEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + // + // This null event is a size efficent way to enusre that + // EFI_EVENT_NOTIFY_SIGNAL_ALL is error checked correctly. + // EFI_EVENT_NOTIFY_SIGNAL_ALL is now mapped into + // CreateEventEx() and this function is used to make the + // old error checking in CreateEvent() for Tiano extensions + // function. + // + return; +} + +#endif + + + + +EFI_STATUS +EFIAPI +CoreCreateEvent ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL + IN VOID *NotifyContext, OPTIONAL + OUT EFI_EVENT *Event + ) +/*++ + +Routine Description: + Creates a general-purpose event structure + +Arguments: + Type - The type of event to create and its mode and attributes + NotifyTpl - The task priority level of event notifications + NotifyFunction - Pointer to the events notification function + NotifyContext - Pointer to the notification functions context; corresponds to + parameter "Context" in the notification function + Event - Pointer to the newly created event if the call succeeds; undefined otherwise + +Returns: + EFI_SUCCESS - The event structure was created + EFI_INVALID_PARAMETER - One of the parameters has an invalid value + EFI_OUT_OF_RESOURCES - The event could not be allocated + +--*/ +{ + EFI_GUID *GuidPtr; + EFI_EVENT_NOTIFY Function; + + GuidPtr = NULL; + Function = NotifyFunction; + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) + // + // Clear EFI_EVENT_NOFITY_SIGNAL_ALL (Tiano extension) as all events in the + // EventGroup now have this property. So we need to filter it out. + // + if (Type & EFI_EVENT_NOTIFY_SIGNAL_ALL) { + Type &= ~EFI_EVENT_NOTIFY_SIGNAL_ALL; + Function = EventNofitySignalAllNullEvent; + } + + // + // Map the Tiano extensions Events to CreateEventEx form + // + if (Type == EFI_EVENT_SIGNAL_READY_TO_BOOT) { + GuidPtr = &gEfiEventReadToBootGuid; + } else if (Type == EFI_EVENT_SIGNAL_LEGACY_BOOT) { + GuidPtr = &gEfiEventLegacyBootGuid + } +#endif + + // + // Convert EFI 1.10 Events to thier UEFI 2.0 CreateEventEx mapping + // + if (Type == EVENT_SIGNAL_EXIT_BOOT_SERVICES) { + GuidPtr = &gEfiEventExitBootServicesGuid; + } else if (Type == EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) { + GuidPtr = &gEfiEventVirtualAddressChangeGuid; + } + + return CoreCreateEventEx (Type, NotifyTpl, Function, NotifyContext, GuidPtr, Event); +} + + +EFI_STATUS +EFIAPI +CoreCreateEventEx ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, OPTIONAL + IN CONST VOID *NotifyContext, OPTIONAL + IN CONST EFI_GUID *EventGroup, OPTIONAL + OUT EFI_EVENT *Event + ) +/*++ + +Routine Description: + Creates a general-purpose event structure + +Arguments: + Type - The type of event to create and its mode and attributes + NotifyTpl - The task priority level of event notifications + NotifyFunction - Pointer to the events notification function + NotifyContext - Pointer to the notification functions context; corresponds to + parameter "Context" in the notification function + EventGrout - GUID for EventGroup if NULL act the same as gBS->CreateEvent(). + Event - Pointer to the newly created event if the call succeeds; undefined otherwise + +Returns: + EFI_SUCCESS - The event structure was created + EFI_INVALID_PARAMETER - One of the parameters has an invalid value + EFI_OUT_OF_RESOURCES - The event could not be allocated + +--*/ +{ + EFI_STATUS Status; + IEVENT *IEvent; + INTN Index; + + + if ((Event == NULL) || (NotifyTpl == EFI_TPL_APPLICATION)) { + return EFI_INVALID_PARAMETER; + } + + // + // Check to make sure no reserved flags are set + // + Status = EFI_INVALID_PARAMETER; + for (Index = 0; Index < (sizeof (mEventTable) / sizeof (UINT32)); Index++) { + if (Type == mEventTable[Index]) { + Status = EFI_SUCCESS; + break; + } + } + if(EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + // + // If it's a notify type of event, check its parameters + // + if ((Type & (EFI_EVENT_NOTIFY_WAIT | EFI_EVENT_NOTIFY_SIGNAL))) { + // + // Check for an invalid NotifyFunction or NotifyTpl + // + if ((NotifyFunction == NULL) || + (NotifyTpl < EFI_TPL_APPLICATION) || + (NotifyTpl >= EFI_TPL_HIGH_LEVEL)) { + return EFI_INVALID_PARAMETER; + } + + } else { + // + // No notification needed, zero ignored values + // + NotifyTpl = 0; + NotifyFunction = NULL; + NotifyContext = NULL; + } + + // + // Allcoate and initialize a new event structure. + // + Status = CoreAllocatePool ( + (Type & EFI_EVENT_RUNTIME) ? EfiRuntimeServicesData: EfiBootServicesData, + sizeof (IEVENT), + (VOID **)&IEvent + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (IEvent, sizeof (IEVENT), 0); + + IEvent->Signature = EVENT_SIGNATURE; + IEvent->Type = Type; + + IEvent->NotifyTpl = NotifyTpl; + IEvent->NotifyFunction = NotifyFunction; + IEvent->NotifyContext = (VOID *)NotifyContext; + if (EventGroup != NULL) { + CopyGuid (&IEvent->EventGroup, EventGroup); + IEvent->ExFlag = TRUE; + } + + *Event = IEvent; + + if (Type & EFI_EVENT_RUNTIME) { + // + // Keep a list of all RT events so we can tell the RT AP. + // + InsertTailList (&mRuntimeEventList, &IEvent->RuntimeLink); + } + + CoreAcquireEventLock (); + + if ((Type & EFI_EVENT_NOTIFY_SIGNAL) != 0x00000000) { + // + // The Event's NotifyFunction must be queued whenever the event is signaled + // + InsertHeadList (&gEventSignalQueue, &IEvent->SignalLink); + } + + CoreReleaseEventLock (); + + // + // Done + // + return EFI_SUCCESS; +} + + + +EFI_STATUS +EFIAPI +CoreSignalEvent ( + IN EFI_EVENT UserEvent + ) +/*++ + +Routine Description: + + Signals the event. Queues the event to be notified if needed + +Arguments: + + UserEvent - The event to signal + +Returns: + + EFI_INVALID_PARAMETER - Parameters are not valid. + + EFI_SUCCESS - The event was signaled. + +--*/ +{ + IEVENT *Event; + + Event = UserEvent; + + if (Event == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Signature != EVENT_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireEventLock (); + + // + // If the event is not already signalled, do so + // + + if (Event->SignalCount == 0x00000000) { + Event->SignalCount++; + + // + // If signalling type is a notify function, queue it + // + if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) { + if (Event->ExFlag) { + // + // The CreateEventEx() style requires all members of the Event Group + // to be signaled. + // + CoreReleaseEventLock (); + CoreNotifySignalList (&Event->EventGroup); + CoreAcquireEventLock (); + } else { + CoreNotifyEvent (Event); + } + } + } + + CoreReleaseEventLock (); + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +CoreCheckEvent ( + IN EFI_EVENT UserEvent + ) +/*++ + +Routine Description: + + Check the status of an event + +Arguments: + + UserEvent - The event to check + +Returns: + + EFI_SUCCESS - The event is in the signaled state + EFI_NOT_READY - The event is not in the signaled state + EFI_INVALID_PARAMETER - Event is of type EVT_NOTIFY_SIGNAL + +--*/ + +{ + IEVENT *Event; + EFI_STATUS Status; + + Event = UserEvent; + + if (Event == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Signature != EVENT_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Type & EFI_EVENT_NOTIFY_SIGNAL) { + return EFI_INVALID_PARAMETER; + } + + Status = EFI_NOT_READY; + + if (!Event->SignalCount && (Event->Type & EFI_EVENT_NOTIFY_WAIT)) { + + // + // Queue the wait notify function + // + + CoreAcquireEventLock (); + if (!Event->SignalCount) { + CoreNotifyEvent (Event); + } + CoreReleaseEventLock (); + } + + // + // If the even looks signalled, get the lock and clear it + // + + if (Event->SignalCount) { + CoreAcquireEventLock (); + + if (Event->SignalCount) { + Event->SignalCount = 0; + Status = EFI_SUCCESS; + } + + CoreReleaseEventLock (); + } + + return Status; +} + + + +EFI_STATUS +EFIAPI +CoreWaitForEvent ( + IN UINTN NumberOfEvents, + IN EFI_EVENT *UserEvents, + OUT UINTN *UserIndex + ) +/*++ + +Routine Description: + + Stops execution until an event is signaled. + +Arguments: + + NumberOfEvents - The number of events in the UserEvents array + UserEvents - An array of EFI_EVENT + UserIndex - Pointer to the index of the event which satisfied the wait condition + +Returns: + + EFI_SUCCESS - The event indicated by Index was signaled. + EFI_INVALID_PARAMETER - The event indicated by Index has a notification function or + Event was not a valid type + EFI_UNSUPPORTED - The current TPL is not TPL_APPLICATION + +--*/ + +{ + EFI_STATUS Status; + UINTN Index; + + // + // Can only WaitForEvent at TPL_APPLICATION + // + if (gEfiCurrentTpl != EFI_TPL_APPLICATION) { + return EFI_UNSUPPORTED; + } + + for(;;) { + + for(Index = 0; Index < NumberOfEvents; Index++) { + + Status = CoreCheckEvent (UserEvents[Index]); + + // + // provide index of event that caused problem + // + if (Status != EFI_NOT_READY) { + *UserIndex = Index; + return Status; + } + } + + // + // This was the location of the Idle loop callback in EFI 1.x reference + // code. We don't have that concept in this base at this point. + // + } +} + + +EFI_STATUS +EFIAPI +CoreCloseEvent ( + IN EFI_EVENT UserEvent + ) +/*++ + +Routine Description: + + Closes an event and frees the event structure. + +Arguments: + + UserEvent - Event to close + +Returns: + + EFI_INVALID_PARAMETER - Parameters are not valid. + + EFI_SUCCESS - The event has been closed + +--*/ + +{ + EFI_STATUS Status; + IEVENT *Event; + + Event = UserEvent; + + if (Event == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Signature != EVENT_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + // + // If it's a timer event, make sure it's not pending + // + if (Event->Type & EFI_EVENT_TIMER) { + CoreSetTimer (Event, TimerCancel, 0); + } + + CoreAcquireEventLock (); + + // + // If the event is queued somewhere, remove it + // + + if (Event->RuntimeLink.ForwardLink != NULL) { + RemoveEntryList (&Event->RuntimeLink); + } + + if (Event->NotifyLink.ForwardLink != NULL) { + RemoveEntryList (&Event->NotifyLink); + } + + if (Event->SignalLink.ForwardLink != NULL) { + RemoveEntryList (&Event->SignalLink); + } + + CoreReleaseEventLock (); + + // + // If the event is registered on a protocol notify, then remove it from the protocol database + // + CoreUnregisterProtocolNotify (Event); + + Status = CoreFreePool (Event); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/EdkModulePkg/Core/Dxe/Event/execdata.c b/EdkModulePkg/Core/Dxe/Event/execdata.c new file mode 100644 index 0000000000..e7a11c2400 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Event/execdata.c @@ -0,0 +1,55 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + execdata.c + +Abstract: + + + + +Revision History + +--*/ + +#include + + +// +// gTpl - Task priority level +// +EFI_TPL gEfiCurrentTpl = EFI_TPL_APPLICATION; + + +// +// gEventQueueLock - Protects the event queus +// +EFI_LOCK gEventQueueLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL); + +// +// gEventQueue - A list of event's to notify for each priority level +// gEventPending - A bitmask of the EventQueues that are pending +// +LIST_ENTRY gEventQueue[EFI_TPL_HIGH_LEVEL + 1]; +UINTN gEventPending = 0; + + +// +// gEventSignalQueue - A list of events to signal based on EventGroup type +// +LIST_ENTRY gEventSignalQueue = INITIALIZE_LIST_HEAD_VARIABLE (gEventSignalQueue); + +// +// LIST of runtime events that need to be fired by RT AP. +// +LIST_ENTRY mRuntimeEventList = INITIALIZE_LIST_HEAD_VARIABLE (mRuntimeEventList); diff --git a/EdkModulePkg/Core/Dxe/Event/timer.c b/EdkModulePkg/Core/Dxe/Event/timer.c new file mode 100644 index 0000000000..8d7932f837 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Event/timer.c @@ -0,0 +1,386 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + timer.c + +Abstract: + + EFI Event support + +Revision History + +--*/ + + +#include + +// +// Internal prototypes +// +STATIC +UINT64 +CoreCurrentSystemTime ( + VOID + ); + +VOID +EFIAPI +CoreCheckTimers ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +STATIC +VOID +CoreInsertEventTimer ( + IN IEVENT *Event + ); + +// +// Internal data +// + +static LIST_ENTRY mEfiTimerList = INITIALIZE_LIST_HEAD_VARIABLE (mEfiTimerList); +static EFI_LOCK mEfiTimerLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL - 1); +static EFI_EVENT mEfiCheckTimerEvent; + +static EFI_LOCK mEfiSystemTimeLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_HIGH_LEVEL); +static UINT64 mEfiSystemTime = 0; + +// +// Timer functions +// + +VOID +CoreInitializeTimer ( + VOID + ) +/*++ + +Routine Description: + + Initializes timer support + +Arguments: + + None + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + + Status = CoreCreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_HIGH_LEVEL - 1, + CoreCheckTimers, + NULL, + &mEfiCheckTimerEvent + ); + ASSERT_EFI_ERROR (Status); +} + +STATIC +UINT64 +CoreCurrentSystemTime ( + VOID + ) +/*++ + +Routine Description: + + Returns the current system time + +Arguments: + + None + +Returns: + + Returns the current system time + +--*/ +{ + UINT64 SystemTime; + + CoreAcquireLock (&mEfiSystemTimeLock); + SystemTime = mEfiSystemTime; + CoreReleaseLock (&mEfiSystemTimeLock); + return SystemTime; +} + +VOID +EFIAPI +CoreTimerTick ( + IN UINT64 Duration + ) +/*++ + +Routine Description: + + Called by the platform code to process a tick. + +Arguments: + + Duration - The number of 100ns elasped since the last call to TimerTick + +Returns: + + None + +--*/ +{ + IEVENT *Event; + + // + // Check runtiem flag in case there are ticks while exiting boot services + // + + CoreAcquireLock (&mEfiSystemTimeLock); + + // + // Update the system time + // + + mEfiSystemTime += Duration; + + // + // If the head of the list is expired, fire the timer event + // to process it + // + + if (!IsListEmpty (&mEfiTimerList)) { + Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE); + + if (Event->u.Timer.TriggerTime <= mEfiSystemTime) { + CoreSignalEvent (mEfiCheckTimerEvent); + } + } + + CoreReleaseLock (&mEfiSystemTimeLock); +} + +VOID +EFIAPI +CoreCheckTimers ( + IN EFI_EVENT CheckEvent, + IN VOID *Context + ) +/*++ + +Routine Description: + + Checks the sorted timer list against the current system time. + Signals any expired event timer. + +Arguments: + + CheckEvent - Not used + + Context - Not used + +Returns: + + None + +--*/ +{ + UINT64 SystemTime; + IEVENT *Event; + + // + // Check the timer database for expired timers + // + + CoreAcquireLock (&mEfiTimerLock); + SystemTime = CoreCurrentSystemTime (); + + while (!IsListEmpty (&mEfiTimerList)) { + Event = CR (mEfiTimerList.ForwardLink, IEVENT, u.Timer.Link, EVENT_SIGNATURE); + + // + // If this timer is not expired, then we're done + // + + if (Event->u.Timer.TriggerTime > SystemTime) { + break; + } + + // + // Remove this timer from the timer queue + // + + RemoveEntryList (&Event->u.Timer.Link); + Event->u.Timer.Link.ForwardLink = NULL; + + // + // Signal it + // + CoreSignalEvent (Event); + + // + // If this is a periodic timer, set it + // + if (Event->u.Timer.Period) { + + // + // Compute the timers new trigger time + // + + Event->u.Timer.TriggerTime = Event->u.Timer.TriggerTime + Event->u.Timer.Period; + + // + // If that's before now, then reset the timer to start from now + // + if (Event->u.Timer.TriggerTime <= SystemTime) { + Event->u.Timer.TriggerTime = SystemTime; + CoreSignalEvent (mEfiCheckTimerEvent); + } + + // + // Add the timer + // + + CoreInsertEventTimer (Event); + } + } + + CoreReleaseLock (&mEfiTimerLock); +} + +STATIC +VOID +CoreInsertEventTimer ( + IN IEVENT *Event + ) +/*++ + +Routine Description: + + Inserts the timer event + +Arguments: + + Event - Points to the internal structure of timer event to be installed + +Returns: + + None + +--*/ +{ + UINT64 TriggerTime; + LIST_ENTRY *Link; + IEVENT *Event2; + + ASSERT_LOCKED (&mEfiTimerLock); + + // + // Get the timer's trigger time + // + + TriggerTime = Event->u.Timer.TriggerTime; + + // + // Insert the timer into the timer database in assending sorted order + // + + for (Link = mEfiTimerList.ForwardLink; Link != &mEfiTimerList; Link = Link->ForwardLink) { + Event2 = CR (Link, IEVENT, u.Timer.Link, EVENT_SIGNATURE); + + if (Event2->u.Timer.TriggerTime > TriggerTime) { + break; + } + } + + InsertTailList (Link, &Event->u.Timer.Link); +} + + + +EFI_STATUS +EFIAPI +CoreSetTimer ( + IN EFI_EVENT UserEvent, + IN EFI_TIMER_DELAY Type, + IN UINT64 TriggerTime + ) +/*++ + +Routine Description: + + Sets the type of timer and the trigger time for a timer event. + +Arguments: + + UserEvent - The timer event that is to be signaled at the specified time + Type - The type of time that is specified in TriggerTime + TriggerTime - The number of 100ns units until the timer expires + +Returns: + + EFI_SUCCESS - The event has been set to be signaled at the requested time + EFI_INVALID_PARAMETER - Event or Type is not valid + +--*/ +{ + IEVENT *Event; + + Event = UserEvent; + + if (Event == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Signature != EVENT_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + if (Type < 0 || Type > TimerRelative || !(Event->Type & EFI_EVENT_TIMER)) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireLock (&mEfiTimerLock); + + // + // If the timer is queued to the timer database, remove it + // + + if (Event->u.Timer.Link.ForwardLink != NULL) { + RemoveEntryList (&Event->u.Timer.Link); + Event->u.Timer.Link.ForwardLink = NULL; + } + + Event->u.Timer.TriggerTime = 0; + Event->u.Timer.Period = 0; + + if (Type != TimerCancel) { + + if (Type == TimerPeriodic) { + Event->u.Timer.Period = TriggerTime; + } + + Event->u.Timer.TriggerTime = CoreCurrentSystemTime () + TriggerTime; + CoreInsertEventTimer (Event); + + if (TriggerTime == 0) { + CoreSignalEvent (mEfiCheckTimerEvent); + } + } + + CoreReleaseLock (&mEfiTimerLock); + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/Dxe/Event/tpl.c b/EdkModulePkg/Core/Dxe/Event/tpl.c new file mode 100644 index 0000000000..ae851638af --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Event/tpl.c @@ -0,0 +1,198 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + tpl.c + +Abstract: + + Task priority function + +--*/ + +#include + +STATIC +VOID +CoreSetInterruptState ( + IN BOOLEAN Enable + ) +/*++ + +Routine Description: + + Set Interrupt State + +Arguments: + + Enable - The state of enable or disable interrupt + +Returns: + + None + +--*/ + +{ + if (gCpu != NULL) { + if (Enable) { + gCpu->EnableInterrupt(gCpu); + } else { + gCpu->DisableInterrupt(gCpu); + } + } +} + +// +// Return the highest set bit +// +UINTN +CoreHighestSetBit ( + IN UINTN Number + ) +/*++ + +Routine Description: + + Return the highest set bit + +Arguments: + + Number - The value to check + +Returns: + + Bit position of the highest set bit + +--*/ +{ + UINTN msb; + + msb = 31; + while ((msb > 0) && ((Number & (UINTN)(1 << msb)) == 0)) { + msb--; + } + + return msb; +} + + + +EFI_TPL +EFIAPI +CoreRaiseTpl ( + IN EFI_TPL NewTpl + ) +/*++ + +Routine Description: + + Raise the task priority level to the new level. + High level is implemented by disabling processor interrupts. + +Arguments: + + NewTpl - New task priority level + +Returns: + + The previous task priority level + +--*/ +{ + EFI_TPL OldTpl; + + OldTpl = gEfiCurrentTpl; + ASSERT (OldTpl <= NewTpl); + ASSERT (VALID_TPL (NewTpl)); + + // + // If raising to high level, disable interrupts + // + if (NewTpl >= EFI_TPL_HIGH_LEVEL && OldTpl < EFI_TPL_HIGH_LEVEL) { + CoreSetInterruptState (FALSE); + } + + // + // Set the new value + // + gEfiCurrentTpl = NewTpl; + + return OldTpl; +} + + + +VOID +EFIAPI +CoreRestoreTpl ( + IN EFI_TPL NewTpl + ) +/*++ + +Routine Description: + + Lowers the task priority to the previous value. If the new + priority unmasks events at a higher priority, they are dispatched. + +Arguments: + + NewTpl - New, lower, task priority + +Returns: + + None + +--*/ +{ + EFI_TPL OldTpl; + + OldTpl = gEfiCurrentTpl; + ASSERT (NewTpl <= OldTpl); + ASSERT (VALID_TPL (NewTpl)); + + // + // If lowering below HIGH_LEVEL, make sure + // interrupts are enabled + // + + if (OldTpl >= EFI_TPL_HIGH_LEVEL && NewTpl < EFI_TPL_HIGH_LEVEL) { + gEfiCurrentTpl = EFI_TPL_HIGH_LEVEL; + } + + // + // Dispatch any pending events + // + + while ((-2 << NewTpl) & gEventPending) { + gEfiCurrentTpl = CoreHighestSetBit (gEventPending); + if (gEfiCurrentTpl < EFI_TPL_HIGH_LEVEL) { + CoreSetInterruptState (TRUE); + } + CoreDispatchEventNotifies (gEfiCurrentTpl); + } + + // + // Set the new value + // + + gEfiCurrentTpl = NewTpl; + + // + // If lowering below HIGH_LEVEL, make sure + // interrupts are enabled + // + if (gEfiCurrentTpl < EFI_TPL_HIGH_LEVEL) { + CoreSetInterruptState (TRUE); + } + +} diff --git a/EdkModulePkg/Core/Dxe/FwVol/Ffs.c b/EdkModulePkg/Core/Dxe/FwVol/Ffs.c new file mode 100644 index 0000000000..6f7d353e05 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/FwVol/Ffs.c @@ -0,0 +1,266 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Ffs.c + +Abstract: + + FFS file access utilities. + +--*/ + + +#include + +#define PHYSICAL_ADDRESS_TO_POINTER(Address) ((VOID *)((UINTN)(Address))) + + +EFI_FFS_FILE_STATE +GetFileState ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Get the FFS file state by checking the highest bit set in the header's state field + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file header + +Returns: + FFS File state + +--*/ +{ + EFI_FFS_FILE_STATE FileState; + UINT8 HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity != 0) { + FileState = (EFI_FFS_FILE_STATE)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && ((HighestBit & FileState) == 0)) { + HighestBit >>= 1; + } + + return (EFI_FFS_FILE_STATE)HighestBit; +} + + +BOOLEAN +IsBufferErased ( + IN UINT8 ErasePolarity, + IN VOID *InBuffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + Check if a block of buffer is erased + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + InBuffer - The buffer to be checked + BufferSize - Size of the buffer in bytes + +Returns: + TRUE - The block of buffer is erased + FALSE - The block of buffer is not erased + +--*/ +{ + UINTN Count; + UINT8 EraseByte; + UINT8 *Buffer; + + if(ErasePolarity == 1) { + EraseByte = 0xFF; + } else { + EraseByte = 0; + } + + Buffer = InBuffer; + for (Count = 0; Count < BufferSize; Count++) { + if (Buffer[Count] != EraseByte) { + return FALSE; + } + } + + return TRUE; +} + + +BOOLEAN +VerifyFvHeaderChecksum ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +/*++ + +Routine Description: + Verify checksum of the firmware volume header + +Arguments: + FvHeader - Points to the firmware volume header to be checked + +Returns: + TRUE - Checksum verification passed + FALSE - Checksum verification failed + +--*/ +{ + UINT32 Index; + UINT32 HeaderLength; + UINT16 Checksum; + UINT16 *ptr; + + HeaderLength = FvHeader->HeaderLength; + ptr = (UINT16 *)FvHeader; + Checksum = 0; + + for (Index = 0; Index < HeaderLength / sizeof (UINT16); Index++) { + Checksum = (UINT16)(Checksum + ptr[Index]); + } + + if (Checksum == 0) { + return TRUE; + } else { + return FALSE; + } +} + + +BOOLEAN +VerifyHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Verify checksum of the FFS file header + +Arguments: + FfsHeader - Points to the FFS file header to be checked + +Returns: + TRUE - Checksum verification passed + FALSE - Checksum verification failed + +--*/ +{ + UINT32 Index; + UINT8 *ptr; + UINT8 HeaderChecksum; + + ptr = (UINT8 *)FfsHeader; + HeaderChecksum = 0; + for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) { + HeaderChecksum = (UINT8)(HeaderChecksum + ptr[Index]); + } + + HeaderChecksum = HeaderChecksum - FfsHeader->State - FfsHeader->IntegrityCheck.Checksum.File; + + if (HeaderChecksum == 0) { + return TRUE; + } else { + return FALSE; + } +} + + +BOOLEAN +IsValidFfsHeader ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_FFS_FILE_STATE *FileState + ) +/*++ + +Routine Description: + Check if it's a valid FFS file header + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file header to be checked + FileState - FFS file state to be returned + +Returns: + TRUE - Valid FFS file header + FALSE - Invalid FFS file header + +--*/ +{ + *FileState = GetFileState (ErasePolarity, FfsHeader); + + switch (*FileState) { + case EFI_FILE_HEADER_VALID: + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + case EFI_FILE_DELETED: + // + // Here we need to verify header checksum + // + return VerifyHeaderChecksum (FfsHeader); + + case EFI_FILE_HEADER_CONSTRUCTION: + case EFI_FILE_HEADER_INVALID: + default: + return FALSE; + } +} + + +BOOLEAN +IsValidFfsFile ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Check if it's a valid FFS file. + Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first. + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file to be checked + +Returns: + TRUE - Valid FFS file + FALSE - Invalid FFS file + +--*/ +{ + EFI_FFS_FILE_STATE FileState; + + FileState = GetFileState (ErasePolarity, FfsHeader); + switch (FileState) { + + case EFI_FILE_DELETED: + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + // + // Some other vliadation like file content checksum might be done here. + // For performance issue, Tiano only do FileState check. + // + return TRUE; + + default: + return FALSE; + } +} + diff --git a/EdkModulePkg/Core/Dxe/FwVol/FwVol.c b/EdkModulePkg/Core/Dxe/FwVol/FwVol.c new file mode 100644 index 0000000000..d8137d79c6 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/FwVol/FwVol.c @@ -0,0 +1,553 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FwVol.c + +Abstract: + + Firmware File System driver that produce Firmware Volume protocol. + Layers on top of Firmware Block protocol to produce a file abstraction + of FV based files. + +--*/ + +#include + +#define KEYSIZE sizeof (UINTN) + +// +// Protocol notify related globals +// +VOID *gEfiFwVolBlockNotifyReg; +EFI_EVENT gEfiFwVolBlockEvent; + +FV_DEVICE mFvDevice = { + FV_DEVICE_SIGNATURE, + NULL, + NULL, + { + FvGetVolumeAttributes, + FvSetVolumeAttributes, + FvReadFile, + FvReadFileSection, + FvWriteFile, + FvGetNextFile, + KEYSIZE + }, + NULL, + NULL, + NULL, + NULL, + { NULL, NULL }, + 0 +}; + + +// +// FFS helper functions +// + +EFI_STATUS +GetFwVolHeader ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, + OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +/*++ + +Routine Description: + given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and + copy the volume header into it. + +Arguments: + Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume + header + FwVolHeader - Pointer to pointer to allocated buffer in which the volume + header is returned. + +Returns: + EFI_OUT_OF_RESOURCES - No enough buffer could be allocated. + EFI_SUCCESS - Successfully read volume header to the allocated buffer. + +--*/ + +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER TempFvh; + UINTN FvhLength; + UINT8 *Buffer; + + + // + //Determine the real length of FV header + // + FvhLength = sizeof (EFI_FIRMWARE_VOLUME_HEADER); + Status = Fvb->Read (Fvb, 0, 0, &FvhLength, (UINT8 *)&TempFvh); + + // + // Allocate a buffer for the caller + // + *FwVolHeader = CoreAllocateBootServicesPool (TempFvh.HeaderLength); + if (*FwVolHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Copy the standard header into the buffer + // + CopyMem (*FwVolHeader, &TempFvh, sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + + // + // Read the rest of the header + // + FvhLength = TempFvh.HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER); + Buffer = (UINT8 *)*FwVolHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER); + Status = Fvb->Read (Fvb, 0, sizeof (EFI_FIRMWARE_VOLUME_HEADER), &FvhLength, Buffer); + if (EFI_ERROR (Status)) { + // + // Read failed so free buffer + // + CoreFreePool (*FwVolHeader); + } + + return Status; +} + + +STATIC +VOID +FreeFvDeviceResource ( + IN FV_DEVICE *FvDevice + ) +/*++ + +Routine Description: + Free FvDevice resource when error happens + +Arguments: + FvDevice - pointer to the FvDevice to be freed. + +Returns: + None. + +--*/ +{ + FFS_FILE_LIST_ENTRY *FfsFileEntry; + LIST_ENTRY *NextEntry; + + // + // Free File List Entry + // + FfsFileEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->FfsFileListHeader.ForwardLink; + while (&FfsFileEntry->Link != &FvDevice->FfsFileListHeader) { + NextEntry = (&FfsFileEntry->Link)->ForwardLink; + + if (FfsFileEntry->StreamHandle != 0) { + // + // Close stream and free resources from SEP + // + FfsFileEntry->Sep->CloseSectionStream (FfsFileEntry->Sep, FfsFileEntry->StreamHandle); + } + + CoreFreePool (FfsFileEntry); + + FfsFileEntry = (FFS_FILE_LIST_ENTRY *)NextEntry; + } + + + // + // Free the cache + // + CoreFreePool (FvDevice->CachedFv); + + // + // Free Volume Header + // + CoreFreePool (FvDevice->FwVolHeader); + + return; +} + + +EFI_STATUS +FvCheck ( + IN OUT FV_DEVICE *FvDevice + ) +/*++ + +Routine Description: + Check if a FV is consistent and allocate cache + +Arguments: + FvDevice - pointer to the FvDevice to be checked. + +Returns: + EFI_OUT_OF_RESOURCES - No enough buffer could be allocated. + EFI_SUCCESS - FV is consistent and cache is allocated. + EFI_VOLUME_CORRUPTED - File system is corrupted. + +--*/ +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FVB_ATTRIBUTES FvbAttributes; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + EFI_FFS_FILE_HEADER *FfsHeader; + UINT8 *CacheLocation; + UINTN LbaOffset; + UINTN Index; + EFI_LBA LbaIndex; + UINTN Size; + UINTN FileLength; + EFI_FFS_FILE_STATE FileState; + UINT8 *TopFvAddress; + UINTN TestLength; + + + Fvb = FvDevice->Fvb; + FwVolHeader = FvDevice->FwVolHeader; + + Status = Fvb->GetVolumeAttributes (Fvb, &FvbAttributes); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Size is the size of the FV minus the head. We have already allocated + // the header to check to make sure the volume is valid + // + Size = (UINTN)(FwVolHeader->FvLength - FwVolHeader->HeaderLength); + FvDevice->CachedFv = CoreAllocateZeroBootServicesPool (Size); + if (FvDevice->CachedFv == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Remember a pointer to the end fo the CachedFv + // + FvDevice->EndOfCachedFv = FvDevice->CachedFv + Size; + + // + // Copy FV minus header into memory using the block map we have all ready + // read into memory. + // + BlockMap = FwVolHeader->FvBlockMap; + CacheLocation = FvDevice->CachedFv; + LbaIndex = 0; + LbaOffset = FwVolHeader->HeaderLength; + while ((BlockMap->NumBlocks != 0) || (BlockMap->BlockLength != 0)) { + + for (Index = 0; Index < BlockMap->NumBlocks; Index ++) { + + Size = BlockMap->BlockLength; + if (Index == 0) { + // + // Cache does not include FV Header + // + Size -= LbaOffset; + } + Status = Fvb->Read (Fvb, + LbaIndex, + LbaOffset, + &Size, + CacheLocation + ); + // + // Not check EFI_BAD_BUFFER_SIZE, for Size = BlockMap->BlockLength + // + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // After we skip Fv Header always read from start of block + // + LbaOffset = 0; + + LbaIndex++; + CacheLocation += Size; + } + BlockMap++; + } + + // + // Scan to check the free space & File list + // + if (FvbAttributes & EFI_FVB_ERASE_POLARITY) { + FvDevice->ErasePolarity = 1; + } else { + FvDevice->ErasePolarity = 0; + } + + + // + // go through the whole FV cache, check the consistence of the FV. + // Make a linked list off all the Ffs file headers + // + Status = EFI_SUCCESS; + InitializeListHead (&FvDevice->FfsFileListHeader); + + // + // Build FFS list + // + FfsHeader = (EFI_FFS_FILE_HEADER *)FvDevice->CachedFv; + TopFvAddress = FvDevice->EndOfCachedFv; + while ((UINT8 *)FfsHeader < TopFvAddress) { + + TestLength = TopFvAddress - ((UINT8 *)FfsHeader); + if (TestLength > sizeof (EFI_FFS_FILE_HEADER)) { + TestLength = sizeof (EFI_FFS_FILE_HEADER); + } + + if (IsBufferErased (FvDevice->ErasePolarity, FfsHeader, TestLength)) { + // + // We have found the free space so we are done! + // + goto Done; + } + + if (!IsValidFfsHeader (FvDevice->ErasePolarity, FfsHeader, &FileState)) { + if ((FileState == EFI_FILE_HEADER_INVALID) || + (FileState == EFI_FILE_HEADER_CONSTRUCTION)) { + FfsHeader++; + + continue; + + } else { + // + // File system is corrputed + // + Status = EFI_VOLUME_CORRUPTED; + goto Done; + } + } + + if (!IsValidFfsFile (FvDevice->ErasePolarity, FfsHeader)) { + // + // File system is corrupted + // + Status = EFI_VOLUME_CORRUPTED; + goto Done; + } + + // + // Size[3] is a three byte array, read 4 bytes and throw one away + // + FileLength = *(UINT32 *)&FfsHeader->Size[0] & 0x00FFFFFF; + + FileState = GetFileState (FvDevice->ErasePolarity, FfsHeader); + + // + // check for non-deleted file + // + if (FileState != EFI_FILE_DELETED) { + // + // Create a FFS list entry for each non-deleted file + // + FfsFileEntry = CoreAllocateZeroBootServicesPool (sizeof (FFS_FILE_LIST_ENTRY)); + if (FfsFileEntry == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + FfsFileEntry->FfsHeader = FfsHeader; + InsertTailList (&FvDevice->FfsFileListHeader, &FfsFileEntry->Link); + } + + FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINT8 *)FfsHeader) + FileLength); + + // + // Adjust pointer to the next 8-byte aligned boundry. + // + FfsHeader = (EFI_FFS_FILE_HEADER *)(((UINTN)FfsHeader + 7) & ~0x07); + + } + +Done: + if (EFI_ERROR (Status)) { + FreeFvDeviceResource (FvDevice); + } + + return Status; +} + + +STATIC +VOID +EFIAPI +NotifyFwVolBlock ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + This notification function is invoked when an instance of the + EFI_FW_VOLUME_BLOCK_PROTOCOL is produced. It layers an instance of the + EFI_FIRMWARE_VOLUME_PROTOCOL on the same handle. This is the function where + the actual initialization of the EFI_FIRMWARE_VOLUME_PROTOCOL is done. + +Arguments: + Event - The event that occured + Context - For EFI compatiblity. Not used. + +Returns: + + None. + +--*/ +{ + EFI_HANDLE Handle; + EFI_STATUS Status; + UINTN BufferSize; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + FV_DEVICE *FvDevice; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + // + // Examine all new handles + // + for (;;) { + // + // Get the next handle + // + BufferSize = sizeof (Handle); + Status = CoreLocateHandle ( + ByRegisterNotify, + NULL, + gEfiFwVolBlockNotifyReg, + &BufferSize, + &Handle + ); + + // + // If not found, we're done + // + if (EFI_NOT_FOUND == Status) { + break; + } + + if (EFI_ERROR (Status)) { + continue; + } + + // + // Get the FirmwareVolumeBlock protocol on that handle + // + Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb); + ASSERT_EFI_ERROR (Status); + + + // + // Make sure the Fv Header is O.K. + // + Status = GetFwVolHeader (Fvb, &FwVolHeader); + if (EFI_ERROR (Status)) { + return; + } + + if (!VerifyFvHeaderChecksum (FwVolHeader)) { + CoreFreePool (FwVolHeader); + continue; + } + + + // + // Check to see that the file system is indeed formatted in a way we can + // understand it... + // + if (!CompareGuid (&FwVolHeader->FileSystemGuid, &gEfiFirmwareFileSystemGuid)) { + continue; + } + + // + // Check if there is an FV protocol already installed in that handle + // + Status = CoreHandleProtocol (Handle, &gEfiFirmwareVolumeProtocolGuid, (VOID **)&Fv); + if (!EFI_ERROR (Status)) { + // + // Update Fv to use a new Fvb + // + FvDevice = _CR (Fv, FV_DEVICE, Fv); + if (FvDevice->Signature == FV_DEVICE_SIGNATURE) { + // + // Only write into our device structure if it's our device structure + // + FvDevice->Fvb = Fvb; + } + + } else { + // + // No FwVol protocol on the handle so create a new one + // + FvDevice = CoreAllocateCopyPool (sizeof (FV_DEVICE), &mFvDevice); + if (FvDevice == NULL) { + return; + } + + FvDevice->Fvb = Fvb; + FvDevice->Handle = Handle; + FvDevice->FwVolHeader = FwVolHeader; + FvDevice->Fv.ParentHandle = Fvb->ParentHandle; + + // + // Install an New FV protocol on the existing handle + // + Status = CoreInstallProtocolInterface ( + &Handle, + &gEfiFirmwareVolumeProtocolGuid, + EFI_NATIVE_INTERFACE, + &FvDevice->Fv + ); + ASSERT_EFI_ERROR (Status); + } + } + + return; +} + + +EFI_STATUS +EFIAPI +FwVolDriverInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This routine is the driver initialization entry point. It initializes the + libraries, and registers two notification functions. These notification + functions are responsible for building the FV stack dynamically. + +Arguments: + ImageHandle - The image handle. + SystemTable - The system table. + +Returns: + EFI_SUCCESS - Function successfully returned. + +--*/ +{ + gEfiFwVolBlockEvent = CoreCreateProtocolNotifyEvent ( + &gEfiFirmwareVolumeBlockProtocolGuid, + EFI_TPL_CALLBACK, + NotifyFwVolBlock, + NULL, + &gEfiFwVolBlockNotifyReg, + TRUE + ); + return EFI_SUCCESS; +} + diff --git a/EdkModulePkg/Core/Dxe/FwVol/FwVolAttrib.c b/EdkModulePkg/Core/Dxe/FwVol/FwVolAttrib.c new file mode 100644 index 0000000000..8a44653282 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/FwVol/FwVolAttrib.c @@ -0,0 +1,99 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FwVolAttrib.c + +Abstract: + + Implements get/set firmware volume attributes + +--*/ + +#include + +EFI_STATUS +EFIAPI +FvGetVolumeAttributes ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + OUT EFI_FV_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + +Arguments: + This - Calling context + Attributes - output buffer which contains attributes + +Returns: + EFI_SUCCESS - Successfully got volume attributes + +--*/ +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FVB_ATTRIBUTES FvbAttributes; + + FvDevice = FV_DEVICE_FROM_THIS (This); + Fvb = FvDevice->Fvb; + + if (FvDevice->CachedFv == NULL) { + Status = FvCheck (FvDevice); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // First get the Firmware Volume Block Attributes + // + Status = Fvb->GetVolumeAttributes (Fvb, &FvbAttributes); + + // + // Mask out Fvb bits that are not defined in FV + // + FvbAttributes &= 0xfffff0ff; + + *Attributes = (EFI_FV_ATTRIBUTES)FvbAttributes; + + return Status; +} + + +EFI_STATUS +EFIAPI +FvSetVolumeAttributes ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN OUT EFI_FV_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Sets current attributes for volume + +Arguments: + This - Calling context + Attributes - At input, contains attributes to be set. At output contains + new value of FV + +Returns: + EFI_UNSUPPORTED - Could not be set. + +--*/ +{ + return EFI_UNSUPPORTED; +} + diff --git a/EdkModulePkg/Core/Dxe/FwVol/FwVolRead.c b/EdkModulePkg/Core/Dxe/FwVol/FwVolRead.c new file mode 100644 index 0000000000..ff2fcb8023 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/FwVol/FwVolRead.c @@ -0,0 +1,516 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FwVolRead.c + +Abstract: + + Implements read firmware file + +--*/ + +#include + +/*++ + +Required Alignment Alignment Value in FFS Alignment Value in +(bytes) Attributes Field Firmware Volume Interfaces +1 0 0 +2 0 1 +4 0 2 +8 0 3 +16 1 4 +128 2 7 +512 3 9 +1 KB 4 10 +4 KB 5 12 +32 KB 6 15 +64 KB 7 16 + +--*/ + +UINT8 mFvAttributes[] = {0, 4, 7, 9, 10, 12, 15, 16}; + + +STATIC +EFI_FV_FILE_ATTRIBUTES +FfsAttributes2FvFileAttributes ( + IN EFI_FFS_FILE_ATTRIBUTES FfsAttributes + ) +/*++ + + Routine Description: + Convert the FFS File Attributes to FV File Attributes + + Arguments: + FfsAttributes - The attributes of UINT8 type. + + Returns: + The attributes of EFI_FV_FILE_ATTRIBUTES + +--*/ +{ + FfsAttributes = (EFI_FFS_FILE_ATTRIBUTES)((FfsAttributes & FFS_ATTRIB_DATA_ALIGNMENT) >> 3); + ASSERT (FfsAttributes < 8); + + return (EFI_FV_FILE_ATTRIBUTES) mFvAttributes[FfsAttributes]; +} + + +EFI_STATUS +EFIAPI +FvGetNextFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN OUT VOID *Key, + IN OUT EFI_FV_FILETYPE *FileType, + OUT EFI_GUID *NameGuid, + OUT EFI_FV_FILE_ATTRIBUTES *Attributes, + OUT UINTN *Size + ) +/*++ + +Routine Description: + Given the input key, search for the next matching file in the volume. + +Arguments: + This - Indicates the calling context. + FileType - FileType is a pointer to a caller allocated + EFI_FV_FILETYPE. The GetNextFile() API can filter it's + search for files based on the value of *FileType input. + A *FileType input of 0 causes GetNextFile() to search for + files of all types. If a file is found, the file's type + is returned in *FileType. *FileType is not modified if + no file is found. + Key - Key is a pointer to a caller allocated buffer that + contains implementation specific data that is used to + track where to begin the search for the next file. + The size of the buffer must be at least This->KeySize + bytes long. To reinitialize the search and begin from + the beginning of the firmware volume, the entire buffer + must be cleared to zero. Other than clearing the buffer + to initiate a new search, the caller must not modify the + data in the buffer between calls to GetNextFile(). + NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID. + If a file is found, the file's name is returned in + *NameGuid. *NameGuid is not modified if no file is + found. + Attributes - Attributes is a pointer to a caller allocated + EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's + attributes are returned in *Attributes. *Attributes is + not modified if no file is found. + Size - Size is a pointer to a caller allocated UINTN. + If a file is found, the file's size is returned in *Size. + *Size is not modified if no file is found. + +Returns: + EFI_SUCCESS - Successfully find the file. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Fv could not read. + EFI_NOT_FOUND - No matching file found. + EFI_INVALID_PARAMETER - Invalid parameter + +--*/ +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_FV_ATTRIBUTES FvAttributes; + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINTN *KeyValue; + LIST_ENTRY *Link; + FFS_FILE_LIST_ENTRY *FfsFileEntry; + UINTN FileLength; + + FvDevice = FV_DEVICE_FROM_THIS (This); + + Status = FvGetVolumeAttributes (This, &FvAttributes); + if (EFI_ERROR (Status)){ + return Status; + } + + // + // Check if read operation is enabled + // + if ((FvAttributes & EFI_FV_READ_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + if (*FileType > EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) { + // + // File type needs to be in 0 - 0x0B + // + return EFI_INVALID_PARAMETER; + } + + KeyValue = (UINTN *)Key; + for (;;) { + if (*KeyValue == 0) { + // + // Search for 1st matching file + // + Link = &FvDevice->FfsFileListHeader; + } else { + // + // Key is pointer to FFsFileEntry, so get next one + // + Link = (LIST_ENTRY *)(*KeyValue); + } + + if (Link->ForwardLink == &FvDevice->FfsFileListHeader) { + // + // Next is end of list so we did not find data + // + return EFI_NOT_FOUND; + } + + FfsFileEntry = (FFS_FILE_LIST_ENTRY *)Link->ForwardLink; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)FfsFileEntry->FfsHeader; + + // + // remember the key + // + *KeyValue = (UINTN)FfsFileEntry; + + if (FfsFileHeader->Type == EFI_FV_FILETYPE_FFS_PAD) { + // + // we ignore pad files + // + continue; + } + + if (*FileType == 0) { + // + // Process all file types so we have a match + // + break; + } + + if (*FileType == FfsFileHeader->Type) { + // + // Found a matching file type + // + break; + } + + } + + // + // Return FileType, NameGuid, and Attributes + // + *FileType = FfsFileHeader->Type; + CopyMem (NameGuid, &FfsFileHeader->Name, sizeof (EFI_GUID)); + *Attributes = FfsAttributes2FvFileAttributes (FfsFileHeader->Attributes); + + // + // Read four bytes out of the 3 byte array and throw out extra data + // + FileLength = *(UINT32 *)&FfsFileHeader->Size[0] & 0x00FFFFFF; + + // + // we need to substract the header size + // + *Size = FileLength - sizeof(EFI_FFS_FILE_HEADER); + + if (FfsFileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + // + // If tail is present substract it's size; + // + *Size -= sizeof(EFI_FFS_FILE_TAIL); + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +FvReadFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN EFI_GUID *NameGuid, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT EFI_FV_FILETYPE *FoundType, + OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes, + OUT UINT32 *AuthenticationStatus + ) +/*++ + +Routine Description: + Locates a file in the firmware volume and + copies it to the supplied buffer. + +Arguments: + This - Indicates the calling context. + NameGuid - Pointer to an EFI_GUID, which is the filename. + Buffer - Buffer is a pointer to pointer to a buffer in + which the file or section contents or are returned. + BufferSize - BufferSize is a pointer to caller allocated + UINTN. On input *BufferSize indicates the size + in bytes of the memory region pointed to by + Buffer. On output, *BufferSize contains the number + of bytes required to read the file. + FoundType - FoundType is a pointer to a caller allocated + EFI_FV_FILETYPE that on successful return from Read() + contains the type of file read. This output reflects + the file type irrespective of the value of the + SectionType input. + FileAttributes - FileAttributes is a pointer to a caller allocated + EFI_FV_FILE_ATTRIBUTES. On successful return from + Read(), *FileAttributes contains the attributes of + the file read. + AuthenticationStatus - AuthenticationStatus is a pointer to a caller + allocated UINTN in which the authentication status + is returned. +Returns: + EFI_SUCCESS - Successfully read to memory buffer. + EFI_WARN_BUFFER_TOO_SMALL - Buffer too small. + EFI_NOT_FOUND - Not found. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Could not read. + EFI_INVALID_PARAMETER - Invalid parameter. + EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated. + +--*/ +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_GUID SearchNameGuid; + EFI_FV_FILETYPE LocalFoundType; + EFI_FV_FILE_ATTRIBUTES LocalAttributes; + UINTN FileSize; + UINT8 *SrcPtr; + EFI_FFS_FILE_HEADER *FfsHeader; + UINTN InputBufferSize; + + if (NULL == NameGuid) { + return EFI_INVALID_PARAMETER; + } + + FvDevice = FV_DEVICE_FROM_THIS (This); + + + // + // Keep looking until we find the matching NameGuid. + // The Key is really an FfsFileEntry + // + FvDevice->LastKey = 0; + do { + LocalFoundType = 0; + Status = FvGetNextFile ( + This, + &FvDevice->LastKey, + &LocalFoundType, + &SearchNameGuid, + &LocalAttributes, + &FileSize + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } while (!CompareGuid (&SearchNameGuid, NameGuid)); + + // + // Get a pointer to the header + // + FfsHeader = FvDevice->LastKey->FfsHeader; + + // + // Remember callers buffer size + // + InputBufferSize = *BufferSize; + + // + // Calculate return values + // + *FoundType = FfsHeader->Type; + *FileAttributes = FfsAttributes2FvFileAttributes (FfsHeader->Attributes); + *AuthenticationStatus = 0; + *BufferSize = FileSize; + + if (Buffer == NULL) { + // + // If Buffer is NULL, we only want to get the information colected so far + // + return EFI_SUCCESS; + } + + // + // Skip over file header + // + SrcPtr = ((UINT8 *)FfsHeader) + sizeof (EFI_FFS_FILE_HEADER); + + Status = EFI_SUCCESS; + if (*Buffer == NULL) { + // + // Caller passed in a pointer so allocate buffer for them + // + *Buffer = CoreAllocateBootServicesPool (FileSize); + if (*Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else if (FileSize > InputBufferSize) { + // + // Callers buffer was not big enough + // + Status = EFI_WARN_BUFFER_TOO_SMALL; + FileSize = InputBufferSize; + } + + // + // Copy data into callers buffer + // + CopyMem (*Buffer, SrcPtr, FileSize); + + return Status; +} + + +EFI_STATUS +EFIAPI +FvReadFileSection ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ) +/*++ + + Routine Description: + Locates a section in a given FFS File and + copies it to the supplied buffer (not including section header). + + Arguments: + This - Indicates the calling context. + NameGuid - Pointer to an EFI_GUID, which is the filename. + SectionType - Indicates the section type to return. + SectionInstance - Indicates which instance of sections with a type of + SectionType to return. + Buffer - Buffer is a pointer to pointer to a buffer in which + the file or section contents or are returned. + BufferSize - BufferSize is a pointer to caller allocated UINTN. + AuthenticationStatus -AuthenticationStatus is a pointer to a caller + allocated UINT32 in which the authentication status + is returned. + + Returns: + EFI_SUCCESS - Successfully read the file section into buffer. + EFI_WARN_BUFFER_TOO_SMALL - Buffer too small. + EFI_NOT_FOUND - Section not found. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Could not read. + EFI_INVALID_PARAMETER - Invalid parameter. + +--*/ +{ + EFI_STATUS Status; + FV_DEVICE *FvDevice; + EFI_FV_FILETYPE FileType; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + UINTN FileSize; + UINT8 *FileBuffer; + EFI_SECTION_EXTRACTION_PROTOCOL *Sep; + FFS_FILE_LIST_ENTRY *FfsEntry; + + if (NULL == NameGuid || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + FvDevice = FV_DEVICE_FROM_THIS (This); + + // + // Read the whole file into buffer + // + FileBuffer = NULL; + Status = FvReadFile ( + This, + NameGuid, + (VOID **)&FileBuffer, + &FileSize, + &FileType, + &FileAttributes, + AuthenticationStatus + ); + // + // Get the last key used by our call to FvReadFile as it is the FfsEntry for this file. + // + FfsEntry = (FFS_FILE_LIST_ENTRY *)FvDevice->LastKey; + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check to see that the file actually HAS sections before we go any further. + // + if (FileType == EFI_FV_FILETYPE_RAW) { + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Use FfsEntry to cache Section Extraction Protocol Inforomation + // + if (FfsEntry->StreamHandle == 0) { + // + // Located the protocol + // + Status = CoreLocateProtocol (&gEfiSectionExtractionProtocolGuid, NULL, (VOID **)&Sep); + // + // Section Extraction Protocol is part of Dxe Core so this should never fail + // + ASSERT_EFI_ERROR (Status); + + Status = Sep->OpenSectionStream ( + Sep, + FileSize, + FileBuffer, + &FfsEntry->StreamHandle + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + FfsEntry->Sep = Sep; + } else { + // + // Get cached copy of Sep + // + Sep = FfsEntry->Sep; + } + + // + // If SectionType == 0 We need the whole section stream + // + Status = Sep->GetSection ( + Sep, + FfsEntry->StreamHandle, + (SectionType == 0) ? NULL : &SectionType, + NULL, + (SectionType == 0) ? 0 : SectionInstance, + Buffer, + BufferSize, + AuthenticationStatus + ); + + // + // Close of stream defered to close of FfsHeader list to allow SEP to cache data + // + +Done: + CoreFreePool (FileBuffer); + + return Status; +} + diff --git a/EdkModulePkg/Core/Dxe/FwVol/FwVolWrite.c b/EdkModulePkg/Core/Dxe/FwVol/FwVolWrite.c new file mode 100644 index 0000000000..4368fe534e --- /dev/null +++ b/EdkModulePkg/Core/Dxe/FwVol/FwVolWrite.c @@ -0,0 +1,60 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FwVolWrite.c + +Abstract: + + Implements write firmware file + +--*/ + +#include + + +EFI_STATUS +EFIAPI +FvWriteFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN UINT32 NumberOfFiles, + IN EFI_FV_WRITE_POLICY WritePolicy, + IN EFI_FV_WRITE_FILE_DATA *FileData + ) +/*++ + + Routine Description: + Writes one or more files to the firmware volume. + + Arguments: + This - Indicates the calling context. + NumberOfFiles - Number of files. + WritePolicy - WritePolicy indicates the level of reliability for + the write in the event of a power failure or other + system failure during the write operation. + FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA. + Each element of FileData[] represents a file to be written. + + Returns: + EFI_SUCCESS - Files successfully written to firmware volume + EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated. + EFI_DEVICE_ERROR - Device error. + EFI_WRITE_PROTECTED - Write protected. + EFI_NOT_FOUND - Not found. + EFI_INVALID_PARAMETER - Invalid parameter. + EFI_UNSUPPORTED - This function not supported. + +--*/ +{ + return EFI_UNSUPPORTED; +} + diff --git a/EdkModulePkg/Core/Dxe/FwVolBlock.h b/EdkModulePkg/Core/Dxe/FwVolBlock.h new file mode 100644 index 0000000000..2e76242184 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/FwVolBlock.h @@ -0,0 +1,324 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FwVolBlock.h + +Abstract: + + Firmware Volume Block protocol.. Consumes FV hobs and creates + appropriate block protocols. + + Also consumes NT_NON_MM_FV envinronment variable and produces appropriate + block protocols fro them also... (this is TBD) + +--*/ + +#ifndef _FWVOL_BLOCK_H_ +#define _FWVOL_BLOCK_H_ + + +#define FVB_DEVICE_SIGNATURE EFI_SIGNATURE_32('_','F','V','B') + +typedef struct { + UINTN Base; + UINTN Length; +} LBA_CACHE; + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_DEVICE_PATH; + + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + FV_DEVICE_PATH DevicePath; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance; + UINTN NumBlocks; + LBA_CACHE *LbaCache; + UINT32 FvbAttributes; + EFI_PHYSICAL_ADDRESS BaseAddress; +} EFI_FW_VOL_BLOCK_DEVICE; + +#define FVB_DEVICE_FROM_THIS(a) \ + CR(a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE) + + + +EFI_STATUS +EFIAPI +FwVolBlockDriverInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This routine is the driver initialization entry point. It initializes the + libraries, consumes FV hobs and NT_NON_MM_FV environment variable and + produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate. +Arguments: + ImageHandle - The image handle. + SystemTable - The system table. +Returns: + EFI_SUCCESS - Successfully initialized firmware volume block driver. +--*/ +; + + +EFI_STATUS +EFIAPI +FwVolBlockGetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves Volume attributes. No polarity translations are done. + +Arguments: + This - Calling context + Attributes - output buffer which contains attributes + +Returns: + EFI_SUCCESS - The firmware volume attributes were returned. + +--*/ +; + + +EFI_STATUS +EFIAPI +FwVolBlockSetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Modifies the current settings of the firmware volume according to the input parameter. + +Arguments: + This - Calling context + Attributes - input buffer which contains attributes + +Returns: + EFI_SUCCESS - The firmware volume attributes were returned. + EFI_INVALID_PARAMETER - The attributes requested are in conflict with the capabilities as + declared in the firmware volume header. + EFI_UNSUPPORTED - Not supported. +--*/ +; + + +EFI_STATUS +EFIAPI +FwVolBlockEraseBlock ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +/*++ + +Routine Description: + The EraseBlock() function erases one or more blocks as denoted by the +variable argument list. The entire parameter list of blocks must be verified +prior to erasing any blocks. If a block is requested that does not exist +within the associated firmware volume (it has a larger index than the last +block of the firmware volume), the EraseBlock() function must return +EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. + +Arguments: + This - Calling context + ... - Starting LBA followed by Number of Lba to erase. a -1 to terminate + the list. + +Returns: + EFI_SUCCESS - The erase request was successfully completed. + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state. + EFI_DEVICE_ERROR - The block device is not functioning correctly and could not be + written. The firmware device may have been partially erased. + EFI_INVALID_PARAMETER - One or more of the LBAs listed in the variable argument list do + EFI_UNSUPPORTED - Not supported. + +--*/ +; + + +EFI_STATUS +EFIAPI +FwVolBlockReadBlock ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Read the specified number of bytes from the block to the input buffer. + +Arguments: + This - Indicates the calling context. + Lba - The starting logical block index to read. + Offset - Offset into the block at which to begin reading. + NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the + total size of the buffer. At exit, *NumBytes contains the + total number of bytes actually read. + Buffer - Pinter to a caller-allocated buffer that contains the destine + for the read. + +Returns: + EFI_SUCCESS - The firmware volume was read successfully. + EFI_BAD_BUFFER_SIZE - The read was attempted across an LBA boundary. + EFI_ACCESS_DENIED - Access denied. + EFI_DEVICE_ERROR - The block device is malfunctioning and could not be read. +--*/ +; + + +EFI_STATUS +EFIAPI +FwVolBlockWriteBlock ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Writes the specified number of bytes from the input buffer to the block. + +Arguments: + This - Indicates the calling context. + Lba - The starting logical block index to write to. + Offset - Offset into the block at which to begin writing. + NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the + total size of the buffer. At exit, *NumBytes contains the + total number of bytes actually written. + Buffer - Pinter to a caller-allocated buffer that contains the source + for the write. + +Returns: + EFI_SUCCESS - The firmware volume was written successfully. + EFI_BAD_BUFFER_SIZE - The write was attempted across an LBA boundary. On output, + NumBytes contains the total number of bytes actually written. + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state. + EFI_DEVICE_ERROR - The block device is malfunctioning and could not be written. + EFI_UNSUPPORTED - Not supported. +--*/ +; + + +EFI_STATUS +EFIAPI +FwVolBlockGetPhysicalAddress ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +/*++ + +Routine Description: + Get Fvb's base address. + +Arguments: + This - Indicates the calling context. + Address - Fvb device base address. + +Returns: + EFI_SUCCESS - Successfully got Fvb's base address. + EFI_UNSUPPORTED - Not supported. +--*/ +; + + +EFI_STATUS +EFIAPI +FwVolBlockGetBlockSize ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ) +/*++ + +Routine Description: + Retrieves the size in bytes of a specific block within a firmware volume. + +Arguments: + This - Indicates the calling context. + Lba - Indicates the block for which to return the size. + BlockSize - Pointer to a caller-allocated UINTN in which the size of the + block is returned. + NumberOfBlocks - Pointer to a caller-allocated UINTN in which the number of + consecutive blocks starting with Lba is returned. All blocks + in this range have a size of BlockSize. +Returns: + EFI_SUCCESS - The firmware volume base address is returned. + EFI_INVALID_PARAMETER - The requested LBA is out of range. +--*/ +; +EFI_STATUS +FwVolBlockDriverInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This routine is the driver initialization entry point. It initializes the + libraries, consumes FV hobs and NT_NON_MM_FV environment variable and + produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate. +Arguments: + ImageHandle - The image handle. + SystemTable - The system table. +Returns: + Status code + +--*/ +; + +EFI_STATUS +ProduceFVBProtocolOnBuffer ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_HANDLE ParentHandle, + OUT EFI_HANDLE *FvProtocolHandle OPTIONAL + ) +/*++ + +Routine Description: + This routine produces a firmware volume block protocol on a given + buffer. + +Arguments: + BaseAddress - base address of the firmware volume image + Length - length of the firmware volume image + ParentHandle - handle of parent firmware volume, if this + image came from an FV image file in another + firmware volume (ala capsules) + FvProtocolHandle - Firmware volume block protocol produced. + +Returns: + EFI_VOLUME_CORRUPTED - Volume corrupted. + EFI_OUT_OF_RESOURCES - No enough buffer to be allocated. + EFI_SUCCESS - Successfully produced a FVB protocol on given buffer. + +--*/ +; + +#endif diff --git a/EdkModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c b/EdkModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c new file mode 100644 index 0000000000..49f197f811 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/FwVolBlock/FwVolBlock.c @@ -0,0 +1,598 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FwVolBlock.c + +Abstract: + + Firmware Volume Block protocol.. Consumes FV hobs and creates + appropriate block protocols. + + Also consumes NT_NON_MM_FV envinronment variable and produces appropriate + block protocols fro them also... (this is TBD) + +--*/ + +#include + + +EFI_FW_VOL_BLOCK_DEVICE mFwVolBlock = { + FVB_DEVICE_SIGNATURE, + NULL, + { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { (UINT8)(sizeof (MEMMAP_DEVICE_PATH)), (UINT8)(sizeof (MEMMAP_DEVICE_PATH) >> 8) } + }, + EfiMemoryMappedIO, + (EFI_PHYSICAL_ADDRESS)0, + (EFI_PHYSICAL_ADDRESS)0, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { END_DEVICE_PATH_LENGTH, 0 } + }, + }, + { + FwVolBlockGetAttributes, + (EFI_FVB_SET_ATTRIBUTES)FwVolBlockSetAttributes, + FwVolBlockGetPhysicalAddress, + FwVolBlockGetBlockSize, + FwVolBlockReadBlock, + (EFI_FVB_WRITE)FwVolBlockWriteBlock, + (EFI_FVB_ERASE_BLOCKS)FwVolBlockEraseBlock, + NULL + }, + 0, + NULL, + 0, + 0 +}; + + + + +EFI_STATUS +EFIAPI +FwVolBlockGetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves Volume attributes. No polarity translations are done. + +Arguments: + This - Calling context + Attributes - output buffer which contains attributes + +Returns: + EFI_SUCCESS - The firmware volume attributes were returned. + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + // + // Since we are read only, it's safe to get attributes data from our in-memory copy. + // + *Attributes = FvbDevice->FvbAttributes; + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +FwVolBlockSetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Modifies the current settings of the firmware volume according to the input parameter. + +Arguments: + This - Calling context + Attributes - input buffer which contains attributes + +Returns: + EFI_SUCCESS - The firmware volume attributes were returned. + EFI_INVALID_PARAMETER - The attributes requested are in conflict with the capabilities as + declared in the firmware volume header. + EFI_UNSUPPORTED - Not supported. +--*/ +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +FwVolBlockEraseBlock ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +/*++ + +Routine Description: + The EraseBlock() function erases one or more blocks as denoted by the +variable argument list. The entire parameter list of blocks must be verified +prior to erasing any blocks. If a block is requested that does not exist +within the associated firmware volume (it has a larger index than the last +block of the firmware volume), the EraseBlock() function must return +EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. + +Arguments: + This - Calling context + ... - Starting LBA followed by Number of Lba to erase. a -1 to terminate + the list. + +Returns: + EFI_SUCCESS - The erase request was successfully completed. + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state. + EFI_DEVICE_ERROR - The block device is not functioning correctly and could not be + written. The firmware device may have been partially erased. + EFI_INVALID_PARAMETER - One or more of the LBAs listed in the variable argument list do + EFI_UNSUPPORTED - Not supported. + +--*/ +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +FwVolBlockReadBlock ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Read the specified number of bytes from the block to the input buffer. + +Arguments: + This - Indicates the calling context. + Lba - The starting logical block index to read. + Offset - Offset into the block at which to begin reading. + NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the + total size of the buffer. At exit, *NumBytes contains the + total number of bytes actually read. + Buffer - Pinter to a caller-allocated buffer that contains the destine + for the read. + +Returns: + EFI_SUCCESS - The firmware volume was read successfully. + EFI_BAD_BUFFER_SIZE - The read was attempted across an LBA boundary. + EFI_ACCESS_DENIED - Access denied. + EFI_DEVICE_ERROR - The block device is malfunctioning and could not be read. +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINT8 *LbaOffset; + UINTN LbaStart; + UINTN NumOfBytesRead; + UINTN LbaIndex; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + // + // Check if This FW can be read + // + if ((FvbDevice->FvbAttributes & EFI_FVB_READ_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + + LbaIndex = (UINTN)Lba; + if (LbaIndex >= FvbDevice->NumBlocks) { + // + // Invalid Lba, read nothing. + // + *NumBytes = 0; + return EFI_BAD_BUFFER_SIZE; + } + + if (Offset > FvbDevice->LbaCache[LbaIndex].Length) { + // + // all exceed boundry, read nothing. + // + *NumBytes = 0; + return EFI_BAD_BUFFER_SIZE; + } + + NumOfBytesRead = *NumBytes; + if (Offset + NumOfBytesRead > FvbDevice->LbaCache[LbaIndex].Length) { + // + // partial exceed boundry, read data from current postion to end. + // + NumOfBytesRead = FvbDevice->LbaCache[LbaIndex].Length - Offset; + } + + LbaStart = FvbDevice->LbaCache[LbaIndex].Base; + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress); + LbaOffset = (UINT8 *)FwVolHeader + LbaStart + Offset; + + // + // Perform read operation + // + CopyMem (Buffer, LbaOffset, NumOfBytesRead); + + if (NumOfBytesRead == *NumBytes) { + return EFI_SUCCESS; + } + + *NumBytes = NumOfBytesRead; + return EFI_BAD_BUFFER_SIZE; +} + + +EFI_STATUS +EFIAPI +FwVolBlockWriteBlock ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Writes the specified number of bytes from the input buffer to the block. + +Arguments: + This - Indicates the calling context. + Lba - The starting logical block index to write to. + Offset - Offset into the block at which to begin writing. + NumBytes - Pointer to a UINT32. At entry, *NumBytes contains the + total size of the buffer. At exit, *NumBytes contains the + total number of bytes actually written. + Buffer - Pinter to a caller-allocated buffer that contains the source + for the write. + +Returns: + EFI_SUCCESS - The firmware volume was written successfully. + EFI_BAD_BUFFER_SIZE - The write was attempted across an LBA boundary. On output, + NumBytes contains the total number of bytes actually written. + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state. + EFI_DEVICE_ERROR - The block device is malfunctioning and could not be written. + EFI_UNSUPPORTED - Not supported. +--*/ +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +FwVolBlockGetPhysicalAddress ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +/*++ + +Routine Description: + Get Fvb's base address. + +Arguments: + This - Indicates the calling context. + Address - Fvb device base address. + +Returns: + EFI_SUCCESS - Successfully got Fvb's base address. + EFI_UNSUPPORTED - Not supported. +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + if (FvbDevice->FvbAttributes & EFI_FVB_MEMORY_MAPPED) { + *Address = FvbDevice->BaseAddress; + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +FwVolBlockGetBlockSize ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ) +/*++ + +Routine Description: + Retrieves the size in bytes of a specific block within a firmware volume. + +Arguments: + This - Indicates the calling context. + Lba - Indicates the block for which to return the size. + BlockSize - Pointer to a caller-allocated UINTN in which the size of the + block is returned. + NumberOfBlocks - Pointer to a caller-allocated UINTN in which the number of + consecutive blocks starting with Lba is returned. All blocks + in this range have a size of BlockSize. +Returns: + EFI_SUCCESS - The firmware volume base address is returned. + EFI_INVALID_PARAMETER - The requested LBA is out of range. +--*/ +{ + UINTN TotalBlocks; + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + // + // Do parameter checking + // + if (Lba >= FvbDevice->NumBlocks) { + return EFI_INVALID_PARAMETER; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINTN)FvbDevice->BaseAddress); + + PtrBlockMapEntry = FwVolHeader->FvBlockMap; + + // + // Search the block map for the given block + // + TotalBlocks = 0; + while ((PtrBlockMapEntry->NumBlocks != 0) || (PtrBlockMapEntry->BlockLength !=0 )) { + TotalBlocks += PtrBlockMapEntry->NumBlocks; + if (Lba < TotalBlocks) { + // + // We find the range + // + break; + } + + PtrBlockMapEntry++; + } + + *BlockSize = PtrBlockMapEntry->BlockLength; + *NumberOfBlocks = TotalBlocks - (UINTN)Lba; + + return EFI_SUCCESS; +} + + +EFI_STATUS +ProduceFVBProtocolOnBuffer ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_HANDLE ParentHandle, + OUT EFI_HANDLE *FvProtocol OPTIONAL + ) +/*++ + +Routine Description: + This routine produces a firmware volume block protocol on a given + buffer. + +Arguments: + BaseAddress - base address of the firmware volume image + Length - length of the firmware volume image + ParentHandle - handle of parent firmware volume, if this + image came from an FV image file in another + firmware volume (ala capsules) + FvProtocol - Firmware volume block protocol produced. + +Returns: + EFI_VOLUME_CORRUPTED - Volume corrupted. + EFI_OUT_OF_RESOURCES - No enough buffer to be allocated. + EFI_SUCCESS - Successfully produced a FVB protocol on given buffer. + +--*/ +{ + EFI_STATUS Status; + EFI_FW_VOL_BLOCK_DEVICE *FvbDev; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINTN BlockIndex; + UINTN BlockIndex2; + UINTN LinearOffset; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *)(UINTN)BaseAddress; + // + // Validate FV Header, if not as expected, return + // + if (FwVolHeader->Signature != EFI_FVH_SIGNATURE) { + return EFI_VOLUME_CORRUPTED; + } + // + // Allocate EFI_FW_VOL_BLOCK_DEVICE + // + FvbDev = CoreAllocateCopyPool (sizeof (EFI_FW_VOL_BLOCK_DEVICE), &mFwVolBlock); + if (FvbDev == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + FvbDev->BaseAddress = BaseAddress; + FvbDev->FvbAttributes = FwVolHeader->Attributes; + FvbDev->FwVolBlockInstance.ParentHandle = ParentHandle; + + // + // Init the block caching fields of the device + // First, count the number of blocks + // + FvbDev->NumBlocks = 0; + for (PtrBlockMapEntry = FwVolHeader->FvBlockMap; + PtrBlockMapEntry->NumBlocks != 0; + PtrBlockMapEntry++) { + FvbDev->NumBlocks += PtrBlockMapEntry->NumBlocks; + } + // + // Second, allocate the cache + // + FvbDev->LbaCache = CoreAllocateBootServicesPool (FvbDev->NumBlocks * sizeof (LBA_CACHE)); + if (FvbDev->LbaCache == NULL) { + CoreFreePool (FvbDev); + return EFI_OUT_OF_RESOURCES; + } + // + // Last, fill in the cache with the linear address of the blocks + // + BlockIndex = 0; + LinearOffset = 0; + for (PtrBlockMapEntry = FwVolHeader->FvBlockMap; + PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { + for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) { + FvbDev->LbaCache[BlockIndex].Base = LinearOffset; + FvbDev->LbaCache[BlockIndex].Length = PtrBlockMapEntry->BlockLength; + LinearOffset += PtrBlockMapEntry->BlockLength; + BlockIndex++; + } + } + + // + // Set up the devicepath + // + FvbDev->DevicePath.MemMapDevPath.StartingAddress = BaseAddress; + FvbDev->DevicePath.MemMapDevPath.EndingAddress = BaseAddress + FwVolHeader->FvLength - 1; + + // + // + // Attach FvVolBlock Protocol to new handle + // + Status = CoreInstallMultipleProtocolInterfaces ( + &FvbDev->Handle, + &gEfiFirmwareVolumeBlockProtocolGuid, &FvbDev->FwVolBlockInstance, + &gEfiDevicePathProtocolGuid, &FvbDev->DevicePath, + &gEfiFirmwareVolumeDispatchProtocolGuid, NULL, + NULL + ); + + // + // If they want the handle back, set it. + // + if (FvProtocol != NULL) { + *FvProtocol = FvbDev->Handle; + } + + return Status; +} + + +EFI_STATUS +EFIAPI +FwVolBlockDriverInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This routine is the driver initialization entry point. It initializes the + libraries, consumes FV hobs and NT_NON_MM_FV environment variable and + produces instances of FW_VOL_BLOCK_PROTOCOL as appropriate. +Arguments: + ImageHandle - The image handle. + SystemTable - The system table. +Returns: + EFI_SUCCESS - Successfully initialized firmware volume block driver. +--*/ +{ + EFI_PEI_HOB_POINTERS FvHob; + // + // Core Needs Firmware Volumes to function + // + FvHob.Raw = GetHobList (); + while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) { + // + // Produce an FVB protocol for it + // + ProduceFVBProtocolOnBuffer (FvHob.FirmwareVolume->BaseAddress, FvHob.FirmwareVolume->Length, NULL, NULL); + FvHob.Raw = GET_NEXT_HOB (FvHob); + } + return EFI_SUCCESS; +} + + +EFI_STATUS +CoreProcessFirmwareVolume ( + IN VOID *FvHeader, + IN UINTN Size, + OUT EFI_HANDLE *FVProtocolHandle + ) +/*++ + +Routine Description: + This DXE service routine is used to process a firmware volume. In + particular, it can be called by BDS to process a single firmware + volume found in a capsule. + +Arguments: + FvHeader - pointer to a firmware volume header + Size - the size of the buffer pointed to by FvHeader + FVProtocolHandle - the handle on which a firmware volume protocol + was produced for the firmware volume passed in. + +Returns: + EFI_OUT_OF_RESOURCES - if an FVB could not be produced due to lack of + system resources + EFI_VOLUME_CORRUPTED - if the volume was corrupted + EFI_SUCCESS - a firmware volume protocol was produced for the + firmware volume + +--*/ +{ + VOID *Ptr; + EFI_STATUS Status; + + *FVProtocolHandle = NULL; + Status = ProduceFVBProtocolOnBuffer ( + (EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, + (UINT64)Size, + NULL, + FVProtocolHandle + ); + // + // Since in our implementation we use register-protocol-notify to put a + // FV protocol on the FVB protocol handle, we can't directly verify that + // the FV protocol was produced. Therefore here we will check the handle + // and make sure an FV protocol is on it. This indicates that all went + // well. Otherwise we have to assume that the volume was corrupted + // somehow. + // + if (!EFI_ERROR(Status)) { + Ptr = NULL; + Status = CoreHandleProtocol (*FVProtocolHandle, &gEfiFirmwareVolumeProtocolGuid, (VOID **)&Ptr); + if (EFI_ERROR(Status) || (Ptr == NULL)) { + return EFI_VOLUME_CORRUPTED; + } + return EFI_SUCCESS; + } + return Status; +} + + diff --git a/EdkModulePkg/Core/Dxe/FwVolDriver.h b/EdkModulePkg/Core/Dxe/FwVolDriver.h new file mode 100644 index 0000000000..fb4e0d5bb2 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/FwVolDriver.h @@ -0,0 +1,466 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FwVolDriver.h + +Abstract: + + Firmware File System protocol. Layers on top of Firmware + Block protocol to produce a file abstraction of FV based files. + +--*/ + +#ifndef __FWVOL_H +#define __FWVOL_H + + +// +// Used to track all non-deleted files +// +typedef struct { + LIST_ENTRY Link; + EFI_FFS_FILE_HEADER *FfsHeader; + UINTN StreamHandle; + EFI_SECTION_EXTRACTION_PROTOCOL *Sep; +} FFS_FILE_LIST_ENTRY; + +typedef struct { + UINTN Signature; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_HANDLE Handle; + EFI_FIRMWARE_VOLUME_PROTOCOL Fv; + + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + UINT8 *CachedFv; + UINT8 *EndOfCachedFv; + + FFS_FILE_LIST_ENTRY *LastKey; + + LIST_ENTRY FfsFileListHeader; + + UINT8 ErasePolarity; +} FV_DEVICE; + +#define FV_DEVICE_FROM_THIS(a) CR(a, FV_DEVICE, Fv, FV_DEVICE_SIGNATURE) + + +EFI_STATUS +EFIAPI +FvGetVolumeAttributes ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + OUT EFI_FV_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + +Arguments: + This - Calling context + Attributes - output buffer which contains attributes + +Returns: + EFI_SUCCESS - Successfully got volume attributes + +--*/ +; + +EFI_STATUS +EFIAPI +FvSetVolumeAttributes ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN OUT EFI_FV_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Sets current attributes for volume + +Arguments: + This - Calling context + Attributes - At input, contains attributes to be set. At output contains + new value of FV + +Returns: + EFI_UNSUPPORTED - Could not be set. +--*/ +; + +EFI_STATUS +EFIAPI +FvGetNextFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN OUT VOID *Key, + IN OUT EFI_FV_FILETYPE *FileType, + OUT EFI_GUID *NameGuid, + OUT EFI_FV_FILE_ATTRIBUTES *Attributes, + OUT UINTN *Size + ) +/*++ + +Routine Description: + Given the input key, search for the next matching file in the volume. + +Arguments: + This - Indicates the calling context. + FileType - FileType is a pointer to a caller allocated + EFI_FV_FILETYPE. The GetNextFile() API can filter it's + search for files based on the value of *FileType input. + A *FileType input of 0 causes GetNextFile() to search for + files of all types. If a file is found, the file's type + is returned in *FileType. *FileType is not modified if + no file is found. + Key - Key is a pointer to a caller allocated buffer that + contains implementation specific data that is used to + track where to begin the search for the next file. + The size of the buffer must be at least This->KeySize + bytes long. To reinitialize the search and begin from + the beginning of the firmware volume, the entire buffer + must be cleared to zero. Other than clearing the buffer + to initiate a new search, the caller must not modify the + data in the buffer between calls to GetNextFile(). + NameGuid - NameGuid is a pointer to a caller allocated EFI_GUID. + If a file is found, the file's name is returned in + *NameGuid. *NameGuid is not modified if no file is + found. + Attributes - Attributes is a pointer to a caller allocated + EFI_FV_FILE_ATTRIBUTES. If a file is found, the file's + attributes are returned in *Attributes. *Attributes is + not modified if no file is found. + Size - Size is a pointer to a caller allocated UINTN. + If a file is found, the file's size is returned in *Size. + *Size is not modified if no file is found. + +Returns: + EFI_SUCCESS - Successfully find the file. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Fv could not read. + EFI_NOT_FOUND - No matching file found. + EFI_INVALID_PARAMETER - Invalid parameter + +--*/ +; + + +EFI_STATUS +EFIAPI +FvReadFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN EFI_GUID *NameGuid, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT EFI_FV_FILETYPE *FoundType, + OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes, + OUT UINT32 *AuthenticationStatus + ) +/*++ + +Routine Description: + Locates a file in the firmware volume and + copies it to the supplied buffer. + +Arguments: + This - Indicates the calling context. + NameGuid - Pointer to an EFI_GUID, which is the filename. + Buffer - Buffer is a pointer to pointer to a buffer in + which the file or section contents or are returned. + BufferSize - BufferSize is a pointer to caller allocated + UINTN. On input *BufferSize indicates the size + in bytes of the memory region pointed to by + Buffer. On output, *BufferSize contains the number + of bytes required to read the file. + FoundType - FoundType is a pointer to a caller allocated + EFI_FV_FILETYPE that on successful return from Read() + contains the type of file read. This output reflects + the file type irrespective of the value of the + SectionType input. + FileAttributes - FileAttributes is a pointer to a caller allocated + EFI_FV_FILE_ATTRIBUTES. On successful return from + Read(), *FileAttributes contains the attributes of + the file read. + AuthenticationStatus - AuthenticationStatus is a pointer to a caller + allocated UINTN in which the authentication status + is returned. +Returns: + EFI_SUCCESS - Successfully read to memory buffer. + EFI_WARN_BUFFER_TOO_SMALL - Buffer too small. + EFI_NOT_FOUND - Not found. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Could not read. + EFI_INVALID_PARAMETER - Invalid parameter. + EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated. + +--*/ +; + +EFI_STATUS +EFIAPI +FvReadFileSection ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ) +/*++ + + Routine Description: + Locates a section in a given FFS File and + copies it to the supplied buffer (not including section header). + + Arguments: + This - Indicates the calling context. + NameGuid - Pointer to an EFI_GUID, which is the filename. + SectionType - Indicates the section type to return. + SectionInstance - Indicates which instance of sections with a type of + SectionType to return. + Buffer - Buffer is a pointer to pointer to a buffer in which + the file or section contents or are returned. + BufferSize - BufferSize is a pointer to caller allocated UINTN. + AuthenticationStatus -AuthenticationStatus is a pointer to a caller + allocated UINT32 in which the authentication status + is returned. + + Returns: + EFI_SUCCESS - Successfully read the file section into buffer. + EFI_WARN_BUFFER_TOO_SMALL - Buffer too small. + EFI_NOT_FOUND - Section not found. + EFI_DEVICE_ERROR - Device error. + EFI_ACCESS_DENIED - Could not read. + EFI_INVALID_PARAMETER - Invalid parameter. + +--*/ +; + +EFI_STATUS +EFIAPI +FvWriteFile ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN UINT32 NumberOfFiles, + IN EFI_FV_WRITE_POLICY WritePolicy, + IN EFI_FV_WRITE_FILE_DATA *FileData + ) +/*++ + + Routine Description: + Writes one or more files to the firmware volume. + + Arguments: + This - Indicates the calling context. + WritePolicy - WritePolicy indicates the level of reliability for + the write in the event of a power failure or other + system failure during the write operation. + FileData - FileData is an pointer to an array of EFI_FV_WRITE_DATA. + Each element of FileData[] represents a file to be written. + + Returns: + EFI_SUCCESS - Files successfully written to firmware volume + EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated. + EFI_DEVICE_ERROR - Device error. + EFI_WRITE_PROTECTED - Write protected. + EFI_NOT_FOUND - Not found. + EFI_INVALID_PARAMETER - Invalid parameter. + EFI_UNSUPPORTED - This function not supported. + +--*/ +; + + + +// +//Internal functions +// +typedef enum { + EfiCheckSumUint8 = 0, + EfiCheckSumUint16 = 1, + EfiCheckSumUint32 = 2, + EfiCheckSumUint64 = 3, + EfiCheckSumMaximum = 4 +} EFI_CHECKSUM_TYPE; + + +BOOLEAN +IsBufferErased ( + IN UINT8 ErasePolarity, + IN VOID *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + Check if a block of buffer is erased + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + Buffer - The buffer to be checked + BufferSize - Size of the buffer in bytes + +Returns: + TRUE - The block of buffer is erased + FALSE - The block of buffer is not erased + +--*/ +; + +EFI_FFS_FILE_STATE +GetFileState ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Get the FFS file state by checking the highest bit set in the header's state field + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file header + +Returns: + FFS File state + +--*/ +; + +VOID +SetFileState ( + IN UINT8 State, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Set the FFS file state. + +Arguments: + State - The state to be set. + FfsHeader - Points to the FFS file header + +Returns: + None. + +--*/ +; + +BOOLEAN +VerifyFvHeaderChecksum ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +/*++ + +Routine Description: + Verify checksum of the firmware volume header + +Arguments: + FvHeader - Points to the firmware volume header to be checked + +Returns: + TRUE - Checksum verification passed + FALSE - Checksum verification failed + +--*/ +; + +BOOLEAN +IsValidFfsHeader ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_FFS_FILE_STATE *FileState + ) +/*++ + +Routine Description: + Check if it's a valid FFS file header + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file header to be checked + FileState - FFS file state to be returned + +Returns: + TRUE - Valid FFS file header + FALSE - Invalid FFS file header + +--*/ +; + +BOOLEAN +IsValidFfsFile ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Check if it's a valid FFS file. + Here we are sure that it has a valid FFS file header since we must call IsValidFfsHeader() first. + +Arguments: + ErasePolarity - Erase polarity attribute of the firmware volume + FfsHeader - Points to the FFS file to be checked + +Returns: + TRUE - Valid FFS file + FALSE - Invalid FFS file + +--*/ +; + +EFI_STATUS +GetFwVolHeader ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb, + OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +/*++ + +Routine Description: + given the supplied FW_VOL_BLOCK_PROTOCOL, allocate a buffer for output and + copy the volume header into it. + +Arguments: + Fvb - The FW_VOL_BLOCK_PROTOCOL instance from which to read the volume + header + FwVolHeader - Pointer to pointer to allocated buffer in which the volume + header is returned. + +Returns: + Status code. + +--*/ +; + + +EFI_STATUS +FvCheck ( + IN OUT FV_DEVICE *FvDevice + ) +/*++ + +Routine Description: + Check if a FV is consistent and allocate cache + +Arguments: + FvDevice - pointer to the FvDevice to be checked. + +Returns: + EFI_OUT_OF_RESOURCES - Not enough buffer to be allocated. + EFI_SUCCESS - FV is consistent and cache is allocated. + EFI_VOLUME_CORRUPTED - File system is corrupted. + +--*/ +; + +#endif diff --git a/EdkModulePkg/Core/Dxe/Gcd/gcd.c b/EdkModulePkg/Core/Dxe/Gcd/gcd.c new file mode 100644 index 0000000000..73037edb24 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Gcd/gcd.c @@ -0,0 +1,2481 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + gcd.c + +Abstract: + The file contains the GCD related services in the EFI Boot Services Table. + The GCD services are used to manage the memory and I/O regions that + are accessible to the CPU that is executing the DXE core. + +--*/ + +#include + +#define MINIMUM_INITIAL_MEMORY_SIZE 0x10000 + +#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ + EFI_RESOURCE_ATTRIBUTE_TESTED | \ + EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED | \ + EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \ + EFI_RESOURCE_ATTRIBUTE_64_BIT_IO ) + +#define TESTED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \ + EFI_RESOURCE_ATTRIBUTE_TESTED ) + +#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | \ + EFI_RESOURCE_ATTRIBUTE_INITIALIZED ) + +#define PRESENT_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT) + +#define INVALID_CPU_ARCH_ATTRIBUTES 0xffffffff + +// +// Module Variables +// +EFI_LOCK mGcdMemorySpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY); +EFI_LOCK mGcdIoSpaceLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY); +LIST_ENTRY mGcdMemorySpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdMemorySpaceMap); +LIST_ENTRY mGcdIoSpaceMap = INITIALIZE_LIST_HEAD_VARIABLE (mGcdIoSpaceMap); + +EFI_GCD_MAP_ENTRY mGcdMemorySpaceMapEntryTemplate = { + EFI_GCD_MAP_SIGNATURE, + { NULL, NULL }, + 0, + 0, + 0, + 0, + EfiGcdMemoryTypeNonExistent, + 0, + NULL, + NULL +}; + +EFI_GCD_MAP_ENTRY mGcdIoSpaceMapEntryTemplate = { + EFI_GCD_MAP_SIGNATURE, + { NULL, NULL }, + 0, + 0, + 0, + 0, + 0, + EfiGcdIoTypeNonExistent, + NULL, + NULL +}; + +GCD_ATTRIBUTE_CONVERSION_ENTRY mAttributeConversionTable[] = { + { EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE, EFI_MEMORY_UC, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED, EFI_MEMORY_UCE, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE, EFI_MEMORY_WC, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE, EFI_MEMORY_WT, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE, EFI_MEMORY_WB, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED, EFI_MEMORY_RP, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED, EFI_MEMORY_WP, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED, EFI_MEMORY_XP, TRUE }, + { EFI_RESOURCE_ATTRIBUTE_PRESENT, EFI_MEMORY_PRESENT, FALSE }, + { EFI_RESOURCE_ATTRIBUTE_INITIALIZED, EFI_MEMORY_INITIALIZED, FALSE }, + { EFI_RESOURCE_ATTRIBUTE_TESTED, EFI_MEMORY_TESTED, FALSE }, + { 0, 0, FALSE } +}; + +VOID +CoreAcquireGcdMemoryLock ( + VOID + ) +/*++ + +Routine Description: + Acquire memory lock on mGcdMemorySpaceLock + +Arguments: + None + +Returns: + None + +--*/ +{ + CoreAcquireLock (&mGcdMemorySpaceLock); +} + + +VOID +CoreReleaseGcdMemoryLock ( + VOID + ) +/*++ + +Routine Description: + Release memory lock on mGcdMemorySpaceLock + +Arguments: + None + +Returns: + None + +--*/ +{ + CoreReleaseLock (&mGcdMemorySpaceLock); +} + + + +VOID +CoreAcquireGcdIoLock ( + VOID + ) +/*++ + +Routine Description: + Acquire memory lock on mGcdIoSpaceLock + +Arguments: + None + +Returns: + None + +--*/ +{ + CoreAcquireLock (&mGcdIoSpaceLock); +} + + +VOID +CoreReleaseGcdIoLock ( + VOID + ) +/*++ + +Routine Description: + Release memory lock on mGcdIoSpaceLock + +Arguments: + None + +Returns: + None + +--*/ +{ + CoreReleaseLock (&mGcdIoSpaceLock); +} + + + +// +// GCD Initialization Worker Functions +// +UINT64 +AlignValue ( + IN UINT64 Value, + IN UINTN Alignment, + IN BOOLEAN RoundUp + ) +/*++ + +Routine Description: + + Aligns a value to the specified boundary. + +Arguments: + + Value - 64 bit value to align + Alignment - Log base 2 of the boundary to align Value to + RoundUp - TRUE if Value is to be rounded up to the nearest aligned boundary. + FALSE is Value is to be rounded down to the nearest aligned boundary. + +Returns: + + A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment. + +--*/ +{ + UINT64 AlignmentMask; + + AlignmentMask = LShiftU64 (1, Alignment) - 1; + if (RoundUp) { + Value += AlignmentMask; + } + return Value & (~AlignmentMask); +} + +UINT64 +PageAlignAddress ( + IN UINT64 Value + ) +/*++ + +Routine Description: + + Aligns address to the page boundary. + +Arguments: + + Value - 64 bit address to align + +Returns: + + A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment. + +--*/ +{ + return AlignValue (Value, EFI_PAGE_SHIFT, TRUE); +} + +UINT64 +PageAlignLength ( + IN UINT64 Value + ) +/*++ + +Routine Description: + + Aligns length to the page boundary. + +Arguments: + + Value - 64 bit length to align + +Returns: + + A 64 bit value is the aligned to the value nearest Value with an alignment by Alignment. + +--*/ +{ + return AlignValue (Value, EFI_PAGE_SHIFT, FALSE); +} + +// +// GCD Memory Space Worker Functions +// +EFI_STATUS +CoreAllocateGcdMapEntry ( + IN OUT EFI_GCD_MAP_ENTRY **TopEntry, + IN OUT EFI_GCD_MAP_ENTRY **BottomEntry + ) +/*++ + +Routine Description: + + Allocate pool for two entries. + +Arguments: + + TopEntry - An entry of GCD map + BottomEntry - An entry of GCD map + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to be allocated. + EFI_SUCCESS - Both entries successfully allocated. + +--*/ +{ + *TopEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY)); + if (*TopEntry == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *BottomEntry = CoreAllocateZeroBootServicesPool (sizeof (EFI_GCD_MAP_ENTRY)); + if (*BottomEntry == NULL) { + CoreFreePool (*TopEntry); + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CoreInsertGcdMapEntry ( + IN LIST_ENTRY *Link, + IN EFI_GCD_MAP_ENTRY *Entry, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_GCD_MAP_ENTRY *TopEntry, + IN EFI_GCD_MAP_ENTRY *BottomEntry + ) +/*++ + +Routine Description: + + Internal function. Inserts a new descriptor into a sorted list + +Arguments: + + Link - The linked list to insert the range BaseAddress and Length into + + Entry - A pointer to the entry that is inserted + + BaseAddress - The base address of the new range + + Length - The length of the new range in bytes + + TopEntry - Top pad entry to insert if needed. + + BottomEntry - Bottom pad entry to insert if needed. + +Returns: + + EFI_SUCCESS - The new range was inserted into the linked list + +--*/ +{ + ASSERT (Length != 0); + ASSERT (TopEntry->Signature == 0); + ASSERT (BottomEntry->Signature == 0); + + if (BaseAddress > Entry->BaseAddress) { + CopyMem (BottomEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY)); + Entry->BaseAddress = BaseAddress; + BottomEntry->EndAddress = BaseAddress - 1; + InsertTailList (Link, &BottomEntry->Link); + } + + if ((BaseAddress + Length - 1) < Entry->EndAddress) { + CopyMem (TopEntry, Entry, sizeof (EFI_GCD_MAP_ENTRY)); + TopEntry->BaseAddress = BaseAddress + Length; + Entry->EndAddress = BaseAddress + Length - 1; + InsertHeadList (Link, &TopEntry->Link); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CoreMergeGcdMapEntry ( + IN LIST_ENTRY *Link, + IN BOOLEAN Forward, + IN LIST_ENTRY *Map + ) +/*++ + +Routine Description: + + Merge the Gcd region specified by Link and its adjacent entry + +Arguments: + + Link - Specify the entry to be merged (with its adjacent entry). + + Forward - Direction (forward or backward). + + Map - Boundary. + +Returns: + + EFI_SUCCESS - Successfully returned. + + EFI_UNSUPPORTED - These adjacent regions could not merge. + +--*/ +{ + LIST_ENTRY *AdjacentLink; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_MAP_ENTRY *AdjacentEntry; + + // + // Get adjacent entry + // + if (Forward) { + AdjacentLink = Link->ForwardLink; + } else { + AdjacentLink = Link->BackLink; + } + + // + // If AdjacentLink is the head of the list, then no merge can be performed + // + if (AdjacentLink == Map) { + return EFI_SUCCESS; + } + + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + AdjacentEntry = CR (AdjacentLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + + if (Entry->Capabilities != AdjacentEntry->Capabilities) { + return EFI_UNSUPPORTED; + } + if (Entry->Attributes != AdjacentEntry->Attributes) { + return EFI_UNSUPPORTED; + } + if (Entry->GcdMemoryType != AdjacentEntry->GcdMemoryType) { + return EFI_UNSUPPORTED; + } + if (Entry->GcdIoType != AdjacentEntry->GcdIoType) { + return EFI_UNSUPPORTED; + } + if (Entry->ImageHandle != AdjacentEntry->ImageHandle) { + return EFI_UNSUPPORTED; + } + if (Entry->DeviceHandle != AdjacentEntry->DeviceHandle) { + return EFI_UNSUPPORTED; + } + + if (Forward) { + Entry->EndAddress = AdjacentEntry->EndAddress; + } else { + Entry->BaseAddress = AdjacentEntry->BaseAddress; + } + RemoveEntryList (AdjacentLink); + CoreFreePool (AdjacentEntry); + + return EFI_SUCCESS; +} + +EFI_STATUS +CoreCleanupGcdMapEntry ( + IN EFI_GCD_MAP_ENTRY *TopEntry, + IN EFI_GCD_MAP_ENTRY *BottomEntry, + IN LIST_ENTRY *StartLink, + IN LIST_ENTRY *EndLink, + IN LIST_ENTRY *Map + ) +/*++ + +Routine Description: + + Merge adjacent entries on total chain. + +Arguments: + + TopEntry - Top entry of GCD map. + + BottomEntry - Bottom entry of GCD map. + + StartLink - Start link of the list for this loop. + + EndLink - End link of the list for this loop. + + Map - Boundary. + +Returns: + + EFI_SUCCESS - GCD map successfully cleaned up. + +--*/ +{ + LIST_ENTRY *Link; + + if (TopEntry->Signature == 0) { + CoreFreePool (TopEntry); + } + if (BottomEntry->Signature == 0) { + CoreFreePool (BottomEntry); + } + + Link = StartLink; + while (Link != EndLink->ForwardLink) { + CoreMergeGcdMapEntry (Link, FALSE, Map); + Link = Link->ForwardLink; + } + CoreMergeGcdMapEntry (EndLink, TRUE, Map); + + return EFI_SUCCESS; +} + +EFI_STATUS +CoreSearchGcdMapEntry ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + OUT LIST_ENTRY **StartLink, + OUT LIST_ENTRY **EndLink, + IN LIST_ENTRY *Map + ) +/*++ + +Routine Description: + + Search a segment of memory space in GCD map. The result is a range of GCD entry list. + +Arguments: + + BaseAddress - The start address of the segment. + + Length - The length of the segment. + + StartLink - The first GCD entry involves this segment of memory space. + + EndLink - The first GCD entry involves this segment of memory space. + + Map - Points to the start entry to search. + +Returns: + + EFI_SUCCESS - Successfully found the entry. + + EFI_NOT_FOUND - Not found. + +--*/ +{ + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *Entry; + + ASSERT (Length != 0); + + *StartLink = NULL; + *EndLink = NULL; + + Link = Map->ForwardLink; + while (Link != Map) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + if (BaseAddress >= Entry->BaseAddress && BaseAddress <= Entry->EndAddress) { + *StartLink = Link; + } + if (*StartLink != NULL) { + if ((BaseAddress + Length - 1) >= Entry->BaseAddress && + (BaseAddress + Length - 1) <= Entry->EndAddress ) { + *EndLink = Link; + return EFI_SUCCESS; + } + } + Link = Link->ForwardLink; + } + return EFI_NOT_FOUND; +} + +UINTN +CoreCountGcdMapEntry ( + IN LIST_ENTRY *Map + ) +/*++ + +Routine Description: + + Count the amount of GCD map entries. + +Arguments: + + Map - Points to the start entry to do the count loop. + +Returns: + + The count. + +--*/ +{ + UINTN Count; + LIST_ENTRY *Link; + + Count = 0; + Link = Map->ForwardLink; + while (Link != Map) { + Count++; + Link = Link->ForwardLink; + } + return Count; +} + + + +UINT64 +ConverToCpuArchAttributes ( + UINT64 Attributes + ) +/*++ + +Routine Description: + + Return the memory attribute specified by Attributes + +Arguments: + + Attributes - A num with some attribute bits on. + +Returns: + + The enum value of memory attribute. + +--*/ +{ + if ( (Attributes & EFI_MEMORY_UC) == EFI_MEMORY_UC) { + return EFI_MEMORY_UC; + } + + if ( (Attributes & EFI_MEMORY_WC ) == EFI_MEMORY_WC) { + return EFI_MEMORY_WC; + } + + if ( (Attributes & EFI_MEMORY_WT ) == EFI_MEMORY_WT) { + return EFI_MEMORY_WT; + } + + if ( (Attributes & EFI_MEMORY_WB) == EFI_MEMORY_WB) { + return EFI_MEMORY_WB; + } + + if ( (Attributes & EFI_MEMORY_WP) == EFI_MEMORY_WP) { + return EFI_MEMORY_WP; + } + + return INVALID_CPU_ARCH_ATTRIBUTES; + +} + + +EFI_STATUS +CoreConvertSpace ( + IN UINTN Operation, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + Do operation on a segment of memory space specified (add, free, remove, change attribute ...). + +Arguments: + + Operation - The type of the operation + + GcdMemoryType - Additional information for the operation + + GcdIoType - Additional information for the operation + + BaseAddress - Start address of the segment + + Length - length of the segment + + Capabilities - The alterable attributes of a newly added entry + + Attributes - The attributes needs to be set + +Returns: + + EFI_INVALID_PARAMETER - Length is 0 or address (length) not aligned when setting attribute. + + EFI_SUCCESS - Action successfully done. + + EFI_UNSUPPORTED - Could not find the proper descriptor on this segment or + set an upsupported attribute. + + EFI_ACCESS_DENIED - Operate on an space non-exist or is used for an image. + + EFI_NOT_FOUND - Free a non-using space or remove a non-exist space, and so on. + + EFI_OUT_OF_RESOURCES - No buffer could be allocated. + +Returns: + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY *Map; + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_MAP_ENTRY *TopEntry; + EFI_GCD_MAP_ENTRY *BottomEntry; + LIST_ENTRY *StartLink; + LIST_ENTRY *EndLink; + + EFI_CPU_ARCH_PROTOCOL *CpuArch; + UINT64 CpuArchAttributes; + + if (Length == 0) { + return EFI_INVALID_PARAMETER; + } + + Map = NULL; + if (Operation & GCD_MEMORY_SPACE_OPERATION) { + CoreAcquireGcdMemoryLock (); + Map = &mGcdMemorySpaceMap; + } + if (Operation & GCD_IO_SPACE_OPERATION) { + CoreAcquireGcdIoLock (); + Map = &mGcdIoSpaceMap; + } + + // + // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length + // + Status = CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, &EndLink, Map); + if (EFI_ERROR (Status)) { + Status = EFI_UNSUPPORTED; + + goto Done; + } + + // + // Verify that the list of descriptors are unallocated non-existent memory. + // + Link = StartLink; + while (Link != EndLink->ForwardLink) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + switch (Operation) { + // + // Add operations + // + case GCD_ADD_MEMORY_OPERATION: + if (Entry->GcdMemoryType != EfiGcdMemoryTypeNonExistent || + Entry->ImageHandle != NULL ) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + break; + case GCD_ADD_IO_OPERATION: + if (Entry->GcdIoType != EfiGcdIoTypeNonExistent || + Entry->ImageHandle != NULL ) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + break; + // + // Free operations + // + case GCD_FREE_MEMORY_OPERATION: + case GCD_FREE_IO_OPERATION: + if (Entry->ImageHandle == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + break; + // + // Remove operations + // + case GCD_REMOVE_MEMORY_OPERATION: + if (Entry->GcdMemoryType == EfiGcdMemoryTypeNonExistent) { + Status = EFI_NOT_FOUND; + goto Done; + } + if (Entry->ImageHandle != NULL) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + break; + case GCD_REMOVE_IO_OPERATION: + if (Entry->GcdIoType == EfiGcdIoTypeNonExistent) { + Status = EFI_NOT_FOUND; + goto Done; + } + if (Entry->ImageHandle != NULL) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + break; + // + // Set attribute operations + // + case GCD_SET_ATTRIBUTES_MEMORY_OPERATION: + if (Attributes & EFI_MEMORY_RUNTIME) { + if ((BaseAddress & EFI_PAGE_MASK) != 0 || (Length & EFI_PAGE_MASK) != 0) { + Status = EFI_INVALID_PARAMETER; + + goto Done; + } + } + if ((Entry->Capabilities & Attributes) != Attributes) { + Status = EFI_UNSUPPORTED; + goto Done; + } + break; + } + Link = Link->ForwardLink; + } + + // + // Allocate work space to perform this operation + // + Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // + // + if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) { + // + // Call CPU Arch Protocol to attempt to set attributes on the range + // + CpuArchAttributes = ConverToCpuArchAttributes (Attributes); + if ( CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES ) { + Status = CoreLocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **)&CpuArch); + if (EFI_ERROR (Status)) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + Status = CpuArch->SetMemoryAttributes ( + CpuArch, + BaseAddress, + Length, + CpuArchAttributes + ); + if (EFI_ERROR (Status)) { + goto Done; + } + } + + } + + // + // Convert/Insert the list of descriptors from StartLink to EndLink + // + Link = StartLink; + while (Link != EndLink->ForwardLink) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + CoreInsertGcdMapEntry (Link, Entry, BaseAddress, Length, TopEntry, BottomEntry); + switch (Operation) { + // + // Add operations + // + case GCD_ADD_MEMORY_OPERATION: + Entry->GcdMemoryType = GcdMemoryType; + if (GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) { + Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME | EFI_MEMORY_PORT_IO; + } else { + Entry->Capabilities = Capabilities | EFI_MEMORY_RUNTIME; + } + break; + case GCD_ADD_IO_OPERATION: + Entry->GcdIoType = GcdIoType; + break; + // + // Free operations + // + case GCD_FREE_MEMORY_OPERATION: + case GCD_FREE_IO_OPERATION: + Entry->ImageHandle = NULL; + Entry->DeviceHandle = NULL; + break; + // + // Remove operations + // + case GCD_REMOVE_MEMORY_OPERATION: + Entry->GcdMemoryType = EfiGcdMemoryTypeNonExistent; + Entry->Capabilities = 0; + break; + case GCD_REMOVE_IO_OPERATION: + Entry->GcdIoType = EfiGcdIoTypeNonExistent; + break; + // + // Set attribute operations + // + case GCD_SET_ATTRIBUTES_MEMORY_OPERATION: + Entry->Attributes = Attributes; + break; + } + Link = Link->ForwardLink; + } + + // + // Cleanup + // + Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map); + +Done: + if (Operation & GCD_MEMORY_SPACE_OPERATION) { + CoreReleaseGcdMemoryLock (); + } + if (Operation & GCD_IO_SPACE_OPERATION) { + CoreReleaseGcdIoLock (); + } + + return Status; +} + +EFI_STATUS +CoreAllocateSpaceCheckEntry ( + IN UINTN Operation, + IN EFI_GCD_MAP_ENTRY *Entry, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_GCD_IO_TYPE GcdIoType + ) +/*++ + +Routine Description: + + Check whether an entry could be used to allocate space. + +Arguments: + + Operation - Allocate memory or IO + + Entry - The entry to be tested + + GcdMemoryType - The desired memory type + + GcdIoType - The desired IO type + +Returns: + + EFI_NOT_FOUND - The memory type does not match or there's an image handle on the entry. + + EFI_UNSUPPORTED - The operation unsupported. + + EFI_SUCCESS - It's ok for this entry to be used to allocate space. + +--*/ +{ + if (Entry->ImageHandle != NULL) { + return EFI_NOT_FOUND; + } + switch (Operation) { + case GCD_ALLOCATE_MEMORY_OPERATION: + if (Entry->GcdMemoryType != GcdMemoryType) { + return EFI_NOT_FOUND; + } + break; + case GCD_ALLOCATE_IO_OPERATION: + if (Entry->GcdIoType != GcdIoType) { + return EFI_NOT_FOUND; + } + break; + default: + return EFI_UNSUPPORTED; + } + return EFI_SUCCESS; +} + +EFI_STATUS +CoreAllocateSpace ( + IN UINTN Operation, + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ) +/*++ + +Routine Description: + + Allocate space on specified address and length. + +Arguments: + + Operation - The type of operation (memory or IO) + + GcdAllocateType - The type of allocate operation + + GcdMemoryType - The desired memory type + + GcdIoType - The desired IO type + + Alignment - Align with 2^Alignment + + Length - Length to allocate + + BaseAddress - Base address to allocate + + ImageHandle - The image handle consume the allocated space. + + DeviceHandle - The device handle consume the allocated space. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter. + + EFI_NOT_FOUND - No descriptor for the desired space exists. + + EFI_SUCCESS - Space successfully allocated. + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS AlignmentMask; + EFI_PHYSICAL_ADDRESS MaxAddress; + LIST_ENTRY *Map; + LIST_ENTRY *Link; + LIST_ENTRY *SubLink; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_MAP_ENTRY *TopEntry; + EFI_GCD_MAP_ENTRY *BottomEntry; + LIST_ENTRY *StartLink; + LIST_ENTRY *EndLink; + BOOLEAN Found; + + // + // Make sure parameters are valid + // + if (GcdAllocateType < 0 || GcdAllocateType >= EfiGcdMaxAllocateType) { + return EFI_INVALID_PARAMETER; + } + if (GcdMemoryType < 0 || GcdMemoryType >= EfiGcdMemoryTypeMaximum) { + return EFI_INVALID_PARAMETER; + } + if (GcdIoType < 0 || GcdIoType >= EfiGcdIoTypeMaximum) { + return EFI_INVALID_PARAMETER; + } + if (BaseAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + if (ImageHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + if (Alignment >= 64) { + return EFI_NOT_FOUND; + } + if (Length == 0) { + return EFI_INVALID_PARAMETER; + } + + Map = NULL; + if (Operation & GCD_MEMORY_SPACE_OPERATION) { + CoreAcquireGcdMemoryLock (); + Map = &mGcdMemorySpaceMap; + } + if (Operation & GCD_IO_SPACE_OPERATION) { + CoreAcquireGcdIoLock (); + Map = &mGcdIoSpaceMap; + } + + Found = FALSE; + StartLink = NULL; + EndLink = NULL; + // + // Compute alignment bit mask + // + AlignmentMask = LShiftU64 (1, Alignment) - 1; + + if (GcdAllocateType == EfiGcdAllocateAddress) { + // + // Verify that the BaseAddress passed in is aligned correctly + // + if ((*BaseAddress & AlignmentMask) != 0) { + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length + // + Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Verify that the list of descriptors are unallocated memory matching GcdMemoryType. + // + Link = StartLink; + while (Link != EndLink->ForwardLink) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + Link = Link->ForwardLink; + Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType); + if (EFI_ERROR (Status)) { + goto Done; + } + } + Found = TRUE; + } else { + + Entry = CR (Map->BackLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + + // + // Compute the maximum address to use in the search algorithm + // + if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchBottomUp || + GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown ) { + MaxAddress = *BaseAddress - 1; + } else { + MaxAddress = Entry->EndAddress; + } + + // + // Verify that the list of descriptors are unallocated memory matching GcdMemoryType. + // + if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown || + GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) { + Link = Map->BackLink; + } else { + Link = Map->ForwardLink; + } + while (Link != Map) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + + if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown || + GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) { + Link = Link->BackLink; + } else { + Link = Link->ForwardLink; + } + + Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType); + if (EFI_ERROR (Status)) { + continue; + } + + if (GcdAllocateType == EfiGcdAllocateMaxAddressSearchTopDown || + GcdAllocateType == EfiGcdAllocateAnySearchTopDown ) { + if ((Entry->BaseAddress + Length) > MaxAddress) { + continue; + } + if (Length > (Entry->EndAddress + 1)) { + Status = EFI_NOT_FOUND; + goto Done; + } + if (Entry->EndAddress > MaxAddress) { + *BaseAddress = MaxAddress; + } else { + *BaseAddress = Entry->EndAddress; + } + *BaseAddress = (*BaseAddress + 1 - Length) & (~AlignmentMask); + } else { + *BaseAddress = (Entry->BaseAddress + AlignmentMask) & (~AlignmentMask); + if ((*BaseAddress + Length - 1) > MaxAddress) { + Status = EFI_NOT_FOUND; + goto Done; + } + } + + // + // Search for the list of descriptors that cover the range BaseAddress to BaseAddress+Length + // + Status = CoreSearchGcdMapEntry (*BaseAddress, Length, &StartLink, &EndLink, Map); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + goto Done; + } + + Link = StartLink; + // + // Verify that the list of descriptors are unallocated memory matching GcdMemoryType. + // + Found = TRUE; + SubLink = StartLink; + while (SubLink != EndLink->ForwardLink) { + Entry = CR (SubLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + Status = CoreAllocateSpaceCheckEntry (Operation, Entry, GcdMemoryType, GcdIoType); + if (EFI_ERROR (Status)) { + Link = SubLink; + Found = FALSE; + break; + } + SubLink = SubLink->ForwardLink; + } + if (Found) { + break; + } + } + } + if (!Found) { + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Allocate work space to perform this operation + // + Status = CoreAllocateGcdMapEntry (&TopEntry, &BottomEntry); + if (EFI_ERROR (Status)) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Convert/Insert the list of descriptors from StartLink to EndLink + // + Link = StartLink; + while (Link != EndLink->ForwardLink) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + CoreInsertGcdMapEntry (Link, Entry, *BaseAddress, Length, TopEntry, BottomEntry); + Entry->ImageHandle = ImageHandle; + Entry->DeviceHandle = DeviceHandle; + Link = Link->ForwardLink; + } + + // + // Cleanup + // + Status = CoreCleanupGcdMapEntry (TopEntry, BottomEntry, StartLink, EndLink, Map); + +Done: + if (Operation & GCD_MEMORY_SPACE_OPERATION) { + CoreReleaseGcdMemoryLock (); + } + if (Operation & GCD_IO_SPACE_OPERATION) { + CoreReleaseGcdIoLock (); + } + + return Status; +} + + +EFI_STATUS +CoreInternalAddMemorySpace ( + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ) +/*++ + +Routine Description: + + Add a segment of memory to GCD map. + +Arguments: + + GcdMemoryType - Memory type of the segment. + + BaseAddress - Base address of the segment. + + Length - Length of the segment. + + Capabilities - alterable attributes of the segment. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameters. + + EFI_SUCCESS - Successfully add a segment of memory space. + +--*/ +{ + // + // Make sure parameters are valid + // + if (GcdMemoryType <= EfiGcdMemoryTypeNonExistent || GcdMemoryType >= EfiGcdMemoryTypeMaximum) { + return EFI_INVALID_PARAMETER; + } + + return CoreConvertSpace (GCD_ADD_MEMORY_OPERATION, GcdMemoryType, 0, BaseAddress, Length, Capabilities, 0); +} + +// +// GCD Core Services +// +EFI_STATUS +CoreAllocateMemorySpace ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ) +/*++ + +Routine Description: + + Allocates nonexistent memory, reserved memory, system memory, or memorymapped +I/O resources from the global coherency domain of the processor. + +Arguments: + + GcdAllocateType - The type of allocate operation + + GcdMemoryType - The desired memory type + + Alignment - Align with 2^Alignment + + Length - Length to allocate + + BaseAddress - Base address to allocate + + ImageHandle - The image handle consume the allocated space. + + DeviceHandle - The device handle consume the allocated space. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter. + + EFI_NOT_FOUND - No descriptor contains the desired space. + + EFI_SUCCESS - Memory space successfully allocated. + +--*/ +{ + return CoreAllocateSpace ( + GCD_ALLOCATE_MEMORY_OPERATION, + GcdAllocateType, + GcdMemoryType, + 0, + Alignment, + Length, + BaseAddress, + ImageHandle, + DeviceHandle + ); +} + +EFI_STATUS +CoreAddMemorySpace ( + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ) +/*++ + +Routine Description: + + Adds reserved memory, system memory, or memory-mapped I/O resources to the +global coherency domain of the processor. + +Arguments: + + GcdMemoryType - Memory type of the memory space. + + BaseAddress - Base address of the memory space. + + Length - Length of the memory space. + + Capabilities - alterable attributes of the memory space. + +Returns: + + EFI_SUCCESS - Merged this memory space into GCD map. + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS PageBaseAddress; + UINT64 PageLength; + + Status = CoreInternalAddMemorySpace (GcdMemoryType, BaseAddress, Length, Capabilities); + + if (!EFI_ERROR (Status) && GcdMemoryType == EfiGcdMemoryTypeSystemMemory) { + + PageBaseAddress = PageAlignLength (BaseAddress); + PageLength = PageAlignLength (BaseAddress + Length - PageBaseAddress); + + Status = CoreAllocateMemorySpace ( + EfiGcdAllocateAddress, + GcdMemoryType, + EFI_PAGE_SHIFT, + PageLength, + &PageBaseAddress, + gDxeCoreImageHandle, + NULL + ); + + if (!EFI_ERROR (Status)) { + CoreAddMemoryDescriptor ( + EfiConventionalMemory, + PageBaseAddress, + RShiftU64 (PageLength, EFI_PAGE_SHIFT), + Capabilities + ); + } else { + for (; PageLength != 0; PageLength -= EFI_PAGE_SIZE, PageBaseAddress += EFI_PAGE_SIZE) { + Status = CoreAllocateMemorySpace ( + EfiGcdAllocateAddress, + GcdMemoryType, + EFI_PAGE_SHIFT, + EFI_PAGE_SIZE, + &PageBaseAddress, + gDxeCoreImageHandle, + NULL + ); + + if (!EFI_ERROR (Status)) { + CoreAddMemoryDescriptor ( + EfiConventionalMemory, + PageBaseAddress, + 1, + Capabilities + ); + } + } + } + } + return Status; +} + +EFI_STATUS +CoreFreeMemorySpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Frees nonexistent memory, reserved memory, system memory, or memory-mapped +I/O resources from the global coherency domain of the processor. + +Arguments: + + BaseAddress - Base address of the memory space. + + Length - Length of the memory space. + +Returns: + + EFI_SUCCESS - Space successfully freed. + +--*/ +{ + return CoreConvertSpace (GCD_FREE_MEMORY_OPERATION, 0, 0, BaseAddress, Length, 0, 0); +} + +EFI_STATUS +CoreRemoveMemorySpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Removes reserved memory, system memory, or memory-mapped I/O resources from +the global coherency domain of the processor. + +Arguments: + + BaseAddress - Base address of the memory space. + + Length - Length of the memory space. + +Returns: + + EFI_SUCCESS - Successfully remove a segment of memory space. + +--*/ +{ + return CoreConvertSpace (GCD_REMOVE_MEMORY_OPERATION, 0, 0, BaseAddress, Length, 0, 0); +} + +VOID +BuildMemoryDescriptor ( + IN OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor, + IN EFI_GCD_MAP_ENTRY *Entry + ) +/*++ + +Routine Description: + + Build a memory descriptor according to an entry. + +Arguments: + + Descriptor - The descriptor to be built + + Entry - According to this entry + +Returns: + + None + +--*/ +{ + Descriptor->BaseAddress = Entry->BaseAddress; + Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1; + Descriptor->Capabilities = Entry->Capabilities; + Descriptor->Attributes = Entry->Attributes; + Descriptor->GcdMemoryType = Entry->GcdMemoryType; + Descriptor->ImageHandle = Entry->ImageHandle; + Descriptor->DeviceHandle = Entry->DeviceHandle; +} + +EFI_STATUS +CoreGetMemorySpaceDescriptor ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor + ) +/*++ + +Routine Description: + + Retrieves the descriptor for a memory region containing a specified address. + +Arguments: + + BaseAddress - Specified start address + + Descriptor - Specified length + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_SUCCESS - Successfully get memory space descriptor. + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY *StartLink; + LIST_ENTRY *EndLink; + EFI_GCD_MAP_ENTRY *Entry; + + // + // Make sure parameters are valid + // + if (Descriptor == NULL) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireGcdMemoryLock (); + + // + // Search for the list of descriptors that contain BaseAddress + // + Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdMemorySpaceMap); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + } else { + // + // Copy the contents of the found descriptor into Descriptor + // + Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + BuildMemoryDescriptor (Descriptor, Entry); + } + + CoreReleaseGcdMemoryLock (); + + return Status; +} + +EFI_STATUS +CoreSetMemorySpaceAttributes ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + Modifies the attributes for a memory region in the global coherency domain of the +processor. + +Arguments: + + BaseAddress - Specified start address + + Length - Specified length + + Attributes - Specified attributes + +Returns: + + EFI_SUCCESS - Successfully set attribute of a segment of memory space. + +--*/ +{ + return CoreConvertSpace (GCD_SET_ATTRIBUTES_MEMORY_OPERATION, 0, 0, BaseAddress, Length, 0, Attributes); +} + +EFI_STATUS +CoreGetMemorySpaceMap ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap + ) +/*++ + +Routine Description: + + Returns a map of the memory resources in the global coherency domain of the +processor. + +Arguments: + + NumberOfDescriptors - Number of descriptors. + + MemorySpaceMap - Descriptor array + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Successfully get memory space map. + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor; + + // + // Make sure parameters are valid + // + if (NumberOfDescriptors == NULL) { + return EFI_INVALID_PARAMETER; + } + if (MemorySpaceMap == NULL) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireGcdMemoryLock (); + + // + // Count the number of descriptors + // + *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdMemorySpaceMap); + + // + // Allocate the MemorySpaceMap + // + *MemorySpaceMap = CoreAllocateBootServicesPool (*NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR)); + if (*MemorySpaceMap == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Fill in the MemorySpaceMap + // + Descriptor = *MemorySpaceMap; + Link = mGcdMemorySpaceMap.ForwardLink; + while (Link != &mGcdMemorySpaceMap) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + BuildMemoryDescriptor (Descriptor, Entry); + Descriptor++; + Link = Link->ForwardLink; + } + Status = EFI_SUCCESS; + +Done: + CoreReleaseGcdMemoryLock (); + return Status; +} + +EFI_STATUS +CoreAddIoSpace ( + IN EFI_GCD_IO_TYPE GcdIoType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Adds reserved I/O or I/O resources to the global coherency domain of the processor. + +Arguments: + + GcdIoType - IO type of the segment. + + BaseAddress - Base address of the segment. + + Length - Length of the segment. + +Returns: + + EFI_SUCCESS - Merged this segment into GCD map. + EFI_INVALID_PARAMETER - Parameter not valid + +--*/ +{ + // + // Make sure parameters are valid + // + if (GcdIoType <= EfiGcdIoTypeNonExistent || GcdIoType >= EfiGcdIoTypeMaximum) { + return EFI_INVALID_PARAMETER; + } + return CoreConvertSpace (GCD_ADD_IO_OPERATION, 0, GcdIoType, BaseAddress, Length, 0, 0); +} + +EFI_STATUS +CoreAllocateIoSpace ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ) +/*++ + +Routine Description: + + Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency +domain of the processor. + +Arguments: + + GcdAllocateType - The type of allocate operation + + GcdIoType - The desired IO type + + Alignment - Align with 2^Alignment + + Length - Length to allocate + + BaseAddress - Base address to allocate + + ImageHandle - The image handle consume the allocated space. + + DeviceHandle - The device handle consume the allocated space. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter. + + EFI_NOT_FOUND - No descriptor contains the desired space. + + EFI_SUCCESS - IO space successfully allocated. + +--*/ +{ + return CoreAllocateSpace ( + GCD_ALLOCATE_IO_OPERATION, + GcdAllocateType, + 0, + GcdIoType, + Alignment, + Length, + BaseAddress, + ImageHandle, + DeviceHandle + ); +} + +EFI_STATUS +CoreFreeIoSpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency +domain of the processor. + +Arguments: + + BaseAddress - Base address of the segment. + + Length - Length of the segment. + +Returns: + + EFI_SUCCESS - Space successfully freed. + +--*/ +{ + return CoreConvertSpace (GCD_FREE_IO_OPERATION, 0, 0, BaseAddress, Length, 0, 0); +} + +EFI_STATUS +CoreRemoveIoSpace ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Removes reserved I/O or I/O resources from the global coherency domain of the +processor. + +Arguments: + + BaseAddress - Base address of the segment. + + Length - Length of the segment. + +Returns: + + EFI_SUCCESS - Successfully removed a segment of IO space. + +--*/ +{ + return CoreConvertSpace (GCD_REMOVE_IO_OPERATION, 0, 0, BaseAddress, Length, 0, 0); +} + +VOID +BuildIoDescriptor ( + IN EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor, + IN EFI_GCD_MAP_ENTRY *Entry + ) +/*++ + +Routine Description: + + Build a IO descriptor according to an entry. + +Arguments: + + Descriptor - The descriptor to be built + + Entry - According to this entry + +Returns: + + None + +--*/ +{ + Descriptor->BaseAddress = Entry->BaseAddress; + Descriptor->Length = Entry->EndAddress - Entry->BaseAddress + 1; + Descriptor->GcdIoType = Entry->GcdIoType; + Descriptor->ImageHandle = Entry->ImageHandle; + Descriptor->DeviceHandle = Entry->DeviceHandle; +} + +EFI_STATUS +CoreGetIoSpaceDescriptor ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor + ) +/*++ + +Routine Description: + + Retrieves the descriptor for an I/O region containing a specified address. + +Arguments: + + BaseAddress - Specified start address + + Descriptor - Specified length + +Returns: + + EFI_INVALID_PARAMETER - Descriptor is NULL. + + EFI_SUCCESS - Successfully get the IO space descriptor. + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY *StartLink; + LIST_ENTRY *EndLink; + EFI_GCD_MAP_ENTRY *Entry; + + // + // Make sure parameters are valid + // + if (Descriptor == NULL) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireGcdIoLock (); + + // + // Search for the list of descriptors that contain BaseAddress + // + Status = CoreSearchGcdMapEntry (BaseAddress, 1, &StartLink, &EndLink, &mGcdIoSpaceMap); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + } else { + // + // Copy the contents of the found descriptor into Descriptor + // + Entry = CR (StartLink, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + BuildIoDescriptor (Descriptor, Entry); + } + + CoreReleaseGcdIoLock (); + + return Status; +} + +EFI_STATUS +CoreGetIoSpaceMap ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap + ) +/*++ + +Routine Description: + + Returns a map of the I/O resources in the global coherency domain of the processor. + +Arguments: + + NumberOfDescriptors - Number of descriptors. + + IoSpaceMap - Descriptor array + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Successfully get IO space map. + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor; + + // + // Make sure parameters are valid + // + if (NumberOfDescriptors == NULL) { + return EFI_INVALID_PARAMETER; + } + if (IoSpaceMap == NULL) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireGcdIoLock (); + + // + // Count the number of descriptors + // + *NumberOfDescriptors = CoreCountGcdMapEntry (&mGcdIoSpaceMap); + + // + // Allocate the IoSpaceMap + // + *IoSpaceMap = CoreAllocateBootServicesPool (*NumberOfDescriptors * sizeof (EFI_GCD_IO_SPACE_DESCRIPTOR)); + if (*IoSpaceMap == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Fill in the IoSpaceMap + // + Descriptor = *IoSpaceMap; + Link = mGcdIoSpaceMap.ForwardLink; + while (Link != &mGcdIoSpaceMap) { + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + BuildIoDescriptor (Descriptor, Entry); + Descriptor++; + Link = Link->ForwardLink; + } + Status = EFI_SUCCESS; + +Done: + CoreReleaseGcdIoLock (); + return Status; +} + +UINT64 +CoreConvertResourceDescriptorHobAttributesToCapabilities ( + EFI_GCD_MEMORY_TYPE GcdMemoryType, + UINT64 Attributes + ) +/*++ + +Routine Description: + + Converts a Resource Descriptor HOB attributes mask to an EFI Memory Descriptor + capabilities mask + +Arguments: + + GcdMemoryType - Type of resource in the GCD memory map. + Attributes - The attribute mask in the Resource Descriptor HOB. + +Returns: + + The capabilities mask for an EFI Memory Descriptor. + +--*/ +{ + UINT64 Capabilities; + GCD_ATTRIBUTE_CONVERSION_ENTRY *Conversion; + + // + // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask + // + for (Capabilities = 0, Conversion = mAttributeConversionTable; Conversion->Attribute != 0; Conversion++) { + if (Conversion->Memory || (GcdMemoryType != EfiGcdMemoryTypeSystemMemory)) { + if (Attributes & Conversion->Attribute) { + Capabilities |= Conversion->Capability; + } + } + } + + return Capabilities; +} + +EFI_STATUS +CoreInitializeMemoryServices ( + IN VOID **HobStart, + OUT EFI_PHYSICAL_ADDRESS *MemoryBaseAddress, + OUT UINT64 *MemoryLength + ) +/*++ + +Routine Description: + + External function. Initializes the GCD and memory services based on the memory + descriptor HOBs. This function is responsible for priming the GCD map and the + memory map, so memory allocations and resource allocations can be made. The first + part of this function can not depend on any memory services until at least one + memory descriptor is provided to the memory services. Then the memory services + can be used to intialize the GCD map. + +Arguments: + + HobStart - The start address of the HOB. + MemoryBaseAddress - Start address of memory region found to init DXE core. + MemoryLength - Length of memory region found to init DXE core. + +Returns: + + EFI_SUCCESS - Memory services successfully initialized. + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + EFI_MEMORY_TYPE_INFORMATION *EfiMemoryTypeInformation; + UINTN DataSize; + BOOLEAN Found; + EFI_HOB_HANDOFF_INFO_TABLE *PhitHob; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + EFI_HOB_RESOURCE_DESCRIPTOR *PhitResourceHob; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; + UINT64 Attributes; + UINT64 Capabilities; + EFI_PHYSICAL_ADDRESS MaxMemoryBaseAddress; + UINT64 MaxMemoryLength; + UINT64 MaxMemoryAttributes; + EFI_PHYSICAL_ADDRESS MaxAddress; + EFI_PHYSICAL_ADDRESS HighAddress; + EFI_HOB_RESOURCE_DESCRIPTOR *MaxResourceHob; + EFI_HOB_GUID_TYPE *GuidHob; + + // + // Point at the first HOB. This must be the PHIT HOB. + // + Hob.Raw = *HobStart; + ASSERT (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_HANDOFF); + + // + // Initialize the spin locks and maps in the memory services. + // Also fill in the memory services into the EFI Boot Services Table + // + CoreInitializePool (); + + // + // Initialize Local Variables + // + PhitResourceHob = NULL; + MaxResourceHob = NULL; + ResourceHob = NULL; + BaseAddress = 0; + Length = 0; + Attributes = 0; + MaxMemoryBaseAddress = 0; + MaxMemoryLength = 0; + MaxMemoryAttributes = 0; + + // + // Cache the PHIT HOB for later use + // + PhitHob = Hob.HandoffInformationTable; + + // + // See if a Memory Type Information HOB is available + // + GuidHob = GetFirstGuidHob (&gEfiMemoryTypeInformationGuid); + if (GuidHob != NULL) { + EfiMemoryTypeInformation = GET_GUID_HOB_DATA (GuidHob); + DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob); + if (EfiMemoryTypeInformation != NULL && DataSize > 0 && DataSize < EfiMaxMemoryType * sizeof (EFI_MEMORY_TYPE_INFORMATION)) { + CopyMem (&gMemoryTypeInformation, EfiMemoryTypeInformation, DataSize); + } + } + + // + // Find the Resource Descriptor HOB that contains range FreeMemoryBaseAddress..FreeMemoryLength + // + Length = 0; + Found = FALSE; + for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { + + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + + ResourceHob = Hob.ResourceDescriptor; + + if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && + (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES ) { + + if (PhitHob->EfiFreeMemoryBottom >= ResourceHob->PhysicalStart && + PhitHob->EfiFreeMemoryTop <= (ResourceHob->PhysicalStart + ResourceHob->ResourceLength) ) { + + // + // Cache the resource descriptor HOB for the memory region described by the PHIT HOB + // + PhitResourceHob = ResourceHob; + Found = TRUE; + + Attributes = PhitResourceHob->ResourceAttribute; + BaseAddress = PageAlignAddress (PhitHob->EfiMemoryTop); + Length = PageAlignLength (ResourceHob->PhysicalStart + ResourceHob->ResourceLength - BaseAddress); + if (Length < MINIMUM_INITIAL_MEMORY_SIZE) { + BaseAddress = PageAlignAddress (PhitHob->EfiFreeMemoryBottom); + Length = PageAlignLength (PhitHob->EfiFreeMemoryTop - BaseAddress); + if (Length < MINIMUM_INITIAL_MEMORY_SIZE) { + BaseAddress = PageAlignAddress (ResourceHob->PhysicalStart); + Length = PageAlignLength ((UINT64)((UINTN)*HobStart - BaseAddress)); + } + } + break; + } + } + } + } + + // + // Assert if a resource descriptor HOB for the memory region described by the PHIT was not found + // + ASSERT (Found); + + // + // Search all the resource descriptor HOBs from the highest possible addresses down for a memory + // region that is big enough to initialize the DXE core. Always skip the PHIT Resource HOB. + // The max address must be within the physically addressible range for the processor. + // + MaxMemoryLength = 0; + MaxAddress = EFI_MAX_ADDRESS; + do { + HighAddress = 0; + Found = FALSE; + // + // Search for a tested memory region that is below MaxAddress + // + for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { + + // + // See if this is a resource descriptor HOB that does not contain the PHIT. + // + if (Hob.ResourceDescriptor != PhitResourceHob && GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + + ResourceHob = Hob.ResourceDescriptor; + // + // See if this resource descrior HOB describes tested system memory below MaxAddress + // + if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY && + (ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES && + ResourceHob->PhysicalStart + ResourceHob->ResourceLength <= MaxAddress ) { + + // + // See if this is the highest tested system memory region below MaxAddress + // + if (ResourceHob->PhysicalStart > HighAddress) { + + MaxResourceHob = ResourceHob; + HighAddress = MaxResourceHob->PhysicalStart; + Found = TRUE; + } + } + } + } + if (Found) { + // + // Compute the size of the tested memory region below MaxAddrees + // + MaxMemoryBaseAddress = PageAlignAddress (MaxResourceHob->PhysicalStart); + MaxMemoryLength = PageAlignLength (MaxResourceHob->PhysicalStart + MaxResourceHob->ResourceLength - MaxMemoryBaseAddress); + MaxMemoryAttributes = MaxResourceHob->ResourceAttribute; + } + MaxAddress = ResourceHob->PhysicalStart; + } while (Found && MaxMemoryLength < MINIMUM_INITIAL_MEMORY_SIZE); + + // + // + // + if ((Length < MINIMUM_INITIAL_MEMORY_SIZE) || + (MaxMemoryBaseAddress > BaseAddress && MaxMemoryLength >= MINIMUM_INITIAL_MEMORY_SIZE) ) { + BaseAddress = MaxMemoryBaseAddress; + Length = MaxMemoryLength; + Attributes = MaxMemoryAttributes; + } + + // + // If no memory regions are found that are big enough to initialize the DXE core, then ASSERT(). + // + ASSERT (Length >= MINIMUM_INITIAL_MEMORY_SIZE); + + // + // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask + // + Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities (EfiGcdMemoryTypeSystemMemory, Attributes); + + // + // Declare the very first memory region, so the EFI Memory Services are available. + // + CoreAddMemoryDescriptor ( + EfiConventionalMemory, + BaseAddress, + RShiftU64 (Length, EFI_PAGE_SHIFT), + Capabilities + ); + + *MemoryBaseAddress = BaseAddress; + *MemoryLength = Length; + + return EFI_SUCCESS; +} + +EFI_STATUS +CoreInitializeGcdServices ( + IN VOID **HobStart, + IN EFI_PHYSICAL_ADDRESS MemoryBaseAddress, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + External function. Initializes the GCD and memory services based on the memory + descriptor HOBs. This function is responsible for priming the GCD map and the + memory map, so memory allocations and resource allocations can be made. The first + part of this function can not depend on any memory services until at least one + memory descriptor is provided to the memory services. Then the memory services + can be used to intialize the GCD map. + +Arguments: + + HobStart - The start address of the HOB + + MemoryBaseAddress - Start address of memory region found to init DXE core. + + MemoryLength - Length of memory region found to init DXE core. + + +Returns: + + EFI_SUCCESS - GCD services successfully initialized. + +--*/ +{ + EFI_PEI_HOB_POINTERS Hob; + VOID *NewHobList; + EFI_HOB_HANDOFF_INFO_TABLE *PhitHob; + UINT8 SizeOfMemorySpace; + UINT8 SizeOfIoSpace; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; + EFI_STATUS Status; + EFI_GCD_MAP_ENTRY *Entry; + EFI_GCD_MEMORY_TYPE GcdMemoryType; + EFI_GCD_IO_TYPE GcdIoType; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + EFI_HOB_MEMORY_ALLOCATION *MemoryHob; + EFI_HOB_FIRMWARE_VOLUME *FirmwareVolumeHob; + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; + UINTN Index; + UINT64 Capabilities; + EFI_HOB_CPU * CpuHob; + // + // Cache the PHIT HOB for later use + // + PhitHob = (EFI_HOB_HANDOFF_INFO_TABLE *)(*HobStart); + + // + // Get the number of address lines in the I/O and Memory space for the CPU + // + CpuHob = GetFirstHob (EFI_HOB_TYPE_CPU); + ASSERT (CpuHob != NULL); + SizeOfMemorySpace = CpuHob->SizeOfMemorySpace; + SizeOfIoSpace = CpuHob->SizeOfIoSpace; + + // + // Initialize the GCD Memory Space Map + // + Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdMemorySpaceMapEntryTemplate); + ASSERT (Entry != NULL); + + Entry->EndAddress = LShiftU64 (1, SizeOfMemorySpace) - 1; + + InsertHeadList (&mGcdMemorySpaceMap, &Entry->Link); + + // + // Initialize the GCD I/O Space Map + // + Entry = CoreAllocateCopyPool (sizeof (EFI_GCD_MAP_ENTRY), &mGcdIoSpaceMapEntryTemplate); + ASSERT (Entry != NULL); + + Entry->EndAddress = LShiftU64 (1, SizeOfIoSpace) - 1; + + InsertHeadList (&mGcdIoSpaceMap, &Entry->Link); + + // + // Walk the HOB list and add all resource descriptors to the GCD + // + for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { + + GcdMemoryType = EfiGcdMemoryTypeNonExistent; + GcdIoType = EfiGcdIoTypeNonExistent; + + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { + + ResourceHob = Hob.ResourceDescriptor; + + switch (ResourceHob->ResourceType) { + case EFI_RESOURCE_SYSTEM_MEMORY: + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) { + GcdMemoryType = EfiGcdMemoryTypeSystemMemory; + } + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) { + GcdMemoryType = EfiGcdMemoryTypeReserved; + } + if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) { + GcdMemoryType = EfiGcdMemoryTypeReserved; + } + break; + case EFI_RESOURCE_MEMORY_MAPPED_IO: + case EFI_RESOURCE_FIRMWARE_DEVICE: + GcdMemoryType = EfiGcdMemoryTypeMemoryMappedIo; + break; + case EFI_RESOURCE_MEMORY_MAPPED_IO_PORT: + case EFI_RESOURCE_MEMORY_RESERVED: + GcdMemoryType = EfiGcdMemoryTypeReserved; + break; + case EFI_RESOURCE_IO: + GcdIoType = EfiGcdIoTypeIo; + break; + case EFI_RESOURCE_IO_RESERVED: + GcdIoType = EfiGcdIoTypeReserved; + break; + } + + if (GcdMemoryType != EfiGcdMemoryTypeNonExistent) { + + // + // Convert the Resource HOB Attributes to an EFI Memory Capabilities mask + // + Capabilities = CoreConvertResourceDescriptorHobAttributesToCapabilities ( + GcdMemoryType, + ResourceHob->ResourceAttribute + ); + + Status = CoreInternalAddMemorySpace ( + GcdMemoryType, + ResourceHob->PhysicalStart, + ResourceHob->ResourceLength, + Capabilities + ); + } + + if (GcdIoType != EfiGcdIoTypeNonExistent) { + Status = CoreAddIoSpace ( + GcdIoType, + ResourceHob->PhysicalStart, + ResourceHob->ResourceLength + ); + } + } + } + + // + // Allocate first memory region from the GCD by the DXE core + // + Status = CoreAllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeSystemMemory, + 0, + MemoryLength, + &MemoryBaseAddress, + gDxeCoreImageHandle, + NULL + ); + + // + // Walk the HOB list and allocate all memory space that is consumed by memory allocation HOBs, + // and Firmware Volume HOBs. Also update the EFI Memory Map with the memory allocation HOBs. + // + for (Hob.Raw = *HobStart; !END_OF_HOB_LIST(Hob); Hob.Raw = GET_NEXT_HOB(Hob)) { + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_MEMORY_ALLOCATION) { + MemoryHob = Hob.MemoryAllocation; + BaseAddress = MemoryHob->AllocDescriptor.MemoryBaseAddress; + Status = CoreAllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeSystemMemory, + 0, + MemoryHob->AllocDescriptor.MemoryLength, + &BaseAddress, + gDxeCoreImageHandle, + NULL + ); + if (!EFI_ERROR (Status)) { + Status = CoreGetMemorySpaceDescriptor (MemoryHob->AllocDescriptor.MemoryBaseAddress, &Descriptor); + if (!EFI_ERROR (Status)) { + CoreAddMemoryDescriptor ( + MemoryHob->AllocDescriptor.MemoryType, + MemoryHob->AllocDescriptor.MemoryBaseAddress, + RShiftU64 (MemoryHob->AllocDescriptor.MemoryLength, EFI_PAGE_SHIFT), + Descriptor.Capabilities & (~EFI_MEMORY_RUNTIME) + ); + } + } + } + + if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_FV) { + FirmwareVolumeHob = Hob.FirmwareVolume; + BaseAddress = FirmwareVolumeHob->BaseAddress; + Status = CoreAllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeMemoryMappedIo, + 0, + FirmwareVolumeHob->Length, + &BaseAddress, + gDxeCoreImageHandle, + NULL + ); + } + } + + // + // Relocate HOB List to an allocated pool buffer. + // + NewHobList = CoreAllocateCopyPool ( + (UINTN)PhitHob->EfiFreeMemoryBottom - (UINTN)(*HobStart), + *HobStart + ); + ASSERT (NewHobList != NULL); + + *HobStart = NewHobList; + + // + // Add and allocate the remaining unallocated system memory to the memory services. + // + Status = CoreGetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); + for (Index = 0; Index < NumberOfDescriptors; Index++) { + if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) { + if (MemorySpaceMap[Index].ImageHandle == NULL) { + BaseAddress = PageAlignAddress (MemorySpaceMap[Index].BaseAddress); + Length = PageAlignLength (MemorySpaceMap[Index].BaseAddress + MemorySpaceMap[Index].Length - BaseAddress); + CoreAddMemoryDescriptor ( + EfiConventionalMemory, + BaseAddress, + RShiftU64 (Length, EFI_PAGE_SHIFT), + MemorySpaceMap[Index].Capabilities & (~EFI_MEMORY_RUNTIME) + ); + Status = CoreAllocateMemorySpace ( + EfiGcdAllocateAddress, + EfiGcdMemoryTypeSystemMemory, + 0, + Length, + &BaseAddress, + gDxeCoreImageHandle, + NULL + ); + } + } + } + CoreFreePool (MemorySpaceMap); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/Dxe/Hand/DriverSupport.c b/EdkModulePkg/Core/Dxe/Hand/DriverSupport.c new file mode 100644 index 0000000000..aa601fba08 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Hand/DriverSupport.c @@ -0,0 +1,848 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DriverSupport.c + +Abstract: + + EFI Driver Support Protocol + +Revision History + +--*/ + +#include + + + +STATIC +EFI_STATUS +GetHandleFromDriverBinding ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindingNeed, + OUT EFI_HANDLE *Handle + ); + + +// +// Driver Support Function Prototypes +// +STATIC +EFI_STATUS +CoreConnectSingleController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *DriverImageHandle OPTIONAL, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ); + +// +// Driver Support Functions +// + + +EFI_STATUS +EFIAPI +CoreConnectController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *DriverImageHandle OPTIONAL, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, + IN BOOLEAN Recursive + ) +/*++ + +Routine Description: + + Connects one or more drivers to a controller. + +Arguments: + + ControllerHandle - Handle of the controller to be connected. + + DriverImageHandle - DriverImageHandle A pointer to an ordered list of driver image handles. + + RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child of the + controller specified by ControllerHandle. + + Recursive - Whether the function would be called recursively or not. + +Returns: + + Status code. + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + IHANDLE *Handle; + PROTOCOL_INTERFACE *Prot; + LIST_ENTRY *Link; + LIST_ENTRY *ProtLink; + OPEN_PROTOCOL_DATA *OpenData; + EFI_DEVICE_PATH_PROTOCOL *AlignedRemainingDevicePath; + + // + // Make sure ControllerHandle is valid + // + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + Handle = ControllerHandle; + + // + // Connect all drivers to ControllerHandle + // + AlignedRemainingDevicePath = NULL; + if (RemainingDevicePath != NULL) { + AlignedRemainingDevicePath = CoreDuplicateDevicePath (RemainingDevicePath); + } + ReturnStatus = CoreConnectSingleController ( + ControllerHandle, + DriverImageHandle, + AlignedRemainingDevicePath + ); + if (AlignedRemainingDevicePath != NULL) { + CoreFreePool (AlignedRemainingDevicePath); + } + + // + // If not recursive, then just return after connecting drivers to ControllerHandle + // + if (!Recursive) { + return ReturnStatus; + } + + // + // If recursive, then connect all drivers to all of ControllerHandle's children + // + CoreAcquireProtocolLock (); + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + CoreReleaseProtocolLock (); + Status = CoreConnectController ( + OpenData->ControllerHandle, + NULL, + NULL, + TRUE + ); + CoreAcquireProtocolLock (); + } + } + } + CoreReleaseProtocolLock (); + + return ReturnStatus; +} + +VOID +AddSortedDriverBindingProtocol ( + IN EFI_HANDLE DriverBindingHandle, + IN OUT UINTN *NumberOfSortedDriverBindingProtocols, + IN OUT EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols, + IN UINTN DriverBindingHandleCount, + IN OUT EFI_HANDLE *DriverBindingHandleBuffer + ) +/*++ + +Routine Description: + + Add Driver Binding Protocols from Context Driver Image Handles to sorted + Driver Binding Protocol list. + +Arguments: + + DriverBindingHandle - Handle of the driver binding protocol. + + NumberOfSortedDriverBindingProtocols - Number Of sorted driver binding protocols + + SortedDriverBindingProtocols - The sorted protocol list. + + DriverBindingHandleCount - Driver Binding Handle Count. + + DriverBindingHandleBuffer - The buffer of driver binding protocol to be modified. + +Returns: + + None. + +--*/ +{ + EFI_STATUS Status; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + UINTN Index; + + // + // Make sure the DriverBindingHandle is valid + // + Status = CoreValidateHandle (DriverBindingHandle); + if (EFI_ERROR (Status)) { + return; + } + + // + // Retrieve the Driver Binding Protocol from DriverBindingHandle + // + Status = CoreHandleProtocol( + DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, + (VOID **)&DriverBinding + ); + // + // If DriverBindingHandle does not support the Driver Binding Protocol then return + // + if (EFI_ERROR (Status) || DriverBinding == NULL) { + return; + } + + // + // See if DriverBinding is already in the sorted list + // + for (Index = 0; Index < *NumberOfSortedDriverBindingProtocols; Index++) { + if (DriverBinding == SortedDriverBindingProtocols[Index]) { + return; + } + } + + // + // Add DriverBinding to the end of the list + // + SortedDriverBindingProtocols[*NumberOfSortedDriverBindingProtocols] = DriverBinding; + *NumberOfSortedDriverBindingProtocols = *NumberOfSortedDriverBindingProtocols + 1; + + // + // Mark the cooresponding handle in DriverBindingHandleBuffer as used + // + for (Index = 0; Index < DriverBindingHandleCount; Index++) { + if (DriverBindingHandleBuffer[Index] == DriverBindingHandle) { + DriverBindingHandleBuffer[Index] = NULL; + } + } +} + +STATIC +EFI_STATUS +CoreConnectSingleController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *ContextDriverImageHandles OPTIONAL, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +/*++ + +Routine Description: + + Connects a controller to a driver. + +Arguments: + + ControllerHandle - Handle of the controller to be connected. + ContextDriverImageHandles - DriverImageHandle A pointer to an ordered list of driver image handles. + RemainingDevicePath - RemainingDevicePath A pointer to the device path that specifies a child + of the controller specified by ControllerHandle. + +Returns: + + EFI_SUCCESS - One or more drivers were connected to ControllerHandle. + EFI_OUT_OF_RESOURCES - No enough system resources to complete the request. + EFI_NOT_FOUND - No drivers were connected to ControllerHandle. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE DriverImageHandle; + UINTN PlatformDriverOverrideHandleCount; + EFI_HANDLE *PlatformDriverOverrideHandleBuffer; + EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *PlatformDriverOverride; + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *BusSpecificDriverOverride; + UINTN DriverBindingHandleCount; + EFI_HANDLE *DriverBindingHandleBuffer; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + UINTN NumberOfSortedDriverBindingProtocols; + EFI_DRIVER_BINDING_PROTOCOL **SortedDriverBindingProtocols; + UINT32 HighestVersion; + UINTN HighestIndex; + UINTN SortIndex; + BOOLEAN OneStarted; + BOOLEAN DriverFound; + EFI_HANDLE DriverBindingHandle; + + // + // DriverBindingHandle is used for performance measurement, initialize it here just in case. + // + DriverBindingHandle = NULL; + // + // Initialize local variables + // + DriverBindingHandleCount = 0; + DriverBindingHandleBuffer = NULL; + PlatformDriverOverrideHandleCount = 0; + PlatformDriverOverrideHandleBuffer = NULL; + NumberOfSortedDriverBindingProtocols = 0; + SortedDriverBindingProtocols = NULL; + + // + // Get list of all Driver Binding Protocol Instances + // + Status = CoreLocateHandleBuffer ( + ByProtocol, + &gEfiDriverBindingProtocolGuid, + NULL, + &DriverBindingHandleCount, + &DriverBindingHandleBuffer + ); + if (EFI_ERROR (Status) || (DriverBindingHandleCount == 0)) { + return EFI_NOT_FOUND; + } + + // + // Allocate a duplicate array for the sorted Driver Binding Protocol Instances + // + SortedDriverBindingProtocols = CoreAllocateBootServicesPool (sizeof (VOID *) * DriverBindingHandleCount); + if (SortedDriverBindingProtocols == NULL) { + CoreFreePool (DriverBindingHandleBuffer); + return EFI_OUT_OF_RESOURCES; + } + + // + // Add Driver Binding Protocols from Context Driver Image Handles first + // + if (ContextDriverImageHandles != NULL) { + for (Index = 0; ContextDriverImageHandles[Index] != NULL; Index++) { + AddSortedDriverBindingProtocol ( + ContextDriverImageHandles[Index], + &NumberOfSortedDriverBindingProtocols, + SortedDriverBindingProtocols, + DriverBindingHandleCount, + DriverBindingHandleBuffer + ); + } + } + + // + // Add the Platform Driver Override Protocol drivers for ControllerHandle next + // + Status = CoreLocateProtocol ( + &gEfiPlatformDriverOverrideProtocolGuid, + NULL, + (VOID **)&PlatformDriverOverride + ); + if (!EFI_ERROR (Status) && (PlatformDriverOverride != NULL)) { + DriverImageHandle = NULL; + do { + Status = PlatformDriverOverride->GetDriver ( + PlatformDriverOverride, + ControllerHandle, + &DriverImageHandle + ); + if (!EFI_ERROR (Status)) { + AddSortedDriverBindingProtocol ( + DriverImageHandle, + &NumberOfSortedDriverBindingProtocols, + SortedDriverBindingProtocols, + DriverBindingHandleCount, + DriverBindingHandleBuffer + ); + } + } while (!EFI_ERROR (Status)); + } + + // + // Get the Bus Specific Driver Override Protocol instance on the Controller Handle + // + Status = CoreHandleProtocol( + ControllerHandle, + &gEfiBusSpecificDriverOverrideProtocolGuid, + (VOID **)&BusSpecificDriverOverride + ); + if (!EFI_ERROR (Status) && (BusSpecificDriverOverride != NULL)) { + DriverImageHandle = NULL; + do { + Status = BusSpecificDriverOverride->GetDriver ( + BusSpecificDriverOverride, + &DriverImageHandle + ); + if (!EFI_ERROR (Status)) { + AddSortedDriverBindingProtocol ( + DriverImageHandle, + &NumberOfSortedDriverBindingProtocols, + SortedDriverBindingProtocols, + DriverBindingHandleCount, + DriverBindingHandleBuffer + ); + } + } while (!EFI_ERROR (Status)); + } + + // + // Then add all the remaining Driver Binding Protocols + // + SortIndex = NumberOfSortedDriverBindingProtocols; + for (Index = 0; Index < DriverBindingHandleCount; Index++) { + AddSortedDriverBindingProtocol ( + DriverBindingHandleBuffer[Index], + &NumberOfSortedDriverBindingProtocols, + SortedDriverBindingProtocols, + DriverBindingHandleCount, + DriverBindingHandleBuffer + ); + } + + // + // Free the Driver Binding Handle Buffer + // + CoreFreePool (DriverBindingHandleBuffer); + + // + // Sort the remaining DriverBinding Protocol based on their Version field from + // highest to lowest. + // + for ( ; SortIndex < DriverBindingHandleCount; SortIndex++) { + HighestVersion = SortedDriverBindingProtocols[SortIndex]->Version; + HighestIndex = SortIndex; + for (Index = SortIndex + 1; Index < DriverBindingHandleCount; Index++) { + if (SortedDriverBindingProtocols[Index]->Version > HighestVersion) { + HighestVersion = SortedDriverBindingProtocols[Index]->Version; + HighestIndex = Index; + } + } + if (SortIndex != HighestIndex) { + DriverBinding = SortedDriverBindingProtocols[SortIndex]; + SortedDriverBindingProtocols[SortIndex] = SortedDriverBindingProtocols[HighestIndex]; + SortedDriverBindingProtocols[HighestIndex] = DriverBinding; + } + } + + // + // Loop until no more drivers can be started on ControllerHandle + // + OneStarted = FALSE; + do { + + // + // Loop through the sorted Driver Binding Protocol Instances in order, and see if + // any of the Driver Binding Protocols support the controller specified by + // ControllerHandle. + // + DriverBinding = NULL; + DriverFound = FALSE; + for (Index = 0; (Index < NumberOfSortedDriverBindingProtocols) && !DriverFound; Index++) { + if (SortedDriverBindingProtocols[Index] != NULL) { + DriverBinding = SortedDriverBindingProtocols[Index]; + Status = DriverBinding->Supported( + DriverBinding, + ControllerHandle, + RemainingDevicePath + ); + if (!EFI_ERROR (Status)) { + SortedDriverBindingProtocols[Index] = NULL; + DriverFound = TRUE; + + // + // A driver was found that supports ControllerHandle, so attempt to start the driver + // on ControllerHandle. + // + PERF_CODE_BEGIN (); + GetHandleFromDriverBinding (DriverBinding, &DriverBindingHandle); + PERF_CODE_END (); + + PERF_START (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0); + Status = DriverBinding->Start ( + DriverBinding, + ControllerHandle, + RemainingDevicePath + ); + PERF_END (DriverBindingHandle, DRIVERBINDING_START_TOK, NULL, 0); + + if (!EFI_ERROR (Status)) { + // + // The driver was successfully started on ControllerHandle, so set a flag + // + OneStarted = TRUE; + } + } + } + } + } while (DriverFound); + + // + // Free any buffers that were allocated with AllocatePool() + // + CoreFreePool (SortedDriverBindingProtocols); + + // + // If at least one driver was started on ControllerHandle, then return EFI_SUCCESS. + // + if (OneStarted) { + return EFI_SUCCESS; + } + + // + // If no drivers started and RemainingDevicePath is an End Device Path Node, then return EFI_SUCCESS + // + if (RemainingDevicePath != NULL) { + if (IsDevicePathEnd (RemainingDevicePath)) { + return EFI_SUCCESS; + } + } + + // + // Otherwise, no drivers were started on ControllerHandle, so return EFI_NOT_FOUND + // + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EFIAPI +CoreDisconnectController ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverImageHandle OPTIONAL, + IN EFI_HANDLE ChildHandle OPTIONAL + ) +/*++ + +Routine Description: + + Disonnects a controller from a driver + +Arguments: + + ControllerHandle - ControllerHandle The handle of the controller from which driver(s) + are to be disconnected. + DriverImageHandle - DriverImageHandle The driver to disconnect from ControllerHandle. + ChildHandle - ChildHandle The handle of the child to destroy. + +Returns: + + EFI_SUCCESS - One or more drivers were disconnected from the controller. + EFI_SUCCESS - On entry, no drivers are managing ControllerHandle. + EFI_SUCCESS - DriverImageHandle is not NULL, and on entry DriverImageHandle is not managing ControllerHandle. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - DriverImageHandle is not NULL, and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL, and it is not a valid EFI_HANDLE. + EFI_OUT_OF_RESOURCES - There are not enough resources available to disconnect any drivers from ControllerHandle. + EFI_DEVICE_ERROR - The controller could not be disconnected because of a device error. + +--*/ +{ + EFI_STATUS Status; + IHANDLE *Handle; + EFI_HANDLE *DriverImageHandleBuffer; + EFI_HANDLE *ChildBuffer; + UINTN Index; + UINTN HandleIndex; + UINTN DriverImageHandleCount; + UINTN ChildrenToStop; + UINTN ChildBufferCount; + UINTN StopCount; + BOOLEAN Duplicate; + BOOLEAN ChildHandleValid; + BOOLEAN DriverImageHandleValid; + LIST_ENTRY *Link; + LIST_ENTRY *ProtLink; + OPEN_PROTOCOL_DATA *OpenData; + PROTOCOL_INTERFACE *Prot; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + + // + // Make sure ControllerHandle is valid + // + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure ChildHandle is valid if it is not NULL + // + if (ChildHandle != NULL) { + Status = CoreValidateHandle (ChildHandle); + if (EFI_ERROR (Status)) { + return Status; + } + } + + Handle = ControllerHandle; + + // + // Get list of drivers that are currently managing ControllerHandle + // + DriverImageHandleBuffer = NULL; + DriverImageHandleCount = 1; + + if (DriverImageHandle == NULL) { + // + // Look at each protocol interface for a match + // + DriverImageHandleCount = 0; + + CoreAcquireProtocolLock (); + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + DriverImageHandleCount++; + } + } + } + CoreReleaseProtocolLock (); + + // + // If there are no drivers managing this controller, then return EFI_SUCCESS + // + if (DriverImageHandleCount == 0) { + Status = EFI_SUCCESS; + goto Done; + } + + DriverImageHandleBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * DriverImageHandleCount); + if (DriverImageHandleBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + DriverImageHandleCount = 0; + + CoreAcquireProtocolLock (); + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + Duplicate = FALSE; + for (Index = 0; Index< DriverImageHandleCount; Index++) { + if (DriverImageHandleBuffer[Index] == OpenData->AgentHandle) { + Duplicate = TRUE; + break; + } + } + if (!Duplicate) { + DriverImageHandleBuffer[DriverImageHandleCount] = OpenData->AgentHandle; + DriverImageHandleCount++; + } + } + } + } + CoreReleaseProtocolLock (); + } + + StopCount = 0; + for (HandleIndex = 0; HandleIndex < DriverImageHandleCount; HandleIndex++) { + + if (DriverImageHandleBuffer != NULL) { + DriverImageHandle = DriverImageHandleBuffer[HandleIndex]; + } + + // + // Get the Driver Binding Protocol of the driver that is managing this controller + // + Status = CoreHandleProtocol ( + DriverImageHandle, + &gEfiDriverBindingProtocolGuid, + (VOID **)&DriverBinding + ); + if (EFI_ERROR (Status)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Look at each protocol interface for a match + // + DriverImageHandleValid = FALSE; + ChildBufferCount = 0; + + CoreAcquireProtocolLock (); + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if (OpenData->AgentHandle == DriverImageHandle) { + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) { + ChildBufferCount++; + } + if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) { + DriverImageHandleValid = TRUE; + } + } + } + } + CoreReleaseProtocolLock (); + + if (DriverImageHandleValid) { + ChildHandleValid = FALSE; + ChildBuffer = NULL; + if (ChildBufferCount != 0) { + ChildBuffer = CoreAllocateBootServicesPool (sizeof (EFI_HANDLE) * ChildBufferCount); + if (ChildBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + ChildBufferCount = 0; + + CoreAcquireProtocolLock (); + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + for (ProtLink = Prot->OpenList.ForwardLink; + ProtLink != &Prot->OpenList; + ProtLink = ProtLink->ForwardLink) { + OpenData = CR (ProtLink, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if ((OpenData->AgentHandle == DriverImageHandle) && + ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0)) { + Duplicate = FALSE; + for (Index = 0; Index < ChildBufferCount; Index++) { + if (ChildBuffer[Index] == OpenData->ControllerHandle) { + Duplicate = TRUE; + break; + } + } + if (!Duplicate) { + ChildBuffer[ChildBufferCount] = OpenData->ControllerHandle; + if (ChildHandle == ChildBuffer[ChildBufferCount]) { + ChildHandleValid = TRUE; + } + ChildBufferCount++; + } + } + } + } + CoreReleaseProtocolLock (); + } + + if (ChildHandle == NULL || ChildHandleValid) { + ChildrenToStop = 0; + Status = EFI_SUCCESS; + if (ChildBufferCount > 0) { + if (ChildHandle != NULL) { + ChildrenToStop = 1; + Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, &ChildHandle); + } else { + ChildrenToStop = ChildBufferCount; + Status = DriverBinding->Stop (DriverBinding, ControllerHandle, ChildrenToStop, ChildBuffer); + } + } + if (!EFI_ERROR (Status) && ((ChildHandle == NULL) || (ChildBufferCount == ChildrenToStop))) { + Status = DriverBinding->Stop (DriverBinding, ControllerHandle, 0, NULL); + } + if (!EFI_ERROR (Status)) { + StopCount++; + } + } + + if (ChildBuffer != NULL) { + CoreFreePool (ChildBuffer); + } + } + } + + if (StopCount > 0) { + Status = EFI_SUCCESS; + } else { + Status = EFI_NOT_FOUND; + } + +Done: + + if (DriverImageHandleBuffer != NULL) { + CoreFreePool (DriverImageHandleBuffer); + } + + return Status; +} + + + +STATIC +EFI_STATUS +GetHandleFromDriverBinding ( + IN EFI_DRIVER_BINDING_PROTOCOL *DriverBindingNeed, + OUT EFI_HANDLE *Handle + ) +/*++ + +Routine Description: + + Locate the driver binding handle which a specified driver binding protocol installed on. + +Arguments: + + DriverBindingNeed - The specified driver binding protocol. + + Handle - The driver binding handle which the protocol installed on. + + +Returns: + + EFI_NOT_FOUND - Could not find the handle. + + EFI_SUCCESS - Successfully find the associated driver binding handle. + +--*/ + { + EFI_STATUS Status ; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + UINTN DriverBindingHandleCount; + EFI_HANDLE *DriverBindingHandleBuffer; + UINTN Index; + + DriverBindingHandleCount = 0; + DriverBindingHandleBuffer = NULL; + *Handle = NULL_HANDLE; + Status = CoreLocateHandleBuffer ( + ByProtocol, + &gEfiDriverBindingProtocolGuid, + NULL, + &DriverBindingHandleCount, + &DriverBindingHandleBuffer + ); + if (EFI_ERROR (Status) || DriverBindingHandleCount == 0) { + return EFI_NOT_FOUND; + } + + for (Index = 0 ; Index < DriverBindingHandleCount; Index++ ) { + Status = CoreOpenProtocol( + DriverBindingHandleBuffer[Index], + &gEfiDriverBindingProtocolGuid, + (VOID **)&DriverBinding, + gDxeCoreImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (!EFI_ERROR (Status) && DriverBinding != NULL) { + + if ( DriverBinding == DriverBindingNeed ) { + *Handle = DriverBindingHandleBuffer[Index]; + CoreFreePool (DriverBindingHandleBuffer); + return EFI_SUCCESS ; + } + } + } + + CoreFreePool (DriverBindingHandleBuffer); + return EFI_NOT_FOUND ; +} + diff --git a/EdkModulePkg/Core/Dxe/Hand/Notify.c b/EdkModulePkg/Core/Dxe/Hand/Notify.c new file mode 100644 index 0000000000..f48fee76cb --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Hand/Notify.c @@ -0,0 +1,333 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + notify.c + +Abstract: + + EFI notify infrastructure + + + +Revision History + +--*/ + +#include + +VOID +CoreNotifyProtocolEntry ( + IN PROTOCOL_ENTRY *ProtEntry + ) +/*++ + +Routine Description: + + Signal event for every protocol in protocol entry. + +Arguments: + + ProtEntry - Protocol entry + +Returns: + +--*/ +{ + PROTOCOL_NOTIFY *ProtNotify; + LIST_ENTRY *Link; + + ASSERT_LOCKED (&gProtocolDatabaseLock); + + for (Link=ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { + ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + CoreSignalEvent (ProtNotify->Event); + } +} + + +PROTOCOL_INTERFACE * +CoreRemoveInterfaceFromProtocol ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +/*++ + +Routine Description: + + Removes Protocol from the protocol list (but not the handle list). + +Arguments: + + Handle - The handle to remove protocol on. + + Protocol - GUID of the protocol to be moved + + Interface - The interface of the protocol + +Returns: + + Protocol Entry + +--*/ +{ + PROTOCOL_INTERFACE *Prot; + PROTOCOL_NOTIFY *ProtNotify; + PROTOCOL_ENTRY *ProtEntry; + LIST_ENTRY *Link; + + ASSERT_LOCKED (&gProtocolDatabaseLock); + + Prot = CoreFindProtocolInterface (Handle, Protocol, Interface); + if (Prot != NULL) { + + ProtEntry = Prot->Protocol; + + // + // If there's a protocol notify location pointing to this entry, back it up one + // + + for(Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link=Link->ForwardLink) { + ProtNotify = CR(Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + + if (ProtNotify->Position == &Prot->ByProtocol) { + ProtNotify->Position = Prot->ByProtocol.BackLink; + } + } + + // + // Remove the protocol interface entry + // + + RemoveEntryList (&Prot->ByProtocol); + } + + return Prot; +} + + + +EFI_STATUS +EFIAPI +CoreRegisterProtocolNotify ( + IN EFI_GUID *Protocol, + IN EFI_EVENT Event, + OUT VOID **Registration + ) +/*++ + +Routine Description: + + Add a new protocol notification record for the request protocol. + +Arguments: + + Protocol - The requested protocol to add the notify registration + + Event - The event to signal + + Registration - Returns the registration record + + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_SUCCESS - Successfully returned the registration record that has been added + +--*/ +{ + PROTOCOL_ENTRY *ProtEntry; + PROTOCOL_NOTIFY *ProtNotify; + EFI_STATUS Status; + + if ((Protocol == NULL) || (Event == NULL) || (Registration == NULL)) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireProtocolLock (); + + ProtNotify = NULL; + + // + // Get the protocol entry to add the notification too + // + + ProtEntry = CoreFindProtocolEntry (Protocol, TRUE); + if (ProtEntry != NULL) { + + // + // Allocate a new notification record + // + + ProtNotify = CoreAllocateBootServicesPool (sizeof(PROTOCOL_NOTIFY)); + + if (ProtNotify != NULL) { + + ProtNotify->Signature = PROTOCOL_NOTIFY_SIGNATURE; + ProtNotify->Protocol = ProtEntry; + ProtNotify->Event = Event; + // + // start at the begining + // + ProtNotify->Position = &ProtEntry->Protocols; + + InsertTailList (&ProtEntry->Notify, &ProtNotify->Link); + } + } + + CoreReleaseProtocolLock (); + + // + // Done. If we have a protocol notify entry, then return it. + // Otherwise, we must have run out of resources trying to add one + // + + Status = EFI_OUT_OF_RESOURCES; + if (ProtNotify != NULL) { + *Registration = ProtNotify; + Status = EFI_SUCCESS; + } + + return Status; +} + + + +EFI_STATUS +EFIAPI +CoreReinstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *OldInterface, + IN VOID *NewInterface + ) +/*++ + +Routine Description: + + Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface. + +Arguments: + + UserHandle - Handle on which the interface is to be reinstalled + Protocol - The numeric ID of the interface + OldInterface - A pointer to the old interface + NewInterface - A pointer to the new interface + + +Returns: + + Status code. + + On EFI_SUCCESS The protocol interface was installed + On EFI_NOT_FOUND The OldInterface on the handle was not found + On EFI_INVALID_PARAMETER One of the parameters has an invalid value + +--*/ +{ + EFI_STATUS Status; + IHANDLE *Handle; + PROTOCOL_INTERFACE *Prot; + PROTOCOL_ENTRY *ProtEntry; + + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + Handle = (IHANDLE *) UserHandle; + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Check that Protocol exists on UserHandle, and Interface matches the interface in the database + // + Prot = CoreFindProtocolInterface (UserHandle, Protocol, OldInterface); + if (Prot == NULL) { + CoreReleaseProtocolLock (); + return EFI_NOT_FOUND; + } + + // + // Attempt to disconnect all drivers that are using the protocol interface that is about to be reinstalled + // + Status = CoreDisconnectControllersUsingProtocolInterface ( + UserHandle, + Prot + ); + if (EFI_ERROR (Status)) { + // + // One or more drivers refused to release, so return the error + // + CoreReleaseProtocolLock (); + return Status; + } + + // + // Remove the protocol interface from the protocol + // + Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, OldInterface); + + if (Prot == NULL) { + CoreReleaseProtocolLock (); + return EFI_NOT_FOUND; + } + + ProtEntry = Prot->Protocol; + + // + // Update the interface on the protocol + // + Prot->Interface = NewInterface; + + // + // Add this protocol interface to the tail of the + // protocol entry + // + InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); + + // + // Update the Key to show that the handle has been created/modified + // + gHandleDatabaseKey++; + Handle->Key = gHandleDatabaseKey; + + // + // Release the lock and connect all drivers to UserHandle + // + CoreReleaseProtocolLock (); + Status = CoreConnectController ( + UserHandle, + NULL, + NULL, + TRUE + ); + CoreAcquireProtocolLock (); + + // + // Notify the notification list for this protocol + // + CoreNotifyProtocolEntry (ProtEntry); + + CoreReleaseProtocolLock (); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/Dxe/Hand/handle.c b/EdkModulePkg/Core/Dxe/Hand/handle.c new file mode 100644 index 0000000000..2edfdeb78b --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Hand/handle.c @@ -0,0 +1,1699 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + handle.c + +Abstract: + + EFI handle & protocol handling + + + +Revision History + +--*/ + +#include + + +// +// mProtocolDatabase - A list of all protocols in the system. (simple list for now) +// gHandleList - A list of all the handles in the system +// gProtocolDatabaseLock - Lock to protect the mProtocolDatabase +// gHandleDatabaseKey - The Key to show that the handle has been created/modified +// +static LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase); +LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList); +EFI_LOCK gProtocolDatabaseLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY); +UINT64 gHandleDatabaseKey = 0; + + +VOID +CoreAcquireProtocolLock ( + VOID + ) +/*++ + +Routine Description: + + Acquire lock on gProtocolDatabaseLock. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + CoreAcquireLock (&gProtocolDatabaseLock); +} + + +VOID +CoreReleaseProtocolLock ( + VOID + ) +/*++ + +Routine Description: + + Release lock on gProtocolDatabaseLock. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + CoreReleaseLock (&gProtocolDatabaseLock); +} + + +EFI_STATUS +CoreValidateHandle ( + IN EFI_HANDLE UserHandle + ) +/*++ + +Routine Description: + + Check whether a handle is a valid EFI_HANDLE + +Arguments: + + UserHandle - The handle to check + +Returns: + + EFI_INVALID_PARAMETER - The handle is NULL or not a valid EFI_HANDLE. + + EFI_SUCCESS - The handle is valid EFI_HANDLE. + +--*/ +{ + IHANDLE *Handle; + + Handle = (IHANDLE *)UserHandle; + if (Handle == NULL) { + return EFI_INVALID_PARAMETER; + } + if (Handle->Signature != EFI_HANDLE_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + return EFI_SUCCESS; +} + + +PROTOCOL_ENTRY * +CoreFindProtocolEntry ( + IN EFI_GUID *Protocol, + IN BOOLEAN Create + ) +/*++ + +Routine Description: + + Finds the protocol entry for the requested protocol. + + The gProtocolDatabaseLock must be owned + +Arguments: + + Protocol - The ID of the protocol + + Create - Create a new entry if not found + +Returns: + + Protocol entry + +--*/ +{ + LIST_ENTRY *Link; + PROTOCOL_ENTRY *Item; + PROTOCOL_ENTRY *ProtEntry; + + ASSERT_LOCKED(&gProtocolDatabaseLock); + + // + // Search the database for the matching GUID + // + + ProtEntry = NULL; + for (Link = mProtocolDatabase.ForwardLink; + Link != &mProtocolDatabase; + Link = Link->ForwardLink) { + + Item = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE); + if (CompareGuid (&Item->ProtocolID, Protocol)) { + + // + // This is the protocol entry + // + + ProtEntry = Item; + break; + } + } + + // + // If the protocol entry was not found and Create is TRUE, then + // allocate a new entry + // + if ((ProtEntry == NULL) && Create) { + ProtEntry = CoreAllocateBootServicesPool (sizeof(PROTOCOL_ENTRY)); + + if (ProtEntry != NULL) { + // + // Initialize new protocol entry structure + // + ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE; + CopyMem ((VOID *)&ProtEntry->ProtocolID, Protocol, sizeof (EFI_GUID)); + InitializeListHead (&ProtEntry->Protocols); + InitializeListHead (&ProtEntry->Notify); + + // + // Add it to protocol database + // + InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries); + } + } + + return ProtEntry; +} + + +PROTOCOL_INTERFACE * +CoreFindProtocolInterface ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +/*++ + +Routine Description: + + Finds the protocol instance for the requested handle and protocol. + + Note: This function doesn't do parameters checking, it's caller's responsibility + to pass in valid parameters. + +Arguments: + + Handle - The handle to search the protocol on + + Protocol - GUID of the protocol + + Interface - The interface for the protocol being searched + +Returns: + + Protocol instance (NULL: Not found) + +--*/ +{ + PROTOCOL_INTERFACE *Prot; + PROTOCOL_ENTRY *ProtEntry; + LIST_ENTRY *Link; + + ASSERT_LOCKED(&gProtocolDatabaseLock); + Prot = NULL; + + // + // Lookup the protocol entry for this protocol ID + // + + ProtEntry = CoreFindProtocolEntry (Protocol, FALSE); + if (ProtEntry != NULL) { + + // + // Look at each protocol interface for any matches + // + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link=Link->ForwardLink) { + + // + // If this protocol interface matches, remove it + // + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + if (Prot->Interface == Interface && Prot->Protocol == ProtEntry) { + break; + } + + Prot = NULL; + } + } + + return Prot; +} + +STATIC +EFI_STATUS +CoreUnregisterProtocolNotifyEvent ( + IN EFI_EVENT Event + ) +/*++ + +Routine Description: + + Removes an event from a register protocol notify list on a protocol. + +Arguments: + + Event - The event to search for in the protocol database. + +Returns: + + EFI_SUCCESS if the event was found and removed. + EFI_NOT_FOUND if the event was not found in the protocl database. + +--*/ +{ + LIST_ENTRY *Link; + PROTOCOL_ENTRY *ProtEntry; + LIST_ENTRY *NotifyLink; + PROTOCOL_NOTIFY *ProtNotify; + + CoreAcquireProtocolLock (); + + for ( Link = mProtocolDatabase.ForwardLink; + Link != &mProtocolDatabase; + Link = Link->ForwardLink) { + + ProtEntry = CR(Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE); + + for ( NotifyLink = ProtEntry->Notify.ForwardLink; + NotifyLink != &ProtEntry->Notify; + NotifyLink = NotifyLink->ForwardLink) { + + ProtNotify = CR(NotifyLink, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE); + + if (ProtNotify->Event == Event) { + RemoveEntryList(&ProtNotify->Link); + CoreFreePool(ProtNotify); + CoreReleaseProtocolLock (); + return EFI_SUCCESS; + } + } + } + + CoreReleaseProtocolLock (); + return EFI_NOT_FOUND; +} + + +EFI_STATUS +CoreUnregisterProtocolNotify ( + IN EFI_EVENT Event + ) +/*++ + +Routine Description: + + Removes all the events in the protocol database that match Event. + +Arguments: + + Event - The event to search for in the protocol database. + +Returns: + + EFI_SUCCESS when done searching the entire database. + +--*/ +{ + EFI_STATUS Status; + + do { + Status = CoreUnregisterProtocolNotifyEvent (Event); + } while (!EFI_ERROR (Status)); + + return EFI_SUCCESS; +} + + + +EFI_STATUS +EFIAPI +CoreInstallProtocolInterface ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface + ) +/*++ + +Routine Description: + + Wrapper function to CoreInstallProtocolInterfaceNotify. This is the public API which + Calls the private one which contains a BOOLEAN parameter for notifications + +Arguments: + + UserHandle - The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + + Protocol - The protocol to add to the handle + + InterfaceType - Indicates whether Interface is supplied in native form. + + Interface - The interface for the protocol being added + +Returns: + + Status code + +--*/ +{ + return CoreInstallProtocolInterfaceNotify ( + UserHandle, + Protocol, + InterfaceType, + Interface, + TRUE + ); +} + +EFI_STATUS +CoreInstallProtocolInterfaceNotify ( + IN OUT EFI_HANDLE *UserHandle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface, + IN BOOLEAN Notify + ) +/*++ + +Routine Description: + + Installs a protocol interface into the boot services environment. + +Arguments: + + UserHandle - The handle to install the protocol handler on, + or NULL if a new handle is to be allocated + + Protocol - The protocol to add to the handle + + InterfaceType - Indicates whether Interface is supplied in native form. + + Interface - The interface for the protocol being added + + Notify - indicates whether notify the notification list + for this protocol + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Protocol interface successfully installed + +--*/ +{ + PROTOCOL_INTERFACE *Prot; + PROTOCOL_ENTRY *ProtEntry; + IHANDLE *Handle; + EFI_STATUS Status; + VOID *ExistingInterface; + + // + // returns EFI_INVALID_PARAMETER if InterfaceType is invalid. + // Also added check for invalid UserHandle and Protocol pointers. + // + if (UserHandle == NULL || Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (InterfaceType != EFI_NATIVE_INTERFACE) { + return EFI_INVALID_PARAMETER; + } + + // + // Print debug message + // + DEBUG((EFI_D_ERROR | EFI_D_INFO, "InstallProtocolInterface: %g %x\n", Protocol, Interface)); + + Status = EFI_OUT_OF_RESOURCES; + Prot = NULL; + Handle = NULL; + + ASSERT (NULL != gBS); + + if (*UserHandle != NULL_HANDLE) { + Status = CoreHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface); + if (!EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + } + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Lookup the Protocol Entry for the requested protocol + // + ProtEntry = CoreFindProtocolEntry (Protocol, TRUE); + if (ProtEntry == NULL) { + goto Done; + } + + // + // Allocate a new protocol interface structure + // + Prot = CoreAllocateZeroBootServicesPool (sizeof(PROTOCOL_INTERFACE)); + if (Prot == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // If caller didn't supply a handle, allocate a new one + // + Handle = (IHANDLE *)*UserHandle; + if (Handle == NULL) { + Handle = CoreAllocateZeroBootServicesPool (sizeof(IHANDLE)); + if (Handle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Initialize new handler structure + // + Handle->Signature = EFI_HANDLE_SIGNATURE; + InitializeListHead (&Handle->Protocols); + + // + // Initialize the Key to show that the handle has been created/modified + // + gHandleDatabaseKey++; + Handle->Key = gHandleDatabaseKey; + + // + // Add this handle to the list global list of all handles + // in the system + // + InsertTailList (&gHandleList, &Handle->AllHandles); + } + + Status = CoreValidateHandle (Handle); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Each interface that is added must be unique + // + ASSERT (CoreFindProtocolInterface (Handle, Protocol, Interface) == NULL); + + // + // Initialize the protocol interface structure + // + Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE; + Prot->Handle = Handle; + Prot->Protocol = ProtEntry; + Prot->Interface = Interface; + + // + // Initalize OpenProtocol Data base + // + InitializeListHead (&Prot->OpenList); + Prot->OpenListCount = 0; + + // + // Add this protocol interface to the head of the supported + // protocol list for this handle + // + InsertHeadList (&Handle->Protocols, &Prot->Link); + + // + // Add this protocol interface to the tail of the + // protocol entry + // + InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol); + + // + // Notify the notification list for this protocol + // + if (Notify) { + CoreNotifyProtocolEntry (ProtEntry); + } + Status = EFI_SUCCESS; + +Done: + // + // Done, unlock the database and return + // + CoreReleaseProtocolLock (); + if (!EFI_ERROR (Status)) { + // + // Return the new handle back to the caller + // + *UserHandle = Handle; + } else { + // + // There was an error, clean up + // + if (Prot != NULL) { + CoreFreePool (Prot); + } + } + + return Status; +} + + + +EFI_STATUS +EFIAPI +CoreInstallMultipleProtocolInterfaces ( + IN OUT EFI_HANDLE *Handle, + ... + ) +/*++ + +Routine Description: + + Installs a list of protocol interface into the boot services environment. + This function calls InstallProtocolInterface() in a loop. If any error + occures all the protocols added by this function are removed. This is + basically a lib function to save space. + +Arguments: + + Handle - The handle to install the protocol handlers on, + or NULL if a new handle is to be allocated + ... - EFI_GUID followed by protocol instance. A NULL terminates the + list. The pairs are the arguments to InstallProtocolInterface(). + All the protocols are added to Handle. + +Returns: + + EFI_INVALID_PARAMETER - Handle is NULL. + + EFI_SUCCESS - Protocol interfaces successfully installed. + +--*/ +{ + VA_LIST args; + EFI_STATUS Status; + EFI_GUID *Protocol; + VOID *Interface; + EFI_TPL OldTpl; + UINTN Index; + EFI_HANDLE OldHandle; + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if (Handle == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Syncronize with notifcations. + // + OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY); + OldHandle = *Handle; + + // + // Check for duplicate device path and install the protocol interfaces + // + VA_START (args, Handle); + for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) { + // + // If protocol is NULL, then it's the end of the list + // + Protocol = VA_ARG (args, EFI_GUID *); + if (Protocol == NULL) { + break; + } + + Interface = VA_ARG (args, VOID *); + + // + // Make sure you are installing on top a device path that has already been added. + // + if (CompareGuid (Protocol, &gEfiDevicePathProtocolGuid)) { + DeviceHandle = NULL; + DevicePath = Interface; + Status = CoreLocateDevicePath (&gEfiDevicePathProtocolGuid, &DevicePath, &DeviceHandle); + if (!EFI_ERROR (Status) && (DeviceHandle != NULL_HANDLE) && IsDevicePathEnd(DevicePath)) { + Status = EFI_ALREADY_STARTED; + continue; + } + } + + // + // Install it + // + Status = CoreInstallProtocolInterface (Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); + } + + // + // If there was an error, remove all the interfaces that were installed without any errors + // + if (EFI_ERROR (Status)) { + // + // Reset the va_arg back to the first argument. + // + VA_START (args, Handle); + for (; Index > 1; Index--) { + Protocol = VA_ARG (args, EFI_GUID *); + Interface = VA_ARG (args, VOID *); + CoreUninstallProtocolInterface (*Handle, Protocol, Interface); + } + *Handle = OldHandle; + } + + // + // Done + // + CoreRestoreTpl (OldTpl); + return Status; +} + +EFI_STATUS +CoreDisconnectControllersUsingProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN PROTOCOL_INTERFACE *Prot + ) +/*++ + +Routine Description: + + Attempts to disconnect all drivers that are using the protocol interface being queried. + If failed, reconnect all drivers disconnected. + + Note: This function doesn't do parameters checking, it's caller's responsibility + to pass in valid parameters. + +Arguments: + + UserHandle - The handle on which the protocol is installed + Prot - The protocol to disconnect drivers from + +Returns: + + EFI_SUCCESS - Drivers using the protocol interface are all disconnected + EFI_ACCESS_DENIED - Failed to disconnect one or all of the drivers + +--*/ +{ + EFI_STATUS Status; + BOOLEAN ItemFound; + LIST_ENTRY *Link; + OPEN_PROTOCOL_DATA *OpenData; + + Status = EFI_SUCCESS; + + // + // Attempt to disconnect all drivers from this protocol interface + // + do { + ItemFound = FALSE; + for ( Link = Prot->OpenList.ForwardLink; + (Link != &Prot->OpenList) && !ItemFound; + Link = Link->ForwardLink ) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) { + ItemFound = TRUE; + CoreReleaseProtocolLock (); + Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL); + CoreAcquireProtocolLock (); + if (EFI_ERROR (Status)) { + ItemFound = FALSE; + break; + } + } + } + } while (ItemFound); + + if (!EFI_ERROR (Status)) { + // + // Attempt to remove BY_HANDLE_PROTOOCL and GET_PROTOCOL and TEST_PROTOCOL Open List items + // + do { + ItemFound = FALSE; + for ( Link = Prot->OpenList.ForwardLink; + (Link != &Prot->OpenList) && !ItemFound; + Link = Link->ForwardLink ) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if (OpenData->Attributes & + (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) { + ItemFound = TRUE; + RemoveEntryList (&OpenData->Link); + Prot->OpenListCount--; + CoreFreePool (OpenData); + } + } + } while (ItemFound); + } + + // + // If there are errors or still has open items in the list, then reconnect all the drivers and return an error + // + if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) { + CoreReleaseProtocolLock (); + CoreConnectController (UserHandle, NULL, NULL, TRUE); + CoreAcquireProtocolLock (); + Status = EFI_ACCESS_DENIED; + } + + return Status; +} + + +EFI_STATUS +EFIAPI +CoreUninstallProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +/*++ + +Routine Description: + + Uninstalls all instances of a protocol:interfacer from a handle. + If the last protocol interface is remove from the handle, the + handle is freed. + +Arguments: + + UserHandle - The handle to remove the protocol handler from + + Protocol - The protocol, of protocol:interface, to remove + + Interface - The interface, of protocol:interface, to remove + +Returns: + + EFI_INVALID_PARAMETER - Protocol is NULL. + + EFI_SUCCESS - Protocol interface successfully uninstalled. + +--*/ +{ + EFI_STATUS Status; + IHANDLE *Handle; + PROTOCOL_INTERFACE *Prot; + + // + // Check that Protocol is valid + // + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check that UserHandle is a valid handle + // + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Check that Protocol exists on UserHandle, and Interface matches the interface in the database + // + Prot = CoreFindProtocolInterface (UserHandle, Protocol, Interface); + if (Prot == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + + // + // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed + // + Status = CoreDisconnectControllersUsingProtocolInterface ( + UserHandle, + Prot + ); + if (EFI_ERROR (Status)) { + // + // One or more drivers refused to release, so return the error + // + goto Done; + } + + // + // Remove the protocol interface from the protocol + // + Status = EFI_NOT_FOUND; + Handle = (IHANDLE *)UserHandle; + Prot = CoreRemoveInterfaceFromProtocol (Handle, Protocol, Interface); + + if (Prot != NULL) { + // + // Update the Key to show that the handle has been created/modified + // + gHandleDatabaseKey++; + Handle->Key = gHandleDatabaseKey; + + // + // Remove the protocol interface from the handle + // + RemoveEntryList (&Prot->Link); + + // + // Free the memory + // + Prot->Signature = 0; + CoreFreePool (Prot); + Status = EFI_SUCCESS; + } + + // + // If there are no more handlers for the handle, free the handle + // + if (IsListEmpty (&Handle->Protocols)) { + Handle->Signature = 0; + RemoveEntryList (&Handle->AllHandles); + CoreFreePool (Handle); + } + +Done: + // + // Done, unlock the database and return + // + CoreReleaseProtocolLock (); + return Status; +} + + + +EFI_STATUS +EFIAPI +CoreUninstallMultipleProtocolInterfaces ( + IN EFI_HANDLE Handle, + ... + ) +/*++ + +Routine Description: + + Uninstalls a list of protocol interface in the boot services environment. + This function calls UnisatllProtocolInterface() in a loop. This is + basically a lib function to save space. + +Arguments: + + Handle - The handle to uninstall the protocol + + ... - EFI_GUID followed by protocol instance. A NULL terminates the + list. The pairs are the arguments to UninstallProtocolInterface(). + All the protocols are added to Handle. + +Returns: + + Status code + +--*/ +{ + EFI_STATUS Status; + VA_LIST args; + EFI_GUID *Protocol; + VOID *Interface; + UINTN Index; + + VA_START (args, Handle); + for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) { + // + // If protocol is NULL, then it's the end of the list + // + Protocol = VA_ARG (args, EFI_GUID *); + if (Protocol == NULL) { + break; + } + + Interface = VA_ARG (args, VOID *); + + // + // Uninstall it + // + Status = CoreUninstallProtocolInterface (Handle, Protocol, Interface); + } + + // + // If there was an error, add all the interfaces that were + // uninstalled without any errors + // + if (EFI_ERROR (Status)) { + // + // Reset the va_arg back to the first argument. + // + VA_START (args, Handle); + for (; Index > 1; Index--) { + Protocol = VA_ARG(args, EFI_GUID *); + Interface = VA_ARG(args, VOID *); + CoreInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface); + } + } + + return Status; +} + +PROTOCOL_INTERFACE * +CoreGetProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol + ) +/*++ + +Routine Description: + + Locate a certain GUID protocol interface in a Handle's protocols. + +Arguments: + + UserHandle - The handle to obtain the protocol interface on + + Protocol - The GUID of the protocol + +Returns: + + The requested protocol interface for the handle + +--*/ +{ + EFI_STATUS Status; + PROTOCOL_ENTRY *ProtEntry; + PROTOCOL_INTERFACE *Prot; + IHANDLE *Handle; + LIST_ENTRY *Link; + + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return NULL; + } + + Handle = (IHANDLE *)UserHandle; + + // + // Look at each protocol interface for a match + // + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + ProtEntry = Prot->Protocol; + if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) { + return Prot; + } + } + return NULL; +} + + +EFI_STATUS +EFIAPI +CoreHandleProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface + ) +/*++ + +Routine Description: + + Queries a handle to determine if it supports a specified protocol. + +Arguments: + + UserHandle - The handle being queried. + + Protocol - The published unique identifier of the protocol. + + Interface - Supplies the address where a pointer to the corresponding Protocol + Interface is returned. + +Returns: + + The requested protocol interface for the handle + +--*/ +{ + return CoreOpenProtocol ( + UserHandle, + Protocol, + Interface, + gDxeCoreImageHandle, + NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); +} + + +EFI_STATUS +EFIAPI +CoreOpenProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT VOID **Interface OPTIONAL, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE ControllerHandle, + IN UINT32 Attributes + ) +/*++ + +Routine Description: + + Locates the installed protocol handler for the handle, and + invokes it to obtain the protocol interface. Usage information + is registered in the protocol data base. + +Arguments: + + UserHandle - The handle to obtain the protocol interface on + + Protocol - The ID of the protocol + + Interface - The location to return the protocol interface + + ImageHandle - The handle of the Image that is opening the protocol interface + specified by Protocol and Interface. + + ControllerHandle - The controller handle that is requiring this interface. + + Attributes - The open mode of the protocol interface specified by Handle + and Protocol. + +Returns: + + EFI_INVALID_PARAMETER - Protocol is NULL. + + EFI_SUCCESS - Get the protocol interface. + +--*/ +{ + EFI_STATUS Status; + PROTOCOL_INTERFACE *Prot; + LIST_ENTRY *Link; + OPEN_PROTOCOL_DATA *OpenData; + BOOLEAN ByDriver; + BOOLEAN Exclusive; + BOOLEAN Disconnect; + BOOLEAN ExactMatch; + + // + // Check for invalid Protocol + // + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check for invalid Interface + // + if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) { + if (Interface == NULL) { + return EFI_INVALID_PARAMETER; + } else { + *Interface = NULL; + } + } + + // + // Check for invalid UserHandle + // + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Check for invalid Attributes + // + switch (Attributes) { + case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER : + Status = CoreValidateHandle (ImageHandle); + if (EFI_ERROR (Status)) { + return Status; + } + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + return Status; + } + if (UserHandle == ControllerHandle) { + return EFI_INVALID_PARAMETER; + } + break; + case EFI_OPEN_PROTOCOL_BY_DRIVER : + case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE : + Status = CoreValidateHandle (ImageHandle); + if (EFI_ERROR (Status)) { + return Status; + } + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + return Status; + } + break; + case EFI_OPEN_PROTOCOL_EXCLUSIVE : + Status = CoreValidateHandle (ImageHandle); + if (EFI_ERROR (Status)) { + return Status; + } + break; + case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL : + case EFI_OPEN_PROTOCOL_GET_PROTOCOL : + case EFI_OPEN_PROTOCOL_TEST_PROTOCOL : + break; + default: + return EFI_INVALID_PARAMETER; + } + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Look at each protocol interface for a match + // + Prot = CoreGetProtocolInterface (UserHandle, Protocol); + if (Prot == NULL) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + // + // This is the protocol interface entry for this protocol + // + if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) { + *Interface = Prot->Interface; + } + Status = EFI_SUCCESS; + + ByDriver = FALSE; + Exclusive = FALSE; + for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) && + (OpenData->Attributes == Attributes) && + (OpenData->ControllerHandle == ControllerHandle)); + if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) { + ByDriver = TRUE; + if (ExactMatch) { + Status = EFI_ALREADY_STARTED; + goto Done; + } + } + if (OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) { + Exclusive = TRUE; + } else if (ExactMatch) { + OpenData->OpenCount++; + Status = EFI_SUCCESS; + goto Done; + } + } + + // + // ByDriver TRUE -> A driver is managing (UserHandle, Protocol) + // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol) + // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol) + // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol) + // + + switch (Attributes) { + case EFI_OPEN_PROTOCOL_BY_DRIVER : + if (Exclusive || ByDriver) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + break; + case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE : + case EFI_OPEN_PROTOCOL_EXCLUSIVE : + if (Exclusive) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + if (ByDriver) { + do { + Disconnect = FALSE; + for ( Link = Prot->OpenList.ForwardLink; (Link != &Prot->OpenList) && (!Disconnect); Link = Link->ForwardLink) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + if (OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) { + Disconnect = TRUE; + CoreReleaseProtocolLock (); + Status = CoreDisconnectController (UserHandle, OpenData->AgentHandle, NULL); + CoreAcquireProtocolLock (); + if (EFI_ERROR (Status)) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + } + } + } while (Disconnect); + } + break; + case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER : + case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL : + case EFI_OPEN_PROTOCOL_GET_PROTOCOL : + case EFI_OPEN_PROTOCOL_TEST_PROTOCOL : + break; + } + + if (ImageHandle == NULL) { + Status = EFI_SUCCESS; + goto Done; + } + // + // Create new entry + // + OpenData = CoreAllocateBootServicesPool (sizeof(OPEN_PROTOCOL_DATA)); + if (OpenData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } else { + OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE; + OpenData->AgentHandle = ImageHandle; + OpenData->ControllerHandle = ControllerHandle; + OpenData->Attributes = Attributes; + OpenData->OpenCount = 1; + InsertTailList (&Prot->OpenList, &OpenData->Link); + Prot->OpenListCount++; + Status = EFI_SUCCESS; + } + +Done: + // + // Done. Release the database lock are return + // + CoreReleaseProtocolLock (); + return Status; +} + + +EFI_STATUS +EFIAPI +CoreCloseProtocol ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle + ) +/*++ + +Routine Description: + + Closes a protocol on a handle that was opened using OpenProtocol(). + +Arguments: + + UserHandle - The handle for the protocol interface that was previously opened + with OpenProtocol(), and is now being closed. + Protocol - The published unique identifier of the protocol. It is the caller¡¯s + responsibility to pass in a valid GUID. + AgentHandle - The handle of the agent that is closing the protocol interface. + ControllerHandle - If the agent that opened a protocol is a driver that follows the + EFI Driver Model, then this parameter is the controller handle + that required the protocol interface. If the agent does not follow + the EFI Driver Model, then this parameter is optional and may be NULL. + +Returns: + + EFI_SUCCESS - The protocol instance was closed. + EFI_INVALID_PARAMETER - Handle, AgentHandle or ControllerHandle is not a valid EFI_HANDLE. + EFI_NOT_FOUND - Can not find the specified protocol or AgentHandle. + +--*/ +{ + EFI_STATUS Status; + PROTOCOL_INTERFACE *ProtocolInterface; + LIST_ENTRY *Link; + OPEN_PROTOCOL_DATA *OpenData; + + // + // Check for invalid parameters + // + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + Status = CoreValidateHandle (AgentHandle); + if (EFI_ERROR (Status)) { + return Status; + } + if (ControllerHandle != NULL_HANDLE) { + Status = CoreValidateHandle (ControllerHandle); + if (EFI_ERROR (Status)) { + return Status; + } + } + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Look at each protocol interface for a match + // + Status = EFI_NOT_FOUND; + ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol); + if (ProtocolInterface == NULL) { + goto Done; + } + + // + // Walk the Open data base looking for AgentHandle + // + Link = ProtocolInterface->OpenList.ForwardLink; + while (Link != &ProtocolInterface->OpenList) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + Link = Link->ForwardLink; + if ((OpenData->AgentHandle == AgentHandle) && (OpenData->ControllerHandle == ControllerHandle)) { + RemoveEntryList (&OpenData->Link); + ProtocolInterface->OpenListCount--; + CoreFreePool (OpenData); + Status = EFI_SUCCESS; + } + } + +Done: + // + // Done. Release the database lock and return. + // + CoreReleaseProtocolLock (); + return Status; +} + + + +EFI_STATUS +EFIAPI +CoreOpenProtocolInformation ( + IN EFI_HANDLE UserHandle, + IN EFI_GUID *Protocol, + OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + OUT UINTN *EntryCount + ) +/*++ + +Routine Description: + + Return information about Opened protocols in the system + +Arguments: + + UserHandle - The handle to close the protocol interface on + + Protocol - The ID of the protocol + + EntryBuffer - A pointer to a buffer of open protocol information in the form of + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures. + + EntryCount - Number of EntryBuffer entries + +Returns: + + +--*/ +{ + EFI_STATUS Status; + PROTOCOL_INTERFACE *ProtocolInterface; + LIST_ENTRY *Link; + OPEN_PROTOCOL_DATA *OpenData; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *Buffer; + UINTN Count; + UINTN Size; + + *EntryBuffer = NULL; + *EntryCount = 0; + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + // + // Look at each protocol interface for a match + // + Status = EFI_NOT_FOUND; + ProtocolInterface = CoreGetProtocolInterface (UserHandle, Protocol); + if (ProtocolInterface == NULL) { + goto Done; + } + + // + // Count the number of Open Entries + // + for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0; + (Link != &ProtocolInterface->OpenList) ; + Link = Link->ForwardLink ) { + Count++; + } + + ASSERT (Count == ProtocolInterface->OpenListCount); + + if (Count == 0) { + Size = sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY); + } else { + Size = Count * sizeof(EFI_OPEN_PROTOCOL_INFORMATION_ENTRY); + } + + Buffer = CoreAllocateBootServicesPool (Size); + if (Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status = EFI_SUCCESS; + for ( Link = ProtocolInterface->OpenList.ForwardLink, Count = 0; + (Link != &ProtocolInterface->OpenList); + Link = Link->ForwardLink, Count++ ) { + OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE); + + Buffer[Count].AgentHandle = OpenData->AgentHandle; + Buffer[Count].ControllerHandle = OpenData->ControllerHandle; + Buffer[Count].Attributes = OpenData->Attributes; + Buffer[Count].OpenCount = OpenData->OpenCount; + } + + *EntryBuffer = Buffer; + *EntryCount = Count; + +Done: + // + // Done. Release the database lock are return + // + CoreReleaseProtocolLock (); + return Status; +} + + + +EFI_STATUS +EFIAPI +CoreProtocolsPerHandle ( + IN EFI_HANDLE UserHandle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount + ) +/*++ + +Routine Description: + + Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated + from pool. + +Arguments: + + UserHandle - The handle from which to retrieve the list of protocol interface + GUIDs. + + ProtocolBuffer - A pointer to the list of protocol interface GUID pointers that are + installed on Handle. + + ProtocolBufferCount - A pointer to the number of GUID pointers present in + ProtocolBuffer. + +Returns: + EFI_SUCCESS - The list of protocol interface GUIDs installed on Handle was returned in + ProtocolBuffer. The number of protocol interface GUIDs was + returned in ProtocolBufferCount. + EFI_INVALID_PARAMETER - Handle is NULL. + EFI_INVALID_PARAMETER - Handle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ProtocolBuffer is NULL. + EFI_INVALID_PARAMETER - ProtocolBufferCount is NULL. + EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the results. + +--*/ +{ + EFI_STATUS Status; + IHANDLE *Handle; + PROTOCOL_INTERFACE *Prot; + LIST_ENTRY *Link; + UINTN ProtocolCount; + EFI_GUID **Buffer; + + Status = CoreValidateHandle (UserHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + Handle = (IHANDLE *)UserHandle; + + if (ProtocolBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (ProtocolBufferCount == NULL) { + return EFI_INVALID_PARAMETER; + } + + *ProtocolBufferCount = 0; + + ProtocolCount = 0; + + CoreAcquireProtocolLock (); + + for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) { + ProtocolCount++; + } + + // + // If there are no protocol interfaces installed on Handle, then Handle is not a valid EFI_HANDLE + // + if (ProtocolCount == 0) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + Buffer = CoreAllocateBootServicesPool (sizeof (EFI_GUID *) * ProtocolCount); + if (Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + *ProtocolBuffer = Buffer; + *ProtocolBufferCount = ProtocolCount; + + for ( Link = Handle->Protocols.ForwardLink, ProtocolCount = 0; + Link != &Handle->Protocols; + Link = Link->ForwardLink, ProtocolCount++) { + Prot = CR(Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE); + Buffer[ProtocolCount] = &(Prot->Protocol->ProtocolID); + } + Status = EFI_SUCCESS; + +Done: + CoreReleaseProtocolLock (); + return Status; +} + + +UINT64 +CoreGetHandleDatabaseKey ( + VOID + ) +/*++ + +Routine Description: + + return handle database key. + +Arguments: + + None + +Returns: + + Handle database key. + +--*/ +{ + return gHandleDatabaseKey; +} + + +VOID +CoreConnectHandlesByKey ( + UINT64 Key + ) +/*++ + +Routine Description: + + Go connect any handles that were created or modified while a image executed. + +Arguments: + + Key - The Key to show that the handle has been created/modified + +Returns: + + None +--*/ +{ + UINTN Count; + LIST_ENTRY *Link; + EFI_HANDLE *HandleBuffer; + IHANDLE *Handle; + UINTN Index; + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) { + Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); + if (Handle->Key > Key) { + Count++; + } + } + + HandleBuffer = CoreAllocateBootServicesPool (Count * sizeof (EFI_HANDLE)); + if (HandleBuffer == NULL) { + CoreReleaseProtocolLock (); + return; + } + + for (Link = gHandleList.ForwardLink, Count = 0; Link != &gHandleList; Link = Link->ForwardLink) { + Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); + if (Handle->Key > Key) { + HandleBuffer[Count++] = Handle; + } + } + + // + // Unlock the protocol database + // + CoreReleaseProtocolLock (); + + // + // Connect all handles whose Key value is greater than Key + // + for (Index = 0; Index < Count; Index++) { + CoreConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + + CoreFreePool(HandleBuffer); +} diff --git a/EdkModulePkg/Core/Dxe/Hand/locate.c b/EdkModulePkg/Core/Dxe/Hand/locate.c new file mode 100644 index 0000000000..faa4255c7e --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Hand/locate.c @@ -0,0 +1,737 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + locate.c + +Abstract: + + Locate handle functions + +Revision History + +--*/ + +#include + +// +// ProtocolRequest - Last LocateHandle request ID +// +UINTN mEfiLocateHandleRequest = 0; + +// +// Internal prototypes +// + +typedef struct { + EFI_GUID *Protocol; + VOID *SearchKey; + LIST_ENTRY *Position; + PROTOCOL_ENTRY *ProtEntry; +} LOCATE_POSITION; + +typedef +IHANDLE * +(* CORE_GET_NEXT) ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ); + +STATIC +IHANDLE * +CoreGetNextLocateAllHandles ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ); + +STATIC +IHANDLE * +CoreGetNextLocateByRegisterNotify ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ); + +STATIC +IHANDLE * +CoreGetNextLocateByProtocol ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ); + +// +// +// + + + + +EFI_STATUS +EFIAPI +CoreLocateHandle ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer + ) +/*++ + +Routine Description: + + Locates the requested handle(s) and returns them in Buffer. + +Arguments: + + SearchType - The type of search to perform to locate the handles + + Protocol - The protocol to search for + + SearchKey - Dependant on SearchType + + BufferSize - On input the size of Buffer. On output the + size of data returned. + + Buffer - The buffer to return the results in + + +Returns: + + EFI_BUFFER_TOO_SMALL - Buffer too small, required buffer size is returned in BufferSize. + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_SUCCESS - Successfully found the requested handle(s) and returns them in Buffer. + +--*/ +{ + EFI_STATUS Status; + LOCATE_POSITION Position; + PROTOCOL_NOTIFY *ProtNotify; + CORE_GET_NEXT GetNext; + UINTN ResultSize; + IHANDLE *Handle; + IHANDLE **ResultBuffer; + VOID *Interface; + + if (BufferSize == NULL) { + Status = EFI_INVALID_PARAMETER; + } + + if ((*BufferSize > 0) && (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + GetNext = NULL; + // + // Set initial position + // + + Position.Protocol = Protocol; + Position.SearchKey = SearchKey; + Position.Position = &gHandleList; + + ResultSize = 0; + ResultBuffer = (IHANDLE **) Buffer; + Status = EFI_SUCCESS; + + // + // Lock the protocol database + // + + CoreAcquireProtocolLock (); + + // + // Get the search function based on type + // + switch (SearchType) { + case AllHandles: + GetNext = CoreGetNextLocateAllHandles; + break; + + case ByRegisterNotify: + // + // Must have SearchKey for locate ByRegisterNotify + // + if (SearchKey == NULL) { + Status = EFI_INVALID_PARAMETER; + break; + } + GetNext = CoreGetNextLocateByRegisterNotify; + break; + + case ByProtocol: + GetNext = CoreGetNextLocateByProtocol; + if (Protocol == NULL) { + Status = EFI_INVALID_PARAMETER; + break; + } + // + // Look up the protocol entry and set the head pointer + // + Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE); + if (Position.ProtEntry == NULL) { + Status = EFI_NOT_FOUND; + break; + } + Position.Position = &Position.ProtEntry->Protocols; + break; + + default: + Status = EFI_INVALID_PARAMETER; + break; + } + + if (EFI_ERROR(Status)) { + CoreReleaseProtocolLock (); + return Status; + } + + // + // Enumerate out the matching handles + // + mEfiLocateHandleRequest += 1; + for (; ;) { + // + // Get the next handle. If no more handles, stop + // + Handle = GetNext (&Position, &Interface); + if (NULL == Handle) { + break; + } + + // + // Increase the resulting buffer size, and if this handle + // fits return it + // + ResultSize += sizeof(Handle); + if (ResultSize <= *BufferSize) { + *ResultBuffer = Handle; + ResultBuffer += 1; + } + } + + // + // If the result is a zero length buffer, then there were no + // matching handles + // + if (ResultSize == 0) { + Status = EFI_NOT_FOUND; + } else { + // + // Return the resulting buffer size. If it's larger than what + // was passed, then set the error code + // + if (ResultSize > *BufferSize) { + Status = EFI_BUFFER_TOO_SMALL; + } + + *BufferSize = ResultSize; + + if (SearchType == ByRegisterNotify && !EFI_ERROR(Status)) { + // + // If this is a search by register notify and a handle was + // returned, update the register notification position + // + ProtNotify = SearchKey; + ProtNotify->Position = ProtNotify->Position->ForwardLink; + } + } + + CoreReleaseProtocolLock (); + return Status; +} + + +STATIC +IHANDLE * +CoreGetNextLocateAllHandles ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ) +/*++ + +Routine Description: + + Routine to get the next Handle, when you are searching for all handles. + +Arguments: + + Position - Information about which Handle to seach for. + + Interface - Return the interface structure for the matching protocol. + +Returns: + IHANDLE - An IHANDLE is returned if the next Position is not the end of the + list. A NULL_HANDLE is returned if it's the end of the list. + +--*/ +{ + IHANDLE *Handle; + + // + // Next handle + // + Position->Position = Position->Position->ForwardLink; + + // + // If not at the end of the list, get the handle + // + Handle = NULL_HANDLE; + *Interface = NULL; + if (Position->Position != &gHandleList) { + Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE); + } + + return Handle; +} + + +STATIC +IHANDLE * +CoreGetNextLocateByRegisterNotify ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ) +/*++ + +Routine Description: + + Routine to get the next Handle, when you are searching for register protocol + notifies. + +Arguments: + + Position - Information about which Handle to seach for. + + Interface - Return the interface structure for the matching protocol. + +Returns: + IHANDLE - An IHANDLE is returned if the next Position is not the end of the + list. A NULL_HANDLE is returned if it's the end of the list. + +--*/ +{ + IHANDLE *Handle; + PROTOCOL_NOTIFY *ProtNotify; + PROTOCOL_INTERFACE *Prot; + LIST_ENTRY *Link; + + Handle = NULL_HANDLE; + *Interface = NULL; + ProtNotify = Position->SearchKey; + + // + // If this is the first request, get the next handle + // + if (ProtNotify != NULL) { + ASSERT(ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE); + Position->SearchKey = NULL; + + // + // If not at the end of the list, get the next handle + // + Link = ProtNotify->Position->ForwardLink; + if (Link != &ProtNotify->Protocol->Protocols) { + Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE); + Handle = (IHANDLE *) Prot->Handle; + *Interface = Prot->Interface; + } + } + + return Handle; +} + + +STATIC +IHANDLE * +CoreGetNextLocateByProtocol ( + IN OUT LOCATE_POSITION *Position, + OUT VOID **Interface + ) +/*++ + +Routine Description: + + Routine to get the next Handle, when you are searching for a given protocol. + +Arguments: + + Position - Information about which Handle to seach for. + + Interface - Return the interface structure for the matching protocol. + +Returns: + IHANDLE - An IHANDLE is returned if the next Position is not the end of the + list. A NULL_HANDLE is returned if it's the end of the list. + +--*/ +{ + IHANDLE *Handle; + LIST_ENTRY *Link; + PROTOCOL_INTERFACE *Prot; + + Handle = NULL_HANDLE; + *Interface = NULL; + for (; ;) { + // + // Next entry + // + Link = Position->Position->ForwardLink; + Position->Position = Link; + + // + // If not at the end, return the handle + // + if (Link == &Position->ProtEntry->Protocols) { + Handle = NULL_HANDLE; + break; + } + + // + // Get the handle + // + Prot = CR(Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE); + Handle = (IHANDLE *) Prot->Handle; + *Interface = Prot->Interface; + + // + // If this handle has not been returned this request, then + // return it now + // + if (Handle->LocateRequest != mEfiLocateHandleRequest) { + Handle->LocateRequest = mEfiLocateHandleRequest; + break; + } + } + + return Handle; +} + + + +EFI_STATUS +EFIAPI +CoreLocateDevicePath ( + IN EFI_GUID *Protocol, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT EFI_HANDLE *Device + ) +/*++ + +Routine Description: + + Locates the handle to a device on the device path that best matches the specified protocol. + +Arguments: + + Protocol - The protocol to search for. + DevicePath - On input, a pointer to a pointer to the device path. On output, the device + path pointer is modified to point to the remaining part of the devicepath. + Device - A pointer to the returned device handle. + +Returns: + + EFI_SUCCESS - The resulting handle was returned. + EFI_NOT_FOUND - No handles matched the search. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + +--*/ +{ + INTN SourceSize; + INTN Size; + INTN BestMatch; + UINTN HandleCount; + UINTN Index; + EFI_STATUS Status; + EFI_HANDLE *Handles; + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *SourcePath; + EFI_DEVICE_PATH_PROTOCOL *TmpDevicePath; + + if (Protocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + if ((DevicePath == NULL) || (*DevicePath == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (Device == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Device = NULL_HANDLE; + SourcePath = *DevicePath; + SourceSize = CoreDevicePathSize (SourcePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL); + + // + // The source path can only have 1 instance + // + if (CoreIsDevicePathMultiInstance (SourcePath)) { + DEBUG((EFI_D_ERROR, "LocateDevicePath: Device path has too many instances\n")); + return EFI_INVALID_PARAMETER; + } + + // + // Get a list of all handles that support the requested protocol + // + Status = CoreLocateHandleBuffer (ByProtocol, Protocol, NULL, &HandleCount, &Handles); + if (EFI_ERROR (Status) || HandleCount == 0) { + return EFI_NOT_FOUND; + } + + BestMatch = -1; + for(Index = 0; Index < HandleCount; Index += 1) { + Handle = Handles[Index]; + Status = CoreHandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID **)&TmpDevicePath); + if (EFI_ERROR (Status)) { + // + // If this handle doesn't support device path, then skip it + // + continue; + } + + // + // Check if DevicePath is first part of SourcePath + // + Size = CoreDevicePathSize (TmpDevicePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL); + if ((Size <= SourceSize) && CompareMem (SourcePath, TmpDevicePath, Size) == 0) { + // + // If the size is equal to the best match, then we + // have a duplice device path for 2 different device + // handles + // + ASSERT (Size != BestMatch); + + // + // We've got a match, see if it's the best match so far + // + if (Size > BestMatch) { + BestMatch = Size; + *Device = Handle; + } + } + } + + CoreFreePool (Handles); + + // + // If there wasn't any match, then no parts of the device path was found. + // Which is strange since there is likely a "root level" device path in the system. + // + if (BestMatch == -1) { + return EFI_NOT_FOUND; + } + + // + // Return the remaining part of the device path + // + *DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) SourcePath) + BestMatch); + return EFI_SUCCESS; +} + + + +EFI_STATUS +EFIAPI +CoreLocateProtocol ( + IN EFI_GUID *Protocol, + IN VOID *Registration OPTIONAL, + OUT VOID **Interface + ) +/*++ + +Routine Description: + + Return the first Protocol Interface that matches the Protocol GUID. If + Registration is pasased in return a Protocol Instance that was just add + to the system. If Retistration is NULL return the first Protocol Interface + you find. + +Arguments: + + Protocol - The protocol to search for + + Registration - Optional Registration Key returned from RegisterProtocolNotify() + + Interface - Return the Protocol interface (instance). + +Returns: + + EFI_SUCCESS - If a valid Interface is returned + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_NOT_FOUND - Protocol interface not found + +--*/ +{ + EFI_STATUS Status; + LOCATE_POSITION Position; + PROTOCOL_NOTIFY *ProtNotify; + IHANDLE *Handle; + + if (Interface == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Protocol == NULL) { + return EFI_NOT_FOUND; + } + + *Interface = NULL; + Status = EFI_SUCCESS; + + // + // Set initial position + // + Position.Protocol = Protocol; + Position.SearchKey = Registration; + Position.Position = &gHandleList; + + // + // Lock the protocol database + // + CoreAcquireProtocolLock (); + + mEfiLocateHandleRequest += 1; + + if (NULL == Registration) { + // + // Look up the protocol entry and set the head pointer + // + Position.ProtEntry = CoreFindProtocolEntry (Protocol, FALSE); + if (Position.ProtEntry == NULL) { + Status = EFI_NOT_FOUND; + goto Done; + } + Position.Position = &Position.ProtEntry->Protocols; + + Handle = CoreGetNextLocateByProtocol (&Position, Interface); + } else { + Handle = CoreGetNextLocateByRegisterNotify (&Position, Interface); + } + + if (NULL == Handle) { + Status = EFI_NOT_FOUND; + } else if (NULL != Registration) { + // + // If this is a search by register notify and a handle was + // returned, update the register notification position + // + ProtNotify = Registration; + ProtNotify->Position = ProtNotify->Position->ForwardLink; + } + +Done: + CoreReleaseProtocolLock (); + return Status; +} + + + +EFI_STATUS +EFIAPI +CoreLocateHandleBuffer ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol OPTIONAL, + IN VOID *SearchKey OPTIONAL, + IN OUT UINTN *NumberHandles, + OUT EFI_HANDLE **Buffer + ) +/*++ + +Routine Description: + + Function returns an array of handles that support the requested protocol + in a buffer allocated from pool. This is a version of CoreLocateHandle() + that allocates a buffer for the caller. + +Arguments: + + SearchType - Specifies which handle(s) are to be returned. + Protocol - Provides the protocol to search by. + This parameter is only valid for SearchType ByProtocol. + SearchKey - Supplies the search key depending on the SearchType. + NumberHandles - The number of handles returned in Buffer. + Buffer - A pointer to the buffer to return the requested array of + handles that support Protocol. + +Returns: + + EFI_SUCCESS - The result array of handles was returned. + EFI_NOT_FOUND - No handles match the search. + EFI_OUT_OF_RESOURCES - There is not enough pool memory to store the matching results. + EFI_INVALID_PARAMETER - Invalid parameter + +--*/ +{ + EFI_STATUS Status; + UINTN BufferSize; + + if (NumberHandles == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + BufferSize = 0; + *NumberHandles = 0; + *Buffer = NULL; + Status = CoreLocateHandle ( + SearchType, + Protocol, + SearchKey, + &BufferSize, + *Buffer + ); + // + // LocateHandleBuffer() returns incorrect status code if SearchType is + // invalid. + // + // Add code to correctly handle expected errors from CoreLocateHandle(). + // + if (EFI_ERROR(Status)) { + switch (Status) { + case EFI_BUFFER_TOO_SMALL: + break; + case EFI_INVALID_PARAMETER: + return Status; + default: + return EFI_NOT_FOUND; + } + } + + *Buffer = CoreAllocateBootServicesPool (BufferSize); + if (*Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = CoreLocateHandle ( + SearchType, + Protocol, + SearchKey, + &BufferSize, + *Buffer + ); + + *NumberHandles = BufferSize/sizeof(EFI_HANDLE); + if (EFI_ERROR(Status)) { + *NumberHandles = 0; + } + + return Status; +} + + diff --git a/EdkModulePkg/Core/Dxe/Image.h b/EdkModulePkg/Core/Dxe/Image.h new file mode 100644 index 0000000000..067d42d4b5 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Image.h @@ -0,0 +1,380 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Image.h + +Abstract: + +Revision History + +--*/ + + +#ifndef _IMAGE_H_ +#define _IMAGE_H_ + + + +#define LOADED_IMAGE_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('l','d','r','i') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; // Image handle + UINTN Type; // Image type + + BOOLEAN Started; // If entrypoint has been called + + EFI_IMAGE_ENTRY_POINT EntryPoint; // The image's entry point + EFI_LOADED_IMAGE_PROTOCOL Info; // loaded image protocol + + EFI_PHYSICAL_ADDRESS ImageBasePage; // Location in memory + UINTN NumberOfPages; // Number of pages + + CHAR8 *FixupData; // Original fixup data + + EFI_TPL Tpl; // Tpl of started image + EFI_STATUS Status; // Status returned by started image + + UINTN ExitDataSize; // Size of ExitData from started image + VOID *ExitData; // Pointer to exit data from started image + BASE_LIBRARY_JUMP_BUFFER *JumpContext; // Pointer to buffer for context save/retore + UINT16 Machine; // Machine type from PE image + + EFI_EBC_PROTOCOL *Ebc; // EBC Protocol pointer + + BOOLEAN RuntimeFixupValid; // True if RT image needs fixup + VOID *RuntimeFixup; // Copy of fixup data; + LIST_ENTRY Link; // List of RT LOADED_IMAGE_PRIVATE_DATA + + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; // PeCoffLoader ImageContext + +} LOADED_IMAGE_PRIVATE_DATA; + +#define LOADED_IMAGE_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, LOADED_IMAGE_PRIVATE_DATA, Info, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE) + + + +#define LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32('l','p','e','i') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; // Image handle + EFI_PE32_IMAGE_PROTOCOL Pe32Image; +} LOAD_PE32_IMAGE_PRIVATE_DATA; + +#define LOAD_PE32_IMAGE_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, LOAD_PE32_IMAGE_PRIVATE_DATA, Pe32Image, LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE) + + + +// +// Private Data Types +// +#define IMAGE_FILE_HANDLE_SIGNATURE EFI_SIGNATURE_32('i','m','g','f') +typedef struct { + UINTN Signature; + BOOLEAN FreeBuffer; + VOID *Source; + UINTN SourceSize; +} IMAGE_FILE_HANDLE; + + +// +// Abstractions for reading image contents +// + +EFI_STATUS +CoreOpenImageFile ( + IN BOOLEAN BootPolicy, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + IN OUT EFI_DEVICE_PATH_PROTOCOL *FilePath, + OUT EFI_HANDLE *DeviceHandle, + IN IMAGE_FILE_HANDLE *ImageFileHandle, + OUT UINT32 *AuthenticationStatus + ) +/*++ + +Routine Description: + + Opens a file for (simple) reading. The simple read abstraction + will access the file either from a memory copy, from a file + system interface, or from the load file interface. + +Arguments: + + BootPolicy - Policy for Open Image File. + SourceBuffer - Pointer to the memory location containing copy + of the image to be loaded. + SourceSize - The size in bytes of SourceBuffer. + FilePath - The specific file path from which the image is loaded + DeviceHandle - Pointer to the return device handle. + ImageFileHandle - Pointer to the image file handle. + AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned. + +Returns: + + A handle to access the file + +--*/ +; + + +EFI_STATUS +EFIAPI +CoreReadImageFile ( + IN VOID *UserHandle, + IN UINTN Offset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Read image file (specified by UserHandle) into user specified buffer with specified offset + and length. + +Arguments: + + UserHandle - Image file handle + + Offset - Offset to the source file + + ReadSize - For input, pointer of size to read; + For output, pointer of size actually read. + + Buffer - Buffer to write into + +Returns: + + EFI_SUCCESS - Successfully read the specified part of file into buffer. + +--*/ +; + +VOID +EFIAPI +CoreCloseImageFile ( + IN IMAGE_FILE_HANDLE *ImageFileHandle + ) +/*++ + +Routine Description: + + A function out of date, should be removed. + +Arguments: + + ImageFileHandle - Handle of the file to close + +Returns: + + None + +--*/ +; + +// +// Image processing worker functions +// +EFI_STATUS +CoreDevicePathToInterface ( + IN EFI_GUID *Protocol, + IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath, + OUT VOID **Interface, + OUT EFI_HANDLE *Handle + ) +/*++ + +Routine Description: + + Search a handle to a device on a specified device path that supports a specified protocol, + interface of that protocol on that handle is another output. + +Arguments: + + Protocol - The protocol to search for + + FilePath - The specified device path + + Interface - Interface of the protocol on the handle + + Handle - The handle to the device on the specified device path that supports the protocol. + +Returns: + + Status code. + +--*/ +; + +EFI_STATUS +CoreLoadPeImage ( + IN VOID *Pe32Handle, + IN LOADED_IMAGE_PRIVATE_DATA *Image, + IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL, + IN UINT32 Attribute + ) +/*++ + +Routine Description: + + Loads, relocates, and invokes a PE/COFF image + +Arguments: + + Pe32Handle - The handle of PE32 image + Image - PE image to be loaded + DstBuffer - The buffer to store the image + EntryPoint - A pointer to the entry point + Attribute - The bit mask of attributes to set for the load PE image + +Returns: + + EFI_SUCCESS - The file was loaded, relocated, and invoked + + EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_BUFFER_TOO_SMALL - Buffer for image is too small + +--*/ +; + +LOADED_IMAGE_PRIVATE_DATA * +CoreLoadedImageInfo ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +CoreUnloadAndCloseImage ( + IN LOADED_IMAGE_PRIVATE_DATA *Image, + IN BOOLEAN FreePage + ) +/*++ + +Routine Description: + + Unloads EFI image from memory. + +Arguments: + + Image - EFI image + FreePage - Free allocated pages + +Returns: + + None + +--*/ +; + + +// +// Exported Image functions +// + +EFI_STATUS +EFIAPI +CoreLoadImageEx ( + IN EFI_PE32_IMAGE_PROTOCOL *This, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL, + OUT UINTN *NumberOfPages OPTIONAL, + OUT EFI_HANDLE *ImageHandle, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL, + IN UINT32 Attribute + ) +/*++ + +Routine Description: + + Loads an EFI image into memory and returns a handle to the image with extended parameters. + +Arguments: + + ParentImageHandle - The caller's image handle. + FilePath - The specific file path from which the image is loaded. + SourceBuffer - If not NULL, a pointer to the memory location containing a copy of + the image to be loaded. + SourceSize - The size in bytes of SourceBuffer. + DstBuffer - The buffer to store the image. + NumberOfPages - For input, specifies the space size of the image by caller if not NULL. + For output, specifies the actual space size needed. + ImageHandle - Image handle for output. + EntryPoint - Image entry point for output. + Attribute - The bit mask of attributes to set for the load PE image. + +Returns: + + EFI_SUCCESS - The image was loaded into memory. + EFI_NOT_FOUND - The FilePath was not found. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be + parsed to locate the proper protocol for loading the file. + EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources. +--*/ +; + +EFI_STATUS +EFIAPI +CoreUnloadImageEx ( + IN EFI_PE32_IMAGE_PROTOCOL *This, + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Unload the specified image. + +Arguments: + + This - Indicates the calling context. + + ImageHandle - The specified image handle. + +Returns: + + EFI_INVALID_PARAMETER - Image handle is NULL. + + EFI_UNSUPPORTED - Attempt to unload an unsupported image. + + EFI_SUCCESS - Image successfully unloaded. + +--*/ +; +#endif diff --git a/EdkModulePkg/Core/Dxe/Image/Image.c b/EdkModulePkg/Core/Dxe/Image/Image.c new file mode 100644 index 0000000000..c818cc2131 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Image/Image.c @@ -0,0 +1,1377 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Image.c + +Abstract: + + Core image handling services + +--*/ + +#include +// +// Module Globals +// + +// +// LIST of runtime images that need to be relocated. +// +LIST_ENTRY mRuntimeImageList = INITIALIZE_LIST_HEAD_VARIABLE (mRuntimeImageList); + +LOADED_IMAGE_PRIVATE_DATA *mCurrentImage = NULL; + +LOAD_PE32_IMAGE_PRIVATE_DATA mLoadPe32PrivateData = { + LOAD_PE32_IMAGE_PRIVATE_DATA_SIGNATURE, + NULL, + { + CoreLoadImageEx, + CoreUnloadImageEx + } +}; + + +// +// This code is needed to build the Image handle for the DXE Core +// +LOADED_IMAGE_PRIVATE_DATA mCorePrivateImage = { + LOADED_IMAGE_PRIVATE_DATA_SIGNATURE, // Signature + NULL, // Image handle + EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, // Image type + TRUE, // If entrypoint has been called + NULL, // EntryPoint + { + EFI_LOADED_IMAGE_INFORMATION_REVISION, // Revision + NULL, // Parent handle + NULL, // System handle + + NULL, // Device handle + NULL, // File path + NULL, // Reserved + + 0, // LoadOptionsSize + NULL, // LoadOptions + + NULL, // ImageBase + 0, // ImageSize + EfiBootServicesCode, // ImageCodeType + EfiBootServicesData // ImageDataType + }, + (EFI_PHYSICAL_ADDRESS)0, // ImageBasePage + 0, // NumberOfPages + NULL, // FixupData + 0, // Tpl + EFI_SUCCESS, // Status + 0, // ExitDataSize + NULL, // ExitData + NULL, // JumpContext + 0, // Machine + NULL, // Ebc + FALSE, // RuntimeFixupValid + NULL, // RuntimeFixup + { NULL, NULL }, // Link +}; + + +EFI_STATUS +CoreInitializeImageServices ( + IN VOID *HobStart + ) +/*++ + +Routine Description: + + Add the Image Services to EFI Boot Services Table and install the protocol + interfaces for this image. + +Arguments: + + HobStart - The HOB to initialize + +Returns: + + Status code. + +--*/ +{ + EFI_STATUS Status; + LOADED_IMAGE_PRIVATE_DATA *Image; + EFI_PHYSICAL_ADDRESS DxeCoreImageBaseAddress; + UINT64 DxeCoreImageLength; + VOID *DxeCoreEntryPoint; + EFI_PEI_HOB_POINTERS DxeCoreHob; + // + // Searching for image hob + // + DxeCoreHob.Raw = HobStart; + while ((DxeCoreHob.Raw = GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, DxeCoreHob.Raw)) != NULL) { + if (CompareGuid (&DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.Name, &gEfiHobMemoryAllocModuleGuid)) { + // + // Find Dxe Core HOB + // + break; + } + DxeCoreHob.Raw = GET_NEXT_HOB (DxeCoreHob); + } + ASSERT (DxeCoreHob.Raw != NULL); + + DxeCoreImageBaseAddress = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryBaseAddress; + DxeCoreImageLength = DxeCoreHob.MemoryAllocationModule->MemoryAllocationHeader.MemoryLength; + DxeCoreEntryPoint = (VOID *) (UINTN) DxeCoreHob.MemoryAllocationModule->EntryPoint; + gDxeCoreFileName = &DxeCoreHob.MemoryAllocationModule->ModuleName; + // + // Initialize the fields for an internal driver + // + Image = &mCorePrivateImage; + + Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)DxeCoreEntryPoint; + Image->ImageBasePage = DxeCoreImageBaseAddress; + Image->NumberOfPages = (UINTN)(EFI_SIZE_TO_PAGES((UINTN)(DxeCoreImageLength))); + Image->Tpl = gEfiCurrentTpl; + Image->Info.SystemTable = gST; + Image->Info.ImageBase = (VOID *)(UINTN)DxeCoreImageBaseAddress; + Image->Info.ImageSize = DxeCoreImageLength; + + // + // Install the protocol interfaces for this image + // + Status = CoreInstallProtocolInterface ( + &Image->Handle, + &gEfiLoadedImageProtocolGuid, + EFI_NATIVE_INTERFACE, + &Image->Info + ); + ASSERT_EFI_ERROR (Status); + + mCurrentImage = Image; + + // + // Fill in DXE globals + // + gDxeCoreImageHandle = Image->Handle; + gDxeCoreLoadedImage = &Image->Info; + + // + // Export DXE Core PE Loader functionality + // + return CoreInstallProtocolInterface ( + &mLoadPe32PrivateData.Handle, + &gEfiLoadPeImageProtocolGuid, + EFI_NATIVE_INTERFACE, + &mLoadPe32PrivateData.Pe32Image + ); +} + + +EFI_STATUS +CoreShutdownImageServices ( + VOID + ) +/*++ + +Routine Description: + + Transfer control of runtime images to runtime service + +Arguments: + + None + +Returns: + + EFI_SUCCESS - Function successfully returned + +--*/ +{ + LIST_ENTRY *Link; + LOADED_IMAGE_PRIVATE_DATA *Image; + + // + // The Runtime AP is required for the core to function! + // + ASSERT (gRuntime != NULL); + + for (Link = mRuntimeImageList.ForwardLink; Link != &mRuntimeImageList; Link = Link->ForwardLink) { + Image = CR (Link, LOADED_IMAGE_PRIVATE_DATA, Link, LOADED_IMAGE_PRIVATE_DATA_SIGNATURE); + if (Image->RuntimeFixupValid) { + gRuntime->RegisterImage ( + gRuntime, + (UINT64)(UINTN)(Image->Info.ImageBase), + (EFI_SIZE_TO_PAGES ((UINTN)Image->Info.ImageSize)), + Image->RuntimeFixup + ); + } + } + + return EFI_SUCCESS; +} + + + +EFI_STATUS +CoreLoadPeImage ( + IN VOID *Pe32Handle, + IN LOADED_IMAGE_PRIVATE_DATA *Image, + IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL, + IN UINT32 Attribute + ) +/*++ + +Routine Description: + + Loads, relocates, and invokes a PE/COFF image + +Arguments: + + Pe32Handle - The handle of PE32 image + Image - PE image to be loaded + DstBuffer - The buffer to store the image + EntryPoint - A pointer to the entry point + Attribute - The bit mask of attributes to set for the load PE image + +Returns: + + EFI_SUCCESS - The file was loaded, relocated, and invoked + + EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_BUFFER_TOO_SMALL - Buffer for image is too small + +--*/ +{ + EFI_STATUS Status; + UINTN Size; + + ZeroMem (&Image->ImageContext, sizeof (Image->ImageContext)); + + Image->ImageContext.Handle = Pe32Handle; + Image->ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)CoreReadImageFile; + + // + // Get information about the image being loaded + // + Status = gEfiPeiPeCoffLoader->GetImageInfo (gEfiPeiPeCoffLoader, &Image->ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate memory of the correct memory type aligned on the required image boundry + // + + if (DstBuffer == 0) { + // + // Allocate Destination Buffer as caller did not pass it in + // + + if (Image->ImageContext.SectionAlignment > EFI_PAGE_SIZE) { + Size = (UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment; + } else { + Size = (UINTN)Image->ImageContext.ImageSize; + } + + Image->NumberOfPages = EFI_SIZE_TO_PAGES (Size); + + // + // If the image relocations have not been stripped, then load at any address. + // Otherwise load at the address at which it was linked. + // + Status = CoreAllocatePages ( + (Image->ImageContext.RelocationsStripped) ? AllocateAddress : AllocateAnyPages, + Image->ImageContext.ImageCodeMemoryType, + Image->NumberOfPages, + &Image->ImageContext.ImageAddress + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Image->ImageBasePage = Image->ImageContext.ImageAddress; + + } else { + // + // Caller provided the destination buffer + // + + if (Image->ImageContext.RelocationsStripped && (Image->ImageContext.ImageAddress != DstBuffer)) { + // + // If the image relocations were stripped, and the caller provided a + // destination buffer address that does not match the address that the + // image is linked at, then the image cannot be loaded. + // + return EFI_INVALID_PARAMETER; + } + + if (Image->NumberOfPages != 0 && + Image->NumberOfPages < + (EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment))) { + Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment); + return EFI_BUFFER_TOO_SMALL; + } + + Image->NumberOfPages = EFI_SIZE_TO_PAGES ((UINTN)Image->ImageContext.ImageSize + Image->ImageContext.SectionAlignment); + Image->ImageContext.ImageAddress = DstBuffer; + Image->ImageBasePage = Image->ImageContext.ImageAddress; + } + + Image->ImageContext.ImageAddress = + (Image->ImageContext.ImageAddress + Image->ImageContext.SectionAlignment - 1) & + ~((UINTN)Image->ImageContext.SectionAlignment - 1); + + // + // Load the image from the file into the allocated memory + // + Status = gEfiPeiPeCoffLoader->LoadImage (gEfiPeiPeCoffLoader, &Image->ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If this is a Runtime Driver, then allocate memory for the FixupData that + // is used to relocate the image when SetVirtualAddressMap() is called. The + // relocation is done by the Runtime AP. + // + if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION) { + if (Image->ImageContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) { + Image->ImageContext.FixupData = CoreAllocateRuntimePool ((UINTN)(Image->ImageContext.FixupDataSize)); + if (Image->ImageContext.FixupData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + // + // Make a list off all the RT images so we can let the RT AP know about them + // + Image->RuntimeFixupValid = TRUE; + Image->RuntimeFixup = Image->ImageContext.FixupData; + InsertTailList (&mRuntimeImageList, &Image->Link); + } + } + + // + // Relocate the image in memory + // + Status = gEfiPeiPeCoffLoader->RelocateImage (gEfiPeiPeCoffLoader, &Image->ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Flush the Instruction Cache + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.ImageSize); + + // + // Copy the machine type from the context to the image private data. This + // is needed during image unload to know if we should call an EBC protocol + // to unload the image. + // + Image->Machine = Image->ImageContext.Machine; + + // + // Get the image entry point. If it's an EBC image, then call into the + // interpreter to create a thunk for the entry point and use the returned + // value for the entry point. + // + Image->EntryPoint = (EFI_IMAGE_ENTRY_POINT)(UINTN)Image->ImageContext.EntryPoint; + if (Image->ImageContext.Machine == EFI_IMAGE_MACHINE_EBC) { + // + // Locate the EBC interpreter protocol + // + Status = CoreLocateProtocol (&gEfiEbcProtocolGuid, NULL, (VOID **)&Image->Ebc); + if (EFI_ERROR(Status)) { + goto Done; + } + + // + // Register a callback for flushing the instruction cache so that created + // thunks can be flushed. + // + Status = Image->Ebc->RegisterICacheFlush (Image->Ebc, (EBC_ICACHE_FLUSH)InvalidateInstructionCacheRange); + if (EFI_ERROR(Status)) { + goto Done; + } + + // + // Create a thunk for the image's entry point. This will be the new + // entry point for the image. + // + Status = Image->Ebc->CreateThunk ( + Image->Ebc, + Image->Handle, + (VOID *)(UINTN)Image->ImageContext.EntryPoint, + (VOID **)&Image->EntryPoint + ); + if (EFI_ERROR(Status)) { + goto Done; + } + } + + // + // Fill in the image information for the Loaded Image Protocol + // + Image->Type = Image->ImageContext.ImageType; + Image->Info.ImageBase = (VOID *)(UINTN)Image->ImageContext.ImageAddress; + Image->Info.ImageSize = Image->ImageContext.ImageSize; + Image->Info.ImageCodeType = Image->ImageContext.ImageCodeMemoryType; + Image->Info.ImageDataType = Image->ImageContext.ImageDataMemoryType; + + // + // Fill in the entry point of the image if it is available + // + if (EntryPoint != NULL) { + *EntryPoint = Image->ImageContext.EntryPoint; + } + + // + // Print the load address and the PDB file name if it is available + // + + DEBUG_CODE ( + { + UINTN Index; + UINTN StartIndex; + CHAR8 EfiFileName[256]; + + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading driver at 0x%08x EntryPoint=0x%08x ", (UINTN)Image->ImageContext.ImageAddress, (UINTN)Image->ImageContext.EntryPoint)); + if (Image->ImageContext.PdbPointer != NULL) { + StartIndex = 0; + for (Index = 0; Image->ImageContext.PdbPointer[Index] != 0; Index++) { + if (Image->ImageContext.PdbPointer[Index] == '\\') { + StartIndex = Index + 1; + } + } + // + // Copy the PDB file name to our temporary string, and replace .pdb with .efi + // + for (Index = 0; Index < sizeof (EfiFileName); Index++) { + EfiFileName[Index] = Image->ImageContext.PdbPointer[Index + StartIndex]; + if (EfiFileName[Index] == 0) { + EfiFileName[Index] = '.'; + } + if (EfiFileName[Index] == '.') { + EfiFileName[Index + 1] = 'e'; + EfiFileName[Index + 2] = 'f'; + EfiFileName[Index + 3] = 'i'; + EfiFileName[Index + 4] = 0; + break; + } + } + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a", EfiFileName)); // &Image->ImageContext.PdbPointer[StartIndex])); + } + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n")); + } + ); + + return EFI_SUCCESS; + +Done: + // + // Free memory + // + CoreFreePages (Image->ImageContext.ImageAddress, Image->NumberOfPages); + return Status; +} + + +LOADED_IMAGE_PRIVATE_DATA * +CoreLoadedImageInfo ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Get the image's private data from its handle. + +Arguments: + + ImageHandle - The image handle + +Returns: + + Return the image private data associated with ImageHandle. + +--*/ +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + LOADED_IMAGE_PRIVATE_DATA *Image; + + Status = CoreHandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + if (!EFI_ERROR (Status)) { + Image = LOADED_IMAGE_PRIVATE_DATA_FROM_THIS (LoadedImage); + } else { + DEBUG ((EFI_D_LOAD, "CoreLoadedImageInfo: Not an ImageHandle %x\n", ImageHandle)); + Image = NULL; + } + + return Image; +} + + +EFI_STATUS +CoreLoadImageCommon ( + IN BOOLEAN BootPolicy, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL, + IN OUT UINTN *NumberOfPages OPTIONAL, + OUT EFI_HANDLE *ImageHandle, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL, + IN UINT32 Attribute + ) +/*++ + +Routine Description: + + Loads an EFI image into memory and returns a handle to the image. + +Arguments: + + BootPolicy - If TRUE, indicates that the request originates from the boot manager, + and that the boot manager is attempting to load FilePath as a boot selection. + ParentImageHandle - The caller's image handle. + FilePath - The specific file path from which the image is loaded. + SourceBuffer - If not NULL, a pointer to the memory location containing a copy of + the image to be loaded. + SourceSize - The size in bytes of SourceBuffer. + DstBuffer - The buffer to store the image + NumberOfPages - If not NULL, a pointer to the image's page number, if this number + is not enough, return EFI_BUFFER_TOO_SMALL and this parameter contain + the required number. + ImageHandle - Pointer to the returned image handle that is created when the image + is successfully loaded. + EntryPoint - A pointer to the entry point + Attribute - The bit mask of attributes to set for the load PE image + +Returns: + + EFI_SUCCESS - The image was loaded into memory. + EFI_NOT_FOUND - The FilePath was not found. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + EFI_BUFFER_TOO_SMALL - The buffer is too small + EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be + parsed to locate the proper protocol for loading the file. + EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources. +--*/ +{ + LOADED_IMAGE_PRIVATE_DATA *Image; + LOADED_IMAGE_PRIVATE_DATA *ParentImage; + IMAGE_FILE_HANDLE FHand; + EFI_STATUS Status; + EFI_STATUS SecurityStatus; + EFI_HANDLE DeviceHandle; + UINT32 AuthenticationStatus; + EFI_DEVICE_PATH_PROTOCOL *OriginalFilePath; + EFI_DEVICE_PATH_PROTOCOL *HandleFilePath; + UINTN FilePathSize; + + + ASSERT (gEfiCurrentTpl < EFI_TPL_NOTIFY); + ParentImage = NULL; + + // + // The caller must pass in a valid ParentImageHandle + // + if (ImageHandle == NULL || ParentImageHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + ParentImage = CoreLoadedImageInfo (ParentImageHandle); + if (ParentImage == NULL) { + DEBUG((EFI_D_LOAD|EFI_D_ERROR, "LoadImageEx: Parent handle not an image handle\n")); + return EFI_INVALID_PARAMETER; + } + + // + // Get simple read access to the source file + // + OriginalFilePath = FilePath; + Status = CoreOpenImageFile ( + BootPolicy, + SourceBuffer, + SourceSize, + FilePath, + &DeviceHandle, + &FHand, + &AuthenticationStatus + ); + if (Status == EFI_ALREADY_STARTED) { + Image = NULL; + goto Done; + } else if (EFI_ERROR (Status)) { + return Status; + } + + // + // Verify the Authentication Status through the Security Architectural Protocol + // + if ((gSecurity != NULL) && (OriginalFilePath != NULL)) { + SecurityStatus = gSecurity->FileAuthenticationState ( + gSecurity, + AuthenticationStatus, + OriginalFilePath + ); + if (EFI_ERROR (SecurityStatus) && SecurityStatus != EFI_SECURITY_VIOLATION) { + Status = SecurityStatus; + Image = NULL; + goto Done; + } + } + + + // + // Allocate a new image structure + // + Image = CoreAllocateZeroBootServicesPool (sizeof(LOADED_IMAGE_PRIVATE_DATA)); + if (Image == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Pull out just the file portion of the DevicePath for the LoadedImage FilePath + // + Status = CoreHandleProtocol (DeviceHandle, &gEfiDevicePathProtocolGuid, (VOID **)&HandleFilePath); + if (!EFI_ERROR (Status)) { + FilePathSize = CoreDevicePathSize (HandleFilePath) - sizeof(EFI_DEVICE_PATH_PROTOCOL); + FilePath = (EFI_DEVICE_PATH_PROTOCOL *) ( ((UINT8 *)FilePath) + FilePathSize ); + } + + // + // Initialize the fields for an internal driver + // + Image->Signature = LOADED_IMAGE_PRIVATE_DATA_SIGNATURE; + Image->Info.SystemTable = gST; + Image->Info.DeviceHandle = DeviceHandle; + Image->Info.Revision = EFI_LOADED_IMAGE_INFORMATION_REVISION; + Image->Info.FilePath = CoreDuplicateDevicePath (FilePath); + Image->Info.ParentHandle = ParentImageHandle; + + if (NumberOfPages != NULL) { + Image->NumberOfPages = *NumberOfPages ; + } else { + Image->NumberOfPages = 0 ; + } + + // + // Install the protocol interfaces for this image + // don't fire notifications yet + // + Status = CoreInstallProtocolInterfaceNotify ( + &Image->Handle, + &gEfiLoadedImageProtocolGuid, + EFI_NATIVE_INTERFACE, + &Image->Info, + FALSE + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + // + // Load the image. If EntryPoint is Null, it will not be set. + // + Status = CoreLoadPeImage (&FHand, Image, DstBuffer, EntryPoint, Attribute); + if (EFI_ERROR (Status)) { + if ((Status == EFI_BUFFER_TOO_SMALL) || (Status == EFI_OUT_OF_RESOURCES)) { + if (NumberOfPages != NULL) { + *NumberOfPages = Image->NumberOfPages; + } + } + goto Done; + } + + // + // Register the image in the Debug Image Info Table if the attribute is set + // + if (Attribute & EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION) { + CoreNewDebugImageInfoEntry (EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL, &Image->Info, Image->Handle); + } + + // + //Reinstall loaded image protocol to fire any notifications + // + Status = CoreReinstallProtocolInterface ( + Image->Handle, + &gEfiLoadedImageProtocolGuid, + &Image->Info, + &Image->Info + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + + // + // Success. Return the image handle + // + *ImageHandle = Image->Handle; + +Done: + // + // All done accessing the source file + // If we allocated the Source buffer, free it + // + if (FHand.FreeBuffer) { + CoreFreePool (FHand.Source); + } + + // + // There was an error. If there's an Image structure, free it + // + if (EFI_ERROR (Status)) { + if (Image != NULL) { + CoreUnloadAndCloseImage (Image, (BOOLEAN)(DstBuffer == 0)); + *ImageHandle = NULL; + } + } + + return Status; +} + + + +EFI_STATUS +EFIAPI +CoreLoadImage ( + IN BOOLEAN BootPolicy, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + OUT EFI_HANDLE *ImageHandle + ) +/*++ + +Routine Description: + + Loads an EFI image into memory and returns a handle to the image. + +Arguments: + + BootPolicy - If TRUE, indicates that the request originates from the boot manager, + and that the boot manager is attempting to load FilePath as a boot selection. + ParentImageHandle - The caller's image handle. + FilePath - The specific file path from which the image is loaded. + SourceBuffer - If not NULL, a pointer to the memory location containing a copy of + the image to be loaded. + SourceSize - The size in bytes of SourceBuffer. + ImageHandle - Pointer to the returned image handle that is created when the image + is successfully loaded. + +Returns: + + EFI_SUCCESS - The image was loaded into memory. + EFI_NOT_FOUND - The FilePath was not found. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be + parsed to locate the proper protocol for loading the file. + EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources. +--*/ +{ + EFI_STATUS Status; + + PERF_START (NULL, "LoadImage", NULL, 0); + + Status = CoreLoadImageCommon ( + BootPolicy, + ParentImageHandle, + FilePath, + SourceBuffer, + SourceSize, + (EFI_PHYSICAL_ADDRESS)NULL, + NULL, + ImageHandle, + NULL, + EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION | EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION + ); + + PERF_END (NULL, "LoadImage", NULL, 0); + + return Status; +} + + +EFI_STATUS +EFIAPI +CoreLoadImageEx ( + IN EFI_PE32_IMAGE_PROTOCOL *This, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL, + OUT UINTN *NumberOfPages OPTIONAL, + OUT EFI_HANDLE *ImageHandle, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL, + IN UINT32 Attribute + ) +/*++ + +Routine Description: + + Loads an EFI image into memory and returns a handle to the image with extended parameters. + +Arguments: + + This - Calling context + ParentImageHandle - The caller's image handle. + FilePath - The specific file path from which the image is loaded. + SourceBuffer - If not NULL, a pointer to the memory location containing a copy of + the image to be loaded. + SourceSize - The size in bytes of SourceBuffer. + DstBuffer - The buffer to store the image. + NumberOfPages - For input, specifies the space size of the image by caller if not NULL. + For output, specifies the actual space size needed. + ImageHandle - Image handle for output. + EntryPoint - Image entry point for output. + Attribute - The bit mask of attributes to set for the load PE image. + +Returns: + + EFI_SUCCESS - The image was loaded into memory. + EFI_NOT_FOUND - The FilePath was not found. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + EFI_UNSUPPORTED - The image type is not supported, or the device path cannot be + parsed to locate the proper protocol for loading the file. + EFI_OUT_OF_RESOURCES - Image was not loaded due to insufficient resources. +--*/ +{ + return CoreLoadImageCommon ( + TRUE, + ParentImageHandle, + FilePath, + SourceBuffer, + SourceSize, + DstBuffer, + NumberOfPages, + ImageHandle, + EntryPoint, + Attribute + ); +} + + + + +EFI_STATUS +EFIAPI +CoreStartImage ( + IN EFI_HANDLE ImageHandle, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ) +/*++ + +Routine Description: + + Transfer control to a loaded image's entry point. + +Arguments: + + ImageHandle - Handle of image to be started. + + ExitDataSize - Pointer of the size to ExitData + + ExitData - Pointer to a pointer to a data buffer that includes a Null-terminated + Unicode string, optionally followed by additional binary data. The string + is a description that the caller may use to further indicate the reason for + the image¡¯s exit. + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Successfully transfer control to the image's entry point. + +--*/ +{ + EFI_STATUS Status; + LOADED_IMAGE_PRIVATE_DATA *Image; + LOADED_IMAGE_PRIVATE_DATA *LastImage; + UINT64 HandleDatabaseKey; + UINTN SetJumpFlag; + + Image = CoreLoadedImageInfo (ImageHandle); + if (Image == NULL_HANDLE || Image->Started) { + return EFI_INVALID_PARAMETER; + } + + // + // Don't profile Objects or invalid start requests + // + PERF_START (ImageHandle, START_IMAGE_TOK, NULL, 0); + + if (sizeof (UINTN) == 4 && Image->Machine == EFI_IMAGE_MACHINE_X64) { + return EFI_UNSUPPORTED; + } else if (sizeof (UINTN) == 8 && Image->Machine == EFI_IMAGE_MACHINE_IA32) { + return EFI_UNSUPPORTED; + } else { + // + // For orther possible cases + // + } + + // + // Push the current start image context, and + // link the current image to the head. This is the + // only image that can call Exit() + // + HandleDatabaseKey = CoreGetHandleDatabaseKey(); + LastImage = mCurrentImage; + mCurrentImage = Image; + Image->Tpl = gEfiCurrentTpl; + + // + // Set long jump for Exit() support + // + Image->JumpContext = CoreAllocateBootServicesPool (sizeof (*Image->JumpContext)); + if (Image->JumpContext == NULL) { + PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0); + return EFI_OUT_OF_RESOURCES; + } + + SetJumpFlag = SetJump (Image->JumpContext); + // + // The initial call to SetJump() must always return 0. + // Subsequent calls to LongJump() cause a non-zero value to be returned by SetJump(). + // + if (!SetJumpFlag) { + // + // Call the image's entry point + // + Image->Started = TRUE; + Image->Status = Image->EntryPoint (ImageHandle, Image->Info.SystemTable); + + // + // Add some debug information if the image returned with error. + // This make the user aware and check if the driver image have already released + // all the resource in this situation. + // + DEBUG_CODE ( + if (EFI_ERROR (Image->Status)) { + DEBUG ((EFI_D_ERROR, "Error: Image at %08X start failed: %x\n", Image->Info.ImageBase, Image->Status)); + } + ); + + // + // If the image returns, exit it through Exit() + // + CoreExit (ImageHandle, Image->Status, 0, NULL); + } + + // + // Image has completed. Verify the tpl is the same + // + ASSERT (Image->Tpl == gEfiCurrentTpl); + CoreRestoreTpl (Image->Tpl); + + CoreFreePool (Image->JumpContext); + + // + // Pop the current start image context + // + mCurrentImage = LastImage; + + // + // Go connect any handles that were created or modified while the image executed. + // + CoreConnectHandlesByKey (HandleDatabaseKey); + + // + // Handle the image's returned ExitData + // + DEBUG_CODE ( + if (Image->ExitDataSize != 0 || Image->ExitData != NULL) { + + DEBUG ( + (EFI_D_LOAD, + "StartImage: ExitDataSize %d, ExitData %x", + Image->ExitDataSize, + Image->ExitData) + ); + if (Image->ExitData != NULL) { + DEBUG ((EFI_D_LOAD, " (%hs)", Image->ExitData)); + } + DEBUG ((EFI_D_LOAD, "\n")); + } + ); + + // + // Return the exit data to the caller + // + if (ExitData != NULL && ExitDataSize != NULL) { + *ExitDataSize = Image->ExitDataSize; + *ExitData = Image->ExitData; + } else { + // + // Caller doesn't want the exit data, free it + // + CoreFreePool (Image->ExitData); + Image->ExitData = NULL; + } + + // + // Save the Status because Image will get destroyed if it is unloaded. + // + Status = Image->Status; + + // + // If the image returned an error, or if the image is an application + // unload it + // + if (EFI_ERROR (Image->Status) || Image->Type == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { + CoreUnloadAndCloseImage (Image, TRUE); + } + + // + // Done + // + PERF_END (ImageHandle, START_IMAGE_TOK, NULL, 0); + return Status; +} + + +VOID +CoreUnloadAndCloseImage ( + IN LOADED_IMAGE_PRIVATE_DATA *Image, + IN BOOLEAN FreePage + ) +/*++ + +Routine Description: + + Unloads EFI image from memory. + +Arguments: + + Image - EFI image + FreePage - Free allocated pages + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN HandleIndex; + EFI_GUID **ProtocolGuidArray; + UINTN ArrayCount; + UINTN ProtocolIndex; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo; + UINTN OpenInfoCount; + UINTN OpenInfoIndex; + + if (Image->Ebc != NULL) { + // + // If EBC protocol exists we must perform cleanups for this image. + // + Image->Ebc->UnloadImage (Image->Ebc, Image->Handle); + } + + // + // Unload image, free Image->ImageContext->ModHandle + // + gEfiPeiPeCoffLoader->UnloadImage (gEfiPeiPeCoffLoader, &Image->ImageContext); + + // + // Free our references to the image handle + // + if (Image->Handle != NULL_HANDLE) { + + Status = CoreLocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (!EFI_ERROR (Status)) { + for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { + Status = CoreProtocolsPerHandle ( + HandleBuffer[HandleIndex], + &ProtocolGuidArray, + &ArrayCount + ); + if (!EFI_ERROR (Status)) { + for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) { + Status = CoreOpenProtocolInformation ( + HandleBuffer[HandleIndex], + ProtocolGuidArray[ProtocolIndex], + &OpenInfo, + &OpenInfoCount + ); + if (!EFI_ERROR (Status)) { + for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) { + if (OpenInfo[OpenInfoIndex].AgentHandle == Image->Handle) { + Status = CoreCloseProtocol ( + HandleBuffer[HandleIndex], + ProtocolGuidArray[ProtocolIndex], + Image->Handle, + OpenInfo[OpenInfoIndex].ControllerHandle + ); + } + } + if (OpenInfo != NULL) { + CoreFreePool(OpenInfo); + } + } + } + if (ProtocolGuidArray != NULL) { + CoreFreePool(ProtocolGuidArray); + } + } + } + if (HandleBuffer != NULL) { + CoreFreePool (HandleBuffer); + } + } + + CoreRemoveDebugImageInfoEntry (Image->Handle); + + Status = CoreUninstallProtocolInterface ( + Image->Handle, + &gEfiLoadedImageProtocolGuid, + &Image->Info + ); + } + + if (Image->RuntimeFixupValid) { + // + // Remove the Image from the Runtime Image list as we are about to Free it! + // + RemoveEntryList (&Image->Link); + } + + // + // Free the Image from memory + // + if ((Image->ImageBasePage != 0) && FreePage) { + CoreFreePages (Image->ImageBasePage, Image->NumberOfPages); + } + + // + // Done with the Image structure + // + if (Image->Info.FilePath != NULL) { + CoreFreePool (Image->Info.FilePath); + } + + if (Image->FixupData != NULL) { + CoreFreePool (Image->FixupData); + } + + CoreFreePool (Image); +} + + + +EFI_STATUS +EFIAPI +CoreExit ( + IN EFI_HANDLE ImageHandle, + IN EFI_STATUS Status, + IN UINTN ExitDataSize, + IN CHAR16 *ExitData OPTIONAL + ) +/*++ + +Routine Description: + + Terminates the currently loaded EFI image and returns control to boot services. + +Arguments: + + ImageHandle - Handle that identifies the image. This parameter is passed to the image + on entry. + Status - The image¡¯s exit code. + ExitDataSize - The size, in bytes, of ExitData. Ignored if ExitStatus is + EFI_SUCCESS. + ExitData - Pointer to a data buffer that includes a Null-terminated Unicode string, + optionally followed by additional binary data. The string is a + description that the caller may use to further indicate the reason for + the image¡¯s exit. + +Returns: + + EFI_INVALID_PARAMETER - Image handle is NULL or it is not current image. + + EFI_SUCCESS - Successfully terminates the currently loaded EFI image. + + EFI_ACCESS_DENIED - Should never reach there. + + EFI_OUT_OF_RESOURCES - Could not allocate pool + +--*/ +{ + LOADED_IMAGE_PRIVATE_DATA *Image; + + Image = CoreLoadedImageInfo (ImageHandle); + if (Image == NULL_HANDLE) { + return EFI_INVALID_PARAMETER; + } + + if (!Image->Started) { + // + // The image has not been started so just free its resources + // + CoreUnloadAndCloseImage (Image, TRUE); + return EFI_SUCCESS; + } + + // + // Image has been started, verify this image can exit + // + if (Image != mCurrentImage) { + DEBUG ((EFI_D_LOAD|EFI_D_ERROR, "Exit: Image is not exitable image\n")); + return EFI_INVALID_PARAMETER; + } + + // + // Set status + // + Image->Status = Status; + + // + // If there's ExitData info, move it + // + if (ExitData != NULL) { + Image->ExitDataSize = ExitDataSize; + Image->ExitData = CoreAllocateBootServicesPool (Image->ExitDataSize); + if (Image->ExitData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CopyMem (Image->ExitData, ExitData, Image->ExitDataSize); + } + + // + // return to StartImage + // + LongJump (Image->JumpContext, (UINTN)-1); + + // + // If we return from LongJump, then it is an error + // + ASSERT (FALSE); + return EFI_ACCESS_DENIED; +} + + + +EFI_STATUS +EFIAPI +CoreUnloadImage ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Unloads an image. + +Arguments: + + ImageHandle - Handle that identifies the image to be unloaded. + +Returns: + + EFI_SUCCESS - The image has been unloaded. + EFI_UNSUPPORTED - The image has been sarted, and does not support unload. + EFI_INVALID_PARAMPETER - ImageHandle is not a valid image handle. + +--*/ +{ + EFI_STATUS Status; + LOADED_IMAGE_PRIVATE_DATA *Image; + + Image = CoreLoadedImageInfo (ImageHandle); + if (Image == NULL ) { + // + // The image handle is not valid + // + return EFI_INVALID_PARAMETER; + } + + if (Image->Started) { + // + // The image has been started, request it to unload. + // + Status = EFI_UNSUPPORTED; + if (Image->Info.Unload != NULL) { + Status = Image->Info.Unload (ImageHandle); + } + + } else { + // + // This Image hasn't been started, thus it can be unloaded + // + Status = EFI_SUCCESS; + } + + + if (!EFI_ERROR (Status)) { + // + // if the Image was not started or Unloaded O.K. then clean up + // + CoreUnloadAndCloseImage (Image, TRUE); + } + + return Status; +} + + +EFI_STATUS +EFIAPI +CoreUnloadImageEx ( + IN EFI_PE32_IMAGE_PROTOCOL *This, + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Unload the specified image. + +Arguments: + + This - Indicates the calling context. + + ImageHandle - The specified image handle. + +Returns: + + EFI_INVALID_PARAMETER - Image handle is NULL. + + EFI_UNSUPPORTED - Attempt to unload an unsupported image. + + EFI_SUCCESS - Image successfully unloaded. + +--*/ +{ + return CoreUnloadImage (ImageHandle); +} diff --git a/EdkModulePkg/Core/Dxe/Image/ImageFile.c b/EdkModulePkg/Core/Dxe/Image/ImageFile.c new file mode 100644 index 0000000000..999cd694ad --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Image/ImageFile.c @@ -0,0 +1,569 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ImageFile.c + + +Abstract: + + + + +Revision History + +--*/ + +#include + + +VOID +CoreDevicePathToFileName ( + IN FILEPATH_DEVICE_PATH *FilePath, + OUT CHAR16 **String + ); + + + +EFI_STATUS +CoreOpenImageFile ( + IN BOOLEAN BootPolicy, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + IN OUT EFI_DEVICE_PATH_PROTOCOL *FilePath, + OUT EFI_HANDLE *DeviceHandle, + IN IMAGE_FILE_HANDLE *ImageFileHandle, + OUT UINT32 *AuthenticationStatus + ) +/*++ + +Routine Description: + + Opens a file for (simple) reading. The simple read abstraction + will access the file either from a memory copy, from a file + system interface, or from the load file interface. + +Arguments: + + BootPolicy - Policy for Open Image File. + SourceBuffer - Pointer to the memory location containing copy + of the image to be loaded. + SourceSize - The size in bytes of SourceBuffer. + FilePath - The specific file path from which the image is loaded + DeviceHandle - Pointer to the return device handle. + ImageFileHandle - Pointer to the image file handle. + AuthenticationStatus - Pointer to a caller-allocated UINT32 in which the authentication status is returned. + +Returns: + + EFI_SUCCESS - Image file successfully opened. + + EFI_LOAD_ERROR - If the caller passed a copy of the file, and SourceSize is 0. + + EFI_INVALID_PARAMETER - File path is not valid. + + EFI_NOT_FOUND - File not found. + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *TempFilePath; + FILEPATH_DEVICE_PATH *FilePathNode; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FwVolFilePathNode; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; + EFI_FILE_HANDLE FileHandle; + EFI_FILE_HANDLE LastHandle; + EFI_LOAD_FILE_PROTOCOL *LoadFile; + EFI_FIRMWARE_VOLUME_PROTOCOL *FwVol; + EFI_SECTION_TYPE SectionType; + UINT8 *Pe32Buffer; + UINTN Pe32BufferSize; + EFI_FV_FILETYPE Type; + EFI_FV_FILE_ATTRIBUTES Attrib; + EFI_FILE_INFO *FileInfo; + UINTN FileInfoSize; + EFI_GUID *NameGuid; + + *AuthenticationStatus = 0; + ZeroMem (ImageFileHandle, sizeof (IMAGE_FILE_HANDLE)); + ImageFileHandle->Signature = IMAGE_FILE_HANDLE_SIGNATURE; + + // + // If the caller passed a copy of the file, then just use it + // + if (SourceBuffer != NULL) { + ImageFileHandle->Source = SourceBuffer; + ImageFileHandle->SourceSize = SourceSize; + *DeviceHandle = NULL; + if (SourceSize > 0) { + Status = EFI_SUCCESS; + } else { + Status = EFI_LOAD_ERROR; + } + goto Done; + } + + // + // Make sure FilePath is valid + // + if (FilePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Check to see if it's in a Firmware Volume + // + FwVolFilePathNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)FilePath; + Status = CoreDevicePathToInterface ( + &gEfiFirmwareVolumeProtocolGuid, + (EFI_DEVICE_PATH_PROTOCOL **)&FwVolFilePathNode, + (VOID*)&FwVol, + DeviceHandle + ); + if (!EFI_ERROR (Status)) { + // + // For FwVol File system there is only a single file name that is a GUID. + // + NameGuid = EfiGetNameGuidFromFwVolDevicePathNode (FwVolFilePathNode); + if (NameGuid != NULL) { + + SectionType = EFI_SECTION_PE32; + Pe32Buffer = NULL; + Status = FwVol->ReadSection ( + FwVol, + NameGuid, + SectionType, + 0, + (VOID **)&Pe32Buffer, + &Pe32BufferSize, + AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + // + // Try a raw file, since a PE32 SECTION does not exist + // + if (Pe32Buffer != NULL) { + CoreFreePool (Pe32Buffer); + *AuthenticationStatus = 0; + } + Pe32Buffer = NULL; + Status = FwVol->ReadFile ( + FwVol, + NameGuid, + (VOID **)&Pe32Buffer, + &Pe32BufferSize, + &Type, + &Attrib, + AuthenticationStatus + ); + } + + if (!EFI_ERROR (Status)) { + // + // One of the reads passed so we are done + // + ImageFileHandle->Source = Pe32Buffer; + ImageFileHandle->SourceSize = Pe32BufferSize; + ImageFileHandle->FreeBuffer = TRUE; + goto Done; + } + } + } + + // + // Attempt to access the file via a file system interface + // + FilePathNode = (FILEPATH_DEVICE_PATH *) FilePath; + Status = CoreDevicePathToInterface ( + &gEfiSimpleFileSystemProtocolGuid, + (EFI_DEVICE_PATH_PROTOCOL **)&FilePathNode, + (VOID*)&Volume, + DeviceHandle + ); + if (!EFI_ERROR (Status)) { + // + // Open the Volume to get the File System handle + // + Status = Volume->OpenVolume (Volume, &FileHandle); + if (!EFI_ERROR (Status)) { + + // + // Parse each MEDIA_FILEPATH_DP node. There may be more than one, since the + // directory information and filename can be seperate. The goal is to inch + // our way down each device path node and close the previous node + // + while (!IsDevicePathEnd (&FilePathNode->Header)) { + if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH || + DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) { + Status = EFI_UNSUPPORTED; + } + + if (EFI_ERROR (Status)) { + // + // Exit loop on Error + // + break; + } + + LastHandle = FileHandle; + FileHandle = NULL; + Status = LastHandle->Open ( + LastHandle, + &FileHandle, + FilePathNode->PathName, + EFI_FILE_MODE_READ, + 0 + ); + + // + // Close the previous node + // + LastHandle->Close (LastHandle); + + FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header); + } + + if (!EFI_ERROR (Status)) { + // + // We have found the file. Now we need to read it. Before we can read the file we need to + // figure out how big the file is. + // + FileInfo = NULL; + FileInfoSize = sizeof (EFI_FILE_INFO); + while (CoreGrowBuffer (&Status, (VOID **)&FileInfo, FileInfoSize)) { + // + // Automatically allocate buffer of the correct size and make the call + // + Status = FileHandle->GetInfo ( + FileHandle, + &gEfiFileInfoGuid, + &FileInfoSize, + FileInfo + ); + } + if (!EFI_ERROR (Status)) { + // + // Allocate space for the file + // + ImageFileHandle->Source = CoreAllocateBootServicesPool ((UINTN)FileInfo->FileSize); + if (ImageFileHandle->Source != NULL) { + // + // Read the file into the buffer we allocated + // + ImageFileHandle->SourceSize = (UINTN)FileInfo->FileSize; + ImageFileHandle->FreeBuffer = TRUE; + Status = FileHandle->Read (FileHandle, &ImageFileHandle->SourceSize, ImageFileHandle->Source); + + // + // Close the file since we are done + // + FileHandle->Close (FileHandle); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + + goto Done; + } + } + } + } + + + // + // Try LoadFile style + // + + TempFilePath = FilePath; + Status = CoreDevicePathToInterface ( + &gEfiLoadFileProtocolGuid, + &TempFilePath, + (VOID*)&LoadFile, + DeviceHandle + ); + if (!EFI_ERROR (Status)) { + // + // Call LoadFile with the correct buffer size + // + while (CoreGrowBuffer (&Status, (VOID **)&ImageFileHandle->Source, ImageFileHandle->SourceSize)) { + Status = LoadFile->LoadFile ( + LoadFile, + TempFilePath, + BootPolicy, + &ImageFileHandle->SourceSize, + ImageFileHandle->Source + ); + // + // If success or other error happens, stop loop + // + if (Status != EFI_BUFFER_TOO_SMALL) { + break; + } + } + + if (!EFI_ERROR (Status) || Status == EFI_ALREADY_STARTED) { + ImageFileHandle->FreeBuffer = TRUE; + goto Done; + } + } + + // + // Nothing else to try + // + DEBUG ((EFI_D_LOAD|EFI_D_WARN, "CoreOpenImageFile: Device did not support a known load protocol\n")); + Status = EFI_NOT_FOUND; + +Done: + + // + // If the file was not accessed, clean up + // + if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) { + if (ImageFileHandle->FreeBuffer) { + // + // Free the source buffer if we allocated it + // + CoreFreePool (ImageFileHandle->Source); + } + } + + return Status; +} + + + +EFI_STATUS +EFIAPI +CoreReadImageFile ( + IN VOID *UserHandle, + IN UINTN Offset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Read image file (specified by UserHandle) into user specified buffer with specified offset + and length. + +Arguments: + + UserHandle - Image file handle + + Offset - Offset to the source file + + ReadSize - For input, pointer of size to read; + For output, pointer of size actually read. + + Buffer - Buffer to write into + +Returns: + + EFI_SUCCESS - Successfully read the specified part of file into buffer. + +--*/ +{ + UINTN EndPosition; + IMAGE_FILE_HANDLE *FHand; + + FHand = (IMAGE_FILE_HANDLE *)UserHandle; + ASSERT (FHand->Signature == IMAGE_FILE_HANDLE_SIGNATURE); + + // + // Move data from our local copy of the file + // + EndPosition = Offset + *ReadSize; + if (EndPosition > FHand->SourceSize) { + *ReadSize = (UINT32)(FHand->SourceSize - Offset); + } + if (Offset >= FHand->SourceSize) { + *ReadSize = 0; + } + + CopyMem (Buffer, (CHAR8 *)FHand->Source + Offset, *ReadSize); + return EFI_SUCCESS; +} + +EFI_STATUS +CoreDevicePathToInterface ( + IN EFI_GUID *Protocol, + IN EFI_DEVICE_PATH_PROTOCOL **FilePath, + OUT VOID **Interface, + OUT EFI_HANDLE *Handle + ) +/*++ + +Routine Description: + + Search a handle to a device on a specified device path that supports a specified protocol, + interface of that protocol on that handle is another output. + +Arguments: + + Protocol - The protocol to search for + + FilePath - The specified device path + + Interface - Interface of the protocol on the handle + + Handle - The handle to the device on the specified device path that supports the protocol. + +Returns: + + Status code. + +--*/ +{ + EFI_STATUS Status; + + Status = CoreLocateDevicePath (Protocol, FilePath, Handle); + if (!EFI_ERROR (Status)) { + Status = CoreHandleProtocol (*Handle, Protocol, Interface); + } + return Status; +} + + +VOID +CoreDevicePathToFileName ( + IN FILEPATH_DEVICE_PATH *FilePath, + OUT CHAR16 **String + ) +/*++ + +Routine Description: + + Transfer a device's full path a string. + +Arguments: + + FilePath - Device path + + String - The string represent the device's full path + +Returns: + + None + +--*/ +{ + UINTN StringSize; + FILEPATH_DEVICE_PATH *FilePathNode; + CHAR16 *Str; + + *String = NULL; + StringSize = 0; + FilePathNode = FilePath; + while (!IsDevicePathEnd (&FilePathNode->Header)) { + + // + // For filesystem access each node should be a filepath component + // + if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH || + DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP) { + + return; + } + + StringSize += StrLen (FilePathNode->PathName); + + FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header); + } + + *String = CoreAllocateBootServicesPool (StringSize); + if (*String == NULL) { + return; + } + + FilePathNode = FilePath; + Str = *String; + while (!IsDevicePathEnd (&FilePathNode->Header)) { + StrCat (Str, FilePathNode->PathName); + FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header); + } +} + + +BOOLEAN +CoreGrowBuffer ( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + Helper function called as part of the code needed + to allocate the proper sized buffer for various + EFI interfaces. + +Arguments: + + Status - Current status + + Buffer - Current allocated buffer, or NULL + + BufferSize - Current buffer size needed + +Returns: + + TRUE - if the buffer was reallocated and the caller + should try the API again. + + FALSE - buffer could not be allocated and the caller + should not try the API again. + +--*/ +{ + BOOLEAN TryAgain; + + TryAgain = FALSE; + // + // If this is an initial request, buffer will be null with a new buffer size + // + if (*Buffer == NULL) { + *Status = EFI_BUFFER_TOO_SMALL; + } + + if (BufferSize == 0) { + return TRUE; + } + + // + // If the status code is "buffer too small", resize the buffer + // + + if (*Status == EFI_BUFFER_TOO_SMALL) { + if (*Buffer != NULL) { + CoreFreePool (*Buffer); + } + + *Buffer = CoreAllocateBootServicesPool (BufferSize); + if (*Buffer != NULL) { + TryAgain = TRUE; + } else { + *Status = EFI_OUT_OF_RESOURCES; + } + } + + // + // If there's an error, free the buffer + // + if ((!TryAgain) && (EFI_ERROR (*Status)) && (*Buffer)) { + CoreFreePool (*Buffer); + *Buffer = NULL; + } + + return TryAgain; +} + diff --git a/EdkModulePkg/Core/Dxe/Library.h b/EdkModulePkg/Core/Dxe/Library.h new file mode 100644 index 0000000000..5e33da5285 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Library.h @@ -0,0 +1,407 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Library.h + +Abstract: + +Revision History + +--*/ + +#ifndef _DXE_LIBRARY_H_ +#define _DXE_LIBRARY_H_ + + +VOID +CoreReportProgressCode ( + IN EFI_STATUS_CODE_VALUE Value + ) +/*++ + +Routine Description: + + Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid. + +Arguments: + + Value - Describes the class/subclass/operation of the hardware or software entity + that the Status Code relates to. + +Returns: + + None + +--*/ +; + +VOID +CoreReportProgressCodeSpecific ( + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_HANDLE Handle + ) +/*++ + +Routine Description: + + Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid, + with a handle as additional information. + +Arguments: + + Value - Describes the class/subclass/operation of the hardware or software entity + that the Status Code relates to. + + Handle - Additional information. + +Returns: + + None + +--*/ +; + +VOID +CoreAcquireLock ( + IN EFI_LOCK *Lock + ) +/*++ + +Routine Description: + + Raising to the task priority level of the mutual exclusion + lock, and then acquires ownership of the lock. + +Arguments: + + Lock - The lock to acquire + +Returns: + + Lock owned + +--*/ +; + +EFI_STATUS +CoreAcquireLockOrFail ( + IN EFI_LOCK *Lock + ) +/*++ + +Routine Description: + + Initialize a basic mutual exclusion lock. Each lock + provides mutual exclusion access at it's task priority + level. Since there is no-premption (at any TPL) or + multiprocessor support, acquiring the lock only consists + of raising to the locks TPL. + +Arguments: + + Lock - The EFI_LOCK structure to initialize + +Returns: + + EFI_SUCCESS - Lock Owned. + EFI_ACCESS_DENIED - Reentrant Lock Acquisition, Lock not Owned. + +--*/ +; + +VOID +CoreReleaseLock ( + IN EFI_LOCK *Lock + ) +/*++ + +Routine Description: + + Releases ownership of the mutual exclusion lock, and + restores the previous task priority level. + +Arguments: + + Lock - The lock to release + +Returns: + + Lock unowned + +--*/ +; + +// +// Device Path functions +// + +UINTN +CoreDevicePathSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + + Calculate the size of a whole device path. + +Arguments: + + DevicePath - The pointer to the device path data. + +Returns: + + Size of device path data structure.. + +--*/ +; + +BOOLEAN +CoreIsDevicePathMultiInstance ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Return TRUE is this is a multi instance device path. + +Arguments: + DevicePath - A pointer to a device path data structure. + + +Returns: + TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi + instance. + +--*/ +; + + +EFI_DEVICE_PATH_PROTOCOL * +CoreDuplicateDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Duplicate a new device path data structure from the old one. + +Arguments: + DevicePath - A pointer to a device path data structure. + +Returns: + A pointer to the new allocated device path data. + Caller must free the memory used by DevicePath if it is no longer needed. + +--*/ +; + +EFI_DEVICE_PATH_PROTOCOL * +CoreAppendDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *Src1, + IN EFI_DEVICE_PATH_PROTOCOL *Node + ) +/*++ + +Routine Description: + Function is used to append a Src1 and Src2 together. + +Arguments: + Src1 - A pointer to a device path data structure. + + Node - A pointer to a device path data structure. + +Returns: + + A pointer to the new device path is returned. + NULL is returned if space for the new device path could not be allocated from pool. + It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed. + +--*/ +; + +VOID * +CoreAllocateBootServicesPool ( + IN UINTN AllocationSize + ) +/*++ + +Routine Description: + + Allocate pool of type EfiBootServicesData, the size is specified with AllocationSize. + +Arguments: + + AllocationSize - Size to allocate. + +Returns: + + Pointer of the allocated pool. + +--*/ +; + +VOID * +CoreAllocateZeroBootServicesPool ( + IN UINTN AllocationSize + ) +/*++ + +Routine Description: + + Allocate pool of type EfiBootServicesData and zero it, the size is specified with AllocationSize. + +Arguments: + + AllocationSize - Size to allocate. + +Returns: + + Pointer of the allocated pool. + +--*/ +; + +EFI_STATUS +CoreGetConfigTable ( + IN EFI_GUID *Guid, + IN OUT VOID **Table + ) +/*++ + +Routine Description: + + Find a config table by name in system table's ConfigurationTable. + +Arguments: + + Guid - The table name to look for + + Table - Pointer of the config table + +Returns: + + EFI_NOT_FOUND - Could not find the table in system table's ConfigurationTable. + + EFI_SUCCESS - Table successfully found. + +--*/ +; + +VOID * +CoreAllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Allocate pool of specified size with EfiRuntimeServicesData type, and copy specified buffer to this pool. + +Arguments: + + AllocationSize - Size to allocate. + + Buffer - Specified buffer that will be copy to the allocated pool + +Returns: + + Pointer of the allocated pool. + +--*/ +; + +VOID * +CoreAllocateRuntimePool ( + IN UINTN AllocationSize + ) +/*++ + +Routine Description: + + Allocate pool of type EfiRuntimeServicesData, the size is specified with AllocationSize. + +Arguments: + + AllocationSize - Size to allocate. + +Returns: + + Pointer of the allocated pool. + +--*/ +; + +VOID * +CoreAllocateCopyPool ( + IN UINTN AllocationSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Allocate pool of specified size with EfiBootServicesData type, and copy specified buffer to this pool. + +Arguments: + + AllocationSize - Size to allocate. + + Buffer - Specified buffer that will be copy to the allocated pool + +Returns: + + Pointer of the allocated pool. + +--*/ +; + +EFI_EVENT +CoreCreateProtocolNotifyEvent ( + IN EFI_GUID *ProtocolGuid, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + OUT VOID **Registration, + IN BOOLEAN SignalFlag + ) +/*++ + +Routine Description: + + Create a protocol notification event and return it. + +Arguments: + + ProtocolGuid - Protocol to register notification event on. + + NotifyTpl - Maximum TPL to signal the NotifyFunction. + + NotifyFuncition - EFI notification routine. + + NotifyContext - Context passed into Event when it is created. + + Registration - Registration key returned from RegisterProtocolNotify(). + + SignalFlag - Boolean value to decide whether kick the event after register or not. + +Returns: + + The EFI_EVENT that has been registered to be signaled when a ProtocolGuid + is added to the system. + +--*/ +; + +#endif diff --git a/EdkModulePkg/Core/Dxe/Library/Library.c b/EdkModulePkg/Core/Dxe/Library/Library.c new file mode 100644 index 0000000000..74d873e3f8 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Library/Library.c @@ -0,0 +1,613 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Library.c + +Abstract: + + DXE Core library services. + +--*/ + +#include + +UINTN mErrorLevel = EFI_D_ERROR | EFI_D_LOAD; + +EFI_DEVICE_HANDLE_EXTENDED_DATA mStatusCodeData = { + { + sizeof (EFI_STATUS_CODE_DATA), + 0, + EFI_STATUS_CODE_SPECIFIC_DATA_GUID + }, + NULL +}; + +VOID +CoreReportProgressCodeSpecific ( + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_HANDLE Handle + ) +/*++ + +Routine Description: + + Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid, + with a handle as additional information. + +Arguments: + + Value - Describes the class/subclass/operation of the hardware or software entity + that the Status Code relates to. + + Handle - Additional information. + +Returns: + + None + +--*/ +{ + mStatusCodeData.DataHeader.Size = sizeof (EFI_DEVICE_HANDLE_EXTENDED_DATA) - sizeof (EFI_STATUS_CODE_DATA); + mStatusCodeData.Handle = Handle; + + if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) { + gStatusCode->ReportStatusCode ( + EFI_PROGRESS_CODE, + Value, + 0, + &gEfiDxeServicesTableGuid, + (EFI_STATUS_CODE_DATA *) &mStatusCodeData + ); + } +} + +VOID +CoreReportProgressCode ( + IN EFI_STATUS_CODE_VALUE Value + ) +/*++ + +Routine Description: + + Report status code of type EFI_PROGRESS_CODE by caller ID gEfiDxeServicesTableGuid. + +Arguments: + + Value - Describes the class/subclass/operation of the hardware or software entity + that the Status Code relates to. + +Returns: + + None + +--*/ +{ + if ((gStatusCode != NULL) && (gStatusCode->ReportStatusCode != NULL) ) { + gStatusCode->ReportStatusCode ( + EFI_PROGRESS_CODE, + Value, + 0, + &gEfiDxeServicesTableGuid, + NULL + ); + } +} + + +VOID * +CoreAllocateBootServicesPool ( + IN UINTN AllocationSize + ) +/*++ + +Routine Description: + + Allocate pool of type EfiBootServicesData, the size is specified with AllocationSize. + +Arguments: + + AllocationSize - Size to allocate. + +Returns: + + Pointer of the allocated pool. + +--*/ +{ + VOID *Memory; + + CoreAllocatePool (EfiBootServicesData, AllocationSize, &Memory); + return Memory; +} + + +VOID * +CoreAllocateZeroBootServicesPool ( + IN UINTN AllocationSize + ) +/*++ + +Routine Description: + + Allocate pool of type EfiBootServicesData and zero it, the size is specified with AllocationSize. + +Arguments: + + AllocationSize - Size to allocate. + +Returns: + + Pointer of the allocated pool. + +--*/ +{ + VOID *Memory; + + Memory = CoreAllocateBootServicesPool (AllocationSize); + SetMem (Memory, (Memory == NULL) ? 0 : AllocationSize, 0); + return Memory; +} + + +VOID * +CoreAllocateCopyPool ( + IN UINTN AllocationSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Allocate pool of specified size with EfiBootServicesData type, and copy specified buffer to this pool. + +Arguments: + + AllocationSize - Size to allocate. + + Buffer - Specified buffer that will be copy to the allocated pool + +Returns: + + Pointer of the allocated pool. + +--*/ +{ + VOID *Memory; + + Memory = CoreAllocateBootServicesPool (AllocationSize); + CopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize); + + return Memory; +} + + + +VOID * +CoreAllocateRuntimePool ( + IN UINTN AllocationSize + ) +/*++ + +Routine Description: + + Allocate pool of type EfiRuntimeServicesData, the size is specified with AllocationSize. + +Arguments: + + AllocationSize - Size to allocate. + +Returns: + + Pointer of the allocated pool. + +--*/ +{ + VOID *Memory; + + CoreAllocatePool (EfiRuntimeServicesData, AllocationSize, &Memory); + return Memory; +} + +VOID * +CoreAllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Allocate pool of specified size with EfiRuntimeServicesData type, and copy specified buffer to this pool. + +Arguments: + + AllocationSize - Size to allocate. + + Buffer - Specified buffer that will be copy to the allocated pool + +Returns: + + Pointer of the allocated pool. + +--*/ + +{ + VOID *Memory; + + Memory = CoreAllocateRuntimePool (AllocationSize); + CopyMem (Memory, Buffer, (Memory == NULL) ? 0 : AllocationSize); + + return Memory; +} + + + +// +// Lock Stuff +// + + + +EFI_STATUS +CoreAcquireLockOrFail ( + IN EFI_LOCK *Lock + ) +/*++ + +Routine Description: + + Initialize a basic mutual exclusion lock. Each lock + provides mutual exclusion access at it's task priority + level. Since there is no-premption (at any TPL) or + multiprocessor support, acquiring the lock only consists + of raising to the locks TPL. + +Arguments: + + Lock - The EFI_LOCK structure to initialize + +Returns: + + EFI_SUCCESS - Lock Owned. + EFI_ACCESS_DENIED - Reentrant Lock Acquisition, Lock not Owned. + +--*/ +{ + ASSERT (Lock != NULL); + ASSERT (Lock->Lock != EfiLockUninitialized); + + if (Lock->Lock == EfiLockAcquired) { + // + // Lock is already owned, so bail out + // + return EFI_ACCESS_DENIED; + } + + Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl); + + Lock->Lock = EfiLockAcquired; + return EFI_SUCCESS; +} + + +VOID +CoreAcquireLock ( + IN EFI_LOCK *Lock + ) +/*++ + +Routine Description: + + Raising to the task priority level of the mutual exclusion + lock, and then acquires ownership of the lock. + +Arguments: + + Lock - The lock to acquire + +Returns: + + Lock owned + +--*/ +{ + ASSERT (Lock != NULL); + ASSERT (Lock->Lock == EfiLockReleased); + + Lock->OwnerTpl = CoreRaiseTpl (Lock->Tpl); + Lock->Lock = EfiLockAcquired; +} + + +VOID +CoreReleaseLock ( + IN EFI_LOCK *Lock + ) +/*++ + +Routine Description: + + Releases ownership of the mutual exclusion lock, and + restores the previous task priority level. + +Arguments: + + Lock - The lock to release + +Returns: + + Lock unowned + +--*/ +{ + EFI_TPL Tpl; + + ASSERT (Lock != NULL); + ASSERT (Lock->Lock == EfiLockAcquired); + + Tpl = Lock->OwnerTpl; + + Lock->Lock = EfiLockReleased; + + CoreRestoreTpl (Tpl); +} + + +UINTN +CoreDevicePathSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + + Calculate the size of a whole device path. + +Arguments: + + DevicePath - The pointer to the device path data. + +Returns: + + Size of device path data structure.. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = DevicePath; + while (!EfiIsDevicePathEnd (DevicePath)) { + DevicePath = EfiNextDevicePathNode (DevicePath); + } + + // + // Compute the size and add back in the size of the end device path structure + // + return ((UINTN)DevicePath - (UINTN)Start) + sizeof(EFI_DEVICE_PATH_PROTOCOL); +} + + +BOOLEAN +CoreIsDevicePathMultiInstance ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Return TRUE is this is a multi instance device path. + +Arguments: + DevicePath - A pointer to a device path data structure. + + +Returns: + TRUE - If DevicePath is multi instance. FALSE - If DevicePath is not multi + instance. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + + if (DevicePath == NULL) { + return FALSE; + } + + Node = DevicePath; + while (!EfiIsDevicePathEnd (Node)) { + if (EfiIsDevicePathEndInstance (Node)) { + return TRUE; + } + Node = EfiNextDevicePathNode (Node); + } + return FALSE; +} + + + +EFI_DEVICE_PATH_PROTOCOL * +CoreDuplicateDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Duplicate a new device path data structure from the old one. + +Arguments: + DevicePath - A pointer to a device path data structure. + +Returns: + A pointer to the new allocated device path data. + Caller must free the memory used by DevicePath if it is no longer needed. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + UINTN Size; + + if (DevicePath == NULL) { + return NULL; + } + + // + // Compute the size + // + Size = CoreDevicePathSize (DevicePath); + + // + // Allocate space for duplicate device path + // + NewDevicePath = CoreAllocateCopyPool (Size, DevicePath); + + return NewDevicePath; +} + + + +EFI_DEVICE_PATH_PROTOCOL * +CoreAppendDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *Src1, + IN EFI_DEVICE_PATH_PROTOCOL *Src2 + ) +/*++ + +Routine Description: + Function is used to append a Src1 and Src2 together. + +Arguments: + Src1 - A pointer to a device path data structure. + + Src2 - A pointer to a device path data structure. + +Returns: + + A pointer to the new device path is returned. + NULL is returned if space for the new device path could not be allocated from pool. + It is up to the caller to free the memory used by Src1 and Src2 if they are no longer needed. + +--*/ +{ + UINTN Size; + UINTN Size1; + UINTN Size2; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath; + + if (Src1 == NULL && Src2 == NULL) { + return NULL; + } + + // + // Allocate space for the combined device path. It only has one end node of + // length EFI_DEVICE_PATH_PROTOCOL + // + Size1 = CoreDevicePathSize (Src1); + Size2 = CoreDevicePathSize (Src2); + Size = Size1 + Size2 - sizeof(EFI_DEVICE_PATH_PROTOCOL); + + NewDevicePath = CoreAllocateCopyPool (Size, Src1); + if (NewDevicePath != NULL) { + + // + // Over write Src1 EndNode and do the copy + // + SecondDevicePath = (EFI_DEVICE_PATH_PROTOCOL *)((CHAR8 *)NewDevicePath + (Size1 - sizeof(EFI_DEVICE_PATH_PROTOCOL))); + CopyMem (SecondDevicePath, Src2, Size2); + } + + return NewDevicePath; +} + + + +EFI_EVENT +CoreCreateProtocolNotifyEvent ( + IN EFI_GUID *ProtocolGuid, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + OUT VOID **Registration, + IN BOOLEAN SignalFlag + ) +/*++ + +Routine Description: + + Create a protocol notification event and return it. + +Arguments: + + ProtocolGuid - Protocol to register notification event on. + + NotifyTpl - Maximum TPL to signal the NotifyFunction. + + NotifyFuncition - EFI notification routine. + + NotifyContext - Context passed into Event when it is created. + + Registration - Registration key returned from RegisterProtocolNotify(). + + SignalFlag - Boolean value to decide whether kick the event after register or not. + +Returns: + + The EFI_EVENT that has been registered to be signaled when a ProtocolGuid + is added to the system. + +--*/ +{ + EFI_STATUS Status; + EFI_EVENT Event; + + // + // Create the event + // + + Status = CoreCreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + NotifyTpl, + NotifyFunction, + NotifyContext, + &Event + ); + ASSERT_EFI_ERROR (Status); + + // + // Register for protocol notifactions on this event + // + + Status = CoreRegisterProtocolNotify ( + ProtocolGuid, + Event, + Registration + ); + ASSERT_EFI_ERROR (Status); + + if (SignalFlag) { + // + // Kick the event so we will perform an initial pass of + // current installed drivers + // + CoreSignalEvent (Event); + } + + return Event; +} + diff --git a/EdkModulePkg/Core/Dxe/Mem/Page.c b/EdkModulePkg/Core/Dxe/Mem/Page.c new file mode 100644 index 0000000000..e65b0283c6 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Mem/Page.c @@ -0,0 +1,1589 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + page.c + +Abstract: + + EFI Memory page management + + +Revision History + +--*/ + +#include + +#define EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE) + +// +// Entry for tracking the memory regions for each memory type to help cooalese like memory types +// +typedef struct { + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_PHYSICAL_ADDRESS MaximumAddress; + UINT64 CurrentNumberOfPages; + UINTN InformationIndex; +} EFI_MEMORY_TYPE_STAISTICS; + +// +// MemoryMap - The current memory map +// +UINTN mMemoryMapKey = 0; + +// +// mMapStack - space to use as temp storage to build new map descriptors +// mMapDepth - depth of new descriptor stack +// + +#define MAX_MAP_DEPTH 6 +UINTN mMapDepth = 0; +MEMORY_MAP mMapStack[MAX_MAP_DEPTH]; +UINTN mFreeMapStack = 0; + +BOOLEAN mMemoryTypeInformationInitialized = FALSE; + +EFI_MEMORY_TYPE_STAISTICS mMemoryTypeStatistics[EfiMaxMemoryType + 1] = { + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiReservedMemoryType + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiLoaderCode + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiLoaderData + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiBootServicesCode + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiBootServicesData + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiRuntimeServicesCode + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiRuntimeServicesData + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiConventionalMemory + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiUnusableMemory + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiACPIReclaimMemory + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiACPIMemoryNVS + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiMemoryMappedIO + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiMemoryMappedIOPortSpace + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType }, // EfiPalCode + { 0, EFI_MAX_ADDRESS, 0, EfiMaxMemoryType } // EfiMaxMemoryType +}; + +EFI_PHYSICAL_ADDRESS mDefaultMaximumAddress = EFI_MAX_ADDRESS; + +EFI_MEMORY_TYPE_INFORMATION gMemoryTypeInformation[EfiMaxMemoryType + 1] = { + { EfiReservedMemoryType, 0 }, + { EfiLoaderCode, 0 }, + { EfiLoaderData, 0 }, + { EfiBootServicesCode, 0 }, + { EfiBootServicesData, 0 }, + { EfiRuntimeServicesCode, 0 }, + { EfiRuntimeServicesData, 0 }, + { EfiConventionalMemory, 0 }, + { EfiUnusableMemory, 0 }, + { EfiACPIReclaimMemory, 0 }, + { EfiACPIMemoryNVS, 0 }, + { EfiMemoryMappedIO, 0 }, + { EfiMemoryMappedIOPortSpace, 0 }, + { EfiPalCode, 0 }, + { EfiMaxMemoryType, 0 } +}; + +// +// Internal prototypes +// +VOID +PromoteMemoryResource ( + VOID +); + +STATIC +VOID +CoreAddRange ( + IN EFI_MEMORY_TYPE Type, + IN EFI_PHYSICAL_ADDRESS Start, + IN EFI_PHYSICAL_ADDRESS End, + IN UINT64 Attribute + ); + +STATIC +VOID +CoreFreeMemoryMapStack ( + VOID + ); + +STATIC +EFI_STATUS +CoreConvertPages ( + IN UINT64 Start, + IN UINT64 NumberOfPages, + IN EFI_MEMORY_TYPE NewType + ); + +STATIC +VOID +RemoveMemoryMapEntry ( + MEMORY_MAP *Entry + ); + +VOID +CoreAcquireMemoryLock ( + VOID + ) +/*++ + +Routine Description: + + Enter critical section by gaining lock on gMemoryLock + +Arguments: + + None + +Returns: + + None + +--*/ +{ + CoreAcquireLock (&gMemoryLock); +} + + +VOID +CoreReleaseMemoryLock ( + VOID + ) +/*++ + +Routine Description: + + Exit critical section by releasing lock on gMemoryLock + +Arguments: + + None + +Returns: + + None + +--*/ +{ + CoreReleaseLock (&gMemoryLock); +} + +VOID +PromoteMemoryResource ( + VOID + ) +/*++ + +Routine Description: + + Find untested but initialized memory regions in GCD map and convert them to be DXE allocatable. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + LIST_ENTRY *Link; + EFI_GCD_MAP_ENTRY *Entry; + + DEBUG ((EFI_D_ERROR | EFI_D_PAGE, "Promote the memory resource\n")); + + CoreAcquireGcdMemoryLock (); + + Link = mGcdMemorySpaceMap.ForwardLink; + while (Link != &mGcdMemorySpaceMap) { + + Entry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + + if (Entry->GcdMemoryType == EfiGcdMemoryTypeReserved && + Entry->EndAddress < EFI_MAX_ADDRESS && + (Entry->Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) == + (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED)) { + // + // Update the GCD map + // + Entry->GcdMemoryType = EfiGcdMemoryTypeSystemMemory; + Entry->Capabilities |= EFI_MEMORY_TESTED; + Entry->ImageHandle = gDxeCoreImageHandle; + Entry->DeviceHandle = NULL; + + // + // Add to allocable system memory resource + // + + CoreAddRange ( + EfiConventionalMemory, + Entry->BaseAddress, + Entry->EndAddress, + Entry->Capabilities & ~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME) + ); + CoreFreeMemoryMapStack (); + + } + + Link = Link->ForwardLink; + } + + CoreReleaseGcdMemoryLock (); + + return; +} + +VOID +CoreAddMemoryDescriptor ( + IN EFI_MEMORY_TYPE Type, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 NumberOfPages, + IN UINT64 Attribute + ) +/*++ + +Routine Description: + + Called to initialize the memory map and add descriptors to + the current descriptor list. + + The first descriptor that is added must be general usable + memory as the addition allocates heap. + +Arguments: + + Type - The type of memory to add + + Start - The starting address in the memory range + Must be page aligned + + NumberOfPages - The number of pages in the range + + Attribute - Attributes of the memory to add + +Returns: + + None. The range is added to the memory map + +--*/ +{ + EFI_PHYSICAL_ADDRESS End; + EFI_STATUS Status; + UINTN Index; + UINTN FreeIndex; + + if ((Start & EFI_PAGE_MASK) != 0) { + return; + } + + if (Type >= EfiMaxMemoryType && Type <= 0x7fffffff) { + return; + } + + CoreAcquireMemoryLock (); + End = Start + LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT) - 1; + CoreAddRange (Type, Start, End, Attribute); + CoreFreeMemoryMapStack (); + CoreReleaseMemoryLock (); + + // + // Check to see if the statistics for the different memory types have already been established + // + if (mMemoryTypeInformationInitialized) { + return; + } + + // + // Loop through each memory type in the order specified by the gMemoryTypeInformation[] array + // + for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) { + // + // Make sure the memory type in the gMemoryTypeInformation[] array is valid + // + Type = gMemoryTypeInformation[Index].Type; + if (Type < 0 || Type > EfiMaxMemoryType) { + continue; + } + + if (gMemoryTypeInformation[Index].NumberOfPages != 0) { + // + // Allocate pages for the current memory type from the top of available memory + // + Status = CoreAllocatePages ( + AllocateAnyPages, + Type, + gMemoryTypeInformation[Index].NumberOfPages, + &mMemoryTypeStatistics[Type].BaseAddress + ); + if (EFI_ERROR (Status)) { + // + // If an error occurs allocating the pages for the current memory type, then + // free all the pages allocates for the previous memory types and return. This + // operation with be retied when/if more memory is added to the system + // + for (FreeIndex = 0; FreeIndex < Index; FreeIndex++) { + // + // Make sure the memory type in the gMemoryTypeInformation[] array is valid + // + Type = gMemoryTypeInformation[FreeIndex].Type; + if (Type < 0 || Type > EfiMaxMemoryType) { + continue; + } + + if (gMemoryTypeInformation[FreeIndex].NumberOfPages != 0) { + CoreFreePages ( + mMemoryTypeStatistics[Type].BaseAddress, + gMemoryTypeInformation[FreeIndex].NumberOfPages + ); + mMemoryTypeStatistics[Type].BaseAddress = 0; + mMemoryTypeStatistics[Type].MaximumAddress = EFI_MAX_ADDRESS; + } + } + return; + } + + // + // Compute the address at the top of the current statistics + // + mMemoryTypeStatistics[Type].MaximumAddress = + mMemoryTypeStatistics[Type].BaseAddress + + LShiftU64 (gMemoryTypeInformation[Index].NumberOfPages, EFI_PAGE_SHIFT) - 1; + + // + // If the current base address is the lowest address so far, then update the default + // maximum address + // + if (mMemoryTypeStatistics[Type].BaseAddress < mDefaultMaximumAddress) { + mDefaultMaximumAddress = mMemoryTypeStatistics[Type].BaseAddress - 1; + } + } + } + + // + // There was enough system memory for all the the memory types were allocated. So, + // those memory areas can be freed for future allocations, and all future memory + // allocations can occur within their respective bins + // + for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) { + // + // Make sure the memory type in the gMemoryTypeInformation[] array is valid + // + Type = gMemoryTypeInformation[Index].Type; + if (Type < 0 || Type > EfiMaxMemoryType) { + continue; + } + + if (gMemoryTypeInformation[Index].NumberOfPages != 0) { + CoreFreePages ( + mMemoryTypeStatistics[Type].BaseAddress, + gMemoryTypeInformation[Index].NumberOfPages + ); + gMemoryTypeInformation[Index].NumberOfPages = 0; + } + } + + // + // If the number of pages reserved for a memory type is 0, then all allocations for that type + // should be in the default range. + // + for (Type = 0; Type < EfiMaxMemoryType; Type++) { + for (Index = 0; gMemoryTypeInformation[Index].Type != EfiMaxMemoryType; Index++) { + if (Type == (EFI_MEMORY_TYPE)gMemoryTypeInformation[Index].Type) { + mMemoryTypeStatistics[Type].InformationIndex = Index; + } + } + mMemoryTypeStatistics[Type].CurrentNumberOfPages = 0; + if (mMemoryTypeStatistics[Type].MaximumAddress == EFI_MAX_ADDRESS) { + mMemoryTypeStatistics[Type].MaximumAddress = mDefaultMaximumAddress; + } + } + + mMemoryTypeInformationInitialized = TRUE; +} + + +STATIC +VOID +CoreAddRange ( + IN EFI_MEMORY_TYPE Type, + IN EFI_PHYSICAL_ADDRESS Start, + IN EFI_PHYSICAL_ADDRESS End, + IN UINT64 Attribute + ) +/*++ + +Routine Description: + + Internal function. Adds a ranges to the memory map. + The range must not already exist in the map. + +Arguments: + + Type - The type of memory range to add + + Start - The starting address in the memory range + Must be paged aligned + + End - The last address in the range + Must be the last byte of a page + + Attribute - The attributes of the memory range to add + +Returns: + + None. The range is added to the memory map + +--*/ +{ + LIST_ENTRY *Link; + MEMORY_MAP *Entry; + + ASSERT ((Start & EFI_PAGE_MASK) == 0); + ASSERT (End > Start) ; + + ASSERT_LOCKED (&gMemoryLock); + + DEBUG ((EFI_D_PAGE, "AddRange: %lx-%lx to %d\n", Start, End, Type)); + + // + // Memory map being altered so updated key + // + mMemoryMapKey += 1; + + // + // UEFI 2.0 added an event group for notificaiton on memory map changes. + // So we need to signal this Event Group every time the memory map changes. + // If we are in EFI 1.10 compatability mode no event groups will be + // found and nothing will happen we we call this function. These events + // will get signaled but since a lock is held around the call to this + // function the notificaiton events will only be called after this funciton + // returns and the lock is released. + // + CoreNotifySignalList (&gEfiEventMemoryMapChangeGuid); + + // + // Look for adjoining memory descriptor + // + + // Two memory descriptors can only be merged if they have the same Type + // and the same Attribute + // + + Link = gMemoryMap.ForwardLink; + while (Link != &gMemoryMap) { + Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); + Link = Link->ForwardLink; + + if (Entry->Type != Type) { + continue; + } + + if (Entry->Attribute != Attribute) { + continue; + } + + if (Entry->End + 1 == Start) { + + Start = Entry->Start; + RemoveMemoryMapEntry (Entry); + + } else if (Entry->Start == End + 1) { + + End = Entry->End; + RemoveMemoryMapEntry (Entry); + } + } + + // + // Add descriptor + // + + mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE; + mMapStack[mMapDepth].FromPool = FALSE; + mMapStack[mMapDepth].Type = Type; + mMapStack[mMapDepth].Start = Start; + mMapStack[mMapDepth].End = End; + mMapStack[mMapDepth].VirtualStart = 0; + mMapStack[mMapDepth].Attribute = Attribute; + InsertTailList (&gMemoryMap, &mMapStack[mMapDepth].Link); + + mMapDepth += 1; + ASSERT (mMapDepth < MAX_MAP_DEPTH); + + return ; +} + +STATIC +VOID +CoreFreeMemoryMapStack ( + VOID + ) +/*++ + +Routine Description: + + Internal function. Moves any memory descriptors that are on the + temporary descriptor stack to heap. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + MEMORY_MAP *Entry; + MEMORY_MAP *Entry2; + LIST_ENTRY *Link2; + + ASSERT_LOCKED (&gMemoryLock); + + // + // If already freeing the map stack, then return + // + if (mFreeMapStack) { + return ; + } + + // + // Move the temporary memory descriptor stack into pool + // + mFreeMapStack += 1; + + while (mMapDepth) { + + // + // Allocate memory for a entry + // + Entry = CoreAllocatePoolI (EfiRuntimeServicesData, sizeof(MEMORY_MAP)); + + ASSERT (Entry); + + // + // Update to proper entry + // + mMapDepth -= 1; + + if (mMapStack[mMapDepth].Link.ForwardLink != NULL) { + + // + // Move this entry to general pool + // + RemoveEntryList (&mMapStack[mMapDepth].Link); + mMapStack[mMapDepth].Link.ForwardLink = NULL; + + CopyMem (Entry , &mMapStack[mMapDepth], sizeof (MEMORY_MAP)); + Entry->FromPool = TRUE; + + // + // Find insertion location + // + for (Link2 = gMemoryMap.ForwardLink; Link2 != &gMemoryMap; Link2 = Link2->ForwardLink) { + Entry2 = CR (Link2, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); + if (Entry2->FromPool && Entry2->Start > Entry->Start) { + break; + } + } + + InsertTailList (Link2, &Entry->Link); + + } else { + + // + // It was removed, don't move it + // + CoreFreePoolI (Entry); + + } + } + + mFreeMapStack -= 1; +} + +STATIC +VOID +RemoveMemoryMapEntry ( + MEMORY_MAP *Entry + ) +/*++ + +Routine Description: + + Internal function. Removes a descriptor entry. + +Arguments: + + Entry - The entry to remove + +Returns: + + None + +--*/ +{ + RemoveEntryList (&Entry->Link); + Entry->Link.ForwardLink = NULL; + + if (Entry->FromPool) { + CoreFreePoolI (Entry); + } +} + + +STATIC +EFI_STATUS +CoreConvertPages ( + IN UINT64 Start, + IN UINT64 NumberOfPages, + IN EFI_MEMORY_TYPE NewType + ) +/*++ + +Routine Description: + + Internal function. Converts a memory range to the specified type. + The range must exist in the memory map. + +Arguments: + + Start - The first address of the range + Must be page aligned + + NumberOfPages - The number of pages to convert + + NewType - The new type for the memory range + +Returns: + + EFI_INVALID_PARAMETER - Invalid parameter + + EFI_NOT_FOUND - Could not find a descriptor cover the specified range + or convertion not allowed. + + EFI_SUCCESS - Successfully converts the memory range to the specified type. + +--*/ +{ + + UINT64 NumberOfBytes; + UINT64 End; + UINT64 RangeEnd; + UINT64 Attribute; + LIST_ENTRY *Link; + MEMORY_MAP *Entry; + + Entry = NULL; + NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT); + End = Start + NumberOfBytes - 1; + + ASSERT (NumberOfPages); + ASSERT ((Start & EFI_PAGE_MASK) == 0); + ASSERT (End > Start) ; + ASSERT_LOCKED (&gMemoryLock); + + if (NumberOfPages == 0 || (Start & EFI_PAGE_MASK ) || (Start > (Start + NumberOfBytes))) { + return EFI_INVALID_PARAMETER; + } + + // + // Convert the entire range + // + + while (Start < End) { + + // + // Find the entry that the covers the range + // + for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) { + Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); + + if (Entry->Start <= Start && Entry->End > Start) { + break; + } + } + + if (Link == &gMemoryMap) { + DEBUG ((EFI_D_ERROR | EFI_D_PAGE, "ConvertPages: failed to find range %lx - %lx\n", Start, End)); + return EFI_NOT_FOUND; + } + + // + // Convert range to the end, or to the end of the descriptor + // if that's all we've got + // + RangeEnd = End; + if (Entry->End < End) { + RangeEnd = Entry->End; + } + + DEBUG ((EFI_D_PAGE, "ConvertRange: %lx-%lx to %d\n", Start, RangeEnd, NewType)); + + // + // Debug code - verify conversion is allowed + // + if (!(NewType == EfiConventionalMemory ? 1 : 0) ^ (Entry->Type == EfiConventionalMemory ? 1 : 0)) { + DEBUG ((EFI_D_ERROR , "ConvertPages: Incompatible memory types\n")); + return EFI_NOT_FOUND; + } + + // + // Update counters for the number of pages allocated to each memory type + // + if (Entry->Type >= 0 && Entry->Type < EfiMaxMemoryType) { + if (Start >= mMemoryTypeStatistics[Entry->Type].BaseAddress && + Start <= mMemoryTypeStatistics[Entry->Type].MaximumAddress) { + if (NumberOfPages > mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages) { + mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages = 0; + } else { + mMemoryTypeStatistics[Entry->Type].CurrentNumberOfPages -= NumberOfPages; + } + } + } + + if (NewType >= 0 && NewType < EfiMaxMemoryType) { + if (Start >= mMemoryTypeStatistics[NewType].BaseAddress && Start <= mMemoryTypeStatistics[NewType].MaximumAddress) { + mMemoryTypeStatistics[NewType].CurrentNumberOfPages += NumberOfPages; + if (mMemoryTypeStatistics[NewType].CurrentNumberOfPages > + gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages) { + gMemoryTypeInformation[mMemoryTypeStatistics[NewType].InformationIndex].NumberOfPages = (UINT32)mMemoryTypeStatistics[NewType].CurrentNumberOfPages; + } + } + } + + // + // Pull range out of descriptor + // + if (Entry->Start == Start) { + + // + // Clip start + // + Entry->Start = RangeEnd + 1; + + } else if (Entry->End == RangeEnd) { + + // + // Clip end + // + Entry->End = Start - 1; + + } else { + + // + // Pull it out of the center, clip current + // + + // + // Add a new one + // + mMapStack[mMapDepth].Signature = MEMORY_MAP_SIGNATURE; + mMapStack[mMapDepth].FromPool = FALSE; + mMapStack[mMapDepth].Type = Entry->Type; + mMapStack[mMapDepth].Start = RangeEnd+1; + mMapStack[mMapDepth].End = Entry->End; + + // + // Inherit Attribute from the Memory Descriptor that is being clipped + // + mMapStack[mMapDepth].Attribute = Entry->Attribute; + + Entry->End = Start - 1; + ASSERT (Entry->Start < Entry->End); + + Entry = &mMapStack[mMapDepth]; + InsertTailList (&gMemoryMap, &Entry->Link); + + mMapDepth += 1; + ASSERT (mMapDepth < MAX_MAP_DEPTH); + } + + // + // The new range inherits the same Attribute as the Entry + //it is being cut out of + // + Attribute = Entry->Attribute; + + // + // If the descriptor is empty, then remove it from the map + // + if (Entry->Start == Entry->End + 1) { + RemoveMemoryMapEntry (Entry); + Entry = NULL; + } + + // + // Add our new range in + // + CoreAddRange (NewType, Start, RangeEnd, Attribute); + + // + // Move any map descriptor stack to general pool + // + CoreFreeMemoryMapStack (); + + // + // Bump the starting address, and convert the next range + // + Start = RangeEnd + 1; + } + + // + // Converted the whole range, done + // + + return EFI_SUCCESS; +} + + +STATIC +UINT64 +CoreFindFreePagesI ( + IN UINT64 MaxAddress, + IN UINT64 NumberOfPages, + IN EFI_MEMORY_TYPE NewType, + IN UINTN Alignment + ) +/*++ + +Routine Description: + + Internal function. Finds a consecutive free page range below + the requested address. + +Arguments: + + MaxAddress - The address that the range must be below + + NumberOfPages - Number of pages needed + + NewType - The type of memory the range is going to be turned into + + Alignment - Bits to align with + +Returns: + + The base address of the range, or 0 if the range was not found + +--*/ +{ + UINT64 NumberOfBytes; + UINT64 Target; + UINT64 DescStart; + UINT64 DescEnd; + UINT64 DescNumberOfBytes; + LIST_ENTRY *Link; + MEMORY_MAP *Entry; + + if ((MaxAddress < EFI_PAGE_MASK) ||(NumberOfPages == 0)) { + return 0; + } + + if ((MaxAddress & EFI_PAGE_MASK) != EFI_PAGE_MASK) { + + // + // If MaxAddress is not aligned to the end of a page + // + + // + // Change MaxAddress to be 1 page lower + // + MaxAddress -= (EFI_PAGE_MASK + 1); + + // + // Set MaxAddress to a page boundary + // + MaxAddress &= ~EFI_PAGE_MASK; + + // + // Set MaxAddress to end of the page + // + MaxAddress |= EFI_PAGE_MASK; + } + + NumberOfBytes = LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT); + Target = 0; + + for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) { + Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); + + // + // If it's not a free entry, don't bother with it + // + if (Entry->Type != EfiConventionalMemory) { + continue; + } + + DescStart = Entry->Start; + DescEnd = Entry->End; + + // + // If desc is past max allowed address, skip it + // + if (DescStart >= MaxAddress) { + continue; + } + + // + // If desc ends past max allowed address, clip the end + // + if (DescEnd >= MaxAddress) { + DescEnd = MaxAddress; + } + + DescEnd = ((DescEnd + 1) & (~(Alignment - 1))) - 1; + + // + // Compute the number of bytes we can used from this + // descriptor, and see it's enough to satisfy the request + // + DescNumberOfBytes = DescEnd - DescStart + 1; + + if (DescNumberOfBytes >= NumberOfBytes) { + + // + // If this is the best match so far remember it + // + if (DescEnd > Target) { + Target = DescEnd; + } + } + } + + // + // If this is a grow down, adjust target to be the allocation base + // + Target -= NumberOfBytes - 1; + + // + // If we didn't find a match, return 0 + // + if ((Target & EFI_PAGE_MASK) != 0) { + return 0; + } + + return Target; +} + +STATIC +UINT64 +FindFreePages ( + IN UINT64 MaxAddress, + IN UINT64 NoPages, + IN EFI_MEMORY_TYPE NewType, + IN UINTN Alignment + ) +/*++ + +Routine Description: + + Internal function. Finds a consecutive free page range below + the requested address + +Arguments: + + MaxAddress - The address that the range must be below + + NoPages - Number of pages needed + + NewType - The type of memory the range is going to be turned into + + Alignment - Bits to align with + +Returns: + + The base address of the range, or 0 if the range was not found. + +--*/ +{ + UINT64 NewMaxAddress; + UINT64 Start; + + NewMaxAddress = MaxAddress; + + if (NewType >= 0 && NewType < EfiMaxMemoryType && NewMaxAddress >= mMemoryTypeStatistics[NewType].MaximumAddress) { + NewMaxAddress = mMemoryTypeStatistics[NewType].MaximumAddress; + } else { + if (NewMaxAddress > mDefaultMaximumAddress) { + NewMaxAddress = mDefaultMaximumAddress; + } + } + + Start = CoreFindFreePagesI (NewMaxAddress, NoPages, NewType, Alignment); + if (!Start) { + Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment); + if (!Start) { + // + // Here means there may be no enough memory to use, so try to go through + // all the memory descript to promote the untested memory directly + // + PromoteMemoryResource (); + + // + // Allocate memory again after the memory resource re-arranged + // + Start = CoreFindFreePagesI (MaxAddress, NoPages, NewType, Alignment); + } + } + + return Start; +} + + +EFI_STATUS +EFIAPI +CoreAllocatePages ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ) +/*++ + +Routine Description: + + Allocates pages from the memory map. + +Arguments: + + Type - The type of allocation to perform + + MemoryType - The type of memory to turn the allocated pages into + + NumberOfPages - The number of pages to allocate + + Memory - A pointer to receive the base allocated memory address + +Returns: + + Status. On success, Memory is filled in with the base address allocated + + EFI_INVALID_PARAMETER - Parameters violate checking rules defined in spec. + + EFI_NOT_FOUND - Could not allocate pages match the requirement. + + EFI_OUT_OF_RESOURCES - No enough pages to allocate. + + EFI_SUCCESS - Pages successfully allocated. + +--*/ +{ + EFI_STATUS Status; + UINT64 Start; + UINT64 MaxAddress; + UINTN Alignment; + + if (Type < AllocateAnyPages || Type >= (UINTN) MaxAllocateType) { + return EFI_INVALID_PARAMETER; + } + + if ((MemoryType >= EfiMaxMemoryType && MemoryType <= 0x7fffffff) || + MemoryType == EfiConventionalMemory) { + return EFI_INVALID_PARAMETER; + } + + Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT; + + if (MemoryType == EfiACPIReclaimMemory || + MemoryType == EfiACPIMemoryNVS || + MemoryType == EfiRuntimeServicesCode || + MemoryType == EfiRuntimeServicesData) { + + Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT; + } + + if (Type == AllocateAddress) { + if ((*Memory & (Alignment - 1)) != 0) { + return EFI_NOT_FOUND; + } + } + + NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1; + NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1); + + // + // If this is for below a particular address, then + // + Start = *Memory; + + // + // The max address is the max natively addressable address for the processor + // + MaxAddress = EFI_MAX_ADDRESS; + + if (Type == AllocateMaxAddress) { + MaxAddress = Start; + } + + CoreAcquireMemoryLock (); + + // + // If not a specific address, then find an address to allocate + // + if (Type != AllocateAddress) { + Start = FindFreePages (MaxAddress, NumberOfPages, MemoryType, Alignment); + if (Start == 0) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + } + + // + // Convert pages from FreeMemory to the requested type + // + Status = CoreConvertPages (Start, NumberOfPages, MemoryType); + +Done: + CoreReleaseMemoryLock (); + + if (!EFI_ERROR (Status)) { + *Memory = Start; + } + + return Status; +} + + + + +EFI_STATUS +EFIAPI +CoreFreePages ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages + ) +/*++ + +Routine Description: + + Frees previous allocated pages. + +Arguments: + + Memory - Base address of memory being freed + + NumberOfPages - The number of pages to free + +Returns: + + EFI_NOT_FOUND - Could not find the entry that covers the range + + EFI_INVALID_PARAMETER - Address not aligned + + EFI_SUCCESS -Pages successfully freed. + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + MEMORY_MAP *Entry; + UINTN Alignment; + + // + // Free the range + // + CoreAcquireMemoryLock (); + + // + // Find the entry that the covers the range + // + Entry = NULL; + for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) { + Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); + if (Entry->Start <= Memory && Entry->End > Memory) { + break; + } + } + if (Link == &gMemoryMap) { + CoreReleaseMemoryLock (); + return EFI_NOT_FOUND; + } + + Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT; + + if (Entry->Type == EfiACPIReclaimMemory || + Entry->Type == EfiACPIMemoryNVS || + Entry->Type == EfiRuntimeServicesCode || + Entry->Type == EfiRuntimeServicesData) { + + Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT; + + } + + if ((Memory & (Alignment - 1)) != 0) { + CoreReleaseMemoryLock (); + return EFI_INVALID_PARAMETER; + } + + NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1; + NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1); + + Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory); + + CoreReleaseMemoryLock (); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Destroy the contents + // + if (Memory < EFI_MAX_ADDRESS) { + DEBUG_CLEAR_MEMORY ((VOID *)(UINTN)Memory, NumberOfPages << EFI_PAGE_SHIFT); + } + + return Status; +} + + + +EFI_STATUS +EFIAPI +CoreGetMemoryMap ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ) +/*++ + +Routine Description: + + This function returns a copy of the current memory map. The map is an array of + memory descriptors, each of which describes a contiguous block of memory. + +Arguments: + + MemoryMapSize - A pointer to the size, in bytes, of the MemoryMap buffer. On + input, this is the size of the buffer allocated by the caller. + On output, it is the size of the buffer returned by the firmware + if the buffer was large enough, or the size of the buffer needed + to contain the map if the buffer was too small. + MemoryMap - A pointer to the buffer in which firmware places the current memory map. + MapKey - A pointer to the location in which firmware returns the key for the + current memory map. + DescriptorSize - A pointer to the location in which firmware returns the size, in + bytes, of an individual EFI_MEMORY_DESCRIPTOR. + DescriptorVersion - A pointer to the location in which firmware returns the version + number associated with the EFI_MEMORY_DESCRIPTOR. + +Returns: + + EFI_SUCCESS - The memory map was returned in the MemoryMap buffer. + EFI_BUFFER_TOO_SMALL - The MemoryMap buffer was too small. The current buffer size + needed to hold the memory map is returned in MemoryMapSize. + EFI_INVALID_PARAMETER - One of the parameters has an invalid value. + +--*/ +{ + EFI_STATUS Status; + UINTN Size; + UINTN BufferSize; + UINTN NumberOfRuntimeEntries; + LIST_ENTRY *Link; + MEMORY_MAP *Entry; + EFI_GCD_MAP_ENTRY *GcdMapEntry; + + // + // Make sure the parameters are valid + // + if (MemoryMapSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireGcdMemoryLock (); + + // + // Count the number of Reserved and MMIO entries that are marked for runtime use + // + NumberOfRuntimeEntries = 0; + for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) { + GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) || + (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) { + if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) { + NumberOfRuntimeEntries++; + } + } + } + + Size = sizeof (EFI_MEMORY_DESCRIPTOR); + + // + // Make sure Size != sizeof(EFI_MEMORY_DESCRIPTOR). This will + // prevent people from having pointer math bugs in their code. + // now you have to use *DescriptorSize to make things work. + // + Size += sizeof(UINT64) - (Size % sizeof (UINT64)); + + if (DescriptorSize != NULL) { + *DescriptorSize = Size; + } + + if (DescriptorVersion != NULL) { + *DescriptorVersion = EFI_MEMORY_DESCRIPTOR_VERSION; + } + + CoreAcquireMemoryLock (); + + // + // Compute the buffer size needed to fit the entire map + // + BufferSize = Size * NumberOfRuntimeEntries; + for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) { + BufferSize += Size; + } + + if (*MemoryMapSize < BufferSize) { + Status = EFI_BUFFER_TOO_SMALL; + goto Done; + } + + if (MemoryMap == NULL) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + // + // Build the map + // + ZeroMem (MemoryMap, Size); + for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) { + Entry = CR (Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); + ASSERT (Entry->VirtualStart == 0); + + MemoryMap->Type = Entry->Type; + MemoryMap->PhysicalStart = Entry->Start; + MemoryMap->VirtualStart = Entry->VirtualStart; + MemoryMap->NumberOfPages = RShiftU64 (Entry->End - Entry->Start + 1, EFI_PAGE_SHIFT); + + switch (Entry->Type) { + case EfiRuntimeServicesCode: + case EfiRuntimeServicesData: + case EfiPalCode: + MemoryMap->Attribute = Entry->Attribute | EFI_MEMORY_RUNTIME; + break; + + default: + MemoryMap->Attribute = Entry->Attribute; + break; + } + + MemoryMap = NextMemoryDescriptor (MemoryMap, Size); + } + + for (Link = mGcdMemorySpaceMap.ForwardLink; Link != &mGcdMemorySpaceMap; Link = Link->ForwardLink) { + GcdMapEntry = CR (Link, EFI_GCD_MAP_ENTRY, Link, EFI_GCD_MAP_SIGNATURE); + if ((GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) || + (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo)) { + if ((GcdMapEntry->Attributes & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) { + + MemoryMap->PhysicalStart = GcdMapEntry->BaseAddress; + MemoryMap->VirtualStart = 0; + MemoryMap->NumberOfPages = MemoryMap->NumberOfPages = RShiftU64 ((GcdMapEntry->EndAddress - GcdMapEntry->BaseAddress + 1), EFI_PAGE_SHIFT); + MemoryMap->Attribute = GcdMapEntry->Attributes & ~EFI_MEMORY_PORT_IO; + + if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeReserved) { + MemoryMap->Type = EfiReservedMemoryType; + } else if (GcdMapEntry->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) { + if ((GcdMapEntry->Attributes & EFI_MEMORY_PORT_IO) == EFI_MEMORY_PORT_IO) { + MemoryMap->Type = EfiMemoryMappedIOPortSpace; + } else { + MemoryMap->Type = EfiMemoryMappedIO; + } + } + + MemoryMap = NextMemoryDescriptor (MemoryMap, Size); + } + } + } + + Status = EFI_SUCCESS; + +Done: + + CoreReleaseMemoryLock (); + + CoreReleaseGcdMemoryLock (); + + // + // Update the map key finally + // + if (MapKey != NULL) { + *MapKey = mMemoryMapKey; + } + + *MemoryMapSize = BufferSize; + + return Status; +} + +VOID * +CoreAllocatePoolPages ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN NumberOfPages, + IN UINTN Alignment + ) +/*++ + +Routine Description: + + Internal function. Used by the pool functions to allocate pages + to back pool allocation requests. + +Arguments: + + PoolType - The type of memory for the new pool pages + + NumberOfPages - No of pages to allocate + + Alignment - Bits to align. + +Returns: + + The allocated memory, or NULL + +--*/ +{ + EFI_STATUS Status; + UINT64 Start; + + // + // Find the pages to convert + // + Start = FindFreePages (EFI_MAX_ADDRESS, NumberOfPages, PoolType, Alignment); + + // + // Convert it to boot services data + // + if (Start == 0) { + DEBUG ((EFI_D_ERROR | EFI_D_PAGE, "AllocatePoolPages: failed to allocate %d pages\n", NumberOfPages)); + } else { + Status = CoreConvertPages (Start, NumberOfPages, PoolType); + } + + return (VOID *)(UINTN)Start; +} + +VOID +CoreFreePoolPages ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages + ) +/*++ + +Routine Description: + + Internal function. Frees pool pages allocated via AllocatePoolPages () + +Arguments: + + Memory - The base address to free + + NumberOfPages - The number of pages to free + +Returns: + + None + +--*/ +{ + CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory); +} + + +EFI_STATUS +CoreTerminateMemoryMap ( + IN UINTN MapKey + ) +/*++ + +Routine Description: + + Make sure the memory map is following all the construction rules, + it is the last time to check memory map error before exit boot services. + +Arguments: + + MapKey - Memory map key + +Returns: + + EFI_INVALID_PARAMETER - Memory map not consistent with construction rules. + + EFI_SUCCESS - Valid memory map. + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + MEMORY_MAP *Entry; + + Status = EFI_SUCCESS; + + CoreAcquireMemoryLock (); + + if (MapKey == mMemoryMapKey) { + + // + // Make sure the memory map is following all the construction rules + // This is the last chance we will be able to display any messages on + // the console devices. + // + + for (Link = gMemoryMap.ForwardLink; Link != &gMemoryMap; Link = Link->ForwardLink) { + Entry = CR(Link, MEMORY_MAP, Link, MEMORY_MAP_SIGNATURE); + if (Entry->Attribute & EFI_MEMORY_RUNTIME) { + if (Entry->Type == EfiACPIReclaimMemory || Entry->Type == EfiACPIMemoryNVS) { + DEBUG((EFI_D_ERROR, "ExitBootServices: ACPI memory entry has RUNTIME attribute set.\n")); + CoreReleaseMemoryLock (); + return EFI_INVALID_PARAMETER; + } + if (Entry->Start & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) { + DEBUG((EFI_D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n")); + CoreReleaseMemoryLock (); + return EFI_INVALID_PARAMETER; + } + if ((Entry->End + 1) & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) { + DEBUG((EFI_D_ERROR, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n")); + CoreReleaseMemoryLock (); + return EFI_INVALID_PARAMETER; + } + } + } + + // + // The map key they gave us matches what we expect. Fall through and + // return success. In an ideal world we would clear out all of + // EfiBootServicesCode and EfiBootServicesData. However this function + // is not the last one called by ExitBootServices(), so we have to + // preserve the memory contents. + // + } else { + Status = EFI_INVALID_PARAMETER; + } + + CoreReleaseMemoryLock (); + + return Status; +} + + + + + + + + diff --git a/EdkModulePkg/Core/Dxe/Mem/memdata.c b/EdkModulePkg/Core/Dxe/Mem/memdata.c new file mode 100644 index 0000000000..2fa4843102 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Mem/memdata.c @@ -0,0 +1,41 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + memdata.c + +Abstract: + + Global data used in memory service + + +Revision History + +--*/ + +#include + + +// +// MemoryLock - synchronizes access to the memory map and pool lists +// +EFI_LOCK gMemoryLock = EFI_INITIALIZE_LOCK_VARIABLE (EFI_TPL_NOTIFY); + +// +// MemoryMap - the current memory map +// +LIST_ENTRY gMemoryMap = INITIALIZE_LIST_HEAD_VARIABLE (gMemoryMap); + +// +// MemoryLastConvert - the last memory descriptor used for a conversion request +// +MEMORY_MAP *gMemoryLastConvert; diff --git a/EdkModulePkg/Core/Dxe/Mem/pool.c b/EdkModulePkg/Core/Dxe/Mem/pool.c new file mode 100644 index 0000000000..2f4669e6c1 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Mem/pool.c @@ -0,0 +1,613 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + pool.c + +Abstract: + + EFI Memory pool management + +Revision History + +--*/ + +#include + +#define POOL_FREE_SIGNATURE EFI_SIGNATURE_32('p','f','r','0') +typedef struct { + UINT32 Signature; + UINT32 Index; + LIST_ENTRY Link; +} POOL_FREE; + + +#define POOL_HEAD_SIGNATURE EFI_SIGNATURE_32('p','h','d','0') +typedef struct { + UINT32 Signature; + UINT32 Size; + EFI_MEMORY_TYPE Type; + UINTN Reserved; + CHAR8 Data[1]; +} POOL_HEAD; + +#define SIZE_OF_POOL_HEAD EFI_FIELD_OFFSET(POOL_HEAD,Data) + +#define POOL_TAIL_SIGNATURE EFI_SIGNATURE_32('p','t','a','l') +typedef struct { + UINT32 Signature; + UINT32 Size; +} POOL_TAIL; + + +#define POOL_SHIFT 7 + +#define POOL_OVERHEAD (SIZE_OF_POOL_HEAD + sizeof(POOL_TAIL)) + +#define HEAD_TO_TAIL(a) \ + ((POOL_TAIL *) (((CHAR8 *) (a)) + (a)->Size - sizeof(POOL_TAIL))); + + +#define SIZE_TO_LIST(a) ((a) >> POOL_SHIFT) +#define LIST_TO_SIZE(a) ((a+1) << POOL_SHIFT) + +#define MAX_POOL_LIST SIZE_TO_LIST(DEFAULT_PAGE_ALLOCATION) + +#define MAX_POOL_SIZE 0xffffff00 + +// +// Globals +// + +#define POOL_SIGNATURE EFI_SIGNATURE_32('p','l','s','t') +typedef struct { + INTN Signature; + UINTN Used; + EFI_MEMORY_TYPE MemoryType; + LIST_ENTRY FreeList[MAX_POOL_LIST]; + LIST_ENTRY Link; +} POOL; + + +POOL PoolHead[EfiMaxMemoryType]; +LIST_ENTRY PoolHeadList; + +// +// +// + +VOID +CoreInitializePool ( + VOID + ) +/*++ + +Routine Description: + + Called to initialize the pool. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + UINTN Type; + UINTN Index; + + for (Type=0; Type < EfiMaxMemoryType; Type++) { + PoolHead[Type].Signature = 0; + PoolHead[Type].Used = 0; + PoolHead[Type].MemoryType = Type; + for (Index=0; Index < MAX_POOL_LIST; Index++) { + InitializeListHead (&PoolHead[Type].FreeList[Index]); + } + } + InitializeListHead (&PoolHeadList); +} + + +POOL * +LookupPoolHead ( + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Look up pool head for specified memory type. + +Arguments: + + MemoryType - Memory type of which pool head is looked for + +Returns: + + Pointer of Corresponding pool head. + +--*/ +{ + LIST_ENTRY *Link; + POOL *Pool; + UINTN Index; + + if (MemoryType >= 0 && MemoryType < EfiMaxMemoryType) { + return &PoolHead[MemoryType]; + } + + if (MemoryType < 0) { + + for (Link = PoolHeadList.ForwardLink; Link != &PoolHeadList; Link = Link->ForwardLink) { + Pool = CR(Link, POOL, Link, POOL_SIGNATURE); + if (Pool->MemoryType == MemoryType) { + return Pool; + } + } + + Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL)); + if (Pool == NULL) { + return NULL; + } + + Pool->Signature = POOL_SIGNATURE; + Pool->Used = 0; + Pool->MemoryType = MemoryType; + for (Index=0; Index < MAX_POOL_LIST; Index++) { + InitializeListHead (&Pool->FreeList[Index]); + } + + InsertHeadList (&PoolHeadList, &Pool->Link); + + return Pool; + } + + return NULL; +} + + + +EFI_STATUS +EFIAPI +CoreAllocatePool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Allocate pool of a particular type. + +Arguments: + + PoolType - Type of pool to allocate + + Size - The amount of pool to allocate + + Buffer - The address to return a pointer to the allocated pool + +Returns: + + EFI_INVALID_PARAMETER - PoolType not valid + + EFI_OUT_OF_RESOURCES - Size exceeds max pool size or allocation failed. + + EFI_SUCCESS - Pool successfully allocated. + +--*/ +{ + EFI_STATUS Status; + + // + // If it's not a valid type, fail it + // + if ((PoolType >= EfiMaxMemoryType && PoolType <= 0x7fffffff) || + PoolType == EfiConventionalMemory) { + return EFI_INVALID_PARAMETER; + } + + *Buffer = NULL; + + // + // If size is too large, fail it + // Base on the EFI spec, return status of EFI_OUT_OF_RESOURCES + // + if (Size > MAX_POOL_SIZE) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Acquire the memory lock and make the allocation + // + Status = CoreAcquireLockOrFail (&gMemoryLock); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + *Buffer = CoreAllocatePoolI (PoolType, Size); + CoreReleaseMemoryLock (); + return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES; +} + + +VOID * +CoreAllocatePoolI ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size + ) +/*++ + +Routine Description: + + Internal function to allocate pool of a particular type. + + Caller must have the memory lock held + + +Arguments: + + PoolType - Type of pool to allocate + + Size - The amount of pool to allocate + +Returns: + + The allocate pool, or NULL + +--*/ +{ + POOL *Pool; + POOL_FREE *Free; + POOL_HEAD *Head; + POOL_TAIL *Tail; + CHAR8 *NewPage; + VOID *Buffer; + UINTN Index; + UINTN FSize; + UINTN offset; + UINTN Adjustment; + UINTN NoPages; + + ASSERT_LOCKED (&gMemoryLock); + + // + // Adjust the size by the pool header & tail overhead + // + + // + // Adjusting the Size to be of proper alignment so that + // we don't get an unaligned access fault later when + // pool_Tail is being initialized + // + ALIGN_VARIABLE (Size, Adjustment); + + Size += POOL_OVERHEAD; + Index = SIZE_TO_LIST(Size); + Pool = LookupPoolHead (PoolType); + if (Pool== NULL) { + return NULL; + } + Head = NULL; + + // + // If allocation is over max size, just allocate pages for the request + // (slow) + // + if (Index >= MAX_POOL_LIST) { + NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1; + NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1); + Head = CoreAllocatePoolPages (PoolType, NoPages, DEFAULT_PAGE_ALLOCATION); + goto Done; + } + + // + // If there's no free pool in the proper list size, go get some more pages + // + if (IsListEmpty (&Pool->FreeList[Index])) { + + // + // Get another page + // + NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION); + if (NewPage == NULL) { + goto Done; + } + + // + // Carve up new page into free pool blocks + // + offset = 0; + while (offset < DEFAULT_PAGE_ALLOCATION) { + ASSERT (Index < MAX_POOL_LIST); + FSize = LIST_TO_SIZE(Index); + + while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) { + Free = (POOL_FREE *) &NewPage[offset]; + Free->Signature = POOL_FREE_SIGNATURE; + Free->Index = (UINT32)Index; + InsertHeadList (&Pool->FreeList[Index], &Free->Link); + offset += FSize; + } + + Index -= 1; + } + + ASSERT (offset == DEFAULT_PAGE_ALLOCATION); + Index = SIZE_TO_LIST(Size); + } + + // + // Remove entry from free pool list + // + Free = CR (Pool->FreeList[Index].ForwardLink, POOL_FREE, Link, POOL_FREE_SIGNATURE); + RemoveEntryList (&Free->Link); + + Head = (POOL_HEAD *) Free; + +Done: + Buffer = NULL; + + if (Head != NULL) { + + // + // If we have a pool buffer, fill in the header & tail info + // + Head->Signature = POOL_HEAD_SIGNATURE; + Head->Size = (UINT32) Size; + Head->Type = (EFI_MEMORY_TYPE) PoolType; + Tail = HEAD_TO_TAIL (Head); + Tail->Signature = POOL_TAIL_SIGNATURE; + Tail->Size = (UINT32) Size; + Buffer = Head->Data; + DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD); + + DEBUG ( + (EFI_D_POOL, + "AllcocatePoolI: Type %x, Addr %x (len %x) %,d\n", + PoolType, + Buffer, + Size - POOL_OVERHEAD, + Pool->Used) + ); + + // + // Account the allocation + // + Pool->Used += Size; + + } else { + DEBUG ((EFI_D_ERROR | EFI_D_POOL, "AllocatePool: failed to allocate %d bytes\n", Size)); + } + + return Buffer; +} + + + +EFI_STATUS +EFIAPI +CoreFreePool ( + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Frees pool. + +Arguments: + + Buffer - The allocated pool entry to free + +Returns: + + EFI_INVALID_PARAMETER - Buffer is not a valid value. + + EFI_SUCCESS - Pool successfully freed. + +--*/ +{ + EFI_STATUS Status; + + if (NULL == Buffer) { + return EFI_INVALID_PARAMETER; + } + + CoreAcquireMemoryLock (); + Status = CoreFreePoolI (Buffer); + CoreReleaseMemoryLock (); + return Status; +} + + +EFI_STATUS +CoreFreePoolI ( + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Internal function to free a pool entry. + + Caller must have the memory lock held + + +Arguments: + + Buffer - The allocated pool entry to free + +Returns: + + EFI_INVALID_PARAMETER - Buffer not valid + + EFI_SUCCESS - Buffer successfully freed. + +--*/ +{ + POOL *Pool; + POOL_HEAD *Head; + POOL_TAIL *Tail; + POOL_FREE *Free; + UINTN Index; + UINTN NoPages; + UINTN Size; + CHAR8 *NewPage; + UINTN FSize; + UINTN offset; + BOOLEAN AllFree; + + ASSERT(NULL != Buffer); + // + // Get the head & tail of the pool entry + // + Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE); + ASSERT(NULL != Head); + + if (Head->Signature != POOL_HEAD_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + Tail = HEAD_TO_TAIL (Head); + ASSERT(NULL != Tail); + + // + // Debug + // + ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE); + ASSERT (Head->Size == Tail->Size); + ASSERT_LOCKED (&gMemoryLock); + + if (Tail->Signature != POOL_TAIL_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + if (Head->Size != Tail->Size) { + return EFI_INVALID_PARAMETER; + } + + // + // Determine the pool type and account for it + // + Size = Head->Size; + Pool = LookupPoolHead (Head->Type); + if (Pool == NULL) { + return EFI_INVALID_PARAMETER; + } + Pool->Used -= Size; + DEBUG ((EFI_D_POOL, "FreePool: %x (len %x) %,d\n", Head->Data, Head->Size - POOL_OVERHEAD, Pool->Used)); + + // + // Determine the pool list + // + Index = SIZE_TO_LIST(Size); + DEBUG_CLEAR_MEMORY (Head, Size); + + // + // If it's not on the list, it must be pool pages + // + if (Index >= MAX_POOL_LIST) { + + // + // Return the memory pages back to free memory + // + NoPages = EFI_SIZE_TO_PAGES(Size) + EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1; + NoPages &= ~(EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION) - 1); + CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN) Head, NoPages); + + } else { + + // + // Put the pool entry onto the free pool list + // + Free = (POOL_FREE *) Head; + ASSERT(NULL != Free); + Free->Signature = POOL_FREE_SIGNATURE; + Free->Index = (UINT32)Index; + InsertHeadList (&Pool->FreeList[Index], &Free->Link); + + // + // See if all the pool entries in the same page as Free are freed pool + // entries + // + NewPage = (CHAR8 *)((UINTN)Free & ~((DEFAULT_PAGE_ALLOCATION) -1)); + Free = (POOL_FREE *) &NewPage[0]; + ASSERT(NULL != Free); + + if (Free->Signature == POOL_FREE_SIGNATURE) { + + Index = Free->Index; + + AllFree = TRUE; + offset = 0; + + while ((offset < DEFAULT_PAGE_ALLOCATION) && (AllFree)) { + FSize = LIST_TO_SIZE(Index); + while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) { + Free = (POOL_FREE *) &NewPage[offset]; + ASSERT(NULL != Free); + if (Free->Signature != POOL_FREE_SIGNATURE) { + AllFree = FALSE; + } + offset += FSize; + } + Index -= 1; + } + + if (AllFree) { + + // + // All of the pool entries in the same page as Free are free pool + // entries + // Remove all of these pool entries from the free loop lists. + // + Free = (POOL_FREE *) &NewPage[0]; + ASSERT(NULL != Free); + Index = Free->Index; + offset = 0; + + while (offset < DEFAULT_PAGE_ALLOCATION) { + FSize = LIST_TO_SIZE(Index); + while (offset + FSize <= DEFAULT_PAGE_ALLOCATION) { + Free = (POOL_FREE *) &NewPage[offset]; + ASSERT(NULL != Free); + RemoveEntryList (&Free->Link); + offset += FSize; + } + Index -= 1; + } + + // + // Free the page + // + CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION)); + } + } + } + + // + // If this is an OS specific memory type, then check to see if the last + // portion of that memory type has been freed. If it has, then free the + // list entry for that memory type + // + if (Pool->MemoryType < 0 && Pool->Used == 0) { + RemoveEntryList (&Pool->Link); + CoreFreePoolI (Pool); + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/Dxe/Misc/DebugImageInfo.c b/EdkModulePkg/Core/Dxe/Misc/DebugImageInfo.c new file mode 100644 index 0000000000..e7f90de025 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Misc/DebugImageInfo.c @@ -0,0 +1,260 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugImageInfo.c + +Abstract: + + Support functions for managing debug image info table when loading and unloading + images. + +--*/ + +#include + + +static EFI_DEBUG_IMAGE_INFO_TABLE_HEADER mDebugInfoTableHeader = { + 0, // volatile UINT32 UpdateStatus; + 0, // UINT32 TableSize; + NULL // EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable; +}; + +static EFI_SYSTEM_TABLE_POINTER *mDebugTable = NULL; + + +VOID +CoreInitializeDebugImageInfoTable ( + VOID + ) +/*++ + +Routine Description: + + Creates and initializes the DebugImageInfo Table. Also creates the configuration + table and registers it into the system table. + +Arguments: + None + +Returns: + NA + +Notes: + This function allocates memory, frees it, and then allocates memory at an + address within the initial allocation. Since this function is called early + in DXE core initialization (before drivers are dispatched), this should not + be a problem. + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Mem; + UINTN NumberOfPages; + + // + // Allocate boot services memory for the structure. It's required to be aligned on + // a 4M boundary, so allocate a 4M block (plus what we require), free it up, calculate + // a 4M aligned address within the memory we just freed, and then allocate memory at that + // address for our initial structure. + // + NumberOfPages = FOUR_MEG_PAGES + EFI_SIZE_TO_PAGES(sizeof (EFI_SYSTEM_TABLE_POINTER)); + + Status = CoreAllocatePages (AllocateAnyPages, EfiBootServicesData, NumberOfPages , &Mem); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR(Status)) { + return; + } + Status = CoreFreePages (Mem, NumberOfPages); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR(Status)) { + return; + } + // + // Now get a 4M aligned address within the memory range we were given. + // Then allocate memory at that address + // + Mem = (Mem + FOUR_MEG_MASK) & (~FOUR_MEG_MASK); + + Status = CoreAllocatePages (AllocateAddress, EfiBootServicesData, NumberOfPages - FOUR_MEG_PAGES, &Mem); + ASSERT_EFI_ERROR (Status); + if (EFI_ERROR(Status)) { + return; + } + // + // We now have a 4M aligned page allocated, so fill in the data structure. + // Ideally we would update the CRC now as well, but the service may not yet be available. + // See comments in the CoreUpdateDebugTableCrc32() function below for details. + // + mDebugTable = (EFI_SYSTEM_TABLE_POINTER *)(UINTN)Mem; + mDebugTable->Signature = EFI_SYSTEM_TABLE_SIGNATURE; + mDebugTable->EfiSystemTableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) gST; + mDebugTable->Crc32 = 0; + Status = CoreInstallConfigurationTable (&gEfiDebugImageInfoTableGuid, &mDebugInfoTableHeader); + ASSERT_EFI_ERROR (Status); +} + +VOID +CoreUpdateDebugTableCrc32 ( + VOID + ) +/*++ + +Routine Description: + + Update the CRC32 in the Debug Table. + Since the CRC32 service is made available by the Runtime driver, we have to + wait for the Runtime Driver to be installed before the CRC32 can be computed. + This function is called elsewhere by the core when the runtime architectural + protocol is produced. + +Arguments: + None + +Returns: + NA + +--*/ +{ + ASSERT(mDebugTable != NULL); + mDebugTable->Crc32 = 0; + gBS->CalculateCrc32 ((VOID *)mDebugTable, sizeof (EFI_SYSTEM_TABLE_POINTER), &mDebugTable->Crc32); +} + +VOID +CoreNewDebugImageInfoEntry ( + IN UINTN ImageInfoType, + IN EFI_LOADED_IMAGE_PROTOCOL *LoadedImage, + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Adds a new DebugImageInfo structure to the DebugImageInfo Table. Re-Allocates + the table if it's not large enough to accomidate another entry. + +Arguments: + + ImageInfoType - type of debug image information + LoadedImage - pointer to the loaded image protocol for the image being loaded + ImageHandle - image handle for the image being loaded + +Returns: + NA + +--*/ +{ + EFI_DEBUG_IMAGE_INFO *Table; + EFI_DEBUG_IMAGE_INFO *NewTable; + UINTN Index; + UINTN MaxTableIndex; + UINTN TableSize; + + // + // Set the flag indicating that we're in the process of updating the table. + // + mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; + + Table = mDebugInfoTableHeader.EfiDebugImageInfoTable; + MaxTableIndex = mDebugInfoTableHeader.TableSize; + + for (Index = 0; Index < MaxTableIndex; Index++) { + if (Table[Index].NormalImage == NULL) { + // + // We have found a free entry so exit the loop + // + break; + } + } + if (Index == MaxTableIndex) { + // + // Table is full, so re-allocate another page for a larger table... + // + TableSize = MaxTableIndex * EFI_DEBUG_TABLE_ENTRY_SIZE; + NewTable = CoreAllocateZeroBootServicesPool (TableSize + EFI_PAGE_SIZE); + if (NewTable == NULL) { + mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; + return; + } + // + // Copy the old table into the new one + // + CopyMem (NewTable, Table, TableSize); + // + // Free the old table + // + CoreFreePool (Table); + // + // Update the table header + // + Table = NewTable; + mDebugInfoTableHeader.EfiDebugImageInfoTable = NewTable; + mDebugInfoTableHeader.TableSize += EFI_PAGE_SIZE / EFI_DEBUG_TABLE_ENTRY_SIZE; + } + // + // Allocate data for new entry + // + Table[Index].NormalImage = CoreAllocateZeroBootServicesPool (sizeof (EFI_DEBUG_IMAGE_INFO_NORMAL)); + if (Table[Index].NormalImage != NULL) { + // + // Update the entry + // + Table[Index].NormalImage->ImageInfoType = (UINT32) ImageInfoType; + Table[Index].NormalImage->LoadedImageProtocolInstance = LoadedImage; + Table[Index].NormalImage->ImageHandle = ImageHandle; + } + mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; +} + + +VOID +CoreRemoveDebugImageInfoEntry ( + EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + Removes and frees an entry from the DebugImageInfo Table. + +Arguments: + + ImageHandle - image handle for the image being unloaded + +Returns: + + NA + +--*/ +{ + EFI_DEBUG_IMAGE_INFO *Table; + UINTN Index; + + mDebugInfoTableHeader.UpdateStatus |= EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; + + Table = mDebugInfoTableHeader.EfiDebugImageInfoTable; + + for (Index = 0; Index < mDebugInfoTableHeader.TableSize; Index++) { + if (Table[Index].NormalImage != NULL && Table[Index].NormalImage->ImageHandle == ImageHandle) { + // + // Found a match. Free up the record, then NULL the pointer to indicate the slot + // is free. + // + CoreFreePool (Table[Index].NormalImage); + Table[Index].NormalImage = NULL; + break; + } + } + mDebugInfoTableHeader.UpdateStatus &= ~EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS; +} + diff --git a/EdkModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c b/EdkModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c new file mode 100644 index 0000000000..e81fcad35a --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Misc/InstallConfigurationTable.c @@ -0,0 +1,214 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + InstallConfigurationTable.c + + +Abstract: + + Tiano Miscellaneous Services InstallConfigurationTable service + +--*/ + +#include + +#define CONFIG_TABLE_SIZE_INCREASED 0x10 + +UINTN mSystemTableAllocateSize = 0; + + +EFI_STATUS +CoreGetConfigTable ( + IN EFI_GUID *Guid, + OUT VOID **Table + ) +/*++ + +Routine Description: + + Find a config table by name in system table's ConfigurationTable. + +Arguments: + + Guid - The table name to look for + + Table - Pointer of the config table + +Returns: + + EFI_NOT_FOUND - Could not find the table in system table's ConfigurationTable. + + EFI_SUCCESS - Table successfully found. + +--*/ +{ + UINTN Index; + + for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { + if (CompareGuid (Guid, &(gST->ConfigurationTable[Index].VendorGuid))) { + *Table = gST->ConfigurationTable[Index].VendorTable; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + + +EFI_STATUS +EFIAPI +CoreInstallConfigurationTable ( + IN EFI_GUID *Guid, + IN VOID *Table + ) +/*++ + +Routine Description: + + Boot Service called to add, modify, or remove a system configuration table from + the EFI System Table. + +Arguments: + + Guid - Pointer to the GUID for the entry to add, update, or remove + Table - Pointer to the configuration table for the entry to add, update, or + remove, may be NULL. + +Returns: + + EFI_SUCCESS Guid, Table pair added, updated, or removed. + EFI_INVALID_PARAMETER Input GUID not valid. + EFI_NOT_FOUND Attempted to delete non-existant entry + EFI_OUT_OF_RESOURCES Not enough memory available + +--*/ +{ + UINTN Index; + EFI_CONFIGURATION_TABLE *EfiConfigurationTable; + + // + // If Guid is NULL, then this operation cannot be performed + // + if (Guid == NULL) { + return EFI_INVALID_PARAMETER; + } + + EfiConfigurationTable = gST->ConfigurationTable; + + // + // Search all the table for an entry that matches Guid + // + for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { + if (CompareGuid (Guid, &(gST->ConfigurationTable[Index].VendorGuid))) { + break; + } + } + + if (Index < gST->NumberOfTableEntries) { + // + // A match was found, so this is either a modify or a delete operation + // + if (Table != NULL) { + // + // If Table is not NULL, then this is a modify operation. + // Modify the table enty and return. + // + gST->ConfigurationTable[Index].VendorTable = Table; + return EFI_SUCCESS; + } + + // + // A match was found and Table is NULL, so this is a delete operation. + // + gST->NumberOfTableEntries--; + + // + // Copy over deleted entry + // + CopyMem ( + &(EfiConfigurationTable[Index]), + &(gST->ConfigurationTable[Index + 1]), + (gST->NumberOfTableEntries - Index) * sizeof (EFI_CONFIGURATION_TABLE) + ); + + } else { + + // + // No matching GUIDs were found, so this is an add operation. + // + + if (Table == NULL) { + // + // If Table is NULL on an add operation, then return an error. + // + return EFI_NOT_FOUND; + } + + // + // Assume that Index == gST->NumberOfTableEntries + // + if ((Index * sizeof (EFI_CONFIGURATION_TABLE)) >= mSystemTableAllocateSize) { + // + // Allocate a table with one additional entry. + // + mSystemTableAllocateSize += (CONFIG_TABLE_SIZE_INCREASED * sizeof (EFI_CONFIGURATION_TABLE)); + EfiConfigurationTable = CoreAllocateRuntimePool (mSystemTableAllocateSize); + if (EfiConfigurationTable == NULL) { + // + // If a new table could not be allocated, then return an error. + // + return EFI_OUT_OF_RESOURCES; + } + + if (gST->ConfigurationTable != NULL) { + // + // Copy the old table to the new table. + // + CopyMem ( + EfiConfigurationTable, + gST->ConfigurationTable, + Index * sizeof (EFI_CONFIGURATION_TABLE) + ); + + // + // Free Old Table + // + CoreFreePool (gST->ConfigurationTable); + } + + // + // Update System Table + // + gST->ConfigurationTable = EfiConfigurationTable; + } + + // + // Fill in the new entry + // + CopyMem ((VOID *)&EfiConfigurationTable[Index].VendorGuid, Guid, sizeof (EFI_GUID)); + EfiConfigurationTable[Index].VendorTable = Table; + + // + // This is an add operation, so increment the number of table entries + // + gST->NumberOfTableEntries++; + } + + // + // Fix up the CRC-32 in the EFI System Table + // + CalculateEfiHdrCrc (&gST->Hdr); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c b/EdkModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c new file mode 100644 index 0000000000..c11c926e06 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Misc/SetWatchdogTimer.c @@ -0,0 +1,83 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + SetWatchdogTimer.c + +Abstract: + + Tiano Miscellaneous Services SetWatchdogTimer service implementation + +--*/ + +#include + +#define WATCHDOG_TIMER_CALIBRATE_PER_SECOND 10000000 + + +EFI_STATUS +EFIAPI +CoreSetWatchdogTimer ( + IN UINTN Timeout, + IN UINT64 WatchdogCode, + IN UINTN DataSize, + IN CHAR16 *WatchdogData OPTIONAL + ) +/*++ + +Routine Description: + + Sets the system's watchdog timer. + +Arguments: + + Timeout The number of seconds. Zero disables the timer. + + ///////following three parameters are left for platform specific using + + WatchdogCode The numberic code to log. 0x0 to 0xffff are firmware + DataSize Size of the optional data + WatchdogData Optional Null terminated unicode string followed by binary + data. + +Returns: + + EFI_SUCCESS Timeout has been set + EFI_NOT_AVAILABLE_YET WatchdogTimer is not available yet + EFI_UNSUPPORTED System does not have a timer (currently not used) + EFI_DEVICE_ERROR Could not complete due to hardware error + +--*/ +{ + EFI_STATUS Status; + + // + // Check our architectural protocol + // + if (gWatchdogTimer == NULL) { + return EFI_NOT_AVAILABLE_YET; + } + + // + // Attempt to set the timeout + // + Status = gWatchdogTimer->SetTimerPeriod (gWatchdogTimer, MultU64x32 (Timeout, WATCHDOG_TIMER_CALIBRATE_PER_SECOND)); + + // + // Check for errors + // + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/Dxe/Misc/Stall.c b/EdkModulePkg/Core/Dxe/Misc/Stall.c new file mode 100644 index 0000000000..c251f31dc9 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/Misc/Stall.c @@ -0,0 +1,82 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Stall.c + +Abstract: + + Tiano Miscellaneous Services Stall service implementation + +--*/ + +// +// Include statements +// + +#include + + +EFI_STATUS +EFIAPI +CoreStall ( + IN UINTN Microseconds + ) +/*++ + +Routine Description: + + Introduces a fine-grained stall. + +Arguments: + + Microseconds The number of microseconds to stall execution + +Returns: + + EFI_SUCCESS - Execution was stalled for at least the requested amount + of microseconds. + + EFI_NOT_AVAILABLE_YET - gMetronome is not available yet + +--*/ +{ + UINT32 Counter; + UINT32 Remainder; + + if (gMetronome == NULL) { + return EFI_NOT_AVAILABLE_YET; + } + + // + // Calculate the number of ticks by dividing the number of microseconds by + // the TickPeriod. + // Calcullation is based on 100ns unit. + // + Counter = (UINT32) DivU64x32Remainder ( + Microseconds * 10, + gMetronome->TickPeriod, + &Remainder + ); + + // + // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick + // periods, thus attempting to ensure Microseconds of stall time. + // + if (Remainder != 0) { + Counter++; + } + + gMetronome->WaitForTick (gMetronome, Counter); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c b/EdkModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c new file mode 100644 index 0000000000..e98b80cddf --- /dev/null +++ b/EdkModulePkg/Core/Dxe/SectionExtraction/CoreSectionExtraction.c @@ -0,0 +1,1339 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CoreSectionExtraction.c + +Abstract: + + Section Extraction Protocol implementation. + + Stream database is implemented as a linked list of section streams, + where each stream contains a linked list of children, which may be leaves or + encapsulations. + + Children that are encapsulations generate new stream entries + when they are created. Streams can also be created by calls to + SEP->OpenSectionStream(). + + The database is only created far enough to return the requested data from + any given stream, or to determine that the requested data is not found. + + If a GUIDed encapsulation is encountered, there are three possiblilites. + + 1) A support protocol is found, in which the stream is simply processed with + the support protocol. + + 2) A support protocol is not found, but the data is available to be read + without processing. In this case, the database is built up through the + recursions to return the data, and a RPN event is set that will enable + the stream in question to be refreshed if and when the required section + extraction protocol is published.This insures the AuthenticationStatus + does not become stale in the cache. + + 3) A support protocol is not found, and the data is not available to be read + without it. This results in EFI_PROTOCOL_ERROR. + +--*/ + +#include + +// +// Local defines and typedefs +// +#define CORE_SECTION_CHILD_SIGNATURE EFI_SIGNATURE_32('S','X','C','S') +#define CHILD_SECTION_NODE_FROM_LINK(Node) \ + CR (Node, CORE_SECTION_CHILD_NODE, Link, CORE_SECTION_CHILD_SIGNATURE) + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + UINT32 Type; + UINT32 Size; + // + // StreamBase + OffsetInStream == pointer to section header in stream. The + // stream base is always known when walking the sections within. + // + UINT32 OffsetInStream; + // + // Then EncapsulatedStreamHandle below is always 0 if the section is NOT an + // encapsulating section. Otherwise, it contains the stream handle + // of the encapsulated stream. This handle is ALWAYS produced any time an + // encapsulating child is encountered, irrespective of whether the + // encapsulated stream is processed further. + // + UINTN EncapsulatedStreamHandle; + EFI_GUID *EncapsulationGuid; +} CORE_SECTION_CHILD_NODE; + +#define CORE_SECTION_STREAM_SIGNATURE EFI_SIGNATURE_32('S','X','S','S') +#define STREAM_NODE_FROM_LINK(Node) \ + CR (Node, CORE_SECTION_STREAM_NODE, Link, CORE_SECTION_STREAM_SIGNATURE) + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + UINTN StreamHandle; + UINT8 *StreamBuffer; + UINTN StreamLength; + LIST_ENTRY Children; + // + // Authentication status is from GUIDed encapsulations. + // + UINT32 AuthenticationStatus; +} CORE_SECTION_STREAM_NODE; + +#define NULL_STREAM_HANDLE 0 + +typedef struct { + CORE_SECTION_CHILD_NODE *ChildNode; + CORE_SECTION_STREAM_NODE *ParentStream; + VOID *Registration; + EFI_EVENT Event; +} RPN_EVENT_CONTEXT; + + + +// +// Local prototypes +// + +STATIC +BOOLEAN +ChildIsType ( + IN CORE_SECTION_STREAM_NODE *Stream, + IN CORE_SECTION_CHILD_NODE *Child, + IN EFI_SECTION_TYPE SearchType, + IN EFI_GUID *SectionDefinitionGuid + ); + +STATIC +VOID +EFIAPI +NotifyGuidedExtraction ( + IN EFI_EVENT Event, + IN VOID *RpnContext + ); + +STATIC +VOID +CreateGuidedExtractionRpnEvent ( + IN CORE_SECTION_STREAM_NODE *ParentStream, + IN CORE_SECTION_CHILD_NODE *ChildNode + ); + +EFI_STATUS +EFIAPI +OpenSectionStream ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamLength, + IN VOID *SectionStream, + OUT UINTN *SectionStreamHandle + ); + +EFI_STATUS +EFIAPI +GetSection ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamHandle, + IN EFI_SECTION_TYPE *SectionType, + IN EFI_GUID *SectionDefinitionGuid, + IN UINTN SectionInstance, + IN VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ); + +EFI_STATUS +EFIAPI +CloseSectionStream ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN StreamHandleToClose + ); + +STATIC +EFI_STATUS +FindStreamNode ( + IN UINTN SearchHandle, + OUT CORE_SECTION_STREAM_NODE **FoundStream + ); + +STATIC +EFI_STATUS +FindChildNode ( + IN CORE_SECTION_STREAM_NODE *SourceStream, + IN EFI_SECTION_TYPE SearchType, + IN UINTN *SectionInstance, + IN EFI_GUID *SectionDefinitionGuid, + OUT CORE_SECTION_CHILD_NODE **FoundChild, + OUT CORE_SECTION_STREAM_NODE **FoundStream, + OUT UINT32 *AuthenticationStatus + ); + +STATIC +EFI_STATUS +CreateChildNode ( + IN CORE_SECTION_STREAM_NODE *Stream, + IN UINT32 ChildOffset, + OUT CORE_SECTION_CHILD_NODE **ChildNode + ); + +STATIC +VOID +FreeChildNode ( + IN CORE_SECTION_CHILD_NODE *ChildNode + ); + +STATIC +EFI_STATUS +OpenSectionStreamEx ( + IN UINTN SectionStreamLength, + IN VOID *SectionStream, + IN BOOLEAN AllocateBuffer, + IN UINT32 AuthenticationStatus, + OUT UINTN *SectionStreamHandle + ); + +STATIC +BOOLEAN +IsValidSectionStream ( + IN VOID *SectionStream, + IN UINTN SectionStreamLength + ); + +// +// Module globals +// +LIST_ENTRY mStreamRoot = INITIALIZE_LIST_HEAD_VARIABLE (mStreamRoot); + +EFI_HANDLE mSectionExtractionHandle = NULL; + +EFI_SECTION_EXTRACTION_PROTOCOL mSectionExtraction = { + OpenSectionStream, + GetSection, + CloseSectionStream +}; + + +EFI_STATUS +EFIAPI +InitializeSectionExtraction ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Entry point of the section extraction code. Initializes an instance of the + section extraction interface and installs it on a new handle. + +Arguments: + ImageHandle EFI_HANDLE: A handle for the image that is initializing this driver + SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table + +Returns: + EFI_SUCCESS: Driver initialized successfully + EFI_OUT_OF_RESOURCES: Could not allocate needed resources + +--*/ +{ + EFI_STATUS Status; + + // + // Install SEP to a new handle + // + Status = CoreInstallProtocolInterface ( + &mSectionExtractionHandle, + &gEfiSectionExtractionProtocolGuid, + EFI_NATIVE_INTERFACE, + &mSectionExtraction + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + + +EFI_STATUS +EFIAPI +OpenSectionStream ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamLength, + IN VOID *SectionStream, + OUT UINTN *SectionStreamHandle + ) +/*++ + +Routine Description: + SEP member function. This function creates and returns a new section stream + handle to represent the new section stream. + +Arguments: + This - Indicates the calling context. + SectionStreamLength - Size in bytes of the section stream. + SectionStream - Buffer containing the new section stream. + SectionStreamHandle - A pointer to a caller allocated UINTN that on output + contains the new section stream handle. + +Returns: + EFI_SUCCESS + EFI_OUT_OF_RESOURCES - memory allocation failed. + EFI_INVALID_PARAMETER - section stream does not end concident with end of + last section. + +--*/ +{ + // + // Check to see section stream looks good... + // + if (!IsValidSectionStream (SectionStream, SectionStreamLength)) { + return EFI_INVALID_PARAMETER; + } + + return OpenSectionStreamEx ( + SectionStreamLength, + SectionStream, + TRUE, + 0, + SectionStreamHandle + ); +} + + +EFI_STATUS +EFIAPI +GetSection ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamHandle, + IN EFI_SECTION_TYPE *SectionType, + IN EFI_GUID *SectionDefinitionGuid, + IN UINTN SectionInstance, + IN VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ) +/*++ + +Routine Description: + SEP member function. Retrieves requested section from section stream. + +Arguments: + This: Pointer to SEP instance. + SectionStreamHandle: The section stream from which to extract the requested + section. + SectionType: A pointer to the type of section to search for. + SectionDefinitionGuid: If the section type is EFI_SECTION_GUID_DEFINED, then + SectionDefinitionGuid indicates which of these types + of sections to search for. + SectionInstance: Indicates which instance of the requested section to + return. + Buffer: Double indirection to buffer. If *Buffer is non-null on + input, then the buffer is caller allocated. If + *Buffer is NULL, then the buffer is callee allocated. + In either case, the requried buffer size is returned + in *BufferSize. + BufferSize: On input, indicates the size of *Buffer if *Buffer is + non-null on input. On output, indicates the required + size (allocated size if callee allocated) of *Buffer. + AuthenticationStatus: Indicates the authentication status of the retrieved + section. + +Returns: + EFI_SUCCESS: Section was retrieved successfully + EFI_PROTOCOL_ERROR: A GUID defined section was encountered in the section + stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED + bit set, but there was no corresponding GUIDed Section + Extraction Protocol in the handle database. *Buffer is + unmodified. + EFI_NOT_FOUND: An error was encountered when parsing the SectionStream. + This indicates the SectionStream is not correctly + formatted. + EFI_NOT_FOUND: The requested section does not exist. + EFI_OUT_OF_RESOURCES: The system has insufficient resources to process the + request. + EFI_INVALID_PARAMETER: The SectionStreamHandle does not exist. + EFI_WARN_TOO_SMALL: The size of the caller allocated input buffer is + insufficient to contain the requested section. The + input buffer is filled and contents are section contents + are truncated. + +--*/ +{ + CORE_SECTION_STREAM_NODE *StreamNode; + EFI_TPL OldTpl; + EFI_STATUS Status; + CORE_SECTION_CHILD_NODE *ChildNode; + CORE_SECTION_STREAM_NODE *ChildStreamNode; + UINTN CopySize; + UINT32 ExtractedAuthenticationStatus; + UINTN Instance; + UINT8 *CopyBuffer; + UINTN SectionSize; + + + OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY); + Instance = SectionInstance + 1; + + // + // Locate target stream + // + Status = FindStreamNode (SectionStreamHandle, &StreamNode); + if (EFI_ERROR (Status)) { + Status = EFI_INVALID_PARAMETER; + goto GetSection_Done; + } + + // + // Found the stream, now locate and return the appropriate section + // + if (SectionType == NULL) { + // + // SectionType == NULL means return the WHOLE section stream... + // + CopySize = StreamNode->StreamLength; + CopyBuffer = StreamNode->StreamBuffer; + *AuthenticationStatus = StreamNode->AuthenticationStatus; + } else { + // + // There's a requested section type, so go find it and return it... + // + Status = FindChildNode ( + StreamNode, + *SectionType, + &Instance, + SectionDefinitionGuid, + &ChildNode, + &ChildStreamNode, + &ExtractedAuthenticationStatus + ); + if (EFI_ERROR (Status)) { + goto GetSection_Done; + } + CopySize = ChildNode->Size - sizeof (EFI_COMMON_SECTION_HEADER); + CopyBuffer = ChildStreamNode->StreamBuffer + ChildNode->OffsetInStream + sizeof (EFI_COMMON_SECTION_HEADER); + *AuthenticationStatus = ExtractedAuthenticationStatus; + } + + SectionSize = CopySize; + if (*Buffer != NULL) { + // + // Caller allocated buffer. Fill to size and return required size... + // + if (*BufferSize < CopySize) { + Status = EFI_WARN_BUFFER_TOO_SMALL; + CopySize = *BufferSize; + } + } else { + // + // Callee allocated buffer. Allocate buffer and return size. + // + *Buffer = CoreAllocateBootServicesPool (CopySize); + if (*Buffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto GetSection_Done; + } + } + CopyMem (*Buffer, CopyBuffer, CopySize); + *BufferSize = SectionSize; + +GetSection_Done: + CoreRestoreTpl (OldTpl); + return Status; +} + + + +EFI_STATUS +EFIAPI +CloseSectionStream ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN StreamHandleToClose + ) +/*++ + +Routine Description: + SEP member function. Deletes an existing section stream + +Arguments: + This - Indicates the calling context. + StreamHandleToClose - Indicates the stream to close + +Returns: + EFI_SUCCESS + EFI_OUT_OF_RESOURCES - memory allocation failed. + EFI_INVALID_PARAMETER - section stream does not end concident with end of + last section. + +--*/ +{ + CORE_SECTION_STREAM_NODE *StreamNode; + EFI_TPL OldTpl; + EFI_STATUS Status; + LIST_ENTRY *Link; + CORE_SECTION_CHILD_NODE *ChildNode; + + OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY); + + // + // Locate target stream + // + Status = FindStreamNode (StreamHandleToClose, &StreamNode); + if (!EFI_ERROR (Status)) { + // + // Found the stream, so close it + // + RemoveEntryList (&StreamNode->Link); + while (!IsListEmpty (&StreamNode->Children)) { + Link = GetFirstNode (&StreamNode->Children); + ChildNode = CHILD_SECTION_NODE_FROM_LINK (Link); + FreeChildNode (ChildNode); + } + CoreFreePool (StreamNode->StreamBuffer); + CoreFreePool (StreamNode); + Status = EFI_SUCCESS; + } else { + Status = EFI_INVALID_PARAMETER; + } + + CoreRestoreTpl (OldTpl); + return Status; +} + + +STATIC +BOOLEAN +ChildIsType ( + IN CORE_SECTION_STREAM_NODE *Stream, + IN CORE_SECTION_CHILD_NODE *Child, + IN EFI_SECTION_TYPE SearchType, + IN EFI_GUID *SectionDefinitionGuid + ) +/*++ + +Routine Description: + Worker function. Determine if the input stream:child matches the input type. + +Arguments: + Stream - Indicates the section stream associated with the child + Child - Indicates the child to check + SearchType - Indicates the type of section to check against for + SectionDefinitionGuid - Indicates the GUID to check against if the type is + EFI_SECTION_GUID_DEFINED +Returns: + TRUE - The child matches + FALSE - The child doesn't match + +--*/ +{ + EFI_GUID_DEFINED_SECTION *GuidedSection; + + if (SearchType == EFI_SECTION_ALL) { + return TRUE; + } + if (Child->Type != SearchType) { + return FALSE; + } + if (SearchType != EFI_SECTION_GUID_DEFINED) { + return TRUE; + } + GuidedSection = (EFI_GUID_DEFINED_SECTION * )(Stream->StreamBuffer + Child->OffsetInStream); + return CompareGuid (&GuidedSection->SectionDefinitionGuid, SectionDefinitionGuid); +} + + +STATIC +EFI_STATUS +FindChildNode ( + IN CORE_SECTION_STREAM_NODE *SourceStream, + IN EFI_SECTION_TYPE SearchType, + IN OUT UINTN *SectionInstance, + IN EFI_GUID *SectionDefinitionGuid, + OUT CORE_SECTION_CHILD_NODE **FoundChild, + OUT CORE_SECTION_STREAM_NODE **FoundStream, + OUT UINT32 *AuthenticationStatus + ) +/*++ + +Routine Description: + Worker function Recursively searches / builds section stream database + looking for requested section. + +Arguments: + SourceStream - Indicates the section stream in which to do the search. + SearchType - Indicates the type of section to search for. + SectionInstance - Indicates which instance of section to find. This is + an in/out parameter to deal with recursions. + SectionDefinitionGuid - Guid of section definition + FoundChild - Output indicating the child node that is found. + FoundStream - Output indicating which section stream the child was + found in. If this stream was generated as a result of + an encapsulation section, the streamhandle is visible + within the SEP driver only. + AuthenticationStatus- Indicates the authentication status of the found section. + +Returns: + EFI_SUCCESS - Child node was found and returned. + EFI_OUT_OF_RESOURCES- Memory allocation failed. + EFI_NOT_FOUND - Requested child node does not exist. + EFI_PROTOCOL_ERROR - a required GUIDED section extraction protocol does not + exist + +--*/ +{ + CORE_SECTION_CHILD_NODE *CurrentChildNode; + CORE_SECTION_CHILD_NODE *RecursedChildNode; + CORE_SECTION_STREAM_NODE *RecursedFoundStream; + UINT32 NextChildOffset; + EFI_STATUS ErrorStatus; + EFI_STATUS Status; + + CurrentChildNode = NULL; + ErrorStatus = EFI_NOT_FOUND; + + if (SourceStream->StreamLength == 0) { + return EFI_NOT_FOUND; + } + + if (IsListEmpty (&SourceStream->Children) && + SourceStream->StreamLength > sizeof (EFI_COMMON_SECTION_HEADER)) { + // + // This occurs when a section stream exists, but no child sections + // have been parsed out yet. Therefore, extract the first child and add it + // to the list of children so we can get started. + // + Status = CreateChildNode (SourceStream, 0, &CurrentChildNode); + if (EFI_ERROR (Status)) { + return Status; + } + } + + // + // At least one child has been parsed out of the section stream. So, walk + // through the sections that have already been parsed out looking for the + // requested section, if necessary, continue parsing section stream and + // adding children until either the requested section is found, or we run + // out of data + // + CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetFirstNode(&SourceStream->Children)); + + for (;;) { + if (ChildIsType (SourceStream, CurrentChildNode, SearchType, SectionDefinitionGuid)) { + // + // The type matches, so check the instance count to see if it's the one we want + // + (*SectionInstance)--; + if (*SectionInstance == 0) { + // + // Got it! + // + *FoundChild = CurrentChildNode; + *FoundStream = SourceStream; + *AuthenticationStatus = SourceStream->AuthenticationStatus; + return EFI_SUCCESS; + } + } + + if (CurrentChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) { + // + // If the current node is an encapsulating node, recurse into it... + // + Status = FindChildNode ( + (CORE_SECTION_STREAM_NODE *)CurrentChildNode->EncapsulatedStreamHandle, + SearchType, + SectionInstance, + SectionDefinitionGuid, + &RecursedChildNode, + &RecursedFoundStream, + AuthenticationStatus + ); + // + // If the status is not EFI_SUCCESS, just save the error code and continue + // to find the request child node in the rest stream. + // + if (*SectionInstance == 0) { + ASSERT_EFI_ERROR (Status); + *FoundChild = RecursedChildNode; + *FoundStream = RecursedFoundStream; + return EFI_SUCCESS; + } else { + ErrorStatus = Status; + } + } + + if (!IsNodeAtEnd (&SourceStream->Children, &CurrentChildNode->Link)) { + // + // We haven't found the child node we're interested in yet, but there's + // still more nodes that have already been parsed so get the next one + // and continue searching.. + // + CurrentChildNode = CHILD_SECTION_NODE_FROM_LINK (GetNextNode (&SourceStream->Children, &CurrentChildNode->Link)); + } else { + // + // We've exhausted children that have already been parsed, so see if + // there's any more data and continue parsing out more children if there + // is. + // + NextChildOffset = CurrentChildNode->OffsetInStream + CurrentChildNode->Size; + // + // Round up to 4 byte boundary + // + NextChildOffset += 3; + NextChildOffset &= ~(UINTN)3; + if (NextChildOffset <= SourceStream->StreamLength - sizeof (EFI_COMMON_SECTION_HEADER)) { + // + // There's an unparsed child remaining in the stream, so create a new child node + // + Status = CreateChildNode (SourceStream, NextChildOffset, &CurrentChildNode); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + ASSERT (EFI_ERROR (ErrorStatus)); + return ErrorStatus; + } + } + } +} + + +STATIC +EFI_STATUS +CreateChildNode ( + IN CORE_SECTION_STREAM_NODE *Stream, + IN UINT32 ChildOffset, + OUT CORE_SECTION_CHILD_NODE **ChildNode + ) +/*++ + +Routine Description: + Worker function. Constructor for new child nodes. + +Arguments: + Stream - Indicates the section stream in which to add the child. + ChildOffset - Indicates the offset in Stream that is the beginning + of the child section. + ChildNode - Indicates the Callee allocated and initialized child. + +Returns: + EFI_SUCCESS - Child node was found and returned. + EFI_OUT_OF_RESOURCES- Memory allocation failed. + EFI_PROTOCOL_ERROR - Encapsulation sections produce new stream handles when + the child node is created. If the section type is GUID + defined, and the extraction GUID does not exist, and + producing the stream requires the GUID, then a protocol + error is generated and no child is produced. + Values returned by OpenSectionStreamEx. + +--*/ +{ + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *SectionHeader; + EFI_COMPRESSION_SECTION *CompressionHeader; + EFI_GUID_DEFINED_SECTION *GuidedHeader; + EFI_TIANO_DECOMPRESS_PROTOCOL *Decompress; + EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction; + VOID *NewStreamBuffer; + VOID *ScratchBuffer; + UINT32 ScratchSize; + UINTN NewStreamBufferSize; + UINT32 AuthenticationStatus; + UINT32 SectionLength; + + CORE_SECTION_CHILD_NODE *Node; + + SectionHeader = (EFI_COMMON_SECTION_HEADER *) (Stream->StreamBuffer + ChildOffset); + + // + // Allocate a new node + // + *ChildNode = CoreAllocateBootServicesPool (sizeof (CORE_SECTION_CHILD_NODE)); + Node = *ChildNode; + if (Node == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Now initialize it + // + Node->Signature = CORE_SECTION_CHILD_SIGNATURE; + Node->Type = SectionHeader->Type; + Node->Size = SECTION_SIZE (SectionHeader); + Node->OffsetInStream = ChildOffset; + Node->EncapsulatedStreamHandle = NULL_STREAM_HANDLE; + Node->EncapsulationGuid = NULL; + + // + // If it's an encapsulating section, then create the new section stream also + // + switch (Node->Type) { + case EFI_SECTION_COMPRESSION: + // + // Get the CompressionSectionHeader + // + ASSERT (Node->Size >= sizeof (EFI_COMPRESSION_SECTION)); + + CompressionHeader = (EFI_COMPRESSION_SECTION *) SectionHeader; + + // + // Allocate space for the new stream + // + if (CompressionHeader->UncompressedLength > 0) { + NewStreamBufferSize = CompressionHeader->UncompressedLength; + NewStreamBuffer = CoreAllocateBootServicesPool (NewStreamBufferSize); + if (NewStreamBuffer == NULL) { + CoreFreePool (Node); + return EFI_OUT_OF_RESOURCES; + } + + if (CompressionHeader->CompressionType == EFI_NOT_COMPRESSED) { + // + // stream is not actually compressed, just encapsulated. So just copy it. + // + CopyMem (NewStreamBuffer, CompressionHeader + 1, NewStreamBufferSize); + } else if (CompressionHeader->CompressionType == EFI_STANDARD_COMPRESSION || + CompressionHeader->CompressionType == EFI_CUSTOMIZED_COMPRESSION) { + // + // Decompress the stream + // + if (CompressionHeader->CompressionType == EFI_STANDARD_COMPRESSION) { + Status = CoreLocateProtocol (&gEfiTianoDecompressProtocolGuid, NULL, (VOID **)&Decompress); + } else { + Status = CoreLocateProtocol (&gEfiCustomizedDecompressProtocolGuid, NULL, (VOID **)&Decompress); + } + + ASSERT_EFI_ERROR (Status); + + Status = Decompress->GetInfo ( + Decompress, + CompressionHeader + 1, + Node->Size - sizeof (EFI_COMPRESSION_SECTION), + (UINT32 *)&NewStreamBufferSize, + &ScratchSize + ); + ASSERT_EFI_ERROR (Status); + ASSERT (NewStreamBufferSize == CompressionHeader->UncompressedLength); + + ScratchBuffer = CoreAllocateBootServicesPool (ScratchSize); + if (ScratchBuffer == NULL) { + CoreFreePool (Node); + CoreFreePool (NewStreamBuffer); + return EFI_OUT_OF_RESOURCES; + } + + Status = Decompress->Decompress ( + Decompress, + CompressionHeader + 1, + Node->Size - sizeof (EFI_COMPRESSION_SECTION), + NewStreamBuffer, + (UINT32)NewStreamBufferSize, + ScratchBuffer, + ScratchSize + ); + ASSERT_EFI_ERROR (Status); + CoreFreePool (ScratchBuffer); + } + } else { + NewStreamBuffer = NULL; + NewStreamBufferSize = 0; + } + + Status = OpenSectionStreamEx ( + NewStreamBufferSize, + NewStreamBuffer, + FALSE, + Stream->AuthenticationStatus, + &Node->EncapsulatedStreamHandle + ); + if (EFI_ERROR (Status)) { + CoreFreePool (Node); + CoreFreePool (NewStreamBuffer); + return Status; + } + break; + + case EFI_SECTION_GUID_DEFINED: + GuidedHeader = (EFI_GUID_DEFINED_SECTION *) SectionHeader; + Node->EncapsulationGuid = &GuidedHeader->SectionDefinitionGuid; + Status = CoreLocateProtocol (Node->EncapsulationGuid, NULL, (VOID **)&GuidedExtraction); + if (!EFI_ERROR (Status)) { + // + // NewStreamBuffer is always allocated by ExtractSection... No caller + // allocation here. + // + Status = GuidedExtraction->ExtractSection ( + GuidedExtraction, + GuidedHeader, + &NewStreamBuffer, + &NewStreamBufferSize, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + CoreFreePool (*ChildNode); + return EFI_PROTOCOL_ERROR; + } + + // + // Make sure we initialize the new stream with the correct + // authentication status for both aggregate and local status fields. + // + if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) { + // + // OR in the parent stream's aggregate status. + // + AuthenticationStatus |= Stream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL; + } else { + // + // since there's no authentication data contributed by the section, + // just inherit the full value from our immediate parent. + // + AuthenticationStatus = Stream->AuthenticationStatus; + } + + Status = OpenSectionStreamEx ( + NewStreamBufferSize, + NewStreamBuffer, + FALSE, + AuthenticationStatus, + &Node->EncapsulatedStreamHandle + ); + if (EFI_ERROR (Status)) { + CoreFreePool (*ChildNode); + CoreFreePool (NewStreamBuffer); + return Status; + } + } else { + // + // There's no GUIDed section extraction protocol available. + // + if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) { + // + // If the section REQUIRES an extraction protocol, then we're toast + // + CoreFreePool (*ChildNode); + return EFI_PROTOCOL_ERROR; + } + + // + // Figure out the proper authentication status + // + AuthenticationStatus = Stream->AuthenticationStatus; + if (GuidedHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) { + // + // The local status of the new stream is contained in + // AuthenticaionStatus. This value needs to be ORed into the + // Aggregate bits also... + // + + // + // Clear out and initialize the local status + // + AuthenticationStatus &= ~EFI_LOCAL_AUTH_STATUS_ALL; + AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED; + // + // OR local status into aggregate status + // + AuthenticationStatus |= AuthenticationStatus >> 16; + } + + SectionLength = SECTION_SIZE (GuidedHeader); + Status = OpenSectionStreamEx ( + SectionLength - GuidedHeader->DataOffset, + (UINT8 *) GuidedHeader + GuidedHeader->DataOffset, + TRUE, + AuthenticationStatus, + &Node->EncapsulatedStreamHandle + ); + if (EFI_ERROR (Status)) { + CoreFreePool (Node); + return Status; + } + } + + if ((AuthenticationStatus & EFI_LOCAL_AUTH_STATUS_ALL) == + (EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_LOCAL_AUTH_STATUS_NOT_TESTED)) { + // + // Need to register for RPN for when the required GUIDed extraction + // protocol becomes available. This will enable us to refresh the + // AuthenticationStatus cached in the Stream if it's ever requested + // again. + // + CreateGuidedExtractionRpnEvent (Stream, Node); + } + + break; + + default: + + // + // Nothing to do if it's a leaf + // + break; + } + + // + // Last, add the new child node to the stream + // + InsertTailList (&Stream->Children, &Node->Link); + + return EFI_SUCCESS; +} + + +STATIC +VOID +CreateGuidedExtractionRpnEvent ( + IN CORE_SECTION_STREAM_NODE *ParentStream, + IN CORE_SECTION_CHILD_NODE *ChildNode + ) +/*++ + +Routine Description: + Worker function. Constructor for RPN event if needed to keep AuthenticationStatus + cache correct when a missing GUIDED_SECTION_EXTRACTION_PROTOCOL appears... + +Arguments: + ParentStream - Indicates the parent of the ecnapsulation section (child) + ChildNode - Indicates the child node that is the encapsulation section. + +Returns: + None + +--*/ +{ + RPN_EVENT_CONTEXT *Context; + + // + // Allocate new event structure and context + // + Context = CoreAllocateBootServicesPool (sizeof (RPN_EVENT_CONTEXT)); + ASSERT (Context != NULL); + + Context->ChildNode = ChildNode; + Context->ParentStream = ParentStream; + + Context->Event = CoreCreateProtocolNotifyEvent ( + Context->ChildNode->EncapsulationGuid, + EFI_TPL_NOTIFY, + NotifyGuidedExtraction, + Context, + &Context->Registration, + FALSE + ); +} + + +STATIC +VOID +EFIAPI +NotifyGuidedExtraction ( + IN EFI_EVENT Event, + IN VOID *RpnContext + ) +/*++ + +Routine Description: + RPN callback function. Removes a stale section stream and re-initializes it + with an updated AuthenticationStatus. + +Arguments: + Event - The event that fired + RpnContext - A pointer to the context that allows us to identify + the relevent encapsulation... + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + EFI_GUID_DEFINED_SECTION *GuidedHeader; + EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *GuidedExtraction; + VOID *NewStreamBuffer; + UINTN NewStreamBufferSize; + UINT32 AuthenticationStatus; + RPN_EVENT_CONTEXT *Context; + + Context = RpnContext; + + Status = CloseSectionStream (&mSectionExtraction, Context->ChildNode->EncapsulatedStreamHandle); + if (!EFI_ERROR (Status)) { + // + // The stream closed successfully, so re-open the stream with correct AuthenticationStatus + // + + GuidedHeader = (EFI_GUID_DEFINED_SECTION *) + (Context->ParentStream->StreamBuffer + Context->ChildNode->OffsetInStream); + ASSERT (GuidedHeader->CommonHeader.Type == EFI_SECTION_GUID_DEFINED); + + Status = CoreLocateProtocol (Context->ChildNode->EncapsulationGuid, NULL, (VOID **)&GuidedExtraction); + ASSERT_EFI_ERROR (Status); + + + Status = GuidedExtraction->ExtractSection ( + GuidedExtraction, + GuidedHeader, + &NewStreamBuffer, + &NewStreamBufferSize, + &AuthenticationStatus + ); + ASSERT_EFI_ERROR (Status); + // + // OR in the parent stream's aggregagate status. + // + AuthenticationStatus |= Context->ParentStream->AuthenticationStatus & EFI_AGGREGATE_AUTH_STATUS_ALL; + Status = OpenSectionStreamEx ( + NewStreamBufferSize, + NewStreamBuffer, + FALSE, + AuthenticationStatus, + &Context->ChildNode->EncapsulatedStreamHandle + ); + ASSERT_EFI_ERROR (Status); + } + + // + // If above, the stream did not close successfully, it indicates it's + // alread been closed by someone, so just destroy the event and be done with + // it. + // + + CoreCloseEvent (Event); + CoreFreePool (Context); +} + + +STATIC +VOID +FreeChildNode ( + IN CORE_SECTION_CHILD_NODE *ChildNode + ) +/*++ + +Routine Description: + Worker function. Destructor for child nodes. + +Arguments: + ChildNode - Indicates the node to destroy + +Returns: + none + +--*/ +{ + ASSERT (ChildNode->Signature == CORE_SECTION_CHILD_SIGNATURE); + // + // Remove the child from it's list + // + RemoveEntryList (&ChildNode->Link); + + if (ChildNode->EncapsulatedStreamHandle != NULL_STREAM_HANDLE) { + // + // If it's an encapsulating section, we close the resulting section stream. + // CloseSectionStream will free all memory associated with the stream. + // + CloseSectionStream (&mSectionExtraction, ChildNode->EncapsulatedStreamHandle); + } + // + // Last, free the child node itself + // + CoreFreePool (ChildNode); +} + + +STATIC +EFI_STATUS +OpenSectionStreamEx ( + IN UINTN SectionStreamLength, + IN VOID *SectionStream, + IN BOOLEAN AllocateBuffer, + IN UINT32 AuthenticationStatus, + OUT UINTN *SectionStreamHandle + ) +/*++ + + Routine Description: + Worker function. Constructor for section streams. + + Arguments: + SectionStreamLength - Size in bytes of the section stream. + SectionStream - Buffer containing the new section stream. + AllocateBuffer - Indicates whether the stream buffer is to be copied + or the input buffer is to be used in place. + AuthenticationStatus- Indicates the default authentication status for the + new stream. + SectionStreamHandle - A pointer to a caller allocated section stream handle. + + Returns: + EFI_SUCCESS - Stream was added to stream database. + EFI_OUT_OF_RESOURCES - memory allocation failed. + +--*/ +{ + CORE_SECTION_STREAM_NODE *NewStream; + EFI_TPL OldTpl; + + // + // Allocate a new stream + // + NewStream = CoreAllocateBootServicesPool (sizeof (CORE_SECTION_STREAM_NODE)); + if (NewStream == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if (AllocateBuffer) { + // + // if we're here, we're double buffering, allocate the buffer and copy the + // data in + // + if (SectionStreamLength > 0) { + NewStream->StreamBuffer = CoreAllocateBootServicesPool (SectionStreamLength); + if (NewStream->StreamBuffer == NULL) { + CoreFreePool (NewStream); + return EFI_OUT_OF_RESOURCES; + } + // + // Copy in stream data + // + CopyMem (NewStream->StreamBuffer, SectionStream, SectionStreamLength); + } else { + // + // It's possible to have a zero length section stream. + // + NewStream->StreamBuffer = NULL; + } + } else { + // + // If were here, the caller has supplied the buffer (it's an internal call) + // so just assign the buffer. This happens when we open section streams + // as a result of expanding an encapsulating section. + // + NewStream->StreamBuffer = SectionStream; + } + + // + // Initialize the rest of the section stream + // + NewStream->Signature = CORE_SECTION_STREAM_SIGNATURE; + NewStream->StreamHandle = (UINTN) NewStream; + NewStream->StreamLength = SectionStreamLength; + InitializeListHead (&NewStream->Children); + NewStream->AuthenticationStatus = AuthenticationStatus; + + // + // Add new stream to stream list + // + OldTpl = CoreRaiseTpl (EFI_TPL_NOTIFY); + InsertTailList (&mStreamRoot, &NewStream->Link); + CoreRestoreTpl (OldTpl); + + *SectionStreamHandle = NewStream->StreamHandle; + + return EFI_SUCCESS; +} + + +STATIC +EFI_STATUS +FindStreamNode ( + IN UINTN SearchHandle, + OUT CORE_SECTION_STREAM_NODE **FoundStream + ) +/*++ + + Routine Description: + Worker function. Search stream database for requested stream handle. + + Arguments: + SearchHandle - Indicates which stream to look for. + FoundStream - Output pointer to the found stream. + + Returns: + EFI_SUCCESS - StreamHandle was found and *FoundStream contains + the stream node. + EFI_NOT_FOUND - SearchHandle was not found in the stream database. + +--*/ +{ + CORE_SECTION_STREAM_NODE *StreamNode; + + if (!IsListEmpty (&mStreamRoot)) { + StreamNode = STREAM_NODE_FROM_LINK (GetFirstNode (&mStreamRoot)); + for (;;) { + if (StreamNode->StreamHandle == SearchHandle) { + *FoundStream = StreamNode; + return EFI_SUCCESS; + } else if (IsNodeAtEnd (&mStreamRoot, &StreamNode->Link)) { + break; + } else { + StreamNode = STREAM_NODE_FROM_LINK (GetNextNode (&mStreamRoot, &StreamNode->Link)); + } + } + } + + return EFI_NOT_FOUND; +} + + +STATIC +BOOLEAN +IsValidSectionStream ( + IN VOID *SectionStream, + IN UINTN SectionStreamLength + ) +/*++ + +Routine Description: + Check if a stream is valid. + +Arguments: + SectionStream - The section stream to be checked + SectionStreamLength - The length of section stream + +Returns: + TRUE + FALSE + +--*/ +{ + UINTN TotalLength; + UINTN SectionLength; + EFI_COMMON_SECTION_HEADER *SectionHeader; + EFI_COMMON_SECTION_HEADER *NextSectionHeader; + + TotalLength = 0; + SectionHeader = (EFI_COMMON_SECTION_HEADER *)SectionStream; + + while (TotalLength < SectionStreamLength) { + SectionLength = SECTION_SIZE (SectionHeader); + TotalLength += SectionLength; + + if (TotalLength == SectionStreamLength) { + return TRUE; + } + + // + // Move to the next byte following the section... + // + SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength); + + // + // Figure out where the next section begins + // + NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) SectionHeader + 3); + NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader & ~(UINTN)3); + TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader; + SectionHeader = NextSectionHeader; + } + + ASSERT (FALSE); + return FALSE; +} diff --git a/EdkModulePkg/Core/Dxe/build.xml b/EdkModulePkg/Core/Dxe/build.xml new file mode 100644 index 0000000000..1041d64072 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Core/Dxe/exec.h b/EdkModulePkg/Core/Dxe/exec.h new file mode 100644 index 0000000000..e7b0f7b660 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/exec.h @@ -0,0 +1,209 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + exec.h + +Abstract: + + EFI Event support + +--*/ + +#ifndef _EXEC_H_ +#define _EXEC_H_ + +#define VALID_TPL(a) ((a) <= EFI_TPL_HIGH_LEVEL) + +// +// EFI_EVENT +// + + + +#define EVENT_SIGNATURE EFI_SIGNATURE_32('e','v','n','t') +typedef struct { + UINTN Signature; + UINT32 Type; + UINT32 SignalCount; + + // + // Entry if the event is registered to be signalled + // + + LIST_ENTRY SignalLink; + + // + // Notification information for this event + // + + EFI_TPL NotifyTpl; + EFI_EVENT_NOTIFY NotifyFunction; + VOID *NotifyContext; + EFI_GUID EventGroup; + LIST_ENTRY NotifyLink; + BOOLEAN ExFlag; + + // + // A list of all runtime events + // + LIST_ENTRY RuntimeLink; + + // + // Information by event type + // + + union { + // + // For timer events + // + struct { + LIST_ENTRY Link; + UINT64 TriggerTime; + UINT64 Period; + } Timer; + } u; + +} IEVENT; + +// +// Internal prototypes +// + +VOID +CoreDispatchEventNotifies ( + IN EFI_TPL Priority + ) +/*++ + +Routine Description: + + Dispatches all pending events. + +Arguments: + + Priority - The task priority level of event notifications to dispatch + +Returns: + + None + +--*/ +; + + +UINTN +CoreHighestSetBit ( + IN UINTN Number + ) +/*++ + +Routine Description: + + Return the highest set bit + +Arguments: + + Number - The value to check + +Returns: + + Bit position of the highest set bit + +--*/ +; + + +BOOLEAN +GetInterruptState ( + VOID + ) +/*++ + +Routine Description: + + Disables CPU interrupts. + +Arguments: + + This - Protocol instance structure + + State - Pointer to the CPU's current interrupt state + +Returns: + + EFI_SUCCESS - If interrupts were disabled in the CPU. + + EFI_INVALID_PARAMETER - State is NULL. + +--*/ +; + +// +// Exported functions +// + +VOID +CoreEventVirtualAddressFixup ( + VOID + ) +/*++ + +Routine Description: + + A function out of date, should be removed. + +Arguments: + + None + +Returns: + + None + +--*/ +; + + +VOID +CoreInitializeTimer ( + VOID + ) +/*++ + +Routine Description: + + Initializes timer support + +Arguments: + + None + +Returns: + + None + +--*/ +; + +// +// extern data declarations +// + +extern EFI_LOCK gEventQueueLock; +extern UINTN gEventPending; +extern LIST_ENTRY gEventQueue[]; +extern LIST_ENTRY gEventSignalQueue; +extern UINT8 gHSB[]; +extern LIST_ENTRY mRuntimeEventList; + +#endif diff --git a/EdkModulePkg/Core/Dxe/gcd.h b/EdkModulePkg/Core/Dxe/gcd.h new file mode 100644 index 0000000000..445821e913 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/gcd.h @@ -0,0 +1,51 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + gcd.h + +Abstract: + +Revision History + +--*/ + +#ifndef _GCD_H +#define _GCD_H + +// +// GCD Operations +// +#define GCD_MEMORY_SPACE_OPERATION 0x20 +#define GCD_IO_SPACE_OPERATION 0x40 + +#define GCD_ADD_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 0) +#define GCD_ALLOCATE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 1) +#define GCD_FREE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 2) +#define GCD_REMOVE_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 3) +#define GCD_SET_ATTRIBUTES_MEMORY_OPERATION (GCD_MEMORY_SPACE_OPERATION | 4) + +#define GCD_ADD_IO_OPERATION (GCD_IO_SPACE_OPERATION | 0) +#define GCD_ALLOCATE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 1) +#define GCD_FREE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 2) +#define GCD_REMOVE_IO_OPERATION (GCD_IO_SPACE_OPERATION | 3) + +// +// The data structure used to convert from GCD attributes to EFI Memory Map attributes +// +typedef struct { + UINT64 Attribute; + UINT64 Capability; + BOOLEAN Memory; +} GCD_ATTRIBUTE_CONVERSION_ENTRY; + +#endif diff --git a/EdkModulePkg/Core/Dxe/hand.h b/EdkModulePkg/Core/Dxe/hand.h new file mode 100644 index 0000000000..c61af16234 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/hand.h @@ -0,0 +1,337 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + hand.h + +Abstract: + + EFI internal protocol definitions + + + +Revision History + +--*/ + +#ifndef _HAND_H_ +#define _HAND_H_ + + +// +// IHANDLE - contains a list of protocol handles +// + +#define EFI_HANDLE_SIGNATURE EFI_SIGNATURE_32('h','n','d','l') +typedef struct { + UINTN Signature; + LIST_ENTRY AllHandles; // All handles list of IHANDLE + LIST_ENTRY Protocols; // List of PROTOCOL_INTERFACE's for this handle + UINTN LocateRequest; // + UINT64 Key; // The Handle Database Key value when this handle was last created or modified +} IHANDLE; + +#define ASSERT_IS_HANDLE(a) ASSERT((a)->Signature == EFI_HANDLE_SIGNATURE) + + +// +// PROTOCOL_ENTRY - each different protocol has 1 entry in the protocol +// database. Each handler that supports this protocol is listed, along +// with a list of registered notifies. +// + +#define PROTOCOL_ENTRY_SIGNATURE EFI_SIGNATURE_32('p','r','t','e') +typedef struct { + UINTN Signature; + LIST_ENTRY AllEntries; // All entries + EFI_GUID ProtocolID; // ID of the protocol + LIST_ENTRY Protocols; // All protocol interfaces + LIST_ENTRY Notify; // Registerd notification handlers +} PROTOCOL_ENTRY; + +// +// PROTOCOL_INTERFACE - each protocol installed on a handle is tracked +// with a protocol interface structure +// + +#define PROTOCOL_INTERFACE_SIGNATURE EFI_SIGNATURE_32('p','i','f','c') +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; // Back pointer + LIST_ENTRY Link; // Link on IHANDLE.Protocols + LIST_ENTRY ByProtocol; // Link on PROTOCOL_ENTRY.Protocols + PROTOCOL_ENTRY *Protocol; // The protocol ID + VOID *Interface; // The interface value + + LIST_ENTRY OpenList; // OPEN_PROTOCOL_DATA list. + UINTN OpenListCount; + + EFI_HANDLE ControllerHandle; + +} PROTOCOL_INTERFACE; + +#define OPEN_PROTOCOL_DATA_SIGNATURE EFI_SIGNATURE_32('p','o','d','l') + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + EFI_HANDLE AgentHandle; + EFI_HANDLE ControllerHandle; + UINT32 Attributes; + UINT32 OpenCount; +} OPEN_PROTOCOL_DATA; + + +// +// PROTOCOL_NOTIFY - used for each register notification for a protocol +// + +#define PROTOCOL_NOTIFY_SIGNATURE EFI_SIGNATURE_32('p','r','t','n') +typedef struct { + UINTN Signature; + PROTOCOL_ENTRY *Protocol; + LIST_ENTRY Link; // All notifications for this protocol + EFI_EVENT Event; // Event to notify + LIST_ENTRY *Position; // Last position notified +} PROTOCOL_NOTIFY; + +// +// Internal prototypes +// + + +PROTOCOL_ENTRY * +CoreFindProtocolEntry ( + IN EFI_GUID *Protocol, + IN BOOLEAN Create + ) +/*++ + +Routine Description: + + Finds the protocol entry for the requested protocol. + + The gProtocolDatabaseLock must be owned + +Arguments: + + Protocol - The ID of the protocol + + Create - Create a new entry if not found + +Returns: + + Protocol entry + +--*/ +; + +VOID +CoreNotifyProtocolEntry ( + IN PROTOCOL_ENTRY *ProtEntry + ) +/*++ + +Routine Description: + + Signal event for every protocol in protocol entry. + +Arguments: + + ProtEntry - Protocol entry + +Returns: + +--*/ +; + +PROTOCOL_INTERFACE * +CoreFindProtocolInterface ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +/*++ + +Routine Description: + + Finds the protocol instance for the requested handle and protocol. + + Note: This function doesn't do parameters checking, it's caller's responsibility + to pass in valid parameters. + +Arguments: + + Handle - The handle to search the protocol on + + Protocol - GUID of the protocol + + Interface - The interface for the protocol being searched + +Returns: + + Protocol instance (NULL: Not found) + +--*/ +; + +PROTOCOL_INTERFACE * +CoreRemoveInterfaceFromProtocol ( + IN IHANDLE *Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ) +/*++ + +Routine Description: + + Removes Protocol from the protocol list (but not the handle list). + +Arguments: + + Handle - The handle to remove protocol on. + + Protocol - GUID of the protocol to be moved + + Interface - The interface of the protocol + +Returns: + + Protocol Entry + +--*/ +; + +EFI_STATUS +CoreUnregisterProtocolNotify ( + IN EFI_EVENT Event + ) +/*++ + +Routine Description: + + Removes all the events in the protocol database that match Event. + +Arguments: + + Event - The event to search for in the protocol database. + +Returns: + + EFI_SUCCESS when done searching the entire database. + +--*/ +; + +EFI_STATUS +CoreDisconnectControllersUsingProtocolInterface ( + IN EFI_HANDLE UserHandle, + IN PROTOCOL_INTERFACE *Prot + ) +/*++ + +Routine Description: + + Attempts to disconnect all drivers that are using the protocol interface being queried. + If failed, reconnect all drivers disconnected. + + Note: This function doesn't do parameters checking, it's caller's responsibility + to pass in valid parameters. + +Arguments: + + UserHandle - The handle on which the protocol is installed + Prot - The protocol to disconnect drivers from + +Returns: + + EFI_SUCCESS - Drivers using the protocol interface are all disconnected + EFI_ACCESS_DENIED - Failed to disconnect one or all of the drivers + +--*/ +; + +VOID +CoreAcquireProtocolLock ( + VOID + ) +/*++ + +Routine Description: + + Acquire lock on gProtocolDatabaseLock. + +Arguments: + + None + +Returns: + + None + +--*/ +; + +VOID +CoreReleaseProtocolLock ( + VOID + ) +/*++ + +Routine Description: + + Release lock on gProtocolDatabaseLock. + +Arguments: + + None + +Returns: + + None + +--*/ +; + +EFI_STATUS +CoreValidateHandle ( + IN EFI_HANDLE UserHandle + ) +/*++ + +Routine Description: + + Check whether a handle is a valid EFI_HANDLE + +Arguments: + + UserHandle - The handle to check + +Returns: + + EFI_INVALID_PARAMETER - The handle is NULL or not a valid EFI_HANDLE. + + EFI_SUCCESS - The handle is valid EFI_HANDLE. + +--*/ +; + +// +// Externs +// + +extern EFI_LOCK gProtocolDatabaseLock; +extern LIST_ENTRY gHandleList; +extern UINT64 gHandleDatabaseKey; + +#endif diff --git a/EdkModulePkg/Core/Dxe/imem.h b/EdkModulePkg/Core/Dxe/imem.h new file mode 100644 index 0000000000..e1f8215eb7 --- /dev/null +++ b/EdkModulePkg/Core/Dxe/imem.h @@ -0,0 +1,227 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + imem.h + +Abstract: + + Head file to imem.h + + +Revision History + +--*/ + +#ifndef _IMEM_H_ +#define _IMEM_H_ + +#if defined (MDE_CPU_IPF) +// +// For Itanium machines make the default allocations 8K aligned +// +#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE * 2) +#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE * 2) + +#else +// +// For genric EFI machines make the default allocations 4K aligned +// +#define EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT (EFI_PAGE_SIZE) +#define DEFAULT_PAGE_ALLOCATION (EFI_PAGE_SIZE) + +#endif + + +// +// MEMORY_MAP_ENTRY +// + +#define MEMORY_MAP_SIGNATURE EFI_SIGNATURE_32('m','m','a','p') +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + BOOLEAN FromPool; + + EFI_MEMORY_TYPE Type; + UINT64 Start; + UINT64 End; + + UINT64 VirtualStart; + UINT64 Attribute; +} MEMORY_MAP; + +// +// Internal prototypes +// + +VOID * +CoreAllocatePoolPages ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN NumberOfPages, + IN UINTN Alignment + ) +/*++ + +Routine Description: + + Internal function. Used by the pool functions to allocate pages + to back pool allocation requests. + +Arguments: + + PoolType - The type of memory for the new pool pages + + NumberOfPages - No of pages to allocate + + Alignment - Bits to align. + +Returns: + + The allocated memory, or NULL + +--*/ +; + + +VOID +CoreFreePoolPages ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages + ) +/*++ + +Routine Description: + + Internal function. Frees pool pages allocated via AllocatePoolPages () + +Arguments: + + Memory - The base address to free + + NumberOfPages - The number of pages to free + +Returns: + + None + +--*/ +; + + +VOID * +CoreAllocatePoolI ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size + ) +/*++ + +Routine Description: + + Internal function to allocate pool of a particular type. + + Caller must have the memory lock held + + +Arguments: + + PoolType - Type of pool to allocate + + Size - The amount of pool to allocate + +Returns: + + The allocate pool, or NULL + +--*/ +; + + +EFI_STATUS +CoreFreePoolI ( + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Internal function to free a pool entry. + + Caller must have the memory lock held + + +Arguments: + + Buffer - The allocated pool entry to free + +Returns: + + EFI_INVALID_PARAMETER - Buffer not valid + + EFI_SUCCESS - Buffer successfully freed. + +--*/ +; + + +VOID +CoreAcquireMemoryLock ( + VOID + ) +/*++ + +Routine Description: + + Enter critical section by gaining lock on gMemoryLock + +Arguments: + + None + +Returns: + + None + +--*/ +; + +VOID +CoreReleaseMemoryLock ( + VOID + ) +/*++ + +Routine Description: + + Exit critical section by releasing lock on gMemoryLock + +Arguments: + + None + +Returns: + + None + +--*/ +; + + +// +// Internal Global data +// + +extern EFI_LOCK gMemoryLock; +extern LIST_ENTRY gMemoryMap; +extern MEMORY_MAP *gMemoryLastConvert; +extern LIST_ENTRY mGcdMemorySpaceMap; +#endif diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.dxs b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.dxs new file mode 100644 index 0000000000..6370d86cbf --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.dxs @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeIpl.dxs + +Abstract: + + Dependency expression file for DXE Initial Program Loader PEIM. + +--*/ + +#include +#include + +DEPENDENCY_START + EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID +DEPENDENCY_END + + diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.h b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.h new file mode 100644 index 0000000000..bc50666df6 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.h @@ -0,0 +1,146 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeIpl.h + +Abstract: + +--*/ + +#ifndef __PEI_DXEIPL_H__ +#define __PEI_DXEIPL_H__ + +#define STACK_SIZE 0x20000 +#define BSP_STORE_SIZE 0x4000 + +extern BOOLEAN gInMemory; + +VOID +SwitchIplStacks ( + VOID *EntryPoint, + UINTN Parameter1, + UINTN Parameter2, + VOID *NewStack, + VOID *NewBsp + ) +; + +EFI_STATUS +PeiFindFile ( + IN UINT8 Type, + IN UINT16 SectionType, + OUT EFI_GUID *FileName, + OUT VOID **Pe32Data + ) +; + +EFI_STATUS +PeiLoadFile ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, + IN VOID *Pe32Data, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +; + + +EFI_STATUS +CreateArchSpecificHobs ( + OUT EFI_PHYSICAL_ADDRESS *BspStore + ) +; + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +; + +EFI_STATUS +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +; + +EFI_STATUS +EFIAPI +DxeIplLoadFile ( + IN EFI_PEI_FV_FILE_LOADER_PPI *This, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ); + +EFI_STATUS +ShadowDxeIpl ( + IN EFI_FFS_FILE_HEADER *DxeIpl, + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader + ); + +EFI_STATUS +EFIAPI +DxeLoadCore ( + IN EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ); + +EFI_STATUS +PeiProcessFile ( + IN UINT16 SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + OUT VOID **Pe32Data + ); + +EFI_STATUS +EFIAPI +PeimInitializeDxeIpl ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ); + +EFI_STATUS +PeiLoadx64File ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, + IN VOID *Pe32Data, + IN EFI_MEMORY_TYPE MemoryType, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +; + +EFI_PHYSICAL_ADDRESS +CreateIdentityMappingPageTables ( + IN UINT32 NumberOfProcessorPhysicalAddressBits + ) +; + +VOID +ActivateLongMode ( + IN EFI_PHYSICAL_ADDRESS PageTables, + IN EFI_PHYSICAL_ADDRESS HobStart, + IN EFI_PHYSICAL_ADDRESS Stack, + IN EFI_PHYSICAL_ADDRESS CodeEntryPoint1, + IN EFI_PHYSICAL_ADDRESS CodeEntryPoint2 + ); + +VOID +LoadGo64Gdt(); + +#endif diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.mbd b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.mbd new file mode 100644 index 0000000000..a604fccf08 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.mbd @@ -0,0 +1,63 @@ + + + + + DxeIpl + 86D70125-BAA3-4296-A62F-602BEBBB9081 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-22 18:54 + + + PeimEntryPoint + PeiMemoryLib + PeiCoreLib + PeiServicesTablePointerLib + PeiHobLib + BaseCacheMaintenanceLib + BaseUefiTianoDecompressLib + BaseCustomDecompressLibNull + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + PeiMemoryAllocationLib + + EdkPeCoffLoaderLib + BasePeCoffLib + + + EdkPeCoffLoaderLib + BasePeCoffLib + + + EdkPeCoffLoaderLib + BasePeCoffLib + + + EdkPeCoffLoaderLib + BasePeCoffLib + + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa new file mode 100644 index 0000000000..7d7d531cca --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/DxeIpl.msa @@ -0,0 +1,129 @@ + + + + + DxeIpl + PEIM + PE32_PEIM + 86D70125-BAA3-4296-A62F-602BEBBB9081 + EDK_RELEASE_VERSION 0x00020000 + Component description file for DxeIpl module + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-22 18:54 + + + DebugLib + PeimEntryPoint + BaseLib + HobLib + PerformanceLib + PeiCoreLib + ReportStatusCodeLib + CacheMaintenanceLib + EdkPeCoffLoaderLib + UefiDecompressLib + TianoDecompressLib + CustomDecompressLib + PeiServicesTablePointerLib + BaseMemoryLib + MemoryAllocationLib + + + DxeLoad.c + DxeIpl.dxs + + ia32\ImageRead.c + ia32\DxeLoadFunc.c + + + ia32\ImageRead.c + ia32\DxeLoadFunc.c + + + ipf\ImageRead.c + ipf\DxeLoadFunc.c + + + ia32\ImageRead.c + ia32\DxeLoadFunc.c + + + + MdePkg + EdkModulePkg + + + Decompress + TianoDecompress + CustomizedDecompress + + + + gEfiHobMemoryAllocBspStoreGuid + 0x564b33cd, 0xc92a, 0x4593, 0x90, 0xbf, 0x24, 0x73, 0xe4, 0x3c, 0x63, 0x22 + + + gEfiDecompressProtocolGuid + 0xd8117cfe, 0x94a6, 0x11d4, 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiTianoDecompressProtocolGuid + 0xe84cf29c, 0x191f, 0x4eae, 0x96, 0xe1, 0xf4, 0x6a, 0xec, 0xea, 0xea, 0x0b + + + gEfiCustomizedDecompressProtocolGuid + 0x9a44198e, 0xa4a2, 0x44e6, 0x8a, 0x1f, 0x39, 0xbe, 0xfd, 0xac, 0x89, 0x6f + + + gEfiPeiPeCoffLoaderGuid + 0xd8117cff, 0x94a6, 0x11d4, 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiHobMemoryAllocModuleGuid + 0xf8e21975, 0x0899, 0x4f58, 0xa4, 0xbe, 0x55, 0x25, 0xa9, 0xc6, 0xd7, 0x7a + + + DecompressedFvmain.fv + + + + DxeIpl + FvFileLoader + EndOfPeiSignal + RecoveryModule + S3Resume + SectionExtraction + Security + PeiInMemory + + + + PeiPeCoffLoader + + + + + PeimInitializeDxeIpl + + + diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.mbd b/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.mbd new file mode 100644 index 0000000000..2df91ecde8 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.mbd @@ -0,0 +1,49 @@ + + + + + DxeIpl + 86D70125-BAA3-4296-A62F-602BEBBB9081 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright 2004-2006, 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. + + 2006-04-03 23:58 + + + PeimEntryPoint + PeiMemoryLib + PeiCoreLib + PeiServicesTablePointerLib + PeiHobLib + BaseCacheMaintenanceLib + BaseUefiTianoDecompressLib + BaseCustomDecompressLibNull + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + PeiMemoryAllocationLib + PeiReportStatusCodeLib + + EdkPeCoffLoaderX64Lib + EdkPeCoffLoaderLib + BasePeCoffLib + + + diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa b/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa new file mode 100644 index 0000000000..df4efbc285 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/DxeIplX64.msa @@ -0,0 +1,85 @@ + + + + + DxeIpl + PEIM + PE32_PEIM + 86D70125-BAA3-4296-A62F-602BEBBB9081 + EDK_RELEASE_VERSION 0x00020000 + Component description file for DxeIpl module + FIX ME! + Copyright 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-03 23:58 + + + DebugLib + PeimEntryPoint + BaseLib + HobLib + PerformanceLib + PeiCoreLib + ReportStatusCodeLib + CacheMaintenanceLib + EdkPeCoffLoaderLib + UefiDecompressLib + TianoDecompressLib + CustomDecompressLib + PeiServicesTablePointerLib + BaseMemoryLib + MemoryAllocationLib + EdkPeCoffLoaderX64Lib + + + DxeIpl.dxs + DxeLoadX64.c + + x64\ImageRead.c + x64\LongMode.asm + x64\DxeLoadFunc.c + x64\VirtualMemory.c + + + + MdePkg + EdkModulePkg + + + Decompress + TianoDecompress + CustomizedDecompress + + + PeiInMemory + RecoveryModule + SectionExtraction + Security + DxeIpl + S3Resume + EndOfPeiSignal + FvFileLoader + + + + PeiPeCoffLoader + + + diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeLoad.c b/EdkModulePkg/Core/DxeIplPeim/DxeLoad.c new file mode 100644 index 0000000000..a181095813 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/DxeLoad.c @@ -0,0 +1,1010 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeLoad.c + +Abstract: + + Last PEIM. + Responsibility of this module is to load the DXE Core from a Firmware Volume. + +--*/ + +#include + +BOOLEAN gInMemory = FALSE; + +// +// Module Globals used in the DXE to PEI handoff +// These must be module globals, so the stack can be switched +// +static EFI_DXE_IPL_PPI mDxeIplPpi = { + DxeLoadCore +}; + +static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = { + DxeIplLoadFile +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiFvFileLoaderPpiGuid, + &mLoadFilePpi +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiDxeIplPpiGuid, + &mDxeIplPpi +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiInMemoryGuid, + NULL +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + NULL +}; + +DECOMPRESS_LIBRARY gEfiDecompress = { + UefiDecompressGetInfo, + UefiDecompress +}; + +DECOMPRESS_LIBRARY gTianoDecompress = { + TianoDecompressGetInfo, + TianoDecompress +}; + +DECOMPRESS_LIBRARY gCustomDecompress = { + CustomDecompressGetInfo, + CustomDecompress +}; + +STATIC +UINTN +GetOccupiedSize ( + IN UINTN ActualSize, + IN UINTN Alignment + ) +{ + UINTN OccupiedSize; + + OccupiedSize = ActualSize; + while ((OccupiedSize & (Alignment - 1)) != 0) { + OccupiedSize++; + } + + return OccupiedSize; +} + +EFI_STATUS +EFIAPI +PeimInitializeDxeIpl ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Initializes the Dxe Ipl PPI + +Arguments: + + FfsHeader - Pointer to FFS file header + PeiServices - General purpose services available to every PEIM. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_BOOT_MODE BootMode; + + Status = PeiCoreGetBootMode (&BootMode); + + ASSERT_EFI_ERROR (Status); + + Status = PeiCoreLocatePpi ( + &gPeiInMemoryGuid, + 0, + NULL, + NULL + ); + + if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) { + // + // The DxeIpl has not yet been shadowed + // + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + + // + // Shadow DxeIpl and then re-run its entry point + // + Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader); + if (EFI_ERROR (Status)) { + return Status; + } + + } else { + if (BootMode != BOOT_ON_S3_RESUME) { + // + // The DxeIpl has been shadowed + // + gInMemory = TRUE; + + // + // Install LoadFile PPI + // + Status = PeiCoreInstallPpi (&mPpiLoadFile); + + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // Install DxeIpl PPI + // + PeiCoreInstallPpi (&mPpiList); + + if (EFI_ERROR (Status)) { + return Status; + } + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DxeLoadCore ( + IN EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ) +/*++ + +Routine Description: + + Main entry point to last PEIM + +Arguments: + This - Entry point for DXE IPL PPI + PeiServices - General purpose services available to every PEIM. + HobList - Address to the Pei HOB list + +Returns: + + EFI_SUCCESS - DEX core was successfully loaded. + EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core. + +--*/ +{ + EFI_STATUS Status; + VOID *TopOfStack; + VOID *BaseOfStack; + EFI_PHYSICAL_ADDRESS BspStore; + EFI_GUID DxeCoreFileName; + EFI_GUID FirmwareFileName; + VOID *Pe32Data; + EFI_PHYSICAL_ADDRESS DxeCoreAddress; + UINT64 DxeCoreSize; + EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_BOOT_MODE BootMode; + EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; + EFI_PEI_S3_RESUME_PPI *S3Resume; + +// PERF_START (PeiServices, L"DxeIpl", NULL, 0); + TopOfStack = NULL; + BaseOfStack = NULL; + BspStore = 0; + Status = EFI_SUCCESS; + + // + // if in S3 Resume, restore configure + // + Status = PeiCoreGetBootMode (&BootMode); + + if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) { + Status = PeiCoreLocatePpi ( + &gEfiPeiS3ResumePpiGuid, + 0, + NULL, + (VOID **)&S3Resume + ); + + ASSERT_EFI_ERROR (Status); + + Status = S3Resume->S3RestoreConfig (PeiServices); + + ASSERT_EFI_ERROR (Status); + } + + Status = EFI_SUCCESS; + + // + // Install the PEI Protocols that are shared between PEI and DXE + // + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + ASSERT (PeiEfiPeiPeCoffLoader != NULL); + + + // + // Allocate 128KB for the Stack + // + BaseOfStack = AllocatePages (EFI_SIZE_TO_PAGES (STACK_SIZE)); + ASSERT (BaseOfStack != NULL); + + // + // Compute the top of the stack we were allocated. Pre-allocate a UINTN + // for safety. + // + TopOfStack = (VOID *)((UINTN)BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - sizeof (UINTN)); + + // + // Add architecture-specifc HOBs (including the BspStore HOB) + // + Status = CreateArchSpecificHobs (&BspStore); + + ASSERT_EFI_ERROR (Status); + + // + // Add HOB for the EFI Decompress Protocol + // + BuildGuidDataHob ( + &gEfiDecompressProtocolGuid, + (VOID *)&gEfiDecompress, + sizeof (gEfiDecompress) + ); + + // + // Add HOB for the Tiano Decompress Protocol + // + BuildGuidDataHob ( + &gEfiTianoDecompressProtocolGuid, + (VOID *)&gTianoDecompress, + sizeof (gTianoDecompress) + ); + + // + // Add HOB for the user customized Decompress Protocol + // + BuildGuidDataHob ( + &gEfiCustomizedDecompressProtocolGuid, + (VOID *)&gCustomDecompress, + sizeof (gCustomDecompress) + ); + + // + // Add HOB for the PE/COFF Loader Protocol + // + BuildGuidDataHob ( + &gEfiPeiPeCoffLoaderGuid, + (VOID *)&PeiEfiPeiPeCoffLoader, + sizeof (VOID *) + ); + + // + // See if we are in crisis recovery + // + Status = PeiCoreGetBootMode (&BootMode); + + if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) { + + Status = PeiCoreLocatePpi ( + &gEfiPeiRecoveryModulePpiGuid, + 0, + NULL, + (VOID **)&PeiRecovery + ); + + ASSERT_EFI_ERROR (Status); + Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery); + ASSERT_EFI_ERROR (Status); + + // + // Now should have a HOB with the DXE core w/ the old HOB destroyed + // + } + + // + // Find the EFI_FV_FILETYPE_RAW type compressed Firmware Volume file in FTW spare block + // The file found will be processed by PeiProcessFile: It will first be decompressed to + // a normal FV, then a corresponding FV type hob will be built which is provided for DXE + // core to find and dispatch drivers in this FV. Because PeiProcessFile typically checks + // for EFI_FV_FILETYPE_DXE_CORE type file, in this condition we need not check returned + // status + // + Status = PeiFindFile ( + EFI_FV_FILETYPE_RAW, + EFI_SECTION_PE32, + &FirmwareFileName, + &Pe32Data + ); + + // + // Find the DXE Core in a Firmware Volume + // + Status = PeiFindFile ( + EFI_FV_FILETYPE_DXE_CORE, + EFI_SECTION_PE32, + &DxeCoreFileName, + &Pe32Data + ); + + ASSERT_EFI_ERROR (Status); + + // + // Load the DXE Core from a Firmware Volume + // + Status = PeiLoadFile ( + PeiEfiPeiPeCoffLoader, + Pe32Data, + &DxeCoreAddress, + &DxeCoreSize, + &DxeCoreEntryPoint + ); + + ASSERT_EFI_ERROR (Status); + + // + // Transfer control to the DXE Core + // The handoff state is simply a pointer to the HOB list + // +// PERF_END (PeiServices, L"DxeIpl", NULL, 0); + + Status = PeiCoreInstallPpi (&mPpiSignal); + + ASSERT_EFI_ERROR (Status); + + // + // Add HOB for the DXE Core + // + BuildModuleHob ( + &DxeCoreFileName, + DxeCoreAddress, + DxeCoreSize, + DxeCoreEntryPoint + ); + + // + // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT + ); + + DEBUG ((EFI_D_INFO, "DXE Core Entry\n")); + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)DxeCoreEntryPoint, + HobList.Raw, + (VOID *) (UINTN) BspStore, + TopOfStack + ); + + // + // If we get here, then the DXE Core returned. This is an error + // + ASSERT_EFI_ERROR (Status); + + return EFI_OUT_OF_RESOURCES; +} + +EFI_STATUS +PeiFindFile ( + IN UINT8 Type, + IN UINT16 SectionType, + OUT EFI_GUID *FileName, + OUT VOID **Pe32Data + ) +/*++ + +Routine Description: + + Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes + described in the HOB list. Able to search in a compression set in a FFS file. + But only one level of compression is supported, that is, not able to search + in a compression set that is within another compression set. + +Arguments: + + Type - The Type of file to retrieve + + SectionType - The type of section to retrieve from a file + + FileName - The name of the file found in the Firmware Volume + + Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume + +Returns: + + EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to + the PE/COFF image is returned in Pe32Data + + EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FFS_FILE_HEADER *FfsFileHeader; + VOID *SectionData; + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + + + FwVolHeader = NULL; + FfsFileHeader = NULL; + SectionData = NULL; + + // + // Foreach Firmware Volume, look for a specified type + // of file and break out when one is found + // + Hob.Raw = GetHobList (); + while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) { + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress); + Status = PeiCoreFfsFindNextFile ( + Type, + FwVolHeader, + &FfsFileHeader + ); + if (!EFI_ERROR (Status)) { + CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID)); + Status = PeiProcessFile ( + SectionType, + FfsFileHeader, + Pe32Data + ); + return Status; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +PeiLoadFile ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, + IN VOID *Pe32Data, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + + Loads and relocates a PE/COFF image into memory. + +Arguments: + + PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol + + Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated + + ImageAddress - The base address of the relocated PE/COFF image + + ImageSize - The size of the relocated PE/COFF image + + EntryPoint - The entry point of the relocated PE/COFF image + +Returns: + + EFI_SUCCESS - The file was loaded and relocated + + EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + Status = GetImageReadFunction (&ImageContext); + + ASSERT_EFI_ERROR (Status); + + Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate Memory for the image + // + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS)(UINTN) AllocatePages (EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize)); + ASSERT (ImageContext.ImageAddress != 0); + + // + // Load the image to our new buffer + // + Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Relocate the image in our new buffer + // + Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Flush the instruction cache so the image data is written before we execute it + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + + *ImageAddress = ImageContext.ImageAddress; + *ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + + return EFI_SUCCESS; +} + +EFI_STATUS +ShadowDxeIpl ( + IN EFI_FFS_FILE_HEADER *DxeIplFileHeader, + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader + ) +/*++ + +Routine Description: + + Shadow the DXE IPL to a different memory location. This occurs after permanent + memory has been discovered. + +Arguments: + + DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver + + PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol + +Returns: + + EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location. + + EFI_ ERROR - The shadow was unsuccessful. + + +--*/ +{ + UINTN SectionLength; + UINTN OccupiedSectionLength; + EFI_PHYSICAL_ADDRESS DxeIplAddress; + UINT64 DxeIplSize; + EFI_PHYSICAL_ADDRESS DxeIplEntryPoint; + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *Section; + + Section = (EFI_COMMON_SECTION_HEADER *) (DxeIplFileHeader + 1); + + while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) { + SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; + OccupiedSectionLength = GetOccupiedSize (SectionLength, 4); + Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); + } + // + // Relocate DxeIpl into memory by using loadfile service + // + Status = PeiLoadFile ( + PeiEfiPeiPeCoffLoader, + (VOID *) (Section + 1), + &DxeIplAddress, + &DxeIplSize, + &DxeIplEntryPoint + ); + + if (Status == EFI_SUCCESS) { + // + // Install PeiInMemory to indicate the Dxeipl is shadowed + // + Status = PeiCoreInstallPpi (&mPpiPeiInMemory); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer()); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DxeIplLoadFile ( + IN EFI_PEI_FV_FILE_LOADER_PPI *This, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + + Given a pointer to an FFS file containing a PE32 image, get the + information on the PE32 image, and then "load" it so that it + can be executed. + +Arguments: + + This - pointer to our file loader protocol + + FfsHeader - pointer to the FFS file header of the FFS file that + contains the PE32 image we want to load + + ImageAddress - returned address where the PE32 image is loaded + + ImageSize - returned size of the loaded PE32 image + + EntryPoint - entry point to the loaded PE32 image + +Returns: + + EFI_SUCCESS - The FFS file was successfully loaded. + + EFI_ERROR - Unable to load the FFS file. + +--*/ +{ + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_STATUS Status; + VOID *Pe32Data; + + Pe32Data = NULL; + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + + // + // Preprocess the FFS file to get a pointer to the PE32 information + // in the enclosed PE32 image. + // + Status = PeiProcessFile ( + EFI_SECTION_PE32, + FfsHeader, + &Pe32Data + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Load the PE image from the FFS file + // + Status = PeiLoadFile ( + PeiEfiPeiPeCoffLoader, + Pe32Data, + ImageAddress, + ImageSize, + EntryPoint + ); + + return Status; +} + +EFI_STATUS +PeiProcessFile ( + IN UINT16 SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + OUT VOID **Pe32Data + ) +/*++ + +Routine Description: + +Arguments: + + SectionType - The type of section in the FFS file to process. + + FfsFileHeader - Pointer to the FFS file to process, looking for the + specified SectionType + + Pe32Data - returned pointer to the start of the PE32 image found + in the FFS file. + +Returns: + + EFI_SUCCESS - found the PE32 section in the FFS file + +--*/ +{ + EFI_STATUS Status; + VOID *SectionData; + DECOMPRESS_LIBRARY *DecompressLibrary; + UINT8 *DstBuffer; + UINT8 *ScratchBuffer; + UINT32 DstBufferSize; + UINT32 ScratchBufferSize; + EFI_COMMON_SECTION_HEADER *CmpSection; + UINTN CmpSectionLength; + UINTN OccupiedCmpSectionLength; + VOID *CmpFileData; + UINTN CmpFileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINTN SectionLength; + UINTN OccupiedSectionLength; + UINT64 FileSize; + EFI_GUID_DEFINED_SECTION *GuidedSectionHeader; + UINT32 AuthenticationStatus; + EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract; + UINT32 BufferSize; + UINT8 *Buffer; + EFI_PEI_SECURITY_PPI *Security; + BOOLEAN StartCrisisRecovery; + EFI_GUID TempGuid; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_COMPRESSION_SECTION *CompressionSection; + + Status = PeiCoreFfsFindSectionData ( + EFI_SECTION_COMPRESSION, + FfsFileHeader, + &SectionData + ); + + // + // Upon finding a DXE Core file, see if there is first a compression section + // + if (!EFI_ERROR (Status)) { + // + // Yes, there is a compression section, so extract the contents + // Decompress the image here + // + Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER)); + + do { + SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; + OccupiedSectionLength = GetOccupiedSize (SectionLength, 4); + + // + // Was the DXE Core file encapsulated in a GUID'd section? + // + if (Section->Type == EFI_SECTION_GUID_DEFINED) { + // + // Locate the GUID'd Section Extractor + // + GuidedSectionHeader = (VOID *) (Section + 1); + + // + // This following code constitutes the addition of the security model + // to the DXE IPL. + // + // + // Set a default authenticatino state + // + AuthenticationStatus = 0; + + Status = PeiCoreLocatePpi ( + &gEfiPeiSectionExtractionPpiGuid, + 0, + NULL, + (VOID **)&SectionExtract + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Verify Authentication State + // + CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID)); + + Status = SectionExtract->PeiGetSection ( + GetPeiServicesTablePointer(), + SectionExtract, + (EFI_SECTION_TYPE *) &SectionType, + &TempGuid, + 0, + (VOID **) &Buffer, + &BufferSize, + &AuthenticationStatus + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // If not ask the Security PPI, if exists, for disposition + // + // + Status = PeiCoreLocatePpi ( + &gEfiPeiSecurityPpiGuid, + 0, + NULL, + (VOID **)&Security + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Security->AuthenticationState ( + GetPeiServicesTablePointer(), + (struct _EFI_PEI_SECURITY_PPI *) Security, + AuthenticationStatus, + FfsFileHeader, + &StartCrisisRecovery + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // If there is a security violation, report to caller and have + // the upper-level logic possible engender a crisis recovery + // + if (StartCrisisRecovery) { + return EFI_SECURITY_VIOLATION; + } + } + + if (Section->Type == EFI_SECTION_PE32) { + // + // This is what we want + // + *Pe32Data = (VOID *) (Section + 1); + return EFI_SUCCESS; + } else if (Section->Type == EFI_SECTION_COMPRESSION) { + // + // This is a compression set, expand it + // + CompressionSection = (EFI_COMPRESSION_SECTION *) Section; + + switch (CompressionSection->CompressionType) { + case EFI_STANDARD_COMPRESSION: + DecompressLibrary = &gTianoDecompress; + break; + + case EFI_CUSTOMIZED_COMPRESSION: + // + // Load user customized compression protocol. + // + DecompressLibrary = &gCustomDecompress; + break; + + case EFI_NOT_COMPRESSED: + default: + // + // Need to support not compressed file + // + ASSERT_EFI_ERROR (Status); + return EFI_NOT_FOUND; + } + + Status = DecompressLibrary->GetInfo ( + (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION), + &DstBufferSize, + &ScratchBufferSize + ); + if (EFI_ERROR (Status)) { + // + // GetInfo failed + // + return EFI_NOT_FOUND; + } + + // + // Allocate scratch buffer + // + ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); + if (ScratchBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Allocate destination buffer + // + DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Call decompress function + // + Status = DecompressLibrary->Decompress ( + (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + DstBuffer, + ScratchBuffer + ); + + CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer; + if (CmpSection->Type == EFI_SECTION_RAW) { + // + // Skip the section header and + // adjust the pointer alignment to 16 + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16); + + if (FvHeader->Signature == EFI_FVH_SIGNATURE) { + FfsFileHeader = NULL; + BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength); + Status = PeiCoreFfsFindNextFile ( + EFI_FV_FILETYPE_DXE_CORE, + FvHeader, + &FfsFileHeader + ); + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + return PeiProcessFile (SectionType, FfsFileHeader, Pe32Data); + } + } + // + // Decompress successfully. + // Loop the decompressed data searching for expected section. + // + CmpFileData = (VOID *) DstBuffer; + CmpFileSize = DstBufferSize; + do { + CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff; + if (CmpSection->Type == EFI_SECTION_PE32) { + // + // This is what we want + // + *Pe32Data = (VOID *) (CmpSection + 1); + return EFI_SUCCESS; + } + + OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4); + CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength); + } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize); + } + + Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); + FileSize = FfsFileHeader->Size[0] & 0xFF; + FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00; + FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000; + FileSize &= 0x00FFFFFF; + } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize); + + // + // End of the decompression activity + // + } else { + + Status = PeiCoreFfsFindSectionData ( + EFI_SECTION_PE32, + FfsFileHeader, + &SectionData + ); + + if (EFI_ERROR (Status)) { + Status = PeiCoreFfsFindSectionData ( + EFI_SECTION_TE, + FfsFileHeader, + &SectionData + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + *Pe32Data = SectionData; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c b/EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c new file mode 100644 index 0000000000..6727bf4ca7 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/DxeLoadX64.c @@ -0,0 +1,1018 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeLoad.c + +Abstract: + + Last PEIM. + Responsibility of this module is to load the DXE Core from a Firmware Volume. + +--*/ + +#include + +#pragma warning( disable : 4305 ) + +BOOLEAN gInMemory = FALSE; + +// +// GUID for EM64T +// +#define EFI_PPI_NEEDED_BY_DXE \ + { \ + 0x4d37da42, 0x3a0c, 0x4eda, 0xb9, 0xeb, 0xbc, 0x0e, 0x1d, 0xb4, 0x71, 0x3b \ + } +EFI_GUID mPpiNeededByDxeGuid = EFI_PPI_NEEDED_BY_DXE; + +// +// Module Globals used in the DXE to PEI handoff +// These must be module globals, so the stack can be switched +// +static EFI_DXE_IPL_PPI mDxeIplPpi = { + DxeLoadCore +}; + +static EFI_PEI_FV_FILE_LOADER_PPI mLoadFilePpi = { + DxeIplLoadFile +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiLoadFile = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiFvFileLoaderPpiGuid, + &mLoadFilePpi +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiList = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiDxeIplPpiGuid, + &mDxeIplPpi +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiPeiInMemory = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiInMemoryGuid, + NULL +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiSignal = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + NULL +}; + +DECOMPRESS_LIBRARY gEfiDecompress = { + UefiDecompressGetInfo, + UefiDecompress +}; + +DECOMPRESS_LIBRARY gTianoDecompress = { + TianoDecompressGetInfo, + TianoDecompress +}; + +DECOMPRESS_LIBRARY gCustomDecompress = { + CustomDecompressGetInfo, + CustomDecompress +}; + +STATIC +UINTN +GetOccupiedSize ( + IN UINTN ActualSize, + IN UINTN Alignment + ) +{ + UINTN OccupiedSize; + + OccupiedSize = ActualSize; + while ((OccupiedSize & (Alignment - 1)) != 0) { + OccupiedSize++; + } + + return OccupiedSize; +} + +EFI_STATUS +EFIAPI +PeimInitializeDxeIpl ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Initializes the Dxe Ipl PPI + +Arguments: + + FfsHeader - Pointer to FFS file header + PeiServices - General purpose services available to every PEIM. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_BOOT_MODE BootMode; + + Status = PeiCoreGetBootMode (&BootMode); + + ASSERT_EFI_ERROR (Status); + + Status = PeiCoreLocatePpi ( + &gPeiInMemoryGuid, + 0, + NULL, + NULL + ); + + if (EFI_ERROR (Status) && (BootMode != BOOT_ON_S3_RESUME)) { + // + // The DxeIpl has not yet been shadowed + // + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + + // + // Shadow DxeIpl and then re-run its entry point + // + Status = ShadowDxeIpl (FfsHeader, PeiEfiPeiPeCoffLoader); + if (EFI_ERROR (Status)) { + return Status; + } + + } else { + if (BootMode != BOOT_ON_S3_RESUME) { + // + // The DxeIpl has been shadowed + // + gInMemory = TRUE; + + // + // Install LoadFile PPI + // + Status = PeiCoreInstallPpi (&mPpiLoadFile); + + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // Install DxeIpl PPI + // + PeiCoreInstallPpi (&mPpiList); + + if (EFI_ERROR (Status)) { + return Status; + } + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DxeLoadCore ( + IN EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ) +/*++ + +Routine Description: + + Main entry point to last PEIM + +Arguments: + + This - Entry point for DXE IPL PPI + PeiServices - General purpose services available to every PEIM. + HobList - Address to the Pei HOB list + +Returns: + + EFI_SUCCESS - DEX core was successfully loaded. + EFI_OUT_OF_RESOURCES - There are not enough resources to load DXE core. + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS TopOfStack; + EFI_PHYSICAL_ADDRESS BaseOfStack; + EFI_PHYSICAL_ADDRESS BspStore; + EFI_GUID DxeCoreFileName; + VOID *DxeCorePe32Data; + EFI_PHYSICAL_ADDRESS DxeCoreAddress; + UINT64 DxeCoreSize; + EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint; + VOID *PpisNeededByDxePe32Data; + EFI_PHYSICAL_ADDRESS PpisNeededByDxeAddress; + UINT64 PpisNeededByDxeSize; + EFI_PHYSICAL_ADDRESS PpisNeededByDxeEntryPoint; + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_BOOT_MODE BootMode; + EFI_PEI_RECOVERY_MODULE_PPI *PeiRecovery; + EFI_PEI_S3_RESUME_PPI *S3Resume; + EFI_PHYSICAL_ADDRESS PageTables; + + TopOfStack = 0; + BaseOfStack = 0; + BspStore = 0; + Status = EFI_SUCCESS; + + // + // if in S3 Resume, restore configure + // + Status = PeiCoreGetBootMode (&BootMode); + + if (!EFI_ERROR (Status) && (BootMode == BOOT_ON_S3_RESUME)) { + Status = PeiCoreLocatePpi ( + &gEfiPeiS3ResumePpiGuid, + 0, + NULL, + (VOID **)&S3Resume + ); + + ASSERT_EFI_ERROR (Status); + + Status = S3Resume->S3RestoreConfig (PeiServices); + + ASSERT_EFI_ERROR (Status); + } + + Status = EFI_SUCCESS; + + // + // Install the PEI Protocols that are shared between PEI and DXE + // +#ifdef EFI_NT_EMULATOR + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + ASSERT (PeiEfiPeiPeCoffLoader != NULL); +#else + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderX64Protocol (); +#endif + +#if 0 + Status = InstallEfiPeiPeCoffLoader64 (PeiServices, &PeiEfiPeiPeCoffLoader, NULL); + ASSERT_EFI_ERROR (Status); +#endif + // + // Allocate 128KB for the Stack + // + PeiCoreAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (STACK_SIZE), &BaseOfStack); + ASSERT (BaseOfStack != 0); + + // + // Compute the top of the stack we were allocated. Pre-allocate a 32 bytes + // for safety (PpisNeededByDxe and DxeCore). + // + TopOfStack = BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - 32; + + // + // Add architecture-specifc HOBs (including the BspStore HOB) + // + Status = CreateArchSpecificHobs (&BspStore); + ASSERT_EFI_ERROR (Status); + + // + // See if we are in crisis recovery + // + Status = PeiCoreGetBootMode (&BootMode); + if (!EFI_ERROR (Status) && (BootMode == BOOT_IN_RECOVERY_MODE)) { + Status = PeiCoreLocatePpi ( + &gEfiPeiRecoveryModulePpiGuid, + 0, + NULL, + (VOID **)&PeiRecovery + ); + + ASSERT_EFI_ERROR (Status); + Status = PeiRecovery->LoadRecoveryCapsule (PeiServices, PeiRecovery); + ASSERT_EFI_ERROR (Status); + } + + // + // Find the DXE Core in a Firmware Volume + // + Status = PeiFindFile ( + EFI_FV_FILETYPE_DXE_CORE, + EFI_SECTION_PE32, + &DxeCoreFileName, + &DxeCorePe32Data + ); + ASSERT_EFI_ERROR (Status); + + // + // Find the PpisNeededByDxe in a Firmware Volume + // + Status = PeiFindFile ( + EFI_FV_FILETYPE_ALL, + EFI_SECTION_PE32, + &mPpiNeededByDxeGuid, + &PpisNeededByDxePe32Data + ); + ASSERT_EFI_ERROR (Status); + + // + // Transfer control to the DXE Core + // The handoff state is simply a pointer to the HOB list + // + // PEI_PERF_END (PeiServices, L"DxeIpl", NULL, 0); + + Status = PeiCoreInstallPpi (&mPpiSignal); + ASSERT_EFI_ERROR (Status); + + // + // Load the GDT of Go64. Since the GDT of 32-bit Tiano locates in the BS_DATA \ + // memory, it may be corrupted when copying FV to high-end memory + LoadGo64Gdt(); + + // + // Limit to 36 bits of addressing for debug. Should get it from CPU + // + PageTables = CreateIdentityMappingPageTables (36); + + // + // Load the PpiNeededByDxe from a Firmware Volume + // + Status = PeiLoadx64File ( + PeiEfiPeiPeCoffLoader, + PpisNeededByDxePe32Data, + EfiBootServicesData, + &PpisNeededByDxeAddress, + &PpisNeededByDxeSize, + &PpisNeededByDxeEntryPoint + ); + ASSERT_EFI_ERROR (Status); + + + // + // Load the DXE Core from a Firmware Volume + // + Status = PeiLoadx64File ( + PeiEfiPeiPeCoffLoader, + DxeCorePe32Data, + EfiBootServicesData, + &DxeCoreAddress, + &DxeCoreSize, + &DxeCoreEntryPoint + ); + ASSERT_EFI_ERROR (Status); + + // + // + // Add HOB for the DXE Core + // + BuildModuleHob ( + &DxeCoreFileName, + DxeCoreAddress, + DxeCoreSize, + DxeCoreEntryPoint + ); + + // + // Report Status Code EFI_SW_PEI_PC_HANDOFF_TO_NEXT + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_MODULE | EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT + ); + + DEBUG ((EFI_D_INFO, "DXE Core Entry\n")); + // + // Go to Long Mode. Interrupts will not get turned on until the CPU AP is loaded. + // Call x64 drivers passing in single argument, a pointer to the HOBs. + // + ActivateLongMode ( + PageTables, + (EFI_PHYSICAL_ADDRESS)(UINTN)(HobList.Raw), + TopOfStack, + PpisNeededByDxeEntryPoint, + DxeCoreEntryPoint + ); + + // + // If we get here, then the DXE Core returned. This is an error + // + ASSERT_EFI_ERROR (Status); + + return EFI_OUT_OF_RESOURCES; +} + +EFI_STATUS +PeiFindFile ( + IN UINT8 Type, + IN UINT16 SectionType, + OUT EFI_GUID *FileName, + OUT VOID **Pe32Data + ) +/*++ + +Routine Description: + + Finds a PE/COFF of a specific Type and SectionType in the Firmware Volumes + described in the HOB list. Able to search in a compression set in a FFS file. + But only one level of compression is supported, that is, not able to search + in a compression set that is within another compression set. + +Arguments: + + Type - The Type of file to retrieve + + SectionType - The type of section to retrieve from a file + + FileName - The name of the file found in the Firmware Volume + + Pe32Data - Pointer to the beginning of the PE/COFF file found in the Firmware Volume + +Returns: + + EFI_SUCCESS - The file was found, and the name is returned in FileName, and a pointer to + the PE/COFF image is returned in Pe32Data + + EFI_NOT_FOUND - The file was not found in the Firmware Volumes present in the HOB List + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FFS_FILE_HEADER *FfsFileHeader; + VOID *SectionData; + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + + + FwVolHeader = NULL; + FfsFileHeader = NULL; + SectionData = NULL; + + // + // Foreach Firmware Volume, look for a specified type + // of file and break out when one is found + // + Hob.Raw = GetHobList (); + while ((Hob.Raw = GetNextHob (EFI_HOB_TYPE_FV, Hob.Raw)) != NULL) { + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (Hob.FirmwareVolume->BaseAddress); + Status = PeiCoreFfsFindNextFile ( + Type, + FwVolHeader, + &FfsFileHeader + ); + if (!EFI_ERROR (Status)) { + CopyMem (FileName, &FfsFileHeader->Name, sizeof (EFI_GUID)); + Status = PeiProcessFile ( + SectionType, + FfsFileHeader, + Pe32Data + ); + return Status; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return EFI_NOT_FOUND; +} + +EFI_STATUS +PeiLoadx64File ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader, + IN VOID *Pe32Data, + IN EFI_MEMORY_TYPE MemoryType, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + + Loads and relocates a PE/COFF image into memory. + +Arguments: + + PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol + + Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated + + ImageAddress - The base address of the relocated PE/COFF image + + ImageSize - The size of the relocated PE/COFF image + + EntryPoint - The entry point of the relocated PE/COFF image + +Returns: + + EFI_SUCCESS - The file was loaded and relocated + EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_PHYSICAL_ADDRESS MemoryBuffer; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + Status = GetImageReadFunction (&ImageContext); + + ASSERT_EFI_ERROR (Status); + + Status = PeiEfiPeiPeCoffLoader->GetImageInfo (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate Memory for the image + // + // + // Allocate Memory for the image + // + PeiCoreAllocatePages (MemoryType, EFI_SIZE_TO_PAGES ((UINT32) ImageContext.ImageSize), &MemoryBuffer); + ImageContext.ImageAddress = MemoryBuffer; + ASSERT (ImageContext.ImageAddress != 0); + + // + // Load the image to our new buffer + // + + Status = PeiEfiPeiPeCoffLoader->LoadImage (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Relocate the image in our new buffer + // + Status = PeiEfiPeiPeCoffLoader->RelocateImage (PeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Flush the instruction cache so the image data is written before we execute it + // + InvalidateInstructionCacheRange ((VOID *)(UINTN)ImageContext.ImageAddress, (UINTN)ImageContext.ImageSize); + + *ImageAddress = ImageContext.ImageAddress; + *ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + + return EFI_SUCCESS; +} + +EFI_STATUS +ShadowDxeIpl ( + IN EFI_FFS_FILE_HEADER *DxeIplFileHeader, + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader + ) +/*++ + +Routine Description: + + Shadow the DXE IPL to a different memory location. This occurs after permanent + memory has been discovered. + +Arguments: + + DxeIplFileHeader - Pointer to the FFS file header of the DXE IPL driver + + PeiEfiPeiPeCoffLoader - Pointer to a PE COFF loader protocol + +Returns: + + EFI_SUCCESS - DXE IPL was successfully shadowed to a different memory location. + + EFI_ ERROR - The shadow was unsuccessful. + + +--*/ +{ + UINTN SectionLength; + UINTN OccupiedSectionLength; + EFI_PHYSICAL_ADDRESS DxeIplAddress; + UINT64 DxeIplSize; + EFI_PHYSICAL_ADDRESS DxeIplEntryPoint; + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER *Section; + + Section = (EFI_COMMON_SECTION_HEADER *) (DxeIplFileHeader + 1); + + while ((Section->Type != EFI_SECTION_PE32) && (Section->Type != EFI_SECTION_TE)) { + SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; + OccupiedSectionLength = GetOccupiedSize (SectionLength, 4); + Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); + } + + // + // Relocate DxeIpl into memory by using loadfile service + // + Status = PeiLoadx64File ( + PeiEfiPeiPeCoffLoader, + (VOID *) (Section + 1), + EfiBootServicesData, + &DxeIplAddress, + &DxeIplSize, + &DxeIplEntryPoint + ); + + if (Status == EFI_SUCCESS) { + // + // Install PeiInMemory to indicate the Dxeipl is shadowed + // + Status = PeiCoreInstallPpi (&mPpiPeiInMemory); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = ((EFI_PEIM_ENTRY_POINT) (UINTN) DxeIplEntryPoint) (DxeIplFileHeader, GetPeiServicesTablePointer()); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DxeIplLoadFile ( + IN EFI_PEI_FV_FILE_LOADER_PPI *This, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + + Given a pointer to an FFS file containing a PE32 image, get the + information on the PE32 image, and then "load" it so that it + can be executed. + +Arguments: + + This - pointer to our file loader protocol + FfsHeader - pointer to the FFS file header of the FFS file that + contains the PE32 image we want to load + ImageAddress - returned address where the PE32 image is loaded + ImageSize - returned size of the loaded PE32 image + EntryPoint - entry point to the loaded PE32 image + +Returns: + + EFI_SUCCESS - The FFS file was successfully loaded. + EFI_ERROR - Unable to load the FFS file. + +--*/ +{ + EFI_PEI_PE_COFF_LOADER_PROTOCOL *PeiEfiPeiPeCoffLoader; + EFI_STATUS Status; + VOID *Pe32Data; + + Pe32Data = NULL; + PeiEfiPeiPeCoffLoader = (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)GetPeCoffLoaderProtocol (); + + // + // Preprocess the FFS file to get a pointer to the PE32 information + // in the enclosed PE32 image. + // + Status = PeiProcessFile ( + EFI_SECTION_PE32, + FfsHeader, + &Pe32Data + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Load the PE image from the FFS file + // + Status = PeiLoadx64File ( + PeiEfiPeiPeCoffLoader, + Pe32Data, + EfiBootServicesData, + ImageAddress, + ImageSize, + EntryPoint + ); + + return Status; +} + +EFI_STATUS +PeiProcessFile ( + IN UINT16 SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + OUT VOID **Pe32Data + ) +/*++ + +Routine Description: + +Arguments: + + SectionType - The type of section in the FFS file to process. + + FfsFileHeader - Pointer to the FFS file to process, looking for the + specified SectionType + + Pe32Data - returned pointer to the start of the PE32 image found + in the FFS file. + +Returns: + + EFI_SUCCESS - found the PE32 section in the FFS file + +--*/ +{ + EFI_STATUS Status; + VOID *SectionData; + DECOMPRESS_LIBRARY *DecompressLibrary; + UINT8 *DstBuffer; + UINT8 *ScratchBuffer; + UINT32 DstBufferSize; + UINT32 ScratchBufferSize; + EFI_COMMON_SECTION_HEADER *CmpSection; + UINTN CmpSectionLength; + UINTN OccupiedCmpSectionLength; + VOID *CmpFileData; + UINTN CmpFileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINTN SectionLength; + UINTN OccupiedSectionLength; + UINT64 FileSize; + EFI_GUID_DEFINED_SECTION *GuidedSectionHeader; + UINT32 AuthenticationStatus; + EFI_PEI_SECTION_EXTRACTION_PPI *SectionExtract; + UINT32 BufferSize; + UINT8 *Buffer; + EFI_PEI_SECURITY_PPI *Security; + BOOLEAN StartCrisisRecovery; + EFI_GUID TempGuid; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_COMPRESSION_SECTION *CompressionSection; + + Status = PeiCoreFfsFindSectionData ( + EFI_SECTION_COMPRESSION, + FfsFileHeader, + &SectionData + ); + + // + // Upon finding a DXE Core file, see if there is first a compression section + // + if (!EFI_ERROR (Status)) { + // + // Yes, there is a compression section, so extract the contents + // Decompress the image here + // + Section = (EFI_COMMON_SECTION_HEADER *) (UINTN) (VOID *) ((UINT8 *) (FfsFileHeader) + (UINTN) sizeof (EFI_FFS_FILE_HEADER)); + + do { + SectionLength = *(UINT32 *) (Section->Size) & 0x00ffffff; + OccupiedSectionLength = GetOccupiedSize (SectionLength, 4); + + // + // Was the DXE Core file encapsulated in a GUID'd section? + // + if (Section->Type == EFI_SECTION_GUID_DEFINED) { + // + // Locate the GUID'd Section Extractor + // + GuidedSectionHeader = (VOID *) (Section + 1); + + // + // This following code constitutes the addition of the security model + // to the DXE IPL. + // + // + // Set a default authenticatino state + // + AuthenticationStatus = 0; + + Status = PeiCoreLocatePpi ( + &gEfiPeiSectionExtractionPpiGuid, + 0, + NULL, + (VOID **)&SectionExtract + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Verify Authentication State + // + CopyMem (&TempGuid, Section + 1, sizeof (EFI_GUID)); + + Status = SectionExtract->PeiGetSection ( + GetPeiServicesTablePointer(), + SectionExtract, + (EFI_SECTION_TYPE *) &SectionType, + &TempGuid, + 0, + (VOID **) &Buffer, + &BufferSize, + &AuthenticationStatus + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // If not ask the Security PPI, if exists, for disposition + // + // + Status = PeiCoreLocatePpi ( + &gEfiPeiSecurityPpiGuid, + 0, + NULL, + (VOID **)&Security + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = Security->AuthenticationState ( + GetPeiServicesTablePointer(), + (struct _EFI_PEI_SECURITY_PPI *) Security, + AuthenticationStatus, + FfsFileHeader, + &StartCrisisRecovery + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // If there is a security violation, report to caller and have + // the upper-level logic possible engender a crisis recovery + // + if (StartCrisisRecovery) { + return EFI_SECURITY_VIOLATION; + } + } + + if (Section->Type == EFI_SECTION_PE32) { + // + // This is what we want + // + *Pe32Data = (VOID *) (Section + 1); + return EFI_SUCCESS; + } else if (Section->Type == EFI_SECTION_COMPRESSION) { + // + // This is a compression set, expand it + // + CompressionSection = (EFI_COMPRESSION_SECTION *) Section; + + switch (CompressionSection->CompressionType) { + case EFI_STANDARD_COMPRESSION: + DecompressLibrary = &gTianoDecompress; + break; + + case EFI_CUSTOMIZED_COMPRESSION: + // + // Load user customized compression protocol. + // + DecompressLibrary = &gCustomDecompress; + break; + + case EFI_NOT_COMPRESSED: + default: + // + // Need to support not compressed file + // + ASSERT_EFI_ERROR (Status); + return EFI_NOT_FOUND; + } + + Status = DecompressLibrary->GetInfo ( + (UINT8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + (UINT32) SectionLength - sizeof (EFI_COMPRESSION_SECTION), + &DstBufferSize, + &ScratchBufferSize + ); + if (EFI_ERROR (Status)) { + // + // GetInfo failed + // + return EFI_NOT_FOUND; + } + + // + // Allocate scratch buffer + // + ScratchBuffer = AllocatePages (EFI_SIZE_TO_PAGES (ScratchBufferSize)); + if (ScratchBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Allocate destination buffer + // + DstBuffer = AllocatePages (EFI_SIZE_TO_PAGES (DstBufferSize)); + if (DstBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Call decompress function + // + Status = DecompressLibrary->Decompress ( + (CHAR8 *) ((EFI_COMPRESSION_SECTION *) Section + 1), + DstBuffer, + ScratchBuffer + ); + + CmpSection = (EFI_COMMON_SECTION_HEADER *) DstBuffer; + if (CmpSection->Type == EFI_SECTION_RAW) { + // + // Skip the section header and + // adjust the pointer alignment to 16 + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (DstBuffer + 16); + + if (FvHeader->Signature == EFI_FVH_SIGNATURE) { + FfsFileHeader = NULL; + BuildFvHob ((EFI_PHYSICAL_ADDRESS) (UINTN) FvHeader, FvHeader->FvLength); + Status = PeiCoreFfsFindNextFile ( + EFI_FV_FILETYPE_DXE_CORE, + FvHeader, + &FfsFileHeader + ); + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + return PeiProcessFile (SectionType, FfsFileHeader, Pe32Data); + } + } + // + // Decompress successfully. + // Loop the decompressed data searching for expected section. + // + CmpFileData = (VOID *) DstBuffer; + CmpFileSize = DstBufferSize; + do { + CmpSectionLength = *(UINT32 *) (CmpSection->Size) & 0x00ffffff; + if (CmpSection->Type == EFI_SECTION_PE32) { + // + // This is what we want + // + *Pe32Data = (VOID *) (CmpSection + 1); + return EFI_SUCCESS; + } + + OccupiedCmpSectionLength = GetOccupiedSize (CmpSectionLength, 4); + CmpSection = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) CmpSection + OccupiedCmpSectionLength); + } while (CmpSection->Type != 0 && (UINTN) ((UINT8 *) CmpSection - (UINT8 *) CmpFileData) < CmpFileSize); + } + + Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + OccupiedSectionLength); + FileSize = FfsFileHeader->Size[0] & 0xFF; + FileSize += (FfsFileHeader->Size[1] << 8) & 0xFF00; + FileSize += (FfsFileHeader->Size[2] << 16) & 0xFF0000; + FileSize &= 0x00FFFFFF; + } while (Section->Type != 0 && (UINTN) ((UINT8 *) Section - (UINT8 *) FfsFileHeader) < FileSize); + + // + // End of the decompression activity + // + } else { + + Status = PeiCoreFfsFindSectionData ( + EFI_SECTION_PE32, + FfsFileHeader, + &SectionData + ); + + if (EFI_ERROR (Status)) { + Status = PeiCoreFfsFindSectionData ( + EFI_SECTION_TE, + FfsFileHeader, + &SectionData + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + *Pe32Data = SectionData; + + return EFI_SUCCESS; +} \ No newline at end of file diff --git a/EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c b/EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c new file mode 100644 index 0000000000..95fb0937c5 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/Ipf/DxeLoadFunc.c @@ -0,0 +1,70 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + IpfDxeLoad.c + +Abstract: + + Ipf-specifc functionality for DxeLoad. + +--*/ + +#include + +EFI_STATUS +CreateArchSpecificHobs ( + OUT EFI_PHYSICAL_ADDRESS *BspStore + ) +/*++ + +Routine Description: + + Creates architecture-specific HOBs. + + Note: New parameters should NOT be added for any HOBs that are added to this + function. BspStore is a special case because it is required for the + call to SwitchStacks() in DxeLoad(). + +Arguments: + + BspStore - The address of the BSP Store for those architectures that need + it. Otherwise 0. + +Returns: + + EFI_SUCCESS - The HOBs were created successfully. + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + + ASSERT (NULL != BspStore); + + // + // Allocate 16KB for the BspStore + // + Status = PeiCoreAllocatePages (EfiBootServicesData, EFI_SIZE_TO_PAGES (BSP_STORE_SIZE), BspStore); + if (EFI_ERROR (Status)) { + return Status; + } + + BuildBspStoreHob ( + *BspStore, + BSP_STORE_SIZE, + EfiBootServicesData + ); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c b/EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c new file mode 100644 index 0000000000..16b44b24d8 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/Ipf/ImageRead.c @@ -0,0 +1,72 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ImageRead.c + +Abstract: + +--*/ + +#include + +EFI_STATUS +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINTN Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + ImageContext->ImageRead = PeiImageRead; + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/DxeIplPeim/build.xml b/EdkModulePkg/Core/DxeIplPeim/build.xml new file mode 100644 index 0000000000..5f83fe7365 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Core/DxeIplPeim/build_X64.xml b/EdkModulePkg/Core/DxeIplPeim/build_X64.xml new file mode 100644 index 0000000000..aef68ec4dc --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/build_X64.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Core/DxeIplPeim/ia32/DxeLoadFunc.c b/EdkModulePkg/Core/DxeIplPeim/ia32/DxeLoadFunc.c new file mode 100644 index 0000000000..4d1015bbd8 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/ia32/DxeLoadFunc.c @@ -0,0 +1,51 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeLoadFunc.c + +Abstract: + + Ia32-specifc functionality for DxeLoad. + +--*/ + +#include + +EFI_STATUS +CreateArchSpecificHobs ( + OUT EFI_PHYSICAL_ADDRESS *BspStore + ) +/*++ + +Routine Description: + + Creates architecture-specific HOBs. + + Note: New parameters should NOT be added for any HOBs that are added to this + function. BspStore is a special case because it is required for the + call to SwitchStacks() in DxeLoad(). + +Arguments: + + BspStore - The address of the BSP Store for those architectures that need + it. Otherwise 0. + +Returns: + + EFI_SUCCESS - The HOBs were created successfully. + +--*/ +{ + *BspStore = 0; + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/DxeIplPeim/ia32/ImageRead.c b/EdkModulePkg/Core/DxeIplPeim/ia32/ImageRead.c new file mode 100644 index 0000000000..fe07608290 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/ia32/ImageRead.c @@ -0,0 +1,112 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ImageRead.c + +Abstract: + +--*/ + +#include + +EFI_STATUS +EFIAPI +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + UINT8 *Destination32; + UINT8 *Source32; + UINTN Length; + + + Destination32 = Buffer; + Source32 = (UINT8 *) ((UINTN) FileHandle + FileOffset); + + // + // This function assumes 32-bit alignment to increase performance + // +// ASSERT (ALIGN_POINTER (Destination32, sizeof (UINT32)) == Destination32); +// ASSERT (ALIGN_POINTER (Source32, sizeof (UINT32)) == Source32); + + Length = *ReadSize; + while (Length--) { + *(Destination32++) = *(Source32++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + Support routine to return the PE32 Image Reader. + If the PeiImageRead() function is less than a page + in legnth. If the function is more than a page the DXE IPL will crash!!!! + +Arguments: + ImageContext - The context of the image being loaded + +Returns: + EFI_SUCCESS - If Image function location is found + +--*/ +{ + VOID *MemoryBuffer; + + if (gInMemory) { + ImageContext->ImageRead = PeiImageRead; + return EFI_SUCCESS; + } + + // + // BugBug; This code assumes PeiImageRead() is less than a page in size! + // Allocate a page so we can shaddow the read function from FLASH into + // memory to increase performance. + // + + MemoryBuffer = AllocateCopyPool (0x400, (VOID *)(UINTN) PeiImageRead); + ASSERT (MemoryBuffer != NULL); + + ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c b/EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c new file mode 100644 index 0000000000..c93c7e1747 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/x64/DxeLoadFunc.c @@ -0,0 +1,53 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeLoadFunc.c + +Abstract: + + Ia32-specifc functionality for DxeLoad X64 Lakeport. + +--*/ + +#include + +EFI_STATUS +CreateArchSpecificHobs ( + OUT EFI_PHYSICAL_ADDRESS *BspStore + ) +/*++ + +Routine Description: + + Creates architecture-specific HOBs. + + Note: New parameters should NOT be added for any HOBs that are added to this + function. BspStore is a special case because it is required for the + call to SwitchStacks() in DxeLoad(). + +Arguments: + + PeiServices - General purpose services available to every PEIM. + BspStore - The address of the BSP Store for those architectures that need + it. Otherwise 0. + +Returns: + + EFI_SUCCESS - The HOBs were created successfully. + +--*/ +{ + *BspStore = 0; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c b/EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c new file mode 100644 index 0000000000..dd977f2d2e --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/x64/ImageRead.c @@ -0,0 +1,106 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ImageRead.c + +Abstract: + +--*/ + +#include + +EFI_STATUS +EFIAPI +PeiImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINTN Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Support routine to return the PE32 Image Reader. + If the PeiImageRead() function is less than a page + in legnth. If the function is more than a page the DXE IPL will crash!!!! + +Arguments: + ImageContext - The context of the image being loaded + +Returns: + + EFI_SUCCESS - If Image function location is found + +--*/ +{ + VOID *MemoryBuffer; + + if (gInMemory) { + ImageContext->ImageRead = PeiImageRead; + return EFI_SUCCESS; + } + + // + // BugBug; This code assumes PeiImageRead() is less than a page in size! + // Allocate a page so we can shaddow the read function from FLASH into + // memory to increase performance. + // + + MemoryBuffer = AllocateCopyPool (0x400, (VOID *)(UINTN) PeiImageRead); + ASSERT (MemoryBuffer != NULL); + + ImageContext->ImageRead = (PE_COFF_LOADER_READ_FILE) (UINTN) MemoryBuffer; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm b/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm new file mode 100644 index 0000000000..a9c4e774cf --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/x64/LongMode.asm @@ -0,0 +1,1357 @@ + TITLE LongMode.asm: Assembly code for the entering long mode + +;------------------------------------------------------------------------------ +;* +;* Copyright (c) 2006, 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. +;* +;* LongMode.asm +;* +;* Abstract: +;* +;* Transition from 32-bit protected mode EFI environment into x64 +;* 64-bit bit long mode. +;* +;------------------------------------------------------------------------------ + +.686p +.model flat + +; +; Create the exception handler code in IA32 C code +; + +.code +.stack +.MMX +.XMM + +_LoadGo64Gdt PROC Near Public + push ebp ; C prolog + push edi + mov ebp, esp + ; + ; Disable interrupts + ; + cli + ; + ; Reload the selectors + ; Note: + ; Make the Selectors 64-bit ready + ; + mov edi, OFFSET gdtr ; Load GDT register + mov ax,cs ; Get the selector data from our code image + mov es,ax + lgdt FWORD PTR es:[edi] ; and update the GDTR + + db 067h + db 0eah ; Far Jump Offset:Selector to reload CS + dd OFFSET DataSelectorRld; Offset is ensuing instruction boundary + dw LINEAR_CODE_SEL ; Selector is our code selector, 10h +DataSelectorRld:: + mov ax, SYS_DATA_SEL ; Update the Base for the new selectors, too + mov ds, ax + mov es, ax + mov fs, ax + mov gs, ax + mov ss, ax + + pop edi + pop ebp + ret +_LoadGo64Gdt endp + + +; VOID +; ActivateLongMode ( +; IN EFI_PHYSICAL_ADDRESS PageTables, +; IN EFI_PHYSICAL_ADDRESS HobStart, +; IN EFI_PHYSICAL_ADDRESS Stack, +; IN EFI_PHYSICAL_ADDRESS PpisNeededByDxeIplEntryPoint, +; IN EFI_PHYSICAL_ADDRESS DxeCoreEntryPoint +; ) +; +; Input: [ebp][0h] = Original ebp +; [ebp][4h] = Return address +; [ebp][8h] = PageTables +; [ebp][10h] = HobStart +; [ebp][18h] = Stack +; [ebp][20h] = CodeEntryPoint1 <--- Call this first (for each call, pass HOB pointer) +; [ebp][28h] = CodeEntryPoint2 <--- Call this second +; +; +_ActivateLongMode PROC Near Public + push ebp ; C prolog + mov ebp, esp + + ; + ; Use CPUID to determine if the processor supports long mode. + ; + mov eax, 80000000h ; Extended-function code 8000000h. + cpuid ; Is largest extended function + cmp eax, 80000000h ; any function > 80000000h? + jbe no_long_mode ; If not, no long mode. + mov eax, 80000001h ; Extended-function code 8000001h. + cpuid ; Now EDX = extended-features flags. + bt edx, 29 ; Test if long mode is supported. + jnc no_long_mode ; Exit if not supported. + + ; + ; Enable the 64-bit page-translation-table entries by + ; setting CR4.PAE=1 (this is _required_ before activating + ; long mode). Paging is not enabled until after long mode + ; is enabled. + ; + mov eax, cr4 + bts eax, 5 + mov cr4, eax + + ; + ; Get the long-mode page tables, and initialize the + ; 64-bit CR3 (page-table base address) to point to the base + ; of the PML4 page table. The PML4 page table must be located + ; below 4 Gbytes because only 32 bits of CR3 are loaded when + ; the processor is not in 64-bit mode. + ; + mov eax, [ebp+8h] ; Get Page Tables + mov cr3, eax ; Initialize CR3 with PML4 base. + + ; + ; Enable long mode (set EFER.LME=1). + ; + mov ecx, 0c0000080h ; EFER MSR number. + rdmsr ; Read EFER. + bts eax, 8 ; Set LME=1. + wrmsr ; Write EFER. + + ; + ; Enable paging to activate long mode (set CR0.PG=1) + ; + + + mov eax, cr0 ; Read CR0. + bts eax, 31 ; Set PG=1. + mov cr0, eax ; Write CR0. + jmp go_to_long_mode +go_to_long_mode: + + ; + ; This is the next instruction after enabling paging. Jump to long mode + ; + db 067h + db 0eah ; Far Jump Offset:Selector to reload CS + dd OFFSET in_long_mode; Offset is ensuing instruction boundary + dw SYS_CODE64_SEL ; Selector is our code selector, 10h +in_long_mode:: + mov ax, SYS_DATA64_SEL + mov es, ax + mov ss, ax + mov ds, ax +;; jmp $ + + + ; + ; We're in long mode, so marshall the arguments to call the + ; passed in function pointers + ; Recall + ; [ebp][10h] = HobStart + ; [ebp][18h] = Stack + ; [ebp][20h] = PpisNeededByDxeIplEntryPoint <--- Call this first (for each call, pass HOB pointer) + ; [ebp][28h] = DxeCoreEntryPoint <--- Call this second + ; + db 48h + mov ebx, [ebp+18h] ; Setup the stack + db 48h + mov esp, ebx ; On a new stack now + + db 48h + mov ecx, [ebp+10h] ; Pass Hob Start in RCX + db 48h + mov eax, [ebp+20h] ; Get the function pointer for + ; PpisNeededByDxeIplEntryPoint into EAX + +;; 00000905 FF D0 call rax + db 0ffh + db 0d0h + + db 48h + mov ecx, [ebp+10h] ; Pass Hob Start in RCX + db 48h + mov eax, [ebp+28h] ; Get the function pointer for + ; DxeCoreEntryPoint into EAX + +;; 00000905 FF D0 call rax + db 0ffh + db 0d0h + + ; + ; WE SHOULD NEVER GET HERE!!!!!!!!!!!!! + ; +no_long_mode: + jmp no_long_mode +_ActivateLongMode endp + + align 16 + +gdtr dw GDT_END - GDT_BASE - 1 ; GDT limit + dd OFFSET GDT_BASE ; (GDT base gets set above) + +;-----------------------------------------------------------------------------; +; global descriptor table (GDT) +;-----------------------------------------------------------------------------; + + align 16 + +public GDT_BASE +GDT_BASE: +; null descriptor +NULL_SEL equ $-GDT_BASE ; Selector [0] + dw 0 ; limit 15:0 + dw 0 ; base 15:0 + db 0 ; base 23:16 + db 0 ; type + db 0 ; limit 19:16, flags + db 0 ; base 31:24 + +; linear data segment descriptor +LINEAR_SEL equ $-GDT_BASE ; Selector [0x8] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 092h ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; linear code segment descriptor +LINEAR_CODE_SEL equ $-GDT_BASE ; Selector [0x10] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Fh ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; system data segment descriptor +SYS_DATA_SEL equ $-GDT_BASE ; Selector [0x18] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 093h ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; system code segment descriptor +SYS_CODE_SEL equ $-GDT_BASE ; Selector [0x20] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Ah ; present, ring 0, data, expand-up, writable + db 0CFh ; page-granular, 32-bit + db 0 + +; spare segment descriptor +SPARE3_SEL equ $-GDT_BASE ; Selector [0x28] + dw 0 ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 0 ; present, ring 0, data, expand-up, writable + db 0 ; page-granular, 32-bit + db 0 + +; +; system data segment descriptor +; +SYS_DATA64_SEL equ $-GDT_BASE ; Selector [0x30] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 092h ; P | DPL [1..2] | 1 | 1 | C | R | A + db 0CFh ; G | D | L | AVL | Segment [19..16] + db 0 + +; +; system code segment descriptor +; +SYS_CODE64_SEL equ $-GDT_BASE ; Selector [0x38] + dw 0FFFFh ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 09Ah ; P | DPL [1..2] | 1 | 1 | C | R | A + db 0AFh ; G | D | L | AVL | Segment [19..16] + db 0 + +; spare segment descriptor +SPARE4_SEL equ $-GDT_BASE ; Selector [0x40] + dw 0 ; limit 0xFFFFF + dw 0 ; base 0 + db 0 + db 0 ; present, ring 0, data, expand-up, writable + db 0 ; page-granular, 32-bit + db 0 + +GDT_END: + +; +; +;------------------------------------------------------------------------------ +; Generic IDT Vector Handlers for the Host. They are all the same so they +; will compress really well. +; +; By knowing the return address for Vector 00 you can can calculate the +; vector number by looking at the call CommonInterruptEntry return address. +; (return address - AsmIdtVector00Base)/8 == IDT index +; +;------------------------------------------------------------------------------ + +_AsmIdtVector00 PROC NEAR PUBLIC + call CommonInterruptEntry +_AsmIdtVector00 ENDP +AsmIdtVector00Base PROC NEAR PUBLIC + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop + call CommonInterruptEntry + nop + nop + nop +AsmIdtVector00Base ENDP + + +;---------------------------------------; +; CommonInterruptEntry ; +;---------------------------------------; +; The follow algorithm is used for the common interrupt routine. +; TBD: Save EFI_SYSTEM_CONTEXT_x64 on the stack per AP definition +; +; +CommonInterruptEntry PROC NEAR PUBLIC + cli + jmp $ + iret + +CommonInterruptEntry ENDP + +END + diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c b/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c new file mode 100644 index 0000000000..40eaed2ce6 --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.c @@ -0,0 +1,434 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + VirtualMemory.c + +Abstract: + + x64 Virtual Memory Management Services in the form of an IA-32 driver. + Used to establish a 1:1 Virtual to Physical Mapping that is required to + enter Long Mode (x64 64-bit mode). + + While we make a 1:1 mapping (identity mapping) for all physical pages + we still need to use the MTRR's to ensure that the cachability attirbutes + for all memory regions is correct. + + The basic idea is to use 2MB page table entries where ever possible. If + more granularity of cachability is required then 4K page tables are used. + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + +--*/ + +#include "VirtualMemory.h" + +x64_MTRR_VARIABLE_RANGE *mMTRRVariableRange; +x64_MTRR_FIXED_RANGE mMTRRFixedRange; + + +// +// Physial memory limit values for each of the 11 fixed MTRRs +// +UINTN mFixedRangeLimit[] = { + 0x7FFFF, // Fixed MTRR #0 describes 0x00000..0x7FFFF + 0x9FFFF, // Fixed MTRR #1 describes 0x80000..0x9FFFF + 0xBFFFF, // Fixed MTRR #2 describes 0xA0000..0xBFFFF + 0xC7FFF, // Fixed MTRR #3 describes 0xC0000..0xC7FFF + 0xCFFFF, // Fixed MTRR #4 describes 0xC8000..0xCFFFF + 0xD7FFF, // Fixed MTRR #5 describes 0xD0000..0xD7FFF + 0xDFFFF, // Fixed MTRR #6 describes 0xD8000..0xDFFFF + 0xE7FFF, // Fixed MTRR #7 describes 0xE0000..0xE7FFF + 0xEFFFF, // Fixed MTRR #8 describes 0xE8000..0xEFFFF + 0xF7FFF, // Fixed MTRR #9 describes 0xF0000..0xF7FFF + 0xFFFFF // Fixed MTRR #10 describes 0xF8000..0xFFFFF +}; + +// +// The size, in bits, of each of the 11 fixed MTRR. +// +UINTN mFixedRangeShift[] = { + 16, // Fixed MTRR #0 describes 8, 64 KB ranges + 14, // Fixed MTRR #1 describes 8, 16 KB ranges + 14, // Fixed MTRR #2 describes 8, 16 KB ranges + 12, // Fixed MTRR #3 describes 8, 4 KB ranges + 12, // Fixed MTRR #4 describes 8, 4 KB ranges + 12, // Fixed MTRR #5 describes 8, 4 KB ranges + 12, // Fixed MTRR #6 describes 8, 4 KB ranges + 12, // Fixed MTRR #7 describes 8, 4 KB ranges + 12, // Fixed MTRR #8 describes 8, 4 KB ranges + 12, // Fixed MTRR #9 describes 8, 4 KB ranges + 12 // Fixed MTRR #10 describes 8, 4 KB ranges +}; + + +UINTN mPowerOf2[] = { + 1, + 2, + 4, + 8, + 16, + 32, + 64, + 128, + 256, + 512 +}; + +x64_MTRR_MEMORY_TYPE +EfiGetMTRRMemoryType ( + IN EFI_PHYSICAL_ADDRESS Address + ) +/*++ + +Routine Description: + + Retrieves the memory type from the MTRR that describes a physical address. + +Arguments: + + VariableRange - Set of Variable MTRRs + + FixedRange - Set of Fixed MTRRs + + Address - The physical address for which the MTRR memory type is being retrieved + +Returns: + + The MTRR Memory Type for the physical memory specified by Address. + +--*/ +{ + UINTN Index; + UINTN TypeIndex; + BOOLEAN Found; + x64_MTRR_MEMORY_TYPE VariableType; + EFI_PHYSICAL_ADDRESS MaskBase; + EFI_PHYSICAL_ADDRESS PhysMask; + + // + // If the MTRRs are disabled, then return the Uncached Memory Type + // + if (mMTRRFixedRange.DefaultType.Bits.E == 0) { + return Uncached; + } + + // + // If the CPU supports Fixed MTRRs and the Fixed MTRRs are enabled, then + // see if Address falls into one of the Fixed MTRRs + // + if (mMTRRFixedRange.Capabilities.Bits.FIX && mMTRRFixedRange.DefaultType.Bits.FE) { + // + // Loop though 11 fixed MTRRs + // + for (Index = 0; Index < 11; Index++) { + // + // Check for a matching range + // + if (Address <= mFixedRangeLimit[Index]) { + // + // Compute the offset address into the MTRR bu subtrating the base address of the MTRR + // + if (Index > 0) { + Address = Address - (mFixedRangeLimit[Index-1] + 1); + } + // + // Retrieve the index into the MTRR to extract the memory type. The range is 0..7 + // + TypeIndex = (UINTN)RShiftU64 (Address, mFixedRangeShift[Index]); + + // + // Retrieve and return the memory type for the matching range + // + return mMTRRFixedRange.Fixed[Index].Type[TypeIndex]; + } + } + } + + // + // If Address was not found in a Fixed MTRR, then search the Variable MTRRs + // + for (Index = 0, Found = FALSE, VariableType = WriteBack; Index < mMTRRFixedRange.Capabilities.Bits.VCNT; Index++) { + // + // BugBug: __aullshr complier error + // + if ((mMTRRVariableRange[Index].PhysMask.Uint64 & 0x800) == 0x800) { + //if (mMTRRVariableRange[Index].PhysMask.Bits.Valid == 1) { + PhysMask = mMTRRVariableRange[Index].PhysMask.Uint64 & ~0xfff; + MaskBase = PhysMask & (mMTRRVariableRange[Index].PhysBase.Uint64 & ~0xfff); + if (MaskBase == (PhysMask & Address)) { + // + // Check to see how many matches we find + // + Found = TRUE; + if ((mMTRRVariableRange[Index].PhysBase.Bits.Type == Uncached) || (VariableType == Uncached)) { + // + // If any matching region uses UC, the memory region is UC + // + VariableType = Uncached; + } else if ((mMTRRVariableRange[Index].PhysBase.Bits.Type == WriteThrough) || (VariableType == WriteThrough)){ + // + // If it's WT and WB then set it to WT. If it's WT and other type it's undefined + // + VariableType = WriteThrough; + } else { + VariableType = mMTRRVariableRange[Index].PhysBase.Bits.Type; + } + } + } + } + + if (Found) { + return VariableType; + } + + // + // Address was not found in the Fixed or Variable MTRRs, so return the default memory type + // + return mMTRRFixedRange.DefaultType.Bits.Type; +} + + +BOOLEAN +CanNotUse2MBPage ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +/*++ + +Routine Description: + Test to see if a 2MB aligned page has all the same attributes. If a 2MB page + has more than one attibute type it needs to be split into multiple 4K pages. + +Arguments: + BaseAddress - 2MB aligned address to check out + +Returns: + TRUE - This 2MB address range (BaseAddress) can NOT be mapped by a 2MB page + FALSE - This 2MB address range can be mapped by a 2MB page + +--*/ +{ + UINTN Index; + x64_MTRR_MEMORY_TYPE MemoryType; + x64_MTRR_MEMORY_TYPE PreviousMemoryType; + + // + // Address needs to be 2MB aligned + // + ASSERT ((BaseAddress & 0x1fffff) == 0); + + PreviousMemoryType = -1; + for (Index = 0; Index < 512; Index++, BaseAddress += 0x1000) { + MemoryType = EfiGetMTRRMemoryType (BaseAddress); + if ((Index != 0) && (MemoryType != PreviousMemoryType)) { + return TRUE; + } + + PreviousMemoryType = MemoryType; + } + + // + // All the pages had the same type + // + return FALSE; +} + + + + +VOID +Convert2MBPageTo4KPages ( + IN x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB, + IN EFI_PHYSICAL_ADDRESS PageAddress + ) +/*++ + +Routine Description: + Convert a single 2MB page entry to 512 4K page entries. The attributes for + the 4K pages are read from the MTRR registers. + +Arguments: + PageDirectoryEntry2MB - Page directory entry for PageAddress + PageAddress - 2MB algined address of region to convert + +Returns: + None + +--*/ +{ + EFI_PHYSICAL_ADDRESS Address; + x64_PAGE_DIRECTORY_ENTRY_4K *PageDirectoryEntry4k; + x64_PAGE_TABLE_ENTRY_4K *PageTableEntry; + UINTN Index1; + + // + // Allocate the page table entry for the 4K pages + // + PageTableEntry = (x64_PAGE_TABLE_ENTRY_4K *) AllocatePages (1); + + ASSERT (PageTableEntry != NULL); + + // + // Convert PageDirectoryEntry2MB into a 4K Page Directory + // + PageDirectoryEntry4k = (x64_PAGE_DIRECTORY_ENTRY_4K *)PageDirectoryEntry2MB; + PageDirectoryEntry2MB->Uint64 = (UINT64)PageTableEntry; + PageDirectoryEntry2MB->Bits.ReadWrite = 1; + PageDirectoryEntry2MB->Bits.Present = 1; + + // + // Fill in the 4K page entries with the attributes from the MTRRs + // + for (Index1 = 0, Address = PageAddress; Index1 < 512; Index1++, PageTableEntry++, Address += 0x1000) { + PageTableEntry->Uint64 = (UINT64)Address; + PageTableEntry->Bits.ReadWrite = 1; + PageTableEntry->Bits.Present = 1; + } +} + + +EFI_PHYSICAL_ADDRESS +CreateIdentityMappingPageTables ( + IN UINT32 NumberOfProcessorPhysicalAddressBits + ) +/*++ + +Routine Description: + + Allocates and fills in the Page Directory and Page Table Entries to + establish a 1:1 Virtual to Physical mapping for physical memory from + 0 to 4GB. Memory above 4GB is not mapped. The MTRRs are used to + determine the cachability of the physical memory regions + +Arguments: + + NumberOfProcessorPhysicalAddressBits - Number of processor address bits to use. + Limits the number of page table entries + to the physical address space. + +Returns: + EFI_OUT_OF_RESOURCES There are not enough resources to allocate the Page Tables + + EFI_SUCCESS The 1:1 Virtual to Physical identity mapping was created + +--*/ +{ + EFI_PHYSICAL_ADDRESS PageAddress; + UINTN Index; + UINTN MaxBitsSupported; + UINTN Index1; + UINTN Index2; + x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry; + x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMap; + x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry; + x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB; + + + // + // Page Table structure 4 level 4K, 3 level 2MB. + // + // PageMapLevel4Entry : bits 47-39 + // PageDirectoryPointerEntry : bits 38-30 + // Page Table 2MB : PageDirectoryEntry2M : bits 29-21 + // Page Table 4K : PageDirectoryEntry4K : bits 29 - 21 + // PageTableEntry : bits 20 - 12 + // + // Strategy is to map every thing in the processor address space using + // 2MB pages. If more granularity is required the 2MB page will get + // converted to set of 4K pages. + // + + // + // By architecture only one PageMapLevel4 exists - so lets allocate storgage for it. + // + PageMap = PageMapLevel4Entry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) AllocatePages (1); + ASSERT (PageMap != NULL); + PageAddress = 0; + + // + // The number of page-map Level-4 Offset entries is based on the number of + // physical address bits. Less than equal to 38 bits only takes one entry. + // 512 entries represents 48 address bits. + // + if (NumberOfProcessorPhysicalAddressBits <= 38) { + MaxBitsSupported = 1; + } else { + MaxBitsSupported = mPowerOf2[NumberOfProcessorPhysicalAddressBits - 39]; + } + + for (Index = 0; Index < MaxBitsSupported; Index++, PageMapLevel4Entry++) { + // + // Each PML4 entry points to a page of Page Directory Pointer entires. + // So lets allocate space for them and fill them in in the Index1 loop. + // + PageDirectoryPointerEntry = (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *) AllocatePages (1); + ASSERT (PageDirectoryPointerEntry != NULL); + + // + // Make a PML4 Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINTN)PageDirectoryPointerEntry; + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + for (Index1 = 0; Index1 < 512; Index1++, PageDirectoryPointerEntry++) { + // + // Each Directory Pointer entries points to a page of Page Directory entires. + // So lets allocate space for them and fill them in in the Index2 loop. + // + PageDirectoryEntry2MB = (x64_PAGE_TABLE_ENTRY_2M *) AllocatePages (1); + ASSERT (PageDirectoryEntry2MB != NULL); + + // + // Fill in a Page Directory Pointer Entries + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINTN)PageDirectoryEntry2MB; + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (Index2 = 0; Index2 < 512; Index2++, PageDirectoryEntry2MB++, PageAddress += 0x200000) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress; + PageDirectoryEntry2MB->Bits.ReadWrite = 1; + PageDirectoryEntry2MB->Bits.Present = 1; + PageDirectoryEntry2MB->Bits.MustBe1 = 1; + + if (CanNotUse2MBPage (PageAddress)) { + // + // Check to see if all 2MB has the same mapping. If not convert + // to 4K pages by adding the 4th level of page table entries + // + Convert2MBPageTo4KPages (PageDirectoryEntry2MB, PageAddress); + } + } + } + } + + // + // For the PML4 entries we are not using fill in a null entry. + // for now we just copy the first entry. + // + for (; Index < 512; Index++, PageMapLevel4Entry++) { + // EfiCopyMem (PageMapLevel4Entry, PageMap, sizeof (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K)); + CopyMem (PageMapLevel4Entry, + PageMap, + sizeof (x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K) + ); + } + + return (EFI_PHYSICAL_ADDRESS)PageMap; +} + diff --git a/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h b/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h new file mode 100644 index 0000000000..8133ad447f --- /dev/null +++ b/EdkModulePkg/Core/DxeIplPeim/x64/VirtualMemory.h @@ -0,0 +1,239 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + VirtualMemory.h + +Abstract: + + x64 Long Mode Virtual Memory Management Definitions + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming +--*/ +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + + +#pragma pack(1) + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} x64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K; + +// +// Page-Directory Offset 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:1; // Must Be Zero + UINT64 Reserved2:1; // Reserved + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} x64_PAGE_DIRECTORY_ENTRY_4K; + +// +// Page Table Entry 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 PAT:1; // 0 = Ignore Page Attribute Table + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} x64_PAGE_TABLE_ENTRY_4K; + + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} x64_PAGE_TABLE_ENTRY_2M; + +typedef union { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 Reserved:57; +} x64_PAGE_TABLE_ENTRY_COMMON; + +typedef union { + x64_PAGE_TABLE_ENTRY_4K Page4k; + x64_PAGE_TABLE_ENTRY_2M Page2Mb; + x64_PAGE_TABLE_ENTRY_COMMON Common; +} x64_PAGE_TABLE_ENTRY; + +// +// MTRR Definitions +// +typedef enum { + Uncached = 0, + WriteCombining = 1, + WriteThrough = 4, + WriteProtected = 5, + WriteBack = 6 +} x64_MTRR_MEMORY_TYPE; + +typedef union { + struct { + UINT32 VCNT:8; // The number of Variable Range MTRRs + UINT32 FIX:1; // 1=Fixed Range MTRRs supported. 0=Fixed Range MTRRs not supported + UINT32 Reserved_0; // Reserved + UINT32 WC:1; // Write combining memory type supported + UINT32 Reserved_1:21; // Reserved + UINT32 Reserved_2:32; // Reserved + } Bits; + UINT64 Uint64; +} x64_MTRRCAP_MSR; + +typedef union { + struct { + UINT32 Type:8; // Default Memory Type + UINT32 Reserved_0:2; // Reserved + UINT32 FE:1; // 1=Fixed Range MTRRs enabled. 0=Fixed Range MTRRs disabled + UINT32 E:1; // 1=MTRRs enabled, 0=MTRRs disabled + UINT32 Reserved_1:20; // Reserved + UINT32 Reserved_2:32; // Reserved + } Bits; + UINT64 Uint64; +} x64_MTRR_DEF_TYPE_MSR; + +typedef union { + UINT8 Type[8]; // The 8 Memory Type values in the 64-bit MTRR + UINT64 Uint64; // The full 64-bit MSR +} x64_MTRR_FIXED_RANGE_MSR; + +typedef struct { + x64_MTRRCAP_MSR Capabilities; // MTRR Capabilities MSR value + x64_MTRR_DEF_TYPE_MSR DefaultType; // Default Memory Type MSR Value + x64_MTRR_FIXED_RANGE_MSR Fixed[11]; // The 11 Fixed MTRR MSR Values +} x64_MTRR_FIXED_RANGE; + + +typedef union { + struct { + UINT64 Type:8; // Memory Type + UINT64 Reserved0:4; // Reserved + UINT64 PhysBase:40; // The physical base address(bits 35..12) of the MTRR + UINT64 Reserved1:12 ; // Reserved + } Bits; + UINT64 Uint64; +} x64_MTRR_PHYSBASE_MSR; + +typedef union { + struct { + UINT64 Reserved0:11; // Reserved + UINT64 Valid:1; // 1=MTRR is valid, 0=MTRR is not valid + UINT64 PhysMask:40; // The physical address mask (bits 35..12) of the MTRR + UINT64 Reserved1:12; // Reserved + } Bits; + UINT64 Uint64; +} x64_MTRR_PHYSMASK_MSR; + +typedef struct { + x64_MTRR_PHYSBASE_MSR PhysBase; // Variable MTRR Physical Base MSR + x64_MTRR_PHYSMASK_MSR PhysMask; // Variable MTRR Physical Mask MSR +} x64_MTRR_VARIABLE_RANGE; + +#pragma pack() + +x64_MTRR_MEMORY_TYPE +EfiGetMTRRMemoryType ( + IN EFI_PHYSICAL_ADDRESS Address + ) +; + +BOOLEAN +CanNotUse2MBPage ( + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +; + +VOID +Convert2MBPageTo4KPages ( + IN x64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB, + IN EFI_PHYSICAL_ADDRESS PageAddress + ) +; + +EFI_PHYSICAL_ADDRESS +CreateIdentityMappingPageTables ( + IN UINT32 NumberOfProcessorPhysicalAddressBits + ) +; + +#endif diff --git a/EdkModulePkg/Core/Pei/BootMode/BootMode.c b/EdkModulePkg/Core/Pei/BootMode/BootMode.c new file mode 100644 index 0000000000..049cfd1a8f --- /dev/null +++ b/EdkModulePkg/Core/Pei/BootMode/BootMode.c @@ -0,0 +1,106 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BootMode.c + +Abstract: + + EFI PEI Core Boot Mode services + + + +Revision History + +--*/ + +#include + +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to ascertain the present value of the boot mode. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - A pointer to contain the value of the boot mode. + +Returns: + + EFI_SUCCESS - The boot mode was returned successfully. + EFI_INVALID_PARAMETER - BootMode is NULL. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + + if (BootMode == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + *BootMode = HandOffHob->BootMode; + + + return EFI_SUCCESS; +}; + + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to update the boot mode variable. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - The value of the boot mode to set. + +Returns: + + EFI_SUCCESS - The value was successfully updated + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + HandOffHob = (PrivateData->HobList.HandoffInformationTable); + + HandOffHob->BootMode = BootMode; + + + return EFI_SUCCESS; +}; diff --git a/EdkModulePkg/Core/Pei/Dependency/dependency.c b/EdkModulePkg/Core/Pei/Dependency/dependency.c new file mode 100644 index 0000000000..5c82eefa1b --- /dev/null +++ b/EdkModulePkg/Core/Pei/Dependency/dependency.c @@ -0,0 +1,264 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + dependency.c + +Abstract: + + PEI Dispatcher Dependency Evaluator + + This routine evaluates a dependency expression (DEPENDENCY_EXPRESSION) to determine + if a driver can be scheduled for execution. The criteria for + schedulability is that the dependency expression is satisfied. + +--*/ + +#include +#include "Dependency.h" + +STATIC +BOOLEAN +IsPpiInstalled ( + IN EFI_PEI_SERVICES **PeiServices, + IN EVAL_STACK_ENTRY *Stack + ) +/*++ + +Routine Description: + + This routine determines if a PPI has been installed. + The truth value of a GUID is determined by if the PPI has + been published and can be queried from the PPI database. + +Arguments: + PeiServices - The PEI core services table. + Stack - Reference to EVAL_STACK_ENTRY that contains PPI GUID to check + +Returns: + + True if the PPI is already installed. + False if the PPI has yet to be installed. + +--*/ +{ + VOID *PeiInstance; + EFI_STATUS Status; + EFI_GUID PpiGuid; + + // + // If there is no GUID to evaluate, just return current result on stack. + // + if (Stack->Operator == NULL) { + return Stack->Result; + } + + // + // Copy the Guid into a locale variable so that there are no + // possibilities of alignment faults for cross-compilation + // environments such as Intel?Itanium(TM). + // + CopyMem(&PpiGuid, Stack->Operator, sizeof(EFI_GUID)); + + // + // Check if the PPI is installed. + // + Status = PeiCoreLocatePpi( + &PpiGuid, // GUID + 0, // INSTANCE + NULL, // EFI_PEI_PPI_DESCRIPTOR + &PeiInstance // PPI + ); + + if (EFI_ERROR(Status)) { + return FALSE; + } + + return TRUE; +} + + +EFI_STATUS +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression, + OUT BOOLEAN *Runnable + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + +Arguments: + + PeiServices - Calling context. + + DependencyExpression - Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + Runnable - is True if the driver can be scheduled and False if the driver + cannot be scheduled. This is the value that the schedulers + should use for deciding the state of the driver. + +Returns: + + Status = EFI_SUCCESS if it is a well-formed Grammar + EFI_INVALID_PARAMETER if the dependency expression overflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression underflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression is not a + well-formed Grammar. +--*/ +{ + EFI_STATUS Status; + DEPENDENCY_EXPRESSION_OPERAND *Iterator; + EVAL_STACK_ENTRY *StackPtr; + EVAL_STACK_ENTRY EvalStack[MAX_GRAMMAR_SIZE]; + + Status = EFI_SUCCESS; + Iterator = DependencyExpression; + *Runnable = FALSE; + + StackPtr = &EvalStack[0]; + + while (TRUE) { + + switch (*(Iterator++)) { + + // + // For performance reason we put the frequently used items in front of + // the rarely used items + // + + case (EFI_DEP_PUSH): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + return EFI_INVALID_PARAMETER; + } + + // + // Push the pointer to the PUSH opcode operator (pointer to PPI GUID) + // We will evaluate if the PPI is insalled on the POP operation. + // + StackPtr->Operator = (VOID *) Iterator; + Iterator = Iterator + sizeof (EFI_GUID); + StackPtr++; + break; + + case (EFI_DEP_AND): + case (EFI_DEP_OR): + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the two POPs for the AND operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did two POPs. + // + if (StackPtr < &EvalStack[2]) { + return EFI_INVALID_PARAMETER; + } + + // + // Evaluate the first POPed operator only. If the operand is + // EFI_DEP_AND and the POPed operator evaluates to FALSE, or the + // operand is EFI_DEP_OR and the POPed operator evaluates to TRUE, + // we don't need to check the second operator, and the result will be + // evaluation of the POPed operator. Otherwise, don't POP the second + // operator since it will now evaluate to the final result on the + // next operand that causes a POP. + // + StackPtr--; + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_AND) { + if (!(IsPpiInstalled (PeiServices, StackPtr))) { + (StackPtr-1)->Result = FALSE; + (StackPtr-1)->Operator = NULL; + } + } else { + if (IsPpiInstalled (PeiServices, StackPtr)) { + (StackPtr-1)->Result = TRUE; + (StackPtr-1)->Operator = NULL; + } + } + break; + + case (EFI_DEP_END): + StackPtr--; + // + // Check to make sure EvalStack is balanced. If not, then there is + // an error in the dependency grammar, so return EFI_INVALID_PARAMETER. + // + if (StackPtr != &EvalStack[0]) { + return EFI_INVALID_PARAMETER; + } + *Runnable = IsPpiInstalled (PeiServices, StackPtr); + return EFI_SUCCESS; + break; + + case (EFI_DEP_NOT): + // + // Check to make sure the dependency grammar doesn't underflow the + // EvalStack on the POP for the NOT operation. Don't need to + // check for the overflow on PUSHing the result since we already + // did a POP. + // + if (StackPtr < &EvalStack[1]) { + return EFI_INVALID_PARAMETER; + } + (StackPtr-1)->Result = (BOOLEAN) !IsPpiInstalled (PeiServices, (StackPtr-1)); + (StackPtr-1)->Operator = NULL; + break; + + case (EFI_DEP_TRUE): + case (EFI_DEP_FALSE): + // + // Check to make sure the dependency grammar doesn't overflow the + // EvalStack on the push + // + if (StackPtr > &EvalStack[MAX_GRAMMAR_SIZE-1]) { + return EFI_INVALID_PARAMETER; + } + // + // Iterator has increased by 1 after we retrieve the operand, so here we + // should get the value pointed by (Iterator - 1), in order to obtain the + // same operand. + // + if (*(Iterator - 1) == EFI_DEP_TRUE) { + StackPtr->Result = TRUE; + } else { + StackPtr->Result = FALSE; + } + StackPtr->Operator = NULL; + StackPtr++; + break; + + default: + // + // The grammar should never arrive here + // + return EFI_INVALID_PARAMETER; + break; + } + } +} diff --git a/EdkModulePkg/Core/Pei/Dependency/dependency.h b/EdkModulePkg/Core/Pei/Dependency/dependency.h new file mode 100644 index 0000000000..a1a54ed0cd --- /dev/null +++ b/EdkModulePkg/Core/Pei/Dependency/dependency.h @@ -0,0 +1,38 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + dependency.h + +Abstract: + + This module contains data specific to dependency expressions + and local function prototypes. + +--*/ + +#ifndef _PEI_DEPENDENCY_H_ +#define _PEI_DEPENDENCY_H_ + +#define MAX_GRAMMAR_SIZE 256 + +// +// type definitions +// +typedef UINT8 DEPENDENCY_EXPRESSION_OPERAND; + +typedef struct { + BOOLEAN Result; + VOID *Operator; +} EVAL_STACK_ENTRY; + +#endif diff --git a/EdkModulePkg/Core/Pei/Dispatcher/Dispatcher.c b/EdkModulePkg/Core/Pei/Dispatcher/Dispatcher.c new file mode 100644 index 0000000000..b4e09e3fca --- /dev/null +++ b/EdkModulePkg/Core/Pei/Dispatcher/Dispatcher.c @@ -0,0 +1,535 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Dispatcher.c + +Abstract: + + EFI PEI Core dispatch services + +Revision History + +--*/ + +#include + +VOID * +TransferOldDataToNewDataRange ( + IN PEI_CORE_INSTANCE *PrivateData + ); + +EFI_GUID gEfiPeiCorePrivateGuid = EFI_PEI_CORE_PRIVATE_GUID; + + +EFI_STATUS +PeiDispatcher ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_DISPATCH_DATA *DispatchData + ) + +/*++ + +Routine Description: + + Conduct PEIM dispatch. + +Arguments: + + PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR + PrivateData - Pointer to the private data passed in from caller + DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data. + +Returns: + + EFI_SUCCESS - Successfully dispatched PEIM. + EFI_NOT_FOUND - The dispatch failed. + +--*/ +{ + EFI_STATUS Status; + PEI_CORE_TEMP_POINTERS TempPtr; + UINTN PrivateDataInMem; + BOOLEAN NextFvFound; + EFI_FIRMWARE_VOLUME_HEADER *NextFvAddress; + EFI_FIRMWARE_VOLUME_HEADER *DefaultFvAddress; + // + // Debug data for uninstalled Peim list + // + EFI_GUID DebugFoundPeimList[32]; + REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA ExtendedData; + + // + // save the Current FV Address so that we will not process it again if FindFv returns it later + // + DefaultFvAddress = DispatchData->BootFvAddress; + + // + // This is the main dispatch loop. It will search known FVs for PEIMs and + // attempt to dispatch them. If any PEIM gets dispatched through a single + // pass of the dispatcher, it will start over from the Bfv again to see + // if any new PEIMs dependencies got satisfied. With a well ordered + // FV where PEIMs are found in the order their dependencies are also + // satisfied, this dipatcher should run only once. + // + for (;;) { + // + // This is the PEIM search loop. It will scan through all PEIMs it can find + // looking for PEIMs to dispatch, and will dipatch them if they have not + // already been dispatched and all of their dependencies are met. + // If no more PEIMs can be found in this pass through all known FVs, + // then it will break out of this loop. + // + for (;;) { + + Status = FindNextPeim ( + &PrivateData->PS, + DispatchData->CurrentFvAddress, + &DispatchData->CurrentPeimAddress + ); + + // + // If we found a PEIM, check if it is dispatched. If so, go to the + // next PEIM. If not, dispatch it if its dependencies are satisfied. + // If its dependencies are not satisfied, go to the next PEIM. + // + if (Status == EFI_SUCCESS) { + + DEBUG_CODE ( + + // + // Fill list of found Peims for later list of those not installed + // + CopyMem ( + &DebugFoundPeimList[DispatchData->CurrentPeim], + &DispatchData->CurrentPeimAddress->Name, + sizeof (EFI_GUID) + ); + + ); + + if (!Dispatched ( + DispatchData->CurrentPeim, + DispatchData->DispatchedPeimBitMap + )) { + if (DepexSatisfied (&PrivateData->PS, DispatchData->CurrentPeimAddress)) { + Status = PeiLoadImage ( + &PrivateData->PS, + DispatchData->CurrentPeimAddress, + &TempPtr.Raw + ); + if (Status == EFI_SUCCESS) { + + // + // The PEIM has its dependencies satisfied, and its entry point + // has been found, so invoke it. + // + PERF_START ( + (VOID *) (UINTN) (DispatchData->CurrentPeimAddress), + "PEIM", + NULL, + 0 + ); + + // + // BUGBUG: Used to be EFI_PEI_REPORT_STATUS_CODE_CODE + // + ExtendedData.Handle = (EFI_HANDLE)DispatchData->CurrentPeimAddress; + + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_BEGIN, + (VOID *)(&ExtendedData), + sizeof (ExtendedData) + ); + + // + // Is this a authentic image + // + Status = VerifyPeim ( + &PrivateData->PS, + DispatchData->CurrentPeimAddress + ); + + if (Status != EFI_SECURITY_VIOLATION) { + + Status = TempPtr.PeimEntry ( + DispatchData->CurrentPeimAddress, + &PrivateData->PS + ); + } + + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT_END, + (VOID *)(&ExtendedData), + sizeof (ExtendedData) + ); + + PERF_END ((VOID *) (UINTN) (DispatchData->CurrentPeimAddress), "PEIM", NULL, 0); + + // + // Mark the PEIM as dispatched so we don't attempt to run it again + // + SetDispatched ( + &PrivateData->PS, + DispatchData->CurrentPeim, + &DispatchData->DispatchedPeimBitMap + ); + + // + // Process the Notify list and dispatch any notifies for + // newly installed PPIs. + // + ProcessNotifyList (&PrivateData->PS); + + // + // If real system memory was discovered and installed by this + // PEIM, switch the stacks to the new memory. Since we are + // at dispatch level, only the Core's private data is preserved, + // nobody else should have any data on the stack. + // + if (PrivateData->SwitchStackSignal) { + TempPtr.PeiCore = (PEI_CORE_ENTRY_POINT)PeiCore; + PrivateDataInMem = (UINTN) TransferOldDataToNewDataRange (PrivateData); + ASSERT (PrivateDataInMem != 0); + // + //Subtract 0x10 from the 4th parameter indicating the new stack base, + //in order to provide buffer protection against possible illegal stack + //access that might corrupt the stack. + // + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT)(UINTN)TempPtr.Raw, + PeiStartupDescriptor, + (VOID*)PrivateDataInMem, + (VOID*)((UINTN)PrivateData->StackBase + (UINTN)PrivateData->StackSize) + ); + } + } + } + } + DispatchData->CurrentPeim++; + continue; + + } else { + + // + // If we could not find another PEIM in the current FV, go try + // the FindFv PPI to look in other FVs for more PEIMs. If we can + // not locate the FindFv PPI, or if the FindFv PPI can not find + // anymore FVs, then exit the PEIM search loop. + // + if (DispatchData->FindFv == NULL) { + Status = PeiCoreLocatePpi ( + &gEfiFindFvPpiGuid, + 0, + NULL, + (VOID **)&DispatchData->FindFv + ); + if (Status != EFI_SUCCESS) { + break; + } + } + NextFvFound = FALSE; + while (!NextFvFound) { + Status = DispatchData->FindFv->FindFv ( + DispatchData->FindFv, + &PrivateData->PS, + &DispatchData->CurrentFv, + &NextFvAddress + ); + // + // if there is no next fv, get out of this loop of finding FVs + // + if (Status != EFI_SUCCESS) { + break; + } + // + // don't process the default Fv again. (we don't know the order in which the hobs were created) + // + if ((NextFvAddress != DefaultFvAddress) && + (NextFvAddress != DispatchData->CurrentFvAddress)) { + + // + // VerifyFv() is currently returns SUCCESS all the time, add code to it to + // actually verify the given FV + // + Status = VerifyFv (NextFvAddress); + if (Status == EFI_SUCCESS) { + NextFvFound = TRUE; + DispatchData->CurrentFvAddress = NextFvAddress; + DispatchData->CurrentPeimAddress = NULL; + // + // current PRIM number (CurrentPeim) must continue as is, don't reset it here + // + } + } + } + // + // if there is no next fv, get out of this loop of dispatching PEIMs + // + if (!NextFvFound) { + break; + } + // + // continue in the inner for(;;) loop with a new FV; + // + } + } + + // + // If all the PEIMs that we have found have been dispatched, then + // there is nothing left to dispatch and we don't need to go search + // through all PEIMs again. + // + if ((~(DispatchData->DispatchedPeimBitMap) & + ((1 << DispatchData->CurrentPeim)-1)) == 0) { + break; + } + + // + // Check if no more PEIMs that depex was satisfied + // + if (DispatchData->DispatchedPeimBitMap == DispatchData->PreviousPeimBitMap) { + break; + } + + // + // Case when Depex is not satisfied and has to traverse the list again + // + DispatchData->CurrentPeim = 0; + DispatchData->CurrentPeimAddress = 0; + DispatchData->PreviousPeimBitMap = DispatchData->DispatchedPeimBitMap; + + // + // don't go back to the loop without making sure that the CurrentFvAddress is the + // same as the 1st (or default) FV we started with. otherwise we will interpret the bimap wrongly and + // mess it up, always start processing the PEIMs from the default FV just like in the first time around. + // + DispatchData->CurrentFv = 0; + DispatchData->CurrentFvAddress = DefaultFvAddress; + } + + DEBUG_CODE ( + // + // Debug data for uninstalled Peim list + // + UINT32 DebugNotDispatchedBitmap; + UINT8 DebugFoundPeimPoint; + + DebugFoundPeimPoint = 0; + // + // Get bitmap of Peims that were not dispatched, + // + + DebugNotDispatchedBitmap = ((DispatchData->DispatchedPeimBitMap) ^ ((1 << DispatchData->CurrentPeim)-1)); + // + // Scan bitmap of Peims not installed and print GUIDS + // + while (DebugNotDispatchedBitmap != 0) { + if ((DebugNotDispatchedBitmap & 1) != 0) { + DEBUG ((EFI_D_INFO, "WARNING -> InstallPpi: Not Installed: %g\n", + &DebugFoundPeimList[DebugFoundPeimPoint] + )); + } + DebugFoundPeimPoint++; + DebugNotDispatchedBitmap >>= 1; + } + + ); + + return EFI_NOT_FOUND; +} + +VOID +InitializeDispatcherData ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Initialize the Dispatcher's data members + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to old core data (before switching stack). + NULL if being run in non-permament memory mode. + PeiStartupDescriptor - Information and services provided by SEC phase. + +Returns: + + None. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + if (OldCoreData == NULL) { + PrivateData->DispatchData.CurrentFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume; + PrivateData->DispatchData.BootFvAddress = (EFI_FIRMWARE_VOLUME_HEADER *) PeiStartupDescriptor->BootFirmwareVolume; + } else { + + // + // Current peim has been dispatched, but not count + // + PrivateData->DispatchData.CurrentPeim = (UINT8)(OldCoreData->DispatchData.CurrentPeim + 1); + } + + return; +} + + +BOOLEAN +Dispatched ( + IN UINT8 CurrentPeim, + IN UINT32 DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine checks to see if a particular PEIM has been dispatched during + the PEI core dispatch. + +Arguments: + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + TRUE - PEIM already dispatched + FALSE - Otherwise + +--*/ +{ + return (BOOLEAN)((DispatchedPeimBitMap & (1 << CurrentPeim)) != 0); +} + +VOID +SetDispatched ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 CurrentPeim, + OUT UINT32 *DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine sets a PEIM as having been dispatched once its entry + point has been invoked. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + None + +--*/ +{ + // + // Check if the total number of PEIMs exceed the bitmap. + // CurrentPeim is 0-based + // + DEBUG_CODE ( + if (CurrentPeim > (sizeof (*DispatchedPeimBitMap) * 8 - 1)) { + ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES); + } + ); + + *DispatchedPeimBitMap |= (1 << CurrentPeim); + return; +} + +BOOLEAN +DepexSatisfied ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *CurrentPeimAddress + ) +/*++ + +Routine Description: + + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + +Arguments: + PeiServices - The PEI Service Table + CurrentPeimAddress - Address of the PEIM Firmware File under investigation + +Returns: + TRUE - Can be dispatched + FALSE - Cannot be dispatched + +--*/ +{ + EFI_STATUS Status; + INT8 *DepexData; + BOOLEAN Runnable; + + Status = PeiCoreFfsFindSectionData ( + EFI_SECTION_PEI_DEPEX, + CurrentPeimAddress, + (VOID **)&DepexData + ); + // + // If there is no DEPEX, assume the module can be executed + // + if (EFI_ERROR (Status)) { + return TRUE; + } + + // + // Evaluate a given DEPEX + // + Status = PeimDispatchReadiness ( + PeiServices, + DepexData, + &Runnable + ); + + return Runnable; +} + + +VOID * +TransferOldDataToNewDataRange ( + IN PEI_CORE_INSTANCE *PrivateData + ) +/*++ + +Routine Description: + + This routine transfers the contents of the pre-permanent memory + PEI Core private data to a post-permanent memory data location. + +Arguments: + + PrivateData - Pointer to the current PEI Core private data pre-permanent memory + +Returns: + + Pointer to the PrivateData once the private data has been transferred to permanent memory + +--*/ +{ + return BuildGuidDataHob (&gEfiPeiCorePrivateGuid, PrivateData, sizeof (PEI_CORE_INSTANCE)); +} + diff --git a/EdkModulePkg/Core/Pei/FwVol/FwVol.c b/EdkModulePkg/Core/Pei/FwVol/FwVol.c new file mode 100644 index 0000000000..d034513bb0 --- /dev/null +++ b/EdkModulePkg/Core/Pei/FwVol/FwVol.c @@ -0,0 +1,474 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FwVol.c + +Abstract: + + Pei Core Firmware File System service routines. + +--*/ + +#include + +#define GETOCCUPIEDSIZE(ActualSize, Alignment) \ + (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)) + +STATIC +EFI_FFS_FILE_STATE +GetFileState( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + Returns the highest bit set of the State field + +Arguments: + + ErasePolarity - Erase Polarity as defined by EFI_FVB_ERASE_POLARITY + in the Attributes field. + FfsHeader - Pointer to FFS File Header. + +Returns: + Returns the highest bit in the State field + +--*/ +{ + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_STATE HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity != 0) { + FileState = (EFI_FFS_FILE_STATE)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} + +STATIC +UINT8 +CalculateHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FileHeader + ) +/*++ + +Routine Description: + + Calculates the checksum of the header of a file. + +Arguments: + + FileHeader - Pointer to FFS File Header. + +Returns: + Checksum of the header. + + The header is zero byte checksum. + - Zero means the header is good. + - Non-zero means the header is bad. + + +Bugbug: For PEI performance reason, we comments this code at this time. +--*/ +{ + UINT8 *ptr; + UINTN Index; + UINT8 Sum; + + Sum = 0; + ptr = (UINT8 *)FileHeader; + + for (Index = 0; Index < sizeof(EFI_FFS_FILE_HEADER) - 3; Index += 4) { + Sum = (UINT8)(Sum + ptr[Index]); + Sum = (UINT8)(Sum + ptr[Index+1]); + Sum = (UINT8)(Sum + ptr[Index+2]); + Sum = (UINT8)(Sum + ptr[Index+3]); + } + + for (; Index < sizeof(EFI_FFS_FILE_HEADER); Index++) { + Sum = (UINT8)(Sum + ptr[Index]); + } + + // + // State field (since this indicates the different state of file). + // + Sum = (UINT8)(Sum - FileHeader->State); + // + // Checksum field of the file is not part of the header checksum. + // + Sum = (UINT8)(Sum - FileHeader->IntegrityCheck.Checksum.File); + + return Sum; +} + +STATIC +EFI_STATUS +PeiFfsFindNextFileEx ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader, + IN BOOLEAN Flag + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + Flag - Indicator for if this is for PEI Dispath search +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileLength; + UINT32 FileOccupiedSize; + UINT32 FileOffset; + UINT64 FvLength; + UINT8 ErasePolarity; + UINT8 FileState; + + + FvLength = FwVolHeader->FvLength; + if (FwVolHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + + // + // If FileHeader is not specified (NULL) start with the first file in the + // firmware volume. Otherwise, start from the FileHeader. + // + if (*FileHeader == NULL) { + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FwVolHeader + FwVolHeader->HeaderLength); + } else { + // + // Length is 24 bits wide so mask upper 8 bits + // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + FileLength = *(UINT32 *)(*FileHeader)->Size & 0x00FFFFFF; + FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)*FileHeader + FileOccupiedSize); + } + + FileOffset = (UINT32) ((UINT8 *)FfsFileHeader - (UINT8 *)FwVolHeader); + ASSERT (FileOffset <= 0xFFFFFFFF); + + while (FileOffset < (FvLength - sizeof(EFI_FFS_FILE_HEADER))) { + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, FfsFileHeader); + + switch (FileState) { + + case EFI_FILE_HEADER_INVALID: + FileOffset += sizeof(EFI_FFS_FILE_HEADER); + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + sizeof(EFI_FFS_FILE_HEADER)); + break; + + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + if (CalculateHeaderChecksum (FfsFileHeader) == 0) { + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + if (Flag) { + if ((FfsFileHeader->Type == EFI_FV_FILETYPE_PEIM) || + (FfsFileHeader->Type == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER)) { + + *FileHeader = FfsFileHeader; + + + return EFI_SUCCESS; + } + } else { + if ((SearchType == FfsFileHeader->Type) || + (SearchType == EFI_FV_FILETYPE_ALL)) { + + *FileHeader = FfsFileHeader; + + + return EFI_SUCCESS; + } + } + + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + } else { + ASSERT (FALSE); + return EFI_NOT_FOUND; + } + break; + + case EFI_FILE_DELETED: + FileLength = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GETOCCUPIEDSIZE(FileLength, 8); + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *)((UINT8 *)FfsFileHeader + FileOccupiedSize); + break; + + default: + return EFI_NOT_FOUND; + + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only sections of this type. + FfsFileHeader - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + - NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINT32 SectionLength; + UINT32 ParsedLength; + + + // + // Size is 24 bits wide so mask upper 8 bits. + // Does not include FfsFileHeader header size + // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + Section = (EFI_COMMON_SECTION_HEADER *)(FfsFileHeader + 1); + FileSize = *(UINT32 *)(FfsFileHeader->Size) & 0x00FFFFFF; + FileSize -= sizeof(EFI_FFS_FILE_HEADER); + + *SectionData = NULL; + ParsedLength = 0; + while (ParsedLength < FileSize) { + if (Section->Type == SectionType) { + *SectionData = (VOID *)(Section + 1); + + + return EFI_SUCCESS; + } + // + // Size is 24 bits wide so mask upper 8 bits. + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = *(UINT32 *)Section->Size & 0x00FFFFFF; + SectionLength = GETOCCUPIEDSIZE (SectionLength, 4); + ASSERT (SectionLength != 0); + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *)((UINT8 *)Section + SectionLength); + } + + return EFI_NOT_FOUND; + +} + + +EFI_STATUS +FindNextPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **PeimFileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + PeimFileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + return PeiFfsFindNextFileEx ( + 0, + FwVolHeader, + PeimFileHeader, + TRUE + ); +} + +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + return PeiFfsFindNextFileEx ( + SearchType, + FwVolHeader, + FileHeader, + FALSE + ); +} + +EFI_STATUS +EFIAPI +PeiFvFindNextVolume ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +/*++ + +Routine Description: + + Return the BFV location + + BugBug -- Move this to the location of this code to where the + other FV and FFS support code lives. + Also, update to use FindFV for instances #'s >= 1. + +Arguments: + + PeiServices - The PEI core services table. + Instance - Instance of FV to find + FwVolHeader - Pointer to contain the data to return + +Returns: + Pointer to the Firmware Volume instance requested + + EFI_INVALID_PARAMETER - FwVolHeader is NULL + + EFI_SUCCESS - Firmware volume instance successfully found. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_STATUS Status; + EFI_PEI_FIND_FV_PPI *FindFvPpi; + UINT8 LocalInstance; + + + LocalInstance = (UINT8) Instance; + + Status = EFI_SUCCESS; + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + if (FwVolHeader == NULL) { + + return EFI_INVALID_PARAMETER; + } + + if (Instance == 0) { + *FwVolHeader = PrivateData->DispatchData.BootFvAddress; + + + return Status; + } else { + // + // Locate all instances of FindFV + // Alternately, could use FV HOBs, but the PPI is cleaner + // + Status = PeiCoreLocatePpi ( + &gEfiFindFvPpiGuid, + 0, + NULL, + (VOID **)&FindFvPpi + ); + + if (Status != EFI_SUCCESS) { + Status = EFI_NOT_FOUND; + } else { + Status = FindFvPpi->FindFv ( + FindFvPpi, + PeiServices, + &LocalInstance, + FwVolHeader + ); + + } + } + return Status; +} diff --git a/EdkModulePkg/Core/Pei/Hob/Hob.c b/EdkModulePkg/Core/Pei/Hob/Hob.c new file mode 100644 index 0000000000..6117827522 --- /dev/null +++ b/EdkModulePkg/Core/Pei/Hob/Hob.c @@ -0,0 +1,189 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Hob.c + +Abstract: + + EFI PEI Core HOB services + +--*/ + +#include + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +/*++ + +Routine Description: + + Gets the pointer to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + HobList - Pointer to the HOB List. + +Returns: + + EFI_SUCCESS - Get the pointer of HOB List + EFI_NOT_AVAILABLE_YET - the HOB List is not yet published + EFI_INVALID_PARAMETER - HobList is NULL (in debug mode) + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + + // + // Only check this parameter in debug mode + // + + DEBUG_CODE ( + if (HobList == NULL) { + return EFI_INVALID_PARAMETER; + } + ); + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + *HobList = PrivateData->HobList.Raw; + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Add a new HOB to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of the new HOB. + Length - Length of the new HOB to allocate. + Hob - Pointer to the new HOB. + +Returns: + + Status - EFI_SUCCESS + - EFI_INVALID_PARAMETER if Hob is NULL + - EFI_NOT_AVAILABLE_YET if HobList is still not available. + - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_HANDOFF_INFO_TABLE *HandOffHob; + EFI_HOB_GENERIC_HEADER *HobEnd; + EFI_PHYSICAL_ADDRESS FreeMemory; + + + Status = PeiGetHobList (PeiServices, Hob); + if (EFI_ERROR(Status)) { + return Status; + } + + HandOffHob = *Hob; + + Length = (UINT16)((Length + 0x7) & (~0x7)); + + FreeMemory = HandOffHob->EfiFreeMemoryTop - + HandOffHob->EfiFreeMemoryBottom; + + if (FreeMemory < Length) { + return EFI_OUT_OF_RESOURCES; + } + + *Hob = (VOID*) (UINTN) HandOffHob->EfiEndOfHobList; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobType = Type; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->HobLength = Length; + ((EFI_HOB_GENERIC_HEADER*) *Hob)->Reserved = 0; + + HobEnd = (EFI_HOB_GENERIC_HEADER*) ((UINTN) *Hob + Length); + HandOffHob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + HobEnd++; + HandOffHob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Builds a Handoff Information Table HOB + +Arguments: + + BootMode - Current Bootmode + MemoryBegin - Start Memory Address. + MemoryLength - Length of Memory. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_HOB_HANDOFF_INFO_TABLE *Hob; + EFI_HOB_GENERIC_HEADER *HobEnd; + + Hob = (VOID *)(UINTN)MemoryBegin; + HobEnd = (EFI_HOB_GENERIC_HEADER*) (Hob+1); + Hob->Header.HobType = EFI_HOB_TYPE_HANDOFF; + Hob->Header.HobLength = sizeof(EFI_HOB_HANDOFF_INFO_TABLE); + Hob->Header.Reserved = 0; + + HobEnd->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST; + HobEnd->HobLength = sizeof(EFI_HOB_GENERIC_HEADER); + HobEnd->Reserved = 0; + + Hob->Version = EFI_HOB_HANDOFF_TABLE_VERSION; + Hob->BootMode = BootMode; + + Hob->EfiMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiMemoryBottom = MemoryBegin; + Hob->EfiFreeMemoryTop = MemoryBegin + MemoryLength; + Hob->EfiFreeMemoryBottom = (EFI_PHYSICAL_ADDRESS) (UINTN) (HobEnd+1); + Hob->EfiEndOfHobList = (EFI_PHYSICAL_ADDRESS) (UINTN) HobEnd; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/Pei/Image/Image.c b/EdkModulePkg/Core/Pei/Image/Image.c new file mode 100644 index 0000000000..74286cff31 --- /dev/null +++ b/EdkModulePkg/Core/Pei/Image/Image.c @@ -0,0 +1,237 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Image.c + +Abstract: + + Pei Core Load Image Support + +--*/ + +#include + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *PeimFileHeader, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Routine for loading file image. + +Arguments: + + PeiServices - The PEI core services table. + PeimFileHeader - Pointer to the FFS file header of the image. + EntryPoint - Pointer to entry point of specified image file for output. + +Returns: + + Status - EFI_SUCCESS - Image is successfully loaded. + EFI_NOT_FOUND - Fail to locate necessary PPI + Others - Fail to load file. + +--*/ +{ + EFI_STATUS Status; + VOID *Pe32Data; + EFI_PEI_FV_FILE_LOADER_PPI *FvLoadFilePpi; +//#ifdef EFI_NT_EMULATOR +// EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; +// NT_PEI_LOAD_FILE_PPI *PeiNtService; +//#endif + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS ImageEntryPoint; + EFI_TE_IMAGE_HEADER *TEImageHeader; + + *EntryPoint = NULL; + TEImageHeader = NULL; + + // + // Try to find a PE32 section. + // + Status = PeiCoreFfsFindSectionData ( + EFI_SECTION_PE32, + PeimFileHeader, + &Pe32Data + ); + // + // If we didn't find a PE32 section, try to find a TE section. + // + if (EFI_ERROR (Status)) { + Status = PeiCoreFfsFindSectionData ( + EFI_SECTION_TE, + PeimFileHeader, + (VOID **) &TEImageHeader + ); + if (EFI_ERROR (Status) || TEImageHeader == NULL) { + // + // There was not a PE32 or a TE section, so assume that it's a Compressed section + // and use the LoadFile + // + Status = PeiCoreLocatePpi ( + &gEfiPeiFvFileLoaderPpiGuid, + 0, + NULL, + (VOID **)&FvLoadFilePpi + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + Status = FvLoadFilePpi->FvLoadFile ( + FvLoadFilePpi, + PeimFileHeader, + &ImageAddress, + &ImageSize, + &ImageEntryPoint + ); + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + // + // Retrieve the entry point from the PE/COFF image header + // + Status = PeCoffLoaderGetEntryPoint ((VOID *)(UINTN)ImageAddress, EntryPoint); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } else { + // + // Retrieve the entry point from the TE image header + // + ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) TEImageHeader; + *EntryPoint = (VOID *)((UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) + + TEImageHeader->AddressOfEntryPoint - TEImageHeader->StrippedSize); + } + } else { + // + // Retrieve the entry point from the PE/COFF image header + // + ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) Pe32Data; + Status = PeCoffLoaderGetEntryPoint (Pe32Data, EntryPoint); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + } + + // + // Print debug message: Loading PEIM at 0x12345678 EntryPoint=0x12345688 Driver.efi + // + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Loading PEIM at 0x%08x EntryPoint=0x%08x ", Pe32Data, *EntryPoint)); + DEBUG_CODE ( + EFI_IMAGE_DATA_DIRECTORY * DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY * DebugEntry; + UINTN DirCount; + UINTN Index; + UINTN Index1; + BOOLEAN FileNameFound; + CHAR8 *AsciiString; + CHAR8 AsciiBuffer[512]; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_NT_HEADERS *PeHeader; + + DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + PeHeader = (EFI_IMAGE_NT_HEADERS *) Pe32Data; + } + + // + // Find the codeview info in the image and display the file name + // being loaded. + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + DebugEntry = NULL; + DirectoryEntry = NULL; + TEImageAdjust = 0; + if (TEImageHeader == NULL) { + if (PeHeader->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHeader->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) ImageAddress + DirectoryEntry->VirtualAddress); + } + } else { + if (TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize; + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) TEImageHeader + + TEImageHeader->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress + + TEImageAdjust); + } + } + + if (DebugEntry != NULL && DirectoryEntry != NULL) { + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) { + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + if (DebugEntry->SizeOfData > 0) { + CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageAddress + (UINTN)TEImageAdjust); + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + AsciiString = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + AsciiString = NULL; + break; + } + if (AsciiString != NULL) { + FileNameFound = FALSE; + for (Index = 0, Index1 = 0; AsciiString[Index] != 0; Index++) { + if (AsciiString[Index] == '\\') { + Index1 = Index; + FileNameFound = TRUE; + } + } + + if (FileNameFound) { + for (Index = Index1 + 1; AsciiString[Index] != '.'; Index++) { + AsciiBuffer[Index - (Index1 + 1)] = AsciiString[Index]; + } + AsciiBuffer[Index - (Index1 + 1)] = 0; + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "%a.efi", AsciiBuffer)); + break; + } + } + } + } + } + } + ); + + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "\n")); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.i b/EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.i new file mode 100644 index 0000000000..c8a209debc --- /dev/null +++ b/EdkModulePkg/Core/Pei/Ipf/IpfCpuCore.i @@ -0,0 +1,93 @@ +//++ +// Copyright (c) 2006, 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. +// +// Module Name: +// +// IpfCpuCore.i +// +// Abstract: +// IPF CPU definitions +// +//-- + +#ifndef _IPF_CPU_CORE_ +#define _IPF_CPU_CORE_ + +#define PEI_BSP_STORE_SIZE 0x4000 +#define ResetFn 0x00 +#define MachineCheckFn 0x01 +#define InitFn 0x02 +#define RecoveryFn 0x03 +#define GuardBand 0x10 + +// +// Define hardware RSE Configuration Register +// + +// +// RS Configuration (RSC) bit field positions +// +#define RSC_MODE 0 +#define RSC_PL 2 +#define RSC_BE 4 +// +// RSC bits 5-15 reserved +// +#define RSC_MBZ0 5 +#define RSC_MBZ0_V 0x3ff +#define RSC_LOADRS 16 +#define RSC_LOADRS_LEN 14 +// +// RSC bits 30-63 reserved +// +#define RSC_MBZ1 30 +#define RSC_MBZ1_V 0x3ffffffffULL + +// +// RSC modes +// + +// +// Lazy +// +#define RSC_MODE_LY (0x0) +// +// Store intensive +// +#define RSC_MODE_SI (0x1) +// +// Load intensive +// +#define RSC_MODE_LI (0x2) +// +// Eager +// +#define RSC_MODE_EA (0x3) + +// +// RSC Endian bit values +// +#define RSC_BE_LITTLE 0 +#define RSC_BE_BIG 1 + +// +// RSC while in kernel: enabled, little endian, pl = 0, eager mode +// +#define RSC_KERNEL ((RSC_MODE_EA< +#include "IpfCpuCore.i" + +extern +SAL_RETURN_REGS +GetHandOffStatus ( + VOID + ); + +VOID +SwitchToCacheMode ( + IN PEI_CORE_INSTANCE *CoreData + ) +/*++ + +Routine Description: + + Switch the PHIT pointers to cache mode after InstallPeiMemory in CAR. + +Arguments: + + CoreData - The PEI core Private Data + +Returns: + +--*/ +{ + EFI_HOB_HANDOFF_INFO_TABLE *Phit; + + if (CoreData == NULL) { + // + // the first call with CoreData as NULL. + // + return; + } + + if ((GetHandOffStatus().r10 & 0xFF) == RecoveryFn) { + CoreData->StackBase = CoreData->StackBase & CACHE_MODE_ADDRESS_MASK; + CoreData->HobList.Raw = (UINT8 *)((UINTN)CoreData->HobList.Raw & CACHE_MODE_ADDRESS_MASK); + + // + // Change the PHIT pointer value to cache mode + // + Phit = CoreData->HobList.HandoffInformationTable; + + Phit->EfiMemoryTop = Phit->EfiMemoryTop & CACHE_MODE_ADDRESS_MASK; + Phit->EfiFreeMemoryTop = Phit->EfiFreeMemoryTop & CACHE_MODE_ADDRESS_MASK; + Phit->EfiMemoryBottom = Phit->EfiMemoryBottom & CACHE_MODE_ADDRESS_MASK; + Phit->EfiFreeMemoryBottom = Phit->EfiFreeMemoryBottom & CACHE_MODE_ADDRESS_MASK; + Phit->EfiEndOfHobList = Phit->EfiEndOfHobList & CACHE_MODE_ADDRESS_MASK; + } + + return; +} \ No newline at end of file diff --git a/EdkModulePkg/Core/Pei/Memory/MemoryServices.c b/EdkModulePkg/Core/Pei/Memory/MemoryServices.c new file mode 100644 index 0000000000..48b2b3818c --- /dev/null +++ b/EdkModulePkg/Core/Pei/Memory/MemoryServices.c @@ -0,0 +1,314 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MemoryServices.c + +Abstract: + + EFI PEI Core memory services + +--*/ + +#include + +VOID +InitializeMemoryServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the memory services. + +Arguments: + + PeiServices - The PEI core services table. + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + + None + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + UINT64 SizeOfCarHeap; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + PrivateData->SwitchStackSignal = FALSE; + + if (OldCoreData == NULL) { + + PrivateData->PeiMemoryInstalled = FALSE; + + PrivateData->BottomOfCarHeap = (VOID *) (((UINTN)(VOID *)(&PrivateData)) + & (~((PeiStartupDescriptor->SizeOfCacheAsRam) - 1))); + PrivateData->TopOfCarHeap = (VOID *)((UINTN)(PrivateData->BottomOfCarHeap) + PeiStartupDescriptor->SizeOfCacheAsRam); + // + // SizeOfCarHeap is 1/2 (arbitrary) of CacheAsRam Size. + // + SizeOfCarHeap = (UINT64) PeiStartupDescriptor->SizeOfCacheAsRam; + SizeOfCarHeap = RShiftU64 (SizeOfCarHeap, 1); + + DEBUG_CODE ( + PrivateData->SizeOfCacheAsRam = PeiStartupDescriptor->SizeOfCacheAsRam; + PrivateData->MaxTopOfCarHeap = (VOID *) ((UINTN) PrivateData->BottomOfCarHeap + (UINTN) SizeOfCarHeap); + ); + + PrivateData->HobList.Raw = PrivateData->BottomOfCarHeap; + + PeiCoreBuildHobHandoffInfoTable ( + BOOT_WITH_FULL_CONFIGURATION, + (EFI_PHYSICAL_ADDRESS) (UINTN) PrivateData->BottomOfCarHeap, + (UINTN) SizeOfCarHeap + ); + // + // Copy PeiServices from ROM to Cache in PrivateData + // + CopyMem (&(PrivateData->ServiceTableShadow), *PeiServices, sizeof (EFI_PEI_SERVICES)); + + // + // Set PS to point to ServiceTableShadow in Cache + // + PrivateData->PS = &(PrivateData->ServiceTableShadow); + } else { + // + // Set PS to point to ServiceTableShadow in Cache one time after the + // stack switched to main memory + // + PrivateData->PS = &(PrivateData->ServiceTableShadow); +} + + return; +} + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + +Arguments: + + PeiServices - The PEI core services table. + MemoryBegin - Start of memory address. + MemoryLength - Length of memory. + +Returns: + + Status - EFI_SUCCESS + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob; + EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob; + UINT64 PeiStackSize; + UINT64 EfiFreeMemorySize; + EFI_PHYSICAL_ADDRESS PhysicalAddressOfOldHob; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + PrivateData->SwitchStackSignal = TRUE; + PrivateData->PeiMemoryInstalled = TRUE; + + PrivateData->StackBase = MemoryBegin; + + PeiStackSize = RShiftU64 (MemoryLength, 1); + if (PEI_STACK_SIZE > PeiStackSize) { + PrivateData->StackSize = PeiStackSize; + } else { + PrivateData->StackSize = PEI_STACK_SIZE; + } + + OldHandOffHob = PrivateData->HobList.HandoffInformationTable; + + PrivateData->HobList.Raw = (VOID *)((UINTN)(MemoryBegin + PrivateData->StackSize)); + NewHandOffHob = PrivateData->HobList.HandoffInformationTable; + PhysicalAddressOfOldHob = (EFI_PHYSICAL_ADDRESS) (UINTN) OldHandOffHob; + + EfiFreeMemorySize = OldHandOffHob->EfiFreeMemoryBottom - PhysicalAddressOfOldHob; + + DEBUG ((EFI_D_INFO, "HOBLIST address before memory init = 0x%08x\n", OldHandOffHob)); + DEBUG ((EFI_D_INFO, "HOBLIST address after memory init = 0x%08x\n", NewHandOffHob)); + + CopyMem ( + NewHandOffHob, + OldHandOffHob, + (UINTN)EfiFreeMemorySize + ); + + NewHandOffHob->EfiMemoryTop = MemoryBegin + MemoryLength; + NewHandOffHob->EfiFreeMemoryTop = NewHandOffHob->EfiMemoryTop; + NewHandOffHob->EfiMemoryBottom = MemoryBegin; + + NewHandOffHob->EfiFreeMemoryBottom = (UINTN)NewHandOffHob + EfiFreeMemorySize; + + NewHandOffHob->EfiEndOfHobList = (UINTN)NewHandOffHob + + (OldHandOffHob->EfiEndOfHobList - + PhysicalAddressOfOldHob); + + ConvertPpiPointers (PeiServices, OldHandOffHob, NewHandOffHob); + + BuildStackHob (PrivateData->StackBase, PrivateData->StackSize); + + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +/*++ + +Routine Description: + + Memory allocation service on permanent memory, + not usable prior to the memory installation. + +Arguments: + + PeiServices - The PEI core services table. + MemoryType - Type of memory to allocate. + Pages - Number of pages to allocate. + Memory - Pointer of memory allocated. + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. + EFI_NOT_AVAILABLE_YET Called with permanent memory not available + EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement + to allocate the number of pages. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_PEI_HOB_POINTERS Hob; + EFI_PHYSICAL_ADDRESS Offset; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // Check if Hob already available + // + if (!PrivateData->PeiMemoryInstalled) { + return EFI_NOT_AVAILABLE_YET; + } + + Hob.Raw = PrivateData->HobList.Raw; + + // + // Check to see if on 4k boundary + // + Offset = Hob.HandoffInformationTable->EfiFreeMemoryTop & 0xFFF; + + // + // If not aligned, make the allocation aligned. + // + if (Offset != 0) { + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Offset; + } + + // + // Verify that there is sufficient memory to satisfy the allocation + // + if (Hob.HandoffInformationTable->EfiFreeMemoryTop - ((Pages * EFI_PAGE_SIZE) + sizeof (EFI_HOB_MEMORY_ALLOCATION)) < + Hob.HandoffInformationTable->EfiFreeMemoryBottom) { + return EFI_OUT_OF_RESOURCES; + } else { + // + // Update the PHIT to reflect the memory usage + // + Hob.HandoffInformationTable->EfiFreeMemoryTop -= Pages * EFI_PAGE_SIZE; + + // + // Update the value for the caller + // + *Memory = Hob.HandoffInformationTable->EfiFreeMemoryTop; + + // + // Create a memory allocation HOB. + // + BuildMemoryAllocationHob ( + Hob.HandoffInformationTable->EfiFreeMemoryTop, + Pages * EFI_PAGE_SIZE + Offset, + MemoryType + ); + + return EFI_SUCCESS; + } +} + + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Memory allocation service on the CAR. + +Arguments: + + PeiServices - The PEI core services table. + + Size - Amount of memory required + + Buffer - Address of pointer to the buffer + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_POOL *Hob; + + + Status = PeiCoreCreateHob ( + EFI_HOB_TYPE_PEI_MEMORY_POOL, + (UINT16)(sizeof (EFI_HOB_MEMORY_POOL) + Size), + (VOID **)&Hob + ); + *Buffer = Hob+1; + + + return Status; +} diff --git a/EdkModulePkg/Core/Pei/PeiMain.h b/EdkModulePkg/Core/Pei/PeiMain.h new file mode 100644 index 0000000000..783fcd5867 --- /dev/null +++ b/EdkModulePkg/Core/Pei/PeiMain.h @@ -0,0 +1,1141 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeiMain.h + +Abstract: + + Definition of Pei Core Structures and Services + +Revision History + +--*/ + +#ifndef _PEI_MAIN_H_ +#define _PEI_MAIN_H_ + +#ifdef EFI64 +#include "SalApi.h" +#endif + +// +//Build private HOB to PEI core to transfer old NEM-range data to new NEM-range +// +#define EFI_PEI_CORE_PRIVATE_GUID \ + {0xd641a0f5, 0xcb7c, 0x4846, { 0xa3, 0x80, 0x1d, 0x01, 0xb4, 0xd9, 0xe3, 0xb9 } } + +// +// Pei Core private data structures +// +typedef union { + EFI_PEI_PPI_DESCRIPTOR *Ppi; + EFI_PEI_NOTIFY_DESCRIPTOR *Notify; + VOID *Raw; +} PEI_PPI_LIST_POINTERS; + +#define PEI_STACK_SIZE 0x20000 + +#define MAX_PPI_DESCRIPTORS 64 + +typedef struct { + INTN PpiListEnd; + INTN NotifyListEnd; + INTN DispatchListEnd; + INTN LastDispatchedInstall; + INTN LastDispatchedNotify; + PEI_PPI_LIST_POINTERS PpiListPtrs[MAX_PPI_DESCRIPTORS]; +} PEI_PPI_DATABASE; + +typedef struct { + UINT8 CurrentPeim; + UINT8 CurrentFv; + UINT32 DispatchedPeimBitMap; + UINT32 PreviousPeimBitMap; + EFI_FFS_FILE_HEADER *CurrentPeimAddress; + EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress; + EFI_FIRMWARE_VOLUME_HEADER *BootFvAddress; + EFI_PEI_FIND_FV_PPI *FindFv; +} PEI_CORE_DISPATCH_DATA; + + +// +// Pei Core private data structure instance +// + +#define PEI_CORE_HANDLE_SIGNATURE EFI_SIGNATURE_32('P','e','i','C') + +typedef struct{ + UINTN Signature; + EFI_PEI_SERVICES *PS; // Point to ServiceTableShadow + PEI_PPI_DATABASE PpiData; + PEI_CORE_DISPATCH_DATA DispatchData; + EFI_PEI_HOB_POINTERS HobList; + BOOLEAN SwitchStackSignal; + BOOLEAN PeiMemoryInstalled; + EFI_PHYSICAL_ADDRESS StackBase; + UINT64 StackSize; + VOID *BottomOfCarHeap; + VOID *TopOfCarHeap; + VOID *CpuIo; + EFI_PEI_SECURITY_PPI *PrivateSecurityPpi; + EFI_PEI_SERVICES ServiceTableShadow; + UINTN SizeOfCacheAsRam; + VOID *MaxTopOfCarHeap; +} PEI_CORE_INSTANCE; + +// +// Pei Core Instance Data Macros +// + +#define PEI_CORE_INSTANCE_FROM_PS_THIS(a) \ + CR(a, PEI_CORE_INSTANCE, PS, PEI_CORE_HANDLE_SIGNATURE) + +// +// BUGBUG: Where does this go really? +// +typedef +EFI_STATUS +(EFIAPI *PEI_CORE_ENTRY_POINT)( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ); + +// +// Union of temporarily used function pointers (to save stack space) +// +typedef union { + PEI_CORE_ENTRY_POINT PeiCore; + EFI_PEIM_ENTRY_POINT PeimEntry; + EFI_PEIM_NOTIFY_ENTRY_POINT PeimNotifyEntry; + EFI_DXE_IPL_PPI *DxeIpl; + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + VOID *Raw; +} PEI_CORE_TEMP_POINTERS; + + +// +// Main PEI entry +// +EFI_STATUS +EFIAPI +PeiMain ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Main entry point to Pei Core. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + +Returns: + + This function never returns + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiCore ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to old core data that is used to initialize the + core's data areas. + +Returns: + + This function never returns + +--*/ +; + + +// +// Dispatcher support functions +// + +EFI_STATUS +PeimDispatchReadiness ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *DependencyExpression, + IN OUT BOOLEAN *Runnable + ) +/*++ + +Routine Description: + + This is the POSTFIX version of the dependency evaluator. When a + PUSH [PPI GUID] is encountered, a pointer to the GUID is stored on + the evaluation stack. When that entry is poped from the evaluation + stack, the PPI is checked if it is installed. This method allows + some time savings as not all PPIs must be checked for certain + operation types (AND, OR). + +Arguments: + + PeiServices - Calling context. + + DependencyExpression - Pointer to a dependency expression. The Grammar adheres to + the BNF described above and is stored in postfix notation. + Runnable - is True if the driver can be scheduled and False if the driver + cannot be scheduled. This is the value that the schedulers + should use for deciding the state of the driver. + +Returns: + + Status = EFI_SUCCESS if it is a well-formed Grammar + EFI_INVALID_PARAMETER if the dependency expression overflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression underflows + the evaluation stack + EFI_INVALID_PARAMETER if the dependency expression is not a + well-formed Grammar. +--*/ +; + + +EFI_STATUS +PeiDispatcher ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *PrivateData, + IN PEI_CORE_DISPATCH_DATA *DispatchData + ) + +/*++ + +Routine Description: + + Conduct PEIM dispatch. + +Arguments: + + PeiStartupDescriptor - Pointer to IN EFI_PEI_STARTUP_DESCRIPTOR + PrivateData - Pointer to the private data passed in from caller + DispatchData - Pointer to PEI_CORE_DISPATCH_DATA data. + +Returns: + + EFI_SUCCESS - Successfully dispatched PEIM. + EFI_NOT_FOUND - The dispatch failed. + +--*/ +; + + +VOID +InitializeDispatcherData ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +/*++ + +Routine Description: + + Initialize the Dispatcher's data members + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to old core data (before switching stack). + NULL if being run in non-permament memory mode. + PeiStartupDescriptor - Information and services provided by SEC phase. + + +Returns: + + None + +--*/ +; + + +EFI_STATUS +FindNextPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **PeimFileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + PeimFileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +BOOLEAN +Dispatched ( + IN UINT8 CurrentPeim, + IN UINT32 DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine checks to see if a particular PEIM has been dispatched during + the PEI core dispatch. + +Arguments: + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + TRUE if PEIM already dispatched + FALSE if not + +--*/ +; + +VOID +SetDispatched ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 CurrentPeim, + OUT UINT32 *DispatchedPeimBitMap + ) +/*++ + +Routine Description: + + This routine sets a PEIM as having been dispatched once its entry + point has been invoked. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeim - The PEIM/FV in the bit array to check. + DispatchedPeimBitMap - Bit array, each bit corresponds to a PEIM/FV. + +Returns: + None + +--*/ +; + +BOOLEAN +DepexSatisfied ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *CurrentPeimAddress + ) +/*++ + +Routine Description: + + This routine parses the Dependency Expression, if available, and + decides if the module can be executed. + +Arguments: + PeiServices - The PEI Service Table + CurrentPeimAddress - Address of the PEIM Firmware File under investigation + +Returns: + TRUE - Can be dispatched + FALSE - Cannot be dispatched + +--*/ +; + +#ifdef EFI64 + // + // In Ipf we should make special changes for the PHIT pointers to support + // recovery boot in cache mode. + // +#define SWITCH_TO_CACHE_MODE(CoreData) SwitchToCacheMode(CoreData) +#define CACHE_MODE_ADDRESS_MASK 0x7FFFFFFFFFFFFFFFULL +VOID +SwitchToCacheMode ( + IN PEI_CORE_INSTANCE *CoreData +) +/*++ + +Routine Description: + + Switch the PHIT pointers to cache mode after InstallPeiMemory in CAR. + +Arguments: + + CoreData - The PEI core Private Data + +Returns: + +--*/ +; + +#else + +#define SWITCH_TO_CACHE_MODE(CoreData) + +#endif + +// +// PPI support functions +// +VOID +InitializePpiServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize PPI services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + Nothing + +--*/ +; + +VOID +ConvertPpiPointers ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob, + IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob + ) +/*++ + +Routine Description: + + Migrate the Hob list from the CAR stack to PEI installed memory. + +Arguments: + + PeiServices - The PEI core services table. + OldHandOffHob - The old handoff HOB list. + NewHandOffHob - The new handoff HOB list. + +Returns: + +--*/ +; + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +/*++ + +Routine Description: + + Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + PpiList - Pointer to a list of PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if all PPIs in PpiList are successfully installed. + EFI_INVALID_PARAMETER - if PpiList is NULL pointer + EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid + EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI + +--*/ +; + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +/*++ + +Routine Description: + + Re-Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + OldPpi - Pointer to the old PEI PPI Descriptors. + NewPpi - Pointer to the new PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if the operation was successful + EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL + EFI_INVALID_PARAMETER - if NewPpi is not valid + EFI_NOT_FOUND - if the PPI was not in the database + +--*/ +; + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + Locate a given named PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + Guid - Pointer to GUID of the PPI. + Instance - Instance Number to discover. + PpiDescriptor - Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + Ppi - Pointer to reference the found PPI + +Returns: + + Status - EFI_SUCCESS if the PPI is in the database + EFI_NOT_FOUND if the PPI is not in the database +--*/ +; + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +/*++ + +Routine Description: + + Install a notification for a given PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyList - Pointer to list of Descriptors to notify upon. + +Returns: + + Status - EFI_SUCCESS if successful + EFI_OUT_OF_RESOURCES if no space in the database + EFI_INVALID_PARAMETER if not a good decriptor + +--*/ +; + +VOID +ProcessNotifyList ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Process the Notify List at dispatch level. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + +Returns: + +--*/ +; + +VOID +DispatchNotify ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +/*++ + +Routine Description: + + Dispatch notifications. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyType - Type of notify to fire. + InstallStartIndex - Install Beginning index. + InstallStopIndex - Install Ending index. + NotifyStartIndex - Notify Beginning index. + NotifyStopIndex - Notify Ending index. + +Returns: None + +--*/ +; + +// +// Boot mode support functions +// +EFI_STATUS +EFIAPI +PeiGetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to ascertain the present value of the boot mode. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - A pointer to contain the value of the boot mode. + +Returns: + + EFI_SUCCESS - The boot mode was returned successfully. + EFI_INVALID_PARAMETER - BootMode is NULL. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiSetBootMode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This service enables PEIMs to update the boot mode variable. + +Arguments: + + PeiServices - The PEI core services table. + BootMode - The value of the boot mode to set. + +Returns: + + EFI_SUCCESS - The value was successfully updated + +--*/ +; + +// +// Security support functions +// +VOID +InitializeSecurityServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the security services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permament memory mode. +Returns: + + None + +--*/ +; + +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress + ) +/*++ + +Routine Description: + + Provide a callout to the OEM FV verification service. + +Arguments: + + CurrentFvAddress - Pointer to the FV under investigation. + +Returns: + + Status - EFI_SUCCESS + +--*/ +; + + +EFI_STATUS +VerifyPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *CurrentPeimAddress + ) +/*++ + +Routine Description: + + Provide a callout to the security verification service. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeimAddress - Pointer to the Firmware File under investigation. + +Returns: + + EFI_SUCCESS - Image is OK + EFI_SECURITY_VIOLATION - Image is illegal + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiGetHobList ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ) +/*++ + +Routine Description: + + Gets the pointer to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + HobList - Pointer to the HOB List. + +Returns: + + EFI_SUCCESS - Get the pointer of HOB List + EFI_NOT_AVAILABLE_YET - the HOB List is not yet published + EFI_INVALID_PARAMETER - HobList is NULL (in debug mode) + +--*/ +; + +EFI_STATUS +EFIAPI +PeiCreateHob ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Add a new HOB to the HOB List. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of the new HOB. + Length - Length of the new HOB to allocate. + Hob - Pointer to the new HOB. + +Returns: + + Status - EFI_SUCCESS + - EFI_INVALID_PARAMETER if Hob is NULL + - EFI_NOT_AVAILABLE_YET if HobList is still not available. + - EFI_OUT_OF_RESOURCES if there is no more memory to grow the Hoblist. + +--*/ +; + +EFI_STATUS +PeiCoreBuildHobHandoffInfoTable ( + IN EFI_BOOT_MODE BootMode, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Builds a Handoff Information Table HOB + +Arguments: + + BootMode - Current Bootmode + MemoryBegin - Start Memory Address. + MemoryLength - Length of Memory. + +Returns: + + EFI_SUCCESS + +--*/ +; + + +// +// FFS Fw Volume support functions +// +EFI_STATUS +EFIAPI +PeiFfsFindNextFile ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFfsFindSectionData ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + PeiServices - Pointer to the PEI Core Services Table. + SearchType - Filter to find only sections of this type. + FfsFileHeader - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + - NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiFvFindNextVolume ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +/*++ + +Routine Description: + + Return the BFV location + + BugBug -- Move this to the location of this code to where the + other FV and FFS support code lives. + Also, update to use FindFV for instances #'s >= 1. + +Arguments: + + PeiServices - The PEI core services table. + Instance - Instance of FV to find + FwVolHeader - Pointer to contain the data to return + +Returns: + Pointer to the Firmware Volume instance requested + + EFI_INVALID_PARAMETER - FwVolHeader is NULL + + EFI_SUCCESS - Firmware volume instance successfully found. + +--*/ +; + +// +// Memory support functions +// +VOID +InitializeMemoryServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the memory services. + +Arguments: + + PeiServices - The PEI core services table. + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + + None + +--*/ +; + +EFI_STATUS +EFIAPI +PeiInstallPeiMemory ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +/*++ + +Routine Description: + + Install the permanent memory is now available. + Creates HOB (PHIT and Stack). + +Arguments: + + PeiServices - The PEI core services table. + MemoryBegin - Start of memory address. + MemoryLength - Length of memory. + +Returns: + + Status - EFI_SUCCESS + +--*/ +; + +EFI_STATUS +EFIAPI +PeiAllocatePages ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ) +/*++ + +Routine Description: + + Memory allocation service on permanent memory, + not usable prior to the memory installation. + +Arguments: + + PeiServices - The PEI core services table. + Type - Type of allocation. + MemoryType - Type of memory to allocate. + Pages - Number of pages to allocate. + Memory - Pointer of memory allocated. + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_INVALID_PARAMETER Only AllocateAnyAddress is supported. + EFI_NOT_AVAILABLE_YET Called with permanent memory not available + EFI_OUT_OF_RESOURCES There is not enough HOB heap to satisfy the requirement + to allocate the number of pages. + +--*/ +; + +EFI_STATUS +EFIAPI +PeiAllocatePool ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ) +/*++ + +Routine Description: + + Memory allocation service on the CAR. + +Arguments: + + PeiServices - The PEI core services table. + + Size - Amount of memory required + + Buffer - Address of pointer to the buffer + +Returns: + + Status - EFI_SUCCESS The allocation was successful + EFI_OUT_OF_RESOURCES There is not enough heap to satisfy the requirement + to allocate the requested size. + +--*/ +; + +EFI_STATUS +PeiLoadImage ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *PeimFileHeader, + OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Get entry point of a Peim file. + +Arguments: + + PeiServices - Calling context. + + PeimFileHeader - Peim file's header. + + EntryPoint - Entry point of that Peim file. + +Returns: + + Status code. + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +/*++ + +Routine Description: + + Core version of the Status Code reporter + +Arguments: + + PeiServices - The PEI core services table. + + CodeType - Type of Status Code. + + Value - Value to output for Status Code. + + Instance - Instance Number of this status code. + + CallerId - ID of the caller of this status code. + + Data - Optional data associated with this status code. + +Returns: + + Status - EFI_SUCCESS if status code is successfully reported + - EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +--*/ +; + + +EFI_STATUS +EFIAPI +PeiResetSystem ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Core version of the Reset System + +Arguments: + + PeiServices - The PEI core services table. + +Returns: + + Status - EFI_NOT_AVAILABLE_YET. PPI not available yet. + - EFI_DEVICE_ERROR. Did not reset system. + + Otherwise, resets the system. + +--*/ +; + +#endif diff --git a/EdkModulePkg/Core/Pei/PeiMain.mbd b/EdkModulePkg/Core/Pei/PeiMain.mbd new file mode 100644 index 0000000000..c9d64e336a --- /dev/null +++ b/EdkModulePkg/Core/Pei/PeiMain.mbd @@ -0,0 +1,53 @@ + + + + + PeiMain + 52C05B14-0B98-496c-BC3B-04B50211D680 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + + PeiCoreEntryPoint + BaseLib + BaseMemoryLib + PeiServicesTablePointerLib + PeiCoreLib + PeiHobLib + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + BasePerformanceLibNull + + BasePeCoffGetEntryPointLib + + + BasePeCoffGetEntryPointLib + + + BasePeCoffGetEntryPointLib + + + BasePeCoffGetEntryPointLib + + + diff --git a/EdkModulePkg/Core/Pei/PeiMain.msa b/EdkModulePkg/Core/Pei/PeiMain.msa new file mode 100644 index 0000000000..b18b178caa --- /dev/null +++ b/EdkModulePkg/Core/Pei/PeiMain.msa @@ -0,0 +1,91 @@ + + + + + PeiMain + PEI_CORE + PEI_CORE + 52C05B14-0B98-496c-BC3B-04B50211D680 + 0 + Component description file for PeiMain module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + DebugLib + PeiCoreEntryPoint + BaseLib + HobLib + PerformanceLib + PeiCoreLib + ReportStatusCodeLib + PeCoffGetEntryPointLib + BaseMemoryLib + TimerLib + + + PeiMain.h + BootMode\BootMode.c + Dependency\Dependency.c + Dispatcher\Dispatcher.c + FwVol\FwVol.c + Hob\Hob.c + Image\Image.c + Memory\MemoryServices.c + PeiMain\PeiMain.c + Ppi\Ppi.c + Reset\Reset.c + Security\Security.c + StatusCode\StatusCode.c + + ipf\SwitchToCacheMode.c + ipf\IpfCpuCore.i + ipf\IpfCpuCore.s + + + + MdePkg + EdkModulePkg + + + + + gPeiPerformanceHobGuid + 0xec4df5af, 0x4395, 0x4cc9, 0x94, 0xde, 0x77, 0x50, 0x6d, 0x12, 0xc7, 0xb8 + + + + MemoryDiscovered + FindFv + FvFileLoader + DxeIpl + Reset + StatusCode + Security + + + + PeiCore + + + diff --git a/EdkModulePkg/Core/Pei/PeiMain/PeiMain.c b/EdkModulePkg/Core/Pei/PeiMain/PeiMain.c new file mode 100644 index 0000000000..014c571c05 --- /dev/null +++ b/EdkModulePkg/Core/Pei/PeiMain/PeiMain.c @@ -0,0 +1,243 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeiMain.c + +Abstract: + + Pei Core Main Entry Point + +Revision History + +--*/ + +#include + +// +//CAR is filled with this initial value during SEC phase +// +#define INIT_CAR_VALUE 0x5AA55AA5 + +static EFI_PEI_PPI_DESCRIPTOR mMemoryDiscoveredPpi = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMemoryDiscoveredPpiGuid, + NULL +}; + +// +// Pei Core Module Variables +// +// +static EFI_PEI_SERVICES mPS = { + { + PEI_SERVICES_SIGNATURE, + PEI_SERVICES_REVISION, + sizeof (EFI_PEI_SERVICES), + 0, + 0 + }, + PeiInstallPpi, + PeiReInstallPpi, + PeiLocatePpi, + PeiNotifyPpi, + + PeiGetBootMode, + PeiSetBootMode, + + PeiGetHobList, + PeiCreateHob, + + PeiFvFindNextVolume, + PeiFfsFindNextFile, + PeiFfsFindSectionData, + + PeiInstallPeiMemory, + PeiAllocatePages, + PeiAllocatePool, + (EFI_PEI_COPY_MEM)CopyMem, + (EFI_PEI_SET_MEM)SetMem, + + PeiReportStatusCode, + + PeiResetSystem +}; + +EFI_STATUS +EFIAPI +PeiCore ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + The entry routine to Pei Core, invoked by PeiMain during transition + from SEC to PEI. After switching stack in the PEI core, it will restart + with the old core data. + +Arguments: + + PeiStartupDescriptor - Information and services provided by SEC phase. + OldCoreData - Pointer to old core data that is used to initialize the + core's data areas. + +Returns: + + This function never returns + EFI_NOT_FOUND - Never reach + +--*/ +{ + PEI_CORE_INSTANCE PrivateData; + EFI_STATUS Status; + PEI_CORE_TEMP_POINTERS TempPtr; + PEI_CORE_DISPATCH_DATA *DispatchData; + UINT64 mTick; + + mTick = 0; + +#ifdef EFI_PEI_PERFORMANCE + if (OldCoreData == NULL) { + mTick = GetPerformanceCounter (); + } +#endif + + + // + // For IPF in CAR mode the real memory access is uncached,in InstallPeiMemory() + // the 63-bit of address is set to 1. + // + SWITCH_TO_CACHE_MODE (OldCoreData); + + if (OldCoreData != NULL) { + CopyMem (&PrivateData, OldCoreData, sizeof (PEI_CORE_INSTANCE)); + } else { + ZeroMem (&PrivateData, sizeof (PEI_CORE_INSTANCE)); + } + + PrivateData.Signature = PEI_CORE_HANDLE_SIGNATURE; + PrivateData.PS = &mPS; + + // + // Initialize libraries that the PeiCore is linked against + // BUGBUG: The FfsHeader is passed in as NULL. Do we look it up or remove it from the lib init? + // + ProcessLibraryConstructorList (NULL, &PrivateData.PS); + + InitializeMemoryServices (&PrivateData.PS, PeiStartupDescriptor, OldCoreData); + + InitializePpiServices (&PrivateData.PS, OldCoreData); + + InitializeSecurityServices (&PrivateData.PS, OldCoreData); + + InitializeDispatcherData (&PrivateData.PS, OldCoreData, PeiStartupDescriptor); + + if (OldCoreData != NULL) { + + PERF_END (NULL,"PreMem", NULL, 0); + PERF_START (NULL,"PostMem", NULL, 0); + + // + // The following code dumps out interesting cache as RAM usage information + // so we can keep tabs on how the cache as RAM is being utilized. The + // DEBUG_CODE macro is used to prevent this code from being compiled + // on a debug build. + // + DEBUG_CODE ( + UINTN *StackPointer; + UINTN StackValue; + + StackValue = INIT_CAR_VALUE; + for (StackPointer = (UINTN *) OldCoreData->MaxTopOfCarHeap; + ((UINTN) StackPointer < ((UINTN) OldCoreData->BottomOfCarHeap + OldCoreData->SizeOfCacheAsRam)) + && StackValue == INIT_CAR_VALUE; + StackPointer++) { + StackValue = *StackPointer; + } + + DEBUG ((EFI_D_INFO, "Total Cache as RAM: %d bytes.\n", OldCoreData->SizeOfCacheAsRam)); + DEBUG ((EFI_D_INFO, " CAR stack ever used: %d bytes.\n", + ((UINTN) OldCoreData->TopOfCarHeap - (UINTN) StackPointer) + )); + DEBUG ((EFI_D_INFO, " CAR heap used: %d bytes.\n", + ((UINTN) OldCoreData->HobList.HandoffInformationTable->EfiFreeMemoryBottom - + (UINTN) OldCoreData->HobList.Raw) + )); + ); + + // + // Alert any listeners that there is permanent memory available + // + PERF_START (NULL,"DisMem", NULL, 0); + Status = PeiCoreInstallPpi (&mMemoryDiscoveredPpi); + PERF_END (NULL,"DisMem", NULL, 0); + + } else { + + // + // Report Status Code EFI_SW_PC_INIT + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_SOFTWARE_PEI_CORE | EFI_SW_PC_INIT + ); + + // + // If first pass, start performance measurement. + // + PERF_START (NULL,"PreMem", NULL, mTick); + + // + // If SEC provided any PPI services to PEI, install them. + // + if (PeiStartupDescriptor->DispatchTable != NULL) { + Status = PeiCoreInstallPpi (PeiStartupDescriptor->DispatchTable); + ASSERT_EFI_ERROR (Status); + } + } + + DispatchData = &PrivateData.DispatchData; + + // + // Call PEIM dispatcher + // + PeiDispatcher (PeiStartupDescriptor, &PrivateData, DispatchData); + + // + // Check if InstallPeiMemory service was called. + // + ASSERT(PrivateData.PeiMemoryInstalled == TRUE); + + PERF_END (NULL, "PostMem", NULL, 0); + + Status = PeiCoreLocatePpi ( + &gEfiDxeIplPpiGuid, + 0, + NULL, + (VOID **)&TempPtr.DxeIpl + ); + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_INFO, "DXE IPL Entry\n")); + Status = TempPtr.DxeIpl->Entry ( + TempPtr.DxeIpl, + &PrivateData.PS, + PrivateData.HobList + ); + + ASSERT_EFI_ERROR (Status); + + return EFI_NOT_FOUND; +} + diff --git a/EdkModulePkg/Core/Pei/Ppi/Ppi.c b/EdkModulePkg/Core/Pei/Ppi/Ppi.c new file mode 100644 index 0000000000..7fdb08c66f --- /dev/null +++ b/EdkModulePkg/Core/Pei/Ppi/Ppi.c @@ -0,0 +1,658 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Ppi.c + +Abstract: + + EFI PEI Core PPI services + +Revision History + +--*/ + +#include + +VOID +InitializePpiServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize PPI services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the PEI Core data. + NULL if being run in non-permament memory mode. + +Returns: + Nothing + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + if (OldCoreData == NULL) { + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + PrivateData->PpiData.NotifyListEnd = MAX_PPI_DESCRIPTORS-1; + PrivateData->PpiData.DispatchListEnd = MAX_PPI_DESCRIPTORS-1; + PrivateData->PpiData.LastDispatchedNotify = MAX_PPI_DESCRIPTORS-1; + } + + return; +} + +VOID +ConvertPpiPointers ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_HOB_HANDOFF_INFO_TABLE *OldHandOffHob, + IN EFI_HOB_HANDOFF_INFO_TABLE *NewHandOffHob + ) +/*++ + +Routine Description: + + Migrate the Hob list from the CAR stack to PEI installed memory. + +Arguments: + + PeiServices - The PEI core services table. + OldHandOffHob - The old handoff HOB list. + NewHandOffHob - The new handoff HOB list. + +Returns: + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + UINT8 Index; + PEI_PPI_LIST_POINTERS *PpiPointer; + UINTN Fixup; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Fixup = (UINTN)NewHandOffHob - (UINTN)OldHandOffHob; + + for (Index = 0; Index < MAX_PPI_DESCRIPTORS; Index++) { + if (Index < PrivateData->PpiData.PpiListEnd || + Index > PrivateData->PpiData.NotifyListEnd) { + PpiPointer = &PrivateData->PpiData.PpiListPtrs[Index]; + + if (((UINTN)PpiPointer->Raw < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && + ((UINTN)PpiPointer->Raw >= (UINTN)OldHandOffHob)) { + // + // Convert the pointer to the PEIM descriptor from the old HOB heap + // to the relocated HOB heap. + // + PpiPointer->Raw = (VOID *) ((UINTN)PpiPointer->Raw + Fixup); + + // + // Only when the PEIM descriptor is in the old HOB should it be necessary + // to try to convert the pointers in the PEIM descriptor + // + + if (((UINTN)PpiPointer->Ppi->Guid < (UINTN)OldHandOffHob->EfiFreeMemoryBottom) && + ((UINTN)PpiPointer->Ppi->Guid >= (UINTN)OldHandOffHob)) { + // + // Convert the pointer to the GUID in the PPI or NOTIFY descriptor + // from the old HOB heap to the relocated HOB heap. + // + PpiPointer->Ppi->Guid = (VOID *) ((UINTN)PpiPointer->Ppi->Guid + Fixup); + } + + // + // Assume that no code is located in the temporary memory, so the pointer to + // the notification function in the NOTIFY descriptor needs not be converted. + // + if (Index < PrivateData->PpiData.PpiListEnd && + (UINTN)PpiPointer->Ppi->Ppi < (UINTN)OldHandOffHob->EfiFreeMemoryBottom && + (UINTN)PpiPointer->Ppi->Ppi >= (UINTN)OldHandOffHob) { + // + // Convert the pointer to the PPI interface structure in the PPI descriptor + // from the old HOB heap to the relocated HOB heap. + // + PpiPointer->Ppi->Ppi = (VOID *) ((UINTN)PpiPointer->Ppi->Ppi+ Fixup); + } + } + } + } +} + + + +EFI_STATUS +EFIAPI +PeiInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +/*++ + +Routine Description: + + Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + PpiList - Pointer to a list of PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if all PPIs in PpiList are successfully installed. + EFI_INVALID_PARAMETER - if PpiList is NULL pointer + EFI_INVALID_PARAMETER - if any PPI in PpiList is not valid + EFI_OUT_OF_RESOURCES - if there is no more memory resource to install PPI + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + INTN LastCallbackInstall; + + + if (PpiList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Index = PrivateData->PpiData.PpiListEnd; + LastCallbackInstall = Index; + + // + // This is loop installs all PPI descriptors in the PpiList. It is terminated + // by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_PPI_DESCRIPTOR in the list. + // + + for (;;) { + // + // Since PpiData is used for NotifyList and InstallList, max resource + // is reached if the Install reaches the NotifyList + // + if (Index == PrivateData->PpiData.NotifyListEnd + 1) { + return EFI_OUT_OF_RESOURCES; + } + // + // Check if it is a valid PPI. + // If not, rollback list to exclude all in this list. + // Try to indicate which item failed. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + PrivateData->PpiData.PpiListEnd = LastCallbackInstall; + DEBUG((EFI_D_INFO, "ERROR -> InstallPpi: %g %x\n", PpiList->Guid, PpiList->Ppi)); + return EFI_INVALID_PARAMETER; + } + + DEBUG((EFI_D_INFO, "Install PPI: %g\n", PpiList->Guid)); + PrivateData->PpiData.PpiListPtrs[Index].Ppi = PpiList; + PrivateData->PpiData.PpiListEnd++; + + // + // Continue until the end of the PPI List. + // + if ((PpiList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + break; + } + PpiList++; + Index++; + } + + // + // Dispatch any callback level notifies for newly installed PPIs. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + LastCallbackInstall, + PrivateData->PpiData.PpiListEnd, + PrivateData->PpiData.DispatchListEnd, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiReInstallPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +/*++ + +Routine Description: + + Re-Install PPI services. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + OldPpi - Pointer to the old PEI PPI Descriptors. + NewPpi - Pointer to the new PEI PPI Descriptors. + +Returns: + + EFI_SUCCESS - if the operation was successful + EFI_INVALID_PARAMETER - if OldPpi or NewPpi is NULL + EFI_INVALID_PARAMETER - if NewPpi is not valid + EFI_NOT_FOUND - if the PPI was not in the database + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + + + if ((OldPpi == NULL) || (NewPpi == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if ((NewPpi->Flags & EFI_PEI_PPI_DESCRIPTOR_PPI) == 0) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Find the old PPI instance in the database. If we can not find it, + // return the EFI_NOT_FOUND error. + // + for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) { + if (OldPpi == PrivateData->PpiData.PpiListPtrs[Index].Ppi) { + break; + } + } + if (Index == PrivateData->PpiData.PpiListEnd) { + return EFI_NOT_FOUND; + } + + // + // Remove the old PPI from the database, add the new one. + // + DEBUG((EFI_D_INFO, "Reinstall PPI: %g\n", NewPpi->Guid)); + PrivateData->PpiData.PpiListPtrs[Index].Ppi = NewPpi; + + // + // Dispatch any callback level notifies for the newly installed PPI. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + Index, + Index+1, + PrivateData->PpiData.DispatchListEnd, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +PeiLocatePpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +/*++ + +Routine Description: + + Locate a given named PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + Guid - Pointer to GUID of the PPI. + Instance - Instance Number to discover. + PpiDescriptor - Pointer to reference the found descriptor. If not NULL, + returns a pointer to the descriptor (includes flags, etc) + Ppi - Pointer to reference the found PPI + +Returns: + + Status - EFI_SUCCESS if the PPI is in the database + EFI_NOT_FOUND if the PPI is not in the database +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + EFI_GUID *CheckGuid; + EFI_PEI_PPI_DESCRIPTOR *TempPtr; + + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Search the data base for the matching instance of the GUIDed PPI. + // + for (Index = 0; Index < PrivateData->PpiData.PpiListEnd; Index++) { + TempPtr = PrivateData->PpiData.PpiListPtrs[Index].Ppi; + CheckGuid = TempPtr->Guid; + + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) { + if (Instance == 0) { + + if (PpiDescriptor != NULL) { + *PpiDescriptor = TempPtr; + } + + if (Ppi != NULL) { + *Ppi = TempPtr->Ppi; + } + + + return EFI_SUCCESS; + } + Instance--; + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EFIAPI +PeiNotifyPpi ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +/*++ + +Routine Description: + + Install a notification for a given PPI. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyList - Pointer to list of Descriptors to notify upon. + +Returns: + + Status - EFI_SUCCESS if successful + EFI_OUT_OF_RESOURCES if no space in the database + EFI_INVALID_PARAMETER if not a good decriptor + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index; + INTN NotifyIndex; + INTN LastCallbackNotify; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyPtr; + UINTN NotifyDispatchCount; + + + NotifyDispatchCount = 0; + + if (NotifyList == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + Index = PrivateData->PpiData.NotifyListEnd; + LastCallbackNotify = Index; + + // + // This is loop installs all Notify descriptors in the NotifyList. It is + // terminated by the EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST being set in the last + // EFI_PEI_NOTIFY_DESCRIPTOR in the list. + // + + for (;;) { + // + // Since PpiData is used for NotifyList and InstallList, max resource + // is reached if the Install reaches the PpiList + // + if (Index == PrivateData->PpiData.PpiListEnd - 1) { + return EFI_OUT_OF_RESOURCES; + } + + // + // If some of the PPI data is invalid restore original Notify PPI database value + // + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES) == 0) { + PrivateData->PpiData.NotifyListEnd = LastCallbackNotify; + DEBUG((EFI_D_INFO, "ERROR -> InstallNotify: %g %x\n", NotifyList->Guid, NotifyList->Notify)); + return EFI_INVALID_PARAMETER; + } + + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) { + NotifyDispatchCount ++; + } + + PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyList; + + PrivateData->PpiData.NotifyListEnd--; + DEBUG((EFI_D_INFO, "Register PPI Notify: %g\n", NotifyList->Guid)); + if ((NotifyList->Flags & EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) == + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST) { + break; + } + // + // Go the next descriptor. Remember the NotifyList moves down. + // + NotifyList++; + Index--; + } + + // + // If there is Dispatch Notify PPI installed put them on the bottom + // + if (NotifyDispatchCount > 0) { + for (NotifyIndex = LastCallbackNotify; NotifyIndex > PrivateData->PpiData.NotifyListEnd; NotifyIndex--) { + if ((PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify->Flags & EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH) != 0) { + NotifyPtr = PrivateData->PpiData.PpiListPtrs[NotifyIndex].Notify; + + for (Index = NotifyIndex; Index < PrivateData->PpiData.DispatchListEnd; Index++){ + PrivateData->PpiData.PpiListPtrs[Index].Notify = PrivateData->PpiData.PpiListPtrs[Index + 1].Notify; + } + PrivateData->PpiData.PpiListPtrs[Index].Notify = NotifyPtr; + PrivateData->PpiData.DispatchListEnd--; + } + } + + LastCallbackNotify -= NotifyDispatchCount; + } + + // + // Dispatch any callback level notifies for all previously installed PPIs. + // + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK, + 0, + PrivateData->PpiData.PpiListEnd, + LastCallbackNotify, + PrivateData->PpiData.NotifyListEnd + ); + + + return EFI_SUCCESS; +} + + +VOID +ProcessNotifyList ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Process the Notify List at dispatch level. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + +Returns: + +--*/ + +{ + PEI_CORE_INSTANCE *PrivateData; + INTN TempValue; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + + while (TRUE) { + // + // Check if the PEIM that was just dispatched resulted in any + // Notifies getting installed. If so, go process any dispatch + // level Notifies that match the previouly installed PPIs. + // Use "while" instead of "if" since DispatchNotify can modify + // DispatchListEnd (with NotifyPpi) so we have to iterate until the same. + // + while (PrivateData->PpiData.LastDispatchedNotify != PrivateData->PpiData.DispatchListEnd) { + TempValue = PrivateData->PpiData.DispatchListEnd; + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + 0, + PrivateData->PpiData.LastDispatchedInstall, + PrivateData->PpiData.LastDispatchedNotify, + PrivateData->PpiData.DispatchListEnd + ); + PrivateData->PpiData.LastDispatchedNotify = TempValue; + } + + + // + // Check if the PEIM that was just dispatched resulted in any + // PPIs getting installed. If so, go process any dispatch + // level Notifies that match the installed PPIs. + // Use "while" instead of "if" since DispatchNotify can modify + // PpiListEnd (with InstallPpi) so we have to iterate until the same. + // + while (PrivateData->PpiData.LastDispatchedInstall != PrivateData->PpiData.PpiListEnd) { + TempValue = PrivateData->PpiData.PpiListEnd; + DispatchNotify ( + PeiServices, + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH, + PrivateData->PpiData.LastDispatchedInstall, + PrivateData->PpiData.PpiListEnd, + MAX_PPI_DESCRIPTORS-1, + PrivateData->PpiData.DispatchListEnd + ); + PrivateData->PpiData.LastDispatchedInstall = TempValue; + } + + if (PrivateData->PpiData.LastDispatchedNotify == PrivateData->PpiData.DispatchListEnd) { + break; + } + } + return; +} + +VOID +DispatchNotify ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN NotifyType, + IN INTN InstallStartIndex, + IN INTN InstallStopIndex, + IN INTN NotifyStartIndex, + IN INTN NotifyStopIndex + ) +/*++ + +Routine Description: + + Dispatch notifications. + +Arguments: + + PeiServices - Pointer to the PEI Service Table + NotifyType - Type of notify to fire. + InstallStartIndex - Install Beginning index. + InstallStopIndex - Install Ending index. + NotifyStartIndex - Notify Beginning index. + NotifyStopIndex - Notify Ending index. + +Returns: None + +--*/ + +{ + PEI_CORE_INSTANCE *PrivateData; + INTN Index1; + INTN Index2; + EFI_GUID *SearchGuid; + EFI_GUID *CheckGuid; + EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor; + + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS(PeiServices); + + // + // Remember that Installs moves up and Notifies moves down. + // + for (Index1 = NotifyStartIndex; Index1 > NotifyStopIndex; Index1--) { + NotifyDescriptor = PrivateData->PpiData.PpiListPtrs[Index1].Notify; + + CheckGuid = NotifyDescriptor->Guid; + + for (Index2 = InstallStartIndex; Index2 < InstallStopIndex; Index2++) { + SearchGuid = PrivateData->PpiData.PpiListPtrs[Index2].Ppi->Guid; + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID as INT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *)SearchGuid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)SearchGuid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)SearchGuid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)SearchGuid)[3] == ((INT32 *)CheckGuid)[3])) { + DEBUG ((EFI_D_INFO, "Notify: PPI Guid: %g, Peim notify entry point: %x\n", + SearchGuid, + NotifyDescriptor->Notify + )); + NotifyDescriptor->Notify ( + PeiServices, + NotifyDescriptor, + (PrivateData->PpiData.PpiListPtrs[Index2].Ppi)->Ppi + ); + } + } + } + + return; +} + diff --git a/EdkModulePkg/Core/Pei/Reset/Reset.c b/EdkModulePkg/Core/Pei/Reset/Reset.c new file mode 100644 index 0000000000..6bcb4ce31b --- /dev/null +++ b/EdkModulePkg/Core/Pei/Reset/Reset.c @@ -0,0 +1,68 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Reset.c + +Abstract: + + Pei Core Reset System Support + +Revision History + +--*/ + +#include + +EFI_STATUS +EFIAPI +PeiResetSystem ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Core version of the Reset System + +Arguments: + + PeiServices - The PEI core services table. + +Returns: + + Status - EFI_NOT_AVAILABLE_YET. PPI not available yet. + - EFI_DEVICE_ERROR. Did not reset system. + + Otherwise, resets the system. + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_RESET_PPI *ResetPpi; + + Status = PeiCoreLocatePpi ( + &gEfiPeiResetPpiGuid, + 0, + NULL, + (VOID **)&ResetPpi + ); + + // + // LocatePpi returns EFI_NOT_FOUND on error + // + if (!EFI_ERROR (Status)) { + return ResetPpi->ResetSystem (PeiServices); + } + return EFI_NOT_AVAILABLE_YET; +} + diff --git a/EdkModulePkg/Core/Pei/Security/Security.c b/EdkModulePkg/Core/Pei/Security/Security.c new file mode 100644 index 0000000000..5908928c7b --- /dev/null +++ b/EdkModulePkg/Core/Pei/Security/Security.c @@ -0,0 +1,192 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Security.c + +Abstract: + + EFI PEI Core Security services + +--*/ + +#include + +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +static EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = { + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gEfiPeiSecurityPpiGuid, + SecurityPpiNotifyCallback +}; + +VOID +InitializeSecurityServices ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_CORE_INSTANCE *OldCoreData + ) +/*++ + +Routine Description: + + Initialize the security services. + +Arguments: + + PeiServices - The PEI core services table. + OldCoreData - Pointer to the old core data. + NULL if being run in non-permament memory mode. +Returns: + + None + +--*/ +{ + if (OldCoreData == NULL) { + PeiCoreNotifyPpi (&mNotifyList); + } + return; +} + +EFI_STATUS +EFIAPI +SecurityPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Provide a callback for when the security PPI is installed. + +Arguments: + + PeiServices - The PEI core services table. + NotifyDescriptor - The descriptor for the notification event. + Ppi - Pointer to the PPI in question. + +Returns: + + EFI_SUCCESS - The function is successfully processed. + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + + // + // Get PEI Core private data + // + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + // + // If there isn't a security PPI installed, use the one from notification + // + if (PrivateData->PrivateSecurityPpi == NULL) { + PrivateData->PrivateSecurityPpi = (EFI_PEI_SECURITY_PPI *)Ppi; + } + return EFI_SUCCESS; +} + +EFI_STATUS +VerifyPeim ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FFS_FILE_HEADER *CurrentPeimAddress + ) +/*++ + +Routine Description: + + Provide a callout to the security verification service. + +Arguments: + + PeiServices - The PEI core services table. + CurrentPeimAddress - Pointer to the Firmware File under investigation. + +Returns: + + EFI_SUCCESS - Image is OK + EFI_SECURITY_VIOLATION - Image is illegal + +--*/ +{ + PEI_CORE_INSTANCE *PrivateData; + EFI_STATUS Status; + UINT32 AuthenticationStatus; + BOOLEAN StartCrisisRecovery; + + // + // Set a default authentication state + // + AuthenticationStatus = 0; + + // + // get security PPI instance from PEI private data + // + PrivateData = PEI_CORE_INSTANCE_FROM_PS_THIS (PeiServices); + + if (PrivateData->PrivateSecurityPpi == NULL) { + Status = EFI_NOT_FOUND; + } else { + // + // Check to see if the image is OK + // + Status = PrivateData->PrivateSecurityPpi->AuthenticationState ( + PeiServices, + PrivateData->PrivateSecurityPpi, + AuthenticationStatus, + CurrentPeimAddress, + &StartCrisisRecovery + ); + if (StartCrisisRecovery) { + Status = EFI_SECURITY_VIOLATION; + } + } + return Status; +} + + +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *CurrentFvAddress + ) +/*++ + +Routine Description: + + Verify a Firmware volume + +Arguments: + + CurrentFvAddress - Pointer to the current Firmware Volume under consideration + +Returns: + + EFI_SUCCESS - Firmware Volume is legal + EFI_SECURITY_VIOLATION - Firmware Volume fails integrity test + +--*/ +{ + // + // Right now just pass the test. Future can authenticate and/or check the + // FV-header or other metric for goodness of binary. + // + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Core/Pei/StatusCode/StatusCode.c b/EdkModulePkg/Core/Pei/StatusCode/StatusCode.c new file mode 100644 index 0000000000..496effa5e5 --- /dev/null +++ b/EdkModulePkg/Core/Pei/StatusCode/StatusCode.c @@ -0,0 +1,95 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + StatusCode.c + +Abstract: + + Pei Core Status Code Support + +Revision History + +--*/ + +#include + +EFI_STATUS +EFIAPI +PeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +/*++ + +Routine Description: + + Core version of the Status Code reporter + +Arguments: + + PeiServices - The PEI core services table. + + CodeType - Type of Status Code. + + Value - Value to output for Status Code. + + Instance - Instance Number of this status code. + + CallerId - ID of the caller of this status code. + + Data - Optional data associated with this status code. + +Returns: + + Status - EFI_SUCCESS if status code is successfully reported + - EFI_NOT_AVAILABLE_YET if StatusCodePpi has not been installed + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PROGRESS_CODE_PPI *StatusCodePpi; + + + // + //Locate StatusCode Ppi. + // + Status = PeiCoreLocatePpi ( + &gEfiPeiStatusCodePpiGuid, + 0, + NULL, + (VOID **)&StatusCodePpi + ); + + if (!EFI_ERROR (Status)) { + Status = StatusCodePpi->ReportStatusCode ( + PeiServices, + CodeType, + Value, + Instance, + CallerId, + Data + ); + + return Status; + } + + + return EFI_NOT_AVAILABLE_YET; +} + + + diff --git a/EdkModulePkg/Core/Pei/build.xml b/EdkModulePkg/Core/Pei/build.xml new file mode 100644 index 0000000000..94a26db352 --- /dev/null +++ b/EdkModulePkg/Core/Pei/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/EdkModulePkg.fpd b/EdkModulePkg/EdkModulePkg.fpd new file mode 100644 index 0000000000..c820656838 --- /dev/null +++ b/EdkModulePkg/EdkModulePkg.fpd @@ -0,0 +1,453 @@ + + + + + MdePkg + EFI/Tiano MdePkg Package + This FPD file is used for Package Level build. + 2006-04-03 13:40 + lhauch + + + dummy.fdf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PcdMaximumUnicodeStringLength + 0x00000001 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 1000000 + + + PcdMaximumAsciiStringLength + 0x00000002 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 1000000 + + + PcdMaximumLinkedListLength + 0x00000003 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 1000000 + + + PcdSpinLockTimeout + 0x00000004 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 10000000 + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 0x0f + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 0x80000000 + + + PcdReportStatusCodePropertyMask + 0x00000007 + UINT8 + false + false + false + false + false + 0x00 + 0x00 + 1 + 0 + L"" + 0 + 0 + 0x07 + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + false + false + false + false + false + 0 + 0 + 1 + 0 + L"" + 0 + 0 + 0xAF + + + PcdPerformanceLibraryPropertyMask + 0x00000009 + UINT8 + false + false + false + false + false + 0x00 + 0x00 + 1 + 0 + L"" + 0 + 0 + 0 + + + + + + diff --git a/EdkModulePkg/EdkModulePkg.spd b/EdkModulePkg/EdkModulePkg.spd new file mode 100644 index 0000000000..f2bdfa0401 --- /dev/null +++ b/EdkModulePkg/EdkModulePkg.spd @@ -0,0 +1,655 @@ + + + + + EdkModulePkg + 0xb6ec423c, 0x21d2, 0x490d, 0x85, 0xc6, 0xdd, 0x58, 0x64, 0xea, 0xa6, 0x74 + 0 + Edk Module Package Reference Implementations + This Module provides standard reference information for EFI/Tiano implementations. + Copyright (c) 2006, 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. + + 2006-02-21 17:43 + 2006-03-19 16:26 + http://www.TianoCore.org + SOURCE + true + false + + + + CustomDecompressLib + Include/Library/CustomDecompressLib.h + + + EdkBsDataHubStatusCodeLib + Include/Library/EdkBsDataHubStatusCodeLib.h + + + EdkDxeSalLib + Include/Library/EdkDxeSalLib.h + + + EdkFvbServiceLib + Include/Library/EdkFvbServiceLib.h + + + EdkGraphicsLib + Include/Library/EdkGraphicsLib.h + + + EdkIfrSupportLib + Include/Library/EdkIfrSupportLib.h + + + EdkMemoryStatusCodeLib + Include/Library/EdkMemoryStatusCodeLib.h + + + EdkPeCoffLoaderLib + Include/Library/EdkPeCoffLoaderLib.h + + + EdkPeCoffLoaderX64Lib + Include/Library/EdkPeCoffLoaderX64Lib.h + + + EdkRtMemoryStatusCodeLib + Include/Library/EdkRtMemoryStatusCodeLib.h + + + EdkRtPlatformStatusCodeLib + Include/Library/EdkRtPlatformStatusCodeLib.h + + + EdkScsiLib + Include/Library/EdkScsiLib.h + + + EdkUsbLib + Include/Library/EdkUsbLib.h + + + TianoDecompressLib + Include/Library/TianoDecompressLib.h + + + + + Application/HelloWorld/HelloWorld.msa + + + Bus/Pci/AtapiPassThru/Dxe/AtapiPassThru.msa + + + Bus/Pci/CirrusLogic/Dxe/CirrusLogic5430.msa + + + Bus/Pci/IdeBus/Dxe/idebus.msa + + + Bus/Pci/IdeBus/Dxe/idebusLite.msa + + + Bus/Pci/PciBus/Dxe/LightPciBus.msa + + + Bus/Pci/PciBus/Dxe/PciBus.msa + + + Bus/Pci/PciBus/Dxe/PciBusLite.msa + + + Bus/Pci/Uhci/Dxe/Uhci.msa + + + Bus/Pci/Undi/RuntimeDxe/Undi.msa + + + Bus/Scsi/ScsiBus/Dxe/ScsiBus.msa + + + Bus/Scsi/ScsiDisk/Dxe/ScsiDisk.msa + + + Bus/Usb/UsbBot/Dxe/UsbBot.msa + + + Bus/Usb/UsbBus/Dxe/UsbBus.msa + + + Bus/Usb/UsbCbi/Dxe/Cbi0/UsbCbi0.msa + + + Bus/Usb/UsbCbi/Dxe/Cbi1/UsbCbi1.msa + + + Bus/Usb/UsbKb/Dxe/UsbKb.msa + + + Bus/Usb/UsbMassStorage/Dxe/UsbMassStorage.msa + + + Bus/Usb/UsbMouse/Dxe/UsbMouse.msa + + + Core/Dxe/DxeMain.msa + + + Core/DxeIplPeim/DxeIpl.msa + + + Core/Pei/PeiMain.msa + + + Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.msa + + + Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.msa + + + Library/DxeCoreCustomDecompressLibFromHob/DxeCoreCustomDecompressLibFromHob.msa + + + Library/DxeCorePerformanceLib/DxeCorePerformanceLib.msa + + + Library/DxeCoreTianoDecompressLibFromHob/DxeCoreTianoDecompressLibFromHob.msa + + + Library/DxeCoreUefiDecompressLibFromHob/DxeCoreUefiDecompressLibFromHob.msa + + + Library/EdkDxeDebugLibReportStatusCode/EdkDxeDebugLibReportStatusCode.msa + + + Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.msa + + + Library/EdkDxePerformanceLib/EdkDxePerformanceLib.msa + + + Library/EdkDxePrintLib/EdkDxePrintLib.msa + + + Library/EdkDxeRuntimeDriverLib/EdkDxeRuntimeDriverLib.msa + + + Library/EdkDxeSalLib/EdkDxeSalLib.msa + + + Library/EdkFvbServiceLib/EdkFvbServiceLib.msa + + + Library/EdkGraphicsLib/EdkGraphicsLib.msa + + + Library/EdkIfrSupportLib/EdkIfrSupportLib.msa + + + Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.msa + + + Library/EdkNullCustomizedDecompressLib/EdkNullCustomizedDecompressLib.msa + + + Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.msa + + + Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.msa + + + Library/EdkPeiPerformanceLib/EdkPeiPerformanceLib.msa + + + Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.msa + + + Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/RtMemoryStatusCode.msa + + + Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/RtPlatformStatusCode.msa + + + Library/EdkScsiLib/EdkScsiLib.msa + + + Library/EdkUefiDebugLibConOut/EdkUefiDebugLibConOut.msa + + + Library/EdkUefiDebugLibStdErr/EdkUefiDebugLibStdErr.msa + + + Library/EdkUsbLib/EdkUsbLib.msa + + + Universal/Console/ConSplitter/Dxe/ConSplitter.msa + + + Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.msa + + + Universal/Console/Terminal/Dxe/Terminal.msa + + + Universal/DataHub/DataHub/Dxe/DataHub.msa + + + Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.msa + + + Universal/Debugger/Debugport/Dxe/DebugPort.msa + + + Universal/DebugSupport/Dxe/DebugSupport.msa + + + Universal/Disk/DiskIo/Dxe/DiskIo.msa + + + Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.msa + + + Universal/Disk/Partition/Dxe/Partition.msa + + + Universal/Disk/UnicodeCollation/English/Dxe/English.msa + + + Universal/Ebc/Dxe/Ebc.msa + + + Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa + + + Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa + + + Universal/GenericMemoryTest/Dxe/NullMemoryTest.msa + + + Universal/GenericMemoryTest/Pei/BaseMemoryTest.msa + + + Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.msa + + + Universal/Network/PxeBc/Dxe/BC.msa + + + Universal/Network/PxeDhcp4/Dxe/Dhcp4.msa + + + Universal/Network/Snp32_64/Dxe/SNP.msa + + + Universal/Runtime/RuntimeDxe/Runtime.msa + + + Universal/Security/SecurityStub/Dxe/SecurityStub.msa + + + Universal/StatusCode/RuntimeDxe/StatusCode.msa + + + Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.msa + + + Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.msa + + + Universal/UserInterface/SetupBrowser/Dxe/SetupBrowser.msa + + + Universal/Variable/Pei/Variable.msa + + + Universal/EmuVariable/RuntimeDxe/EmuVariable.msa + + + Universal/Variable/RuntimeDxe/Variable.msa + + + Universal/WatchdogTimer/Dxe/WatchDogTimer.msa + + + + Include/EdkPeim.h + Include/EdkPeiCore.h + Include/EdkPeim.h + Include/EdkDxeCore.h + Include/EdkDxe.h + Include/EdkDxe.h + Include/EdkDxe.h + Include/EdkDxe.h + Include/EdkDxe.h + + + + gEfiPeiPeCoffLoaderGuid + 0xd8117cff, 0x94a6, 0x11d4, 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiFlashMapHobGuid + 0xb091e7d2, 0x5a0, 0x4198, 0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 + + + gEfiStatusCodeDataTypeStringGuid + 0x92D11080, 0x496F, 0x4D95, 0xBE, 0x7E, 0x03, 0x74, 0x88, 0x38, 0x2B, 0x0A + + + gEfiStatusCodeDataTypeDebugGuid + 0x9A4E9246, 0xD553, 0x11D5, 0x87, 0xE2, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xb9 + + + gEfiStatusCodeDataTypeAssertGuid + 0xDA571595, 0x4D99, 0x487C, 0x82, 0x7C, 0x26, 0x22, 0x67, 0x7D, 0x33, 0x07 + + + gEfiStatusCodeDataTypeExceptionHandlerGuid + 0x3BC2BD12, 0xAD2E, 0x11D5, 0x87, 0xDD, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xB9 + + + gEfiStatusCodeDataTypeErrorGuid + 0xAB359CE3, 0x99B3, 0xAE18, 0xC8, 0x9D, 0x95, 0xD3, 0xB0, 0x72, 0xE1, 0x9B + + + gEfiStatusCodeDataTypeProgressCodeGuid + 0xA356AB39, 0x35C4, 0x35DA, 0xB3, 0x7A, 0xF8, 0xEA, 0x9E, 0x8B, 0x36, 0xA3 + + + gEfiStatusCodeSpecificDataGuid + 0x335984bd, 0xe805, 0x409a, 0xb8, 0xf8, 0xd2, 0x7e, 0xce, 0x5f, 0xf7, 0xa6 + + + gEfiSystemNvDataHobGuid + 0xd6e5092d, 0xc7b2, 0x4872, 0xaf, 0x66, 0xfd, 0xc0, 0xe6, 0xf9, 0x5e, 0x78 + + + gEfiSystemNvDataFvGuid + 0xfff12b8d, 0x7696, 0x4c8b, 0xa9, 0x85, 0x27, 0x47, 0x07, 0x5b, 0x4f, 0x50 + + + gEfiDiskInfoIdeInterfaceGuid + 0x5e948fe3, 0x26d3, 0x42b5, 0xaf, 0x17, 0x61, 0x02, 0x87, 0x18, 0x8d, 0xec + + + gEfiDiskInfoScsiInterfaceGuid + 0x8f74baa, 0xea36, 0x41d9, 0x95, 0x21, 0x21, 0xa7, 0x0f, 0x87, 0x80, 0xbc + + + gEfiDiskInfoUsbInterfaceGuid + 0xcb871572, 0xc11a, 0x47b5, 0xb4, 0x92, 0x67, 0x5e, 0xaf, 0xa7, 0x77, 0x27 + + + gEfiAlternateFvBlockGuid + 0xf496922d, 0x172f, 0x4bbc, 0xa1, 0xeb, 0x0e, 0xeb, 0x94, 0x9c, 0x34, 0x86 + + + gEfiConsoleInDeviceGuid + 0xd3b36f2b, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiConsoleOutDeviceGuid + 0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiStandardErrorDeviceGuid + 0xd3b36f2d, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiHotPlugDeviceGuid + 0x220ac432, 0x1d43, 0x49e5, 0xa7, 0x4f, 0x4c, 0x9d, 0xa6, 0x7a, 0xd2, 0x3b + + + gEfiPrimaryStandardErrorDeviceGuid + 0x5a68191b, 0x9b97, 0x4752, 0x99, 0x46, 0xe3, 0x6a, 0x5d, 0xa9, 0x42, 0xb1 + + + gEfiPrimaryConsoleInDeviceGuid + 0xe451dcbe, 0x96a1, 0x4729, 0xa5, 0xcf, 0x6b, 0x9c, 0x2c, 0xff, 0x47, 0xfd + + + gEfiPrimaryConsoleOutDeviceGuid + 0x62bdf38a, 0xe3d5, 0x492c, 0x95, 0x0c, 0x23, 0xa7, 0xf6, 0x6e, 0x67, 0x2e + + + gEfiDefaultBmpLogoGuid + 0x7BB28B99, 0x61BB, 0x11d5, 0x9A, 0x5D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D + + + gEfiBootStateGuid + 0x60b5e939, 0xfcf, 0x4227, 0xba, 0x83, 0x6b, 0xbe, 0xd4, 0x5b, 0xc0, 0xe3 + + + gEfiShellFileGuid + 0xc57ad6b7, 0x0515, 0x40a8, 0x9d, 0x21, 0x55, 0x16, 0x52, 0x85, 0x4e, 0x37 + + + gEfiMiniShellFileGuid + 0x86ad232b, 0xd33a, 0x465c, 0xbf, 0x5f, 0x41, 0x37, 0x0b, 0xa9, 0x2f, 0xe2 + + + gEfiStatusCodeGuid + 0xd083e94c, 0x6560, 0x42e4, 0xb6, 0xd4, 0x2d, 0xf7, 0x5a, 0xdf, 0x6a, 0x2a + + + gEfiPciOptionRomTableGuid + 0x7462660f, 0x1cbd, 0x48da, 0xad, 0x11, 0x91, 0x71, 0x79, 0x13, 0x83, 0x1c + + + gEfiPciHotplugDeviceGuid + 0x0b280816, 0x52e7, 0x4e51, 0xaa, 0x57, 0x11, 0xbd, 0x41, 0xcb, 0xef, 0xc3 + + + gEfiMemoryTypeInformationGuid + 0x4c19049f, 0x4137, 0x4dd3, 0x9c, 0x10, 0x8b, 0x97, 0xa8, 0x3f, 0xfd, 0xfa + + + gEfiCapsuleVendorGuid + 0x711C703F, 0xC285, 0x4B10, 0xA3, 0xB0, 0x36, 0xEC, 0xBD, 0x3C, 0x8B, 0xE2 + + + gEfiCompatibleMemoryTestedGuid + 0x64c475ef, 0x344b, 0x492c, 0x93, 0xad, 0xab, 0x9e, 0xb4, 0x39, 0x50, 0x4 + + + + + gEfiCustomizedDecompressProtocolGuid + 0x9a44198e, 0xa4a2, 0x44e6, 0x8a, 0x1f, 0x39, 0xbe, 0xfd, 0xac, 0x89, 0x6f + + + gEfiDebugLevelProtocolGuid + 0x8d4c62e6, 0xcd98, 0x4e1d, 0xad, 0x6e, 0x48, 0xbb, 0x50, 0xd2, 0x9f, 0xf7 + + + gEfiTianoDecompressProtocolGuid + 0xe84cf29c, 0x191f, 0x4eae, 0x96, 0xe1, 0xf4, 0x6a, 0xec, 0xea, 0xea, 0x0b + + + gEfiLoadPeImageProtocolGuid + 0x5cb5c776, 0x60d5, 0x45ee, 0x88, 0x3c, 0x45, 0x27, 0x08, 0xcd, 0x74, 0x3f + + + gEfiPrintProtocolGuid + 0xdf2d868e, 0x32fc, 0x4cf0, 0x8e, 0x6b, 0xff, 0xd9, 0x5d, 0x13, 0x43, 0xd0 + + + gEfiGenericMemTestProtocolGuid + 0x309de7f1, 0x7f5e, 0x4ace, 0xb4, 0x9c, 0x53, 0x1b, 0xe5, 0xaa, 0x95, 0xef + + + gEfiDiskInfoProtocolGuid + 0xd432a67f, 0x14dc, 0x484b, 0xb3, 0xbb, 0x3f, 0x02, 0x91, 0x84, 0x93, 0x27 + + + gEfiFvbExtensionProtocolGuid + 0x53a4c71b, 0xb581, 0x4170, 0x91, 0xb3, 0x8d, 0xb8, 0x7a, 0x4b, 0x5c, 0x46 + + + gEfiFaultTolerantWriteLiteProtocolGuid + 0x3f557189, 0x8dae, 0x45ae, 0xa0, 0xb3, 0x2b, 0x99, 0xca, 0x7a, 0xa7, 0xa0 + + + gEfiConsoleControlProtocolGuid + 0xf42f7782, 0x12e, 0x4c12, 0x99, 0x56, 0x49, 0xf9, 0x43, 0x04, 0xf7, 0x21 + + + gEfiOEMBadgingProtocolGuid + 0x170e13c0, 0xbf1b, 0x4218, 0x87, 0x1d, 0x2a, 0xbd, 0xc6, 0xf8, 0x87, 0xbc + + + gEfiUgaSplashProtocolGuid + 0xa45b3a0d, 0x2e55, 0x4c03, 0xad, 0x9c, 0x27, 0xd4, 0x82, 0x0b, 0x50, 0x7e + + + gEfiAcpiS3SaveProtocolGuid + 0x125f2de1, 0xfb85, 0x440c, 0xa5, 0x4c, 0x4d, 0x99, 0x35, 0x8a, 0x8d, 0x38 + + + gEfiPerformanceProtocolGuid + 0xFFECFFFF, 0x923C, 0x14d2, 0x9E, 0x3F, 0x22, 0xA0, 0xC9, 0x69, 0x56, 0x3B + + + gEfiPxeDhcp4ProtocolGuid + 0x03c4e624, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x29, 0x3f, 0xc1, 0x4d + + + gEfiPxeDhcp4CallbackProtocolGuid + 0xc1544c01, 0x92a4, 0x4198, 0x8a, 0x84, 0x77, 0x85, 0x83, 0xc2, 0x36, 0x21 + + + gEfiUgaIoProtocolGuid + 0x61a4d49e, 0x6f68, 0x4f1b, 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0x0b, 0x07, 0xa2 + + + gEfiDebugAssertProtocolGuid + 0xbe499c92, 0x7d4b, 0x11d4, 0xbc, 0xee, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiUsbAtapiProtocolGuid + 0x2B2F68DA, 0x0CD2, 0x44cf, 0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 + + + gEfiPciHotPlugRequestProtocolGuid + 0x19cb87ab, 0x2cb9, 0x4665, 0x83, 0x60, 0xdd, 0xcf, 0x60, 0x54, 0xf7, 0x9d + + + gEfiExtendedSalBootServiceProtocolGuid + 0xde0ee9a4, 0x3c7a, 0x44f2, 0xb7, 0x8b, 0xe3, 0xcc, 0xd6, 0x9c, 0x3a, 0xf7 + + + gEfiExtendedSalVariableServicesProtocolGuid + 0x4ecb6c53, 0xc641, 0x4370, 0x8c, 0xb2, 0x3b, 0x0e, 0x49, 0x6e, 0x83, 0x78 + + + gEfiExtendedSalStatusCodeServicesProtocolGuid + 0x00dbd91d, 0x55e9, 0x420f, 0x96, 0x39, 0x5e, 0x9f, 0x84, 0x37, 0xb4, 0x4f + + + gEfiIsaIoProtocolGuid + 0x7ee2bd44, 0x3da0, 0x11d4, 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiIsaAcpiProtocolGuid + 0x64a892dc, 0x5561, 0x4536, 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55 + + + + + gPeiInMemoryGuid + 0x643b8786, 0xb417, 0x48d2, 0x8f, 0x5e, 0x78, 0x19, 0x93, 0x1c, 0xae, 0xd8 + + + gPeiFlashMapPpiGuid + 0xf34c2fa0, 0xde88, 0x4270, 0x84, 0x14, 0x96, 0x12, 0x22, 0xf4, 0x52, 0x1c + + + gPeiBaseMemoryTestPpiGuid + 0xb6ec423c, 0x21d2, 0x490d, 0x85, 0xc6, 0xdd, 0x58, 0x64, 0xea, 0xa6, 0x74 + + + gPeiStatusCodeMemoryPpiGuid + 0x26f8ab01, 0xd3cd, 0x489c, 0x98, 0x4f, 0xdf, 0xde, 0xf7, 0x68, 0x39, 0x5b + + + + + PcdMaximumUnicodeStringLength + 0x00000001 + UINT32 + 1000000 + + + PcdMaximumAsciiStringLength + 0x00000002 + UINT32 + 1000000 + + + PcdMaximumLinkedListLength + 0x00000003 + UINT32 + 1000000 + + + PcdSpinLockTimeout + 0x00000004 + UINT32 + 10000000 + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + 0x0f + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + 0x80000000 + + + PcdReportStatusCodePropertyMask + 0x00000007 + UINT8 + 0x07 + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + 0xAF + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + 0xAF + + + PcdPerformanceLibraryPropertyMask + 0x00000009 + UINT8 + 0 + + + diff --git a/EdkModulePkg/Include/Common/CapsuleName.h b/EdkModulePkg/Include/Common/CapsuleName.h new file mode 100644 index 0000000000..651fbe3889 --- /dev/null +++ b/EdkModulePkg/Include/Common/CapsuleName.h @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CapsuleName.h + +Abstract: + +--*/ + +#ifndef _CAPSULE_NAME_H +#define _CAPSULE_NAME_H + +// +// If capsule data is passed via a variable, then this name should be used. +// +#define EFI_CAPSULE_VARIABLE_NAME L"CapsuleUpdateData" + +#endif diff --git a/EdkModulePkg/Include/Common/DecompressLibraryHob.h b/EdkModulePkg/Include/Common/DecompressLibraryHob.h new file mode 100644 index 0000000000..ee7b8a2ea1 --- /dev/null +++ b/EdkModulePkg/Include/Common/DecompressLibraryHob.h @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DecompressLibraryHob.h + +Abstract: + + Declaration of HOB that is used to pass decompressor library functions from PEI to DXE + +--*/ + +#ifndef __DECOMPRESS_LIBRARY_HOB_H__ +#define __DECOMPRESS_LIBRARY_HOB_H__ + +typedef +RETURN_STATUS +(EFIAPI *DECOMPRESS_LIBRARY_GET_INFO) ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +typedef +RETURN_STATUS +(EFIAPI *DECOMPRESS_LIBRARY_DECOMPRESS) ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ); + +typedef struct { + DECOMPRESS_LIBRARY_GET_INFO GetInfo; + DECOMPRESS_LIBRARY_DECOMPRESS Decompress; +} DECOMPRESS_LIBRARY; + +#endif diff --git a/EdkModulePkg/Include/Common/FlashMap.h b/EdkModulePkg/Include/Common/FlashMap.h new file mode 100644 index 0000000000..829fa2ddd6 --- /dev/null +++ b/EdkModulePkg/Include/Common/FlashMap.h @@ -0,0 +1,110 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FlashMap.h + +Abstract: + + FlashMap PPI defined in Tiano + + This code abstracts FlashMap access + +--*/ + +#ifndef __COMMON_FLASHMAP_H__ +#define __COMMON_FLASHMAP_H__ + +#include +// +// Definition for flash map GUIDed HOBs +// +typedef UINT32 EFI_FLASH_AREA_ATTRIBUTES; + +#define EFI_FLASH_AREA_FV 0x0001 +#define EFI_FLASH_AREA_SUBFV 0x0002 +#define EFI_FLASH_AREA_MEMMAPPED_FV 0x0004 +#define EFI_FLASH_AREA_REQUIRED 0x0008 +#define EFI_FLASH_AREA_CORRUPT 0x0010 + +typedef UINT8 EFI_FLASH_AREA_TYPE; + +#define EFI_FLASH_AREA_RECOVERY_BIOS 0x0 // Recovery code +#define EFI_FLASH_AREA_MAIN_BIOS 0x1 // Regular BIOS code +#define EFI_FLASH_AREA_PAL_B 0x2 // PAL-B +#define EFI_FLASH_AREA_RESERVED_03 0x3 // Reserved for backwards compatibility +#define EFI_FLASH_AREA_RESERVED_04 0x4 // Reserved for backwards compatibility +#define EFI_FLASH_AREA_DMI_FRU 0x5 // DMI FRU information +#define EFI_FLASH_AREA_OEM_BINARY 0x6 // OEM Binary Code/data +#define EFI_FLASH_AREA_RESERVED_07 0x7 // Reserved for backwards compatibility +#define EFI_FLASH_AREA_RESERVED_08 0x8 // Reserved for backwards compatibility +#define EFI_FLASH_AREA_RESERVED_09 0x9 // Reserved for backwards compatibility +#define EFI_FLASH_AREA_RESERVED_0A 0x0a // Reserved for backwards compatibility +#define EFI_FLASH_AREA_EFI_VARIABLES 0x0b // EFI variables +#define EFI_FLASH_AREA_MCA_LOG 0x0c // MCA error log +#define EFI_FLASH_AREA_SMBIOS_LOG 0x0d // SMBIOS error log +#define EFI_FLASH_AREA_FTW_BACKUP 0x0e // A backup block during FTW operations +#define EFI_FLASH_AREA_FTW_STATE 0x0f // State information during FTW operations +#define EFI_FLASH_AREA_UNUSED 0x0fd // Not used +#define EFI_FLASH_AREA_GUID_DEFINED 0x0fe // Usage defined by a GUID +#pragma pack(1) +// +// An individual sub-area Entry. +// A single flash area may consist of more than one sub-area. +// +typedef struct { + EFI_FLASH_AREA_ATTRIBUTES Attributes; + UINT32 Reserved; + EFI_PHYSICAL_ADDRESS Base; + EFI_PHYSICAL_ADDRESS Length; + EFI_GUID FileSystem; +} EFI_FLASH_SUBAREA_ENTRY; + +typedef struct { + UINT8 Reserved[3]; + EFI_FLASH_AREA_TYPE AreaType; + EFI_GUID AreaTypeGuid; + UINT32 NumEntries; + EFI_FLASH_SUBAREA_ENTRY Entries[1]; +} EFI_FLASH_MAP_ENTRY_DATA; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_GUID Name; + UINT8 Reserved[3]; + EFI_FLASH_AREA_TYPE AreaType; + EFI_GUID AreaTypeGuid; + UINT32 NumEntries; + EFI_FLASH_SUBAREA_ENTRY Entries[1]; +} EFI_HOB_FLASH_MAP_ENTRY_TYPE; + +// +// Internal definitions +// +typedef struct { + UINT8 Reserved[3]; + EFI_FLASH_AREA_TYPE AreaType; + EFI_GUID AreaTypeGuid; + UINT32 NumberOfEntries; + EFI_FLASH_SUBAREA_ENTRY SubAreaData; +} EFI_FLASH_AREA_HOB_DATA; + +typedef struct { + UINTN Base; + UINTN Length; + EFI_FLASH_AREA_ATTRIBUTES Attributes; + EFI_FLASH_AREA_TYPE AreaType; +} EFI_FLASH_AREA_DATA; + +#pragma pack() + +#endif diff --git a/EdkModulePkg/Include/Common/Variable.h b/EdkModulePkg/Include/Common/Variable.h new file mode 100644 index 0000000000..e75adafc12 --- /dev/null +++ b/EdkModulePkg/Include/Common/Variable.h @@ -0,0 +1,78 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EfiVariable.h + +Abstract: + + Header file for EFI Variable Services + +--*/ + +#ifndef _EFI_VARIABLE_H_ +#define _EFI_VARIABLE_H_ + +#define VARIABLE_STORE_SIGNATURE EFI_SIGNATURE_32 ('$', 'V', 'S', 'S') + +#define MAX_VARIABLE_SIZE 1024 + +#define VARIABLE_DATA 0x55AA + +// +// Variable Store Header flags +// +#define VARIABLE_STORE_FORMATTED 0x5a +#define VARIABLE_STORE_HEALTHY 0xfe + +// +// Variable Store Status +// +typedef enum { + EfiRaw, + EfiValid, + EfiInvalid, + EfiUnknown +} VARIABLE_STORE_STATUS; + +// +// Variable State flags +// +#define VAR_IN_DELETED_TRANSITION 0xfe // Variable is in obsolete transistion +#define VAR_DELETED 0xfd // Variable is obsolete +#define VAR_ADDED 0x7f // Variable has been completely added +#define IS_VARIABLE_STATE(_c, _Mask) (BOOLEAN) (((~_c) & (~_Mask)) != 0) + +#pragma pack(1) + +typedef struct { + UINT32 Signature; + UINT32 Size; + UINT8 Format; + UINT8 State; + UINT16 Reserved; + UINT32 Reserved1; +} VARIABLE_STORE_HEADER; + +typedef struct { + UINT16 StartId; + UINT8 State; + UINT8 Reserved; + UINT32 Attributes; + UINT32 NameSize; + UINT32 DataSize; + EFI_GUID VendorGuid; +} VARIABLE_HEADER; + +#pragma pack() + +#endif // _EFI_VARIABLE_H_ diff --git a/EdkModulePkg/Include/Common/WorkingBlockHeader.h b/EdkModulePkg/Include/Common/WorkingBlockHeader.h new file mode 100644 index 0000000000..235b740e83 --- /dev/null +++ b/EdkModulePkg/Include/Common/WorkingBlockHeader.h @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EfiWorkingBlockHeader.h + +Abstract: + + Defines data structure that is the headers found at the runtime + updatable firmware volumes, such as the FileSystemGuid of the + working block, the header structure of the variable block, FTW + working block, or event log block. + +--*/ + +#ifndef _EFI_WORKING_BLOCK_HEADER_H_ +#define _EFI_WORKING_BLOCK_HEADER_H_ + +// +// EFI Fault tolerant working block header +// The header is immediately followed by the write queue. +// +typedef struct { + EFI_GUID Signature; + UINT32 Crc; + UINT32 WorkingBlockValid : 1; + UINT32 WorkingBlockInvalid : 1; +#define WORKING_BLOCK_VALID 0x1 +#define WORKING_BLOCK_INVALID 0x2 + UINT32 Reserved : 6; + UINT8 Reserved3[3]; + UINTN WriteQueueSize; + // + // UINT8 WriteQueue[WriteQueueSize]; + // +} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER; + +#endif diff --git a/EdkModulePkg/Include/EdkDxe.h b/EdkModulePkg/Include/EdkDxe.h new file mode 100644 index 0000000000..775c52e84c --- /dev/null +++ b/EdkModulePkg/Include/EdkDxe.h @@ -0,0 +1,95 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + EdkDxe.h + +Abstract: + This file defines the base package surface area for writting a PEIM + + Things defined in the Tiano specification go in DxeCis.h. + + Dxe.h contains build environment and library information needed to build + a basic Dxe driver. This file must match the "base package" definition of + how to write a Dxe driver. + +--*/ + +#ifndef __EDK_DXE_H__ +#define __EDK_DXE_H__ + +// +#include +// BUGBUG: We must include this lib here due to ordering issues +// +#include +#include + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if ((EDK_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000)) +// +// Tiano8.5 Module use ScsiPassThru protocol together with the original ScsiIo protocol +// In UEFI2.0, Module use ScsiPassThruExt Protocol with new UEFI2.0 ScsiIo protocol +// +#include +#endif + +#endif diff --git a/EdkModulePkg/Include/EdkDxeCore.h b/EdkModulePkg/Include/EdkDxeCore.h new file mode 100644 index 0000000000..d1b4ca77e3 --- /dev/null +++ b/EdkModulePkg/Include/EdkDxeCore.h @@ -0,0 +1,53 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + EdkDxe.h + +Abstract: + This file defines the base package surface area for writting a PEIM + + Things defined in the Tiano specification go in DxeCis.h. + + Dxe.h contains build environment and library information needed to build + a basic Dxe driver. This file must match the "base package" definition of + how to write a Dxe driver. + +--*/ + +#ifndef __EDK_DXE_CORE_H__ +#define __EDK_DXE_CORE_H__ + +// +// BUGBUG: We must include this lib here due to ordering issues +// +#include +#include + +// +// BUGBUG: Performance related protocol and Guid. +// They are Tiano-private, but are required for DxeCore +// +#include +#include +// +// BUGBUG: Do these really belomg here? +// +#include +#include + +#include +#include +#include +#include +#include + +#endif diff --git a/EdkModulePkg/Include/EdkDxeDepex.h b/EdkModulePkg/Include/EdkDxeDepex.h new file mode 100644 index 0000000000..1ce8be1832 --- /dev/null +++ b/EdkModulePkg/Include/EdkDxeDepex.h @@ -0,0 +1,62 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + EdkDxeDepex.h + +Abstract: + This include file is only used in *.DXS files. Do not use this + include file in normal DXE code. + + Depex - Dependency Expresion + + The BNF grammar is thus: + ::= before GUID + | after GUID + | SOR + | + ::= and + | or + | + ::= not + | + ::= + | + | + | + ::= true + | false + ::= push GUID + ::= end + +--*/ + +#ifndef __EDK_DXE_DEPEX_H__ +#define __EDK_DXE_DEPEX_H__ + +#include + +// +// The Depex grammer needs the following strings so we must undo +// any pre-processor redefinitions +// +#undef DEPENDENCY_START +#undef BEFORE +#undef AFTER +#undef SOR +#undef AND +#undef OR +#undef NOT +#undef TRUE +#undef FALSE +#undef DEPENDENCY_END + +#endif diff --git a/EdkModulePkg/Include/EdkPeiCore.h b/EdkModulePkg/Include/EdkPeiCore.h new file mode 100644 index 0000000000..4e07efb01b --- /dev/null +++ b/EdkModulePkg/Include/EdkPeiCore.h @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + EdkDxe.h + +Abstract: + This file defines the base package surface area for writting a PEIM + + Things defined in the Tiano specification go in DxeCis.h. + + Dxe.h contains build environment and library information needed to build + a basic Dxe driver. This file must match the "base package" definition of + how to write a Dxe driver. + +--*/ + +#ifndef __EDK_PEI_CORE_H__ +#define __EDK_PEI_CORE_H__ + +// +// BUGBUG: We must include this lib here due to ordering issues +// +#include + +#include + +// +// BUGBUG: Performance related Guid. +// It is Tiano-private, but is required for PeiCore +// +#include + +#endif diff --git a/EdkModulePkg/Include/EdkPeim.h b/EdkModulePkg/Include/EdkPeim.h new file mode 100644 index 0000000000..5da04e555e --- /dev/null +++ b/EdkModulePkg/Include/EdkPeim.h @@ -0,0 +1,58 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EdkPeim.h + +Abstract: + This file defines the base package surface area for writting a PEIM + + Things defined in the PEI CIS specification go in PeiCis.h. + + EdkPeim.h contains build environment and library information needed to build + a basic PEIM that needs Tiano specific definitiosn. T + + Currently we just add in some extra PPI and GUID definitions + +--*/ + +#ifndef __EDK_PEIM_H__ +#define __EDK_PEIM_H__ + +// +#include +#include +// BUGBUG: We must include this lib here due to ordering issues +// +#include + +// +// BUGBUG: Performance related Guid. +// It is Tiano-private, but is required for PeiCore +// +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +#include + +#endif diff --git a/EdkModulePkg/Include/EdkPeimDepex.h b/EdkModulePkg/Include/EdkPeimDepex.h new file mode 100644 index 0000000000..0b5059906e --- /dev/null +++ b/EdkModulePkg/Include/EdkPeimDepex.h @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + EdkPeimDepex.h + +Abstract: + This include file is only used in *.DXS files. Do not use this + include file in normal Peim code. + + Depex - Dependency Expresion + + The BNF grammar is thus: + ::= + ::= and + | or + | + ::= not + | + ::= + | + | + | + ::= true + | false + ::= push GUID + ::= end + +--*/ + +#ifndef __EDK_PEIM_DEPEX_H__ +#define __EDK_PEIM_DEPEX_H__ + +#include + +// +// The Depex grammer needs the following strings so we must undo +// any pre-processor redefinitions +// +#undef DEPENDENCY_START +#undef AND +#undef OR +#undef NOT +#undef TRUE +#undef FALSE +#undef DEPENDENCY_END + +#endif diff --git a/EdkModulePkg/Include/Guid/AlternateFvBlock.h b/EdkModulePkg/Include/Guid/AlternateFvBlock.h new file mode 100644 index 0000000000..e3a789a4d2 --- /dev/null +++ b/EdkModulePkg/Include/Guid/AlternateFvBlock.h @@ -0,0 +1,32 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + AlternateFvBlock.h + +Abstract: + + Tiano Guid used to define the Alternate Firmware Volume Block Guid. + +--*/ + +#ifndef _ALT_FVB_GUID_H +#define _ALT_FVB_GUID_H + +#define EFI_ALTERNATE_FV_BLOCK_GUID \ + { \ + 0xf496922d, 0x172f, 0x4bbc, {0xa1, 0xeb, 0xe, 0xeb, 0x94, 0x9c, 0x34, 0x86 } \ + } + +extern EFI_GUID gEfiAlternateFvBlockGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/Bmp.h b/EdkModulePkg/Include/Guid/Bmp.h new file mode 100644 index 0000000000..7a5f5a8d8e --- /dev/null +++ b/EdkModulePkg/Include/Guid/Bmp.h @@ -0,0 +1,62 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Bmp.h + +Abstract: + +--*/ + +#ifndef _BMP_GUID_H_ +#define _BMP_GUID_H_ + + +// +// Definitions for BMP files +// +#pragma pack(1) + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} BMP_COLOR_MAP; + +typedef struct { + CHAR8 CharB; + CHAR8 CharM; + UINT32 Size; + UINT16 Reserved[2]; + UINT32 ImageOffset; + UINT32 HeaderSize; + UINT32 PixelWidth; + UINT32 PixelHeight; + UINT16 Planes; // Must be 1 + UINT16 BitPerPixel; // 1, 4, 8, or 24 + UINT32 CompressionType; + UINT32 ImageSize; // Compressed image size in bytes + UINT32 XPixelsPerMeter; + UINT32 YPixelsPerMeter; + UINT32 NumberOfColors; + UINT32 ImportantColors; +} BMP_IMAGE_HEADER; + +#pragma pack() + +#define EFI_DEFAULT_BMP_LOGO_GUID \ + {0x7BB28B99,0x61BB,0x11d5,{0x9A,0x5D,0x00,0x90,0x27,0x3F,0xC1,0x4D}} + +extern EFI_GUID gEfiDefaultBmpLogoGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/BootState.h b/EdkModulePkg/Include/Guid/BootState.h new file mode 100644 index 0000000000..2d9a0d1faf --- /dev/null +++ b/EdkModulePkg/Include/Guid/BootState.h @@ -0,0 +1,36 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BootState.h + +Abstract: + + Constants and declarations that are common accross PEI and DXE. +--*/ + +#ifndef _BOOT_STATE_H_ +#define _BOOT_STATE_H_ + +// +// BOOT STATE +// + +typedef UINT32 EFI_BOOT_STATE; + +#define BOOT_STATE_VARIABLE_NAME L"BootState" + +#define EFI_BOOT_STATE_VARIABLE_GUID \ + {0x60b5e939, 0xfcf, 0x4227, {0xba, 0x83, 0x6b, 0xbe, 0xd4, 0x5b, 0xc0, 0xe3} } + +extern EFI_GUID gEfiBootStateGuid; +#endif diff --git a/EdkModulePkg/Include/Guid/CapsuleVendor.h b/EdkModulePkg/Include/Guid/CapsuleVendor.h new file mode 100644 index 0000000000..4f5762883a --- /dev/null +++ b/EdkModulePkg/Include/Guid/CapsuleVendor.h @@ -0,0 +1,35 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CapsuleVendor.h + +Abstract: + + Capsule update Guid definitions + +--*/ + +#ifndef _EFI_CAPSULE_VENDOR_GUID_H_ +#define _EFI_CAPSULE_VENDOR_GUID_H_ + +// +// Note -- This guid is used as a vendor GUID (depending on implementation) +// for the capsule variable if the capsule pointer is passes through reset +// via a variable. +// +#define EFI_CAPSULE_VENDOR_GUID \ + { 0x711C703F, 0xC285, 0x4B10, { 0xA3, 0xB0, 0x36, 0xEC, 0xBD, 0x3C, 0x8B, 0xE2 } } + +extern EFI_GUID gEfiCapsuleVendorGuid; + +#endif // #ifndef _EFI_CAPSULE_VENDOR_GUID_H_ diff --git a/EdkModulePkg/Include/Guid/CompatibleMemoryTested.h b/EdkModulePkg/Include/Guid/CompatibleMemoryTested.h new file mode 100644 index 0000000000..645cacf93e --- /dev/null +++ b/EdkModulePkg/Include/Guid/CompatibleMemoryTested.h @@ -0,0 +1,32 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CompatibleMemoryTested.h + +Abstract: + + Tiano Guid used for all Compatible Memory Range Tested GUID. + +--*/ + +#ifndef _COMPATIBLE_MEMORY_TESTED_GUID_H_ +#define _COMPATIBLE_MEMORY_TESTED_GUID_H_ + +#define EFI_COMPATIBLE_MEMORY_TESTED_PROTOCOL_GUID \ + { \ + 0x64c475ef, 0x344b, 0x492c, 0x93, 0xad, 0xab, 0x9e, 0xb4, 0x39, 0x50, 0x4 \ + } + +extern EFI_GUID gEfiCompatibleMemoryTestedGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/ConsoleInDevice.h b/EdkModulePkg/Include/Guid/ConsoleInDevice.h new file mode 100644 index 0000000000..6e53028307 --- /dev/null +++ b/EdkModulePkg/Include/Guid/ConsoleInDevice.h @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ConsoleInDevice.h + +Abstract: + + +--*/ + +#ifndef _CONSOLE_IN_DEVICE_H_ +#define _CONSOLE_IN_DEVICE_H_ + +#define EFI_CONSOLE_IN_DEVICE_GUID \ + { 0xd3b36f2b, 0xd551, 0x11d4, {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } } + +extern EFI_GUID gEfiConsoleInDeviceGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/ConsoleOutDevice.h b/EdkModulePkg/Include/Guid/ConsoleOutDevice.h new file mode 100644 index 0000000000..691aa4167d --- /dev/null +++ b/EdkModulePkg/Include/Guid/ConsoleOutDevice.h @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ConsoleOutDevice.h + +Abstract: + + +--*/ + +#ifndef _CONSOLE_OUT_DEVICE_H_ +#define _CONSOLE_OUT_DEVICE_H_ + +#define EFI_CONSOLE_OUT_DEVICE_GUID \ + { 0xd3b36f2c, 0xd551, 0x11d4, {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } } + +extern EFI_GUID gEfiConsoleOutDeviceGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/ExtendedSalGuid.h b/EdkModulePkg/Include/Guid/ExtendedSalGuid.h new file mode 100644 index 0000000000..4a4dbee9c0 --- /dev/null +++ b/EdkModulePkg/Include/Guid/ExtendedSalGuid.h @@ -0,0 +1,279 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ExtendedSalGuid.h + +Abstract: + + +--*/ + +#ifndef _EXTENDED_SAL_GUID_H_ +#define _EXTENDED_SAL_GUID_H_ + +// +// Extended SAL Services protocol GUIDs +// + +#define EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID \ + { 0x5aea42b5, 0x31e1, 0x4515, {0xbc, 0x31, 0xb8, 0xd5, 0x25, 0x75, 0x65, 0xa6 } } + +#define EFI_EXTENDED_SAL_STALL_SERVICES_PROTOCOL_GUID \ + { 0x53a58d06, 0xac27, 0x4d8c, {0xb5, 0xe9, 0xf0, 0x8a, 0x80, 0x65, 0x41, 0x70 } } + +#define EFI_EXTENDED_SAL_LOCK_SERVICES_PROTOCOL_GUID \ + { 0x76b75c23, 0xfe4f, 0x4e17, {0xa2, 0xad, 0x1a, 0x65, 0x3d, 0xbb, 0x49, 0x4a } } + +#define EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID \ + { 0xc1a74056, 0x260e, 0x4871, {0xa0, 0x31, 0xe6, 0x45, 0xa6, 0x5b, 0x6e, 0x11 } } + +#define EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID \ + { 0x7e97a470, 0xefdb, 0x4d02, {0x8f, 0xce, 0x61, 0x90, 0xd2, 0x7b, 0xa2, 0x96 } } + +#define EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID \ + { 0x4ecb6c53, 0xc641, 0x4370, {0x8c, 0xb2, 0x3b, 0x0e, 0x49, 0x6e, 0x83, 0x78 } } + +#define EFI_EXTENDED_SAL_MTC_SERVICES_PROTOCOL_GUID \ + { 0x899afd18, 0x75e8, 0x408b, {0xa4, 0x1a, 0x6e, 0x2e, 0x7e, 0xcd, 0xf4, 0x54 } } + +#define EFI_EXTENDED_SAL_RESET_SERVICES_PROTOCOL_GUID \ + { 0x7d019990, 0x8ce1, 0x46f5, {0xa7, 0x76, 0x3c, 0x51, 0x98, 0x67, 0x6a, 0xa0 } } + +#define EFI_EXTENDED_SAL_STATUS_CODE_SERVICES_PROTOCOL_GUID \ + { 0xdbd91d, 0x55e9, 0x420f, {0x96, 0x39, 0x5e, 0x9f, 0x84, 0x37, 0xb4, 0x4f } } + +#define EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID \ + { 0xa2271df1, 0xbcbb, 0x4f1d, {0x98, 0xa9, 0x06, 0xbc, 0x17, 0x2f, 0x07, 0x1a } } + +#define EFI_EXTENDED_SAL_MP_SERVICES_PROTOCOL_GUID \ + { 0x697d81a2, 0xcf18, 0x4dc0, {0x9e, 0x0d, 0x06, 0x11, 0x3b, 0x61, 0x8a, 0x3f } } + +#define EFI_EXTENDED_SAL_PAL_SERVICES_PROTOCOL_GUID \ + { 0xe1cd9d21, 0x0fc2, 0x438d, {0x97, 0x03, 0x04, 0xe6, 0x6d, 0x96, 0x1e, 0x57 } } + +#define EFI_EXTENDED_SAL_BASE_SERVICES_PROTOCOL_GUID \ + { 0xd9e9fa06, 0x0fe0, 0x41c3, {0x96, 0xfb, 0x83, 0x42, 0x5a, 0x33, 0x94, 0xf8 } } + +#define EFI_EXTENDED_SAL_MCA_SERVICES_PROTOCOL_GUID \ + { 0x2a591128, 0x6cc7, 0x42b1, {0x8a, 0xf0, 0x58, 0x93, 0x3b, 0x68, 0x2d, 0xbb } } + +#define EFI_EXTENDED_SAL_PCI_SERVICES_PROTOCOL_GUID \ + { 0xa46b1a31, 0xad66, 0x4905, {0x92, 0xf6, 0x2b, 0x46, 0x59, 0xdc, 0x30, 0x63 } } + +#define EFI_EXTENDED_SAL_CACHE_SERVICES_PROTOCOL_GUID \ + { 0xedc9494, 0x2743, 0x4ba5, { 0x88, 0x18, 0x0a, 0xef, 0x52, 0x13, 0xf1, 0x88 } } + +#define EFI_EXTENDED_SAL_MCA_LOG_SERVICES_PROTOCOL_GUID \ + { 0xcb3fd86e, 0x38a3, 0x4c03, {0x9a, 0x5c, 0x90, 0xcf, 0xa3, 0xa2, 0xab, 0x7a } } + +#define EFI_EXTENDED_SAL_ELOG_SERVICES_PROTOCOL_GUID \ + { 0xd5e4ee5f, 0x3e0a, 0x453c, {0xa7, 0x25, 0xb6, 0x92, 0xbb, 0x6, 0x36, 0x5a } } + +#define EFI_EXTENDED_SAL_SENSOR_SERVICES_PROTOCOL_GUID \ + { 0x4a153b6e, 0x85a1, 0x4982, {0x98, 0xf4, 0x6a, 0x8c, 0xfc, 0xa4, 0xab, 0xa1 } } + +#define EFI_EXTENDED_SAL_SM_COM_LAYER_SERVICES_PROTOCOL_GUID \ + { 0x4356799, 0x81b7, 0x4e08, { 0xa3, 0x8d, 0xd9, 0x78, 0xfa, 0x47, 0xba, 0x42 } } + +#define EFI_EXTENDED_SAL_SST_GUID \ + { 0x38802700, 0x868a, 0x4b4e, {0x81, 0xd4, 0x4f, 0x1b, 0xdc, 0xcf, 0xb4, 0x6f } } + +// +// Extended Sal Proc Function IDs. +// + +// +// BugBug: These enums are name colisions waiting to happen. They should all be +// prefixed with Esal! It might be better to just make them #define, so +// they would be all caps. +// + +typedef enum { + IoRead, + IoWrite, + MemRead, + MemWrite +} EFI_EXTENDED_SAL_BASE_IO_SERVICES_FUNC_ID; + +typedef enum { + Stall +} EFI_EXTENDED_SAL_STALL_FUNC_ID; + + +typedef enum { + InitializeLockService, + AcquireLockService, + ReleaseLockService, + MaxLockServiceFunctionId +} EFI_EXTENDED_SAL_LOCK_SERVICES_FUNC_ID; + +// +// BugBug : Covert the first 3 functions into a lib functions +// and move SalRegisterPhysicalAddress to SAL BASE Class +// +typedef enum { + SetVirtualAddress, + IsVirtual, + IsEfiRuntime, + SalRegisterPhysicalAddress +} EFI_EXTENDED_SAL_VIRTUAL_SERVICES_FUNC_ID; + +typedef enum { + GetTime, + SetTime, + GetWakeupTime, + SetWakeupTime, + GetRtcFreq, + InitializeThreshold, + BumpThresholdCount, + GetThresholdCount +} EFI_EXTENDED_SAL_RTC_SERVICES_FUNC_ID; + +typedef enum { + EsalGetVariable, + EsalGetNextVariableName, + EsalSetVariable +} EFI_EXTENDED_SAL_VARIABLE_SERVICES_FUNC_ID; + +typedef enum { + GetNextHighMonotonicCount +} EFI_EXTENDED_SAL_MTC_SERVICES_FUNC_ID; + +typedef enum { + ResetSystem +} EFI_EXTENDED_SAL_RESET_SERVICES_FUNC_ID; + +typedef enum { + StatusCode +} EFI_EXTENDED_SAL_STATUS_CODE_FUNC_ID; + +typedef enum { + ReportStatusCodeService +} EFI_EXTENDED_SAL_STATUS_CODE_SERVICES_FUNC_ID; + +typedef enum { + Read, + Write, + EraseBlock, + GetVolumeAttributes, + SetVolumeAttributes, + GetPhysicalAddress, + GetBlockSize, + EraseCustomBlockRange, +} EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_FUNC_ID; + +typedef enum { + AddCpuData, + RemoveCpuData, + ModifyCpuData, + GetCpuDataByID, + GetCpuDataByIndex, + SendIpi, + CurrentProcInfo, + NumProcessors, + SetMinState, + GetMinState +} EFI_EXTENDED_SAL_MP_SERVICES_FUNC_ID; + +typedef enum { + PalProc, + SetNewPalEntry, + GetNewPalEntry +} EFI_EXTENDED_SAL_PAL_SERVICES_FUNC_ID; + +typedef enum { + SalSetVectors, + SalMcRendez, + SalMcSetParams, + EsalGetVectors, + EsalMcGetParams, + EsalMcGetMcParams, + EsalGetMcCheckinFlags, + EsalGetPlatformBaseFreq +} EFI_EXTENDED_SAL_BASE_SERVICES_FUNC_ID; + +typedef enum { + McaGetStateInfo, + McaRegisterCpu +} EFI_EXTENDED_SAL_MCA_SERVICES_FUNC_ID; + +typedef enum { + SalPciConfigRead, + SalPciConfigWrite +} EFI_EXTENDED_SAL_PCI_SERVICES_FUNC_ID; + +typedef enum { + SalCacheInit, + SalCacheFlush +} EFI_EXTENDED_SAL_CACHE_SERVICES_FUNC_ID; + +typedef enum { + SalGetStateInfo, + SalGetStateInfoSize, + SalClearStateInfo, + EsalGetStateBuffer, + EsalSaveStateBuffer +} EFI_EXTENDED_SAL_MCA_LOG_SERVICES_FUNC_ID; + +typedef enum { + SalSetEventLogData, + SalGetEventLogData, + SalEraseEventLogData, + SalActivateEventLogData +} EFI_EXTENDED_SAL_ELOG_SERVICES_FUNC_ID; + +typedef enum { + EsalGetComControllerInfo, + EsalSendComData, + EsalReceiveComData +} EFI_EXTENDED_SAL_SM_COM_LAYER_SERVICES_FUNC_ID; + +typedef enum { + SalUpdatePal +} EFI_EXTENDED_SAL_UPDATE_PAL_SERVICES_FUNC_ID; + +typedef enum { + EsalReadSensorInfo, + EsalReadSensorStatus, + EsalRearmSensor, + EsalReadSensorData +} EFI_EXTENDED_SAL_SENSOR_SERVICES_FUNC_ID; + +typedef struct { + UINT64 ProtoData; +} ESAL_GUID_DUMMY_PROTOCOL; + +extern EFI_GUID gEfiExtendedSalBaseIoServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalStallServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalLockServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalVirtualServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalRtcServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalVariableServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalMtcServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalResetServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalStatusCodeServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalFvBlockServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalMpServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalPalServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalBaseServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalMcaServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalPciServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalCacheServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalMcaLogServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalElogServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalSensorServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalSmComLayerServicesProtocolGuid; +extern EFI_GUID gEfiExtendedSalSstGuid; + + +#endif diff --git a/EdkModulePkg/Include/Guid/FlashMapHob.h b/EdkModulePkg/Include/Guid/FlashMapHob.h new file mode 100644 index 0000000000..a9e9b6736f --- /dev/null +++ b/EdkModulePkg/Include/Guid/FlashMapHob.h @@ -0,0 +1,33 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FlashMapHob.h + +Abstract: + + GUID used for Flash Map HOB entries in the HOB list. + +--*/ + +#ifndef _FLASH_MAP_HOB_GUID_H_ +#define _FLASH_MAP_HOB_GUID_H_ + +// +// Definitions for Flash Map +// +#define EFI_FLASH_MAP_HOB_GUID \ + { 0xb091e7d2, 0x5a0, 0x4198, {0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 } } + +extern EFI_GUID gEfiFlashMapHobGuid; + +#endif // _FLASH_MAP_HOB_GUID_H_ diff --git a/EdkModulePkg/Include/Guid/HotPlugDevice.h b/EdkModulePkg/Include/Guid/HotPlugDevice.h new file mode 100644 index 0000000000..42fb6da8f3 --- /dev/null +++ b/EdkModulePkg/Include/Guid/HotPlugDevice.h @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + HotPlugDevice.h + +Abstract: + + +--*/ + +#ifndef _HOT_PLUG_DEVICE_H_ +#define _HOT_PLUG_DEVICE_H_ + +#define HOT_PLUG_DEVICE_GUID \ + { 0x220ac432, 0x1d43, 0x49e5, {0xa7, 0x4f, 0x4c, 0x9d, 0xa6, 0x7a, 0xd2, 0x3b } } + +extern EFI_GUID gEfiHotPlugDeviceGuid; +#endif diff --git a/EdkModulePkg/Include/Guid/MemoryTypeInformation.h b/EdkModulePkg/Include/Guid/MemoryTypeInformation.h new file mode 100644 index 0000000000..ed9270b09d --- /dev/null +++ b/EdkModulePkg/Include/Guid/MemoryTypeInformation.h @@ -0,0 +1,35 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + MemoryTypeInformation.h + +Abstract: + GUID used for Memory Type Information entries in the HOB list. + +--*/ + +#ifndef __MEMORY_TYPE_INFORMATION_GUID_H__ +#define __MEMORY_TYPE_INFORMATION_GUID_H__ + +#define EFI_MEMORY_TYPE_INFORMATION_GUID \ + { 0x4c19049f,0x4137,0x4dd3, { 0x9c,0x10,0x8b,0x97,0xa8,0x3f,0xfd,0xfa } } + +#define EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME L"MemoryTypeInformation" + +extern EFI_GUID gEfiMemoryTypeInformationGuid; + +typedef struct { + UINT32 Type; + UINT32 NumberOfPages; +} EFI_MEMORY_TYPE_INFORMATION; + +#endif diff --git a/EdkModulePkg/Include/Guid/MiniShellFile.h b/EdkModulePkg/Include/Guid/MiniShellFile.h new file mode 100644 index 0000000000..fa42d4d6b1 --- /dev/null +++ b/EdkModulePkg/Include/Guid/MiniShellFile.h @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EfiShell.h + +Abstract: + + FFS Filename for EFI Shell + +--*/ + +#ifndef _MINISHELLFILE_H_ +#define _MINISHELLFILE_H_ + +#define EFI_MINI_SHELL_FILE_GUID \ + { 0x86ad232b, 0xd33a, 0x465c, {0xbf, 0x5f, 0x41, 0x37, 0xb, 0xa9, 0x2f, 0xe2 } } + +extern EFI_GUID gEfiMiniShellFileGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/PciHotplugDevice.h b/EdkModulePkg/Include/Guid/PciHotplugDevice.h new file mode 100644 index 0000000000..3b488ced2f --- /dev/null +++ b/EdkModulePkg/Include/Guid/PciHotplugDevice.h @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciHotplugDevice.h + +Abstract: + + GUIDs used to indicate the device is Pccard hotplug device + +--*/ + +#ifndef _PCI_HOTPLUG_DEVICE_GUID_H_ +#define _PCI_HOTPLUG_DEVICE_GUID_H_ + +#define EFI_PCI_HOTPLUG_DEVICE_GUID \ + { 0x0b280816, 0x52e7, 0x4e51, {0xaa, 0x57, 0x11, 0xbd, 0x41, 0xcb, 0xef, 0xc3 } } + +extern EFI_GUID gEfiPciHotplugDeviceGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/PciOptionRomTable.h b/EdkModulePkg/Include/Guid/PciOptionRomTable.h new file mode 100644 index 0000000000..5ad956e1c3 --- /dev/null +++ b/EdkModulePkg/Include/Guid/PciOptionRomTable.h @@ -0,0 +1,46 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciOptionRomTable.h + +Abstract: + + GUID and data structure used to describe the list of PCI Option ROMs present in a system. + +--*/ + +#ifndef _PCI_OPTION_ROM_TABLE_GUID_H_ + +#define EFI_PCI_OPTION_ROM_TABLE_GUID \ + { 0x7462660f, 0x1cbd, 0x48da, {0xad, 0x11, 0x91, 0x71, 0x79, 0x13, 0x83, 0x1c } } + +extern EFI_GUID gEfiPciOptionRomTableGuid; + +typedef struct { + EFI_PHYSICAL_ADDRESS RomAddress; + EFI_MEMORY_TYPE MemoryType; + UINT32 RomLength; + UINT32 Seg; + UINT8 Bus; + UINT8 Dev; + UINT8 Func; + BOOLEAN ExecutedLegacyBiosImage; + BOOLEAN DontLoadEfiRom; +} EFI_PCI_OPTION_ROM_DESCRIPTOR; + +typedef struct { + UINT64 PciOptionRomCount; + EFI_PCI_OPTION_ROM_DESCRIPTOR *PciOptionRomDescriptors; +} EFI_PCI_OPTION_ROM_TABLE; + +#endif diff --git a/EdkModulePkg/Include/Guid/PeiPeCoffLoader.h b/EdkModulePkg/Include/Guid/PeiPeCoffLoader.h new file mode 100644 index 0000000000..abafb71afd --- /dev/null +++ b/EdkModulePkg/Include/Guid/PeiPeCoffLoader.h @@ -0,0 +1,67 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PeiPeCoffLoader.h + +Abstract: + GUID for the PE/COFF Loader APIs shared between PEI and DXE + +--*/ + +#ifndef __PEI_PE_COFF_LOADER_H__ +#define __PEI_PE_COFF_LOADER_H__ + + +#define EFI_PEI_PE_COFF_LOADER_GUID \ + { 0xd8117cff, 0x94a6, 0x11d4, {0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } } + +typedef struct _EFI_PEI_PE_COFF_LOADER_PROTOCOL EFI_PEI_PE_COFF_LOADER_PROTOCOL; + + +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PE_COFF_LOADER_GET_IMAGE_INFO) ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PE_COFF_LOADER_LOAD_IMAGE) ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PE_COFF_LOADER_RELOCATE_IMAGE) ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PE_COFF_LOADER_UNLOAD_IMAGE) ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +struct _EFI_PEI_PE_COFF_LOADER_PROTOCOL { + EFI_PEI_PE_COFF_LOADER_GET_IMAGE_INFO GetImageInfo; + EFI_PEI_PE_COFF_LOADER_LOAD_IMAGE LoadImage; + EFI_PEI_PE_COFF_LOADER_RELOCATE_IMAGE RelocateImage; + EFI_PEI_PE_COFF_LOADER_UNLOAD_IMAGE UnloadImage; +}; + +extern EFI_GUID gEfiPeiPeCoffLoaderGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/PeiPerformanceHob.h b/EdkModulePkg/Include/Guid/PeiPerformanceHob.h new file mode 100644 index 0000000000..33a2dc9089 --- /dev/null +++ b/EdkModulePkg/Include/Guid/PeiPerformanceHob.h @@ -0,0 +1,60 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeiPerformanceHob.h + +Abstract: + + GUIDs used for PEI Performance HOB data structures + +--*/ + +#ifndef __PEI_PERFORMANCE_HOB_H__ +#define __PEI_PERFORMANCE_HOB_H__ + +// +// This is the GUID of PEI performance HOB +// +#define PEI_PERFORMANCE_HOB_GUID \ + { 0xec4df5af, 0x4395, 0x4cc9, { 0x94, 0xde, 0x77, 0x50, 0x6d, 0x12, 0xc7, 0xb8 } } + +// +// PEI_PERFORMANCE_STRING_SIZE must be a multiple of 8. +// +#define PEI_PERFORMANCE_STRING_SIZE 8 +#define PEI_PERFORMANCE_STRING_LENGTH (PEI_PERFORMANCE_STRING_SIZE - 1) +// +// Bugbug: This macro will be replaced by a binary patchable PCD entry in EdkModulePkg +// +#define MAX_PEI_PERFORMANCE_LOG_ENTRIES 28 + +typedef struct { + EFI_PHYSICAL_ADDRESS Handle; + CHAR8 Token[PEI_PERFORMANCE_STRING_SIZE]; + CHAR8 Module[PEI_PERFORMANCE_STRING_SIZE]; + UINT64 StartTimeStamp; + UINT64 EndTimeStamp; +} PEI_PERFORMANCE_LOG_ENTRY; + +// +// The header must be aligned at 8 bytes. +// +typedef struct { + UINT32 NumberOfEntries; + UINT32 Reserved; +} PEI_PERFORMANCE_LOG_HEADER; + + +extern EFI_GUID gPeiPerformanceHobGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/PrimaryConsoleInDevice.h b/EdkModulePkg/Include/Guid/PrimaryConsoleInDevice.h new file mode 100644 index 0000000000..e5aa49cf44 --- /dev/null +++ b/EdkModulePkg/Include/Guid/PrimaryConsoleInDevice.h @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PrimaryConsoleInDevice.h + +Abstract: + + +--*/ + +#ifndef _PRIMARY_CONSOLE_IN_DEVICE_H_ +#define _PRIMARY_CONSOLE_IN_DEVICE_H_ + +#define EFI_PRIMARY_CONSOLE_IN_DEVICE_GUID \ + { 0xe451dcbe, 0x96a1, 0x4729, {0xa5, 0xcf, 0x6b, 0x9c, 0x2c, 0xff, 0x47, 0xfd } } + +extern EFI_GUID gEfiPrimaryConsoleInDeviceGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/PrimaryConsoleOutDevice.h b/EdkModulePkg/Include/Guid/PrimaryConsoleOutDevice.h new file mode 100644 index 0000000000..f73d727e88 --- /dev/null +++ b/EdkModulePkg/Include/Guid/PrimaryConsoleOutDevice.h @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PrimaryConsoleOutDevice.h + +Abstract: + +--*/ + +#ifndef _PRIMARY_CONSOLE_OUT_DEVICE_H_ +#define _PRIMARY_CONSOLE_OUT_DEVICE_H_ + +#define EFI_PRIMARY_CONSOLE_OUT_DEVICE_GUID \ + { 0x62bdf38a, 0xe3d5, 0x492c, {0x95, 0xc, 0x23, 0xa7, 0xf6, 0x6e, 0x67, 0x2e } } + +extern EFI_GUID gEfiPrimaryConsoleOutDeviceGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/PrimaryStandardErrorDevice.h b/EdkModulePkg/Include/Guid/PrimaryStandardErrorDevice.h new file mode 100644 index 0000000000..97905ea6aa --- /dev/null +++ b/EdkModulePkg/Include/Guid/PrimaryStandardErrorDevice.h @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PrimaryStandardErrorDevice.h + +Abstract: + +--*/ + +#ifndef _PRIMARY_STANDARD_ERROR_DEVICE_H_ +#define _PRIMARY_STANDARD_ERROR_DEVICE_H_ + +#define EFI_PRIMARY_STANDARD_ERROR_DEVICE_GUID \ + { 0x5a68191b, 0x9b97, 0x4752, {0x99, 0x46, 0xe3, 0x6a, 0x5d, 0xa9, 0x42, 0xb1 } } + +extern EFI_GUID gEfiPrimaryStandardErrorDeviceGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/ShellFile.h b/EdkModulePkg/Include/Guid/ShellFile.h new file mode 100644 index 0000000000..1f3d3b3d00 --- /dev/null +++ b/EdkModulePkg/Include/Guid/ShellFile.h @@ -0,0 +1,31 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EfiShell.h + +Abstract: + + FFS Filename for EFI Shell + +--*/ + +#ifndef _SHELLFILE_H_ +#define _SHELLFILE_H_ + +#define EFI_SHELL_FILE_GUID \ + { 0xc57ad6b7, 0x0515, 0x40a8, {0x9d, 0x21, 0x55, 0x16, 0x52, 0x85, 0x4e, 0x37 } } + + +extern EFI_GUID gEfiShellFileGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/StandardErrorDevice.h b/EdkModulePkg/Include/Guid/StandardErrorDevice.h new file mode 100644 index 0000000000..32b5af44c8 --- /dev/null +++ b/EdkModulePkg/Include/Guid/StandardErrorDevice.h @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + StandardErrorDevice.h + +Abstract: + + +--*/ + +#ifndef _STANDARD_ERROR_DEVICE_H_ +#define _STANDARD_ERROR_DEVICE_H_ + +#define EFI_STANDARD_ERROR_DEVICE_GUID \ + { 0xd3b36f2d, 0xd551, 0x11d4, {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } } + +extern EFI_GUID gEfiStandardErrorDeviceGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/StatusCode.h b/EdkModulePkg/Include/Guid/StatusCode.h new file mode 100644 index 0000000000..8242290b22 --- /dev/null +++ b/EdkModulePkg/Include/Guid/StatusCode.h @@ -0,0 +1,33 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + StatusCode.h + +Abstract: + + GUID used to identify Data Hub records that originate from the Tiano + ReportStatusCode API. + +--*/ + +#ifndef _STATUS_CODE_H__ +#define _STATUS_CODE_H__ + +#define EFI_STATUS_CODE_GUID \ + { \ + 0xd083e94c, 0x6560, 0x42e4, {0xb6, 0xd4, 0x2d, 0xf7, 0x5a, 0xdf, 0x6a, 0x2a } \ + } + +extern EFI_GUID gEfiStatusCodeGuid; + +#endif diff --git a/EdkModulePkg/Include/Guid/StatusCodeCallerId.h b/EdkModulePkg/Include/Guid/StatusCodeCallerId.h new file mode 100644 index 0000000000..8cf9d16928 --- /dev/null +++ b/EdkModulePkg/Include/Guid/StatusCodeCallerId.h @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + StatusCodeCallerId.h + +Abstract: + GUID used to identify id for the caller who is initiating the Status Code. + +--*/ + +#ifndef __STATUS_CODE_CALLER_ID_H__ +#define __STATUS_CODE_CALLER_ID_H__ + + +#define EFI_STANDARD_CALLER_ID_GUID \ + {0xC9DCF469, 0xA7C4, 0x11D5, {0x87, 0xDA, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xB9} } + +extern EFI_GUID gEfiCallerIdGuid; + + +#endif diff --git a/EdkModulePkg/Include/Guid/SystemNvDataGuid.h b/EdkModulePkg/Include/Guid/SystemNvDataGuid.h new file mode 100644 index 0000000000..946d4d8d03 --- /dev/null +++ b/EdkModulePkg/Include/Guid/SystemNvDataGuid.h @@ -0,0 +1,45 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + SystemNvDataGuid.h + +Abstract: + + GUIDs used for System Non Volatile HOB entries in the in the HOB list and FV Guids carrying + the System specific information. + +--*/ + +#ifndef __SYSTEM_NV_DATA_GUID_H__ +#define __SYSTEM_NV_DATA_GUID_H__ + +#define EFI_SYSTEM_NV_DATA_FV_GUID \ + {0xfff12b8d, 0x7696, 0x4c8b, {0xa9, 0x85, 0x27, 0x47, 0x7, 0x5b, 0x4f, 0x50} } + +#define EFI_SYSTEM_NV_DATA_HOB_GUID \ + {0xd6e5092d, 0xc7b2, 0x4872, {0xaf, 0x66, 0xfd, 0xc0, 0xe6, 0xf9, 0x5e, 0x78} } + +typedef struct { + EFI_GUID SystemNvDataHobGuid; + EFI_GUID SystemNvDataFvGuid; + EFI_LBA StartLba; + UINTN StartLbaOffset; + EFI_LBA EndLba; + UINTN EndLbaOffset; + UINT32 DataTypeSignature; +} NV_SYSTEM_DATA_GUID_TYPE; + +extern EFI_GUID gEfiSystemNvDataHobGuid; +extern EFI_GUID gEfiSystemNvDataFvGuid; + +#endif diff --git a/EdkModulePkg/Include/Library/CustomDecompressLib.h b/EdkModulePkg/Include/Library/CustomDecompressLib.h new file mode 100644 index 0000000000..6edd3ba80f --- /dev/null +++ b/EdkModulePkg/Include/Library/CustomDecompressLib.h @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CustomDecompressLib.h + +Abstract: + + Custom Decompress Functions + +--*/ + +#ifndef __CUSTOM_DECPOMPRESS_LIB_H__ +#define __CUSTOM_DECPOMPRESS_LIB_H__ + +RETURN_STATUS +EFIAPI +CustomDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +RETURN_STATUS +EFIAPI +CustomDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ); + +#endif diff --git a/EdkModulePkg/Include/Library/EdkBsDataHubStatusCodeLib.h b/EdkModulePkg/Include/Library/EdkBsDataHubStatusCodeLib.h new file mode 100644 index 0000000000..a334c92697 --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkBsDataHubStatusCodeLib.h @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BsDataHubStatusCodeLib.h + +Abstract: + + Lib to provide data hub status code reporting. + +--*/ + +#ifndef _EFI_BS_DATA_HUB_STATUS_CODE_LIB_H_ +#define _EFI_BS_DATA_HUB_STATUS_CODE_LIB_H_ + +// +// Initialization function +// +VOID +BsDataHubStatusCodeInitialize ( + VOID + ) +; + +// +// Status code reporting function +// +EFI_STATUS +BsDataHubReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +; + +#endif diff --git a/EdkModulePkg/Include/Library/EdkDxeSalLib.h b/EdkModulePkg/Include/Library/EdkDxeSalLib.h new file mode 100644 index 0000000000..9d21846289 --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkDxeSalLib.h @@ -0,0 +1,141 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EdkDxeSalLib.h + +Abstract: + +--*/ + +#ifndef _ESAL_SERVICE_LIB_H__ +#define _ESAL_SERVICE_LIB_H__ + +//#include + +EFI_STATUS +RegisterEsalFunction ( + IN UINT64 FunctionId, + IN EFI_GUID *ClassGuid, + IN SAL_INTERNAL_EXTENDED_SAL_PROC Function, + IN VOID *ModuleGlobal + ) +/*++ + +Routine Description: + + Register ESAL Class Function and it's asociated global. + This function is boot service only! + +Arguments: + FunctionId - ID of function to register + ClassGuid - GUID of function class + Function - Function to register under ClassGuid/FunctionId pair + ModuleGlobal - Module global for Function. + +Returns: + EFI_SUCCESS - If ClassGuid/FunctionId Function was registered. + +--*/ +; + +EFI_STATUS +RegisterEsalClass ( + IN EFI_GUID *ClassGuid, + IN VOID *ModuleGlobal, + ... + ) +/*++ + +Routine Description: + + Register ESAL Class and it's asociated global. + This function is boot service only! + +Arguments: + ClassGuid - GUID of function class + ModuleGlobal - Module global for Function. + .. - SAL_INTERNAL_EXTENDED_SAL_PROC and FunctionId pairs. NULL + indicates the end of the list. + +Returns: + EFI_SUCCESS - All members of ClassGuid registered + +--*/ +; + +SAL_RETURN_REGS +EfiCallEsalService ( + IN EFI_GUID *ClassGuid, + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8 + ) +/*++ + +Routine Description: + + Call module that is not linked direclty to this module. This code is IP + relative and hides the binding issues of virtual or physical calling. The + function that gets dispatched has extra arguments that include the registered + module global and a boolean flag to indicate if the system is in virutal mode. + +Arguments: + ClassGuid - GUID of function + FunctionId - Function in ClassGuid to call + Arg2 - Argument 2 ClassGuid/FunctionId defined + Arg3 - Argument 3 ClassGuid/FunctionId defined + Arg4 - Argument 4 ClassGuid/FunctionId defined + Arg5 - Argument 5 ClassGuid/FunctionId defined + Arg6 - Argument 6 ClassGuid/FunctionId defined + Arg7 - Argument 7 ClassGuid/FunctionId defined + Arg8 - Argument 8 ClassGuid/FunctionId defined + +Returns: + Status of ClassGuid/FuncitonId + +--*/ +; + +SAL_RETURN_REGS +SetEsalVirtualEntryPoint ( + IN UINT64 EntryPoint, + IN UINT64 Gp + ) +; + +SAL_RETURN_REGS +SetEsalPhysicalEntryPoint ( + IN UINT64 EntryPoint, + IN UINT64 Gp + ) +; + +SAL_RETURN_REGS +GetEsalEntryPoint ( + VOID + ) +; + +VOID +SalFlushCache ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +; + +#endif diff --git a/EdkModulePkg/Include/Library/EdkFvbServiceLib.h b/EdkModulePkg/Include/Library/EdkFvbServiceLib.h new file mode 100644 index 0000000000..16e00d3a8d --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkFvbServiceLib.h @@ -0,0 +1,250 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EdkFvbServiceLib.h + +Abstract: + +--*/ +#ifndef __EDK_FVB_SERVICE_LIB_H__ +#define __EDK_FVB_SERVICE_LIB_H__ + +EFI_STATUS +EfiFvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Reads specified number of bytes into a buffer from the specified block + +Arguments: + Instance - The FV instance to be read from + Lba - The logical block address to be read from + Offset - Offset into the block at which to begin reading + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes read + Buffer - Pointer to a caller allocated buffer that will be + used to hold the data read + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +; + +EFI_STATUS +EfiFvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Writes specified number of bytes from the input buffer to the block + +Arguments: + Instance - The FV instance to be written to + Lba - The starting logical block index to write to + Offset - Offset into the block at which to begin writing + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes actually written + Buffer - Pointer to a caller allocated buffer that contains + the source for the write + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +; + +EFI_STATUS +EfiFvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba + ) +/*++ + +Routine Description: + Erases and initializes a firmware volume block + +Arguments: + Instance - The FV instance to be erased + Lba - The logical block index to be erased + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +; + +EFI_STATUS +EfiFvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + +Arguments: + Instance - The FV instance whose attributes is going to be + returned + Attributes - Output buffer which contains attributes + +Returns: + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +; + +EFI_STATUS +EfiFvbSetVolumeAttributes ( + IN UINTN Instance, + IN EFI_FVB_ATTRIBUTES Attributes + ) +/*++ + +Routine Description: + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + +Arguments: + Instance - The FV instance whose attributes is going to be + modified + Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES + containing the desired firmware volume settings. + On successful return, it contains the new settings + of the firmware volume + +Returns: + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +; + +EFI_STATUS +EfiFvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *BaseAddress + ) +/*++ + +Routine Description: + Retrieves the physical address of a memory mapped FV + +Arguments: + Instance - The FV instance whose base address is going to be + returned + BaseAddress - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS + that on successful return, contains the base address + of the firmware volume. + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +; + +EFI_STATUS +EfiFvbGetBlockSize ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +/*++ + +Routine Description: + Retrieve the size of a logical block + +Arguments: + Instance - The FV instance whose block size is going to be + returned + Lba - Indicates which block to return the size for. + BlockSize - A pointer to a caller allocated UINTN in which + the size of the block is returned + NumOfBlocks - a pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + +Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +; + +EFI_STATUS +EfiFvbEraseCustomBlockRange ( + IN UINTN Instance, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba + ) +/*++ + +Routine Description: + Erases and initializes a specified range of a firmware volume + +Arguments: + Instance - The FV instance to be erased + StartLba - The starting logical block index to be erased + OffsetStartLba - Offset into the starting block at which to + begin erasing + LastLba - The last logical block index to be erased + OffsetLastLba - Offset into the last block at which to end erasing + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + + EFI_UNSUPPORTED - not support + +--*/ +; + +#endif diff --git a/EdkModulePkg/Include/Library/EdkGraphicsLib.h b/EdkModulePkg/Include/Library/EdkGraphicsLib.h new file mode 100644 index 0000000000..52bedd891a --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkGraphicsLib.h @@ -0,0 +1,185 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + GraphicsLib.h + +Abstract: + + +--*/ + +#ifndef _EFI_GRAPHICS_LIB_H_ +#define _EFI_GRAPHICS_LIB_H_ + +EFI_STATUS +GetGraphicsBitMapFromFV ( + IN EFI_GUID *FileNameGuid, + OUT VOID **Image, + OUT UINTN *ImageSize + ) +/*++ + +Routine Description: + + Return the graphics image file named FileNameGuid into Image and return it's + size in ImageSize. All Firmware Volumes (FV) in the system are searched for the + file name. + +Arguments: + + FileNameGuid - File Name of graphics file in the FV(s). + + Image - Pointer to pointer to return graphics image. If NULL, a + buffer will be allocated. + + ImageSize - Size of the graphics Image in bytes. Zero if no image found. + + +Returns: + + EFI_SUCCESS - Image and ImageSize are valid. + EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size + EFI_NOT_FOUND - FileNameGuid not found + +--*/ +; + +EFI_STATUS +ConvertBmpToUgaBlt ( + IN VOID *BmpImage, + IN UINTN BmpImageSize, + IN OUT VOID **UgaBlt, + IN OUT UINTN *UgaBltSize, + OUT UINTN *PixelHeight, + OUT UINTN *PixelWidth + ) +/*++ + +Routine Description: + + Convert a *.BMP graphics image to a UGA blt buffer. If a NULL UgaBlt buffer + is passed in a UgaBlt buffer will be allocated by this routine. If a UgaBlt + buffer is passed in it will be used if it is big enough. + +Arguments: + + BmpImage - Pointer to BMP file + + BmpImageSize - Number of bytes in BmpImage + + UgaBlt - Buffer containing UGA version of BmpImage. + + UgaBltSize - Size of UgaBlt in bytes. + + PixelHeight - Height of UgaBlt/BmpImage in pixels + + PixelWidth - Width of UgaBlt/BmpImage in pixels + + +Returns: + + EFI_SUCCESS - UgaBlt and UgaBltSize are returned. + EFI_UNSUPPORTED - BmpImage is not a valid *.BMP image + EFI_BUFFER_TOO_SMALL - The passed in UgaBlt buffer is not big enough. + UgaBltSize will contain the required size. + +--*/ +; + +EFI_STATUS +EnableQuietBoot ( + IN EFI_GUID *LogoFile + ) +/*++ + +Routine Description: + + Use Console Control to turn off UGA based Simple Text Out consoles from going + to the UGA device. Put up LogoFile on every UGA device that is a console + +Arguments: + + LogoFile - File name of logo to display on the center of the screen. + + +Returns: + + EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo + displayed. + EFI_UNSUPPORTED - Logo not found + +--*/ +; + +EFI_STATUS +DisableQuietBoot ( + VOID + ) +/*++ + +Routine Description: + + Use Console Control to turn on UGA based Simple Text Out consoles. The UGA + Simple Text Out screens will now be synced up with all non UGA output devices + +Arguments: + + NONE + +Returns: + + EFI_SUCCESS - UGA devices are back in text mode and synced up. + EFI_UNSUPPORTED - Logo not found + +--*/ +; + +EFI_STATUS +LockKeyboards ( + IN CHAR16 *Password + ) +/*++ + +Routine Description: + Use Console Control Protocol to lock the Console In Spliter virtual handle. + This is the ConInHandle and ConIn handle in the EFI system table. All key + presses will be ignored until the Password is typed in. The only way to + disable the password is to type it in to a ConIn device. + +Arguments: + Password - Password used to lock ConIn device + + +Returns: + + EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo + displayed. + EFI_UNSUPPORTED - Logo not found + +--*/ +; + +UINTN +EFIAPI +PrintXY ( + IN UINTN X, + IN UINTN Y, + IN EFI_UGA_PIXEL *Foreground, OPTIONAL + IN EFI_UGA_PIXEL *Background, OPTIONAL + IN CHAR16 *Fmt, + ... + ) +; + + +#endif diff --git a/EdkModulePkg/Include/Library/EdkIfrSupportLib.h b/EdkModulePkg/Include/Library/EdkIfrSupportLib.h new file mode 100644 index 0000000000..d2a1ff5ee4 --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkIfrSupportLib.h @@ -0,0 +1,1270 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + IfrSupportLib.h + +Abstract: + + The file contain all library function for Ifr Operations. + +--*/ + +#ifndef _IFRSUPPORTLIBRARY_H +#define _IFRSUPPORTLIBRARY_H + +#define DEFAULT_FORM_BUFFER_SIZE 0xFFFF +#define DEFAULT_STRING_BUFFER_SIZE 0xFFFF + +#pragma pack(1) +typedef struct { + CHAR16 *OptionString; // Passed in string to generate a token for in a truly dynamic form creation + STRING_REF StringToken; // This is used when creating a single op-code without generating a StringToken (have one already) + UINT16 Value; + UINT8 Flags; + UINT16 Key; +} IFR_OPTION; +#pragma pack() + +EFI_STATUS +GetCurrentLanguage ( + OUT CHAR16 *Lang + ) +/*++ + +Routine Description: + + Determine what is the current language setting + +Arguments: + + Lang - Pointer of system language + +Returns: + + Status code + +--*/ +; + +EFI_STATUS +AddString ( + IN VOID *StringBuffer, + IN CHAR16 *Language, + IN CHAR16 *String, + IN OUT STRING_REF *StringToken + ) +/*++ + +Routine Description: + + Add a string to the incoming buffer and return the token and offset data + +Arguments: + + StringBuffer - The incoming buffer + + Language - Currrent language + + String - The string to be added + + StringToken - The index where the string placed + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - String successfully added to the incoming buffer + +--*/ +; + +EFI_STATUS +AddOpCode ( + IN VOID *FormBuffer, + IN OUT VOID *OpCodeData + ) +/*++ + +Routine Description: + + Add op-code data to the FormBuffer + +Arguments: + + FormBuffer - Form buffer to be inserted to + + OpCodeData - Op-code data to be inserted + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Op-code data successfully inserted + +--*/ +; + +EFI_STATUS +CreateFormSet ( + IN CHAR16 *FormSetTitle, + IN EFI_GUID *Guid, + IN UINT8 Class, + IN UINT8 SubClass, + IN OUT VOID **FormBuffer, + IN OUT VOID **StringBuffer + ) +/*++ + +Routine Description: + + Create a formset + +Arguments: + + FormSetTitle - Title of formset + + Guid - Guid of formset + + Class - Class of formset + + SubClass - Sub class of formset + + FormBuffer - Pointer of the formset created + + StringBuffer - Pointer of FormSetTitile string created + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Formset successfully created + +--*/ +; + +EFI_STATUS +CreateForm ( + IN CHAR16 *FormTitle, + IN UINT16 FormId, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a form + +Arguments: + + FormTitle - Title of the form + + FormId - Id of the form + + FormBuffer - Pointer of the form created + + StringBuffer - Pointer of FormTitil string created + +Returns: + + EFI_SUCCESS - Form successfully created + +--*/ +; + +EFI_STATUS +CreateSubTitle ( + IN CHAR16 *SubTitle, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a SubTitle + +Arguments: + + SubTitle - Sub title to be created + + FormBuffer - Where this subtitle to add to + + StringBuffer - String buffer created for subtitle + +Returns: + + EFI_SUCCESS - Subtitle successfully created + +--*/ +; + +EFI_STATUS +CreateText ( + IN CHAR16 *String, + IN CHAR16 *String2, + IN CHAR16 *String3, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a line of text + +Arguments: + + String - First string of the text + + String2 - Second string of the text + + String3 - Help string of the text + + Flags - Flag of the text + + Key - Key of the text + + FormBuffer - The form where this text adds to + + StringBuffer - String buffer created for String, String2 and String3 + +Returns: + + EFI_SUCCESS - Text successfully created + +--*/ +; + +EFI_STATUS +CreateGoto ( + IN UINT16 FormId, + IN CHAR16 *Prompt, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a hyperlink + +Arguments: + + FormId - Form ID of the hyperlink + + Prompt - Prompt of the hyperlink + + FormBuffer - The form where this hyperlink adds to + + StringBuffer - String buffer created for Prompt + +Returns: + + EFI_SUCCESS - Hyperlink successfully created + +--*/ +; + +EFI_STATUS +CreateOneOf ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a one-of question with a set of options to choose from. The + OptionsList is a pointer to a null-terminated list of option descriptions. + +Arguments: + + QuestionId - Question ID of the one-of box + + DataWidth - DataWidth of the one-of box + + Prompt - Prompt of the one-of box + + Help - Help of the one-of box + + OptionsList - Each string in it is an option of the one-of box + + OptionCount - Option string count + + FormBuffer - The form where this one-of box adds to + + StringBuffer - String buffer created for Prompt, Help and Option strings + +Returns: + + EFI_DEVICE_ERROR - DataWidth > 2 + + EFI_SUCCESS - One-Of box successfully created. + +--*/ +; + +EFI_STATUS +CreateOrderedList ( + IN UINT16 QuestionId, + IN UINT8 MaxEntries, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a one-of question with a set of options to choose from. The + OptionsList is a pointer to a null-terminated list of option descriptions. + +Arguments: + + QuestionId - Question ID of the ordered list + + MaxEntries - MaxEntries of the ordered list + + Prompt - Prompt of the ordered list + + Help - Help of the ordered list + + OptionsList - Each string in it is an option of the ordered list + + OptionCount - Option string count + + FormBuffer - The form where this ordered list adds to + + StringBuffer - String buffer created for Prompt, Help and Option strings + +Returns: + + EFI_SUCCESS - Ordered list successfully created. + +--*/ +; + +EFI_STATUS +CreateCheckBox ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN UINT8 Flags, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a checkbox + +Arguments: + + QuestionId - Question ID of the check box + + DataWidth - DataWidth of the check box + + Prompt - Prompt of the check box + + Help - Help of the check box + + Flags - Flags of the check box + + FormBuffer - The form where this check box adds to + + StringBuffer - String buffer created for Prompt and Help. + +Returns: + + EFI_DEVICE_ERROR - DataWidth > 1 + + EFI_SUCCESS - Check box successfully created + +--*/ +; + +EFI_STATUS +CreateNumeric ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN UINT16 Minimum, + IN UINT16 Maximum, + IN UINT16 Step, + IN UINT16 Default, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a numeric + +Arguments: + + QuestionId - Question ID of the numeric + + DataWidth - DataWidth of the numeric + + Prompt - Prompt of the numeric + + Help - Help of the numeric + + Minimum - Minumun boundary of the numeric + + Maximum - Maximum boundary of the numeric + + Step - Step of the numeric + + Default - Default value + + Flags - Flags of the numeric + + Key - Key of the numeric + + FormBuffer - The form where this numeric adds to + + StringBuffer - String buffer created for Prompt and Help. + +Returns: + + EFI_DEVICE_ERROR - DataWidth > 2 + + EFI_SUCCESS - Numeric is successfully created + +--*/ +; + +EFI_STATUS +CreateString ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN UINT8 MinSize, + IN UINT8 MaxSize, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a string + +Arguments: + + QuestionId - Question ID of the string + + DataWidth - DataWidth of the string + + Prompt - Prompt of the string + + Help - Help of the string + + MinSize - Min size boundary of the string + + MaxSize - Max size boundary of the string + + Flags - Flags of the string + + Key - Key of the string + + FormBuffer - The form where this string adds to + + StringBuffer - String buffer created for Prompt and Help. + +Returns: + + EFI_SUCCESS - String successfully created. + +--*/ +; + +EFI_STATUS +ExtractDataFromHiiHandle ( + IN EFI_HII_HANDLE HiiHandle, + IN OUT UINT16 *ImageLength, + OUT UINT8 *DefaultImage, + OUT EFI_GUID *Guid + ) +/*++ + +Routine Description: + + Extract information pertaining to the HiiHandle + +Arguments: + + HiiHandle - Hii handle + + ImageLength - For input, length of DefaultImage; + For output, length of actually required + + DefaultImage - Image buffer prepared by caller + + Guid - Guid information about the form + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength + + EFI_SUCCESS - Successfully extract data from Hii database. + + +--*/ +; + +EFI_HII_HANDLE +FindHiiHandle ( + IN OUT EFI_HII_PROTOCOL **HiiProtocol, OPTIONAL + IN EFI_GUID *Guid + ) +/*++ + +Routine Description: + Finds HII handle for given pack GUID previously registered with the HII. + +Arguments: + HiiProtocol - pointer to pointer to HII protocol interface. + If NULL, the interface will be found but not returned. + If it points to NULL, the interface will be found and + written back to the pointer that is pointed to. + Guid - The GUID of the pack that registered with the HII. + +Returns: + Handle to the HII pack previously registered by the memory driver. + +--*/ +; + +EFI_STATUS +CreateSubTitleOpCode ( + IN STRING_REF StringToken, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a SubTitle opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + StringToken - StringToken of the subtitle + + FormBuffer - Output of subtitle as a form + +Returns: + + EFI_SUCCESS - Subtitle created to be a form + +--*/ +; + +EFI_STATUS +CreateTextOpCode ( + IN STRING_REF StringToken, + IN STRING_REF StringTokenTwo, + IN STRING_REF StringTokenThree, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a Text opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + StringToken - First string token of the text + + StringTokenTwo - Second string token of the text + + StringTokenThree - Help string token of the text + + Flags - Flag of the text + + Key - Key of the text + + FormBuffer - Output of text as a form + +Returns: + + EFI_SUCCESS - Text created to be a form + +--*/ +; + +EFI_STATUS +CreateGotoOpCode ( + IN UINT16 FormId, + IN STRING_REF StringToken, + IN STRING_REF StringTokenTwo, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a hyperlink opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + FormId - Form ID of the hyperlink + + StringToken - Prompt string token of the hyperlink + + StringTokenTwo - Help string token of the hyperlink + + Flags - Flags of the hyperlink + + Key - Key of the hyperlink + + FormBuffer - Output of hyperlink as a form + +Returns: + + EFI_SUCCESS - Hyperlink created to be a form + +--*/ +; + +EFI_STATUS +CreateOneOfOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a one-of opcode with a set of option op-codes to choose from independent of string creation. + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + + OptionsList is a pointer to a null-terminated list of option descriptions. Ensure that OptionsList[x].StringToken + has been filled in since this routine will not generate StringToken values. + +Arguments: + + QuestionId - Question ID of the one-of box + + DataWidth - DataWidth of the one-of box + + PromptToken - Prompt string token of the one-of box + + HelpToken - Help string token of the one-of box + + OptionsList - Each string in it is an option of the one-of box + + OptionCount - Option string count + + FormBuffer - Output of One-Of box as a form + +Returns: + + EFI_SUCCESS - One-Of box created to be a form + + EFI_DEVICE_ERROR - DataWidth > 2 + +--*/ +; + +EFI_STATUS +CreateOrderedListOpCode ( + IN UINT16 QuestionId, + IN UINT8 MaxEntries, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a ordered list opcode with a set of option op-codes to choose from independent of string creation. + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + + OptionsList is a pointer to a null-terminated list of option descriptions. Ensure that OptionsList[x].StringToken + has been filled in since this routine will not generate StringToken values. + +Arguments: + + QuestionId - Question ID of the ordered list + + MaxEntries - MaxEntries of the ordered list + + PromptToken - Prompt string token of the ordered list + + HelpToken - Help string token of the ordered list + + OptionsList - Each string in it is an option of the ordered list + + OptionCount - Option string count + + FormBuffer - Output of ordered list as a form + +Returns: + + EFI_SUCCESS - Ordered list created to be a form + +--*/ +; + +EFI_STATUS +CreateCheckBoxOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a checkbox opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + QuestionId - Question ID of the check box + + DataWidth - DataWidth of the check box + + PromptToken - Prompt string token of the check box + + HelpToken - Help string token of the check box + + Flags - Flags of the check box + + Key - Key of the check box + + FormBuffer - Output of the check box as a form + +Returns: + + EFI_SUCCESS - Checkbox created to be a form + + EFI_DEVICE_ERROR - DataWidth > 1 + +--*/ +; + +EFI_STATUS +CreateNumericOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN UINT16 Minimum, + IN UINT16 Maximum, + IN UINT16 Step, + IN UINT16 Default, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a numeric opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + QuestionId - Question ID of the numeric + + DataWidth - DataWidth of the numeric + + PromptToken - Prompt string token of the numeric + + HelpToken - Help string token of the numeric + + Minimum - Minumun boundary of the numeric + + Maximum - Maximum boundary of the numeric + + Step - Step of the numeric + + Default - Default value of the numeric + + Flags - Flags of the numeric + + Key - Key of the numeric + + FormBuffer - Output of the numeric as a form + +Returns: + + EFI_SUCCESS - The numeric created to be a form. + + EFI_DEVICE_ERROR - DataWidth > 2 + +--*/ +; + +EFI_STATUS +CreateStringOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN UINT8 MinSize, + IN UINT8 MaxSize, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a numeric opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + QuestionId - Question ID of the string + + DataWidth - DataWidth of the string + + PromptToken - Prompt token of the string + + HelpToken - Help token of the string + + MinSize - Min size boundary of the string + + MaxSize - Max size boundary of the string + + Flags - Flags of the string + + Key - Key of the string + + FormBuffer - Output of the string as a form + +Returns: + + EFI_SUCCESS - String created to be a form. + +--*/ +; + +EFI_STATUS +ValidateDataFromHiiHandle ( + IN EFI_HII_HANDLE HiiHandle, + OUT BOOLEAN *Results + ) +/*++ + +Routine Description: + + Validate that the data associated with the HiiHandle in NVRAM is within + the reasonable parameters for that FormSet. Values for strings and passwords + are not verified due to their not having the equivalent of valid range settings. + +Arguments: + + HiiHandle - Handle of the HII database entry to query + + Results - If return Status is EFI_SUCCESS, Results provides valid data + TRUE = NVRAM Data is within parameters + FALSE = NVRAM Data is NOT within parameters + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Data successfully validated +--*/ +; + +EFI_STATUS +CreateBannerOpCode ( + IN UINT16 Title, + IN UINT16 LineNumber, + IN UINT8 Alignment, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a banner opcode. This is primarily used by the FrontPage implementation from BDS. + +Arguments: + + Title - Title of the banner + + LineNumber - LineNumber of the banner + + Alignment - Alignment of the banner + + FormBuffer - Output of banner as a form + +Returns: + + EFI_SUCCESS - Banner created to be a form. + +--*/ +; + +VOID +EfiLibHiiVariablePackGetMap ( + IN EFI_HII_VARIABLE_PACK *Pack, + OUT CHAR16 **Name, OPTIONAL + OUT EFI_GUID **Guid, OPTIONAL + OUT UINT16 *Id, OPTIONAL + OUT VOID **Var, OPTIONAL + OUT UINTN *Size OPTIONAL + ) +/*++ + +Routine Description: + + Extracts a variable form a Pack. + +Arguments: + + Pack - List of variables + Name - Name of the variable/map + Guid - GUID of the variable/map + Var - Pointer to the variable/map + Size - Size of the variable/map in bytes + +Returns: + + VOID. + +--*/ +; + +UINTN +EfiLibHiiVariablePackListGetMapCnt ( + IN EFI_HII_VARIABLE_PACK_LIST *List + ) +/*++ + +Routine Description: + + Finds a count of the variables/maps in the List. + +Arguments: + + List - List of variables + +Returns: + + Number of Map in the variable pack list. + +--*/ +; + +typedef VOID (EFI_LIB_HII_VARIABLE_PACK_LIST_CALLBACK) ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINT16 Id, + IN VOID *Var, + IN UINTN Size + ) +/*++ + +Routine Description: + + type definition for the callback to be + used with EfiLibHiiVariablePackListForEachVar(). + +Arguments: + + Id - Variable/Map ID + Name - Name of the variable/map + Guid - GUID of the variable/map + Var - Pointer to the variable/map + Size - Size of the variable/map in bytes + +Returns: + + VOID + +--*/ +; + +VOID +EfiLibHiiVariablePackListForEachVar ( + IN EFI_HII_VARIABLE_PACK_LIST *List, + IN EFI_LIB_HII_VARIABLE_PACK_LIST_CALLBACK *Callback + ) +/*++ + +Routine Description: + + Will iterate all variable/maps as appearing + in List and for each, it will call the Callback. + +Arguments: + + List - List of variables + Callback - Routine to be called for each iterated variable. + +Returns: + + VOID + +--*/ +; + +EFI_STATUS +EfiLibHiiVariablePackListGetMapByIdx ( + IN UINTN Idx, + IN EFI_HII_VARIABLE_PACK_LIST *List, + OUT CHAR16 **Name, OPTIONAL + OUT EFI_GUID **Guid, OPTIONAL + OUT UINT16 *Id, OPTIONAL + OUT VOID **Var, + OUT UINTN *Size + ) +/*++ + +Routine Description: + + Finds a variable form List given + the order number as appears in the List. + +Arguments: + + Idx - The index of the variable/map to retrieve + List - List of variables + Name - Name of the variable/map + Guid - GUID of the variable/map + Var - Pointer to the variable/map + Size - Size of the variable/map in bytes + +Returns: + + EFI_SUCCESS - Variable is found, OUT parameters are valid + EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid + +--*/ +; + +EFI_STATUS +EfiLibHiiVariablePackListGetMapById ( + IN UINT16 Id, + IN EFI_HII_VARIABLE_PACK_LIST *List, + OUT CHAR16 **Name, OPTIONAL + OUT EFI_GUID **Guid, OPTIONAL + OUT VOID **Var, + OUT UINTN *Size + ) +/*++ + +Routine Description: + + Finds a variable form List given the + order number as appears in the List. + +Arguments: + + Id - The ID of the variable/map to retrieve + List - List of variables + Name - Name of the variable/map + Guid - GUID of the variable/map + Var - Pointer to the variable/map + Size - Size of the variable/map in bytes + +Returns: + + EFI_SUCCESS - Variable is found, OUT parameters are valid + EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid + +--*/ +; + +EFI_STATUS +EfiLibHiiVariablePackListGetMap ( + IN EFI_HII_VARIABLE_PACK_LIST *List, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + OUT UINT16 *Id, + OUT VOID **Var, + OUT UINTN *Size + ) +/*++ + +Routine Description: + + Finds a variable form EFI_HII_VARIABLE_PACK_LIST given name and GUID. + +Arguments: + + List - List of variables + Name - Name of the variable/map to be found + Guid - GUID of the variable/map to be found + Var - Pointer to the variable/map found + Size - Size of the variable/map in bytes found + +Returns: + + EFI_SUCCESS - variable is found, OUT parameters are valid + EFI_NOT_FOUND - variable is not found, OUT parameters are not valid + +--*/ +; + +EFI_STATUS +EfiLibHiiVariableRetrieveFromNv ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINTN Size, + OUT VOID **Var + ) +/*++ + +Routine Description: + Finds out if a variable of specific Name/Guid/Size exists in NV. + If it does, it will retrieve it into the Var. + +Arguments: + Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly. + Var - Variable will be retrieved into buffer pointed by this pointer. + If pointing to NULL, the buffer will be allocated. Caller is responsible for releasing the buffer. +Returns: + EFI_SUCCESS - The variable of exact Name/Guid/Size parameters was retrieved and written to Var. + EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV. + EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error. + +--*/ +; + +//// +//// Variable override support. +//// + +EFI_STATUS +EfiLibHiiVariableOverrideIfSuffix ( + IN CHAR16 *Suffix, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINTN Size, + OUT VOID *Var + ) +/*++ + +Routine Description: + Overrrides the variable with NV data if found. + But it only does it if the Name ends with specified Suffix. + For example, if Suffix="MyOverride" and the Name="XyzSetupMyOverride", + the Suffix matches the end of Name, so the variable will be loaded from NV + provided the variable exists and the GUID and Size matches. + +Arguments: + Suffix - Suffix the Name should end with. + Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly. + Var - Variable will be retrieved into this buffer. + Caller is responsible for providing storage of exactly Size size in bytes. +Returns: + EFI_SUCCESS - The variable was overriden with NV variable of same Name/Guid/Size. + EFI_INVALID_PARAMETER - The name of the variable does not end with . + EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV. + EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error. + +--*/ +; + +EFI_STATUS +EfiLibHiiVariableOverrideBySuffix ( + IN CHAR16 *Suffix, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINTN Size, + OUT VOID *Var + ) +/*++ + +Routine Description: + Overrrides the variable with NV data if found. + But it only does it if the NV contains the same variable with Name is appended with Suffix. + For example, if Suffix="MyOverride" and the Name="XyzSetup", + the Suffix will be appended to the end of Name, and the variable with Name="XyzSetupMyOverride" + will be loaded from NV provided the variable exists and the GUID and Size matches. + +Arguments: + Suffix - Suffix the variable will be appended with. + Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly. + Var - Variable will be retrieved into this buffer. + Caller is responsible for providing storage of exactly Size size in bytes. + +Returns: + EFI_SUCCESS - The variable was overriden with NV variable of same Name/Guid/Size. + EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV. + EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error. + +--*/ +; + +#endif diff --git a/EdkModulePkg/Include/Library/EdkMemoryStatusCodeLib.h b/EdkModulePkg/Include/Library/EdkMemoryStatusCodeLib.h new file mode 100644 index 0000000000..08aaf69c47 --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkMemoryStatusCodeLib.h @@ -0,0 +1,48 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MemoryStatusCodeLib.h + +Abstract: + + Lib to provide memory status code reporting. + +--*/ + +#ifndef _PEI_MEMORY_STATUS_CODE_LIB_H_ +#define _PEI_MEMORY_STATUS_CODE_LIB_H_ + +// +// Initialization function +// +EFI_STATUS +MemoryStatusCodeInitialize ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +; + +// +// Status code reporting function +// +EFI_STATUS +MemoryReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +; + +#endif diff --git a/EdkModulePkg/Include/Library/EdkPeCoffLoaderLib.h b/EdkModulePkg/Include/Library/EdkPeCoffLoaderLib.h new file mode 100644 index 0000000000..ccacf7ee5e --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkPeCoffLoaderLib.h @@ -0,0 +1,32 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EdkPeCoffLoaderLib.h + +Abstract: + Wrap the Base PE/COFF loader with the PE COFF Protocol + + + +--*/ + +#ifndef __EDK_PE_COFF_LOADER_LIB__ +#define __EDK_PE_COFF_LOADER_LIB__ + +EFI_PEI_PE_COFF_LOADER_PROTOCOL * +EFIAPI +GetPeCoffLoaderProtocol ( + VOID + ); + +#endif diff --git a/EdkModulePkg/Include/Library/EdkPeCoffLoaderX64Lib.h b/EdkModulePkg/Include/Library/EdkPeCoffLoaderX64Lib.h new file mode 100644 index 0000000000..47756d3cf5 --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkPeCoffLoaderX64Lib.h @@ -0,0 +1,33 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EdkPeCoffLoaderX64Lib.h + +Abstract: + Wrap the Base PE/COFF loader with the PE COFF Protocol + + + +--*/ + +#ifndef __EDK_PE_COFF_LOADER_X64_LIB__ +#define __EDK_PE_COFF_LOADER_X64_LIB__ + +EFI_PEI_PE_COFF_LOADER_PROTOCOL * +EFIAPI +GetPeCoffLoaderX64Protocol ( + VOID + ); + +#endif + diff --git a/EdkModulePkg/Include/Library/EdkRtMemoryStatusCodeLib.h b/EdkModulePkg/Include/Library/EdkRtMemoryStatusCodeLib.h new file mode 100644 index 0000000000..02ae5a874e --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkRtMemoryStatusCodeLib.h @@ -0,0 +1,66 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RtMemoryStatusCodeLib.h + +Abstract: + + Lib to provide memory status code reporting. + +--*/ + +#ifndef _EFI_RT_MEMORY_STATUS_CODE_LIB_H_ +#define _EFI_RT_MEMORY_STATUS_CODE_LIB_H_ + +// +// Initialization function +// +VOID +RtMemoryStatusCodeInitialize ( + VOID + ) +; + +// +// Status code reporting function +// +EFI_STATUS +RtMemoryReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +; + +// +// Playback all prior status codes to a listener +// +typedef +EFI_STATUS +(*PLATFORM_REPORT_STATUS_CODE) ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ); + +VOID +PlaybackStatusCodes ( + IN PLATFORM_REPORT_STATUS_CODE ReportStatusCode + ) +; + +#endif diff --git a/EdkModulePkg/Include/Library/EdkRtPlatformStatusCodeLib.h b/EdkModulePkg/Include/Library/EdkRtPlatformStatusCodeLib.h new file mode 100644 index 0000000000..c0a690756e --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkRtPlatformStatusCodeLib.h @@ -0,0 +1,49 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RtPlatformStatusCodeLib.h + +Abstract: + + Lib to provide platform implementations necessary for the Monolithic status + code to work. + +--*/ + +#ifndef _EFI_PLATFORM_STATUS_CODE_LIB_H_ +#define _EFI_PLATFORM_STATUS_CODE_LIB_H_ + + +// +// Initialization function +// +VOID +RtPlatformStatusCodeInitialize ( + VOID + ) +; + +// +// Status code reporting function +// +EFI_STATUS +RtPlatformReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +; + +#endif diff --git a/EdkModulePkg/Include/Library/EdkScsiLib.h b/EdkModulePkg/Include/Library/EdkScsiLib.h new file mode 100644 index 0000000000..bb1a1adbb3 --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkScsiLib.h @@ -0,0 +1,299 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ScsiLib.h + + Abstract: + + Common Libarary for SCSI + + Revision History + +--*/ + +#ifndef _SCSI_LIB_H +#define _SCSI_LIB_H + +// +// the time unit is 100ns, since the SCSI I/O defines timeout in 100ns unit. +// +#define EFI_SCSI_STALL_1_MICROSECOND 10 +#define EFI_SCSI_STALL_1_MILLISECOND 10000 +#define EFI_SCSI_STALL_1_SECOND 10000000 + +// +// this macro cannot be directly used by the gBS->Stall(), +// since the value output by this macro is in 100ns unit, +// not 1us unit (1us = 1000ns) +// +#define EfiScsiStallSeconds(a) (a) * EFI_SCSI_STALL_1_SECOND + +EFI_STATUS +SubmitTestUnitReadyCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + OUT VOID *SenseData, + OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiIo - TODO: add argument description + Timeout - TODO: add argument description + SenseData - TODO: add argument description + SenseDataLength - TODO: add argument description + HostAdapterStatus - TODO: add argument description + TargetStatus - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SubmitInquiryCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *InquiryDataBuffer, + IN OUT UINT32 *InquiryDataLength, + IN BOOLEAN EnableVitalProductData + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiIo - TODO: add argument description + Timeout - TODO: add argument description + SenseData - TODO: add argument description + SenseDataLength - TODO: add argument description + HostAdapterStatus - TODO: add argument description + TargetStatus - TODO: add argument description + InquiryDataBuffer - TODO: add argument description + InquiryDataLength - TODO: add argument description + EnableVitalProductData - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SubmitModeSense10Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN VOID *DataBuffer, + IN OUT UINT32 *DataLength, + IN UINT8 DBDField, OPTIONAL + IN UINT8 PageControl, + IN UINT8 PageCode + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiIo - TODO: add argument description + Timeout - TODO: add argument description + SenseData - TODO: add argument description + SenseDataLength - TODO: add argument description + HostAdapterStatus - TODO: add argument description + TargetStatus - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + DBDField - TODO: add argument description + PageControl - TODO: add argument description + PageCode - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SubmitRequestSenseCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiIo - TODO: add argument description + Timeout - TODO: add argument description + SenseData - TODO: add argument description + SenseDataLength - TODO: add argument description + HostAdapterStatus - TODO: add argument description + TargetStatus - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// Commands for direct access command +// +EFI_STATUS +SubmitReadCapacityCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + OUT VOID *DataBuffer, + IN OUT UINT32 *DataLength, + IN BOOLEAN PMI + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiIo - TODO: add argument description + Timeout - TODO: add argument description + SenseData - TODO: add argument description + SenseDataLength - TODO: add argument description + HostAdapterStatus - TODO: add argument description + TargetStatus - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + PMI - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SubmitRead10Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + OUT VOID *DataBuffer, + IN OUT UINT32 *DataLength, + IN UINT32 StartLba, + IN UINT32 SectorSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiIo - TODO: add argument description + Timeout - TODO: add argument description + SenseData - TODO: add argument description + SenseDataLength - TODO: add argument description + HostAdapterStatus - TODO: add argument description + TargetStatus - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + StartLba - TODO: add argument description + SectorSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SubmitWrite10Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + OUT VOID *DataBuffer, + IN OUT UINT32 *DataLength, + IN UINT32 StartLba, + IN UINT32 SectorSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ScsiIo - TODO: add argument description + Timeout - TODO: add argument description + SenseData - TODO: add argument description + SenseDataLength - TODO: add argument description + HostAdapterStatus - TODO: add argument description + TargetStatus - TODO: add argument description + DataBuffer - TODO: add argument description + DataLength - TODO: add argument description + StartLba - TODO: add argument description + SectorSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Include/Library/EdkUsbLib.h b/EdkModulePkg/Include/Library/EdkUsbLib.h new file mode 100644 index 0000000000..005e045aac --- /dev/null +++ b/EdkModulePkg/Include/Library/EdkUsbLib.h @@ -0,0 +1,373 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + + UsbDxeLib.h + + Abstract: + + Common Dxe Libarary for USB + Add Constants & structure definitions for Usb HID + + Revision History + +--*/ + +#ifndef _USB_DXE_LIB_H +#define _USB_DXE_LIB_H + +// +// define the timeout time as 3ms +// +#define TIMEOUT_VALUE 3 * 1000 + +// +// HID constants definition, see HID rev1.0 +// +// +// HID report item format +// +#define HID_ITEM_FORMAT_SHORT 0 +#define HID_ITEM_FORMAT_LONG 1 + +// +// Special tag indicating long items +// +#define HID_ITEM_TAG_LONG 15 + +// +// HID report descriptor item type (prefix bit 2,3) +// +#define HID_ITEM_TYPE_MAIN 0 +#define HID_ITEM_TYPE_GLOBAL 1 +#define HID_ITEM_TYPE_LOCAL 2 +#define HID_ITEM_TYPE_RESERVED 3 + +// +// HID report descriptor main item tags +// +#define HID_MAIN_ITEM_TAG_INPUT 8 +#define HID_MAIN_ITEM_TAG_OUTPUT 9 +#define HID_MAIN_ITEM_TAG_FEATURE 11 +#define HID_MAIN_ITEM_TAG_BEGIN_COLLECTION 10 +#define HID_MAIN_ITEM_TAG_END_COLLECTION 12 + +// +// HID report descriptor main item contents +// +#define HID_MAIN_ITEM_CONSTANT 0x001 +#define HID_MAIN_ITEM_VARIABLE 0x002 +#define HID_MAIN_ITEM_RELATIVE 0x004 +#define HID_MAIN_ITEM_WRAP 0x008 +#define HID_MAIN_ITEM_NONLINEAR 0x010 +#define HID_MAIN_ITEM_NO_PREFERRED 0x020 +#define HID_MAIN_ITEM_NULL_STATE 0x040 +#define HID_MAIN_ITEM_VOLATILE 0x080 +#define HID_MAIN_ITEM_BUFFERED_BYTE 0x100 + +// +// HID report descriptor collection item types +// +#define HID_COLLECTION_PHYSICAL 0 +#define HID_COLLECTION_APPLICATION 1 +#define HID_COLLECTION_LOGICAL 2 + +// +// HID report descriptor global item tags +// +#define HID_GLOBAL_ITEM_TAG_USAGE_PAGE 0 +#define HID_GLOBAL_ITEM_TAG_LOGICAL_MINIMUM 1 +#define HID_GLOBAL_ITEM_TAG_LOGICAL_MAXIMUM 2 +#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MINIMUM 3 +#define HID_GLOBAL_ITEM_TAG_PHYSICAL_MAXIMUM 4 +#define HID_GLOBAL_ITEM_TAG_UNIT_EXPONENT 5 +#define HID_GLOBAL_ITEM_TAG_UNIT 6 +#define HID_GLOBAL_ITEM_TAG_REPORT_SIZE 7 +#define HID_GLOBAL_ITEM_TAG_REPORT_ID 8 +#define HID_GLOBAL_ITEM_TAG_REPORT_COUNT 9 +#define HID_GLOBAL_ITEM_TAG_PUSH 10 +#define HID_GLOBAL_ITEM_TAG_POP 11 + +// +// HID report descriptor local item tags +// +#define HID_LOCAL_ITEM_TAG_USAGE 0 +#define HID_LOCAL_ITEM_TAG_USAGE_MINIMUM 1 +#define HID_LOCAL_ITEM_TAG_USAGE_MAXIMUM 2 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_INDEX 3 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MINIMUM 4 +#define HID_LOCAL_ITEM_TAG_DESIGNATOR_MAXIMUM 5 +#define HID_LOCAL_ITEM_TAG_STRING_INDEX 7 +#define HID_LOCAL_ITEM_TAG_STRING_MINIMUM 8 +#define HID_LOCAL_ITEM_TAG_STRING_MAXIMUM 9 +#define HID_LOCAL_ITEM_TAG_DELIMITER 10 + +// +// HID usage tables +// +#define HID_USAGE_PAGE 0xffff0000 + +#define HID_UP_GENDESK 0x00010000 +#define HID_UP_KEYBOARD 0x00070000 +#define HID_UP_LED 0x00080000 +#define HID_UP_BUTTON 0x00090000 +#define HID_UP_CONSUMER 0x000c0000 +#define HID_UP_DIGITIZER 0x000d0000 +#define HID_UP_PID 0x000f0000 + +#define HID_USAGE 0x0000ffff + +#define HID_GD_POINTER 0x00010001 +#define HID_GD_MOUSE 0x00010002 +#define HID_GD_JOYSTICK 0x00010004 +#define HID_GD_GAMEPAD 0x00010005 +#define HID_GD_HATSWITCH 0x00010039 + +// +// HID report types +// +#define HID_INPUT_REPORT 1 +#define HID_OUTPUT_REPORT 2 +#define HID_FEATURE_REPORT 3 + +// +// HID device quirks. +// +#define HID_QUIRK_INVERT 0x01 +#define HID_QUIRK_NOTOUCH 0x02 + +// +// HID class protocol request +// +#define EFI_USB_GET_REPORT_REQUEST 0x01 +#define EFI_USB_GET_IDLE_REQUEST 0x02 +#define EFI_USB_GET_PROTOCOL_REQUEST 0x03 +#define EFI_USB_SET_REPORT_REQUEST 0x09 +#define EFI_USB_SET_IDLE_REQUEST 0x0a +#define EFI_USB_SET_PROTOCOL_REQUEST 0x0b + +#pragma pack(1) +// +// Descriptor header for Report/Physical Descriptors +// +typedef struct hid_class_descriptor { + UINT8 DescriptorType; + UINT16 DescriptorLength; +} EFI_USB_HID_CLASS_DESCRIPTOR; + +typedef struct hid_descriptor { + UINT8 Length; + UINT8 DescriptorType; + UINT16 BcdHID; + UINT8 CountryCode; + UINT8 NumDescriptors; + EFI_USB_HID_CLASS_DESCRIPTOR HidClassDesc[1]; +} EFI_USB_HID_DESCRIPTOR; + +#pragma pack() + +EFI_STATUS +UsbGetHidDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 InterfaceNum, + OUT EFI_USB_HID_DESCRIPTOR *HidDescriptor + ); + +EFI_STATUS +UsbGetReportDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 InterfaceNum, + IN UINT16 DescriptorSize, + OUT UINT8 *DescriptorBuffer + ); + +EFI_STATUS +UsbGetProtocolRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 *Protocol + ); + +EFI_STATUS +UsbSetProtocolRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 Protocol + ); + +EFI_STATUS +UsbSetIdleRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + IN UINT8 Duration + ); + +EFI_STATUS +UsbGetIdleRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + OUT UINT8 *Duration + ); + +EFI_STATUS +UsbSetReportRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + IN UINT8 ReportType, + IN UINT16 ReportLen, + IN UINT8 *Report + ); + +EFI_STATUS +UsbGetReportRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + IN UINT8 ReportType, + IN UINT16 ReportLen, + IN UINT8 *Report + ); + +// +// Get Device Descriptor +// +EFI_STATUS +UsbGetDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Value, + IN UINT16 Index, + IN UINT16 DescriptorLength, + OUT VOID *Descriptor, + OUT UINT32 *Status + ); + +// +// Set Device Descriptor +// +EFI_STATUS +UsbSetDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Value, + IN UINT16 Index, + IN UINT16 DescriptorLength, + IN VOID *Descriptor, + OUT UINT32 *Status + ); + +// +// Get device Interface +// +EFI_STATUS +UsbGetDeviceInterface ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Index, + OUT UINT8 *AltSetting, + OUT UINT32 *Status + ); + +// +// Set device interface +// +EFI_STATUS +UsbSetDeviceInterface ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 InterfaceNo, + IN UINT16 AltSetting, + OUT UINT32 *Status + ); + +// +// Get device configuration +// +EFI_STATUS +UsbGetDeviceConfiguration ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT UINT8 *ConfigValue, + OUT UINT32 *Status + ); + +// +// Set device configuration +// +EFI_STATUS +UsbSetDeviceConfiguration ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Value, + OUT UINT32 *Status + ); + +// +// Set Device Feature +// +EFI_STATUS +UsbSetDeviceFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN EFI_USB_RECIPIENT Recipient, + IN UINT16 Value, + IN UINT16 Target, + OUT UINT32 *Status + ); + +// +// Clear Device Feature +// +EFI_STATUS +UsbClearDeviceFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN EFI_USB_RECIPIENT Recipient, + IN UINT16 Value, + IN UINT16 Target, + OUT UINT32 *Status + ); + +// +// Get Device Status +// +EFI_STATUS +UsbGetDeviceStatus ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN EFI_USB_RECIPIENT Recipient, + IN UINT16 Target, + OUT UINT16 *DevStatus, + OUT UINT32 *Status + ); + +// +// The following APIs are not basic library, but they are common used. +// +// +// Usb Get String +// +EFI_STATUS +UsbGetString ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 LangID, + IN UINT8 Index, + IN VOID *Buf, + IN UINTN BufSize, + OUT UINT32 *Status + ); + +// +// Clear endpoint stall +// +EFI_STATUS +UsbClearEndpointHalt ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 EndpointNo, + OUT UINT32 *Status + ); + +#endif diff --git a/EdkModulePkg/Include/Library/TianoDecompressLib.h b/EdkModulePkg/Include/Library/TianoDecompressLib.h new file mode 100644 index 0000000000..58e9426a31 --- /dev/null +++ b/EdkModulePkg/Include/Library/TianoDecompressLib.h @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + TianoDecompressLib.h + +Abstract: + + Tiano Decompress functions + +--*/ + +#ifndef __TIANO_DECPOMPRESS_LIB_H__ +#define __TIANO_DECPOMPRESS_LIB_H__ + +RETURN_STATUS +EFIAPI +TianoDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +RETURN_STATUS +EFIAPI +TianoDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ); + +#endif diff --git a/EdkModulePkg/Include/Ppi/BaseMemoryTest.h b/EdkModulePkg/Include/Ppi/BaseMemoryTest.h new file mode 100644 index 0000000000..8b0be6e130 --- /dev/null +++ b/EdkModulePkg/Include/Ppi/BaseMemoryTest.h @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BaseMemoryTest.h + +Abstract: + + Pei memory test PPI as defined in Tiano + + Used to Pei memory test in PEI + +--*/ + +#ifndef _BASE_MEMORY_TEST_H_ +#define _BASE_MEMORY_TEST_H_ + +#define PEI_BASE_MEMORY_TEST_GUID \ + { 0xb6ec423c, 0x21d2, 0x490d, {0x85, 0xc6, 0xdd, 0x58, 0x64, 0xea, 0xa6, 0x74 } } + +typedef struct _PEI_BASE_MEMORY_TEST_PPI PEI_BASE_MEMORY_TEST_PPI; + +typedef enum { + Ignore, + Quick, + Sparse, + Extensive +} PEI_MEMORY_TEST_OP; + +typedef +EFI_STATUS +(EFIAPI *PEI_BASE_MEMORY_TEST) ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_BASE_MEMORY_TEST_PPI * This, + IN EFI_PHYSICAL_ADDRESS BeginAddress, + IN UINT64 MemoryLength, + IN PEI_MEMORY_TEST_OP Operation, + OUT EFI_PHYSICAL_ADDRESS * ErrorAddress + ); + +struct _PEI_BASE_MEMORY_TEST_PPI { + PEI_BASE_MEMORY_TEST BaseMemoryTest; +}; + +extern EFI_GUID gPeiBaseMemoryTestPpiGuid; + +#endif diff --git a/EdkModulePkg/Include/Ppi/FlashMap.h b/EdkModulePkg/Include/Ppi/FlashMap.h new file mode 100644 index 0000000000..312f38b416 --- /dev/null +++ b/EdkModulePkg/Include/Ppi/FlashMap.h @@ -0,0 +1,52 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FlashMap.h + +Abstract: + + FlashMap PPI defined in Tiano + + This code abstracts FlashMap access + +--*/ + +#ifndef _PEI_FLASH_MAP_PPI_H_ +#define _PEI_FLASH_MAP_PPI_H_ + +#define PEI_FLASH_MAP_PPI_GUID \ + { 0xf34c2fa0, 0xde88, 0x4270, {0x84, 0x14, 0x96, 0x12, 0x22, 0xf4, 0x52, 0x1c } } + +typedef struct _PEI_FLASH_MAP_PPI PEI_FLASH_MAP_PPI; +// +// Functions +// +typedef +EFI_STATUS +(EFIAPI *PEI_GET_FLASH_AREA_INFO) ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_FLASH_MAP_PPI *This, + IN EFI_FLASH_AREA_TYPE AreaType, + IN EFI_GUID *AreaTypeGuid, + OUT UINT32 *NumEntries, + OUT EFI_FLASH_SUBAREA_ENTRY **Entries + ); + + +struct _PEI_FLASH_MAP_PPI { + PEI_GET_FLASH_AREA_INFO GetAreaInfo; +}; + +extern EFI_GUID gPeiFlashMapPpiGuid; + +#endif diff --git a/EdkModulePkg/Include/Ppi/PeiInMemory.h b/EdkModulePkg/Include/Ppi/PeiInMemory.h new file mode 100644 index 0000000000..74d0905766 --- /dev/null +++ b/EdkModulePkg/Include/Ppi/PeiInMemory.h @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeiInMemory.h + +Abstract: + + +--*/ + +#ifndef __PEI_IN_MEMORY_H__ +#define __PEI_IN_MEMORY_H__ + +#define PEI_IN_MEMORY_GUID \ + {0x643b8786, 0xb417, 0x48d2, {0x8f, 0x5e, 0x78, 0x19, 0x93, 0x1c, 0xae, 0xd8} } + +extern EFI_GUID gPeiInMemoryGuid; + +#endif diff --git a/EdkModulePkg/Include/Ppi/StatusCodeMemory.h b/EdkModulePkg/Include/Ppi/StatusCodeMemory.h new file mode 100644 index 0000000000..85b2b6de5f --- /dev/null +++ b/EdkModulePkg/Include/Ppi/StatusCodeMemory.h @@ -0,0 +1,53 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + StatusCodeMemory.h + +Abstract: + + Status Code memory descriptor PPI. Contains information about memory that + the Status Code PEIM may use to journal Status Codes. + +--*/ + +#ifndef _PEI_STATUS_CODE_MEMORY_PPI_H_ +#define _PEI_STATUS_CODE_MEMORY_PPI_H_ + +// +// GUID definition +// +#define PEI_STATUS_CODE_MEMORY_PPI_GUID \ + { 0x26f8ab01, 0xd3cd, 0x489c, {0x98, 0x4f, 0xdf, 0xde, 0xf7, 0x68, 0x39, 0x5b } } + +// +// Data types +// +typedef struct { + EFI_STATUS_CODE_TYPE Type; + EFI_STATUS_CODE_VALUE Value; + UINT32 Instance; +} EFI_STATUS_CODE_ENTRY; + +// +// PPI definition +// +typedef struct { + UINTN FirstEntry; + UINTN LastEntry; + EFI_PHYSICAL_ADDRESS Address; + UINTN Length; +} PEI_STATUS_CODE_MEMORY_PPI; + +extern EFI_GUID gPeiStatusCodeMemoryPpiGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/AcpiS3Save.h b/EdkModulePkg/Include/Protocol/AcpiS3Save.h new file mode 100644 index 0000000000..1571e3dcd2 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/AcpiS3Save.h @@ -0,0 +1,61 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + AcpiS3Save.h + +Abstract: + + +--*/ + +#ifndef _ACPI_S3_SAVE_PROTOCOL_H +#define _ACPI_S3_SAVE_PROTOCOL_H + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_ACPI_S3_SAVE_PROTOCOL EFI_ACPI_S3_SAVE_PROTOCOL; + +// +// S3 Save Protocol GUID +// +#define EFI_ACPI_S3_SAVE_GUID \ + { \ + 0x125f2de1, 0xfb85, 0x440c, {0xa5, 0x4c, 0x4d, 0x99, 0x35, 0x8a, 0x8d, 0x38 } \ + } + +// +// Protocol Data Structures +// +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_S3_SAVE) ( + IN EFI_ACPI_S3_SAVE_PROTOCOL * This, + IN VOID * LegacyMemoryAddress + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_GET_LEGACY_MEMORY_SIZE) ( + IN EFI_ACPI_S3_SAVE_PROTOCOL * This, + OUT UINTN * Size +); + +struct _EFI_ACPI_S3_SAVE_PROTOCOL { + EFI_ACPI_GET_LEGACY_MEMORY_SIZE GetLegacyMemorySize; + EFI_ACPI_S3_SAVE S3Save; +}; + +extern EFI_GUID gEfiAcpiS3SaveProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/ConsoleControl.h b/EdkModulePkg/Include/Protocol/ConsoleControl.h new file mode 100644 index 0000000000..c894302c66 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/ConsoleControl.h @@ -0,0 +1,121 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ConsoleControl.h + +Abstract: + + Abstraction of a Text mode or UGA screen + +--*/ + +#ifndef __CONSOLE_CONTROL_H__ +#define __CONSOLE_CONTROL_H__ + +#define EFI_CONSOLE_CONTROL_PROTOCOL_GUID \ + { 0xf42f7782, 0x12e, 0x4c12, {0x99, 0x56, 0x49, 0xf9, 0x43, 0x4, 0xf7, 0x21 } } + +typedef struct _EFI_CONSOLE_CONTROL_PROTOCOL EFI_CONSOLE_CONTROL_PROTOCOL; + + +typedef enum { + EfiConsoleControlScreenText, + EfiConsoleControlScreenGraphics, + EfiConsoleControlScreenMaxValue +} EFI_CONSOLE_CONTROL_SCREEN_MODE; + + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *UgaExists, OPTIONAL + OUT BOOLEAN *StdInLocked OPTIONAL + ) +/*++ + + Routine Description: + Return the current video mode information. Also returns info about existence + of UGA Draw devices in system, and if the Std In device is locked. All the + arguments are optional and only returned if a non NULL pointer is passed in. + + Arguments: + This - Protocol instance pointer. + Mode - Are we in text of grahics mode. + UgaExists - TRUE if UGA Spliter has found a UGA device + StdInLocked - TRUE if StdIn device is keyboard locked + + Returns: + EFI_SUCCESS - Mode information returned. + +--*/ +; + + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ) +/*++ + + Routine Description: + Set the current mode to either text or graphics. Graphics is + for Quiet Boot. + + Arguments: + This - Protocol instance pointer. + Mode - Mode to set the + + Returns: + EFI_SUCCESS - Mode information returned. + +--*/ +; + + +typedef +EFI_STATUS +(EFIAPI *EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN) ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password + ) +/*++ + + Routine Description: + Lock Std In devices until Password is typed. + + Arguments: + This - Protocol instance pointer. + Password - Password needed to unlock screen. NULL means unlock keyboard + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_DEVICE_ERROR - Std In not locked + +--*/ +; + + + +struct _EFI_CONSOLE_CONTROL_PROTOCOL { + EFI_CONSOLE_CONTROL_PROTOCOL_GET_MODE GetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_SET_MODE SetMode; + EFI_CONSOLE_CONTROL_PROTOCOL_LOCK_STD_IN LockStdIn; +}; + +extern EFI_GUID gEfiConsoleControlProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/CustomizedDecompress.h b/EdkModulePkg/Include/Protocol/CustomizedDecompress.h new file mode 100644 index 0000000000..bff8d46e88 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/CustomizedDecompress.h @@ -0,0 +1,137 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + CustomizedDecompress.h + +Abstract: + The user Customized Decompress Protocol Interface + +--*/ + +#ifndef __CUSTOMIZED_DECOMPRESS_H__ +#define __CUSTOMIZED_DECOMPRESS_H__ + +#define EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL_GUID \ + { 0x9a44198e, 0xa4a2, 0x44e6, {0x8a, 0x1f, 0x39, 0xbe, 0xfd, 0xac, 0x89, 0x6f } } + +typedef struct _EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *EFI_CUSTOMIZED_DECOMPRESS_GET_INFO) ( + IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); +/*++ + +Routine Description: + + The GetInfo() function retrieves the size of the uncompressed buffer + and the temporary scratch buffer required to decompress the buffer + specified by Source and SourceSize. If the size of the uncompressed + buffer or the size of the scratch buffer cannot be determined from + the compressed data specified by Source and SourceData, then + EFI_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed + buffer is returned in DestinationSize, the size of the scratch buffer is + returned in ScratchSize, and EFI_SUCCESS is returned. + + The GetInfo() function does not have scratch buffer available to perform + a thorough checking of the validity of the source data. It just retrieves + the 'Original Size' field from the beginning bytes of the source data and + output it as DestinationSize. And ScratchSize is specific to the decompression + implementation. + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SourceSize - The size, in bytes, of source buffer. + DestinationSize - A pointer to the size, in bytes, of the uncompressed buffer + that will be generated when the compressed buffer specified + by Source and SourceSize is decompressed. + ScratchSize - A pointer to the size, in bytes, of the scratch buffer that + is required to decompress the compressed buffer specified by + Source and SourceSize. + +Returns: + EFI_SUCCESS - The size of the uncompressed data was returned in DestinationSize + and the size of the scratch buffer was returned in ScratchSize. + EFI_INVALID_PARAMETER - The size of the uncompressed data or the size of the scratch + buffer cannot be determined from the compressed data specified by + Source and SourceData. + +--*/ + + +typedef +EFI_STATUS +(EFIAPI *EFI_CUSTOMIZED_DECOMPRESS_DECOMPRESS) ( + IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This, + IN VOID* Source, + IN UINT32 SourceSize, + IN OUT VOID* Destination, + IN UINT32 DestinationSize, + IN OUT VOID* Scratch, + IN UINT32 ScratchSize + ); +/*++ + +Routine Description: + + The Decompress() function extracts decompressed data to its original form. + + This protocol is designed so that the decompression algorithm can be + implemented without using any memory services. As a result, the + Decompress() function is not allowed to call AllocatePool() or + AllocatePages() in its implementation. It is the caller's responsibility + to allocate and free the Destination and Scratch buffers. + + If the compressed source data specified by Source and SourceSize is + sucessfully decompressed into Destination, then EFI_SUCCESS is returned. + If the compressed source data specified by Source and SourceSize is not in + a valid compressed data format, then EFI_INVALID_PARAMETER is returned. + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SourceSize - The size of source data. + Destination - On output, the destination buffer that contains + the uncompressed data. + DestinationSize - The size of destination buffer. The size of destination + buffer needed is obtained from GetInfo(). + Scratch - A temporary scratch buffer that is used to perform the + decompression. + ScratchSize - The size of scratch buffer. The size of scratch buffer needed + is obtained from GetInfo(). + +Returns: + + EFI_SUCCESS - Decompression completed successfully, and the uncompressed + buffer is returned in Destination. + EFI_INVALID_PARAMETER + - The source buffer specified by Source and SourceSize is + corrupted (not in a valid compressed format). + +--*/ + +struct _EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL { + EFI_CUSTOMIZED_DECOMPRESS_GET_INFO GetInfo; + EFI_CUSTOMIZED_DECOMPRESS_DECOMPRESS Decompress; +}; + +extern EFI_GUID gEfiCustomizedDecompressProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/DebugAssert.h b/EdkModulePkg/Include/Protocol/DebugAssert.h new file mode 100644 index 0000000000..9d26d83277 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/DebugAssert.h @@ -0,0 +1,89 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugAssert.h + +Abstract: + + This protocol allows provides debug services to a driver. This is not + debugger support, but things like ASSERT() and DEBUG() macros + +--*/ + +#ifndef _DEBUG_ASSERT_H_ +#define _DEBUG_ASSERT_H_ + + +#define EFI_DEBUG_ASSERT_PROTOCOL_GUID \ + { 0xbe499c92, 0x7d4b, 0x11d4, {0xbc, 0xee, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_DEBUG_ASSERT_PROTOCOL EFI_DEBUG_ASSERT_PROTOCOL; + + +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUG_ASSERT) ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUG_PRINT) ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN UINTN ErrorLevel, + IN CHAR8 *Format, + IN VA_LIST Marker + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_POST_CODE) ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN UINT16 PostCode, + IN CHAR8 *PostCodeString OPTIONAL + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_GET_ERROR_LEVEL) ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN UINTN *ErrorLevel + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SET_ERROR_LEVEL) ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN UINTN ErrorLevel + ); + +struct _EFI_DEBUG_ASSERT_PROTOCOL { + + EFI_DEBUG_ASSERT Assert; + EFI_DEBUG_PRINT Print; + EFI_POST_CODE PostCode; + + EFI_GET_ERROR_LEVEL GetErrorLevel; + EFI_SET_ERROR_LEVEL SetErrorLevel; + +}; + +extern EFI_GUID gEfiDebugAssertProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/DebugLevel.h b/EdkModulePkg/Include/Protocol/DebugLevel.h new file mode 100644 index 0000000000..9c5f06a21f --- /dev/null +++ b/EdkModulePkg/Include/Protocol/DebugLevel.h @@ -0,0 +1,40 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugLevel.h + +Abstract: + This protocol is used to abstract the Debug Mask serivces for + the specific driver or application image. + +--*/ + +#ifndef __DEBUG_LEVEL_H__ +#define __DEBUG_LEVEL_H__ + +// +// 8D4C62E6-CD98-4e1d-AD6E-48BB50D29FF7 +// +#define EFI_DEBUG_LEVEL_PROTOCOL_GUID \ + { 0x8d4c62e6, 0xcd98, 0x4e1d, {0xad, 0x6e, 0x48, 0xbb, 0x50, 0xd2, 0x9f, 0xf7 } } + +// +// DebugLevel protocol definition +// +typedef struct _EFI_DEBUG_LEVEL_PROTOCOL { + UINTN DebugLevel; +} EFI_DEBUG_LEVEL_PROTOCOL; + +extern EFI_GUID gEfiDebugLevelProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/DiskInfo.h b/EdkModulePkg/Include/Protocol/DiskInfo.h new file mode 100644 index 0000000000..6952163c22 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/DiskInfo.h @@ -0,0 +1,179 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DiskInfo.h + +Abstract: + + Disk Info protocol is used to export Inquiry Data for a drive. + Its needed to support low level formating of drives in a mannor + thats DOS compatible. + +--*/ + +#ifndef __DISK_INFO_H__ +#define __DISK_INFO_H__ + +#define EFI_DISK_INFO_PROTOCOL_GUID \ + { \ + 0xd432a67f, 0x14dc, 0x484b, {0xb3, 0xbb, 0x3f, 0x2, 0x91, 0x84, 0x93, 0x27 } \ + } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_DISK_INFO_PROTOCOL EFI_DISK_INFO_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_INFO_INQUIRY) ( + IN EFI_DISK_INFO_PROTOCOL * This, + IN OUT VOID *InquiryData, + IN OUT UINT32 *IntquiryDataSize + ) +/*++ + + Routine Description: + Return the results of the Inquiry command to a drive in InquiryData. + Data format of Inquiry data is defined by the Interface GUID. + + Arguments: + This - Protocol instance pointer. + InquiryData - Results of Inquiry command to device + InquiryDataSize - Size of InquiryData in bytes. + + Returns: + EFI_SUCCESS - InquiryData valid + EFI_NOT_FOUND - Device does not support this data class + EFI_DEVICE_ERROR - Error reading InquiryData from device + EFI_BUFFER_TOO_SMALL - IntquiryDataSize not big enough + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_INFO_IDENTIFY) ( + IN EFI_DISK_INFO_PROTOCOL * This, + IN OUT VOID *IdentifyData, + IN OUT UINT32 *IdentifyDataSize + ) +/*++ + + Routine Description: + Return the results of the Identify command to a drive in IdentifyData. + Data format of Identify data is defined by the Interface GUID. + + Arguments: + This - Protocol instance pointer. + IdentifyData - Results of Identify command to device + IdentifyDataSize - Size of IdentifyData in bytes. + + Returns: + EFI_SUCCESS - IdentifyData valid + EFI_NOT_FOUND - Device does not support this data class + EFI_DEVICE_ERROR - Error reading IdentifyData from device + EFI_BUFFER_TOO_SMALL - IdentifyDataSize not big enough + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_INFO_SENSE_DATA) ( + IN EFI_DISK_INFO_PROTOCOL * This, + IN OUT VOID *SenseData, + IN OUT UINT32 *SenseDataSize, + OUT UINT8 *SenseDataNumber + ) +/*++ + + Routine Description: + Return the results of the Request Sense command to a drive in SenseData. + Data format of Sense data is defined by the Interface GUID. + + Arguments: + This - Protocol instance pointer. + SenseData - Results of Request Sense command to device + SenseDataSize - Size of SenseData in bytes. + SenseDataNumber - Type of SenseData + + Returns: + EFI_SUCCESS - InquiryData valid + EFI_NOT_FOUND - Device does not support this data class + EFI_DEVICE_ERROR - Error reading InquiryData from device + EFI_BUFFER_TOO_SMALL - SenseDataSize not big enough + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_INFO_WHICH_IDE) ( + IN EFI_DISK_INFO_PROTOCOL * This, + OUT UINT32 *IdeChannel, + OUT UINT32 *IdeDevice + ) +/*++ + + Routine Description: + Return the results of the Request Sense command to a drive in SenseData. + Data format of Sense data is defined by the Interface GUID. + + Arguments: + This - Protocol instance pointer. + IdeChannel - Primary or Secondary + IdeDevice - Master or Slave + + Returns: + EFI_SUCCESS - IdeChannel and IdeDevice are valid + EFI_UNSUPPORTED - This is not an IDE device + +--*/ +; + +// +// GUIDs for EFI_DISK_INFO_PROTOCOL.Interface. Defines the format of the +// buffers returned by member functions +// +#define EFI_DISK_INFO_IDE_INTERFACE_GUID \ + { \ + 0x5e948fe3, 0x26d3, 0x42b5, {0xaf, 0x17, 0x61, 0x2, 0x87, 0x18, 0x8d, 0xec } \ + } +extern EFI_GUID gEfiDiskInfoIdeInterfaceGuid; + +#define EFI_DISK_INFO_SCSI_INTERFACE_GUID \ + { \ + 0x8f74baa, 0xea36, 0x41d9, {0x95, 0x21, 0x21, 0xa7, 0xf, 0x87, 0x80, 0xbc } \ + } +extern EFI_GUID gEfiDiskInfoScsiInterfaceGuid; + +#define EFI_DISK_INFO_USB_INTERFACE_GUID \ + { \ + 0xcb871572, 0xc11a, 0x47b5, {0xb4, 0x92, 0x67, 0x5e, 0xaf, 0xa7, 0x77, 0x27 } \ + } +extern EFI_GUID gEfiDiskInfoUsbInterfaceGuid; + +struct _EFI_DISK_INFO_PROTOCOL { + EFI_GUID Interface; + EFI_DISK_INFO_INQUIRY Inquiry; + EFI_DISK_INFO_IDENTIFY Identify; + EFI_DISK_INFO_SENSE_DATA SenseData; + EFI_DISK_INFO_WHICH_IDE WhichIde; +}; + +extern EFI_GUID gEfiDiskInfoProtocolGuid; + +#endif + + diff --git a/EdkModulePkg/Include/Protocol/EdkDecompress.h b/EdkModulePkg/Include/Protocol/EdkDecompress.h new file mode 100644 index 0000000000..ab9b840cf2 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/EdkDecompress.h @@ -0,0 +1,137 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + EdkDecompress.h + +Abstract: + The Tiano Decompress Protocol Interface + +--*/ + +#ifndef __EDK_DECOMPRESS_H__ +#define __EDK_DECOMPRESS_H__ + +#define EFI_TIANO_DECOMPRESS_PROTOCOL_GUID \ + { 0xe84cf29c, 0x191f, 0x4eae, {0x96, 0xe1, 0xf4, 0x6a, 0xec, 0xea, 0xea, 0x0b } } + +typedef struct _EFI_TIANO_DECOMPRESS_PROTOCOL EFI_TIANO_DECOMPRESS_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *EFI_TIANO_DECOMPRESS_GET_INFO) ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); +/*++ + +Routine Description: + + The GetInfo() function retrieves the size of the uncompressed buffer + and the temporary scratch buffer required to decompress the buffer + specified by Source and SourceSize. If the size of the uncompressed + buffer or the size of the scratch buffer cannot be determined from + the compressed data specified by Source and SourceData, then + EFI_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed + buffer is returned in DestinationSize, the size of the scratch buffer is + returned in ScratchSize, and EFI_SUCCESS is returned. + + The GetInfo() function does not have scratch buffer available to perform + a thorough checking of the validity of the source data. It just retrieves + the 'Original Size' field from the beginning bytes of the source data and + output it as DestinationSize. And ScratchSize is specific to the decompression + implementation. + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SourceSize - The size, in bytes, of source buffer. + DestinationSize - A pointer to the size, in bytes, of the uncompressed buffer + that will be generated when the compressed buffer specified + by Source and SourceSize is decompressed. + ScratchSize - A pointer to the size, in bytes, of the scratch buffer that + is required to decompress the compressed buffer specified by + Source and SourceSize. + +Returns: + EFI_SUCCESS - The size of the uncompressed data was returned in DestinationSize + and the size of the scratch buffer was returned in ScratchSize. + EFI_INVALID_PARAMETER - The size of the uncompressed data or the size of the scratch + buffer cannot be determined from the compressed data specified by + Source and SourceData. + +--*/ + + +typedef +EFI_STATUS +(EFIAPI *EFI_TIANO_DECOMPRESS_DECOMPRESS) ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID* Source, + IN UINT32 SourceSize, + IN OUT VOID* Destination, + IN UINT32 DestinationSize, + IN OUT VOID* Scratch, + IN UINT32 ScratchSize + ); +/*++ + +Routine Description: + + The Decompress() function extracts decompressed data to its original form. + + This protocol is designed so that the decompression algorithm can be + implemented without using any memory services. As a result, the + Decompress() function is not allowed to call AllocatePool() or + AllocatePages() in its implementation. It is the caller's responsibility + to allocate and free the Destination and Scratch buffers. + + If the compressed source data specified by Source and SourceSize is + sucessfully decompressed into Destination, then EFI_SUCCESS is returned. + If the compressed source data specified by Source and SourceSize is not in + a valid compressed data format, then EFI_INVALID_PARAMETER is returned. + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SourceSize - The size of source data. + Destination - On output, the destination buffer that contains + the uncompressed data. + DestinationSize - The size of destination buffer. The size of destination + buffer needed is obtained from GetInfo(). + Scratch - A temporary scratch buffer that is used to perform the + decompression. + ScratchSize - The size of scratch buffer. The size of scratch buffer needed + is obtained from GetInfo(). + +Returns: + + EFI_SUCCESS - Decompression completed successfully, and the uncompressed + buffer is returned in Destination. + EFI_INVALID_PARAMETER + - The source buffer specified by Source and SourceSize is + corrupted (not in a valid compressed format). + +--*/ + +struct _EFI_TIANO_DECOMPRESS_PROTOCOL { + EFI_TIANO_DECOMPRESS_GET_INFO GetInfo; + EFI_TIANO_DECOMPRESS_DECOMPRESS Decompress; +}; + +extern EFI_GUID gEfiTianoDecompressProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/ExtendedSalBootService.h b/EdkModulePkg/Include/Protocol/ExtendedSalBootService.h new file mode 100644 index 0000000000..28aceb3758 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/ExtendedSalBootService.h @@ -0,0 +1,113 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ExtendedSalBootService.h + +Abstract: + +--*/ + +#ifndef _EXTENDED_SAL_PROTOCOL_H_ +#define _EXTENDED_SAL_PROTOCOL_H_ + +#define EXTENDED_SAL_BOOT_SERVICE_PROTOCOL_GUID \ + {0xde0ee9a4,0x3c7a,0x44f2, {0xb7,0x8b,0xe3,0xcc,0xd6,0x9c,0x3a,0xf7}} + +#define EXTENDED_SAL_SIGNATURE EFI_SIGNATURE_32('e', 's', 'a', 'l') + +#define SAL_MIN_STATE_SIZE 0x400 * 1 +#define PAL_SCARTCH_SIZE 0x400 * 3 +#define ALIGN_MINSTATE_SIZE 512 +#define MAX_SAL_RECORD_SIZE 8*1024 + +#define SAL_RUNTIMESERVICE + +typedef UINT16 EFI_SAL_PROCESSOR_ID; + +typedef struct _EXTENDED_SAL_BOOT_SERVICE_PROTOCOL EXTENDED_SAL_BOOT_SERVICE_PROTOCOL; + +typedef +SAL_RUNTIMESERVICE +SAL_RETURN_REGS +(EFIAPI *SAL_EXTENDED_SAL_PROC) ( + IN EFI_GUID *ClassGuid, + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8 + ); + +typedef +SAL_RUNTIMESERVICE +SAL_RETURN_REGS +(EFIAPI *SAL_INTERNAL_EXTENDED_SAL_PROC) ( + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + IN SAL_EXTENDED_SAL_PROC ExtendedSalProc, + IN BOOLEAN VirtualMode, + IN VOID *ModuleGlobal + ); + +typedef +EFI_STATUS +(EFIAPI *EXTENDED_SAL_ADD_SST_INFO) ( + IN EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *This, + IN UINT16 SalAVersion, + IN UINT16 SalBVersion, + IN CHAR8 *OemId, + IN CHAR8 *ProductId + ); + +typedef +EFI_STATUS +(EFIAPI *EXTENDED_SAL_ADD_SST_ENTRY) ( + IN EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *This, + IN UINT8 EntryType, + IN UINT8 *TableEntry, + IN UINTN EntrySize + ); + +typedef +EFI_STATUS +(EFIAPI *EXTENDED_SAL_REGISTER_INTERNAL_PROC) ( + IN EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *This, + IN EFI_GUID *ClassGuid, + IN UINT64 FunctionId, + IN SAL_INTERNAL_EXTENDED_SAL_PROC InternalSalProc, + IN VOID *PhysicalModuleGlobal + ); + +// +// Extended Sal Boot Service Protocol Interface +// +struct _EXTENDED_SAL_BOOT_SERVICE_PROTOCOL{ + EXTENDED_SAL_ADD_SST_INFO AddSalSystemTableInfo; + EXTENDED_SAL_ADD_SST_ENTRY AddSalSystemTableEntry; + EXTENDED_SAL_REGISTER_INTERNAL_PROC AddExtendedSalProc; + SAL_EXTENDED_SAL_PROC ExtendedSalProc; + SAL_PROC SalProc; +}; + +extern EFI_GUID gEfiExtendedSalBootServiceProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/FaultTolerantWriteLite.h b/EdkModulePkg/Include/Protocol/FaultTolerantWriteLite.h new file mode 100644 index 0000000000..c3ec825461 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/FaultTolerantWriteLite.h @@ -0,0 +1,88 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FaultTolerantWriteLite.h + +Abstract: + + This is a simple fault tolerant write driver, based on PlatformFd library. + And it only supports write BufferSize <= SpareAreaLength. + +--*/ + +#ifndef _FW_FAULT_TOLERANT_WRITE_LITE_PROTOCOL_H_ +#define _FW_FAULT_TOLERANT_WRITE_LITE_PROTOCOL_H_ + +#define EFI_FTW_LITE_PROTOCOL_GUID \ +{ 0x3f557189, 0x8dae, 0x45ae, {0xa0, 0xb3, 0x2b, 0x99, 0xca, 0x7a, 0xa7, 0xa0 } } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_FTW_LITE_PROTOCOL EFI_FTW_LITE_PROTOCOL; + +// +// Protocol API definitions +// + +typedef +EFI_STATUS +(EFIAPI * EFI_FTW_LITE_WRITE) ( + IN EFI_FTW_LITE_PROTOCOL *This, + IN EFI_HANDLE FvbHandle, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN VOID *Buffer + ); +/*++ + +Routine Description: + + Starts a target block update. This records information about the write + in fault tolerant storage and will complete the write in a recoverable + manner, ensuring at all times that either the original contents or + the modified contents are available. + +Arguments: + + This - Calling context + FvBlockHandle - The handle of FVB protocol that provides services for + reading, writing, and erasing the target block. + Lba - The logical block address of the target block. + Offset - The offset within the target block to place the data. + Length - The number of bytes to write to the target block. + Buffer - The data to write. + +Returns: + + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully. + EFI_BAD_BUFFER_SIZE - The write would span a block boundary, + which is not a valid action. + EFI_ACCESS_DENIED - No writes have been allocated. + EFI_NOT_READY - The last write has not been completed. + Restart () must be called to complete it. + +--*/ + +// +// Protocol declaration +// +struct _EFI_FTW_LITE_PROTOCOL { + EFI_FTW_LITE_WRITE Write; +}; + +extern EFI_GUID gEfiFaultTolerantWriteLiteProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/FvbExtension.h b/EdkModulePkg/Include/Protocol/FvbExtension.h new file mode 100644 index 0000000000..c2be78b8e4 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/FvbExtension.h @@ -0,0 +1,53 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FvbExtension.h + +Abstract: + + FVB Extension protocol that extends the FVB Class in a component fashion. + +--*/ + +#ifndef _FVB_EXTENSION_H_ +#define _FVB_EXTENSION_H_ + +#define EFI_FVB_EXTENSION_PROTOCOL_GUID \ + {0x53a4c71b, 0xb581, 0x4170, {0x91, 0xb3, 0x8d, 0xb8, 0x7a, 0x4b, 0x5c, 0x46 } } + +typedef struct _EFI_FVB_EXTENSION_PROTOCOL EFI_FVB_EXTENSION_PROTOCOL; + +// +// FVB Extension Function Prototypes +// +typedef +EFI_STATUS +(EFIAPI * EFI_FV_ERASE_CUSTOM_BLOCK) ( + IN EFI_FVB_EXTENSION_PROTOCOL *This, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba +); + +// +// IPMI TRANSPORT PROTOCOL +// +struct _EFI_FVB_EXTENSION_PROTOCOL { + EFI_FV_ERASE_CUSTOM_BLOCK EraseFvbCustomBlock; +}; + +extern EFI_GUID gEfiFvbExtensionProtocolGuid; + +#endif + diff --git a/EdkModulePkg/Include/Protocol/GenericMemoryTest.h b/EdkModulePkg/Include/Protocol/GenericMemoryTest.h new file mode 100644 index 0000000000..8f566d3763 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/GenericMemoryTest.h @@ -0,0 +1,156 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + GenericMemoryTest.h + +Abstract: + + The EFI generic memory test protocol + For more information please look at EfiMemoryTest.doc + +--*/ + +#ifndef __GENERIC_MEMORY_TEST_H__ +#define __GENERIC_MEMORY_TEST_H__ + +#define EFI_GENERIC_MEMORY_TEST_PROTOCOL_GUID \ + { 0x309de7f1, 0x7f5e, 0x4ace, {0xb4, 0x9c, 0x53, 0x1b, 0xe5, 0xaa, 0x95, 0xef} } + +typedef struct _EFI_GENERIC_MEMORY_TEST_PROTOCOL EFI_GENERIC_MEMORY_TEST_PROTOCOL; + +typedef enum { + IGNORE, + QUICK, + SPARSE, + EXTENSIVE, + MAXLEVEL +} EXTENDMEM_COVERAGE_LEVEL; + +typedef +EFI_STATUS +(EFIAPI *EFI_MEMORY_TEST_INIT) ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This, + IN EXTENDMEM_COVERAGE_LEVEL Level, + OUT BOOLEAN *RequireSoftECCInit + ) +/*++ + + Routine Description: + Initialize the generic memory test. + + Arguments: + This - Protocol instance pointer. + Level - The coverage level of the memory test. + RequireSoftECCInit - Indicate if the memory need software ECC init. + + Returns: + EFI_SUCCESS - The generic memory test initialized correctly. + EFI_NO_MEDIA - There is not any non-tested memory found, in this + function if not any non-tesed memory found means + that the memory test driver have not detect any + non-tested extended memory of current system. + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_PERFORM_MEMORY_TEST) ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This, + OUT UINT64 *TestedMemorySize, + OUT UINT64 *TotalMemorySize, + OUT BOOLEAN *ErrorOut, + IN BOOLEAN IfTestAbort + ) +/*++ + + Routine Description: + Perform the memory test. + + Arguments: + This - Protocol instance pointer. + TestedMemorySize - Return the tested extended memory size. + TotalMemorySize - Return the whole system physical memory size, this + value may be changed if in some case some error + DIMMs be disabled. + ErrorOut - Any time the memory error occurs, this will be TRUE. + IfTestAbort - Indicate if the user press "ESC" to skip the memory + test. + + Returns: + EFI_SUCCESS - One block of memory test ok, the block size is hide + internally. + EFI_NOT_FOUND - Indicate all the non-tested memory blocks have + already go through. + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_MEMORY_TEST_FINISHED) ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This + ) +/*++ + + Routine Description: + The memory test finished. + + Arguments: + This - Protocol instance pointer. + + Returns: + EFI_SUCCESS - Successful free all the generic memory test driver + allocated resource and notify to platform memory + test driver that memory test finished. + +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_MEMORY_TEST_COMPATIBLE_RANGE) ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS StartAddress, + IN UINT64 Length + ) +/*++ + + Routine Description: + Provide capability to test compatible range which used by some sepcial + driver required using memory range before BDS perform memory test. + + Arguments: + This - Protocol instance pointer. + StartAddress - The start address of the memory range. + Length - The memory range's length. + + Return: + EFI_SUCCESS - The compatible memory range pass the memory test. + EFI_DEVICE_ERROR - The compatible memory range test find memory error + and also return return the error address. + +--*/ +; + +struct _EFI_GENERIC_MEMORY_TEST_PROTOCOL { + EFI_MEMORY_TEST_INIT MemoryTestInit; + EFI_PERFORM_MEMORY_TEST PerformMemoryTest; + EFI_MEMORY_TEST_FINISHED Finished; + EFI_MEMORY_TEST_COMPATIBLE_RANGE CompatibleRangeTest; +}; + +extern EFI_GUID gEfiGenericMemTestProtocolGuid; + +#endif + diff --git a/EdkModulePkg/Include/Protocol/IsaAcpi.h b/EdkModulePkg/Include/Protocol/IsaAcpi.h new file mode 100644 index 0000000000..c3d92f609d --- /dev/null +++ b/EdkModulePkg/Include/Protocol/IsaAcpi.h @@ -0,0 +1,177 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + IsaAcpi.h + +Abstract: + + EFI ISA Acpi Protocol + +Revision History + +--*/ + +#ifndef _ISA_ACPI_H_ +#define _ISA_ACPI_H_ + +#define EFI_ISA_ACPI_PROTOCOL_GUID \ + { 0x64a892dc, 0x5561, 0x4536, { 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55 } } + +typedef struct _EFI_ISA_ACPI_PROTOCOL EFI_ISA_ACPI_PROTOCOL; + +// +// Resource Attribute definition +// +#define EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_EDGE_SENSITIVE 0x01 +#define EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_EDGE_SENSITIVE 0x02 +#define EFI_ISA_ACPI_IRQ_TYPE_HIGH_TRUE_LEVEL_SENSITIVE 0x04 +#define EFI_ISA_ACPI_IRQ_TYPE_LOW_TRUE_LEVEL_SENSITIVE 0x08 + +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_MASK 0x03 + +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_COMPATIBILITY 0x00 +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_A 0x01 +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_B 0x02 +#define EFI_ISA_ACPI_DMA_SPEED_TYPE_F 0x03 +#define EFI_ISA_ACPI_DMA_COUNT_BY_BYTE 0x04 +#define EFI_ISA_ACPI_DMA_COUNT_BY_WORD 0x08 +#define EFI_ISA_ACPI_DMA_BUS_MASTER 0x10 +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_8_BIT 0x20 +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_8_BIT_AND_16_BIT 0x40 +#define EFI_ISA_ACPI_DMA_TRANSFER_TYPE_16_BIT 0x80 + +#define EFI_ISA_ACPI_MEMORY_WIDTH_MASK 0x03 + +#define EFI_ISA_ACPI_MEMORY_WIDTH_8_BIT 0x00 +#define EFI_ISA_ACPI_MEMORY_WIDTH_16_BIT 0x01 +#define EFI_ISA_ACPI_MEMORY_WIDTH_8_BIT_AND_16_BIT 0x02 +#define EFI_ISA_ACPI_MEMORY_WRITEABLE 0x04 +#define EFI_ISA_ACPI_MEMORY_CACHEABLE 0x08 +#define EFI_ISA_ACPI_MEMORY_SHADOWABLE 0x10 +#define EFI_ISA_ACPI_MEMORY_EXPANSION_ROM 0x20 + +#define EFI_ISA_ACPI_IO_DECODE_10_BITS 0x01 +#define EFI_ISA_ACPI_IO_DECODE_16_BITS 0x02 + +// +// Resource List definition: +// at first, the resource was defined as below +// but in the future, it will be defined again that follow ACPI spec: ACPI resource type +// so that, in this driver, we can interpret the ACPI table and get the ISA device information. +// + +typedef enum { + EfiIsaAcpiResourceEndOfList, + EfiIsaAcpiResourceIo, + EfiIsaAcpiResourceMemory, + EfiIsaAcpiResourceDma, + EfiIsaAcpiResourceInterrupt +} EFI_ISA_ACPI_RESOURCE_TYPE; + +typedef struct { + EFI_ISA_ACPI_RESOURCE_TYPE Type; + UINT32 Attribute; + UINT32 StartRange; + UINT32 EndRange; +} EFI_ISA_ACPI_RESOURCE; + +typedef struct { + UINT32 HID; + UINT32 UID; +} EFI_ISA_ACPI_DEVICE_ID; + +typedef struct { + EFI_ISA_ACPI_DEVICE_ID Device; + EFI_ISA_ACPI_RESOURCE *ResourceItem; +} EFI_ISA_ACPI_RESOURCE_LIST; + +// +// Prototypes for the ISA ACPI Protocol +// +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_DEVICE_ENUMERATE) ( + IN EFI_ISA_ACPI_PROTOCOL *This, + OUT EFI_ISA_ACPI_DEVICE_ID **Device + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_SET_DEVICE_POWER) ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN BOOLEAN OnOff + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_GET_CUR_RESOURCE) ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_GET_POS_RESOURCE) ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + OUT EFI_ISA_ACPI_RESOURCE_LIST **ResourceList + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_SET_RESOURCE) ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN EFI_ISA_ACPI_RESOURCE_LIST *ResourceList + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_ENABLE_DEVICE) ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device, + IN BOOLEAN Enable + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_INIT_DEVICE) ( + IN EFI_ISA_ACPI_PROTOCOL *This, + IN EFI_ISA_ACPI_DEVICE_ID *Device + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_ACPI_INTERFACE_INIT) ( + IN EFI_ISA_ACPI_PROTOCOL *This + ); + +// +// Interface structure for the ISA ACPI Protocol +// +struct _EFI_ISA_ACPI_PROTOCOL { + EFI_ISA_ACPI_DEVICE_ENUMERATE DeviceEnumerate; + EFI_ISA_ACPI_SET_DEVICE_POWER SetPower; + EFI_ISA_ACPI_GET_CUR_RESOURCE GetCurResource; + EFI_ISA_ACPI_GET_POS_RESOURCE GetPosResource; + EFI_ISA_ACPI_SET_RESOURCE SetResource; + EFI_ISA_ACPI_ENABLE_DEVICE EnableDevice; + EFI_ISA_ACPI_INIT_DEVICE InitDevice; + EFI_ISA_ACPI_INTERFACE_INIT InterfaceInit; +}; + +extern EFI_GUID gEfiIsaAcpiProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/IsaIo.h b/EdkModulePkg/Include/Protocol/IsaIo.h new file mode 100644 index 0000000000..8419dd4792 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/IsaIo.h @@ -0,0 +1,174 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + IsaIo.h + +Abstract: + + EFI ISA I/O Protocol + +Revision History + +--*/ + +#ifndef _EFI_ISA_IO_H +#define _EFI_ISA_IO_H + +// +// Global ID for the ISA I/O Protocol +// + +#define EFI_ISA_IO_PROTOCOL_GUID \ + { 0x7ee2bd44, 0x3da0, 0x11d4, { 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } } + +typedef struct _EFI_ISA_IO_PROTOCOL EFI_ISA_IO_PROTOCOL; + +// +// Prototypes for the ISA I/O Protocol +// + +typedef enum { + EfiIsaIoWidthUint8, + EfiIsaIoWidthUint16, + EfiIsaIoWidthUint32, + EfiIsaIoWidthReserved, + EfiIsaIoWidthFifoUint8, + EfiIsaIoWidthFifoUint16, + EfiIsaIoWidthFifoUint32, + EfiIsaIoWidthFifoReserved, + EfiIsaIoWidthFillUint8, + EfiIsaIoWidthFillUint16, + EfiIsaIoWidthFillUint32, + EfiIsaIoWidthFillReserved, + EfiIsaIoWidthMaximum +} EFI_ISA_IO_PROTOCOL_WIDTH; + +// +// Attributes for common buffer allocations +// +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x080 // Map a memory range so write are combined +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_CACHED 0x800 // Map a memory range so all r/w accesses are cached +#define EFI_ISA_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 // Disable a memory range + +// +// Channel attribute for DMA operations +// +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_COMPATIBLE 0x001 +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_A 0x002 +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_B 0x004 +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SPEED_C 0x008 +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_8 0x010 +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_WIDTH_16 0x020 +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_SINGLE_MODE 0x040 +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_DEMAND_MODE 0x080 +#define EFI_ISA_IO_SLAVE_DMA_ATTRIBUTE_AUTO_INITIALIZE 0x100 + +typedef enum { + EfiIsaIoOperationBusMasterRead, + EfiIsaIoOperationBusMasterWrite, + EfiIsaIoOperationBusMasterCommonBuffer, + EfiIsaIoOperationSlaveRead, + EfiIsaIoOperationSlaveWrite, + EfiIsaIoOperationMaximum +} EFI_ISA_IO_PROTOCOL_OPERATION; + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_IO_MEM) ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + EFI_ISA_IO_PROTOCOL_IO_MEM Read; + EFI_ISA_IO_PROTOCOL_IO_MEM Write; +} EFI_ISA_IO_PROTOCOL_ACCESS; + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_COPY_MEM) ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_WIDTH Width, + IN UINT32 DestOffset, + IN UINT32 SrcOffset, + IN UINTN Count + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_MAP) ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ISA_IO_PROTOCOL_OPERATION Operation, + IN UINT8 ChannelNumber OPTIONAL, + IN UINT32 ChannelAttributes, + IN VOID *HostAddress, + IN OUT UINTN *NumberOfBytes, + OUT EFI_PHYSICAL_ADDRESS *DeviceAddress, + OUT VOID **Mapping + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_UNMAP) ( + IN EFI_ISA_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_ALLOCATE_BUFFER) ( + IN EFI_ISA_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_FREE_BUFFER) ( + IN EFI_ISA_IO_PROTOCOL *This, + IN UINTN Pages, + IN VOID *HostAddress + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_ISA_IO_PROTOCOL_FLUSH) ( + IN EFI_ISA_IO_PROTOCOL *This + ); + +// +// Interface structure for the ISA I/O Protocol +// +struct _EFI_ISA_IO_PROTOCOL { + EFI_ISA_IO_PROTOCOL_ACCESS Mem; + EFI_ISA_IO_PROTOCOL_ACCESS Io; + EFI_ISA_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_ISA_IO_PROTOCOL_MAP Map; + EFI_ISA_IO_PROTOCOL_UNMAP Unmap; + EFI_ISA_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_ISA_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_ISA_IO_PROTOCOL_FLUSH Flush; + EFI_ISA_ACPI_RESOURCE_LIST *ResourceList; + UINT32 RomSize; + VOID *RomImage; +}; + +extern EFI_GUID gEfiIsaIoProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/LoadPe32Image.h b/EdkModulePkg/Include/Protocol/LoadPe32Image.h new file mode 100644 index 0000000000..d6f54aa527 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/LoadPe32Image.h @@ -0,0 +1,68 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + LoadPe32Image.h + +Abstract: + Load File protocol as defined in the EFI 1.0 specification. + + Load file protocol exists to supports the addition of new boot devices, + and to support booting from devices that do not map well to file system. + Network boot is done via a LoadFile protocol. + + EFI 1.0 can boot from any device that produces a LoadFile protocol. + +--*/ + +#ifndef __LOAD_PE32_IMAGE_H__ +#define __LOAD_PE32_IMAGE_H__ + +#define PE32_IMAGE_PROTOCOL_GUID \ + {0x5cb5c776,0x60d5,0x45ee,{0x88,0x3c,0x45,0x27,0x8,0xcd,0x74,0x3f }} + +#define EFI_LOAD_PE_IMAGE_ATTRIBUTE_NONE 0x00 +#define EFI_LOAD_PE_IMAGE_ATTRIBUTE_RUNTIME_REGISTRATION 0x01 +#define EFI_LOAD_PE_IMAGE_ATTRIBUTE_DEBUG_IMAGE_INFO_TABLE_REGISTRATION 0x02 + +typedef struct _EFI_PE32_IMAGE_PROTOCOL EFI_PE32_IMAGE_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *LOAD_PE_IMAGE) ( + IN EFI_PE32_IMAGE_PROTOCOL *This, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + IN EFI_PHYSICAL_ADDRESS DstBuffer OPTIONAL, + OUT UINTN *NumberOfPages OPTIONAL, + OUT EFI_HANDLE *ImageHandle, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint OPTIONAL, + IN UINT32 Attribute + ); + +typedef +EFI_STATUS +(EFIAPI *UNLOAD_PE_IMAGE) ( + IN EFI_PE32_IMAGE_PROTOCOL *This, + IN EFI_HANDLE ImageHandle + ); + +struct _EFI_PE32_IMAGE_PROTOCOL { + LOAD_PE_IMAGE LoadPeImage; + UNLOAD_PE_IMAGE UnLoadPeImage; +}; + +extern EFI_GUID gEfiLoadPeImageProtocolGuid; + +#endif + diff --git a/EdkModulePkg/Include/Protocol/OEMBadging.h b/EdkModulePkg/Include/Protocol/OEMBadging.h new file mode 100644 index 0000000000..6b4602e2ee --- /dev/null +++ b/EdkModulePkg/Include/Protocol/OEMBadging.h @@ -0,0 +1,79 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EfiOEMBadging.h + +Abstract: + + EFI OEM Badging Protocol definition header file + +Revision History + +--*/ + +#ifndef _EFI_OEM_BADGING_H_ +#define _EFI_OEM_BADGING_H_ + +// +// GUID for EFI OEM Badging Protocol +// +#define EFI_OEM_BADGING_PROTOCOL_GUID \ + { 0x170e13c0, 0xbf1b, 0x4218, {0x87, 0x1d, 0x2a, 0xbd, 0xc6, 0xf8, 0x87, 0xbc } } + + +typedef struct _EFI_OEM_BADGING_PROTOCOL EFI_OEM_BADGING_PROTOCOL; + +typedef enum { + EfiBadgingFormatBMP, + EfiBadgingFormatJPEG, + EfiBadgingFormatTIFF, + EfiBadgingFormatGIF, + EfiBadgingFormatUnknown +} EFI_BADGING_FORMAT; + +typedef enum { + EfiBadgingDisplayAttributeLeftTop, + EfiBadgingDisplayAttributeCenterTop, + EfiBadgingDisplayAttributeRightTop, + EfiBadgingDisplayAttributeCenterRight, + EfiBadgingDisplayAttributeRightBottom, + EfiBadgingDisplayAttributeCenterBottom, + EfiBadgingDisplayAttributeLeftBottom, + EfiBadgingDisplayAttributeCenterLeft, + EfiBadgingDisplayAttributeCenter, + EfiBadgingDisplayAttributeCustomized +} EFI_BADGING_DISPLAY_ATTRIBUTE; + + +typedef +EFI_STATUS +(EFIAPI *EFI_BADGING_GET_IMAGE) ( + IN EFI_OEM_BADGING_PROTOCOL *This, + IN OUT UINT32 *Instance, + OUT EFI_BADGING_FORMAT *Format, + OUT UINT8 **ImageData, + OUT UINTN *ImageSize, + OUT EFI_BADGING_DISPLAY_ATTRIBUTE *Attribute, + OUT UINTN *CoordinateX, + OUT UINTN *CoordinateY +); + + +struct _EFI_OEM_BADGING_PROTOCOL { + EFI_BADGING_GET_IMAGE GetImage; +}; + + +extern EFI_GUID gEfiOEMBadgingProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/PciHotPlugRequest.h b/EdkModulePkg/Include/Protocol/PciHotPlugRequest.h new file mode 100644 index 0000000000..6d194ae3f0 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/PciHotPlugRequest.h @@ -0,0 +1,54 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PciHotPlugRequest.h + +Abstract: + + + +--*/ + +#ifndef _PCI_HOTPLUG_REQUEST_H_ +#define _PCI_HOTPLUG_REQUEST_H_ + +#define EFI_PCI_HOTPLUG_REQUEST_PROTOCOL_GUID \ +{0x19cb87ab,0x2cb9,{0x4665,0x83,0x60,0xdd,0xcf,0x60,0x54,0xf7,0x9d}} + +typedef enum { + EfiPciHotPlugRequestAdd, + EfiPciHotplugRequestRemove +} EFI_PCI_HOTPLUG_OPERATION; + +typedef struct _EFI_PCI_HOTPLUG_REQUEST_PROTOCOL EFI_PCI_HOTPLUG_REQUEST_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOTPLUG_REQUEST_NOTIFY) ( + IN EFI_PCI_HOTPLUG_REQUEST_PROTOCOL *This, + IN EFI_PCI_HOTPLUG_OPERATION Operation, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL, + IN OUT UINT8 *NumberOfChildren, + IN OUT EFI_HANDLE *ChildHandleBuffer +); + + + +struct _EFI_PCI_HOTPLUG_REQUEST_PROTOCOL { + EFI_PCI_HOTPLUG_REQUEST_NOTIFY Notify; +}; + +extern EFI_GUID gEfiPciHotPlugRequestProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/Performance.h b/EdkModulePkg/Include/Protocol/Performance.h new file mode 100644 index 0000000000..c16ed8cced --- /dev/null +++ b/EdkModulePkg/Include/Protocol/Performance.h @@ -0,0 +1,166 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Performance.h + +Abstract: + + +--*/ + +#ifndef __PERFORMANCE_H_ +#define __PERFORMANCE_H_ + +#define PERFORMANCE_PROTOCOL_GUID \ + { 0x76b6bdfa, 0x2acd, 0x4462, {0x9E, 0x3F, 0xcb, 0x58, 0xC9, 0x69, 0xd9, 0x37 } } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _PERFORMANCE_PROTOCOL PERFORMANCE_PROTOCOL; + +#define DXE_TOK "DXE" +#define SHELL_TOK "SHELL" +#define PEI_TOK "PEI" +#define BDS_TOK "BDS" +#define DRIVERBINDING_START_TOK "DriverBinding:Start" +#define DRIVERBINDING_SUPPORT_TOK "DriverBinding:Support" +#define START_IMAGE_TOK "StartImage" +#define LOAD_IMAGE_TOK "LoadImage" + +// +// DXE_PERFORMANCE_STRING_SIZE must be a multiple of 8. +// +#define DXE_PERFORMANCE_STRING_SIZE 32 +#define DXE_PERFORMANCE_STRING_LENGTH (DXE_PERFORMANCE_STRING_SIZE - 1) + +// +// The default guage entries number for DXE phase. +// +#define INIT_DXE_GAUGE_DATA_ENTRIES 800 + +typedef struct { + EFI_PHYSICAL_ADDRESS Handle; + CHAR8 Token[DXE_PERFORMANCE_STRING_SIZE]; + CHAR8 Module[DXE_PERFORMANCE_STRING_SIZE]; + UINT64 StartTimeStamp; + UINT64 EndTimeStamp; +} GAUGE_DATA_ENTRY; + +// +// The header must be aligned at 8 bytes +// +typedef struct { + UINT32 NumberOfEntries; + UINT32 Reserved; +} GAUGE_DATA_HEADER; + +/** + Adds a record at the end of the performance measurement log + that records the start time of a performance measurement. + + Adds a record to the end of the performance measurement log + that contains the Handle, Token, and Module. + The end time of the new record must be set to zero. + If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record. + If TimeStamp is zero, the start time in the record is filled in with the value + read from the current time stamp. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement. + +**/ +typedef +EFI_STATUS +(EFIAPI * PERFORMANCE_START_GAUGE) ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ); + +/** + Searches the performance measurement log from the beginning of the log + for the first matching record that contains a zero end time and fills in a valid end time. + + Searches the performance measurement log from the beginning of the log + for the first record that matches Handle, Token, and Module and has an end time value of zero. + If the record can not be found then return EFI_NOT_FOUND. + If the record is found and TimeStamp is not zero, + then the end time in the record is filled in with the value specified by TimeStamp. + If the record is found and TimeStamp is zero, then the end time in the matching record + is filled in with the current time stamp value. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval EFI_SUCCESS The end of the measurement was recorded. + @retval EFI_NOT_FOUND The specified measurement record could not be found. + +**/ +typedef +EFI_STATUS +(EFIAPI * PERFORMANCE_END_GAUGE) ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ); + +/** + Retrieves a previously logged performance measurement. + + Retrieves the performance log entry from the performance log specified by LogEntryKey. + If it stands for a valid entry, then EFI_SUCCESS is returned and + GaugeDataEntry stores the pointer to that entry. + + @param LogEntryKey The key for the previous performance measurement log entry. + If 0, then the first performance measurement log entry is retrieved. + @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey + if the retrieval is successful. + + @retval EFI_SUCCESS The GuageDataEntry is successfuly found based on LogEntryKey. + @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number). + @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number). + @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI * PERFORMANCE_GET_GAUGE) ( + IN UINTN LogEntryKey, + OUT GAUGE_DATA_ENTRY **GaugeDataEntry + ); + +struct _PERFORMANCE_PROTOCOL { + PERFORMANCE_START_GAUGE StartGauge; + PERFORMANCE_END_GAUGE EndGauge; + PERFORMANCE_GET_GAUGE GetGauge; +}; + +extern EFI_GUID gPerformanceProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/Print.h b/EdkModulePkg/Include/Protocol/Print.h new file mode 100644 index 0000000000..eee7a0db47 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/Print.h @@ -0,0 +1,50 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Print.h + +Abstract: + + This file defines the Print protocol + +--*/ + +#ifndef _PPRINT_H_ +#define _PPRINT_H_ + +#define EFI_PRINT_PROTOCOL_GUID \ + { 0xdf2d868e, 0x32fc, 0x4cf0, {0x8e, 0x6b, 0xff, 0xd9, 0x5d, 0x13, 0x43, 0xd0 } } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_PRINT_PROTOCOL EFI_PRINT_PROTOCOL; + + +typedef +UINTN +(EFIAPI *EFI_VSPRINT) ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + IN VA_LIST Marker + ); + +struct _EFI_PRINT_PROTOCOL { + EFI_VSPRINT VSPrint; +}; + + +extern EFI_GUID gEfiPrintProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/PxeDhcp4.h b/EdkModulePkg/Include/Protocol/PxeDhcp4.h new file mode 100644 index 0000000000..cd4602c06c --- /dev/null +++ b/EdkModulePkg/Include/Protocol/PxeDhcp4.h @@ -0,0 +1,350 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PxeDhcp4.h + +Abstract: + EFI PXE DHCPv4 protocol definition + +--*/ + +#ifndef _PXEDHCP4_H_ +#define _PXEDHCP4_H_ + + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +// +// PXE DHCPv4 GUID definition +// + +#define EFI_PXE_DHCP4_PROTOCOL_GUID \ + { 0x03c4e624, 0xac28, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x29, 0x3f, 0xc1, 0x4d } } + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +// +// Interface definition +// + +typedef struct _EFI_PXE_DHCP4_PROTOCOL EFI_PXE_DHCP4_PROTOCOL; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +// +// Descriptions of the DHCP version 4 header and options can be found +// in RFC-2131 and RFC-2132 at www.ietf.org +// + +#pragma pack(1) +typedef struct { + + UINT8 op; +#define BOOTP_REQUEST 1 +#define BOOTP_REPLY 2 + + UINT8 htype; + + UINT8 hlen; + + UINT8 hops; + + UINT32 xid; + + UINT16 secs; +#define DHCP4_INITIAL_SECONDS 4 + + UINT16 flags; +#define DHCP4_BROADCAST_FLAG 0x8000 + + UINT32 ciaddr; + + UINT32 yiaddr; + + UINT32 siaddr; + + UINT32 giaddr; + + UINT8 chaddr[16]; + + UINT8 sname[64]; + + UINT8 fname[128]; + +// +// This is the minimum option length as specified in RFC-2131. +// The packet must be padded out this far with DHCP4_PAD. +// DHCPv4 packets are usually 576 bytes in length. This length +// includes the IPv4 and UDPv4 headers but not the media header. +// Note: Not all DHCP relay agents will forward DHCPv4 packets +// if they are less than 384 bytes or exceed 576 bytes. Even if +// the underlying hardware can handle smaller and larger packets, +// many older relay agents will not accept them. +// + UINT32 magik; +#define DHCP4_MAGIK_NUMBER 0x63825363 + + UINT8 options[308]; + +} DHCP4_HEADER; +#pragma pack() + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +// +// DHCPv4 packet definition. Room for 576 bytes including IP and +// UDP header. +// + +#define DHCP4_MAX_PACKET_SIZE 576 +#define DHCP4_UDP_HEADER_SIZE 8 +#define DHCP4_IP_HEADER_SIZE 20 + +#pragma pack(1) +typedef union _DHCP4_PACKET { + UINT32 _force_data_alignment; + + UINT8 raw[1500]; + + DHCP4_HEADER dhcp4; +} DHCP4_PACKET; +#pragma pack() + +#define DHCP4_SERVER_PORT 67 +#define DHCP4_CLIENT_PORT 68 + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +// +// DHCPv4 and PXE option numbers. +// + +#define DHCP4_PAD 0 +#define DHCP4_END 255 +#define DHCP4_SUBNET_MASK 1 +#define DHCP4_TIME_OFFSET 2 +#define DHCP4_ROUTER_LIST 3 +#define DHCP4_TIME_SERVERS 4 +#define DHCP4_NAME_SERVERS 5 +#define DHCP4_DNS_SERVERS 6 +#define DHCP4_LOG_SERVERS 7 +#define DHCP4_COOKIE_SERVERS 8 +#define DHCP4_LPR_SREVERS 9 +#define DHCP4_IMPRESS_SERVERS 10 +#define DHCP4_RESOURCE_LOCATION_SERVERS 11 +#define DHCP4_HOST_NAME 12 +#define DHCP4_BOOT_FILE_SIZE 13 +#define DHCP4_DUMP_FILE 14 +#define DHCP4_DOMAIN_NAME 15 +#define DHCP4_SWAP_SERVER 16 +#define DHCP4_ROOT_PATH 17 +#define DHCP4_EXTENSION_PATH 18 +#define DHCP4_IP_FORWARDING 19 +#define DHCP4_NON_LOCAL_SOURCE_ROUTE 20 +#define DHCP4_POLICY_FILTER 21 +#define DHCP4_MAX_DATAGRAM_SIZE 22 +#define DHCP4_DEFAULT_TTL 23 +#define DHCP4_MTU_AGING_TIMEOUT 24 +#define DHCP4_MTU_SIZES 25 +#define DHCP4_MTU_TO_USE 26 +#define DHCP4_ALL_SUBNETS_LOCAL 27 +#define DHCP4_BROADCAST_ADDRESS 28 +#define DHCP4_PERFORM_MASK_DISCOVERY 29 +#define DHCP4_RESPOND_TO_MASK_REQ 30 +#define DHCP4_PERFORM_ROUTER_DISCOVERY 31 +#define DHCP4_ROUTER_SOLICIT_ADDRESS 32 +#define DHCP4_STATIC_ROUTER_LIST 33 +#define DHCP4_USE_ARP_TRAILERS 34 +#define DHCP4_ARP_CACHE_TIMEOUT 35 +#define DHCP4_ETHERNET_ENCAPSULATION 36 +#define DHCP4_TCP_DEFAULT_TTL 37 +#define DHCP4_TCP_KEEP_ALIVE_INT 38 +#define DHCP4_KEEP_ALIVE_GARBAGE 39 +#define DHCP4_NIS_DOMAIN_NAME 40 +#define DHCP4_NIS_SERVERS 41 +#define DHCP4_NTP_SERVERS 42 +#define DHCP4_VENDOR_SPECIFIC 43 +# define PXE_MTFTP_IP 1 +# define PXE_MTFTP_CPORT 2 +# define PXE_MTFTP_SPORT 3 +# define PXE_MTFTP_TMOUT 4 +# define PXE_MTFTP_DELAY 5 +# define PXE_DISCOVERY_CONTROL 6 +# define PXE_DISABLE_BROADCAST_DISCOVERY 0x01 +# define PXE_DISABLE_MULTICAST_DISCOVERY 0x02 +# define PXE_ACCEPT_ONLY_PXE_BOOT_SERVERS 0x04 +# define PXE_DO_NOT_PROMPT 0x08 +# define PXE_DISCOVERY_MCAST_ADDR 7 +# define PXE_BOOT_SERVERS 8 +# define PXE_BOOT_MENU 9 +# define PXE_BOOT_PROMPT 10 +# define PXE_MCAST_ADDRS_ALLOC 11 +# define PXE_CREDENTIAL_TYPES 12 +# define PXE_BOOT_ITEM 71 +#define DHCP4_NBNS_SERVERS 44 +#define DHCP4_NBDD_SERVERS 45 +#define DHCP4_NETBIOS_NODE_TYPE 46 +#define DHCP4_NETBIOS_SCOPE 47 +#define DHCP4_XWINDOW_SYSTEM_FONT_SERVERS 48 +#define DHCP4_XWINDOW_SYSTEM_DISPLAY_MANAGERS 49 +#define DHCP4_REQUESTED_IP_ADDRESS 50 +#define DHCP4_LEASE_TIME 51 +#define DHCP4_OPTION_OVERLOAD 52 +# define DHCP4_OVERLOAD_FNAME 1 +# define DHCP4_OVERLOAD_SNAME 2 +# define DHCP4_OVERLOAD_FNAME_AND_SNAME 3 +#define DHCP4_MESSAGE_TYPE 53 +# define DHCP4_MESSAGE_TYPE_DISCOVER 1 +# define DHCP4_MESSAGE_TYPE_OFFER 2 +# define DHCP4_MESSAGE_TYPE_REQUEST 3 +# define DHCP4_MESSAGE_TYPE_DECLINE 4 +# define DHCP4_MESSAGE_TYPE_ACK 5 +# define DHCP4_MESSAGE_TYPE_NAK 6 +# define DHCP4_MESSAGE_TYPE_RELEASE 7 +# define DHCP4_MESSAGE_TYPE_INFORM 8 +#define DHCP4_SERVER_IDENTIFIER 54 +#define DHCP4_PARAMETER_REQUEST_LIST 55 +#define DHCP4_ERROR_MESSAGE 56 +#define DHCP4_MAX_MESSAGE_SIZE 57 +# define DHCP4_DEFAULT_MAX_MESSAGE_SIZE 576 +#define DHCP4_RENEWAL_TIME 58 +#define DHCP4_REBINDING_TIME 59 +#define DHCP4_CLASS_IDENTIFIER 60 +#define DHCP4_CLIENT_IDENTIFIER 61 +#define DHCP4_NISPLUS_DOMAIN_NAME 64 +#define DHCP4_NISPLUS_SERVERS 65 +#define DHCP4_TFTP_SERVER_NAME 66 +#define DHCP4_BOOTFILE 67 +#define DHCP4_MOBILE_IP_HOME_AGENTS 68 +#define DHCP4_SMPT_SERVERS 69 +#define DHCP4_POP3_SERVERS 70 +#define DHCP4_NNTP_SERVERS 71 +#define DHCP4_WWW_SERVERS 72 +#define DHCP4_FINGER_SERVERS 73 +#define DHCP4_IRC_SERVERS 74 +#define DHCP4_STREET_TALK_SERVERS 75 +#define DHCP4_STREET_TALK_DIR_ASSIST_SERVERS 76 +#define DHCP4_NDS_SERVERS 85 +#define DHCP4_NDS_TREE_NAME 86 +#define DHCP4_NDS_CONTEXT 87 +#define DHCP4_SYSTEM_ARCHITECTURE 93 +#define DHCP4_NETWORK_ARCHITECTURE 94 +#define DHCP4_PLATFORM_ID 97 + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +// +// DHCP4 option format. +// + +#pragma pack(1) +typedef struct { + UINT8 op; + UINT8 len; + UINT8 data[1]; +} DHCP4_OP; +#pragma pack() + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +typedef struct { + DHCP4_PACKET Discover; + DHCP4_PACKET Offer; + DHCP4_PACKET Request; + DHCP4_PACKET AckNak; + BOOLEAN SetupCompleted; + BOOLEAN InitCompleted; + BOOLEAN SelectCompleted; + BOOLEAN IsBootp; + BOOLEAN IsAck; +} EFI_PXE_DHCP4_DATA; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_DHCP4_RUN) ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN OPTIONAL UINTN OpLen, + IN OPTIONAL VOID *OpList + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_DHCP4_SETUP) ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN OPTIONAL EFI_PXE_DHCP4_DATA * NewData + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_DHCP4_INIT) ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN UINTN SecondsTimeout, + OUT UINTN *Offers, + OUT DHCP4_PACKET **OfferList + ); + +#define DHCP4_MIN_SECONDS 1 +#define DHCP4_MAX_SECONDS 60 + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_DHCP4_SELECT) ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN UINTN SecondsTimeout, + IN DHCP4_PACKET * offer + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_DHCP4_RENEW) ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + UINTN seconds_timeout + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_DHCP4_REBIND) ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + UINTN seconds_timeout + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_DHCP4_RELEASE) ( + IN EFI_PXE_DHCP4_PROTOCOL * This + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +#define EFI_PXE_DHCP4_PROTOCOL_REVISION 0x00010000 + +struct _EFI_PXE_DHCP4_PROTOCOL { + UINT64 Revision; + EFI_PXE_DHCP4_RUN Run; + EFI_PXE_DHCP4_SETUP Setup; + EFI_PXE_DHCP4_INIT Init; + EFI_PXE_DHCP4_SELECT Select; + EFI_PXE_DHCP4_RENEW Renew; + EFI_PXE_DHCP4_REBIND Rebind; + EFI_PXE_DHCP4_RELEASE Release; + EFI_PXE_DHCP4_DATA *Data; +}; + +// +// +// + +extern EFI_GUID gEfiPxeDhcp4ProtocolGuid; + +#endif /* _PXEDHCP4_H_ */ +/* EOF - PxeDhcp4.h */ diff --git a/EdkModulePkg/Include/Protocol/PxeDhcp4CallBack.h b/EdkModulePkg/Include/Protocol/PxeDhcp4CallBack.h new file mode 100644 index 0000000000..aa2b89a884 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/PxeDhcp4CallBack.h @@ -0,0 +1,85 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PxeDhcp4Callback.h + +Abstract: + EFI PXE DHCP4 Callback protocol definition. + +--*/ + +#ifndef _PXE_DHCP4CALLBACK_H +#define _PXE_DHCP4CALLBACK_H + +#include +// +// GUID definition +// + +#define EFI_PXE_DHCP4_CALLBACK_PROTOCOL_GUID \ +{ 0xc1544c01, 0x92a4, 0x4198, {0x8a, 0x84, 0x77, 0x85, 0x83, 0xc2, 0x36, 0x21 } } + + +// +// Revision number +// + +#define EFI_PXE_DHCP4_CALLBACK_INTERFACE_REVISION 0x00010000 + +// +// Interface definition +// + +typedef struct _EFI_PXE_DHCP4_CALLBACK_PROTOCOL EFI_PXE_DHCP4_CALLBACK_PROTOCOL; + +typedef enum { + EFI_PXE_DHCP4_FUNCTION_FIRST, + EFI_PXE_DHCP4_FUNCTION_INIT, + EFI_PXE_DHCP4_FUNCTION_SELECT, + EFI_PXE_DHCP4_FUNCTION_RENEW, + EFI_PXE_DHCP4_FUNCTION_REBIND, + EFI_PXE_DHCP4_FUNCTION_LAST +} EFI_PXE_DHCP4_FUNCTION; + +typedef enum { + EFI_PXE_DHCP4_CALLBACK_STATUS_FIRST, + EFI_PXE_DHCP4_CALLBACK_STATUS_ABORT, + EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_ABORT, + EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_ABORT, + EFI_PXE_DHCP4_CALLBACK_STATUS_CONTINUE, + EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_CONTINUE, + EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_CONTINUE, + EFI_PXE_DHCP4_CALLBACK_STATUS_LAST +} EFI_PXE_DHCP4_CALLBACK_STATUS; + +typedef +EFI_PXE_DHCP4_CALLBACK_STATUS +(EFIAPI *EFI_PXE_DHCP4_CALLBACK) ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN EFI_PXE_DHCP4_FUNCTION Function, + IN UINT32 PacketLen, + IN DHCP4_PACKET *Packet OPTIONAL + ); + +struct _EFI_PXE_DHCP4_CALLBACK_PROTOCOL { + UINT64 Revision; + EFI_PXE_DHCP4_CALLBACK Callback; +}; + +// +// GUID declaration +// + +extern EFI_GUID gEfiPxeDhcp4CallbackProtocolGuid; + +#endif /* _PXE_DHCP4CALLBACK_H */ +/* EOF - PxeDhcp4Callback.h */ diff --git a/EdkModulePkg/Include/Protocol/ScsiIo.h b/EdkModulePkg/Include/Protocol/ScsiIo.h new file mode 100644 index 0000000000..1b0bbbf862 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/ScsiIo.h @@ -0,0 +1,241 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ScsiIo.h + +Abstract: + + SCSI I/O protocol. + +--*/ + +#ifndef __SCSI_IO_H__ +#define __SCSI_IO_H__ + +#define EFI_SCSI_IO_PROTOCOL_GUID \ + { 0x403cd195, 0xf233, 0x48ec, {0x84, 0x55, 0xb2, 0xe5, 0x2f, 0x1d, 0x9e, 0x2 } } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_SCSI_IO_PROTOCOL EFI_SCSI_IO_PROTOCOL; + +// +// SCSI Host Adapter Status definition +// +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK 0x00 +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND 0x09 // timeout when processing the command +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT 0x0b // timeout when waiting for the command processing +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT 0x0d // a message reject was received when processing command +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET 0x0e // a bus reset was detected +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR 0x0f +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED 0x10 // the adapter failed in issuing request sense command +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT 0x11 // selection timeout +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN 0x12 // data overrun or data underrun +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE 0x13 // Unexepected bus free +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR 0x14 // Target bus phase sequence failure +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_OTHER 0x7f + + +// +// SCSI Target Status definition +// +#define EFI_SCSI_IO_STATUS_TARGET_GOOD 0x00 +#define EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION 0x02 // check condition +#define EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET 0x04 // condition met +#define EFI_SCSI_IO_STATUS_TARGET_BUSY 0x08 // busy +#define EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE 0x10 // intermediate +#define EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET 0x14 // intermediate-condition met +#define EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT 0x18 // reservation conflict +#define EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED 0x22 // command terminated +#define EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL 0x28 // queue full + +typedef struct { + UINT64 Timeout; + VOID *DataBuffer; + VOID *SenseData; + VOID *Cdb; + UINT32 TransferLength; + UINT8 CdbLength; + UINT8 DataDirection; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + UINT8 SenseDataLength; +}EFI_SCSI_IO_SCSI_REQUEST_PACKET; + +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_GET_DEVICE_TYPE) ( + IN EFI_SCSI_IO_PROTOCOL *This, + OUT UINT8 *DeviceType + ) +/*++ + + Routine Description: + Retrieves the device type information of the SCSI Controller. + + Arguments: + This - Protocol instance pointer. + DeviceType - A pointer to the device type information + retrieved from the SCSI Controller. + + Returns: + EFI_SUCCESS - Retrieves the device type information successfully. + EFI_INVALID_PARAMETER - The DeviceType is NULL. +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_GET_DEVICE_LOCATION) ( + IN EFI_SCSI_IO_PROTOCOL *This, + OUT UINT32 *Target, + OUT UINT64 *Lun + ) +/*++ + Routine Description: + Retrieves the device location in the SCSI channel. + + Arguments: + This - Protocol instance pointer. + Target - A pointer to the Target ID of a SCSI device + on the SCSI channel. + Lun - A pointer to the LUN of the SCSI device on + the SCSI channel. + + Returns: + EFI_SUCCESS - Retrieves the device location successfully. + EFI_INVALID_PARAMETER - The Target or Lun is NULL. +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_RESET_BUS) ( + IN EFI_SCSI_IO_PROTOCOL *This + ) +/*++ + + Routine Description: + Resets the SCSI Bus that the SCSI Controller is attached to. + + Arguments: + This - Protocol instance pointer. + + Returns: + EFI_SUCCESS - The SCSI bus is reset successfully. + EFI_DEVICE_ERROR - Errors encountered when resetting the SCSI bus. + EFI_UNSUPPORTED - The bus reset operation is not supported by the + SCSI Host Controller. + EFI_TIMEOUT - A timeout occurred while attempting to reset + the SCSI bus. +--*/ +; + +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_RESET_DEVICE) ( + IN EFI_SCSI_IO_PROTOCOL *This + ) +/*++ + + Routine Description: + Resets the SCSI Controller that the device handle specifies. + + Arguments: + This - Protocol instance pointer. + + + Returns: + EFI_SUCCESS - Reset the SCSI controller successfully. + EFI_DEVICE_ERROR - Errors are encountered when resetting the + SCSI Controller. + EFI_UNSUPPORTED - The SCSI bus does not support a device + reset operation. + EFI_TIMEOUT - A timeout occurred while attempting to + reset the SCSI Controller. +--*/ +; + + +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_EXEC_SCSI_CMD) ( + IN EFI_SCSI_IO_PROTOCOL *This, + IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ) +/*++ + + Routine Description: + Sends a SCSI Request Packet to the SCSI Controller for execution. + + Arguments: + This - Protocol instance pointer. + Packet - The SCSI request packet to send to the SCSI + Controller specified by the device handle. + Event - If the SCSI bus where the SCSI device is attached + does not support non-blocking I/O, then Event is + ignored, and blocking I/O is performed. + If Event is NULL, then blocking I/O is performed. + If Event is not NULL and non-blocking I/O is + supported, then non-blocking I/O is performed, + and Event will be signaled when the SCSI Request + Packet completes. + Returns: + EFI_SUCCESS - The SCSI Request Packet was sent by the host + successfully, and TransferLength bytes were + transferred to/from DataBuffer.See + HostAdapterStatus, TargetStatus, + SenseDataLength, and SenseData in that order + for additional status information. + EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, + but the entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in TransferLength. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + EFI_NOT_READY - The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued.The caller may retry again later. + EFI_DEVICE_ERROR - A device error occurred while attempting to send + the SCSI Request Packet. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. + The SCSI Request Packet was not sent, so no + additional status information is available. + EFI_UNSUPPORTED - The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). The SCSI Request Packet was not + sent, so no additional status information is + available. + EFI_TIMEOUT - A timeout occurred while waiting for the SCSI + Request Packet to execute. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. +--*/ +; + +struct _EFI_SCSI_IO_PROTOCOL { + EFI_SCSI_IO_PROTOCOL_GET_DEVICE_TYPE GetDeviceType; + EFI_SCSI_IO_PROTOCOL_GET_DEVICE_LOCATION GetDeviceLocation; + EFI_SCSI_IO_PROTOCOL_RESET_BUS ResetBus; + EFI_SCSI_IO_PROTOCOL_RESET_DEVICE ResetDevice; + EFI_SCSI_IO_PROTOCOL_EXEC_SCSI_CMD ExecuteSCSICommand; +}; + +extern EFI_GUID gEfiScsiIoProtocolGuid; + +#endif + diff --git a/EdkModulePkg/Include/Protocol/SecurityPolicy.h b/EdkModulePkg/Include/Protocol/SecurityPolicy.h new file mode 100644 index 0000000000..f587b441e5 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/SecurityPolicy.h @@ -0,0 +1,33 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + SecurityPolicy.h + +Abstract: + + Security Policy protocol as defined in the DXE CIS + +--*/ + +#ifndef _SECURITY_POLICY_H_ +#define _SECURITY_POLICY_H_ + +// +// Security policy protocol GUID definition +// +#define EFI_SECURITY_POLICY_PROTOCOL_GUID \ + {0x78E4D245, 0xCD4D, 0x4a05, {0xA2, 0xBA, 0x47, 0x43, 0xE8, 0x6C, 0xFC, 0xAB} } + +extern EFI_GUID gEfiSecurityPolicyProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/UgaIo.h b/EdkModulePkg/Include/Protocol/UgaIo.h new file mode 100644 index 0000000000..91ff8df35a --- /dev/null +++ b/EdkModulePkg/Include/Protocol/UgaIo.h @@ -0,0 +1,236 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + UgaIo.h + +Abstract: + + UGA IO protocol from the EFI 1.1 specification. + + Abstraction of a very simple graphics device. + +--*/ + +#ifndef __UGA_IO_H__ +#define __UGA_IO_H__ + +#define EFI_UGA_IO_PROTOCOL_GUID \ + { \ + 0x61a4d49e, 0x6f68, 0x4f1b, { 0xb9, 0x22, 0xa8, 0x6e, 0xed, 0xb, 0x7, 0xa2 } \ + } + +typedef struct _EFI_UGA_IO_PROTOCOL EFI_UGA_IO_PROTOCOL; + +typedef UINT32 UGA_STATUS; + +typedef enum { + UgaDtParentBus = 1, + UgaDtGraphicsController, + UgaDtOutputController, + UgaDtOutputPort, + UgaDtOther +} +UGA_DEVICE_TYPE, *PUGA_DEVICE_TYPE; + +typedef UINT32 UGA_DEVICE_ID, *PUGA_DEVICE_ID; + +typedef struct { + UGA_DEVICE_TYPE deviceType; + UGA_DEVICE_ID deviceId; + UINT32 ui32DeviceContextSize; + UINT32 ui32SharedContextSize; +} +UGA_DEVICE_DATA, *PUGA_DEVICE_DATA; + +typedef struct _UGA_DEVICE { + VOID *pvDeviceContext; + VOID *pvSharedContext; + VOID *pvRunTimeContext; + struct _UGA_DEVICE *pParentDevice; + VOID *pvBusIoServices; + VOID *pvStdIoServices; + UGA_DEVICE_DATA deviceData; +} +UGA_DEVICE, *PUGA_DEVICE; + +#ifndef UGA_IO_REQUEST_CODE +// +// Prevent conflicts with UGA typedefs. +// +typedef enum { + UgaIoGetVersion = 1, + UgaIoGetChildDevice, + UgaIoStartDevice, + UgaIoStopDevice, + UgaIoFlushDevice, + UgaIoResetDevice, + UgaIoGetDeviceState, + UgaIoSetDeviceState, + UgaIoSetPowerState, + UgaIoGetMemoryConfiguration, + UgaIoSetVideoMode, + UgaIoCopyRectangle, + UgaIoGetEdidSegment, + UgaIoDeviceChannelOpen, + UgaIoDeviceChannelClose, + UgaIoDeviceChannelRead, + UgaIoDeviceChannelWrite, + UgaIoGetPersistentDataSize, + UgaIoGetPersistentData, + UgaIoSetPersistentData, + UgaIoGetDevicePropertySize, + UgaIoGetDeviceProperty, + UgaIoBtPrivateInterface +} +UGA_IO_REQUEST_CODE, *PUGA_IO_REQUEST_CODE; + +#endif + +typedef struct { + IN UGA_IO_REQUEST_CODE ioRequestCode; + IN VOID *pvInBuffer; + IN UINT64 ui64InBufferSize; + OUT VOID *pvOutBuffer; + IN UINT64 ui64OutBufferSize; + OUT UINT64 ui64BytesReturned; +} +UGA_IO_REQUEST, *PUGA_IO_REQUEST; + +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_IO_PROTOCOL_CREATE_DEVICE) ( + IN EFI_UGA_IO_PROTOCOL * This, + IN UGA_DEVICE * ParentDevice, + IN UGA_DEVICE_DATA * DeviceData, + IN VOID *RunTimeContext, + OUT UGA_DEVICE **Device + ); + +/*++ + + Routine Description: + + Dynamically allocate storage for a child UGA_DEVICE . + + Arguments: + + This - The EFI_UGA_IO_PROTOCOL instance. Type EFI_UGA_IO_PROTOCOL is + defined in Section 10.7. + + ParentDevice - ParentDevice specifies a pointer to the parent device of Device. + + DeviceData - A pointer to UGA_DEVICE_DATA returned from a call to DispatchService() + with a UGA_DEVICE of Parent and an IoRequest of type UgaIoGetChildDevice. + + RuntimeContext - Context to associate with Device. + + Device - The Device returns a dynamically allocated child UGA_DEVICE object + for ParentDevice. The caller is responsible for deleting Device. + + Returns: + + EFI_SUCCESS - Device was returned. + + EFI_INVALID_PARAMETER - One of the arguments was not valid. + + EFI_DEVICE_ERROR - The device had an error and could not complete the request. + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_IO_PROTOCOL_DELETE_DEVICE) ( + IN EFI_UGA_IO_PROTOCOL * This, + IN UGA_DEVICE * Device + ); + +/*++ + + Routine Description: + + Delete a dynamically allocated child UGA_DEVICE object that was allocated via + CreateDevice() . + + Arguments: + + This - The EFI_UGA_IO_PROTOCOL instance. Type EFI_UGA_IO_PROTOCOL is defined + in Section 10.7. + + Device - The Device points to a UGA_DEVICE object that was dynamically + allocated via a CreateDevice() call. + + Returns: + + EFI_SUCCESS - Device was deleted. + + EFI_INVALID_PARAMETER - The Device was not allocated via CreateDevice() + +--*/ +typedef UGA_STATUS (EFIAPI *PUGA_FW_SERVICE_DISPATCH) (IN PUGA_DEVICE pDevice, IN OUT PUGA_IO_REQUEST pIoRequest); + +/*++ + + Routine Description: + + This is the main UGA service dispatch routine for all UGA_IO_REQUEST s. + + Arguments: + + pDevice - pDevice specifies a pointer to a device object associated with a + device enumerated by a pIoRequest->ioRequestCode of type + UgaIoGetChildDevice. The root device for the EFI_UGA_IO_PROTOCOL + is represented by pDevice being set to NULL. + + pIoRequest - pIoRequest points to a caller allocated buffer that contains data + defined by pIoRequest->ioRequestCode. See Related Definitions for + a definition of UGA_IO_REQUEST_CODE s and their associated data + structures. + + Returns: + + Varies depending on pIoRequest. + +--*/ +struct _EFI_UGA_IO_PROTOCOL { + EFI_UGA_IO_PROTOCOL_CREATE_DEVICE CreateDevice; + EFI_UGA_IO_PROTOCOL_DELETE_DEVICE DeleteDevice; + PUGA_FW_SERVICE_DISPATCH DispatchService; +}; + +extern EFI_GUID gEfiUgaIoProtocolGuid; + +// +// Data structure that is stored in the EFI Configuration Table with the +// EFI_UGA_IO_PROTOCOL_GUID. The option ROMs listed in this table may have +// EBC UGA drivers. +// +typedef struct { + UINT32 Version; + UINT32 HeaderSize; + UINT32 SizeOfEntries; + UINT32 NumberOfEntries; +} EFI_DRIVER_OS_HANDOFF_HEADER; + +typedef enum { + EfiUgaDriverFromPciRom, + EfiUgaDriverFromSystem, + EfiDriverHandoffMax +} EFI_DRIVER_HANOFF_ENUM; + +typedef struct { + EFI_DRIVER_HANOFF_ENUM Type; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + VOID *PciRomImage; + UINT64 PciRomSize; +} EFI_DRIVER_OS_HANDOFF; + +#endif diff --git a/EdkModulePkg/Include/Protocol/UgaSplash.h b/EdkModulePkg/Include/Protocol/UgaSplash.h new file mode 100644 index 0000000000..51dcf523d3 --- /dev/null +++ b/EdkModulePkg/Include/Protocol/UgaSplash.h @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + UgaSplash.h + +Abstract: + + UGA Splash screen protocol. + + Abstraction of a very simple graphics device. + +--*/ + +#ifndef __UGA_SPLASH_H__ +#define __UGA_SPLASH_H__ + + +#define EFI_UGA_SPLASH_PROTOCOL_GUID \ + { 0xa45b3a0d, 0x2e55, 0x4c03, {0xad, 0x9c, 0x27, 0xd4, 0x82, 0xb, 0x50, 0x7e } } + +typedef struct _EFI_UGA_SPLASH_PROTOCOL EFI_UGA_SPLASH_PROTOCOL; + + +struct _EFI_UGA_SPLASH_PROTOCOL { + UINT32 PixelWidth; + UINT32 PixelHeight; + EFI_UGA_PIXEL *Image; +}; + +extern EFI_GUID gEfiUgaSplashProtocolGuid; + +#endif diff --git a/EdkModulePkg/Include/Protocol/usbatapi.h b/EdkModulePkg/Include/Protocol/usbatapi.h new file mode 100644 index 0000000000..8801a7ae6c --- /dev/null +++ b/EdkModulePkg/Include/Protocol/usbatapi.h @@ -0,0 +1,83 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + UsbAtapi.h + +Abstract: + + EFI Atapi Protocol definition. + +Revision History + +--*/ + +#ifndef _EFI_USB_ATAPI_H +#define _EFI_USB_ATAPI_H + +// +// Transfer protocol types +// +#define BOT 0x50 +#define CBI0 0x00 +#define CBI1 0x01 + +// +// SubClass Code (defines command set) +// +#define EFI_USB_SUBCLASS_RBC 0x01 +#define EFI_USB_SUBCLASS_ATAPI 0x02 +#define EFI_USB_SUBCLASS_QIC_157 0x03 +#define EFI_USB_SUBCLASS_UFI 0x04 +#define EFI_USB_SUBCLASS_SFF_8070i 0x05 +#define EFI_USB_SUBCLASS_SCSI 0x06 +#define EFI_USB_SUBCLASS_RESERVED_LOW 0x07 +#define EFI_USB_SUBCLASS_RESERVED_HIGH 0xff +// +// Global GUID for transfer protocol interface +// +#define EFI_USB_ATAPI_PROTOCOL_GUID \ + { 0x2B2F68DA, 0x0CD2, 0x44cf, {0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 } } + +typedef struct _EFI_USB_ATAPI_PROTOCOL EFI_USB_ATAPI_PROTOCOL; + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_ATAPI_PACKET_CMD) ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN VOID *Command, + IN UINT8 CommandSize, + IN VOID *DataBuffer, + IN UINT32 BufferLength, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT16 TimeOutInMilliSeconds +); + +typedef +EFI_STATUS +(EFIAPI *EFI_USB_MASS_STORAGE_RESET) ( + IN EFI_USB_ATAPI_PROTOCOL *This, + IN BOOLEAN ExtendedVerification +); + +// +// Protocol Interface Structure +// +struct _EFI_USB_ATAPI_PROTOCOL { + EFI_USB_ATAPI_PACKET_CMD UsbAtapiPacketCmd; + EFI_USB_MASS_STORAGE_RESET UsbAtapiReset; + UINT32 CommandProtocol; +}; + +extern EFI_GUID gEfiUsbAtapiProtocolGuid; + +#endif diff --git a/EdkModulePkg/Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.c b/EdkModulePkg/Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.c new file mode 100644 index 0000000000..b165f474e3 --- /dev/null +++ b/EdkModulePkg/Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.c @@ -0,0 +1,80 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BaseCustomDecompressLibNull.c + +Abstract: + + NULL Custom Decompress Library + +--*/ + +RETURN_STATUS +EFIAPI +CustomDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SourceSize - The size of source buffer + DestinationSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return RETURN_UNSUPPORTED; +} + +RETURN_STATUS +EFIAPI +CustomDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + Destination - The destination buffer to store the decompressed data + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + +Returns: + + RETURN_SUCCESS - Decompression is successfull + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return RETURN_UNSUPPORTED; +} diff --git a/EdkModulePkg/Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.mbd b/EdkModulePkg/Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.mbd new file mode 100644 index 0000000000..0cbb341dd7 --- /dev/null +++ b/EdkModulePkg/Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.mbd @@ -0,0 +1,30 @@ + + + + + BaseCustomDecompressLibNull + e5566134-c75e-4ace-bad1-e23a3b335e30 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + diff --git a/EdkModulePkg/Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.msa b/EdkModulePkg/Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.msa new file mode 100644 index 0000000000..4dbc8a6f63 --- /dev/null +++ b/EdkModulePkg/Library/BaseCustomDecompressLibNull/BaseCustomDecompressLibNull.msa @@ -0,0 +1,45 @@ + + + + + BaseCustomDecompressLibNull + BASE + LIBRARY + e5566134-c75e-4ace-bad1-e23a3b335e30 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + CustomDecompressLib + DebugLib + + + BaseCustomDecompressLibNull.c + + + MdePkg + EdkModulePkg + + diff --git a/EdkModulePkg/Library/BaseCustomDecompressLibNull/build.xml b/EdkModulePkg/Library/BaseCustomDecompressLibNull/build.xml new file mode 100644 index 0000000000..d2f8ab44df --- /dev/null +++ b/EdkModulePkg/Library/BaseCustomDecompressLibNull/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.c b/EdkModulePkg/Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.c new file mode 100644 index 0000000000..bbf88f93e7 --- /dev/null +++ b/EdkModulePkg/Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.c @@ -0,0 +1,887 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BaseUefiTianoDecompressLib.c + +Abstract: + + UEFI and Tiano Decompress Library + +--*/ + +// +// Decompression algorithm begins here +// +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define BAD_TABLE - 1 + +// +// C: Char&Len Set; P: Position Set; T: exTra Set +// +#define NC (0xff + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define MAXPBIT 5 +#define TBIT 5 +#define MAXNP ((1U << MAXPBIT) - 1) +#define NT (CODE_BIT + 3) +#if NT > MAXNP +#define NPT NT +#else +#define NPT MAXNP +#endif + +typedef struct { + UINT8 *mSrcBase; // Starting address of compressed data + UINT8 *mDstBase; // Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; + + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; + + UINT16 mBadTableFlag; + + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; + + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm, mPBit = 4 + // For Tiano de/compression algorithm, mPBit = 5 + // + UINT8 mPBit; +} SCRATCH_DATA; + +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + +Arguments: + + Sd - The global scratch data + NumOfBits - The number of bits to shift and read. + +Returns: (VOID) + +--*/ +{ + Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); + + while (NumOfBits > Sd->mBitCount) { + + Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); + + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; + Sd->mBitCount = 8; + + } else { + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + + } + } + + Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; +} + +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + +Arguments: + + Sd - The global scratch data. + NumOfBits - The number of bits to pop and read. + +Returns: + + The bits that are popped out. + +--*/ +{ + UINT32 OutBits; + + OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + + FillBuf (Sd, NumOfBits); + + return OutBits; +} + +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ) +/*++ + +Routine Description: + + Creates Huffman Code mapping table according to code length array. + +Arguments: + + Sd - The global scratch data + NumOfChar - Number of symbols in the symbol set + BitLen - Code length array + TableBits - The width of the mapping table + Table - The table + +Returns: + + 0 - OK. + BAD_TABLE - The table is corrupted. + +--*/ +{ + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *Pointer; + UINT16 Index3; + volatile UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; + + for (Index = 1; Index <= 16; Index++) { + Count[Index] = 0; + } + + for (Index = 0; Index < NumOfChar; Index++) { + Count[BitLen[Index]]++; + } + + Start[1] = 0; + + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index))); + } + + if (Start[17] != 0) { + /*(1U << 16)*/ + return (UINT16) BAD_TABLE; + } + + JuBits = (UINT16) (16 - TableBits); + + for (Index = 1; Index <= TableBits; Index++) { + Start[Index] >>= JuBits; + Weight[Index] = (UINT16) (1U << (TableBits - Index)); + } + + while (Index <= 16) { + Weight[Index] = (UINT16) (1U << (16 - Index)); + Index++; + } + + Index = (UINT16) (Start[TableBits + 1] >> JuBits); + + if (Index != 0) { + Index3 = (UINT16) (1U << TableBits); + while (Index != Index3) { + Table[Index++] = 0; + } + } + + Avail = NumOfChar; + Mask = (UINT16) (1U << (15 - TableBits)); + + for (Char = 0; Char < NumOfChar; Char++) { + + Len = BitLen[Char]; + if (Len == 0) { + continue; + } + + NextCode = (UINT16) (Start[Len] + Weight[Len]); + + if (Len <= TableBits) { + + for (Index = Start[Len]; Index < NextCode; Index++) { + Table[Index] = Char; + } + + } else { + + Index3 = Start[Len]; + Pointer = &Table[Index3 >> JuBits]; + Index = (UINT16) (Len - TableBits); + + while (Index != 0) { + if (*Pointer == 0) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *Pointer = Avail++; + } + + if (Index3 & Mask) { + Pointer = &Sd->mRight[*Pointer]; + } else { + Pointer = &Sd->mLeft[*Pointer]; + } + + Index3 <<= 1; + Index--; + } + + *Pointer = Char; + + } + + Start[Len] = NextCode; + } + // + // Succeeds + // + return 0; +} + +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decodes a position value. + +Arguments: + + Sd - the global scratch data + +Returns: + + The position value decoded. + +--*/ +{ + UINT16 Val; + UINT32 Mask; + UINT32 Pos; + + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Sd->mBitBuf & Mask) { + Val = Sd->mRight[Val]; + } else { + Val = Sd->mLeft[Val]; + } + + Mask >>= 1; + } while (Val >= MAXNP); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[Val]); + + Pos = Val; + if (Val > 1) { + Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); + } + + return Pos; +} + +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ) +/*++ + +Routine Description: + + Reads code lengths for the Extra Set or the Position Set + +Arguments: + + Sd - The global scratch data + nn - Number of symbols + nbit - Number of bits needed to represent nn + Special - The special symbol that needs to be taken care of + +Returns: + + 0 - OK. + BAD_TABLE - Table is corrupted. + +--*/ +{ + UINT16 Number; + UINT16 CharC; + volatile UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, nbit); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, nbit); + + for (Index = 0; Index < 256; Index++) { + Sd->mPTTable[Index] = CharC; + } + + for (Index = 0; Index < nn; Index++) { + Sd->mPTLen[Index] = 0; + } + + return 0; + } + + Index = 0; + + while (Index < Number) { + + CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); + + if (CharC == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + CharC += 1; + } + } + + FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); + + Sd->mPTLen[Index++] = (UINT8) CharC; + + if (Index == Special) { + CharC = (UINT16) GetBits (Sd, 2); + while ((INT16) (--CharC) >= 0) { + Sd->mPTLen[Index++] = 0; + } + } + } + + while (Index < nn) { + Sd->mPTLen[Index++] = 0; + } + + return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); +} + +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Reads code lengths for Char&Len Set. + +Arguments: + + Sd - the global scratch data + +Returns: (VOID) + +--*/ +{ + UINT16 Number; + UINT16 CharC; + volatile UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, CBIT); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, CBIT); + + for (Index = 0; Index < NC; Index++) { + Sd->mCLen[Index] = 0; + } + + for (Index = 0; Index < 4096; Index++) { + Sd->mCTable[Index] = CharC; + } + + return ; + } + + Index = 0; + while (Index < Number) { + + CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (CharC >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Mask & Sd->mBitBuf) { + CharC = Sd->mRight[CharC]; + } else { + CharC = Sd->mLeft[CharC]; + } + + Mask >>= 1; + + } while (CharC >= NT); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[CharC]); + + if (CharC <= 2) { + + if (CharC == 0) { + CharC = 1; + } else if (CharC == 1) { + CharC = (UINT16) (GetBits (Sd, 4) + 3); + } else if (CharC == 2) { + CharC = (UINT16) (GetBits (Sd, CBIT) + 20); + } + + while ((INT16) (--CharC) >= 0) { + Sd->mCLen[Index++] = 0; + } + + } else { + + Sd->mCLen[Index++] = (UINT8) (CharC - 2); + + } + } + + while (Index < NC) { + Sd->mCLen[Index++] = 0; + } + + MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); + + return ; +} + +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode a character/length value. + +Arguments: + + Sd - The global scratch data. + +Returns: + + The value decoded. + +--*/ +{ + UINT16 Index2; + UINT32 Mask; + + if (Sd->mBlockSize == 0) { + // + // Starting a new block + // + Sd->mBlockSize = (UINT16) GetBits (Sd, 16); + Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } + + ReadCLen (Sd); + + Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } + + Sd->mBlockSize--; + Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + + if (Index2 >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); + + do { + if (Sd->mBitBuf & Mask) { + Index2 = Sd->mRight[Index2]; + } else { + Index2 = Sd->mLeft[Index2]; + } + + Mask >>= 1; + } while (Index2 >= NC); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mCLen[Index2]); + + return Index2; +} + +VOID +Decode ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode the source data and put the resulting data into the destination buffer. + +Arguments: + + Sd - The global scratch data + +Returns: (VOID) + + --*/ +{ + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 CharC; + + BytesRemain = (UINT16) (-1); + + DataIdx = 0; + + for (;;) { + CharC = DecodeC (Sd); + if (Sd->mBadTableFlag != 0) { + return ; + } + + if (CharC < 256) { + // + // Process an Original character + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } else { + Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; + } + + } else { + // + // Process a Pointer + // + CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD)); + + BytesRemain = CharC; + + DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; + + BytesRemain--; + while ((INT16) (BytesRemain) >= 0) { + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } + + BytesRemain--; + } + } + } + + return ; +} + +RETURN_STATUS +EFIAPI +UefiDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SourceSize - The size of source buffer + DestinationSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + UINT32 CompressedSize; + + ASSERT (Source != NULL); + ASSERT (DestinationSize != NULL); + ASSERT (ScratchSize != NULL); + + *ScratchSize = sizeof (SCRATCH_DATA); + + if (SourceSize < 8) { + return RETURN_INVALID_PARAMETER; + } + + CopyMem (&CompressedSize, Source, sizeof (UINT32)); + CopyMem (DestinationSize, (VOID *)((UINT8 *)Source + 4), sizeof (UINT32)); + + if (SourceSize < (CompressedSize + 8)) { + return RETURN_INVALID_PARAMETER; + } + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EFIAPI +UefiTianoDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch, + IN UINT32 Version + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + Destination - The destination buffer to store the decompressed data + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + Version - 1 for UEFI Decompress algoruthm, 2 for Tiano Decompess algorithm + +Returns: + + RETURN_SUCCESS - Decompression is successfull + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + volatile UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + SCRATCH_DATA *Sd; + CONST UINT8 *Src; + UINT8 *Dst; + + ASSERT (Source != NULL); + ASSERT (Destination != NULL); + ASSERT (Scratch != NULL); + + Src = Source; + Dst = Destination; + + Sd = (SCRATCH_DATA *) Scratch; + + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + // + // If compressed file size is 0, return + // + if (OrigSize == 0) { + return RETURN_SUCCESS; + } + + Src = Src + 8; + + for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { + ((UINT8 *) Sd)[Index] = 0; + } + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 + // For Tiano de/compression algorithm(Version 2), mPBit = 5 + // + switch (Version) { + case 1 : + Sd->mPBit = 4; + break; + case 2 : + Sd->mPBit = 5; + break; + default: + ASSERT (FALSE); + } + Sd->mSrcBase = (UINT8 *)Src; + Sd->mDstBase = Dst; + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; + + // + // Fill the first BITBUFSIZ bits + // + FillBuf (Sd, BITBUFSIZ); + + // + // Decompress it + // + Decode (Sd); + + if (Sd->mBadTableFlag != 0) { + // + // Something wrong with the source + // + return RETURN_INVALID_PARAMETER; + } + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EFIAPI +UefiDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + Destination - The destination buffer to store the decompressed data + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + +Returns: + + RETURN_SUCCESS - Decompression is successfull + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return UefiTianoDecompress (Source, Destination, Scratch, 1); +} + +RETURN_STATUS +EFIAPI +TianoDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SourceSize - The size of source buffer + DestinationSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return UefiDecompressGetInfo (Source, SourceSize, DestinationSize, ScratchSize); +} + +RETURN_STATUS +EFIAPI +TianoDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + Destination - The destination buffer to store the decompressed data + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + +Returns: + + RETURN_SUCCESS - Decompression is successfull + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return UefiTianoDecompress (Source, Destination, Scratch, 2); +} diff --git a/EdkModulePkg/Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.mbd b/EdkModulePkg/Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.mbd new file mode 100644 index 0000000000..684d8e635d --- /dev/null +++ b/EdkModulePkg/Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.mbd @@ -0,0 +1,30 @@ + + + + + BaseUefiTianoDecompressLib + d774c4d9-c121-4da3-a5e2-0f317e3c630c + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:18 + + diff --git a/EdkModulePkg/Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.msa b/EdkModulePkg/Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.msa new file mode 100644 index 0000000000..89d574e180 --- /dev/null +++ b/EdkModulePkg/Library/BaseUefiTianoDecompressLib/BaseUefiTianoDecompressLib.msa @@ -0,0 +1,47 @@ + + + + + BaseUefiTianoDecompressLib + BASE + LIBRARY + d774c4d9-c121-4da3-a5e2-0f317e3c630c + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:18 + + + UefiDecompressLib + TianoDecompressLib + DebugLib + BaseMemoryLib + + + BaseUefiTianoDecompressLib.c + + + MdePkg + EdkModulePkg + + diff --git a/EdkModulePkg/Library/BaseUefiTianoDecompressLib/build.xml b/EdkModulePkg/Library/BaseUefiTianoDecompressLib/build.xml new file mode 100644 index 0000000000..9b8695b963 --- /dev/null +++ b/EdkModulePkg/Library/BaseUefiTianoDecompressLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/DxeCoreCustomDecompressLibFromHob.c b/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/DxeCoreCustomDecompressLibFromHob.c new file mode 100644 index 0000000000..300cc91fed --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/DxeCoreCustomDecompressLibFromHob.c @@ -0,0 +1,105 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeCoreCustomDecompressLibFromHob.c + +Abstract: + + Custom Decompress Library from HOBs + +--*/ + +static DECOMPRESS_LIBRARY mCustomDecompress; + +EFI_STATUS +DxeCoreCustomDecompressLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = GetFirstGuidHob (&gEfiCustomizedDecompressProtocolGuid); + ASSERT (GuidHob != NULL); + CopyMem (&mCustomDecompress, GET_GUID_HOB_DATA (GuidHob), sizeof (mCustomDecompress)); + return EFI_SUCCESS; +} + +RETURN_STATUS +EFIAPI +CustomDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SourceSize - The size of source buffer + DestinationSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return mCustomDecompress.GetInfo (Source, SourceSize, DestinationSize, ScratchSize); +} + +RETURN_STATUS +EFIAPI +CustomDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + Destination - The destination buffer to store the decompressed data + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + +Returns: + + RETURN_SUCCESS - Decompression is successfull + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return mCustomDecompress.Decompress (Source, Destination, Scratch); +} diff --git a/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/DxeCoreCustomDecompressLibFromHob.mbd b/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/DxeCoreCustomDecompressLibFromHob.mbd new file mode 100644 index 0000000000..f183e5aa15 --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/DxeCoreCustomDecompressLibFromHob.mbd @@ -0,0 +1,30 @@ + + + + + DxeCoreCustomDecompressLibFromHob + 942e0182-3e1d-47f9-92dc-4939d1a0ba00 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-31 13:07 + + diff --git a/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/DxeCoreCustomDecompressLibFromHob.msa b/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/DxeCoreCustomDecompressLibFromHob.msa new file mode 100644 index 0000000000..e135047315 --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/DxeCoreCustomDecompressLibFromHob.msa @@ -0,0 +1,55 @@ + + + + + DxeCoreCustomDecompressLibFromHob + DXE_CORE + LIBRARY + 942e0182-3e1d-47f9-92dc-4939d1a0ba00 + EDK_RELEASE_VERSION 0x00020000 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-31 13:07 + + + CustomDecompressLib + DebugLib + HobLib + BaseMemoryLib + + + DxeCoreCustomDecompressLibFromHob.c + + + MdePkg + EdkModulePkg + + + CustomizedDecompress + + + + DxeCoreCustomDecompressLibConstructor + + + diff --git a/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/build.xml b/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/build.xml new file mode 100644 index 0000000000..c8fb0f7cd6 --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreCustomDecompressLibFromHob/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c b/EdkModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c new file mode 100644 index 0000000000..c75ab851f7 --- /dev/null +++ b/EdkModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.c @@ -0,0 +1,623 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeCorePerformance.c + +Abstract: + + Support for measurement of DXE performance + +--*/ + +// +// Interface declarations for Performance Protocol. +// +/** + Adds a record at the end of the performance measurement log + that records the start time of a performance measurement. + + Adds a record to the end of the performance measurement log + that contains the Handle, Token, and Module. + The end time of the new record must be set to zero. + If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record. + If TimeStamp is zero, the start time in the record is filled in with the value + read from the current time stamp. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement. + +**/ +EFI_STATUS +EFIAPI +StartGauge ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ); + +/** + Searches the performance measurement log from the beginning of the log + for the first matching record that contains a zero end time and fills in a valid end time. + + Searches the performance measurement log from the beginning of the log + for the first record that matches Handle, Token, and Module and has an end time value of zero. + If the record can not be found then return EFI_NOT_FOUND. + If the record is found and TimeStamp is not zero, + then the end time in the record is filled in with the value specified by TimeStamp. + If the record is found and TimeStamp is zero, then the end time in the matching record + is filled in with the current time stamp value. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval EFI_SUCCESS The end of the measurement was recorded. + @retval EFI_NOT_FOUND The specified measurement record could not be found. + +**/ +EFI_STATUS +EFIAPI +EndGauge ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ); + +/** + Retrieves a previously logged performance measurement. + + Retrieves the performance log entry from the performance log specified by LogEntryKey. + If it stands for a valid entry, then EFI_SUCCESS is returned and + GaugeDataEntry stores the pointer to that entry. + + @param LogEntryKey The key for the previous performance measurement log entry. + If 0, then the first performance measurement log entry is retrieved. + @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey + if the retrieval is successful. + + @retval EFI_SUCCESS The GuageDataEntry is successfuly found based on LogEntryKey. + @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number). + @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number). + @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL. + +**/ +EFI_STATUS +EFIAPI +GetGauge ( + IN UINTN LogEntryKey, + OUT GAUGE_DATA_ENTRY **GaugeDataEntry + ); + +// +// Definition for global variables. +// +STATIC GAUGE_DATA_HEADER *mGaugeData; +STATIC UINT32 mMaxGaugeRecords; + +PERFORMANCE_PROTOCOL PerformanceInterface = { + StartGauge, + EndGauge, + GetGauge + }; + + +/** + Searches in the gauge array with keyword Handle, Token and Module. + + This internal function searches for the gauge entry in the gauge array. + If there is an entry that exactly matches the given key word triple + and its end time stamp is zero, then the index of that gauge entry is returned; + otherwise, the the number of gauge entries in the array is returned. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + + @retval The index of gauge entry in the array. + +**/ +UINT32 +InternalSearchForGaugeEntry ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module OPTIONAL + ) +{ + UINT32 Index; + UINT32 NumberOfEntries; + GAUGE_DATA_ENTRY *GaugeEntryArray; + + if (Token == NULL) { + Token = ""; + } + if (Module == NULL) { + Module = ""; + } + + NumberOfEntries = mGaugeData->NumberOfEntries; + GaugeEntryArray = (GAUGE_DATA_ENTRY *) (mGaugeData + 1); + + for (Index = 0; Index < NumberOfEntries; Index++) { + if ((GaugeEntryArray[Index].Handle == (EFI_PHYSICAL_ADDRESS) (UINTN) Handle) && + AsciiStrnCmp (GaugeEntryArray[Index].Token, Token, PEI_PERFORMANCE_STRING_LENGTH) == 0 && + AsciiStrnCmp (GaugeEntryArray[Index].Module, Module, PEI_PERFORMANCE_STRING_LENGTH) == 0 && + GaugeEntryArray[Index].EndTimeStamp == 0 + ) { + break; + } + } + + return Index; +} + +/** + Adds a record at the end of the performance measurement log + that records the start time of a performance measurement. + + Adds a record to the end of the performance measurement log + that contains the Handle, Token, and Module. + The end time of the new record must be set to zero. + If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record. + If TimeStamp is zero, the start time in the record is filled in with the value + read from the current time stamp. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to record the measurement. + +**/ +EFI_STATUS +EFIAPI +StartGauge ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ) +{ + GAUGE_DATA_ENTRY *GaugeEntryArray; + UINTN GaugeDataSize; + UINTN OldGaugeDataSize; + GAUGE_DATA_HEADER *OldGaugeData; + EFI_STATUS Status; + UINT32 Index; + + Index = mGaugeData->NumberOfEntries; + if (Index >= mMaxGaugeRecords) { + // + // Try to enlarge the scale of gauge arrary. + // + OldGaugeData = mGaugeData; + OldGaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY) * mMaxGaugeRecords; + mMaxGaugeRecords *= 2; + GaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY) * mMaxGaugeRecords; + Status = gBS->AllocatePool ( + EfiBootServicesData, + GaugeDataSize, + (VOID **) &mGaugeData + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Initialize new data arry and migrate old data one. + // + mGaugeData = ZeroMem (mGaugeData, GaugeDataSize); + mGaugeData = CopyMem (mGaugeData, OldGaugeData, OldGaugeDataSize); + + gBS->FreePool (OldGaugeData); + } + + GaugeEntryArray = (GAUGE_DATA_ENTRY *) (mGaugeData + 1); + GaugeEntryArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle; + + if (Token != NULL) { + AsciiStrnCpy (GaugeEntryArray[Index].Token, Token, DXE_PERFORMANCE_STRING_LENGTH); + } + if (Module != NULL) { + AsciiStrnCpy (GaugeEntryArray[Index].Module, Module, DXE_PERFORMANCE_STRING_LENGTH); + } + + if (TimeStamp == 0) { + TimeStamp = GetPerformanceCounter (); + } + GaugeEntryArray[Index].StartTimeStamp = TimeStamp; + + mGaugeData->NumberOfEntries++; + + return EFI_SUCCESS; +} + +/** + Searches the performance measurement log from the beginning of the log + for the first matching record that contains a zero end time and fills in a valid end time. + + Searches the performance measurement log from the beginning of the log + for the first record that matches Handle, Token, and Module and has an end time value of zero. + If the record can not be found then return EFI_NOT_FOUND. + If the record is found and TimeStamp is not zero, + then the end time in the record is filled in with the value specified by TimeStamp. + If the record is found and TimeStamp is zero, then the end time in the matching record + is filled in with the current time stamp value. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval EFI_SUCCESS The end of the measurement was recorded. + @retval EFI_NOT_FOUND The specified measurement record could not be found. + +**/ +EFI_STATUS +EFIAPI +EndGauge ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ) +{ + GAUGE_DATA_ENTRY *GaugeEntryArray; + UINT32 Index; + + if (TimeStamp == 0) { + TimeStamp = GetPerformanceCounter (); + } + + Index = InternalSearchForGaugeEntry (Handle, Token, Module); + if (Index >= mGaugeData->NumberOfEntries) { + return EFI_NOT_FOUND; + } + GaugeEntryArray = (GAUGE_DATA_ENTRY *) (mGaugeData + 1); + GaugeEntryArray[Index].EndTimeStamp = TimeStamp; + + return EFI_SUCCESS; +} + +/** + Retrieves a previously logged performance measurement. + + Retrieves the performance log entry from the performance log specified by LogEntryKey. + If it stands for a valid entry, then EFI_SUCCESS is returned and + GaugeDataEntry stores the pointer to that entry. + + @param LogEntryKey The key for the previous performance measurement log entry. + If 0, then the first performance measurement log entry is retrieved. + @param GaugeDataEntry The indirect pointer to the gauge data entry specified by LogEntryKey + if the retrieval is successful. + + @retval EFI_SUCCESS The GuageDataEntry is successfuly found based on LogEntryKey. + @retval EFI_NOT_FOUND The LogEntryKey is the last entry (equals to the total entry number). + @retval EFI_INVALIDE_PARAMETER The LogEntryKey is not a valid entry (greater than the total entry number). + @retval EFI_INVALIDE_PARAMETER GaugeDataEntry is NULL. + +**/ +EFI_STATUS +EFIAPI +GetGauge ( + IN UINTN LogEntryKey, + OUT GAUGE_DATA_ENTRY **GaugeDataEntry + ) +{ + UINTN NumberOfEntries; + GAUGE_DATA_ENTRY *LogEntryArray; + + NumberOfEntries = (UINTN) (mGaugeData->NumberOfEntries); + if (LogEntryKey > NumberOfEntries) { + return EFI_INVALID_PARAMETER; + } + if (LogEntryKey == NumberOfEntries) { + return EFI_NOT_FOUND; + } + + LogEntryArray = (GAUGE_DATA_ENTRY *) (mGaugeData + 1); + + if (GaugeDataEntry == NULL) { + return EFI_INVALID_PARAMETER; + } + *GaugeDataEntry = &LogEntryArray[LogEntryKey]; + + return EFI_SUCCESS; +} + +/** + Dumps all the PEI performance log to DXE performance gauge array. + + This internal function dumps all the PEI performance log to the DXE performance gauge array. + It retrieves the optional GUID HOB for PEI performance and then saves the performance data + to DXE performance data structures. + +**/ +VOID +InternalGetPeiPerformance ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + PEI_PERFORMANCE_LOG_HEADER *LogHob; + PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray; + GAUGE_DATA_ENTRY *GaugeEntryArray; + UINT32 Index; + UINT32 NumberOfEntries; + + NumberOfEntries = 0; + GaugeEntryArray = (GAUGE_DATA_ENTRY *) (mGaugeData + 1); + + // + // Dump PEI Log Entries to DXE Guage Data structure. + // + GuidHob = GetFirstGuidHob (&gPeiPerformanceHobGuid); + if (GuidHob != NULL) { + LogHob = GET_GUID_HOB_DATA (GuidHob); + LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (LogHob + 1); + GaugeEntryArray = (GAUGE_DATA_ENTRY *) (mGaugeData + 1); + + NumberOfEntries = LogHob->NumberOfEntries; + for (Index = 0; Index < NumberOfEntries; Index++) { + GaugeEntryArray[Index].Handle = LogEntryArray[Index].Handle; + AsciiStrnCpy (GaugeEntryArray[Index].Token, LogEntryArray[Index].Token, DXE_PERFORMANCE_STRING_LENGTH); + AsciiStrnCpy (GaugeEntryArray[Index].Module, LogEntryArray[Index].Module, DXE_PERFORMANCE_STRING_LENGTH); + GaugeEntryArray[Index].StartTimeStamp = LogEntryArray[Index].StartTimeStamp; + GaugeEntryArray[Index].EndTimeStamp = LogEntryArray[Index].EndTimeStamp; + } + } + mGaugeData->NumberOfEntries = NumberOfEntries; +} + +/** + The constructor function initializes Performance infrastructure for DXE phase. + + The constructor function publishes Performance protocol, allocates memory to log DXE performance + and merges PEI performance data to DXE performance log. + It will ASSERT() if one of these operations fails and it will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +DxeCorePerformanceLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + UINTN GaugeDataSize; + + // + // Install the protocol interfaces. + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gPerformanceProtocolGuid, + EFI_NATIVE_INTERFACE, + &PerformanceInterface + ); + ASSERT_EFI_ERROR (Status); + + mMaxGaugeRecords = INIT_DXE_GAUGE_DATA_ENTRIES + MAX_PEI_PERFORMANCE_LOG_ENTRIES; + GaugeDataSize = sizeof (GAUGE_DATA_HEADER) + sizeof (GAUGE_DATA_ENTRY) * mMaxGaugeRecords; + Status = gBS->AllocatePool ( + EfiBootServicesData, + GaugeDataSize, + (VOID **) &mGaugeData + ); + ASSERT_EFI_ERROR (Status); + + ZeroMem (mGaugeData, GaugeDataSize); + + InternalGetPeiPerformance (); + + return Status; +} + +/** + Adds a record at the end of the performance measurement log + that records the start time of a performance measurement. + + Adds a record to the end of the performance measurement log + that contains the Handle, Token, and Module. + The end time of the new record must be set to zero. + If TimeStamp is not zero, then TimeStamp is used to fill in the start time in the record. + If TimeStamp is zero, the start time in the record is filled in with the value + read from the current time stamp. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The start of the measurement was recorded. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement. + +**/ +RETURN_STATUS +EFIAPI +StartPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ) +{ + EFI_STATUS Status; + + Status = StartGauge (Handle, Token, Module, TimeStamp); + return (RETURN_STATUS) Status; +} + +/** + Searches the performance measurement log from the beginning of the log + for the first matching record that contains a zero end time and fills in a valid end time. + + Searches the performance measurement log from the beginning of the log + for the first record that matches Handle, Token, and Module and has an end time value of zero. + If the record can not be found then return RETURN_NOT_FOUND. + If the record is found and TimeStamp is not zero, + then the end time in the record is filled in with the value specified by TimeStamp. + If the record is found and TimeStamp is zero, then the end time in the matching record + is filled in with the current time stamp value. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The end of the measurement was recorded. + @retval RETURN_NOT_FOUND The specified measurement record could not be found. + +**/ +RETURN_STATUS +EFIAPI +EndPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ) +{ + EFI_STATUS Status; + + Status = EndGauge (Handle, Token, Module, TimeStamp); + return (RETURN_STATUS) Status; +} + +/** + Retrieves a previously logged performance measurement. + + Retrieves the performance log entry from the performance log + that immediately follows the log entry specified by LogEntryKey. + If LogEntryKey is zero, then the first entry from the performance log is returned. + If the log entry specified by LogEntryKey is the last entry in the performance log, + then 0 is returned. Otherwise, the performance log entry is returned in Handle, + Token, Module, StartTimeStamp, and EndTimeStamp. + The key for the current performance log entry is returned. + + @param LogEntryKey The key for the previous performance measurement log entry. + If 0, then the first performance measurement log entry is retrieved. + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param StartTimeStamp The 64-bit time stamp that was recorded when the measurement was started. + @param EndTimeStamp The 64-bit time stamp that was recorded when the measurement was ended. + + @return The key for the current performance log entry. + +**/ +UINTN +EFIAPI +GetPerformanceMeasurement ( + UINTN LogEntryKey, + OUT CONST VOID **Handle, + OUT CONST CHAR8 **Token, + OUT CONST CHAR8 **Module, + OUT UINT64 *StartTimeStamp, + OUT UINT64 *EndTimeStamp + ) +{ + EFI_STATUS Status; + GAUGE_DATA_ENTRY *GaugeData; + + ASSERT (Handle != NULL); + ASSERT (Token != NULL); + ASSERT (Module != NULL); + ASSERT (StartTimeStamp != NULL); + ASSERT (EndTimeStamp != NULL); + + Status = GetGauge (LogEntryKey++, &GaugeData); + + // + // Make sure that LogEntryKey is a valid log entry key, + // + ASSERT (Status != EFI_INVALID_PARAMETER); + + if (EFI_ERROR (Status)) { + // + // The LogEntryKey is the last entry (equals to the total entry number). + // + return 0; + } + + ASSERT (GaugeData != NULL); + + *Handle = (VOID *) (UINTN) GaugeData->Handle; + *Token = GaugeData->Token; + *Module = GaugeData->Module; + *StartTimeStamp = GaugeData->StartTimeStamp; + *EndTimeStamp = GaugeData->EndTimeStamp; + + return LogEntryKey; +} + +/** + Returns TRUE if the performance measurement macros are enabled. + + This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. + @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is clear. + +**/ +BOOLEAN +EFIAPI +PerformanceMeasurementEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0); +} diff --git a/EdkModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.mbd b/EdkModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.mbd new file mode 100644 index 0000000000..a8f235f65b --- /dev/null +++ b/EdkModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.mbd @@ -0,0 +1,29 @@ + + + + + DxeCorePerformanceLib + D0F78BBF-0A30-4c63-8A48-0F618A4AFACD + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-04-04 11:10 + + diff --git a/EdkModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.msa b/EdkModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.msa new file mode 100644 index 0000000000..40ce308449 --- /dev/null +++ b/EdkModulePkg/Library/DxeCorePerformanceLib/DxeCorePerformanceLib.msa @@ -0,0 +1,70 @@ + + + + + DxeCorePerformanceLib + DXE_CORE + LIBRARY + D0F78BBF-0A30-4c63-8A48-0F618A4AFACD + EDK_RELEASE_VERSION 0x00020000 + Component description file for the Tiano Decompress Library + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-04 11:10 + + + PerformanceLib + DebugLib + HobLib + BaseLib + BaseMemoryLib + TimerLib + PcdLib + UefiBootServicesTableLib + + + DxeCorePerformanceLib.c + + + MdePkg + EdkModulePkg + + + Performance + + + + PeiPerformanceHob + + + + + DxeCorePerformanceLibConstructor + + + + + PcdPerformanceLibraryPropertyMask + 0x00000001 + UINT8 + + + diff --git a/EdkModulePkg/Library/DxeCorePerformanceLib/build.xml b/EdkModulePkg/Library/DxeCorePerformanceLib/build.xml new file mode 100644 index 0000000000..b9d04eed7b --- /dev/null +++ b/EdkModulePkg/Library/DxeCorePerformanceLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/DxeCoreTianoDecompressLibFromHob.c b/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/DxeCoreTianoDecompressLibFromHob.c new file mode 100644 index 0000000000..1bb832be02 --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/DxeCoreTianoDecompressLibFromHob.c @@ -0,0 +1,106 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeCoreTianoDecompressLibFromHob.c + +Abstract: + + Tiano Decompress Library from HOBs + +--*/ + +static DECOMPRESS_LIBRARY mTianoDecompress; + +EFI_STATUS +DxeCoreTianoDecompressLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = GetFirstGuidHob (&gEfiTianoDecompressProtocolGuid); + ASSERT (GuidHob != NULL); + CopyMem (&mTianoDecompress, GET_GUID_HOB_DATA (GuidHob), sizeof (mTianoDecompress)); + return EFI_SUCCESS; +} + +RETURN_STATUS +EFIAPI +TianoDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SourceSize - The size of source buffer + DestinationSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return mTianoDecompress.GetInfo (Source, SourceSize, DestinationSize, ScratchSize); +} + +RETURN_STATUS +EFIAPI +TianoDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + Destination - The destination buffer to store the decompressed data + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + +Returns: + + RETURN_SUCCESS - Decompression is successfull + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return mTianoDecompress.Decompress (Source, Destination, Scratch); +} + diff --git a/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/DxeCoreTianoDecompressLibFromHob.mbd b/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/DxeCoreTianoDecompressLibFromHob.mbd new file mode 100644 index 0000000000..f3ca9a4321 --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/DxeCoreTianoDecompressLibFromHob.mbd @@ -0,0 +1,30 @@ + + + + + DxeCoreTianoDecompressLibFromHob + cef487a1-751d-4fe0-a39b-e6892b4610c8 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-31 13:10 + + diff --git a/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/DxeCoreTianoDecompressLibFromHob.msa b/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/DxeCoreTianoDecompressLibFromHob.msa new file mode 100644 index 0000000000..bf49ef5644 --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/DxeCoreTianoDecompressLibFromHob.msa @@ -0,0 +1,55 @@ + + + + + DxeCoreTianoDecompressLibFromHob + DXE_CORE + LIBRARY + cef487a1-751d-4fe0-a39b-e6892b4610c8 + EDK_RELEASE_VERSION 0x00020000 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-31 13:10 + + + TianoDecompressLib + DebugLib + HobLib + BaseMemoryLib + + + DxeCoreTianoDecompressLibFromHob.c + + + MdePkg + EdkModulePkg + + + TianoDecompress + + + + DxeCoreTianoDecompressLibConstructor + + + diff --git a/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/build.xml b/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/build.xml new file mode 100644 index 0000000000..095b92e284 --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreTianoDecompressLibFromHob/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/DxeCoreUefiDecompressLibFromHob.c b/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/DxeCoreUefiDecompressLibFromHob.c new file mode 100644 index 0000000000..b4bd539975 --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/DxeCoreUefiDecompressLibFromHob.c @@ -0,0 +1,105 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxeCoreUefiDecompressLibFromHob.c + +Abstract: + + UEFI Decompress Library from HOBs + +--*/ + +static DECOMPRESS_LIBRARY mEfiDecompress; + +EFI_STATUS +DxeCoreUefiDecompressLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = GetFirstGuidHob (&gEfiDecompressProtocolGuid); + ASSERT (GuidHob != NULL); + CopyMem (&mEfiDecompress, GET_GUID_HOB_DATA (GuidHob), sizeof (mEfiDecompress)); + return EFI_SUCCESS; +} + +RETURN_STATUS +EFIAPI +UefiDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SourceSize - The size of source buffer + DestinationSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + RETURN_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return mEfiDecompress.GetInfo (Source, SourceSize, DestinationSize, ScratchSize); +} + +RETURN_STATUS +EFIAPI +UefiDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + Destination - The destination buffer to store the decompressed data + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + +Returns: + + RETURN_SUCCESS - Decompression is successfull + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return mEfiDecompress.Decompress (Source, Destination, Scratch); +} diff --git a/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/DxeCoreUefiDecompressLibFromHob.mbd b/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/DxeCoreUefiDecompressLibFromHob.mbd new file mode 100644 index 0000000000..5bb0b9344d --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/DxeCoreUefiDecompressLibFromHob.mbd @@ -0,0 +1,30 @@ + + + + + DxeCoreUefiDecompressLibFromHob + 5c12c06f-5cf8-48a6-9860-6c5b2c036bbf + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-31 13:10 + + diff --git a/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/DxeCoreUefiDecompressLibFromHob.msa b/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/DxeCoreUefiDecompressLibFromHob.msa new file mode 100644 index 0000000000..895b86c4ba --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/DxeCoreUefiDecompressLibFromHob.msa @@ -0,0 +1,55 @@ + + + + + DxeCoreUefiDecompressLibFromHob + DXE_CORE + LIBRARY + 5c12c06f-5cf8-48a6-9860-6c5b2c036bbf + EDK_RELEASE_VERSION 0x00020000 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-31 13:10 + + + UefiDecompressLib + DebugLib + HobLib + BaseMemoryLib + + + DxeCoreUefiDecompressLibFromHob.c + + + MdePkg + EdkModulePkg + + + Decompress + + + + DxeCoreUefiDecompressLibConstructor + + + diff --git a/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/build.xml b/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/build.xml new file mode 100644 index 0000000000..b46ad569f0 --- /dev/null +++ b/EdkModulePkg/Library/DxeCoreUefiDecompressLibFromHob/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/DebugLib.c b/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/DebugLib.c new file mode 100644 index 0000000000..5a7300faba --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/DebugLib.c @@ -0,0 +1,314 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugLib.c + +Abstract: + + EFI Debug Library + +--*/ + +static BOOLEAN mDebugLevelInstalled = FALSE; +static EFI_DEBUG_LEVEL_PROTOCOL mDebugLevel = { 0 }; + +EFI_STATUS +DebugLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + + // + // Initialize Debug Level Protocol + // + mDebugLevel.DebugLevel = PcdGet32(PcdDebugPrintErrorLevel); + + // + // Install Debug Level Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiDebugLevelProtocolGuid, &mDebugLevel, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Set flag to show that the Debug Level Protocol has been installed + // + mDebugLevelInstalled = TRUE; + + return EFI_SUCCESS; +} + +VOID +EFIAPI +DebugAssert ( + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) +/*++ + +Routine Description: + + Worker function for ASSERT(). If Error Logging hub is loaded log ASSERT + information. If Error Logging hub is not loaded CpuBreakpoint (). + + We use UINT64 buffers due to IPF alignment concerns. + +Arguments: + + FileName - File name of failing routine. + + LineNumber - Line number of failing ASSERT(). + + Description - Descritption, usally the assertion, + +Returns: + + None + +--*/ +{ + UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof(UINT64)]; + EFI_DEBUG_ASSERT_DATA *AssertData; + UINTN TotalSize; + CHAR8 *Temp; + + if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) == 0) { + return; + } + + // + // Make sure it will all fit in the passed in buffer + // + TotalSize = sizeof (EFI_DEBUG_ASSERT_DATA) + AsciiStrLen (FileName) + 1 + AsciiStrLen (Description) + 1; + if (TotalSize <= EFI_STATUS_CODE_DATA_MAX_SIZE) { + // + // Fill in EFI_DEBUG_ASSERT_DATA + // + AssertData = (EFI_DEBUG_ASSERT_DATA *)Buffer; + AssertData->LineNumber = (UINT32)LineNumber; + + // + // Copy Ascii FileName including NULL. + // + Temp = AsciiStrCpy ((CHAR8 *)(AssertData + 1), FileName); + + // + // Copy Ascii Description + // + AsciiStrCpy (Temp + AsciiStrLen(FileName) + 1, Description); + + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE), + AssertData, + TotalSize + ); + } + + // + // Put break point in module that contained the error. + // + CpuBreakpoint (); +} + +VOID +DebugVPrint ( + IN UINTN ErrorLevel, + IN CHAR8 *Format, + IN VA_LIST Marker + ) +/*++ + +Routine Description: + + Worker function for DEBUG(). If Error Logging hub is loaded log ASSERT + information. If Error Logging hub is not loaded do nothing. + + We use UINT64 buffers due to IPF alignment concerns. + +Arguments: + + ErrorLevel - If error level is set do the debug print. + + Format - String to use for the print, followed by Print arguments. + + Marker - VarArgs + +Returns: + + None + +--*/ +{ + UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof (UINT64)]; + EFI_DEBUG_INFO *DebugInfo; + UINTN TotalSize; + UINTN Index; + UINT64 *ArgumentPointer; + + // + // Check driver Debug Level value and global debug level + // + if (mDebugLevelInstalled) { + if ((ErrorLevel & mDebugLevel.DebugLevel) == 0) { + return; + } + } else { + if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) { + return; + } + } + + TotalSize = sizeof (EFI_DEBUG_INFO) + 12 * sizeof (UINT64 *) + AsciiStrLen (Format) + 1; + if (TotalSize > EFI_STATUS_CODE_DATA_MAX_SIZE) { + return; + } + + // + // Then EFI_DEBUG_INFO + // + DebugInfo = (EFI_DEBUG_INFO *)Buffer; + DebugInfo->ErrorLevel = (UINT32)ErrorLevel; + + // + // 256 byte mini Var Arg stack. That is followed by the format string. + // + for (Index = 0, ArgumentPointer = (UINT64 *)(DebugInfo + 1); Index < 12; Index++, ArgumentPointer++) { + *ArgumentPointer = VA_ARG (Marker, UINT64); + } + AsciiStrCpy ((CHAR8 *)ArgumentPointer, Format); + + // + // + // + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_DEBUG_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_DC_UNSPECIFIED), + DebugInfo, + TotalSize + ); +} + +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ) +/*++ + +Routine Description: + + Wrapper for DebugVPrint () + +Arguments: + + ErrorLevel - If error level is set do the debug print. + + Format - String to use for the print, followed by Print arguments. + + ... - Print arguments. + +Returns: + + None + +--*/ +{ + VA_LIST Marker; + + VA_START (Marker, Format); + DebugVPrint (ErrorLevel, Format, Marker); + VA_END (Marker); +} + +/** + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + + If Length is greater than (MAX_ADDRESS – Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ +// SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue)); + SetMem (Buffer, Length, 0xAF); + return Buffer; +} + +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} + diff --git a/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/EdkDxeDebugLibReportStatusCode.mbd b/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/EdkDxeDebugLibReportStatusCode.mbd new file mode 100644 index 0000000000..9825a208c4 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/EdkDxeDebugLibReportStatusCode.mbd @@ -0,0 +1,30 @@ + + + + + EdkDxeDebugLibReportStatusCode + 76a2a4d8-f605-407a-8057-4a17dcdc4c6d + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-31 13:12 + + diff --git a/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/EdkDxeDebugLibReportStatusCode.msa b/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/EdkDxeDebugLibReportStatusCode.msa new file mode 100644 index 0000000000..e80bee2a87 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/EdkDxeDebugLibReportStatusCode.msa @@ -0,0 +1,69 @@ + + + + + EdkDxeDebugLibReportStatusCode + DXE_DRIVER + LIBRARY + 76a2a4d8-f605-407a-8057-4a17dcdc4c6d + EDK_RELEASE_VERSION 0x00020000 + Debug Library for DXE drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-31 13:12 + + + DebugLib + ReportStatusCodeLib + BaseMemoryLib + BaseLib + PcdLib + UefiBootServicesTableLib + + + DebugLib.c + + + MdePkg + EdkModulePkg + + + DebugLevel + + + + DebugLibConstructor + + + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + + + diff --git a/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/build.xml b/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/build.xml new file mode 100644 index 0000000000..fb105466c7 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeDebugLibReportStatusCode/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.mbd b/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.mbd new file mode 100644 index 0000000000..bc500a04a7 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkDxePeCoffLoaderFromHobLib + ed3de5c8-c389-44f2-a35e-2ebdc9802a49 + 0 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-03-12 17:09 + 2006-03-22 15:50 + + diff --git a/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.msa b/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.msa new file mode 100644 index 0000000000..892ae8a34a --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/EdkDxePeCoffLoaderFromHobLib.msa @@ -0,0 +1,50 @@ + + + + + EdkDxePeCoffLoaderFromHobLib + DXE_DRIVER + LIBRARY + ed3de5c8-c389-44f2-a35e-2ebdc9802a49 + 0 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 0 + 2006-03-12 17:09 + 2006-03-22 15:50 + + + EdkPeCoffLoaderLib + HobLib + + + PeCoff.c + + + MdePkg + EdkModulePkg + + + + PeiPeCoffLoader + + + diff --git a/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/PeCoff.c b/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/PeCoff.c new file mode 100644 index 0000000000..7afe9c2446 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/PeCoff.c @@ -0,0 +1,38 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Decompress.c + +Abstract: + +--*/ + + + + + +EFI_PEI_PE_COFF_LOADER_PROTOCOL * +EFIAPI +GetPeCoffLoaderProtocol ( + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = GetFirstGuidHob (&gEfiPeiPeCoffLoaderGuid); + if (GuidHob == NULL) { + return NULL; + } else { + return (EFI_PEI_PE_COFF_LOADER_PROTOCOL *)(*(UINTN *)(GET_GUID_HOB_DATA (GuidHob))); + } +} + diff --git a/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/build.xml b/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/build.xml new file mode 100644 index 0000000000..ba50f03c3d --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePeCoffLoaderFromHobLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkDxePerformanceLib/DxePerformanceLib.c b/EdkModulePkg/Library/EdkDxePerformanceLib/DxePerformanceLib.c new file mode 100644 index 0000000000..5e448c6974 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePerformanceLib/DxePerformanceLib.c @@ -0,0 +1,213 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DxePerformanceLib.c + +Abstract: + + Performance Library + +--*/ + +STATIC PERFORMANCE_PROTOCOL *mPerformance = NULL; + +/** + The constructor function caches the pointer to Performance protocol. + + The constructor function locates Performance protocol from protocol database. + It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +PerformanceLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gPerformanceProtocolGuid, NULL, (VOID **) &mPerformance); + ASSERT_EFI_ERROR (Status); + ASSERT (mPerformance != NULL); + + return Status; +} + +/** + Creates a record for the beginning of a performance measurement. + + Creates a record that contains the Handle, Token, and Module. + If TimeStamp is not zero, then TimeStamp is added to the record as the start time. + If TimeStamp is zero, then this function reads the current time stamp + and adds that time stamp value to the record as the start time. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The start of the measurement was recorded. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement. + +**/ +RETURN_STATUS +EFIAPI +StartPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ) +{ + EFI_STATUS Status; + + Status = mPerformance->StartGauge (Handle, Token, Module, TimeStamp); + + return (RETURN_STATUS) Status; +} + +/** + Fills in the end time of a performance measurement. + + Looks up the record that matches Handle, Token, and Module. + If the record can not be found then return RETURN_NOT_FOUND. + If the record is found and TimeStamp is not zero, + then TimeStamp is added to the record as the end time. + If the record is found and TimeStamp is zero, then this function reads + the current time stamp and adds that time stamp value to the record as the end time. + If this function is called multiple times for the same record, then the end time is overwritten. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The end of the measurement was recorded. + @retval RETURN_NOT_FOUND The specified measurement record could not be found. + +**/ +RETURN_STATUS +EFIAPI +EndPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ) +{ + EFI_STATUS Status; + + Status = mPerformance->EndGauge (Handle, Token, Module, TimeStamp); + + return (RETURN_STATUS) Status; +} + +/** + Retrieves a previously logged performance measurement. + + Looks up the record that matches Handle, Token, and Module. + If the record can not be found then return RETURN_NOT_FOUND. + If the record is found then the start of the measurement is returned in StartTimeStamp, + and the end of the measurement is returned in EndTimeStamp. + + @param LogEntryKey The key for the previous performance measurement log entry. + If 0, then the first performance measurement log entry is retrieved. + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param StartTimeStamp The 64-bit time stamp that was recorded when the measurement was started. + @param EndTimeStamp The 64-bit time stamp that was recorded when the measurement was ended. + + @return The key for the current performance log entry. + +**/ +UINTN +EFIAPI +GetPerformanceMeasurement ( + UINTN LogEntryKey, + OUT CONST VOID **Handle, + OUT CONST CHAR8 **Token, + OUT CONST CHAR8 **Module, + OUT UINT64 *StartTimeStamp, + OUT UINT64 *EndTimeStamp + ) +{ + EFI_STATUS Status; + GAUGE_DATA_ENTRY *GaugeData; + + ASSERT (Handle != NULL); + ASSERT (Token != NULL); + ASSERT (Module != NULL); + ASSERT (StartTimeStamp != NULL); + ASSERT (EndTimeStamp != NULL); + + Status = mPerformance->GetGauge (LogEntryKey++, &GaugeData); + + // + // Make sure that LogEntryKey is a valid log entry key, + // + ASSERT (Status != EFI_INVALID_PARAMETER); + + if (EFI_ERROR (Status)) { + // + // The LogEntryKey is the last entry (equals to the total entry number). + // + return 0; + } + + ASSERT (GaugeData != NULL); + + *Handle = (VOID *) (UINTN) GaugeData->Handle; + *Token = GaugeData->Token; + *Module = GaugeData->Module; + *StartTimeStamp = GaugeData->StartTimeStamp; + *EndTimeStamp = GaugeData->EndTimeStamp; + + return LogEntryKey; +} + +/** + Returns TRUE if the performance measurement macros are enabled. + + This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. + @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is clear. + +**/ +BOOLEAN +EFIAPI +PerformanceMeasurementEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0); +} diff --git a/EdkModulePkg/Library/EdkDxePerformanceLib/EdkDxePerformanceLib.mbd b/EdkModulePkg/Library/EdkDxePerformanceLib/EdkDxePerformanceLib.mbd new file mode 100644 index 0000000000..7bd0e106f0 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePerformanceLib/EdkDxePerformanceLib.mbd @@ -0,0 +1,29 @@ + + + + + EdkDxePerformanceLib + 8B8B4CCC-65FC-41a5-8067-308B8E42CCF2 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2006, 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. + + 2006-04-04 11:11 + + diff --git a/EdkModulePkg/Library/EdkDxePerformanceLib/EdkDxePerformanceLib.msa b/EdkModulePkg/Library/EdkDxePerformanceLib/EdkDxePerformanceLib.msa new file mode 100644 index 0000000000..8cddf79be5 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePerformanceLib/EdkDxePerformanceLib.msa @@ -0,0 +1,62 @@ + + + + + EdkDxePerformanceLib + DXE_DRIVER + LIBRARY + 8B8B4CCC-65FC-41a5-8067-308B8E42CCF2 + EDK_RELEASE_VERSION 0x00020000 + Memory-only library functions with no library constructor/destructor + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-04 11:11 + + + PerformanceLib + DebugLib + UefiBootServicesTableLib + TimerLib + PcdLib + + + DxePerformanceLib.c + + + MdePkg + EdkModulePkg + + + Performance + + + + PerformanceLibConstructor + + + + + PcdPerformanceLibraryPropertyMask + 0x00000001 + UINT8 + + + diff --git a/EdkModulePkg/Library/EdkDxePerformanceLib/build.xml b/EdkModulePkg/Library/EdkDxePerformanceLib/build.xml new file mode 100644 index 0000000000..5a1dca4e89 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePerformanceLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkDxePrintLib/EdkDxePrintLib.mbd b/EdkModulePkg/Library/EdkDxePrintLib/EdkDxePrintLib.mbd new file mode 100644 index 0000000000..ca9912b2c1 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePrintLib/EdkDxePrintLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkDxePrintLib + 50bcb105-6634-441d-b403-659110a03ad2 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + diff --git a/EdkModulePkg/Library/EdkDxePrintLib/EdkDxePrintLib.msa b/EdkModulePkg/Library/EdkDxePrintLib/EdkDxePrintLib.msa new file mode 100644 index 0000000000..bd58f916db --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePrintLib/EdkDxePrintLib.msa @@ -0,0 +1,49 @@ + + + + + EdkDxePrintLib + DXE_DRIVER + LIBRARY + 50bcb105-6634-441d-b403-659110a03ad2 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + PrintLib + MemoryAllocationLib + UefiBootServicesTableLib + + + PrintLib.c + + + MdePkg + EdkModulePkg + + + Print + + diff --git a/EdkModulePkg/Library/EdkDxePrintLib/PrintLib.c b/EdkModulePkg/Library/EdkDxePrintLib/PrintLib.c new file mode 100644 index 0000000000..30c0354021 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePrintLib/PrintLib.c @@ -0,0 +1,145 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PrintLib.c + +Abstract: + + Print Library + +--*/ + + + +static EFI_PRINT_PROTOCOL *gPrintProtocol = NULL; + +UINTN +UnicodeVSPrint ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN const CHAR16 *FormatString, + IN VA_LIST Marker + ) +/*++ + +Routine Description: + + VSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this rountine allows the nesting of Vararg routines. Thus + this is the main print working routine + +Arguments: + + StartOfBuffer - Unicode buffer to print the results of the parsing of Format into. + + BufferSize - Maximum number of characters to put into buffer. Zero means + no limit. + + FormatString - Unicode format string see file header for more details. + + Marker - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +{ + EFI_STATUS Status; + + if (gPrintProtocol == NULL) { + Status = gBS->LocateProtocol ( + &gEfiPrintProtocolGuid, + NULL, + (VOID **)&gPrintProtocol + ); + if (EFI_ERROR (Status)) { + gPrintProtocol = NULL; + } + if (gPrintProtocol == NULL) { + return 0; + } + } + return gPrintProtocol->VSPrint (StartOfBuffer, BufferSize, FormatString, Marker); +} + +UINTN +UnicodeSPrint ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN const CHAR16 *FormatString, + ... + ) + +{ + UINTN Return; + VA_LIST Marker; + + VA_START (Marker, FormatString); + Return = UnicodeVSPrint (StartOfBuffer, BufferSize, FormatString, Marker); + VA_END (Marker); + return Return; +} + +UINTN +AsciiVSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN const CHAR8 *FormatString, + IN VA_LIST Marker + ) +/*++ + +Routine Description: + + VSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this rountine allows the nesting of Vararg routines. Thus + this is the main print working routine + +Arguments: + + StartOfBuffer - Unicode buffer to print the results of the parsing of Format into. + + BufferSize - Maximum number of characters to put into buffer. Zero means + no limit. + + FormatString - Unicode format string see file header for more details. + + Marker - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +{ + return 0; +} + +UINTN +AsciiSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN const CHAR8 *FormatString, + ... + ) + +{ + UINTN Return; + VA_LIST Marker; + + VA_START (Marker, FormatString); + Return = AsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker); + VA_END (Marker); + return Return; +} diff --git a/EdkModulePkg/Library/EdkDxePrintLib/build.xml b/EdkModulePkg/Library/EdkDxePrintLib/build.xml new file mode 100644 index 0000000000..2ad6bed86c --- /dev/null +++ b/EdkModulePkg/Library/EdkDxePrintLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Common/RuntimeLib.c b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Common/RuntimeLib.c new file mode 100644 index 0000000000..adddf933e2 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Common/RuntimeLib.c @@ -0,0 +1,258 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RuntimeLib.c + +Abstract: + + Light weight lib to support Tiano drivers. + +--*/ + +#include + +// +// Driver Lib Module Globals +// +STATIC EFI_EVENT mRuntimeNotifyEvent; +STATIC EFI_EVENT mEfiVirtualNotifyEvent; +STATIC BOOLEAN mEfiGoneVirtual = FALSE; +STATIC BOOLEAN mEfiAtRuntime = FALSE; + +EFI_RUNTIME_SERVICES *mRT = NULL; + +VOID +EFIAPI +RuntimeDriverExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Set AtRuntime flag as TRUE after ExitBootServices + +Arguments: + + Event - The Event that is being processed + + Context - Event Context + +Returns: + + None + +--*/ +{ + EFI_EVENT_NOTIFY ChildNotifyEventHandler; + UINTN Index; + + for (Index = 0; + _gDriverExitBootServicesEvent[Index] != NULL; + Index++) { + ChildNotifyEventHandler = _gDriverExitBootServicesEvent[Index]; + ChildNotifyEventHandler (Event, NULL); + } + + mEfiAtRuntime = TRUE; +} + +STATIC +VOID +EFIAPI +RuntimeLibVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + +Arguments: + + Event - The Event that is being processed + + Context - Event Context + +Returns: + + None + +--*/ +{ + UINTN Index; + EFI_EVENT_NOTIFY ChildNotifyEventHandler; + + for (Index = 0; + _gDriverSetVirtualAddressMapEvent[Index] != NULL; + Index++) { + ChildNotifyEventHandler = _gDriverSetVirtualAddressMapEvent[Index]; + ChildNotifyEventHandler (Event, NULL); + } + + // + // Update global for Runtime Services Table and IO + // + EfiConvertInternalPointer ((VOID **) &mRT); + + // + // Clear out BootService globals + // + gBS = NULL; + gST = NULL; + mEfiGoneVirtual = TRUE; +} + +EFI_STATUS +RuntimeDriverLibConstruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Intialize runtime Driver Lib if it has not yet been initialized. + +Arguments: + + ImageHandle - The firmware allocated handle for the EFI image. + + SystemTable - A pointer to the EFI System Table. + + GoVirtualChildEvent - Caller can register a virtual notification event. + +Returns: + + EFI_STATUS always returns EFI_SUCCESS except EFI_ALREADY_STARTED if already started. + +--*/ +{ + EFI_STATUS Status; + + mRT = SystemTable->RuntimeServices; + + // + // Register our ExitBootServices () notify function + // + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES, + EFI_TPL_NOTIFY, + RuntimeDriverExitBootServices, + NULL, + &mRuntimeNotifyEvent + ); + + ASSERT_EFI_ERROR (Status); + + // + // Register SetVirtualAddressMap () notify function + // + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + EFI_TPL_NOTIFY, + RuntimeLibVirtualNotifyEvent, + NULL, + &mEfiVirtualNotifyEvent + ); + + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +EFI_STATUS +RuntimeDriverLibDeconstruct ( + VOID + ) +/*++ + +Routine Description: + + This routine will free some resources which have been allocated in + EfiInitializeRuntimeDriverLib(). If a runtime driver exits with an error, + it must call this routine to free the allocated resource before the exiting. + +Arguments: + + None + +Returns: + + EFI_SUCCESS - Shotdown the Runtime Driver Lib successfully + EFI_UNSUPPORTED - Runtime Driver lib was not initialized at all + +--*/ +{ + EFI_STATUS Status; + + // + // Close our ExitBootServices () notify function + // + Status = gBS->CloseEvent (mRuntimeNotifyEvent); + ASSERT_EFI_ERROR (Status); + + // + // Close SetVirtualAddressMap () notify function + // + Status = gBS->CloseEvent (mEfiVirtualNotifyEvent); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +BOOLEAN +EfiAtRuntime ( + VOID + ) +/*++ + +Routine Description: + Return TRUE if ExitBootServices () has been called + +Arguments: + NONE + +Returns: + TRUE - If ExitBootServices () has been called + +--*/ +{ + return mEfiAtRuntime; +} + +BOOLEAN +EfiGoneVirtual ( + VOID + ) +/*++ + +Routine Description: + Return TRUE if SetVirtualAddressMap () has been called + +Arguments: + NONE + +Returns: + TRUE - If SetVirtualAddressMap () has been called + +--*/ +{ + return mEfiGoneVirtual; +} + diff --git a/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Common/RuntimeService.c b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Common/RuntimeService.c new file mode 100644 index 0000000000..971dcdbf89 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Common/RuntimeService.c @@ -0,0 +1,480 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RuntimeService.c + +Abstract: + + Light weight lib to support Tiano drivers. + +--*/ + +#include + +VOID +EfiResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData + ) +/*++ + +Routine Description: + + Resets the entire platform. + +Arguments: + + ResetType - The type of reset to perform. + ResetStatus - The status code for the reset. + DataSize - The size, in bytes, of ResetData. + ResetData - A data buffer that includes a Null-terminated Unicode string, optionally + followed by additional binary data. + +Returns: + + None + +--*/ +{ + mRT->ResetSystem (ResetType, ResetStatus, DataSize, ResetData); +} + +// +// The following functions hide the mRT local global from the call to +// runtime service in the EFI system table. +// +EFI_STATUS +EfiGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +/*++ + +Routine Description: + + Returns the current time and date information, and the time-keeping + capabilities of the hardware platform. + +Arguments: + + Time - A pointer to storage to receive a snapshot of the current time. + Capabilities - An optional pointer to a buffer to receive the real time clock device¡¯s + capabilities. + +Returns: + + Status code + +--*/ +{ + return mRT->GetTime (Time, Capabilities); +} + +EFI_STATUS +EfiSetTime ( + IN EFI_TIME *Time + ) +/*++ + +Routine Description: + + Sets the current local time and date information. + +Arguments: + + Time - A pointer to the current time. + +Returns: + + Status code + +--*/ +{ + return mRT->SetTime (Time); +} + +EFI_STATUS +EfiGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +/*++ + +Routine Description: + + Returns the current wakeup alarm clock setting. + +Arguments: + + Enabled - Indicates if the alarm is currently enabled or disabled. + Pending - Indicates if the alarm signal is pending and requires acknowledgement. + Time - The current alarm setting. + +Returns: + + Status code + +--*/ +{ + return mRT->GetWakeupTime (Enabled, Pending, Time); +} + +EFI_STATUS +EfiSetWakeupTime ( + IN BOOLEAN Enable, + IN EFI_TIME *Time + ) +/*++ + +Routine Description: + + Sets the system wakeup alarm clock time. + +Arguments: + + Enable - Enable or disable the wakeup alarm. + Time - If Enable is TRUE, the time to set the wakeup alarm for. + If Enable is FALSE, then this parameter is optional, and may be NULL. + +Returns: + + Status code + +--*/ +{ + return mRT->SetWakeupTime (Enable, Time); +} + + + + +EFI_STATUS +EfiGetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +/*++ + +Routine Description: + + Returns the value of a variable. + +Arguments: + + VariableName - A Null-terminated Unicode string that is the name of the + vendor¡¯s variable. + VendorGuid - A unique identifier for the vendor. + Attributes - If not NULL, a pointer to the memory location to return the + attributes bitmask for the variable. + DataSize - On input, the size in bytes of the return Data buffer. + On output the size of data returned in Data. + Data - The buffer to return the contents of the variable. + +Returns: + + Status code + +--*/ +{ + return mRT->GetVariable (VariableName, VendorGuid, Attributes, DataSize, Data); +} + +EFI_STATUS +EfiGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +/*++ + +Routine Description: + + Enumerates the current variable names. + +Arguments: + + VariableNameSize - The size of the VariableName buffer. + VariableName - On input, supplies the last VariableName that was returned + by GetNextVariableName(). + On output, returns the Nullterminated Unicode string of the + current variable. + VendorGuid - On input, supplies the last VendorGuid that was returned by + GetNextVariableName(). + On output, returns the VendorGuid of the current variable. + +Returns: + + Status code + +--*/ +{ + return mRT->GetNextVariableName (VariableNameSize, VariableName, VendorGuid); +} + +EFI_STATUS +EfiSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +/*++ + +Routine Description: + + Sets the value of a variable. + +Arguments: + + VariableName - A Null-terminated Unicode string that is the name of the + vendor¡¯s variable. + VendorGuid - A unique identifier for the vendor. + Attributes - Attributes bitmask to set for the variable. + DataSize - The size in bytes of the Data buffer. + Data - The contents for the variable. + +Returns: + + Status code + +--*/ +{ + return mRT->SetVariable (VariableName, VendorGuid, Attributes, DataSize, Data); +} + +EFI_STATUS +EfiGetNextHighMonotonicCount ( + OUT UINT32 *HighCount + ) +/*++ + +Routine Description: + + Returns the next high 32 bits of the platform¡¯s monotonic counter. + +Arguments: + + HighCount - Pointer to returned value. + +Returns: + + Status code + +--*/ +{ + return mRT->GetNextHighMonotonicCount (HighCount); +} + +EFI_STATUS +EfiConvertPointer ( + IN UINTN DebugDisposition, + IN OUT VOID *Address + ) +/*++ + +Routine Description: + + Determines the new virtual address that is to be used on subsequent memory accesses. + +Arguments: + + DebugDisposition - Supplies type information for the pointer being converted. + Address - A pointer to a pointer that is to be fixed to be the value needed + for the new virtual address mappings being applied. + +Returns: + + Status code + +--*/ +{ + return mRT->ConvertPointer (DebugDisposition, Address); +} + +EFI_STATUS +EfiConvertInternalPointer ( + IN OUT VOID *Address + ) +/*++ + +Routine Description: + + Call EfiConvertPointer() to convert internal pointer. + +Arguments: + + Address - A pointer to a pointer that is to be fixed to be the value needed + for the new virtual address mappings being applied. + +Returns: + + Status code + +--*/ +{ + return EfiConvertPointer (0x0, Address); +} + +EFI_STATUS +EfiConvertList ( + IN UINTN DebugDisposition, + IN OUT LIST_ENTRY *ListHead + ) +/*++ + +Routine Description: + + Conver the standard Lib double linked list to a virtual mapping. + +Arguments: + + DebugDisposition - Argument to EfiConvertPointer (EFI 1.0 API) + + ListHead - Head of linked list to convert + +Returns: + + EFI_SUCCESS + +--*/ +{ + LIST_ENTRY *Link; + LIST_ENTRY *NextLink; + + // + // Convert all the ForwardLink & BackLink pointers in the list + // + Link = ListHead; + do { + NextLink = Link->ForwardLink; + + EfiConvertPointer ( + Link->ForwardLink == ListHead ? DebugDisposition : 0, + (VOID **) &Link->ForwardLink + ); + + EfiConvertPointer ( + Link->BackLink == ListHead ? DebugDisposition : 0, + (VOID **) &Link->BackLink + ); + + Link = NextLink; + } while (Link != ListHead); + return EFI_SUCCESS; +} + + +/** + Change the runtime addressing mode of EFI firmware from physical to virtual. + + @param MemoryMapSize The size in bytes of VirtualMap. + @param DescriptorSize The size in bytes of an entry in the VirtualMap. + @param DescriptorVersion The version of the structure entries in VirtualMap. + @param VirtualMap An array of memory descriptors which contain new virtual + address mapping information for all runtime ranges. Type + EFI_MEMORY_DESCRIPTOR is defined in the + GetMemoryMap() function description. + + @retval EFI_SUCCESS The virtual address map has been applied. + @retval EFI_UNSUPPORTED EFI firmware is not at runtime, or the EFI firmware is already in + virtual address mapped mode. + @retval EFI_INVALID_PARAMETER DescriptorSize or DescriptorVersion is + invalid. + @retval EFI_NO_MAPPING A virtual address was not supplied for a range in the memory + map that requires a mapping. + @retval EFI_NOT_FOUND A virtual address was supplied for an address that is not found + in the memory map. +**/ +EFI_STATUS +EFIAPI +EfiSetVirtualAddressMap ( + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize, + IN UINT32 DescriptorVersion, + IN CONST EFI_MEMORY_DESCRIPTOR *VirtualMap + ) +{ + return mRT->SetVirtualAddressMap ( + MemoryMapSize, + DescriptorSize, + DescriptorVersion, + (EFI_MEMORY_DESCRIPTOR *) VirtualMap + ); +} + + +EFI_STATUS +EfiUpdateCapsule ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ) +{ +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + return mRT->UpdateCapsule ( + CapsuleHeaderArray, + CapsuleCount, + ScatterGatherList + ); +#else + return EFI_UNSUPPORTED; +#endif +} + +EFI_STATUS +EfiQueryCapsuleCapabilities ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaximumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ) +{ +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + return mRT->QueryCapsuleCapabilities ( + CapsuleHeaderArray, + CapsuleCount, + MaximumCapsuleSize, + ResetType + ); +#else + return EFI_UNSUPPORTED; +#endif +} + + +EFI_STATUS +EfiQueryVariableInfo ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ) +{ +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + return mRT->QueryVariableInfo ( + Attributes, + MaximumVariableStorageSize, + RemainingVariableStorageSize, + MaximumVariableSize + ); +#else + return EFI_UNSUPPORTED; +#endif +} diff --git a/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/EdkDxeRuntimeDriverLib.mbd b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/EdkDxeRuntimeDriverLib.mbd new file mode 100644 index 0000000000..72edffb8ba --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/EdkDxeRuntimeDriverLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkDxeRuntimeDriverLib + b1ee6c28-54aa-4d17-b705-3e28ccb27b2e + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-31 13:13 + + diff --git a/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/EdkDxeRuntimeDriverLib.msa b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/EdkDxeRuntimeDriverLib.msa new file mode 100644 index 0000000000..4d9183e32e --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/EdkDxeRuntimeDriverLib.msa @@ -0,0 +1,69 @@ + + + + + EdkDxeRuntimeDriverLib + DXE_DRIVER + LIBRARY + b1ee6c28-54aa-4d17-b705-3e28ccb27b2e + EDK_RELEASE_VERSION 0x00020000 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-31 13:13 + + + DxeRuntimeDriverLib + UefiLib + BaseLib + DebugLib + UefiBootServicesTableLib + EdkDxeSalLib + + + + Common\RuntimeLib.c + Common\RuntimeService.c + + + Common\RuntimeLib.c + Common\RuntimeService.c + + + Ipf\RuntimeLib.c + Ipf\RuntimeService.c + + + + MdePkg + EdkModulePkg + + + ExtendedSalBootService + + + + RuntimeDriverLibConstruct + RuntimeDriverLibDeconstruct + + + diff --git a/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Ipf/RuntimeLib.c b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Ipf/RuntimeLib.c new file mode 100644 index 0000000000..a4eeb33838 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Ipf/RuntimeLib.c @@ -0,0 +1,284 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RuntimeLib.c + +Abstract: + + Light weight lib to support Tiano drivers. + +--*/ + +#include +#include + +// +// Driver Lib Module Globals +// + +STATIC EFI_EVENT mRuntimeNotifyEvent; +STATIC EFI_EVENT mEfiVirtualNotifyEvent; + +STATIC EFI_PLABEL mPlabel; +STATIC EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *mEsalBootService; + +EFI_RUNTIME_SERVICES *mRT = NULL; + +STATIC +VOID +EFIAPI +RuntimeDriverExitBootServices ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Set AtRuntime flag as TRUE after ExitBootServices + +Arguments: + + Event - The Event that is being processed + + Context - Event Context + +Returns: + + None + +--*/ +{ + EFI_EVENT_NOTIFY ChildNotifyEventHandler; + UINTN Index; + + for (Index = 0; _gDriverExitBootServicesEvent[Index] != NULL; Index++) { + ChildNotifyEventHandler = _gDriverExitBootServicesEvent[Index]; + ChildNotifyEventHandler (Event, NULL); + } +} + +STATIC +VOID +EFIAPI +RuntimeLibVirtualNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Fixup internal data so that EFI can be call in virtual mode. + Call the passed in Child Notify event and convert any pointers in + lib to virtual mode. + +Arguments: + + Event - The Event that is being processed + + Context - Event Context + +Returns: + + None + +--*/ +{ + UINTN Index; + EFI_EVENT_NOTIFY ChildNotifyEventHandler; + + for (Index = 0; _gDriverSetVirtualAddressMapEvent[Index] != NULL; Index++) { + ChildNotifyEventHandler = _gDriverSetVirtualAddressMapEvent[Index]; + ChildNotifyEventHandler (Event, NULL); + } + + mRT->ConvertPointer (0x0, (VOID **) &mPlabel.EntryPoint); + mRT->ConvertPointer (EFI_IPF_GP_POINTER, (VOID **) &mPlabel.GP); + + SetEsalVirtualEntryPoint (mPlabel.EntryPoint, mPlabel.GP); + + // + // Clear out BootService globals + // + gBS = NULL; + gST = NULL; + mRT = NULL; +} + +EFI_STATUS +RuntimeDriverLibConstruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Intialize runtime Driver Lib if it has not yet been initialized. + +Arguments: + + ImageHandle - The firmware allocated handle for the EFI image. + + SystemTable - A pointer to the EFI System Table. + + GoVirtualChildEvent - Caller can register a virtual notification event. + +Returns: + + EFI_STATUS always returns EFI_SUCCESS except EFI_ALREADY_STARTED if already started. + +--*/ +{ + EFI_PLABEL *Plabel; + EFI_STATUS Status; + + mRT = SystemTable->RuntimeServices; + + // + // The protocol contains a function pointer, which is an indirect procedure call. + // An indirect procedure call goes through a plabel, and pointer to a function is + // a pointer to a plabel. To implement indirect procedure calls that can work in + // both physical and virtual mode, two plabels are required (one physical and one + // virtual). So lets grap the physical PLABEL for the EsalEntryPoint and store it + // away. We cache it in a module global, so we can register the vitrual version. + // + Status = gBS->LocateProtocol (&gEfiExtendedSalBootServiceProtocolGuid, NULL, &mEsalBootService); + ASSERT_EFI_ERROR (Status); + + Plabel = (EFI_PLABEL *) (UINTN) mEsalBootService->ExtendedSalProc; + + mPlabel.EntryPoint = Plabel->EntryPoint; + mPlabel.GP = Plabel->GP; + + SetEsalPhysicalEntryPoint (mPlabel.EntryPoint, mPlabel.GP); + + // + // Register our ExitBootServices () notify function + // + + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES, + EFI_TPL_NOTIFY, + RuntimeDriverExitBootServices, + NULL, + &mRuntimeNotifyEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Register SetVirtualAddressMap () notify function + // + + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + EFI_TPL_NOTIFY, + RuntimeLibVirtualNotifyEvent, + NULL, + mEfiVirtualNotifyEvent + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +EFI_STATUS +RuntimeDriverLibDeconstruct ( + VOID + ) +/*++ + +Routine Description: + + This routine will free some resources which have been allocated in + EfiInitializeRuntimeDriverLib(). If a runtime driver exits with an error, + it must call this routine to free the allocated resource before the exiting. + +Arguments: + + None + +Returns: + + EFI_SUCCESS - Shotdown the Runtime Driver Lib successfully + EFI_UNSUPPORTED - Runtime Driver lib was not initialized at all + +--*/ +{ + EFI_STATUS Status; + + // + // Close our ExitBootServices () notify function + // + Status = gBS->CloseEvent (mRuntimeNotifyEvent); + ASSERT_EFI_ERROR (Status); + + // + // Close SetVirtualAddressMap () notify function + // + Status = gBS->CloseEvent (mEfiVirtualNotifyEvent); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +BOOLEAN +EfiAtRuntime ( + VOID + ) +/*++ + +Routine Description: + Return TRUE if ExitBootService () has been called + +Arguments: + NONE + +Returns: + TRUE - If ExitBootService () has been called + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID; + SAL_RETURN_REGS ReturnReg; + + ReturnReg = EfiCallEsalService (&Guid, IsEfiRuntime, 0, 0, 0, 0, 0, 0, 0); + + return (BOOLEAN) (ReturnReg.r9 == 1); +} + +BOOLEAN +EfiGoneVirtual ( + VOID + ) +/*++ + +Routine Description: + Return TRUE if SetVirtualAddressMap () has been called + +Arguments: + NONE + +Returns: + TRUE - If SetVirtualAddressMap () has been called + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID; + SAL_RETURN_REGS ReturnReg; + + ReturnReg = EfiCallEsalService (&Guid, IsVirtual, 0, 0, 0, 0, 0, 0, 0); + + return (BOOLEAN) (ReturnReg.r9 == 1); +} diff --git a/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Ipf/RuntimeService.c b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Ipf/RuntimeService.c new file mode 100644 index 0000000000..bc7a31841b --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/Ipf/RuntimeService.c @@ -0,0 +1,516 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RuntimeService.c + +Abstract: + + Light weight lib to support Tiano drivers. + +--*/ + +#include + +VOID +EfiResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData + ) +/*++ + +Routine Description: + + Resets the entire platform. + +Arguments: + + ResetType - The type of reset to perform. + ResetStatus - The status code for the reset. + DataSize - The size, in bytes, of ResetData. + ResetData - A data buffer that includes a Null-terminated Unicode string, optionally + followed by additional binary data. + +Returns: + + None + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_RESET_SERVICES_PROTOCOL_GUID; + + EfiCallEsalService ( + &Guid, + ResetSystem, + (UINT64) ResetType, + (UINT64) ResetStatus, + (UINT64) DataSize, + (UINT64) ResetData, + 0, + 0, + 0 + ); +} + + +// +// The following functions hide the mRT local global from the call to +// runtime service in the EFI system table. +// +EFI_STATUS +EfiGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ) +/*++ + +Routine Description: + + Returns the current time and date information, and the time-keeping + capabilities of the hardware platform. + +Arguments: + + Time - A pointer to storage to receive a snapshot of the current time. + Capabilities - An optional pointer to a buffer to receive the real time clock device¡¯s + capabilities. + +Returns: + + Status code + +--*/ +{ + SAL_RETURN_REGS ReturnReg; + EFI_GUID Guid = EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID; + + ReturnReg = EfiCallEsalService (&Guid, GetTime, (UINT64) Time, (UINT64) Capabilities, 0, 0, 0, 0, 0); + return ReturnReg.Status; +} + +EFI_STATUS +EfiSetTime ( + IN EFI_TIME *Time + ) +/*++ + +Routine Description: + + Sets the current local time and date information. + +Arguments: + + Time - A pointer to the current time. + +Returns: + + Status code + +--*/ +{ + SAL_RETURN_REGS ReturnReg; + + EFI_GUID Guid = EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID; + + ReturnReg = EfiCallEsalService (&Guid, SetTime, (UINT64) Time, 0, 0, 0, 0, 0, 0); + return ReturnReg.Status; +} + +EFI_STATUS +EfiGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +/*++ + +Routine Description: + + Returns the current wakeup alarm clock setting. + +Arguments: + + Enabled - Indicates if the alarm is currently enabled or disabled. + Pending - Indicates if the alarm signal is pending and requires acknowledgement. + Time - The current alarm setting. + +Returns: + + Status code + +--*/ +{ + SAL_RETURN_REGS ReturnReg; + + EFI_GUID Guid = EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID; + + ReturnReg = EfiCallEsalService (&Guid, GetWakeupTime, (UINT64) Enabled, (UINT64) Pending, (UINT64) Time, 0, 0, 0, 0); + return ReturnReg.Status; +} + +EFI_STATUS +EfiSetWakeupTime ( + IN BOOLEAN Enable, + IN EFI_TIME *Time + ) +/*++ + +Routine Description: + + Sets the system wakeup alarm clock time. + +Arguments: + + Enable - Enable or disable the wakeup alarm. + Time - If Enable is TRUE, the time to set the wakeup alarm for. + If Enable is FALSE, then this parameter is optional, and may be NULL. + +Returns: + + Status code + +--*/ +{ + SAL_RETURN_REGS ReturnReg; + + EFI_GUID Guid = EFI_EXTENDED_SAL_RTC_SERVICES_PROTOCOL_GUID; + + ReturnReg = EfiCallEsalService (&Guid, SetWakeupTime, (UINT64) Enable, (UINT64) Time, 0, 0, 0, 0, 0); + return ReturnReg.Status; +} + +EFI_STATUS +EfiGetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +/*++ + +Routine Description: + + Returns the value of a variable. + +Arguments: + + VariableName - A Null-terminated Unicode string that is the name of the + vendor¡¯s variable. + VendorGuid - A unique identifier for the vendor. + Attributes - If not NULL, a pointer to the memory location to return the + attributes bitmask for the variable. + DataSize - On input, the size in bytes of the return Data buffer. + On output the size of data returned in Data. + Data - The buffer to return the contents of the variable. + +Returns: + + Status code + +--*/ +{ + SAL_RETURN_REGS ReturnReg; + EFI_GUID Guid = EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID; + + ReturnReg = EfiCallEsalService ( + &Guid, + EsalGetVariable, + (UINT64) VariableName, + (UINT64) VendorGuid, + (UINT64) Attributes, + (UINT64) DataSize, + (UINT64) Data, + 0, + 0 + ); + return (EFI_STATUS) ReturnReg.Status; +} + +EFI_STATUS +EfiGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +/*++ + +Routine Description: + + Enumerates the current variable names. + +Arguments: + + VariableNameSize - The size of the VariableName buffer. + VariableName - On input, supplies the last VariableName that was returned + by GetNextVariableName(). + On output, returns the Nullterminated Unicode string of the + current variable. + VendorGuid - On input, supplies the last VendorGuid that was returned by + GetNextVariableName(). + On output, returns the VendorGuid of the current variable. + +Returns: + + Status code + +--*/ +{ + SAL_RETURN_REGS ReturnReg; + EFI_GUID Guid = EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID; + + ReturnReg = EfiCallEsalService ( + &Guid, + EsalGetNextVariableName, + (UINT64) VariableNameSize, + (UINT64) VariableName, + (UINT64) VendorGuid, + 0, + 0, + 0, + 0 + ); + return (EFI_STATUS) ReturnReg.Status; +} + +EFI_STATUS +EfiSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +/*++ + +Routine Description: + + Sets the value of a variable. + +Arguments: + + VariableName - A Null-terminated Unicode string that is the name of the + vendor¡¯s variable. + VendorGuid - A unique identifier for the vendor. + Attributes - Attributes bitmask to set for the variable. + DataSize - The size in bytes of the Data buffer. + Data - The contents for the variable. + +Returns: + + Status code + +--*/ +{ + SAL_RETURN_REGS ReturnReg; + EFI_GUID Guid = EFI_EXTENDED_SAL_VARIABLE_SERVICES_PROTOCOL_GUID; + + ReturnReg = EfiCallEsalService ( + &Guid, + EsalSetVariable, + (UINT64) VariableName, + (UINT64) VendorGuid, + (UINT64) Attributes, + (UINT64) DataSize, + (UINT64) Data, + 0, + 0 + ); + return (EFI_STATUS) ReturnReg.Status; +} + +EFI_STATUS +EfiGetNextHighMonotonicCount ( + OUT UINT32 *HighCount + ) +/*++ + +Routine Description: + + Returns the next high 32 bits of the platform¡¯s monotonic counter. + +Arguments: + + HighCount - Pointer to returned value. + +Returns: + + Status code + +--*/ +{ + SAL_RETURN_REGS ReturnReg; + + EFI_GUID Guid = EFI_EXTENDED_SAL_MTC_SERVICES_PROTOCOL_GUID; + + ReturnReg = EfiCallEsalService (&Guid, GetNextHighMonotonicCount, (UINT64) HighCount, 0, 0, 0, 0, 0, 0); + return (EFI_STATUS) ReturnReg.Status; +} + +EFI_STATUS +EfiConvertPointer ( + IN UINTN DebugDisposition, + IN OUT VOID *Address + ) +/*++ + +Routine Description: + + Determines the new virtual address that is to be used on subsequent memory accesses. + +Arguments: + + DebugDisposition - Supplies type information for the pointer being converted. + Address - A pointer to a pointer that is to be fixed to be the value needed + for the new virtual address mappings being applied. + +Returns: + + Status code + +--*/ +{ + return mRT->ConvertPointer (DebugDisposition, Address); +} + +EFI_STATUS +EfiConvertList ( + IN UINTN DebugDisposition, + IN OUT LIST_ENTRY *ListHead + ) +/*++ + +Routine Description: + + Conver the standard Lib double linked list to a virtual mapping. + +Arguments: + + DebugDisposition - Argument to EfiConvertPointer (EFI 1.0 API) + + ListHead - Head of linked list to convert + +Returns: + + EFI_SUCCESS + +--*/ +{ + LIST_ENTRY *Link; + LIST_ENTRY *NextLink; + + // + // Convert all the ForwardLink & BackLink pointers in the list + // + Link = ListHead; + do { + NextLink = Link->ForwardLink; + + EfiConvertPointer ( + Link->ForwardLink == ListHead ? DebugDisposition : 0, + (VOID **) &Link->ForwardLink + ); + + EfiConvertPointer ( + Link->BackLink == ListHead ? DebugDisposition : 0, + (VOID **) &Link->BackLink + ); + + Link = NextLink; + } while (Link != ListHead); + return EFI_SUCCESS; +} + + +/** + Change the runtime addressing mode of EFI firmware from physical to virtual. + + @param MemoryMapSize The size in bytes of VirtualMap. + @param DescriptorSize The size in bytes of an entry in the VirtualMap. + @param DescriptorVersion The version of the structure entries in VirtualMap. + @param VirtualMap An array of memory descriptors which contain new virtual + address mapping information for all runtime ranges. Type + EFI_MEMORY_DESCRIPTOR is defined in the + GetMemoryMap() function description. + + @retval EFI_SUCCESS The virtual address map has been applied. + @retval EFI_UNSUPPORTED EFI firmware is not at runtime, or the EFI firmware is already in + virtual address mapped mode. + @retval EFI_INVALID_PARAMETER DescriptorSize or DescriptorVersion is + invalid. + @retval EFI_NO_MAPPING A virtual address was not supplied for a range in the memory + map that requires a mapping. + @retval EFI_NOT_FOUND A virtual address was supplied for an address that is not found + in the memory map. +**/ +EFI_STATUS +EFIAPI +EfiSetVirtualAddressMap ( + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize, + IN UINT32 DescriptorVersion, + IN CONST EFI_MEMORY_DESCRIPTOR *VirtualMap + ) +{ + SAL_RETURN_REGS ReturnReg; + EFI_GUID Guid = EFI_EXTENDED_SAL_VIRTUAL_SERVICES_PROTOCOL_GUID; + + ReturnReg = EfiCallEsalService ( + &Guid, + SetVirtualAddress, + (UINT64) MemoryMapSize, + (UINT64) DescriptorSize, + (UINT64) DescriptorVersion, + (UINT64) VirtualMap, + 0, + 0, + 0 + ); + + return ReturnReg.Status; +} + + +EFI_STATUS +EfiUpdateCapsule ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EfiQueryCapsuleCapabilities ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaximumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ) +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EfiQueryVariableInfo ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ) +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/RuntimeLibInternal.h b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/RuntimeLibInternal.h new file mode 100644 index 0000000000..82494fd7a0 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/RuntimeLibInternal.h @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RuntimeLibInternal.h + +Abstract: + +--*/ + +#ifndef __RUNTIMELIBINTERNAL_H__ +#define __RUNTIMELIBINTERNAL_H__ + +EFI_STATUS +EfiConvertInternalPointer ( + IN OUT VOID *Address + ); + +extern EFI_RUNTIME_SERVICES *mRT; + +#endif //__RUNTIMELIBINTERNAL_H__ diff --git a/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/build.xml b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/build.xml new file mode 100644 index 0000000000..e43f7080a9 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeRuntimeDriverLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkDxeSalLib/EdkDxeSalLib.mbd b/EdkModulePkg/Library/EdkDxeSalLib/EdkDxeSalLib.mbd new file mode 100644 index 0000000000..dababd27ad --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeSalLib/EdkDxeSalLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkDxeSalLib + 61999c3c-72a5-4506-a4ff-4271d18a1d14 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-31 13:13 + + diff --git a/EdkModulePkg/Library/EdkDxeSalLib/EdkDxeSalLib.msa b/EdkModulePkg/Library/EdkDxeSalLib/EdkDxeSalLib.msa new file mode 100644 index 0000000000..d9fc5830ed --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeSalLib/EdkDxeSalLib.msa @@ -0,0 +1,58 @@ + + + + + EdkDxeSalLib + DXE_DRIVER + LIBRARY + 61999c3c-72a5-4506-a4ff-4271d18a1d14 + EDK_RELEASE_VERSION 0x00020000 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-31 13:13 + + + EdkDxeSalLib + DebugLib + UefiBootServicesTableLib + + + + Ipf/EsalServiceLib.c + Ipf/AsmEsalServiceLib.s + Ipf/AsmIpfCpuCache.s + + + + MdePkg + EdkModulePkg + + + ExtendedSalBootService + + + + DxeSalLibConstruct + + + diff --git a/EdkModulePkg/Library/EdkDxeSalLib/Ipf/AsmEsalServiceLib.s b/EdkModulePkg/Library/EdkDxeSalLib/Ipf/AsmEsalServiceLib.s new file mode 100644 index 0000000000..2b040b710b --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeSalLib/Ipf/AsmEsalServiceLib.s @@ -0,0 +1,149 @@ +//++ +// Copyright (c) 2006, 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. +// +// Module Name: +// +// EsalLib.s +// +// Abstract: +// +// +// Revision History: +// +//-- + +.file "EsalLib.s" + +#include "IpfMacro.i" + +// +// Exports +// +.global GetEsalEntryPoint + + +//----------------------------------------------------------------------------- +//++ +// GetEsalEntryPoint +// +// Return Esal global and PSR register. +// +// On Entry : +// +// +// Return Value: +// r8 = EFI_SAL_SUCCESS +// r9 = Physical Plabel +// r10 = Virtual Plabel +// r11 = psr +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- +PROCEDURE_ENTRY (GetEsalEntryPoint) + + NESTED_SETUP (0,8,0,0) + +EsalCalcStart: + mov r8 = ip;; + add r8 = (EsalEntryPoint - EsalCalcStart), r8;; + mov r9 = r8;; + add r10 = 0x10, r8;; + mov r11 = psr;; + mov r8 = r0;; + + NESTED_RETURN + +PROCEDURE_EXIT (GetEsalEntryPoint) + + + + + +//----------------------------------------------------------------------------- +//++ +// SetEsalPhysicalEntryPoint +// +// Set the dispatcher entry point +// +// On Entry: +// in0 = Physical address of Esal Dispatcher +// in1 = Physical GP +// +// Return Value: +// r8 = EFI_SAL_SUCCESS +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- +PROCEDURE_ENTRY (SetEsalPhysicalEntryPoint) + + NESTED_SETUP (2,8,0,0) + +EsalCalcStart1: + mov r8 = ip;; + add r8 = (EsalEntryPoint - EsalCalcStart1), r8;; + st8 [r8] = in0;; + add r8 = 0x08, r8;; + st8 [r8] = in1;; + mov r8 = r0;; + + NESTED_RETURN + +PROCEDURE_EXIT (SetEsalPhysicalEntryPoint) + + +//----------------------------------------------------------------------------- +//++ +// SetEsalVirtualEntryPoint +// +// Register physical address of Esal globals. +// +// On Entry : +// in0 = Virtual address of Esal Dispatcher +// in1 = Virtual GP +// +// Return Value: +// r8 = EFI_SAL_ERROR +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- +PROCEDURE_ENTRY (SetEsalVirtualEntryPoint) + + NESTED_SETUP (2,8,0,0) + +EsalCalcStart2: + mov r8 = ip;; + add r8 = (EsalEntryPoint - EsalCalcStart2), r8;; + add r8 = 0x10, r8;; + st8 [r8] = in0;; + add r8 = 0x08, r8;; + st8 [r8] = in1;; + mov r8 = r0;; + + NESTED_RETURN + +PROCEDURE_EXIT (SetEsalVirtualEntryPoint) + + + + +.align 32 +EsalEntryPoint: + data8 0 // Physical Entry + data8 0 // GP + data8 0 // Virtual Entry + data8 0 // GP + + diff --git a/EdkModulePkg/Library/EdkDxeSalLib/Ipf/AsmIpfCpuCache.s b/EdkModulePkg/Library/EdkDxeSalLib/Ipf/AsmIpfCpuCache.s new file mode 100644 index 0000000000..c4505051fa --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeSalLib/Ipf/AsmIpfCpuCache.s @@ -0,0 +1,88 @@ +//++ +// Copyright (c) 2006, 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. +// +// Module Name: +// +// IpfCpuCache.s +// +// Abstract: +// +// Contains Misc assembly procedures to support IPF CPU AP. +// +// Revision History: +// +//-- + +.file "IpfCpuCache.s" + +#include "IpfMacro.i" +#include "IpfDefines.h" + +//----------------------------------------------------------------------------- +//++ +// Flush Cache +// +// Arguments : + +// Input = in0 = Starting Address to Flush. +// Input = in1 = Length in bytes. +// Input = b0 = return branch register. +// On Entry : +// +// Return Value: +// +// VOID +// SalFlushCache ( +// IN UINT64 BaseToFlush, +// IN UINT64 LengthToFlush +// ); +// +//-- +//--------------------------------------------------------------------------- +PROCEDURE_ENTRY (SalFlushCache) + + NESTED_SETUP (5,8,0,0) + + mov loc2 = ar.lc + + mov loc3 = in0 // Start address. + mov loc4 = in1;; // Length in bytes. + + cmp.eq p6,p7 = loc4, r0;; // If Length is zero then don't flush any cache + (p6) br.spnt.many DoneFlushingC;; + + add loc4 = loc4,loc3 + mov loc5 = 1;; + sub loc4 = loc4, loc5 ;; // the End address to flush + + dep loc3 = r0,loc3,0,5 + dep loc4 = r0,loc4,0,5;; + shr loc3 = loc3,5 + shr loc4 = loc4,5;; // 32 byte cache line + + sub loc4 = loc4,loc3;; // total flush count, It should be add 1 but + // the br.cloop will first execute one time + mov loc3 = in0 + mov loc5 = 32 + mov ar.lc = loc4;; + +StillFlushingC: + fc loc3;; + sync.i;; + srlz.i;; + add loc3 = loc5,loc3;; + br.cloop.sptk.few StillFlushingC;; + +DoneFlushingC: + mov ar.lc = loc2 + NESTED_RETURN + +PROCEDURE_EXIT (SalFlushCache) + diff --git a/EdkModulePkg/Library/EdkDxeSalLib/Ipf/EsalServiceLib.c b/EdkModulePkg/Library/EdkDxeSalLib/Ipf/EsalServiceLib.c new file mode 100644 index 0000000000..d258b98cab --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeSalLib/Ipf/EsalServiceLib.c @@ -0,0 +1,199 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EsalServiceLib.c + +Abstract: + +--*/ + +#include + + +STATIC EXTENDED_SAL_BOOT_SERVICE_PROTOCOL *mEsalBootService; + +EFI_STATUS +EFIAPI +DxeSalLibConstruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiExtendedSalBootServiceProtocolGuid, NULL, &mEsalBootService); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +EFI_STATUS +RegisterEsalFunction ( + IN UINT64 FunctionId, + IN EFI_GUID *ClassGuid, + IN SAL_INTERNAL_EXTENDED_SAL_PROC Function, + IN VOID *ModuleGlobal + ) +/*++ + +Routine Description: + + Register ESAL Class Function and it's asociated global. + This function is boot service only! + +Arguments: + FunctionId - ID of function to register + ClassGuid - GUID of function class + Function - Function to register under ClassGuid/FunctionId pair + ModuleGlobal - Module global for Function. + +Returns: + EFI_SUCCESS - If ClassGuid/FunctionId Function was registered. + +--*/ +{ + return mEsalBootService->AddExtendedSalProc ( + mEsalBootService, + ClassGuid, + FunctionId, + Function, + ModuleGlobal + ); +} + +EFI_STATUS +RegisterEsalClass ( + IN EFI_GUID *ClassGuid, + IN VOID *ModuleGlobal, + ... + ) +/*++ + +Routine Description: + + Register ESAL Class and it's asociated global. + This function is boot service only! + +Arguments: + ClassGuid - GUID of function class + ModuleGlobal - Module global for Function. + ... - SAL_INTERNAL_EXTENDED_SAL_PROC and FunctionId pairs. NULL + indicates the end of the list. + +Returns: + EFI_SUCCESS - All members of ClassGuid registered + +--*/ +{ + VA_LIST Args; + EFI_STATUS Status; + SAL_INTERNAL_EXTENDED_SAL_PROC Function; + UINT64 FunctionId; + EFI_HANDLE NewHandle; + + VA_START (Args, ModuleGlobal); + + Status = EFI_SUCCESS; + while (!EFI_ERROR (Status)) { + Function = (SAL_INTERNAL_EXTENDED_SAL_PROC) VA_ARG (Args, SAL_INTERNAL_EXTENDED_SAL_PROC); + if (Function == NULL) { + break; + } + + FunctionId = VA_ARG (Args, UINT64); + + Status = RegisterEsalFunction (FunctionId, ClassGuid, Function, ModuleGlobal); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + NewHandle = NULL; + return gBS->InstallProtocolInterface ( + &NewHandle, + ClassGuid, + EFI_NATIVE_INTERFACE, + NULL + ); +} + +SAL_RETURN_REGS +EfiCallEsalService ( + IN EFI_GUID *ClassGuid, + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8 + ) +/*++ + +Routine Description: + + Call module that is not linked direclty to this module. This code is IP + relative and hides the binding issues of virtual or physical calling. The + function that gets dispatched has extra arguments that include the registered + module global and a boolean flag to indicate if the system is in virutal mode. + +Arguments: + ClassGuid - GUID of function + FunctionId - Function in ClassGuid to call + Arg2 - Argument 2 ClassGuid/FunctionId defined + Arg3 - Argument 3 ClassGuid/FunctionId defined + Arg4 - Argument 4 ClassGuid/FunctionId defined + Arg5 - Argument 5 ClassGuid/FunctionId defined + Arg6 - Argument 6 ClassGuid/FunctionId defined + Arg7 - Argument 7 ClassGuid/FunctionId defined + Arg8 - Argument 8 ClassGuid/FunctionId defined + +Returns: + Status of ClassGuid/FuncitonId + +--*/ +{ + SAL_RETURN_REGS ReturnReg; + SAL_EXTENDED_SAL_PROC EsalProc; + + ReturnReg = GetEsalEntryPoint (); + if (ReturnReg.Status != EFI_SAL_SUCCESS) { + return ReturnReg; + } + + if (ReturnReg.r11 & PSR_IT_MASK) { + // + // Virtual mode plabel to entry point + // + EsalProc = (SAL_EXTENDED_SAL_PROC) ReturnReg.r10; + } else { + // + // Physical mode plabel to entry point + // + EsalProc = (SAL_EXTENDED_SAL_PROC) ReturnReg.r9; + } + + return EsalProc ( + ClassGuid, + FunctionId, + Arg2, + Arg3, + Arg4, + Arg5, + Arg6, + Arg7, + Arg8 + ); +} diff --git a/EdkModulePkg/Library/EdkDxeSalLib/build.xml b/EdkModulePkg/Library/EdkDxeSalLib/build.xml new file mode 100644 index 0000000000..e4f1e3ea02 --- /dev/null +++ b/EdkModulePkg/Library/EdkDxeSalLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.mbd b/EdkModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.mbd new file mode 100644 index 0000000000..a5ee7cb19d --- /dev/null +++ b/EdkModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkFvbServiceLib + bd4d540e-04b0-4b10-8fd5-4a7bb533cf67 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-31 13:13 + + diff --git a/EdkModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.msa b/EdkModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.msa new file mode 100644 index 0000000000..c20d5ee16d --- /dev/null +++ b/EdkModulePkg/Library/EdkFvbServiceLib/EdkFvbServiceLib.msa @@ -0,0 +1,74 @@ + + + + + EdkFvbServiceLib + DXE_DRIVER + LIBRARY + bd4d540e-04b0-4b10-8fd5-4a7bb533cf67 + EDK_RELEASE_VERSION 0x00020000 + FvbService Library for UEFI drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-31 13:13 + + + EdkFvbServiceLib + UefiLib + PrintLib + BaseLib + MemoryAllocationLib + DebugLib + BaseMemoryLib + DxeRuntimeDriverLib + UefiBootServicesTableLib + EdkDxeSalLib + + + + Ia32/Fvb.c + + + x64/Fvb.c + + + Ipf/Fvb.c + + + + MdePkg + EdkModulePkg + + + FirmwareVolumeBlock + FvbExtension + FirmwareVolumeBlock + + + + FvbLibInitialize + + + FvbVirtualAddressChangeNotifyEvent + + + diff --git a/EdkModulePkg/Library/EdkFvbServiceLib/Fvb.h b/EdkModulePkg/Library/EdkFvbServiceLib/Fvb.h new file mode 100644 index 0000000000..c6d1eb7193 --- /dev/null +++ b/EdkModulePkg/Library/EdkFvbServiceLib/Fvb.h @@ -0,0 +1,31 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Fvb.h + +Abstract: + +--*/ + +#ifndef __FVB_H__ +#define __FVB_H__ + +#define MAX_FVB_COUNT 16 + +typedef struct { + EFI_HANDLE Handle; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FVB_EXTENSION_PROTOCOL *FvbExtension; +} FVB_ENTRY; + +#endif diff --git a/EdkModulePkg/Library/EdkFvbServiceLib/Ia32/Fvb.c b/EdkModulePkg/Library/EdkFvbServiceLib/Ia32/Fvb.c new file mode 100644 index 0000000000..222fb9bd4d --- /dev/null +++ b/EdkModulePkg/Library/EdkFvbServiceLib/Ia32/Fvb.c @@ -0,0 +1,534 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Fvb.c + +Abstract: + + Firmware Volume Block Protocol Runtime Abstraction + + mFvbEntry is an array of Handle Fvb pairs. The Fvb Lib Instance matches the + index in the mFvbEntry array. This should be the same sequence as the FVB's + were described in the HOB. We have to remember the handle so we can tell if + the protocol has been reinstalled and it needs updateing. + + If you are using any of these lib functions.you must first call FvbInitialize (). + +Key: + FVB - Firmware Volume Block + +--*/ + +#include "Fvb.h" + +// +// Lib will ASSERT if more FVB devices than this are added to the system. +// +STATIC FVB_ENTRY *mFvbEntry; +STATIC EFI_EVENT mFvbRegistration; +STATIC BOOLEAN mEfiFvbInitialized = FALSE; +STATIC UINTN mFvbCount; + +STATIC +VOID +EFIAPI +FvbNotificationEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is + reinstalled. + +Arguments: + + Event - The Event that is being processed + + Context - Event Context + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HANDLE Handle; + UINTN Index; + UINTN UpdateIndex; + + while (TRUE) { + BufferSize = sizeof (Handle); + Status = gBS->LocateHandle ( + ByRegisterNotify, + &gEfiFirmwareVolumeBlockProtocolGuid, + mFvbRegistration, + &BufferSize, + &Handle + ); + if (EFI_ERROR (Status)) { + // + // Exit Path of While Loop.... + // + break; + } + + UpdateIndex = MAX_FVB_COUNT; + for (Index = 0; Index < mFvbCount; Index++) { + if (mFvbEntry[Index].Handle == Handle) { + // + // If the handle is already in the table just update the protocol + // + UpdateIndex = Index; + break; + } + } + + if (UpdateIndex == MAX_FVB_COUNT) { + // + // Use the next free slot for a new entry + // + UpdateIndex = mFvbCount++;; + mFvbEntry[UpdateIndex].Handle = Handle; + } + // + // The array does not have enough entries + // + ASSERT (UpdateIndex < MAX_FVB_COUNT); + + // + // Get the interface pointer and if it's ours, skip it + // + Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **) &mFvbEntry[UpdateIndex].Fvb); + ASSERT_EFI_ERROR (Status); + + Status = gBS->HandleProtocol (Handle, &gEfiFvbExtensionProtocolGuid, (VOID **) &mFvbEntry[UpdateIndex].FvbExtension); + if (Status != EFI_SUCCESS) { + mFvbEntry[UpdateIndex].FvbExtension = NULL; + } + } +} + +VOID +EFIAPI +FvbVirtualAddressChangeNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Convert all pointers in mFvbEntry after ExitBootServices. + +Arguments: + + Event - The Event that is being processed + + Context - Event Context + +Returns: + + None + +--*/ +{ + UINTN Index; + if (mFvbEntry != NULL) { + for (Index = 0; Index < MAX_FVB_COUNT; Index++) { + if (NULL != mFvbEntry[Index].Fvb) { + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetBlockSize); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetPhysicalAddress); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetVolumeAttributes); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->SetVolumeAttributes); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Read); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Write); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->EraseBlocks); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb); + } + + if (NULL != mFvbEntry[Index].FvbExtension) { + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension->EraseFvbCustomBlock); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension); + } + } + + EfiConvertPointer (0x0, (VOID **) &mFvbEntry); + } +} + +EFI_STATUS +EFIAPI +FvbLibInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Initialize globals and register Fvb Protocol notification function. + +Arguments: + None + +Returns: + EFI_SUCCESS + +--*/ +{ + UINTN Status; + mFvbCount = 0; + + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + (UINTN) sizeof (FVB_ENTRY) * MAX_FVB_COUNT, + (VOID *) &mFvbEntry + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (mFvbEntry, sizeof (FVB_ENTRY) * MAX_FVB_COUNT); + + EfiCreateProtocolNotifyEvent ( + &gEfiFirmwareVolumeBlockProtocolGuid, + EFI_TPL_CALLBACK, + FvbNotificationEvent, + NULL, + &mFvbRegistration + ); + + // + // Register SetVirtualAddressMap () notify function + // + // Status = gBS->CreateEvent ( + // EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + // EFI_TPL_NOTIFY, + // EfiRuntimeLibFvbVirtualNotifyEvent, + // NULL, + // &mEfiFvbVirtualNotifyEvent + // ); + // ASSERT_EFI_ERROR (Status); + // + + // + // Register SetVirtualAddressMap () notify function + // + + ASSERT_EFI_ERROR (Status); + + mEfiFvbInitialized = TRUE; + + return EFI_SUCCESS; +} +// +// The following functions wrap Fvb protocol in the Runtime Lib functions. +// The Instance translates into Fvb instance. The Fvb order defined by HOBs and +// thus the sequence of FVB protocol addition define Instance. +// +// EfiFvbInitialize () must be called before any of the following functions +// must be called. +// + +EFI_STATUS +EfiFvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Reads specified number of bytes into a buffer from the specified block + +Arguments: + Instance - The FV instance to be read from + Lba - The logical block address to be read from + Offset - Offset into the block at which to begin reading + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes read + Buffer - Pointer to a caller allocated buffer that will be + used to hold the data read + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->Read (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer); +} + +EFI_STATUS +EfiFvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Writes specified number of bytes from the input buffer to the block + +Arguments: + Instance - The FV instance to be written to + Lba - The starting logical block index to write to + Offset - Offset into the block at which to begin writing + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes actually written + Buffer - Pointer to a caller allocated buffer that contains + the source for the write + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->Write (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer); +} + +EFI_STATUS +EfiFvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba + ) +/*++ + +Routine Description: + Erases and initializes a firmware volume block + +Arguments: + Instance - The FV instance to be erased + Lba - The logical block index to be erased + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->EraseBlocks (mFvbEntry[Instance].Fvb, Lba, -1); +} + +EFI_STATUS +EfiFvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + +Arguments: + Instance - The FV instance whose attributes is going to be + returned + Attributes - Output buffer which contains attributes + +Returns: + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetVolumeAttributes (mFvbEntry[Instance].Fvb, Attributes); +} + +EFI_STATUS +EfiFvbSetVolumeAttributes ( + IN UINTN Instance, + IN EFI_FVB_ATTRIBUTES Attributes + ) +/*++ + +Routine Description: + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + +Arguments: + Instance - The FV instance whose attributes is going to be + modified + Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES + containing the desired firmware volume settings. + On successful return, it contains the new settings + of the firmware volume + +Returns: + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->SetVolumeAttributes (mFvbEntry[Instance].Fvb, &Attributes); +} + +EFI_STATUS +EfiFvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *BaseAddress + ) +/*++ + +Routine Description: + Retrieves the physical address of a memory mapped FV + +Arguments: + Instance - The FV instance whose base address is going to be + returned + BaseAddress - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS + that on successful return, contains the base address + of the firmware volume. + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetPhysicalAddress (mFvbEntry[Instance].Fvb, BaseAddress); +} + +EFI_STATUS +EfiFvbGetBlockSize ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +/*++ + +Routine Description: + Retrieve the size of a logical block + +Arguments: + Instance - The FV instance whose block size is going to be + returned + Lba - Indicates which block to return the size for. + BlockSize - A pointer to a caller allocated UINTN in which + the size of the block is returned + NumOfBlocks - a pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + +Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetBlockSize (mFvbEntry[Instance].Fvb, Lba, BlockSize, NumOfBlocks); +} + +EFI_STATUS +EfiFvbEraseCustomBlockRange ( + IN UINTN Instance, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba + ) +/*++ + +Routine Description: + Erases and initializes a specified range of a firmware volume + +Arguments: + Instance - The FV instance to be erased + StartLba - The starting logical block index to be erased + OffsetStartLba - Offset into the starting block at which to + begin erasing + LastLba - The last logical block index to be erased + OffsetLastLba - Offset into the last block at which to end erasing + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + + EFI_UNSUPPORTED - not support + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (!(mFvbEntry[Instance].FvbExtension)) { + return EFI_UNSUPPORTED; + } + + if (!(mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock)) { + return EFI_UNSUPPORTED; + } + + return mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock ( + mFvbEntry[Instance].FvbExtension, + StartLba, + OffsetStartLba, + LastLba, + OffsetLastLba + ); +} diff --git a/EdkModulePkg/Library/EdkFvbServiceLib/Ipf/Fvb.c b/EdkModulePkg/Library/EdkFvbServiceLib/Ipf/Fvb.c new file mode 100644 index 0000000000..58ad6f538c --- /dev/null +++ b/EdkModulePkg/Library/EdkFvbServiceLib/Ipf/Fvb.c @@ -0,0 +1,324 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Fvb.c + +Abstract: + + Light weight lib to support Tiano Firmware Volume Block + protocol abstraction at runtime. + + All these functions convert EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID + class function to the Runtime Lib function. There is a 1 to 1 mapping. + + If you are using any of these lib functions.you must first call FvbInitialize (). + +--*/ + +EFI_STATUS +FvbLibInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Initialize globals and register Fvb Protocol notification function. + +Arguments: + None + +Returns: + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; +} +// +// The following functions wrap Fvb protocol in the Runtime Lib functions. +// The Instance translates into Fvb instance. The Fvb order defined by HOBs and +// thus the sequence of FVB protocol addition define Instance. +// +// EfiFvbInitialize () must be called before any of the following functions +// must be called. +// +EFI_STATUS +EfiFvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Reads specified number of bytes into a buffer from the specified block + +Arguments: + Instance - The FV instance to be read from + Lba - The logical block address to be read from + Offset - Offset into the block at which to begin reading + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes read + Buffer - Pointer to a caller allocated buffer that will be + used to hold the data read + +Returns: + Status code + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID; + + return EfiCallEsalService (&Guid, Read, Instance, Lba, Offset, (UINT64) NumBytes, (UINT64) Buffer, 0, 0).Status; +} + +EFI_STATUS +EfiFvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Writes specified number of bytes from the input buffer to the block + +Arguments: + Instance - The FV instance to be written to + Lba - The starting logical block index to write to + Offset - Offset into the block at which to begin writing + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes actually written + Buffer - Pointer to a caller allocated buffer that contains + the source for the write + +Returns: + Status code + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID; + + return EfiCallEsalService (&Guid, Write, Instance, Lba, Offset, (UINT64) NumBytes, (UINT64) Buffer, 0, 0).Status; +} + +EFI_STATUS +EfiFvbEraseBlock ( + IN UINTN Instance, + IN UINTN Lba + ) +/*++ + +Routine Description: + Erases and initializes a firmware volume block + +Arguments: + Instance - The FV instance to be erased + Lba - The logical block index to be erased + +Returns: + Status code + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID; + + return EfiCallEsalService (&Guid, EraseBlock, Instance, Lba, 0, 0, 0, 0, 0).Status; +} + +EFI_STATUS +EfiFvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + +Arguments: + Instance - The FV instance whose attributes is going to be + returned + Attributes - Output buffer which contains attributes + +Returns: + Status code + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID; + + return EfiCallEsalService (&Guid, SetVolumeAttributes, Instance, (UINT64) Attributes, 0, 0, 0, 0, 0).Status; +} + +EFI_STATUS +EfiFvbSetVolumeAttributes ( + IN UINTN Instance, + IN EFI_FVB_ATTRIBUTES Attributes + ) +/*++ + +Routine Description: + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + +Arguments: + Instance - The FV instance whose attributes is going to be + modified + Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES + containing the desired firmware volume settings. + On successful return, it contains the new settings + of the firmware volume + +Returns: + Status code + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID; + + return EfiCallEsalService (&Guid, SetVolumeAttributes, Instance, (UINT64) Attributes, 0, 0, 0, 0, 0).Status; +} + +EFI_STATUS +EfiFvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *BaseAddress + ) +/*++ + +Routine Description: + Retrieves the physical address of a memory mapped FV + +Arguments: + Instance - The FV instance whose base address is going to be + returned + BaseAddress - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS + that on successful return, contains the base address + of the firmware volume. + +Returns: + Status code + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID; + + return EfiCallEsalService (&Guid, GetPhysicalAddress, Instance, (UINT64) BaseAddress, 0, 0, 0, 0, 0).Status; +} + +EFI_STATUS +EfiFvbGetBlockSize ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +/*++ + +Routine Description: + Retrieve the size of a logical block + +Arguments: + Instance - The FV instance whose block size is going to be + returned + Lba - Indicates which block to return the size for. + BlockSize - A pointer to a caller allocated UINTN in which + the size of the block is returned + NumOfBlocks - a pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + +Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID; + + return EfiCallEsalService ( + &Guid, + GetBlockSize, + Instance, + Lba, + (UINT64) BlockSize, + (UINT64) NumOfBlocks, + 0, + 0, + 0 + ).Status; +} + +EFI_STATUS +EfiFvbEraseCustomBlockRange ( + IN UINTN Instance, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba + ) +/*++ + +Routine Description: + Erases and initializes a specified range of a firmware volume + +Arguments: + Instance - The FV instance to be erased + StartLba - The starting logical block index to be erased + OffsetStartLba - Offset into the starting block at which to + begin erasing + LastLba - The last logical block index to be erased + OffsetLastLba - Offset into the last block at which to end erasing + +Returns: + Status code + +--*/ +{ + EFI_GUID Guid = EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID; + + return EfiCallEsalService ( + &Guid, + EraseCustomBlockRange, + Instance, + StartLba, + OffsetStartLba, + LastLba, + OffsetLastLba, + 0, + 0 + ).Status; +} + + +/** + BugBug: Can't turn this off in the current MSA so we need a stub +**/ +VOID +EFIAPI +FvbVirtualAddressChangeNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ +} diff --git a/EdkModulePkg/Library/EdkFvbServiceLib/build.xml b/EdkModulePkg/Library/EdkFvbServiceLib/build.xml new file mode 100644 index 0000000000..ebbb303b70 --- /dev/null +++ b/EdkModulePkg/Library/EdkFvbServiceLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkFvbServiceLib/x64/Fvb.c b/EdkModulePkg/Library/EdkFvbServiceLib/x64/Fvb.c new file mode 100644 index 0000000000..76ddfa80d4 --- /dev/null +++ b/EdkModulePkg/Library/EdkFvbServiceLib/x64/Fvb.c @@ -0,0 +1,536 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Fvb.c + +Abstract: + + Firmware Volume Block Protocol Runtime Abstraction + + mFvbEntry is an array of Handle Fvb pairs. The Fvb Lib Instance matches the + index in the mFvbEntry array. This should be the same sequence as the FVB's + were described in the HOB. We have to remember the handle so we can tell if + the protocol has been reinstalled and it needs updateing. + + If you are using any of these lib functions.you must first call FvbInitialize (). + +Key: + FVB - Firmware Volume Block + +--*/ + +#include "Fvb.h" + +// +// Lib will ASSERT if more FVB devices than this are added to the system. +// +STATIC FVB_ENTRY *mFvbEntry; +STATIC EFI_EVENT mFvbVirtualNotifyEvent; +STATIC EFI_EVENT mFvbRegistration; +STATIC EFI_EVENT mEfiFvbVirtualNotifyEvent; +STATIC BOOLEAN mEfiFvbInitialized = FALSE; +STATIC UINTN mFvbCount; + +STATIC +VOID +EFIAPI +FvbNotificationEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + Update mFvbEntry. Add new entry, or update existing entry if Fvb protocol is + reinstalled. + +Arguments: + + Event - The Event that is being processed + + Context - Event Context + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HANDLE Handle; + UINTN Index; + UINTN UpdateIndex; + + while (TRUE) { + BufferSize = sizeof (Handle); + Status = gBS->LocateHandle ( + ByRegisterNotify, + &gEfiFirmwareVolumeBlockProtocolGuid, + mFvbRegistration, + &BufferSize, + &Handle + ); + if (EFI_ERROR (Status)) { + // + // Exit Path of While Loop.... + // + break; + } + + UpdateIndex = MAX_FVB_COUNT; + for (Index = 0; Index < mFvbCount; Index++) { + if (mFvbEntry[Index].Handle == Handle) { + // + // If the handle is already in the table just update the protocol + // + UpdateIndex = Index; + break; + } + } + + if (UpdateIndex == MAX_FVB_COUNT) { + // + // Use the next free slot for a new entry + // + UpdateIndex = mFvbCount++;; + mFvbEntry[UpdateIndex].Handle = Handle; + } + // + // The array does not have enough entries + // + ASSERT (UpdateIndex < MAX_FVB_COUNT); + + // + // Get the interface pointer and if it's ours, skip it + // + Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, &mFvbEntry[UpdateIndex].Fvb); + ASSERT_EFI_ERROR (Status); + + Status = gBS->HandleProtocol (Handle, &gEfiFvbExtensionProtocolGuid, &mFvbEntry[UpdateIndex].FvbExtension); + if (Status != EFI_SUCCESS) { + mFvbEntry[UpdateIndex].FvbExtension = NULL; + } + } +} + +VOID +EFIAPI +FvbVirtualAddressChangeNotifyEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Convert all pointers in mFvbEntry after ExitBootServices. + +Arguments: + + Event - The Event that is being processed + + Context - Event Context + +Returns: + + None + +--*/ +{ + UINTN Index; + if (mFvbEntry != NULL) { + for (Index = 0; Index < MAX_FVB_COUNT; Index++) { + if (NULL != mFvbEntry[Index].Fvb) { + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetBlockSize); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetPhysicalAddress); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->GetVolumeAttributes); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->SetVolumeAttributes); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Read); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->Write); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb->EraseBlocks); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].Fvb); + } + + if (NULL != mFvbEntry[Index].FvbExtension) { + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension->EraseFvbCustomBlock); + EfiConvertPointer (0x0, (VOID **) &mFvbEntry[Index].FvbExtension); + } + } + + EfiConvertPointer (0x0, (VOID **) &mFvbEntry); + } +} + +EFI_STATUS +EFIAPI +FvbLibInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Initialize globals and register Fvb Protocol notification function. + +Arguments: + None + +Returns: + EFI_SUCCESS + +--*/ +{ + UINTN Status; + mFvbCount = 0; + + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + (UINTN) sizeof (FVB_ENTRY) * MAX_FVB_COUNT, + (VOID *) &mFvbEntry + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + ZeroMem (mFvbEntry, sizeof (FVB_ENTRY) * MAX_FVB_COUNT); + + EfiCreateProtocolNotifyEvent ( + &gEfiFirmwareVolumeBlockProtocolGuid, + EFI_TPL_CALLBACK, + FvbNotificationEvent, + NULL, + &mFvbRegistration + ); + + // + // Register SetVirtualAddressMap () notify function + // + // Status = gBS->CreateEvent ( + // EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE, + // EFI_TPL_NOTIFY, + // EfiRuntimeLibFvbVirtualNotifyEvent, + // NULL, + // &mEfiFvbVirtualNotifyEvent + // ); + // ASSERT_EFI_ERROR (Status); + // + + // + // Register SetVirtualAddressMap () notify function + // + + ASSERT_EFI_ERROR (Status); + + mEfiFvbInitialized = TRUE; + + return EFI_SUCCESS; +} +// +// The following functions wrap Fvb protocol in the Runtime Lib functions. +// The Instance translates into Fvb instance. The Fvb order defined by HOBs and +// thus the sequence of FVB protocol addition define Instance. +// +// EfiFvbInitialize () must be called before any of the following functions +// must be called. +// + +EFI_STATUS +EfiFvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Reads specified number of bytes into a buffer from the specified block + +Arguments: + Instance - The FV instance to be read from + Lba - The logical block address to be read from + Offset - Offset into the block at which to begin reading + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes read + Buffer - Pointer to a caller allocated buffer that will be + used to hold the data read + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->Read (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer); +} + +EFI_STATUS +EfiFvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + Writes specified number of bytes from the input buffer to the block + +Arguments: + Instance - The FV instance to be written to + Lba - The starting logical block index to write to + Offset - Offset into the block at which to begin writing + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes actually written + Buffer - Pointer to a caller allocated buffer that contains + the source for the write + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->Write (mFvbEntry[Instance].Fvb, Lba, Offset, NumBytes, Buffer); +} + +EFI_STATUS +EfiFvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba + ) +/*++ + +Routine Description: + Erases and initializes a firmware volume block + +Arguments: + Instance - The FV instance to be erased + Lba - The logical block index to be erased + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->EraseBlocks (mFvbEntry[Instance].Fvb, Lba, -1); +} + +EFI_STATUS +EfiFvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + +Arguments: + Instance - The FV instance whose attributes is going to be + returned + Attributes - Output buffer which contains attributes + +Returns: + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetVolumeAttributes (mFvbEntry[Instance].Fvb, Attributes); +} + +EFI_STATUS +EfiFvbSetVolumeAttributes ( + IN UINTN Instance, + IN EFI_FVB_ATTRIBUTES Attributes + ) +/*++ + +Routine Description: + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + +Arguments: + Instance - The FV instance whose attributes is going to be + modified + Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES + containing the desired firmware volume settings. + On successful return, it contains the new settings + of the firmware volume + +Returns: + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->SetVolumeAttributes (mFvbEntry[Instance].Fvb, &Attributes); +} + +EFI_STATUS +EfiFvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *BaseAddress + ) +/*++ + +Routine Description: + Retrieves the physical address of a memory mapped FV + +Arguments: + Instance - The FV instance whose base address is going to be + returned + BaseAddress - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS + that on successful return, contains the base address + of the firmware volume. + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetPhysicalAddress (mFvbEntry[Instance].Fvb, BaseAddress); +} + +EFI_STATUS +EfiFvbGetBlockSize ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +/*++ + +Routine Description: + Retrieve the size of a logical block + +Arguments: + Instance - The FV instance whose block size is going to be + returned + Lba - Indicates which block to return the size for. + BlockSize - A pointer to a caller allocated UINTN in which + the size of the block is returned + NumOfBlocks - a pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + +Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + + EFI_INVALID_PARAMETER - invalid parameter + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + return mFvbEntry[Instance].Fvb->GetBlockSize (mFvbEntry[Instance].Fvb, Lba, BlockSize, NumOfBlocks); +} + +EFI_STATUS +EfiFvbEraseCustomBlockRange ( + IN UINTN Instance, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba + ) +/*++ + +Routine Description: + Erases and initializes a specified range of a firmware volume + +Arguments: + Instance - The FV instance to be erased + StartLba - The starting logical block index to be erased + OffsetStartLba - Offset into the starting block at which to + begin erasing + LastLba - The last logical block index to be erased + OffsetLastLba - Offset into the last block at which to end erasing + +Returns: + + Status code + + EFI_INVALID_PARAMETER - invalid parameter + + EFI_UNSUPPORTED - not support + +--*/ +{ + if (Instance >= mFvbCount) { + return EFI_INVALID_PARAMETER; + } + + if (!(mFvbEntry[Instance].FvbExtension)) { + return EFI_UNSUPPORTED; + } + + if (!(mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock)) { + return EFI_UNSUPPORTED; + } + + return mFvbEntry[Instance].FvbExtension->EraseFvbCustomBlock ( + mFvbEntry[Instance].FvbExtension, + StartLba, + OffsetStartLba, + LastLba, + OffsetLastLba + ); +} diff --git a/EdkModulePkg/Library/EdkGraphicsLib/EdkGraphicsLib.mbd b/EdkModulePkg/Library/EdkGraphicsLib/EdkGraphicsLib.mbd new file mode 100644 index 0000000000..4758d6b192 --- /dev/null +++ b/EdkModulePkg/Library/EdkGraphicsLib/EdkGraphicsLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkGraphicsLib + 08c1a0e4-1208-47f8-a2c5-f42eabee653a + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + diff --git a/EdkModulePkg/Library/EdkGraphicsLib/EdkGraphicsLib.msa b/EdkModulePkg/Library/EdkGraphicsLib/EdkGraphicsLib.msa new file mode 100644 index 0000000000..03b4f51026 --- /dev/null +++ b/EdkModulePkg/Library/EdkGraphicsLib/EdkGraphicsLib.msa @@ -0,0 +1,61 @@ + + + + + EdkGraphicsLib + DXE_DRIVER + LIBRARY + 08c1a0e4-1208-47f8-a2c5-f42eabee653a + 0 + Graphics Library for UEFI drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + EdkGraphicsLib + UefiLib + PrintLib + BaseLib + MemoryAllocationLib + UefiBootServicesTableLib + + + Graphics.c + + + MdePkg + EdkModulePkg + + + OEMBadging + FirmwareVolume + ConsoleControl + UgaDraw + SimpleTextOut + + + + Bmp + + + diff --git a/EdkModulePkg/Library/EdkGraphicsLib/Graphics.c b/EdkModulePkg/Library/EdkGraphicsLib/Graphics.c new file mode 100644 index 0000000000..01c612abd3 --- /dev/null +++ b/EdkModulePkg/Library/EdkGraphicsLib/Graphics.c @@ -0,0 +1,780 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Graphics.c + +Abstract: + + Support for Basic Graphics operations. + + BugBug: Currently *.BMP files are supported. This will be replaced + when Tiano graphics format is supported. + +--*/ + +EFI_STATUS +GetGraphicsBitMapFromFV ( + IN EFI_GUID *FileNameGuid, + OUT VOID **Image, + OUT UINTN *ImageSize + ) +/*++ + +Routine Description: + + Return the graphics image file named FileNameGuid into Image and return it's + size in ImageSize. All Firmware Volumes (FV) in the system are searched for the + file name. + +Arguments: + + FileNameGuid - File Name of graphics file in the FV(s). + + Image - Pointer to pointer to return graphics image. If NULL, a + buffer will be allocated. + + ImageSize - Size of the graphics Image in bytes. Zero if no image found. + + +Returns: + + EFI_SUCCESS - Image and ImageSize are valid. + EFI_BUFFER_TOO_SMALL - Image not big enough. ImageSize has required size + EFI_NOT_FOUND - FileNameGuid not found + +--*/ +{ + EFI_STATUS Status; + UINTN FvProtocolCount; + EFI_HANDLE *FvHandles; + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + UINTN Index; + UINT32 AuthenticationStatus; + + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeProtocolGuid, + NULL, + &FvProtocolCount, + &FvHandles + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + for (Index = 0; Index < FvProtocolCount; Index++) { + Status = gBS->HandleProtocol ( + FvHandles[Index], + &gEfiFirmwareVolumeProtocolGuid, + (VOID **) &Fv + ); + + // + // Assuming Image and ImageSize are correct on input. + // + Status = Fv->ReadSection ( + Fv, + &gEfiDefaultBmpLogoGuid, + EFI_SECTION_RAW, + 0, + Image, + ImageSize, + &AuthenticationStatus + ); + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } else if (Status == EFI_BUFFER_TOO_SMALL) { + // + // ImageSize updated to needed size so return + // + return EFI_BUFFER_TOO_SMALL; + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +ConvertBmpToUgaBlt ( + IN VOID *BmpImage, + IN UINTN BmpImageSize, + IN OUT VOID **UgaBlt, + IN OUT UINTN *UgaBltSize, + OUT UINTN *PixelHeight, + OUT UINTN *PixelWidth + ) +/*++ + +Routine Description: + + Convert a *.BMP graphics image to a UGA blt buffer. If a NULL UgaBlt buffer + is passed in a UgaBlt buffer will be allocated by this routine. If a UgaBlt + buffer is passed in it will be used if it is big enough. + +Arguments: + + BmpImage - Pointer to BMP file + + BmpImageSize - Number of bytes in BmpImage + + UgaBlt - Buffer containing UGA version of BmpImage. + + UgaBltSize - Size of UgaBlt in bytes. + + PixelHeight - Height of UgaBlt/BmpImage in pixels + + PixelWidth - Width of UgaBlt/BmpImage in pixels + + +Returns: + + EFI_SUCCESS - UgaBlt and UgaBltSize are returned. + EFI_UNSUPPORTED - BmpImage is not a valid *.BMP image + EFI_BUFFER_TOO_SMALL - The passed in UgaBlt buffer is not big enough. + UgaBltSize will contain the required size. + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + +--*/ +{ + UINT8 *Image; + UINT8 *ImageHeader; + BMP_IMAGE_HEADER *BmpHeader; + BMP_COLOR_MAP *BmpColorMap; + EFI_UGA_PIXEL *BltBuffer; + EFI_UGA_PIXEL *Blt; + UINTN BltBufferSize; + UINTN Index; + UINTN Height; + UINTN Width; + UINTN ImageIndex; + + BmpHeader = (BMP_IMAGE_HEADER *) BmpImage; + if (BmpHeader->CharB != 'B' || BmpHeader->CharM != 'M') { + return EFI_UNSUPPORTED; + } + + if (BmpHeader->CompressionType != 0) { + return EFI_UNSUPPORTED; + } + + // + // Calculate Color Map offset in the image. + // + Image = BmpImage; + BmpColorMap = (BMP_COLOR_MAP *) (Image + sizeof (BMP_IMAGE_HEADER)); + + // + // Calculate graphics image data address in the image + // + Image = ((UINT8 *) BmpImage) + BmpHeader->ImageOffset; + ImageHeader = Image; + + BltBufferSize = BmpHeader->PixelWidth * BmpHeader->PixelHeight * sizeof (EFI_UGA_PIXEL); + if (*UgaBlt == NULL) { + *UgaBltSize = BltBufferSize; + *UgaBlt = AllocatePool (*UgaBltSize); + if (*UgaBlt == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } else { + if (*UgaBltSize < BltBufferSize) { + *UgaBltSize = BltBufferSize; + return EFI_BUFFER_TOO_SMALL; + } + } + + *PixelWidth = BmpHeader->PixelWidth; + *PixelHeight = BmpHeader->PixelHeight; + + // + // Convert image from BMP to Blt buffer format + // + BltBuffer = *UgaBlt; + for (Height = 0; Height < BmpHeader->PixelHeight; Height++) { + Blt = &BltBuffer[(BmpHeader->PixelHeight - Height - 1) * BmpHeader->PixelWidth]; + for (Width = 0; Width < BmpHeader->PixelWidth; Width++, Image++, Blt++) { + switch (BmpHeader->BitPerPixel) { + case 1: + // + // Convert 1bit BMP to 24-bit color + // + for (Index = 0; Index < 8 && Width < BmpHeader->PixelWidth; Index++) { + Blt->Red = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Red; + Blt->Green = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Green; + Blt->Blue = BmpColorMap[((*Image) >> (7 - Index)) & 0x1].Blue; + Blt++; + Width++; + } + + Blt --; + Width --; + break; + + case 4: + // + // Convert BMP Palette to 24-bit color + // + Index = (*Image) >> 4; + Blt->Red = BmpColorMap[Index].Red; + Blt->Green = BmpColorMap[Index].Green; + Blt->Blue = BmpColorMap[Index].Blue; + if (Width < (BmpHeader->PixelWidth - 1)) { + Blt++; + Width++; + Index = (*Image) & 0x0f; + Blt->Red = BmpColorMap[Index].Red; + Blt->Green = BmpColorMap[Index].Green; + Blt->Blue = BmpColorMap[Index].Blue; + } + break; + + case 8: + // + // Convert BMP Palette to 24-bit color + // + Blt->Red = BmpColorMap[*Image].Red; + Blt->Green = BmpColorMap[*Image].Green; + Blt->Blue = BmpColorMap[*Image].Blue; + break; + + case 24: + Blt->Blue = *Image++; + Blt->Green = *Image++; + Blt->Red = *Image; + break; + + default: + return EFI_UNSUPPORTED; + break; + }; + + } + + ImageIndex = (UINTN) (Image - ImageHeader); + if ((ImageIndex % 4) != 0) { + // + // Bmp Image starts each row on a 32-bit boundary! + // + Image = Image + (4 - (ImageIndex % 4)); + } + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +LockKeyboards ( + IN CHAR16 *Password + ) +/*++ + +Routine Description: + Use Console Control Protocol to lock the Console In Spliter virtual handle. + This is the ConInHandle and ConIn handle in the EFI system table. All key + presses will be ignored until the Password is typed in. The only way to + disable the password is to type it in to a ConIn device. + +Arguments: + Password - Password used to lock ConIn device + + +Returns: + + EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo + displayed. + EFI_UNSUPPORTED - Logo not found + +--*/ +{ + EFI_STATUS Status; + EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl; + + Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = ConsoleControl->LockStdIn (ConsoleControl, Password); + return Status; +} + + +EFI_STATUS +EnableQuietBoot ( + IN EFI_GUID *LogoFile + ) +/*++ + +Routine Description: + + Use Console Control to turn off UGA based Simple Text Out consoles from going + to the UGA device. Put up LogoFile on every UGA device that is a console + +Arguments: + + LogoFile - File name of logo to display on the center of the screen. + + +Returns: + + EFI_SUCCESS - ConsoleControl has been flipped to graphics and logo + displayed. + EFI_UNSUPPORTED - Logo not found + +--*/ +{ + EFI_STATUS Status; + EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_OEM_BADGING_PROTOCOL *Badging; + UINT32 SizeOfX; + UINT32 SizeOfY; + UINT32 ColorDepth; + UINT32 RefreshRate; + INTN DestX; + INTN DestY; + + UINT8 *ImageData; + UINTN ImageSize; + EFI_UGA_PIXEL *UgaBlt; + UINTN UgaBltSize; + + UINT32 Instance; + EFI_BADGING_FORMAT Format; + EFI_BADGING_DISPLAY_ATTRIBUTE Attribute; + UINTN CoordinateX; + UINTN CoordinateY; + UINTN Height; + UINTN Width; + + Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = gBS->HandleProtocol (gST->ConsoleOutHandle, &gEfiUgaDrawProtocolGuid, (VOID **) &UgaDraw); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Badging = NULL; + Status = gBS->LocateProtocol (&gEfiOEMBadgingProtocolGuid, NULL, (VOID **) &Badging); + + ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenGraphics); + + Status = UgaDraw->GetMode (UgaDraw, &SizeOfX, &SizeOfY, &ColorDepth, &RefreshRate); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Instance = 0; + while (1) { + ImageData = NULL; + ImageSize = 0; + + if (Badging != NULL) { + Status = Badging->GetImage ( + Badging, + &Instance, + &Format, + &ImageData, + &ImageSize, + &Attribute, + &CoordinateX, + &CoordinateY + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Currently only support BMP format + // + if (Format != EfiBadgingFormatBMP) { + gBS->FreePool (ImageData); + continue; + } + } else { + Status = GetGraphicsBitMapFromFV (LogoFile, (VOID **) &ImageData, &ImageSize); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + CoordinateX = 0; + CoordinateY = 0; + Attribute = EfiBadgingDisplayAttributeCenter; + } + + UgaBlt = NULL; + Status = ConvertBmpToUgaBlt ( + ImageData, + ImageSize, + (VOID **) &UgaBlt, + &UgaBltSize, + &Height, + &Width + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (ImageData); + continue; + } + + switch (Attribute) { + case EfiBadgingDisplayAttributeLeftTop: + DestX = CoordinateX; + DestY = CoordinateY; + break; + + case EfiBadgingDisplayAttributeCenterTop: + DestX = (SizeOfX - Width) / 2; + DestY = CoordinateY; + break; + + case EfiBadgingDisplayAttributeRightTop: + DestX = (SizeOfX - Width - CoordinateX); + DestY = CoordinateY;; + break; + + case EfiBadgingDisplayAttributeCenterRight: + DestX = (SizeOfX - Width - CoordinateX); + DestY = (SizeOfY - Height) / 2; + break; + + case EfiBadgingDisplayAttributeRightBottom: + DestX = (SizeOfX - Width - CoordinateX); + DestY = (SizeOfY - Height - CoordinateY); + break; + + case EfiBadgingDisplayAttributeCenterBottom: + DestX = (SizeOfX - Width) / 2; + DestY = (SizeOfY - Height - CoordinateY); + break; + + case EfiBadgingDisplayAttributeLeftBottom: + DestX = CoordinateX; + DestY = (SizeOfY - Height - CoordinateY); + break; + + case EfiBadgingDisplayAttributeCenterLeft: + DestX = CoordinateX; + DestY = (SizeOfY - Height) / 2; + break; + + case EfiBadgingDisplayAttributeCenter: + DestX = (SizeOfX - Width) / 2; + DestY = (SizeOfY - Height) / 2; + break; + + default: + DestX = CoordinateX; + DestY = CoordinateY; + break; + } + + if ((DestX >= 0) && (DestY >= 0)) { + Status = UgaDraw->Blt ( + UgaDraw, + UgaBlt, + EfiUgaBltBufferToVideo, + 0, + 0, + (UINTN) DestX, + (UINTN) DestY, + Width, + Height, + Width * sizeof (EFI_UGA_PIXEL) + ); + } + + gBS->FreePool (ImageData); + gBS->FreePool (UgaBlt); + + if (Badging == NULL) { + break; + } + } + + return Status; +} + + +EFI_STATUS +DisableQuietBoot ( + VOID + ) +/*++ + +Routine Description: + + Use Console Control to turn on UGA based Simple Text Out consoles. The UGA + Simple Text Out screens will now be synced up with all non UGA output devices + +Arguments: + + NONE + +Returns: + + EFI_SUCCESS - UGA devices are back in text mode and synced up. + EFI_UNSUPPORTED - Logo not found + +--*/ +{ + EFI_STATUS Status; + EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl; + + Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, (VOID **) &ConsoleControl); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText); +} + +static EFI_UGA_PIXEL mEfiColors[16] = { + { 0x00, 0x00, 0x00, 0x00 }, + { 0x98, 0x00, 0x00, 0x00 }, + { 0x00, 0x98, 0x00, 0x00 }, + { 0x98, 0x98, 0x00, 0x00 }, + { 0x00, 0x00, 0x98, 0x00 }, + { 0x98, 0x00, 0x98, 0x00 }, + { 0x00, 0x98, 0x98, 0x00 }, + { 0x98, 0x98, 0x98, 0x00 }, + { 0x10, 0x10, 0x10, 0x00 }, + { 0xff, 0x10, 0x10, 0x00 }, + { 0x10, 0xff, 0x10, 0x00 }, + { 0xff, 0xff, 0x10, 0x00 }, + { 0x10, 0x10, 0xff, 0x00 }, + { 0xf0, 0x10, 0xff, 0x00 }, + { 0x10, 0xff, 0xff, 0x00 }, + { 0xff, 0xff, 0xff, 0x00 } +}; + +STATIC +UINTN +_IPrint ( + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw, + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *Sto, + IN UINTN X, + IN UINTN Y, + IN EFI_UGA_PIXEL *Foreground, + IN EFI_UGA_PIXEL *Background, + IN CHAR16 *fmt, + IN VA_LIST args + ) +/*++ + +Routine Description: + + Display string worker for: Print, PrintAt, IPrint, IPrintAt + +Arguments: + + UgaDraw - UGA draw protocol interface + + Sto - Simple text out protocol interface + + X - X coordinate to start printing + + Y - Y coordinate to start printing + + Foreground - Foreground color + + Background - Background color + + fmt - Format string + + args - Print arguments + +Returns: + + EFI_SUCCESS - success + EFI_OUT_OF_RESOURCES - out of resources + +--*/ +{ + VOID *Buffer; + EFI_STATUS Status; + UINT16 GlyphWidth; + UINT32 GlyphStatus; + UINT16 StringIndex; + UINTN Index; + CHAR16 *UnicodeWeight; + EFI_NARROW_GLYPH *Glyph; + EFI_HII_PROTOCOL *Hii; + EFI_UGA_PIXEL *LineBuffer; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; + + GlyphStatus = 0; + + // + // For now, allocate an arbitrarily long buffer + // + Buffer = AllocateZeroPool (0x10000); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + UgaDraw->GetMode (UgaDraw, &HorizontalResolution, &VerticalResolution, &ColorDepth, &RefreshRate); + + LineBuffer = AllocatePool (sizeof (EFI_UGA_PIXEL) * HorizontalResolution * GLYPH_WIDTH * GLYPH_HEIGHT); + if (LineBuffer == NULL) { + gBS->FreePool (Buffer); + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, (VOID **) &Hii); + if (EFI_ERROR (Status)) { + goto Error; + } + + UnicodeVSPrint (Buffer, 0x10000, fmt, args); + + UnicodeWeight = (CHAR16 *) Buffer; + + for (Index = 0; UnicodeWeight[Index] != 0; Index++) { + if (UnicodeWeight[Index] == CHAR_BACKSPACE || + UnicodeWeight[Index] == CHAR_LINEFEED || + UnicodeWeight[Index] == CHAR_CARRIAGE_RETURN) { + UnicodeWeight[Index] = 0; + } + } + + for (Index = 0; Index < StrLen (Buffer); Index++) { + StringIndex = (UINT16) Index; + Status = Hii->GetGlyph (Hii, UnicodeWeight, &StringIndex, (UINT8 **) &Glyph, &GlyphWidth, &GlyphStatus); + if (EFI_ERROR (Status)) { + goto Error; + } + + if (Foreground == NULL || Background == NULL) { + Status = Hii->GlyphToBlt ( + Hii, + (UINT8 *) Glyph, + mEfiColors[Sto->Mode->Attribute & 0x0f], + mEfiColors[Sto->Mode->Attribute >> 4], + StrLen (Buffer), + GlyphWidth, + GLYPH_HEIGHT, + &LineBuffer[Index * GLYPH_WIDTH] + ); + } else { + Status = Hii->GlyphToBlt ( + Hii, + (UINT8 *) Glyph, + *Foreground, + *Background, + StrLen (Buffer), + GlyphWidth, + GLYPH_HEIGHT, + &LineBuffer[Index * GLYPH_WIDTH] + ); + } + } + + // + // Blt a character to the screen + // + Status = UgaDraw->Blt ( + UgaDraw, + LineBuffer, + EfiUgaBltBufferToVideo, + 0, + 0, + X, + Y, + GLYPH_WIDTH * StrLen (Buffer), + GLYPH_HEIGHT, + GLYPH_WIDTH * StrLen (Buffer) * sizeof (EFI_UGA_PIXEL) + ); + +Error: + gBS->FreePool (LineBuffer); + gBS->FreePool (Buffer); + return Status; +} + + +UINTN +PrintXY ( + IN UINTN X, + IN UINTN Y, + IN EFI_UGA_PIXEL *ForeGround, OPTIONAL + IN EFI_UGA_PIXEL *BackGround, OPTIONAL + IN CHAR16 *Fmt, + ... + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to the default console + +Arguments: + + X - X coordinate to start printing + + Y - Y coordinate to start printing + + ForeGround - Foreground color + + BackGround - Background color + + Fmt - Format string + + ... - Print arguments + +Returns: + + Length of string printed to the console + +--*/ +{ + EFI_HANDLE Handle; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *Sto; + EFI_STATUS Status; + VA_LIST Args; + + VA_START (Args, Fmt); + + Handle = gST->ConsoleOutHandle; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &Sto + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + return _IPrint (UgaDraw, Sto, X, Y, ForeGround, BackGround, Fmt, Args); +} diff --git a/EdkModulePkg/Library/EdkGraphicsLib/build.xml b/EdkModulePkg/Library/EdkGraphicsLib/build.xml new file mode 100644 index 0000000000..cccef0efe3 --- /dev/null +++ b/EdkModulePkg/Library/EdkGraphicsLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.mbd b/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.mbd new file mode 100644 index 0000000000..3864ea2a5c --- /dev/null +++ b/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkIfrSupportLib + ea55bada-d488-427b-9d2d-227e0aaa3707 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-31 13:14 + + diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.msa b/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.msa new file mode 100644 index 0000000000..fcf02afb02 --- /dev/null +++ b/EdkModulePkg/Library/EdkIfrSupportLib/EdkIfrSupportLib.msa @@ -0,0 +1,75 @@ + + + + + EdkIfrSupportLib + DXE_DRIVER + LIBRARY + ea55bada-d488-427b-9d2d-227e0aaa3707 + EDK_RELEASE_VERSION 0x00020000 + Graphics Library for UEFI drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-31 13:14 + + + EdkIfrSupportLib + UefiLib + DebugLib + PrintLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + + + IfrCommon.c + IfrOnTheFly.c + IfrOpCodeCreation.c + IfrLibrary.h + IfrVariable.c + + + MdePkg + EdkModulePkg + + + Hii + + + + L"Lang" + 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C} + + + + + GlobalVariable + + + + + IfrLibConstruct + + + diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/IfrCommon.c b/EdkModulePkg/Library/EdkIfrSupportLib/IfrCommon.c new file mode 100644 index 0000000000..6d0a84de5e --- /dev/null +++ b/EdkModulePkg/Library/EdkIfrSupportLib/IfrCommon.c @@ -0,0 +1,995 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + IfrCommon.c + +Abstract: + + Common Library Routines to assist in IFR creation on-the-fly + +Revision History: + +--*/ + +EFI_STATUS +IfrLibConstruct ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +GetCurrentLanguage ( + OUT CHAR16 *Lang + ) +/*++ + +Routine Description: + + Determine what is the current language setting + +Arguments: + + Lang - Pointer of system language + +Returns: + + Status code + +--*/ +{ + EFI_STATUS Status; + UINTN Size; + UINTN Index; + CHAR8 Language[4]; + + // + // Getting the system language and placing it into our Global Data + // + Size = sizeof (Language); + + Status = gRT->GetVariable ( + (CHAR16 *) L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &Size, + Language + ); + + if (EFI_ERROR (Status)) { + AsciiStrCpy (Language, "eng"); + } + + for (Index = 0; Language[Index] != 0; Index++) { + // + // Bitwise AND ascii value with 0xDF yields an uppercase value. + // Sign extend into a unicode value + // + Lang[Index] = (CHAR16) (Language[Index] & 0xDF); + } + + // + // Null-terminate the value + // + Lang[3] = (CHAR16) 0; + + return Status; +} + + +EFI_STATUS +AddString ( + IN VOID *StringBuffer, + IN CHAR16 *Language, + IN CHAR16 *String, + IN OUT STRING_REF *StringToken + ) +/*++ + +Routine Description: + + Add a string to the incoming buffer and return the token and offset data + +Arguments: + + StringBuffer - The incoming buffer + + Language - Currrent language + + String - The string to be added + + StringToken - The index where the string placed + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - String successfully added to the incoming buffer + +--*/ +{ + EFI_HII_STRING_PACK *StringPack; + EFI_HII_STRING_PACK *StringPackBuffer; + VOID *NewBuffer; + RELOFST *PackSource; + RELOFST *PackDestination; + UINT8 *Source; + UINT8 *Destination; + UINTN Index; + BOOLEAN Finished; + + StringPack = (EFI_HII_STRING_PACK *) StringBuffer; + Finished = FALSE; + + // + // Pre-allocate a buffer sufficient for us to work on. + // We will use it as a destination scratch pad to build data on + // and when complete shift the data back to the original buffer + // + NewBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + StringPackBuffer = (EFI_HII_STRING_PACK *) NewBuffer; + + // + // StringPack is terminated with a length 0 entry + // + for (; StringPack->Header.Length != 0;) { + // + // If this stringpack's language is same as CurrentLanguage, use it + // + if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language, 3) == 0) { + // + // We have some data in this string pack, copy the string package up to the string data + // + CopyMem (&StringPackBuffer->Header, &StringPack->Header, sizeof (StringPack)); + + // + // These are references in the structure to tokens, need to increase them by the space occupied by an additional StringPointer + // + StringPackBuffer->LanguageNameString = (UINT16) (StringPackBuffer->LanguageNameString + (UINT16) sizeof (RELOFST)); + StringPackBuffer->PrintableLanguageName = (UINT16) (StringPackBuffer->PrintableLanguageName + (UINT16) sizeof (RELOFST)); + + PackSource = (RELOFST *) (StringPack + 1); + PackDestination = (RELOFST *) (StringPackBuffer + 1); + for (Index = 0; PackSource[Index] != 0x0000; Index++) { + // + // Copy the stringpointers from old to new buffer + // remember that we are adding a string, so the string offsets will all go up by sizeof (RELOFST) + // + PackDestination[Index] = (UINT16) (PackDestination[Index] + sizeof (RELOFST)); + } + + // + // Add a new stringpointer in the new buffer since we are adding a string. Null terminate it + // + PackDestination[Index] = (UINT16)(PackDestination[Index-1] + + StrSize((CHAR16 *)((CHAR8 *)(StringPack) + PackSource[Index-1]))); + PackDestination[Index + 1] = (UINT16) 0; + + // + // Index is the token value for the new string + // + *StringToken = (UINT16) Index; + + // + // Source now points to the beginning of the old buffer strings + // Destination now points to the beginning of the new buffer strings + // + Source = (UINT8 *) &PackSource[Index + 1]; + Destination = (UINT8 *) &PackDestination[Index + 2]; + + // + // This should copy all the strings from the old buffer to the new buffer + // + for (; Index != 0; Index--) { + // + // Copy Source string to destination buffer + // + StrCpy ((CHAR16 *) Destination, (CHAR16 *) Source); + + // + // Adjust the source/destination to the next string location + // + Destination = Destination + StrSize ((CHAR16 *) Source); + Source = Source + StrSize ((CHAR16 *) Source); + } + + // + // This copies the new string to the destination buffer + // + StrCpy ((CHAR16 *) Destination, (CHAR16 *) String); + + // + // Adjust the size of the changed string pack by adding the size of the new string + // along with the size of the additional offset entry for the new string + // + StringPackBuffer->Header.Length = (UINT32) ((UINTN) StringPackBuffer->Header.Length + StrSize (String) + sizeof (RELOFST)); + + // + // Advance the buffers to point to the next spots. + // + StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPackBuffer->Header.Length); + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length); + Finished = TRUE; + continue; + } + // + // This isn't the language of the stringpack we were asked to add a string to + // so we need to copy it to the new buffer. + // + CopyMem (&StringPackBuffer->Header, &StringPack->Header, StringPack->Header.Length); + + // + // Advance the buffers to point to the next spots. + // + StringPackBuffer = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPackBuffer) + StringPack->Header.Length); + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length); + } + + // + // If we didn't copy the new data to a stringpack yet + // + if (!Finished) { + PackDestination = (RELOFST *) (StringPackBuffer + 1); + // + // Pointing to a new string pack location + // + StringPackBuffer->Header.Length = (UINT32) + ( + sizeof (EFI_HII_STRING_PACK) - + sizeof (EFI_STRING) + + sizeof (RELOFST) + + sizeof (RELOFST) + + StrSize (Language) + + StrSize (String) + ); + StringPackBuffer->Header.Type = EFI_HII_STRING; + StringPackBuffer->LanguageNameString = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer); + StringPackBuffer->PrintableLanguageName = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer); + StringPackBuffer->Attributes = 0; + PackDestination[0] = (UINT16) ((UINTN) &PackDestination[3] - (UINTN) StringPackBuffer); + PackDestination[1] = (UINT16) (PackDestination[0] + StrSize (Language)); + PackDestination[2] = (UINT16) 0; + + // + // The first string location will be set to destination. The minimum number of strings + // associated with a stringpack will always be token 0 stored as the languagename (e.g. ENG, SPA, etc) + // and token 1 as the new string being added and and null entry for the stringpointers + // + Destination = (UINT8 *) &PackDestination[3]; + + // + // Copy the language name string to the new buffer + // + StrCpy ((CHAR16 *) Destination, Language); + + // + // Advance the destination to the new empty spot + // + Destination = Destination + StrSize (Language); + + // + // Copy the string to the new buffer + // + StrCpy ((CHAR16 *) Destination, String); + + // + // Since we are starting with a new string pack - we know the new string is token 1 + // + *StringToken = (UINT16) 1; + } + + // + // Zero out the original buffer and copy the updated data in the new buffer to the old buffer + // + ZeroMem (StringBuffer, DEFAULT_STRING_BUFFER_SIZE); + CopyMem (StringBuffer, NewBuffer, DEFAULT_STRING_BUFFER_SIZE); + + // + // Free the newly created buffer since we don't need it anymore + // + gBS->FreePool (NewBuffer); + return EFI_SUCCESS; +} + + +EFI_STATUS +AddOpCode ( + IN VOID *FormBuffer, + IN OUT VOID *OpCodeData + ) +/*++ + +Routine Description: + + Add op-code data to the FormBuffer + +Arguments: + + FormBuffer - Form buffer to be inserted to + + OpCodeData - Op-code data to be inserted + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Op-code data successfully inserted + +--*/ +{ + EFI_HII_PACK_HEADER *NewBuffer; + UINT8 *Source; + UINT8 *Destination; + + // + // Pre-allocate a buffer sufficient for us to work on. + // We will use it as a destination scratch pad to build data on + // and when complete shift the data back to the original buffer + // + NewBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE); + if (NewBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Source = (UINT8 *) FormBuffer; + Destination = (UINT8 *) NewBuffer; + + // + // Copy the IFR Package header to the new buffer + // + CopyMem (Destination, Source, sizeof (EFI_HII_PACK_HEADER)); + + // + // Advance Source and Destination to next op-code + // + Source = Source + sizeof (EFI_HII_PACK_HEADER); + Destination = Destination + sizeof (EFI_HII_PACK_HEADER); + + // + // Copy data to the new buffer until we run into the end_form + // + for (; ((EFI_IFR_OP_HEADER *) Source)->OpCode != EFI_IFR_END_FORM_OP;) { + // + // If the this opcode is an end_form_set we better be creating and endform + // Nonetheless, we will add data before the end_form_set. This also provides + // for interesting behavior in the code we will run, but has no bad side-effects + // since we will possibly do a 0 byte copy in this particular end-case. + // + if (((EFI_IFR_OP_HEADER *) Source)->OpCode == EFI_IFR_END_FORM_SET_OP) { + break; + } + + // + // Copy data to new buffer + // + CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length); + + // + // Adjust Source/Destination to next op-code location + // + Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length; + Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length; + } + + // + // Prior to the end_form is where we insert the new op-code data + // + CopyMem (Destination, OpCodeData, ((EFI_IFR_OP_HEADER *) OpCodeData)->Length); + Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) OpCodeData)->Length; + + NewBuffer->Length = (UINT32) (NewBuffer->Length + (UINT32) (((EFI_IFR_OP_HEADER *) OpCodeData)->Length)); + + // + // Copy end-form data to new buffer + // + CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length); + + // + // Adjust Source/Destination to next op-code location + // + Destination = Destination + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length; + Source = Source + (UINTN) ((EFI_IFR_OP_HEADER *) Source)->Length; + + // + // Copy end-formset data to new buffer + // + CopyMem (Destination, Source, ((EFI_IFR_OP_HEADER *) Source)->Length); + + // + // Zero out the original buffer and copy the updated data in the new buffer to the old buffer + // + ZeroMem (FormBuffer, DEFAULT_FORM_BUFFER_SIZE); + CopyMem (FormBuffer, NewBuffer, DEFAULT_FORM_BUFFER_SIZE); + + // + // Free the newly created buffer since we don't need it anymore + // + gBS->FreePool (NewBuffer); + return EFI_SUCCESS; +} + + +EFI_STATUS +GetHiiInterface ( + OUT EFI_HII_PROTOCOL **Hii + ) +/*++ + +Routine Description: + + Get the HII protocol interface + +Arguments: + + Hii - HII protocol interface + +Returns: + + Status code + +--*/ +{ + EFI_STATUS Status; + + // + // There should only be one HII protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + (VOID **) Hii + ); + + return Status;; +} + + +EFI_STATUS +ExtractDataFromHiiHandle ( + IN EFI_HII_HANDLE HiiHandle, + IN OUT UINT16 *ImageLength, + OUT UINT8 *DefaultImage, + OUT EFI_GUID *Guid + ) +/*++ + +Routine Description: + + Extract information pertaining to the HiiHandle + +Arguments: + + HiiHandle - Hii handle + + ImageLength - For input, length of DefaultImage; + For output, length of actually required + + DefaultImage - Image buffer prepared by caller + + Guid - Guid information about the form + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_BUFFER_TOO_SMALL - DefualtImage has no enough ImageLength + + EFI_SUCCESS - Successfully extract data from Hii database. + + +--*/ +{ + EFI_STATUS Status; + EFI_HII_PROTOCOL *Hii; + UINTN DataLength; + UINT8 *RawData; + UINT8 *OldData; + UINTN Index; + UINTN Temp; + UINTN SizeOfNvStore; + UINTN CachedStart; + + DataLength = DEFAULT_FORM_BUFFER_SIZE; + SizeOfNvStore = 0; + CachedStart = 0; + + Status = GetHiiInterface (&Hii); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate space for retrieval of IFR data + // + RawData = AllocateZeroPool (DataLength); + if (RawData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all the forms associated with this HiiHandle + // + Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData); + + if (EFI_ERROR (Status)) { + gBS->FreePool (RawData); + + // + // Allocate space for retrieval of IFR data + // + RawData = AllocateZeroPool (DataLength); + if (RawData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all the forms associated with this HiiHandle + // + Status = Hii->GetForms (Hii, HiiHandle, 0, &DataLength, RawData); + } + + OldData = RawData; + + // + // Point RawData to the beginning of the form data + // + RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER)); + + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + switch (RawData[Index]) { + case EFI_IFR_FORM_SET_OP: + // + // Copy the GUID information from this handle + // + CopyMem (Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID)); + break; + + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_DATE_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + // + // Remember, multiple op-codes may reference the same item, so let's keep a running + // marker of what the highest QuestionId that wasn't zero length. This will accurately + // maintain the Size of the NvStore + // + if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) { + Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width; + if (SizeOfNvStore < Temp) { + SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width; + } + } + } + + Index = RawData[Index + 1] + Index; + } + + // + // Return an error if buffer is too small + // + if (SizeOfNvStore > *ImageLength) { + gBS->FreePool (OldData); + *ImageLength = (UINT16) SizeOfNvStore; + return EFI_BUFFER_TOO_SMALL; + } + + if (DefaultImage != NULL) { + ZeroMem (DefaultImage, SizeOfNvStore); + } + + // + // Copy the default image information to the user's buffer + // + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + switch (RawData[Index]) { + case EFI_IFR_ONE_OF_OP: + CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + if (((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Flags & EFI_IFR_FLAG_DEFAULT) { + CopyMem (&DefaultImage[CachedStart], &((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value, 2); + } + break; + + case EFI_IFR_CHECKBOX_OP: + DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId] = ((EFI_IFR_CHECKBOX *) &RawData[Index])->Flags; + break; + + case EFI_IFR_NUMERIC_OP: + CopyMem ( + &DefaultImage[((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId], + &((EFI_IFR_NUMERIC *) &RawData[Index])->Default, + 2 + ); + break; + + } + + Index = RawData[Index + 1] + Index; + } + + *ImageLength = (UINT16) SizeOfNvStore; + + // + // Free our temporary repository of form data + // + gBS->FreePool (OldData); + + return EFI_SUCCESS; +} + + +EFI_HII_HANDLE +FindHiiHandle ( + IN OUT EFI_HII_PROTOCOL **HiiProtocol, OPTIONAL + IN EFI_GUID *Guid + ) +/*++ + +Routine Description: + Finds HII handle for given pack GUID previously registered with the HII. + +Arguments: + HiiProtocol - pointer to pointer to HII protocol interface. + If NULL, the interface will be found but not returned. + If it points to NULL, the interface will be found and + written back to the pointer that is pointed to. + Guid - The GUID of the pack that registered with the HII. + +Returns: + Handle to the HII pack previously registered by the memory driver. + +--*/ +{ + EFI_STATUS Status; + + EFI_HII_HANDLE *HiiHandleBuffer; + EFI_HII_HANDLE HiiHandle; + UINT16 HiiHandleBufferLength; + UINT32 NumberOfHiiHandles; + EFI_GUID HiiGuid; + EFI_HII_PROTOCOL *HiiProt; + UINT32 Index; + UINT16 Length; + + HiiHandle = 0; + if ((HiiProtocol != NULL) && (*HiiProtocol != NULL)) { + // + // The protocol has been passed in + // + HiiProt = *HiiProtocol; + } else { + gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + (VOID **) &HiiProt + ); + if (HiiProt == NULL) { + return HiiHandle; + } + + if (HiiProtocol != NULL) { + // + // Return back the HII protocol for the caller as promissed + // + *HiiProtocol = HiiProt; + } + } + // + // Allocate buffer + // + HiiHandleBufferLength = 10; + HiiHandleBuffer = AllocatePool (HiiHandleBufferLength); + ASSERT (HiiHandleBuffer != NULL); + + // + // Get the Handles of the packages that were registered with Hii + // + Status = HiiProt->FindHandles ( + HiiProt, + &HiiHandleBufferLength, + HiiHandleBuffer + ); + + // + // Get a bigger bugffer if this one is to small, and try again + // + if (Status == EFI_BUFFER_TOO_SMALL) { + + gBS->FreePool (HiiHandleBuffer); + + HiiHandleBuffer = AllocatePool (HiiHandleBufferLength); + ASSERT (HiiHandleBuffer != NULL); + + Status = HiiProt->FindHandles ( + HiiProt, + &HiiHandleBufferLength, + HiiHandleBuffer + ); + } + + if (EFI_ERROR (Status)) { + goto lbl_exit; + } + + NumberOfHiiHandles = HiiHandleBufferLength / sizeof (EFI_HII_HANDLE); + + // + // Iterate Hii handles and look for the one that matches our Guid + // + for (Index = 0; Index < NumberOfHiiHandles; Index++) { + + Length = 0; + ExtractDataFromHiiHandle (HiiHandleBuffer[Index], &Length, NULL, &HiiGuid); + + if (CompareGuid (&HiiGuid, Guid)) { + + HiiHandle = HiiHandleBuffer[Index]; + break; + } + } + +lbl_exit: + gBS->FreePool (HiiHandleBuffer); + return HiiHandle; +} + + +EFI_STATUS +ValidateDataFromHiiHandle ( + IN EFI_HII_HANDLE HiiHandle, + OUT BOOLEAN *Results + ) +/*++ + +Routine Description: + + Validate that the data associated with the HiiHandle in NVRAM is within + the reasonable parameters for that FormSet. Values for strings and passwords + are not verified due to their not having the equivalent of valid range settings. + +Arguments: + + HiiHandle - Handle of the HII database entry to query + + Results - If return Status is EFI_SUCCESS, Results provides valid data + TRUE = NVRAM Data is within parameters + FALSE = NVRAM Data is NOT within parameters + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Data successfully validated +--*/ +{ + EFI_STATUS Status; + EFI_HII_PROTOCOL *Hii; + EFI_GUID Guid; + UINT8 *RawData; + UINT8 *OldData; + UINTN RawDataLength; + UINT8 *VariableData; + UINTN Index; + UINTN Temp; + UINTN SizeOfNvStore; + UINTN CachedStart; + BOOLEAN GotMatch; + + RawDataLength = DEFAULT_FORM_BUFFER_SIZE; + SizeOfNvStore = 0; + CachedStart = 0; + GotMatch = FALSE; + *Results = TRUE; + + Status = GetHiiInterface (&Hii); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Allocate space for retrieval of IFR data + // + RawData = AllocateZeroPool (RawDataLength); + if (RawData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all the forms associated with this HiiHandle + // + Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData); + + if (EFI_ERROR (Status)) { + gBS->FreePool (RawData); + + // + // Allocate space for retrieval of IFR data + // + RawData = AllocateZeroPool (RawDataLength); + if (RawData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Get all the forms associated with this HiiHandle + // + Status = Hii->GetForms (Hii, HiiHandle, 0, &RawDataLength, RawData); + } + + OldData = RawData; + + // + // Point RawData to the beginning of the form data + // + RawData = (UINT8 *) ((UINTN) RawData + sizeof (EFI_HII_PACK_HEADER)); + + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + if (RawData[Index] == EFI_IFR_FORM_SET_OP) { + CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID)); + break; + } + + Index = RawData[Index + 1] + Index; + } + + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + switch (RawData[Index]) { + case EFI_IFR_FORM_SET_OP: + break; + + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_DATE_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + // + // Remember, multiple op-codes may reference the same item, so let's keep a running + // marker of what the highest QuestionId that wasn't zero length. This will accurately + // maintain the Size of the NvStore + // + if (((EFI_IFR_ONE_OF *) &RawData[Index])->Width != 0) { + Temp = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width; + if (SizeOfNvStore < Temp) { + SizeOfNvStore = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId + ((EFI_IFR_ONE_OF *) &RawData[Index])->Width; + } + } + } + + Index = RawData[Index + 1] + Index; + } + + // + // Allocate memory for our File Form Tags + // + VariableData = AllocateZeroPool (SizeOfNvStore); + if (VariableData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gRT->GetVariable ( + (CHAR16 *) L"Setup", + &Guid, + NULL, + &SizeOfNvStore, + (VOID *) VariableData + ); + + if (EFI_ERROR (Status)) { + + // + // If there is a variable that exists already and it is larger than what we calculated the + // storage needs to be, we must assume the variable size from GetVariable is correct and not + // allow the truncation of the variable. It is very possible that the user who created the IFR + // we are cracking is not referring to a variable that was in a previous map, however we cannot + // allow it's truncation. + // + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Free the buffer that was allocated that was too small + // + gBS->FreePool (VariableData); + + VariableData = AllocatePool (SizeOfNvStore); + if (VariableData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gRT->GetVariable ( + (CHAR16 *) L"Setup", + &Guid, + NULL, + &SizeOfNvStore, + (VOID *) VariableData + ); + } + } + + // + // Walk through the form and see that the variable data it refers to is ok. + // This allows for the possibility of stale (obsoleted) data in the variable + // can be overlooked without causing an error + // + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + switch (RawData[Index]) { + case EFI_IFR_ONE_OF_OP: + // + // A one_of has no data, its the option that does - cache the storage Id + // + CachedStart = ((EFI_IFR_ONE_OF *) &RawData[Index])->QuestionId; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + // + // A one_of_option can be any value + // + if (VariableData[CachedStart] == ((EFI_IFR_ONE_OF_OPTION *) &RawData[Index])->Value) { + GotMatch = TRUE; + } + break; + + case EFI_IFR_END_ONE_OF_OP: + // + // At this point lets make sure that the data value in the NVRAM matches one of the options + // + if (!GotMatch) { + *Results = FALSE; + return EFI_SUCCESS; + } + break; + + case EFI_IFR_CHECKBOX_OP: + // + // A checkbox is a boolean, so 0 and 1 are valid + // Remember, QuestionId corresponds to the offset location of the data in the variable + // + if (VariableData[((EFI_IFR_CHECKBOX *) &RawData[Index])->QuestionId] > 1) { + *Results = FALSE; + return EFI_SUCCESS; + } + break; + + case EFI_IFR_NUMERIC_OP: + if ((VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] < ((EFI_IFR_NUMERIC *)&RawData[Index])->Minimum) || + (VariableData[((EFI_IFR_NUMERIC *)&RawData[Index])->QuestionId] > ((EFI_IFR_NUMERIC *)&RawData[Index])->Maximum)) { + *Results = FALSE; + return EFI_SUCCESS; + } + break; + + } + + Index = RawData[Index + 1] + Index; + } + + // + // Free our temporary repository of form data + // + gBS->FreePool (OldData); + gBS->FreePool (VariableData); + + return EFI_SUCCESS; +} + diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/IfrOnTheFly.c b/EdkModulePkg/Library/EdkIfrSupportLib/IfrOnTheFly.c new file mode 100644 index 0000000000..e3d1040896 --- /dev/null +++ b/EdkModulePkg/Library/EdkIfrSupportLib/IfrOnTheFly.c @@ -0,0 +1,972 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + IfrOnTheFly.c + +Abstract: + + Library Routines to create IFR on-the-fly + +Revision History: + +--*/ + +EFI_STATUS +CreateFormSet ( + IN CHAR16 *FormSetTitle, + IN EFI_GUID *Guid, + IN UINT8 Class, + IN UINT8 SubClass, + IN OUT VOID **FormBuffer, + IN OUT VOID **StringBuffer + ) +/*++ + +Routine Description: + + Create a formset + +Arguments: + + FormSetTitle - Title of formset + + Guid - Guid of formset + + Class - Class of formset + + SubClass - Sub class of formset + + FormBuffer - Pointer of the formset created + + StringBuffer - Pointer of FormSetTitile string created + +Returns: + + EFI_OUT_OF_RESOURCES - No enough buffer to allocate + + EFI_SUCCESS - Formset successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_HII_IFR_PACK IfrPack; + EFI_IFR_FORM_SET FormSet; + EFI_IFR_END_FORM_SET EndFormSet; + UINT8 *Destination; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Pre-allocate a buffer sufficient for us to work from. + // + FormBuffer = AllocateZeroPool (DEFAULT_FORM_BUFFER_SIZE); + if (FormBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Pre-allocate a buffer sufficient for us to work from. + // + StringBuffer = AllocateZeroPool (DEFAULT_STRING_BUFFER_SIZE); + if (StringBuffer == NULL) { + gBS->FreePool (FormBuffer); + return EFI_OUT_OF_RESOURCES; + } + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add the FormSetTitle to the string buffer and get the StringToken + // + Status = AddString (*StringBuffer, CurrentLanguage, FormSetTitle, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Initialize the Ifr Package header data + // + IfrPack.Header.Length = sizeof (EFI_HII_PACK_HEADER) + sizeof (EFI_IFR_FORM_SET) + sizeof (EFI_IFR_END_FORM_SET); + IfrPack.Header.Type = EFI_HII_IFR; + + // + // Initialize FormSet with the appropriate information + // + FormSet.Header.OpCode = EFI_IFR_FORM_SET_OP; + FormSet.Header.Length = sizeof (EFI_IFR_FORM_SET); + FormSet.FormSetTitle = StringToken; + FormSet.Class = Class; + FormSet.SubClass = SubClass; + CopyMem (&FormSet.Guid, Guid, sizeof (EFI_GUID)); + + // + // Initialize the end formset data + // + EndFormSet.Header.Length = sizeof (EFI_IFR_END_FORM_SET); + EndFormSet.Header.OpCode = EFI_IFR_END_FORM_SET_OP; + + Destination = (UINT8 *) *FormBuffer; + + // + // Copy the formset/endformset data to the form buffer + // + CopyMem (Destination, &IfrPack, sizeof (EFI_HII_PACK_HEADER)); + + Destination = Destination + sizeof (EFI_HII_PACK_HEADER); + + CopyMem (Destination, &FormSet, sizeof (EFI_IFR_FORM_SET)); + + Destination = Destination + sizeof (EFI_IFR_FORM_SET); + + CopyMem (Destination, &EndFormSet, sizeof (EFI_IFR_END_FORM_SET)); + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateForm ( + IN CHAR16 *FormTitle, + IN UINT16 FormId, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a form + +Arguments: + + FormTitle - Title of the form + + FormId - Id of the form + + FormBuffer - Pointer of the form created + + StringBuffer - Pointer of FormTitil string created + +Returns: + + EFI_SUCCESS - Form successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_FORM Form; + EFI_IFR_END_FORM EndForm; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + Status = AddString (StringBuffer, CurrentLanguage, FormTitle, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Form.Header.OpCode = EFI_IFR_FORM_OP; + Form.Header.Length = sizeof (EFI_IFR_FORM); + Form.FormId = FormId; + Form.FormTitle = StringToken; + + Status = AddOpCode (FormBuffer, &Form); + + if (EFI_ERROR (Status)) { + return Status; + } + + EndForm.Header.OpCode = EFI_IFR_END_FORM_OP; + EndForm.Header.Length = sizeof (EFI_IFR_END_FORM); + + Status = AddOpCode (FormBuffer, &EndForm); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateSubTitle ( + IN CHAR16 *SubTitle, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a SubTitle + +Arguments: + + SubTitle - Sub title to be created + + FormBuffer - Where this subtitle to add to + + StringBuffer - String buffer created for subtitle + +Returns: + + EFI_SUCCESS - Subtitle successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_SUBTITLE Subtitle; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + Status = AddString (StringBuffer, CurrentLanguage, SubTitle, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP; + Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE); + Subtitle.SubTitle = StringToken; + + Status = AddOpCode (FormBuffer, &Subtitle); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateText ( + IN CHAR16 *String, + IN CHAR16 *String2, + IN CHAR16 *String3, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a line of text + +Arguments: + + String - First string of the text + + String2 - Second string of the text + + String3 - Help string of the text + + Flags - Flag of the text + + Key - Key of the text + + FormBuffer - The form where this text adds to + + StringBuffer - String buffer created for String, String2 and String3 + +Returns: + + EFI_SUCCESS - Text successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_TEXT Text; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, String, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Text.Header.OpCode = EFI_IFR_TEXT_OP; + Text.Header.Length = sizeof (EFI_IFR_TEXT); + Text.Text = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, String2, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Text.TextTwo = StringToken; + + Text.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED); + Text.Key = Key; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, String3, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Text.Help = StringToken; + + Status = AddOpCode (FormBuffer, &Text); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateGoto ( + IN UINT16 FormId, + IN CHAR16 *Prompt, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a hyperlink + +Arguments: + + FormId - Form ID of the hyperlink + + Prompt - Prompt of the hyperlink + + FormBuffer - The form where this hyperlink adds to + + StringBuffer - String buffer created for Prompt + +Returns: + + EFI_SUCCESS - Hyperlink successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_REF Hyperlink; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Hyperlink.Header.OpCode = EFI_IFR_REF_OP; + Hyperlink.Header.Length = sizeof (EFI_IFR_REF); + Hyperlink.FormId = FormId; + Hyperlink.Prompt = StringToken; + + Status = AddOpCode (FormBuffer, &Hyperlink); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateOneOf ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a one-of question with a set of options to choose from. The + OptionsList is a pointer to a null-terminated list of option descriptions. + +Arguments: + + QuestionId - Question ID of the one-of box + + DataWidth - DataWidth of the one-of box + + Prompt - Prompt of the one-of box + + Help - Help of the one-of box + + OptionsList - Each string in it is an option of the one-of box + + OptionCount - Option string count + + FormBuffer - The form where this one-of box adds to + + StringBuffer - String buffer created for Prompt, Help and Option strings + +Returns: + + EFI_DEVICE_ERROR - DataWidth > 2 + + EFI_SUCCESS - One-Of box successfully created. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_IFR_ONE_OF OneOf; + EFI_IFR_ONE_OF_OPTION OneOfOption; + EFI_IFR_END_ONE_OF EndOneOf; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // We do not create op-code storage widths for one-of in excess of 16 bits for now + // + if (DataWidth > 2) { + return EFI_DEVICE_ERROR; + } + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP; + OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF); + OneOf.QuestionId = QuestionId; + OneOf.Width = DataWidth; + OneOf.Prompt = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + OneOf.Help = StringToken; + + Status = AddOpCode (FormBuffer, &OneOf); + + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < OptionCount; Index++) { + OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP; + OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION); + + // + // Add string and get token back + // + Status = AddString (StringBuffer, CurrentLanguage, OptionsList[Index].OptionString, &StringToken); + + OneOfOption.Option = StringToken; + OneOfOption.Value = OptionsList[Index].Value; + OneOfOption.Flags = (UINT8) (OptionsList[Index].Flags | EFI_IFR_FLAG_CREATED); + OneOfOption.Key = OptionsList[Index].Key; + + Status = AddOpCode (FormBuffer, &OneOfOption); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + EndOneOf.Header.Length = sizeof (EFI_IFR_END_ONE_OF); + EndOneOf.Header.OpCode = EFI_IFR_END_ONE_OF_OP; + + Status = AddOpCode (FormBuffer, &EndOneOf); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateOrderedList ( + IN UINT16 QuestionId, + IN UINT8 MaxEntries, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a one-of question with a set of options to choose from. The + OptionsList is a pointer to a null-terminated list of option descriptions. + +Arguments: + + QuestionId - Question ID of the ordered list + + MaxEntries - MaxEntries of the ordered list + + Prompt - Prompt of the ordered list + + Help - Help of the ordered list + + OptionsList - Each string in it is an option of the ordered list + + OptionCount - Option string count + + FormBuffer - The form where this ordered list adds to + + StringBuffer - String buffer created for Prompt, Help and Option strings + +Returns: + + EFI_SUCCESS - Ordered list successfully created. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_IFR_ORDERED_LIST OrderedList; + EFI_IFR_ONE_OF_OPTION OrderedListOption; + EFI_IFR_END_ONE_OF EndOrderedList; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP; + OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST); + OrderedList.QuestionId = QuestionId; + OrderedList.MaxEntries = MaxEntries; + OrderedList.Prompt = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + OrderedList.Help = StringToken; + + Status = AddOpCode (FormBuffer, &OrderedList); + + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < OptionCount; Index++) { + OrderedListOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP; + OrderedListOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION); + + // + // Add string and get token back + // + Status = AddString (StringBuffer, CurrentLanguage, OptionsList[Index].OptionString, &StringToken); + + OrderedListOption.Option = StringToken; + OrderedListOption.Value = OptionsList[Index].Value; + OrderedListOption.Flags = (UINT8) (OptionsList[Index].Flags | EFI_IFR_FLAG_CREATED); + OrderedListOption.Key = OptionsList[Index].Key; + + Status = AddOpCode (FormBuffer, &OrderedListOption); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + EndOrderedList.Header.Length = sizeof (EFI_IFR_END_ONE_OF); + EndOrderedList.Header.OpCode = EFI_IFR_END_ONE_OF_OP; + + Status = AddOpCode (FormBuffer, &EndOrderedList); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateCheckBox ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN UINT8 Flags, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a checkbox + +Arguments: + + QuestionId - Question ID of the check box + + DataWidth - DataWidth of the check box + + Prompt - Prompt of the check box + + Help - Help of the check box + + Flags - Flags of the check box + + FormBuffer - The form where this check box adds to + + StringBuffer - String buffer created for Prompt and Help. + +Returns: + + EFI_DEVICE_ERROR - DataWidth > 1 + + EFI_SUCCESS - Check box successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_CHECKBOX CheckBox; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // We do not create op-code storage widths for checkbox in excess of 8 bits for now + // + if (DataWidth > 1) { + return EFI_DEVICE_ERROR; + } + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP; + CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX); + CheckBox.QuestionId = QuestionId; + CheckBox.Width = DataWidth; + CheckBox.Prompt = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + CheckBox.Help = StringToken; + CheckBox.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED); + + Status = AddOpCode (FormBuffer, &CheckBox); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateNumeric ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN UINT16 Minimum, + IN UINT16 Maximum, + IN UINT16 Step, + IN UINT16 Default, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a numeric + +Arguments: + + QuestionId - Question ID of the numeric + + DataWidth - DataWidth of the numeric + + Prompt - Prompt of the numeric + + Help - Help of the numeric + + Minimum - Minumun boundary of the numeric + + Maximum - Maximum boundary of the numeric + + Step - Step of the numeric + + Default - Default value + + Flags - Flags of the numeric + + Key - Key of the numeric + + FormBuffer - The form where this numeric adds to + + StringBuffer - String buffer created for Prompt and Help. + +Returns: + + EFI_DEVICE_ERROR - DataWidth > 2 + + EFI_SUCCESS - Numeric is successfully created + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_NUMERIC Numeric; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // We do not create op-code storage widths for numerics in excess of 16 bits for now + // + if (DataWidth > 2) { + return EFI_DEVICE_ERROR; + } + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP; + Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC); + Numeric.QuestionId = QuestionId; + Numeric.Width = DataWidth; + Numeric.Prompt = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + Numeric.Help = StringToken; + Numeric.Minimum = Minimum; + Numeric.Maximum = Maximum; + Numeric.Step = Step; + Numeric.Default = Default; + Numeric.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED); + Numeric.Key = Key; + + Status = AddOpCode (FormBuffer, &Numeric); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateString ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN CHAR16 *Prompt, + IN CHAR16 *Help, + IN UINT8 MinSize, + IN UINT8 MaxSize, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer, + IN OUT VOID *StringBuffer + ) +/*++ + +Routine Description: + + Create a string + +Arguments: + + QuestionId - Question ID of the string + + DataWidth - DataWidth of the string + + Prompt - Prompt of the string + + Help - Help of the string + + MinSize - Min size boundary of the string + + MaxSize - Max size boundary of the string + + Flags - Flags of the string + + Key - Key of the string + + FormBuffer - The form where this string adds to + + StringBuffer - String buffer created for Prompt and Help. + +Returns: + + EFI_SUCCESS - String successfully created. + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_STRING String; + CHAR16 CurrentLanguage[4]; + STRING_REF StringToken; + + // + // Obtain current language value + // + GetCurrentLanguage (CurrentLanguage); + + // + // Add first string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Prompt, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + String.Header.OpCode = EFI_IFR_STRING_OP; + String.Header.Length = sizeof (EFI_IFR_STRING); + String.QuestionId = QuestionId; + String.Width = DataWidth; + String.Prompt = StringToken; + + // + // Add second string, get first string's token + // + Status = AddString (StringBuffer, CurrentLanguage, Help, &StringToken); + + if (EFI_ERROR (Status)) { + return Status; + } + + String.Help = StringToken; + String.MinSize = MinSize; + String.MaxSize = MaxSize; + String.Flags = (UINT8) (Flags | EFI_IFR_FLAG_CREATED); + String.Key = Key; + + Status = AddOpCode (FormBuffer, &String); + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/IfrOpCodeCreation.c b/EdkModulePkg/Library/EdkIfrSupportLib/IfrOpCodeCreation.c new file mode 100644 index 0000000000..6fb2be791e --- /dev/null +++ b/EdkModulePkg/Library/EdkIfrSupportLib/IfrOpCodeCreation.c @@ -0,0 +1,613 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + IfrOpCodeCreation.c + +Abstract: + + Library Routines to create IFR independent of string data - assume tokens already exist + Primarily to be used for exporting op-codes at a label in pre-defined forms. + +Revision History: + +--*/ + +EFI_STATUS +CreateSubTitleOpCode ( + IN STRING_REF StringToken, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a SubTitle opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + StringToken - StringToken of the subtitle + + FormBuffer - Output of subtitle as a form + +Returns: + + EFI_SUCCESS - Subtitle created to be a form + +--*/ +{ + EFI_IFR_SUBTITLE Subtitle; + + Subtitle.Header.OpCode = EFI_IFR_SUBTITLE_OP; + Subtitle.Header.Length = sizeof (EFI_IFR_SUBTITLE); + Subtitle.SubTitle = StringToken; + + CopyMem (FormBuffer, &Subtitle, sizeof (EFI_IFR_SUBTITLE)); + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateTextOpCode ( + IN STRING_REF StringToken, + IN STRING_REF StringTokenTwo, + IN STRING_REF StringTokenThree, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a Text opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + StringToken - First string token of the text + + StringTokenTwo - Second string token of the text + + StringTokenThree - Help string token of the text + + Flags - Flag of the text + + Key - Key of the text + + FormBuffer - Output of text as a form + +Returns: + + EFI_SUCCESS - Text created to be a form + +--*/ +{ + EFI_IFR_TEXT Text; + + Text.Header.OpCode = EFI_IFR_TEXT_OP; + Text.Header.Length = sizeof (EFI_IFR_TEXT); + Text.Text = StringToken; + + Text.TextTwo = StringTokenTwo; + Text.Help = StringTokenThree; + Text.Flags = Flags; + Text.Key = Key; + + CopyMem (FormBuffer, &Text, sizeof (EFI_IFR_TEXT)); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateGotoOpCode ( + IN UINT16 FormId, + IN STRING_REF StringToken, + IN STRING_REF StringTokenTwo, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a hyperlink opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + FormId - Form ID of the hyperlink + + StringToken - Prompt string token of the hyperlink + + StringTokenTwo - Help string token of the hyperlink + + Flags - Flags of the hyperlink + + Key - Key of the hyperlink + + FormBuffer - Output of hyperlink as a form + +Returns: + + EFI_SUCCESS - Hyperlink created to be a form + +--*/ +{ + EFI_IFR_REF Hyperlink; + + Hyperlink.Header.OpCode = EFI_IFR_REF_OP; + Hyperlink.Header.Length = sizeof (EFI_IFR_REF); + Hyperlink.FormId = FormId; + Hyperlink.Prompt = StringToken; + Hyperlink.Help = StringTokenTwo; + Hyperlink.Key = Key; + Hyperlink.Flags = Flags; + + CopyMem (FormBuffer, &Hyperlink, sizeof (EFI_IFR_REF)); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateOneOfOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a one-of opcode with a set of option op-codes to choose from independent of string creation. + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + + OptionsList is a pointer to a null-terminated list of option descriptions. Ensure that OptionsList[x].StringToken + has been filled in since this routine will not generate StringToken values. + +Arguments: + + QuestionId - Question ID of the one-of box + + DataWidth - DataWidth of the one-of box + + PromptToken - Prompt string token of the one-of box + + HelpToken - Help string token of the one-of box + + OptionsList - Each string in it is an option of the one-of box + + OptionCount - Option string count + + FormBuffer - Output of One-Of box as a form + +Returns: + + EFI_SUCCESS - One-Of box created to be a form + + EFI_DEVICE_ERROR - DataWidth > 2 + +--*/ +{ + UINTN Index; + EFI_IFR_ONE_OF OneOf; + EFI_IFR_ONE_OF_OPTION OneOfOption; + EFI_IFR_END_ONE_OF EndOneOf; + UINT8 *LocalBuffer; + + // + // We do not create op-code storage widths for one-of in excess of 16 bits for now + // + if (DataWidth > 2) { + return EFI_DEVICE_ERROR; + } + + OneOf.Header.OpCode = EFI_IFR_ONE_OF_OP; + OneOf.Header.Length = sizeof (EFI_IFR_ONE_OF); + OneOf.QuestionId = QuestionId; + OneOf.Width = DataWidth; + OneOf.Prompt = PromptToken; + + OneOf.Help = HelpToken; + + LocalBuffer = (UINT8 *) FormBuffer; + + CopyMem (LocalBuffer, &OneOf, sizeof (EFI_IFR_ONE_OF)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF)); + + for (Index = 0; Index < OptionCount; Index++) { + OneOfOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP; + OneOfOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION); + + OneOfOption.Option = OptionsList[Index].StringToken; + OneOfOption.Value = OptionsList[Index].Value; + OneOfOption.Flags = OptionsList[Index].Flags; + OneOfOption.Key = OptionsList[Index].Key; + + CopyMem (LocalBuffer, &OneOfOption, sizeof (EFI_IFR_ONE_OF_OPTION)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF_OPTION)); + } + + EndOneOf.Header.Length = sizeof (EFI_IFR_END_ONE_OF); + EndOneOf.Header.OpCode = EFI_IFR_END_ONE_OF_OP; + + CopyMem (LocalBuffer, &EndOneOf, sizeof (EFI_IFR_END_ONE_OF)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_END_ONE_OF)); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateOrderedListOpCode ( + IN UINT16 QuestionId, + IN UINT8 MaxEntries, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN IFR_OPTION *OptionsList, + IN UINTN OptionCount, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a ordered list opcode with a set of option op-codes to choose from independent of string creation. + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + + OptionsList is a pointer to a null-terminated list of option descriptions. Ensure that OptionsList[x].StringToken + has been filled in since this routine will not generate StringToken values. + +Arguments: + + QuestionId - Question ID of the ordered list + + MaxEntries - MaxEntries of the ordered list + + PromptToken - Prompt string token of the ordered list + + HelpToken - Help string token of the ordered list + + OptionsList - Each string in it is an option of the ordered list + + OptionCount - Option string count + + FormBuffer - Output of ordered list as a form + +Returns: + + EFI_SUCCESS - Ordered list created to be a form + +--*/ +{ + UINTN Index; + EFI_IFR_ORDERED_LIST OrderedList; + EFI_IFR_ONE_OF_OPTION OrderedListOption; + EFI_IFR_END_ONE_OF EndOrderedList; + UINT8 *LocalBuffer; + + OrderedList.Header.OpCode = EFI_IFR_ORDERED_LIST_OP; + OrderedList.Header.Length = sizeof (EFI_IFR_ORDERED_LIST); + OrderedList.QuestionId = QuestionId; + OrderedList.MaxEntries = MaxEntries; + OrderedList.Prompt = PromptToken; + + OrderedList.Help = HelpToken; + + LocalBuffer = (UINT8 *) FormBuffer; + + CopyMem (LocalBuffer, &OrderedList, sizeof (EFI_IFR_ORDERED_LIST)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ORDERED_LIST)); + + for (Index = 0; Index < OptionCount; Index++) { + OrderedListOption.Header.OpCode = EFI_IFR_ONE_OF_OPTION_OP; + OrderedListOption.Header.Length = sizeof (EFI_IFR_ONE_OF_OPTION); + + OrderedListOption.Option = OptionsList[Index].StringToken; + OrderedListOption.Value = OptionsList[Index].Value; + OrderedListOption.Flags = OptionsList[Index].Flags; + OrderedListOption.Key = OptionsList[Index].Key; + + CopyMem (LocalBuffer, &OrderedListOption, sizeof (EFI_IFR_ONE_OF_OPTION)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_ONE_OF_OPTION)); + } + + EndOrderedList.Header.Length = sizeof (EFI_IFR_END_ONE_OF); + EndOrderedList.Header.OpCode = EFI_IFR_END_ONE_OF_OP; + + CopyMem (LocalBuffer, &EndOrderedList, sizeof (EFI_IFR_END_ONE_OF)); + + LocalBuffer = (UINT8 *) (LocalBuffer + sizeof (EFI_IFR_END_ONE_OF)); + + return EFI_SUCCESS; +} + +EFI_STATUS +CreateCheckBoxOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a checkbox opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + QuestionId - Question ID of the check box + + DataWidth - DataWidth of the check box + + PromptToken - Prompt string token of the check box + + HelpToken - Help string token of the check box + + Flags - Flags of the check box + + Key - Key of the check box + + FormBuffer - Output of the check box as a form + +Returns: + + EFI_SUCCESS - Checkbox created to be a form + + EFI_DEVICE_ERROR - DataWidth > 1 + +--*/ +{ + EFI_IFR_CHECKBOX CheckBox; + + // + // We do not create op-code storage widths for checkbox in excess of 8 bits for now + // + if (DataWidth > 1) { + return EFI_DEVICE_ERROR; + } + + CheckBox.Header.OpCode = EFI_IFR_CHECKBOX_OP; + CheckBox.Header.Length = sizeof (EFI_IFR_CHECKBOX); + CheckBox.QuestionId = QuestionId; + CheckBox.Width = DataWidth; + CheckBox.Prompt = PromptToken; + + CheckBox.Help = HelpToken; + CheckBox.Flags = Flags; + CheckBox.Key = Key; + + CopyMem (FormBuffer, &CheckBox, sizeof (EFI_IFR_CHECKBOX)); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateNumericOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN UINT16 Minimum, + IN UINT16 Maximum, + IN UINT16 Step, + IN UINT16 Default, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a numeric opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + QuestionId - Question ID of the numeric + + DataWidth - DataWidth of the numeric + + PromptToken - Prompt string token of the numeric + + HelpToken - Help string token of the numeric + + Minimum - Minumun boundary of the numeric + + Maximum - Maximum boundary of the numeric + + Step - Step of the numeric + + Default - Default value of the numeric + + Flags - Flags of the numeric + + Key - Key of the numeric + + FormBuffer - Output of the numeric as a form + +Returns: + + EFI_SUCCESS - The numeric created to be a form. + + EFI_DEVICE_ERROR - DataWidth > 2 + +--*/ +{ + EFI_IFR_NUMERIC Numeric; + + // + // We do not create op-code storage widths for numerics in excess of 16 bits for now + // + if (DataWidth > 2) { + return EFI_DEVICE_ERROR; + } + + Numeric.Header.OpCode = EFI_IFR_NUMERIC_OP; + Numeric.Header.Length = sizeof (EFI_IFR_NUMERIC); + Numeric.QuestionId = QuestionId; + Numeric.Width = DataWidth; + Numeric.Prompt = PromptToken; + + Numeric.Help = HelpToken; + Numeric.Minimum = Minimum; + Numeric.Maximum = Maximum; + Numeric.Step = Step; + Numeric.Default = Default; + Numeric.Flags = Flags; + Numeric.Key = Key; + + CopyMem (FormBuffer, &Numeric, sizeof (EFI_IFR_NUMERIC)); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateStringOpCode ( + IN UINT16 QuestionId, + IN UINT8 DataWidth, + IN STRING_REF PromptToken, + IN STRING_REF HelpToken, + IN UINT8 MinSize, + IN UINT8 MaxSize, + IN UINT8 Flags, + IN UINT16 Key, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a numeric opcode independent of string creation + This is used primarily by users who need to create just one particular valid op-code and the string + data will be assumed to exist in the HiiDatabase already. (Useful when exporting op-codes at a label + location to pre-defined forms in HII) + +Arguments: + + QuestionId - Question ID of the string + + DataWidth - DataWidth of the string + + PromptToken - Prompt token of the string + + HelpToken - Help token of the string + + MinSize - Min size boundary of the string + + MaxSize - Max size boundary of the string + + Flags - Flags of the string + + Key - Key of the string + + FormBuffer - Output of the string as a form + +Returns: + + EFI_SUCCESS - String created to be a form. + +--*/ +{ + EFI_IFR_STRING String; + + String.Header.OpCode = EFI_IFR_STRING_OP; + String.Header.Length = sizeof (EFI_IFR_STRING); + String.QuestionId = QuestionId; + String.Width = DataWidth; + String.Prompt = PromptToken; + + String.Help = HelpToken; + String.MinSize = MinSize; + String.MaxSize = MaxSize; + String.Flags = Flags; + String.Key = Key; + + CopyMem (FormBuffer, &String, sizeof (EFI_IFR_STRING)); + + return EFI_SUCCESS; +} + + +EFI_STATUS +CreateBannerOpCode ( + IN UINT16 Title, + IN UINT16 LineNumber, + IN UINT8 Alignment, + IN OUT VOID *FormBuffer + ) +/*++ + +Routine Description: + + Create a banner opcode. This is primarily used by the FrontPage implementation from BDS. + +Arguments: + + Title - Title of the banner + + LineNumber - LineNumber of the banner + + Alignment - Alignment of the banner + + FormBuffer - Output of banner as a form + +Returns: + + EFI_SUCCESS - Banner created to be a form. + +--*/ +{ + EFI_IFR_BANNER Banner; + + Banner.Header.OpCode = EFI_IFR_BANNER_OP; + Banner.Header.Length = sizeof (EFI_IFR_BANNER); + CopyMem (&Banner.Title, &Title, sizeof (UINT16)); + CopyMem (&Banner.LineNumber, &LineNumber, sizeof (UINT16)); + Banner.Alignment = Alignment; + + CopyMem (FormBuffer, &Banner, sizeof (EFI_IFR_BANNER)); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/IfrVariable.c b/EdkModulePkg/Library/EdkIfrSupportLib/IfrVariable.c new file mode 100644 index 0000000000..3e37553668 --- /dev/null +++ b/EdkModulePkg/Library/EdkIfrSupportLib/IfrVariable.c @@ -0,0 +1,484 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + IfrVariable.c + +Abstract: + Variable/Map manipulations routines + +--*/ + +VOID +EfiLibHiiVariablePackGetMap ( + IN EFI_HII_VARIABLE_PACK *Pack, + OUT CHAR16 **Name, OPTIONAL + OUT EFI_GUID **Guid, OPTIONAL + OUT UINT16 *Id, OPTIONAL + OUT VOID **Var, OPTIONAL + OUT UINTN *Size OPTIONAL + ) +/*++ + +Routine Description: + + Extracts a variable form a Pack. + +Arguments: + + Pack - List of variables + Name - Name of the variable/map + Guid - GUID of the variable/map + Var - Pointer to the variable/map + Size - Size of the variable/map in bytes + +Returns: + + VOID + +--*/ +{ + if (NULL != Name) { + *Name = (VOID *) (Pack + 1); + } + + if (NULL != Guid) { + *Guid = (EFI_GUID *)(UINTN)&Pack->VariableGuid; + } + + + if (NULL != Id) { + *Id = Pack->VariableId; + } + + if (NULL != Var) { + *Var = (VOID *) ((CHAR8 *) (Pack + 1) + Pack->VariableNameLength); + } + + if (NULL != Size) { + *Size = Pack->Header.Length - sizeof (*Pack) - Pack->VariableNameLength; + } +} + + +UINTN +EfiLibHiiVariablePackListGetMapCnt ( + IN EFI_HII_VARIABLE_PACK_LIST *List + ) + +/*++ + +Routine Description: + + Finds a count of the variables/maps in the List. + +Arguments: + + List - List of variables + +Returns: + + UINTN - The number of map count. + +--*/ + +{ + UINTN Cnt = 0; + while (NULL != List) { + Cnt++; + List = List->NextVariablePack; + } + return Cnt; +} + + +VOID +EfiLibHiiVariablePackListForEachVar ( + IN EFI_HII_VARIABLE_PACK_LIST *List, + IN EFI_LIB_HII_VARIABLE_PACK_LIST_CALLBACK *Callback + ) +/*++ + +Routine Description: + + Will iterate all variable/maps as appearing + in List and for each, it will call the Callback. + +Arguments: + + List - List of variables + Callback - Routine to be called for each iterated variable. + +Returns: + + VOID + +--*/ + +{ + CHAR16 *MapName; + EFI_GUID *MapGuid; + UINT16 MapId; + VOID *Map; + UINTN MapSize; + + while (NULL != List) { + EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize); + // + // call the callback + // + Callback (MapName, MapGuid, MapId, Map, MapSize); + List = List->NextVariablePack; + } +} + + +EFI_STATUS +EfiLibHiiVariablePackListGetMapByIdx ( + IN UINTN Idx, + IN EFI_HII_VARIABLE_PACK_LIST *List, + OUT CHAR16 **Name, OPTIONAL + OUT EFI_GUID **Guid, OPTIONAL + OUT UINT16 *Id, OPTIONAL + OUT VOID **Var, + OUT UINTN *Size + ) + +/*++ + +Routine Description: + + Finds a variable form List given + the order number as appears in the List. + +Arguments: + + Idx - The index of the variable/map to retrieve + List - List of variables + Name - Name of the variable/map + Guid - GUID of the variable/map + Var - Pointer to the variable/map + Size - Size of the variable/map in bytes + +Returns: + + EFI_SUCCESS - Variable is found, OUT parameters are valid + EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid + +--*/ +{ + CHAR16 *MapName; + EFI_GUID *MapGuid; + UINT16 MapId; + VOID *Map; + UINTN MapSize; + + while (NULL != List) { + EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize); + if (0 == Idx--) { + *Var = Map; + *Size = MapSize; + + if (NULL != Name) { + *Name = MapName; + } + + if (NULL != Guid) { + *Guid = MapGuid; + } + + if (NULL != Id) { + *Id = MapId; + } + + return EFI_SUCCESS; // Map found + } + List = List->NextVariablePack; + } + // + // If here, the map is not found + // + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EfiLibHiiVariablePackListGetMapById ( + IN UINT16 Id, + IN EFI_HII_VARIABLE_PACK_LIST *List, + OUT CHAR16 **Name, OPTIONAL + OUT EFI_GUID **Guid, OPTIONAL + OUT VOID **Var, + OUT UINTN *Size + ) + +/*++ + +Routine Description: + + Finds a variable form List given the + order number as appears in the List. + +Arguments: + + Id - The ID of the variable/map to retrieve + List - List of variables + Name - Name of the variable/map + Guid - GUID of the variable/map + Var - Pointer to the variable/map + Size - Size of the variable/map in bytes + +Returns: + + EFI_SUCCESS - Variable is found, OUT parameters are valid + EFI_NOT_FOUND - Variable is not found, OUT parameters are not valid + +--*/ + +{ + CHAR16 *MapName; + EFI_GUID *MapGuid; + UINT16 MapId; + VOID *Map; + UINTN MapSize; + + while (NULL != List) { + EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize); + if (MapId == Id) { + *Var = Map; + *Size = MapSize; + if (NULL != Name) { + *Name = MapName; + } + if (NULL != Guid) { + *Guid = MapGuid; + } + // + // Map found + // + return EFI_SUCCESS; + } + List = List->NextVariablePack; + } + // + // If here, the map is not found + // + return EFI_NOT_FOUND; +} + + +EFI_STATUS +EfiLibHiiVariablePackListGetMap ( + IN EFI_HII_VARIABLE_PACK_LIST *List, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + OUT UINT16 *Id, + OUT VOID **Var, + OUT UINTN *Size + ) + +/*++ + +Routine Description: + + Finds a variable form EFI_HII_VARIABLE_PACK_LIST given name and GUID. + +Arguments: + + List - List of variables + Name - Name of the variable/map to be found + Guid - GUID of the variable/map to be found + Var - Pointer to the variable/map found + Size - Size of the variable/map in bytes found + +Returns: + + EFI_SUCCESS - variable is found, OUT parameters are valid + EFI_NOT_FOUND - variable is not found, OUT parameters are not valid + +--*/ + +{ + VOID *Map; + UINTN MapSize; + UINT16 MapId; + CHAR16 *MapName; + EFI_GUID *MapGuid; + + while (NULL != List) { + EfiLibHiiVariablePackGetMap (List->VariablePack, &MapName, &MapGuid, &MapId, &Map, &MapSize); + if ((0 == StrCmp (Name, MapName)) && CompareGuid (Guid, MapGuid)) { + *Id = MapId; + *Var = Map; + *Size = MapSize; + return EFI_SUCCESS; + } + List = List->NextVariablePack; + } + // + // If here, the map is not found + // + return EFI_NOT_FOUND; +} + +EFI_STATUS +EfiLibHiiVariableRetrieveFromNv ( + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINTN Size, + OUT VOID **Var + ) +/*++ + +Routine Description: + Finds out if a variable of specific Name/Guid/Size exists in NV. + If it does, it will retrieve it into the Var. + +Arguments: + Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly. + Var - Variable will be retrieved into buffer pointed by this pointer. + If pointing to NULL, the buffer will be allocated. Caller is responsible for releasing the buffer. +Returns: + EFI_SUCCESS - The variable of exact Name/Guid/Size parameters was retrieved and written to Var. + EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV. + EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error. + +--*/ +{ + EFI_STATUS Status; + UINTN SizeNv; + + // + // Test for existence of the variable. + // + SizeNv = 0; + Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, NULL); + if (EFI_BUFFER_TOO_SMALL != Status) { + ASSERT (EFI_SUCCESS != Status); + return EFI_NOT_FOUND; + } + if (SizeNv != Size) { + // + // The variable is considered corrupt, as it has different size from expected. + // + return EFI_LOAD_ERROR; + } + + if (NULL == *Var) { + *Var = AllocatePool (Size); + ASSERT (NULL != *Var); + } + SizeNv = Size; + // + // Final read into the Var + // + Status = gRT->GetVariable (Name, Guid, NULL, &SizeNv, *Var); + // + // No tolerance for random failures. Such behavior is undetermined and not validated. + // + ASSERT_EFI_ERROR (Status); + ASSERT (SizeNv == Size); + return EFI_SUCCESS; +} + + + +EFI_STATUS +EfiLibHiiVariableOverrideIfSuffix ( + IN CHAR16 *Suffix, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINTN Size, + OUT VOID *Var + ) +/*++ + +Routine Description: + Overrrides the variable with NV data if found. + But it only does it if the Name ends with specified Suffix. + For example, if Suffix="MyOverride" and the Name="XyzSetupMyOverride", + the Suffix matches the end of Name, so the variable will be loaded from NV + provided the variable exists and the GUID and Size matches. + +Arguments: + Suffix - Suffix the Name should end with. + Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly. + Var - Variable will be retrieved into this buffer. + Caller is responsible for providing storage of exactly Size size in bytes. +Returns: + EFI_SUCCESS - The variable was overriden with NV variable of same Name/Guid/Size. + EFI_INVALID_PARAMETER - The name of the variable does not end with . + EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV. + EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error. + +--*/ +{ + UINTN StrLength; + UINTN StrLenSuffix; + + StrLength = StrLen (Name); + StrLenSuffix = StrLen (Suffix); + if ((StrLength <= StrLenSuffix) || (0 != StrCmp (Suffix, &Name[StrLength - StrLenSuffix]))) { + // + // Not ending with . + // + return EFI_INVALID_PARAMETER; + } + return EfiLibHiiVariableRetrieveFromNv (Name, Guid, Size, &Var); +} + +EFI_STATUS +EfiLibHiiVariableOverrideBySuffix ( + IN CHAR16 *Suffix, + IN CHAR16 *Name, + IN EFI_GUID *Guid, + IN UINTN Size, + OUT VOID *Var + ) +/*++ + +Routine Description: + Overrrides the variable with NV data if found. + But it only does it if the NV contains the same variable with Name is appended with Suffix. + For example, if Suffix="MyOverride" and the Name="XyzSetup", + the Suffix will be appended to the end of Name, and the variable with Name="XyzSetupMyOverride" + will be loaded from NV provided the variable exists and the GUID and Size matches. + +Arguments: + Suffix - Suffix the variable will be appended with. + Name, Guid, Size - Parameters of the variable to retrieve. Must match exactly. + Var - Variable will be retrieved into this buffer. + Caller is responsible for providing storage of exactly Size size in bytes. + +Returns: + EFI_SUCCESS - The variable was overriden with NV variable of same Name/Guid/Size. + EFI_NOT_FOUND - The variable of this Name/Guid was not found in the NV. + EFI_LOAD_ERROR - The variable in the NV was of different size, or NV API returned error. + +--*/ +{ + EFI_STATUS Status; + CHAR16 *NameSuffixed; + + // + // enough to concatenate both strings. + // + NameSuffixed = AllocateZeroPool ((StrLen (Name) + StrLen (Suffix) + 1) * sizeof (CHAR16)); + + StrCpy (NameSuffixed, Name); + StrCat (NameSuffixed, Suffix); + + Status = EfiLibHiiVariableRetrieveFromNv (NameSuffixed, Guid, Size, &Var); + gBS->FreePool (NameSuffixed); + + return Status; +} + diff --git a/EdkModulePkg/Library/EdkIfrSupportLib/build.xml b/EdkModulePkg/Library/EdkIfrSupportLib/build.xml new file mode 100644 index 0000000000..54b607a71f --- /dev/null +++ b/EdkModulePkg/Library/EdkIfrSupportLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.mbd b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.mbd new file mode 100644 index 0000000000..01e0cb2e4a --- /dev/null +++ b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkMemoryStatusCodeLib + e2368d1d-4c94-4e62-be2f-7817bbd78293 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + diff --git a/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.msa b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.msa new file mode 100644 index 0000000000..6ad58a20e4 --- /dev/null +++ b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/EdkMemoryStatusCodeLib.msa @@ -0,0 +1,63 @@ + + + + + EdkMemoryStatusCodeLib + PEIM + LIBRARY + e2368d1d-4c94-4e62-be2f-7817bbd78293 + 0 + Memory Status Code Library for UEFI drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + EdkMemoryStatusCodeLib + DebugLib + HobLib + BaseLib + PeiCoreLib + PeiServicesTablePointerLib + BaseMemoryLib + + + MemoryStatusCode.c + MemoryStatusCode.h + + + MdePkg + EdkModulePkg + + + + StatusCodeMemoryPpi + gPeiStatusCodeMemoryPpiGuid + 0x26f8ab01, 0xd3cd, 0x489c, 0x98, 0x4f, 0xdf, 0xde, 0xf7, 0x68, 0x39, 0x5b + + + + StatusCodeMemory + StatusCode + FvFileLoader + + diff --git a/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.c b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.c new file mode 100644 index 0000000000..1661d7753c --- /dev/null +++ b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.c @@ -0,0 +1,498 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MemoryStatusCode.c + +Abstract: + + Lib to provide memory journal status code reporting Routines. + +--*/ +#include "MemoryStatusCode.h" + +// +// Global variable. Not accessible while running from flash. +// After we relocate ourselves into memory, we update this +// and use it to determine if we are running from flash or memory. +// + +// +// Global variable used to replace the PPI once we start running from memory. +// +PEI_STATUS_CODE_MEMORY_PPI mStatusCodeMemoryPpi = { 0, 0, 0, 0 }; + +// +// PPI descriptor for the MonoStatusCode PEIM, see MonoStatusCode.c +// +extern EFI_PEI_PPI_DESCRIPTOR mPpiListStatusCode; + +EFI_STATUS +EFIAPI +MemoryStatusCodeInitialize ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Initialization routine. + Allocates heap space for storing Status Codes. + Installs a PPI to point to that heap space. + Installs a callback to switch to memory. + Installs a callback to + +Arguments: + + FfsHeader - FV this PEIM was loaded from. + PeiServices - General purpose services available to every PEIM. + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + MEMORY_STATUS_CODE_INSTANCE *PrivateData; + PEI_STATUS_CODE_MEMORY_PPI *StatusCodeMemoryPpi; + EFI_PEI_PROGRESS_CODE_PPI *ReportStatusCodePpi; + EFI_PHYSICAL_ADDRESS Buffer; + VOID *StartPointer; + UINTN Length; + UINTN LastEntry; + EFI_PEI_PPI_DESCRIPTOR *ReportStatusCodeDescriptor; + EFI_PEI_PPI_DESCRIPTOR *StatusCodeMemoryDescriptor; + + // + // Determine if we are being called after relocation into memory. + // + if (!gRunningFromMemory) { + // + // If we are not running from memory, we need to allocate some heap and + // install the PPI + // + // + // Allocate heap storage for the journal + // + Status = (*PeiServices)->AllocatePool ( + PeiServices, + PEI_STATUS_CODE_HEAP_LENGTH, + &StartPointer + ); + + // + // This is not a required feature to boot. + // + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate heap storage for private data + // The private data contains the FFS header for this PEIM, + // a PPI containing information about the status code journal, and + // a notification for the LoadFile service, to relocate the PEIM into + // memory. + // + Status = (*PeiServices)->AllocatePool ( + PeiServices, + sizeof (MEMORY_STATUS_CODE_INSTANCE), + (VOID **) &PrivateData + ); + + // + // This is not a required feature to boot. + // + if (EFI_ERROR (Status)) { + return Status; + } + // + // Update the contents of the private data. + // + PrivateData->Signature = MEMORY_STATUS_CODE_SIGNATURE; + PrivateData->This = PrivateData; + PrivateData->FfsHeader = FfsHeader; + PrivateData->PpiDescriptor.Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + PrivateData->PpiDescriptor.Guid = &gPeiStatusCodeMemoryPpiGuid; + PrivateData->PpiDescriptor.Ppi = &PrivateData->StatusCodeMemoryPpi; + PrivateData->StatusCodeMemoryPpi.FirstEntry = 0; + PrivateData->StatusCodeMemoryPpi.LastEntry = 0; + PrivateData->StatusCodeMemoryPpi.Address = (EFI_PHYSICAL_ADDRESS) (UINTN) StartPointer; + PrivateData->StatusCodeMemoryPpi.Length = PEI_STATUS_CODE_HEAP_LENGTH; + PrivateData->NotifyDescriptor.Flags = + ( + EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | + EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST + ); + PrivateData->NotifyDescriptor.Guid = &gEfiPeiFvFileLoaderPpiGuid; + PrivateData->NotifyDescriptor.Notify = LoadImageCallback; + + // + // Publish the PPI + // + Status = (*PeiServices)->InstallPpi (PeiServices, &PrivateData->PpiDescriptor); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Post a callback to relocate to memory + // + Status = (**PeiServices).NotifyPpi (PeiServices, &PrivateData->NotifyDescriptor); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + // + // If we are running from memory, we need to copy from the heap to a RT + // memory buffer. + // + // + // Locate Journal + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gPeiStatusCodeMemoryPpiGuid, + 0, + &StatusCodeMemoryDescriptor, + (VOID **) &StatusCodeMemoryPpi + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get private data + // + PrivateData = _CR (StatusCodeMemoryDescriptor, MEMORY_STATUS_CODE_INSTANCE, PpiDescriptor); + // + // At this point, we need to fix up any addresses that we have as the heap + // has moved. + // + PrivateData->PpiDescriptor.Ppi = &PrivateData->StatusCodeMemoryPpi; + PrivateData->PpiDescriptor.Guid = &gPeiStatusCodeMemoryPpiGuid; + PrivateData->StatusCodeMemoryPpi.Address = PrivateData->StatusCodeMemoryPpi.Address + + (UINTN) PrivateData - (UINTN) PrivateData->This; + PrivateData->NotifyDescriptor.Guid = &gEfiPeiFvFileLoaderPpiGuid; + PrivateData->NotifyDescriptor.Notify = LoadImageCallback; + PrivateData->This = PrivateData; + + // + // Allocate RT memory. + // + Status = (*PeiServices)->AllocatePages ( + PeiServices, + EfiRuntimeServicesData, + PEI_STATUS_CODE_RT_PAGES, + &Buffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DEBUG_CODE ( + ZeroMem ((VOID *) (UINTN) Buffer, PEI_STATUS_CODE_RT_LENGTH); + ); + + // + // Copy the heap to the allocated memory. + // Unwind the rolling queue to start at 0 in the new space. We need to do + // this because the new queue is much bigger than the heap allocation. + // + if (PEI_STATUS_CODE_RT_LENGTH <= PEI_STATUS_CODE_HEAP_LENGTH) { + return Status; + } + + if (StatusCodeMemoryPpi->LastEntry >= StatusCodeMemoryPpi->FirstEntry) { + LastEntry = StatusCodeMemoryPpi->LastEntry - StatusCodeMemoryPpi->FirstEntry; + StartPointer = (VOID *) ((UINTN) StatusCodeMemoryPpi->Address + (StatusCodeMemoryPpi->FirstEntry * sizeof (EFI_STATUS_CODE_ENTRY))); + Length = (StatusCodeMemoryPpi->LastEntry - StatusCodeMemoryPpi->FirstEntry) * sizeof (EFI_STATUS_CODE_ENTRY); + (*PeiServices)->CopyMem ((VOID *) (UINTN) Buffer, StartPointer, Length); + } else { + // + // The last entry will be the new last entry after moving heap to buffer + // + LastEntry = (PEI_STATUS_CODE_MAX_HEAP_ENTRY - StatusCodeMemoryPpi->FirstEntry) + StatusCodeMemoryPpi->LastEntry; + // + // Copy from the first entry to the end of the heap + // + StartPointer = (VOID *) ((UINTN) StatusCodeMemoryPpi->Address + (StatusCodeMemoryPpi->FirstEntry * sizeof (EFI_STATUS_CODE_ENTRY))); + Length = PEI_STATUS_CODE_HEAP_LENGTH - (StatusCodeMemoryPpi->FirstEntry * sizeof (EFI_STATUS_CODE_ENTRY)); + (*PeiServices)->CopyMem ((VOID *) (UINTN) Buffer, StartPointer, Length); + // + // Copy from the start to the heap to the last entry + // + StartPointer = (VOID *) (UINTN) StatusCodeMemoryPpi->Address; + (*PeiServices)->CopyMem ( + (VOID *) (UINTN) (Buffer + Length), + StartPointer, + (StatusCodeMemoryPpi->LastEntry * sizeof (EFI_STATUS_CODE_ENTRY)) + ); + }; + + // + // Update the PPI to NULL, so it will not be used. + // + StatusCodeMemoryPpi->FirstEntry = 0; + StatusCodeMemoryPpi->LastEntry = 0; + StatusCodeMemoryPpi->Address = 0; + StatusCodeMemoryPpi->Length = 0; + + // + // Update in memory version of PPI that will be used. + // + mStatusCodeMemoryPpi.FirstEntry = 0; + mStatusCodeMemoryPpi.LastEntry = LastEntry; + mStatusCodeMemoryPpi.Address = (EFI_PHYSICAL_ADDRESS) (UINTN) Buffer; + mStatusCodeMemoryPpi.Length = PEI_STATUS_CODE_RT_LENGTH; + + // + // Reinstall the report status code function + // + // + // Locate status code PPI + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiStatusCodePpiGuid, + 0, + &ReportStatusCodeDescriptor, + (VOID **) &ReportStatusCodePpi + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Reinstall the ReportStatusCode interface using the memory-based + // descriptor + // + Status = (*PeiServices)->ReInstallPpi ( + PeiServices, + ReportStatusCodeDescriptor, + &mPpiListStatusCode + ); + if (EFI_ERROR (Status)) { + CpuBreakpoint (); + return Status; + } + // + // Publish a GUIDed HOB that contains a pointer to the status code PPI + // structure. This is a bit of a short cut as I just used the PPI GUID to + // identify the HOB. This HOB is caught by the DXE status code memory + // listener and used to find the journal. + // + StatusCodeMemoryPpi = &mStatusCodeMemoryPpi; + + BuildGuidDataHob ( + &gPeiStatusCodeMemoryPpiGuid, + &StatusCodeMemoryPpi, + sizeof (VOID *) + ); + } + return EFI_SUCCESS; +} + +EFI_STATUS +MemoryReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +/*++ + +Routine Description: + + Provide a memory status code + +Arguments: + + Same as ReportStatusCode PPI + +Returns: + + EFI_SUCCESS This function always returns success + +--*/ +{ + EFI_STATUS Status; + PEI_STATUS_CODE_MEMORY_PPI *StatusCodeMemoryPpi; + EFI_STATUS_CODE_ENTRY *CurrentEntry; + UINTN LastEntry; + MEMORY_STATUS_CODE_INSTANCE *PrivateData; + EFI_PEI_PPI_DESCRIPTOR *StatusCodeMemoryDescriptor; + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + // + // We don't care to log debug codes. + // + if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { + return EFI_SUCCESS; + } + + if (!gRunningFromMemory) { + // + // If we are called from DXE and have not been reinstalled into memory, we + // can no longer locate the journal, so we can no longer log status codes. + // + if (!PeiServices) { + return EFI_SUCCESS; + } + // + // Locate Journal + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gPeiStatusCodeMemoryPpiGuid, + 0, + &StatusCodeMemoryDescriptor, + (VOID **) &StatusCodeMemoryPpi + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + // + // Determine the last entry in the journal. + // This is needed to properly implement the rolling queue. + // + LastEntry = PEI_STATUS_CODE_MAX_HEAP_ENTRY; + + // + // Get private data + // + PrivateData = _CR (StatusCodeMemoryDescriptor, MEMORY_STATUS_CODE_INSTANCE, PpiDescriptor); + + // + // Once memory gets installed, heap gets moved to real memory. + // We need to fix up the pointers to match the move. + // + PrivateData->PpiDescriptor.Ppi = &PrivateData->StatusCodeMemoryPpi; + PrivateData->PpiDescriptor.Guid = &gPeiStatusCodeMemoryPpiGuid; + PrivateData->StatusCodeMemoryPpi.Address = PrivateData->StatusCodeMemoryPpi.Address + + (UINTN) PrivateData - (UINTN) PrivateData->This; + PrivateData->NotifyDescriptor.Guid = &gEfiPeiFvFileLoaderPpiGuid; + PrivateData->NotifyDescriptor.Notify = LoadImageCallback; + PrivateData->This = PrivateData; + + StatusCodeMemoryPpi = PrivateData->PpiDescriptor.Ppi; + } else { + // + // Use global/memory copy of the PPI + // + StatusCodeMemoryPpi = &mStatusCodeMemoryPpi; + + // + // Determine the last entry in the journal. + // This is needed to properly implement the rolling queue. + // + LastEntry = PEI_STATUS_CODE_MAX_RT_ENTRY; + } + // + // Return if we are using a cleared PPI somehow + // + if (!StatusCodeMemoryPpi->Address || !StatusCodeMemoryPpi->Length) { + return EFI_SUCCESS; + } + // + // Update the latest entry in the journal (may actually be first due to rolling + // queue). + // + CurrentEntry = (EFI_STATUS_CODE_ENTRY *) (UINTN) (StatusCodeMemoryPpi->Address + (StatusCodeMemoryPpi->LastEntry * sizeof (EFI_STATUS_CODE_ENTRY))); + + StatusCodeMemoryPpi->LastEntry = (StatusCodeMemoryPpi->LastEntry + 1) % LastEntry; + if (StatusCodeMemoryPpi->LastEntry == StatusCodeMemoryPpi->FirstEntry) { + StatusCodeMemoryPpi->FirstEntry = (StatusCodeMemoryPpi->FirstEntry + 1) % LastEntry; + } + + CurrentEntry->Type = CodeType; + CurrentEntry->Value = Value; + CurrentEntry->Instance = Instance; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +LoadImageCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +/*++ + +Routine Description: + + Relocate the PEIM into memory. + + Once load protocol becomes available, relocate our PEIM into memory. + The primary benefit is to eliminate the blackout window that we would have in + the memory log between the end of PEI and the status code DXE driver taking + control. If we don't do this, we cannot determine where our memory journal + is located and cannot function. + + A second benefit is speed optimization throughout DXE. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + NotifyDescriptor - Information about the notify event. + Ppi - Context + +Returns: + + EFI_SUCCESS This function always returns success. + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS ImageAddress; + EFI_PHYSICAL_ADDRESS EntryPoint; + UINT64 ImageSize; + MEMORY_STATUS_CODE_INSTANCE *PrivateData; + + // + // Relocate to memory + // + if (!gRunningFromMemory) { + // + // Use the callback descriptor to get the FfsHeader + // + PrivateData = _CR (NotifyDescriptor, MEMORY_STATUS_CODE_INSTANCE, NotifyDescriptor); + + Status = ((EFI_PEI_FV_FILE_LOADER_PPI *) Ppi)->FvLoadFile ( + Ppi, + PrivateData->FfsHeader, + &ImageAddress, + &ImageSize, + &EntryPoint + ); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + // + // Set the flag in the loaded image that indicates the PEIM is executing + // from memory. + // +#ifdef EFI_NT_EMULATOR + gRunningFromMemory = TRUE; +#else + * (BOOLEAN *) ((UINTN) &gRunningFromMemory + (UINTN) EntryPoint - (UINTN) InstallMonoStatusCode) = TRUE; +#endif + Status = ((EFI_PEIM_ENTRY_POINT )(UINTN) EntryPoint) (PrivateData->FfsHeader, PeiServices); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.h b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.h new file mode 100644 index 0000000000..3580083efa --- /dev/null +++ b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/MemoryStatusCode.h @@ -0,0 +1,94 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MemoryStatusCode.h + +Abstract: + + Lib to provide status code reporting via memory. + +--*/ + +#ifndef _PEI_MEMORY_STATUS_CODE_H_ +#define _PEI_MEMORY_STATUS_CODE_H_ + +// +// Publicly exported function +// +EFI_STATUS +EFIAPI +InstallMonoStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +; +// +// Publicly exported data +// +extern BOOLEAN gRunningFromMemory; +// +// Private data +// +// +// Define the amount of heap to use before memory is allocated +// +#define PEI_STATUS_CODE_HEAP_LENGTH 512 +#define PEI_STATUS_CODE_MAX_HEAP_ENTRY (PEI_STATUS_CODE_HEAP_LENGTH / sizeof (EFI_STATUS_CODE_ENTRY)) + +// +// Define the number of 4K pages of BS memory to allocate (1MB) +// +#define PEI_STATUS_CODE_RT_PAGES (128) +#define PEI_STATUS_CODE_RT_LENGTH (PEI_STATUS_CODE_RT_PAGES * 1024 * 4) +#define PEI_STATUS_CODE_MAX_RT_ENTRY (PEI_STATUS_CODE_RT_LENGTH / sizeof (EFI_STATUS_CODE_ENTRY)) + +// +// Define a private data structure +// +#define MEMORY_STATUS_CODE_SIGNATURE EFI_SIGNATURE_32 ('M', 'S', 'C', 'S') + +typedef struct _MEMORY_STATUS_CODE_INSTANCE { + UINT32 Signature; + struct _MEMORY_STATUS_CODE_INSTANCE *This; + EFI_FFS_FILE_HEADER *FfsHeader; + EFI_PEI_PPI_DESCRIPTOR PpiDescriptor; + PEI_STATUS_CODE_MEMORY_PPI StatusCodeMemoryPpi; + EFI_PEI_NOTIFY_DESCRIPTOR NotifyDescriptor; +} MEMORY_STATUS_CODE_INSTANCE; + +#define MEMORY_STATUS_CODE_FROM_DESCRIPTOR_THIS(a) \ + PEI_CR (a, \ + MEMORY_STATUS_CODE_INSTANCE, \ + PpiDescriptor, \ + MEMORY_STATUS_CODE_SIGNATURE \ + ) +#define MEMORY_STATUS_CODE_FROM_NOTIFY_THIS(a) \ + PEI_CR (a, \ + MEMORY_STATUS_CODE_INSTANCE, \ + NotifyDescriptor, \ + MEMORY_STATUS_CODE_SIGNATURE \ + ) + +// +// Private function declarations +// +EFI_STATUS +EFIAPI +LoadImageCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ) +; + +#endif diff --git a/EdkModulePkg/Library/EdkMemoryStatusCodeLib/build.xml b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/build.xml new file mode 100644 index 0000000000..40db09a722 --- /dev/null +++ b/EdkModulePkg/Library/EdkMemoryStatusCodeLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/CustomizedDecompress.c b/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/CustomizedDecompress.c new file mode 100644 index 0000000000..55d9bbe216 --- /dev/null +++ b/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/CustomizedDecompress.c @@ -0,0 +1,109 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CustomizedDecompress.c + +Abstract: + + Implementation file for Customized decompression routine + +--*/ + +#include + +EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL mCustomizedDecompress = { + CustomizedGetInfo, + CustomizedDecompress +}; + +EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL * +EFIAPI +GetCustomizedDecompressProtocol ( + VOID + ) +{ + return &mCustomizedDecompress; +} + + + +EFI_STATUS +EFIAPI +CustomizedGetInfo ( + IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation of Customized GetInfo(). + +Arguments: + This - The EFI customized decompress protocol + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + EFI_UNSUPPORTED - Not supported + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +CustomizedDecompress ( + IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation of Customized Decompress(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + EFI_UNSUPPORTED - Not supported + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/CustomizedDecompress.h b/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/CustomizedDecompress.h new file mode 100644 index 0000000000..e94be43b48 --- /dev/null +++ b/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/CustomizedDecompress.h @@ -0,0 +1,95 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CustomizedDecompress.h + +Abstract: + + Header file for Customized decompression routine + +--*/ +#ifndef _CUSTOMIZED_DECOMPRESS_LIB_H_ +#define _CUSTOMIZED_DECOMPRESS_LIB_H_ + + + + +EFI_STATUS +EFIAPI +CustomizedGetInfo ( + IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation of Customized GetInfo(). + +Arguments: + This - The EFI customized decompress protocol + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + EFI_UNSUPPORTED - Not supported + +--*/ +; + +EFI_STATUS +EFIAPI +CustomizedDecompress ( + IN EFI_CUSTOMIZED_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation of Customized Decompress(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + EFI_UNSUPPORTED - Not supported + +--*/ +; + + +#endif diff --git a/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/EdkNullCustomizedDecompressLib.mbd b/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/EdkNullCustomizedDecompressLib.mbd new file mode 100644 index 0000000000..a6a6d56a1c --- /dev/null +++ b/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/EdkNullCustomizedDecompressLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkNullCustomizedDecompressLib + 4a024320-0648-49c3-84d4-3d04670a1c77 + 0 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + diff --git a/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/EdkNullCustomizedDecompressLib.msa b/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/EdkNullCustomizedDecompressLib.msa new file mode 100644 index 0000000000..3ca559f642 --- /dev/null +++ b/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/EdkNullCustomizedDecompressLib.msa @@ -0,0 +1,44 @@ + + + + + EdkNullCustomizedDecompressLib + DXE_DRIVER + LIBRARY + 4a024320-0648-49c3-84d4-3d04670a1c77 + 0 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + CustomDecompressLib + + + CustomizedDecompress.c + + + MdePkg + EdkModulePkg + + diff --git a/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/build.xml b/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/build.xml new file mode 100644 index 0000000000..a8ae7fe640 --- /dev/null +++ b/EdkModulePkg/Library/EdkNullCustomizedDecompressLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoader.c b/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoader.c new file mode 100644 index 0000000000..86421dbff0 --- /dev/null +++ b/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoader.c @@ -0,0 +1,112 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + TianoPeCoffLoader.c + +Abstract: + + Wrap the Base PE/COFF loader with the PE COFF Protocol + + +--*/ + + + +EFI_STATUS +EFIAPI +TianoPeCoffLoaderLibGetImageInfo ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + EFI_STATUS Status; + + Status = PeCoffLoaderGetImageInfo (ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + switch (ImageContext->ImageType) { + + case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: + ImageContext->ImageCodeMemoryType = EfiLoaderCode; + ImageContext->ImageDataMemoryType = EfiLoaderData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: + ImageContext->ImageCodeMemoryType = EfiBootServicesCode; + ImageContext->ImageDataMemoryType = EfiBootServicesData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER: + ImageContext->ImageCodeMemoryType = EfiRuntimeServicesCode; + ImageContext->ImageDataMemoryType = EfiRuntimeServicesData; + break; + + default: + ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM; + return RETURN_UNSUPPORTED; + } + + return Status; +} + +EFI_STATUS +EFIAPI +TianoPeCoffLoaderLibLoadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + return PeCoffLoaderLoadImage (ImageContext); +} + +EFI_STATUS +EFIAPI +TianoPeCoffLoaderLibRelocateImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + return PeCoffLoaderRelocateImage (ImageContext); +} + + +EFI_STATUS +EFIAPI +TianoPeCoffLoaderLibUnloadimage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + return EFI_SUCCESS; +} + + +EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeiEfiPeiPeCoffLoader = { + TianoPeCoffLoaderLibGetImageInfo, + TianoPeCoffLoaderLibLoadImage, + TianoPeCoffLoaderLibRelocateImage, + TianoPeCoffLoaderLibUnloadimage +}; + +EFI_PEI_PE_COFF_LOADER_PROTOCOL * +EFIAPI +GetPeCoffLoaderProtocol ( + ) +{ + return &mPeiEfiPeiPeCoffLoader; +} + + diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.mbd b/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.mbd new file mode 100644 index 0000000000..4ffdf99f8f --- /dev/null +++ b/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkPeCoffLoaderLib + 858bbbc9-474f-4556-a361-0ae52a44ffa5 + 0 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.msa b/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.msa new file mode 100644 index 0000000000..0f855307d5 --- /dev/null +++ b/EdkModulePkg/Library/EdkPeCoffLoaderLib/EdkPeCoffLoaderLib.msa @@ -0,0 +1,45 @@ + + + + + EdkPeCoffLoaderLib + PEIM + LIBRARY + 858bbbc9-474f-4556-a361-0ae52a44ffa5 + 0 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + EdkPeCoffLoaderLib + PeCoffLib + + + EdkPeCoffLoader.c + + + MdePkg + EdkModulePkg + + diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderLib/build.xml b/EdkModulePkg/Library/EdkPeCoffLoaderLib/build.xml new file mode 100644 index 0000000000..6e7a34f37b --- /dev/null +++ b/EdkModulePkg/Library/EdkPeCoffLoaderLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64.c b/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64.c new file mode 100644 index 0000000000..a2862576fa --- /dev/null +++ b/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64.c @@ -0,0 +1,940 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EdkPeCoffLoaderX64.c + +Abstract: + + Wrap the Base PE/COFF loader with the PE COFF Protocol + + +--*/ + +#define IMAGE_64_MACHINE_TYPE_SUPPORTED(Machine) \ + ((Machine) == EFI_IMAGE_MACHINE_IA32 || \ + (Machine) == EFI_IMAGE_MACHINE_X64 || \ + (Machine) == EFI_IMAGE_MACHINE_EBC) + +STATIC +EFI_STATUS +PeCoffLoader64GetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_NT_HEADERS64 *PeHdr + ); + +STATIC +EFI_STATUS +PeCoffLoader64CheckImageType ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_NT_HEADERS64 *PeHdr + ); + +STATIC +VOID * +PeCoffLoader64ImageAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ); + +EFI_STATUS +EFIAPI +PeCoffLoader64GetImageInfo ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +PeCoffLoader64RelocateImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +PeCoffLoader64LoadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +PeCoffLoader64UnloadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +PeCoffLoader64RelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ); + +EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoaderX64 = { + PeCoffLoader64GetImageInfo, + PeCoffLoader64LoadImage, + PeCoffLoader64RelocateImage, + PeCoffLoader64UnloadImage +}; + +STATIC +EFI_STATUS +PeCoffLoader64GetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_NT_HEADERS64 *PeHdr + ) +/*++ + +Routine Description: + Retrieves the PE Header from a PE/COFF image + +Arguments: + ImageContext - The context of the image being loaded + PeHdr - The buffer in which to return the PE header + +Returns: + EFI_SUCCESS if the PE Header is read, + Otherwise, the error status from reading the PE/COFF image using the ImageRead function. + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_DOS_HEADER DosHdr; + UINTN Size; + + // + // Read the DOS image headers + // + Size = sizeof (EFI_IMAGE_DOS_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &Size, + &DosHdr + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + ImageContext->PeCoffHeaderOffset = 0; + if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew; + } + + // + // Read the PE/COFF Header + // + Size = sizeof (EFI_IMAGE_NT_HEADERS64); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + ImageContext->PeCoffHeaderOffset, + &Size, + PeHdr + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + return EFI_SUCCESS; +} + +static +EFI_STATUS +PeCoffLoader64CheckImageType ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_NT_HEADERS64 *PeHdr + ) +/*++ + +Routine Description: + Checks the PE header of a PE/COFF image to determine if it supported + +Arguments: + ImageContext - The context of the image being loaded + PeHdr - The buffer in which to return the PE header + +Returns: + EFI_SUCCESS if the PE/COFF image is supported + EFI_UNSUPPORTED of the PE/COFF image is not supported. + +--*/ +{ + // + // Check the PE/COFF Header SIgnature + // + if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE; + return EFI_UNSUPPORTED; + } + + // + // See if the machine type is supported. We support a native machine type (IA-32/Itanium-based) + // and the machine type for the Virtual Machine. + // + ImageContext->Machine = PeHdr->FileHeader.Machine; + if (!(IMAGE_64_MACHINE_TYPE_SUPPORTED (ImageContext->Machine))) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE; + return EFI_UNSUPPORTED; + } + + // + // See if the image type is supported. We support EFI Applications, + // EFI Boot Service Drivers, and EFI Runtime Drivers. + // + ImageContext->ImageType = PeHdr->OptionalHeader.Subsystem; + switch (ImageContext->ImageType) { + + case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: + ImageContext->ImageCodeMemoryType = EfiLoaderCode; + ImageContext->ImageDataMemoryType = EfiLoaderData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: + ImageContext->ImageCodeMemoryType = EfiBootServicesCode; + ImageContext->ImageDataMemoryType = EfiBootServicesData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER: + ImageContext->ImageCodeMemoryType = EfiRuntimeServicesCode; + ImageContext->ImageDataMemoryType = EfiRuntimeServicesData; + break; + + default: + ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM; + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PeCoffLoader64GetImageInfo ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + Retrieves information on a PE/COFF image + +Arguments: + ImageContext - The context of the image being loaded + PeHdr - The buffer in which to return the PE header + +Returns: + EFI_SUCCESS if the information on the PE/COFF image was collected. + EFI_UNSUPPORTED of the PE/COFF image is not supported. + Otherwise, the error status from reading the PE/COFF image using the + ImageContext->ImageRead() function + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_NT_HEADERS64 PeHdr; + EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry; + UINTN Size; + UINTN Index; + UINTN DebugDirectoryEntryRva; + UINTN DebugDirectoryEntryFileOffset; + UINTN SectionHeaderOffset; + EFI_IMAGE_SECTION_HEADER SectionHeader; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry; + + if (NULL == ImageContext) { + return EFI_INVALID_PARAMETER; + } + + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + Status = PeCoffLoader64GetPeHeader (ImageContext, &PeHdr); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Verify machine type + // + Status = PeCoffLoader64CheckImageType (ImageContext, &PeHdr); + if (EFI_ERROR(Status)) { + return Status; + } + + // + // Retrieve the base address of the image + // + ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase; + + // + // Initialize the alternate destination address to 0 indicating that it + // should not be used. + // + ImageContext->DestinationAddress = 0; + + // + // Initialize the codeview pointer. + // + ImageContext->CodeView = NULL; + ImageContext->PdbPointer = NULL; + + // + // Three cases with regards to relocations: + // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable + // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable + // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but + // has no base relocs to apply + // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid. + // + // Look at the file header to determine if relocations have been stripped, and + // save this info in the image context for later use. + // + if (PeHdr.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) { + ImageContext->RelocationsStripped = TRUE; + } else { + ImageContext->RelocationsStripped = FALSE; + } + + ImageContext->ImageSize = (UINT64)PeHdr.OptionalHeader.SizeOfImage; + ImageContext->SectionAlignment = PeHdr.OptionalHeader.SectionAlignment; + ImageContext->SizeOfHeaders = PeHdr.OptionalHeader.SizeOfHeaders; + + // + // Modify ImageSize to contain .PDB file name if required and initialize + // PdbRVA field... + // + + if (PeHdr.OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) + &(PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + + // + // Determine the file offset of the debug directory... This means we walk + // the sections to find which section contains the RVA of the debug + // directory + // + + DebugDirectoryEntryFileOffset = 0; + + SectionHeaderOffset = (UINTN) ( + ImageContext->PeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + PeHdr.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < PeHdr.FileHeader.NumberOfSections; Index += 1) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData; + break; + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset, + &Size, + &DebugEntry + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) { + ImageContext->ImageSize += DebugEntry.SizeOfData; + } + return EFI_SUCCESS; + } + } + } + } + return EFI_SUCCESS; +} + +static +VOID * +PeCoffLoader64ImageAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ) +/*++ + +Routine Description: + Converts an image address to the loaded address + +Arguments: + ImageContext - The context of the image being loaded + Address - The address to be converted to the loaded address + +Returns: + NULL if the address can not be converted, otherwise, the converted address + +--*/ +{ + if (Address >= ImageContext->ImageSize) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return NULL; + } + return (CHAR8 *)((UINTN)ImageContext->ImageAddress + Address); +} + +EFI_STATUS +EFIAPI +PeCoffLoader64RelocateImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + Relocates a PE/COFF image in memory + +Arguments: + ImageContext - Contains information on the loaded image to relocate + +Returns: + EFI_SUCCESS if the PE/COFF image was relocated + EFI_LOAD_ERROR if the image is not a valid PE/COFF image + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_NT_HEADERS64 *PeHdr; + EFI_IMAGE_DATA_DIRECTORY *RelocDir; + IN UINT64 Adjust; + EFI_IMAGE_BASE_RELOCATION *RelocBase; + EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; + UINT16 *Reloc; + UINT16 *RelocEnd; + CHAR8 *Fixup; + CHAR8 *FixupBase; + UINT16 *F16; + UINT32 *F32; + CHAR8 *FixupData; + EFI_PHYSICAL_ADDRESS BaseAddress; + + + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + // + // If there are no relocation entries, then we are done + // + if (ImageContext->RelocationsStripped) { + return EFI_SUCCESS; + } + + // + // If the destination address is not 0, use that rather than the + // image address as the relocation target. + // + if (ImageContext->DestinationAddress) { + BaseAddress = ImageContext->DestinationAddress; + } else { + BaseAddress = ImageContext->ImageAddress; + } + PeHdr = (EFI_IMAGE_NT_HEADERS64 *)((UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset); + Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase; + + PeHdr->OptionalHeader.ImageBase = (UINTN) BaseAddress; + + // + // Find the relocation block + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + RelocDir = &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + RelocBase = PeCoffLoader64ImageAddress (ImageContext, RelocDir->VirtualAddress); + RelocBaseEnd = PeCoffLoader64ImageAddress ( + ImageContext, + RelocDir->VirtualAddress + RelocDir->Size - 1 + ); +} else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = 0; + } + // + // Run the relocation information and apply the fixups + // + FixupData = ImageContext->FixupData; + while (RelocBase < RelocBaseEnd) { + + Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof(EFI_IMAGE_BASE_RELOCATION)); + RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock); + FixupBase = PeCoffLoader64ImageAddress (ImageContext, RelocBase->VirtualAddress); + if ((CHAR8 *) RelocEnd < (CHAR8 *)((UINTN)ImageContext->ImageAddress) || + (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + + (UINTN)ImageContext->ImageSize)) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return EFI_LOAD_ERROR; + } + + // + // Run this relocation record + // + while (Reloc < RelocEnd) { + + Fixup = FixupBase + (*Reloc & 0xFFF); + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + case EFI_IMAGE_REL_BASED_HIGH: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16)((*F16 << 16) + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof(UINT16); + } + break; + case EFI_IMAGE_REL_BASED_LOW: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16)(*F16 + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof(UINT16); + } + break; + case EFI_IMAGE_REL_BASED_HIGHLOW: + F32 = (UINT32 *) Fixup; + *F32 = *F32 + (UINT32) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER(FixupData, sizeof(UINT32)); + *(UINT32 *) FixupData = *F32; + FixupData = FixupData + sizeof(UINT32); + } + break; + case EFI_IMAGE_REL_BASED_HIGHADJ: + // Return the same EFI_UNSUPPORTED return code as + // PeCoffLoader64RelocateImageEx() returns if it does not recognize + // the relocation type. + // + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return EFI_UNSUPPORTED; + default: + Status = PeCoffLoader64RelocateImageEx (Reloc, Fixup, &FixupData, Adjust); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return Status; + } + } + + // + // Next relocation record + // + Reloc += 1; + } + + // + // Next reloc block + // + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeCoffLoader64RelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + Performs an IA-32 specific relocation fixup + +Arguments: + Reloc - Pointer to the relocation record + Fixup - Pointer to the address to fix up + FixupData - Pointer to a buffer to log the fixups + Adjust - The offset to adjust the fixup + +Returns: + None + +--*/ +{ + UINT64 *F64; + + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_DIR64: + F64 = (UINT64 *) Fixup; + *F64 = *F64 + (UINT64) Adjust; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + default: + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + + + +EFI_STATUS +EFIAPI +PeCoffLoader64LoadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + Loads a PE/COFF image into memory + +Arguments: + ImageContext - Contains information on image to load into memory + +Returns: + EFI_SUCCESS if the PE/COFF image was loaded + EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer + EFI_LOAD_ERROR if the image is a runtime driver with no relocations + EFI_INVALID_PARAMETER if the image address is invalid + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_NT_HEADERS64 *PeHdr; + PE_COFF_LOADER_IMAGE_CONTEXT CheckContext; + EFI_IMAGE_SECTION_HEADER *FirstSection; + EFI_IMAGE_SECTION_HEADER *Section; + UINTN Index; + CHAR8 *Base; + CHAR8 *End; + CHAR8 *MaxEnd; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN Size; + UINT32 TempDebugEntryRva; + + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + // + // Copy the provided context info into our local version, get what we + // can from the original image, and then use that to make sure everything + // is legit. + // + CopyMem ( + &CheckContext, + ImageContext, + sizeof (PE_COFF_LOADER_IMAGE_CONTEXT) + ); + + Status = PeCoffLoader64GetImageInfo ( + This, + &CheckContext + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure there is enough allocated space for the image being loaded + // + if (ImageContext->ImageSize < CheckContext.ImageSize) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE; + return EFI_BUFFER_TOO_SMALL; + } + + // + // If there's no relocations, then make sure it's not a runtime driver, + // and that it's being loaded at the linked address. + // + if (CheckContext.RelocationsStripped == TRUE) { + // + // If the image does not contain relocations and it is a runtime driver + // then return an error. + // + if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM; + return EFI_LOAD_ERROR; + } + // + // If the image does not contain relocations, and the requested load address + // is not the linked address, then return an error. + // + if (CheckContext.ImageAddress != ImageContext->ImageAddress) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return EFI_INVALID_PARAMETER; + } + } + + // + // Make sure the allocated space has the proper section alignment + // + if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT; + return EFI_INVALID_PARAMETER; + } + + // + // Read the entire PE/COFF header into memory + // + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (VOID *)(UINTN)ImageContext->ImageAddress + ); + if (EFI_ERROR(Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return EFI_LOAD_ERROR; + } + + PeHdr = (EFI_IMAGE_NT_HEADERS64 *) + ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset); + + // + // Load each section of the image + // + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + PeHdr->FileHeader.SizeOfOptionalHeader + ); + + Section = FirstSection; + for ( Index=0, MaxEnd = NULL; + Index < PeHdr->FileHeader.NumberOfSections; + Index += 1) { + + // + // Compute sections address + // + Base = PeCoffLoader64ImageAddress (ImageContext, Section->VirtualAddress); + End = PeCoffLoader64ImageAddress ( + ImageContext, + Section->VirtualAddress + Section->Misc.VirtualSize - 1); + if (End > MaxEnd) { + MaxEnd = End; + } + // + // If the base start or end address resolved to 0, then fail. + // + if (!Base || !End) { + ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED; + return EFI_LOAD_ERROR; + } + + // + // Read the section, we can resume the length of PE image can't + // exceed the max 32bit integer + // + Size = (UINTN) Section->Misc.VirtualSize; + if ((Size == 0) || (Size > Section->SizeOfRawData)) { + Size = (UINTN) Section->SizeOfRawData; + } + if (Section->SizeOfRawData) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData, + &Size, + Base); + if (EFI_ERROR(Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + } + + // + // If raw size is less then virt size, zero fill the remaining + // + + if (Size < Section->Misc.VirtualSize) { + ZeroMem (Base + Size, Section->Misc.VirtualSize - (UINTN)Size); + } + + // + // Next Section + // + Section += 1; + } + + // + // Get image's entry point + // + ImageContext->EntryPoint = + (EFI_PHYSICAL_ADDRESS) (UINTN) PeCoffLoader64ImageAddress ( + ImageContext, + PeHdr->OptionalHeader.AddressOfEntryPoint + ); + + // + // Determine the size of the fixup data + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) + &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + ImageContext->FixupDataSize = + DirectoryEntry->Size / sizeof(UINT16) * sizeof(UINTN); + } else { + ImageContext->FixupDataSize = 0; + } + // + // Consumer must allocate a buffer for the relocation fixup log. + // Only used for runtime drivers. + // + ImageContext->FixupData = NULL; + + // + // Load the Codeview info if present + // + if (ImageContext->DebugDirectoryEntryRva != 0) { + DebugEntry = PeCoffLoader64ImageAddress ( + ImageContext, + ImageContext->DebugDirectoryEntryRva + ); + if (DebugEntry != NULL) { + TempDebugEntryRva = DebugEntry->RVA; + if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) { + Section--; + if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) { + TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize; + } else { + TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData; + } + } + if (TempDebugEntryRva != 0) { + ImageContext->CodeView = PeCoffLoader64ImageAddress (ImageContext, TempDebugEntryRva); + if (ImageContext->CodeView == NULL) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return EFI_LOAD_ERROR; + } + + if (DebugEntry->RVA == 0) { + Size = (UINTN) DebugEntry->SizeOfData; + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset, + &Size, + ImageContext->CodeView + ); + if (EFI_ERROR(Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return EFI_LOAD_ERROR; + } + DebugEntry->RVA = TempDebugEntryRva; + } + + switch (* (UINT32 *) ImageContext->CodeView) { + case CODEVIEW_SIGNATURE_NB10: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + case CODEVIEW_SIGNATURE_RSDS: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + default: + break; + } + } + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +PeCoffLoader64UnloadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + Unload of images is not supported + +Arguments: + ImageContext - The image to unload + +Returns: + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; +} + +EFI_PEI_PE_COFF_LOADER_PROTOCOL * +EFIAPI +GetPeCoffLoaderX64Protocol ( + ) +{ + return &mPeCoffLoaderX64; +} + + diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.mbd b/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.mbd new file mode 100644 index 0000000000..8b6f365014 --- /dev/null +++ b/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.mbd @@ -0,0 +1,30 @@ + + + + + EdkPeCoffLoaderX64Lib + 6aac37f2-7b46-4ef3-8645-c24800a3d410 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-04-03 23:59 + 2006-04-05 21:30 + + diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.msa b/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.msa new file mode 100644 index 0000000000..964ae551c9 --- /dev/null +++ b/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/EdkPeCoffLoaderX64Lib.msa @@ -0,0 +1,46 @@ + + + + + EdkPeCoffLoaderX64Lib + PEIM + LIBRARY + 6aac37f2-7b46-4ef3-8645-c24800a3d410 + EDK_RELEASE_VERSION 0x00020000 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-03 23:59 + 2006-04-05 21:30 + + + EdkPeCoffLoaderX64Lib + BaseMemoryLib + PeCoffLib + + + EdkPeCoffLoaderX64.c + + + MdePkg + EdkModulePkg + + diff --git a/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/build.xml b/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/build.xml new file mode 100644 index 0000000000..c72e03e73e --- /dev/null +++ b/EdkModulePkg/Library/EdkPeCoffLoaderX64Lib/build.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkPeiPerformanceLib/EdkPeiPerformanceLib.mbd b/EdkModulePkg/Library/EdkPeiPerformanceLib/EdkPeiPerformanceLib.mbd new file mode 100644 index 0000000000..103f7c4466 --- /dev/null +++ b/EdkModulePkg/Library/EdkPeiPerformanceLib/EdkPeiPerformanceLib.mbd @@ -0,0 +1,29 @@ + + + + + EdkPeiPerformanceLib + F72DE735-B24F-4ef6-897F-70A85D01A047 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2006, 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. + + 2006-04-04 11:12 + + diff --git a/EdkModulePkg/Library/EdkPeiPerformanceLib/EdkPeiPerformanceLib.msa b/EdkModulePkg/Library/EdkPeiPerformanceLib/EdkPeiPerformanceLib.msa new file mode 100644 index 0000000000..9c2eda7216 --- /dev/null +++ b/EdkModulePkg/Library/EdkPeiPerformanceLib/EdkPeiPerformanceLib.msa @@ -0,0 +1,61 @@ + + + + + EdkPeiPerformanceLib + PEIM + LIBRARY + F72DE735-B24F-4ef6-897F-70A85D01A047 + EDK_RELEASE_VERSION 0x00020000 + Memory-only library functions with no library constructor/destructor + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-04 11:12 + + + PerformanceLib + DebugLib + HobLib + BaseLib + TimerLib + PcdLib + BaseMemoryLib + + + PeiPerformanceLib.c + + + MdePkg + EdkModulePkg + + + + PeiPerformanceHob + + + + + PcdPerformanceLibraryPropertyMask + 0x00000001 + UINT8 + + + diff --git a/EdkModulePkg/Library/EdkPeiPerformanceLib/PeiPerformanceLib.c b/EdkModulePkg/Library/EdkPeiPerformanceLib/PeiPerformanceLib.c new file mode 100644 index 0000000000..89e2dd3c94 --- /dev/null +++ b/EdkModulePkg/Library/EdkPeiPerformanceLib/PeiPerformanceLib.c @@ -0,0 +1,315 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeiPerformanceLib.c + +Abstract: + + Performance Library + +--*/ + +/** + Gets PEI the GUID HOB for PEI performance. + + This internal function searches for the GUID HOB for PEI performance. + If that GUID HOB is not found, it will build a new one. + It returns the data area of that GUID HOB to record performance log. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + + @retval The index of log entry in the array. + +**/ +PEI_PERFORMANCE_LOG_HEADER * +InternalGetPerformanceHobLog ( + VOID + ) +{ + EFI_HOB_GUID_TYPE *GuidHob; + PEI_PERFORMANCE_LOG_HEADER *PeiPerformanceLog; + UINTN PeiPerformanceLogSize; + + GuidHob = GetFirstGuidHob (&gPeiPerformanceHobGuid); + + if (GuidHob != NULL) { + // + // PEI Performance HOB was found, then return the existing one. + // + PeiPerformanceLog = GET_GUID_HOB_DATA (GuidHob); + } else { + // + // PEI Performance HOB was not found, then build one. + // + PeiPerformanceLogSize = sizeof (PEI_PERFORMANCE_LOG_HEADER) + + sizeof (PEI_PERFORMANCE_LOG_ENTRY) * MAX_PEI_PERFORMANCE_LOG_ENTRIES; + PeiPerformanceLog = BuildGuidHob (&gPeiPerformanceHobGuid, PeiPerformanceLogSize); + PeiPerformanceLog = ZeroMem (PeiPerformanceLog, PeiPerformanceLogSize); + } + + return PeiPerformanceLog; +} + +/** + Searches in the log array with keyword Handle, Token and Module. + + This internal function searches for the log entry in the log array. + If there is an entry that exactly matches the given key word triple + and its end time stamp is zero, then the index of that log entry is returned; + otherwise, the the number of log entries in the array is returned. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + + @retval The index of log entry in the array. + +**/ +UINT32 +InternalSearchForLogEntry ( + IN PEI_PERFORMANCE_LOG_HEADER *PeiPerformanceLog, + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module OPTIONAL + ) +{ + UINT32 Index; + UINT32 NumberOfEntries; + PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray; + + + if (Token == NULL) { + Token = ""; + } + if (Module == NULL) { + Module = ""; + } + NumberOfEntries = PeiPerformanceLog->NumberOfEntries; + LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1); + + for (Index = 0; Index < NumberOfEntries; Index++) { + if ((LogEntryArray[Index].Handle == (EFI_PHYSICAL_ADDRESS) (UINTN) Handle) && + AsciiStrnCmp (LogEntryArray[Index].Token, Token, PEI_PERFORMANCE_STRING_LENGTH) == 0 && + AsciiStrnCmp (LogEntryArray[Index].Module, Module, PEI_PERFORMANCE_STRING_LENGTH) == 0 && + LogEntryArray[Index].EndTimeStamp == 0 + ) { + break; + } + } + return Index; +} + +/** + Creates a record for the beginning of a performance measurement. + + Creates a record that contains the Handle, Token, and Module. + If TimeStamp is not zero, then TimeStamp is added to the record as the start time. + If TimeStamp is zero, then this function reads the current time stamp + and adds that time stamp value to the record as the start time. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The start of the measurement was recorded. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement. + +**/ +RETURN_STATUS +EFIAPI +StartPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ) +{ + PEI_PERFORMANCE_LOG_HEADER *PeiPerformanceLog; + PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray; + UINT32 Index; + + PeiPerformanceLog = InternalGetPerformanceHobLog (); + + if (PeiPerformanceLog->NumberOfEntries >= MAX_PEI_PERFORMANCE_LOG_ENTRIES) { + return RETURN_OUT_OF_RESOURCES; + } + Index = PeiPerformanceLog->NumberOfEntries++; + LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1); + LogEntryArray[Index].Handle = (EFI_PHYSICAL_ADDRESS) (UINTN) Handle; + + if (Token != NULL) { + AsciiStrnCpy (LogEntryArray[Index].Token, Token, PEI_PERFORMANCE_STRING_LENGTH); + } + if (Module != NULL) { + AsciiStrnCpy (LogEntryArray[Index].Module, Module, PEI_PERFORMANCE_STRING_LENGTH); + } + + if (TimeStamp == 0) { + TimeStamp = GetPerformanceCounter (); + } + LogEntryArray[Index].StartTimeStamp = TimeStamp; + + return RETURN_SUCCESS; +} + +/** + Fills in the end time of a performance measurement. + + Looks up the record that matches Handle, Token, and Module. + If the record can not be found then return RETURN_NOT_FOUND. + If the record is found and TimeStamp is not zero, + then TimeStamp is added to the record as the end time. + If the record is found and TimeStamp is zero, then this function reads + the current time stamp and adds that time stamp value to the record as the end time. + If this function is called multiple times for the same record, then the end time is overwritten. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The end of the measurement was recorded. + @retval RETURN_NOT_FOUND The specified measurement record could not be found. + +**/ +RETURN_STATUS +EFIAPI +EndPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ) +{ + PEI_PERFORMANCE_LOG_HEADER *PeiPerformanceLog; + PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray; + UINT32 Index; + + if (TimeStamp == 0) { + TimeStamp = GetPerformanceCounter (); + } + + PeiPerformanceLog = InternalGetPerformanceHobLog (); + Index = InternalSearchForLogEntry (PeiPerformanceLog, Handle, Token, Module); + if (Index >= PeiPerformanceLog->NumberOfEntries) { + return RETURN_NOT_FOUND; + } + LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1); + LogEntryArray[Index].EndTimeStamp = TimeStamp; + + return RETURN_SUCCESS; +} + +/** + Retrieves a previously logged performance measurement. + + Looks up the record that matches Handle, Token, and Module. + If the record can not be found then return RETURN_NOT_FOUND. + If the record is found then the start of the measurement is returned in StartTimeStamp, + and the end of the measurement is returned in EndTimeStamp. + + @param LogEntryKey The key for the previous performance measurement log entry. + If 0, then the first performance measurement log entry is retrieved. + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param StartTimeStamp The 64-bit time stamp that was recorded when the measurement was started. + @param EndTimeStamp The 64-bit time stamp that was recorded when the measurement was ended. + + @return The key for the current performance log entry. + +**/ +UINTN +EFIAPI +GetPerformanceMeasurement ( + UINTN LogEntryKey, + OUT CONST VOID **Handle, + OUT CONST CHAR8 **Token, + OUT CONST CHAR8 **Module, + OUT UINT64 *StartTimeStamp, + OUT UINT64 *EndTimeStamp + ) +{ + PEI_PERFORMANCE_LOG_HEADER *PeiPerformanceLog; + PEI_PERFORMANCE_LOG_ENTRY *CurrentLogEntry; + PEI_PERFORMANCE_LOG_ENTRY *LogEntryArray; + UINTN NumberOfEntries; + + ASSERT (Handle != NULL); + ASSERT (Token != NULL); + ASSERT (Module != NULL); + ASSERT (StartTimeStamp != NULL); + ASSERT (EndTimeStamp != NULL); + + PeiPerformanceLog = InternalGetPerformanceHobLog (); + + NumberOfEntries = (UINTN) (PeiPerformanceLog->NumberOfEntries); + LogEntryArray = (PEI_PERFORMANCE_LOG_ENTRY *) (PeiPerformanceLog + 1); + // + // Make sure that LogEntryKey is a valid log entry key. + // + ASSERT (LogEntryKey <= NumberOfEntries); + + if (LogEntryKey == NumberOfEntries) { + return 0; + } + + CurrentLogEntry = &(LogEntryArray[LogEntryKey++]); + + *Handle = (VOID *) (UINTN) (CurrentLogEntry->Handle); + *Token = CurrentLogEntry->Token; + *Module = CurrentLogEntry->Module; + *StartTimeStamp = CurrentLogEntry->StartTimeStamp; + *EndTimeStamp = CurrentLogEntry->EndTimeStamp; + + return LogEntryKey; +} + +/** + Returns TRUE if the performance measurement macros are enabled. + + This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. + @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is clear. + +**/ +BOOLEAN +EFIAPI +PerformanceMeasurementEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0); +} diff --git a/EdkModulePkg/Library/EdkPeiPerformanceLib/build.xml b/EdkModulePkg/Library/EdkPeiPerformanceLib/build.xml new file mode 100644 index 0000000000..8b476daa7e --- /dev/null +++ b/EdkModulePkg/Library/EdkPeiPerformanceLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.c b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.c new file mode 100644 index 0000000000..d72aae11a3 --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.c @@ -0,0 +1,397 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BsDataHubStatusCode.c + +Abstract: + + This implements a status code listener that logs status codes into the data + hub. This is only active during non-runtime DXE. + +--*/ +#include "BsDataHubStatusCode.h" + +// +// Globals only work at BootService Time. NOT at Runtime! +// +static EFI_DATA_HUB_PROTOCOL *mDataHub; +static LIST_ENTRY mRecordBuffer; +static INTN mRecordNum; +static EFI_EVENT mLogDataHubEvent; +static EFI_LOCK mStatusCodeReportLock; +static BOOLEAN mEventHandlerActive = FALSE; + +STATUS_CODE_RECORD_LIST * +GetRecordBuffer ( + VOID + ) +/*++ + +Routine Description: + + Returned buffer of length BYTES_PER_RECORD + +Arguments: + + None + +Returns: + + Entry in mRecordBuffer or NULL if non available + +--*/ +{ + STATUS_CODE_RECORD_LIST *Buffer; + + gBS->AllocatePool (EfiBootServicesData, sizeof (STATUS_CODE_RECORD_LIST), (VOID **) &Buffer); + if (Buffer == NULL) { + return NULL; + } + + ZeroMem (Buffer, sizeof (STATUS_CODE_RECORD_LIST)); + Buffer->Signature = BS_DATA_HUB_STATUS_CODE_SIGNATURE; + + return Buffer; +} + +DATA_HUB_STATUS_CODE_DATA_RECORD * +AquireEmptyRecordBuffer ( + VOID + ) +/*++ + +Routine Description: + + Allocate a mRecordBuffer entry in the form of a pointer. + +Arguments: + + None + +Returns: + + Pointer to new buffer. NULL if none exist. + +--*/ +{ + STATUS_CODE_RECORD_LIST *DataBuffer; + + if (mRecordNum < MAX_RECORD_NUM) { + DataBuffer = GetRecordBuffer (); + if (DataBuffer != NULL) { + EfiAcquireLock (&mStatusCodeReportLock); + InsertTailList (&mRecordBuffer, &DataBuffer->Link); + mRecordNum++; + EfiReleaseLock (&mStatusCodeReportLock); + return (DATA_HUB_STATUS_CODE_DATA_RECORD *) DataBuffer->RecordBuffer; + } + } + + return NULL; +} + +EFI_STATUS +ReleaseRecordBuffer ( + IN STATUS_CODE_RECORD_LIST *RecordBuffer + ) +/*++ + +Routine Description: + + Release a mRecordBuffer entry allocated by AquireEmptyRecordBuffer (). + +Arguments: + + RecordBuffer - Data to free + +Returns: + + EFI_SUCCESS - If DataRecord is valid + EFI_UNSUPPORTED - The record list has empty + +--*/ +{ + ASSERT (RecordBuffer != NULL); + if (mRecordNum <= 0) { + return EFI_UNSUPPORTED; + } + + EfiAcquireLock (&mStatusCodeReportLock); + RemoveEntryList (&RecordBuffer->Link); + mRecordNum--; + EfiReleaseLock (&mStatusCodeReportLock); + gBS->FreePool (RecordBuffer); + return EFI_SUCCESS; +} + +EFI_STATUS +BsDataHubReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +/*++ + +Routine Description: + + Boot service report status code listener. This function logs the status code + into the data hub. + +Arguments: + + Same as ReportStatusCode (See Tiano Runtime Specification) + +Returns: + + None + +--*/ +{ + DATA_HUB_STATUS_CODE_DATA_RECORD *DataHub; + UINT32 ErrorLevel; + VA_LIST Marker; + CHAR8 *Format; + UINTN Index; + CHAR16 FormatBuffer[BYTES_PER_RECORD]; + + if (EfiAtRuntime ()) { + // + // For now all we do is post code at runtime + // + return EFI_SUCCESS; + } + // + // If we had an error while in our event handler, then do nothing so + // that we don't get in an endless loop. + // + if (mEventHandlerActive) { + return EFI_SUCCESS; + } + + DataHub = (DATA_HUB_STATUS_CODE_DATA_RECORD *) AquireEmptyRecordBuffer (); + if (DataHub == NULL) { + // + // There are no empty record buffer in private buffers + // + return EFI_OUT_OF_RESOURCES; + } + // + // Construct Data Hub Extended Data + // + DataHub->CodeType = CodeType; + DataHub->Value = Value; + DataHub->Instance = Instance; + + if (CallerId != NULL) { + CopyMem (&DataHub->CallerId, CallerId, sizeof (EFI_GUID)); + } else { + ZeroMem (&DataHub->CallerId, sizeof (EFI_GUID)); + } + + if (Data == NULL) { + ZeroMem (&DataHub->Data, sizeof (EFI_STATUS_CODE_DATA)); + } else { + // + // Copy generic Header + // + CopyMem (&DataHub->Data, Data, sizeof (EFI_STATUS_CODE_DATA)); + + if (ReportStatusCodeExtractDebugInfo (Data, &ErrorLevel, &Marker, &Format)) { + // + // Convert Ascii Format string to Unicode. + // + for (Index = 0; Format[Index] != '\0' && Index < (BYTES_PER_RECORD - 1); Index += 1) { + FormatBuffer[Index] = (CHAR16) Format[Index]; + } + + FormatBuffer[Index] = L'\0'; + + // + // Put processed string into the buffer + // + Index = UnicodeVSPrint ( + (CHAR16 *) (DataHub + 1), + BYTES_PER_RECORD - (sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD)), + FormatBuffer, + Marker + ); + + // + // DATA_HUB_STATUS_CODE_DATA_RECORD followed by VSPrint String Buffer + // + DataHub->Data.Size = (UINT16) (Index * sizeof (CHAR16)); + + } else { + // + // Default behavior is to copy optional data + // + if (Data->Size > (BYTES_PER_RECORD - sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD))) { + DataHub->Data.Size = (UINT16) (BYTES_PER_RECORD - sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD)); + } + + CopyMem (DataHub + 1, Data + 1, DataHub->Data.Size); + } + } + + gBS->SignalEvent (mLogDataHubEvent); + + return EFI_SUCCESS; +} + +VOID +EFIAPI +LogDataHubEventHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + The Event handler which will be notified to log data in Data Hub. + +Arguments: + + Event - Instance of the EFI_EVENT to signal whenever data is + available to be logged in the system. + Context - Context of the event. + +Returns: + + None. + +--*/ +{ + EFI_STATUS Status; + DATA_HUB_STATUS_CODE_DATA_RECORD *DataRecord; + UINTN Size; + UINT64 DataRecordClass; + LIST_ENTRY *Link; + STATUS_CODE_RECORD_LIST *BufferEntry; + + // + // Set our global flag so we don't recurse if we get an error here. + // + mEventHandlerActive = TRUE; + + // + // Log DataRecord in Data Hub. + // If there are multiple DataRecords, Log all of them. + // + for (Link = mRecordBuffer.ForwardLink; Link != &mRecordBuffer;) { + BufferEntry = CR (Link, STATUS_CODE_RECORD_LIST, Link, BS_DATA_HUB_STATUS_CODE_SIGNATURE); + DataRecord = (DATA_HUB_STATUS_CODE_DATA_RECORD *) (BufferEntry->RecordBuffer); + Link = Link->ForwardLink; + + // + // Add in the size of the header we added. + // + Size = sizeof (DATA_HUB_STATUS_CODE_DATA_RECORD) + DataRecord->Data.Size; + + if ((DataRecord->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + } else if ((DataRecord->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_ERROR; + } else if ((DataRecord->CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { + DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG; + } else { + // + // Should never get here. + // + DataRecordClass = EFI_DATA_RECORD_CLASS_DEBUG | + EFI_DATA_RECORD_CLASS_ERROR | + EFI_DATA_RECORD_CLASS_DATA | + EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + } + + if (((DataRecord->Instance & EFI_D_ERROR) != 0) && + (((DataRecord->Instance & EFI_D_POOL) != 0) || ((DataRecord->Instance & EFI_D_PAGE) != 0)) + ) { + // + // If memory error, do not call LogData (). + // + DebugPrint ((UINTN)-1, "Memory Error\n"); + Status = EFI_OUT_OF_RESOURCES; + } else { + // + // Log DataRecord in Data Hub + // + Status = mDataHub->LogData ( + mDataHub, + &gEfiStatusCodeGuid, + &gEfiStatusCodeRuntimeProtocolGuid, + DataRecordClass, + DataRecord, + (UINT32) Size + ); + } + + ReleaseRecordBuffer (BufferEntry); + } + + mEventHandlerActive = FALSE; + + return ; +} + +VOID +BsDataHubStatusCodeInitialize ( + VOID + ) +/*++ + +Routine Description: + + Install a data hub listener. + +Arguments: + + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + EFI_SUCCESS - Logging Hub protocol installed + Other - No protocol installed, unload driver. + +--*/ +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **) &mDataHub); + // + // Should never fail due to dependency grammer + // + ASSERT_EFI_ERROR (Status); + + // + // Initialize FIFO + // + InitializeListHead (&mRecordBuffer); + mRecordNum = 0; + + EfiInitializeLock (&mStatusCodeReportLock, EFI_TPL_HIGH_LEVEL); + + // + // Create a Notify Event to log data in Data Hub + // + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + LogDataHubEventHandler, + NULL, + &mLogDataHubEvent + ); + +} diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.h b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.h new file mode 100644 index 0000000000..f15a90e5e2 --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.h @@ -0,0 +1,130 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BsDataHubStatusCode.h + +Abstract: + + Header for the status code data hub logging component + +--*/ + +#ifndef _EFI_BS_DATA_HUB_STATUS_CODE_H_ +#define _EFI_BS_DATA_HUB_STATUS_CODE_H_ + +// +// Private data declarations +// +#define MAX_RECORD_NUM 1000 +#define BYTES_PER_RECORD EFI_STATUS_CODE_DATA_MAX_SIZE +#define EMPTY_RECORD_TAG 0xFF + +#define BS_DATA_HUB_STATUS_CODE_SIGNATURE EFI_SIGNATURE_32 ('B', 'D', 'H', 'S') + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + UINT8 RecordBuffer[BYTES_PER_RECORD]; +} STATUS_CODE_RECORD_LIST; + +// +// Function prototypes +// +STATUS_CODE_RECORD_LIST * +GetRecordBuffer ( + VOID + ) +; + +/*++ + +Routine Description: + + Returned buffer of length BYTES_PER_RECORD + +Arguments: + + None + +Returns: + + Entry in mRecordBuffer or NULL if non available + +--*/ +DATA_HUB_STATUS_CODE_DATA_RECORD * +AquireEmptyRecordBuffer ( + VOID + ) +; + +/*++ + +Routine Description: + + Allocate a mRecordBuffer entry in the form of a pointer. + +Arguments: + + None + +Returns: + + Pointer to new buffer. NULL if none exist. + +--*/ +EFI_STATUS +ReleaseRecordBuffer ( + IN STATUS_CODE_RECORD_LIST *RecordBuffer + ) +; + +/*++ + +Routine Description: + + Release a mRecordBuffer entry allocated by AquireEmptyRecordBuffer (). + +Arguments: + + RecordBuffer - Data to free + +Returns: + + EFI_SUCCESS - If RecordBuffer is valid + EFI_UNSUPPORTED - The record list has empty + +--*/ +VOID +EFIAPI +LogDataHubEventHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +/*++ + +Routine Description: + + Event Handler that log in Status code in Data Hub. + +Arguments: + + (Standard EFI Event Handler - EFI_EVENT_NOTIFY) + +Returns: + + NONE + +--*/ +#endif diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.mbd b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.mbd new file mode 100644 index 0000000000..ce1bd63b0d --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.mbd @@ -0,0 +1,30 @@ + + + + + EdkBsDataHubStatusCodeLib + 041bf780-dc3e-49ab-8d67-4b86075440ea + 0 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.msa b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.msa new file mode 100644 index 0000000000..7eff726640 --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/BsDataHubStatusCode.msa @@ -0,0 +1,72 @@ + + + + + EdkBsDataHubStatusCodeLib + DXE_DRIVER + LIBRARY + 041bf780-dc3e-49ab-8d67-4b86075440ea + 0 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + EdkBsDataHubStatusCodeLib + UefiLib + DebugLib + BaseLib + BaseMemoryLib + DxeRuntimeDriverLib + ReportStatusCodeLib + PrintLib + UefiBootServicesTableLib + + + BsDataHubStatusCode.c + BsDataHubStatusCode.h + + + MdePkg + EdkModulePkg + + + StatusCode + DataHub + + + + + EFI_EVENT_NOTIFY_SIGNAL + + + + + gEfiStatusCodeGuid + + + + StatusCode + + + diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/build.xml b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/build.xml new file mode 100644 index 0000000000..308ca95b11 --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/BsDataHubStatusCode/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/RtMemoryStatusCode.c b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/RtMemoryStatusCode.c new file mode 100644 index 0000000000..375a338a85 --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/RtMemoryStatusCode.c @@ -0,0 +1,188 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RtMemoryStatusCode.c + +Abstract: + + EFI lib to provide memory journal status code reporting routines. + +--*/ + +#include + +// +// Global variables +// +PEI_STATUS_CODE_MEMORY_PPI mStatusCodeMemoryPpi = { 0, 0, 0, 0 }; + +// +// Function implementations +// +EFI_STATUS +RtMemoryReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +/*++ + +Routine Description: + + Log a status code to a memory journal. If no memory journal exists, + we will just return. + +Arguments: + + Same as ReportStatusCode AP + +Returns: + + EFI_SUCCESS This function always returns success + +--*/ +{ + EFI_STATUS_CODE_ENTRY *CurrentEntry; + UINTN MaxEntry; + + // + // We don't care to log debug codes. + // + if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { + return EFI_SUCCESS; + } + // + // Update the latest entry in the journal. + // + MaxEntry = mStatusCodeMemoryPpi.Length / sizeof (EFI_STATUS_CODE_ENTRY); + if (!MaxEntry) { + // + // If we don't have any entries, then we can return. + // This effectively means that no memory buffer was passed forward from PEI. + // + return EFI_SUCCESS; + } + + CurrentEntry = (EFI_STATUS_CODE_ENTRY *) (UINTN) (mStatusCodeMemoryPpi.Address + (mStatusCodeMemoryPpi.LastEntry * sizeof (EFI_STATUS_CODE_ENTRY))); + + mStatusCodeMemoryPpi.LastEntry = (mStatusCodeMemoryPpi.LastEntry + 1) % MaxEntry; + if (mStatusCodeMemoryPpi.LastEntry == mStatusCodeMemoryPpi.FirstEntry) { + mStatusCodeMemoryPpi.FirstEntry = (mStatusCodeMemoryPpi.FirstEntry + 1) % MaxEntry; + } + + CurrentEntry->Type = CodeType; + CurrentEntry->Value = Value; + CurrentEntry->Instance = Instance; + + return EFI_SUCCESS; +} + +VOID +RtMemoryStatusCodeInitialize ( + VOID + ) +/*++ + +Routine Description: + + Initialization routine. + Allocates heap space for storing Status Codes. + Installs a PPI to point to that heap space. + Installs a callback to switch to memory. + Installs a callback to + +Arguments: + + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + None + +--*/ +{ + EFI_HOB_GUID_TYPE *GuidHob; + PEI_STATUS_CODE_MEMORY_PPI **StatusCodeMemoryPpi; + + GuidHob = GetFirstGuidHob (&gPeiStatusCodeMemoryPpiGuid); + if (GuidHob == NULL) { + return; + } + + StatusCodeMemoryPpi = GET_GUID_HOB_DATA (GuidHob); + + // + // Copy data to our structure since the HOB will go away at runtime + // + // BUGBUG: Virtualize for RT + // + mStatusCodeMemoryPpi.FirstEntry = (*StatusCodeMemoryPpi)->FirstEntry; + mStatusCodeMemoryPpi.LastEntry = (*StatusCodeMemoryPpi)->LastEntry; + mStatusCodeMemoryPpi.Address = (*StatusCodeMemoryPpi)->Address; + mStatusCodeMemoryPpi.Length = (*StatusCodeMemoryPpi)->Length; +} + +VOID +PlaybackStatusCodes ( + IN EFI_REPORT_STATUS_CODE ReportStatusCodeFunc + ) +/*++ + +Routine Description: + + Call the input ReportStatusCode function with every status code recorded in + the journal. + +Arguments: + + ReportStatusCode ReportStatusCode function to call. + +Returns: + + None + +--*/ +{ + UINTN MaxEntry; + EFI_STATUS_CODE_ENTRY *CurrentEntry; + UINTN Counter; + + if (ReportStatusCodeFunc == RtMemoryReportStatusCode) { + return ; + } + // + // Playback prior status codes to current listeners + // + MaxEntry = mStatusCodeMemoryPpi.Length / sizeof (EFI_STATUS_CODE_ENTRY); + for (Counter = mStatusCodeMemoryPpi.FirstEntry; Counter != mStatusCodeMemoryPpi.LastEntry; Counter++) { + // + // Check if we have to roll back to beginning of queue buffer + // + if (Counter == MaxEntry) { + Counter = 0; + } + // + // Play current entry + // + CurrentEntry = (EFI_STATUS_CODE_ENTRY *) (UINTN) (mStatusCodeMemoryPpi.Address + (Counter * sizeof (EFI_STATUS_CODE_ENTRY))); + ReportStatusCodeFunc ( + CurrentEntry->Type, + CurrentEntry->Value, + CurrentEntry->Instance, + NULL, + NULL + ); + } +} diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/RtMemoryStatusCode.mbd b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/RtMemoryStatusCode.mbd new file mode 100644 index 0000000000..1795204d66 --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/RtMemoryStatusCode.mbd @@ -0,0 +1,30 @@ + + + + + EdkRtMemoryStatusCodeLib + 1517564b-ab66-42b7-8903-731a95f314f9 + 0 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/RtMemoryStatusCode.msa b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/RtMemoryStatusCode.msa new file mode 100644 index 0000000000..84d38e3293 --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/RtMemoryStatusCode.msa @@ -0,0 +1,52 @@ + + + + + EdkRtMemoryStatusCodeLib + DXE_DRIVER + LIBRARY + 1517564b-ab66-42b7-8903-731a95f314f9 + 0 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + EdkRtMemoryStatusCodeLib + UefiLib + DebugLib + BaseLib + DxeRuntimeDriverLib + ReportStatusCodeLib + PrintLib + HobLib + UefiBootServicesTableLib + + + RtMemoryStatusCode.c + + + MdePkg + EdkModulePkg + + diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/build.xml b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/build.xml new file mode 100644 index 0000000000..0f02e4e8f7 --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtMemoryStatusCode/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/RtPlatformStatusCode.c b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/RtPlatformStatusCode.c new file mode 100644 index 0000000000..47f7f96511 --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/RtPlatformStatusCode.c @@ -0,0 +1,130 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RtPlatformStatusCode.c + +Abstract: + + Contains NT32 specific implementations required to use status codes. + +--*/ + +// +// Globals only work at BootService Time. NOT at Runtime! +// +// + +typedef +EFI_STATUS +(EFIAPI *REPORT_STATUS_CODE_FUNCTION) ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +REPORT_STATUS_CODE_FUNCTION mPeiReportStatusCode; + +// +// Function implementations +// +EFI_STATUS +RtPlatformReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +/*++ + +Routine Description: + + Call all status code listeners in the MonoStatusCode. + +Arguments: + + Same as ReportStatusCode service + +Returns: + + EFI_SUCCESS Always returns success. + +--*/ +{ + RtMemoryReportStatusCode (CodeType, Value, Instance, CallerId, Data); + if (EfiAtRuntime ()) { + // + // For now all we do is post code at runtime + // + return EFI_SUCCESS; + } + + BsDataHubReportStatusCode (CodeType, Value, Instance, CallerId, Data); + + // + // Call back into PEI to get status codes. This is because SecMain contains + // status code that reports to Win32. + // + if (mPeiReportStatusCode != NULL) { + return mPeiReportStatusCode (CodeType, Value, Instance, CallerId, Data); + } + + return EFI_SUCCESS; +} + +VOID +RtPlatformStatusCodeInitialize ( + VOID + ) +/*++ + +Routine Description: + + Initialize the status code listeners. + +Arguments: + + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + None + +--*/ +{ + EFI_HOB_GUID_TYPE *GuidHob; + void *Pointer; + + RtMemoryStatusCodeInitialize (); + BsDataHubStatusCodeInitialize (); + + // + // Play any prior status codes to the data hub. + // + PlaybackStatusCodes (BsDataHubReportStatusCode); + + // + // If PEI has a ReportStatusCode callback find it and use it before StdErr + // is connected. + // + mPeiReportStatusCode = NULL; + + GuidHob = GetFirstGuidHob (&gEfiStatusCodeRuntimeProtocolGuid); + if (NULL == GuidHob) { + return; + } + Pointer = GET_GUID_HOB_DATA (GuidHob); + mPeiReportStatusCode = (REPORT_STATUS_CODE_FUNCTION) (*(UINTN *) Pointer); +} diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/RtPlatformStatusCode.mbd b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/RtPlatformStatusCode.mbd new file mode 100644 index 0000000000..64591313c7 --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/RtPlatformStatusCode.mbd @@ -0,0 +1,30 @@ + + + + + EdkRtPlatformStatusCodeLib + 68b157b5-9534-43ff-9cd3-6705e4e1d56c + 0 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/RtPlatformStatusCode.msa b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/RtPlatformStatusCode.msa new file mode 100644 index 0000000000..2225ca5b2b --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/RtPlatformStatusCode.msa @@ -0,0 +1,54 @@ + + + + + EdkRtPlatformStatusCodeLib + DXE_DRIVER + LIBRARY + 68b157b5-9534-43ff-9cd3-6705e4e1d56c + 0 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + EdkRtPlatformStatusCodeLib + UefiLib + DebugLib + BaseLib + DxeRuntimeDriverLib + ReportStatusCodeLib + PrintLib + HobLib + EdkBsDataHubStatusCodeLib + EdkRtMemoryStatusCodeLib + UefiBootServicesTableLib + + + RtPlatformStatusCode.c + + + MdePkg + EdkModulePkg + + diff --git a/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/build.xml b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/build.xml new file mode 100644 index 0000000000..34d4d7563c --- /dev/null +++ b/EdkModulePkg/Library/EdkRuntimeStatusCodeLib/RtPlatformStatusCode/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkScsiLib/EdkScsiLib.mbd b/EdkModulePkg/Library/EdkScsiLib/EdkScsiLib.mbd new file mode 100644 index 0000000000..18d03c26b1 --- /dev/null +++ b/EdkModulePkg/Library/EdkScsiLib/EdkScsiLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkScsiLib + 46c9adef-aee6-410c-99e4-240e3af18d8b + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + diff --git a/EdkModulePkg/Library/EdkScsiLib/EdkScsiLib.msa b/EdkModulePkg/Library/EdkScsiLib/EdkScsiLib.msa new file mode 100644 index 0000000000..033d54847c --- /dev/null +++ b/EdkModulePkg/Library/EdkScsiLib/EdkScsiLib.msa @@ -0,0 +1,45 @@ + + + + + EdkScsiLib + DXE_DRIVER + LIBRARY + 46c9adef-aee6-410c-99e4-240e3af18d8b + 0 + Component description file for Scsi Dxe Library. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + EdkScsiLib + BaseMemoryLib + + + ScsiLib.c + + + MdePkg + EdkModulePkg + + diff --git a/EdkModulePkg/Library/EdkScsiLib/ScsiLib.c b/EdkModulePkg/Library/EdkScsiLib/ScsiLib.c new file mode 100644 index 0000000000..9a6eb6751e --- /dev/null +++ b/EdkModulePkg/Library/EdkScsiLib/ScsiLib.c @@ -0,0 +1,651 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ScsiLib.c + +Abstract: + + +Revision History +--*/ + + +#include + +EFI_STATUS +SubmitTestUnitReadyCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + OUT VOID *SenseData, + OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus + ) +/*++ + +Routine Description: + Function tests the ready status of SCSI unit. + +Arguments: + ScsiIo - A pointer to SCSI IO protocol. + Timeout - The length of timeout period. + SenseData - A pointer to output sense data. + SenseDataLength - The length of output sense data. + HostAdapterStatus - The status of Host Adapter. + TargetStatus - The status of the target. + +Returns: + + Returns: + EFI_SUCCESS - The status of the unit is tested successfully. + EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, + but the entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in InTransferLength. + EFI_NOT_READY - The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued. + EFI_DEVICE_ERROR - A device error occurred while attempting to send + the SCSI Request Packet. + EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. + EFI_UNSUPPORTED - The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). + EFI_TIMEOUT - A timeout occurred while waiting for the SCSI + Request Packet to execute. + +--*/ +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + UINT64 Lun; + UINT8 *Target; + EFI_STATUS Status; + UINT8 Cdb[6]; + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, 6); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = NULL; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength= 0; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Test Unit Ready Command + // + ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); + + Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY; + Cdb[1] = (UINT8) (Lun & 0xe0); + CommandPacket.CdbLength = (UINT8) 6; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + + return Status; +} + +EFI_STATUS +SubmitInquiryCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN OUT VOID *InquiryDataBuffer, + IN OUT UINT32 *InquiryDataLength, + IN BOOLEAN EnableVitalProductData + ) +/*++ + +Routine Description: + Function to submit SCSI inquiry command. + +Arguments: + ScsiIo - A pointer to SCSI IO protocol. + Timeout - The length of timeout period. + SenseData - A pointer to output sense data. + SenseDataLength - The length of output sense data. + HostAdapterStatus - The status of Host Adapter. + TargetStatus - The status of the target. + InquiryDataBuffer - A pointer to inquiry data buffer. + InquiryDataLength - The length of inquiry data buffer. + EnableVitalProductData - Boolean to enable Vital Product Data. + +Returns: + + Returns: + EFI_SUCCESS - The status of the unit is tested successfully. + EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, + but the entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in TransferLength. + EFI_NOT_READY - The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued. + EFI_DEVICE_ERROR - A device error occurred while attempting to send + the SCSI Request Packet. + EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. + EFI_UNSUPPORTED - The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). + EFI_TIMEOUT - A timeout occurred while waiting for the SCSI + Request Packet to execute. + +--*/ +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + UINT64 Lun; + UINT8 *Target; + EFI_STATUS Status; + UINT8 Cdb[6]; + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, 6); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = InquiryDataBuffer; + CommandPacket.InTransferLength= *InquiryDataLength; + CommandPacket.SenseData = SenseData; + CommandPacket.SenseDataLength = *SenseDataLength; + CommandPacket.Cdb = Cdb; + + ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); + + Cdb[0] = EFI_SCSI_OP_INQUIRY; + Cdb[1] = (UINT8) (Lun & 0xe0); + if (EnableVitalProductData) { + Cdb[1] |= 0x01; + } + + if (*InquiryDataLength > 0xff) { + *InquiryDataLength = 0xff; + } + + Cdb[4] = (UINT8) (*InquiryDataLength); + CommandPacket.CdbLength = (UINT8) 6; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + + Status = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *InquiryDataLength = CommandPacket.InTransferLength; + + return Status; +} + +EFI_STATUS +SubmitModeSense10Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + IN VOID *DataBuffer, + IN OUT UINT32 *DataLength, + IN UINT8 DBDField, OPTIONAL + IN UINT8 PageControl, + IN UINT8 PageCode + ) +/*++ + +Routine Description: + Function to submit SCSI mode sense 10 command. + +Arguments: + ScsiIo - A pointer to SCSI IO protocol. + Timeout - The length of timeout period. + SenseData - A pointer to output sense data. + SenseDataLength - The length of output sense data. + HostAdapterStatus - The status of Host Adapter. + TargetStatus - The status of the target. + DataBuffer - A pointer to input data buffer. + DataLength - The length of input data buffer. + DBDField - The DBD Field (Optional). + PageControl - Page Control. + PageCode - Page code. + +Returns: + + Returns: + EFI_SUCCESS - The status of the unit is tested successfully. + EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, + but the entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in TransferLength. + EFI_NOT_READY - The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued. + EFI_DEVICE_ERROR - A device error occurred while attempting to send + the SCSI Request Packet. + EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. + EFI_UNSUPPORTED - The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). + EFI_TIMEOUT - A timeout occurred while waiting for the SCSI + Request Packet to execute. + +--*/ +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + UINT64 Lun; + UINT8 *Target; + EFI_STATUS Status; + UINT8 Cdb[10]; + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, 10); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength= *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Mode Sense (10) Command + // + ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); + + Cdb[0] = EFI_SCSI_OP_MODE_SEN10; + Cdb[1] = (UINT8) ((Lun & 0xe0) + ((DBDField << 3) & 0x08)); + Cdb[2] = (UINT8) ((PageControl & 0xc0) | (PageCode & 0x3f)); + Cdb[7] = (UINT8) (*DataLength >> 8); + Cdb[8] = (UINT8) (*DataLength); + + CommandPacket.CdbLength = 10; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.InTransferLength; + + return Status; +} + +EFI_STATUS +SubmitRequestSenseCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus + ) +/*++ + +Routine Description: + Function to submit SCSI request sense command. + +Arguments: + ScsiIo - A pointer to SCSI IO protocol. + Timeout - The length of timeout period. + SenseData - A pointer to output sense data. + SenseDataLength - The length of output sense data. + HostAdapterStatus - The status of Host Adapter. + TargetStatus - The status of the target. + +Returns: + + Returns: + EFI_SUCCESS - The status of the unit is tested successfully. + EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, + but the entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in TransferLength. + EFI_NOT_READY - The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued. + EFI_DEVICE_ERROR - A device error occurred while attempting to send + the SCSI Request Packet. + EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. + EFI_UNSUPPORTED - The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). + EFI_TIMEOUT - A timeout occurred while waiting for the SCSI + Request Packet to execute. + +--*/ +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + UINT64 Lun; + UINT8 *Target; + EFI_STATUS Status; + UINT8 Cdb[6]; + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, 6); +/* + if (*SenseDataLength > 0xff) { + *SenseDataLength = 0xff; + } +*/ + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = SenseData; + CommandPacket.SenseData = NULL; + CommandPacket.InTransferLength= *SenseDataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Request Sense Command + // + ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); + + Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE; + Cdb[1] = (UINT8) (Lun & 0xe0); + Cdb[4] = (UINT8) (*SenseDataLength); + + CommandPacket.CdbLength = (UINT8) 6; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = 0; + + Status = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = (UINT8) CommandPacket.InTransferLength; + + return Status; +} + +EFI_STATUS +SubmitReadCapacityCommand ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + OUT VOID *DataBuffer, + IN OUT UINT32 *DataLength, + IN BOOLEAN PMI + ) +/*++ + +Routine Description: + Function to submit read capacity command. + +Arguments: + ScsiIo - A pointer to SCSI IO protocol. + Timeout - The length of timeout period. + SenseData - A pointer to output sense data. + SenseDataLength - The length of output sense data. + HostAdapterStatus - The status of Host Adapter. + TargetStatus - The status of the target. + DataBuffer - A pointer to a data buffer. + DataLength - The length of data buffer. + PMI - Partial medium indicator. + +Returns: + + Returns: + EFI_SUCCESS - The status of the unit is tested successfully. + EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, + but the entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in TransferLength. + EFI_NOT_READY - The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued. + EFI_DEVICE_ERROR - A device error occurred while attempting to send + the SCSI Request Packet. + EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. + EFI_UNSUPPORTED - The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). + EFI_TIMEOUT - A timeout occurred while waiting for the SCSI + Request Packet to execute. + +--*/ +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + UINT64 Lun; + UINT8 *Target; + EFI_STATUS Status; + UINT8 Cdb[10]; + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, 10); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength= *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Read Capacity Command + // + ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); + + Cdb[0] = EFI_SCSI_OP_READ_CAPACITY; + Cdb[1] = (UINT8) (Lun & 0xe0); + if (!PMI) { + // + // Partial medium indicator,if PMI is FALSE, the Cdb.2 ~ Cdb.5 MUST BE ZERO. + // + ZeroMem ((Cdb + 2), 4); + } else { + Cdb[8] |= 0x01; + } + + CommandPacket.CdbLength = 10; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.InTransferLength; + + return Status; +} + +EFI_STATUS +SubmitRead10Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + OUT VOID *DataBuffer, + IN OUT UINT32 *DataLength, + IN UINT32 StartLba, + IN UINT32 SectorSize + ) +/*++ + +Routine Description: + Function to submit read 10 command. + +Arguments: + ScsiIo - A pointer to SCSI IO protocol. + Timeout - The length of timeout period. + SenseData - A pointer to output sense data. + SenseDataLength - The length of output sense data. + HostAdapterStatus - The status of Host Adapter. + TargetStatus - The status of the target. + DataBuffer - A pointer to a data buffer. + DataLength - The length of data buffer. + StartLba - The start address of LBA. + SectorSize - The sector size. + +Returns: + + Returns: + EFI_SUCCESS - The status of the unit is tested successfully. + EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, + but the entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in TransferLength. + EFI_NOT_READY - The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued. + EFI_DEVICE_ERROR - A device error occurred while attempting to send + the SCSI Request Packet. + EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. + EFI_UNSUPPORTED - The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). + EFI_TIMEOUT - A timeout occurred while waiting for the SCSI + Request Packet to execute. + +--*/ +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + UINT64 Lun; + UINT8 *Target; + EFI_STATUS Status; + UINT8 Cdb[10]; + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, 10); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength= *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Read (10) Command + // + ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); + + Cdb[0] = EFI_SCSI_OP_READ10; + Cdb[1] = (UINT8) (Lun & 0xe0); + Cdb[2] = (UINT8) (StartLba >> 24); + Cdb[3] = (UINT8) (StartLba >> 16); + Cdb[4] = (UINT8) (StartLba >> 8); + Cdb[5] = (UINT8) StartLba; + Cdb[7] = (UINT8) (SectorSize >> 8); + Cdb[8] = (UINT8) SectorSize; + + CommandPacket.CdbLength = 10; + CommandPacket.DataDirection = EFI_SCSI_DATA_IN; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.InTransferLength; + + return Status; +} + +EFI_STATUS +SubmitWrite10Command ( + IN EFI_SCSI_IO_PROTOCOL *ScsiIo, + IN UINT64 Timeout, + IN VOID *SenseData, + IN OUT UINT8 *SenseDataLength, + OUT UINT8 *HostAdapterStatus, + OUT UINT8 *TargetStatus, + OUT VOID *DataBuffer, + IN OUT UINT32 *DataLength, + IN UINT32 StartLba, + IN UINT32 SectorSize + ) +/*++ + +Routine Description: + Function to submit SCSI write 10 command. + +Arguments: + ScsiIo - A pointer to SCSI IO protocol. + Timeout - The length of timeout period. + SenseData - A pointer to output sense data. + SenseDataLength - The length of output sense data. + HostAdapterStatus - The status of Host Adapter. + TargetStatus - The status of the target. + DataBuffer - A pointer to a data buffer. + DataLength - The length of data buffer. + StartLba - The start address of LBA. + SectorSize - The sector size. + +Returns: + + Returns: + EFI_SUCCESS - The status of the unit is tested successfully. + EFI_WARN_BUFFER_TOO_SMALL - The SCSI Request Packet was executed, + but the entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in InTransferLength. + EFI_NOT_READY - The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued. + EFI_DEVICE_ERROR - A device error occurred while attempting to send + the SCSI Request Packet. + EFI_INVALID_PARAMETER - The contents of CommandPacket are invalid. + EFI_UNSUPPORTED - The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). + EFI_TIMEOUT - A timeout occurred while waiting for the SCSI + Request Packet to execute. + +--*/ +{ + EFI_SCSI_IO_SCSI_REQUEST_PACKET CommandPacket; + UINT64 Lun; + UINT8 *Target; + EFI_STATUS Status; + UINT8 Cdb[10]; + + ZeroMem (&CommandPacket, sizeof (EFI_SCSI_IO_SCSI_REQUEST_PACKET)); + ZeroMem (Cdb, 10); + + CommandPacket.Timeout = Timeout; + CommandPacket.InDataBuffer = DataBuffer; + CommandPacket.SenseData = SenseData; + CommandPacket.InTransferLength= *DataLength; + CommandPacket.Cdb = Cdb; + // + // Fill Cdb for Write (10) Command + // + ScsiIo->GetDeviceLocation (ScsiIo, &Target, &Lun); + + Cdb[0] = EFI_SCSI_OP_WRITE10; + Cdb[1] = (UINT8) (Lun & 0xe0); + Cdb[2] = (UINT8) (StartLba >> 24); + Cdb[3] = (UINT8) (StartLba >> 16); + Cdb[4] = (UINT8) (StartLba >> 8); + Cdb[5] = (UINT8) StartLba; + Cdb[7] = (UINT8) (SectorSize >> 8); + Cdb[8] = (UINT8) SectorSize; + + CommandPacket.CdbLength = 10; + CommandPacket.DataDirection = EFI_SCSI_DATA_OUT; + CommandPacket.SenseDataLength = *SenseDataLength; + + Status = ScsiIo->ExecuteSCSICommand (ScsiIo, &CommandPacket, NULL); + + *HostAdapterStatus = CommandPacket.HostAdapterStatus; + *TargetStatus = CommandPacket.TargetStatus; + *SenseDataLength = CommandPacket.SenseDataLength; + *DataLength = CommandPacket.InTransferLength; + + return Status; +} diff --git a/EdkModulePkg/Library/EdkScsiLib/build.xml b/EdkModulePkg/Library/EdkScsiLib/build.xml new file mode 100644 index 0000000000..511cf6fb7c --- /dev/null +++ b/EdkModulePkg/Library/EdkScsiLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkUefiDebugLibConOut/DebugLib.c b/EdkModulePkg/Library/EdkUefiDebugLibConOut/DebugLib.c new file mode 100644 index 0000000000..911002e96c --- /dev/null +++ b/EdkModulePkg/Library/EdkUefiDebugLibConOut/DebugLib.c @@ -0,0 +1,255 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugLib.c + +Abstract: + + UEFI Debug Library that uses PrintLib to send messages to CONOUT + +--*/ + +static BOOLEAN mDebugLevelInstalled = FALSE; +static EFI_DEBUG_LEVEL_PROTOCOL mDebugLevel = { 0 }; + +EFI_STATUS +DebugLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + + // + // Initialize Debug Level Protocol + // + mDebugLevel.DebugLevel = PcdGet32(PcdDebugPrintErrorLevel); + + // + // Install Debug Level Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiDebugLevelProtocolGuid, &mDebugLevel, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Set flag to show that the Debug Level Protocol has been installed + // + mDebugLevelInstalled = TRUE; + + return EFI_SUCCESS; +} + +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ) +/*++ + +Routine Description: + + Wrapper for DebugVPrint () + +Arguments: + + ErrorLevel - If error level is set do the debug print. + + Format - String to use for the print, followed by Print arguments. + + ... - Print arguments. + +Returns: + + None + +--*/ +{ + CHAR16 Buffer[0x100]; + CHAR16 UnicodeBuffer[0x100]; + UINT32 Index; + VA_LIST Marker; + + // + // Check to see if CONOUT is avilable + // + if (gST->ConOut == NULL) { + return; + } + + // + // Check driver Debug Level value and global debug level + // + if (mDebugLevelInstalled) { + if ((ErrorLevel & mDebugLevel.DebugLevel) == 0) { + return; + } + } else { + if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) { + return; + } + } + + // + // BUGBUG: Need print that take CHAR8 Format and returns CHAR16 Buffer + // + for (Index = 0; Format[Index] != 0; Index++) { + UnicodeBuffer[Index] = Format[Index]; + } + UnicodeBuffer[Index] = Format[Index]; + + // + // Convert the DEBUG() message to a Unicode String + // + VA_START (Marker, Format); + UnicodeVSPrint (Buffer, sizeof (Buffer), UnicodeBuffer, Marker); + VA_END (Marker); + + // + // Send the print string to the Standard Error device + // + gST->ConOut->OutputString (gST->ConOut, Buffer); +} + +VOID +EFIAPI +DebugAssert ( + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) +/*++ + +Routine Description: + + Worker function for ASSERT(). If Error Logging hub is loaded log ASSERT + information. If Error Logging hub is not loaded CpuBreakpoint (). + + We use UINT64 buffers due to IPF alignment concerns. + +Arguments: + + FileName - File name of failing routine. + + LineNumber - Line number of failing ASSERT(). + + Description - Descritption, usally the assertion, + +Returns: + + None + +--*/ +{ + CHAR16 Buffer[0x100]; + + // + // Check to see if CONOUT is avilable + // + if (gST->ConOut == NULL) { + return; + } + + // + // Generate the ASSERT() message in Unicode format + // + UnicodeSPrint (Buffer, sizeof (Buffer), (CHAR16 *)L"ASSERT %s(%d): %s\n", FileName, LineNumber, Description); + + // + // Send the print string to the Standard Error device + // + gST->ConOut->OutputString (gST->ConOut, Buffer); + + // + // Put break point in module that contained the error. + // + CpuBreakpoint (); +} + +/** + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + + If Length is greater than (MAX_ADDRESS – Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ +// SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue)); + SetMem (Buffer, Length, 0xAF); + return Buffer; +} + +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} diff --git a/EdkModulePkg/Library/EdkUefiDebugLibConOut/EdkUefiDebugLibConOut.mbd b/EdkModulePkg/Library/EdkUefiDebugLibConOut/EdkUefiDebugLibConOut.mbd new file mode 100644 index 0000000000..08bc04d0b0 --- /dev/null +++ b/EdkModulePkg/Library/EdkUefiDebugLibConOut/EdkUefiDebugLibConOut.mbd @@ -0,0 +1,30 @@ + + + + + EdkUefiDebugLibConOut + 7293fe0b-1fff-4f8f-b808-10cb55f6a174 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-31 13:14 + + diff --git a/EdkModulePkg/Library/EdkUefiDebugLibConOut/EdkUefiDebugLibConOut.msa b/EdkModulePkg/Library/EdkUefiDebugLibConOut/EdkUefiDebugLibConOut.msa new file mode 100644 index 0000000000..874c873cef --- /dev/null +++ b/EdkModulePkg/Library/EdkUefiDebugLibConOut/EdkUefiDebugLibConOut.msa @@ -0,0 +1,69 @@ + + + + + EdkUefiDebugLibConOut + DXE_DRIVER + LIBRARY + 7293fe0b-1fff-4f8f-b808-10cb55f6a174 + EDK_RELEASE_VERSION 0x00020000 + Debug Library for UEFI drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-31 13:14 + + + DebugLib + PrintLib + PcdLib + UefiBootServicesTableLib + BaseMemoryLib + BaseLib + + + DebugLib.c + + + MdePkg + EdkModulePkg + + + DebugLevel + + + + DebugLibConstructor + + + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + + + diff --git a/EdkModulePkg/Library/EdkUefiDebugLibConOut/build.xml b/EdkModulePkg/Library/EdkUefiDebugLibConOut/build.xml new file mode 100644 index 0000000000..4a7cb25121 --- /dev/null +++ b/EdkModulePkg/Library/EdkUefiDebugLibConOut/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkUefiDebugLibStdErr/DebugLib.c b/EdkModulePkg/Library/EdkUefiDebugLibStdErr/DebugLib.c new file mode 100644 index 0000000000..1074d6a2ce --- /dev/null +++ b/EdkModulePkg/Library/EdkUefiDebugLibStdErr/DebugLib.c @@ -0,0 +1,255 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugLib.c + +Abstract: + + UEFI Debug Library that uses PrintLib to send messages to STDERR + +--*/ + +static BOOLEAN mDebugLevelInstalled = FALSE; +static EFI_DEBUG_LEVEL_PROTOCOL mDebugLevel = { 0 }; + +EFI_STATUS +DebugLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + + // + // Initialize Debug Level Protocol + // + mDebugLevel.DebugLevel = PcdGet32(PcdDebugPrintErrorLevel); + + // + // Install Debug Level Protocol + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gEfiDebugLevelProtocolGuid, &mDebugLevel, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Set flag to show that the Debug Level Protocol has been installed + // + mDebugLevelInstalled = TRUE; + + return EFI_SUCCESS; +} + +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ) +/*++ + +Routine Description: + + Wrapper for DebugVPrint () + +Arguments: + + ErrorLevel - If error level is set do the debug print. + + Format - String to use for the print, followed by Print arguments. + + ... - Print arguments. + +Returns: + + None + +--*/ +{ + CHAR16 Buffer[0x100]; + CHAR16 UnicodeBuffer[0x100]; + UINT32 Index; + VA_LIST Marker; + + // + // Check to see if STDERR is avilable + // + if (gST->StdErr == NULL) { + return; + } + + // + // Check driver Debug Level value and global debug level + // + if (mDebugLevelInstalled) { + if ((ErrorLevel & mDebugLevel.DebugLevel) == 0) { + return; + } + } else { + if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) { + return; + } + } + + // + // BUGBUG: Need print that take CHAR8 Format and returns CHAR16 Buffer + // + for (Index = 0; Format[Index] != 0; Index++) { + UnicodeBuffer[Index] = Format[Index]; + } + UnicodeBuffer[Index] = Format[Index]; + + // + // Convert the DEBUG() message to a Unicode String + // + VA_START (Marker, Format); + UnicodeVSPrint (Buffer, sizeof (Buffer), UnicodeBuffer, Marker); + VA_END (Marker); + + // + // Send the print string to the Standard Error device + // + gST->StdErr->OutputString (gST->StdErr, Buffer); +} + +VOID +EFIAPI +DebugAssert ( + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) +/*++ + +Routine Description: + + Worker function for ASSERT(). If Error Logging hub is loaded log ASSERT + information. If Error Logging hub is not loaded CpuBreakpoint (). + + We use UINT64 buffers due to IPF alignment concerns. + +Arguments: + + FileName - File name of failing routine. + + LineNumber - Line number of failing ASSERT(). + + Description - Descritption, usally the assertion, + +Returns: + + None + +--*/ +{ + CHAR16 Buffer[0x100]; + + // + // Check to see if STDERR is avilable + // + if (gST->StdErr == NULL) { + return; + } + + // + // Generate the ASSERT() message in Unicode format + // + UnicodeSPrint (Buffer, sizeof (Buffer), (CHAR16 *)L"ASSERT %s(%d): %s\n", FileName, LineNumber, Description); + + // + // Send the print string to the Standard Error device + // + gST->StdErr->OutputString (gST->StdErr, Buffer); + + // + // Put break point in module that contained the error. + // + CpuBreakpoint (); +} + +/** + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + + If Length is greater than (MAX_ADDRESS – Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ +// SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue)); + SetMem (Buffer, Length, 0xAF); + return Buffer; +} + +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} diff --git a/EdkModulePkg/Library/EdkUefiDebugLibStdErr/EdkUefiDebugLibStdErr.mbd b/EdkModulePkg/Library/EdkUefiDebugLibStdErr/EdkUefiDebugLibStdErr.mbd new file mode 100644 index 0000000000..833b2eea09 --- /dev/null +++ b/EdkModulePkg/Library/EdkUefiDebugLibStdErr/EdkUefiDebugLibStdErr.mbd @@ -0,0 +1,30 @@ + + + + + EdkUefiDebugLibStdErr + 8b9968e0-c76b-4b57-aec4-24e17fe602c0 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-31 13:14 + + diff --git a/EdkModulePkg/Library/EdkUefiDebugLibStdErr/EdkUefiDebugLibStdErr.msa b/EdkModulePkg/Library/EdkUefiDebugLibStdErr/EdkUefiDebugLibStdErr.msa new file mode 100644 index 0000000000..3c5fc2b901 --- /dev/null +++ b/EdkModulePkg/Library/EdkUefiDebugLibStdErr/EdkUefiDebugLibStdErr.msa @@ -0,0 +1,69 @@ + + + + + EdkUefiDebugLibStdErr + DXE_DRIVER + LIBRARY + 8b9968e0-c76b-4b57-aec4-24e17fe602c0 + EDK_RELEASE_VERSION 0x00020000 + Debug Library for UEFI drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-31 13:14 + + + DebugLib + PrintLib + PcdLib + UefiBootServicesTableLib + BaseMemoryLib + BaseLib + + + DebugLib.c + + + MdePkg + EdkModulePkg + + + DebugLevel + + + + DebugLibConstructor + + + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + + + diff --git a/EdkModulePkg/Library/EdkUefiDebugLibStdErr/build.xml b/EdkModulePkg/Library/EdkUefiDebugLibStdErr/build.xml new file mode 100644 index 0000000000..1479581406 --- /dev/null +++ b/EdkModulePkg/Library/EdkUefiDebugLibStdErr/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkUsbLib/EdkUsbLib.mbd b/EdkModulePkg/Library/EdkUsbLib/EdkUsbLib.mbd new file mode 100644 index 0000000000..79fa4b10fc --- /dev/null +++ b/EdkModulePkg/Library/EdkUsbLib/EdkUsbLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkUsbLib + 87eb5df9-722a-4241-ad7f-370d0b3a56d7 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + diff --git a/EdkModulePkg/Library/EdkUsbLib/EdkUsbLib.msa b/EdkModulePkg/Library/EdkUsbLib/EdkUsbLib.msa new file mode 100644 index 0000000000..f2aa74b28f --- /dev/null +++ b/EdkModulePkg/Library/EdkUsbLib/EdkUsbLib.msa @@ -0,0 +1,46 @@ + + + + + EdkUsbLib + DXE_DRIVER + LIBRARY + 87eb5df9-722a-4241-ad7f-370d0b3a56d7 + 0 + Component description file for UsbDxeLib module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + EdkUsbLib + BaseMemoryLib + + + UsbDxelib.c + hid.c + + + MdePkg + EdkModulePkg + + diff --git a/EdkModulePkg/Library/EdkUsbLib/UsbDxeLib.c b/EdkModulePkg/Library/EdkUsbLib/UsbDxeLib.c new file mode 100644 index 0000000000..8bbd0893ae --- /dev/null +++ b/EdkModulePkg/Library/EdkUsbLib/UsbDxeLib.c @@ -0,0 +1,699 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + + UsbDxeLib.c + + Abstract: + + Common Dxe Libarary for USB + + Revision History + +--*/ + +// +// Get Device Descriptor +// +EFI_STATUS +UsbGetDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Value, + IN UINT16 Index, + IN UINT16 DescriptorLength, + OUT VOID *Descriptor, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Get Descriptor + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + Value - Device Request Value + Index - Device Request Index + DescriptorLength - Descriptor Length + Descriptor - Descriptor buffer to contain result + Status - Transfer Status +Returns: + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_GET_DESCRIPTOR_REQ_TYPE; + DevReq.Request = USB_DEV_GET_DESCRIPTOR; + DevReq.Value = Value; + DevReq.Index = Index; + DevReq.Length = DescriptorLength; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + TIMEOUT_VALUE, + Descriptor, + DescriptorLength, + Status + ); +} +// +// Set Device Descriptor +// +EFI_STATUS +UsbSetDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Value, + IN UINT16 Index, + IN UINT16 DescriptorLength, + IN VOID *Descriptor, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Set Descriptor + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + Value - Device Request Value + Index - Device Request Index + DescriptorLength - Descriptor Length + Descriptor - Descriptor buffer to set + Status - Transfer Status +Returns: + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_SET_DESCRIPTOR_REQ_TYPE; + DevReq.Request = USB_DEV_SET_DESCRIPTOR; + DevReq.Value = Value; + DevReq.Index = Index; + DevReq.Length = DescriptorLength; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataOut, + TIMEOUT_VALUE, + Descriptor, + DescriptorLength, + Status + ); +} + +// +// Get device Interface +// +EFI_STATUS +UsbGetDeviceInterface ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Index, + OUT UINT8 *AltSetting, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Get Device Interface + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + Index - Interface index value + AltSetting - Alternate setting + Status - Trasnsfer status + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_GET_INTERFACE_REQ_TYPE; + DevReq.Request = USB_DEV_GET_INTERFACE; + DevReq.Index = Index; + DevReq.Length = 1; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + TIMEOUT_VALUE, + AltSetting, + 1, + Status + ); +} +// +// Set device interface +// +EFI_STATUS +UsbSetDeviceInterface ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 InterfaceNo, + IN UINT16 AltSetting, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Set Device Interface + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + InterfaceNo - Interface Number + AltSetting - Alternate setting + Status - Trasnsfer status + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_SET_INTERFACE_REQ_TYPE; + DevReq.Request = USB_DEV_SET_INTERFACE; + DevReq.Value = AltSetting; + DevReq.Index = InterfaceNo; + + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + TIMEOUT_VALUE, + NULL, + 0, + Status + ); +} +// +// Get device configuration +// +EFI_STATUS +UsbGetDeviceConfiguration ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + OUT UINT8 *ConfigValue, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Get Device Configuration + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + ConfigValue - Config Value + Status - Transfer Status + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_GET_CONFIGURATION_REQ_TYPE; + DevReq.Request = USB_DEV_GET_CONFIGURATION; + DevReq.Length = 1; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + TIMEOUT_VALUE, + ConfigValue, + 1, + Status + ); +} +// +// Set device configuration +// +EFI_STATUS +UsbSetDeviceConfiguration ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 Value, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Set Device Configuration + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + Value - Configuration Value to set + Status - Transfer status + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + DevReq.RequestType = USB_DEV_SET_CONFIGURATION_REQ_TYPE; + DevReq.Request = USB_DEV_SET_CONFIGURATION; + DevReq.Value = Value; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + TIMEOUT_VALUE, + NULL, + 0, + Status + ); +} +// +// Set Device Feature +// +EFI_STATUS +UsbSetDeviceFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN EFI_USB_RECIPIENT Recipient, + IN UINT16 Value, + IN UINT16 Target, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Set Device Feature + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + Recipient - Interface/Device/Endpoint + Value - Request value + Target - Request Index + Status - Transfer status + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + switch (Recipient) { + + case EfiUsbDevice: + DevReq.RequestType = 0x00; + break; + + case EfiUsbInterface: + DevReq.RequestType = 0x01; + break; + + case EfiUsbEndpoint: + DevReq.RequestType = 0x02; + break; + } + // + // Fill device request, see USB1.1 spec + // + DevReq.Request = USB_DEV_SET_FEATURE; + DevReq.Value = Value; + DevReq.Index = Target; + + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + TIMEOUT_VALUE, + NULL, + 0, + Status + ); +} +// +// Clear Device Feature +// +EFI_STATUS +UsbClearDeviceFeature ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN EFI_USB_RECIPIENT Recipient, + IN UINT16 Value, + IN UINT16 Target, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Clear Device Feature + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + Recipient - Interface/Device/Endpoint + Value - Request value + Target - Request Index + Status - Transfer status + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + switch (Recipient) { + + case EfiUsbDevice: + DevReq.RequestType = 0x00; + break; + + case EfiUsbInterface: + DevReq.RequestType = 0x01; + break; + + case EfiUsbEndpoint: + DevReq.RequestType = 0x02; + break; + } + // + // Fill device request, see USB1.1 spec + // + DevReq.Request = USB_DEV_CLEAR_FEATURE; + DevReq.Value = Value; + DevReq.Index = Target; + + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbNoData, + TIMEOUT_VALUE, + NULL, + 0, + Status + ); +} +// +// Get Device Status +// +EFI_STATUS +UsbGetDeviceStatus ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN EFI_USB_RECIPIENT Recipient, + IN UINT16 Target, + OUT UINT16 *DevStatus, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Get Device Status + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + Recipient - Interface/Device/Endpoint + Target - Request index + DevStatus - Device status + Status - Transfer status + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + +--*/ +{ + EFI_USB_DEVICE_REQUEST DevReq; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&DevReq, sizeof (EFI_USB_DEVICE_REQUEST)); + + switch (Recipient) { + + case EfiUsbDevice: + DevReq.RequestType = 0x80; + break; + + case EfiUsbInterface: + DevReq.RequestType = 0x81; + break; + + case EfiUsbEndpoint: + DevReq.RequestType = 0x82; + break; + } + // + // Fill device request, see USB1.1 spec + // + DevReq.Request = USB_DEV_GET_STATUS; + DevReq.Value = 0; + DevReq.Index = Target; + DevReq.Length = 2; + + return UsbIo->UsbControlTransfer ( + UsbIo, + &DevReq, + EfiUsbDataIn, + TIMEOUT_VALUE, + DevStatus, + 2, + Status + ); +} +// +// Usb Get String +// +EFI_STATUS +UsbGetString ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT16 LangID, + IN UINT8 Index, + IN VOID *Buf, + IN UINTN BufSize, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Usb Get String + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + LangID - Language ID + Index - Request index + Buf - Buffer to store string + BufSize - Buffer size + Status - Transfer status + +Returns: + + EFI_INVALID_PARAMETER - Parameter is error + EFI_SUCCESS - Success + EFI_TIMEOUT - Device has no response + +--*/ +{ + UINT16 Value; + + if (UsbIo == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Fill value, see USB1.1 spec + // + Value = (UINT16) ((USB_DT_STRING << 8) | Index); + + return UsbGetDescriptor ( + UsbIo, + Value, + LangID, + (UINT16) BufSize, + Buf, + Status + ); +} + +EFI_STATUS +UsbClearEndpointHalt ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 EndpointNo, + OUT UINT32 *Status + ) +/*++ + +Routine Description: + + Clear endpoint stall + +Arguments: + + UsbIo - EFI_USB_IO_PROTOCOL + EndpointNo - Endpoint Number + Status - Transfer Status + +Returns: + + EFI_NOT_FOUND - Can't find the Endpoint + EFI_DEVICE_ERROR - Hardware error + EFI_SUCCESS - Success + +--*/ +{ + EFI_STATUS Result; + EFI_USB_ENDPOINT_DESCRIPTOR EndpointDescriptor; + EFI_USB_INTERFACE_DESCRIPTOR InterfaceDescriptor; + UINT8 Index; + + ZeroMem (&EndpointDescriptor, sizeof (EFI_USB_ENDPOINT_DESCRIPTOR)); + // + // First seach the endpoint descriptor for that endpoint addr + // + Result = UsbIo->UsbGetInterfaceDescriptor ( + UsbIo, + &InterfaceDescriptor + ); + if (EFI_ERROR (Result)) { + return Result; + } + + for (Index = 0; Index < InterfaceDescriptor.NumEndpoints; Index++) { + Result = UsbIo->UsbGetEndpointDescriptor ( + UsbIo, + Index, + &EndpointDescriptor + ); + if (EFI_ERROR (Result)) { + continue; + } + + if (EndpointDescriptor.EndpointAddress == EndpointNo) { + break; + } + } + + if (Index == InterfaceDescriptor.NumEndpoints) { + // + // No such endpoint + // + return EFI_NOT_FOUND; + } + + Result = UsbClearDeviceFeature ( + UsbIo, + EfiUsbEndpoint, + EfiUsbEndpointHalt, + EndpointDescriptor.EndpointAddress, + Status + ); + + return Result; +} diff --git a/EdkModulePkg/Library/EdkUsbLib/build.xml b/EdkModulePkg/Library/EdkUsbLib/build.xml new file mode 100644 index 0000000000..0b9eaade6b --- /dev/null +++ b/EdkModulePkg/Library/EdkUsbLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Library/EdkUsbLib/hid.c b/EdkModulePkg/Library/EdkUsbLib/hid.c new file mode 100644 index 0000000000..edf9a94efc --- /dev/null +++ b/EdkModulePkg/Library/EdkUsbLib/hid.c @@ -0,0 +1,459 @@ +/*++ + +Copyright (c) 2006, 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. + + Module Name: + + hid.c + + Abstract: + + HID class request + + Revision History + +--*/ + +// +// Function to get HID descriptor +// +EFI_STATUS +UsbGetHidDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 InterfaceNum, + OUT EFI_USB_HID_DESCRIPTOR *HidDescriptor + ) +/*++ + + Routine Description: + Get Hid Descriptor + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL + InterfaceNum - Hid interface number + HidDescriptor - Caller allocated buffer to store Usb hid descriptor + if successfully returned. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_TIMEOUT + +--*/ +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + Request.RequestType = 0x81; + Request.Request = 0x06; + Request.Value = (UINT16) (0x21 << 8); + Request.Index = InterfaceNum; + Request.Length = sizeof (EFI_USB_HID_DESCRIPTOR); + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataIn, + TIMEOUT_VALUE, + HidDescriptor, + sizeof (EFI_USB_HID_DESCRIPTOR), + &Status + ); + + return Result; + +} +// +// Function to get Report Class descriptor +// +EFI_STATUS +UsbGetReportDescriptor ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 InterfaceNum, + IN UINT16 DescriptorSize, + OUT UINT8 *DescriptorBuffer + ) +/*++ + + Routine Description: + get Report Class descriptor + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL. + InterfaceNum - Report interface number. + DescriptorSize - Length of DescriptorBuffer. + DescriptorBuffer - Caller allocated buffer to store Usb report descriptor + if successfully returned. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_TIMEOUT + +--*/ +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + // + // Fill Device request packet + // + Request.RequestType = 0x81; + Request.Request = 0x06; + Request.Value = (UINT16) (0x22 << 8); + Request.Index = InterfaceNum; + Request.Length = DescriptorSize; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataIn, + TIMEOUT_VALUE, + DescriptorBuffer, + DescriptorSize, + &Status + ); + + return Result; + +} +// +// Following are HID class request +// +EFI_STATUS +UsbGetProtocolRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 *Protocol + ) +/*++ + + Routine Description: + Get Hid Protocol Request + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL + Interface - Which interface the caller wants to get protocol + Protocol - Protocol value returned. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_TIMEOUT + +--*/ +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + // + // Fill Device request packet + // + Request.RequestType = 0xa1; + // + // 10100001b; + // + Request.Request = EFI_USB_GET_PROTOCOL_REQUEST; + Request.Value = 0; + Request.Index = Interface; + Request.Length = 1; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataIn, + TIMEOUT_VALUE, + Protocol, + sizeof (UINT8), + &Status + ); + + return Result; +} + + +EFI_STATUS +UsbSetProtocolRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 Protocol + ) +/*++ + + Routine Description: + Set Hid Protocol Request + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL + Interface - Which interface the caller wants to set protocol + Protocol - Protocol value the caller wants to set. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_TIMEOUT + +--*/ +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + // + // Fill Device request packet + // + Request.RequestType = 0x21; + // + // 00100001b; + // + Request.Request = EFI_USB_SET_PROTOCOL_REQUEST; + Request.Value = Protocol; + Request.Index = Interface; + Request.Length = 0; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbNoData, + TIMEOUT_VALUE, + NULL, + 0, + &Status + ); + return Result; +} + + +EFI_STATUS +UsbSetIdleRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + IN UINT8 Duration + ) +/*++ + + Routine Description: + Set Idel request. + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL + Interface - Which interface the caller wants to set. + ReportId - Which report the caller wants to set. + Duration - Idle rate the caller wants to set. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_TIMEOUT + +--*/ +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + // + // Fill Device request packet + // + Request.RequestType = 0x21; + // + // 00100001b; + // + Request.Request = EFI_USB_SET_IDLE_REQUEST; + Request.Value = (UINT16) ((Duration << 8) | ReportId); + Request.Index = Interface; + Request.Length = 0; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbNoData, + TIMEOUT_VALUE, + NULL, + 0, + &Status + ); + return Result; +} + +EFI_STATUS +UsbGetIdleRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + OUT UINT8 *Duration + ) +/*++ + + Routine Description: + Get Idel request. + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL + Interface - Which interface the caller wants to get. + ReportId - Which report the caller wants to get. + Duration - Idle rate the caller wants to get. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_TIMEOUT + +--*/ +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + // + // Fill Device request packet + // + Request.RequestType = 0xa1; + // + // 10100001b; + // + Request.Request = EFI_USB_GET_IDLE_REQUEST; + Request.Value = ReportId; + Request.Index = Interface; + Request.Length = 1; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataIn, + TIMEOUT_VALUE, + Duration, + 1, + &Status + ); + + return Result; +} + + +EFI_STATUS +UsbSetReportRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + IN UINT8 ReportType, + IN UINT16 ReportLen, + IN UINT8 *Report + ) +/*++ + + Routine Description: + Hid Set Report request. + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL + Interface - Which interface the caller wants to set. + ReportId - Which report the caller wants to set. + ReportType - Type of report. + ReportLen - Length of report descriptor. + Report - Report Descriptor buffer. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_TIMEOUT + +--*/ +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + // + // Fill Device request packet + // + Request.RequestType = 0x21; + // + // 00100001b; + // + Request.Request = EFI_USB_SET_REPORT_REQUEST; + Request.Value = (UINT16) ((ReportType << 8) | ReportId); + Request.Index = Interface; + Request.Length = ReportLen; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataOut, + TIMEOUT_VALUE, + Report, + ReportLen, + &Status + ); + + return Result; +} + +EFI_STATUS +UsbGetReportRequest ( + IN EFI_USB_IO_PROTOCOL *UsbIo, + IN UINT8 Interface, + IN UINT8 ReportId, + IN UINT8 ReportType, + IN UINT16 ReportLen, + IN UINT8 *Report + ) +/*++ + + Routine Description: + Hid Set Report request. + + Arguments: + UsbIo - EFI_USB_IO_PROTOCOL + Interface - Which interface the caller wants to set. + ReportId - Which report the caller wants to set. + ReportType - Type of report. + ReportLen - Length of report descriptor. + Report - Caller allocated buffer to store Report Descriptor. + + Returns: + EFI_SUCCESS + EFI_DEVICE_ERROR + EFI_TIMEOUT + +--*/ +{ + UINT32 Status; + EFI_STATUS Result; + EFI_USB_DEVICE_REQUEST Request; + + // + // Fill Device request packet + // + Request.RequestType = 0xa1; + // + // 10100001b; + // + Request.Request = EFI_USB_GET_REPORT_REQUEST; + Request.Value = (UINT16) ((ReportType << 8) | ReportId); + Request.Index = Interface; + Request.Length = ReportLen; + + Result = UsbIo->UsbControlTransfer ( + UsbIo, + &Request, + EfiUsbDataIn, + TIMEOUT_VALUE, + Report, + ReportLen, + &Status + ); + + return Result; +} diff --git a/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ComponentName.c b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ComponentName.c new file mode 100644 index 0000000000..dc2a22f447 --- /dev/null +++ b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ComponentName.c @@ -0,0 +1,531 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "ConSplitter.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +ConSplitterComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +ConSplitterConInComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +EFI_STATUS +EFIAPI +ConSplitterConOutComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +EFI_STATUS +EFIAPI +ConSplitterStdErrComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gConSplitterConInComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterConInComponentNameGetControllerName, + "eng" +}; + +EFI_COMPONENT_NAME_PROTOCOL gConSplitterSimplePointerComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterSimplePointerComponentNameGetControllerName, + "eng" +}; + +EFI_COMPONENT_NAME_PROTOCOL gConSplitterConOutComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterConOutComponentNameGetControllerName, + "eng" +}; + +EFI_COMPONENT_NAME_PROTOCOL gConSplitterStdErrComponentName = { + ConSplitterComponentNameGetDriverName, + ConSplitterStdErrComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mConSplitterDriverNameTable[] = { + { + "eng", + (CHAR16 *) L"Console Splitter Driver" + }, + { + NULL, + NULL + } +}; + +static EFI_UNICODE_STRING_TABLE mConSplitterConInControllerNameTable[] = { + { + "eng", + (CHAR16 *) L"Primary Console Input Device" + }, + { + NULL, + NULL + } +}; + +static EFI_UNICODE_STRING_TABLE mConSplitterSimplePointerControllerNameTable[] = { + { + "eng", + (CHAR16 *) L"Primary Simple Pointer Device" + }, + { + NULL, + NULL + } +}; + +static EFI_UNICODE_STRING_TABLE mConSplitterConOutControllerNameTable[] = { + { + "eng", + (CHAR16 *) L"Primary Console Output Device" + }, + { + NULL, + NULL + } +}; + +static EFI_UNICODE_STRING_TABLE mConSplitterStdErrControllerNameTable[] = { + { + "eng", + (CHAR16 *) L"Primary Standard Error Device" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +ConSplitterComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gConSplitterConInComponentName.SupportedLanguages, + mConSplitterDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +ConSplitterConInComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_IN_PROTOCOL *TextIn; + // + // here ChildHandle is not an Optional parameter. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &TextIn, + NULL, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return LookupUnicodeString ( + Language, + gConSplitterConInComponentName.SupportedLanguages, + mConSplitterConInControllerNameTable, + ControllerName + ); +} + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer; + // + // here ChildHandle is not an Optional parameter. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointer, + NULL, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return LookupUnicodeString ( + Language, + gConSplitterSimplePointerComponentName.SupportedLanguages, + mConSplitterSimplePointerControllerNameTable, + ControllerName + ); +} + +EFI_STATUS +EFIAPI +ConSplitterConOutComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut; + // + // here ChildHandle is not an Optional parameter. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut, + NULL, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return LookupUnicodeString ( + Language, + gConSplitterConOutComponentName.SupportedLanguages, + mConSplitterConOutControllerNameTable, + ControllerName + ); +} + +EFI_STATUS +EFIAPI +ConSplitterStdErrComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *ErrOut; + // + // here ChildHandle is not an Optional parameter. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &ErrOut, + NULL, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + return LookupUnicodeString ( + Language, + gConSplitterStdErrComponentName.SupportedLanguages, + mConSplitterStdErrControllerNameTable, + ControllerName + ); +} diff --git a/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.c b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.c new file mode 100644 index 0000000000..a9d39e945e --- /dev/null +++ b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.c @@ -0,0 +1,3193 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ConSplitter.c + +Abstract: + + Console Splitter Driver. Any Handle that attatched + EFI_CONSOLE_IDENTIFIER_PROTOCOL can be bound by this driver. + + So far it works like any other driver by opening a SimpleTextIn and/or + SimpleTextOut protocol with EFI_OPEN_PROTOCOL_BY_DRIVER attributes. The big + difference is this driver does not layer a protocol on the passed in + handle, or construct a child handle like a standard device or bus driver. + This driver produces three virtual handles as children, one for console input + splitter, one for console output splitter and one for error output splitter. + EFI_CONSOLE_SPLIT_PROTOCOL will be attatched onto each virtual handle to + identify the splitter type. + + Each virtual handle, that supports both the EFI_CONSOLE_SPLIT_PROTOCOL + and Console I/O protocol, will be produced in the driver entry point. + The virtual handle are added on driver entry and never removed. + Such design ensures sytem function well during none console device situation. + +--*/ + +#include "ConSplitter.h" + +// +// Global Variables +// +static TEXT_IN_SPLITTER_PRIVATE_DATA mConIn = { + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE, + (EFI_HANDLE) NULL, + { + ConSplitterTextInReset, + ConSplitterTextInReadKeyStroke, + (EFI_EVENT) NULL + }, + 0, + (EFI_SIMPLE_TEXT_IN_PROTOCOL **) NULL, + 0, + + { + ConSplitterSimplePointerReset, + ConSplitterSimplePointerGetState, + (EFI_EVENT) NULL, + (EFI_SIMPLE_POINTER_MODE *) NULL + }, + { + 0x10000, + 0x10000, + 0x10000, + TRUE, + TRUE + }, + 0, + (EFI_SIMPLE_POINTER_PROTOCOL **) NULL, + 0, + + FALSE, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + 0, + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + }, + (EFI_EVENT) NULL, + + FALSE, + FALSE +}; + +static TEXT_OUT_SPLITTER_PRIVATE_DATA mConOut = { + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE, + (EFI_HANDLE) NULL, + { + ConSplitterTextOutReset, + ConSplitterTextOutOutputString, + ConSplitterTextOutTestString, + ConSplitterTextOutQueryMode, + ConSplitterTextOutSetMode, + ConSplitterTextOutSetAttribute, + ConSplitterTextOutClearScreen, + ConSplitterTextOutSetCursorPosition, + ConSplitterTextOutEnableCursor, + (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL + }, + { + 1, + 0, + 0, + 0, + 0, + FALSE, + }, + { + ConSpliterUgaDrawGetMode, + ConSpliterUgaDrawSetMode, + ConSpliterUgaDrawBlt + }, + 0, + 0, + 0, + 0, + (EFI_UGA_PIXEL *) NULL, + + { + ConSpliterConsoleControlGetMode, + ConSpliterConsoleControlSetMode, + ConSpliterConsoleControlLockStdIn + }, + + 0, + (TEXT_OUT_AND_UGA_DATA *) NULL, + 0, + (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL, + 0, + (INT32 *) NULL, + + EfiConsoleControlScreenText, + 0, + 0, + (CHAR16 *) NULL, + (INT32 *) NULL +}; + +static TEXT_OUT_SPLITTER_PRIVATE_DATA mStdErr = { + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE, + (EFI_HANDLE) NULL, + { + ConSplitterTextOutReset, + ConSplitterTextOutOutputString, + ConSplitterTextOutTestString, + ConSplitterTextOutQueryMode, + ConSplitterTextOutSetMode, + ConSplitterTextOutSetAttribute, + ConSplitterTextOutClearScreen, + ConSplitterTextOutSetCursorPosition, + ConSplitterTextOutEnableCursor, + (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL + }, + { + 1, + 0, + 0, + 0, + 0, + FALSE, + }, + { + ConSpliterUgaDrawGetMode, + ConSpliterUgaDrawSetMode, + ConSpliterUgaDrawBlt + }, + 0, + 0, + 0, + 0, + (EFI_UGA_PIXEL *) NULL, + + { + ConSpliterConsoleControlGetMode, + ConSpliterConsoleControlSetMode, + ConSpliterConsoleControlLockStdIn + }, + + 0, + (TEXT_OUT_AND_UGA_DATA *) NULL, + 0, + (TEXT_OUT_SPLITTER_QUERY_DATA *) NULL, + 0, + (INT32 *) NULL, + + EfiConsoleControlScreenText, + 0, + 0, + (CHAR16 *) NULL, + (INT32 *) NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gConSplitterConInDriverBinding = { + ConSplitterConInDriverBindingSupported, + ConSplitterConInDriverBindingStart, + ConSplitterConInDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gConSplitterSimplePointerDriverBinding = { + ConSplitterSimplePointerDriverBindingSupported, + ConSplitterSimplePointerDriverBindingStart, + ConSplitterSimplePointerDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gConSplitterConOutDriverBinding = { + ConSplitterConOutDriverBindingSupported, + ConSplitterConOutDriverBindingStart, + ConSplitterConOutDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gConSplitterStdErrDriverBinding = { + ConSplitterStdErrDriverBindingSupported, + ConSplitterStdErrDriverBindingStart, + ConSplitterStdErrDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +ConSplitterDriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Intialize a virtual console device to act as an agrigator of physical console + devices. + +Arguments: + ImageHandle - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + SystemTable - (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) +Returns: + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + // + // The driver creates virtual handles for ConIn, ConOut, and StdErr. + // The virtual handles will always exist even if no console exist in the + // system. This is need to support hotplug devices like USB. + // + // + // Create virtual device handle for StdErr Splitter + // + Status = ConSplitterTextOutConstructor (&mStdErr); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mStdErr.VirtualHandle, + &gEfiSimpleTextOutProtocolGuid, + &mStdErr.TextOut, + &gEfiPrimaryStandardErrorDeviceGuid, + NULL, + NULL + ); + } + // + // Create virtual device handle for ConIn Splitter + // + Status = ConSplitterTextInConstructor (&mConIn); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mConIn.VirtualHandle, + &gEfiSimpleTextInProtocolGuid, + &mConIn.TextIn, + &gEfiSimplePointerProtocolGuid, + &mConIn.SimplePointer, + &gEfiPrimaryConsoleInDeviceGuid, + NULL, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Update the EFI System Table with new virtual console + // + gST->ConsoleInHandle = mConIn.VirtualHandle; + gST->ConIn = &mConIn.TextIn; + } + } + // + // Create virtual device handle for ConOut Splitter + // + Status = ConSplitterTextOutConstructor (&mConOut); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &mConOut.VirtualHandle, + &gEfiSimpleTextOutProtocolGuid, + &mConOut.TextOut, + &gEfiUgaDrawProtocolGuid, + &mConOut.UgaDraw, + &gEfiConsoleControlProtocolGuid, + &mConOut.ConsoleControl, + &gEfiPrimaryConsoleOutDeviceGuid, + NULL, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Update the EFI System Table with new virtual console + // + gST->ConsoleOutHandle = mConOut.VirtualHandle; + gST->ConOut = &mConOut.TextOut; + } + + } + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *) &gST->Hdr, + gST->Hdr.HeaderSize, + &gST->Hdr.CRC32 + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +ConSplitterTextInConstructor ( + TEXT_IN_SPLITTER_PRIVATE_DATA *ConInPrivate + ) +/*++ + +Routine Description: + + Construct the ConSplitter. + +Arguments: + + ConInPrivate - A pointer to the TEXT_IN_SPLITTER_PRIVATE_DATA structure. + +Returns: + EFI_OUT_OF_RESOURCES - Out of resources. + +--*/ +{ + EFI_STATUS Status; + + // + // Initilize console input splitter's private data. + // + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL *), + &ConInPrivate->TextInListCount, + (VOID **) &ConInPrivate->TextInList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Create Event to support locking StdIn Device + // + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + ConSpliterConsoleControlLockStdInEvent, + NULL, + &ConInPrivate->LockEvent + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_WAIT, + EFI_TPL_NOTIFY, + ConSplitterTextInWaitForKey, + ConInPrivate, + &ConInPrivate->TextIn.WaitForKey + ); + ASSERT_EFI_ERROR (Status); + + ConInPrivate->SimplePointer.Mode = &ConInPrivate->SimplePointerMode; + + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_POINTER_PROTOCOL *), + &ConInPrivate->PointerListCount, + (VOID **) &ConInPrivate->PointerList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_WAIT, + EFI_TPL_NOTIFY, + ConSplitterSimplePointerWaitForInput, + ConInPrivate, + &ConInPrivate->SimplePointer.WaitForInput + ); + + return Status; +} + + +EFI_STATUS +ConSplitterTextOutConstructor ( + TEXT_OUT_SPLITTER_PRIVATE_DATA *ConOutPrivate + ) +{ + EFI_STATUS Status; + + // + // Initilize console output splitter's private data. + // + ConOutPrivate->TextOut.Mode = &ConOutPrivate->TextOutMode; + + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_AND_UGA_DATA), + &ConOutPrivate->TextOutListCount, + (VOID **) &ConOutPrivate->TextOutList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_SPLITTER_QUERY_DATA), + &ConOutPrivate->TextOutQueryDataCount, + (VOID **) &ConOutPrivate->TextOutQueryData + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Setup the DevNullTextOut console to 80 x 25 + // + ConOutPrivate->TextOutQueryData[0].Columns = 80; + ConOutPrivate->TextOutQueryData[0].Rows = 25; + DevNullTextOutSetMode (ConOutPrivate, 0); + + // + // Setup the DevNullUgaDraw to 800 x 600 x 32 bits per pixel + // + ConSpliterUgaDrawSetMode (&ConOutPrivate->UgaDraw, 800, 600, 32, 60); + + return Status; +} + + +EFI_STATUS +ConSplitterSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_GUID *Guid + ) +/*++ + +Routine Description: + Generic Supported Check + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller Handle. + Guid - Guid. + +Returns: + + EFI_UNSUPPORTED - unsupported. + EFI_SUCCESS - operation is OK. + +--*/ +{ + EFI_STATUS Status; + VOID *Instance; + + // + // Make sure the Console Splitter does not attempt to attach to itself + // + if (ControllerHandle == mConIn.VirtualHandle) { + return EFI_UNSUPPORTED; + } + + if (ControllerHandle == mConOut.VirtualHandle) { + return EFI_UNSUPPORTED; + } + + if (ControllerHandle == mStdErr.VirtualHandle) { + return EFI_UNSUPPORTED; + } + // + // Check to see whether the handle has the ConsoleInDevice GUID on it + // + Status = gBS->OpenProtocol ( + ControllerHandle, + Guid, + &Instance, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + ControllerHandle, + Guid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Console In Supported Check + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_STATUS + +--*/ +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiConsoleInDeviceGuid + ); +} + + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Standard Error Supported Check + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_STATUS + +--*/ +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiSimplePointerProtocolGuid + ); +} + + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Console Out Supported Check + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_STATUS + +--*/ +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiConsoleOutDeviceGuid + ); +} + + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Standard Error Supported Check + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_STATUS + +--*/ +{ + return ConSplitterSupported ( + This, + ControllerHandle, + &gEfiStandardErrorDeviceGuid + ); +} + + +EFI_STATUS +EFIAPI +ConSplitterStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ConSplitterVirtualHandle, + IN EFI_GUID *DeviceGuid, + IN EFI_GUID *InterfaceGuid, + IN VOID **Interface + ) +/*++ + +Routine Description: + Start ConSplitter on ControllerHandle, and create the virtual + agrogated console device on first call Start for a SimpleTextIn handle. + +Arguments: + (Standard DriverBinding Protocol Start() function) + +Returns: + EFI_ERROR if a SimpleTextIn protocol is not started. + +--*/ +{ + EFI_STATUS Status; + VOID *Instance; + + // + // Check to see whether the handle has the ConsoleInDevice GUID on it + // + Status = gBS->OpenProtocol ( + ControllerHandle, + DeviceGuid, + &Instance, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + DeviceGuid, + &Instance, + This->DriverBindingHandle, + ConSplitterVirtualHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return gBS->OpenProtocol ( + ControllerHandle, + InterfaceGuid, + Interface, + This->DriverBindingHandle, + ConSplitterVirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); +} + + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Start ConSplitter on ControllerHandle, and create the virtual + agrogated console device on first call Start for a SimpleTextIn handle. + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_STATUS + EFI_ERROR if a SimpleTextIn protocol is not started. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_IN_PROTOCOL *TextIn; + + // + // Start ConSplitter on ControllerHandle, and create the virtual + // agrogated console device on first call Start for a SimpleTextIn handle. + // + Status = ConSplitterStart ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiConsoleInDeviceGuid, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &TextIn + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return ConSplitterTextInAddDevice (&mConIn, TextIn); +} + + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Start ConSplitter on ControllerHandle, and create the virtual + agrogated console device on first call Start for a SimpleTextIn handle. + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + + EFI_ERROR if a SimpleTextIn protocol is not started. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer; + + Status = ConSplitterStart ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiSimplePointerProtocolGuid, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return ConSplitterSimplePointerAddDevice (&mConIn, SimplePointer); +} + + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Start ConSplitter on ControllerHandle, and create the virtual + agrogated console device on first call Start for a SimpleTextIn handle. + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + EFI_ERROR if a SimpleTextIn protocol is not started. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + + Status = ConSplitterStart ( + This, + ControllerHandle, + mConOut.VirtualHandle, + &gEfiConsoleOutDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open UGA_DRAW protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw, + This->DriverBindingHandle, + mConOut.VirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + UgaDraw = NULL; + } + // + // If both ConOut and StdErr incorporate the same Text Out device, + // their MaxMode and QueryData should be the intersection of both. + // + Status = ConSplitterTextOutAddDevice (&mConOut, TextOut, UgaDraw); + ConSplitterTextOutSetAttribute (&mConOut.TextOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + // + // Match the UGA mode data of ConOut with the current mode + // + if (UgaDraw) { + UgaDraw->GetMode ( + UgaDraw, + &mConOut.UgaHorizontalResolution, + &mConOut.UgaVerticalResolution, + &mConOut.UgaColorDepth, + &mConOut.UgaRefreshRate + ); + } + return Status; +} + + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Start ConSplitter on ControllerHandle, and create the virtual + agrogated console device on first call Start for a SimpleTextIn handle. + +Arguments: + This - Pointer to protocol. + ControllerHandle - Controller handle. + RemainingDevicePath - Remaining device path. + +Returns: + EFI_ERROR if a SimpleTextIn protocol is not started. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut; + + Status = ConSplitterStart ( + This, + ControllerHandle, + mStdErr.VirtualHandle, + &gEfiStandardErrorDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // If both ConOut and StdErr incorporate the same Text Out device, + // their MaxMode and QueryData should be the intersection of both. + // + Status = ConSplitterTextOutAddDevice (&mStdErr, TextOut, NULL); + ConSplitterTextOutSetAttribute (&mStdErr.TextOut, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK)); + if (EFI_ERROR (Status)) { + return Status; + } + + if (mStdErr.CurrentNumberOfConsoles == 1) { + gST->StandardErrorHandle = mStdErr.VirtualHandle; + gST->StdErr = &mStdErr.TextOut; + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *) &gST->Hdr, + gST->Hdr.HeaderSize, + &gST->Hdr.CRC32 + ); + } + + return Status; +} + + +EFI_STATUS +EFIAPI +ConSplitterStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ConSplitterVirtualHandle, + IN EFI_GUID *DeviceGuid, + IN EFI_GUID *InterfaceGuid, + IN VOID **Interface + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( + ControllerHandle, + InterfaceGuid, + Interface, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // close the protocol refered. + // + gBS->CloseProtocol ( + ControllerHandle, + DeviceGuid, + This->DriverBindingHandle, + ConSplitterVirtualHandle + ); + gBS->CloseProtocol ( + ControllerHandle, + DeviceGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_IN_PROTOCOL *TextIn; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + Status = ConSplitterStop ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiConsoleInDeviceGuid, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &TextIn + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Delete this console input device's data structures. + // + return ConSplitterTextInDeleteDevice (&mConIn, TextIn); +} + + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + Status = ConSplitterStop ( + This, + ControllerHandle, + mConIn.VirtualHandle, + &gEfiSimplePointerProtocolGuid, + &gEfiSimplePointerProtocolGuid, + (VOID **) &SimplePointer + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Delete this console input device's data structures. + // + return ConSplitterSimplePointerDeleteDevice (&mConIn, SimplePointer); +} + + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + Status = ConSplitterStop ( + This, + ControllerHandle, + mConOut.VirtualHandle, + &gEfiConsoleOutDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Remove any UGA devices + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw, + This->DriverBindingHandle, + mConOut.VirtualHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + // + // Delete this console output device's data structures. + // + return ConSplitterTextOutDeleteDevice (&mConOut, TextOut); +} + + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + EFI_SUCCESS - Complete successfully. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut; + + if (NumberOfChildren == 0) { + return EFI_SUCCESS; + } + + Status = ConSplitterStop ( + This, + ControllerHandle, + mStdErr.VirtualHandle, + &gEfiStandardErrorDeviceGuid, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Delete this console error out device's data structures. + // + Status = ConSplitterTextOutDeleteDevice (&mStdErr, TextOut); + if (EFI_ERROR (Status)) { + return Status; + } + + if (mStdErr.CurrentNumberOfConsoles == 0) { + gST->StandardErrorHandle = NULL; + gST->StdErr = NULL; + // + // Update the CRC32 in the EFI System Table header + // + gST->Hdr.CRC32 = 0; + gBS->CalculateCrc32 ( + (UINT8 *) &gST->Hdr, + gST->Hdr.HeaderSize, + &gST->Hdr.CRC32 + ); + } + + return Status; +} + +EFI_STATUS +ConSplitterGrowBuffer ( + IN UINTN SizeOfCount, + IN UINTN *Count, + IN OUT VOID **Buffer + ) +/*++ + +Routine Description: + Take the passed in Buffer of size SizeOfCount and grow the buffer + by MAX (CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT, MaxGrow) * SizeOfCount + bytes. Copy the current data in Buffer to the new version of Buffer + and free the old version of buffer. + + +Arguments: + SizeOfCount - Size of element in array + Count - Current number of elements in array + Buffer - Bigger version of passed in Buffer with all the data + +Returns: + EFI_SUCCESS - Buffer size has grown + EFI_OUT_OF_RESOURCES - Could not grow the buffer size + + None + +--*/ +{ + UINTN NewSize; + UINTN OldSize; + VOID *Ptr; + + // + // grow the buffer to new buffer size, + // copy the old buffer's content to the new-size buffer, + // then free the old buffer. + // + OldSize = *Count * SizeOfCount; + *Count += CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT; + NewSize = *Count * SizeOfCount; + + Ptr = AllocateZeroPool (NewSize); + if (Ptr == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (Ptr, *Buffer, OldSize); + + if (*Buffer != NULL) { + gBS->FreePool (*Buffer); + } + + *Buffer = Ptr; + + return EFI_SUCCESS; +} + +EFI_STATUS +ConSplitterTextInAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *TextIn + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + EFI_SUCCESS + EFI_OUT_OF_RESOURCES + +--*/ +{ + EFI_STATUS Status; + + // + // If the Text In List is full, enlarge it by calling growbuffer(). + // + if (Private->CurrentNumberOfConsoles >= Private->TextInListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_TEXT_IN_PROTOCOL *), + &Private->TextInListCount, + (VOID **) &Private->TextInList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Add the new text-in device data structure into the Text In List. + // + Private->TextInList[Private->CurrentNumberOfConsoles] = TextIn; + Private->CurrentNumberOfConsoles++; + + // + // Extra CheckEvent added to reduce the double CheckEvent() in UI.c + // + gBS->CheckEvent (TextIn->WaitForKey); + + return EFI_SUCCESS; +} + +EFI_STATUS +ConSplitterTextInDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *TextIn + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + UINTN Index; + // + // Remove the specified text-in device data structure from the Text In List, + // and rearrange the remaining data structures in the Text In List. + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + if (Private->TextInList[Index] == TextIn) { + for (Index = Index; Index < Private->CurrentNumberOfConsoles - 1; Index++) { + Private->TextInList[Index] = Private->TextInList[Index + 1]; + } + + Private->CurrentNumberOfConsoles--; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +ConSplitterSimplePointerAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + EFI_OUT_OF_RESOURCES + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + // + // If the Text In List is full, enlarge it by calling growbuffer(). + // + if (Private->CurrentNumberOfPointers >= Private->PointerListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (EFI_SIMPLE_POINTER_PROTOCOL *), + &Private->PointerListCount, + (VOID **) &Private->PointerList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Add the new text-in device data structure into the Text In List. + // + Private->PointerList[Private->CurrentNumberOfPointers] = SimplePointer; + Private->CurrentNumberOfPointers++; + return EFI_SUCCESS; +} + +EFI_STATUS +ConSplitterSimplePointerDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINTN Index; + // + // Remove the specified text-in device data structure from the Text In List, + // and rearrange the remaining data structures in the Text In List. + // + for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) { + if (Private->PointerList[Index] == SimplePointer) { + for (Index = Index; Index < Private->CurrentNumberOfPointers - 1; Index++) { + Private->PointerList[Index] = Private->PointerList[Index + 1]; + } + + Private->CurrentNumberOfPointers--; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +ConSplitterGrowMapTable ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINTN Size; + UINTN NewSize; + UINTN TotalSize; + INT32 *TextOutModeMap; + INT32 *OldTextOutModeMap; + INT32 *SrcAddress; + INT32 Index; + + NewSize = Private->TextOutListCount * sizeof (INT32); + OldTextOutModeMap = Private->TextOutModeMap; + TotalSize = NewSize * Private->TextOutQueryDataCount; + + TextOutModeMap = AllocateZeroPool (TotalSize); + if (TextOutModeMap == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (TextOutModeMap, TotalSize, 0xFF); + Private->TextOutModeMap = TextOutModeMap; + + // + // If TextOutList has been enlarged, need to realloc the mode map table + // The mode map table is regarded as a two dimension array. + // + // Old New + // 0 ---------> TextOutListCount ----> TextOutListCount + // | ------------------------------------------- + // | | | | + // | | | | + // | | | | + // | | | | + // | | | | + // \/ | | | + // ------------------------------------------- + // QueryDataCount + // + if (OldTextOutModeMap != NULL) { + + Size = Private->CurrentNumberOfConsoles * sizeof (INT32); + Index = 0; + SrcAddress = OldTextOutModeMap; + + // + // Copy the old data to the new one + // + while (Index < Private->TextOutMode.MaxMode) { + CopyMem (TextOutModeMap, SrcAddress, Size); + TextOutModeMap += NewSize; + SrcAddress += Size; + Index++; + } + // + // Free the old buffer + // + gBS->FreePool (OldTextOutModeMap); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ConSplitterAddOutputMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + INT32 MaxMode; + INT32 Mode; + UINTN Index; + + MaxMode = TextOut->Mode->MaxMode; + Private->TextOutMode.MaxMode = MaxMode; + + // + // Grow the buffer if query data buffer is not large enough to + // hold all the mode supported by the first console. + // + while (MaxMode > (INT32) Private->TextOutQueryDataCount) { + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_SPLITTER_QUERY_DATA), + &Private->TextOutQueryDataCount, + (VOID **) &Private->TextOutQueryData + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + // + // Allocate buffer for the output mode map + // + Status = ConSplitterGrowMapTable (Private); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // As the first textout device, directly add the mode in to QueryData + // and at the same time record the mapping between QueryData and TextOut. + // + Mode = 0; + Index = 0; + while (Mode < MaxMode) { + TextOut->QueryMode ( + TextOut, + Mode, + &Private->TextOutQueryData[Mode].Columns, + &Private->TextOutQueryData[Mode].Rows + ); + Private->TextOutModeMap[Index] = Mode; + Mode++; + Index += Private->TextOutListCount; + } + + return EFI_SUCCESS; +} + +VOID +ConSplitterGetIntersection ( + IN INT32 *TextOutModeMap, + IN INT32 *NewlyAddedMap, + IN UINTN MapStepSize, + IN UINTN NewMapStepSize, + OUT INT32 *MaxMode, + OUT INT32 *CurrentMode + ) +{ + INT32 Index; + INT32 *CurrentMapEntry; + INT32 *NextMapEntry; + INT32 CurrentMaxMode; + INT32 Mode; + + Index = 0; + CurrentMapEntry = TextOutModeMap; + NextMapEntry = TextOutModeMap; + CurrentMaxMode = *MaxMode; + Mode = *CurrentMode; + + while (Index < CurrentMaxMode) { + if (*NewlyAddedMap == -1) { + // + // This mode is not supported any more. Remove it. Special care + // must be taken as this remove will also affect current mode; + // + if (Index == *CurrentMode) { + Mode = -1; + } else if (Index < *CurrentMode) { + Mode--; + } + (*MaxMode)--; + } else { + if (CurrentMapEntry != NextMapEntry) { + CopyMem (NextMapEntry, CurrentMapEntry, MapStepSize * sizeof (INT32)); + } + + NextMapEntry += MapStepSize; + } + + CurrentMapEntry += MapStepSize; + NewlyAddedMap += NewMapStepSize; + Index++; + } + + *CurrentMode = Mode; + + return ; +} + +VOID +ConSplitterSyncOutputMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut + ) +/*++ + +Routine Description: + +Arguments: + Private - Private data structure. + TextOut - Text Out Protocol. +Returns: + + None + +--*/ +{ + INT32 CurrentMode; + INT32 CurrentMaxMode; + INT32 Mode; + INT32 Index; + INT32 *TextOutModeMap; + INT32 *MapTable; + TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData; + UINTN Rows; + UINTN Columns; + UINTN StepSize; + + // + // Must make sure that current mode won't change even if mode number changes + // + CurrentMode = Private->TextOutMode.Mode; + CurrentMaxMode = Private->TextOutMode.MaxMode; + TextOutModeMap = Private->TextOutModeMap; + StepSize = Private->TextOutListCount; + TextOutQueryData = Private->TextOutQueryData; + + // + // Query all the mode that the newly added TextOut supports + // + Mode = 0; + MapTable = TextOutModeMap + Private->CurrentNumberOfConsoles; + while (Mode < TextOut->Mode->MaxMode) { + TextOut->QueryMode (TextOut, Mode, &Columns, &Rows); + + // + // Search the QueryData database to see if they intersects + // + Index = 0; + while (Index < CurrentMaxMode) { + if ((TextOutQueryData[Index].Rows == Rows) && (TextOutQueryData[Index].Columns == Columns)) { + MapTable[Index * StepSize] = Mode; + break; + } + + Index++; + } + + Mode++; + } + // + // Now search the TextOutModeMap table to find the intersection of supported + // mode between ConSplitter and the newly added device. + // + ConSplitterGetIntersection ( + TextOutModeMap, + MapTable, + StepSize, + StepSize, + &Private->TextOutMode.MaxMode, + &Private->TextOutMode.Mode + ); + + return ; +} + +EFI_STATUS +ConSplitterGetIntersectionBetweenConOutAndStrErr ( + VOID + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + UINTN ConOutNumOfConsoles; + UINTN StdErrNumOfConsoles; + TEXT_OUT_AND_UGA_DATA *ConOutTextOutList; + TEXT_OUT_AND_UGA_DATA *StdErrTextOutList; + UINTN Indexi; + UINTN Indexj; + UINTN Rows; + UINTN Columns; + INT32 ConOutCurrentMode; + INT32 StdErrCurrentMode; + INT32 ConOutMaxMode; + INT32 StdErrMaxMode; + INT32 Mode; + INT32 Index; + INT32 *ConOutModeMap; + INT32 *StdErrModeMap; + INT32 *ConOutMapTable; + INT32 *StdErrMapTable; + TEXT_OUT_SPLITTER_QUERY_DATA *ConOutQueryData; + TEXT_OUT_SPLITTER_QUERY_DATA *StdErrQueryData; + UINTN ConOutStepSize; + UINTN StdErrStepSize; + BOOLEAN FoundTheSameTextOut; + UINTN ConOutMapTableSize; + UINTN StdErrMapTableSize; + + ConOutNumOfConsoles = mConOut.CurrentNumberOfConsoles; + StdErrNumOfConsoles = mStdErr.CurrentNumberOfConsoles; + ConOutTextOutList = mConOut.TextOutList; + StdErrTextOutList = mStdErr.TextOutList; + + Indexi = 0; + FoundTheSameTextOut = FALSE; + while ((Indexi < ConOutNumOfConsoles) && (!FoundTheSameTextOut)) { + Indexj = 0; + while (Indexj < StdErrNumOfConsoles) { + if (ConOutTextOutList->TextOut == StdErrTextOutList->TextOut) { + FoundTheSameTextOut = TRUE; + break; + } + + Indexj++; + StdErrTextOutList++; + } + + Indexi++; + ConOutTextOutList++; + } + + if (!FoundTheSameTextOut) { + return EFI_SUCCESS; + } + // + // Must make sure that current mode won't change even if mode number changes + // + ConOutCurrentMode = mConOut.TextOutMode.Mode; + ConOutMaxMode = mConOut.TextOutMode.MaxMode; + ConOutModeMap = mConOut.TextOutModeMap; + ConOutStepSize = mConOut.TextOutListCount; + ConOutQueryData = mConOut.TextOutQueryData; + + StdErrCurrentMode = mStdErr.TextOutMode.Mode; + StdErrMaxMode = mStdErr.TextOutMode.MaxMode; + StdErrModeMap = mStdErr.TextOutModeMap; + StdErrStepSize = mStdErr.TextOutListCount; + StdErrQueryData = mStdErr.TextOutQueryData; + + // + // Allocate the map table and set the map table's index to -1. + // + ConOutMapTableSize = ConOutMaxMode * sizeof (INT32); + ConOutMapTable = AllocateZeroPool (ConOutMapTableSize); + if (ConOutMapTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (ConOutMapTable, ConOutMapTableSize, 0xFF); + + StdErrMapTableSize = StdErrMaxMode * sizeof (INT32); + StdErrMapTable = AllocateZeroPool (StdErrMapTableSize); + if (StdErrMapTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (StdErrMapTable, StdErrMapTableSize, 0xFF); + + // + // Find the intersection of the two set of modes. If they actually intersect, the + // correponding entry in the map table is set to 1. + // + Mode = 0; + while (Mode < ConOutMaxMode) { + // + // Search the other's QueryData database to see if they intersect + // + Index = 0; + Rows = ConOutQueryData[Mode].Rows; + Columns = ConOutQueryData[Mode].Columns; + while (Index < StdErrMaxMode) { + if ((StdErrQueryData[Index].Rows == Rows) && (StdErrQueryData[Index].Columns == Columns)) { + ConOutMapTable[Mode] = 1; + StdErrMapTable[Index] = 1; + break; + } + + Index++; + } + + Mode++; + } + // + // Now search the TextOutModeMap table to find the intersection of supported + // mode between ConSplitter and the newly added device. + // + ConSplitterGetIntersection ( + ConOutModeMap, + ConOutMapTable, + mConOut.TextOutListCount, + 1, + &(mConOut.TextOutMode.MaxMode), + &(mConOut.TextOutMode.Mode) + ); + if (mConOut.TextOutMode.Mode < 0) { + mConOut.TextOut.SetMode (&(mConOut.TextOut), 0); + } + + ConSplitterGetIntersection ( + StdErrModeMap, + StdErrMapTable, + mStdErr.TextOutListCount, + 1, + &(mStdErr.TextOutMode.MaxMode), + &(mStdErr.TextOutMode.Mode) + ); + if (mStdErr.TextOutMode.Mode < 0) { + mStdErr.TextOut.SetMode (&(mStdErr.TextOut), 0); + } + + gBS->FreePool (ConOutMapTable); + gBS->FreePool (StdErrMapTable); + + return EFI_SUCCESS; +} + +EFI_STATUS +ConSplitterTextOutAddDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + UINTN CurrentNumOfConsoles; + INT32 CurrentMode; + INT32 MaxMode; + TEXT_OUT_AND_UGA_DATA *TextAndUga; + + Status = EFI_SUCCESS; + CurrentNumOfConsoles = Private->CurrentNumberOfConsoles; + + // + // If the Text Out List is full, enlarge it by calling growbuffer(). + // + while (CurrentNumOfConsoles >= Private->TextOutListCount) { + Status = ConSplitterGrowBuffer ( + sizeof (TEXT_OUT_AND_UGA_DATA), + &Private->TextOutListCount, + (VOID **) &Private->TextOutList + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Also need to reallocate the TextOutModeMap table + // + Status = ConSplitterGrowMapTable (Private); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + } + + TextAndUga = &Private->TextOutList[CurrentNumOfConsoles]; + + TextAndUga->TextOut = TextOut; + TextAndUga->UgaDraw = UgaDraw; + if (UgaDraw == NULL) { + // + // If No UGA device then use the ConOut device + // + TextAndUga->TextOutEnabled = TRUE; + } else { + // + // If UGA device use ConOut device only used if UGA screen is in Text mode + // + TextAndUga->TextOutEnabled = (BOOLEAN) (Private->UgaMode == EfiConsoleControlScreenText); + } + + if (CurrentNumOfConsoles == 0) { + // + // Add the first device's output mode to console splitter's mode list + // + Status = ConSplitterAddOutputMode (Private, TextOut); + } else { + ConSplitterSyncOutputMode (Private, TextOut); + } + + Private->CurrentNumberOfConsoles++; + + // + // Scan both TextOutList, for the intersection TextOut device + // maybe both ConOut and StdErr incorporate the same Text Out + // device in them, thus the output of both should be synced. + // + ConSplitterGetIntersectionBetweenConOutAndStrErr (); + + CurrentMode = Private->TextOutMode.Mode; + MaxMode = Private->TextOutMode.MaxMode; + ASSERT (MaxMode >= 1); + + if (Private->UgaMode == EfiConsoleControlScreenGraphics && UgaDraw != NULL) { + // + // We just added a new UGA device in graphics mode + // + DevNullUgaSync (Private, UgaDraw); + + } else if ((CurrentMode >= 0) && (UgaDraw != NULL) && (CurrentMode < Private->TextOutMode.MaxMode)) { + // + // The new console supports the same mode of the current console so sync up + // + DevNullSyncUgaStdOut (Private); + } else { + // + // If ConOut, then set the mode to Mode #0 which us 80 x 25 + // + Private->TextOut.SetMode (&Private->TextOut, 0); + } + + return Status; +} + +EFI_STATUS +ConSplitterTextOutDeleteDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +{ + INT32 Index; + UINTN CurrentNumOfConsoles; + TEXT_OUT_AND_UGA_DATA *TextOutList; + EFI_STATUS Status; + + // + // Remove the specified text-out device data structure from the Text out List, + // and rearrange the remaining data structures in the Text out List. + // + CurrentNumOfConsoles = Private->CurrentNumberOfConsoles; + Index = (INT32) CurrentNumOfConsoles - 1; + TextOutList = Private->TextOutList; + while (Index >= 0) { + if (TextOutList->TextOut == TextOut) { + CopyMem (TextOutList, TextOutList + 1, sizeof (TEXT_OUT_AND_UGA_DATA) * Index); + CurrentNumOfConsoles--; + break; + } + + Index--; + TextOutList++; + } + // + // The specified TextOut is not managed by the ConSplitter driver + // + if (Index < 0) { + return EFI_NOT_FOUND; + } + + if (CurrentNumOfConsoles == 0) { + // + // If the number of consoles is zero clear the Dev NULL device + // + Private->CurrentNumberOfConsoles = 0; + Private->TextOutMode.MaxMode = 1; + Private->TextOutQueryData[0].Columns = 80; + Private->TextOutQueryData[0].Rows = 25; + DevNullTextOutSetMode (Private, 0); + + return EFI_SUCCESS; + } + // + // Max Mode is realy an intersection of the QueryMode command to all + // devices. So we must copy the QueryMode of the first device to + // QueryData. + // + ZeroMem ( + Private->TextOutQueryData, + Private->TextOutQueryDataCount * sizeof (TEXT_OUT_SPLITTER_QUERY_DATA) + ); + + gBS->FreePool (Private->TextOutModeMap); + Private->TextOutModeMap = NULL; + TextOutList = Private->TextOutList; + + // + // Add the first TextOut to the QueryData array and ModeMap table + // + Status = ConSplitterAddOutputMode (Private, TextOutList->TextOut); + + // + // Now add one by one + // + Index = 1; + Private->CurrentNumberOfConsoles = 1; + TextOutList++; + while ((UINTN) Index < CurrentNumOfConsoles) { + ConSplitterSyncOutputMode (Private, TextOutList->TextOut); + Index++; + Private->CurrentNumberOfConsoles++; + TextOutList++; + } + + ConSplitterGetIntersectionBetweenConOutAndStrErr (); + + return Status; +} +// +// ConSplitter TextIn member functions +// +EFI_STATUS +EFIAPI +ConSplitterTextInReset ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the input device and optionaly run diagnostics + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The device was reset. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + Private->KeyEventSignalState = FALSE; + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextInList[Index]->Reset ( + Private->TextInList[Index], + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextInPrivateReadKeyStroke ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + OUT EFI_INPUT_KEY *Key + ) +/*++ + + Routine Description: + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + Arguments: + This - Protocol instance pointer. + Key - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The keystroke information was returned. + EFI_NOT_READY - There was no keystroke data availiable. + EFI_DEVICE_ERROR - The keydtroke information was not returned due to + hardware errors. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_INPUT_KEY CurrentKey; + + Key->UnicodeChar = 0; + Key->ScanCode = SCAN_NULL; + + // + // if no physical console input device exists, return EFI_NOT_READY; + // if any physical console input device has key input, + // return the key and EFI_SUCCESS. + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = Private->TextInList[Index]->ReadKeyStroke ( + Private->TextInList[Index], + &CurrentKey + ); + if (!EFI_ERROR (Status)) { + *Key = CurrentKey; + return Status; + } + } + + return EFI_NOT_READY; +} + +BOOLEAN +ConSpliterConssoleControlStdInLocked ( + VOID + ) +/*++ + +Routine Description: + Return TRUE if StdIn is locked. The ConIn device on the virtual handle is + the only device locked. + +Arguments: + NONE + +Returns: + TRUE - StdIn locked + FALSE - StdIn working normally + +--*/ +{ + return mConIn.PasswordEnabled; +} + +VOID +EFIAPI +ConSpliterConsoleControlLockStdInEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + This timer event will fire when StdIn is locked. It will check the key + sequence on StdIn to see if it matches the password. Any error in the + password will cause the check to reset. As long a mConIn.PasswordEnabled is + TRUE the StdIn splitter will not report any input. + +Arguments: + (Standard EFI_EVENT_NOTIFY) + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + CHAR16 BackSpaceString[2]; + CHAR16 SpaceString[2]; + + do { + Status = ConSplitterTextInPrivateReadKeyStroke (&mConIn, &Key); + if (!EFI_ERROR (Status)) { + // + // if it's an ENTER, match password + // + if ((Key.UnicodeChar == CHAR_CARRIAGE_RETURN) && (Key.ScanCode == SCAN_NULL)) { + mConIn.PwdAttempt[mConIn.PwdIndex] = CHAR_NULL; + if (StrCmp (mConIn.Password, mConIn.PwdAttempt)) { + // + // Password not match + // + ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\rPassword not correct\n\r"); + mConIn.PwdIndex = 0; + } else { + // + // Key matches password sequence + // + gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, 0); + mConIn.PasswordEnabled = FALSE; + Status = EFI_NOT_READY; + } + } else if ((Key.UnicodeChar == CHAR_BACKSPACE) && (Key.ScanCode == SCAN_NULL)) { + // + // BackSpace met + // + if (mConIn.PwdIndex > 0) { + BackSpaceString[0] = CHAR_BACKSPACE; + BackSpaceString[1] = 0; + + SpaceString[0] = ' '; + SpaceString[1] = 0; + + ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString); + ConSplitterTextOutOutputString (&mConOut.TextOut, SpaceString); + ConSplitterTextOutOutputString (&mConOut.TextOut, BackSpaceString); + + mConIn.PwdIndex--; + } + } else if ((Key.ScanCode == SCAN_NULL) && (Key.UnicodeChar >= 32)) { + // + // If it's not an ENTER, neigher a function key, nor a CTRL-X or ALT-X, record the input + // + if (mConIn.PwdIndex < (MAX_STD_IN_PASSWORD - 1)) { + if (mConIn.PwdIndex == 0) { + ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"\n\r"); + } + + ConSplitterTextOutOutputString (&mConOut.TextOut, (CHAR16 *) L"*"); + mConIn.PwdAttempt[mConIn.PwdIndex] = Key.UnicodeChar; + mConIn.PwdIndex++; + } + } + } + } while (!EFI_ERROR (Status)); +} + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlLockStdIn ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password + ) +/*++ + +Routine Description: + If Password is NULL unlock the password state variable and set the event + timer. If the Password is too big return an error. If the Password is valid + Copy the Password and enable state variable and then arm the periodic timer + +Arguments: + +Returns: + EFI_SUCCESS - Lock the StdIn device + EFI_INVALID_PARAMETER - Password is NULL + EFI_OUT_OF_RESOURCES - Buffer allocation to store the password fails + +--*/ +{ + if (Password == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (StrLen (Password) >= MAX_STD_IN_PASSWORD) { + // + // Currently have a max password size + // + return EFI_OUT_OF_RESOURCES; + } + // + // Save the password, initialize state variables and arm event timer + // + StrCpy (mConIn.Password, Password); + mConIn.PasswordEnabled = TRUE; + mConIn.PwdIndex = 0; + gBS->SetTimer (mConIn.LockEvent, TimerPeriodic, (10000 * 25)); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSplitterTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +/*++ + + Routine Description: + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + If the ConIn is password locked make it look like no keystroke is availible + + Arguments: + This - Protocol instance pointer. + Key - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The keystroke information was returned. + EFI_NOT_READY - There was no keystroke data availiable. + EFI_DEVICE_ERROR - The keydtroke information was not returned due to + hardware errors. + +--*/ +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + if (Private->PasswordEnabled) { + // + // If StdIn Locked return not ready + // + return EFI_NOT_READY; + } + + Private->KeyEventSignalState = FALSE; + + return ConSplitterTextInPrivateReadKeyStroke (Private, Key); +} + +VOID +EFIAPI +ConSplitterTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + This event agregates all the events of the ConIn devices in the spliter. + If the ConIn is password locked then return. + If any events of physical ConIn devices are signaled, signal the ConIn + spliter event. This will cause the calling code to call + ConSplitterTextInReadKeyStroke (). + +Arguments: + Event - The Event assoicated with callback. + Context - Context registered when Event was created. + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context; + if (Private->PasswordEnabled) { + // + // If StdIn Locked return not ready + // + return ; + } + + // + // if KeyEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke() + // + if (Private->KeyEventSignalState) { + gBS->SignalEvent (Event); + return ; + } + // + // if any physical console input device has key input, signal the event. + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + Status = gBS->CheckEvent (Private->TextInList[Index]->WaitForKey); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (Event); + Private->KeyEventSignalState = TRUE; + } + } +} + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the input device and optionaly run diagnostics + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The device was reset. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This); + + Private->InputEventSignalState = FALSE; + + if (Private->CurrentNumberOfPointers == 0) { + return EFI_SUCCESS; + } + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfPointers; Index++) { + Status = Private->PointerList[Index]->Reset ( + Private->PointerList[Index], + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerPrivateGetState ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ) +/*++ + + Routine Description: + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + Arguments: + This - Protocol instance pointer. + State - + + Returns: + EFI_SUCCESS - The keystroke information was returned. + EFI_NOT_READY - There was no keystroke data availiable. + EFI_DEVICE_ERROR - The keydtroke information was not returned due to + hardware errors. + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + UINTN Index; + EFI_SIMPLE_POINTER_STATE CurrentState; + + State->RelativeMovementX = 0; + State->RelativeMovementY = 0; + State->RelativeMovementZ = 0; + State->LeftButton = FALSE; + State->RightButton = FALSE; + + // + // if no physical console input device exists, return EFI_NOT_READY; + // if any physical console input device has key input, + // return the key and EFI_SUCCESS. + // + ReturnStatus = EFI_NOT_READY; + for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) { + + Status = Private->PointerList[Index]->GetState ( + Private->PointerList[Index], + &CurrentState + ); + if (!EFI_ERROR (Status)) { + if (ReturnStatus == EFI_NOT_READY) { + ReturnStatus = EFI_SUCCESS; + } + + if (CurrentState.LeftButton) { + State->LeftButton = TRUE; + } + + if (CurrentState.RightButton) { + State->RightButton = TRUE; + } + + if (CurrentState.RelativeMovementX != 0 && Private->PointerList[Index]->Mode->ResolutionX != 0) { + State->RelativeMovementX += (CurrentState.RelativeMovementX * (INT32) Private->SimplePointerMode.ResolutionX) / (INT32) Private->PointerList[Index]->Mode->ResolutionX; + } + + if (CurrentState.RelativeMovementY != 0 && Private->PointerList[Index]->Mode->ResolutionY != 0) { + State->RelativeMovementY += (CurrentState.RelativeMovementY * (INT32) Private->SimplePointerMode.ResolutionY) / (INT32) Private->PointerList[Index]->Mode->ResolutionY; + } + + if (CurrentState.RelativeMovementZ != 0 && Private->PointerList[Index]->Mode->ResolutionZ != 0) { + State->RelativeMovementZ += (CurrentState.RelativeMovementZ * (INT32) Private->SimplePointerMode.ResolutionZ) / (INT32) Private->PointerList[Index]->Mode->ResolutionZ; + } + } else if (Status == EFI_DEVICE_ERROR) { + ReturnStatus = EFI_DEVICE_ERROR; + } + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerGetState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ) +/*++ + + Routine Description: + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + If the ConIn is password locked make it look like no keystroke is availible + + Arguments: + This - Protocol instance pointer. + State - + + Returns: + EFI_SUCCESS - The keystroke information was returned. + EFI_NOT_READY - There was no keystroke data availiable. + EFI_DEVICE_ERROR - The keydtroke information was not returned due to + hardware errors. + +--*/ +{ + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + + Private = TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS (This); + if (Private->PasswordEnabled) { + // + // If StdIn Locked return not ready + // + return EFI_NOT_READY; + } + + Private->InputEventSignalState = FALSE; + + return ConSplitterSimplePointerPrivateGetState (Private, State); +} + +VOID +EFIAPI +ConSplitterSimplePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + This event agregates all the events of the ConIn devices in the spliter. + If the ConIn is password locked then return. + If any events of physical ConIn devices are signaled, signal the ConIn + spliter event. This will cause the calling code to call + ConSplitterTextInReadKeyStroke (). + +Arguments: + Event - The Event assoicated with callback. + Context - Context registered when Event was created. + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + TEXT_IN_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = (TEXT_IN_SPLITTER_PRIVATE_DATA *) Context; + if (Private->PasswordEnabled) { + // + // If StdIn Locked return not ready + // + return ; + } + + // + // if InputEventSignalState is flagged before, and not cleared by Reset() or ReadKeyStroke() + // + if (Private->InputEventSignalState) { + gBS->SignalEvent (Event); + return ; + } + // + // if any physical console input device has key input, signal the event. + // + for (Index = 0; Index < Private->CurrentNumberOfPointers; Index++) { + Status = gBS->CheckEvent (Private->PointerList[Index]->WaitForInput); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (Event); + Private->InputEventSignalState = TRUE; + } + } +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutReset ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the text output device hardware and optionaly run diagnostics + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform more exhaustive verfication + operation of the device during reset. + + Returns: + EFI_SUCCESS - The text output device was reset. + EFI_DEVICE_ERROR - The text output device is not functioning correctly and + could not be reset. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + + Status = Private->TextOutList[Index].TextOut->Reset ( + Private->TextOutList[Index].TextOut, + ExtendedVerification + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); + + Status = DevNullTextOutSetMode (Private, 0); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutOutputString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + + Routine Description: + Write a Unicode string to the output device. + + Arguments: + This - Protocol instance pointer. + String - The NULL-terminated Unicode string to be displayed on the output + device(s). All output devices must also support the Unicode + drawing defined in this file. + + Returns: + EFI_SUCCESS - The string was output to the device. + EFI_DEVICE_ERROR - The device reported an error while attempting to output + the text. + EFI_UNSUPPORTED - The output device's mode is not currently in a + defined text mode. + EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + UINTN BackSpaceCount; + EFI_STATUS ReturnStatus; + CHAR16 *TargetString; + + This->SetAttribute (This, This->Mode->Attribute); + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + BackSpaceCount = 0; + for (TargetString = WString; *TargetString; TargetString++) { + if (*TargetString == CHAR_BACKSPACE) { + BackSpaceCount++; + } + + } + + if (BackSpaceCount == 0) { + TargetString = WString; + } else { + TargetString = AllocatePool (sizeof (CHAR16) * (StrLen (WString) + BackSpaceCount + 1)); + StrCpy (TargetString, WString); + } + // + // return the worst status met + // + Status = DevNullTextOutOutputString (Private, TargetString); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->OutputString ( + Private->TextOutList[Index].TextOut, + TargetString + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + if (BackSpaceCount) { + gBS->FreePool (TargetString); + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutTestString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + + Routine Description: + Verifies that all characters in a Unicode string can be output to the + target device. + + Arguments: + This - Protocol instance pointer. + String - The NULL-terminated Unicode string to be examined for the output + device(s). + + Returns: + EFI_SUCCESS - The device(s) are capable of rendering the output string. + EFI_UNSUPPORTED - Some of the characters in the Unicode string cannot be + rendered by one or more of the output devices mapped + by the EFI handle. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->TestString ( + Private->TextOutList[Index].TextOut, + WString + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + // + // There is no DevNullTextOutTestString () since a Unicode buffer would + // always return EFI_SUCCESS. + // ReturnStatus will be EFI_SUCCESS if no consoles are present + // + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +/*++ + + Routine Description: + Returns information for an available text mode that the output device(s) + supports. + + Arguments: + This - Protocol instance pointer. + ModeNumber - The mode number to return information on. + Columns, Rows - Returns the geometry of the text output device for the + requested ModeNumber. + + Returns: + EFI_SUCCESS - The requested mode information was returned. + EFI_DEVICE_ERROR - The device had an error and could not + complete the request. + EFI_UNSUPPORTED - The mode number was not valid. + +--*/ +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Check whether param ModeNumber is valid. + // ModeNumber should be within range 0 ~ MaxMode - 1. + // + if (ModeNumber > (UINTN)(((UINT32)-1)>>1)) { + return EFI_UNSUPPORTED; + } + + if ((INT32) ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + *Columns = Private->TextOutQueryData[ModeNumber].Columns; + *Rows = Private->TextOutQueryData[ModeNumber].Rows; + + if (*Columns <= 0 && *Rows <= 0) { + return EFI_UNSUPPORTED; + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + + Routine Description: + Sets the output device(s) to a specified mode. + + Arguments: + This - Protocol instance pointer. + ModeNumber - The mode number to set. + + Returns: + EFI_SUCCESS - The requested text mode was set. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The mode number was not valid. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + INT32 *TextOutModeMap; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Check whether param ModeNumber is valid. + // ModeNumber should be within range 0 ~ MaxMode - 1. + // + if (ModeNumber > (UINTN)(((UINT32)-1)>>1)) { + return EFI_UNSUPPORTED; + } + + if ((INT32) ModeNumber >= This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + // + // If the mode is being set to the curent mode, then just clear the screen and return. + // + if (Private->TextOutMode.Mode == (INT32) ModeNumber) { + return ConSplitterTextOutClearScreen (This); + } + // + // return the worst status met + // + TextOutModeMap = Private->TextOutModeMap + Private->TextOutListCount * ModeNumber; + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->SetMode ( + Private->TextOutList[Index].TextOut, + TextOutModeMap[Index] + ); + // + // If this console device is based on a UGA device, then sync up the bitmap from + // the UGA splitter and reclear the text portion of the display in the new mode. + // + if (Private->TextOutList[Index].UgaDraw != NULL) { + Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut); + } + + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + // + // The DevNull Console will support any possible mode as it allocates memory + // + Status = DevNullTextOutSetMode (Private, ModeNumber); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ) +/*++ + + Routine Description: + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + Arguments: + This - Protocol instance pointer. + Attribute - The attribute to set. Bits 0..3 are the foreground color, and + bits 4..6 are the background color. All other bits are undefined + and must be zero. The valid Attributes are defined in this file. + + Returns: + EFI_SUCCESS - The attribute was set. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The attribute requested is not defined. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Check whether param Attribute is valid. + // + if ( (Attribute > (UINTN)(((UINT32)-1)>>1)) ) { + return EFI_UNSUPPORTED; + } + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->SetAttribute ( + Private->TextOutList[Index].TextOut, + Attribute + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + Private->TextOutMode.Attribute = (INT32) Attribute; + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +/*++ + + Routine Description: + Clears the output device(s) display to the currently selected background + color. + + Arguments: + This - Protocol instance pointer. + + Returns: + EFI_SUCCESS - The operation completed successfully. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The output device is not in a valid text mode. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->ClearScreen (Private->TextOutList[Index].TextOut); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + Status = DevNullTextOutClearScreen (Private); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +/*++ + + Routine Description: + Sets the current coordinates of the cursor position + + Arguments: + This - Protocol instance pointer. + Column, Row - the position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + + Returns: + EFI_SUCCESS - The operation completed successfully. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The output device is not in a valid text mode, or the + cursor position is invalid for the current mode. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + UINTN MaxColumn; + UINTN MaxRow; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + MaxColumn = Private->TextOutQueryData[Private->TextOutMode.Mode].Columns; + MaxRow = Private->TextOutQueryData[Private->TextOutMode.Mode].Rows; + + if (Column >= MaxColumn || Row >= MaxRow) { + return EFI_UNSUPPORTED; + } + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->SetCursorPosition ( + Private->TextOutList[Index].TextOut, + Column, + Row + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + DevNullTextOutSetCursorPosition (Private, Column, Row); + + return ReturnStatus; +} + +EFI_STATUS +EFIAPI +ConSplitterTextOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +/*++ + + Routine Description: + Makes the cursor visible or invisible + + Arguments: + This - Protocol instance pointer. + Visible - If TRUE, the cursor is set to be visible. If FALSE, the cursor is + set to be invisible. + + Returns: + EFI_SUCCESS - The operation completed successfully. + EFI_DEVICE_ERROR - The device had an error and could not complete the + request, or the device does not support changing + the cursor mode. + EFI_UNSUPPORTED - The output device is not in a valid text mode. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // return the worst status met + // + for (Index = 0, ReturnStatus = EFI_SUCCESS; Index < Private->CurrentNumberOfConsoles; Index++) { + + if (Private->TextOutList[Index].TextOutEnabled) { + Status = Private->TextOutList[Index].TextOut->EnableCursor ( + Private->TextOutList[Index].TextOut, + Visible + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + DevNullTextOutEnableCursor (Private, Visible); + + return ReturnStatus; +} diff --git a/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.h b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.h new file mode 100644 index 0000000000..fc68f049a0 --- /dev/null +++ b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.h @@ -0,0 +1,623 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ConSplitter.h + +Abstract: + + Private data structures for the Console Splitter driver + +--*/ + +#ifndef SPLITER_H_ +#define SPLITER_H_ + +// +// Private Data Structures +// +#define CONSOLE_SPLITTER_CONSOLES_ALLOC_UNIT 32 +#define CONSOLE_SPLITTER_MODES_ALLOC_UNIT 32 +#define MAX_STD_IN_PASSWORD 80 + +typedef struct { + UINTN Columns; + UINTN Rows; +} TEXT_OUT_SPLITTER_QUERY_DATA; + +// +// Private data for the EFI_SIMPLE_INPUT_PROTOCOL splitter +// +#define TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('T', 'i', 'S', 'p') + +typedef struct { + UINT64 Signature; + EFI_HANDLE VirtualHandle; + + EFI_SIMPLE_TEXT_IN_PROTOCOL TextIn; + UINTN CurrentNumberOfConsoles; + EFI_SIMPLE_TEXT_IN_PROTOCOL **TextInList; + UINTN TextInListCount; + + EFI_SIMPLE_POINTER_PROTOCOL SimplePointer; + EFI_SIMPLE_POINTER_MODE SimplePointerMode; + UINTN CurrentNumberOfPointers; + EFI_SIMPLE_POINTER_PROTOCOL **PointerList; + UINTN PointerListCount; + + BOOLEAN PasswordEnabled; + CHAR16 Password[MAX_STD_IN_PASSWORD]; + UINTN PwdIndex; + CHAR16 PwdAttempt[MAX_STD_IN_PASSWORD]; + EFI_EVENT LockEvent; + + BOOLEAN KeyEventSignalState; + BOOLEAN InputEventSignalState; +} TEXT_IN_SPLITTER_PRIVATE_DATA; + +#define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + TEXT_IN_SPLITTER_PRIVATE_DATA, \ + TextIn, \ + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define TEXT_IN_SPLITTER_PRIVATE_DATA_FROM_SIMPLE_POINTER_THIS(a) \ + CR (a, \ + TEXT_IN_SPLITTER_PRIVATE_DATA, \ + SimplePointer, \ + TEXT_IN_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +// +// Private data for the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL splitter +// +#define TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('T', 'o', 'S', 'p') + +typedef struct { + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut; + BOOLEAN TextOutEnabled; +} TEXT_OUT_AND_UGA_DATA; + +typedef struct { + UINT64 Signature; + EFI_HANDLE VirtualHandle; + EFI_SIMPLE_TEXT_OUT_PROTOCOL TextOut; + EFI_SIMPLE_TEXT_OUTPUT_MODE TextOutMode; + EFI_UGA_DRAW_PROTOCOL UgaDraw; + UINT32 UgaHorizontalResolution; + UINT32 UgaVerticalResolution; + UINT32 UgaColorDepth; + UINT32 UgaRefreshRate; + EFI_UGA_PIXEL *UgaBlt; + + EFI_CONSOLE_CONTROL_PROTOCOL ConsoleControl; + + UINTN CurrentNumberOfConsoles; + TEXT_OUT_AND_UGA_DATA *TextOutList; + UINTN TextOutListCount; + TEXT_OUT_SPLITTER_QUERY_DATA *TextOutQueryData; + UINTN TextOutQueryDataCount; + INT32 *TextOutModeMap; + + EFI_CONSOLE_CONTROL_SCREEN_MODE UgaMode; + + UINTN DevNullColumns; + UINTN DevNullRows; + CHAR16 *DevNullScreen; + INT32 *DevNullAttributes; + +} TEXT_OUT_SPLITTER_PRIVATE_DATA; + +#define TEXT_OUT_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + TextOut, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + UgaDraw, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +#define CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA, \ + ConsoleControl, \ + TEXT_OUT_SPLITTER_PRIVATE_DATA_SIGNATURE \ + ) + +// +// Function Prototypes +// +EFI_STATUS +EFIAPI +ConSplitterDriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + + +EFI_STATUS +ConSplitterTextInConstructor ( + TEXT_IN_SPLITTER_PRIVATE_DATA *Private + ) +; + + +EFI_STATUS +ConSplitterTextOutConstructor ( + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +; + +// +// Driver Binding Functions +// + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterConInDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterConOutDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + + +EFI_STATUS +EFIAPI +ConSplitterStdErrDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + +// +// TextIn Constructor/Destructor functions +// +EFI_STATUS +ConSplitterTextInAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *TextIn + ) +; + +EFI_STATUS +ConSplitterTextInDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *TextIn + ) +; + +// +// SimplePointer Constuctor/Destructor functions +// +EFI_STATUS +ConSplitterSimplePointerAddDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ) +; + +EFI_STATUS +ConSplitterSimplePointerDeleteDevice ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_POINTER_PROTOCOL *SimplePointer + ) +; + +// +// TextOut Constuctor/Destructor functions +// +EFI_STATUS +ConSplitterTextOutAddDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +; + +EFI_STATUS +ConSplitterTextOutDeleteDevice ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut + ) +; + +// +// TextIn I/O Functions +// +EFI_STATUS +EFIAPI +ConSplitterTextInReset ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +; + +VOID +EFIAPI +ConSplitterTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +BOOLEAN +ConSpliterConssoleControlStdInLocked ( + VOID + ) +; + +VOID +EFIAPI +ConSpliterConsoleControlLockStdInEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlLockStdIn ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN CHAR16 *Password + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextInPrivateReadKeyStroke ( + IN TEXT_IN_SPLITTER_PRIVATE_DATA *Private, + OUT EFI_INPUT_KEY *Key + ) +; + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerReset ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +EFI_STATUS +EFIAPI +ConSplitterSimplePointerGetState ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ) +; + +VOID +EFIAPI +ConSplitterSimplePointerWaitForInput ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +// +// TextOut I/O Functions +// +VOID +ConSplitterSynchronizeModeData ( + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutReset ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutOutputString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutTestString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +; + +EFI_STATUS +EFIAPI +ConSplitterTextOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +; + +EFI_STATUS +ConSplitterGrowBuffer ( + IN UINTN SizeOfCount, + IN UINTN *Count, + IN OUT VOID **Buffer + ) +; + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlGetMode ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *UgaExists, + OUT BOOLEAN *StdInLocked + ) +; + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlSetMode ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ) +; + +EFI_STATUS +EFIAPI +ConSpliterUgaDrawGetMode ( + IN EFI_UGA_DRAW_PROTOCOL *This, + OUT UINT32 *HorizontalResolution, + OUT UINT32 *VerticalResolution, + OUT UINT32 *ColorDepth, + OUT UINT32 *RefreshRate + ) +; + +EFI_STATUS +EFIAPI +ConSpliterUgaDrawSetMode ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ) +; + +EFI_STATUS +EFIAPI +ConSpliterUgaDrawBlt ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +; + +EFI_STATUS +DevNullUgaSync ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +; + +EFI_STATUS +DevNullTextOutOutputString ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN CHAR16 *WString + ) +; + +EFI_STATUS +DevNullTextOutSetMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN UINTN ModeNumber + ) +; + +EFI_STATUS +DevNullTextOutClearScreen ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +; + +EFI_STATUS +DevNullTextOutSetCursorPosition ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN UINTN Column, + IN UINTN Row + ) +; + +EFI_STATUS +DevNullTextOutEnableCursor ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN BOOLEAN Visible + ) +; + +EFI_STATUS +DevNullSyncUgaStdOut ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.mbd b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.mbd new file mode 100644 index 0000000000..d4b36b6f8f --- /dev/null +++ b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.mbd @@ -0,0 +1,41 @@ + + + + + ConSplitter + 408edcec-cf6d-477c-a5a8-b4844e3de281 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.msa b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.msa new file mode 100644 index 0000000000..287556ad59 --- /dev/null +++ b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitter.msa @@ -0,0 +1,102 @@ + + + + + ConSplitter + DXE_DRIVER + BS_DRIVER + 408edcec-cf6d-477c-a5a8-b4844e3de281 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + ConSplitter.c + ConSplitter.h + ComponentName.c + ConSplitterGraphics.c + + + MdePkg + EdkModulePkg + + + UgaDraw + SimpleTextOut + SimpleTextIn + SimplePointer + ConsoleControl + + + + PrimaryStandardErrorDevice + + + PrimaryConsoleInDevice + + + PrimaryConsoleOutDevice + + + ConsoleOutDevice + + + StandardErrorDevice + + + ConsoleInDevice + + + + + ConSplitterDriverEntry + + + gConSplitterConInDriverBinding + gConSplitterConInComponentName + + + gConSplitterSimplePointerDriverBinding + gConSplitterSimplePointerComponentName + + + gConSplitterConOutDriverBinding + gConSplitterConOutComponentName + + + gConSplitterStdErrDriverBinding + gConSplitterStdErrComponentName + + + diff --git a/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitterGraphics.c b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitterGraphics.c new file mode 100644 index 0000000000..412d695d77 --- /dev/null +++ b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/ConSplitterGraphics.c @@ -0,0 +1,1076 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ConSplitterGraphics.c + +Abstract: + + Support for ConsoleControl protocol. Support for UGA Draw spliter. + Support for DevNull Console Out. This console uses memory buffers + to represnt the console. It allows a console to start very early and + when a new console is added it is synced up with the current console + +--*/ + + +#include "ConSplitter.h" + +static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlGetMode ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + OUT EFI_CONSOLE_CONTROL_SCREEN_MODE *Mode, + OUT BOOLEAN *UgaExists, + OUT BOOLEAN *StdInLocked + ) +/*++ + + Routine Description: + Return the current video mode information. Also returns info about existence + of UGA Draw devices in system, and if the Std In device is locked. All the + arguments are optional and only returned if a non NULL pointer is passed in. + + Arguments: + This - Protocol instance pointer. + Mode - Are we in text of grahics mode. + UgaExists - TRUE if UGA Spliter has found a UGA device + StdInLocked - TRUE if StdIn device is keyboard locked + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_INVALID_PARAMETER - Invalid parameters. + +--*/ +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + + Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + if (Mode == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Mode = Private->UgaMode; + + if (UgaExists != NULL) { + *UgaExists = FALSE; + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + if (Private->TextOutList[Index].UgaDraw != NULL) { + *UgaExists = TRUE; + break; + } + } + } + + if (StdInLocked != NULL) { + *StdInLocked = ConSpliterConssoleControlStdInLocked (); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSpliterConsoleControlSetMode ( + IN EFI_CONSOLE_CONTROL_PROTOCOL *This, + IN EFI_CONSOLE_CONTROL_SCREEN_MODE Mode + ) +/*++ + + Routine Description: + Set the current mode to either text or graphics. Graphics is + for Quiet Boot. + + Arguments: + This - Protocol instance pointer. + Mode - Mode to set the + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_INVALID_PARAMETER - Invalid parameter. + EFI_UNSUPPORTED - Operation unsupported. + +--*/ +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + TEXT_OUT_AND_UGA_DATA *TextAndUga; + BOOLEAN Supported; + + Private = CONSOLE_CONTROL_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + if (Mode >= EfiConsoleControlScreenMaxValue) { + return EFI_INVALID_PARAMETER; + } + + Supported = FALSE; + TextAndUga = &Private->TextOutList[0]; + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndUga++) { + if (TextAndUga->UgaDraw != NULL) { + Supported = TRUE; + break; + } + } + + if ((!Supported) && (Mode == EfiConsoleControlScreenGraphics)) { + return EFI_UNSUPPORTED; + } + + Private->UgaMode = Mode; + + TextAndUga = &Private->TextOutList[0]; + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++, TextAndUga++) { + + TextAndUga->TextOutEnabled = TRUE; + // + // If we are going into Graphics mode disable ConOut to any UGA device + // + if ((Mode == EfiConsoleControlScreenGraphics) && (TextAndUga->UgaDraw != NULL)) { + TextAndUga->TextOutEnabled = FALSE; + DevNullUgaSync (Private, TextAndUga->UgaDraw); + } + } + + if (Mode == EfiConsoleControlScreenText) { + DevNullSyncUgaStdOut (Private); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSpliterUgaDrawGetMode ( + IN EFI_UGA_DRAW_PROTOCOL *This, + OUT UINT32 *HorizontalResolution, + OUT UINT32 *VerticalResolution, + OUT UINT32 *ColorDepth, + OUT UINT32 *RefreshRate + ) +/*++ + + Routine Description: + Return the current video mode information. + + Arguments: + This - Protocol instance pointer. + HorizontalResolution - Current video horizontal resolution in pixels + VerticalResolution - Current video vertical resolution in pixels + ColorDepth - Current video color depth in bits per pixel + RefreshRate - Current video refresh rate in Hz. + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_NOT_STARTED - Video display is not initialized. Call SetMode () + EFI_INVALID_PARAMETER - One of the input args was NULL. + +--*/ +{ + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + + if (!(HorizontalResolution && VerticalResolution && RefreshRate && ColorDepth)) { + return EFI_INVALID_PARAMETER; + } + // + // retrieve private data + // + Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + *HorizontalResolution = Private->UgaHorizontalResolution; + *VerticalResolution = Private->UgaVerticalResolution; + *ColorDepth = Private->UgaColorDepth; + *RefreshRate = Private->UgaRefreshRate; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSpliterUgaDrawSetMode ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ) +/*++ + + Routine Description: + Return the current video mode information. + + Arguments: + This - Protocol instance pointer. + HorizontalResolution - Current video horizontal resolution in pixels + VerticalResolution - Current video vertical resolution in pixels + ColorDepth - Current video color depth in bits per pixel + RefreshRate - Current video refresh rate in Hz. + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_NOT_STARTED - Video display is not initialized. Call SetMode () + EFI_OUT_OF_RESOURCES - Out of resources. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + UINTN Size; + + Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // UgaDevNullSetMode () + // + ReturnStatus = EFI_SUCCESS; + + // + // Free the old version + // + gBS->FreePool (Private->UgaBlt); + + // + // Allocate the virtual Blt buffer + // + Size = HorizontalResolution * VerticalResolution * sizeof (EFI_UGA_PIXEL); + Private->UgaBlt = AllocateZeroPool (Size); + if (Private->UgaBlt == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Update the Mode data + // + Private->UgaHorizontalResolution = HorizontalResolution; + Private->UgaVerticalResolution = VerticalResolution; + Private->UgaColorDepth = ColorDepth; + Private->UgaRefreshRate = RefreshRate; + + if (Private->UgaMode != EfiConsoleControlScreenGraphics) { + return ReturnStatus; + } + // + // return the worst status met + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + if (Private->TextOutList[Index].UgaDraw != NULL) { + Status = Private->TextOutList[Index].UgaDraw->SetMode ( + Private->TextOutList[Index].UgaDraw, + HorizontalResolution, + VerticalResolution, + ColorDepth, + RefreshRate + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + return ReturnStatus; +} + +EFI_STATUS +DevNullUgaBlt ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +{ + UINTN SrcY; + UINTN Index; + EFI_UGA_PIXEL *BltPtr; + EFI_UGA_PIXEL *ScreenPtr; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + + if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) { + return EFI_INVALID_PARAMETER; + } + + if (Width == 0 || Height == 0) { + return EFI_INVALID_PARAMETER; + } + + if (Delta == 0) { + Delta = Width * sizeof (EFI_UGA_PIXEL); + } + + HorizontalResolution = Private->UgaHorizontalResolution; + VerticalResolution = Private->UgaVerticalResolution; + + // + // We need to fill the Virtual Screen buffer with the blt data. + // + if (BltOperation == EfiUgaVideoToBltBuffer) { + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if ((SourceY + Height) > VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if ((SourceX + Width) > HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + + BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + DestinationY * Delta + DestinationX * sizeof (EFI_UGA_PIXEL)); + ScreenPtr = &Private->UgaBlt[SourceY * HorizontalResolution + SourceX]; + while (Height) { + CopyMem (BltPtr, ScreenPtr, Width * sizeof (EFI_UGA_PIXEL)); + BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltPtr + Delta); + ScreenPtr += HorizontalResolution; + Height--; + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + + ScreenPtr = &Private->UgaBlt[DestinationY * HorizontalResolution + DestinationX]; + SrcY = SourceY; + while (Height) { + if (BltOperation == EfiUgaVideoFill) { + for (Index = 0; Index < Width; Index++) { + ScreenPtr[Index] = *BltBuffer; + } + } else { + if (BltOperation == EfiUgaBltBufferToVideo) { + BltPtr = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + SrcY * Delta + SourceX * sizeof (EFI_UGA_PIXEL)); + } else { + BltPtr = &Private->UgaBlt[SrcY * HorizontalResolution + SourceX]; + } + + CopyMem (ScreenPtr, BltPtr, Width * sizeof (EFI_UGA_PIXEL)); + } + + ScreenPtr += HorizontalResolution; + SrcY++; + Height--; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +ConSpliterUgaDrawBlt ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +/*++ + + Routine Description: + The following table defines actions for BltOperations: + EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + EfiUgaVideoToBltBuffer - Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + EfiUgaVideoToVideo - Copy from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) . + to the video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + Arguments: + This - Protocol instance pointer. + BltBuffer - Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL) + BltOperation - Operation to perform on BlitBuffer and video memory + SourceX - X coordinate of source for the BltBuffer. + SourceY - Y coordinate of source for the BltBuffer. + DestinationX - X coordinate of destination for the BltBuffer. + DestinationY - Y coordinate of destination for the BltBuffer. + Width - Width of rectangle in BltBuffer in pixels. + Height - Hight of rectangle in BltBuffer in pixels. + Delta - + + Returns: + EFI_SUCCESS - The Blt operation completed. + EFI_INVALID_PARAMETER - BltOperation is not valid. + EFI_DEVICE_ERROR - A hardware error occured writting to the video + buffer. + +--*/ +{ + EFI_STATUS Status; + TEXT_OUT_SPLITTER_PRIVATE_DATA *Private; + UINTN Index; + EFI_STATUS ReturnStatus; + + Private = UGA_DRAW_SPLITTER_PRIVATE_DATA_FROM_THIS (This); + + // + // Sync up DevNull UGA device + // + ReturnStatus = DevNullUgaBlt ( + Private, + BltBuffer, + BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta + ); + if (Private->UgaMode != EfiConsoleControlScreenGraphics) { + return ReturnStatus; + } + // + // return the worst status met + // + for (Index = 0; Index < Private->CurrentNumberOfConsoles; Index++) { + if (Private->TextOutList[Index].UgaDraw != NULL) { + Status = Private->TextOutList[Index].UgaDraw->Blt ( + Private->TextOutList[Index].UgaDraw, + BltBuffer, + BltOperation, + SourceX, + SourceY, + DestinationX, + DestinationY, + Width, + Height, + Delta + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } else if (BltOperation == EfiUgaVideoToBltBuffer) { + // + // Only need to read the data into buffer one time + // + return EFI_SUCCESS; + } + } + } + + return ReturnStatus; +} + +EFI_STATUS +DevNullUgaSync ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN EFI_UGA_DRAW_PROTOCOL *UgaDraw + ) +{ + return UgaDraw->Blt ( + UgaDraw, + Private->UgaBlt, + EfiUgaBltBufferToVideo, + 0, + 0, + 0, + 0, + Private->UgaHorizontalResolution, + Private->UgaVerticalResolution, + Private->UgaHorizontalResolution * sizeof (EFI_UGA_PIXEL) + ); +} + +EFI_STATUS +DevNullTextOutOutputString ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN CHAR16 *WString + ) +/*++ + + Routine Description: + Write a Unicode string to the output device. + + Arguments: + Private - Pointer to the console output splitter's private data. It + indicates the calling context. + WString - The NULL-terminated Unicode string to be displayed on the output + device(s). All output devices must also support the Unicode + drawing defined in this file. + + Returns: + EFI_SUCCESS - The string was output to the device. + EFI_DEVICE_ERROR - The device reported an error while attempting to + output the text. + EFI_UNSUPPORTED - The output device's mode is not currently in a + defined text mode. + EFI_WARN_UNKNOWN_GLYPH - This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. + +--*/ +{ + UINTN SizeScreen; + UINTN SizeAttribute; + UINTN Index; + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + CHAR16 *Screen; + CHAR16 *NullScreen; + CHAR16 InsertChar; + CHAR16 TempChar; + CHAR16 *PStr; + INT32 *Attribute; + INT32 *NullAttributes; + INT32 CurrentWidth; + UINTN LastRow; + UINTN MaxColumn; + + Mode = &Private->TextOutMode; + NullScreen = Private->DevNullScreen; + NullAttributes = Private->DevNullAttributes; + LastRow = Private->DevNullRows - 1; + MaxColumn = Private->DevNullColumns; + + if (Mode->Attribute & EFI_WIDE_ATTRIBUTE) { + CurrentWidth = 2; + } else { + CurrentWidth = 1; + } + + while (*WString) { + + if (*WString == CHAR_BACKSPACE) { + // + // If the cursor is at the left edge of the display, then move the cursor + // one row up. + // + if (Mode->CursorColumn == 0 && Mode->CursorRow > 0) { + Mode->CursorRow--; + Mode->CursorColumn = (INT32) MaxColumn; + } + + // + // If the cursor is not at the left edge of the display, + // then move the cursor left one column. + // + if (Mode->CursorColumn > 0) { + Mode->CursorColumn--; + if (Mode->CursorColumn > 0 && + NullAttributes[Mode->CursorRow * MaxColumn + Mode->CursorColumn - 1] & EFI_WIDE_ATTRIBUTE + ) { + Mode->CursorColumn--; + + // + // Insert an extra backspace + // + InsertChar = CHAR_BACKSPACE; + PStr = WString + 1; + while (*PStr) { + TempChar = *PStr; + *PStr = InsertChar; + InsertChar = TempChar; + PStr++; + } + + *PStr = InsertChar; + *(++PStr) = 0; + + WString++; + } + } + + WString++; + + } else if (*WString == CHAR_LINEFEED) { + // + // If the cursor is at the bottom of the display, + // then scroll the display one row, and do not update + // the cursor position. Otherwise, move the cursor down one row. + // + if (Mode->CursorRow == (INT32) (LastRow)) { + // + // Scroll Screen Up One Row + // + SizeAttribute = LastRow * MaxColumn; + CopyMem ( + NullAttributes, + NullAttributes + MaxColumn, + SizeAttribute * sizeof (INT32) + ); + + // + // Each row has an ending CHAR_NULL. So one more character each line + // for DevNullScreen than DevNullAttributes + // + SizeScreen = SizeAttribute + LastRow; + CopyMem ( + NullScreen, + NullScreen + (MaxColumn + 1), + SizeScreen * sizeof (CHAR16) + ); + + // + // Print Blank Line at last line + // + Screen = NullScreen + SizeScreen; + Attribute = NullAttributes + SizeAttribute; + + for (Index = 0; Index < MaxColumn; Index++, Screen++, Attribute++) { + *Screen = ' '; + *Attribute = Mode->Attribute; + } + } else { + Mode->CursorRow++; + } + + WString++; + } else if (*WString == CHAR_CARRIAGE_RETURN) { + // + // Move the cursor to the beginning of the current row. + // + Mode->CursorColumn = 0; + WString++; + } else { + // + // Print the character at the current cursor position and + // move the cursor right one column. If this moves the cursor + // past the right edge of the display, then the line should wrap to + // the beginning of the next line. This is equivalent to inserting + // a CR and an LF. Note that if the cursor is at the bottom of the + // display, and the line wraps, then the display will be scrolled + // one line. + // + Index = Mode->CursorRow * MaxColumn + Mode->CursorColumn; + + while (Mode->CursorColumn < (INT32) MaxColumn) { + if (*WString == CHAR_NULL) { + break; + } + + if (*WString == CHAR_BACKSPACE) { + break; + } + + if (*WString == CHAR_LINEFEED) { + break; + } + + if (*WString == CHAR_CARRIAGE_RETURN) { + break; + } + + if (*WString == WIDE_CHAR || *WString == NARROW_CHAR) { + CurrentWidth = (*WString == WIDE_CHAR) ? 2 : 1; + WString++; + continue; + } + + if (Mode->CursorColumn + CurrentWidth > (INT32) MaxColumn) { + // + // If a wide char is at the rightmost column, then move the char + // to the beginning of the next row + // + NullScreen[Index + Mode->CursorRow] = L' '; + NullAttributes[Index] = Mode->Attribute | (UINT32) EFI_WIDE_ATTRIBUTE; + Index++; + Mode->CursorColumn++; + } else { + NullScreen[Index + Mode->CursorRow] = *WString; + NullAttributes[Index] = Mode->Attribute; + if (CurrentWidth == 1) { + NullAttributes[Index] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE); + } else { + NullAttributes[Index] |= (UINT32) EFI_WIDE_ATTRIBUTE; + NullAttributes[Index + 1] &= (~ (UINT32) EFI_WIDE_ATTRIBUTE); + } + + Index += CurrentWidth; + WString++; + Mode->CursorColumn += CurrentWidth; + } + } + // + // At the end of line, output carriage return and line feed + // + if (Mode->CursorColumn >= (INT32) MaxColumn) { + DevNullTextOutOutputString (Private, mCrLfString); + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DevNullTextOutSetMode ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN UINTN ModeNumber + ) +/*++ + + Routine Description: + Sets the output device(s) to a specified mode. + + Arguments: + Private - Private data structure pointer. + ModeNumber - The mode number to set. + + Returns: + EFI_SUCCESS - The requested text mode was set. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The mode number was not valid. + EFI_OUT_OF_RESOURCES - Out of resources. + +--*/ +{ + UINTN Size; + UINTN Row; + UINTN Column; + TEXT_OUT_SPLITTER_QUERY_DATA *Mode; + + // + // No extra check for ModeNumber here, as it has been checked in + // ConSplitterTextOutSetMode. And mode 0 should always be supported. + // + Mode = &(Private->TextOutQueryData[ModeNumber]); + Row = Mode->Rows; + Column = Mode->Columns; + + if (Row <= 0 && Column <= 0) { + return EFI_UNSUPPORTED; + } + + if (Private->DevNullColumns != Column || Private->DevNullRows != Row) { + + Private->TextOutMode.Mode = (INT32) ModeNumber; + Private->DevNullColumns = Column; + Private->DevNullRows = Row; + + gBS->FreePool (Private->DevNullScreen); + + Size = (Row * (Column + 1)) * sizeof (CHAR16); + Private->DevNullScreen = AllocateZeroPool (Size); + if (Private->DevNullScreen == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + gBS->FreePool (Private->DevNullAttributes); + + Size = Row * Column * sizeof (INT32); + Private->DevNullAttributes = AllocateZeroPool (Size); + if (Private->DevNullAttributes == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + + DevNullTextOutClearScreen (Private); + + return EFI_SUCCESS; +} + +EFI_STATUS +DevNullTextOutClearScreen ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +/*++ + + Routine Description: + Clears the output device(s) display to the currently selected background + color. + + Arguments: + Private - Protocol instance pointer. + + Returns: + EFI_SUCCESS - The operation completed successfully. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The output device is not in a valid text mode. + +--*/ +{ + UINTN Row; + UINTN Column; + CHAR16 *Screen; + INT32 *Attributes; + INT32 CurrentAttribute; + + // + // Clear the DevNull Text Out Buffers. + // The screen is filled with spaces. + // The attributes are all synced with the current Simple Text Out Attribute + // + Screen = Private->DevNullScreen; + Attributes = Private->DevNullAttributes; + CurrentAttribute = Private->TextOutMode.Attribute; + + for (Row = 0; Row < Private->DevNullRows; Row++) { + for (Column = 0; Column < Private->DevNullColumns; Column++, Screen++, Attributes++) { + *Screen = ' '; + *Attributes = CurrentAttribute; + } + // + // Each line of the screen has a NULL on the end so we must skip over it + // + Screen++; + } + + DevNullTextOutSetCursorPosition (Private, 0, 0); + + return DevNullTextOutEnableCursor (Private, TRUE); +} + +EFI_STATUS +DevNullTextOutSetCursorPosition ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN UINTN Column, + IN UINTN Row + ) +/*++ + + Routine Description: + Sets the current coordinates of the cursor position + + Arguments: + Private - Protocol instance pointer. + Column, Row - the position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + + Returns: + EFI_SUCCESS - The operation completed successfully. + EFI_DEVICE_ERROR - The device had an error and + could not complete the request. + EFI_UNSUPPORTED - The output device is not in a valid text mode, or the + cursor position is invalid for the current mode. + +--*/ +{ + // + // No need to do extra check here as whether (Column, Row) is valid has + // been checked in ConSplitterTextOutSetCursorPosition. And (0, 0) should + // always be supported. + // + Private->TextOutMode.CursorColumn = (INT32) Column; + Private->TextOutMode.CursorRow = (INT32) Row; + + return EFI_SUCCESS; +} + +EFI_STATUS +DevNullTextOutEnableCursor ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private, + IN BOOLEAN Visible + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). + In this driver, the cursor cannot be hidden. + + Arguments: + + Private - Indicates the calling context. + + Visible - If TRUE, the cursor is set to be visible, If FALSE, the cursor + is set to be invisible. + + Returns: + + EFI_SUCCESS - The request is valid. + + +--*/ +{ + Private->TextOutMode.CursorVisible = Visible; + + return EFI_SUCCESS; +} + +EFI_STATUS +DevNullSyncUgaStdOut ( + IN TEXT_OUT_SPLITTER_PRIVATE_DATA *Private + ) +/*++ + Routine Description: + Take the DevNull TextOut device and update the Simple Text Out on every + UGA device. + + Arguments: + Private - Indicates the calling context. + + Returns: + EFI_SUCCESS - The request is valid. + other - Return status of TextOut->OutputString () + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + UINTN Row; + UINTN Column; + UINTN List; + UINTN MaxColumn; + UINTN CurrentColumn; + UINTN StartRow; + UINTN StartColumn; + INT32 StartAttribute; + BOOLEAN StartCursorState; + CHAR16 *Screen; + CHAR16 *Str; + CHAR16 *Buffer; + CHAR16 *BufferTail; + CHAR16 *ScreenStart; + INT32 CurrentAttribute; + INT32 *Attributes; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *Sto; + + // + // Save the devices Attributes, Cursor enable state and location + // + StartColumn = Private->TextOutMode.CursorColumn; + StartRow = Private->TextOutMode.CursorRow; + StartAttribute = Private->TextOutMode.Attribute; + StartCursorState = Private->TextOutMode.CursorVisible; + + for (List = 0; List < Private->CurrentNumberOfConsoles; List++) { + + Sto = Private->TextOutList[List].TextOut; + + // + // Skip non UGA devices + // + if (Private->TextOutList[List].UgaDraw != NULL) { + Sto->EnableCursor (Sto, FALSE); + Sto->ClearScreen (Sto); + } + } + + ReturnStatus = EFI_SUCCESS; + Screen = Private->DevNullScreen; + Attributes = Private->DevNullAttributes; + MaxColumn = Private->DevNullColumns; + + Buffer = AllocateZeroPool ((MaxColumn + 1) * sizeof (CHAR16)); + + for (Row = 0; Row < Private->DevNullRows; Row++, Screen += (MaxColumn + 1), Attributes += MaxColumn) { + + if (Row == (Private->DevNullRows - 1)) { + // + // Don't ever sync the last character as it will scroll the screen + // + Screen[MaxColumn - 1] = 0x00; + } + + Column = 0; + while (Column < MaxColumn) { + if (Screen[Column]) { + CurrentAttribute = Attributes[Column]; + CurrentColumn = Column; + ScreenStart = &Screen[Column]; + + // + // the line end is alway 0x0. So Column should be less than MaxColumn + // It should be still in the same row + // + for (Str = ScreenStart, BufferTail = Buffer; *Str != 0; Str++, Column++) { + + if (Attributes[Column] != CurrentAttribute) { + Column--; + break; + } + + *BufferTail = *Str; + BufferTail++; + if (Attributes[Column] & EFI_WIDE_ATTRIBUTE) { + Str++; + Column++; + } + } + + *BufferTail = 0; + + for (List = 0; List < Private->CurrentNumberOfConsoles; List++) { + + Sto = Private->TextOutList[List].TextOut; + + // + // Skip non UGA devices + // + if (Private->TextOutList[List].UgaDraw != NULL) { + Sto->SetAttribute (Sto, CurrentAttribute); + Sto->SetCursorPosition (Sto, CurrentColumn, Row); + Status = Sto->OutputString (Sto, Buffer); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + } + + Column++; + } + } + // + // Restore the devices Attributes, Cursor enable state and location + // + for (List = 0; List < Private->CurrentNumberOfConsoles; List++) { + Sto = Private->TextOutList[List].TextOut; + + // + // Skip non UGA devices + // + if (Private->TextOutList[List].UgaDraw != NULL) { + Sto->SetAttribute (Sto, StartAttribute); + Sto->SetCursorPosition (Sto, StartColumn, StartRow); + Status = Sto->EnableCursor (Sto, StartCursorState); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + } + } + + gBS->FreePool (Buffer); + + return ReturnStatus; +} diff --git a/EdkModulePkg/Universal/Console/ConSplitter/Dxe/build.xml b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/build.xml new file mode 100644 index 0000000000..b49ce9027c --- /dev/null +++ b/EdkModulePkg/Universal/Console/ConSplitter/Dxe/build.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/ComponentName.c b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/ComponentName.c new file mode 100644 index 0000000000..5c615ba1c8 --- /dev/null +++ b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/ComponentName.c @@ -0,0 +1,139 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "GraphicsConsole.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gGraphicsConsoleComponentName = { + GraphicsConsoleComponentNameGetDriverName, + GraphicsConsoleComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mGraphicsConsoleDriverNameTable[] = { + { + "eng", + (CHAR16 *)L"UGA Console Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gGraphicsConsoleComponentName.SupportedLanguages, + mGraphicsConsoleDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/ComponentName.h b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/ComponentName.h new file mode 100644 index 0000000000..c5999b64d1 --- /dev/null +++ b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/ComponentName.h @@ -0,0 +1,51 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.h + +Abstract: + + +Revision History + +--*/ + +#ifndef _GRAPHICS_CONSOLE_COMPONENT_NAME_H +#define _GRAPHICS_CONSOLE_COMPONENT_NAME_H + +extern EFI_COMPONENT_NAME_PROTOCOL gGraphicsConsoleComponentName; + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +; + +EFI_STATUS +EFIAPI +GraphicsConsoleComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c new file mode 100644 index 0000000000..a475723dfd --- /dev/null +++ b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.c @@ -0,0 +1,1566 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + GraphicsConsole.c + +Abstract: + + This is the main routine for initializing the Graphics Console support routines. + +Revision History + +Remaining Tasks + Add all standard Glyphs from EFI 1.02 Specification + Implement optimal automatic Mode creation algorithm + Solve palette issues for mixed graphics and text + When does this protocol reset the palette? + +--*/ + +#include "GraphicsConsole.h" + +// +// Function Prototypes +// +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_STATUS +GetTextColors ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + OUT EFI_UGA_PIXEL *Foreground, + OUT EFI_UGA_PIXEL *Background + ); + +EFI_STATUS +DrawUnicodeWeightAtCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 UnicodeWeight + ); + +EFI_STATUS +DrawUnicodeWeightAtCursorN ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *UnicodeWeight, + IN UINTN Count + ); + +EFI_STATUS +EraseCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ); + +// +// Globals +// +GRAPHICS_CONSOLE_DEV mGraphicsConsoleDevTemplate = { + GRAPHICS_CONSOLE_DEV_SIGNATURE, + (EFI_UGA_DRAW_PROTOCOL *) NULL, + { + GraphicsConsoleConOutReset, + GraphicsConsoleConOutOutputString, + GraphicsConsoleConOutTestString, + GraphicsConsoleConOutQueryMode, + GraphicsConsoleConOutSetMode, + GraphicsConsoleConOutSetAttribute, + GraphicsConsoleConOutClearScreen, + GraphicsConsoleConOutSetCursorPosition, + GraphicsConsoleConOutEnableCursor, + (EFI_SIMPLE_TEXT_OUTPUT_MODE *) NULL + }, + { + 0, + 0, + EFI_TEXT_ATTR(EFI_LIGHTGRAY, EFI_BLACK), + 0, + 0, + TRUE + }, + { + { 80, 25, 0, 0, 0, 0 }, // Mode 0 + { 0, 0, 0, 0, 0, 0 }, // Mode 1 + { 0, 0, 0, 0, 0, 0 } // Mode 2 + }, + (EFI_UGA_PIXEL *) NULL, + (EFI_HII_HANDLE) 0 +}; + +EFI_HII_PROTOCOL *mHii; + +static CHAR16 mCrLfString[3] = { CHAR_CARRIAGE_RETURN, CHAR_LINEFEED, CHAR_NULL }; + +static EFI_UGA_PIXEL mEfiColors[16] = { + // + // B G R + // + { 0x00, 0x00, 0x00, 0x00 }, // BLACK + { 0x98, 0x00, 0x00, 0x00 }, // BLUE + { 0x00, 0x98, 0x00, 0x00 }, // GREEN + { 0x98, 0x98, 0x00, 0x00 }, // CYAN + { 0x00, 0x00, 0x98, 0x00 }, // RED + { 0x98, 0x00, 0x98, 0x00 }, // MAGENTA + { 0x00, 0x98, 0x98, 0x00 }, // BROWN + { 0x98, 0x98, 0x98, 0x00 }, // LIGHTGRAY + { 0x30, 0x30, 0x30, 0x00 }, // DARKGRAY - BRIGHT BLACK + { 0xff, 0x00, 0x00, 0x00 }, // LIGHTBLUE - ? + { 0x00, 0xff, 0x00, 0x00 }, // LIGHTGREEN - ? + { 0xff, 0xff, 0x00, 0x00 }, // LIGHTCYAN + { 0x00, 0x00, 0xff, 0x00 }, // LIGHTRED + { 0xff, 0x00, 0xff, 0x00 }, // LIGHTMAGENTA + { 0x00, 0xff, 0xff, 0x00 }, // LIGHTBROWN + { 0xff, 0xff, 0xff, 0x00 } // WHITE +}; + +static EFI_NARROW_GLYPH mCursorGlyph = { + 0x0000, + 0x00, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF } +}; + +static CHAR16 SpaceStr[] = { (CHAR16)NARROW_CHAR, ' ', 0 }; + + +EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding = { + GraphicsConsoleControllerDriverSupported, + GraphicsConsoleControllerDriverStart, + GraphicsConsoleControllerDriverStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + (VOID **) &UgaDraw, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // We need to ensure that we do not layer on top of a virtual handle. + // We need to ensure that the handles produced by the conspliter do not + // get used. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + goto Error; + } + // + // Does Hii Exist? If not, we aren't ready to run + // + Status = EfiLocateHiiProtocol (); + + // + // Close the I/O Abstraction(s) used to perform the supported test + // +Error: + gBS->CloseProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Start the controller. + + Arguments: + + This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - The handle of the controller to start. + RemainingDevicePath - A pointer to the remaining portion of a devcie path. + + Returns: + + EFI_SUCCESS - Return successfully. + EFI_OUT_OF_RESOURCES - Out of resources. + +--*/ +{ + EFI_STATUS Status; + GRAPHICS_CONSOLE_DEV *Private; + EFI_HII_PACKAGES *Package; + EFI_HII_FONT_PACK *FontPack; + UINTN NarrowFontSize; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; + UINTN MaxMode; + UINTN Columns; + UINTN Rows; + UINT8 *Location; + // + // Initialize the Graphics Console device instance + // + Private = AllocateCopyPool ( + sizeof (GRAPHICS_CONSOLE_DEV), + &mGraphicsConsoleDevTemplate + ); + if (Private == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Private->SimpleTextOutput.Mode = &(Private->SimpleTextOutputMode); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + (VOID **) &Private->UgaDraw, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // Get the HII protocol. If Supported() succeeds, do we really + // need to get HII protocol again? + // + Status = EfiLocateHiiProtocol (); + if (EFI_ERROR (Status)) { + goto Error; + } + + NarrowFontSize = ReturnNarrowFontSize (); + + FontPack = AllocateZeroPool (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize); + ASSERT (FontPack); + + FontPack->Header.Length = (UINT32) (sizeof (EFI_HII_FONT_PACK) + NarrowFontSize); + FontPack->Header.Type = EFI_HII_FONT; + FontPack->NumberOfNarrowGlyphs = (UINT16) (NarrowFontSize / sizeof (EFI_NARROW_GLYPH)); + + Location = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)); + CopyMem (Location, UsStdNarrowGlyphData, NarrowFontSize); + + // + // Register our Fonts into the global database + // + Package = PreparePackages (1, NULL, FontPack); + mHii->NewPack (mHii, Package, &(Private->HiiHandle)); + gBS->FreePool (Package); + + // + // Free the font database + // + gBS->FreePool (FontPack); + + // + // If the current mode information can not be retrieved, then attemp to set the default mode + // of 800x600, 32 bit colot, 60 Hz refresh. + // + HorizontalResolution = 800; + VerticalResolution = 600; + ColorDepth = 32; + RefreshRate = 60; + Status = Private->UgaDraw->SetMode ( + Private->UgaDraw, + HorizontalResolution, + VerticalResolution, + ColorDepth, + RefreshRate + ); + if (EFI_ERROR (Status)) { + // + // Get the current mode information from the UGA Draw Protocol + // + Status = Private->UgaDraw->GetMode ( + Private->UgaDraw, + &HorizontalResolution, + &VerticalResolution, + &ColorDepth, + &RefreshRate + ); + if (EFI_ERROR (Status)) { + goto Error; + } + } + // + // Compute the maximum number of text Rows and Columns that this current graphics mode can support + // + Columns = HorizontalResolution / GLYPH_WIDTH; + Rows = VerticalResolution / GLYPH_HEIGHT; + + // + // See if the mode is too small to support the required 80x25 text mode + // + if (Columns < 80 || Rows < 25) { + goto Error; + } + // + // Add Mode #0 that must be 80x25 + // + MaxMode = 0; + Private->ModeData[MaxMode].UgaWidth = HorizontalResolution; + Private->ModeData[MaxMode].UgaHeight = VerticalResolution; + Private->ModeData[MaxMode].DeltaX = (HorizontalResolution - (80 * GLYPH_WIDTH)) >> 1; + Private->ModeData[MaxMode].DeltaY = (VerticalResolution - (25 * GLYPH_HEIGHT)) >> 1; + MaxMode++; + + // + // If it is possible to support Mode #1 - 80x50, than add it as an active mode + // + if (Rows >= 50) { + Private->ModeData[MaxMode].UgaWidth = HorizontalResolution; + Private->ModeData[MaxMode].UgaHeight = VerticalResolution; + Private->ModeData[MaxMode].DeltaX = (HorizontalResolution - (80 * GLYPH_WIDTH)) >> 1; + Private->ModeData[MaxMode].DeltaY = (VerticalResolution - (50 * GLYPH_HEIGHT)) >> 1; + MaxMode++; + } + // + // If the graphics mode is 800x600, than add a text mode that uses the entire display + // + if (HorizontalResolution == 800 && VerticalResolution == 600) { + + if (MaxMode < 2) { + Private->ModeData[MaxMode].Columns = 0; + Private->ModeData[MaxMode].Rows = 0; + Private->ModeData[MaxMode].UgaWidth = 800; + Private->ModeData[MaxMode].UgaHeight = 600; + Private->ModeData[MaxMode].DeltaX = 0; + Private->ModeData[MaxMode].DeltaY = 0; + MaxMode++; + } + + Private->ModeData[MaxMode].Columns = 800 / GLYPH_WIDTH; + Private->ModeData[MaxMode].Rows = 600 / GLYPH_HEIGHT; + Private->ModeData[MaxMode].UgaWidth = 800; + Private->ModeData[MaxMode].UgaHeight = 600; + Private->ModeData[MaxMode].DeltaX = (800 % GLYPH_WIDTH) >> 1; + Private->ModeData[MaxMode].DeltaY = (600 % GLYPH_HEIGHT) >> 1; + MaxMode++; + } + // + // Update the maximum number of modes + // + Private->SimpleTextOutputMode.MaxMode = (INT32) MaxMode; + + // + // Determine the number of text modes that this protocol can support + // + Status = GraphicsConsoleConOutSetMode (&Private->SimpleTextOutput, 0); + if (EFI_ERROR (Status)) { + goto Error; + } + + DEBUG_CODE ( + GraphicsConsoleConOutOutputString (&Private->SimpleTextOutput, (CHAR16 *)L"Graphics Console Started\n\r"); + ); + + // + // Install protocol interfaces for the Graphics Console device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiSimpleTextOutProtocolGuid, + &Private->SimpleTextOutput, + NULL + ); + +Error: + if (EFI_ERROR (Status)) { + // + // Close the UGA IO Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Free private data + // + if (Private != NULL) { + gBS->FreePool (Private->LineBuffer); + gBS->FreePool (Private); + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleControllerDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *SimpleTextOutput; + GRAPHICS_CONSOLE_DEV *Private; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &SimpleTextOutput, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_STARTED; + } + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (SimpleTextOutput); + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiSimpleTextOutProtocolGuid, + &Private->SimpleTextOutput + ); + + if (!EFI_ERROR (Status)) { + // + // Close the UGA IO Protocol + // + gBS->CloseProtocol ( + Controller, + &gEfiUgaDrawProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // Remove the font pack + // + mHii->RemovePack (mHii, Private->HiiHandle); + + // + // Free our instance data + // + if (Private != NULL) { + gBS->FreePool (Private->LineBuffer); + gBS->FreePool (Private); + } + } + + return Status; +} + +EFI_STATUS +EfiLocateHiiProtocol ( + VOID + ) +/*++ + + Routine Description: + Find if the HII protocol is available. If yes, locate the HII protocol + + Arguments: + + Returns: + +--*/ +{ + EFI_HANDLE Handle; + UINTN Size; + EFI_STATUS Status; + + // + // There should only be one - so buffer size is this + // + Size = sizeof (EFI_HANDLE); + + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiHiiProtocolGuid, + NULL, + &Size, + &Handle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->HandleProtocol ( + Handle, + &gEfiHiiProtocolGuid, + (VOID **)&mHii + ); + + return Status; +} +// +// Body of the STO functions +// +EFI_STATUS +EFIAPI +GraphicsConsoleConOutReset ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.Reset(). + If ExtendeVerification is TRUE, then perform dependent Graphics Console + device reset, and set display mode to mode 0. + If ExtendedVerification is FALSE, only set display mode to mode 0. + + Arguments: + + This - Indicates the calling context. + + ExtendedVerification - Indicates that the driver may perform a more exhaustive + verification operation of the device during reset. + + Returns: + + EFI_SUCCESS + The reset operation succeeds. + + EFI_DEVICE_ERROR + The Graphics Console is not functioning correctly + +--*/ +{ + This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); + return This->SetMode (This, 0); +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.OutputString(). + The Unicode string will be converted to Glyphs and will be + sent to the Graphics Console. + + + Arguments: + + This - Indicates the calling context. + + WString - The Null-terminated Unicode string to be displayed on + the Graphics Console. + + Returns: + + EFI_SUCCESS + The string is output successfully. + + EFI_DEVICE_ERROR + The Graphics Console failed to send the string out. + + EFI_WARN_UNKNOWN_GLYPH + Indicates that some of the characters in the Unicode string could not + be rendered and are skipped. + +--*/ +{ + GRAPHICS_CONSOLE_DEV *Private; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + INTN Mode; + UINTN MaxColumn; + UINTN MaxRow; + UINTN Width; + UINTN Height; + UINTN Delta; + EFI_STATUS Status; + BOOLEAN Warning; + EFI_UGA_PIXEL Foreground; + EFI_UGA_PIXEL Background; + UINTN DeltaX; + UINTN DeltaY; + UINTN Count; + UINTN Index; + INT32 OriginAttribute; + + // + // Current mode + // + Mode = This->Mode->Mode; + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + UgaDraw = Private->UgaDraw; + + MaxColumn = Private->ModeData[Mode].Columns; + MaxRow = Private->ModeData[Mode].Rows; + DeltaX = Private->ModeData[Mode].DeltaX; + DeltaY = Private->ModeData[Mode].DeltaY; + Width = MaxColumn * GLYPH_WIDTH; + Height = (MaxRow - 1) * GLYPH_HEIGHT; + Delta = Width * sizeof (EFI_UGA_PIXEL); + + // + // The Attributes won't change when during the time OutputString is called + // + GetTextColors (This, &Foreground, &Background); + + EraseCursor (This); + + Warning = FALSE; + + // + // Backup attribute + // + OriginAttribute = This->Mode->Attribute; + + while (*WString) { + + if (*WString == CHAR_BACKSPACE) { + // + // If the cursor is at the left edge of the display, then move the cursor + // one row up. + // + if (This->Mode->CursorColumn == 0 && This->Mode->CursorRow > 0) { + This->Mode->CursorRow--; + This->Mode->CursorColumn = (INT32) (MaxColumn - 1); + This->OutputString (This, SpaceStr); + EraseCursor (This); + This->Mode->CursorRow--; + This->Mode->CursorColumn = (INT32) (MaxColumn - 1); + } else if (This->Mode->CursorColumn > 0) { + // + // If the cursor is not at the left edge of the display, then move the cursor + // left one column. + // + This->Mode->CursorColumn--; + This->OutputString (This, SpaceStr); + EraseCursor (This); + This->Mode->CursorColumn--; + } + + WString++; + + } else if (*WString == CHAR_LINEFEED) { + // + // If the cursor is at the bottom of the display, then scroll the display one + // row, and do not update the cursor position. Otherwise, move the cursor + // down one row. + // + if (This->Mode->CursorRow == (INT32) (MaxRow - 1)) { + // + // Scroll Screen Up One Row + // + UgaDraw->Blt ( + UgaDraw, + NULL, + EfiUgaVideoToVideo, + DeltaX, + DeltaY + GLYPH_HEIGHT, + DeltaX, + DeltaY, + Width, + Height, + Delta + ); + + // + // Print Blank Line at last line + // + UgaDraw->Blt ( + UgaDraw, + &Background, + EfiUgaVideoFill, + 0, + 0, + DeltaX, + DeltaY + Height, + Width, + GLYPH_HEIGHT, + Delta + ); + + } else { + This->Mode->CursorRow++; + } + + WString++; + + } else if (*WString == CHAR_CARRIAGE_RETURN) { + // + // Move the cursor to the beginning of the current row. + // + This->Mode->CursorColumn = 0; + WString++; + + } else if (*WString == WIDE_CHAR) { + + This->Mode->Attribute |= EFI_WIDE_ATTRIBUTE; + WString++; + + } else if (*WString == NARROW_CHAR) { + + This->Mode->Attribute &= (~ (UINT32) EFI_WIDE_ATTRIBUTE); + WString++; + + } else { + // + // Print the character at the current cursor position and move the cursor + // right one column. If this moves the cursor past the right edge of the + // display, then the line should wrap to the beginning of the next line. This + // is equivalent to inserting a CR and an LF. Note that if the cursor is at the + // bottom of the display, and the line wraps, then the display will be scrolled + // one line. + // If wide char is going to be displayed, need to display one character at a time + // Or, need to know the display length of a certain string. + // + // Index is used to determine how many character width units (wide = 2, narrow = 1) + // Count is used to determine how many characters are used regardless of their attributes + // + for (Count = 0, Index = 0; (This->Mode->CursorColumn + Index) < MaxColumn; Count++, Index++) { + if (WString[Count] == CHAR_NULL) { + break; + } + + if (WString[Count] == CHAR_BACKSPACE) { + break; + } + + if (WString[Count] == CHAR_LINEFEED) { + break; + } + + if (WString[Count] == CHAR_CARRIAGE_RETURN) { + break; + } + + if (WString[Count] == WIDE_CHAR) { + break; + } + + if (WString[Count] == NARROW_CHAR) { + break; + } + // + // Is the wide attribute on? + // + if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) { + // + // If wide, add one more width unit than normal since we are going to increment at the end of the for loop + // + Index++; + // + // This is the end-case where if we are at column 79 and about to print a wide character + // We should prevent this from happening because we will wrap inappropriately. We should + // not print this character until the next line. + // + if ((This->Mode->CursorColumn + Index + 1) > MaxColumn) { + Index++; + break; + } + } + } + + Status = DrawUnicodeWeightAtCursorN (This, WString, Count); + if (EFI_ERROR (Status)) { + Warning = TRUE; + } + // + // At the end of line, output carriage return and line feed + // + WString += Count; + This->Mode->CursorColumn += (INT32) Index; + if (This->Mode->CursorColumn > (INT32) MaxColumn) { + This->Mode->CursorColumn -= 2; + This->OutputString (This, SpaceStr); + } + + if (This->Mode->CursorColumn >= (INT32) MaxColumn) { + EraseCursor (This); + This->OutputString (This, mCrLfString); + EraseCursor (This); + } + } + } + + This->Mode->Attribute = OriginAttribute; + + EraseCursor (This); + + if (Warning) { + return EFI_WARN_UNKNOWN_GLYPH; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutTestString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.TestString(). + If one of the characters in the *Wstring is + neither valid valid Unicode drawing characters, + not ASCII code, then this function will return + EFI_UNSUPPORTED. + + + Arguments: + + This - Indicates the calling context. + + WString - The Null-terminated Unicode string to be tested. + + Returns: + + EFI_SUCCESS + The Graphics Console is capable of rendering the output string. + + EFI_UNSUPPORTED + Some of the characters in the Unicode string cannot be rendered. + +--*/ +{ + EFI_STATUS Status; + UINT16 GlyphWidth; + UINT32 GlyphStatus; + UINT16 Count; + GRAPHICS_CONSOLE_DEV *Private; + GLYPH_UNION *Glyph; + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + GlyphStatus = 0; + Count = 0; + + while (WString[Count]) { + Status = mHii->GetGlyph ( + mHii, + WString, + &Count, + (UINT8 **) &Glyph, + &GlyphWidth, + &GlyphStatus + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.QueryMode(). + It returnes information for an available text mode + that the Graphics Console supports. + In this driver,we only support text mode 80x25, which is + defined as mode 0. + + + Arguments: + + This - Indicates the calling context. + + ModeNumber - The mode number to return information on. + + Columns - The returned columns of the requested mode. + + Rows - The returned rows of the requested mode. + + Returns: + + EFI_SUCCESS + The requested mode information is returned. + + EFI_UNSUPPORTED + The mode number is not valid. + +--*/ +{ + GRAPHICS_CONSOLE_DEV *Private; + + if (ModeNumber >= (UINTN) This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + + *Columns = Private->ModeData[ModeNumber].Columns; + *Rows = Private->ModeData[ModeNumber].Rows; + + if (*Columns <= 0 && *Rows <= 0) { + return EFI_UNSUPPORTED; + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.SetMode(). + Set the Graphics Console to a specified mode. + In this driver, we only support mode 0. + + Arguments: + + This - Indicates the calling context. + + ModeNumber - The text mode to set. + + Returns: + + EFI_SUCCESS + The requested text mode is set. + + EFI_DEVICE_ERROR + The requested text mode cannot be set because of Graphics Console device error. + + EFI_UNSUPPORTED + The text mode number is not valid. + +--*/ +{ + EFI_STATUS Status; + GRAPHICS_CONSOLE_DEV *Private; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + GRAPHICS_CONSOLE_MODE_DATA *ModeData; + EFI_UGA_PIXEL *NewLineBuffer; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + UgaDraw = Private->UgaDraw; + ModeData = &(Private->ModeData[ModeNumber]); + + // + // Make sure the requested mode number is supported + // + if (ModeNumber >= (UINTN) This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + if (ModeData->Columns <= 0 && ModeData->Rows <= 0) { + return EFI_UNSUPPORTED; + } + // + // Attempt to allocate a line buffer for the requested mode number + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_UGA_PIXEL) * ModeData->Columns * GLYPH_WIDTH * GLYPH_HEIGHT, + (VOID **) &NewLineBuffer + ); + if (EFI_ERROR (Status)) { + // + // The new line buffer could not be allocated, so return an error. + // No changes to the state of the current console have been made, so the current console is still valid + // + return Status; + } + // + // If the mode has been set at least one other time, then LineBuffer will not be NULL + // + if (Private->LineBuffer != NULL) { + // + // Clear the current text window on the current graphics console + // + This->ClearScreen (This); + + // + // If the new mode is the same as the old mode, then just return EFI_SUCCESS + // + if ((INT32) ModeNumber == This->Mode->Mode) { + gBS->FreePool (NewLineBuffer); + return EFI_SUCCESS; + } + // + // Otherwise, the size of the text console and/or the UGA mode will be changed, + // so turn off the cursor, and free the LineBuffer for the current mode + // + This->EnableCursor (This, FALSE); + + gBS->FreePool (Private->LineBuffer); + } + // + // Assign the current line buffer to the newly allocated line buffer + // + Private->LineBuffer = NewLineBuffer; + + // + // Get the current UGA Draw mode information + // + Status = UgaDraw->GetMode ( + UgaDraw, + &HorizontalResolution, + &VerticalResolution, + &ColorDepth, + &RefreshRate + ); + if (EFI_ERROR (Status) || HorizontalResolution != ModeData->UgaWidth || VerticalResolution != ModeData->UgaHeight) { + // + // Either no graphics mode is currently set, or it is set to the wrong resolution, so set the new grapghics mode + // + Status = UgaDraw->SetMode ( + UgaDraw, + ModeData->UgaWidth, + ModeData->UgaHeight, + 32, + 60 + ); + if (EFI_ERROR (Status)) { + // + // The mode set operation failed + // + return Status; + } + } else { + // + // The current graphics mode is correct, so simply clear the entire display + // + Status = UgaDraw->Blt ( + UgaDraw, + &mEfiColors[0], + EfiUgaVideoFill, + 0, + 0, + 0, + 0, + ModeData->UgaWidth, + ModeData->UgaHeight, + 0 + ); + } + // + // The new mode is valid, so commit the mode change + // + This->Mode->Mode = (INT32) ModeNumber; + + // + // Move the text cursor to the upper left hand corner of the displat and enable it + // + This->SetCursorPosition (This, 0, 0); + This->EnableCursor (This, TRUE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.SetAttribute(). + + Arguments: + + This - Indicates the calling context. + + Attrubute - The attribute to set. Only bit0..6 are valid, all other bits + are undefined and must be zero. + + Returns: + + EFI_SUCCESS + The requested attribute is set. + + EFI_DEVICE_ERROR + The requested attribute cannot be set due to Graphics Console port error. + + EFI_UNSUPPORTED + The attribute requested is not defined by EFI spec. + +--*/ +{ + if ((Attribute | 0xFF) != 0xFF) { + return EFI_UNSUPPORTED; + } + + if ((INT32) Attribute == This->Mode->Attribute) { + return EFI_SUCCESS; + } + + EraseCursor (This); + + This->Mode->Attribute = (INT32) Attribute; + + EraseCursor (This); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.ClearScreen(). + It clears the Graphics Console's display to the + currently selected background color. + + + Arguments: + + This - Indicates the calling context. + + Returns: + + EFI_SUCCESS + The operation completed successfully. + + EFI_DEVICE_ERROR + The Graphics Console cannot be cleared due to Graphics Console device error. + + EFI_UNSUPPORTED + The Graphics Console is not in a valid text mode. + +--*/ +{ + EFI_STATUS Status; + GRAPHICS_CONSOLE_DEV *Private; + GRAPHICS_CONSOLE_MODE_DATA *ModeData; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_UGA_PIXEL Foreground; + EFI_UGA_PIXEL Background; + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + UgaDraw = Private->UgaDraw; + ModeData = &(Private->ModeData[This->Mode->Mode]); + + GetTextColors (This, &Foreground, &Background); + + Status = UgaDraw->Blt ( + UgaDraw, + &Background, + EfiUgaVideoFill, + 0, + 0, + 0, + 0, + ModeData->UgaWidth, + ModeData->UgaHeight, + 0 + ); + + This->Mode->CursorColumn = 0; + This->Mode->CursorRow = 0; + + EraseCursor (This); + + return Status; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.SetCursorPosition(). + + Arguments: + + This - Indicates the calling context. + + Column - The row to set cursor to. + + Row - The column to set cursor to. + + Returns: + + EFI_SUCCESS + The operation completed successfully. + + EFI_DEVICE_ERROR + The request fails due to Graphics Console device error. + + EFI_UNSUPPORTED + The Graphics Console is not in a valid text mode, or the cursor position + is invalid for current mode. + +--*/ +{ + GRAPHICS_CONSOLE_DEV *Private; + GRAPHICS_CONSOLE_MODE_DATA *ModeData; + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + ModeData = &(Private->ModeData[This->Mode->Mode]); + + if ((Column >= ModeData->Columns) || (Row >= ModeData->Rows)) { + return EFI_UNSUPPORTED; + } + + if (((INT32) Column == This->Mode->CursorColumn) && ((INT32) Row == This->Mode->CursorRow)) { + return EFI_SUCCESS; + } + + EraseCursor (This); + + This->Mode->CursorColumn = (INT32) Column; + This->Mode->CursorRow = (INT32) Row; + + EraseCursor (This); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). + In this driver, the cursor cannot be hidden. + + Arguments: + + This - Indicates the calling context. + + Visible - If TRUE, the cursor is set to be visible, + If FALSE, the cursor is set to be invisible. + + Returns: + + EFI_SUCCESS + The request is valid. + + EFI_UNSUPPORTED + The Graphics Console does not support a hidden cursor. + +--*/ +{ + EraseCursor (This); + + This->Mode->CursorVisible = Visible; + + EraseCursor (This); + + return EFI_SUCCESS; +} + +EFI_STATUS +GetTextColors ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + OUT EFI_UGA_PIXEL *Foreground, + OUT EFI_UGA_PIXEL *Background + ) +{ + INTN Attribute; + + Attribute = This->Mode->Attribute & 0x7F; + + *Foreground = mEfiColors[Attribute & 0x0f]; + *Background = mEfiColors[Attribute >> 4]; + + return EFI_SUCCESS; +} + +EFI_STATUS +DrawUnicodeWeightAtCursorN ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *UnicodeWeight, + IN UINTN Count + ) +{ + GRAPHICS_CONSOLE_DEV *Private; + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + GLYPH_UNION *Glyph; + GLYPH_UNION GlyphData; + INTN GlyphX; + INTN GlyphY; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_UGA_PIXEL Foreground; + EFI_UGA_PIXEL Background; + UINTN Index; + UINTN ArrayIndex; + UINTN Counts; + UINT16 GlyphWidth; + UINT32 GlyphStatus; + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + + ReturnStatus = EFI_SUCCESS; + GlyphStatus = 0; + GlyphWidth = 0x08; + + GetTextColors (This, &Foreground, &Background); + + Index = 0; + ArrayIndex = 0; + while (Index < Count) { + if (This->Mode->Attribute & EFI_WIDE_ATTRIBUTE) { + GlyphStatus = WIDE_CHAR; + } else { + GlyphStatus = NARROW_CHAR; + } + + Status = mHii->GetGlyph ( + mHii, + UnicodeWeight, + (UINT16 *) &Index, + (UINT8 **) &Glyph, + &GlyphWidth, + &GlyphStatus + ); + if (EFI_ERROR (Status)) { + ReturnStatus = Status; + } + + Counts = 0; + + CopyMem (&GlyphData, Glyph, sizeof (GLYPH_UNION)); + + do { + // + // We are creating the second half of the wide character's BLT buffer + // + if (GlyphWidth == 0x10 && Counts == 1) { + CopyMem (&GlyphData.NarrowGlyph.GlyphCol1, &Glyph->WideGlyph.GlyphCol2, sizeof (Glyph->WideGlyph.GlyphCol2)); + } + + Counts++; + + if (GlyphWidth == 0x10) { + mHii->GlyphToBlt ( + mHii, + (UINT8 *) &GlyphData, + Foreground, + Background, + Count * 2, + GLYPH_WIDTH, + GLYPH_HEIGHT, + &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH] + ); + } else { + mHii->GlyphToBlt ( + mHii, + (UINT8 *) &GlyphData, + Foreground, + Background, + Count, + GLYPH_WIDTH, + GLYPH_HEIGHT, + &Private->LineBuffer[ArrayIndex * GLYPH_WIDTH] + ); + } + + ArrayIndex++; + + } while (Counts < 2 && GlyphWidth == 0x10); + + } + // + // If we are printing Wide characters, treat the BLT as if it is twice as many characters + // + if (GlyphWidth == 0x10) { + Count = Count * 2; + } + // + // Blt a character to the screen + // + GlyphX = This->Mode->CursorColumn * GLYPH_WIDTH; + GlyphY = This->Mode->CursorRow * GLYPH_HEIGHT; + UgaDraw = Private->UgaDraw; + UgaDraw->Blt ( + UgaDraw, + Private->LineBuffer, + EfiUgaBltBufferToVideo, + 0, + 0, + GlyphX + Private->ModeData[This->Mode->Mode].DeltaX, + GlyphY + Private->ModeData[This->Mode->Mode].DeltaY, + GLYPH_WIDTH * Count, + GLYPH_HEIGHT, + GLYPH_WIDTH * Count * sizeof (EFI_UGA_PIXEL) + ); + + return ReturnStatus; +} + +EFI_STATUS +EraseCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +{ + GRAPHICS_CONSOLE_DEV *Private; + EFI_SIMPLE_TEXT_OUTPUT_MODE *CurrentMode; + INTN GlyphX; + INTN GlyphY; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_UGA_PIXEL_UNION Foreground; + EFI_UGA_PIXEL_UNION Background; + EFI_UGA_PIXEL_UNION BltChar[GLYPH_HEIGHT][GLYPH_WIDTH]; + UINTN X; + UINTN Y; + + CurrentMode = This->Mode; + + if (!CurrentMode->CursorVisible) { + return EFI_SUCCESS; + } + + Private = GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS (This); + UgaDraw = Private->UgaDraw; + + // + // BUGBUG - we need to think about what to do with wide and narrow character deletions. + // + // + // Blt a character to the screen + // + GlyphX = (CurrentMode->CursorColumn * GLYPH_WIDTH) + Private->ModeData[CurrentMode->Mode].DeltaX; + GlyphY = (CurrentMode->CursorRow * GLYPH_HEIGHT) + Private->ModeData[CurrentMode->Mode].DeltaY; + UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) BltChar, + EfiUgaVideoToBltBuffer, + GlyphX, + GlyphY, + 0, + 0, + GLYPH_WIDTH, + GLYPH_HEIGHT, + GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL) + ); + + GetTextColors (This, &Foreground.Pixel, &Background.Pixel); + + // + // Convert Monochrome bitmap of the Glyph to BltBuffer structure + // + for (Y = 0; Y < GLYPH_HEIGHT; Y++) { + for (X = 0; X < GLYPH_WIDTH; X++) { + if ((mCursorGlyph.GlyphCol1[Y] & (1 << X)) != 0) { + BltChar[Y][GLYPH_WIDTH - X - 1].Raw ^= Foreground.Raw; + } + } + } + + UgaDraw->Blt ( + UgaDraw, + (EFI_UGA_PIXEL *) BltChar, + EfiUgaBltBufferToVideo, + 0, + 0, + GlyphX, + GlyphY, + GLYPH_WIDTH, + GLYPH_HEIGHT, + GLYPH_WIDTH * sizeof (EFI_UGA_PIXEL) + ); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.h b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.h new file mode 100644 index 0000000000..cfbbbb2fa2 --- /dev/null +++ b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.h @@ -0,0 +1,160 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + GraphicsConsole.h + +Abstract: + + +Revision History + +--*/ + +#ifndef _GRAPHICS_CONSOLE_H +#define _GRAPHICS_CONSOLE_H + + +#include "ComponentName.h" + +// +// Glyph database +// +#define GLYPH_WIDTH 8 +#define GLYPH_HEIGHT 19 + +typedef union { + EFI_NARROW_GLYPH NarrowGlyph; + EFI_WIDE_GLYPH WideGlyph; +} GLYPH_UNION; + +extern EFI_NARROW_GLYPH UsStdNarrowGlyphData[]; +extern EFI_WIDE_GLYPH UsStdWideGlyphData[]; + +// +// Device Structure +// +#define GRAPHICS_CONSOLE_DEV_SIGNATURE EFI_SIGNATURE_32 ('g', 's', 't', 'o') + +typedef struct { + UINTN Columns; + UINTN Rows; + INTN DeltaX; + INTN DeltaY; + UINT32 UgaWidth; + UINT32 UgaHeight; +} GRAPHICS_CONSOLE_MODE_DATA; + +#define GRAPHICS_MAX_MODE 3 + +typedef struct { + UINTN Signature; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_SIMPLE_TEXT_OUT_PROTOCOL SimpleTextOutput; + EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode; + GRAPHICS_CONSOLE_MODE_DATA ModeData[GRAPHICS_MAX_MODE]; + EFI_UGA_PIXEL *LineBuffer; + EFI_HII_HANDLE HiiHandle; +} GRAPHICS_CONSOLE_DEV; + +#define GRAPHICS_CONSOLE_CON_OUT_DEV_FROM_THIS(a) \ + CR (a, GRAPHICS_CONSOLE_DEV, SimpleTextOutput, GRAPHICS_CONSOLE_DEV_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gGraphicsConsoleDriverBinding; + +// +// Prototypes +// +UINTN +ReturnNarrowFontSize ( + VOID + ); + +UINTN +ReturnWideFontSize ( + VOID + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutReset ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutTestString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ); + +EFI_STATUS +EFIAPI +GraphicsConsoleConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Visible + ); + +EFI_STATUS +EfiLocateHiiProtocol ( + VOID + ); + +#endif diff --git a/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.mbd b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.mbd new file mode 100644 index 0000000000..4b240ac60b --- /dev/null +++ b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.mbd @@ -0,0 +1,42 @@ + + + + + GraphicsConsole + CCCB0C28-4B24-11d5-9A5A-0090273FC14D + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + UefiMemoryLib + HiiLib + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.msa b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.msa new file mode 100644 index 0000000000..b919c7dea2 --- /dev/null +++ b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/GraphicsConsole.msa @@ -0,0 +1,69 @@ + + + + + GraphicsConsole + DXE_DRIVER + BS_DRIVER + CCCB0C28-4B24-11d5-9A5A-0090273FC14D + 0 + Component description file for GraphicsConsole module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + HiiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + GraphicsConsole.h + GraphicsConsole.c + LaffStd.c + ComponentName.c + + + MdePkg + + + UgaDraw + Hii + SimpleTextOut + DevicePath + + + + + + + gGraphicsConsoleDriverBinding + gGraphicsConsoleComponentName + + + diff --git a/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/LaffStd.c b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/LaffStd.c new file mode 100644 index 0000000000..ac8dd16833 --- /dev/null +++ b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/LaffStd.c @@ -0,0 +1,290 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + LaffStd.c + +Abstract: + + +Revision History + +--*/ + +#include "GraphicsConsole.h" + +EFI_NARROW_GLYPH UsStdNarrowGlyphData[] = { + // + // Unicode glyphs from 0x20 to 0x7e are the same as ASCII characters 0x20 to 0x7e + // + { 0x0020, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0021, 0x00, {0x00,0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x0022, 0x00, {0x00,0x00,0x00,0x6C,0x6C,0x6C,0x28,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0023, 0x00, {0x00,0x00,0x00,0x00,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0xFE,0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00}}, + { 0x0024, 0x00, {0x00,0x00,0x18,0x18,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00}}, + { 0x0025, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x60,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x0026, 0x00, {0x00,0x00,0x00,0x78,0xCC,0xCC,0xCC,0x78,0x76,0xDC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x0027, 0x00, {0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0028, 0x00, {0x00,0x00,0x00,0x06,0x0C,0x0C,0x18,0x18,0x18,0x18,0x18,0x18,0x0C,0x0C,0x06,0x00,0x00,0x00,0x00}}, + { 0x0029, 0x00, {0x00,0x00,0x00,0xC0,0x60,0x60,0x30,0x30,0x30,0x30,0x30,0x30,0x60,0x60,0xC0,0x00,0x00,0x00,0x00}}, + { 0x002a, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x38,0xFE,0x38,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x002b, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x002c, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00,0x00}}, + { 0x002d, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x002e, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x002f, 0x00, {0x00,0x00,0x00,0x06,0x06,0x0C,0x0C,0x18,0x18,0x30,0x30,0x60,0x60,0xC0,0xC0,0x00,0x00,0x00,0x00}}, + { 0x0030, 0x00, {0x00,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xD6,0xD6,0xC6,0xC6,0xC6,0x6C,0x38,0x00,0x00,0x00,0x00}}, + { 0x0031, 0x00, {0x00,0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00}}, + { 0x0032, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0x06,0x06,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC2,0xFE,0x00,0x00,0x00,0x00}}, + { 0x0033, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0x06,0x06,0x06,0x3C,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0034, 0x00, {0x00,0x00,0x00,0x1C,0x1C,0x3C,0x3C,0x6C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}}, + { 0x0035, 0x00, {0x00,0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0036, 0x00, {0x00,0x00,0x00,0x3C,0x60,0xC0,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0037, 0x00, {0x00,0x00,0x00,0xFE,0xC6,0x06,0x06,0x06,0x0C,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x0038, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0039, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00}}, + { 0x003a, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { 0x003b, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00}}, + { 0x003c, 0x00, {0x00,0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00}}, + { 0x003d, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x003e, 0x00, {0x00,0x00,0x00,0x00,0xC0,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0xC0,0x00,0x00,0x00,0x00}}, + { 0x003f, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x0040, 0x00, {0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0xC0,0x7E,0x00,0x00,0x00,0x00}}, + + { 0x0041, 0x00, {0x00,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + + { 0x0042, 0x00, {0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00}}, + { 0x0043, 0x00, {0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00}}, + { 0x0044, 0x00, {0x00,0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00}}, + { 0x0045, 0x00, {0x00,0x00,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x0046, 0x00, {0x00,0x00,0x00,0xFE,0x66,0x62,0x60,0x64,0x7C,0x64,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}}, + { 0x0047, 0x00, {0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xDE,0xC6,0xC6,0xC6,0x66,0x3C,0x00,0x00,0x00,0x00}}, + { 0x0048, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x0049, 0x00, {0x00,0x00,0x00,0xFC,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xFC,0x00,0x00,0x00,0x00}}, + { 0x004a, 0x00, {0x00,0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00}}, + { 0x004b, 0x00, {0x00,0x00,0x00,0xE6,0x66,0x6C,0x6C,0x78,0x70,0x78,0x6C,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}}, + { 0x004c, 0x00, {0x00,0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x004d, 0x00, {0x00,0x00,0x00,0xC6,0xEE,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x004e, 0x00, {0x00,0x00,0x00,0xC6,0xE6,0xF6,0xF6,0xF6,0xDE,0xCE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x004f, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0050, 0x00, {0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}}, + { 0x0051, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0x7C,0x1C,0x0E,0x00,0x00}}, + { 0x0052, 0x00, {0x00,0x00,0x00,0xFC,0x66,0x66,0x66,0x66,0x7C,0x78,0x6C,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}}, + { 0x0053, 0x00, {0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x60,0x38,0x0C,0x06,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0054, 0x00, {0x00,0x00,0x00,0xFC,0xFC,0xB4,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}}, + { 0x0055, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0056, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00}}, + { 0x0057, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00}}, + { 0x0058, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0xC6,0x6C,0x6C,0x38,0x6C,0x6C,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x0059, 0x00, {0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}}, + { 0x005a, 0x00, {0x00,0x00,0x00,0xFE,0xC6,0x86,0x0C,0x0C,0x18,0x30,0x60,0xC0,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00}}, + { 0x005b, 0x00, {0x00,0x00,0x00,0x1E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1E,0x00,0x00,0x00,0x00}}, + { 0x005c, 0x00, {0x00,0x00,0x00,0xC0,0xC0,0x60,0x60,0x30,0x30,0x18,0x18,0x0C,0x0C,0x06,0x06,0x00,0x00,0x00,0x00}}, + { 0x005d, 0x00, {0x00,0x00,0x00,0xF0,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0xF0,0x00,0x00,0x00,0x00}}, + { 0x005e, 0x00, {0x00,0x00,0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x005f, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00}}, + { 0x0060, 0x00, {0x00,0x30,0x30,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x0061, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x0062, 0x00, {0x00,0x00,0x00,0xE0,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0063, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0064, 0x00, {0x00,0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x3C,0x6C,0xCC,0xCC,0xCC,0xCC,0xCC,0x7E,0x00,0x00,0x00,0x00}}, + { 0x0065, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0066, 0x00, {0x00,0x00,0x00,0x1E,0x33,0x30,0x30,0x30,0x78,0x30,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}}, + { 0x0067, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0xCC,0x78,0x00}}, + { 0x0068, 0x00, {0x00,0x00,0x00,0xE0,0x60,0x60,0x60,0x7C,0x76,0x66,0x66,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00}}, + { 0x0069, 0x00, {0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x006a, 0x00, {0x00,0x00,0x00,0x0C,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x6C,0x38,0x00}}, + { 0x006b, 0x00, {0x00,0x00,0x00,0xE0,0x60,0x60,0x66,0x6C,0x78,0x70,0x78,0x6C,0x6C,0x66,0xE6,0x00,0x00,0x00,0x00}}, + { 0x006c, 0x00, {0x00,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x006d, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEC,0xEE,0xFE,0xD6,0xD6,0xD6,0xD6,0xD6,0x00,0x00,0x00,0x00}}, + { 0x006e, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00}}, + { 0x006f, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0070, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00}}, + { 0x0071, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x76,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x7C,0x0C,0x0C,0x1E,0x00}}, + { 0x0072, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDC,0x66,0x60,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00}}, + { 0x0073, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0x7C,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x0074, 0x00, {0x00,0x00,0x00,0x10,0x30,0x30,0x30,0xFC,0x30,0x30,0x30,0x30,0x30,0x36,0x1C,0x00,0x00,0x00,0x00}}, + { 0x0075, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x0076, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x78,0x30,0x00,0x00,0x00,0x00}}, + { 0x0077, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00}}, + { 0x0078, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x6C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x0079, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00}}, + { 0x007a, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x86,0x0C,0x18,0x30,0x60,0xC0,0xFE,0x00,0x00,0x00,0x00}}, + { 0x007b, 0x00, {0x00,0x00,0x00,0x0E,0x18,0x18,0x18,0x18,0x30,0x18,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}}, + { 0x007c, 0x00, {0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x007d, 0x00, {0x00,0x00,0x00,0xE0,0x30,0x30,0x30,0x30,0x18,0x30,0x30,0x30,0x30,0x30,0xE0,0x00,0x00,0x00,0x00}}, + { 0x007e, 0x00, {0x00,0x00,0x00,0x76,0xDC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + + { 0x00a0, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00a1, 0x00, {0x00,0x00,0x00,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x3C,0x3C,0x3C,0x18,0x00,0x00,0x00,0x00}}, + { 0x00a2, 0x00, {0x00,0x00,0x00,0x00,0x18,0x18,0x7C,0xC6,0xC0,0xC0,0xC0,0xC6,0x7C,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x00a3, 0x00, {0x00,0x00,0x00,0x38,0x6C,0x64,0x60,0x60,0xF0,0x60,0x60,0x60,0x60,0xE6,0xFC,0x00,0x00,0x00,0x00}}, + { 0x00a4, 0x00, {0x00,0x00,0x18,0x00,0x00,0x00,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x00a5, 0x00, {0x00,0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x7E,0x18,0x7E,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x00a6, 0x00, {0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00}}, + { 0x00a7, 0x00, {0x00,0x00,0x18,0x7C,0xC6,0x60,0x38,0x6C,0xC6,0xC6,0x6C,0x38,0x0C,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00a8, 0x00, {0x00,0x00,0x00,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00a9, 0x00, {0x00,0x00,0x00,0x00,0x7C,0x82,0x9A,0xA2,0xA2,0xA2,0x9A,0x82,0x7C,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00aa, 0x00, {0x00,0x00,0x00,0x00,0x3C,0x6C,0x6C,0x6C,0x3E,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ab, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x36,0x6C,0xD8,0x6C,0x36,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ac, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0x06,0x06,0x06,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ad, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ae, 0x00, {0x00,0x00,0x00,0x00,0x7C,0x82,0xB2,0xAA,0xAA,0xB2,0xAA,0xAA,0x82,0x7C,0x00,0x00,0x00,0x00,0x00}}, + { 0x00af, 0x00, {0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b0, 0x00, {0x00,0x00,0x00,0x38,0x6C,0x6C,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b1, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b2, 0x00, {0x00,0x00,0x00,0x3C,0x66,0x0C,0x18,0x32,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b3, 0x00, {0x00,0x00,0x00,0x7C,0x06,0x3C,0x06,0x06,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b4, 0x00, {0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b5, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xC0,0x00}}, + { 0x00b6, 0x00, {0x00,0x00,0x00,0x7F,0xDB,0xDB,0xDB,0xDB,0x7B,0x1B,0x1B,0x1B,0x1B,0x1B,0x1B,0x00,0x00,0x00,0x00}}, + { 0x00b7, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00b8, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x0C,0x78,0x00,0x00,0x00}}, + { 0x00b9, 0x00, {0x00,0x00,0x00,0x18,0x38,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00ba, 0x00, {0x00,0x00,0x00,0x00,0x38,0x6C,0x6C,0x6C,0x38,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00bb, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xD8,0x6C,0x36,0x6C,0xD8,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00bc, 0x00, {0x00,0x00,0x00,0x60,0xE0,0x62,0x66,0x6C,0x18,0x30,0x66,0xCE,0x9A,0x3F,0x06,0x06,0x00,0x00,0x00}}, + { 0x00bd, 0x00, {0x00,0x00,0x00,0x60,0xE0,0x62,0x66,0x6C,0x18,0x30,0x60,0xDC,0x86,0x0C,0x18,0x3E,0x00,0x00,0x00}}, + { 0x00be, 0x00, {0x00,0x00,0x00,0xE0,0x30,0x62,0x36,0xEC,0x18,0x30,0x66,0xCE,0x9A,0x3F,0x06,0x06,0x00,0x00,0x00}}, + { 0x00bf, 0x00, {0x00,0x00,0x00,0x00,0x30,0x30,0x00,0x30,0x30,0x60,0x60,0xC0,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00c0, 0x00, {0x60,0x30,0x18,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c1, 0x00, {0x18,0x30,0x60,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c2, 0x00, {0x10,0x38,0x6C,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c3, 0x00, {0x76,0xDC,0x00,0x00,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c4, 0x00, {0xCC,0xCC,0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c5, 0x00, {0x38,0x6C,0x38,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00c6, 0x00, {0x00,0x00,0x00,0x00,0x3E,0x6C,0xCC,0xCC,0xCC,0xFE,0xCC,0xCC,0xCC,0xCC,0xCE,0x00,0x00,0x00,0x00}}, + { 0x00c7, 0x00, {0x00,0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x18,0x70,0x00,0x00}}, + { 0x00c8, 0x00, {0x60,0x30,0x18,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x00c9, 0x00, {0x18,0x30,0x60,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x00ca, 0x00, {0x10,0x38,0x6C,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x00cb, 0x00, {0xCC,0xCC,0x00,0x00,0xFE,0x66,0x62,0x60,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00}}, + { 0x00cc, 0x00, {0x60,0x30,0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00cd, 0x00, {0x18,0x30,0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00ce, 0x00, {0x10,0x38,0x6C,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00cf, 0x00, {0xCC,0xCC,0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00d0, 0x00, {0x00,0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0xF6,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00}}, + { 0x00d1, 0x00, {0x76,0xDC,0x00,0x00,0xC6,0xE6,0xE6,0xF6,0xF6,0xDE,0xDE,0xCE,0xCE,0xC6,0xC6,0x00,0x00,0x00,0x00}}, + { 0x00d2, 0x00, {0x60,0x30,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00d3, 0x00, {0x18,0x30,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00d4, 0x00, {0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00d5, 0x00, {0x76,0xDC,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00d6, 0x00, {0xCC,0xCC,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00d7, 0x00, {0x10,0x28,0x00,0x00,0x00,0x00,0x00,0xC6,0x6C,0x38,0x38,0x6C,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00}}, + { 0x00d8, 0x00, {0x00,0x00,0x00,0x7C,0xCE,0xCE,0xDE,0xD6,0xD6,0xD6,0xD6,0xF6,0xE6,0xE6,0x7C,0x40,0x00,0x00,0x00}}, + { 0x00d9, 0x00, {0x60,0x30,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00da, 0x00, {0x18,0x30,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00db, 0x00, {0x10,0x38,0x6C,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00dc, 0x00, {0xCC,0xCC,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00dd, 0x00, {0x18,0x30,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00de, 0x00, {0x00,0x00,0x10,0x00,0xF0,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x7C,0x60,0xF0,0x00,0x00,0x00,0x00}}, + { 0x00df, 0x00, {0x00,0x00,0x00,0x78,0xCC,0xCC,0xCC,0xCC,0xD8,0xCC,0xC6,0xC6,0xC6,0xC6,0xCC,0x00,0x00,0x00,0x00}}, + { 0x00e0, 0x00, {0x00,0x30,0x30,0x60,0x30,0x18,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e1, 0x00, {0x00,0x00,0x00,0x18,0x30,0x60,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e2, 0x00, {0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e3, 0x00, {0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e4, 0x00, {0x00,0x00,0x00,0xCC,0xCC,0x00,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e5, 0x00, {0x00,0x00,0x00,0x38,0x6C,0x38,0x00,0x78,0x0C,0x0C,0x7C,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00e6, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEC,0x36,0x36,0x7E,0xD8,0xD8,0xD8,0x6E,0x00,0x00,0x00,0x00}}, + { 0x00e7, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xC6,0xC0,0xC0,0xC0,0xC0,0xC6,0x7C,0x18,0x70,0x00,0x00}}, + { 0x00e8, 0x00, {0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00e9, 0x00, {0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00ea, 0x00, {0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00eb, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xFE,0xC0,0xC0,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00ec, 0x00, {0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00ed, 0x00, {0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00ee, 0x00, {0x00,0x00,0x00,0x18,0x3C,0x66,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00ef, 0x00, {0x00,0x00,0x00,0x66,0x66,0x00,0x00,0x38,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00f0, 0x00, {0x00,0x00,0x00,0x34,0x18,0x2C,0x0C,0x06,0x3E,0x66,0x66,0x66,0x66,0x66,0x3C,0x00,0x00,0x00,0x00}}, + { 0x00f1, 0x00, {0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0xDC,0x66,0x66,0x66,0x66,0x66,0x66,0x66,0x00,0x00,0x00,0x00}}, + { 0x00f2, 0x00, {0x00,0x00,0x00,0x60,0x30,0x18,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f3, 0x00, {0x00,0x00,0x00,0x18,0x30,0x60,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f4, 0x00, {0x00,0x00,0x00,0x10,0x38,0x6C,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f5, 0x00, {0x00,0x00,0x00,0x00,0x76,0xDC,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f6, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f7, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x7E,0x00,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { 0x00f8, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xCE,0xDE,0xD6,0xF6,0xE6,0xC6,0x7C,0x00,0x00,0x00,0x00}}, + { 0x00f9, 0x00, {0x00,0x00,0x00,0x60,0x30,0x18,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00fa, 0x00, {0x00,0x00,0x00,0x18,0x30,0x60,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00fb, 0x00, {0x00,0x00,0x00,0x30,0x78,0xCC,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00fc, 0x00, {0x00,0x00,0x00,0xCC,0xCC,0x00,0x00,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00}}, + { 0x00fd, 0x00, {0x00,0x00,0x00,0x0C,0x18,0x30,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0xF8,0x00}}, + { 0x00fe, 0x00, {0x00,0x00,0x00,0xE0,0x60,0x60,0x60,0x7C,0x66,0x66,0x66,0x66,0x66,0x66,0x7C,0x60,0x60,0xF0,0x00}}, + { 0x00ff, 0x00, {0x00,0x00,0x00,0xC6,0xC6,0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7E,0x06,0x0C,0x78,0x00}}, + + { (CHAR16)BOXDRAW_HORIZONTAL, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_VERTICAL, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_RIGHT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_LEFT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_UP_RIGHT, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_UP_LEFT, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_VERTICAL_RIGHT, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_VERTICAL_LEFT, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_HORIZONTAL, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_UP_HORIZONTAL, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_VERTICAL_HORIZONTAL, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOUBLE_HORIZONTAL, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_DOUBLE_VERTICAL, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOWN_RIGHT_DOUBLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_DOUBLE_RIGHT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_DOWN_RIGHT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3F,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOWN_LEFT_DOUBLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_DOUBLE_LEFT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_DOWN_LEFT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_UP_RIGHT_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_UP_DOUBLE_RIGHT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_DOUBLE_UP_RIGHT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_UP_LEFT_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_UP_DOUBLE_LEFT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_DOUBLE_UP_LEFT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_VERTICAL_RIGHT_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x18,0x1F,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_VERTICAL_DOUBLE_RIGHT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_VERTICAL_RIGHT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x37,0x30,0x37,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_VERTICAL_LEFT_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xF8,0x18,0xF8,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_VERTICAL_DOUBLE_LEFT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_VERTICAL_LEFT, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF6,0x06,0xF6,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOWN_HORIZONTAL_DOUBLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_DOWN_DOUBLE_HORIZONTAL, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_DOWN_HORIZONTAL, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_UP_HORIZONTAL_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_UP_DOUBLE_HORIZONTAL, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_DOUBLE_UP_HORIZONTAL, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, 0x00, {0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18}}, + { (CHAR16)BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xFF,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + { (CHAR16)BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, 0x00, {0x36,0x36,0x36,0x36,0x36,0x36,0x36,0xF7,0x00,0xF7,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36,0x36}}, + + { (CHAR16)BLOCKELEMENT_FULL_BLOCK, 0x00, {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}}, + { (CHAR16)BLOCKELEMENT_LIGHT_SHADE, 0x00, {0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22,0x88,0x22}}, + + { (CHAR16)GEOMETRICSHAPE_RIGHT_TRIANGLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0xF0,0xF8,0xFE,0xF8,0xF0,0xE0,0xC0,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)GEOMETRICSHAPE_LEFT_TRIANGLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x06,0x0E,0x1E,0x3E,0xFE,0x3E,0x1E,0x0E,0x06,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)GEOMETRICSHAPE_UP_TRIANGLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x38,0x38,0x7C,0x7C,0xFE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)GEOMETRICSHAPE_DOWN_TRIANGLE, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xFE,0x7C,0x7C,0x38,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00}}, + + { (CHAR16)ARROW_UP, 0x00, {0x00,0x00,0x00,0x18,0x3C,0x7E,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)ARROW_DOWN, 0x00, {0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x3C,0x18,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)ARROW_LEFT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x20,0x60,0x60,0xFE,0xFE,0x60,0x60,0x20,0x00,0x00,0x00,0x00,0x00,0x00}}, + { (CHAR16)ARROW_RIGHT, 0x00, {0x00,0x00,0x00,0x00,0x00,0x08,0x0C,0x0C,0xFE,0xFE,0x0C,0x0C,0x08,0x00,0x00,0x00,0x00,0x00,0x00}}, + + { 0x0000, 0x00, {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}} //EOL +}; + +UINTN +ReturnNarrowFontSize ( + VOID + ) +{ + // + // I need the size of this outside of this file, so here is a stub function to do that for me + // + return sizeof (UsStdNarrowGlyphData); +} diff --git a/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/build.xml b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/build.xml new file mode 100644 index 0000000000..896302767b --- /dev/null +++ b/EdkModulePkg/Universal/Console/GraphicsConsole/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Console/Terminal/Dxe/ComponentName.c b/EdkModulePkg/Universal/Console/Terminal/Dxe/ComponentName.c new file mode 100644 index 0000000000..cc925b13c9 --- /dev/null +++ b/EdkModulePkg/Universal/Console/Terminal/Dxe/ComponentName.c @@ -0,0 +1,194 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + + +#include "Terminal.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +TerminalComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +TerminalComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gTerminalComponentName = { + TerminalComponentNameGetDriverName, + TerminalComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mTerminalDriverNameTable[] = { + { + "eng", + (CHAR16 *) L"Serial Terminal Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +TerminalComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gTerminalComponentName.SupportedLanguages, + mTerminalDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +TerminalComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *SimpleTextOutput; + TERMINAL_DEV *TerminalDevice; + + // + // This is a bus driver, so ChildHandle can not be NULL. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &SimpleTextOutput, + gTerminalDriverBinding.DriverBindingHandle, + ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput); + + return LookupUnicodeString ( + Language, + gTerminalComponentName.SupportedLanguages, + TerminalDevice->ControllerNameTable, + ControllerName + ); +} diff --git a/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.c b/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.c new file mode 100644 index 0000000000..d462e05d0c --- /dev/null +++ b/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.c @@ -0,0 +1,1214 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Terminal.c + +Abstract: + +Revision History: + +--*/ + + +#include "Terminal.h" +#include + +// +// Function Prototypes +// +EFI_STATUS +EFIAPI +TerminalDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +TerminalDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +TerminalDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Globals +// +EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding = { + TerminalDriverBindingSupported, + TerminalDriverBindingStart, + TerminalDriverBindingStop, + 0x10, + NULL, + NULL +}; + + +EFI_STATUS +EFIAPI +TerminalDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + VENDOR_DEVICE_PATH *Node; + + // + // If remaining device path is not NULL, then make sure it is a + // device path that describes a terminal communications protocol. + // + if (RemainingDevicePath != NULL) { + + Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath; + + if (Node->Header.Type != MESSAGING_DEVICE_PATH || + Node->Header.SubType != MSG_VENDOR_DP || + DevicePathNodeLength(&Node->Header) != sizeof(VENDOR_DEVICE_PATH)) { + + return EFI_UNSUPPORTED; + + } + // + // only supports PC ANSI, VT100, VT100+ and VT-UTF8 terminal types + // + if (!CompareGuid (&Node->Guid, &gEfiPcAnsiGuid) && + !CompareGuid (&Node->Guid, &gEfiVT100Guid) && + !CompareGuid (&Node->Guid, &gEfiVT100PlusGuid) && + !CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) { + + return EFI_UNSUPPORTED; + } + } + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + // + // The Controller must support the Serial I/O Protocol. + // This driver is a bus driver with at most 1 child device, so it is + // ok for it to be already started. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + + Start the controller. + + Arguments: + + This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - The handle of the controller to start. + RemainingDevicePath - A pointer to the remaining portion of a devcie path. + + Returns: + + EFI_SUCCESS. + +--*/ +{ + EFI_STATUS Status; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + VENDOR_DEVICE_PATH *Node; + VENDOR_DEVICE_PATH *DefaultNode; + EFI_SERIAL_IO_MODE *Mode; + UINTN SerialInTimeOut; + TERMINAL_DEV *TerminalDevice; + UINT8 TerminalType; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + TerminalDevice = NULL; + DefaultNode = NULL; + // + // Get the Device Path Protocol to build the device path of the child device + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + // + // Report that the remote terminal is being enabled + // + DevicePath = ParentDevicePath; + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_ENABLE, + DevicePath + ); + + // + // Open the Serial I/O Protocol BY_DRIVER. It might already be started. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + if (Status != EFI_ALREADY_STARTED) { + // + // If Serial I/O is not already open by this driver, then tag the handle + // with the Terminal Driver GUID and update the ConInDev, ConOutDev, and + // StdErrDev variables with the list of possible terminal types on this + // serial port. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiCallerIdGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiCallerIdGuid, + DuplicateDevicePath (ParentDevicePath), + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // if the serial device is a hot plug device, do not update the + // ConInDev, ConOutDev, and StdErrDev variables. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiHotPlugDeviceGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + TerminalUpdateConsoleDevVariable ((CHAR16 *)VarConsoleInpDev, ParentDevicePath); + TerminalUpdateConsoleDevVariable ((CHAR16 *)VarConsoleOutDev, ParentDevicePath); + TerminalUpdateConsoleDevVariable ((CHAR16 *)VarErrorOutDev, ParentDevicePath); + } + } + } + // + // Make sure a child handle does not already exist. This driver can only + // produce one child per serial port. + // + Status = gBS->OpenProtocolInformation ( + Controller, + &gEfiSerialIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (!EFI_ERROR (Status)) { + Status = EFI_SUCCESS; + for (Index = 0; Index < EntryCount; Index++) { + if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { + Status = EFI_ALREADY_STARTED; + } + } + + gBS->FreePool (OpenInfoBuffer); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // If RemainingDevicePath is NULL, then create default device path node + // + if (RemainingDevicePath == NULL) { + DefaultNode = AllocatePool (sizeof (VENDOR_DEVICE_PATH)); + if (DefaultNode == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + CopyMem (&DefaultNode->Guid, &gEfiPcAnsiGuid, sizeof (EFI_GUID)); + RemainingDevicePath = (EFI_DEVICE_PATH_PROTOCOL*) DefaultNode; + } + // + // Use the RemainingDevicePath to determine the terminal type + // + Node = (VENDOR_DEVICE_PATH *) RemainingDevicePath; + + if (CompareGuid (&Node->Guid, &gEfiPcAnsiGuid)) { + + TerminalType = PcAnsiType; + + } else if (CompareGuid (&Node->Guid, &gEfiVT100Guid)) { + + TerminalType = VT100Type; + + } else if (CompareGuid (&Node->Guid, &gEfiVT100PlusGuid)) { + + TerminalType = VT100PlusType; + + } else if (CompareGuid (&Node->Guid, &gEfiVTUTF8Guid)) { + + TerminalType = VTUTF8Type; + + } else { + goto Error; + } + // + // Initialize the Terminal Dev + // + TerminalDevice = AllocatePool (sizeof (TERMINAL_DEV)); + if (TerminalDevice == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + ZeroMem (TerminalDevice, sizeof (TERMINAL_DEV)); + + TerminalDevice->Signature = TERMINAL_DEV_SIGNATURE; + + TerminalDevice->TerminalType = TerminalType; + + TerminalDevice->SerialIo = SerialIo; + + // + // Simple Input Protocol + // + TerminalDevice->SimpleInput.Reset = TerminalConInReset; + TerminalDevice->SimpleInput.ReadKeyStroke = TerminalConInReadKeyStroke; + + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_WAIT, + EFI_TPL_NOTIFY, + TerminalConInWaitForKey, + &TerminalDevice->SimpleInput, + &TerminalDevice->SimpleInput.WaitForKey + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // initialize the FIFO buffer used for accommodating + // the pre-read pending characters + // + InitializeRawFiFo (TerminalDevice); + InitializeUnicodeFiFo (TerminalDevice); + InitializeEfiKeyFiFo (TerminalDevice); + + // + // Set the timeout value of serial buffer for + // keystroke response performance issue + // + Mode = TerminalDevice->SerialIo->Mode; + + SerialInTimeOut = 0; + if (Mode->BaudRate != 0) { + SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate; + } + + Status = TerminalDevice->SerialIo->SetAttributes ( + TerminalDevice->SerialIo, + Mode->BaudRate, + Mode->ReceiveFifoDepth, + (UINT32) SerialInTimeOut, + Mode->Parity, + (UINT8) Mode->DataBits, + Mode->StopBits + ); + if (EFI_ERROR (Status)) { + // + // if set attributes operation fails, invalidate + // the value of SerialInTimeOut,thus make it + // inconsistent with the default timeout value + // of serial buffer. This will invoke the recalculation + // in the readkeystroke routine. + // + TerminalDevice->SerialInTimeOut = 0; + } else { + TerminalDevice->SerialInTimeOut = SerialInTimeOut; + } + // + // Build the device path for the child device + // + Status = SetTerminalDevicePath ( + TerminalDevice->TerminalType, + ParentDevicePath, + &TerminalDevice->DevicePath + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + DevicePath = TerminalDevice->DevicePath; + + Status = TerminalDevice->SimpleInput.Reset ( + &TerminalDevice->SimpleInput, + FALSE + ); + if (EFI_ERROR (Status)) { + // + // Need to report Error Code first + // + goto ReportError; + } + // + // Simple Text Output Protocol + // + TerminalDevice->SimpleTextOutput.Reset = TerminalConOutReset; + TerminalDevice->SimpleTextOutput.OutputString = TerminalConOutOutputString; + TerminalDevice->SimpleTextOutput.TestString = TerminalConOutTestString; + TerminalDevice->SimpleTextOutput.QueryMode = TerminalConOutQueryMode; + TerminalDevice->SimpleTextOutput.SetMode = TerminalConOutSetMode; + TerminalDevice->SimpleTextOutput.SetAttribute = TerminalConOutSetAttribute; + TerminalDevice->SimpleTextOutput.ClearScreen = TerminalConOutClearScreen; + TerminalDevice->SimpleTextOutput.SetCursorPosition = TerminalConOutSetCursorPosition; + TerminalDevice->SimpleTextOutput.EnableCursor = TerminalConOutEnableCursor; + TerminalDevice->SimpleTextOutput.Mode = &TerminalDevice->SimpleTextOutputMode; + + TerminalDevice->SimpleTextOutputMode.MaxMode = 1; + // + // For terminal devices, cursor is always visible + // + TerminalDevice->SimpleTextOutputMode.CursorVisible = TRUE; + TerminalDevice->SimpleTextOutputMode.Attribute = EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK); + + Status = TerminalDevice->SimpleTextOutput.Reset ( + &TerminalDevice->SimpleTextOutput, + FALSE + ); + if (EFI_ERROR (Status)) { + goto ReportError; + } + + Status = TerminalDevice->SimpleTextOutput.SetMode ( + &TerminalDevice->SimpleTextOutput, + 0 + ); + if (EFI_ERROR (Status)) { + goto ReportError; + } + + Status = TerminalDevice->SimpleTextOutput.EnableCursor ( + &TerminalDevice->SimpleTextOutput, + TRUE + ); + if (EFI_ERROR (Status)) { + goto ReportError; + } + // + // + // + TerminalDevice->InputState = INPUT_STATE_DEFAULT; + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &TerminalDevice->TwoSecondTimeOut + ); + + // + // Build the component name for the child device + // + TerminalDevice->ControllerNameTable = NULL; + switch (TerminalDevice->TerminalType) { + case PcAnsiType: + AddUnicodeString ( + "eng", + gTerminalComponentName.SupportedLanguages, + &TerminalDevice->ControllerNameTable, + (CHAR16 *)L"PC-ANSI Serial Console" + ); + break; + + case VT100Type: + AddUnicodeString ( + "eng", + gTerminalComponentName.SupportedLanguages, + &TerminalDevice->ControllerNameTable, + (CHAR16 *)L"VT-100 Serial Console" + ); + break; + + case VT100PlusType: + AddUnicodeString ( + "eng", + gTerminalComponentName.SupportedLanguages, + &TerminalDevice->ControllerNameTable, + (CHAR16 *)L"VT-100+ Serial Console" + ); + break; + + case VTUTF8Type: + AddUnicodeString ( + "eng", + gTerminalComponentName.SupportedLanguages, + &TerminalDevice->ControllerNameTable, + (CHAR16 *)L"VT-UTF8 Serial Console" + ); + break; + } + // + // Install protocol interfaces for the serial device. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &TerminalDevice->Handle, + &gEfiDevicePathProtocolGuid, + TerminalDevice->DevicePath, + &gEfiSimpleTextInProtocolGuid, + &TerminalDevice->SimpleInput, + &gEfiSimpleTextOutProtocolGuid, + &TerminalDevice->SimpleTextOutput, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + // + // if the serial device is a hot plug device, attaches the HotPlugGuid + // onto the terminal device handle. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiHotPlugDeviceGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &TerminalDevice->Handle, + &gEfiHotPlugDeviceGuid, + NULL, + NULL + ); + } + // + // Register the Parent-Child relationship via + // EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + (VOID **) &TerminalDevice->SerialIo, + This->DriverBindingHandle, + TerminalDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + if (DefaultNode != NULL) { + gBS->FreePool (DefaultNode); + } + + return EFI_SUCCESS; + +ReportError: + // + // Report error code before exiting + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + DevicePath + ); + +Error: + // + // Use the Stop() function to free all resources allocated in Start() + // + if (TerminalDevice != NULL) { + + if (TerminalDevice->Handle != NULL) { + This->Stop (This, Controller, 1, &TerminalDevice->Handle); + } else { + + if (TerminalDevice->TwoSecondTimeOut != NULL) { + gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut); + } + + if (TerminalDevice->SimpleInput.WaitForKey != NULL) { + gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey); + } + + if (TerminalDevice->ControllerNameTable != NULL) { + FreeUnicodeStringTable (TerminalDevice->ControllerNameTable); + } + + if (TerminalDevice->DevicePath != NULL) { + gBS->FreePool (TerminalDevice->DevicePath); + } + + gBS->FreePool (TerminalDevice); + } + } + + if (DefaultNode != NULL) { + gBS->FreePool (DefaultNode); + } + + This->Stop (This, Controller, 0, NULL); + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + + Stop a device controller. + + Arguments: + + This - A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance. + Controller - A handle to the device being stopped. + NumberOfChildren - The number of child device handles in ChildHandleBuffer. + ChildHandleBuffer - An array of child handles to be freed. + + Returns: + + EFI_SUCCESS - Operation successful. + EFI_DEVICE_ERROR - Devices error. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + BOOLEAN AllChildrenStopped; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *SimpleTextOutput; + TERMINAL_DEV *TerminalDevice; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + Status = gBS->HandleProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Report that the remote terminal is being disabled + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_DISABLE, + DevicePath + ); + + // + // Complete all outstanding transactions to Controller. + // Don't allow any new transaction to Controller to be started. + // + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiCallerIdGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + // + // Remove Parent Device Path from + // the Console Device Environment Variables + // + TerminalRemoveConsoleDevVariable ((CHAR16 *)VarConsoleInpDev, ParentDevicePath); + TerminalRemoveConsoleDevVariable ((CHAR16 *)VarConsoleOutDev, ParentDevicePath); + TerminalRemoveConsoleDevVariable ((CHAR16 *)VarErrorOutDev, ParentDevicePath); + + // + // Uninstall the Terminal Driver's GUID Tag from the Serial controller + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiCallerIdGuid, + ParentDevicePath, + NULL + ); + + // + // Free the ParentDevicePath that was duplicated in Start() + // + if (!EFI_ERROR (Status)) { + gBS->FreePool (ParentDevicePath); + } + } + + gBS->CloseProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return EFI_SUCCESS; + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &SimpleTextOutput, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (SimpleTextOutput); + + gBS->CloseProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiSimpleTextInProtocolGuid, + &TerminalDevice->SimpleInput, + &gEfiSimpleTextOutProtocolGuid, + &TerminalDevice->SimpleTextOutput, + &gEfiDevicePathProtocolGuid, + TerminalDevice->DevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Controller, + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + + if (TerminalDevice->ControllerNameTable != NULL) { + FreeUnicodeStringTable (TerminalDevice->ControllerNameTable); + } + + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiHotPlugDeviceGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiHotPlugDeviceGuid, + NULL, + NULL + ); + } else { + Status = EFI_SUCCESS; + } + + gBS->CloseEvent (TerminalDevice->TwoSecondTimeOut); + gBS->CloseEvent (TerminalDevice->SimpleInput.WaitForKey); + gBS->FreePool (TerminalDevice->DevicePath); + gBS->FreePool (TerminalDevice); + } + } + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +VOID +TerminalUpdateConsoleDevVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath + ) +{ + EFI_STATUS Status; + UINTN VariableSize; + UINT8 TerminalType; + EFI_DEVICE_PATH_PROTOCOL *Variable; + EFI_DEVICE_PATH_PROTOCOL *NewVariable; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + + Variable = NULL; + + // + // Get global variable and its size according to the name given. + // + Variable = TerminalGetVariableAndSize ( + VariableName, + &gEfiGlobalVariableGuid, + &VariableSize + ); + // + // Append terminal device path onto the variable. + // + for (TerminalType = PcAnsiType; TerminalType <= VTUTF8Type; TerminalType++) { + SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath); + NewVariable = AppendDevicePathInstance (Variable, TempDevicePath); + if (Variable != NULL) { + gBS->FreePool (Variable); + } + + if (TempDevicePath != NULL) { + gBS->FreePool (TempDevicePath); + } + + Variable = NewVariable; + } + + VariableSize = GetDevicePathSize (Variable); + + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VariableSize, + Variable + ); + gBS->FreePool (Variable); + + return ; +} + +VOID +TerminalRemoveConsoleDevVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath + ) +/*++ + + Routine Description: + + Remove console device variable. + + Arguments: + + VariableName - A pointer to the variable name. + ParentDevicePath - A pointer to the parent device path. + + Returns: + +--*/ +{ + EFI_STATUS Status; + BOOLEAN FoundOne; + BOOLEAN Match; + UINTN VariableSize; + UINTN InstanceSize; + UINT8 TerminalType; + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *Variable; + EFI_DEVICE_PATH_PROTOCOL *OriginalVariable; + EFI_DEVICE_PATH_PROTOCOL *NewVariable; + EFI_DEVICE_PATH_PROTOCOL *SavedNewVariable; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + + Variable = NULL; + Instance = NULL; + + // + // Get global variable and its size according to the name given. + // + Variable = TerminalGetVariableAndSize ( + VariableName, + &gEfiGlobalVariableGuid, + &VariableSize + ); + if (Variable == NULL) { + return ; + } + + FoundOne = FALSE; + OriginalVariable = Variable; + NewVariable = NULL; + + // + // Get first device path instance from Variable + // + Instance = GetNextDevicePathInstance (&Variable, &InstanceSize); + if (Instance == NULL) { + gBS->FreePool (OriginalVariable); + return ; + } + // + // Loop through all the device path instances of Variable + // + do { + // + // Loop through all the terminal types that this driver supports + // + Match = FALSE; + for (TerminalType = PcAnsiType; TerminalType <= VTUTF8Type; TerminalType++) { + + SetTerminalDevicePath (TerminalType, ParentDevicePath, &TempDevicePath); + + // + // Compare the genterated device path to the current device path instance + // + if (TempDevicePath != NULL) { + if (CompareMem (Instance, TempDevicePath, InstanceSize) == 0) { + Match = TRUE; + FoundOne = TRUE; + } + + gBS->FreePool (TempDevicePath); + } + } + // + // If a match was not found, then keep the current device path instance + // + if (!Match) { + SavedNewVariable = NewVariable; + NewVariable = AppendDevicePathInstance (NewVariable, Instance); + if (SavedNewVariable != NULL) { + gBS->FreePool (SavedNewVariable); + } + } + // + // Get next device path instance from Variable + // + gBS->FreePool (Instance); + Instance = GetNextDevicePathInstance (&Variable, &InstanceSize); + } while (Instance != NULL); + + gBS->FreePool (OriginalVariable); + + if (FoundOne) { + VariableSize = GetDevicePathSize (NewVariable); + + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VariableSize, + NewVariable + ); + } + + if (NewVariable != NULL) { + gBS->FreePool (NewVariable); + } + + return ; +} + +VOID * +TerminalGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ) +/*++ + +Routine Description: + Read the EFI variable (VendorGuid/Name) and return a dynamically allocated + buffer, and the size of the buffer. On failure return NULL. + +Arguments: + Name - String part of EFI variable name + + VendorGuid - GUID part of EFI variable name + + VariableSize - Returns the size of the EFI variable that was read + +Returns: + Dynamically allocated memory that contains a copy of the EFI variable. + Caller is repsoncible freeing the buffer. + + NULL - Variable was not read + +--*/ +{ + EFI_STATUS Status; + UINTN BufferSize; + VOID *Buffer; + + Buffer = NULL; + + // + // Pass in a small size buffer to find the actual variable size. + // + BufferSize = 1; + Buffer = AllocatePool (BufferSize); + if (Buffer == NULL) { + *VariableSize = 0; + return NULL; + } + + Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); + + if (Status == EFI_SUCCESS) { + *VariableSize = BufferSize; + return Buffer; + + } else if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Allocate the buffer to return + // + gBS->FreePool (Buffer); + Buffer = AllocatePool (BufferSize); + if (Buffer == NULL) { + *VariableSize = 0; + return NULL; + } + // + // Read variable into the allocated buffer. + // + Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); + if (EFI_ERROR (Status)) { + BufferSize = 0; + gBS->FreePool (Buffer); + Buffer = NULL; + } + } else { + // + // Variable not found or other errors met. + // + BufferSize = 0; + gBS->FreePool (Buffer); + Buffer = NULL; + } + + *VariableSize = BufferSize; + return Buffer; +} + +EFI_STATUS +SetTerminalDevicePath ( + IN UINT8 TerminalType, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath + ) +{ + VENDOR_DEVICE_PATH Node; + + *TerminalDevicePath = NULL; + Node.Header.Type = MESSAGING_DEVICE_PATH; + Node.Header.SubType = MSG_VENDOR_DP; + + // + // generate terminal device path node according to terminal type. + // + switch (TerminalType) { + + case PcAnsiType: + CopyMem ( + &Node.Guid, + &gEfiPcAnsiGuid, + sizeof (EFI_GUID) + ); + break; + + case VT100Type: + CopyMem ( + &Node.Guid, + &gEfiVT100Guid, + sizeof (EFI_GUID) + ); + break; + + case VT100PlusType: + CopyMem ( + &Node.Guid, + &gEfiVT100PlusGuid, + sizeof (EFI_GUID) + ); + break; + + case VTUTF8Type: + CopyMem ( + &Node.Guid, + &gEfiVTUTF8Guid, + sizeof (EFI_GUID) + ); + break; + + default: + return EFI_UNSUPPORTED; + break; + } + + SetDevicePathNodeLength ( + &Node.Header, + sizeof (VENDOR_DEVICE_PATH) + ); + // + // append the terminal node onto parent device path + // to generate a complete terminal device path. + // + *TerminalDevicePath = AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Node + ); + if (*TerminalDevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + return EFI_SUCCESS; +} + +VOID +InitializeRawFiFo ( + IN TERMINAL_DEV *TerminalDevice + ) +{ + // + // Make the raw fifo empty. + // + TerminalDevice->RawFiFo.Head = TerminalDevice->RawFiFo.Tail; +} + +VOID +InitializeUnicodeFiFo ( + IN TERMINAL_DEV *TerminalDevice + ) +{ + // + // Make the unicode fifo empty + // + TerminalDevice->UnicodeFiFo.Head = TerminalDevice->UnicodeFiFo.Tail; +} + +VOID +InitializeEfiKeyFiFo ( + IN TERMINAL_DEV *TerminalDevice + ) +{ + // + // Make the efi key fifo empty + // + TerminalDevice->EfiKeyFiFo.Head = TerminalDevice->EfiKeyFiFo.Tail; +} diff --git a/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.h b/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.h new file mode 100644 index 0000000000..2382d86f7e --- /dev/null +++ b/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.h @@ -0,0 +1,506 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + terminal.h + +Abstract: + + +Revision History + +--*/ + +#ifndef _TERMINAL_H +#define _TERMINAL_H + +#define RAW_FIFO_MAX_NUMBER 256 +#define FIFO_MAX_NUMBER 128 + +typedef struct { + UINT8 Head; + UINT8 Tail; + UINT8 Data[RAW_FIFO_MAX_NUMBER + 1]; +} RAW_DATA_FIFO; + +typedef struct { + UINT8 Head; + UINT8 Tail; + UINT16 Data[FIFO_MAX_NUMBER + 1]; +} UNICODE_FIFO; + +typedef struct { + UINT8 Head; + UINT8 Tail; + EFI_INPUT_KEY Data[FIFO_MAX_NUMBER + 1]; +} EFI_KEY_FIFO; + +#define TERMINAL_DEV_SIGNATURE EFI_SIGNATURE_32 ('t', 'm', 'n', 'l') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + UINT8 TerminalType; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + VENDOR_DEVICE_PATH Node; + EFI_SIMPLE_TEXT_IN_PROTOCOL SimpleInput; + EFI_SIMPLE_TEXT_OUT_PROTOCOL SimpleTextOutput; + EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutputMode; + UINTN SerialInTimeOut; + RAW_DATA_FIFO RawFiFo; + UNICODE_FIFO UnicodeFiFo; + EFI_KEY_FIFO EfiKeyFiFo; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + EFI_EVENT TwoSecondTimeOut; + UINT32 InputState; + UINT32 ResetState; + + // + // Esc could not be output to the screen by user, + // but the terminal driver need to output it to + // the terminal emulation software to send control sequence. + // This boolean is used by the terminal driver only + // to indicate whether the Esc could be sent or not. + // + BOOLEAN OutputEscChar; +} TERMINAL_DEV; + +#define INPUT_STATE_DEFAULT 0x00 +#define INPUT_STATE_ESC 0x01 +#define INPUT_STATE_CSI 0x02 +#define INPUT_STATE_LEFTOPENBRACKET 0x04 +#define INPUT_STATE_O 0x08 +#define INPUT_STATE_2 0x10 + +#define RESET_STATE_DEFAULT 0x00 +#define RESET_STATE_ESC_R 0x01 +#define RESET_STATE_ESC_R_ESC_r 0x02 + +#define TERMINAL_CON_IN_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleInput, TERMINAL_DEV_SIGNATURE) +#define TERMINAL_CON_OUT_DEV_FROM_THIS(a) CR (a, TERMINAL_DEV, SimpleTextOutput, TERMINAL_DEV_SIGNATURE) + +typedef union { + UINT8 Utf8_1; + UINT8 Utf8_2[2]; + UINT8 Utf8_3[3]; +} UTF8_CHAR; + +#define PcAnsiType 0 +#define VT100Type 1 +#define VT100PlusType 2 +#define VTUTF8Type 3 + +#define LEFTOPENBRACKET 0x5b // '[' +#define ACAP 0x41 +#define BCAP 0x42 +#define CCAP 0x43 +#define DCAP 0x44 + +#define MODE0_COLUMN_COUNT 80 +#define MODE0_ROW_COUNT 25 + +#define BACKSPACE 8 +#define ESC 27 +#define CSI 0x9B +#define DEL 127 +#define BRIGHT_CONTROL_OFFSET 2 +#define FOREGROUND_CONTROL_OFFSET 6 +#define BACKGROUND_CONTROL_OFFSET 11 +#define ROW_OFFSET 2 +#define COLUMN_OFFSET 5 + +typedef struct { + UINT16 Unicode; + CHAR8 PcAnsi; + CHAR8 Ascii; +} UNICODE_TO_CHAR; + +#define VarConsoleInpDev L"ConInDev" +#define VarConsoleOutDev L"ConOutDev" +#define VarErrorOutDev L"ErrOutDev" + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gTerminalDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gTerminalComponentName; + +// +// Prototypes +// +EFI_STATUS +EFIAPI +InitializeTerminal ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +EFI_STATUS +EFIAPI +TerminalConInReset ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +EFI_STATUS +EFIAPI +TerminalConInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +; + +VOID +EFIAPI +TerminalConInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutReset ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutTestString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +; + +EFI_STATUS +EFIAPI +TerminalConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +; + +// +// internal functions +// +EFI_STATUS +TerminalConInCheckForKey ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This + ) +; + +VOID +TerminalUpdateConsoleDevVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath + ) +; + +VOID +TerminalRemoveConsoleDevVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath + ) +; + +VOID * +TerminalGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ) +; + +EFI_STATUS +SetTerminalDevicePath ( + IN UINT8 TerminalType, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + OUT EFI_DEVICE_PATH_PROTOCOL **TerminalDevicePath + ) +; + +VOID +InitializeRawFiFo ( + IN TERMINAL_DEV *TerminalDevice + ) +; + +VOID +InitializeUnicodeFiFo ( + IN TERMINAL_DEV *TerminalDevice + ) +; + +VOID +InitializeEfiKeyFiFo ( + IN TERMINAL_DEV *TerminalDevice + ) +; + +EFI_STATUS +GetOneKeyFromSerial ( + EFI_SERIAL_IO_PROTOCOL *SerialIo, + UINT8 *Input + ) +; + +BOOLEAN +RawFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT8 Input + ) +; + +BOOLEAN +RawFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT8 *Output + ) +; + +BOOLEAN +IsRawFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +; + +BOOLEAN +IsRawFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +; + +BOOLEAN +EfiKeyFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + EFI_INPUT_KEY Key + ) +; + +BOOLEAN +EfiKeyFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + EFI_INPUT_KEY *Output + ) +; + +BOOLEAN +IsEfiKeyFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +; + +BOOLEAN +IsEfiKeyFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +; + +BOOLEAN +UnicodeFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT16 Input + ) +; + +BOOLEAN +UnicodeFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT16 *Output + ) +; + +BOOLEAN +IsUnicodeFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +; + +BOOLEAN +IsUnicodeFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +; + +UINT8 +UnicodeFiFoGetKeyCount ( + TERMINAL_DEV *TerminalDevice + ) +; + +VOID +TranslateRawDataToEfiKey ( + IN TERMINAL_DEV *TerminalDevice + ) +; + +// +// internal functions for PC ANSI +// +VOID +AnsiRawDataToUnicode ( + IN TERMINAL_DEV *PcAnsiDevice + ) +; + +VOID +UnicodeToEfiKey ( + IN TERMINAL_DEV *PcAnsiDevice + ) +; + +EFI_STATUS +AnsiTestString ( + IN TERMINAL_DEV *TerminalDevice, + IN CHAR16 *WString + ) +; + +// +// internal functions for VT100 +// +EFI_STATUS +VT100TestString ( + IN TERMINAL_DEV *VT100Device, + IN CHAR16 *WString + ) +; + +// +// internal functions for VT100Plus +// +EFI_STATUS +VT100PlusTestString ( + IN TERMINAL_DEV *TerminalDevice, + IN CHAR16 *WString + ) +; + +// +// internal functions for VTUTF8 +// +VOID +VTUTF8RawDataToUnicode ( + IN TERMINAL_DEV *VtUtf8Device + ) +; + +EFI_STATUS +VTUTF8TestString ( + IN TERMINAL_DEV *TerminalDevice, + IN CHAR16 *WString + ) +; + +VOID +UnicodeToUtf8 ( + IN CHAR16 Unicode, + OUT UTF8_CHAR *Utf8Char, + OUT UINT8 *ValidBytes + ) +; + +VOID +GetOneValidUtf8Char ( + IN TERMINAL_DEV *Utf8Device, + OUT UTF8_CHAR *Utf8Char, + OUT UINT8 *ValidBytes + ) +; + +VOID +Utf8ToUnicode ( + IN UTF8_CHAR Utf8Char, + IN UINT8 ValidBytes, + OUT CHAR16 *UnicodeChar + ) +; + +// +// functions for boxdraw unicode +// +BOOLEAN +TerminalIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8 *PcAnsi, OPTIONAL + OUT CHAR8 *Ascii OPTIONAL + ) +; + +BOOLEAN +TerminalIsValidAscii ( + IN CHAR16 Ascii + ) +; + +BOOLEAN +TerminalIsValidEfiCntlChar ( + IN CHAR16 CharC + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.mbd b/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.mbd new file mode 100644 index 0000000000..7ec90ab781 --- /dev/null +++ b/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.mbd @@ -0,0 +1,44 @@ + + + + + Terminal + 9E863906-A40F-4875-977F-5B93FF237FC6 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-22 19:05 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + DxeMemoryAllocationLib + UefiDevicePathLib + + diff --git a/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.msa b/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.msa new file mode 100644 index 0000000000..6382a8548c --- /dev/null +++ b/EdkModulePkg/Universal/Console/Terminal/Dxe/Terminal.msa @@ -0,0 +1,108 @@ + + + + + Terminal + DXE_DRIVER + BS_DRIVER + 9E863906-A40F-4875-977F-5B93FF237FC6 + EDK_RELEASE_VERSION 0x00020000 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-22 19:05 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + ReportStatusCodeLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DevicePathLib + + + Terminal.h + Terminal.c + TerminalConIn.c + TerminalConOut.c + ansi.c + vtutf8.c + ComponentName.c + + + MdePkg + EdkModulePkg + + + SimpleTextOut + SimpleTextIn + DevicePath + SerialIo + + + + ConInDev + 0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C + + + ConOutDev + 0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C + + + ErrOutDev + 0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C + + + + + HotPlugDevice + + + GlobalVariable + + + PcAnsi + + + VT100Plus + + + VT100 + + + VTUTF8 + + + + + + + + gTerminalDriverBinding + gTerminalComponentName + + + diff --git a/EdkModulePkg/Universal/Console/Terminal/Dxe/TerminalConIn.c b/EdkModulePkg/Universal/Console/Terminal/Dxe/TerminalConIn.c new file mode 100644 index 0000000000..feaef5f557 --- /dev/null +++ b/EdkModulePkg/Universal/Console/Terminal/Dxe/TerminalConIn.c @@ -0,0 +1,1185 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + TerminalConIn.c + +Abstract: + + +Revision History +--*/ + + +#include +#include "Terminal.h" + + +EFI_STATUS +EFIAPI +TerminalConInReset ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_IN_PROTOCOL.Reset(). + This driver only perform dependent serial device reset regardless of + the value of ExtendeVerification + + Arguments: + + This - Indicates the calling context. + + ExtendedVerification - Skip by this driver. + + Returns: + + EFI_SUCCESS + The reset operation succeeds. + + EFI_DEVICE_ERROR + The dependent serial port reset fails. + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This); + + // + // Report progress code here + // + Status = REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET, + TerminalDevice->DevicePath + ); + + Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo); + + // + // clear all the internal buffer for keys + // + InitializeRawFiFo (TerminalDevice); + InitializeUnicodeFiFo (TerminalDevice); + InitializeEfiKeyFiFo (TerminalDevice); + + if (EFI_ERROR (Status)) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_LOCAL_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + TerminalDevice->DevicePath + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalConInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_IN_PROTOCOL.ReadKeyStroke(). + + Arguments: + + This - Indicates the calling context. + + Key - A pointer to a buffer that is filled in with the keystroke + information for the key that was sent from terminal. + + Returns: + + EFI_SUCCESS + The keystroke information is returned successfully. + + EFI_NOT_READY + There is no keystroke data available. + + EFI_DEVICE_ERROR + The dependent serial device encounters error. + +--*/ +{ + TERMINAL_DEV *TerminalDevice; + EFI_STATUS Status; + + // + // Initialize *Key to nonsense value. + // + Key->ScanCode = SCAN_NULL; + Key->UnicodeChar = 0; + // + // get TERMINAL_DEV from "This" parameter. + // + TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This); + + Status = TerminalConInCheckForKey (This); + if (EFI_ERROR (Status)) { + return EFI_NOT_READY; + } + + EfiKeyFiFoRemoveOneKey (TerminalDevice, Key); + + return EFI_SUCCESS; + +} + +VOID +TranslateRawDataToEfiKey ( + IN TERMINAL_DEV *TerminalDevice + ) +/*++ + Step1: Turn raw data into Unicode (according to different encode). + Step2: Translate Unicode into key information. + (according to different terminal standard). +--*/ +{ + switch (TerminalDevice->TerminalType) { + + case PcAnsiType: + case VT100Type: + case VT100PlusType: + AnsiRawDataToUnicode (TerminalDevice); + UnicodeToEfiKey (TerminalDevice); + break; + + case VTUTF8Type: + // + // Process all the raw data in the RawFIFO, + // put the processed key into UnicodeFIFO. + // + VTUTF8RawDataToUnicode (TerminalDevice); + + // + // Translate all the Unicode data in the UnicodeFIFO to Efi key, + // then put into EfiKeyFIFO. + // + UnicodeToEfiKey (TerminalDevice); + + break; + } +} + +VOID +EFIAPI +TerminalConInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + Routine Description: + + Event notification function for EFI_SIMPLE_TEXT_IN_PROTOCOL.WaitForKey event + Signal the event if there is key available + + Arguments: + + Event - Indicates the event that invoke this function. + + Context - Indicates the calling context. + + Returns: + + N/A + +--*/ +{ + // + // Someone is waiting on the keystroke event, if there's + // a key pending, signal the event + // + // Context is the pointer to EFI_SIMPLE_TEXT_IN_PROTOCOL + // + if (!EFI_ERROR (TerminalConInCheckForKey (Context))) { + + gBS->SignalEvent (Event); + } +} + +EFI_STATUS +TerminalConInCheckForKey ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This + ) +/*++ + Routine Description: + + Check for a pending key in the Efi Key FIFO or Serial device buffer. + + Arguments: + + This - Indicates the calling context. + + Returns: + + EFI_SUCCESS + There is key pending. + + EFI_NOT_READY + There is no key pending. + + EFI_DEVICE_ERROR + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + UINT32 Control; + UINT8 Input; + EFI_SERIAL_IO_MODE *Mode; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + UINTN SerialInTimeOut; + + TerminalDevice = TERMINAL_CON_IN_DEV_FROM_THIS (This); + + SerialIo = TerminalDevice->SerialIo; + if (SerialIo == NULL) { + return EFI_DEVICE_ERROR; + } + // + // if current timeout value for serial device is not identical with + // the value saved in TERMINAL_DEV structure, then recalculate the + // timeout value again and set serial attribute according to this value. + // + Mode = SerialIo->Mode; + if (Mode->Timeout != TerminalDevice->SerialInTimeOut) { + + SerialInTimeOut = 0; + if (Mode->BaudRate != 0) { + SerialInTimeOut = (1 + Mode->DataBits + Mode->StopBits) * 2 * 1000000 / (UINTN) Mode->BaudRate; + } + + Status = SerialIo->SetAttributes ( + SerialIo, + Mode->BaudRate, + Mode->ReceiveFifoDepth, + (UINT32) SerialInTimeOut, + Mode->Parity, + (UINT8) Mode->DataBits, + Mode->StopBits + ); + + if (EFI_ERROR (Status)) { + TerminalDevice->SerialInTimeOut = 0; + } else { + TerminalDevice->SerialInTimeOut = SerialInTimeOut; + } + } + // + // check whether serial buffer is empty + // + Status = SerialIo->GetControl (SerialIo, &Control); + + if (Control & EFI_SERIAL_INPUT_BUFFER_EMPTY) { + // + // Translate all the raw data in RawFIFO into EFI Key, + // according to different terminal type supported. + // + TranslateRawDataToEfiKey (TerminalDevice); + + // + // if there is pre-fetched Efi Key in EfiKeyFIFO buffer, + // return directly. + // + if (!IsEfiKeyFiFoEmpty (TerminalDevice)) { + return EFI_SUCCESS; + } else { + return EFI_NOT_READY; + } + } + // + // Fetch all the keys in the serial buffer, + // and insert the byte stream into RawFIFO. + // + do { + + Status = GetOneKeyFromSerial (TerminalDevice->SerialIo, &Input); + + if (EFI_ERROR (Status)) { + if (Status == EFI_DEVICE_ERROR) { + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_INPUT_ERROR, + TerminalDevice->DevicePath + ); + } + break; + } + + RawFiFoInsertOneKey (TerminalDevice, Input); + } while (TRUE); + + // + // Translate all the raw data in RawFIFO into EFI Key, + // according to different terminal type supported. + // + TranslateRawDataToEfiKey (TerminalDevice); + + if (IsEfiKeyFiFoEmpty (TerminalDevice)) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetOneKeyFromSerial ( + EFI_SERIAL_IO_PROTOCOL *SerialIo, + UINT8 *Input + ) +/*++ + Get one key out of serial buffer. + If serial buffer is empty, return EFI_NOT_READY; + if reading serial buffer encounter error, returns EFI_DEVICE_ERROR; + if reading serial buffer successfully, put the fetched key to + the parameter "Input", and return EFI_SUCCESS. +--*/ +{ + EFI_STATUS Status; + UINTN Size; + + Size = 1; + *Input = 0; + + Status = SerialIo->Read (SerialIo, &Size, Input); + + if (EFI_ERROR (Status)) { + + if (Status == EFI_TIMEOUT) { + return EFI_NOT_READY; + } + + return EFI_DEVICE_ERROR; + + } + + if (*Input == 0) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + +BOOLEAN +RawFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT8 Input + ) +/*++ + Insert one byte raw data into the Raw Data FIFO. + If FIFO is FULL before data insertion, + return FALSE, and the key is lost. +--*/ +{ + UINT8 Tail; + + Tail = TerminalDevice->RawFiFo.Tail; + + if (IsRawFiFoFull (TerminalDevice)) { + // + // Raw FIFO is full + // + return FALSE; + } + + TerminalDevice->RawFiFo.Data[Tail] = Input; + + TerminalDevice->RawFiFo.Tail = (UINT8) ((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +RawFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT8 *Output + ) +/*++ + Remove one byte raw data out of the Raw Data FIFO. + If FIFO buffer is empty before remove operation, + return FALSE. +--*/ +{ + UINT8 Head; + + Head = TerminalDevice->RawFiFo.Head; + + if (IsRawFiFoEmpty (TerminalDevice)) { + // + // FIFO is empty + // + *Output = 0; + return FALSE; + } + + *Output = TerminalDevice->RawFiFo.Data[Head]; + + TerminalDevice->RawFiFo.Head = (UINT8) ((Head + 1) % (RAW_FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +IsRawFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is empty. +--*/ +{ + if (TerminalDevice->RawFiFo.Head == TerminalDevice->RawFiFo.Tail) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsRawFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is full. +--*/ +{ + UINT8 Tail; + UINT8 Head; + + Tail = TerminalDevice->RawFiFo.Tail; + Head = TerminalDevice->RawFiFo.Head; + + if (((Tail + 1) % (RAW_FIFO_MAX_NUMBER + 1)) == Head) { + + return TRUE; + } + + return FALSE; +} + +BOOLEAN +EfiKeyFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + EFI_INPUT_KEY Key + ) +/*++ + Insert one pre-fetched key into the FIFO buffer. + If FIFO buffer is FULL before key insertion, + return FALSE, and the key is lost. +--*/ +{ + UINT8 Tail; + + Tail = TerminalDevice->EfiKeyFiFo.Tail; + + if (IsEfiKeyFiFoFull (TerminalDevice)) { + // + // Efi Key FIFO is full + // + return FALSE; + } + + TerminalDevice->EfiKeyFiFo.Data[Tail] = Key; + + TerminalDevice->EfiKeyFiFo.Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +EfiKeyFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + EFI_INPUT_KEY *Output + ) +/*++ + Remove one pre-fetched key out of the FIFO buffer. + If FIFO buffer is empty before remove operation, + return FALSE. +--*/ +{ + UINT8 Head; + + Head = TerminalDevice->EfiKeyFiFo.Head; + + if (IsEfiKeyFiFoEmpty (TerminalDevice)) { + // + // FIFO is empty + // + Output->ScanCode = SCAN_NULL; + Output->UnicodeChar = 0; + return FALSE; + } + + *Output = TerminalDevice->EfiKeyFiFo.Data[Head]; + + TerminalDevice->EfiKeyFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +IsEfiKeyFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is empty. +--*/ +{ + if (TerminalDevice->EfiKeyFiFo.Head == TerminalDevice->EfiKeyFiFo.Tail) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsEfiKeyFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is full. +--*/ +{ + UINT8 Tail; + UINT8 Head; + + Tail = TerminalDevice->EfiKeyFiFo.Tail; + Head = TerminalDevice->EfiKeyFiFo.Head; + + if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) { + + return TRUE; + } + + return FALSE; +} + +BOOLEAN +UnicodeFiFoInsertOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT16 Input + ) +/*++ + Insert one pre-fetched key into the FIFO buffer. + If FIFO buffer is FULL before key insertion, + return FALSE, and the key is lost. +--*/ +{ + UINT8 Tail; + + Tail = TerminalDevice->UnicodeFiFo.Tail; + + if (IsUnicodeFiFoFull (TerminalDevice)) { + // + // Unicode FIFO is full + // + return FALSE; + } + + TerminalDevice->UnicodeFiFo.Data[Tail] = Input; + + TerminalDevice->UnicodeFiFo.Tail = (UINT8) ((Tail + 1) % (FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +UnicodeFiFoRemoveOneKey ( + TERMINAL_DEV *TerminalDevice, + UINT16 *Output + ) +/*++ + Remove one pre-fetched key out of the FIFO buffer. + If FIFO buffer is empty before remove operation, + return FALSE. +--*/ +{ + UINT8 Head; + + Head = TerminalDevice->UnicodeFiFo.Head; + + if (IsUnicodeFiFoEmpty (TerminalDevice)) { + // + // FIFO is empty + // + Output = NULL; + return FALSE; + } + + *Output = TerminalDevice->UnicodeFiFo.Data[Head]; + + TerminalDevice->UnicodeFiFo.Head = (UINT8) ((Head + 1) % (FIFO_MAX_NUMBER + 1)); + + return TRUE; +} + +BOOLEAN +IsUnicodeFiFoEmpty ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is empty. +--*/ +{ + if (TerminalDevice->UnicodeFiFo.Head == TerminalDevice->UnicodeFiFo.Tail) { + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +IsUnicodeFiFoFull ( + TERMINAL_DEV *TerminalDevice + ) +/*++ + Clarify whether FIFO buffer is full. +--*/ +{ + UINT8 Tail; + UINT8 Head; + + Tail = TerminalDevice->UnicodeFiFo.Tail; + Head = TerminalDevice->UnicodeFiFo.Head; + + if (((Tail + 1) % (FIFO_MAX_NUMBER + 1)) == Head) { + + return TRUE; + } + + return FALSE; +} + +UINT8 +UnicodeFiFoGetKeyCount ( + TERMINAL_DEV *TerminalDevice + ) +{ + UINT8 Tail; + UINT8 Head; + + Tail = TerminalDevice->UnicodeFiFo.Tail; + Head = TerminalDevice->UnicodeFiFo.Head; + + if (Tail >= Head) { + return (UINT8) (Tail - Head); + } else { + return (UINT8) (Tail + FIFO_MAX_NUMBER + 1 - Head); + } +} + +VOID +UnicodeToEfiKeyFlushState ( + IN TERMINAL_DEV *TerminalDevice + ) +{ + EFI_INPUT_KEY Key; + + if (TerminalDevice->InputState & INPUT_STATE_ESC) { + Key.ScanCode = SCAN_ESC; + Key.UnicodeChar = 0; + EfiKeyFiFoInsertOneKey (TerminalDevice, Key); + } + + if (TerminalDevice->InputState & INPUT_STATE_CSI) { + Key.ScanCode = SCAN_NULL; + Key.UnicodeChar = CSI; + EfiKeyFiFoInsertOneKey (TerminalDevice, Key); + } + + if (TerminalDevice->InputState & INPUT_STATE_LEFTOPENBRACKET) { + Key.ScanCode = SCAN_NULL; + Key.UnicodeChar = LEFTOPENBRACKET; + EfiKeyFiFoInsertOneKey (TerminalDevice, Key); + } + + if (TerminalDevice->InputState & INPUT_STATE_O) { + Key.ScanCode = SCAN_NULL; + Key.UnicodeChar = 'O'; + EfiKeyFiFoInsertOneKey (TerminalDevice, Key); + } + + if (TerminalDevice->InputState & INPUT_STATE_2) { + Key.ScanCode = SCAN_NULL; + Key.UnicodeChar = '2'; + EfiKeyFiFoInsertOneKey (TerminalDevice, Key); + } + + gBS->SetTimer ( + TerminalDevice->TwoSecondTimeOut, + TimerCancel, + 0 + ); + + TerminalDevice->InputState = INPUT_STATE_DEFAULT; +} + +VOID +UnicodeToEfiKey ( + IN TERMINAL_DEV *TerminalDevice + ) +/*++ + Routine Description: + + Converts a stream of Unicode characters from a terminal input device into EFI Keys that + can be read through the Simple Input Protocol. The table below shows the keyboard + input mappings that this function supports. If the ESC sequence listed in one of the + columns is presented, then it is translated into the coorespoding EFI Scan Code. If a + matching sequence is not found, then the raw key strokes are converted into EFI Keys. + + 2 seconds are allowed for an ESC sequence to be completed. If the ESC sequence is not + completed in 2 seconds, then the raw key strokes of the partial ESC sequence are + converted into EFI Keys. + + There is one special input sequence that will force the system to reset. + This is ESC R ESC r ESC R. + + Arguments: + + TerminaDevice : The terminal device to use to translate raw input into EFI Keys + + Returns: + + None + +Symbols used in table below +=========================== + ESC = 0x1B + CSI = 0x9B + DEL = 0x7f + ^ = CTRL + ++=========+======+===========+==========+==========+ +| | EFI | EFI 1.10 | | | +| | Scan | | VT100+ | | +| KEY | Code | PC ANSI | VTUTF8 | VT100 | ++=========+======+===========+==========+==========+ +| NULL | 0x00 | | | | +| UP | 0x01 | ESC [ A | ESC [ A | ESC [ A | +| DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B | +| RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C | +| LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D | +| HOME | 0x05 | ESC [ H | ESC h | ESC [ H | +| END | 0x06 | ESC [ F | ESC k | ESC [ K | +| INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ | +| | | ESC [ L | | ESC [ L | +| DELETE | 0x08 | ESC [ X | ESC - | ESC [ P | +| PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V | +| | | | | ESC [ ? | +| PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U | +| | | | | ESC [ / | +| F1 | 0x0B | ESC [ M | ESC 1 | ESC O P | +| F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q | +| F3 | 0x0D | ESC [ O | ESC 3 | ESC O w | +| F4 | 0x0E | ESC [ P | ESC 4 | ESC O x | +| F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t | +| F6 | 0x10 | ESC [ R | ESC 6 | ESC O u | +| F7 | 0x11 | ESC [ S | ESC 7 | ESC O q | +| F8 | 0x12 | ESC [ T | ESC 8 | ESC O r | +| F9 | 0x13 | ESC [ U | ESC 9 | ESC O p | +| F10 | 0x14 | ESC [ V | ESC 0 | ESC O M | +| Escape | 0x17 | ESC | ESC | ESC | ++=========+======+===========+==========+=========+ + +Special Mappings +================ +ESC R ESC r ESC R = Reset System + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS TimerStatus; + UINT16 UnicodeChar; + EFI_INPUT_KEY Key; + BOOLEAN SetDefaultResetState; + + TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut); + + if (!EFI_ERROR (TimerStatus)) { + UnicodeToEfiKeyFlushState (TerminalDevice); + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + } + + while (!IsUnicodeFiFoEmpty(TerminalDevice)) { + + if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) { + // + // Check to see if the 2 second timer has expired + // + TimerStatus = gBS->CheckEvent (TerminalDevice->TwoSecondTimeOut); + if (!EFI_ERROR (TimerStatus)) { + UnicodeToEfiKeyFlushState (TerminalDevice); + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + } + } + + // + // Fetch one Unicode character from the Unicode FIFO + // + UnicodeFiFoRemoveOneKey (TerminalDevice,&UnicodeChar); + + SetDefaultResetState = TRUE; + + switch (TerminalDevice->InputState) { + case INPUT_STATE_DEFAULT: + + break; + + case INPUT_STATE_ESC: + + if (UnicodeChar == LEFTOPENBRACKET) { + TerminalDevice->InputState |= INPUT_STATE_LEFTOPENBRACKET; + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + continue; + } + + if (UnicodeChar == 'O' && TerminalDevice->TerminalType == VT100Type) { + TerminalDevice->InputState |= INPUT_STATE_O; + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + continue; + } + + Key.ScanCode = SCAN_NULL; + + if (TerminalDevice->TerminalType == VT100PlusType || + TerminalDevice->TerminalType == VTUTF8Type) { + switch (UnicodeChar) { + case '1': + Key.ScanCode = SCAN_F1; + break; + case '2': + Key.ScanCode = SCAN_F2; + break; + case '3': + Key.ScanCode = SCAN_F3; + break; + case '4': + Key.ScanCode = SCAN_F4; + break; + case '5': + Key.ScanCode = SCAN_F5; + break; + case '6': + Key.ScanCode = SCAN_F6; + break; + case '7': + Key.ScanCode = SCAN_F7; + break; + case '8': + Key.ScanCode = SCAN_F8; + break; + case '9': + Key.ScanCode = SCAN_F9; + break; + case '0': + Key.ScanCode = SCAN_F10; + break; + case 'h': + Key.ScanCode = SCAN_HOME; + break; + case 'k': + Key.ScanCode = SCAN_END; + break; + case '+': + Key.ScanCode = SCAN_INSERT; + break; + case '-': + Key.ScanCode = SCAN_DELETE; + break; + case '/': + Key.ScanCode = SCAN_PAGE_DOWN; + break; + case '?': + Key.ScanCode = SCAN_PAGE_UP; + break; + default : + break; + } + } + + switch (UnicodeChar) { + case 'R': + if (TerminalDevice->ResetState == RESET_STATE_DEFAULT) { + TerminalDevice->ResetState = RESET_STATE_ESC_R; + SetDefaultResetState = FALSE; + } else if (TerminalDevice->ResetState == RESET_STATE_ESC_R_ESC_r) { + gRT->ResetSystem (EfiResetWarm, EFI_SUCCESS, 0, NULL); + } + Key.ScanCode = SCAN_NULL; + break; + case 'r': + if (TerminalDevice->ResetState == RESET_STATE_ESC_R) { + TerminalDevice->ResetState = RESET_STATE_ESC_R_ESC_r; + SetDefaultResetState = FALSE; + } + Key.ScanCode = SCAN_NULL; + break; + default : + break; + } + + if (SetDefaultResetState) { + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + } + + if (Key.ScanCode != SCAN_NULL) { + Key.UnicodeChar = 0; + EfiKeyFiFoInsertOneKey (TerminalDevice,Key); + TerminalDevice->InputState = INPUT_STATE_DEFAULT; + UnicodeToEfiKeyFlushState (TerminalDevice); + continue; + } + + UnicodeToEfiKeyFlushState (TerminalDevice); + + break; + + case INPUT_STATE_ESC | INPUT_STATE_O: + + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + + Key.ScanCode = SCAN_NULL; + + if (TerminalDevice->TerminalType == VT100Type) { + switch (UnicodeChar) { + case 'P': + Key.ScanCode = SCAN_F1; + break; + case 'Q': + Key.ScanCode = SCAN_F2; + break; + case 'w': + Key.ScanCode = SCAN_F3; + break; + case 'x': + Key.ScanCode = SCAN_F4; + break; + case 't': + Key.ScanCode = SCAN_F5; + break; + case 'u': + Key.ScanCode = SCAN_F6; + break; + case 'q': + Key.ScanCode = SCAN_F7; + break; + case 'r': + Key.ScanCode = SCAN_F8; + break; + case 'p': + Key.ScanCode = SCAN_F9; + break; + case 'M': + Key.ScanCode = SCAN_F10; + break; + default : + break; + } + } + + if (Key.ScanCode != SCAN_NULL) { + Key.UnicodeChar = 0; + EfiKeyFiFoInsertOneKey (TerminalDevice,Key); + TerminalDevice->InputState = INPUT_STATE_DEFAULT; + UnicodeToEfiKeyFlushState (TerminalDevice); + continue; + } + + UnicodeToEfiKeyFlushState (TerminalDevice); + + break; + + case INPUT_STATE_ESC | INPUT_STATE_LEFTOPENBRACKET: + + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + + Key.ScanCode = SCAN_NULL; + + if (TerminalDevice->TerminalType == PcAnsiType || + TerminalDevice->TerminalType == VT100Type || + TerminalDevice->TerminalType == VT100PlusType || + TerminalDevice->TerminalType == VTUTF8Type) { + switch (UnicodeChar) { + case 'A': + Key.ScanCode = SCAN_UP; + break; + case 'B': + Key.ScanCode = SCAN_DOWN; + break; + case 'C': + Key.ScanCode = SCAN_RIGHT; + break; + case 'D': + Key.ScanCode = SCAN_LEFT; + break; + case 'H': + if (TerminalDevice->TerminalType == PcAnsiType || + TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_HOME; + } + break; + case 'F': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_END; + } + break; + case 'K': + if (TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_END; + } + break; + case 'L': + case '@': + if (TerminalDevice->TerminalType == PcAnsiType || + TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_INSERT; + } + break; + case 'X': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_DELETE; + } + break; + case 'P': + if (TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_DELETE; + } else if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F4; + } + break; + case 'I': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_PAGE_UP; + } + break; + case 'V': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F10; + } + case '?': + if (TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_PAGE_UP; + } + break; + case 'G': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_PAGE_DOWN; + } + break; + case 'U': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F9; + } + case '/': + if (TerminalDevice->TerminalType == VT100Type) { + Key.ScanCode = SCAN_PAGE_DOWN; + } + break; + case 'M': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F1; + } + break; + case 'N': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F2; + } + break; + case 'O': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F3; + } + break; + case 'Q': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F5; + } + break; + case 'R': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F6; + } + break; + case 'S': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F7; + } + break; + case 'T': + if (TerminalDevice->TerminalType == PcAnsiType) { + Key.ScanCode = SCAN_F8; + } + break; + default : + break; + } + } + + if (Key.ScanCode != SCAN_NULL) { + Key.UnicodeChar = 0; + EfiKeyFiFoInsertOneKey (TerminalDevice,Key); + TerminalDevice->InputState = INPUT_STATE_DEFAULT; + UnicodeToEfiKeyFlushState (TerminalDevice); + continue; + } + + UnicodeToEfiKeyFlushState (TerminalDevice); + + break; + + + default: + // + // Invalid state. This should never happen. + // + ASSERT (FALSE); + + UnicodeToEfiKeyFlushState (TerminalDevice); + + break; + } + + if (UnicodeChar == ESC) { + TerminalDevice->InputState = INPUT_STATE_ESC; + } + + if (TerminalDevice->InputState != INPUT_STATE_DEFAULT) { + Status = gBS->SetTimer( + TerminalDevice->TwoSecondTimeOut, + TimerRelative, + (UINT64)20000000 + ); + continue; + } + + if (SetDefaultResetState) { + TerminalDevice->ResetState = RESET_STATE_DEFAULT; + } + + if (UnicodeChar == DEL) { + Key.ScanCode = SCAN_DELETE; + Key.UnicodeChar = 0; + } else { + Key.ScanCode = SCAN_NULL; + Key.UnicodeChar = UnicodeChar; + } + + EfiKeyFiFoInsertOneKey (TerminalDevice,Key); + } +} diff --git a/EdkModulePkg/Universal/Console/Terminal/Dxe/TerminalConOut.c b/EdkModulePkg/Universal/Console/Terminal/Dxe/TerminalConOut.c new file mode 100644 index 0000000000..4d98e59707 --- /dev/null +++ b/EdkModulePkg/Universal/Console/Terminal/Dxe/TerminalConOut.c @@ -0,0 +1,997 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + TerminalConOut.c + +Abstract: + + +Revision History +--*/ + + +#include "Terminal.h" +#include + +// +// This list is used to define the valid extend chars. +// It also provides a mapping from Unicode to PCANSI or +// ASCII. The ASCII mapping we just made up. +// +// +STATIC UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = { + { BOXDRAW_HORIZONTAL, 0xc4, L'-' }, + { BOXDRAW_VERTICAL, 0xb3, L'|' }, + { BOXDRAW_DOWN_RIGHT, 0xda, L'/' }, + { BOXDRAW_DOWN_LEFT, 0xbf, L'\\' }, + { BOXDRAW_UP_RIGHT, 0xc0, L'\\' }, + { BOXDRAW_UP_LEFT, 0xd9, L'/' }, + { BOXDRAW_VERTICAL_RIGHT, 0xc3, L'|' }, + { BOXDRAW_VERTICAL_LEFT, 0xb4, L'|' }, + { BOXDRAW_DOWN_HORIZONTAL, 0xc2, L'+' }, + { BOXDRAW_UP_HORIZONTAL, 0xc1, L'+' }, + { BOXDRAW_VERTICAL_HORIZONTAL, 0xc5, L'+' }, + { BOXDRAW_DOUBLE_HORIZONTAL, 0xcd, L'-' }, + { BOXDRAW_DOUBLE_VERTICAL, 0xba, L'|' }, + { BOXDRAW_DOWN_RIGHT_DOUBLE, 0xd5, L'/' }, + { BOXDRAW_DOWN_DOUBLE_RIGHT, 0xd6, L'/' }, + { BOXDRAW_DOUBLE_DOWN_RIGHT, 0xc9, L'/' }, + { BOXDRAW_DOWN_LEFT_DOUBLE, 0xb8, L'\\' }, + { BOXDRAW_DOWN_DOUBLE_LEFT, 0xb7, L'\\' }, + { BOXDRAW_DOUBLE_DOWN_LEFT, 0xbb, L'\\' }, + { BOXDRAW_UP_RIGHT_DOUBLE, 0xd4, L'\\' }, + { BOXDRAW_UP_DOUBLE_RIGHT, 0xd3, L'\\' }, + { BOXDRAW_DOUBLE_UP_RIGHT, 0xc8, L'\\' }, + { BOXDRAW_UP_LEFT_DOUBLE, 0xbe, L'/' }, + { BOXDRAW_UP_DOUBLE_LEFT, 0xbd, L'/' }, + { BOXDRAW_DOUBLE_UP_LEFT, 0xbc, L'/' }, + { BOXDRAW_VERTICAL_RIGHT_DOUBLE, 0xc6, L'|' }, + { BOXDRAW_VERTICAL_DOUBLE_RIGHT, 0xc7, L'|' }, + { BOXDRAW_DOUBLE_VERTICAL_RIGHT, 0xcc, L'|' }, + { BOXDRAW_VERTICAL_LEFT_DOUBLE, 0xb5, L'|' }, + { BOXDRAW_VERTICAL_DOUBLE_LEFT, 0xb6, L'|' }, + { BOXDRAW_DOUBLE_VERTICAL_LEFT, 0xb9, L'|' }, + { BOXDRAW_DOWN_HORIZONTAL_DOUBLE, 0xd1, L'+' }, + { BOXDRAW_DOWN_DOUBLE_HORIZONTAL, 0xd2, L'+' }, + { BOXDRAW_DOUBLE_DOWN_HORIZONTAL, 0xcb, L'+' }, + { BOXDRAW_UP_HORIZONTAL_DOUBLE, 0xcf, L'+' }, + { BOXDRAW_UP_DOUBLE_HORIZONTAL, 0xd0, L'+' }, + { BOXDRAW_DOUBLE_UP_HORIZONTAL, 0xca, L'+' }, + { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, 0xd8, L'+' }, + { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, 0xd7, L'+' }, + { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, 0xce, L'+' }, + + { BLOCKELEMENT_FULL_BLOCK, 0xdb, L'*' }, + { BLOCKELEMENT_LIGHT_SHADE, 0xb0, L'+' }, + + { GEOMETRICSHAPE_UP_TRIANGLE, 0x1e, L'^' }, + { GEOMETRICSHAPE_RIGHT_TRIANGLE, 0x10, L'>' }, + { GEOMETRICSHAPE_DOWN_TRIANGLE, 0x1f, L'v' }, + { GEOMETRICSHAPE_LEFT_TRIANGLE, 0x11, L'<' }, + + { ARROW_LEFT, 0x3c, L'<' }, + { ARROW_UP, 0x18, L'^' }, + { ARROW_RIGHT, 0x3e, L'>' }, + { ARROW_DOWN, 0x19, L'v' }, + + { 0x0000, 0x00, L'\0' } +}; + +CHAR16 mSetModeString[] = { ESC, '[', '=', '3', 'h', 0 }; +CHAR16 mSetAttributeString[] = { ESC, '[', '0', 'm', ESC, '[', '4', '0', 'm', ESC, '[', '4', '0', 'm', 0 }; +CHAR16 mClearScreenString[] = { ESC, '[', '2', 'J', 0 }; +CHAR16 mSetCursorPositionString[] = { ESC, '[', '0', '0', ';', '0', '0', 'H', 0 }; + +// +// Body of the ConOut functions +// +EFI_STATUS +EFIAPI +TerminalConOutReset ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.Reset(). + If ExtendeVerification is TRUE, then perform dependent serial device reset, + and set display mode to mode 0. + If ExtendedVerification is FALSE, only set display mode to mode 0. + + Arguments: + + This - Indicates the calling context. + + ExtendedVerification - Indicates that the driver may perform a more exhaustive + verification operation of the device during reset. + + Returns: + + EFI_SUCCESS + The reset operation succeeds. + + EFI_DEVICE_ERROR + The terminal is not functioning correctly or the serial port reset fails. + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // Perform a more exhaustive reset by resetting the serial port. + // + if (ExtendedVerification) { + // + // Report progress code here + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET, + TerminalDevice->DevicePath + ); + + Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo); + if (EFI_ERROR (Status)) { + // + // Report error code here + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR, + TerminalDevice->DevicePath + ); + + return Status; + } + } + + This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); + + Status = This->SetMode (This, 0); + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.OutputString(). + The Unicode string will be converted to terminal expressible data stream + and send to terminal via serial port. + + + Arguments: + + This - Indicates the calling context. + + WString - The Null-terminated Unicode string to be displayed on + the terminal screen. + + Returns: + + EFI_SUCCESS + The string is output successfully. + + EFI_DEVICE_ERROR + The serial port fails to send the string out. + + EFI_WARN_UNKNOWN_GLYPH + Indicates that some of the characters in the Unicode string could not + be rendered and are skipped. + + EFI_UNSUPPORTED + +--*/ +{ + TERMINAL_DEV *TerminalDevice; + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + UINTN MaxColumn; + UINTN MaxRow; + UINTN Length; + UTF8_CHAR Utf8Char; + CHAR8 GraphicChar; + CHAR8 AsciiChar; + EFI_STATUS Status; + UINT8 ValidBytes; + // + // flag used to indicate whether condition happens which will cause + // return EFI_WARN_UNKNOWN_GLYPH + // + BOOLEAN Warning; + + ValidBytes = 0; + Warning = FALSE; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // get current display mode + // Terminal driver only support mode 0 + // + Mode = This->Mode; + if (Mode->Mode != 0) { + return EFI_UNSUPPORTED; + } + + This->QueryMode ( + This, + Mode->Mode, + &MaxColumn, + &MaxRow + ); + + for (; *WString != CHAR_NULL; WString++) { + + switch (TerminalDevice->TerminalType) { + + case PcAnsiType: + case VT100Type: + case VT100PlusType: + + if (!TerminalIsValidTextGraphics (*WString, &GraphicChar, &AsciiChar)) { + // + // If it's not a graphic character convert Unicode to ASCII. + // + GraphicChar = (CHAR8) *WString; + + if (!(TerminalIsValidAscii (GraphicChar) || TerminalIsValidEfiCntlChar (GraphicChar))) { + // + // when this driver use the OutputString to output control string, + // TerminalDevice->OutputEscChar is set to let the Esc char + // to be output to the terminal emulation software. + // + if ((GraphicChar == 27) && TerminalDevice->OutputEscChar) { + GraphicChar = 27; + } else { + GraphicChar = '?'; + Warning = TRUE; + } + } + + AsciiChar = GraphicChar; + + } + + if (TerminalDevice->TerminalType != PcAnsiType) { + GraphicChar = AsciiChar; + } + + Length = 1; + + Status = TerminalDevice->SerialIo->Write ( + TerminalDevice->SerialIo, + &Length, + &GraphicChar + ); + + if (EFI_ERROR (Status)) { + goto OutputError; + } + + break; + + case VTUTF8Type: + UnicodeToUtf8 (*WString, &Utf8Char, &ValidBytes); + Length = ValidBytes; + Status = TerminalDevice->SerialIo->Write ( + TerminalDevice->SerialIo, + &Length, + (UINT8 *) &Utf8Char + ); + if (EFI_ERROR (Status)) { + goto OutputError; + } + break; + } + // + // Update cursor position. + // + switch (*WString) { + + case CHAR_BACKSPACE: + if (Mode->CursorColumn > 0) { + Mode->CursorColumn--; + } + break; + + case CHAR_LINEFEED: + if (Mode->CursorRow < (INT32) (MaxRow - 1)) { + Mode->CursorRow++; + } + break; + + case CHAR_CARRIAGE_RETURN: + Mode->CursorColumn = 0; + break; + + default: + if (Mode->CursorColumn < (INT32) (MaxColumn - 1)) { + + Mode->CursorColumn++; + + } else { + + Mode->CursorColumn = 0; + if (Mode->CursorRow < (INT32) (MaxRow - 1)) { + Mode->CursorRow++; + } + + } + break; + + }; + + } + + if (Warning) { + return EFI_WARN_UNKNOWN_GLYPH; + } + + return EFI_SUCCESS; + +OutputError: + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_OUTPUT_ERROR, + TerminalDevice->DevicePath + ); + + return EFI_DEVICE_ERROR; +} + +EFI_STATUS +EFIAPI +TerminalConOutTestString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *WString + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.TestString(). + If one of the characters in the *Wstring is + neither valid Unicode drawing characters, + not ASCII code, then this function will return + EFI_UNSUPPORTED. + + + Arguments: + + This - Indicates the calling context. + + WString - The Null-terminated Unicode string to be tested. + + Returns: + + EFI_SUCCESS + The terminal is capable of rendering the output string. + + EFI_UNSUPPORTED + Some of the characters in the Unicode string cannot be rendered. + +--*/ +{ + TERMINAL_DEV *TerminalDevice; + EFI_STATUS Status; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + switch (TerminalDevice->TerminalType) { + + case PcAnsiType: + case VT100Type: + case VT100PlusType: + Status = AnsiTestString (TerminalDevice, WString); + break; + + case VTUTF8Type: + Status = VTUTF8TestString (TerminalDevice, WString); + break; + + default: + Status = EFI_UNSUPPORTED; + break; + } + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.QueryMode(). + It returns information for an available text mode + that the terminal supports. + In this driver, we only support text mode 80x25, which is + defined as mode 0. + + + Arguments: + + *This + Indicates the calling context. + + ModeNumber + The mode number to return information on. + + Columns + The returned columns of the requested mode. + + Rows + The returned rows of the requested mode. + + Returns: + + EFI_SUCCESS + The requested mode information is returned. + + EFI_UNSUPPORTED + The mode number is not valid. + + EFI_DEVICE_ERROR + +--*/ +{ + if (This->Mode->MaxMode > 1) { + return EFI_DEVICE_ERROR; + } + + if (ModeNumber == 0) { + + *Columns = MODE0_COLUMN_COUNT; + *Rows = MODE0_ROW_COUNT; + + return EFI_SUCCESS; + } + + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +TerminalConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUT.SetMode(). + Set the terminal to a specified display mode. + In this driver, we only support mode 0. + + Arguments: + + This + Indicates the calling context. + + ModeNumber + The text mode to set. + + Returns: + + EFI_SUCCESS + The requested text mode is set. + + EFI_DEVICE_ERROR + The requested text mode cannot be set because of serial device error. + + EFI_UNSUPPORTED + The text mode number is not valid. + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + if (ModeNumber != 0) { + return EFI_UNSUPPORTED; + } + + This->Mode->Mode = 0; + + This->ClearScreen (This); + + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mSetModeString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + This->Mode->Mode = 0; + + Status = This->ClearScreen (This); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +TerminalConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.SetAttribute(). + + Arguments: + + This + Indicates the calling context. + + Attribute + The attribute to set. Only bit0..6 are valid, all other bits + are undefined and must be zero. + + Returns: + + EFI_SUCCESS + The requested attribute is set. + + EFI_DEVICE_ERROR + The requested attribute cannot be set due to serial port error. + + EFI_UNSUPPORTED + The attribute requested is not defined by EFI spec. + +--*/ +{ + UINT8 ForegroundControl; + UINT8 BackgroundControl; + UINT8 BrightControl; + INT32 SavedColumn; + INT32 SavedRow; + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + SavedColumn = 0; + SavedRow = 0; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // only the bit0..6 of the Attribute is valid + // + if ((Attribute | 0x7f) != 0x7f) { + return EFI_UNSUPPORTED; + } + // + // convert Attribute value to terminal emulator + // understandable foreground color + // + switch (Attribute & 0x07) { + + case EFI_BLACK: + ForegroundControl = 30; + break; + + case EFI_BLUE: + ForegroundControl = 34; + break; + + case EFI_GREEN: + ForegroundControl = 32; + break; + + case EFI_CYAN: + ForegroundControl = 36; + break; + + case EFI_RED: + ForegroundControl = 31; + break; + + case EFI_MAGENTA: + ForegroundControl = 35; + break; + + case EFI_BROWN: + ForegroundControl = 33; + break; + + default: + + case EFI_LIGHTGRAY: + ForegroundControl = 37; + break; + + } + // + // bit4 of the Attribute indicates bright control + // of terminal emulator. + // + BrightControl = (UINT8) ((Attribute >> 3) & 1); + + // + // convert Attribute value to terminal emulator + // understandable background color. + // + switch ((Attribute >> 4) & 0x07) { + + case EFI_BLACK: + BackgroundControl = 40; + break; + + case EFI_BLUE: + BackgroundControl = 44; + break; + + case EFI_GREEN: + BackgroundControl = 42; + break; + + case EFI_CYAN: + BackgroundControl = 46; + break; + + case EFI_RED: + BackgroundControl = 41; + break; + + case EFI_MAGENTA: + BackgroundControl = 45; + break; + + case EFI_BROWN: + BackgroundControl = 43; + break; + + default: + + case EFI_LIGHTGRAY: + BackgroundControl = 47; + break; + } + // + // terminal emulator's control sequence to set attributes + // + mSetAttributeString[BRIGHT_CONTROL_OFFSET] = (CHAR16) ('0' + BrightControl); + mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 0] = (CHAR16) ('0' + (ForegroundControl / 10)); + mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 1] = (CHAR16) ('0' + (ForegroundControl % 10)); + mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 0] = (CHAR16) ('0' + (BackgroundControl / 10)); + mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 1] = (CHAR16) ('0' + (BackgroundControl % 10)); + + // + // save current column and row + // for future scrolling back use. + // + SavedColumn = This->Mode->CursorColumn; + SavedRow = This->Mode->CursorRow; + + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mSetAttributeString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // scroll back to saved cursor position. + // + This->Mode->CursorColumn = SavedColumn; + This->Mode->CursorRow = SavedRow; + + This->Mode->Attribute = (INT32) Attribute; + + return EFI_SUCCESS; + +} + +EFI_STATUS +EFIAPI +TerminalConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.ClearScreen(). + It clears the ANSI terminal's display to the + currently selected background color. + + + Arguments: + + This + Indicates the calling context. + + Returns: + + EFI_SUCCESS + The operation completed successfully. + + EFI_DEVICE_ERROR + The terminal screen cannot be cleared due to serial port error. + + EFI_UNSUPPORTED + The terminal is not in a valid display mode. + +--*/ +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // control sequence for clear screen request + // + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mClearScreenString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = This->SetCursorPosition (This, 0, 0); + + return Status; +} + +EFI_STATUS +EFIAPI +TerminalConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +/*++ + Routine Description: + + Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.SetCursorPosition(). + + Arguments: + + This + Indicates the calling context. + + Column + The row to set cursor to. + + Row + The column to set cursor to. + + Returns: + + EFI_SUCCESS + The operation completed successfully. + + EFI_DEVICE_ERROR + The request fails due to serial port error. + + EFI_UNSUPPORTED + The terminal is not in a valid text mode, or the cursor position + is invalid for current mode. + +--*/ +{ + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + UINTN MaxColumn; + UINTN MaxRow; + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // get current mode + // + Mode = This->Mode; + + // + // get geometry of current mode + // + Status = This->QueryMode ( + This, + Mode->Mode, + &MaxColumn, + &MaxRow + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + if (Column >= MaxColumn || Row >= MaxRow) { + return EFI_UNSUPPORTED; + } + // + // control sequence to move the cursor + // + mSetCursorPositionString[ROW_OFFSET + 0] = (CHAR16) ('0' + ((Row + 1) / 10)); + mSetCursorPositionString[ROW_OFFSET + 1] = (CHAR16) ('0' + ((Row + 1) % 10)); + mSetCursorPositionString[COLUMN_OFFSET + 0] = (CHAR16) ('0' + ((Column + 1) / 10)); + mSetCursorPositionString[COLUMN_OFFSET + 1] = (CHAR16) ('0' + ((Column + 1) % 10)); + + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mSetCursorPositionString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // update current cursor position + // in the Mode data structure. + // + Mode->CursorColumn = (INT32) Column; + Mode->CursorRow = (INT32) Row; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +TerminalConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +/*++ + Routine Description: + + Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). + In this driver, the cursor cannot be hidden. + + Arguments: + + This + Indicates the calling context. + + Visible + If TRUE, the cursor is set to be visible, + If FALSE, the cursor is set to be invisible. + + Returns: + + EFI_SUCCESS + The request is valid. + + EFI_UNSUPPORTED + The terminal does not support cursor hidden. + +--*/ +{ + if (!Visible) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +BOOLEAN +TerminalIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8 *PcAnsi, OPTIONAL + OUT CHAR8 *Ascii OPTIONAL + ) +/*++ + +Routine Description: + + Detects if a Unicode char is for Box Drawing text graphics. + +Arguments: + + Graphic - Unicode char to test. + + PcAnsi - Optional pointer to return PCANSI equivalent of Graphic. + + Ascii - Optional pointer to return ASCII equivalent of Graphic. + +Returns: + + TRUE if Graphic is a supported Unicode Box Drawing character. + +--*/ +{ + UNICODE_TO_CHAR *Table; + + if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) { + // + // Unicode drawing code charts are all in the 0x25xx range, + // arrows are 0x21xx + // + return FALSE; + } + + for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) { + if (Graphic == Table->Unicode) { + if (PcAnsi != NULL) { + *PcAnsi = Table->PcAnsi; + } + + if (Ascii != NULL) { + *Ascii = Table->Ascii; + } + + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN +TerminalIsValidAscii ( + IN CHAR16 Ascii + ) +{ + // + // valid ascii code lies in the extent of 0x20 ~ 0x7f + // + if ((Ascii >= 0x20) && (Ascii <= 0x7f)) { + return TRUE; + } + + return FALSE; +} + +BOOLEAN +TerminalIsValidEfiCntlChar ( + IN CHAR16 CharC + ) +{ + // + // only support four control characters. + // + if (CharC == CHAR_NULL || + CharC == CHAR_BACKSPACE || + CharC == CHAR_LINEFEED || + CharC == CHAR_CARRIAGE_RETURN || + CharC == CHAR_TAB + ) { + return TRUE; + } + + return FALSE; +} diff --git a/EdkModulePkg/Universal/Console/Terminal/Dxe/ansi.c b/EdkModulePkg/Universal/Console/Terminal/Dxe/ansi.c new file mode 100644 index 0000000000..babc4bbedc --- /dev/null +++ b/EdkModulePkg/Universal/Console/Terminal/Dxe/ansi.c @@ -0,0 +1,68 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ansi.c + +Abstract: + + +Revision History +--*/ + + +#include "Terminal.h" + +VOID +AnsiRawDataToUnicode ( + IN TERMINAL_DEV *TerminalDevice + ) +{ + UINT8 RawData; + + // + // pop the raw data out from the raw fifo, + // and translate it into unicode, then push + // the unicode into unicode fifo, until the raw fifo is empty. + // + while (!IsRawFiFoEmpty (TerminalDevice)) { + + RawFiFoRemoveOneKey (TerminalDevice, &RawData); + + UnicodeFiFoInsertOneKey (TerminalDevice, (UINT16) RawData); + } +} + +EFI_STATUS +AnsiTestString ( + IN TERMINAL_DEV *TerminalDevice, + IN CHAR16 *WString + ) +{ + CHAR8 GraphicChar; + + // + // support three kind of character: + // valid ascii, valid efi control char, valid text graphics. + // + for (; *WString != CHAR_NULL; WString++) { + + if ( !(TerminalIsValidAscii (*WString) || + TerminalIsValidEfiCntlChar (*WString) || + TerminalIsValidTextGraphics (*WString, &GraphicChar, NULL) )) { + + return EFI_UNSUPPORTED; + } + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/Console/Terminal/Dxe/build.xml b/EdkModulePkg/Universal/Console/Terminal/Dxe/build.xml new file mode 100644 index 0000000000..a3c17133de --- /dev/null +++ b/EdkModulePkg/Universal/Console/Terminal/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Console/Terminal/Dxe/vtutf8.c b/EdkModulePkg/Universal/Console/Terminal/Dxe/vtutf8.c new file mode 100644 index 0000000000..062d0d429f --- /dev/null +++ b/EdkModulePkg/Universal/Console/Terminal/Dxe/vtutf8.c @@ -0,0 +1,270 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + vtutf8.c + +Abstract: + + +Revision History +--*/ + + +#include "Terminal.h" + +VOID +VTUTF8RawDataToUnicode ( + IN TERMINAL_DEV *TerminalDevice + ) +{ + UTF8_CHAR Utf8Char; + UINT8 ValidBytes; + UINT16 UnicodeChar; + + ValidBytes = 0; + // + // pop the raw data out from the raw fifo, + // and translate it into unicode, then push + // the unicode into unicode fifo, until the raw fifo is empty. + // + while (!IsRawFiFoEmpty (TerminalDevice)) { + + GetOneValidUtf8Char (TerminalDevice, &Utf8Char, &ValidBytes); + + if (ValidBytes < 1 || ValidBytes > 3) { + continue; + } + + Utf8ToUnicode (Utf8Char, ValidBytes, (CHAR16 *) &UnicodeChar); + + UnicodeFiFoInsertOneKey (TerminalDevice, UnicodeChar); + } +} + +VOID +GetOneValidUtf8Char ( + IN TERMINAL_DEV *Utf8Device, + OUT UTF8_CHAR *Utf8Char, + OUT UINT8 *ValidBytes + ) +{ + UINT8 Temp; + UINT8 Index; + BOOLEAN FetchFlag; + + Temp = 0; + Index = 0; + FetchFlag = TRUE; + + // + // if no valid Utf8 char is found in the RawFiFo, + // then *ValidBytes will be zero. + // + *ValidBytes = 0; + + while (!IsRawFiFoEmpty (Utf8Device)) { + + RawFiFoRemoveOneKey (Utf8Device, &Temp); + + switch (*ValidBytes) { + + case 0: + if ((Temp & 0x80) == 0) { + // + // one-byte utf8 char + // + *ValidBytes = 1; + + Utf8Char->Utf8_1 = Temp; + + FetchFlag = FALSE; + + } else if ((Temp & 0xe0) == 0xc0) { + // + // two-byte utf8 char + // + *ValidBytes = 2; + + Utf8Char->Utf8_2[1] = Temp; + + } else if ((Temp & 0xf0) == 0xe0) { + // + // three-byte utf8 char + // + *ValidBytes = 3; + + Utf8Char->Utf8_3[2] = Temp; + + Index++; + + } else { + // + // reset *ValidBytes to zero, let valid utf8 char search restart + // + *ValidBytes = 0; + } + + break; + + case 2: + if ((Temp & 0xc0) == 0x80) { + + Utf8Char->Utf8_2[0] = Temp; + + FetchFlag = FALSE; + + } else { + + *ValidBytes = 0; + } + break; + + case 3: + if ((Temp & 0xc0) == 0x80) { + + Utf8Char->Utf8_3[2 - Index] = Temp; + Index++; + if (Index == 3) { + FetchFlag = FALSE; + } + } else { + + *ValidBytes = 0; + Index = 0; + } + break; + + default: + break; + } + + if (!FetchFlag) { + break; + } + } + + return ; +} + +VOID +Utf8ToUnicode ( + IN UTF8_CHAR Utf8Char, + IN UINT8 ValidBytes, + OUT CHAR16 *UnicodeChar + ) +{ + UINT8 UnicodeByte0; + UINT8 UnicodeByte1; + UINT8 Byte0; + UINT8 Byte1; + UINT8 Byte2; + + *UnicodeChar = 0; + + // + // translate utf8 code to unicode, in terminal standard, + // up to 3 bytes utf8 code is supported. + // + switch (ValidBytes) { + case 1: + // + // one-byte utf8 code + // + *UnicodeChar = (UINT16) Utf8Char.Utf8_1; + break; + + case 2: + // + // two-byte utf8 code + // + Byte0 = Utf8Char.Utf8_2[0]; + Byte1 = Utf8Char.Utf8_2[1]; + + UnicodeByte0 = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f)); + UnicodeByte1 = (UINT8) ((Byte1 >> 2) & 0x07); + *UnicodeChar = (UINT16) (UnicodeByte0 | (UnicodeByte1 << 8)); + break; + + case 3: + // + // three-byte utf8 code + // + Byte0 = Utf8Char.Utf8_3[0]; + Byte1 = Utf8Char.Utf8_3[1]; + Byte2 = Utf8Char.Utf8_3[2]; + + UnicodeByte0 = (UINT8) ((Byte1 << 6) | (Byte0 & 0x3f)); + UnicodeByte1 = (UINT8) ((Byte2 << 4) | ((Byte1 >> 2) & 0x0f)); + *UnicodeChar = (UINT16) (UnicodeByte0 | (UnicodeByte1 << 8)); + + default: + break; + } + + return ; +} + +VOID +UnicodeToUtf8 ( + IN CHAR16 Unicode, + OUT UTF8_CHAR *Utf8Char, + OUT UINT8 *ValidBytes + ) +{ + UINT8 UnicodeByte0; + UINT8 UnicodeByte1; + // + // translate unicode to utf8 code + // + UnicodeByte0 = (UINT8) Unicode; + UnicodeByte1 = (UINT8) (Unicode >> 8); + + if (Unicode < 0x0080) { + + Utf8Char->Utf8_1 = (UINT8) (UnicodeByte0 & 0x7f); + *ValidBytes = 1; + + } else if (Unicode < 0x0800) { + // + // byte sequence: high -> low + // Utf8_2[0], Utf8_2[1] + // + Utf8Char->Utf8_2[1] = (UINT8) ((UnicodeByte0 & 0x3f) + 0x80); + Utf8Char->Utf8_2[0] = (UINT8) ((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x1f) + 0xc0); + + *ValidBytes = 2; + + } else { + // + // byte sequence: high -> low + // Utf8_3[0], Utf8_3[1], Utf8_3[2] + // + Utf8Char->Utf8_3[2] = (UINT8) ((UnicodeByte0 & 0x3f) + 0x80); + Utf8Char->Utf8_3[1] = (UINT8) ((((UnicodeByte1 << 2) + (UnicodeByte0 >> 6)) & 0x3f) + 0x80); + Utf8Char->Utf8_3[0] = (UINT8) (((UnicodeByte1 >> 4) & 0x0f) + 0xe0); + + *ValidBytes = 3; + } +} + +EFI_STATUS +VTUTF8TestString ( + IN TERMINAL_DEV *TerminalDevice, + IN CHAR16 *WString + ) +{ + // + // to utf8, all kind of characters are supported. + // + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.c b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.c new file mode 100644 index 0000000000..01e7a6ed69 --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.c @@ -0,0 +1,655 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DataHub.c + +Abstract: + + This code produces the Data Hub protocol. It preloads the data hub + with status information copied in from PEI HOBs. + + Only code that implements the Data Hub protocol should go in this file! + + The Term MTC stands for MonoTonicCounter. + + For more information please look at DataHub.doc + + NOTE: For extra security of the log GetNextDataRecord () could return a copy + of the data record. +--*/ + +#include "DataHub.h" + +CONST EFI_GUID gZeroGuid = { 0, 0, 0, { 0, 0, 0, 0, 0, 0, 0, 0 } }; + +// +// Worker functions private to this file +// +STATIC +DATA_HUB_FILTER_DRIVER * +FindFilterDriverByEvent ( + IN LIST_ENTRY *Head, + IN EFI_EVENT Event + ); + +STATIC +EFI_DATA_RECORD_HEADER * +GetNextDataRecord ( + IN LIST_ENTRY *Head, + IN UINT64 ClassFilter, + IN OUT UINT64 *PtrCurrentMTC + ); + +EFI_STATUS +EFIAPI +DataHubLogData ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_GUID *DataRecordGuid, + IN EFI_GUID *ProducerName, + IN UINT64 DataRecordClass, + IN VOID *RawData, + IN UINT32 RawDataSize + ) +/*++ + +Routine Description: + + Log data record into the data logging hub + +Arguments: + + This - Protocol instance structure + + DataRecordGuid - GUID that defines record contents + + ProducerName - GUID that defines the name of the producer of the data + + DataRecordClass - Class that defines generic record type + + RawData - Data Log record as defined by DataRecordGuid + + RawDataSize - Size of Data Log data in bytes + +Returns: + + EFI_SUCCESS - If data was logged + + EFI_OUT_OF_RESOURCES - If data was not logged due to lack of system + resources. +--*/ +{ + EFI_STATUS Status; + DATA_HUB_INSTANCE *Private; + EFI_DATA_ENTRY *LogEntry; + UINT32 TotalSize; + UINT32 RecordSize; + EFI_DATA_RECORD_HEADER *Record; + VOID *Raw; + DATA_HUB_FILTER_DRIVER *FilterEntry; + LIST_ENTRY *Link; + LIST_ENTRY *Head; + + Private = DATA_HUB_INSTANCE_FROM_THIS (This); + + // + // Combine the storage for the internal structs and a copy of the log record. + // Record follows PrivateLogEntry. The consumer will be returned a pointer + // to Record so we don't what it to be the thing that was allocated from + // pool, so the consumer can't free an data record by mistake. + // + RecordSize = sizeof (EFI_DATA_RECORD_HEADER) + RawDataSize; + TotalSize = sizeof (EFI_DATA_ENTRY) + RecordSize; + + // + // The Logging action is the critical section, so it is locked. + // The MTC asignment & update, time, and logging must be an + // atomic operation, so use the lock. + // + Status = EfiAcquireLockOrFail (&Private->DataLock); + if (EFI_ERROR (Status)) { + // + // Reentrancy detected so exit! + // + return Status; + } + + Status = gBS->AllocatePool (EfiBootServicesData, TotalSize, (VOID **) &LogEntry); + if (EFI_ERROR (Status)) { + EfiReleaseLock (&Private->DataLock); + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem (LogEntry, TotalSize); + + Record = (EFI_DATA_RECORD_HEADER *) (LogEntry + 1); + Raw = (VOID *) (Record + 1); + + // + // Build Standard Log Header + // + Record->Version = EFI_DATA_RECORD_HEADER_VERSION; + Record->HeaderSize = sizeof (EFI_DATA_RECORD_HEADER); + Record->RecordSize = RecordSize; + CopyMem (&Record->DataRecordGuid, DataRecordGuid, sizeof (EFI_GUID)); + CopyMem (&Record->ProducerName, ProducerName, sizeof (EFI_GUID)); + Record->DataRecordClass = DataRecordClass; + + Record->LogMonotonicCount = Private->GlobalMonotonicCount++; + + gRT->GetTime (&Record->LogTime, NULL); + + // + // Insert log into the internal linked list. + // + LogEntry->Signature = EFI_DATA_ENTRY_SIGNATURE; + LogEntry->Record = Record; + LogEntry->RecordSize = sizeof (EFI_DATA_ENTRY) + RawDataSize; + InsertTailList (&Private->DataListHead, &LogEntry->Link); + + CopyMem (Raw, RawData, RawDataSize); + + EfiReleaseLock (&Private->DataLock); + + // + // Send Signal to all the filter drivers which are interested + // in the record's class and guid. + // + Head = &Private->FilterDriverListHead; + for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { + FilterEntry = FILTER_ENTRY_FROM_LINK (Link); + if (((FilterEntry->ClassFilter & DataRecordClass) != 0) && + (CompareGuid (&FilterEntry->FilterDataRecordGuid, &gZeroGuid) || + CompareGuid (&FilterEntry->FilterDataRecordGuid, DataRecordGuid))) { + gBS->SignalEvent (FilterEntry->Event); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DataHubGetNextRecord ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN OUT UINT64 *MonotonicCount, + IN EFI_EVENT *FilterDriverEvent, OPTIONAL + OUT EFI_DATA_RECORD_HEADER **Record + ) +/*++ + +Routine Description: + + Get a previously logged data record and the MonotonicCount for the next + availible Record. This allows all records or all records later + than a give MonotonicCount to be returned. If an optional FilterDriverEvent + is passed in with a MonotonicCout of zero return the first record + not yet read by the filter driver. If FilterDriverEvent is NULL and + MonotonicCount is zero return the first data record. + +Arguments: + + This - The EFI_DATA_HUB_PROTOCOL instance. + MonotonicCount - Specifies the Record to return. On input, zero means + return the first record. On output, contains the next + record to availible. Zero indicates no more records. + FilterDriverEvent - If FilterDriverEvent is not passed in a MonotonicCount + of zero, it means to return the first data record. + If FilterDriverEvent is passed in, then a MonotonicCount + of zero means to return the first data not yet read by + FilterDriverEvent. + Record - Returns a dynamically allocated memory buffer with a data + record that matches MonotonicCount. + +Returns: + + EFI_SUCCESS - Data was returned in Record. + EFI_INVALID_PARAMETER - FilterDriverEvent was passed in but does not exist. + EFI_NOT_FOUND - MonotonicCount does not match any data record in the + system. If a MonotonicCount of zero was passed in, then + no data records exist in the system. + EFI_OUT_OF_RESOURCES - Record was not returned due to lack of system resources. + +--*/ +{ + DATA_HUB_INSTANCE *Private; + DATA_HUB_FILTER_DRIVER *FilterDriver; + UINT64 ClassFilter; + UINT64 FilterMonotonicCount; + + Private = DATA_HUB_INSTANCE_FROM_THIS (This); + + FilterDriver = NULL; + FilterMonotonicCount = 0; + ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG | + EFI_DATA_RECORD_CLASS_ERROR | + EFI_DATA_RECORD_CLASS_DATA | + EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + + if (FilterDriverEvent != NULL) { + // + // For events the beginning is the last unread record. This info is + // stored in the instance structure, so we must look up the event + // to get the data. + // + FilterDriver = FindFilterDriverByEvent ( + &Private->FilterDriverListHead, + *FilterDriverEvent + ); + if (FilterDriver == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Use the Class filter the event was created with. + // + ClassFilter = FilterDriver->ClassFilter; + + if (*MonotonicCount == 0) { + // + // Use the MTC from the Filter Driver. + // + FilterMonotonicCount = FilterDriver->GetNextMonotonicCount; + if (FilterMonotonicCount != 0) { + // + // The GetNextMonotonicCount field remembers the last value from the previous time. + // But we already processed this vaule, so we need to find the next one. So if + // It is not the first time get the new record entry. + // + *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, &FilterMonotonicCount); + *MonotonicCount = FilterMonotonicCount; + if (FilterMonotonicCount == 0) { + // + // If there is no new record to get exit now. + // + return EFI_NOT_FOUND; + } + } + } + } + // + // Return the record + // + *Record = GetNextDataRecord (&Private->DataListHead, ClassFilter, MonotonicCount); + if (*Record == NULL) { + return EFI_NOT_FOUND; + } + + if (FilterDriver != NULL) { + // + // If we have a filter driver update the records that have been read. + // If MonotonicCount is zero No more reacords left. + // + if (*MonotonicCount == 0) { + if (FilterMonotonicCount != 0) { + // + // Return the result of our extra GetNextDataRecord. + // + FilterDriver->GetNextMonotonicCount = FilterMonotonicCount; + } + } else { + // + // Point to next undread record + // + FilterDriver->GetNextMonotonicCount = *MonotonicCount; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DataHubRegisterFilterDriver ( + IN EFI_DATA_HUB_PROTOCOL * This, + IN EFI_EVENT FilterEvent, + IN EFI_TPL FilterTpl, + IN UINT64 FilterClass, + IN EFI_GUID * FilterDataRecordGuid OPTIONAL + ) +/*++ + +Routine Description: + + This function registers the data hub filter driver that is represented + by FilterEvent. Only one instance of each FilterEvent can be registered. + After the FilterEvent is registered, it will be signaled so it can sync + with data records that have been recorded prior to the FilterEvent being + registered. + +Arguments: + + This - The EFI_DATA_HUB_PROTOCOL instance. + FilterEvent - The EFI_EVENT to signal whenever data that matches + FilterClass is logged in the system. + FilterTpl - The maximum EFI_TPL at which FilterEvent can be + signaled. It is strongly recommended that you use the + lowest EFI_TPL possible. + FilterClass - FilterEvent will be signaled whenever a bit in + EFI_DATA_RECORD_HEADER.DataRecordClass is also set in + FilterClass. If FilterClass is zero, no class-based + filtering will be performed. + FilterDataRecordGuid - FilterEvent will be signaled whenever FilterDataRecordGuid + matches EFI_DATA_RECORD_HEADER.DataRecordGuid. If + FilterDataRecordGuid is NULL, then no GUID-based filtering + will be performed. +Returns: + + EFI_SUCCESS - The filter driver event was registered. + EFI_ALREADY_STARTED - FilterEvent was previously registered and cannot be + registered again. + EFI_OUT_OF_RESOURCES - The filter driver event was not registered due to lack of + system resources. + +--*/ +{ + DATA_HUB_INSTANCE *Private; + DATA_HUB_FILTER_DRIVER *FilterDriver; + + Private = DATA_HUB_INSTANCE_FROM_THIS (This); + + FilterDriver = (DATA_HUB_FILTER_DRIVER *) AllocateZeroPool (sizeof (DATA_HUB_FILTER_DRIVER)); + if (FilterDriver == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize filter driver info + // + FilterDriver->Signature = EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE; + FilterDriver->Event = FilterEvent; + FilterDriver->Tpl = FilterTpl; + FilterDriver->GetNextMonotonicCount = 0; + if (FilterClass == 0) { + FilterDriver->ClassFilter = EFI_DATA_RECORD_CLASS_DEBUG | + EFI_DATA_RECORD_CLASS_ERROR | + EFI_DATA_RECORD_CLASS_DATA | + EFI_DATA_RECORD_CLASS_PROGRESS_CODE; + } else { + FilterDriver->ClassFilter = FilterClass; + } + + if (FilterDataRecordGuid != NULL) { + CopyMem (&FilterDriver->FilterDataRecordGuid, FilterDataRecordGuid, sizeof (EFI_GUID)); + } + // + // Search for duplicate entries + // + if (FindFilterDriverByEvent (&Private->FilterDriverListHead, FilterEvent) != NULL) { + gBS->FreePool (FilterDriver); + return EFI_ALREADY_STARTED; + } + // + // Make insertion an atomic operation with the lock. + // + EfiAcquireLock (&Private->DataLock); + InsertTailList (&Private->FilterDriverListHead, &FilterDriver->Link); + EfiReleaseLock (&Private->DataLock); + + // + // Signal the Filter driver we just loaded so they will recieve all the + // previous history. If we did not signal here we would have to wait until + // the next data was logged to get the history. In a case where no next + // data was logged we would never get synced up. + // + gBS->SignalEvent (FilterEvent); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DataHubUnregisterFilterDriver ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_EVENT FilterEvent + ) +/*++ + +Routine Description: + + Remove a Filter Driver, so it no longer gets called when data + information is logged. + +Arguments: + + This - Protocol instance structure + + FilterEvent - Event that represents a filter driver that is to be + Unregistered. + +Returns: + + EFI_SUCCESS - If FilterEvent was unregistered + + EFI_NOT_FOUND - If FilterEvent does not exist + +--*/ +{ + DATA_HUB_INSTANCE *Private; + DATA_HUB_FILTER_DRIVER *FilterDriver; + + Private = DATA_HUB_INSTANCE_FROM_THIS (This); + + // + // Search for duplicate entries + // + FilterDriver = FindFilterDriverByEvent ( + &Private->FilterDriverListHead, + FilterEvent + ); + if (FilterDriver == NULL) { + return EFI_NOT_FOUND; + } + // + // Make removal an atomic operation with the lock + // + EfiAcquireLock (&Private->DataLock); + RemoveEntryList (&FilterDriver->Link); + EfiReleaseLock (&Private->DataLock); + + return EFI_SUCCESS; +} +// +// STATIC Worker fucntions follow +// +STATIC +DATA_HUB_FILTER_DRIVER * +FindFilterDriverByEvent ( + IN LIST_ENTRY *Head, + IN EFI_EVENT Event + ) +/*++ + +Routine Description: + Search the Head list for a EFI_DATA_HUB_FILTER_DRIVER member that + represents Event and return it. + +Arguments: + + Head - Head of dual linked list of EFI_DATA_HUB_FILTER_DRIVER + structures. + + Event - Event to be search for in the Head list. + +Returns: + + EFI_DATA_HUB_FILTER_DRIVER - Returned if Event stored in the + Head doubly linked list. + + NULL - If Event is not in the list + +--*/ +{ + DATA_HUB_FILTER_DRIVER *FilterEntry; + LIST_ENTRY *Link; + + for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { + FilterEntry = FILTER_ENTRY_FROM_LINK (Link); + if (FilterEntry->Event == Event) { + return FilterEntry; + } + } + + return NULL; +} + +STATIC +EFI_DATA_RECORD_HEADER * +GetNextDataRecord ( + IN LIST_ENTRY *Head, + IN UINT64 ClassFilter, + IN OUT UINT64 *PtrCurrentMTC + ) +/*++ + +Routine Description: + Search the Head doubly linked list for the passed in MTC. Return the + matching element in Head and the MTC on the next entry. + +Arguments: + + Head - Head of Data Log linked list. + + ClassFilter - Only match the MTC if it is in the same Class as the + ClassFilter. + + PtrCurrentMTC - On IN contians MTC to search for. On OUT contians next + MTC in the data log list or zero if at end of the list. + +Returns: + + EFI_DATA_LOG_ENTRY - Return pointer to data log data from Head list. + + NULL - If no data record exists. + +--*/ +{ + EFI_DATA_ENTRY *LogEntry; + LIST_ENTRY *Link; + BOOLEAN ReturnFirstEntry; + EFI_DATA_RECORD_HEADER *Record; + EFI_DATA_ENTRY *NextLogEntry; + + // + // If MonotonicCount == 0 just return the first one + // + ReturnFirstEntry = (BOOLEAN) (*PtrCurrentMTC == 0); + + Record = NULL; + for (Link = Head->ForwardLink; Link != Head; Link = Link->ForwardLink) { + LogEntry = DATA_ENTRY_FROM_LINK (Link); + if ((LogEntry->Record->DataRecordClass & ClassFilter) == 0) { + // + // Skip any entry that does not have the correct ClassFilter + // + continue; + } + + if ((LogEntry->Record->LogMonotonicCount == *PtrCurrentMTC) || ReturnFirstEntry) { + // + // Return record to the user + // + Record = LogEntry->Record; + + // + // Calculate the next MTC value. If there is no next entry set + // MTC to zero. + // + *PtrCurrentMTC = 0; + for (Link = Link->ForwardLink; Link != Head; Link = Link->ForwardLink) { + NextLogEntry = DATA_ENTRY_FROM_LINK (Link); + if ((NextLogEntry->Record->DataRecordClass & ClassFilter) != 0) { + // + // Return the MTC of the next thing to search for if found + // + *PtrCurrentMTC = NextLogEntry->Record->LogMonotonicCount; + break; + } + } + // + // Record found exit loop and return + // + break; + } + } + + return Record; +} +// +// Module Global: +// Since this driver will only ever produce one instance of the Logging Hub +// protocol you are not required to dynamically allocate the PrivateData. +// +DATA_HUB_INSTANCE mPrivateData; + +EFI_STATUS +EFIAPI +DataHubInstall ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Install Driver to produce Data Hub protocol. + +Arguments: + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + EFI_SUCCESS - Logging Hub protocol installed + + Other - No protocol installed, unload driver. + +--*/ +{ + EFI_STATUS Status; + UINT32 HighMontonicCount; + + mPrivateData.Signature = DATA_HUB_INSTANCE_SIGNATURE; + mPrivateData.DataHub.LogData = DataHubLogData; + mPrivateData.DataHub.GetNextRecord = DataHubGetNextRecord; + mPrivateData.DataHub.RegisterFilterDriver = DataHubRegisterFilterDriver; + mPrivateData.DataHub.UnregisterFilterDriver = DataHubUnregisterFilterDriver; + + // + // Initialize Private Data in CORE_LOGGING_HUB_INSTANCE that is + // required by this protocol + // + InitializeListHead (&mPrivateData.DataListHead); + InitializeListHead (&mPrivateData.FilterDriverListHead); + + EfiInitializeLock (&mPrivateData.DataLock, EFI_TPL_NOTIFY); + + // + // Make sure we get a bigger MTC number on every boot! + // + Status = gRT->GetNextHighMonotonicCount (&HighMontonicCount); + if (EFI_ERROR (Status)) { + // + // if system service fails pick a sane value. + // + mPrivateData.GlobalMonotonicCount = 0; + } else { + mPrivateData.GlobalMonotonicCount = LShiftU64 ((UINT64) HighMontonicCount, 32); + } + // + // Make a new handle and install the protocol + // + mPrivateData.Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &mPrivateData.Handle, + &gEfiDataHubProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPrivateData.DataHub + ); + return Status; +} diff --git a/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.dxs b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.dxs new file mode 100644 index 0000000000..3483185b35 --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.dxs @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DataHub.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.h b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.h new file mode 100644 index 0000000000..fb364a3b38 --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.h @@ -0,0 +1,122 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DataHub.h + +Abstract: + This code supports a the private implementation + of the Data Hub protocol + +--*/ + +#ifndef _DATA_HUB_H_ +#define _DATA_HUB_H_ + + +#define DATA_HUB_INSTANCE_SIGNATURE EFI_SIGNATURE_32 ('D', 'H', 'u', 'b') +typedef struct { + UINT32 Signature; + + EFI_HANDLE Handle; + + // + // Produced protocol(s) + // + EFI_DATA_HUB_PROTOCOL DataHub; + + // + // Private Data + // + // + // Updates to GlobalMonotonicCount, LogListHead, and FilterDriverListHead + // must be locked. + // + EFI_LOCK DataLock; + + // + // Runing Monotonic Count to use for each error record. + // Increment AFTER use in an error record. + // + UINT64 GlobalMonotonicCount; + + // + // List of EFI_DATA_ENTRY structures. This is the data log! The list + // must be in assending order of LogMonotonicCount. + // + LIST_ENTRY DataListHead; + + // + // List of EFI_DATA_HUB_FILTER_DRIVER structures. Represents all + // the registered filter drivers. + // + LIST_ENTRY FilterDriverListHead; + +} DATA_HUB_INSTANCE; + +#define DATA_HUB_INSTANCE_FROM_THIS(this) CR (this, DATA_HUB_INSTANCE, DataHub, DATA_HUB_INSTANCE_SIGNATURE) + +// +// Private data structure to contain the data log. One record per +// structure. Head pointer to the list is the Log member of +// EFI_DATA_ENTRY. Record is a copy of the data passed in. +// +#define EFI_DATA_ENTRY_SIGNATURE EFI_SIGNATURE_32 ('D', 'r', 'e', 'c') +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + + EFI_DATA_RECORD_HEADER *Record; + + UINTN RecordSize; + +} EFI_DATA_ENTRY; + +#define DATA_ENTRY_FROM_LINK(link) CR (link, EFI_DATA_ENTRY, Link, EFI_DATA_ENTRY_SIGNATURE) + +// +// Private data to contain the filter driver Event and it's +// associated EFI_TPL. +// +#define EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('D', 'h', 'F', 'd') + +typedef struct { + UINT32 Signature; + LIST_ENTRY Link; + + // + // Store Filter Driver Event and Tpl level it can be Signaled at. + // + EFI_EVENT Event; + EFI_TPL Tpl; + + // + // Monotonic count on the get next operation for Event. + // Zero indicates get next has not been called for this event yet. + // + UINT64 GetNextMonotonicCount; + + // + // Filter driver will register what class filter should be used. + // + UINT64 ClassFilter; + + // + // Filter driver will register what record guid filter should be used. + // + EFI_GUID FilterDataRecordGuid; + +} DATA_HUB_FILTER_DRIVER; + +#define FILTER_ENTRY_FROM_LINK(link) CR (link, DATA_HUB_FILTER_DRIVER, Link, EFI_DATA_HUB_FILTER_DRIVER_SIGNATURE) + +#endif diff --git a/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.mbd b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.mbd new file mode 100644 index 0000000000..39b2c9393b --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.mbd @@ -0,0 +1,44 @@ + + + + + DataHub + 53BCC14F-C24F-434C-B294-8ED2D4CC1860 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.msa b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.msa new file mode 100644 index 0000000000..a9f318e1d7 --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/DataHub.msa @@ -0,0 +1,61 @@ + + + + + DataHub + DXE_DRIVER + BS_DRIVER + 53BCC14F-C24F-434C-B294-8ED2D4CC1860 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverEntryPoint + UefiLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + + + DataHub.c + DataHub.h + DataHub.dxs + + + MdePkg + EdkModulePkg + + + DataHub + + + + DataHubInstall + + + diff --git a/EdkModulePkg/Universal/DataHub/DataHub/Dxe/build.xml b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/build.xml new file mode 100644 index 0000000000..9d59b30b4b --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHub/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.c b/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.c new file mode 100644 index 0000000000..1a392ab703 --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.c @@ -0,0 +1,163 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DataHubStdErr.c + +Abstract: + + Data Hub filter driver that takes DEBUG () info from Data Hub and writes it + to StdErr if it exists. + +--*/ + + + +EFI_DATA_HUB_PROTOCOL *mDataHub = NULL; + +EFI_EVENT mDataHubStdErrEvent; + +STATIC +VOID +EFIAPI +DataHubStdErrEventHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + Event handler registered with the Data Hub to parse EFI_DEBUG_CODE. This + handler reads the Data Hub and sends any DEBUG info to StdErr. + +Arguments: + Event - The event that occured, not used + Context - DataHub Protocol Pointer + +Returns: + None. + +--*/ +{ + EFI_STATUS Status; + EFI_DATA_HUB_PROTOCOL *DataHub; + EFI_DATA_RECORD_HEADER *Record; + DATA_HUB_STATUS_CODE_DATA_RECORD *DataRecord; + UINT64 Mtc; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *Sto; + INT32 OldAttribute; + + DataHub = (EFI_DATA_HUB_PROTOCOL *) Context; + + // + // If StdErr is not yet initialized just return a DEBUG print in the BDS + // after consoles are connect will make sure data gets flushed properly + // when StdErr is availible. + // + if (gST == NULL) { + return ; + } + + if (gST->StdErr == NULL) { + return ; + } + // + // Mtc of zero means return the next record that has not been read by the + // event handler. + // + Mtc = 0; + do { + Status = DataHub->GetNextRecord (DataHub, &Mtc, &mDataHubStdErrEvent, &Record); + if (!EFI_ERROR (Status)) { + if (CompareGuid (&Record->DataRecordGuid, &gEfiStatusCodeGuid)) { + DataRecord = (DATA_HUB_STATUS_CODE_DATA_RECORD *) (((CHAR8 *) Record) + Record->HeaderSize); + + if (DataRecord->Data.HeaderSize > 0) { + if (CompareGuid (&DataRecord->Data.Type, &gEfiStatusCodeDataTypeDebugGuid)) { + // + // If the Data record is from a DEBUG () then send it to Standard Error + // + Sto = gST->StdErr; + OldAttribute = Sto->Mode->Attribute; + Sto->SetAttribute (Sto, EFI_TEXT_ATTR (EFI_MAGENTA, EFI_BLACK)); + Sto->OutputString (Sto, (CHAR16 *) (DataRecord + 1)); + Sto->SetAttribute (Sto, OldAttribute); + } + } + } + } + } while ((Mtc != 0) && !EFI_ERROR (Status)); +} + +EFI_STATUS +EFIAPI +DataHubStdErrInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Register an event handler with the Data Hub to parse EFI_DEBUG_CODE. This + handler reads the Data Hub and sends any DEBUG info to StdErr. + +Arguments: + + ImageHandle - Image handle of this driver. + SystemTable - Pointer to EFI system table. + +Returns: + + EFI_SUCCESS - The event handler was registered. + EFI_OUT_OF_RESOURCES - The event hadler was not registered due to lack of + system resources. + +--*/ +{ + EFI_STATUS Status; + UINT64 DataClass; + + gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, (VOID **) &mDataHub); + // + // Should never fail due to Depex grammer. + // + ASSERT (mDataHub != NULL); + + // + // Create an event and register it with the filter driver + // + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + DataHubStdErrEventHandler, + mDataHub, + &mDataHubStdErrEvent + ); + if (EFI_ERROR (Status)) { + return Status; + } + + DataClass = EFI_DATA_RECORD_CLASS_DEBUG | EFI_DATA_RECORD_CLASS_ERROR; + Status = mDataHub->RegisterFilterDriver ( + mDataHub, + mDataHubStdErrEvent, + EFI_TPL_CALLBACK, + DataClass, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->CloseEvent (mDataHubStdErrEvent); + } + + return Status; +} diff --git a/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.dxs b/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.dxs new file mode 100644 index 0000000000..ac6fb1db4d --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DataHubStdErr.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + + +DEPENDENCY_START + EFI_DATA_HUB_PROTOCOL_GUID +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.mbd b/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.mbd new file mode 100644 index 0000000000..8d03e0cf3b --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.mbd @@ -0,0 +1,41 @@ + + + + + DataHubStdErr + CA515306-00CE-4032-874E-11B755FF6866 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.msa b/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.msa new file mode 100644 index 0000000000..63b0d93cd2 --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/DataHubStdErr.msa @@ -0,0 +1,64 @@ + + + + + DataHubStdErr + DXE_DRIVER + BS_DRIVER + CA515306-00CE-4032-874E-11B755FF6866 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverEntryPoint + BaseMemoryLib + UefiBootServicesTableLib + + + DataHubStdErr.c + DataHubStdErr.dxs + + + MdePkg + EdkModulePkg + + + DataHub + + + + StatusCode + + + StatusCodeDataTypeDebug + + + + + DataHubStdErrInitialize + + + diff --git a/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/build.xml b/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/build.xml new file mode 100644 index 0000000000..22bea3fd3b --- /dev/null +++ b/EdkModulePkg/Universal/DataHub/DataHubStdErr/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.c b/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.c new file mode 100644 index 0000000000..118e9b7979 --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.c @@ -0,0 +1,151 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugSupport.c + +Abstract: + + Top level C file for debug support driver. Contains initialization function. + +Revision History + +--*/ + +// +// private header files +// +#include "plDebugSupport.h" + +// +// This is a global that is the actual interface +// +EFI_DEBUG_SUPPORT_PROTOCOL gDebugSupportProtocolInterface = { + EFI_ISA, + GetMaximumProcessorIndex, + RegisterPeriodicCallback, + RegisterExceptionCallback, + InvalidateInstructionCache +}; + +// +// Driver Entry Point +// +EFI_STATUS +InitializeDebugSupportDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Driver entry point. Checks to see there's not already a DebugSupport protocol + installed for the selected processor before installing protocol. + +Arguments: + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + +Returns: + + EFI_STATUS + +--*/ +// TODO: ImageHandle - add argument and description to function comment +// TODO: SystemTable - add argument and description to function comment +{ + EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocolPtr; + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_HANDLE *HandlePtr; + UINTN NumHandles; + EFI_DEBUG_SUPPORT_PROTOCOL *DebugSupportProtocolPtr; + + // + // Install Protocol Interface... + // + // First check to see that the debug support protocol for this processor + // type is not already installed + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDebugSupportProtocolGuid, + NULL, + &NumHandles, + &HandlePtr + ); + + if (Status != EFI_NOT_FOUND) { + do { + NumHandles--; + Status = gBS->OpenProtocol ( + HandlePtr[NumHandles], + &gEfiDebugSupportProtocolGuid, + (VOID **) &DebugSupportProtocolPtr, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (Status == EFI_SUCCESS && DebugSupportProtocolPtr->Isa == EFI_ISA) { + gBS->FreePool (HandlePtr); + Status = EFI_ALREADY_STARTED; + goto ErrExit; + } + } while (NumHandles > 0); + gBS->FreePool (HandlePtr); + } + + // + // Get our image information and install platform specific unload handler + // + Status = gBS->OpenProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &LoadedImageProtocolPtr, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + ASSERT (!EFI_ERROR (Status)); + if (Status != EFI_SUCCESS) { + goto ErrExit; + } + + LoadedImageProtocolPtr->Unload = plUnloadDebugSupportDriver; + + // + // Call hook for platform specific initialization + // + Status = plInitializeDebugSupportDriver (); + ASSERT (!EFI_ERROR (Status)); + if (Status != EFI_SUCCESS) { + goto ErrExit; + } + + // + // Install DebugSupport protocol to new handle + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiDebugSupportProtocolGuid, + EFI_NATIVE_INTERFACE, + &gDebugSupportProtocolInterface + ); + ASSERT (!EFI_ERROR (Status)); + if (Status != EFI_SUCCESS) { + goto ErrExit; + } + +ErrExit: + return Status; +} diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.dxs b/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.dxs new file mode 100644 index 0000000000..34f680a787 --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.dxs @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugSupport.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.mbd b/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.mbd new file mode 100644 index 0000000000..a38bf30903 --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.mbd @@ -0,0 +1,42 @@ + + + + + DebugSupport + 911D584C-35F7-4955-BEF9-B452769DDC3A + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.msa b/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.msa new file mode 100644 index 0000000000..3cf5e12299 --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/DebugSupport.msa @@ -0,0 +1,68 @@ + + + + + DebugSupport + DXE_DRIVER + BS_DRIVER + 911D584C-35F7-4955-BEF9-B452769DDC3A + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverEntryPoint + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + DebugSupport.c + DebugSupport.dxs + + ia32\AsmFuncs.asm + ia32\plDebugSupport.c + + + ipf\AsmFuncs.s + ipf\common.i + ipf\ds64macros.i + ipf\plDebugSupport.c + + + + MdePkg + EdkModulePkg + + + DebugSupport + LoadedImage + + + + InitializeDebugSupportDriver + + + diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/build.xml b/EdkModulePkg/Universal/DebugSupport/Dxe/build.xml new file mode 100644 index 0000000000..b879fc094a --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/ia32/AsmFuncs.asm b/EdkModulePkg/Universal/DebugSupport/Dxe/ia32/AsmFuncs.asm new file mode 100644 index 0000000000..89c9f83176 --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/ia32/AsmFuncs.asm @@ -0,0 +1,547 @@ +;****************************************************************************** +;* +;* Copyright (c) 2006, 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. +;* +;****************************************************************************** + +.586p +.MODEL FLAT, C + +EXCPT32_DIVIDE_ERROR EQU 0 +EXCPT32_DEBUG EQU 1 +EXCPT32_NMI EQU 2 +EXCPT32_BREAKPOINT EQU 3 +EXCPT32_OVERFLOW EQU 4 +EXCPT32_BOUND EQU 5 +EXCPT32_INVALID_OPCODE EQU 6 +EXCPT32_DOUBLE_FAULT EQU 8 +EXCPT32_INVALID_TSS EQU 10 +EXCPT32_SEG_NOT_PRESENT EQU 11 +EXCPT32_STACK_FAULT EQU 12 +EXCPT32_GP_FAULT EQU 13 +EXCPT32_PAGE_FAULT EQU 14 +EXCPT32_FP_ERROR EQU 16 +EXCPT32_ALIGNMENT_CHECK EQU 17 +EXCPT32_MACHINE_CHECK EQU 18 +EXCPT32_SIMD EQU 19 + +FXSTOR_FLAG EQU 01000000h ; bit cpuid 24 of feature flags + +;; The FXSTOR and FXRSTOR commands are used for saving and restoring the x87, +;; MMX, SSE, SSE2, etc registers. The initialization of the debugsupport driver +;; MUST check the CPUID feature flags to see that these instructions are available +;; and fail to init if they are not. + +;; fxstor [edi] +FXSTOR_EDI MACRO + db 0fh, 0aeh, 00000111y ; mod = 00, reg/op = 000, r/m = 111 = [edi] +ENDM + +;; fxrstor [esi] +FXRSTOR_ESI MACRO + db 0fh, 0aeh, 00001110y ; mod = 00, reg/op = 001, r/m = 110 = [esi] +ENDM +.DATA + +public OrigVector, InterruptEntryStub, StubSize, CommonIdtEntry, FxStorSupport + +StubSize dd InterruptEntryStubEnd - InterruptEntryStub +AppEsp dd 11111111h ; ? +DebugEsp dd 22222222h ; ? +ExtraPush dd 33333333h ; ? +ExceptData dd 44444444h ; ? +Eflags dd 55555555h ; ? +OrigVector dd 66666666h ; ? + +;; The declarations below define the memory region that will be used for the debug stack. +;; The context record will be built by pushing register values onto this stack. +;; It is imparitive that alignment be carefully managed, since the FXSTOR and +;; FXRSTOR instructions will GP fault if their memory operand is not 16 byte aligned. +;; +;; The stub will switch stacks from the application stack to the debuger stack +;; and pushes the exception number. +;; +;; Then we building the context record on the stack. Since the stack grows down, +;; we push the fields of the context record from the back to the front. There +;; are 132 bytes of stack used prior allocating the 512 bytes of stack to be +;; used as the memory buffer for the fxstor instruction. Therefore address of +;; the buffer used for the FXSTOR instruction is &Eax - 132 - 512, which +;; must be 16 byte aligned. +;; +;; We carefully locate the stack to make this happen. +;; +;; For reference, the context structure looks like this: +;; struct { +;; UINT32 ExceptionData; +;; FX_SAVE_STATE FxSaveState; // 512 bytes, must be 16 byte aligned +;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; +;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; +;; UINT32 Ldtr, Tr; +;; UINT64 Gdtr, Idtr; +;; UINT32 EFlags; +;; UINT32 Eip; +;; UINT32 SegGs, SegFs, SegEs, SegDs, SegCs, SegSs; +;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; +;; } SYSTEM_CONTEXT_IA32; // 32 bit system context record + + +align 16 +DebugStackEnd db "DbgStkEnd >>>>>>" ;; 16 byte long string - must be 16 bytes to preserve alignment + dd 1ffdh dup (000000000h) ;; 32K should be enough stack + ;; This allocation is coocked to insure + ;; that the the buffer for the FXSTORE instruction + ;; will be 16 byte aligned also. + ;; +ExceptionNumber dd ? ;; first entry will be the vector number pushed by the stub + +DebugStackBegin db "<<<< DbgStkBegin" ;; initial debug ESP == DebugStackBegin, set in stub + +.CODE + +externdef InterruptDistrubutionHub:near + +;------------------------------------------------------------------------------ +; BOOLEAN +; FxStorSupport ( +; void +; ) +; +; Abstract: Returns TRUE if FxStor instructions are supported +; +FxStorSupport PROC C PUBLIC + +; +; cpuid corrupts ebx which must be preserved per the C calling convention +; + push ebx + mov eax, 1 + cpuid + mov eax, edx + and eax, FXSTOR_FLAG + shr eax, 24 + pop ebx + ret +FxStorSupport ENDP + + +;------------------------------------------------------------------------------ +; DESCRIPTOR * +; GetIdtr ( +; void +; ) +; +; Abstract: Returns physical address of IDTR +; +GetIdtr PROC C PUBLIC + LOCAL IdtrBuf:FWORD + + sidt IdtrBuf + mov eax, DWORD PTR IdtrBuf + 2 + ret +GetIdtr ENDP + + +;------------------------------------------------------------------------------ +; BOOLEAN +; WriteInterruptFlag ( +; BOOLEAN NewState +; ) +; +; Abstract: Programs interrupt flag to the requested state and returns previous +; state. +; +WriteInterruptFlag PROC C PUBLIC State:DWORD + + pushfd + pop eax + and eax, 200h + shr eax, 9 + mov ecx, State + .IF ecx == 0 + cli + .ELSE + sti + .ENDIF + ret + +WriteInterruptFlag ENDP + + + +;------------------------------------------------------------------------------ +; void +; Vect2Desc ( +; DESCRIPTOR * DestDesc, +; void (*Vector) (void) +; ) +; +; Abstract: Encodes an IDT descriptor with the given physical address +; +Vect2Desc PROC C PUBLIC DestPtr:DWORD, Vector:DWORD + + mov eax, Vector + mov ecx, DestPtr + mov word ptr [ecx], ax ; write bits 15..0 of offset + mov word ptr [ecx+2], 20h ; SYS_CODE_SEL from GDT + mov word ptr [ecx+4], 0e00h OR 8000h ; type = 386 interrupt gate, present + shr eax, 16 + mov word ptr [ecx+6], ax ; write bits 31..16 of offset + + ret + +Vect2Desc ENDP + + + +;------------------------------------------------------------------------------ +; InterruptEntryStub +; +; Abstract: This code is not a function, but is a small piece of code that is +; copied and fixed up once for each IDT entry that is hooked. +; +InterruptEntryStub:: + mov AppEsp, esp ; save stack top + mov esp, offset DebugStackBegin ; switch to debugger stack + push 0 ; push vector number - will be modified before installed + db 0e9h ; jump rel32 + dd 0 ; fixed up to relative address of CommonIdtEntry +InterruptEntryStubEnd: + + + +;------------------------------------------------------------------------------ +; CommonIdtEntry +; +; Abstract: This code is not a function, but is the common part for all IDT +; vectors. +; +CommonIdtEntry:: +;; +;; At this point, the stub has saved the current application stack esp into AppEsp +;; and switched stacks to the debug stack, where it pushed the vector number +;; +;; The application stack looks like this: +;; +;; ... +;; (last application stack entry) +;; eflags from interrupted task +;; CS from interrupted task +;; EIP from interrupted task +;; Error code <-------------------- Only present for some exeption types +;; +;; + + +;; The stub switched us to the debug stack and pushed the interrupt number. +;; +;; Next, construct the context record. It will be build on the debug stack by +;; pushing the registers in the correct order so as to create the context structure +;; on the debug stack. The context record must be built from the end back to the +;; beginning because the stack grows down... +; +;; For reference, the context record looks like this: +;; +;; typedef +;; struct { +;; UINT32 ExceptionData; +;; FX_SAVE_STATE FxSaveState; +;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; +;; UINT32 Cr0, Cr2, Cr3, Cr4; +;; UINT32 Ldtr, Tr; +;; UINT64 Gdtr, Idtr; +;; UINT32 EFlags; +;; UINT32 Eip; +;; UINT32 SegGs, SegFs, SegEs, SegDs, SegCs, SegSs; +;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; +;; } SYSTEM_CONTEXT_IA32; // 32 bit system context record + +;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; + pushad + +;; Save interrupt state eflags register... + pushfd + pop eax + mov dword ptr Eflags, eax + +;; We need to determine if any extra data was pushed by the exception, and if so, save it +;; To do this, we check the exception number pushed by the stub, and cache the +;; result in a variable since we'll need this again. + .IF ExceptionNumber == EXCPT32_DOUBLE_FAULT + mov ExtraPush, 1 + .ELSEIF ExceptionNumber == EXCPT32_INVALID_TSS + mov ExtraPush, 1 + .ELSEIF ExceptionNumber == EXCPT32_SEG_NOT_PRESENT + mov ExtraPush, 1 + .ELSEIF ExceptionNumber == EXCPT32_STACK_FAULT + mov ExtraPush, 1 + .ELSEIF ExceptionNumber == EXCPT32_GP_FAULT + mov ExtraPush, 1 + .ELSEIF ExceptionNumber == EXCPT32_PAGE_FAULT + mov ExtraPush, 1 + .ELSEIF ExceptionNumber == EXCPT32_ALIGNMENT_CHECK + mov ExtraPush, 1 + .ELSE + mov ExtraPush, 0 + .ENDIF + +;; If there's some extra data, save it also, and modify the saved AppEsp to effectively +;; pop this value off the application's stack. + .IF ExtraPush == 1 + mov eax, AppEsp + mov ebx, [eax] + mov ExceptData, ebx + add eax, 4 + mov AppEsp, eax + .ELSE + mov ExceptData, 0 + .ENDIF + +;; The "pushad" above pushed the debug stack esp. Since what we're actually doing +;; is building the context record on the debug stack, we need to save the pushed +;; debug ESP, and replace it with the application's last stack entry... + mov eax, [esp + 12] + mov DebugEsp, eax + mov eax, AppEsp + add eax, 12 + ; application stack has eflags, cs, & eip, so + ; last actual application stack entry is + ; 12 bytes into the application stack. + mov [esp + 12], eax + +;; continue building context record +;; UINT32 Gs, Fs, Es, Ds, Cs, Ss; insure high 16 bits of each is zero + mov eax, ss + push eax + + ; CS from application is one entry back in application stack + mov eax, AppEsp + movzx eax, word ptr [eax + 4] + push eax + + mov eax, ds + push eax + mov eax, es + push eax + mov eax, fs + push eax + mov eax, gs + push eax + +;; UINT32 Eip; + ; Eip from application is on top of application stack + mov eax, AppEsp + push dword ptr [eax] + +;; UINT64 Gdtr, Idtr; + push 0 + push 0 + sidt fword ptr [esp] + push 0 + push 0 + sgdt fword ptr [esp] + +;; UINT32 Ldtr, Tr; + xor eax, eax + str ax + push eax + sldt ax + push eax + +;; UINT32 EFlags; +;; Eflags from application is two entries back in application stack + mov eax, AppEsp + push dword ptr [eax + 8] + +;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; +;; insure FXSAVE/FXRSTOR is enabled in CR4... +;; ... while we're at it, make sure DE is also enabled... + mov eax, cr4 + or eax, 208h + mov cr4, eax + push eax + mov eax, cr3 + push eax + mov eax, cr2 + push eax + push 0 + mov eax, cr0 + push eax + +;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; + mov eax, dr7 + push eax +;; clear Dr7 while executing debugger itself + xor eax, eax + mov dr7, eax + + mov eax, dr6 + push eax +;; insure all status bits in dr6 are clear... + xor eax, eax + mov dr6, eax + + mov eax, dr3 + push eax + mov eax, dr2 + push eax + mov eax, dr1 + push eax + mov eax, dr0 + push eax + +;; FX_SAVE_STATE FxSaveState; + sub esp, 512 + mov edi, esp + ; IMPORTANT!! The debug stack has been carefully constructed to + ; insure that esp and edi are 16 byte aligned when we get here. + ; They MUST be. If they are not, a GP fault will occur. + FXSTOR_EDI + +;; UINT32 ExceptionData; + mov eax, ExceptData + push eax + +; call to C code which will in turn call registered handler +; pass in the vector number + mov eax, esp + push eax + mov eax, ExceptionNumber + push eax + call InterruptDistrubutionHub + add esp, 8 + +; restore context... +;; UINT32 ExceptionData; + add esp, 4 + +;; FX_SAVE_STATE FxSaveState; + mov esi, esp + FXRSTOR_ESI + add esp, 512 + +;; UINT32 Dr0, Dr1, Dr2, Dr3, Dr6, Dr7; + pop eax + mov dr0, eax + pop eax + mov dr1, eax + pop eax + mov dr2, eax + pop eax + mov dr3, eax +;; skip restore of dr6. We cleared dr6 during the context save. + add esp, 4 + pop eax + mov dr7, eax + +;; UINT32 Cr0, Cr1, Cr2, Cr3, Cr4; + pop eax + mov cr0, eax + add esp, 4 + pop eax + mov cr2, eax + pop eax + mov cr3, eax + pop eax + mov cr4, eax + +;; UINT32 EFlags; + mov eax, AppEsp + pop dword ptr [eax + 8] + +;; UINT16 Ldtr, Tr; +;; UINT64 Gdtr, Idtr; +;; Best not let anyone mess with these particular registers... + add esp, 24 + +;; UINT32 Eip; + pop dword ptr [eax] + +;; UINT32 SegGs, SegFs, SegEs, SegDs, SegCs, SegSs; +;; NOTE - modified segment registers could hang the debugger... We +;; could attempt to insulate ourselves against this possibility, +;; but that poses risks as well. +;; + + pop gs + pop fs + pop es + pop ds + pop [eax + 4] + pop ss + +;; The next stuff to restore is the general purpose registers that were pushed +;; using the pushad instruction. +;; +;; The value of ESP as stored in the context record is the application ESP +;; including the 3 entries on the application stack caused by the exception +;; itself. It may have been modified by the debug agent, so we need to +;; determine if we need to relocate the application stack. + + mov ebx, [esp + 12] ; move the potentially modified AppEsp into ebx + mov eax, AppEsp + add eax, 12 + cmp ebx, eax + je NoAppStackMove + + mov eax, AppEsp + mov ecx, [eax] ; EIP + mov [ebx], ecx + + mov ecx, [eax + 4] ; CS + mov [ebx + 4], ecx + + mov ecx, [eax + 8] ; EFLAGS + mov [ebx + 8], ecx + + mov eax, ebx ; modify the saved AppEsp to the new AppEsp + mov AppEsp, eax +NoAppStackMove: + mov eax, DebugEsp ; restore the DebugEsp on the debug stack + ; so our popad will not cause a stack switch + mov [esp + 12], eax + + cmp ExceptionNumber, 068h + jne NoChain + +Chain: + +;; Restore eflags so when we chain, the flags will be exactly as if we were never here. +;; We gin up the stack to do an iretd so we can get ALL the flags. + mov eax, AppEsp + mov ebx, [eax + 8] + and ebx, NOT 300h ; special handling for IF and TF + push ebx + push cs + push PhonyIretd + iretd +PhonyIretd: + +;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; + popad + +;; Switch back to application stack + mov esp, AppEsp + +;; Jump to original handler + jmp OrigVector + +NoChain: +;; UINT32 Edi, Esi, Ebp, Esp, Ebx, Edx, Ecx, Eax; + popad + +;; Switch back to application stack + mov esp, AppEsp + +;; We're outa here... + iretd +END + + + diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/ia32/plDebugSupport.c b/EdkModulePkg/Universal/DebugSupport/Dxe/ia32/plDebugSupport.c new file mode 100644 index 0000000000..2198192a04 --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/ia32/plDebugSupport.c @@ -0,0 +1,440 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + plDebugSupport.c + +Abstract: + + IA32 specific debug support functions + +Revision History + +--*/ + +// +// private header files +// +#include "plDebugSupport.h" + +// +// This the global main table to keep track of the interrupts +// +IDT_ENTRY *IdtEntryTable = NULL; +DESCRIPTOR NullDesc = 0; + +#ifndef EFI_NT_EMULATOR +STATIC +EFI_STATUS +CreateEntryStub ( + IN EFI_EXCEPTION_TYPE ExceptionType, + OUT VOID **Stub + ) +/*++ + +Routine Description: Allocate pool for a new IDT entry stub. Copy the generic + stub into the new buffer and fixup the vector number and jump target address. + +Arguments: + ExceptionType - This is the exception type that the new stub will be created + for. + Stub - On successful exit, *Stub contains the newly allocated entry stub. +Returns: + Typically EFI_SUCCESS + other possibilities are passed through from AllocatePool + +--*/ +{ + EFI_STATUS Status; + UINT8 *StubCopy; + + // + // First, allocate a new buffer and copy the stub code into it + // + Status = gBS->AllocatePool (EfiBootServicesData, StubSize, Stub); + if (Status == EFI_SUCCESS) { + StubCopy = *Stub; + gBS->CopyMem (StubCopy, InterruptEntryStub, StubSize); + + // + // Next fixup the stub code for this vector + // + + // The stub code looks like this: + // + // 00000000 89 25 00000004 R mov AppEsp, esp ; save stack top + // 00000006 BC 00008014 R mov esp, offset DbgStkBot ; switch to debugger stack + // 0000000B 6A 00 push 0 ; push vector number - will be modified before installed + // 0000000D E9 db 0e9h ; jump rel32 + // 0000000E 00000000 dd 0 ; fixed up to relative address of CommonIdtEntry + // + + // + // poke in the exception type so the second push pushes the exception type + // + StubCopy[0x0c] = (UINT8) ExceptionType; + + // + // fixup the jump target to point to the common entry + // + *(UINT32 *) &StubCopy[0x0e] = (UINT32) CommonIdtEntry - (UINT32) &StubCopy[StubSize]; + } + + return Status; +} + +STATIC +EFI_STATUS +HookEntry ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN VOID (*NewCallback) () + ) +/*++ + +Routine Description: + Creates a nes entry stub. Then saves the current IDT entry and replaces it + with an interrupt gate for the new entry point. The IdtEntryTable is updated + with the new registered function. + + This code executes in boot services context. The stub entry executes in interrupt + context. + +Arguments: + ExceptionType - specifies which vector to hook. + NewCallback - a pointer to the new function to be registered. + +Returns: + EFI_SUCCESS + Other possibilities are passed through by CreateEntryStub + +--*/ +// TODO: ) - add argument and description to function comment +{ + BOOLEAN OldIntFlagState; + EFI_STATUS Status; + + Status = CreateEntryStub (ExceptionType, (VOID **) &IdtEntryTable[ExceptionType].StubEntry); + if (Status == EFI_SUCCESS) { + OldIntFlagState = WriteInterruptFlag (0); + ReadIdt (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc)); + + ((UINT16 *) &IdtEntryTable[ExceptionType].OrigVector)[0] = ((UINT16 *) &IdtEntryTable[ExceptionType].OrigDesc)[0]; + ((UINT16 *) &IdtEntryTable[ExceptionType].OrigVector)[1] = ((UINT16 *) &IdtEntryTable[ExceptionType].OrigDesc)[3]; + + Vect2Desc (&IdtEntryTable[ExceptionType].NewDesc, IdtEntryTable[ExceptionType].StubEntry); + IdtEntryTable[ExceptionType].RegisteredCallback = NewCallback; + WriteIdt (ExceptionType, &(IdtEntryTable[ExceptionType].NewDesc)); + WriteInterruptFlag (OldIntFlagState); + } + + return Status; +} + +STATIC +EFI_STATUS +UnhookEntry ( + IN EFI_EXCEPTION_TYPE ExceptionType + ) +/*++ + +Routine Description: + Undoes HookEntry. This code executes in boot services context. + +Arguments: + ExceptionType - specifies which entry to unhook + +Returns: + EFI_SUCCESS + Other values are passed through from FreePool + +--*/ +{ + BOOLEAN OldIntFlagState; + EFI_STATUS Status; + + OldIntFlagState = WriteInterruptFlag (0); + WriteIdt (ExceptionType, &(IdtEntryTable[ExceptionType].OrigDesc)); + Status = gBS->FreePool ((VOID *) (UINTN) IdtEntryTable[ExceptionType].StubEntry); + ZeroMem (&IdtEntryTable[ExceptionType], sizeof (IDT_ENTRY)); + WriteInterruptFlag (OldIntFlagState); + + return (Status); +} +#endif + +EFI_STATUS +ManageIdtEntryTable ( + VOID (*NewCallback)(), + EFI_EXCEPTION_TYPE ExceptionType + ) +/*++ + +Routine Description: + This is the main worker function that manages the state of the interrupt + handlers. It both installs and uninstalls interrupt handlers based on the + value of NewCallback. If NewCallback is NULL, then uninstall is indicated. + If NewCallback is non-NULL, then install is indicated. + +Arguments: + NewCallback - If non-NULL, NewCallback specifies the new handler to register. + If NULL, specifies that the previously registered handler should + be uninstalled. + ExceptionType - Indicates which entry to manage + +Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER - requested uninstalling a handler from a vector that has + no handler registered for it + EFI_ALREADY_STARTED - requested install to a vector that already has a handler registered. + + Other possible return values are passed through from UnHookEntry and HookEntry. + +--*/ +// TODO: ) - add argument and description to function comment +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + +#ifndef EFI_NT_EMULATOR + if (CompareDescriptor (&IdtEntryTable[ExceptionType].NewDesc, &NullDesc)) { + // + // we've already installed to this vector + // + if (NewCallback != NULL) { + // + // if the input handler is non-null, error + // + Status = EFI_ALREADY_STARTED; + } else { + Status = UnhookEntry (ExceptionType); + } + } else { + // + // no user handler installed on this vector + // + if (NewCallback == NULL) { + // + // if the input handler is null, error + // + Status = EFI_INVALID_PARAMETER; + } else { + Status = HookEntry (ExceptionType, NewCallback); + } + } +#endif + return Status; +} + +EFI_STATUS +EFIAPI +GetMaximumProcessorIndex ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex + ) +/*++ + +Routine Description: This is a DebugSupport protocol member function. + +Arguments: + +Returns: Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0 + +--*/ +// TODO: This - add argument and description to function comment +// TODO: MaxProcessorIndex - add argument and description to function comment +{ + *MaxProcessorIndex = 0; + return (EFI_SUCCESS); +} + +EFI_STATUS +EFIAPI +RegisterPeriodicCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ) +/*++ + +Routine Description: This is a DebugSupport protocol member function. + +Arguments: + +Returns: + +--*/ +// TODO: This - add argument and description to function comment +// TODO: ProcessorIndex - add argument and description to function comment +// TODO: PeriodicCallback - add argument and description to function comment +{ + return ManageIdtEntryTable (PeriodicCallback, SYSTEM_TIMER_VECTOR); +} + +EFI_STATUS +EFIAPI +RegisterExceptionCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK NewCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + ) +/*++ + +Routine Description: + This is a DebugSupport protocol member function. + + This code executes in boot services context. + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: ProcessorIndex - add argument and description to function comment +// TODO: NewCallback - add argument and description to function comment +// TODO: ExceptionType - add argument and description to function comment +{ + return ManageIdtEntryTable (NewCallback, ExceptionType); +} + +EFI_STATUS +EFIAPI +InvalidateInstructionCache ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + This is a DebugSupport protocol member function. + For IA32, this is a no-op since the instruction and data caches are coherent. + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: ProcessorIndex - add argument and description to function comment +// TODO: Start - add argument and description to function comment +// TODO: Length - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + return EFI_SUCCESS; +} + +EFI_STATUS +plInitializeDebugSupportDriver ( + VOID + ) +/*++ + +Routine Description: + Initializes driver's handler registration database. + + This code executes in boot services context. + +Arguments: + None + +Returns: + EFI_SUCCESS + EFI_UNSUPPORTED - if IA32 processor does not support FXSTOR/FXRSTOR instructions, + the context save will fail, so these processor's are not supported. + +--*/ +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +{ + if (!FxStorSupport ()) { + return EFI_UNSUPPORTED; + } else { + IdtEntryTable = AllocateZeroPool (sizeof (IDT_ENTRY) * NUM_IDT_ENTRIES); + if (IdtEntryTable != NULL) { + return EFI_SUCCESS; + } else { + return EFI_OUT_OF_RESOURCES; + } + } +} + +EFI_STATUS +EFIAPI +plUnloadDebugSupportDriver ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + This is the callback that is written to the LoadedImage protocol instance + on the image handle. It uninstalls all registered handlers and frees all entry + stub memory. + + This code executes in boot services context. + +Arguments: + ImageHandle - The image handle of the unload handler + +Returns: + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_EXCEPTION_TYPE ExceptionType; + + for (ExceptionType = 0; ExceptionType < NUM_IDT_ENTRIES; ExceptionType++) { + ManageIdtEntryTable (NULL, ExceptionType); + } + + gBS->FreePool (IdtEntryTable); + return EFI_SUCCESS; +} + +VOID +InterruptDistrubutionHub ( + EFI_EXCEPTION_TYPE ExceptionType, + EFI_SYSTEM_CONTEXT_IA32 *ContextRecord + ) +/*++ + +Routine Description: Common piece of code that invokes the registered handlers. + + This code executes in exception context so no efi calls are allowed. + +Arguments: + +Returns: + + None + +--*/ +// TODO: ExceptionType - add argument and description to function comment +// TODO: ContextRecord - add argument and description to function comment +{ + if (IdtEntryTable[ExceptionType].RegisteredCallback != NULL) { + if (ExceptionType != SYSTEM_TIMER_VECTOR) { + IdtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, ContextRecord); + } else { + OrigVector = IdtEntryTable[ExceptionType].OrigVector; + IdtEntryTable[ExceptionType].RegisteredCallback (ContextRecord); + } + } +} diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/ia32/plDebugSupport.h b/EdkModulePkg/Universal/DebugSupport/Dxe/ia32/plDebugSupport.h new file mode 100644 index 0000000000..abb6967dea --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/ia32/plDebugSupport.h @@ -0,0 +1,312 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + plDebugSupport.h + +Abstract: + + IA32 specific debug support macros, typedefs and prototypes. + +Revision History + +--*/ + +#ifndef _PLDEBUG_SUPPORT_H +#define _PLDEBUG_SUPPORT_H + +#define NUM_IDT_ENTRIES 0x78 +#define SYSTEM_TIMER_VECTOR 0x68 +#define VECTOR_ENTRY_PAGES 1 +#define CopyDescriptor(Dest, Src) CopyMem ((Dest), (Src), sizeof (DESCRIPTOR)) +#define ZeroDescriptor(Dest) CopyDescriptor ((Dest), &NullDesc) +#define ReadIdt(Vector, Dest) CopyDescriptor ((Dest), &((GetIdtr ())[(Vector)])) +#define WriteIdt(Vector, Src) CopyDescriptor (&((GetIdtr ())[(Vector)]), (Src)) +#define CompareDescriptor(Desc1, Desc2) CompareMem ((Desc1), (Desc2), sizeof (DESCRIPTOR)) +#define EFI_ISA IsaIa32 +#define FF_FXSR (1 << 24) + +typedef UINT64 DESCRIPTOR; + +typedef struct { + DESCRIPTOR OrigDesc; + VOID (*OrigVector) (VOID); + DESCRIPTOR NewDesc; + VOID (*StubEntry) (VOID); + VOID (*RegisteredCallback) (); +} IDT_ENTRY; + +extern EFI_SYSTEM_CONTEXT SystemContext; +extern UINT8 InterruptEntryStub[]; +extern UINT32 StubSize; +extern VOID (*OrigVector) (VOID); + +VOID +CommonIdtEntry ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +FxStorSupport ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +DESCRIPTOR * +GetIdtr ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +VOID +Vect2Desc ( + DESCRIPTOR * DestDesc, + VOID (*Vector) (VOID) + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + DestDesc - TODO: add argument description + ) - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +WriteInterruptFlag ( + BOOLEAN NewState + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + NewState - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +plInitializeDebugSupportDriver ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +plUnloadDebugSupportDriver ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// DebugSupport protocol member functions +// +EFI_STATUS +EFIAPI +GetMaximumProcessorIndex ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MaxProcessorIndex - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +RegisterPeriodicCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ProcessorIndex - TODO: add argument description + PeriodicCallback - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +RegisterExceptionCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK NewCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ProcessorIndex - TODO: add argument description + NewCallback - TODO: add argument description + ExceptionType - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +InvalidateInstructionCache ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ProcessorIndex - TODO: add argument description + Start - TODO: add argument description + Length - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/AsmFuncs.s b/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/AsmFuncs.s new file mode 100644 index 0000000000..1ac4a7e503 --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/AsmFuncs.s @@ -0,0 +1,1389 @@ +//++ +// Copyright (c) 2006, 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. +// +// Module Name: +// +// AsmFuncs.s +// +// Abstract: +// +// Low level IPF routines used by the debug support driver +// +// Revision History: +// +//-- + + +#include "common.i" +#include "Ds64Macros.i" + +.global PatchSaveBuffer +.global IpfContextBuf +.global CommonHandler +.global ExternalInterruptCount + + +///////////////////////////////////////////// +// +// Name: +// InstructionCacheFlush +// +// Description: +// Flushes instruction cache for specified number of bytes +// + .global InstructionCacheFlush + .proc InstructionCacheFlush + .align 32 +InstructionCacheFlush:: + { .mii + alloc r3=2, 0, 0, 0 + cmp4.leu p0,p6=32, r33;; + (p6) mov r33=32;; + } + { .mii + nop.m 0 + zxt4 r29=r33;; + dep.z r30=r29, 0, 5;; + } + { .mii + cmp4.eq p0,p7=r0, r30 + shr.u r28=r29, 5;; + (p7) adds r28=1, r28;; + } + { .mii + nop.m 0 + shl r27=r28, 5;; + zxt4 r26=r27;; + } + { .mfb + add r31=r26, r32 + nop.f 0 + nop.b 0 + } +LoopBack: // $L143: + { .mii + fc r32 + adds r32=32, r32;; + cmp.ltu p14,p15=r32, r31 + } + { .mfb + nop.m 0 + nop.f 0 + //(p14) br.cond.dptk.few $L143#;; + (p14) br.cond.dptk.few LoopBack;; + } + { .mmi + sync.i;; + srlz.i + nop.i 0;; + } + { .mfb + nop.m 0 + nop.f 0 + br.ret.sptk.few b0;; + } + .endp InstructionCacheFlush + + +///////////////////////////////////////////// +// +// Name: +// ChainHandler +// +// Description: +// Chains an interrupt handler +// +// The purpose of this function is to enable chaining of the external interrupt. +// Since there's no clean SAL abstraction for doing this, we must do it +// surreptitiously. +// +// The reserved IVT entry at offset 0x3400 is coopted for use by this handler. +// According to Itanium architecture, it is reserved. Strictly speaking, this is +// not safe, as we're cheating and violating the Itanium architecture. However, +// as long as we're the only ones cheating, we should be OK. Without hooks in +// the SAL to enable IVT management, there aren't many good options. +// +// The strategy is to replace the first bundle of the external interrupt handler +// with our own that will branch into a piece of code we've supplied and located +// in the reserved IVT entry. Only the first bundle of the external interrupt +// IVT entry is modified. +// +// The original bundle is moved and relocated to space +// allocated within the reserved IVT entry. The next bundle following is +// is generated to go a hard coded branch back to the second bundle of the +// external interrupt IVT entry just in case the first bundle had no branch. +// +// Our new code will execute our handler, and then fall through to the +// original bundle after restoring all context appropriately. +// +// The following is a representation of what the IVT memory map looks like with +// our chained handler installed: +// +// +// +// +// +// This IVT entry is Failsafe bundle +// reserved by the +// Itanium architecture Original bundle 0 +// and is used for +// for locating our +// handler and the +// original bundle Patch code... +// zero of the ext +// interrupt handler +// +// RSVD (3400) Unused +// +// +// +// +// +// +// +// +// +// +// +// +// EXT_INT (3000) Bundle 0 Bundle zero - This one is +// modified, all other bundles +// in the EXT_INT entry are +// untouched. +// +// +// Arguments: +// +// Returns: +// +// Notes: +// +// + .global ChainHandler + .proc ChainHandler +ChainHandler: + + NESTED_SETUP( 0,2+3,3,0 ) + + mov r8=1 // r8 = success + mov r2=cr.iva;; +// +// NOTE: There's a potential hazard here in that we're simply stealing a bunch of +// bundles (memory) from the IVT and assuming there's no catastrophic side effect. +// +// First, save IVT area we're taking over with the patch so we can restore it later +// + addl out0=PATCH_ENTRY_OFFSET, r2 // out0 = source buffer + movl out1=PatchSaveBuffer // out1 = destination buffer + mov out2=0x40;; // out2 = number of bundles to copy... save entire IDT entry + br.call.sptk.few b0 = CopyBundles + +// Next, copy the patch code into the IVT + movl out0=PatchCode // out0 = source buffer of patch code + addl out1=PATCH_OFFSET, r2 // out1 = destination buffer - in IVT + mov out2=NUM_PATCH_BUNDLES;; // out2 = number of bundles to copy + br.call.sptk.few b0 = CopyBundles + + +// copy original bundle 0 from the external interrupt handler to the +// appropriate place in the reserved IVT interrupt slot + addl out0=EXT_INT_ENTRY_OFFSET, r2 // out0 = source buffer + addl out1=RELOCATED_EXT_INT, r2 // out1 = destination buffer - in reserved IVT + mov out2=1;; // out2 = copy 1 bundle + br.call.sptk.few b0 = CopyBundles + +// Now relocate it there because it very likely had a branch instruction that +// that must now be fixed up. + addl out0=RELOCATED_EXT_INT, r2 // out0 = new runtime address of bundle - in reserved IVT + addl out1=EXT_INT_ENTRY_OFFSET, r2;;// out1 = IP address of previous location + mov out2=out0;; // out2 = IP address of new location + br.call.sptk.few b0 = RelocateBundle + +// Now copy into the failsafe branch into the next bundle just in case +// the original ext int bundle 0 bundle did not contain a branch instruction + movl out0=FailsafeBranch // out0 = source buffer + addl out1=FAILSAFE_BRANCH_OFFSET, r2 // out1 = destination buffer - in reserved IVT + mov out2=1;; // out2 = copy 1 bundle + br.call.sptk.few b0 = CopyBundles + +// Last, copy in our replacement for the external interrupt IVT entry bundle 0 + movl out0=PatchCodeNewBun0 // out0 = source buffer - our replacement bundle 0 + addl out1=EXT_INT_ENTRY_OFFSET, r2 // out1 = destination buffer - bundle 0 of External interrupt entry + mov out2=1;; // out2 = copy 1 bundle + br.call.sptk.few b0 = CopyBundles + +ChainHandlerDone: + NESTED_RETURN + + .endp ChainHandler + + +///////////////////////////////////////////// +// +// Name: +// UnchainHandler +// +// Description: +// Unchains an interrupt handler +// +// Arguments: +// +// Returns: +// +// Notes: +// +// + .global UnchainHandler + .proc UnchainHandler + +UnchainHandler: + + NESTED_SETUP( 0,2+3,3,0 ) + + mov r8=1 // r8 = success + mov r2=cr.iva;; // r2 = interrupt vector address + +// First copy original Ext Int bundle 0 back to it's proper home... + addl out0=RELOCATED_EXT_INT, r2 // out0 = source - in reserved IVT + addl out1=EXT_INT_ENTRY_OFFSET, r2 // out1 = destination buffer - first bundle of Ext Int entry + mov out2=1;; // out2 = copy 1 bundle + br.call.sptk.few b0 = CopyBundles + +// Now, relocate it again... + addl out0=EXT_INT_ENTRY_OFFSET, r2 // out1 = New runtime address + addl out1=RELOCATED_EXT_INT, r2;; // out0 = IP address of previous location + mov out2=out0;; // out2 = IP address of new location + br.call.sptk.few b0 = RelocateBundle + +// Last, restore the patch area + movl out0=PatchSaveBuffer // out0 = source buffer + addl out1=PATCH_ENTRY_OFFSET, r2 // out1 = destination buffer + mov out2=0x40;; // out2 = number of bundles to copy... save entire IDT entry + br.call.sptk.few b0 = CopyBundles + +UnchainHandlerDone: + NESTED_RETURN + + .endp UnchainHandler + + +///////////////////////////////////////////// +// +// Name: +// CopyBundles +// +// Description: +// Copies instruction bundles - flushes icache as necessary +// +// Arguments: +// in0 - Bundle source +// in1 - Bundle destination +// in2 - Bundle count +// +// Returns: +// +// Notes: +// This procedure is a leaf routine +// + .proc CopyBundles + +CopyBundles: + + NESTED_SETUP(3,2+1,0,0) + + shl in2=in2, 1;; // in2 = count of 8 byte blocks to copy + +CopyBundlesLoop: + + cmp.eq p14, p15 = 0, in2;; // Check if done +(p14) br.sptk.few CopyBundlesDone;; + + ld8 loc2=[in0], 0x8;; // loc2 = source bytes + st8 [in1]=loc2;; // [in1] = destination bytes + fc in1;; // Flush instruction cache + sync.i;; // Ensure local and remote data/inst caches in sync + srlz.i;; // Ensure sync has been observed + add in1=0x8, in1;; // in1 = next destination + add in2=-1, in2;; // in2 = decrement 8 bytes blocks to copy + br.sptk.few CopyBundlesLoop;; + +CopyBundlesDone: + NESTED_RETURN + + .endp CopyBundles + + +///////////////////////////////////////////// +// +// Name: +// RelocateBundle +// +// Description: +// Relocates an instruction bundle by updating any ip-relative branch instructions. +// +// Arguments: +// in0 - Runtime address of bundle +// in1 - IP address of previous location of bundle +// in2 - IP address of new location of bundle +// +// Returns: +// in0 - 1 if successful or 0 if unsuccessful +// +// Notes: +// This routine examines all slots in the given bundle that are destined for the +// branch execution unit. If any of these slots contain an IP-relative branch +// namely instructions B1, B2, B3, or B6, the slot is fixed-up with a new relative +// address. Errors can occur if a branch cannot be reached. +// + .proc RelocateBundle + +RelocateBundle: + + NESTED_SETUP(3,2+4,3,0) + + mov loc2=SLOT0 // loc2 = slot index + mov loc5=in0;; // loc5 = runtime address of bundle + mov in0=1;; // in0 = success + +RelocateBundleNextSlot: + + cmp.ge p14, p15 = SLOT2, loc2;; // Check if maximum slot +(p15) br.sptk.few RelocateBundleDone + + mov out0=loc5;; // out0 = runtime address of bundle + br.call.sptk.few b0 = GetTemplate + mov loc3=out0;; // loc3 = instruction template + mov out0=loc5 // out0 = runtime address of bundle + mov out1=loc2;; // out1 = instruction slot number + br.call.sptk.few b0 = GetSlot + mov loc4=out0;; // loc4 = instruction encoding + mov out0=loc4 // out0 = instuction encoding + mov out1=loc2 // out1 = instruction slot number + mov out2=loc3;; // out2 = instruction template + br.call.sptk.few b0 = IsSlotBranch + cmp.eq p14, p15 = 1, out0;; // Check if branch slot +(p15) add loc2=1,loc2 // Increment slot +(p15) br.sptk.few RelocateBundleNextSlot + mov out0=loc4 // out0 = instuction encoding + mov out1=in1 // out1 = IP address of previous location + mov out2=in2;; // out2 = IP address of new location + br.call.sptk.few b0 = RelocateSlot + cmp.eq p14, p15 = 1, out1;; // Check if relocated slot +(p15) mov in0=0 // in0 = failure +(p15) br.sptk.few RelocateBundleDone + mov out2=out0;; // out2 = instruction encoding + mov out0=loc5 // out0 = runtime address of bundle + mov out1=loc2;; // out1 = instruction slot number + br.call.sptk.few b0 = SetSlot + add loc2=1,loc2;; // Increment slot + br.sptk.few RelocateBundleNextSlot + +RelocateBundleDone: + NESTED_RETURN + + .endp RelocateBundle + + +///////////////////////////////////////////// +// +// Name: +// RelocateSlot +// +// Description: +// Relocates an instruction bundle by updating any ip-relative branch instructions. +// +// Arguments: +// in0 - Instruction encoding (41-bits, right justified) +// in1 - IP address of previous location of bundle +// in2 - IP address of new location of bundle +// +// Returns: +// in0 - Instruction encoding (41-bits, right justified) +// in1 - 1 if successful otherwise 0 +// +// Notes: +// This procedure is a leaf routine +// + .proc RelocateSlot + +RelocateSlot: + NESTED_SETUP(3,2+5,0,0) + extr.u loc2=in0, 37, 4;; // loc2 = instruction opcode + cmp.eq p14, p15 = 4, loc2;; // IP-relative branch (B1) or + // IP-relative counted branch (B2) +(p15) cmp.eq p14, p15 = 5, loc2;; // IP-relative call (B3) +(p15) cmp.eq p14, p15 = 7, loc2;; // IP-relative predict (B6) +(p15) mov in1=1 // Instruction did not need to be reencoded +(p15) br.sptk.few RelocateSlotDone + tbit.nz p14, p15 = in0, 36;; // put relative offset sign bit in p14 + extr.u loc2=in0, 13, 20;; // loc2 = relative offset in instruction +(p14) movl loc3=0xfffffffffff00000;; // extend sign +(p14) or loc2=loc2, loc3;; + shl loc2=loc2,4;; // convert to byte offset instead of bundle offset + add loc3=loc2, in1;; // loc3 = physical address of branch target +(p14) sub loc2=r0,loc2;; // flip sign in loc2 if offset is negative + sub loc4=loc3,in2;; // loc4 = relative offset from new ip to branch target + cmp.lt p15, p14 = 0, loc4;; // get new sign bit +(p14) sub loc5=r0,loc4 // get absolute value of offset +(p15) mov loc5=loc4;; + movl loc6=0x0FFFFFF;; // maximum offset in bytes for ip-rel branch + cmp.gt p14, p15 = loc5, loc6;; // check to see we're not out of range for an ip-relative branch +(p14) br.sptk.few RelocateSlotError + cmp.lt p15, p14 = 0, loc4;; // store sign in p14 again +(p14) dep in0=1,in0,36,1 // store sign bit in instruction +(p15) dep in0=0,in0,36,1 + shr loc4=loc4, 4;; // convert back to bundle offset + dep in0=loc4,in0,13,16;; // put first 16 bits of new offset into instruction + shr loc4=loc4,16;; + dep in0=loc4,in0,13+16,4 // put last 4 bits of new offset into instruction + mov in1=1;; // in1 = success + br.sptk.few RelocateSlotDone;; + +RelocateSlotError: + mov in1=0;; // in1 = failure + +RelocateSlotDone: + NESTED_RETURN + + .endp RelocateSlot + + +///////////////////////////////////////////// +// +// Name: +// IsSlotBranch +// +// Description: +// Determines if the given instruction is a branch instruction. +// +// Arguments: +// in0 - Instruction encoding (41-bits, right justified) +// in1 - Instruction slot number +// in2 - Bundle template +// +// Returns: +// in0 - 1 if branch or 0 if not branch +// +// Notes: +// This procedure is a leaf routine +// +// IsSlotBranch recognizes all branch instructions by looking at the provided template. +// The instruction encoding is only passed to this routine for future expansion. +// + .proc IsSlotBranch + +IsSlotBranch: + + NESTED_SETUP (3,2+0,0,0) + + mov in0=1;; // in0 = 1 which destroys the instruction + andcm in2=in2,in0;; // in2 = even template to reduce compares + mov in0=0;; // in0 = not a branch + cmp.eq p14, p15 = 0x16, in2;; // Template 0x16 is BBB +(p14) br.sptk.few IsSlotBranchTrue + cmp.eq p14, p15 = SLOT0, in1;; // Slot 0 has no other possiblities +(p14) br.sptk.few IsSlotBranchDone + cmp.eq p14, p15 = 0x12, in2;; // Template 0x12 is MBB +(p14) br.sptk.few IsSlotBranchTrue + cmp.eq p14, p15 = SLOT1, in1;; // Slot 1 has no other possiblities +(p14) br.sptk.few IsSlotBranchDone + cmp.eq p14, p15 = 0x10, in2;; // Template 0x10 is MIB +(p14) br.sptk.few IsSlotBranchTrue + cmp.eq p14, p15 = 0x18, in2;; // Template 0x18 is MMB +(p14) br.sptk.few IsSlotBranchTrue + cmp.eq p14, p15 = 0x1C, in2;; // Template 0x1C is MFB +(p14) br.sptk.few IsSlotBranchTrue + br.sptk.few IsSlotBranchDone + +IsSlotBranchTrue: + mov in0=1;; // in0 = branch + +IsSlotBranchDone: + NESTED_RETURN + + .endp IsSlotBranch + + +///////////////////////////////////////////// +// +// Name: +// GetTemplate +// +// Description: +// Retrieves the instruction template for an instruction bundle +// +// Arguments: +// in0 - Runtime address of bundle +// +// Returns: +// in0 - Instruction template (5-bits, right-justified) +// +// Notes: +// This procedure is a leaf routine +// + .proc GetTemplate + +GetTemplate: + + NESTED_SETUP (1,2+2,0,0) + + ld8 loc2=[in0], 0x8 // loc2 = first 8 bytes of branch bundle + movl loc3=MASK_0_4;; // loc3 = template mask + and loc2=loc2,loc3;; // loc2 = template, right justified + mov in0=loc2;; // in0 = template, right justified + + NESTED_RETURN + + .endp GetTemplate + + +///////////////////////////////////////////// +// +// Name: +// GetSlot +// +// Description: +// Gets the instruction encoding for an instruction slot and bundle +// +// Arguments: +// in0 - Runtime address of bundle +// in1 - Instruction slot (either 0, 1, or 2) +// +// Returns: +// in0 - Instruction encoding (41-bits, right justified) +// +// Notes: +// This procedure is a leaf routine +// +// Slot0 - [in0 + 0x8] Bits 45-5 +// Slot1 - [in0 + 0x8] Bits 63-46 and [in0] Bits 22-0 +// Slot2 - [in0] Bits 63-23 +// + .proc GetSlot + +GetSlot: + NESTED_SETUP (2,2+3,0,0) + + ld8 loc2=[in0], 0x8;; // loc2 = first 8 bytes of branch bundle + ld8 loc3=[in0];; // loc3 = second 8 bytes of branch bundle + cmp.eq p14, p15 = 2, in1;; // check if slot 2 specified + (p14) br.cond.sptk.few GetSlot2;; // get slot 2 + cmp.eq p14, p15 = 1, in1;; // check if slot 1 specified + (p14) br.cond.sptk.few GetSlot1;; // get slot 1 + +GetSlot0: + extr.u in0=loc2, 5, 45 // in0 = extracted slot 0 + br.sptk.few GetSlotDone;; + +GetSlot1: + extr.u in0=loc2, 46, 18 // in0 = bits 63-46 of loc2 right-justified + extr.u loc4=loc3, 0, 23;; // loc4 = bits 22-0 of loc3 right-justified + dep in0=loc4, in0, 18, 15;; + shr.u loc4=loc4,15;; + dep in0=loc4, in0, 33, 8;; // in0 = extracted slot 1 + br.sptk.few GetSlotDone;; + +GetSlot2: + extr.u in0=loc3, 23, 41;; // in0 = extracted slot 2 + +GetSlotDone: + NESTED_RETURN + + .endp GetSlot + + +///////////////////////////////////////////// +// +// Name: +// SetSlot +// +// Description: +// Sets the instruction encoding for an instruction slot and bundle +// +// Arguments: +// in0 - Runtime address of bundle +// in1 - Instruction slot (either 0, 1, or 2) +// in2 - Instruction encoding (41-bits, right justified) +// +// Returns: +// +// Notes: +// This procedure is a leaf routine +// + .proc SetSlot + +SetSlot: + NESTED_SETUP (3,2+3,0,0) + + ld8 loc2=[in0], 0x8;; // loc2 = first 8 bytes of bundle + ld8 loc3=[in0];; // loc3 = second 8 bytes of bundle + cmp.eq p14, p15 = 2, in1;; // check if slot 2 specified + (p14) br.cond.sptk.few SetSlot2;; // set slot 2 + cmp.eq p14, p15 = 1, in1;; // check if slot 1 specified + (p14) br.cond.sptk.few SetSlot1;; // set slot 1 + +SetSlot0: + dep loc2=0, loc2, 5, 41;; // remove old instruction from slot 0 + shl loc4=in2, 5;; // loc4 = new instruction ready to be inserted + or loc2=loc2, loc4;; // loc2 = updated first 8 bytes of bundle + add loc4=0x8,in0;; // loc4 = address to store first 8 bytes of bundle + st8 [loc4]=loc2 // [loc4] = updated bundle + br.sptk.few SetSlotDone;; + ;; + +SetSlot1: + dep loc2=0, loc2, 46, 18 // remove old instruction from slot 1 + dep loc3=0, loc3, 0, 23;; + shl loc4=in2, 46;; // loc4 = partial instruction ready to be inserted + or loc2=loc2, loc4;; // loc2 = updated first 8 bytes of bundle + add loc4=0x8,in0;; // loc4 = address to store first 8 bytes of bundle + st8 [loc4]=loc2;; // [loc4] = updated bundle + shr.u loc4=in2, 18;; // loc4 = partial instruction ready to be inserted + or loc3=loc3, loc4;; // loc3 = updated second 8 bytes of bundle + st8 [in0]=loc3;; // [in0] = updated bundle + br.sptk.few SetSlotDone;; + +SetSlot2: + dep loc3=0, loc3, 23, 41;; // remove old instruction from slot 2 + shl loc4=in2, 23;; // loc4 = instruction ready to be inserted + or loc3=loc3, loc4;; // loc3 = updated second 8 bytes of bundle + st8 [in0]=loc3;; // [in0] = updated bundle + +SetSlotDone: + + NESTED_RETURN + .endp SetSlot + + +///////////////////////////////////////////// +// +// Name: +// GetIva +// +// Description: +// C callable function to obtain the current value of IVA +// +// Returns: +// Current value if IVA + + .global GetIva + .proc GetIva +GetIva: + mov r8=cr2;; + br.ret.sptk.many b0 + + .endp GetIva + + +///////////////////////////////////////////// +// +// Name: +// ProgramInterruptFlags +// +// Description: +// C callable function to enable/disable interrupts +// +// Returns: +// Previous state of psr.ic +// + .global ProgramInterruptFlags + .proc ProgramInterruptFlags +ProgramInterruptFlags: + alloc loc0=1,2,0,0;; + mov loc0=psr + mov loc1=0x6000;; + and r8=loc0, loc1 // obtain current psr.ic and psr.i state + and in0=in0, loc1 // insure no extra bits set in input + andcm loc0=loc0,loc1;; // clear original psr.i and psr.ic + or loc0=loc0,in0;; // OR in new psr.ic value + mov psr.l=loc0;; // write new psr + srlz.d + br.ret.sptk.many b0 // return + + .endp ProgramInterruptFlags + + +///////////////////////////////////////////// +// +// Name: +// SpillContext +// +// Description: +// Saves system context to context record. +// +// Arguments: +// in0 = 512 byte aligned context record address +// in1 = original B0 +// in2 = original ar.bsp +// in3 = original ar.bspstore +// in4 = original ar.rnat +// in5 = original ar.pfs +// +// Notes: +// loc0 - scratch +// loc1 - scratch +// loc2 - temporary application unat storage +// loc3 - temporary exception handler unat storage + + .proc SpillContext + +SpillContext: + alloc loc0=6,4,0,0;; // alloc 6 input, 4 locals, 0 outs + mov loc2=ar.unat;; // save application context unat (spilled later) + mov ar.unat=r0;; // set UNAT=0 + st8.spill [in0]=r0,8;; + st8.spill [in0]=r1,8;; // save R1 - R31 + st8.spill [in0]=r2,8;; + st8.spill [in0]=r3,8;; + st8.spill [in0]=r4,8;; + st8.spill [in0]=r5,8;; + st8.spill [in0]=r6,8;; + st8.spill [in0]=r7,8;; + st8.spill [in0]=r8,8;; + st8.spill [in0]=r9,8;; + st8.spill [in0]=r10,8;; + st8.spill [in0]=r11,8;; + st8.spill [in0]=r12,8;; + st8.spill [in0]=r13,8;; + st8.spill [in0]=r14,8;; + st8.spill [in0]=r15,8;; + st8.spill [in0]=r16,8;; + st8.spill [in0]=r17,8;; + st8.spill [in0]=r18,8;; + st8.spill [in0]=r19,8;; + st8.spill [in0]=r20,8;; + st8.spill [in0]=r21,8;; + st8.spill [in0]=r22,8;; + st8.spill [in0]=r23,8;; + st8.spill [in0]=r24,8;; + st8.spill [in0]=r25,8;; + st8.spill [in0]=r26,8;; + st8.spill [in0]=r27,8;; + st8.spill [in0]=r28,8;; + st8.spill [in0]=r29,8;; + st8.spill [in0]=r30,8;; + st8.spill [in0]=r31,8;; + mov loc3=ar.unat;; // save debugger context unat (spilled later) + stf.spill [in0]=f2,16;; // save f2 - f31 + stf.spill [in0]=f3,16;; + stf.spill [in0]=f4,16;; + stf.spill [in0]=f5,16;; + stf.spill [in0]=f6,16;; + stf.spill [in0]=f7,16;; + stf.spill [in0]=f8,16;; + stf.spill [in0]=f9,16;; + stf.spill [in0]=f10,16;; + stf.spill [in0]=f11,16;; + stf.spill [in0]=f12,16;; + stf.spill [in0]=f13,16;; + stf.spill [in0]=f14,16;; + stf.spill [in0]=f15,16;; + stf.spill [in0]=f16,16;; + stf.spill [in0]=f17,16;; + stf.spill [in0]=f18,16;; + stf.spill [in0]=f19,16;; + stf.spill [in0]=f20,16;; + stf.spill [in0]=f21,16;; + stf.spill [in0]=f22,16;; + stf.spill [in0]=f23,16;; + stf.spill [in0]=f24,16;; + stf.spill [in0]=f25,16;; + stf.spill [in0]=f26,16;; + stf.spill [in0]=f27,16;; + stf.spill [in0]=f28,16;; + stf.spill [in0]=f29,16;; + stf.spill [in0]=f30,16;; + stf.spill [in0]=f31,16;; + mov loc0=pr;; // save predicates + st8.spill [in0]=loc0,8;; + st8.spill [in0]=in1,8;; // save b0 - b7... in1 already equals saved b0 + mov loc0=b1;; + st8.spill [in0]=loc0,8;; + mov loc0=b2;; + st8.spill [in0]=loc0,8;; + mov loc0=b3;; + st8.spill [in0]=loc0,8;; + mov loc0=b4;; + st8.spill [in0]=loc0,8;; + mov loc0=b5;; + st8.spill [in0]=loc0,8;; + mov loc0=b6;; + st8.spill [in0]=loc0,8;; + mov loc0=b7;; + st8.spill [in0]=loc0,8;; + mov loc0=ar.rsc;; // save ar.rsc + st8.spill [in0]=loc0,8;; + st8.spill [in0]=in2,8;; // save ar.bsp (in2) + st8.spill [in0]=in3,8;; // save ar.bspstore (in3) + st8.spill [in0]=in4,8;; // save ar.rnat (in4) + mov loc0=ar.fcr;; // save ar.fcr (ar21 - IA32 floating-point control register) + st8.spill [in0]=loc0,8;; + mov loc0=ar.eflag;; // save ar.eflag (ar24) + st8.spill [in0]=loc0,8;; + mov loc0=ar.csd;; // save ar.csd (ar25 - ia32 CS descriptor) + st8.spill [in0]=loc0,8;; + mov loc0=ar.ssd;; // save ar.ssd (ar26 - ia32 ss descriptor) + st8.spill [in0]=loc0,8;; + mov loc0=ar.cflg;; // save ar.cflg (ar27 - ia32 cr0 and cr4) + st8.spill [in0]=loc0,8;; + mov loc0=ar.fsr;; // save ar.fsr (ar28 - ia32 floating-point status register) + st8.spill [in0]=loc0,8;; + mov loc0=ar.fir;; // save ar.fir (ar29 - ia32 floating-point instruction register) + st8.spill [in0]=loc0,8;; + mov loc0=ar.fdr;; // save ar.fdr (ar30 - ia32 floating-point data register) + st8.spill [in0]=loc0,8;; + mov loc0=ar.ccv;; // save ar.ccv + st8.spill [in0]=loc0,8;; + st8.spill [in0]=loc2,8;; // save ar.unat (saved to loc2 earlier) + mov loc0=ar.fpsr;; // save floating point status register + st8.spill [in0]=loc0,8;; + st8.spill [in0]=in5,8;; // save ar.pfs + mov loc0=ar.lc;; // save ar.lc + st8.spill [in0]=loc0,8;; + mov loc0=ar.ec;; // save ar.ec + st8.spill [in0]=loc0,8;; + + // save control registers + mov loc0=cr.dcr;; // save dcr + st8.spill [in0]=loc0,8;; + mov loc0=cr.itm;; // save itm + st8.spill [in0]=loc0,8;; + mov loc0=cr.iva;; // save iva + st8.spill [in0]=loc0,8;; + mov loc0=cr.pta;; // save pta + st8.spill [in0]=loc0,8;; + mov loc0=cr.ipsr;; // save ipsr + st8.spill [in0]=loc0,8;; + mov loc0=cr.isr;; // save isr + st8.spill [in0]=loc0,8;; + mov loc0=cr.iip;; // save iip + st8.spill [in0]=loc0,8;; + mov loc0=cr.ifa;; // save ifa + st8.spill [in0]=loc0,8;; + mov loc0=cr.itir;; // save itir + st8.spill [in0]=loc0,8;; + mov loc0=cr.iipa;; // save iipa + st8.spill [in0]=loc0,8;; + mov loc0=cr.ifs;; // save ifs + st8.spill [in0]=loc0,8;; + mov loc0=cr.iim;; // save iim + st8.spill [in0]=loc0,8;; + mov loc0=cr.iha;; // save iha + st8.spill [in0]=loc0,8;; + + // save debug registers + mov loc0=dbr[r0];; // save dbr0 - dbr7 + st8.spill [in0]=loc0,8;; + movl loc1=1;; + mov loc0=dbr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=2;; + mov loc0=dbr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=3;; + mov loc0=dbr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=4;; + mov loc0=dbr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=5;; + mov loc0=dbr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=6;; + mov loc0=dbr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=7;; + mov loc0=dbr[loc1];; + st8.spill [in0]=loc0,8;; + mov loc0=ibr[r0];; // save ibr0 - ibr7 + st8.spill [in0]=loc0,8;; + movl loc1=1;; + mov loc0=ibr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=2;; + mov loc0=ibr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=3;; + mov loc0=ibr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=4;; + mov loc0=ibr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=5;; + mov loc0=ibr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=6;; + mov loc0=ibr[loc1];; + st8.spill [in0]=loc0,8;; + movl loc1=7;; + mov loc0=ibr[loc1];; + st8.spill [in0]=loc0,8;; + st8.spill [in0]=loc3;; + + br.ret.sptk.few b0 + + .endp SpillContext + + +///////////////////////////////////////////// +// +// Name: +// FillContext +// +// Description: +// Restores register context from context record. +// +// Arguments: +// in0 = address of last element 512 byte aligned context record address +// in1 = modified B0 +// in2 = modified ar.bsp +// in3 = modified ar.bspstore +// in4 = modified ar.rnat +// in5 = modified ar.pfs +// +// Notes: +// loc0 - scratch +// loc1 - scratch +// loc2 - temporary application unat storage +// loc3 - temporary exception handler unat storage + + .proc FillContext +FillContext: + alloc loc0=6,4,0,0;; // alloc 6 inputs, 4 locals, 0 outs + ld8.fill loc3=[in0],-8;; // int_nat (nat bits for R1-31) + movl loc1=7;; // ibr7 + ld8.fill loc0=[in0],-8;; + mov ibr[loc1]=loc0;; + movl loc1=6;; // ibr6 + ld8.fill loc0=[in0],-8;; + mov ibr[loc1]=loc0;; + movl loc1=5;; // ibr5 + ld8.fill loc0=[in0],-8;; + mov ibr[loc1]=loc0;; + movl loc1=4;; // ibr4 + ld8.fill loc0=[in0],-8;; + mov ibr[loc1]=loc0;; + movl loc1=3;; // ibr3 + ld8.fill loc0=[in0],-8;; + mov ibr[loc1]=loc0;; + movl loc1=2;; // ibr2 + ld8.fill loc0=[in0],-8;; + mov ibr[loc1]=loc0;; + movl loc1=1;; // ibr1 + ld8.fill loc0=[in0],-8;; + mov ibr[loc1]=loc0;; + ld8.fill loc0=[in0],-8;; // ibr0 + mov ibr[r0]=loc0;; + movl loc1=7;; // dbr7 + ld8.fill loc0=[in0],-8;; + mov dbr[loc1]=loc0;; + movl loc1=6;; // dbr6 + ld8.fill loc0=[in0],-8;; + mov dbr[loc1]=loc0;; + movl loc1=5;; // dbr5 + ld8.fill loc0=[in0],-8;; + mov dbr[loc1]=loc0;; + movl loc1=4;; // dbr4 + ld8.fill loc0=[in0],-8;; + mov dbr[loc1]=loc0;; + movl loc1=3;; // dbr3 + ld8.fill loc0=[in0],-8;; + mov dbr[loc1]=loc0;; + movl loc1=2;; // dbr2 + ld8.fill loc0=[in0],-8;; + mov dbr[loc1]=loc0;; + movl loc1=1;; // dbr1 + ld8.fill loc0=[in0],-8;; + mov dbr[loc1]=loc0;; + ld8.fill loc0=[in0],-8;; // dbr0 + mov dbr[r0]=loc0;; + ld8.fill loc0=[in0],-8;; // iha + mov cr.iha=loc0;; + ld8.fill loc0=[in0],-8;; // iim + mov cr.iim=loc0;; + ld8.fill loc0=[in0],-8;; // ifs + mov cr.ifs=loc0;; + ld8.fill loc0=[in0],-8;; // iipa + mov cr.iipa=loc0;; + ld8.fill loc0=[in0],-8;; // itir + mov cr.itir=loc0;; + ld8.fill loc0=[in0],-8;; // ifa + mov cr.ifa=loc0;; + ld8.fill loc0=[in0],-8;; // iip + mov cr.iip=loc0;; + ld8.fill loc0=[in0],-8;; // isr + mov cr.isr=loc0;; + ld8.fill loc0=[in0],-8;; // ipsr + mov cr.ipsr=loc0;; + ld8.fill loc0=[in0],-8;; // pta + mov cr.pta=loc0;; + ld8.fill loc0=[in0],-8;; // iva + mov cr.iva=loc0;; + ld8.fill loc0=[in0],-8;; // itm + mov cr.itm=loc0;; + ld8.fill loc0=[in0],-8;; // dcr + mov cr.dcr=loc0;; + ld8.fill loc0=[in0],-8;; // ec + mov ar.ec=loc0;; + ld8.fill loc0=[in0],-8;; // lc + mov ar.lc=loc0;; + ld8.fill in5=[in0],-8;; // ar.pfs + ld8.fill loc0=[in0],-8;; // ar.fpsr + mov ar.fpsr=loc0;; + ld8.fill loc2=[in0],-8;; // ar.unat - restored later... + ld8.fill loc0=[in0],-8;; // ar.ccv + mov ar.ccv=loc0;; + ld8.fill loc0=[in0],-8;; // ar.fdr + mov ar.fdr=loc0;; + ld8.fill loc0=[in0],-8;; // ar.fir + mov ar.fir=loc0;; + ld8.fill loc0=[in0],-8;; // ar.fsr + mov ar.fsr=loc0;; + ld8.fill loc0=[in0],-8;; // ar.cflg + mov ar.cflg=loc0;; + ld8.fill loc0=[in0],-8;; // ar.ssd + mov ar.ssd=loc0;; + ld8.fill loc0=[in0],-8;; // ar.csd + mov ar.csd=loc0;; + ld8.fill loc0=[in0],-8;; // ar.eflag + mov ar.eflag=loc0;; + ld8.fill loc0=[in0],-8;; // ar.fcr + mov ar.fcr=loc0;; + ld8.fill in4=[in0],-8;; // ar.rnat + ld8.fill in3=[in0],-8;; // bspstore + ld8.fill in2=[in0],-8;; // bsp + ld8.fill loc0=[in0],-8;; // ar.rsc + mov ar.rsc=loc0;; + ld8.fill loc0=[in0],-8;; // B7 - B0 + mov b7=loc0;; + ld8.fill loc0=[in0],-8;; + mov b6=loc0;; + ld8.fill loc0=[in0],-8;; + mov b5=loc0;; + ld8.fill loc0=[in0],-8;; + mov b4=loc0;; + ld8.fill loc0=[in0],-8;; + mov b3=loc0;; + ld8.fill loc0=[in0],-8;; + mov b2=loc0;; + ld8.fill loc0=[in0],-8;; + mov b1=loc0;; + ld8.fill in1=[in0],-8;; // b0 is temporarily stored in in1 + ld8.fill loc0=[in0],-16;; // predicates + mov pr=loc0;; + ldf.fill f31=[in0],-16;; + ldf.fill f30=[in0],-16;; + ldf.fill f29=[in0],-16;; + ldf.fill f28=[in0],-16;; + ldf.fill f27=[in0],-16;; + ldf.fill f26=[in0],-16;; + ldf.fill f25=[in0],-16;; + ldf.fill f24=[in0],-16;; + ldf.fill f23=[in0],-16;; + ldf.fill f22=[in0],-16;; + ldf.fill f21=[in0],-16;; + ldf.fill f20=[in0],-16;; + ldf.fill f19=[in0],-16;; + ldf.fill f18=[in0],-16;; + ldf.fill f17=[in0],-16;; + ldf.fill f16=[in0],-16;; + ldf.fill f15=[in0],-16;; + ldf.fill f14=[in0],-16;; + ldf.fill f13=[in0],-16;; + ldf.fill f12=[in0],-16;; + ldf.fill f11=[in0],-16;; + ldf.fill f10=[in0],-16;; + ldf.fill f9=[in0],-16;; + ldf.fill f8=[in0],-16;; + ldf.fill f7=[in0],-16;; + ldf.fill f6=[in0],-16;; + ldf.fill f5=[in0],-16;; + ldf.fill f4=[in0],-16;; + ldf.fill f3=[in0],-16;; + ldf.fill f2=[in0],-8;; + mov ar.unat=loc3;; // restore unat (int_nat) before fill of general registers + ld8.fill r31=[in0],-8;; + ld8.fill r30=[in0],-8;; + ld8.fill r29=[in0],-8;; + ld8.fill r28=[in0],-8;; + ld8.fill r27=[in0],-8;; + ld8.fill r26=[in0],-8;; + ld8.fill r25=[in0],-8;; + ld8.fill r24=[in0],-8;; + ld8.fill r23=[in0],-8;; + ld8.fill r22=[in0],-8;; + ld8.fill r21=[in0],-8;; + ld8.fill r20=[in0],-8;; + ld8.fill r19=[in0],-8;; + ld8.fill r18=[in0],-8;; + ld8.fill r17=[in0],-8;; + ld8.fill r16=[in0],-8;; + ld8.fill r15=[in0],-8;; + ld8.fill r14=[in0],-8;; + ld8.fill r13=[in0],-8;; + ld8.fill r12=[in0],-8;; + ld8.fill r11=[in0],-8;; + ld8.fill r10=[in0],-8;; + ld8.fill r9=[in0],-8;; + ld8.fill r8=[in0],-8;; + ld8.fill r7=[in0],-8;; + ld8.fill r6=[in0],-8;; + ld8.fill r5=[in0],-8;; + ld8.fill r4=[in0],-8;; + ld8.fill r3=[in0],-8;; + ld8.fill r2=[in0],-8;; + ld8.fill r1=[in0],-8;; + mov ar.unat=loc2;; // restore application context unat + + br.ret.sptk.many b0 + + .endp FillContext + + +///////////////////////////////////////////// +// +// Name: +// HookHandler +// +// Description: +// Common branch target from hooked IVT entries. Runs in interrupt context. +// Responsible for saving and restoring context and calling common C +// handler. Banked registers running on bank 0 at entry. +// +// Arguments: +// All arguments are passed in banked registers: +// B0_REG = Original B0 +// SCRATCH_REG1 = IVT entry index +// +// Returns: +// Returns via rfi +// +// Notes: +// loc0 - scratch +// loc1 - scratch +// loc2 - vector number / mask +// loc3 - 16 byte aligned context record address +// loc4 - temporary storage of last address in context record + +HookHandler: + flushrs;; // Synch RSE with backing store + mov SCRATCH_REG2=ar.bsp // save interrupted context bsp + mov SCRATCH_REG3=ar.bspstore // save interrupted context bspstore + mov SCRATCH_REG4=ar.rnat // save interrupted context rnat + mov SCRATCH_REG6=cr.ifs;; // save IFS in case we need to chain... + cover;; // creates new frame, moves old + // CFM to IFS. + alloc SCRATCH_REG5=0,5,6,0 // alloc 5 locals, 6 outs + ;; + // save banked registers to locals + mov out1=B0_REG // out1 = Original B0 + mov out2=SCRATCH_REG2 // out2 = original ar.bsp + mov out3=SCRATCH_REG3 // out3 = original ar.bspstore + mov out4=SCRATCH_REG4 // out4 = original ar.rnat + mov out5=SCRATCH_REG5 // out5 = original ar.pfs + mov loc2=SCRATCH_REG1;; // loc2 = vector number + chain flag + bsw.1;; // switch banked registers to bank 1 + srlz.d // explicit serialize required + // now fill in context record structure + movl loc3=IpfContextBuf // Insure context record is aligned + add loc0=-0x200,r0;; // mask the lower 9 bits (align on 512 byte boundary) + and loc3=loc3,loc0;; + add loc3=0x200,loc3;; // move to next 512 byte boundary + // loc3 now contains the 512 byte aligned context record + // spill register context into context record + mov out0=loc3;; // Context record base in out0 + // original B0 in out1 already + // original ar.bsp in out2 already + // original ar.bspstore in out3 already + br.call.sptk.few b0=SpillContext;; // spill context + mov loc4=out0 // save modified address + + // At this point, the context has been saved to the context record and we're + // ready to call the C part of the handler... + + movl loc0=CommonHandler;; // obtain address of plabel + ld8 loc1=[loc0];; // get entry point of CommonHandler + mov b6=loc1;; // put it in a branch register + adds loc1= 8, loc0;; // index to GP in plabel + ld8 r1=[loc1];; // set up gp for C call + mov loc1=0xfffff;; // mask off so only vector bits are present + and out0=loc2,loc1;; // pass vector number (exception type) + mov out1=loc3;; // pass context record address + br.call.sptk.few b0=b6;; // call C handler + + // We've returned from the C call, so restore the context and either rfi + // back to interrupted thread, or chain into the SAL if this was an external interrupt + mov out0=loc4;; // pass address of last element in context record + br.call.sptk.few b0=FillContext;; // Fill context + mov b0=out1 // fill in b0 + mov ar.rnat=out4 + mov ar.pfs=out5 + + // Loadrs is necessary because the debugger may have changed some values in + // the backing store. The processor, however may not be aware that the + // stacked registers need to be reloaded from the backing store. Therefore, + // we explicitly cause the RSE to refresh the stacked register's contents + // from the backing store. + mov loc0=ar.rsc // get RSC value + mov loc1=ar.rsc // save it so we can restore it + movl loc3=0xffffffffc000ffff;; // create mask for clearing RSC.loadrs + and loc0=loc0,loc3;; // create value for RSC with RSC.loadrs==0 + mov ar.rsc=loc0;; // modify RSC + loadrs;; // invalidate register stack + mov ar.rsc=loc1;; // restore original RSC + + bsw.0;; // switch banked registers back to bank 0 + srlz.d;; // explicit serialize required + mov PR_REG=pr // save predicates - to be restored after chaining decision + mov B0_REG=b0 // save b0 - required by chain code + mov loc2=EXCPT_EXTERNAL_INTERRUPT;; + cmp.eq p7,p0=SCRATCH_REG1,loc2;; // check to see if this is the timer tick + (p7) br.cond.dpnt.few DO_CHAIN;; + +NO_CHAIN: + mov pr=PR_REG;; + rfi;; // we're outa here. + +DO_CHAIN: + mov pr=PR_REG + mov SCRATCH_REG1=cr.iva + mov SCRATCH_REG2=PATCH_RETURN_OFFSET;; + add SCRATCH_REG1=SCRATCH_REG1, SCRATCH_REG2;; + mov b0=SCRATCH_REG1;; + br.cond.sptk.few b0;; + +EndHookHandler: + + +///////////////////////////////////////////// +// +// Name: +// HookStub +// +// Description: +// HookStub will be copied from it's loaded location into the IVT when +// an IVT entry is hooked. The IVT entry does an indirect jump via B0 to +// HookHandler, which in turn calls into the default C handler, which calls +// the user-installed C handler. The calls return and HookHandler executes +// an rfi. +// +// Notes: +// Saves B0 to B0_REG +// Saves IVT index to SCRATCH_REG1 (immediate value is fixed up when code is copied +// to the IVT entry. + + .global HookStub + .proc HookStub +HookStub: + + mov B0_REG=b0 + movl SCRATCH_REG1=HookHandler;; + mov b0=SCRATCH_REG1;; + mov SCRATCH_REG1=0;;// immediate value is fixed up during install of handler to be the vector number + br.cond.sptk.few b0 + + .endp HookStub + + +///////////////////////////////////////////// +// The following code is moved into IVT entry 14 (offset 3400) which is reserved +// in the Itanium architecture. The patch code is located at the end of the +// IVT entry. + +PatchCode: + mov SCRATCH_REG0=psr + mov SCRATCH_REG6=cr.ipsr + mov PR_REG=pr + mov B0_REG=b0;; + + // turn off any virtual translations + movl SCRATCH_REG1 = ~( MASK(PSR_DT,1) | MASK(PSR_RT,1));; + and SCRATCH_REG1 = SCRATCH_REG0, SCRATCH_REG1;; + mov psr.l = SCRATCH_REG1;; + srlz.d + tbit.z p14, p15 = SCRATCH_REG6, PSR_IS;; // Check to see if we were + // interrupted from IA32 + // context. If so, bail out + // and chain to SAL immediately + (p15) br.cond.sptk.few Stub_IVT_Passthru;; + // we only want to take 1 out of 32 external interrupts to minimize the + // impact to system performance. Check our interrupt count and bail + // out if we're not up to 32 + movl SCRATCH_REG1=ExternalInterruptCount;; + ld8 SCRATCH_REG2=[SCRATCH_REG1];; // ExternalInterruptCount + tbit.z p14, p15 = SCRATCH_REG2, 5;; // bit 5 set? + (p14) add SCRATCH_REG2=1, SCRATCH_REG2;; // No? Then increment + // ExternalInterruptCount + // and Chain to SAL + // immediately + (p14) st8 [SCRATCH_REG1]=SCRATCH_REG2;; + (p14) br.cond.sptk.few Stub_IVT_Passthru;; + (p15) mov SCRATCH_REG2=0;; // Yes? Then reset + // ExternalInterruptCount + // and branch to + // HookHandler + (p15) st8 [SCRATCH_REG1]=SCRATCH_REG2;; + mov pr=PR_REG + movl SCRATCH_REG1=HookHandler;; // SCRATCH_REG1 = entrypoint of HookHandler + mov b0=SCRATCH_REG1;; // b0 = entrypoint of HookHandler + mov SCRATCH_REG1=EXCPT_EXTERNAL_INTERRUPT;; + br.sptk.few b0;; // branch to HookHandler + +PatchCodeRet: + // fake-up an rfi to get RSE back to being coherent and insure psr has + // original contents when interrupt occured, then exit to SAL + // at this point: + // cr.ifs has been modified by previous "cover" + // SCRATCH_REG6 has original cr.ifs + + mov SCRATCH_REG5=cr.ipsr + mov SCRATCH_REG4=cr.iip;; + mov cr.ipsr=SCRATCH_REG0 + mov SCRATCH_REG1=ip;; + add SCRATCH_REG1=0x30, SCRATCH_REG1;; + mov cr.iip=SCRATCH_REG1;; + rfi;; // rfi to next instruction + +Stub_RfiTarget: + mov cr.ifs=SCRATCH_REG6 + mov cr.ipsr=SCRATCH_REG5 + mov cr.iip=SCRATCH_REG4;; + +Stub_IVT_Passthru: + mov pr=PR_REG // pr = saved predicate registers + mov b0=B0_REG;; // b0 = saved b0 +EndPatchCode: + + +///////////////////////////////////////////// +// The following bundle is moved into IVT entry 14 (offset 0x3400) which is reserved +// in the Itanium architecture. This bundle will be the last bundle and will +// be located at offset 0x37F0 in the IVT. + +FailsafeBranch: +{ + .mib + nop.m 0 + nop.i 0 + br.sptk.few -(FAILSAFE_BRANCH_OFFSET - EXT_INT_ENTRY_OFFSET - 0x10) +} + + +///////////////////////////////////////////// +// The following bundle is moved into IVT entry 13 (offset 0x3000) which is the +// external interrupt. It branches to the patch code. + +PatchCodeNewBun0: +{ + .mib + nop.m 0 + nop.i 0 + br.cond.sptk.few PATCH_BRANCH +} diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/Ds64Macros.i b/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/Ds64Macros.i new file mode 100644 index 0000000000..6088ce70fd --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/Ds64Macros.i @@ -0,0 +1,85 @@ +//++ +// Copyright (c) 2006, 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. +// +// Module Name: +// +// Ds64Macros.i +// +// Abstract: +// +// This is set of macros used in calculating offsets in the IVT +// +// Revision History: +// +//-- + +#define EXCPT_EXTERNAL_INTERRUPT 12 +#define MASK_0_4 0x000000000000001F // mask bits 0 through 4 +#define SLOT0 0 +#define SLOT1 1 +#define SLOT2 2 + +#define PSR_DT 17 +#define PSR_TB 26 +#define PSR_RT 27 +#define PSR_IS 34 +#define PSR_IT 36 +#define PSR_IC 13 +#define PSR_I 14 +#define PSR_SS 40 +#define PSR_BN 44 +#define PSR_RI_MASK 0x60000000000 + +#define EXCPT_EXTERNAL_INTERRUPT 12 + +#define SCRATCH_REG0 r23 +#define SCRATCH_REG1 r24 +#define SCRATCH_REG2 r25 +#define SCRATCH_REG3 r26 +#define SCRATCH_REG4 r27 +#define SCRATCH_REG5 r28 +#define SCRATCH_REG6 r29 +#define PR_REG r30 +#define B0_REG r31 + + +// EXT_INT_OFFSET is the offset of the external interrupt entry in the IVT +#define EXT_INT_ENTRY_OFFSET 0x03000 + +// PATCH_ENTRY_OFFSET is the offset into the IVT of the entry that is coopted (stolen) +// for use by the handler. The entire entry is restored when the handler is +// unloaded. +#define PATCH_ENTRY_OFFSET 0x03400 + +// PATCH_BUNDLES is the number of bundles actually in the patch +#define NUM_PATCH_BUNDLES ((EndPatchCode - PatchCode) / 0x10) + +// A hard coded branch back into the external interrupt IVT entry's second bundle +// is put here, just in case the original bundle zero did not have a branch +// This is the last bundle in the reserved IVT entry +#define FAILSAFE_BRANCH_OFFSET (PATCH_ENTRY_OFFSET + 0x400 - 0x10) + +// the original external interrupt IVT entry bundle zero is copied and relocated +// here... also in the reserved IVT entry +// This is the second-to-last bundle in the reserved IVT entry +#define RELOCATED_EXT_INT (PATCH_ENTRY_OFFSET + 0x400 - 0x20) + +// The patch is actually stored at the end of IVT:PATCH_ENTRY. The PATCH_OFFSET +// is the offset into IVT where the patch is actually stored. It is carefully +// located so that when we run out of patch code, the next bundle is the +// relocated bundle 0 from the original external interrupt handler +#define PATCH_OFFSET (PATCH_ENTRY_OFFSET + 0x400 - ( EndPatchCode - PatchCode ) - 0x20) + +#define PATCH_RETURN_OFFSET (PATCH_ENTRY_OFFSET + 0x400 - ( EndPatchCode - PatchCodeRet ) - 0x20) + +// PATCH_BRANCH is used only in the new bundle that is placed at the beginning +// of the external interrupt IVT entry. +#define PATCH_BRANCH (PATCH_OFFSET - EXT_INT_ENTRY_OFFSET) + diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/common.i b/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/common.i new file mode 100644 index 0000000000..a7b571b308 --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/common.i @@ -0,0 +1,34 @@ +//++ +// Copyright (c) 2006, 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. +// +// Module Name: +// +// Common.i +// +// Abstract: +// +// This is set of useful macros +// +// Revision History: +// +//-- + +#define NESTED_SETUP(i,l,o,r) \ + alloc loc1=ar##.##pfs,i,l,o,r ; \ + mov loc0=b0 ;; + + +#define NESTED_RETURN \ + mov b0=loc0 ; \ + mov ar##.##pfs=loc1 ;; \ + br##.##ret##.##dpnt b0 ;; + +#define MASK(bp,value) (value << bp) + diff --git a/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/plDebugSupport.c b/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/plDebugSupport.c new file mode 100644 index 0000000000..6f2ded213e --- /dev/null +++ b/EdkModulePkg/Universal/DebugSupport/Dxe/ipf/plDebugSupport.c @@ -0,0 +1,625 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PlDebugSupport.c + +Abstract: + + IPF specific debug support functions + +Revision History + +--*/ + +// +// Master EFI header file +// +#include "Tiano.h" + +// +// Common library header files +// +#include "EfiDriverLib.h" + +// +// Produced protocols +// +#include EFI_PROTOCOL_DEFINITION (DebugSupport) + +// +// private header files +// +#include "plDebugSupport.h" + +typedef struct { + UINT64 low; + UINT64 high; +} BUNDLE; + +// +// number of bundles to swap in ivt +// +#define NUM_BUNDLES_IN_STUB 5 +#define NUM_IVT_ENTRIES 64 + +typedef struct { + BUNDLE OrigBundles[NUM_BUNDLES_IN_STUB]; + VOID (*RegisteredCallback) (); +} IVT_ENTRY; + +STATIC +EFI_STATUS +ManageIvtEntryTable ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN BUNDLE NewBundles[4], + IN VOID (*NewCallback) () + ); + +STATIC +VOID +HookEntry ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN BUNDLE NewBundles[4], + IN VOID (*NewCallback) () + ); + +STATIC +VOID +UnhookEntry ( + IN EFI_EXCEPTION_TYPE ExceptionType + ); + +STATIC +VOID +ChainExternalInterrupt ( + IN VOID (*NewCallback) () + ); + +STATIC +VOID +UnchainExternalInterrupt ( + VOID + ); + +STATIC +VOID +GetHandlerEntryPoint ( + UINTN HandlerIndex, + VOID **EntryPoint + ); + +IVT_ENTRY IvtEntryTable[NUM_IVT_ENTRIES]; + +// +// IPF context record is overallocated by 512 bytes to guarantee a 512 byte alignment exists +// within the buffer and still have a large enough buffer to hold a whole IPF context record. +// +UINT8 IpfContextBuf[sizeof (EFI_SYSTEM_CONTEXT_IPF) + 512]; + +// +// The PatchSaveBuffer is used to store the original bundles from the IVT where it is patched +// with the common handler. +// +UINT8 PatchSaveBuffer[0x400]; +UINTN ExternalInterruptCount; + +EFI_STATUS +plInitializeDebugSupportDriver ( + VOID + ) +/*++ + +Routine Description: + IPF specific DebugSupport driver initialization. Must be public because it's + referenced from DebugSupport.c + +Arguments: + +Returns: + + EFI_SUCCESS + +--*/ +{ + gBS->SetMem (IvtEntryTable, sizeof (IvtEntryTable), 0); + ExternalInterruptCount = 0; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +plUnloadDebugSupportDriver ( + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + Unload handler that is called during UnloadImage() - deallocates pool memory + used by the driver. Must be public because it's referenced from DebugSuport.c + +Arguments: + IN EFI_HANDLE ImageHandle + +Returns: + + EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered. + +--*/ +// TODO: ImageHandle - add argument and description to function comment +{ + EFI_EXCEPTION_TYPE ExceptionType; + + for (ExceptionType = 0; ExceptionType < NUM_IVT_ENTRIES; ExceptionType++) { + ManageIvtEntryTable (ExceptionType, NULL, NULL); + } + + return EFI_SUCCESS; +} + +VOID +CommonHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EFI_SYSTEM_CONTEXT Context + ) +/*++ + +Routine Description: + C routine that is called for all registered exceptions. This is the main + exception dispatcher. Must be public because it's referenced from AsmFuncs.s. + +Arguments: + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EFI_SYSTEM_CONTEXT Context + +Returns: + + Nothing + +--*/ +// TODO: ExceptionType - add argument and description to function comment +// TODO: Context - add argument and description to function comment +{ + static BOOLEAN InHandler = FALSE; + + DEBUG_CODE ( + if (InHandler) { + EfiDebugPrint (EFI_D_GENERIC, "ERROR: Re-entered debugger!\n" + " ExceptionType == %X\n" + " Context == %X\n" + " Context.SystemContextIpf->CrIip == %X\n" + " Context.SystemContextIpf->CrIpsr == %X\n" + " InHandler == %X\n", + ExceptionType, + Context, + Context.SystemContextIpf->CrIip, + Context.SystemContextIpf->CrIpsr, + InHandler); + } + ) + ASSERT (!InHandler); + InHandler = TRUE; + if (IvtEntryTable[ExceptionType].RegisteredCallback != NULL) { + if (ExceptionType != EXCEPT_IPF_EXTERNAL_INTERRUPT) { + IvtEntryTable[ExceptionType].RegisteredCallback (ExceptionType, Context.SystemContextIpf); + } else { + IvtEntryTable[ExceptionType].RegisteredCallback (Context.SystemContextIpf); + } + } else { + ASSERT (0); + } + + InHandler = FALSE; +} + +STATIC +VOID +GetHandlerEntryPoint ( + UINTN HandlerIndex, + VOID **EntryPoint + ) +/*++ + +Routine Description: + Given an integer number, return the physical address of the entry point in the IFT + +Arguments: + UINTN HandlerIndex, + VOID ** EntryPoint + +Returns: + + Nothing + +--*/ +// TODO: HandlerIndex - add argument and description to function comment +// TODO: EntryPoint - add argument and description to function comment +{ + UINT8 *TempPtr; + + // + // get base address of IVT + // + TempPtr = GetIva (); + + if (HandlerIndex < 20) { + // + // first 20 provide 64 bundles per vector + // + TempPtr += 0x400 * HandlerIndex; + } else { + // + // the rest provide 16 bundles per vector + // + TempPtr += 0x5000 + 0x100 * (HandlerIndex - 20); + } + + *EntryPoint = (VOID *) TempPtr; +} + +STATIC +EFI_STATUS +ManageIvtEntryTable ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN BUNDLE NewBundles[NUM_BUNDLES_IN_STUB], + IN VOID (*NewCallback) () + ) +/*++ + +Routine Description: + This is the worker function that installs and removes all handlers + +Arguments: + IN EFI_EXCEPTION_TYPE ExceptionType, + IN BUNDLE NewBundles[NUM_BUNDLES_IN_STUB], + IN VOID (*NewCallback) () + +Returns: + + EFI_STATUS - any return other than EFI_SUCCESS indicates the request was not + satisfied. + +--*/ +// TODO: ExceptionType - add argument and description to function comment +// TODO: ] - add argument and description to function comment +// TODO: ) - add argument and description to function comment +// TODO: EFI_ALREADY_STARTED - add return value to function comment +{ + BUNDLE *B0Ptr; + UINT64 InterruptFlags; + EFI_TPL OldTpl; + + // + // Get address of bundle 0 + // + GetHandlerEntryPoint (ExceptionType, (VOID **) &B0Ptr); + + if (IvtEntryTable[ExceptionType].RegisteredCallback != NULL) { + // + // we've already installed to this vector + // + if (NewCallback != NULL) { + // + // if the input handler is non-null, error + // + return EFI_ALREADY_STARTED; + } else { + // + // else remove the previously installed handler + // + OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + InterruptFlags = ProgramInterruptFlags (DISABLE_INTERRUPTS); + if (ExceptionType == EXCEPT_IPF_EXTERNAL_INTERRUPT) { + UnchainExternalInterrupt (); + } else { + UnhookEntry (ExceptionType); + } + + ProgramInterruptFlags (InterruptFlags); + gBS->RestoreTPL (OldTpl); + // + // re-init IvtEntryTable + // + gBS->SetMem (&IvtEntryTable[ExceptionType], sizeof (IVT_ENTRY), 0); + } + } else { + // + // no user handler installed on this vector + // + if (NewCallback != NULL) { + OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + InterruptFlags = ProgramInterruptFlags (DISABLE_INTERRUPTS); + if (ExceptionType == EXCEPT_IPF_EXTERNAL_INTERRUPT) { + ChainExternalInterrupt (NewCallback); + } else { + HookEntry (ExceptionType, NewBundles, NewCallback); + } + + ProgramInterruptFlags (InterruptFlags); + gBS->RestoreTPL (OldTpl); + } + } + + return EFI_SUCCESS; +} + +STATIC +VOID +HookEntry ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN BUNDLE NewBundles[4], + IN VOID (*NewCallback) () + ) +/*++ + +Routine Description: + Saves original IVT contents and inserts a few new bundles which are fixed up + to store the ExceptionType and then call the common handler. + +Arguments: + IN EFI_EXCEPTION_TYPE ExceptionType, + IN BUNDLE NewBundles[4], + IN VOID (*NewCallback) () + +Returns: + + Nothing + +--*/ +// TODO: ExceptionType - add argument and description to function comment +// TODO: ] - add argument and description to function comment +// TODO: ) - add argument and description to function comment +{ + BUNDLE *FixupBundle; + BUNDLE *B0Ptr; + + // + // Get address of bundle 0 + // + GetHandlerEntryPoint (ExceptionType, (VOID **) &B0Ptr); + + // + // copy original bundles from IVT to IvtEntryTable so we can restore them later + // + gBS->CopyMem ( + IvtEntryTable[ExceptionType].OrigBundles, + B0Ptr, + sizeof (BUNDLE) * NUM_BUNDLES_IN_STUB + ); + // + // insert new B0 + // + gBS->CopyMem (B0Ptr, NewBundles, sizeof (BUNDLE) * NUM_BUNDLES_IN_STUB); + + // + // fixup IVT entry so it stores its index and whether or not to chain... + // + FixupBundle = B0Ptr + 2; + FixupBundle->high |= ExceptionType << 36; + + InstructionCacheFlush (B0Ptr, 5); + IvtEntryTable[ExceptionType].RegisteredCallback = NewCallback; +} + +STATIC +VOID +UnhookEntry ( + IN EFI_EXCEPTION_TYPE ExceptionType + ) +/*++ + +Routine Description: + Restores original IVT contents when unregistering a callback function + +Arguments: + IN EFI_EXCEPTION_TYPE ExceptionType, + +Returns: + + Nothing + +--*/ +// TODO: ExceptionType - add argument and description to function comment +{ + BUNDLE *B0Ptr; + + // + // Get address of bundle 0 + // + GetHandlerEntryPoint (ExceptionType, (VOID **) &B0Ptr); + // + // restore original bundles in IVT + // + gBS->CopyMem ( + B0Ptr, + IvtEntryTable[ExceptionType].OrigBundles, + sizeof (BUNDLE) * NUM_BUNDLES_IN_STUB + ); + InstructionCacheFlush (B0Ptr, 5); +} + +STATIC +VOID +ChainExternalInterrupt ( + IN VOID (*NewCallback) () + ) +/*++ + +Routine Description: + Sets up cache flush and calls assembly function to chain external interrupt. + Records new callback in IvtEntryTable. + +Arguments: + IN VOID (*NewCallback) () + +Returns: + + Nothing + +--*/ +// TODO: ) - add argument and description to function comment +{ + VOID *Start; + + Start = (VOID *) ((UINT8 *) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT + 0x400); + IvtEntryTable[EXCEPT_IPF_EXTERNAL_INTERRUPT].RegisteredCallback = NewCallback; + ChainHandler (); + InstructionCacheFlush (Start, 0x400); +} + +STATIC +VOID +UnchainExternalInterrupt ( + VOID + ) +/*++ + +Routine Description: + Sets up cache flush and calls assembly function to restore external interrupt. + Removes registered callback from IvtEntryTable. + +Arguments: + Nothing + +Returns: + + Nothing + +--*/ +{ + VOID *Start; + + Start = (VOID *) ((UINT8 *) GetIva () + 0x400 * EXCEPT_IPF_EXTERNAL_INTERRUPT + 0x400); + UnchainHandler (); + InstructionCacheFlush (Start, 0x400); + IvtEntryTable[EXCEPT_IPF_EXTERNAL_INTERRUPT].RegisteredCallback = NULL; +} + +// +// The rest of the functions in this file are all member functions for the +// DebugSupport protocol +// + +EFI_STATUS +EFIAPI +GetMaximumProcessorIndex ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex + ) +/*++ + +Routine Description: This is a DebugSupport protocol member function. Hard + coded to support only 1 processor for now. + +Arguments: + +Returns: Always returns EFI_SUCCESS with *MaxProcessorIndex set to 0 + +--*/ +// TODO: This - add argument and description to function comment +// TODO: MaxProcessorIndex - add argument and description to function comment +{ + *MaxProcessorIndex = 0; + return (EFI_SUCCESS); +} + +EFI_STATUS +EFIAPI +RegisterPeriodicCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK NewPeriodicCallback + ) +/*++ + +Routine Description: + DebugSupport protocol member function + +Arguments: + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK NewPeriodicCallback + +Returns: + + EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered. + +--*/ +// TODO: This - add argument and description to function comment +// TODO: ProcessorIndex - add argument and description to function comment +// TODO: NewPeriodicCallback - add argument and description to function comment +{ + return ManageIvtEntryTable (EXCEPT_IPF_EXTERNAL_INTERRUPT, NULL, NewPeriodicCallback); +} + +EFI_STATUS +EFIAPI +RegisterExceptionCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK NewCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + ) +/*++ + +Routine Description: + DebugSupport protocol member function + +Arguments: + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN EFI_EXCEPTION_CALLBACK NewCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + +Returns: + + EFI_STATUS - anything other than EFI_SUCCESS indicates the callback was not registered. + +--*/ +// TODO: This - add argument and description to function comment +// TODO: ProcessorIndex - add argument and description to function comment +// TODO: NewCallback - add argument and description to function comment +// TODO: ExceptionType - add argument and description to function comment +{ + return ManageIvtEntryTable ( + ExceptionType, + (BUNDLE *) ((EFI_PLABEL *) HookStub)->EntryPoint, + NewCallback + ); +} + +EFI_STATUS +EFIAPI +InvalidateInstructionCache ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINTN Length + ) +/*++ + +Routine Description: + DebugSupport protocol member function. Calls assembly routine to flush cache. + +Arguments: + +Returns: + EFI_SUCCESS + +--*/ +// TODO: This - add argument and description to function comment +// TODO: ProcessorIndex - add argument and description to function comment +// TODO: Start - add argument and description to function comment +// TODO: Length - add argument and description to function comment +{ + InstructionCacheFlush (Start, Length); + return (EFI_SUCCESS); +} diff --git a/EdkModulePkg/Universal/Debugger/Debugport/Dxe/ComponentName.c b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/ComponentName.c new file mode 100644 index 0000000000..078bdab54d --- /dev/null +++ b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/ComponentName.c @@ -0,0 +1,108 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + ComponentName.c + +Abstract: + Component name protocol member functions for DebugPort... + +--*/ + +#include "DebugPort.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gDebugPortComponentName = { + DebugPortComponentNameGetDriverName, + DebugPortComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mDebugPortDriverNameTable[] = { + { + "eng", + (CHAR16 *) L"DebugPort Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +DebugPortComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gDebugPortComponentName.SupportedLanguages, + mDebugPortDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +DebugPortComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + The debug port driver does not support GetControllerName, so this function + is just stubbed and returns EFI_UNSUPPORTED. + + Arguments: + Per EFI 1.10 driver model + + Returns: + EFI_UNSUPPORTED + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.c b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.c new file mode 100644 index 0000000000..a24bfd06d5 --- /dev/null +++ b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.c @@ -0,0 +1,833 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugPort.c + +Abstract: + + Top level C file for debugport driver. Contains initialization function. + This driver layers on top of SerialIo. + + ALL CODE IN THE SERIALIO STACK MUST BE RE-ENTRANT AND CALLABLE FROM + INTERRUPT CONTEXT. + +Revision History + +--*/ + + +#include "DebugPort.h" + +// +// Misc. functions local to this module +// +STATIC +VOID +GetDebugPortVariable ( + DEBUGPORT_DEVICE *DebugPortDevice + ); + +EFI_STATUS +EFIAPI +ImageUnloadHandler ( + EFI_HANDLE ImageHandle + ); + +// +// Globals +// + +EFI_DRIVER_BINDING_PROTOCOL gDebugPortDriverBinding = { + DebugPortSupported, + DebugPortStart, + DebugPortStop, + DEBUGPORT_DRIVER_VERSION, + NULL, + NULL +}; + +DEBUGPORT_DEVICE *gDebugPortDevice; +static UINT32 mHid16550; +static UINT32 mHidStdPcComPort; + +// +// implementation code +// + +EFI_STATUS +EFIAPI +InitializeDebugPortDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Driver entry point. Reads DebugPort variable to determine what device and settings + to use as the debug port. Binds exclusively to SerialIo. Reverts to defaults \ + if no variable is found. + + Creates debugport and devicepath protocols on new handle. + +Arguments: + ImageHandle, + SystemTable + +Returns: + + EFI_UNSUPPORTED + EFI_OUT_OF_RESOURCES + +--*/ +{ + mHid16550 = EFI_ACPI_16550UART_HID; + mHidStdPcComPort = EFI_ACPI_PC_COMPORT_HID; + + // + // Allocate and Initialize dev structure + // + gDebugPortDevice = AllocateZeroPool (sizeof (DEBUGPORT_DEVICE)); + if (gDebugPortDevice == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Fill in static and default pieces of device structure first. + // + gDebugPortDevice->Signature = DEBUGPORT_DEVICE_SIGNATURE; + + gDebugPortDevice->DebugPortInterface.Reset = DebugPortReset; + gDebugPortDevice->DebugPortInterface.Read = DebugPortRead; + gDebugPortDevice->DebugPortInterface.Write = DebugPortWrite; + gDebugPortDevice->DebugPortInterface.Poll = DebugPortPoll; + + gDebugPortDevice->BaudRate = DEBUGPORT_UART_DEFAULT_BAUDRATE; + gDebugPortDevice->ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH; + gDebugPortDevice->Timeout = DEBUGPORT_UART_DEFAULT_TIMEOUT; + gDebugPortDevice->Parity = DEBUGPORT_UART_DEFAULT_PARITY; + gDebugPortDevice->DataBits = DEBUGPORT_UART_DEFAULT_DATA_BITS; + gDebugPortDevice->StopBits = DEBUGPORT_UART_DEFAULT_STOP_BITS; + + return EFI_SUCCESS; +} +// +// DebugPort driver binding member functions... +// +EFI_STATUS +EFIAPI +DebugPortSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Checks to see that there's not already a DebugPort interface somewhere. If so, + fail. + + If there's a DEBUGPORT variable, the device path must match exactly. If there's + no DEBUGPORT variable, then device path is not checked and does not matter. + + Checks to see that there's a serial io interface on the controller handle + that can be bound BY_DRIVER | EXCLUSIVE. + + If all these tests succeed, then we return EFI_SUCCESS, else, EFI_UNSUPPORTED + or other error returned by OpenProtocol. + +Arguments: + This + ControllerHandle + RemainingDevicePath + +Returns: + EFI_UNSUPPORTED + EFI_OUT_OF_RESOURCES + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *Dp1; + EFI_DEVICE_PATH_PROTOCOL *Dp2; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEBUGPORT_PROTOCOL *DebugPortInterface; + EFI_HANDLE TempHandle; + + // + // Check to see that there's not a debugport protocol already published + // + if (gBS->LocateProtocol (&gEfiDebugPortProtocolGuid, NULL, (VOID **) &DebugPortInterface) != EFI_NOT_FOUND) { + return EFI_UNSUPPORTED; + } + // + // Read DebugPort variable to determine debug port selection and parameters + // + GetDebugPortVariable (gDebugPortDevice); + + if (gDebugPortDevice->DebugPortVariable != NULL) { + // + // There's a DEBUGPORT variable, so do LocateDevicePath and check to see if + // the closest matching handle matches the controller handle, and if it does, + // check to see that the remaining device path has the DebugPort GUIDed messaging + // device path only. Otherwise, it's a mismatch and EFI_UNSUPPORTED is returned. + // + Dp1 = DuplicateDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) gDebugPortDevice->DebugPortVariable); + if (Dp1 == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Dp2 = Dp1; + + Status = gBS->LocateDevicePath ( + &gEfiSerialIoProtocolGuid, + &Dp2, + &TempHandle + ); + + if (Status == EFI_SUCCESS && TempHandle != ControllerHandle) { + Status = EFI_UNSUPPORTED; + } + + if (Status == EFI_SUCCESS && (Dp2->Type != 3 || Dp2->SubType != 10 || *((UINT16 *) Dp2->Length) != 20)) { + Status = EFI_UNSUPPORTED; + } + + if (Status == EFI_SUCCESS && CompareMem (&gEfiDebugPortDevicePathGuid, Dp2 + 1, sizeof (EFI_GUID))) { + Status = EFI_UNSUPPORTED; + } + + gBS->FreePool (Dp1); + if (EFI_ERROR (Status)) { + return Status; + } + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSerialIoProtocolGuid, + (VOID **) &SerialIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DebugPortStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Binds exclusively to serial io on the controller handle. Produces DebugPort + protocol and DevicePath on new handle. + +Arguments: + This + ControllerHandle + RemainingDevicePath + +Returns: + EFI_OUT_OF_RESOURCES + EFI_SUCCESS +--*/ +{ + EFI_STATUS Status; + DEBUGPORT_DEVICE_PATH DebugPortDP; + EFI_DEVICE_PATH_PROTOCOL EndDP; + EFI_DEVICE_PATH_PROTOCOL *Dp1; + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSerialIoProtocolGuid, + (VOID **) &gDebugPortDevice->SerialIoBinding, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gDebugPortDevice->SerialIoDeviceHandle = ControllerHandle; + + // + // Initialize the Serial Io interface... + // + Status = gDebugPortDevice->SerialIoBinding->SetAttributes ( + gDebugPortDevice->SerialIoBinding, + gDebugPortDevice->BaudRate, + gDebugPortDevice->ReceiveFifoDepth, + gDebugPortDevice->Timeout, + gDebugPortDevice->Parity, + gDebugPortDevice->DataBits, + gDebugPortDevice->StopBits + ); + if (EFI_ERROR (Status)) { + gDebugPortDevice->BaudRate = 0; + gDebugPortDevice->Parity = DefaultParity; + gDebugPortDevice->DataBits = 0; + gDebugPortDevice->StopBits = DefaultStopBits; + gDebugPortDevice->ReceiveFifoDepth = 0; + Status = gDebugPortDevice->SerialIoBinding->SetAttributes ( + gDebugPortDevice->SerialIoBinding, + gDebugPortDevice->BaudRate, + gDebugPortDevice->ReceiveFifoDepth, + gDebugPortDevice->Timeout, + gDebugPortDevice->Parity, + gDebugPortDevice->DataBits, + gDebugPortDevice->StopBits + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + } + } + + gDebugPortDevice->SerialIoBinding->Reset (gDebugPortDevice->SerialIoBinding); + + // + // Create device path instance for DebugPort + // + DebugPortDP.Header.Type = MESSAGING_DEVICE_PATH; + DebugPortDP.Header.SubType = MSG_VENDOR_DP; + SetDevicePathNodeLength (&(DebugPortDP.Header), sizeof (DebugPortDP)); + gBS->CopyMem (&DebugPortDP.Guid, &gEfiDebugPortDevicePathGuid, sizeof (EFI_GUID)); + + Dp1 = DevicePathFromHandle (ControllerHandle); + if (Dp1 == NULL) { + Dp1 = &EndDP; + SetDevicePathEndNode (Dp1); + } + + gDebugPortDevice->DebugPortDevicePath = AppendDevicePathNode (Dp1, (EFI_DEVICE_PATH_PROTOCOL *) &DebugPortDP); + if (gDebugPortDevice->DebugPortDevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Publish DebugPort and Device Path protocols + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &gDebugPortDevice->DebugPortDeviceHandle, + &gEfiDevicePathProtocolGuid, + gDebugPortDevice->DebugPortDevicePath, + &gEfiDebugPortProtocolGuid, + &gDebugPortDevice->DebugPortInterface, + NULL + ); + + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + } + // + // Connect debugport child to serial io + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSerialIoProtocolGuid, + (VOID **) &gDebugPortDevice->SerialIoBinding, + This->DriverBindingHandle, + gDebugPortDevice->DebugPortDeviceHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + + if (EFI_ERROR (Status)) { + DEBUG_CODE ( + UINTN BufferSize; + + BufferSize = 48; + DebugPortWrite ( + &gDebugPortDevice->DebugPortInterface, + 0, + &BufferSize, + "DebugPort driver failed to open child controller\n\n" + ); + ); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + } + + DEBUG_CODE ( + UINTN BufferSize; + + BufferSize = 38; + DebugPortWrite ( + &gDebugPortDevice->DebugPortInterface, + 0, + &BufferSize, + "Hello World from the DebugPort driver\n\n" + ); + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DebugPortStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + We're never intending to be stopped via the driver model so this just returns + EFI_UNSUPPORTED + +Arguments: + Per EFI 1.10 driver model + +Returns: + EFI_UNSUPPORTED + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + gDebugPortDevice->SerialIoBinding = NULL; + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + gBS->FreePool (gDebugPortDevice->DebugPortDevicePath); + + return EFI_SUCCESS; + } else { + // + // Disconnect SerialIo child handle + // + Status = gBS->CloseProtocol ( + gDebugPortDevice->SerialIoDeviceHandle, + &gEfiSerialIoProtocolGuid, + This->DriverBindingHandle, + gDebugPortDevice->DebugPortDeviceHandle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Unpublish our protocols (DevicePath, DebugPort) + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + gDebugPortDevice->DebugPortDeviceHandle, + &gEfiDevicePathProtocolGuid, + gDebugPortDevice->DebugPortDevicePath, + &gEfiDebugPortProtocolGuid, + &gDebugPortDevice->DebugPortInterface, + NULL + ); + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + ControllerHandle, + &gEfiSerialIoProtocolGuid, + (VOID **) &gDebugPortDevice->SerialIoBinding, + This->DriverBindingHandle, + gDebugPortDevice->DebugPortDeviceHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + gDebugPortDevice->DebugPortDeviceHandle = NULL; + } + } + + return Status; +} +// +// Debugport protocol member functions +// +EFI_STATUS +EFIAPI +DebugPortReset ( + IN EFI_DEBUGPORT_PROTOCOL *This + ) +/*++ + +Routine Description: + DebugPort protocol member function. Calls SerialIo:GetControl to flush buffer. + We cannot call SerialIo:SetAttributes because it uses pool services, which use + locks, which affect TPL, so it's not interrupt context safe or re-entrant. + SerialIo:Reset() calls SetAttributes, so it can't be used either. + + The port itself should be fine since it was set up during initialization. + +Arguments: + This + +Returns: + + EFI_SUCCESS + +--*/ +{ + DEBUGPORT_DEVICE *DebugPortDevice; + UINTN BufferSize; + UINTN BitBucket; + + DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This); + while (This->Poll (This) == EFI_SUCCESS) { + BufferSize = 1; + This->Read (This, 0, &BufferSize, &BitBucket); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DebugPortRead ( + IN EFI_DEBUGPORT_PROTOCOL *This, + IN UINT32 Timeout, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + DebugPort protocol member function. Calls SerialIo:Read() after setting + if it's different than the last SerialIo access. + +Arguments: + IN EFI_DEBUGPORT_PROTOCOL *This + IN UINT32 Timeout, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + +Returns: + + EFI_STATUS + +--*/ +{ + DEBUGPORT_DEVICE *DebugPortDevice; + UINTN LocalBufferSize; + EFI_STATUS Status; + UINT8 *BufferPtr; + + DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This); + BufferPtr = Buffer; + LocalBufferSize = *BufferSize; + do { + Status = DebugPortDevice->SerialIoBinding->Read ( + DebugPortDevice->SerialIoBinding, + &LocalBufferSize, + BufferPtr + ); + if (Status == EFI_TIMEOUT) { + if (Timeout > DEBUGPORT_UART_DEFAULT_TIMEOUT) { + Timeout -= DEBUGPORT_UART_DEFAULT_TIMEOUT; + } else { + Timeout = 0; + } + } else if (EFI_ERROR (Status)) { + break; + } + + BufferPtr += LocalBufferSize; + LocalBufferSize = *BufferSize - (BufferPtr - (UINT8 *) Buffer); + } while (LocalBufferSize != 0 && Timeout > 0); + + *BufferSize = (UINTN) (BufferPtr - (UINT8 *) Buffer); + + return Status; +} + +EFI_STATUS +EFIAPI +DebugPortWrite ( + IN EFI_DEBUGPORT_PROTOCOL *This, + IN UINT32 Timeout, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + DebugPort protocol member function. Calls SerialIo:Write() Writes 8 bytes at + a time and does a GetControl between 8 byte writes to help insure reads are + interspersed This is poor-man's flow control.. + +Arguments: + This - Pointer to DebugPort protocol + Timeout - Timeout value + BufferSize - On input, the size of Buffer. + On output, the amount of data actually written. + Buffer - Pointer to buffer to write + +Returns: + EFI_SUCCESS - The data was written. + EFI_DEVICE_ERROR - The device reported an error. + EFI_TIMEOUT - The data write was stopped due to a timeout. + +--*/ +{ + DEBUGPORT_DEVICE *DebugPortDevice; + UINTN Position; + UINTN WriteSize; + EFI_STATUS Status; + UINT32 SerialControl; + + Status = EFI_SUCCESS; + DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This); + + WriteSize = 8; + for (Position = 0; Position < *BufferSize && !EFI_ERROR (Status); Position += WriteSize) { + DebugPortDevice->SerialIoBinding->GetControl ( + DebugPortDevice->SerialIoBinding, + &SerialControl + ); + if (*BufferSize - Position < 8) { + WriteSize = *BufferSize - Position; + } + + Status = DebugPortDevice->SerialIoBinding->Write ( + DebugPortDevice->SerialIoBinding, + &WriteSize, + &((UINT8 *) Buffer)[Position] + ); + } + + *BufferSize = Position; + return Status; +} + +EFI_STATUS +EFIAPI +DebugPortPoll ( + IN EFI_DEBUGPORT_PROTOCOL *This + ) +/*++ + +Routine Description: + DebugPort protocol member function. Calls SerialIo:Write() after setting + if it's different than the last SerialIo access. + +Arguments: + IN EFI_DEBUGPORT_PROTOCOL *This + +Returns: + EFI_SUCCESS - At least 1 character is ready to be read from the DebugPort interface + EFI_NOT_READY - There are no characters ready to read from the DebugPort interface + EFI_DEVICE_ERROR - A hardware failure occured... (from SerialIo) + +--*/ +{ + EFI_STATUS Status; + UINT32 SerialControl; + DEBUGPORT_DEVICE *DebugPortDevice; + + DebugPortDevice = DEBUGPORT_DEVICE_FROM_THIS (This); + + Status = DebugPortDevice->SerialIoBinding->GetControl ( + DebugPortDevice->SerialIoBinding, + &SerialControl + ); + + if (!EFI_ERROR (Status)) { + if (SerialControl & EFI_SERIAL_INPUT_BUFFER_EMPTY) { + Status = EFI_NOT_READY; + } else { + Status = EFI_SUCCESS; + } + } + + return Status; +} +// +// Misc. functions local to this module.. +// +STATIC +VOID +GetDebugPortVariable ( + DEBUGPORT_DEVICE *DebugPortDevice + ) +/*++ + +Routine Description: + Local worker function to obtain device path information from DebugPort variable. + Records requested settings in DebugPort device structure. + +Arguments: + DEBUGPORT_DEVICE *DebugPortDevice, + +Returns: + + Nothing + +--*/ +{ + UINTN DataSize; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_STATUS Status; + + DataSize = 0; + + Status = gRT->GetVariable ( + (CHAR16 *) EFI_DEBUGPORT_VARIABLE_NAME, + &gEfiDebugPortVariableGuid, + NULL, + &DataSize, + DebugPortDevice->DebugPortVariable + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + if (gDebugPortDevice->DebugPortVariable != NULL) { + gBS->FreePool (gDebugPortDevice->DebugPortVariable); + } + + DebugPortDevice->DebugPortVariable = AllocatePool (DataSize); + if (DebugPortDevice->DebugPortVariable != NULL) { + gRT->GetVariable ( + (CHAR16 *) EFI_DEBUGPORT_VARIABLE_NAME, + &gEfiDebugPortVariableGuid, + NULL, + &DataSize, + DebugPortDevice->DebugPortVariable + ); + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) DebugPortDevice->DebugPortVariable; + while (!EfiIsDevicePathEnd (DevicePath) && !EfiIsUartDevicePath (DevicePath)) { + DevicePath = EfiNextDevicePathNode (DevicePath); + } + + if (EfiIsDevicePathEnd (DevicePath)) { + gBS->FreePool (gDebugPortDevice->DebugPortVariable); + DebugPortDevice->DebugPortVariable = NULL; + } else { + gBS->CopyMem ( + &DebugPortDevice->BaudRate, + &((UART_DEVICE_PATH *) DevicePath)->BaudRate, + sizeof (((UART_DEVICE_PATH *) DevicePath)->BaudRate) + ); + DebugPortDevice->ReceiveFifoDepth = DEBUGPORT_UART_DEFAULT_FIFO_DEPTH; + DebugPortDevice->Timeout = DEBUGPORT_UART_DEFAULT_TIMEOUT; + gBS->CopyMem ( + &DebugPortDevice->Parity, + &((UART_DEVICE_PATH *) DevicePath)->Parity, + sizeof (((UART_DEVICE_PATH *) DevicePath)->Parity) + ); + gBS->CopyMem ( + &DebugPortDevice->DataBits, + &((UART_DEVICE_PATH *) DevicePath)->DataBits, + sizeof (((UART_DEVICE_PATH *) DevicePath)->DataBits) + ); + gBS->CopyMem ( + &DebugPortDevice->StopBits, + &((UART_DEVICE_PATH *) DevicePath)->StopBits, + sizeof (((UART_DEVICE_PATH *) DevicePath)->StopBits) + ); + } + } + } +} + +EFI_STATUS +EFIAPI +ImageUnloadHandler ( + EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + Unload function that is registered in the LoadImage protocol. It un-installs + protocols produced and deallocates pool used by the driver. Called by the core + when unloading the driver. + +Arguments: + EFI_HANDLE ImageHandle + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + if (gDebugPortDevice->SerialIoBinding != NULL) { + return EFI_ABORTED; + } + + Status = gBS->UninstallMultipleProtocolInterfaces ( + ImageHandle, + &gEfiDriverBindingProtocolGuid, + &gDebugPortDevice->DriverBindingInterface, + &gEfiComponentNameProtocolGuid, + &gDebugPortDevice->ComponentNameInterface, + NULL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Clean up allocations + // + if (gDebugPortDevice->DebugPortVariable != NULL) { + gBS->FreePool (gDebugPortDevice->DebugPortVariable); + } + + gBS->FreePool (gDebugPortDevice); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.dxs b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.dxs new file mode 100644 index 0000000000..280931b5c0 --- /dev/null +++ b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.dxs @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugPort.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.h b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.h new file mode 100644 index 0000000000..bb486c3147 --- /dev/null +++ b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.h @@ -0,0 +1,172 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + DebugPort.h + +Abstract: + Definitions and prototypes for DebugPort driver + +--*/ + +#ifndef __DEBUGPORT_H__ +#define __DEBUGPORT_H__ + + +// +// local type definitions +// +#define DEBUGPORT_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('D', 'B', 'G', 'P') + +// +// Device structure used by driver +// +typedef struct { + UINT32 Signature; + EFI_HANDLE DriverBindingHandle; + EFI_HANDLE DebugPortDeviceHandle; + VOID *DebugPortVariable; + + EFI_DRIVER_BINDING_PROTOCOL DriverBindingInterface; + EFI_COMPONENT_NAME_PROTOCOL ComponentNameInterface; + EFI_DEVICE_PATH_PROTOCOL *DebugPortDevicePath; + EFI_DEBUGPORT_PROTOCOL DebugPortInterface; + + EFI_HANDLE SerialIoDeviceHandle; + EFI_SERIAL_IO_PROTOCOL *SerialIoBinding; + UINT64 BaudRate; + UINT32 ReceiveFifoDepth; + UINT32 Timeout; + EFI_PARITY_TYPE Parity; + UINT8 DataBits; + EFI_STOP_BITS_TYPE StopBits; +} DEBUGPORT_DEVICE; + +#define DEBUGPORT_DEVICE_FROM_THIS(a) CR (a, DEBUGPORT_DEVICE, DebugPortInterface, DEBUGPORT_DEVICE_SIGNATURE) + +#define EFI_ACPI_PC_COMPORT_HID EISA_PNP_ID (0x0500) +#define EFI_ACPI_16550UART_HID EISA_PNP_ID (0x0501) + +#define DEBUGPORT_UART_DEFAULT_BAUDRATE 115200 +#define DEBUGPORT_UART_DEFAULT_PARITY 0 +#define DEBUGPORT_UART_DEFAULT_FIFO_DEPTH 16 +#define DEBUGPORT_UART_DEFAULT_TIMEOUT 50000 // 5 ms +#define DEBUGPORT_UART_DEFAULT_DATA_BITS 8 +#define DEBUGPORT_UART_DEFAULT_STOP_BITS 1 + +#define DEBUGPORT_DRIVER_VERSION 1 + +#define EfiIsUartDevicePath(dp) (DevicePathType (dp) == MESSAGING_DEVICE_PATH && DevicePathSubType (dp) == MSG_UART_DP) + +// +// globals +// +extern DEBUGPORT_DEVICE *gDebugPortDevice; + +// +// Driver binding interface functions... +// +EFI_STATUS +DebugPortEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +EFI_STATUS +EFIAPI +DebugPortSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +EFIAPI +DebugPortStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +; + +EFI_STATUS +EFIAPI +DebugPortStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +; + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +DebugPortComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +; + +EFI_STATUS +EFIAPI +DebugPortComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +; + +// +// DebugPort member functions +// +EFI_STATUS +EFIAPI +DebugPortReset ( + IN EFI_DEBUGPORT_PROTOCOL *This + ) +; + +EFI_STATUS +EFIAPI +DebugPortRead ( + IN EFI_DEBUGPORT_PROTOCOL *This, + IN UINT32 Timeout, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +; + +EFI_STATUS +EFIAPI +DebugPortWrite ( + IN EFI_DEBUGPORT_PROTOCOL *This, + IN UINT32 Timeout, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +; + +EFI_STATUS +EFIAPI +DebugPortPoll ( + IN EFI_DEBUGPORT_PROTOCOL *This + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.mbd b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.mbd new file mode 100644 index 0000000000..62abeee2d6 --- /dev/null +++ b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.mbd @@ -0,0 +1,46 @@ + + + + + DebugPort + 73E9457A-CEA1-4917-9A9C-9F1F0F0FD322 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + DxeMemoryAllocationLib + UefiDevicePathLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.msa b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.msa new file mode 100644 index 0000000000..6762026c3f --- /dev/null +++ b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/DebugPort.msa @@ -0,0 +1,77 @@ + + + + + DebugPort + UEFI_DRIVER + BS_DRIVER + 73E9457A-CEA1-4917-9A9C-9F1F0F0FD322 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DevicePathLib + + + DebugPort.h + DebugPort.c + ComponentName.c + DebugPort.dxs + + + MdePkg + EdkModulePkg + + + DebugPort + DevicePath + SerialIo + + + + DEBUGPORT + 0xEBA4E8D2, 0x3858, 0x41EC, 0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 + + + + + InitializeDebugPortDriver + ImageUnloadHandler + + + gDebugPortDriverBinding + gDebugPortComponentName + + + diff --git a/EdkModulePkg/Universal/Debugger/Debugport/Dxe/build.xml b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/build.xml new file mode 100644 index 0000000000..89b603c257 --- /dev/null +++ b/EdkModulePkg/Universal/Debugger/Debugport/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/ComponentName.c b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/ComponentName.c new file mode 100644 index 0000000000..35ca70d8f8 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/ComponentName.c @@ -0,0 +1,160 @@ + /*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "DiskIo.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +DiskIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +DiskIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gDiskIoComponentName = { + DiskIoComponentNameGetDriverName, + DiskIoComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mDiskIoDriverNameTable[] = { + { + "eng", + (CHAR16 *)L"Generic Disk I/O Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +DiskIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gDiskIoComponentName.SupportedLanguages, + mDiskIoDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +DiskIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.mbd b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.mbd new file mode 100644 index 0000000000..087bedf5bb --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.mbd @@ -0,0 +1,41 @@ + + + + + DiskIo + 6B38F7B4-AD98-40e9-9093-ACA2B5A253C4 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.msa b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.msa new file mode 100644 index 0000000000..2ddc5233f2 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/DiskIo.msa @@ -0,0 +1,65 @@ + + + + + DiskIo + UEFI_DRIVER + BS_DRIVER + 6B38F7B4-AD98-40e9-9093-ACA2B5A253C4 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + diskio.c + diskio.h + ComponentName.c + + + MdePkg + + + BlockIo + DiskIo + + + + + + + gDiskIoDriverBinding + gDiskIoComponentName + + + diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/build.xml b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/build.xml new file mode 100644 index 0000000000..8a6ff7b7bc --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.c b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.c new file mode 100644 index 0000000000..4998c9b0f7 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.c @@ -0,0 +1,876 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DiskIo.c + +Abstract: + + DiskIo driver that layers it's self on every Block IO protocol in the system. + DiskIo converts a block oriented device to a byte oriented device. + + ReadDisk may have to do reads that are not aligned on sector boundaries. + There are three cases: + + UnderRun - The first byte is not on a sector boundary or the read request is + less than a sector in length. + + Aligned - A read of N contiguous sectors. + + OverRun - The last byte is not on a sector boundary. + +--*/ + +#include "DiskIo.h" + +// +// Prototypes +// Driver model protocol interface +// +EFI_STATUS +EFIAPI +DiskIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +DiskIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +DiskIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Disk I/O Protocol Interface +// +EFI_STATUS +EFIAPI +DiskIoReadDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +DiskIoWriteDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + IN VOID *Buffer + ); + +EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding = { + DiskIoDriverBindingSupported, + DiskIoDriverBindingStart, + DiskIoDriverBindingStop, + 0x10, + NULL, + NULL +}; + +DISK_IO_PRIVATE_DATA gDiskIoPrivateDataTemplate = { + DISK_IO_PRIVATE_DATA_SIGNATURE, + { + EFI_DISK_IO_PROTOCOL_REVISION, + DiskIoReadDisk, + DiskIoWriteDisk + }, + NULL +}; + +EFI_STATUS +EFIAPI +DiskIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a BlockIo protocol can be supported. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to test. + RemainingDevicePath - Not used. + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_ALREADY_STARTED - This driver is already running on this device. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; +/* + DEBUG_CODE_BEGIN + UINT32 Bar; + UINT32 Foo; + UINT32 HotPlug; + + // + // Get TYPE 0 + // + Bar = PcdGet32 (PciExpressBaseVersion); + DEBUG ((EFI_D_ERROR, "PciExpressBaseVersion = %08x\n", Bar)); + + // + // Get TYPE 1 + // + Foo = PcdGet32 (PciExpressBaseAddress); + DEBUG ((EFI_D_ERROR, "PciExpressBaseAddress = %08x\n", Foo)); + + // + // Set TYPE 1 + // + PcdSet32 (PciExpressBaseAddress, Foo + 1); + + // + // Get TYPE 1 + // + Foo = PcdGet32 (PciExpressBaseAddress); + DEBUG ((EFI_D_ERROR, "PciExpressBaseAddress = %08x\n", Foo)); + + // + // Get TYPE 2 + // + HotPlug = PcdGet32 (PciExpressBaseHotPlug); + DEBUG ((EFI_D_ERROR, "PciExpressHotPlug = %08x\n", HotPlug)); + + // + // Set TYPE 1 + // + PcdSet32 (PciExpressBaseHotPlug, HotPlug + 1); + + // + // Get TYPE 1 + // + HotPlug = PcdGet32 (PciExpressBaseHotPlug); + DEBUG ((EFI_D_ERROR, "PciExpressHotPlug = %08x\n", HotPlug)); + + DEBUG_CODE_END + + DEBUG_CODE_BEGIN + UINT32 MyVariable; + + if (ControllerHandle == NULL) { + MyVariable = 32 * (UINTN)This; + ControllerHandle = (EFI_HANDLE)MyVariable; + DEBUG ((EFI_D_ERROR, "DiskIoSupported-DebugCode. MyVariable = %08x\n", MyVariable)); + ASSERT (MyVariable != 32); + } + DEBUG_CODE_END +*/ + DEBUG ((EFI_D_ERROR, "DiskIoSupported\n")); + +// Io8Or (0x400, 1); +// Io8And (0x400, 1); +// Io8AndThenOr (0x400, 1, 2); + +// Mmio8Or (0xa0000000, 1); +// Mmio8And (0xa0000000, 1); +// Mmio8AndThenOr (0xa0000000, 1, 2); + +/* + PciRead8 (PCI_LIB_ADDRESS (1,2,3,4)); + PciRead16 (PCI_LIB_ADDRESS (1,2,3,4)); + PciRead32 (PCI_LIB_ADDRESS (1,2,3,4)); + + PciWrite8 (PCI_LIB_ADDRESS (1,2,3,4), 0xAA); + PciWrite16 (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55); + PciWrite32 (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55A55A); + + Pci8Or (PCI_LIB_ADDRESS (1,2,3,4), 0xAA); + Pci8And (PCI_LIB_ADDRESS (1,2,3,4), 0x55); + Pci8AndThenOr (PCI_LIB_ADDRESS (1,2,3,4), 0xAA, 0x55); + + Pci16Or (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55); + Pci16And (PCI_LIB_ADDRESS (1,2,3,4), 0x55AA); + Pci16AndThenOr (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55, 0x55AA); + + Pci32Or (PCI_LIB_ADDRESS (1,2,3,4), 0xAA55A55A); + Pci32And (PCI_LIB_ADDRESS (1,2,3,4), 0x55AA5AA5); + Pci32AndThenOr (PCI_LIB_ADDRESS (1,2,3,4), 0xAA555AA5, 0x55AAA55A); +*/ + // + // Open the IO Abstraction(s) needed to perform the supported test. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the I/O Abstraction(s) used to perform the supported test. + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DiskIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +/*++ + + Routine Description: + Start this driver on ControllerHandle by opening a Block IO protocol and + installing a Disk IO protocol on ControllerHandle. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to bind driver to. + RemainingDevicePath - Not used, always produce all possible children. + + Returns: + EFI_SUCCESS - This driver is added to ControllerHandle. + EFI_ALREADY_STARTED - This driver is already running on ControllerHandle. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + DISK_IO_PRIVATE_DATA *Private; + + Private = NULL; + + DEBUG ((EFI_D_ERROR, "DiskIoStart\n")); + // + // Connect to the Block IO interface on ControllerHandle. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &gDiskIoPrivateDataTemplate.BlockIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Initialize the Disk IO device instance. + // + Private = AllocateCopyPool (sizeof (DISK_IO_PRIVATE_DATA), &gDiskIoPrivateDataTemplate); + if (Private == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ErrorExit; + } + // + // Install protocol interfaces for the Disk IO device. + // + Status = gBS->InstallProtocolInterface ( + &ControllerHandle, + &gEfiDiskIoProtocolGuid, + EFI_NATIVE_INTERFACE, + &Private->DiskIo + ); + +ErrorExit: + if (EFI_ERROR (Status)) { + + if (Private != NULL) { + gBS->FreePool (Private); + } + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DiskIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle by removing Disk IO protocol and closing + the Block IO protocol on ControllerHandle. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to stop driver on. + NumberOfChildren - Not used. + ChildHandleBuffer - Not used. + + Returns: + EFI_SUCCESS - This driver is removed ControllerHandle. + other - This driver was not removed from this device. + EFI_UNSUPPORTED + +--*/ +{ + EFI_STATUS Status; + EFI_DISK_IO_PROTOCOL *DiskIo; + DISK_IO_PRIVATE_DATA *Private; + + DEBUG ((EFI_D_ERROR, "DiskIoStop\n")); + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = DISK_IO_PRIVATE_DATA_FROM_THIS (DiskIo); + + Status = gBS->UninstallProtocolInterface ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + &Private->DiskIo + ); + if (!EFI_ERROR (Status)) { + + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + + if (!EFI_ERROR (Status)) { + gBS->FreePool (Private); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DiskIoReadDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + + Routine Description: + Read BufferSize bytes from Offset into Buffer. + + Reads may support reads that are not aligned on + sector boundaries. There are three cases: + + UnderRun - The first byte is not on a sector boundary or the read request is + less than a sector in length. + + Aligned - A read of N contiguous sectors. + + OverRun - The last byte is not on a sector boundary. + + + Arguments: + This - Protocol instance pointer. + MediaId - Id of the media, changes every time the media is replaced. + Offset - The starting byte offset to read from. + BufferSize - Size of Buffer. + Buffer - Buffer containing read data. + + Returns: + EFI_SUCCESS - The data was read correctly from the device. + EFI_DEVICE_ERROR - The device reported an error while performing the read. + EFI_NO_MEDIA - There is no media in the device. + EFI_MEDIA_CHNAGED - The MediaId does not matched the current device. + EFI_INVALID_PARAMETER - The read request contains device addresses that are not + valid for the device. + EFI_OUT_OF_RESOURCES + +--*/ +{ + EFI_STATUS Status; + DISK_IO_PRIVATE_DATA *Private; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *Media; + UINT32 BlockSize; + UINT64 Lba; + UINT64 OverRunLba; + UINT32 UnderRun; + UINT32 OverRun; + BOOLEAN TransactionComplete; + UINTN WorkingBufferSize; + UINT8 *WorkingBuffer; + UINTN Length; + UINT8 *Data; + UINT8 *PreData; + UINTN IsBufferAligned; + UINTN DataBufferSize; + BOOLEAN LastRead; + + DEBUG ((EFI_D_ERROR, "DiskIoReadDisk\n")); + + Private = DISK_IO_PRIVATE_DATA_FROM_THIS (This); + + BlockIo = Private->BlockIo; + Media = BlockIo->Media; + BlockSize = Media->BlockSize; + + if (Media->MediaId != MediaId) { + return EFI_MEDIA_CHANGED; + } + + WorkingBuffer = Buffer; + WorkingBufferSize = BufferSize; + + // + // Allocate a temporary buffer for operation + // + DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM; + + if (Media->IoAlign > 1) { + PreData = AllocatePool (DataBufferSize + Media->IoAlign); + Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign; + } else { + PreData = AllocatePool (DataBufferSize); + Data = PreData; + } + + if (PreData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun); + + Length = BlockSize - UnderRun; + TransactionComplete = FALSE; + + Status = EFI_SUCCESS; + if (UnderRun != 0) { + // + // Offset starts in the middle of an Lba, so read the entire block. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Length > BufferSize) { + Length = BufferSize; + TransactionComplete = TRUE; + } + + CopyMem (WorkingBuffer, Data + UnderRun, Length); + + WorkingBuffer += Length; + + WorkingBufferSize -= Length; + if (WorkingBufferSize == 0) { + goto Done; + } + + Lba += 1; + } + + OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun); + + if (!TransactionComplete && WorkingBufferSize >= BlockSize) { + // + // If the DiskIo maps directly to a BlockIo device do the read. + // + if (OverRun != 0) { + WorkingBufferSize -= OverRun; + } + // + // Check buffer alignment + // + IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1); + + if (Media->IoAlign <= 1 || IsBufferAligned == 0) { + // + // Alignment is satisfied, so read them together + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + WorkingBufferSize, + WorkingBuffer + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBuffer += WorkingBufferSize; + + } else { + // + // Use the allocated buffer instead of the original buffer + // to avoid alignment issue. + // Here, the allocated buffer (8-byte align) can satisfy the alignment + // + LastRead = FALSE; + do { + if (WorkingBufferSize <= DataBufferSize) { + // + // It is the last calling to readblocks in this loop + // + DataBufferSize = WorkingBufferSize; + LastRead = TRUE; + } + + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + DataBufferSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (WorkingBuffer, Data, DataBufferSize); + WorkingBufferSize -= DataBufferSize; + WorkingBuffer += DataBufferSize; + Lba += DATA_BUFFER_BLOCK_NUM; + } while (!LastRead); + } + } + + if (!TransactionComplete && OverRun != 0) { + // + // Last read is not a complete block. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + OverRunLba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (WorkingBuffer, Data, OverRun); + } + +Done: + if (PreData != NULL) { + gBS->FreePool (PreData); + } + + return Status; +} + +EFI_STATUS +EFIAPI +DiskIoWriteDisk ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + + Routine Description: + Read BufferSize bytes from Offset into Buffer. + + Writes may require a read modify write to support writes that are not + aligned on sector boundaries. There are three cases: + + UnderRun - The first byte is not on a sector boundary or the write request + is less than a sector in length. Read modify write is required. + + Aligned - A write of N contiguous sectors. + + OverRun - The last byte is not on a sector boundary. Read modified write + required. + + Arguments: + This - Protocol instance pointer. + MediaId - Id of the media, changes every time the media is replaced. + Offset - The starting byte offset to read from. + BufferSize - Size of Buffer. + Buffer - Buffer containing read data. + + Returns: + EFI_SUCCESS - The data was written correctly to the device. + EFI_WRITE_PROTECTED - The device can not be written to. + EFI_DEVICE_ERROR - The device reported an error while performing the write. + EFI_NO_MEDIA - There is no media in the device. + EFI_MEDIA_CHNAGED - The MediaId does not matched the current device. + EFI_INVALID_PARAMETER - The write request contains device addresses that are not + valid for the device. + EFI_OUT_OF_RESOURCES + +--*/ +{ + EFI_STATUS Status; + DISK_IO_PRIVATE_DATA *Private; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_BLOCK_IO_MEDIA *Media; + UINT32 BlockSize; + UINT64 Lba; + UINT64 OverRunLba; + UINT32 UnderRun; + UINT32 OverRun; + BOOLEAN TransactionComplete; + UINTN WorkingBufferSize; + UINT8 *WorkingBuffer; + UINTN Length; + UINT8 *Data; + UINT8 *PreData; + UINTN IsBufferAligned; + UINTN DataBufferSize; + BOOLEAN LastWrite; + + DEBUG ((EFI_D_ERROR, "DiskIoWriteDisk\n")); + + Private = DISK_IO_PRIVATE_DATA_FROM_THIS (This); + + BlockIo = Private->BlockIo; + Media = BlockIo->Media; + BlockSize = Media->BlockSize; + + if (Media->ReadOnly) { + return EFI_WRITE_PROTECTED; + } + + if (Media->MediaId != MediaId) { + return EFI_MEDIA_CHANGED; + } + + DataBufferSize = BlockSize * DATA_BUFFER_BLOCK_NUM; + + if (Media->IoAlign > 1) { + PreData = AllocatePool (DataBufferSize + Media->IoAlign); + Data = PreData - ((UINTN) PreData & (Media->IoAlign - 1)) + Media->IoAlign; + } else { + PreData = AllocatePool (DataBufferSize); + Data = PreData; + } + + if (PreData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + WorkingBuffer = Buffer; + WorkingBufferSize = BufferSize; + + Lba = DivU64x32Remainder (Offset, BlockSize, &UnderRun); + + Length = BlockSize - UnderRun; + TransactionComplete = FALSE; + + Status = EFI_SUCCESS; + if (UnderRun != 0) { + // + // Offset starts in the middle of an Lba, so do read modify write. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + Lba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Length > BufferSize) { + Length = BufferSize; + TransactionComplete = TRUE; + } + + CopyMem (Data + UnderRun, WorkingBuffer, Length); + + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + Lba, + BlockSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBuffer += Length; + WorkingBufferSize -= Length; + if (WorkingBufferSize == 0) { + goto Done; + } + + Lba += 1; + } + + OverRunLba = Lba + DivU64x32Remainder (WorkingBufferSize, BlockSize, &OverRun); + + if (!TransactionComplete && WorkingBufferSize >= BlockSize) { + // + // If the DiskIo maps directly to a BlockIo device do the write. + // + if (OverRun != 0) { + WorkingBufferSize -= OverRun; + } + // + // Check buffer alignment + // + IsBufferAligned = (UINTN) WorkingBuffer & (UINTN) (Media->IoAlign - 1); + + if (Media->IoAlign <= 1 || IsBufferAligned == 0) { + // + // Alignment is satisfied, so write them together + // + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + Lba, + WorkingBufferSize, + WorkingBuffer + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBuffer += WorkingBufferSize; + + } else { + // + // The buffer parameter is not aligned with the request + // So use the allocated instead. + // It can fit almost all the cases. + // + LastWrite = FALSE; + do { + if (WorkingBufferSize <= DataBufferSize) { + // + // It is the last calling to writeblocks in this loop + // + DataBufferSize = WorkingBufferSize; + LastWrite = TRUE; + } + + CopyMem (Data, WorkingBuffer, DataBufferSize); + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + Lba, + DataBufferSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + WorkingBufferSize -= DataBufferSize; + WorkingBuffer += DataBufferSize; + Lba += DATA_BUFFER_BLOCK_NUM; + } while (!LastWrite); + } + } + + if (!TransactionComplete && OverRun != 0) { + // + // Last bit is not a complete block, so do a read modify write. + // + Status = BlockIo->ReadBlocks ( + BlockIo, + MediaId, + OverRunLba, + BlockSize, + Data + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (Data, WorkingBuffer, OverRun); + + Status = BlockIo->WriteBlocks ( + BlockIo, + MediaId, + OverRunLba, + BlockSize, + Data + ); + if (EFI_ERROR (Status)) { + goto Done; + } + } + +Done: + if (PreData != NULL) { + gBS->FreePool (PreData); + } + + return Status; +} diff --git a/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.h b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.h new file mode 100644 index 0000000000..39d87661c6 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIo/Dxe/diskio.h @@ -0,0 +1,44 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DiskIo.h + +Abstract: + Private Data definition for Disk IO driver + +--*/ + +#ifndef _DISK_IO_H +#define _DISK_IO_H + + + +#define DISK_IO_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('d', 's', 'k', 'I') + +#define DATA_BUFFER_BLOCK_NUM (64) + +typedef struct { + UINTN Signature; + EFI_DISK_IO_PROTOCOL DiskIo; + EFI_BLOCK_IO_PROTOCOL *BlockIo; +} DISK_IO_PRIVATE_DATA; + +#define DISK_IO_PRIVATE_DATA_FROM_THIS(a) CR (a, DISK_IO_PRIVATE_DATA, DiskIo, DISK_IO_PRIVATE_DATA_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gDiskIoDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gDiskIoComponentName; + +#endif diff --git a/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.mbd b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.mbd new file mode 100644 index 0000000000..ed89f0716e --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.mbd @@ -0,0 +1,42 @@ + + + + + DiskIoPartition + 854E153A-8AC8-40f4-A5A9-4C51F18CFB1B + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeMemoryAllocationLib + UefiDevicePathLib + + diff --git a/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.msa b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.msa new file mode 100644 index 0000000000..930f57b96a --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/DiskIoPartition.msa @@ -0,0 +1,88 @@ + + + + + DiskIoPartition + UEFI_DRIVER + BS_DRIVER + 854E153A-8AC8-40f4-A5A9-4C51F18CFB1B + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + DevicePathLib + + + ..\..\DiskIo\Dxe\diskio.c + ..\..\DiskIo\Dxe\diskio.h + ..\..\DiskIo\Dxe\ComponentName.c + ..\..\Partition\Dxe\Partition.h + ..\..\Partition\Dxe\ElTorito.h + ..\..\Partition\Dxe\Gpt.h + ..\..\Partition\Dxe\Mbr.h + ..\..\Partition\Dxe\Partition.c + ..\..\Partition\Dxe\Eltorito.c + ..\..\Partition\Dxe\Gpt.c + ..\..\Partition\Dxe\Mbr.c + ..\..\Partition\Dxe\ComponentName.c + + + MdePkg + + + BlockIo + DiskIo + DevicePath + + + + PartTypeSystemPart + + + PartTypeUnused + + + + + + + + gPartitionDriverBinding + gPartitionComponentName + + + gDiskIoDriverBinding + gDiskIoComponentName + + + diff --git a/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/build.xml b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/build.xml new file mode 100644 index 0000000000..4b1c1f88cf --- /dev/null +++ b/EdkModulePkg/Universal/Disk/DiskIoPartition/dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/ComponentName.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/ComponentName.c new file mode 100644 index 0000000000..3821690f0c --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/ComponentName.c @@ -0,0 +1,160 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "Partition.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +PartitionComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +PartitionComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gPartitionComponentName = { + PartitionComponentNameGetDriverName, + PartitionComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mPartitionDriverNameTable[] = { + { + "eng", + (CHAR16 *)L"Partition Driver(MBR/GPT/El Torito)" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +PartitionComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gPartitionComponentName.SupportedLanguages, + mPartitionDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +PartitionComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.c new file mode 100644 index 0000000000..27beba171b --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.c @@ -0,0 +1,277 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ElTorito.c + +Abstract: + + Decode an El Torito formatted CD-ROM + +Revision History + +--*/ + +#include "Partition.h" +#include "ElTorito.h" + +BOOLEAN +PartitionInstallElToritoChildHandles ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Install child handles if the Handle supports El Torito format. + +Arguments: + This - Calling context. + Handle - Parent Handle + DiskIo - Parent DiskIo interface + BlockIo - Parent BlockIo interface + DevicePath - Parent Device Path + +Returns: + TRUE - some child handle(s) was added + FALSE - no child handle was added + +--*/ +{ + EFI_STATUS Status; + UINT32 VolDescriptorLba; + UINT32 Lba; + EFI_BLOCK_IO_MEDIA *Media; + CDROM_VOLUME_DESCRIPTOR *VolDescriptor; + ELTORITO_CATALOG *Catalog; + UINTN Check; + UINTN Index; + UINTN BootEntry; + UINTN MaxIndex; + UINT16 *CheckBuffer; + CDROM_DEVICE_PATH CdDev; + UINT32 SubBlockSize; + UINT32 SectorCount; + BOOLEAN Found; + UINT32 VolSpaceSize; + + Found = FALSE; + Media = BlockIo->Media; + VolSpaceSize = 0; + + // + // CD_ROM has the fixed block size as 2048 bytes + // + if (Media->BlockSize != 2048) { + return FALSE; + } + + VolDescriptor = AllocatePool ((UINTN) Media->BlockSize); + + if (VolDescriptor == NULL) { + return FALSE; + } + + Catalog = (ELTORITO_CATALOG *) VolDescriptor; + + // + // the ISO-9660 volume descriptor starts at 32k on the media + // and CD_ROM has the fixed block size as 2048 bytes, so... + // + // + // ((16*2048) / Media->BlockSize) - 1; + // + VolDescriptorLba = 15; + // + // Loop: handle one volume descriptor per time + // + while (TRUE) { + + VolDescriptorLba += 1; + if (VolDescriptorLba > Media->LastBlock) { + // + // We are pointing past the end of the device so exit + // + break; + } + + Status = BlockIo->ReadBlocks ( + BlockIo, + Media->MediaId, + VolDescriptorLba, + Media->BlockSize, + VolDescriptor + ); + if (EFI_ERROR (Status)) { + break; + } + // + // Check for valid volume descriptor signature + // + if (VolDescriptor->Type == CDVOL_TYPE_END || + CompareMem (VolDescriptor->Id, CDVOL_ID, sizeof (VolDescriptor->Id)) != 0 + ) { + // + // end of Volume descriptor list + // + break; + } + // + // Read the Volume Space Size from Primary Volume Descriptor 81-88 byte, + // the 32-bit numerical values is stored in Both-byte orders + // + if (VolDescriptor->Type == CDVOL_TYPE_CODED) { + VolSpaceSize = VolDescriptor->VolSpaceSize[1]; + } + // + // Is it an El Torito volume descriptor? + // + if (CompareMem (VolDescriptor->SystemId, CDVOL_ELTORITO_ID, sizeof (CDVOL_ELTORITO_ID) - 1) != 0) { + continue; + } + // + // Read in the boot El Torito boot catalog + // + Lba = UNPACK_INT32 (VolDescriptor->EltCatalog); + if (Lba > Media->LastBlock) { + continue; + } + + Status = BlockIo->ReadBlocks ( + BlockIo, + Media->MediaId, + Lba, + Media->BlockSize, + Catalog + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "EltCheckDevice: error reading catalog %r\n", Status)); + continue; + } + // + // We don't care too much about the Catalog header's contents, but we do want + // to make sure it looks like a Catalog header + // + if (Catalog->Catalog.Indicator != ELTORITO_ID_CATALOG || Catalog->Catalog.Id55AA != 0xAA55) { + DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header IDs not correct\n")); + continue; + } + + Check = 0; + CheckBuffer = (UINT16 *) Catalog; + for (Index = 0; Index < sizeof (ELTORITO_CATALOG) / sizeof (UINT16); Index += 1) { + Check += CheckBuffer[Index]; + } + + if (Check & 0xFFFF) { + DEBUG ((EFI_D_ERROR, "EltCheckBootCatalog: El Torito boot catalog header checksum failed\n")); + continue; + } + + MaxIndex = Media->BlockSize / sizeof (ELTORITO_CATALOG); + for (Index = 1, BootEntry = 1; Index < MaxIndex; Index += 1) { + // + // Next entry + // + Catalog += 1; + + // + // Check this entry + // + if (Catalog->Boot.Indicator != ELTORITO_ID_SECTION_BOOTABLE || Catalog->Boot.Lba == 0) { + continue; + } + + SubBlockSize = 512; + SectorCount = Catalog->Boot.SectorCount; + + switch (Catalog->Boot.MediaType) { + + case ELTORITO_NO_EMULATION: + SubBlockSize = Media->BlockSize; + break; + + case ELTORITO_HARD_DISK: + break; + + case ELTORITO_12_DISKETTE: + SectorCount = 0x50 * 0x02 * 0x0F; + break; + + case ELTORITO_14_DISKETTE: + SectorCount = 0x50 * 0x02 * 0x12; + break; + + case ELTORITO_28_DISKETTE: + SectorCount = 0x50 * 0x02 * 0x24; + break; + + default: + DEBUG ((EFI_D_INIT, "EltCheckDevice: unsupported El Torito boot media type %x\n", Catalog->Boot.MediaType)); + SectorCount = 0; + SubBlockSize = Media->BlockSize; + break; + } + // + // Create child device handle + // + CdDev.Header.Type = MEDIA_DEVICE_PATH; + CdDev.Header.SubType = MEDIA_CDROM_DP; + SetDevicePathNodeLength (&CdDev.Header, sizeof (CdDev)); + + if (Index == 1) { + // + // This is the initial/default entry + // + BootEntry = 0; + } + + CdDev.BootEntry = (UINT32) BootEntry; + BootEntry++; + CdDev.PartitionStart = Catalog->Boot.Lba; + if (SectorCount < 2) { + CdDev.PartitionSize = VolSpaceSize; + } else { + CdDev.PartitionSize = DivU64x32 ( + MultU64x32 ( + SectorCount, + SubBlockSize + ) + Media->BlockSize - 1, + Media->BlockSize + ); + } + + Status = PartitionInstallChildHandle ( + This, + Handle, + DiskIo, + BlockIo, + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &CdDev, + Catalog->Boot.Lba, + Catalog->Boot.Lba + CdDev.PartitionSize - 1, + SubBlockSize, + FALSE + ); + if (!EFI_ERROR (Status)) { + Found = TRUE; + } + } + } + + gBS->FreePool (VolDescriptor); + + return Found; +} diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.h b/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.h new file mode 100644 index 0000000000..f085315b4d --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/ElTorito.h @@ -0,0 +1,130 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ElTorito.h + +Abstract: + + Data Structures required for detecting ElTorito Partitions + +Revision History + +--*/ + +#ifndef _ELTORITO_H_ +#define _ELTORITO_H_ + +#pragma pack(1) +// +// CDROM_VOLUME_DESCRIPTOR.Types +// +#define CDVOL_TYPE_STANDARD 0x0 +#define CDVOL_TYPE_CODED 0x1 +#define CDVOL_TYPE_END 0xFF + +// +// CDROM_VOLUME_DESCRIPTOR.Id +// +#define CDVOL_ID "CD001" + +// +// CDROM_VOLUME_DESCRIPTOR.SystemId +// +#define CDVOL_ELTORITO_ID "EL TORITO SPECIFICATION" + +// +// Indicator types +// +#define ELTORITO_ID_CATALOG 0x01 +#define ELTORITO_ID_SECTION_BOOTABLE 0x88 +#define ELTORITO_ID_SECTION_NOT_BOOTABLE 0x00 +#define ELTORITO_ID_SECTION_HEADER 0x90 +#define ELTORITO_ID_SECTION_HEADER_FINAL 0x91 + +// +// ELTORITO_CATALOG.Boot.MediaTypes +// +#define ELTORITO_NO_EMULATION 0x00 +#define ELTORITO_12_DISKETTE 0x01 +#define ELTORITO_14_DISKETTE 0x02 +#define ELTORITO_28_DISKETTE 0x03 +#define ELTORITO_HARD_DISK 0x04 + +// +// El Torito Volume Descriptor +// Note that the CDROM_VOLUME_DESCRIPTOR does not match the ISO-9660 +// descriptor. For some reason descriptor used by El Torito is +// different, but they start the same. The El Torito descriptor +// is left shifted 1 byte starting with the SystemId. (Note this +// causes the field to get unaligned) +// +typedef struct { + UINT8 Type; + CHAR8 Id[5]; // CD001 + UINT8 Version; + CHAR8 SystemId[26]; + CHAR8 Unused[38]; + UINT8 EltCatalog[4]; + CHAR8 Unused2[5]; + UINT32 VolSpaceSize[2]; +} CDROM_VOLUME_DESCRIPTOR; + +// +// Catalog Entry +// +typedef union { + struct { + CHAR8 Reserved[0x20]; + } Unknown; + + // + // Catalog validation entry (Catalog header) + // + struct { + UINT8 Indicator; + UINT8 PlatformId; + UINT16 Reserved; + CHAR8 ManufacId[24]; + UINT16 Checksum; + UINT16 Id55AA; + } Catalog; + + // + // Initial/Default Entry or Section Entry + // + struct { + UINT8 Indicator; + UINT8 MediaType : 4; + UINT8 Reserved1 : 4; + UINT16 LoadSegment; + UINT8 SystemType; + UINT8 Reserved2; + UINT16 SectorCount; + UINT32 Lba; + } Boot; + + // + // Section Header Entry + // + struct { + UINT8 Indicator; + UINT8 PlatformId; + UINT16 SectionEntries; + CHAR8 Id[28]; + } Section; + +} ELTORITO_CATALOG; + +#pragma pack() + +#endif diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.c new file mode 100644 index 0000000000..35ff1a8606 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.c @@ -0,0 +1,768 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Gpt.c + +Abstract: + + Decode a hard disk partitioned with the GPT scheme in the EFI 1.0 + specification. + +--*/ + +#include "Partition.h" +#include "Gpt.h" +#include "Mbr.h" + +BOOLEAN +PartitionValidGptTable ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_LBA Lba, + OUT EFI_PARTITION_TABLE_HEADER *PartHeader + ); + +BOOLEAN +PartitionCheckGptEntryArrayCRC ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_PARTITION_TABLE_HEADER *PartHeader + ); + +BOOLEAN +PartitionRestoreGptTable ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_PARTITION_TABLE_HEADER *PartHeader + ); + +VOID +PartitionCheckGptEntry ( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *PartEntry, + OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus + ); + +BOOLEAN +PartitionCheckCrcAltSize ( + IN UINTN MaxSize, + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ); + +BOOLEAN +PartitionCheckCrc ( + IN UINTN MaxSize, + IN OUT EFI_TABLE_HEADER *Hdr + ); + +VOID +PartitionSetCrcAltSize ( + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ); + +VOID +PartitionSetCrc ( + IN OUT EFI_TABLE_HEADER *Hdr + ); + +BOOLEAN +PartitionInstallGptChildHandles ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Install child handles if the Handle supports GPT partition structure. + +Arguments: + This - Calling context. + Handle - Parent Handle + DiskIo - Parent DiskIo interface + BlockIo - Parent BlockIo interface + DevicePath - Parent Device Path + +Returns: + TRUE - Valid GPT disk + FALSE - Not a valid GPT disk + +--*/ +{ + EFI_STATUS Status; + UINT32 BlockSize; + EFI_LBA LastBlock; + MASTER_BOOT_RECORD *ProtectiveMbr; + EFI_PARTITION_TABLE_HEADER *PrimaryHeader; + EFI_PARTITION_TABLE_HEADER *BackupHeader; + EFI_PARTITION_ENTRY *PartEntry; + EFI_PARTITION_ENTRY_STATUS *PEntryStatus; + UINTN Index; + BOOLEAN GptValid; + HARDDRIVE_DEVICE_PATH HdDev; + + ProtectiveMbr = NULL; + PrimaryHeader = NULL; + BackupHeader = NULL; + PartEntry = NULL; + PEntryStatus = NULL; + + BlockSize = BlockIo->Media->BlockSize; + LastBlock = BlockIo->Media->LastBlock; + + DEBUG ((EFI_D_INFO, " BlockSize : %d \n", BlockSize)); + DEBUG ((EFI_D_INFO, " LastBlock : %x \n", LastBlock)); + + GptValid = FALSE; + + // + // Allocate a buffer for the Protective MBR + // + ProtectiveMbr = AllocatePool (BlockSize); + if (ProtectiveMbr == NULL) { + return FALSE; + } + + // + // Read the Protective MBR from LBA #0 + // + Status = BlockIo->ReadBlocks ( + BlockIo, + BlockIo->Media->MediaId, + 0, + BlockIo->Media->BlockSize, + ProtectiveMbr + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Verify that the Protective MBR is valid + // + if (ProtectiveMbr->Partition[0].BootIndicator != 0x00 || + ProtectiveMbr->Partition[0].OSIndicator != 0xEE || + UNPACK_UINT32 (ProtectiveMbr->Partition[0].StartingLBA) != 1 + ) { + goto Done; + } + + // + // Allocate the GPT structures + // + PrimaryHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER)); + if (PrimaryHeader == NULL) { + goto Done; + } + + BackupHeader = AllocateZeroPool (sizeof (EFI_PARTITION_TABLE_HEADER)); + + if (BackupHeader == NULL) { + goto Done; + } + + // + // Check primary and backup partition tables + // + if (!PartitionValidGptTable (BlockIo, DiskIo, PRIMARY_PART_HEADER_LBA, PrimaryHeader)) { + DEBUG ((EFI_D_INFO, " Not Valid primary partition table\n")); + + if (!PartitionValidGptTable (BlockIo, DiskIo, LastBlock, BackupHeader)) { + DEBUG ((EFI_D_INFO, " Not Valid backup partition table\n")); + goto Done; + } else { + DEBUG ((EFI_D_INFO, " Valid backup partition table\n")); + DEBUG ((EFI_D_INFO, " Restore primary partition table by the backup\n")); + if (!PartitionRestoreGptTable (BlockIo, DiskIo, BackupHeader)) { + DEBUG ((EFI_D_INFO, " Restore primary partition table error\n")); + } + + if (PartitionValidGptTable (BlockIo, DiskIo, BackupHeader->AlternateLBA, PrimaryHeader)) { + DEBUG ((EFI_D_INFO, " Restore backup partition table success\n")); + } + } + } else if (!PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) { + DEBUG ((EFI_D_INFO, " Valid primary and !Valid backup partition table\n")); + DEBUG ((EFI_D_INFO, " Restore backup partition table by the primary\n")); + if (!PartitionRestoreGptTable (BlockIo, DiskIo, PrimaryHeader)) { + DEBUG ((EFI_D_INFO, " Restore backup partition table error\n")); + } + + if (PartitionValidGptTable (BlockIo, DiskIo, PrimaryHeader->AlternateLBA, BackupHeader)) { + DEBUG ((EFI_D_INFO, " Restore backup partition table success\n")); + } + + } + + DEBUG ((EFI_D_INFO, " Valid primary and Valid backup partition table\n")); + + // + // Read the EFI Partition Entries + // + PartEntry = AllocatePool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY)); + if (PartEntry == NULL) { + DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); + goto Done; + } + + Status = DiskIo->ReadDisk ( + DiskIo, + BlockIo->Media->MediaId, + MultU64x32(PrimaryHeader->PartitionEntryLBA, BlockSize), + PrimaryHeader->NumberOfPartitionEntries * (PrimaryHeader->SizeOfPartitionEntry), + PartEntry + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, " Partition Entry ReadBlocks error\n")); + goto Done; + } + + DEBUG ((EFI_D_INFO, " Partition entries read block success\n")); + + DEBUG ((EFI_D_INFO, " Number of partition entries: %d\n", PrimaryHeader->NumberOfPartitionEntries)); + + PEntryStatus = AllocateZeroPool (PrimaryHeader->NumberOfPartitionEntries * sizeof (EFI_PARTITION_ENTRY_STATUS)); + if (PEntryStatus == NULL) { + DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); + goto Done; + } + + // + // Check the integrity of partition entries + // + PartitionCheckGptEntry (PrimaryHeader, PartEntry, PEntryStatus); + + // + // If we got this far the GPT layout of the disk is valid and we should return true + // + GptValid = TRUE; + + // + // Create child device handles + // + for (Index = 0; Index < PrimaryHeader->NumberOfPartitionEntries; Index++) { + if (CompareGuid (&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeUnusedGuid) || + PEntryStatus[Index].OutOfRange || + PEntryStatus[Index].Overlap + ) { + // + // Don't use null EFI Partition Entries or Invalid Partition Entries + // + continue; + } + + ZeroMem (&HdDev, sizeof (HdDev)); + HdDev.Header.Type = MEDIA_DEVICE_PATH; + HdDev.Header.SubType = MEDIA_HARDDRIVE_DP; + SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev)); + + HdDev.PartitionNumber = (UINT32) Index + 1; + HdDev.MBRType = MBR_TYPE_EFI_PARTITION_TABLE_HEADER; + HdDev.SignatureType = SIGNATURE_TYPE_GUID; + HdDev.PartitionStart = PartEntry[Index].StartingLBA; + HdDev.PartitionSize = PartEntry[Index].EndingLBA - PartEntry[Index].StartingLBA + 1; + CopyMem (HdDev.Signature, &PartEntry[Index].UniquePartitionGUID, sizeof (EFI_GUID)); + + DEBUG ((EFI_D_INFO, " Index : %d\n", Index)); + DEBUG ((EFI_D_INFO, " Start LBA : %x\n", HdDev.PartitionStart)); + DEBUG ((EFI_D_INFO, " End LBA : %x\n", PartEntry[Index].EndingLBA)); + DEBUG ((EFI_D_INFO, " Partition size: %x\n", HdDev.PartitionSize)); + DEBUG ((EFI_D_INFO, " Start : %x", MultU64x32 (PartEntry[Index].StartingLBA, BlockSize))); + DEBUG ((EFI_D_INFO, " End : %x\n", MultU64x32 (PartEntry[Index].EndingLBA, BlockSize))); + + Status = PartitionInstallChildHandle ( + This, + Handle, + DiskIo, + BlockIo, + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, + PartEntry[Index].StartingLBA, + PartEntry[Index].EndingLBA, + BlockSize, + CompareGuid(&PartEntry[Index].PartitionTypeGUID, &gEfiPartTypeSystemPartGuid) + ); + } + + DEBUG ((EFI_D_INFO, "Prepare to Free Pool\n")); + +Done: + if (ProtectiveMbr != NULL) { + gBS->FreePool (ProtectiveMbr); + } + if (PrimaryHeader != NULL) { + gBS->FreePool (PrimaryHeader); + } + if (BackupHeader != NULL) { + gBS->FreePool (BackupHeader); + } + if (PartEntry != NULL) { + gBS->FreePool (PartEntry); + } + if (PEntryStatus != NULL) { + gBS->FreePool (PEntryStatus); + } + + return GptValid; +} + +BOOLEAN +PartitionValidGptTable ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_LBA Lba, + OUT EFI_PARTITION_TABLE_HEADER *PartHeader + ) +/*++ + +Routine Description: + Check if the GPT partition table is valid + +Arguments: + BlockIo - Parent BlockIo interface + DiskIo - Disk Io protocol. + Lba - The starting Lba of the Partition Table + PartHeader - Stores the partition table that is read + +Returns: + TRUE - The partition table is valid + FALSE - The partition table is not valid + +--*/ +{ + EFI_STATUS Status; + UINT32 BlockSize; + EFI_PARTITION_TABLE_HEADER *PartHdr; + + BlockSize = BlockIo->Media->BlockSize; + + PartHdr = AllocateZeroPool (BlockSize); + + if (PartHdr == NULL) { + DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); + return FALSE; + } + // + // Read the EFI Partition Table Header + // + Status = BlockIo->ReadBlocks ( + BlockIo, + BlockIo->Media->MediaId, + Lba, + BlockSize, + PartHdr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (PartHdr); + return FALSE; + } + + if (CompareMem (&PartHdr->Header.Signature, EFI_PTAB_HEADER_ID, sizeof (UINT64)) != 0 || + !PartitionCheckCrc (BlockSize, &PartHdr->Header) || + PartHdr->MyLBA != Lba + ) { + DEBUG ((EFI_D_INFO, " !Valid efi partition table header\n")); + gBS->FreePool (PartHdr); + return FALSE; + } + + CopyMem (PartHeader, PartHdr, sizeof (EFI_PARTITION_TABLE_HEADER)); + if (!PartitionCheckGptEntryArrayCRC (BlockIo, DiskIo, PartHeader)) { + gBS->FreePool (PartHdr); + return FALSE; + } + + DEBUG ((EFI_D_INFO, " Valid efi partition table header\n")); + gBS->FreePool (PartHdr); + return TRUE; +} + +BOOLEAN +PartitionCheckGptEntryArrayCRC ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_PARTITION_TABLE_HEADER *PartHeader + ) +/*++ + +Routine Description: + + Check if the CRC field in the Partition table header is valid + for Partition entry array + +Arguments: + + BlockIo - parent BlockIo interface + DiskIo - Disk Io Protocol. + PartHeader - Partition table header structure + +Returns: + + TRUE - the CRC is valid + FALSE - the CRC is invalid + +--*/ +{ + EFI_STATUS Status; + UINT8 *Ptr; + UINT32 Crc; + UINTN Size; + + // + // Read the EFI Partition Entries + // + Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); + if (Ptr == NULL) { + DEBUG ((EFI_D_ERROR, " Allocate pool error\n")); + return FALSE; + } + + Status = DiskIo->ReadDisk ( + DiskIo, + BlockIo->Media->MediaId, + MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), + PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Ptr); + return FALSE; + } + + Size = PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry; + + Status = gBS->CalculateCrc32 (Ptr, Size, &Crc); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "CheckPEntryArrayCRC: Crc calculation failed\n")); + gBS->FreePool (Ptr); + return FALSE; + } + + gBS->FreePool (Ptr); + + return (BOOLEAN) (PartHeader->PartitionEntryArrayCRC32 == Crc); +} + +BOOLEAN +PartitionRestoreGptTable ( + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_PARTITION_TABLE_HEADER *PartHeader + ) +/*++ + +Routine Description: + + Restore Partition Table to its alternate place + (Primary -> Backup or Backup -> Primary) + +Arguments: + + BlockIo - parent BlockIo interface + DiskIo - Disk Io Protocol. + PartHeader - the source Partition table header structure + +Returns: + + TRUE - Restoring succeeds + FALSE - Restoring failed + +--*/ +{ + EFI_STATUS Status; + UINTN BlockSize; + EFI_PARTITION_TABLE_HEADER *PartHdr; + EFI_LBA PEntryLBA; + UINT8 *Ptr; + + PartHdr = NULL; + Ptr = NULL; + + BlockSize = BlockIo->Media->BlockSize; + + PartHdr = AllocateZeroPool (BlockSize); + + if (PartHdr == NULL) { + DEBUG ((EFI_D_ERROR, "Allocate pool error\n")); + return FALSE; + } + + PEntryLBA = (PartHeader->MyLBA == PRIMARY_PART_HEADER_LBA) ? \ + (PartHeader->LastUsableLBA + 1) : \ + (PRIMARY_PART_HEADER_LBA + 1); + + CopyMem (PartHdr, PartHeader, sizeof (EFI_PARTITION_TABLE_HEADER)); + + PartHdr->MyLBA = PartHeader->AlternateLBA; + PartHdr->AlternateLBA = PartHeader->MyLBA; + PartHdr->PartitionEntryLBA = PEntryLBA; + PartitionSetCrc ((EFI_TABLE_HEADER *) PartHdr); + + Status = BlockIo->WriteBlocks (BlockIo, BlockIo->Media->MediaId, PartHdr->MyLBA, BlockSize, PartHdr); + if (EFI_ERROR (Status)) { + goto Done; + } + + Ptr = AllocatePool (PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry); + if (Ptr == NULL) { + DEBUG ((EFI_D_ERROR, " Allocate pool effor\n")); + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status = DiskIo->ReadDisk ( + DiskIo, + BlockIo->Media->MediaId, + MultU64x32(PartHeader->PartitionEntryLBA, BlockIo->Media->BlockSize), + PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, + Ptr + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = DiskIo->WriteDisk ( + DiskIo, + BlockIo->Media->MediaId, + MultU64x32(PEntryLBA, BlockIo->Media->BlockSize), + PartHeader->NumberOfPartitionEntries * PartHeader->SizeOfPartitionEntry, + Ptr + ); + +Done: + gBS->FreePool (PartHdr); + gBS->FreePool (Ptr); + + if (EFI_ERROR (Status)) { + return FALSE; + } + + return TRUE; +} + +VOID +PartitionCheckGptEntry ( + IN EFI_PARTITION_TABLE_HEADER *PartHeader, + IN EFI_PARTITION_ENTRY *PartEntry, + OUT EFI_PARTITION_ENTRY_STATUS *PEntryStatus + ) +/*++ + +Routine Description: + + Check each partition entry for its range + +Arguments: + + PartHeader - the partition table header + PartEntry - the partition entry array + PEntryStatus - the partition entry status array recording the status of + each partition + +Returns: + VOID + +--*/ +{ + EFI_LBA StartingLBA; + EFI_LBA EndingLBA; + UINTN Index1; + UINTN Index2; + + DEBUG ((EFI_D_INFO, " start check partition entries\n")); + for (Index1 = 0; Index1 < PartHeader->NumberOfPartitionEntries; Index1++) { + if (CompareGuid (&PartEntry[Index1].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + continue; + } + + StartingLBA = PartEntry[Index1].StartingLBA; + EndingLBA = PartEntry[Index1].EndingLBA; + if (StartingLBA > EndingLBA || + StartingLBA < PartHeader->FirstUsableLBA || + StartingLBA > PartHeader->LastUsableLBA || + EndingLBA < PartHeader->FirstUsableLBA || + EndingLBA > PartHeader->LastUsableLBA + ) { + PEntryStatus[Index1].OutOfRange = TRUE; + continue; + } + + for (Index2 = Index1 + 1; Index2 < PartHeader->NumberOfPartitionEntries; Index2++) { + + if (CompareGuid (&PartEntry[Index2].PartitionTypeGUID, &gEfiPartTypeUnusedGuid)) { + continue; + } + + if (PartEntry[Index2].EndingLBA >= StartingLBA && PartEntry[Index2].StartingLBA <= EndingLBA) { + // + // This region overlaps with the Index1'th region + // + PEntryStatus[Index1].Overlap = TRUE; + PEntryStatus[Index2].Overlap = TRUE; + continue; + + } + } + } + + DEBUG ((EFI_D_INFO, " End check partition entries\n")); +} + +VOID +PartitionSetCrc ( + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Updates the CRC32 value in the table header + +Arguments: + + Hdr - The table to update + +Returns: + + None + +--*/ +{ + PartitionSetCrcAltSize (Hdr->HeaderSize, Hdr); +} + +VOID +PartitionSetCrcAltSize ( + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Updates the CRC32 value in the table header + +Arguments: + + Size - The size of the table + Hdr - The table to update + +Returns: + + None + +--*/ +{ + UINT32 Crc; + + Hdr->CRC32 = 0; + gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc); + Hdr->CRC32 = Crc; +} + +BOOLEAN +PartitionCheckCrc ( + IN UINTN MaxSize, + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Checks the CRC32 value in the table header + +Arguments: + + MaxSize - Max Size limit + Hdr - The table to check + +Returns: + + TRUE if the CRC is OK in the table + +--*/ +{ + return PartitionCheckCrcAltSize (MaxSize, Hdr->HeaderSize, Hdr); +} + +BOOLEAN +PartitionCheckCrcAltSize ( + IN UINTN MaxSize, + IN UINTN Size, + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Checks the CRC32 value in the table header + +Arguments: + + MaxSize - Max Size Limit + Size - The size of the table + Hdr - The table to check + +Returns: + + TRUE if the CRC is OK in the table + +--*/ +{ + UINT32 Crc; + UINT32 OrgCrc; + EFI_STATUS Status; + + Crc = 0; + + if (Size == 0) { + // + // If header size is 0 CRC will pass so return FALSE here + // + return FALSE; + } + + if (MaxSize && Size > MaxSize) { + DEBUG ((EFI_D_ERROR, "CheckCrc32: Size > MaxSize\n")); + return FALSE; + } + // + // clear old crc from header + // + OrgCrc = Hdr->CRC32; + Hdr->CRC32 = 0; + + Status = gBS->CalculateCrc32 ((UINT8 *) Hdr, Size, &Crc); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc calculation failed\n")); + return FALSE; + } + // + // set results + // + Hdr->CRC32 = Crc; + + // + // return status + // + DEBUG_CODE ( + if (OrgCrc != Crc) { + DEBUG ((EFI_D_ERROR, "CheckCrc32: Crc check failed\n")); + } + ); + + return (BOOLEAN) (OrgCrc == Crc); +} diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.h b/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.h new file mode 100644 index 0000000000..fbcd93db12 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Gpt.h @@ -0,0 +1,76 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Gpt.h + +Abstract: + + Data Structures required for detecting GPT Partitions + +Revision History + +--*/ + +#ifndef _GPT_H_ +#define _GPT_H_ + +#pragma pack(1) + +#define PRIMARY_PART_HEADER_LBA 1 + +#define EFI_PTAB_HEADER_ID "EFI PART" + +// +// EFI Partition Attributes +// +#define EFI_PART_REQUIRED_TO_FUNCTION 0x0000000000000001 + +// +// GPT Partition Table Header +// +typedef struct { + EFI_TABLE_HEADER Header; + EFI_LBA MyLBA; + EFI_LBA AlternateLBA; + EFI_LBA FirstUsableLBA; + EFI_LBA LastUsableLBA; + EFI_GUID DiskGUID; + EFI_LBA PartitionEntryLBA; + UINT32 NumberOfPartitionEntries; + UINT32 SizeOfPartitionEntry; + UINT32 PartitionEntryArrayCRC32; +} EFI_PARTITION_TABLE_HEADER; + +// +// GPT Partition Entry +// +typedef struct { + EFI_GUID PartitionTypeGUID; + EFI_GUID UniquePartitionGUID; + EFI_LBA StartingLBA; + EFI_LBA EndingLBA; + UINT64 Attributes; + CHAR16 PartitionName[36]; +} EFI_PARTITION_ENTRY; + +// +// GPT Partition Entry Status +// +typedef struct { + BOOLEAN OutOfRange; + BOOLEAN Overlap; +} EFI_PARTITION_ENTRY_STATUS; + +#pragma pack() + +#endif diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.c new file mode 100644 index 0000000000..07e3cbe459 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.c @@ -0,0 +1,317 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Mbr.c + +Abstract: + + Decode a hard disk partitioned with the legacy MBR found on most PC's + + MBR - Master Boot Record is in the first sector of a partitioned hard disk. + The MBR supports four partitions per disk. The MBR also contains legacy + code that is not run on an EFI system. The legacy code reads the + first sector of the active partition into memory and + + BPB - Boot(?) Parameter Block is in the first sector of a FAT file system. + The BPB contains information about the FAT file system. The BPB is + always on the first sector of a media. The first sector also contains + the legacy boot strap code. + +--*/ + +#include "Partition.h" +#include "Mbr.h" + +BOOLEAN +PartitionValidMbr ( + IN MASTER_BOOT_RECORD *Mbr, + IN EFI_LBA LastLba + ) +/*++ + +Routine Description: + Test to see if the Mbr buffer is a valid MBR + +Arguments: + Mbr - Parent Handle + LastLba - Last Lba address on the device. + +Returns: + TRUE - Mbr is a Valid MBR + FALSE - Mbr is not a Valid MBR + +--*/ +{ + UINT32 StartingLBA; + UINT32 EndingLBA; + UINT32 NewEndingLBA; + INTN Index1; + INTN Index2; + BOOLEAN MbrValid; + + if (Mbr->Signature != MBR_SIGNATURE) { + return FALSE; + } + // + // The BPB also has this signature, so it can not be used alone. + // + MbrValid = FALSE; + for (Index1 = 0; Index1 < MAX_MBR_PARTITIONS; Index1++) { + if (Mbr->Partition[Index1].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) == 0) { + continue; + } + + MbrValid = TRUE; + StartingLBA = UNPACK_UINT32 (Mbr->Partition[Index1].StartingLBA); + EndingLBA = StartingLBA + UNPACK_UINT32 (Mbr->Partition[Index1].SizeInLBA) - 1; + if (EndingLBA > LastLba) { + // + // Compatibility Errata: + // Some systems try to hide drive space with their INT 13h driver + // This does not hide space from the OS driver. This means the MBR + // that gets created from DOS is smaller than the MBR created from + // a real OS (NT & Win98). This leads to BlockIo->LastBlock being + // wrong on some systems FDISKed by the OS. + // + // return FALSE since no block devices on a system are implemented + // with INT 13h + // + return FALSE; + } + + for (Index2 = Index1 + 1; Index2 < MAX_MBR_PARTITIONS; Index2++) { + if (Mbr->Partition[Index2].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) == 0) { + continue; + } + + NewEndingLBA = UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) + UNPACK_UINT32 (Mbr->Partition[Index2].SizeInLBA) - 1; + if (NewEndingLBA >= StartingLBA && UNPACK_UINT32 (Mbr->Partition[Index2].StartingLBA) <= EndingLBA) { + // + // This region overlaps with the Index1'th region + // + return FALSE; + } + } + } + // + // Non of the regions overlapped so MBR is O.K. + // + return MbrValid; +} + +BOOLEAN +PartitionInstallMbrChildHandles ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Install child handles if the Handle supports MBR format. + +Arguments: + This - Calling context. + Handle - Parent Handle + DiskIo - Parent DiskIo interface + BlockIo - Parent BlockIo interface + DevicePath - Parent Device Path + +Returns: + EFI_SUCCESS - If a child handle was added + other - A child handle was not added + +--*/ +{ + EFI_STATUS Status; + MASTER_BOOT_RECORD *Mbr; + UINT32 ExtMbrStartingLba; + UINTN Index; + HARDDRIVE_DEVICE_PATH HdDev; + HARDDRIVE_DEVICE_PATH ParentHdDev; + BOOLEAN Found; + UINT32 PartitionNumber; + EFI_DEVICE_PATH_PROTOCOL *DevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *LastDevicePathNode; + + Mbr = NULL; + Found = FALSE; + + Mbr = AllocatePool (BlockIo->Media->BlockSize); + if (Mbr == NULL) { + goto Done; + } + + Status = BlockIo->ReadBlocks ( + BlockIo, + BlockIo->Media->MediaId, + 0, + BlockIo->Media->BlockSize, + Mbr + ); + if (EFI_ERROR (Status) || !PartitionValidMbr (Mbr, BlockIo->Media->LastBlock)) { + goto Done; + } + // + // We have a valid mbr - add each partition + // + // + // Get starting and ending LBA of the parent block device. + // + LastDevicePathNode = NULL; + ZeroMem (&ParentHdDev, sizeof (ParentHdDev)); + DevicePathNode = DevicePath; + while (!EfiIsDevicePathEnd (DevicePathNode)) { + LastDevicePathNode = DevicePathNode; + DevicePathNode = EfiNextDevicePathNode (DevicePathNode); + } + + if (LastDevicePathNode != NULL) { + if (DevicePathType (LastDevicePathNode) == MEDIA_DEVICE_PATH && + DevicePathSubType (LastDevicePathNode) == MEDIA_HARDDRIVE_DP + ) { + gBS->CopyMem (&ParentHdDev, LastDevicePathNode, sizeof (ParentHdDev)); + } else { + LastDevicePathNode = NULL; + } + } + + PartitionNumber = 1; + + ZeroMem (&HdDev, sizeof (HdDev)); + HdDev.Header.Type = MEDIA_DEVICE_PATH; + HdDev.Header.SubType = MEDIA_HARDDRIVE_DP; + SetDevicePathNodeLength (&HdDev.Header, sizeof (HdDev)); + HdDev.MBRType = MBR_TYPE_PCAT; + HdDev.SignatureType = SIGNATURE_TYPE_MBR; + + if (LastDevicePathNode == NULL) { + // + // This is a MBR, add each partition + // + for (Index = 0; Index < MAX_MBR_PARTITIONS; Index++) { + if (Mbr->Partition[Index].OSIndicator == 0x00 || UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA) == 0) { + // + // Don't use null MBR entries + // + continue; + } + + if (Mbr->Partition[Index].OSIndicator == 0xEE) { + // + // This is the guard MBR for the GPT. If you ever see a GPT disk with zero partitions you can get here. + // We can not produce an MBR BlockIo for this device as the MBR spans the GPT headers. So formating + // this BlockIo would corrupt the GPT structures and require a recovery that would corrupt the format + // that corrupted the GPT partition. + // + continue; + } + + HdDev.PartitionNumber = PartitionNumber ++; + HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[Index].StartingLBA); + HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[Index].SizeInLBA); + CopyMem (HdDev.Signature, &(Mbr->UniqueMbrSignature[0]), sizeof (UINT32)); + + Status = PartitionInstallChildHandle ( + This, + Handle, + DiskIo, + BlockIo, + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, + HdDev.PartitionStart, + HdDev.PartitionStart + HdDev.PartitionSize - 1, + MBR_SIZE, + (BOOLEAN) (Mbr->Partition[Index].OSIndicator == EFI_PARTITION) + ); + + if (!EFI_ERROR (Status)) { + Found = TRUE; + } + } + } else { + // + // It's an extended partition. Follow the extended partition + // chain to get all the logical drives + // + ExtMbrStartingLba = 0; + + do { + + Status = BlockIo->ReadBlocks ( + BlockIo, + BlockIo->Media->MediaId, + ExtMbrStartingLba, + BlockIo->Media->BlockSize, + Mbr + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (Mbr->Partition[0].OSIndicator == 0) { + break; + } + + HdDev.PartitionNumber = PartitionNumber ++; + HdDev.PartitionStart = UNPACK_UINT32 (Mbr->Partition[0].StartingLBA) + ExtMbrStartingLba + ParentHdDev.PartitionStart; + HdDev.PartitionSize = UNPACK_UINT32 (Mbr->Partition[0].SizeInLBA); + if (HdDev.PartitionStart + HdDev.PartitionSize - 1 >= + ParentHdDev.PartitionStart + ParentHdDev.PartitionSize) { + break; + } + + // + // The signature in EBR(Extended Boot Record) should always be 0. + // + *((UINT32 *) &HdDev.Signature[0]) = 0; + + Status = PartitionInstallChildHandle ( + This, + Handle, + DiskIo, + BlockIo, + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &HdDev, + HdDev.PartitionStart - ParentHdDev.PartitionStart, + HdDev.PartitionStart - ParentHdDev.PartitionStart + HdDev.PartitionSize - 1, + MBR_SIZE, + (BOOLEAN) (Mbr->Partition[0].OSIndicator == EFI_PARTITION) + ); + if (!EFI_ERROR (Status)) { + Found = TRUE; + } + + if (Mbr->Partition[1].OSIndicator != EXTENDED_DOS_PARTITION && + Mbr->Partition[1].OSIndicator != EXTENDED_WINDOWS_PARTITION + ) { + break; + } + + ExtMbrStartingLba = UNPACK_UINT32 (Mbr->Partition[1].StartingLBA); + // + // Don't allow partition to be self referencing + // + if (ExtMbrStartingLba == 0) { + break; + } + } while (ExtMbrStartingLba < ParentHdDev.PartitionSize); + } + +Done: + gBS->FreePool (Mbr); + + return Found; +} diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.h b/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.h new file mode 100644 index 0000000000..c0022c88ad --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Mbr.h @@ -0,0 +1,68 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Mbr.h + +Abstract: + + Data Structures required for detecting MBR Partitions + +Revision History + +--*/ + +#ifndef _MBR_H_ +#define _MBR_H_ + +#pragma pack(1) + +#define MBR_SIGNATURE 0xaa55 +#define MIN_MBR_DEVICE_SIZE 0x80000 +#define MBR_ERRATA_PAD 0x40000 // 128 MB +#define EXTENDED_DOS_PARTITION 0x05 +#define EXTENDED_WINDOWS_PARTITION 0x0F +#define MAX_MBR_PARTITIONS 4 + +#define EFI_PARTITION 0xef +#define MBR_SIZE 512 + +// +// MBR Partition Entry +// +typedef struct { + UINT8 BootIndicator; + UINT8 StartHead; + UINT8 StartSector; + UINT8 StartTrack; + UINT8 OSIndicator; + UINT8 EndHead; + UINT8 EndSector; + UINT8 EndTrack; + UINT8 StartingLBA[4]; + UINT8 SizeInLBA[4]; +} MBR_PARTITION_RECORD; + +// +// MBR Partition table +// +typedef struct { + UINT8 BootStrapCode[440]; + UINT8 UniqueMbrSignature[4]; + UINT8 Unknown[2]; + MBR_PARTITION_RECORD Partition[MAX_MBR_PARTITIONS]; + UINT16 Signature; +} MASTER_BOOT_RECORD; + +#pragma pack() + +#endif diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c new file mode 100644 index 0000000000..59e33b27c1 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.c @@ -0,0 +1,735 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Partition.c + +Abstract: + + Partition driver that produces logical BlockIo devices from a physical + BlockIo device. The logical BlockIo devices are based on the format + of the raw block devices media. Currently "El Torito CD-ROM", Legacy + MBR, and GPT partition schemes are supported. + +--*/ + +#include "Partition.h" + +// +// Function Prototypes +// +EFI_STATUS +EFIAPI +PartitionEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +PartitionDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +PartitionDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +PartitionDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Partition Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding = { + PartitionDriverBindingSupported, + PartitionDriverBindingStart, + PartitionDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +PartitionDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any ControllerHandle + than contains a BlockIo and DiskIo protocol can be supported. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to test + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver supports this device + EFI_ALREADY_STARTED - This driver is already running on this device + EFI_UNSUPPORTED - This driver does not support this device + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_DEV_PATH *Node; + + if (RemainingDevicePath != NULL) { + Node = (EFI_DEV_PATH *) RemainingDevicePath; + if (Node->DevPath.Type != MEDIA_DEVICE_PATH || + Node->DevPath.SubType != MEDIA_HARDDRIVE_DP || + DevicePathNodeLength (&Node->DevPath) != sizeof (HARDDRIVE_DEVICE_PATH) + ) { + return EFI_UNSUPPORTED; + } + } + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PartitionDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Start this driver on ControllerHandle by opening a Block IO and Disk IO + protocol, reading Device Path, and creating a child handle with a + Disk IO and device path protocol. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to bind driver to + RemainingDevicePath - Not used + + Returns: + EFI_SUCCESS - This driver is added to DeviceHandle + EFI_ALREADY_STARTED - This driver is already running on DeviceHandle + other - This driver does not support this device + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS OpenStatus; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the Device Path Protocol on ControllerHandle's handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &ParentDevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return Status; + } + + OpenStatus = Status; + + // + // If no media is present, do nothing here. + // + Status = EFI_UNSUPPORTED; + if (BlockIo->Media->MediaPresent) { + // + // Try for GPT, then El Torito, and then legacy MBR partition types. If the + // media supports a given partition type install child handles to represent + // the partitions described by the media. + // + if (PartitionInstallGptChildHandles ( + This, + ControllerHandle, + DiskIo, + BlockIo, + ParentDevicePath + ) || + + PartitionInstallElToritoChildHandles ( + This, + ControllerHandle, + DiskIo, + BlockIo, + ParentDevicePath + ) || + + PartitionInstallMbrChildHandles ( + This, + ControllerHandle, + DiskIo, + BlockIo, + ParentDevicePath + )) { + Status = EFI_SUCCESS; + } else { + Status = EFI_NOT_FOUND; + } + } + // + // In the case that the driver is already started (OpenStatus == EFI_ALREADY_STARTED), + // the DevicePathProtocol and the DiskIoProtocol are not actually opened by the + // driver. So don't try to close them. Otherwise, we will break the dependency + // between the controller and the driver set up before. + // + if (EFI_ERROR (Status) && !EFI_ERROR (OpenStatus)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +PartitionDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle. Support stoping any child handles + created by this driver. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to stop driver on + NumberOfChildren - Number of Children in the ChildHandleBuffer + ChildHandleBuffer - List of handles for the children we need to stop. + + Returns: + EFI_SUCCESS - This driver is removed DeviceHandle + EFI_DEVICE_ERROR - This driver was not removed from this device + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + BOOLEAN AllChildrenStopped; + PARTITION_PRIVATE_DATA *Private; + EFI_DISK_IO_PROTOCOL *DiskIo; + + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; + } + + AllChildrenStopped = TRUE; + for (Index = 0; Index < NumberOfChildren; Index++) { + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlockIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + + Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (BlockIo); + + // + // All Software protocols have be freed from the handle so remove it. + // + BlockIo->FlushBlocks (BlockIo); + + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + Private->DevicePath, + &gEfiBlockIoProtocolGuid, + &Private->BlockIo, + Private->EspGuid, + NULL, + NULL + ); + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + ControllerHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &DiskIo, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + gBS->FreePool (Private->DevicePath); + gBS->FreePool (Private); + } + + } + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PartitionReset ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the parent Block Device. + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The device was reset. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +--*/ +{ + PARTITION_PRIVATE_DATA *Private; + + Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This); + + return Private->ParentBlockIo->Reset ( + Private->ParentBlockIo, + ExtendedVerification + ); +} + +EFI_STATUS +EFIAPI +PartitionReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + + Routine Description: + Read by using the Disk IO protocol on the parent device. Lba addresses + must be converted to byte offsets. + + Arguments: + This - Protocol instance pointer. + MediaId - Id of the media, changes every time the media is replaced. + Lba - The starting Logical Block Address to read from + BufferSize - Size of Buffer, must be a multiple of device block size. + Buffer - Buffer containing read data + + Returns: + EFI_SUCCESS - The data was read correctly from the device. + EFI_DEVICE_ERROR - The device reported an error while performing the read. + EFI_NO_MEDIA - There is no media in the device. + EFI_MEDIA_CHANGED - The MediaId does not matched the current device. + EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the + device. + EFI_INVALID_PARAMETER - The read request contains device addresses that are not + valid for the device. + +--*/ +{ + PARTITION_PRIVATE_DATA *Private; + UINT64 Offset; + + Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This); + + if (BufferSize % Private->BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start; + if (Offset + BufferSize > Private->End) { + return EFI_INVALID_PARAMETER; + } + // + // Because some kinds of partition have different block size from their parent + // device, we call the Disk IO protocol on the parent device, not the Block IO + // protocol + // + return Private->DiskIo->ReadDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer); +} + +EFI_STATUS +EFIAPI +PartitionWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + + Routine Description: + Write by using the Disk IO protocol on the parent device. Lba addresses + must be converted to byte offsets. + + Arguments: + This - Protocol instance pointer. + MediaId - Id of the media, changes every time the media is replaced. + Lba - The starting Logical Block Address to read from + BufferSize - Size of Buffer, must be a multiple of device block size. + Buffer - Buffer containing read data + + Returns: + EFI_SUCCESS - The data was written correctly to the device. + EFI_WRITE_PROTECTED - The device can not be written to. + EFI_DEVICE_ERROR - The device reported an error while performing the write. + EFI_NO_MEDIA - There is no media in the device. + EFI_MEDIA_CHNAGED - The MediaId does not matched the current device. + EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the + device. + EFI_INVALID_PARAMETER - The write request contains a LBA that is not + valid for the device. + +--*/ +{ + PARTITION_PRIVATE_DATA *Private; + UINT64 Offset; + + Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This); + + if (BufferSize % Private->BlockSize != 0) { + return EFI_BAD_BUFFER_SIZE; + } + + Offset = MultU64x32 (Lba, Private->BlockSize) + Private->Start; + if (Offset + BufferSize > Private->End) { + return EFI_INVALID_PARAMETER; + } + // + // Because some kinds of partition have different block size from their parent + // device, we call the Disk IO protocol on the parent device, not the Block IO + // protocol + // + return Private->DiskIo->WriteDisk (Private->DiskIo, MediaId, Offset, BufferSize, Buffer); +} + +EFI_STATUS +EFIAPI +PartitionFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + + Routine Description: + Flush the parent Block Device. + + Arguments: + This - Protocol instance pointer. + + Returns: + EFI_SUCCESS - All outstanding data was written to the device + EFI_DEVICE_ERROR - The device reported an error while writing back the data + EFI_NO_MEDIA - There is no media in the device. + +--*/ +{ + PARTITION_PRIVATE_DATA *Private; + + Private = PARTITION_DEVICE_FROM_BLOCK_IO_THIS (This); + + return Private->ParentBlockIo->FlushBlocks (Private->ParentBlockIo); +} + +EFI_STATUS +PartitionInstallChildHandle ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_DISK_IO_PROTOCOL *ParentDiskIo, + IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN EFI_LBA Start, + IN EFI_LBA End, + IN UINT32 BlockSize, + IN BOOLEAN InstallEspGuid + ) +/*++ + +Routine Description: + Create a child handle for a logical block device that represents the + bytes Start to End of the Parent Block IO device. + +Arguments: + This - Calling context. + ParentHandle - Parent Handle for new child + ParentDiskIo - Parent DiskIo interface + ParentBlockIo - Parent BlockIo interface + ParentDevicePath - Parent Device Path + DevicePathNode - Child Device Path node + Start - Start Block + End - End Block + BlockSize - Child block size + InstallEspGuid - Flag to install EFI System Partition GUID on handle + +Returns: + EFI_SUCCESS - If a child handle was added + EFI_OUT_OF_RESOURCES - A child handle was not added + +--*/ +{ + EFI_STATUS Status; + PARTITION_PRIVATE_DATA *Private; + + Private = AllocateZeroPool (sizeof (PARTITION_PRIVATE_DATA)); + if (Private == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Private->Signature = PARTITION_PRIVATE_DATA_SIGNATURE; + + Private->Start = MultU64x32 (Start, ParentBlockIo->Media->BlockSize); + Private->End = MultU64x32 (End + 1, ParentBlockIo->Media->BlockSize); + + Private->BlockSize = BlockSize; + Private->ParentBlockIo = ParentBlockIo; + Private->DiskIo = ParentDiskIo; + + Private->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; + + Private->BlockIo.Media = &Private->Media; + CopyMem (Private->BlockIo.Media, ParentBlockIo->Media, sizeof (EFI_BLOCK_IO_MEDIA)); + Private->Media.LogicalPartition = TRUE; + Private->Media.LastBlock = DivU64x32 ( + MultU64x32 ( + End - Start + 1, + ParentBlockIo->Media->BlockSize + ), + BlockSize + ) - 1; + + Private->Media.BlockSize = (UINT32) BlockSize; + + Private->BlockIo.Reset = PartitionReset; + Private->BlockIo.ReadBlocks = PartitionReadBlocks; + Private->BlockIo.WriteBlocks = PartitionWriteBlocks; + Private->BlockIo.FlushBlocks = PartitionFlushBlocks; + + Private->DevicePath = AppendDevicePathNode (ParentDevicePath, DevicePathNode); + + if (Private->DevicePath == NULL) { + gBS->FreePool (Private); + return EFI_OUT_OF_RESOURCES; + } + + if (InstallEspGuid) { + Private->EspGuid = &gEfiPartTypeSystemPartGuid; + } else { + // + // If NULL InstallMultipleProtocolInterfaces will ignore it. + // + Private->EspGuid = NULL; + } + // + // Create the new handle + // + Private->Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->Handle, + &gEfiDevicePathProtocolGuid, + Private->DevicePath, + &gEfiBlockIoProtocolGuid, + &Private->BlockIo, + Private->EspGuid, + NULL, + NULL + ); + + if (!EFI_ERROR (Status)) { + // + // Open the Parent Handle for the child + // + Status = gBS->OpenProtocol ( + ParentHandle, + &gEfiDiskIoProtocolGuid, + (VOID **) &ParentDiskIo, + This->DriverBindingHandle, + Private->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + gBS->FreePool (Private->DevicePath); + gBS->FreePool (Private); + } + + return Status; +} diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.h b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.h new file mode 100644 index 0000000000..de6fbf12ef --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.h @@ -0,0 +1,123 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Partition.h + +Abstract: + + Partition driver that produces logical BlockIo devices from a physical + BlockIo device. The logical BlockIo devices are based on the format + of the raw block devices media. Currently "El Torito CD-ROM", Legacy + MBR, and GPT partition schemes are supported. + +Revision History + +--*/ + +#ifndef __PARTITION_H__ +#define __PARTITION_H__ + + + +// +// Partition private data +// +#define PARTITION_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('P', 'a', 'r', 't') +typedef struct { + UINT64 Signature; + + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_BLOCK_IO_PROTOCOL BlockIo; + EFI_BLOCK_IO_MEDIA Media; + + EFI_DISK_IO_PROTOCOL *DiskIo; + EFI_BLOCK_IO_PROTOCOL *ParentBlockIo; + UINT64 Start; + UINT64 End; + UINT32 BlockSize; + + EFI_GUID *EspGuid; + +} PARTITION_PRIVATE_DATA; + +#define PARTITION_DEVICE_FROM_BLOCK_IO_THIS(a) CR (a, PARTITION_PRIVATE_DATA, BlockIo, PARTITION_PRIVATE_DATA_SIGNATURE) + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gPartitionDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gPartitionComponentName; + +// +// Extract INT32 from char array +// +#define UNPACK_INT32(a) (INT32)( (((UINT8 *) a)[0] << 0) | \ + (((UINT8 *) a)[1] << 8) | \ + (((UINT8 *) a)[2] << 16) | \ + (((UINT8 *) a)[3] << 24) ) + +// +// Extract UINT32 from char array +// +#define UNPACK_UINT32(a) (UINT32)( (((UINT8 *) a)[0] << 0) | \ + (((UINT8 *) a)[1] << 8) | \ + (((UINT8 *) a)[2] << 16) | \ + (((UINT8 *) a)[3] << 24) ) + +EFI_STATUS +PartitionInstallChildHandle ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_DISK_IO_PROTOCOL *ParentDiskIo, + IN EFI_BLOCK_IO_PROTOCOL *ParentBlockIo, + IN EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode, + IN UINT64 Start, + IN UINT64 End, + IN UINT32 BlockSize, + IN BOOLEAN InstallEspGuid + ) +; + +BOOLEAN +PartitionInstallGptChildHandles ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +; + +BOOLEAN +PartitionInstallElToritoChildHandles ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +; + +BOOLEAN +PartitionInstallMbrChildHandles ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DISK_IO_PROTOCOL *DiskIo, + IN EFI_BLOCK_IO_PROTOCOL *BlockIo, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.mbd b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.mbd new file mode 100644 index 0000000000..7be0d52c92 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.mbd @@ -0,0 +1,42 @@ + + + + + Partition + 1FA1F39E-FEFF-4aae-BD7B-38A070A3B609 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeMemoryAllocationLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + UefiDevicePathLib + + diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa new file mode 100644 index 0000000000..a4eed02ef1 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/Partition.msa @@ -0,0 +1,81 @@ + + + + + Partition + UEFI_DRIVER + BS_DRIVER + 1FA1F39E-FEFF-4aae-BD7B-38A070A3B609 + 0 + Component description file for Partition module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + BaseLib + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + DevicePathLib + + + Partition.h + ElTorito.h + Gpt.h + Mbr.h + Partition.c + Eltorito.c + Gpt.c + Mbr.c + ComponentName.c + + + MdePkg + + + BlockIo + DiskIo + DevicePath + + + + PartTypeSystemPart + + + PartTypeUnused + + + + + + + + gPartitionDriverBinding + gPartitionComponentName + + + diff --git a/EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml b/EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml new file mode 100644 index 0000000000..ea4ea4e1ed --- /dev/null +++ b/EdkModulePkg/Universal/Disk/Partition/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.mbd b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.mbd new file mode 100644 index 0000000000..46b51cffdd --- /dev/null +++ b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.mbd @@ -0,0 +1,38 @@ + + + + + English + CD3BAFB6-50FB-4fe8-8E4E-AB74D2C1A600 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + + diff --git a/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.msa b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.msa new file mode 100644 index 0000000000..9abe3284ad --- /dev/null +++ b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/English.msa @@ -0,0 +1,53 @@ + + + + + English + UEFI_DRIVER + BS_DRIVER + CD3BAFB6-50FB-4fe8-8E4E-AB74D2C1A600 + 0 + Component description file for English module for unicode collation. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverEntryPoint + UefiBootServicesTableLib + + + UnicodeCollationEng.c + + + MdePkg + + + UnicodeCollation + + + + InitializeUnicodeCollationEng + + + diff --git a/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.c b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.c new file mode 100644 index 0000000000..f043f37a5c --- /dev/null +++ b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.c @@ -0,0 +1,478 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + UnicodeCollationEng.c + +Abstract: + + Unicode Collation Protocol (English) + +Revision History + +--*/ + +#include "UnicodeCollationEng.h" + +CHAR8 mEngUpperMap[0x100]; +CHAR8 mEngLowerMap[0x100]; +CHAR8 mEngInfoMap[0x100]; + +CHAR8 mOtherChars[] = { + '0', + '1', + '2', + '3', + '4', + '5', + '6', + '7', + '8', + '9', + '\\', + '.', + '_', + '^', + '$', + '~', + '!', + '#', + '%', + '&', + '-', + '{', + '}', + '(', + ')', + '@', + '`', + '\'', + '\0' +}; + +EFI_HANDLE mHandle = NULL; + +EFI_UNICODE_COLLATION_PROTOCOL UnicodeEng = { + EngStriColl, + EngMetaiMatch, + EngStrLwr, + EngStrUpr, + EngFatToStr, + EngStrToFat, + "eng" +}; + +// +// +// +EFI_STATUS +InitializeUnicodeCollationEng ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initializes the Unicode Collation Driver + +Arguments: + + ImageHandle - + + SystemTable - + +Returns: + + EFI_SUCCESS + EFI_OUT_OF_RESOURCES + +--*/ +{ + UINTN Index; + UINTN Index2; + + // + // Initialize mapping tables for the supported languages + // + for (Index = 0; Index < 0x100; Index++) { + mEngUpperMap[Index] = (CHAR8) Index; + mEngLowerMap[Index] = (CHAR8) Index; + mEngInfoMap[Index] = 0; + + if ((Index >= 'a' && Index <= 'z') || (Index >= 0xe0 && Index <= 0xf6) || (Index >= 0xf8 && Index <= 0xfe)) { + + Index2 = Index - 0x20; + mEngUpperMap[Index] = (CHAR8) Index2; + mEngLowerMap[Index2] = (CHAR8) Index; + + mEngInfoMap[Index] |= CHAR_FAT_VALID; + mEngInfoMap[Index2] |= CHAR_FAT_VALID; + } + } + + for (Index = 0; mOtherChars[Index]; Index++) { + Index2 = mOtherChars[Index]; + mEngInfoMap[Index2] |= CHAR_FAT_VALID; + } + // + // Create a handle for the device + // + return gBS->InstallProtocolInterface ( + &mHandle, + &gEfiUnicodeCollationProtocolGuid, + EFI_NATIVE_INTERFACE, + &UnicodeEng + ); +} + +INTN +EFIAPI +EngStriColl ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *s1, + IN CHAR16 *s2 + ) +/*++ + +Routine Description: + + Performs a case-insensitive comparison of two Null-terminated Unicode strings. + +Arguments: + + This + s1 + s2 + +Returns: + +--*/ +{ + while (*s1) { + if (ToUpper (*s1) != ToUpper (*s2)) { + break; + } + + s1 += 1; + s2 += 1; + } + + return ToUpper (*s1) - ToUpper (*s2); +} + +VOID +EFIAPI +EngStrLwr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ) +/*++ + +Routine Description: + + Converts all the Unicode characters in a Null-terminated Unicode string + to lower case Unicode characters. + +Arguments: + + This - A pointer to the EFI_UNICODE_COLLATION_PROTOCOL instance. + Str1 - A pointer to a Null-terminated Unicode string. + Str2 - A pointer to a Null-terminated Unicode string. + +Returns: + + 0 - s1 is equivalent to s2. + > 0 - s1 is lexically greater than s2. + < 0 - s1 is lexically less than s2. + +--*/ +{ + while (*Str) { + *Str = ToLower (*Str); + Str += 1; + } +} + +VOID +EFIAPI +EngStrUpr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ) +/*++ + +Routine Description: + + Converts all the Unicode characters in a Null-terminated + Unicode string to upper case Unicode characters. + +Arguments: + This + Str + +Returns: + None + +--*/ +{ + while (*Str) { + *Str = ToUpper (*Str); + Str += 1; + } +} + +BOOLEAN +EFIAPI +EngMetaiMatch ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN CHAR16 *Pattern + ) +/*++ + +Routine Description: + + Performs a case-insensitive comparison between a Null-terminated + Unicode pattern string and a Null-terminated Unicode string. + + The pattern string can use the '?' wildcard to match any character, + and the '*' wildcard to match any sub-string. + +Arguments: + + This - A pointer to the EFI_UNICODE_COLLATION_PROTOCOL instance. + String - A pointer to a Null-terminated Unicode string. + Pattern - A pointer to a Null-terminated Unicode pattern string. + +Returns: + + TRUE - Pattern was found in String. + FALSE - Pattern was not found in String. + +--*/ +{ + CHAR16 CharC; + CHAR16 CharP; + CHAR16 Index3; + + for (;;) { + CharP = *Pattern; + Pattern += 1; + + switch (CharP) { + case 0: + // + // End of pattern. If end of string, TRUE match + // + if (*String) { + return FALSE; + } else { + return TRUE; + } + + case '*': + // + // Match zero or more chars + // + while (*String) { + if (EngMetaiMatch (This, String, Pattern)) { + return TRUE; + } + + String += 1; + } + + return EngMetaiMatch (This, String, Pattern); + + case '?': + // + // Match any one char + // + if (!*String) { + return FALSE; + } + + String += 1; + break; + + case '[': + // + // Match char set + // + CharC = *String; + if (!CharC) { + // + // syntax problem + // + return FALSE; + } + + Index3 = 0; + CharP = *Pattern++; + while (CharP) { + if (CharP == ']') { + return FALSE; + } + + if (CharP == '-') { + // + // if range of chars, get high range + // + CharP = *Pattern; + if (CharP == 0 || CharP == ']') { + // + // syntax problem + // + return FALSE; + } + + if (ToUpper (CharC) >= ToUpper (Index3) && ToUpper (CharC) <= ToUpper (CharP)) { + // + // if in range, it's a match + // + break; + } + } + + Index3 = CharP; + if (ToUpper (CharC) == ToUpper (CharP)) { + // + // if char matches + // + break; + } + + CharP = *Pattern++; + } + // + // skip to end of match char set + // + while (CharP && CharP != ']') { + CharP = *Pattern; + Pattern += 1; + } + + String += 1; + break; + + default: + CharC = *String; + if (ToUpper (CharC) != ToUpper (CharP)) { + return FALSE; + } + + String += 1; + break; + } + } +} + +VOID +EFIAPI +EngFatToStr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN UINTN FatSize, + IN CHAR8 *Fat, + OUT CHAR16 *String + ) +/*++ + +Routine Description: + + Converts an 8.3 FAT file name using an OEM character set + to a Null-terminated Unicode string. + + BUGBUG: Function has to expand DBCS FAT chars, currently not. + +Arguments: + This + FatSize + Fat + String + +Returns: + +--*/ +{ + // + // No DBCS issues, just expand and add null terminate to end of string + // + while (*Fat && FatSize) { + *String = *Fat; + String += 1; + Fat += 1; + FatSize -= 1; + } + + *String = 0; +} + +BOOLEAN +EFIAPI +EngStrToFat ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN UINTN FatSize, + OUT CHAR8 *Fat + ) +/*++ + +Routine Description: + + Converts a Null-terminated Unicode string to legal characters + in a FAT filename using an OEM character set. + + Functions has to crunch string to a fat string. Replacing + any chars that can't be represented in the fat name. + +Arguments: + This + String + FatSize + Fat + +Returns: + TRUE + FALSE +--*/ +{ + BOOLEAN SpecialCharExist; + + SpecialCharExist = FALSE; + while (*String && FatSize) { + // + // Skip '.' or ' ' when making a fat name + // + if (*String != '.' && *String != ' ') { + // + // If this is a valid fat char, move it. + // Otherwise, move a '_' and flag the fact that the name needs an Lfn + // + if (*String < 0x100 && (mEngInfoMap[*String] & CHAR_FAT_VALID)) { + *Fat = mEngUpperMap[*String]; + } else { + *Fat = '_'; + SpecialCharExist = TRUE; + } + + Fat += 1; + FatSize -= 1; + } + + String += 1; + } + // + // Do not terminate that fat string + // + return SpecialCharExist; +} diff --git a/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.h b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.h new file mode 100644 index 0000000000..6bd547997f --- /dev/null +++ b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/UnicodeCollationEng.h @@ -0,0 +1,102 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + UnicodeCollationEng.h + +Abstract: + + Head file for Unicode Collation Protocol (English) + +Revision History + +--*/ + +#ifndef _UNICODE_COLLATION_ENG_H +#define _UNICODE_COLLATION_ENG_H + + + +// +// Defines +// +#define CHAR_FAT_VALID 0x01 + +#define ToUpper(a) (CHAR16) (a <= 0xFF ? mEngUpperMap[a] : a) +#define ToLower(a) (CHAR16) (a <= 0xFF ? mEngLowerMap[a] : a) + +// +// Prototypes +// +INTN +EFIAPI +EngStriColl ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *s1, + IN CHAR16 *s2 + ) +; + +BOOLEAN +EFIAPI +EngMetaiMatch ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN CHAR16 *Pattern + ) +; + +VOID +EFIAPI +EngStrLwr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ) +; + +VOID +EFIAPI +EngStrUpr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ) +; + +VOID +EFIAPI +EngFatToStr ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN UINTN FatSize, + IN CHAR8 *Fat, + OUT CHAR16 *String + ) +; + +BOOLEAN +EFIAPI +EngStrToFat ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN UINTN FatSize, + OUT CHAR8 *Fat + ) +; + +EFI_STATUS +EFIAPI +InitializeUnicodeCollationEng ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/build.xml b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/build.xml new file mode 100644 index 0000000000..81fd524667 --- /dev/null +++ b/EdkModulePkg/Universal/Disk/UnicodeCollation/English/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ebc.dxs b/EdkModulePkg/Universal/Ebc/Dxe/Ebc.dxs new file mode 100644 index 0000000000..662aa1cb11 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/Ebc.dxs @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Ebc.dxs + +Abstract: + + Dependency expression file for EBC VM. + +--*/ +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ebc.mbd b/EdkModulePkg/Universal/Ebc/Dxe/Ebc.mbd new file mode 100644 index 0000000000..61073596f3 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/Ebc.mbd @@ -0,0 +1,43 @@ + + + + + Ebc + 13AC6DD0-73D0-11D4-B06B-00AA00BD6DE7 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-22 14:03 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ebc.msa b/EdkModulePkg/Universal/Ebc/Dxe/Ebc.msa new file mode 100644 index 0000000000..e736450b39 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/Ebc.msa @@ -0,0 +1,80 @@ + + + + + Ebc + DXE_DRIVER + BS_DRIVER + 13AC6DD0-73D0-11D4-B06B-00AA00BD6DE7 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-22 15:19 + + + DebugLib + UefiDriverEntryPoint + ReportStatusCodeLib + UefiLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + EbcInt.c + EbcInt.h + EbcExecute.c + EbcExecute.h + Ebc.dxs + + Ia32\EbcLowLevel.asm + Ia32\Ia32Math.asm + Ia32\EbcSupport.c + + + x64\EbcLowLevel.asm + x64\x64Math.c + x64\EbcSupport.c + + + Ipf\EbcLowLevel.s + Ipf\IpfMath.c + Ipf\IpfMul.s + Ipf\EbcSupport.c + + + + MdePkg + EdkModulePkg + + + Ebc + DebugSupport + + + + InitializeEbcDriver + + + diff --git a/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.c b/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.c new file mode 100644 index 0000000000..9d375a5461 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.c @@ -0,0 +1,4603 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EbcExecute.c + +Abstract: + + Contains code that implements the virtual machine. + +--*/ + +#include "EbcInt.h" +#include "EbcExecute.h" + +// +// VM major/minor version +// +#define VM_MAJOR_VERSION 1 +#define VM_MINOR_VERSION 0 + +// +// Define some useful data size constants to allow switch statements based on +// size of operands or data. +// +#define DATA_SIZE_INVALID 0 +#define DATA_SIZE_8 1 +#define DATA_SIZE_16 2 +#define DATA_SIZE_32 4 +#define DATA_SIZE_64 8 +#define DATA_SIZE_N 48 // 4 or 8 +// +// Structure we'll use to dispatch opcodes to execute functions. +// +typedef struct { + EFI_STATUS (*ExecuteFunction) (IN VM_CONTEXT * VmPtr); +} +VM_TABLE_ENTRY; + +typedef +UINT64 +(*DATA_MANIP_EXEC_FUNCTION) ( + IN VM_CONTEXT * VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +INT16 +VmReadIndex16 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 CodeOffset + ); + +STATIC +INT32 +VmReadIndex32 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 CodeOffset + ); + +STATIC +INT64 +VmReadIndex64 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 CodeOffset + ); + +STATIC +UINT8 +VmReadMem8 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ); + +STATIC +UINT16 +VmReadMem16 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ); + +STATIC +UINT32 +VmReadMem32 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ); + +STATIC +UINT64 +VmReadMem64 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ); + +STATIC +UINTN +VmReadMemN ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ); + +STATIC +EFI_STATUS +VmWriteMem8 ( + IN VM_CONTEXT *VmPtr, + UINTN Addr, + IN UINT8 Data + ); + +STATIC +EFI_STATUS +VmWriteMem16 ( + IN VM_CONTEXT *VmPtr, + UINTN Addr, + IN UINT16 Data + ); + +STATIC +EFI_STATUS +VmWriteMem32 ( + IN VM_CONTEXT *VmPtr, + UINTN Addr, + IN UINT32 Data + ); + +EFI_STATUS +VmWriteMemN ( + IN VM_CONTEXT *VmPtr, + UINTN Addr, + IN UINTN Data + ); + +EFI_STATUS +VmWriteMem64 ( + IN VM_CONTEXT *VmPtr, + UINTN Addr, + IN UINT64 Data + ); + +STATIC +UINT16 +VmReadCode16 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ); + +STATIC +UINT32 +VmReadCode32 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ); + +STATIC +UINT64 +VmReadCode64 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ); + +STATIC +INT8 +VmReadImmed8 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ); + +STATIC +INT16 +VmReadImmed16 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ); + +STATIC +INT32 +VmReadImmed32 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ); + +STATIC +INT64 +VmReadImmed64 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ); + +STATIC +UINTN +ConvertStackAddr ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ); + +STATIC +EFI_STATUS +ExecuteDataManip ( + IN VM_CONTEXT *VmPtr, + IN BOOLEAN IsSignedOperation + ); + +// +// Functions that execute VM opcodes +// +STATIC +EFI_STATUS +ExecuteBREAK ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteJMP ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteJMP8 ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteCALL ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteRET ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteCMP ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteCMPI ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteMOVxx ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteMOVI ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteMOVIn ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteMOVREL ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecutePUSHn ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecutePUSH ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecutePOPn ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecutePOP ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteSignedDataManip ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteUnsignedDataManip ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteLOADSP ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteSTORESP ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteMOVsnd ( + IN VM_CONTEXT *VmPtr + ); + +STATIC +EFI_STATUS +ExecuteMOVsnw ( + IN VM_CONTEXT *VmPtr + ); + +// +// Data manipulation subfunctions +// +STATIC +UINT64 +ExecuteNOT ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteNEG ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteADD ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteSUB ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteMUL ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteMULU ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteDIV ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteDIVU ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteMOD ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteMODU ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteAND ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteOR ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteXOR ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteSHL ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteSHR ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteASHR ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteEXTNDB ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteEXTNDW ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +STATIC +UINT64 +ExecuteEXTNDD ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ); + +// +// Once we retrieve the operands for the data manipulation instructions, +// call these functions to perform the operation. +// +static CONST DATA_MANIP_EXEC_FUNCTION mDataManipDispatchTable[] = { + ExecuteNOT, + ExecuteNEG, + ExecuteADD, + ExecuteSUB, + ExecuteMUL, + ExecuteMULU, + ExecuteDIV, + ExecuteDIVU, + ExecuteMOD, + ExecuteMODU, + ExecuteAND, + ExecuteOR, + ExecuteXOR, + ExecuteSHL, + ExecuteSHR, + ExecuteASHR, + ExecuteEXTNDB, + ExecuteEXTNDW, + ExecuteEXTNDD, +}; + +static CONST VM_TABLE_ENTRY mVmOpcodeTable[] = { + { ExecuteBREAK }, // opcode 0x00 + { ExecuteJMP }, // opcode 0x01 + { ExecuteJMP8 }, // opcode 0x02 + { ExecuteCALL }, // opcode 0x03 + { ExecuteRET }, // opcode 0x04 + { ExecuteCMP }, // opcode 0x05 CMPeq + { ExecuteCMP }, // opcode 0x06 CMPlte + { ExecuteCMP }, // opcode 0x07 CMPgte + { ExecuteCMP }, // opcode 0x08 CMPulte + { ExecuteCMP }, // opcode 0x09 CMPugte + { ExecuteUnsignedDataManip }, // opcode 0x0A NOT + { ExecuteSignedDataManip }, // opcode 0x0B NEG + { ExecuteSignedDataManip }, // opcode 0x0C ADD + { ExecuteSignedDataManip }, // opcode 0x0D SUB + { ExecuteSignedDataManip }, // opcode 0x0E MUL + { ExecuteUnsignedDataManip }, // opcode 0x0F MULU + { ExecuteSignedDataManip }, // opcode 0x10 DIV + { ExecuteUnsignedDataManip }, // opcode 0x11 DIVU + { ExecuteSignedDataManip }, // opcode 0x12 MOD + { ExecuteUnsignedDataManip }, // opcode 0x13 MODU + { ExecuteUnsignedDataManip }, // opcode 0x14 AND + { ExecuteUnsignedDataManip }, // opcode 0x15 OR + { ExecuteUnsignedDataManip }, // opcode 0x16 XOR + { ExecuteUnsignedDataManip }, // opcode 0x17 SHL + { ExecuteUnsignedDataManip }, // opcode 0x18 SHR + { ExecuteSignedDataManip }, // opcode 0x19 ASHR + { ExecuteUnsignedDataManip }, // opcode 0x1A EXTNDB + { ExecuteUnsignedDataManip }, // opcode 0x1B EXTNDW + { ExecuteUnsignedDataManip }, // opcode 0x1C EXTNDD + { ExecuteMOVxx }, // opcode 0x1D MOVBW + { ExecuteMOVxx }, // opcode 0x1E MOVWW + { ExecuteMOVxx }, // opcode 0x1F MOVDW + { ExecuteMOVxx }, // opcode 0x20 MOVQW + { ExecuteMOVxx }, // opcode 0x21 MOVBD + { ExecuteMOVxx }, // opcode 0x22 MOVWD + { ExecuteMOVxx }, // opcode 0x23 MOVDD + { ExecuteMOVxx }, // opcode 0x24 MOVQD + { ExecuteMOVsnw }, // opcode 0x25 MOVsnw + { ExecuteMOVsnd }, // opcode 0x26 MOVsnd + { NULL }, // opcode 0x27 + { ExecuteMOVxx }, // opcode 0x28 MOVqq + { ExecuteLOADSP }, // opcode 0x29 LOADSP SP1, R2 + { ExecuteSTORESP }, // opcode 0x2A STORESP R1, SP2 + { ExecutePUSH }, // opcode 0x2B PUSH {@}R1 [imm16] + { ExecutePOP }, // opcode 0x2C POP {@}R1 [imm16] + { ExecuteCMPI }, // opcode 0x2D CMPIEQ + { ExecuteCMPI }, // opcode 0x2E CMPILTE + { ExecuteCMPI }, // opcode 0x2F CMPIGTE + { ExecuteCMPI }, // opcode 0x30 CMPIULTE + { ExecuteCMPI }, // opcode 0x31 CMPIUGTE + { ExecuteMOVxx }, // opcode 0x32 MOVN + { ExecuteMOVxx }, // opcode 0x33 MOVND + { NULL }, // opcode 0x34 + { ExecutePUSHn }, // opcode 0x35 + { ExecutePOPn }, // opcode 0x36 + { ExecuteMOVI }, // opcode 0x37 - mov immediate data + { ExecuteMOVIn }, // opcode 0x38 - mov immediate natural + { ExecuteMOVREL } // opcode 0x39 - move data relative to PC +}; + +// +// Length of JMP instructions, depending on upper two bits of opcode. +// +static CONST UINT8 mJMPLen[] = { 2, 2, 6, 10 }; + +// +// Simple Debugger Protocol GUID +// +EFI_GUID mEbcSimpleDebuggerProtocolGuid = EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL_GUID; + +EFI_STATUS +EbcExecuteInstructions ( + IN EFI_EBC_VM_TEST_PROTOCOL *This, + IN VM_CONTEXT *VmPtr, + IN OUT UINTN *InstructionCount + ) +/*++ + +Routine Description: + + Given a pointer to a new VM context, execute one or more instructions. This + function is only used for test purposes via the EBC VM test protocol. + +Arguments: + + This - pointer to protocol interface + VmPtr - pointer to a VM context + InstructionCount - how many instructions to execute. 0 if don't count. + +Returns: + + EFI_UNSUPPORTED + EFI_SUCCESS + +--*/ +{ + UINTN ExecFunc; + EFI_STATUS Status; + UINTN InstructionsLeft; + UINTN SavedInstructionCount; + + Status = EFI_SUCCESS; + + if (*InstructionCount == 0) { + InstructionsLeft = 1; + } else { + InstructionsLeft = *InstructionCount; + } + + SavedInstructionCount = *InstructionCount; + *InstructionCount = 0; + + // + // Index into the opcode table using the opcode byte for this instruction. + // This gives you the execute function, which we first test for null, then + // call it if it's not null. + // + while (InstructionsLeft != 0) { + ExecFunc = (UINTN) mVmOpcodeTable[(*VmPtr->Ip & 0x3F)].ExecuteFunction; + if (ExecFunc == (UINTN) NULL) { + EbcDebugSignalException (EXCEPT_EBC_INVALID_OPCODE, EXCEPTION_FLAG_FATAL, VmPtr); + return EFI_UNSUPPORTED; + } else { + mVmOpcodeTable[(*VmPtr->Ip & 0x3F)].ExecuteFunction (VmPtr); + *InstructionCount = *InstructionCount + 1; + } + + // + // Decrement counter if applicable + // + if (SavedInstructionCount != 0) { + InstructionsLeft--; + } + } + + return Status; +} + +EFI_STATUS +EbcExecute ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + + Execute an EBC image from an entry point or from a published protocol. + +Arguments: + + VmPtr - pointer to prepared VM context. + +Returns: + + Standard EBC status. + +--*/ +{ + UINTN ExecFunc; + UINT8 StackCorrupted; + EFI_STATUS Status; + EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL *EbcSimpleDebugger; + + // + // end DEBUG_CODE + // + EbcSimpleDebugger = NULL; + Status = EFI_SUCCESS; + StackCorrupted = 0; + + // + // Make sure the magic value has been put on the stack before we got here. + // + if (*VmPtr->StackMagicPtr != (UINTN) VM_STACK_KEY_VALUE) { + StackCorrupted = 1; + } + + VmPtr->FramePtr = (VOID *) ((UINT8 *) (UINTN) VmPtr->R[0] + 8); + + // + // Try to get the debug support for EBC + // + DEBUG_CODE ( + Status = gBS->LocateProtocol ( + &mEbcSimpleDebuggerProtocolGuid, + NULL, + (VOID **) &EbcSimpleDebugger + ); + if (EFI_ERROR (Status)) { + EbcSimpleDebugger = NULL; + } + ); + + // + // Save the start IP for debug. For example, if we take an exception we + // can print out the location of the exception relative to the entry point, + // which could then be used in a disassembly listing to find the problem. + // + VmPtr->EntryPoint = (VOID *) VmPtr->Ip; + + // + // We'll wait for this flag to know when we're done. The RET + // instruction sets it if it runs out of stack. + // + VmPtr->StopFlags = 0; + while (!(VmPtr->StopFlags & STOPFLAG_APP_DONE)) { + // + // If we've found a simple debugger protocol, call it + // + DEBUG_CODE ( + if (EbcSimpleDebugger != NULL) { + EbcSimpleDebugger->Debugger (EbcSimpleDebugger, VmPtr); + } + ); + + // + // Verify the opcode is in range. Otherwise generate an exception. + // + if ((*VmPtr->Ip & OPCODE_M_OPCODE) >= (sizeof (mVmOpcodeTable) / sizeof (mVmOpcodeTable[0]))) { + EbcDebugSignalException (EXCEPT_EBC_INVALID_OPCODE, EXCEPTION_FLAG_FATAL, VmPtr); + Status = EFI_UNSUPPORTED; + goto Done; + } + // + // Use the opcode bits to index into the opcode dispatch table. If the + // function pointer is null then generate an exception. + // + ExecFunc = (UINTN) mVmOpcodeTable[(*VmPtr->Ip & OPCODE_M_OPCODE)].ExecuteFunction; + if (ExecFunc == (UINTN) NULL) { + EbcDebugSignalException (EXCEPT_EBC_INVALID_OPCODE, EXCEPTION_FLAG_FATAL, VmPtr); + Status = EFI_UNSUPPORTED; + goto Done; + } + // + // The EBC VM is a strongly ordered processor, so perform a fence operation before + // and after each instruction is executed. + // + MemoryFence (); + + mVmOpcodeTable[(*VmPtr->Ip & OPCODE_M_OPCODE)].ExecuteFunction (VmPtr); + + MemoryFence (); + + // + // If the step flag is set, signal an exception and continue. We don't + // clear it here. Assuming the debugger is responsible for clearing it. + // + if (VMFLAG_ISSET (VmPtr, VMFLAGS_STEP)) { + EbcDebugSignalException (EXCEPT_EBC_STEP, EXCEPTION_FLAG_NONE, VmPtr); + } + // + // Make sure stack has not been corrupted. Only report it once though. + // + if (!StackCorrupted && (*VmPtr->StackMagicPtr != (UINTN) VM_STACK_KEY_VALUE)) { + EbcDebugSignalException (EXCEPT_EBC_STACK_FAULT, EXCEPTION_FLAG_FATAL, VmPtr); + StackCorrupted = 1; + } + } + +Done: + return Status; +} + +STATIC +EFI_STATUS +ExecuteMOVxx ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + + Execute the MOVxx instructions. + +Arguments: + + VmPtr - pointer to a VM context. + +Returns: + + EFI_UNSUPPORTED + EFI_SUCCESS + +Instruction format: + + MOV[b|w|d|q|n]{w|d} {@}R1 {Index16|32}, {@}R2 {Index16|32} + MOVqq {@}R1 {Index64}, {@}R2 {Index64} + + Copies contents of [R2] -> [R1], zero extending where required. + + First character indicates the size of the move. + Second character indicates the size of the index(s). + + Invalid to have R1 direct with index. + +--*/ +{ + UINT8 Opcode; + UINT8 OpcMasked; + UINT8 Operands; + UINT8 Size; + UINT8 MoveSize; + INT16 Index16; + INT32 Index32; + INT64 Index64Op1; + INT64 Index64Op2; + UINT64 Data64; + UINT64 DataMask; + UINTN Source; + + Opcode = GETOPCODE (VmPtr); + OpcMasked = (UINT8) (Opcode & OPCODE_M_OPCODE); + + // + // Get the operands byte so we can get R1 and R2 + // + Operands = GETOPERANDS (VmPtr); + + // + // Assume no indexes + // + Index64Op1 = 0; + Index64Op2 = 0; + Data64 = 0; + + // + // Determine if we have an index/immediate data. Base instruction size + // is 2 (opcode + operands). Add to this size each index specified. + // + Size = 2; + if (Opcode & (OPCODE_M_IMMED_OP1 | OPCODE_M_IMMED_OP2)) { + // + // Determine size of the index from the opcode. Then get it. + // + if ((OpcMasked <= OPCODE_MOVQW) || (OpcMasked == OPCODE_MOVNW)) { + // + // MOVBW, MOVWW, MOVDW, MOVQW, and MOVNW have 16-bit immediate index. + // Get one or both index values. + // + if (Opcode & OPCODE_M_IMMED_OP1) { + Index16 = VmReadIndex16 (VmPtr, 2); + Index64Op1 = (INT64) Index16; + Size += sizeof (UINT16); + } + + if (Opcode & OPCODE_M_IMMED_OP2) { + Index16 = VmReadIndex16 (VmPtr, Size); + Index64Op2 = (INT64) Index16; + Size += sizeof (UINT16); + } + } else if ((OpcMasked <= OPCODE_MOVQD) || (OpcMasked == OPCODE_MOVND)) { + // + // MOVBD, MOVWD, MOVDD, MOVQD, and MOVND have 32-bit immediate index + // + if (Opcode & OPCODE_M_IMMED_OP1) { + Index32 = VmReadIndex32 (VmPtr, 2); + Index64Op1 = (INT64) Index32; + Size += sizeof (UINT32); + } + + if (Opcode & OPCODE_M_IMMED_OP2) { + Index32 = VmReadIndex32 (VmPtr, Size); + Index64Op2 = (INT64) Index32; + Size += sizeof (UINT32); + } + } else if (OpcMasked == OPCODE_MOVQQ) { + // + // MOVqq -- only form with a 64-bit index + // + if (Opcode & OPCODE_M_IMMED_OP1) { + Index64Op1 = VmReadIndex64 (VmPtr, 2); + Size += sizeof (UINT64); + } + + if (Opcode & OPCODE_M_IMMED_OP2) { + Index64Op2 = VmReadIndex64 (VmPtr, Size); + Size += sizeof (UINT64); + } + } else { + // + // Obsolete MOVBQ, MOVWQ, MOVDQ, and MOVNQ have 64-bit immediate index + // + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return EFI_UNSUPPORTED; + } + } + // + // Determine the size of the move, and create a mask for it so we can + // clear unused bits. + // + if ((OpcMasked == OPCODE_MOVBW) || (OpcMasked == OPCODE_MOVBD)) { + MoveSize = DATA_SIZE_8; + DataMask = 0xFF; + } else if ((OpcMasked == OPCODE_MOVWW) || (OpcMasked == OPCODE_MOVWD)) { + MoveSize = DATA_SIZE_16; + DataMask = 0xFFFF; + } else if ((OpcMasked == OPCODE_MOVDW) || (OpcMasked == OPCODE_MOVDD)) { + MoveSize = DATA_SIZE_32; + DataMask = 0xFFFFFFFF; + } else if ((OpcMasked == OPCODE_MOVQW) || (OpcMasked == OPCODE_MOVQD) || (OpcMasked == OPCODE_MOVQQ)) { + MoveSize = DATA_SIZE_64; + DataMask = (UINT64)~0; + } else if ((OpcMasked == OPCODE_MOVNW) || (OpcMasked == OPCODE_MOVND)) { + MoveSize = DATA_SIZE_N; + DataMask = (UINT64)~0 >> (64 - 8 * sizeof (UINTN)); + } else { + // + // We were dispatched to this function and we don't recognize the opcode + // + EbcDebugSignalException (EXCEPT_EBC_UNDEFINED, EXCEPTION_FLAG_FATAL, VmPtr); + return EFI_UNSUPPORTED; + } + // + // Now get the source address + // + if (OPERAND2_INDIRECT (Operands)) { + // + // Indirect form @R2. Compute address of operand2 + // + Source = (UINTN) (VmPtr->R[OPERAND2_REGNUM (Operands)] + Index64Op2); + // + // Now get the data from the source. Always 0-extend and let the compiler + // sign-extend where required. + // + switch (MoveSize) { + case DATA_SIZE_8: + Data64 = (UINT64) (UINT8) VmReadMem8 (VmPtr, Source); + break; + + case DATA_SIZE_16: + Data64 = (UINT64) (UINT16) VmReadMem16 (VmPtr, Source); + break; + + case DATA_SIZE_32: + Data64 = (UINT64) (UINT32) VmReadMem32 (VmPtr, Source); + break; + + case DATA_SIZE_64: + Data64 = (UINT64) VmReadMem64 (VmPtr, Source); + break; + + case DATA_SIZE_N: + Data64 = (UINT64) (UINTN) VmReadMemN (VmPtr, Source); + break; + + default: + // + // not reached + // + break; + } + } else { + // + // Not indirect source: MOVxx {@}Rx, Ry [Index] + // + Data64 = VmPtr->R[OPERAND2_REGNUM (Operands)] + Index64Op2; + // + // Did Operand2 have an index? If so, treat as two signed values since + // indexes are signed values. + // + if (Opcode & OPCODE_M_IMMED_OP2) { + // + // NOTE: need to find a way to fix this, most likely by changing the VM + // implementation to remove the stack gap. To do that, we'd need to + // allocate stack space for the VM and actually set the system + // stack pointer to the allocated buffer when the VM starts. + // + // Special case -- if someone took the address of a function parameter + // then we need to make sure it's not in the stack gap. We can identify + // this situation if (Operand2 register == 0) && (Operand2 is direct) + // && (Index applies to Operand2) && (Index > 0) && (Operand1 register != 0) + // Situations that to be aware of: + // * stack adjustments at beginning and end of functions R0 = R0 += stacksize + // + if ((OPERAND2_REGNUM (Operands) == 0) && + (!OPERAND2_INDIRECT (Operands)) && + (Index64Op2 > 0) && + (OPERAND1_REGNUM (Operands) == 0) && + (OPERAND1_INDIRECT (Operands)) + ) { + Data64 = (UINT64) ConvertStackAddr (VmPtr, (UINTN) (INT64) Data64); + } + } + } + // + // Now write it back + // + if (OPERAND1_INDIRECT (Operands)) { + // + // Reuse the Source variable to now be dest. + // + Source = (UINTN) (VmPtr->R[OPERAND1_REGNUM (Operands)] + Index64Op1); + // + // Do the write based on the size + // + switch (MoveSize) { + case DATA_SIZE_8: + VmWriteMem8 (VmPtr, Source, (UINT8) Data64); + break; + + case DATA_SIZE_16: + VmWriteMem16 (VmPtr, Source, (UINT16) Data64); + break; + + case DATA_SIZE_32: + VmWriteMem32 (VmPtr, Source, (UINT32) Data64); + break; + + case DATA_SIZE_64: + VmWriteMem64 (VmPtr, Source, Data64); + break; + + case DATA_SIZE_N: + VmWriteMemN (VmPtr, Source, (UINTN) Data64); + break; + + default: + // + // not reached + // + break; + } + } else { + // + // Operand1 direct. + // Make sure we didn't have an index on operand1. + // + if (Opcode & OPCODE_M_IMMED_OP1) { + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return EFI_UNSUPPORTED; + } + // + // Direct storage in register. Clear unused bits and store back to + // register. + // + VmPtr->R[OPERAND1_REGNUM (Operands)] = Data64 & DataMask; + } + // + // Advance the instruction pointer + // + VmPtr->Ip += Size; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteBREAK ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + + Execute the EBC BREAK instruction + +Arguments: + + VmPtr - pointer to current VM context + +Returns: + + EFI_UNSUPPORTED + EFI_SUCCESS + +--*/ +{ + UINT8 Operands; + VOID *EbcEntryPoint; + VOID *Thunk; + EFI_STATUS Status; + UINT64 U64EbcEntryPoint; + INT32 Offset; + + Operands = GETOPERANDS (VmPtr); + switch (Operands) { + // + // Runaway program break. Generate an exception and terminate + // + case 0: + EbcDebugSignalException (EXCEPT_EBC_BAD_BREAK, EXCEPTION_FLAG_FATAL, VmPtr); + break; + + // + // Get VM version -- return VM revision number in R7 + // + case 1: + // + // Bits: + // 63-17 = 0 + // 16-8 = Major version + // 7-0 = Minor version + // + VmPtr->R[7] = GetVmVersion (); + break; + + // + // Debugger breakpoint + // + case 3: + VmPtr->StopFlags |= STOPFLAG_BREAKPOINT; + // + // See if someone has registered a handler + // + EbcDebugSignalException ( + EXCEPT_EBC_BREAKPOINT, + EXCEPTION_FLAG_NONE, + VmPtr + ); + // + // Don't advance the IP + // + return EFI_UNSUPPORTED; + break; + + // + // System call, which there are none, so NOP it. + // + case 4: + break; + + // + // Create a thunk for EBC code. R7 points to a 32-bit (in a 64-bit slot) + // "offset from self" pointer to the EBC entry point. + // After we're done, *(UINT64 *)R7 will be the address of the new thunk. + // + case 5: + Offset = (INT32) VmReadMem32 (VmPtr, (UINTN) VmPtr->R[7]); + U64EbcEntryPoint = (UINT64) (VmPtr->R[7] + Offset + 4); + EbcEntryPoint = (VOID *) (UINTN) U64EbcEntryPoint; + + // + // Now create a new thunk + // + Status = EbcCreateThunks (VmPtr->ImageHandle, EbcEntryPoint, &Thunk, 0); + + // + // Finally replace the EBC entry point memory with the thunk address + // + VmWriteMem64 (VmPtr, (UINTN) VmPtr->R[7], (UINT64) (UINTN) Thunk); + break; + + // + // Compiler setting version per value in R7 + // + case 6: + VmPtr->CompilerVersion = (UINT32) VmPtr->R[7]; + // + // Check compiler version against VM version? + // + break; + + // + // Unhandled break code. Signal exception. + // + default: + EbcDebugSignalException (EXCEPT_EBC_BAD_BREAK, EXCEPTION_FLAG_FATAL, VmPtr); + break; + } + // + // Advance IP + // + VmPtr->Ip += 2; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteJMP ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the JMP instruction + +Arguments: + VmPtr - pointer to VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + JMP64{cs|cc} Immed64 + JMP32{cs|cc} {@}R1 {Immed32|Index32} + +Encoding: + b0.7 - immediate data present + b0.6 - 1 = 64 bit immediate data + 0 = 32 bit immediate data + b1.7 - 1 = conditional + b1.6 1 = CS (condition set) + 0 = CC (condition clear) + b1.4 1 = relative address + 0 = absolute address + b1.3 1 = operand1 indirect + b1.2-0 operand 1 + +--*/ +{ + UINT8 Opcode; + UINT8 CompareSet; + UINT8 ConditionFlag; + UINT8 Size; + UINT8 Operand; + UINT64 Data64; + INT32 Index32; + UINTN Addr; + + Operand = GETOPERANDS (VmPtr); + Opcode = GETOPCODE (VmPtr); + + // + // Get instruction length from the opcode. The upper two bits are used here + // to index into the length array. + // + Size = mJMPLen[(Opcode >> 6) & 0x03]; + + // + // Decode instruction conditions + // If we haven't met the condition, then simply advance the IP and return. + // + CompareSet = (UINT8) ((Operand & JMP_M_CS) ? 1 : 0); + ConditionFlag = (UINT8) VMFLAG_ISSET (VmPtr, VMFLAGS_CC); + if (Operand & CONDITION_M_CONDITIONAL) { + if (CompareSet != ConditionFlag) { + VmPtr->Ip += Size; + return EFI_SUCCESS; + } + } + // + // Check for 64-bit form and do it right away since it's the most + // straight-forward form. + // + if (Opcode & OPCODE_M_IMMDATA64) { + // + // Double check for immediate-data, which is required. If not there, + // then signal an exception + // + if (!(Opcode & OPCODE_M_IMMDATA)) { + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_ERROR, + VmPtr + ); + return EFI_UNSUPPORTED; + } + // + // 64-bit immediate data is full address. Read the immediate data, + // check for alignment, and jump absolute. + // + Data64 = VmReadImmed64 (VmPtr, 2); + if (!IS_ALIGNED ((UINTN) Data64, sizeof (UINT16))) { + EbcDebugSignalException ( + EXCEPT_EBC_ALIGNMENT_CHECK, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + + return EFI_UNSUPPORTED; + } + + // + // Take jump -- relative or absolute + // + if (Operand & JMP_M_RELATIVE) { + VmPtr->Ip += (UINTN) Data64 + Size; + } else { + VmPtr->Ip = (VMIP) (UINTN) Data64; + } + + return EFI_SUCCESS; + } + // + // 32-bit forms: + // Get the index if there is one. May be either an index, or an immediate + // offset depending on indirect operand. + // JMP32 @R1 Index32 -- immediate data is an index + // JMP32 R1 Immed32 -- immedate data is an offset + // + if (Opcode & OPCODE_M_IMMDATA) { + if (OPERAND1_INDIRECT (Operand)) { + Index32 = VmReadIndex32 (VmPtr, 2); + } else { + Index32 = VmReadImmed32 (VmPtr, 2); + } + } else { + Index32 = 0; + } + // + // Get the register data. If R == 0, then special case where it's ignored. + // + if (OPERAND1_REGNUM (Operand) == 0) { + Data64 = 0; + } else { + Data64 = OPERAND1_REGDATA (VmPtr, Operand); + } + // + // Decode the forms + // + if (OPERAND1_INDIRECT (Operand)) { + // + // Form: JMP32 @Rx {Index32} + // + Addr = VmReadMemN (VmPtr, (UINTN) Data64 + Index32); + if (!IS_ALIGNED ((UINTN) Addr, sizeof (UINT16))) { + EbcDebugSignalException ( + EXCEPT_EBC_ALIGNMENT_CHECK, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + + return EFI_UNSUPPORTED; + } + + if (Operand & JMP_M_RELATIVE) { + VmPtr->Ip += (UINTN) Addr + Size; + } else { + VmPtr->Ip = (VMIP) Addr; + } + } else { + // + // Form: JMP32 Rx {Immed32} + // + Addr = (UINTN) (Data64 + Index32); + if (!IS_ALIGNED ((UINTN) Addr, sizeof (UINT16))) { + EbcDebugSignalException ( + EXCEPT_EBC_ALIGNMENT_CHECK, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + + return EFI_UNSUPPORTED; + } + + if (Operand & JMP_M_RELATIVE) { + VmPtr->Ip += (UINTN) Addr + Size; + } else { + VmPtr->Ip = (VMIP) Addr; + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteJMP8 ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the EBC JMP8 instruction + +Arguments: + VmPtr - pointer to a VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + JMP8{cs|cc} Offset/2 + +--*/ +{ + UINT8 Opcode; + UINT8 ConditionFlag; + UINT8 CompareSet; + INT8 Offset; + + // + // Decode instruction. + // + Opcode = GETOPCODE (VmPtr); + CompareSet = (UINT8) ((Opcode & JMP_M_CS) ? 1 : 0); + ConditionFlag = (UINT8) VMFLAG_ISSET (VmPtr, VMFLAGS_CC); + + // + // If we haven't met the condition, then simply advance the IP and return + // + if (Opcode & CONDITION_M_CONDITIONAL) { + if (CompareSet != ConditionFlag) { + VmPtr->Ip += 2; + return EFI_SUCCESS; + } + } + // + // Get the offset from the instruction stream. It's relative to the + // following instruction, and divided by 2. + // + Offset = VmReadImmed8 (VmPtr, 1); + // + // Want to check for offset == -2 and then raise an exception? + // + VmPtr->Ip += (Offset * 2) + 2; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteMOVI ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + + Execute the EBC MOVI + +Arguments: + + VmPtr - pointer to a VM context + +Returns: + + Standard EFI_STATUS + +Instruction syntax: + + MOVI[b|w|d|q][w|d|q] {@}R1 {Index16}, ImmData16|32|64 + + First variable character specifies the move size + Second variable character specifies size of the immediate data + + Sign-extend the immediate data to the size of the operation, and zero-extend + if storing to a register. + + Operand1 direct with index/immed is invalid. + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + UINT8 Size; + INT16 Index16; + INT64 ImmData64; + UINT64 Op1; + UINT64 Mask64; + + // + // Get the opcode and operands byte so we can get R1 and R2 + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + + // + // Get the index (16-bit) if present + // + if (Operands & MOVI_M_IMMDATA) { + Index16 = VmReadIndex16 (VmPtr, 2); + Size = 4; + } else { + Index16 = 0; + Size = 2; + } + // + // Extract the immediate data. Sign-extend always. + // + if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH16) { + ImmData64 = (INT64) (INT16) VmReadImmed16 (VmPtr, Size); + Size += 2; + } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH32) { + ImmData64 = (INT64) (INT32) VmReadImmed32 (VmPtr, Size); + Size += 4; + } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH64) { + ImmData64 = (INT64) VmReadImmed64 (VmPtr, Size); + Size += 8; + } else { + // + // Invalid encoding + // + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return EFI_UNSUPPORTED; + } + // + // Now write back the result + // + if (!OPERAND1_INDIRECT (Operands)) { + // + // Operand1 direct. Make sure it didn't have an index. + // + if (Operands & MOVI_M_IMMDATA) { + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return EFI_UNSUPPORTED; + } + // + // Writing directly to a register. Clear unused bits. + // + if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH8) { + Mask64 = 0x000000FF; + } else if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH16) { + Mask64 = 0x0000FFFF; + } else if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH32) { + Mask64 = 0x00000000FFFFFFFF; + } else { + Mask64 = (UINT64)~0; + } + + VmPtr->R[OPERAND1_REGNUM (Operands)] = ImmData64 & Mask64; + } else { + // + // Get the address then write back based on size of the move + // + Op1 = (UINT64) VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16; + if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH8) { + VmWriteMem8 (VmPtr, (UINTN) Op1, (UINT8) ImmData64); + } else if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH16) { + VmWriteMem16 (VmPtr, (UINTN) Op1, (UINT16) ImmData64); + } else if ((Operands & MOVI_M_MOVEWIDTH) == MOVI_MOVEWIDTH32) { + VmWriteMem32 (VmPtr, (UINTN) Op1, (UINT32) ImmData64); + } else { + VmWriteMem64 (VmPtr, (UINTN) Op1, ImmData64); + } + } + // + // Advance the instruction pointer + // + VmPtr->Ip += Size; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteMOVIn ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + + Execute the EBC MOV immediate natural. This instruction moves an immediate + index value into a register or memory location. + +Arguments: + + VmPtr - pointer to a VM context + +Returns: + + Standard EFI_STATUS + +Instruction syntax: + + MOVIn[w|d|q] {@}R1 {Index16}, Index16|32|64 + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + UINT8 Size; + INT16 Index16; + INT16 ImmedIndex16; + INT32 ImmedIndex32; + INT64 ImmedIndex64; + UINT64 Op1; + + // + // Get the opcode and operands byte so we can get R1 and R2 + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + + // + // Get the operand1 index (16-bit) if present + // + if (Operands & MOVI_M_IMMDATA) { + Index16 = VmReadIndex16 (VmPtr, 2); + Size = 4; + } else { + Index16 = 0; + Size = 2; + } + // + // Extract the immediate data and convert to a 64-bit index. + // + if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH16) { + ImmedIndex16 = VmReadIndex16 (VmPtr, Size); + ImmedIndex64 = (INT64) ImmedIndex16; + Size += 2; + } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH32) { + ImmedIndex32 = VmReadIndex32 (VmPtr, Size); + ImmedIndex64 = (INT64) ImmedIndex32; + Size += 4; + } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH64) { + ImmedIndex64 = VmReadIndex64 (VmPtr, Size); + Size += 8; + } else { + // + // Invalid encoding + // + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return EFI_UNSUPPORTED; + } + // + // Now write back the result + // + if (!OPERAND1_INDIRECT (Operands)) { + // + // Check for MOVIn R1 Index16, Immed (not indirect, with index), which + // is illegal + // + if (Operands & MOVI_M_IMMDATA) { + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return EFI_UNSUPPORTED; + } + + VmPtr->R[OPERAND1_REGNUM (Operands)] = ImmedIndex64; + } else { + // + // Get the address + // + Op1 = (UINT64) VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16; + VmWriteMemN (VmPtr, (UINTN) Op1, (INTN) ImmedIndex64); + } + // + // Advance the instruction pointer + // + VmPtr->Ip += Size; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteMOVREL ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + + Execute the EBC MOVREL instruction. + Dest <- Ip + ImmData + +Arguments: + + VmPtr - pointer to a VM context + +Returns: + + Standard EFI_STATUS + +Instruction syntax: + + MOVREL[w|d|q] {@}R1 {Index16}, ImmData16|32|64 + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + UINT8 Size; + INT16 Index16; + INT64 ImmData64; + UINT64 Op1; + UINT64 Op2; + + // + // Get the opcode and operands byte so we can get R1 and R2 + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + + // + // Get the Operand 1 index (16-bit) if present + // + if (Operands & MOVI_M_IMMDATA) { + Index16 = VmReadIndex16 (VmPtr, 2); + Size = 4; + } else { + Index16 = 0; + Size = 2; + } + // + // Get the immediate data. + // + if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH16) { + ImmData64 = (INT64) VmReadImmed16 (VmPtr, Size); + Size += 2; + } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH32) { + ImmData64 = (INT64) VmReadImmed32 (VmPtr, Size); + Size += 4; + } else if ((Opcode & MOVI_M_DATAWIDTH) == MOVI_DATAWIDTH64) { + ImmData64 = VmReadImmed64 (VmPtr, Size); + Size += 8; + } else { + // + // Invalid encoding + // + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return EFI_UNSUPPORTED; + } + // + // Compute the value and write back the result + // + Op2 = (UINT64) ((INT64) ((UINT64) (UINTN) VmPtr->Ip) + (INT64) ImmData64 + Size); + if (!OPERAND1_INDIRECT (Operands)) { + // + // Check for illegal combination of operand1 direct with immediate data + // + if (Operands & MOVI_M_IMMDATA) { + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return EFI_UNSUPPORTED; + } + + VmPtr->R[OPERAND1_REGNUM (Operands)] = (VM_REGISTER) Op2; + } else { + // + // Get the address = [Rx] + Index16 + // Write back the result. Always a natural size write, since + // we're talking addresses here. + // + Op1 = (UINT64) VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16; + VmWriteMemN (VmPtr, (UINTN) Op1, (UINTN) Op2); + } + // + // Advance the instruction pointer + // + VmPtr->Ip += Size; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteMOVsnw ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + + Execute the EBC MOVsnw instruction. This instruction loads a signed + natural value from memory or register to another memory or register. On + 32-bit machines, the value gets sign-extended to 64 bits if the destination + is a register. + +Arguments: + + VmPtr - pointer to a VM context + +Returns: + + Standard EFI_STATUS + +Instruction syntax: + + MOVsnw {@}R1 {Index16}, {@}R2 {Index16|Immed16} + + 0:7 1=>operand1 index present + 0:6 1=>operand2 index present + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + UINT8 Size; + INT16 Op1Index; + INT16 Op2Index; + UINT64 Op2; + + // + // Get the opcode and operand bytes + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + + Op1Index = Op2Index = 0; + + // + // Get the indexes if present. + // + Size = 2; + if (Opcode & OPCODE_M_IMMED_OP1) { + if (OPERAND1_INDIRECT (Operands)) { + Op1Index = VmReadIndex16 (VmPtr, 2); + } else { + // + // Illegal form operand1 direct with index: MOVsnw R1 Index16, {@}R2 + // + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return EFI_UNSUPPORTED; + } + + Size += sizeof (UINT16); + } + + if (Opcode & OPCODE_M_IMMED_OP2) { + if (OPERAND2_INDIRECT (Operands)) { + Op2Index = VmReadIndex16 (VmPtr, Size); + } else { + Op2Index = VmReadImmed16 (VmPtr, Size); + } + + Size += sizeof (UINT16); + } + // + // Get the data from the source. + // + Op2 = (INT64) ((INTN) (VmPtr->R[OPERAND2_REGNUM (Operands)] + Op2Index)); + if (OPERAND2_INDIRECT (Operands)) { + Op2 = (INT64) (INTN) VmReadMemN (VmPtr, (UINTN) Op2); + } + // + // Now write back the result. + // + if (!OPERAND1_INDIRECT (Operands)) { + VmPtr->R[OPERAND1_REGNUM (Operands)] = Op2; + } else { + VmWriteMemN (VmPtr, (UINTN) (VmPtr->R[OPERAND1_REGNUM (Operands)] + Op1Index), (UINTN) Op2); + } + // + // Advance the instruction pointer + // + VmPtr->Ip += Size; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteMOVsnd ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + + Execute the EBC MOVsnw instruction. This instruction loads a signed + natural value from memory or register to another memory or register. On + 32-bit machines, the value gets sign-extended to 64 bits if the destination + is a register. + +Arguments: + + VmPtr - pointer to a VM context + +Returns: + + Standard EFI_STATUS + +Instruction syntax: + + MOVsnd {@}R1 {Indx32}, {@}R2 {Index32|Immed32} + + 0:7 1=>operand1 index present + 0:6 1=>operand2 index present + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + UINT8 Size; + INT32 Op1Index; + INT32 Op2Index; + UINT64 Op2; + + // + // Get the opcode and operand bytes + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + + Op1Index = Op2Index = 0; + + // + // Get the indexes if present. + // + Size = 2; + if (Opcode & OPCODE_M_IMMED_OP1) { + if (OPERAND1_INDIRECT (Operands)) { + Op1Index = VmReadIndex32 (VmPtr, 2); + } else { + // + // Illegal form operand1 direct with index: MOVsnd R1 Index16,.. + // + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return EFI_UNSUPPORTED; + } + + Size += sizeof (UINT32); + } + + if (Opcode & OPCODE_M_IMMED_OP2) { + if (OPERAND2_INDIRECT (Operands)) { + Op2Index = VmReadIndex32 (VmPtr, Size); + } else { + Op2Index = VmReadImmed32 (VmPtr, Size); + } + + Size += sizeof (UINT32); + } + // + // Get the data from the source. + // + Op2 = (INT64) ((INTN) (VmPtr->R[OPERAND2_REGNUM (Operands)] + Op2Index)); + if (OPERAND2_INDIRECT (Operands)) { + Op2 = (INT64) (INTN) VmReadMemN (VmPtr, (UINTN) Op2); + } + // + // Now write back the result. + // + if (!OPERAND1_INDIRECT (Operands)) { + VmPtr->R[OPERAND1_REGNUM (Operands)] = Op2; + } else { + VmWriteMemN (VmPtr, (UINTN) (VmPtr->R[OPERAND1_REGNUM (Operands)] + Op1Index), (UINTN) Op2); + } + // + // Advance the instruction pointer + // + VmPtr->Ip += Size; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecutePUSHn ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the EBC PUSHn instruction + +Arguments: + VmPtr - pointer to a VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + PUSHn {@}R1 {Index16|Immed16} + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + INT16 Index16; + UINTN DataN; + + // + // Get opcode and operands + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + + // + // Get index if present + // + if (Opcode & PUSHPOP_M_IMMDATA) { + if (OPERAND1_INDIRECT (Operands)) { + Index16 = VmReadIndex16 (VmPtr, 2); + } else { + Index16 = VmReadImmed16 (VmPtr, 2); + } + + VmPtr->Ip += 4; + } else { + Index16 = 0; + VmPtr->Ip += 2; + } + // + // Get the data to push + // + if (OPERAND1_INDIRECT (Operands)) { + DataN = VmReadMemN (VmPtr, (UINTN) (VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16)); + } else { + DataN = (UINTN) (VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16); + } + // + // Adjust the stack down. + // + VmPtr->R[0] -= sizeof (UINTN); + VmWriteMemN (VmPtr, (UINTN) VmPtr->R[0], DataN); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecutePUSH ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the EBC PUSH instruction + +Arguments: + VmPtr - pointer to a VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + PUSH[32|64] {@}R1 {Index16|Immed16} + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + UINT32 Data32; + UINT64 Data64; + INT16 Index16; + + // + // Get opcode and operands + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + // + // Get immediate index if present, then advance the IP. + // + if (Opcode & PUSHPOP_M_IMMDATA) { + if (OPERAND1_INDIRECT (Operands)) { + Index16 = VmReadIndex16 (VmPtr, 2); + } else { + Index16 = VmReadImmed16 (VmPtr, 2); + } + + VmPtr->Ip += 4; + } else { + Index16 = 0; + VmPtr->Ip += 2; + } + // + // Get the data to push + // + if (Opcode & PUSHPOP_M_64) { + if (OPERAND1_INDIRECT (Operands)) { + Data64 = VmReadMem64 (VmPtr, (UINTN) (VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16)); + } else { + Data64 = (UINT64) VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16; + } + // + // Adjust the stack down, then write back the data + // + VmPtr->R[0] -= sizeof (UINT64); + VmWriteMem64 (VmPtr, (UINTN) VmPtr->R[0], Data64); + } else { + // + // 32-bit data + // + if (OPERAND1_INDIRECT (Operands)) { + Data32 = VmReadMem32 (VmPtr, (UINTN) (VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16)); + } else { + Data32 = (UINT32) VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16; + } + // + // Adjust the stack down and write the data + // + VmPtr->R[0] -= sizeof (UINT32); + VmWriteMem32 (VmPtr, (UINTN) VmPtr->R[0], Data32); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecutePOPn ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the EBC POPn instruction + +Arguments: + VmPtr - pointer to a VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + POPn {@}R1 {Index16|Immed16} + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + INT16 Index16; + UINTN DataN; + + // + // Get opcode and operands + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + // + // Get immediate data if present, and advance the IP + // + if (Opcode & PUSHPOP_M_IMMDATA) { + if (OPERAND1_INDIRECT (Operands)) { + Index16 = VmReadIndex16 (VmPtr, 2); + } else { + Index16 = VmReadImmed16 (VmPtr, 2); + } + + VmPtr->Ip += 4; + } else { + Index16 = 0; + VmPtr->Ip += 2; + } + // + // Read the data off the stack, then adjust the stack pointer + // + DataN = VmReadMemN (VmPtr, (UINTN) VmPtr->R[0]); + VmPtr->R[0] += sizeof (UINTN); + // + // Do the write-back + // + if (OPERAND1_INDIRECT (Operands)) { + VmWriteMemN (VmPtr, (UINTN) (VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16), DataN); + } else { + VmPtr->R[OPERAND1_REGNUM (Operands)] = (INT64) (UINT64) ((UINTN) DataN + Index16); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecutePOP ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the EBC POP instruction + +Arguments: + VmPtr - pointer to a VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + POP {@}R1 {Index16|Immed16} + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + INT16 Index16; + INT32 Data32; + UINT64 Data64; + + // + // Get opcode and operands + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + // + // Get immediate data if present, and advance the IP. + // + if (Opcode & PUSHPOP_M_IMMDATA) { + if (OPERAND1_INDIRECT (Operands)) { + Index16 = VmReadIndex16 (VmPtr, 2); + } else { + Index16 = VmReadImmed16 (VmPtr, 2); + } + + VmPtr->Ip += 4; + } else { + Index16 = 0; + VmPtr->Ip += 2; + } + // + // Get the data off the stack, then write it to the appropriate location + // + if (Opcode & PUSHPOP_M_64) { + // + // Read the data off the stack, then adjust the stack pointer + // + Data64 = VmReadMem64 (VmPtr, (UINTN) VmPtr->R[0]); + VmPtr->R[0] += sizeof (UINT64); + // + // Do the write-back + // + if (OPERAND1_INDIRECT (Operands)) { + VmWriteMem64 (VmPtr, (UINTN) (VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16), Data64); + } else { + VmPtr->R[OPERAND1_REGNUM (Operands)] = Data64 + Index16; + } + } else { + // + // 32-bit pop. Read it off the stack and adjust the stack pointer + // + Data32 = (INT32) VmReadMem32 (VmPtr, (UINTN) VmPtr->R[0]); + VmPtr->R[0] += sizeof (UINT32); + // + // Do the write-back + // + if (OPERAND1_INDIRECT (Operands)) { + VmWriteMem32 (VmPtr, (UINTN) (VmPtr->R[OPERAND1_REGNUM (Operands)] + Index16), Data32); + } else { + VmPtr->R[OPERAND1_REGNUM (Operands)] = (INT64) Data32 + Index16; + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteCALL ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Implements the EBC CALL instruction. + + Instruction format: + + CALL64 Immed64 + CALL32 {@}R1 {Immed32|Index32} + CALLEX64 Immed64 + CALLEX16 {@}R1 {Immed32} + + If Rx == R0, then it's a PC relative call to PC = PC + imm32. + +Arguments: + VmPtr - pointer to a VM context. + +Returns: + Standard EFI_STATUS + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + INT32 Immed32; + UINT8 Size; + INT64 Immed64; + VOID *FramePtr; + + // + // Get opcode and operands + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + // + // Assign these as well to avoid compiler warnings + // + Immed64 = 0; + Immed32 = 0; + + FramePtr = VmPtr->FramePtr; + // + // Determine the instruction size, and get immediate data if present + // + if (Opcode & OPCODE_M_IMMDATA) { + if (Opcode & OPCODE_M_IMMDATA64) { + Immed64 = VmReadImmed64 (VmPtr, 2); + Size = 10; + } else { + // + // If register operand is indirect, then the immediate data is an index + // + if (OPERAND1_INDIRECT (Operands)) { + Immed32 = VmReadIndex32 (VmPtr, 2); + } else { + Immed32 = VmReadImmed32 (VmPtr, 2); + } + + Size = 6; + } + } else { + Size = 2; + } + // + // If it's a call to EBC, adjust the stack pointer down 16 bytes and + // put our return address and frame pointer on the VM stack. + // + if ((Operands & OPERAND_M_NATIVE_CALL) == 0) { + VmPtr->R[0] -= 8; + VmWriteMemN (VmPtr, (UINTN) VmPtr->R[0], (UINTN) FramePtr); + VmPtr->FramePtr = (VOID *) (UINTN) VmPtr->R[0]; + VmPtr->R[0] -= 8; + VmWriteMem64 (VmPtr, (UINTN) VmPtr->R[0], (UINT64) (UINTN) (VmPtr->Ip + Size)); + } + // + // If 64-bit data, then absolute jump only + // + if (Opcode & OPCODE_M_IMMDATA64) { + // + // Native or EBC call? + // + if ((Operands & OPERAND_M_NATIVE_CALL) == 0) { + VmPtr->Ip = (VMIP) (UINTN) Immed64; + } else { + // + // Call external function, get the return value, and advance the IP + // + EbcLLCALLEX (VmPtr, (UINTN) Immed64, (UINTN) VmPtr->R[0], FramePtr, Size); + } + } else { + // + // Get the register data. If operand1 == 0, then ignore register and + // take immediate data as relative or absolute address. + // Compiler should take care of upper bits if 32-bit machine. + // + if (OPERAND1_REGNUM (Operands) != 0) { + Immed64 = (UINT64) (UINTN) VmPtr->R[OPERAND1_REGNUM (Operands)]; + } + // + // Get final address + // + if (OPERAND1_INDIRECT (Operands)) { + Immed64 = (INT64) (UINT64) (UINTN) VmReadMemN (VmPtr, (UINTN) (Immed64 + Immed32)); + } else { + Immed64 += Immed32; + } + // + // Now determine if external call, and then if relative or absolute + // + if ((Operands & OPERAND_M_NATIVE_CALL) == 0) { + // + // EBC call. Relative or absolute? If relative, then it's relative to the + // start of the next instruction. + // + if (Operands & OPERAND_M_RELATIVE_ADDR) { + VmPtr->Ip += Immed64 + Size; + } else { + VmPtr->Ip = (VMIP) (UINTN) Immed64; + } + } else { + // + // Native call. Relative or absolute? + // + if (Operands & OPERAND_M_RELATIVE_ADDR) { + EbcLLCALLEX (VmPtr, (UINTN) (Immed64 + VmPtr->Ip + Size), (UINTN) VmPtr->R[0], FramePtr, Size); + } else { + if (VmPtr->StopFlags & STOPFLAG_BREAK_ON_CALLEX) { + CpuBreakpoint (); + } + + EbcLLCALLEX (VmPtr, (UINTN) Immed64, (UINTN) VmPtr->R[0], FramePtr, Size); + } + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteRET ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the EBC RET instruction + +Arguments: + VmPtr - pointer to a VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + RET + +--*/ +{ + // + // If we're at the top of the stack, then simply set the done + // flag and return + // + if (VmPtr->StackRetAddr == (UINT64) VmPtr->R[0]) { + VmPtr->StopFlags |= STOPFLAG_APP_DONE; + } else { + // + // Pull the return address off the VM app's stack and set the IP + // to it + // + if (!IS_ALIGNED ((UINTN) VmPtr->R[0], sizeof (UINT16))) { + EbcDebugSignalException ( + EXCEPT_EBC_ALIGNMENT_CHECK, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + } + // + // Restore the IP and frame pointer from the stack + // + VmPtr->Ip = (VMIP) (UINTN) VmReadMem64 (VmPtr, (UINTN) VmPtr->R[0]); + VmPtr->R[0] += 8; + VmPtr->FramePtr = (VOID *) VmReadMemN (VmPtr, (UINTN) VmPtr->R[0]); + VmPtr->R[0] += 8; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteCMP ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the EBC CMP instruction + +Arguments: + VmPtr - pointer to a VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + CMP[32|64][eq|lte|gte|ulte|ugte] R1, {@}R2 {Index16|Immed16} + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + UINT8 Size; + INT16 Index16; + UINT32 Flag; + INT64 Op2; + INT64 Op1; + + // + // Get opcode and operands + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + // + // Get the register data we're going to compare to + // + Op1 = VmPtr->R[OPERAND1_REGNUM (Operands)]; + // + // Get immediate data + // + if (Opcode & OPCODE_M_IMMDATA) { + if (OPERAND2_INDIRECT (Operands)) { + Index16 = VmReadIndex16 (VmPtr, 2); + } else { + Index16 = VmReadImmed16 (VmPtr, 2); + } + + Size = 4; + } else { + Index16 = 0; + Size = 2; + } + // + // Now get Op2 + // + if (OPERAND2_INDIRECT (Operands)) { + if (Opcode & OPCODE_M_64BIT) { + Op2 = (INT64) VmReadMem64 (VmPtr, (UINTN) (VmPtr->R[OPERAND2_REGNUM (Operands)] + Index16)); + } else { + // + // 32-bit operations. 0-extend the values for all cases. + // + Op2 = (INT64) (UINT64) ((UINT32) VmReadMem32 (VmPtr, (UINTN) (VmPtr->R[OPERAND2_REGNUM (Operands)] + Index16))); + } + } else { + Op2 = VmPtr->R[OPERAND2_REGNUM (Operands)] + Index16; + } + // + // Now do the compare + // + Flag = 0; + if (Opcode & OPCODE_M_64BIT) { + // + // 64-bit compares + // + switch (Opcode & OPCODE_M_OPCODE) { + case OPCODE_CMPEQ: + if (Op1 == Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPLTE: + if (Op1 <= Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPGTE: + if (Op1 >= Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPULTE: + if ((UINT64) Op1 <= (UINT64) Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPUGTE: + if ((UINT64) Op1 >= (UINT64) Op2) { + Flag = 1; + } + break; + + default: + ASSERT (0); + } + } else { + // + // 32-bit compares + // + switch (Opcode & OPCODE_M_OPCODE) { + case OPCODE_CMPEQ: + if ((INT32) Op1 == (INT32) Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPLTE: + if ((INT32) Op1 <= (INT32) Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPGTE: + if ((INT32) Op1 >= (INT32) Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPULTE: + if ((UINT32) Op1 <= (UINT32) Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPUGTE: + if ((UINT32) Op1 >= (UINT32) Op2) { + Flag = 1; + } + break; + + default: + ASSERT (0); + } + } + // + // Now set the flag accordingly for the comparison + // + if (Flag) { + VMFLAG_SET (VmPtr, VMFLAGS_CC); + } else { + VMFLAG_CLEAR (VmPtr, VMFLAGS_CC); + } + // + // Advance the IP + // + VmPtr->Ip += Size; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteCMPI ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the EBC CMPI instruction + +Arguments: + VmPtr - pointer to a VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + CMPI[32|64]{w|d}[eq|lte|gte|ulte|ugte] {@}Rx {Index16}, Immed16|Immed32 + +--*/ +{ + UINT8 Opcode; + UINT8 Operands; + UINT8 Size; + INT64 Op1; + INT64 Op2; + INT16 Index16; + UINT32 Flag; + + // + // Get opcode and operands + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + + // + // Get operand1 index if present + // + Size = 2; + if (Operands & OPERAND_M_CMPI_INDEX) { + Index16 = VmReadIndex16 (VmPtr, 2); + Size += 2; + } else { + Index16 = 0; + } + // + // Get operand1 data we're going to compare to + // + Op1 = (INT64) VmPtr->R[OPERAND1_REGNUM (Operands)]; + if (OPERAND1_INDIRECT (Operands)) { + // + // Indirect operand1. Fetch 32 or 64-bit value based on compare size. + // + if (Opcode & OPCODE_M_CMPI64) { + Op1 = (INT64) VmReadMem64 (VmPtr, (UINTN) Op1 + Index16); + } else { + Op1 = (INT64) VmReadMem32 (VmPtr, (UINTN) Op1 + Index16); + } + } else { + // + // Better not have been an index with direct. That is, CMPI R1 Index,... + // is illegal. + // + if (Operands & OPERAND_M_CMPI_INDEX) { + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_ERROR, + VmPtr + ); + VmPtr->Ip += Size; + return EFI_UNSUPPORTED; + } + } + // + // Get immediate data -- 16- or 32-bit sign extended + // + if (Opcode & OPCODE_M_CMPI32_DATA) { + Op2 = (INT64) VmReadImmed32 (VmPtr, Size); + Size += 4; + } else { + // + // 16-bit immediate data. Sign extend always. + // + Op2 = (INT64) ((INT16) VmReadImmed16 (VmPtr, Size)); + Size += 2; + } + // + // Now do the compare + // + Flag = 0; + if (Opcode & OPCODE_M_CMPI64) { + // + // 64 bit comparison + // + switch (Opcode & OPCODE_M_OPCODE) { + case OPCODE_CMPIEQ: + if (Op1 == (INT64) Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPILTE: + if (Op1 <= (INT64) Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPIGTE: + if (Op1 >= (INT64) Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPIULTE: + if ((UINT64) Op1 <= (UINT64) ((UINT32) Op2)) { + Flag = 1; + } + break; + + case OPCODE_CMPIUGTE: + if ((UINT64) Op1 >= (UINT64) ((UINT32) Op2)) { + Flag = 1; + } + break; + + default: + ASSERT (0); + } + } else { + // + // 32-bit comparisons + // + switch (Opcode & OPCODE_M_OPCODE) { + case OPCODE_CMPIEQ: + if ((INT32) Op1 == Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPILTE: + if ((INT32) Op1 <= Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPIGTE: + if ((INT32) Op1 >= Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPIULTE: + if ((UINT32) Op1 <= (UINT32) Op2) { + Flag = 1; + } + break; + + case OPCODE_CMPIUGTE: + if ((UINT32) Op1 >= (UINT32) Op2) { + Flag = 1; + } + break; + + default: + ASSERT (0); + } + } + // + // Now set the flag accordingly for the comparison + // + if (Flag) { + VMFLAG_SET (VmPtr, VMFLAGS_CC); + } else { + VMFLAG_CLEAR (VmPtr, VMFLAGS_CC); + } + // + // Advance the IP + // + VmPtr->Ip += Size; + return EFI_SUCCESS; +} + +STATIC +UINT64 +ExecuteNOT ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC NOT instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + ~Op2 + +Instruction syntax: + NOT[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + return ~Op2; +} + +STATIC +UINT64 +ExecuteNEG ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC NEG instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op2 * -1 + +Instruction syntax: + NEG[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + return ~Op2 + 1; +} + +STATIC +UINT64 +ExecuteADD ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + + Execute the EBC ADD instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 + Op2 + +Instruction syntax: + ADD[32|64] {@}R1, {@}R2 {Index16} + +--*/ +{ + return Op1 + Op2; +} + +STATIC +UINT64 +ExecuteSUB ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC SUB instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 - Op2 + Standard EFI_STATUS + +Instruction syntax: + SUB[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + if (*VmPtr->Ip & DATAMANIP_M_64) { + return (UINT64) ((INT64) ((INT64) Op1 - (INT64) Op2)); + } else { + return (UINT64) ((INT64) ((INT32) Op1 - (INT32) Op2)); + } +} + +STATIC +UINT64 +ExecuteMUL ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + + Execute the EBC MUL instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 * Op2 + +Instruction syntax: + MUL[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + INT64 ResultHigh; + + if (*VmPtr->Ip & DATAMANIP_M_64) { + return MulS64x64 (Op1, Op2, &ResultHigh); + } else { + return (UINT64) ((INT64) ((INT32) Op1 * (INT32) Op2)); + } +} + +STATIC +UINT64 +ExecuteMULU ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC MULU instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + (unsigned)Op1 * (unsigned)Op2 + +Instruction syntax: + MULU[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + INT64 ResultHigh; + if (*VmPtr->Ip & DATAMANIP_M_64) { + return MulU64x64 (Op1, Op2, (UINT64 *)&ResultHigh); + } else { + return (UINT64) ((UINT32) Op1 * (UINT32) Op2); + } +} + +STATIC +UINT64 +ExecuteDIV ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + + Execute the EBC DIV instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1/Op2 + +Instruction syntax: + DIV[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + INT64 Remainder; + UINT32 Error; + + // + // Check for divide-by-0 + // + if (Op2 == 0) { + EbcDebugSignalException ( + EXCEPT_EBC_DIVIDE_ERROR, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + + return 0; + } else { + if (*VmPtr->Ip & DATAMANIP_M_64) { + return (UINT64) (DivS64x64 (Op1, Op2, &Remainder, &Error)); + } else { + return (UINT64) ((INT64) ((INT32) Op1 / (INT32) Op2)); + } + } +} + +STATIC +UINT64 +ExecuteDIVU ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC DIVU instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + (unsigned)Op1 / (unsigned)Op2 + +Instruction syntax: + DIVU[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + UINT64 Remainder; + UINT32 Error; + + // + // Check for divide-by-0 + // + if (Op2 == 0) { + EbcDebugSignalException ( + EXCEPT_EBC_DIVIDE_ERROR, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return 0; + } else { + // + // Get the destination register + // + if (*VmPtr->Ip & DATAMANIP_M_64) { + return (UINT64) (DivU64x64 (Op1, Op2, &Remainder, &Error)); + } else { + return (UINT64) ((UINT32) Op1 / (UINT32) Op2); + } + } +} + +STATIC +UINT64 +ExecuteMOD ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC MOD instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 MODULUS Op2 + +Instruction syntax: + MOD[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + INT64 Remainder; + UINT32 Error; + + // + // Check for divide-by-0 + // + if (Op2 == 0) { + EbcDebugSignalException ( + EXCEPT_EBC_DIVIDE_ERROR, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return 0; + } else { + DivS64x64 ((INT64) Op1, (INT64) Op2, &Remainder, &Error); + return Remainder; + } +} + +STATIC +UINT64 +ExecuteMODU ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC MODU instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 UNSIGNED_MODULUS Op2 + +Instruction syntax: + MODU[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + UINT64 Remainder; + UINT32 Error; + + // + // Check for divide-by-0 + // + if (Op2 == 0) { + EbcDebugSignalException ( + EXCEPT_EBC_DIVIDE_ERROR, + EXCEPTION_FLAG_FATAL, + VmPtr + ); + return 0; + } else { + DivU64x64 (Op1, Op2, &Remainder, &Error); + return Remainder; + } +} + +STATIC +UINT64 +ExecuteAND ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC AND instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 AND Op2 + +Instruction syntax: + AND[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + return Op1 & Op2; +} + +STATIC +UINT64 +ExecuteOR ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC OR instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 OR Op2 + +Instruction syntax: + OR[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + return Op1 | Op2; +} + +STATIC +UINT64 +ExecuteXOR ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC XOR instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 XOR Op2 + +Instruction syntax: + XOR[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + return Op1 ^ Op2; +} + +STATIC +UINT64 +ExecuteSHL ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + + Execute the EBC SHL shift left instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 << Op2 + +Instruction syntax: + SHL[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + if (*VmPtr->Ip & DATAMANIP_M_64) { + return LeftShiftU64 (Op1, Op2); + } else { + return (UINT64) ((UINT32) ((UINT32) Op1 << (UINT32) Op2)); + } +} + +STATIC +UINT64 +ExecuteSHR ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC SHR instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 >> Op2 (unsigned operands) + +Instruction syntax: + SHR[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + if (*VmPtr->Ip & DATAMANIP_M_64) { + return RightShiftU64 (Op1, Op2); + } else { + return (UINT64) ((UINT32) Op1 >> (UINT32) Op2); + } +} + +STATIC +UINT64 +ExecuteASHR ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC ASHR instruction + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + Op1 >> Op2 (signed) + +Instruction syntax: + ASHR[32|64] {@}R1, {@}R2 {Index16|Immed16} + +--*/ +{ + if (*VmPtr->Ip & DATAMANIP_M_64) { + return ARightShift64 (Op1, Op2); + } else { + return (UINT64) ((INT64) ((INT32) Op1 >> (UINT32) Op2)); + } +} + +STATIC +UINT64 +ExecuteEXTNDB ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC EXTNDB instruction to sign-extend a byte value. + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + (INT64)(INT8)Op2 + +Instruction syntax: + EXTNDB[32|64] {@}R1, {@}R2 {Index16|Immed16} + + +--*/ +{ + INT8 Data8; + INT64 Data64; + // + // Convert to byte, then return as 64-bit signed value to let compiler + // sign-extend the value + // + Data8 = (INT8) Op2; + Data64 = (INT64) Data8; + + return (UINT64) Data64; +} + +STATIC +UINT64 +ExecuteEXTNDW ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC EXTNDW instruction to sign-extend a 16-bit value. + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + (INT64)(INT16)Op2 + +Instruction syntax: + EXTNDW[32|64] {@}R1, {@}R2 {Index16|Immed16} + + +--*/ +{ + INT16 Data16; + INT64 Data64; + // + // Convert to word, then return as 64-bit signed value to let compiler + // sign-extend the value + // + Data16 = (INT16) Op2; + Data64 = (INT64) Data16; + + return (UINT64) Data64; +} +// +// Execute the EBC EXTNDD instruction. +// +// Format: EXTNDD {@}Rx, {@}Ry [Index16|Immed16] +// EXTNDD Dest, Source +// +// Operation: Dest <- SignExtended((DWORD)Source)) +// +STATIC +UINT64 +ExecuteEXTNDD ( + IN VM_CONTEXT *VmPtr, + IN UINT64 Op1, + IN UINT64 Op2 + ) +/*++ + +Routine Description: + Execute the EBC EXTNDD instruction to sign-extend a 32-bit value. + +Arguments: + VmPtr - pointer to a VM context + Op1 - Operand 1 from the instruction + Op2 - Operand 2 from the instruction + +Returns: + (INT64)(INT32)Op2 + +Instruction syntax: + EXTNDD[32|64] {@}R1, {@}R2 {Index16|Immed16} + + +--*/ +{ + INT32 Data32; + INT64 Data64; + // + // Convert to 32-bit value, then return as 64-bit signed value to let compiler + // sign-extend the value + // + Data32 = (INT32) Op2; + Data64 = (INT64) Data32; + + return (UINT64) Data64; +} + +STATIC +EFI_STATUS +ExecuteSignedDataManip ( + IN VM_CONTEXT *VmPtr + ) +{ + // + // Just call the data manipulation function with a flag indicating this + // is a signed operation. + // + return ExecuteDataManip (VmPtr, TRUE); +} + +STATIC +EFI_STATUS +ExecuteUnsignedDataManip ( + IN VM_CONTEXT *VmPtr + ) +{ + // + // Just call the data manipulation function with a flag indicating this + // is not a signed operation. + // + return ExecuteDataManip (VmPtr, FALSE); +} + +STATIC +EFI_STATUS +ExecuteDataManip ( + IN VM_CONTEXT *VmPtr, + IN BOOLEAN IsSignedOp + ) +/*++ + +Routine Description: + Execute all the EBC data manipulation instructions. + Since the EBC data manipulation instructions all have the same basic form, + they can share the code that does the fetch of operands and the write-back + of the result. This function performs the fetch of the operands (even if + both are not needed to be fetched, like NOT instruction), dispatches to the + appropriate subfunction, then writes back the returned result. + +Arguments: + VmPtr - pointer to VM context + +Returns: + Standard EBC status + +Format: + INSTRUCITON[32|64] {@}R1, {@}R2 {Immed16|Index16} + +--*/ +{ + UINT8 Opcode; + INT16 Index16; + UINT8 Operands; + UINT8 Size; + UINT64 Op1; + UINT64 Op2; + + // + // Get opcode and operands + // + Opcode = GETOPCODE (VmPtr); + Operands = GETOPERANDS (VmPtr); + + // + // Determine if we have immediate data by the opcode + // + if (Opcode & DATAMANIP_M_IMMDATA) { + // + // Index16 if Ry is indirect, or Immed16 if Ry direct. + // + if (OPERAND2_INDIRECT (Operands)) { + Index16 = VmReadIndex16 (VmPtr, 2); + } else { + Index16 = VmReadImmed16 (VmPtr, 2); + } + + Size = 4; + } else { + Index16 = 0; + Size = 2; + } + // + // Now get operand2 (source). It's of format {@}R2 {Index16|Immed16} + // + Op2 = (UINT64) VmPtr->R[OPERAND2_REGNUM (Operands)] + Index16; + if (OPERAND2_INDIRECT (Operands)) { + // + // Indirect form: @R2 Index16. Fetch as 32- or 64-bit data + // + if (Opcode & DATAMANIP_M_64) { + Op2 = VmReadMem64 (VmPtr, (UINTN) Op2); + } else { + // + // Read as signed value where appropriate. + // + if (IsSignedOp) { + Op2 = (UINT64) (INT64) ((INT32) VmReadMem32 (VmPtr, (UINTN) Op2)); + } else { + Op2 = (UINT64) VmReadMem32 (VmPtr, (UINTN) Op2); + } + } + } else { + if ((Opcode & DATAMANIP_M_64) == 0) { + if (IsSignedOp) { + Op2 = (UINT64) (INT64) ((INT32) Op2); + } else { + Op2 = (UINT64) ((UINT32) Op2); + } + } + } + // + // Get operand1 (destination and sometimes also an actual operand) + // of form {@}R1 + // + Op1 = VmPtr->R[OPERAND1_REGNUM (Operands)]; + if (OPERAND1_INDIRECT (Operands)) { + if (Opcode & DATAMANIP_M_64) { + Op1 = VmReadMem64 (VmPtr, (UINTN) Op1); + } else { + if (IsSignedOp) { + Op1 = (UINT64) (INT64) ((INT32) VmReadMem32 (VmPtr, (UINTN) Op1)); + } else { + Op1 = (UINT64) VmReadMem32 (VmPtr, (UINTN) Op1); + } + } + } else { + if ((Opcode & DATAMANIP_M_64) == 0) { + if (IsSignedOp) { + Op1 = (UINT64) (INT64) ((INT32) Op1); + } else { + Op1 = (UINT64) ((UINT32) Op1); + } + } + } + // + // Dispatch to the computation function + // + if (((Opcode & OPCODE_M_OPCODE) - OPCODE_NOT) >= + (sizeof (mDataManipDispatchTable) / sizeof (mDataManipDispatchTable[0])) + ) { + EbcDebugSignalException ( + EXCEPT_EBC_INVALID_OPCODE, + EXCEPTION_FLAG_ERROR, + VmPtr + ); + // + // Advance and return + // + VmPtr->Ip += Size; + return EFI_UNSUPPORTED; + } else { + Op2 = mDataManipDispatchTable[(Opcode & OPCODE_M_OPCODE) - OPCODE_NOT](VmPtr, Op1, Op2); + } + // + // Write back the result. + // + if (OPERAND1_INDIRECT (Operands)) { + Op1 = VmPtr->R[OPERAND1_REGNUM (Operands)]; + if (Opcode & DATAMANIP_M_64) { + VmWriteMem64 (VmPtr, (UINTN) Op1, Op2); + } else { + VmWriteMem32 (VmPtr, (UINTN) Op1, (UINT32) Op2); + } + } else { + // + // Storage back to a register. Write back, clearing upper bits (as per + // the specification) if 32-bit operation. + // + VmPtr->R[OPERAND1_REGNUM (Operands)] = Op2; + if ((Opcode & DATAMANIP_M_64) == 0) { + VmPtr->R[OPERAND1_REGNUM (Operands)] &= 0xFFFFFFFF; + } + } + // + // Advance the instruction pointer + // + VmPtr->Ip += Size; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteLOADSP ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the EBC LOADSP instruction + +Arguments: + VmPtr - pointer to a VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + LOADSP SP1, R2 + +--*/ +{ + UINT8 Operands; + + // + // Get the operands + // + Operands = GETOPERANDS (VmPtr); + + // + // Do the operation + // + switch (OPERAND1_REGNUM (Operands)) { + // + // Set flags + // + case 0: + // + // Spec states that this instruction will not modify reserved bits in + // the flags register. + // + VmPtr->Flags = (VmPtr->Flags &~VMFLAGS_ALL_VALID) | (VmPtr->R[OPERAND2_REGNUM (Operands)] & VMFLAGS_ALL_VALID); + break; + + default: + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_WARNING, + VmPtr + ); + VmPtr->Ip += 2; + return EFI_UNSUPPORTED; + } + + VmPtr->Ip += 2; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +ExecuteSTORESP ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + Execute the EBC STORESP instruction + +Arguments: + VmPtr - pointer to a VM context + +Returns: + Standard EFI_STATUS + +Instruction syntax: + STORESP Rx, FLAGS|IP + +--*/ +{ + UINT8 Operands; + + // + // Get the operands + // + Operands = GETOPERANDS (VmPtr); + + // + // Do the operation + // + switch (OPERAND2_REGNUM (Operands)) { + // + // Get flags + // + case 0: + // + // Retrieve the value in the flags register, then clear reserved bits + // + VmPtr->R[OPERAND1_REGNUM (Operands)] = (UINT64) (VmPtr->Flags & VMFLAGS_ALL_VALID); + break; + + // + // Get IP -- address of following instruction + // + case 1: + VmPtr->R[OPERAND1_REGNUM (Operands)] = (UINT64) (UINTN) VmPtr->Ip + 2; + break; + + default: + EbcDebugSignalException ( + EXCEPT_EBC_INSTRUCTION_ENCODING, + EXCEPTION_FLAG_WARNING, + VmPtr + ); + VmPtr->Ip += 2; + return EFI_UNSUPPORTED; + break; + } + + VmPtr->Ip += 2; + return EFI_SUCCESS; +} + +STATIC +INT16 +VmReadIndex16 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 CodeOffset + ) +/*++ + +Routine Description: + Decode a 16-bit index to determine the offset. Given an index value: + + b15 - sign bit + b14:12 - number of bits in this index assigned to natural units (=a) + ba:11 - constant units = C + b0:a - natural units = N + + Given this info, the offset can be computed by: + offset = sign_bit * (C + N * sizeof(UINTN)) + + Max offset is achieved with index = 0x7FFF giving an offset of + 0x27B (32-bit machine) or 0x477 (64-bit machine). + Min offset is achieved with index = + +Arguments: + VmPtr - pointer to VM context + CodeOffset - offset from IP of the location of the 16-bit index to decode + +Returns: + The decoded offset. + +--*/ +{ + UINT16 Index; + INT16 Offset; + INT16 C; + INT16 N; + INT16 NBits; + INT16 Mask; + + // + // First read the index from the code stream + // + Index = VmReadCode16 (VmPtr, CodeOffset); + + // + // Get the mask for N. First get the number of bits from the index. + // + NBits = (INT16) ((Index & 0x7000) >> 12); + + // + // Scale it for 16-bit indexes + // + NBits *= 2; + + // + // Now using the number of bits, create a mask. + // + Mask = (INT16) ((INT16)~0 << NBits); + + // + // Now using the mask, extract N from the lower bits of the index. + // + N = (INT16) (Index &~Mask); + + // + // Now compute C + // + C = (INT16) (((Index &~0xF000) & Mask) >> NBits); + + Offset = (INT16) (N * sizeof (UINTN) + C); + + // + // Now set the sign + // + if (Index & 0x8000) { + // + // Do it the hard way to work around a bogus compiler warning + // + // Offset = -1 * Offset; + // + Offset = (INT16) ((INT32) Offset * -1); + } + + return Offset; +} + +STATIC +INT32 +VmReadIndex32 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 CodeOffset + ) +/*++ + +Routine Description: + Decode a 32-bit index to determine the offset. + +Arguments: + VmPtr - pointer to VM context + CodeOffset - offset from IP of the location of the 32-bit index to decode + +Returns: + Converted index per EBC VM specification + +--*/ +{ + UINT32 Index; + INT32 Offset; + INT32 C; + INT32 N; + INT32 NBits; + INT32 Mask; + + Index = VmReadImmed32 (VmPtr, CodeOffset); + + // + // Get the mask for N. First get the number of bits from the index. + // + NBits = (Index & 0x70000000) >> 28; + + // + // Scale it for 32-bit indexes + // + NBits *= 4; + + // + // Now using the number of bits, create a mask. + // + Mask = (INT32)~0 << NBits; + + // + // Now using the mask, extract N from the lower bits of the index. + // + N = Index &~Mask; + + // + // Now compute C + // + C = ((Index &~0xF0000000) & Mask) >> NBits; + + Offset = N * sizeof (UINTN) + C; + + // + // Now set the sign + // + if (Index & 0x80000000) { + Offset = Offset * -1; + } + + return Offset; +} + +STATIC +INT64 +VmReadIndex64 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 CodeOffset + ) +/*++ + +Routine Description: + Decode a 64-bit index to determine the offset. + +Arguments: + VmPtr - pointer to VM context + CodeOffset - offset from IP of the location of the 64-bit index to decode + +Returns: + Converted index per EBC VM specification + +--*/ +{ + UINT64 Index; + UINT64 Remainder; + INT64 Offset; + INT64 C; + INT64 N; + INT64 NBits; + INT64 Mask; + + Index = VmReadCode64 (VmPtr, CodeOffset); + + // + // Get the mask for N. First get the number of bits from the index. + // + NBits = RightShiftU64 ((Index & 0x7000000000000000ULL), 60); + + // + // Scale it for 64-bit indexes (multiply by 8 by shifting left 3) + // + NBits = LeftShiftU64 (NBits, 3); + + // + // Now using the number of bits, create a mask. + // + Mask = (LeftShiftU64 ((UINT64)~0, (UINT64) NBits)); + + // + // Now using the mask, extract N from the lower bits of the index. + // + N = Index &~Mask; + + // + // Now compute C + // + C = ARightShift64 (((Index &~0xF000000000000000ULL) & Mask), (UINTN) NBits); + + Offset = MulU64x64 (N, sizeof (UINTN), &Remainder) + C; + + // + // Now set the sign + // + if (Index & 0x8000000000000000ULL) { + Offset = MulS64x64 (Offset, -1, (INT64 *)&Index); + } + + return Offset; +} + +STATIC +EFI_STATUS +VmWriteMem8 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr, + IN UINT8 Data + ) +/*++ + +Routine Description: + The following VmWriteMem? routines are called by the EBC data + movement instructions that write to memory. Since these writes + may be to the stack, which looks like (high address on top) this, + + [EBC entry point arguments] + [VM stack] + [EBC stack] + + we need to detect all attempts to write to the EBC entry point argument + stack area and adjust the address (which will initially point into the + VM stack) to point into the EBC entry point arguments. + +Arguments: + VmPtr - pointer to a VM context + Addr - adddress to write to + Data - value to write to Addr + +Returns: + Standard EFI_STATUS + +--*/ +{ + // + // Convert the address if it's in the stack gap + // + Addr = ConvertStackAddr (VmPtr, Addr); + *(UINT8 *) Addr = Data; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +VmWriteMem16 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr, + IN UINT16 Data + ) +{ + EFI_STATUS Status; + + // + // Convert the address if it's in the stack gap + // + Addr = ConvertStackAddr (VmPtr, Addr); + + // + // Do a simple write if aligned + // + if (IS_ALIGNED (Addr, sizeof (UINT16))) { + *(UINT16 *) Addr = Data; + } else { + // + // Write as two bytes + // + MemoryFence (); + if ((Status = VmWriteMem8 (VmPtr, Addr, (UINT8) Data)) != EFI_SUCCESS) { + return Status; + } + + MemoryFence (); + if ((Status = VmWriteMem8 (VmPtr, Addr + 1, (UINT8) (Data >> 8))) != EFI_SUCCESS) { + return Status; + } + + MemoryFence (); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +VmWriteMem32 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr, + IN UINT32 Data + ) +{ + EFI_STATUS Status; + + // + // Convert the address if it's in the stack gap + // + Addr = ConvertStackAddr (VmPtr, Addr); + + // + // Do a simple write if aligned + // + if (IS_ALIGNED (Addr, sizeof (UINT32))) { + *(UINT32 *) Addr = Data; + } else { + // + // Write as two words + // + MemoryFence (); + if ((Status = VmWriteMem16 (VmPtr, Addr, (UINT16) Data)) != EFI_SUCCESS) { + return Status; + } + + MemoryFence (); + if ((Status = VmWriteMem16 (VmPtr, Addr + sizeof (UINT16), (UINT16) (Data >> 16))) != EFI_SUCCESS) { + return Status; + } + + MemoryFence (); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +VmWriteMem64 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr, + IN UINT64 Data + ) +{ + EFI_STATUS Status; + UINT32 Data32; + + // + // Convert the address if it's in the stack gap + // + Addr = ConvertStackAddr (VmPtr, Addr); + + // + // Do a simple write if aligned + // + if (IS_ALIGNED (Addr, sizeof (UINT64))) { + *(UINT64 *) Addr = Data; + } else { + // + // Write as two 32-bit words + // + MemoryFence (); + if ((Status = VmWriteMem32 (VmPtr, Addr, (UINT32) Data)) != EFI_SUCCESS) { + return Status; + } + + MemoryFence (); + Data32 = (UINT32) (((UINT32 *) &Data)[1]); + if ((Status = VmWriteMem32 (VmPtr, Addr + sizeof (UINT32), Data32)) != EFI_SUCCESS) { + return Status; + } + + MemoryFence (); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +VmWriteMemN ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr, + IN UINTN Data + ) +{ + EFI_STATUS Status; + UINTN Index; + + Status = EFI_SUCCESS; + + // + // Convert the address if it's in the stack gap + // + Addr = ConvertStackAddr (VmPtr, Addr); + + // + // Do a simple write if aligned + // + if (IS_ALIGNED (Addr, sizeof (UINTN))) { + *(UINTN *) Addr = Data; + } else { + for (Index = 0; Index < sizeof (UINTN) / sizeof (UINT32); Index++) { + MemoryFence (); + Status = VmWriteMem32 (VmPtr, Addr + Index * sizeof (UINT32), (UINT32) Data); + MemoryFence (); + Data = (UINTN)RShiftU64 ((UINT64)Data, 32); + } + } + + return Status; +} + +STATIC +INT8 +VmReadImmed8 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ) +/*++ + +Routine Description: + + The following VmReadImmed routines are called by the EBC execute + functions to read EBC immediate values from the code stream. + Since we can't assume alignment, each tries to read in the biggest + chunks size available, but will revert to smaller reads if necessary. + +Arguments: + VmPtr - pointer to a VM context + Offset - offset from IP of the code bytes to read. + +Returns: + Signed data of the requested size from the specified address. + +--*/ +{ + // + // Simply return the data in flat memory space + // + return * (INT8 *) (VmPtr->Ip + Offset); +} + +STATIC +INT16 +VmReadImmed16 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ) +{ + // + // Read direct if aligned + // + if (IS_ALIGNED ((UINTN) VmPtr->Ip + Offset, sizeof (INT16))) { + return * (INT16 *) (VmPtr->Ip + Offset); + } else { + // + // All code word reads should be aligned + // + EbcDebugSignalException ( + EXCEPT_EBC_ALIGNMENT_CHECK, + EXCEPTION_FLAG_WARNING, + VmPtr + ); + } + // + // Return unaligned data + // + return (INT16) (*(UINT8 *) (VmPtr->Ip + Offset) + (*(UINT8 *) (VmPtr->Ip + Offset + 1) << 8)); +} + +STATIC +INT32 +VmReadImmed32 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ) +{ + UINT32 Data; + + // + // Read direct if aligned + // + if (IS_ALIGNED ((UINTN) VmPtr->Ip + Offset, sizeof (UINT32))) { + return * (INT32 *) (VmPtr->Ip + Offset); + } + // + // Return unaligned data + // + Data = (UINT32) VmReadCode16 (VmPtr, Offset); + Data |= (UINT32) (VmReadCode16 (VmPtr, Offset + 2) << 16); + return Data; +} + +STATIC +INT64 +VmReadImmed64 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ) +{ + UINT64 Data64; + UINT32 Data32; + UINT8 *Ptr; + + // + // Read direct if aligned + // + if (IS_ALIGNED ((UINTN) VmPtr->Ip + Offset, sizeof (UINT64))) { + return * (UINT64 *) (VmPtr->Ip + Offset); + } + // + // Return unaligned data. + // + Ptr = (UINT8 *) &Data64; + Data32 = VmReadCode32 (VmPtr, Offset); + *(UINT32 *) Ptr = Data32; + Ptr += sizeof (Data32); + Data32 = VmReadCode32 (VmPtr, Offset + sizeof (UINT32)); + *(UINT32 *) Ptr = Data32; + return Data64; +} + +STATIC +UINT16 +VmReadCode16 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ) +/*++ + +Routine Description: + The following VmReadCode() routines provide the ability to read raw + unsigned data from the code stream. + +Arguments: + VmPtr - pointer to VM context + Offset - offset from current IP to the raw data to read. + +Returns: + The raw unsigned 16-bit value from the code stream. + +--*/ +{ + // + // Read direct if aligned + // + if (IS_ALIGNED ((UINTN) VmPtr->Ip + Offset, sizeof (UINT16))) { + return * (UINT16 *) (VmPtr->Ip + Offset); + } else { + // + // All code word reads should be aligned + // + EbcDebugSignalException ( + EXCEPT_EBC_ALIGNMENT_CHECK, + EXCEPTION_FLAG_WARNING, + VmPtr + ); + } + // + // Return unaligned data + // + return (UINT16) (*(UINT8 *) (VmPtr->Ip + Offset) + (*(UINT8 *) (VmPtr->Ip + Offset + 1) << 8)); +} + +STATIC +UINT32 +VmReadCode32 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ) +{ + UINT32 Data; + // + // Read direct if aligned + // + if (IS_ALIGNED ((UINTN) VmPtr->Ip + Offset, sizeof (UINT32))) { + return * (UINT32 *) (VmPtr->Ip + Offset); + } + // + // Return unaligned data + // + Data = (UINT32) VmReadCode16 (VmPtr, Offset); + Data |= (VmReadCode16 (VmPtr, Offset + 2) << 16); + return Data; +} + +STATIC +UINT64 +VmReadCode64 ( + IN VM_CONTEXT *VmPtr, + IN UINT32 Offset + ) +{ + UINT64 Data64; + UINT32 Data32; + UINT8 *Ptr; + + // + // Read direct if aligned + // + if (IS_ALIGNED ((UINTN) VmPtr->Ip + Offset, sizeof (UINT64))) { + return * (UINT64 *) (VmPtr->Ip + Offset); + } + // + // Return unaligned data. + // + Ptr = (UINT8 *) &Data64; + Data32 = VmReadCode32 (VmPtr, Offset); + *(UINT32 *) Ptr = Data32; + Ptr += sizeof (Data32); + Data32 = VmReadCode32 (VmPtr, Offset + sizeof (UINT32)); + *(UINT32 *) Ptr = Data32; + return Data64; +} + +STATIC +UINT8 +VmReadMem8 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ) +{ + // + // Convert the address if it's in the stack gap + // + Addr = ConvertStackAddr (VmPtr, Addr); + // + // Simply return the data in flat memory space + // + return * (UINT8 *) Addr; +} + +STATIC +UINT16 +VmReadMem16 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ) +{ + // + // Convert the address if it's in the stack gap + // + Addr = ConvertStackAddr (VmPtr, Addr); + // + // Read direct if aligned + // + if (IS_ALIGNED (Addr, sizeof (UINT16))) { + return * (UINT16 *) Addr; + } + // + // Return unaligned data + // + return (UINT16) (*(UINT8 *) Addr + (*(UINT8 *) (Addr + 1) << 8)); +} + +STATIC +UINT32 +VmReadMem32 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ) +{ + UINT32 Data; + + // + // Convert the address if it's in the stack gap + // + Addr = ConvertStackAddr (VmPtr, Addr); + // + // Read direct if aligned + // + if (IS_ALIGNED (Addr, sizeof (UINT32))) { + return * (UINT32 *) Addr; + } + // + // Return unaligned data + // + Data = (UINT32) VmReadMem16 (VmPtr, Addr); + Data |= (VmReadMem16 (VmPtr, Addr + 2) << 16); + return Data; +} + +STATIC +UINT64 +VmReadMem64 ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ) +{ + UINT64 Data; + UINT32 Data32; + + // + // Convert the address if it's in the stack gap + // + Addr = ConvertStackAddr (VmPtr, Addr); + + // + // Read direct if aligned + // + if (IS_ALIGNED (Addr, sizeof (UINT64))) { + return * (UINT64 *) Addr; + } + // + // Return unaligned data. Assume little endian. + // + Data = (UINT64) VmReadMem32 (VmPtr, Addr); + Data32 = VmReadMem32 (VmPtr, Addr + sizeof (UINT32)); + *(UINT32 *) ((UINT32 *) &Data + 1) = Data32; + return Data; +} + +STATIC +UINTN +ConvertStackAddr ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ) +/*++ + +Routine Description: + + Given an address that EBC is going to read from or write to, return + an appropriate address that accounts for a gap in the stack. + + The stack for this application looks like this (high addr on top) + [EBC entry point arguments] + [VM stack] + [EBC stack] + + The EBC assumes that its arguments are at the top of its stack, which + is where the VM stack is really. Therefore if the EBC does memory + accesses into the VM stack area, then we need to convert the address + to point to the EBC entry point arguments area. Do this here. + +Arguments: + + VmPtr - pointer to VM context + Addr - address of interest + +Returns: + + The unchanged address if it's not in the VM stack region. Otherwise, + adjust for the stack gap and return the modified address. + +--*/ +{ + if ((Addr >= VmPtr->LowStackTop) && (Addr < VmPtr->HighStackBottom)) { + // + // In the stack gap -- now make sure it's not in the VM itself, which + // would be the case if it's accessing VM register contents. + // + if ((Addr < (UINTN) VmPtr) || (Addr > (UINTN) VmPtr + sizeof (VM_CONTEXT))) { + VmPtr->LastAddrConverted = Addr; + VmPtr->LastAddrConvertedValue = Addr - VmPtr->LowStackTop + VmPtr->HighStackBottom; + return Addr - VmPtr->LowStackTop + VmPtr->HighStackBottom; + } + } + + return Addr; +} + +STATIC +UINTN +VmReadMemN ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr + ) +/*++ + +Routine Description: + Read a natural value from memory. May or may not be aligned. + +Arguments: + VmPtr - current VM context + Addr - the address to read from + +Returns: + The natural value at address Addr. + +--*/ +{ + UINTN Data; + UINT32 Size; + UINT8 *FromPtr; + UINT8 *ToPtr; + // + // Convert the address if it's in the stack gap + // + Addr = ConvertStackAddr (VmPtr, Addr); + // + // Read direct if aligned + // + if (IS_ALIGNED (Addr, sizeof (UINTN))) { + return * (UINTN *) Addr; + } + // + // Return unaligned data + // + Data = 0; + FromPtr = (UINT8 *) Addr; + ToPtr = (UINT8 *) &Data; + + for (Size = 0; Size < sizeof (Data); Size++) { + *ToPtr = *FromPtr; + ToPtr++; + FromPtr++; + } + + return Data; +} + +UINT64 +GetVmVersion ( + VOID + ) +{ + return (UINT64) (((VM_MAJOR_VERSION & 0xFFFF) << 16) | ((VM_MINOR_VERSION & 0xFFFF))); +} diff --git a/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.h b/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.h new file mode 100644 index 0000000000..62b530b952 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/EbcExecute.h @@ -0,0 +1,383 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EbcExecute.h + +Abstract: + + Header file for Virtual Machine support. Contains EBC defines that can + be of use to a disassembler for the most part. Also provides function + prototypes for VM functions. + +--*/ + +#ifndef _EBC_EXECUTE_H_ +#define _EBC_EXECUTE_H_ + +// +// Macros to check and set alignment +// +#define ASSERT_ALIGNED(addr, size) ASSERT (!((UINT32) (addr) & (size - 1))) +#define IS_ALIGNED(addr, size) !((UINT32) (addr) & (size - 1)) + +// +// Define a macro to get the operand. Then we can change it to be either a +// direct read or have it call a function to read memory. +// +#define GETOPERANDS(pVM) (UINT8) (*(UINT8 *) (pVM->Ip + 1)) +#define GETOPCODE(pVM) (UINT8) (*(UINT8 *) pVM->Ip) + +// +// Bit masks for opcode encodings +// +#define OPCODE_M_OPCODE 0x3F // bits of interest for first level decode +#define OPCODE_M_IMMDATA 0x80 +#define OPCODE_M_IMMDATA64 0x40 +#define OPCODE_M_64BIT 0x40 // for CMP +#define OPCODE_M_RELADDR 0x10 // for CALL instruction +#define OPCODE_M_CMPI32_DATA 0x80 // for CMPI +#define OPCODE_M_CMPI64 0x40 // for CMPI 32 or 64 bit comparison +#define OPERAND_M_MOVIN_N 0x80 +#define OPERAND_M_CMPI_INDEX 0x10 + +// +// Masks for instructions that encode presence of indexes for operand1 and/or +// operand2. +// +#define OPCODE_M_IMMED_OP1 0x80 +#define OPCODE_M_IMMED_OP2 0x40 + +// +// Bit masks for operand encodings +// +#define OPERAND_M_INDIRECT1 0x08 +#define OPERAND_M_INDIRECT2 0x80 +#define OPERAND_M_OP1 0x07 +#define OPERAND_M_OP2 0x70 + +// +// Masks for data manipulation instructions +// +#define DATAMANIP_M_64 0x40 // 64-bit width operation +#define DATAMANIP_M_IMMDATA 0x80 + +// +// For MOV instructions, need a mask for the opcode when immediate +// data applies to R2. +// +#define OPCODE_M_IMMED_OP2 0x40 + +// +// The MOVI/MOVIn instructions use bit 6 of operands byte to indicate +// if an index is present. Then bits 4 and 5 are used to indicate the width +// of the move. +// +#define MOVI_M_IMMDATA 0x40 +#define MOVI_M_DATAWIDTH 0xC0 +#define MOVI_DATAWIDTH16 0x40 +#define MOVI_DATAWIDTH32 0x80 +#define MOVI_DATAWIDTH64 0xC0 +#define MOVI_M_MOVEWIDTH 0x30 +#define MOVI_MOVEWIDTH8 0x00 +#define MOVI_MOVEWIDTH16 0x10 +#define MOVI_MOVEWIDTH32 0x20 +#define MOVI_MOVEWIDTH64 0x30 + +// +// Masks for CALL instruction encodings +// +#define OPERAND_M_RELATIVE_ADDR 0x10 +#define OPERAND_M_NATIVE_CALL 0x20 + +// +// Masks for decoding push/pop instructions +// +#define PUSHPOP_M_IMMDATA 0x80 // opcode bit indicating immediate data +#define PUSHPOP_M_64 0x40 // opcode bit indicating 64-bit operation +// +// Mask for operand of JMP instruction +// +#define JMP_M_RELATIVE 0x10 +#define JMP_M_CONDITIONAL 0x80 +#define JMP_M_CS 0x40 + +// +// Macros to determine if a given operand is indirect +// +#define OPERAND1_INDIRECT(op) ((op) & OPERAND_M_INDIRECT1) +#define OPERAND2_INDIRECT(op) ((op) & OPERAND_M_INDIRECT2) + +// +// Macros to extract the operands from second byte of instructions +// +#define OPERAND1_REGNUM(op) ((op) & OPERAND_M_OP1) +#define OPERAND2_REGNUM(op) (((op) & OPERAND_M_OP2) >> 4) + +#define OPERAND1_CHAR(op) ('0' + OPERAND1_REGNUM (op)) +#define OPERAND2_CHAR(op) ('0' + OPERAND2_REGNUM (op)) + +#define OPERAND1_REGDATA(pvm, op) pvm->R[OPERAND1_REGNUM (op)] +#define OPERAND2_REGDATA(pvm, op) pvm->R[OPERAND2_REGNUM (op)] + +// +// Condition masks usually for byte 1 encodings of code +// +#define CONDITION_M_CONDITIONAL 0x80 +#define CONDITION_M_CS 0x40 + +// +// Bits in the VM->StopFlags field +// +#define STOPFLAG_APP_DONE 0x0001 +#define STOPFLAG_BREAKPOINT 0x0002 +#define STOPFLAG_INVALID_BREAK 0x0004 +#define STOPFLAG_BREAK_ON_CALLEX 0x0008 + +// +// Masks for working with the VM flags register +// +#define VMFLAGS_CC 0x0001 // condition flag +#define VMFLAGS_STEP 0x0002 // step instruction mode +#define VMFLAGS_ALL_VALID (VMFLAGS_CC | VMFLAGS_STEP) + +// +// Macros for operating on the VM flags register +// +#define VMFLAG_SET(pVM, Flag) (pVM->Flags |= (Flag)) +#define VMFLAG_ISSET(pVM, Flag) ((pVM->Flags & (Flag)) ? 1 : 0) +#define VMFLAG_CLEAR(pVM, Flag) (pVM->Flags &= ~(Flag)) + +// +// Debug macro +// +#define EBCMSG(s) gST->ConOut->OutputString (gST->ConOut, s) + +// +// Define OPCODES +// +#define OPCODE_BREAK 0x00 +#define OPCODE_JMP 0x01 +#define OPCODE_JMP8 0x02 +#define OPCODE_CALL 0x03 +#define OPCODE_RET 0x04 +#define OPCODE_CMPEQ 0x05 +#define OPCODE_CMPLTE 0x06 +#define OPCODE_CMPGTE 0x07 +#define OPCODE_CMPULTE 0x08 +#define OPCODE_CMPUGTE 0x09 +#define OPCODE_NOT 0x0A +#define OPCODE_NEG 0x0B +#define OPCODE_ADD 0x0C +#define OPCODE_SUB 0x0D +#define OPCODE_MUL 0x0E +#define OPCODE_MULU 0x0F +#define OPCODE_DIV 0x10 +#define OPCODE_DIVU 0x11 +#define OPCODE_MOD 0x12 +#define OPCODE_MODU 0x13 +#define OPCODE_AND 0x14 +#define OPCODE_OR 0x15 +#define OPCODE_XOR 0x16 +#define OPCODE_SHL 0x17 +#define OPCODE_SHR 0x18 +#define OPCODE_ASHR 0x19 +#define OPCODE_EXTNDB 0x1A +#define OPCODE_EXTNDW 0x1B +#define OPCODE_EXTNDD 0x1C +#define OPCODE_MOVBW 0x1D +#define OPCODE_MOVWW 0x1E +#define OPCODE_MOVDW 0x1F +#define OPCODE_MOVQW 0x20 +#define OPCODE_MOVBD 0x21 +#define OPCODE_MOVWD 0x22 +#define OPCODE_MOVDD 0x23 +#define OPCODE_MOVQD 0x24 +#define OPCODE_MOVSNW 0x25 // Move signed natural with word index +#define OPCODE_MOVSND 0x26 // Move signed natural with dword index +// +// #define OPCODE_27 0x27 +// +#define OPCODE_MOVQQ 0x28 // Does this go away? +#define OPCODE_LOADSP 0x29 +#define OPCODE_STORESP 0x2A +#define OPCODE_PUSH 0x2B +#define OPCODE_POP 0x2C +#define OPCODE_CMPIEQ 0x2D +#define OPCODE_CMPILTE 0x2E +#define OPCODE_CMPIGTE 0x2F +#define OPCODE_CMPIULTE 0x30 +#define OPCODE_CMPIUGTE 0x31 +#define OPCODE_MOVNW 0x32 +#define OPCODE_MOVND 0x33 +// +// #define OPCODE_34 0x34 +// +#define OPCODE_PUSHN 0x35 +#define OPCODE_POPN 0x36 +#define OPCODE_MOVI 0x37 +#define OPCODE_MOVIN 0x38 +#define OPCODE_MOVREL 0x39 + +EFI_STATUS +EbcExecute ( + IN VM_CONTEXT *VmPtr + ) +; + +// +// Math library routines +// +INT64 +DivS64x64 ( + IN INT64 Value1, + IN INT64 Value2, + OUT INT64 *Remainder, + OUT UINT32 *Error + ) +; +#if 0 +UINT64 +DivU64x64 ( + IN UINT64 Value1, + IN UINT64 Value2, + OUT UINT64 *Remainder, + OUT UINT32 *Error + ) +; +#endif + +INT64 +MulS64x64 ( + IN INT64 Value1, + IN INT64 Value2, + OUT INT64 *ResultHigh + ) +; + +UINT64 +MulU64x64 ( + IN UINT64 Value1, + IN UINT64 Value2, + OUT UINT64 *ResultHigh + ) +; + +UINT64 +DivU64x64 ( + IN UINT64 Value1, + IN UINT64 Value2, + OUT UINT64 *Remainder, + OUT UINT32 *Error + ) +; + +INT64 +ARightShift64 ( + IN INT64 Operand, + IN INT64 Count + ) +; + +UINT64 +LeftShiftU64 ( + IN UINT64 Operand, + IN UINT64 Count + ) +; + +UINT64 +RightShiftU64 ( + IN UINT64 Operand, + IN UINT64 Count + ) +; + +UINT64 +GetVmVersion ( + VOID + ) +; + +EFI_STATUS +VmWriteMemN ( + IN VM_CONTEXT *VmPtr, + IN UINTN Addr, + IN UINTN Data + ) +; + +EFI_STATUS +VmWriteMem64 ( + IN VM_CONTEXT *VmPtr, + UINTN Addr, + IN UINT64 Data + ) +; + +// +// Define a protocol for an EBC VM test interface. +// +#define EFI_EBC_VM_TEST_PROTOCOL_GUID \ + { \ + 0xAAEACCFDL, 0xF27B, 0x4C17, { 0xB6, 0x10, 0x75, 0xCA, 0x1F, 0x2D, 0xFB, 0x52 } \ + } + +// +// Define for forward reference. +// +typedef struct _EFI_EBC_VM_TEST_PROTOCOL EFI_EBC_VM_TEST_PROTOCOL; + +typedef +EFI_STATUS +(*EBC_VM_TEST_EXECUTE) ( + IN EFI_EBC_VM_TEST_PROTOCOL * This, + IN VM_CONTEXT * VmPtr, + IN OUT UINTN *InstructionCount + ); + +typedef +EFI_STATUS +(*EBC_VM_TEST_ASM) ( + IN EFI_EBC_VM_TEST_PROTOCOL * This, + IN CHAR16 *AsmText, + IN OUT INT8 *Buffer, + IN OUT UINTN *BufferLen + ); + +typedef +EFI_STATUS +(*EBC_VM_TEST_DASM) ( + IN EFI_EBC_VM_TEST_PROTOCOL * This, + IN OUT CHAR16 *AsmText, + IN OUT INT8 *Buffer, + IN OUT UINTN *Len + ); + +// +// Prototype for the actual EBC test protocol interface +// +struct _EFI_EBC_VM_TEST_PROTOCOL { + EBC_VM_TEST_EXECUTE Execute; + EBC_VM_TEST_ASM Assemble; + EBC_VM_TEST_DASM Disassemble; +}; + +EFI_STATUS +EbcExecuteInstructions ( + IN EFI_EBC_VM_TEST_PROTOCOL *This, + IN VM_CONTEXT *VmPtr, + IN OUT UINTN *InstructionCount + ) +; + +#endif // ifndef _EBC_EXECUTE_H_ diff --git a/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c b/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c new file mode 100644 index 0000000000..220c8fefac --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.c @@ -0,0 +1,932 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EbcInt.c + +Abstract: + + Top level module for the EBC virtual machine implementation. + Provides auxilliary support routines for the VM. That is, routines + that are not particularly related to VM execution of EBC instructions. + +--*/ + +#include "EbcInt.h" +#include "EbcExecute.h" + +// +// We'll keep track of all thunks we create in a linked list. Each +// thunk is tied to an image handle, so we have a linked list of +// image handles, with each having a linked list of thunks allocated +// to that image handle. +// +typedef struct _EBC_THUNK_LIST { + VOID *ThunkBuffer; + struct _EBC_THUNK_LIST *Next; +} EBC_THUNK_LIST; + +typedef struct _EBC_IMAGE_LIST { + struct _EBC_IMAGE_LIST *Next; + EFI_HANDLE ImageHandle; + EBC_THUNK_LIST *ThunkList; +} EBC_IMAGE_LIST; + +// +// Function prototypes +// +EFI_STATUS +EFIAPI +InitializeEbcDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +STATIC +EFI_STATUS +EFIAPI +EbcUnloadImage ( + IN EFI_EBC_PROTOCOL *This, + IN EFI_HANDLE ImageHandle + ); + +STATIC +EFI_STATUS +EFIAPI +EbcCreateThunk ( + IN EFI_EBC_PROTOCOL *This, + IN EFI_HANDLE ImageHandle, + IN VOID *EbcEntryPoint, + OUT VOID **Thunk + ); + +STATIC +EFI_STATUS +EFIAPI +EbcGetVersion ( + IN EFI_EBC_PROTOCOL *This, + IN OUT UINT64 *Version + ); + +// +// These two functions and the GUID are used to produce an EBC test protocol. +// This functionality is definitely not required for execution. +// +STATIC +EFI_STATUS +InitEbcVmTestProtocol ( + IN EFI_HANDLE *Handle + ); + +STATIC +EFI_STATUS +EbcVmTestUnsupported ( + VOID + ); + +STATIC +EFI_STATUS +EFIAPI +EbcRegisterICacheFlush ( + IN EFI_EBC_PROTOCOL *This, + IN EBC_ICACHE_FLUSH Flush + ); + +STATIC +EFI_STATUS +EFIAPI +EbcDebugGetMaximumProcessorIndex ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex + ); + +STATIC +EFI_STATUS +EFIAPI +EbcDebugRegisterPeriodicCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ); + +STATIC +EFI_STATUS +EFIAPI +EbcDebugRegisterExceptionCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK ExceptionCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + ); + +STATIC +EFI_STATUS +EFIAPI +EbcDebugInvalidateInstructionCache ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINT64 Length + ); + +// +// We have one linked list of image handles for the whole world. Since +// there should only be one interpreter, make them global. They must +// also be global since the execution of an EBC image does not provide +// a This pointer. +// +static EBC_IMAGE_LIST *mEbcImageList = NULL; + +// +// Callback function to flush the icache after thunk creation +// +static EBC_ICACHE_FLUSH mEbcICacheFlush; + +// +// These get set via calls by the debug agent +// +static EFI_PERIODIC_CALLBACK mDebugPeriodicCallback = NULL; +static EFI_EXCEPTION_CALLBACK mDebugExceptionCallback = NULL; +static EFI_GUID mEfiEbcVmTestProtocolGuid = EFI_EBC_VM_TEST_PROTOCOL_GUID; + +EFI_STATUS +EFIAPI +InitializeEbcDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initializes the VM EFI interface. Allocates memory for the VM interface + and registers the VM protocol. + +Arguments: + + ImageHandle - EFI image handle. + SystemTable - Pointer to the EFI system table. + +Returns: + Standard EFI status code. + +--*/ +{ + EFI_EBC_PROTOCOL *EbcProtocol; + EFI_EBC_PROTOCOL *OldEbcProtocol; + EFI_STATUS Status; + EFI_DEBUG_SUPPORT_PROTOCOL *EbcDebugProtocol; + EFI_HANDLE *HandleBuffer; + UINTN NumHandles; + UINTN Index; + BOOLEAN Installed; + + // + // Allocate memory for our protocol. Then fill in the blanks. + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_EBC_PROTOCOL), + (VOID **) &EbcProtocol + ); + if (Status != EFI_SUCCESS) { + return EFI_OUT_OF_RESOURCES; + } + + EbcProtocol->CreateThunk = EbcCreateThunk; + EbcProtocol->UnloadImage = EbcUnloadImage; + EbcProtocol->RegisterICacheFlush = EbcRegisterICacheFlush; + EbcProtocol->GetVersion = EbcGetVersion; + mEbcICacheFlush = NULL; + + // + // Find any already-installed EBC protocols and uninstall them + // + Installed = FALSE; + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiEbcProtocolGuid, + NULL, + &NumHandles, + &HandleBuffer + ); + if (Status == EFI_SUCCESS) { + // + // Loop through the handles + // + for (Index = 0; Index < NumHandles; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiEbcProtocolGuid, + (VOID **) &OldEbcProtocol + ); + if (Status == EFI_SUCCESS) { + if (gBS->ReinstallProtocolInterface ( + HandleBuffer[Index], + &gEfiEbcProtocolGuid, + OldEbcProtocol, + EbcProtocol + ) == EFI_SUCCESS) { + Installed = TRUE; + } + } + } + } + + if (HandleBuffer != NULL) { + gBS->FreePool (HandleBuffer); + HandleBuffer = NULL; + } + // + // Add the protocol so someone can locate us if we haven't already. + // + if (!Installed) { + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiEbcProtocolGuid, + EFI_NATIVE_INTERFACE, + EbcProtocol + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (EbcProtocol); + return Status; + } + } + // + // Allocate memory for our debug protocol. Then fill in the blanks. + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_DEBUG_SUPPORT_PROTOCOL), + (VOID **) &EbcDebugProtocol + ); + if (Status != EFI_SUCCESS) { + return EFI_OUT_OF_RESOURCES; + } + + EbcDebugProtocol->Isa = IsaEbc; + EbcDebugProtocol->GetMaximumProcessorIndex = EbcDebugGetMaximumProcessorIndex; + EbcDebugProtocol->RegisterPeriodicCallback = EbcDebugRegisterPeriodicCallback; + EbcDebugProtocol->RegisterExceptionCallback = EbcDebugRegisterExceptionCallback; + EbcDebugProtocol->InvalidateInstructionCache = EbcDebugInvalidateInstructionCache; + + // + // Add the protocol so the debug agent can find us + // + Status = gBS->InstallProtocolInterface ( + &ImageHandle, + &gEfiDebugSupportProtocolGuid, + EFI_NATIVE_INTERFACE, + EbcDebugProtocol + ); + // + // This is recoverable, so free the memory and continue. + // + if (EFI_ERROR (Status)) { + gBS->FreePool (EbcDebugProtocol); + } + // + // Produce a VM test interface protocol. Not required for execution. + // + DEBUG_CODE ( + InitEbcVmTestProtocol (&ImageHandle); + ); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +EbcCreateThunk ( + IN EFI_EBC_PROTOCOL *This, + IN EFI_HANDLE ImageHandle, + IN VOID *EbcEntryPoint, + OUT VOID **Thunk + ) +/*++ + +Routine Description: + + This is the top-level routine plugged into the EBC protocol. Since thunks + are very processor-specific, from here we dispatch directly to the very + processor-specific routine EbcCreateThunks(). + +Arguments: + + This - protocol instance pointer + ImageHandle - handle to the image. The EBC interpreter may use this to keep + track of any resource allocations performed in loading and + executing the image. + EbcEntryPoint - the entry point for the image (as defined in the file header) + Thunk - pointer to thunk pointer where the address of the created + thunk is returned. + +Returns: + + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + + Status = EbcCreateThunks ( + ImageHandle, + EbcEntryPoint, + Thunk, + FLAG_THUNK_ENTRY_POINT + ); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +EbcDebugGetMaximumProcessorIndex ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex + ) +/*++ + +Routine Description: + + This EBC debugger protocol service is called by the debug agent + +Arguments: + + This - pointer to the caller's debug support protocol interface + MaxProcessorIndex - pointer to a caller allocated UINTN in which the maximum + processor index is returned. + +Returns: + + Standard EFI_STATUS + +--*/ +{ + *MaxProcessorIndex = 0; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +EbcDebugRegisterPeriodicCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ) +/*++ + +Routine Description: + + This protocol service is called by the debug agent to register a function + for us to call on a periodic basis. + + +Arguments: + + This - pointer to the caller's debug support protocol interface + PeriodicCallback - pointer to the function to call periodically + +Returns: + + Always EFI_SUCCESS + +--*/ +{ + mDebugPeriodicCallback = PeriodicCallback; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +EbcDebugRegisterExceptionCallback ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK ExceptionCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + ) +/*++ + +Routine Description: + + This protocol service is called by the debug agent to register a function + for us to call when we detect an exception. + + +Arguments: + + This - pointer to the caller's debug support protocol interface + PeriodicCallback - pointer to the function to call periodically + +Returns: + + Always EFI_SUCCESS + +--*/ +{ + mDebugExceptionCallback = ExceptionCallback; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +EbcDebugInvalidateInstructionCache ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + This EBC debugger protocol service is called by the debug agent. Required + for DebugSupport compliance but is only stubbed out for EBC. + +Arguments: + +Returns: + + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EbcDebugSignalException ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EXCEPTION_FLAGS ExceptionFlags, + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + + The VM interpreter calls this function when an exception is detected. + +Arguments: + + VmPtr - pointer to a VM context for passing info to the EFI debugger. + +Returns: + + EFI_SUCCESS if it returns at all + +--*/ +{ + EFI_SYSTEM_CONTEXT_EBC EbcContext; + EFI_SYSTEM_CONTEXT SystemContext; + EFI_STATUS_CODE_VALUE StatusCodeValue; + BOOLEAN Report; + // + // Save the exception in the context passed in + // + VmPtr->ExceptionFlags |= ExceptionFlags; + VmPtr->LastException = ExceptionType; + // + // If it's a fatal exception, then flag it in the VM context in case an + // attached debugger tries to return from it. + // + if (ExceptionFlags & EXCEPTION_FLAG_FATAL) { + VmPtr->StopFlags |= STOPFLAG_APP_DONE; + } + // + // Initialize the context structure + // + EbcContext.R0 = VmPtr->R[0]; + EbcContext.R1 = VmPtr->R[1]; + EbcContext.R2 = VmPtr->R[2]; + EbcContext.R3 = VmPtr->R[3]; + EbcContext.R4 = VmPtr->R[4]; + EbcContext.R5 = VmPtr->R[5]; + EbcContext.R6 = VmPtr->R[6]; + EbcContext.R7 = VmPtr->R[7]; + EbcContext.Ip = (UINT64) (UINTN) VmPtr->Ip; + EbcContext.Flags = VmPtr->Flags; + SystemContext.SystemContextEbc = &EbcContext; + // + // If someone's registered for exception callbacks, then call them. + // Otherwise report the status code via the status code API + // + if (mDebugExceptionCallback != NULL) { + mDebugExceptionCallback (ExceptionType, SystemContext); + } + // + // Determine if we should report the exception. We report all of them by default, + // but if a debugger is attached don't report the breakpoint, debug, and step exceptions. + // Note that EXCEPT_EBC_OVERFLOW is never reported by this VM implementation, so is + // not included in the switch statement. + // + Report = TRUE; + switch (ExceptionType) { + case EXCEPT_EBC_UNDEFINED: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_UNDEFINED; + break; + + case EXCEPT_EBC_DIVIDE_ERROR: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_DIVIDE_ERROR; + break; + + case EXCEPT_EBC_DEBUG: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_DEBUG; + Report = (BOOLEAN) ((mDebugExceptionCallback == NULL) ? TRUE : FALSE); + break; + + case EXCEPT_EBC_BREAKPOINT: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_BREAKPOINT; + Report = (BOOLEAN) ((mDebugExceptionCallback == NULL) ? TRUE : FALSE); + break; + + case EXCEPT_EBC_INVALID_OPCODE: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_INVALID_OPCODE; + break; + + case EXCEPT_EBC_STACK_FAULT: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_STACK_FAULT; + break; + + case EXCEPT_EBC_ALIGNMENT_CHECK: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_ALIGNMENT_CHECK; + break; + + case EXCEPT_EBC_INSTRUCTION_ENCODING: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_INSTRUCTION_ENCODING; + break; + + case EXCEPT_EBC_BAD_BREAK: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_BAD_BREAK; + break; + + case EXCEPT_EBC_STEP: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_EBC_STEP; + Report = (BOOLEAN) ((mDebugExceptionCallback == NULL) ? TRUE : FALSE); + break; + + default: + StatusCodeValue = EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_NON_SPECIFIC; + break; + } + // + // If we determined that we should report the condition, then do so now. + // + if (Report) { + REPORT_STATUS_CODE (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED, StatusCodeValue); + } + + switch (ExceptionType) { + // + // If ReportStatusCode returned, then for most exceptions we do an assert. The + // ExceptionType++ is done simply to force the ASSERT() condition to be met. + // For breakpoints, assume a debugger did not insert a software breakpoint + // and skip the instruction. + // + case EXCEPT_EBC_BREAKPOINT: + VmPtr->Ip += 2; + break; + + case EXCEPT_EBC_STEP: + break; + + case EXCEPT_EBC_UNDEFINED: + ExceptionType++; + ASSERT (ExceptionType == EXCEPT_EBC_UNDEFINED); + break; + + case EXCEPT_EBC_DIVIDE_ERROR: + ExceptionType++; + ASSERT (ExceptionType == EXCEPT_EBC_DIVIDE_ERROR); + break; + + case EXCEPT_EBC_DEBUG: + ExceptionType++; + ASSERT (ExceptionType == EXCEPT_EBC_DEBUG); + break; + + case EXCEPT_EBC_INVALID_OPCODE: + ExceptionType++; + ASSERT (ExceptionType == EXCEPT_EBC_INVALID_OPCODE); + break; + + case EXCEPT_EBC_STACK_FAULT: + ExceptionType++; + ASSERT (ExceptionType == EXCEPT_EBC_STACK_FAULT); + break; + + case EXCEPT_EBC_ALIGNMENT_CHECK: + ExceptionType++; + ASSERT (ExceptionType == EXCEPT_EBC_ALIGNMENT_CHECK); + break; + + case EXCEPT_EBC_INSTRUCTION_ENCODING: + ExceptionType++; + ASSERT (ExceptionType == EXCEPT_EBC_INSTRUCTION_ENCODING); + break; + + case EXCEPT_EBC_BAD_BREAK: + ExceptionType++; + ASSERT (ExceptionType == EXCEPT_EBC_BAD_BREAK); + break; + + default: + // + // Unknown + // + ASSERT (0); + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EbcDebugPeriodic ( + IN VM_CONTEXT *VmPtr + ) +/*++ + +Routine Description: + + The VM interpreter calls this function on a periodic basis to support + the EFI debug support protocol. + +Arguments: + + VmPtr - pointer to a VM context for passing info to the debugger. + +Returns: + + Standard EFI status. + +--*/ +{ + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +EbcUnloadImage ( + IN EFI_EBC_PROTOCOL *This, + IN EFI_HANDLE ImageHandle + ) +/*++ + +Routine Description: + + This routine is called by the core when an image is being unloaded from + memory. Basically we now have the opportunity to do any necessary cleanup. + Typically this will include freeing any memory allocated for thunk-creation. + +Arguments: + + This - protocol instance pointer + ImageHandle - handle to the image being unloaded. + +Returns: + + EFI_INVALID_PARAMETER - the ImageHandle passed in was not found in + the internal list of EBC image handles. + EFI_STATUS - completed successfully + +--*/ +{ + EBC_THUNK_LIST *ThunkList; + EBC_THUNK_LIST *NextThunkList; + EBC_IMAGE_LIST *ImageList; + EBC_IMAGE_LIST *PrevImageList; + // + // First go through our list of known image handles and see if we've already + // created an image list element for this image handle. + // + PrevImageList = NULL; + for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) { + if (ImageList->ImageHandle == ImageHandle) { + break; + } + // + // Save the previous so we can connect the lists when we remove this one + // + PrevImageList = ImageList; + } + + if (ImageList == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Free up all the thunk buffers and thunks list elements for this image + // handle. + // + ThunkList = ImageList->ThunkList; + while (ThunkList != NULL) { + NextThunkList = ThunkList->Next; + gBS->FreePool (ThunkList->ThunkBuffer); + gBS->FreePool (ThunkList); + ThunkList = NextThunkList; + } + // + // Now remove this image list element from the chain + // + if (PrevImageList == NULL) { + // + // Remove from head + // + mEbcImageList = ImageList->Next; + } else { + PrevImageList->Next = ImageList->Next; + } + // + // Now free up the image list element + // + gBS->FreePool (ImageList); + return EFI_SUCCESS; +} + +EFI_STATUS +EbcAddImageThunk ( + IN EFI_HANDLE ImageHandle, + IN VOID *ThunkBuffer, + IN UINT32 ThunkSize + ) +/*++ + +Routine Description: + + Add a thunk to our list of thunks for a given image handle. + Also flush the instruction cache since we've written thunk code + to memory that will be executed eventually. + +Arguments: + + ImageHandle - the image handle to which the thunk is tied + ThunkBuffer - the buffer we've created/allocated + ThunkSize - the size of the thunk memory allocated + +Returns: + + EFI_OUT_OF_RESOURCES - memory allocation failed + EFI_SUCCESS - successful completion + +--*/ +{ + EBC_THUNK_LIST *ThunkList; + EBC_IMAGE_LIST *ImageList; + EFI_STATUS Status; + + // + // It so far so good, then flush the instruction cache + // + if (mEbcICacheFlush != NULL) { + Status = mEbcICacheFlush ((EFI_PHYSICAL_ADDRESS) (UINTN) ThunkBuffer, ThunkSize); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // Go through our list of known image handles and see if we've already + // created a image list element for this image handle. + // + for (ImageList = mEbcImageList; ImageList != NULL; ImageList = ImageList->Next) { + if (ImageList->ImageHandle == ImageHandle) { + break; + } + } + + if (ImageList == NULL) { + // + // Allocate a new one + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EBC_IMAGE_LIST), + (VOID **) &ImageList + ); + if (Status != EFI_SUCCESS) { + return EFI_OUT_OF_RESOURCES; + } + + ImageList->ThunkList = NULL; + ImageList->ImageHandle = ImageHandle; + ImageList->Next = mEbcImageList; + mEbcImageList = ImageList; + } + // + // Ok, now create a new thunk element to add to the list + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EBC_THUNK_LIST), + (VOID **) &ThunkList + ); + if (Status != EFI_SUCCESS) { + return EFI_OUT_OF_RESOURCES; + } + // + // Add it to the head of the list + // + ThunkList->Next = ImageList->ThunkList; + ThunkList->ThunkBuffer = ThunkBuffer; + ImageList->ThunkList = ThunkList; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +EbcRegisterICacheFlush ( + IN EFI_EBC_PROTOCOL *This, + IN EBC_ICACHE_FLUSH Flush + ) +{ + mEbcICacheFlush = Flush; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +EbcGetVersion ( + IN EFI_EBC_PROTOCOL *This, + IN OUT UINT64 *Version + ) +{ + if (Version == NULL) { + return EFI_INVALID_PARAMETER; + } + + *Version = GetVmVersion (); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +InitEbcVmTestProtocol ( + IN EFI_HANDLE *IHandle + ) +/*++ + +Routine Description: + + Produce an EBC VM test protocol that can be used for regression tests. + +Arguments: + + IHandle - handle on which to install the protocol. + +Returns: + + EFI_OUT_OF_RESOURCES - memory allocation failed + EFI_SUCCESS - successful completion + +--*/ +{ + EFI_HANDLE Handle; + EFI_STATUS Status; + EFI_EBC_VM_TEST_PROTOCOL *EbcVmTestProtocol; + + // + // Allocate memory for the protocol, then fill in the fields + // + Status = gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_EBC_VM_TEST_PROTOCOL), (VOID **) &EbcVmTestProtocol); + if (Status != EFI_SUCCESS) { + return EFI_OUT_OF_RESOURCES; + } + EbcVmTestProtocol->Execute = (EBC_VM_TEST_EXECUTE) EbcExecuteInstructions; + + DEBUG_CODE( + EbcVmTestProtocol->Assemble = (EBC_VM_TEST_ASM) EbcVmTestUnsupported; + EbcVmTestProtocol->Disassemble = (EBC_VM_TEST_DASM) EbcVmTestUnsupported; + ); + + // + // Publish the protocol + // + Handle = NULL; + Status = gBS->InstallProtocolInterface (&Handle, &mEfiEbcVmTestProtocolGuid, EFI_NATIVE_INTERFACE, EbcVmTestProtocol); + if (EFI_ERROR (Status)) { + gBS->FreePool (EbcVmTestProtocol); + } + return Status; +} +STATIC +EFI_STATUS +EbcVmTestUnsupported () +{ + return EFI_UNSUPPORTED; +} + diff --git a/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.h b/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.h new file mode 100644 index 0000000000..51bd785a53 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/EbcInt.h @@ -0,0 +1,231 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EbcInt.h + +Abstract: + + Main routines for the EBC interpreter. Includes the initialization and + main interpreter routines. + +--*/ + +#ifndef _EBC_INT_H_ +#define _EBC_INT_H_ + +typedef INT64 VM_REGISTER; +typedef UINT8 *VMIP; // instruction pointer for the VM +typedef UINT32 EXCEPTION_FLAGS; + +typedef struct { + VM_REGISTER R[8]; // General purpose registers. + UINT64 Flags; // Flags register: + // 0 Set to 1 if the result of the last compare was true + // 1 Set to 1 if stepping + // 2..63 Reserved. + VMIP Ip; // Instruction pointer. + UINTN LastException; // + EXCEPTION_FLAGS ExceptionFlags; // to keep track of exceptions + UINT32 StopFlags; + UINT32 CompilerVersion; // via break(6) + UINTN HighStackBottom; // bottom of the upper stack + UINTN LowStackTop; // top of the lower stack + UINT64 StackRetAddr; // location of final return address on stack + UINTN *StackMagicPtr; // pointer to magic value on stack to detect corruption + EFI_HANDLE ImageHandle; // for this EBC driver + EFI_SYSTEM_TABLE *SystemTable; // for debugging only + UINTN LastAddrConverted; // for debug + UINTN LastAddrConvertedValue; // for debug + VOID *FramePtr; + VOID *EntryPoint; // entry point of EBC image + UINTN ImageBase; +} VM_CONTEXT; + +// +// Bits of exception flags field of VM context +// +#define EXCEPTION_FLAG_FATAL 0x80000000 // can't continue +#define EXCEPTION_FLAG_ERROR 0x40000000 // bad, but try to continue +#define EXCEPTION_FLAG_WARNING 0x20000000 // harmless problem +#define EXCEPTION_FLAG_NONE 0x00000000 // for normal return +// +// Flags passed to the internal create-thunks function. +// +#define FLAG_THUNK_ENTRY_POINT 0x01 // thunk for an image entry point +#define FLAG_THUNK_PROTOCOL 0x00 // thunk for an EBC protocol service +// +// Put this value at the bottom of the VM's stack gap so we can check it on +// occasion to make sure the stack has not been corrupted. +// +#define VM_STACK_KEY_VALUE 0xDEADBEEF + +EFI_STATUS +EbcCreateThunks ( + IN EFI_HANDLE ImageHandle, + IN VOID *EbcEntryPoint, + OUT VOID **Thunk, + IN UINT32 Flags + ) +; + +EFI_STATUS +EbcAddImageThunk ( + IN EFI_HANDLE ImageHandle, + IN VOID *ThunkBuffer, + IN UINT32 ThunkSize + ) +; + +// +// The interpreter calls these when an exception is detected, +// or as a periodic callback. +// +EFI_STATUS +EbcDebugSignalException ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EXCEPTION_FLAGS ExceptionFlags, + IN VM_CONTEXT *VmPtr + ) +; + +// +// Define a constant of how often to call the debugger periodic callback +// function. +// +#define EBC_VM_PERIODIC_CALLBACK_RATE 1000 + +EFI_STATUS +EbcDebugSignalPeriodic ( + IN VM_CONTEXT *VmPtr + ) +; + +// +// External low level functions that are native-processor dependent +// +UINTN +EbcLLGetEbcEntryPoint ( + VOID + ) +; + +UINTN +EbcLLGetStackPointer ( + VOID + ) +; + +VOID +EbcLLCALLEXNative ( + IN UINTN CallAddr, + IN UINTN EbcSp, + IN VOID *FramePtr + ) +; + +VOID +EbcLLCALLEX ( + IN VM_CONTEXT *VmPtr, + IN UINTN CallAddr, + IN UINTN EbcSp, + IN VOID *FramePtr, + IN UINT8 Size + ) +; + +INT64 +EbcLLGetReturnValue ( + VOID + ) +; + +// +// Defines for a simple EBC debugger interface +// +typedef struct _EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL; + +#define EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL_GUID \ + { \ + 0x2a72d11e, 0x7376, 0x40f6, { 0x9c, 0x68, 0x23, 0xfa, 0x2f, 0xe3, 0x63, 0xf1 } \ + } + +typedef +EFI_STATUS +(*EBC_DEBUGGER_SIGNAL_EXCEPTION) ( + IN EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL * This, + IN VM_CONTEXT * VmPtr, + IN EFI_EXCEPTION_TYPE ExceptionType + ); + +typedef +VOID +(*EBC_DEBUGGER_DEBUG) ( + IN EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL * This, + IN VM_CONTEXT * VmPtr + ); + +typedef +UINT32 +(*EBC_DEBUGGER_DASM) ( + IN EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL * This, + IN VM_CONTEXT * VmPtr, + IN UINT16 *DasmString OPTIONAL, + IN UINT32 DasmStringSize + ); + +// +// This interface allows you to configure the EBC debug support +// driver. For example, turn on or off saving and printing of +// delta VM even if called. Or to even disable the entire interface, +// in which case all functions become no-ops. +// +typedef +EFI_STATUS +(*EBC_DEBUGGER_CONFIGURE) ( + IN EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL * This, + IN UINT32 ConfigId, + IN UINTN ConfigValue + ); + +// +// Prototype for the actual EBC debug support protocol interface +// +struct _EFI_EBC_SIMPLE_DEBUGGER_PROTOCOL { + EBC_DEBUGGER_DEBUG Debugger; + EBC_DEBUGGER_SIGNAL_EXCEPTION SignalException; + EBC_DEBUGGER_DASM Dasm; + EBC_DEBUGGER_CONFIGURE Configure; +}; + +typedef struct { + EFI_EBC_PROTOCOL *This; + VOID *EntryPoint; + EFI_HANDLE ImageHandle; + VM_CONTEXT VmContext; +} EFI_EBC_THUNK_DATA; + +#define EBC_PROTOCOL_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('e', 'b', 'c', 'p') + +struct _EBC_PROTOCOL_PRIVATE_DATA { + UINT32 Signature; + EFI_EBC_PROTOCOL EbcProtocol; + UINTN StackBase; + UINTN StackTop; + UINTN StackSize; +} ; + +#define EBC_PROTOCOL_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, EBC_PROTOCOL_PRIVATE_DATA, EbcProtocol, EBC_PROTOCOL_PRIVATE_DATA_SIGNATURE) + + +#endif // #ifndef _EBC_INT_H_ diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.asm b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.asm new file mode 100644 index 0000000000..b485bc9fd2 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcLowLevel.asm @@ -0,0 +1,148 @@ + page ,132 + title VM ASSEMBLY LANGUAGE ROUTINES +;**************************************************************************** +;* +;* Copyright (c) 2006, 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. +;* +;**************************************************************************** +;**************************************************************************** +; REV 1.0 +;**************************************************************************** +; +; Rev Date Description +; --- -------- ------------------------------------------------------------ +; 1.0 03/14/01 Initial creation of file. +; +;**************************************************************************** + +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; This code provides low level routines that support the Virtual Machine +; for option ROMs. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +;--------------------------------------------------------------------------- +; Equate files needed. +;--------------------------------------------------------------------------- + +.XLIST + +.LIST + +;--------------------------------------------------------------------------- +; Assembler options +;--------------------------------------------------------------------------- + +.686p +.model flat +.code +;--------------------------------------------------------------------------- +;;GenericPostSegment SEGMENT USE16 +;--------------------------------------------------------------------------- + +;**************************************************************************** +; EbcLLCALLEXNative +; +; This function is called to execute an EBC CALLEX instruction +; to native code. +; This instruction requires that we thunk out to external native +; code. For IA32, we simply switch stacks and jump to the +; specified function. On return, we restore the stack pointer +; to its original location. +; +; Destroys no working registers. +;**************************************************************************** +; VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr) +_EbcLLCALLEXNative PROC NEAR PUBLIC + push ebp + mov ebp, esp ; standard function prolog + + ; Get function address in a register + ; mov ecx, FuncAddr => mov ecx, dword ptr [FuncAddr] + mov ecx, dword ptr [esp]+8 + + ; Set stack pointer to new value + ; mov eax, NewStackPointer => mov eax, dword ptr [NewSp] + mov eax, dword ptr [esp] + 0Ch + mov esp, eax + + ; Now call the external routine + call ecx + + ; ebp is preserved by the callee. In this function it + ; equals the original esp, so set them equal + mov esp, ebp + + ; Standard function epilog + mov esp, ebp + pop ebp + ret +_EbcLLCALLEXNative ENDP + + +; UINTN EbcLLGetEbcEntryPoint(VOID); +; Routine Description: +; The VM thunk code stuffs an EBC entry point into a processor +; register. Since we can't use inline assembly to get it from +; the interpreter C code, stuff it into the return value +; register and return. +; +; Arguments: +; None. +; +; Returns: +; The contents of the register in which the entry point is passed. +; +_EbcLLGetEbcEntryPoint PROC NEAR PUBLIC + ret +_EbcLLGetEbcEntryPoint ENDP + +;/*++ +; +;Routine Description: +; +; Return the caller's value of the stack pointer. +; +;Arguments: +; +; None. +; +;Returns: +; +; The current value of the stack pointer for the caller. We +; adjust it by 4 here because when they called us, the return address +; is put on the stack, thereby lowering it by 4 bytes. +; +;--*/ + +; UINTN EbcLLGetStackPointer() +_EbcLLGetStackPointer PROC NEAR PUBLIC + mov eax, esp ; get current stack pointer + add eax, 4 ; stack adjusted by this much when we were called + ret +_EbcLLGetStackPointer ENDP + +; UINT64 EbcLLGetReturnValue(VOID); +; Routine Description: +; When EBC calls native, on return the VM has to stuff the return +; value into a VM register. It's assumed here that the value is still +; in the register, so simply return and the caller should get the +; return result properly. +; +; Arguments: +; None. +; +; Returns: +; The unmodified value returned by the native code. +; +_EbcLLGetReturnValue PROC NEAR PUBLIC + ret +_EbcLLGetReturnValue ENDP + +END diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcSupport.c b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcSupport.c new file mode 100644 index 0000000000..14059d71e5 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/EbcSupport.c @@ -0,0 +1,482 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EbcSupport.c + +Abstract: + + This module contains EBC support routines that are customized based on + the target processor. + +--*/ + +#include "EbcInt.h" +#include "EbcExecute.h" + +// +// NOTE: This is the stack size allocated for the interpreter +// when it executes an EBC image. The requirements can change +// based on whether or not a debugger is present, and other +// platform-specific configurations. +// +#define VM_STACK_SIZE (1024 * 4) +#define EBC_THUNK_SIZE 32 + +VOID +EbcLLCALLEX ( + IN VM_CONTEXT *VmPtr, + IN UINTN FuncAddr, + IN UINTN NewStackPointer, + IN VOID *FramePtr, + IN UINT8 Size + ) +/*++ + +Routine Description: + + This function is called to execute an EBC CALLEX instruction. + The function check the callee's content to see whether it is common native + code or a thunk to another piece of EBC code. + If the callee is common native code, use EbcLLCAllEXASM to manipulate, + otherwise, set the VM->IP to target EBC code directly to avoid another VM + be startup which cost time and stack space. + +Arguments: + + VmPtr - Pointer to a VM context. + FuncAddr - Callee's address + NewStackPointer - New stack pointer after the call + FramePtr - New frame pointer after the call + Size - The size of call instruction + +Returns: + + None. + +--*/ +{ + UINTN IsThunk; + UINTN TargetEbcAddr; + + IsThunk = 1; + TargetEbcAddr = 0; + + // + // Processor specific code to check whether the callee is a thunk to EBC. + // + if (*((UINT8 *)FuncAddr) != 0xB8) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 1) != 0xBC) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 2) != 0x2E) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 3) != 0x11) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 4) != 0xCA) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 5) != 0xB8) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 10) != 0xB9) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 15) != 0xFF) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 16) != 0xE1) { + IsThunk = 0; + goto Action; + } + + TargetEbcAddr = ((UINTN)(*((UINT8 *)FuncAddr + 9)) << 24) + ((UINTN)(*((UINT8 *)FuncAddr + 8)) << 16) + + ((UINTN)(*((UINT8 *)FuncAddr + 7)) << 8) + ((UINTN)(*((UINT8 *)FuncAddr + 6))); + +Action: + if (IsThunk == 1){ + // + // The callee is a thunk to EBC, adjust the stack pointer down 16 bytes and + // put our return address and frame pointer on the VM stack. + // Then set the VM's IP to new EBC code. + // + VmPtr->R[0] -= 8; + VmWriteMemN (VmPtr, (UINTN) VmPtr->R[0], (UINTN) FramePtr); + VmPtr->FramePtr = (VOID *) (UINTN) VmPtr->R[0]; + VmPtr->R[0] -= 8; + VmWriteMem64 (VmPtr, (UINTN) VmPtr->R[0], (UINT64) (UINTN) (VmPtr->Ip + Size)); + + VmPtr->Ip = (VMIP) (UINTN) TargetEbcAddr; + } else { + // + // The callee is not a thunk to EBC, call native code. + // + EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr); + + // + // Get return value and advance the IP. + // + VmPtr->R[7] = EbcLLGetReturnValue (); + VmPtr->Ip += Size; + } +} + +STATIC +UINT64 +EbcInterpret ( + IN OUT UINTN Arg1, + IN OUT UINTN Arg2, + IN OUT UINTN Arg3, + IN OUT UINTN Arg4, + IN OUT UINTN Arg5, + IN OUT UINTN Arg6, + IN OUT UINTN Arg7, + IN OUT UINTN Arg8 + ) +/*++ + +Routine Description: + + Begin executing an EBC image. The address of the entry point is passed + in via a processor register, so we'll need to make a call to get the + value. + +Arguments: + + None. Since we're called from a fixed up thunk (which we want to keep + small), our only so-called argument is the EBC entry point passed in + to us in a processor register. + +Returns: + + The value returned by the EBC application we're going to run. + +--*/ +{ + // + // Create a new VM context on the stack + // + VM_CONTEXT VmContext; + UINTN Addr; + + // + // Get the EBC entry point from the processor register. + // + Addr = EbcLLGetEbcEntryPoint (); + + // + // Now clear out our context + // + ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT)); + + // + // Set the VM instruction pointer to the correct location in memory. + // + VmContext.Ip = (VMIP) Addr; + + // + // Initialize the stack pointer for the EBC. Get the current system stack + // pointer and adjust it down by the max needed for the interpreter. + // + Addr = EbcLLGetStackPointer (); + + VmContext.R[0] = (UINT64) Addr; + VmContext.R[0] -= VM_STACK_SIZE; + + // + // Align the stack on a natural boundary + // + VmContext.R[0] &= ~(sizeof (UINTN) - 1); + + // + // Put a magic value in the stack gap, then adjust down again + // + *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) VM_STACK_KEY_VALUE; + VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0]; + VmContext.R[0] -= sizeof (UINTN); + + // + // For IA32, this is where we say our return address is + // + VmContext.StackRetAddr = (UINT64) VmContext.R[0]; + VmContext.LowStackTop = (UINTN) VmContext.R[0]; + + // + // We need to keep track of where the EBC stack starts. This way, if the EBC + // accesses any stack variables above its initial stack setting, then we know + // it's accessing variables passed into it, which means the data is on the + // VM's stack. + // When we're called, on the stack (high to low) we have the parameters, the + // return address, then the saved ebp. Save the pointer to the return address. + // EBC code knows that's there, so should look above it for function parameters. + // The offset is the size of locals (VMContext + Addr + saved ebp). + // Note that the interpreter assumes there is a 16 bytes of return address on + // the stack too, so adjust accordingly. + // VmContext.HighStackBottom = (UINTN)(Addr + sizeof (VmContext) + sizeof (Addr)); + // + VmContext.HighStackBottom = (UINTN) &Arg1 - 16; + // + // Begin executing the EBC code + // + EbcExecute (&VmContext); + + // + // Return the value in R[7] unless there was an error + // + return (UINT64) VmContext.R[7]; +} + +STATIC +UINT64 +ExecuteEbcImageEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Begin executing an EBC image. The address of the entry point is passed + in via a processor register, so we'll need to make a call to get the + value. + +Arguments: + + ImageHandle - image handle for the EBC application we're executing + SystemTable - standard system table passed into an driver's entry point + +Returns: + + The value returned by the EBC application we're going to run. + +--*/ +{ + // + // Create a new VM context on the stack + // + VM_CONTEXT VmContext; + UINTN Addr; + + // + // Get the EBC entry point from the processor register. Make sure you don't + // call any functions before this or you could mess up the register the + // entry point is passed in. + // + Addr = EbcLLGetEbcEntryPoint (); + + // + // Print(L"*** Thunked into EBC entry point - ImageHandle = 0x%X\n", (UINTN)ImageHandle); + // Print(L"EBC entry point is 0x%X\n", (UINT32)(UINTN)Addr); + // + // Now clear out our context + // + ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT)); + + // + // Save the image handle so we can track the thunks created for this image + // + VmContext.ImageHandle = ImageHandle; + VmContext.SystemTable = SystemTable; + + // + // Set the VM instruction pointer to the correct location in memory. + // + VmContext.Ip = (VMIP) Addr; + + // + // Initialize the stack pointer for the EBC. Get the current system stack + // pointer and adjust it down by the max needed for the interpreter. + // + Addr = EbcLLGetStackPointer (); + VmContext.R[0] = (UINT64) Addr; + VmContext.R[0] -= VM_STACK_SIZE; + // + // Put a magic value in the stack gap, then adjust down again + // + *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) VM_STACK_KEY_VALUE; + VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0]; + VmContext.R[0] -= sizeof (UINTN); + + // + // Align the stack on a natural boundary + // VmContext.R[0] &= ~(sizeof(UINTN) - 1); + // + VmContext.StackRetAddr = (UINT64) VmContext.R[0]; + VmContext.LowStackTop = (UINTN) VmContext.R[0]; + // + // VM pushes 16-bytes for return address. Simulate that here. + // + VmContext.HighStackBottom = (UINTN) &ImageHandle - 16; + + // + // Begin executing the EBC code + // + EbcExecute (&VmContext); + + // + // Return the value in R[7] unless there was an error + // + return (UINT64) VmContext.R[7]; +} + +EFI_STATUS +EbcCreateThunks ( + IN EFI_HANDLE ImageHandle, + IN VOID *EbcEntryPoint, + OUT VOID **Thunk, + IN UINT32 Flags + ) +/*++ + +Routine Description: + + Create an IA32 thunk for the given EBC entry point. + +Arguments: + + ImageHandle - Handle of image for which this thunk is being created + EbcEntryPoint - Address of the EBC code that the thunk is to call + Thunk - Returned thunk we create here + +Returns: + + Standard EFI status. + +--*/ +{ + UINT8 *Ptr; + UINT8 *ThunkBase; + UINT32 I; + UINT32 Addr; + INT32 Size; + INT32 ThunkSize; + EFI_STATUS Status; + + // + // Check alignment of pointer to EBC code + // + if ((UINT32) (UINTN) EbcEntryPoint & 0x01) { + return EFI_INVALID_PARAMETER; + } + + Size = EBC_THUNK_SIZE; + ThunkSize = Size; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + Size, + (VOID *) &Ptr + ); + if (Status != EFI_SUCCESS) { + return EFI_OUT_OF_RESOURCES; + } + // + // Print(L"Allocate TH: 0x%X\n", (UINT32)Ptr); + // + // Save the start address so we can add a pointer to it to a list later. + // + ThunkBase = Ptr; + + // + // Give them the address of our buffer we're going to fix up + // + *Thunk = (VOID *) Ptr; + + // + // Add a magic code here to help the VM recognize the thunk.. + // mov eax, 0xca112ebc => B8 BC 2E 11 CA + // + *Ptr = 0xB8; + Ptr++; + Size--; + Addr = (UINT32) 0xCA112EBC; + for (I = 0; I < sizeof (Addr); I++) { + *Ptr = (UINT8) (UINTN) Addr; + Addr >>= 8; + Ptr++; + Size--; + } + + // + // Add code bytes to load up a processor register with the EBC entry point. + // mov eax, 0xaa55aa55 => B8 55 AA 55 AA + // The first 8 bytes of the thunk entry is the address of the EBC + // entry point. + // + *Ptr = 0xB8; + Ptr++; + Size--; + Addr = (UINT32) EbcEntryPoint; + for (I = 0; I < sizeof (Addr); I++) { + *Ptr = (UINT8) (UINTN) Addr; + Addr >>= 8; + Ptr++; + Size--; + } + // + // Stick in a load of ecx with the address of appropriate VM function. + // mov ecx 12345678h => 0xB9 0x78 0x56 0x34 0x12 + // + if (Flags & FLAG_THUNK_ENTRY_POINT) { + Addr = (UINT32) (UINTN) ExecuteEbcImageEntryPoint; + } else { + Addr = (UINT32) (UINTN) EbcInterpret; + } + + // + // MOV ecx + // + *Ptr = 0xB9; + Ptr++; + Size--; + for (I = 0; I < sizeof (Addr); I++) { + *Ptr = (UINT8) Addr; + Addr >>= 8; + Ptr++; + Size--; + } + // + // Stick in jump opcode bytes for jmp ecx => 0xFF 0xE1 + // + *Ptr = 0xFF; + Ptr++; + Size--; + *Ptr = 0xE1; + Size--; + + // + // Double check that our defined size is ok (application error) + // + if (Size < 0) { + ASSERT (FALSE); + return EFI_BUFFER_TOO_SMALL; + } + // + // Add the thunk to the list for this image. Do this last since the add + // function flushes the cache for us. + // + EbcAddImageThunk (ImageHandle, (VOID *) ThunkBase, ThunkSize); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ia32/Ia32Math.asm b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/Ia32Math.asm new file mode 100644 index 0000000000..4c91a2730b --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/Ia32/Ia32Math.asm @@ -0,0 +1,622 @@ + TITLE Ia32math.asm: Generic math routines for EBC interpreter running on IA32 processor + +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Ia32math.asm +; +; Abstract: +; +; Generic math routines for EBC interpreter running on IA32 processor +; +;------------------------------------------------------------------------------ + + .686P + .XMM + .MODEL SMALL + .CODE + +LeftShiftU64 PROTO C Operand: QWORD, CountIn: QWORD +RightShiftU64 PROTO C Operand: QWORD, CountIn: QWORD +ARightShift64 PROTO C Operand: QWORD, CountIn: QWORD +MulU64x64 PROTO C Value1: QWORD, Value2: QWORD, ResultHigh: DWORD +MulS64x64 PROTO C Value1: QWORD, Value2: QWORD, ResultHigh: DWORD +DivU64x64 PROTO C Dividend: QWORD, Divisor: QWORD, Remainder: DWORD, Error: DWORD +DivS64x64 PROTO C Dividend: QWORD, Divisor: QWORD, Remainder: DWORD, Error: DWORD + + +LeftShiftU64 PROC C Operand: QWORD, CountIn: QWORD + +;------------------------------------------------------------------------------ +; UINT64 +; LeftShiftU64 ( +; IN UINT64 Operand, +; IN UINT64 CountIn +; ) +; +; Routine Description: +; +; Left-shift a 64-bit value. +; +; Arguments: +; +; Operand - the value to shift +; Count - shift count +; +; Returns: +; +; Operand << Count +;------------------------------------------------------------------------------ + + push ecx + ; + ; if (CountIn > 63) return 0; + ; + cmp dword ptr CountIn[4], 0 + jne _LeftShiftU64_Overflow + mov ecx, dword ptr CountIn[0] + cmp ecx, 63 + jbe _LeftShiftU64_Calc + +_LeftShiftU64_Overflow: + xor eax, eax + xor edx, edx + jmp _LeftShiftU64_Done + +_LeftShiftU64_Calc: + mov eax, dword ptr Operand[0] + mov edx, dword ptr Operand[4] + + shld edx, eax, cl + shl eax, cl + cmp ecx, 32 + jc short _LeftShiftU64_Done + + mov edx, eax + xor eax, eax + +_LeftShiftU64_Done: + pop ecx + ret + +LeftShiftU64 ENDP + + +RightShiftU64 PROC C Operand: QWORD, CountIn: QWORD + +;------------------------------------------------------------------------------ +; UINT64 +; RightShiftU64 ( +; IN UINT64 Operand, +; IN UINT64 CountIn +; ) +; +; Routine Description: +; +; Right-shift an unsigned 64-bit value. +; +; Arguments: +; +; Operand - the value to shift +; Count - shift count +; +; Returns: +; +; Operand >> Count +;------------------------------------------------------------------------------ + + push ecx + ; + ; if (CountIn > 63) return 0; + ; + cmp dword ptr CountIn[4], 0 + jne _RightShiftU64_Overflow + mov ecx, dword ptr CountIn[0] + cmp ecx, 63 + jbe _RightShiftU64_Calc + +_RightShiftU64_Overflow: + xor eax, eax + xor edx, edx + jmp _RightShiftU64_Done + +_RightShiftU64_Calc: + mov eax, dword ptr Operand[0] + mov edx, dword ptr Operand[4] + + shrd edx, eax, cl + shr eax, cl + cmp ecx, 32 + jc short _RightShiftU64_Done + + mov eax, edx + xor edx, edx + +_RightShiftU64_Done: + pop ecx + ret + +RightShiftU64 ENDP + + +ARightShift64 PROC C Operand: QWORD, CountIn: QWORD + +;------------------------------------------------------------------------------ +; INT64 +; ARightShift64 ( +; IN INT64 Operand, +; IN UINT64 CountIn +; ) +; +; Routine Description: +; +; Arithmatic shift a 64 bit signed value. +; +; Arguments: +; +; Operand - the value to shift +; Count - shift count +; +; Returns: +; +; Operand >> Count +;------------------------------------------------------------------------------ + + push ecx + ; + ; If they exceeded the max shift count, then return either 0 or all F's + ; depending on the sign bit. + ; + cmp dword ptr CountIn[4], 0 + jne _ARightShiftU64_Overflow + mov ecx, dword ptr CountIn[0] + cmp ecx, 63 + jbe _ARightShiftU64_Calc + +_ARightShiftU64_Overflow: + ; + ; Check the sign bit of Operand + ; + bt dword ptr Operand[4], 31 + jnc _ARightShiftU64_Return_Zero + ; + ; return -1 + ; + or eax, 0FFFFFFFFh + or edx, 0FFFFFFFFh + jmp _ARightShiftU64_Done + +_ARightShiftU64_Return_Zero: + xor eax, eax + xor edx, edx + jmp _ARightShiftU64_Done + +_ARightShiftU64_Calc: + mov eax, dword ptr Operand[0] + mov edx, dword ptr Operand[4] + + shrd eax, edx, cl + sar edx, cl + cmp ecx, 32 + jc short _ARightShiftU64_Done + + ; + ; if ecx >= 32, then eax = edx, and edx = sign bit + ; + mov eax, edx + sar edx, 31 + +_ARightShiftU64_Done: + pop ecx + ret + +ARightShift64 ENDP + + +MulU64x64 PROC C Value1: QWORD, Value2: QWORD, ResultHigh: DWORD + +;------------------------------------------------------------------------------ +; UINT64 +; MulU64x64 ( +; UINT64 Value1, +; UINT64 Value2, +; UINT64 *ResultHigh +; ) +; +; Routine Description: +; +; Multiply two unsigned 64-bit values. +; +; Arguments: +; +; Value1 - first value to multiply +; Value2 - value to multiply by Value1 +; ResultHigh - result to flag overflows +; +; Returns: +; +; Value1 * Value2 +; The 128-bit result is the concatenation of *ResultHigh and the return value +;------------------------------------------------------------------------------ + + push ebx + push ecx + mov ebx, ResultHigh ; ebx points to the high 4 words of result + ; + ; The result consists of four double-words. + ; Here we assume their names from low to high: dw0, dw1, dw2, dw3 + ; + mov eax, dword ptr Value1[0] + mul dword ptr Value2[0] + push eax ; eax contains final result of dw0, push it + mov ecx, edx ; ecx contains partial result of dw1 + + mov eax, dword ptr Value1[4] + mul dword ptr Value2[0] + add ecx, eax ; add eax to partial result of dw1 + adc edx, 0 + mov dword ptr [ebx], edx ; lower double-word of ResultHigh contains partial result of dw2 + + mov eax, dword ptr Value1[0] + mul dword ptr Value2[4] + add ecx, eax ; add eax to partial result of dw1 + push ecx ; ecx contains final result of dw1, push it + adc edx, 0 + mov ecx, edx ; ecx contains partial result of dw2, together with ResultHigh + + mov eax, dword ptr Value1[4] + mul dword ptr Value2[4] + add ecx, eax ; add eax to partial result of dw2 + adc edx, 0 + add dword ptr [ebx], ecx ; lower double-word of ResultHigh contains final result of dw2 + adc edx, 0 + mov dword ptr [ebx + 4], edx ; high double-word of ResultHigh contains final result of dw3 + + pop edx ; edx contains the final result of dw1 + pop eax ; edx contains the final result of dw0 + pop ecx + pop ebx + ret + +MulU64x64 ENDP + + +MulS64x64 PROC C Value1: QWORD, Value2: QWORD, ResultHigh: DWORD + +;------------------------------------------------------------------------------ +; INT64 +; MulS64x64 ( +; INT64 Value1, +; INT64 Value2, +; INT64 *ResultHigh +; ) +; +; Routine Description: +; +; Multiply two signed 64-bit values. +; +; Arguments: +; +; Value1 - first value to multiply +; Value2 - value to multiply by Value1 +; ResultHigh - result to flag overflows +; +; Returns: +; +; Value1 * Value2 +; The 128-bit result is the concatenation of *ResultHigh and the return value +;------------------------------------------------------------------------------ + + push ebx + push ecx + mov ebx, ResultHigh ; ebx points to the high 4 words of result + xor ecx, ecx ; the lowest bit of ecx flags the sign + + mov edx, dword ptr Value1[4] + bt edx, 31 + jnc short _MulS64x64_A_Positive + ; + ; a is negative + ; + mov eax, dword ptr Value1[0] + not edx + not eax + add eax, 1 + adc edx, 0 + mov dword ptr Value1[0], eax + mov dword ptr Value1[4], edx + btc ecx, 0 + +_MulS64x64_A_Positive: + mov edx, dword ptr Value2[4] + bt edx, 31 + jnc short _MulS64x64_B_Positive + ; + ; b is negative + ; + mov eax, dword ptr Value2[0] + not edx + not eax + add eax, 1 + adc edx, 0 + mov dword ptr Value2[0], eax + mov dword ptr Value2[4], edx + btc ecx, 0 + +_MulS64x64_B_Positive: + invoke MulU64x64, Value1, Value2, ResultHigh + bt ecx, 0 + jnc short _MulS64x64_Done + ; + ;negate the result + ; + not eax + not edx + not dword ptr [ebx] + not dword ptr [ebx + 4] + add eax, 1 + adc edx, 0 + adc dword ptr [ebx], 0 + adc dword ptr [ebx + 4], 0 + +_MulS64x64_Done: + pop ecx + pop ebx + ret + +MulS64x64 ENDP + + +DivU64x64 PROC C Dividend: QWORD, Divisor: QWORD, Remainder: DWORD, Error: DWORD, + +;------------------------------------------------------------------------------ +; UINT64 +; DivU64x64 ( +; IN UINT64 Dividend, +; IN UINT64 Divisor, +; OUT UINT64 *Remainder OPTIONAL, +; OUT UINT32 *Error +; ) +; +; Routine Description: +; +; This routine allows a 64 bit value to be divided with a 64 bit value returns +; 64bit result and the Remainder +; +; Arguments: +; +; Dividend - dividend +; Divisor - divisor +; ResultHigh - result to flag overflows +; Error - flag for error +; +; Returns: +; +; Dividend / Divisor +; Remainder = Dividend mod Divisor +;------------------------------------------------------------------------------ + + push ecx + + mov eax, Error + mov dword ptr [eax], 0 + + cmp dword ptr Divisor[0], 0 + jne _DivU64x64_Valid + cmp dword ptr Divisor[4], 0 + jne _DivU64x64_Valid + ; + ; the divisor is zero + ; + mov dword ptr [eax], 1 + cmp Remainder, 0 + je _DivU64x64_Invalid_Return + ; + ; fill the remainder if the pointer is not null + ; + mov eax, Remainder + mov dword ptr [eax], 0 + mov dword ptr [eax + 4], 80000000h + +_DivU64x64_Invalid_Return: + xor eax, eax + mov edx, 80000000h + jmp _DivU64x64_Done + +_DivU64x64_Valid: + ; + ; let edx and eax contain the intermediate result of remainder + ; + xor edx, edx + xor eax, eax + mov ecx, 64 + +_DivU64x64_Wend: + ; + ; shift dividend left one + ; + shl dword ptr Dividend[0], 1 + rcl dword ptr Dividend[4], 1 + ; + ; rotate intermediate result of remainder left one + ; + rcl eax, 1 + rcl edx, 1 + + cmp edx, dword ptr Divisor[4] + ja _DivU64x64_Sub_Divisor + jb _DivU64x64_Cont + cmp eax, dword ptr Divisor[0] + jb _DivU64x64_Cont + +_DivU64x64_Sub_Divisor: + ; + ; If intermediate result of remainder is larger than + ; or equal to divisor, then set the lowest bit of dividend, + ; and subtract divisor from intermediate remainder + ; + bts dword ptr Dividend[0], 0 + sub eax, dword ptr Divisor[0] + sbb edx, dword ptr Divisor[4] + +_DivU64x64_Cont: + loop _DivU64x64_Wend + + cmp Remainder, 0 + je _DivU64x64_Assign + mov ecx, Remainder + mov dword ptr [ecx], eax + mov dword ptr [ecx + 4], edx + +_DivU64x64_Assign: + mov eax, dword ptr Dividend[0] + mov edx, dword ptr Dividend[4] + +_DivU64x64_Done: + pop ecx + ret + +DivU64x64 ENDP + +DivS64x64 PROC C Dividend: QWORD, Divisor: QWORD, Remainder: DWORD, Error: DWORD, + +;------------------------------------------------------------------------------ +; INT64 +; DivU64x64 ( +; IN INT64 Dividend, +; IN INT64 Divisor, +; OUT UINT64 *Remainder OPTIONAL, +; OUT UINT32 *Error +; ) +; +; Routine Description: +; +; This routine allows a 64 bit signed value to be divided with a 64 bit +; signed value returns 64bit result and the Remainder. +; +; Arguments: +; +; Dividend - dividend +; Divisor - divisor +; ResultHigh - result to flag overflows +; Error - flag for error +; +; Returns: +; +; Dividend / Divisor +; Remainder = Dividend mod Divisor +;------------------------------------------------------------------------------ + + push ecx + + mov eax, Error + mov dword ptr [eax], 0 + + cmp dword ptr Divisor[0], 0 + jne _DivS64x64_Valid + cmp dword ptr Divisor[4], 0 + jne _DivS64x64_Valid + ; + ; the divisor is zero + ; + mov dword ptr [eax], 1 + cmp Remainder, 0 + je _DivS64x64_Invalid_Return + ; + ; fill the remainder if the pointer is not null + ; + mov eax, Remainder + mov dword ptr [eax], 0 + mov dword ptr [eax + 4], 80000000h + +_DivS64x64_Invalid_Return: + xor eax, eax + mov edx, 80000000h + jmp _DivS64x64_Done + +_DivS64x64_Valid: + ; + ; The lowest bit of ecx flags the sign of quotient, + ; The seconde lowest bit flags the sign of remainder + ; + xor ecx, ecx + + mov edx, dword ptr Dividend[4] + bt edx, 31 + jnc short _DivS64x64_Dividend_Positive + ; + ; dividend is negative + ; + mov eax, dword ptr Dividend[0] + not edx + not eax + add eax, 1 + adc edx, 0 + mov dword ptr Dividend[0], eax + mov dword ptr Dividend[4], edx + ; + ; set both the flags for signs of quotient and remainder + ; + btc ecx, 0 + btc ecx, 1 + +_DivS64x64_Dividend_Positive: + mov edx, dword ptr Divisor[4] + bt edx, 31 + jnc short _DivS64x64_Divisor_Positive + ; + ; divisor is negative + ; + mov eax, dword ptr Divisor[0] + not edx + not eax + add eax, 1 + adc edx, 0 + mov dword ptr Divisor[0], eax + mov dword ptr Divisor[4], edx + ; + ; just complement the flag for sign of quotient + ; + btc ecx, 0 + +_DivS64x64_Divisor_Positive: + invoke DivU64x64, Dividend, Divisor, Remainder, Error + bt ecx, 0 + jnc short _DivS64x64_Remainder + ; + ; negate the quotient + ; + not eax + not edx + add eax, 1 + adc edx, 0 + +_DivS64x64_Remainder: + bt ecx, 1 + jnc short _DivS64x64_Done + ; + ; negate the remainder + ; + mov ecx, remainder + not dword ptr [ecx] + not dword ptr [ecx + 4] + add dword ptr [ecx], 1 + adc dword ptr [ecx + 4], 0 + +_DivS64x64_Done: + pop ecx + ret + +DivS64x64 ENDP + +END \ No newline at end of file diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcLowLevel.s b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcLowLevel.s new file mode 100644 index 0000000000..fe2ca3f572 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcLowLevel.s @@ -0,0 +1,167 @@ +//++ +// Copyright (c) 2006, 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. +// +// Module Name: +// +// EbcLowLevel.s +// +// Abstract: +// +// Contains low level routines for the Virtual Machine implementation +// on an Itanium-based platform. +// +// +//-- + +.file "EbcLowLevel.s" + +#define PROCEDURE_ENTRY(name) .##text; \ + .##type name, @function; \ + .##proc name; \ +name:: + +#define PROCEDURE_EXIT(name) .##endp name + +// Note: use of NESTED_SETUP requires number of locals (l) >= 3 + +#define NESTED_SETUP(i,l,o,r) \ + alloc loc1=ar##.##pfs,i,l,o,r ;\ + mov loc0=b0 + +#define NESTED_RETURN \ + mov b0=loc0 ;\ + mov ar##.##pfs=loc1 ;;\ + br##.##ret##.##dpnt b0;; + + +//----------------------------------------------------------------------------- +//++ +// EbcAsmLLCALLEX +// +// Implements the low level EBC CALLEX instruction. Sets up the +// stack pointer, does the spill of function arguments, and +// calls the native function. On return it restores the original +// stack pointer and returns to the caller. +// +// Arguments : +// +// On Entry : +// in0 = Address of native code to call +// in1 = New stack pointer +// +// Return Value: +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- +;// void EbcAsmLLCALLEX (UINTN FunctionAddr, UINTN EbcStackPointer) +PROCEDURE_ENTRY(EbcAsmLLCALLEX) + NESTED_SETUP (2,6,8,0) + + // NESTED_SETUP uses loc0 and loc1 for context save + + // + // Save a copy of the EBC VM stack pointer + // + mov r8 = in1;; + + // + // Copy stack arguments from EBC stack into registers. + // Assume worst case and copy 8. + // + ld8 out0 = [r8], 8;; + ld8 out1 = [r8], 8;; + ld8 out2 = [r8], 8;; + ld8 out3 = [r8], 8;; + ld8 out4 = [r8], 8;; + ld8 out5 = [r8], 8;; + ld8 out6 = [r8], 8;; + ld8 out7 = [r8], 8;; + + // + // Save the original stack pointer + // + mov loc2 = r12; + + // + // Save the gp + // + or loc3 = r1, r0 + + // + // Set the new aligned stack pointer. Reserve space for the required + // 16-bytes of scratch area as well. + // + add r12 = 48, in1 + + // + // Now call the function. Load up the function address from the descriptor + // pointed to by in0. Then get the gp from the descriptor at the following + // address in the descriptor. + // + ld8 r31 = [in0], 8;; + ld8 r30 = [in0];; + mov b1 = r31 + mov r1 = r30 + (p0) br.call.dptk.many b0 = b1;; + + // + // Restore the original stack pointer and gp + // + mov r12 = loc2 + or r1 = loc3, r0 + + // + // Now return + // + NESTED_RETURN + +PROCEDURE_EXIT(EbcAsmLLCALLEX) + +// +// UINTN EbcLLGetEbcEntryPoint(VOID) +// +// Description: +// Simply return, so that the caller retrieves the return register +// contents (R8). That's where the thunk-to-ebc code stuffed the +// EBC entry point. +// +PROCEDURE_ENTRY(EbcLLGetEbcEntryPoint) + br.ret.sptk b0 ;; +PROCEDURE_EXIT(EbcLLGetEbcEntryPoint) + +// +// INT64 EbcLLGetReturnValue(VOID) +// +// Description: +// This function is called to get the value returned by native code +// to EBC. It simply returns because the return value should still +// be in the register, so the caller just gets the unmodified value. +// +PROCEDURE_ENTRY(EbcLLGetReturnValue) + br.ret.sptk b0 ;; +PROCEDURE_EXIT(EbcLLGetReturnValue) + +// +// UINTN EbcLLGetStackPointer(VOID) +// +PROCEDURE_ENTRY(EbcLLGetStackPointer) + mov r8 = r12 ;; + br.ret.sptk b0 ;; + br.sptk.few b6 +PROCEDURE_EXIT(EbcLLGetStackPointer) + + + + + + + diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.c b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.c new file mode 100644 index 0000000000..50402aadd5 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/EbcSupport.c @@ -0,0 +1,906 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EbcSupport.c + +Abstract: + + This module contains EBC support routines that are customized based on + the target processor. + +--*/ + +#include "EbcInt.h" +#include "EbcExecute.h" + +#define VM_STACK_SIZE (1024 * 32) + +#define EBC_THUNK_SIZE 128 + +// +// For code execution, thunks must be aligned on 16-byte boundary +// +#define EBC_THUNK_ALIGNMENT 16 + +// +// Per the IA-64 Software Conventions and Runtime Architecture Guide, +// section 3.3.4, IPF stack must always be 16-byte aligned. +// +#define IPF_STACK_ALIGNMENT 16 + +// +// Opcodes for IPF instructions. We'll need to hand-create thunk code (stuffing +// bits) to insert a jump to the interpreter. +// +#define OPCODE_NOP (UINT64) 0x00008000000 +#define OPCODE_BR_COND_SPTK_FEW (UINT64) 0x00100000000 +#define OPCODE_MOV_BX_RX (UINT64) 0x00E00100000 + +// +// Opcode for MOVL instruction +// +#define MOVL_OPCODE 0x06 + +VOID +EbcAsmLLCALLEX ( + IN UINTN CallAddr, + IN UINTN EbcSp + ); + +STATIC +EFI_STATUS +WriteBundle ( + IN VOID *MemPtr, + IN UINT8 Template, + IN UINT64 Slot0, + IN UINT64 Slot1, + IN UINT64 Slot2 + ); + +STATIC +VOID +PushU64 ( + VM_CONTEXT *VmPtr, + UINT64 Arg + ) +{ + // + // Advance the VM stack down, and then copy the argument to the stack. + // Hope it's aligned. + // + VmPtr->R[0] -= sizeof (UINT64); + *(UINT64 *) VmPtr->R[0] = Arg; +} + +UINT64 +EbcInterpret ( + UINT64 Arg1, + ... + ) +{ + // + // Create a new VM context on the stack + // + VM_CONTEXT VmContext; + UINTN Addr; + VA_LIST List; + UINT64 Arg2; + UINT64 Arg3; + UINT64 Arg4; + UINT64 Arg5; + UINT64 Arg6; + UINT64 Arg7; + UINT64 Arg8; + UINTN Arg9Addr; + // + // Get the EBC entry point from the processor register. Make sure you don't + // call any functions before this or you could mess up the register the + // entry point is passed in. + // + Addr = EbcLLGetEbcEntryPoint (); + // + // Need the args off the stack. + // + VA_START (List, Arg1); + Arg2 = VA_ARG (List, UINT64); + Arg3 = VA_ARG (List, UINT64); + Arg4 = VA_ARG (List, UINT64); + Arg5 = VA_ARG (List, UINT64); + Arg6 = VA_ARG (List, UINT64); + Arg7 = VA_ARG (List, UINT64); + Arg8 = VA_ARG (List, UINT64); + Arg9Addr = (UINTN) List; + // + // Now clear out our context + // + ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT)); + // + // Set the VM instruction pointer to the correct location in memory. + // + VmContext.Ip = (VMIP) Addr; + // + // Initialize the stack pointer for the EBC. Get the current system stack + // pointer and adjust it down by the max needed for the interpreter. + // + Addr = (UINTN) Arg9Addr; + // + // NOTE: Eventually we should have the interpreter allocate memory + // for stack space which it will use during its execution. This + // would likely improve performance because the interpreter would + // no longer be required to test each memory access and adjust + // those reading from the stack gap. + // + // For IPF, the stack looks like (assuming 10 args passed) + // arg10 + // arg9 (Bottom of high stack) + // [ stack gap for interpreter execution ] + // [ magic value for detection of stack corruption ] + // arg8 (Top of low stack) + // arg7.... + // arg1 + // [ 64-bit return address ] + // [ ebc stack ] + // If the EBC accesses memory in the stack gap, then we assume that it's + // actually trying to access args9 and greater. Therefore we need to + // adjust memory accesses in this region to point above the stack gap. + // + VmContext.HighStackBottom = (UINTN) Addr; + // + // Now adjust the EBC stack pointer down to leave a gap for interpreter + // execution. Then stuff a magic value there. + // + VmContext.R[0] = (UINT64) Addr; + VmContext.R[0] -= VM_STACK_SIZE; + PushU64 (&VmContext, (UINT64) VM_STACK_KEY_VALUE); + VmContext.StackMagicPtr = (UINTN *) VmContext.R[0]; + VmContext.LowStackTop = (UINTN) VmContext.R[0]; + // + // Push the EBC arguments on the stack. Does not matter that they may not + // all be valid. + // + PushU64 (&VmContext, Arg8); + PushU64 (&VmContext, Arg7); + PushU64 (&VmContext, Arg6); + PushU64 (&VmContext, Arg5); + PushU64 (&VmContext, Arg4); + PushU64 (&VmContext, Arg3); + PushU64 (&VmContext, Arg2); + PushU64 (&VmContext, Arg1); + // + // Push a bogus return address on the EBC stack because the + // interpreter expects one there. For stack alignment purposes on IPF, + // EBC return addresses are always 16 bytes. Push a bogus value as well. + // + PushU64 (&VmContext, 0); + PushU64 (&VmContext, 0xDEADBEEFDEADBEEF); + VmContext.StackRetAddr = (UINT64) VmContext.R[0]; + // + // Begin executing the EBC code + // + EbcExecute (&VmContext); + // + // Return the value in R[7] unless there was an error + // + return (UINT64) VmContext.R[7]; +} + +UINT64 +ExecuteEbcImageEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + IPF implementation. + + Begin executing an EBC image. The address of the entry point is passed + in via a processor register, so we'll need to make a call to get the + value. + +Arguments: + + ImageHandle - image handle for the EBC application we're executing + SystemTable - standard system table passed into an driver's entry point + +Returns: + + The value returned by the EBC application we're going to run. + +--*/ +{ + // + // Create a new VM context on the stack + // + VM_CONTEXT VmContext; + UINTN Addr; + + // + // Get the EBC entry point from the processor register. Make sure you don't + // call any functions before this or you could mess up the register the + // entry point is passed in. + // + Addr = EbcLLGetEbcEntryPoint (); + + // + // Now clear out our context + // + ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT)); + + // + // Save the image handle so we can track the thunks created for this image + // + VmContext.ImageHandle = ImageHandle; + VmContext.SystemTable = SystemTable; + + // + // Set the VM instruction pointer to the correct location in memory. + // + VmContext.Ip = (VMIP) Addr; + + // + // Get the stack pointer. This is the bottom of the upper stack. + // + Addr = EbcLLGetStackPointer (); + VmContext.HighStackBottom = (UINTN) Addr; + VmContext.R[0] = (INT64) Addr; + + // + // Allocate stack space for the interpreter. Then put a magic value + // at the bottom so we can detect stack corruption. + // + VmContext.R[0] -= VM_STACK_SIZE; + PushU64 (&VmContext, (UINT64) VM_STACK_KEY_VALUE); + VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0]; + + // + // When we thunk to external native code, we copy the last 8 qwords from + // the EBC stack into the processor registers, and adjust the stack pointer + // up. If the caller is not passing 8 parameters, then we've moved the + // stack pointer up into the stack gap. If this happens, then the caller + // can mess up the stack gap contents (in particular our magic value). + // Therefore, leave another gap below the magic value. Pick 10 qwords down, + // just as a starting point. + // + VmContext.R[0] -= 10 * sizeof (UINT64); + + // + // Align the stack pointer such that after pushing the system table, + // image handle, and return address on the stack, it's aligned on a 16-byte + // boundary as required for IPF. + // + VmContext.R[0] &= (INT64)~0x0f; + VmContext.LowStackTop = (UINTN) VmContext.R[0]; + // + // Simply copy the image handle and system table onto the EBC stack. + // Greatly simplifies things by not having to spill the args + // + PushU64 (&VmContext, (UINT64) SystemTable); + PushU64 (&VmContext, (UINT64) ImageHandle); + + // + // Interpreter assumes 64-bit return address is pushed on the stack. + // IPF does not do this so pad the stack accordingly. Also, a + // "return address" is 16 bytes as required for IPF stack alignments. + // + PushU64 (&VmContext, (UINT64) 0); + PushU64 (&VmContext, (UINT64) 0x1234567887654321); + VmContext.StackRetAddr = (UINT64) VmContext.R[0]; + + // + // Begin executing the EBC code + // + EbcExecute (&VmContext); + + // + // Return the value in R[7] unless there was an error + // + return (UINT64) VmContext.R[7]; +} + +EFI_STATUS +EbcCreateThunks ( + IN EFI_HANDLE ImageHandle, + IN VOID *EbcEntryPoint, + OUT VOID **Thunk, + IN UINT32 Flags + ) +/*++ + +Routine Description: + + Create thunks for an EBC image entry point, or an EBC protocol service. + +Arguments: + + ImageHandle - Image handle for the EBC image. If not null, then we're + creating a thunk for an image entry point. + EbcEntryPoint - Address of the EBC code that the thunk is to call + Thunk - Returned thunk we create here + Flags - Flags indicating options for creating the thunk + +Returns: + + Standard EFI status. + +--*/ +{ + UINT8 *Ptr; + UINT8 *ThunkBase; + UINT64 Addr; + UINT64 Code[3]; // Code in a bundle + UINT64 RegNum; // register number for MOVL + UINT64 I; // bits of MOVL immediate data + UINT64 Ic; // bits of MOVL immediate data + UINT64 Imm5c; // bits of MOVL immediate data + UINT64 Imm9d; // bits of MOVL immediate data + UINT64 Imm7b; // bits of MOVL immediate data + UINT64 Br; // branch register for loading and jumping + UINT64 *Data64Ptr; + UINT32 ThunkSize; + UINT32 Size; + EFI_STATUS Status; + + // + // Check alignment of pointer to EBC code, which must always be aligned + // on a 2-byte boundary. + // + if ((UINT32) (UINTN) EbcEntryPoint & 0x01) { + return EFI_INVALID_PARAMETER; + } + // + // Allocate memory for the thunk. Make the (most likely incorrect) assumption + // that the returned buffer is not aligned, so round up to the next + // alignment size. + // + Size = EBC_THUNK_SIZE + EBC_THUNK_ALIGNMENT - 1; + ThunkSize = Size; + Status = gBS->AllocatePool ( + EfiBootServicesData, + Size, + (VOID *) &Ptr + ); + if (Status != EFI_SUCCESS) { + return EFI_OUT_OF_RESOURCES; + } + // + // Save the start address of the buffer. + // + ThunkBase = Ptr; + + // + // Make sure it's aligned for code execution. If not, then + // round up. + // + if ((UINT32) (UINTN) Ptr & (EBC_THUNK_ALIGNMENT - 1)) { + Ptr = (UINT8 *) (((UINTN) Ptr + (EBC_THUNK_ALIGNMENT - 1)) &~ (UINT64) (EBC_THUNK_ALIGNMENT - 1)); + } + // + // Return the pointer to the thunk to the caller to user as the + // image entry point. + // + *Thunk = (VOID *) Ptr; + + // + // Clear out the thunk entry + // ZeroMem(Ptr, Size); + // + // For IPF, when you do a call via a function pointer, the function pointer + // actually points to a function descriptor which consists of a 64-bit + // address of the function, followed by a 64-bit gp for the function being + // called. See the the Software Conventions and Runtime Architecture Guide + // for details. + // So first off in our thunk, create a descriptor for our actual thunk code. + // This means we need to create a pointer to the thunk code (which follows + // the descriptor we're going to create), followed by the gp of the Vm + // interpret function we're going to eventually execute. + // + Data64Ptr = (UINT64 *) Ptr; + + // + // Write the function's entry point (which is our thunk code that follows + // this descriptor we're creating). + // + *Data64Ptr = (UINT64) (Data64Ptr + 2); + // + // Get the gp from the descriptor for EbcInterpret and stuff it in our thunk + // descriptor. + // + *(Data64Ptr + 1) = *(UINT64 *) ((UINT64 *) (UINTN) EbcInterpret + 1); + // + // Advance our thunk data pointer past the descriptor. Since the + // descriptor consists of 16 bytes, the pointer is still aligned for + // IPF code execution (on 16-byte boundary). + // + Ptr += sizeof (UINT64) * 2; + + // + // *************************** MAGIC BUNDLE ******************************** + // + // Write magic code bundle for: movl r8 = 0xca112ebcca112ebc to help the VM + // to recognize it is a thunk. + // + Addr = (UINT64) 0xCA112EBCCA112EBC; + + // + // Now generate the code bytes. First is nop.m 0x0 + // + Code[0] = OPCODE_NOP; + + // + // Next is simply Addr[62:22] (41 bits) of the address + // + Code[1] = RightShiftU64 (Addr, 22) & 0x1ffffffffff; + + // + // Extract bits from the address for insertion into the instruction + // i = Addr[63:63] + // + I = RightShiftU64 (Addr, 63) & 0x01; + // + // ic = Addr[21:21] + // + Ic = RightShiftU64 (Addr, 21) & 0x01; + // + // imm5c = Addr[20:16] for 5 bits + // + Imm5c = RightShiftU64 (Addr, 16) & 0x1F; + // + // imm9d = Addr[15:7] for 9 bits + // + Imm9d = RightShiftU64 (Addr, 7) & 0x1FF; + // + // imm7b = Addr[6:0] for 7 bits + // + Imm7b = Addr & 0x7F; + + // + // The EBC entry point will be put into r8, so r8 can be used here + // temporary. R8 is general register and is auto-serialized. + // + RegNum = 8; + + // + // Next is jumbled data, including opcode and rest of address + // + Code[2] = LeftShiftU64 (Imm7b, 13) + | LeftShiftU64 (0x00, 20) // vc + | LeftShiftU64 (Ic, 21) + | LeftShiftU64 (Imm5c, 22) + | LeftShiftU64 (Imm9d, 27) + | LeftShiftU64 (I, 36) + | LeftShiftU64 ((UINT64)MOVL_OPCODE, 37) + | LeftShiftU64 ((RegNum & 0x7F), 6); + + WriteBundle ((VOID *) Ptr, 0x05, Code[0], Code[1], Code[2]); + + // + // *************************** FIRST BUNDLE ******************************** + // + // Write code bundle for: movl r8 = EBC_ENTRY_POINT so we pass + // the ebc entry point in to the interpreter function via a processor + // register. + // Note -- we could easily change this to pass in a pointer to a structure + // that contained, among other things, the EBC image's entry point. But + // for now pass it directly. + // + Ptr += 16; + Addr = (UINT64) EbcEntryPoint; + + // + // Now generate the code bytes. First is nop.m 0x0 + // + Code[0] = OPCODE_NOP; + + // + // Next is simply Addr[62:22] (41 bits) of the address + // + Code[1] = RightShiftU64 (Addr, 22) & 0x1ffffffffff; + + // + // Extract bits from the address for insertion into the instruction + // i = Addr[63:63] + // + I = RightShiftU64 (Addr, 63) & 0x01; + // + // ic = Addr[21:21] + // + Ic = RightShiftU64 (Addr, 21) & 0x01; + // + // imm5c = Addr[20:16] for 5 bits + // + Imm5c = RightShiftU64 (Addr, 16) & 0x1F; + // + // imm9d = Addr[15:7] for 9 bits + // + Imm9d = RightShiftU64 (Addr, 7) & 0x1FF; + // + // imm7b = Addr[6:0] for 7 bits + // + Imm7b = Addr & 0x7F; + + // + // Put the EBC entry point in r8, which is the location of the return value + // for functions. + // + RegNum = 8; + + // + // Next is jumbled data, including opcode and rest of address + // + Code[2] = LeftShiftU64 (Imm7b, 13) + | LeftShiftU64 (0x00, 20) // vc + | LeftShiftU64 (Ic, 21) + | LeftShiftU64 (Imm5c, 22) + | LeftShiftU64 (Imm9d, 27) + | LeftShiftU64 (I, 36) + | LeftShiftU64 ((UINT64)MOVL_OPCODE, 37) + | LeftShiftU64 ((RegNum & 0x7F), 6); + + WriteBundle ((VOID *) Ptr, 0x05, Code[0], Code[1], Code[2]); + + // + // *************************** NEXT BUNDLE ********************************* + // + // Write code bundle for: + // movl rx = offset_of(EbcInterpret|ExecuteEbcImageEntryPoint) + // + // Advance pointer to next bundle, then compute the offset from this bundle + // to the address of the entry point of the interpreter. + // + Ptr += 16; + if (Flags & FLAG_THUNK_ENTRY_POINT) { + Addr = (UINT64) ExecuteEbcImageEntryPoint; + } else { + Addr = (UINT64) EbcInterpret; + } + // + // Indirection on Itanium-based systems + // + Addr = *(UINT64 *) Addr; + + // + // Now write the code to load the offset into a register + // + Code[0] = OPCODE_NOP; + + // + // Next is simply Addr[62:22] (41 bits) of the address + // + Code[1] = RightShiftU64 (Addr, 22) & 0x1ffffffffff; + + // + // Extract bits from the address for insertion into the instruction + // i = Addr[63:63] + // + I = RightShiftU64 (Addr, 63) & 0x01; + // + // ic = Addr[21:21] + // + Ic = RightShiftU64 (Addr, 21) & 0x01; + // + // imm5c = Addr[20:16] for 5 bits + // + Imm5c = RightShiftU64 (Addr, 16) & 0x1F; + // + // imm9d = Addr[15:7] for 9 bits + // + Imm9d = RightShiftU64 (Addr, 7) & 0x1FF; + // + // imm7b = Addr[6:0] for 7 bits + // + Imm7b = Addr & 0x7F; + + // + // Put it in r31, a scratch register + // + RegNum = 31; + + // + // Next is jumbled data, including opcode and rest of address + // + Code[2] = LeftShiftU64(Imm7b, 13) + | LeftShiftU64 (0x00, 20) // vc + | LeftShiftU64 (Ic, 21) + | LeftShiftU64 (Imm5c, 22) + | LeftShiftU64 (Imm9d, 27) + | LeftShiftU64 (I, 36) + | LeftShiftU64 ((UINT64)MOVL_OPCODE, 37) + | LeftShiftU64 ((RegNum & 0x7F), 6); + + WriteBundle ((VOID *) Ptr, 0x05, Code[0], Code[1], Code[2]); + + // + // *************************** NEXT BUNDLE ********************************* + // + // Load branch register with EbcInterpret() function offset from the bundle + // address: mov b6 = RegNum + // + // See volume 3 page 4-29 of the Arch. Software Developer's Manual. + // + // Advance pointer to next bundle + // + Ptr += 16; + Code[0] = OPCODE_NOP; + Code[1] = OPCODE_NOP; + Code[2] = OPCODE_MOV_BX_RX; + + // + // Pick a branch register to use. Then fill in the bits for the branch + // register and user register (same user register as previous bundle). + // + Br = 6; + Code[2] |= LeftShiftU64 (Br, 6); + Code[2] |= LeftShiftU64 (RegNum, 13); + WriteBundle ((VOID *) Ptr, 0x0d, Code[0], Code[1], Code[2]); + + // + // *************************** NEXT BUNDLE ********************************* + // + // Now do the branch: (p0) br.cond.sptk.few b6 + // + // Advance pointer to next bundle. + // Fill in the bits for the branch register (same reg as previous bundle) + // + Ptr += 16; + Code[0] = OPCODE_NOP; + Code[1] = OPCODE_NOP; + Code[2] = OPCODE_BR_COND_SPTK_FEW; + Code[2] |= LeftShiftU64 (Br, 13); + WriteBundle ((VOID *) Ptr, 0x1d, Code[0], Code[1], Code[2]); + + // + // Add the thunk to our list of allocated thunks so we can do some cleanup + // when the image is unloaded. Do this last since the Add function flushes + // the instruction cache for us. + // + EbcAddImageThunk (ImageHandle, (VOID *) ThunkBase, ThunkSize); + + // + // Done + // + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +WriteBundle ( + IN VOID *MemPtr, + IN UINT8 Template, + IN UINT64 Slot0, + IN UINT64 Slot1, + IN UINT64 Slot2 + ) +/*++ + +Routine Description: + + Given raw bytes of Itanium based code, format them into a bundle and + write them out. + +Arguments: + + MemPtr - pointer to memory location to write the bundles to + Template - 5-bit template + Slot0-2 - instruction slot data for the bundle + +Returns: + + EFI_INVALID_PARAMETER - Pointer is not aligned + - No more than 5 bits in template + - More than 41 bits used in code + EFI_SUCCESS - All data is written. + +--*/ +{ + UINT8 *BPtr; + UINT32 Index; + UINT64 Low64; + UINT64 High64; + + // + // Verify pointer is aligned + // + if ((UINT64) MemPtr & 0xF) { + return EFI_INVALID_PARAMETER; + } + // + // Verify no more than 5 bits in template + // + if (Template &~0x1F) { + return EFI_INVALID_PARAMETER; + } + // + // Verify max of 41 bits used in code + // + if ((Slot0 | Slot1 | Slot2) &~0x1ffffffffff) { + return EFI_INVALID_PARAMETER; + } + + Low64 = LeftShiftU64 (Slot1, 46) | LeftShiftU64 (Slot0, 5) | Template; + High64 = RightShiftU64 (Slot1, 18) | LeftShiftU64 (Slot2, 23); + + // + // Now write it all out + // + BPtr = (UINT8 *) MemPtr; + for (Index = 0; Index < 8; Index++) { + *BPtr = (UINT8) Low64; + Low64 = RightShiftU64 (Low64, 8); + BPtr++; + } + + for (Index = 0; Index < 8; Index++) { + *BPtr = (UINT8) High64; + High64 = RightShiftU64 (High64, 8); + BPtr++; + } + + return EFI_SUCCESS; +} + +VOID +EbcLLCALLEX ( + IN VM_CONTEXT *VmPtr, + IN UINTN FuncAddr, + IN UINTN NewStackPointer, + IN VOID *FramePtr, + IN UINT8 Size + ) +/*++ + +Routine Description: + + This function is called to execute an EBC CALLEX instruction. + The function check the callee's content to see whether it is common native + code or a thunk to another piece of EBC code. + If the callee is common native code, use EbcLLCAllEXASM to manipulate, + otherwise, set the VM->IP to target EBC code directly to avoid another VM + be startup which cost time and stack space. + +Arguments: + + VmPtr - Pointer to a VM context. + FuncAddr - Callee's address + NewStackPointer - New stack pointer after the call + FramePtr - New frame pointer after the call + Size - The size of call instruction + +Returns: + + None. + +--*/ +{ + UINTN IsThunk; + UINTN TargetEbcAddr; + UINTN CodeOne18; + UINTN CodeOne23; + UINTN CodeTwoI; + UINTN CodeTwoIc; + UINTN CodeTwo7b; + UINTN CodeTwo5c; + UINTN CodeTwo9d; + UINTN CalleeAddr; + + IsThunk = 1; + TargetEbcAddr = 0; + + // + // FuncAddr points to the descriptor of the target instructions. + // + CalleeAddr = *((UINT64 *)FuncAddr); + + // + // Processor specific code to check whether the callee is a thunk to EBC. + // + if (*((UINT64 *)CalleeAddr) != 0xBCCA000100000005) { + IsThunk = 0; + goto Action; + } + if (*((UINT64 *)CalleeAddr + 1) != 0x697623C1004A112E) { + IsThunk = 0; + goto Action; + } + + CodeOne18 = RightShiftU64 (*((UINT64 *)CalleeAddr + 2), 46) & 0x3FFFF; + CodeOne23 = (*((UINT64 *)CalleeAddr + 3)) & 0x7FFFFF; + CodeTwoI = RightShiftU64 (*((UINT64 *)CalleeAddr + 3), 59) & 0x1; + CodeTwoIc = RightShiftU64 (*((UINT64 *)CalleeAddr + 3), 44) & 0x1; + CodeTwo7b = RightShiftU64 (*((UINT64 *)CalleeAddr + 3), 36) & 0x7F; + CodeTwo5c = RightShiftU64 (*((UINT64 *)CalleeAddr + 3), 45) & 0x1F; + CodeTwo9d = RightShiftU64 (*((UINT64 *)CalleeAddr + 3), 50) & 0x1FF; + + TargetEbcAddr = CodeTwo7b + | LeftShiftU64 (CodeTwo9d, 7) + | LeftShiftU64 (CodeTwo5c, 16) + | LeftShiftU64 (CodeTwoIc, 21) + | LeftShiftU64 (CodeOne18, 22) + | LeftShiftU64 (CodeOne23, 40) + | LeftShiftU64 (CodeTwoI, 63) + ; + +Action: + if (IsThunk == 1){ + // + // The callee is a thunk to EBC, adjust the stack pointer down 16 bytes and + // put our return address and frame pointer on the VM stack. + // Then set the VM's IP to new EBC code. + // + VmPtr->R[0] -= 8; + VmWriteMemN (VmPtr, (UINTN) VmPtr->R[0], (UINTN) FramePtr); + VmPtr->FramePtr = (VOID *) (UINTN) VmPtr->R[0]; + VmPtr->R[0] -= 8; + VmWriteMem64 (VmPtr, (UINTN) VmPtr->R[0], (UINT64) (VmPtr->Ip + Size)); + + VmPtr->Ip = (VMIP) (UINTN) TargetEbcAddr; + } else { + // + // The callee is not a thunk to EBC, call native code. + // + EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr); + + // + // Get return value and advance the IP. + // + VmPtr->R[7] = EbcLLGetReturnValue (); + VmPtr->Ip += Size; + } +} + +VOID +EbcLLCALLEXNative ( + IN UINTN CallAddr, + IN UINTN EbcSp, + IN VOID *FramePtr + ) +/*++ + +Routine Description: + Implements the EBC CALLEX instruction to call an external function, which + seems to be native code. + + We'll copy the entire EBC stack frame down below itself in memory and use + that copy for passing parameters. + +Arguments: + CallAddr - address (function pointer) of function to call + EbcSp - current EBC stack pointer + FramePtr - current EBC frame pointer. + +Returns: + NA + +--*/ +{ + UINTN FrameSize; + VOID *Destination; + VOID *Source; + // + // The stack for an EBC function looks like this: + // FramePtr (8) + // RetAddr (8) + // Locals (n) + // Stack for passing args (m) + // + // Pad the frame size with 64 bytes because the low-level code we call + // will move the stack pointer up assuming worst-case 8 args in registers. + // + FrameSize = (UINTN) FramePtr - (UINTN) EbcSp + 64; + Source = (VOID *) EbcSp; + Destination = (VOID *) ((UINT8 *) EbcSp - FrameSize - IPF_STACK_ALIGNMENT); + Destination = (VOID *) ((UINTN) ((UINTN) Destination + IPF_STACK_ALIGNMENT - 1) &~((UINTN) IPF_STACK_ALIGNMENT - 1)); + gBS->CopyMem (Destination, Source, FrameSize); + EbcAsmLLCALLEX ((UINTN) CallAddr, (UINTN) Destination); +} diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ipf/IpfMath.c b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/IpfMath.c new file mode 100644 index 0000000000..f35f1b9ad1 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/IpfMath.c @@ -0,0 +1,375 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Ipfmath.c + +Abstract: + + Math routines for IPF. + +--*/ + +UINT64 +LeftShiftU64 ( + IN UINT64 Operand, + IN UINT64 Count + ) +/*++ + +Routine Description: + + Left-shift a 64 bit value. + +Arguments: + + Operand - 64-bit value to shift + Count - shift count + +Returns: + + Operand << Count + +--*/ +{ + if (Count > 63) { + return 0; + } + + return Operand << Count; +} + +UINT64 +RightShiftU64 ( + IN UINT64 Operand, + IN UINT64 Count + ) +/*++ + +Routine Description: + + Right-shift a 64 bit value. + +Arguments: + + Operand - 64-bit value to shift + Count - shift count + +Returns: + + Operand >> Count + +--*/ +{ + if (Count > 63) { + return 0; + } + + return Operand >> Count; +} + +INT64 +ARightShift64 ( + IN INT64 Operand, + IN UINT64 Count + ) +/*++ + +Routine Description: + + Right-shift a 64 bit signed value. + +Arguments: + + Operand - 64-bit value to shift + Count - shift count + +Returns: + + Operand >> Count + +--*/ +{ + if (Count > 63) { + + if (Operand & (0x01 << 63)) { + return (INT64)~0; + } + + return 0; + } + + return Operand >> Count; +} + +#if 0 +// +// The compiler generates true assembly for these, so we don't need them. +// +INT32 +ARightShift32 ( + IN INT32 Operand, + IN UINTN Count + ) +/*++ + +Routine Description: + + Right shift a 32-bit value + +Arguments: + + Operand - value to shift + Count - shift count + +Returns: + + Operand >> Count + +--*/ +{ + return Operand >> (Count & 0x1f); +} + +INT32 +MulS32x32 ( + INT32 Value1, + INT32 Value2, + INT32 *ResultHigh + ) +/*++ + +Routine Description: + + Multiply two signed 32-bit numbers. + +Arguments: + + Value1 - first value to multiply + Value2 - value to multiply Value1 by + ResultHigh - overflow + +Returns: + + Value1 * Value2 + +Notes: + + The 64-bit result is the concatenation of *ResultHigh and the return value + + The product fits in 32 bits if + (*ResultHigh == 0x00000000 AND *ResultLow_bit31 == 0) + OR + (*ResultHigh == 0xffffffff AND *ResultLow_bit31 == 1) + +--*/ +{ + INT64 Rres64; + INT32 Result; + + Res64 = (INT64) Value1 * (INT64) Value2; + *ResultHigh = (Res64 >> 32) & 0xffffffff; + Result = Res64 & 0xffffffff; + return Result; +} + +UINT32 +MulU32x32 ( + UINT32 Value1, + UINT32 Value2, + UINT32 *ResultHigh + ) +/*++ + +Routine Description: + + Multiply two unsigned 32-bit values. + +Arguments: + + Value1 - first number + Value2 - number to multiply by Value1 + ResultHigh - overflow + +Returns: + + Value1 * Value2 + +Notes: + + The 64-bit result is the concatenation of *ResultHigh and the return value. + The product fits in 32 bits if *ResultHigh == 0x00000000 + +--*/ +{ + UINT64 Res64; + UINT32 Result; + + Res64 = (INT64) Value1 * (INT64) Value2; + *ResultHigh = (Res64 >> 32) & 0xffffffff; + Result = Res64 & 0xffffffff; + return Result; +} + +INT32 +DivS32x32 ( + INT32 Value1, + INT32 Value2, + INT32 *Remainder, + UINTN *error + ) +// +// signed 32-bit by signed 32-bit divide; the 32-bit remainder is +// in *Remainder and the quotient is the return value; *error = 1 if the +// divisor is 0, and it is 1 otherwise +// +{ + INT32 Result; + + *error = 0; + + if (Value2 == 0x0) { + *error = 1; + Result = 0x80000000; + *Remainder = 0x80000000; + } else { + Result = Value1 / Value2; + *Remainder = Value1 - Result * Value2; + } + + return Result; +} + +UINT32 +DivU32x32 ( + UINT32 Value1, + UINT32 Value2, + UINT32 *Remainder, + UINTN *Error + ) +// +// unsigned 32-bit by unsigned 32-bit divide; the 32-bit remainder is +// in *Remainder and the quotient is the return value; *error = 1 if the +// divisor is 0, and it is 1 otherwise +// +{ + UINT32 Result; + + *Error = 0; + + if (Value2 == 0x0) { + *Error = 1; + Result = 0x80000000; + *Remainder = 0x80000000; + } else { + Result = Value1 / Value2; + *Remainder = Value1 - Result * Value2; + } + + return Result; +} + +#endif + +INT64 +DivS64x64 ( + INT64 Value1, + INT64 Value2, + INT64 *Remainder, + UINTN *Error + ) +/*++ + +Routine Description: + + Divide two 64-bit signed values. + +Arguments: + + Value1 - dividend + Value2 - divisor + Remainder - remainder of Value1/Value2 + Error - to flag errors (divide-by-0) + +Returns: + + Value1 / Valu2 + +Note: + + The 64-bit remainder is in *Remainder and the quotient is the return value. + *Error = 1 if the divisor is 0, and it is 1 otherwise + +--*/ +{ + INT64 Result; + + *Error = 0; + + if (Value2 == 0x0) { + *Error = 1; + Result = 0x8000000000000000; + *Remainder = 0x8000000000000000; + } else { + Result = Value1 / Value2; + *Remainder = Value1 - Result * Value2; + } + + return Result; +} + +UINT64 +DivU64x64 ( + UINT64 Value1, + UINT64 Value2, + UINT64 *Remainder, + UINTN *Error + ) +/*++ + +Routine Description: + + Divide two 64-bit unsigned values. + +Arguments: + + Value1 - dividend + Value2 - divisor + Remainder - remainder of Value1/Value2 + Error - to flag errors (divide-by-0) + +Returns: + + Value1 / Valu2 + +Note: + + The 64-bit remainder is in *Remainder and the quotient is the return value. + *Error = 1 if the divisor is 0, and it is 1 otherwise + +--*/ +{ + UINT64 Result; + + *Error = 0; + + if (Value2 == 0x0) { + *Error = 1; + Result = 0x8000000000000000; + *Remainder = 0x8000000000000000; + } else { + Result = Value1 / Value2; + *Remainder = Value1 - Result * Value2; + } + + return Result; +} diff --git a/EdkModulePkg/Universal/Ebc/Dxe/Ipf/IpfMul.s b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/IpfMul.s new file mode 100644 index 0000000000..e887dd61ef --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/Ipf/IpfMul.s @@ -0,0 +1,144 @@ +///*++ +// +// Copyright (c) 2006, 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. +// +//Module Name: +// +// IpfMul.s +// +//Abstract: +// +// Low level routines for IPF multiply support +// +//--*/ + +.file "IpfMul.s" +.section .text + + .proc MulS64x64# + .align 32 + .global MulS64x64# + .align 32 + +///*++ +// +//Routine Description: +// +// Multiply two 64-bit signed numbers. +// +// +//Arguments: +// +// INT64 +// MulS64x64 ( +// IN INT64 Value1, +// IN INT64 Value2, +// OUT INT64 *ResultHigh); +// +//Returns: +// +// 64-bit signed result +// +//--*/ + +MulS64x64: + // signed 64x64->128-bit multiply + // A in r32, B in r33, Q_hi stored in [r34], Q_lo returned in r8 +{ .mfi + alloc r31=ar.pfs,3,0,0,0 // r32-r34 + nop.f 0 + nop.i 0;; +} +{.mmi + setf.sig f6=r32 + setf.sig f7=r33 + nop.i 0;; +} + +{.mfi + nop.m 0 + xma.h f8=f6,f7,f0 + nop.i 0 +} +{.mfi + nop.m 0 + xma.l f6=f6,f7,f0 + nop.i 0;; +} + + +{.mmb + stf8 [r34]=f8 + getf.sig r8=f6 + br.ret.sptk b0;; +} + +.endp MulS64x64 + + .proc MulU64x64# + .align 32 + .global MulU64x64# + .align 32 + + +///*++ +// +//Routine Description: +// +// Multiply two 64-bit unsigned numbers. +// +// +//Arguments: +// +// UINT64 +// MulU64x64 ( +// IN UINT64 Value1, +// IN UINT64 Value2, +// OUT UINT64 *ResultHigh); +// +//Returns: +// +// 64-bit unsigned result +// +//--*/ +MulU64x64: + // A in r32, B in r33, Q_hi stored in [r34], Q_lo returned in r8 +{ .mfi + alloc r31=ar.pfs,3,0,0,0 // r32-r34 + nop.f 0 + nop.i 0;; +} +{.mmi + setf.sig f6=r32 + setf.sig f7=r33 + nop.i 0;; +} + +{.mfi + nop.m 0 + xma.hu f8=f6,f7,f0 + nop.i 0 +} +{.mfi + nop.m 0 + xma.l f6=f6,f7,f0 + nop.i 0;; +} + + +{.mmb + stf8 [r34]=f8 + getf.sig r8=f6 + br.ret.sptk b0;; +} + +.endp MulU64x64 + + diff --git a/EdkModulePkg/Universal/Ebc/Dxe/build.xml b/EdkModulePkg/Universal/Ebc/Dxe/build.xml new file mode 100644 index 0000000000..2145923e2a --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.asm b/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.asm new file mode 100644 index 0000000000..59394621ba --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcLowLevel.asm @@ -0,0 +1,145 @@ + page ,132 + title VM ASSEMBLY LANGUAGE ROUTINES +;**************************************************************************** +;* +;* Copyright (c) 2006, 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. +;* +;**************************************************************************** +;**************************************************************************** +; REV 1.0 +;**************************************************************************** +; +; Rev Date Description +; --- -------- ------------------------------------------------------------ +; 1.0 05/09/12 Initial creation of file. +; +;**************************************************************************** + +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; This code provides low level routines that support the Virtual Machine +; for option ROMs. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +;--------------------------------------------------------------------------- +; Equate files needed. +;--------------------------------------------------------------------------- + +text SEGMENT + +;--------------------------------------------------------------------------- +;;GenericPostSegment SEGMENT USE16 +;--------------------------------------------------------------------------- + +;**************************************************************************** +; EbcLLCALLEX +; +; This function is called to execute an EBC CALLEX instruction. +; This instruction requires that we thunk out to external native +; code. For x64, we switch stacks, copy the arguments to the stack +; and jump to the specified function. +; On return, we restore the stack pointer to its original location. +; +; Destroys no working registers. +;**************************************************************************** +; VOID EbcLLCALLEXNative(UINTN FuncAddr, UINTN NewStackPointer, VOID *FramePtr) +EbcLLCALLEXNative PROC + push rbp + push rbx + mov rbp, rsp + ; Function prolog + + ; Copy FuncAddr to a preserved register. + mov rbx, rcx + + ; Set stack pointer to new value + mov rsp, rdx + + ; Considering the worst case, load 4 potiential arguments + ; into registers. + mov rcx, qword ptr [rsp] + mov rdx, qword ptr [rsp+8h] + mov r8, qword ptr [rsp+10h] + mov r9, qword ptr [rsp+18h] + + ; Now call the external routine + call rbx + + ; Function epilog + mov rsp, rbp + pop rbx + pop rbp + ret +EbcLLCALLEXNative ENDP + + +; UINTN EbcLLGetEbcEntryPoint(VOID); +; Routine Description: +; The VM thunk code stuffs an EBC entry point into a processor +; register. Since we can't use inline assembly to get it from +; the interpreter C code, stuff it into the return value +; register and return. +; +; Arguments: +; None. +; +; Returns: +; The contents of the register in which the entry point is passed. +; +EbcLLGetEbcEntryPoint PROC + ret +EbcLLGetEbcEntryPoint ENDP + +;/*++ +; +;Routine Description: +; +; Return the caller's value of the stack pointer. +; +;Arguments: +; +; None. +; +;Returns: +; +; The current value of the stack pointer for the caller. We +; adjust it by 4 here because when they called us, the return address +; is put on the stack, thereby lowering it by 4 bytes. +; +;--*/ + +; UINTN EbcLLGetStackPointer() +EbcLLGetStackPointer PROC + mov rax, rsp ; get current stack pointer + ; Stack adjusted by this much when we were called, + ; For this function, it's 4. + add rax, 4 + ret +EbcLLGetStackPointer ENDP + +; UINT64 EbcLLGetReturnValue(VOID); +; Routine Description: +; When EBC calls native, on return the VM has to stuff the return +; value into a VM register. It's assumed here that the value is still +; in the register, so simply return and the caller should get the +; return result properly. +; +; Arguments: +; None. +; +; Returns: +; The unmodified value returned by the native code. +; +EbcLLGetReturnValue PROC + ret +EbcLLGetReturnValue ENDP + +text ENDS +END + diff --git a/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcSupport.c b/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcSupport.c new file mode 100644 index 0000000000..d111f3c0bf --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/x64/EbcSupport.c @@ -0,0 +1,579 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EbcSupport.c + +Abstract: + + This module contains EBC support routines that are customized based on + the target x64 processor. + +--*/ + +#include "EbcInt.h" +#include "EbcExecute.h" + +// +// NOTE: This is the stack size allocated for the interpreter +// when it executes an EBC image. The requirements can change +// based on whether or not a debugger is present, and other +// platform-specific configurations. +// +#define VM_STACK_SIZE (1024 * 8) +#define EBC_THUNK_SIZE 64 + +STATIC +VOID +PushU64 ( + VM_CONTEXT *VmPtr, + UINT64 Arg + ) +/*++ + +Routine Description: + + Push a 64 bit unsigned value to the VM stack. + +Arguments: + + VmPtr - The pointer to current VM context. + Arg - The value to be pushed + +Returns: + + VOID + +--*/ +{ + // + // Advance the VM stack down, and then copy the argument to the stack. + // Hope it's aligned. + // + VmPtr->R[0] -= sizeof (UINT64); + *(UINT64 *) VmPtr->R[0] = Arg; + return; +} + +STATIC +UINT64 +EbcInterpret ( + UINTN Arg1, + UINTN Arg2, + UINTN Arg3, + UINTN Arg4, + UINTN Arg5 + ) +/*++ + +Routine Description: + + Begin executing an EBC image. The address of the entry point is passed + in via a processor register, so we'll need to make a call to get the + value. + +Arguments: + + This is a thunk function. Microsoft x64 compiler only provide fast_call + calling convention, so the first four arguments are passed by rcx, rdx, + r8, and r9, while other arguments are passed in stack. + +Returns: + + The value returned by the EBC application we're going to run. + +--*/ +{ + // + // Create a new VM context on the stack + // + VM_CONTEXT VmContext; + UINTN Addr; + + // + // Get the EBC entry point from the processor register. + // Don't call any function before getting the EBC entry + // point because this will collab the return register. + // + Addr = EbcLLGetEbcEntryPoint (); + + // + // Now clear out our context + // + ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT)); + + // + // Set the VM instruction pointer to the correct location in memory. + // + VmContext.Ip = (VMIP) Addr; + + // + // Initialize the stack pointer for the EBC. Get the current system stack + // pointer and adjust it down by the max needed for the interpreter. + // + Addr = EbcLLGetStackPointer (); + + // + // Adjust the VM's stack pointer down. + // + VmContext.R[0] = (UINT64) Addr; + VmContext.R[0] -= VM_STACK_SIZE; + + // + // Align the stack on a natural boundary. + // + VmContext.R[0] &= ~(sizeof (UINTN) - 1); + + // + // Put a magic value in the stack gap, then adjust down again. + // + *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) VM_STACK_KEY_VALUE; + VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0]; + + // + // The stack upper to LowStackTop is belong to the VM. + // + VmContext.LowStackTop = (UINTN) VmContext.R[0]; + + // + // For the worst case, assume there are 4 arguments passed in registers, store + // them to VM's stack. + // + PushU64 (&VmContext, (UINT64) Arg4); + PushU64 (&VmContext, (UINT64) Arg3); + PushU64 (&VmContext, (UINT64) Arg2); + PushU64 (&VmContext, (UINT64) Arg1); + + // + // Interpreter assumes 64-bit return address is pushed on the stack. + // The x64 does not do this so pad the stack accordingly. + // + PushU64 (&VmContext, (UINT64) 0); + PushU64 (&VmContext, (UINT64) 0x1234567887654321); + + // + // For x64, this is where we say our return address is + // + VmContext.StackRetAddr = (UINT64) VmContext.R[0]; + + // + // We need to keep track of where the EBC stack starts. This way, if the EBC + // accesses any stack variables above its initial stack setting, then we know + // it's accessing variables passed into it, which means the data is on the + // VM's stack. + // When we're called, on the stack (high to low) we have the parameters, the + // return address, then the saved ebp. Save the pointer to the return address. + // EBC code knows that's there, so should look above it for function parameters. + // The offset is the size of locals (VMContext + Addr + saved ebp). + // Note that the interpreter assumes there is a 16 bytes of return address on + // the stack too, so adjust accordingly. + // VmContext.HighStackBottom = (UINTN)(Addr + sizeof (VmContext) + sizeof (Addr)); + // + VmContext.HighStackBottom = (UINTN) &Arg5; + + // + // Begin executing the EBC code + // + EbcExecute (&VmContext); + + // + // Return the value in R[7] unless there was an error + // + return (UINT64) VmContext.R[7]; +} + +STATIC +UINT64 +ExecuteEbcImageEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Begin executing an EBC image. The address of the entry point is passed + in via a processor register, so we'll need to make a call to get the + value. + +Arguments: + + ImageHandle - image handle for the EBC application we're executing + SystemTable - standard system table passed into an driver's entry point + +Returns: + + The value returned by the EBC application we're going to run. + +--*/ +{ + // + // Create a new VM context on the stack + // + VM_CONTEXT VmContext; + UINTN Addr; + + // + // Get the EBC entry point from the processor register. Make sure you don't + // call any functions before this or you could mess up the register the + // entry point is passed in. + // + Addr = EbcLLGetEbcEntryPoint (); + + // + // Now clear out our context + // + ZeroMem ((VOID *) &VmContext, sizeof (VM_CONTEXT)); + + // + // Save the image handle so we can track the thunks created for this image + // + VmContext.ImageHandle = ImageHandle; + VmContext.SystemTable = SystemTable; + + // + // Set the VM instruction pointer to the correct location in memory. + // + VmContext.Ip = (VMIP) Addr; + + // + // Initialize the stack pointer for the EBC. Get the current system stack + // pointer and adjust it down by the max needed for the interpreter. + // + Addr = EbcLLGetStackPointer (); + VmContext.R[0] = (UINT64) Addr; + VmContext.R[0] -= VM_STACK_SIZE; + + // + // Put a magic value in the stack gap, then adjust down again + // + *(UINTN *) (UINTN) (VmContext.R[0]) = (UINTN) VM_STACK_KEY_VALUE; + VmContext.StackMagicPtr = (UINTN *) (UINTN) VmContext.R[0]; + + // + // Align the stack on a natural boundary + VmContext.R[0] &= ~(sizeof(UINTN) - 1); + // + VmContext.LowStackTop = (UINTN) VmContext.R[0]; + + // + // Simply copy the image handle and system table onto the EBC stack. + // Greatly simplifies things by not having to spill the args. + // + PushU64 (&VmContext, (UINT64) SystemTable); + PushU64 (&VmContext, (UINT64) ImageHandle); + + // + // VM pushes 16-bytes for return address. Simulate that here. + // + PushU64 (&VmContext, (UINT64) 0); + PushU64 (&VmContext, (UINT64) 0x1234567887654321); + + // + // For x64, this is where we say our return address is + // + VmContext.StackRetAddr = (UINT64) VmContext.R[0]; + + // + // Entry function needn't access high stack context, simply + // put the stack pointer here. + // + VmContext.HighStackBottom = (UINTN) Addr; + + // + // Begin executing the EBC code + // + EbcExecute (&VmContext); + + // + // Return the value in R[7] unless there was an error + // + return (UINT64) VmContext.R[7]; +} + +EFI_STATUS +EbcCreateThunks ( + IN EFI_HANDLE ImageHandle, + IN VOID *EbcEntryPoint, + OUT VOID **Thunk, + IN UINT32 Flags + ) +/*++ + +Routine Description: + + Create an IA32 thunk for the given EBC entry point. + +Arguments: + + ImageHandle - Handle of image for which this thunk is being created + EbcEntryPoint - Address of the EBC code that the thunk is to call + Thunk - Returned thunk we create here + +Returns: + + Standard EFI status. + +--*/ +{ + UINT8 *Ptr; + UINT8 *ThunkBase; + UINT32 I; + UINT64 Addr; + INT32 Size; + INT32 ThunkSize; + EFI_STATUS Status; + + // + // Check alignment of pointer to EBC code + // + if ((UINT32) (UINTN) EbcEntryPoint & 0x01) { + return EFI_INVALID_PARAMETER; + } + + Size = EBC_THUNK_SIZE; + ThunkSize = Size; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + Size, + (VOID *) &Ptr + ); + if (Status != EFI_SUCCESS) { + return EFI_OUT_OF_RESOURCES; + } + // + // Print(L"Allocate TH: 0x%X\n", (UINT32)Ptr); + // + // Save the start address so we can add a pointer to it to a list later. + // + ThunkBase = Ptr; + + // + // Give them the address of our buffer we're going to fix up + // + *Thunk = (VOID *) Ptr; + + // + // Add a magic code here to help the VM recognize the thunk.. + // mov rax, ca112ebccall2ebch => 48 B8 BC 2E 11 CA BC 2E 11 CA + // + *Ptr = 0x48; + Ptr++; + Size--; + *Ptr = 0xB8; + Ptr++; + Size--; + Addr = (UINT64) 0xCA112EBCCA112EBC; + for (I = 0; I < sizeof (Addr); I++) { + *Ptr = (UINT8) (UINTN) Addr; + Addr >>= 8; + Ptr++; + Size--; + } + + // + // Add code bytes to load up a processor register with the EBC entry point. + // mov rax, 123456789abcdef0h => 48 B8 F0 DE BC 9A 78 56 34 12 + // The first 8 bytes of the thunk entry is the address of the EBC + // entry point. + // + *Ptr = 0x48; + Ptr++; + Size--; + *Ptr = 0xB8; + Ptr++; + Size--; + Addr = (UINT64) EbcEntryPoint; + for (I = 0; I < sizeof (Addr); I++) { + *Ptr = (UINT8) (UINTN) Addr; + Addr >>= 8; + Ptr++; + Size--; + } + + // + // Stick in a load of ecx with the address of appropriate VM function. + // Using r11 because it's a volatile register and won't be used in this + // point. + // mov r11 123456789abcdef0h => 49 BB F0 DE BC 9A 78 56 34 12 + // + if (Flags & FLAG_THUNK_ENTRY_POINT) { + Addr = (UINTN) ExecuteEbcImageEntryPoint; + } else { + Addr = (UINTN) EbcInterpret; + } + + // + // mov r11 Addr => 0x49 0xBB + // + *Ptr = 0x49; + Ptr++; + Size--; + *Ptr = 0xBB; + Ptr++; + Size--; + for (I = 0; I < sizeof (Addr); I++) { + *Ptr = (UINT8) Addr; + Addr >>= 8; + Ptr++; + Size--; + } + // + // Stick in jump opcode bytes for jmp r11 => 0x41 0xFF 0xE3 + // + *Ptr = 0x41; + Ptr++; + Size--; + *Ptr = 0xFF; + Ptr++; + Size--; + *Ptr = 0xE3; + Size--; + + // + // Double check that our defined size is ok (application error) + // + if (Size < 0) { + ASSERT (FALSE); + return EFI_BUFFER_TOO_SMALL; + } + // + // Add the thunk to the list for this image. Do this last since the add + // function flushes the cache for us. + // + EbcAddImageThunk (ImageHandle, (VOID *) ThunkBase, ThunkSize); + + return EFI_SUCCESS; +} + +VOID +EbcLLCALLEX ( + IN VM_CONTEXT *VmPtr, + IN UINTN FuncAddr, + IN UINTN NewStackPointer, + IN VOID *FramePtr, + IN UINT8 Size + ) +/*++ + +Routine Description: + + This function is called to execute an EBC CALLEX instruction. + The function check the callee's content to see whether it is common native + code or a thunk to another piece of EBC code. + If the callee is common native code, use EbcLLCAllEXASM to manipulate, + otherwise, set the VM->IP to target EBC code directly to avoid another VM + be startup which cost time and stack space. + +Arguments: + + VmPtr - Pointer to a VM context. + FuncAddr - Callee's address + NewStackPointer - New stack pointer after the call + FramePtr - New frame pointer after the call + Size - The size of call instruction + +Returns: + + None. + +--*/ +{ + UINTN IsThunk; + UINTN TargetEbcAddr; + + IsThunk = 1; + TargetEbcAddr = 0; + + // + // Processor specific code to check whether the callee is a thunk to EBC. + // + if (*((UINT8 *)FuncAddr) != 0x48) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 1) != 0xB8) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 2) != 0xBC) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 3) != 0x2E) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 4) != 0x11) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 5) != 0xCA) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 6) != 0xBC) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 7) != 0x2E) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 8) != 0x11) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 9) != 0xCA) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 10) != 0x48) { + IsThunk = 0; + goto Action; + } + if (*((UINT8 *)FuncAddr + 11) != 0xB8) { + IsThunk = 0; + goto Action; + } + + CopyMem (&TargetEbcAddr, (UINT8 *)FuncAddr + 12, 8); + +Action: + if (IsThunk == 1){ + // + // The callee is a thunk to EBC, adjust the stack pointer down 16 bytes and + // put our return address and frame pointer on the VM stack. + // Then set the VM's IP to new EBC code. + // + VmPtr->R[0] -= 8; + VmWriteMemN (VmPtr, (UINTN) VmPtr->R[0], (UINTN) FramePtr); + VmPtr->FramePtr = (VOID *) (UINTN) VmPtr->R[0]; + VmPtr->R[0] -= 8; + VmWriteMem64 (VmPtr, (UINTN) VmPtr->R[0], (UINT64) (VmPtr->Ip + Size)); + + VmPtr->Ip = (VMIP) (UINTN) TargetEbcAddr; + } else { + // + // The callee is not a thunk to EBC, call native code. + // + EbcLLCALLEXNative (FuncAddr, NewStackPointer, FramePtr); + + // + // Get return value and advance the IP. + // + VmPtr->R[7] = EbcLLGetReturnValue (); + VmPtr->Ip += Size; + } +} + diff --git a/EdkModulePkg/Universal/Ebc/Dxe/x64/x64Math.c b/EdkModulePkg/Universal/Ebc/Dxe/x64/x64Math.c new file mode 100644 index 0000000000..0842490732 --- /dev/null +++ b/EdkModulePkg/Universal/Ebc/Dxe/x64/x64Math.c @@ -0,0 +1,451 @@ +/*++ + +Copyright (c) 2006 , 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. + +Module Name: + + x64math.c + +Abstract: + + Math routines for x64. + +--*/ + +UINT64 +LeftShiftU64 ( + IN UINT64 Operand, + IN UINT64 Count + ) +/*++ + +Routine Description: + + Left-shift a 64 bit value. + +Arguments: + + Operand - 64-bit value to shift + Count - shift count + +Returns: + + Operand << Count + +--*/ +{ + if (Count > 63) { + return 0; + } + + return Operand << Count; +} + +UINT64 +RightShiftU64 ( + IN UINT64 Operand, + IN UINT64 Count + ) +/*++ + +Routine Description: + + Right-shift a 64 bit value. + +Arguments: + + Operand - 64-bit value to shift + Count - shift count + +Returns: + + Operand >> Count + +--*/ +{ + if (Count > 63) { + return 0; + } + + return Operand >> Count; +} + +INT64 +ARightShift64 ( + IN INT64 Operand, + IN UINT64 Count + ) +/*++ + +Routine Description: + + Right-shift a 64 bit signed value. + +Arguments: + + Operand - 64-bit value to shift + Count - shift count + +Returns: + + Operand >> Count + +--*/ +{ + if (Count > 63) { + + if (Operand & 0x8000000000000000ULL) { + return (INT64)~0; + } + + return 0; + } + + return Operand >> Count; +} + +#if 0 +// +// The compiler generates true assembly for these, so we don't need them. +// +INT32 +ARightShift32 ( + IN INT32 Operand, + IN UINTN Count + ) +/*++ + +Routine Description: + + Right shift a 32-bit value + +Arguments: + + Operand - value to shift + Count - shift count + +Returns: + + Operand >> Count + +--*/ +{ + return Operand >> (Count & 0x1f); +} + +INT32 +MulS32x32 ( + INT32 Value1, + INT32 Value2, + INT32 *ResultHigh + ) +/*++ + +Routine Description: + + Multiply two signed 32-bit numbers. + +Arguments: + + Value1 - first value to multiply + Value2 - value to multiply Value1 by + ResultHigh - overflow + +Returns: + + Value1 * Value2 + +Notes: + + The 64-bit result is the concatenation of *ResultHigh and the return value + + The product fits in 32 bits if + (*ResultHigh == 0x00000000 AND *ResultLow_bit31 == 0) + OR + (*ResultHigh == 0xffffffff AND *ResultLow_bit31 == 1) + +--*/ +{ + INT64 Rres64; + INT32 Result; + + Res64 = (INT64) Value1 * (INT64) Value2; + *ResultHigh = (Res64 >> 32) & 0xffffffff; + Result = Res64 & 0xffffffff; + return Result; +} + +UINT32 +MulU32x32 ( + UINT32 Value1, + UINT32 Value2, + UINT32 *ResultHigh + ) +/*++ + +Routine Description: + + Multiply two unsigned 32-bit values. + +Arguments: + + Value1 - first number + Value2 - number to multiply by Value1 + ResultHigh - overflow + +Returns: + + Value1 * Value2 + +Notes: + + The 64-bit result is the concatenation of *ResultHigh and the return value. + The product fits in 32 bits if *ResultHigh == 0x00000000 + +--*/ +{ + UINT64 Res64; + UINT32 Result; + + Res64 = (INT64) Value1 * (INT64) Value2; + *ResultHigh = (Res64 >> 32) & 0xffffffff; + Result = Res64 & 0xffffffff; + return Result; +} + +INT32 +DivS32x32 ( + INT32 Value1, + INT32 Value2, + INT32 *Remainder, + UINTN *error + ) +// +// signed 32-bit by signed 32-bit divide; the 32-bit remainder is +// in *Remainder and the quotient is the return value; *error = 1 if the +// divisor is 0, and it is 1 otherwise +// +{ + INT32 Result; + + *error = 0; + + if (Value2 == 0x0) { + *error = 1; + Result = 0x80000000; + *Remainder = 0x80000000; + } else { + Result = Value1 / Value2; + *Remainder = Value1 - Result * Value2; + } + + return Result; +} + +UINT32 +DivU32x32 ( + UINT32 Value1, + UINT32 Value2, + UINT32 *Remainder, + UINTN *Error + ) +// +// unsigned 32-bit by unsigned 32-bit divide; the 32-bit remainder is +// in *Remainder and the quotient is the return value; *error = 1 if the +// divisor is 0, and it is 1 otherwise +// +{ + UINT32 Result; + + *Error = 0; + + if (Value2 == 0x0) { + *Error = 1; + Result = 0x80000000; + *Remainder = 0x80000000; + } else { + Result = Value1 / Value2; + *Remainder = Value1 - Result * Value2; + } + + return Result; +} + +#endif + +INT64 +MulS64x64 ( + INT64 Value1, + INT64 Value2, + INT64 *ResultHigh + ) +/*++ + +Routine Description: + + Multiply two signed 32-bit numbers. + +Arguments: + + Value1 - first value to multiply + Value2 - value to multiply Value1 by + ResultHigh - overflow + +Returns: + + Value1 * Value2 + +Notes: + + The 64-bit result is the concatenation of *ResultHigh and the return value + + The product fits in 32 bits if + (*ResultHigh == 0x00000000 AND *ResultLow_bit31 == 0) + OR + (*ResultHigh == 0xffffffff AND *ResultLow_bit31 == 1) + +--*/ +{ + INT64 Result; + + Result = Value1 * Value2; + + return Result; +} + +UINT64 +MulU64x64 ( + UINT64 Value1, + UINT64 Value2, + UINT64 *ResultHigh + ) +/*++ + +Routine Description: + + Multiply two unsigned 32-bit values. + +Arguments: + + Value1 - first number + Value2 - number to multiply by Value1 + ResultHigh - overflow + +Returns: + + Value1 * Value2 + +Notes: + + The 64-bit result is the concatenation of *ResultHigh and the return value. + The product fits in 32 bits if *ResultHigh == 0x00000000 + +--*/ +{ + UINT64 Result; + + Result = Value1 * Value2; + + return Result; +} + +INT64 +DivS64x64 ( + INT64 Value1, + INT64 Value2, + INT64 *Remainder, + UINTN *Error + ) +/*++ + +Routine Description: + + Divide two 64-bit signed values. + +Arguments: + + Value1 - dividend + Value2 - divisor + Remainder - remainder of Value1/Value2 + Error - to flag errors (divide-by-0) + +Returns: + + Value1 / Valu2 + +Note: + + The 64-bit remainder is in *Remainder and the quotient is the return value. + *Error = 1 if the divisor is 0, and it is 1 otherwise + +--*/ +{ + INT64 Result; + + *Error = 0; + + if (Value2 == 0x0) { + *Error = 1; + Result = 0x8000000000000000; + *Remainder = 0x8000000000000000; + } else { + Result = Value1 / Value2; + *Remainder = Value1 - Result * Value2; + } + + return Result; +} + +UINT64 +DivU64x64 ( + UINT64 Value1, + UINT64 Value2, + UINT64 *Remainder, + UINTN *Error + ) +/*++ + +Routine Description: + + Divide two 64-bit unsigned values. + +Arguments: + + Value1 - dividend + Value2 - divisor + Remainder - remainder of Value1/Value2 + Error - to flag errors (divide-by-0) + +Returns: + + Value1 / Valu2 + +Note: + + The 64-bit remainder is in *Remainder and the quotient is the return value. + *Error = 1 if the divisor is 0, and it is 1 otherwise + +--*/ +{ + UINT64 Result; + + *Error = 0; + + if (Value2 == 0x0) { + *Error = 1; + Result = 0x8000000000000000; + *Remainder = 0x8000000000000000; + } else { + Result = Value1 / Value2; + *Remainder = Value1 - Result * Value2; + } + + return Result; +} diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.c b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.c new file mode 100644 index 0000000000..beb404f42c --- /dev/null +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.c @@ -0,0 +1,754 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EmuVariable.c + +Abstract: + +Revision History + +--*/ + +#include "Variable.h" + +// +// Don't use module globals after the SetVirtualAddress map is signaled +// +ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal; + +UINT32 +EFIAPI +ArrayLength ( + IN CHAR16 *String + ) +/*++ + +Routine Description: + + Determine the length of null terminated char16 array. + +Arguments: + + String Null-terminated CHAR16 array pointer. + +Returns: + + UINT32 Number of bytes in the string, including the double NULL at the end; + +--*/ +{ + UINT32 Count; + + if (NULL == String) { + return 0; + } + + Count = 0; + + while (0 != String[Count]) { + Count++; + } + + return (Count * 2) + 2; +} + +UINTN +EFIAPI +GetPadSize ( + IN UINTN Value + ) +/*++ + +Routine Description: + + This function return the pad size for alignment + +Arguments: + + Value The value need to align + +Returns: + + Pad size for value + +--*/ +{ + // + // If alignment is 0 or 1, means no alignment required + // + if (ALIGNMENT == 0 || ALIGNMENT == 1) { + return 0; + } + + return ALIGNMENT - (Value % ALIGNMENT); +} + +VARIABLE_STORE_STATUS +EFIAPI +GetVariableStoreStatus ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ) +/*++ + +Routine Description: + + This code gets the pointer to the variable name. + +Arguments: + + VarStoreHeader Pointer to the Variable Store Header. + +Returns: + + EfiHealthy Variable store is healthy + EfiRaw Variable store is raw + EfiInvalid Variable store is invalid + +--*/ +{ + if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE && + VarStoreHeader->Format == VARIABLE_STORE_FORMATTED && + VarStoreHeader->State == VARIABLE_STORE_HEALTHY + ) { + + return EfiValid; + } else if (VarStoreHeader->Signature == 0xffffffff && + VarStoreHeader->Size == 0xffffffff && + VarStoreHeader->Format == 0xff && + VarStoreHeader->State == 0xff + ) { + + return EfiRaw; + } else { + return EfiInvalid; + } +} + +UINT8 * +EFIAPI +GetVariableDataPtr ( + IN VARIABLE_HEADER *Variable + ) +/*++ + +Routine Description: + + This code gets the pointer to the variable data. + +Arguments: + + Variable Pointer to the Variable Header. + +Returns: + + UINT8* Pointer to Variable Data + +--*/ +{ + if (Variable->StartId != VARIABLE_DATA) { + return NULL; + } + // + // Be careful about pad size for alignment + // + return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GetPadSize (Variable->NameSize)); +} + +VARIABLE_HEADER * +EFIAPI +GetNextVariablePtr ( + IN VARIABLE_HEADER *Variable + ) +/*++ + +Routine Description: + + This code gets the pointer to the next variable header. + +Arguments: + + Variable Pointer to the Variable Header. + +Returns: + + VARIABLE_HEADER* Pointer to next variable header. + +--*/ +{ + VARIABLE_HEADER *VarHeader; + + if (Variable->StartId != VARIABLE_DATA) { + return NULL; + } + // + // Be careful about pad size for alignment + // + VarHeader = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize)); + + if (VarHeader->StartId != VARIABLE_DATA || + (sizeof (VARIABLE_HEADER) + VarHeader->DataSize + VarHeader->NameSize) > MAX_VARIABLE_SIZE + ) { + return NULL; + } + + return VarHeader; +} + +VARIABLE_HEADER * +EFIAPI +GetEndPointer ( + IN VARIABLE_STORE_HEADER *VolHeader + ) +/*++ + +Routine Description: + + This code gets the pointer to the last variable memory pointer byte + +Arguments: + + Variable Pointer to the Variable Header. + +Returns: + + VARIABLE_HEADER* Pointer to last unavailable Variable Header + +--*/ +{ + // + // The end of variable store + // + return (VARIABLE_HEADER *) ((UINTN) VolHeader + VolHeader->Size); +} + +EFI_STATUS +EFIAPI +FindVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack, + IN VARIABLE_GLOBAL *Global + ) +/*++ + +Routine Description: + + This code finds variable in storage blocks (Volatile or Non-Volatile) + +Arguments: + + VariableName Name of the variable to be found + VendorGuid Vendor GUID to be found. + PtrTrack Variable Track Pointer structure that contains + Variable Information. + Contains the pointer of Variable header. + Global VARIABLE_GLOBAL pointer + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_HEADER *Variable[2]; + VARIABLE_STORE_HEADER *VariableStoreHeader[2]; + UINTN Index; + + // + // 0: Non-Volatile, 1: Volatile + // + VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase); + VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase); + + // + // Start Pointers for the variable. + // Actual Data Pointer where data can be written. + // + Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1); + Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1); + + if (VariableName[0] != 0 && VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Find the variable by walk through non-volatile and volatile variable store + // + for (Index = 0; Index < 2; Index++) { + PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1); + PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]); + + while ((Variable[Index] != NULL) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) { + if (Variable[Index]->StartId == VARIABLE_DATA && Variable[Index]->State == VAR_ADDED) { + if (!(EfiAtRuntime () && !(Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) { + if (VariableName[0] == 0) { + PtrTrack->CurrPtr = Variable[Index]; + PtrTrack->Volatile = (BOOLEAN) Index; + return EFI_SUCCESS; + } else { + if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) { + if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), ArrayLength (VariableName))) { + PtrTrack->CurrPtr = Variable[Index]; + PtrTrack->Volatile = (BOOLEAN) Index; + return EFI_SUCCESS; + } + } + } + } + } + + Variable[Index] = GetNextVariablePtr (Variable[Index]); + } + } + PtrTrack->CurrPtr = NULL; + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +GetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data, + IN VARIABLE_GLOBAL * Global, + IN UINT32 Instance + ) +/*++ + +Routine Description: + + This code finds variable in storage blocks (Volatile or Non-Volatile) + +Arguments: + + VariableName Name of Variable to be found + VendorGuid Variable vendor GUID + Attributes OPTIONAL Attribute value of the variable found + DataSize Size of Data found. If size is less than the + data, this value contains the required size. + Data Data pointer + Global Pointer to VARIABLE_GLOBAL structure + Instance Instance of the Firmware Volume. + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + UINTN VarDataSize; + EFI_STATUS Status; + + if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Find existing variable + // + Status = FindVariable (VariableName, VendorGuid, &Variable, Global); + + if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) { + return Status; + } + // + // Get data size + // + VarDataSize = Variable.CurrPtr->DataSize; + if (*DataSize >= VarDataSize) { + CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize); + if (Attributes) { + *Attributes = Variable.CurrPtr->Attributes; + } + + *DataSize = VarDataSize; + return EFI_SUCCESS; + } else { + *DataSize = VarDataSize; + return EFI_BUFFER_TOO_SMALL; + } +} + +EFI_STATUS +EFIAPI +GetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid, + IN VARIABLE_GLOBAL *Global, + IN UINT32 Instance + ) +/*++ + +Routine Description: + + This code Finds the Next available variable + +Arguments: + + VariableNameSize Size of the variable + VariableName Pointer to variable name + VendorGuid Variable Vendor Guid + Global VARIABLE_GLOBAL structure pointer. + Instance FV instance + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + UINTN VarNameSize; + EFI_STATUS Status; + + if (VariableNameSize == NULL || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FindVariable (VariableName, VendorGuid, &Variable, Global); + + if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) { + return Status; + } + + while (TRUE) { + if (VariableName[0] != 0) { + // + // If variable name is not NULL, get next variable + // + Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); + } + // + // If both volatile and non-volatile variable store are parsed, + // return not found + // + if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) { + Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1)); + if (Variable.Volatile) { + Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER))); + Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase)); + } else { + return EFI_NOT_FOUND; + } + + Variable.CurrPtr = Variable.StartPtr; + if (Variable.CurrPtr->StartId != VARIABLE_DATA) { + continue; + } + } + // + // Variable is found + // + if (Variable.CurrPtr->StartId == VARIABLE_DATA && Variable.CurrPtr->State == VAR_ADDED) { + if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) { + VarNameSize = Variable.CurrPtr->NameSize; + if (VarNameSize <= *VariableNameSize) { + CopyMem ( + VariableName, + GET_VARIABLE_NAME_PTR (Variable.CurrPtr), + VarNameSize + ); + CopyMem ( + VendorGuid, + &Variable.CurrPtr->VendorGuid, + sizeof (EFI_GUID) + ); + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + + *VariableNameSize = VarNameSize; + return Status; + } + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +SetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data, + IN VARIABLE_GLOBAL *Global, + IN UINTN *VolatileOffset, + IN UINTN *NonVolatileOffset, + IN UINT32 Instance + ) +/*++ + +Routine Description: + + This code sets variable in storage blocks (Volatile or Non-Volatile) + +Arguments: + + VariableName Name of Variable to be found + VendorGuid Variable vendor GUID + Attributes Attribute value of the variable found + DataSize Size of Data found. If size is less than the + data, this value contains the required size. + Data Data pointer + Global Pointer to VARIABLE_GLOBAL structure + VolatileOffset The offset of last volatile variable + NonVolatileOffset The offset of last non-volatile variable + Instance Instance of the Firmware Volume. + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + EFI_STATUS Status; + VARIABLE_HEADER *NextVariable; + UINTN VarNameSize; + UINTN VarNameOffset; + UINTN VarDataOffset; + UINTN VarSize; + + if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FindVariable (VariableName, VendorGuid, &Variable, Global); + + if (Status == EFI_INVALID_PARAMETER) { + return Status; + } + // + // The size of the VariableName, including the Unicode Null in bytes plus + // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes. + // + else if (sizeof (VARIABLE_HEADER) + (ArrayLength (VariableName) + DataSize) > MAX_VARIABLE_SIZE) { + return EFI_INVALID_PARAMETER; + } + // + // Make sure if runtime bit is set, boot service bit is set also + // + else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS + ) { + return EFI_INVALID_PARAMETER; + } + // + // Runtime but Attribute is not Runtime + // + else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) { + return EFI_INVALID_PARAMETER; + } + // + // Cannot set volatile variable in Runtime + // + else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) { + return EFI_INVALID_PARAMETER; + } + // + // Setting a data variable with no access, or zero DataSize attributes + // specified causes it to be deleted. + // + else if (DataSize == 0 || Attributes == 0) { + if (!EFI_ERROR (Status)) { + Variable.CurrPtr->State &= VAR_DELETED; + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; + } else { + if (!EFI_ERROR (Status)) { + // + // If the variable is marked valid and the same data has been passed in + // then return to the caller immediately. + // + if (Variable.CurrPtr->DataSize == DataSize && + !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize) + ) { + return EFI_SUCCESS; + } else if (Variable.CurrPtr->State == VAR_ADDED) { + // + // Mark the old variable as in delete transition + // + Variable.CurrPtr->State &= VAR_IN_DELETED_TRANSITION; + } + } + // + // Create a new variable and copy the data. + // + VarNameOffset = sizeof (VARIABLE_HEADER); + VarNameSize = ArrayLength (VariableName); + VarDataOffset = VarNameOffset + VarNameSize + GetPadSize (VarNameSize); + VarSize = VarDataOffset + DataSize + GetPadSize (DataSize); + + if (Attributes & EFI_VARIABLE_NON_VOLATILE) { + if ((UINT32) (VarSize +*NonVolatileOffset) > + ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size + ) { + return EFI_OUT_OF_RESOURCES; + } + + NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*NonVolatileOffset + (UINTN) Global->NonVolatileVariableBase); + *NonVolatileOffset = *NonVolatileOffset + VarSize; + } else { + if (EfiAtRuntime ()) { + return EFI_INVALID_PARAMETER; + } + + if ((UINT32) (VarSize +*VolatileOffset) > + ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size + ) { + return EFI_OUT_OF_RESOURCES; + } + + NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*VolatileOffset + (UINTN) Global->VolatileVariableBase); + *VolatileOffset = *VolatileOffset + VarSize; + } + + NextVariable->StartId = VARIABLE_DATA; + NextVariable->Attributes = Attributes; + NextVariable->State = VAR_ADDED; + NextVariable->Reserved = 0; + + // + // There will be pad bytes after Data, the NextVariable->NameSize and + // NextVariable->NameSize should not include pad size so that variable + // service can get actual size in GetVariable + // + NextVariable->NameSize = (UINT32)VarNameSize; + NextVariable->DataSize = (UINT32)DataSize; + + CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID)); + CopyMem ( + (UINT8 *) ((UINTN) NextVariable + VarNameOffset), + VariableName, + VarNameSize + ); + CopyMem ( + (UINT8 *) ((UINTN) NextVariable + VarDataOffset), + Data, + DataSize + ); + + // + // Mark the old variable as deleted + // + if (!EFI_ERROR (Status)) { + Variable.CurrPtr->State &= VAR_DELETED; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +InitializeVariableStore ( + OUT EFI_PHYSICAL_ADDRESS *VariableBase, + OUT UINTN *LastVariableOffset + ) +/*++ + +Routine Description: + This function initializes variable store + +Arguments: + +Returns: + +--*/ +{ + VARIABLE_STORE_HEADER *VariableStore; + + // + // Allocate memory for volatile variable store + // + VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool ( + VARIABLE_STORE_SIZE + ); + if (NULL == VariableStore) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (VariableStore, VARIABLE_STORE_SIZE, 0xff); + + // + // Variable Specific Data + // + *VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore; + *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER); + + VariableStore->Signature = VARIABLE_STORE_SIGNATURE; + VariableStore->Size = VARIABLE_STORE_SIZE; + VariableStore->Format = VARIABLE_STORE_FORMATTED; + VariableStore->State = VARIABLE_STORE_HEALTHY; + VariableStore->Reserved = 0; + VariableStore->Reserved1 = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VariableCommonInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This function does common initialization for variable services + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + + // + // Allocate memory for mVariableModuleGlobal + // + mVariableModuleGlobal = (ESAL_VARIABLE_GLOBAL *) AllocateRuntimePool ( + sizeof (ESAL_VARIABLE_GLOBAL) + ); + if (NULL == mVariableModuleGlobal) { + return EFI_OUT_OF_RESOURCES; + } + // + // Intialize volatile variable store + // + Status = InitializeVariableStore ( + &mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase, + &mVariableModuleGlobal->VolatileLastVariableOffset + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Intialize non volatile variable store + // + Status = InitializeVariableStore ( + &mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase, + &mVariableModuleGlobal->NonVolatileLastVariableOffset + ); + + return Status; +} diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.dxs b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.dxs new file mode 100644 index 0000000000..51c93d7657 --- /dev/null +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.dxs @@ -0,0 +1,25 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EmuVariable.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include "DxeDepex.h" + +DEPENDENCY_START + TRUE +DEPENDENCY_END \ No newline at end of file diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.mbd b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.mbd new file mode 100644 index 0000000000..4cc2c2085d --- /dev/null +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.mbd @@ -0,0 +1,45 @@ + + + + + EmuVariable + CBD2E4D5-7068-4FF5-B866-9822B4AD8D60 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-23 16:05 + + + UefiBootServicesTableLib + BaseMemoryLib + BaseDebugLibReportStatusCode + UefiDriverEntryPoint + EdkDxeRuntimeDriverLib + DxeMemoryAllocationLib + BaseLib + DxeReportStatusCodeLib + + EdkDxeSalLib + + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.msa b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.msa new file mode 100644 index 0000000000..e5142bed73 --- /dev/null +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/EmuVariable.msa @@ -0,0 +1,76 @@ + + + + + EmuVariable + DXE_RUNTIME_DRIVER + RT_DRIVER + CBD2E4D5-7068-4FF5-B866-9822B4AD8D60 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-23 16:05 + + + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + DxeRuntimeDriverLib + UefiDriverEntryPoint + EdkDxeSalLib + UefiBootServicesTableLib + + + EmuVariable.c + EmuVariable.dxs + + InitVariable.c + + + InitVariable.c + + + InitVariable.c + + + Ipf\InitVariable.c + + + + MdePkg + EdkModulePkg + + + VariableWrite + Variable + VariableWrite + Variable + ExtendedSalVariableServices + ExtendedSalBootService + + + + VariableServiceInitialize + + + diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/InitVariable.c b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/InitVariable.c new file mode 100644 index 0000000000..0ad86642ea --- /dev/null +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/InitVariable.c @@ -0,0 +1,185 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + InitVariable.c + +Abstract: + +Revision History + +--*/ + +#include "Variable.h" + +// +// Don't use module globals after the SetVirtualAddress map is signaled +// +extern ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal; + +EFI_STATUS +EFIAPI +RuntimeServiceGetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return GetVariable ( + VariableName, + VendorGuid, + Attributes OPTIONAL, + DataSize, + Data, + &mVariableModuleGlobal->VariableBase[Physical], + mVariableModuleGlobal->FvbInstance + ); +} + +EFI_STATUS +EFIAPI +RuntimeServiceGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return GetNextVariableName ( + VariableNameSize, + VariableName, + VendorGuid, + &mVariableModuleGlobal->VariableBase[Physical], + mVariableModuleGlobal->FvbInstance + ); +} + +EFI_STATUS +EFIAPI +RuntimeServiceSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return SetVariable ( + VariableName, + VendorGuid, + Attributes, + DataSize, + Data, + &mVariableModuleGlobal->VariableBase[Physical], + &mVariableModuleGlobal->VolatileLastVariableOffset, + &mVariableModuleGlobal->NonVolatileLastVariableOffset, + mVariableModuleGlobal->FvbInstance + ); +} + +VOID +EFIAPI +VariableClassAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EfiConvertPointer ( + 0x0, + (VOID **) &mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase + ); + EfiConvertPointer ( + 0x0, + (VOID **) &mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase + ); + EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal); +} + +EFI_STATUS +EFIAPI +VariableServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_HANDLE NewHandle; + EFI_STATUS Status; + + Status = VariableCommonInitialize (ImageHandle, SystemTable); + ASSERT_EFI_ERROR (Status); + + SystemTable->RuntimeServices->GetVariable = RuntimeServiceGetVariable; + SystemTable->RuntimeServices->GetNextVariableName = RuntimeServiceGetNextVariableName; + SystemTable->RuntimeServices->SetVariable = RuntimeServiceSetVariable; + + // + // Now install the Variable Runtime Architectural Protocol on a new handle + // + NewHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &NewHandle, + &gEfiVariableArchProtocolGuid, + NULL, + &gEfiVariableWriteArchProtocolGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Ipf/InitVariable.c b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Ipf/InitVariable.c new file mode 100644 index 0000000000..061e6db73d --- /dev/null +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Ipf/InitVariable.c @@ -0,0 +1,167 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + IpfVariable.c + +Abstract: + +Revision History + +--*/ + +#include "Variable.h" + +// +// Don't use module globals after the SetVirtualAddress map is signaled +// +extern ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal; + +SAL_RETURN_REGS +EsalVariableCommonEntry ( + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + IN SAL_EXTENDED_SAL_PROC ExtendedSalProc, + IN BOOLEAN VirtualMode, + IN ESAL_VARIABLE_GLOBAL *Global + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + SAL_RETURN_REGS ReturnVal; + + switch (FunctionId) { + case EsalGetVariable: + ReturnVal.Status = GetVariable ( + (CHAR16 *) Arg2, + (EFI_GUID *) Arg3, + (UINT32 *) Arg4, + (UINTN *) Arg5, + (VOID *) Arg6, + &Global->VariableBase[VirtualMode], + Global->FvbInstance + ); + return ReturnVal; + + case EsalGetNextVariableName: + ReturnVal.Status = GetNextVariableName ( + (UINTN *) Arg2, + (CHAR16 *) Arg3, + (EFI_GUID *) Arg4, + &Global->VariableBase[VirtualMode], + Global->FvbInstance + ); + return ReturnVal; + + case EsalSetVariable: + ReturnVal.Status = SetVariable ( + (CHAR16 *) Arg2, + (EFI_GUID *) Arg3, + (UINT32) Arg4, + (UINTN) Arg5, + (VOID *) Arg6, + &Global->VariableBase[VirtualMode], + (UINTN *) &Global->VolatileLastVariableOffset, + (UINTN *) &Global->NonVolatileLastVariableOffset, + Global->FvbInstance + ); + return ReturnVal; + + default: + ReturnVal.Status = EFI_SAL_INVALID_ARGUMENT; + return ReturnVal; + } +} + + +VOID +VariableClassAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + CopyMem ( + &mVariableModuleGlobal->VariableBase[Virtual], + &mVariableModuleGlobal->VariableBase[Physical], + sizeof (VARIABLE_GLOBAL) + ); + + EfiConvertPointer ( + 0x0, + (VOID **) &mVariableModuleGlobal->VariableBase[Virtual].NonVolatileVariableBase + ); + EfiConvertPointer ( + 0x0, + (VOID **) &mVariableModuleGlobal->VariableBase[Virtual].VolatileVariableBase + ); + EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal); +} + +EFI_STATUS +VariableServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + + Status = VariableCommonInitialize (ImageHandle, SystemTable); + ASSERT_EFI_ERROR (Status); + + // + // Register All the Functions with Extended Sal. + // + RegisterEsalClass ( + &gEfiExtendedSalVariableServicesProtocolGuid, + mVariableModuleGlobal, + EsalVariableCommonEntry, + EsalGetVariable, + EsalVariableCommonEntry, + EsalGetNextVariableName, + EsalVariableCommonEntry, + EsalSetVariable, + NULL + ); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Variable.h b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Variable.h new file mode 100644 index 0000000000..d1fd5e271e --- /dev/null +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/Variable.h @@ -0,0 +1,143 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Variable.h + +Abstract: + +--*/ + +#ifndef _VARIABLE_H +#define _VARIABLE_H + +// +// Statements that include other header files +// + +// +// BugBug: We need relcate the head file. +// +#include + +#if defined (MDE_CPU_IPF) +#define ALIGNMENT 8 +#else +#define ALIGNMENT 1 +#endif + + +#define VARIABLE_STORE_SIZE (64 * 1024) +#define SCRATCH_SIZE (4 * 1024) + +// +// Define GET_PAD_SIZE to optimize compiler +// +#if ((ALIGNMENT == 0) || (ALIGNMENT == 1)) +#define GET_PAD_SIZE(a) (0) +#else +#define GET_PAD_SIZE(a) (((~a) + 1) & (ALIGNMENT - 1)) +#endif + +#define GET_VARIABLE_NAME_PTR(a) (CHAR16 *) ((UINTN) (a) + sizeof (VARIABLE_HEADER)) + +typedef enum { + Physical, + Virtual +} VARIABLE_POINTER_TYPE; + +typedef struct { + VARIABLE_HEADER *CurrPtr; + VARIABLE_HEADER *EndPtr; + VARIABLE_HEADER *StartPtr; + BOOLEAN Volatile; +} VARIABLE_POINTER_TRACK; + +typedef struct { + EFI_PHYSICAL_ADDRESS VolatileVariableBase; + EFI_PHYSICAL_ADDRESS NonVolatileVariableBase; +} VARIABLE_GLOBAL; + +typedef struct { + VARIABLE_GLOBAL VariableBase[2]; + UINTN VolatileLastVariableOffset; + UINTN NonVolatileLastVariableOffset; + UINT32 FvbInstance; +} ESAL_VARIABLE_GLOBAL; + +// +// Functions +// +EFI_STATUS +EFIAPI +VariableCommonInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +EFI_STATUS +EFIAPI +VariableServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +VOID +EFIAPI +VariableClassAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +EFI_STATUS +EFIAPI +GetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data, + IN VARIABLE_GLOBAL * Global, + IN UINT32 Instance + ) +; + +EFI_STATUS +EFIAPI +GetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid, + IN VARIABLE_GLOBAL *Global, + IN UINT32 Instance + ) +; + +EFI_STATUS +EFIAPI +SetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data, + IN VARIABLE_GLOBAL *Global, + IN UINTN *VolatileOffset, + IN UINTN *NonVolatileOffset, + IN UINT32 Instance + ) +; + +#endif diff --git a/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/build.xml b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/build.xml new file mode 100644 index 0000000000..b2767a2608 --- /dev/null +++ b/EdkModulePkg/Universal/EmuVariable/RuntimeDxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c new file mode 100644 index 0000000000..0d20e88058 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.c @@ -0,0 +1,951 @@ +/*++ + +Copyright (c) 2006, 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. + + +Module Name: + + FtwLite.c + +Abstract: + + This is a simple fault tolerant write driver, based on PlatformFd library. + And it only supports write BufferSize <= SpareAreaLength. + + This boot service only protocol provides fault tolerant write capability for + block devices. The protocol has internal non-volatile intermediate storage + of the data and private information. It should be able to recover + automatically from a critical fault, such as power failure. + +Notes: + + The implementation uses an FTW Lite (Fault Tolerant Write) Work Space. + This work space is a memory copy of the work space on the Woring Block, + the size of the work space is the FTW_WORK_SPACE_SIZE bytes. + +--*/ + +#include + +// +// In write function, we should check the target range to prevent the user +// from writing Spare block and Working space directly. +// +// +// Fault Tolerant Write Protocol API +// +EFI_STATUS +EFIAPI +FtwLiteWrite ( + IN EFI_FTW_LITE_PROTOCOL *This, + IN EFI_HANDLE FvbHandle, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN VOID *Buffer + ) +/*++ + +Routine Description: + Starts a target block update. This function will record data about write + in fault tolerant storage and will complete the write in a recoverable + manner, ensuring at all times that either the original contents or + the modified contents are available. + +Arguments: + This - Calling context + FvbHandle - The handle of FVB protocol that provides services for + reading, writing, and erasing the target block. + Lba - The logical block address of the target block. + Offset - The offset within the target block to place the data. + NumBytes - The number of bytes to write to the target block. + Buffer - The data to write. + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_BAD_BUFFER_SIZE - The write would span a target block, which is not + a valid action. + EFI_ACCESS_DENIED - No writes have been allocated. + EFI_NOT_FOUND - Cannot find FVB by handle. + EFI_OUT_OF_RESOURCES - Cannot allocate memory. + EFI_ABORTED - The function could not complete successfully. + +--*/ +{ + EFI_STATUS Status; + EFI_FTW_LITE_DEVICE *FtwLiteDevice; + EFI_FTW_LITE_RECORD *Record; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_PHYSICAL_ADDRESS FvbPhysicalAddress; + UINTN MyLength; + UINTN MyOffset; + UINTN MyBufferSize; + UINT8 *MyBuffer; + UINTN SpareBufferSize; + UINT8 *SpareBuffer; + UINTN Index; + UINT8 *Ptr; + EFI_DEV_PATH_PTR DevPtr; + + // + // Refresh work space and get last record + // + FtwLiteDevice = FTW_LITE_CONTEXT_FROM_THIS (This); + Status = WorkSpaceRefresh (FtwLiteDevice); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + + Record = FtwLiteDevice->FtwLastRecord; + + // + // Check the flags of last write record + // + if ((Record->WriteAllocated == FTW_VALID_STATE) || (Record->SpareCompleted == FTW_VALID_STATE)) { + return EFI_ACCESS_DENIED; + } + // + // IF former record has completed, THEN use next record + // + if (Record->WriteCompleted == FTW_VALID_STATE) { + Record++; + FtwLiteDevice->FtwLastRecord = Record; + } + + MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace; + + // + // Check if the input data can fit within the target block + // + if ((Offset +*NumBytes) > FtwLiteDevice->SpareAreaLength) { + return EFI_BAD_BUFFER_SIZE; + } + // + // Check if there is enough free space for allocate a record + // + if ((MyOffset + WRITE_TOTAL_SIZE) > FtwLiteDevice->FtwWorkSpaceSize) { + Status = FtwReclaimWorkSpace (FtwLiteDevice); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FtwLite: Reclaim work space - %r", Status)); + return EFI_ABORTED; + } + } + // + // Get the FVB protocol by handle + // + Status = FtwGetFvbByHandle (FvbHandle, &Fvb); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + // + // Allocate a write record in workspace. + // Update Header->WriteAllocated as VALID + // + Status = FtwUpdateFvState ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkSpaceLba, + FtwLiteDevice->FtwWorkSpaceBase + MyOffset, + WRITE_ALLOCATED + ); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Allocate record - %r\n", Status)); + return EFI_ABORTED; + } + + Record->WriteAllocated = FTW_VALID_STATE; + + // + // Prepare data of write record, filling DevPath with memory mapped address. + // + DevPtr.MemMap = (MEMMAP_DEVICE_PATH *) &Record->DevPath; + DevPtr.MemMap->Header.Type = HARDWARE_DEVICE_PATH; + DevPtr.MemMap->Header.SubType = HW_MEMMAP_DP; + SetDevicePathNodeLength (&DevPtr.MemMap->Header, sizeof (MEMMAP_DEVICE_PATH)); + + Status = Fvb->GetPhysicalAddress (Fvb, &FvbPhysicalAddress); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Get FVB physical address - %r\n", Status)); + return EFI_ABORTED; + } + + DevPtr.MemMap->MemoryType = EfiMemoryMappedIO; + DevPtr.MemMap->StartingAddress = FvbPhysicalAddress; + DevPtr.MemMap->EndingAddress = FvbPhysicalAddress +*NumBytes; + // + // ignored! + // + Record->Lba = Lba; + Record->Offset = Offset; + Record->NumBytes = *NumBytes; + + // + // Write the record to the work space. + // + MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace; + MyLength = FTW_LITE_RECORD_SIZE; + + Status = FtwLiteDevice->FtwFvBlock->Write ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkSpaceLba, + FtwLiteDevice->FtwWorkSpaceBase + MyOffset, + &MyLength, + (UINT8 *) Record + ); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Record has been written to working block, then write data. + // + // + // Allocate a memory buffer + // + MyBufferSize = FtwLiteDevice->SpareAreaLength; + MyBuffer = AllocatePool (MyBufferSize); + if (MyBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Starting at Lba, if the number of the rest blocks on Fvb is less + // than NumberOfSpareBlock. + // + // + // Read all original data from target block to memory buffer + // + if (IsInWorkingBlock (FtwLiteDevice, Fvb, Lba)) { + // + // If target block falls into working block, we must follow the process of + // updating working block. + // + Ptr = MyBuffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + MyLength = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwFvBlock->Read ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkBlockLba + Index, + 0, + &MyLength, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (MyBuffer); + return EFI_ABORTED; + } + + Ptr += MyLength; + } + // + // Update Offset by adding the offset from the start LBA of working block to + // the target LBA. The target block can not span working block! + // + Offset = (((UINTN) (Lba - FtwLiteDevice->FtwWorkBlockLba)) * FtwLiteDevice->SizeOfSpareBlock + Offset); + ASSERT ((Offset +*NumBytes) <= FtwLiteDevice->SpareAreaLength); + + } else { + + Ptr = MyBuffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + MyLength = FtwLiteDevice->SizeOfSpareBlock; + Status = Fvb->Read (Fvb, Lba + Index, 0, &MyLength, Ptr); + if (EFI_ERROR (Status)) { + gBS->FreePool (MyBuffer); + return EFI_ABORTED; + } + + Ptr += MyLength; + } + } + // + // Overwrite the updating range data with + // the input buffer content + // + CopyMem (MyBuffer + Offset, Buffer, *NumBytes); + + // + // Try to keep the content of spare block + // Save spare block into a spare backup memory buffer (Sparebuffer) + // + SpareBufferSize = FtwLiteDevice->SpareAreaLength; + SpareBuffer = AllocatePool (SpareBufferSize); + if (SpareBuffer == NULL) { + gBS->FreePool (MyBuffer); + return EFI_OUT_OF_RESOURCES; + } + + Ptr = SpareBuffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + MyLength = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwBackupFvb->Read ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + Index, + 0, + &MyLength, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (MyBuffer); + gBS->FreePool (SpareBuffer); + return EFI_ABORTED; + } + + Ptr += MyLength; + } + // + // Write the memory buffer to spare block + // Don't forget to erase Flash first. + // + Status = FtwEraseSpareBlock (FtwLiteDevice); + Ptr = MyBuffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + MyLength = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwBackupFvb->Write ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + Index, + 0, + &MyLength, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (MyBuffer); + gBS->FreePool (SpareBuffer); + return EFI_ABORTED; + } + + Ptr += MyLength; + } + // + // Free MyBuffer + // + gBS->FreePool (MyBuffer); + + // + // Set the SpareCompleteD in the FTW record, + // + MyOffset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace; + Status = FtwUpdateFvState ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkSpaceLba, + FtwLiteDevice->FtwWorkSpaceBase + MyOffset, + SPARE_COMPLETED + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (SpareBuffer); + return EFI_ABORTED; + } + + Record->SpareCompleted = FTW_VALID_STATE; + + // + // Since the content has already backuped in spare block, the write is + // guaranteed to be completed with fault tolerant manner. + // + Status = FtwWriteRecord (FtwLiteDevice, Fvb); + if (EFI_ERROR (Status)) { + gBS->FreePool (SpareBuffer); + return EFI_ABORTED; + } + + Record++; + FtwLiteDevice->FtwLastRecord = Record; + + // + // Restore spare backup buffer into spare block , if no failure happened during FtwWrite. + // + Status = FtwEraseSpareBlock (FtwLiteDevice); + Ptr = SpareBuffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + MyLength = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwBackupFvb->Write ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + Index, + 0, + &MyLength, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (SpareBuffer); + return EFI_ABORTED; + } + + Ptr += MyLength; + } + // + // All success. + // + gBS->FreePool (SpareBuffer); + + DEBUG ( + (EFI_D_FTW_LITE, + "FtwLite: Write() success, (Lba:Offset)=(%lx:0x%x), NumBytes: 0x%x\n", + Lba, + Offset, + *NumBytes) + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FtwWriteRecord ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb + ) +/*++ + +Routine Description: + Write a record with fault tolerant mannaer. + Since the content has already backuped in spare block, the write is + guaranteed to be completed with fault tolerant manner. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + Fvb - The FVB protocol that provides services for + reading, writing, and erasing the target block. + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully + +--*/ +{ + EFI_STATUS Status; + EFI_FTW_LITE_RECORD *Record; + EFI_LBA WorkSpaceLbaOffset; + UINTN Offset; + + // + // Spare Complete but Destination not complete, + // Recover the targt block with the spare block. + // + Record = FtwLiteDevice->FtwLastRecord; + + // + // IF target block is working block, THEN Flush Spare Block To Working Block; + // ELSE IF target block is boot block, THEN Flush Spare Block To boot Block; + // ELSE flush spare block to normal target block.ENDIF + // + if (IsInWorkingBlock (FtwLiteDevice, Fvb, Record->Lba)) { + // + // If target block is working block, Attention: + // it's required to set SPARE_COMPLETED to spare block. + // + WorkSpaceLbaOffset = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba; + Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace; + Status = FtwUpdateFvState ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + WorkSpaceLbaOffset, + FtwLiteDevice->FtwWorkSpaceBase + Offset, + SPARE_COMPLETED + ); + ASSERT_EFI_ERROR (Status); + + Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice); + } else if (IsBootBlock (FtwLiteDevice, Fvb, Record->Lba)) { + // + // Update boot block + // + Status = FlushSpareBlockToBootBlock (FtwLiteDevice); + } else { + // + // Update blocks other than working block or boot block + // + Status = FlushSpareBlockToTargetBlock (FtwLiteDevice, Fvb, Record->Lba); + } + + ASSERT_EFI_ERROR (Status); + + // + // Set WriteCompleted flag in record + // + Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace; + Status = FtwUpdateFvState ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkSpaceLba, + FtwLiteDevice->FtwWorkSpaceBase + Offset, + WRITE_COMPLETED + ); + ASSERT_EFI_ERROR (Status); + + Record->WriteCompleted = FTW_VALID_STATE; + return EFI_SUCCESS; +} + + +EFI_STATUS +FtwRestart ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Restarts a previously interrupted write. The caller must provide the + block protocol needed to complete the interrupted write. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + FvbHandle - The handle of FVB protocol that provides services for + reading, writing, and erasing the target block. + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ACCESS_DENIED - No pending writes exist + EFI_NOT_FOUND - FVB protocol not found by the handle + EFI_ABORTED - The function could not complete successfully + +--*/ +{ + EFI_STATUS Status; + EFI_FTW_LITE_RECORD *Record; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_DEV_PATH_PTR DevPathPtr; + + // + // Spare Completed but Destination not complete, + // Recover the targt block with the spare block. + // + Record = FtwLiteDevice->FtwLastRecord; + + // + // Only support memory mapped FVB device path by now. + // + DevPathPtr.MemMap = (MEMMAP_DEVICE_PATH *) &Record->DevPath; + if (!((DevPathPtr.MemMap->Header.Type == HARDWARE_DEVICE_PATH) && (DevPathPtr.MemMap->Header.SubType == HW_MEMMAP_DP)) + ) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Device Path is not memory mapped\n")); + return EFI_ABORTED; + } + + Status = GetFvbByAddress (DevPathPtr.MemMap->StartingAddress, &Fvb); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + // + // Since the content has already backuped in spare block, the write is + // guaranteed to be completed with fault tolerant manner. + // + Status = FtwWriteRecord (FtwLiteDevice, Fvb); + DEBUG ((EFI_D_FTW_INFO, "FtwLite: Restart() - %r\n", Status)); + + Record++; + FtwLiteDevice->FtwLastRecord = Record; + + // + // Erase Spare block + // This is restart, no need to keep spareblock content. + // + FtwEraseSpareBlock (FtwLiteDevice); + + return Status; +} + + +EFI_STATUS +FtwAbort ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Aborts all previous allocated writes. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully. + EFI_NOT_FOUND - No allocated writes exist. + +--*/ +{ + EFI_STATUS Status; + UINTN Offset; + + if (FtwLiteDevice->FtwLastRecord->WriteCompleted == FTW_VALID_STATE) { + return EFI_NOT_FOUND; + } + // + // Update the complete state of the header as VALID and abort. + // + Offset = (UINT8 *) FtwLiteDevice->FtwLastRecord - FtwLiteDevice->FtwWorkSpace; + Status = FtwUpdateFvState ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkSpaceLba, + FtwLiteDevice->FtwWorkSpaceBase + Offset, + WRITE_COMPLETED + ); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + + FtwLiteDevice->FtwLastRecord->WriteCompleted = FTW_VALID_STATE; + + Status = FtwGetLastRecord (FtwLiteDevice, &FtwLiteDevice->FtwLastRecord); + + // + // Erase the spare block + // + Status = FtwEraseSpareBlock (FtwLiteDevice); + + DEBUG ((EFI_D_FTW_INFO, "FtwLite: Abort() success \n")); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +InitializeFtwLite ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + Routine Description: + This function is the entry point of the Fault Tolerant Write driver. + + Arguments: + ImageHandle - EFI_HANDLE: A handle for the image that is initializing + this driver + SystemTable - EFI_SYSTEM_TABLE: A pointer to the EFI system table + + Returns: + EFI_SUCCESS - FTW has finished the initialization + EFI_ABORTED - FTW initialization error + +--*/ +{ + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + UINTN Index; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_FTW_LITE_DEVICE *FtwLiteDevice; + EFI_FTW_LITE_RECORD *Record; + UINTN Length; + EFI_STATUS Status; + UINTN Offset; + EFI_FLASH_MAP_ENTRY_DATA *FlashMapEntry; + EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry; + UINT32 LbaIndex; + EFI_PEI_HOB_POINTERS GuidHob; + + // + // Allocate Private data of this driver, + // INCLUDING THE FtwWorkSpace[FTW_WORK_SPACE_SIZE]. + // + FtwLiteDevice = NULL; + FtwLiteDevice = AllocatePool (sizeof (EFI_FTW_LITE_DEVICE) + FTW_WORK_SPACE_SIZE); + if (FtwLiteDevice != NULL) { + Status = EFI_SUCCESS; + } else { + Status = EFI_OUT_OF_RESOURCES; + } + + ASSERT_EFI_ERROR (Status); + + ZeroMem (FtwLiteDevice, sizeof (EFI_FTW_LITE_DEVICE)); + FtwLiteDevice->Signature = FTW_LITE_DEVICE_SIGNATURE; + + // + // Initialize other parameters, and set WorkSpace as FTW_ERASED_BYTE. + // + FtwLiteDevice->FtwWorkSpace = (UINT8 *) (FtwLiteDevice + 1); + FtwLiteDevice->FtwWorkSpaceSize = FTW_WORK_SPACE_SIZE; + SetMem ( + FtwLiteDevice->FtwWorkSpace, + FtwLiteDevice->FtwWorkSpaceSize, + FTW_ERASED_BYTE + ); + FtwLiteDevice->FtwWorkSpaceHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FtwLiteDevice->FtwWorkSpace; + + FtwLiteDevice->FtwLastRecord = NULL; + + FtwLiteDevice->SpareAreaLength = 0; + FtwLiteDevice->WorkSpaceLength = 0; + + GuidHob.Raw = GetHobList (); + while (NULL != (GuidHob.Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, GuidHob.Raw))) { + FlashMapEntry = (EFI_FLASH_MAP_ENTRY_DATA *) GET_GUID_HOB_DATA (GuidHob.Guid); + // + // Get the FTW work space Flash Map SUB area + // + if ((FlashMapEntry->AreaType == EFI_FLASH_AREA_FTW_STATE) && (FlashMapEntry->NumEntries == 1)) { + FtwLiteDevice->WorkSpaceAddress = FlashMapEntry->Entries[0].Base; + FtwLiteDevice->WorkSpaceLength = (UINTN) FlashMapEntry->Entries[0].Length; + } + // + // Get the FTW backup SUB area + // + if ((FlashMapEntry->AreaType == EFI_FLASH_AREA_FTW_BACKUP) && (FlashMapEntry->NumEntries == 1)) { + FtwLiteDevice->SpareAreaAddress = FlashMapEntry->Entries[0].Base; + FtwLiteDevice->SpareAreaLength = (UINTN) FlashMapEntry->Entries[0].Length; + } + + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + + ASSERT ((FtwLiteDevice->WorkSpaceLength != 0) && (FtwLiteDevice->SpareAreaLength != 0)); + + // + // Locate FVB protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeBlockProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + ASSERT_EFI_ERROR (Status); + + ASSERT (HandleCount > 0); + + FtwLiteDevice->FtwFvBlock = NULL; + FtwLiteDevice->FtwBackupFvb = NULL; + FtwLiteDevice->FtwWorkSpaceLba = (EFI_LBA) (-1); + FtwLiteDevice->FtwSpareLba = (EFI_LBA) (-1); + for (Index = 0; Index < HandleCount; Index += 1) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &Fvb + ); + ASSERT_EFI_ERROR (Status); + + Status = Fvb->GetPhysicalAddress (Fvb, &BaseAddress); + if (EFI_ERROR (Status)) { + continue; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) BaseAddress); + + if ((FtwLiteDevice->WorkSpaceAddress >= BaseAddress) && + (FtwLiteDevice->WorkSpaceAddress <= (BaseAddress + FwVolHeader->FvLength)) + ) { + FtwLiteDevice->FtwFvBlock = Fvb; + // + // To get the LBA of work space + // + if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) { + // + // FV may have multiple types of BlockLength + // + FvbMapEntry = &FwVolHeader->FvBlockMap[0]; + while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->BlockLength == 0))) { + for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) { + if (FtwLiteDevice->WorkSpaceAddress < (BaseAddress + FvbMapEntry->BlockLength * LbaIndex)) { + FtwLiteDevice->FtwWorkSpaceLba = LbaIndex - 1; + // + // Get the Work space size and Base(Offset) + // + FtwLiteDevice->FtwWorkSpaceSize = FtwLiteDevice->WorkSpaceLength; + FtwLiteDevice->FtwWorkSpaceBase = (UINTN) (FtwLiteDevice->WorkSpaceAddress - (BaseAddress + FvbMapEntry->BlockLength * (LbaIndex - 1))); + break; + } + } + // + // end for + // + FvbMapEntry++; + } + // + // end while + // + } + } + + if ((FtwLiteDevice->SpareAreaAddress >= BaseAddress) && + (FtwLiteDevice->SpareAreaAddress <= (BaseAddress + FwVolHeader->FvLength)) + ) { + FtwLiteDevice->FtwBackupFvb = Fvb; + // + // To get the LBA of spare + // + if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) { + // + // FV may have multiple types of BlockLength + // + FvbMapEntry = &FwVolHeader->FvBlockMap[0]; + while (!((FvbMapEntry->NumBlocks == 0) && (FvbMapEntry->BlockLength == 0))) { + for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) { + if (FtwLiteDevice->SpareAreaAddress < (BaseAddress + FvbMapEntry->BlockLength * LbaIndex)) { + // + // Get the NumberOfSpareBlock and SizeOfSpareBlock + // + FtwLiteDevice->FtwSpareLba = LbaIndex - 1; + FtwLiteDevice->SizeOfSpareBlock = FvbMapEntry->BlockLength; + FtwLiteDevice->NumberOfSpareBlock = FtwLiteDevice->SpareAreaLength / FtwLiteDevice->SizeOfSpareBlock; + // + // Check the range of spare area to make sure that it's in FV range + // + ASSERT ((FtwLiteDevice->FtwSpareLba + FtwLiteDevice->NumberOfSpareBlock) <= FvbMapEntry->NumBlocks); + break; + } + } + + FvbMapEntry++; + } + // + // end while + // + } + } + } + // + // Calculate the start LBA of working block. Working block is an area which + // contains working space in its last block and has the same size as spare + // block, unless there are not enough blocks before the block that contains + // working space. + // + FtwLiteDevice->FtwWorkBlockLba = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->NumberOfSpareBlock + 1; + if ((INT64) (FtwLiteDevice->FtwWorkBlockLba) < 0) { + FtwLiteDevice->FtwWorkBlockLba = 0; + } + + if ((FtwLiteDevice->FtwFvBlock == NULL) || + (FtwLiteDevice->FtwBackupFvb == NULL) || + (FtwLiteDevice->FtwWorkSpaceLba == (EFI_LBA) (-1)) || + (FtwLiteDevice->FtwSpareLba == (EFI_LBA) (-1)) + ) { + DEBUG ((EFI_D_ERROR, "FtwLite: Working or spare FVB not ready\n")); + ASSERT_EFI_ERROR (Status); + } + // + // Refresh workspace data from working block + // + Status = WorkSpaceRefresh (FtwLiteDevice); + ASSERT_EFI_ERROR (Status); + + // + // If the working block workspace is not valid, try the spare block + // + if (!IsValidWorkSpace (FtwLiteDevice->FtwWorkSpaceHeader)) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace invalid, read from backup\n")); + // + // Read from spare block + // + Length = FtwLiteDevice->FtwWorkSpaceSize; + Status = FtwLiteDevice->FtwBackupFvb->Read ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba, + FtwLiteDevice->FtwWorkSpaceBase, + &Length, + FtwLiteDevice->FtwWorkSpace + ); + ASSERT_EFI_ERROR (Status); + + // + // If spare block is valid, then replace working block content. + // + if (IsValidWorkSpace (FtwLiteDevice->FtwWorkSpaceHeader)) { + Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice); + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Restart working block in Init() - %r\n", Status)); + ASSERT_EFI_ERROR (Status); + + FtwAbort (FtwLiteDevice); + // + // Refresh work space. + // + Status = WorkSpaceRefresh (FtwLiteDevice); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + } else { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Both are invalid, init workspace\n")); + // + // If both are invalid, then initialize work space. + // + SetMem ( + FtwLiteDevice->FtwWorkSpace, + FtwLiteDevice->FtwWorkSpaceSize, + FTW_ERASED_BYTE + ); + InitWorkSpaceHeader (FtwLiteDevice->FtwWorkSpaceHeader); + // + // Write to work space on the working block + // + Length = FtwLiteDevice->FtwWorkSpaceSize; + Status = FtwLiteDevice->FtwFvBlock->Write ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkSpaceLba, + FtwLiteDevice->FtwWorkSpaceBase, + &Length, + FtwLiteDevice->FtwWorkSpace + ); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + } + } + // + // Hook the protocol API + // + FtwLiteDevice->FtwLiteInstance.Write = FtwLiteWrite; + + // + // Install protocol interface + // + Status = gBS->InstallProtocolInterface ( + &FtwLiteDevice->Handle, + &gEfiFaultTolerantWriteLiteProtocolGuid, + EFI_NATIVE_INTERFACE, + &FtwLiteDevice->FtwLiteInstance + ); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // If (!SpareCompleted) THEN Abort to rollback. + // + if ((FtwLiteDevice->FtwLastRecord->WriteAllocated == FTW_VALID_STATE) && + (FtwLiteDevice->FtwLastRecord->SpareCompleted != FTW_VALID_STATE) + ) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Init.. record not SpareCompleted, abort()\n")); + FtwAbort (FtwLiteDevice); + } + // + // if (SpareCompleted) THEN Restart to fault tolerant write. + // + if ((FtwLiteDevice->FtwLastRecord->SpareCompleted == FTW_VALID_STATE) && + (FtwLiteDevice->FtwLastRecord->WriteCompleted != FTW_VALID_STATE) + ) { + + Status = FtwRestart (FtwLiteDevice); + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Restart last write - %r\n", Status)); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // To check the workspace buffer behind last records is EMPTY or not. + // If it's not EMPTY, FTW_LITE also need to call reclaim(). + // + Record = FtwLiteDevice->FtwLastRecord; + Offset = (UINT8 *) Record - FtwLiteDevice->FtwWorkSpace; + if (FtwLiteDevice->FtwWorkSpace[Offset] != FTW_ERASED_BYTE) { + Offset += WRITE_TOTAL_SIZE; + } + + if (!IsErasedFlashBuffer ( + FTW_ERASE_POLARITY, + FtwLiteDevice->FtwWorkSpace + Offset, + FtwLiteDevice->FtwWorkSpaceSize - Offset + )) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace is dirty, call reclaim...\n")); + Status = FtwReclaimWorkSpace (FtwLiteDevice); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Workspace reclaim - %r\n", Status)); + return EFI_ABORTED; + } + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs new file mode 100644 index 0000000000..f2a6221b5d --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + + +Module Name: + + FtwLite.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + + +DEPENDENCY_START + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID AND EFI_ALTERNATE_FV_BLOCK_GUID +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h new file mode 100644 index 0000000000..8754827e2d --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.h @@ -0,0 +1,675 @@ +/*++ + +Copyright (c) 2006, 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. + + +Module Name: + + FtwLite.h + +Abstract: + + This is a simple fault tolerant write driver, based on PlatformFd library. + And it only supports write BufferSize <= SpareAreaLength. + + This boot service only protocol provides fault tolerant write capability for + block devices. The protocol has internal non-volatile intermediate storage + of the data and private information. It should be able to recover + automatically from a critical fault, such as power failure. + +--*/ + +#ifndef _EFI_FAULT_TOLERANT_WRITE_LITE_H_ +#define _EFI_FAULT_TOLERANT_WRITE_LITE_H_ + +#include +#include + +#define EFI_D_FTW_LITE EFI_D_ERROR +#define EFI_D_FTW_INFO EFI_D_INFO + +// +// Flash erase polarity is 1 +// +#define FTW_ERASE_POLARITY 1 + +#define FTW_VALID_STATE 0 +#define FTW_INVALID_STATE 1 + +#define FTW_ERASED_BYTE ((UINT8) (255)) +#define FTW_POLARITY_REVERT ((UINT8) (255)) + +typedef struct { + UINT8 WriteAllocated : 1; + UINT8 SpareCompleted : 1; + UINT8 WriteCompleted : 1; + UINT8 Reserved : 5; +#define WRITE_ALLOCATED 0x1 +#define SPARE_COMPLETED 0x2 +#define WRITE_COMPLETED 0x4 + + EFI_DEV_PATH DevPath; + EFI_LBA Lba; + UINTN Offset; + UINTN NumBytes; + // + // UINTN SpareAreaOffset; + // +} EFI_FTW_LITE_RECORD; + +#define FTW_LITE_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('F', 'T', 'W', 'L') + +// +// MACRO for Block size. +// Flash Erasing will do in block granularity. +// +#ifdef FV_BLOCK_SIZE +#define FTW_BLOCK_SIZE FV_BLOCK_SIZE +#else +#define FV_BLOCK_SIZE 0x10000 +#define FTW_BLOCK_SIZE FV_BLOCK_SIZE +#endif +// +// MACRO for FTW WORK SPACE Base & Size +// +#ifdef EFI_FTW_WORKING_OFFSET +#define FTW_WORK_SPACE_BASE EFI_FTW_WORKING_OFFSET +#else +#define FTW_WORK_SPACE_BASE 0x00E000 +#endif + +#ifdef EFI_FTW_WORKING_LENGTH +#define FTW_WORK_SPACE_SIZE EFI_FTW_WORKING_LENGTH +#else +#define FTW_WORK_SPACE_SIZE 0x002000 +#endif +// +// MACRO for FTW header and record +// +#define FTW_WORKING_QUEUE_SIZE (FTW_WORK_SPACE_SIZE - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER)) +#define FTW_LITE_RECORD_SIZE (sizeof (EFI_FTW_LITE_RECORD)) +#define WRITE_TOTAL_SIZE FTW_LITE_RECORD_SIZE + +// +// EFI Fault tolerant protocol private data structure +// +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + EFI_FTW_LITE_PROTOCOL FtwLiteInstance; + EFI_PHYSICAL_ADDRESS WorkSpaceAddress; + UINTN WorkSpaceLength; + EFI_PHYSICAL_ADDRESS SpareAreaAddress; + UINTN SpareAreaLength; + UINTN NumberOfSpareBlock; // Number of the blocks in spare block + UINTN SizeOfSpareBlock; // Block size in bytes of the blocks in spare block + EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FtwWorkSpaceHeader; + EFI_FTW_LITE_RECORD *FtwLastRecord; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FtwFvBlock; // FVB of working block + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FtwBackupFvb; // FVB of spare block + EFI_LBA FtwSpareLba; + EFI_LBA FtwWorkBlockLba; // Start LBA of working block + EFI_LBA FtwWorkSpaceLba; // Start LBA of working space + UINTN FtwWorkSpaceBase; // Offset from LBA start addr + UINTN FtwWorkSpaceSize; + UINT8 *FtwWorkSpace; + // + // Following a buffer of FtwWorkSpace[FTW_WORK_SPACE_SIZE], + // Allocated with EFI_FTW_LITE_DEVICE. + // +} EFI_FTW_LITE_DEVICE; + +#define FTW_LITE_CONTEXT_FROM_THIS(a) CR (a, EFI_FTW_LITE_DEVICE, FtwLiteInstance, FTW_LITE_DEVICE_SIGNATURE) + +// +// Driver entry point +// +EFI_STATUS +EFIAPI +InitializeFtwLite ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This function is the entry point of the Fault Tolerant Write driver. + +Arguments: + ImageHandle - EFI_HANDLE: A handle for the image that is initializing + this driver + SystemTable - EFI_SYSTEM_TABLE: A pointer to the EFI system table + +Returns: + EFI_SUCCESS - FTW has finished the initialization + EFI_ABORTED - FTW initialization error + +--*/ +; + +// +// Fault Tolerant Write Protocol API +// +EFI_STATUS +EFIAPI +FtwLiteWrite ( + IN EFI_FTW_LITE_PROTOCOL *This, + IN EFI_HANDLE FvbHandle, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINTN *NumBytes, + IN VOID *Buffer + ) +/*++ + +Routine Description: + Starts a target block update. This function will record data about write + in fault tolerant storage and will complete the write in a recoverable + manner, ensuring at all times that either the original contents or + the modified contents are available. + +Arguments: + This - Calling context + FvbHandle - The handle of FVB protocol that provides services for + reading, writing, and erasing the target block. + Lba - The logical block address of the target block. + Offset - The offset within the target block to place the data. + NumBytes - The number of bytes to write to the target block. + Buffer - The data to write. + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_BAD_BUFFER_SIZE - The write would span a target block, which is not + a valid action. + EFI_ACCESS_DENIED - No writes have been allocated. + EFI_NOT_FOUND - Cannot find FVB by handle. + EFI_OUT_OF_RESOURCES - Cannot allocate memory. + EFI_ABORTED - The function could not complete successfully. + +--*/ +; + +// +// Internal functions +// +EFI_STATUS +FtwRestart ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Restarts a previously interrupted write. The caller must provide the + block protocol needed to complete the interrupted write. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + FvbHandle - The handle of FVB protocol that provides services for + reading, writing, and erasing the target block. + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ACCESS_DENIED - No pending writes exist + EFI_NOT_FOUND - FVB protocol not found by the handle + EFI_ABORTED - The function could not complete successfully + +--*/ +; + +EFI_STATUS +FtwAbort ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Aborts all previous allocated writes. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully. + EFI_NOT_FOUND - No allocated writes exist. + +--*/ +; + + +EFI_STATUS +FtwWriteRecord ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb + ) +/*++ + +Routine Description: + Write a record with fault tolerant mannaer. + Since the content has already backuped in spare block, the write is + guaranteed to be completed with fault tolerant manner. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + Fvb - The FVB protocol that provides services for + reading, writing, and erasing the target block. + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully + +--*/ +; + +EFI_STATUS +FtwEraseBlock ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + EFI_LBA Lba + ) +/*++ + +Routine Description: + To Erase one block. The size is FTW_BLOCK_SIZE + +Arguments: + FtwLiteDevice - Calling context + FvBlock - FVB Protocol interface + Lba - Lba of the firmware block + +Returns: + EFI_SUCCESS - Block LBA is Erased successfully + Others - Error occurs + +--*/ +; + +EFI_STATUS +FtwEraseSpareBlock ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + + Erase spare block. + +Arguments: + + FtwLiteDevice - Calling context + +Returns: + + Status code + +--*/ +; + +EFI_STATUS +FtwGetFvbByHandle ( + IN EFI_HANDLE FvBlockHandle, + OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock + ) +/*++ + +Routine Description: + Retrive the proper FVB protocol interface by HANDLE. + +Arguments: + FvBlockHandle - The handle of FVB protocol that provides services for + reading, writing, and erasing the target block. + FvBlock - The interface of FVB protocol + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully +--*/ +; + +EFI_STATUS +GetFvbByAddress ( + IN EFI_PHYSICAL_ADDRESS Address, + OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock + ) +/*++ + +Routine Description: + + Get firmware block by address. + +Arguments: + + Address - Address specified the block + FvBlock - The block caller wanted + +Returns: + + Status code + + EFI_NOT_FOUND - Block not found + +--*/ +; + +BOOLEAN +IsInWorkingBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice, + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + EFI_LBA Lba + ) +/*++ + +Routine Description: + + Is it in working block? + +Arguments: + + FtwLiteDevice - Calling context + FvBlock - Fvb protocol instance + Lba - The block specified + +Returns: + + In working block or not + +--*/ +; + +BOOLEAN +IsBootBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice, + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + EFI_LBA Lba + ) +/*++ + +Routine Description: + + Check whether the block is a boot block. + +Arguments: + + FtwLiteDevice - Calling context + FvBlock - Fvb protocol instance + Lba - Lba value + +Returns: + + Is a boot block or not + +--*/ +; + +EFI_STATUS +FlushSpareBlockToTargetBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice, + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + EFI_LBA Lba + ) +/*++ + +Routine Description: + Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE. + Spare block is accessed by FTW backup FVB protocol interface. LBA is + FtwLiteDevice->FtwSpareLba. + Target block is accessed by FvBlock protocol interface. LBA is Lba. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + FvBlock - FVB Protocol interface to access target block + Lba - Lba of the target block + +Returns: + EFI_SUCCESS - Spare block content is copied to target block + EFI_INVALID_PARAMETER - Input parameter error + EFI_OUT_OF_RESOURCES - Allocate memory error + EFI_ABORTED - The function could not complete successfully + +--*/ +; + +EFI_STATUS +FlushSpareBlockToWorkingBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE. + Spare block is accessed by FTW backup FVB protocol interface. LBA is + FtwLiteDevice->FtwSpareLba. + Working block is accessed by FTW working FVB protocol interface. LBA is + FtwLiteDevice->FtwWorkBlockLba. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + +Returns: + EFI_SUCCESS - Spare block content is copied to target block + EFI_OUT_OF_RESOURCES - Allocate memory error + EFI_ABORTED - The function could not complete successfully + +Notes: + Since the working block header is important when FTW initializes, the + state of the operation should be handled carefully. The Crc value is + calculated without STATE element. + +--*/ +; + +EFI_STATUS +FlushSpareBlockToBootBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE. + Spare block is accessed by FTW backup FVB protocol interface. LBA is + FtwLiteDevice->FtwSpareLba. + Boot block is accessed by BootFvb protocol interface. LBA is 0. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + +Returns: + EFI_SUCCESS - Spare block content is copied to boot block + EFI_INVALID_PARAMETER - Input parameter error + EFI_OUT_OF_RESOURCES - Allocate memory error + EFI_ABORTED - The function could not complete successfully + +Notes: + +--*/ +; + +EFI_STATUS +FtwUpdateFvState ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINT8 NewBit + ) +/*++ + +Routine Description: + Update a bit of state on a block device. The location of the bit is + calculated by the (Lba, Offset, bit). Here bit is determined by the + the name of a certain bit. + +Arguments: + FvBlock - FVB Protocol interface to access SrcBlock and DestBlock + Lba - Lba of a block + Offset - Offset on the Lba + NewBit - New value that will override the old value if it can be change + +Returns: + EFI_SUCCESS - A state bit has been updated successfully + Others - Access block device error. + +Notes: + Assume all bits of State are inside the same BYTE. + + EFI_ABORTED - Read block fail +--*/ +; + +EFI_STATUS +FtwGetLastRecord ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + OUT EFI_FTW_LITE_RECORD **FtwLastRecord + ) +/*++ + +Routine Description: + Get the last Write record pointer. + The last record is the record whose 'complete' state hasn't been set. + After all, this header may be a EMPTY header entry for next Allocate. + +Arguments: + FtwLiteDevice - Private data of this driver + FtwLastRecord - Pointer to retrieve the last write record + +Returns: + EFI_SUCCESS - Get the last write record successfully + EFI_ABORTED - The FTW work space is damaged + +--*/ +; + +BOOLEAN +IsErasedFlashBuffer ( + IN BOOLEAN Polarity, + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + Check whether a flash buffer is erased. + +Arguments: + + Polarity - All 1 or all 0 + Buffer - Buffer to check + BufferSize - Size of the buffer + +Returns: + + Erased or not. + +--*/ +; + +EFI_STATUS +InitWorkSpaceHeader ( + IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader + ) +/*++ + +Routine Description: + Initialize a work space when there is no work space. + +Arguments: + WorkingHeader - Pointer of working block header + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully. + +--*/ +; + +EFI_STATUS +WorkSpaceRefresh ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Read from working block to refresh the work space in memory. + +Arguments: + FtwLiteDevice - Point to private data of FTW driver + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully. + +--*/ +; + +BOOLEAN +IsValidWorkSpace ( + IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader + ) +/*++ + +Routine Description: + Check to see if it is a valid work space. + +Arguments: + WorkingHeader - Pointer of working block header + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully. + +--*/ +; + +EFI_STATUS +CleanupWorkSpace ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + IN OUT UINT8 *BlockBuffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + Reclaim the work space. Get rid of all the completed write records + and write records in the Fault Tolerant work space. + +Arguments: + FtwLiteDevice - Point to private data of FTW driver + FtwSpaceBuffer - Buffer to contain the reclaimed clean data + BufferSize - Size of the FtwSpaceBuffer + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_BUFFER_TOO_SMALL - The FtwSpaceBuffer is too small + EFI_ABORTED - The function could not complete successfully. + +--*/ +; + +EFI_STATUS +FtwReclaimWorkSpace ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Reclaim the work space on the working block. + +Arguments: + FtwLiteDevice - Point to private data of FTW driver + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_OUT_OF_RESOURCES - Allocate memory error + EFI_ABORTED - The function could not complete successfully + +--*/ +; + +#endif diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.mbd b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.mbd new file mode 100644 index 0000000000..a56e9defc0 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.mbd @@ -0,0 +1,44 @@ + + + + + FtwLite + 4C862FC6-0E54-4e36-8C8F-FF6F3167951F + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-22 14:11 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + DxeHobLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa new file mode 100644 index 0000000000..06eb47c2a2 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwLite.msa @@ -0,0 +1,90 @@ + + + + + FtwLite + DXE_DRIVER + BS_DRIVER + 4C862FC6-0E54-4e36-8C8F-FF6F3167951F + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-22 14:11 + + + DebugLib + UefiDriverEntryPoint + UefiLib + BaseLib + HobLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + FtwLite.c + FtwMisc.c + FtwWorkSpace.c + FtwLite.dxs + + ia32\Ia32FtwMisc.c + + + x64\x64FtwMisc.c + + + Ipf\IpfFtwMisc.c + + + ia32\Ia32FtwMisc.c + + + + MdePkg + EdkModulePkg + + + FaultTolerantWriteLite + PciRootBridgeIo + FirmwareVolumeBlock + + + + FlashMapHob + gEfiFlashMapHobGuid + 0xb091e7d2, 0x5a0, 0x4198, 0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 + + + + + FlashMapHob + + + SystemNvDataFv + + + + + InitializeFtwLite + + + diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c new file mode 100644 index 0000000000..025ec33f7b --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwMisc.c @@ -0,0 +1,530 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FtwMisc.c + +Abstract: + + Internal functions to support fault tolerant write. + +Revision History + +--*/ + +#include + +BOOLEAN +IsErasedFlashBuffer ( + IN BOOLEAN Polarity, + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + Check whether a flash buffer is erased. + +Arguments: + + Polarity - All 1 or all 0 + Buffer - Buffer to check + BufferSize - Size of the buffer + +Returns: + + Erased or not. + +--*/ +{ + UINT8 ErasedValue; + UINT8 *Ptr; + + if (Polarity) { + ErasedValue = 0xFF; + } else { + ErasedValue = 0; + } + + Ptr = Buffer; + while (BufferSize--) { + if (*Ptr++ != ErasedValue) { + return FALSE; + } + } + + return TRUE; +} + +EFI_STATUS +FtwEraseBlock ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + EFI_LBA Lba + ) +/*++ + +Routine Description: + To Erase one block. The size is FTW_BLOCK_SIZE + +Arguments: + FtwLiteDevice - Calling context + FvBlock - FVB Protocol interface + Lba - Lba of the firmware block + +Returns: + EFI_SUCCESS - Block LBA is Erased successfully + Others - Error occurs + +--*/ +{ + return FvBlock->EraseBlocks ( + FvBlock, + Lba, + FtwLiteDevice->NumberOfSpareBlock, + EFI_LBA_LIST_TERMINATOR + ); +} + +EFI_STATUS +FtwEraseSpareBlock ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + + Erase spare block. + +Arguments: + + FtwLiteDevice - Calling context + +Returns: + + Status code + +--*/ +{ + return FtwLiteDevice->FtwBackupFvb->EraseBlocks ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba, + FtwLiteDevice->NumberOfSpareBlock, + EFI_LBA_LIST_TERMINATOR + ); +} + +EFI_STATUS +FtwGetFvbByHandle ( + IN EFI_HANDLE FvBlockHandle, + OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock + ) +/*++ + +Routine Description: + Retrive the proper FVB protocol interface by HANDLE. + +Arguments: + FvBlockHandle - The handle of FVB protocol that provides services for + reading, writing, and erasing the target block. + FvBlock - The interface of FVB protocol + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully +--*/ +{ + // + // To get the FVB protocol interface on the handle + // + return gBS->HandleProtocol ( + FvBlockHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) FvBlock + ); +} + +EFI_STATUS +GetFvbByAddress ( + IN EFI_PHYSICAL_ADDRESS Address, + OUT EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL **FvBlock + ) +/*++ + +Routine Description: + + Get firmware block by address. + +Arguments: + + Address - Address specified the block + FvBlock - The block caller wanted + +Returns: + + Status code + + EFI_NOT_FOUND - Block not found + +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_PHYSICAL_ADDRESS FvbBaseAddress; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + + *FvBlock = NULL; + // + // Locate all handles of Fvb protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeBlockProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + // + // Search all FVB until find the right one + // + for (Index = 0; Index < HandleCount; Index += 1) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &Fvb + ); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + break; + } + // + // Compare the address and select the right one + // + Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress); + if (EFI_ERROR (Status)) { + continue; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress); + if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + (FwVolHeader->FvLength - 1)))) { + *FvBlock = Fvb; + Status = EFI_SUCCESS; + break; + } + } + + gBS->FreePool (HandleBuffer); + return Status; +} + +BOOLEAN +IsInWorkingBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice, + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + EFI_LBA Lba + ) +/*++ + +Routine Description: + + Is it in working block? + +Arguments: + + FtwLiteDevice - Calling context + FvBlock - Fvb protocol instance + Lba - The block specified + +Returns: + + In working block or not + +--*/ +{ + // + // If matching the following condition, the target block is in working block. + // 1. Target block is on the FV of working block (Using the same FVB protocol instance). + // 2. Lba falls into the range of working block. + // + return (BOOLEAN) + ( + (FvBlock == FtwLiteDevice->FtwFvBlock) && + (Lba >= FtwLiteDevice->FtwWorkBlockLba) && + (Lba <= FtwLiteDevice->FtwWorkSpaceLba) + ); +} + +EFI_STATUS +FlushSpareBlockToTargetBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice, + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + EFI_LBA Lba + ) +/*++ + +Routine Description: + Copy the content of spare block to a target block. Size is FTW_BLOCK_SIZE. + Spare block is accessed by FTW backup FVB protocol interface. LBA is + FtwLiteDevice->FtwSpareLba. + Target block is accessed by FvBlock protocol interface. LBA is Lba. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + FvBlock - FVB Protocol interface to access target block + Lba - Lba of the target block + +Returns: + EFI_SUCCESS - Spare block content is copied to target block + EFI_INVALID_PARAMETER - Input parameter error + EFI_OUT_OF_RESOURCES - Allocate memory error + EFI_ABORTED - The function could not complete successfully + +--*/ +{ + EFI_STATUS Status; + UINTN Length; + UINT8 *Buffer; + UINTN Count; + UINT8 *Ptr; + UINTN Index; + + if ((FtwLiteDevice == NULL) || (FvBlock == NULL)) { + return EFI_INVALID_PARAMETER; + } + // + // Allocate a memory buffer + // + Length = FtwLiteDevice->SpareAreaLength; + Buffer = AllocatePool (Length); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Read all content of spare block to memory buffer + // + Ptr = Buffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Count = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwBackupFvb->Read ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + Index, + 0, + &Count, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Buffer); + return Status; + } + + Ptr += Count; + } + // + // Erase the target block + // + Status = FtwEraseBlock (FtwLiteDevice, FvBlock, Lba); + if (EFI_ERROR (Status)) { + gBS->FreePool (Buffer); + return EFI_ABORTED; + } + // + // Write memory buffer to block, using the FvbBlock protocol interface + // + Ptr = Buffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Count = FtwLiteDevice->SizeOfSpareBlock; + Status = FvBlock->Write (FvBlock, Lba + Index, 0, &Count, Ptr); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write block - %r\n", Status)); + gBS->FreePool (Buffer); + return Status; + } + + Ptr += Count; + } + + gBS->FreePool (Buffer); + + return Status; +} + +EFI_STATUS +FlushSpareBlockToWorkingBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Copy the content of spare block to working block. Size is FTW_BLOCK_SIZE. + Spare block is accessed by FTW backup FVB protocol interface. LBA is + FtwLiteDevice->FtwSpareLba. + Working block is accessed by FTW working FVB protocol interface. LBA is + FtwLiteDevice->FtwWorkBlockLba. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + +Returns: + EFI_SUCCESS - Spare block content is copied to target block + EFI_OUT_OF_RESOURCES - Allocate memory error + EFI_ABORTED - The function could not complete successfully + +Notes: + Since the working block header is important when FTW initializes, the + state of the operation should be handled carefully. The Crc value is + calculated without STATE element. + +--*/ +{ + EFI_STATUS Status; + UINTN Length; + UINT8 *Buffer; + EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader; + EFI_LBA WorkSpaceLbaOffset; + UINTN Count; + UINT8 *Ptr; + UINTN Index; + + // + // Allocate a memory buffer + // + Length = FtwLiteDevice->SpareAreaLength; + Buffer = AllocatePool (Length); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // To guarantee that the WorkingBlockValid is set on spare block + // + WorkSpaceLbaOffset = FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba; + FtwUpdateFvState ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + WorkSpaceLbaOffset, + FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32), + WORKING_BLOCK_VALID + ); + // + // Read from spare block to memory buffer + // + Ptr = Buffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Count = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwBackupFvb->Read ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + Index, + 0, + &Count, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Buffer); + return Status; + } + + Ptr += Count; + } + // + // Clear the CRC and STATE, copy data from spare to working block. + // + WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) (Buffer + (UINTN) WorkSpaceLbaOffset * FtwLiteDevice->SizeOfSpareBlock + FtwLiteDevice->FtwWorkSpaceBase); + InitWorkSpaceHeader (WorkingBlockHeader); + WorkingBlockHeader->WorkingBlockValid = FTW_ERASE_POLARITY; + WorkingBlockHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY; + + // + // target block is working block, then + // Set WorkingBlockInvalid in EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER + // before erase the working block. + // + // Offset = EFI_FIELD_OFFSET(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER, + // WorkingBlockInvalid); + // To skip Signature and Crc: sizeof(EFI_GUID)+sizeof(UINT32). + // + Status = FtwUpdateFvState ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkSpaceLba, + FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32), + WORKING_BLOCK_INVALID + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Buffer); + return EFI_ABORTED; + } + + FtwLiteDevice->FtwWorkSpaceHeader->WorkingBlockInvalid = FTW_VALID_STATE; + + // + // Erase the working block + // + Status = FtwEraseBlock ( + FtwLiteDevice, + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkBlockLba + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Buffer); + return EFI_ABORTED; + } + // + // Write memory buffer to working block, using the FvbBlock protocol interface + // + Ptr = Buffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Count = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwFvBlock->Write ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkBlockLba + Index, + 0, + &Count, + Ptr + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write block - %r\n", Status)); + gBS->FreePool (Buffer); + return Status; + } + + Ptr += Count; + } + // + // Since the memory buffer will not be used, free memory Buffer. + // + gBS->FreePool (Buffer); + + // + // Update the VALID of the working block + // + // Offset = EFI_FIELD_OFFSET(EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER, + // WorkingBlockValid); + // Hardcode offset sizeof(EFI_GUID)+sizeof(UINT32), to skip Signature and Crc + // + Status = FtwUpdateFvState ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkSpaceLba, + FtwLiteDevice->FtwWorkSpaceBase + sizeof (EFI_GUID) + sizeof (UINT32), + WORKING_BLOCK_VALID + ); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + + FtwLiteDevice->FtwWorkSpaceHeader->WorkingBlockValid = FTW_VALID_STATE; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c new file mode 100644 index 0000000000..820655c76b --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/FtwWorkSpace.c @@ -0,0 +1,567 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FtwWorkSpace.c + +Abstract: + +Revision History + +--*/ + + +#include + +BOOLEAN +IsValidWorkSpace ( + IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader + ) +/*++ + +Routine Description: + Check to see if it is a valid work space. + +Arguments: + WorkingHeader - Pointer of working block header + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully. + +--*/ +{ + EFI_STATUS Status; + EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER WorkingBlockHeader; + + ASSERT (WorkingHeader != NULL); + if (WorkingHeader->WorkingBlockValid != FTW_VALID_STATE) { + return FALSE; + } + // + // Check signature with gEfiSystemNvDataFvGuid + // + if (!CompareGuid (&gEfiSystemNvDataFvGuid, &WorkingHeader->Signature)) { + return FALSE; + } + // + // Check the CRC of header + // + CopyMem ( + &WorkingBlockHeader, + WorkingHeader, + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER) + ); + + // + // Filter out the Crc and State fields + // + SetMem ( + &WorkingBlockHeader.Crc, + sizeof (UINT32), + FTW_ERASED_BYTE + ); + WorkingBlockHeader.WorkingBlockValid = FTW_ERASE_POLARITY; + WorkingBlockHeader.WorkingBlockInvalid = FTW_ERASE_POLARITY; + + // + // Calculate the Crc of woking block header + // + Status = gBS->CalculateCrc32 ( + (UINT8 *) &WorkingBlockHeader, + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), + &WorkingBlockHeader.Crc + ); + ASSERT_EFI_ERROR (Status); + + if (WorkingBlockHeader.Crc != WorkingHeader->Crc) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Work block header CRC check error\n")); + return FALSE; + } + + return TRUE; +} + +EFI_STATUS +InitWorkSpaceHeader ( + IN EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingHeader + ) +/*++ + +Routine Description: + Initialize a work space when there is no work space. + +Arguments: + WorkingHeader - Pointer of working block header + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully. + +--*/ +{ + EFI_STATUS Status; + + ASSERT (WorkingHeader != NULL); + + // + // Here using gEfiSystemNvDataFvGuid as the signature. + // + CopyMem ( + &WorkingHeader->Signature, + &gEfiSystemNvDataFvGuid, + sizeof (EFI_GUID) + ); + WorkingHeader->WriteQueueSize = FTW_WORKING_QUEUE_SIZE; + + // + // Crc is calculated with all the fields except Crc and STATE + // + WorkingHeader->WorkingBlockValid = FTW_ERASE_POLARITY; + WorkingHeader->WorkingBlockInvalid = FTW_ERASE_POLARITY; + SetMem (&WorkingHeader->Crc, sizeof (UINT32), FTW_ERASED_BYTE); + + // + // Calculate the CRC value + // + Status = gBS->CalculateCrc32 ( + (UINT8 *) WorkingHeader, + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), + &WorkingHeader->Crc + ); + ASSERT_EFI_ERROR (Status); + + // + // Restore the WorkingBlockValid flag to VALID state + // + WorkingHeader->WorkingBlockValid = FTW_VALID_STATE; + WorkingHeader->WorkingBlockInvalid = FTW_INVALID_STATE; + + return EFI_SUCCESS; +} + +EFI_STATUS +FtwUpdateFvState ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + IN EFI_LBA Lba, + IN UINTN Offset, + IN UINT8 NewBit + ) +/*++ + +Routine Description: + Update a bit of state on a block device. The location of the bit is + calculated by the (Lba, Offset, bit). Here bit is determined by the + the name of a certain bit. + +Arguments: + FvBlock - FVB Protocol interface to access SrcBlock and DestBlock + Lba - Lba of a block + Offset - Offset on the Lba + NewBit - New value that will override the old value if it can be change + +Returns: + EFI_SUCCESS - A state bit has been updated successfully + Others - Access block device error. + +Notes: + Assume all bits of State are inside the same BYTE. + + EFI_ABORTED - Read block fail +--*/ +{ + EFI_STATUS Status; + UINT8 State; + UINTN Length; + + // + // Read state from device, assume State is only one byte. + // + Length = sizeof (UINT8); + Status = FvBlock->Read (FvBlock, Lba, Offset, &Length, &State); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + + State ^= FTW_POLARITY_REVERT; + State |= NewBit; + State ^= FTW_POLARITY_REVERT; + + // + // Write state back to device + // + Length = sizeof (UINT8); + Status = FvBlock->Write (FvBlock, Lba, Offset, &Length, &State); + + return Status; +} + +EFI_STATUS +FtwGetLastRecord ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + OUT EFI_FTW_LITE_RECORD **FtwLastRecord + ) +/*++ + +Routine Description: + Get the last Write record pointer. + The last record is the record whose 'complete' state hasn't been set. + After all, this header may be a EMPTY header entry for next Allocate. + +Arguments: + FtwLiteDevice - Private data of this driver + FtwLastRecord - Pointer to retrieve the last write record + +Returns: + EFI_SUCCESS - Get the last write record successfully + EFI_ABORTED - The FTW work space is damaged + +--*/ +{ + EFI_FTW_LITE_RECORD *Record; + + Record = (EFI_FTW_LITE_RECORD *) (FtwLiteDevice->FtwWorkSpaceHeader + 1); + while (Record->WriteCompleted == FTW_VALID_STATE) { + // + // If Offset exceed the FTW work space boudary, return error. + // + if ((UINTN) ((UINT8 *) Record - FtwLiteDevice->FtwWorkSpace) > FtwLiteDevice->FtwWorkSpaceSize) { + return EFI_ABORTED; + } + + Record++; + } + // + // Last write record is found + // + *FtwLastRecord = Record; + return EFI_SUCCESS; +} + +EFI_STATUS +WorkSpaceRefresh ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Read from working block to refresh the work space in memory. + +Arguments: + FtwLiteDevice - Point to private data of FTW driver + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully. + +--*/ +{ + EFI_STATUS Status; + UINTN Length; + UINTN Offset; + EFI_FTW_LITE_RECORD *Record; + + // + // Initialize WorkSpace as FTW_ERASED_BYTE + // + SetMem ( + FtwLiteDevice->FtwWorkSpace, + FtwLiteDevice->FtwWorkSpaceSize, + FTW_ERASED_BYTE + ); + + // + // Read from working block + // + Length = FtwLiteDevice->FtwWorkSpaceSize; + Status = FtwLiteDevice->FtwFvBlock->Read ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkSpaceLba, + FtwLiteDevice->FtwWorkSpaceBase, + &Length, + FtwLiteDevice->FtwWorkSpace + ); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Refresh the FtwLastRecord + // + Status = FtwGetLastRecord (FtwLiteDevice, &FtwLiteDevice->FtwLastRecord); + + Record = FtwLiteDevice->FtwLastRecord; + Offset = (UINTN) (UINT8 *) Record - (UINTN) FtwLiteDevice->FtwWorkSpace; + + // + // IF work space has error or Record is out of the workspace limit, THEN + // call reclaim. + // + if (EFI_ERROR (Status) || (Offset + WRITE_TOTAL_SIZE >= FtwLiteDevice->FtwWorkSpaceSize)) { + // + // reclaim work space in working block. + // + Status = FtwReclaimWorkSpace (FtwLiteDevice); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: Reclaim workspace - %r\n", Status)); + return EFI_ABORTED; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +CleanupWorkSpace ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + IN OUT UINT8 *FtwSpaceBuffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + Reclaim the work space. Get rid of all the completed write records + and write records in the Fault Tolerant work space. + +Arguments: + FtwLiteDevice - Point to private data of FTW driver + FtwSpaceBuffer - Buffer to contain the reclaimed clean data + BufferSize - Size of the FtwSpaceBuffer + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_BUFFER_TOO_SMALL - The FtwSpaceBuffer is too small + EFI_ABORTED - The function could not complete successfully. + +--*/ +{ + UINTN Length; + EFI_FTW_LITE_RECORD *Record; + + // + // To check if the buffer is large enough + // + Length = FtwLiteDevice->FtwWorkSpaceSize; + if (BufferSize < Length) { + return EFI_BUFFER_TOO_SMALL; + } + // + // Clear the content of buffer that will save the new work space data + // + SetMem (FtwSpaceBuffer, Length, FTW_ERASED_BYTE); + + // + // Copy EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER to buffer + // + CopyMem ( + FtwSpaceBuffer, + FtwLiteDevice->FtwWorkSpaceHeader, + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER) + ); + + // + // Get the last record + // + Record = FtwLiteDevice->FtwLastRecord; + if ((Record != NULL) && (Record->WriteAllocated == FTW_VALID_STATE) && (Record->WriteCompleted != FTW_VALID_STATE)) { + CopyMem ( + (UINT8 *) FtwSpaceBuffer + sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), + Record, + WRITE_TOTAL_SIZE + ); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +FtwReclaimWorkSpace ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Reclaim the work space on the working block. + +Arguments: + FtwLiteDevice - Point to private data of FTW driver + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_OUT_OF_RESOURCES - Allocate memory error + EFI_ABORTED - The function could not complete successfully + +--*/ +{ + EFI_STATUS Status; + UINT8 *TempBuffer; + UINTN TempBufferSize; + UINT8 *Ptr; + UINTN Length; + UINTN Index; + UINTN SpareBufferSize; + UINT8 *SpareBuffer; + EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *WorkingBlockHeader; + + DEBUG ((EFI_D_FTW_LITE, "FtwLite: start to reclaim work space\n")); + + // + // Read all original data from working block to a memory buffer + // + TempBufferSize = FtwLiteDevice->SpareAreaLength; + Status = gBS->AllocatePool ( + EfiBootServicesData, + TempBufferSize, + (VOID **) &TempBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + ZeroMem (TempBuffer, TempBufferSize); + + Ptr = TempBuffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Length = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwFvBlock->Read ( + FtwLiteDevice->FtwFvBlock, + FtwLiteDevice->FtwWorkBlockLba + Index, + 0, + &Length, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (TempBuffer); + return EFI_ABORTED; + } + + Ptr += Length; + } + // + // Clean up the workspace, remove all the completed records. + // + Ptr = TempBuffer + + ((UINTN) (FtwLiteDevice->FtwWorkSpaceLba - FtwLiteDevice->FtwWorkBlockLba)) * + FtwLiteDevice->SizeOfSpareBlock + + FtwLiteDevice->FtwWorkSpaceBase; + Status = CleanupWorkSpace ( + FtwLiteDevice, + Ptr, + FtwLiteDevice->FtwWorkSpaceSize + ); + + CopyMem ( + FtwLiteDevice->FtwWorkSpace, + Ptr, + FtwLiteDevice->FtwWorkSpaceSize + ); + + Status = FtwGetLastRecord (FtwLiteDevice, &FtwLiteDevice->FtwLastRecord); + + // + // Set the WorkingBlockValid and WorkingBlockInvalid as INVALID + // + WorkingBlockHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) Ptr; + WorkingBlockHeader->WorkingBlockValid = FTW_INVALID_STATE; + WorkingBlockHeader->WorkingBlockInvalid = FTW_INVALID_STATE; + + // + // Try to keep the content of spare block + // Save spare block into a spare backup memory buffer (Sparebuffer) + // + SpareBufferSize = FtwLiteDevice->SpareAreaLength; + SpareBuffer = AllocatePool (SpareBufferSize); + if (SpareBuffer == NULL) { + gBS->FreePool (TempBuffer); + return EFI_OUT_OF_RESOURCES; + } + + Ptr = SpareBuffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Length = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwBackupFvb->Read ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + Index, + 0, + &Length, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (TempBuffer); + gBS->FreePool (SpareBuffer); + return EFI_ABORTED; + } + + Ptr += Length; + } + // + // Write the memory buffer to spare block + // + Status = FtwEraseSpareBlock (FtwLiteDevice); + Ptr = TempBuffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Length = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwBackupFvb->Write ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + Index, + 0, + &Length, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (TempBuffer); + gBS->FreePool (SpareBuffer); + return EFI_ABORTED; + } + + Ptr += Length; + } + // + // Free TempBuffer + // + gBS->FreePool (TempBuffer); + + // + // Write the spare block to working block + // + Status = FlushSpareBlockToWorkingBlock (FtwLiteDevice); + if (EFI_ERROR (Status)) { + gBS->FreePool (SpareBuffer); + return Status; + } + // + // Restore spare backup buffer into spare block , if no failure happened during FtwWrite. + // + Status = FtwEraseSpareBlock (FtwLiteDevice); + Ptr = SpareBuffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Length = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwBackupFvb->Write ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + Index, + 0, + &Length, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (SpareBuffer); + return EFI_ABORTED; + } + + Ptr += Length; + } + + gBS->FreePool (SpareBuffer); + + DEBUG ((EFI_D_FTW_LITE, "FtwLite: reclaim work space success\n")); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c new file mode 100644 index 0000000000..80258f4cc3 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ia32/Ia32FtwMisc.c @@ -0,0 +1,399 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Ia32FtwMisc.c + +Abstract: + + Ia32 platform related code to support FtwLite.. + +Revision History + +--*/ + + +#include + +// +// MACROs for boot block update +// +#define BOOT_BLOCK_BASE 0xFFFF0000 + +// +// (LPC -- D31:F0) +// +#define LPC_BUS_NUMBER 0x00 +#define LPC_DEVICE_NUMBER 0x1F +#define LPC_IF 0xF0 +// +// Top swap +// +#define GEN_STATUS 0xD4 +#define TOP_SWAP_BIT (1 << 13) + +STATIC +UINT32 +ReadPciRegister ( + IN UINT32 Offset + ) +/*++ + +Routine Description: + + Read PCI register value. + +Arguments: + + Offset - Offset of the register + +Returns: + + The value. + +--*/ +{ + EFI_STATUS Status; + UINT32 Value; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + + Value = 0; + Status = gBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID **) &PciRootBridgeIo); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FtwLite: Locate PCI root bridge io protocol - %r", Status)); + return 0; + } + + Status = PciRootBridgeIo->Pci.Read ( + PciRootBridgeIo, + EfiPciWidthUint32, + EFI_PCI_ADDRESS (LPC_BUS_NUMBER, + LPC_DEVICE_NUMBER, + LPC_IF, + Offset), + 1, + &Value + ); + ASSERT_EFI_ERROR (Status); + + return Value; +} + +STATIC +EFI_STATUS +GetSwapState ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + OUT BOOLEAN *SwapState + ) +/*++ + +Routine Description: + + Get swap state + +Arguments: + + FtwLiteDevice - Calling context + SwapState - Swap state + +Returns: + + EFI_SUCCESS - State successfully got + +--*/ +{ + // + // Top swap status is 13 bit + // + *SwapState = (BOOLEAN) ((ReadPciRegister (GEN_STATUS) & TOP_SWAP_BIT) != 0); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SetSwapState ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + IN BOOLEAN TopSwap + ) +/*++ + +Routine Description: + Set swap state. + +Arguments: + FtwLiteDevice - Indicates a pointer to the calling context. + TopSwap - New swap state + +Returns: + EFI_SUCCESS - The function completed successfully + +Note: + the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that + software will not be able to clear the Top-Swap bit until the system is + rebooted without GNT[A]# being pulled down. + +--*/ +{ + UINT32 GenStatus; + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo; + EFI_STATUS Status; + + // + // Top-Swap bit (bit 13, D31: F0, Offset D4h) + // + GenStatus = ReadPciRegister (GEN_STATUS); + + // + // Set 13 bit, according to input NewSwapState + // + if (TopSwap) { + GenStatus |= TOP_SWAP_BIT; + } else { + GenStatus &= ~TOP_SWAP_BIT; + } + + Status = gBS->LocateProtocol (&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID **) &PciRootBridgeIo); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FtwLite: Locate PCI root bridge io protocol - %r", Status)); + return Status; + } + // + // Write back the GenStatus register + // + Status = PciRootBridgeIo->Pci.Write ( + PciRootBridgeIo, + EfiPciWidthUint32, + EFI_PCI_ADDRESS (LPC_BUS_NUMBER, + LPC_DEVICE_NUMBER, + LPC_IF, + GEN_STATUS), + 1, + &GenStatus + ); + + DEBUG_CODE ( + if (TopSwap) { + DEBUG ((EFI_D_ERROR, "SAR: Set top swap\n")); + } else { + DEBUG ((EFI_D_ERROR, "SAR: Clear top swap\n")); + } + ); + + return EFI_SUCCESS; +} + +BOOLEAN +IsBootBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice, + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + EFI_LBA Lba + ) +/*++ + +Routine Description: + + Check whether the block is a boot block. + +Arguments: + + FtwLiteDevice - Calling context + FvBlock - Fvb protocol instance + Lba - Lba value + +Returns: + + Is a boot block or not + +--*/ +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb; + + Status = GetFvbByAddress (BOOT_BLOCK_BASE, &BootFvb); + if (EFI_ERROR (Status)) { + return FALSE; + } + // + // Compare the Fvb + // + return (BOOLEAN) (FvBlock == BootFvb); +} + +EFI_STATUS +FlushSpareBlockToBootBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE. + Spare block is accessed by FTW backup FVB protocol interface. LBA is + FtwLiteDevice->FtwSpareLba. + Boot block is accessed by BootFvb protocol interface. LBA is 0. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + +Returns: + EFI_SUCCESS - Spare block content is copied to boot block + EFI_INVALID_PARAMETER - Input parameter error + EFI_OUT_OF_RESOURCES - Allocate memory error + EFI_ABORTED - The function could not complete successfully + +Notes: + FTW will do extra work on boot block update. + FTW should depend on a protocol of EFI_ADDRESS_RANGE_SWAP_PROTOCOL, + which is produced by a chipset driver. + + FTW updating boot block steps: + 1. Erase top swap block (0xFFFE-0xFFFEFFFF) and write data to it ready + 2. Read data from top swap block to memory buffer + 3. SetSwapState(EFI_SWAPPED) + 4. Erasing boot block (0xFFFF-0xFFFFFFFF) + 5. Programming boot block until the boot block is ok. + 6. SetSwapState(UNSWAPPED) + + Notes: + 1. Since the SwapState bit is saved in CMOS, FTW can restore and continue + even in the scenario of power failure. + 2. FTW shall not allow to update boot block when battery state is error. + +--*/ +{ + EFI_STATUS Status; + UINTN Length; + UINT8 *Buffer; + UINTN Count; + UINT8 *Ptr; + UINTN Index; + BOOLEAN TopSwap; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BootFvb; + EFI_LBA BootLba; + + // + // Allocate a memory buffer + // + Length = FtwLiteDevice->SpareAreaLength; + Buffer = AllocatePool (Length); + if (Buffer == NULL) { + } + // + // Get TopSwap bit state + // + Status = GetSwapState (FtwLiteDevice, &TopSwap); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "FtwLite: Get Top Swapped status - %r\n", Status)); + gBS->FreePool (Buffer); + return EFI_ABORTED; + } + + if (TopSwap) { + // + // Get FVB of current boot block + // + Status = GetFvbByAddress (FtwLiteDevice->SpareAreaAddress + FTW_BLOCK_SIZE, &BootFvb); + if (EFI_ERROR (Status)) { + gBS->FreePool (Buffer); + return Status; + } + // + // Read data from current boot block + // + BootLba = 0; + Ptr = Buffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Count = FtwLiteDevice->SizeOfSpareBlock; + Status = BootFvb->Read ( + BootFvb, + BootLba + Index, + 0, + &Count, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Buffer); + return Status; + } + + Ptr += Count; + } + + } else { + // + // Read data from spare block + // + Ptr = Buffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Count = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwBackupFvb->Read ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + Index, + 0, + &Count, + Ptr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Buffer); + return Status; + } + + Ptr += Count; + } + // + // Set TopSwap bit + // + Status = SetSwapState (FtwLiteDevice, TRUE); + DEBUG ((EFI_D_ERROR, "FtwLite: Set Swap State - %r\n", Status)); + ASSERT_EFI_ERROR (Status); + } + // + // Erase boot block. After setting TopSwap bit, it's spare block now! + // + Status = FtwEraseSpareBlock (FtwLiteDevice); + if (EFI_ERROR (Status)) { + gBS->FreePool (Buffer); + return EFI_ABORTED; + } + // + // Write memory buffer to currenet spare block + // + Ptr = Buffer; + for (Index = 0; Index < FtwLiteDevice->NumberOfSpareBlock; Index += 1) { + Count = FtwLiteDevice->SizeOfSpareBlock; + Status = FtwLiteDevice->FtwBackupFvb->Write ( + FtwLiteDevice->FtwBackupFvb, + FtwLiteDevice->FtwSpareLba + Index, + 0, + &Count, + Ptr + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_FTW_LITE, "FtwLite: FVB Write boot block - %r\n", Status)); + gBS->FreePool (Buffer); + return Status; + } + + Ptr += Count; + } + + gBS->FreePool (Buffer); + + // + // Clear TopSwap bit + // + Status = SetSwapState (FtwLiteDevice, FALSE); + DEBUG ((EFI_D_ERROR, "FtwLite: Clear Swap State - %r\n", Status)); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c new file mode 100644 index 0000000000..d31883b2ee --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/Ipf/IpfFtwMisc.c @@ -0,0 +1,143 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + IpfFtwMisc.c + +Abstract: + + Ipf platform related code to support FtwLite.. + +Revision History + +--*/ + + +#include + +// +// MACROs for boot block update +// +#define BOOT_BLOCK_BASE + +STATIC +EFI_STATUS +GetSwapState ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + OUT BOOLEAN *SwapState + ) +/*++ + +Routine Description: + + Get swap state + +Arguments: + + FtwLiteDevice - Calling context + SwapState - Swap state + +Returns: + + EFI_SUCCESS - State successfully got + +--*/ +{ + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SetSwapState ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + IN BOOLEAN TopSwap + ) +/*++ + +Routine Description: + Set swap state. + +Arguments: + FtwLiteDevice - Indicates a pointer to the calling context. + TopSwap - New swap state + +Returns: + EFI_SUCCESS - The function completed successfully + +Note: + the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that + software will not be able to clear the Top-Swap bit until the system is + rebooted without GNT[A]# being pulled down. + +--*/ +{ + return EFI_SUCCESS; +} + +BOOLEAN +IsBootBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice, + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + EFI_LBA Lba + ) +/*++ + +Routine Description: + + Check whether the block is a boot block. + +Arguments: + + FtwLiteDevice - Calling context + FvBlock - Fvb protocol instance + Lba - Lba value + +Returns: + + Is a boot block or not + +--*/ +{ + // + // IPF doesn't support safe bootblock update + // so treat bootblock as normal block + // + return FALSE; +} + +EFI_STATUS +FlushSpareBlockToBootBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE. + Spare block is accessed by FTW backup FVB protocol interface. LBA is + FtwLiteDevice->FtwSpareLba. + Boot block is accessed by BootFvb protocol interface. LBA is 0. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + +Returns: + EFI_SUCCESS - Spare block content is copied to boot block + EFI_INVALID_PARAMETER - Input parameter error + EFI_OUT_OF_RESOURCES - Allocate memory error + EFI_ABORTED - The function could not complete successfully + +Notes: + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/build.xml b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/build.xml new file mode 100644 index 0000000000..0883c25cba --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c new file mode 100644 index 0000000000..067bfcf179 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/FaultTolerantWriteLite/Dxe/x64/x64FtwMisc.c @@ -0,0 +1,140 @@ + +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + x64FtwMisc.c + +Abstract: + + X64 platform related code to support FtwLite.. + +Revision History + +--*/ + + +#include + +// +// MACROs for boot block update +// +#define BOOT_BLOCK_BASE + +STATIC +EFI_STATUS +GetSwapState ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + OUT BOOLEAN *SwapState + ) +/*++ + +Routine Description: + + Get swap state + +Arguments: + + FtwLiteDevice - Calling context + SwapState - Swap state + +Returns: + + EFI_SUCCESS - State successfully got + +--*/ +{ + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SetSwapState ( + IN EFI_FTW_LITE_DEVICE *FtwLiteDevice, + IN BOOLEAN TopSwap + ) +/*++ + +Routine Description: + Set swap state. + +Arguments: + FtwLiteDevice - Indicates a pointer to the calling context. + TopSwap - New swap state + +Returns: + EFI_SUCCESS - The function completed successfully + +Note: + the Top-Swap bit (bit 13, D31: F0, Offset D4h). Note that + software will not be able to clear the Top-Swap bit until the system is + rebooted without GNT[A]# being pulled down. + +--*/ +{ + return EFI_SUCCESS; +} + +BOOLEAN +IsBootBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice, + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *FvBlock, + EFI_LBA Lba + ) +/*++ + +Routine Description: + + Check whether the block is a boot block. + +Arguments: + + FtwLiteDevice - Calling context + FvBlock - Fvb protocol instance + Lba - Lba value + +Returns: + + Is a boot block or not + +--*/ +{ + return FALSE; +} + +EFI_STATUS +FlushSpareBlockToBootBlock ( + EFI_FTW_LITE_DEVICE *FtwLiteDevice + ) +/*++ + +Routine Description: + Copy the content of spare block to a boot block. Size is FTW_BLOCK_SIZE. + Spare block is accessed by FTW backup FVB protocol interface. LBA is + FtwLiteDevice->FtwSpareLba. + Boot block is accessed by BootFvb protocol interface. LBA is 0. + +Arguments: + FtwLiteDevice - The private data of FTW_LITE driver + +Returns: + EFI_SUCCESS - Spare block content is copied to boot block + EFI_INVALID_PARAMETER - Input parameter error + EFI_OUT_OF_RESOURCES - Allocate memory error + EFI_ABORTED - The function could not complete successfully + +Notes: + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c new file mode 100644 index 0000000000..dc7ed07baa --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.c @@ -0,0 +1,234 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Crc32SectionExtract.c + +Abstract: + + Implements GUIDed section extraction protocol interface with + a specific GUID: CRC32. + + Please refer to the Tiano File Image Format Specification, + FV spec 0.3.6 + +--*/ + + +#include +#include + +EFI_STATUS +InitializeCrc32GuidedSectionExtractionProtocol ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +InitializeCrc32GuidedSectionExtractionProtocol ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Entry point of the CRC32 GUIDed section extraction protocol. + Creates and initializes an instance of the GUIDed section + extraction protocol with CRC32 GUID. + +Arguments: + + ImageHandle EFI_HANDLE: A handle for the image that is initializing + this driver + SystemTable EFI_SYSTEM_TABLE: A pointer to the EFI system table + +Returns: + + EFI_SUCCESS: Driver initialized successfully + EFI_LOAD_ERROR: Failed to Initialize or has been loaded + EFI_OUT_OF_RESOURCES: Could not allocate needed resources + +--*/ +{ + EFI_STATUS Status; + EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *Crc32GuidedSep; + EFI_HANDLE Handle; + + // + // Call all constructors per produced protocols + // + Status = GuidedSectionExtractionProtocolConstructor ( + &Crc32GuidedSep, + (EFI_EXTRACT_GUIDED_SECTION) Crc32ExtractSection + ); + if (EFI_ERROR (Status)) { + if (Crc32GuidedSep != NULL) { + gBS->FreePool (Crc32GuidedSep); + } + + return Status; + } + // + // Pass in a NULL to install to a new handle + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiCrc32GuidedSectionExtractionProtocolGuid, + EFI_NATIVE_INTERFACE, + Crc32GuidedSep + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Crc32GuidedSep); + return EFI_LOAD_ERROR; + } + + return EFI_SUCCESS; +} + +STATIC +UINT32 +GetSectionLength ( + IN EFI_COMMON_SECTION_HEADER *CommonHeader + ) +/*++ + + Routine Description: + Get a length of section. + + Parameters: + CommonHeader - Pointer to the common section header. + + Return Value: + The length of the section, including the section header. + +--*/ +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: CommonHeader - add argument and description to function comment +{ + UINT32 Size; + + Size = *(UINT32 *) CommonHeader->Size & 0x00FFFFFF; + + return Size; +} + +STATIC +EFI_STATUS +Crc32ExtractSection ( + IN EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This, + IN VOID *InputSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize, + OUT UINT32 *AuthenticationStatus + ) +/*++ + + Routine Description: + This function reads and extracts contents of a section from an + encapsulating section. + + Parameters: + This - Indicates the calling context. + InputSection - Buffer containing the input GUIDed section + to be processed. + OutputBuffer - *OutputBuffer is allocated from boot services + pool memory and containing the new section + stream. The caller is responsible for freeing + this buffer. + AuthenticationStatus - Pointer to a caller allocated UINT32 that + indicates the authentication status of the + output buffer + + Return Value: + EFI_SUCCESS + EFI_OUT_OF_RESOURCES + EFI_INVALID_PARAMETER + EFI_NOT_AVAILABLE_YET + +--*/ +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: This - add argument and description to function comment +// TODO: InputSection - add argument and description to function comment +// TODO: OutputBuffer - add argument and description to function comment +// TODO: OutputSize - add argument and description to function comment +// TODO: AuthenticationStatus - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + CRC32_SECTION_HEADER *Crc32SectionHeader; + EFI_GUID_DEFINED_SECTION *GuidedSectionHeader; + UINT8 *Image; + UINT32 Crc32Checksum; + VOID *DummyInterface; + + if (OutputBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + *OutputBuffer = NULL; + + // + // Points to the section header + // + Crc32SectionHeader = (CRC32_SECTION_HEADER *) InputSection; + GuidedSectionHeader = (EFI_GUID_DEFINED_SECTION *) InputSection; + + // + // Check if the GUID is a CRC32 section GUID + // + if (!CompareGuid ( + &(GuidedSectionHeader->SectionDefinitionGuid), + &gEfiCrc32GuidedSectionExtractionProtocolGuid + )) { + return EFI_INVALID_PARAMETER; + } + + Image = (UINT8 *) InputSection + (UINT32) (GuidedSectionHeader->DataOffset); + *OutputSize = GetSectionLength ((EFI_COMMON_SECTION_HEADER *) InputSection) - (UINT32) GuidedSectionHeader->DataOffset; + + Status = gBS->AllocatePool (EfiBootServicesData, *OutputSize, OutputBuffer); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Implictly CRC32 GUIDed section should have STATUS_VALID bit set + // + ASSERT (GuidedSectionHeader->Attributes & EFI_GUIDED_SECTION_AUTH_STATUS_VALID); + *AuthenticationStatus = EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED | EFI_AGGREGATE_AUTH_STATUS_IMAGE_SIGNED; + + // + // Check whether there exists EFI_SECURITY_POLICY_PROTOCOL_GUID. + // + Status = gBS->LocateProtocol (&gEfiSecurityPolicyProtocolGuid, NULL, &DummyInterface); + if (!EFI_ERROR (Status)) { + *AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_PLATFORM_OVERRIDE | EFI_AGGREGATE_AUTH_STATUS_PLATFORM_OVERRIDE; + } else { + // + // Calculate CRC32 Checksum of Image + // + gBS->CalculateCrc32 (Image, *OutputSize, &Crc32Checksum); + if (Crc32Checksum != Crc32SectionHeader->CRC32Checksum) { + *AuthenticationStatus |= EFI_LOCAL_AUTH_STATUS_TEST_FAILED | EFI_AGGREGATE_AUTH_STATUS_TEST_FAILED; + } + } + + CopyMem (*OutputBuffer, Image, *OutputSize); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs new file mode 100644 index 0000000000..033ff94ac3 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Crc32SectionExtraction.dxs + +Abstract: + + Dependency expression file. + +--*/ + +#include +#include "DxeDepex.h" + +DEPENDENCY_START + EFI_RUNTIME_ARCH_PROTOCOL_GUID +DEPENDENCY_END + diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h new file mode 100644 index 0000000000..8e32d6d7bb --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.h @@ -0,0 +1,65 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Crc32SectionExtract.h + +Abstract: + + Header file for Crc32SectionExtract.c + Please refer to Tiano File Image Format specification + FV spec 0.3.6 + +--*/ + +#ifndef _CRC32_GUIDED_SECTION_EXTRACTION_H +#define _CRC32_GUIDED_SECTION_EXTRACTION_H + +typedef struct { + EFI_GUID_DEFINED_SECTION GuidedSectionHeader; + UINT32 CRC32Checksum; +} CRC32_SECTION_HEADER; + +// +// Function prototype declarations +// +STATIC +EFI_STATUS +Crc32ExtractSection ( + IN EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This, + IN VOID *InputSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize, + OUT UINT32 *AuthenticationStatus + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + InputSection - TODO: add argument description + OutputBuffer - TODO: add argument description + OutputSize - TODO: add argument description + AuthenticationStatus - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.mbd b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.mbd new file mode 100644 index 0000000000..67ea3cd4b9 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.mbd @@ -0,0 +1,40 @@ + + + + + Crc32SectionExtract + 51C9F40C-5243-4473-B265-B3C8FFAFF9FA + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + + diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa new file mode 100644 index 0000000000..da82d561a0 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/Crc32SectionExtract.msa @@ -0,0 +1,61 @@ + + + + + Crc32SectionExtract + DXE_DRIVER + BS_DRIVER + 51C9F40C-5243-4473-B265-B3C8FFAFF9FA + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverEntryPoint + UefiLib + BaseLib + BaseMemoryLib + UefiBootServicesTableLib + + + Crc32SectionExtract.c + Crc32SectionExtract.h + GuidedSection.c + GuidedSection.h + + + MdePkg + EdkModulePkg + + + SecurityPolicy + Crc32GuidedSectionExtraction + + + + InitializeCrc32GuidedSectionExtractionProtocol + + + diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c new file mode 100644 index 0000000000..3c3f22f760 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.c @@ -0,0 +1,75 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + GuidedSection.c + +Abstract: + + GUIDed section extraction protocol implementation. + This contains the common constructor of GUIDed section + extraction protocol. GUID specific implementation of each + GUIDed section extraction protocol can be found in other + files under the same directory. + + Please refer to the Tiano File Image Format Specification, + FV spec 0.3.6 + + Acronyms used Meaning + + +--*/ + + +#include "Common/FirmwareFileSystem.h" + +EFI_STATUS +GuidedSectionExtractionProtocolConstructor ( + OUT EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL **GuidedSep, + IN EFI_EXTRACT_GUIDED_SECTION ExtractSection + ) +/*++ + +Routine Description: + + Constructor for the GUIDed section extraction protocol. Initializes + instance data. + +Arguments: + + This Instance to construct + +Returns: + + EFI_SUCCESS: Instance initialized. + +--*/ +// TODO: GuidedSep - add argument and description to function comment +// TODO: ExtractSection - add argument and description to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +{ + EFI_STATUS Status; + + *GuidedSep = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL), + (VOID **) GuidedSep + ); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + (*GuidedSep)->ExtractSection = ExtractSection; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h new file mode 100644 index 0000000000..1399edf4f6 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/GuidedSection.h @@ -0,0 +1,53 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + GuidedSection.h + +Abstract: + + Header file for GuidedSection.c + Please refer to Tiano File Image Format specification + FV spec 0.3.6 + +--*/ + +#ifndef _GUIDED_SECTION_EXTRACTION_H +#define _GUIDED_SECTION_EXTRACTION_H + +// +// Function prototype declarations +// +EFI_STATUS +GuidedSectionExtractionProtocolConstructor ( + OUT EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL **GuidedSep, + IN EFI_EXTRACT_GUIDED_SECTION ExtractSection + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + GuidedSep - TODO: add argument description + ExtractSection - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/build.xml b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/build.xml new file mode 100644 index 0000000000..7582701719 --- /dev/null +++ b/EdkModulePkg/Universal/FirmwareVolume/GuidedSectionExtraction/Crc32SectionExtract/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Dxe/Common.h b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/Common.h new file mode 100644 index 0000000000..7a1ab78a1e --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/Common.h @@ -0,0 +1,59 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Common.h + +Abstract: + The generic memory test driver definition + +--*/ + +#ifndef _COMMON_H +#define _COMMON_H + +// +// Some global define +// +#define GENERIC_CACHELINE_SIZE 0x40 + +// +// The SPARSE_SPAN_SIZE size can not small then the MonoTestSize +// +#define TEST_BLOCK_SIZE 0x2000000 +#define QUICK_SPAN_SIZE (TEST_BLOCK_SIZE >> 2) +#define SPARSE_SPAN_SIZE (TEST_BLOCK_SIZE >> 4) + +// +// This structure records every nontested memory range parsed through GCD +// service. +// +#define EFI_NONTESTED_MEMORY_RANGE_SIGNATURE EFI_SIGNATURE_32 ('N', 'T', 'M', 'E') +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + EFI_PHYSICAL_ADDRESS StartAddress; + UINT64 Length; + UINT64 Capabilities; + BOOLEAN Above4G; + BOOLEAN AlreadyMapped; +} NONTESTED_MEMORY_RANGE; + +#define NONTESTED_MEMORY_RANGE_FROM_LINK(link) \ + CR(link, NONTESTED_MEMORY_RANGE, Link, EFI_NONTESTED_MEMORY_RANGE_SIGNATURE) + +// +// This is the memory test driver's structure definition +// +#define EFI_GENERIC_MEMORY_TEST_PRIVATE_SIGNATURE EFI_SIGNATURE_32 ('G', 'E', 'M', 'T') + +#endif diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.c b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.c new file mode 100644 index 0000000000..7bad347f24 --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.c @@ -0,0 +1,214 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + NullMemoryTest.c + +Abstract: + +--*/ + + +#include "NullMemoryTest.h" + +// +// Module global members +// +UINT64 mTestedSystemMemory = 0; +UINT64 mTotalSystemMemory = 0; +EFI_HANDLE mGenericMemoryTestHandle; + +// +// Driver entry here +// +EFI_GENERIC_MEMORY_TEST_PROTOCOL mGenericMemoryTest = { + InitializeMemoryTest, + GenPerformMemoryTest, + GenMemoryTestFinished, + GenCompatibleRangeTest +}; + +EFI_STATUS +EFIAPI +GenericMemoryTestEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + The generic memory test driver's entry point, it can initialize private data + to default value + +Arguments: + + ImageHandle of the loaded driver + Pointer to the System Table + +Returns: + + Status + + EFI_SUCCESS - Protocol successfully installed + EFI_OUT_OF_RESOURCES - Can not allocate protocol data structure in base + memory + +--*/ +{ + EFI_STATUS Status; + + // + // Install the protocol + // + Status = gBS->InstallProtocolInterface ( + &mGenericMemoryTestHandle, + &gEfiGenericMemTestProtocolGuid, + EFI_NATIVE_INTERFACE, + &mGenericMemoryTest + ); + + return Status; +} +// +// EFI_GENERIC_MEMORY_TEST_PROTOCOL implementation +// +EFI_STATUS +EFIAPI +InitializeMemoryTest ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This, + IN EXTENDMEM_COVERAGE_LEVEL Level, + OUT BOOLEAN *RequireSoftECCInit + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemorySpaceMap; + UINTN Index; + + gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemorySpaceMap); + for (Index = 0; Index < NumberOfDescriptors; Index++) { + if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeReserved && + (MemorySpaceMap[Index].Capabilities & (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED)) == + (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED) + ) { + gDS->RemoveMemorySpace ( + MemorySpaceMap[Index].BaseAddress, + MemorySpaceMap[Index].Length + ); + + gDS->AddMemorySpace ( + EfiGcdMemoryTypeSystemMemory, + MemorySpaceMap[Index].BaseAddress, + MemorySpaceMap[Index].Length, + MemorySpaceMap[Index].Capabilities &~ + (EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME) + ); + + mTestedSystemMemory += MemorySpaceMap[Index].Length; + mTotalSystemMemory += MemorySpaceMap[Index].Length; + } else if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeSystemMemory) { + mTotalSystemMemory += MemorySpaceMap[Index].Length; + } + } + + gBS->FreePool (MemorySpaceMap); + + *RequireSoftECCInit = FALSE; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GenPerformMemoryTest ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This, + IN OUT UINT64 *TestedMemorySize, + OUT UINT64 *TotalMemorySize, + OUT BOOLEAN *ErrorOut, + IN BOOLEAN TestAbort + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + *ErrorOut = FALSE; + *TestedMemorySize = mTestedSystemMemory; + *TotalMemorySize = mTotalSystemMemory; + + return EFI_NOT_FOUND; + +} + +EFI_STATUS +EFIAPI +GenMemoryTestFinished ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GenCompatibleRangeTest ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS StartAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_GCD_MEMORY_SPACE_DESCRIPTOR descriptor; + + gDS->GetMemorySpaceDescriptor (StartAddress, &descriptor); + + gDS->RemoveMemorySpace (StartAddress, Length); + + gDS->AddMemorySpace ( + EfiGcdMemoryTypeSystemMemory, + StartAddress, + Length, + descriptor.Capabilities &~(EFI_MEMORY_PRESENT | EFI_MEMORY_INITIALIZED | EFI_MEMORY_TESTED | EFI_MEMORY_RUNTIME) + ); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.dxs b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.dxs new file mode 100644 index 0000000000..9f281b3d7d --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.dxs @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + NullMemoryTest.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.h b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.h new file mode 100644 index 0000000000..b4a0720f6b --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.h @@ -0,0 +1,65 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + NullMemoryTest.h + +Abstract: + The generic memory test driver definition + +--*/ + +#ifndef _NULL_MEMORY_TEST_H +#define _NULL_MEMORY_TEST_H + +#include "Common.h" + +// +// Function Prototypes +// +EFI_STATUS +EFIAPI +InitializeMemoryTest ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This, + IN EXTENDMEM_COVERAGE_LEVEL Level, + OUT BOOLEAN *RequireSoftECCInit + ) +; + +EFI_STATUS +EFIAPI +GenPerformMemoryTest ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This, + IN OUT UINT64 *TestedMemorySize, + OUT UINT64 *TotalMemorySize, + OUT BOOLEAN *ErrorOut, + IN BOOLEAN TestAbort + ) +; + +EFI_STATUS +EFIAPI +GenMemoryTestFinished ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This + ) +; + +EFI_STATUS +EFIAPI +GenCompatibleRangeTest ( + IN EFI_GENERIC_MEMORY_TEST_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS StartAddress, + IN UINT64 Length + ) +; + +#endif diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.mbd b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.mbd new file mode 100644 index 0000000000..2b770fe63d --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.mbd @@ -0,0 +1,44 @@ + + + + + NullMemoryTest + 96B5C032-DF4C-4b6e-8232-438DCF448D0E + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + DxeServicesTableLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.msa b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.msa new file mode 100644 index 0000000000..89c1b40348 --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/NullMemoryTest.msa @@ -0,0 +1,60 @@ + + + + + NullMemoryTest + DXE_DRIVER + BS_DRIVER + 96B5C032-DF4C-4b6e-8232-438DCF448D0E + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverEntryPoint + DxeServicesTableLib + BaseLib + MemoryAllocationLib + UefiBootServicesTableLib + + + Common.h + NullMemoryTest.c + NullMemoryTest.h + NullMemoryTest.dxs + + + MdePkg + EdkModulePkg + + + GenericMemTest + + + + GenericMemoryTestEntryPoint + + + diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Dxe/build.xml b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/build.xml new file mode 100644 index 0000000000..c392081b01 --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.c b/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.c new file mode 100644 index 0000000000..e091ae18fb --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.c @@ -0,0 +1,154 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BaseMemoryTest.c + +Abstract: + + The PEI memory test support + +--*/ + +#include +#include + +static PEI_BASE_MEMORY_TEST_PPI mPeiBaseMemoryTestPpi = { BaseMemoryTest }; + +static EFI_PEI_PPI_DESCRIPTOR PpiListPeiBaseMemoryTest = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiBaseMemoryTestPpiGuid, + &mPeiBaseMemoryTestPpi +}; + +EFI_STATUS +EFIAPI +PeiBaseMemoryTestInit ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ +Description: + + Entry point function of BaseMemoryTestInit Peim. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + FfsHeader - Ffs header pointer + +Returns: + + Status - Result of InstallPpi + +--*/ +{ + EFI_STATUS Status; + + Status = (**PeiServices).InstallPpi (PeiServices, &PpiListPeiBaseMemoryTest); + + return Status; +} + +EFI_STATUS +EFIAPI +BaseMemoryTest ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_BASE_MEMORY_TEST_PPI *This, + IN EFI_PHYSICAL_ADDRESS BeginAddress, + IN UINT64 MemoryLength, + IN PEI_MEMORY_TEST_OP Operation, + OUT EFI_PHYSICAL_ADDRESS *ErrorAddress + ) +/*++ +Description: + + Test base memory. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + This - Pei memory test PPI pointer. + BeginAddress - Beginning of the memory address to be checked. + MemoryLength - Bytes of memory range to be checked. + Operation - Type of memory check operation to be performed. + ErrorAddress - Return the address of the error memory address. + ErrorAddress - Address which has error when checked. + +Returns: + + Status - Result of InstallPpi + +--*/ +{ + UINT32 TestPattern; + UINT32 TestMask; + EFI_PHYSICAL_ADDRESS TempAddress; + UINT32 SpanSize; + + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + EFI_COMPUTING_UNIT_MEMORY + EFI_CU_MEMORY_PC_TEST + ); + + TestPattern = TEST_PATTERN; + TestMask = 0; + SpanSize = 0; + + // + // Make sure we don't try and test anything above the max physical address range + // + ASSERT_EFI_ERROR (BeginAddress + MemoryLength < EFI_MAX_ADDRESS); + + switch (Operation) { + case Extensive: + SpanSize = 0x4; + break; + + case Sparse: + case Quick: + SpanSize = COVER_SPAN; + break; + + case Ignore: + goto Done; + break; + } + // + // Write the test pattern into memory range + // + TempAddress = BeginAddress; + while (TempAddress < BeginAddress + MemoryLength) { + (*(UINT32 *) (UINTN) TempAddress) = TestPattern; + TempAddress += SpanSize; + } + // + // Read pattern from memory and compare it + // + TempAddress = BeginAddress; + while (TempAddress < BeginAddress + MemoryLength) { + if ((*(UINT32 *) (UINTN) TempAddress) != TestPattern) { + *ErrorAddress = TempAddress; + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED, + EFI_COMPUTING_UNIT_MEMORY | EFI_CU_MEMORY_EC_UNCORRECTABLE + ); + + return EFI_DEVICE_ERROR; + } + + TempAddress += SpanSize; + } + +Done: + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.h b/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.h new file mode 100644 index 0000000000..15d6c61bd4 --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.h @@ -0,0 +1,89 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BaseMemoryTest.h + +Abstract: + + Tiano PEIM to provide a PEI memory test service. + +--*/ + +#ifndef _PEI_BASE_MEMORY_TEST_H_ +#define _PEI_BASE_MEMORY_TEST_H_ + +#include + +// +// Some global define +// +#define COVER_SPAN 0x40000 +#define TEST_PATTERN 0x5A5A5A5A + +EFI_STATUS +EFIAPI +PeiBaseMemoryTestInit ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + FfsHeader - TODO: add argument description + PeiServices - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +BaseMemoryTest ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_BASE_MEMORY_TEST_PPI *This, + IN EFI_PHYSICAL_ADDRESS BeginAddress, + IN UINT64 MemoryLength, + IN PEI_MEMORY_TEST_OP Operation, + OUT EFI_PHYSICAL_ADDRESS *ErrorAddress + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PeiServices - TODO: add argument description + This - TODO: add argument description + BeginAddress - TODO: add argument description + MemoryLength - TODO: add argument description + Operation - TODO: add argument description + ErrorAddress - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.mbd b/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.mbd new file mode 100644 index 0000000000..59c52c9718 --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.mbd @@ -0,0 +1,39 @@ + + + + + PeiBaseMemoryTestInit + 736EB068-8C01-47c5-964B-1C57BD5D4D64 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + PeimEntryPoint + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + PeiServicesTablePointerLib + PeiMemoryLib + PeiCoreLib + BaseLib + + diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.msa b/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.msa new file mode 100644 index 0000000000..ff96a6b210 --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Pei/BaseMemoryTest.msa @@ -0,0 +1,54 @@ + + + + + PeiBaseMemoryTestInit + PEIM + PE32_PEIM + 736EB068-8C01-47c5-964B-1C57BD5D4D64 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + PeimEntryPoint + PeiCoreLib + + + BaseMemoryTest.c + + + MdePkg + EdkModulePkg + + + BaseMemoryTest + + + + PeiBaseMemoryTestInit + + + diff --git a/EdkModulePkg/Universal/GenericMemoryTest/Pei/build.xml b/EdkModulePkg/Universal/GenericMemoryTest/Pei/build.xml new file mode 100644 index 0000000000..4a96b6bda8 --- /dev/null +++ b/EdkModulePkg/Universal/GenericMemoryTest/Pei/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.c b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.c new file mode 100644 index 0000000000..6e4350f0ed --- /dev/null +++ b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.c @@ -0,0 +1,266 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MonotonicCounter.c + +Abstract: + + Produced the Monotonic Counter Services as defined in the DXE CIS + +Revision History: + +--*/ + +#include "MonotonicCounter.h" + +// +// The Monotonic Counter Handle +// +EFI_HANDLE mMonotonicCounterHandle = NULL; + +// +// The current Monotonic count value +// +UINT64 mEfiMtc; + + +// +// Event to use to update the Mtc's high part when wrapping +// +EFI_EVENT mEfiMtcEvent; + +// +// EfiMtcName - Variable name of the MTC value +// +CHAR16 *mEfiMtcName = (CHAR16 *) L"MTC"; + +// +// EfiMtcGuid - Guid of the MTC value +// +EFI_GUID mEfiMtcGuid = { 0xeb704011, 0x1402, 0x11d3, { 0x8e, 0x77, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } }; + +// +// Worker functions +// +EFI_STATUS +EFIAPI +MonotonicCounterDriverGetNextMonotonicCount ( + OUT UINT64 *Count + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_TPL OldTpl; + + // + // Can not be called after ExitBootServices() + // + if (EfiAtRuntime ()) { + return EFI_UNSUPPORTED; + } + // + // Check input parameters + // + if (Count == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Update the monotonic counter with a lock + // + OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + *Count = mEfiMtc; + mEfiMtc++; + gBS->RestoreTPL (OldTpl); + + // + // If the MSB bit of the low part toggled, then signal that the high + // part needs updated now + // + if ((((UINT32) mEfiMtc) ^ ((UINT32) *Count)) & 0x80000000) { + gBS->SignalEvent (mEfiMtcEvent); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +MonotonicCounterDriverGetNextHighMonotonicCount ( + OUT UINT32 *HighCount + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + EFI_TPL OldTpl; + + // + // Check input parameters + // + if (HighCount == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (!EfiAtRuntime ()) { + // + // Use a lock if called before ExitBootServices() + // + OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1; + mEfiMtc = LShiftU64 (*HighCount, 32); + gBS->RestoreTPL (OldTpl); + } else { + *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1; + mEfiMtc = LShiftU64 (*HighCount, 32); + } + // + // Update the NvRam store to match the new high part + // + Status = gRT->SetVariable ( + mEfiMtcName, + &mEfiMtcGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINT32), + HighCount + ); + + return Status; +} + +VOID +EFIAPI +EfiMtcEventHandler ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Monotonic count event handler. This handler updates the high monotonic count. + +Arguments: + + Event The event to handle + Context The event context + +Returns: + + EFI_SUCCESS The event has been handled properly + EFI_NOT_FOUND An error occurred updating the variable. + +--*/ +{ + UINT32 HighCount; + + MonotonicCounterDriverGetNextHighMonotonicCount (&HighCount); +} + +EFI_STATUS +EFIAPI +MonotonicCounterDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + +--*/ +{ + EFI_STATUS Status; + UINT32 HighCount; + UINTN BufferSize; + + // + // Make sure the Monotonic Counter Architectural Protocol is not already installed in the system + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiMonotonicCounterArchProtocolGuid); + + // + // Initialize event to handle overflows + // + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + EfiMtcEventHandler, + NULL, + &mEfiMtcEvent + ); + + ASSERT_EFI_ERROR (Status); + + // + // Read the last high part + // + BufferSize = sizeof (UINT32); + Status = gRT->GetVariable ( + mEfiMtcName, + &mEfiMtcGuid, + NULL, + &BufferSize, + &HighCount + ); + if (EFI_ERROR (Status)) { + HighCount = 0; + } + // + // Set the current value + // + mEfiMtc = LShiftU64 (HighCount, 32); + + // + // Increment the upper 32 bits for this boot + // Continue even if it fails. It will only fail if the variable services are + // not functional. + // + Status = MonotonicCounterDriverGetNextHighMonotonicCount (&HighCount); + + // + // Fill in the EFI Boot Services and EFI Runtime Services Monotonic Counter Fields + // + gBS->GetNextMonotonicCount = MonotonicCounterDriverGetNextMonotonicCount; + gRT->GetNextHighMonotonicCount = MonotonicCounterDriverGetNextHighMonotonicCount; + + // + // Install the Monotonic Counter Architctural Protocol onto a new handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mMonotonicCounterHandle, + &gEfiMonotonicCounterArchProtocolGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.dxs b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.dxs new file mode 100644 index 0000000000..d32e0288ff --- /dev/null +++ b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MonotonicCounter.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + EFI_VARIABLE_ARCH_PROTOCOL_GUID AND + EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.h b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.h new file mode 100644 index 0000000000..c86b15dd26 --- /dev/null +++ b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.h @@ -0,0 +1,36 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MonotonicCounter.h + +Abstract: + + Produces the Monotonic Counter services as defined in the DXE CIS + +--*/ + +#ifndef _MONOTONIC_COUNTER_DRIVER_H_ +#define _MONOTONIC_COUNTER_DRIVER_H_ + +// +// Function Prototypes +// +EFI_STATUS +EFIAPI +MonotonicCounterDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +#endif diff --git a/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.mbd b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.mbd new file mode 100644 index 0000000000..6a5fa71a76 --- /dev/null +++ b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.mbd @@ -0,0 +1,47 @@ + + + + + MonotonicCounter + AD608272-D07F-4964-801E-7BD3B7888652 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-22 14:36 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeMemoryAllocationLib + EdkDxeRuntimeDriverLib + + EdkDxeSalLib + + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.msa b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.msa new file mode 100644 index 0000000000..c86e89ee48 --- /dev/null +++ b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/MonotonicCounter.msa @@ -0,0 +1,70 @@ + + + + + MonotonicCounter + DXE_RUNTIME_DRIVER + RT_DRIVER + AD608272-D07F-4964-801E-7BD3B7888652 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-22 14:36 + + + BaseLib + UefiLib + UefiDriverEntryPoint + DxeRuntimeDriverLib + DebugLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + + + MonotonicCounter.c + MonotonicCounter.h + MonotonicCounter.dxs + + + MdePkg + EdkModulePkg + + + MonotonicCounter + + + + MTC + 0xeb704011, 0x1402, 0x11d3, 0x8e, 0x77, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + + + MonotonicCounterDriverInitialize + + + + + + + diff --git a/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/build.xml b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/build.xml new file mode 100644 index 0000000000..ef6b8c4aa9 --- /dev/null +++ b/EdkModulePkg/Universal/MonotonicCounter/RuntimeDxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/BC.mbd b/EdkModulePkg/Universal/Network/PxeBc/Dxe/BC.mbd new file mode 100644 index 0000000000..2262fc64c7 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/BC.mbd @@ -0,0 +1,42 @@ + + + + + BC + A3f436EA-A127-4EF8-957C-8048606FF670 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/BC.msa b/EdkModulePkg/Universal/Network/PxeBc/Dxe/BC.msa new file mode 100644 index 0000000000..e94492bac8 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/BC.msa @@ -0,0 +1,94 @@ + + + + + BC + UEFI_DRIVER + BS_DRIVER + A3f436EA-A127-4EF8-957C-8048606FF670 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseLib + PrintLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + bc.c + pxe_bc_arp.c + pxe_bc_dhcp.c + pxe_bc_igmp.c + pxe_bc_ip.c + pxe_bc_mtftp.c + pxe_bc_udp.c + pxe_loadfile.c + dhcp.h + bc.h + ip.h + ComponentName.c + Print.c + + + MdePkg + EdkModulePkg + + + Bis + LoadFile + PxeBaseCodeCallBack + SimpleNetwork + DevicePath + NetworkInterfaceIdentifier + NetworkInterfaceIdentifier2 + PxeBaseCode + + + + gEfiSmbiosTableGuid + + + + + SmbiosTable + + + + + InitializeBCDriver + + + + gPxeBcDriverBinding + gPxeBcComponentName + + + diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/ComponentName.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/ComponentName.c new file mode 100644 index 0000000000..2c11dc4556 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/ComponentName.c @@ -0,0 +1,160 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + ComponentName.c + +Abstract: + +--*/ + + +#include "Bc.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +PxeBcComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +PxeBcComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gPxeBcComponentName = { + PxeBcComponentNameGetDriverName, + PxeBcComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mPxeBcDriverNameTable[] = { + { + "eng", + (CHAR16 *) L"PXE Base Code Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +PxeBcComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gPxeBcComponentName.SupportedLanguages, + mPxeBcDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +PxeBcComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/Print.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/Print.c new file mode 100644 index 0000000000..4ea5cbadab --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/Print.c @@ -0,0 +1,81 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + Print.c + +Abstract: + +--*/ + + +#include + +UINTN +EFIAPI +AsciiPrint ( + IN CONST CHAR8 *Format, + ... + ) +/*++ + +Routine Description: + + Print function for a maximum of PXE_MAX_PRINT_BUFFER ascii + characters. + +Arguments: + + Format - Ascii format string see file header for more details. + + ... - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +{ + UINTN Return; + VA_LIST Marker; + UINTN Index; + UINTN MaxIndex; + CHAR16 Buffer[PXE_MAX_PRINT_BUFFER]; + CHAR16 UnicodeFormat[PXE_MAX_PRINT_BUFFER]; + + MaxIndex = AsciiStrLen ((CHAR8 *) Format); + if (MaxIndex > PXE_MAX_PRINT_BUFFER) { + // + // Format string was too long for use to process. + // + return 0; + } + + for (Index = 0; Index < PXE_MAX_PRINT_BUFFER; Index++) { + UnicodeFormat[Index] = (CHAR16) Format[Index]; + } + + VA_START (Marker, Format); + Return = UnicodeVSPrint (Buffer, sizeof (Buffer), UnicodeFormat, Marker); + VA_END (Marker); + + // + // Need to convert to Unicode to do an OutputString + // + + if (gST->ConOut != NULL) { + // + // To be extra safe make sure ConOut has been initialized + // + gST->ConOut->OutputString (gST->ConOut, Buffer); + } + + return Return; +} diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/bc.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/bc.c new file mode 100644 index 0000000000..b9f48912e2 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/bc.c @@ -0,0 +1,2510 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + bc.c + +Abstract: + +--*/ + +#include "bc.h" + +// +// +// +EFI_STATUS +EFIAPI +PxeBcDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +PxeBcDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +PxeBcDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +extern +VOID +InitArpHeader ( + VOID + ); +extern +VOID +OptionsStrucInit ( + VOID + ); + +// +// helper routines +// +VOID +CvtNum ( + IN UINTN Number, + IN UINT8 *Buffer, + IN INTN Length + ) +/*++ + + Routine Description: + Convert number to ASCII value + + Arguments: + Number - Numeric value to convert to decimal ASCII value. + Buffer - Buffer to place ASCII version of the Number + Length - Length of Buffer. + + Returns: + none - none + +--*/ +{ + UINTN Remainder; + + while (Length--) { + Remainder = Number % 10; + Number /= 10; + Buffer[Length] = (UINT8) ('0' + Remainder); + } +} + +VOID +UtoA10 ( + IN UINTN Number, + IN UINT8 *Buffer + ) +/*++ + + Routine Description: + Convert number to decimal ASCII value at Buffer location + + Arguments: + Number - Numeric value to convert to decimal ASCII value. + Buffer - Buffer to place ASCII version of the Number + + Returns: + none - none + +--*/ +{ + INTN Index; + UINT8 BuffArray[31]; + + BuffArray[30] = 0; + CvtNum (Number, BuffArray, 30); + + for (Index = 0; Index < 30; ++Index) { + if (BuffArray[Index] != '0') { + break; + } + } + + CopyMem (Buffer, BuffArray + Index, 31 - Index); +} + +UINTN +AtoU ( + IN UINT8 *Buffer + ) +/*++ + + Routine Description: + Convert ASCII numeric string to a UINTN value + + Arguments: + Number - Numeric value to convert to decimal ASCII value. + Buffer - Buffer to place ASCII version of the Number + + Returns: + Value - UINTN value of the ASCII string. + +--*/ +{ + UINTN Value; + INT8 Character; + + Value = 0; + Character = *Buffer++; + do { + Value = Value * 10 + Character - '0'; + Character = *Buffer++; + } while (Character); + + return Value; +} + +UINT64 +AtoU64 ( + IN UINT8 *Buffer + ) +/*++ + + Routine Description: + Convert ASCII numeric string to a UINTN value + + Arguments: + Number - Numeric value to convert to decimal ASCII value. + Buffer - Buffer to place ASCII version of the Number + + Returns: + Value - UINTN value of the ASCII string. + +--*/ +{ + UINT64 Value; + UINT8 Character; + + Value = 0; + while ((Character = *Buffer++) != '\0') { + Value = MultU64x32 (Value, 10) + (Character - '0'); + } + + return Value; +} +// +// random number generator +// +#define RANDOM_MULTIPLIER 2053 +#define RANDOM_ADD_IN_VALUE 19 + +VOID +SeedRandom ( + IN PXE_BASECODE_DEVICE *Private, + IN UINT16 InitialSeed + ) +/*++ + + Routine Description: + Initialize the Seed for the random number generator + + Arguments: + + Returns: + none - + +--*/ +{ + if (Private != NULL) { + Private->RandomSeed = InitialSeed; + } +} + +UINT16 +Random ( + IN PXE_BASECODE_DEVICE *Private + ) +/*++ + + Routine Description: + Generate and return a pseudo-random number + + Arguments: + + Returns: + Number - UINT16 random number + +--*/ +{ + UINTN Number; + + if (Private != NULL) { + Number = -(INTN) Private->RandomSeed * RANDOM_MULTIPLIER + RANDOM_ADD_IN_VALUE; + + return Private->RandomSeed = (UINT16) Number; + } else { + return 0; + } +} +// +// calculate the internet checksum (RFC 1071) +// return 16 bit ones complement of ones complement sum of 16 bit words +// +UINT16 +IpChecksum ( + IN UINT16 *Packet, + IN UINTN Length + ) +/*++ + + Routine Description: + Calculate the internet checksum (see RFC 1071) + + Arguments: + Packet - Buffer which contains the data to be checksummed + Length - Length to be checksummed + + Returns: + Checksum - Returns the 16 bit ones complement of + ones complement sum of 16 bit words + +--*/ +{ + UINT32 Sum; + UINT8 Odd; + + Sum = 0; + Odd = (UINT8) (Length & 1); + Length >>= 1; + while (Length--) { + Sum += *Packet++; + } + + if (Odd) { + Sum += *(UINT8 *) Packet; + } + + Sum = (Sum & 0xffff) + (Sum >> 16); + // + // in case above carried + // + Sum += Sum >> 16; + + return (UINT16) (~ (UINT16) Sum); +} + +UINT16 +IpChecksum2 ( + IN UINT16 *Header, + IN UINTN HeaderLen, + IN UINT16 *Message, + IN UINTN MessageLen + ) +/*++ + + Routine Description: + Calculate the internet checksum (see RFC 1071) + on a non contiguous header and data + + Arguments: + Header - Buffer which contains the data to be checksummed + HeaderLen - Length to be checksummed + Message - Buffer which contains the data to be checksummed + MessageLen - Length to be checksummed + + Returns: + Checksum - Returns the 16 bit ones complement of + ones complement sum of 16 bit words + +--*/ +{ + UINT32 Sum; + + Sum = (UINT16)~IpChecksum (Header, HeaderLen) + (UINT16)~IpChecksum (Message, MessageLen); + + // + // in case above carried + // + Sum += Sum >> 16; + + return (UINT16) (~ (UINT16) Sum); +} + +UINT16 +UpdateChecksum ( + IN UINT16 OldChksum, + IN UINT16 OldWord, + IN UINT16 NewWord + ) +/*++ + + Routine Description: + Adjust the internet checksum (see RFC 1071) on a single word update. + + Arguments: + OldChkSum - Checksum previously calculated + OldWord - Value + NewWord - New Value + + Returns: + Checksum - Returns the 16 bit ones complement of + ones complement sum of 16 bit words + +--*/ +{ + UINT32 sum; + + sum = ~OldChksum + NewWord - OldWord; + // + // in case above carried + // + sum += sum >> 16; + return (UINT16) (~ (UINT16) sum); +} + +STATIC +BOOLEAN +SetMakeCallback ( + IN PXE_BASECODE_DEVICE *Private + ) +/*++ + + Routine Description: + See if a callback is in play + + Arguments: + Private - Pointer to Pxe BaseCode Protocol + + Returns: + 0 - Callbacks are active on the handle + 1 - Callbacks are not active on the handle + +--*/ +{ + Private->EfiBc.Mode->MakeCallbacks = (BOOLEAN) (gBS->HandleProtocol ( + Private->Handle, + &gEfiPxeBaseCodeCallbackProtocolGuid, + (VOID *) &Private->CallbackProtocolPtr + ) == EFI_SUCCESS); + + DEBUG ( + (EFI_D_INFO, + "\nMode->MakeCallbacks == %d ", + Private->EfiBc.Mode->MakeCallbacks) + ); + + DEBUG ( + (EFI_D_INFO, + "\nPrivate->CallbackProtocolPtr == %xh ", + Private->CallbackProtocolPtr) + ); + + if (Private->CallbackProtocolPtr != NULL) { + DEBUG ( + (EFI_D_INFO, + "\nCallbackProtocolPtr->Revision = %xh ", + Private->CallbackProtocolPtr->Revision) + ); + + DEBUG ( + (EFI_D_INFO, + "\nCallbackProtocolPtr->Callback = %xh ", + Private->CallbackProtocolPtr->Callback) + ); + } + + return Private->EfiBc.Mode->MakeCallbacks; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +WaitForReceive ( + IN PXE_BASECODE_DEVICE *Private, + IN EFI_PXE_BASE_CODE_FUNCTION Function, + IN EFI_EVENT TimeoutEvent, + IN OUT UINTN *HeaderSizePtr, + IN OUT UINTN *BufferSizePtr, + IN OUT UINT16 *ProtocolPtr + ) +/*++ + + Routine Description: + Routine which does an SNP->Receive over a timeout period and doing callbacks + + Arguments: + Private - Pointer to Pxe BaseCode Protocol + Function - What PXE function to callback + TimeoutEvent - Timer event that will trigger when we have waited too + long for an incoming packet + HeaderSizePtr - Pointer to the size of the Header size + BufferSizePtr - Pointer to the size of the Buffer size + ProtocolPtr - The protocol to sniff for (namely, UDP/etc) + + Returns: + 0 - Something was returned + !0 - Like there was nothing to receive (EFI_TIMEOUT/NOT_READY) + +--*/ +{ + EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr; + EFI_PXE_CALLBACK CallbackPtr; + EFI_STATUS StatCode; + EFI_EVENT CallbackEvent; + + // + // Initialize pointer to SNP interface + // + SnpPtr = Private->SimpleNetwork; + + // + // Initialize pointer to PxeBc callback routine - if any + // + CallbackPtr = (Private->EfiBc.Mode->MakeCallbacks) ? Private->CallbackProtocolPtr->Callback : NULL; + + // + // Create callback event and set timer + // + StatCode = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &CallbackEvent + ); + + if (EFI_ERROR (StatCode)) { + return EFI_DEVICE_ERROR; + } + + // + // every 100 milliseconds + // + StatCode = gBS->SetTimer ( + CallbackEvent, + TimerPeriodic, + 1000000 + ); + + if (EFI_ERROR (StatCode)) { + gBS->CloseEvent (CallbackEvent); + return EFI_DEVICE_ERROR; + } + // + // Loop until a packet is received or a receive error is detected or + // a callback abort is detected or a timeout event occurs. + // + for (;;) + { +#if 0 + // + // Check for received packet event. + // + if (!EFI_ERROR (gBS->CheckEvent (SnpPtr->WaitForPacket))) { + // + // Packet should be available. Attempt to read it. + // + *BufferSizePtr = BUFFER_ALLOCATE_SIZE; + + StatCode = SnpPtr->Receive ( + SnpPtr, + HeaderSizePtr, + BufferSizePtr, + Private->ReceiveBufferPtr, + 0, + 0, + ProtocolPtr + ); + + if (EFI_ERROR (StatCode)) { + break; + } + // + // Packet was received. Make received callback then return. + // + if (CallbackPtr != NULL) { + StatCode = CallbackPtr ( + Private->CallbackProtocolPtr, + Function, + TRUE, + (UINT32) *BufferSizePtr, + (EFI_PXE_BASE_CODE_PACKET *) Private->ReceiveBufferPtr + ); + + if (StatCode != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { + StatCode = EFI_ABORTED; + } else { + StatCode = EFI_SUCCESS; + } + } + + break; + } + +#else + // + // Poll for received packet. + // + *BufferSizePtr = BUFFER_ALLOCATE_SIZE; + + StatCode = SnpPtr->Receive ( + SnpPtr, + HeaderSizePtr, + BufferSizePtr, + Private->ReceiveBufferPtr, + 0, + 0, + ProtocolPtr + ); + + if (!EFI_ERROR (StatCode)) { + // + // Packet was received. Make received callback then return. + // + if (CallbackPtr != NULL) { + StatCode = CallbackPtr ( + Private->CallbackProtocolPtr, + Function, + TRUE, + (UINT32) *BufferSizePtr, + (EFI_PXE_BASE_CODE_PACKET *) Private->ReceiveBufferPtr + ); + + if (StatCode != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { + StatCode = EFI_ABORTED; + } else { + StatCode = EFI_SUCCESS; + } + } + + break; + } + + if (StatCode != EFI_NOT_READY) { + break; + } +#endif + // + // Check for callback event. + // + if (!EFI_ERROR (gBS->CheckEvent (CallbackEvent))) { + // + // Make periodic callback if callback pointer is initialized. + // + if (CallbackPtr != NULL) { + StatCode = CallbackPtr ( + Private->CallbackProtocolPtr, + Function, + FALSE, + 0, + NULL + ); + + // + // Abort if directed to by callback routine. + // + if (StatCode != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { + StatCode = EFI_ABORTED; + break; + } + } + } + // + // Check for timeout event. + // + if (TimeoutEvent == 0) { + StatCode = EFI_TIMEOUT; + break; + } + + if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { + StatCode = EFI_TIMEOUT; + break; + } + // + // Check IGMP timer events. + // + IgmpCheckTimers (Private); + } + + gBS->CloseEvent (CallbackEvent); + + return StatCode; +} + +EFI_STATUS +SendPacket ( + PXE_BASECODE_DEVICE *Private, + VOID *HeaderPtr, + VOID *PacketPtr, + INTN PacketLen, + VOID *HardwareAddr, + UINT16 MediaProtocol, + IN EFI_PXE_BASE_CODE_FUNCTION Function + ) +/*++ + + Routine Description: + Routine which does an SNP->Transmit of a buffer + + Arguments: + Private - Pointer to Pxe BaseCode Protocol + HeaderPtr - Pointer to the buffer + PacketPtr - Pointer to the packet to send + PacketLen - The length of the entire packet to send + HardwareAddr - Pointer to the MAC address of the destination + MediaProtocol - What type of frame to create (RFC 1700) - IE. Ethernet + Function - What PXE function to callback + + Returns: + 0 - Something was sent + !0 - An error was encountered during sending of a packet + +--*/ +{ + EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr; + EFI_SIMPLE_NETWORK_MODE *SnpModePtr; + EFI_PXE_CALLBACK CallbackPtr; + EFI_STATUS StatCode; + EFI_EVENT TimeoutEvent; + UINT32 IntStatus; + VOID *TxBuf; + + // + // + // + CallbackPtr = Private->EfiBc.Mode->MakeCallbacks ? Private->CallbackProtocolPtr->Callback : 0; + + SnpPtr = Private->SimpleNetwork; + SnpModePtr = SnpPtr->Mode; + + // + // clear prior interrupt status + // + StatCode = SnpPtr->GetStatus (SnpPtr, &IntStatus, 0); + + if (EFI_ERROR (StatCode)) { + DEBUG ( + (EFI_D_WARN, + "\nSendPacket() Exit #1 %xh (%r)", + StatCode, + StatCode) + ); + return StatCode; + } + + Private->DidTransmit = FALSE; + + if (CallbackPtr != NULL) { + if (CallbackPtr ( + Private->CallbackProtocolPtr, + Function, + FALSE, + (UINT32) PacketLen, + PacketPtr + ) != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { + DEBUG ( + (EFI_D_WARN, + "\nSendPacket() Exit #2 %xh (%r)", + EFI_ABORTED, + EFI_ABORTED) + ); + return EFI_ABORTED; + } + } + // + // put packet in transmit queue + // headersize should be zero if not filled in + // + StatCode = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); + + if (EFI_ERROR (StatCode)) { + DEBUG ( + (EFI_D_ERROR, + "Could not create transmit timeout event. %r\n", + StatCode) + ); + return EFI_DEVICE_ERROR; + } + + // + // 5 milliseconds + // + StatCode = gBS->SetTimer ( + TimeoutEvent, + TimerRelative, + 50000 + ); + + if (EFI_ERROR (StatCode)) { + DEBUG ( + (EFI_D_ERROR, + "Could not set transmit timeout event timer. %r\n", + StatCode) + ); + gBS->CloseEvent (TimeoutEvent); + return EFI_DEVICE_ERROR; + } + + for (;;) { + StatCode = SnpPtr->Transmit ( + SnpPtr, + (UINTN) SnpPtr->Mode->MediaHeaderSize, + (UINTN) (PacketLen + SnpPtr->Mode->MediaHeaderSize), + HeaderPtr, + &SnpModePtr->CurrentAddress, + (EFI_MAC_ADDRESS *) HardwareAddr, + &MediaProtocol + ); + + if (StatCode != EFI_NOT_READY) { + break; + } + + if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { + StatCode = EFI_TIMEOUT; + break; + } + } + + gBS->CloseEvent (TimeoutEvent); + + if (EFI_ERROR (StatCode)) { + DEBUG ( + (EFI_D_WARN, + "\nSendPacket() Exit #3 %xh (%r)", + StatCode, + StatCode) + ); + return StatCode; + } + // + // remove transmit buffer from snp's unused queue + // done this way in case someday things are buffered and we don't get it back + // immediately + // + StatCode = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); + + if (EFI_ERROR (StatCode)) { + DEBUG ( + (EFI_D_ERROR, + "Could not create transmit status timeout event. %r\n", + StatCode) + ); + return EFI_DEVICE_ERROR; + } + + // + // 5 milliseconds + // + StatCode = gBS->SetTimer ( + TimeoutEvent, + TimerRelative, + 50000 + ); + + if (EFI_ERROR (StatCode)) { + DEBUG ( + (EFI_D_ERROR, + "Could not set transmit status timeout event timer. %r\n", + StatCode) + ); + gBS->CloseEvent (TimeoutEvent); + return EFI_DEVICE_ERROR; + } + + for (;;) { + StatCode = SnpPtr->GetStatus (SnpPtr, &IntStatus, &TxBuf); + + if (EFI_ERROR (StatCode)) { + DEBUG ( + (EFI_D_WARN, + "\nSendPacket() Exit #4 %xh (%r)", + StatCode, + StatCode) + ); + break; + } + + if (IntStatus & EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT) { + Private->DidTransmit = TRUE; + } + + if (TxBuf != NULL) { + break; + } + + if (!EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { + StatCode = EFI_TIMEOUT; + break; + } + } + + gBS->CloseEvent (TimeoutEvent); + + return StatCode; +} +// +// +// +EFI_BIS_PROTOCOL * +PxebcBisStart ( + IN PXE_BASECODE_DEVICE *Private, + OUT BIS_APPLICATION_HANDLE *BisAppHandle, + OUT OPTIONAL EFI_BIS_DATA **BisDataSigInfo + ) +/*++ +Routine description: + Locate BIS interface and if found, try to start it. + +Parameters: + Private := Pointer to PxeBc protocol + BisAppHandle := Pointer to BIS application handle storage + BisDataSigInfo := Pointer to BIS signature information storage +Returns: +--*/ +{ + EFI_STATUS EfiStatus; + EFI_HANDLE BisHandleBuffer; + UINTN BisHandleCount; + EFI_BIS_PROTOCOL *BisPtr; + EFI_BIS_VERSION BisInterfaceVersion; + BOOLEAN BisCheckFlag; + + BisHandleCount = sizeof (EFI_HANDLE); + BisCheckFlag = FALSE; + + // + // Locate BIS protocol handle (if present). + // If BIS protocol handle is not found, return NULL. + // + DEBUG ((EFI_D_INFO, "\ngBS->LocateHandle() ")); + + EfiStatus = gBS->LocateHandle ( + ByProtocol, + &gEfiBisProtocolGuid, + NULL, + &BisHandleCount, + &BisHandleBuffer + ); + + if (EFI_ERROR (EfiStatus)) { + // + // Any error means that there is no BIS. + // Note - It could mean that there are more than + // one BIS protocols installed, but that scenario + // is not yet supported. + // + DEBUG ( + (EFI_D_WARN, + "\nPxebcBisStart()""\n gBS->LocateHandle() %r (%xh)\n", + EfiStatus, + EfiStatus) + ); + + return NULL; + } + + if (BisHandleCount != sizeof BisHandleBuffer) { + // + // This really should never happen, but I am paranoid. + // + DEBUG ( + (EFI_D_NET, + "\nPxebcBisStart() BisHandleCount != %d\n", + sizeof BisHandleBuffer) + ); + + return NULL; + } + + DEBUG ((EFI_D_INFO, "BIS handle found.")); + + // + // Locate BIS protocol interface. + // If the BIS protocol interface cannot be found, return NULL. + // + DEBUG ((EFI_D_INFO, "\ngBS->HandleProtocol() ")); + + EfiStatus = gBS->HandleProtocol ( + BisHandleBuffer, + &gEfiBisProtocolGuid, + (VOID **) &BisPtr + ); + + if (EFI_ERROR (EfiStatus)) { + DEBUG ( + (EFI_D_WARN, + "\nPxebcBisStart()""\n gBS->HandleProtocol() %r (%xh)\n", + EfiStatus, + EfiStatus) + ); + + return NULL; + } + + if (BisPtr == NULL) { + // + // This really should never happen. + // + DEBUG ( + (EFI_D_NET, + "\nPxebcBisStart()""\n gBS->HandleProtocoL() ""BIS protocol interface pointer is NULL!\n") + ); + + return NULL; + } + + DEBUG ((EFI_D_INFO, "BIS protocol interface found.")); + + // + // Check that all of the BIS API function pointers are not NULL. + // + if (BisPtr->Initialize == NULL || + BisPtr->Shutdown == NULL || + BisPtr->Free == NULL || + BisPtr->GetBootObjectAuthorizationCertificate == NULL || + BisPtr->GetBootObjectAuthorizationCheckFlag == NULL || + BisPtr->GetBootObjectAuthorizationUpdateToken == NULL || + BisPtr->GetSignatureInfo == NULL || + BisPtr->UpdateBootObjectAuthorization == NULL || + BisPtr->VerifyBootObject == NULL || + BisPtr->VerifyObjectWithCredential == NULL + ) { + DEBUG ( + ( + EFI_D_NET, + "\nPxebcBisStart()""\n BIS protocol interface is invalid." + "\n At least one BIS protocol function pointer is NULL.\n" + ) + ); + + return NULL; + } + // + // Initialize BIS. + // If BIS does not initialize, return NULL. + // + DEBUG ((EFI_D_INFO, "\nBisPtr->Initialize() ")); + + BisInterfaceVersion.Major = BIS_VERSION_1; + + EfiStatus = BisPtr->Initialize ( + BisPtr, + BisAppHandle, + &BisInterfaceVersion, + NULL + ); + + if (EFI_ERROR (EfiStatus)) { + DEBUG ( + (EFI_D_WARN, + "\nPxebcBisStart()""\n BisPtr->Initialize() %r (%xh)\n", + EfiStatus, + EfiStatus) + ); + + return NULL; + } + + DEBUG ( + (EFI_D_INFO, + " BIS version: %d.%d", + BisInterfaceVersion.Major, + BisInterfaceVersion.Minor) + ); + + // + // If the requested BIS API version is not supported, + // shutdown BIS and return NULL. + // + if (BisInterfaceVersion.Major != BIS_VERSION_1) { + DEBUG ( + (EFI_D_WARN, + "\nPxebcBisStart()""\n BIS version %d.%d not supported by PXE BaseCode.\n", + BisInterfaceVersion.Major, + BisInterfaceVersion.Minor) + ); + + BisPtr->Shutdown (*BisAppHandle); + return NULL; + } + // + // Get BIS check flag. + // If the BIS check flag cannot be read, shutdown BIS and return NULL. + // + DEBUG ((EFI_D_INFO, "\nBisPtr->GetBootObjectAuthorizationCheckFlag() ")); + + EfiStatus = BisPtr->GetBootObjectAuthorizationCheckFlag (*BisAppHandle, &BisCheckFlag); + + if (EFI_ERROR (EfiStatus)) { + DEBUG ( + (EFI_D_WARN, + "\nPxebcBisStart()""\n BisPtr->GetBootObjectAuthorizationCheckFlag() %r (%xh)\n", + EfiStatus, + EfiStatus) + ); + + BisPtr->Shutdown (*BisAppHandle); + return NULL; + } + // + // If the BIS check flag is FALSE, shutdown BIS and return NULL. + // + if (!BisCheckFlag) { + DEBUG ((EFI_D_INFO, "\nBIS check flag is FALSE.\n")); + BisPtr->Shutdown (*BisAppHandle); + return NULL; + } else { + DEBUG ((EFI_D_INFO, "\nBIS check flag is TRUE.")); + } + // + // Early out if caller does not want signature information. + // + if (BisDataSigInfo == NULL) { + return BisPtr; + } + // + // Get BIS signature information. + // If the signature information cannot be read or is invalid, + // shutdown BIS and return NULL. + // + DEBUG ((EFI_D_INFO, "\nBisPtr->GetSignatureInfo() ")); + + EfiStatus = BisPtr->GetSignatureInfo (*BisAppHandle, BisDataSigInfo); + + if (EFI_ERROR (EfiStatus)) { + DEBUG ( + (EFI_D_WARN, + "\nPxebcBisStart()""\n BisPtr_GetSignatureInfo() %r (%xh)\n", + EfiStatus, + EfiStatus) + ); + + BisPtr->Shutdown (*BisAppHandle); + return NULL; + } + + if (*BisDataSigInfo == NULL) { + // + // This should never happen. + // + DEBUG ( + (EFI_D_NET, + "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Data pointer is NULL!\n") + ); + + BisPtr->Shutdown (*BisAppHandle); + return NULL; + } + + if ((*BisDataSigInfo)->Length < sizeof (EFI_BIS_SIGNATURE_INFO) || + (*BisDataSigInfo)->Length % sizeof (EFI_BIS_SIGNATURE_INFO) || + (*BisDataSigInfo)->Length > sizeof (EFI_BIS_SIGNATURE_INFO) * 63 + ) { + // + // This should never happen. + // + DEBUG ( + (EFI_D_NET, + "\nPxebcBisStart()""\n BisPtr->GetSignatureInfo() Invalid BIS siginfo length.\n") + ); + + BisPtr->Free (*BisAppHandle, *BisDataSigInfo); + BisPtr->Shutdown (*BisAppHandle); + return NULL; + } + + return BisPtr; +} + +VOID +PxebcBisStop ( + EFI_BIS_PROTOCOL *BisPtr, + BIS_APPLICATION_HANDLE BisAppHandle, + EFI_BIS_DATA *BisDataSigInfo + ) +/*++ +Routine description: + Stop the BIS interface and release allocations. + +Parameters: + BisPtr := Pointer to BIS interface + BisAppHandle := BIS application handle + BisDataSigInfo := Pointer to BIS signature information data + +Returns: + +--*/ +{ + if (BisPtr == NULL) { + return ; + } + // + // Free BIS allocated resources and shutdown BIS. + // Return TRUE - BIS support is officially detected. + // + if (BisDataSigInfo != NULL) { + BisPtr->Free (BisAppHandle, BisDataSigInfo); + } + + BisPtr->Shutdown (BisAppHandle); +} + +BOOLEAN +PxebcBisVerify ( + PXE_BASECODE_DEVICE *Private, + VOID *FileBuffer, + UINTN FileLength, + VOID *CredentialBuffer, + UINTN CredentialLength + ) +/*++ +Routine description: + Verify image and credential file. + +Parameters: + Private := Pointer to PxeBc interface + FileBuffer := Pointer to image buffer + FileLength := Image length in bytes + CredentialBuffer := Pointer to credential buffer + CredentialLength := Credential length in bytes + +Returns: + TRUE := verified + FALSE := not verified +--*/ +{ + EFI_BIS_PROTOCOL *BisPtr; + BIS_APPLICATION_HANDLE BisAppHandle; + EFI_BIS_DATA FileData; + EFI_BIS_DATA CredentialData; + EFI_STATUS EfiStatus; + BOOLEAN IsVerified; + + if (Private == NULL || FileBuffer == NULL || FileLength == 0 || CredentialBuffer == NULL || CredentialLength == 0) { + return FALSE; + } + + BisPtr = PxebcBisStart (Private, &BisAppHandle, NULL); + + if (BisPtr == NULL) { + return FALSE; + } + + FileData.Length = (UINT32) FileLength; + FileData.Data = FileBuffer; + CredentialData.Length = (UINT32) CredentialLength; + CredentialData.Data = CredentialBuffer; + + EfiStatus = BisPtr->VerifyBootObject ( + BisAppHandle, + &CredentialData, + &FileData, + &IsVerified + ); + + PxebcBisStop (BisPtr, BisAppHandle, NULL); + + return (BOOLEAN) ((EFI_ERROR (EfiStatus)) ? FALSE : (IsVerified ? TRUE : FALSE)); +} + +BOOLEAN +PxebcBisDetect ( + PXE_BASECODE_DEVICE *Private + ) +/*++ +Routine description: + Check for BIS interface presence. + +Parameters: + Private := Pointer to PxeBc interface + +Returns: + TRUE := BIS present + FALSE := BIS not present +--*/ +{ + EFI_BIS_PROTOCOL *BisPtr; + BIS_APPLICATION_HANDLE BisAppHandle; + EFI_BIS_DATA *BisDataSigInfo; + + BisPtr = PxebcBisStart (Private, &BisAppHandle, &BisDataSigInfo); + + if (BisPtr == NULL) { + return FALSE; + } + + PxebcBisStop (BisPtr, BisAppHandle, BisDataSigInfo); + + return TRUE; +} + +VOID *BCNotifyReg; + +EFI_STATUS +EFIAPI +BcStart ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN UseIPv6 + ) +/*++ + + Routine Description: + Start and initialize the BaseCode protocol, Simple Network protocol and UNDI. + + Arguments: + Private - Pointer to Pxe BaseCode Protocol + UseIPv6 - Do we want to support IPv6? + + Returns: + EFI_SUCCESS + EFI_INVALID_PARAMETER + EFI_UNSUPPORTED + EFI_ALREADY_STARTED + EFI_OUT_OF_RESOURCES + Status is also returned from SNP.Start() and SNP.Initialize(). + +--*/ +{ + EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr; + EFI_SIMPLE_NETWORK_MODE *SnpModePtr; + EFI_STATUS Status; + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + // + // Lock the instance data + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + // + // Make sure BaseCode is not already started. + // + if (This->Mode->Started) { + DEBUG ((EFI_D_WARN, "\nBcStart() BC is already started.\n")); + EfiReleaseLock (&Private->Lock); + return EFI_ALREADY_STARTED; + } + +#if !SUPPORT_IPV6 + // + // Fail if IPv6 is requested and not supported. + // + if (UseIPv6) { + DEBUG ((EFI_D_WARN, "\nBcStart() IPv6 is not supported.\n")); + EfiReleaseLock (&Private->Lock); + return EFI_UNSUPPORTED; + } +#endif + // + // Setup shortcuts to SNP protocol and data structure. + // + SnpPtr = Private->SimpleNetwork; + SnpModePtr = SnpPtr->Mode; + + // + // Start and initialize SNP. + // + if (SnpModePtr->State == EfiSimpleNetworkStopped) { + StatCode = (*SnpPtr->Start) (SnpPtr); + + if (SnpModePtr->State != EfiSimpleNetworkStarted) { + DEBUG ((EFI_D_WARN, "\nBcStart() Could not start SNP.\n")); + EfiReleaseLock (&Private->Lock); + return StatCode; + } + } + // + // acquire memory for mode and transmit/receive buffers + // + if (SnpModePtr->State == EfiSimpleNetworkStarted) { + StatCode = (*SnpPtr->Initialize) (SnpPtr, 0, 0); + + if (SnpModePtr->State != EfiSimpleNetworkInitialized) { + DEBUG ((EFI_D_WARN, "\nBcStart() Could not initialize SNP.")); + EfiReleaseLock (&Private->Lock); + return StatCode; + } + } + // + // Dump debug info. + // + DEBUG ((EFI_D_INFO, "\nBC Start()")); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->State %Xh", + SnpModePtr->State) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->HwAddressSize %Xh", + SnpModePtr->HwAddressSize) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->MediaHeaderSize %Xh", + SnpModePtr->MediaHeaderSize) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->MaxPacketSize %Xh", + SnpModePtr->MaxPacketSize) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->MacAddressChangeable %Xh", + SnpModePtr->MacAddressChangeable) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->MultipleTxSupported %Xh", + SnpModePtr->MultipleTxSupported) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->CurrentAddress %Xh", + *((UINTN *)&SnpModePtr->CurrentAddress)) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->BroadcastAddress %Xh", + *((UINTN *)&SnpModePtr->BroadcastAddress)) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->PermanentAddress %Xh", + *((UINTN *)&SnpModePtr->PermanentAddress)) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->NvRamSize %Xh", + SnpModePtr->NvRamSize) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->NvRamAccessSize %Xh", + SnpModePtr->NvRamAccessSize) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->ReceiveFilterMask %Xh", + SnpModePtr->ReceiveFilterMask) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->ReceiveFilterSetting %Xh", + SnpModePtr->ReceiveFilterSetting) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->MCastFilterCount %Xh", + SnpModePtr->MCastFilterCount) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->MCastFilter %Xh", + SnpModePtr->MCastFilter) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->IfType %Xh", + SnpModePtr->IfType) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->MediaPresentSupported %Xh", + SnpModePtr->MediaPresentSupported) + ); + DEBUG ( + (EFI_D_INFO, + "\nSnpModePtr->MediaPresent %Xh", + SnpModePtr->MediaPresent) + ); + + // + // If media check is supported and there is no media, + // return error to caller. + // + if (SnpModePtr->MediaPresentSupported && !SnpModePtr->MediaPresent) { + DEBUG ((EFI_D_WARN, "\nBcStart() Media not present.\n")); + EfiReleaseLock (&Private->Lock); + return EFI_NO_MEDIA; + } + // + // Allocate Tx/Rx buffers + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + BUFFER_ALLOCATE_SIZE, + (VOID **) &Private->TransmitBufferPtr + ); + + if (!EFI_ERROR (Status)) { + ZeroMem (Private->TransmitBufferPtr, BUFFER_ALLOCATE_SIZE); + } else { + DEBUG ((EFI_D_NET, "\nBcStart() Could not alloc TxBuf.\n")); + EfiReleaseLock (&Private->Lock); + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + BUFFER_ALLOCATE_SIZE, + (VOID **) &Private->ReceiveBufferPtr + ); + + if (!EFI_ERROR (Status)) { + ZeroMem (Private->ReceiveBufferPtr, BUFFER_ALLOCATE_SIZE); + } else { + DEBUG ((EFI_D_NET, "\nBcStart() Could not alloc RxBuf.\n")); + gBS->FreePool (Private->TransmitBufferPtr); + EfiReleaseLock (&Private->Lock); + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + 256, + (VOID **) &Private->TftpErrorBuffer + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (Private->ReceiveBufferPtr); + gBS->FreePool (Private->TransmitBufferPtr); + EfiReleaseLock (&Private->Lock); + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->AllocatePool (EfiBootServicesData, 256, (VOID **) &Private->TftpAckBuffer); + + if (EFI_ERROR (Status)) { + gBS->FreePool (Private->TftpErrorBuffer); + gBS->FreePool (Private->ReceiveBufferPtr); + gBS->FreePool (Private->TransmitBufferPtr); + EfiReleaseLock (&Private->Lock); + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize private BaseCode instance data + // + do { + Private->RandomPort = (UINT16) (Private->RandomPort + PXE_RND_PORT_LOW + Random (Private)); + } while (Private->RandomPort < PXE_RND_PORT_LOW); + + Private->Igmpv1TimeoutEvent = NULL; + Private->UseIgmpv1Reporting = TRUE; + Private->IpLength = IP_ADDRESS_LENGTH (Private->EfiBc.Mode); + + // + // Initialize Mode structure + // + // + // check for callback protocol and set boolean + // + SetMakeCallback (Private); + Private->EfiBc.Mode->Started = TRUE; + Private->EfiBc.Mode->TTL = DEFAULT_TTL; + Private->EfiBc.Mode->ToS = DEFAULT_ToS; + Private->EfiBc.Mode->UsingIpv6 = UseIPv6; + Private->EfiBc.Mode->DhcpDiscoverValid = FALSE; + Private->EfiBc.Mode->DhcpAckReceived = FALSE; + Private->EfiBc.Mode->ProxyOfferReceived = FALSE; + Private->EfiBc.Mode->PxeDiscoverValid = FALSE; + Private->EfiBc.Mode->PxeReplyReceived = FALSE; + Private->EfiBc.Mode->PxeBisReplyReceived = FALSE; + Private->EfiBc.Mode->IcmpErrorReceived = FALSE; + Private->EfiBc.Mode->TftpErrorReceived = FALSE; + ZeroMem (&Private->EfiBc.Mode->StationIp, sizeof (EFI_IP_ADDRESS)); + ZeroMem (&Private->EfiBc.Mode->SubnetMask, sizeof (EFI_IP_ADDRESS)); + Private->EfiBc.Mode->IpFilter.Filters = 0; + Private->EfiBc.Mode->IpFilter.IpCnt = 0; + Private->EfiBc.Mode->ArpCacheEntries = 0; + Private->EfiBc.Mode->RouteTableEntries = 0; + ZeroMem (&Private->EfiBc.Mode->IcmpError, sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)); + ZeroMem (&Private->EfiBc.Mode->TftpError, sizeof (EFI_PXE_BASE_CODE_TFTP_ERROR)); + + // + // Set to PXE_TRUE by the BC constructor if this BC implementation + // supports IPv6. + // + Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6; + +#if SUPPORT_IPV6 + Private->EfiBc.Mode->Ipv6Available = Private->NiiPtr->Ipv6Supported; +#else + Private->EfiBc.Mode->Ipv6Available = FALSE; +#endif + // + // Set to TRUE by the BC constructor if this BC implementation + // supports BIS. + // + Private->EfiBc.Mode->BisSupported = TRUE; + Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private); + + // + // This field is set to PXE_TRUE by the BC Start() function. When this + // field is PXE_TRUE, ARP packets are sent as needed to get IP and MAC + // addresses. This can cause unexpected delays in the DHCP(), Discover() + // and MTFTP() functions. Setting this to PXE_FALSE will cause these + // functions to fail if the required IP/MAC information is not in the + // ARP cache. The value of this field can be changed by an application + // at any time. + // + Private->EfiBc.Mode->AutoArp = TRUE; + + // + // Unlock the instance data + // + EfiReleaseLock (&Private->Lock); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +BcStop ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This + ) +/*++ + + Routine Description: + Stop the BaseCode protocol, Simple Network protocol and UNDI. + + Arguments: + Private - Pointer to Pxe BaseCode Protocol + + Returns: + + 0 - Successfully stopped + !0 - Failed +--*/ +{ + // + // Lock the instance data + // + EFI_PXE_BASE_CODE_MODE *PxebcMode; + EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr; + EFI_SIMPLE_NETWORK_MODE *SnpModePtr; + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + PxebcMode = Private->EfiBc.Mode; + SnpPtr = Private->SimpleNetwork; + SnpModePtr = SnpPtr->Mode; + + // + // Issue BC command + // + StatCode = EFI_NOT_STARTED; + + if (SnpModePtr->State == EfiSimpleNetworkInitialized) { + StatCode = (*SnpPtr->Shutdown) (SnpPtr); + } + + if (SnpModePtr->State == EfiSimpleNetworkStarted) { + StatCode = (*SnpPtr->Stop) (SnpPtr); + } + + if (Private->TransmitBufferPtr != NULL) { + gBS->FreePool (Private->TransmitBufferPtr); + Private->TransmitBufferPtr = NULL; + } + + if (Private->ReceiveBufferPtr != NULL) { + gBS->FreePool (Private->ReceiveBufferPtr); + Private->ReceiveBufferPtr = NULL; + } + + if (Private->ArpBuffer != NULL) { + gBS->FreePool (Private->ArpBuffer); + Private->ArpBuffer = NULL; + } + + if (Private->TftpErrorBuffer != NULL) { + gBS->FreePool (Private->TftpErrorBuffer); + Private->TftpErrorBuffer = NULL; + } + + if (Private->TftpAckBuffer != NULL) { + gBS->FreePool (Private->TftpAckBuffer); + Private->TftpAckBuffer = NULL; + } + + if (Private->Igmpv1TimeoutEvent != NULL) { + gBS->CloseEvent (Private->Igmpv1TimeoutEvent); + Private->Igmpv1TimeoutEvent = NULL; + } + + Private->FileSize = 0; + Private->EfiBc.Mode->Started = FALSE; + + // + // Unlock the instance data + // + EfiReleaseLock (&Private->Lock); + return StatCode; +} + +const IPV4_ADDR AllSystemsGroup = { { 224, 0, 0, 1 } }; + +EFI_STATUS +IpFilter ( + IN PXE_BASECODE_DEVICE *Private, + IN EFI_PXE_BASE_CODE_IP_FILTER *Filter + ) +/*++ + + Routine Description: + Set up the IP filter + + Arguments: + Private - Pointer to Pxe BaseCode Protocol + Filter - Pointer to the filter + + Returns: + + 0 - Successfully set the filter + !0 - Failed +--*/ +{ + EFI_STATUS StatCode; + EFI_MAC_ADDRESS MACadds[PXE_IP_FILTER_SIZE]; + EFI_PXE_BASE_CODE_MODE *PxebcMode; + EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr; + EFI_SIMPLE_NETWORK_MODE *SnpModePtr; + UINT32 Enable; + UINT32 Disable; + UINTN Index; + UINTN Index2; + + PxebcMode = Private->EfiBc.Mode; + SnpPtr = Private->SimpleNetwork; + SnpModePtr = SnpPtr->Mode; + + // + // validate input parameters + // must have a filter + // must not have any extra filter bits set + // + if (Filter == NULL || + (Filter->Filters &~FILTER_BITS) + // + // must not have a count which is too large or with no IP list + // + || + (Filter->IpCnt && (!Filter->IpList || Filter->IpCnt > PXE_IP_FILTER_SIZE)) + // + // must not have incompatible filters - promiscuous incompatible with anything else + // + || + ( + (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) && + ((Filter->Filters &~EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) || Filter->IpCnt) + ) + ) { + DEBUG ((EFI_D_INFO, "\nIpFilter() Exit #1")); + return EFI_INVALID_PARAMETER; + } + // + // promiscuous multicast incompatible with multicast in IP list + // + if (Filter->IpCnt && (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST)) { + for (Index = 0; Index < Filter->IpCnt; ++Index) { + if (IS_MULTICAST (&Filter->IpList[Index])) { + DEBUG ((EFI_D_INFO, "\nIpFilter() Exit #2")); + return EFI_INVALID_PARAMETER; + } + } + } + // + // leave groups for all those multicast which are no longer enabled + // + for (Index = 0; Index < PxebcMode->IpFilter.IpCnt; ++Index) { + if (!IS_MULTICAST (&PxebcMode->IpFilter.IpList[Index])) { + continue; + } + + for (Index2 = 0; Index2 < Filter->IpCnt; ++Index2) { + if (!CompareMem (&PxebcMode->IpFilter.IpList[Index], &Filter->IpList[Index2], IP_ADDRESS_LENGTH (PxebcMode))) { + // + // still enabled + // + break; + } + } + // + // if we didn't find it, remove from group + // + if (Index2 == Filter->IpCnt) { + IgmpLeaveGroup (Private, &PxebcMode->IpFilter.IpList[Index]); + } + } + // + // set enable bits, convert multicast ip adds, join groups + // allways leave receive broadcast enabled at hardware layer + // + Index2 = 0; + + if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) { + Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; + } else { + if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) { + Enable = EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + } else { + Enable = EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; + + for (Index = 0; Index < Filter->IpCnt; ++Index) { + CopyMem (&(PxebcMode->IpFilter.IpList[Index]), &(Filter->IpList[Index]), sizeof (EFI_IP_ADDRESS)); + + if (IS_MULTICAST (&Filter->IpList[Index])) { + EFI_IP_ADDRESS *TmpIp; + + Enable |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST; + + // + // if this is the first group, add the all systems group to mcast list + // + if (!Index2) + { +#if SUPPORT_IPV6 + if (PxebcMode->UsingIpv6) { + // + // TBD + // + } else +#endif + TmpIp = (EFI_IP_ADDRESS *) &AllSystemsGroup; + --Index; + } else { + TmpIp = (EFI_IP_ADDRESS *) &Filter->IpList[Index]; + } + // + // get MAC address of IP + // + StatCode = (*SnpPtr->MCastIpToMac) (SnpPtr, PxebcMode->UsingIpv6, TmpIp, &MACadds[Index2++]); + + if (EFI_ERROR (StatCode)) { + DEBUG ( + (EFI_D_INFO, + "\nIpFilter() Exit #2 %Xh (%r)", + StatCode, + StatCode) + ); + return StatCode; + } + } else { + Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; + } + } + } + + if (Filter->Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) { + Enable |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; + } + } + // + // if nothing changed, just return + // + DEBUG ( + (EFI_D_INFO, + "\nsnp->ReceiveFilterSetting == %Xh Filter->IpCnt == %Xh", + SnpModePtr->ReceiveFilterSetting, + Filter->IpCnt) + ); + + if (SnpModePtr->ReceiveFilterSetting == Enable && !Filter->IpCnt) { + DEBUG ((EFI_D_INFO, "\nIpFilter() Exit #4")); + return EFI_SUCCESS; + } + // + // disable those currently set but not set in new filter + // + Disable = SnpModePtr->ReceiveFilterSetting &~Enable; + + StatCode = SnpPtr->ReceiveFilters (SnpPtr, Enable, Disable, FALSE, Index2, MACadds); + + PxebcMode->IpFilter.IpCnt = Filter->IpCnt; + + // + // join groups for all multicast in list + // + for (Index = 0; Index < Filter->IpCnt; ++Index) { + if (IS_MULTICAST (&Filter->IpList[Index])) { + IgmpJoinGroup (Private, &Filter->IpList[Index]); + } + } + + DEBUG ((EFI_D_INFO, "\nIpFilter() Exit #5 %Xh (%r)", StatCode, StatCode)); + + return StatCode; +} + +EFI_STATUS +EFIAPI +BcIpFilter ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_IP_FILTER *Filter + ) +/*++ + + Routine Description: + Call the IP filter + + Arguments: + Private - Pointer to Pxe BaseCode Protocol + Filter - Pointer to the filter + + Returns: + + 0 - Successfully set the filter + !0 - Failed +--*/ +{ + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + // + // Lock the instance data and make sure started + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + if (This->Mode == NULL || !This->Mode->Started) { + DEBUG ((EFI_D_ERROR, "BC was not started.")); + EfiReleaseLock (&Private->Lock); + return EFI_NOT_STARTED; + } + + if (Filter == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Issue BC command + // + StatCode = IpFilter (Private, Filter); + + // + // Unlock the instance data + // + EfiReleaseLock (&Private->Lock); + return StatCode; +} + +EFI_STATUS +EFIAPI +BcSetParameters ( + EFI_PXE_BASE_CODE_PROTOCOL *This, + BOOLEAN *AutoArpPtr, + BOOLEAN *SendGuidPtr, + UINT8 *TimeToLivePtr, + UINT8 *TypeOfServicePtr, + BOOLEAN *MakeCallbackPtr + ) +/*++ + + Routine Description: + Set the Base Code behavior parameters + + Arguments: + This - Pointer to Pxe BaseCode Protocol + AutoArpPtr - Boolean to do ARP stuff + SendGuidPtr - Boolean whether or not to send GUID info + TimeToLivePtr - Value for Total time to live + TypeOfServicePtr - Value for Type of Service + MakeCallbackPtr - Boolean to determine if we make callbacks + + Returns: + + 0 - Successfully set the parameters + !0 - Failed +--*/ +{ + EFI_PXE_BASE_CODE_MODE *PxebcMode; + EFI_GUID TmpGuid; + CHAR8 *SerialNumberPtr; + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + // + // Lock the instance data and make sure started + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + if (This->Mode == NULL || !This->Mode->Started) { + DEBUG ((EFI_D_ERROR, "BC was not started.")); + EfiReleaseLock (&Private->Lock); + return EFI_NOT_STARTED; + } + + DEBUG ((EFI_D_INFO, "\nSetParameters() Entry. ")); + + PxebcMode = Private->EfiBc.Mode; + StatCode = EFI_SUCCESS; + + if (SendGuidPtr != NULL) { + if (*SendGuidPtr) { + if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber (&TmpGuid, &SerialNumberPtr) != EFI_SUCCESS) { + return EFI_INVALID_PARAMETER; + } + } + } + + if (MakeCallbackPtr != NULL) { + if (*MakeCallbackPtr) { + if (!SetMakeCallback (Private)) { + return EFI_INVALID_PARAMETER; + } + } + + PxebcMode->MakeCallbacks = *MakeCallbackPtr; + } + + if (AutoArpPtr != NULL) { + PxebcMode->AutoArp = *AutoArpPtr; + } + + if (SendGuidPtr != NULL) { + PxebcMode->SendGUID = *SendGuidPtr; + } + + if (TimeToLivePtr != NULL) { + PxebcMode->TTL = *TimeToLivePtr; + } + + if (TypeOfServicePtr != NULL) { + PxebcMode->ToS = *TypeOfServicePtr; + } + // + // Unlock the instance data + // + DEBUG ((EFI_D_INFO, "\nSetparameters() Exit = %xh ", StatCode)); + + EfiReleaseLock (&Private->Lock); + return StatCode; +} +// +// ////////////////////////////////////////////////////////// +// +// BC Set Station IP Routine +// +EFI_STATUS +EFIAPI +BcSetStationIP ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_IP_ADDRESS *StationIpPtr, + IN EFI_IP_ADDRESS *SubnetMaskPtr + ) +/*++ + + Routine Description: + Set the station IP address + + Arguments: + This - Pointer to Pxe BaseCode Protocol + StationIpPtr - Pointer to the requested IP address to set in base code + SubnetMaskPtr - Pointer to the requested subnet mask for the base code + + Returns: + + EFI_SUCCESS - Successfully set the parameters + EFI_NOT_STARTED - BC has not started +--*/ +{ + EFI_PXE_BASE_CODE_MODE *PxebcMode; + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + // + // Lock the instance data and make sure started + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + if (This->Mode == NULL || !This->Mode->Started) { + DEBUG ((EFI_D_ERROR, "BC was not started.")); + EfiReleaseLock (&Private->Lock); + return EFI_NOT_STARTED; + } + + PxebcMode = Private->EfiBc.Mode; + + if (StationIpPtr != NULL) { + CopyMem (&PxebcMode->StationIp, StationIpPtr, sizeof (EFI_IP_ADDRESS)); + Private->GoodStationIp = TRUE; + } + + if (SubnetMaskPtr != NULL) { + CopyMem (&PxebcMode->SubnetMask, SubnetMaskPtr, sizeof (EFI_IP_ADDRESS)); + } + // + // Unlock the instance data + // + EfiReleaseLock (&Private->Lock); + + return EFI_SUCCESS; +} + +EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding = { + PxeBcDriverSupported, + PxeBcDriverStart, + PxeBcDriverStop, + 0x10, + NULL, + NULL +}; + +EFI_STATUS +EFIAPI +PxeBcDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports Controller. Any Controller + than contains a Snp protocol can be supported. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to test. + RemainingDevicePath - Not used. + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_ALREADY_STARTED - This driver is already running on this device. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_PROTOCOL *SnpPtr; + + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleNetworkProtocolGuid, + (VOID **) &SnpPtr, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Controller, + &gEfiSimpleNetworkProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +PxeBcDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Start the Base code driver. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to test. + RemainingDevicePath - Not used. + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_ALREADY_STARTED - This driver is already running on this device. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + PXE_BASECODE_DEVICE *Private; + LOADFILE_DEVICE *pLF; + + // + // Allocate structures needed by BaseCode and LoadFile protocols. + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (PXE_BASECODE_DEVICE), + (VOID **) &Private + ); + + if (!EFI_ERROR (Status)) { + ZeroMem (Private, sizeof (PXE_BASECODE_DEVICE)); + } else { + DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc PXE_BASECODE_DEVICE structure.\n")); + return Status; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (LOADFILE_DEVICE), + (VOID **) &pLF + ); + + if (!EFI_ERROR (Status)) { + ZeroMem (pLF, sizeof (LOADFILE_DEVICE)); + } else { + DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc LOADFILE_DEVICE structure.\n")); + gBS->FreePool (Private); + return Status; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_PXE_BASE_CODE_MODE), + (VOID **) &Private->EfiBc.Mode + ); + + if (!EFI_ERROR (Status)) { + ZeroMem (Private->EfiBc.Mode, sizeof (EFI_PXE_BASE_CODE_MODE)); + } else { + DEBUG ((EFI_D_NET, "\nBcNotifySnp() Could not alloc Mode structure.\n")); + gBS->FreePool (Private); + gBS->FreePool (pLF); + return Status; + } + // + // Lock access, just in case + // + EfiInitializeLock (&Private->Lock, EFI_TPL_CALLBACK); + EfiAcquireLock (&Private->Lock); + + EfiInitializeLock (&pLF->Lock, EFI_TPL_CALLBACK); + EfiAcquireLock (&pLF->Lock); + + // + // Initialize PXE structure + // + // + // First initialize the internal 'private' data that the application + // does not see. + // + Private->Signature = PXE_BASECODE_DEVICE_SIGNATURE; + Private->Handle = Controller; + + // + // Get the NII interface + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + (VOID **) &Private->NiiPtr, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + (VOID **) &Private->NiiPtr, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + goto PxeBcError; + } + } + // + // Get the Snp interface + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleNetworkProtocolGuid, + (VOID **) &Private->SimpleNetwork, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + goto PxeBcError; + } + + // + // Next, initialize the external 'public' data that + // the application does see. + // + Private->EfiBc.Revision = EFI_PXE_BASE_CODE_INTERFACE_REVISION; + Private->EfiBc.Start = BcStart; + Private->EfiBc.Stop = BcStop; + Private->EfiBc.Dhcp = BcDhcp; + Private->EfiBc.Discover = BcDiscover; + Private->EfiBc.Mtftp = BcMtftp; + Private->EfiBc.UdpWrite = BcUdpWrite; + Private->EfiBc.UdpRead = BcUdpRead; + Private->EfiBc.Arp = BcArp; + Private->EfiBc.SetIpFilter = BcIpFilter; + Private->EfiBc.SetParameters = BcSetParameters; + Private->EfiBc.SetStationIp = BcSetStationIP; + Private->EfiBc.SetPackets = BcSetPackets; + + // + // Initialize BaseCode Mode structure + // + Private->EfiBc.Mode->Started = FALSE; + Private->EfiBc.Mode->TTL = DEFAULT_TTL; + Private->EfiBc.Mode->ToS = DEFAULT_ToS; + Private->EfiBc.Mode->UsingIpv6 = FALSE; + Private->EfiBc.Mode->AutoArp = TRUE; + + // + // Set to PXE_TRUE by the BC constructor if this BC + // implementation supports IPv6. + // + Private->EfiBc.Mode->Ipv6Supported = SUPPORT_IPV6; + +#if SUPPORT_IPV6 + Private->EfiBc.Mode->Ipv6Available = Private->NiiPtr->Ipv6Supported; +#else + Private->EfiBc.Mode->Ipv6Available = FALSE; +#endif + // + // Set to TRUE by the BC constructor if this BC + // implementation supports BIS. + // + Private->EfiBc.Mode->BisSupported = TRUE; + Private->EfiBc.Mode->BisDetected = PxebcBisDetect (Private); + + // + // Initialize LoadFile structure. + // + pLF->Signature = LOADFILE_DEVICE_SIGNATURE; + pLF->LoadFile.LoadFile = LoadFile; + pLF->Private = Private; + + // + // Install protocol interfaces. + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Controller, + &gEfiPxeBaseCodeProtocolGuid, + &Private->EfiBc, + &gEfiLoadFileProtocolGuid, + &pLF->LoadFile, + NULL + ); + + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiSimpleNetworkProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + goto PxeBcError; + } + // + // Release locks. + // + EfiReleaseLock (&pLF->Lock); + EfiReleaseLock (&Private->Lock); + return Status; + +PxeBcError: ; + gBS->FreePool (Private->EfiBc.Mode); + gBS->FreePool (Private); + gBS->FreePool (pLF); + return Status; +} + +EFI_STATUS +EFIAPI +PxeBcDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop the Base code driver. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to test. + NumberOfChildren - Not used + ChildHandleBuffer - Not used + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_ALREADY_STARTED - This driver is already running on this device. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_LOAD_FILE_PROTOCOL *LfProtocol; + LOADFILE_DEVICE *LoadDevice; + + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiLoadFileProtocolGuid, + (VOID **) &LfProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + LoadDevice = EFI_LOAD_FILE_DEV_FROM_THIS (LfProtocol); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Controller, + &gEfiLoadFileProtocolGuid, + &LoadDevice->LoadFile, + &gEfiPxeBaseCodeProtocolGuid, + &LoadDevice->Private->EfiBc, + NULL + ); + + if (!EFI_ERROR (Status)) { + + Status = gBS->CloseProtocol ( + Controller, + &gEfiSimpleNetworkProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + gBS->FreePool (LoadDevice->Private->EfiBc.Mode); + gBS->FreePool (LoadDevice->Private); + gBS->FreePool (LoadDevice); + } + + return Status; +} + +EFI_STATUS +EFIAPI +InitializeBCDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + + Routine Description: + Initialize the base code drivers and install the driver binding + + Arguments: + Standard EFI Image Entry + + Returns: + EFI_SUCCESS - This driver was successfully bound + +--*/ +{ + InitArpHeader (); + OptionsStrucInit (); + + return EFI_SUCCESS; +} + +/* eof - bc.c */ diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/bc.h b/EdkModulePkg/Universal/Network/PxeBc/Dxe/bc.h new file mode 100644 index 0000000000..a391709c9e --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/bc.h @@ -0,0 +1,499 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + bc.h + +Abstract: + +--*/ + +#ifndef _BC_H +#define _BC_H + +#ifndef EFI_MIN +#define EFI_MIN(_a, _b) ((_a) < (_b) ? (_a) : (_b)) +#endif + +#define CALLBACK_INTERVAL 100 // ten times a second +#define FILTER_BITS (EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP | \ + EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST | \ + EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS | \ + EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST \ + ) + +#define WAIT_TX_TIMEOUT 1000 + +#define SUPPORT_IPV6 0 + +#define PXE_BASECODE_DEVICE_SIGNATURE EFI_SIGNATURE_32('p','x','e','d') + +// +// Determine the classes of IPv4 address +// +#define IS_CLASSA_IPADDR(x) ((((EFI_IP_ADDRESS*)x)->v4.Addr[0] & 0x80) == 0x00) +#define IS_CLASSB_IPADDR(x) ((((EFI_IP_ADDRESS*)x)->v4.Addr[0] & 0xc0) == 0x80) +#define IS_CLASSC_IPADDR(x) ((((EFI_IP_ADDRESS*)x)->v4.Addr[0] & 0xe0) == 0xc0) +#define IS_INADDR_UNICAST(x) ((IS_CLASSA_IPADDR(x) || IS_CLASSB_IPADDR(x) || IS_CLASSC_IPADDR(x)) && (((EFI_IP_ADDRESS*)x)->Addr[0] != 0) ) + +// +// Definitions for internet group management protocol version 2 message +// structure +// Per RFC 2236, November 1997 +// +#pragma pack(1) + +typedef struct { + UINT8 Type; + UINT8 MaxRespTime; // in tenths of a second + UINT16 Checksum; // ones complement of ones complement sum of + // 16 bit words of message + UINT32 GroupAddress; // for general query, all systems group, + // for group specific, the group +} IGMPV2_MESSAGE; + +#define IGMP_TYPE_QUERY 0x11 +#define IGMP_TYPE_REPORT 0x16 +#define IGMP_TYPE_V1REPORT 0x12 +#define IGMP_TYPE_LEAVE_GROUP 0x17 + +#define IGMP_DEFAULT_MAX_RESPONSE_TIME 10 // 10 second default +#pragma pack() + +#define MAX_MCAST_GROUPS 8 // most we allow ourselves to join at once +#define MAX_OFFERS 16 + +typedef struct { + UINTN Signature; + EFI_LOCK Lock; + BOOLEAN ShowErrorMessages; + EFI_PXE_BASE_CODE_PROTOCOL EfiBc; + EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *CallbackProtocolPtr; + EFI_HANDLE Handle; + + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiPtr; + EFI_SIMPLE_NETWORK_PROTOCOL *SimpleNetwork; + UINT8 *TransmitBufferPtr; + UINT8 *ReceiveBufferPtr; + EFI_PXE_BASE_CODE_FUNCTION Function; + + UINTN OldestArpEntry; + UINTN MCastGroupCount; + EFI_EVENT Igmpv1TimeoutEvent; + BOOLEAN UseIgmpv1Reporting; + EFI_EVENT IgmpGroupEvent[MAX_MCAST_GROUPS]; + UINT16 RandomPort; + +#if SUPPORT_IPV6 + // + // TBD + // +#else + UINT32 MCastGroup[MAX_MCAST_GROUPS]; +#endif + + BOOLEAN GoodStationIp; + BOOLEAN DidTransmit; + UINTN IpLength; + VOID *DhcpPacketBuffer; + UINTN FileSize; + VOID *BootServerReceiveBuffer; + EFI_IP_ADDRESS ServerIp; + + // + // work area + // for dhcp + // + VOID *ReceiveBuffers; + VOID *TransmitBuffer; + UINTN NumOffersReceived; + UINT16 TotalSeconds; + + // + // arrays for different types of offers + // + UINT8 ServerCount[4]; + UINT8 OfferCount[4][MAX_OFFERS]; + UINT8 GotBootp; + UINT8 GotProxy[4]; + UINT8 BinlProxies[MAX_OFFERS]; + + UINT8 *ArpBuffer; + UINT8 *TftpAckBuffer; + UINT8 *TftpErrorBuffer; + IGMPV2_MESSAGE IgmpMessage; + BOOLEAN BigBlkNumFlag; + UINT8 Timeout; + UINT16 RandomSeed; +} PXE_BASECODE_DEVICE; + +// +// type index +// +#define DHCP_ONLY_IX 0 +#define PXE10_IX 1 +#define WfM11a_IX 2 +#define BINL_IX 3 + +#define PXE_RND_PORT_LOW 2070 + +#define PXE_MAX_PRINT_BUFFER 128 + +// +// +// +#define LOADFILE_DEVICE_SIGNATURE EFI_SIGNATURE_32('p','x','e','l') + +typedef struct { + UINTN Signature; + EFI_LOCK Lock; + EFI_LOAD_FILE_PROTOCOL LoadFile; + PXE_BASECODE_DEVICE *Private; +} LOADFILE_DEVICE; + +#define EFI_BASE_CODE_DEV_FROM_THIS(a) CR (a, PXE_BASECODE_DEVICE, efi_bc, PXE_BASECODE_DEVICE_SIGNATURE); + +#define EFI_LOAD_FILE_DEV_FROM_THIS(a) CR (a, LOADFILE_DEVICE, LoadFile, LOADFILE_DEVICE_SIGNATURE) + +EFI_BIS_PROTOCOL * +PxebcBisStart ( + PXE_BASECODE_DEVICE *Private, + BIS_APPLICATION_HANDLE *BisAppHandle, + EFI_BIS_DATA **BisDataSigInfo + ) +; + +VOID +PxebcBisStop ( + EFI_BIS_PROTOCOL *Bis, + BIS_APPLICATION_HANDLE BisAppHandle, + EFI_BIS_DATA *BisDataSigInfo + ) +; + +BOOLEAN +PxebcBisVerify ( + PXE_BASECODE_DEVICE *Private, + VOID *FileBuffer, + UINTN FileBufferLength, + VOID *CredentialBuffer, + UINTN CredentialBufferLength + ) +; + +BOOLEAN +PxebcBisDetect ( + PXE_BASECODE_DEVICE *Private + ) +; + +// +// Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gPxeBcDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gPxeBcComponentName; + +// +// ////////////////////////////////////////////////////////// +// +// prototypes +// +EFI_STATUS +EFIAPI +InitializeBCDriver ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +EFI_STATUS +EFIAPI +BcStart ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN UseIpv6 + ) +; + +EFI_STATUS +EFIAPI +BcStop ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This + ) +; + +EFI_STATUS +EFIAPI +BcDhcp ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN SortOffers + ) +; + +EFI_STATUS +EFIAPI +BcDiscover ( + IN EFI_PXE_BASE_CODE_PROTOCOL * This, + IN UINT16 Type, + IN UINT16 *Layer, + IN BOOLEAN UseBis, + IN EFI_PXE_BASE_CODE_DISCOVER_INFO * Info OPTIONAL + ) +; + +EFI_STATUS +EFIAPI +BcMtftp ( + IN EFI_PXE_BASE_CODE_PROTOCOL * This, + IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, + IN OUT VOID *BufferPtr, + IN BOOLEAN Overwrite, + IN OUT UINT64 *BufferSize, + IN UINTN *BlockSize OPTIONAL, + IN EFI_IP_ADDRESS * ServerIp, + IN UINT8 *Filename, + IN EFI_PXE_BASE_CODE_MTFTP_INFO * Info OPTIONAL, + IN BOOLEAN DontUseBuffer + ) +; + +EFI_STATUS +EFIAPI +BcUdpWrite ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 OpFlags, + IN EFI_IP_ADDRESS *DestIp, + IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort, + IN EFI_IP_ADDRESS *GatewayIp, OPTIONAL + IN EFI_IP_ADDRESS *SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL + IN UINTN *HeaderSize, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN UINTN *BufferSize, + IN VOID *BufferPtr + ) +; + +EFI_STATUS +EFIAPI +BcUdpRead ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 OpFlags, + IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL + IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL + IN UINTN *HeaderSize, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN OUT UINTN *BufferSize, + IN VOID *BufferPtr + ) +; + +EFI_STATUS +EFIAPI +BcArp ( + IN EFI_PXE_BASE_CODE_PROTOCOL * This, + IN EFI_IP_ADDRESS * IpAddr, + IN EFI_MAC_ADDRESS * MacAddr OPTIONAL + ) +; + +EFI_STATUS +EFIAPI +BcIpFilter ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_IP_FILTER *NewFilter + ) +; + +EFI_STATUS +EFIAPI +BcSetParameters ( + IN EFI_PXE_BASE_CODE_PROTOCOL * This, + IN BOOLEAN *NewAutoArp, OPTIONAL + IN BOOLEAN *NewSendGUID, OPTIONAL + IN UINT8 *NewTTL, OPTIONAL + IN UINT8 *NewToS, OPTIONAL + IN BOOLEAN *NewMakeCallback OPTIONAL + ) +; + +EFI_STATUS +EFIAPI +BcSetStationIP ( + IN EFI_PXE_BASE_CODE_PROTOCOL * This, + IN EFI_IP_ADDRESS * NewStationIp, OPTIONAL + IN EFI_IP_ADDRESS * NewSubnetMask OPTIONAL + ) +; + +EFI_STATUS +EFIAPI +BcSetPackets ( + IN EFI_PXE_BASE_CODE_PROTOCOL * This, + BOOLEAN *NewDhcpDiscoverValid, OPTIONAL + BOOLEAN *NewDhcpAckReceived, OPTIONAL + BOOLEAN *NewProxyOfferReceived, OPTIONAL + BOOLEAN *NewPxeDiscoverValid, OPTIONAL + BOOLEAN *NewPxeReplyReceived, OPTIONAL + BOOLEAN *NewPxeBisReplyReceived, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewDhcpDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewDhcpAck, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewProxyOffer, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewPxeDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewPxeReply, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewPxeBisReply OPTIONAL + ) +; + +EFI_STATUS +EFIAPI +LoadFile ( + IN EFI_LOAD_FILE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN BOOLEAN BootPolicy, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +; + +EFI_STATUS +PxeBcLibGetSmbiosSystemGuidAndSerialNumber ( + IN EFI_GUID *SystemGuid, + OUT CHAR8 **SystemSerialNumber + ) +; + +UINTN +EFIAPI +AsciiPrint ( + IN CONST CHAR8 *Format, + ... + ) +; + +// +// Define SMBIOS tables. +// +#pragma pack(1) +typedef struct { + UINT8 AnchorString[4]; + UINT8 EntryPointStructureChecksum; + UINT8 EntryPointLength; + UINT8 MajorVersion; + UINT8 MinorVersion; + UINT16 MaxStructureSize; + UINT8 EntryPointRevision; + UINT8 FormattedArea[5]; + UINT8 IntermediateAnchorString[5]; + UINT8 IntermediateChecksum; + UINT16 TableLength; + UINT32 TableAddress; + UINT16 NumberOfSmbiosStructures; + UINT8 SmbiosBcdRevision; +} SMBIOS_STRUCTURE_TABLE; + +// +// Please note that SMBIOS structures can be odd byte aligned since the +// unformated section of each record is a set of arbitrary size strings. +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Handle[2]; +} SMBIOS_HEADER; + +typedef UINT8 SMBIOS_STRING; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Vendor; + SMBIOS_STRING BiosVersion; + UINT8 BiosSegment[2]; + SMBIOS_STRING BiosReleaseDate; + UINT8 BiosSize; + UINT8 BiosCharacteristics[8]; +} SMBIOS_TYPE0; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Manufacturer; + SMBIOS_STRING ProductName; + SMBIOS_STRING Version; + SMBIOS_STRING SerialNumber; + + // + // always byte copy this data to prevent alignment faults! + // + EFI_GUID Uuid; + + UINT8 WakeUpType; +} SMBIOS_TYPE1; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Manufacturer; + SMBIOS_STRING ProductName; + SMBIOS_STRING Version; + SMBIOS_STRING SerialNumber; +} SMBIOS_TYPE2; + +typedef struct { + SMBIOS_HEADER Hdr; + SMBIOS_STRING Manufacturer; + UINT8 Type; + SMBIOS_STRING Version; + SMBIOS_STRING SerialNumber; + SMBIOS_STRING AssetTag; + UINT8 BootupState; + UINT8 PowerSupplyState; + UINT8 ThermalState; + UINT8 SecurityStatus; + UINT8 OemDefined[4]; +} SMBIOS_TYPE3; + +typedef struct { + SMBIOS_HEADER Hdr; + UINT8 Socket; + UINT8 ProcessorType; + UINT8 ProcessorFamily; + SMBIOS_STRING ProcessorManufacture; + UINT8 ProcessorId[8]; + SMBIOS_STRING ProcessorVersion; + UINT8 Voltage; + UINT8 ExternalClock[2]; + UINT8 MaxSpeed[2]; + UINT8 CurrentSpeed[2]; + UINT8 Status; + UINT8 ProcessorUpgrade; + UINT8 L1CacheHandle[2]; + UINT8 L2CacheHandle[2]; + UINT8 L3CacheHandle[2]; +} SMBIOS_TYPE4; + +typedef union { + SMBIOS_HEADER *Hdr; + SMBIOS_TYPE0 *Type0; + SMBIOS_TYPE1 *Type1; + SMBIOS_TYPE2 *Type2; + SMBIOS_TYPE3 *Type3; + SMBIOS_TYPE4 *Type4; + UINT8 *Raw; +} SMBIOS_STRUCTURE_POINTER; +#pragma pack() + +#include "ip.h" +#include "dhcp.h" +#include "tftp.h" + +#endif /* _BC_H */ + +/* EOF - bc.h */ diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/build.xml b/EdkModulePkg/Universal/Network/PxeBc/Dxe/build.xml new file mode 100644 index 0000000000..8ead9eabcc --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/dhcp.h b/EdkModulePkg/Universal/Network/PxeBc/Dxe/dhcp.h new file mode 100644 index 0000000000..cd448b37a5 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/dhcp.h @@ -0,0 +1,627 @@ +/*++ + +Copyright (c) 2006, 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 _DHCP_H +#define _DHCP_H + +// +// Definitions for DHCP version 4 UDP packet. +// The field names in this structure are defined and described in RFC 2131. +// +#pragma pack(1) + +typedef struct { + UINT8 op; +#define BOOTP_REQUEST 1 +#define BOOTP_REPLY 2 + + UINT8 htype; + UINT8 hlen; + UINT8 hops; + UINT32 xid; + UINT16 secs; + UINT16 flags; +#define DHCP_BROADCAST_FLAG 0x8000 + + UINT32 ciaddr; + UINT32 yiaddr; + UINT32 siaddr; + UINT32 giaddr; + UINT8 chaddr[16]; + UINT8 sname[64]; + UINT8 file[128]; + UINT8 options[312]; +#define OP_PAD 0 +#define OP_END 255 +#define OP_SUBNET_MASK 1 +#define OP_TIME_OFFSET 2 +#define OP_ROUTER_LIST 3 +#define OP_TIME_SERVERS 4 +#define OP_NAME_SERVERS 5 +#define OP_DNS_SERVERS 6 +#define OP_LOG_SERVERS 7 +#define OP_COOKIE_SERVERS 8 +#define OP_LPR_SREVERS 9 +#define OP_IMPRESS_SERVERS 10 +#define OP_RES_LOC_SERVERS 11 +#define OP_HOST_NAME 12 +#define OP_BOOT_FILE_SZ 13 +#define OP_DUMP_FILE 14 +#define OP_DOMAIN_NAME 15 +#define OP_SWAP_SERVER 16 +#define OP_ROOT_PATH 17 +#define OP_EXTENSION_PATH 18 +#define OP_IP_FORWARDING 19 +#define OP_NON_LOCAL_SRC_RTE 20 +#define OP_POLICY_FILTER 21 +#define OP_MAX_DATAGRAM_SZ 22 +#define OP_DEFAULT_TTL 23 +#define OP_MTU_AGING_TIMEOUT 24 +#define OP_MTU_SIZES 25 +#define OP_MTU_TO_USE 26 +#define OP_ALL_SUBNETS_LOCAL 27 +#define OP_BROADCAST_ADD 28 +#define OP_PERFORM_MASK_DISCOVERY 29 +#define OP_RESPOND_TO_MASK_REQ 30 +#define OP_PERFORM_ROUTER_DISCOVERY 31 +#define OP_ROUTER_SOLICIT_ADDRESS 32 +#define OP_STATIC_ROUTER_LIST 33 +#define OP_USE_ARP_TRAILERS 34 +#define OP_ARP_CACHE_TIMEOUT 35 +#define OP_ETHERNET_ENCAPSULATION 36 +#define OP_TCP_DEFAULT_TTL 37 +#define OP_TCP_KEEP_ALIVE_INT 38 +#define OP_KEEP_ALIVE_GARBAGE 39 +#define OP_NIS_DOMAIN_NAME 40 +#define OP_NIS_SERVERS 41 +#define OP_NTP_SERVERS 42 +#define OP_VENDOR_SPECIFIC 43 +#define VEND_PXE_MTFTP_IP 1 +#define VEND_PXE_MTFTP_CPORT 2 +#define VEND_PXE_MTFTP_SPORT 3 +#define VEND_PXE_MTFTP_TMOUT 4 +#define VEND_PXE_MTFTP_DELAY 5 +#define VEND_PXE_DISCOVERY_CONTROL 6 +#define VEND_PXE_DISCOVERY_MCAST_ADDR 7 +#define VEND_PXE_BOOT_SERVERS 8 +#define VEND_PXE_BOOT_MENU 9 +#define VEND_PXE_BOOT_PROMPT 10 +#define VEND_PXE_MCAST_ADDRS_ALLOC 11 +#define VEND_PXE_CREDENTIAL_TYPES 12 +#define VEND_PXE_BOOT_ITEM 71 +#define OP_NBNS_SERVERS 44 +#define OP_NBDD_SERVERS 45 +#define OP_NETBIOS_NODE_TYPE 46 +#define OP_NETBIOS_SCOPE 47 +#define OP_XWINDOW_SYSTEM_FONT_SERVERS 48 +#define OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS 49 +#define OP_DHCP_REQ_IP_ADD 50 +#define OP_DHCP_LEASE_TIME 51 +#define OP_DHCP_OPTION_OVERLOAD 52 +#define OVLD_FILE 1 +#define OVLD_SRVR_NAME 2 +#define OP_DHCP_MESSAGE_TYPE 53 +#define DHCPDISCOVER 1 +#define DHCPOFFER 2 +#define DHCPREQUEST 3 +#define DHCPDECLINE 4 +#define DHCPACK 5 +#define DHCPNAK 6 +#define DHCPRELEASE 7 +#define DHCPINFORM 8 +#define OP_DHCP_SERVER_IP 54 +#define OP_DHCP_PARM_REQ_LIST 55 +#define OP_DHCP_ERROR_MESSAGE 56 +#define OP_DHCP_MAX_MESSAGE_SZ 57 +#define OP_DHCP_RENEWAL_TIME 58 +#define OP_DHCP_REBINDING_TIME 59 +#define OP_DHCP_CLASS_IDENTIFIER 60 +#define OP_DHCP_CLIENT_IDENTIFIER 61 +#define OP_NISPLUS_DOMAIN_NAME 64 +#define OP_NISPLUS_SERVERS 65 +#define OP_DHCP_TFTP_SERVER_NAME 66 +#define OP_DHCP_BOOTFILE 67 +#define OP_MOBILE_IP_HOME_AGENTS 68 +#define OP_SMPT_SERVERS 69 +#define OP_POP3_SERVERS 70 +#define OP_NNTP_SERVERS 71 +#define OP_WWW_SERVERS 72 +#define OP_FINGER_SERVERS 73 +#define OP_IRC_SERVERS 74 +#define OP_STREET_TALK_SERVERS 75 +#define OP_STREET_TALK_DIR_ASSIST_SERVERS 76 +#define OP_NDS_SERVERS 85 +#define OP_NDS_TREE_NAME 86 +#define OP_NDS_CONTEXT 87 +#define OP_DHCP_SYSTEM_ARCH 93 +#define OP_DHCP_NETWORK_ARCH 94 +#define OP_DHCP_PLATFORM_ID 97 +} DHCPV4_STRUCT; + +// +// DHCPv4 option header +// +typedef struct { + UINT8 OpCode; + UINT8 Length; + // + // followed by Data[] + // +} DHCPV4_OP_HEADER; + +// +// Generic DHCPv4 option (header followed by data) +// +typedef struct { + DHCPV4_OP_HEADER Header; + UINT8 Data[1]; +} DHCPV4_OP_STRUCT; + +// +// Maximum DHCP packet size on ethernet +// +#define MAX_DHCP_MSG_SZ (MAX_ENET_DATA_SIZE - sizeof (IPV4_HEADER) - sizeof (UDPV4_HEADER)) + +// +// Macros used in pxe_bc_dhcp.c and pxe_loadfile.c +// +#define DHCPV4_TRANSMIT_BUFFER (*(DHCPV4_STRUCT *) (Private->TransmitBuffer)) +#define DHCPV4_OPTIONS_BUFFER (*(struct optionsstr *) DHCPV4_TRANSMIT_BUFFER.options) + +#define DHCPV4_ACK_INDEX 0 +#define PXE_BINL_INDEX 1 +#define PXE_OFFER_INDEX 1 +#define PXE_ACK_INDEX 2 +#define PXE_BIS_INDEX 3 + +#define DHCPV4_ACK_BUFFER ((struct DhcpReceiveBufferStruct *) Private->DhcpPacketBuffer)[DHCPV4_ACK_INDEX] +#define PXE_BINL_BUFFER ((struct DhcpReceiveBufferStruct *) Private->DhcpPacketBuffer)[PXE_BINL_INDEX] +#define PXE_OFFER_BUFFER ((struct DhcpReceiveBufferStruct *) Private->DhcpPacketBuffer)[PXE_OFFER_INDEX] +#define PXE_ACK_BUFFER ((struct DhcpReceiveBufferStruct *) Private->DhcpPacketBuffer)[PXE_ACK_INDEX] +#define PXE_BIS_BUFFER ((struct DhcpReceiveBufferStruct *) Private->DhcpPacketBuffer)[PXE_BIS_INDEX] + +#define DHCPV4_ACK_PACKET DHCPV4_ACK_BUFFER.u.Dhcpv4 +#define PXE_BINL_PACKET PXE_BINL_BUFFER.u.Dhcpv4 +#define PXE_OFFER_PACKET PXE_OFFER_BUFFER.u.Dhcpv4 +#define PXE_ACK_PACKET PXE_ACK_BUFFER.u.Dhcpv4 +#define PXE_BIS_PACKET PXE_BIS_BUFFER.u.Dhcpv4 + +// +// network structure definitions +// +// +// some option definitions +// +#define DHCPV4_OPTION_LENGTH(type) (sizeof (type) - sizeof (DHCPV4_OP_HEADER)) + +typedef struct { + DHCPV4_OP_HEADER Header; + UINT8 Type; +} DHCPV4_OP_MESSAGE_TYPE; + +typedef struct { + DHCPV4_OP_HEADER Header; + UINT8 Overload; +} DHCPV4_OP_OVERLOAD; + +// +// boot server list structure +// one or more contained in a pxe boot servers structure +// +typedef struct { + UINT8 IpCount; + EFI_IPv4_ADDRESS IpList[1]; // IP count of IPs +} PXEV4_SERVER_LIST; + +typedef struct { + UINT8 IpCount; + EFI_IPv6_ADDRESS IpList[1]; // IP count of IPs +} PXEV6_SERVER_LIST; + +typedef union { + PXEV4_SERVER_LIST Ipv4List; + PXEV6_SERVER_LIST Ipv6List; +} PXE_SERVER_LISTS; + +typedef struct { + UINT16 Type; + PXE_SERVER_LISTS u; +} PXE_SERVER_LIST; + +// +// pxe boot servers structure +// +typedef struct { + DHCPV4_OP_HEADER Header; + PXE_SERVER_LIST ServerList[1]; // one or more +} PXE_OP_SERVER_LIST; + +// +// pxe boot item structure +// +typedef struct { + DHCPV4_OP_HEADER Header; + UINT16 Type; + UINT16 Layer; +} PXE_OP_BOOT_ITEM; + +// +// pxe boot menu item structure +// +typedef struct { + UINT16 Type; + UINT8 DataLen; + UINT8 Data[1]; +} PXE_BOOT_MENU_ENTRY; + +// +// pxe boot menu structure +// +typedef struct { + DHCPV4_OP_HEADER Header; + PXE_BOOT_MENU_ENTRY MenuItem[1]; +} PXE_OP_BOOT_MENU; + +// +// pxe boot prompt structure +// +typedef struct { + DHCPV4_OP_HEADER Header; + UINT8 Timeout; + UINT8 Prompt[1]; +} PXE_OP_BOOT_PROMPT; + +#define PXE_BOOT_PROMPT_AUTO_SELECT 0 +#define PXE_BOOT_PROMPT_NO_TIMEOUT 255 + +typedef struct { + DHCPV4_OP_HEADER Header; + UINT8 Class[1]; +} DHCPV4_OP_CLASS; + +typedef struct { + DHCPV4_OP_HEADER Header; + UINT8 File[1]; +} DHCPV4_OP_BOOTFILE; + +typedef struct { + DHCPV4_OP_HEADER Header; + UINT8 VendorOptions[1]; +} DHCPV4_OP_VENDOR_OPTIONS; + +typedef struct { + DHCPV4_OP_HEADER Header; + UINT8 MaxSize[2]; +} DHCPV4_OP_MAX_MESSAGE_SIZE; + +typedef struct { + UINT8 _OP_SUBNET_MASK; /* 1 */ + UINT8 _OP_TIME_OFFSET; /* 2 */ + UINT8 _OP_ROUTER_LIST; /* 3 */ + UINT8 _OP_TIME_SERVERS; /* 4 */ + UINT8 _OP_NAME_SERVERS; /* 5 */ + UINT8 _OP_DNS_SERVERS; /* 6 */ + UINT8 _OP_HOST_NAME; /* 12 */ + UINT8 _OP_BOOT_FILE_SZ; /* 13 */ + UINT8 _OP_DOMAIN_NAME; /* 15 */ + UINT8 _OP_ROOT_PATH; /* 17 */ + UINT8 _OP_EXTENSION_PATH; /* 18 */ + UINT8 _OP_MAX_DATAGRAM_SZ; /* 22 */ + UINT8 _OP_DEFAULT_TTL; /* 23 */ + UINT8 _OP_BROADCAST_ADD; /* 28 */ + UINT8 _OP_NIS_DOMAIN_NAME; /* 40 */ + UINT8 _OP_NIS_SERVERS; /* 41 */ + UINT8 _OP_NTP_SERVERS; /* 42 */ + UINT8 _OP_VENDOR_SPECIFIC; /* 43 */ + UINT8 _OP_DHCP_REQ_IP_ADD; /* 50 */ + UINT8 _OP_DHCP_LEASE_TIME; /* 51 */ + UINT8 _OP_DHCP_SERVER_IP; /* 54 */ + UINT8 _OP_DHCP_RENEWAL_TIME; /* 58 */ + UINT8 _OP_DHCP_REBINDING_TIME; /* 59 */ + UINT8 _OP_DHCP_CLASS_IDENTIFIER; /* 60 */ + UINT8 _OP_DHCP_TFTP_SERVER_NAME; /* 66 */ + UINT8 _OP_DHCP_BOOTFILE; /* 67 */ + UINT8 _OP_DHCP_PLATFORM_ID; /* 97 */ + UINT8 VendorOption128; // vendor option 128 + UINT8 VendorOption129; // vendor option 129 + UINT8 VendorOption130; // vendor option 130 + UINT8 VendorOption131; // vendor option 131 + UINT8 VendorOption132; // vendor option 132 + UINT8 VendorOption133; // vendor option 133 + UINT8 VendorOption134; // vendor option 134 + UINT8 VendorOption135; // vendor option 135 +} DHCPV4_REQUESTED_OPTIONS_DATA; + +typedef struct { + DHCPV4_OP_HEADER Header; + DHCPV4_REQUESTED_OPTIONS_DATA Data; +} DHCPV4_OP_REQUESTED_OPTIONS; + +typedef struct opipstr { + DHCPV4_OP_HEADER Header; + EFI_IPv4_ADDRESS Ip; +} DHCPV4_OP_IP_ADDRESS; + +// +// ip list structure - e.g. router list +// +typedef struct { + DHCPV4_OP_HEADER Header; + EFI_IPv4_ADDRESS IpList[1]; +} DHCPV4_OP_IP_LIST; + +typedef struct { + DHCPV4_OP_HEADER Header; + UINT8 Type; + UINT8 Guid[sizeof (EFI_GUID)]; +} DHCPV4_OP_CLIENT_ID; + +// +// special options start - someday obsolete ??? +// +#define DHCPV4_OP_PLATFORM_ID DHCPV4_OP_CLIENT_ID + +typedef struct { + DHCPV4_OP_HEADER Header; + UINT8 Type; // SNP = 2 + UINT8 MajorVersion; + UINT8 MinorVersion; +} DHCPV4_OP_NETWORK_INTERFACE; + +#define UNDI_TYPE 1 +#define SNP_TYPE 2 + +typedef struct { + DHCPV4_OP_HEADER Header; + UINT16 Type; +} DHCPV4_OP_ARCHITECTURE_TYPE; +// +// special options end - someday obsolete ??? +// +typedef struct { + UINT8 ClassIdentifier[10]; // PXEClient: + UINT8 Lit2[5]; // Arch: + UINT8 ArchitectureType[5]; // 00000 - 65536 + UINT8 Lit3[1]; // : + UINT8 InterfaceName[4]; // e.g. UNDI + UINT8 Lit4[1]; // : + UINT8 UndiMajor[3]; // 000 - 255 + UINT8 UndiMinor[3]; // 000 - 255 +} DHCPV4_CLASS_ID_DATA; + +typedef struct { + DHCPV4_OP_HEADER Header; + DHCPV4_CLASS_ID_DATA Data; +} DHCPV4_OP_CLASS_ID; + +typedef struct { + DHCPV4_OP_HEADER Header; + EFI_IPv4_ADDRESS Ip; +} DHCPV4_OP_REQUESTED_IP; + +typedef struct { + DHCPV4_OP_HEADER Header; + EFI_IPv4_ADDRESS Ip; +} DHCPV4_OP_SERVER_IP; + +typedef struct { + DHCPV4_OP_HEADER Header; + EFI_IPv4_ADDRESS Ip; +} DHCPV4_OP_SUBNET_MASK; + +typedef struct { // oppxedisctlstr { + DHCPV4_OP_HEADER Header; + UINT8 ControlBits; +} PXE_OP_DISCOVERY_CONTROL; + +#define DISABLE_BCAST (1 << 0) +#define DISABLE_MCAST (1 << 1) +#define USE_ACCEPT_LIST (1 << 2) +#define USE_BOOTFILE (1 << 3) + +#pragma pack() +// +// definitions of indices to populate option interest array +// +#define VEND_PXE_MTFTP_IP_IX 1 // multicast IP address of bootfile for MTFTP listen +#define VEND_PXE_MTFTP_CPORT_IX 2 // UDP Port to monitor for MTFTP responses - Intel order +#define VEND_PXE_MTFTP_SPORT_IX 3 // Server UDP Port for MTFTP open - Intel order +#define VEND_PXE_MTFTP_TMOUT_IX 4 // Listen timeout - secs +#define VEND_PXE_MTFTP_DELAY_IX 5 // Transmission timeout - secs +#define VEND_PXE_DISCOVERY_CONTROL_IX 6 // bit field +#define VEND_PXE_DISCOVERY_MCAST_ADDR_IX 7 // boot server discovery multicast address +#define VEND_PXE_BOOT_SERVERS_IX 8 // list of boot servers of form tp(2) cnt(1) ips[cnt] +#define VEND_PXE_BOOT_MENU_IX 9 +#define VEND_PXE_BOOT_PROMPT_IX 10 +#define VEND_PXE_MCAST_ADDRS_ALLOC_IX 0 // not used by PXE client +#define VEND_PXE_CREDENTIAL_TYPES_IX 11 +#define VEND_13_IX 0 // not used by PXE client +#define VEND_14_IX 0 // not used by PXE client +#define VEND_15_IX 0 // not used by PXE client +#define VEND_16_IX 0 // not used by PXE client +#define VEND_17_IX 0 // not used by PXE client +#define VEND_18_IX 0 // not used by PXE client +#define VEND_19_IX 0 // not used by PXE client +#define VEND_20_IX 0 // not used by PXE client +#define VEND_21_IX 0 // not used by PXE client +#define VEND_22_IX 0 // not used by PXE client +#define VEND_23_IX 0 // not used by PXE client +#define VEND_24_IX 0 // not used by PXE client +#define VEND_25_IX 0 // not used by PXE client +#define VEND_26_IX 0 // not used by PXE client +#define VEND_27_IX 0 // not used by PXE client +#define VEND_28_IX 0 // not used by PXE client +#define VEND_29_IX 0 // not used by PXE client +#define VEND_30_IX 0 // not used by PXE client +#define VEND_31_IX 0 // not used by PXE client +#define VEND_32_IX 0 // not used by PXE client +#define VEND_33_IX 0 // not used by PXE client +#define VEND_34_IX 0 // not used by PXE client +#define VEND_35_IX 0 // not used by PXE client +#define VEND_36_IX 0 // not used by PXE client +#define VEND_37_IX 0 // not used by PXE client +#define VEND_38_IX 0 // not used by PXE client +#define VEND_39_IX 0 // not used by PXE client +#define VEND_40_IX 0 // not used by PXE client +#define VEND_41_IX 0 // not used by PXE client +#define VEND_42_IX 0 // not used by PXE client +#define VEND_43_IX 0 // not used by PXE client +#define VEND_44_IX 0 // not used by PXE client +#define VEND_45_IX 0 // not used by PXE client +#define VEND_46_IX 0 // not used by PXE client +#define VEND_47_IX 0 // not used by PXE client +#define VEND_48_IX 0 // not used by PXE client +#define VEND_49_IX 0 // not used by PXE client +#define VEND_50_IX 0 // not used by PXE client +#define VEND_51_IX 0 // not used by PXE client +#define VEND_52_IX 0 // not used by PXE client +#define VEND_53_IX 0 // not used by PXE client +#define VEND_54_IX 0 // not used by PXE client +#define VEND_55_IX 0 // not used by PXE client +#define VEND_56_IX 0 // not used by PXE client +#define VEND_57_IX 0 // not used by PXE client +#define VEND_58_IX 0 // not used by PXE client +#define VEND_59_IX 0 // not used by PXE client +#define VEND_60_IX 0 // not used by PXE client +#define VEND_61_IX 0 // not used by PXE client +#define VEND_62_IX 0 // not used by PXE client +#define VEND_63_IX 0 // not used by PXE client +#define VEND_64_IX 0 // not used by PXE client +#define VEND_65_IX 0 // not used by PXE client +#define VEND_66_IX 0 // not used by PXE client +#define VEND_67_IX 0 // not used by PXE client +#define VEND_68_IX 0 // not used by PXE client +#define VEND_69_IX 0 // not used by PXE client +#define VEND_70_IX 0 // not used by PXE client +#define VEND_PXE_BOOT_ITEM_IX 12 + +#define MAX_OUR_PXE_OPT VEND_PXE_BOOT_ITEM // largest PXE option in which we are interested +#define MAX_OUR_PXE_IX VEND_PXE_BOOT_ITEM_IX // largest PXE option index +// +// define various types by options that are sent +// +#define WfM11a_OPTS ((1<> 8) & 0x00ff)) + +#define HTONL(v) \ + (UINT32) ((((v) << 24) & 0xff000000) + (((v) << 8) & 0x00ff0000) + (((v) >> 8) & 0x0000ff00) + (((v) >> 24) & 0x000000ff)) + +#define HTONLL(v) swap64 (v) + +#define U8PTR(na) ((UINT8 *) &(na)) + +#define NTOHS(ns) ((UINT16) (((*U8PTR (ns)) << 8) +*(U8PTR (ns) + 1))) + +#define NTOHL(ns) \ + ((UINT32) (((*U8PTR (ns)) << 24) + ((*(U8PTR (ns) + 1)) << 16) + ((*(U8PTR (ns) + 2)) << 8) +*(U8PTR (ns) + 3))) + +#endif /* _HTON_H_ */ + +/* EOF - hton.h */ diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/ip.h b/EdkModulePkg/Universal/Network/PxeBc/Dxe/ip.h new file mode 100644 index 0000000000..fcfc264763 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/ip.h @@ -0,0 +1,741 @@ +/*++ + +Copyright (c) 2006, 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 _IP_H_ +#define _IP_H_ + +#include "hton.h" + +// +// Client architecture types +// +#define IA64 2 +#define SYS_ARCH_EFI32 6 + +// +// portability macros +// +#define UDP_FILTER_MASK (EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | \ + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT | \ + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP | \ + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT | \ + EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER \ + ) + +#define PXE_BOOT_LAYER_MASK 0x7FFF +#define PXE_BOOT_LAYER_INITIAL 0x0000 +#define PXE_BOOT_LAYER_CREDENTIAL_FLAG 0x8000 +#define MAX_BOOT_SERVERS 32 + +// +// macro to evaluate IP address as TRUE if it is a multicast IP address +// +#define IS_MULTICAST(ptr) ((*((UINT8 *) ptr) & 0xf0) == 0xe0) + +// +// length macros +// +#define IP_ADDRESS_LENGTH(qp) (((qp)->UsingIpv6) ? sizeof (EFI_IPv6_ADDRESS) : sizeof (EFI_IPv4_ADDRESS)) + +#define MAX_FRAME_DATA_SIZE 1488 +#define ALLOCATE_SIZE(X) (((X) + 7) & 0xfff8) +#define MODE_ALLOCATE_SIZE ALLOCATE_SIZE (sizeof (EFI_PXE_BASE_CODE_MODE)) +#define BUFFER_ALLOCATE_SIZE (8192 + 512) +#define ROUTER_ALLOCATE_SIZE ALLOCATE_SIZE ((sizeof (EFI_PXE_BASE_CODE_ROUTE_ENTRY) * PXE_ROUTER_TABLE_SIZE)) +#define ARP_ALLOCATE_SIZE ALLOCATE_SIZE ((sizeof (EFI_PXE_BASE_CODE_ARP_ENTRY) * PXE_ARP_CACHE_SIZE)) +#define FILTER_ALLOCATE_SIZE ALLOCATE_SIZE ((sizeof (EFI_IP_ADDRESS) * PXE_IP_FILTER_SIZE)) +#define PXE_ARP_CACHE_SIZE 8 +#define PXE_ROUTER_TABLE_SIZE 8 +#define PXE_IP_FILTER_SIZE 8 +#define ICMP_ALLOCATE_SIZE ALLOCATE_SIZE (sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR)) +#define TFTP_ERR_ALLOCATE_SIZE ALLOCATE_SIZE (sizeof (EFI_PXE_BASE_CODE_TFTP_ERROR)) + +// +// DHCP discover/request packets are sent to this UDP port. ProxyDHCP +// servers listen on this port for DHCP discover packets that have a +// class identifier (option 60) with 'PXEClient' in the first 9 bytes. +// Bootservers also listen on this port for PXE broadcast discover +// requests from PXE clients. +// +#define DHCP_SERVER_PORT 67 + +// +// When DHCP, proxyDHCP and Bootservers respond to DHCP and PXE broadcast +// discover requests by broadcasting the reply packet, the packet is +// broadcast to this port. +// +#define DHCP_CLIENT_PORT 68 + +// +// TFTP servers listen for TFTP open requests on this port. +// +#define TFTP_OPEN_PORT 69 + +// +// proxyDHCP and Bootservers listen on this port for a PXE unicast and/or +// multicast discover requests from PXE clients. A PXE discover request +// looks like a DHCP discover or DHCP request packet. +// +#define PXE_DISCOVERY_PORT 4011 + +// +// This port is used by the PXE client/server protocol tests. +// +#define PXE_PORT_PXETEST_PORT 0x8080 + +// +// Definitions for Ethertype protocol numbers and interface types +// Per RFC 1700, +// +#define PXE_PROTOCOL_ETHERNET_IP 0x0800 +#define PXE_PROTOCOL_ETHERNET_ARP 0x0806 +#define PXE_PROTOCOL_ETHERNET_RARP 0x8035 + +#define PXE_IFTYPE_ETHERNET 0x01 +#define PXE_IFTYPE_TOKENRING 0x04 +#define PXE_IFTYPE_FIBRE_CHANNEL 0x12 + +// +// Definitions for internet protocol version 4 header +// Per RFC 791, September 1981. +// +#define IPVER4 4 + +#pragma pack(1) // make network structures packed byte alignment +typedef union { + UINT8 B[4]; + UINT32 L; +} IPV4_ADDR; + +#define IPV4_HEADER_LENGTH(IpHeaderPtr) (((IpHeaderPtr)->VersionIhl & 0xf) << 2) + +#define SET_IPV4_VER_HDL(IpHeaderPtr, IpHeaderLen) { \ + (IpHeaderPtr)->VersionIhl = (UINT8) ((IPVER4 << 4) | ((IpHeaderLen) >> 2)); \ + } + +typedef struct { + UINT8 VersionIhl; + UINT8 TypeOfService; + UINT16 TotalLength; + UINT16 Id; + UINT16 FragmentFields; + UINT8 TimeToLive; + UINT8 Protocol; + UINT16 HeaderChecksum; + IPV4_ADDR SrcAddr; + IPV4_ADDR DestAddr; + // + // options are not implemented + // +} IPV4_HEADER; + +#define IP_FRAG_RSVD 0x8000 // reserved bit - must be zero +#define IP_NO_FRAG 0x4000 // do not fragment bit +#define IP_MORE_FRAG 0x2000 // not last fragment +#define IP_FRAG_OFF_MSK 0x1fff // fragment offset in 8 byte chunks +#define DEFAULT_RFC_TTL 64 + +#define PROT_ICMP 1 +#define PROT_IGMP 2 +#define PROT_TCP 6 +#define PROT_UDP 17 + +/* + * Definitions for internet control message protocol version 4 message + * structure. Per RFC 792, September 1981. + */ + +// +// icmp header for all icmp messages +// +typedef struct { + UINT8 Type; // message type + UINT8 Code; // type specific - 0 for types we implement + UINT16 Checksum; // ones complement of ones complement sum of 16 bit words of message +} ICMPV4_HEADER; + +#define ICMP_DEST_UNREACHABLE 3 +#define ICMP_SOURCE_QUENCH 4 +#define ICMP_REDIRECT 5 +#define ICMP_ECHO 8 +#define ICMP_ECHO_REPLY 0 +#define ICMP_ROUTER_ADV 9 +#define ICMP_ROUTER_SOLICIT 10 +#define ICMP_TIME_EXCEEDED 11 +#define ICMP_PARAMETER_PROBLEM 12 +#define ICMP_TIMESTAMP 13 +#define ICMP_TIMESTAMP_REPLY 14 +#define ICMP_INFO_REQ 15 +#define ICMP_INFO_REQ_REPLY 16 +#define ICMP_SUBNET_MASK_REQ 17 +#define ICMP_SUBNET_MASK_REPLY 18 +// +// other ICMP message types ignored in this implementation +// +// icmp general messages +// +typedef struct { + ICMPV4_HEADER Header; + // + // generally unused except byte [0] for + // parameter problem message + // + UINT8 GenerallyUnused[4]; + // + // original message ip header of plus 64 + // bits of data + // + IPV4_HEADER IpHeader; +} ICMPV4_GENERAL_MESSAGE; + +// +// icmp req/rply message header +// +typedef struct { + ICMPV4_HEADER Header; + UINT16 Id; + UINT16 SequenceNumber; +} ICMPV4_REQUEST_REPLY_HEADER; + +// +// icmp echo message +// +typedef struct { + ICMPV4_REQUEST_REPLY_HEADER Header; + UINT8 EchoData[1]; // variable length data to be echoed +} ICMPV4_ECHO_MESSAGE; + +// +// icmp timestamp message - times are milliseconds since midnight UT - +// if non std, set high order bit +// +typedef struct { + ICMPV4_REQUEST_REPLY_HEADER Header; + UINT32 OriginalTime; // originating timestamp + UINT32 ReceiveTime; // receiving timestamp + UINT32 TransmitTime; // transmitting timestamp +} ICMPV4_TIMESTAMP_MESSAGE; + +// +// icmp info request structure - fill in source and dest net ip address on reply +// +typedef struct { + ICMPV4_REQUEST_REPLY_HEADER Header; +} ICMPV4_INFO_MESSAGE; + +// +// Definitions for internet control message protocol version 4 message structure +// Router discovery +// Per RFC 1256, September 1991. +// +// +// icmp router advertisement message +// +typedef struct { + ICMPV4_HEADER Header; + UINT8 NumberEntries; // number of address entries + UINT8 EntrySize; // number of 32 bit words per address entry + UINT16 Lifetime; // seconds to consider info valid + UINT32 RouterIp; + UINT32 Preferance; +} ICMPV4_ROUTER_ADVERTISE_MESSAGE; + +// +// icmp router solicitation message +// +typedef struct { + ICMPV4_HEADER Header; + UINT32 Reserved; +} ICMPV4_ROUTER_SOLICIT_MESSAGE; + +#define MAX_SOLICITATION_DELAY 1 // 1 second +#define SOLICITATION_INTERVAL 3 // 3 seconds +#define MAX_SOLICITATIONS 3 // 3 transmissions +#define V1ROUTER_PRESENT_TIMEOUT 400 // 400 second timeout until v2 reports can be sent +#define UNSOLICITED_REPORT_INTERVAL 10 // 10 seconds between unsolicited reports +#define BROADCAST_IPv4 0xffffffff + +// +// Definitions for address resolution protocol message structure +// Per RFC 826, November 1982 +// +typedef struct { + UINT16 HwType; // hardware type - e.g. ethernet (1) + UINT16 ProtType; // protocol type - for ethernet, 0x800 for IP + UINT8 HwAddLen; // byte length of a hardware address (e.g. 6 for ethernet) + UINT8 ProtAddLen; // byte length of a protocol address (e.g. 4 for ipv4) + UINT16 OpCode; + // + // source and dest hw and prot addresses follow - see example below + // +} ARP_HEADER; + +#define ETHERNET_ADD_SPC 1 + +#define ETHER_TYPE_IP 0x800 + +#define ARP_REQUEST 1 +#define ARP_REPLY 2 + +// +// generic ARP packet +// +typedef struct { + ARP_HEADER ArpHeader; + EFI_MAC_ADDRESS SrcHardwareAddr; + EFI_IP_ADDRESS SrcProtocolAddr; + EFI_MAC_ADDRESS DestHardwareAddr; + EFI_IP_ADDRESS DestProtocolAddr; +} ARP_PACKET; + +#define ENET_HWADDLEN 6 +#define IPV4_PROTADDLEN 4 + +// +// Definitions for user datagram protocol version 4 pseudo header & header +// Per RFC 768, 28 August 1980 +// +typedef struct { + IPV4_ADDR SrcAddr; // source ip address + IPV4_ADDR DestAddr; // dest ip address + UINT8 Zero; // 0 + UINT8 Protocol; // protocol + UINT16 TotalLength; // UDP length - sizeof udpv4hdr + data length +} UDPV4_PSEUDO_HEADER; + +typedef struct { + UINT16 SrcPort; // source port identifier + UINT16 DestPort; // destination port identifier + UINT16 TotalLength; // total length header plus data + // + // ones complement of ones complement sum of 16 bit + // words of pseudo header, UDP header, and data + // zero checksum is transmitted as -0 (ones comp) + // zero transmitted means checksum not computed + // data follows + // + UINT16 Checksum; +} UDPV4_HEADER; + +typedef struct { + UDPV4_PSEUDO_HEADER Udpv4PseudoHeader; + UDPV4_HEADER Udpv4Header; +} UDPV4_HEADERS; + +// +// Definitions for transmission control protocol header +// Per RFC 793, September, 1981 +// +typedef struct { + IPV4_ADDR SrcAddr; // source ip address + IPV4_ADDR DestAddr; // dest ip address + UINT8 Zero; // 0 + UINT8 Protocol; // protocol + UINT16 TotalLength; // TCP length - TCP header length + data length +} TCPV4_PSEUDO_HEADER; + +typedef struct { + UINT16 SrcPort; // source port identifier + UINT16 DestPort; // destination port identifier + UINT32 SeqNumber; // Sequence number + UINT32 AckNumber; // Acknowledgement Number + // + // Nibble of HLEN (length of header in 32-bit multiples) + // 6bits of RESERVED + // Nibble of Code Bits + // + UINT16 HlenResCode; + UINT16 Window; // Software buffer size (sliding window size) in network-standard byte order + // + // ones complement of ones complement sum of 16 bit words of + // pseudo header, TCP header, and data + // zero checksum is transmitted as -0 (ones comp) + // zero transmitted means checksum not computed + // + UINT16 Checksum; + UINT16 UrgentPointer; // pointer to urgent data (allows sender to specify urgent data) +} TCPV4_HEADER; + +typedef struct { + TCPV4_PSEUDO_HEADER Tcpv4PseudoHeader; + TCPV4_HEADER Tcpv4Header; +} TCPV4_HEADERS; + +typedef struct { + UINT8 Kind; // one of the following: + UINT8 Length; // total option length including Kind and Lth + UINT8 Data[1]; // length = Lth - 2 +} TCPV4_OPTION; + +#define TCP_OP_END 0 // only used to pad to end of TCP header +#define TCP_NOP 1 // optional - may be used to pad between options to get alignment +#define TCP_MAX_SEG 2 // maximum receive segment size - only send at initial connection request +#define MAX_MEDIA_HDR_SIZE 64 +#define MIN_ENET_DATA_SIZE 64 +#define MAX_ENET_DATA_SIZE 1500 // temp def - make a network based var +#define MAX_IPV4_PKT_SIZE 65535 // maximum IP packet size +#define MAX_IPV4_DATA_SIZE (MAX_IPV4_PKT_SIZE - sizeof (IPV4_HEADER)) +#define MAX_IPV4_FRAME_DATA_SIZE (MAX_FRAME_DATA_SIZE - sizeof (IPV4_HEADER)) +#define REAS_IPV4_PKT_SIZE 576 // minimum IP packet size all IP host can handle +#define REAS_IPV4_DATA_SIZE (REAS_IPV4_PKT_SIZE - sizeof (IPV4_HEADER)) + +// +// +// +typedef union { + UINT8 Data[MAX_ENET_DATA_SIZE]; + ICMPV4_HEADER IcmpHeader; + IGMPV2_MESSAGE IgmpMessage; + struct { + UDPV4_HEADER UdpHeader; + UINT8 Data[1]; + } Udp; + struct { + TCPV4_HEADER TcpHeader; + UINT8 Data[1]; + } Tcp; +} PROTOCOL_UNION; + +// +// out buffer structure +// +typedef struct { + UINT8 MediaHeader[MAX_MEDIA_HDR_SIZE]; + IPV4_HEADER IpHeader; + // + // following union placement only valid if no option IP header + // + PROTOCOL_UNION u; +} IPV4_BUFFER; + +typedef struct { + IPV4_HEADER IpHeader; + // + // following union placement only valid if no option IP header + // + PROTOCOL_UNION u; +} IPV4_STRUCT; + +#pragma pack() // reset to default + + //////////////////////////////////////////////////////////// +// +// BC IP Filter Routine +// +EFI_STATUS +IpFilter ( + PXE_BASECODE_DEVICE *Private, + IN EFI_PXE_BASE_CODE_IP_FILTER *Filter + ) +; + +// +// ////////////////////////////////////////////////////////////////////// +// +// Udp Write Routine - called by base code - e.g. TFTP - already locked +// +EFI_STATUS +UdpWrite ( + IN PXE_BASECODE_DEVICE *Private, + IN UINT16 OpFlags, + IN EFI_IP_ADDRESS *DestIpPtr, + IN EFI_PXE_BASE_CODE_UDP_PORT *DestPortptr, + IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL + IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL + IN UINTN *HeaderSizePtr, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN UINTN *BufferSizePtr, + IN VOID *BufferPtr + ) +; + +// +// ///////////////////////////////////////////////////////////////////// +// +// Udp Read Routine - called by base code - e.g. TFTP - already locked +// +EFI_STATUS +UdpRead ( + IN PXE_BASECODE_DEVICE *Private, + IN UINT16 OpFlags, + IN OUT EFI_IP_ADDRESS *DestIpPtr, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPorPtrt, OPTIONAL + IN OUT EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL + IN UINTN *HeaderSizePtr, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN OUT UINTN *BufferSizePtr, + IN VOID *BufferPtr, + IN EFI_EVENT TimeoutEvent + ) +; + +VOID +IgmpLeaveGroup ( + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS * + ) +; + +VOID +IgmpJoinGroup ( + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS * + ) +; + +// +// convert number to zero filled ascii value of length lth +// +VOID +CvtNum ( + UINTN Number, + UINT8 *BufferPtr, + INTN BufferLen + ) +; + +// +// convert number to ascii string at ptr +// +VOID +UtoA10 ( + UINTN Number, + UINT8 *BufferPtr + ) +; + +// +// convert ascii numeric string to UINTN +// +UINTN +AtoU ( + UINT8 *BufferPtr + ) +; + +UINT64 +AtoU64 ( + UINT8 *BufferPtr + ) +; + +// +// calculate the internet checksum (RFC 1071) +// return 16 bit ones complement of ones complement sum of 16 bit words +// +UINT16 +IpChecksum ( + UINT16 *MessagePtr, + UINTN ByteLength + ) +; + +// +// do checksum on non contiguous header and data +// +UINT16 +IpChecksum2 ( + UINT16 *Header, + UINTN HeaderLength, + UINT16 *Message, + UINTN MessageLength + ) +; + +// +// update checksum when only a single word changes +// +UINT16 +UpdateChecksum ( + UINT16 OldChecksum, + UINT16 OldWord, + UINT16 NewWord + ) +; + +VOID +SeedRandom ( + IN PXE_BASECODE_DEVICE *Private, + IN UINT16 InitialSeed + ) +; + +UINT16 +Random ( + IN PXE_BASECODE_DEVICE *Private + ) +; + +EFI_STATUS +SendPacket ( + PXE_BASECODE_DEVICE *Private, + VOID *HeaderPtr, + VOID *PacketPtr, + INTN PacketLength, + VOID *HardwareAddress, + UINT16 MediaProtocol, + IN EFI_PXE_BASE_CODE_FUNCTION Function + ) +; + +VOID +HandleArpReceive ( + PXE_BASECODE_DEVICE *Private, + ARP_PACKET *ArpPacketPtr, + VOID *HeaderPtr + ) +; + +VOID +HandleIgmp ( + PXE_BASECODE_DEVICE *Private, + IGMPV2_MESSAGE *IgmpMessageptr, + UINTN IgmpMessageLen + ) +; + +VOID +IgmpCheckTimers ( + PXE_BASECODE_DEVICE *Private + ) +; // poll when doing a receive +// return hw add of IP and TRUE if available, otherwise FALSE +// +BOOLEAN +GetHwAddr ( + IN PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS *ProtocolAddressPtr, + EFI_MAC_ADDRESS *HardwareAddressPtr + ) +; + +EFI_STATUS +DoArp ( + IN PXE_BASECODE_DEVICE *Private, + IN EFI_IP_ADDRESS *ProtocolAddressPtr, + OUT EFI_MAC_ADDRESS *HardwareAddressptr + ) +; + +BOOLEAN +OnSameSubnet ( + UINTN IpAddressLen, + EFI_IP_ADDRESS *Ip1, + EFI_IP_ADDRESS *Ip2, + EFI_IP_ADDRESS *SubnetMask + ) +; + +VOID +IpAddRouter ( + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS *RouterIp + ) +; + +#define Ip4AddRouter(Private, Ipv4Ptr) IpAddRouter (Private, (EFI_IP_ADDRESS *) Ipv4Ptr) + +// +// routine to send ipv4 packet +// ipv4 + upper protocol header for length TotHdrLth in xmtbuf, ipv4 header length IpHdrLth +// routine fills in ipv4hdr Ver_Hdl, TotLth, and Checksum, moves in Data, and gets dest MAC address +// +EFI_STATUS +Ipv4Xmt ( + PXE_BASECODE_DEVICE *Private, + UINT32 GatewayIP, + UINTN IpHeaderLen, + UINTN TotalHeaderLen, + VOID *Data, + UINTN DataLen, + EFI_PXE_BASE_CODE_FUNCTION Function + ) +; + +// +// send ipv4 packet with ipv4 option +// +EFI_STATUS +Ipv4SendWOp ( + PXE_BASECODE_DEVICE *Private, + UINT32 GatewayIP, + UINT8 *MessagePtr, + UINTN MessageLth, + UINT8 Protocol, + UINT8 *Option, + UINTN OptionLen, + UINT32 DestIp, + EFI_PXE_BASE_CODE_FUNCTION Function + ) +; + +// +// send MsgLth message at MsgPtr - higher level protocol header already in xmtbuf, length HdrSize +// +EFI_STATUS +Ip4Send ( + IN PXE_BASECODE_DEVICE *Private, // pointer to instance data + IN UINTN MayFragment, // + IN UINT8 Protocol, // protocol + IN UINT32 SrcIp, // Source IP address + IN UINT32 DestIp, // Destination IP address + IN UINT32 GatewayIp, // used if not NULL and needed + IN UINTN HeaderSize, // protocol header byte length + IN UINT8 *MsgPtr, // pointer to data + IN UINTN MsgLength + ) +; // data byte length +// receive up to MsgLth message into MsgPtr for protocol Prot +// return message length, src/dest ips if select any, and pointer to protocol header +// +EFI_STATUS +IpReceive ( + IN PXE_BASECODE_DEVICE *Private, // pointer to instance data + UINT16 OpFlags, // Flags to determine if filtering on IP addresses + EFI_IP_ADDRESS *SrcIpPtr, // if filtering, O if accept any + EFI_IP_ADDRESS *DstIpPtr, // if filtering, O if accept any + UINT8 Protocol, // protocol + VOID *HeaderPtr, // address of where to put protocol header + UINTN HeaderSize, // protocol header byte length + UINT8 *MsgPtr, // pointer to data buffer + UINTN *MsgLenPtr, // pointer to data buffer length/ O - returned data length + IN EFI_EVENT TimeoutEvent + ) +; + +#if 0 +VOID +WaitForTxComplete ( + IN PXE_BASECODE_DEVICE *Private + ) +; +#endif +// +// routine to cycle waiting for a receive or timeout +// +EFI_STATUS +WaitForReceive ( + IN PXE_BASECODE_DEVICE *Private, + IN EFI_PXE_BASE_CODE_FUNCTION Function, + IN EFI_EVENT TimeoutEvent, + IN OUT UINTN *HeaderSizePtr, + IN OUT UINTN *BufferSizePtr, + IN OUT UINT16 *ProtocolPtr + ) +; + +#endif /* _IP_H_ */ + +/* EOF - ip.h */ diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_arp.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_arp.c new file mode 100644 index 0000000000..801f592042 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_arp.c @@ -0,0 +1,617 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + pxe_bc_arp.c + +Abstract: + +--*/ + + +#include "bc.h" + +// +// Definitions for ARP +// Per RFC 826 +// +STATIC ARP_HEADER ArpHeader; + +#pragma pack(1) +STATIC struct { + UINT8 MediaHeader[14]; + ARP_HEADER ArpHeader; + UINT8 ArpData[64]; +} ArpReplyPacket; +#pragma pack() + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +InitArpHeader ( + VOID + ) +/*++ +Routine description: + Initialize ARP packet header. + +Parameters: + none + +Returns: + none + +--*/ +{ + ArpHeader.HwType = HTONS (ETHERNET_ADD_SPC); + ArpHeader.ProtType = HTONS (ETHER_TYPE_IP); + ArpHeader.HwAddLen = ENET_HWADDLEN; + ArpHeader.ProtAddLen = IPV4_PROTADDLEN; + ArpHeader.OpCode = HTONS (ARP_REQUEST); + + CopyMem (&ArpReplyPacket.ArpHeader, &ArpHeader, sizeof (ARP_HEADER)); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +HandleArpReceive ( + IN PXE_BASECODE_DEVICE *Private, + IN ARP_PACKET *ArpPacketPtr, + IN VOID *MediaHeader + ) +/*++ +Routine description: + Process ARP packet. + +Parameters: + Private := Pointer to PxeBc interface + ArpPacketPtr := Pointer to ARP packet + MediaHeader := Pointer to media header. +Returns: +--*/ +{ + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + EFI_SIMPLE_NETWORK_MODE *SnpMode; + EFI_MAC_ADDRESS TmpMacAddr; + UINTN Index; + UINT8 *SrcHwAddr; + UINT8 *SrcPrAddr; + UINT8 *DstHwAddr; + UINT8 *DstPrAddr; + UINT8 *TmpPtr; + + // + // + // + PxeBcMode = Private->EfiBc.Mode; + SnpMode = Private->SimpleNetwork->Mode; + + // + // For now only ethernet addresses are supported. + // This will need to be updated when other media + // layers are supported by PxeBc, Snp and UNDI. + // + if (ArpPacketPtr->ArpHeader.HwType != HTONS (ETHERNET_ADD_SPC)) { + return ; + } + // + // For now only IP protocol addresses are supported. + // This will need to be updated when other protocol + // types are supported by PxeBc, Snp and UNDI. + // + if (ArpPacketPtr->ArpHeader.ProtType != HTONS (ETHER_TYPE_IP)) { + return ; + } + // + // For now only SNP hardware address sizes are supported. + // + if (ArpPacketPtr->ArpHeader.HwAddLen != SnpMode->HwAddressSize) { + return ; + } + // + // For now only PxeBc protocol address sizes are supported. + // + if (ArpPacketPtr->ArpHeader.ProtAddLen != Private->IpLength) { + return ; + } + // + // Ignore out of range opcodes + // + switch (ArpPacketPtr->ArpHeader.OpCode) { + case HTONS (ARP_REPLY): + case HTONS (ARP_REQUEST): + break; + + default: + return ; + } + // + // update entry in our ARP cache if we have it + // + SrcHwAddr = (UINT8 *) &ArpPacketPtr->SrcHardwareAddr; + SrcPrAddr = SrcHwAddr + SnpMode->HwAddressSize; + + for (Index = 0; Index < PxeBcMode->ArpCacheEntries; ++Index) { + if (CompareMem ( + &PxeBcMode->ArpCache[Index].IpAddr, + SrcPrAddr, + Private->IpLength + )) { + continue; + } + + CopyMem ( + &PxeBcMode->ArpCache[Index].MacAddr, + SrcHwAddr, + SnpMode->HwAddressSize + ); + + break; + } + // + // Done if ARP packet was not for us. + // + DstHwAddr = SrcPrAddr + Private->IpLength; + DstPrAddr = DstHwAddr + SnpMode->HwAddressSize; + + if (CompareMem (DstPrAddr, &PxeBcMode->StationIp, Private->IpLength)) { + return ; + // + // not for us + // + } + // + // for us - if we did not update entry, add it + // + if (Index == PxeBcMode->ArpCacheEntries) { + // + // if we have a full table, get rid of oldest + // + if (Index == PXE_ARP_CACHE_SIZE) { + Index = Private->OldestArpEntry; + + if (++Private->OldestArpEntry == PXE_ARP_CACHE_SIZE) { + Private->OldestArpEntry = 0; + } + } else { + ++PxeBcMode->ArpCacheEntries; + } + + CopyMem ( + &PxeBcMode->ArpCache[Index].MacAddr, + SrcHwAddr, + SnpMode->HwAddressSize + ); + + CopyMem ( + &PxeBcMode->ArpCache[Index].IpAddr, + SrcPrAddr, + Private->IpLength + ); + } + // + // if this is not a request or we don't yet have an IP, finished + // + if (ArpPacketPtr->ArpHeader.OpCode != HTONS (ARP_REQUEST) || !Private->GoodStationIp) { + return ; + } + // + // Assemble ARP reply. + // + // + // Create media header. [ dest mac | src mac | prot ] + // + CopyMem ( + &ArpReplyPacket.MediaHeader[0], + SrcHwAddr, + SnpMode->HwAddressSize + ); + + CopyMem ( + &ArpReplyPacket.MediaHeader[SnpMode->HwAddressSize], + &SnpMode->CurrentAddress, + SnpMode->HwAddressSize + ); + + CopyMem ( + &ArpReplyPacket.MediaHeader[2 * SnpMode->HwAddressSize], + &((UINT8 *) MediaHeader)[2 * SnpMode->HwAddressSize], + sizeof (UINT16) + ); + + // + // ARP reply header is almost filled in, + // just insert the correct opcode. + // + ArpReplyPacket.ArpHeader.OpCode = HTONS (ARP_REPLY); + + // + // Now fill in ARP data. [ src mac | src prot | dest mac | dest prot ] + // + TmpPtr = ArpReplyPacket.ArpData; + CopyMem (TmpPtr, &SnpMode->CurrentAddress, SnpMode->HwAddressSize); + + TmpPtr += SnpMode->HwAddressSize; + CopyMem (TmpPtr, &PxeBcMode->StationIp, Private->IpLength); + + TmpPtr += Private->IpLength; + CopyMem (TmpPtr, SrcHwAddr, SnpMode->HwAddressSize); + + TmpPtr += SnpMode->HwAddressSize; + CopyMem (TmpPtr, SrcPrAddr, Private->IpLength); + + // + // Now send out the ARP reply. + // + CopyMem (&TmpMacAddr, SrcHwAddr, sizeof (EFI_MAC_ADDRESS)); + + SendPacket ( + Private, + &ArpReplyPacket.MediaHeader, + &ArpReplyPacket.ArpHeader, + sizeof (ARP_HEADER) + 2 * (Private->IpLength + SnpMode->HwAddressSize), + &TmpMacAddr, + PXE_PROTOCOL_ETHERNET_ARP, + EFI_PXE_BASE_CODE_FUNCTION_ARP + ); + + // + // Give time (100 microseconds) for ARP reply to get onto wire. + // + gBS->Stall (1000); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +BOOLEAN +GetHwAddr ( + IN PXE_BASECODE_DEVICE *Private, + IN EFI_IP_ADDRESS *ProtocolAddrPtr, + OUT EFI_MAC_ADDRESS *HardwareAddrPtr + ) +/*++ +Routine description: + Locate IP address in ARP cache and return MAC address. + +Parameters: + Private := Pointer to PxeBc interface + ProtocolAddrPtr := Pointer to IP address + HardwareAddrPtr := Pointer to MAC address storage + +Returns: + TRUE := If IP address was found and MAC address was stored + FALSE := If IP address was not found +--*/ +{ + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + UINTN HardwareAddrLength; + UINTN Index; + + PxeBcMode = Private->EfiBc.Mode; + HardwareAddrLength = Private->SimpleNetwork->Mode->HwAddressSize; + + for (Index = 0; Index < PxeBcMode->ArpCacheEntries; ++Index) { + if (!CompareMem ( + ProtocolAddrPtr, + &PxeBcMode->ArpCache[Index].IpAddr, + Private->IpLength + )) { + CopyMem ( + HardwareAddrPtr, + &PxeBcMode->ArpCache[Index].MacAddr, + HardwareAddrLength + ); + + return TRUE; + } + } + + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +SendRequest ( + IN PXE_BASECODE_DEVICE *Private, + IN EFI_IP_ADDRESS *ProtocolAddrPtr, + IN EFI_MAC_ADDRESS *HardwareAddrPtr + ) +/*++ +Routine description: + Transmit ARP request packet + +Parameters: + Private := Pointer to PxeBc interface + ProtocolAddrPtr := Pointer IP address to find + HardwareAddrPtr := Pointer to MAC address to find + +Returns: + EFI_SUCCESS := ARP request sent + other := ARP request could not be sent +--*/ +{ + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + EFI_SIMPLE_NETWORK_MODE *SnpMode; + ARP_PACKET *ArpPacket; + EFI_STATUS Status; + UINTN HardwareAddrLength; + UINT8 *SrcProtocolAddrPtr; + UINT8 *DestHardwareAddrptr; + UINT8 *DestProtocolAddrPtr; + + // + // + // + PxeBcMode = Private->EfiBc.Mode; + SnpMode = Private->SimpleNetwork->Mode; + HardwareAddrLength = SnpMode->HwAddressSize; + + // + // Allocate ARP buffer + // + if (Private->ArpBuffer == NULL) { + Status = gBS->AllocatePool ( + EfiBootServicesData, + SnpMode->MediaHeaderSize + sizeof (ARP_PACKET), + (VOID **) &Private->ArpBuffer + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + ArpPacket = (VOID *) (Private->ArpBuffer + SnpMode->MediaHeaderSize); + + // + // for now, only handle one kind of hw and pr address + // + ArpPacket->ArpHeader = ArpHeader; + ArpPacket->ArpHeader.HwAddLen = (UINT8) HardwareAddrLength; + ArpPacket->ArpHeader.ProtAddLen = (UINT8) Private->IpLength; + + // + // rest more generic + // + SrcProtocolAddrPtr = (UINT8 *) (&ArpPacket->SrcHardwareAddr) + HardwareAddrLength; + DestHardwareAddrptr = SrcProtocolAddrPtr + Private->IpLength; + DestProtocolAddrPtr = DestHardwareAddrptr + HardwareAddrLength; + + CopyMem (DestProtocolAddrPtr, ProtocolAddrPtr, Private->IpLength); + CopyMem (DestHardwareAddrptr, HardwareAddrPtr, HardwareAddrLength); + CopyMem (SrcProtocolAddrPtr, &PxeBcMode->StationIp, Private->IpLength); + CopyMem ( + &ArpPacket->SrcHardwareAddr, + &SnpMode->CurrentAddress, + HardwareAddrLength + ); + + return SendPacket ( + Private, + Private->ArpBuffer, + ArpPacket, + sizeof (ARP_HEADER) + ((Private->IpLength + HardwareAddrLength) << 1), + &SnpMode->BroadcastAddress, + PXE_PROTOCOL_ETHERNET_ARP, + EFI_PXE_BASE_CODE_FUNCTION_ARP + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// check for address - if not there, send ARP request, wait and check again +// not how it would be done in a full system +// +#define ARP_REQUEST_TIMEOUT_MS 500 // try for half a second + + //////////////////////////////////////////////////////////// +// +// BC Arp Routine +// +EFI_STATUS +EFIAPI +BcArp ( + IN EFI_PXE_BASE_CODE_PROTOCOL * This, + IN EFI_IP_ADDRESS * ProtocolAddrPtr, + OUT EFI_MAC_ADDRESS * HardwareAddrPtr OPTIONAL + ) +/*++ +Routine description: + PxeBc ARP API. + +Parameters: + This := Pointer to PxeBc interface + ProtocolAddrPtr := Pointer to IP address to find + HardwareAddrPtr := Pointer to MAC address found. + +Returns: +--*/ +{ + EFI_MAC_ADDRESS Mac; + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + // + // Lock the instance data and make sure started + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + if (This->Mode == NULL || !This->Mode->Started) { + DEBUG ((EFI_D_ERROR, "BC was not started.")); + EfiReleaseLock (&Private->Lock); + return EFI_NOT_STARTED; + } + + DEBUG ((EFI_D_INFO, "\nBcArp()")); + + // + // Issue BC command + // + if (ProtocolAddrPtr == NULL) { + DEBUG ( + (EFI_D_INFO, + "\nBcArp() Exit #1 %Xh (%r)", + EFI_INVALID_PARAMETER, + EFI_INVALID_PARAMETER) + ); + + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + + if (HardwareAddrPtr == NULL) { + HardwareAddrPtr = &Mac; + } + + ZeroMem (HardwareAddrPtr, Private->SimpleNetwork->Mode->HwAddressSize); + + if (GetHwAddr (Private, ProtocolAddrPtr, HardwareAddrPtr)) { + DEBUG ( + (EFI_D_INFO, + "\nBcArp() Exit #2 %Xh (%r)", + EFI_SUCCESS, + EFI_SUCCESS) + ); + + EfiReleaseLock (&Private->Lock); + return EFI_SUCCESS; + } + + StatCode = DoArp (Private, ProtocolAddrPtr, HardwareAddrPtr); + + DEBUG ((EFI_D_INFO, "\nBcArp() Exit #3 %Xh (%r)", StatCode, StatCode)); + + EfiReleaseLock (&Private->Lock); + return StatCode; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +DoArp ( + IN PXE_BASECODE_DEVICE *Private, + IN EFI_IP_ADDRESS *ProtocolAddrPtr, + OUT EFI_MAC_ADDRESS *HardwareAddrPtr + ) +/*++ +Routine description: + Internal ARP implementation. + +Parameters: + Private := Pointer to PxeBc interface + ProtocolAddrPtr := Pointer to IP address to find + HardwareAddrPtr := Pointer to MAC address found + +Returns: + EFI_SUCCESS := MAC address found + other := MAC address could not be found +--*/ +{ + EFI_STATUS StatCode; + EFI_EVENT TimeoutEvent; + UINTN HeaderSize; + UINTN BufferSize; + UINT16 Protocol; + + DEBUG ((EFI_D_INFO, "\nDoArp()")); + + // + // + // + StatCode = SendRequest (Private, ProtocolAddrPtr, HardwareAddrPtr); + + if (EFI_ERROR (StatCode)) { + DEBUG ((EFI_D_INFO, "\nDoArp() Exit #1 %Xh (%r)", StatCode, StatCode)); + return StatCode; + } + // + // + // + StatCode = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); + + if (EFI_ERROR (StatCode)) { + return StatCode; + } + + StatCode = gBS->SetTimer ( + TimeoutEvent, + TimerRelative, + ARP_REQUEST_TIMEOUT_MS * 10000 + ); + + if (EFI_ERROR (StatCode)) { + gBS->CloseEvent (TimeoutEvent); + return StatCode; + } + // + // + // + for (;;) { + StatCode = WaitForReceive ( + Private, + EFI_PXE_BASE_CODE_FUNCTION_ARP, + TimeoutEvent, + &HeaderSize, + &BufferSize, + &Protocol + ); + + if (EFI_ERROR (StatCode)) { + break; + } + + if (Protocol != PXE_PROTOCOL_ETHERNET_ARP) { + continue; + } + + HandleArpReceive ( + Private, + (ARP_PACKET *) (Private->ReceiveBufferPtr + HeaderSize), + Private->ReceiveBufferPtr + ); + + if (GetHwAddr (Private, ProtocolAddrPtr, HardwareAddrPtr)) { + break; + } + } + + DEBUG ( + (EFI_D_INFO, + "\nDoArp() Exit #2 %Xh, (%r)", + StatCode, + StatCode) + ); + + gBS->CloseEvent (TimeoutEvent); + + return StatCode; +} + +/* eof - pxe_bc_arp.c */ diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_dhcp.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_dhcp.c new file mode 100644 index 0000000000..012b61cf37 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_dhcp.c @@ -0,0 +1,3332 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + pxe_bc_dhcp.c + +Abstract: + DHCP and PXE discovery protocol implementations. + +--*/ + + +#include "bc.h" + +STATIC EFI_PXE_BASE_CODE_UDP_PORT DhcpServerPort = DHCP_SERVER_PORT; +STATIC EFI_PXE_BASE_CODE_UDP_PORT DHCPClientPort = DHCP_CLIENT_PORT; +STATIC EFI_PXE_BASE_CODE_UDP_PORT PseudoDhcpServerPort = PXE_DISCOVERY_PORT; +#define PSEUDO_DHCP_CLIENT_PORT PseudoDhcpServerPort +STATIC EFI_IP_ADDRESS BroadcastIP = { { 0xffffffff } }; +STATIC EFI_IP_ADDRESS DefaultSubnetMask = { { 0xffffff00 } }; + +typedef union { + DHCPV4_OP_STRUCT *OpPtr; + PXE_OP_SERVER_LIST *BootServersStr; + PXE_SERVER_LIST *BootServerList; + PXE_BOOT_MENU_ENTRY *BootMenuItem; + PXE_OP_DISCOVERY_CONTROL *DiscoveryControl; + PXE_OP_BOOT_MENU *BootMenu; + PXE_OP_BOOT_ITEM *BootItem; + DHCPV4_OP_VENDOR_OPTIONS *VendorOptions; + DHCPV4_OP_OVERLOAD *Overload; + DHCPV4_OP_CLASS *PxeClassStr; + DHCPV4_OP_SUBNET_MASK *SubnetMaskStr; + DHCPV4_OP_MESSAGE_TYPE *MessageType; + UINT8 *BytePtr; +} UNION_PTR; + +// +// 1 for Itanium-based, 0 for IA32 +// +#define IA64SZ ((sizeof (UINTN) / sizeof (UINT32)) - 1) + +#define SYS_ARCH (SYS_ARCH_EFI32 - (SYS_ARCH_EFI32 - IA64) * IA64SZ) + +#pragma pack(1) +// +// option structure for DHCPREQUEST at end of DISCOVER options +// and for DHCPDECLINE +// +STATIC const struct requestopendstr { + DHCPV4_OP_REQUESTED_IP OpReqIP; + DHCPV4_OP_SERVER_IP DhcServerIpPtr; + UINT8 End[1]; +} +RequestOpEndStr = { + { + { + OP_DHCP_REQ_IP_ADD, + DHCPV4_OPTION_LENGTH(DHCPV4_OP_REQUESTED_IP) + } + }, + { + { + OP_DHCP_SERVER_IP, + DHCPV4_OPTION_LENGTH(DHCPV4_OP_SERVER_IP) + } + }, + { + OP_END + } +}; + +#define DHCP_REQ_OPTIONS (*(struct requestopendstr *) DHCPV4_OPTIONS_BUFFER.End) + +PXE_OP_BOOT_ITEM DefaultBootItem = { + { + VEND_PXE_BOOT_ITEM, + DHCPV4_OPTION_LENGTH(PXE_OP_BOOT_ITEM) + }, + 0, 0, +}; + +// +// PXE discovery control default structure +// +STATIC PXE_OP_DISCOVERY_CONTROL DefaultDisCtl = { + { VEND_PXE_DISCOVERY_CONTROL, DHCPV4_OPTION_LENGTH(PXE_OP_DISCOVERY_CONTROL) }, + 0 +}; + +// +// PXE credentials option structure +// +typedef struct { + UINT8 c[4]; +} PXE_CREDENTIAL; + +typedef struct { + DHCPV4_OP_HEADER Header; + PXE_CREDENTIAL Credentials[1]; +} PXE_OP_CREDENTIAL_TYPES; + +// +// option structure for PXE discover (without credentials) +// +typedef struct { // discoveropendstr { + DHCPV4_OP_HEADER Header; // vendor options + PXE_OP_BOOT_ITEM BootItem; + UINT8 End[1]; // if credentials option, it starts here +} PXE_DISCOVER_OPTIONS; + +#define DISCOVERoptions (*(PXE_DISCOVER_OPTIONS *) DHCPV4_OPTIONS_BUFFER.End) +#define DISCREDoptions (*(PXE_OP_CREDENTIAL_TYPES *) DISCOVERoptions.End) + +// +// common option beginning for all our DHCP messages except +// DHCPDECLINE and DHCPRELEASE +// +STATIC struct optionsstr { + UINT8 DhcpCookie[4]; + DHCPV4_OP_MESSAGE_TYPE DhcpMessageType; + DHCPV4_OP_MAX_MESSAGE_SIZE DhcpMaxMessageSize; + DHCPV4_OP_REQUESTED_OPTIONS DhcpRequestedOptions; + DHCPV4_OP_PLATFORM_ID DhcpPlatformId; + DHCPV4_OP_NETWORK_INTERFACE DhcpNetworkInterface; + DHCPV4_OP_ARCHITECTURE_TYPE DhcpClientArchitecture; + DHCPV4_OP_CLASS_ID DhcpClassIdentifier; + UINT8 End[1]; +} DHCPOpStart; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +OptionsStrucInit ( + VOID + ) +{ + DHCPOpStart.DhcpCookie[0] = 99; + DHCPOpStart.DhcpCookie[1] = 130; + DHCPOpStart.DhcpCookie[2] = 83; + DHCPOpStart.DhcpCookie[3] = 99; + DHCPOpStart.DhcpMessageType.Header.OpCode = OP_DHCP_MESSAGE_TYPE; + DHCPOpStart.DhcpMessageType.Header.Length = 1; + DHCPOpStart.DhcpMessageType.Type = DHCPDISCOVER; + DHCPOpStart.DhcpMaxMessageSize.Header.OpCode = OP_DHCP_MAX_MESSAGE_SZ; + DHCPOpStart.DhcpMaxMessageSize.Header.Length = 2; + DHCPOpStart.DhcpMaxMessageSize.MaxSize[0] = MAX_DHCP_MSG_SZ >> 8; + DHCPOpStart.DhcpMaxMessageSize.MaxSize[1] = MAX_DHCP_MSG_SZ & 0xff; + DHCPOpStart.DhcpRequestedOptions.Header.OpCode = OP_DHCP_PARM_REQ_LIST; + DHCPOpStart.DhcpRequestedOptions.Header.Length = sizeof (DHCPV4_REQUESTED_OPTIONS_DATA); + DHCPOpStart.DhcpRequestedOptions.Data._OP_SUBNET_MASK = OP_SUBNET_MASK; /* 1 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_TIME_OFFSET = OP_TIME_OFFSET; /* 2 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_ROUTER_LIST = OP_ROUTER_LIST; /* 3 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_TIME_SERVERS = OP_TIME_SERVERS; /* 4 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_NAME_SERVERS = OP_NAME_SERVERS; /* 5 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DNS_SERVERS = OP_DNS_SERVERS; /* 6 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_HOST_NAME = OP_HOST_NAME; /* 12 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_BOOT_FILE_SZ = OP_BOOT_FILE_SZ; /* 13 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DOMAIN_NAME = OP_DOMAIN_NAME; /* 15 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_ROOT_PATH = OP_ROOT_PATH; /* 17 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_EXTENSION_PATH = OP_EXTENSION_PATH; /* 18 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_MAX_DATAGRAM_SZ = OP_MAX_DATAGRAM_SZ; /* 22 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DEFAULT_TTL = OP_DEFAULT_TTL; /* 23 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_BROADCAST_ADD = OP_BROADCAST_ADD; /* 28 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_NIS_DOMAIN_NAME = OP_NIS_DOMAIN_NAME; /* 40 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_NIS_SERVERS = OP_NIS_SERVERS; /* 41 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_NTP_SERVERS = OP_NTP_SERVERS; /* 42 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_VENDOR_SPECIFIC = OP_VENDOR_SPECIFIC; /* 43 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_REQ_IP_ADD = OP_DHCP_REQ_IP_ADD; /* 50 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_LEASE_TIME = OP_DHCP_LEASE_TIME; /* 51 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_SERVER_IP = OP_DHCP_SERVER_IP; /* 54 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_RENEWAL_TIME = OP_DHCP_RENEWAL_TIME; /* 58 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_REBINDING_TIME = OP_DHCP_REBINDING_TIME; /* 59 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_CLASS_IDENTIFIER = OP_DHCP_CLASS_IDENTIFIER; /* 60 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_TFTP_SERVER_NAME = OP_DHCP_TFTP_SERVER_NAME; /* 66 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_BOOTFILE = OP_DHCP_BOOTFILE; /* 67 */ + DHCPOpStart.DhcpRequestedOptions.Data._OP_DHCP_PLATFORM_ID = OP_DHCP_PLATFORM_ID; /* 97 */ + DHCPOpStart.DhcpRequestedOptions.Data.VendorOption128 = 128; + DHCPOpStart.DhcpRequestedOptions.Data.VendorOption129 = 129; + DHCPOpStart.DhcpRequestedOptions.Data.VendorOption130 = 130; + DHCPOpStart.DhcpRequestedOptions.Data.VendorOption131 = 131; + DHCPOpStart.DhcpRequestedOptions.Data.VendorOption132 = 132; + DHCPOpStart.DhcpRequestedOptions.Data.VendorOption133 = 133, DHCPOpStart.DhcpRequestedOptions.Data.VendorOption134 = 134; + DHCPOpStart.DhcpRequestedOptions.Data.VendorOption135 = 135; + DHCPOpStart.DhcpPlatformId.Header.OpCode = OP_DHCP_PLATFORM_ID; + DHCPOpStart.DhcpPlatformId.Header.Length = DHCPV4_OPTION_LENGTH (DHCPV4_OP_PLATFORM_ID); + DHCPOpStart.DhcpNetworkInterface.Header.OpCode = OP_DHCP_NETWORK_ARCH; + DHCPOpStart.DhcpNetworkInterface.Header.Length = DHCPV4_OPTION_LENGTH (DHCPV4_OP_NETWORK_INTERFACE); + DHCPOpStart.DhcpNetworkInterface.Type = 0; + DHCPOpStart.DhcpNetworkInterface.MajorVersion = 0; + DHCPOpStart.DhcpNetworkInterface.MinorVersion = 0; + DHCPOpStart.DhcpClientArchitecture.Header.OpCode = OP_DHCP_SYSTEM_ARCH; + DHCPOpStart.DhcpClientArchitecture.Header.Length = DHCPV4_OPTION_LENGTH (DHCPV4_OP_ARCHITECTURE_TYPE); + DHCPOpStart.DhcpClientArchitecture.Type = HTONS (SYS_ARCH); + DHCPOpStart.DhcpClassIdentifier.Header.OpCode = OP_DHCP_CLASS_IDENTIFIER; + DHCPOpStart.DhcpClassIdentifier.Header.Length = sizeof (DHCPV4_CLASS_ID_DATA); + CopyMem ( + DHCPOpStart.DhcpClassIdentifier.Data.ClassIdentifier, + "PXEClient:", + sizeof ("PXEClient:") + ); + CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.Lit2, "Arch:", sizeof ("Arch:")); + CopyMem ( + DHCPOpStart.DhcpClassIdentifier.Data.ArchitectureType, + "xxxxx", + sizeof ("xxxxx") + ); + CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.Lit3, ":", sizeof (":")); + CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.InterfaceName, "XXXX", sizeof ("XXXX")); + CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.Lit4, ":", sizeof (":")); + CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.UndiMajor, "yyy", sizeof ("yyy")); + CopyMem (DHCPOpStart.DhcpClassIdentifier.Data.UndiMinor, "xxx", sizeof ("xxx")); + DHCPOpStart.End[0] = OP_END; +}; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// DHCPDECLINE option structure +// +struct opdeclinestr { + UINT8 DhcpCookie[4]; + DHCPV4_OP_MESSAGE_TYPE DhcpMessageType; + struct requestopendstr OpDeclineEnd; +}; + +#define DHCPDECLINEoptions (*(struct opdeclinestr *) DHCPV4_TRANSMIT_BUFFER.options) + +// +// DHCPRELEASE option structure +// +struct opreleasestr { + UINT8 DhcpCookie[4]; + DHCPV4_OP_MESSAGE_TYPE DhcpMessageType; + DHCPV4_OP_SERVER_IP DhcServerIpPtr; + UINT8 End[1]; +}; + +#define DHCPRELEASEoptions (*(struct opreleasestr *) DHCPV4_TRANSMIT_BUFFER.options) + +// +// array of PXE vendor options in which we are interested +// value 0 -> not of interest, else value is index into PXE OPTION array +// option values from 1 to MAX_OUR_PXE_OPT +// +STATIC UINT8 ourPXEopts[MAX_OUR_PXE_OPT] = { + VEND_PXE_MTFTP_IP_IX, // multicast IP address of bootfile for MTFTP listen + VEND_PXE_MTFTP_CPORT_IX, // UDP Port to monitor for MTFTP responses - Intel order + VEND_PXE_MTFTP_SPORT_IX, // Server UDP Port for MTFTP open - Intel order + VEND_PXE_MTFTP_TMOUT_IX, // Listen timeout - secs + VEND_PXE_MTFTP_DELAY_IX, // Transmission timeout - secs + VEND_PXE_DISCOVERY_CONTROL_IX, // bit field + VEND_PXE_DISCOVERY_MCAST_ADDR_IX, // boot server discovery multicast address + VEND_PXE_BOOT_SERVERS_IX, // list of boot servers of form tp(2) cnt(1) ips[cnt] + VEND_PXE_BOOT_MENU_IX, + VEND_PXE_BOOT_PROMPT_IX, + VEND_PXE_MCAST_ADDRS_ALLOC_IX, // not used by client + VEND_PXE_CREDENTIAL_TYPES_IX, + VEND_13_IX, // not used by client + VEND_14_IX, // not used by client + VEND_15_IX, // not used by client + VEND_16_IX, // not used by client + VEND_17_IX, // not used by client + VEND_18_IX, // not used by client + VEND_19_IX, // not used by client + VEND_20_IX, // not used by client + VEND_21_IX, // not used by client + VEND_22_IX, // not used by client + VEND_23_IX, // not used by client + VEND_24_IX, // not used by client + VEND_25_IX, // not used by client + VEND_26_IX, // not used by client + VEND_27_IX, // not used by client + VEND_28_IX, // not used by client + VEND_29_IX, // not used by client + VEND_30_IX, // not used by client + VEND_31_IX, // not used by client + VEND_32_IX, // not used by client + VEND_33_IX, // not used by client + VEND_34_IX, // not used by client + VEND_35_IX, // not used by client + VEND_36_IX, // not used by client + VEND_37_IX, // not used by client + VEND_38_IX, // not used by client + VEND_39_IX, // not used by client + VEND_40_IX, // not used by client + VEND_41_IX, // not used by client + VEND_42_IX, // not used by client + VEND_43_IX, // not used by client + VEND_44_IX, // not used by client + VEND_45_IX, // not used by client + VEND_46_IX, // not used by client + VEND_47_IX, // not used by client + VEND_48_IX, // not used by client + VEND_49_IX, // not used by client + VEND_50_IX, // not used by client + VEND_51_IX, // not used by client + VEND_52_IX, // not used by client + VEND_53_IX, // not used by client + VEND_54_IX, // not used by client + VEND_55_IX, // not used by client + VEND_56_IX, // not used by client + VEND_57_IX, // not used by client + VEND_58_IX, // not used by client + VEND_59_IX, // not used by client + VEND_60_IX, // not used by client + VEND_61_IX, // not used by client + VEND_62_IX, // not used by client + VEND_63_IX, // not used by client + VEND_64_IX, // not used by client + VEND_65_IX, // not used by client + VEND_66_IX, // not used by client + VEND_67_IX, // not used by client + VEND_68_IX, // not used by client + VEND_69_IX, // not used by client + VEND_70_IX, // not used by client + VEND_PXE_BOOT_ITEM_IX +}; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// array of options in which we are interested +// value 0 -> not of interest, else value is index into OPTION array +// option values from 1 to MAX_OUR_OPT +// +STATIC UINT8 OurDhcpOptions[MAX_OUR_OPT] = { + OP_SUBNET_MASK_IX, // OP_SUBNET_MASK 1 // data is the subnet mask + OP_TIME_OFFSET_IX, // OP_TIME_OFFSET 2 // data is the time offset of subnet to UTC in seconds + OP_ROUTER_LIST_IX, // OP_ROUTER_LIST 3 // list of routers on subnet + OP_TIME_SERVERS_IX, // OP_TIME_SERVERS 4 // list of time servers available + OP_NAME_SERVERS_IX, // OP_NAME_SERVERS 5 // list of name servers available + OP_DNS_SERVERS_IX, // OP_DNS_SERVERS 6 // list of DNS servers available + OP_LOG_SERVERS_IX, // OP_LOG_SERVERS 7 + OP_COOKIE_SERVERS_IX, // OP_COOKIE_SERVERS 8 + OP_LPR_SREVERS_IX, // OP_LPR_SREVERS 9 + OP_IMPRESS_SERVERS_IX, // OP_IMPRESS_SERVERS 10 + OP_RES_LOC_SERVERS_IX, // OP_RES_LOC_SERVERS 11 + OP_HOST_NAME_IX, // OP_HOST_NAME 12 // client name + OP_BOOT_FILE_SZ_IX, // OP_BOOT_FILE_SZ 13 // number of 512 blocks of boot file + OP_DUMP_FILE_IX, // OP_DUMP_FILE 14 // path name of dump file if client crashes + OP_DOMAIN_NAME_IX, // OP_DOMAIN_NAME 15 // domain name to use + OP_SWAP_SERVER_IX, // OP_SWAP_SERVER 16 + OP_ROOT_PATH_IX, // OP_ROOT_PATH 17 // path name containing root disk + OP_EXTENSION_PATH_IX, // OP_EXTENSION_PATH 18 // name of TFTP downloadable file of form of OP + OP_IP_FORWARDING_IX, // OP_IP_FORWARDING 19 // enable/disable IP packet forwarding + OP_NON_LOCAL_SRC_RTE_IX, // OP_NON_LOCAL_SRC_RTE 20 // enable/disable non local source routing + OP_POLICY_FILTER_IX, // OP_POLICY_FILTER 21 // policy filters for non local source routing + OP_MAX_DATAGRAM_SZ_IX, // OP_MAX_DATAGRAM_SZ 22 // maximum datagram reassembly size + OP_DEFAULT_TTL_IX, // OP_DEFAULT_TTL 23 // default IP time to live + OP_MTU_AGING_TIMEOUT_IX, // OP_MTU_AGING_TIMEOUT 24 + OP_MTU_SIZES_IX, // OP_MTU_SIZES 25 + OP_MTU_TO_USE_IX, // OP_MTU_TO_USE 26 + OP_ALL_SUBNETS_LOCAL_IX, // OP_ALL_SUBNETS_LOCAL 27 + OP_BROADCAST_ADD_IX, // OP_BROADCAST_ADD 28 // broadcast address used on subnet + OP_PERFORM_MASK_DISCOVERY_IX, // OP_PERFORM_MASK_DISCOVERY 29 // perform mask discovery using ICMP + OP_RESPOND_TO_MASK_REQ_IX, // OP_RESPOND_TO_MASK_REQ 30 // respond to subnet mask requests using ICMP + OP_PERFORM_ROUTER_DISCOVERY_IX, // OP_PERFORM_ROUTER_DISCOVERY 31 + OP_ROUTER_SOLICIT_ADDRESS_IX, // OP_ROUTER_SOLICIT_ADDRESS 32 + OP_STATIC_ROUTER_LIST_IX, // OP_STATIC_ROUTER_LIST 33 // list of dest/route pairs + OP_USE_ARP_TRAILERS_IX, // OP_USE_ARP_TRAILERS 34 + OP_ARP_CACHE_TIMEOUT_IX, // OP_ARP_CACHE_TIMEOUT 35 + OP_ETHERNET_ENCAPSULATION_IX, // OP_ETHERNET_ENCAPSULATION 36 // 0 -> RFC 894, 1 -> IEEE 802.3 (RFC 1042) + OP_TCP_DEFAULT_TTL_IX, // OP_TCP_DEFAULT_TTL 37 // default time to live when sending TCP segments + OP_TCP_KEEP_ALIVE_INT_IX, // OP_TCP_KEEP_ALIVE_INT 38 // keep alive interval in seconds + OP_KEEP_ALIVE_GARBAGE_IX, // OP_KEEP_ALIVE_GARBAGE 39 + OP_NIS_DOMAIN_NAME_IX, // OP_NIS_DOMAIN_NAME 40 + OP_NIS_SERVERS_IX, // OP_NIS_SERVERS 41 + OP_NTP_SERVERS_IX, // OP_NTP_SERVERS 42 + OP_VENDOR_SPECIFIC_IX, // OP_VENDOR_SPECIFIC 43 + OP_NBNS_SERVERS_IX, // OP_NBNS_SERVERS 44 + OP_NBDD_SERVERS_IX, // OP_NBDD_SERVERS 45 + OP_NETBIOS_NODE_TYPE_IX, // OP_NETBIOS_NODE_TYPE 46 + OP_NETBIOS_SCOPE_IX, // OP_NETBIOS_SCOPE 47 + OP_XWINDOW_SYSTEM_FONT_SERVERS_IX, // OP_XWINDOW_SYSTEM_FONT_SERVERS 48 + OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS_IX, // OP_XWINDOW_SYSTEM_DISPLAY_MANAGERS 49 + OP_DHCP_REQ_IP_ADD_IX, // OP_DHCP_REQ_IP_ADD 50 // requested IP address - in DHCPDISCOVER + OP_DHCP_LEASE_TIME_IX, // OP_DHCP_LEASE_TIME 51 // lease time requested/granted + OP_DHCP_OPTION_OVERLOAD_IX, // OP_DHCP_OPTION_OVERLOAD 52 // file/server name/both used to hold options + OP_DHCP_MESSAGE_TYPE_IX, // OP_DHCP_MESSAGE_TYPE 53 // message type + OP_DHCP_SERVER_IP_IX, // OP_DHCP_SERVER_IP 54 // IP of server + OP_DHCP_PARM_REQ_LIST_IX, // OP_DHCP_PARM_REQ_LIST 55 // list of requested parameters + OP_DHCP_ERROR_MESSAGE_IX, // OP_DHCP_ERROR_MESSAGE 56 // in DHCPNAK or DECLINE messages + OP_DHCP_MAX_MESSAGE_SZ_IX, // OP_DHCP_MAX_MESSAGE_SZ 57 // maximum DHCP message size client will accept + OP_DHCP_RENEWAL_TIME_IX, // OP_DHCP_RENEWAL_TIME 58 // time in seconds before transitioning to RENEWING state + OP_DHCP_REBINDING_TIME_IX, // OP_DHCP_REBINDING_TIME 59 // time in seconds before transitioning to REBINDING state + OP_DHCP_CLASS_IDENTIFIER_IX, // OP_DHCP_CLASS_IDENTIFIER 60 + OP_DHCP_CLIENT_IDENTIFIER_IX, // OP_DHCP_CLIENT_IDENTIFIER 61 + OP_RESERVED62_IX, // OP_RESERVED62 + OP_RESERVED63_IX, // OP_RESERVED63 + OP_NISPLUS_DOMAIN_NAME_IX, // OP_NISPLUS_DOMAIN_NAME 64 + OP_NISPLUS_SERVERS_IX, // OP_NISPLUS_SERVERS 65 + OP_DHCP_TFTP_SERVER_NAME_IX, // OP_DHCP_TFTP_SERVER_NAME 66 + OP_DHCP_BOOTFILE_IX // OP_DHCP_BOOTFILE 67 +}; + +#define RxBuf ((DHCP_RECEIVE_BUFFER *) (Private->ReceiveBuffers)) + +#pragma pack() + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +CHAR8 * +PxeBcLibGetSmbiosString ( + IN SMBIOS_STRUCTURE_POINTER *Smbios, + IN UINT16 StringNumber + ) +/*++ +Routine description: + Return SMBIOS string given the string number. + +Arguments: + Smbios - Pointer to SMBIOS structure + StringNumber - String number to return. 0 is used to skip all strings and + point to the next SMBIOS structure. + +Returns: + Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == 0 +--*/ +{ + UINT16 Index; + CHAR8 *String; + + // + // Skip over formatted section + // + String = (CHAR8 *) (Smbios->Raw + Smbios->Hdr->Length); + + // + // Look through unformated section + // + for (Index = 1; Index <= StringNumber || StringNumber == 0; Index++) { + if (StringNumber == Index) { + return String; + } + // + // Skip string + // + for (; *String != 0; String++) + ; + String++; + + if (*String == 0) { + // + // If double NULL then we are done. + // Return pointer to next structure in Smbios. + // if you pass in a 0 you will always get here + // + Smbios->Raw = (UINT8 *)++String; + return NULL; + } + } + + return NULL; +} + +EFI_STATUS +PxeBcLibGetSmbiosSystemGuidAndSerialNumber ( + IN EFI_GUID *SystemGuid, + OUT CHAR8 **SystemSerialNumber + ) +/*++ + +Routine Description: + This function gets system guid and serial number from the smbios table + +Arguments: + SystemGuid - The pointer of returned system guid + SystemSerialNumber - The pointer of returned system serial number + +Returns: + EFI_SUCCESS - Successfully get the system guid and system serial number + EFI_NOT_FOUND - Not find the SMBIOS table +--*/ +{ + EFI_STATUS Status; + SMBIOS_STRUCTURE_TABLE *SmbiosTable; + SMBIOS_STRUCTURE_POINTER Smbios; + SMBIOS_STRUCTURE_POINTER SmbiosEnd; + UINT16 Index; + + Status = EfiGetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID **) &SmbiosTable); + + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + Smbios.Hdr = (SMBIOS_HEADER *) (UINTN) SmbiosTable->TableAddress; + SmbiosEnd.Raw = (UINT8 *) (UINTN) (SmbiosTable->TableAddress + SmbiosTable->TableLength); + + for (Index = 0; Index < SmbiosTable->TableLength; Index++) { + if (Smbios.Hdr->Type == 1) { + if (Smbios.Hdr->Length < 0x19) { + // + // Older version did not support Guid and Serial number + // + continue; + } + // + // SMBIOS tables are byte packed so we need to do a byte copy to + // prevend alignment faults on Itanium-based platform. + // + CopyMem (SystemGuid, &Smbios.Type1->Uuid, sizeof (EFI_GUID)); + *SystemSerialNumber = PxeBcLibGetSmbiosString (&Smbios, Smbios.Type1->SerialNumber); + + return EFI_SUCCESS; + } + // + // Make Smbios point to the next record + // + PxeBcLibGetSmbiosString (&Smbios, 0); + + if (Smbios.Raw >= SmbiosEnd.Raw) { + // + // SMBIOS 2.1 incorrectly stated the length of SmbiosTable as 0x1e. + // given this we must double check against the lenght of + // the structure. + // + return EFI_SUCCESS; + } + } + + return EFI_SUCCESS; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// add router list to list +// +STATIC +VOID +Ip4AddRouterList ( + PXE_BASECODE_DEVICE *Private, + DHCPV4_OP_IP_LIST *IpListPtr + ) +{ + EFI_IP_ADDRESS TmpIp; + INTN Index; + INTN num; + + if (IpListPtr == NULL) { + return ; + } + + for (Index = 0, num = IpListPtr->Header.Length >> 2; Index < num; ++Index) { + CopyMem (&TmpIp, &IpListPtr->IpList[Index], 4); + Ip4AddRouter (Private, &TmpIp); + } +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// send ARP for our IP - fail if someone has it +// +STATIC +BOOLEAN +SetStationIP ( + PXE_BASECODE_DEVICE *Private + ) +{ + EFI_MAC_ADDRESS DestMac; + EFI_STATUS EfiStatus; + + ZeroMem (&DestMac, sizeof DestMac); + + if (GetHwAddr(Private, (EFI_IP_ADDRESS *)&DHCP_REQ_OPTIONS.OpReqIP.Ip, (EFI_MAC_ADDRESS *)&DestMac) + || DoArp(Private, (EFI_IP_ADDRESS *)&DHCP_REQ_OPTIONS.OpReqIP.Ip, (EFI_MAC_ADDRESS *)&DestMac) == EFI_SUCCESS) { + return FALSE; // somebody else has this IP + } + + CopyMem ( + (EFI_IPv4_ADDRESS *) &Private->EfiBc.Mode->StationIp, + &DHCP_REQ_OPTIONS.OpReqIP.Ip, + sizeof (EFI_IPv4_ADDRESS) + ); + + Private->GoodStationIp = TRUE; + + if (!Private->UseIgmpv1Reporting) { + return TRUE; + } + + if (Private->Igmpv1TimeoutEvent != NULL) { + return TRUE; + } + + EfiStatus = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &Private->Igmpv1TimeoutEvent + ); + + if (EFI_ERROR (EfiStatus)) { + Private->Igmpv1TimeoutEvent = NULL; + return TRUE; + } + + EfiStatus = gBS->SetTimer ( + Private->Igmpv1TimeoutEvent, + TimerRelative, + (UINT64) V1ROUTER_PRESENT_TIMEOUT * 10000000 + ); /* 400 seconds */ + + if (EFI_ERROR (EfiStatus)) { + gBS->CloseEvent (Private->Igmpv1TimeoutEvent); + Private->Igmpv1TimeoutEvent = NULL; + } + + return TRUE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +VOID +AddRouters ( + PXE_BASECODE_DEVICE *Private, + DHCP_RECEIVE_BUFFER *RxBufPtr + ) +{ + Ip4AddRouter (Private, &RxBufPtr->u.Dhcpv4.giaddr); + + Ip4AddRouterList ( + Private, + (DHCPV4_OP_IP_LIST *) RxBufPtr->OpAdds.PktOptAdds[OP_ROUTER_LIST_IX - 1] + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +DoUdpWrite ( + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS *ServerIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ServerPortPtr, + EFI_IP_ADDRESS *ClientIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ClientPortPtr + ) +{ + UINTN Len; + + Len = sizeof DHCPV4_TRANSMIT_BUFFER; + + return UdpWrite ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT, + ServerIpPtr, + ServerPortPtr, + 0, + ClientIpPtr, + ClientPortPtr, + 0, + 0, + &Len, + Private->TransmitBuffer + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// initialize the DHCP structure +// +typedef struct { + UINT8 x[4]; +} C4Str; + +STATIC +VOID +InitDhcpv4TxBuf ( + PXE_BASECODE_DEVICE *Private + ) +{ + UINTN HwAddrLen; + UINT8 *String; + CHAR8 *SystemSerialNumber; + EFI_PXE_BASE_CODE_MODE *PxebcMode; + + PxebcMode = Private->EfiBc.Mode; + + ZeroMem (&DHCPV4_TRANSMIT_BUFFER, sizeof (DHCPV4_STRUCT)); + DHCPV4_TRANSMIT_BUFFER.op = BOOTP_REQUEST; + DHCPV4_TRANSMIT_BUFFER.htype = Private->SimpleNetwork->Mode->IfType; + DHCPV4_TRANSMIT_BUFFER.flags = HTONS (DHCP_BROADCAST_FLAG); + CopyMem (&DHCPV4_OPTIONS_BUFFER, (VOID *) &DHCPOpStart, sizeof (DHCPOpStart)); + + // + // default to hardware address + // + HwAddrLen = Private->SimpleNetwork->Mode->HwAddressSize; + + if (HwAddrLen > sizeof DHCPV4_TRANSMIT_BUFFER.chaddr) { + HwAddrLen = sizeof DHCPV4_TRANSMIT_BUFFER.chaddr; + } + + String = (UINT8 *) &Private->SimpleNetwork->Mode->CurrentAddress; + + if (PxeBcLibGetSmbiosSystemGuidAndSerialNumber ( + (EFI_GUID *) DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, + &SystemSerialNumber + ) == EFI_SUCCESS) { + if (PxebcMode->SendGUID) { + HwAddrLen = sizeof (EFI_GUID); + String = (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid; + } + } else { + // + // GUID not yet set - send all 0xff's to show programable (via SetVariable) + // SetMem(DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof(EFI_GUID), 0xff); + // GUID not yet set - send all 0's to show not programable + // + ZeroMem (DHCPV4_OPTIONS_BUFFER.DhcpPlatformId.Guid, sizeof (EFI_GUID)); + } + + DHCPV4_TRANSMIT_BUFFER.hlen = (UINT8) HwAddrLen; + CopyMem (DHCPV4_TRANSMIT_BUFFER.chaddr, String, HwAddrLen); + + CvtNum ( + SYS_ARCH, + (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.ArchitectureType, + sizeof DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.ArchitectureType + ); + + DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.Type = Private->NiiPtr->Type; + DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MajorVersion = Private->NiiPtr->MajorVer; + DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MinorVersion = Private->NiiPtr->MinorVer; + + *(C4Str *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.InterfaceName = *(C4Str *) Private->NiiPtr->StringId; + + CvtNum ( + DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MajorVersion, + (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMajor, + sizeof DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMajor + ); + + CvtNum ( + DHCPV4_OPTIONS_BUFFER.DhcpNetworkInterface.MinorVersion, + (UINT8 *) DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMinor, + sizeof DHCPV4_OPTIONS_BUFFER.DhcpClassIdentifier.Data.UndiMinor + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +UINT32 +DecodePxeOptions ( + DHCP_RECEIVE_BUFFER *RxBufPtr, + UINT8 *ptr, + INTN Len + ) +{ + UINT8 Op; + UINT8 *EndPtr; + INTN Index; + UNION_PTR LocalPtr; + UINT32 status; + + status = 0; + + for (EndPtr = ptr + Len; ptr < EndPtr; ptr += Len + 2) { + Op = ptr[0]; + Len = ptr[1]; + + switch (Op) { + case OP_PAD: + Len = -1; + break; + + case OP_END: + return status; + + default: + LocalPtr.BytePtr = ptr; + if (Op <= MAX_OUR_PXE_OPT) { + Index = ourPXEopts[Op - 1]; + if (Index) { + RxBufPtr->OpAdds.PxeOptAdds[Index - 1] = LocalPtr.OpPtr; + status |= 1 << Index; + if (Index == VEND_PXE_BOOT_ITEM && LocalPtr.BootItem->Header.Length == 3) { + RxBufPtr->OpAdds.Status |= USE_THREE_BYTE; + } + } + } + break; + } + } + + return status; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +VOID +DecodeOptions ( + DHCP_RECEIVE_BUFFER *RxBufPtr, + UINT8 *ptr, + INTN Len + ) +{ + UINT8 Op; + UINT8 *EndPtr; + INTN Index; + UNION_PTR LocalPtr; + + for (EndPtr = ptr + Len; ptr < EndPtr; ptr += Len + 2) { + Op = ptr[0]; + Len = ptr[1]; + + switch (Op) { + case OP_PAD: + Len = -1; + break; + + case OP_END: + return ; + + default: + LocalPtr.BytePtr = ptr; + if (Op <= MAX_OUR_OPT) { + Index = OurDhcpOptions[Op - 1]; + if (Index) { + RxBufPtr->OpAdds.PktOptAdds[Index - 1] = LocalPtr.OpPtr; + if (Index == OP_VENDOR_SPECIFIC_IX) { + UINT32 status; + status = DecodePxeOptions ( + RxBufPtr, + (UINT8 *) LocalPtr.VendorOptions->VendorOptions, + LocalPtr.VendorOptions->Header.Length + ); + if (status) { + RxBufPtr->OpAdds.Status |= PXE_TYPE; + // + // check for all the MTFTP info options present - any missing is a nogo + // + if ((status & WfM11a_OPTS) == WfM11a_OPTS) { + RxBufPtr->OpAdds.Status |= WfM11a_TYPE; + } + + if (status & DISCOVER_OPTS) { + RxBufPtr->OpAdds.Status |= DISCOVER_TYPE; + } + + if (status & CREDENTIALS_OPT) { + RxBufPtr->OpAdds.Status |= CREDENTIALS_TYPE; + } + } + } + } + } + break; + } + } +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +Parse ( + DHCP_RECEIVE_BUFFER *RxBufPtr, + INTN Len + ) +{ + UNION_PTR LocalPtr; + + // + // initialize + // + SetMem (&RxBufPtr->OpAdds, sizeof RxBufPtr->OpAdds, 0); + + DecodeOptions ( + RxBufPtr, + RxBufPtr->u.Dhcpv4.options + 4, + Len - (sizeof RxBufPtr->u.Dhcpv4 - sizeof RxBufPtr->u.Dhcpv4.options + 4) + ); + + LocalPtr.OpPtr = RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_OPTION_OVERLOAD_IX - 1]; + + if ((LocalPtr.OpPtr) && (LocalPtr.Overload->Overload & OVLD_SRVR_NAME)) { + DecodeOptions (RxBufPtr, RxBufPtr->u.Dhcpv4.sname, sizeof RxBufPtr->u.Dhcpv4.sname); + } + + if (LocalPtr.OpPtr && (LocalPtr.Overload->Overload & OVLD_FILE)) { + DecodeOptions (RxBufPtr, RxBufPtr->u.Dhcpv4.file, sizeof RxBufPtr->u.Dhcpv4.file); + } else if (!RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] && RxBufPtr->u.Dhcpv4.file[0]) { + RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] = (DHCPV4_OP_STRUCT *) (RxBufPtr->u.Dhcpv4.file - sizeof (DHCPV4_OP_HEADER)); + + RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]->Header.Length = (UINT8) AsciiStrLen ((CHAR8 *)RxBufPtr->u.Dhcpv4.file); + } + + LocalPtr.OpPtr = RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_CLASS_IDENTIFIER_IX - 1]; + + if ((LocalPtr.OpPtr) && + LocalPtr.PxeClassStr->Header.Length >= 9 && + !CompareMem (LocalPtr.PxeClassStr->Class, "PXEClient", 9) + ) { + RxBufPtr->OpAdds.Status |= PXE_TYPE; + } +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +VOID +CopyParseRxBuf ( + PXE_BASECODE_DEVICE *Private, + INTN RxBufIndex, + INTN PacketIndex + ) +{ + DHCP_RECEIVE_BUFFER *RxBufPtr; + + RxBufPtr = &((DHCP_RECEIVE_BUFFER *) Private->DhcpPacketBuffer)[PacketIndex]; + + CopyMem ( + &RxBufPtr->u.Dhcpv4, + &RxBuf[RxBufIndex].u.Dhcpv4, + sizeof (RxBuf[RxBufIndex].u.Dhcpv4) + ); + + Parse (RxBufPtr, sizeof RxBufPtr->u.ReceiveBuffer); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +VOID +CopyProxyRxBuf ( + PXE_BASECODE_DEVICE *Private, + INTN RxBufIndex + ) +{ + Private->EfiBc.Mode->ProxyOfferReceived = TRUE; + CopyParseRxBuf (Private, RxBufIndex, PXE_OFFER_INDEX); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +VOID +CopyParse ( + PXE_BASECODE_DEVICE *Private, + EFI_PXE_BASE_CODE_PACKET *PacketPtr, + EFI_PXE_BASE_CODE_PACKET *NewPacketPtr, + INTN Index + ) +{ + DHCP_RECEIVE_BUFFER *DhcpRxBuf; + + DhcpRxBuf = &((DHCP_RECEIVE_BUFFER *) Private->DhcpPacketBuffer)[Index]; + + CopyMem ( + (EFI_PXE_BASE_CODE_PACKET *) &DhcpRxBuf->u.Dhcpv4, + NewPacketPtr, + sizeof (*NewPacketPtr) + ); + + CopyMem (&*PacketPtr, &*NewPacketPtr, sizeof (*NewPacketPtr)); + + Parse (DhcpRxBuf, sizeof DhcpRxBuf->u.ReceiveBuffer); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +BOOLEAN +AckEdit ( + DHCP_RECEIVE_BUFFER *DhcpRxBuf + ) +{ + UNION_PTR LocalPtr; + + LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_MESSAGE_TYPE_IX - 1]; + + // + // check that an ACK + // if a DHCP type, must be DHCPOFFER and must have server id + // + return (BOOLEAN) + ( + (LocalPtr.OpPtr) && + (LocalPtr.MessageType->Type == DHCPACK) && + DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1] + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// if a discover type packet, make sure all required fields are present +// +BOOLEAN +DHCPOfferAckEdit ( + DHCP_RECEIVE_BUFFER *DhcpRxBuf + ) +{ + PXE_OP_SERVER_LIST *BootServerOpPtr; + UNION_PTR LocalPtr; + + if ((DhcpRxBuf->OpAdds.Status & DISCOVER_TYPE) == 0) { + return TRUE; + } + + LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_CONTROL_IX - 1]; + + if (LocalPtr.OpPtr == NULL) { + LocalPtr.OpPtr = (DHCPV4_OP_STRUCT *) &DefaultDisCtl; + DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_CONTROL_IX - 1] = (DHCPV4_OP_STRUCT *) &DefaultDisCtl; + } + // + // make sure all required fields are here + // if mucticast enabled, need multicast address + // + if (!(LocalPtr.DiscoveryControl->ControlBits & DISABLE_MCAST) && + (!DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_MCAST_ADDR_IX - 1] || !IS_MULTICAST (((DHCPV4_OP_STRUCT *) DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_MCAST_ADDR_IX - 1])->Data)) + ) { + return FALSE; + // + // missing required field + // + } + // + // if a list, it better be good + // + BootServerOpPtr = (PXE_OP_SERVER_LIST *) DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_SERVERS_IX - 1]; + + if (BootServerOpPtr != NULL) { + PXE_SERVER_LIST *BootServerListPtr; + INTN ServerListLen; + INTN ServerEntryLen; + + BootServerListPtr = BootServerOpPtr->ServerList; + ServerListLen = BootServerOpPtr->Header.Length; + + do { + EFI_IPv4_ADDRESS *IpListPtr; + INTN IpCnt; + + IpCnt = BootServerListPtr->u.Ipv4List.IpCount; + + ServerEntryLen = sizeof (PXEV4_SERVER_LIST) + 2 + (IpCnt - 1) * sizeof (EFI_IPv4_ADDRESS); + + if (ServerListLen < ServerEntryLen) { + // + // missing required field + // + return FALSE; + } + + IpListPtr = BootServerListPtr->u.Ipv4List.IpList; + + while (IpCnt--) { + if (IS_MULTICAST (IpListPtr)) { + // + // missing required field + // + return FALSE; + } else { + ++IpListPtr; + } + } + + BootServerListPtr = (PXE_SERVER_LIST *) IpListPtr; + } while (ServerListLen -= ServerEntryLen); + } + // + // else there must be a list if use list enabled or multicast and + // broadcast disabled + // + else if ((LocalPtr.DiscoveryControl->ControlBits & USE_ACCEPT_LIST) || + ((LocalPtr.DiscoveryControl->ControlBits & (DISABLE_MCAST | DISABLE_BCAST)) == (DISABLE_MCAST | DISABLE_BCAST)) + ) { + // + // missing required field + // + return FALSE; + } + // + // if not USE_BOOTFILE or no bootfile given, must have menu stuff + // + if (!(LocalPtr.DiscoveryControl->ControlBits & USE_BOOTFILE) || + !DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] + ) { + INTN MenuLth; + + LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_MENU_IX - 1]; + + if (LocalPtr.OpPtr == NULL || !DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_PROMPT_IX - 1]) { + // + // missing required field + // + return FALSE; + } + // + // make sure menu valid + // + MenuLth = LocalPtr.BootMenu->Header.Length; + LocalPtr.BootMenuItem = LocalPtr.BootMenu->MenuItem; + + do { + INTN MenuItemLen; + + MenuItemLen = LocalPtr.BootMenuItem->DataLen; + + if (MenuItemLen == 0) { + // + // missing required field + // + return FALSE; + } + + MenuItemLen += sizeof (*LocalPtr.BootMenuItem) - sizeof (LocalPtr.BootMenuItem->Data); + + MenuLth -= MenuItemLen; + LocalPtr.BytePtr += MenuItemLen; + } while (MenuLth > 0); + + if (MenuLth != 0) { + // + // missing required field + // + return FALSE; + } + } + + if (!DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1]) { + DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1] = (DHCPV4_OP_STRUCT *) &DefaultBootItem; + } + + return TRUE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +BOOLEAN +DHCPAckEdit ( + DHCP_RECEIVE_BUFFER *RxBufPtr + ) +{ + return (BOOLEAN) (DHCPOfferAckEdit (RxBufPtr) ? AckEdit (RxBufPtr) : FALSE); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// get an offer/ack +// +EFI_STATUS +GetOfferAck ( + PXE_BASECODE_DEVICE *Private, + BOOLEAN (*ExtraEdit)(DHCP_RECEIVE_BUFFER *DhcpRxBuf), + UINT16 OpFlags, // for Udp read + EFI_IP_ADDRESS *ServerIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ServerPortPtr, + EFI_IP_ADDRESS *ClientIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ClientPortPtr, + DHCP_RECEIVE_BUFFER *DhcpRxBuf, + EFI_EVENT TimeoutEvent + ) +/*++ +Routine description: + Wait for an OFFER/ACK packet. + +Parameters: + Private := Pointer to PxeBc interface + ExtraEdit := Pointer to extra option checking function + OpFlags := UdpRead() option flags + ServerIpPtr := + ServerPortPtr := + ClientIpPtr := + ClientPortPtr := + DhcpRxBuf := + TimeoutEvent := + +Returns: +--*/ +{ + EFI_IP_ADDRESS ServerIp; + EFI_STATUS StatCode; + INTN RxBufLen; + + for (;;) { + // + // Wait until we get a UDP packet. + // + ZeroMem (&ServerIp, sizeof (EFI_IP_ADDRESS)); + RxBufLen = sizeof RxBuf[0].u.ReceiveBuffer; + + if ((StatCode = UdpRead ( + Private, + OpFlags, + ClientIpPtr, + ClientPortPtr, + ServerIpPtr, + ServerPortPtr, + 0, + 0, + (UINTN *) &RxBufLen, + &DhcpRxBuf->u.Dhcpv4, + TimeoutEvent + )) != EFI_SUCCESS) { + if (StatCode == EFI_TIMEOUT) { + StatCode = EFI_NO_RESPONSE; + } + + break; + } + // + // got a packet - see if a good offer + // + if (DhcpRxBuf->u.Dhcpv4.op != BOOTP_REPLY) { + continue; + } + + if (DhcpRxBuf->u.Dhcpv4.xid != DHCPV4_TRANSMIT_BUFFER.xid) { + continue; + } + + if (*(UINT32 *) DHCPV4_TRANSMIT_BUFFER.options != * (UINT32 *) DhcpRxBuf->u.Dhcpv4.options) { + continue; + } + + if (*(UINT8 *) &DhcpRxBuf->u.Dhcpv4.yiaddr > 223) { + continue; + } + + if (CompareMem ( + DhcpRxBuf->u.Dhcpv4.chaddr, + DHCPV4_TRANSMIT_BUFFER.chaddr, + sizeof DhcpRxBuf->u.Dhcpv4.chaddr + )) { + // + // no good + // + continue; + } + + Parse (DhcpRxBuf, RxBufLen); + + if (!(*ExtraEdit) (DhcpRxBuf)) { + continue; + } + // + // Good DHCP packet. + // + StatCode = EFI_SUCCESS; + break; + } + + return StatCode; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// get DHCPOFFER's +// +EFI_STATUS +GetOffers ( + PXE_BASECODE_DEVICE *Private + ) +{ + EFI_IP_ADDRESS ClientIp; + EFI_IP_ADDRESS ServerIp; + EFI_STATUS StatCode; + EFI_EVENT TimeoutEvent; + INTN NumOffers; + INTN Index; + + // + // + // + ZeroMem (&ServerIp, sizeof (EFI_IP_ADDRESS)); + NumOffers = 0; + + for (Index = 0; Index < (sizeof Private->ServerCount) / sizeof Private->ServerCount[0]; ++Index) { + Private->ServerCount[Index] = 0; + Private->GotProxy[Index] = 0; + } + + Private->GotBootp = 0; + // + // these we throw away + // + Private->GotProxy[DHCP_ONLY_IX] = 1; + StatCode = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); + + if (EFI_ERROR (StatCode)) { + return StatCode; + } + + StatCode = gBS->SetTimer ( + TimeoutEvent, + TimerRelative, + Private->Timeout * 10000000 + 1000000 + ); + + if (EFI_ERROR (StatCode)) { + gBS->CloseEvent (TimeoutEvent); + return StatCode; + } + // + // get offers + // + for (;;) { + DHCP_RECEIVE_BUFFER *DhcpRxBuf; + UNION_PTR LocalPtr; + + DhcpRxBuf = &RxBuf[NumOffers]; + + if (( + StatCode = GetOfferAck ( + Private, + DHCPOfferAckEdit, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP | + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT, + &ServerIp, + &DhcpServerPort, + &ClientIp, + &DHCPClientPort, + DhcpRxBuf, + TimeoutEvent + ) +) != EFI_SUCCESS + ) { + break; + } + + LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_MESSAGE_TYPE_IX - 1]; + + // + // check type of offer + // + if (LocalPtr.OpPtr == NULL) { + // + // bootp - we only need one and make sure has bootfile + // + if (Private->GotBootp || !DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]) { + continue; + } + + Private->GotBootp = (UINT8) (NumOffers + 1); + } + // + // if a DHCP type, must be DHCPOFFER and must have server id + // + else if (LocalPtr.MessageType->Type != DHCPOFFER || !DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1]) { + continue; + } else { + INTN TypeIx; + + // + // get type - PXE10, WfM11a, or BINL + // + if (DhcpRxBuf->OpAdds.Status & DISCOVER_TYPE) { + TypeIx = PXE10_IX; + } else if (DhcpRxBuf->OpAdds.Status & WfM11a_TYPE) { + // + // WfM - make sure it has a bootfile + // + if (!DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]) { + continue; + } + + TypeIx = WfM11a_IX; + } else { + TypeIx = (DhcpRxBuf->OpAdds.Status & PXE_TYPE) ? BINL_IX : DHCP_ONLY_IX; + } + // + // check DHCP or proxy + // + if (DhcpRxBuf->u.Dhcpv4.yiaddr == 0) { + // + // proxy - only need one of each type if not BINL + // and must have at least PXE_TYPE + // + if (TypeIx == BINL_IX) { + Private->BinlProxies[Private->GotProxy[BINL_IX]++] = (UINT8) NumOffers; + } else if (Private->GotProxy[TypeIx]) { + continue; + } else { + Private->GotProxy[TypeIx] = (UINT8) (NumOffers + 1); + } + } else { + Private->OfferCount[TypeIx][Private->ServerCount[TypeIx]++] = (UINT8) NumOffers; + } + } + + if (++NumOffers == MAX_OFFERS) { + break; + } + } + + gBS->CloseEvent (TimeoutEvent); + Private->NumOffersReceived = NumOffers; + + return (Private->NumOffersReceived) ? EFI_SUCCESS : EFI_NO_RESPONSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// send DHCPDECLINE +// +STATIC +VOID +DeclineOffer ( + PXE_BASECODE_DEVICE *Private + ) +{ + EFI_PXE_BASE_CODE_MODE *PxebcMode; + UINT16 SaveSecs; + + PxebcMode = Private->EfiBc.Mode; + SaveSecs = DHCPV4_TRANSMIT_BUFFER.secs; + + DHCPV4_TRANSMIT_BUFFER.secs = 0; + DHCPV4_TRANSMIT_BUFFER.flags = 0; + SetMem ( + DHCPV4_TRANSMIT_BUFFER.options + sizeof (struct opdeclinestr), + sizeof (DHCPOpStart) - sizeof (struct opdeclinestr), + OP_PAD + ); + DHCPDECLINEoptions.DhcpMessageType.Type = DHCPDECLINE; + CopyMem (&DHCPDECLINEoptions.OpDeclineEnd, &DHCP_REQ_OPTIONS, sizeof (struct requestopendstr)); + // DHCPDECLINEoptions.OpDeclineEnd = DHCP_REQ_OPTIONS; + + { + EFI_IP_ADDRESS TmpIp; + + CopyMem (&TmpIp, &DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip, sizeof TmpIp); + + DoUdpWrite ( + Private, + &TmpIp, + &DhcpServerPort, + &PxebcMode->StationIp, + &DHCPClientPort + ); + } + + InitDhcpv4TxBuf (Private); + DHCPV4_TRANSMIT_BUFFER.secs = SaveSecs; + Private->GoodStationIp = FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// send DHCPRELEASE +// +STATIC +BOOLEAN +Release ( + PXE_BASECODE_DEVICE *Private + ) +{ + EFI_PXE_BASE_CODE_MODE *PxebcMode; + UINT16 SaveSecs; + DHCPV4_OP_SERVER_IP *Point; + + PxebcMode = Private->EfiBc.Mode; + SaveSecs = DHCPV4_TRANSMIT_BUFFER.secs; + DHCPV4_TRANSMIT_BUFFER.secs = 0; + + SetMem ( + DHCPV4_TRANSMIT_BUFFER.options + sizeof (struct opreleasestr), + sizeof (DHCPOpStart) - sizeof (struct opreleasestr), + OP_PAD + ); + + DHCPRELEASEoptions.DhcpMessageType.Type = DHCPRELEASE; + Point = (DHCPV4_OP_SERVER_IP *) DHCPV4_ACK_BUFFER.OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1]; + CopyMem ( + &DHCPRELEASEoptions.DhcServerIpPtr, + &Point, + sizeof DHCPRELEASEoptions.DhcServerIpPtr + ); + + DHCPRELEASEoptions.End[0] = OP_END; + + { + EFI_IP_ADDRESS TmpIp; + + CopyMem (&TmpIp, &DHCPRELEASEoptions.DhcServerIpPtr.Ip, sizeof TmpIp); + + DoUdpWrite ( + Private, + &TmpIp, + &DhcpServerPort, + &PxebcMode->StationIp, + &DHCPClientPort + ); + } + + InitDhcpv4TxBuf (Private); + + DHCPV4_TRANSMIT_BUFFER.secs = SaveSecs; + Private->GoodStationIp = FALSE; + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +BOOLEAN +GetBINLAck ( + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS *ServerIpPtr + ) +{ + DHCP_RECEIVE_BUFFER *DhcpRxBuf; + EFI_STATUS StatCode; + EFI_EVENT TimeoutEvent; + + // + // + // + StatCode = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); + + if (EFI_ERROR (StatCode)) { + return FALSE; + } + + StatCode = gBS->SetTimer ( + TimeoutEvent, + TimerRelative, + Private->Timeout * 10000000 + 1000000 + ); + + if (EFI_ERROR (StatCode)) { + gBS->CloseEvent (TimeoutEvent); + return FALSE; + } + // + // + // + DhcpRxBuf = &PXE_BINL_BUFFER; + + for (;;) { + EFI_PXE_BASE_CODE_UDP_PORT BINLSrvPort; + + BINLSrvPort = 0; + + if (GetOfferAck ( + Private, + AckEdit, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT, + ServerIpPtr, + &BINLSrvPort, + &Private->EfiBc.Mode->StationIp, + &PSEUDO_DHCP_CLIENT_PORT, + DhcpRxBuf, + TimeoutEvent + ) != EFI_SUCCESS) { + break; + } + // + // make sure from whom we wanted + // + if (!DhcpRxBuf->u.Dhcpv4.yiaddr && !CompareMem ( + &ServerIpPtr->v4, + &((DHCPV4_OP_SERVER_IP *) DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip, + sizeof (ServerIpPtr->v4) + )) { + gBS->CloseEvent (TimeoutEvent); + // + // got an ACK from server + // + return TRUE; + } + } + + gBS->CloseEvent (TimeoutEvent); + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// make sure we can get BINL +// send DHCPREQUEST to PXE server +// +STATIC +BOOLEAN +TryBINL ( + PXE_BASECODE_DEVICE *Private, + INTN OfferIx + ) +{ + DHCP_RECEIVE_BUFFER *DhcpRxBuf; + EFI_IP_ADDRESS ServerIp; + UINT16 SaveSecs; + INTN Index; + + DhcpRxBuf = &RxBuf[OfferIx]; + + // + // send DHCP request + // if fail return false + // + CopyMem ( + ((EFI_IPv4_ADDRESS *) &ServerIp), + &((DHCPV4_OP_SERVER_IP *) DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip, + sizeof (EFI_IPv4_ADDRESS) + ); + + // + // client IP address - filled in by client if it knows it + // + CopyMem ( + ((EFI_IPv4_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr), + &DHCP_REQ_OPTIONS.OpReqIP.Ip, + sizeof (EFI_IPv4_ADDRESS) + ); + + SetMem (&DHCP_REQ_OPTIONS, sizeof DHCP_REQ_OPTIONS, OP_PAD); + DHCPV4_TRANSMIT_BUFFER.flags = 0; + DHCPV4_OPTIONS_BUFFER.End[0] = OP_END; + AddRouters (Private, DhcpRxBuf); + SaveSecs = DHCPV4_TRANSMIT_BUFFER.secs; + + for (Index = 0; Index < 3; Private->TotalSeconds = (UINT16) (Private->TotalSeconds + Private->Timeout), ++Index) { + DHCPV4_TRANSMIT_BUFFER.secs = HTONS (Private->TotalSeconds); + + // + // unicast DHCPREQUEST to PXE server + // + if (DoUdpWrite ( + Private, + &ServerIp, + &PseudoDhcpServerPort, + (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr, + &PSEUDO_DHCP_CLIENT_PORT + ) != EFI_SUCCESS) { + break; + } + + if (!GetBINLAck (Private, &ServerIp)) { + continue; + } + // + // early exit failures + // make sure a good ACK + // + if (!DHCPOfferAckEdit (&PXE_BINL_BUFFER) || ( + !(PXE_BINL_BUFFER.OpAdds.Status & DISCOVER_TYPE) && !PXE_BINL_BUFFER.OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] + ) + ) { + break; + } + + Private->EfiBc.Mode->ProxyOfferReceived = TRUE; + return TRUE; + } + // + // failed - reset seconds field, etc. + // + Private->EfiBc.Mode->RouteTableEntries = 0; + // + // reset + // + DHCPV4_TRANSMIT_BUFFER.secs = SaveSecs; + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +BOOLEAN +TryFinishBINL ( + PXE_BASECODE_DEVICE *Private, + INTN OfferIx + ) +{ + if (TryBINL (Private, OfferIx)) { + return TRUE; + } + + return Release (Private); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +BOOLEAN +TryFinishProxyBINL ( + PXE_BASECODE_DEVICE *Private + ) +{ + INTN Index; + + for (Index = 0; Index < Private->GotProxy[BINL_IX]; ++Index) { + if (TryBINL (Private, Private->BinlProxies[Index])) { + return TRUE; + } + } + + return Release (Private); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// try to finish DORA - send DHCP request, wait for ACK, check with ARP +// +STATIC +BOOLEAN +TryFinishDORA ( + PXE_BASECODE_DEVICE *Private, + INTN OfferIx + ) +{ + DHCP_RECEIVE_BUFFER *DhcpRxBuf; + EFI_IP_ADDRESS ClientIp; + EFI_IP_ADDRESS ServerIp; + EFI_STATUS StatCode; + UNION_PTR LocalPtr; + EFI_EVENT TimeoutEvent; + + // + // send DHCP request + // if fail return false + // + DhcpRxBuf = &DHCPV4_ACK_BUFFER; + DHCPV4_OPTIONS_BUFFER.DhcpMessageType.Type = DHCPREQUEST; + CopyMem (&DHCP_REQ_OPTIONS, &RequestOpEndStr, sizeof (RequestOpEndStr)); +// DHCP_REQ_OPTIONS = RequestOpEndStr; + DHCP_REQ_OPTIONS.OpReqIP.Ip = *(EFI_IPv4_ADDRESS *) &RxBuf[OfferIx].u.Dhcpv4.yiaddr; + + CopyMem ( + &DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip, + &((DHCPV4_OP_SERVER_IP *) RxBuf[OfferIx].OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip, + sizeof DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip + ); + + CopyMem ( + Private->EfiBc.Mode->SubnetMask.Addr, + &DefaultSubnetMask, + 4 + ); + + // + // broadcast DHCPREQUEST + // + if (DoUdpWrite ( + Private, + &BroadcastIP, + &DhcpServerPort, + (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr, + &DHCPClientPort + ) != EFI_SUCCESS) { + return FALSE; + } + // + // + // + StatCode = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); + + if (EFI_ERROR (StatCode)) { + return FALSE; + } + + StatCode = gBS->SetTimer ( + TimeoutEvent, + TimerPeriodic, + Private->Timeout * 10000000 + 1000000 + ); + + if (EFI_ERROR (StatCode)) { + gBS->CloseEvent (TimeoutEvent); + return FALSE; + } + // + // wait for ACK + // + for (;;) { + if (GetOfferAck ( + Private, + DHCPAckEdit, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP, + &ServerIp, + &DhcpServerPort, + &ClientIp, + &DHCPClientPort, + DhcpRxBuf, + TimeoutEvent + ) != EFI_SUCCESS) { + break; + } + // + // check type of response - need DHCPACK + // + if (CompareMem ( + &DHCP_REQ_OPTIONS.OpReqIP.Ip, + &DhcpRxBuf->u.Dhcpv4.yiaddr, + sizeof (EFI_IPv4_ADDRESS) + ) || CompareMem ( + &DHCP_REQ_OPTIONS.DhcServerIpPtr.Ip, + &((DHCPV4_OP_SERVER_IP *) DhcpRxBuf->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip, + sizeof (EFI_IPv4_ADDRESS) + )) { + continue; + } + // + // got ACK + // check with ARP that IP unused - good return true + // + if (!SetStationIP (Private)) { + // + // fail - send DHCPDECLINE and return false + // + DeclineOffer (Private); + break; + } + + LocalPtr.OpPtr = DHCPV4_ACK_BUFFER.OpAdds.PktOptAdds[OP_SUBNET_MASK_IX - 1]; + + if (LocalPtr.OpPtr != NULL) { + CopyMem ( + (EFI_IPv4_ADDRESS *) &Private->EfiBc.Mode->SubnetMask, + &LocalPtr.SubnetMaskStr->Ip, + sizeof (EFI_IPv4_ADDRESS) + ); + } + + AddRouters (Private, DhcpRxBuf); + gBS->CloseEvent (TimeoutEvent); + return TRUE; + } + + gBS->CloseEvent (TimeoutEvent); + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// try a DHCP server of appropriate type +// +STATIC +BOOLEAN +TryDHCPFinishDORA ( + PXE_BASECODE_DEVICE *Private, + INTN TypeIx + ) +{ + INTN Index; + + // + // go through the DHCP servers of the requested type + // + for (Index = 0; Index < Private->ServerCount[TypeIx]; ++Index) { + if (TryFinishDORA (Private, Index = Private->OfferCount[TypeIx][Index])) { + if (TypeIx == BINL_IX && !TryFinishBINL (Private, Index)) { + continue; + } + + return TRUE; + } + } + + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// try a DHCP only server and a proxy of appropriate type +// +STATIC +BOOLEAN +TryProxyFinishDORA ( + PXE_BASECODE_DEVICE *Private, + INTN TypeIx + ) +{ + INTN Index; + + if (!Private->GotProxy[TypeIx]) { + // + // no proxies of the type wanted + // + return FALSE; + } + // + // go through the DHCP only servers + // + for (Index = 0; Index < Private->ServerCount[DHCP_ONLY_IX]; ++Index) { + if (TryFinishDORA (Private, Private->OfferCount[DHCP_ONLY_IX][Index])) { + if (TypeIx != BINL_IX) { + CopyProxyRxBuf (Private, Private->GotProxy[TypeIx] - 1); + } else if (!TryFinishProxyBINL (Private)) { + // + // if didn't work with this DHCP, won't work with any + // + return FALSE; + } + + return TRUE; + } + } + + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// getting to the bottom of the barrel +// +STATIC +BOOLEAN +TryAnyWithBootfileFinishDORA ( + PXE_BASECODE_DEVICE *Private + ) +{ + // + // try a DHCP only server who has a bootfile + // + UNION_PTR LocalPtr; + INTN Index; + + for (Index = 0; Index < Private->ServerCount[DHCP_ONLY_IX]; ++Index) { + INTN offer; + + offer = Private->OfferCount[DHCP_ONLY_IX][Index]; + + if (RxBuf[offer].OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] && TryFinishDORA (Private, offer)) { + return TRUE; + } + } + // + // really at bottom - see if be have any bootps + // + if (!Private->GotBootp) { + return FALSE; + } + + DHCP_REQ_OPTIONS.OpReqIP.Ip = *(EFI_IPv4_ADDRESS *) &RxBuf[Private->GotBootp - 1].u.Dhcpv4.yiaddr; + + if (!SetStationIP (Private)) { + return FALSE; + } + // + // treat BOOTP response as DHCP ACK packet + // + CopyParseRxBuf (Private, Private->GotBootp - 1, DHCPV4_ACK_INDEX); + + LocalPtr.OpPtr = RxBuf[Private->GotBootp - 1].OpAdds.PktOptAdds[OP_SUBNET_MASK_IX - 1]; + + if (LocalPtr.OpPtr != NULL) { + *(EFI_IPv4_ADDRESS *) &Private->EfiBc.Mode->SubnetMask = LocalPtr.SubnetMaskStr->Ip; + } + + return TRUE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* DoDhcpDora() + */ +STATIC +EFI_STATUS +DoDhcpDora ( + PXE_BASECODE_DEVICE *Private, + BOOLEAN SortOffers + ) +{ + EFI_PXE_BASE_CODE_IP_FILTER Filter; + EFI_STATUS StatCode; + INTN NumOffers; + + Filter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP | EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST; + + Filter.IpCnt = 0; + Filter.reserved = 0; + + // + // set filter unicast or broadcast + // + if ((StatCode = IpFilter (Private, &Filter)) != EFI_SUCCESS) { + return StatCode; + } + // + // seed random number with hardware address + // + SeedRandom (Private, *(UINT16 *) &Private->SimpleNetwork->Mode->CurrentAddress); + + for (Private->Timeout = 1; + Private->Timeout < 17; + Private->TotalSeconds = (UINT16) (Private->TotalSeconds + Private->Timeout), Private->Timeout <<= 1 + ) { + INTN Index; + + InitDhcpv4TxBuf (Private); + DHCPV4_TRANSMIT_BUFFER.xid = Random (Private); + DHCPV4_TRANSMIT_BUFFER.secs = HTONS (Private->TotalSeconds); + + // + // broadcast DHCPDISCOVER + // + StatCode = DoUdpWrite ( + Private, + &BroadcastIP, + &DhcpServerPort, + (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr, + &DHCPClientPort + ); + + if (StatCode != EFI_SUCCESS) { + return StatCode; + } + + CopyMem ( + &Private->EfiBc.Mode->DhcpDiscover, + (EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_TRANSMIT_BUFFER, + sizeof (EFI_PXE_BASE_CODE_PACKET) + ); + + // + // get DHCPOFFER's + // + if ((StatCode = GetOffers (Private)) != EFI_SUCCESS) { + if (StatCode != EFI_NO_RESPONSE) { + return StatCode; + } + + continue; + } + // + // select offer and reply DHCPREQUEST + // + if (SortOffers) { + if (TryDHCPFinishDORA(Private, PXE10_IX) || // try DHCP with PXE10 + TryDHCPFinishDORA(Private, WfM11a_IX) || // no - try with WfM + TryProxyFinishDORA(Private, PXE10_IX) || // no - try DHCP only and proxy with PXE10 + TryProxyFinishDORA(Private, WfM11a_IX) || // no - try DHCP only and proxy with WfM + TryDHCPFinishDORA(Private, BINL_IX) || // no - try with WfM + TryProxyFinishDORA(Private, BINL_IX) || // no - try DHCP only and proxy with PXE10 + TryAnyWithBootfileFinishDORA(Private)) + { + return EFI_SUCCESS; + } + + continue; + } + // + // FIFO order + // + NumOffers = Private->NumOffersReceived; + + for (Index = 0; Index < NumOffers; ++Index) { + // + // ignore proxies + // + if (!RxBuf[Index].u.Dhcpv4.yiaddr) { + continue; + } + // + // check if a bootp server + // + if (!RxBuf[Index].OpAdds.PktOptAdds[OP_DHCP_MESSAGE_TYPE_IX - 1]) { + // + // it is - just check ARP + // + if (!SetStationIP (Private)) { + continue; + } + } + // + // else check if a DHCP only server + // + else if (!(RxBuf[Index].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE | PXE_TYPE))) { + // + // it is a normal DHCP offer (without any PXE options), just finish the D.O.R.A by sending DHCP request. + // + if (!TryFinishDORA (Private, Index)) { + continue; + } + } else if (TryFinishDORA (Private, Index)) { + if (!(RxBuf[Index].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE)) && !TryFinishBINL (Private, Index)) { + continue; + } + } + + DEBUG ((EFI_D_WARN, "\nDoDhcpDora() Got packets. ")); + return EFI_SUCCESS; + } + // + // now look for DHCP onlys and a Proxy + // + for (Index = 0; Index < NumOffers; ++Index) { + INT8 Index2; + + // + // ignore proxies, bootps, non DHCP onlys, and bootable DHCPS + // + if (!RxBuf[Index].u.Dhcpv4.yiaddr || + !RxBuf[Index].OpAdds.PktOptAdds[OP_DHCP_MESSAGE_TYPE_IX - 1] || + RxBuf[Index].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE | PXE_TYPE) || + RxBuf[Index].OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] + ) { + continue; + } + // + // found non bootable DHCP only - try to find a proxy + // + for (Index2 = 0; Index2 < NumOffers; ++Index2) { + if (!RxBuf[Index2].u.Dhcpv4.yiaddr) { + if (!TryFinishDORA (Private, Index)) { + // + // DHCP no ACK + // + break; + } + + if (RxBuf[Index2].OpAdds.Status & (DISCOVER_TYPE | WfM11a_TYPE)) { + CopyProxyRxBuf (Private, Index2); + } else if (!TryFinishBINL (Private, Index2)) { + continue; + } + + DEBUG ((EFI_D_WARN, "\nDoDhcpDora() Got packets. ")); + return EFI_SUCCESS; + } + } + } + } + + return EFI_NO_RESPONSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// determine if the server ip is in the ip list +// +BOOLEAN +InServerList ( + EFI_IP_ADDRESS *ServerIpPtr, + PXE_SERVER_LISTS *ServerListPtr + ) +{ + UINTN Index; + + if (!ServerListPtr || !ServerListPtr->Ipv4List.IpCount) { + return TRUE; + } + + for (Index = 0; Index < ServerListPtr->Ipv4List.IpCount; ++Index) { + if (!CompareMem ( + ServerIpPtr, + &ServerListPtr->Ipv4List.IpList[Index], + sizeof (EFI_IPv4_ADDRESS) + )) { + return TRUE; + } + } + + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +BOOLEAN +ExtractBootServerList ( + UINT16 Type, + DHCPV4_OP_STRUCT *ptr, + PXE_SERVER_LISTS **ServerListPtr + ) +{ + UNION_PTR LocalPtr; + INTN ServerListLen; + + LocalPtr.OpPtr = ptr; + ServerListLen = LocalPtr.BootServersStr->Header.Length; + + // + // find type + // + LocalPtr.BootServerList = LocalPtr.BootServersStr->ServerList; + + while (ServerListLen) { + INTN ServerEntryLen; + + ServerEntryLen = sizeof (PXEV4_SERVER_LIST) + 2 + (LocalPtr.BootServerList->u.Ipv4List.IpCount - 1) * + sizeof (EFI_IPv4_ADDRESS); + + if (NTOHS (LocalPtr.BootServerList->Type) == Type) { + *ServerListPtr = &LocalPtr.BootServerList->u; + return TRUE; + } + + (LocalPtr.BytePtr) += ServerEntryLen; + ServerListLen -= ServerEntryLen; + } + + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +FreeMem ( + PXE_BASECODE_DEVICE *Private + ) +{ + if (Private->TransmitBuffer != NULL) { + gBS->FreePool (Private->TransmitBuffer); + Private->TransmitBuffer = NULL; + } + + if (Private->ReceiveBuffers != NULL) { + gBS->FreePool (Private->ReceiveBuffers); + Private->ReceiveBuffers = NULL; + } +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +BOOLEAN +GetMem ( + PXE_BASECODE_DEVICE *Private + ) +{ + EFI_STATUS Status; + + if (Private->DhcpPacketBuffer == NULL) { + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (DHCP_RECEIVE_BUFFER) * (PXE_BIS_INDEX + 1), + &Private->DhcpPacketBuffer + ); + + if (EFI_ERROR (Status) || Private->DhcpPacketBuffer == NULL) { + Private->DhcpPacketBuffer = NULL; + FreeMem (Private); + return FALSE; + } + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_PXE_BASE_CODE_PACKET), + &Private->TransmitBuffer + ); + + if (EFI_ERROR (Status) || Private->TransmitBuffer == NULL) { + gBS->FreePool (Private->DhcpPacketBuffer); + Private->DhcpPacketBuffer = NULL; + Private->TransmitBuffer = NULL; + FreeMem (Private); + return FALSE; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (DHCP_RECEIVE_BUFFER) * (MAX_OFFERS), + &Private->ReceiveBuffers + ); + + if (EFI_ERROR (Status) || Private->ReceiveBuffers == NULL) { + gBS->FreePool (Private->TransmitBuffer); + gBS->FreePool (Private->DhcpPacketBuffer); + Private->DhcpPacketBuffer = NULL; + Private->TransmitBuffer = NULL; + Private->ReceiveBuffers = NULL; + FreeMem (Private); + return FALSE; + } + + return TRUE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +BcDhcp ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN SortOffers + ) +/*++ +Routine description: + standard DHCP Discover/Offer/Request/Ack session + broadcast DHCPDISCOVER + receive DHCPOFFER's + broadcast DHCPREQUEST + receive DHCPACK + check (ARP) good IP + +Parameters: + This := Pointer to PxeBc interface + SortOffers := + +Returns: +--*/ +{ + EFI_PXE_BASE_CODE_IP_FILTER Filter; + EFI_PXE_BASE_CODE_MODE *PxebcMode; + PXE_BASECODE_DEVICE *Private; + EFI_STATUS StatCode; + + // + // Lock the instance data and make sure started + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + if (This->Mode == NULL || !This->Mode->Started) { + DEBUG ((EFI_D_ERROR, "BC was not started.")); + EfiReleaseLock (&Private->Lock); + return EFI_NOT_STARTED; + } + + Filter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP; + Filter.IpCnt = 0; + Filter.reserved = 0; + + DEBUG ((EFI_D_INFO, "\nBcDhcp() Enter. ")); + + PxebcMode = Private->EfiBc.Mode; + + if (!GetMem (Private)) { + DEBUG ((EFI_D_ERROR, "\nBcDhcp() GetMem() failed.\n")); + EfiReleaseLock (&Private->Lock); + return EFI_OUT_OF_RESOURCES; + } + + PxebcMode->DhcpDiscoverValid = FALSE; + PxebcMode->DhcpAckReceived = FALSE; + PxebcMode->ProxyOfferReceived = FALSE; + + Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DHCP; + + // + // Issue BC command + // + if (Private->TotalSeconds == 0) { + // + // put in seconds field of DHCP send packets + // + Private->TotalSeconds = 4; + } + + if ((StatCode = DoDhcpDora (Private, SortOffers)) == EFI_SUCCESS) { + // + // success - copy packets + // + PxebcMode->DhcpDiscoverValid = PxebcMode->DhcpAckReceived = TRUE; + + CopyMem ( + &PxebcMode->DhcpAck, + (EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_ACK_PACKET, + sizeof (EFI_PXE_BASE_CODE_PACKET) + ); + + if (PxebcMode->ProxyOfferReceived) { + CopyMem ( + &PxebcMode->ProxyOffer, + (EFI_PXE_BASE_CODE_PACKET *) &PXE_OFFER_PACKET, + sizeof (EFI_PXE_BASE_CODE_PACKET) + ); + } + } + // + // set filter back to unicast + // + IpFilter (Private, &Filter); + + FreeMem (Private); + + // + // Unlock the instance data + // + DEBUG ((EFI_D_WARN, "\nBcDhcp() Exit = %xh ", StatCode)); + + EfiReleaseLock (&Private->Lock); + return StatCode; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +BOOLEAN +VerifyCredentialOption ( + UINT8 *tx, + UINT8 *rx + ) +{ + UINTN n; + + // + // Fail verification if either pointer is NULL. + // + if (tx == NULL || rx == NULL) { + return FALSE; + } + // + // Fail verification if tx[0] is not a credential type option + // or if the length is zero or not a multiple of four. + // + if (tx[0] != VEND_PXE_CREDENTIAL_TYPES || tx[1] == 0 || tx[1] % 4 != 0) { + return FALSE; + } + // + // Fail verification if rx[0] is not a credential type option + // or if the length is not equal to four. + // + if (rx[0] != VEND_PXE_CREDENTIAL_TYPES || rx[1] != 4) { + return FALSE; + } + // + // Look through transmitted credential types for a copy + // of the received credential type. + // + for (n = 0; n < tx[1]; n += 4) { + if (!CompareMem (&tx[n + 2], &rx[2], 4)) { + return TRUE; + } + } + + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +DoDiscover ( + PXE_BASECODE_DEVICE *Private, + UINT16 OpFlags, + IN UINT16 Type, + IN UINT16 *LayerPtr, + IN BOOLEAN UseBis, + EFI_IP_ADDRESS *DestPtr, + PXE_SERVER_LISTS *ServerListPtr + ) +/*++ +Routine description: + This function tries to complete the PXE Bootserver and/or boot image + discovery sequence. When this command completes successfully, the + PXEdiscover and PXEreply fields in the BC instance data structure are + updated. If the Info pointer is set to NULL, the discovery information + in the DHCPack and ProxyOffer packets must be valid and will be used. + If Info is not set to NULL, the discovery methods in the Info field + must be set and will be used. When discovering any layer number other + than zero (the credential flag does not count), only unicast discovery + is used. + +Parameters: + Private := Pointer to PxeBc interface + OpFlags := + Type := + LayerPtr := + UseBis := + DestPtr := + ServerListPtr := + +Returns: +--*/ +{ + EFI_PXE_BASE_CODE_UDP_PORT ClientPort; + EFI_PXE_BASE_CODE_UDP_PORT ServerPort; + EFI_PXE_BASE_CODE_MODE *PxebcMode; + EFI_STATUS StatCode; + EFI_EVENT TimeoutEvent; + UINT8 OpLen; + + PxebcMode = Private->EfiBc.Mode; + + if (DestPtr->Addr[0] == 0) { + DEBUG ((EFI_D_WARN, "\nDoDiscover() !DestPtr->Addr[0]")); + return EFI_INVALID_PARAMETER; + } + // + // seed random number with hardware address + // + SeedRandom (Private, *(UINT16 *) &Private->SimpleNetwork->Mode->CurrentAddress); + + if (DestPtr->Addr[0] == BroadcastIP.Addr[0]) { + ClientPort = DHCPClientPort; + ServerPort = DhcpServerPort; + } else { + ClientPort = PSEUDO_DHCP_CLIENT_PORT; + ServerPort = PseudoDhcpServerPort; + } + + if (UseBis) { + *LayerPtr |= PXE_BOOT_LAYER_CREDENTIAL_FLAG; + } else { + *LayerPtr &= PXE_BOOT_LAYER_MASK; + } + + for (Private->Timeout = 1; + Private->Timeout < 5; + Private->TotalSeconds = (UINT16) (Private->TotalSeconds + Private->Timeout), ++Private->Timeout + ) { + InitDhcpv4TxBuf (Private); + // + // initialize DHCP message structure + // + DHCPV4_TRANSMIT_BUFFER.xid = Random (Private); + DHCPV4_TRANSMIT_BUFFER.secs = HTONS (Private->TotalSeconds); + CopyMem ( + &DHCPV4_TRANSMIT_BUFFER.ciaddr, + &PxebcMode->StationIp, + sizeof DHCPV4_TRANSMIT_BUFFER.ciaddr + ); + + DHCPV4_OPTIONS_BUFFER.DhcpMessageType.Type = DHCPREQUEST; + DISCOVERoptions.Header.OpCode = OP_VENDOR_SPECIFIC; + DISCOVERoptions.BootItem.Header.OpCode = VEND_PXE_BOOT_ITEM; + DISCOVERoptions.BootItem.Header.Length = DHCPV4_OPTION_LENGTH (PXE_OP_BOOT_ITEM); + DISCOVERoptions.BootItem.Type = HTONS (Type); + DISCOVERoptions.BootItem.Layer = HTONS (*LayerPtr); + + if (UseBis) { + EFI_BIS_PROTOCOL *BisPtr; + BIS_APPLICATION_HANDLE BisAppHandle; + EFI_BIS_DATA *BisDataSigInfo; + EFI_BIS_SIGNATURE_INFO *BisSigInfo; + UINTN Index; + UINTN Index2; + + BisPtr = PxebcBisStart ( + Private, + &BisAppHandle, + &BisDataSigInfo + ); + + if (BisPtr == NULL) { + // + // %%TBD - In order to get here, BIS must have + // been present when PXEBC.Start() was called. + // BIS had to be shutdown/removed/damaged + // before PXEBC.Discover() was called. + // Do we need to document a specific error + // for this case? + // + return EFI_OUT_OF_RESOURCES; + } + // + // Compute number of credential types. + // + Index2 = BisDataSigInfo->Length / sizeof (EFI_BIS_SIGNATURE_INFO); + + DISCREDoptions.Header.OpCode = VEND_PXE_CREDENTIAL_TYPES; + + DISCREDoptions.Header.Length = (UINT8) (Index2 * sizeof (PXE_CREDENTIAL)); + + OpLen = (UINT8) (DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS) + sizeof (DHCPV4_OP_HEADER) + DISCREDoptions.Header.Length); + + BisSigInfo = (EFI_BIS_SIGNATURE_INFO *) BisDataSigInfo->Data; + + for (Index = 0; Index < Index2; ++Index) { + UINT32 x; + + CopyMem (&x, &BisSigInfo[Index], sizeof x); + x = HTONL (x); + CopyMem (&DISCREDoptions.Credentials[Index], &x, sizeof x); + } + + PxebcBisStop (BisPtr, BisAppHandle, BisDataSigInfo); + } else { + OpLen = DHCPV4_OPTION_LENGTH (PXE_DISCOVER_OPTIONS); + } + + DISCOVERoptions.Header.Length = OpLen; + + ((UINT8 *) &DISCOVERoptions)[sizeof (DHCPV4_OP_HEADER) + OpLen - 1] = OP_END; + ((UINT8 *) &DISCOVERoptions)[sizeof (DHCPV4_OP_HEADER) + OpLen] = OP_END; + + StatCode = DoUdpWrite ( + Private, + DestPtr, + &ServerPort, + (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr, + &ClientPort + ); + + if (StatCode != EFI_SUCCESS) { + return StatCode; + } + // + // + // + StatCode = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); + + if (EFI_ERROR (StatCode)) { + return StatCode; + } + + StatCode = gBS->SetTimer ( + TimeoutEvent, + TimerRelative, + Private->Timeout * 10000000 + 1000000 + ); + + if (EFI_ERROR (StatCode)) { + gBS->CloseEvent (TimeoutEvent); + return StatCode; + } + // + // wait for ACK + // + for (;;) { + DHCP_RECEIVE_BUFFER *RxBufPtr; + UINT16 TmpType; + UINT16 TmpLayer; + + RxBufPtr = UseBis ? &PXE_BIS_BUFFER : &PXE_ACK_BUFFER; + ZeroMem (&Private->ServerIp, sizeof (EFI_IP_ADDRESS)); + + if (GetOfferAck ( + Private, + AckEdit, + OpFlags, + (EFI_IP_ADDRESS *) &Private->ServerIp, + 0, + (EFI_IP_ADDRESS *) &DHCPV4_TRANSMIT_BUFFER.ciaddr, + &ClientPort, + RxBufPtr, + TimeoutEvent + ) != EFI_SUCCESS) { + break; + } + // + // check type of response - need PXEClient DHCPACK of proper type with bootfile + // + if (!(RxBufPtr->OpAdds.Status & PXE_TYPE) || + (UseBis && (RxBufPtr->OpAdds.Status & USE_THREE_BYTE)) || + !RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1] || + !RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1] || + !InServerList((EFI_IP_ADDRESS *)&((DHCPV4_OP_SERVER_IP *)RxBufPtr->OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX-1])->Ip, ServerListPtr)) { + + continue; + } + + TmpType = TmpLayer = 0; + + if (RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1]) { + TmpType = NTOHS (((PXE_OP_BOOT_ITEM *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1])->Type); + + if (RxBufPtr->OpAdds.Status & USE_THREE_BYTE) { + TmpLayer = (UINT16) (((PXE_OP_BOOT_ITEM *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1])->Layer >> 8); + } else { + TmpLayer = NTOHS (((PXE_OP_BOOT_ITEM *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_ITEM_IX - 1])->Layer); + } + } + + if (TmpType != Type) { + continue; + } + + if (UseBis) { + if (!RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_CREDENTIAL_TYPES_IX - 1]) { + continue; + } + + if (!VerifyCredentialOption ( + (UINT8 *) &DISCREDoptions.Header, + (UINT8 *) RxBufPtr->OpAdds.PxeOptAdds[VEND_PXE_CREDENTIAL_TYPES_IX - 1] + )) { + continue; + } + } + + *LayerPtr = TmpLayer; + + if (UseBis) { + CopyMem ( + &PxebcMode->PxeBisReply, + &RxBufPtr->u.Dhcpv4, + sizeof (EFI_PXE_BASE_CODE_PACKET) + ); + + PxebcMode->PxeBisReplyReceived = TRUE; + + StatCode = DoDiscover ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT, + Type, + LayerPtr, + FALSE, + &Private->ServerIp, + 0 + ); + + gBS->CloseEvent (TimeoutEvent); + return StatCode; + } + + PxebcMode->PxeDiscoverValid = PxebcMode->PxeReplyReceived = TRUE; + + CopyMem ( + &PxebcMode->PxeDiscover, + &*(EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_TRANSMIT_BUFFER, + sizeof (*(EFI_PXE_BASE_CODE_PACKET *) &DHCPV4_TRANSMIT_BUFFER) + ); + + CopyMem ( + &PxebcMode->PxeReply, + &*(EFI_PXE_BASE_CODE_PACKET *) &RxBufPtr->u.Dhcpv4, + sizeof (*(EFI_PXE_BASE_CODE_PACKET *) &RxBufPtr->u.Dhcpv4) + ); + + AddRouters (Private, RxBufPtr); + + gBS->CloseEvent (TimeoutEvent); + return EFI_SUCCESS; + } + + gBS->CloseEvent (TimeoutEvent); + } + // + // end for loop + // + return EFI_TIMEOUT; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +Discover ( + PXE_BASECODE_DEVICE *Private, + IN UINT16 Type, + IN UINT16 *LayerPtr, + IN BOOLEAN UseBis, + IN EFI_PXE_BASE_CODE_DISCOVER_INFO *DiscoverInfoPtr, + PXE_SERVER_LISTS *McastServerListPtr, + PXE_SERVER_LISTS *ServerListPtr + ) +/*++ +Routine Description: + +Parameters: + Private := Pointer to PxeBc interface + Type := + LayerPtr := + UseBis := + DiscoverInfoPtr := + McastServerListPtr := + ServerListPtr := + +Returns: +--*/ +{ + EFI_IP_ADDRESS DestIp; + EFI_STATUS StatCode; + + DEBUG ((EFI_D_INFO, "\nDiscover() Type=%d Layer=%d ", Type, *LayerPtr)); + + if (UseBis) { + DEBUG ((EFI_D_INFO, "BIS ")); + } + // + // get dest IP addr - mcast, bcast, or unicast + // + if (DiscoverInfoPtr->UseMCast) { + DestIp.v4 = DiscoverInfoPtr->ServerMCastIp.v4; + + DEBUG ( + (EFI_D_INFO, + "\nDiscover() MCast %d.%d.%d.%d ", + DestIp.v4.Addr[0], + DestIp.v4.Addr[1], + DestIp.v4.Addr[2], + DestIp.v4.Addr[3]) + ); + + if ((StatCode = DoDiscover ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT, + Type, + LayerPtr, + UseBis, + &DestIp, + McastServerListPtr + )) != EFI_TIMEOUT) { + DEBUG ( + (EFI_D_WARN, + "\nDiscover() status == %r (%Xh)", + StatCode, + StatCode) + ); + + return StatCode; + } + } + + if (DiscoverInfoPtr->UseBCast) { + DEBUG ((EFI_D_INFO, "\nDiscver() BCast ")); + + if ((StatCode = DoDiscover ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT, + Type, + LayerPtr, + UseBis, + &BroadcastIP, + McastServerListPtr + )) != EFI_TIMEOUT) { + + DEBUG ((EFI_D_WARN, "\nDiscover() status == %r (%Xh)", StatCode, StatCode)); + + return StatCode; + } + } + + if (DiscoverInfoPtr->UseUCast) { + UINTN Index; + + DEBUG ( + (EFI_D_INFO, + "\nDiscover() UCast IP#=%d ", + ServerListPtr->Ipv4List.IpCount) + ); + + for (Index = 0; Index < ServerListPtr->Ipv4List.IpCount; ++Index) { + CopyMem (&DestIp, &ServerListPtr->Ipv4List.IpList[Index], 4); + + DEBUG ( + (EFI_D_INFO, + "\nDiscover() UCast %d.%d.%d.%d ", + DestIp.v4.Addr[0], + DestIp.v4.Addr[1], + DestIp.v4.Addr[2], + DestIp.v4.Addr[3]) + ); + + if ((StatCode = DoDiscover ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT, + Type, + LayerPtr, + UseBis, + &DestIp, + 0 + )) != EFI_TIMEOUT) { + DEBUG ( + (EFI_D_WARN, + "\nDiscover() status == %r (%Xh)", + StatCode, + StatCode) + ); + + return StatCode; + } + } + } + + DEBUG ((EFI_D_WARN, "\nDiscover() TIMEOUT")); + + return EFI_TIMEOUT; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* BcDiscover() + */ +EFI_STATUS +EFIAPI +BcDiscover ( + IN EFI_PXE_BASE_CODE_PROTOCOL * This, + IN UINT16 Type, + IN UINT16 *LayerPtr, + IN BOOLEAN UseBis, + IN EFI_PXE_BASE_CODE_DISCOVER_INFO * DiscoverInfoPtr OPTIONAL + ) +/*++ +Routine description: + +Parameters: + This := + Type := + LayerPtr := + UseBis := + DiscoverInfoPtr := + +Returns: +--*/ +{ + EFI_PXE_BASE_CODE_DISCOVER_INFO DefaultInfo; + EFI_PXE_BASE_CODE_MODE *PxebcMode; + DHCP_RECEIVE_BUFFER *DhcpRxBuf; + PXE_SERVER_LISTS DefaultSrvList; + PXE_SERVER_LISTS *ServerListPtr; + PXE_SERVER_LISTS *McastServerListPtr; + EFI_STATUS Status; + UNION_PTR LocalPtr; + UINTN Index; + UINTN Index2; + BOOLEAN AcquiredSrvList; + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + // + // Lock the instance data and make sure started + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + if (This->Mode == NULL || !This->Mode->Started) { + DEBUG ((EFI_D_ERROR, "BC was not started.")); + EfiReleaseLock (&Private->Lock); + return EFI_NOT_STARTED; + } + + ServerListPtr = NULL; + McastServerListPtr = NULL; + AcquiredSrvList = FALSE; + + PxebcMode = Private->EfiBc.Mode; + + if (!GetMem (Private)) { + EfiReleaseLock (&Private->Lock); + return EFI_OUT_OF_RESOURCES; + } + + if (UseBis) { + if (!PxebcMode->BisSupported) { + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + } + + Private->Function = EFI_PXE_BASE_CODE_FUNCTION_DISCOVER; + + if (Private->TotalSeconds == 0) { + // + // put in seconds field of DHCP send packets + // + Private->TotalSeconds = 4; + } + + ZeroMem (&DefaultInfo, sizeof (EFI_PXE_BASE_CODE_DISCOVER_INFO)); + + // + // if layer number not zero, use previous discover + // + if (*LayerPtr != 0) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() layer != 0")); + + if (DiscoverInfoPtr != NULL) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() layer != 0 && DiscoverInfoPtr != NULL\n")); + + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + + if (!PxebcMode->PxeDiscoverValid) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() layer != 0 && PxeDiscoverValid == 0\n")); + + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + + if (!PxebcMode->PxeReplyReceived) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() layer != 0 && PxeReplyReceived == 0\n")); + + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + + if (UseBis && !PxebcMode->PxeBisReplyReceived) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() layer != 0 && PxeBisReplyReceived == 0\n")); + + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + + DefaultInfo.UseUCast = TRUE; + DiscoverInfoPtr = &DefaultInfo; + + DefaultSrvList.Ipv4List.IpCount = 1; + CopyMem (&DefaultSrvList.Ipv4List.IpList[0], &Private->ServerIp, 4); + + ServerListPtr = &DefaultSrvList; + } + // + // layer is zero - see if info is supplied or if we need to use info from a cached offer + // + else if (!DiscoverInfoPtr) { + // + // not supplied - generate it + // make sure that there is cached, appropriate information + // if neither DhcpAck packet nor ProxyOffer packet has pxe info, fail + // + DhcpRxBuf = (PxebcMode->ProxyOfferReceived) ? &PXE_OFFER_BUFFER : &DHCPV4_ACK_BUFFER; + + if (!PxebcMode->DhcpAckReceived || !(DhcpRxBuf->OpAdds.Status & DISCOVER_TYPE)) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() !ack && !proxy")); + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + + DiscoverInfoPtr = &DefaultInfo; + + LocalPtr.OpPtr = DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_CONTROL_IX - 1]; + + // + // if multicast enabled, need multicast address + // + if (!(LocalPtr.DiscoveryControl->ControlBits & DISABLE_MCAST)) { + DefaultInfo.UseMCast = TRUE; + + CopyMem ( + ((EFI_IPv4_ADDRESS *) &DefaultInfo.ServerMCastIp), + &((DHCPV4_OP_IP_ADDRESS *) DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_MCAST_ADDR_IX - 1])->Ip, + sizeof (EFI_IPv4_ADDRESS) + ); + } + + DefaultInfo.UseBCast = (BOOLEAN) ((LocalPtr.DiscoveryControl->ControlBits & DISABLE_BCAST) == 0); + + DefaultInfo.MustUseList = (BOOLEAN) ((LocalPtr.DiscoveryControl->ControlBits & USE_ACCEPT_LIST) != 0); + + DefaultInfo.UseUCast = (BOOLEAN) + ( + (DefaultInfo.MustUseList) || + ((LocalPtr.DiscoveryControl->ControlBits & (DISABLE_MCAST | DISABLE_BCAST)) == (DISABLE_MCAST | DISABLE_BCAST)) + ); + + if ((DefaultInfo.UseUCast | DefaultInfo.MustUseList) && !ExtractBootServerList ( + Type, + DhcpRxBuf->OpAdds.PxeOptAdds[VEND_PXE_BOOT_SERVERS_IX - 1], + &ServerListPtr + )) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() type not in list")); + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + } + // + // Info supplied - make SrvList if required + // if we use ucast discovery or must use list, there better be one + // + else if (DiscoverInfoPtr->UseUCast || DiscoverInfoPtr->MustUseList) { + // + // there better be a list + // + if (DiscoverInfoPtr->IpCnt == 0) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() no bootserver list")); + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + // + // get its size + // + for (Index = Index2 = 0; Index < DiscoverInfoPtr->IpCnt; ++Index) { + if (DiscoverInfoPtr->SrvList[Index].Type == Type) { + if (DiscoverInfoPtr->SrvList[Index].AcceptAnyResponse) { + if (Index2 != 0) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() accept any?")); + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } else { + Index2 = 1; + DefaultSrvList.Ipv4List.IpCount = 0; + ServerListPtr = &DefaultSrvList; + break; + } + } else { + ++Index2; + } + } + } + + if (Index2 == 0) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() !Index2?")); + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + + if (ServerListPtr == NULL) { + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (PXEV4_SERVER_LIST) + (Index2 - 1) * sizeof (EFI_IPv4_ADDRESS), + (VOID **) &ServerListPtr + ); + + if (EFI_ERROR (Status) || ServerListPtr == NULL) { + ServerListPtr = NULL; + EfiReleaseLock (&Private->Lock); + return EFI_OUT_OF_RESOURCES; + } + // + // build an array of IP addresses from the server list + // + AcquiredSrvList = TRUE; + ServerListPtr->Ipv4List.IpCount = (UINT8) Index2; + + for (Index = Index2 = 0; Index < DiscoverInfoPtr->IpCnt; ++Index) { + if (DiscoverInfoPtr->SrvList[Index].Type == Type) { + CopyMem ( + &ServerListPtr->Ipv4List.IpList[Index2++], + &DiscoverInfoPtr->SrvList[Index].IpAddr.v4, + sizeof ServerListPtr->Ipv4List.IpList[0] + ); + } + } + } + } + + if (DiscoverInfoPtr->MustUseList) { + McastServerListPtr = ServerListPtr; + } + + if (!(DiscoverInfoPtr->UseMCast || DiscoverInfoPtr->UseBCast || DiscoverInfoPtr->UseUCast)) { + DEBUG ((EFI_D_WARN, "\nBcDiscover() Nothing to use!\n")); + + EfiReleaseLock (&Private->Lock); + return EFI_INVALID_PARAMETER; + } + + PxebcMode->PxeDiscoverValid = PxebcMode->PxeReplyReceived = PxebcMode->PxeBisReplyReceived = FALSE; + + StatCode = Discover ( + Private, + Type, + LayerPtr, + UseBis, + DiscoverInfoPtr, + McastServerListPtr, + ServerListPtr + ); + + if (AcquiredSrvList) { + gBS->FreePool (ServerListPtr); + } + + FreeMem (Private); + + // + // Unlock the instance data + // + DEBUG ( + (EFI_D_INFO, + "\nBcDiscover() status == %r (%Xh)\n", + StatCode, + StatCode) + ); + + EfiReleaseLock (&Private->Lock); + return StatCode; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +BcSetPackets ( + IN EFI_PXE_BASE_CODE_PROTOCOL * This, + BOOLEAN *NewDhcpDiscoverValid, OPTIONAL + BOOLEAN *NewDhcpAckReceived, OPTIONAL + BOOLEAN *NewProxyOfferReceived, OPTIONAL + BOOLEAN *NewPxeDiscoverValid, OPTIONAL + BOOLEAN *NewPxeReplyReceived, OPTIONAL + BOOLEAN *NewPxeBisReplyReceived, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewDhcpDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewDhcpAck, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewProxyOffer, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewPxeDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewPxeReply, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET * NewPxeBisReply OPTIONAL + ) +/*++ +Routine description: + +Parameters: + +Returns: +--*/ +{ + EFI_PXE_BASE_CODE_MODE *PxebcMode; + EFI_STATUS Status; + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + // + // Lock the instance data and make sure started + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + if (This->Mode == NULL || !This->Mode->Started) { + DEBUG ((EFI_D_ERROR, "BC was not started.")); + EfiReleaseLock (&Private->Lock); + return EFI_NOT_STARTED; + } + + PxebcMode = Private->EfiBc.Mode; + + if (Private->DhcpPacketBuffer == NULL) { + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (DHCP_RECEIVE_BUFFER) * (PXE_BIS_INDEX + 1), + &Private->DhcpPacketBuffer + ); + + if (EFI_ERROR (Status) || Private->DhcpPacketBuffer == NULL) { + Private->DhcpPacketBuffer = NULL; + EfiReleaseLock (&Private->Lock); + return EFI_OUT_OF_RESOURCES; + } + } + // + // Issue BC command + // + // + // reset + // + Private->FileSize = 0; + if (NewDhcpDiscoverValid != NULL) { + PxebcMode->DhcpDiscoverValid = *NewDhcpDiscoverValid; + } + + if (NewDhcpAckReceived != NULL) { + PxebcMode->DhcpAckReceived = *NewDhcpAckReceived; + } + + if (NewProxyOfferReceived != NULL) { + PxebcMode->ProxyOfferReceived = *NewProxyOfferReceived; + } + + if (NewPxeDiscoverValid != NULL) { + PxebcMode->PxeDiscoverValid = *NewPxeDiscoverValid; + } + + if (NewPxeReplyReceived != NULL) { + PxebcMode->PxeReplyReceived = *NewPxeReplyReceived; + } + + if (NewPxeBisReplyReceived != NULL) { + PxebcMode->PxeBisReplyReceived = *NewPxeBisReplyReceived; + } + + if (NewDhcpDiscover != NULL) { + CopyMem ( + &PxebcMode->DhcpDiscover, + NewDhcpDiscover, + sizeof *NewDhcpDiscover + ); + } + + if (NewDhcpAck != NULL) { + CopyParse (Private, &PxebcMode->DhcpAck, NewDhcpAck, DHCPV4_ACK_INDEX); + } + + if (NewProxyOffer != NULL) { + CopyParse (Private, &PxebcMode->ProxyOffer, NewProxyOffer, PXE_OFFER_INDEX); + } + + if (NewPxeDiscover != NULL) { + CopyMem ( + &PxebcMode->PxeDiscover, + NewPxeDiscover, + sizeof *NewPxeDiscover + ); + } + + if (NewPxeReply != NULL) { + CopyParse (Private, &PxebcMode->PxeReply, NewPxeReply, PXE_ACK_INDEX); + } + + if (NewPxeBisReply != NULL) { + CopyParse (Private, &PxebcMode->PxeBisReply, NewPxeBisReply, PXE_BIS_INDEX); + } + // + // Unlock the instance data + // + EfiReleaseLock (&Private->Lock); + return EFI_SUCCESS; +} + +/* eof - pxe_bc_dhcp.c */ diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_igmp.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_igmp.c new file mode 100644 index 0000000000..6737ede9b8 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_igmp.c @@ -0,0 +1,476 @@ +/*++ + +Copyright (c) 2006, 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. + +--*/ + + + + +#define RAND_MAX 0x10000 +#include "bc.h" + +// +// Definitions for internet group management protocol version 2 message +// structure Per RFC 2236, November 1997 +// +STATIC UINT8 RouterAlertOption[4] = { 0x80 | 20, 4, 0, 0 }; +STATIC IPV4_ADDR AllRoutersGroup = { { 224, 0, 0, 2 } }; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +VOID +ClearGroupTimer ( + PXE_BASECODE_DEVICE *Private, + UINTN TimerId + ) +{ + if (Private == NULL) { + return ; + } + + if (TimerId >= Private->MCastGroupCount) { + return ; + } + + if (Private->IgmpGroupEvent[TimerId] == NULL) { + return ; + } + + gBS->CloseEvent (Private->IgmpGroupEvent[TimerId]); + Private->IgmpGroupEvent[TimerId] = NULL; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +VOID +SetGroupTimer ( + PXE_BASECODE_DEVICE *Private, + UINTN TimerId, + UINTN MaxRespTime + ) +/*++ +Routine description: + Set IGMP response timeout value. + +Parameters: + Private := Pointer to PxeBc interface + TimerId := Timer ID# + MaxRespTime := Base response timeout value in tenths of seconds + +Returns: +--*/ +{ + EFI_STATUS EfiStatus; + + if (Private == NULL) { + return ; + } + + if (TimerId >= Private->MCastGroupCount) { + return ; + } + + if (Private->IgmpGroupEvent[TimerId] != NULL) { + gBS->CloseEvent (Private->IgmpGroupEvent[TimerId]); + } + + EfiStatus = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &Private->IgmpGroupEvent[TimerId] + ); + + if (EFI_ERROR (EfiStatus)) { + Private->IgmpGroupEvent[TimerId] = NULL; + return ; + } + + EfiStatus = gBS->SetTimer ( + Private->IgmpGroupEvent[TimerId], + TimerRelative, + MaxRespTime * 1000000 + Random (Private) % RAND_MAX + ); + + if (EFI_ERROR (EfiStatus)) { + gBS->CloseEvent (Private->IgmpGroupEvent[TimerId]); + Private->IgmpGroupEvent[TimerId] = NULL; + } +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +VOID +SendIgmpMessage ( + PXE_BASECODE_DEVICE *Private, + UINT8 Type, + INTN GroupId + ) +/*++ +Routine description: + Send an IGMP message + +Parameters: + Private := Pointer to PxeBc interface + Type := Message type opcode + GroupId := Group ID# + +Returns: +--*/ +{ + Private->IgmpMessage.Type = Type; + Private->IgmpMessage.MaxRespTime = 0; + Private->IgmpMessage.Checksum = 0; + Private->IgmpMessage.GroupAddress = Private->MCastGroup[GroupId]; + Private->IgmpMessage.Checksum = IpChecksum ( + (UINT16 *) &Private->IgmpMessage, + sizeof Private->IgmpMessage + ); + + Ipv4SendWOp ( + Private, + 0, + (UINT8 *) &Private->IgmpMessage, + sizeof Private->IgmpMessage, + PROT_IGMP, + RouterAlertOption, + sizeof RouterAlertOption, + ((Type == IGMP_TYPE_LEAVE_GROUP) ? AllRoutersGroup.L : Private->IgmpMessage.GroupAddress), + EFI_PXE_BASE_CODE_FUNCTION_IGMP + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +VOID +ReportIgmp ( + PXE_BASECODE_DEVICE *Private, + INTN GroupId + ) +/*++ +Routine description: + Send an IGMP report message. + +Parameters: + Private := Pointer to PxeBc interface + GroupId := Group ID# + +Returns: +--*/ +{ + // + // if version 1 querier, send v1 report + // + UINT8 Type; + + if (Private->Igmpv1TimeoutEvent != NULL) { + if (!EFI_ERROR (gBS->CheckEvent (Private->Igmpv1TimeoutEvent))) { + gBS->CloseEvent (Private->Igmpv1TimeoutEvent); + Private->Igmpv1TimeoutEvent = NULL; + Private->UseIgmpv1Reporting = TRUE; + } + } + + Type = (UINT8) (Private->UseIgmpv1Reporting ? IGMP_TYPE_V1REPORT : IGMP_TYPE_REPORT); + + SendIgmpMessage (Private, Type, GroupId); + ClearGroupTimer (Private, GroupId); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +IgmpCheckTimers ( + PXE_BASECODE_DEVICE *Private + ) +/*++ +Routine description: + Check IGMP timers and send reports for all groups that have expired. +Parameters: + Private := Pointer to PxeBc interface + +Returns: +--*/ +{ + UINTN GroupId; + + if (Private == NULL) { + return ; + } + + for (GroupId = 0; GroupId < Private->MCastGroupCount; ++GroupId) { + if (Private->IgmpGroupEvent[GroupId] == NULL) { + continue; + } + + if (!EFI_ERROR (gBS->CheckEvent (Private->IgmpGroupEvent[GroupId]))) { + // + // send a report + // + ReportIgmp (Private, GroupId); + } + } +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +INTN +FindMulticastGroup ( + PXE_BASECODE_DEVICE *Private, + UINT32 GroupAddress + ) +/*++ +Routine description: + Fund group ID# (index). + +Parameters: + Private := Pointer to PxeBc interface + GroupAddress := Group multicast address + +Returns: + 0 := Group not found + other := Group ID# +--*/ +{ + UINTN GroupId; + + for (GroupId = 0; GroupId < Private->MCastGroupCount; ++GroupId) { + if (Private->MCastGroup[GroupId] == GroupAddress) { + return GroupId + 1; + } + } + + return 0; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +IgmpJoinGroup ( + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS *GroupPtr + ) +/*++ +Routine description: + Join multicast group. + +Parameters: + Private := Pointer to PxeBc interface + GroupPtr := Pointer to group mutlicast IP address. + +Returns: +--*/ +{ + UINT32 Grp; + + Grp = *(UINT32 *) GroupPtr; + +#if SUPPORT_IPV6 + if (Private->EfiBc.Mode->UsingIpv6) { + // + // TBD + // + } +#endif + // + // see if we already have it or if we can't take anymore + // + if (FindMulticastGroup (Private, Grp) || Private->MCastGroupCount == MAX_MCAST_GROUPS) { + return ; + } + // + // add the group + // + Private->MCastGroup[Private->MCastGroupCount] = Grp; + + ReportIgmp (Private, Private->MCastGroupCount); + // + // send a report + // so it will get sent again per RFC 2236 + // + SetGroupTimer ( + Private, + Private->MCastGroupCount++, + UNSOLICITED_REPORT_INTERVAL * 10 + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +IgmpLeaveGroup ( + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS *GroupPtr + ) +/*++ +Routine description: + Leave multicast group. + +Parameters: + Private := Pointer to PxeBc interface + GroupPtr := Mutlicast group IP address. + +Returns: +--*/ +{ + UINT32 Grp; + UINTN GroupId; + + Grp = *(UINT32 *) GroupPtr; + +#if SUPPORT_IPV6 + if (Private->EfiBc.Mode->UsingIpv6) { + // + // TBD + // + } +#endif + // + // if not in group, ignore + // + GroupId = FindMulticastGroup (Private, Grp); + + if (GroupId == 0) { + return ; + } + // + // if not v1 querrier, send leave group IGMP message + // + if (Private->Igmpv1TimeoutEvent != NULL) { + if (!EFI_ERROR (gBS->CheckEvent (Private->Igmpv1TimeoutEvent))) { + gBS->CloseEvent (Private->Igmpv1TimeoutEvent); + Private->Igmpv1TimeoutEvent = NULL; + Private->UseIgmpv1Reporting = TRUE; + } else { + SendIgmpMessage (Private, IGMP_TYPE_LEAVE_GROUP, GroupId - 1); + } + } + + while (GroupId < Private->MCastGroupCount) { + Private->MCastGroup[GroupId - 1] = Private->MCastGroup[GroupId]; + Private->IgmpGroupEvent[GroupId - 1] = Private->IgmpGroupEvent[GroupId]; + ++GroupId; + } + + --Private->MCastGroupCount; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +HandleIgmp ( + PXE_BASECODE_DEVICE *Private, + IGMPV2_MESSAGE *IgmpMessagePtr, + UINTN IgmpLength + ) +/*++ +Routine description: + Handle received IGMP packet + +Parameters: + Private := Pointer to PxeBc interface + IgmpMessagePtr := Pointer to IGMP packet + IgmpLength := packet length in bytes + +Returns: +--*/ +{ + EFI_STATUS EfiStatus; + UINTN GroupId; + INTN MaxRespTime; + + if (Private == NULL) { + return ; + } + + if (Private->MCastGroupCount == 0) { + // + // if we don't belong to any multicast groups, ignore + // + return ; + } + // + // verify checksum + // + if (IpChecksum ((UINT16 *) IgmpMessagePtr, IgmpLength)) { + // + // bad checksum - ignore packet + // + return ; + } + + switch (IgmpMessagePtr->Type) { + case IGMP_TYPE_QUERY: + // + // if a version 1 querier, note the fact and set max resp time + // + MaxRespTime = IgmpMessagePtr->MaxRespTime; + + if (MaxRespTime == 0) { + Private->UseIgmpv1Reporting = TRUE; + + if (Private->Igmpv1TimeoutEvent != NULL) { + gBS->CloseEvent (Private->Igmpv1TimeoutEvent); + } + + EfiStatus = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &Private->Igmpv1TimeoutEvent + ); + + if (EFI_ERROR (EfiStatus)) { + Private->Igmpv1TimeoutEvent = NULL; + } else { + EfiStatus = gBS->SetTimer ( + Private->Igmpv1TimeoutEvent, + TimerRelative, + (UINT64) V1ROUTER_PRESENT_TIMEOUT * 10000000 + ); + } + + MaxRespTime = IGMP_DEFAULT_MAX_RESPONSE_TIME * 10; + } + // + // if a general query (!GroupAddress), set all our group timers + // + if (!IgmpMessagePtr->GroupAddress) { + for (GroupId = 0; GroupId < Private->MCastGroupCount; ++GroupId) { + SetGroupTimer (Private, GroupId, MaxRespTime); + } + } else { + // + // specific query - set only specific group + // + GroupId = FindMulticastGroup (Private, IgmpMessagePtr->GroupAddress); + + if (GroupId != 0) { + SetGroupTimer (Private, GroupId - 1, MaxRespTime); + } + } + + break; + + // + // if we have a timer running for this group, clear it + // + case IGMP_TYPE_V1REPORT: + case IGMP_TYPE_REPORT: + GroupId = FindMulticastGroup (Private, IgmpMessagePtr->GroupAddress); + + if (GroupId != 0) { + ClearGroupTimer (Private, GroupId - 1); + } + + break; + } +} + +/* EOF - pxe_bc_igmp.c */ diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_ip.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_ip.c new file mode 100644 index 0000000000..26bc2109ae --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_ip.c @@ -0,0 +1,861 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + pxe_bc_ip.c + +Abstract: + +--*/ + + +#include "bc.h" + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +BOOLEAN +OnSameSubnet ( + IN UINTN IpLength, + IN EFI_IP_ADDRESS *Ip1, + IN EFI_IP_ADDRESS *Ip2, + IN EFI_IP_ADDRESS *SubnetMask + ) +/*++ + + Routine Description: + Check if two IP addresses are on the same subnet. + + Arguments: + IpLength - Length of IP address in bytes. + Ip1 - IP address to check. + Ip2 - IP address to check. + SubnetMask - Subnet mask to check with. + + Returns: + TRUE - IP addresses are on the same subnet. + FALSE - IP addresses are on different subnets. + +--*/ +{ + if (IpLength == 0 || Ip1 == NULL || Ip2 == NULL || SubnetMask == NULL) { + return FALSE; + } + + while (IpLength-- != 0) { + if ((Ip1->v6.Addr[IpLength] ^ Ip2->v6.Addr[IpLength]) & SubnetMask->v6.Addr[IpLength]) { + return FALSE; + } + } + + return TRUE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +IpAddRouter ( + IN PXE_BASECODE_DEVICE *Private, + IN EFI_IP_ADDRESS *RouterIpPtr + ) +/*++ + + Routine Description: + Add router to router table. + + Arguments: + Private - Pointer PxeBc instance data. + RouterIpPtr - Pointer to router IP address. + + Returns: + Nothing + +--*/ +{ + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + UINTN Index; + + if (Private == NULL || RouterIpPtr == NULL) { + return ; + } + + PxeBcMode = Private->EfiBc.Mode; + + // + // if we are filled up or this is not on the same subnet, forget it + // + if ((PxeBcMode->RouteTableEntries == PXE_ROUTER_TABLE_SIZE) || + !OnSameSubnet(Private->IpLength, &PxeBcMode->StationIp, RouterIpPtr, &PxeBcMode->SubnetMask)) { + return ; + } + // + // make sure we don't already have it + // + for (Index = 0; Index < PxeBcMode->RouteTableEntries; ++Index) { + if (!CompareMem ( + &PxeBcMode->RouteTable[Index].GwAddr, + RouterIpPtr, + Private->IpLength + )) { + return ; + } + } + // + // keep it + // + ZeroMem ( + &PxeBcMode->RouteTable[PxeBcMode->RouteTableEntries], + sizeof (EFI_PXE_BASE_CODE_ROUTE_ENTRY) + ); + + CopyMem ( + &PxeBcMode->RouteTable[PxeBcMode->RouteTableEntries++].GwAddr, + RouterIpPtr, + Private->IpLength + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// return router ip to use for DestIp (0 if none) +// +STATIC +EFI_IP_ADDRESS * +GetRouterIp ( + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS *DestIpPtr + ) +{ + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + UINTN Index; + + if (Private == NULL || DestIpPtr == NULL) { + return NULL; + } + + PxeBcMode = Private->EfiBc.Mode; + + for (Index = 0; Index < PxeBcMode->RouteTableEntries; ++Index) { + if (OnSameSubnet ( + Private->IpLength, + &PxeBcMode->RouteTable[Index].IpAddr, + DestIpPtr, + &PxeBcMode->RouteTable[Index].SubnetMask + )) { + return &PxeBcMode->RouteTable[Index].GwAddr; + } + } + + return NULL; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// routine to send ipv4 packet +// ipv4 header of length HdrLth in TransmitBufferPtr +// routine fills in ipv4hdr Ver_Hdl, TotalLength, and Checksum, moves in Data +// and gets dest MAC address +// +#define IP_TX_BUFFER ((IPV4_BUFFER *) Private->TransmitBufferPtr) +#define IP_TX_HEADER IP_TX_BUFFER->IpHeader + +EFI_STATUS +Ipv4Xmt ( + PXE_BASECODE_DEVICE *Private, + UINT32 GatewayIp, + UINTN IpHeaderLength, + UINTN TotalHeaderLength, + VOID *Data, + UINTN DataLength, + EFI_PXE_BASE_CODE_FUNCTION Function + ) +{ + EFI_MAC_ADDRESS DestMac; + EFI_SIMPLE_NETWORK_PROTOCOL *Snp; + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + EFI_STATUS StatCode; + UINTN PacketLength; + + Snp = Private->SimpleNetwork; + PxeBcMode = Private->EfiBc.Mode; + StatCode = EFI_SUCCESS; + PacketLength = TotalHeaderLength + DataLength; + + // + // get dest MAC address + // multicast - convert to hw equiv + // unicast on same net, use arp + // on different net, arp for router + // + if (IP_TX_HEADER.DestAddr.L == BROADCAST_IPv4) { + CopyMem (&DestMac, &Snp->Mode->BroadcastAddress, sizeof (DestMac)); + } else if (IS_MULTICAST (&IP_TX_HEADER.DestAddr)) { + StatCode = (*Snp->MCastIpToMac) (Snp, PxeBcMode->UsingIpv6, (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr, &DestMac); + } else { + UINT32 Ip; + + if (OnSameSubnet ( + Private->IpLength, + &PxeBcMode->StationIp, + (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr, + &PxeBcMode->SubnetMask + )) { + Ip = IP_TX_HEADER.DestAddr.L; + } else if (GatewayIp != 0) { + Ip = GatewayIp; + } else { + EFI_IP_ADDRESS *TmpIp; + + TmpIp = GetRouterIp (Private, (EFI_IP_ADDRESS *) &IP_TX_HEADER.DestAddr); + + if (TmpIp == NULL) { + DEBUG ( + (EFI_D_WARN, + "\nIpv4Xmit() Exit #1 %xh (%r)", + EFI_NO_RESPONSE, + EFI_NO_RESPONSE) + ); + + return EFI_NO_RESPONSE; + // + // no router + // + } + + Ip = TmpIp->Addr[0]; + } + + if (!GetHwAddr ( + Private, + (EFI_IP_ADDRESS *) &Ip, + (EFI_MAC_ADDRESS *) &DestMac + )) { + if (!PxeBcMode->AutoArp) { + DEBUG ( + (EFI_D_WARN, + "\nIpv4Xmit() Exit #2 %xh (%r)", + EFI_DEVICE_ERROR, + EFI_DEVICE_ERROR) + ); + + return EFI_DEVICE_ERROR; + } else { + StatCode = DoArp ( + Private, + (EFI_IP_ADDRESS *) &Ip, + (EFI_MAC_ADDRESS *) &DestMac + ); + } + } + } + + if (EFI_ERROR (StatCode)) { + DEBUG ((EFI_D_WARN, "\nIpv4Xmit() Exit #3 %xh (%r)", StatCode, StatCode)); + return StatCode; + } + // + // fill in packet info + // + SET_IPV4_VER_HDL (&IP_TX_HEADER, IpHeaderLength); + IP_TX_HEADER.TotalLength = HTONS (PacketLength); + IP_TX_HEADER.HeaderChecksum = IpChecksum ((UINT16 *) &IP_TX_HEADER, IpHeaderLength); + CopyMem (((UINT8 *) &IP_TX_HEADER) + TotalHeaderLength, Data, DataLength); + + // + // send it + // + return SendPacket ( + Private, + (UINT8 *) &IP_TX_HEADER - Snp->Mode->MediaHeaderSize, + &IP_TX_HEADER, + PacketLength, + &DestMac, + PXE_PROTOCOL_ETHERNET_IP, + Function + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// send ipv4 packet with option +// +EFI_STATUS +Ipv4SendWOp ( + PXE_BASECODE_DEVICE *Private, + UINT32 GatewayIp, + UINT8 *Msg, + UINTN MessageLength, + UINT8 Prot, + UINT8 *Option, + UINTN OptionLength, + UINT32 DestIp, + EFI_PXE_BASE_CODE_FUNCTION Function + ) +{ + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + UINTN HdrLth; + + PxeBcMode = Private->EfiBc.Mode; + HdrLth = sizeof (IPV4_HEADER) + OptionLength; + + ZeroMem ((VOID *) &IP_TX_HEADER, sizeof (IPV4_HEADER)); + IP_TX_HEADER.TimeToLive = PxeBcMode->TTL; + IP_TX_HEADER.TypeOfService = PxeBcMode->ToS; + IP_TX_HEADER.Protocol = Prot; + IP_TX_HEADER.SrcAddr.L = *(UINT32 *) &PxeBcMode->StationIp; + IP_TX_HEADER.DestAddr.L = DestIp; + IP_TX_HEADER.Id = Random (Private); + CopyMem (IP_TX_BUFFER->u.Data, Option, OptionLength); + return Ipv4Xmt ( + Private, + GatewayIp, + HdrLth, + HdrLth, + Msg, + MessageLength, + Function + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// send MessageLength message at MessagePtr - higher level protocol header already in TransmitBufferPtr, length HdrSize +// +EFI_STATUS +Ip4Send ( + PXE_BASECODE_DEVICE *Private, // pointer to instance data + UINTN MayFrag, // + UINT8 Prot, // protocol + UINT32 SrcIp, // Source IP address + UINT32 DestIp, // Destination IP address + UINT32 GatewayIp, // used if not NULL and needed + UINTN HdrSize, // protocol header byte length + UINT8 *MessagePtr, // pointer to data + UINTN MessageLength // data byte length + ) +{ + EFI_STATUS StatCode; + UINTN TotDataLength; + + TotDataLength = HdrSize + MessageLength; + + if (TotDataLength > MAX_IPV4_DATA_SIZE) { + DEBUG ( + (EFI_D_WARN, + "\nIp4Send() Exit #1 %xh (%r)", + EFI_BAD_BUFFER_SIZE, + EFI_BAD_BUFFER_SIZE) + ); + + return EFI_BAD_BUFFER_SIZE; + } + + ZeroMem ((VOID *) &IP_TX_HEADER, sizeof (IPV4_HEADER)); + IP_TX_HEADER.TimeToLive = DEFAULT_TTL; + IP_TX_HEADER.Protocol = Prot; + IP_TX_HEADER.SrcAddr.L = SrcIp; + IP_TX_HEADER.DestAddr.L = DestIp; + IP_TX_HEADER.Id = Random (Private); + + if (!MayFrag) { + *(UINT8 *) (&IP_TX_HEADER.FragmentFields) = IP_NO_FRAG >> 8; + } + // + // check for need to fragment + // + if (TotDataLength > MAX_IPV4_FRAME_DATA_SIZE) { + UINTN DataLengthSent; + UINT16 FragmentOffset; + + FragmentOffset = IP_MORE_FRAG; + // + // frag offset field + // + if (!MayFrag) { + DEBUG ( + (EFI_D_WARN, + "\nIp4Send() Exit #2 %xh (%r)", + EFI_BAD_BUFFER_SIZE, + EFI_BAD_BUFFER_SIZE) + ); + + return EFI_BAD_BUFFER_SIZE; + } + // + // send out in fragments - first includes upper level header + // all are max and include more frag bit except last + // + * (UINT8 *) (&IP_TX_HEADER.FragmentFields) = IP_MORE_FRAG >> 8; + +#define IPV4_FRAG_SIZE (MAX_IPV4_FRAME_DATA_SIZE & 0xfff8) +#define IPV4_FRAG_OFF_INC (IPV4_FRAG_SIZE >> 3) + + DataLengthSent = IPV4_FRAG_SIZE - HdrSize; + + StatCode = Ipv4Xmt ( + Private, + GatewayIp, + sizeof (IPV4_HEADER), + sizeof (IPV4_HEADER) + HdrSize, + MessagePtr, + DataLengthSent, + Private->Function + ); + + if (EFI_ERROR (StatCode)) { + DEBUG ( + (EFI_D_WARN, + "\nIp4Send() Exit #3 %xh (%r)", + StatCode, + StatCode) + ); + + return StatCode; + } + + MessagePtr += DataLengthSent; + MessageLength -= DataLengthSent; + FragmentOffset += IPV4_FRAG_OFF_INC; + IP_TX_HEADER.FragmentFields = HTONS (FragmentOffset); + + while (MessageLength > IPV4_FRAG_SIZE) { + StatCode = Ipv4Xmt ( + Private, + GatewayIp, + sizeof (IPV4_HEADER), + sizeof (IPV4_HEADER), + MessagePtr, + IPV4_FRAG_SIZE, + Private->Function + ); + + if (EFI_ERROR (StatCode)) { + DEBUG ( + (EFI_D_WARN, + "\nIp4Send() Exit #3 %xh (%r)", + StatCode, + StatCode) + ); + + return StatCode; + } + + MessagePtr += IPV4_FRAG_SIZE; + MessageLength -= IPV4_FRAG_SIZE; + FragmentOffset += IPV4_FRAG_OFF_INC; + IP_TX_HEADER.FragmentFields = HTONS (FragmentOffset); + } + + * (UINT8 *) (&IP_TX_HEADER.FragmentFields) &= ~(IP_MORE_FRAG >> 8); + HdrSize = 0; + } + // + // transmit + // + return Ipv4Xmt ( + Private, + GatewayIp, + sizeof (IPV4_HEADER), + sizeof (IPV4_HEADER) + HdrSize, + MessagePtr, + MessageLength, + Private->Function + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// return true if dst IP in receive header matched with what's enabled +// +STATIC +BOOLEAN +IPgood ( + PXE_BASECODE_DEVICE *Private, + IPV4_HEADER *IpHeader + ) +{ + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + UINTN Index; + + PxeBcMode = Private->EfiBc.Mode; + + if (PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS) { + return TRUE; + } + + if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST) && + IS_MULTICAST (&IpHeader->DestAddr) + ) { + return TRUE; + } + + if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP) && + PxeBcMode->StationIp.Addr[0] == IpHeader->DestAddr.L + ) { + return TRUE; + } + + if ((PxeBcMode->IpFilter.Filters & EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST) && IpHeader->DestAddr.L == BROADCAST_IPv4) { + return TRUE; + } + + for (Index = 0; Index < PxeBcMode->IpFilter.IpCnt; ++Index) { + if (IpHeader->DestAddr.L == PxeBcMode->IpFilter.IpList[Index].Addr[0]) { + return TRUE; + } + } + + return FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// receive up to MessageLength message into MessagePtr for protocol Prot +// return message length, src/dest ips if select any, and pointer to protocol +// header routine will filter based on source and/or dest ip if OpFlags set. +// +EFI_STATUS +IpReceive ( + PXE_BASECODE_DEVICE *Private, + PXE_OPFLAGS OpFlags, + EFI_IP_ADDRESS *SrcIpPtr, + EFI_IP_ADDRESS *DestIpPtr, + UINT8 Prot, + VOID *HeaderPtr, + UINTN HdrSize, + UINT8 *MessagePtr, + UINTN *MessageLengthPtr, + EFI_EVENT TimeoutEvent + ) +{ + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + EFI_STATUS StatCode; + UINTN ByteCount; + UINTN FragmentCount; + UINTN ExpectedPacketLength; + UINTN Id; + BOOLEAN GotFirstFragment; + BOOLEAN GotLastFragment; + + DEBUG ( + (EFI_D_NET, + "\nIpReceive() Hdr=%Xh HdrSz=%d Data=%Xh DataSz=%d", + HeaderPtr, + HdrSize, + MessagePtr, + *MessageLengthPtr) + ); + + PxeBcMode = Private->EfiBc.Mode; + PxeBcMode->IcmpErrorReceived = FALSE; + + ExpectedPacketLength = 0; + GotFirstFragment = FALSE; + GotLastFragment = FALSE; + FragmentCount = 0; + ByteCount = 0; + Id = 0; + + for (;;) { + IPV4_HEADER IpHdr; + UINTN FFlds; + UINTN TotalLength; + UINTN FragmentOffset; + UINTN HeaderSize; + UINTN BufferSize; + UINTN IpHeaderLength; + UINTN DataLength; + UINT16 Protocol; + UINT8 *NextHdrPtr; + UINT8 *PacketPtr; + + StatCode = WaitForReceive ( + Private, + Private->Function, + TimeoutEvent, + &HeaderSize, + &BufferSize, + &Protocol + ); + + if (EFI_ERROR (StatCode)) { + return StatCode; + } + + PacketPtr = Private->ReceiveBufferPtr + HeaderSize; + + if (Protocol == PXE_PROTOCOL_ETHERNET_ARP) { + HandleArpReceive ( + Private, + (ARP_PACKET *) PacketPtr, + Private->ReceiveBufferPtr + ); + + continue; + } + + if (Protocol != PXE_PROTOCOL_ETHERNET_IP) { + continue; + } + +#if SUPPORT_IPV6 + if (PxeBcMode->UsingIpv6) { + // + // TBD + // + } +#endif + +#define IpRxHeader ((IPV4_HEADER *) PacketPtr) + + // + // filter for version & check sum + // + IpHeaderLength = IPV4_HEADER_LENGTH (IpRxHeader); + + if ((IpRxHeader->VersionIhl >> 4) != IPVER4) { + continue; + } + + if (IpChecksum ((UINT16 *) IpRxHeader, IpHeaderLength)) { + continue; + } + + CopyMem (&IpHdr, IpRxHeader, sizeof (IpHdr)); + //IpHdr = *IpRxHeader; + TotalLength = NTOHS (IpHdr.TotalLength); + + if (IpHdr.Protocol == PROT_TCP) { + // + // The NextHdrPtr is used to seed the header buffer we are passing back. + // That being the case, we want to see everything in pPkt which contains + // everything but the ethernet (or whatever) frame. IP + TCP in this case. + // + DataLength = TotalLength; + NextHdrPtr = PacketPtr; + } else { + DataLength = TotalLength - IpHeaderLength; + NextHdrPtr = PacketPtr + IpHeaderLength; + } + // + // If this is an ICMP, it might not be for us. + // Double check the state of the IP stack and the + // packet fields before assuming it is an ICMP + // error. ICMP requests are not supported by the + // PxeBc IP stack and should be ignored. + // + if (IpHdr.Protocol == PROT_ICMP) { + ICMPV4_HEADER *Icmpv4; + + Icmpv4 = (ICMPV4_HEADER *) NextHdrPtr; + + // + // For now only obvious ICMP error replies will be accepted by + // this stack. This still makes us vulnerable to DoS attacks. + // But at least we will not be killed by DHCP daemons. + // + switch (Icmpv4->Type) { + case ICMP_REDIRECT: + case ICMP_ECHO: + case ICMP_ROUTER_ADV: + case ICMP_ROUTER_SOLICIT: + case ICMP_TIMESTAMP: + case ICMP_TIMESTAMP_REPLY: + case ICMP_INFO_REQ: + case ICMP_INFO_REQ_REPLY: + case ICMP_SUBNET_MASK_REQ: + case ICMP_SUBNET_MASK_REPLY: + default: + continue; + + // + // %%TBD - This should be implemented. + // + case ICMP_ECHO_REPLY: + continue; + + case ICMP_DEST_UNREACHABLE: + case ICMP_TIME_EXCEEDED: + case ICMP_PARAMETER_PROBLEM: + case ICMP_SOURCE_QUENCH: + PxeBcMode->IcmpErrorReceived = TRUE; + + CopyMem ( + &PxeBcMode->IcmpError, + NextHdrPtr, + sizeof (EFI_PXE_BASE_CODE_ICMP_ERROR) + ); + + DEBUG ( + (EFI_D_NET, + "\nIpReceive() Exit #1 %Xh (%r)", + EFI_ICMP_ERROR, + EFI_ICMP_ERROR) + ); + } + + return EFI_ICMP_ERROR; + } + + if (IpHdr.Protocol == PROT_IGMP) { + HandleIgmp (Private, (IGMPV2_MESSAGE *) NextHdrPtr, DataLength); + + DEBUG ((EFI_D_NET, "\n IGMP")); + continue; + } + // + // check for protocol + // + if (IpHdr.Protocol != Prot) { + continue; + } + // + // do filtering + // + if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) && SrcIpPtr && SrcIpPtr->Addr[0] != IpHdr.SrcAddr.L) { + DEBUG ((EFI_D_NET, "\n Not expected source IP address.")); + continue; + } + + if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER) { + if (!IPgood (Private, &IpHdr)) { + continue; + } + } else if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP)) { + if (DestIpPtr == NULL) { + if (PxeBcMode->StationIp.Addr[0] != IpHdr.DestAddr.L) { + continue; + } + } else if (DestIpPtr->Addr[0] != IpHdr.DestAddr.L) { + continue; + } + } + // + // get some data we need + // + FFlds = NTOHS (IpHdr.FragmentFields); + FragmentOffset = ((FFlds & IP_FRAG_OFF_MSK) << 3); + + /* Keep count of fragments that belong to this session. + * If we get packets with a different IP ID number, + * ignore them. Ignored packets should be handled + * by the upper level protocol. + */ + if (FragmentCount == 0) { + Id = IpHdr.Id; + + if (DestIpPtr != NULL) { + DestIpPtr->Addr[0] = IpHdr.DestAddr.L; + } + + if (SrcIpPtr != NULL) { + SrcIpPtr->Addr[0] = IpHdr.SrcAddr.L; + } + } else { + if (IpHdr.Id != Id) { + continue; + } + } + + ++FragmentCount; + + /* Fragment management. + */ + if (FragmentOffset == 0) { + /* This is the first fragment (may also be the + * only fragment). + */ + GotFirstFragment = TRUE; + + /* If there is a separate protocol header buffer, + * copy the header, adjust the data pointer and + * the data length. + */ + if (HdrSize != 0) { + CopyMem (HeaderPtr, NextHdrPtr, HdrSize); + + NextHdrPtr += HdrSize; + DataLength -= HdrSize; + } + } else { + /* If there is a separate protocol header buffer, + * adjust the fragment offset. + */ + FragmentOffset -= HdrSize; + } + + /* See if this is the last fragment. + */ + if (!(FFlds & IP_MORE_FRAG)) { + // + // This is the last fragment (may also be the only fragment). + // + GotLastFragment = TRUE; + + /* Compute the expected length of the assembled + * packet. This will be used to decide if we + * have gotten all of the fragments. + */ + ExpectedPacketLength = FragmentOffset + DataLength; + } + + DEBUG ( + (EFI_D_NET, + "\n ID = %Xh Off = %d Len = %d", + Id, + FragmentOffset, + DataLength) + ); + + /* Check for receive buffer overflow. + */ + if (FragmentOffset + DataLength > *MessageLengthPtr) { + /* There is not enough space in the receive + * buffer for the fragment. + */ + DEBUG ( + (EFI_D_NET, + "\nIpReceive() Exit #3 %Xh (%r)", + EFI_BUFFER_TOO_SMALL, + EFI_BUFFER_TOO_SMALL) + ); + + return EFI_BUFFER_TOO_SMALL; + } + + /* Copy data into receive buffer. + */ + if (DataLength != 0) { + DEBUG ((EFI_D_NET, " To = %Xh", MessagePtr + FragmentOffset)); + + CopyMem (MessagePtr + FragmentOffset, NextHdrPtr, DataLength); + ByteCount += DataLength; + } + + /* If we have seen the first and last fragments and + * the receive byte count is at least as large as the + * expected byte count, return SUCCESS. + * + * We could be tricked by receiving a fragment twice + * but the upper level protocol should figure this + * out. + */ + if (GotFirstFragment && GotLastFragment && ByteCount >= ExpectedPacketLength) { + *MessageLengthPtr = ExpectedPacketLength; + return EFI_SUCCESS; + } + } +} + +/* eof - pxe_bc_ip.c */ diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_mtftp.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_mtftp.c new file mode 100644 index 0000000000..3e0b0f547f --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_mtftp.c @@ -0,0 +1,2391 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + pxe_bc_mtftp.c + +Abstract: + TFTP and MTFTP (multicast TFTP) implementation. + +Revision History + +--*/ + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// The following #define is used to create a version that does not wait to +// open after a listen. This is just for a special regression test of MTFTP +// server to make sure multiple opens are handled correctly. Normally this +// next line should be a comment. +// #define SpecialNowaitVersion // comment out for normal operation +// + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + + +#include "bc.h" + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +UINT64 +Swap64 ( + UINT64 n + ) +{ + union { + UINT64 n; + UINT8 b[8]; + } u; + + UINT8 t; + + u.n = n; + + t = u.b[0]; + u.b[0] = u.b[7]; + u.b[7] = t; + + t = u.b[1]; + u.b[1] = u.b[6]; + u.b[6] = t; + + t = u.b[2]; + u.b[2] = u.b[5]; + u.b[5] = t; + + t = u.b[3]; + u.b[3] = u.b[4]; + u.b[4] = t; + + return u.n; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +TftpUdpRead ( + PXE_BASECODE_DEVICE *Private, + UINT16 Operation, + VOID *HeaderPtr, + UINTN *BufferSizePtr, + VOID *BufferPtr, + EFI_IP_ADDRESS *ServerIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ServerPortPtr, + EFI_IP_ADDRESS *OurIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *OurPortPtr, + UINT16 Timeout + ) +/*++ +Routine description: + Read TFTP packet. If TFTP ERROR packet is read, fill in TFTP error + information in Mode structure and return TFTP_ERROR status. + +Parameters: + Private := + Operation := + HeaderPtr := + BufferSizePtr := + BufferPtr := + ServerIpPtr := + ServerPortPtr := + OurIpPtr := + OurPortPtr := + Timeout := + +Returns: + EFI_SUCCESS := + EFI_TFTP_ERROR := + other := +--*/ +{ + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + EFI_STATUS Status; + EFI_EVENT TimeoutEvent; + UINTN HeaderSize; + + // + // + // + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->SetTimer ( + TimeoutEvent, + TimerRelative, + Timeout * 10000000 + 1000000 + ); + + if (EFI_ERROR (Status)) { + gBS->CloseEvent (TimeoutEvent); + return Status; + } + // + // + // + HeaderSize = Private->BigBlkNumFlag ? sizeof (struct Tftpv4Ack8) : sizeof (struct Tftpv4Ack); + +#define ERROR_MESSAGE_PTR ((struct Tftpv4Error *) HeaderPtr) + + Status = UdpRead ( + Private, + Operation, + OurIpPtr, + OurPortPtr, + ServerIpPtr, + ServerPortPtr, + &HeaderSize, + HeaderPtr, + BufferSizePtr, + BufferPtr, + TimeoutEvent + ); + + if (Status != EFI_SUCCESS || ERROR_MESSAGE_PTR->OpCode != HTONS (TFTP_ERROR)) { + gBS->CloseEvent (TimeoutEvent); + return Status; + } + // + // got an error packet + // write one byte error code followed by error message + // + PxeBcMode = Private->EfiBc.Mode; + PxeBcMode->TftpErrorReceived = TRUE; + PxeBcMode->TftpError.ErrorCode = (UINT8) NTOHS (ERROR_MESSAGE_PTR->ErrCode); + HeaderSize = EFI_MIN (*BufferSizePtr, sizeof PxeBcMode->TftpError.ErrorString); + CopyMem (PxeBcMode->TftpError.ErrorString, BufferPtr, HeaderSize); + + gBS->CloseEvent (TimeoutEvent); + return EFI_TFTP_ERROR; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +VOID +SendError ( + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS *ServerIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ServerPortPtr, + EFI_PXE_BASE_CODE_UDP_PORT *OurPortPtr + ) +/*++ +Routine description: + Send TFTP ERROR message to TFTP server + +Parameters: + Private := + ServerIpPtr := + ServerPortPtr := + OurPortPtr := + +Returns: +--*/ +{ + struct Tftpv4Error *ErrStr; + UINTN Len; + + ErrStr = (VOID *) Private->TftpErrorBuffer; + Len = sizeof *ErrStr; + + ErrStr->OpCode = HTONS (TFTP_ERROR); + ErrStr->ErrCode = HTONS (TFTP_ERR_OPTION); + ErrStr->ErrMsg[0] = 0; + + UdpWrite ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT, + ServerIpPtr, + ServerPortPtr, + 0, + 0, + OurPortPtr, + 0, + 0, + &Len, + ErrStr + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +SendAckAndGetData ( + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS *ServerIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ServerPortPtr, + EFI_IP_ADDRESS *ReplyIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *OurPortPtr, + UINT16 Timeout, + UINTN *ReplyLenPtr, + UINT8 *PxeBcMode, + UINT64 *BlockNumPtr, + BOOLEAN AckOnly + ) +/*++ +Routine description: + Send TFTP ACK packet to server and read next DATA packet. + +Parameters: + Private := Pointer to PxeBc interface + ServerIpPtr := Pointer to TFTP server IP address + ServerPortPtr := Pointer to TFTP server UDP port + ReplyIpPtr := Pointer to TFTP DATA packet destination IP address + OurPortPtr := Pointer to TFTP client UDP port + Timeout := + ReplyLenPtr := Pointer to packet length + PxeBcMode := Pointer to packet buffer + BlockNumPtr := Pointer to block number + AckOnly := TRUE == Send last ack - do not wait for reply + +Returns: +--*/ +{ + struct Tftpv4Data DataBuffer; + struct Tftpv4Ack *Ack2Ptr; + struct Tftpv4Ack8 *Ack8Ptr; + EFI_STATUS Status; + UINTN Len; + + Ack2Ptr = (VOID *) Private->TftpAckBuffer; + Ack8Ptr = (VOID *) Private->TftpAckBuffer; + + if (Private->BigBlkNumFlag) { + Len = sizeof (struct Tftpv4Ack8); + + Ack8Ptr->OpCode = HTONS (TFTP_ACK8); + Ack8Ptr->BlockNum = Swap64 (*BlockNumPtr); + + Status = UdpWrite ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT, + ServerIpPtr, + ServerPortPtr, + 0, + 0, + OurPortPtr, + 0, + 0, + &Len, + Ack8Ptr + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } else { + Len = sizeof (struct Tftpv4Ack); + + Ack2Ptr->OpCode = HTONS (TFTP_ACK); + Ack2Ptr->BlockNum = HTONS ((UINT16) *BlockNumPtr); + + Status = UdpWrite ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT, + ServerIpPtr, + ServerPortPtr, + 0, + 0, + OurPortPtr, + 0, + 0, + &Len, + Ack2Ptr + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + if (AckOnly) { + // + // ACK of last packet. This is just a courtesy. + // Do not wait for response. + // + return EFI_SUCCESS; + } + // + // read reply + // + Status = TftpUdpRead ( + Private, + 0, + &DataBuffer, + ReplyLenPtr, + PxeBcMode, + ServerIpPtr, + ServerPortPtr, + ReplyIpPtr, + OurPortPtr, + Timeout + ); + + if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { + return Status; + } + // + // got a good reply (so far) + // check for next data packet + // + if (!Private->BigBlkNumFlag && DataBuffer.Header.OpCode == HTONS (TFTP_DATA)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + SendError (Private, ServerIpPtr, ServerPortPtr, OurPortPtr); + } + + *BlockNumPtr = NTOHS (DataBuffer.Header.BlockNum); + return Status; + } + + if (Private->BigBlkNumFlag && DataBuffer.Header.OpCode == HTONS (TFTP_DATA8)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + SendError (Private, ServerIpPtr, ServerPortPtr, OurPortPtr); + } + + *BlockNumPtr = Swap64 (*(UINT64 *) &DataBuffer.Header.BlockNum); + return Status; + } + + return EFI_PROTOCOL_ERROR; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +LockStepReceive ( + PXE_BASECODE_DEVICE *Private, + UINTN PacketSize, + UINT64 *BufferSizePtr, + UINT64 Offset, + UINT8 *BufferPtr, + EFI_IP_ADDRESS *ServerIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ServerPortPtr, + EFI_IP_ADDRESS *ReplyIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *OurPortPtr, + UINT64 LastBlock, + UINT16 Timeout, + IN BOOLEAN DontUseBuffer + ) +/*++ +Routine description: + Read rest of file after successfull M/TFTP request. + +Parameters: + Private := Pointer to PxeBc interface + PacketSize := Pointer to packet size + BufferSizePtr := Pointer to buffer (file) size + Offset := Offset into buffer of next packet + BufferPtr := Pointer to receive buffer + ServerIpPtr := Pointer to TFTP server IP address + ServerPortPtr := Pointer to TFTP server UDP port + ReplyIpPtr := Pointer to TFTP DATA packet destination IP address + OurPortPtr := Pointer to TFTP client UDP port + LastBlock := Last block number received + Timeout := + DontUseBuffer := TRUE == throw away data, just count # of bytes + +Returns: +--*/ +{ + EFI_STATUS Status; + UINT64 BlockNum; + UINT64 BufferSize; + UINTN Retries; + UINTN SaveLen; + UINTN ReplyLen; + + ReplyLen = PacketSize; + BlockNum = LastBlock; + + DEBUG ((EFI_D_INFO, "\nLockStepReceive() PacketSize = %d", PacketSize)); + + if (DontUseBuffer) { + BufferSize = PacketSize; + } else { + BufferSize = *BufferSizePtr - Offset; + BufferPtr += Offset; + } + + while (ReplyLen >= 512 && ReplyLen == PacketSize) { + if (BufferSize < PacketSize) { + ReplyLen = (UINTN) ((BufferSize > 0) ? BufferSize : 0); + } + + SaveLen = ReplyLen; + + // + // write an ack packet and get data - retry up to NUM_ACK_RETRIES on timeout + // + Retries = NUM_ACK_RETRIES; + + do { + ReplyLen = SaveLen; + + Status = SendAckAndGetData ( + Private, + ServerIpPtr, + ServerPortPtr, + ReplyIpPtr, + OurPortPtr, + Timeout, + (UINTN *) &ReplyLen, + BufferPtr, + &BlockNum, + FALSE + ); + + if (!EFI_ERROR (Status) || Status == EFI_BUFFER_TOO_SMALL) { + if (BlockNum == LastBlock) { + DEBUG ((EFI_D_NET, "\nresend")); + // + // a resend - continue + // + Status = EFI_TIMEOUT; + } else if (Private->BigBlkNumFlag) { + if (BlockNum != ++LastBlock) { + DEBUG ((EFI_D_NET, "\nLockStepReceive() Exit #1a")); + // + // not correct blocknum - error + // + return EFI_PROTOCOL_ERROR; + } + } else { + LastBlock = (LastBlock + 1) & 0xFFFF; + if (BlockNum != LastBlock) { + DEBUG ((EFI_D_NET, "\nLockStepReceive() Exit #1b")); + return EFI_PROTOCOL_ERROR; + // + // not correct blocknum - error + // + } + } + } + } while (Status == EFI_TIMEOUT && --Retries); + + if (EFI_ERROR (Status)) { + if (Status != EFI_BUFFER_TOO_SMALL) { + SendError (Private, ServerIpPtr, ServerPortPtr, OurPortPtr); + } + + return Status; + } + + if (DontUseBuffer) { + BufferSize += ReplyLen; + } else { + BufferPtr += ReplyLen; + BufferSize -= ReplyLen; + } + } + // + // while (ReplyLen == PacketSize); + // + if (DontUseBuffer) { + if (BufferSizePtr != NULL) { + *BufferSizePtr = (BufferSize - PacketSize); + } + } else { + *BufferSizePtr -= BufferSize; + } + + /* Send ACK of last packet. */ + ReplyLen = 0; + + SendAckAndGetData ( + Private, + ServerIpPtr, + ServerPortPtr, + ReplyIpPtr, + OurPortPtr, + Timeout, + (UINTN *) &ReplyLen, + BufferPtr, + &BlockNum, + TRUE + ); + + return EFI_SUCCESS; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// some literals +// +STATIC UINT8 Mode[] = MODE_BINARY; +STATIC UINT8 BlockSizeOp[] = OP_BLKSIZE; +STATIC UINT8 TsizeOp[] = OP_TFRSIZE; +STATIC UINT8 OverwriteOp[] = OP_OVERWRITE; +STATIC UINT8 BigBlkNumOp[] = OP_BIGBLKNUM; +STATIC EFI_PXE_BASE_CODE_UDP_PORT TftpRequestPort = TFTP_OPEN_PORT; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +UINT8 * +FindOption ( + UINT8 *OptionPtr, + INTN OpLen, + UINT8 *OackPtr, + INTN OackSize + ) +/*++ +Routine description: + Check TFTP OACK packet for option. + +Parameters: + OptionPtr := Pointer to option string to find + OpLen := Length of option string + OackPtr := Pointer to OACK data + OackSize := Length of OACK data + +Returns: + Pointer to value field if option found or NULL if not found. +--*/ +{ + if ((OackSize -= OpLen) <= 0) { + return NULL; + } + + do { + if (!CompareMem (OackPtr, OptionPtr, OpLen)) { + return OackPtr + OpLen; + } + + ++OackPtr; + } while (--OackSize); + + return NULL; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +#define BKSZOP 1 // block size +#define TSIZEOP 2 // transfer size +#define OVERWRITEOP 4 // overwrite +#define BIGBLKNUMOP 8 // big block numbers +STATIC +EFI_STATUS +TftpRwReq ( + UINT16 Req, + UINT16 Options, + PXE_BASECODE_DEVICE *Private, + EFI_IP_ADDRESS *ServerIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ServerPortPtr, + EFI_PXE_BASE_CODE_UDP_PORT *OurPortPtr, + UINT8 *FilenamePtr, + UINTN *PacketSizePtr, + VOID *Buffer + ) +/*++ +Routine description: + Send TFTP RRQ/WRQ packet. + +Parameters: + Req := Type of request to send + Options := One or more of the #define values above + Private := Pointer to PxeBc interface + ServerIpPtr := Pointer to TFTP server IP address + ServerPortPtr := Pointer to TFTP server UDP port + OurPortPtr := Pointer to TFTP client UDP port + FilenamePtr := Pointer to TFTP file or directory name + PacketSizePtr := Pointer to block size + Buffer := + +Returns: +--*/ +{ + union { + UINT8 Data[514]; + struct Tftpv4Req ReqStr; + } *u; + + UINT16 OpFlags; + INTN Len; + INTN TotalLen; + UINT8 *Ptr; + + if (*OurPortPtr == 0) { + OpFlags = EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT; + } else { + OpFlags = EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT; + } + // + // build the basic request - opcode, filename, mode + // + u = Buffer; + u->ReqStr.OpCode = HTONS (Req); + TotalLen = sizeof (Mode) + sizeof (u->ReqStr.OpCode) + (Len = 1 + AsciiStrLen ((CHAR8 *)FilenamePtr)); + + CopyMem (u->ReqStr.FileName, FilenamePtr, Len); + Ptr = (UINT8 *) (u->ReqStr.FileName + Len); + + CopyMem (Ptr, Mode, sizeof (Mode)); + Ptr += sizeof (Mode); + + if (Options & BKSZOP) { + CopyMem (Ptr, BlockSizeOp, sizeof (BlockSizeOp)); + UtoA10 (*PacketSizePtr, Ptr + sizeof (BlockSizeOp)); + + TotalLen += (Len = 1 + AsciiStrLen ((CHAR8 *)Ptr + sizeof (BlockSizeOp)) + sizeof (BlockSizeOp)); + + Ptr += Len; + } + + if (Options & TSIZEOP) { + CopyMem (Ptr, TsizeOp, sizeof (TsizeOp)); + CopyMem (Ptr + sizeof (TsizeOp), "0", 2); + TotalLen += sizeof (TsizeOp) + 2; + Ptr += sizeof (TsizeOp) + 2; + } + + if (Options & OVERWRITEOP) { + CopyMem (Ptr, OverwriteOp, sizeof (OverwriteOp)); + CopyMem (Ptr + sizeof (OverwriteOp), "1", 2); + TotalLen += sizeof (OverwriteOp) + 2; + Ptr += sizeof (OverwriteOp) + 2; + } + + if (Options & BIGBLKNUMOP) { + CopyMem (Ptr, BigBlkNumOp, sizeof (BigBlkNumOp)); + CopyMem (Ptr + sizeof (BigBlkNumOp), "8", 2); + TotalLen += sizeof (BigBlkNumOp) + 2; + Ptr += sizeof (BigBlkNumOp) + 2; + } + // + // send it + // + return UdpWrite ( + Private, + OpFlags, + ServerIpPtr, + ServerPortPtr, + 0, + 0, + OurPortPtr, + 0, + 0, + (UINTN *) &TotalLen, + u + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +TftpRwReqwResp ( + UINT16 Req, + UINT16 Options, + PXE_BASECODE_DEVICE *Private, + VOID *HeaderPtr, + UINTN *PacketSizePtr, + UINTN *ReplyLenPtr, + VOID *BufferPtr, + EFI_IP_ADDRESS *ServerIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ServerPortPtr, + EFI_PXE_BASE_CODE_UDP_PORT *ServerReplyPortPtr, + EFI_PXE_BASE_CODE_UDP_PORT *OurPortPtr, + UINT8 *FilenamePtr, + UINT16 Timeout + ) +/*++ +Routine description: + Start TFTP session. Issue request and wait for response. + Retry three times on error. If failed using options, + retry three times w/o options on error. + +Parameters: + Req := TFTP request type + Options := TFTP option bits + Private := Pointer to PxeBc interface + HeaderPtr := + PacketSizePtr := Pointer to block size + ReplyLenPtr := + BufferPtr := + ServerIpPtr := Pointer to TFTP server IP address + ServerPortPtr := Pointer to TFTP server UDP port + ServerReplyPortPtr := + OurPortPtr := Pointer to TFTP client UDP Port + FilenamePtr := Pointer to file or directory name + Timeout := + +Returns: +--*/ +{ + EFI_STATUS Status; + UINTN SaveReplyLen; + INTN Retries; + UINT8 Buffer[514]; + + SaveReplyLen = *ReplyLenPtr; + Retries = 3; + Private->BigBlkNumFlag = FALSE; + *OurPortPtr = 0; + // + // generate random + // + do { + if (*OurPortPtr != 0) { + if (++ *OurPortPtr == 0) { + *OurPortPtr = PXE_RND_PORT_LOW; + } + } + // + // send request from our Ip = StationIp + // + if ((Status = TftpRwReq ( + Req, + Options, + Private, + ServerIpPtr, + ServerPortPtr, + OurPortPtr, + FilenamePtr, + PacketSizePtr, + Buffer + )) != EFI_SUCCESS) { + DEBUG ( + (EFI_D_WARN, + "\nTftpRwReqwResp() Exit #1 %xh (%r)", + Status, + Status) + ); + + return Status; + } + // + // read reply to our Ip = StationIp + // + *ReplyLenPtr = SaveReplyLen; + + Status = TftpUdpRead ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT, + HeaderPtr, + ReplyLenPtr, + BufferPtr, + ServerIpPtr, + ServerReplyPortPtr, + 0, + OurPortPtr, + Timeout + ); + } while (Status == EFI_TIMEOUT && --Retries); + + if (!Options || Status != EFI_TFTP_ERROR) { + DEBUG ( + (EFI_D_WARN, + "\nTftpRwReqwResp() Exit #2 %xh (%r)", + Status, + Status) + ); + return Status; + } + + Status = TftpRwReqwResp ( + Req, + 0, + Private, + HeaderPtr, + PacketSizePtr, + ReplyLenPtr, + BufferPtr, + ServerIpPtr, + ServerPortPtr, + ServerReplyPortPtr, + OurPortPtr, + FilenamePtr, + Timeout + ); + + DEBUG ((EFI_D_WARN, "\nTftpRwReqwResp() Exit #3 %xh (%r)", Status, Status)); + + return Status; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// mtftp listen +// read on mcast ip, cport, from sport, for data packet +// returns success if gets multicast last packet or all up to last block +// if not missing, then finished +// +STATIC +EFI_STATUS +MtftpListen ( + PXE_BASECODE_DEVICE *Private, + UINT64 *BufferSizePtr, + UINT8 *BufferPtr, + EFI_IP_ADDRESS *ServerIpPtr, + EFI_PXE_BASE_CODE_MTFTP_INFO *MtftpInfoPtr, + UINT64 *StartBlockPtr, + UINTN *NumMissedPtr, + UINT16 TransTimeout, + UINT16 ListenTimeout, + UINT64 FinalBlock, + IN BOOLEAN DontUseBuffer + ) +/*++ +Routine description: + Listen for MTFTP traffic and save desired packets. + +Parameters: + Private := Pointer to PxeBc interface + BufferSizePtr := + BufferPtr := + ServerIpPtr := Pointer to TFTP server IP address + MtftpInfoPtr := Pointer to MTFTP session information + StartBlockPtr := IN=first block we are looking for OUT=first block received + NumMissedPtr := Number of blocks missed + TransTimeout := + ListenTimeout := + FinalBlock := + DontUseBuffer := TRUE == throw packets away, just count bytes + +Returns: +--*/ +{ + EFI_STATUS Status; + struct Tftpv4Ack Header; + UINT64 Offset; + UINT64 BlockNum; + UINT64 LastBlockNum; + UINT64 BufferSize; + UINTN NumMissed; + UINTN PacketSize; + UINTN SaveReplyLen; + UINTN ReplyLen; + UINT16 Timeout; + + LastBlockNum = *StartBlockPtr; + Timeout = ListenTimeout; + *NumMissedPtr = 0; + PacketSize = 0; + BufferSize = *BufferSizePtr; + ReplyLen = MAX_TFTP_PKT_SIZE;; + + // + // receive + // + do { + if ((SaveReplyLen = ReplyLen) > BufferSize) { + SaveReplyLen = (UINTN) BufferSize; + } + + /* %%TBD - add big block number support */ + + // + // get data - loop on resends + // + do { + ReplyLen = SaveReplyLen; + + if ((Status = TftpUdpRead ( + Private, + 0, + &Header, + &ReplyLen, + BufferPtr, + ServerIpPtr, + &MtftpInfoPtr->SPort, + &MtftpInfoPtr->MCastIp, + &MtftpInfoPtr->CPort, + Timeout + )) != EFI_SUCCESS) { + return Status; + } + // + // make sure a data packet + // + if (Header.OpCode != HTONS (TFTP_DATA)) { + return EFI_PROTOCOL_ERROR; + } + } while ((BlockNum = NTOHS (Header.BlockNum)) == LastBlockNum); + + // + // make sure still going up + // + if (LastBlockNum > BlockNum) { + return EFI_PROTOCOL_ERROR; + } + + if (BlockNum - LastBlockNum > 0xFFFFFFFF) { + return EFI_PROTOCOL_ERROR; + } else { + NumMissed = (UINTN) (BlockNum - LastBlockNum - 1); + } + + LastBlockNum = BlockNum; + + // + // if first time through, some reinitialization + // + if (!PacketSize) { + *StartBlockPtr = BlockNum; + PacketSize = ReplyLen; + Timeout = TransTimeout; + } else { + *NumMissedPtr = (UINT16) (*NumMissedPtr + NumMissed); + } + // + // if missed packets, update start block, + // etc. and move packet to proper place in buffer + // + if (NumMissed) { + *StartBlockPtr = BlockNum; + if (!DontUseBuffer) { + Offset = NumMissed * PacketSize; + CopyMem (BufferPtr + Offset, BufferPtr, ReplyLen); + BufferPtr += Offset; + BufferSize -= Offset; + } + } + + if (!DontUseBuffer) { + BufferPtr += ReplyLen; + BufferSize -= ReplyLen; + } + } while (ReplyLen == PacketSize && BlockNum != FinalBlock); + + *BufferSizePtr = BufferSize; + + return EFI_SUCCESS; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +MtftpOpen ( + PXE_BASECODE_DEVICE * Private, + UINT64 *BufferSizePtr, + UINT8 *BufferPtr, + UINTN *PacketSizePtr, + EFI_IP_ADDRESS * ServerIpPtr, + UINT8 *FilenamePtr, + EFI_PXE_BASE_CODE_MTFTP_INFO * MtftpInfoPtr, + UINT8 *CompletionStatusPtr, +#define GOTUNI 1 +#define GOTMULTI 2 + IN BOOLEAN DontUseBuffer + ) +/*++ +Routine description: + Open MTFTP session. + +Parameters: + Private := Pointer to PxeBc interface + BufferSizePtr := IN=buffer size OUT=transfer size + BufferPtr := + PacketSizePtr := + ServerIpPtr := + FilenamePtr := + MtftpInfoPtr := + CompletionStatusPtr := + DontUseBuffer := + +Returns: +// mtftp open session +// return code EFI_SUCCESS +// and *CompletionStatusPtr = GOTUNI | GOTMULTI means done +// and *CompletionStatusPtr = GOTMULTI means got first two multicast packets, use listen for rest +// and *CompletionStatusPtr = 0 means did not get first two multicast packets, use listen for all +// (do not get = GOTUNI - returns NO_DATA go will go to TFTP session) +--*/ +{ + EFI_STATUS Status; + EFI_IP_ADDRESS OurReplyIp; + struct Tftpv4Ack Header; + INTN ReplyLen; + INTN Retries; + UINT8 *BufferPtr2; + UINT8 TmpBuf[514]; + + Retries = NUM_MTFTP_OPEN_RETRIES; + BufferPtr2 = BufferPtr; + *PacketSizePtr = (UINTN) (EFI_MIN (*BufferSizePtr, MAX_TFTP_PKT_SIZE)); + + do { + // + // send a read request + // + *CompletionStatusPtr = 0; + + if ((Status = TftpRwReq ( + TFTP_RRQ, + 0, + Private, + ServerIpPtr, + &MtftpInfoPtr->SPort, + &MtftpInfoPtr->CPort, + FilenamePtr, + PacketSizePtr, + TmpBuf + )) != EFI_SUCCESS) { + return Status; + } + + for (;;) { + // + // read reply + // + ZeroMem (&OurReplyIp, Private->IpLength); + ReplyLen = *PacketSizePtr; + + if ((Status = TftpUdpRead ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER, + &Header, + (UINTN *) &ReplyLen, + BufferPtr2, + ServerIpPtr, + &MtftpInfoPtr->SPort, + &OurReplyIp, + &MtftpInfoPtr->CPort, + MtftpInfoPtr->TransmitTimeout + )) == EFI_SUCCESS) { + // + // check for first data packet + // + if (Header.OpCode != HTONS (TFTP_DATA)) { + return EFI_PROTOCOL_ERROR; + } + // + // check block num + // + if (Header.BlockNum != HTONS (1)) { + // + // it's not first + // if we are not the primary client, + // we probably got first and now second + // multicast but no unicast, so + // *CompletionStatusPtr = GOTMULTI - if this is + // the second, can just go on to listen + // starting with 2 as the last block + // received + // + if (Header.BlockNum != HTONS (2)) { + // + // not second + // + *CompletionStatusPtr = 0; + } + + return Status; + } + + // + // now actual + // + *PacketSizePtr = ReplyLen; + // + // see if a unicast data packet + // + if (!CompareMem ( + &OurReplyIp, + &Private->EfiBc.Mode->StationIp, + Private->IpLength + )) { + *CompletionStatusPtr |= GOTUNI; + // + // it is + // if already got multicast packet, + // got em both + // + if (*CompletionStatusPtr & GOTMULTI) { + break; + } + } else if (!CompareMem ( + &OurReplyIp, + &MtftpInfoPtr->MCastIp, + Private->IpLength + )) { + // + // otherwise see if a multicast data packet + // + *CompletionStatusPtr |= GOTMULTI; + // + // it is + // got first - bump pointer so that if + // second multi comes along, we're OK + // + if (!DontUseBuffer) { + BufferPtr2 = (UINT8 *) BufferPtr + ReplyLen; + } + // + // if already got unicast packet, + // got em both + // + if (*CompletionStatusPtr & GOTUNI) { + break; + } + } else { + // + // else protocol error + // + return EFI_PROTOCOL_ERROR; + } + } else if (Status == EFI_TIMEOUT) { + // + // bad return code - if timed out, retry + // + break; + } else { + // + // else just bad - failed MTFTP open + // + return Status; + } + } + } while (Status == EFI_TIMEOUT && --Retries); + + if (Status != EFI_SUCCESS) { + // + // open failed + // + return Status; + } + // + // got em both - go into receive mode + // routine to read rest of file after a successful open (TFTP or MTFTP) + // sends ACK and gets next data packet until short packet arrives, + // then sends ACK and (hopefully) times out + // + return LockStepReceive ( + Private, + (UINT16) ReplyLen, + BufferSizePtr, + ReplyLen, + BufferPtr, + ServerIpPtr, + &MtftpInfoPtr->SPort, + &MtftpInfoPtr->MCastIp, + &MtftpInfoPtr->CPort, + 1, + MtftpInfoPtr->TransmitTimeout, + DontUseBuffer + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +MtftpDownload ( + PXE_BASECODE_DEVICE *Private, + UINT64 *BufferSizePtr, + UINT8 *BufferPtr, + EFI_IP_ADDRESS *ServerIpPtr, + UINT8 *FilenamePtr, + EFI_PXE_BASE_CODE_MTFTP_INFO *MtftpInfoPtr, + IN BOOLEAN DontUseBuffer + ) +/*++ +Routine description: +// mtftp +// loop +// listen +// if did not get any packets, try MTFTP open +// if got all packets, return +// compute listen timeout and loop + +Parameters: + Private := Pointer to PxeBc interface + BufferSizePtr := + BufferPtr := + ServerIpPtr := + FilenamePtr := + MtftpInfoPtr := + DontUseBuffer := + +Returns: +--*/ +{ + EFI_PXE_BASE_CODE_IP_FILTER Filter; + EFI_STATUS Status; + UINT64 StartBlock; + UINT64 LastBlock; + UINT64 LastStartBlock; + UINT64 BufferSize; + UINTN Offset; + UINTN NumMissed; + UINT16 TransTimeout; + UINT16 ListenTimeout; + UINT8 *BufferPtrLocal; + + TransTimeout = MtftpInfoPtr->TransmitTimeout; + ListenTimeout = MtftpInfoPtr->ListenTimeout; + LastBlock = 0; + LastStartBlock = 0; + Offset = 0; + + Filter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST; + Filter.IpCnt = 2; + CopyMem (&Filter.IpList[0], &Private->EfiBc.Mode->StationIp, sizeof (EFI_IP_ADDRESS)); + CopyMem (&Filter.IpList[1], &MtftpInfoPtr->MCastIp, sizeof (EFI_IP_ADDRESS)); + + if ((Status = IpFilter (Private, &Filter)) != EFI_SUCCESS) { + return Status; + } + + for (;;) { + StartBlock = LastStartBlock; + BufferSize = *BufferSizePtr - Offset; + + if (DontUseBuffer) { + // + // overwrie the temp buf + // + BufferPtrLocal = BufferPtr; + } else { + BufferPtrLocal = BufferPtr + Offset; + + } + // + // special !!! do not leave enabled in saved version on Source Safe + // Following code put in in order to create a special version for regression + // test of MTFTP server to make sure it handles mulitple opens correctly. + // This code should NOT be enabled normally. + // +#ifdef SpecialNowaitVersion +#pragma message ("This is special version for MTFTP regression test") + if (StartBlock || !LastBlock) +#endif + if (((Status = MtftpListen ( + Private, + &BufferSize, + BufferPtrLocal, + ServerIpPtr, + MtftpInfoPtr, + &StartBlock, + &NumMissed, + TransTimeout, + ListenTimeout, + LastBlock, + DontUseBuffer + )) != EFI_SUCCESS) && (Status != EFI_TIMEOUT)) { + return Status; + // + // failed + // + } + // + // if none were received, start block is not reset + // + if (StartBlock == LastStartBlock) { + UINT8 CompStat; + + // + // timed out with none received - try MTFTP open + // + if ((Status = MtftpOpen ( + Private, + BufferSizePtr, + BufferPtr, + &Offset, + ServerIpPtr, + FilenamePtr, + MtftpInfoPtr, + &CompStat, + DontUseBuffer + )) != EFI_SUCCESS) { + // + // open failure - try TFTP + // + return Status; + } + // + // return code EFI_SUCCESS + // and *CompletionStatusPtr = GOTUNI | GOTMULTI means done + // and *CompletionStatusPtr = GOTMULTI means got first two multicast packets, use listen for rest + // and *CompletionStatusPtr = 0 means did not get first two multicast packets, use listen for all + // (do not get = GOTUNI - returns NO_DATA go will go to TFTP session) + // + if (CompStat == (GOTUNI | GOTMULTI)) { + // + // finished - got it all + // + return Status; + } + + if (CompStat) { + // + // offset is two packet lengths + // + Offset <<= 1; + // + // last block received + // + LastStartBlock = 2; + } else { + Offset = 0; + LastStartBlock = 0; + } + + ListenTimeout = TransTimeout; + continue; + } + // + // did we get the last block + // + if (Status == EFI_SUCCESS) { + // + // yes - set the file size if this was first time + // + if (!LastBlock) { + *BufferSizePtr -= BufferSize; + } + // + // if buffer was too small, finished + // + if (!DontUseBuffer) { + return EFI_BUFFER_TOO_SMALL; + } + // + // if we got them all, finished + // + if (!NumMissed && StartBlock == LastStartBlock + 1) { + return Status; + } + // + // did not get them all - set last block + // + LastBlock = (UINT16) (StartBlock - 1); + } + // + // compute listen timeout + // + ListenTimeout = (UINT16) ((NumMissed > MtftpInfoPtr->ListenTimeout) ? 0 : (MtftpInfoPtr->ListenTimeout - NumMissed)); + + // + // reset + // + Offset = 0; + LastStartBlock = 0; + } +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +TftpInfo ( + PXE_BASECODE_DEVICE *Private, + UINT64 *BufferSizePtr, + EFI_IP_ADDRESS *ServerIpPtr, + EFI_PXE_BASE_CODE_UDP_PORT SrvPort, + UINT8 *FilenamePtr, + UINTN *PacketSizePtr + ) +/*++ +Routine description: +// TFTP info request routine +// send read request with block size and transfer size options +// get reply +// send error to terminate session +// if OACK received, set info + +Parameters: + Private := + BufferSizePtr := + ServerIpPtr := + SrvPort := + FilenamePtr := + PacketSizePtr := + +Returns: +--*/ +{ + EFI_PXE_BASE_CODE_UDP_PORT OurPort; + EFI_PXE_BASE_CODE_UDP_PORT ServerReplyPort; + EFI_STATUS Status; + UINT64 BlockNum; + UINTN Offset; + UINTN ReplyLen; + UINT8 *Ptr; + + union { + struct Tftpv4Oack OAck2Ptr; + struct Tftpv4Ack Ack2Ptr; + struct Tftpv4Data Datastr; + } u; + + OurPort = 0; + ServerReplyPort = 0; + ReplyLen = sizeof (u.Datastr.Data); + + // + // send a write request with the blocksize option - + // sets our IP and port - and receive reply - sets his port + // will retry operation up to 3 times if no response, + // and will retry without options on an error reply + // + if ((Status = TftpRwReqwResp ( + TFTP_RRQ, + /* BIGBLKNUMOP | */BKSZOP | TSIZEOP, + Private, + &u, + PacketSizePtr, + &ReplyLen, + u.Datastr.Data, + ServerIpPtr, + &SrvPort, + &ServerReplyPort, + &OurPort, + FilenamePtr, + REQ_RESP_TIMEOUT + )) != EFI_SUCCESS) { + DEBUG ((EFI_D_WARN, "\nTftpInfo() Exit #1")); + return Status; + } + // + // check for good OACK + // + if (u.OAck2Ptr.OpCode == HTONS (TFTP_OACK)) { + // + // now parse it for options + // bigblk# + // + Ptr = FindOption ( + BigBlkNumOp, + sizeof (BigBlkNumOp), + u.OAck2Ptr.OpAck[0].Option, + ReplyLen + sizeof (u.Ack2Ptr.BlockNum) + ); + + if (Ptr != NULL) { + if (AtoU (Ptr) == 8) { + Private->BigBlkNumFlag = TRUE; + } else { + return EFI_PROTOCOL_ERROR; + } + } + // + // blksize + // + Ptr = FindOption ( + BlockSizeOp, + sizeof (BlockSizeOp), + u.OAck2Ptr.OpAck[0].Option, + ReplyLen += sizeof (u.Ack2Ptr.BlockNum) + ); + + *PacketSizePtr = (Ptr) ? AtoU (Ptr) : 512; + + // + // tsize + // + Ptr = FindOption ( + TsizeOp, + sizeof (TsizeOp), + u.OAck2Ptr.OpAck[0].Option, + ReplyLen + ); + + if (Ptr != NULL) { + *BufferSizePtr = AtoU64 (Ptr); + + // + // teminate session with error + // + SendError (Private, ServerIpPtr, &ServerReplyPort, &OurPort); + + return EFI_SUCCESS; + } + + Offset = 0; + BlockNum = 0; + } else { + // + // if MTFTP get filesize, return unsupported + // + if (SrvPort != TftpRequestPort) { + SendError (Private, ServerIpPtr, &ServerReplyPort, &OurPort); + DEBUG ((EFI_D_WARN, "\nTftpInfo() Exit #3")); + return EFI_UNSUPPORTED; + } + + Offset = ReplyLen; + // + // last block received + // + BlockNum = 1; + } + // + // does not support the option - do a download with no buffer + // + *BufferSizePtr = 0; + + Status = LockStepReceive ( + Private, + (UINT16) ReplyLen, + BufferSizePtr, + Offset, + (UINT8 *) &u, + ServerIpPtr, + &ServerReplyPort, + &Private->EfiBc.Mode->StationIp, + &OurPort, + BlockNum, + ACK_TIMEOUT, + TRUE + ); + + if (Status != EFI_SUCCESS) { + DEBUG ((EFI_D_WARN, "\nTftpInfo() LockStepReceive() == %Xh", Status)); + } + + if (Status != EFI_BUFFER_TOO_SMALL) { + return Status; + } + + return EFI_SUCCESS; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +TftpDownload ( + PXE_BASECODE_DEVICE *Private, + UINT64 *BufferSizePtr, + UINT8 *BufferPtr, + EFI_IP_ADDRESS *ServerIpPtr, + UINT8 *FilenamePtr, + UINTN *PacketSizePtr, + EFI_PXE_BASE_CODE_UDP_PORT SrvPort, + UINT16 Req, + IN BOOLEAN DontUseBuffer + ) +/*++ +Routine description: +// tftp read session +// send read request +// [get OACK +// send ACK] +// loop +// get data +// send ACK +// while data size is max + +Parameters: + Private := + BufferSizePtr := + BufferPtr := + ServerIpPtr := + FilenamePtr := + PacketSizePtr := + SrvPort := + Req := + DontUseBuffer := + +Returns: +--*/ +{ + EFI_PXE_BASE_CODE_UDP_PORT OurPort; + EFI_PXE_BASE_CODE_UDP_PORT ServerReplyPort; + EFI_STATUS Status; + UINT64 Offset; + UINT64 BlockNum; + UINTN ReplyLen; + UINT8 *Ptr; + + union { + struct Tftpv4Ack Ack2Ptr; + struct Tftpv4Oack OAck2Ptr; + struct Tftpv4Data Data; + struct Tftpv4Ack8 Ack8Ptr; + struct Tftpv4Data8 Data8; + } U; + + OurPort = 0; + ServerReplyPort = 0; + ReplyLen = (UINTN) ((*BufferSizePtr > 0xFFFF) ? 0xFFFF : *BufferSizePtr); + + // + // send a read request with the blocksize option - sets our IP and port + // - and receive reply - sets his port will retry operation up to 3 + // times if no response, and will retry without options on an error + // reply + // + if ((Status = TftpRwReqwResp ( + Req, + /* BIGBLKNUMOP | */BKSZOP, + Private, + &U, + PacketSizePtr, + &ReplyLen, + BufferPtr, + ServerIpPtr, + &SrvPort, + &ServerReplyPort, + &OurPort, + FilenamePtr, + REQ_RESP_TIMEOUT + )) != EFI_SUCCESS) { + DEBUG ((EFI_D_WARN, "\nTftpDownload() Exit #1 %xh (%r)", Status, Status)); + return Status; + } + // + // check for OACK + // + if (U.OAck2Ptr.OpCode == HTONS (TFTP_OACK)) { + // + // get the OACK + // + CopyMem (U.Data.Data, BufferPtr, ReplyLen); + + Ptr = FindOption ( + BigBlkNumOp, + sizeof (BigBlkNumOp), + U.OAck2Ptr.OpAck[0].Option, + ReplyLen + sizeof (U.Ack2Ptr.BlockNum) + ); + + if (Ptr != NULL) { + if (AtoU (Ptr) == 8) { + Private->BigBlkNumFlag = TRUE; + } else { + return EFI_PROTOCOL_ERROR; + } + } + // + // now parse it for blocksize option + // + Ptr = FindOption ( + BlockSizeOp, + sizeof (BlockSizeOp), + U.OAck2Ptr.OpAck[0].Option, + ReplyLen += sizeof (U.Ack2Ptr.BlockNum) + ); + + ReplyLen = (Ptr != NULL) ? AtoU (Ptr) : 512; + + Offset = 0; + // + // last block received + // + BlockNum = 0; + } else if (U.Ack2Ptr.OpCode != HTONS (TFTP_DATA) || U.Ack2Ptr.BlockNum != HTONS (1)) { + // + // or data + // + DEBUG ((EFI_D_WARN, "\nTftpDownload() Exit #2 %xh (%r)", Status, Status)); + + return EFI_PROTOCOL_ERROR; + } else { + // + // got good data packet + // + Offset = ReplyLen; + // + // last block received + // + BlockNum = 1; + } + + if (PacketSizePtr != NULL) { + *PacketSizePtr = ReplyLen; + } + // + // routine to read rest of file after a successful open (TFTP or MTFTP) + // sends ACK and gets next data packet until short packet arrives, then sends + // ACK and (hopefully) times out + // if first packet has been read, BufferPtr and BufferSize must reflect fact + // + Status = LockStepReceive ( + Private, + ReplyLen, + BufferSizePtr, + Offset, + BufferPtr, + ServerIpPtr, + &ServerReplyPort, + &Private->EfiBc.Mode->StationIp, + &OurPort, + BlockNum, + ACK_TIMEOUT, + DontUseBuffer + ); + + if (Status != EFI_SUCCESS) { + DEBUG ((EFI_D_WARN, "\nTftpDownload() Exit #3 %xh (%r)", Status, Status)); + + if (Status == EFI_BUFFER_TOO_SMALL) { + Status = TftpInfo ( + Private, + BufferSizePtr, + ServerIpPtr, + SrvPort, + FilenamePtr, + PacketSizePtr + ); + + if (!EFI_ERROR (Status)) { + Status = EFI_BUFFER_TOO_SMALL; + } + } + } + + return Status; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +TftpUpload ( + PXE_BASECODE_DEVICE *Private, + UINT64 *BufferSizePtr, + VOID *BufferPtr, + EFI_IP_ADDRESS *ServerIpPtr, + UINT8 *FilenamePtr, + UINTN *PacketSizePtr, + BOOLEAN Overwrite + ) +/*++ +Routine description: +// tftp write session +// send write request +// get OACK or ACK +// loop +// send min (rest of data, max data packet) +// get ACK +// while data size is max + +Parameters: + Private := + BufferSizePtr := + BufferPtr := + ServerIpPtr := + FilenamePtr := + PacketSizePtr := + Overwrite := + +Returns: +--*/ +{ + struct Tftpv4Ack Header; + EFI_PXE_BASE_CODE_UDP_PORT OurPort; + EFI_PXE_BASE_CODE_UDP_PORT ServerReplyPort; + EFI_STATUS Status; + UINT64 BlockNum; + UINT64 TransferSize; + UINTN ReplyLen; + UINTN TransferLen; + UINT16 Options; + UINT8 *Ptr; + + union { + struct Tftpv4Oack OAck2Ptr; + struct Tftpv4Ack Ack2Ptr; + struct Tftpv4Data Datastr; + } u; + + OurPort = 0; + ServerReplyPort = 0; + TransferSize = *BufferSizePtr; + ReplyLen = sizeof (u.Datastr.Data); + Options = (UINT16) ((Overwrite) ? OVERWRITEOP | BKSZOP : BKSZOP); + + // + // send a write request with the blocksize option - sets our IP and port - + // and receive reply - sets his port + // will retry operation up to 3 times if no response, and will retry without + // options on an error reply + // + if ((Status = TftpRwReqwResp ( + TFTP_WRQ, + Options, + Private, + &u, + PacketSizePtr, + &ReplyLen, + u.Datastr.Data, + ServerIpPtr, + &TftpRequestPort, + &ServerReplyPort, + &OurPort, + FilenamePtr, + REQ_RESP_TIMEOUT + )) != EFI_SUCCESS) { + return Status; + } + // + // check for OACK + // + if (u.OAck2Ptr.OpCode == HTONS (TFTP_OACK)) { + // + // parse it for blocksize option + // + Ptr = FindOption ( + BlockSizeOp, + sizeof (BlockSizeOp), + u.OAck2Ptr.OpAck[0].Option, + ReplyLen += sizeof (u.Ack2Ptr.BlockNum) + ); + *PacketSizePtr = (Ptr) ? AtoU (Ptr) : 512; + } + // + // or ACK + // + else if (u.Ack2Ptr.OpCode == HTONS (TFTP_ACK)) { + // + // option was not supported + // + *PacketSizePtr = 512; + } else { + return EFI_PROTOCOL_ERROR; + } + // + // loop + // + Header.OpCode = HTONS (TFTP_DATA); + BlockNum = 1; + Header.BlockNum = HTONS (1); + + do { + UINTN HeaderSize; + INTN Retries; + + Retries = NUM_ACK_RETRIES; + HeaderSize = sizeof (Header); + TransferLen = (UINTN) (EFI_MIN (*PacketSizePtr, TransferSize)); + + // + // write a data packet and get an ack + // + do { + // + // write + // + if ((Status = UdpWrite ( + Private, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT, + ServerIpPtr, + &ServerReplyPort, + 0, + 0, + &OurPort, + &HeaderSize, + &Header, + &TransferLen, + BufferPtr + )) != EFI_SUCCESS) { + return Status; + } + // + // read reply + // + ReplyLen = sizeof (u.Datastr.Data); + + if ((Status = TftpUdpRead ( + Private, + 0, + &u, + &ReplyLen, + u.Datastr.Data, + ServerIpPtr, + &ServerReplyPort, + 0, + &OurPort, + ACK_TIMEOUT + )) == EFI_SUCCESS) { + // + // check for ACK for this data packet + // + if (u.Ack2Ptr.OpCode != HTONS (TFTP_ACK)) { + return EFI_PROTOCOL_ERROR; + } + + if (u.Ack2Ptr.BlockNum != Header.BlockNum) { + // + // not for this packet - continue + // + Status = EFI_TIMEOUT; + } + } + } while (Status == EFI_TIMEOUT && --Retries); + + if (Status != EFI_SUCCESS) { + return Status; + } + + BufferPtr = (VOID *) ((UINT8 *) (BufferPtr) + TransferLen); + TransferSize -= TransferLen; + ++BlockNum; + Header.BlockNum = HTONS ((UINT16) BlockNum); + } while (TransferLen == *PacketSizePtr); + + return EFI_SUCCESS; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +PxeBcMtftp ( + PXE_BASECODE_DEVICE *Private, + IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, + UINT64 *BufferSizePtr, + VOID *BufferPtr, + EFI_IP_ADDRESS *ServerIpPtr, + UINT8 *FilenamePtr, + UINTN *PacketSizePtr, + IN EFI_PXE_BASE_CODE_MTFTP_INFO *MtftpInfoPtr, OPTIONAL + IN BOOLEAN Overwrite, + IN BOOLEAN DontUseBuffer + ) +/*++ +Routine description: + MTFTP API entry point + +Parameters: + Private := + Operation := + BufferSizePtr := + BufferPtr := + ServerIpPtr := + FilenamePtr := + PacketSizePtr := + MtftpInfoPtr := + Overwrite := + DontUseBuffer := + +Returns: + * EFI_INVALID_PARAMETER + * EFI_OUT_OF_RESOURCES + * EFI_BAD_BUFFER_SIZE + * Status is also returned from IpFilter(), TftpInfo(), MtftpDownload(), + * TftpDownload() and TftpUpload(). +--*/ +{ + EFI_PXE_BASE_CODE_IP_FILTER Filter; + EFI_STATUS StatCode; + EFI_STATUS Status; + UINT64 BufferSizeLocal; + UINTN PacketSize; + UINT8 *BufferPtrLocal; + + Filter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP; + Filter.IpCnt = 0; + Filter.reserved = 0; + + /* No error has occurred, yet. */ + Private->EfiBc.Mode->TftpErrorReceived = FALSE; + + /* We must at least have an MTFTP server IP address and + * a pointer to the buffer size. + */ + if (!ServerIpPtr || !BufferSizePtr) { + DEBUG ((EFI_D_WARN, "\nPxeBcMtftp() Exit #1")); + + return EFI_INVALID_PARAMETER; + } + + Private->Function = EFI_PXE_BASE_CODE_FUNCTION_MTFTP; + + // + // make sure filter set to unicast at start + // + if ((StatCode = IpFilter (Private, &Filter)) != EFI_SUCCESS) { + DEBUG ( + (EFI_D_NET, + "\nPxeBcMtftp() Exit IpFilter() == %Xh", + StatCode) + ); + + return StatCode; + } + // + // set unset parms to default values + // + if (!PacketSizePtr) { + *(PacketSizePtr = &PacketSize) = MAX_TFTP_PKT_SIZE; + } + + if (*PacketSizePtr > *BufferSizePtr) { + *PacketSizePtr = (UINTN) *BufferSizePtr; + } + + if (*PacketSizePtr < MIN_TFTP_PKT_SIZE) { + *PacketSizePtr = MIN_TFTP_PKT_SIZE; + } + + if (*PacketSizePtr > BUFFER_ALLOCATE_SIZE) { + *PacketSizePtr = BUFFER_ALLOCATE_SIZE; + } + + if (*PacketSizePtr > MAX_TFTP_PKT_SIZE) { + *PacketSizePtr = MAX_TFTP_PKT_SIZE; + } + + if (Operation == EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE) { + StatCode = TftpInfo ( + Private, + BufferSizePtr, + ServerIpPtr, + TftpRequestPort, + FilenamePtr, + PacketSizePtr + ); + + if (StatCode != EFI_SUCCESS) { + DEBUG ( + (EFI_D_WARN, + "\nPxeBcMtftp() Exit TftpInfo() == %Xh", + StatCode) + ); + } + + return StatCode; + } + + if (Operation == EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE) { + if (!MtftpInfoPtr || !MtftpInfoPtr->SPort) { + DEBUG ((EFI_D_WARN, "\nPxeBcMtftp() Exit #2")); + return EFI_INVALID_PARAMETER; + } else { + StatCode = TftpInfo ( + Private, + BufferSizePtr, + ServerIpPtr, + MtftpInfoPtr->SPort, + FilenamePtr, + PacketSizePtr + ); + + gBS->Stall (10000); + + if (StatCode != EFI_SUCCESS) { + DEBUG ( + (EFI_D_WARN, + "\nPxeBcMtftp() Exit TftpInfo() == %Xh", + StatCode) + ); + } + + return StatCode; + } + } + + if (!BufferPtr && !DontUseBuffer) { + // + // if dontusebuffer is false and no buffer??? + // + DEBUG ((EFI_D_WARN, "\nPxeBcMtftp() Exit #3")); + // + // DontUseBuffer can be true only for read_file operation + // + return EFI_INVALID_PARAMETER; + } + + if (DontUseBuffer) { + Status = gBS->AllocatePool ( + EfiBootServicesData, + BUFFER_ALLOCATE_SIZE, + (VOID **) &BufferPtrLocal + ); + + if (EFI_ERROR (Status) || BufferPtrLocal == NULL) { + DEBUG ((EFI_D_NET, "\nPxeBcMtftp() Exit #4")); + return EFI_OUT_OF_RESOURCES; + } + + BufferSizeLocal = BUFFER_ALLOCATE_SIZE; + } else { + if (!*BufferSizePtr && Operation != EFI_PXE_BASE_CODE_TFTP_WRITE_FILE) { + DEBUG ((EFI_D_WARN, "\nPxeBcMtftp() Exit #5")); + return EFI_BAD_BUFFER_SIZE; + } + + BufferPtrLocal = BufferPtr; + BufferSizeLocal = *BufferSizePtr; + } + + switch (Operation) { + case EFI_PXE_BASE_CODE_MTFTP_READ_FILE: + if (FilenamePtr == NULL || + MtftpInfoPtr == NULL || + MtftpInfoPtr->MCastIp.Addr[0] == 0 || + MtftpInfoPtr->SPort == 0 || + MtftpInfoPtr->CPort == 0 || + MtftpInfoPtr->ListenTimeout == 0 || + MtftpInfoPtr->TransmitTimeout == 0 + ) { + StatCode = EFI_INVALID_PARAMETER; + break; + } + // + // try MTFTP - if fails, drop into TFTP read + // + if ((StatCode = MtftpDownload ( + Private, + &BufferSizeLocal, + BufferPtrLocal, + ServerIpPtr, + FilenamePtr, + MtftpInfoPtr, + DontUseBuffer + )) == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) { + if (BufferSizePtr /* %% !DontUseBuffer */ ) { + *BufferSizePtr = BufferSizeLocal; + } + + break; + } + // + // go back to unicast + // + if ((StatCode = IpFilter (Private, &Filter)) != EFI_SUCCESS) { + break; + } + + /* fall thru */ + case EFI_PXE_BASE_CODE_TFTP_READ_FILE: + if (FilenamePtr == NULL) { + StatCode = EFI_INVALID_PARAMETER; + break; + } + + StatCode = TftpDownload ( + Private, + &BufferSizeLocal, + BufferPtrLocal, + ServerIpPtr, + FilenamePtr, + PacketSizePtr, + TftpRequestPort, + TFTP_RRQ, + DontUseBuffer + ); + + if (StatCode == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) { + if (BufferSizePtr /* !DontUseBuffer */ ) { + *BufferSizePtr = BufferSizeLocal; + } + } + + break; + + case EFI_PXE_BASE_CODE_TFTP_WRITE_FILE: + if (FilenamePtr == NULL || DontUseBuffer) { + // + // not a valid option + // + StatCode = EFI_INVALID_PARAMETER; + break; + } + + StatCode = TftpUpload ( + Private, + BufferSizePtr, + BufferPtr, + ServerIpPtr, + FilenamePtr, + PacketSizePtr, + Overwrite + ); + + if (StatCode != EFI_SUCCESS) { + DEBUG ( + (EFI_D_WARN, + "\nPxeBcMtftp() Exit #6 %xh (%r)", + StatCode, + StatCode) + ); + } + + return StatCode; + + case EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY: + if (FilenamePtr == NULL || DontUseBuffer) { + // + // not a valid option + // + StatCode = EFI_INVALID_PARAMETER; + break; + } + + StatCode = TftpDownload ( + Private, + BufferSizePtr, + BufferPtr, + ServerIpPtr, + FilenamePtr, + PacketSizePtr, + TftpRequestPort, + TFTP_DIR, + DontUseBuffer + ); + + if (StatCode != EFI_SUCCESS) { + DEBUG ( + (EFI_D_WARN, + "\nPxeBcMtftp() Exit #7 %xh (%r)", + StatCode, + StatCode) + ); + } + + return StatCode; + + case EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY: + if (DontUseBuffer) { + StatCode = EFI_INVALID_PARAMETER; + break; + } + + if (MtftpInfoPtr == NULL || !MtftpInfoPtr->SPort) { + DEBUG ( + (EFI_D_WARN, + "\nPxeBcMtftp() Exit #9 %xh (%r)", + EFI_INVALID_PARAMETER, + EFI_INVALID_PARAMETER) + ); + + return EFI_INVALID_PARAMETER; + } + + StatCode = TftpDownload ( + Private, + BufferSizePtr, + BufferPtr, + ServerIpPtr, + (UINT8 *) "/", + PacketSizePtr, + MtftpInfoPtr->SPort, + TFTP_DIR, + DontUseBuffer + ); + + break; + + default: + StatCode = EFI_INVALID_PARAMETER; + } + + if (DontUseBuffer) { + gBS->FreePool (BufferPtrLocal); + } + + if (StatCode != EFI_SUCCESS) { + DEBUG ( + (EFI_D_WARN, + "\nPxeBcMtftp() Exit #8 %xh (%r)", + StatCode, + StatCode) + ); + } + + gBS->Stall (10000); + + return StatCode; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +BcMtftp ( + IN EFI_PXE_BASE_CODE_PROTOCOL * This, + IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, + IN OUT VOID *BufferPtr, + IN BOOLEAN Overwrite, + IN OUT UINT64 *BufferSizePtr, + IN UINTN *BlockSizePtr OPTIONAL, + IN EFI_IP_ADDRESS * ServerIpPtr, + IN UINT8 *FilenamePtr, + IN EFI_PXE_BASE_CODE_MTFTP_INFO * MtftpInfoPtr OPTIONAL, + IN BOOLEAN DontUseBuffer + ) +/*++ +Routine description: + MTFTP API entry point. + +Parameters: + This := + Operation := + BufferPtr := + Overwrite := + BufferSizePtr := + BlockSizePtr := + ServerIpPtr := + FilenamePtr := + MtftpInfoPtr := + DontUseBuffer := + +Returns: + * EFI_INVALID_PARAMETER + * Status is also returned from PxeBcMtftp(); +--*/ +{ + EFI_PXE_BASE_CODE_IP_FILTER Filter; + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + // + // Lock the instance data and make sure started + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + if (This->Mode == NULL || !This->Mode->Started) { + DEBUG ((EFI_D_ERROR, "BC was not started.")); + EfiReleaseLock (&Private->Lock); + return EFI_NOT_STARTED; + } + // + // Issue BC command + // + Filter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP; + Filter.IpCnt = 0; + Filter.reserved = 0; + + DEBUG ((EFI_D_WARN, "\nBcMtftp() Op=%d Buf=%Xh", Operation, BufferPtr)); + + StatCode = PxeBcMtftp ( + Private, + Operation, + BufferSizePtr, + BufferPtr, + ServerIpPtr, + FilenamePtr, + BlockSizePtr, + MtftpInfoPtr, + Overwrite, + DontUseBuffer + ); + + // + // restore to unicast + // + IpFilter (Private, &Filter); + + // + // Unlock the instance data + // + EfiReleaseLock (&Private->Lock); + return StatCode; +} + +/* eof - PxeBcMtftp.c */ diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_udp.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_udp.c new file mode 100644 index 0000000000..ab9d3b794b --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_bc_udp.c @@ -0,0 +1,577 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + pxe_bc_udp.c + +Abstract: + +--*/ + + +#include "bc.h" + +// +// ////////////////////////////////////////////////////////////////////// +// +// Udp Write Routine - called by base code - e.g. TFTP - already locked +// +EFI_STATUS +UdpWrite ( + IN PXE_BASECODE_DEVICE *Private, + IN UINT16 OpFlags, + IN EFI_IP_ADDRESS *DestIpPtr, + IN EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr, + IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL + IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL + IN UINTN *HeaderSizePtr, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN UINTN *BufferSizeptr, + IN VOID *BufferPtr + ) +/*++ +Routine description: + UDP write packet. + +Parameters: + Private := Pointer to PxeBc interface + OpFlags := + DestIpPtr := + DestPortPtr := + GatewayIpPtr := + SrcIpPtr := + SrcPortPtr := + HeaderSizePtr := + HeaderPtr := + BufferSizeptr := + BufferPtr := + +Returns: + EFI_SUCCESS := + EFI_INVALID_PARAMETER := + other := +--*/ +{ + UINTN TotalLength; + UINTN HeaderSize; + EFI_PXE_BASE_CODE_UDP_PORT DefaultSrcPort; + + // + // + // + HeaderSize = (HeaderSizePtr != NULL) ? *HeaderSizePtr : 0; + DefaultSrcPort = 0; + + // + // check parameters + // + if (BufferSizeptr == NULL || + BufferPtr == NULL || + DestIpPtr == NULL || + DestPortPtr == NULL || + (HeaderSizePtr != NULL && *HeaderSizePtr == 0) || + (HeaderSize != 0 && HeaderPtr == NULL) || + (GatewayIpPtr != NULL && !IS_INADDR_UNICAST(GatewayIpPtr)) || + (OpFlags &~(EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT)) + ) { + DEBUG ( + (EFI_D_WARN, + "\nUdpWrite() Exit #1 %xh (%r)", + EFI_INVALID_PARAMETER, + EFI_INVALID_PARAMETER) + ); + + return EFI_INVALID_PARAMETER; + } + + TotalLength = *BufferSizeptr + HeaderSize + sizeof (UDPV4_HEADER); + + if (TotalLength > 0x0000ffff) { + DEBUG ( + (EFI_D_WARN, + "\nUdpWrite() Exit #2 %xh (%r)", + EFI_BAD_BUFFER_SIZE, + EFI_BAD_BUFFER_SIZE) + ); + + return EFI_BAD_BUFFER_SIZE; + } + + if (SrcIpPtr == NULL) { + SrcIpPtr = &Private->EfiBc.Mode->StationIp; + } + + if (SrcPortPtr == NULL) { + SrcPortPtr = &DefaultSrcPort; + OpFlags |= EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT; + } + + if (OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) { + *SrcPortPtr = Private->RandomPort; + + if (++Private->RandomPort == 0) { + Private->RandomPort = PXE_RND_PORT_LOW; + } + } + +#define IpTxBuffer ((IPV4_BUFFER *) Private->TransmitBufferPtr) + // + // build pseudo header and udp header in transmit buffer + // +#define Udpv4Base ((UDPV4_HEADERS *) (IpTxBuffer->u.Data - sizeof (UDPV4_PSEUDO_HEADER))) + + Udpv4Base->Udpv4PseudoHeader.SrcAddr.L = SrcIpPtr->Addr[0]; + Udpv4Base->Udpv4PseudoHeader.DestAddr.L = DestIpPtr->Addr[0]; + Udpv4Base->Udpv4PseudoHeader.Zero = 0; + Udpv4Base->Udpv4PseudoHeader.Protocol = PROT_UDP; + Udpv4Base->Udpv4PseudoHeader.TotalLength = HTONS (TotalLength); + Udpv4Base->Udpv4Header.SrcPort = HTONS (*SrcPortPtr); + Udpv4Base->Udpv4Header.DestPort = HTONS (*DestPortPtr); + Udpv4Base->Udpv4Header.TotalLength = Udpv4Base->Udpv4PseudoHeader.TotalLength; + Udpv4Base->Udpv4Header.Checksum = 0; + + if (HeaderSize != 0) { + CopyMem (IpTxBuffer->u.Udp.Data, HeaderPtr, HeaderSize); + } + + HeaderSize += sizeof (UDPV4_HEADER); + + Udpv4Base->Udpv4Header.Checksum = IpChecksum2 ( + (UINT16 *) Udpv4Base, + HeaderSize + sizeof (UDPV4_PSEUDO_HEADER), + (UINT16 *) BufferPtr, + (UINT16) *BufferSizeptr + ); + + if (Udpv4Base->Udpv4Header.Checksum == 0) { + Udpv4Base->Udpv4Header.Checksum = 0xffff; + // + // transmit zero checksum as ones complement + // + } + + return Ip4Send ( + Private, + OpFlags, + PROT_UDP, + Udpv4Base->Udpv4PseudoHeader.SrcAddr.L, + Udpv4Base->Udpv4PseudoHeader.DestAddr.L, + (GatewayIpPtr) ? GatewayIpPtr->Addr[0] : 0, + HeaderSize, + BufferPtr, + *BufferSizeptr + ); +} +// +// ////////////////////////////////////////////////////////// +// +// BC Udp Write Routine +// +EFI_STATUS +EFIAPI +BcUdpWrite ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 OpFlags, + IN EFI_IP_ADDRESS *DestIpPtr, + IN EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr, + IN EFI_IP_ADDRESS *GatewayIpPtr, OPTIONAL + IN EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL + IN UINTN *HeaderSizePtr, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN UINTN *BufferSizeptr, + IN VOID *BufferPtr + ) +/*++ +Routine description: + UDP write API entry point. + +Parameters: + This := Pointer to PxeBc interface. + OpFlags := + DestIpPtr := + DestPortPtr := + GatewayIpPtr := + SrcIpPtr := + SrcPortPtr := + HeaderSizePtr := + HeaderPtr := + BufferSizeptr := + BufferPtr := + +Returns: + EFI_SUCCESS := + other := +--*/ +{ + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + // + // Lock the instance data and make sure started + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + if (This->Mode == NULL || !This->Mode->Started) { + DEBUG ((EFI_D_ERROR, "BC was not started.")); + EfiReleaseLock (&Private->Lock); + return EFI_NOT_STARTED; + } + + Private->Function = EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE; + + // + // Issue BC command + // + StatCode = UdpWrite ( + Private, + OpFlags, + DestIpPtr, + DestPortPtr, + GatewayIpPtr, + SrcIpPtr, + SrcPortPtr, + HeaderSizePtr, + HeaderPtr, + BufferSizeptr, + BufferPtr + ); + + // + // Unlock the instance data + // + EfiReleaseLock (&Private->Lock); + return StatCode; +} +// +// ///////////////////////////////////////////////////////////////////// +// +// Udp Read Routine - called by base code - e.g. TFTP - already locked +// +EFI_STATUS +UdpRead ( + IN PXE_BASECODE_DEVICE *Private, + IN UINT16 OpFlags, + IN OUT EFI_IP_ADDRESS *DestIpPtr, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPortPtr, OPTIONAL + IN OUT EFI_IP_ADDRESS *SrcIpPtr, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPortPtr, OPTIONAL + IN UINTN *HeaderSizePtr, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN OUT UINTN *BufferSizeptr, + IN VOID *BufferPtr, + EFI_EVENT TimeoutEvent + ) +/*++ +Routine description: + UDP read packet. + +Parameters: + Private := Pointer to PxeBc interface + OpFlags := + DestIpPtr := + DestPortPtr := + SrcIpPtr := + SrcPortPtr := + HeaderSizePtr := + HeaderPtr := + BufferSizeptr := + BufferPtr := + TimeoutEvent := + +Returns: + EFI_SUCCESS := + EFI_INVALID_PARAMETER := + other := +--*/ +{ + EFI_STATUS StatCode; + EFI_IP_ADDRESS TmpSrcIp; + EFI_IP_ADDRESS TmpDestIp; + UINTN BufferSize; + UINTN HeaderSize; + + // + // combination structure of pseudo header/udp header + // +#pragma pack (1) + struct { + UDPV4_PSEUDO_HEADER Udpv4PseudoHeader; + UDPV4_HEADER Udpv4Header; + UINT8 ProtHdr[64]; + } Hdrs; +#pragma pack () + + HeaderSize = (HeaderSizePtr != NULL) ? *HeaderSizePtr : 0; + // + // read [with filtering] + // check parameters + // + if (BufferSizeptr == NULL || + BufferPtr == NULL || + (HeaderSize != 0 && HeaderPtr == NULL) || + (OpFlags &~UDP_FILTER_MASK) + // + // if filtering on a particular IP/Port, need it + // + || + (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP) && SrcIpPtr == NULL) || + (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && SrcPortPtr == NULL) || + (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && DestPortPtr == NULL) + ) { + DEBUG ((EFI_D_INFO, "\nUdpRead() Exit #1 Invalid Parameter")); + return EFI_INVALID_PARAMETER; + } + + // + // in case we loop + // + BufferSize = *BufferSizeptr; + // + // we need source and dest IPs for pseudo header + // + if (SrcIpPtr == NULL) { + SrcIpPtr = &TmpSrcIp; + } + + if (DestIpPtr == NULL) { + DestIpPtr = &TmpDestIp; + CopyMem (&TmpDestIp, &Private->EfiBc.Mode->StationIp, sizeof (TmpDestIp)); + } + +#if SUPPORT_IPV6 + if (Private->EfiBc.Mode->UsingIpv6) { + // + // %%TBD + // + } +#endif + + for (;;) { + *BufferSizeptr = BufferSize; + + StatCode = IpReceive ( + Private, + OpFlags, + SrcIpPtr, + DestIpPtr, + PROT_UDP, + &Hdrs.Udpv4Header, + HeaderSize + sizeof Hdrs.Udpv4Header, + BufferPtr, + BufferSizeptr, + TimeoutEvent + ); + + if (StatCode == EFI_SUCCESS || StatCode == EFI_BUFFER_TOO_SMALL) { + UINT16 SPort; + UINT16 DPort; + + SPort = NTOHS (Hdrs.Udpv4Header.SrcPort); + DPort = NTOHS (Hdrs.Udpv4Header.DestPort); + + // + // do filtering + // + if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT) && *SrcPortPtr != SPort) { + continue; + } + + if (!(OpFlags & EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT) && *DestPortPtr != DPort) { + continue; + } + // + // check checksum + // + if (StatCode == EFI_SUCCESS && Hdrs.Udpv4Header.Checksum) { + Hdrs.Udpv4PseudoHeader.SrcAddr.L = SrcIpPtr->Addr[0]; + Hdrs.Udpv4PseudoHeader.DestAddr.L = DestIpPtr->Addr[0]; + Hdrs.Udpv4PseudoHeader.Zero = 0; + Hdrs.Udpv4PseudoHeader.Protocol = PROT_UDP; + Hdrs.Udpv4PseudoHeader.TotalLength = Hdrs.Udpv4Header.TotalLength; + + if (Hdrs.Udpv4Header.Checksum == 0xffff) { + Hdrs.Udpv4Header.Checksum = 0; + } + + if (IpChecksum2 ( + (UINT16 *) &Hdrs.Udpv4PseudoHeader, + HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader) + sizeof (Hdrs.Udpv4Header), + (UINT16 *) BufferPtr, + *BufferSizeptr + )) { + DEBUG ( + (EFI_D_INFO, + "\nUdpRead() Hdrs.Udpv4PseudoHeader == %Xh", + &Hdrs.Udpv4PseudoHeader) + ); + DEBUG ( + (EFI_D_INFO, + "\nUdpRead() Header size == %d", + HeaderSize + sizeof (Hdrs.Udpv4PseudoHeader)) + ); + DEBUG ( + (EFI_D_INFO, + "\nUdpRead() BufferPtr == %Xh", + BufferPtr) + ); + DEBUG ( + (EFI_D_INFO, + "\nUdpRead() Buffer size == %d", + *BufferSizeptr) + ); + DEBUG ((EFI_D_INFO, "\nUdpRead() Exit #2 Device Error")); + return EFI_DEVICE_ERROR; + } + } + // + // all passed + // + if (SrcPortPtr != NULL) { + *SrcPortPtr = SPort; + } + + if (DestPortPtr != NULL) { + *DestPortPtr = DPort; + } + + if (HeaderSize != 0) { + CopyMem (HeaderPtr, Hdrs.ProtHdr, HeaderSize); + } + } + + switch (StatCode) { + case EFI_SUCCESS: + case EFI_TIMEOUT: + break; + + default: + DEBUG ( + (EFI_D_INFO, + "\nUdpRead() Exit #3 %Xh %r", + StatCode, + StatCode) + ); + } + + return StatCode; + } +} +// +// ////////////////////////////////////////////////////////// +// +// BC Udp Read Routine +// +EFI_STATUS +EFIAPI +BcUdpRead ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 OpFlags, + IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL + IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL + IN UINTN *HeaderSize, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN OUT UINTN *BufferSize, + IN VOID *BufferPtr + ) +/*++ +Routine description: + UDP read API entry point. + +Parameters: + This := Pointer to PxeBc interface. + OpFlags := + DestIpPtr := + DestPortPtr := + SrcIpPtr := + SrcPortPtr := + HeaderSizePtr := + HeaderPtr := + BufferSizeptr := + BufferPtr := + +Returns: + EFI_SUCCESS := + other := +--*/ +{ + EFI_STATUS StatCode; + PXE_BASECODE_DEVICE *Private; + + // + // Lock the instance data and make sure started + // + StatCode = EFI_SUCCESS; + + if (This == NULL) { + DEBUG ((EFI_D_ERROR, "BC *This pointer == NULL")); + return EFI_INVALID_PARAMETER; + } + + Private = CR (This, PXE_BASECODE_DEVICE, EfiBc, PXE_BASECODE_DEVICE_SIGNATURE); + + if (Private == NULL) { + DEBUG ((EFI_D_ERROR, "PXE_BASECODE_DEVICE poiner == NULL")); + return EFI_INVALID_PARAMETER; + } + + EfiAcquireLock (&Private->Lock); + + if (This->Mode == NULL || !This->Mode->Started) { + DEBUG ((EFI_D_ERROR, "BC was not started.")); + EfiReleaseLock (&Private->Lock); + return EFI_NOT_STARTED; + } + + Private->Function = EFI_PXE_BASE_CODE_FUNCTION_UDP_READ; + + // + // Issue BC command + // + StatCode = UdpRead ( + Private, + OpFlags, + DestIp, + DestPort, + SrcIp, + SrcPort, + HeaderSize, + HeaderPtr, + BufferSize, + BufferPtr, + 0 + ); + + // + // Unlock the instance data and return + // + EfiReleaseLock (&Private->Lock); + return StatCode; +} + +/* eof - pxe_bc_udp.c */ diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_loadfile.c b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_loadfile.c new file mode 100644 index 0000000000..8897bc726e --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/pxe_loadfile.c @@ -0,0 +1,1697 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + pxe_loadfile.c + +Abstract: + An implementation of the load file protocol for network devices. + +--*/ + + +#include "bc.h" + +#define DO_MENU (EFI_SUCCESS) +#define NO_MENU (DO_MENU + 1) +#define LOCAL_BOOT (EFI_ABORTED) +#define AUTO_SELECT (NO_MENU) + +#define NUMBER_ROWS 25 // we set to mode 0 +#define MAX_MENULIST 23 + +#define Ctl(x) (0x1F & (x)) + +typedef union { + DHCPV4_OP_STRUCT *OpPtr; + PXE_BOOT_MENU_ENTRY *CurrentMenuItemPtr; + PXE_OP_DISCOVERY_CONTROL *DiscCtlOpStr; + PXE_OP_BOOT_MENU *MenuPtr; + UINT8 *BytePtr; +} UNION_PTR; + + +STATIC +EFI_PXE_BASE_CODE_CALLBACK_STATUS +EFIAPI +bc_callback ( + IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL * This, + IN EFI_PXE_BASE_CODE_FUNCTION Function, + IN BOOLEAN Received, + IN UINT32 PacketLength, + IN EFI_PXE_BASE_CODE_PACKET * PacketPtr OPTIONAL + ) +/*++ + +Routine Description: + + PxeBc callback routine for status updates and aborts. + +Arguments: + + This - Pointer to PxeBcCallback interface + Function - PxeBc function ID# + Received - Receive/transmit flag + PacketLength - Length of received packet (0 == idle callback) + PacketPtr - Pointer to received packet (NULL == idle callback) + +Returns: + + EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE - + EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT - + +--*/ +{ + STATIC UINTN Propeller; + + EFI_INPUT_KEY Key; + UINTN Row; + UINTN Col; + + Propeller = 0; + // + // Resolve Warning 4 unreferenced parameter problem + // + This = This; + + // + // Check for user abort. + // + if (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key) == EFI_SUCCESS) { + if (!Key.ScanCode) { + if (Key.UnicodeChar == Ctl ('c')) { + return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT; + } + } else if (Key.ScanCode == SCAN_ESC) { + return EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT; + } + } + // + // Do nothing if this is a receive. + // + if (Received) { + return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE; + } + // + // The display code is only for these functions. + // + switch (Function) { + case EFI_PXE_BASE_CODE_FUNCTION_MTFTP: + // + // If this is a transmit and not a M/TFTP open request, + // return now. Do not print a dot for each M/TFTP packet + // that is sent, only for the open packets. + // + if (PacketLength != 0 && PacketPtr != NULL) { + if (PacketPtr->Raw[0x1C] != 0x00 || PacketPtr->Raw[0x1D] != 0x01) { + return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE; + } + } + + break; + + case EFI_PXE_BASE_CODE_FUNCTION_DHCP: + case EFI_PXE_BASE_CODE_FUNCTION_DISCOVER: + break; + + default: + return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE; + } + // + // Display routines + // + if (PacketLength != 0 && PacketPtr != NULL) { + // + // Display a '.' when a packet is transmitted. + // + AsciiPrint ("."); + } else if (PacketLength == 0 && PacketPtr == NULL) { + // + // Display a propeller when waiting for packets if at + // least 200 ms have passed. + // + Row = gST->ConOut->Mode->CursorRow; + Col = gST->ConOut->Mode->CursorColumn; + + AsciiPrint ("%c", "/-\\|"[Propeller]); + gST->ConOut->SetCursorPosition (gST->ConOut, Col, Row); + + Propeller = (Propeller + 1) & 3; + } + + return EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE; +} + +STATIC EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL _bc_callback = { + EFI_PXE_BASE_CODE_CALLBACK_INTERFACE_REVISION, + &bc_callback +}; + +STATIC +VOID +PrintIpv4 ( + UINT8 *Ptr + ) +/*++ + +Routine Description: + + Display an IPv4 address in dot notation. + +Arguments: + + Ptr - Pointer to IPv4 address. + +Returns: + + None + +--*/ +{ + if (Ptr != NULL) { + AsciiPrint ("%d.%d.%d.%d", Ptr[0], Ptr[1], Ptr[2], Ptr[3]); + } +} + +STATIC +VOID +ShowMyInfo ( + IN PXE_BASECODE_DEVICE *Private + ) +/*++ + +Routine Description: + + Display client and server IP information. + +Arguments: + + Private - Pointer to PxeBc interface + +Returns: + + None + +--*/ +{ + EFI_PXE_BASE_CODE_MODE *PxeBcMode; + UINTN Index; + + // + // Do nothing if a NULL pointer is passed in. + // + if (Private == NULL) { + return ; + } + // + // Get pointer to PXE BaseCode mode structure + // + PxeBcMode = Private->EfiBc.Mode; + + // + // Display client IP address + // + AsciiPrint ("\rCLIENT IP: "); + PrintIpv4 (PxeBcMode->StationIp.v4.Addr); + + // + // Display subnet mask + // + AsciiPrint (" MASK: "); + PrintIpv4 (PxeBcMode->SubnetMask.v4.Addr); + + // + // Display DHCP and proxyDHCP IP addresses + // + if (PxeBcMode->ProxyOfferReceived) { + AsciiPrint ("\nDHCP IP: "); + PrintIpv4 (((DHCPV4_OP_SERVER_IP *) DHCPV4_ACK_BUFFER.OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip.Addr); + + AsciiPrint (" PROXY IP: "); + PrintIpv4 (((DHCPV4_OP_SERVER_IP *) PXE_OFFER_BUFFER.OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip.Addr); + } else { + AsciiPrint (" DHCP IP: "); + PrintIpv4 (((DHCPV4_OP_SERVER_IP *) DHCPV4_ACK_BUFFER.OpAdds.PktOptAdds[OP_DHCP_SERVER_IP_IX - 1])->Ip.Addr); + } + // + // Display gateway IP addresses + // + for (Index = 0; Index < PxeBcMode->RouteTableEntries; ++Index) { + if ((Index % 3) == 0) { + AsciiPrint ("\r\nGATEWAY IP:"); + } + + AsciiPrint (" "); + PrintIpv4 (PxeBcMode->RouteTable[Index].GwAddr.v4.Addr); + AsciiPrint (" "); + } + + AsciiPrint ("\n"); +} + +STATIC +EFI_STATUS +DoPrompt ( + PXE_BASECODE_DEVICE *Private, + PXE_OP_BOOT_PROMPT *BootPromptPtr + ) +/*++ + +Routine Description: + + Display prompt and wait for input. + +Arguments: + + Private - Pointer to PxeBc interface + BootPromptPtr - Pointer to PXE boot prompt option + +Returns: + + AUTO_SELECT - + DO_MENU - + NO_MENU - + LOCAL_BOOT - + +--*/ +{ + EFI_STATUS Status; + EFI_EVENT TimeoutEvent; + EFI_EVENT SecondsEvent; + INT32 SecColumn; + INT32 SecRow; + UINT8 SaveChar; + UINT8 SecsLeft; + + // + // if auto select, just get right to it + // + if (BootPromptPtr->Timeout == PXE_BOOT_PROMPT_AUTO_SELECT) { + return AUTO_SELECT; + } + // + // if no timeout, go directly to display of menu + // + if (BootPromptPtr->Timeout == PXE_BOOT_PROMPT_NO_TIMEOUT) { + return DO_MENU; + } + // + // + // + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &TimeoutEvent + ); + + if (EFI_ERROR (Status)) { + return DO_MENU; + } + + Status = gBS->SetTimer ( + TimeoutEvent, + TimerRelative, + BootPromptPtr->Timeout * 10000000 + 100000 + ); + + if (EFI_ERROR (Status)) { + gBS->CloseEvent (TimeoutEvent); + return DO_MENU; + } + // + // + // + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER, + EFI_TPL_CALLBACK, + NULL, + NULL, + &SecondsEvent + ); + + if (EFI_ERROR (Status)) { + gBS->CloseEvent (TimeoutEvent); + return DO_MENU; + } + + Status = gBS->SetTimer ( + SecondsEvent, + TimerPeriodic, + 10000000 + ); /* 1 second */ + + if (EFI_ERROR (Status)) { + gBS->CloseEvent (SecondsEvent); + gBS->CloseEvent (TimeoutEvent); + return DO_MENU; + } + // + // display the prompt + // IMPORTANT! This prompt is an ASCII character string that may + // not be terminated with a NULL byte. + // + SaveChar = BootPromptPtr->Prompt[BootPromptPtr->Header.Length - 1]; + BootPromptPtr->Prompt[BootPromptPtr->Header.Length - 1] = 0; + + AsciiPrint ("%a ", BootPromptPtr->Prompt); + BootPromptPtr->Prompt[BootPromptPtr->Header.Length - 1] = SaveChar; + + // + // wait until time expires or selection made - menu or local + // + SecColumn = gST->ConOut->Mode->CursorColumn; + SecRow = gST->ConOut->Mode->CursorRow; + SecsLeft = BootPromptPtr->Timeout; + + gST->ConOut->SetCursorPosition (gST->ConOut, SecColumn, SecRow); + AsciiPrint ("(%d) ", SecsLeft); + + // + // set the default action to be AUTO_SELECT + // + Status = AUTO_SELECT; + + while (EFI_ERROR (gBS->CheckEvent (TimeoutEvent))) { + EFI_INPUT_KEY Key; + + if (!EFI_ERROR (gBS->CheckEvent (SecondsEvent))) { + --SecsLeft; + gST->ConOut->SetCursorPosition (gST->ConOut, SecColumn, SecRow); + AsciiPrint ("(%d) ", SecsLeft); + } + + if (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key) == EFI_NOT_READY) { + UINT8 Buffer[512]; + UINTN BufferSize; + EFI_STATUS Status; + + BufferSize = sizeof Buffer; + + Status = Private->EfiBc.UdpRead ( + &Private->EfiBc, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT | + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT, + NULL, /* dest ip */ + NULL, /* dest port */ + NULL, /* src ip */ + NULL, /* src port */ + NULL, /* hdr size */ + NULL, /* hdr ptr */ + &BufferSize, + Buffer + ); + + continue; + } + + if (Key.ScanCode == 0) { + switch (Key.UnicodeChar) { + case Ctl ('c'): + Status = LOCAL_BOOT; + break; + + case Ctl ('m'): + case 'm': + case 'M': + Status = DO_MENU; + break; + + default: + continue; + } + } else { + switch (Key.ScanCode) { + case SCAN_F8: + Status = DO_MENU; + break; + + case SCAN_ESC: + Status = LOCAL_BOOT; + break; + + default: + continue; + } + } + + break; + } + + gBS->CloseEvent (SecondsEvent); + gBS->CloseEvent (TimeoutEvent); + + gST->ConOut->SetCursorPosition (gST->ConOut, SecColumn, SecRow); + AsciiPrint (" "); + + return Status; +} + +STATIC +VOID +PrintMenuItem ( + PXE_BOOT_MENU_ENTRY *MenuItemPtr + ) +/*++ + +Routine Description: + + Display one menu item. + +Arguments: + + MenuItemPtr - Pointer to PXE menu item option. + +Returns: + + None + +--*/ +{ + UINT8 Length; + UINT8 SaveChar; + + Length = (UINT8) EFI_MIN (70, MenuItemPtr->DataLen); + SaveChar = MenuItemPtr->Data[Length]; + + MenuItemPtr->Data[Length] = 0; + AsciiPrint (" %a\n", MenuItemPtr->Data); + MenuItemPtr->Data[Length] = SaveChar; +} + +STATIC +EFI_STATUS +DoMenu ( + PXE_BASECODE_DEVICE *Private, + DHCP_RECEIVE_BUFFER *RxBufferPtr + ) +/*++ + +Routine Description: + + Display and process menu. + +Arguments: + + Private - Pointer to PxeBc interface + RxBufferPtr - Pointer to receive buffer + +Returns: + + NO_MENU - + LOCAL_BOOT - + +--*/ +{ + PXE_OP_DISCOVERY_CONTROL *DiscoveryControlPtr; + PXE_BOOT_MENU_ENTRY *MenuItemPtrs[MAX_MENULIST]; + EFI_STATUS Status; + UNION_PTR Ptr; + UINTN SaveNumRte; + UINTN TopRow; + UINTN MenuLth; + UINTN NumMenuItems; + UINTN Index; + UINTN Longest; + UINTN Selected; + UINT16 Type; + UINT16 Layer; + BOOLEAN Done; + + Selected = 0; + Layer = 0; + + DEBUG ((EFI_D_WARN, "\nDoMenu() Enter.")); + + /* see if we have a menu/prompt */ + if (!(RxBufferPtr->OpAdds.Status & DISCOVER_TYPE)) { + DEBUG ( + (EFI_D_WARN, + "\nDoMenu() No menu/prompt info. OpAdds.Status == %xh ", + RxBufferPtr->OpAdds.Status) + ); + + return NO_MENU; + } + + DiscoveryControlPtr = (PXE_OP_DISCOVERY_CONTROL *) RxBufferPtr->OpAdds.PxeOptAdds[VEND_PXE_DISCOVERY_CONTROL_IX - 1]; + + // + // if not USE_BOOTFILE or no bootfile given, must have menu stuff + // + if ((DiscoveryControlPtr->ControlBits & USE_BOOTFILE) && RxBufferPtr->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]) { + DEBUG ((EFI_D_WARN, "\nDoMenu() DHCP w/ bootfile. ")); + return NO_MENU; + } + // + // do prompt & menu if necessary + // + Status = DoPrompt (Private, (PXE_OP_BOOT_PROMPT *) RxBufferPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_PROMPT_IX - 1]); + + if (Status == LOCAL_BOOT) { + DEBUG ((EFI_D_WARN, "\nDoMenu() DoPrompt() returned LOCAL_BOOT. ")); + + return Status; + } + + Ptr.BytePtr = (UINT8 *) RxBufferPtr->OpAdds.PxeOptAdds[VEND_PXE_BOOT_MENU_IX - 1]; + + MenuLth = Ptr.MenuPtr->Header.Length; + Ptr.CurrentMenuItemPtr = Ptr.MenuPtr->MenuItem; + + // + // build menu items array + // + for (Longest = NumMenuItems = Index = 0; Index < MenuLth && NumMenuItems <= MAX_MENULIST;) { + UINTN lth; + + lth = Ptr.CurrentMenuItemPtr->DataLen + sizeof (*Ptr.CurrentMenuItemPtr) - sizeof (Ptr.CurrentMenuItemPtr->Data); + + MenuItemPtrs[NumMenuItems++] = Ptr.CurrentMenuItemPtr; + + if (lth > Longest) { + // + // check if too long + // + if ((Longest = lth) > 70 + (sizeof (*Ptr.CurrentMenuItemPtr) - sizeof (Ptr.CurrentMenuItemPtr->Data))) { + Longest = 70 + (sizeof (*Ptr.CurrentMenuItemPtr) - sizeof (Ptr.CurrentMenuItemPtr->Data)); + } + } + + Index += lth; + Ptr.BytePtr += lth; + } + + if (Status != AUTO_SELECT) { + UINT8 BlankBuf[75]; + + SetMem (BlankBuf, sizeof BlankBuf, ' '); + BlankBuf[Longest + 5 - (sizeof (*Ptr.CurrentMenuItemPtr) - sizeof (Ptr.CurrentMenuItemPtr->Data))] = 0; + AsciiPrint ("\n"); + + // + // now put up menu + // + for (Index = 0; Index < NumMenuItems; ++Index) { + PrintMenuItem (MenuItemPtrs[Index]); + } + + TopRow = gST->ConOut->Mode->CursorRow - NumMenuItems; + + // + // now wait for a selection + // + Done = FALSE; + do { + // + // highlight selection + // + EFI_INPUT_KEY Key; + UINTN NewSelected; + + NewSelected = Selected; + + // + // highlight selected row + // + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY) + ); + gST->ConOut->SetCursorPosition (gST->ConOut, 0, TopRow + Selected); + + AsciiPrint (" --->%a\r", BlankBuf); + + PrintMenuItem (MenuItemPtrs[Selected]); + gST->ConOut->SetAttribute ( + gST->ConOut, + EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK) + ); + gST->ConOut->SetCursorPosition (gST->ConOut, 0, TopRow + NumMenuItems); + + // + // wait for a keystroke + // + while (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key) == EFI_NOT_READY) { + UINT8 TmpBuf[512]; + UINTN TmpBufLen; + + TmpBufLen = sizeof TmpBuf; + + Private->EfiBc.UdpRead ( + &Private->EfiBc, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT | + EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT, + NULL, /* dest ip */ + NULL, /* dest port */ + NULL, /* src ip */ + NULL, /* src port */ + NULL, /* hdr size */ + NULL, /* hdr ptr */ + &TmpBufLen, + TmpBuf + ); + } + + if (!Key.ScanCode) { + switch (Key.UnicodeChar) { + case Ctl ('c'): + Key.ScanCode = SCAN_ESC; + break; + + case Ctl ('j'): /* linefeed */ + case Ctl ('m'): /* return */ + Done = TRUE; + break; + + case Ctl ('i'): /* tab */ + case ' ': + case 'd': + case 'D': + Key.ScanCode = SCAN_DOWN; + break; + + case Ctl ('h'): /* backspace */ + case 'u': + case 'U': + Key.ScanCode = SCAN_UP; + break; + + default: + Key.ScanCode = 0; + } + } + + switch (Key.ScanCode) { + case SCAN_LEFT: + case SCAN_UP: + if (NewSelected) { + --NewSelected; + } + + break; + + case SCAN_DOWN: + case SCAN_RIGHT: + if (++NewSelected == NumMenuItems) { + --NewSelected; + } + + break; + + case SCAN_PAGE_UP: + case SCAN_HOME: + NewSelected = 0; + break; + + case SCAN_PAGE_DOWN: + case SCAN_END: + NewSelected = NumMenuItems - 1; + break; + + case SCAN_ESC: + return LOCAL_BOOT; + } + + /* unhighlight last selected row */ + gST->ConOut->SetCursorPosition (gST->ConOut, 5, TopRow + Selected); + + AsciiPrint ("%a\r", BlankBuf); + + PrintMenuItem (MenuItemPtrs[Selected]); + + Selected = NewSelected; + } while (!Done); + } + + SaveNumRte = Private->EfiBc.Mode->RouteTableEntries; + + Type = NTOHS (MenuItemPtrs[Selected]->Type); + + if (Type == 0) { + DEBUG ((EFI_D_WARN, "\nDoMenu() Local boot selected. ")); + return LOCAL_BOOT; + } + + AsciiPrint ("Discover"); + + Status = Private->EfiBc.Discover ( + &Private->EfiBc, + Type, + &Layer, + (BOOLEAN) (Private->EfiBc.Mode->BisSupported && Private->EfiBc.Mode->BisDetected), + 0 + ); + + if (EFI_ERROR (Status)) { + AsciiPrint ("\r \r"); + + DEBUG ( + (EFI_D_WARN, + "\nDoMenu() Return w/ %xh (%r).", + Status, + Status) + ); + + return Status; + } + + AsciiPrint ("\rBOOT_SERVER_IP: "); + PrintIpv4 ((UINT8 *) &Private->ServerIp); + + for (Index = SaveNumRte; Index < Private->EfiBc.Mode->RouteTableEntries; ++Index) { + if ((Index % 3) == 0) { + AsciiPrint ("\r\nGATEWAY IP:"); + } + + AsciiPrint (" "); + PrintIpv4 ((UINT8 *) &Private->EfiBc.Mode->RouteTable[Index].GwAddr); + AsciiPrint (" "); + } + + AsciiPrint ("\n"); + + DEBUG ((EFI_D_WARN, "\nDoMenu() Return w/ EFI_SUCCESS. ")); + + return EFI_SUCCESS; +} + +STATIC +UINT16 +GetValue ( + DHCPV4_OP_STRUCT *OpPtr + ) +/*++ + +Routine Description: + + Get value 8- or 16-bit value from DHCP option. + +Arguments: + + OpPtr - Pointer to DHCP option + +Returns: + + Value from DHCP option + +--*/ +{ + if (OpPtr->Header.Length == 1) { + return OpPtr->Data[0]; + } else { + return NTOHS (OpPtr->Data); + } +} + +STATIC +UINT8 * +_PxeBcFindOpt ( + UINT8 *BufferPtr, + UINTN BufferLen, + UINT8 OpCode + ) +/*++ + +Routine Description: + + Locate opcode in buffer. + +Arguments: + + BufferPtr - Pointer to buffer + BufferLen - Length of buffer + OpCode - Option number + +Returns: + + Pointer to opcode, may be NULL + +--*/ +{ + if (BufferPtr == NULL) { + return NULL; + } + + while (BufferLen != 0) { + if (*BufferPtr == OpCode) { + return BufferPtr; + } + + switch (*BufferPtr) { + case OP_END: + return NULL; + + case OP_PAD: + ++BufferPtr; + --BufferLen; + continue; + } + + if ((UINTN) BufferLen <= (UINTN) 2 + BufferPtr[1]) { + return NULL; + } + + BufferLen -= 2 + BufferPtr[1]; + BufferPtr += 2 + BufferPtr[1]; + } + + return NULL; +} + +UINT8 * +PxeBcFindDhcpOpt ( + EFI_PXE_BASE_CODE_PACKET *PacketPtr, + UINT8 OpCode + ) +/*++ + +Routine Description: + + Find option in packet + +Arguments: + + PacketPtr - Pointer to packet + OpCode - option number + +Returns: + + Pointer to option in packet + +--*/ +{ + UINTN PacketLen; + UINT8 Overload; + UINT8 *OptionBufferPtr; + + // + // + // + PacketLen = 380; + Overload = 0; + + // + // Figure size of DHCP option space. + // + OptionBufferPtr = _PxeBcFindOpt ( + PacketPtr->Dhcpv4.DhcpOptions, + 380, + OP_DHCP_MAX_MESSAGE_SZ + ); + + if (OptionBufferPtr != NULL) { + if (OptionBufferPtr[1] == 2) { + UINT16 n; + + CopyMem (&n, &OptionBufferPtr[2], 2); + PacketLen = HTONS (n); + + if (PacketLen < sizeof (EFI_PXE_BASE_CODE_DHCPV4_PACKET)) { + PacketLen = 380; + } else { + PacketLen -= (PacketPtr->Dhcpv4.DhcpOptions - &PacketPtr->Dhcpv4.BootpOpcode) + 28; + } + } + } + // + // Look for option overloading. + // + OptionBufferPtr = _PxeBcFindOpt ( + PacketPtr->Dhcpv4.DhcpOptions, + PacketLen, + OP_DHCP_OPTION_OVERLOAD + ); + + if (OptionBufferPtr != NULL) { + if (OptionBufferPtr[1] == 1) { + Overload = OptionBufferPtr[2]; + } + } + // + // Look for caller's option. + // + OptionBufferPtr = _PxeBcFindOpt ( + PacketPtr->Dhcpv4.DhcpOptions, + PacketLen, + OpCode + ); + + if (OptionBufferPtr != NULL) { + return OptionBufferPtr; + } + + if (Overload & OVLD_FILE) { + OptionBufferPtr = _PxeBcFindOpt (PacketPtr->Dhcpv4.BootpBootFile, 128, OpCode); + + if (OptionBufferPtr != NULL) { + return OptionBufferPtr; + } + } + + if (Overload & OVLD_SRVR_NAME) { + OptionBufferPtr = _PxeBcFindOpt (PacketPtr->Dhcpv4.BootpSrvName, 64, OpCode); + + if (OptionBufferPtr != NULL) { + return OptionBufferPtr; + } + } + + return NULL; +} + +STATIC +EFI_STATUS +DownloadFile ( + IN PXE_BASECODE_DEVICE *Private, + IN OUT UINT64 *BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Download file into buffer + +Arguments: + + Private - Pointer to PxeBc interface + BufferSize - pointer to size of download buffer + Buffer - Pointer to buffer + +Returns: + + EFI_BUFFER_TOO_SMALL - + EFI_NOT_FOUND - + EFI_PROTOCOL_ERROR - + +--*/ +{ + EFI_PXE_BASE_CODE_MTFTP_INFO MtftpInfo; + EFI_PXE_BASE_CODE_TFTP_OPCODE OpCode; + DHCP_RECEIVE_BUFFER *RxBuf; + EFI_STATUS Status; + UINTN BlockSize; + + RxBuf = (DHCP_RECEIVE_BUFFER *) Private->BootServerReceiveBuffer; + BlockSize = 0x8000; + + DEBUG ((EFI_D_WARN, "\nDownloadFile() Enter.")); + + if (Buffer == NULL || *BufferSize == 0 || *BufferSize < Private->FileSize) { + if (Private->FileSize != 0) { + *BufferSize = Private->FileSize; + return EFI_BUFFER_TOO_SMALL; + } + + AsciiPrint ("\nTSize"); + + OpCode = EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE; + } else if (RxBuf->OpAdds.Status & WfM11a_TYPE) { + OpCode = EFI_PXE_BASE_CODE_MTFTP_READ_FILE; + + ZeroMem (&MtftpInfo, sizeof MtftpInfo); + + *(IPV4_ADDR *) &MtftpInfo.MCastIp = *(IPV4_ADDR *) RxBuf->OpAdds.PxeOptAdds[VEND_PXE_MTFTP_IP - 1]->Data; + + CopyMem ( + &MtftpInfo.CPort, + RxBuf->OpAdds.PxeOptAdds[VEND_PXE_MTFTP_CPORT - 1]->Data, + sizeof MtftpInfo.CPort + ); + + CopyMem ( + &MtftpInfo.SPort, + RxBuf->OpAdds.PxeOptAdds[VEND_PXE_MTFTP_SPORT - 1]->Data, + sizeof MtftpInfo.SPort + ); + + MtftpInfo.ListenTimeout = GetValue (RxBuf->OpAdds.PxeOptAdds[VEND_PXE_MTFTP_TMOUT - 1]); + + MtftpInfo.TransmitTimeout = GetValue (RxBuf->OpAdds.PxeOptAdds[VEND_PXE_MTFTP_DELAY - 1]); + + AsciiPrint ("\nMTFTP"); + } else { + AsciiPrint ("\nTFTP"); + + OpCode = EFI_PXE_BASE_CODE_TFTP_READ_FILE; + } + + Private->FileSize = 0; + + RxBuf->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]->Data[RxBuf->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]->Header.Length] = 0; + + Status = Private->EfiBc.Mtftp ( + &Private->EfiBc, + OpCode, + Buffer, + FALSE, + BufferSize, + &BlockSize, + &Private->ServerIp, + (UINT8 *) RxBuf->OpAdds.PktOptAdds[OP_DHCP_BOOTFILE_IX - 1]->Data, + &MtftpInfo, + FALSE + ); + + if (Status != EFI_SUCCESS && Status != EFI_BUFFER_TOO_SMALL) { + DEBUG ((EFI_D_WARN, "\nDownloadFile() Exit #1 %Xh", Status)); + return Status; + } + + if (sizeof (UINTN) < sizeof (UINT64) && *BufferSize > 0xFFFFFFFF) { + Private->FileSize = 0xFFFFFFFF; + } else { + Private->FileSize = (UINTN) *BufferSize; + } + + if (OpCode == EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE) { + DEBUG ((EFI_D_WARN, "\nDownloadFile() Exit #2")); + return EFI_BUFFER_TOO_SMALL; + } + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_WARN, "\nDownloadFile() Exit #3 %Xh", Status)); + return Status; + } + + if (Private->EfiBc.Mode->BisSupported && Private->EfiBc.Mode->BisDetected && Private->EfiBc.Mode->PxeBisReplyReceived) { + UINT64 CredentialLen; + UINTN BlockSize; + UINT8 CredentialFilename[256]; + UINT8 *op; + VOID *CredentialBuffer; + + // + // Get name of credential file. It may be in the BOOTP + // bootfile field or a DHCP option. + // + ZeroMem (CredentialFilename, sizeof CredentialFilename); + + op = PxeBcFindDhcpOpt (&Private->EfiBc.Mode->PxeBisReply, OP_DHCP_BOOTFILE); + + if (op != NULL) { + if (op[1] == 0) { + /* No credential filename */ + return EFI_NOT_FOUND; + } + + CopyMem (CredentialFilename, &op[2], op[1]); + } else { + if (Private->EfiBc.Mode->PxeBisReply.Dhcpv4.BootpBootFile[0] == 0) { + /* No credential filename */ + return EFI_NOT_FOUND; + } + + CopyMem (CredentialFilename, &op[2], 128); + } + // + // Get size of credential file. It may be available as a + // DHCP option. If not, use the TFTP get file size. + // + CredentialLen = 0; + + op = PxeBcFindDhcpOpt (&Private->EfiBc.Mode->PxeBisReply, OP_BOOT_FILE_SZ); + + if (op != NULL) { + /* + * This is actually the size of the credential file + * buffer. The actual credential file size will be + * returned when we download the file. + */ + if (op[1] == 2) { + UINT16 n; + + CopyMem (&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 + // + AsciiPrint ("\nCLIENT MAC ADDR: "); + + { + UINTN Index; + UINTN hlen; + + hlen = SnpMode->HwAddressSize; + + for (Index = 0; Index < hlen; ++Index) { + AsciiPrint ("%02x ", SnpMode->CurrentAddress.Addr[Index]); + } + } + + AsciiPrint ("\nDHCP"); + + Status = Private->EfiBc.Dhcp (&Private->EfiBc, TRUE); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_WARN, "\nLoadfileStart() Exit BC.Dhcp() == %Xh", Status)); + AsciiPrint ("\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; + + AsciiPrint ("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; + } + + AsciiPrint ("\nPXE-E05: Download buffer is smaller than requested file.\n"); + break; + + case EFI_DEVICE_ERROR: /* 7 */ + AsciiPrint ("\nPXE-E07: Network device error. Check network connection.\n"); + break; + + case EFI_OUT_OF_RESOURCES: /* 9 */ + AsciiPrint ("\nPXE-E09: Could not allocate I/O buffers.\n"); + break; + + case EFI_NO_MEDIA: /* 12 */ + AsciiPrint ("\nPXE-E12: Could not detect network connection. Check cable.\n"); + break; + + case EFI_NO_RESPONSE: /* 16 */ + AsciiPrint ("\nPXE-E16: Valid PXE offer not received.\n"); + break; + + case EFI_TIMEOUT: /* 18 */ + AsciiPrint ("\nPXE-E18: Timeout. Server did not respond.\n"); + break; + + case EFI_ABORTED: /* 21 */ + AsciiPrint ("\nPXE-E21: Remote boot cancelled.\n"); + break; + + case EFI_ICMP_ERROR: /* 22 */ + AsciiPrint ("\nPXE-E22: Client received ICMP error from server.\n"); + + if (LoadfilePtr->Private->EfiBc.Mode == NULL) { + break; + } + + if (!LoadfilePtr->Private->EfiBc.Mode->IcmpErrorReceived) { + break; + } + + AsciiPrint ( + "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 */ + AsciiPrint ("Net unreachable"); + break; + + case 0x01: /* host unreachable */ + AsciiPrint ("Host unreachable"); + break; + + case 0x02: /* protocol unreachable */ + AsciiPrint ("Protocol unreachable"); + break; + + case 0x03: /* port unreachable */ + AsciiPrint ("Port unreachable"); + break; + + case 0x04: /* Fragmentation needed */ + AsciiPrint ("Fragmentation needed"); + break; + + case 0x05: /* Source route failed */ + AsciiPrint ("Source route failed"); + break; + } + + break; + } + + AsciiPrint ("\n"); + + break; + + case EFI_TFTP_ERROR: /* 23 */ + AsciiPrint ("\nPXE-E23: Client received TFTP error from server.\n"); + + if (LoadfilePtr->Private->EfiBc.Mode == NULL) { + break; + } + + if (LoadfilePtr->Private->EfiBc.Mode->TftpErrorReceived) { + AsciiPrint ( + "PXE-E98: Code: %xh %a\n", + LoadfilePtr->Private->EfiBc.Mode->TftpError.ErrorCode, + LoadfilePtr->Private->EfiBc.Mode->TftpError.ErrorString + ); + } + + break; + + default: + AsciiPrint ("\nPXE-E99: Unexpected network error: %xh\n", Status); + } + + LoadfilePtr->Private->EfiBc.Stop (&LoadfilePtr->Private->EfiBc); + + return Status; +} diff --git a/EdkModulePkg/Universal/Network/PxeBc/Dxe/tftp.h b/EdkModulePkg/Universal/Network/PxeBc/Dxe/tftp.h new file mode 100644 index 0000000000..3cc0724e9c --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeBc/Dxe/tftp.h @@ -0,0 +1,153 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + tftp.h + +Abstract: + +--*/ + +#ifndef __TFTP_H__ +#define __TFTP_H__ + +// +// Definitions for trivial file transfer protocol functionality with IP v4 +// Per RFC 1350, July 1992 and RFC 2347, 8, and 9, May 1998 +// +#pragma pack(1) +// +// max and min packet sizes +// (all data packets in transmission except last) +// +#define MAX_TFTP_PKT_SIZE (BUFFER_ALLOCATE_SIZE - 512) +#define MIN_TFTP_PKT_SIZE 512 + +// +// TFTPv4 OpCodes +// +#define TFTP_RRQ 1 // read request +#define TFTP_WRQ 2 // write request +#define TFTP_DATA 3 // data +#define TFTP_ACK 4 // acknowledgement +#define TFTP_ERROR 5 // error packet +#define TFTP_OACK 6 // option acknowledge +#define TFTP_DIR 7 // read directory request +#define TFTP_DATA8 8 +#define TFTP_ACK8 9 + +// +// request packet (read or write) +// Fields shown (except file name) are not to be referenced directly, +// since their placement is variable within a request packet. +// All are null terminated case insensitive ascii strings. +// +struct Tftpv4Req { + UINT16 OpCode; // TFTP Op code + UINT8 FileName[2]; // file name + UINT8 Mode[2]; // "netascii" or "octet" + struct { // optionally, one or more option requests + UINT8 Option[2]; // option name + UINT8 Value[2]; // value requested + } OpReq[1]; +}; + +// +// modes +// +#define MODE_ASCII "netascii" +#define MODE_BINARY "octet" + +// +// option strings +// +#define OP_BLKSIZE "blksize" // block size option +#define OP_TIMEOUT "timeout" // time to wait before retransmitting +#define OP_TFRSIZE "tsize" // total transfer size option +#define OP_OVERWRITE "overwrite" // overwrite file option +#define OP_BIGBLKNUM "bigblk#" // big block number +// See RFC 2347, 8, and 9 for more information on TFTP options +// option acknowledge packet (optional) +// options not acknowledged are rejected +// +struct Tftpv4Oack { + UINT16 OpCode; // TFTP Op code + struct { // optionally, one or more option acknowledgements + UINT8 Option[2]; // option name (of those requested) + UINT8 Value[2]; // value acknowledged + } OpAck[1]; +}; + +// +// acknowledge packet +// +struct Tftpv4Ack { + UINT16 OpCode; // TFTP Op code + UINT16 BlockNum; +}; + +// +// data packet +// +struct Tftpv4Data { + struct Tftpv4Ack Header; + UINT8 Data[512]; +}; + +// +// big block number ack packet +// +struct Tftpv4Ack8 { + UINT16 OpCode; + UINT64 BlockNum; +}; + +// +// big block number data packet +// +struct Tftpv4Data8 { + struct Tftpv4Ack8 Header; + UINT8 Data[506]; +}; + +// +// error packet +// +struct Tftpv4Error { + UINT16 OpCode; // TFTP Op code + UINT16 ErrCode; // error code + UINT8 ErrMsg[1]; // error message (nul terminated) +}; + +#pragma pack() +// +// error codes +// +#define TFTP_ERR_UNDEF 0 // Not defined, see error message (if any). +#define TFTP_ERR_NOT_FOUND 1 // File not found. +#define TFTP_ERR_ACCESS 2 // Access violation. +#define TFTP_ERR_FULL 3 // Disk full or allocation exceeded. +#define TFTP_ERR_ILLEGAL 4 // Illegal TFTP operation. +#define TFTP_ERR_BAD_ID 5 // Unknown transfer ID. +#define TFTP_ERR_EXISTS 6 // File already exists. +#define TFTP_ERR_NO_USER 7 // No such user. +#define TFTP_ERR_OPTION 8 // Option negotiation termination +// +// some defines +// +#define REQ_RESP_TIMEOUT 5 // Wait five seconds for request response. +#define ACK_TIMEOUT 4 // Wait four seconds for ack response. +#define NUM_ACK_RETRIES 3 +#define NUM_MTFTP_OPEN_RETRIES 3 + +#endif /* __TFTP_H__ */ + +/* EOF - tftp.h */ diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/ComponentName.c b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/ComponentName.c new file mode 100644 index 0000000000..b48b5d0b85 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/ComponentName.c @@ -0,0 +1,169 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + ComponentName.c + +Abstract: + PxeDhcp4 component name protocol declarations + +--*/ + + +#include "PxeDhcp4.h" + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +PxeDhcp4ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +PxeDhcp4ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gPxeDhcp4ComponentName = { + PxeDhcp4ComponentNameGetDriverName, + PxeDhcp4ComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mPxeDhcp4DriverNameTable[] = { + { + "eng", + (CHAR16 *) L"PXE DHCPv4 Driver" + }, + { + NULL, + NULL + } +}; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4ComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gPxeDhcp4ComponentName.SupportedLanguages, + mPxeDhcp4DriverNameTable, + DriverName + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4ComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} + +/* EOF - ComponentName.c */ diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/Dhcp4.mbd b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/Dhcp4.mbd new file mode 100644 index 0000000000..090884a8a8 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/Dhcp4.mbd @@ -0,0 +1,41 @@ + + + + + Dhcp4 + a46c3330-be36-4977-9d24-a7cf92eef0fe + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/Dhcp4.msa b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/Dhcp4.msa new file mode 100644 index 0000000000..96bfc9b931 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/Dhcp4.msa @@ -0,0 +1,74 @@ + + + + + Dhcp4 + UEFI_DRIVER + BS_DRIVER + a46c3330-be36-4977-9d24-a7cf92eef0fe + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + ComponentName.c + PxeDhcp4.c + PxeDhcp4.h + PxeDhcp4InitSelect.c + PxeDhcp4Release.c + PxeDhcp4RenewRebind.c + PxeDhcp4Run.c + PxeDhcp4Setup.c + support.c + + + MdePkg + EdkModulePkg + + + PxeDhcp4Callback + PxeDhcp4 + SimpleNetwork + PxeBaseCode + + + + + + + + gPxeDhcp4DriverBinding + gPxeDhcp4ComponentName + + + diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4.c b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4.c new file mode 100644 index 0000000000..57a44a02b4 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4.c @@ -0,0 +1,342 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PxeDhcp4.c + +Abstract: + +--*/ + + +#include "PxeDhcp4.h" + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// Prototypes +// Driver model protocol interface +// +EFI_STATUS +EFIAPI +PxeDhcp4DriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +PxeDhcp4DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +PxeDhcp4DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +PxeDhcp4DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// PXE DHCP Protocol Interface +// +EFI_DRIVER_BINDING_PROTOCOL gPxeDhcp4DriverBinding = { + PxeDhcp4DriverBindingSupported, + PxeDhcp4DriverBindingStart, + PxeDhcp4DriverBindingStop, + 0x10, + NULL, + NULL +}; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4DriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL + ) +/*++ + + Routine Description: + Test to see if this driver supports ControllerHandle. Any + ControllerHandle that contains a PxeBaseCode protocol can be + supported. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to test. + RemainingDevicePath - Not used. + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_ALREADY_STARTED - This driver is already running on this + device. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; + + // + // Open the IO Abstraction(s) needed to perform the supported test. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiPxeBaseCodeProtocolGuid, + (VOID **) &PxeBc, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close the I/O Abstraction(s) used to perform the supported test. + // + return gBS->CloseProtocol ( + ControllerHandle, + &gEfiPxeBaseCodeProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4DriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL * This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL + ) +/*++ + + Routine Description: + Start this driver on ControllerHandle by opening a PxeBaseCode + protocol and installing a PxeDhcp4 protocol on ControllerHandle. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to bind driver to. + RemainingDevicePath - Not used, always produce all possible + children. + + Returns: + EFI_SUCCESS - This driver is added to ControllerHandle. + EFI_ALREADY_STARTED - This driver is already running on + ControllerHandle. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; + EFI_SIMPLE_NETWORK_PROTOCOL *Snp; + PXE_DHCP4_PRIVATE_DATA *Private; + + // + // Connect to the PxeBaseCode interface on ControllerHandle. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiPxeBaseCodeProtocolGuid, + (VOID **) &PxeBc, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // BaseCode has already grabbed the SimpleNetwork interface + // so just do a HandleProtocol() to get it. + // + Status = gBS->HandleProtocol ( + ControllerHandle, + &gEfiSimpleNetworkProtocolGuid, + (VOID **) &Snp + ); + + if (EFI_ERROR (Status)) { + goto error_exit; + } + + ASSERT (Snp); + + // + // Initialize the PXE DHCP device instance. + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (PXE_DHCP4_PRIVATE_DATA), + (VOID **) &Private + ); + + if (EFI_ERROR (Status)) { + goto error_exit; + } + // + // + // + ZeroMem (Private, sizeof (PXE_DHCP4_PRIVATE_DATA)); + + Private->Signature = PXE_DHCP4_PRIVATE_DATA_SIGNATURE; + Private->PxeBc = PxeBc; + Private->Snp = Snp; + Private->Handle = ControllerHandle; + Private->PxeDhcp4.Revision = EFI_PXE_DHCP4_PROTOCOL_REVISION; + Private->PxeDhcp4.Run = PxeDhcp4Run; + Private->PxeDhcp4.Setup = PxeDhcp4Setup; + Private->PxeDhcp4.Init = PxeDhcp4Init; + Private->PxeDhcp4.Select = PxeDhcp4Select; + Private->PxeDhcp4.Renew = PxeDhcp4Renew; + Private->PxeDhcp4.Rebind = PxeDhcp4Rebind; + Private->PxeDhcp4.Release = PxeDhcp4Release; + Private->PxeDhcp4.Data = NULL; + + // + // Install protocol interfaces for the PXE DHCP device. + // + Status = gBS->InstallProtocolInterface ( + &ControllerHandle, + &gEfiPxeDhcp4ProtocolGuid, + EFI_NATIVE_INTERFACE, + &Private->PxeDhcp4 + ); + + if (!EFI_ERROR (Status)) { + return Status; + } + +error_exit: ; + gBS->CloseProtocol ( + ControllerHandle, + &gEfiPxeBaseCodeProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return Status; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4DriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + + Routine Description: + Stop this driver on ControllerHandle by removing PXE DHCP + protocol and closing the PXE Base Code protocol on + ControllerHandle. + + Arguments: + This - Protocol instance pointer. + ControllerHandle - Handle of device to stop driver on. + NumberOfChildren - Not used. + ChildHandleBuffer - Not used. + + Returns: + EFI_SUCCESS - This driver is removed ControllerHandle. + other - This driver was not removed from this + device. + +--*/ +{ + EFI_STATUS Status; + EFI_PXE_DHCP4_PROTOCOL *PxeDhcp4; + PXE_DHCP4_PRIVATE_DATA *Private; + + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiPxeDhcp4ProtocolGuid, + (VOID **) &PxeDhcp4, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (PxeDhcp4); + + // + // Release allocated resources + // + if (Private->PxeDhcp4.Data) { + gBS->FreePool (Private->PxeDhcp4.Data); + Private->PxeDhcp4.Data = NULL; + } + // + // Uninstall our protocol + // + Status = gBS->UninstallProtocolInterface ( + ControllerHandle, + &gEfiPxeDhcp4ProtocolGuid, + &Private->PxeDhcp4 + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Close any consumed protocols + // + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiPxeBaseCodeProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Release our private data + // + gBS->FreePool (Private); + + return Status; +} + +/* EOF - PxeDhcp4.c */ diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4.h b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4.h new file mode 100644 index 0000000000..136d392504 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4.h @@ -0,0 +1,307 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PxeDhcp4.h + +Abstract: + Common header for PxeDhcp4 protocol driver + +--*/ +#ifndef _PXEDHCP4_H +#define _PXEDHCP4_H + +// +// PxeDhcp4 protocol instance data +// +typedef struct { + // + // Signature field used to locate beginning of containment record. + // + UINTN Signature; + +#define PXE_DHCP4_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('p', 'x', 'D', '4') + // + // Device handle the protocol is bound to. + // + EFI_HANDLE Handle; + + // + // Public PxeDhcp4 protocol interface. + // + EFI_PXE_DHCP4_PROTOCOL PxeDhcp4; + + // + // Consumed PxeBc, Snp and PxeDhcp4Callback protocol interfaces. + // + EFI_PXE_BASE_CODE_PROTOCOL *PxeBc; + EFI_SIMPLE_NETWORK_PROTOCOL *Snp; + EFI_PXE_DHCP4_CALLBACK_PROTOCOL *callback; + + // + // PxeDhcp4 called function for PxeDhcp4Callback. + // + EFI_PXE_DHCP4_FUNCTION function; + + // + // Timeout event and flag for PxeDhcp4Callback. + // + EFI_EVENT TimeoutEvent; + BOOLEAN TimeoutOccurred; + + // + // Periodic event and flag for PxeDhcp4Callback. + // + EFI_EVENT PeriodicEvent; + BOOLEAN PeriodicOccurred; + + // + // DHCP server IP address. + // + UINT32 ServerIp; + + // + // DHCP renewal and rebinding times, in seconds. + // + UINT32 RenewTime; + UINT32 RebindTime; + UINT32 LeaseTime; + + // + // Number of offers received & allocated offer list. + // + UINTN offers; + DHCP4_PACKET *offer_list; + + // + // + // + BOOLEAN StopPxeBc; + +} PXE_DHCP4_PRIVATE_DATA; + +#define PXE_DHCP4_PRIVATE_DATA_FROM_THIS(a) CR (a, PXE_DHCP4_PRIVATE_DATA, PxeDhcp4, PXE_DHCP4_PRIVATE_DATA_SIGNATURE) + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// Protocol function prototypes. +// +extern +EFI_STATUS +EFIAPI +PxeDhcp4Run ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN OPTIONAL UINTN OpLen, + IN OPTIONAL VOID *OpList + ) +; + +extern +EFI_STATUS +EFIAPI +PxeDhcp4Setup ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN EFI_PXE_DHCP4_DATA *Data + ) +; + +extern +EFI_STATUS +EFIAPI +PxeDhcp4Init ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN UINTN seconds_timeout, + OUT UINTN *offer_list_entries, + OUT DHCP4_PACKET **offer_list + ) +; + +extern +EFI_STATUS +EFIAPI +PxeDhcp4Select ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN UINTN seconds_timeout, + IN DHCP4_PACKET *offer_list + ) +; + +extern +EFI_STATUS +EFIAPI +PxeDhcp4Renew ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + UINTN seconds_timeout + ) +; + +extern +EFI_STATUS +EFIAPI +PxeDhcp4Rebind ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + UINTN seconds_timeout + ) +; + +extern +EFI_STATUS +EFIAPI +PxeDhcp4Release ( + IN EFI_PXE_DHCP4_PROTOCOL *This + ) +; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// Support function prototypes. +// +extern +UINT16 +htons ( + UINTN n + ) +; + +extern +UINT32 +htonl ( + UINTN n + ) +; + +extern +VOID +EFIAPI +timeout_notify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +extern +VOID +EFIAPI +periodic_notify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +extern +EFI_STATUS +find_opt ( + IN DHCP4_PACKET *Packet, + IN UINT8 OpCode, + IN UINTN Skip, + OUT DHCP4_OP **OpPtr + ) +; + +extern +EFI_STATUS +add_opt ( + IN DHCP4_PACKET *Packet, + IN DHCP4_OP *OpPtr + ) +; + +extern +EFI_STATUS +start_udp ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN OPTIONAL EFI_IP_ADDRESS *station_ip, + IN OPTIONAL EFI_IP_ADDRESS *subnet_mask + ) +; + +extern +VOID +stop_udp ( + IN PXE_DHCP4_PRIVATE_DATA *Private + ) +; + +extern +EFI_STATUS +start_receive_events ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN UINTN seconds_timeout + ) +; + +extern +VOID +stop_receive_events ( + IN PXE_DHCP4_PRIVATE_DATA *Private + ) +; + +extern +EFI_STATUS +tx_udp ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN EFI_IP_ADDRESS *dest_ip, + IN OPTIONAL EFI_IP_ADDRESS *gateway_ip, + IN EFI_IP_ADDRESS *src_ip, + IN VOID *buffer, + IN UINTN BufferSize + ) +; + +extern +EFI_STATUS +rx_udp ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + OUT VOID *buffer, + OUT UINTN *BufferSize, + IN OUT EFI_IP_ADDRESS *dest_ip, + IN OUT EFI_IP_ADDRESS *src_ip, + IN UINT16 op_flags + ) +; + +extern +EFI_STATUS +tx_rx_udp ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN OUT EFI_IP_ADDRESS *ServerIp, + IN OPTIONAL EFI_IP_ADDRESS *gateway_ip, + IN OPTIONAL EFI_IP_ADDRESS *client_ip, + IN OPTIONAL EFI_IP_ADDRESS *subnet_mask, + IN DHCP4_PACKET *tx_pkt, + OUT DHCP4_PACKET *rx_pkt, + IN INTN + ( + *rx_vfy) + ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN DHCP4_PACKET *tx_pkt, + IN DHCP4_PACKET *rx_pkt, + IN UINTN rx_pkt_size + ), + IN UINTN seconds_timeout + ) +; + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +// +// Global variable definitions. +// +extern EFI_DRIVER_BINDING_PROTOCOL gPxeDhcp4DriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gPxeDhcp4ComponentName; + +#endif /* _PXEDHCP4_H */ + +/* EOF - PxeDhcp4.h */ diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4InitSelect.c b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4InitSelect.c new file mode 100644 index 0000000000..8b7cd28810 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4InitSelect.c @@ -0,0 +1,786 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PxeDhcp4InitSelect.c + +Abstract: + +--*/ + + +#include "PxeDhcp4.h" + +#define DebugPrint(x) +// +// #define DebugPrint(x) Aprint x +// +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +INTN +offer_verify ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN DHCP4_PACKET *tx_pkt, + IN DHCP4_PACKET *rx_pkt, + IN UINTN rx_pkt_size + ) +/*++ + -2 = ignore, stop waiting + -1 = ignore, keep waiting + 0 = accept, keep waiting + 1 = accept, stop waiting +--*/ +{ + EFI_STATUS EfiStatus; + DHCP4_PACKET *tmp; + DHCP4_OP *msg_type_op; + DHCP4_OP *srvid_op; + UINT32 magik; + + // + // Verify parameters. Touch unused parameters to keep + // compiler happy. + // + ASSERT (Private); + ASSERT (rx_pkt); + + if (Private == NULL || rx_pkt == NULL) { + return -2; + } + + tx_pkt = tx_pkt; + rx_pkt_size = rx_pkt_size; + + // + // This may be a BOOTP Reply or DHCP Offer packet. + // If there is no DHCP magik number, assume that + // this is a BOOTP Reply packet. + // + magik = htonl (DHCP4_MAGIK_NUMBER); + + while (!CompareMem (&rx_pkt->dhcp4.magik, &magik, 4)) { + // + // If there is no DHCP message type option, assume + // this is a BOOTP reply packet and cache it. + // + EfiStatus = find_opt (rx_pkt, DHCP4_MESSAGE_TYPE, 0, &msg_type_op); + + if (EFI_ERROR (EfiStatus)) { + break; + } + // + // If there is a DHCP message type option, it must be a + // DHCP offer packet + // + if (msg_type_op->len != 1) { + return -1; + } + + if (msg_type_op->data[0] != DHCP4_MESSAGE_TYPE_OFFER) { + return -1; + } + // + // There must be a server identifier option. + // + EfiStatus = find_opt ( + rx_pkt, + DHCP4_SERVER_IDENTIFIER, + 0, + &srvid_op + ); + + if (EFI_ERROR (EfiStatus)) { + return -1; + } + + if (srvid_op->len != 4) { + return -1; + } + // + // Good DHCP offer packet. + // + break; + } + // + // Good DHCP (or BOOTP) packet. Cache it! + // + EfiStatus = gBS->AllocatePool ( + EfiBootServicesData, + (Private->offers + 1) * sizeof (DHCP4_PACKET), + (VOID **) &tmp + ); + + if (EFI_ERROR (EfiStatus)) { + return -2; + } + + ASSERT (tmp); + + if (Private->offers != 0) { + CopyMem ( + tmp, + Private->offer_list, + Private->offers * sizeof (DHCP4_PACKET) + ); + + gBS->FreePool (Private->offer_list); + } + + CopyMem (&tmp[Private->offers++], rx_pkt, sizeof (DHCP4_PACKET)); + + Private->offer_list = tmp; + + return 0; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +INTN +acknak_verify ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN DHCP4_PACKET *tx_pkt, + IN DHCP4_PACKET *rx_pkt, + IN UINTN rx_pkt_size + ) +/*++ + -2 = ignore, stop waiting + -1 = ignore, keep waiting + 0 = accept, keep waiting + 1 = accept, stop waiting +--*/ +{ + EFI_STATUS EfiStatus; + DHCP4_OP *msg_type_op; + DHCP4_OP *srvid_op; + DHCP4_OP *renew_op; + DHCP4_OP *rebind_op; + DHCP4_OP *lease_time_op; + UINT32 magik; + + // + // Verify parameters. Touch unused parameters to + // keep compiler happy. + // + ASSERT (Private); + ASSERT (rx_pkt); + + if (Private == NULL || rx_pkt == NULL) { + return -2; + } + + tx_pkt = tx_pkt; + rx_pkt_size = rx_pkt_size; + + // + // This must be a DHCP Ack message. + // + magik = htonl (DHCP4_MAGIK_NUMBER); + + if (CompareMem (&rx_pkt->dhcp4.magik, &magik, 4)) { + return -1; + } + + EfiStatus = find_opt (rx_pkt, DHCP4_MESSAGE_TYPE, 0, &msg_type_op); + + if (EFI_ERROR (EfiStatus)) { + return -1; + } + + if (msg_type_op->len != 1) { + return -1; + } + + if (msg_type_op->data[0] != DHCP4_MESSAGE_TYPE_ACK) { + return -1; + } + // + // There must be a server identifier. + // + EfiStatus = find_opt (rx_pkt, DHCP4_SERVER_IDENTIFIER, 0, &srvid_op); + + if (EFI_ERROR (EfiStatus)) { + return -1; + } + + if (srvid_op->len != 4) { + return -1; + } + // + // There should be a renewal time. + // If there is not, we will default to the 7/8 of the rebinding time. + // + EfiStatus = find_opt (rx_pkt, DHCP4_RENEWAL_TIME, 0, &renew_op); + + if (EFI_ERROR (EfiStatus)) { + renew_op = NULL; + } else if (renew_op->len != 4) { + renew_op = NULL; + } + // + // There should be a rebinding time. + // If there is not, we will default to 7/8 of the lease time. + // + EfiStatus = find_opt (rx_pkt, DHCP4_REBINDING_TIME, 0, &rebind_op); + + if (EFI_ERROR (EfiStatus)) { + rebind_op = NULL; + } else if (rebind_op->len != 4) { + rebind_op = NULL; + } + // + // There should be a lease time. + // If there is not, we will default to one week. + // + EfiStatus = find_opt (rx_pkt, DHCP4_LEASE_TIME, 0, &lease_time_op); + + if (EFI_ERROR (EfiStatus)) { + lease_time_op = NULL; + } else if (lease_time_op->len != 4) { + lease_time_op = NULL; + } + // + // Packet looks good. Double check the renew, rebind and lease times. + // + CopyMem (&Private->ServerIp, srvid_op->data, 4); + + if (renew_op != NULL) { + CopyMem (&Private->RenewTime, renew_op->data, 4); + Private->RenewTime = htonl (Private->RenewTime); + } else { + Private->RenewTime = 0; + } + + if (rebind_op != NULL) { + CopyMem (&Private->RebindTime, rebind_op->data, 4); + Private->RebindTime = htonl (Private->RebindTime); + } else { + Private->RebindTime = 0; + } + + if (lease_time_op != NULL) { + CopyMem (&Private->LeaseTime, lease_time_op->data, 4); + Private->LeaseTime = htonl (Private->LeaseTime); + } else { + Private->LeaseTime = 0; + } + + if (Private->LeaseTime < 60) { + Private->LeaseTime = 7 * 86400; + } + + if (Private->RebindTime < 52 || Private->RebindTime >= Private->LeaseTime) { + Private->RebindTime = Private->LeaseTime / 2 + Private->LeaseTime / 4 + Private->LeaseTime / 8; + } + + if (Private->RenewTime < 45 || Private->RenewTime >= Private->RebindTime) { + Private->RenewTime = Private->RebindTime / 2 + Private->RebindTime / 4 + Private->RebindTime / 8; + } + + return 1; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4Init ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN UINTN seconds_timeout, + OUT UINTN *Offers, + OUT DHCP4_PACKET **OfferList + ) +{ + PXE_DHCP4_PRIVATE_DATA *Private; + DHCP4_PACKET offer; + EFI_IP_ADDRESS bcast_ip; + EFI_STATUS EfiStatus; + + // + // Verify parameters and protocol state. + // + if (This == NULL || + seconds_timeout < DHCP4_MIN_SECONDS || + seconds_timeout > DHCP4_MAX_SECONDS || + Offers == NULL || + OfferList == NULL + ) { + // + // Return parameters are not initialized when + // parameters are invalid! + // + return EFI_INVALID_PARAMETER; + } + + *Offers = 0; + *OfferList = NULL; + + // + // Check protocol state. + // + if (This->Data == NULL) { + return EFI_NOT_STARTED; + } + + if (!This->Data->SetupCompleted) { + return EFI_NOT_READY; + } + +#if 0 + if (!is_good_discover (&This->Data->Discover)) { + // + // %%TBD - check discover packet fields + // + } +#endif + // + // Get pointer to our instance data. + // + Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This); + + if (Private == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Private->PxeBc == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Setup variables... + // + Private->offers = 0; + Private->offer_list = NULL; + + EfiStatus = gBS->HandleProtocol ( + Private->Handle, + &gEfiPxeDhcp4CallbackProtocolGuid, + (VOID *) &Private->callback + ); + + if (EFI_ERROR (EfiStatus)) { + Private->callback = NULL; + } + + Private->function = EFI_PXE_DHCP4_FUNCTION_INIT; + + // + // Increment the transaction ID. + // + { + UINT32 xid; + + CopyMem (&xid, &This->Data->Discover.dhcp4.xid, sizeof (UINT32)); + + xid = htonl (htonl (xid) + 1); + + CopyMem (&This->Data->Discover.dhcp4.xid, &xid, sizeof (UINT32)); + } + // + // Transmit discover and wait for offers... + // + SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF); + + EfiStatus = tx_rx_udp ( + Private, + &bcast_ip, + NULL, + NULL, + NULL, + &This->Data->Discover, + &offer, + &offer_verify, + seconds_timeout + ); + + if (EFI_ERROR (EfiStatus)) { + if (Private->offer_list) { + gBS->FreePool (Private->offer_list); + } + + Private->offers = 0; + Private->offer_list = NULL; + Private->callback = NULL; + + DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus)); + return EfiStatus; + } + + *Offers = Private->offers; + *OfferList = Private->offer_list; + + Private->offers = 0; + Private->offer_list = NULL; + Private->callback = NULL; + + This->Data->InitCompleted = TRUE; + This->Data->SelectCompleted = FALSE; + This->Data->IsBootp = FALSE; + This->Data->IsAck = FALSE; + + return EFI_SUCCESS; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4Select ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN UINTN seconds_timeout, + IN DHCP4_PACKET *Offer + ) +{ + PXE_DHCP4_PRIVATE_DATA *Private; + EFI_STATUS EfiStatus; + DHCP4_PACKET request; + DHCP4_PACKET acknak; + EFI_IP_ADDRESS bcast_ip; + EFI_IP_ADDRESS zero_ip; + EFI_IP_ADDRESS local_ip; + DHCP4_OP *srvid; + DHCP4_OP *op; + UINT32 dhcp4_magik; + UINT8 buf[16]; + BOOLEAN is_bootp; + + // + // Verify parameters. + // + if (This == NULL || seconds_timeout < DHCP4_MIN_SECONDS || seconds_timeout > DHCP4_MAX_SECONDS || Offer == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Check protocol state. + // + if (This->Data == NULL) { + return EFI_NOT_STARTED; + } + + if (!This->Data->SetupCompleted) { + return EFI_NOT_READY; + } + // + // Get pointer to instance data. + // + Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This); + + if (Private == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Private->PxeBc == NULL) { + return EFI_DEVICE_ERROR; + } + +#if 0 + if (!is_good_discover (&This->Data->Discover)) { + // + // %%TBD - check discover packet fields + // + } +#endif + // + // Setup useful variables... + // + SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF); + + ZeroMem (&zero_ip, sizeof (EFI_IP_ADDRESS)); + + ZeroMem (&local_ip, sizeof (EFI_IP_ADDRESS)); + local_ip.v4.Addr[0] = 127; + local_ip.v4.Addr[3] = 1; + + This->Data->SelectCompleted = FALSE; + This->Data->IsBootp = FALSE; + This->Data->IsAck = FALSE; + + EfiStatus = gBS->HandleProtocol ( + Private->Handle, + &gEfiPxeDhcp4CallbackProtocolGuid, + (VOID *) &Private->callback + ); + + if (EFI_ERROR (EfiStatus)) { + Private->callback = NULL; + } + + Private->function = EFI_PXE_DHCP4_FUNCTION_SELECT; + + // + // Verify offer packet fields. + // + if (Offer->dhcp4.op != BOOTP_REPLY) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + if (Offer->dhcp4.htype != This->Data->Discover.dhcp4.htype) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + if (Offer->dhcp4.hlen != This->Data->Discover.dhcp4.hlen) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + if (CompareMem (&Offer->dhcp4.xid, &This->Data->Discover.dhcp4.xid, 4)) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + if (!CompareMem (&Offer->dhcp4.yiaddr, &bcast_ip, 4)) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + if (!CompareMem (&Offer->dhcp4.yiaddr, &zero_ip, 4)) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + if (!CompareMem (&Offer->dhcp4.yiaddr, &local_ip, 4)) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + if (CompareMem ( + &Offer->dhcp4.chaddr, + &This->Data->Discover.dhcp4.chaddr, + 16 + )) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + // + // DHCP option checks + // + dhcp4_magik = htonl (DHCP4_MAGIK_NUMBER); + is_bootp = TRUE; + + if (!CompareMem (&Offer->dhcp4.magik, &dhcp4_magik, 4)) { + // + // If present, DHCP message type must be offer. + // + EfiStatus = find_opt (Offer, DHCP4_MESSAGE_TYPE, 0, &op); + + if (!EFI_ERROR (EfiStatus)) { + if (op->len != 1 || op->data[0] != DHCP4_MESSAGE_TYPE_OFFER) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + is_bootp = FALSE; + } + // + // If present, DHCP max message size must be valid. + // + EfiStatus = find_opt (Offer, DHCP4_MAX_MESSAGE_SIZE, 0, &op); + + if (!EFI_ERROR (EfiStatus)) { + if (op->len != 2 || ((op->data[0] << 8) | op->data[1]) < DHCP4_DEFAULT_MAX_MESSAGE_SIZE) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + } + // + // If present, DHCP server identifier must be valid. + // + EfiStatus = find_opt (Offer, DHCP4_SERVER_IDENTIFIER, 0, &op); + + if (!EFI_ERROR (EfiStatus)) { + if (op->len != 4 || !CompareMem (op->data, &bcast_ip, 4) || !CompareMem (op->data, &zero_ip, 4)) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + } + // + // If present, DHCP subnet mask must be valid. + // + EfiStatus = find_opt ( + Offer, + DHCP4_SUBNET_MASK, + 0, + &op + ); + + if (!EFI_ERROR (EfiStatus)) { + if (op->len != 4) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + } + } + // + // Early out for BOOTP. + // + This->Data->IsBootp = is_bootp; + if (is_bootp) { + // + // Copy offer packet to instance data. + // + CopyMem (&This->Data->Offer, Offer, sizeof (DHCP4_PACKET)); + + // + // Copy discover to request and offer to acknak. + // + CopyMem ( + &This->Data->Request, + &This->Data->Discover, + sizeof (DHCP4_PACKET) + ); + + CopyMem ( + &This->Data->AckNak, + &This->Data->Offer, + sizeof (DHCP4_PACKET) + ); + + // + // Set state flags. + // + This->Data->SelectCompleted = TRUE; + This->Data->IsAck = TRUE; + + Private->callback = NULL; + return EFI_SUCCESS; + } + // + // Copy discover packet contents to request packet. + // + CopyMem (&request, &This->Data->Discover, sizeof (DHCP4_PACKET)); + + This->Data->IsAck = FALSE; + + // + // Change DHCP message type from discover to request. + // + EfiStatus = find_opt (&request, DHCP4_MESSAGE_TYPE, 0, &op); + + if (EFI_ERROR (EfiStatus) && EfiStatus != EFI_NOT_FOUND) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + if (EfiStatus == EFI_NOT_FOUND) { + EfiStatus = find_opt (&request, DHCP4_END, 0, &op); + + if (EFI_ERROR (EfiStatus)) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + op->op = DHCP4_MESSAGE_TYPE; + op->len = 1; + + op->data[1] = DHCP4_END; + } + + op->data[0] = DHCP4_MESSAGE_TYPE_REQUEST; + + // + // Copy server identifier option from offer to request. + // + EfiStatus = find_opt (Offer, DHCP4_SERVER_IDENTIFIER, 0, &srvid); + + if (EFI_ERROR (EfiStatus)) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + if (srvid->len != 4) { + Private->callback = NULL; + return EFI_INVALID_PARAMETER; + } + + EfiStatus = add_opt (&request, srvid); + + if (EFI_ERROR (EfiStatus)) { + DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus)); + Private->callback = NULL; + return EfiStatus; + } + // + // Add requested IP address option to request packet. + // + op = (DHCP4_OP *) buf; + op->op = DHCP4_REQUESTED_IP_ADDRESS; + op->len = 4; + CopyMem (op->data, &Offer->dhcp4.yiaddr, 4); + + EfiStatus = add_opt (&request, op); + + if (EFI_ERROR (EfiStatus)) { + DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus)); + Private->callback = NULL; + return EfiStatus; + } + // + // Transimit DHCP request and wait for DHCP ack... + // + SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF); + + EfiStatus = tx_rx_udp ( + Private, + &bcast_ip, + NULL, + NULL, + NULL, + &request, + &acknak, + &acknak_verify, + seconds_timeout + ); + + if (EFI_ERROR (EfiStatus)) { + DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus)); + Private->callback = NULL; + return EfiStatus; + } + // + // Set Data->IsAck and return. + // + EfiStatus = find_opt (&acknak, DHCP4_MESSAGE_TYPE, 0, &op); + + if (EFI_ERROR (EfiStatus)) { + Private->callback = NULL; + return EFI_DEVICE_ERROR; + } + + if (op->len != 1) { + Private->callback = NULL; + return EFI_DEVICE_ERROR; + } + + switch (op->data[0]) { + case DHCP4_MESSAGE_TYPE_ACK: + This->Data->IsAck = TRUE; + break; + + case DHCP4_MESSAGE_TYPE_NAK: + This->Data->IsAck = FALSE; + break; + + default: + Private->callback = NULL; + return EFI_DEVICE_ERROR; + } + // + // Copy packets into instance data... + // + CopyMem (&This->Data->Offer, Offer, sizeof (DHCP4_PACKET)); + CopyMem (&This->Data->Request, &request, sizeof (DHCP4_PACKET)); + CopyMem (&This->Data->AckNak, &acknak, sizeof (DHCP4_PACKET)); + + This->Data->SelectCompleted = TRUE; + + Private->callback = NULL; + return EFI_SUCCESS; +} + +/* eof - PxeDhcp4InitSelect.c */ diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Release.c b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Release.c new file mode 100644 index 0000000000..6086e55eba --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Release.c @@ -0,0 +1,246 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PxeDhcp4Release.c + +Abstract: + Transmit release packet, free allocations and shutdown PxeDhcp4. + +--*/ + + +#include "PxeDhcp4.h" + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4Release ( + IN EFI_PXE_DHCP4_PROTOCOL *This + ) +{ + PXE_DHCP4_PRIVATE_DATA *Private; + EFI_IP_ADDRESS ServerIp; + EFI_IP_ADDRESS client_ip; + EFI_IP_ADDRESS gateway_ip; + EFI_IP_ADDRESS subnet_mask; + EFI_STATUS efi_status; + DHCP4_OP *op; + UINT8 op_list[20]; + + // + // Check for invalid parameters. + // + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Release does nothing if the protocol has never been setup. + // + if (This->Data == NULL) { + return EFI_NOT_STARTED; + } + // + // Fail if we do not have valid instance data. + // + Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This); + + if (Private == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Private->PxeBc == NULL) { + return EFI_DEVICE_ERROR; + } + // + // If this is a BOOTP session and there is not a DHCP Ack + // packet, just release storage and return. + // + if (This->Data->IsBootp || !This->Data->IsAck) { + gBS->FreePool (This->Data); + This->Data = NULL; + + if (Private->StopPxeBc) { + Private->PxeBc->Stop (Private->PxeBc); + } + + return EFI_SUCCESS; + } + // + // Build option list for DHCP Release packet. + // If any errors occur, just release storage and return. + // + // + // Message type is first. + // + op_list[0] = DHCP4_MESSAGE_TYPE; + op_list[1] = 1; + op_list[2] = DHCP4_MESSAGE_TYPE_RELEASE; + + // + // Followed by server identifier. + // + efi_status = find_opt ( + &This->Data->Request, + DHCP4_SERVER_IDENTIFIER, + 0, + &op + ); + + if (EFI_ERROR (efi_status)) { + gBS->FreePool (This->Data); + This->Data = NULL; + + if (Private->StopPxeBc) { + Private->PxeBc->Stop (Private->PxeBc); + } + + return EFI_SUCCESS; + } + + if (op->len != 4) { + gBS->FreePool (This->Data); + This->Data = NULL; + + if (Private->StopPxeBc) { + Private->PxeBc->Stop (Private->PxeBc); + } + + return EFI_SUCCESS; + } + + CopyMem (&ServerIp, op->data, 4); + + op_list[3] = DHCP4_SERVER_IDENTIFIER; + op_list[4] = 4; + CopyMem (&op_list[5], &ServerIp, 4); + + // + // Followed by end. + // + op_list[9] = DHCP4_END; + + // + // We need a subnet mask for IP stack operation. + // + efi_status = find_opt ( + &This->Data->AckNak, + DHCP4_SUBNET_MASK, + 0, + &op + ); + + if (EFI_ERROR (efi_status)) { + gBS->FreePool (This->Data); + This->Data = NULL; + + if (Private->StopPxeBc) { + Private->PxeBc->Stop (Private->PxeBc); + } + + return EFI_SUCCESS; + } + + if (op->len != 4) { + gBS->FreePool (This->Data); + This->Data = NULL; + + if (Private->StopPxeBc) { + Private->PxeBc->Stop (Private->PxeBc); + } + + return EFI_SUCCESS; + } + + ZeroMem (&subnet_mask, sizeof (EFI_IP_ADDRESS)); + CopyMem (&subnet_mask, op->data, 4); + + // + // Gateway IP address may be needed. + // + ZeroMem (&gateway_ip, sizeof (EFI_IP_ADDRESS)); + CopyMem (&gateway_ip, &This->Data->AckNak.dhcp4.giaddr, 4); + + // + // Client IP address needed for IP stack operation. + // + ZeroMem (&client_ip, sizeof (EFI_IP_ADDRESS)); + CopyMem (&client_ip, &This->Data->AckNak.dhcp4.yiaddr, 4); + + // + // Enable UDP... + // + efi_status = start_udp (Private, &client_ip, &subnet_mask); + + if (EFI_ERROR (efi_status)) { + gBS->FreePool (This->Data); + This->Data = NULL; + + if (Private->StopPxeBc) { + Private->PxeBc->Stop (Private->PxeBc); + } + + return efi_status; + } + // + // Gather information out of DHCP request packet needed for + // DHCP release packet. + // + // + // Setup DHCP Release packet. + // + CopyMem (&This->Data->Request.dhcp4.ciaddr, &client_ip, 4); + + ZeroMem (&This->Data->Request.dhcp4.yiaddr, 12); + + ZeroMem (&This->Data->Request.dhcp4.sname, 64 + 128); + + This->Data->Request.dhcp4.hops = 0; + This->Data->Request.dhcp4.secs = 0; + This->Data->Request.dhcp4.flags = 0; + + ZeroMem ( + &This->Data->Request.dhcp4.options, + sizeof This->Data->Request.dhcp4.options + ); + + CopyMem (&This->Data->Request.dhcp4.options, op_list, 10); + + // + // Transmit DHCP Release packet. + // + tx_udp ( + Private, + &ServerIp, + &gateway_ip, + &client_ip, + &This->Data->Request, + DHCP4_MAX_PACKET_SIZE - (DHCP4_UDP_HEADER_SIZE + DHCP4_IP_HEADER_SIZE) + ); + + gBS->Stall (1000000); /* 1/10th second */ + + // + // Shutdown PXE BaseCode and release local storage. + // + stop_udp (Private); + + gBS->FreePool (This->Data); + This->Data = NULL; + + if (Private->StopPxeBc) { + Private->PxeBc->Stop (Private->PxeBc); + } + + return EFI_SUCCESS; +} + +/* eof - PxeDhcp4Release.c */ diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4RenewRebind.c b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4RenewRebind.c new file mode 100644 index 0000000000..2905255faa --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4RenewRebind.c @@ -0,0 +1,408 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PxeDhcp4RenewRebind.c + +Abstract: + +--*/ + + +#include "PxeDhcp4.h" + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +INTN +acknak_verify ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN DHCP4_PACKET *tx_pkt, + IN DHCP4_PACKET *rx_pkt, + IN UINTN rx_pkt_size + ) +/*++ +Routine Description: + +Parameters: + +Returns: + -2 = ignore, stop waiting + -1 = ignore, keep waiting + 0 = accept, keep waiting + 1 = accept, stop waiting +--*/ +{ + EFI_STATUS efi_status; + DHCP4_OP *msg_type_op; + DHCP4_OP *srvid_op; + DHCP4_OP *renew_op; + DHCP4_OP *rebind_op; + DHCP4_OP *lease_time_op; + UINT32 magik; + + // + // Verify parameters. Unused parameters are also touched + // to make the compiler happy. + // + ASSERT (Private); + ASSERT (rx_pkt); + + if (Private == NULL || rx_pkt == NULL) { + return -2; + } + + tx_pkt = tx_pkt; + rx_pkt_size = rx_pkt_size; + + // + // This must be a DHCP Ack message. + // + magik = htonl (DHCP4_MAGIK_NUMBER); + + if (CompareMem (&rx_pkt->dhcp4.magik, &magik, 4)) { + return -1; + } + + efi_status = find_opt (rx_pkt, DHCP4_MESSAGE_TYPE, 0, &msg_type_op); + + if (EFI_ERROR (efi_status)) { + return -1; + } + + if (msg_type_op->len != 1) { + return -1; + } + + if (msg_type_op->data[0] != DHCP4_MESSAGE_TYPE_ACK) { + return -1; + } + // + // There must be a server identifier. + // + efi_status = find_opt (rx_pkt, DHCP4_SERVER_IDENTIFIER, 0, &srvid_op); + + if (EFI_ERROR (efi_status)) { + return -1; + } + + if (srvid_op->len != 4) { + return -1; + } + // + // There should be a renewal time. + // If there is not, we will default to the 7/8 of the rebinding time. + // + efi_status = find_opt (rx_pkt, DHCP4_RENEWAL_TIME, 0, &renew_op); + + if (EFI_ERROR (efi_status)) { + renew_op = NULL; + } else if (renew_op->len != 4) { + renew_op = NULL; + } + // + // There should be a rebinding time. + // If there is not, we will default to 7/8 of the lease time. + // + efi_status = find_opt (rx_pkt, DHCP4_REBINDING_TIME, 0, &rebind_op); + + if (EFI_ERROR (efi_status)) { + rebind_op = NULL; + } else if (rebind_op->len != 4) { + rebind_op = NULL; + } + // + // There should be a lease time. + // If there is not, we will default to one week. + // + efi_status = find_opt (rx_pkt, DHCP4_LEASE_TIME, 0, &lease_time_op); + + if (EFI_ERROR (efi_status)) { + lease_time_op = NULL; + } else if (lease_time_op->len != 4) { + lease_time_op = NULL; + } + // + // Packet looks good. Double check the renew, rebind and lease times. + // + CopyMem (&Private->ServerIp, srvid_op->data, 4); + + if (renew_op != NULL) { + CopyMem (&Private->RenewTime, renew_op->data, 4); + Private->RenewTime = htonl (Private->RenewTime); + } else { + Private->RenewTime = 0; + } + + if (rebind_op != NULL) { + CopyMem (&Private->RebindTime, rebind_op->data, 4); + Private->RebindTime = htonl (Private->RebindTime); + } else { + Private->RebindTime = 0; + } + + if (lease_time_op != NULL) { + CopyMem (&Private->LeaseTime, lease_time_op->data, 4); + Private->LeaseTime = htonl (Private->LeaseTime); + } else { + Private->LeaseTime = 0; + } + + if (Private->LeaseTime < 60) { + Private->LeaseTime = 7 * 86400; + } + + if (Private->RebindTime < 52 || Private->RebindTime >= Private->LeaseTime) { + Private->RebindTime = Private->LeaseTime / 2 + Private->LeaseTime / 4 + Private->LeaseTime / 8; + } + + if (Private->RenewTime < 45 || Private->RenewTime >= Private->RebindTime) { + Private->RenewTime = Private->RebindTime / 2 + Private->RebindTime / 4 + Private->RebindTime / 8; + } + + return 1; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +STATIC +EFI_STATUS +EFIAPI +renew_rebind ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN UINTN seconds_timeout, + IN BOOLEAN renew + ) +{ + PXE_DHCP4_PRIVATE_DATA *Private; + EFI_IP_ADDRESS ServerIp; + EFI_IP_ADDRESS client_ip; + EFI_IP_ADDRESS subnet_mask; + EFI_IP_ADDRESS gateway_ip; + DHCP4_PACKET Request; + DHCP4_PACKET AckNak; + DHCP4_OP *op; + EFI_STATUS efi_status; + + // + // Check for invalid parameters. + // + if (This == NULL || seconds_timeout < DHCP4_MIN_SECONDS || seconds_timeout > DHCP4_MAX_SECONDS) { + return EFI_INVALID_PARAMETER; + } + // + // Check for proper protocol state. + // + if (This->Data == NULL) { + return EFI_NOT_STARTED; + } + + if (!This->Data->SelectCompleted) { + return EFI_NOT_READY; + } + + if (This->Data->IsBootp) { + return EFI_SUCCESS; + } + + if (!This->Data->IsAck) { + return EFI_INVALID_PARAMETER; + } + // + // Get pointer to instance data. + // + Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This); + + if (Private == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Private->PxeBc == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Copy Discover packet to temporary request packet + // to be used for Renew/Rebind operation. + // + CopyMem (&Request, &This->Data->Discover, sizeof (DHCP4_PACKET)); + + CopyMem (&Request.dhcp4.ciaddr, &This->Data->AckNak.dhcp4.yiaddr, 4); + + Request.dhcp4.flags = 0; /* Reply does not need to be broadcast. */ + + // + // Change message type from discover to request. + // + efi_status = find_opt (&Request, DHCP4_MESSAGE_TYPE, 0, &op); + + if (EFI_ERROR (efi_status)) { + return EFI_INVALID_PARAMETER; + } + + if (op->len != 1) { + return EFI_INVALID_PARAMETER; + } + + op->data[0] = DHCP4_MESSAGE_TYPE_REQUEST; + + // + // Need a subnet mask. + // + efi_status = find_opt ( + &This->Data->AckNak, + DHCP4_SUBNET_MASK, + 0, + &op + ); + + if (EFI_ERROR (efi_status)) { + return EFI_INVALID_PARAMETER; + } + + if (op->len != 4) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&subnet_mask, sizeof (EFI_IP_ADDRESS)); + CopyMem (&subnet_mask, op->data, 4); + + // + // Need a server IP address (renew) or a broadcast + // IP address (rebind). + // + ZeroMem (&gateway_ip, sizeof (EFI_IP_ADDRESS)); + + if (renew) { + efi_status = find_opt ( + &This->Data->AckNak, + DHCP4_SERVER_IDENTIFIER, + 0, + &op + ); + + if (EFI_ERROR (efi_status)) { + return EFI_INVALID_PARAMETER; + } + + if (op->len != 4) { + return EFI_INVALID_PARAMETER; + } + + ZeroMem (&ServerIp, sizeof (EFI_IP_ADDRESS)); + CopyMem (&ServerIp, op->data, 4); + + // + // + // + if (CompareMem (&This->Data->AckNak.dhcp4.giaddr, &gateway_ip, 4)) { + CopyMem (&gateway_ip, &This->Data->AckNak.dhcp4.giaddr, 4); + } + } else { + SetMem (&ServerIp, sizeof (EFI_IP_ADDRESS), 0xFF); + } + // + // Need a client IP address. + // + ZeroMem (&client_ip, sizeof (EFI_IP_ADDRESS)); + CopyMem (&client_ip, &Request.dhcp4.ciaddr, 4); + + // + // + // + efi_status = gBS->HandleProtocol ( + Private->Handle, + &gEfiPxeDhcp4CallbackProtocolGuid, + (VOID *) &Private->callback + ); + + if (EFI_ERROR (efi_status)) { + Private->callback = NULL; + } + + Private->function = renew ? EFI_PXE_DHCP4_FUNCTION_RENEW : EFI_PXE_DHCP4_FUNCTION_REBIND; + + // + // Transimit DHCP request and wait for DHCP ack... + // + efi_status = tx_rx_udp ( + Private, + &ServerIp, + &gateway_ip, + &client_ip, + &subnet_mask, + &Request, + &AckNak, + &acknak_verify, + seconds_timeout + ); + + if (EFI_ERROR (efi_status)) { + Private->callback = NULL; + return efi_status; + } + // + // Copy server identifier, renewal time and rebinding time + // from temporary ack/nak packet into cached ack/nak packet. + // + efi_status = find_opt ( + &This->Data->AckNak, + DHCP4_SERVER_IDENTIFIER, + 0, + &op + ); + + if (!EFI_ERROR (efi_status)) { + if (op->len == 4) { + CopyMem (op->data, &Private->ServerIp, 4); + } + } + + efi_status = find_opt (&This->Data->AckNak, DHCP4_RENEWAL_TIME, 0, &op); + + if (!EFI_ERROR (efi_status)) { + if (op->len == 4) { + CopyMem (op->data, &Private->RenewTime, 4); + } + } + + efi_status = find_opt (&This->Data->AckNak, DHCP4_REBINDING_TIME, 0, &op); + + if (!EFI_ERROR (efi_status)) { + if (op->len == 4) { + CopyMem (op->data, &Private->RebindTime, 4); + } + } + + Private->callback = NULL; + return efi_status; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4Renew ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN UINTN seconds_timeout + ) +{ + return renew_rebind (This, seconds_timeout, TRUE); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4Rebind ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN UINTN seconds_timeout + ) +{ + return renew_rebind (This, seconds_timeout, FALSE); +} + +/* eof - PxeDhcp4RenewRebind.c */ diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Run.c b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Run.c new file mode 100644 index 0000000000..50f97a8915 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Run.c @@ -0,0 +1,196 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PxeDhcp4Run.c + +Abstract: + Simplified entry point for starting basic PxeDhcp4 client operation. + +--*/ + + +#include "PxeDhcp4.h" + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4Run ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN OPTIONAL UINTN OpLen, + IN OPTIONAL VOID *OpList + ) +{ + PXE_DHCP4_PRIVATE_DATA *Private; + DHCP4_PACKET *offer_list; + EFI_STATUS efi_status; + EFI_IP_ADDRESS zero_ip; + UINTN offers; + UINTN timeout; + UINTN n; + UINT16 seconds; + + // + // Validate parameters. + // + if (This == NULL || (OpLen != 0 && OpList == NULL) || (OpLen == 0 && OpList != NULL)) { + return EFI_INVALID_PARAMETER; + } + + for (n = 0; n < OpLen;) { + switch (((UINT8 *) OpList)[n]) { + case DHCP4_PAD: + ++n; + continue; + + case DHCP4_END: + ++n; + break; + + default: + n += 2 + ((UINT8 *) OpList)[n + 1]; + continue; + } + + break; + } + + if (n != OpLen) { + return EFI_INVALID_PARAMETER; + } + // + // Get pointer to instance data. + // + Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This); + + if (Private == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Private->PxeBc == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Initialize DHCP discover packet. + // + efi_status = PxeDhcp4Setup (This, NULL); + + if (EFI_ERROR (efi_status)) { + return efi_status; + } + + for (n = 0; n < OpLen;) { + switch (((UINT8 *) OpList)[n]) { + case DHCP4_PAD: + ++n; + continue; + + case DHCP4_END: + ++n; + break; + + default: + efi_status = add_opt ( + &This->Data->Discover, + (DHCP4_OP *) &(((UINT8 *) OpList)[n]) + ); + + if (EFI_ERROR (efi_status)) { + return efi_status; + } + + n += 2 + ((UINT8 *) OpList)[n + 1]; + continue; + } + + break; + } + // + // Basic DHCP D.O.R.A. + // 1, 2, 4, 8, 16 & 32 second timeouts. + // Callback routine can be used to break out earlier. + // + ZeroMem (&zero_ip, sizeof (EFI_IP_ADDRESS)); + + for (timeout = 1;;) { + // + // Broadcast DHCP discover and wait for DHCP offers. + // + efi_status = PxeDhcp4Init (This, timeout, &offers, &offer_list); + + switch (efi_status) { + case EFI_NO_RESPONSE: + case EFI_TIMEOUT: + case EFI_SUCCESS: + break; + + case EFI_ABORTED: + default: + return efi_status; + } + // + // Try to select from each DHCP or BOOTP offer. + // + for (n = 0; n < offers; ++n) { + // + // Ignore proxyDHCP offers. + // + if (!CompareMem (&offer_list[n].dhcp4.yiaddr, &zero_ip, 4)) { + continue; + } + // + // Issue DHCP Request and wait for DHCP Ack/Nak. + // + efi_status = PxeDhcp4Select ( + This, + timeout, + &offer_list[n] + ); + + if (EFI_ERROR (efi_status)) { + continue; + } + // + // Exit when we have got our DHCP Ack. + // + if (This->Data->IsAck) { + return EFI_SUCCESS; + } + } + // + // No DHCP Acks. Release DHCP Offer list storage. + // + if (offer_list != NULL) { + gBS->FreePool (offer_list); + offer_list = NULL; + } + // + // Try again until we have used up >= DHCP4_MAX_SECONDS. + // + if ((timeout <<= 1) > DHCP4_MAX_SECONDS) { + if (!EFI_ERROR (efi_status)) { + efi_status = EFI_TIMEOUT; + } + + return efi_status; + } + // + // Next timeout value. + // + CopyMem (&seconds, &This->Data->Discover.dhcp4.secs, 2); + + seconds = htons (htons (seconds) + timeout); + + CopyMem (&This->Data->Discover.dhcp4.secs, &seconds, 2); + } +} + +/* eof - PxeDhcp4Run.c */ diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Setup.c b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Setup.c new file mode 100644 index 0000000000..09ba041ea6 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Setup.c @@ -0,0 +1,268 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PxeDhcp4Setup.c + +Abstract: + +--*/ + + +#include "PxeDhcp4.h" + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +EFIAPI +PxeDhcp4Setup ( + IN EFI_PXE_DHCP4_PROTOCOL *This, + IN EFI_PXE_DHCP4_DATA *Data + ) +{ + PXE_DHCP4_PRIVATE_DATA *Private; + DHCP4_HEADER *Packet; + EFI_STATUS EfiStatus; + UINT8 *OpLen; + UINT8 *OpPtr; + + // + // Return error if parameters are invalid. + // + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This); + + if (Private == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (This->Data != NULL) { + return EFI_ALREADY_STARTED; + } + + if (Private->PxeBc == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Check contents of provided Data structure. + // + if (Data != NULL) { + // + // Do protocol state checks first. + // + if (Data->SelectCompleted) { + if (!Data->InitCompleted || !Data->SetupCompleted) { + return EFI_INVALID_PARAMETER; + } + + if (Data->IsBootp && !Data->IsAck) { + return EFI_INVALID_PARAMETER; + } + } else if (Data->InitCompleted) { + if (!Data->SetupCompleted || Data->IsBootp || Data->IsAck) { + return EFI_INVALID_PARAMETER; + } + } else if (Data->SetupCompleted) { + if (Data->IsBootp || Data->IsAck) { + return EFI_INVALID_PARAMETER; + } + } + // + // Do packet content checks. + // + if (Data->SetupCompleted) { + // + // %%TBD - check discover packet + // + } + + if (Data->SelectCompleted) { + if (Data->IsBootp) { + // + // %%TBD - check offer packet + // + if (CompareMem ( + &Data->Discover, + &Data->Request, + sizeof (DHCP4_PACKET) + )) { + return EFI_INVALID_PARAMETER; + } + + if (CompareMem ( + &Data->Offer, + &Data->AckNak, + sizeof (DHCP4_PACKET) + )) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // %%TBD - check offer, request & acknak packets + // + } + } + } + // + // Allocate data structure. Return error + // if there is not enough available memory. + // + EfiStatus = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_PXE_DHCP4_DATA), + (VOID **) &This->Data + ); + + if (EFI_ERROR (EfiStatus)) { + This->Data = NULL; + return EfiStatus; + } + + if (This->Data == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Start PxeBc because we want to use its UdpWrite, UdpRead and + // SetFilter calls. + // + EfiStatus = Private->PxeBc->Start (Private->PxeBc, FALSE); + + if (EFI_ERROR (EfiStatus)) { + if (EfiStatus != EFI_ALREADY_STARTED) { + gBS->FreePool (This->Data); + This->Data = NULL; + Private->PxeBc->Stop (Private->PxeBc); + return EfiStatus; + } + + Private->StopPxeBc = FALSE; + } else { + Private->StopPxeBc = TRUE; + } + // + // Use new data. + // + if (Data != NULL) { + CopyMem (This->Data, Data, sizeof (EFI_PXE_DHCP4_DATA)); + return EFI_SUCCESS; + } + // + // Initialize new public data structure. + // + ZeroMem (This->Data, sizeof (EFI_PXE_DHCP4_DATA)); + + // + // Fill in default DHCP discover packet. + // Check for MAC addresses of strange lengths, just in case. + // + Packet = &This->Data->Discover.dhcp4; + + Packet->op = BOOTP_REQUEST; + + Packet->htype = Private->Snp->Mode->IfType; + + if (Private->Snp->Mode->HwAddressSize > 16) { + Packet->hlen = 16; + } else { + Packet->hlen = (UINT8) Private->Snp->Mode->HwAddressSize; + } + + Packet->hops = 0; /* Set to zero per RFC 2131. */ + + if (Packet->hlen < sizeof Packet->xid) { + if (Packet->hlen != 0) { + CopyMem ( + &Packet->xid, + &Private->Snp->Mode->CurrentAddress, + Packet->hlen + ); + } + } else { + CopyMem ( + &Packet->xid, + &Private->Snp->Mode->CurrentAddress.Addr[Packet->hlen - sizeof Packet->xid], + sizeof Packet->xid + ); + } + // + // %%TBD - xid should be randomized + // + Packet->secs = htons (DHCP4_INITIAL_SECONDS); + + Packet->flags = htons (DHCP4_BROADCAST_FLAG); + + if (Packet->hlen != 0) { + CopyMem (Packet->chaddr, &Private->Snp->Mode->CurrentAddress, Packet->hlen); + } + + Packet->magik = htonl (DHCP4_MAGIK_NUMBER); + + OpPtr = Packet->options; + + *OpPtr++ = DHCP4_MESSAGE_TYPE; + *OpPtr++ = 1; + *OpPtr++ = DHCP4_MESSAGE_TYPE_DISCOVER; + + *OpPtr++ = DHCP4_MAX_MESSAGE_SIZE; + *OpPtr++ = 2; + *OpPtr++ = (UINT8) ((DHCP4_DEFAULT_MAX_MESSAGE_SIZE >> 8) & 0xFF); + *OpPtr++ = (UINT8) (DHCP4_DEFAULT_MAX_MESSAGE_SIZE & 0xFF); + + *OpPtr++ = DHCP4_PARAMETER_REQUEST_LIST; + OpLen = OpPtr; + *OpPtr++ = 0; + *OpPtr++ = DHCP4_SUBNET_MASK; + *OpPtr++ = DHCP4_TIME_OFFSET; + *OpPtr++ = DHCP4_ROUTER_LIST; + *OpPtr++ = DHCP4_TIME_SERVERS; + *OpPtr++ = DHCP4_NAME_SERVERS; + *OpPtr++ = DHCP4_DNS_SERVERS; + *OpPtr++ = DHCP4_HOST_NAME; + *OpPtr++ = DHCP4_BOOT_FILE_SIZE; + *OpPtr++ = DHCP4_MESSAGE_TYPE; + *OpPtr++ = DHCP4_DOMAIN_NAME; + *OpPtr++ = DHCP4_ROOT_PATH; + *OpPtr++ = DHCP4_EXTENSION_PATH; + *OpPtr++ = DHCP4_MAX_DATAGRAM_SIZE; + *OpPtr++ = DHCP4_DEFAULT_TTL; + *OpPtr++ = DHCP4_BROADCAST_ADDRESS; + *OpPtr++ = DHCP4_NIS_DOMAIN_NAME; + *OpPtr++ = DHCP4_NIS_SERVERS; + *OpPtr++ = DHCP4_NTP_SERVERS; + *OpPtr++ = DHCP4_VENDOR_SPECIFIC; + *OpPtr++ = DHCP4_REQUESTED_IP_ADDRESS; + *OpPtr++ = DHCP4_LEASE_TIME; + *OpPtr++ = DHCP4_SERVER_IDENTIFIER; + *OpPtr++ = DHCP4_RENEWAL_TIME; + *OpPtr++ = DHCP4_REBINDING_TIME; + *OpPtr++ = DHCP4_CLASS_IDENTIFIER; + *OpPtr++ = DHCP4_TFTP_SERVER_NAME; + *OpPtr++ = DHCP4_BOOTFILE; + *OpPtr++ = 128; + *OpPtr++ = 129; + *OpPtr++ = 130; + *OpPtr++ = 131; + *OpPtr++ = 132; + *OpPtr++ = 133; + *OpPtr++ = 134; + *OpPtr++ = 135; + *OpLen = (UINT8) ((OpPtr - OpLen) - 1); + + *OpPtr++ = DHCP4_END; + + This->Data->SetupCompleted = TRUE; + + return EFI_SUCCESS; +} + +/* eof - PxeDhcp4Setup.c */ diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/build.xml b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/build.xml new file mode 100644 index 0000000000..e7afd62b68 --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/support.c b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/support.c new file mode 100644 index 0000000000..50c991372d --- /dev/null +++ b/EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/support.c @@ -0,0 +1,1126 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + support.c + +Abstract: + Miscellaneous support routines for PxeDhcp4 protocol. + +--*/ + + +#include "PxeDhcp4.h" + +#define DebugPrint(x) +// +// #define DebugPrint(x) Aprint x +// + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +UINT16 +htons ( + UINTN n + ) +{ + return (UINT16) ((n >> 8) | (n << 8)); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +UINT32 +htonl ( + UINTN n + ) +{ + return (UINT32) ((n >> 24) | ((n >> 8) & 0xFF00) | ((n & 0xFF00) << 8) | (n << 24)); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +EFIAPI +timeout_notify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + ASSERT (Context); + + if (Context != NULL) { + ((PXE_DHCP4_PRIVATE_DATA *) Context)->TimeoutOccurred = TRUE; + } +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +EFIAPI +periodic_notify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + ASSERT (Context); + + if (Context != NULL) { + ((PXE_DHCP4_PRIVATE_DATA *) Context)->PeriodicOccurred = TRUE; + } +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +find_opt ( + IN DHCP4_PACKET *Packet, + IN UINT8 OpCode, + IN UINTN Skip, + OUT DHCP4_OP **OpPtr + ) +/*++ +Routine description: + Locate option inside DHCP packet. + +Parameters: + Packet := Pointer to DHCP packet structure. + OpCode := Option op-code to find. + Skip := Number of found op-codes to skip. + OpPtr := Pointer to found op-code pointer. + +Returns: + EFI_SUCCESS := Option was found + EFI_INVALID_PARAMETER := Packet == NULL || OpPtr == NULL + EFI_INVALID_PARAMETER := OpCode == DHCP4_PAD + EFI_INVALID_PARAMETER := OpCode == DHCP4_END && Skip != 0 + EFI_INVALID_PARAMETER := DHCP magik number in Packet is not valid + EFI_NOT_FOUND := op-code was not found in packet + EFI_INVALID_PARAMETER := If present, DHCP_MAX_MESSAGE_SIZE option + does not have a valid value. +--*/ +{ + UINTN msg_size; + UINTN buf_len; + UINTN n; + UINT8 *buf; + UINT8 *end_ptr; + UINT8 overload; + + // + // Verify parameters. + // + if (Packet == NULL || OpPtr == NULL || OpCode == DHCP4_PAD || (OpCode == DHCP4_END && Skip != 0)) { + return EFI_INVALID_PARAMETER; + } + + if (Packet->dhcp4.magik != htonl (DHCP4_MAGIK_NUMBER)) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize search variables. + // + *OpPtr = NULL; + + msg_size = DHCP4_MAX_PACKET_SIZE - (DHCP4_UDP_HEADER_SIZE + DHCP4_IP_HEADER_SIZE); + + overload = 0; + end_ptr = NULL; + + buf = Packet->dhcp4.options; + buf_len = msg_size - (Packet->dhcp4.options - Packet->raw); + + // + // Start searching for requested option. + // + for (n = 0;;) { + // + // If match is found, decrement skip count and return + // when desired match is found. + // + if (buf[n] == OpCode) { + *OpPtr = (DHCP4_OP *) &buf[n]; + + if (Skip-- == 0) { + return EFI_SUCCESS; + } + } + // + // Skip past current option. Check for option overload + // and message size options since these will affect the + // amount of data to be searched. + // + switch (buf[n]) { + case DHCP4_PAD: + // + // Remember the first pad byte of a group. This + // could be the end of a badly formed packet. + // + if (end_ptr == NULL) { + end_ptr = &buf[n]; + } + + ++n; + break; + + case DHCP4_END: + // + // If we reach the end we are done. + // + end_ptr = NULL; + return EFI_NOT_FOUND; + + case DHCP4_OPTION_OVERLOAD: + // + // Remember the option overload value since it + // could cause the search to continue into + // the fname and sname fields. + // + end_ptr = NULL; + + if (buf[n + 1] == 1) { + overload = buf[n + 2]; + } + + n += 2 + buf[n + 1]; + break; + + case DHCP4_MAX_MESSAGE_SIZE: + // + // Remember the message size value since it could + // change the amount of option buffer to search. + // + end_ptr = NULL; + + if (buf[n + 1] == 2 && buf == Packet->dhcp4.options) { + msg_size = ((buf[n + 2] << 8) | buf[n + 3]) - (DHCP4_UDP_HEADER_SIZE + DHCP4_IP_HEADER_SIZE); + + if (msg_size < 328) { + return EFI_INVALID_PARAMETER; + } + + buf_len = msg_size - (Packet->dhcp4.options - Packet->raw); + + if (n + 2 + buf[n + 1] > buf_len) { + return EFI_INVALID_PARAMETER; + } + } + + /* fall thru */ + default: + end_ptr = NULL; + + n += 2 + buf[n + 1]; + } + // + // Keep searching until the end of the buffer is reached. + // + if (n < buf_len) { + continue; + } + // + // Reached end of current buffer. Check if we are supposed + // to search the fname and sname buffers. + // + if (buf == Packet->dhcp4.options && + (overload == DHCP4_OVERLOAD_FNAME || overload == DHCP4_OVERLOAD_FNAME_AND_SNAME) + ) { + buf = Packet->dhcp4.fname; + buf_len = 128; + n = 0; + continue; + } + + if (buf != Packet->dhcp4.sname && (overload == DHCP4_OVERLOAD_SNAME || overload == DHCP4_OVERLOAD_FNAME_AND_SNAME)) { + buf = Packet->dhcp4.sname; + buf_len = 64; + n = 0; + continue; + } + // + // End of last buffer reached. If this was a search + // for the end of the options, go back to the start + // of the current pad block. + // + if (OpCode == DHCP4_END && end_ptr != NULL) { + *OpPtr = (DHCP4_OP *) end_ptr; + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; + } +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +add_opt ( + IN DHCP4_PACKET *Packet, + IN DHCP4_OP *OpPtr + ) +/*++ +Routine description: + Add option to DHCP packet. + +Parameters: + Packet := Pointer to DHCP packet structure. + OpPtr := Pointer to DHCP option. + +Returns: + EFI_INVALID_PARAMETER := Packet == NULL || OpPtr == NULL + EFI_INVALID_PARAMETER := OpPtr->op == DHCP4_PAD || OpPtr->op == DHCP4_END + EFI_INVALID_PARAMETER := DHCP magik number in DHCP packet is not valid + EFI_INVALID_PARAMETER := If DHCP_MAX_MESSAGE_SIZE option is present and + is not valid + EFI_INVALID_PARAMETER := If DHCP_OPTION_OVERLOAD option is present and + is not valid + EFI_DEVICE_ERROR := Cannot determine end of packet + EFI_BUFFER_TOO_SMALL := Not enough room in packet to add option + EFI_SUCCESS := Option added to DHCP packet +--*/ +{ + EFI_STATUS efi_status; + DHCP4_OP *msg_size_op; + DHCP4_OP *overload_op; + DHCP4_OP *op; + UINTN msg_size; + UINTN buf_len; + UINT32 magik; + UINT8 *buf; + + // + // Verify parameters. + // + ASSERT (Packet); + ASSERT (OpPtr); + + if (Packet == NULL || OpPtr == NULL) { + return EFI_INVALID_PARAMETER; + } + + switch (OpPtr->op) { + case DHCP4_PAD: + case DHCP4_END: + // + // No adding PAD or END. + // + return EFI_INVALID_PARAMETER; + } + // + // Check the DHCP magik number. + // + CopyMem (&magik, &Packet->dhcp4.magik, 4); + + if (magik != htonl (DHCP4_MAGIK_NUMBER)) { + return EFI_INVALID_PARAMETER; + } + // + // Find the DHCP message size option. + // + msg_size = DHCP4_DEFAULT_MAX_MESSAGE_SIZE; + + efi_status = find_opt ( + Packet, + DHCP4_MAX_MESSAGE_SIZE, + 0, + &msg_size_op + ); + + if (EFI_ERROR (efi_status)) { + if (efi_status != EFI_NOT_FOUND) { + DebugPrint ( + ("%s:%d:%r\n", + __FILE__, + __LINE__, + efi_status) + ); + return efi_status; + } + + msg_size_op = NULL; + } else { + CopyMem (&msg_size, msg_size_op->data, 2); + msg_size = htons (msg_size); + + if (msg_size < DHCP4_DEFAULT_MAX_MESSAGE_SIZE) { + return EFI_INVALID_PARAMETER; + } + } + // + // Find the DHCP option overload option. + // + efi_status = find_opt ( + Packet, + DHCP4_OPTION_OVERLOAD, + 0, + &overload_op + ); + + if (EFI_ERROR (efi_status)) { + if (efi_status != EFI_NOT_FOUND) { + DebugPrint ( + ("%s:%d:%r\n", + __FILE__, + __LINE__, + efi_status) + ); + return efi_status; + } + + overload_op = NULL; + } else { + if (overload_op->len != 1) { + return EFI_INVALID_PARAMETER; + } + + switch (overload_op->data[0]) { + case 1: + case 2: + case 3: + break; + + default: + return EFI_INVALID_PARAMETER; + } + } + // + // Find the end of the packet. + // + efi_status = find_opt (Packet, DHCP4_END, 0, &op); + + if (EFI_ERROR (efi_status)) { + return EFI_INVALID_PARAMETER; + } + // + // Find which buffer the end is in. + // + if ((UINTN) op >= (UINTN) (buf = Packet->dhcp4.options)) { + buf_len = (msg_size - ((UINT8 *) &Packet->dhcp4.options - (UINT8 *) &Packet->raw)) - (DHCP4_UDP_HEADER_SIZE + DHCP4_IP_HEADER_SIZE); + } else if ((UINTN) op >= (UINTN) (buf = Packet->dhcp4.fname)) { + buf_len = 128; + } else if ((UINTN) op >= (UINTN) (buf = Packet->dhcp4.sname)) { + buf_len = 64; + } else { + return EFI_DEVICE_ERROR; + } + // + // Add option to current buffer if there is no overlow. + // + if ((UINTN) ((&op->op - buf) + 3 + op->len) < buf_len) { + CopyMem (op, OpPtr, OpPtr->len + 2); + + op->data[op->len] = DHCP4_END; + + return EFI_SUCCESS; + } + // + // Error if there is no space for option. + // + return EFI_BUFFER_TOO_SMALL; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +start_udp ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN OPTIONAL EFI_IP_ADDRESS *StationIp, + IN OPTIONAL EFI_IP_ADDRESS *SubnetMask + ) +/*++ +Routine description: + Setup PXE BaseCode UDP stack. + +Parameters: + Private := Pointer to PxeDhcp4 private data. + StationIp := Pointer to IP address or NULL if not known. + SubnetMask := Pointer to subnet mask or NULL if not known. + +Returns: + EFI_INVALID_PARAMETER := Private == NULL || Private->PxeBc == NULL + EFI_INVALID_PARAMETER := Only one of StationIp and SubnetMask is given + EFI_SUCCESS := UDP stack is ready + other := Error from PxeBc->SetIpFilter() or PxeBc->SetStationIp() +--*/ +{ + EFI_PXE_BASE_CODE_IP_FILTER bcast_filter; + EFI_STATUS efi_status; + + // + // + // + ASSERT (Private); + ASSERT (Private->PxeBc); + + if (Private == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (Private->PxeBc == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (StationIp != NULL && SubnetMask == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (StationIp == NULL && SubnetMask != NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Setup broadcast receive filter... + // + ZeroMem (&bcast_filter, sizeof (EFI_PXE_BASE_CODE_IP_FILTER)); + + bcast_filter.Filters = EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST; + bcast_filter.IpCnt = 0; + + efi_status = Private->PxeBc->SetIpFilter ( + Private->PxeBc, + &bcast_filter + ); + + if (EFI_ERROR (efi_status)) { + DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status)); + return efi_status; + } + // + // Configure station IP address and subnet mask... + // + efi_status = Private->PxeBc->SetStationIp ( + Private->PxeBc, + StationIp, + SubnetMask + ); + + if (EFI_ERROR (efi_status)) { + DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status)); + } + + return efi_status; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +stop_udp ( + IN PXE_DHCP4_PRIVATE_DATA *Private + ) +{ + // + // + // + ASSERT (Private); + ASSERT (Private->PxeBc); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +start_receive_events ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN UINTN SecondsTimeout + ) +/*++ +Routine description: + Create periodic and timeout receive events. + +Parameters: + Private := Pointer to PxeDhcp4 private data. + SecondsTimeout := Number of seconds to wait before timeout. + +Returns: +--*/ +{ + EFI_STATUS efi_status; + UINTN random; + + // + // + // + ASSERT (Private); + ASSERT (SecondsTimeout); + + if (Private == NULL || SecondsTimeout == 0) { + return EFI_INVALID_PARAMETER; + } + // + // Need a bettern randomizer... + // For now adjust the timeout value by the least significant + // digit in the MAC address. + // + random = 0; + + if (Private->PxeDhcp4.Data != NULL) { + if (Private->PxeDhcp4.Data->Discover.dhcp4.hlen != 0 && Private->PxeDhcp4.Data->Discover.dhcp4.hlen <= 16) { + random = 0xFFF & Private->PxeDhcp4.Data->Discover.dhcp4.chaddr[Private->PxeDhcp4.Data->Discover.dhcp4.hlen - 1]; + } + } + // + // Setup timeout event and start timer. + // + efi_status = gBS->CreateEvent ( + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_NOTIFY, + &timeout_notify, + Private, + &Private->TimeoutEvent + ); + + if (EFI_ERROR (efi_status)) { + DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status)); + return efi_status; + } + + efi_status = gBS->SetTimer ( + Private->TimeoutEvent, + TimerRelative, + SecondsTimeout * 10000000 + random + ); + + if (EFI_ERROR (efi_status)) { + DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status)); + gBS->CloseEvent (Private->TimeoutEvent); + return efi_status; + } + + Private->TimeoutOccurred = FALSE; + + // + // Setup periodic event for callbacks + // + efi_status = gBS->CreateEvent ( + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_NOTIFY, + &periodic_notify, + Private, + &Private->PeriodicEvent + ); + + if (EFI_ERROR (efi_status)) { + DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status)); + gBS->CloseEvent (Private->TimeoutEvent); + return efi_status; + } + + efi_status = gBS->SetTimer ( + Private->PeriodicEvent, + TimerPeriodic, + 1000000 + ); /* 1/10th second */ + + if (EFI_ERROR (efi_status)) { + DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status)); + gBS->CloseEvent (Private->TimeoutEvent); + gBS->CloseEvent (Private->PeriodicEvent); + return efi_status; + } + + Private->PeriodicOccurred = FALSE; + + return EFI_SUCCESS; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +VOID +stop_receive_events ( + IN PXE_DHCP4_PRIVATE_DATA *Private + ) +{ + // + // + // + ASSERT (Private); + + if (Private == NULL) { + return ; + } + // + // + // + gBS->CloseEvent (Private->TimeoutEvent); + Private->TimeoutOccurred = FALSE; + + // + // + // + gBS->CloseEvent (Private->PeriodicEvent); + Private->PeriodicOccurred = FALSE; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +tx_udp ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN EFI_IP_ADDRESS *dest_ip, + IN OPTIONAL EFI_IP_ADDRESS *gateway_ip, + IN EFI_IP_ADDRESS *src_ip, + IN VOID *buffer, + IN UINTN BufferSize + ) +/*++ +Routine description: + Transmit DHCP packet. + +Parameters: + Private := Pointer to PxeDhcp4 private data + dest_ip := Pointer to destination IP address + gateway_ip := Pointer to gateway IP address or NULL + src_ip := Pointer to source IP address or NULL + buffer := Pointer to buffer to transmit + BufferSize := Size of buffer in bytes + +Returns: + EFI_INVALID_PARAMETER := Private == NULL || dest_ip == NULL || + buffer == NULL || BufferSize < 300 || Private->PxeBc == NULL + EFI_SUCCESS := Buffer was transmitted + other := Return from PxeBc->UdpWrite() +--*/ +{ + EFI_PXE_BASE_CODE_UDP_PORT dest_port; + EFI_PXE_BASE_CODE_UDP_PORT src_port; + EFI_IP_ADDRESS zero_ip; + + // + // + // + ASSERT (Private); + ASSERT (dest_ip); + ASSERT (buffer); + ASSERT (BufferSize >= 300); + + if (Private == NULL || dest_ip == NULL || buffer == NULL || BufferSize < 300) { + return EFI_INVALID_PARAMETER; + } + + ASSERT (Private->PxeBc); + + if (Private->PxeBc == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Transmit DHCP discover packet... + // + ZeroMem (&zero_ip, sizeof (EFI_IP_ADDRESS)); + + if (src_ip == NULL) { + src_ip = &zero_ip; + } + + dest_port = DHCP4_SERVER_PORT; + src_port = DHCP4_CLIENT_PORT; + + return Private->PxeBc->UdpWrite ( + Private->PxeBc, + EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT, + dest_ip, + &dest_port, + gateway_ip, + src_ip, + &src_port, + NULL, + NULL, + &BufferSize, + buffer + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +rx_udp ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + OUT VOID *buffer, + IN OUT UINTN *BufferSize, + IN OUT EFI_IP_ADDRESS *dest_ip, + IN OUT EFI_IP_ADDRESS *src_ip, + IN UINT16 op_flags + ) +/*++ +Routine description: + Receive DHCP packet. + +Parameters: + Private := Pointer to PxeDhcp4 private data + buffer := Pointer to buffer to receive DHCP packet + BufferSize := Pointer to buffer size in bytes + dest_ip := Pointer to destination IP address + src_ip := Pointer to source IP address + op_flags := UDP receive operation flags + +Returns: + EFI_INVALID_PARAMETER := + EFI_SUCCESS := Packet received + other := Return from PxeBc->UdpRead() +--*/ +{ + EFI_PXE_BASE_CODE_UDP_PORT dest_port; + EFI_PXE_BASE_CODE_UDP_PORT src_port; + + // + // + // + ASSERT (Private); + ASSERT (buffer); + ASSERT (dest_ip); + ASSERT (src_ip); + + if (Private == NULL || buffer == NULL || dest_ip == NULL || src_ip == NULL || BufferSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + ASSERT (Private->PxeBc); + + if (Private->PxeBc == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Check for packet + // + *BufferSize = sizeof (DHCP4_PACKET); + + dest_port = DHCP4_CLIENT_PORT; + src_port = DHCP4_SERVER_PORT; + + return Private->PxeBc->UdpRead ( + Private->PxeBc, + op_flags, + dest_ip, + &dest_port, + src_ip, + &src_port, + NULL, + NULL, + BufferSize, + buffer + ); +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +EFI_STATUS +tx_rx_udp ( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN OUT EFI_IP_ADDRESS *ServerIp, + IN OPTIONAL EFI_IP_ADDRESS *gateway_ip, + IN OPTIONAL EFI_IP_ADDRESS *client_ip, + IN OPTIONAL EFI_IP_ADDRESS *SubnetMask, + IN DHCP4_PACKET *tx_pkt, + OUT DHCP4_PACKET *rx_pkt, + IN INTN (*rx_vfy)( + IN PXE_DHCP4_PRIVATE_DATA *Private, + IN DHCP4_PACKET *tx_pkt, + IN DHCP4_PACKET *rx_pkt, + IN UINTN rx_pkt_size + ), + IN UINTN SecondsTimeout + ) +/*++ +Routine description: + Transmit DHCP packet and wait for replies. + +Parameters: + Private := Pointer to PxeDhcp4 private data + ServerIp := Pointer to server IP address + gateway_ip := Pointer to gateway IP address or NULL + client_ip := Pointer to client IP address or NULL + SubnetMask := Pointer to subnet mask or NULL + tx_pkt := Pointer to DHCP packet to transmit + rx_pkt := Pointer to DHCP packet receive buffer + rx_vfy := Pointer to DHCP packet receive verification routine + SecondsTimeout := Number of seconds until timeout + +Returns: + EFI_INVALID_PARAMETER := Private == NULL || ServerIp == NULL || + tx_pkt == NULL || rx_pkt == NULL || rx_vfy == NULL || Private->PxeBc == NULL + EFI_ABORTED := Receive aborted + EFI_TIMEOUT := No packets received + EFI_SUCCESS := Packet(s) received + other := Returns from other PxeDhcp4 support routines +--*/ +{ + EFI_PXE_DHCP4_CALLBACK_STATUS CallbackStatus; + EFI_IP_ADDRESS dest_ip; + EFI_IP_ADDRESS src_ip; + EFI_STATUS efi_status; + DHCP4_OP *msg_size_op; + UINTN pkt_size; + UINTN n; + UINT16 msg_size; + UINT16 op_flags; + BOOLEAN done_flag; + BOOLEAN got_packet; + + // + // Bad programmer check... + // + ASSERT (Private); + ASSERT (ServerIp); + ASSERT (tx_pkt); + ASSERT (rx_pkt); + ASSERT (rx_vfy); + + if (Private == NULL || ServerIp == NULL || tx_pkt == NULL || rx_pkt == NULL || rx_vfy == NULL) { + return EFI_INVALID_PARAMETER; + } + + ASSERT (Private->PxeBc); + + if (Private->PxeBc == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Enable UDP... + // + efi_status = start_udp (Private, client_ip, SubnetMask); + + if (EFI_ERROR (efi_status)) { + DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status)); + return efi_status; + } + // + // Get length of transmit packet... + // + msg_size = DHCP4_DEFAULT_MAX_MESSAGE_SIZE; + + efi_status = find_opt ( + tx_pkt, + DHCP4_MAX_MESSAGE_SIZE, + 0, + &msg_size_op + ); + + if (!EFI_ERROR (efi_status)) { + CopyMem (&msg_size, msg_size_op->data, 2); + + if ((msg_size = htons (msg_size)) < 328) { + msg_size = 328; + } + } + // + // Transmit packet... + // + efi_status = tx_udp ( + Private, + ServerIp, + gateway_ip, + client_ip, + tx_pkt, + msg_size - (DHCP4_UDP_HEADER_SIZE + DHCP4_IP_HEADER_SIZE) + ); + + if (EFI_ERROR (efi_status)) { + DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status)); + stop_udp (Private); + return efi_status; + } + // + // Enable periodic and timeout events... + // + efi_status = start_receive_events (Private, SecondsTimeout); + + if (EFI_ERROR (efi_status)) { + DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status)); + stop_udp (Private); + return efi_status; + } + // + // Wait for packet(s)... + // +#if 0 + if (!client_ip) { + Aprint ("client_ip == NULL "); + } else { + Aprint ( + "client_ip == %d.%d.%d.%d ", + client_ip->v4.Addr[0], + client_ip->v4.Addr[1], + client_ip->v4.Addr[2], + client_ip->v4.Addr[3] + ); + } + + if (!ServerIp) { + Aprint ("ServerIp == NULL\n"); + } else { + Aprint ( + "ServerIp == %d.%d.%d.%d\n", + ServerIp->v4.Addr[0], + ServerIp->v4.Addr[1], + ServerIp->v4.Addr[2], + ServerIp->v4.Addr[3] + ); + } +#endif + + done_flag = FALSE; + got_packet = FALSE; + + while (!done_flag) { + // + // Check for timeout event... + // + if (Private->TimeoutOccurred) { + efi_status = EFI_SUCCESS; + break; + } + // + // Check for periodic event... + // + if (Private->PeriodicOccurred && Private->callback != NULL) { + CallbackStatus = EFI_PXE_DHCP4_CALLBACK_STATUS_CONTINUE; + + if (Private->callback->Callback != NULL) { + CallbackStatus = (Private->callback->Callback) (&Private->PxeDhcp4, Private->function, 0, NULL); + } + + switch (CallbackStatus) { + case EFI_PXE_DHCP4_CALLBACK_STATUS_CONTINUE: + break; + + case EFI_PXE_DHCP4_CALLBACK_STATUS_ABORT: + default: + stop_receive_events (Private); + stop_udp (Private); + return EFI_ABORTED; + } + + Private->PeriodicOccurred = FALSE; + } + // + // Check for packet... + // + if (client_ip == NULL) { + SetMem (&dest_ip, sizeof (EFI_IP_ADDRESS), 0xFF); + } else { + CopyMem (&dest_ip, client_ip, sizeof (EFI_IP_ADDRESS)); + } + + SetMem (&src_ip, sizeof (EFI_IP_ADDRESS), 0xFF); + + if (CompareMem (&src_ip, &ServerIp, sizeof (EFI_IP_ADDRESS))) { + ZeroMem (&src_ip, sizeof (EFI_IP_ADDRESS)); + op_flags = EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP; + } else { + op_flags = 0; + } + + efi_status = rx_udp ( + Private, + rx_pkt, + &pkt_size, + &dest_ip, + &src_ip, + op_flags + ); + + if (efi_status == EFI_TIMEOUT) { + efi_status = EFI_SUCCESS; + continue; + } + + if (EFI_ERROR (efi_status)) { + break; + } + // + // Some basic packet sanity checks.. + // + if (pkt_size < 300) { + continue; + } + + if (rx_pkt->dhcp4.op != BOOTP_REPLY) { + continue; + } + + if (tx_pkt->dhcp4.htype != rx_pkt->dhcp4.htype) { + continue; + } + + if ((n = tx_pkt->dhcp4.hlen) != rx_pkt->dhcp4.hlen) { + continue; + } + + if (CompareMem (&tx_pkt->dhcp4.xid, &rx_pkt->dhcp4.xid, 4)) { + continue; + } + + if (n != 0) { + if (n >= 16) { + n = 16; + } + + if (CompareMem (tx_pkt->dhcp4.chaddr, rx_pkt->dhcp4.chaddr, n)) { + continue; + } + } + // + // Internal callback packet verification... + // + switch ((*rx_vfy) (Private, tx_pkt, rx_pkt, pkt_size)) { + case -2: /* ignore and stop */ + stop_receive_events (Private); + stop_udp (Private); + return EFI_ABORTED; + + case -1: /* ignore and wait */ + continue; + + case 0: /* accept and wait */ + break; + + case 1: /* accept and stop */ + done_flag = TRUE; + break; + + default: + ASSERT (0); + } + // + // External callback packet verification... + // + CallbackStatus = EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_CONTINUE; + + if (Private->callback != NULL) { + if (Private->callback->Callback != NULL) { + CallbackStatus = (Private->callback->Callback) (&Private->PxeDhcp4, Private->function, (UINT32) pkt_size, rx_pkt); + } + } + + switch (CallbackStatus) { + case EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_CONTINUE: + continue; + + case EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_ABORT: + done_flag = TRUE; + break; + + case EFI_PXE_DHCP4_CALLBACK_STATUS_IGNORE_ABORT: + stop_receive_events (Private); + stop_udp (Private); + return EFI_ABORTED; + + case EFI_PXE_DHCP4_CALLBACK_STATUS_KEEP_CONTINUE: + default: + break; + } + // + // We did! We did get a packet! + // + got_packet = TRUE; + } + // + // + // + stop_receive_events (Private); + stop_udp (Private); + + if (EFI_ERROR (efi_status)) { + DebugPrint (("%s:%d:%r\n", __FILE__, __LINE__, efi_status)); + return efi_status; + } + + if (got_packet) { + return EFI_SUCCESS; + } else { + return EFI_TIMEOUT; + } +} + +/* eof - support.c */ diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/ComponentName.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/ComponentName.c new file mode 100644 index 0000000000..3cc2d98440 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/ComponentName.c @@ -0,0 +1,160 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "Snp.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +SimpleNetworkComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +SimpleNetworkComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gSimpleNetworkComponentName = { + SimpleNetworkComponentNameGetDriverName, + SimpleNetworkComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mSimpleNetworkDriverNameTable[] = { + { + "eng", + (CHAR16 *) L"Simple Network Protocol Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +SimpleNetworkComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gSimpleNetworkComponentName.SupportedLanguages, + mSimpleNetworkDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +SimpleNetworkComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/SNP.mbd b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/SNP.mbd new file mode 100644 index 0000000000..293812b304 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/SNP.mbd @@ -0,0 +1,41 @@ + + + + + SNP + A2f436EA-A127-4EF8-957C-8048606FF670 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + DxeMemoryAllocationLib + + diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/SNP.msa b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/SNP.msa new file mode 100644 index 0000000000..c8ce3d78dd --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/SNP.msa @@ -0,0 +1,85 @@ + + + + + SNP + UEFI_DRIVER + BS_DRIVER + A2f436EA-A127-4EF8-957C-8048606FF670 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + callback.c + get_status.c + initialize.c + mcast_ip_to_mac.c + nvdata.c + receive.c + receive_filters.c + reset.c + shutdown.c + snp.c + snp.h + start.c + station_address.c + statistics.c + stop.c + transmit.c + WaitForPacket.c + ComponentName.c + + + MdePkg + EdkModulePkg + + + SimpleNetwork + PciIo + DevicePath + NetworkInterfaceIdentifier + NetworkInterfaceIdentifier2 + + + + + + + + mSimpleNetworkDriverBinding + gSimpleNetworkComponentName + + + diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/WaitForPacket.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/WaitForPacket.c new file mode 100644 index 0000000000..dff0da1a63 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/WaitForPacket.c @@ -0,0 +1,100 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + WaitForPacket.c + +Abstract: + Event handler to check for available packet. + +--*/ + + +#include "snp.h" + +VOID +EFIAPI +SnpWaitForPacketNotify ( + EFI_EVENT Event, + VOID *SnpPtr + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + PXE_DB_GET_STATUS PxeDbGetStatus; + + // + // Do nothing if either parameter is a NULL pointer. + // + if (Event == NULL || SnpPtr == NULL) { + return ; + } + // + // Do nothing if the SNP interface is not initialized. + // + switch (((SNP_DRIVER *) SnpPtr)->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + case EfiSimpleNetworkStarted: + default: + return ; + } + // + // Fill in CDB for UNDI GetStatus(). + // + ((SNP_DRIVER *) SnpPtr)->cdb.OpCode = PXE_OPCODE_GET_STATUS; + ((SNP_DRIVER *) SnpPtr)->cdb.OpFlags = 0; + ((SNP_DRIVER *) SnpPtr)->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + ((SNP_DRIVER *) SnpPtr)->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + ((SNP_DRIVER *) SnpPtr)->cdb.DBsize = sizeof (UINT32) * 2; + ((SNP_DRIVER *) SnpPtr)->cdb.DBaddr = (UINT64) (UINTN) (((SNP_DRIVER *) SnpPtr)->db); + ((SNP_DRIVER *) SnpPtr)->cdb.StatCode = PXE_STATCODE_INITIALIZE; + ((SNP_DRIVER *) SnpPtr)->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + ((SNP_DRIVER *) SnpPtr)->cdb.IFnum = ((SNP_DRIVER *) SnpPtr)->if_num; + ((SNP_DRIVER *) SnpPtr)->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Clear contents of DB buffer. + // + ZeroMem (((SNP_DRIVER *) SnpPtr)->db, sizeof (UINT32) * 2); + + // + // Issue UNDI command and check result. + // + (*((SNP_DRIVER *) SnpPtr)->issue_undi32_command) ((UINT64) (UINTN) &((SNP_DRIVER *) SnpPtr)->cdb); + + if (((SNP_DRIVER *) SnpPtr)->cdb.StatCode != EFI_SUCCESS) { + return ; + } + // + // We might have a packet. Check the receive length and signal + // the event if the length is not zero. + // + CopyMem ( + &PxeDbGetStatus, + ((SNP_DRIVER *) SnpPtr)->db, + sizeof (UINT32) * 2 + ); + + if (PxeDbGetStatus.RxFrameLen != 0) { + gBS->SignalEvent (Event); + } +} + +/* eof - WaitForPacket.c */ diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/build.xml b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/build.xml new file mode 100644 index 0000000000..7387603fb3 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/callback.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/callback.c new file mode 100644 index 0000000000..488efc6a01 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/callback.c @@ -0,0 +1,613 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + callback.c + +Abstract: + This file contains two sets of callback routines for undi3.0 and undi3.1. + the callback routines for Undi3.1 have an extra parameter UniqueId which + stores the interface context for the NIC that snp is trying to talk.. + +--*/ + + +#include "snp.h" + +// +// Global variables +// these 2 global variables are used only for 3.0 undi. we could not place +// them in the snp structure because we will not know which snp structure +// in the callback context! +// +STATIC BOOLEAN mInitializeLock = TRUE; +STATIC EFI_LOCK mLock; + +// +// End Global variables +// +extern EFI_PCI_IO_PROTOCOL *mPciIoFncs; + +VOID +snp_undi32_callback_v2p_30 ( + IN UINT64 CpuAddr, + IN OUT UINT64 DeviceAddrPtr + ) +/*++ + +Routine Description: + This is a callback routine supplied to UNDI at undi_start time. + UNDI call this routine with a virtual or CPU address that SNP provided + to convert it to a physical or device address. Since EFI uses the identical + mapping, this routine returns the physical address same as the virtual address + for most of the addresses. an address above 4GB cannot generally be used as a + device address, it needs to be mapped to a lower physical address. This routine + does not call the map routine itself, but it assumes that the mapping was done + at the time of providing the address to UNDI. This routine just looks up the + address in a map table (which is the v2p structure chain) + +Arguments: + CpuAddr - virtual address of a buffer + DeviceAddrPtr - pointer to the physical address + +Returns: + void - The DeviceAddrPtr will contain 0 in case of any error + +--*/ +{ + struct s_v2p *v2p; + // + // Do nothing if virtual address is zero or physical pointer is NULL. + // No need to map if the virtual address is within 4GB limit since + // EFI uses identical mapping + // + if ((CpuAddr == 0) || (DeviceAddrPtr == 0)) { + DEBUG ((EFI_D_ERROR, "\nv2p: Null virtual address or physical pointer.\n")); + return ; + } + + if (CpuAddr < FOUR_GIGABYTES) { + *(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr; + return ; + } + // + // SNP creates a vaddr tp paddr mapping at the time of calling undi with any + // big address, this callback routine just looks up in the v2p list and + // returns the physical address for any given virtual address. + // + if (find_v2p (&v2p, (VOID *) (UINTN) CpuAddr) != EFI_SUCCESS) { + *(UINT64 *) (UINTN) DeviceAddrPtr = CpuAddr; + } else { + *(UINT64 *) (UINTN) DeviceAddrPtr = v2p->paddr; + } +} + +VOID +snp_undi32_callback_block_30 ( + IN UINT32 Enable + ) +/*++ + +Routine Description: + This is a callback routine supplied to UNDI at undi_start time. + UNDI call this routine when it wants to have exclusive access to a critical + section of the code/data + +Arguments: + Enable - non-zero indicates acquire + zero indicates release + +Returns: + void +--*/ +{ + // + // tcpip was calling snp at tpl_notify and if we acquire a lock that was + // created at a lower level (TPL_CALLBACK) it gives an assert! + // + if (mInitializeLock) { + EfiInitializeLock (&mLock, EFI_TPL_NOTIFY); + mInitializeLock = FALSE; + } + + if (Enable != 0) { + EfiAcquireLock (&mLock); + } else { + EfiReleaseLock (&mLock); + } +} + +VOID +snp_undi32_callback_delay_30 ( + IN UINT64 MicroSeconds + ) +/*++ + +Routine Description: + This is a callback routine supplied to UNDI at undi_start time. + UNDI call this routine with the number of micro seconds when it wants to + pause. + +Arguments: + MicroSeconds - number of micro seconds to pause, ususlly multiple of 10 + +Returns: + void +--*/ +{ + if (MicroSeconds != 0) { + gBS->Stall ((UINTN) MicroSeconds); + } +} + +VOID +snp_undi32_callback_memio_30 ( + IN UINT8 ReadOrWrite, + IN UINT8 NumBytes, + IN UINT64 Address, + IN OUT UINT64 BufferAddr + ) +/*++ + +Routine Description: + This is a callback routine supplied to UNDI at undi_start time. + This is the IO routine for UNDI. This is not currently being used by UNDI3.0 + because Undi3.0 uses io/mem offsets relative to the beginning of the device + io/mem address and so it needs to use the PCI_IO_FUNCTION that abstracts the + start of the device's io/mem addresses. Since SNP cannot retrive the context + of the undi3.0 interface it cannot use the PCI_IO_FUNCTION that specific for + that NIC and uses one global IO functions structure, this does not work. + This however works fine for EFI1.0 Undis because they use absolute addresses + for io/mem access. + +Arguments: + ReadOrWrite - indicates read or write, IO or Memory + NumBytes - number of bytes to read or write + Address - IO or memory address to read from or write to + BufferAddr - memory location to read into or that contains the bytes + to write + +Returns: + +--*/ +{ + EFI_PCI_IO_PROTOCOL_WIDTH Width; + + switch (NumBytes) { + case 2: + Width = 1; + break; + + case 4: + Width = 2; + break; + + case 8: + Width = 3; + break; + + default: + Width = 0; + } + + switch (ReadOrWrite) { + case PXE_IO_READ: + mPciIoFncs->Io.Read ( + mPciIoFncs, + Width, + 1, // BAR 1, IO base address + Address, + 1, // count + (VOID *) (UINTN) BufferAddr + ); + break; + + case PXE_IO_WRITE: + mPciIoFncs->Io.Write ( + mPciIoFncs, + Width, + 1, // BAR 1, IO base address + Address, + 1, // count + (VOID *) (UINTN) BufferAddr + ); + break; + + case PXE_MEM_READ: + mPciIoFncs->Mem.Read ( + mPciIoFncs, + Width, + 0, // BAR 0, Memory base address + Address, + 1, // count + (VOID *) (UINTN) BufferAddr + ); + break; + + case PXE_MEM_WRITE: + mPciIoFncs->Mem.Write ( + mPciIoFncs, + Width, + 0, // BAR 0, Memory base address + Address, + 1, // count + (VOID *) (UINTN) BufferAddr + ); + break; + } + + return ; +} +// +// New callbacks for 3.1: +// there won't be a virtual2physical callback for UNDI 3.1 because undi3.1 uses +// the MemMap call to map the required address by itself! +// +VOID +snp_undi32_callback_block ( + IN UINT64 UniqueId, + IN UINT32 Enable + ) +/*++ + +Routine Description: + This is a callback routine supplied to UNDI3.1 at undi_start time. + UNDI call this routine when it wants to have exclusive access to a critical + section of the code/data + +Arguments: + UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store + Undi interface context (Undi does not read or write this variable) + Enable - non-zero indicates acquire + zero indicates release + +Returns: + void + +--*/ +{ + SNP_DRIVER *snp; + + snp = (SNP_DRIVER *) (UINTN) UniqueId; + // + // tcpip was calling snp at tpl_notify and when we acquire a lock that was + // created at a lower level (TPL_CALLBACK) it gives an assert! + // + if (Enable != 0) { + EfiAcquireLock (&snp->lock); + } else { + EfiReleaseLock (&snp->lock); + } +} + +VOID +snp_undi32_callback_delay ( + IN UINT64 UniqueId, + IN UINT64 MicroSeconds + ) +/*++ + +Routine Description: + This is a callback routine supplied to UNDI at undi_start time. + UNDI call this routine with the number of micro seconds when it wants to + pause. + +Arguments: + MicroSeconds - number of micro seconds to pause, ususlly multiple of 10 + +Returns: + void +--*/ +{ + if (MicroSeconds != 0) { + gBS->Stall ((UINTN) MicroSeconds); + } +} + +/* + * IO routine for UNDI start CPB. + */ +VOID +snp_undi32_callback_memio ( + UINT64 UniqueId, + UINT8 ReadOrWrite, + UINT8 NumBytes, + UINT64 Address, + UINT64 BufferAddr + ) +/*++ + +Routine Description: + This is a callback routine supplied to UNDI at undi_start time. + This is the IO routine for UNDI3.1. + +Arguments: + ReadOrWrite - indicates read or write, IO or Memory + NumBytes - number of bytes to read or write + Address - IO or memory address to read from or write to + BufferAddr - memory location to read into or that contains the bytes + to write + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + EFI_PCI_IO_PROTOCOL_WIDTH Width; + + snp = (SNP_DRIVER *) (UINTN) UniqueId; + + Width = 0; + switch (NumBytes) { + case 2: + Width = 1; + break; + + case 4: + Width = 2; + break; + + case 8: + Width = 3; + break; + } + + switch (ReadOrWrite) { + case PXE_IO_READ: + snp->IoFncs->Io.Read ( + snp->IoFncs, + Width, + snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address + Address, + 1, // count + (VOID *) (UINTN) BufferAddr + ); + break; + + case PXE_IO_WRITE: + snp->IoFncs->Io.Write ( + snp->IoFncs, + Width, + snp->IoBarIndex, // BAR 1 (for 32bit regs), IO base address + Address, + 1, // count + (VOID *) (UINTN) BufferAddr + ); + break; + + case PXE_MEM_READ: + snp->IoFncs->Mem.Read ( + snp->IoFncs, + Width, + snp->MemoryBarIndex, // BAR 0, Memory base address + Address, + 1, // count + (VOID *) (UINTN) BufferAddr + ); + break; + + case PXE_MEM_WRITE: + snp->IoFncs->Mem.Write ( + snp->IoFncs, + Width, + snp->MemoryBarIndex, // BAR 0, Memory base address + Address, + 1, // count + (VOID *) (UINTN) BufferAddr + ); + break; + } + + return ; +} + +VOID +snp_undi32_callback_map ( + IN UINT64 UniqueId, + IN UINT64 CpuAddr, + IN UINT32 NumBytes, + IN UINT32 Direction, + IN OUT UINT64 DeviceAddrPtr + ) +/*++ + +Routine Description: + This is a callback routine supplied to UNDI at undi_start time. + UNDI call this routine when it has to map a CPU address to a device + address. + +Arguments: + UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store + Undi interface context (Undi does not read or write this variable) + CpuAddr - Virtual address to be mapped! + NumBytes - size of memory to be mapped + Direction - direction of data flow for this memory's usage: + cpu->device, device->cpu or both ways + DeviceAddrPtr - pointer to return the mapped device address + +Returns: + None + +--*/ +{ + EFI_PHYSICAL_ADDRESS *DevAddrPtr; + EFI_PCI_IO_PROTOCOL_OPERATION DirectionFlag; + UINTN BuffSize; + SNP_DRIVER *snp; + UINTN Index; + EFI_STATUS Status; + + BuffSize = (UINTN) NumBytes; + snp = (SNP_DRIVER *) (UINTN) UniqueId; + DevAddrPtr = (EFI_PHYSICAL_ADDRESS *) (UINTN) DeviceAddrPtr; + + if (CpuAddr == 0) { + *DevAddrPtr = 0; + return ; + } + + switch (Direction) { + case TO_AND_FROM_DEVICE: + DirectionFlag = EfiPciIoOperationBusMasterCommonBuffer; + break; + + case FROM_DEVICE: + DirectionFlag = EfiPciIoOperationBusMasterWrite; + break; + + case TO_DEVICE: + DirectionFlag = EfiPciIoOperationBusMasterRead; + break; + + default: + *DevAddrPtr = 0; + // + // any non zero indicates error! + // + return ; + } + // + // find an unused map_list entry + // + for (Index = 0; Index < MAX_MAP_LENGTH; Index++) { + if (snp->map_list[Index].virt == 0) { + break; + } + } + + if (Index >= MAX_MAP_LENGTH) { + SNP_PRINT (L"SNP maplist is FULL\n"); + *DevAddrPtr = 0; + return ; + } + + snp->map_list[Index].virt = (EFI_PHYSICAL_ADDRESS) CpuAddr; + + Status = snp->IoFncs->Map ( + snp->IoFncs, + DirectionFlag, + (VOID *) (UINTN) CpuAddr, + &BuffSize, + DevAddrPtr, + &(snp->map_list[Index].map_cookie) + ); + if (Status != EFI_SUCCESS) { + *DevAddrPtr = 0; + snp->map_list[Index].virt = 0; + } + + return ; +} + +VOID +snp_undi32_callback_unmap ( + IN UINT64 UniqueId, + IN UINT64 CpuAddr, + IN UINT32 NumBytes, + IN UINT32 Direction, + IN UINT64 DeviceAddr + ) +/*++ + +Routine Description: + This is a callback routine supplied to UNDI at undi_start time. + UNDI call this routine when it wants to unmap an address that was previously + mapped using map callback + +Arguments: + UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store + Undi interface context (Undi does not read or write this variable) + CpuAddr - Virtual address that was mapped! + NumBytes - size of memory mapped + Direction- direction of data flow for this memory's usage: + cpu->device, device->cpu or both ways + DeviceAddr - the mapped device address + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + UINT16 Index; + + snp = (SNP_DRIVER *) (UINTN) UniqueId; + + for (Index = 0; Index < MAX_MAP_LENGTH; Index++) { + if (snp->map_list[Index].virt == CpuAddr) { + break; + } + } + + if (Index >= MAX_MAP_LENGTH) + { +#if SNP_DEBUG + Print (L"SNP could not find a mapping, failed to unmap.\n"); +#endif + return ; + } + + snp->IoFncs->Unmap (snp->IoFncs, snp->map_list[Index].map_cookie); + snp->map_list[Index].virt = 0; + snp->map_list[Index].map_cookie = NULL; + return ; +} + +VOID +snp_undi32_callback_sync ( + UINT64 UniqueId, + UINT64 CpuAddr, + UINT32 NumBytes, + UINT32 Direction, + UINT64 DeviceAddr + ) +/*++ + +Routine Description: + This is a callback routine supplied to UNDI at undi_start time. + UNDI call this routine when it wants synchronize the virtual buffer contents + with the mapped buffer contents. The virtual and mapped buffers need not + correspond to the same physical memory (especially if the virtual address is + > 4GB). Depending on the direction for which the buffer is mapped, undi will + need to synchronize their contents whenever it writes to/reads from the buffer + using either the cpu address or the device address. + + EFI does not provide a sync call, since virt=physical, we sould just do + the synchronization ourself here! + +Arguments: + UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store + Undi interface context (Undi does not read or write this variable) + CpuAddr - Virtual address that was mapped! + NumBytes - size of memory mapped + Direction- direction of data flow for this memory's usage: + cpu->device, device->cpu or both ways + DeviceAddr - the mapped device address + +Returns: + +--*/ +{ + if ((CpuAddr == 0) || (DeviceAddr == 0) || (NumBytes == 0)) { + return ; + + } + + switch (Direction) { + case FROM_DEVICE: + CopyMem ((UINT8 *) (UINTN) CpuAddr, (UINT8 *) (UINTN) DeviceAddr, NumBytes); + break; + + case TO_DEVICE: + CopyMem ((UINT8 *) (UINTN) DeviceAddr, (UINT8 *) (UINTN) CpuAddr, NumBytes); + break; + } + + return ; +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/get_status.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/get_status.c new file mode 100644 index 0000000000..a3fa173d3e --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/get_status.c @@ -0,0 +1,193 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + get_status.c + +Abstract: + +Revision history: + 2000-Feb-03 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_getstatus ( + SNP_DRIVER *snp, + UINT32 *InterruptStatusPtr, + VOID **TransmitBufferListPtr + ) +/*++ + +Routine Description: + this routine calls undi to get the status of the interrupts, get the list of + transmit buffers that completed transmitting! + +Arguments: + snp - pointer to snp driver structure + InterruptStatusPtr - a non null pointer gets the interrupt status + TransmitBufferListPtrs - a non null ointer gets the list of pointers of previously + transmitted buffers whose transmission was completed + asynchrnously. + +Returns: + +--*/ +{ + PXE_DB_GET_STATUS *db; + UINT16 InterruptFlags; + UINT64 TempData; + + db = snp->db; + snp->cdb.OpCode = PXE_OPCODE_GET_STATUS; + + snp->cdb.OpFlags = 0; + + if (TransmitBufferListPtr != NULL) { + snp->cdb.OpFlags |= PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS; + } + + if (InterruptStatusPtr != NULL) { + snp->cdb.OpFlags |= PXE_OPFLAGS_GET_INTERRUPT_STATUS; + } + + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + + // + // size DB for return of one buffer + // + snp->cdb.DBsize = (UINT16) (((UINT16) (sizeof (PXE_DB_GET_STATUS)) - (UINT16) (sizeof db->TxBuffer)) + (UINT16) (sizeof db->TxBuffer[0])); + + snp->cdb.DBaddr = (UINT64) (UINTN) db; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.get_status() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != EFI_SUCCESS) { + DEBUG ( + (EFI_D_NET, + "\nsnp->undi.get_status() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatFlags) + ); + + return EFI_DEVICE_ERROR; + } + // + // report the values back.. + // + if (InterruptStatusPtr != NULL) { + InterruptFlags = (UINT16) (snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK); + + *InterruptStatusPtr = 0; + + if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_RECEIVE) { + *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT; + } + + if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_TRANSMIT) { + *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT; + } + + if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_COMMAND) { + *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT; + } + + if (InterruptFlags & PXE_STATFLAGS_GET_STATUS_SOFTWARE) { + *InterruptStatusPtr |= EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT; + } + + } + + if (TransmitBufferListPtr != NULL) { + *TransmitBufferListPtr = + ( + (snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN) || + (snp->cdb.StatFlags & PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY) + ) ? 0 : (VOID *) (UINTN) db->TxBuffer[0]; + + TempData = (UINT64) (UINTN) (*TransmitBufferListPtr); + if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) { + del_v2p ((VOID *) (UINTN) (db->TxBuffer[0])); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +snp_undi32_get_status ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + OUT UINT32 *InterruptStatusPtr OPTIONAL, + OUT VOID **TransmitBufferListPtr OPTIONAL + ) +/*++ + +Routine Description: + This is the SNP interface routine for getting the status + This routine basically retrieves snp structure, checks the SNP state and + calls the pxe_getstatus routine to actually get the undi status + +Arguments: + this - context pointer + InterruptStatusPtr - a non null pointer gets the interrupt status + TransmitBufferListPtrs - a non null ointer gets the list of pointers of previously + transmitted buffers whose transmission was completed + asynchrnously. + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + + switch (snp->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + + if (InterruptStatusPtr == NULL && TransmitBufferListPtr == NULL) { + return EFI_INVALID_PARAMETER; + } + + return pxe_getstatus (snp, InterruptStatusPtr, TransmitBufferListPtr); +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/initialize.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/initialize.c new file mode 100644 index 0000000000..d05395bd19 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/initialize.c @@ -0,0 +1,244 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + initialize.c + +Abstract: + +Revision history: + 2000-Feb-09 M(f)J Genesis. +--*/ + + +#include "snp.h" + +VOID +EFIAPI +SnpWaitForPacketNotify ( + IN EFI_EVENT Event, + IN VOID *SnpPtr + ); + +EFI_STATUS +pxe_init ( + SNP_DRIVER *snp, + UINT16 CableDetectFlag + ) +/*++ + +Routine Description: + this routine calls undi to initialize the interface. + +Arguments: + snp - pointer to snp driver structure + CableDetectFlag - Do/don't detect the cable (depending on what undi supports) + +Returns: + +--*/ +{ + PXE_CPB_INITIALIZE *cpb; + VOID *addr; + EFI_STATUS Status; + + cpb = snp->cpb; + if (snp->tx_rx_bufsize != 0) { + Status = snp->IoFncs->AllocateBuffer ( + snp->IoFncs, + AllocateAnyPages, + EfiBootServicesData, + SNP_MEM_PAGES (snp->tx_rx_bufsize), + &addr, + 0 + ); + + if (Status != EFI_SUCCESS) { + DEBUG ( + (EFI_D_ERROR, + "\nsnp->pxe_init() AllocateBuffer %xh (%r)\n", + Status, + Status) + ); + + return Status; + } + + ASSERT (addr); + + snp->tx_rx_buffer = addr; + } + + cpb->MemoryAddr = (UINT64) (UINTN) snp->tx_rx_buffer; + + cpb->MemoryLength = snp->tx_rx_bufsize; + + // + // let UNDI decide/detect these values + // + cpb->LinkSpeed = 0; + cpb->TxBufCnt = 0; + cpb->TxBufSize = 0; + cpb->RxBufCnt = 0; + cpb->RxBufSize = 0; + + cpb->DuplexMode = PXE_DUPLEX_DEFAULT; + + cpb->LoopBackMode = LOOPBACK_NORMAL; + + snp->cdb.OpCode = PXE_OPCODE_INITIALIZE; + snp->cdb.OpFlags = CableDetectFlag; + + snp->cdb.CPBsize = sizeof (PXE_CPB_INITIALIZE); + snp->cdb.DBsize = sizeof (PXE_DB_INITIALIZE); + + snp->cdb.CPBaddr = (UINT64) (UINTN) snp->cpb; + snp->cdb.DBaddr = (UINT64) (UINTN) snp->db; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + DEBUG ((EFI_D_NET, "\nsnp->undi.initialize() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode == PXE_STATCODE_SUCCESS) { + snp->mode.State = EfiSimpleNetworkInitialized; + + Status = EFI_SUCCESS; + } else { + DEBUG ( + (EFI_D_WARN, + "\nsnp->undi.initialize() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + if (snp->tx_rx_buffer != NULL) { + snp->IoFncs->FreeBuffer ( + snp->IoFncs, + SNP_MEM_PAGES (snp->tx_rx_bufsize), + (VOID *) snp->tx_rx_buffer + ); + } + + snp->tx_rx_buffer = NULL; + + Status = EFI_DEVICE_ERROR; + } + + return Status; +} + +EFI_STATUS +EFIAPI +snp_undi32_initialize ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this, + IN UINTN extra_rx_buffer_size OPTIONAL, + IN UINTN extra_tx_buffer_size OPTIONAL + ) +/*++ + +Routine Description: + This is the SNP interface routine for initializing the interface + This routine basically retrieves snp structure, checks the SNP state and + calls the pxe_initialize routine to actually do the undi initialization + +Arguments: + this - context pointer + extra_rx_buffer_size - optional parameter, indicates extra space for rx_buffers + extra_tx_buffer_size - optional parameter, indicates extra space for tx_buffers + +Returns: + +--*/ +{ + EFI_STATUS EfiStatus; + SNP_DRIVER *snp; + + // + // + // + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // + // + switch (snp->mode.State) { + case EfiSimpleNetworkStarted: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkInitialized: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + // + // + // + EfiStatus = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_WAIT, + EFI_TPL_NOTIFY, + &SnpWaitForPacketNotify, + snp, + &snp->snp.WaitForPacket + ); + + if (EFI_ERROR (EfiStatus)) { + snp->snp.WaitForPacket = NULL; + return EFI_DEVICE_ERROR; + } + // + // + // + snp->mode.MCastFilterCount = 0; + snp->mode.ReceiveFilterSetting = 0; + ZeroMem (snp->mode.MCastFilter, sizeof snp->mode.MCastFilter); + CopyMem ( + &snp->mode.CurrentAddress, + &snp->mode.PermanentAddress, + sizeof (EFI_MAC_ADDRESS) + ); + + // + // Compute tx/rx buffer sizes based on UNDI init info and parameters. + // + snp->tx_rx_bufsize = (UINT32) (snp->init_info.MemoryRequired + extra_rx_buffer_size + extra_tx_buffer_size); + + if (snp->mode.MediaPresentSupported) { + if (pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DETECT_CABLE) == EFI_SUCCESS) { + snp->mode.MediaPresent = TRUE; + return EFI_SUCCESS; + } + } + + snp->mode.MediaPresent = FALSE; + + EfiStatus = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE); + + if (EFI_ERROR (EfiStatus)) { + gBS->CloseEvent (snp->snp.WaitForPacket); + } + + return EfiStatus; +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/mcast_ip_to_mac.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/mcast_ip_to_mac.c new file mode 100644 index 0000000000..995e33e27d --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/mcast_ip_to_mac.c @@ -0,0 +1,167 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + mcast_ip_to_mac.c + +Abstract: + +Revision history: + 2000-Feb-17 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_ip2mac ( + IN SNP_DRIVER *snp, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + IN OUT EFI_MAC_ADDRESS *MAC + ) +/*++ + +Routine Description: + this routine calls undi to convert an multicast IP address to a MAC address + +Arguments: + snp - pointer to snp driver structure + IPv6 - flag to indicate if this is an ipv6 address + IP - multicast IP address + MAC - pointer to hold the return MAC address + +Returns: + +--*/ +{ + PXE_CPB_MCAST_IP_TO_MAC *cpb; + PXE_DB_MCAST_IP_TO_MAC *db; + + cpb = snp->cpb; + db = snp->db; + snp->cdb.OpCode = PXE_OPCODE_MCAST_IP_TO_MAC; + snp->cdb.OpFlags = (UINT16) (IPv6 ? PXE_OPFLAGS_MCAST_IPV6_TO_MAC : PXE_OPFLAGS_MCAST_IPV4_TO_MAC); + snp->cdb.CPBsize = sizeof (PXE_CPB_MCAST_IP_TO_MAC); + snp->cdb.DBsize = sizeof (PXE_DB_MCAST_IP_TO_MAC); + + snp->cdb.CPBaddr = (UINT64) (UINTN) cpb; + snp->cdb.DBaddr = (UINT64) (UINTN) db; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + CopyMem (&cpb->IP, IP, sizeof (PXE_IP_ADDR)); + + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.mcast_ip_to_mac() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + switch (snp->cdb.StatCode) { + case PXE_STATCODE_SUCCESS: + break; + + case PXE_STATCODE_INVALID_CPB: + return EFI_INVALID_PARAMETER; + + case PXE_STATCODE_UNSUPPORTED: + DEBUG ( + (EFI_D_NET, + "\nsnp->undi.mcast_ip_to_mac() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + return EFI_UNSUPPORTED; + + default: + // + // UNDI command failed. Return EFI_DEVICE_ERROR + // to caller. + // + DEBUG ( + (EFI_D_NET, + "\nsnp->undi.mcast_ip_to_mac() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_DEVICE_ERROR; + } + + CopyMem (MAC, &db->MAC, sizeof (PXE_MAC_ADDR)); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +snp_undi32_mcast_ip_to_mac ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC + ) +/*++ + +Routine Description: + This is the SNP interface routine for converting a multicast IP address to + a MAC address. + This routine basically retrieves snp structure, checks the SNP state and + calls the pxe_ip2mac routine to actually do the conversion + +Arguments: + this - context pointer + IPv6 - flag to indicate if this is an ipv6 address + IP - multicast IP address + MAC - pointer to hold the return MAC address + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + + // + // Get pointer to SNP driver instance for *this. + // + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + + switch (snp->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + + if (IP == NULL || MAC == NULL) { + return EFI_INVALID_PARAMETER; + } + + return pxe_ip2mac (snp, IPv6, IP, MAC); +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/nvdata.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/nvdata.c new file mode 100644 index 0000000000..0167e4db30 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/nvdata.c @@ -0,0 +1,183 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + nvdata.c + +Abstract: + +Revision history: + 2000-Feb-03 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_nvdata_read ( + IN SNP_DRIVER *snp, + IN UINTN RegOffset, + IN UINTN NumBytes, + IN OUT VOID *BufferPtr + ) +/*++ + +Routine Description: + This routine calls Undi to read the desired number of eeprom bytes. + +Arguments: + snp - pointer to the snp driver structure + RegOffset - eeprom register value relative to the base address + NumBytes - number of bytes to read + BufferPtr - pointer where to read into + +Returns: + +--*/ +{ + PXE_DB_NVDATA *db; + + db = snp->db; + snp->cdb.OpCode = PXE_OPCODE_NVDATA; + + snp->cdb.OpFlags = PXE_OPFLAGS_NVDATA_READ; + + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + + snp->cdb.DBsize = sizeof (PXE_DB_NVDATA); + snp->cdb.DBaddr = (UINT64) (UINTN) db; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.nvdata () ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + switch (snp->cdb.StatCode) { + case PXE_STATCODE_SUCCESS: + break; + + case PXE_STATCODE_UNSUPPORTED: + DEBUG ( + (EFI_D_NET, + "\nsnp->undi.nvdata() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_UNSUPPORTED; + + default: + DEBUG ( + (EFI_D_NET, + "\nsnp->undi.nvdata() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_DEVICE_ERROR; + } + + CopyMem (BufferPtr, db->Data.Byte + RegOffset, NumBytes); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +snp_undi32_nvdata ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this, + IN BOOLEAN ReadOrWrite, + IN UINTN RegOffset, + IN UINTN NumBytes, + IN OUT VOID *BufferPtr + ) +/*++ + +Routine Description: + This is an interface call provided by SNP. + It does the basic checking on the input parameters and retrieves snp structure + and then calls the read_nvdata() call which does the actual reading + +Arguments: + this - context pointer + ReadOrWrite - true for reading and false for writing + RegOffset - eeprom register relative to the base + NumBytes - how many bytes to read + BufferPtr - address of memory to read into + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + + // + // Get pointer to SNP driver instance for *this. + // + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Return error if the SNP is not initialized. + // + switch (snp->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + // + // Return error if non-volatile memory variables are not valid. + // + if (snp->mode.NvRamSize == 0 || snp->mode.NvRamAccessSize == 0) { + return EFI_UNSUPPORTED; + } + // + // Check for invalid parameter combinations. + // + if ((NumBytes == 0) || + (BufferPtr == NULL) || + (RegOffset >= snp->mode.NvRamSize) || + (RegOffset + NumBytes > snp->mode.NvRamSize) || + (NumBytes % snp->mode.NvRamAccessSize != 0) || + (RegOffset % snp->mode.NvRamAccessSize != 0) + ) { + return EFI_INVALID_PARAMETER; + } + // + // check the implementation flags of undi if we can write the nvdata! + // + if (!ReadOrWrite) { + return EFI_UNSUPPORTED; + } else { + return pxe_nvdata_read (snp, RegOffset, NumBytes, BufferPtr); + } +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/receive.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/receive.c new file mode 100644 index 0000000000..5a41b8a1ee --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/receive.c @@ -0,0 +1,255 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + receive.c + +Abstract: + +Revision history: + 2000-Feb-03 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_receive ( + SNP_DRIVER *snp, + VOID *BufferPtr, + UINTN *BuffSizePtr, + UINTN *HeaderSizePtr, + EFI_MAC_ADDRESS *SourceAddrPtr, + EFI_MAC_ADDRESS *DestinationAddrPtr, + UINT16 *ProtocolPtr + ) +/*++ + +Routine Description: + this routine calls undi to receive a packet and fills in the data in the + input pointers! + +Arguments: + snp - pointer to snp driver structure + BufferPtr - pointer to the memory for the received data + BuffSizePtr - is a pointer to the length of the buffer on entry and contains + the length of the received data on return + HeaderSizePtr - pointer to the header portion of the data received. + SourceAddrPtr - optional parameter, is a pointer to contain the source + ethernet address on return + DestinationAddrPtr - optional parameter, is a pointer to contain the destination + ethernet address on return + ProtocolPtr - optional parameter, is a pointer to contain the protocol type + from the ethernet header on return + + +Returns: + +--*/ +{ + PXE_CPB_RECEIVE *cpb; + PXE_DB_RECEIVE *db; + UINTN buf_size; + UINT64 TempData; + + cpb = snp->cpb; + db = snp->db; + buf_size = *BuffSizePtr; + // + // IMPORTANT NOTE: + // In case of the older 3.0 UNDI, if the input buffer address is beyond 4GB, + // DO NOT call the map function on the given buffer, instead use + // a global buffer. The reason is that UNDI3.0 has some unnecessary check of + // making sure that all the addresses (whether or not they will be given + // to the NIC ) supplied to it are below 4GB. It may or may not use + // the mapped address after all (like in case of CPB and DB)! + // Instead of using the global buffer whose address is allocated within the + // 2GB limit if I start mapping the given buffer we lose the data, here is + // why!!! + // if our address is > 4GB, the map call creates another buffer below 2GB and + // copies data to/from the original buffer to the mapped buffer either at + // map time or unmap time depending on the map direction. + // UNDI will not complain since we already mapped the buffer to be + // within the 2GB limit but will not use (I know undi) the mapped address + // since it does not give the user buffers to the NIC's receive unit, + // It just copies the received packet into the user buffer using the virtual + // (CPU) address rather than the mapped (device or physical) address. + // When the UNDI call returns, if we then unmap the buffer, we will lose + // the contents because unmap copies the contents of the mapped buffer into + // the original buffer (since the direction is FROM_DEVICE) !!! + // + // this is not a problem in Undi 3.1 because this undi uses it's map callback + // routine to map a cpu address to device address and it does it only if + // it is giving the address to the device and unmaps it before using the cpu + // address! + // + TempData = (UINT64) (UINTN) BufferPtr; + if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) { + cpb->BufferAddr = (UINT64) (UINTN) snp->receive_buf; + cpb->BufferLen = (UINT32) (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen); + } else { + cpb->BufferAddr = (UINT64) (UINTN) BufferPtr; + cpb->BufferLen = (UINT32) *BuffSizePtr; + } + + cpb->reserved = 0; + + snp->cdb.OpCode = PXE_OPCODE_RECEIVE; + snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED; + + snp->cdb.CPBsize = sizeof (PXE_CPB_RECEIVE); + snp->cdb.CPBaddr = (UINT64) (UINTN) cpb; + + snp->cdb.DBsize = sizeof (PXE_DB_RECEIVE); + snp->cdb.DBaddr = (UINT64) (UINTN) db; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_INFO, "\nsnp->undi.receive () ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + switch (snp->cdb.StatCode) { + case PXE_STATCODE_SUCCESS: + break; + + case PXE_STATCODE_NO_DATA: + DEBUG ( + (EFI_D_INFO, + "\nsnp->undi.receive () %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_NOT_READY; + + default: + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.receive() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_DEVICE_ERROR; + } + + *BuffSizePtr = db->FrameLen; + + if (HeaderSizePtr != NULL) { + *HeaderSizePtr = db->MediaHeaderLen; + } + + if (SourceAddrPtr != NULL) { + CopyMem (SourceAddrPtr, &db->SrcAddr, snp->mode.HwAddressSize); + } + + if (DestinationAddrPtr != NULL) { + CopyMem (DestinationAddrPtr, &db->DestAddr, snp->mode.HwAddressSize); + } + + if (ProtocolPtr != NULL) { + *ProtocolPtr = (UINT16) PXE_SWAP_UINT16 (db->Protocol); /* we need to do the byte swapping */ + } + + TempData = (UINT64) (UINTN) BufferPtr; + if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) { + CopyMem (BufferPtr, snp->receive_buf, snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen); + } + + return (*BuffSizePtr <= buf_size) ? EFI_SUCCESS : EFI_BUFFER_TOO_SMALL; +} + +EFI_STATUS +EFIAPI +snp_undi32_receive ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + OUT UINTN *HeaderSizePtr OPTIONAL, + IN OUT UINTN *BuffSizePtr, + OUT VOID *BufferPtr, + OUT EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL, + OUT EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL, + OUT UINT16 *ProtocolPtr OPTIONAL + ) +/*++ + +Routine Description: + This is the SNP interface routine for receiving network data. + This routine basically retrieves snp structure, checks the SNP state and + calls the pxe_receive routine to actually do the receive! + +Arguments: + this - context pointer + HeaderSizePtr - optional parameter and is a pointer to the header portion of + the data received. + BuffSizePtr - is a pointer to the length of the buffer on entry and contains + the length of the received data on return + BufferPtr - pointer to the memory for the received data + SourceAddrPtr - optional parameter, is a pointer to contain the source + ethernet address on return + DestinationAddrPtr - optional parameter, is a pointer to contain the destination + ethernet address on return + ProtocolPtr - optional parameter, is a pointer to contain the protocol type + from the ethernet header on return + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + + switch (snp->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + + if ((BuffSizePtr == NULL) || (BufferPtr == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (!snp->mode.ReceiveFilterSetting) { + return EFI_DEVICE_ERROR; + } + + return pxe_receive ( + snp, + BufferPtr, + BuffSizePtr, + HeaderSizePtr, + SourceAddrPtr, + DestinationAddrPtr, + ProtocolPtr + ); +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/receive_filters.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/receive_filters.c new file mode 100644 index 0000000000..233448cda5 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/receive_filters.c @@ -0,0 +1,411 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + receive_filters.c + +Abstract: + +Revision history: + 2000-Feb-17 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_rcvfilter_enable ( + SNP_DRIVER *snp, + UINT32 EnableFlags, + UINTN MCastAddressCount, + EFI_MAC_ADDRESS *MCastAddressList + ) +/*++ + +Routine Description: + this routine calls undi to enable the receive filters. + +Arguments: + snp - pointer to snp driver structure + EnableFlags - bit mask for enabling the receive filters + MCastAddressCount - multicast address count for a new multicast address list + MCastAddressList - list of new multicast addresses + +Returns: + +--*/ +{ + snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS; + snp->cdb.OpFlags = PXE_OPFLAGS_RECEIVE_FILTER_ENABLE; + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.DBsize = PXE_DBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + snp->cdb.DBaddr = PXE_DBADDR_NOT_USED; + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST; + } + + if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; + } + + if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS; + } + + if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; + } + + if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; + } + + if (MCastAddressCount != 0) { + snp->cdb.CPBsize = (UINT16) (MCastAddressCount * sizeof (EFI_MAC_ADDRESS)); + snp->cdb.CPBaddr = (UINT64) (UINTN) snp->cpb; + CopyMem (snp->cpb, MCastAddressList, snp->cdb.CPBsize); + } + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != EFI_SUCCESS) { + // + // UNDI command failed. Return UNDI status to caller. + // + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.receive_filters() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + switch (snp->cdb.StatCode) { + case PXE_STATCODE_INVALID_CDB: + case PXE_STATCODE_INVALID_CPB: + case PXE_STATCODE_INVALID_PARAMETER: + return EFI_INVALID_PARAMETER; + + case PXE_STATCODE_UNSUPPORTED: + return EFI_UNSUPPORTED; + } + + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +pxe_rcvfilter_disable ( + SNP_DRIVER *snp, + UINT32 DisableFlags, + BOOLEAN ResetMCastList + ) +/*++ + +Routine Description: + this routine calls undi to disable the receive filters. + +Arguments: + snp - pointer to snp driver structure + DisableFlags - bit mask for disabling the receive filters + ResetMCastList - boolean flag to reset/delete the multicast filter list + +Returns: + +--*/ +{ + snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS; + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.DBsize = PXE_DBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + snp->cdb.DBaddr = PXE_DBADDR_NOT_USED; + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + snp->cdb.OpFlags = (UINT16) (DisableFlags ? PXE_OPFLAGS_RECEIVE_FILTER_DISABLE : PXE_OPFLAGS_NOT_USED); + + if (ResetMCastList) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST; + } + + if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_UNICAST) != 0) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_UNICAST; + } + + if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST) != 0) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST; + } + + if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS) != 0) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS; + } + + if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST) != 0) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST; + } + + if ((DisableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0) { + snp->cdb.OpFlags |= PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST; + } + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != EFI_SUCCESS) { + // + // UNDI command failed. Return UNDI status to caller. + // + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.receive_filters() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +pxe_rcvfilter_read ( + SNP_DRIVER *snp + ) +/*++ + +Routine Description: + this routine calls undi to read the receive filters. + +Arguments: + snp - pointer to snp driver structure + +Returns: + +--*/ +{ + snp->cdb.OpCode = PXE_OPCODE_RECEIVE_FILTERS; + snp->cdb.OpFlags = PXE_OPFLAGS_RECEIVE_FILTER_READ; + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.DBsize = (UINT16) (snp->mode.MaxMCastFilterCount * sizeof (EFI_MAC_ADDRESS)); + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + if (snp->cdb.DBsize == 0) { + snp->cdb.DBaddr = (UINT64) NULL; + } else { + snp->cdb.DBaddr = (UINT64) (UINTN) snp->db; + ZeroMem (snp->db, snp->cdb.DBsize); + } + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + DEBUG ((EFI_D_NET, "\nsnp->undi.receive_filters() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != EFI_SUCCESS) { + // + // UNDI command failed. Return UNDI status to caller. + // + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.receive_filters() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_DEVICE_ERROR; + } + // + // Convert UNDI32 StatFlags to EFI SNP filter flags. + // + snp->mode.ReceiveFilterSetting = 0; + + if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_UNICAST) != 0) { + snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; + } + + if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST) != 0) { + snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; + } + + if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS) != 0) { + snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; + } + + if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST) != 0) { + snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + } + + if ((snp->cdb.StatFlags & PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST) != 0) { + snp->mode.ReceiveFilterSetting |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST; + } + + CopyMem (snp->mode.MCastFilter, snp->db, snp->cdb.DBsize); + + // + // Count number of active entries in multicast filter list. + // + { + EFI_MAC_ADDRESS ZeroMacAddr; + + SetMem (&ZeroMacAddr, sizeof ZeroMacAddr, 0); + + for (snp->mode.MCastFilterCount = 0; + snp->mode.MCastFilterCount < snp->mode.MaxMCastFilterCount; + snp->mode.MCastFilterCount++ + ) { + if (CompareMem ( + &snp->mode.MCastFilter[snp->mode.MCastFilterCount], + &ZeroMacAddr, + sizeof ZeroMacAddr + ) == 0) { + break; + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +snp_undi32_receive_filters ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + IN UINT32 EnableFlags, + IN UINT32 DisableFlags, + IN BOOLEAN ResetMCastList, + IN UINTN MCastAddressCount OPTIONAL, + IN EFI_MAC_ADDRESS * MCastAddressList OPTIONAL + ) +/*++ + +Routine Description: + This is the SNP interface routine for reading/enabling/disabling the + receive filters. + This routine basically retrieves snp structure, checks the SNP state and + checks the parameter validity, calls one of the above routines to actually + do the work + +Arguments: + this - context pointer + EnableFlags - bit mask for enabling the receive filters + DisableFlags - bit mask for disabling the receive filters + ResetMCastList - boolean flag to reset/delete the multicast filter list + MCastAddressCount - multicast address count for a new multicast address list + MCastAddressList - list of new multicast addresses + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + EFI_STATUS Status; + + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + + switch (snp->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + // + // check if we are asked to enable or disable something that the UNDI + // does not even support! + // + if ((EnableFlags &~snp->mode.ReceiveFilterMask) != 0) { + return EFI_INVALID_PARAMETER; + } + + if ((DisableFlags &~snp->mode.ReceiveFilterMask) != 0) { + return EFI_INVALID_PARAMETER; + } + + if (ResetMCastList) { + DisableFlags |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST & snp->mode.ReceiveFilterMask; + MCastAddressCount = 0; + MCastAddressList = NULL; + } else { + if (MCastAddressCount != 0) { + if (MCastAddressCount > snp->mode.MaxMCastFilterCount) { + return EFI_INVALID_PARAMETER; + } + + if (MCastAddressList == NULL) { + return EFI_INVALID_PARAMETER; + } + } + } + + if (EnableFlags == 0 && DisableFlags == 0 && !ResetMCastList && MCastAddressCount == 0) { + return EFI_SUCCESS; + } + + if ((EnableFlags & EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST) != 0 && MCastAddressCount == 0) { + return EFI_INVALID_PARAMETER; + } + + if ((EnableFlags != 0) || (MCastAddressCount != 0)) { + Status = pxe_rcvfilter_enable ( + snp, + EnableFlags, + MCastAddressCount, + MCastAddressList + ); + + if (Status != EFI_SUCCESS) { + return Status; + } + } + + if ((DisableFlags != 0) || ResetMCastList) { + Status = pxe_rcvfilter_disable (snp, DisableFlags, ResetMCastList); + + if (Status != EFI_SUCCESS) { + return Status; + } + } + + return pxe_rcvfilter_read (snp); +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/reset.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/reset.c new file mode 100644 index 0000000000..8d56ecf361 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/reset.c @@ -0,0 +1,129 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + reset.c + +Abstract: + +Revision history: + 2000-Feb-09 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_reset ( + SNP_DRIVER *snp + ) +/*++ + +Routine Description: + This routine calls undi to reset the nic. + +Arguments: + snp - pointer to the snp driver structure + +Returns: + EFI_SUCCESSFUL for a successful completion + other for failed calls + +--*/ +{ + snp->cdb.OpCode = PXE_OPCODE_RESET; + snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED; + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.DBsize = PXE_DBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + snp->cdb.DBaddr = PXE_DBADDR_NOT_USED; + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.reset() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) { + DEBUG ( + (EFI_D_WARN, + "\nsnp->undi32.reset() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + // + // UNDI could not be reset. Return UNDI error. + // + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +snp_undi32_reset ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + This is the SNP interface routine for resetting the NIC + This routine basically retrieves snp structure, checks the SNP state and + calls the pxe_reset routine to actually do the reset! + +Arguments: + this - context pointer + ExtendedVerification - not implemented + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + + // + // Resolve Warning 4 unreferenced parameter problem + // + ExtendedVerification = 0; + + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + + switch (snp->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + + return pxe_reset (snp); +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/shutdown.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/shutdown.c new file mode 100644 index 0000000000..efa6cf7302 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/shutdown.c @@ -0,0 +1,152 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + shutdown.c + +Abstract: + +Revision history: + 2000-Feb-14 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_shutdown ( + IN SNP_DRIVER *snp + ) +/*++ + +Routine Description: + this routine calls undi to shut down the interface. + +Arguments: + snp - pointer to snp driver structure + +Returns: + +--*/ +{ + snp->cdb.OpCode = PXE_OPCODE_SHUTDOWN; + snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED; + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.DBsize = PXE_DBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + snp->cdb.DBaddr = PXE_DBADDR_NOT_USED; + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.shutdown() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) { + // + // UNDI could not be shutdown. Return UNDI error. + // + DEBUG ((EFI_D_WARN, "\nsnp->undi.shutdown() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode)); + + return EFI_DEVICE_ERROR; + } + // + // Free allocated memory. + // + if (snp->tx_rx_buffer != NULL) { + snp->IoFncs->FreeBuffer ( + snp->IoFncs, + SNP_MEM_PAGES (snp->tx_rx_bufsize), + (VOID *) snp->tx_rx_buffer + ); + } + + snp->tx_rx_buffer = NULL; + snp->tx_rx_bufsize = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +snp_undi32_shutdown ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this + ) +/*++ + +Routine Description: + This is the SNP interface routine for shutting down the interface + This routine basically retrieves snp structure, checks the SNP state and + calls the pxe_shutdown routine to actually do the undi shutdown + +Arguments: + this - context pointer + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + EFI_STATUS status; + + // + // + // + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + // + // + // + switch (snp->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + // + // + // + status = pxe_shutdown (snp); + + snp->mode.State = EfiSimpleNetworkStarted; + snp->mode.ReceiveFilterSetting = 0; + + snp->mode.MCastFilterCount = 0; + snp->mode.ReceiveFilterSetting = 0; + ZeroMem (snp->mode.MCastFilter, sizeof snp->mode.MCastFilter); + CopyMem ( + &snp->mode.CurrentAddress, + &snp->mode.PermanentAddress, + sizeof (EFI_MAC_ADDRESS) + ); + + gBS->CloseEvent (snp->snp.WaitForPacket); + + return status; +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/snp.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/snp.c new file mode 100644 index 0000000000..ab3c997448 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/snp.c @@ -0,0 +1,1315 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + snp.c + +Abstract: + +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_start ( + SNP_DRIVER *snp + ); +EFI_STATUS +pxe_stop ( + SNP_DRIVER *snp + ); +EFI_STATUS +pxe_init ( + SNP_DRIVER *snp, + UINT16 OpFlags + ); +EFI_STATUS +pxe_shutdown ( + SNP_DRIVER *snp + ); +EFI_STATUS +pxe_get_stn_addr ( + SNP_DRIVER *snp + ); + +EFI_STATUS +EFIAPI +InitializeSnpNiiDriver ( + IN EFI_HANDLE image_handle, + IN EFI_SYSTEM_TABLE *system_table + ); + +EFI_STATUS +EFIAPI +SimpleNetworkDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +SimpleNetworkDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +SimpleNetworkDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +// +// Simple Network Protocol Driver Global Variables +// +EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding = { + SimpleNetworkDriverSupported, + SimpleNetworkDriverStart, + SimpleNetworkDriverStop, + 0x10, + NULL, + NULL +}; + +// +// Module global variables needed to support undi 3.0 interface +// +EFI_PCI_IO_PROTOCOL *mPciIoFncs; +struct s_v2p *_v2p = NULL; // undi3.0 map_list head +// End Global variables +// +EFI_STATUS +add_v2p ( + IN OUT struct s_v2p **v2p, + EFI_PCI_IO_PROTOCOL_OPERATION type, + VOID *vaddr, + UINTN bsize + ) +/*++ + +Routine Description: + This routine maps the given CPU address to a Device address. It creates a + an entry in the map list with the virtual and physical addresses and the + un map cookie. + +Arguments: + v2p - pointer to return a map list node pointer. + type - the direction in which the data flows from the given virtual address + device->cpu or cpu->device or both ways. + vaddr - virtual address (or CPU address) to be mapped + bsize - size of the buffer to be mapped. + +Returns: + + EFI_SUCEESS - routine has completed the mapping + other - error as indicated. + +--*/ +{ + EFI_STATUS Status; + + if ((v2p == NULL) || (vaddr == NULL) || (bsize == 0)) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (struct s_v2p), + (VOID **) v2p + ); + + if (Status != EFI_SUCCESS) { + return Status; + } + + Status = mPciIoFncs->Map ( + mPciIoFncs, + type, + vaddr, + &bsize, + &(*v2p)->paddr, + &(*v2p)->unmap + ); + if (Status != EFI_SUCCESS) { + gBS->FreePool (*v2p); + return Status; + } + (*v2p)->vaddr = vaddr; + (*v2p)->bsize = bsize; + (*v2p)->next = _v2p; + _v2p = *v2p; + + return EFI_SUCCESS; +} + +EFI_STATUS +find_v2p ( + struct s_v2p **v2p, + VOID *vaddr + ) +/*++ + +Routine Description: + This routine searches the linked list of mapped address nodes (for undi3.0 + interface) to find the node that corresponds to the given virtual address and + returns a pointer to that node. + +Arguments: + v2p - pointer to return a map list node pointer. + vaddr - virtual address (or CPU address) to be searched in the map list + +Returns: + + EFI_SUCEESS - if a match found! + Other - match not found + +--*/ +{ + struct s_v2p *v; + + if (v2p == NULL || vaddr == NULL) { + return EFI_INVALID_PARAMETER; + } + + for (v = _v2p; v != NULL; v = v->next) { + if (v->vaddr == vaddr) { + *v2p = v; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +del_v2p ( + VOID *vaddr + ) +/*++ + +Routine Description: + This routine unmaps the given virtual address and frees the memory allocated + for the map list node corresponding to that address. + +Arguments: + vaddr - virtual address (or CPU address) to be unmapped + +Returns: + EFI_SUCEESS - if successfully unmapped + Other - as indicated by the error + + +--*/ +{ + struct s_v2p *v; + struct s_v2p *t; + EFI_STATUS Status; + + if (vaddr == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (_v2p == NULL) { + return EFI_NOT_FOUND; + } + // + // Is our node at the head of the list?? + // + if ((v = _v2p)->vaddr == vaddr) { + _v2p = _v2p->next; + + Status = mPciIoFncs->Unmap (mPciIoFncs, v->unmap); + + gBS->FreePool (v); + +#if SNP_DEBUG + if (Status) { + Print (L"Unmap failed with status = %x\n", Status); + } +#endif + return Status; + } + + for (; v->next != NULL; v = t) { + if ((t = v->next)->vaddr == vaddr) { + v->next = t->next; + Status = mPciIoFncs->Unmap (mPciIoFncs, t->unmap); + gBS->FreePool (t); +#if SNP_DEBUG + if (Status) { + Print (L"Unmap failed with status = %x\n", Status); + } +#endif + return Status; + } + } + + return EFI_NOT_FOUND; +} + +#if SNP_DEBUG +VOID +snp_wait_for_key ( + VOID + ) +/*++ + +Routine Description: + Wait for a key stroke, used for debugging purposes + +Arguments: + none + +Returns: + none + +--*/ +{ + EFI_INPUT_KEY key; + + Aprint ("\nPress any key to continue\n"); + + while (gST->ConIn->ReadKeyStroke (gST->ConIn, &key) == EFI_NOT_READY) { + ; + } +} +#endif + +STATIC +EFI_STATUS +issue_hwundi_command ( + UINT64 cdb + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ +#if SNP_DEBUG + Aprint ("\nissue_hwundi_command() - This should not be called!"); + snp_wait_for_key (); +#endif + if (cdb == 0) { + return EFI_INVALID_PARAMETER; + + } + // + // %%TBD - For now, nothing is done. + // + return EFI_UNSUPPORTED; +} + +STATIC +UINT8 +calc_8bit_cksum ( + VOID *ptr, + UINTN len + ) +/*++ + +Routine Description: + Compute 8-bit checksum of a buffer. + +Arguments: + ptr - Pointer to buffer. + len - Length of buffer in bytes. + +Returns: + 8-bit checksum of all bytes in buffer. + If ptr is NULL or len is zero, zero is returned. + +--*/ +{ + UINT8 *bptr; + UINT8 cksum; + + bptr = ptr; + cksum = 0; + + if (ptr == NULL || len == 0) { + return 0; + } + + while (len--) { + cksum = (UINT8) (cksum +*bptr++); + } + + return cksum; +} + +EFI_STATUS +EFIAPI +SimpleNetworkDriverSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + + Routine Description: + Test to see if this driver supports Controller. Any Controller + that contains a Nii protocol can be supported. + + Arguments: + This - Protocol instance pointer. + Controller - Handle of device to test. + RemainingDevicePath - Not used. + + Returns: + EFI_SUCCESS - This driver supports this device. + EFI_ALREADY_STARTED - This driver is already running on this device. + other - This driver does not support this device. + +--*/ +{ + EFI_STATUS Status; + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol; + PXE_UNDI *pxe; + BOOLEAN IsUndi31; + + IsUndi31 = FALSE; + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + NULL, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + (VOID **) &NiiProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) + { +#if SNP_DEBUG + Aprint ("Support(): Already Started. on handle %x\n", Controller); +#endif + return EFI_ALREADY_STARTED; + } + + if (!EFI_ERROR (Status)) + { + +#if SNP_DEBUG + Aprint ("Support(): UNDI3.1 found on handle %x\n", Controller); + snp_wait_for_key (); +#endif + IsUndi31 = TRUE; + } else { + // + // try the older 3.0 driver + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + (VOID **) &NiiProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + +#if SNP_DEBUG + Aprint ("Support(): UNDI3.0 found on handle %x\n", Controller); + snp_wait_for_key (); +#endif + } + // + // check the version, we don't want to connect to the undi16 + // + if (NiiProtocol->Type != EfiNetworkInterfaceUndi) { + Status = EFI_UNSUPPORTED; + goto Done; + } + // + // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required. + // + if (NiiProtocol->ID & 0x0F) { + DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n")); + Status = EFI_UNSUPPORTED; + goto Done; + } + + pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->ID); + + // + // Verify !PXE revisions. + // + if (pxe->hw.Signature != PXE_ROMID_SIGNATURE) { + DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n")); + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (pxe->hw.Rev < PXE_ROMID_REV) { + DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n")); + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (pxe->hw.MajorVer < PXE_ROMID_MAJORVER) { + + DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n")); + Status = EFI_UNSUPPORTED; + goto Done; + + } else if (pxe->hw.MajorVer == PXE_ROMID_MAJORVER && pxe->hw.MinorVer < PXE_ROMID_MINORVER) { + DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported.")); + Status = EFI_UNSUPPORTED; + goto Done; + } + // + // Do S/W UNDI specific checks. + // + if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) { + if (pxe->sw.EntryPoint < pxe->sw.Len) { + DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid.")); + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (pxe->sw.BusCnt == 0) { + DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero.")); + Status = EFI_UNSUPPORTED; + goto Done; + } + } + + Status = EFI_SUCCESS; +#if SNP_DEBUG + Aprint ("Support(): supported on %x\n", Controller); + snp_wait_for_key (); +#endif + +Done: + if (IsUndi31) { + gBS->CloseProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + This->DriverBindingHandle, + Controller + ); + + } else { + gBS->CloseProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +SimpleNetworkDriverStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + called for any handle that we said "supported" in the above call! + +Arguments: + This - Protocol instance pointer. + Controller - Handle of device to start + RemainingDevicePath - Not used. + + Returns: + EFI_SUCCESS - This driver supports this device. + other - This driver failed to start this device. + +--*/ +{ + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii; + EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath; + EFI_STATUS Status; + PXE_UNDI *pxe; + SNP_DRIVER *snp; + VOID *addr; + VOID *addrUnmap; + EFI_PHYSICAL_ADDRESS paddr; + EFI_HANDLE Handle; + UINTN Size; + BOOLEAN UndiNew; + PXE_PCI_CONFIG_INFO ConfigInfo; + PCI_TYPE00 *ConfigHeader; + UINT32 *TempBar; + UINT8 BarIndex; + PXE_STATFLAGS InitStatFlags; + + DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() ")); + + Status = gBS->OpenProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + (VOID **) &NiiDevicePath, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->LocateDevicePath ( + &gEfiPciIoProtocolGuid, + &NiiDevicePath, + &Handle + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->OpenProtocol ( + Handle, + &gEfiPciIoProtocolGuid, + (VOID **) &mPciIoFncs, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the NII interface. look for 3.1 undi first, if it is not there + // then look for 3.0, validate the interface. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + (VOID **) &Nii, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + return Status; + } + + if (!EFI_ERROR (Status)) { + // + // probably not a 3.1 UNDI + // + UndiNew = TRUE; +#if SNP_DEBUG + Aprint ("Start(): UNDI3.1 found\n"); + snp_wait_for_key (); +#endif + } else { + UndiNew = FALSE; + Status = gBS->OpenProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + (VOID **) &Nii, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; + } + +#if SNP_DEBUG + Aprint ("Start(): UNDI3.0 found\n"); + snp_wait_for_key (); +#endif + } + + pxe = (PXE_UNDI *) (UINTN) (Nii->ID); + + if (calc_8bit_cksum (pxe, pxe->hw.Len) != 0) { + DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n")); + goto NiiError; + } + + if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) { + // + // We can get any packets. + // + } else if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) { + // + // We need to be able to get broadcast packets for DHCP. + // If we do not have promiscuous support, we must at least have + // broadcast support or we cannot do DHCP! + // + } else { + DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support.")); + goto NiiError; + } + // + // OK, we like this UNDI, and we know snp is not already there on this handle + // Allocate and initialize a new simple network protocol structure. + // + Status = mPciIoFncs->AllocateBuffer ( + mPciIoFncs, + AllocateAnyPages, + EfiBootServicesData, + SNP_MEM_PAGES (sizeof (SNP_DRIVER)), + &addr, + 0 + ); + + if (Status != EFI_SUCCESS) { + DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n")); + goto NiiError; + } + + snp = (SNP_DRIVER *) (UINTN) addr; + + if (!UndiNew) { + Size = SNP_MEM_PAGES (sizeof (SNP_DRIVER)); + + Status = mPciIoFncs->Map ( + mPciIoFncs, + EfiPciIoOperationBusMasterCommonBuffer, + addr, + &Size, + &paddr, + &addrUnmap + ); + + ASSERT (paddr); + + DEBUG ((EFI_D_NET, "\nSNP_DRIVER @ %Xh, sizeof(SNP_DRIVER) == %d", addr, sizeof (SNP_DRIVER))); + snp = (SNP_DRIVER *) (UINTN) paddr; + snp->SnpDriverUnmap = addrUnmap; + } + + ZeroMem (snp, sizeof (SNP_DRIVER)); + + snp->IoFncs = mPciIoFncs; + snp->IsOldUndi = (BOOLEAN) (!UndiNew); + + snp->Signature = SNP_DRIVER_SIGNATURE; + + EfiInitializeLock (&snp->lock, EFI_TPL_NOTIFY); + + snp->snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION; + snp->snp.Start = snp_undi32_start; + snp->snp.Stop = snp_undi32_stop; + snp->snp.Initialize = snp_undi32_initialize; + snp->snp.Reset = snp_undi32_reset; + snp->snp.Shutdown = snp_undi32_shutdown; + snp->snp.ReceiveFilters = snp_undi32_receive_filters; + snp->snp.StationAddress = snp_undi32_station_address; + snp->snp.Statistics = snp_undi32_statistics; + snp->snp.MCastIpToMac = snp_undi32_mcast_ip_to_mac; + snp->snp.NvData = snp_undi32_nvdata; + snp->snp.GetStatus = snp_undi32_get_status; + snp->snp.Transmit = snp_undi32_transmit; + snp->snp.Receive = snp_undi32_receive; + snp->snp.WaitForPacket = NULL; + + snp->snp.Mode = &snp->mode; + + snp->tx_rx_bufsize = 0; + snp->tx_rx_buffer = NULL; + + snp->if_num = Nii->IfNum; + + if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) { + snp->is_swundi = FALSE; + snp->issue_undi32_command = &issue_hwundi_command; + } else { + snp->is_swundi = TRUE; + + if ((pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) { + snp->issue_undi32_command = (issue_undi32_command) (UINTN) pxe->sw.EntryPoint; + } else { + snp->issue_undi32_command = (issue_undi32_command) (UINTN) ((UINT8) (UINTN) pxe + pxe->sw.EntryPoint); + } + } + // + // Allocate a global CPB and DB buffer for this UNDI interface. + // we do this because: + // + // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be + // within 2GB limit, create them here and map them so that when undi calls + // v2p callback to check if the physical address is < 2gb, we will pass. + // + // -This is not a requirement for 3.1 or later UNDIs but the code looks + // simpler if we use the same cpb, db variables for both old and new undi + // interfaces from all the SNP interface calls (we don't map the buffers + // for the newer undi interfaces though) + // . + // -it is OK to allocate one global set of CPB, DB pair for each UNDI + // interface as EFI does not multi-task and so SNP will not be re-entered! + // + Status = mPciIoFncs->AllocateBuffer ( + mPciIoFncs, + AllocateAnyPages, + EfiBootServicesData, + SNP_MEM_PAGES (4096), + &addr, + 0 + ); + + if (Status != EFI_SUCCESS) { + DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n")); + goto Error_DeleteSNP; + } + + if (snp->IsOldUndi) { + Size = SNP_MEM_PAGES (4096); + + Status = mPciIoFncs->Map ( + mPciIoFncs, + EfiPciIoOperationBusMasterCommonBuffer, + addr, + &Size, + &paddr, + &snp->CpbUnmap + ); + + ASSERT (paddr); + + snp->cpb = (VOID *) (UINTN) paddr; + snp->db = (VOID *) ((UINTN) paddr + 2048); + } else { + snp->cpb = (VOID *) (UINTN) addr; + snp->db = (VOID *) ((UINTN) addr + 2048); + } + // + // pxe_start call is going to give the callback functions to UNDI, these callback + // functions use the BarIndex values from the snp structure, so these must be initialized + // with default values before doing a pxe_start. The correct values can be obtained after + // getting the config information from UNDI + // + snp->MemoryBarIndex = 0; + snp->IoBarIndex = 1; + + // + // we need the undi init information many times in this snp code, just get it + // once here and store it in the snp driver structure. to get Init Info + // from UNDI we have to start undi first. + // + Status = pxe_start (snp); + + if (Status != EFI_SUCCESS) { + goto Error_DeleteCPBDB; + } + + snp->cdb.OpCode = PXE_OPCODE_GET_INIT_INFO; + snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED; + + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED; + + snp->cdb.DBsize = sizeof snp->init_info; + snp->cdb.DBaddr = (UINT64) (UINTN) &snp->init_info; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + DEBUG ((EFI_D_NET, "\nsnp->undi.get_init_info() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + // + // Save the INIT Stat Code... + // + InitStatFlags = snp->cdb.StatFlags; + + if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) { + DEBUG ((EFI_D_NET, "\nsnp->undi.init_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode)); + pxe_stop (snp); + goto Error_DeleteCPBDB; + } + + snp->cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO; + snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED; + + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED; + + snp->cdb.DBsize = sizeof ConfigInfo; + snp->cdb.DBaddr = (UINT64) (UINTN) &ConfigInfo; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + DEBUG ((EFI_D_NET, "\nsnp->undi.get_config_info() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) { + DEBUG ((EFI_D_NET, "\nsnp->undi.config_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode)); + pxe_stop (snp); + goto Error_DeleteCPBDB; + } + // + // Find the correct BAR to do IO. + // + // + // Enumerate through the PCI BARs for the device to determine which one is + // the IO BAR. Save the index of the BAR into the adapter info structure. + // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped + // + ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0]; + TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0]; + for (BarIndex = 0; BarIndex <= 5; BarIndex++) { + if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) { + // + // This is a 64-bit memory bar, skip this and the + // next bar as well. + // + TempBar++; + } + + if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) { + snp->IoBarIndex = BarIndex; + break; + } + + TempBar++; + } + + // + // We allocate 2 more global buffers for undi 3.0 interface. We use these + // buffers to pass to undi when the user buffers are beyond 4GB. + // UNDI 3.0 wants all the addresses passed to it to be + // within 2GB limit, create them here and map them so that when undi calls + // v2p callback to check if the physical address is < 2gb, we will pass. + // + // For 3.1 and later UNDIs, we do not do this because undi is + // going to call the map() callback if and only if it wants to use the + // device address for any address it receives. + // + if (snp->IsOldUndi) { + // + // buffer for receive + // + Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen); + Status = mPciIoFncs->AllocateBuffer ( + mPciIoFncs, + AllocateAnyPages, + EfiBootServicesData, + Size, + &addr, + 0 + ); + + if (Status != EFI_SUCCESS) { + DEBUG ((EFI_D_ERROR, "\nCould not allocate receive buffer.\n")); + goto Error_DeleteCPBDB; + } + + Status = mPciIoFncs->Map ( + mPciIoFncs, + EfiPciIoOperationBusMasterCommonBuffer, + addr, + &Size, + &paddr, + &snp->ReceiveBufUnmap + ); + + ASSERT (paddr); + + snp->receive_buf = (UINT8 *) (UINTN) paddr; + + // + // buffer for fill_header + // + Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen); + Status = mPciIoFncs->AllocateBuffer ( + mPciIoFncs, + AllocateAnyPages, + EfiBootServicesData, + Size, + &addr, + 0 + ); + + if (Status != EFI_SUCCESS) { + DEBUG ((EFI_D_ERROR, "\nCould not allocate fill_header buffer.\n")); + goto Error_DeleteRCVBuf; + } + + Status = mPciIoFncs->Map ( + mPciIoFncs, + EfiPciIoOperationBusMasterCommonBuffer, + addr, + &Size, + &paddr, + &snp->FillHdrBufUnmap + ); + + ASSERT (paddr); + snp->fill_hdr_buf = (UINT8 *) (UINTN) paddr; + } + // + // Initialize simple network protocol mode structure + // + snp->mode.State = EfiSimpleNetworkStopped; + snp->mode.HwAddressSize = snp->init_info.HWaddrLen; + snp->mode.MediaHeaderSize = snp->init_info.MediaHeaderLen; + snp->mode.MaxPacketSize = snp->init_info.FrameDataLen; + snp->mode.NvRamAccessSize = snp->init_info.NvWidth; + snp->mode.NvRamSize = snp->init_info.NvCount * snp->mode.NvRamAccessSize; + snp->mode.IfType = snp->init_info.IFtype; + snp->mode.MaxMCastFilterCount = snp->init_info.MCastFilterCnt; + snp->mode.MCastFilterCount = 0; + + switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) { + case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED: + snp->mode.MediaPresentSupported = TRUE; + break; + + case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED: + default: + snp->mode.MediaPresentSupported = FALSE; + } + + if ((pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) { + snp->mode.MacAddressChangeable = TRUE; + } else { + snp->mode.MacAddressChangeable = FALSE; + } + + if ((pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) { + snp->mode.MultipleTxSupported = TRUE; + } else { + snp->mode.MultipleTxSupported = FALSE; + } + + snp->mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST; + + if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) { + snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + + } + + if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) { + snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS; + + } + + if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) { + snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST; + + } + + if ((pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) { + snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST; + + } + + if (pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) { + snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST; + + } + + snp->mode.ReceiveFilterSetting = 0; + + // + // need to get the station address to save in the mode structure. we need to + // initialize the UNDI first for this. + // + snp->tx_rx_bufsize = snp->init_info.MemoryRequired; + Status = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE); + + if (Status) { + pxe_stop (snp); + goto Error_DeleteHdrBuf; + } + + Status = pxe_get_stn_addr (snp); + + if (Status != EFI_SUCCESS) { + DEBUG ((EFI_D_ERROR, "\nsnp->undi.get_station_addr() failed.\n")); + pxe_shutdown (snp); + pxe_stop (snp); + goto Error_DeleteHdrBuf; + } + + snp->mode.MediaPresent = FALSE; + + // + // We should not leave UNDI started and initialized here. this DriverStart() + // routine must only find and attach the SNP interface to UNDI layer that it + // finds on the given handle! + // The UNDI layer will be started when upper layers call snp->start. + // How ever, this DriverStart() must fill up the snp mode structure which + // contains the MAC address of the NIC. For this reason we started and + // initialized UNDI here, now we are done, do a shutdown and stop of the + // UNDI interface! + // + pxe_shutdown (snp); + pxe_stop (snp); + + // + // add SNP to the undi handle + // + Status = gBS->InstallProtocolInterface ( + &Controller, + &gEfiSimpleNetworkProtocolGuid, + EFI_NATIVE_INTERFACE, + &(snp->snp) + ); + + if (!EFI_ERROR (Status)) { + return Status; + } + +Error_DeleteHdrBuf: + if (snp->IsOldUndi) { + Status = mPciIoFncs->Unmap ( + mPciIoFncs, + snp->FillHdrBufUnmap + ); + Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen); + mPciIoFncs->FreeBuffer ( + mPciIoFncs, + Size, + snp->fill_hdr_buf + ); + } + +Error_DeleteRCVBuf: + if (snp->IsOldUndi) { + Status = mPciIoFncs->Unmap ( + mPciIoFncs, + snp->ReceiveBufUnmap + ); + Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen); + mPciIoFncs->FreeBuffer ( + mPciIoFncs, + Size, + snp->receive_buf + ); + + } + +Error_DeleteCPBDB: + if (snp->IsOldUndi) { + Status = mPciIoFncs->Unmap ( + mPciIoFncs, + snp->CpbUnmap + ); + } + + Status = mPciIoFncs->FreeBuffer ( + mPciIoFncs, + SNP_MEM_PAGES (4096), + snp->cpb + ); + +Error_DeleteSNP: + if (snp->IsOldUndi) { + Status = mPciIoFncs->Unmap ( + mPciIoFncs, + snp->SnpDriverUnmap + ); + } + + mPciIoFncs->FreeBuffer ( + mPciIoFncs, + SNP_MEM_PAGES (sizeof (SNP_DRIVER)), + snp + ); +NiiError: + if (!UndiNew) { + gBS->CloseProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } else { + gBS->CloseProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + This->DriverBindingHandle, + Controller + ); + } + + gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + return Status; +} + +EFI_STATUS +EFIAPI +SimpleNetworkDriverStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Controller, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol; + SNP_DRIVER *Snp; + + // + // Get our context back. + // + Status = gBS->OpenProtocol ( + Controller, + &gEfiSimpleNetworkProtocolGuid, + (VOID **) &SnpProtocol, + This->DriverBindingHandle, + Controller, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol); + + Status = gBS->UninstallProtocolInterface ( + Controller, + &gEfiSimpleNetworkProtocolGuid, + &Snp->snp + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + if (!Snp->IsOldUndi) { + Status = gBS->CloseProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + This->DriverBindingHandle, + Controller + ); + } else { + Status = gBS->CloseProtocol ( + Controller, + &gEfiNetworkInterfaceIdentifierProtocolGuid, + This->DriverBindingHandle, + Controller + ); + } + + Status = gBS->CloseProtocol ( + Controller, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Controller + ); + + pxe_shutdown (Snp); + pxe_stop (Snp); + + if (Snp->IsOldUndi) { + Status = mPciIoFncs->Unmap ( + mPciIoFncs, + Snp->FillHdrBufUnmap + ); + + mPciIoFncs->FreeBuffer ( + mPciIoFncs, + SNP_MEM_PAGES (Snp->init_info.MediaHeaderLen), + Snp->fill_hdr_buf + ); + Status = mPciIoFncs->Unmap ( + mPciIoFncs, + Snp->ReceiveBufUnmap + ); + + mPciIoFncs->FreeBuffer ( + mPciIoFncs, + SNP_MEM_PAGES (Snp->init_info.MediaHeaderLen + Snp->init_info.FrameDataLen), + Snp->receive_buf + ); + + Status = mPciIoFncs->Unmap ( + mPciIoFncs, + Snp->CpbUnmap + ); + Status = mPciIoFncs->Unmap ( + mPciIoFncs, + Snp->SnpDriverUnmap + ); + } + + mPciIoFncs->FreeBuffer ( + mPciIoFncs, + SNP_MEM_PAGES (4096), + Snp->cpb + ); + + mPciIoFncs->FreeBuffer ( + mPciIoFncs, + SNP_MEM_PAGES (sizeof (SNP_DRIVER)), + Snp + ); + + return Status; +} + diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/snp.h b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/snp.h new file mode 100644 index 0000000000..05c5a8bb92 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/snp.h @@ -0,0 +1,410 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + snp.h + +Abstract: + +Revision history: + 2000-Feb-03 M(f)J Genesis. +--*/ +#ifndef _SNP_H +#define _SNP_H + + +#include "IndustryStandard/pci22.h" + +#define SNP_DEBUG 0 +#define FOUR_GIGABYTES (UINT64) 0x100000000ULL + +#if SNP_DEBUG +#undef D_NET +#define D_NET D_WARN +#define SNP_PRINT(DebugInfo) Print (DebugInfo) +#else +#define SNP_PRINT(DebugInfo) +#endif + +#define SNP_DRIVER_SIGNATURE EFI_SIGNATURE_32 ('s', 'n', 'd', 's') +#define MAX_MAP_LENGTH 100 + +#define PCI_BAR_IO_MASK 0x00000003 +#define PCI_BAR_IO_MODE 0x00000001 + +#define PCI_BAR_MEM_MASK 0x0000000F +#define PCI_BAR_MEM_MODE 0x00000000 +#define PCI_BAR_MEM_64BIT 0x00000004 + +typedef struct { + UINT32 Signature; + EFI_LOCK lock; + + EFI_SIMPLE_NETWORK_PROTOCOL snp; + EFI_SIMPLE_NETWORK_MODE mode; + + EFI_HANDLE device_handle; + EFI_DEVICE_PATH_PROTOCOL *device_path; + + // + // Local instance data needed by SNP driver + // + // Pointer to S/W UNDI API entry point + // This will be NULL for H/W UNDI + // + EFI_STATUS (*issue_undi32_command) (UINT64 cdb); + + BOOLEAN is_swundi; + + // + // undi interface number, if one undi manages more nics + // + PXE_IFNUM if_num; + + // + // Allocated tx/rx buffer that was passed to UNDI Initialize. + // + UINT32 tx_rx_bufsize; + VOID *tx_rx_buffer; + // + // mappable buffers for receive and fill header for undi3.0 + // these will be used if the user buffers are above 4GB limit (instead of + // mapping the user buffers) + // + UINT8 *receive_buf; + VOID *ReceiveBufUnmap; + UINT8 *fill_hdr_buf; + VOID *FillHdrBufUnmap; + + EFI_PCI_IO_PROTOCOL *IoFncs; + UINT8 IoBarIndex; + UINT8 MemoryBarIndex; + BOOLEAN IsOldUndi; // true for EFI1.0 UNDI (3.0) drivers + // + // Buffers for command descriptor block, command parameter block + // and data block. + // + PXE_CDB cdb; + VOID *cpb; + VOID *CpbUnmap; + VOID *db; + + // + // UNDI structure, we need to remember the init info for a long time! + // + PXE_DB_GET_INIT_INFO init_info; + + VOID *SnpDriverUnmap; + // + // when ever we map an address, we must remember it's address and the un-map + // cookie so that we can unmap later + // + struct s_map_list { + EFI_PHYSICAL_ADDRESS virt; + VOID *map_cookie; + } map_list[MAX_MAP_LENGTH]; +} +SNP_DRIVER; + +#define EFI_SIMPLE_NETWORK_DEV_FROM_THIS(a) CR (a, SNP_DRIVER, snp, SNP_DRIVER_SIGNATURE) + +// +// Global Variables +// +extern EFI_COMPONENT_NAME_PROTOCOL gSimpleNetworkComponentName; +extern EFI_DRIVER_BINDING_PROTOCOL gSimpleNetworkDriverBinding; + +// +// Virtual to physical mapping for all UNDI 3.0s. +// +extern struct s_v2p { + struct s_v2p *next; + VOID *vaddr; + UINTN bsize; + EFI_PHYSICAL_ADDRESS paddr; + VOID *unmap; +} +*_v2p; + +EFI_STATUS +add_v2p ( + struct s_v2p **v2p, + EFI_PCI_IO_PROTOCOL_OPERATION type, + VOID *vaddr, + UINTN bsize + ) +; + +EFI_STATUS +find_v2p ( + struct s_v2p **v2p, + VOID *vaddr + ) +; + +EFI_STATUS +del_v2p ( + VOID *vaddr + ) +; + +extern +VOID +snp_undi32_callback_block_30 ( + IN UINT32 Enable + ) +; + +extern +VOID +snp_undi32_callback_delay_30 ( + IN UINT64 MicroSeconds + ) +; + +extern +VOID +snp_undi32_callback_memio_30 ( + IN UINT8 ReadOrWrite, + IN UINT8 NumBytes, + IN UINT64 MemOrPortAddress, + IN OUT UINT64 BufferPtr + ) +; + +extern +VOID +snp_undi32_callback_v2p_30 ( + IN UINT64 CpuAddr, + IN OUT UINT64 DeviceAddrPtr + ) +; + +extern +VOID +snp_undi32_callback_block ( + IN UINT64 UniqueId, + IN UINT32 Enable + ) +; + +extern +VOID +snp_undi32_callback_delay ( + IN UINT64 UniqueId, + IN UINT64 MicroSeconds + ) +; + +extern +VOID +snp_undi32_callback_memio ( + IN UINT64 UniqueId, + IN UINT8 ReadOrWrite, + IN UINT8 NumBytes, + IN UINT64 MemOrPortAddr, + IN OUT UINT64 BufferPtr + ) +; + +extern +VOID +snp_undi32_callback_map ( + IN UINT64 UniqueId, + IN UINT64 CpuAddr, + IN UINT32 NumBytes, + IN UINT32 Direction, + IN OUT UINT64 DeviceAddrPtr + ) +; + +extern +VOID +snp_undi32_callback_unmap ( + IN UINT64 UniqueId, + IN UINT64 CpuAddr, + IN UINT32 NumBytes, + IN UINT32 Direction, + IN UINT64 DeviceAddr // not a pointer to device address + ) +; + +extern +VOID +snp_undi32_callback_sync ( + IN UINT64 UniqueId, + IN UINT64 CpuAddr, + IN UINT32 NumBytes, + IN UINT32 Direction, + IN UINT64 DeviceAddr // not a pointer to device address + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_start ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_stop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_initialize ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this, + IN UINTN extra_rx_buffer_size OPTIONAL, + IN UINTN extra_tx_buffer_size OPTIONAL + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_reset ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this, + IN BOOLEAN ExtendedVerification + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_shutdown ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_receive_filters ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + IN UINT32 enable, + IN UINT32 disable, + IN BOOLEAN reset_mcast_filter, + IN UINTN mcast_filter_count OPTIONAL, + IN EFI_MAC_ADDRESS * mcast_filter OPTIONAL + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_station_address ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + IN BOOLEAN reset, + IN EFI_MAC_ADDRESS *new OPTIONAL + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_statistics ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + IN BOOLEAN reset, + IN OUT UINTN *statistics_size OPTIONAL, + IN OUT EFI_NETWORK_STATISTICS * statistics_table OPTIONAL + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_mcast_ip_to_mac ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_nvdata ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this, + IN BOOLEAN read_write, + IN UINTN offset, + IN UINTN buffer_size, + IN OUT VOID *buffer + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_get_status ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + OUT UINT32 *interrupt_status OPTIONAL, + OUT VOID **tx_buffer OPTIONAL + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_transmit ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + IN UINTN header_size, + IN UINTN buffer_size, + IN VOID *buffer, + IN EFI_MAC_ADDRESS * src_addr OPTIONAL, + IN EFI_MAC_ADDRESS * dest_addr OPTIONAL, + IN UINT16 *protocol OPTIONAL + ) +; + +extern +EFI_STATUS +EFIAPI +snp_undi32_receive ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + OUT UINTN *header_size OPTIONAL, + IN OUT UINTN *buffer_size, + OUT VOID *buffer, + OUT EFI_MAC_ADDRESS * src_addr OPTIONAL, + OUT EFI_MAC_ADDRESS * dest_addr OPTIONAL, + OUT UINT16 *protocol OPTIONAL + ) +; + +typedef +EFI_STATUS +(*issue_undi32_command) ( + UINT64 cdb + ); +typedef +VOID +(*ptr) ( + VOID + ); + +#define SNP_MEM_PAGES(x) (((x) - 1) / 4096 + 1) + +#if SNP_DEBUG +extern +VOID +snp_wait_for_key ( + VOID + ) +; +#endif + +#endif /* _SNP_H */ diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/start.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/start.c new file mode 100644 index 0000000000..1fab0de8ef --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/start.c @@ -0,0 +1,191 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + start.c + +Abstract: + +Revision history: + 2000-Feb-07 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_start ( + SNP_DRIVER *snp + ) +/*++ + +Routine Description: + this routine calls undi to start the interface and changes the snp state! + +Arguments: + snp - pointer to snp driver structure + +Returns: + +--*/ +{ + PXE_CPB_START_30 *cpb; + PXE_CPB_START_31 *cpb_31; + + cpb = snp->cpb; + cpb_31 = snp->cpb; + // + // Initialize UNDI Start CDB for H/W UNDI + // + snp->cdb.OpCode = PXE_OPCODE_START; + snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED; + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.DBsize = PXE_DBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + snp->cdb.DBaddr = PXE_DBADDR_NOT_USED; + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Make changes to H/W UNDI Start CDB if this is + // a S/W UNDI. + // + if (snp->is_swundi) { + if (snp->IsOldUndi) { + snp->cdb.CPBsize = sizeof (PXE_CPB_START_30); + snp->cdb.CPBaddr = (UINT64) (UINTN) cpb; + + cpb->Delay = (UINT64) &snp_undi32_callback_delay_30; + cpb->Block = (UINT64) &snp_undi32_callback_block_30; + + // + // Virtual == Physical. This can be set to zero. + // + cpb->Virt2Phys = (UINT64) &snp_undi32_callback_v2p_30; + cpb->Mem_IO = (UINT64) &snp_undi32_callback_memio_30; + } else { + snp->cdb.CPBsize = sizeof (PXE_CPB_START_31); + snp->cdb.CPBaddr = (UINT64) (UINTN) cpb_31; + + cpb_31->Delay = (UINT64) &snp_undi32_callback_delay; + cpb_31->Block = (UINT64) &snp_undi32_callback_block; + + // + // Virtual == Physical. This can be set to zero. + // + cpb_31->Virt2Phys = (UINT64) 0; + cpb_31->Mem_IO = (UINT64) &snp_undi32_callback_memio; + + cpb_31->Map_Mem = (UINT64) &snp_undi32_callback_map; + cpb_31->UnMap_Mem = (UINT64) &snp_undi32_callback_unmap; + cpb_31->Sync_Mem = (UINT64) &snp_undi32_callback_sync; + + cpb_31->Unique_ID = (UINT64) (UINTN) snp; + } + } + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.start() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) { + // + // UNDI could not be started. Return UNDI error. + // + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.start() %xh:%xh\n", + snp->cdb.StatCode, + snp->cdb.StatFlags) + ); + + return EFI_DEVICE_ERROR; + } + // + // Set simple network state to Started and return success. + // + snp->mode.State = EfiSimpleNetworkStarted; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +snp_undi32_start ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +/*++ + +Routine Description: + This is the SNP interface routine for starting the interface + This routine basically retrieves snp structure, checks the SNP state and + calls the pxe_start routine to actually do start undi interface + +Arguments: + This - context pointer + +Returns: + EFI_INVALID_PARAMETER - "This" is Null + - No SNP driver can be extracted from "This" + EFI_ALREADY_STARTED - The state of SNP is EfiSimpleNetworkStarted + or EfiSimpleNetworkInitialized + EFI_DEVICE_ERROR - The state of SNP is other than EfiSimpleNetworkStarted, + EfiSimpleNetworkInitialized, and EfiSimpleNetworkStopped + EFI_SUCCESS - UNDI interface is succesfully started + Other - Error occurs while calling pxe_start function. + +--*/ +{ + SNP_DRIVER *Snp; + EFI_STATUS Status; + UINTN Index; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (This); + + if (Snp == NULL) { + return EFI_INVALID_PARAMETER; + } + + switch (Snp->mode.State) { + case EfiSimpleNetworkStopped: + break; + + case EfiSimpleNetworkStarted: + case EfiSimpleNetworkInitialized: + return EFI_ALREADY_STARTED; + + default: + return EFI_DEVICE_ERROR; + } + + Status = pxe_start (Snp); + if (Status != EFI_SUCCESS) { + return Status; + } + // + // clear the map_list in SNP structure + // + for (Index = 0; Index < MAX_MAP_LENGTH; Index++) { + Snp->map_list[Index].virt = 0; + Snp->map_list[Index].map_cookie = 0; + } + + Snp->mode.MCastFilterCount = 0; + + return Status; +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/station_address.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/station_address.c new file mode 100644 index 0000000000..2d143ef9a5 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/station_address.c @@ -0,0 +1,248 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + station_address.c + +Abstract: + +Revision history: + 2000-Feb-17 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_get_stn_addr ( + SNP_DRIVER *snp + ) +/*++ + +Routine Description: + this routine calls undi to read the MAC address of the NIC and updates the + mode structure with the address. + +Arguments: + snp - pointer to snp driver structure + +Returns: + +--*/ +{ + PXE_DB_STATION_ADDRESS *db; + + db = snp->db; + snp->cdb.OpCode = PXE_OPCODE_STATION_ADDRESS; + snp->cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_READ; + + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + + snp->cdb.DBsize = sizeof (PXE_DB_STATION_ADDRESS); + snp->cdb.DBaddr = (UINT64) (UINTN) db; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) { + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.station_addr() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_DEVICE_ERROR; + } + // + // Set new station address in SNP->Mode structure and return success. + // + CopyMem ( + &(snp->mode.CurrentAddress), + &db->StationAddr, + snp->mode.HwAddressSize + ); + + CopyMem ( + &snp->mode.BroadcastAddress, + &db->BroadcastAddr, + snp->mode.HwAddressSize + ); + + CopyMem ( + &snp->mode.PermanentAddress, + &db->PermanentAddr, + snp->mode.HwAddressSize + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +pxe_set_stn_addr ( + SNP_DRIVER *snp, + EFI_MAC_ADDRESS *NewMacAddr + ) +/*++ + +Routine Description: + this routine calls undi to set a new MAC address for the NIC, + +Arguments: + snp - pointer to snp driver structure + NewMacAddr - pointer to a mac address to be set for the nic, if this is NULL + then this routine resets the mac address to the NIC's original + address. + +Returns: + +--*/ +{ + PXE_CPB_STATION_ADDRESS *cpb; + PXE_DB_STATION_ADDRESS *db; + + cpb = snp->cpb; + db = snp->db; + snp->cdb.OpCode = PXE_OPCODE_STATION_ADDRESS; + + if (NewMacAddr == NULL) { + snp->cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_RESET; + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + } else { + snp->cdb.OpFlags = PXE_OPFLAGS_STATION_ADDRESS_READ; + // + // even though the OPFLAGS are set to READ, supplying a new address + // in the CPB will make undi change the mac address to the new one. + // + CopyMem (&cpb->StationAddr, NewMacAddr, snp->mode.HwAddressSize); + + snp->cdb.CPBsize = sizeof (PXE_CPB_STATION_ADDRESS); + snp->cdb.CPBaddr = (UINT64) (UINTN) cpb; + } + + snp->cdb.DBsize = sizeof (PXE_DB_STATION_ADDRESS); + snp->cdb.DBaddr = (UINT64) (UINTN) db; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.station_addr() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) { + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.station_addr() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + // + // UNDI command failed. Return UNDI status to caller. + // + return EFI_DEVICE_ERROR; + } + // + // read the changed address and save it in SNP->Mode structure + // + pxe_get_stn_addr (snp); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +snp_undi32_station_address ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + IN BOOLEAN ResetFlag, + IN EFI_MAC_ADDRESS * NewMacAddr OPTIONAL + ) +/*++ + +Routine Description: + This is the SNP interface routine for changing the NIC's mac address. + This routine basically retrieves snp structure, checks the SNP state and + calls the above routines to actually do the work + +Arguments: + this - context pointer + NewMacAddr - pointer to a mac address to be set for the nic, if this is NULL + then this routine resets the mac address to the NIC's original + address. + ResetFlag - If true, the mac address will change to NIC's original address + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + EFI_STATUS Status; + + // + // Get pointer to SNP driver instance for *this. + // + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Return error if the SNP is not initialized. + // + switch (snp->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + // + // Check for invalid parameter combinations. + // + if (!ResetFlag && NewMacAddr == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (ResetFlag) { + Status = pxe_set_stn_addr (snp, NULL); + } else { + Status = pxe_set_stn_addr (snp, NewMacAddr); + + } + + return Status; +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/statistics.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/statistics.c new file mode 100644 index 0000000000..1c148a7e3f --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/statistics.c @@ -0,0 +1,193 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + statistics.c + +Abstract: + +Revision history: + 2000-Feb-17 M(f)J Genesis. +--*/ + + +#include "Snp.h" + +EFI_STATUS +EFIAPI +snp_undi32_statistics ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + IN BOOLEAN ResetFlag, + IN OUT UINTN *StatTableSizePtr OPTIONAL, + IN OUT EFI_NETWORK_STATISTICS * StatTablePtr OPTIONAL + ) +/*++ + +Routine Description: + This is the SNP interface routine for getting the NIC's statistics. + This routine basically retrieves snp structure, checks the SNP state and + calls the pxe_ routine to actually do the + +Arguments: + this - context pointer + ResetFlag - true to reset the NIC's statistics counters to zero. + StatTableSizePtr - pointer to the statistics table size + StatTablePtr - pointer to the statistics table + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + PXE_DB_STATISTICS *db; + UINT64 *stp; + UINT64 mask; + UINTN size; + UINTN n; + + // + // Get pointer to SNP driver instance for *this. + // + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Return error if the SNP is not initialized. + // + switch (snp->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + // + // if we are not resetting the counters, we have to have a valid stat table + // with >0 size. if no reset, no table and no size, return success. + // + if (!ResetFlag && StatTableSizePtr == NULL) { + return StatTablePtr ? EFI_INVALID_PARAMETER : EFI_SUCCESS; + } + // + // Initialize UNDI Statistics CDB + // + snp->cdb.OpCode = PXE_OPCODE_STATISTICS; + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + if (ResetFlag) { + snp->cdb.OpFlags = PXE_OPFLAGS_STATISTICS_RESET; + snp->cdb.DBsize = PXE_DBSIZE_NOT_USED; + snp->cdb.DBaddr = PXE_DBADDR_NOT_USED; + db = snp->db; + } else { + snp->cdb.OpFlags = PXE_OPFLAGS_STATISTICS_READ; + snp->cdb.DBsize = sizeof (PXE_DB_STATISTICS); + snp->cdb.DBaddr = (UINT64) (UINTN) (db = snp->db); + } + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.statistics() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + switch (snp->cdb.StatCode) { + case PXE_STATCODE_SUCCESS: + break; + + case PXE_STATCODE_UNSUPPORTED: + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.statistics() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_UNSUPPORTED; + + default: + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.statistics() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_DEVICE_ERROR; + } + + if (ResetFlag) { + return EFI_SUCCESS; + } + + if (StatTablePtr == NULL) { + *StatTableSizePtr = sizeof (EFI_NETWORK_STATISTICS); + return EFI_BUFFER_TOO_SMALL; + } + // + // Convert the UNDI statistics information to SNP statistics + // information. + // + ZeroMem (StatTablePtr, *StatTableSizePtr); + stp = (UINT64 *) StatTablePtr; + size = 0; + + for (n = 0, mask = 1; n < 64; n++, mask = LShiftU64 (mask, 1), stp++) { + // + // There must be room for a full UINT64. Partial + // numbers will not be stored. + // + if ((n + 1) * sizeof (UINT64) > *StatTableSizePtr) { + break; + } + + if (db->Supported & mask) { + *stp = db->Data[n]; + size = n + 1; + } else { + SetMem (stp, sizeof (UINT64), 0xFF); + } + } + // + // Compute size up to last supported statistic. + // + while (++n < 64) { + if (db->Supported & (mask = LShiftU64 (mask, 1))) { + size = n; + } + } + + size *= sizeof (UINT64); + + if (*StatTableSizePtr >= size) { + *StatTableSizePtr = size; + return EFI_SUCCESS; + } else { + *StatTableSizePtr = size; + return EFI_BUFFER_TOO_SMALL; + } +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/stop.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/stop.c new file mode 100644 index 0000000000..c68731df26 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/stop.c @@ -0,0 +1,120 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + stop.c + +Abstract: + +Revision history: + 2000-Feb-09 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_stop ( + SNP_DRIVER *snp + ) +/*++ + +Routine Description: + this routine calls undi to stop the interface and changes the snp state + +Arguments: + snp - pointer to snp driver structure + +Returns: + +--*/ +{ + snp->cdb.OpCode = PXE_OPCODE_STOP; + snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED; + snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED; + snp->cdb.DBsize = PXE_DBSIZE_NOT_USED; + snp->cdb.CPBaddr = PXE_CPBADDR_NOT_USED; + snp->cdb.DBaddr = PXE_DBADDR_NOT_USED; + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Issue UNDI command + // + DEBUG ((EFI_D_NET, "\nsnp->undi.stop() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) { + DEBUG ( + (EFI_D_WARN, + "\nsnp->undi.stop() %xh:%xh\n", + snp->cdb.StatCode, + snp->cdb.StatFlags) + ); + + return EFI_DEVICE_ERROR; + } + // + // Set simple network state to Started and return success. + // + snp->mode.State = EfiSimpleNetworkStopped; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +snp_undi32_stop ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *this + ) +/*++ + +Routine Description: + This is the SNP interface routine for stopping the interface. + This routine basically retrieves snp structure, checks the SNP state and + calls the pxe_stop routine to actually stop the undi interface + +Arguments: + this - context pointer + +Returns: + +--*/ +{ + SNP_DRIVER *snp; + + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + + switch (snp->mode.State) { + case EfiSimpleNetworkStarted: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkInitialized: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + + return pxe_stop (snp); +} diff --git a/EdkModulePkg/Universal/Network/Snp32_64/Dxe/transmit.c b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/transmit.c new file mode 100644 index 0000000000..b48e2c79e8 --- /dev/null +++ b/EdkModulePkg/Universal/Network/Snp32_64/Dxe/transmit.c @@ -0,0 +1,396 @@ +/*++ +Copyright (c) 2006, 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. + +Module name: + + transmit.c + +Abstract: + +Revision history: + 2000-Feb-03 M(f)J Genesis. +--*/ + + +#include "snp.h" + +EFI_STATUS +pxe_fillheader ( + SNP_DRIVER *snp, + VOID *MacHeaderPtr, + UINTN MacHeaderSize, + VOID *BufferPtr, + UINTN BufferLength, + EFI_MAC_ADDRESS *DestinationAddrPtr, + EFI_MAC_ADDRESS *SourceAddrPtr, + UINT16 *ProtocolPtr + ) +/*++ + +Routine Description: + This routine calls undi to create the meadia header for the given data buffer. + +Arguments: + snp - pointer to SNP driver structure + MacHeaderPtr - address where the media header will be filled in. + MacHeaderSize - size of the memory at MacHeaderPtr + BufferPtr - data buffer pointer + BufferLength - Size of data in the BufferPtr + DestinationAddrPtr - address of the destination mac address buffer + SourceAddrPtr - address of the source mac address buffer + ProtocolPtr - address of the protocol type + +Returns: + EFI_SUCCESS - if successfully completed the undi call + Other - error return from undi call. + +--*/ +{ + PXE_CPB_FILL_HEADER_FRAGMENTED *cpb; + EFI_STATUS Status; + struct s_v2p *pkt_v2p; + UINT64 TempData; + + cpb = snp->cpb; + if (SourceAddrPtr) { + CopyMem ( + (VOID *) cpb->SrcAddr, + (VOID *) SourceAddrPtr, + snp->mode.HwAddressSize + ); + } else { + CopyMem ( + (VOID *) cpb->SrcAddr, + (VOID *) &(snp->mode.CurrentAddress), + snp->mode.HwAddressSize + ); + } + + CopyMem ( + (VOID *) cpb->DestAddr, + (VOID *) DestinationAddrPtr, + snp->mode.HwAddressSize + ); + + // + // we need to do the byte swapping + // + cpb->Protocol = (UINT16) PXE_SWAP_UINT16 (*ProtocolPtr); + + cpb->PacketLen = (UINT32) (BufferLength); + cpb->MediaHeaderLen = (UINT16) MacHeaderSize; + + cpb->FragCnt = 2; + cpb->reserved = 0; + + cpb->FragDesc[0].FragAddr = (UINT64) (UINTN) MacHeaderPtr; + cpb->FragDesc[0].FragLen = (UINT32) MacHeaderSize; + cpb->FragDesc[1].FragAddr = (UINT64) (UINTN) BufferPtr; + cpb->FragDesc[1].FragLen = (UINT32) BufferLength; + + cpb->FragDesc[0].reserved = cpb->FragDesc[1].reserved = 0; + + if (snp->IsOldUndi) { + TempData = (UINT64) (UINTN) MacHeaderPtr; + if (TempData >= FOUR_GIGABYTES) { + cpb->FragDesc[0].FragAddr = (UINT64) (UINTN) snp->fill_hdr_buf; + cpb->FragDesc[0].FragLen = (UINT32) snp->init_info.MediaHeaderLen; + } + + TempData = (UINT64) (UINTN) (BufferPtr); + if (TempData >= FOUR_GIGABYTES) { + // + // Let the device just read this buffer + // + Status = add_v2p ( + &pkt_v2p, + EfiPciIoOperationBusMasterRead, + BufferPtr, + BufferLength + ); + if (Status != EFI_SUCCESS) { + return Status; + } + // + // give the virtual address to UNDI and it will call back on Virt2Phys + // to get the mapped address, if it needs it + // + cpb->FragDesc[1].FragLen = (UINT32) pkt_v2p->bsize; + } + } + + snp->cdb.OpCode = PXE_OPCODE_FILL_HEADER; + snp->cdb.OpFlags = PXE_OPFLAGS_FILL_HEADER_FRAGMENTED; + + snp->cdb.DBsize = PXE_DBSIZE_NOT_USED; + snp->cdb.DBaddr = PXE_DBADDR_NOT_USED; + + snp->cdb.CPBsize = sizeof (PXE_CPB_FILL_HEADER_FRAGMENTED); + snp->cdb.CPBaddr = (UINT64) (UINTN) cpb; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.fill_header() ")); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + if (snp->IsOldUndi) { + TempData = (UINT64) (UINTN) (BufferPtr); + if (TempData >= FOUR_GIGABYTES) { + del_v2p (BufferPtr); + } + // + // if we used the global buffer for header, copy the contents + // + TempData = (UINT64) (UINTN) MacHeaderPtr; + if (TempData >= FOUR_GIGABYTES) { + CopyMem ( + MacHeaderPtr, + snp->fill_hdr_buf, + snp->init_info.MediaHeaderLen + ); + } + } + + switch (snp->cdb.StatCode) { + case PXE_STATCODE_SUCCESS: + return EFI_SUCCESS; + + case PXE_STATCODE_INVALID_PARAMETER: + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.fill_header() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_INVALID_PARAMETER; + + default: + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.fill_header() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return EFI_DEVICE_ERROR; + } +} + +EFI_STATUS +pxe_transmit ( + SNP_DRIVER *snp, + VOID *BufferPtr, + UINTN BufferLength + ) +/*++ + +Routine Description: + This routine calls undi to transmit the given data buffer + +Arguments: + snp - pointer to SNP driver structure + BufferPtr - data buffer pointer + BufferLength - Size of data in the BufferPtr + +Returns: + EFI_SUCCESS - if successfully completed the undi call + Other - error return from undi call. + +--*/ +{ + PXE_CPB_TRANSMIT *cpb; + EFI_STATUS Status; + struct s_v2p *v2p; + UINT64 TempData; + + cpb = snp->cpb; + cpb->FrameAddr = (UINT64) (UINTN) BufferPtr; + cpb->DataLen = (UINT32) BufferLength; + + TempData = (UINT64) (UINTN) BufferPtr; + if (snp->IsOldUndi && (TempData >= FOUR_GIGABYTES)) { + // + // we need to create a mapping now and give it to the undi when it calls + // the Virt2Phys on this address. + // this is a transmit, just map it for the device to READ + // + Status = add_v2p ( + &v2p, + EfiPciIoOperationBusMasterRead, + BufferPtr, + BufferLength + ); + if (Status != EFI_SUCCESS) { + return Status; + } + + cpb->DataLen = (UINT32) v2p->bsize; + } + + cpb->MediaheaderLen = 0; + cpb->reserved = 0; + + snp->cdb.OpFlags = PXE_OPFLAGS_TRANSMIT_WHOLE; + + snp->cdb.CPBsize = sizeof (PXE_CPB_TRANSMIT); + snp->cdb.CPBaddr = (UINT64) (UINTN) cpb; + + snp->cdb.OpCode = PXE_OPCODE_TRANSMIT; + snp->cdb.DBsize = PXE_DBSIZE_NOT_USED; + snp->cdb.DBaddr = PXE_DBADDR_NOT_USED; + + snp->cdb.StatCode = PXE_STATCODE_INITIALIZE; + snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE; + snp->cdb.IFnum = snp->if_num; + snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST; + + // + // Issue UNDI command and check result. + // + DEBUG ((EFI_D_NET, "\nsnp->undi.transmit() ")); + DEBUG ((EFI_D_NET, "\nsnp->cdb.OpCode == %x", snp->cdb.OpCode)); + DEBUG ((EFI_D_NET, "\nsnp->cdb.CPBaddr == %X", snp->cdb.CPBaddr)); + DEBUG ((EFI_D_NET, "\nsnp->cdb.DBaddr == %X", snp->cdb.DBaddr)); + DEBUG ((EFI_D_NET, "\ncpb->FrameAddr == %X\n", cpb->FrameAddr)); + + (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb); + + DEBUG ((EFI_D_NET, "\nexit snp->undi.transmit() ")); + DEBUG ((EFI_D_NET, "\nsnp->cdb.StatCode == %r", snp->cdb.StatCode)); + + // + // we will unmap the buffers in get_status call, not here + // + switch (snp->cdb.StatCode) { + case PXE_STATCODE_SUCCESS: + return EFI_SUCCESS; + + case PXE_STATCODE_QUEUE_FULL: + case PXE_STATCODE_BUSY: + Status = EFI_NOT_READY; + break; + + default: + Status = EFI_DEVICE_ERROR; + } + + DEBUG ( + (EFI_D_ERROR, + "\nsnp->undi.transmit() %xh:%xh\n", + snp->cdb.StatFlags, + snp->cdb.StatCode) + ); + + return Status; +} + +EFI_STATUS +EFIAPI +snp_undi32_transmit ( + IN EFI_SIMPLE_NETWORK_PROTOCOL * this, + IN UINTN MacHeaderSize, + IN UINTN BufferLength, + IN VOID *BufferPtr, + IN EFI_MAC_ADDRESS * SourceAddrPtr OPTIONAL, + IN EFI_MAC_ADDRESS * DestinationAddrPtr OPTIONAL, + IN UINT16 *ProtocolPtr OPTIONAL + ) +/*++ + +Routine Description: + This is the snp interface routine for transmitting a packet. this routine + basically retrieves the snp structure, checks the snp state and calls + pxe_fill_header and pxe_transmit calls to complete the transmission. + +Arguments: + this - pointer to SNP driver context + MacHeaderSize - size of the memory at MacHeaderPtr + BufferLength - Size of data in the BufferPtr + BufferPtr - data buffer pointer + SourceAddrPtr - address of the source mac address buffer + DestinationAddrPtr - address of the destination mac address buffer + ProtocolPtr - address of the protocol type + +Returns: + EFI_SUCCESS - if successfully completed the undi call + Other - error return from undi call. + +--*/ +{ + SNP_DRIVER *snp; + EFI_STATUS Status; + + if (this == NULL) { + return EFI_INVALID_PARAMETER; + } + + snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (this); + + if (snp == NULL) { + return EFI_DEVICE_ERROR; + } + + switch (snp->mode.State) { + case EfiSimpleNetworkInitialized: + break; + + case EfiSimpleNetworkStopped: + return EFI_NOT_STARTED; + + case EfiSimpleNetworkStarted: + return EFI_DEVICE_ERROR; + + default: + return EFI_DEVICE_ERROR; + } + + if (BufferPtr == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (BufferLength < snp->mode.MediaHeaderSize) { + return EFI_BUFFER_TOO_SMALL; + } + + // + // if the MacHeaderSize is non-zero, we need to fill up the header and for that + // we need the destination address and the protocol + // + if (MacHeaderSize != 0) { + if (MacHeaderSize != snp->mode.MediaHeaderSize || DestinationAddrPtr == 0 || ProtocolPtr == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = pxe_fillheader ( + snp, + BufferPtr, + MacHeaderSize, + (UINT8 *) BufferPtr + MacHeaderSize, + BufferLength - MacHeaderSize, + DestinationAddrPtr, + SourceAddrPtr, + ProtocolPtr + ); + + if (Status != EFI_SUCCESS) { + return Status; + } + } + + return pxe_transmit (snp, BufferPtr, BufferLength); +} diff --git a/EdkModulePkg/Universal/PCD/Common/PcdCommon.c b/EdkModulePkg/Universal/PCD/Common/PcdCommon.c new file mode 100644 index 0000000000..1af93c18d8 --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Common/PcdCommon.c @@ -0,0 +1,592 @@ +/** @file +Common functions used by PCD PEIM and PCD DXE. + +Copyright (c) 2006, 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. + + +Module Name: PcdCommon.c + +**/ +#include "PcdCommon.h" + + + +/** + The function retrieves the PCD data value according to + the PCD_DATA_TYPE specified. + + @param[in] Type The PCD_DATA_TYPE used to interpret the data. + @param[in] InData The input data. + @param[in] OutData The output data. + @param[in] Len The length of the data; it is mainly used for PcdPointer type. + + @retval VOID +--*/ +VOID +GetDataBasedOnType ( + IN PCD_DATA_TYPE Type, + IN VOID *InData, + OUT VOID *OutData, + IN UINTN Len + ) +{ + if (Type == PcdPointer) { + // + // When the Type is PcdPointer, we are returning + // the address of the internal buffer kpet by + // PCD database. Therefore, we treat OutData as + // a pointer to a "VOID *". Thus, the ugly type cast + // (VOID **) is used. + // + + *((VOID **) OutData) = InData; + } else { + CopyMem (OutData, InData, Len); + } + + return; + +} + +UINTN +GetExtendedDataOffset ( + IN CONST PCD_INDEX *PcdIndex, + IN UINTN SkuIdx, + IN CONST PCD_DATABASE_HEADER *Info + ) +{ + UINT8 *OffsetAddress; + UINTN Offset; + + OffsetAddress = GetAbsoluteAddress (PcdIndex->ExtendedDataOffset, + Info->ImageIndexOffset, + Info + ); + + OffsetAddress += (SkuIdx * Info->ExtendedOffsetLength); + + + CopyMem (&Offset, OffsetAddress, Info->ExtendedOffsetLength); + + return Offset; +} + + + +VOID +GetHiiDataProperty ( + IN CONST PCD_INDEX *PcdIndex, + IN UINTN SkuIdx, + IN CONST PCD_DATABASE_HEADER *Info, + OUT EFI_GUID **VariableGuid, + OUT UINT16 **VariableName + ) +{ + UINT16 NameOffset; + UINT16 GuidOffset; + UINT8 *HiiDataOffset; + + HiiDataOffset = GetAbsoluteAddress (PcdIndex->HiiData, Info->ImageIndexOffset, Info); + HiiDataOffset += (SkuIdx * (Info->HiiGuidOffsetLength + Info->HiiVariableOffsetLength)); + + CopyMem (&GuidOffset, HiiDataOffset, Info->HiiGuidOffsetLength); + CopyMem (&NameOffset, HiiDataOffset + Info->HiiGuidOffsetLength, Info->HiiVariableOffsetLength); + + *VariableGuid = (EFI_GUID *) GetAbsoluteAddress (GuidOffset * sizeof (EFI_GUID), Info->GuidTableOffset, Info); + *VariableName = (UINT16 *) GetAbsoluteAddress (NameOffset * sizeof (UINT16) , Info->StringTableOffset, Info); + + return; +} + + + +UINTN +GetSkuIdIdx ( + IN CONST PCD_INDEX *PcdIndex, + IN CONST PCD_DATABASE_HEADER *Info + ) +{ + UINT8 *SkuIdArray; + UINTN SkuIdx; + + SkuIdArray = GetAbsoluteAddress (PcdIndex->SkuIdArray, Info->ImageIndexOffset, Info); + + SkuIdx = 0; + + if (PcdIndex->StateByte.SkuEnable) { + + for (; SkuIdx < PcdIndex->SkuCount; SkuIdx++) { + if (SkuIdArray[SkuIdx] == Info->SkuId) { + break; + } + } + + if (SkuIdx > PcdIndex->SkuCount) { + if (Info->SkuId == 0) { + // + // If no SKU_ID is set previously + // Just retrieve the first value + // + SkuIdx = 0; + } else { + // + // Just can't find the SKU_ID, ASSERT according to Spec. + // + ASSERT (FALSE); + } + } + + } + + return SkuIdx; + +} + + + +/** + The function is the worker function to get the data of a PCD entry. + + @param[in] PcdIndex The PCD Index. + @param[in] Info The attributes of the PCD database. + @param[out] Data The output data. + + @retval VOID +--*/ +UINT8* +GetPcdDataPtr ( + IN CONST PCD_INDEX *PcdIndex, + IN CONST PCD_DATABASE_HEADER *Info + ) +{ + UINTN VariableDataSize; + VOID *VariableData; + UINT16 *VariableName; + UINT8 *PcdData; + EFI_GUID *VariableGuid; + EFI_STATUS Status; + UINTN SkuIdx; + UINTN ExtendedOffset; + + // + // If Sku is not enalbed for this PCD Entry. + // SkuIdx 0 will be used to compute PcdData + // + SkuIdx = GetSkuIdIdx (PcdIndex, Info); + + if (PcdIndex->StateByte.HiiEnable) { + + GetHiiDataProperty (PcdIndex, SkuIdx, Info, &VariableGuid, &VariableName); + + Status = GetHiiVariable (VariableGuid, VariableName, &VariableData, &VariableDataSize); + ASSERT_EFI_ERROR (Status); + ASSERT (VariableDataSize >= (PcdIndex->DatumSize + PcdIndex->ExtendedDataOffset)); + + PcdData = (UINT8 *) VariableData + PcdIndex->ExtendedDataOffset; + + return PcdData; + } + + // + // For VPD and Data type, we need the ExtendedOffset. + // So get it here. + // + ExtendedOffset = GetExtendedDataOffset (PcdIndex, SkuIdx, Info); + + if (PcdIndex->StateByte.VpdEnable) { + + PcdData = (VOID *) (Info->VpdStart + ExtendedOffset); + + return PcdData; + } + + // + // For data type, we just need the pointer + // + PcdData = GetAbsoluteAddress ( + ExtendedOffset, + Info->DataBufferOffset, + Info + ); + + return PcdData; + +} + + + +/** + The function locates the PCD_INDEX according to TokeNumber and GUID space given. + + @param[in] TokenNumber The token number. + @param[in] Guid The GUID token space. + @param[out] Info The attributes of the PCD database. + + @retval PCD_INDEX* The PCD_INDEX found. +--*/ +PCD_INDEX * +FindPcdIndex ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, + IN CONST PCD_DATABASE_HEADER *Info, + OUT UINTN *Index + ) +{ + PCD_INDEX *PcdIndex; + UINTN Idx; + EFI_GUID *GuidSpace; + + PcdIndex = (PCD_INDEX *) GetAbsoluteAddress (0, Info->PcdIndexOffset, Info); + + for (Idx = 0; Idx < Info->EntryCount; Idx++, PcdIndex++) { + if (Index != NULL) { + *Index = Idx; + } + + if (PcdIndex->TokenNumber == TokenNumber) { + if (Guid == NULL) { + if (!PcdIndex->StateByte.ExtendedGuidPresent) { + return PcdIndex; + } + } else { + if (PcdIndex->StateByte.ExtendedGuidPresent) { + GuidSpace = (EFI_GUID *) GetAbsoluteAddress (PcdIndex->DynamicExGuid, Info->GuidTableOffset, Info); + if (CompareGuid (GuidSpace, Guid)) { + return PcdIndex; + } + } + } + } + + } + + if (Index != NULL) { + *Index = 0; + } + + return NULL; + +} + + + +/** + The function set the PCD Entry data value according to the + PCD_DATA_TYPE given. + + @param[out] OutData The output data. + @param[in] InData The input data. + @param[in] Len The length of the data. + + + @retval EFI_SUCESS If data value is found according to SKU_ID. + @retval EFI_NOT_FOUND If not such a value is found. + +--*/ +VOID +SetDataBasedOnType ( + OUT VOID * OutData, + IN CONST VOID * InData, + IN UINTN Len +) +{ + CopyMem (OutData, InData, Len); + + return; +} + + + +/** + The function returns the actual address of item in the PCD + database according to its Segment and Offset. + + @param[out] Offset The offset within the segment. + @param[in] SegmentStart The starting address of the segment. + @param[in] DatabaseStart The base address of the PCD DataBase. + + + @retval UINT8* The absolute address. + +--*/ +UINT8 * +GetAbsoluteAddress ( + IN UINTN Offset, + IN UINTN SegmentStart, + IN CONST PCD_DATABASE_HEADER *DatabaseStart + ) +{ + UINT8 *Address; + + Address = (UINT8 *) DatabaseStart + SegmentStart + Offset; + + return Address; +} + + + +/** + The function retrieves the PCD data value according to + TokenNumber and Guid space given. + + @param[in] Database The PCD Database Instance. + @param[in] TokenNumber The token number. + @param[in] Guid The Guid space. + @param[in] Type The storage type. + @param[out] Data The output data. + + @retval VOID + +--*/ +VOID +GetPcdEntryWorker ( + IN CONST PCD_DATABASE_HEADER *Info, + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + OUT VOID *Data + ) +{ + PCD_INDEX *PcdIndex; + UINT8 *PcdData; + + ASSERT (Data != NULL); + + // + // Find the PCD entry in list in memory first + // + PcdIndex = FindPcdIndex (TokenNumber, Guid, Info, NULL); + + ASSERT (PcdIndex != NULL); + + ASSERT (PcdIndex->StateByte.DataType == Type); + + PcdData = GetPcdDataPtr (PcdIndex, Info); + + GetDataBasedOnType (PcdIndex->StateByte.DataType, PcdData, Data, PcdIndex->DatumSize); + + return; +} + + + +/** + The function retrieves the PCD data value according to + TokenNumber and Guid space given. + + @param[in] Database The PCD Database Instance. + @param[in] TokenNumber The token number. + @param[in] Guid The Guid space. + + @retval UINTN The size of the PCD Entry. + +--*/ +UINTN +GetPcdEntrySizeWorker ( + IN CONST PCD_DATABASE_HEADER *Info, + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid OPTIONAL + ) +{ + PCD_INDEX *PcdIndex; + + // + // Find the PCD entry in list in memory first + // + PcdIndex = FindPcdIndex (TokenNumber, Guid, Info, NULL); + + ASSERT (PcdIndex != NULL); + + return PcdIndex->DatumSize; + +} + + + +/** + The function checks if given GUID space match the record + in the PCD_INDEX. + + @param[in] Guid The GUID space. + @param[in] PcdIndex The PCD_INDEX. + @param[in] Info The attribute of the PCD DATABASE. + + @retval TRUE The GUID space match the record. + @retval FALSE Othewise. + +--*/ +BOOLEAN +PeiImageIndexMatchGuidSpace ( + IN CONST EFI_GUID *Guid, + IN CONST PCD_INDEX *PcdIndex, + IN CONST PCD_DATABASE_HEADER *Info +) +{ + EFI_GUID *GuidSpace; + + if (PcdIndex->StateByte.ExtendedGuidPresent) { + GuidSpace = (EFI_GUID *) GetAbsoluteAddress (PcdIndex->DynamicExGuid, Info->GuidTableOffset, Info); + return CompareGuid (GuidSpace, Guid); + } + + return FALSE; +} + + +/** + The function looks for the next PCD ENTRY. + If *TokenNumber is 0, the first TokenNumber in + the GUID token space is return. + If there is no next TokenNumber found, + *TokenNumber will be 0. + + @param[in] Database The PCD Database Instance. + @param[in,out] TokenNumber The token number. + @param[in] Guid The Guid space. + + @retval EFI_NOT_FOUND Can't find the PCD_ENTRY. + @retval EFI_SUCCESS Operation succesful. + +--*/ +EFI_STATUS +GetNextTokenWorker ( + IN CONST PCD_DATABASE_HEADER *Info, + IN OUT UINTN *TokenNumber, + IN CONST EFI_GUID *Guid OPTIONAL + ) +{ + PCD_INDEX *PcdIndex; + UINTN Idx; + BOOLEAN Found; + + Idx = 0; + Found = FALSE; + PcdIndex = (PCD_INDEX *) GetAbsoluteAddress (0, Info->PcdIndexOffset, Info); + + while ((Idx < Info->EntryCount) && !Found) { + if (*TokenNumber == 0) { + if (Guid == NULL || PeiImageIndexMatchGuidSpace (Guid, PcdIndex, Info)) { + *TokenNumber = PcdIndex->TokenNumber; + return EFI_SUCCESS; + } + } else { + if (PcdIndex->TokenNumber == *TokenNumber) { + if (Guid == NULL || PeiImageIndexMatchGuidSpace (Guid, PcdIndex, Info)) { + Found = TRUE; + } + } + } + + PcdIndex++; + Idx++; + } + + // + // No PCD Entry in the database match the GUID space given. + // + if (*TokenNumber == 0) { + return EFI_SUCCESS; + } + + // + // Can't find the PCD Entry + // + if (!Found) { + return EFI_NOT_FOUND; + } + + // + // Move to the Next Entry + // + Idx++; + PcdIndex++; + + // + // Now look for the Next TokenNumber + // + while (Idx < Info->EntryCount) { + if (Guid == NULL || PeiImageIndexMatchGuidSpace (Guid, PcdIndex, Info)) { + *TokenNumber = PcdIndex->TokenNumber; + return EFI_SUCCESS; + } + PcdIndex++; + Idx++; + } + + // + // Reache the last TokeNumber. + // + *TokenNumber = 0; + return EFI_SUCCESS; +} + + +/** + The function is the worker function to set the data of a PCD entry. + + @param[in] PcdIndex The PCD Index. + @param[in] Info The attributes of the PCD database. + @param[in] Data The input data. + + @retval VOID +--*/ +EFI_STATUS +SetPcdData ( + IN CONST PCD_INDEX *PcdIndex, + IN CONST PCD_DATABASE_HEADER *Info, + IN CONST VOID *Data + ) +{ + UINT16 *VariableName; + UINT8 *PcdData; + EFI_GUID *VariableGuid; + EFI_STATUS Status; + UINTN SkuIdx; + UINTN ExtendedOffset; + + if (PcdIndex->StateByte.VpdEnable) { + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; + } + + SkuIdx = GetSkuIdIdx (PcdIndex, Info); + + // + // For Hii and Data type, we need the ExtendedOffset. + // So get it here. + // + ExtendedOffset = GetExtendedDataOffset (PcdIndex, SkuIdx, Info); + + if (PcdIndex->StateByte.HiiEnable) { + GetHiiDataProperty (PcdIndex, SkuIdx, Info, &VariableGuid, &VariableName); + + Status = SetHiiVariable (VariableGuid, + VariableName, + Data, + PcdIndex->DatumSize, + ExtendedOffset + ); + + return Status; + } + + + PcdData = GetAbsoluteAddress ( + ExtendedOffset, + Info->DataBufferOffset, + Info + ); + + CopyMem (PcdData, Data, PcdIndex->DatumSize); + + return EFI_SUCCESS; + +} + diff --git a/EdkModulePkg/Universal/PCD/Common/PcdCommon.h b/EdkModulePkg/Universal/PCD/Common/PcdCommon.h new file mode 100644 index 0000000000..f61aa5be6a --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Common/PcdCommon.h @@ -0,0 +1,386 @@ +/** @file +Common functions used by PCD PEIM and PCD DXE. + +Copyright (c) 2006, 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. + + +Module Name: PcdCommon.h + +**/ + +#ifndef __PCD_COMMON_H__ +#define __PCD_COMMON_H__ + +// +// Enumeration for PCD_DATA_TYPE +// +typedef enum { + PcdByte8, + PcdByte16, + PcdByte32, + PcdByte64, + PcdPointer, + PcdBoolean +} PCD_DATA_TYPE; + + +// +// The definitions for Global PCD Length Fields +// +#define PCD_LENGTH_BIT8 0x01 +#define PCD_LENGTH_BIT16 0x02 +#define PCD_LENGTH_BIT24 0x03 +#define PCD_LENGTH_BIT32 0x04 + + + +/* + * This data structure is used in transverse + */ +typedef struct { + UINTN EntryCount; + UINTN GlobalOffsetLength; + UINTN GlobalTokenLength; + UINTN GlobalGuidTabIdxLength; + UINTN GlobalDatumLength; + UINTN GlobalStrTabIdxLength; + + CONST UINT8 *DataDefaultStart; + UINTN DataDefaultLength; + UINTN WholeDataDefaultLength; + CONST UINT8 *IndexStart; + UINTN IndexLength; + CONST GUID *GuidTableStart; + UINTN GuidTableLength; + CONST UINT16 *StringTableStart; + UINTN StringTableLength; + /* Length of the in byte. + This info is from Section header + in FFS */ + UINTN ImageLength; + CONST UINT8 *ImageStart; + +} PCD_IMAGE_RECORD; + + + +typedef struct { + BOOLEAN HiiEnable; + BOOLEAN SkuEnable; + BOOLEAN VpdEnable; + BOOLEAN SkuDataArrayEnable; + PCD_DATA_TYPE DataType; + BOOLEAN ExtendedGuidPresent; +} PCD_STATEBYTE; + + + +typedef struct { + // + // All Pointer's Offset in byte + // + UINT32 TokenNumber; + PCD_STATEBYTE StateByte; + UINT32 HiiData; + UINT32 SkuIdArray; //Pointer + UINT32 ExtendedDataOffset; + UINT32 DatumSize; + UINT16 DynamicExGuid; //Pointer + UINT8 SkuCount; +} PCD_INDEX; + + + +/* + * PCD Image Definition according PCD Specification 0.51. + * + */ +#pragma pack(1) +typedef struct { + UINT8 ImageLength[3]; + // + // The length of PCD_FFS_ENCODING is included + // in ImageLength + // + UINT8 DataBufferLength[3]; + UINT8 WholeDataBufferLength[3]; + UINT8 PcdIndexLength[3]; + UINT8 GuidTableLength[3]; + // + // The StringTable can be computed using: + // ImageLength, DataBufferLength, PcdIndexLength, GuidTableLength, + // and length of PCD_FFS_ENCODING + // + UINT8 EntryCount[3]; + UINT8 GlobalOffsetLength[1]; + UINT8 GlobalTokenLength[1]; + UINT8 GuidLength[1]; + UINT8 GlobalDatumLength[1]; + UINT8 GlobalStrTabIdxLength[1]; +} PCD_FFS_ENCODING; +#pragma pack() + + + +typedef struct { + UINTN DatabaseLen; + UINTN EntryCount; + UINTN InfoLength; + UINTN GuidTableOffset; + UINTN PcdIndexOffset; + UINTN StringTableOffset; + UINTN CallbackTableOffset; + UINTN ImageIndexOffset; + UINTN DataBufferOffset; + UINTN MaxCallbackNum; + UINTN HiiVariableOffsetLength; + UINTN HiiGuidOffsetLength; + UINTN ExtendedOffsetLength; + UINT8 *VpdStart; + UINTN SkuId; +} PCD_DATABASE_HEADER; + + + +typedef struct { + PCD_DATABASE_HEADER Info; + EFI_GUID GuidTable[1]; +} PCD_DATABASE; + +extern EFI_GUID gPcdDataBaseHobGuid; + + +/** + The function returns the actual address of item in the PCD + database according to its Segment and Offset. + + @param[out] Offset The offset within the segment. + @param[in] SegmentStart The starting address of the segment. + @param[in] DatabaseStart The base address of the PCD DataBase. + + + @retval EFI_SUCESS If data value is found according to SKU_ID. + @retval EFI_NOT_FOUND If not such a value is found. + +--*/ +UINT8 * +GetAbsoluteAddress ( + IN UINTN Offset, + IN UINTN SegmentStart, + IN CONST VOID *Base + ) +; + + + +/** + The function return the number of Unicode Character in a NULL terminated string. + The NULL is NOT counted. + + @param[in] String The unicode string starts from an unaligned address. + + @retval UINTN The number of Unicode characters. +--*/ +UINTN +GetUnalignedStrLen ( + UINT16 *String +); + + +/** + The function retrieves the PCD data value according to + TokenNumber and Guid space given. + + @param[in] Info The PCD Database Info. + @param[in] TokenNumber The token number. + @param[in] Guid The Guid space. + @param[in] Type The storage type. + @param[out] Data The output data. + + @retval VOID + +--*/ +VOID +GetPcdEntryWorker ( + IN CONST PCD_DATABASE_HEADER *Info, + IN UINTN TokenNumber, + IN CONST GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + OUT VOID *Data + ) +; + + + +/** + The function retrieves the PCD data value according to + TokenNumber and Guid space given. + + @param[in] Info The PCD Database info. + @param[in] TokenNumber The token number. + @param[in] Guid The Guid space. + + @retval UINTN The size of the PCD Entry. + +--*/ +UINTN +GetPcdEntrySizeWorker ( + IN CONST PCD_DATABASE_HEADER *Info, + IN UINTN TokenNumber, + IN CONST GUID *Guid OPTIONAL + ) +; + + + +/** + The function looks for the next PCD ENTRY. + If *TokenNumber is 0, the first TokenNumber in + the GUID token space is return. + If there is no next TokenNumber found, + *TokenNumber will be 0. + + @param[in] Info The PCD Database info. + @param[in,out] TokenNumber The token number. + @param[in] Guid The Guid space. + + @retval EFI_NOT_FOUND Can't find the PCD_ENTRY. + @retval EFI_SUCCESS Operation succesful. + +--*/ +EFI_STATUS +GetNextTokenWorker ( + IN CONST PCD_DATABASE_HEADER *Info, + IN OUT UINTN *TokenNumber, + IN CONST GUID *Guid OPTIONAL + ) +; + + + +/** + The function is the worker function to set the data of a PCD entry. + + @param[in] PcdIndex The PCD Index. + @param[in] Info The attributes of the PCD database. + @param[in] Data The input data. + + @retval VOID +--*/ +EFI_STATUS +SetPcdData ( + IN CONST PCD_INDEX *PcdIndex, + IN CONST PCD_DATABASE_HEADER *Info, + IN CONST VOID *Data + ) +; + + +/** + The function is provided by PCD PEIM and PCD DXE driver to + do the work of reading a HII variable from variable service. + + @param[in] VariableGuid The Variable GUID. + @param[in] VariableName The Variable Name. + @param[out] VariableData The output data. + @param[out] VariableSize The size of the variable. + + @retval EFI_SUCCESS Operation successful. + @retval EFI_SUCCESS Variablel not found. +--*/ +EFI_STATUS +GetHiiVariable ( + IN EFI_GUID *VariableGuid, + IN UINT16 *VariableName, + OUT VOID **VariableData, + OUT UINTN *VariableSize + ) +; + + + +/** + The function is provided by PCD PEIM and PCD DXE driver to + do the work of reading a HII variable from variable service. + + @param[in] VariableGuid The Variable GUID. + @param[in] VariableName The Variable Name. + @param[in] Data The input data. + @param[out] VariableSize The size of the variable. + @param[in] Offset The offset of the variable data that a PCD entry will starts from. + + @retval EFI_SUCCESS Operation successful. + @retval EFI_SUCCESS Variablel not found. +--*/ +EFI_STATUS +SetHiiVariable ( + IN EFI_GUID *VariableGuid, + IN UINT16 *VariableName, + IN CONST VOID *Data, + IN UINTN VariableSize, + IN UINTN Offset + ) +; + +/** + The function locates the PCD_INDEX according to TokeNumber and GUID space given. + + @param[in] TokenNumber The token number. + @param[in] Guid The GUID token space. + @param[out] Info The attributes of the PCD database. + + @retval PCD_INDEX* The PCD_INDEX found. +--*/ +PCD_INDEX * +FindPcdIndex ( + IN UINTN TokenNumber, + IN CONST GUID *Guid, + IN CONST PCD_DATABASE_HEADER *Info, + OUT UINTN *Index + ) +; + +/** + (WQBUGBUG: You must handle the new SKU_ID encoding. + The function is the worker function to get the data of a PCD entry. + + @param[in] PcdIndex The PCD Index. + @param[in] Info The attributes of the PCD database. + @param[out] Data The output data. + + @retval VOID +--*/ +UINT8* +GetPcdDataPtr ( + IN CONST PCD_INDEX *PcdIndex, + IN CONST PCD_DATABASE_HEADER *Info + ) +; + +/** + The function retrieves the PCD data value according to + the PCD_DATA_TYPE specified. + + @param[in] Type The PCD_DATA_TYPE used to interpret the data. + @param[in] InData The input data. + @param[in] OutData The output data. + @param[in] Len The length of the data; it is mainly used for PcdPointer type. + + @retval VOID +--*/ +VOID +GetDataBasedOnType ( + IN PCD_DATA_TYPE Type, + IN VOID *InData, + OUT VOID *OutData, + IN UINTN Len + ) +; +#endif diff --git a/EdkModulePkg/Universal/PCD/Dxe/Pcd.c b/EdkModulePkg/Universal/PCD/Dxe/Pcd.c new file mode 100644 index 0000000000..4ed7eb0cd0 --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Dxe/Pcd.c @@ -0,0 +1,472 @@ +/** @file +PCD DXE driver + +Copyright (c) 2006, 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. + + +Module Name: Pcd.c + +**/ + +#include "../Common/PcdCommon.h" +#include "Service.h" + + +PCD_PROTOCOL mPcdInstance = { + DxePcdSetSku, + + DxePcdGet8, + DxePcdGet16, + DxePcdGet32, + DxePcdGet64, + DxePcdGetPtr, + DxePcdGetBool, + DxePcdGetSize, + + DxePcdGet8Ex, + DxePcdGet16Ex, + DxePcdGet32Ex, + DxePcdGet64Ex, + DxePcdGetPtrEx, + DxePcdGetBoolEx, + DxePcdGetSizeEx, + + DxePcdSet8, + DxePcdSet16, + DxePcdSet32, + DxePcdSet64, + DxePcdSetPtr, + DxePcdSetBool, + + DxePcdSet8Ex, + DxePcdSet16Ex, + DxePcdSet32Ex, + DxePcdSet64Ex, + DxePcdSetPtrEx, + DxePcdSetBoolEx, + + PcdRegisterCallBackOnSet, + PcdUnRegisterCallBackOnSet, + DxePcdGetNextToken +}; + + +// +// Static global to reduce the code size +// +static EFI_HANDLE NewHandle = NULL; + +EFI_STATUS +EFIAPI +PcdDxeInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + InitPcdDxeDataBase (); + + Status = gBS->InstallProtocolInterface ( + &NewHandle, + &gPcdProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPcdInstance + ); + + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; + +} + + +EFI_STATUS +EFIAPI +DxePcdSetSku ( + IN UINTN SkuId + ) +{ + return DxeSetSku(SkuId); +} + + + +UINT8 +EFIAPI +DxePcdGet8 ( + IN UINTN TokenNumber + ) +{ + return DxePcdGet8Ex (NULL, TokenNumber); +} + + + +UINT16 +EFIAPI +DxePcdGet16 ( + IN UINTN TokenNumber + ) +{ + return DxePcdGet16Ex (NULL, TokenNumber); +} + + + +UINT32 +EFIAPI +DxePcdGet32 ( + IN UINTN TokenNumber + ) +{ + return DxePcdGet32Ex (NULL, TokenNumber); +} + + + +UINT64 +EFIAPI +DxePcdGet64 ( + IN UINTN TokenNumber + ) +{ + return DxePcdGet32Ex (NULL, TokenNumber); +} + + + +VOID * +EFIAPI +DxePcdGetPtr ( + IN UINTN TokenNumber + ) +{ + return DxePcdGetPtrEx (NULL, TokenNumber); +} + + + +BOOLEAN +EFIAPI +DxePcdGetBool ( + IN UINTN TokenNumber + ) +{ + return DxePcdGetBoolEx (NULL, TokenNumber); +} + + + +UINTN +EFIAPI +DxePcdGetSize ( + IN UINTN TokenNumber + ) +{ + return DxePcdGetSizeEx (NULL, TokenNumber); +} + + + +UINT8 +EFIAPI +DxePcdGet8Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + UINT8 Data; + + DxeGetPcdEntryWorker (TokenNumber, Guid, PcdByte8, &Data); + + return Data; +} + + + +UINT16 +EFIAPI +DxePcdGet16Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + UINT16 Data; + + DxeGetPcdEntryWorker (TokenNumber, Guid, PcdByte16, &Data); + + return Data; +} + + + +UINT32 +EFIAPI +DxePcdGet32Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + UINT32 Data; + + DxeGetPcdEntryWorker (TokenNumber, Guid, PcdByte32, &Data); + + return Data; +} + + + +UINT64 +EFIAPI +DxePcdGet64Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + UINT64 Data; + + DxeGetPcdEntryWorker (TokenNumber, Guid, PcdByte64, &Data); + + return Data; +} + + + +VOID * +EFIAPI +DxePcdGetPtrEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + VOID *Data; + + DxeGetPcdEntryWorker (TokenNumber, Guid, PcdPointer, &Data); + + return Data; +} + + + +BOOLEAN +EFIAPI +DxePcdGetBoolEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + BOOLEAN Data; + DxeGetPcdEntryWorker (TokenNumber, Guid, PcdBoolean, &Data); + return Data; +} + + + +UINTN +EFIAPI +DxePcdGetSizeEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + return DxeGetPcdEntrySizeWorker (TokenNumber, Guid); +} + + + +EFI_STATUS +EFIAPI +DxePcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + return DxePcdSet8Ex (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + return DxePcdSet16Ex (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + return DxePcdSet32Ex (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + return DxePcdSet64Ex (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSetPtr ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + return DxePcdSetPtrEx (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + return DxePcdSetBoolEx (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSet8Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + return DxeSetPcdEntryWorker (TokenNumber, Guid, PcdByte8, &Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSet16Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + return DxeSetPcdEntryWorker (TokenNumber, Guid, PcdByte16, &Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSet32Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + return DxeSetPcdEntryWorker (TokenNumber, Guid, PcdByte32, &Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSet64Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + return DxeSetPcdEntryWorker (TokenNumber, Guid, PcdByte64, &Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSetPtrEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + return DxeSetPcdEntryWorker (TokenNumber, Guid, PcdPointer, Value); +} + + + +EFI_STATUS +EFIAPI +DxePcdSetBoolEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + return DxeSetPcdEntryWorker (TokenNumber, Guid, PcdBoolean, &Value); + +} + + + + +EFI_STATUS +EFIAPI +PcdRegisterCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ) +{ + return DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction, TRUE); +} + + + +EFI_STATUS +EFIAPI +PcdUnRegisterCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ) +{ + return DxeRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction, FALSE); +} + + + +EFI_STATUS +EFIAPI +DxePcdGetNextToken ( + IN CONST EFI_GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ) +{ + return DxeGetNextTokenWorker (TokenNumber, Guid); +} + diff --git a/EdkModulePkg/Universal/PCD/Dxe/Service.c b/EdkModulePkg/Universal/PCD/Dxe/Service.c new file mode 100644 index 0000000000..280a45ea31 --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Dxe/Service.c @@ -0,0 +1,491 @@ +/** @file +Private functions used by PCD DXE driver.s + +Copyright (c) 2006, 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. + + +Module Name: Service.c + +**/ +#include "../Common/PcdCommon.h" +#include "Service.h" + +static PCD_DATABASE *PrivatePcdDxeDatabase; +static LIST_ENTRY mPcdDatabaseListHead = INITIALIZE_LIST_HEAD_VARIABLE(mPcdDatabaseListHead); + +LIST_ENTRY * +GetPcdDatabaseListHead ( + VOID + ) +{ + return &mPcdDatabaseListHead; +} + +PCD_DATABASE * +GetPcdDxeDataBaseInstance ( + VOID +) +{ + return PrivatePcdDxeDatabase; +} + +PCD_DATABASE * +SetPcdDxeDataBaseInstance ( + PCD_DATABASE *PcdDatabase +) +{ + return PrivatePcdDxeDatabase = PcdDatabase; +} + + +VOID +DxeGetPcdEntryWorker ( + IN UINTN TokenNumber, + IN CONST GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + OUT VOID *Data + ) +{ + PCD_DATABASE *Database; + Database = GetPcdDxeDataBaseInstance (); + + GetPcdEntryWorker ( &Database->Info, + TokenNumber, + Guid, + Type, + Data + ); + + + return; +} + + + +EFI_STATUS +DxeSetPcdEntryWorker ( + IN UINTN TokenNumber, + IN CONST GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + IN CONST VOID *Data + ) +{ + PCD_DATABASE *Database; + PCD_INDEX *PcdIndex; + EFI_STATUS Status; + + Database = GetPcdDxeDataBaseInstance (); + + + ASSERT (Data != NULL); + + PcdIndex = FindPcdIndex (TokenNumber, Guid, &Database->Info, NULL); + + ASSERT (PcdIndex != NULL); + + ASSERT (PcdIndex->StateByte.DataType == Type); + + // + // Invoke the callback function. + // + + Status = SetPcdData (PcdIndex, &Database->Info, Data); + + return Status; + + +} + + + +UINTN +DxeGetPcdEntrySizeWorker ( + IN UINTN TokenNumber, + IN CONST GUID *Guid OPTIONAL + ) +{ + PCD_DATABASE *Database; + Database = GetPcdDxeDataBaseInstance (); + + return GetPcdEntrySizeWorker (&Database->Info, + TokenNumber, + Guid + ); +} + + + +LIST_ENTRY * +InsertToGuidSpaceListI ( + IN LIST_ENTRY *GuidSpaceListHead, + IN CONST EFI_GUID *Guid + ) +{ + PCD_GUID_SPACE *GuidSpaceEntry; + + GuidSpaceEntry = AllocatePool (sizeof (PCD_GUID_SPACE)); + ASSERT (GuidSpaceEntry != NULL); + + GuidSpaceEntry->GuidSpace= Guid; + InitializeListHead (&GuidSpaceEntry->TokenSpaceHead); + + InsertTailList (GuidSpaceListHead, &GuidSpaceEntry->ListNode); + + return &GuidSpaceEntry->TokenSpaceHead; +} + + + +LIST_ENTRY * +InsertToTokenSpaceListI ( + IN LIST_ENTRY *TokenSpaceListHead, + IN UINTN TokenNumber + ) +{ + PCD_TOKEN_SPACE *TokenSpaceEntry; + + TokenSpaceEntry = AllocatePool (sizeof (PCD_TOKEN_SPACE)); + ASSERT (TokenSpaceEntry != NULL); + + TokenSpaceEntry->TokeNumber = TokenNumber; + InitializeListHead (&TokenSpaceEntry->CallbackListHead); + + InsertTailList (TokenSpaceListHead, &TokenSpaceEntry->ListNode); + + return &TokenSpaceEntry->CallbackListHead; +} + + + +VOID +InsertToCallbackListI ( + IN LIST_ENTRY *CallbackListHead, + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ) +{ + PCD_CALLBACK_ENTRY *CallbackEntry; + + CallbackEntry = AllocatePool (sizeof (PCD_CALLBACK_ENTRY)); + ASSERT (CallbackEntry != NULL); + CallbackEntry->CallbackFunction = CallBackFunction; + InsertTailList (CallbackListHead, &CallbackEntry->ListNode); + + return; +} + + + + +VOID +InsertToCallbackList ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ) +{ + LIST_ENTRY *GuidListNode; + LIST_ENTRY *GuidListHead; + LIST_ENTRY *TokenListNode; + LIST_ENTRY *TokenListHead; + LIST_ENTRY *CallbackListHead; + PCD_GUID_SPACE *GuidSpaceEntry; + PCD_TOKEN_SPACE *TokenSpaceEntry; + + + GuidListHead = GetPcdDatabaseListHead (); + + GuidListNode = GetFirstNode (GuidListHead); + while (!IsNull (GuidListNode, GuidListHead)) { + GuidSpaceEntry = PCD_GUID_SPACE_FROM_LISTNODE(GuidListNode); + + if (CompareGuid (GuidSpaceEntry->GuidSpace, Guid)) { + TokenListHead = &GuidSpaceEntry->TokenSpaceHead; + TokenListNode = GetFirstNode (TokenListHead); + while (!IsNull (TokenListNode, TokenListHead)) { + TokenSpaceEntry = PCD_TOKEN_SPACE_FROM_LISTNODE(TokenListNode); + if (TokenSpaceEntry->TokeNumber == TokenNumber) { + InsertToCallbackListI (&TokenSpaceEntry->CallbackListHead , CallBackFunction); + } + } + + // + // No TokenNumber match input found in this GuidSpace + // + CallbackListHead = InsertToTokenSpaceListI (TokenListHead, TokenNumber); + InsertToCallbackListI (CallbackListHead , CallBackFunction); + } + + GuidListNode = GetNextNode (GuidListHead, GuidListNode); + } + + // + // No GuidSpace match the input Guid, so build the GuidSpace, TokenNumberSpace and Callback + // + TokenListHead = InsertToGuidSpaceListI (GuidListHead, Guid); + CallbackListHead = InsertToTokenSpaceListI (TokenListHead, TokenNumber); + InsertToCallbackListI (CallbackListHead , CallBackFunction); + + return; + +} + +EFI_STATUS +RemoveFromCallbackListI ( + IN LIST_ENTRY *CallbackListHead, + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ) +{ + LIST_ENTRY *ListNode; + PCD_CALLBACK_ENTRY *CallbackEntry; + + ListNode = GetFirstNode (CallbackListHead); + + while (!IsNull(CallbackListHead, ListNode)) { + CallbackEntry = PCD_CALLBACK_ENTRY_FROM_LISTNODE(ListNode); + + if (CallbackEntry->CallbackFunction == CallBackFunction) { + RemoveEntryList (ListNode); + FreePool (CallbackEntry); + return EFI_SUCCESS; + } + ListNode = GetNextNode (CallbackListHead, ListNode); + } + + return EFI_NOT_FOUND; +} + + + +EFI_STATUS +RemoveFromCallbackList ( + IN UINTN TokenNumber, + IN CONST GUID *Guid, + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ) +{ + LIST_ENTRY *GuidListNode; + LIST_ENTRY *GuidListHead; + LIST_ENTRY *TokenListNode; + LIST_ENTRY *TokenListHead; + PCD_GUID_SPACE *GuidSpaceEntry; + PCD_TOKEN_SPACE *TokenSpaceEntry; + + + GuidListHead = GetPcdDatabaseListHead (); + + GuidListNode = GetFirstNode (GuidListHead); + while (!IsNull (GuidListNode, GuidListHead)) { + + GuidSpaceEntry = PCD_GUID_SPACE_FROM_LISTNODE(GuidListNode); + if (CompareGuid (GuidSpaceEntry->GuidSpace, Guid)) { + + TokenListHead = &GuidSpaceEntry->TokenSpaceHead; + TokenListNode = GetFirstNode (TokenListHead); + while (!IsNull (TokenListNode, TokenListHead)) { + + TokenSpaceEntry = PCD_TOKEN_SPACE_FROM_LISTNODE(TokenListNode); + if (TokenSpaceEntry->TokeNumber == TokenNumber) { + return RemoveFromCallbackListI (&TokenSpaceEntry->CallbackListHead , CallBackFunction); + } + } + + // + // No TokenNumber match input found in this GuidSpace + // + return EFI_NOT_FOUND; + } + + GuidListNode = GetNextNode (GuidListHead, GuidListNode); + } + + + return EFI_NOT_FOUND; + +} + + + +EFI_STATUS +DxeRegisterCallBackWorker ( + IN UINTN TokenNumber, + IN CONST GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction, + IN BOOLEAN Register +) +{ + PCD_DATABASE *Database; + PCD_INDEX *PcdIndex; + + Database = GetPcdDxeDataBaseInstance (); + + PcdIndex = FindPcdIndex (TokenNumber, Guid, &Database->Info, NULL); + + if (PcdIndex == NULL) { + return EFI_NOT_FOUND; + } + + if (Register) { + InsertToCallbackList (TokenNumber, Guid, CallBackFunction); + return EFI_SUCCESS; + } else { + return RemoveFromCallbackList (TokenNumber, Guid, CallBackFunction); + } + + } + + + +EFI_STATUS +DxeSetSku ( + UINTN Id +) +{ + PCD_DATABASE * Database; + + Database = GetPcdDxeDataBaseInstance (); + + return Database->Info.SkuId = Id; + +} + + + +EFI_STATUS +DxeGetNextTokenWorker ( + IN OUT UINTN *TokenNumber, + IN CONST GUID *Guid OPTIONAL + ) +{ + PCD_DATABASE * Database; + + Database = GetPcdDxeDataBaseInstance (); + + return GetNextTokenWorker (&Database->Info, + TokenNumber, + Guid + ); +} + + + +VOID +InitPcdDxeDataBase ( + VOID +) +{ + PCD_DATABASE *PeiDatabase; + PCD_DATABASE *DxeDatabase; + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + ASSERT (GuidHob != NULL); + + PeiDatabase = (PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob); + + DxeDatabase = AllocateCopyPool (PeiDatabase->Info.DatabaseLen, PeiDatabase); + + ASSERT (DxeDatabase != NULL); + + SetPcdDxeDataBaseInstance (DxeDatabase); + + return; +} + + + +EFI_STATUS +GetHiiVariable ( + IN EFI_GUID *VariableGuid, + IN UINT16 *VariableName, + OUT VOID ** VariableData, + OUT UINTN *VariableSize + ) +{ + UINTN Size; + EFI_STATUS Status; + VOID *Buffer; + + Status = EfiGetVariable ( + (UINT16 *)VariableName, + VariableGuid, + NULL, + &Size, + NULL + ); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + Buffer = AllocatePool (Size); + + ASSERT (Buffer != NULL); + + Status = EfiGetVariable ( + VariableName, + VariableGuid, + NULL, + &Size, + Buffer + ); + + return Status; + +} + + + +EFI_STATUS +SetHiiVariable ( + IN EFI_GUID *VariableGuid, + IN UINT16 *VariableName, + IN CONST VOID *Data, + IN UINTN DataSize, + IN UINTN Offset + ) +{ + UINTN Size; + VOID *Buffer; + EFI_STATUS Status; + + Size = 0; + + Status = EfiGetVariable ( + (UINT16 *)VariableName, + VariableGuid, + NULL, + &Size, + NULL + ); + + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + Buffer = AllocatePool (Size); + + ASSERT (Buffer != NULL); + + Status = EfiGetVariable ( + VariableName, + VariableGuid, + NULL, + &Size, + Buffer + ); + + + CopyMem ((UINT8 *)Buffer + Offset, Data, DataSize); + + return EfiSetVariable ( + VariableName, + VariableGuid, + 0, + Size, + Buffer + ); + +} + diff --git a/EdkModulePkg/Universal/PCD/Dxe/Service.h b/EdkModulePkg/Universal/PCD/Dxe/Service.h new file mode 100644 index 0000000000..86e3dfdee3 --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Dxe/Service.h @@ -0,0 +1,399 @@ +/** @file +Private functions used by PCD DXE driver. + +Copyright (c) 2006, 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. + + +Module Name: Service.h + +**/ + +#ifndef _SERVICE_H +#define _SERVICE_H + +VOID +DxeGetPcdEntryWorker ( + IN UINTN Token, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + OUT VOID *Data + ); + +EFI_STATUS +DxeSetPcdEntryWorker ( + IN UINTN Token, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + IN CONST VOID *Data + ); + +UINTN +DxeGetPcdEntrySizeWorker ( + IN UINTN Token, + IN CONST EFI_GUID *Guid OPTIONAL + ); + +EFI_STATUS +DxeRegisterCallBackWorker ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction, + IN BOOLEAN Reigster +); + +EFI_STATUS +DxeSetSku ( + UINTN Id +); + +EFI_STATUS +DxeGetNextTokenWorker ( + IN OUT UINTN *Token, + IN CONST EFI_GUID *Guid OPTIONAL + ); + +VOID +InitPcdDxeDataBase ( + VOID +); + +// +// Protocol Interface function declaration. +// +EFI_STATUS +EFIAPI +DxePcdSetSku ( + IN UINTN SkuId + ) +; + + +UINT8 +EFIAPI +DxePcdGet8 ( + IN UINTN TokenNumber + ) +; + + +UINT16 +EFIAPI +DxePcdGet16 ( + IN UINTN TokenNumber + ) +; + + +UINT32 +EFIAPI +DxePcdGet32 ( + IN UINTN TokenNumber + ) +; + + +UINT64 +EFIAPI +DxePcdGet64 ( + IN UINTN TokenNumber + ) +; + + +VOID * +EFIAPI +DxePcdGetPtr ( + IN UINTN TokenNumber + ) +; + + +BOOLEAN +EFIAPI +DxePcdGetBool ( + IN UINTN TokenNumber + ) +; + + +UINTN +EFIAPI +DxePcdGetSize ( + IN UINTN TokenNumber + ) +; + + +UINT8 +EFIAPI +DxePcdGet8Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +UINT16 +EFIAPI +DxePcdGet16Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +UINT32 +EFIAPI +DxePcdGet32Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + + +UINT64 +EFIAPI +DxePcdGet64Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + + +VOID * +EFIAPI +DxePcdGetPtrEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +BOOLEAN +EFIAPI +DxePcdGetBoolEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +UINTN +EFIAPI +DxePcdGetSizeEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSetPtr ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSet8Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSet16Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSet32Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSet64Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSetPtrEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +; + + +EFI_STATUS +EFIAPI +DxePcdSetBoolEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +; + + + +EFI_STATUS +EFIAPI +PcdRegisterCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ) +; + + +EFI_STATUS +EFIAPI +PcdUnRegisterCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ) +; + + +EFI_STATUS +EFIAPI +DxePcdGetNextToken ( + IN CONST EFI_GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ) +; + + +/* + This DXE_PCD_DATABASE layout. The difference of DXE_PCD_DATABASE + and PEI_PCD_DATABASE is as follows: + + 1) No PCD_CALL_BACK_TABLE; DXE_PCD_DATABASE maintain a LinkList for the + callback function registered. + + --------------------------- + | LIST_ENTRY GuidSpaceHead| + --------------------------- + | PCD_DATABASE_HEADER | + --------------------------- + | GUID_TABLE | Aligned on GUID (128 bits) + --------------------------- + | PCD_INDEX_TABLE | Aligned on PCD_INDEX (see PCD_INDEX's declaration) + --------------------------- + | IMAGE_STRING_TABLE | Aligned on 16 Bits + --------------------------- + | IMAGE_PCD_INDEX | Unaligned + --------------------------- + | Data Defaults | Unaligned + --------------------------- + | Data Buffer | + | for entries without | + | defaults | + --------------------------- + +*/ + + +typedef struct { + LIST_ENTRY ListNode; + LIST_ENTRY TokenSpaceHead; + CONST EFI_GUID *GuidSpace; +} PCD_GUID_SPACE; + +typedef struct { + LIST_ENTRY ListNode; + LIST_ENTRY CallbackListHead; + UINTN TokeNumber; +} PCD_TOKEN_SPACE; + +typedef struct { + LIST_ENTRY ListNode; + PCD_PROTOCOL_CALLBACK CallbackFunction; +} PCD_CALLBACK_ENTRY; + +#define PCD_GUID_SPACE_FROM_LISTNODE(a) \ + _CR(a, PCD_GUID_SPACE, ListNode) + +#define PCD_TOKEN_SPACE_FROM_LISTNODE(a) \ + _CR(a, PCD_TOKEN_SPACE, ListNode) + +#define PCD_CALLBACK_ENTRY_FROM_LISTNODE(a) \ + _CR(a, PCD_CALLBACK_ENTRY, ListNode) + +#endif diff --git a/EdkModulePkg/Universal/PCD/Pei/Pcd.c b/EdkModulePkg/Universal/PCD/Pei/Pcd.c new file mode 100644 index 0000000000..3fb49dd54f --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Pei/Pcd.c @@ -0,0 +1,486 @@ +/** @file +PCD PEIM + +Copyright (c) 2006, 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. + + +Module Name: Pcd.c + +**/ + +#include "../Common/PcdCommon.h" +#include "Service.h" + + +PCD_PPI mPcdPpiInstance = { + PeiPcdSetSku, + + PeiPcdGet8, + PeiPcdGet16, + PeiPcdGet32, + PeiPcdGet64, + PeiPcdGetPtr, + PeiPcdGetBool, + PeiPcdGetSize, + + PeiPcdGet8Ex, + PeiPcdGet16Ex, + PeiPcdGet32Ex, + PeiPcdGet64Ex, + PeiPcdGetPtrEx, + PeiPcdGetBoolEx, + PeiPcdGetSizeEx, + + PeiPcdSet8, + PeiPcdSet16, + PeiPcdSet32, + PeiPcdSet64, + PeiPcdSetPtr, + PeiPcdSetBool, + + PeiPcdSet8Ex, + PeiPcdSet16Ex, + PeiPcdSet32Ex, + PeiPcdSet64Ex, + PeiPcdSetPtrEx, + PeiPcdSetBoolEx, + + PcdRegisterCallBackOnSet, + PcdUnRegisterCallBackOnSet, + PeiPcdGetNextToken +}; + + + +STATIC EFI_PEI_PPI_DESCRIPTOR mPpiPCD = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPcdPpiGuid, + &mPcdPpiInstance +}; + + + +EFI_STATUS +EFIAPI +PcdPeimInit ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + UINT8 *PcdImage; + + PcdImage = (UINT8 *) LocatePcdImage (); + + BuildPcdDatabase (PcdImage); + + Status = PeiCoreInstallPpi (&mPpiPCD); + + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + + +EFI_STATUS +EFIAPI +PeiPcdSetSku ( + IN UINTN SkuId + ) +{ + PCD_DATABASE *Database; + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + ASSERT (GuidHob != NULL); + + Database = (PCD_DATABASE *) GET_GUID_HOB_DATA (GuidHob); + + Database->Info.SkuId = SkuId; + + return SkuId; +} + + + +UINT8 +EFIAPI +PeiPcdGet8 ( + IN UINTN TokenNumber + ) +{ + return PeiPcdGet8Ex (NULL, TokenNumber); +} + + + +UINT16 +EFIAPI +PeiPcdGet16 ( + IN UINTN TokenNumber + ) +{ + return PeiPcdGet16Ex (NULL, TokenNumber); +} + + + +UINT32 +EFIAPI +PeiPcdGet32 ( + IN UINTN TokenNumber + ) +{ + return PeiPcdGet32Ex (NULL, TokenNumber); +} + + + +UINT64 +EFIAPI +PeiPcdGet64 ( + IN UINTN TokenNumber + ) +{ + return PeiPcdGet64Ex (NULL, TokenNumber); +} + + + +VOID * +EFIAPI +PeiPcdGetPtr ( + IN UINTN TokenNumber + ) +{ + return PeiPcdGetPtrEx (NULL, TokenNumber); +} + + + +BOOLEAN +EFIAPI +PeiPcdGetBool ( + IN UINTN TokenNumber + ) +{ + return PeiPcdGetBoolEx (NULL, TokenNumber); +} + + + +UINTN +EFIAPI +PeiPcdGetSize ( + IN UINTN TokenNumber + ) +{ + return PeiPcdGetSizeEx (NULL, TokenNumber); +} + + + +UINT8 +EFIAPI +PeiPcdGet8Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + UINT8 Data; + + PeiGetPcdEntryWorker (TokenNumber, Guid, PcdByte8, &Data); + + return Data; +} + + + +UINT16 +EFIAPI +PeiPcdGet16Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + UINT16 Data; + + PeiGetPcdEntryWorker (TokenNumber, Guid, PcdByte16, &Data); + + return Data; +} + + + +UINT32 +EFIAPI +PeiPcdGet32Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + UINT32 Data; + + PeiGetPcdEntryWorker (TokenNumber, Guid, PcdByte32, &Data); + + return Data; +} + + + +UINT64 +EFIAPI +PeiPcdGet64Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + UINT64 Data; + + PeiGetPcdEntryWorker (TokenNumber, Guid, PcdByte64, &Data); + + return Data; +} + + + +VOID * +EFIAPI +PeiPcdGetPtrEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + VOID *Data; + + PeiGetPcdEntryWorker (TokenNumber, Guid, PcdPointer, &Data); + + return Data; +} + + + +BOOLEAN +EFIAPI +PeiPcdGetBoolEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + BOOLEAN Data; + + PeiGetPcdEntryWorker (TokenNumber, Guid, PcdBoolean, &Data); + + return Data; +} + + + +UINTN +EFIAPI +PeiPcdGetSizeEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +{ + return PeiGetPcdEntrySizeWorker (TokenNumber, Guid); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + return PeiPcdSet8Ex (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + return PeiPcdSet16Ex (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + return PeiPcdSet32Ex (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + return PeiPcdSet64Ex (NULL, TokenNumber, Value); +} + + +EFI_STATUS +EFIAPI +PeiPcdSetPtr ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + return PeiPcdSetPtrEx (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + return PeiPcdSetBoolEx (NULL, TokenNumber, Value); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSet8Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + return PeiSetPcdEntryWorker (TokenNumber, Guid, PcdByte8, &Value); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSet16Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + return PeiSetPcdEntryWorker (TokenNumber, Guid, PcdByte16, &Value); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSet32Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + return PeiSetPcdEntryWorker (TokenNumber, Guid, PcdByte32, &Value); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSet64Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + return PeiSetPcdEntryWorker (TokenNumber, Guid, PcdByte64, &Value); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSetPtrEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + return PeiSetPcdEntryWorker (TokenNumber, Guid, PcdPointer, (VOID *)Value); +} + + + +EFI_STATUS +EFIAPI +PeiPcdSetBoolEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + return PeiSetPcdEntryWorker (TokenNumber, Guid, PcdBoolean, &Value); + +} + + + + +EFI_STATUS +EFIAPI +PcdRegisterCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PPI_CALLBACK CallBackFunction + ) +{ + return PeiRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction, TRUE); +} + + + +EFI_STATUS +EFIAPI +PcdUnRegisterCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PPI_CALLBACK CallBackFunction + ) +{ + return PeiRegisterCallBackWorker (TokenNumber, Guid, CallBackFunction, FALSE); +} + + + +EFI_STATUS +EFIAPI +PeiPcdGetNextToken ( + IN CONST EFI_GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ) +{ + return PeiGetNextTokenWorker (TokenNumber, Guid); +} + + diff --git a/EdkModulePkg/Universal/PCD/Pei/Service.c b/EdkModulePkg/Universal/PCD/Pei/Service.c new file mode 100644 index 0000000000..38293252bc --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Pei/Service.c @@ -0,0 +1,812 @@ +/** @file +Private functions used by PCD PEIM. + +Copyright (c) 2006, 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. + + +Module Name: Service.c + +**/ +#include "../Common/PcdCommon.h" +#include "Service.h" + + + + +/** + This function expand the StateByte + + @param[out] StateByte The output StateByte information. + @param[in] Byte The StateByte. + + @retval VOID +--*/ +VOID +PcdImageExpandStateByte ( + OUT PCD_STATEBYTE *StateByte, + IN UINT8 Byte +) +{ + switch (Byte & PCD_STATEBYTE_DATUMTYPE) { + case PCD_BYTE8: + StateByte->DataType = PcdByte8; + break; + case PCD_BYTE16: + StateByte->DataType = PcdByte16; + break; + case PCD_BYTE32: + StateByte->DataType = PcdByte32; + break; + case PCD_BYTE64: + StateByte->DataType = PcdByte64; + break; + case PCD_POINTER: + StateByte->DataType = PcdPointer; + break; + case PCD_BOOLEAN: + StateByte->DataType = PcdBoolean; + break; + default: + ASSERT (FALSE); + } + + StateByte->ExtendedGuidPresent = (BOOLEAN) ((Byte & PCD_STATEBYTE_EXTENDEDGUIDPRESENT) != 0); + StateByte->HiiEnable = (BOOLEAN) ((Byte & PCD_STATEBYTE_HIIENABLE) != 0); + StateByte->SkuDataArrayEnable = (BOOLEAN) ((Byte & PCD_STATEBYTE_SKUDATAARRAYENABLE) != 0); + StateByte->SkuEnable = (BOOLEAN) ((Byte & PCD_STATEBYTE_SKUENABLE) != 0); + StateByte->VpdEnable = (BOOLEAN) ((Byte & PCD_STATEBYTE_VPDENABLE) != 0); + +} + + + +/** + This function locates the on the flash and + return a pointer to the Section Data on flash. + + @param[in] VOID + + @retval VOID +--*/ +UINT8 * +LocatePcdImage ( + VOID +) +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *FvHdr; + EFI_FFS_FILE_HEADER *FfsHdr; + VOID *SectionData; + + Status = PeiCoreFfsFindNextVolume (0, &FvHdr); + ASSERT_EFI_ERROR (Status); + + do { + FfsHdr = NULL; + Status = PeiCoreFfsFindNextFile (EFI_FV_FILETYPE_FREEFORM, FvHdr, &FfsHdr); + if (Status == EFI_SUCCESS) { + if (CompareGuid (&gPcdImageFileGuid, &FfsHdr->Name)) { + + Status = PeiCoreFfsFindSectionData (EFI_SECTION_RAW, FfsHdr, &SectionData); + ASSERT_EFI_ERROR (Status); + + return (UINT8 *)SectionData; + } + } + } while (Status == EFI_SUCCESS); + + ASSERT (FALSE); + + return NULL; +} + +/** + The function retrieves the PCD data value according to + TokenNumber and Guid space given. + + @param[in] TokenNumber The token number. + @param[in] Guid The Guid space. + @param[in] Type The storage type. + @param[out] Data The output data. + + + @retval EFI_SUCESS If data value is found according to SKU_ID. + @retval EFI_NOT_FOUND If not such a value is found. + +--*/ +VOID +PeiGetPcdEntryWorker ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + OUT VOID *Data + ) +{ + PCD_DATABASE *Database; + EFI_HOB_GUID_TYPE *GuidHob; + + ASSERT (Data != NULL); + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + ASSERT (GuidHob != NULL); + + Database = GET_GUID_HOB_DATA (GuidHob); + + GetPcdEntryWorker ( &Database->Info, + TokenNumber, + Guid, + Type, + Data + ); + + + return; +} + + +/** + The function set the PCD data value according to + TokenNumber and Guid space given. + + @param[in] Database The PCD Database Instance. + @param[in] TokenNumber The token number. + @param[in] Guid The Guid space. + @param[in] Type The storage type. + @param[in] Data The output data. + + + @retval EFI_SUCESS If data value is found according to SKU_ID. + @retval EFI_NOT_FOUND If not such a value is found. + +--*/ +EFI_STATUS +SetPcdEntryWorker ( + IN CONST PCD_DATABASE *Database, + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + IN VOID *Data + ) +{ + PCD_INDEX *PcdIndex; + EFI_STATUS Status; + PCD_PPI_CALLBACK *CallbackTable; + UINTN Idx; + + ASSERT (Data != NULL); + + // + // Find the PCD entry in list in memory first + // + PcdIndex = FindPcdIndex (TokenNumber, Guid, &Database->Info, &Idx); + + ASSERT (PcdIndex != NULL); + + ASSERT (PcdIndex->StateByte.DataType == Type); + + // + // Invoke the callback function. + // + CallbackTable = (PCD_PPI_CALLBACK *) + GetAbsoluteAddress (Idx * Database->Info.MaxCallbackNum * sizeof(PCD_PPI_CALLBACK), + Database->Info.CallbackTableOffset, + &Database->Info + ); + + for (Idx = 0; Idx < Database->Info.MaxCallbackNum; Idx++) { + if (CallbackTable[Idx] != NULL) { + CallbackTable[Idx] (Guid, + PcdIndex->TokenNumber, + Data, + PcdIndex->DatumSize + ); + } + } + + Status = SetPcdData (PcdIndex, &Database->Info, Data); + + return Status; +} + + + +/** + (reviewed) The function set the PCD data value according to + TokenNumber and Guid space given. + + @param[in] TokenNumber The token number. + @param[in] Guid The Guid space. + @param[in] Type The storage type. + @param[in] Data The output data. + + + @retval EFI_SUCESS If data value is found according to SKU_ID. + @retval EFI_NOT_FOUND If not such a value is found. + +--*/ +EFI_STATUS +PeiSetPcdEntryWorker ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + IN VOID *Data + ) +{ + PCD_DATABASE *Database; + EFI_HOB_GUID_TYPE *GuidHob; + + ASSERT (Data != NULL); + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + ASSERT (GuidHob != NULL); + + Database = GET_GUID_HOB_DATA (GuidHob); + + SetPcdEntryWorker (Database, + TokenNumber, + Guid, + Type, + Data + ); + + return EFI_SUCCESS; +} + + + +UINTN +PeiGetPcdEntrySizeWorker ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid OPTIONAL + ) +{ + PCD_DATABASE *Database; + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + ASSERT (GuidHob != NULL); + + Database = GET_GUID_HOB_DATA (GuidHob); + + return GetPcdEntrySizeWorker (&Database->Info, + TokenNumber, + Guid + ); + +} + + + +/** + The function registers the CallBackOnSet fucntion + according to TokenNumber and EFI_GUID space. + + @param[in] TokenNumber The token number. + @param[in] Guid The GUID space. + @param[in] CallBackFunction The Callback function to be registered. + + @retval EFI_SUCCESS If the Callback function is registered. + @retval EFI_NOT_FOUND If the PCD Entry is not found according to Token Number and GUID space. +--*/ +EFI_STATUS +PeiRegisterCallBackWorker ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PPI_CALLBACK CallBackFunction, + IN BOOLEAN Register +) +{ + PCD_DATABASE *Database; + EFI_HOB_GUID_TYPE *GuidHob; + PCD_INDEX *PcdIndex; + UINTN Idx; + PCD_PPI_CALLBACK *CallbackTable; + PCD_PPI_CALLBACK Compare; + PCD_PPI_CALLBACK Assign; + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + ASSERT (GuidHob != NULL); + + Database = GET_GUID_HOB_DATA (GuidHob); + + PcdIndex = FindPcdIndex (TokenNumber, Guid, &Database->Info, NULL); + + ASSERT (PcdIndex != NULL); + + if (PcdIndex->StateByte.VpdEnable) { + return EFI_INVALID_PARAMETER; + } + + Idx = ((UINTN) PcdIndex - Database->Info.CallbackTableOffset) / sizeof(PCD_INDEX); + + CallbackTable = (PCD_PPI_CALLBACK *) GetAbsoluteAddress ( + sizeof (PCD_PPI_CALLBACK) * Idx * Database->Info.MaxCallbackNum, + Database->Info.CallbackTableOffset, + &Database->Info + ); + + Compare = Register? NULL: CallBackFunction; + Assign = Register? CallBackFunction: NULL; + + for (Idx = 0; Idx < Database->Info.MaxCallbackNum; Idx++) { + if (CallbackTable[Idx] == Compare) { + CallbackTable[Idx] = Assign; + return EFI_SUCCESS; + } + } + + return Register? EFI_OUT_OF_RESOURCES : EFI_NOT_FOUND; + +} + + + +EFI_STATUS +PeiGetNextTokenWorker ( + IN OUT UINTN *TokenNumber, + IN CONST EFI_GUID *Guid OPTIONAL + ) +{ + PCD_DATABASE *Database; + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = GetFirstGuidHob (&gPcdDataBaseHobGuid); + ASSERT (GuidHob != NULL); + + Database = GET_GUID_HOB_DATA (GuidHob); + + return GetNextTokenWorker (&Database->Info, + TokenNumber, + Guid + ); + +} + + + +VOID +GetPcdImageInfo ( + IN CONST UINT8 *PcdImageOnFlash, + OUT PCD_IMAGE_RECORD *ImageInfo +) +{ + PCD_FFS_ENCODING *PcdFfsHdr; + + PcdFfsHdr = (PCD_FFS_ENCODING *) PcdImageOnFlash; + + ZeroMem (ImageInfo, sizeof (*ImageInfo)); + + ImageInfo->ImageStart = PcdImageOnFlash; + + CopyMem (&ImageInfo->EntryCount, PcdFfsHdr->EntryCount, 3); + + CopyMem (&ImageInfo->GlobalDatumLength, PcdFfsHdr->GlobalDatumLength, 1); + ASSERT (ImageInfo->GlobalDatumLength <= 3); + + CopyMem (&ImageInfo->GlobalOffsetLength, PcdFfsHdr->GlobalOffsetLength, 1); + ASSERT (ImageInfo->GlobalOffsetLength <= 3); + + CopyMem (&ImageInfo->GlobalTokenLength, PcdFfsHdr->GlobalTokenLength, 1); + ASSERT (ImageInfo->GlobalTokenLength <= 4); + + CopyMem (&ImageInfo->GlobalGuidTabIdxLength, PcdFfsHdr->GuidLength, 1); + ASSERT (ImageInfo->GlobalGuidTabIdxLength <= 2); + + CopyMem (&ImageInfo->GlobalStrTabIdxLength, PcdFfsHdr->GlobalStrTabIdxLength, 1); + ASSERT (ImageInfo->GlobalStrTabIdxLength <= 2); + + CopyMem (&ImageInfo->ImageLength, PcdFfsHdr->ImageLength, 3); + CopyMem (&ImageInfo->IndexLength, PcdFfsHdr->PcdIndexLength, 3); + CopyMem (&ImageInfo->WholeDataDefaultLength, PcdFfsHdr->WholeDataBufferLength, 3); + CopyMem (&ImageInfo->DataDefaultLength, PcdFfsHdr->DataBufferLength, 3); + CopyMem (&ImageInfo->GuidTableLength, PcdFfsHdr->GuidTableLength, 3); + + ImageInfo->StringTableLength = ImageInfo->ImageLength + - sizeof (PCD_FFS_ENCODING) + - ImageInfo->DataDefaultLength + - ImageInfo->IndexLength + - ImageInfo->GuidTableLength; + + ImageInfo->DataDefaultStart = PcdImageOnFlash + sizeof (PCD_FFS_ENCODING); + ImageInfo->IndexStart = ImageInfo->DataDefaultStart + ImageInfo->DataDefaultLength; + ImageInfo->GuidTableStart = (CONST EFI_GUID *)(ImageInfo->IndexStart + ImageInfo->IndexLength); + ImageInfo->StringTableStart = (CONST UINT16 *) ((UINT8 *) ImageInfo->GuidTableStart + ImageInfo->GuidTableLength); + + return; +} + + + +/** + The function builds the PCD database based on the + PCD_IMAGE on the flash. + + The layout of the PCD_DATABASE is as follows: + + --------------------------- + | PCD_DATABASE_HEADER | + --------------------------- + | GUID_TABLE | Aligned on GUID (128 bits) + --------------------------- + | PCD_CALL_BACK_TABLE | Aligned on Pointer (32 bits or 64 bits) + --------------------------- + | PCD_INDEX_TABLE | Aligned on PCD_INDEX (see PCD_INDEX's declaration) + --------------------------- + | IMAGE_STRING_TABLE | Aligned on 16 Bits + --------------------------- + | IMAGE_PCD_INDEX | Unaligned + --------------------------- + | Data Defaults | Unaligned + --------------------------- + | Data Buffer | + | for entries without | + | defaults | + --------------------------- + + @param[in] PcdImageOnFlash The PCD image on flash. + + @retval VOID +--*/ +UINTN +GetPcdDatabaseLen ( + IN CONST UINT8 *PcdImageOnFlash, + OUT PCD_DATABASE_HEADER *Info, + OUT PCD_IMAGE_RECORD *ImageInfo + ) +{ + UINTN DatabaseLen; + UINTN DatabaseHeaderLength; + UINTN PcdIndexLength; + UINTN CallbackBufferLength; + + + GetPcdImageInfo (PcdImageOnFlash, ImageInfo); + + Info->MaxCallbackNum = FixedPcdGet32(PcdMaxPcdCallBackNumber) ; + + DatabaseHeaderLength = sizeof (PCD_DATABASE) - sizeof(UINT8); + + PcdIndexLength = sizeof (PCD_INDEX) * ImageInfo->EntryCount; + CallbackBufferLength = sizeof (PCD_PPI_CALLBACK) * Info->MaxCallbackNum * ImageInfo->EntryCount; + + Info->EntryCount = ImageInfo->EntryCount; + Info->GuidTableOffset = DatabaseHeaderLength; + Info->CallbackTableOffset = Info->GuidTableOffset + ImageInfo->GuidTableLength; + Info->PcdIndexOffset = Info->PcdIndexOffset + PcdIndexLength; + Info->ImageIndexOffset = Info->CallbackTableOffset + CallbackBufferLength; + Info->DataBufferOffset = Info->ImageIndexOffset + ImageInfo->DataDefaultLength; + + Info->HiiGuidOffsetLength = ImageInfo->GlobalGuidTabIdxLength; + Info->HiiVariableOffsetLength = ImageInfo->GlobalStrTabIdxLength; + Info->ExtendedOffsetLength = ImageInfo->GlobalOffsetLength; + + Info->SkuId = 0; + + DatabaseLen = DatabaseHeaderLength + + ImageInfo->GuidTableLength + + PcdIndexLength + + CallbackBufferLength + + ImageInfo->IndexLength + + ImageInfo->WholeDataDefaultLength; + + Info->DatabaseLen = DatabaseLen; + + return DatabaseLen; +} + + +/** + The function constructs a single PCD_INDEX according a index in + . + + @param[in] ImageIndex The starting address of a PCD index defined in PCD spec 0.51. + @param[in] Index The output PCD_INDEX. + @param[in] ImageInfo The attributes of the PCD_IMAGE as this binary stream is highly + optimized for size. + + @retval UINTN The length of the current PCD index. +**/ +UINTN +BuildPcdIndex ( + IN CONST UINT8 *ImageIndex, + OUT PCD_INDEX *Index, + IN CONST PCD_IMAGE_RECORD *ImageInfo +) +{ + UINTN SkuCount; + CONST UINT8 *ImageIndexBackUp; + + ImageIndexBackUp = ImageIndex; + + // + // Token Number + // + CopyMem (&Index->TokenNumber, + ImageIndex, + ImageInfo->GlobalTokenLength + ); + + ImageIndex += ImageInfo->GlobalTokenLength; + + // + // State Byte + // + PcdImageExpandStateByte (&Index->StateByte, + *ImageIndex + ); + + ImageIndex += 1; + + // + // Dataum Size + // + CopyMem (&Index->DatumSize, + ImageIndex, + ImageInfo->GlobalDatumLength + ); + + ImageIndex += ImageInfo->GlobalDatumLength; + + // + // SKU_DATA + // + if (Index->StateByte.SkuEnable) { + Index->SkuCount = *ImageIndex; + SkuCount = *ImageIndex; + ImageIndex++; + Index->SkuIdArray = (UINT32) ImageIndex - (UINT32) ImageInfo->IndexStart; + ImageIndex += Index->SkuCount; + } else { + // + // There is always a default SKU_ID of zero even + // if SKU is not enabled for this PCD entry. + // + // + SkuCount = 1; + } + + // + // Extended Offset + // + CopyMem (&Index->ExtendedDataOffset, + ImageIndex, + ImageInfo->GlobalOffsetLength + ); + + ImageIndex += ImageInfo->GlobalOffsetLength * SkuCount; + + // + // DynamicEX Guid Offset + // + if (Index->StateByte.ExtendedGuidPresent) { + CopyMem (&Index->DynamicExGuid, + ImageIndex, + ImageInfo->GlobalGuidTabIdxLength + ); + + ImageIndex += ImageInfo->GlobalGuidTabIdxLength; + } + + // + // HII_DATA + // + if (Index->StateByte.HiiEnable) { + Index->HiiData = (UINT32) ImageIndex - (UINT32) ImageInfo->IndexStart; + ImageIndex += ((ImageInfo->GlobalStrTabIdxLength + ImageInfo->GlobalGuidTabIdxLength) * SkuCount); + } + + return (UINTN) (ImageIndex - ImageIndexBackUp); +} + + + + +/** + The function builds the PCD database based on the + PCD_IMAGE on the flash. + + @param[in] Database The database instance. + @param[in] ImageIndex The starting address of a PCD index defined in PCD spec 0.51. + @param[in] ImageInfo The attributes of the PCD_IMAGE as this binary stream is highly + optimized for size. + + @retval VOID +**/ +VOID +BuildPcdDatabaseIndex ( + PCD_DATABASE *Database, + UINT8 *ImageIndex, + PCD_IMAGE_RECORD *ImageInfo + ) +{ + UINTN Idx; + UINTN Len; + PCD_INDEX *IndexTable; + + IndexTable = (PCD_INDEX *) GetAbsoluteAddress (0, Database->Info.PcdIndexOffset, Database); + + for (Idx = 0; Idx < Database->Info.EntryCount; Idx++) { + Len = BuildPcdIndex (ImageIndex, &IndexTable[Idx], ImageInfo); + ImageIndex += Len; + } + + return; +} + + +/** + The function builds the PCD database based on the + PCD_IMAGE on the flash. + + @param[in] PcdImageOnFlash The PCD image on flash. + + @retval VOID +--*/ +VOID +BuildPcdDatabase ( + UINT8 *PcdImageOnFlash + ) +{ + PCD_DATABASE *Database; + UINTN Len; + PCD_IMAGE_RECORD ImageInfo; + UINT8 *ImageIndex; + PCD_DATABASE_HEADER DatabaseHeader; + + Len = GetPcdDatabaseLen(PcdImageOnFlash, &DatabaseHeader, &ImageInfo); + + Database = BuildGuidHob (&gPcdDataBaseHobGuid, Len); + ASSERT (Database != NULL); + + ZeroMem (Database, Len); + + // + // Update Database header + // + CopyMem (&Database->Info, &DatabaseHeader, sizeof (DatabaseHeader)); + + // + // I need this to get the GuidTableOffset as we don't + // know if Database field of PCD_DATABASE starts from an aligned + // address. The compilor may add padding after PCD_DATABASE_HEADER field. + // + Database->Info.GuidTableOffset = ((UINTN) &Database->GuidTable) - (UINTN)Database; + + // + // Copy Guid Table from Flash + // + CopyMem ((UINT8 *) Database + Database->Info.GuidTableOffset, + ImageInfo.GuidTableStart, + ImageInfo.GuidTableLength + ); + + // + // Copy ImageIndex from Flash + // + CopyMem ((UINT8 *) Database + Database->Info.ImageIndexOffset, + ImageInfo.IndexStart, + ImageInfo.IndexLength + ); + + // + // Copy Default Value + // + CopyMem ((UINT8 *) Database + Database->Info.DataBufferOffset, + ImageInfo.DataDefaultStart, + ImageInfo.DataDefaultLength + ); + + // + // Copy String Table + // + CopyMem ((UINT8 *) Database + Database->Info.StringTableOffset, + ImageInfo.StringTableStart, + ImageInfo.StringTableLength + ); + + ImageIndex = GetAbsoluteAddress (0, Database->Info.ImageIndexOffset, Database); + + BuildPcdDatabaseIndex (Database, ImageIndex, &ImageInfo); + + return; +} + + + +/** + The function is provided by PCD PEIM and PCD DXE driver to + do the work of reading a HII variable from variable service. + + @param[in] VariableGuid The Variable GUID. + @param[in] VariableName The Variable Name. + @param[out] VariableData The output data. + @param[out] VariableSize The size of the variable. + + @retval EFI_SUCCESS Operation successful. + @retval EFI_SUCCESS Variablel not found. +--*/ +EFI_STATUS +GetHiiVariable ( + IN EFI_GUID *VariableGuid, + IN UINT16 *VariableName, + OUT VOID **VariableData, + OUT UINTN *VariableSize + ) +{ + UINTN Size; + EFI_STATUS Status; + VOID *Buffer; + EFI_PEI_READ_ONLY_VARIABLE_PPI *VariablePpi; + + Status = PeiCoreLocatePpi (&gEfiPeiReadOnlyVariablePpiGuid, 0, NULL, &VariablePpi); + ASSERT_EFI_ERROR (Status); + + Size = 0; + + Status = VariablePpi->PeiGetVariable ( + GetPeiServicesTablePointer (), + VariableName, + VariableGuid, + NULL, + &Size, + NULL + ); + ASSERT (Status == EFI_BUFFER_TOO_SMALL); + + Status = PeiCoreAllocatePool (Size, &Buffer); + ASSERT_EFI_ERROR (Status); + + // declare a local for STP. + // + Status = VariablePpi->PeiGetVariable ( + GetPeiServicesTablePointer (), + (UINT16 *) VariableName, + VariableGuid, + NULL, + &Size, + Buffer + ); + ASSERT_EFI_ERROR (Status); + + *VariableSize = Size; + *VariableData = Buffer; + + return EFI_SUCCESS; +} + + + +/** + The function is provided by PCD PEIM and PCD DXE driver to + do the work of reading a HII variable from variable service. + + @param[in] VariableGuid The Variable GUID. + @param[in] VariableName The Variable Name. + @param[in] Data The input data. + @param[out] VariableSize The size of the variable. + @param[in] Offset The offset of the variable data that a PCD entry will starts from. + + @retval EFI_SUCCESS Operation successful. + @retval EFI_SUCCESS Variablel not found. +--*/ +EFI_STATUS +SetHiiVariable ( + IN EFI_GUID *VariableGuid, + IN UINT16 *VariableName, + IN CONST VOID *Data, + IN UINTN VariableSize, + IN UINTN Offset + ) +{ + ASSERT (FALSE); + return EFI_INVALID_PARAMETER; +} + + diff --git a/EdkModulePkg/Universal/PCD/Pei/Service.h b/EdkModulePkg/Universal/PCD/Pei/Service.h new file mode 100644 index 0000000000..d775a12a17 --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Pei/Service.h @@ -0,0 +1,371 @@ +/** @file +Private functions used by PCD PEIM. + +Copyright (c) 2006, 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. + + +Module Name: Service.h + +**/ + +#ifndef _SERVICE_H +#define _SERVICE_H + +// +// Offset of StateByte +// +#define PCD_STATEBYTE_HIIENABLE 0x01 +#define PCD_STATEBYTE_SKUENABLE 0x02 +#define PCD_STATEBYTE_VPDENABLE 0x04 +#define PCD_STATEBYTE_SKUDATAARRAYENABLE 0x08 +#define PCD_STATEBYTE_DATUMTYPE 0x70 +#define PCD_STATEBYTE_EXTENDEDGUIDPRESENT 0x80 + +#define PCD_DATUMTYPE_OFFSET 4 + +// +// The definitions for interpreting DatumType +// +#define PCD_BYTE8 (0x00 << PCD_DATUMTYPE_OFFSET) +#define PCD_BYTE16 (0x01 << PCD_DATUMTYPE_OFFSET) +#define PCD_BYTE32 (0x02 << PCD_DATUMTYPE_OFFSET) +#define PCD_BYTE64 (0x03 << PCD_DATUMTYPE_OFFSET) +#define PCD_POINTER (0x04 << PCD_DATUMTYPE_OFFSET) +#define PCD_BOOLEAN (0x05 << PCD_DATUMTYPE_OFFSET) + +extern GUID gEfiPcdImageHobGuid; + +/* Internal Function definitions */ + +VOID +PeiGetPcdEntryWorker ( + IN UINTN Token, + IN CONST GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + OUT VOID *Data + ); + +EFI_STATUS +PeiSetPcdEntryWorker ( + IN UINTN Token, + IN CONST GUID *Guid, OPTIONAL + IN PCD_DATA_TYPE Type, + IN VOID *Data + ); + +UINTN +PeiGetPcdEntrySizeWorker ( + IN UINTN Token, + IN CONST GUID *Guid OPTIONAL + ); + +EFI_STATUS +PeiRegisterCallBackWorker ( + IN UINTN TokenNumber, + IN CONST GUID *Guid, OPTIONAL + IN PCD_PPI_CALLBACK CallBackFunction, + IN BOOLEAN Register +); + +EFI_STATUS +PeiSetSku ( + UINTN Id +); + +EFI_STATUS +PeiGetNextTokenWorker ( + IN OUT UINTN *Token, + IN CONST GUID *Guid OPTIONAL + ); + +UINT8 * +LocatePcdImage ( + VOID +); + +VOID +BuildPcdDatabase ( + UINT8 *PcdImageOnFlash + ) +; + + +extern EFI_GUID gPcdImageFileGuid; + +// +// PPI Interface Implementation Declaration. +// +EFI_STATUS +EFIAPI +PeiPcdSetSku ( + IN UINTN SkuId + ) +; + + +UINT8 +EFIAPI +PeiPcdGet8 ( + IN UINTN TokenNumber + ) +; + + +UINT16 +EFIAPI +PeiPcdGet16 ( + IN UINTN TokenNumber + ) +; + + +UINT32 +EFIAPI +PeiPcdGet32 ( + IN UINTN TokenNumber + ) +; + + +UINT64 +EFIAPI +PeiPcdGet64 ( + IN UINTN TokenNumber + ) +; + + +VOID * +EFIAPI +PeiPcdGetPtr ( + IN UINTN TokenNumber + ) +; + + +BOOLEAN +EFIAPI +PeiPcdGetBool ( + IN UINTN TokenNumber + ) +; + + +UINTN +EFIAPI +PeiPcdGetSize ( + IN UINTN TokenNumber + ) +; + + +UINT8 +EFIAPI +PeiPcdGet8Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +UINT16 +EFIAPI +PeiPcdGet16Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + +UINT32 +EFIAPI +PeiPcdGet32Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +UINT64 +EFIAPI +PeiPcdGet64Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +VOID * +EFIAPI +PeiPcdGetPtrEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +BOOLEAN +EFIAPI +PeiPcdGetBoolEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +UINTN +EFIAPI +PeiPcdGetSizeEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +; + +EFI_STATUS +EFIAPI +PeiPcdSetPtr ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdSet8Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +; + +EFI_STATUS +EFIAPI +PeiPcdSet16Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdSet32Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdSet64Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdSetPtrEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdSetBoolEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +; + + + +EFI_STATUS +EFIAPI +PcdRegisterCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PPI_CALLBACK CallBackFunction + ) +; + + +EFI_STATUS +EFIAPI +PcdUnRegisterCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PPI_CALLBACK CallBackFunction + ) +; + + +EFI_STATUS +EFIAPI +PeiPcdGetNextToken ( + IN CONST EFI_GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ) +; +#endif diff --git a/EdkModulePkg/Universal/PCD/Test/PcdTest.c b/EdkModulePkg/Universal/PCD/Test/PcdTest.c new file mode 100644 index 0000000000..77e25ac2b6 --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Test/PcdTest.c @@ -0,0 +1,110 @@ +/** @file +PCD TEST PEIM + +Copyright (c) 2006, 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. + + +Module Name: PcdTest.c + +**/ +#define GUID1 \ + {0xF9349C58, 0xB767, 0x42c8, 0xB3, 0x6B, 0x41, 0x25, 0xDE, 0x3A, 0xEF, 0xEB} + +CONST GUID Guid1 = GUID1; + + +EFI_STATUS +EFIAPI +OnsetCallback1 ( + IN UINT32 CallBackToken, + IN VOID *TokenData, + IN UINTN TokenDataSize + ) +{ + DebugPrint (0x80000000, "In CallbackOnSet %x %d\n", * ((UINT32 *)TokenData), TokenDataSize); + return EFI_SUCCESS; +} + + +VOID +DoTest( + VOID + ) +{ + PCD_TOKEN_NUMBER tn; + UINTN Size; + VOID * Ptr; + UINT32 Uint32; + UINT32 Uint32a; + UINT64 Uint64; + UINT64 Uint64a; + INTN i; + + tn = 0x00001000; + + Size = LibPcdGetSize (tn); + Ptr = LibPcdGetPtr (tn); /* a:RW;2880;512!e:RW;262144;512 */ + + tn = 0x00001001; + Size = LibPcdGetSize (tn); /* FW;40960;512 */ + + tn = 0x00001002; + Size = LibPcdGetSize (tn); /* FW;40960;512 */ + Ptr = LibPcdGetPtr (tn); + + LibPcdSetSku (0x0a); + tn = 0x2233; + Uint64 = LibPcdGet64 (tn); + + LibPcdSetSku (0x0b); + Uint64 = LibPcdGet64 (tn); + + LibPcdSetSku (0x0c); + Uint64a = LibPcdGet64 (tn); + + LibPcdSetSku (0); + tn = 0x2233; + Uint64 = LibPcdGet64 (tn); + + + tn = 0xfaceface; + Size = LibPcdGetExSize (&Guid1, tn); + Uint32 = LibPcdGetEx32 (&Guid1, tn); + + LibPcdCallBackOnSet (&Guid1, tn, OnsetCallback1); + + LibPcdCancelCallBackOnSet (&Guid1, tn, OnsetCallback1); + + for (i = 0; i < 2; i++) { + Uint32a = LibPcdSetEx32 (&Guid1, tn, Uint32 + i); + DebugPrint (0x80000000, "%x\n", Uint32a); + } + + + + Uint32 = LibPcdGet32 (tn); + + + return; +} + +EFI_STATUS +EFIAPI +PcdTestPeimInit ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + + DoTest(); + + return EFI_SUCCESS; +} + diff --git a/EdkModulePkg/Universal/PCD/Test/PcdTest.dxs b/EdkModulePkg/Universal/PCD/Test/PcdTest.dxs new file mode 100644 index 0000000000..bf742966e1 --- /dev/null +++ b/EdkModulePkg/Universal/PCD/Test/PcdTest.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Variable.dxs + +Abstract: + + Dependency expression file for PcdTest PEIM. + +--*/ +#include +#include + +DEPENDENCY_START + PCD_PPI_GUID +DEPENDENCY_END + + diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Crc32.c b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Crc32.c new file mode 100644 index 0000000000..675a5503c3 --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Crc32.c @@ -0,0 +1,124 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Crc32.c + +Abstract: + + CalculateCrc32 Boot Services as defined in DXE CIS. + + This Boot Services is in the Runtime Driver because this service is + also required by SetVirtualAddressMap() when the EFI System Table and + EFI Runtime Services Table are converted from physical address to + virtual addresses. This requires that the 32-bit CRC be recomputed. + +Revision History: + +--*/ + +#include "Runtime.h" + +UINT32 mCrcTable[256]; + +EFI_STATUS +EFIAPI +RuntimeDriverCalculateCrc32 ( + IN VOID *Data, + IN UINTN DataSize, + OUT UINT32 *CrcOut + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + UINT32 Crc; + UINTN Index; + UINT8 *Ptr; + + if (Data == NULL || DataSize == 0 || CrcOut == NULL) { + return EFI_INVALID_PARAMETER; + } + + Crc = 0xffffffff; + for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) { + Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr]; + } + + *CrcOut = Crc ^ 0xffffffff; + return EFI_SUCCESS; +} + +UINT32 +ReverseBits ( + UINT32 Value + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + UINTN Index; + UINT32 NewValue; + + NewValue = 0; + for (Index = 0; Index < 32; Index++) { + if (Value & (1 << Index)) { + NewValue = NewValue | (1 << (31 - Index)); + } + } + + return NewValue; +} + +VOID +RuntimeDriverInitializeCrc32Table ( + VOID + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + UINTN TableEntry; + UINTN Index; + UINT32 Value; + + for (TableEntry = 0; TableEntry < 256; TableEntry++) { + Value = ReverseBits ((UINT32) TableEntry); + for (Index = 0; Index < 8; Index++) { + if (Value & 0x80000000) { + Value = (Value << 1) ^ 0x04c11db7; + } else { + Value = Value << 1; + } + } + + mCrcTable[TableEntry] = ReverseBits (Value); + } +} diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Ia32/PeHotRelocateEx.c b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Ia32/PeHotRelocateEx.c new file mode 100644 index 0000000000..82d464aebe --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Ia32/PeHotRelocateEx.c @@ -0,0 +1,88 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeHotRelocateEx.c + +Abstract: + + Stub to resolve the IPF hook that handles IPF specific relocation types + + +Revision History + +--*/ + +#include "Runtime.h" + +EFI_STATUS +PeHotRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an Itanium-based platform specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; + +} + +// +// Cache Flush Routine. +// +EFI_STATUS +FlushCpuCache ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Flush cache with specified range. + +Arguments: + + Start - Start address + Length - Length in bytes + +Returns: + + Status code + + EFI_SUCCESS - success + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Ipf/PeHotRelocateEx.c b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Ipf/PeHotRelocateEx.c new file mode 100644 index 0000000000..ffc0aaf4a4 --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Ipf/PeHotRelocateEx.c @@ -0,0 +1,242 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeHotRelocateEx.c + +Abstract: + + Fixes IPF specific relocation types + + +Revision History + +--*/ + +#include "Runtime.h" +#include "PeHotRelocateEx.h" + +EFI_STATUS +PeHotRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IPF specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + None + +--*/ +{ + UINT64 *F64; + UINT64 FixupVal; + + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_DIR64: + F64 = (UINT64 *) Fixup; + *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64)); + if (*(UINT64 *) (*FixupData) == *F64) { + *F64 = *F64 + (UINT64) Adjust; + } + + *FixupData = *FixupData + sizeof (UINT64); + break; + + case EFI_IMAGE_REL_BASED_IA64_IMM64: + F64 = (UINT64 *) Fixup; + *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64)); + if (*(UINT64 *) (*FixupData) == *F64) { + // + // Align it to bundle address before fixing up the + // 64-bit immediate value of the movl instruction. + // + // + Fixup = (CHAR8 *) ((UINT64) Fixup & (UINT64)~(15)); + FixupVal = (UINT64) 0; + + // + // Extract the lower 32 bits of IMM64 from bundle + // + EXT_IMM64 ( + FixupVal, + (UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X, + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + EXT_IMM64 ( + FixupVal, + (UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X, + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + EXT_IMM64 ( + FixupVal, + (UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X, + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + EXT_IMM64 ( + FixupVal, + (UINT32 *) Fixup + IMM64_IC_INST_WORD_X, + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + EXT_IMM64 ( + FixupVal, + (UINT32 *) Fixup + IMM64_IMM41a_INST_WORD_X, + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + // + // Update 64-bit address + // + FixupVal += Adjust; + + // + // Insert IMM64 into bundle + // + INS_IMM64 ( + FixupVal, + ((UINT32 *) Fixup + IMM64_IMM7B_INST_WORD_X), + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + INS_IMM64 ( + FixupVal, + ((UINT32 *) Fixup + IMM64_IMM9D_INST_WORD_X), + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + INS_IMM64 ( + FixupVal, + ((UINT32 *) Fixup + IMM64_IMM5C_INST_WORD_X), + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + INS_IMM64 ( + FixupVal, + ((UINT32 *) Fixup + IMM64_IC_INST_WORD_X), + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + INS_IMM64 ( + FixupVal, + ((UINT32 *) Fixup + IMM64_IMM41a_INST_WORD_X), + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + INS_IMM64 ( + FixupVal, + ((UINT32 *) Fixup + IMM64_IMM41b_INST_WORD_X), + IMM64_IMM41b_SIZE_X, + IMM64_IMM41b_INST_WORD_POS_X, + IMM64_IMM41b_VAL_POS_X + ); + + INS_IMM64 ( + FixupVal, + ((UINT32 *) Fixup + IMM64_IMM41c_INST_WORD_X), + IMM64_IMM41c_SIZE_X, + IMM64_IMM41c_INST_WORD_POS_X, + IMM64_IMM41c_VAL_POS_X + ); + + INS_IMM64 ( + FixupVal, + ((UINT32 *) Fixup + IMM64_SIGN_INST_WORD_X), + IMM64_SIGN_SIZE_X, + IMM64_SIGN_INST_WORD_POS_X, + IMM64_SIGN_VAL_POS_X + ); + + *(UINT64 *) (*FixupData) = *F64; + } + + *FixupData = *FixupData + sizeof (UINT64); + break; + + default: + DEBUG ((EFI_D_ERROR, "PeHotRelocateEx:unknown fixed type\n")); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + + +// +// Cache Flush Routine. +// +EFI_STATUS +FlushCpuCache ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Flush cache with specified range. + +Arguments: + + Start - Start address + Length - Length in bytes + +Returns: + + Status code + + EFI_SUCCESS - success + +--*/ +{ + SalFlushCache (Start, Length); + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Ipf/PeHotRelocateEx.h b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Ipf/PeHotRelocateEx.h new file mode 100644 index 0000000000..00c3c100cd --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Ipf/PeHotRelocateEx.h @@ -0,0 +1,76 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeHotRelocateEx.h + +Abstract: + + Fixes Intel Itanium(TM) specific relocation types + + +Revision History + +--*/ + +#ifndef _PEHOTRELOCATE_EX_H_ +#define _PEHOTRELOCATE_EX_H_ + +#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \ + Value |= (((UINT64) ((*(Address) >> InstPos) & (((UINT64) 1 << Size) - 1))) << ValPos) + +#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \ + * (UINT32 *) Address = \ + (*(UINT32 *) Address &~(((1 << Size) - 1) << InstPos)) | \ + ((UINT32) ((((UINT64) Value >> ValPos) & (((UINT64) 1 << Size) - 1))) << InstPos) + +#define IMM64_IMM7B_INST_WORD_X 3 +#define IMM64_IMM7B_SIZE_X 7 +#define IMM64_IMM7B_INST_WORD_POS_X 4 +#define IMM64_IMM7B_VAL_POS_X 0 + +#define IMM64_IMM9D_INST_WORD_X 3 +#define IMM64_IMM9D_SIZE_X 9 +#define IMM64_IMM9D_INST_WORD_POS_X 18 +#define IMM64_IMM9D_VAL_POS_X 7 + +#define IMM64_IMM5C_INST_WORD_X 3 +#define IMM64_IMM5C_SIZE_X 5 +#define IMM64_IMM5C_INST_WORD_POS_X 13 +#define IMM64_IMM5C_VAL_POS_X 16 + +#define IMM64_IC_INST_WORD_X 3 +#define IMM64_IC_SIZE_X 1 +#define IMM64_IC_INST_WORD_POS_X 12 +#define IMM64_IC_VAL_POS_X 21 + +#define IMM64_IMM41a_INST_WORD_X 1 +#define IMM64_IMM41a_SIZE_X 10 +#define IMM64_IMM41a_INST_WORD_POS_X 14 +#define IMM64_IMM41a_VAL_POS_X 22 + +#define IMM64_IMM41b_INST_WORD_X 1 +#define IMM64_IMM41b_SIZE_X 8 +#define IMM64_IMM41b_INST_WORD_POS_X 24 +#define IMM64_IMM41b_VAL_POS_X 32 + +#define IMM64_IMM41c_INST_WORD_X 2 +#define IMM64_IMM41c_SIZE_X 23 +#define IMM64_IMM41c_INST_WORD_POS_X 0 +#define IMM64_IMM41c_VAL_POS_X 40 + +#define IMM64_SIGN_INST_WORD_X 3 +#define IMM64_SIGN_SIZE_X 1 +#define IMM64_SIGN_INST_WORD_POS_X 27 +#define IMM64_SIGN_VAL_POS_X 63 + +#endif diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/PeHotRelocate.c b/EdkModulePkg/Universal/Runtime/RuntimeDxe/PeHotRelocate.c new file mode 100644 index 0000000000..4c2aeff78e --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/PeHotRelocate.c @@ -0,0 +1,216 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeHotRelocate.c + +Abstract: + + +--*/ + +#include "Runtime.h" + +STATIC +VOID * +RuntimePeImageAddress ( + IN RUNTIME_IMAGE_RELOCATION_DATA *Image, + IN UINTN Address + ) +/*++ + +Routine Description: + + Converts an image address to the loaded address + +Arguments: + + Image - The relocation data of the image being loaded + + Address - The address to be converted to the loaded address + +Returns: + + NULL if the address can not be converted, otherwise, the converted address + +--*/ +{ + if (Address >= (Image->ImageSize) << EFI_PAGE_SHIFT) { + return NULL; + } + + return (CHAR8 *) ((UINTN) Image->ImageBase + Address); +} + +VOID +RelocatePeImageForRuntime ( + RUNTIME_IMAGE_RELOCATION_DATA *Image + ) +{ + CHAR8 *OldBase; + CHAR8 *NewBase; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_NT_HEADERS *PeHdr; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY *DataDirectory; + EFI_IMAGE_DATA_DIRECTORY *RelocDir; + EFI_IMAGE_BASE_RELOCATION *RelocBase; + EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; + UINT16 *Reloc; + UINT16 *RelocEnd; + CHAR8 *Fixup; + CHAR8 *FixupBase; + UINT16 *F16; + UINT32 *F32; + CHAR8 *FixupData; + UINTN Adjust; + EFI_STATUS Status; + + OldBase = (CHAR8 *) ((UINTN) Image->ImageBase); + NewBase = (CHAR8 *) ((UINTN) Image->ImageBase); + + Status = RuntimeDriverConvertPointer (0, (VOID **) &NewBase); + ASSERT_EFI_ERROR (Status); + + Adjust = (UINTN) NewBase - (UINTN) OldBase; + + // + // Find the image's relocate dir info + // + DosHdr = (EFI_IMAGE_DOS_HEADER *) OldBase; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // Valid DOS header so get address of PE header + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) (((CHAR8 *) DosHdr) + DosHdr->e_lfanew); + } else { + // + // No Dos header so assume image starts with PE header. + // + PeHdr = (EFI_IMAGE_NT_HEADERS *) OldBase; + } + + if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) { + // + // Not a valid PE image so Exit + // + return ; + } + // + // Get some data from the PE type dependent data + // + NumberOfRvaAndSizes = PeHdr->OptionalHeader.NumberOfRvaAndSizes; + DataDirectory = &PeHdr->OptionalHeader.DataDirectory[0]; + + // + // Find the relocation block + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + RelocDir = DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC; + RelocBase = RuntimePeImageAddress (Image, RelocDir->VirtualAddress); + RelocBaseEnd = RuntimePeImageAddress (Image, RelocDir->VirtualAddress + RelocDir->Size); + } else { + // + // Cannot find relocations, cannot continue + // + ASSERT (FALSE); + return ; + } + + ASSERT (RelocBase != NULL && RelocBaseEnd != NULL); + + // + // Run the whole relocation block. And re-fixup data that has not been + // modified. The FixupData is used to see if the image has been modified + // since it was relocated. This is so data sections that have been updated + // by code will not be fixed up, since that would set them back to + // defaults. + // + FixupData = Image->RelocationData; + while (RelocBase < RelocBaseEnd) { + + Reloc = (UINT16 *) ((UINT8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); + RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock); + FixupBase = (CHAR8 *) ((UINTN) Image->ImageBase) + RelocBase->VirtualAddress; + + // + // Run this relocation record + // + while (Reloc < RelocEnd) { + + Fixup = FixupBase + (*Reloc & 0xFFF); + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + + case EFI_IMAGE_REL_BASED_HIGH: + F16 = (UINT16 *) Fixup; + if (*(UINT16 *) FixupData == *F16) { + *F16 = (UINT16) ((*F16 << 16) + ((UINT16) Adjust & 0xffff)); + } + + FixupData = FixupData + sizeof (UINT16); + break; + + case EFI_IMAGE_REL_BASED_LOW: + F16 = (UINT16 *) Fixup; + if (*(UINT16 *) FixupData == *F16) { + *F16 = (UINT16) (*F16 + ((UINT16) Adjust & 0xffff)); + } + + FixupData = FixupData + sizeof (UINT16); + break; + + case EFI_IMAGE_REL_BASED_HIGHLOW: + F32 = (UINT32 *) Fixup; + FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32)); + if (*(UINT32 *) FixupData == *F32) { + *F32 = *F32 + (UINT32) Adjust; + } + + FixupData = FixupData + sizeof (UINT32); + break; + + case EFI_IMAGE_REL_BASED_HIGHADJ: + // + // Not implemented, but not used in EFI 1.0 + // + ASSERT (FALSE); + break; + + default: + // + // Only Itanium requires ConvertPeImage_Ex + // + Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust); + if (EFI_ERROR (Status)) { + return ; + } + } + // + // Next relocation record + // + Reloc += 1; + } + // + // next reloc block + // + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; + } + + FlushCpuCache (Image->ImageBase, (UINT64) Image->ImageSize); +} diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.c b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.c new file mode 100644 index 0000000000..5a21d4961e --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.c @@ -0,0 +1,574 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Runtime.c + +Abstract: + + Runtime Architectural Protocol as defined in the DXE CIS + + This code is used to produce the EFI runtime virtual switch over + + THIS IS VERY DANGEROUS CODE BE VERY CAREFUL IF YOU CHANGE IT + + The transition for calling EFI Runtime functions in physical mode to calling + them in virtual mode is very very complex. Every pointer in needs to be + converted from physical mode to virtual mode. Be very careful walking linked + lists! Then to make it really hard the code it's self needs be relocated into + the new virtual address space. + + So here is the concept. The code in this module will never ever be called in + virtual mode. This is the code that collects the information needed to convert + to virtual mode (DXE core registers runtime stuff with this code). Since this + code is used to fixup all runtime images, it CAN NOT fix it's self up. So some + code has to stay behind and that is us. + + Also you need to be careful about when you allocate memory, as once we are in + runtime (including our EVT_SIGNAL_EXIT_BOOT_SERVICES event) you can no longer + allocate memory. + + Any runtime driver that gets loaded before us will not be callable in virtual + mode. This is due to the fact that the DXE core can not register the info + needed with us. This is good, since it keeps the code in this file from + getting registered. + + +Revision History: + + - Move the CalculateCrc32 function from Runtime Arch Protocol to Boot Service. + Runtime Arch Protocol definition no longer contains CalculateCrc32. Boot Service + Table now contains an item named CalculateCrc32. + +--*/ + + +#include "Runtime.h" + +// +// This is a only short term solution. +// There is a change coming to the Runtime AP that +// will make it so the Runtime driver will not have to allocate any buffers. +// +#define MAX_RUNTIME_IMAGE_NUM (64) +#define MAX_RUNTIME_EVENT_NUM (64) +RUNTIME_IMAGE_RELOCATION_DATA mRuntimeImageBuffer[MAX_RUNTIME_IMAGE_NUM]; +RUNTIME_NOTIFY_EVENT_DATA mRuntimeEventBuffer[MAX_RUNTIME_EVENT_NUM]; +UINTN mRuntimeImageNumber; +UINTN mRuntimeEventNumber; + +// +// The handle onto which the Runtime Architectural Protocol instance is installed +// +EFI_HANDLE mRuntimeHandle = NULL; + +// +// The Runtime Architectural Protocol instance produced by this driver +// +EFI_RUNTIME_ARCH_PROTOCOL mRuntime = { + RuntimeDriverRegisterImage, + RuntimeDriverRegisterEvent +}; + +// +// Global Variables +// +LIST_ENTRY mRelocationList = INITIALIZE_LIST_HEAD_VARIABLE(mRelocationList); +LIST_ENTRY mEventList = INITIALIZE_LIST_HEAD_VARIABLE(mEventList); +BOOLEAN mEfiVirtualMode = FALSE; +EFI_GUID mLocalEfiUgaIoProtocolGuid = EFI_UGA_IO_PROTOCOL_GUID; +EFI_MEMORY_DESCRIPTOR *mVirtualMap = NULL; +UINTN mVirtualMapDescriptorSize; +UINTN mVirtualMapMaxIndex; + +EFI_LOADED_IMAGE_PROTOCOL *mMyLoadedImage; + +// +// Worker Functions +// +VOID +RuntimeDriverCalculateEfiHdrCrc ( + IN OUT EFI_TABLE_HEADER *Hdr + ) +/*++ + +Routine Description: + + Calcualte the 32-bit CRC in a EFI table using the Runtime Drivers + internal function. The EFI Boot Services Table can not be used because + the EFI Boot Services Table was destroyed at ExitBootServices() + +Arguments: + + Hdr - Pointer to an EFI standard header + +Returns: + + None + +--*/ +{ + UINT32 Crc; + + Hdr->CRC32 = 0; + + Crc = 0; + RuntimeDriverCalculateCrc32 ((UINT8 *) Hdr, Hdr->HeaderSize, &Crc); + Hdr->CRC32 = Crc; +} + +EFI_STATUS +EFIAPI +RuntimeDriverRegisterImage ( + IN EFI_RUNTIME_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS ImageBase, + IN UINTN ImageSize, + IN VOID *RelocationData + ) +/*++ + +Routine Description: + + When a SetVirtualAddressMap() is performed all the runtime images loaded by + DXE must be fixed up with the new virtual address map. To facilitate this the + Runtime Architectural Protocol needs to be informed of every runtime driver + that is registered. All the runtime images loaded by DXE should be registered + with this service by the DXE Core when ExitBootServices() is called. The + images that are registered with this service must have successfully been + loaded into memory with the Boot Service LoadImage(). As a result, no + parameter checking needs to be performed. + +Arguments: + + This - The EFI_RUNTIME_ARCH_PROTOCOL instance. + + ImageBase - Start of image that has been loaded in memory. It is either + a pointer to the DOS or PE header of the image. + + ImageSize - Size of the image in bytes. + + RelocationData - Information about the fixups that were performed on ImageBase + when it was loaded into memory. This information is needed + when the virtual mode fix-ups are reapplied so that data that + has been programmatically updated will not be fixed up. If + code updates a global variable the code is responsible for + fixing up the variable for virtual mode. + +Returns: + + EFI_SUCCESS - The ImageBase has been registered. + +--*/ +{ + RUNTIME_IMAGE_RELOCATION_DATA *RuntimeImage; + + if (mMyLoadedImage->ImageBase == (VOID *) (UINTN) ImageBase) { + // + // We don't want to relocate our selves, as we only run in physical mode. + // + return EFI_SUCCESS; + } + + RuntimeImage = &mRuntimeImageBuffer[mRuntimeImageNumber]; + mRuntimeImageNumber++; + ASSERT (mRuntimeImageNumber < MAX_RUNTIME_IMAGE_NUM); + + RuntimeImage->Valid = TRUE; + RuntimeImage->ImageBase = ImageBase; + RuntimeImage->ImageSize = ImageSize; + RuntimeImage->RelocationData = RelocationData; + + InsertTailList (&mRelocationList, &RuntimeImage->Link); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +RuntimeDriverRegisterEvent ( + IN EFI_RUNTIME_ARCH_PROTOCOL *This, + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + IN EFI_EVENT *Event + ) +/*++ + +Routine Description: + + This function is used to support the required runtime events. Currently only + runtime events of type EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE needs to be + registered with this service. All the runtime events that exist in the DXE + Core should be registered with this service when ExitBootServices() is called. + All the events that are registered with this service must have been created + with the Boot Service CreateEvent(). As a result, no parameter checking needs + to be performed. + +Arguments: + + This - The EFI_RUNTIME_ARCH_PROTOCOL instance. + + Type - The same as Type passed into CreateEvent(). + + NotifyTpl - The same as NotifyTpl passed into CreateEvent(). + + NotifyFunction - The same as NotifyFunction passed into CreateEvent(). + + NotifyContext - The same as NotifyContext passed into CreateEvent(). + + Event - The EFI_EVENT returned by CreateEvent(). Event must be in + runtime memory. + +Returns: + + EFI_SUCCESS - The Event has been registered. + +--*/ +{ + RUNTIME_NOTIFY_EVENT_DATA *RuntimeEvent; + + RuntimeEvent = &mRuntimeEventBuffer[mRuntimeEventNumber]; + mRuntimeEventNumber++; + ASSERT (mRuntimeEventNumber < MAX_RUNTIME_EVENT_NUM); + + RuntimeEvent->Type = Type; + RuntimeEvent->NotifyTpl = NotifyTpl; + RuntimeEvent->NotifyFunction = NotifyFunction; + RuntimeEvent->NotifyContext = NotifyContext; + RuntimeEvent->Event = Event; + + InsertTailList (&mEventList, &RuntimeEvent->Link); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +RuntimeDriverConvertPointer ( + IN UINTN DebugDisposition, + IN OUT VOID **ConvertAddress + ) +{ + UINTN Address; + VOID *PlabelConvertAddress; + UINT64 VirtEndOfRange; + EFI_MEMORY_DESCRIPTOR *VirtEntry; + UINTN Index; + + // + // Make sure ConvertAddress is a valid pointer + // + if (ConvertAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Get the address to convert + // + Address = (UINTN) *ConvertAddress; + + // + // If this is a null pointer, return if it's allowed + // + if (Address == 0) { + if (DebugDisposition & EFI_OPTIONAL_POINTER) { + return EFI_SUCCESS; + } + + return EFI_INVALID_PARAMETER; + } + + PlabelConvertAddress = NULL; + VirtEntry = mVirtualMap; + for (Index = 0; Index < mVirtualMapMaxIndex; Index++) { + // + // To prevent the inclusion of 64-bit math functions a UINTN was placed in + // front of VirtEntry->NumberOfPages to cast it to a 32-bit thing on IA-32 + // platforms. If you get this ASSERT remove the UINTN and do a 64-bit + // multiply. + // + ASSERT ((VirtEntry->NumberOfPages < 0xffffffff) || (sizeof (UINTN) > 4)); + + if ((VirtEntry->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) { + if (Address >= VirtEntry->PhysicalStart) { + VirtEndOfRange = VirtEntry->PhysicalStart + (((UINTN) VirtEntry->NumberOfPages) * EFI_PAGE_SIZE); + if (Address < VirtEndOfRange) { + // + // Compute new address + // + *ConvertAddress = (VOID *) (Address - (UINTN) VirtEntry->PhysicalStart + (UINTN) VirtEntry->VirtualStart); + return EFI_SUCCESS; + } else if (Address < (VirtEndOfRange + 0x200000)) { + // + // On Itanium GP defines a window +/- 2 MB inside an image. + // The compiler may asign a GP value outside of the image. Thus + // it could fall out side of any of our valid regions + // + PlabelConvertAddress = (VOID *) (Address - (UINTN) VirtEntry->PhysicalStart + (UINTN) VirtEntry->VirtualStart); + } + } + } + + VirtEntry = NextMemoryDescriptor (VirtEntry, mVirtualMapDescriptorSize); + } + + if (DebugDisposition & EFI_IPF_GP_POINTER) { + // + // If it's an IPF GP and the GP was outside the image handle that case. + // + if (PlabelConvertAddress != NULL) { + *ConvertAddress = PlabelConvertAddress; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +RuntimeDriverConvertInternalPointer ( + IN OUT VOID **ConvertAddress + ) +{ + return RuntimeDriverConvertPointer (0x0, ConvertAddress); +} + +EFI_STATUS +EFIAPI +RuntimeDriverSetVirtualAddressMap ( + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize, + IN UINT32 DescriptorVersion, + IN EFI_MEMORY_DESCRIPTOR *VirtualMap + ) +{ + RUNTIME_NOTIFY_EVENT_DATA *RuntimeEvent; + RUNTIME_IMAGE_RELOCATION_DATA *RuntimeImage; + LIST_ENTRY *Link; + UINTN Index; + UINTN Index1; + EFI_DRIVER_OS_HANDOFF_HEADER *DriverOsHandoffHeader; + EFI_DRIVER_OS_HANDOFF *DriverOsHandoff; + + // + // Can only switch to virtual addresses once the memory map is locked down, + // and can only set it once + // + if (!EfiAtRuntime () || mEfiVirtualMode) { + return EFI_UNSUPPORTED; + } + // + // Only understand the original descriptor format + // + if (DescriptorVersion != EFI_MEMORY_DESCRIPTOR_VERSION || DescriptorSize < sizeof (EFI_MEMORY_DESCRIPTOR)) { + return EFI_INVALID_PARAMETER; + } + // + // BugBug: Add code here to verify the memory map. We should + // cache a copy of the system memory map in the EFI System Table + // as a GUID pointer pair. + // + // + // Make sure all virtual translations are satisfied + // + mVirtualMapMaxIndex = MemoryMapSize / DescriptorSize; + + // + // BugBug :The following code does not work hence commented out. + // Need to be replaced by something that works. + // + // VirtEntry = VirtualMap; + // for (Index = 0; Index < mVirtualMapMaxIndex; Index++) { + // if (((VirtEntry->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME) && + // (VirtEntry->VirtualStart != 0) ) { + // return EFI_NO_MAPPING; + // } + // VirtEntry = NextMemoryDescriptor(VirtEntry, DescriptorSize); + // } + // + // We are now committed to go to virtual mode, so lets get to it! + // + mEfiVirtualMode = TRUE; + + // + // ConvertPointer() needs this mVirtualMap to do the conversion. So set up + // globals we need to parse the virtual address map. + // + mVirtualMapDescriptorSize = DescriptorSize; + mVirtualMap = VirtualMap; + + // + // Signal all the EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE events. + // The core call RuntimeDriverRegisterEvent() for + // every runtime event and we stored them in the mEventList + // + // + // Currently the bug in StatusCode/RuntimeLib has been fixed, it will + // check whether in Runtime or not (this is judged by looking at + // mEfiAtRuntime global So this ReportStatusCode will work + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_EFI_BOOT_SERVICE | EFI_SW_RS_PC_SET_VIRTUAL_ADDRESS_MAP) + ); + + // + // BugBug - Commented out for now because the status code driver is not + // ready for runtime yet. The Status Code driver calls data hub with does + // a bunch of Boot Service things (locks, AllocatePool) and hangs somewhere + // on the way. + // + // ReportStatusCode ( + // EfiProgressCode, EfiMaxErrorSeverity, + // 0x03, 0x01, 12, // ReadyToBoot Progress code + // 0x00, 30, L"ConvertPointer" + // ); + // + for (Link = mEventList.ForwardLink; Link != &mEventList; Link = Link->ForwardLink) { + RuntimeEvent = _CR (Link, RUNTIME_NOTIFY_EVENT_DATA, Link); + if ((RuntimeEvent->Type & EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) == EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE) { + RuntimeEvent->NotifyFunction ( + RuntimeEvent->Event, + RuntimeEvent->NotifyContext + ); + } + } + // + // Relocate runtime images. Runtime images loaded before the runtime AP was + // started will not be relocated, since they would not have gotten registered. + // This includes the code in this file. + // + for (Link = mRelocationList.ForwardLink; Link != &mRelocationList; Link = Link->ForwardLink) { + RuntimeImage = _CR (Link, RUNTIME_IMAGE_RELOCATION_DATA, Link); + if (RuntimeImage->Valid) { + RelocatePeImageForRuntime (RuntimeImage); + } + } + // + // Convert all the Runtime Services except ConvertPointer() and SetVirtualAddressMap() + // and recompute the CRC-32 + // + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetTime); + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetTime); + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetWakeupTime); + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetWakeupTime); + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->ResetSystem); + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetNextHighMonotonicCount); + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetVariable); + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->SetVariable); + RuntimeDriverConvertInternalPointer ((VOID **) &gRT->GetNextVariableName); + RuntimeDriverCalculateEfiHdrCrc (&gRT->Hdr); + + // + // Convert the UGA OS Handoff Table if it is present in the Configuration Table + // + for (Index = 0; Index < gST->NumberOfTableEntries; Index++) { + if (CompareGuid (&mLocalEfiUgaIoProtocolGuid, &(gST->ConfigurationTable[Index].VendorGuid))) { + DriverOsHandoffHeader = gST->ConfigurationTable[Index].VendorTable; + for (Index1 = 0; Index1 < DriverOsHandoffHeader->NumberOfEntries; Index1++) { + DriverOsHandoff = (EFI_DRIVER_OS_HANDOFF *) + ( + (UINTN) DriverOsHandoffHeader + + DriverOsHandoffHeader->HeaderSize + + Index1 * + DriverOsHandoffHeader->SizeOfEntries + ); + RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &DriverOsHandoff->DevicePath); + RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &DriverOsHandoff->PciRomImage); + } + + RuntimeDriverConvertPointer (EFI_OPTIONAL_POINTER, (VOID **) &(gST->ConfigurationTable[Index].VendorTable)); + } + } + // + // Convert the runtime fields of the EFI System Table and recompute the CRC-32 + // + RuntimeDriverConvertInternalPointer ((VOID **) &gST->FirmwareVendor); + RuntimeDriverConvertInternalPointer ((VOID **) &gST->ConfigurationTable); + RuntimeDriverConvertInternalPointer ((VOID **) &gST->RuntimeServices); + RuntimeDriverCalculateEfiHdrCrc (&gST->Hdr); + + // + // At this point, gRT and gST are physical pointers, but the contents of these tables + // have been converted to runtime. + // + // + // mVirtualMap is only valid during SetVirtualAddressMap() call + // + mVirtualMap = NULL; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +RuntimeDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Install Runtime AP. This code includes the EfiDriverLib, but it functions at + RT in physical mode. The only Lib services are gBS, gRT, and the DEBUG and + ASSERT macros (they do ReportStatusCode). + +Arguments: + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + EFI_SUCEESS - Runtime Driver Architectural Protocol Installed + + Other - Return value from gBS->InstallMultipleProtocolInterfaces + +--*/ +{ + EFI_STATUS Status; + + // + // This image needs to be exclued from relocation for virtual mode, so cache + // a copy of the Loaded Image protocol to test later. + // + Status = gBS->HandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **) &mMyLoadedImage + ); + ASSERT_EFI_ERROR (Status); + + // + // Initialize the table used to compute 32-bit CRCs + // + RuntimeDriverInitializeCrc32Table (); + + // + // Fill in the entries of the EFI Boot Services and EFI Runtime Services Tables + // + gBS->CalculateCrc32 = RuntimeDriverCalculateCrc32; + gRT->SetVirtualAddressMap = RuntimeDriverSetVirtualAddressMap; + gRT->ConvertPointer = RuntimeDriverConvertPointer; + + // + // Install the Runtime Architectural Protocol onto a new handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mRuntimeHandle, + &gEfiRuntimeArchProtocolGuid, + &mRuntime, + NULL + ); + ASSERT_EFI_ERROR (Status); + + mRuntimeImageNumber = 0; + mRuntimeEventNumber = 0; + + return Status; +} diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.dxs b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.dxs new file mode 100644 index 0000000000..42ca881f4b --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.dxs @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Runtime.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.h b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.h new file mode 100644 index 0000000000..3803a9dadd --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.h @@ -0,0 +1,129 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Runtime.h + +Abstract: + + Runtime Architectural Protocol as defined in the DXE CIS + + This code is used to produce the EFI runtime virtual switch over + +--*/ + +#ifndef _RUNTIME_H_ +#define _RUNTIME_H_ + +// +// Data structures +// +typedef struct { + LIST_ENTRY Link; + BOOLEAN Valid; + EFI_PHYSICAL_ADDRESS ImageBase; + UINTN ImageSize; // In no. of pages + VOID *RelocationData; +} RUNTIME_IMAGE_RELOCATION_DATA; + +typedef struct { + LIST_ENTRY Link; + IN UINT32 Type; + IN EFI_TPL NotifyTpl; + IN EFI_EVENT_NOTIFY NotifyFunction; + IN VOID *NotifyContext; + IN EFI_EVENT Event; +} RUNTIME_NOTIFY_EVENT_DATA; + +// +// Function Prototypes +// +VOID +RelocatePeImageForRuntime ( + RUNTIME_IMAGE_RELOCATION_DATA *Image + ) +; + +EFI_STATUS +PeHotRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +; + +EFI_STATUS +EFIAPI +RuntimeDriverCalculateCrc32 ( + IN VOID *Data, + IN UINTN DataSize, + OUT UINT32 *CrcOut + ) +; + +EFI_STATUS +EFIAPI +RuntimeDriverRegisterImage ( + IN EFI_RUNTIME_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS ImageBase, + IN UINTN ImageSize, + IN VOID *RelocationData + ) +; + +EFI_STATUS +EFIAPI +RuntimeDriverRegisterEvent ( + IN EFI_RUNTIME_ARCH_PROTOCOL *This, + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + IN EFI_EVENT *Event + ) +; + +EFI_STATUS +EFIAPI +RuntimeDriverConvertPointer ( + IN UINTN DebugDisposition, + IN OUT VOID **ConvertAddress + ) +; + +VOID +RuntimeDriverInitializeCrc32Table ( + VOID + ) +; + +EFI_STATUS +EFIAPI +RuntimeDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + + +// +// Cache Flush Routine. +// +EFI_STATUS +FlushCpuCache ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.mbd b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.mbd new file mode 100644 index 0000000000..19ac5953f9 --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.mbd @@ -0,0 +1,46 @@ + + + + + Runtime + B601F8C4-43B7-4784-95B1-F4226CB40CEE + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + BaseLib + BaseMemoryLib + EdkDxeRuntimeDriverLib + UefiDriverEntryPoint + BaseDebugLibReportStatusCode + DxeReportStatusCodeLib + + EdkDxeSalLib + + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.msa b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.msa new file mode 100644 index 0000000000..8b918ab205 --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/Runtime.msa @@ -0,0 +1,80 @@ + + + + + Runtime + DXE_RUNTIME_DRIVER + RT_DRIVER + B601F8C4-43B7-4784-95B1-F4226CB40CEE + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + BaseLib + DxeRuntimeDriverLib + UefiDriverEntryPoint + DebugLib + ReportStatusCodeLib + BaseMemoryLib + EdkDxeSalLib + UefiRuntimeServicesTableLib + UefiBootServicesTableLib + + + Runtime.dxs + PeHotRelocate.c + Runtime.c + Runtime.h + Crc32.c + + Ia32\PeHotRelocateEx.c + + + x64\PeHotRelocateEx.c + x64\PeHotRelocateEx.h + + + Ipf\PeHotRelocateEx.c + Ipf\PeHotRelocateEx.h + + + + MdePkg + EdkModulePkg + + + LoadedImage + Runtime + + + + RuntimeDriverInitialize + + + + + + + diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/build.xml b/EdkModulePkg/Universal/Runtime/RuntimeDxe/build.xml new file mode 100644 index 0000000000..d11bd8deb4 --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Runtime/RuntimeDxe/x64/PeHotRelocateEx.c b/EdkModulePkg/Universal/Runtime/RuntimeDxe/x64/PeHotRelocateEx.c new file mode 100644 index 0000000000..82d464aebe --- /dev/null +++ b/EdkModulePkg/Universal/Runtime/RuntimeDxe/x64/PeHotRelocateEx.c @@ -0,0 +1,88 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeHotRelocateEx.c + +Abstract: + + Stub to resolve the IPF hook that handles IPF specific relocation types + + +Revision History + +--*/ + +#include "Runtime.h" + +EFI_STATUS +PeHotRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an Itanium-based platform specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; + +} + +// +// Cache Flush Routine. +// +EFI_STATUS +FlushCpuCache ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Flush cache with specified range. + +Arguments: + + Start - Start address + Length - Length in bytes + +Returns: + + Status code + + EFI_SUCCESS - success + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.c b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.c new file mode 100644 index 0000000000..4b4581d4d8 --- /dev/null +++ b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.c @@ -0,0 +1,156 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + SecurityStub.c + +Abstract: + + This driver supports platform security service + +--*/ + +#include "SecurityStub.h" + +// +// Handle for the Security Architectural Protocol instance produced by this driver +// +EFI_HANDLE mSecurityArchProtocolHandle = NULL; + +// +// Security Architectural Protocol instance produced by this driver +// +EFI_SECURITY_ARCH_PROTOCOL mSecurityStub = { + SecurityStubAuthenticateState +}; + +// +// Worker functions +// +EFI_STATUS +EFIAPI +SecurityStubAuthenticateState ( + IN EFI_SECURITY_ARCH_PROTOCOL *This, + IN UINT32 AuthenticationStatus, + IN EFI_DEVICE_PATH_PROTOCOL *File + ) +/*++ + +Routine Description: + + The EFI_SECURITY_ARCH_PROTOCOL (SAP) is used to abstract platform-specific + policy from the DXE core response to an attempt to use a file that returns a + given status for the authentication check from the section extraction protocol. + + The possible responses in a given SAP implementation may include locking + flash upon failure to authenticate, attestation logging for all signed drivers, + and other exception operations. The File parameter allows for possible logging + within the SAP of the driver. + + If File is NULL, then EFI_INVALID_PARAMETER is returned. + + If the file specified by File with an authentication status specified by + AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned. + + If the file specified by File with an authentication status specified by + AuthenticationStatus is not safe for the DXE Core to use under any circumstances, + then EFI_ACCESS_DENIED is returned. + + If the file specified by File with an authentication status specified by + AuthenticationStatus is not safe for the DXE Core to use right now, but it + might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is + returned. + +Arguments: + + This - The EFI_SECURITY_ARCH_PROTOCOL instance. + + AuthenticationStatus - This is the authentication type returned from the Section + Extraction protocol. See the Section Extraction Protocol + Specification for details on this type. + + File - This is a pointer to the device path of the file that is + being dispatched. This will optionally be used for logging. + +Returns: + + EFI_SUCCESS - The file specified by File did authenticate, and the + platform policy dictates that the DXE Core may use File. + + EFI_INVALID_PARAMETER - File is NULL. + + EFI_SECURITY_VIOLATION - The file specified by File did not authenticate, and + the platform policy dictates that File should be placed + in the untrusted state. A file may be promoted from + the untrusted to the trusted state at a future time + with a call to the Trust() DXE Service. + + EFI_ACCESS_DENIED - The file specified by File did not authenticate, and + the platform policy dictates that File should not be + used for any purpose. + +--*/ +{ + if (File == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SecurityStubInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initialize the state information for the Security Architectural Protocol + +Arguments: + + ImageHandle of the loaded driver + Pointer to the System Table + +Returns: + + Status + + EFI_SUCCESS - successful installation of the service + EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure + EFI_DEVICE_ERROR - cannot create the timer service + +--*/ +{ + EFI_STATUS Status; + + // + // Make sure the Security Architectural Protocol is not already installed in the system + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiSecurityArchProtocolGuid); + + // + // Install the Security Architectural Protocol onto a new handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mSecurityArchProtocolHandle, + &gEfiSecurityArchProtocolGuid, + &mSecurityStub, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.dxs b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.dxs new file mode 100644 index 0000000000..bc3b419c92 --- /dev/null +++ b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + SecurityStub.dxs + +Abstract: + + Dependency expression source file. + +--*/ + +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.h b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.h new file mode 100644 index 0000000000..420afd1e05 --- /dev/null +++ b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.h @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + SecurityStub.h + +Abstract: + + Some definitions for Security Architectural Protocol stub driver + +--*/ + +#ifndef _SECURITY_STUB_ARCH_PROTOCOL_H +#define _SECURITY_STUB_ARCH_PROTOCOL_H + + + +// +// Function prototypes +// +EFI_STATUS +EFIAPI +SecurityStubAuthenticateState ( + IN EFI_SECURITY_ARCH_PROTOCOL *This, + IN UINT32 AuthenticationStatus, + IN EFI_DEVICE_PATH_PROTOCOL *File + ) +; + +EFI_STATUS +EFIAPI +SecurityStubInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.mbd b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.mbd new file mode 100644 index 0000000000..2dc6fe738d --- /dev/null +++ b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.mbd @@ -0,0 +1,40 @@ + + + + + SecurityStub + F80697E9-7FD6-4665-8646-88E33EF71DFC + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-22 19:19 + + + UefiBootServicesTableLib + BaseLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + + diff --git a/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.msa b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.msa new file mode 100644 index 0000000000..224fcec5a3 --- /dev/null +++ b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/SecurityStub.msa @@ -0,0 +1,55 @@ + + + + + SecurityStub + DXE_DRIVER + BS_DRIVER + F80697E9-7FD6-4665-8646-88E33EF71DFC + EDK_RELEASE_VERSION 0x00020000 + Component description file for SecurityStub module + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-12 17:09 + 2006-03-22 19:19 + + + DebugLib + UefiBootServicesTableLib + UefiDriverEntryPoint + + + SecurityStub.dxs + SecurityStub.h + SecurityStub.c + + + MdePkg + + + Security + + + + SecurityStubInitialize + + + diff --git a/EdkModulePkg/Universal/Security/SecurityStub/Dxe/build.xml b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/build.xml new file mode 100644 index 0000000000..991db08208 --- /dev/null +++ b/EdkModulePkg/Universal/Security/SecurityStub/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/DebugAssert.c b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/DebugAssert.c new file mode 100644 index 0000000000..75f0ed144d --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/DebugAssert.c @@ -0,0 +1,231 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DebugAssert.c + +Abstract: + + Produce EfiDebugAssertProtocol to enable EfiUtilityLib to function. + The EfiUtilityLib is used by the EFI shell! + +--*/ + +#include "StatusCode.h" + +EFI_STATUS +EFIAPI +StatusCodeDebugAssert ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ); + +EFI_STATUS +EFIAPI +StatusCodeDebugPrint ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN UINTN ErrorLevel, + IN CHAR8 *Format, + IN VA_LIST Marker + ); + +EFI_STATUS +EFIAPI +StatusCodePostCode ( + IN EFI_DEBUG_ASSERT_PROTOCOL * This, + IN UINT16 PostCode, + IN CHAR8 *PostCodeString OPTIONAL + ); + +EFI_STATUS +EFIAPI +StatusCodeGetErrorLevel ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN UINTN *ErrorLevel + ); + +EFI_STATUS +EFIAPI +StatusCodeSetErrorLevel ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN UINTN ErrorLevel + ); + +// +// Protocol instance, there can be only one. +// +EFI_HANDLE mHandle = NULL; +EFI_DEBUG_ASSERT_PROTOCOL mDebugAssertProtocol = { + StatusCodeDebugAssert, + StatusCodeDebugPrint, + StatusCodePostCode, + StatusCodeGetErrorLevel, + StatusCodeSetErrorLevel +}; + +// +// Function implementations +// +EFI_STATUS +EFIAPI +StatusCodeDebugAssert ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) +/*++ + +Routine Description: + + Worker function for ASSERT (). If Error Logging hub is loaded log ASSERT + information. If Error Logging hub is not loaded CpuBreakpoint (). + +Arguments: + + This - Protocol instance. + FileName - File name of failing routine. + LineNumber - Line number of failing ASSERT(). + Description - Description, usually the assertion, + +Returns: + + EFI_SUCCESS The function always completes successfully. + +--*/ +{ + DebugAssert (FileName, LineNumber, Description); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +StatusCodeDebugPrint ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN UINTN ErrorLevel, + IN CHAR8 *Format, + IN VA_LIST Marker + ) +/*++ + +Routine Description: + + Worker function for DEBUG (). If Error Logging hub is loaded log ASSERT + information. If Error Logging hub is not loaded do nothing. + +Arguments: + + This - Protocol Instance. + ErrorLevel - If error level is set do the debug print. + Format - String to use for the print, followed by Print arguments. + +Returns: + + EFI_SUCCESS The function always completes successfully. + +--*/ +{ + CHAR8 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE]; + + AsciiVSPrint (Buffer, EFI_STATUS_CODE_DATA_MAX_SIZE, Format, Marker); + DebugPrint (ErrorLevel, Buffer); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +StatusCodeGetErrorLevel ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN UINTN *ErrorLevel + ) +{ + *ErrorLevel = PcdGet32(PcdDebugPrintErrorLevel); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +StatusCodeSetErrorLevel ( + IN EFI_DEBUG_ASSERT_PROTOCOL *This, + IN UINTN ErrorLevel + ) +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +StatusCodePostCode ( + IN EFI_DEBUG_ASSERT_PROTOCOL * This, + IN UINT16 PostCode, + IN CHAR8 *PostCodeString OPTIONAL + ) +/*++ + +Routine Description: + + Write the code to IO ports 80 and 81. + +Arguments: + + This - Protocol Instance. + PostCode - Code to write + PostCodeString - String, currently ignored. + +Returns: + + EFI_SUCCESS The function always completes successfully. + +--*/ +{ + IoWrite8 (0x80, (UINT8) (PostCode & 0xff)); + IoWrite8 (0x81, (UINT8) (PostCode >> 8)); + + return EFI_SUCCESS; +} + +EFI_STATUS +InstallStatusCodeDebugAssert ( + VOID + ) +/*++ + +Routine Description: + + Install the status code debug assert protocol + +Arguments: + + None + +Returns: + + Results of call to InstallProtocolInterface. + +--*/ +{ + + DEBUG_CODE ( + gBS->InstallProtocolInterface ( + &mHandle, + &gEfiDebugAssertProtocolGuid, + EFI_NATIVE_INTERFACE, + &mDebugAssertProtocol + ); + ); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ia32/Ia32StatusCode.c b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ia32/Ia32StatusCode.c new file mode 100644 index 0000000000..d2e1009b7f --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ia32/Ia32StatusCode.c @@ -0,0 +1,75 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Ia32StatusCode.c + +Abstract: + + Installs the ReportStatusCode runtime service. + +--*/ + +#include "StatusCode.h" + +// +// +// +EFI_HANDLE gStatusCodeHandle = NULL; + +const EFI_STATUS_CODE_PROTOCOL gStatusCodeInstance = { + StatusCodeReportStatusCode +}; + +// +// Define the driver entry point +// +EFI_STATUS +EFIAPI +InstallStatusCode ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Install the ReportStatusCode runtime service. + +Arguments: + + ImageHandle Image handle of the loaded driver + SystemTable Pointer to the System Table + +Returns: + + EFI_SUCCESS The function always returns success. + +--*/ +{ + EFI_STATUS Status; + + // + // Initialize RT status code + // + InitializeStatusCode (ImageHandle, SystemTable); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &gStatusCodeHandle, + &gEfiStatusCodeRuntimeProtocolGuid, + &gStatusCodeInstance, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ia32/Ia32StatusCode.dxs b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ia32/Ia32StatusCode.dxs new file mode 100644 index 0000000000..6371258e9a --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ia32/Ia32StatusCode.dxs @@ -0,0 +1,26 @@ +#/*++ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# Ia32StatusCode.dxs +# +# Abstract: +# +# Dependency expression source file. +# +#--*/ +#include +#include + +DEPENDENCY_START + EFI_DATA_HUB_PROTOCOL_GUID AND EFI_CPU_IO_PROTOCOL_GUID +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ipf/IpfStatusCode.c b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ipf/IpfStatusCode.c new file mode 100644 index 0000000000..62564c0cd8 --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ipf/IpfStatusCode.c @@ -0,0 +1,126 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + IpfStatusCode.c + +Abstract: + + Contains the IPF installation function and an ESAL entry. + +--*/ + +#include "StatusCode.h" + +SAL_RETURN_REGS +ReportStatusCodeEsalServicesClassCommonEntry ( + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + IN SAL_EXTENDED_SAL_PROC ExtendedSalProc, + IN BOOLEAN VirtualMode, + IN VOID *Global + ) +/*++ + +Routine Description: + + Main entry for Extended SAL ReportStatusCode Services + +Arguments: + + FunctionId Function Id which needed to be called + Arg2 Efi status code type + Arg3 Efi status code value + Arg4 Instance number + Arg5 Caller Id + Arg6 Efi status code data + Arg7 Not used + Arg8 Not used + ExtendedSalProc Esal Proc pointer + VirtualMode If this function is called in virtual mode + Global This module's global variable pointer + +Returns: + + SAL_RETURN_REGS + +--*/ +{ + SAL_RETURN_REGS ReturnVal; + + switch (FunctionId) { + + case ReportStatusCodeService: + ReturnVal.Status = StatusCodeReportStatusCode ( + (EFI_STATUS_CODE_TYPE) Arg2, + (EFI_STATUS_CODE_VALUE) Arg3, + (UINT32) Arg4, + (EFI_GUID *) Arg5, + (EFI_STATUS_CODE_DATA *) Arg6 + ); + break; + + default: + ReturnVal.Status = EFI_SAL_INVALID_ARGUMENT; + break; + } + + return ReturnVal; +} + +EFI_STATUS +EFIAPI +InstallStatusCode ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Install the ReportStatusCode runtime service. + +Arguments: + + ImageHandle Image handle of the loaded driver + SystemTable Pointer to the System Table + +Returns: + + EFI_SUCCESS The function always returns success. + +--*/ +{ + // + // Initialize RT status code + // + InitializeStatusCode (ImageHandle, SystemTable); + + // + // Initialize ESAL capabilities + // + RegisterEsalClass ( + &gEfiExtendedSalStatusCodeServicesProtocolGuid, + NULL, + ReportStatusCodeEsalServicesClassCommonEntry, + StatusCode, + NULL + ); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ipf/IpfStatusCode.dxs b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ipf/IpfStatusCode.dxs new file mode 100644 index 0000000000..aaa3efe3e1 --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/Ipf/IpfStatusCode.dxs @@ -0,0 +1,27 @@ +#/*++ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# IpfStatusCode.dxs +# +# Abstract: +# +# Dependency expression source file. +# +#--*/ + +#include +#include + +DEPENDENCY_START + EFI_DATA_HUB_PROTOCOL_GUID AND EFI_EXTENDED_SAL_BASE_IO_SERVICES_PROTOCOL_GUID +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.c b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.c new file mode 100644 index 0000000000..13b6426beb --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.c @@ -0,0 +1,172 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + StatusCode.c + +Abstract: + + Status Code Architectural Protocol implementation as defined in Tiano + Architecture Specification. + + This driver also depends on the DataHub, and will log all status code info + to the DataHub. Fatal Errors are Printed to Standard Error (StdErr) and not + logged to the data hub (If you crash what good is the data in the data hub). + + This driver has limited functionality at runtime and will not log to Data Hub + at runtime. + + Notes: + This driver assumes the following ReportStatusCode strategy: + PEI -> uses PeiReportStatusCode + DXE IPL -> uses PeiReportStatusCode + early DXE -> uses PeiReportStatusCode via HOB + DXE -> This driver + RT -> This driver + +--*/ + +#include "StatusCode.h" + +EFI_LOCK mStatusCodeLock; +BOOLEAN mStatusCodeFlag = FALSE; + +// +// Function implemenations +// + + +EFI_STATUS +EFIAPI +StatusCodeReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +/*++ + +Routine Description: + + Calls into the platform library which dispatches the platform specific + listeners. For NT environments we still call back into PEI because the + ReportStatusCode functionality requires Win32 services and is built into + the SecMain.exe utility. + +Arguments: + + (See Tiano Runtime Specification) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + + // + // Acquire the lock required to update mStatusCodeFlag + // + Status = EfiAcquireLockOrFail (&mStatusCodeLock); + if (EFI_ERROR (Status)) { + // + // Check for reentrancy of the lock + // + return EFI_DEVICE_ERROR; + } + // + // Check to see if we are already in the middle of a ReportStatusCode() + // + if (mStatusCodeFlag) { + EfiReleaseLock (&mStatusCodeLock); + return EFI_DEVICE_ERROR; + } + // + // Set the flag to show we are in the middle of a ReportStatusCode() + // + mStatusCodeFlag = TRUE; + + // + // Release the lock for updating mStatusCodeFlag + // + EfiReleaseLock (&mStatusCodeLock); + + // + // Go do the work required to report a status code + // + RtPlatformReportStatusCode (CodeType, Value, Instance, CallerId, Data); + + // + // Acquire the lock required to update mStatusCodeFlag + // + Status = EfiAcquireLockOrFail (&mStatusCodeLock); + if (EFI_ERROR (Status)) { + // + // Check for reentrancy of the lock + // + return EFI_DEVICE_ERROR; + } + // + // Clear the flag to show we are no longer in the middle of a ReportStatusCode() + // + mStatusCodeFlag = FALSE; + + // + // Release the lock for updating mStatusCodeFlag + // + EfiReleaseLock (&mStatusCodeLock); + + return EFI_SUCCESS; +} +// +// Protocol instance, there can be only one. +// +EFI_STATUS +InitializeStatusCode ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Install Driver to produce Report Status Code Arch Protocol + +Arguments: + + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + EFI_SUCCESS - Logging Hub protocol installed + Other - No protocol installed, unload driver. + +--*/ +{ + + EfiInitializeLock (&mStatusCodeLock, EFI_TPL_HIGH_LEVEL); + + // + // Call the platform hook to initialize the different listeners. + // + RtPlatformStatusCodeInitialize (); + + // + // Register a protocol that EfiUtilityLib can use to implement DEBUG () and ASSERT () + // Macros. + // + InstallStatusCodeDebugAssert (); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.h b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.h new file mode 100644 index 0000000000..cb4a4d9def --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.h @@ -0,0 +1,64 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + StatusCode.h + +Abstract: + + EFI DXE/RT Status Code include file. + +--*/ + +#ifndef _EFI_RUNTIME_STATUS_CODE_H_ +#define _EFI_RUNTIME_STATUS_CODE_H_ + +// +// Function prototypes +// + +EFI_STATUS +EFIAPI +StatusCodeReportStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +; + +EFI_STATUS +InitializeStatusCode ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +EFI_STATUS +InstallStatusCodeDebugAssert ( + VOID + ) +; + +// +// Driver entry point +// +EFI_STATUS +EFIAPI +InstallStatusCode ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +#endif diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.mbd b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.mbd new file mode 100644 index 0000000000..923914aee9 --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.mbd @@ -0,0 +1,55 @@ + + + + + StatusCode + 9F455D3B-2B8A-4c06-960B-A71B9714B9CD + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseLib + EdkDxeRuntimeDriverLib + UefiDriverEntryPoint + UefiLib + BasePrintLib + BaseDebugLibReportStatusCode + EdkRtPlatformStatusCodeLib + DxeIoLibCpuIo + BaseMemoryLib + DxeReportStatusCodeLib + EdkRtMemoryStatusCodeLib + EdkBsDataHubStatusCodeLib + DxeHobLib + DxeMemoryAllocationLib + EdkMemoryStatusCodeLib + + + EdkDxeSalLib + + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.msa b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.msa new file mode 100644 index 0000000000..b0d888b963 --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/StatusCode.msa @@ -0,0 +1,77 @@ + + + + + StatusCode + DXE_RUNTIME_DRIVER + RT_DRIVER + 9F455D3B-2B8A-4c06-960B-A71B9714B9CD + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + BaseLib + DxeRuntimeDriverLib + UefiDriverEntryPoint + UefiLib + DebugLib + PrintLib + IoLib + EdkRtPlatformStatusCodeLib + EdkDxeSalLib + UefiBootServicesTableLib + PcdLib + + + DebugAssert.c + StatusCode.c + StatusCode.h + + Ia32\Ia32StatusCode.c + Ia32\Ia32StatusCode.dxs + + + x64\x64StatusCode.c + x64\x64StatusCode.dxs + + + Ipf\IpfStatusCode.c + Ipf\IpfStatusCode.dxs + + + + MdePkg + EdkModulePkg + + + DebugAssert + ExtendedSalStatusCodeServices + + + + InstallStatusCode + + + diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/build.xml b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/build.xml new file mode 100644 index 0000000000..994d073598 --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/x64/x64StatusCode.c b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/x64/x64StatusCode.c new file mode 100644 index 0000000000..4c8ad0c81a --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/x64/x64StatusCode.c @@ -0,0 +1,75 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + x64StatusCode.c + +Abstract: + + Installs the ReportStatusCode runtime service. + +--*/ + +#include "StatusCode.h" + +// +// +// +EFI_HANDLE gStatusCodeHandle = NULL; + +const EFI_STATUS_CODE_PROTOCOL gStatusCodeInstance = { + StatusCodeReportStatusCode +}; + +// +// Define the driver entry point +// +EFI_STATUS +EFIAPI +InstallStatusCode ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Install the ReportStatusCode runtime service. + +Arguments: + + ImageHandle Image handle of the loaded driver + SystemTable Pointer to the System Table + +Returns: + + EFI_SUCCESS The function always returns success. + +--*/ +{ + EFI_STATUS Status; + + // + // Initialize RT status code + // + InitializeStatusCode (ImageHandle, SystemTable); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &gStatusCodeHandle, + &gEfiStatusCodeRuntimeProtocolGuid, + &gStatusCodeInstance, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/EdkModulePkg/Universal/StatusCode/RuntimeDxe/x64/x64StatusCode.dxs b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/x64/x64StatusCode.dxs new file mode 100644 index 0000000000..74cf23eee3 --- /dev/null +++ b/EdkModulePkg/Universal/StatusCode/RuntimeDxe/x64/x64StatusCode.dxs @@ -0,0 +1,27 @@ +#/*++ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# x64StatusCode.dxs +# +# Abstract: +# +# Dependency expression source file. +# +#--*/ + +#include +#include + +DEPENDENCY_START + EFI_DATA_HUB_PROTOCOL_GUID AND EFI_CPU_IO_PROTOCOL_GUID +DEPENDENCY_END diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Fonts.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Fonts.c new file mode 100644 index 0000000000..52dc12e877 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Fonts.c @@ -0,0 +1,263 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Fonts.c + +Abstract: + + This file contains the Glyph/Font processing code to the HII database. + +--*/ + + +#include "HiiDatabase.h" + +// +// We only need to define a wide glyph, since we will seed the narrow glyph with EFI_NARROW_GLYPH size of +// this data structure +// +UINT8 mUnknownGlyph[38] = { + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xAA, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xaa, + 0x55, + 0xAA +}; + +EFI_STATUS +EFIAPI +HiiGetGlyph ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Source, + IN OUT UINT16 *Index, + OUT UINT8 **GlyphBuffer, + OUT UINT16 *BitWidth, + IN OUT UINT32 *InternalStatus + ) +/*++ + +Routine Description: + Translates a Unicode character into the corresponding font glyph. + If the Source was pointing to a non-spacing character, the next Source[*Index] + character will be parsed and OR'd to the GlyphBuffer until a spacing character + is found in the Source. Since non-spacing characters are considered to be the + same pixel width as a regular character their BitWidth will be reflected correctly + however due to their special attribute, they are considered to be zero advancing width. + This basically means that the cursor would not advance, thus the character that follows + it would overlay the non-spacing character. The Index is modified to reflect both the + incoming array entry into the Source string but also the outgoing array entry after having + parsed the equivalent of a single Glyph's worth of data. + +Arguments: + +Returns: + +--*/ +{ + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HII_DATA *HiiData; + UINTN Count; + BOOLEAN Narrow; + UINTN Location; + UINTN SearchLocation; + UINTN Value; + CHAR16 Character; + UINTN Attributes; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + GlobalData = HiiData->GlobalData; + Count = sizeof (GlobalData->NarrowGlyphs->GlyphCol1); + + Location = *Index; + SearchLocation = *Index; + Narrow = TRUE; + + if (Source[Location] == NARROW_CHAR || Source[Location] == WIDE_CHAR) { + *InternalStatus = 0; + } + // + // We don't know what glyph database to look in - let's figure it out + // + if (*InternalStatus == 0) { + // + // Determine if we are looking for narrow or wide glyph data + // + do { + if (Source[SearchLocation] == NARROW_CHAR || Source[SearchLocation] == WIDE_CHAR) { + // + // We found something that identifies what glyph database to look in + // + if (Source[SearchLocation] == WIDE_CHAR) { + Narrow = FALSE; + *BitWidth = WIDE_WIDTH; + *InternalStatus = WIDE_CHAR; + Location++; + break; + } else { + Narrow = TRUE; + *BitWidth = NARROW_WIDTH; + *InternalStatus = NARROW_CHAR; + Location++; + break; + } + } + } while (SearchLocation-- > 0); + } + + if (*InternalStatus == NARROW_CHAR) { + Narrow = TRUE; + *BitWidth = NARROW_WIDTH; + } else if (*InternalStatus == WIDE_CHAR) { + Narrow = FALSE; + *BitWidth = WIDE_WIDTH; + } else { + // + // Without otherwise knowing what the width is narrow (e.g. someone passed in a string with index of 0 + // we wouldn't be able to determine the width of the data.) + // BUGBUG - do we go to wide database and if exist, ignore narrow? Check Unicode spec.... + // + Narrow = TRUE; + *BitWidth = NARROW_WIDTH; + } + + Character = Source[Location]; + + if (Narrow) { + if (GlobalData->NarrowGlyphs[Character].UnicodeWeight != 0x0000) { + *GlyphBuffer = (UINT8 *) (&GlobalData->NarrowGlyphs[Character]); + Attributes = GlobalData->NarrowGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING; + } else { + // + // Glyph is uninitialized - return an error, but hand back the glyph + // + *GlyphBuffer = (UINT8 *) (&GlobalData->NarrowGlyphs[Character]); + *Index = (UINT16) (Location + 1); + return EFI_NOT_FOUND; + } + } else { + // + // Wide character + // + if (GlobalData->WideGlyphs[Character].UnicodeWeight != 0x0000) { + *GlyphBuffer = (UINT8 *) (&GlobalData->WideGlyphs[Character]); + Attributes = GlobalData->WideGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING; + } else { + // + // Glyph is uninitialized - return an error, but hand back the glyph + // + *GlyphBuffer = (UINT8 *) (&GlobalData->WideGlyphs[Character]); + *Index = (UINT16) (Location + 1); + return EFI_NOT_FOUND; + } + } + // + // This is a non-spacing character. It will be followed by either more non-spacing + // characters or a regular character. We need to OR together the data associated with each. + // + for (; Attributes != 0; Location++) { + // + // Character is the Unicode value which is the index into the Glyph array. + // + Character = Source[Location]; + + if (Narrow) { + for (Value = 0; Value != Count; Value++) { + *GlyphBuffer[Location + Value] |= GlobalData->NarrowGlyphs[Character].GlyphCol1[Value]; + } + + Attributes = GlobalData->NarrowGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING; + } else { + for (Value = 0; Value != Count; Value++) { + *GlyphBuffer[Location + Value] |= GlobalData->WideGlyphs[Character].GlyphCol1[Value]; + *GlyphBuffer[Location + Value + Count] |= GlobalData->WideGlyphs[Character].GlyphCol2[Value]; + } + + Attributes = GlobalData->WideGlyphs[Character].Attributes & EFI_GLYPH_NON_SPACING; + } + } + // + // Source[*Index] should point to the next character to process + // + *Index = (UINT16) (Location + 1); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiGlyphToBlt ( + IN EFI_HII_PROTOCOL *This, + IN UINT8 *GlyphBuffer, + IN EFI_UGA_PIXEL Foreground, + IN EFI_UGA_PIXEL Background, + IN UINTN Count, + IN UINTN Width, + IN UINTN Height, + IN OUT EFI_UGA_PIXEL *BltBuffer + ) +{ + UINTN X; + UINTN Y; + + // + // Convert Monochrome bitmap of the Glyph to BltBuffer structure + // + for (Y = 0; Y < Height; Y++) { + for (X = 0; X < Width; X++) { + if ((((EFI_NARROW_GLYPH *) GlyphBuffer)->GlyphCol1[Y] & (1 << X)) != 0) { + BltBuffer[Y * Width * Count + (Width - X - 1)] = Foreground; + } else { + BltBuffer[Y * Width * Count + (Width - X - 1)] = Background; + } + } + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Forms.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Forms.c new file mode 100644 index 0000000000..a0a9619197 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Forms.c @@ -0,0 +1,1564 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Forms.c + +Abstract: + + This file contains the form processing code to the HII database. + +--*/ + + +#include "HiiDatabase.h" + +CHAR16* +Ascii2Unicode ( + OUT CHAR16 *UnicodeStr, + IN CHAR8 *AsciiStr + ) +/*++ + + Routine Description: + + This function converts ASCII string to Unicode string. + + Arguments: + + UnicodeStr - NULL terminated Unicode output string. + AsciieStr - NULL terminated ASCII input string. + + Returns: + + Start of the Unicode ouput string. + +--*/ + +{ + CHAR16 *Str = UnicodeStr; + while (TRUE) { + *(UnicodeStr++) = (CHAR16) *AsciiStr; + if (*(AsciiStr++) == '\0') { + return Str; + } + } +} + +CHAR8* +Unicode2Ascii ( + OUT CHAR8 *AsciiStr, + IN CHAR16 *UnicodeStr + ) +/*++ + + Routine Description: + + This function converts Unicode string to ASCII string. + + Arguments: + + AsciieStr - NULL terminated ASCII output string. + UnicodeStr - NULL terminated Unicode input string. + + Returns: + + Start of the ASCII ouput string. + +--*/ + +{ + CHAR8 *Str = AsciiStr; + while (TRUE) { + *(AsciiStr++) = (CHAR8) *UnicodeStr; + if (*(UnicodeStr++) == '\0') { + return Str; + } + } +} + +VOID +ExtractDevicePathData ( + IN EFI_HII_DATA_TABLE *DataTable, + IN UINT8 *IfrData, + IN OUT UINT8 **ExportBufferPtr + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + UINT8 *ExportBuffer; + + ExportBuffer = *ExportBufferPtr; + + // + // BUGBUG - don't have devicepath data yet, setting dummy value + // + DataTable++; + ExportBuffer = (UINT8 *) DataTable; + ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Type = EFI_HII_DEVICE_PATH; + ((EFI_HII_DEVICE_PATH_PACK *) ExportBuffer)->Header.Length = (UINT32) (sizeof (EFI_HII_DEVICE_PATH_PACK) + sizeof (EFI_DEVICE_PATH_PROTOCOL)); + + // + // BUGBUG - part of hack - skip the Device Path Pack.....place some data + // + ExportBuffer = ExportBuffer + sizeof (EFI_HII_DEVICE_PATH_PACK); + + ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->Type = EFI_END_ENTIRE_DEVICE_PATH; + ((EFI_DEVICE_PATH_PROTOCOL *) ExportBuffer)->SubType = EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE; + + // + // BUGBUG - still part of hack.... + // + ExportBuffer = ExportBuffer + sizeof (EFI_DEVICE_PATH_PROTOCOL); + *ExportBufferPtr = ExportBuffer; +} + +VOID +ExtractVariableData ( + IN OUT EFI_HII_DATA_TABLE *DataTable, + IN UINT8 *IfrData, + IN OUT UINT8 **ExportBufferPtr + ) +/*++ + +Routine Description: + + This function extract the EFI_HII_VARIABLE_PACK portion from the + each of the EFI_HII_PACKAGE_INSTANCE in HII handle database. + +Arguments: + + DataTable ¨C On input, this parameter point to the EFI_HII_DATA_TABLE structure + of the final data buffer for the EFI_HII_EXPORT interface. This function + update the NumberOfVariableData attribute. + IfrData - It points to a staring address of a EFI_HII_IFR_PACK structure. + ExportBufferPtr ¨C On input, it points the starting address of the data buffer to + host the variable pack. On output, it is the starting address + of data buffer for the next extraction operation. +Returns: + + VOID + +--*/ +{ + EFI_HII_VARIABLE_PACK *VariableContents; + UINT8 *ExportBuffer; + UINTN Index; + UINTN Index2; + UINTN TempValue; + UINTN TempValue2; + EFI_FORM_CALLBACK_PROTOCOL *FormCallback; + EFI_PHYSICAL_ADDRESS CallbackHandle; + EFI_STATUS Status; + CHAR16 *String; + + FormCallback = NULL; + CallbackHandle = 0; + ExportBuffer = *ExportBufferPtr; + + for (Index = 0; IfrData[Index] != EFI_IFR_END_FORM_SET_OP;) { + VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer; + + switch (IfrData[Index]) { + case EFI_IFR_FORM_SET_OP: + TempValue = EFI_HII_VARIABLE; + CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16)); + CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16)); + + // + // If the variable has 0 size, do not process it + // + if (TempValue == 0) { + break; + } + // + // Add the size of the variable pack overhead. Later, will also add the size of the + // name of the variable. + // + TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK); + + CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32)); + CopyMem ( + &CallbackHandle, + &((EFI_IFR_FORM_SET *) &IfrData[Index])->CallbackHandle, + sizeof (EFI_PHYSICAL_ADDRESS) + ); + if (CallbackHandle != 0) { + Status = gBS->HandleProtocol ( + (EFI_HANDLE) (UINTN) CallbackHandle, + &gEfiFormCallbackProtocolGuid, + (VOID *) &FormCallback + ); + } + // + // Since we have a "Setup" variable that wasn't specified by a variable op-code + // it will have a VariableId of 0. All other variable op-codes will have a designation + // of VariableId 1+ + // + TempValue = 0; + CopyMem (&VariableContents->VariableId, &TempValue, sizeof (UINT16)); + CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_FORM_SET *) &IfrData[Index])->Guid, sizeof (EFI_GUID)); + TempValue = sizeof (SETUP_MAP_NAME); + CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32)); + + // + // Add the size of the name to the Header Length + // + TempValue2 = 0; + CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32)); + TempValue2 = TempValue + TempValue2; + CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32)); + + ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK); + CopyMem (ExportBuffer, SETUP_MAP_NAME, sizeof (SETUP_MAP_NAME)); + ExportBuffer = ExportBuffer + sizeof (SETUP_MAP_NAME); + + CopyMem (&TempValue, &((EFI_IFR_FORM_SET *) &IfrData[Index])->NvDataSize, sizeof (UINT16)); + + if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) { + Status = FormCallback->NvRead ( + FormCallback, + (CHAR16 *) SETUP_MAP_NAME, + (EFI_GUID *)(UINTN)&VariableContents->VariableGuid, + NULL, + &TempValue, + ExportBuffer + ); + } else { + Status = gRT->GetVariable ( + (CHAR16 *) SETUP_MAP_NAME, + (EFI_GUID *)(UINTN)&VariableContents->VariableGuid, + NULL, + &TempValue, + ExportBuffer + ); + } + + ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue); + DataTable->NumberOfVariableData++; + break; + + case EFI_IFR_VARSTORE_OP: + TempValue = EFI_HII_VARIABLE; + CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16)); + CopyMem (&TempValue, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Size, sizeof (UINT16)); + + // + // If the variable has 0 size, do not process it + // + if (TempValue == 0) { + break; + } + // + // Add the size of the variable pack overhead. Later, will also add the size of the + // name of the variable. + // + TempValue = TempValue + sizeof (EFI_HII_VARIABLE_PACK); + + CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32)); + CopyMem (&VariableContents->VariableId, &((EFI_IFR_VARSTORE *) &IfrData[Index])->VarId, sizeof (UINT16)); + CopyMem (&VariableContents->VariableGuid, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Guid, sizeof (EFI_GUID)); + TempValue = (UINTN) ((EFI_IFR_VARSTORE *) &IfrData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE); + TempValue = TempValue * 2; + CopyMem (&VariableContents->VariableNameLength, &TempValue, sizeof (UINT32)); + + // + // Add the size of the name to the Header Length + // + TempValue2 = 0; + CopyMem (&TempValue2, &VariableContents->Header.Length, sizeof (UINT32)); + TempValue2 = TempValue + TempValue2; + CopyMem (&VariableContents->Header.Length, &TempValue2, sizeof (UINT32)); + + ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK); + String = (CHAR16 *) ExportBuffer; + for (Index2 = 0; Index2 < TempValue / 2; Index2++) { + ExportBuffer[Index2 * 2] = IfrData[Index + sizeof (EFI_IFR_VARSTORE) + Index2]; + ExportBuffer[Index2 * 2 + 1] = 0; + } + + ExportBuffer = ExportBuffer + TempValue; + + CopyMem (&TempValue, &((EFI_IFR_VARSTORE *) &IfrData[Index])->Size, sizeof (UINT16)); + + if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) { + Status = FormCallback->NvRead ( + FormCallback, + String, + (EFI_GUID *)(UINTN)&VariableContents->VariableGuid, + NULL, + &TempValue, + ExportBuffer + ); + } else { + Status = gRT->GetVariable ( + String, + (EFI_GUID *)(UINTN)&VariableContents->VariableGuid, + NULL, + &TempValue, + ExportBuffer + ); + } + + ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + TempValue); + DataTable->NumberOfVariableData++; + break; + } + + Index = IfrData[Index + 1] + Index; + } + // + // If we have added a variable pack, add a dummy empty one to signify the end + // + if (ExportBuffer != *ExportBufferPtr) { + VariableContents = (EFI_HII_VARIABLE_PACK *) ExportBuffer; + TempValue = EFI_HII_VARIABLE; + CopyMem (&VariableContents->Header.Type, &TempValue, sizeof (UINT16)); + TempValue = sizeof (EFI_HII_VARIABLE_PACK); + CopyMem (&VariableContents->Header.Length, &TempValue, sizeof (UINT32)); + ExportBuffer = ExportBuffer + sizeof (EFI_HII_VARIABLE_PACK); + } + + *ExportBufferPtr = ExportBuffer; +} + +EFI_STATUS +EFIAPI +HiiExportDatabase ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + This function allows a program to extract a form or form package that has + previously been registered with the EFI HII database. + +Arguments: + +Returns: + +--*/ +{ + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_IFR_PACK *FormPack; + UINT8 *RawData; + UINT8 *ExportBuffer; + EFI_HII_EXPORT_TABLE *ExportTable; + EFI_HII_DATA_TABLE *DataTable; + BOOLEAN InsufficientSize; + BOOLEAN VariableExist; + UINT16 NumberOfHiiDataTables; + UINTN SizeNeeded; + UINTN Index; + UINTN VariableSize; + UINTN TempValue; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + HandleDatabase = HiiData->DatabaseHead; + + FormPack = NULL; + RawData = NULL; + PackageInstance = NULL; + InsufficientSize = FALSE; + NumberOfHiiDataTables = 0; + VariableSize = 0; + TempValue = 0; + SizeNeeded = sizeof (EFI_HII_EXPORT_TABLE); + + // + // How many total tables are there? + // + for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { + if ((Handle != 0) && (Handle != HandleDatabase->Handle)) { + continue; + } + + VariableExist = FALSE; + NumberOfHiiDataTables++; + PackageInstance = HandleDatabase->Buffer; + if (PackageInstance == NULL) { + continue; + } + // + // Extract Size of Export Package + // + SizeNeeded = SizeNeeded + PackageInstance->IfrSize + + PackageInstance->StringSize + + sizeof (EFI_HII_DATA_TABLE) + + sizeof (EFI_HII_DEVICE_PATH_PACK); + + // + // BUGBUG We aren't inserting Device path data yet + // + SizeNeeded = SizeNeeded + sizeof (EFI_DEVICE_PATH_PROTOCOL); + + // + // Extract Size of Variable Data + // + if (PackageInstance->IfrSize > 0) { + FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); + } else { + // + // No IFR? No variable information + // + continue; + } + + RawData = (UINT8 *) FormPack; + + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + switch (RawData[Index]) { + case EFI_IFR_FORM_SET_OP: + CopyMem (&VariableSize, &((EFI_IFR_FORM_SET *) &RawData[Index])->NvDataSize, sizeof (UINT16)); + SizeNeeded = SizeNeeded + VariableSize + sizeof (SETUP_MAP_NAME) + sizeof (EFI_HII_VARIABLE_PACK); + VariableExist = TRUE; + break; + + case EFI_IFR_VARSTORE_OP: + CopyMem (&VariableSize, &((EFI_IFR_VARSTORE *) &RawData[Index])->Size, sizeof (UINT16)); + SizeNeeded = SizeNeeded + VariableSize + sizeof (EFI_HII_VARIABLE_PACK); + // + // We will be expanding the stored ASCII name to a Unicode string. This will cause some memory overhead + // Since the VARSTORE size already takes in consideration the ASCII size, we need to size it and add another + // instance of it. Essentially, 2 ASCII strings == 1 Unicode string in size. + // + TempValue = (UINTN) ((EFI_IFR_VARSTORE *) &RawData[Index])->Header.Length - sizeof (EFI_IFR_VARSTORE); + SizeNeeded = SizeNeeded + TempValue * 2; + VariableExist = TRUE; + break; + } + + Index = RawData[Index + 1] + Index; + } + // + // If a variable exists for this handle, add an additional variable pack overhead to + // indicate that we will have an extra null Variable Pack to signify the end of the Variable Packs + // + if (VariableExist) { + SizeNeeded = SizeNeeded + sizeof (EFI_HII_VARIABLE_PACK); + } + } + + if (SizeNeeded > *BufferSize) { + *BufferSize = SizeNeeded; + return EFI_BUFFER_TOO_SMALL; + } + // + // Zero out the incoming buffer + // + ZeroMem (Buffer, *BufferSize); + + // + // Cast the Buffer to EFI_HII_EXPORT_TABLE + // + ExportTable = (EFI_HII_EXPORT_TABLE *) Buffer; + + // + // Set the Revision for the Export Table + // + CopyMem (&ExportTable->Revision, &gEfiHiiProtocolGuid, sizeof (EFI_GUID)); + + ExportBuffer = (UINT8 *) (UINTN) (((UINT8 *) ExportTable) + sizeof (EFI_HII_EXPORT_TABLE)); + HandleDatabase = HiiData->DatabaseHead; + + // + // Check numeric value against the head of the database + // + for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { + DataTable = (EFI_HII_DATA_TABLE *) ExportBuffer; + PackageInstance = HandleDatabase->Buffer; + // + // If not asking for a specific handle, export the entire database + // + if (Handle == 0) { + ExportTable->NumberOfHiiDataTables = NumberOfHiiDataTables; + CopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID)); + DataTable->HiiHandle = PackageInstance->Handle; + DataTable->DevicePathOffset = (UINT32) (sizeof (EFI_HII_DATA_TABLE)); + + // + // Start Dumping DevicePath + // + ExtractDevicePathData (DataTable, RawData, &ExportBuffer); + + if (((UINTN) ExportBuffer) == ((UINTN) DataTable)) { + // + // If there is no DevicePath information - set offset to 0 to signify the absence of data to parse + // + DataTable->DevicePathOffset = 0; + } + + DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable)); + + if (PackageInstance->IfrSize > 0) { + FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); + + RawData = (UINT8 *) FormPack; + TempValue = 0; + + // + // Start dumping the Variable Data + // + ExtractVariableData (DataTable, RawData, &ExportBuffer); + DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable)); + + if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) { + DataTable->VariableDataOffset = 0; + } + // + // Start dumping the IFR data (Note: It is in an IFR PACK) + // + CopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize); + ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize); + DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable)); + + // + // Start dumping the String data (Note: It is in a String PACK) + // + if (PackageInstance->StringSize > 0) { + RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize); + CopyMem (ExportBuffer, RawData, PackageInstance->StringSize); + DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize); + + CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32)); + for (; TempValue != 0;) { + DataTable->NumberOfLanguages++; + ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length; + CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32)); + } + + ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK); + } else { + DataTable->StringDataOffset = 0; + } + } else { + // + // No IFR? No variable information. If Offset is 0, means there is none. (Hmm - this might be prunable - no strings to export if no IFR - we always have a stub) + // + DataTable->VariableDataOffset = 0; + DataTable->IfrDataOffset = 0; + DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable)); + + // + // Start dumping the String data - NOTE: It is in String Pack form + // + if (PackageInstance->StringSize > 0) { + RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize); + CopyMem (ExportBuffer, RawData, PackageInstance->StringSize); + DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize); + + CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32)); + for (; TempValue != 0;) { + DataTable->NumberOfLanguages++; + ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length; + CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32)); + } + + ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK); + } else { + DataTable->StringDataOffset = 0; + } + } + } else { + // + // Match the numeric value with the database entry - if matched, extract PackageInstance + // + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + ExportTable->NumberOfHiiDataTables = NumberOfHiiDataTables; + DataTable->HiiHandle = PackageInstance->Handle; + CopyMem (&DataTable->PackageGuid, &PackageInstance->Guid, sizeof (EFI_GUID)); + + // + // Start Dumping DevicePath + // + ExtractDevicePathData (DataTable, RawData, &ExportBuffer); + DataTable->VariableDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable)); + + if (PackageInstance->IfrSize > 0) { + FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); + + RawData = (UINT8 *) FormPack; + TempValue = 0; + + // + // Start dumping the Variable Data + // + ExtractVariableData (DataTable, RawData, &ExportBuffer); + DataTable->IfrDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable)); + + if (DataTable->VariableDataOffset == DataTable->IfrDataOffset) { + DataTable->VariableDataOffset = 0; + } + // + // Start dumping the IFR data + // + CopyMem (ExportBuffer, &PackageInstance->IfrData, PackageInstance->IfrSize); + ExportBuffer = (UINT8 *) (UINTN) (((UINTN) ExportBuffer) + PackageInstance->IfrSize); + DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable)); + + // + // Start dumping the String data - NOTE: It is in String Pack form + // + if (PackageInstance->StringSize > 0) { + RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize); + CopyMem (ExportBuffer, RawData, PackageInstance->StringSize); + DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize); + + CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32)); + for (; TempValue != 0;) { + DataTable->NumberOfLanguages++; + ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length; + CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32)); + } + + ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK); + } else { + DataTable->StringDataOffset = 0; + } + } else { + // + // No IFR? No variable information. If Offset is 0, means there is none. + // + DataTable->VariableDataOffset = 0; + DataTable->IfrDataOffset = 0; + DataTable->StringDataOffset = (UINT32) (((UINTN) ExportBuffer) - ((UINTN) DataTable)); + + // + // Start dumping the String data - Note: It is in String Pack form + // + if (PackageInstance->StringSize > 0) { + RawData = (UINT8 *) (((UINTN) &PackageInstance->IfrData) + PackageInstance->IfrSize); + CopyMem (ExportBuffer, RawData, PackageInstance->StringSize); + DataTable->DataTableSize = (UINT32) (DataTable->StringDataOffset + PackageInstance->StringSize); + + CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32)); + for (; TempValue != 0;) { + DataTable->NumberOfLanguages++; + ExportBuffer = ExportBuffer + ((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length; + CopyMem (&TempValue, &((EFI_HII_STRING_PACK *) ExportBuffer)->Header.Length, sizeof (UINT32)); + } + + ExportBuffer = ExportBuffer + sizeof (EFI_HII_STRING_PACK); + } else { + DataTable->StringDataOffset = 0; + } + } + break; + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiGetForms ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID FormId, + IN OUT UINTN *BufferLengthTemp, + OUT UINT8 *Buffer + ) +/*++ + +Routine Description: + + This function allows a program to extract a form or form package that has + previously been registered with the EFI HII database. + +Arguments: + This - A pointer to the EFI_HII_PROTOCOL instance. + + Handle - Handle on which the form resides. Type EFI_HII_HANDLE is defined in + EFI_HII_PROTOCOL.NewPack() in the Packages section. + + FormId - The ID of the form to return. If the ID is zero, the entire form package is returned. + Type EFI_FORM_ID is defined in "Related Definitions" below. + + BufferLength - On input, the length of the Buffer. On output, the length of the returned buffer, if + the length was sufficient and, if it was not, the length that is required to fit the + requested form(s). + + Buffer - The buffer designed to receive the form(s). + +Returns: + + EFI_SUCCESS - Buffer filled with the requested forms. BufferLength + was updated. + + EFI_INVALID_PARAMETER - The handle is unknown. + + EFI_NOT_FOUND - A form on the requested handle cannot be found with the + requested FormId. + + EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored. + +--*/ +{ + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_IFR_PACK *FormPack; + EFI_IFR_FORM *Form; + EFI_IFR_OP_HEADER *Location; + UINT16 *BufferLength = (UINT16 *) BufferLengthTemp; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + HandleDatabase = HiiData->DatabaseHead; + + PackageInstance = NULL; + + // + // Check numeric value against the head of the database + // + for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { + // + // Match the numeric value with the database entry - if matched, extract PackageInstance + // + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + break; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_NOT_FOUND; + } + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (PackageInstance->IfrSize > 0) { + FormPack = (EFI_HII_IFR_PACK *) (&PackageInstance->IfrData); + } else { + // + // If there is no IFR data return an error + // + return EFI_NOT_FOUND; + } + // + // If requesting the entire Form Package + // + if (FormId == 0) { + // + // Return an error if buffer is too small + // + if (PackageInstance->IfrSize > *BufferLength || Buffer == NULL) { + *BufferLength = (UINT16) PackageInstance->IfrSize; + return EFI_BUFFER_TOO_SMALL; + } + + CopyMem (Buffer, FormPack, PackageInstance->IfrSize); + return EFI_SUCCESS; + } else { + FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); + Location = (EFI_IFR_OP_HEADER *) FormPack; + + // + // Look for the FormId requested + // + for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) { + switch (Location->OpCode) { + case EFI_IFR_FORM_OP: + Form = (EFI_IFR_FORM *) Location; + + // + // If we found a Form Op-code and it is of the correct Id, copy it and return + // + if (Form->FormId == FormId) { + if (Location->Length > *BufferLength || Buffer == NULL) { + *BufferLength = Location->Length; + return EFI_BUFFER_TOO_SMALL; + } else { + for (; Location->OpCode != EFI_IFR_END_FORM_OP;) { + CopyMem (Buffer, Location, Location->Length); + Buffer = Buffer + Location->Length; + Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length); + } + + CopyMem (Buffer, Location, Location->Length); + return EFI_SUCCESS; + } + } + + default: + break; + } + // + // Go to the next Op-Code + // + Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length); + } + } + + return EFI_SUCCESS; +} + +// +// Helper functions to HiiGetDefaultImage() +// + +STATIC +UINT8* +HiiGetDefaultImageInitPack ( + IN OUT EFI_HII_VARIABLE_PACK_LIST *VariablePackItem, + IN EFI_IFR_VARSTORE *VarStore + ) +/*++ + + Routine Description: + + Initialize the EFI_HII_VARIABLE_PACK_LIST structure and + prepare it ready to be used by HiiGetDefaultImagePopulateMap (). + + Arguments: + + VariablePackItem - Variable Package List. + VarStore - IFR variable storage. + + Returns: + + Return the pointer to the Map space. + +--*/ +{ + CHAR16 *Name16; + CHAR8 *Name8; + CHAR8 *Map; + EFI_HII_VARIABLE_PACK *VariablePack; + + // + // Set pointer the pack right after the node + // + VariablePackItem->VariablePack = (EFI_HII_VARIABLE_PACK *) (VariablePackItem + 1); + VariablePack = VariablePackItem->VariablePack; + + // + // Copy the var name to VariablePackItem from VarStore + // Needs ASCII->Unicode conversion. + // + ASSERT (VarStore->Header.Length > sizeof (*VarStore)); + Name8 = (CHAR8 *) (VarStore + 1); + Name16 = (CHAR16 *) (VariablePack + 1); + Ascii2Unicode (Name16, Name8); + + // + // Compute the other fields of the VariablePackItem + // + VariablePack->VariableId = VarStore->VarId; + CopyMem (&VariablePack->VariableGuid, &VarStore->Guid, sizeof (EFI_GUID)); + VariablePack->VariableNameLength = (UINT32) ((StrLen (Name16) + 1) * 2); + VariablePack->Header.Length = sizeof (*VariablePack) + + VariablePack->VariableNameLength + + VarStore->Size; + // + // Return the pointer to the Map space. + // + Map = (CHAR8 *) Name16 + VariablePack->VariableNameLength; + + return (UINT8 *)Map; +} + +STATIC +VOID +HiiGetDefaultImagePopulateMap ( + IN OUT UINT8 *Map, + IN EFI_IFR_OP_HEADER *FormSet, + IN EFI_IFR_VARSTORE *VarStore, + IN UINTN DefaultMask + ) +/*++ + + Routine Description: + + Fill the Map with all the default values either from NV or Hii database. + + Arguments: + + Map - Memory pointer to hold the default values. + FormSet - The starting EFI_IFR_OP_HEADER to begin retriving default values. + VarStore - IFR variable storage. + DefaultMask - The mask used to get the default variable. + + Returns: + + VOID + +--*/ +{ + EFI_STATUS Status; + EFI_IFR_OP_HEADER *IfrItem; + UINT16 VarId; + EFI_IFR_VARSTORE_SELECT *VarSelect; + EFI_IFR_ONE_OF_OPTION *OneOfOpt; + EFI_IFR_CHECKBOX *CheckBox; + EFI_IFR_NUMERIC *Numeric; + UINTN Size; + UINTN SizeTmp; + EFI_IFR_NV_DATA *IfrNvData; + EFI_GUID Guid; + CHAR16 *Name16; + CHAR8 *Name8; + EFI_HANDLE CallbackHandle; + EFI_FORM_CALLBACK_PROTOCOL *FormCallbackProt; + + // + // Get the Map's Name/Guid/Szie from the Varstore. + // VARSTORE contains the Name in ASCII format (@#$^&!), must convert it to Unicode. + // + ASSERT (VarStore->Header.Length >= sizeof (*VarStore)); + Name8 = (CHAR8 *) (VarStore + 1); + Name16 = AllocateZeroPool ((VarStore->Header.Length - sizeof (*VarStore)) * sizeof (CHAR16)); + Ascii2Unicode (Name16, Name8); + CopyMem (&Guid, &VarStore->Guid, sizeof(EFI_GUID)); + Size = VarStore->Size; + + // + // First, check if the map exists in the NV. If so, get it from NV and exit. + // + if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) { + // + // Check if Manufaturing Defaults exist in the NV. + // + Status = EfiLibHiiVariableOverrideBySuffix ( + HII_VARIABLE_SUFFIX_MANUFACTURING_OVERRIDE, + Name16, + &Guid, + Size, + Map + ); + } else { + // + // All other cases default to Defaults. Check if Defaults exist in the NV. + // + Status = EfiLibHiiVariableOverrideBySuffix ( + HII_VARIABLE_SUFFIX_DEFAULT_OVERRIDE, + Name16, + &Guid, + Size, + Map + ); + } + if (!EFI_ERROR (Status)) { + // + // Either Defaults/Manufacturing variable exists and appears to be valid. + // The map is read, exit w/ success now. + // + gBS->FreePool (Name16); + return; + } + + // + // First, prime the map with what already is in the NV. + // This is needed to cover a situation where the IFR does not contain all the + // defaults; either deliberately not having appropriate IFR, or in case of IFR_STRING, there is no default. + // Ignore status. Either it gets read or not. + // + FormCallbackProt = NULL; + CopyMem (&CallbackHandle, &((EFI_IFR_FORM_SET*) FormSet)->CallbackHandle, sizeof (CallbackHandle)); + if (CallbackHandle != NULL) { + Status = gBS->HandleProtocol ( + (EFI_HANDLE) (UINTN) CallbackHandle, + &gEfiFormCallbackProtocolGuid, + (VOID *) &FormCallbackProt + ); + } + if ((NULL != FormCallbackProt) && (NULL != FormCallbackProt->NvRead)) { + // + // Attempt to read using NvRead() callback. Probe first for existence and correct variable size. + // + SizeTmp = 0; + Status = FormCallbackProt->NvRead ( + FormCallbackProt, + Name16, + &Guid, + 0, + &SizeTmp, + NULL + ); + if ((EFI_BUFFER_TOO_SMALL == Status) && (SizeTmp == Size)) { + Status = FormCallbackProt->NvRead ( + FormCallbackProt, + Name16, + &Guid, + 0, + &SizeTmp, + Map + ); + ASSERT_EFI_ERROR (Status); + ASSERT (SizeTmp == Size); + } + } else { + // + // No callback available for this formset, read straight from NV. Deliberately ignore the Status. + // The buffer will only be written if variable exists nd has correct size. + // + Status = EfiLibHiiVariableRetrieveFromNv ( + Name16, + &Guid, + Size, + (VOID **) &Map + ); + } + + // + // Iterate all IFR statements and for applicable, retrieve the default into the Map. + // + for (IfrItem = FormSet, VarId = 0; + IfrItem->OpCode != EFI_IFR_END_FORM_SET_OP; + IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length) + ) { + + // + // Observe VarStore switch. + // + if (EFI_IFR_VARSTORE_SELECT_OP == IfrItem->OpCode) { + VarSelect = (EFI_IFR_VARSTORE_SELECT *) IfrItem; + VarId = VarSelect->VarId; + continue; + } + + + // + // Skip opcodes that reference other VarStore than that specific to current map. + // + if (VarId != VarStore->VarId) { + continue; + } + + // + // Extract the default value from this opcode if applicable, and apply it to the map. + // + IfrNvData = (EFI_IFR_NV_DATA *) IfrItem; + switch (IfrItem->OpCode) { + + case EFI_IFR_ONE_OF_OP: + ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size); + // + // Get to the first EFI_IFR_ONE_OF_OPTION_OP + // + IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8*) IfrItem + IfrItem->Length); + ASSERT (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode); + + OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem; + // + // In the worst case, the first will be the default. + // + CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth); + + while (EFI_IFR_ONE_OF_OPTION_OP == IfrItem->OpCode) { + + OneOfOpt = (EFI_IFR_ONE_OF_OPTION *)IfrItem; + if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) { + if (0 != (OneOfOpt->Flags & EFI_IFR_FLAG_MANUFACTURING)) { + // + // In the worst case, the first will be the default. + // + CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth); + break; + } + } else { + if (OneOfOpt->Flags & EFI_IFR_FLAG_DEFAULT) { + // + // In the worst case, the first will be the default. + // + CopyMem (Map + IfrNvData->QuestionId, &OneOfOpt->Value, IfrNvData->StorageWidth); + break; + } + } + + IfrItem = (EFI_IFR_OP_HEADER *)((UINT8*)IfrItem + IfrItem->Length); + } + continue; + break; + + case EFI_IFR_CHECKBOX_OP: + ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size); + CheckBox = (EFI_IFR_CHECK_BOX *)IfrItem; + if (DefaultMask == EFI_IFR_FLAG_MANUFACTURING) { + if (0 != (CheckBox->Flags & EFI_IFR_FLAG_MANUFACTURING)) { + *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE; + } + } else { + if (CheckBox->Flags & EFI_IFR_FLAG_DEFAULT) { + *(UINT8 *) (Map + IfrNvData->QuestionId) = TRUE; + } + } + break; + + case EFI_IFR_NUMERIC_OP: + ASSERT (IfrNvData->QuestionId + IfrNvData->StorageWidth <= VarStore->Size); + Numeric = (EFI_IFR_NUMERIC *) IfrItem; + CopyMem (Map + IfrNvData->QuestionId, &Numeric->Default, IfrNvData->StorageWidth); + break; + + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + // + // No support for default value for these opcodes. + // + break; + } + } + + gBS->FreePool (Name16); + +} + + +EFI_STATUS +EFIAPI +HiiGetDefaultImage ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN UINTN DefaultMask, + OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList + ) +/*++ + + Routine Description: + + This function allows a program to extract the NV Image + that represents the default storage image + + Arguments: + This - A pointer to the EFI_HII_PROTOCOL instance. + Handle - The HII handle from which will have default data retrieved. + UINTN - Mask used to retrieve the default image. + VariablePackList - Callee allocated, tightly-packed, link list data + structure that contain all default varaible packs + from the Hii Database. + + Returns: + EFI_NOT_FOUND - If Hii database does not contain any default images. + EFI_INVALID_PARAMETER - Invalid input parameter. + EFI_SUCCESS - Operation successful. + +--*/ +{ + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_IFR_OP_HEADER *FormSet; + EFI_IFR_OP_HEADER *IfrItem; + EFI_IFR_VARSTORE *VarStore; + EFI_IFR_VARSTORE *VarStoreDefault; + UINTN SetupMapNameSize; + UINTN SizeOfMaps; + EFI_HII_VARIABLE_PACK_LIST *PackList; + EFI_HII_VARIABLE_PACK_LIST *PackListNext; + EFI_HII_VARIABLE_PACK_LIST *PackListLast; + UINT8 *Map; + + + // + // Find the IFR pack from the handle. Then get the formset from the pack. + // + PackageInstance = NULL; + HandleDatabase = (EFI_HII_DATA_FROM_THIS (This))->DatabaseHead; + for ( ; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + break; + } + } + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + FormSet = (EFI_IFR_OP_HEADER *) ((UINT8 *) &PackageInstance->IfrData + sizeof (EFI_HII_IFR_PACK)); + + // + // Get the sizes of all the VARSTOREs in this VFR. + // Then allocate enough space for all of them plus all maps + // + SizeOfMaps = 0; + IfrItem = FormSet; + while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) { + + if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) { + VarStore = (EFI_IFR_VARSTORE *) IfrItem; + // + // Size of the map + // + SizeOfMaps += VarStore->Size; + // + // add the size of the string, in Unicode + // + SizeOfMaps += (VarStore->Header.Length - sizeof (*VarStore)) * 2; + // + // Space for node + // + SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK); + // + // Space for linked list node + // + SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST); + } + + IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length); + } + + // + // If the FormSet OpCode has a non-zero NvDataSize. There is a default + // NvMap with ID=0, GUID that of the formset itself and "Setup" as name. + // + SetupMapNameSize = StrLen (SETUP_MAP_NAME) + 1; + VarStoreDefault = AllocateZeroPool (sizeof (*VarStoreDefault) + SetupMapNameSize); + + if (0 != ((EFI_IFR_FORM_SET*)FormSet)->NvDataSize) { + + VarStoreDefault->Header.OpCode = EFI_IFR_VARSTORE_OP; + VarStoreDefault->Header.Length = (UINT8) (sizeof (*VarStoreDefault) + SetupMapNameSize); + Unicode2Ascii ((CHAR8 *) (VarStoreDefault + 1), SETUP_MAP_NAME); + CopyMem (&VarStoreDefault->Guid, &((EFI_IFR_FORM_SET*) FormSet)->Guid, sizeof (EFI_GUID)); + VarStoreDefault->VarId = 0; + VarStoreDefault->Size = ((EFI_IFR_FORM_SET*) FormSet)->NvDataSize; + + // + // Size of the map + // + SizeOfMaps += VarStoreDefault->Size; + // + // add the size of the string + // + SizeOfMaps += sizeof (SETUP_MAP_NAME); + // + // Space for node + // + SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK); + // + // Space for linked list node + // + SizeOfMaps += sizeof (EFI_HII_VARIABLE_PACK_LIST); + } + + if (0 == SizeOfMaps) { + // + // The IFR does not have any explicit or default map(s). + // + return EFI_NOT_FOUND; + } + + // + // Allocate the return buffer + // + PackList = AllocateZeroPool (SizeOfMaps); + ASSERT (NULL != PackList); + + PackListNext = PackList; + PackListLast = PackList; + + // + // Handle the default map first, if any. + // + if (0 != VarStoreDefault->Size) { + + Map = HiiGetDefaultImageInitPack (PackListNext, VarStoreDefault); + + HiiGetDefaultImagePopulateMap (Map, FormSet, VarStoreDefault, DefaultMask); + + PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length); + PackListLast = PackListNext; + PackListNext = PackListNext->NextVariablePack; + } + + + // + // Handle the explicit varstore(s) + // + IfrItem = FormSet; + while (EFI_IFR_END_FORM_SET_OP != IfrItem->OpCode) { + + if (EFI_IFR_VARSTORE_OP == IfrItem->OpCode) { + + Map = HiiGetDefaultImageInitPack (PackListNext, (EFI_IFR_VARSTORE *) IfrItem); + + HiiGetDefaultImagePopulateMap (Map, FormSet, (EFI_IFR_VARSTORE *) IfrItem, DefaultMask); + + PackListNext->NextVariablePack = (EFI_HII_VARIABLE_PACK_LIST *) ((UINT8 *) PackListNext->VariablePack + PackListNext->VariablePack->Header.Length); + PackListLast = PackListNext; + PackListNext = PackListNext->NextVariablePack; + } + + IfrItem = (EFI_IFR_OP_HEADER *) ((UINT8 *) IfrItem + IfrItem->Length); + } + + PackListLast->NextVariablePack = NULL; + *VariablePackList = PackList; + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +HiiUpdateForm ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_LABEL Label, + IN BOOLEAN AddData, + IN EFI_HII_UPDATE_DATA *Data + ) +/*++ + +Routine Description: + This function allows the caller to update a form that has + previously been registered with the EFI HII database. + +Arguments: + Handle - Hii Handle associated with the Formset to modify + Label - Update information starting immediately after this label in the IFR + AddData - If TRUE, add data. If FALSE, remove data + Data - If adding data, this is the pointer to the data to add + +Returns: + EFI_SUCCESS - Update success. + Other - Update fail. + +--*/ +{ + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_IFR_PACK *FormPack; + EFI_IFR_OP_HEADER *Location; + EFI_IFR_OP_HEADER *DataLocation; + UINT8 *OtherBuffer; + UINT8 *TempBuffer; + UINT8 *OrigTempBuffer; + UINTN TempBufferSize; + UINTN Index; + + OtherBuffer = NULL; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + HandleDatabase = HiiData->DatabaseHead; + + PackageInstance = NULL; + + // + // Check numeric value against the head of the database + // + for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { + // + // Match the numeric value with the database entry - if matched, extract PackageInstance + // + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + break; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Calculate and allocate space for retrieval of IFR data + // + DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data; + TempBufferSize = (CHAR8 *) (&PackageInstance->IfrData) - (CHAR8 *) (PackageInstance); + + for (Index = 0; Index < Data->DataCount; Index++) { + TempBufferSize += DataLocation->Length; + DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length); + } + + TempBufferSize += PackageInstance->IfrSize + PackageInstance->StringSize; + + TempBuffer = AllocateZeroPool (TempBufferSize); + OrigTempBuffer = TempBuffer; + + // + // We update only packages with IFR information in it + // + if (PackageInstance->IfrSize == 0) { + return EFI_INVALID_PARAMETER; + } + + CopyMem ( + TempBuffer, + PackageInstance, + ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance)) + ); + + TempBuffer = TempBuffer + ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER) - (CHAR8 *) (PackageInstance)); + + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); + Location = (EFI_IFR_OP_HEADER *) FormPack; + + // + // Look for the FormId requested + // + for (; Location->OpCode != EFI_IFR_END_FORM_SET_OP;) { + switch (Location->OpCode) { + case EFI_IFR_FORM_SET_OP: + // + // If the FormSet has an update pending, pay attention. + // + if (Data->FormSetUpdate) { + ((EFI_IFR_FORM_SET *) Location)->CallbackHandle = Data->FormCallbackHandle; + } + + CopyMem (TempBuffer, Location, Location->Length); + TempBuffer = TempBuffer + Location->Length; + break; + + case EFI_IFR_FORM_OP: + // + // If the Form has an update pending, pay attention. + // + if (Data->FormUpdate) { + ((EFI_IFR_FORM *) Location)->FormTitle = Data->FormTitle; + } + + CopyMem (TempBuffer, Location, Location->Length); + TempBuffer = TempBuffer + Location->Length; + break; + + case EFI_IFR_LABEL_OP: + // + // If the label does not match the requested update point, ignore it + // + if (((EFI_IFR_LABEL *) Location)->LabelId != Label) { + // + // Copy the label + // + CopyMem (TempBuffer, Location, Location->Length); + TempBuffer = TempBuffer + Location->Length; + + // + // Go to the next Op-Code + // + Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length); + continue; + } + + if (AddData) { + // + // Copy the label + // + CopyMem (TempBuffer, Location, Location->Length); + TempBuffer = TempBuffer + Location->Length; + + // + // Add the DataCount amount of opcodes to TempBuffer + // + DataLocation = (EFI_IFR_OP_HEADER *) &Data->Data; + for (Index = 0; Index < Data->DataCount; Index++) { + CopyMem (TempBuffer, DataLocation, DataLocation->Length); + ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize += DataLocation->Length; + OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN)); + CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2); + TempBuffer = TempBuffer + DataLocation->Length; + DataLocation = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (DataLocation) + DataLocation->Length); + } + // + // Go to the next Op-Code + // + Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length); + continue; + } else { + // + // Copy the label + // + CopyMem (TempBuffer, Location, Location->Length); + TempBuffer = TempBuffer + Location->Length; + Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length); + + // + // Remove the DataCount amount of opcodes unless we run into an end of form or a label + // + for (Index = 0; Index < Data->DataCount; Index++) { + // + // If we are about to skip an end form - bail out, since that is illegal + // + if ((Location->OpCode == EFI_IFR_END_FORM_OP) || (Location->OpCode == EFI_IFR_LABEL_OP)) { + break; + } + // + // By skipping Location entries, we are in effect not copying what was previously there + // + ((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize -= Location->Length; + OtherBuffer = ((UINT8 *) &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->StringSize + sizeof (UINTN)); + CopyMem (OtherBuffer, &((EFI_HII_PACKAGE_INSTANCE *) OrigTempBuffer)->IfrSize, 2); + Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length); + } + } + + default: + CopyMem (TempBuffer, Location, Location->Length); + TempBuffer = TempBuffer + Location->Length; + break; + } + // + // Go to the next Op-Code + // + Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length); + } + // + // Copy the last op-code left behind from the for loop + // + CopyMem (TempBuffer, Location, Location->Length); + + // + // Advance to beginning of strings and copy them + // + TempBuffer = TempBuffer + Location->Length; + Location = (EFI_IFR_OP_HEADER *) ((CHAR8 *) (Location) + Location->Length); + CopyMem (TempBuffer, Location, PackageInstance->StringSize); + + // + // Free the old buffer, and assign into our database the latest buffer + // + gBS->FreePool (HandleDatabase->Buffer); + HandleDatabase->Buffer = OrigTempBuffer; + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.c new file mode 100644 index 0000000000..ce34eff5bd --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.c @@ -0,0 +1,413 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + HiiDatabase.c + +Abstract: + + This file contains the entry code to the HII database. + +--*/ + +#include "HiiDatabase.h" + +EFI_STATUS +EFIAPI +InitializeHiiDatabase ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Initialize HII Database + +Arguments: + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + EFI_SUCCESS - Setup loaded. + other - Setup Error + +--*/ +{ + EFI_STATUS Status; + EFI_HII_DATA *HiiData; + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HANDLE *HandleBuffer; + EFI_HANDLE Handle; + UINTN HandleCount; + UINTN Index; + + // + // There will be only one HII Database in the system + // If there is another out there, someone is trying to install us + // again. Fail that scenario. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiHiiProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + + // + // If there was no error, assume there is an installation and fail to load + // + if (!EFI_ERROR (Status)) { + if (HandleBuffer != NULL) { + gBS->FreePool (HandleBuffer); + } + + return EFI_DEVICE_ERROR; + } + + HiiData = AllocatePool (sizeof (EFI_HII_DATA)); + + ASSERT (HiiData); + + GlobalData = AllocateZeroPool (sizeof (EFI_HII_GLOBAL_DATA)); + + ASSERT (GlobalData); + + // + // Seed the Font Database with a known non-character glyph + // + for (Index = 0; Index <= MAX_GLYPH_COUNT; Index++) { + // + // Seeding the UnicodeWeight with 0 signifies that it is uninitialized + // + GlobalData->NarrowGlyphs[Index].UnicodeWeight = 0; + GlobalData->WideGlyphs[Index].UnicodeWeight = 0; + GlobalData->NarrowGlyphs[Index].Attributes = 0; + GlobalData->WideGlyphs[Index].Attributes = 0; + CopyMem (GlobalData->NarrowGlyphs[Index].GlyphCol1, &mUnknownGlyph, NARROW_GLYPH_ARRAY_SIZE); + CopyMem (GlobalData->WideGlyphs[Index].GlyphCol1, &mUnknownGlyph, WIDE_GLYPH_ARRAY_SIZE); + } + // + // Fill in HII data + // + HiiData->Signature = EFI_HII_DATA_SIGNATURE; + HiiData->GlobalData = GlobalData; + HiiData->GlobalData->SystemKeyboardUpdate = FALSE; + HiiData->DatabaseHead = NULL; + HiiData->Hii.NewPack = HiiNewPack; + HiiData->Hii.RemovePack = HiiRemovePack; + HiiData->Hii.FindHandles = HiiFindHandles; + HiiData->Hii.ExportDatabase = HiiExportDatabase; + HiiData->Hii.GetGlyph = HiiGetGlyph; + HiiData->Hii.GetPrimaryLanguages = HiiGetPrimaryLanguages; + HiiData->Hii.GetSecondaryLanguages = HiiGetSecondaryLanguages; + HiiData->Hii.NewString = HiiNewString; + HiiData->Hii.GetString = HiiGetString; + HiiData->Hii.ResetStrings = HiiResetStrings; + HiiData->Hii.TestString = HiiTestString; + HiiData->Hii.GetLine = HiiGetLine; + HiiData->Hii.GetForms = HiiGetForms; + HiiData->Hii.GetDefaultImage = HiiGetDefaultImage; + HiiData->Hii.UpdateForm = HiiUpdateForm; + HiiData->Hii.GetKeyboardLayout = HiiGetKeyboardLayout; + HiiData->Hii.GlyphToBlt = HiiGlyphToBlt; + + // + // Install protocol interface + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiHiiProtocolGuid, + EFI_NATIVE_INTERFACE, + &HiiData->Hii + ); + + ASSERT_EFI_ERROR (Status); + + return Status; +} + +EFI_STATUS +EFIAPI +HiiFindHandles ( + IN EFI_HII_PROTOCOL *This, + IN OUT UINT16 *HandleBufferLength, + OUT EFI_HII_HANDLE Handle[1] + ) +/*++ + +Routine Description: + Determines the handles that are currently active in the database. + +Arguments: + +Returns: + +--*/ +{ + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HII_HANDLE_DATABASE *Database; + EFI_HII_DATA *HiiData; + UINTN HandleCount; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + GlobalData = HiiData->GlobalData; + + Database = HiiData->DatabaseHead; + + if (Database == NULL) { + *HandleBufferLength = 0; + return EFI_NOT_FOUND; + } + + for (HandleCount = 0; Database != NULL; HandleCount++) { + Database = Database->NextHandleDatabase; + } + // + // Is there a sufficient buffer for the data being passed back? + // + if (*HandleBufferLength >= (sizeof (EFI_HII_HANDLE) * HandleCount)) { + Database = HiiData->DatabaseHead; + + // + // Copy the Head information + // + if (Database->Handle != 0) { + CopyMem (&Handle[0], &Database->Handle, sizeof (EFI_HII_HANDLE)); + Database = Database->NextHandleDatabase; + } + // + // Copy more data if appropriate + // + for (HandleCount = 1; Database != NULL; HandleCount++) { + CopyMem (&Handle[HandleCount], &Database->Handle, sizeof (EFI_HII_HANDLE)); + Database = Database->NextHandleDatabase; + } + + *HandleBufferLength = (UINT16) (sizeof (EFI_HII_HANDLE) * HandleCount); + return EFI_SUCCESS; + } else { + // + // Insufficient buffer length + // + *HandleBufferLength = (UINT16) (sizeof (EFI_HII_HANDLE) * HandleCount); + return EFI_BUFFER_TOO_SMALL; + } +} + +EFI_STATUS +EFIAPI +HiiGetPrimaryLanguages ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + OUT EFI_STRING *LanguageString + ) +/*++ + +Routine Description: + + This function allows a program to determine what the primary languages that are supported on a given handle. + +Arguments: + +Returns: + +--*/ +{ + UINTN Count; + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_PACKAGE_INSTANCE *StringPackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_STRING_PACK *StringPack; + EFI_HII_STRING_PACK *Location; + UINT32 Length; + RELOFST Token; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + PackageInstance = NULL; + // + // Find matching handle in the handle database. Then get the package instance. + // + for (HandleDatabase = HiiData->DatabaseHead; + HandleDatabase != NULL; + HandleDatabase = HandleDatabase->NextHandleDatabase + ) { + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + ValidatePack (This, PackageInstance, &StringPackageInstance, NULL); + + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (StringPackageInstance->IfrSize > 0) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize); + } else { + StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData); + } + + Location = StringPack; + // + // Remember that the string packages are formed into contiguous blocks of language data. + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (Count = 0; Length != 0; Count = Count + 3) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + } + + *LanguageString = AllocateZeroPool (2 * (Count + 1)); + + ASSERT (*LanguageString); + + StringPack = (EFI_HII_STRING_PACK *) Location; + + // + // Copy the 6 bytes to LanguageString - keep concatenating it. Shouldn't we just store uint8's since the ISO + // standard defines the lettering as all US English characters anyway? Save a few bytes. + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (Count = 0; Length != 0; Count = Count + 3) { + CopyMem (&Token, &StringPack->LanguageNameString, sizeof (RELOFST)); + CopyMem (*LanguageString + Count, (VOID *) ((CHAR8 *) (StringPack) + Token), 6); + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiGetSecondaryLanguages ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CHAR16 *PrimaryLanguage, + OUT EFI_STRING *LanguageString + ) +/*++ + +Routine Description: + + This function allows a program to determine which secondary languages are supported + on a given handle for a given primary language. + + Arguments: + +Returns: + +--*/ +{ + UINTN Count; + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_PACKAGE_INSTANCE *StringPackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_STRING_PACK *StringPack; + EFI_HII_STRING_PACK *Location; + RELOFST Token; + UINT32 Length; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + // + // Check numeric value against the head of the database + // + PackageInstance = NULL; + for (HandleDatabase = HiiData->DatabaseHead; + HandleDatabase != NULL; + HandleDatabase = HandleDatabase->NextHandleDatabase + ) { + // + // Match the numeric value with the database entry - if matched, extract PackageInstance + // + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + ValidatePack (This, PackageInstance, &StringPackageInstance, NULL); + + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (StringPackageInstance->IfrSize > 0) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize); + } else { + StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData); + } + + Location = StringPack; + + // + // Remember that the string packages are formed into contiguous blocks of language data. + // + for (; StringPack->Header.Length != 0;) { + // + // Find the PrimaryLanguage being requested + // + Token = StringPack->LanguageNameString; + if (CompareMem ((VOID *) ((CHAR8 *) (StringPack) + Token), PrimaryLanguage, 3) == 0) { + // + // Now that we found the primary, the secondary languages will follow immediately + // or the next character is a NULL if there are no secondary languages. We determine + // the number by getting the stringsize based on the StringPack origination + the LanguageNameString + // offset + 6 (which is the size of the first 3 letter ISO primary language name). If we get 2, there + // are no secondary languages (2 = null-terminator). + // + Count = StrSize ((VOID *) ((CHAR8 *) (StringPack) + Token + 6)); + + *LanguageString = AllocateZeroPool (2 * (Count + 1)); + + ASSERT (*LanguageString); + + CopyMem (*LanguageString, (VOID *) ((CHAR8 *) (StringPack) + Token + 6), Count); + break; + } + + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + } + + return EFI_SUCCESS; +} + diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.dxs b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.dxs new file mode 100644 index 0000000000..86c8ac4ce2 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.dxs @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + HiiDatabase.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END \ No newline at end of file diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.h b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.h new file mode 100644 index 0000000000..c50cd958a0 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.h @@ -0,0 +1,302 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + HiiDatabase.h + +Abstract: + + This file contains global defines and prototype definitions + for the HII database. + +--*/ + +#ifndef _HIIDATABASE_H +#define _HIIDATABASE_H + +// +// HII Database Global data +// +#define EFI_HII_DATA_SIGNATURE EFI_SIGNATURE_32 ('H', 'i', 'i', 'P') + +#define MAX_GLYPH_COUNT 65535 +#define NARROW_GLYPH_ARRAY_SIZE 19 +#define WIDE_GLYPH_ARRAY_SIZE 38 + +#define SETUP_MAP_NAME L"Setup" +#define HII_VARIABLE_SUFFIX_USER_DATA L"UserSavedData" +#define HII_VARIABLE_SUFFIX_DEFAULT_OVERRIDE L"DefaultOverride" +#define HII_VARIABLE_SUFFIX_MANUFACTURING_OVERRIDE L"ManufacturingOverride" + +typedef struct _EFI_HII_HANDLE_DATABASE { + VOID *Buffer; // Actual buffer pointer + EFI_HII_HANDLE Handle; // Monotonically increasing value to signify the value returned to caller + UINT32 NumberOfTokens; // The initial number of tokens when first registered + struct _EFI_HII_HANDLE_DATABASE *NextHandleDatabase; +} EFI_HII_HANDLE_DATABASE; + +typedef struct { + EFI_NARROW_GLYPH NarrowGlyphs[MAX_GLYPH_COUNT]; + EFI_WIDE_GLYPH WideGlyphs[MAX_GLYPH_COUNT]; + EFI_KEY_DESCRIPTOR SystemKeyboardLayout[106]; + EFI_KEY_DESCRIPTOR OverrideKeyboardLayout[106]; + BOOLEAN SystemKeyboardUpdate; // Has the SystemKeyboard been updated? +} EFI_HII_GLOBAL_DATA; + +typedef struct { + UINTN Signature; + + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HII_HANDLE_DATABASE *DatabaseHead; // Head of the Null-terminated singly-linked list of handles. + EFI_HII_PROTOCOL Hii; +} EFI_HII_DATA; + +typedef struct { + EFI_HII_HANDLE Handle; + EFI_GUID Guid; + EFI_HII_HANDLE_PACK HandlePack; + UINTN IfrSize; + UINTN StringSize; + EFI_HII_IFR_PACK *IfrData; // All the IFR data stored here + EFI_HII_STRING_PACK *StringData; // All the String data stored at &IfrData + IfrSize (StringData is just a label - never referenced) +} EFI_HII_PACKAGE_INSTANCE; + +typedef struct { + EFI_HII_PACK_HEADER Header; + EFI_IFR_FORM_SET FormSet; + EFI_IFR_END_FORM_SET EndFormSet; +} EFI_FORM_SET_STUB; + +#define EFI_HII_DATA_FROM_THIS(a) CR (a, EFI_HII_DATA, Hii, EFI_HII_DATA_SIGNATURE) + +#define NARROW_WIDTH 8 +#define WIDE_WIDTH 16 + +extern UINT8 mUnknownGlyph[38]; + +// +// Prototypes +// +EFI_STATUS +GetPackSize ( + IN VOID *Pack, + OUT UINTN *PackSize, + OUT UINT32 *NumberOfTokens + ) +; + +EFI_STATUS +ValidatePack ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACKAGE_INSTANCE *PackageInstance, + OUT EFI_HII_PACKAGE_INSTANCE **StringPackageInstance, + OUT UINT32 *TotalStringCount + ) +; + +// +// Public Interface Prototypes +// +EFI_STATUS +EFIAPI +InitializeHiiDatabase ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +EFI_STATUS +EFIAPI +HiiNewPack ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACKAGES *PackageList, + OUT EFI_HII_HANDLE *Handle + ) +; + +EFI_STATUS +EFIAPI +HiiRemovePack ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ) +; + +EFI_STATUS +EFIAPI +HiiFindHandles ( + IN EFI_HII_PROTOCOL *This, + IN OUT UINT16 *HandleBufferLength, + OUT EFI_HII_HANDLE *Handle + ) +; + +EFI_STATUS +EFIAPI +HiiExportDatabase ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +; + +EFI_STATUS +EFIAPI +HiiGetGlyph ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Source, + IN OUT UINT16 *Index, + OUT UINT8 **GlyphBuffer, + OUT UINT16 *BitWidth, + IN OUT UINT32 *InternalStatus + ) +; + +EFI_STATUS +EFIAPI +HiiGlyphToBlt ( + IN EFI_HII_PROTOCOL *This, + IN UINT8 *GlyphBuffer, + IN EFI_UGA_PIXEL Foreground, + IN EFI_UGA_PIXEL Background, + IN UINTN Count, + IN UINTN Width, + IN UINTN Height, + IN OUT EFI_UGA_PIXEL *BltBuffer + ) +; + +EFI_STATUS +EFIAPI +HiiNewString ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Language, + IN EFI_HII_HANDLE Handle, + IN OUT STRING_REF *Reference, + IN CHAR16 *NewString + ) +; + +EFI_STATUS +EFIAPI +HiiGetString ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN BOOLEAN Raw, + IN CHAR16 *LanguageString, + IN OUT UINTN *BufferLength, + OUT EFI_STRING StringBuffer + ) +; + +EFI_STATUS +EFIAPI +HiiResetStrings ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ) +; + +EFI_STATUS +EFIAPI +HiiTestString ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *StringToTest, + IN OUT UINT32 *FirstMissing, + OUT UINT32 *GlyphBufferSize + ) +; + +EFI_STATUS +EFIAPI +HiiGetPrimaryLanguages ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + OUT EFI_STRING *LanguageString + ) +; + +EFI_STATUS +EFIAPI +HiiGetSecondaryLanguages ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CHAR16 *PrimaryLanguage, + OUT EFI_STRING *LanguageString + ) +; + +EFI_STATUS +EFIAPI +HiiGetLine ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN OUT UINT16 *Index, + IN UINT16 LineWidth, + IN CHAR16 *LanguageString, + IN OUT UINT16 *BufferLength, + OUT EFI_STRING StringBuffer + ) +; + +EFI_STATUS +EFIAPI +HiiGetForms ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID FormId, + IN OUT UINTN *BufferLength, + OUT UINT8 *Buffer + ) +; + +EFI_STATUS +EFIAPI +HiiGetDefaultImage ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN UINTN DefaultMask, + OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList + ) +; + +EFI_STATUS +EFIAPI +HiiUpdateForm ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_LABEL Label, + IN BOOLEAN AddData, + IN EFI_HII_UPDATE_DATA *Data + ) +; + +EFI_STATUS +EFIAPI +HiiGetKeyboardLayout ( + IN EFI_HII_PROTOCOL *This, + OUT UINT16 *DescriptorCount, + OUT EFI_KEY_DESCRIPTOR *Descriptor + ) +; + +EFI_STATUS +HiiCompareLanguage ( + IN CHAR16 *LanguageStringLocation, + IN CHAR16 *Language + ) +; + +#endif diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.mbd b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.mbd new file mode 100644 index 0000000000..03f2ed9463 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.mbd @@ -0,0 +1,44 @@ + + + + + HiiDatabase + FCD337AB-B1D3-4EF8-957C-8048606FF670 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseLib + BaseMemoryLib + BaseDebugLibReportStatusCode + UefiDriverEntryPoint + DxeMemoryAllocationLib + DxeReportStatusCodeLib + EdkIfrSupportLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.msa b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.msa new file mode 100644 index 0000000000..3eb5332c81 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/HiiDatabase.msa @@ -0,0 +1,80 @@ + + + + + HiiDatabase + DXE_DRIVER + BS_DRIVER + FCD337AB-B1D3-4EF8-957C-8048606FF670 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + BaseLib + DebugLib + UefiDriverEntryPoint + MemoryAllocationLib + BaseMemoryLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + EdkIfrSupportLib + + + HiiDatabase.c + HiiDatabase.h + Forms.c + Strings.c + Package.c + Fonts.c + Keyboard.c + HiiDatabase.dxs + + + MdePkg + EdkModulePkg + + + Hii + FormCallback + + + + L"Lang" + + 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C } + + + + + + GlobalVariable + + + + + InitializeHiiDatabase + + + diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Keyboard.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Keyboard.c new file mode 100644 index 0000000000..8e9417fc83 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Keyboard.c @@ -0,0 +1,43 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Keyboard.c + +Abstract: + + This file contains the keyboard processing code to the HII database. + +--*/ + + +#include "HiiDatabase.h" + +EFI_STATUS +EFIAPI +HiiGetKeyboardLayout ( + IN EFI_HII_PROTOCOL *This, + OUT UINT16 *DescriptorCount, + OUT EFI_KEY_DESCRIPTOR *Descriptor + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c new file mode 100644 index 0000000000..3e9e5364e9 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Package.c @@ -0,0 +1,677 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Package.c + +Abstract: + + This file contains the package processing code to the HII database. + +--*/ + + +#include "HiiDatabase.h" + +EFI_STATUS +GetPackSize ( + IN VOID *Pack, + OUT UINTN *PackSize, + OUT UINT32 *NumberOfTokens + ) +/*++ + +Routine Description: + Determines the passed in Pack's size and returns the value. + +Arguments: + +Returns: + +--*/ +{ + EFI_HII_STRING_PACK *StringPack; + UINT16 Type; + UINT32 Length; + + *PackSize = 0; + + Type = EFI_HII_IFR; + if (!CompareMem (&((EFI_HII_PACK_HEADER *) Pack)->Type, &Type, sizeof (UINT16))) { + // + // The header contains the full IFR length + // + CopyMem (&Length, &((EFI_HII_PACK_HEADER *) Pack)->Length, sizeof (Length)); + *PackSize = (UINTN) Length; + return EFI_SUCCESS; + } + + Type = EFI_HII_STRING; + if (!CompareMem (&((EFI_HII_PACK_HEADER *) Pack)->Type, &Type, sizeof (UINT16))) { + // + // The header contains the STRING package length + // The assumption is that the strings for all languages + // are a contiguous block of data and there is a series of + // these package instances which will terminate with a NULL package + // instance. + // + StringPack = (EFI_HII_STRING_PACK *) Pack; + + // + // There may be multiple instances packed together of strings + // so we must walk the self describing structures until we encounter + // the NULL structure to determine the full size. + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (Length)); + if (NumberOfTokens != NULL) { + CopyMem (NumberOfTokens, &StringPack->NumStringPointers, sizeof (UINT32)); + } + + while (Length != 0) { + *PackSize = *PackSize + Length; + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) StringPack + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (Length)); + } + // + // Encountered a length of 0, so let's add the space for the NULL terminator + // pack's length and call it done. + // + *PackSize = *PackSize + sizeof (EFI_HII_STRING_PACK); + return EFI_SUCCESS; + } + // + // We only determine the size of the non-global Package types. + // If neither IFR or STRING data were found, return an error + // + return EFI_NOT_FOUND; +} + +EFI_STATUS +ValidatePack ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACKAGE_INSTANCE *PackageInstance, + OUT EFI_HII_PACKAGE_INSTANCE **StringPackageInstance, + OUT UINT32 *TotalStringCount + ) +/*++ + +Routine Description: + Verifies that the package instance is using the correct handle for string operations. + +Arguments: + +Returns: + +--*/ +{ + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_PACKAGE_INSTANCE *HandlePackageInstance; + UINT8 *RawData; + EFI_GUID Guid; + EFI_HII_IFR_PACK *FormPack; + UINTN Index; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + HandleDatabase = HiiData->DatabaseHead; + ZeroMem (&Guid, sizeof (EFI_GUID)); + + *StringPackageInstance = PackageInstance; + + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (PackageInstance->IfrSize > 0) { + FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&PackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); + } else { + // + // If there is no IFR data assume the caller knows what they are doing. + // + return EFI_SUCCESS; + } + + RawData = (UINT8 *) FormPack; + + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + if (RawData[Index] == EFI_IFR_FORM_SET_OP) { + // + // Cache the guid for this formset + // + CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID)); + break; + } + + Index = RawData[Index + 1] + Index; + } + // + // If there is no string package, and the PackageInstance->IfrPack.Guid and PackageInstance->Guid are + // different, we should return the correct handle for the caller to use for strings. + // + if ((PackageInstance->StringSize == 0) && (!CompareGuid (&Guid, &PackageInstance->Guid))) { + // + // Search the database for a handle that matches the PackageInstance->Guid + // + for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { + // + // Get Ifrdata and extract the Guid for it + // + HandlePackageInstance = HandleDatabase->Buffer; + + ASSERT (HandlePackageInstance->IfrSize != 0); + + FormPack = (EFI_HII_IFR_PACK *) ((CHAR8 *) (&HandlePackageInstance->IfrData) + sizeof (EFI_HII_PACK_HEADER)); + RawData = (UINT8 *) FormPack; + + for (Index = 0; RawData[Index] != EFI_IFR_END_FORM_SET_OP;) { + if (RawData[Index] == EFI_IFR_FORM_SET_OP) { + // + // Cache the guid for this formset + // + CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &RawData[Index])->Guid, sizeof (EFI_GUID)); + break; + } + + Index = RawData[Index + 1] + Index; + } + // + // If the Guid from the new handle matches the original Guid referenced in the original package data + // return the appropriate package instance data to use. + // + if (CompareGuid (&Guid, &PackageInstance->Guid)) { + if (TotalStringCount != NULL) { + *TotalStringCount = HandleDatabase->NumberOfTokens; + } + + *StringPackageInstance = HandlePackageInstance; + } + } + // + // end for + // + } else { + return EFI_SUCCESS; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiNewPack ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACKAGES *Packages, + OUT EFI_HII_HANDLE *Handle + ) +/*++ + +Routine Description: + + Extracts the various packs from a package list. + +Arguments: + + This - Pointer of HII protocol. + Packages - Pointer of HII packages. + Handle - Handle value to be returned. + +Returns: + + EFI_SUCCESS - Pacakges has added to HII database successfully. + EFI_INVALID_PARAMETER - Invalid parameter. + +--*/ +{ + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_HANDLE_DATABASE *Database; + EFI_HII_PACK_HEADER *PackageHeader; + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HII_IFR_PACK *IfrPack; + EFI_HII_STRING_PACK *StringPack; + EFI_HII_FONT_PACK *FontPack; + EFI_HII_KEYBOARD_PACK *KeyboardPack; + EFI_STATUS Status; + UINTN IfrSize; + UINTN StringSize; + UINTN TotalStringSize; + UINTN InstanceSize; + UINTN Count; + UINTN Index; + UINT16 Member; + EFI_GUID Guid; + EFI_FORM_SET_STUB FormSetStub; + UINT8 *Location; + UINT16 Unicode; + UINT16 NumWideGlyphs; + UINT16 NumNarrowGlyphs; + UINT32 NumberOfTokens; + UINT32 TotalTokenNumber; + UINT8 *Local; + EFI_NARROW_GLYPH *NarrowGlyph; + EFI_WIDE_GLYPH *WideGlyph; + + if (Packages->NumberOfPackages == 0 || This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + GlobalData = HiiData->GlobalData; + + Database = HiiData->DatabaseHead; + + PackageInstance = NULL; + IfrPack = NULL; + StringPack = NULL; + InstanceSize = 0; + IfrSize = 0; + StringSize = 0; + TotalStringSize = 0; + NumberOfTokens = 0; + TotalTokenNumber = 0; + + // + // Search through the passed in Packages for the IfrPack and any StringPack. + // + for (Index = 0; Index < Packages->NumberOfPackages; Index++) { + + PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *)); + + switch (PackageHeader->Type) { + case EFI_HII_IFR: + // + // There shoule be only one Ifr package. + // + ASSERT (IfrPack == NULL); + IfrPack = (EFI_HII_IFR_PACK *) PackageHeader; + break; + + case EFI_HII_STRING: + StringPack = (EFI_HII_STRING_PACK *) PackageHeader; + // + // Sending me a String Package. Get its size. + // + Status = GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens); + ASSERT (!EFI_ERROR (Status)); + + // + // The size which GetPackSize() returns include the null terminator. So if multiple + // string packages are passed in, merge all these packages, and only pad one null terminator. + // + if (TotalStringSize > 0) { + TotalStringSize -= sizeof (EFI_HII_STRING_PACK); + } + + TotalStringSize += StringSize; + TotalTokenNumber += NumberOfTokens; + break; + } + } + // + // If sending a StringPack without an IfrPack, you must include a GuidId + // + if ((StringPack != NULL) && (IfrPack == NULL)) { + if (Packages->GuidId == NULL) { + return EFI_INVALID_PARAMETER; + } + } + // + // If passing in an IfrPack and a GuidId is provided, ensure they are the same value. + // + if ((IfrPack != NULL) && (Packages->GuidId != NULL)) { + Location = ((UINT8 *) IfrPack); + Location = (UINT8 *) (((UINTN) Location) + sizeof (EFI_HII_PACK_HEADER)); + + // + // Advance to the Form Set Op-code + // + for (Count = 0; ((EFI_IFR_OP_HEADER *) &Location[Count])->OpCode != EFI_IFR_FORM_SET_OP;) { + Count = Count + ((EFI_IFR_OP_HEADER *) &Location[Count])->Length; + } + // + // Copy to local variable + // + CopyMem (&Guid, &((EFI_IFR_FORM_SET *) &Location[Count])->Guid, sizeof (EFI_GUID)); + + // + // Check to see if IfrPack->Guid != GuidId + // + if (!CompareGuid (&Guid, Packages->GuidId)) { + // + // If a string package is present, the GUIDs should have agreed. Return an error + // + if (StringPack != NULL) { + return EFI_INVALID_PARAMETER; + } + } + } + // + // If someone is passing in a string only, create a dummy IfrPack with a Guid + // to enable future searching of this data. + // + if ((IfrPack == NULL) && (StringPack != NULL)) { + ZeroMem (&FormSetStub, sizeof (FormSetStub)); + + FormSetStub.Header.Type = EFI_HII_IFR; + FormSetStub.Header.Length = sizeof (EFI_FORM_SET_STUB); + + FormSetStub.FormSet.Header.OpCode = EFI_IFR_FORM_SET_OP; + FormSetStub.FormSet.Header.Length = (UINT8) sizeof (EFI_IFR_FORM_SET); + // + // Dummy string + // + FormSetStub.FormSet.FormSetTitle = 0x02; + CopyMem (&FormSetStub.FormSet.Guid, Packages->GuidId, sizeof (EFI_GUID)); + + FormSetStub.EndFormSet.Header.OpCode = EFI_IFR_END_FORM_SET_OP; + FormSetStub.EndFormSet.Header.Length = (UINT8) sizeof (EFI_IFR_END_FORM_SET); + IfrPack = (EFI_HII_IFR_PACK *) &FormSetStub; + } + + if (IfrPack != NULL) { + // + // Sending me an IFR Package. Get its size. + // + Status = GetPackSize ((VOID *) IfrPack, &IfrSize, NULL); + ASSERT (!EFI_ERROR (Status)); + } + // + // Prepare the internal package instace buffer to store package data. + // + InstanceSize = IfrSize + TotalStringSize; + + if (InstanceSize != 0) { + PackageInstance = AllocateZeroPool (InstanceSize + sizeof (EFI_HII_PACKAGE_INSTANCE)); + + ASSERT (PackageInstance); + + // + // If there is no DatabaseHead allocated - allocate one + // + if (HiiData->DatabaseHead == NULL) { + HiiData->DatabaseHead = AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE)); + ASSERT (HiiData->DatabaseHead); + } + // + // If the head is being used (Handle is non-zero), allocate next Database and + // add it to the linked-list + // + if (HiiData->DatabaseHead->Handle != 0) { + HandleDatabase = AllocateZeroPool (sizeof (EFI_HII_HANDLE_DATABASE)); + + ASSERT (HandleDatabase); + + for (; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase) + ; + + // + // We are sitting on the Database entry which contains the null Next pointer. Fix it. + // + Database->NextHandleDatabase = HandleDatabase; + + } + + Database = HiiData->DatabaseHead; + + // + // Initialize this instance data + // + for (*Handle = 1; Database->NextHandleDatabase != NULL; Database = Database->NextHandleDatabase) { + // + // Since the first Database instance will have a passed back handle of 1, we will continue + // down the linked list of entries until we encounter the end of the linked list. Each time + // we go down one level deeper, increment the handle value that will be passed back. + // + if (Database->Handle >= *Handle) { + *Handle = Database->Handle + 1; + } + } + + PackageInstance->Handle = *Handle; + PackageInstance->IfrSize = IfrSize; + PackageInstance->StringSize = TotalStringSize; + if (Packages->GuidId != NULL) { + CopyMem (&PackageInstance->Guid, Packages->GuidId, sizeof (EFI_GUID)); + } + + Database->Buffer = PackageInstance; + Database->Handle = PackageInstance->Handle; + Database->NumberOfTokens = TotalTokenNumber; + Database->NextHandleDatabase = NULL; + } + // + // Copy the Ifr package data into package instance. + // + if (IfrSize > 0) { + CopyMem (&PackageInstance->IfrData, IfrPack, IfrSize); + } + // + // Main loop to store package data into HII database. + // + StringSize = 0; + TotalStringSize = 0; + + for (Index = 0; Index < Packages->NumberOfPackages; Index++) { + + PackageHeader = *(EFI_HII_PACK_HEADER **) (((UINT8 *) Packages) + sizeof (EFI_HII_PACKAGES) + Index * sizeof (VOID *)); + + switch (PackageHeader->Type) { + case EFI_HII_STRING: + StringPack = (EFI_HII_STRING_PACK *) PackageHeader; + // + // The size which GetPackSize() returns include the null terminator. So if multiple + // string packages are passed in, merge all these packages, and only pad one null terminator. + // + if (TotalStringSize > 0) { + TotalStringSize -= sizeof (EFI_HII_STRING_PACK); + } + + GetPackSize ((VOID *) StringPack, &StringSize, &NumberOfTokens); + CopyMem ((CHAR8 *) (&PackageInstance->IfrData) + IfrSize + TotalStringSize, StringPack, StringSize); + + TotalStringSize += StringSize; + break; + + case EFI_HII_HANDLES: + CopyMem (&PackageInstance->HandlePack, PackageHeader, sizeof (EFI_HII_HANDLE_PACK)); + break; + + case EFI_HII_FONT: + FontPack = (EFI_HII_FONT_PACK *) PackageHeader; + // + // Add whatever narrow glyphs were passed to us if undefined + // + CopyMem (&NumNarrowGlyphs, &FontPack->NumberOfNarrowGlyphs, sizeof (UINT16)); + for (Count = 0; Count <= NumNarrowGlyphs; Count++) { + Local = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) + (sizeof (EFI_NARROW_GLYPH)) * Count; + NarrowGlyph = (EFI_NARROW_GLYPH *) Local; + CopyMem (&Member, &NarrowGlyph->UnicodeWeight, sizeof (UINT16)); + // + // If the glyph is already defined, do not overwrite it. It is what it is. + // + CopyMem (&Unicode, &GlobalData->NarrowGlyphs[Member].UnicodeWeight, sizeof (UINT16)); + if (Unicode == 0) { + CopyMem (&GlobalData->NarrowGlyphs[Member], Local, sizeof (EFI_NARROW_GLYPH)); + } + } + // + // Add whatever wide glyphs were passed to us if undefined + // + CopyMem (&NumWideGlyphs, &FontPack->NumberOfWideGlyphs, sizeof (UINT16)); + for (Count = 0; Count <= NumWideGlyphs; Count++) { + Local = (UINT8 *) (&FontPack->NumberOfWideGlyphs + sizeof (UINT8)) + + (sizeof (EFI_NARROW_GLYPH)) * + NumNarrowGlyphs; + WideGlyph = (EFI_WIDE_GLYPH *) Local; + CopyMem ( + &Member, + (UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count), + sizeof (UINT16) + ); + // + // If the glyph is already defined, do not overwrite it. It is what it is. + // + CopyMem (&Unicode, &GlobalData->WideGlyphs[Member].UnicodeWeight, sizeof (UINT16)); + if (Unicode == 0) { + Local = (UINT8*)(&FontPack->NumberOfWideGlyphs + sizeof(UINT8)) + (sizeof(EFI_NARROW_GLYPH)) * NumNarrowGlyphs; + WideGlyph = (EFI_WIDE_GLYPH *) Local; + CopyMem ( + &GlobalData->WideGlyphs[Member], + (UINTN *) (Local + sizeof (EFI_WIDE_GLYPH) * Count), + sizeof (EFI_WIDE_GLYPH) + ); + } + } + break; + + case EFI_HII_KEYBOARD: + KeyboardPack = (EFI_HII_KEYBOARD_PACK *) PackageHeader; + // + // Sending me a Keyboard Package + // + if (KeyboardPack->DescriptorCount > 105) { + return EFI_INVALID_PARAMETER; + } + // + // If someone updates the Descriptors with a count of 0, blow aware the overrides. + // + if (KeyboardPack->DescriptorCount == 0) { + ZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106); + } + + if (KeyboardPack->DescriptorCount < 106 && KeyboardPack->DescriptorCount > 0) { + // + // If SystemKeyboard was updated already, then steer changes to the override database + // + if (GlobalData->SystemKeyboardUpdate) { + ZeroMem (GlobalData->OverrideKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106); + for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) { + CopyMem (&Member, &KeyboardPack->Descriptor[Count].Key, sizeof (UINT16)); + CopyMem ( + &GlobalData->OverrideKeyboardLayout[Member], + &KeyboardPack->Descriptor[Count], + sizeof (EFI_KEY_DESCRIPTOR) + ); + } + } else { + // + // SystemKeyboard was never updated, so this is likely the keyboard driver setting the System database. + // + ZeroMem (GlobalData->SystemKeyboardLayout, sizeof (EFI_KEY_DESCRIPTOR) * 106); + for (Count = 0; Count < KeyboardPack->DescriptorCount; Count++) { + CopyMem (&Member, &KeyboardPack->Descriptor->Key, sizeof (UINT16)); + CopyMem ( + &GlobalData->SystemKeyboardLayout[Member], + &KeyboardPack->Descriptor[Count], + sizeof (EFI_KEY_DESCRIPTOR) + ); + } + // + // Just updated the system keyboard database, reflect that in the global flag. + // + GlobalData->SystemKeyboardUpdate = TRUE; + } + } + break; + + default: + break; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiRemovePack ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ) +/*++ + +Routine Description: + Removes the various packs from a Handle + +Arguments: + +Returns: + +--*/ +{ + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_HANDLE_DATABASE *PreviousHandleDatabase; + UINTN Count; + + if (This == NULL || Handle == 0) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + HandleDatabase = HiiData->DatabaseHead; + PackageInstance = NULL; + + // + // Initialize the Previous with the Head of the Database + // + PreviousHandleDatabase = HandleDatabase; + + for (Count = 0; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { + // + // Match the numeric value with the database entry - if matched, + // free the package instance and apply fix-up to database linked list + // + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + + // + // Free the Package Instance + // + gBS->FreePool (PackageInstance); + + // + // If this was the only Handle in the database + // + if (HiiData->DatabaseHead == HandleDatabase) { + HiiData->DatabaseHead = NULL; + } + // + // Make the parent->Next point to the current->Next + // + PreviousHandleDatabase->NextHandleDatabase = HandleDatabase->NextHandleDatabase; + gBS->FreePool (HandleDatabase); + return EFI_SUCCESS; + } + // + // If this was not the HandleDatabase entry we were looking for, cache it just in case the next one is + // + PreviousHandleDatabase = HandleDatabase; + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Strings.c b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Strings.c new file mode 100644 index 0000000000..742a01dc43 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/Strings.c @@ -0,0 +1,1276 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Strings.c + +Abstract: + + This file contains the string processing code to the HII database. + +--*/ + + +#include "HiiDatabase.h" + +VOID +AsciiToUnicode ( + IN UINT8 *Lang, + IN UINT16 *Language + ) +{ + UINT8 Count; + + // + // Convert the ASCII Lang variable to a Unicode Language variable + // + for (Count = 0; Count < 3; Count++) { + Language[Count] = (CHAR16) Lang[Count]; + } +} + +EFI_STATUS +EFIAPI +HiiTestString ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *StringToTest, + IN OUT UINT32 *FirstMissing, + OUT UINT32 *GlyphBufferSize + ) +/*++ + +Routine Description: + Test if all of the characters in a string have corresponding font characters. + +Arguments: + +Returns: + +--*/ +{ + EFI_HII_GLOBAL_DATA *GlobalData; + EFI_HII_DATA *HiiData; + UINTN Count; + BOOLEAN Narrow; + UINTN Location; + UINT8 GlyphCol1[19]; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + GlobalData = HiiData->GlobalData; + Count = 0; + Narrow = TRUE; + + ZeroMem (GlyphCol1, sizeof (GlyphCol1)); + + // + // Walk through the string until you hit the null terminator + // + for (; StringToTest[*FirstMissing] != 0x00; (*FirstMissing)++) { + Location = *FirstMissing; + // + // Rewind through the string looking for a glyph width identifier + // + for (; Location != 0; Location--) { + if (StringToTest[Location] == NARROW_CHAR || StringToTest[Location] == WIDE_CHAR) { + // + // We found something that identifies what glyph database to look in + // + if (StringToTest[Location] == WIDE_CHAR) { + Narrow = FALSE; + } else { + Narrow = TRUE; + } + } + } + + if (Narrow) { + if (CompareMem ( + GlobalData->NarrowGlyphs[StringToTest[*FirstMissing]].GlyphCol1, + &mUnknownGlyph, + NARROW_GLYPH_ARRAY_SIZE + ) == 0 + ) { + // + // Break since this glyph isn't defined + // + return EFI_NOT_FOUND; + } + } else { + // + // Can compare wide glyph against only GlyphCol1 since GlyphCol1 and GlyphCol2 are contiguous - just give correct size + // + if (CompareMem ( + GlobalData->WideGlyphs[StringToTest[*FirstMissing]].GlyphCol1, + &mUnknownGlyph, + WIDE_GLYPH_ARRAY_SIZE + ) == 0 + ) { + // + // Break since this glyph isn't defined + // + return EFI_NOT_FOUND; + } + } + + Count++; + } + + if (Narrow) { + *GlyphBufferSize = (UINT32) (Count * sizeof (EFI_NARROW_GLYPH)); + } else { + *GlyphBufferSize = (UINT32) (Count * sizeof (EFI_WIDE_GLYPH)); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +HiiNewString2 ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Language, + IN EFI_HII_HANDLE Handle, + IN OUT STRING_REF *Reference, + IN CHAR16 *NewString, + IN BOOLEAN ResetStrings + ) +/*++ + +Routine Description: + + This function allows a new String to be added to an already existing String Package. + We will make a buffer the size of the package + EfiStrSize of the new string. We will + copy the string package that first gets changed and the following language packages until + we encounter the NULL string package. All this time we will ensure that the offsets have + been adjusted. + +Arguments: + + This - Pointer to the HII protocol. + Language - Pointer to buffer which contains the language code of this NewString. + Handle - Handle of the package instance to be processed. + Reference - The token number for the string. If 0, new string token to be returned through this parameter. + NewString - Buffer pointer for the new string. + ResetStrings - Indicate if we are resetting a string. + +Returns: + + EFI_SUCCESS - The string has been added or reset to Hii database. + EFI_INVALID_PARAMETER - Some parameter passed in is invalid. + +--*/ +{ + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_PACKAGE_INSTANCE *StringPackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_STRING_PACK *StringPack; + EFI_HII_STRING_PACK *NewStringPack; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_PACKAGE_INSTANCE *NewBuffer; + UINT8 *Location; + UINT8 *StringLocation; + RELOFST *StringPointer; + UINTN Count; + UINTN Size; + UINTN Index; + UINTN SecondIndex; + BOOLEAN AddString; + EFI_STATUS Status; + UINTN Increment; + UINTN StringCount; + UINT32 TotalStringCount; + UINT32 OriginalStringCount; + RELOFST StringSize; + UINT32 Length; + RELOFST Offset; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + HandleDatabase = HiiData->DatabaseHead; + PackageInstance = NULL; + AddString = FALSE; + Increment = 0; + StringCount = 0; + TotalStringCount = 0; + OriginalStringCount = 0; + + // + // Check numeric value against the head of the database + // + for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { + // + // Match the numeric value with the database entry - if matched, extract PackageInstance + // + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + if (ResetStrings) { + TotalStringCount = HandleDatabase->NumberOfTokens; + } + break; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = ValidatePack (This, PackageInstance, &StringPackageInstance, &TotalStringCount); + + // + // This sets Count to 0 or the size of the IfrData. We intend to use Count as an offset value + // + Count = StringPackageInstance->IfrSize; + + // + // This is the size of the complete series of string packs + // + Size = StringPackageInstance->StringSize; + + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (StringPackageInstance->IfrSize > 0) { + Location = (UINT8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize; + } else { + Location = (UINT8 *) (&StringPackageInstance->IfrData); + } + // + // We allocate a buffer which is big enough for both adding and resetting string. + // The size is slightly larger than the real size of the packages when we are resetting a string. + // + NewBuffer = AllocateZeroPool ( + sizeof (EFI_HII_PACKAGE_INSTANCE) - + 2 * sizeof (VOID *) + + StringPackageInstance->IfrSize + + StringPackageInstance->StringSize + + sizeof (RELOFST) + + StrSize (NewString) + ); + ASSERT (NewBuffer); + + // + // Copy data to new buffer + // + NewBuffer->Handle = StringPackageInstance->Handle; + NewBuffer->IfrSize = StringPackageInstance->IfrSize; + + // + // The worst case scenario for sizing is that we are adding a new string (not replacing one) and there was not a string + // package to begin with. + // + NewBuffer->StringSize = StringPackageInstance->StringSize + StrSize (NewString) + sizeof (EFI_HII_STRING_PACK); + + if (StringPackageInstance->IfrSize > 0) { + CopyMem (&NewBuffer->IfrData, &StringPackageInstance->IfrData, StringPackageInstance->IfrSize); + } + + StringPack = (EFI_HII_STRING_PACK *) Location; + + // + // There may be multiple instances packed together of strings + // so we must walk the self describing structures until we encounter + // what we are looking for. In the meantime, copy everything we encounter + // to the new buffer. + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (; Length != 0;) { + // + // If passed in Language ISO value is in this string pack's language string + // then we are dealing with the strings we want. + // + CopyMem (&Offset, &StringPack->LanguageNameString, sizeof (RELOFST)); + Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + Offset), Language); + + if (!EFI_ERROR (Status)) { + break; + } + + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, Length); + + Count = Count + Length; + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + } + // + // Found the language pack to update on a particular handle + // We need to Copy the Contents of this pack and adjust the offset values associated + // with adding/changing a string. This is a particular piece of code that screams for + // it being prone to programming error. + // + // + // Copy the string package up to the string data + // + StringPointer = (RELOFST *) (StringPack + 1); + CopyMem ( + ((CHAR8 *) (&NewBuffer->IfrData) + Count), + StringPack, + (UINTN) ((UINTN) (StringPointer) - (UINTN) (StringPack)) + ); + + // + // Determine the number of StringPointers + // + if (!ResetStrings) { + CopyMem (&TotalStringCount, &StringPack->NumStringPointers, sizeof (RELOFST)); + } else { + // + // If we are resetting the strings, use the original value when exported + // + CopyMem (&OriginalStringCount, &StringPack->NumStringPointers, sizeof (RELOFST)); + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->LanguageNameString -= + ( + (RELOFST) (OriginalStringCount - TotalStringCount) * + sizeof (RELOFST) + ); + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->PrintableLanguageName -= + ( + (RELOFST) (OriginalStringCount - TotalStringCount) * + sizeof (RELOFST) + ); + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->NumStringPointers = TotalStringCount; + *Reference = (STRING_REF) (TotalStringCount); + } + // + // If the token value is not valid, error out + // + if ((*Reference >= TotalStringCount) && !ResetStrings) { + gBS->FreePool (NewBuffer); + return EFI_INVALID_PARAMETER; + } + // + // If Reference is 0, update it with what the new token reference will be and turn the AddString flag on + // + if (*Reference == 0) { + *Reference = (STRING_REF) (TotalStringCount); + AddString = TRUE; + } + + if (AddString) { + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->LanguageNameString += sizeof (RELOFST); + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->PrintableLanguageName += sizeof (RELOFST); + ((EFI_HII_STRING_PACK *) ((CHAR8 *) (&NewBuffer->IfrData) + Count))->NumStringPointers++; + } + // + // Increment offset by amount of copied data + // + Count = Count + ((UINTN) (StringPointer) - (UINTN) StringPack); + + for (Index = 0; Index < TotalStringCount; Index++) { + // + // If we are pointing to the size of the changing string value + // then cache the old string value so you know what the difference is + // + if (Index == *Reference) { + CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST)); + + StringLocation = ((UINT8 *) (StringPack) + Offset); + for (SecondIndex = 0; + (StringLocation[SecondIndex] != 0) || (StringLocation[SecondIndex + 1] != 0); + SecondIndex = SecondIndex + 2 + ) + ; + SecondIndex = SecondIndex + 2; + + Size = SecondIndex; + + // + // NewString is a passed in local string which is assumed to be aligned + // + Size = StrSize (NewString) - Size; + } + // + // If we are about to copy the offset of the string that follows the changed string make + // sure that the offsets are adjusted accordingly + // + if ((Index > *Reference) && !ResetStrings) { + CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST)); + Offset = (RELOFST) (Offset + Size); + CopyMem (&StringPointer[Index], &Offset, sizeof (RELOFST)); + } + // + // If we are adding a string that means we will have an extra string pointer that will affect all string offsets + // + if (AddString) { + CopyMem (&Offset, &StringPointer[Index], sizeof (RELOFST)); + Offset = (UINT32) (Offset + sizeof (RELOFST)); + CopyMem (&StringPointer[Index], &Offset, sizeof (RELOFST)); + } + // + // If resetting the strings, we need to reduce the offset by the difference in the strings + // + if (ResetStrings) { + CopyMem (&Length, &StringPointer[Index], sizeof (RELOFST)); + Length = Length - ((RELOFST) (OriginalStringCount - TotalStringCount) * sizeof (RELOFST)); + CopyMem (&StringPointer[Index], &Length, sizeof (RELOFST)); + } + // + // Notice that if the string was being added as a new token, we don't have to worry about the + // offsets changing in the other indexes + // + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), &StringPointer[Index], sizeof (RELOFST)); + Count = Count + sizeof (RELOFST); + StringCount++; + } + // + // If we are adding a new string the above for loop did not copy the offset for us + // + if (AddString) { + // + // Since the Index is pointing to the beginning of the first string, we need to gather the size of the previous + // offset's string and create an offset to our new string. + // + CopyMem (&Offset, &StringPointer[Index - 1], sizeof (RELOFST)); + StringLocation = (UINT8 *) StringPack; + StringLocation = StringLocation + Offset - sizeof (RELOFST); + + // + // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues + // + for (Length = 0; + (StringLocation[Length] != 0) || (StringLocation[Length + 1] != 0); + Length = (RELOFST) (Length + 2) + ) + ; + Length = (RELOFST) (Length + 2); + + StringSize = (RELOFST) (Offset + Length); + + // + // Copy the new string offset + // + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), &StringSize, sizeof (RELOFST)); + Count = Count + sizeof (RELOFST); + + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + Length = Length + sizeof (RELOFST); + CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32)); + } + // + // Set Location to the First String + // + if (ResetStrings) { + Index = OriginalStringCount; + } + // + // Set Location to the First String + // + Location = (UINT8 *) &StringPointer[Index]; + Index = 0; + + // + // Keep copying strings until you run into two CHAR16's in a row that are NULL + // + do { + if ((*Reference == Increment) && !AddString) { + StringLocation = ((UINT8 *) (&NewBuffer->IfrData) + Count); + CopyMem (StringLocation, NewString, StrSize (NewString)); + + // + // Advance the destination location by Count number of bytes + // + Count = Count + StrSize (NewString); + + // + // Add the difference between the new string and the old string to the length + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + + // + // Since StringPack is a packed structure, we need to size it carefully (byte-wise) to avoid alignment issues + // + StringLocation = (UINT8 *) &Location[Index]; + for (Offset = 0; + (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0); + Offset = (RELOFST) (Offset + 2) + ) + ; + Offset = (RELOFST) (Offset + 2); + + Length = Length + (UINT32) StrSize (NewString) - Offset; + + CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32)); + } else { + StringLocation = (UINT8 *) &Location[Index]; + for (Offset = 0; + (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0); + Offset = (RELOFST) (Offset + 2) + ) + ; + Offset = (RELOFST) (Offset + 2); + + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringLocation, Offset); + + // + // Advance the destination location by Count number of bytes + // + Count = Count + Offset; + } + // + // Retrieve the number of characters to advance the index - should land at beginning of next string + // + Index = Index + Offset; + Increment++; + StringCount--; + Offset = 0; + } while (StringCount > 0); + + // + // If we are adding a new string, then the above do/while will not suffice + // + if (AddString) { + Offset = (RELOFST) StrSize (NewString); + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), NewString, Offset); + + Count = Count + StrSize (NewString); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + Length = Length + (UINT32) StrSize (NewString); + CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32)); + } + + if (ResetStrings) { + // + // Skip the remainder of strings in the string package + // + StringCount = OriginalStringCount - TotalStringCount; + + while (StringCount > 0) { + StringLocation = (UINT8 *) &Location[Index]; + for (Offset = 0; + (StringLocation[Offset] != 0) || (StringLocation[Offset + 1] != 0); + Offset = (RELOFST) (Offset + 2) + ) + ; + Offset = (RELOFST) (Offset + 2); + Index = Index + Offset; + StringCount--; + + // + // Adjust the size of the string pack by the string size we just skipped. + // Also reduce the length by the size of a RelativeOffset value since we + // obviously would have skipped that as well. + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + Length = Length - Offset - sizeof (RELOFST); + CopyMem (&StringPack->Header.Length, &Length, sizeof (UINT32)); + } + } + + StringPack = (EFI_HII_STRING_PACK *) &Location[Index]; + + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (; Length != 0;) { + + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, Length); + + Count = Count + Length; + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + } + // + // Copy the null terminator to the new buffer + // + CopyMem (((CHAR8 *) (&NewBuffer->IfrData) + Count), StringPack, sizeof (EFI_HII_STRING_PACK)); + + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (StringPackageInstance->IfrSize > 0) { + Location = (UINT8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize; + StringPack = (EFI_HII_STRING_PACK *) Location; + Location = (UINT8 *) (&NewBuffer->IfrData) + NewBuffer->IfrSize; + NewStringPack = (EFI_HII_STRING_PACK *) Location; + } else { + StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData); + NewStringPack = (EFI_HII_STRING_PACK *) (&NewBuffer->IfrData); + } + + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (; Length != 0;) { + // + // Since we updated the old version of the string data as we moved things over + // And we had a chicken-egg problem with the data we copied, let's post-fix the new + // buffer with accurate length data. + // + CopyMem (&Count, &NewStringPack->Header.Length, sizeof (UINT32)); + CopyMem (&NewStringPack->Header.Length, &StringPack->Header.Length, sizeof (UINT32)); + CopyMem (&StringPack->Header.Length, &Count, sizeof (UINT32)); + + CopyMem (&Count, &NewStringPack->Header.Length, sizeof (UINT32)); + NewStringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (NewStringPack) + Count); + CopyMem (&Count, &StringPack->Header.Length, sizeof (UINT32)); + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Count); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + } + + GetPackSize ((VOID *) ((CHAR8 *) (&NewBuffer->IfrData) + NewBuffer->IfrSize), &NewBuffer->StringSize, NULL); + + // + // Search through the handles until the requested handle is found. + // + for (HandleDatabase = HiiData->DatabaseHead; + HandleDatabase->Handle != 0; + HandleDatabase = HandleDatabase->NextHandleDatabase + ) { + if (HandleDatabase->Handle == StringPackageInstance->Handle) { + // + // Free the previous buffer associated with this handle, and assign the new buffer to the handle + // + gBS->FreePool (HandleDatabase->Buffer); + HandleDatabase->Buffer = NewBuffer; + break; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiNewString ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Language, + IN EFI_HII_HANDLE Handle, + IN OUT STRING_REF *Reference, + IN CHAR16 *NewString + ) +/*++ + +Routine Description: + This function allows a new String to be added to an already existing String Package. + We will make a buffer the size of the package + StrSize of the new string. We will + copy the string package that first gets changed and the following language packages until + we encounter the NULL string package. All this time we will ensure that the offsets have + been adjusted. + +Arguments: + +Returns: + +--*/ +{ + UINTN Index; + CHAR16 *LangCodes; + CHAR16 Lang[4]; + STRING_REF OriginalValue; + EFI_STATUS Status; + + // + // To avoid a warning 4 uninitialized variable warning + // + Status = EFI_SUCCESS; + + Status = HiiGetPrimaryLanguages ( + This, + Handle, + &LangCodes + ); + + if (!EFI_ERROR (Status)) { + OriginalValue = *Reference; + + if (Language == NULL) { + for (Index = 0; LangCodes[Index] != 0; Index += 3) { + *Reference = OriginalValue; + CopyMem (Lang, &LangCodes[Index], 6); + Lang[3] = 0; + Status = HiiNewString2 ( + This, + Lang, + Handle, + Reference, + NewString, + FALSE + ); + + } + } else { + Status = HiiNewString2 ( + This, + Language, + Handle, + Reference, + NewString, + FALSE + ); + } + + gBS->FreePool (LangCodes); + } + + return Status; +} + +EFI_STATUS +EFIAPI +HiiResetStrings ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ) +/*++ + +Routine Description: + + This function removes any new strings that were added after the initial string export for this handle. + +Arguments: + +Returns: + +--*/ +{ + UINTN Index; + CHAR16 *LangCodes; + CHAR16 Lang[4]; + STRING_REF Reference; + CHAR16 NewString; + EFI_STATUS Status; + + Reference = 1; + NewString = 0; + + HiiGetPrimaryLanguages ( + This, + Handle, + &LangCodes + ); + + for (Index = 0; LangCodes[Index] != 0; Index += 3) { + CopyMem (Lang, &LangCodes[Index], 6); + Lang[3] = 0; + Status = HiiNewString2 ( + This, + Lang, + Handle, + &Reference, + &NewString, + TRUE + ); + + } + + gBS->FreePool (LangCodes); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +HiiGetString ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN BOOLEAN Raw, + IN CHAR16 *LanguageString, + IN OUT UINTN *BufferLengthTemp, + OUT EFI_STRING StringBuffer + ) +/*++ + +Routine Description: + + This function extracts a string from a package already registered with the EFI HII database. + +Arguments: + This - A pointer to the EFI_HII_PROTOCOL instance. + Handle - The HII handle on which the string resides. + Token - The string token assigned to the string. + Raw - If TRUE, the string is returned unedited in the internal storage format described + above. If false, the string returned is edited by replacing with + and by removing special characters such as the prefix. + LanguageString - Pointer to a NULL-terminated string containing a single ISO 639-2 language + identifier, indicating the language to print. If the LanguageString is empty (starts + with a NULL), the default system language will be used to determine the language. + BufferLength - Length of the StringBuffer. If the status reports that the buffer width is too + small, this parameter is filled with the length of the buffer needed. + StringBuffer - The buffer designed to receive the characters in the string. Type EFI_STRING is + defined in String. + +Returns: + EFI_INVALID_PARAMETER - If input parameter is invalid. + EFI_BUFFER_TOO_SMALL - If the *BufferLength is too small. + EFI_SUCCESS - Operation is successful. + +--*/ +{ + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_PACKAGE_INSTANCE *StringPackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_STRING_PACK *StringPack; + RELOFST *StringPointer; + EFI_STATUS Status; + UINTN DataSize; + CHAR8 Lang[3]; + CHAR16 Language[3]; + UINT32 Length; + UINTN Count; + RELOFST Offset; + UINT16 *Local; + UINT16 Zero; + UINT16 Narrow; + UINT16 Wide; + UINT16 NoBreak; + BOOLEAN LangFound; + UINT16 *BufferLength = (UINT16 *) BufferLengthTemp; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + LangFound = TRUE; + + DataSize = sizeof (Lang); + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + PackageInstance = NULL; + Zero = 0; + Narrow = NARROW_CHAR; + Wide = WIDE_CHAR; + NoBreak = NON_BREAKING_CHAR; + + // + // Check numeric value against the head of the database + // + for (HandleDatabase = HiiData->DatabaseHead; + HandleDatabase != NULL; + HandleDatabase = HandleDatabase->NextHandleDatabase + ) { + // + // Match the numeric value with the database entry - if matched, extract PackageInstance + // + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + break; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = ValidatePack (This, PackageInstance, &StringPackageInstance, NULL); + + // + // If there is no specified language, assume the system default language + // + if (LanguageString == NULL) { + // + // Get system default language + // + Status = gRT->GetVariable ( + (CHAR16 *) L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + Lang + ); + + if (EFI_ERROR (Status)) { + // + // If Lang doesn't exist, just use the first language you find + // + LangFound = FALSE; + goto LangNotFound; + } + // + // Convert the ASCII Lang variable to a Unicode Language variable + // + AsciiToUnicode ((UINT8 *)Lang, Language); + } else { + // + // Copy input ISO value to Language variable + // + CopyMem (Language, LanguageString, 6); + } + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // +LangNotFound: + if (StringPackageInstance->IfrSize > 0) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize); + } else { + StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData); + } + // + // If Token is 0, extract entire string package + // + if (Token == 0) { + // + // Compute the entire string pack length, including all languages' and the terminating pack's. + // + Length = 0; + while (0 != StringPack->Header.Length) { + Length += StringPack->Header.Length; + StringPack = (VOID*)(((UINT8*)StringPack) + StringPack->Header.Length); + } + // + // Back to the start of package. + // + StringPack = (VOID*)(((UINT8*)StringPack) - Length); + // + // Terminating zero sub-pack. + // + Length += sizeof (EFI_HII_STRING_PACK); + + // + // If trying to get the entire string package and have insufficient space. Return error. + // + if (Length > *BufferLength || StringBuffer == NULL) { + *BufferLength = (UINT16)Length; + return EFI_BUFFER_TOO_SMALL; + } + // + // Copy the Pack to the caller's buffer. + // + *BufferLength = (UINT16)Length; + CopyMem (StringBuffer, StringPack, Length); + + return EFI_SUCCESS; + } + // + // There may be multiple instances packed together of strings + // so we must walk the self describing structures until we encounter + // what we are looking for, and then extract the string we are looking for + // + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + for (; Length != 0;) { + // + // If passed in Language ISO value is in this string pack's language string + // then we are dealing with the strings we want. + // + CopyMem (&Offset, &StringPack->LanguageNameString, sizeof (RELOFST)); + Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + Offset), Language); + + // + // If we cannot find the lang variable, we skip this check and use the first language available + // + if (LangFound) { + if (EFI_ERROR (Status)) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + Length); + CopyMem (&Length, &StringPack->Header.Length, sizeof (UINT32)); + continue; + } + } + + StringPointer = (RELOFST *) (StringPack + 1); + + // + // We have the right string package - size it, and copy it to the StringBuffer + // + if (Token >= StringPack->NumStringPointers) { + return EFI_INVALID_PARAMETER; + } else { + CopyMem (&Offset, &StringPointer[Token], sizeof (RELOFST)); + } + // + // Since StringPack is a packed structure, we need to determine the string's + // size safely, thus byte-wise. Post-increment the size to include the null-terminator + // + Local = (UINT16 *) ((CHAR8 *) (StringPack) + Offset); + for (Count = 0; CompareMem (&Local[Count], &Zero, 2); Count++) + ; + Count++; + + Count = Count * sizeof (CHAR16);; + + if (*BufferLength >= Count && StringBuffer != NULL) { + // + // Copy the string to the user's buffer + // + if (Raw) { + CopyMem (StringBuffer, Local, Count); + } else { + for (Count = 0; CompareMem (Local, &Zero, 2); Local++) { + // + // Skip "Narraw, Wide, NoBreak" + // + if (CompareMem (Local, &Narrow, 2) && + CompareMem (Local, &Wide, 2) && + CompareMem (Local, &NoBreak, 2)) { + CopyMem (&StringBuffer[Count++], Local, 2); + } + } + // + // Add "NULL" at the end. + // + CopyMem (&StringBuffer[Count], &Zero, 2); + Count++; + Count *= sizeof (CHAR16); + } + + *BufferLength = (UINT16) Count; + return EFI_SUCCESS; + } else { + *BufferLength = (UINT16) Count; + return EFI_BUFFER_TOO_SMALL; + } + + } + + LangFound = FALSE; + goto LangNotFound; +} + +EFI_STATUS +EFIAPI +HiiGetLine ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN OUT UINT16 *Index, + IN UINT16 LineWidth, + IN CHAR16 *LanguageString, + IN OUT UINT16 *BufferLength, + OUT EFI_STRING StringBuffer + ) +/*++ + +Routine Description: + + This function allows a program to extract a part of a string of not more than a given width. + With repeated calls, this allows a calling program to extract "lines" of text that fit inside + columns. The effort of measuring the fit of strings inside columns is localized to this call. + +Arguments: + +Returns: + +--*/ +{ + UINTN Count; + EFI_HII_PACKAGE_INSTANCE *PackageInstance; + EFI_HII_PACKAGE_INSTANCE *StringPackageInstance; + EFI_HII_DATA *HiiData; + EFI_HII_HANDLE_DATABASE *HandleDatabase; + EFI_HII_STRING_PACK *StringPack; + RELOFST *StringPointer; + CHAR16 *Location; + EFI_STATUS Status; + UINTN DataSize; + CHAR8 Lang[3]; + CHAR16 Language[3]; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + HiiData = EFI_HII_DATA_FROM_THIS (This); + + HandleDatabase = HiiData->DatabaseHead; + + PackageInstance = NULL; + DataSize = 4; + + // + // Check numeric value against the head of the database + // + for (; HandleDatabase != NULL; HandleDatabase = HandleDatabase->NextHandleDatabase) { + // + // Match the numeric value with the database entry - if matched, extract PackageInstance + // + if (Handle == HandleDatabase->Handle) { + PackageInstance = HandleDatabase->Buffer; + } + } + // + // No handle was found - error condition + // + if (PackageInstance == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = ValidatePack (This, PackageInstance, &StringPackageInstance, NULL); + + // + // If there is no specified language, assume the system default language + // + if (LanguageString == NULL) { + // + // Get system default language + // + Status = gRT->GetVariable ( + (CHAR16 *) L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &DataSize, + Lang + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Convert the ASCII Lang variable to a Unicode Language variable + // + AsciiToUnicode ((UINT8 *)Lang, Language); + } else { + // + // Copy input ISO value to Language variable + // + CopyMem (Language, LanguageString, 6); + } + // + // Based on if there is IFR data in this package instance, determine + // what the location is of the beginning of the string data. + // + if (StringPackageInstance->IfrSize > 0) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (&StringPackageInstance->IfrData) + StringPackageInstance->IfrSize); + } else { + StringPack = (EFI_HII_STRING_PACK *) (&StringPackageInstance->IfrData); + } + + StringPointer = (RELOFST *) (StringPack + 1); + + // + // There may be multiple instances packed together of strings + // so we must walk the self describing structures until we encounter + // what we are looking for, and then extract the string we are looking for + // + for (; StringPack->Header.Length != 0;) { + // + // If passed in Language ISO value is in this string pack's language string + // then we are dealing with the strings we want. + // + Status = HiiCompareLanguage ((CHAR16 *) ((CHAR8 *) (StringPack) + StringPack->LanguageNameString), Language); + + if (EFI_ERROR (Status)) { + StringPack = (EFI_HII_STRING_PACK *) ((CHAR8 *) (StringPack) + StringPack->Header.Length); + continue; + } + + Location = (CHAR16 *) ((CHAR8 *) (StringPack) + StringPointer[Token] +*Index * 2); + + // + // If the size of the remaining string is less than the LineWidth + // then copy the entire thing + // + if (StrSize (Location) <= LineWidth) { + if (*BufferLength >= StrSize (Location)) { + StrCpy (StringBuffer, Location); + return EFI_SUCCESS; + } else { + *BufferLength = (UINT16) StrSize (Location); + return EFI_BUFFER_TOO_SMALL; + } + } else { + // + // Rewind the string from the maximum size until we see a space the break the line + // + for (Count = LineWidth; Location[Count] != 0x0020; Count--) + ; + + // + // Put the index at the next character + // + *Index = (UINT16) (Count + 1); + + if (*BufferLength >= Count) { + StrnCpy (StringBuffer, Location, Count); + return EFI_SUCCESS; + } else { + *BufferLength = (UINT16) Count; + return EFI_BUFFER_TOO_SMALL; + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +HiiCompareLanguage ( + IN CHAR16 *LanguageStringLocation, + IN CHAR16 *Language + ) +{ + UINT8 *Local; + UINTN Index; + CHAR16 *InputString; + CHAR16 *OriginalInputString; + + // + // Allocate a temporary buffer for InputString + // + InputString = AllocateZeroPool (0x100); + + ASSERT (InputString); + + OriginalInputString = InputString; + + Local = (UINT8 *) LanguageStringLocation; + + // + // Determine the size of this packed string safely (e.g. access by byte), post-increment + // to include the null-terminator + // + for (Index = 0; Local[Index] != 0; Index = Index + 2) + ; + // + // MARMAR Index = Index + 2; + // + // This is a packed structure that this location comes from, so let's make sure + // the value is aligned by copying it to a local variable and working on it. + // + CopyMem (InputString, LanguageStringLocation, Index); + + for (Index = 0; Index < 3; Index++) { + InputString[Index] = (CHAR16) (InputString[Index] | 0x20); + Language[Index] = (CHAR16) (Language[Index] | 0x20); + } + // + // If the Language is the same return success + // + if (CompareMem (LanguageStringLocation, Language, 6) == 0) { + gBS->FreePool (InputString); + return EFI_SUCCESS; + } + // + // Skip the first three letters that comprised the primary language, + // see if what is being compared against is a secondary language + // + InputString = InputString + 3; + + // + // If the Language is not the same as the Primary language, see if there are any + // secondary languages, and if there are see if we have a match. If not, return an error. + // + for (Index = 0; InputString[Index] != 0; Index = Index + 3) { + // + // Getting in here means we have a secondary language + // + if (CompareMem (&InputString[Index], Language, 6) == 0) { + gBS->FreePool (InputString); + return EFI_SUCCESS; + } + } + // + // If nothing was found, return the error + // + gBS->FreePool (OriginalInputString); + return EFI_NOT_FOUND; + +} diff --git a/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/build.xml b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/build.xml new file mode 100644 index 0000000000..7ffdb7c013 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/HiiDataBase/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Boolean.c b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Boolean.c new file mode 100644 index 0000000000..c7bcb88fb2 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Boolean.c @@ -0,0 +1,1360 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Boolean.c + +Abstract: + + This routine will evaluate the IFR inconsistency data to determine if + something is a valid entry for a particular expression + +--*/ + +#include "Setup.h" +#include "Ui.h" + +// +// Global stack used to evaluate boolean expresions +// +BOOLEAN *mBooleanEvaluationStack = (BOOLEAN) 0; +BOOLEAN *mBooleanEvaluationStackEnd = (BOOLEAN) 0; + +STATIC +VOID +GrowBooleanStack ( + IN OUT BOOLEAN **Stack, + IN UINTN StackSizeInBoolean + ) +/*++ + +Routine Description: + + Grow size of the boolean stack + +Arguments: + + Stack - Old stack on the way in and new stack on the way out + + StackSizeInBoolean - New size of the stack + +Returns: + + NONE + +--*/ +{ + BOOLEAN *NewStack; + + NewStack = AllocatePool (StackSizeInBoolean * sizeof (BOOLEAN)); + ASSERT (NewStack != NULL); + + if (*Stack != NULL) { + // + // Copy to Old Stack to the New Stack + // + CopyMem ( + NewStack, + mBooleanEvaluationStack, + (mBooleanEvaluationStackEnd - mBooleanEvaluationStack) * sizeof (BOOLEAN) + ); + + // + // Make the Stack pointer point to the old data in the new stack + // + *Stack = NewStack + (*Stack - mBooleanEvaluationStack); + + // + // Free The Old Stack + // + gBS->FreePool (mBooleanEvaluationStack); + } + + mBooleanEvaluationStack = NewStack; + mBooleanEvaluationStackEnd = NewStack + StackSizeInBoolean; +} + +VOID +InitializeBooleanEvaluator ( + VOID + ) +/*++ + +Routine Description: + + Allocate a global stack for boolean processing. + +Arguments: + + NONE + +Returns: + + NONE + +--*/ +{ + BOOLEAN *NullStack; + + NullStack = NULL; + GrowBooleanStack (&NullStack, 0x1000); +} + +STATIC +VOID +PushBool ( + IN OUT BOOLEAN **Stack, + IN BOOLEAN BoolResult + ) +/*++ + +Routine Description: + + Push an element onto the Boolean Stack + +Arguments: + + Stack - Current stack location. + BoolResult - BOOLEAN to push. + +Returns: + + None. + +--*/ +{ + CopyMem (*Stack, &BoolResult, sizeof (BOOLEAN)); + *Stack += 1; + + if (*Stack >= mBooleanEvaluationStackEnd) { + // + // If we run out of stack space make a new one that is 2X as big. Copy + // the old data into the new stack and update Stack to point to the old + // data in the new stack. + // + GrowBooleanStack ( + Stack, + (mBooleanEvaluationStackEnd - mBooleanEvaluationStack) * sizeof (BOOLEAN) * 2 + ); + } +} + +STATIC +BOOLEAN +PopBool ( + IN OUT BOOLEAN **Stack + ) +/*++ + +Routine Description: + + Pop an element from the Boolean stack. + +Arguments: + + Stack - Current stack location + +Returns: + + Top of the BOOLEAN stack. + +--*/ +{ + BOOLEAN ReturnValue; + + *Stack -= 1; + CopyMem (&ReturnValue, *Stack, sizeof (BOOLEAN)); + return ReturnValue; +} + +EFI_STATUS +GrowBooleanExpression ( + IN EFI_INCONSISTENCY_DATA *InconsistentTags, + OUT VOID **BooleanExpression, + IN OUT UINTN *BooleanExpressionLength + ) +{ + UINT8 *NewExpression; + + NewExpression = AllocatePool (*BooleanExpressionLength + sizeof (EFI_INCONSISTENCY_DATA)); + ASSERT (NewExpression != NULL); + + if (*BooleanExpression != NULL) { + // + // Copy Old buffer to the New buffer + // + CopyMem (NewExpression, *BooleanExpression, *BooleanExpressionLength); + + CopyMem (&NewExpression[*BooleanExpressionLength], InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA)); + + // + // Free The Old buffer + // + gBS->FreePool (*BooleanExpression); + } else { + // + // Copy data into new buffer + // + CopyMem (NewExpression, InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA)); + } + + *BooleanExpressionLength = *BooleanExpressionLength + sizeof (EFI_INCONSISTENCY_DATA); + *BooleanExpression = (VOID *) NewExpression; + return EFI_SUCCESS; +} + +VOID +CreateBooleanExpression ( + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UINT16 Value, + IN UINT16 Id, + IN BOOLEAN Complex, + OUT VOID **BooleanExpression, + OUT UINTN *BooleanExpressionLength + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + UINTN Count; + EFI_INCONSISTENCY_DATA *InconsistentTags; + EFI_INCONSISTENCY_DATA FakeInconsistentTags; + + InconsistentTags = FileFormTags->InconsistentTags; + + // + // Did we run into a question that contains the Id we are looking for? + // + for (Count = 0; InconsistentTags->Operand != 0xFF; Count++) { + + // + // Reserve INVALID_OFFSET_VALUE - 1 for TURE and FALSE, because we need to treat them as well + // as ideqid etc. but they have no coresponding id, so we reserve this value. + // + if (InconsistentTags->QuestionId1 == Id || + InconsistentTags->QuestionId1 == INVALID_OFFSET_VALUE - 1) { + // + // If !Complex - means evaluate a single if/endif expression + // + if (!Complex) { + // + // If the ConsistencyId does not match the expression we are looking for + // skip to the next consistency database entry + // + if (InconsistentTags->ConsistencyId != Value) { + goto NextEntry; + } + } + // + // We need to rewind to the beginning of the Inconsistent expression + // + for (; + (InconsistentTags->Operand != EFI_IFR_INCONSISTENT_IF_OP) && + (InconsistentTags->Operand != EFI_IFR_GRAYOUT_IF_OP) && + (InconsistentTags->Operand != EFI_IFR_SUPPRESS_IF_OP); + ) { + InconsistentTags = InconsistentTags->Previous; + } + // + // Store the consistency check expression, ensure the next for loop starts at the op-code afterwards + // + GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength); + InconsistentTags = InconsistentTags->Next; + + // + // Keep growing until we hit the End expression op-code or we hit the beginning of another + // consistency check like grayout/suppress + // + for (; + InconsistentTags->Operand != EFI_IFR_END_IF_OP && + InconsistentTags->Operand != EFI_IFR_GRAYOUT_IF_OP && + InconsistentTags->Operand != EFI_IFR_SUPPRESS_IF_OP; + ) { + GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength); + InconsistentTags = InconsistentTags->Next; + } + // + // Store the EndExpression Op-code + // + GrowBooleanExpression (InconsistentTags, BooleanExpression, BooleanExpressionLength); + } + +NextEntry: + if (InconsistentTags->Next != NULL) { + // + // Skip to next entry + // + InconsistentTags = InconsistentTags->Next; + } + } + + FakeInconsistentTags.Operand = 0; + + // + // Add one last expression which will signify we have definitely hit the end + // + GrowBooleanExpression (&FakeInconsistentTags, BooleanExpression, BooleanExpressionLength); +} + +EFI_STATUS +BooleanVariableWorker ( + IN CHAR16 *VariableName, + IN EFI_VARIABLE_DEFINITION *VariableDefinition, + IN BOOLEAN *StackPtr, + IN OUT UINTN *SizeOfVariable, + IN OUT VOID **VariableData + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + + Status = gRT->GetVariable ( + VariableName, + &VariableDefinition->Guid, + NULL, + SizeOfVariable, + *VariableData + ); + + if (EFI_ERROR (Status)) { + + if (Status == EFI_BUFFER_TOO_SMALL) { + *VariableData = AllocatePool (*SizeOfVariable); + ASSERT (*VariableData != NULL); + + Status = gRT->GetVariable ( + VariableName, + &VariableDefinition->Guid, + NULL, + SizeOfVariable, + *VariableData + ); + } + + if (Status == EFI_NOT_FOUND) { + // + // This is a serious flaw, we must have some standard result if a variable + // is not found. Our default behavior must either be return a TRUE or FALSE + // since there is nothing else we can really do. Therefore, my crystal ball + // says I will return a FALSE + // + PushBool (&StackPtr, FALSE); + } + } + + return Status; +} + +UINT8 +PredicateIfrType ( + IN EFI_INCONSISTENCY_DATA *Iterator + ) +/*++ + +Routine Description: + This routine is for the purpose of predicate whether the Ifr is generated by a VfrCompiler greater than or equal to 1.88 or + less than 1.88 which is legacy. + +Arguments: + Iterator - The pointer to inconsistency tags + +Returns: + + 0x2 - If IFR is not legacy + + 0x1 - If IFR is legacy + +--*/ +{ + // + // legacy Ifr cover the states: + // Not ... + // Operand Opcode Operand + // + // while Operand means ideqval, TRUE, or other what can be evaluated to True or False, + // and Opcode means AND or OR. + // + if (Iterator->Operand == EFI_IFR_NOT_OP || + Iterator->Operand == 0) { + return 0x1; + } else if (Iterator->Operand == EFI_IFR_EQ_VAR_VAL_OP || + Iterator->Operand == EFI_IFR_EQ_ID_VAL_OP || + Iterator->Operand == EFI_IFR_EQ_ID_ID_OP || + Iterator->Operand == EFI_IFR_EQ_ID_LIST_OP) { + Iterator++; + if (Iterator->Operand == EFI_IFR_AND_OP || + Iterator->Operand == EFI_IFR_OR_OP) { + Iterator--; + return 0x1; + } + Iterator--; + } + return 0x2; +} + +VOID +PostOrderEvaluate ( + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UINT16 Width, + IN OUT EFI_INCONSISTENCY_DATA **PIterator, + IN OUT BOOLEAN **StackPtr + ) +/*++ + +Routine Description: + PostOrderEvaluate is used for Ifr generated by VfrCompiler greater than or equal to 1.88, + which generate Operand Operand Opcode type Ifr. + PostOrderEvaluete only evaluate boolean expression part, not suppressif/grayoutif. TRUE, + FALSE, >=, >, (, ) are supported. + +Arguments: + + FileFormTags - The pointer to the tags of the form + + Width - Width of Operand, recognized every iteration + + PIterator - The pointer to inconsistency tags + + StackPtr - The pointer to the evaluation stack + +Returns: + + TRUE - If value is valid + + FALSE - If value is not valid + +--*/ +{ + BOOLEAN Operator; + BOOLEAN Operator2; + UINT16 *MapBuffer; + UINT16 *MapBuffer2; + UINT16 MapValue; + UINT16 MapValue2; + UINTN SizeOfVariable; + CHAR16 VariableName[40]; + VOID *VariableData; + EFI_VARIABLE_DEFINITION *VariableDefinition; + EFI_STATUS Status; + UINTN Index; + BOOLEAN PushValue; + + Operator = FALSE; + Operator2 = FALSE; + MapBuffer = NULL; + MapBuffer2 = NULL; + MapValue = 0; + MapValue2 = 0; + VariableData = NULL; + + while (TRUE) { + if ((*PIterator)->Operand == 0) { + return; + } + + Width = (*PIterator)->Width; + + // + // Because INVALID_OFFSET_VALUE - 1 is reserved for TRUE or FALSE, omit them. + // + if ((*PIterator)->QuestionId1 != INVALID_OFFSET_VALUE && + (*PIterator)->QuestionId1 != INVALID_OFFSET_VALUE - 1) { + ExtractNvValue (FileFormTags, (*PIterator)->VariableNumber, Width, (*PIterator)->QuestionId1, (VOID **) &MapBuffer); + ExtractNvValue (FileFormTags, (*PIterator)->VariableNumber2, Width, (*PIterator)->QuestionId2, (VOID **) &MapBuffer2); + if (MapBuffer != NULL) { + if (Width == 2) { + MapValue = *MapBuffer; + } else { + MapValue = (UINT8) *MapBuffer; + } + + gBS->FreePool (MapBuffer); + } + + if (MapBuffer2 != NULL) { + if (Width == 2) { + MapValue2 = *MapBuffer2; + } else { + MapValue2 = (UINT8) *MapBuffer2; + } + + gBS->FreePool (MapBuffer2); + } + } + + switch ((*PIterator)->Operand) { + case EFI_IFR_EQ_VAR_VAL_OP: + UnicodeValueToString ( + VariableName, + FALSE, + (UINTN) (*PIterator)->QuestionId1, + (sizeof (VariableName) / sizeof (VariableName[0])) + ); + + SizeOfVariable = 0; + + ExtractRequestedNvMap (FileFormTags, (*PIterator)->VariableNumber, &VariableDefinition); + + Status = BooleanVariableWorker ( + VariableName, + VariableDefinition, + *StackPtr, + &SizeOfVariable, + &VariableData + ); + + if (!EFI_ERROR (Status)) { + if (SizeOfVariable == 1) { + CopyMem (&MapValue, VariableData, 1); + } else { + CopyMem (&MapValue, VariableData, 2); + } + + // + // Do operation after knowing the compare operator. + // + MapValue2 = (*PIterator)->Value; + (*PIterator)++; + if ((*PIterator)->Operand == EFI_IFR_GT_OP) { + PushValue = (BOOLEAN) (MapValue > MapValue2); + } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) { + PushValue = (BOOLEAN) (MapValue >= MapValue2); + } else { + (*PIterator)--; + PushValue = (BOOLEAN) (MapValue == MapValue2); + } + PushBool (StackPtr, PushValue); + } + + break; + + case EFI_IFR_EQ_ID_VAL_OP: + // + // Do operation after knowing the compare operator. + // + MapValue2 = (*PIterator)->Value; + (*PIterator)++; + if ((*PIterator)->Operand == EFI_IFR_GT_OP) { + PushValue = (BOOLEAN) (MapValue > MapValue2); + } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) { + PushValue = (BOOLEAN) (MapValue >= MapValue2); + } else { + (*PIterator)--; + PushValue = (BOOLEAN) (MapValue == MapValue2); + } + PushBool (StackPtr, PushValue); + break; + + case EFI_IFR_EQ_ID_ID_OP: + // + // Do operation after knowing the compare operator. + // + (*PIterator)++; + if ((*PIterator)->Operand == EFI_IFR_GT_OP) { + PushValue = (BOOLEAN) (MapValue > MapValue2); + } else if ((*PIterator)->Operand == EFI_IFR_GE_OP) { + PushValue = (BOOLEAN) (MapValue >= MapValue2); + } else { + (*PIterator)--; + PushValue = (BOOLEAN) (MapValue == MapValue2); + } + PushBool (StackPtr, PushValue); + break; + + case EFI_IFR_EQ_ID_LIST_OP: + for (Index = 0; Index < (*PIterator)->ListLength; Index++) { + Operator = (BOOLEAN) (MapValue == (*PIterator)->ValueList[Index]); + if (Operator) { + break; + } + } + + PushBool (StackPtr, Operator); + break; + + case EFI_IFR_TRUE_OP: + PushBool (StackPtr, TRUE); + break; + + case EFI_IFR_FALSE_OP: + PushBool (StackPtr, FALSE); + break; + + case EFI_IFR_AND_OP: + Operator = PopBool (StackPtr); + Operator2 = PopBool (StackPtr); + PushBool (StackPtr, (BOOLEAN) (Operator && Operator2)); + break; + case EFI_IFR_OR_OP: + Operator = PopBool (StackPtr); + Operator2 = PopBool (StackPtr); + PushBool (StackPtr, (BOOLEAN) (Operator || Operator2)); + break; + case EFI_IFR_NOT_OP: + Operator = PopBool (StackPtr); + PushBool (StackPtr, !Operator); + break; + + case EFI_IFR_SUPPRESS_IF_OP: + case EFI_IFR_GRAYOUT_IF_OP: + case EFI_IFR_INCONSISTENT_IF_OP: + default: + // + // Return to the previous tag if runs out of boolean expression. + // + (*PIterator)--; + return; + } + (*PIterator)++; + } +} + +BOOLEAN +ValueIsNotValid ( + IN BOOLEAN Complex, + IN UINT16 Value, + IN EFI_TAG *Tag, + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN STRING_REF *PopUp + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + TRUE - If value is valid + + FALSE - If value is not valid + +--*/ +{ + BOOLEAN *StackPtr; + EFI_INCONSISTENCY_DATA *Iterator; + BOOLEAN Operator; + BOOLEAN Operator2; + UINTN Index; + VOID *BooleanExpression; + UINTN BooleanExpressionLength; + BOOLEAN NotOperator; + BOOLEAN OrOperator; + BOOLEAN AndOperator; + BOOLEAN ArtificialEnd; + UINT16 *MapBuffer; + UINT16 *MapBuffer2; + UINT16 MapValue; + UINT16 MapValue2; + UINTN SizeOfVariable; + CHAR16 VariableName[40]; + VOID *VariableData; + EFI_STATUS Status; + UINT16 Id; + UINT16 Width; + EFI_VARIABLE_DEFINITION *VariableDefinition; + BOOLEAN CosmeticConsistency; + UINT8 IsLegacy; + + VariableData = NULL; + BooleanExpressionLength = 0; + BooleanExpression = NULL; + Operator = FALSE; + ArtificialEnd = FALSE; + CosmeticConsistency = TRUE; + IsLegacy = 0; + + Id = Tag->Id; + if (Tag->StorageWidth == 1) { + Width = 1; + } else { + Width = 2; + } + CreateBooleanExpression (FileFormTags, Value, Id, Complex, &BooleanExpression, &BooleanExpressionLength); + + if (mBooleanEvaluationStack == 0) { + InitializeBooleanEvaluator (); + } + + if (BooleanExpression == NULL) { + return FALSE; + } + + StackPtr = mBooleanEvaluationStack; + Iterator = BooleanExpression; + MapBuffer = NULL; + MapBuffer2 = NULL; + MapValue = 0; + MapValue2 = 0; + + while (TRUE) { + NotOperator = FALSE; + OrOperator = FALSE; + AndOperator = FALSE; + + if (Iterator->Operand == 0) { + return Operator; + } + + // + // Because INVALID_OFFSET_VALUE - 1 is reserved for TRUE or FALSE, omit them. + // + if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE && + Iterator->QuestionId1 != INVALID_OFFSET_VALUE-1) { + ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer); + ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2); + if (MapBuffer != NULL) { + if (Width == 2) { + MapValue = *MapBuffer; + } else { + MapValue = (UINT8) *MapBuffer; + } + + gBS->FreePool (MapBuffer); + } + + if (MapBuffer2 != NULL) { + if (Width == 2) { + MapValue2 = *MapBuffer2; + } else { + MapValue2 = (UINT8) *MapBuffer2; + } + + gBS->FreePool (MapBuffer2); + } + } + + switch (Iterator->Operand) { + case EFI_IFR_SUPPRESS_IF_OP: + // + // Must have hit a suppress followed by a grayout or vice-versa + // + if (ArtificialEnd) { + ArtificialEnd = FALSE; + Operator = PopBool (&StackPtr); + if (Operator) { + Tag->Suppress = TRUE; + } + + return Operator; + } + + ArtificialEnd = TRUE; + *PopUp = Iterator->Popup; + break; + + case EFI_IFR_GRAYOUT_IF_OP: + // + // Must have hit a suppress followed by a grayout or vice-versa + // + if (ArtificialEnd) { + ArtificialEnd = FALSE; + Operator = PopBool (&StackPtr); + if (Operator) { + Tag->GrayOut = TRUE; + } + + return Operator; + } + + ArtificialEnd = TRUE; + *PopUp = Iterator->Popup; + break; + + case EFI_IFR_INCONSISTENT_IF_OP: + CosmeticConsistency = FALSE; + *PopUp = Iterator->Popup; + break; + + // + // In the case of external variable values, we must read the variable which is + // named by the human readable version of the OpCode->VariableId and the guid of the formset + // + case EFI_IFR_EQ_VAR_VAL_OP: + // + // To check whether Ifr is legacy. Once every boolean expression. + // + if (IsLegacy == 0) { + IsLegacy = PredicateIfrType (Iterator); + } + if (IsLegacy == 0x2) { + PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr); + break; + } + + UnicodeValueToString ( + VariableName, + FALSE, + (UINTN) Iterator->QuestionId1, + (sizeof (VariableName) / sizeof (VariableName[0])) + ); + + SizeOfVariable = 0; + + ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition); + + Status = BooleanVariableWorker ( + VariableName, + VariableDefinition, + StackPtr, + &SizeOfVariable, + &VariableData + ); + + if (!EFI_ERROR (Status)) { + if (SizeOfVariable == 1) { + CopyMem (&MapValue, VariableData, 1); + } else { + CopyMem (&MapValue, VariableData, 2); + } + + PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value)); + } + + break; + + case EFI_IFR_EQ_ID_VAL_OP: + // + // To check whether Ifr is legacy. Once every boolean expression. + // + if (IsLegacy == 0) { + IsLegacy = PredicateIfrType (Iterator); + } + if (IsLegacy == 0x2) { + PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr); + break; + } + + PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value)); + break; + + case EFI_IFR_EQ_ID_ID_OP: + // + // To check whether Ifr is legacy. Once every boolean expression. + // + if (IsLegacy == 0) { + IsLegacy = PredicateIfrType (Iterator); + } + if (IsLegacy == 0x2) { + PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr); + break; + } + + PushBool (&StackPtr, (BOOLEAN) (MapValue == MapValue2)); + break; + + case EFI_IFR_EQ_ID_LIST_OP: + // + // To check whether Ifr is legacy. Once every boolean expression. + // + if (IsLegacy == 0) { + IsLegacy = PredicateIfrType (Iterator); + } + if (IsLegacy == 0x2) { + PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr); + break; + } + + for (Index = 0; Index < Iterator->ListLength; Index++) { + Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]); + if (Operator) { + break; + } + } + + PushBool (&StackPtr, Operator); + break; + + case EFI_IFR_AND_OP: + Iterator++; + if (Iterator->Operand == EFI_IFR_NOT_OP) { + NotOperator = TRUE; + Iterator++; + } + + if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) { + ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer); + ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2); + if (MapBuffer != NULL) { + if (Width == 2) { + MapValue = *MapBuffer; + } else { + MapValue = (UINT8) *MapBuffer; + } + + gBS->FreePool (MapBuffer); + } + + if (MapBuffer2 != NULL) { + if (Width == 2) { + MapValue2 = *MapBuffer2; + } else { + MapValue2 = (UINT8) *MapBuffer2; + } + + gBS->FreePool (MapBuffer2); + } + } + + switch (Iterator->Operand) { + case EFI_IFR_EQ_ID_VAL_OP: + // + // If Not - flip the results + // + if (NotOperator) { + Operator = (BOOLEAN)!(MapValue == Iterator->Value); + } else { + Operator = (BOOLEAN) (MapValue == Iterator->Value); + } + + PushBool (&StackPtr, Operator); + break; + + // + // In the case of external variable values, we must read the variable which is + // named by the human readable version of the OpCode->VariableId and the guid of the formset + // + case EFI_IFR_EQ_VAR_VAL_OP: + UnicodeValueToString ( + VariableName, + FALSE, + (UINTN) Iterator->QuestionId1, + (sizeof (VariableName) / sizeof (VariableName[0])) + ); + + SizeOfVariable = 0; + + ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition); + + Status = BooleanVariableWorker ( + VariableName, + VariableDefinition, + StackPtr, + &SizeOfVariable, + &VariableData + ); + + if (!EFI_ERROR (Status)) { + if (SizeOfVariable == 1) { + CopyMem (&MapValue, VariableData, 1); + } else { + CopyMem (&MapValue, VariableData, 2); + } + // + // If Not - flip the results + // + if (NotOperator) { + PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value)); + } else { + PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value)); + } + } + break; + + case EFI_IFR_EQ_ID_ID_OP: + // + // If Not - flip the results + // + if (NotOperator) { + Operator = (BOOLEAN)!(MapValue == MapValue2); + } else { + Operator = (BOOLEAN) (MapValue == MapValue2); + } + + PushBool (&StackPtr, Operator); + break; + + case EFI_IFR_EQ_ID_LIST_OP: + for (Index = 0; Index < Iterator->ListLength; Index++) { + // + // If Not - flip the results + // + if (NotOperator) { + Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]); + } else { + Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]); + } + // + // If We are trying to make sure that MapValue != Item[x], keep looking through + // the list to make sure we don't equal any other items + // + if (Operator && NotOperator) { + continue; + } + // + // If MapValue == Item, then we have succeeded (first found is good enough) + // + if (Operator) { + break; + } + } + + PushBool (&StackPtr, Operator); + break; + + default: + return FALSE; + } + + Operator = PopBool (&StackPtr); + Operator2 = PopBool (&StackPtr); + PushBool (&StackPtr, (BOOLEAN) (Operator && Operator2)); + break; + + case EFI_IFR_OR_OP: + Iterator++; + if (Iterator->Operand == EFI_IFR_NOT_OP) { + NotOperator = TRUE; + Iterator++; + } + + if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) { + ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer); + ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2); + if (MapBuffer != NULL) { + if (Width == 2) { + MapValue = *MapBuffer; + } else { + MapValue = (UINT8) *MapBuffer; + } + + gBS->FreePool (MapBuffer); + } + + if (MapBuffer2 != NULL) { + if (Width == 2) { + MapValue2 = *MapBuffer2; + } else { + MapValue2 = (UINT8) *MapBuffer2; + } + + gBS->FreePool (MapBuffer2); + } + } + + switch (Iterator->Operand) { + case EFI_IFR_EQ_ID_VAL_OP: + // + // If Not - flip the results + // + if (NotOperator) { + Operator = (BOOLEAN)!(MapValue == Iterator->Value); + } else { + Operator = (BOOLEAN) (MapValue == Iterator->Value); + } + + PushBool (&StackPtr, Operator); + break; + + // + // In the case of external variable values, we must read the variable which is + // named by the human readable version of the OpCode->VariableId and the guid of the formset + // + case EFI_IFR_EQ_VAR_VAL_OP: + UnicodeValueToString ( + VariableName, + FALSE, + (UINTN) Iterator->QuestionId1, + (sizeof (VariableName) / sizeof (VariableName[0])) + ); + + SizeOfVariable = 0; + + ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition); + + Status = BooleanVariableWorker ( + VariableName, + VariableDefinition, + StackPtr, + &SizeOfVariable, + &VariableData + ); + + if (!EFI_ERROR (Status)) { + if (SizeOfVariable == 1) { + CopyMem (&MapValue, VariableData, 1); + } else { + CopyMem (&MapValue, VariableData, 2); + } + // + // If Not - flip the results + // + if (NotOperator) { + PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value)); + } else { + PushBool (&StackPtr, (BOOLEAN) (MapValue == Iterator->Value)); + } + } + break; + + case EFI_IFR_EQ_ID_ID_OP: + // + // If Not - flip the results + // + if (NotOperator) { + Operator = (BOOLEAN)!(MapValue == MapValue2); + } else { + Operator = (BOOLEAN) (MapValue == MapValue2); + } + + PushBool (&StackPtr, Operator); + break; + + case EFI_IFR_EQ_ID_LIST_OP: + for (Index = 0; Index < Iterator->ListLength; Index++) { + // + // If Not - flip the results + // + if (NotOperator) { + Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]); + } else { + Operator = (BOOLEAN) (MapValue == Iterator->ValueList[Index]); + } + // + // If We are trying to make sure that MapValue != Item[x], keep looking through + // the list to make sure we don't equal any other items + // + if (Operator && NotOperator) { + continue; + } + // + // If MapValue == Item, then we have succeeded (first found is good enough) + // + if (Operator) { + break; + } + } + + PushBool (&StackPtr, Operator); + break; + + default: + return FALSE; + } + + Operator = PopBool (&StackPtr); + Operator2 = PopBool (&StackPtr); + PushBool (&StackPtr, (BOOLEAN) (Operator || Operator2)); + break; + + case EFI_IFR_NOT_OP: + // + // To check whether Ifr is legacy. Once every boolean expression. + // + if (IsLegacy == 0) { + IsLegacy = PredicateIfrType (Iterator); + } + if (IsLegacy == 0x2) { + PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr); + break; + } + + // + // I don't need to set the NotOperator (I know that I have to NOT this in this case + // + Iterator++; + + if (Iterator->Operand == EFI_IFR_OR_OP) { + OrOperator = TRUE; + Iterator++; + } + + if (Iterator->Operand == EFI_IFR_AND_OP) { + AndOperator = TRUE; + Iterator++; + } + + if (Iterator->QuestionId1 != INVALID_OFFSET_VALUE) { + ExtractNvValue (FileFormTags, Iterator->VariableNumber, Width, Iterator->QuestionId1, (VOID **) &MapBuffer); + ExtractNvValue (FileFormTags, Iterator->VariableNumber2, Width, Iterator->QuestionId2, (VOID **) &MapBuffer2); + if (MapBuffer != NULL) { + if (Width == 2) { + MapValue = *MapBuffer; + } else { + MapValue = (UINT8) *MapBuffer; + } + + gBS->FreePool (MapBuffer); + } + + if (MapBuffer2 != NULL) { + if (Width == 2) { + MapValue2 = *MapBuffer2; + } else { + MapValue2 = (UINT8) *MapBuffer2; + } + + gBS->FreePool (MapBuffer2); + } + } + + switch (Iterator->Operand) { + case EFI_IFR_EQ_ID_VAL_OP: + Operator = (BOOLEAN)!(MapValue == Iterator->Value); + PushBool (&StackPtr, Operator); + break; + + // + // In the case of external variable values, we must read the variable which is + // named by the human readable version of the OpCode->VariableId and the guid of the formset + // + case EFI_IFR_EQ_VAR_VAL_OP: + UnicodeValueToString ( + VariableName, + FALSE, + (UINTN) Iterator->QuestionId1, + (sizeof (VariableName) / sizeof (VariableName[0])) + ); + + SizeOfVariable = 0; + + ExtractRequestedNvMap (FileFormTags, Iterator->VariableNumber, &VariableDefinition); + + Status = BooleanVariableWorker ( + VariableName, + VariableDefinition, + StackPtr, + &SizeOfVariable, + &VariableData + ); + + if (!EFI_ERROR (Status)) { + if (SizeOfVariable == 1) { + CopyMem (&MapValue, VariableData, 1); + } else { + CopyMem (&MapValue, VariableData, 2); + } + + PushBool (&StackPtr, (BOOLEAN)!(MapValue == Iterator->Value)); + } + break; + + case EFI_IFR_EQ_ID_ID_OP: + Operator = (BOOLEAN)!(MapValue == MapValue2); + PushBool (&StackPtr, Operator); + break; + + case EFI_IFR_EQ_ID_LIST_OP: + for (Index = 0; Index < Iterator->ListLength; Index++) { + Operator = (BOOLEAN)!(MapValue == Iterator->ValueList[Index]); + if (Operator) { + continue; + } + } + + PushBool (&StackPtr, Operator); + break; + + default: + return FALSE; + } + + Operator = PopBool (&StackPtr); + Operator2 = PopBool (&StackPtr); + + if (OrOperator) { + PushBool (&StackPtr, (BOOLEAN) (Operator || Operator2)); + } + + if (AndOperator) { + PushBool (&StackPtr, (BOOLEAN) (Operator && Operator2)); + } + + if (!OrOperator && !AndOperator) { + PushBool (&StackPtr, Operator); + } + break; + + case EFI_IFR_TRUE_OP: + // + // To check whether Ifr is legacy. Once every boolean expression. + // + if (IsLegacy == 0) { + IsLegacy = PredicateIfrType (Iterator); + } + if (IsLegacy == 0x2) { + PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr); + break; + } + break; + + case EFI_IFR_FALSE_OP: + // + // To check whether Ifr is legacy. Once every boolean expression. + // + if (IsLegacy == 0) { + IsLegacy = PredicateIfrType (Iterator); + } + if (IsLegacy == 0x2) { + PostOrderEvaluate (FileFormTags, Width, &Iterator, &StackPtr); + break; + } + break; + + case EFI_IFR_END_IF_OP: + Operator = PopBool (&StackPtr); + // + // If there is an error, return, otherwise keep looking - there might + // be another test that causes an error + // + if (Operator) { + if (Complex && CosmeticConsistency) { + return EFI_SUCCESS; + } else { + return Operator; + } + } else { + // + // If not doing a global consistency check, the endif is the REAL terminator of this operation + // This is used for grayout/suppress operations. InconsistentIf is a global operation so the EndIf is + // not the end-all be-all of terminators. + // + if (!Complex) { + return Operator; + } + break; + } + + default: + // + // Must have hit a non-consistency related op-code after a suppress/grayout + // + if (ArtificialEnd) { + ArtificialEnd = FALSE; + Operator = PopBool (&StackPtr); + return Operator; + } + + return FALSE; + } + + Iterator++; + } + + return FALSE; +} diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Colors.h b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Colors.h new file mode 100644 index 0000000000..c1f5441432 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Colors.h @@ -0,0 +1,54 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Colors.h + +Abstract: + + +Revision History + +--*/ + +#ifndef _COLORS_H +#define _COLORS_H + +// +// Screen Color Settings +// +#define PICKLIST_HIGHLIGHT_TEXT EFI_WHITE +#define PICKLIST_HIGHLIGHT_BACKGROUND EFI_BACKGROUND_CYAN +#define TITLE_TEXT EFI_WHITE +#define TITLE_BACKGROUND EFI_BACKGROUND_BLUE +#define KEYHELP_TEXT EFI_LIGHTGRAY +#define KEYHELP_BACKGROUND EFI_BACKGROUND_BLACK +#define SUBTITLE_TEXT EFI_BLUE +#define SUBTITLE_BACKGROUND EFI_BACKGROUND_LIGHTGRAY +#define BANNER_TEXT EFI_BLUE +#define BANNER_BACKGROUND EFI_BACKGROUND_LIGHTGRAY +#define FIELD_TEXT EFI_BLACK +#define FIELD_TEXT_GRAYED EFI_DARKGRAY +#define FIELD_BACKGROUND EFI_BACKGROUND_LIGHTGRAY +#define FIELD_TEXT_HIGHLIGHT EFI_LIGHTGRAY +#define FIELD_BACKGROUND_HIGHLIGHT EFI_BACKGROUND_BLACK +#define POPUP_TEXT EFI_LIGHTGRAY +#define POPUP_BACKGROUND EFI_BACKGROUND_BLUE +#define POPUP_INVERSE_TEXT EFI_LIGHTGRAY +#define POPUP_INVERSE_BACKGROUND EFI_BACKGROUND_BLACK +#define HELP_TEXT EFI_BLUE +#define ERROR_TEXT EFI_RED | EFI_BRIGHT +#define INFO_TEXT EFI_YELLOW | EFI_BRIGHT +#define ARROW_TEXT EFI_RED | EFI_BRIGHT +#define ARROW_BACKGROUND EFI_BACKGROUND_LIGHTGRAY + +#endif diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.c b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.c new file mode 100644 index 0000000000..5f3823c612 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.c @@ -0,0 +1,631 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + DriverSample.c + +Abstract: + + This is an example of how a driver might export data to the HII protocol to be + later utilized by the Setup Protocol + +--*/ + +#include "DriverSample.h" + +#define DISPLAY_ONLY_MY_ITEM 0x0001 + +#define STRING_PACK_GUID \ + { \ + 0x8160a85f, 0x934d, 0x468b, { 0xa2, 0x35, 0x72, 0x89, 0x59, 0x14, 0xf6, 0xfc } \ + } + +EFI_GUID mFormSetGuid = FORMSET_GUID; +EFI_GUID mStringPackGuid = STRING_PACK_GUID; + +EFI_STATUS +EFIAPI +DriverCallback ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *Data, + OUT EFI_HII_CALLBACK_PACKET **Packet + ) +/*++ + +Routine Description: + + This is the function that is called to provide results data to the driver. This data + consists of a unique key which is used to identify what data is either being passed back + or being asked for. + +Arguments: + + KeyValue - A unique value which is sent to the original exporting driver so that it + can identify the type of data to expect. The format of the data tends to + vary based on the op-code that geerated the callback. + + Data - A pointer to the data being sent to the original exporting driver. + +Returns: + +--*/ +{ + EFI_CALLBACK_INFO *Private; + EFI_HII_UPDATE_DATA *UpdateData; + EFI_STATUS Status; + UINT8 *Location; + EFI_HII_CALLBACK_PACKET *DataPacket; + UINT16 Value; + CHAR16 VariableName[40]; + STATIC UINT16 QuestionId = 0; + IFR_OPTION *OptionList; + UINTN Index; + MyIfrNVData NVStruc; + + Private = EFI_CALLBACK_INFO_FROM_THIS (This); + + // + // This should tell me the first offset AFTER the end of the compiled NV map + // If op-code results are not going to be saved to NV locations ensure the QuestionId + // is beyond the end of the NVRAM mapping. + // + if (QuestionId == 0) { + QuestionId = sizeof (MyIfrNVData); + } + + ZeroMem (VariableName, (sizeof (CHAR16) * 40)); + + switch (KeyValue) { + case 0x0001: + // + // Create a small boot order list + // + QuestionId = (UINT16) ((UINTN) (&NVStruc.BootOrder) - (UINTN) (&NVStruc)); + + // + // Need some memory for OptionList. Allow for up to 8 options. + // + OptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 8); + + // + // Allocate space for creation of Buffer + // + UpdateData = AllocateZeroPool (0x1000); + + // + // Remove all the op-codes starting with Label 0x2222 to next Label (second label is for convenience + // so we don't have to keep track of how many op-codes we added or subtracted. The rules for removal + // of op-codes are simply that the removal will always stop as soon as a label or the end of a form is + // encountered. Therefore, giving a large obnoxious count such as below takes care of other complexities. + // + UpdateData->DataCount = 0xFF; + + // + // Delete set of op-codes + // + Private->Hii->UpdateForm ( + Private->Hii, + Private->RegisteredHandle, + (EFI_FORM_LABEL) 0x2222, + FALSE, // If we aren't adding, we are deleting + UpdateData + ); + + // + // Create 3 options + // + for (Index = 0; Index < 3; Index++) { + OptionList[Index].StringToken = (UINT16) (STR_BOOT_OPTION1 + Index); + OptionList[Index].Value = (UINT16) (Index + 1); + OptionList[Index].Flags = RESET_REQUIRED; + } + + CreateOrderedListOpCode ( + QuestionId, // Question ID + 8, // Max Entries + (UINT16) STRING_TOKEN (STR_BOOT_OPTIONS), // Token value for the Prompt + (UINT16) STRING_TOKEN (STR_NULL_STRING), // Token value for the Help + OptionList, + 3, + &UpdateData->Data // Buffer location to place op-codes + ); + + // + // For one-of/ordered lists commands, they really consist of 2 op-codes (a header and a footer) + // Each option within a one-of/ordered list is also an op-code + // So this example has 5 op-codes it is adding since we have a one-of header + 3 options + one-of footer + // + UpdateData->DataCount = 0x5; + + // + // Add one op-code + // + Private->Hii->UpdateForm ( + Private->Hii, + Private->RegisteredHandle, + (EFI_FORM_LABEL) 0x2222, + TRUE, + UpdateData + ); + + gBS->FreePool (UpdateData); + gBS->FreePool (OptionList); + break; + + case 0x0002: + // + // Create a large boot order list + // + QuestionId = (UINT16) ((UINTN) (&NVStruc.BootOrder) - (UINTN) (&NVStruc)); + + // + // Need some memory for OptionList. Allow for up to 8 options. + // + OptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 8); + + // + // Allocate space for creation of Buffer + // + UpdateData = AllocateZeroPool (0x1000); + + // + // Remove all the op-codes starting with Label 0x2222 to next Label (second label is for convenience + // so we don't have to keep track of how many op-codes we added or subtracted + // + UpdateData->DataCount = 0xFF; + + // + // Delete one op-code + // + Private->Hii->UpdateForm ( + Private->Hii, + Private->RegisteredHandle, + (EFI_FORM_LABEL) 0x2222, + FALSE, + UpdateData + ); + + // + // Create 4 options + // + for (Index = 0; Index < 4; Index++) { + OptionList[Index].StringToken = (UINT16) (STR_BOOT_OPTION1 + Index); + OptionList[Index].Value = (UINT16) (Index + 1); + OptionList[Index].Flags = RESET_REQUIRED; + } + + CreateOrderedListOpCode ( + QuestionId, // Question ID + 8, // Max Entries + (UINT16) STRING_TOKEN (STR_BOOT_OPTIONS), // Token value for the Prompt + (UINT16) STRING_TOKEN (STR_NULL_STRING), // Token value for the Help + OptionList, + 4, + &UpdateData->Data // Buffer location to place op-codes + ); + + // + // For one-of commands, they really consist of 2 op-codes (a header and a footer) + // Each option within a one-of is also an op-code + // So this example has 6 op-codes it is adding since we have a one-of header + 4 options + one-of footer + // + UpdateData->DataCount = 0x6; + + // + // Add one op-code + // + Private->Hii->UpdateForm ( + Private->Hii, + Private->RegisteredHandle, + (EFI_FORM_LABEL) 0x2222, + TRUE, + UpdateData + ); + + gBS->FreePool (UpdateData); + gBS->FreePool (OptionList); + break; + + case 0x1234: + // + // Allocate space for creation of Buffer + // + QuestionId = (UINT16) ((UINTN) (&NVStruc.DynamicCheck)); + Status = gBS->AllocatePool ( + EfiBootServicesData, + 0x1000, + (VOID **) &UpdateData + ); + + ZeroMem (UpdateData, 0x1000); + + Location = (UINT8 *) &UpdateData->Data; + + UpdateData->FormSetUpdate = TRUE; + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->CallbackHandle; + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = 0; + UpdateData->DataCount = 2; + + CreateGotoOpCode ( + 1, + STR_GOTO_FORM1, // Token value for the Prompt + 0, // Goto Help + 0, // Flags + 0, // Key + &UpdateData->Data // Buffer location to place op-codes + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) &UpdateData->Data)->Length; + + CreateCheckBoxOpCode ( + QuestionId, // Question ID + 1, // Data width (BOOLEAN = 1) + (UINT16) STRING_TOKEN (STR_CHECK_DYNAMIC_PROMPT), // Token value for the Prompt + (UINT16) STRING_TOKEN (STR_CHECK_DYNAMIC_HELP), // Token value for the Help + EFI_IFR_FLAG_INTERACTIVE, // Flags + 0x1236, // Key + Location // Buffer location to place op-codes + ); + + Private->Hii->UpdateForm ( + Private->Hii, + Private->RegisteredHandle, + (EFI_FORM_LABEL) 0x1234, + TRUE, + UpdateData + ); + + gBS->FreePool (UpdateData); + QuestionId++; + break; + + case 0x1235: + // + // Allocate space for creation of Buffer + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + 0x1000, + (VOID **)&UpdateData + ); + + ZeroMem (UpdateData, 0x1000); + + // + // Initialize DataPacket with information intended to remove all + // previously created op-codes in the dynamic page + // + UpdateData->FormSetUpdate = FALSE; + UpdateData->FormCallbackHandle = 0; + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = 0; + // + // Unlikely to be more than 0xff op-codes in the dynamic page to remove + // + UpdateData->DataCount = 0xff; + UpdateData->Data = NULL; + + // + // Remove all op-codes from dynamic page + // + Private->Hii->UpdateForm ( + Private->Hii, + Private->RegisteredHandle, + (EFI_FORM_LABEL) 0x1234, // Label 0x1234 + FALSE, // Remove Op-codes (will never remove form/endform) + UpdateData // Significant value is UpdateData->DataCount + ); + + UpdateData->FormSetUpdate = FALSE; + UpdateData->FormCallbackHandle = 0; + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = 0; + UpdateData->DataCount = 1; + + CreateGotoOpCode ( + 1, + STR_GOTO_FORM1, // Token value for the Prompt + 0, // Goto Help + 0, // Flags + 0, // Key + &UpdateData->Data // Buffer location to place op-codes + ); + + Private->Hii->UpdateForm ( + Private->Hii, + Private->RegisteredHandle, + (EFI_FORM_LABEL) 0x1234, + TRUE, + UpdateData + ); + + gBS->FreePool (UpdateData); + break; + + case 0x1236: + // + // If I hit the checkbox, I enter this case statement... + // + // + // Since I am returning an error (for test purposes) I need to pass in the string for the error + // I will allocate space for the return value. If an error occurs (which is the case) I can simply return + // an error and fill in the string parameter, otherwise, I will return information in the DataArray structure. + // The browser will free this packet structure + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_HII_CALLBACK_PACKET) + sizeof (SAMPLE_STRING) + 2, + (VOID **) Packet + ); + + ZeroMem (*Packet, sizeof (EFI_HII_CALLBACK_PACKET) + sizeof (SAMPLE_STRING) + 2); + + // + // Assign the buffer address to DataPacket + // + DataPacket = *Packet; + + StrCpy (DataPacket->String, (CHAR16 *) SAMPLE_STRING); + return EFI_DEVICE_ERROR; + + case 0x1237: + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_HII_CALLBACK_PACKET) + 2, + (VOID **) Packet + ); + + ZeroMem (*Packet, sizeof (EFI_HII_CALLBACK_PACKET) + 2); + + // + // Assign the buffer address to DataPacket + // + DataPacket = *Packet; + + DataPacket->DataArray.EntryCount = 1; + DataPacket->DataArray.NvRamMap = NULL; + ((EFI_IFR_DATA_ENTRY *) (&DataPacket->DataArray + 1))->Flags = EXIT_REQUIRED; + break; + + case 0x1555: + Value = 0x0001; + UnicodeSPrint (VariableName, 0x80, (CHAR16 *) L"%d", VAR_EQ_TEST_NAME); + + Status = gRT->SetVariable ( + VariableName, + &mFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + 2, + (VOID *) &Value + ); + break; + + case 0x1556: + Value = 0x1000; + UnicodeSPrint (VariableName, 0x80, (CHAR16 *) L"%d", VAR_EQ_TEST_NAME); + + Status = gRT->SetVariable ( + VariableName, + &mFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + 2, + (VOID *) &Value + ); + break; + + case 0x1557: + Value = 0x0000; + UnicodeSPrint (VariableName, 0x80, (CHAR16 *) L"%d", VAR_EQ_TEST_NAME); + + Status = gRT->SetVariable ( + VariableName, + &mFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + 2, + (VOID *) &Value + ); + break; + + default: + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DriverSampleInit ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HII_PROTOCOL *Hii; + // + // EFI_FORM_BROWSER_PROTOCOL *FormConfig; + // + EFI_HII_PACKAGES *PackageList; + EFI_HII_HANDLE HiiHandle; + STRING_REF TokenToUpdate; + STRING_REF TokenToUpdate2; + STRING_REF TokenToUpdate3; + CHAR16 *NewString; + EFI_HII_UPDATE_DATA *UpdateData; + EFI_CALLBACK_INFO *CallbackInfo; + EFI_HANDLE Handle; + EFI_SCREEN_DESCRIPTOR Screen; + + ZeroMem (&Screen, sizeof (EFI_SCREEN_DESCRIPTOR)); + + gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Screen.RightColumn, &Screen.BottomRow); + + // + // Remove 3 characters from top and bottom + // + Screen.TopRow = 3; + Screen.BottomRow = Screen.BottomRow - 3; + + // + // There should only be one HII protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + (VOID **) &Hii + ); + if (EFI_ERROR (Status)) { + return Status;; + } + + /* + // + // There should only be one Form Configuration protocol + // + Status = gBS->LocateProtocol ( + &gEfiFormBrowserProtocolGuid, + NULL, + &FormConfig + ); + if (EFI_ERROR (Status)) { + return Status;; + } +*/ + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_CALLBACK_INFO), + (VOID **) &CallbackInfo + ); + if (EFI_ERROR (Status)) { + return Status; + } + + CallbackInfo->Signature = EFI_CALLBACK_INFO_SIGNATURE; + CallbackInfo->Hii = Hii; + + // + // This example does not implement worker functions for the NV accessor functions. Only a callback evaluator + // + CallbackInfo->DriverCallback.NvRead = NULL; + CallbackInfo->DriverCallback.NvWrite = NULL; + CallbackInfo->DriverCallback.Callback = DriverCallback; + + // + // Install protocol interface + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiFormCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &CallbackInfo->DriverCallback + ); + + ASSERT_EFI_ERROR (Status); + + CallbackInfo->CallbackHandle = Handle; + + PackageList = PreparePackages (1, &mStringPackGuid, DriverSampleStrings); + Status = Hii->NewPack (Hii, PackageList, &HiiHandle); + gBS->FreePool (PackageList); + + PackageList = PreparePackages (1, &mStringPackGuid, InventoryBin); + Status = Hii->NewPack (Hii, PackageList, &HiiHandle); + gBS->FreePool (PackageList); + + PackageList = PreparePackages (1, &mStringPackGuid, VfrBin); + Status = Hii->NewPack (Hii, PackageList, &HiiHandle); + gBS->FreePool (PackageList); + + CallbackInfo->RegisteredHandle = HiiHandle; + + // + // Very simple example of how one would update a string that is already + // in the HII database + // + TokenToUpdate = (STRING_REF) STR_CPU_STRING2; + NewString = (CHAR16 *) L"700 Mhz"; + + Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate, NewString); + + // + // Add a string - if 0 will be updated with new Token number + // + TokenToUpdate = (STRING_REF) 0; + + // + // Add a string - if 0 will be updated with new Token number + // + TokenToUpdate2 = (STRING_REF) 0; + + // + // Add a string - if 0 will be updated with new Token number + // + TokenToUpdate3 = (STRING_REF) 0; + + Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate, (CHAR16 *) L"Desired Speed"); + Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate2, (CHAR16 *) L"5 Thz"); + Hii->NewString (Hii, NULL, HiiHandle, &TokenToUpdate3, (CHAR16 *) L"This is next year's desired speed - right?"); + + // + // Allocate space for creation of Buffer + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + 0x1000, + (VOID **) &UpdateData + ); + + ZeroMem (UpdateData, 0x1000); + + // + // Flag update pending in FormSet + // + UpdateData->FormSetUpdate = TRUE; + // + // Register CallbackHandle data for FormSet + // + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackInfo->CallbackHandle; + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = 0; + UpdateData->DataCount = 1; + + CreateTextOpCode (TokenToUpdate, TokenToUpdate2, TokenToUpdate3, 0, 0, &UpdateData->Data); + + Hii->UpdateForm (Hii, HiiHandle, (EFI_FORM_LABEL) 100, TRUE, UpdateData); + + gBS->FreePool (UpdateData); + + // + // Example of how to display only the item we sent to HII + // + if (DISPLAY_ONLY_MY_ITEM == 0x0001) { + // + // Have the browser pull out our copy of the data, and only display our data + // + // Status = FormConfig->SendForm (FormConfig, TRUE, HiiHandle, NULL, NULL, NULL, &Screen, NULL); + // + } else { + // + // Have the browser pull out all the data in the HII Database and display it. + // + // Status = FormConfig->SendForm (FormConfig, TRUE, 0, NULL, NULL, NULL, NULL, NULL); + // + } + + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.h b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.h new file mode 100644 index 0000000000..b1534e8dc6 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.h @@ -0,0 +1,60 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DriverSample.h + +Abstract: + + +Revision History + +--*/ + +#ifndef _DRIVER_SAMPLE_H +#define _DRIVER_SAMPLE_H + + +#include "NVDataStruc.h" + +// +// This is the generated header file which includes whatever needs to be exported (strings + IFR) +// +#include "DriverSampleStrDefs.h" + +extern UINT8 VfrBin[]; +// +// extern UINT8 VfrStringsStr[]; +// +extern UINT8 InventoryBin[]; +// +// extern UINT8 InventoryStringsStr[]; +// +extern UINT8 DriverSampleStrings[]; + +#define SAMPLE_STRING L"This is an error!" + +#define EFI_CALLBACK_INFO_SIGNATURE EFI_SIGNATURE_32 ('C', 'l', 'b', 'k') + +typedef struct { + UINTN Signature; + EFI_HANDLE CallbackHandle; + EFI_FORM_CALLBACK_PROTOCOL DriverCallback; + UINT16 *KeyList; + VOID *FormBuffer; + EFI_HII_HANDLE RegisteredHandle; + EFI_HII_PROTOCOL *Hii; +} EFI_CALLBACK_INFO; + +#define EFI_CALLBACK_INFO_FROM_THIS(a) CR (a, EFI_CALLBACK_INFO, DriverCallback, EFI_CALLBACK_INFO_SIGNATURE) + +#endif diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.mbd b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.mbd new file mode 100644 index 0000000000..c77f09b976 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.mbd @@ -0,0 +1,45 @@ + + + + + DriverSample + FE3542FE-C1D3-4EF8-657C-8048606FF670 + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibNull + BasePrintLib + EdkGraphicsLib + EdkIfrSupportLib + DxeMemoryAllocationLib + HiiLib + + diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.msa b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.msa new file mode 100644 index 0000000000..f77095e254 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/DriverSample.msa @@ -0,0 +1,84 @@ + + + + + DriverSample + DXE_DRIVER + BS_DRIVER + FE3542FE-C1D3-4EF8-657C-8048606FF670 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DebugLib + UefiDriverEntryPoint + UefiLib + BaseLib + PrintLib + EdkGraphicsLib + EdkIfrSupportLib + BaseMemoryLib + MemoryAllocationLib + HiiLib + + + InventoryStrings.uni + Inventory.vfr + VfrStrings.uni + Vfr.vfr + DriverSample.c + DriverSample.h + + + MdePkg + EdkModulePkg + + + Hii + UgaDraw + OEMBadging + FirmwareVolume + ConsoleControl + FormCallback + + + + L"256" + 0xA04A27f4, 0xDF00, 0x4D42, { 0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D } + + + + + GlobalVariable + + + + + DriverSampleInit + + + diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/NVDataStruc.h b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/NVDataStruc.h new file mode 100644 index 0000000000..01369ebbf0 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/NVDataStruc.h @@ -0,0 +1,62 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + NVDataStruc.h + +Abstract: + + NVData structure used by the sample driver + +Revision History: + +--*/ + +#ifndef _NVDATASTRUC_H +#define _NVDATASTRUC_H + +#define FORMSET_GUID \ + { \ + 0xA04A27f4, 0xDF00, 0x4D42, { 0xB5, 0x52, 0x39, 0x51, 0x13, 0x02, 0x11, 0x3D } \ + } + +#define INVENTORY_GUID \ + { \ + 0xb3f56470, 0x6141, 0x4621, { 0x8f, 0x19, 0x70, 0x4e, 0x57, 0x7a, 0xa9, 0xe8 } \ + } + +#define VAR_EQ_TEST_NAME 0x100 + +#pragma pack(1) +typedef struct { + UINT16 WhatIsThePassword[20]; + UINT16 WhatIsThePassword2[20]; + UINT16 MyStringData[20]; + UINT16 SomethingHiddenForHtml; + UINT8 HowOldAreYouInYearsManual; + UINT16 HowTallAreYouManual; + UINT8 HowOldAreYouInYears; + UINT16 HowTallAreYou; + UINT8 MyFavoriteNumber; + UINT8 TestLateCheck; + UINT8 TestLateCheck2; + UINT8 QuestionAboutTreeHugging; + UINT8 ChooseToActivateNuclearWeaponry; + UINT8 SuppressGrayOutSomething; + UINT8 OrderedList[8]; + UINT8 BootOrder[8]; + UINT8 BootOrderLarge; + UINT8 DynamicCheck; +} MyIfrNVData; +#pragma pack() + +#endif diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/Vfr.vfr b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/Vfr.vfr new file mode 100644 index 0000000000..6509a66b76 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/Vfr.vfr @@ -0,0 +1,622 @@ +// *++ +// +// Copyright (c) 2006, 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. +// +// Module Name: +// +// Vfr.vfr +// +// Abstract: +// +// Sample Setup formset +// +// Revision History: +// +// --*/ + + +#include "DriverSampleStrDefs.h" + +#include "NVDataStruc.h" + + +typedef struct { + UINT8 Field8; + UINT16 Field16; + UINT8 OrderedList[3]; +} MyIfrNVData2; + +typedef struct { + UINT8 Field8; + UINT16 Field16; + UINT8 OrderedList[3]; +} MyIfrNVData3; + +#define MY_TEXT_KEY 0x100 + +#define LABEL_1_VALUE 0x01 +#define LABEL_2_VALUE 0x1000 +#define LABEL_UPDATE_BBS 0x2222 +#define LABEL_END_UPDATE_BBS 0x2223 + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_SET_TITLE), + help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP), + class = 0x10, + subclass = 0, + + varstore MyIfrNVData2, key = 0x1234, name = MY_DATA2, guid = FORMSET_GUID; + + + varstore MyIfrNVData3, key = 0x4321, name = MY_DATA3, guid = FORMSET_GUID; + + form formid = 1, + title = STRING_TOKEN(STR_FORM1_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code + + subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT); + + subtitle text = STRING_TOKEN(STR_SUBTITLE_TEXT2); + + banner + title = STRING_TOKEN(STR_BANNER_TITLE), + line 1, + align center; + + banner + title = STRING_TOKEN(STR_BANNER_TITLE), + line 2, + align left; + + banner + title = STRING_TOKEN(STR_BANNER_TITLE), + line 2, + align right; + + text + help = STRING_TOKEN(STR_TEXT_HELP), + text = STRING_TOKEN(STR_CPU_STRING), + text = STRING_TOKEN(STR_CPU_STRING2), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_EXIT_TEXT), + text = STRING_TOKEN(STR_EXIT_TEXT), + text = STRING_TOKEN(STR_EXIT_TEXT), + flags = INTERACTIVE, + key = 0x1237; + + oneof varid = MyIfrNVData.SuppressGrayOutSomething, + prompt = STRING_TOKEN(STR_ONE_OF_PROMPT), + help = STRING_TOKEN(STR_ONE_OF_HELP), + option text = STRING_TOKEN(STR_ONE_OF_TEXT4), value = 0x0, flags = 0; + option text = STRING_TOKEN(STR_ONE_OF_TEXT5), value = 0x1, flags = 0; + option text = STRING_TOKEN(STR_ONE_OF_TEXT6), value = 0x2, flags = DEFAULT; + endoneof; + + oneof varid = MyIfrNVData.BootOrderLarge, + prompt = STRING_TOKEN(STR_ONE_OF_PROMPT), + help = STRING_TOKEN(STR_ONE_OF_HELP), + option text = STRING_TOKEN(STR_BOOT_ORDER1), value = 0x0, flags = INTERACTIVE, key = 1; + option text = STRING_TOKEN(STR_BOOT_ORDER2), value = 0x1, flags = INTERACTIVE | DEFAULT, key = 2; + endoneof; + + grayoutif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1; + suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x0; + label 0; + checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry, + prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT), + help = STRING_TOKEN(STR_CHECK_BOX_HELP), + flags = 1, // Flags behavior for checkbox is overloaded so that it equals a DEFAULT value. 1 = ON, 0 = off + key = 0, + endcheckbox; + endif; + + + // + // Ordered list: + // sizeof(MyIfrNVData) storage must be UINT8 array, and + // size written for the variable must be size of the entire + // variable. + // + // + suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x0; + label LABEL_UPDATE_BBS; + orderedlist + varid = MyIfrNVData.BootOrder, + prompt = STRING_TOKEN(STR_BOOT_OPTIONS), + help = STRING_TOKEN(STR_NULL_STRING), + option text = STRING_TOKEN(STR_BOOT_OPTION2), value = 2, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_BOOT_OPTION1), value = 1, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_BOOT_OPTION3), value = 3, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_BOOT_OPTION4), value = 4, flags = RESET_REQUIRED; + endlist; + label LABEL_END_UPDATE_BBS; + endif; + + suppressif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x2; + orderedlist + varid = MyIfrNVData.OrderedList, + prompt = STRING_TOKEN(STR_TEST_OPCODE), + help = STRING_TOKEN(STR_TEXT_HELP), + option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 4, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 3, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 2, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_TEXT_HELP), value = 1, flags = RESET_REQUIRED; + endlist; + endif; + + label 100; + + goto 0x1234, + prompt = STRING_TOKEN(STR_GOTO_DYNAMIC), + help = STRING_TOKEN(STR_GOTO_HELP), + flags = INTERACTIVE, + key = 0x1234; + + goto 0x1234, + prompt = STRING_TOKEN(STR_GOTO_DYNAMIC2), + help = STRING_TOKEN(STR_GOTO_HELP), + flags = INTERACTIVE, + key = 0x1235; + + // + // VARSTORE tests + // + // Till now, been using variable NvData (must be reserved) + // now we do a varselect for variable NvData3 + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqid MyIfrNVData3.Field16 == MyIfrNVData3.Field16 + endif; + // now we do a varselect_pair for variable NvData2 and NvData3 + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqid MyIfrNVData2.Field16 == MyIfrNVData3.Field16 + endif; + + + // now we do a varselect_pair for variable NvData and NvData2 +// inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), +// ideqid MyIfrNVData2.Field16 == MyIfrNVData.TestLateCheck +// endif; + + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqid MyIfrNVData.TestLateCheck == MyIfrNVData.TestLateCheck2 + endif; + + oneof varid = MyIfrNVData.TestLateCheck, + prompt = STRING_TOKEN(STR_TEST_OPCODE), + help = STRING_TOKEN(STR_ONE_OF_HELP), + option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = LATE_CHECK | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = LATE_CHECK | DEFAULT | RESET_REQUIRED; + endoneof; + + oneof varid = MyIfrNVData.TestLateCheck2, + prompt = STRING_TOKEN(STR_TEST_OPCODE2), + help = STRING_TOKEN(STR_ONE_OF_HELP), + option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = LATE_CHECK | DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = LATE_CHECK | RESET_REQUIRED; + + endoneof; + + oneof varid = MyIfrNVData.QuestionAboutTreeHugging, + prompt = STRING_TOKEN(STR_ONE_OF_PROMPT), + help = STRING_TOKEN(STR_ONE_OF_HELP), + option text = STRING_TOKEN(STR_ONE_OF_TEXT1), value = 0, flags = RESET_REQUIRED; + option text = STRING_TOKEN(STR_ONE_OF_TEXT2), value = 1, flags = DEFAULT | RESET_REQUIRED; + option text = STRING_TOKEN(STR_ONE_OF_TEXT3), value = 0x03, flags = RESET_REQUIRED; + + endoneof; + + string varid = MyIfrNVData.MyStringData, + prompt = STRING_TOKEN(STR_MY_STRING_PROMPT2), + help = STRING_TOKEN(STR_MY_STRING_HELP2), + flags = INTERACTIVE, + key = 0x1234, + minsize = 6, + maxsize = 0x14, + endstring; + + text + help = STRING_TOKEN(STR_GRAYOUT_TEST), + text = STRING_TOKEN(STR_GRAYOUT_TEST), + text = STRING_TOKEN(STR_GRAYOUT_TEST), + flags = INTERACTIVE, + key = 0x1555; + + text + help = STRING_TOKEN(STR_SUPPRESS_TEST), + text = STRING_TOKEN(STR_SUPPRESS_TEST), + text = STRING_TOKEN(STR_SUPPRESS_TEST), + flags = INTERACTIVE, + key = 0x1556; + + text + help = STRING_TOKEN(STR_CLEAR_TEST), + text = STRING_TOKEN(STR_CLEAR_TEST), + text = STRING_TOKEN(STR_CLEAR_TEST), + flags = INTERACTIVE, + key = 0x1557; + + grayoutif vareqval var(VAR_EQ_TEST_NAME) == 0x1; + suppressif vareqval var(VAR_EQ_TEST_NAME) == 0x1000; + label 30; + checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry, + prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT), + help = STRING_TOKEN(STR_CHECK_BOX_HELP), + flags = 1, + key = 0, + endcheckbox; + endif; + + + numeric varid = MyIfrNVData.HowOldAreYouInYearsManual, + prompt = STRING_TOKEN(STR_NUMERIC_MANUAL_PROMPT), + help = STRING_TOKEN(STR_NUMERIC_HELP0), + minimum = 0, + maximum = 0xf0, // 0xf0 = 240 in decimal + step = 0, // Stepping of 0 equates to a manual entering + // of a value, otherwise it will auto-increment + // with a left/right arrow + default = 21, + + endnumeric; + + numeric varid = MyIfrNVData.HowTallAreYouManual, + prompt = STRING_TOKEN(STR_TALL_MANUAL_PROMPT), + help = STRING_TOKEN(STR_NUMERIC_HELP1), + minimum = 0, + maximum = 300, + step = 0, // Stepping of 0 equates to a manual entering + // of a value, otherwise it will auto-increment + // with a left/right arrow + default = 175, + + endnumeric; + + inventory + help = STRING_TOKEN(STR_INVENTORY_HELP), + text = STRING_TOKEN(STR_INVENTORY_TEXT1), + text = STRING_TOKEN(STR_INVENTORY_TEXT2); + + + restore defaults, + formid = 4, + prompt = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT), + help = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP), + flags = 0, + key = 0; + + save defaults, + formid = 4, + prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT), + help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP), + flags = 0, + key = 0; + + // + // Case with no flags or key + // + save defaults, + formid = 4, + prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT), + help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP); + // + // Case with no key + // + save defaults, + formid = 4, + prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT), + help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP), + flags = 0; + // + // Case with no flags + // + save defaults, + formid = 4, + prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT), + help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP), + key = 0; + + label LABEL_2_VALUE; + + grayoutif ideqval MyIfrNVData.HowOldAreYouInYearsManual == 23 AND ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1; + numeric varid = MyIfrNVData.HowOldAreYouInYears, + prompt = STRING_TOKEN(STR_NUMERIC_PROMPT), + help = STRING_TOKEN(STR_NUMERIC_HELP2), + minimum = 0, + maximum = 243, + step = 3, + default = 18, + + endnumeric; + + label LABEL_1_VALUE; + + // + // Numeric with no step or default specified + // + numeric varid = MyIfrNVData.HowTallAreYou, + prompt = STRING_TOKEN(STR_NUMERIC_PROMPT1), + help = STRING_TOKEN(STR_NUMERIC_HELP3), + minimum = 0, + maximum = 190, + // step = 1, // Stepping of 1 if not specified + // default = minimum; // if not specified + endnumeric; + endif; + + string varid = MyIfrNVData.MyStringData, + prompt = STRING_TOKEN(STR_MY_STRING_PROMPT), + help = STRING_TOKEN(STR_MY_STRING_HELP), + minsize = 6, + maxsize = 0x14, + endstring; + + password varid = MyIfrNVData.WhatIsThePassword, + prompt = STRING_TOKEN(STR_PASSWORD_PROMPT), + help = STRING_TOKEN(STR_PASSWORD_HELP), + minsize = 6, + maxsize = 20, // new opcode + encoding = 1, + endpassword; + password varid = MyIfrNVData.WhatIsThePassword2, + prompt = STRING_TOKEN(STR_PASSWORD_PROMPT), + help = STRING_TOKEN(STR_PASSWORD_HELP), + minsize = 6, + maxsize = 20, // new opcode + encoding = 1, + endpassword; + // + // Test with flags and key fields + // + password varid = MyIfrNVData.WhatIsThePassword, + prompt = STRING_TOKEN(STR_PASSWORD_PROMPT), + help = STRING_TOKEN(STR_PASSWORD_HELP), + flags = INTERACTIVE, + key = 0x2000, + minsize = 6, + maxsize = 20, // new opcode + encoding = 1, + endpassword; + + goto 2, + prompt = STRING_TOKEN(STR_GOTO_FORM2), //SecondSetupPage // this too has no end-op and basically it's a jump to a form ONLY + help = STRING_TOKEN(STR_GOTO_HELP); + + goto 3, + prompt = STRING_TOKEN(STR_GOTO_FORM3), //ThirdSetupPage // this too has no end-op and basically it's a jump to a form ONLY + help = STRING_TOKEN(STR_GOTO_HELP); + + endform; + + form formid = 2, // SecondSetupPage, + title = STRING_TOKEN(STR_FORM2_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code + + + date year varid = Date.Year, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_DATE_PROMPT), + help = STRING_TOKEN(STR_DATE_YEAR_HELP), + minimum = 1998, + maximum = 2099, + step = 1, + default = 2004, + + month varid = Date.Month, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_DATE_PROMPT), + help = STRING_TOKEN(STR_DATE_MONTH_HELP), + minimum = 1, + maximum = 12, + step = 1, + default = 1, + + day varid = Date.Day, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_DATE_PROMPT), + help = STRING_TOKEN(STR_DATE_DAY_HELP), + minimum = 1, + maximum = 31, + step = 0x1, + default = 1, + + enddate; + + time hour varid = Time.Hours, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_TIME_PROMPT), + help = STRING_TOKEN(STR_TIME_HOUR_HELP), + minimum = 0, + maximum = 23, + step = 1, + default = 0, + + minute varid = Time.Minutes, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_TIME_PROMPT), + help = STRING_TOKEN(STR_TIME_MINUTE_HELP), + minimum = 0, + maximum = 59, + step = 1, + default = 0, + + second varid = Time.Seconds, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_TIME_PROMPT), + help = STRING_TOKEN(STR_TIME_SECOND_HELP), + minimum = 0, + maximum = 59, + step = 1, + default = 0, + + endtime; + + date year varid = Date.Year, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_DATE_PROMPT), + help = STRING_TOKEN(STR_DATE_YEAR_HELP), + minimum = 1939, + maximum = 2101, + step = 1, + default = 1964, + + month varid = Date.Month, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_DATE_PROMPT), + help = STRING_TOKEN(STR_DATE_MONTH_HELP), + minimum = 1, + maximum = 12, + step = 1, + default = 1, + + day varid = Date.Day, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_DATE_PROMPT), + help = STRING_TOKEN(STR_DATE_DAY_HELP), + minimum = 1, + maximum = 31, + step = 0x1, + default = 1, + + enddate; + + time hour varid = Time.Hours, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_TIME_PROMPT), + help = STRING_TOKEN(STR_TIME_HOUR_HELP), + minimum = 0, + maximum = 23, + step = 1, + default = 0, + + minute varid = Time.Minutes, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_TIME_PROMPT), + help = STRING_TOKEN(STR_TIME_MINUTE_HELP), + minimum = 0, + maximum = 59, + step = 1, + default = 0, + + second varid = Time.Seconds, // Note that it is a member of NULL, so the RTC will be the system resource to retrieve and save from + prompt = STRING_TOKEN(STR_TIME_PROMPT), + help = STRING_TOKEN(STR_TIME_SECOND_HELP), + minimum = 0, + maximum = 59, + step = 1, + default = 0, + + endtime; + + grayoutif + ideqval Date.Day == 21 + AND + ideqval Date.Month == 8; + + hidden value = 32, key = 0x7777; + + endif; // grayoutif + + suppressif + ideqval Date.Day == 8 + AND + ideqval Date.Month == 21; + + hidden value = 32, key = 0x7777; + + endif; // suppressif + + + hidden value = 32, key = 0x1234; + + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqval MyIfrNVData.HowOldAreYouInYearsManual == 4 + endif; + + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqvallist MyIfrNVData.HowOldAreYouInYearsManual == 1 2 3 4 + endif; + + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqid MyIfrNVData.HowOldAreYouInYearsManual == MyIfrNVData.MyFavoriteNumber + endif; + +// grayoutif +// +// If the day is 31 AND months is any of the following 2, 4, 6, 9, 11 +// + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqval Date.Day == 31 + AND + ideqvallist Date.Month == 2 4 6 9 11 + endif; + +// +// If the day is 30 AND month is 2 +// + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqval Date.Day == 30 + AND + ideqval Date.Month == 2 + endif; + +// +// If the day is 29 AND month is 2 AND it year is NOT a leapyear +// + inconsistentif prompt = STRING_TOKEN(STR_ERROR_POPUP), + ideqval Date.Day == 0x1D + AND + ideqval Date.Month == 2 + AND + NOT + ideqvallist Date.Year == 2004 2008 20012 20016 2020 2024 2028 2032 2036 + endif; + + checkbox varid = MyIfrNVData.ChooseToActivateNuclearWeaponry, + prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT), + help = STRING_TOKEN(STR_CHECK_BOX_HELP), + flags = 1, + key = 0, + endcheckbox; + + text + help = STRING_TOKEN(STR_TEXT_HELP), + text = STRING_TOKEN(STR_TEXT_TEXT_1); + + text + help = STRING_TOKEN(STR_TEXT_HELP), + text = STRING_TOKEN(STR_TEXT_TEXT_1), + text = STRING_TOKEN(STR_TEXT_TEXT_2), + flags = 0, + key = MY_TEXT_KEY; + + goto 1, + prompt = STRING_TOKEN(STR_GOTO_FORM1), //MainSetupPage // this too has no end-op and basically it's a jump to a form ONLY + help = STRING_TOKEN(STR_GOTO_HELP); + + endform; + + form formid = 3, title = STRING_TOKEN(STR_FORM3_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code + + grayoutif ideqval MyIfrNVData.SuppressGrayOutSomething == 0x1; + text + help = STRING_TOKEN(STR_TEXT_HELP), + text = STRING_TOKEN(STR_TEXT_TEXT_1); + + endif; //end grayoutif + + text + help = STRING_TOKEN(STR_TEXT_HELP), + text = STRING_TOKEN(STR_TEXT_TEXT_1); + + endform; + + form formid = 4, title = STRING_TOKEN(STR_FORM3_TITLE); + + endform; + + form formid = 0x1234, // Dynamically created page, + title = STRING_TOKEN(STR_DYNAMIC_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code + + label 0x1234; + + endform; + +endformset; diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/VfrStrings.uni b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/VfrStrings.uni new file mode 100644 index 0000000000..9e9dbf5454 Binary files /dev/null and b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/VfrStrings.uni differ diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/build.xml b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/build.xml new file mode 100644 index 0000000000..1263279552 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/inventory.vfr b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/inventory.vfr new file mode 100644 index 0000000000..ff8a6aacb1 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/inventory.vfr @@ -0,0 +1,123 @@ +// *++ +// +// Copyright (c) 2006, 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. +// +// Module Name: +// +// Inventory.vfr +// +// Abstract: +// +// Sample Inventory Data. +// +// Revision History: +// +// --*/ + +#include "DriverSampleStrDefs.h" + +#define INVENTORY_GUID { 0xb3f56470, 0x6141, 0x4621, { 0x8f, 0x19, 0x70, 0x4e, 0x57, 0x7a, 0xa9, 0xe8 } } + +formset + guid = INVENTORY_GUID, + title = STRING_TOKEN(STR_INV_FORM_SET_TITLE), + help = STRING_TOKEN(STR_INV_FORM_SET_HELP), + class = 0x04, + subclass = 0x03, + + form formid = 1, + title = STRING_TOKEN(STR_INV_FORM1_TITLE); // note formid is a variable (for readability) (UINT16) - also added Form to the line to signify the Op-Code + + text + help = STRING_TOKEN(STR_INV_VERSION_HELP), + text = STRING_TOKEN(STR_INV_VERSION_TEXT), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_INV_EMPTY_STRING), + text = STRING_TOKEN(STR_INV_VERSION_TEXT2), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_INV_EMPTY_STRING), + text = STRING_TOKEN(STR_INV_VERSION_TEXT3), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_INV_EMPTY_STRING), + text = STRING_TOKEN(STR_INV_VERSION_TEXT4), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + subtitle text = STRING_TOKEN(STR_INV_EMPTY_STRING); + + text + help = STRING_TOKEN(STR_INV_EMPTY_STRING), + text = STRING_TOKEN(STR_INV_VERSION_TEXT5), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_INV_EMPTY_STRING), + text = STRING_TOKEN(STR_INV_VERSION_TEXT6), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_INV_EMPTY_STRING), + text = STRING_TOKEN(STR_INV_VERSION_TEXT7), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_INV_EMPTY_STRING), + text = STRING_TOKEN(STR_INV_VERSION_TEXT8), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_INV_EMPTY_STRING), + text = STRING_TOKEN(STR_INV_VERSION_TEXT9), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_INV_EMPTY_STRING), + text = STRING_TOKEN(STR_INV_VERSION_TEXT10), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + text + help = STRING_TOKEN(STR_INV_EMPTY_STRING), + text = STRING_TOKEN(STR_INV_VERSION_TEXT11), + text = STRING_TOKEN(STR_INV_EMPTY_STRING), + flags = 0, + key = 0; + + subtitle text = STRING_TOKEN(STR_INV_EMPTY_STRING); + + subtitle text = STRING_TOKEN(STR_INV_VERSION_TEXT12); + + endform; + +endformset; diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/inventorystrings.uni b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/inventorystrings.uni new file mode 100644 index 0000000000..4946b4ae61 Binary files /dev/null and b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/DriverSample/inventorystrings.uni differ diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/InputHandler.c b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/InputHandler.c new file mode 100644 index 0000000000..d84fcf02b1 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/InputHandler.c @@ -0,0 +1,1580 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + InputHandler.C + +Abstract: + + Implementation for handling user input from the User Interface + +Revision History + +--*/ + +#include "Setup.h" +#include "Ui.h" +#include "Colors.h" + +#ifndef EFI_MAX +#define EFI_MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) +#endif + +EFI_STATUS +ReadString ( + IN UI_MENU_OPTION *MenuOption, + OUT CHAR16 *StringPtr + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + CHAR16 NullCharacter; + UINTN ScreenSize; + EFI_TAG *Tag; + CHAR16 Space[2]; + CHAR16 KeyPad[2]; + BOOLEAN SelectionComplete; + CHAR16 *TempString; + CHAR16 *BufferedString; + UINTN Index; + UINTN Count; + UINTN Start; + UINTN Top; + CHAR16 *PromptForDataString; + UINTN DimensionsWidth; + UINTN DimensionsHeight; + BOOLEAN CursorVisible; + + DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; + DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; + + PromptForDataString = GetToken (STRING_TOKEN (PROMPT_FOR_DATA), gHiiHandle); + + NullCharacter = CHAR_NULL; + ScreenSize = GetStringWidth (PromptForDataString) / 2; + Tag = MenuOption->ThisTag; + Space[0] = L' '; + Space[1] = CHAR_NULL; + SelectionComplete = FALSE; + + TempString = AllocateZeroPool (MenuOption->ThisTag->Maximum * 2); + ASSERT (TempString); + + if (ScreenSize < (Tag->Maximum / (UINTN) 2)) { + ScreenSize = Tag->Maximum / 2; + } + + if ((ScreenSize + 2) > DimensionsWidth) { + ScreenSize = DimensionsWidth - 2; + } + + BufferedString = AllocateZeroPool (ScreenSize * 2); + ASSERT (BufferedString); + + Start = (DimensionsWidth - ScreenSize - 2) / 2 + gScreenDimensions.LeftColumn + 1; + Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1; + + // + // Display prompt for string + // + CreatePopUp (ScreenSize, 4, &NullCharacter, PromptForDataString, Space, &NullCharacter); + + gBS->FreePool (PromptForDataString); + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY)); + + CursorVisible = gST->ConOut->Mode->CursorVisible; + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + + do { + Status = WaitForKeyStroke (&Key); + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY)); + switch (Key.UnicodeChar) { + case CHAR_NULL: + switch (Key.ScanCode) { + case SCAN_LEFT: + break; + + case SCAN_RIGHT: + break; + + case SCAN_ESC: + gBS->FreePool (TempString); + gBS->FreePool (BufferedString); + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); + return EFI_DEVICE_ERROR; + + default: + break; + } + + break; + + case CHAR_CARRIAGE_RETURN: + if (GetStringWidth (StringPtr) >= MenuOption->ThisTag->Minimum) { + SelectionComplete = TRUE; + gBS->FreePool (TempString); + gBS->FreePool (BufferedString); + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); + return EFI_SUCCESS; + } else { + ScreenSize = GetStringWidth (gMiniString) / 2; + CreatePopUp (ScreenSize, 4, &NullCharacter, gMiniString, gPressEnter, &NullCharacter); + // + // Simply create a popup to tell the user that they had typed in too few characters. + // To save code space, we can then treat this as an error and return back to the menu. + // + do { + Status = WaitForKeyStroke (&Key); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + gBS->FreePool (TempString); + gBS->FreePool (BufferedString); + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); + return EFI_DEVICE_ERROR; + } + + break; + + case CHAR_BACKSPACE: + if (StringPtr[0] != CHAR_NULL) { + for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) { + TempString[Index] = StringPtr[Index]; + } + // + // Effectively truncate string by 1 character + // + TempString[Index - 1] = CHAR_NULL; + StrCpy (StringPtr, TempString); + } + + default: + // + // If it is the beginning of the string, don't worry about checking maximum limits + // + if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) { + StrnCpy (StringPtr, &Key.UnicodeChar, 1); + StrnCpy (TempString, &Key.UnicodeChar, 1); + } else if ((GetStringWidth (StringPtr) < MenuOption->ThisTag->Maximum) && (Key.UnicodeChar != CHAR_BACKSPACE)) { + KeyPad[0] = Key.UnicodeChar; + KeyPad[1] = CHAR_NULL; + StrCat (StringPtr, KeyPad); + StrCat (TempString, KeyPad); + } + // + // If the width of the input string is now larger than the screen, we nee to + // adjust the index to start printing portions of the string + // + SetUnicodeMem (BufferedString, ScreenSize - 1, L' '); + + PrintStringAt (Start + 1, Top + 3, BufferedString); + + if ((GetStringWidth (StringPtr) / 2) > (DimensionsWidth - 2)) { + Index = (GetStringWidth (StringPtr) / 2) - DimensionsWidth + 2; + } else { + Index = 0; + } + + for (Count = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++, Count++) { + BufferedString[Count] = StringPtr[Index]; + } + + PrintStringAt (Start + 1, Top + 3, BufferedString); + break; + } + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->SetCursorPosition (gST->ConOut, Start + GetStringWidth (StringPtr) / 2, Top + 3); + } while (!SelectionComplete); + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->EnableCursor (gST->ConOut, CursorVisible); + return Status; +} + +EFI_STATUS +ReadPassword ( + IN UI_MENU_OPTION *MenuOption, + IN BOOLEAN PromptForPassword, + IN EFI_TAG *Tag, + IN EFI_IFR_DATA_ARRAY *PageData, + IN BOOLEAN SecondEntry, + IN EFI_FILE_FORM_TAGS *FileFormTags, + OUT CHAR16 *StringPtr + ) +{ + EFI_STATUS Status; + UINTN PasswordSize; + UINTN ScreenSize; + CHAR16 NullCharacter; + CHAR16 Space[2]; + EFI_INPUT_KEY Key; + CHAR16 KeyPad[2]; + UINTN Index; + UINTN Start; + UINTN Top; + CHAR16 *TempString; + CHAR16 *TempString2; + BOOLEAN Confirmation; + BOOLEAN ConfirmationComplete; + EFI_HII_CALLBACK_PACKET *Packet; + EFI_FORM_CALLBACK_PROTOCOL *FormCallback; + EFI_VARIABLE_DEFINITION *VariableDefinition; + UINTN DimensionsWidth; + UINTN DimensionsHeight; + EFI_IFR_DATA_ENTRY *DataEntry; + + DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; + DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; + + VariableDefinition = NULL; + PasswordSize = 0; + NullCharacter = CHAR_NULL; + Space[0] = L' '; + Space[1] = CHAR_NULL; + Confirmation = FALSE; + ConfirmationComplete = FALSE; + Status = EFI_SUCCESS; + FormCallback = NULL; + Packet = NULL; + + // + // Remember that dynamic pages in an environment where all pages are not + // dynamic require us to call back to the user to give them an opportunity + // to register fresh information in the HII database so that we can extract it. + // + Status = gBS->HandleProtocol ( + (VOID *) (UINTN) MenuOption->Tags[0].CallbackHandle, + &gEfiFormCallbackProtocolGuid, + (VOID **) &FormCallback + ); + + TempString = AllocateZeroPool (MenuOption->ThisTag->Maximum * 2); + TempString2 = AllocateZeroPool (MenuOption->ThisTag->Maximum * 2); + + ASSERT (TempString); + ASSERT (TempString2); + + if (Tag->Flags & EFI_IFR_FLAG_INTERACTIVE) { + // + // Password requires a callback to determine if a password exists + // + DataEntry = (EFI_IFR_DATA_ENTRY *) (PageData + 1); + DataEntry->OpCode = EFI_IFR_PASSWORD_OP; + DataEntry->Length = 3; + + ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition); + + // + // The user is about to be prompted with a password field, Data = 0 (Return Status determines the type of prompt) + // + DataEntry->Data = (VOID *) (UINTN) (UINT8) (0 + SecondEntry * 2); + PageData->NvRamMap = VariableDefinition->NvRamMap; + + if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) { + Status = FormCallback->Callback ( + FormCallback, + Tag->Key, + PageData, + &Packet + ); + } + // + // If error on return, continue with the reading of a typed in password to verify user knows password + // If no error, there is no password set, so prompt for new password + // if the previous callback was to verify the user knew password, and user typed it correctly - should return no error + // + if (!EFI_ERROR (Status)) { + PromptForPassword = FALSE; + + // + // Simulate this as the second entry into this routine for an interactive behavior + // + SecondEntry = TRUE; + } else if (Status == EFI_NOT_READY) { +Error: + if (Packet != NULL) { + // + // Upon error, we will likely receive a string to print out + // Display error popup + // + ScreenSize = EFI_MAX(GetStringWidth (Packet->String), GetStringWidth (gPressEnter)) / 2; + CreatePopUp (ScreenSize, 4, &NullCharacter, Packet->String, gPressEnter, &NullCharacter); + gBS->FreePool (Packet); + + do { + Status = WaitForKeyStroke (&Key); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + } + + gBS->FreePool (TempString); + gBS->FreePool (TempString2); + return EFI_NOT_READY; + } + } + + do { + // + // Display PopUp Screen + // + ScreenSize = GetStringWidth (gPromptForNewPassword) / 2; + if (GetStringWidth (gConfirmPassword) / 2 > ScreenSize) { + ScreenSize = GetStringWidth (gConfirmPassword) / 2; + } + + Start = (DimensionsWidth - ScreenSize - 4) / 2 + gScreenDimensions.LeftColumn + 2; + Top = ((DimensionsHeight - 6) / 2) + gScreenDimensions.TopRow - 1; + + if (!Confirmation) { + if (PromptForPassword) { + CreatePopUp (ScreenSize, 4, &NullCharacter, gPromptForPassword, Space, &NullCharacter); + } else { + CreatePopUp (ScreenSize, 4, &NullCharacter, gPromptForNewPassword, Space, &NullCharacter); + } + } else { + CreatePopUp (ScreenSize, 4, &NullCharacter, gConfirmPassword, Space, &NullCharacter); + StringPtr[0] = CHAR_NULL; + } + + do { + Status = WaitForKeyStroke (&Key); + + switch (Key.UnicodeChar) { + case CHAR_NULL: + if (Key.ScanCode == SCAN_ESC) { + return EFI_NOT_READY; + } + + ConfirmationComplete = FALSE; + break; + + case CHAR_CARRIAGE_RETURN: + if (Tag->Flags & EFI_IFR_FLAG_INTERACTIVE) { + // + // User just typed a string in + // + DataEntry = (EFI_IFR_DATA_ENTRY *) (PageData + 1); + DataEntry->OpCode = EFI_IFR_PASSWORD_OP; + + // + // If the user just typed in a password, Data = 1 + // If the user just typed in a password to confirm the previous password, Data = 2 + // + if (!Confirmation) { + DataEntry->Length = 3; + DataEntry->Data = (VOID *) (UINTN) (UINT8) (1 + SecondEntry * 2); + + if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) { + Status = FormCallback->Callback ( + FormCallback, + Tag->Key, + PageData, + &Packet + ); + } + + DataEntry->Length = sizeof (EFI_IFR_DATA_ENTRY); + DataEntry->Data = (VOID *) TempString; + } else { + DataEntry->Length = 3; + DataEntry->Data = (VOID *) (UINTN) (UINT8) (2 + SecondEntry * 2); + + if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) { + Status = FormCallback->Callback ( + FormCallback, + Tag->Key, + PageData, + &Packet + ); + } + + DataEntry->Length = sizeof (EFI_IFR_DATA_ENTRY); + DataEntry->Data = (VOID *) TempString2; + } + + if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) { + Status = FormCallback->Callback ( + FormCallback, + Tag->Key, + PageData, + &Packet + ); + } + // + // If this was the confirmation round of callbacks + // and an error comes back, display an error + // + if (Confirmation) { + if (EFI_ERROR (Status)) { + if (Packet->String == NULL) { + ScreenSize = EFI_MAX (GetStringWidth (gConfirmError), GetStringWidth (gPressEnter)) / 2; + CreatePopUp (ScreenSize, 4, &NullCharacter, gConfirmError, gPressEnter, &NullCharacter); + } else { + ScreenSize = EFI_MAX (GetStringWidth (Packet->String), GetStringWidth (gPressEnter)) / 2; + CreatePopUp (ScreenSize, 4, &NullCharacter, Packet->String, gPressEnter, &NullCharacter); + gBS->FreePool (Packet); + } + + StringPtr[0] = CHAR_NULL; + do { + Status = WaitForKeyStroke (&Key); + + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + gBS->FreePool (TempString); + gBS->FreePool (TempString2); + return EFI_NOT_READY; + } + } while (1); + } else { + gBS->FreePool (TempString); + gBS->FreePool (TempString2); + return EFI_NOT_READY; + } + } else { + // + // User typed a string in and it wasn't valid somehow from the callback + // For instance, callback may have said that some invalid characters were contained in the string + // + if (Status == EFI_NOT_READY) { + goto Error; + } + + if (PromptForPassword && EFI_ERROR (Status)) { + gBS->FreePool (TempString); + gBS->FreePool (TempString2); + return EFI_DEVICE_ERROR; + } + } + } + + if (Confirmation) { + // + // Compare tempstring and tempstring2, if the same, return with StringPtr success + // Otherwise, kick and error box, and return an error + // + if (StrCmp (TempString, TempString2) == 0) { + gBS->FreePool (TempString); + gBS->FreePool (TempString2); + return EFI_SUCCESS; + } else { + ScreenSize = EFI_MAX (GetStringWidth (gConfirmError), GetStringWidth (gPressEnter)) / 2; + CreatePopUp (ScreenSize, 4, &NullCharacter, gConfirmError, gPressEnter, &NullCharacter); + StringPtr[0] = CHAR_NULL; + do { + Status = WaitForKeyStroke (&Key); + if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) { + gBS->FreePool (TempString); + gBS->FreePool (TempString2); + return EFI_DEVICE_ERROR; + } + } while (1); + } + } + + if (PromptForPassword) { + // + // I was asked for a password, return it back in StringPtr + // + gBS->FreePool (TempString); + gBS->FreePool (TempString2); + return EFI_SUCCESS; + } else { + // + // If the two passwords were not the same kick an error popup + // + Confirmation = TRUE; + ConfirmationComplete = TRUE; + break; + } + + case CHAR_BACKSPACE: + if (StringPtr[0] != CHAR_NULL) { + if (!Confirmation) { + for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) { + TempString[Index] = StringPtr[Index]; + } + // + // Effectively truncate string by 1 character + // + TempString[Index - 1] = CHAR_NULL; + StrCpy (StringPtr, TempString); + } else { + for (Index = 0; StringPtr[Index] != CHAR_NULL; Index++) { + TempString2[Index] = StringPtr[Index]; + } + // + // Effectively truncate string by 1 character + // + TempString2[Index - 1] = CHAR_NULL; + StrCpy (StringPtr, TempString2); + } + + ConfirmationComplete = FALSE; + } else { + ConfirmationComplete = FALSE; + } + + // + // Must be a character we are interested in! + // + default: + if ((StringPtr[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) { + if (!Confirmation) { + StrnCpy (StringPtr, &Key.UnicodeChar, 1); + StrnCpy (TempString, &Key.UnicodeChar, 1); + } else { + StrnCpy (StringPtr, &Key.UnicodeChar, 1); + StrnCpy (TempString2, &Key.UnicodeChar, 1); + ConfirmationComplete = FALSE; + } + } else if ((GetStringWidth (StringPtr) / 2 <= (UINTN) (MenuOption->ThisTag->Maximum - 1) / 2) && + (Key.UnicodeChar != CHAR_BACKSPACE) + ) { + KeyPad[0] = Key.UnicodeChar; + KeyPad[1] = CHAR_NULL; + if (!Confirmation) { + StrCat (StringPtr, KeyPad); + StrCat (TempString, KeyPad); + } else { + StrCat (StringPtr, KeyPad); + StrCat (TempString2, KeyPad); + } + } + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_BLACK, EFI_LIGHTGRAY)); + for (Index = 1; Index < ScreenSize; Index++) { + PrintCharAt (Start + Index, Top + 3, L' '); + } + + gST->ConOut->SetCursorPosition ( + gST->ConOut, + (DimensionsWidth - GetStringWidth (StringPtr) / 2) / 2 + gScreenDimensions.LeftColumn, + Top + 3 + ); + for (Index = 0; Index + 1 < GetStringWidth (StringPtr) / 2; Index++) { + PrintChar (L'*'); + } + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + break; + } + // + // end switch + // + } while (!ConfirmationComplete); + + } while (1); + gBS->FreePool (TempString); + gBS->FreePool (TempString2); + return Status; +} + +VOID +EncodePassword ( + IN CHAR16 *Password, + IN UINT8 MaxSize + ) +{ + UINTN Index; + UINTN Loop; + CHAR16 *Buffer; + CHAR16 *Key; + + Key = (CHAR16 *) L"MAR10648567"; + Buffer = AllocateZeroPool (MaxSize); + + ASSERT (Buffer); + + for (Index = 0; Key[Index] != 0; Index++) { + for (Loop = 0; Loop < (UINT8) (MaxSize / 2); Loop++) { + Buffer[Loop] = (CHAR16) (Password[Loop] ^ Key[Index]); + } + } + + CopyMem (Password, Buffer, MaxSize); + + gBS->FreePool (Buffer); + return ; +} + +EFI_STATUS +GetNumericInput ( + IN UI_MENU_OPTION *MenuOption, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN BOOLEAN ManualInput, + IN EFI_TAG *Tag, + IN UINTN NumericType, + OUT UINT16 *Value + ) +/*++ + +Routine Description: + + This routine reads a numeric value from the user input. + +Arguments: + + MenuOption - Pointer to the current input menu. + + FileFormTagsHead - Pointer to the root of formset. + + ManualInput - If the input is manual or not. + + Tag - Pointer to all the attributes and values associated with a tag. + + Value - Pointer to the numeric value that is going to be read. + +Returns: + + EFI_SUCCESS - If numerical input is read successfully + EFI_DEVICE_ERROR - If operation fails + +--*/ +{ + EFI_INPUT_KEY Key; + BOOLEAN SelectionComplete; + UINTN Column; + UINTN Row; + CHAR16 FormattedNumber[6]; + UINTN PreviousNumber[6]; + INTN Number; + UINTN Count; + UINT16 BackupValue; + STRING_REF PopUp; + CHAR16 NullCharacter; + CHAR16 *StringPtr; + EFI_FILE_FORM_TAGS *FileFormTags; + EFI_STATUS Status; + EFI_VARIABLE_DEFINITION *VariableDefinition; + UINTN Loop; + + NullCharacter = CHAR_NULL; + StringPtr = NULL; + Column = MenuOption->OptCol; + Row = MenuOption->Row; + Number = 0; + PreviousNumber[0] = 0; + Count = 0; + SelectionComplete = FALSE; + BackupValue = Tag->Value; + FileFormTags = FileFormTagsHead; + + if (ManualInput) { + PrintAt (Column, Row, (CHAR16 *) L"[ ]"); + Column++; + if (Tag->Operand != EFI_IFR_TIME_OP) { + *Value = BackupValue; + } + } + // + // First time we enter this handler, we need to check to see if + // we were passed an increment or decrement directive + // + do { + Key.UnicodeChar = CHAR_NULL; + if (gDirection != 0) { + Key.ScanCode = gDirection; + gDirection = 0; + goto TheKey2; + } + + Status = WaitForKeyStroke (&Key); + +TheKey2: + switch (Key.UnicodeChar) { + case '+': + case '-': + if ((Tag->Operand == EFI_IFR_DATE_OP) || (Tag->Operand == EFI_IFR_TIME_OP)) { + Key.UnicodeChar = CHAR_NULL; + if (Key.UnicodeChar == '+') { + Key.ScanCode = SCAN_RIGHT; + } else { + Key.ScanCode = SCAN_LEFT; + } + + goto TheKey2; + } + break; + + case CHAR_NULL: + switch (Key.ScanCode) { + case SCAN_LEFT: + case SCAN_RIGHT: + if ((Tag->Operand == EFI_IFR_DATE_OP) || (Tag->Operand == EFI_IFR_TIME_OP)) { + // + // By setting this value, we will return back to the caller. + // We need to do this since an auto-refresh will destroy the adjustment + // based on what the real-time-clock is showing. So we always commit + // upon changing the value. + // + gDirection = SCAN_DOWN; + } + + if (!ManualInput) { + Tag->Value = *Value; + if (Key.ScanCode == SCAN_LEFT) { + Number = *Value - Tag->Step; + if (Number < Tag->Minimum) { + Number = Tag->Minimum; + } + } else if (Key.ScanCode == SCAN_RIGHT) { + Number = *Value + Tag->Step; + if (Number > Tag->Maximum) { + Number = Tag->Maximum; + } + } + + Tag->Value = (UINT16) Number; + *Value = (UINT16) Number; + UnicodeValueToString ( + FormattedNumber, + FALSE, + (UINTN) Number, + (sizeof (FormattedNumber) / sizeof (FormattedNumber[0])) + ); + Number = (UINT16) GetStringWidth (FormattedNumber); + + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + if ((Tag->Operand == EFI_IFR_DATE_OP) || (Tag->Operand == EFI_IFR_TIME_OP)) { + for (Loop = 0; Loop < (UINTN) ((Number >= 8) ? 4 : 2); Loop++) { + PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, (CHAR16 *) L" "); + } + } else { + for (Loop = 0; Loop < gOptionBlockWidth; Loop++) { + PrintAt (MenuOption->OptCol + Loop, MenuOption->Row, (CHAR16 *) L" "); + } + } + + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT); + + if ((MenuOption->Col + gPromptBlockWidth + 1) == MenuOption->OptCol) { + PrintCharAt (MenuOption->OptCol, Row, LEFT_NUMERIC_DELIMITER); + Column = MenuOption->OptCol + 1; + } + // + // If Number looks like "3", convert it to "03/" + // + if (Number == 4 && (NumericType == DATE_NUMERIC)) { + FormattedNumber[3] = FormattedNumber[1]; + FormattedNumber[2] = DATE_SEPARATOR; + FormattedNumber[1] = FormattedNumber[0]; + FormattedNumber[0] = L'0'; + Number = 8; + } + // + // If Number looks like "13", convert it to "13/" + // + if (Number == 6 && (NumericType == DATE_NUMERIC)) { + FormattedNumber[3] = FormattedNumber[2]; + FormattedNumber[2] = DATE_SEPARATOR; + Number = 8; + } + + if (Number == 4 && + (NumericType == TIME_NUMERIC) && + (MenuOption->Col + gPromptBlockWidth + 8) != MenuOption->OptCol + ) { + FormattedNumber[3] = FormattedNumber[1]; + FormattedNumber[2] = TIME_SEPARATOR; + FormattedNumber[1] = FormattedNumber[0]; + FormattedNumber[0] = L'0'; + Number = 8; + } + + if (Number == 4 && + (NumericType == TIME_NUMERIC) && + (MenuOption->Col + gPromptBlockWidth + 8) == MenuOption->OptCol + ) { + FormattedNumber[3] = FormattedNumber[1]; + FormattedNumber[2] = RIGHT_NUMERIC_DELIMITER; + FormattedNumber[1] = FormattedNumber[0]; + FormattedNumber[0] = L'0'; + Number = 8; + } + + PrintStringAt (Column, Row, FormattedNumber); + if (Number == 10 && (NumericType == DATE_NUMERIC)) { + PrintChar (RIGHT_NUMERIC_DELIMITER); + } + + if (NumericType == REGULAR_NUMERIC) { + PrintChar (RIGHT_NUMERIC_DELIMITER); + } + } + break; + + case SCAN_UP: + case SCAN_DOWN: + goto EnterCarriageReturn; + + case SCAN_ESC: + return EFI_DEVICE_ERROR; + + default: + break; + } + + break; + +EnterCarriageReturn: + + case CHAR_CARRIAGE_RETURN: + // + // Check to see if the Value is something reasonable against consistency limitations. + // If not, let's kick the error specified. + // + // + // This gives us visibility to the FileFormTags->NvRamMap to check things + // ActiveIfr is a global maintained by the menuing code to ensure that we + // are pointing to the correct formset's file data. + // + for (Count = 0; Count < gActiveIfr; Count++) { + FileFormTags = FileFormTags->NextFile; + } + + ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition); + + CopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], &Tag->Value, Tag->StorageWidth); + + // + // Data associated with a NULL device (in the fake NV storage) + // + if (Tag->StorageWidth == (UINT16) 0) { + CopyMem (&VariableDefinition->FakeNvRamMap[Tag->StorageStart], &Tag->Value, 2); + } + // + // If a late check is required save off the information. This is used when consistency checks + // are required, but certain values might be bound by an impossible consistency check such as + // if two questions are bound by consistency checks and each only has two possible choices, there + // would be no way for a user to switch the values. Thus we require late checking. + // + if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) { + CopyMem (&Tag->OldValue, &BackupValue, Tag->StorageWidth); + } else { + // + // In theory, passing the value and the Id are sufficient to determine what needs + // to be done. The Id is the key to look for the entry needed in the Inconsistency + // database. That will yields operand and ID data - and since the ID's correspond + // to the NV storage, we can determine the values for other IDs there. + // + if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) { + if (PopUp == 0x0000) { + SelectionComplete = TRUE; + break; + } + + StringPtr = GetToken (PopUp, MenuOption->Handle); + + CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter); + + do { + Status = WaitForKeyStroke (&Key); + + switch (Key.UnicodeChar) { + + case CHAR_CARRIAGE_RETURN: + SelectionComplete = TRUE; + gBS->FreePool (StringPtr); + break; + + default: + break; + } + } while (!SelectionComplete); + + Tag->Value = BackupValue; + *Value = BackupValue; + + CopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], &Tag->Value, Tag->StorageWidth); + + // + // Data associated with a NULL device (in the fake NV storage) + // + if (Tag->StorageWidth == (UINT16) 0) { + CopyMem (&VariableDefinition->FakeNvRamMap[Tag->StorageStart], &Tag->Value, 2); + } + + return EFI_DEVICE_ERROR; + } + } + + return EFI_SUCCESS; + break; + + case CHAR_BACKSPACE: + if (ManualInput) { + if (Count == 0) { + break; + } + // + // Remove a character + // + Number = PreviousNumber[Count - 1]; + *Value = (UINT16) Number; + UpdateStatusBar (INPUT_ERROR, Tag->Flags, FALSE); + Count--; + Column--; + PrintAt (Column, Row, (CHAR16 *) L" "); + } + break; + + default: + if (ManualInput) { + if (Key.UnicodeChar > L'9' || Key.UnicodeChar < L'0') { + UpdateStatusBar (INPUT_ERROR, Tag->Flags, TRUE); + break; + } + // + // If Count 0-4 is complete, there is no way more is valid + // + if (Count > 4) { + break; + } + // + // Someone typed something valid! + // + if (Count != 0) { + Number = Number * 10 + (Key.UnicodeChar - L'0'); + } else { + Number = Key.UnicodeChar - L'0'; + } + + if (Number > Tag->Maximum) { + UpdateStatusBar (INPUT_ERROR, Tag->Flags, TRUE); + Number = PreviousNumber[Count]; + break; + } else { + UpdateStatusBar (INPUT_ERROR, Tag->Flags, FALSE); + } + + Count++; + + PreviousNumber[Count] = Number; + *Value = (UINT16) Number; + Tag->Value = (UINT16) Number; + + PrintCharAt (Column, Row, Key.UnicodeChar); + Column++; + } + break; + } + } while (!SelectionComplete); + return EFI_SUCCESS; +} +// +// Notice that this is at least needed for the ordered list manipulation. +// Left/Right doesn't make sense for this op-code +// +EFI_STATUS +GetSelectionInputPopUp ( + IN UI_MENU_OPTION *MenuOption, + IN EFI_TAG *Tag, + IN UINTN ValueCount, + OUT UINT16 *Value, + OUT UINT16 *KeyValue + ) +{ + EFI_STATUS Status; + EFI_INPUT_KEY Key; + UINTN Index; + UINTN TempIndex; + CHAR16 *StringPtr; + CHAR16 *TempStringPtr; + UINT16 Token; + UINTN Index2; + UINTN TopOptionIndex; + UINTN HighlightPosition; + UINTN Start; + UINTN End; + UINTN Top; + UINTN Bottom; + UINT16 TempValue; + UINTN Count; + UINTN PopUpMenuLines; + UINTN MenuLinesInView; + UINTN PopUpWidth; + CHAR16 Character; + UINTN FirstOption; + BOOLEAN FirstOptionFoundFlag; + INT32 SavedAttribute; + EFI_TAG TagBackup; + UINT8 *ValueArray; + UINT8 *ValueArrayBackup; + UINT8 ValueBackup; + BOOLEAN Initialized; + BOOLEAN KeyInitialized; + BOOLEAN ShowDownArrow; + BOOLEAN ShowUpArrow; + UINTN DimensionsWidth; + UINTN DimensionsHeight; + + DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; + DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; + + TempValue = 0; + TempIndex = 0; + ValueArray = (UINT8 *) Value; + ValueArrayBackup = NULL; + Initialized = FALSE; + KeyInitialized = FALSE; + ShowDownArrow = FALSE; + ShowUpArrow = FALSE; + + if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) { + ValueArrayBackup = AllocateZeroPool (Tag->StorageWidth); + ASSERT (ValueArrayBackup != NULL); + CopyMem (ValueArrayBackup, ValueArray, ValueCount); + TempValue = *(UINT8 *) (ValueArray); + if (ValueArray[0] != 0x00) { + Initialized = TRUE; + } + + for (Index = 0; ValueArray[Index] != 0x00; Index++) + ; + ValueCount = Index; + } else { + TempValue = *Value; + } + + Count = 0; + PopUpWidth = 0; + + FirstOption = MenuOption->TagIndex; + FirstOptionFoundFlag = FALSE; + + StringPtr = AllocateZeroPool ((gOptionBlockWidth + 1) * 2); + ASSERT (StringPtr); + + // + // Initialization for "One of" pop-up menu + // + // + // Get the number of one of options present and its size + // + for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; Index++) { + if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP && + !MenuOption->Tags[Index].Suppress) { + if (!FirstOptionFoundFlag) { + FirstOption = Index; + FirstOptionFoundFlag = TRUE; + } + + Count++; + Token = MenuOption->Tags[Index].Text; + + // + // If this is an ordered list that is initialized + // + if (Initialized) { + for (ValueBackup = (UINT8) MenuOption->TagIndex; + MenuOption->Tags[ValueBackup].Operand != EFI_IFR_END_OP; + ValueBackup++ + ) { + if (MenuOption->Tags[ValueBackup].Value == ((UINT8 *) ValueArrayBackup)[Index - MenuOption->TagIndex - 1]) { + StringPtr = GetToken (MenuOption->Tags[ValueBackup].Text, MenuOption->Handle); + break; + } + } + } else { + StringPtr = GetToken (Token, MenuOption->Handle); + } + + if (StrLen (StringPtr) > PopUpWidth) { + PopUpWidth = StrLen (StringPtr); + } + + gBS->FreePool (StringPtr); + } + } + // + // Perform popup menu initialization. + // + PopUpMenuLines = Count; + PopUpWidth = PopUpWidth + POPUP_PAD_SPACE_COUNT; + + SavedAttribute = gST->ConOut->Mode->Attribute; + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + + if ((PopUpWidth + POPUP_FRAME_WIDTH) > DimensionsWidth) { + PopUpWidth = DimensionsWidth - POPUP_FRAME_WIDTH; + } + + Start = (DimensionsWidth - PopUpWidth - POPUP_FRAME_WIDTH) / 2 + gScreenDimensions.LeftColumn; + End = Start + PopUpWidth + POPUP_FRAME_WIDTH; + Top = gScreenDimensions.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT; + Bottom = gScreenDimensions.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT; + + MenuLinesInView = Bottom - Top - 1; + if (MenuLinesInView >= PopUpMenuLines) { + Top = Top + (MenuLinesInView - PopUpMenuLines) / 2; + Bottom = Top + PopUpMenuLines + 1; + } else { + TempValue = MenuOption->Tags[MenuOption->TagIndex + 1].Value; + ShowDownArrow = TRUE; + } + + TopOptionIndex = 1; + HighlightPosition = 0; + do { + if (Initialized) { + for (Index = MenuOption->TagIndex, Index2 = 0; Index2 < ValueCount; Index++, Index2++) { + // + // Set the value for the item we are looking for + // + Count = ValueArrayBackup[Index2]; + + // + // If we hit the end of the Array, we are complete + // + if (Count == 0) { + break; + } + + if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) { + for (ValueBackup = (UINT8) MenuOption->TagIndex; + MenuOption->Tags[ValueBackup].Operand != EFI_IFR_END_ONE_OF_OP; + ValueBackup++ + ) { + // + // We just found what we are looking for + // + if (MenuOption->Tags[ValueBackup].Value == Count) { + // + // As long as the two indexes aren't the same, we have + // two different op-codes we need to swap internally + // + if (Index != ValueBackup) { + // + // Backup destination tag, then copy source to destination, then copy backup to source location + // + CopyMem (&TagBackup, &MenuOption->Tags[Index], sizeof (EFI_TAG)); + CopyMem (&MenuOption->Tags[Index], &MenuOption->Tags[ValueBackup], sizeof (EFI_TAG)); + CopyMem (&MenuOption->Tags[ValueBackup], &TagBackup, sizeof (EFI_TAG)); + } else { + // + // If the indexes are the same, then the op-code is where he belongs + // + } + } + } + } else { + // + // Since this wasn't an option op-code (likely the ordered list op-code) decerement Index2 + // + Index2--; + } + } + } + // + // Clear that portion of the screen + // + ClearLines (Start, End, Top, Bottom, POPUP_TEXT | POPUP_BACKGROUND); + + // + // Draw "One of" pop-up menu + // + Character = (CHAR16) BOXDRAW_DOWN_RIGHT; + PrintCharAt (Start, Top, Character); + for (Index = Start; Index + 2 < End; Index++) { + if ((ShowUpArrow) && ((Index + 1) == (Start + End) / 2)) { + Character = (CHAR16) GEOMETRICSHAPE_UP_TRIANGLE; + } else { + Character = (CHAR16) BOXDRAW_HORIZONTAL; + } + + PrintChar (Character); + } + + Character = (CHAR16) BOXDRAW_DOWN_LEFT; + PrintChar (Character); + Character = (CHAR16) BOXDRAW_VERTICAL; + for (Index = Top + 1; Index < Bottom; Index++) { + PrintCharAt (Start, Index, Character); + PrintCharAt (End - 1, Index, Character); + } + // + // Display the One of options + // + Index2 = Top + 1; + for (Index = MenuOption->TagIndex + TopOptionIndex; + (MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP) && (Index2 < Bottom); + Index++ + ) { + if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) { + Token = MenuOption->Tags[Index].Text; + if (Initialized) { + for (ValueBackup = (UINT8) MenuOption->TagIndex; + MenuOption->Tags[ValueBackup].Operand != EFI_IFR_END_ONE_OF_OP; + ValueBackup++ + ) { + if (MenuOption->Tags[ValueBackup].Value == ((UINT8 *) ValueArrayBackup)[Index - MenuOption->TagIndex - 1]) { + StringPtr = GetToken (MenuOption->Tags[ValueBackup].Text, MenuOption->Handle); + break; + } + } + } else { + ValueBackup = (UINT8) Index; + StringPtr = GetToken (Token, MenuOption->Handle); + } + // + // If the string occupies multiple lines, truncate it to fit in one line, + // and append a "..." for indication. + // + if (StrLen (StringPtr) > (PopUpWidth - 1)) { + TempStringPtr = AllocateZeroPool (sizeof (CHAR16) * (PopUpWidth - 1)); + CopyMem (TempStringPtr, StringPtr, (sizeof (CHAR16) * (PopUpWidth - 5))); + gBS->FreePool (StringPtr); + StringPtr = TempStringPtr; + StrCat (StringPtr, (CHAR16 *) L"..."); + } + // + // Code to display the text should go here. Follwed by the [*] + // + if (MenuOption->Tags[ValueBackup].Suppress == TRUE) { + // + // Don't show the one, so decrease the Index2 for balance + // + Index2--; + } else if (MenuOption->Tags[ValueBackup].GrayOut == TRUE) { + // + // Gray Out the one + // + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | POPUP_BACKGROUND); + PrintStringAt (Start + 2, Index2, StringPtr); + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + } else if (MenuOption->Tags[ValueBackup].Value == TempValue) { + // + // Highlight the selected one + // + gST->ConOut->SetAttribute (gST->ConOut, PICKLIST_HIGHLIGHT_TEXT | PICKLIST_HIGHLIGHT_BACKGROUND); + PrintStringAt (Start + 2, Index2, StringPtr); + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + HighlightPosition = Index2; + } else { + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + PrintStringAt (Start + 2, Index2, StringPtr); + } + + gBS->FreePool (StringPtr); + Index2 = Index2 + 1; + } + } + + Character = (CHAR16) BOXDRAW_UP_RIGHT; + PrintCharAt (Start, Bottom, Character); + for (Index = Start; Index + 2 < End; Index++) { + if ((ShowDownArrow) && ((Index + 1) == (Start + End) / 2)) { + Character = (CHAR16) GEOMETRICSHAPE_DOWN_TRIANGLE; + } else { + Character = (CHAR16) BOXDRAW_HORIZONTAL; + } + + PrintChar (Character); + } + + Character = (CHAR16) BOXDRAW_UP_LEFT; + PrintChar (Character); + // + // Get User selection and change TempValue if necessary + // + // + // Stop: One of pop-up menu + // + Key.UnicodeChar = CHAR_NULL; + if ((gDirection == SCAN_UP) || (gDirection == SCAN_DOWN)) { + Key.ScanCode = gDirection; + gDirection = 0; + goto TheKey; + } + + if (!KeyInitialized) { + if (MenuOption->ThisTag->Operand == EFI_IFR_ONE_OF_OP) { + *KeyValue = MenuOption->Tags[MenuOption->TagIndex + 1].Key; + } else { + *KeyValue = MenuOption->ThisTag->Key; + } + + KeyInitialized = TRUE; + } + + Status = WaitForKeyStroke (&Key); + +TheKey: + switch (Key.UnicodeChar) { + case '+': + case '-': + // + // If an ordered list op-code, we will allow for a popup of +/- keys + // to create an ordered list of items + // + if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) { + if (Key.UnicodeChar == '+') { + if ((TopOptionIndex > 1) && (HighlightPosition == (Top + 1))) { + // + // Highlight reaches the top of the popup window, scroll one menu item. + // + TopOptionIndex--; + ShowDownArrow = TRUE; + } + + if (TopOptionIndex == 1) { + ShowUpArrow = FALSE; + } + } else { + if (((TopOptionIndex + MenuLinesInView) <= PopUpMenuLines) && (HighlightPosition == (Bottom - 1))) { + // + // Highlight reaches the bottom of the popup window, scroll one menu item. + // + TopOptionIndex++; + ShowUpArrow = TRUE; + } + + if ((TopOptionIndex + MenuLinesInView) == (PopUpMenuLines + 1)) { + ShowDownArrow = FALSE; + } + } + + for (Index = MenuOption->TagIndex + TopOptionIndex; + MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; + Index++ + ) { + if (MenuOption->Tags[Index].Operand == EFI_IFR_ORDERED_LIST_OP) { + continue; + } + + if (Key.UnicodeChar == '+') { + TempIndex = Index - 1; + } else { + TempIndex = Index + 1; + } + // + // Is this the current tag we are on? + // + if (MenuOption->Tags[Index].Value == TempValue) { + // + // Is this prior tag a valid choice? If not, bail out + // + if (MenuOption->Tags[TempIndex].Operand == EFI_IFR_ONE_OF_OPTION_OP) { + // + // Copy the destination tag to the local variable + // + CopyMem (&TagBackup, &MenuOption->Tags[TempIndex], sizeof (EFI_TAG)); + // + // Copy the current tag to the tag location before us + // + CopyMem (&MenuOption->Tags[TempIndex], &MenuOption->Tags[Index], sizeof (EFI_TAG)); + // + // Copy the backed up tag to the current location + // + CopyMem (&MenuOption->Tags[Index], &TagBackup, sizeof (EFI_TAG)); + + // + // Adjust the array of values + // + for (Index = 0; Index < ValueCount; Index++) { + if (ValueArrayBackup[Index] == (UINT8) TempValue) { + if (Key.UnicodeChar == '+') { + if (Index == 0) { + // + // It is the top of the array already + // + break; + } + + TempIndex = Index - 1; + } else { + if ((Index + 1) == ValueCount) { + // + // It is the bottom of the array already + // + break; + } + + TempIndex = Index + 1; + } + + ValueBackup = ValueArrayBackup[TempIndex]; + ValueArrayBackup[TempIndex] = ValueArrayBackup[Index]; + ValueArrayBackup[Index] = ValueBackup; + Initialized = TRUE; + break; + } + } + break; + } else { + break; + } + } + } + } + break; + + case CHAR_NULL: + switch (Key.ScanCode) { + case SCAN_UP: + case SCAN_DOWN: + if (Key.ScanCode == SCAN_UP) { + if ((TopOptionIndex > 1) && (HighlightPosition == (Top + 1))) { + // + // Highlight reaches the top of the popup window, scroll one menu item. + // + TopOptionIndex--; + ShowDownArrow = TRUE; + } + + if (TopOptionIndex == 1) { + ShowUpArrow = FALSE; + } + } else { + if (((TopOptionIndex + MenuLinesInView) <= PopUpMenuLines) && (HighlightPosition == (Bottom - 1))) { + // + // Highlight reaches the bottom of the popup window, scroll one menu item. + // + TopOptionIndex++; + ShowUpArrow = TRUE; + } + + if ((TopOptionIndex + MenuLinesInView) == (PopUpMenuLines + 1)) { + ShowDownArrow = FALSE; + } + } + + for (Index = MenuOption->TagIndex + TopOptionIndex; + MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; + Index++ + ) { + if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) { + if (Initialized) { + for (Index = 0; (ValueArrayBackup[Index] != TempValue) && (Index < ValueCount); Index++) + ; + + // + // Did we hit the end of the array? Either get the first TempValue or the next one + // + if (Key.ScanCode == SCAN_UP) { + if (Index == 0) { + TempValue = ValueArrayBackup[0]; + } else { + TempValue = ValueArrayBackup[Index - 1]; + } + } else { + if ((Index + 1) == ValueCount) { + TempValue = ValueArrayBackup[Index]; + } else { + TempValue = ValueArrayBackup[Index + 1]; + } + } + break; + } else { + if (Key.ScanCode == SCAN_UP) { + TempIndex = Index - 1; + + // + // Keep going until meets meaningful tag. + // + while ((MenuOption->Tags[TempIndex].Operand != EFI_IFR_ONE_OF_OPTION_OP && + MenuOption->Tags[TempIndex].Operand != EFI_IFR_ONE_OF_OP && + MenuOption->Tags[TempIndex].Operand != EFI_IFR_END_ONE_OF_OP) + || + (MenuOption->Tags[TempIndex].Operand == EFI_IFR_ONE_OF_OPTION_OP && + (MenuOption->Tags[TempIndex].Suppress || MenuOption->Tags[TempIndex].GrayOut))) { + TempIndex--; + } + } else { + TempIndex = Index + 1; + + // + // Keep going until meets meaningful tag. + // + while ((MenuOption->Tags[TempIndex].Operand != EFI_IFR_ONE_OF_OPTION_OP && + MenuOption->Tags[TempIndex].Operand != EFI_IFR_ONE_OF_OP && + MenuOption->Tags[TempIndex].Operand != EFI_IFR_END_ONE_OF_OP) + || + (MenuOption->Tags[TempIndex].Operand == EFI_IFR_ONE_OF_OPTION_OP && + (MenuOption->Tags[TempIndex].Suppress || MenuOption->Tags[TempIndex].GrayOut))) { + TempIndex++; + } + } + // + // The option value is the same as what is stored in NV store. This is where we take action + // + if (MenuOption->Tags[Index].Value == TempValue) { + // + // Only if the previous op-code is an option can we select it, otherwise we are at the left-most option + // + if (MenuOption->Tags[TempIndex].Operand == EFI_IFR_ONE_OF_OPTION_OP) { + TempValue = MenuOption->Tags[TempIndex].Value; + *KeyValue = MenuOption->Tags[TempIndex].Key; + } else { + TempValue = MenuOption->Tags[Index].Value; + *KeyValue = MenuOption->Tags[Index].Key; + } + break; + } + } + } + } + break; + + case SCAN_ESC: + gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); + if (ValueArrayBackup != NULL) { + gBS->FreePool (ValueArrayBackup); + } + + return EFI_DEVICE_ERROR; + + default: + break; + } + + break; + + case CHAR_CARRIAGE_RETURN: + // + // return the current selection + // + if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) { + CopyMem (ValueArray, ValueArrayBackup, ValueCount); + gBS->FreePool (ValueArrayBackup); + } else { + *Value = TempValue; + } + + gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); + return EFI_SUCCESS; + + default: + break; + } + } while (1); + + gST->ConOut->SetAttribute (gST->ConOut, SavedAttribute); + return EFI_SUCCESS; +} + +EFI_STATUS +WaitForKeyStroke ( + OUT EFI_INPUT_KEY *Key + ) +{ + EFI_STATUS Status; + + do { + UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0); + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, Key); + } while (EFI_ERROR(Status)); + + return Status; +} diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Presentation.c b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Presentation.c new file mode 100644 index 0000000000..cf3d0004d9 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Presentation.c @@ -0,0 +1,1481 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + Presentation.c + +Abstract: + + Some presentation routines. + +Revision History: + +--*/ + +#include "Setup.h" +#include "Ui.h" +#include "Colors.h" + +VOID +ClearLines ( + UINTN LeftColumn, + UINTN RightColumn, + UINTN TopRow, + UINTN BottomRow, + UINTN TextAttribute + ) +{ + CHAR16 *Buffer; + UINTN Row; + + // + // For now, allocate an arbitrarily long buffer + // + Buffer = AllocateZeroPool (0x10000); + ASSERT (Buffer != NULL); + + // + // Set foreground and background as defined + // + gST->ConOut->SetAttribute (gST->ConOut, TextAttribute); + + // + // Much faster to buffer the long string instead of print it a character at a time + // + SetUnicodeMem (Buffer, RightColumn - LeftColumn, L' '); + + // + // Clear the desired area with the appropriate foreground/background + // + for (Row = TopRow; Row <= BottomRow; Row++) { + PrintStringAt (LeftColumn, Row, Buffer); + } + + gST->ConOut->SetCursorPosition (gST->ConOut, LeftColumn, TopRow); + + gBS->FreePool (Buffer); + return ; +} + +VOID +NewStrCat ( + CHAR16 *Destination, + CHAR16 *Source + ) +{ + UINTN Length; + + for (Length = 0; Destination[Length] != 0; Length++) + ; + + // + // We now have the length of the original string + // We can safely assume for now that we are concatenating a narrow value to this string. + // For instance, the string is "XYZ" and cat'ing ">" + // If this assumption changes, we need to make this routine a bit more complex + // + Destination[Length] = (CHAR16) NARROW_CHAR; + Length++; + + StrCpy (Destination + Length, Source); +} + +UINTN +GetStringWidth ( + CHAR16 *String + ) +{ + UINTN Index; + UINTN Count; + UINTN IncrementValue; + + Index = 0; + Count = 0; + IncrementValue = 1; + + do { + // + // Advance to the null-terminator or to the first width directive + // + for (; + (String[Index] != NARROW_CHAR) && (String[Index] != WIDE_CHAR) && (String[Index] != 0); + Index++, Count = Count + IncrementValue + ) + ; + + // + // We hit the null-terminator, we now have a count + // + if (String[Index] == 0) { + break; + } + // + // We encountered a narrow directive - strip it from the size calculation since it doesn't get printed + // and also set the flag that determines what we increment by.(if narrow, increment by 1, if wide increment by 2) + // + if (String[Index] == NARROW_CHAR) { + // + // Skip to the next character + // + Index++; + IncrementValue = 1; + } else { + // + // Skip to the next character + // + Index++; + IncrementValue = 2; + } + } while (String[Index] != 0); + + // + // Increment by one to include the null-terminator in the size + // + Count++; + + return Count * sizeof (CHAR16); +} + +VOID +DisplayPageFrame ( + VOID + ) +{ + UINTN Index; + UINT8 Line; + UINT8 Alignment; + CHAR16 Character; + CHAR16 *Buffer; + CHAR16 *StrFrontPageBanner; + EFI_SCREEN_DESCRIPTOR LocalScreen; + UINTN Row; + + ZeroMem (&LocalScreen, sizeof (EFI_SCREEN_DESCRIPTOR)); + gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &LocalScreen.RightColumn, &LocalScreen.BottomRow); + ClearLines (0, LocalScreen.RightColumn, 0, LocalScreen.BottomRow, KEYHELP_BACKGROUND); + + CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + + // + // For now, allocate an arbitrarily long buffer + // + Buffer = AllocateZeroPool (0x10000); + ASSERT (Buffer != NULL); + + Character = (CHAR16) BOXDRAW_HORIZONTAL; + + for (Index = 0; Index + 2 < (LocalScreen.RightColumn - LocalScreen.LeftColumn); Index++) { + Buffer[Index] = Character; + } + + if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) { + // + // ClearLines(0, LocalScreen.RightColumn, 0, BANNER_HEIGHT-1, BANNER_TEXT | BANNER_BACKGROUND); + // + ClearLines ( + LocalScreen.LeftColumn, + LocalScreen.RightColumn, + LocalScreen.TopRow, + FRONT_PAGE_HEADER_HEIGHT - 1 + LocalScreen.TopRow, + BANNER_TEXT | BANNER_BACKGROUND + ); + // + // for (Line = 0; Line < BANNER_HEIGHT; Line++) { + // + for (Line = (UINT8) LocalScreen.TopRow; Line < BANNER_HEIGHT + (UINT8) LocalScreen.TopRow; Line++) { + // + // for (Alignment = 0; Alignment < BANNER_COLUMNS; Alignment++) { + // + for (Alignment = (UINT8) LocalScreen.LeftColumn; + Alignment < BANNER_COLUMNS + (UINT8) LocalScreen.LeftColumn; + Alignment++ + ) { + if (BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn] != 0x0000) { + StrFrontPageBanner = GetToken ( + BannerData->Banner[Line - (UINT8) LocalScreen.TopRow][Alignment - (UINT8) LocalScreen.LeftColumn], + FrontPageHandle + ); + } else { + continue; + } + + switch (Alignment - LocalScreen.LeftColumn) { + case 0: + // + // Handle left column + // + PrintStringAt (LocalScreen.LeftColumn, Line, StrFrontPageBanner); + break; + + case 1: + // + // Handle center column + // + PrintStringAt ( + LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3, + Line, + StrFrontPageBanner + ); + break; + + case 2: + // + // Handle right column + // + PrintStringAt ( + LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3, + Line, + StrFrontPageBanner + ); + break; + } + + gBS->FreePool (StrFrontPageBanner); + } + } + } + + ClearLines ( + LocalScreen.LeftColumn, + LocalScreen.RightColumn, + LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, + LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, + KEYHELP_TEXT | KEYHELP_BACKGROUND + ); + + if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) { + ClearLines ( + LocalScreen.LeftColumn, + LocalScreen.RightColumn, + LocalScreen.TopRow, + LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, + TITLE_TEXT | TITLE_BACKGROUND + ); + // + // Print Top border line + // +------------------------------------------------------------------------------+ + // ? ? + // +------------------------------------------------------------------------------+ + // + Character = (CHAR16) BOXDRAW_DOWN_RIGHT; + + PrintChar (Character); + PrintString (Buffer); + + Character = (CHAR16) BOXDRAW_DOWN_LEFT; + PrintChar (Character); + + Character = (CHAR16) BOXDRAW_VERTICAL; + for (Row = LocalScreen.TopRow + 1; Row <= LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 2; Row++) { + PrintCharAt (LocalScreen.LeftColumn, Row, Character); + PrintCharAt (LocalScreen.RightColumn - 1, Row, Character); + } + + Character = (CHAR16) BOXDRAW_UP_RIGHT; + PrintCharAt (LocalScreen.LeftColumn, LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT - 1, Character); + PrintString (Buffer); + + Character = (CHAR16) BOXDRAW_UP_LEFT; + PrintChar (Character); + + if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) { + // + // Print Bottom border line + // +------------------------------------------------------------------------------+ + // ? ? + // +------------------------------------------------------------------------------+ + // + Character = (CHAR16) BOXDRAW_DOWN_RIGHT; + PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT, Character); + + PrintString (Buffer); + + Character = (CHAR16) BOXDRAW_DOWN_LEFT; + PrintChar (Character); + Character = (CHAR16) BOXDRAW_VERTICAL; + for (Row = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT + 1; + Row <= LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 2; + Row++ + ) { + PrintCharAt (LocalScreen.LeftColumn, Row, Character); + PrintCharAt (LocalScreen.RightColumn - 1, Row, Character); + } + + Character = (CHAR16) BOXDRAW_UP_RIGHT; + PrintCharAt (LocalScreen.LeftColumn, LocalScreen.BottomRow - STATUS_BAR_HEIGHT - 1, Character); + + PrintString (Buffer); + + Character = (CHAR16) BOXDRAW_UP_LEFT; + PrintChar (Character); + } + } + + gBS->FreePool (Buffer); + +} + +/* ++------------------------------------------------------------------------------+ +?F2=Previous Page Setup Page ? ++------------------------------------------------------------------------------+ + + + + + + + + + + + + + + + + + ++------------------------------------------------------------------------------+ +?F1=Scroll Help F9=Reset to Defaults F10=Save and Exit ? +| ^"=Move Highlight Toggles Checkbox Esc=Discard Changes | ++------------------------------------------------------------------------------+ +*/ +UI_MENU_OPTION * +DisplayForm ( + OUT UI_MENU_OPTION *Selection, + IN UINT16 FormHandle, + IN UINT16 TitleToken, + IN EFI_FORM_TAGS FormTags, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN UINT8 *CallbackData + ) +{ + CHAR16 *StringPtr; + UINTN Index; + UINTN Count; + UINT16 MenuItemCount; + EFI_HII_HANDLE Handle; + UINT16 FormId; + STRING_REF String; + EFI_FILE_FORM_TAGS *FileFormTags; + BOOLEAN SuppressIf; + BOOLEAN Suppress; + BOOLEAN GrayOut; + BOOLEAN Conditional; + EFI_SCREEN_DESCRIPTOR LocalScreen; + UINT16 Width; + UINTN ArrayEntry; + CHAR16 *OutputString; + + Handle = Selection->Handle; + FormId = 0; + String = 0; + MenuItemCount = 0; + ArrayEntry = 0; + OutputString = NULL; + + CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + + // + // If we hit a F2 (previous) we already nuked the menu and are simply carrying around what information we need + // + if (Selection->Previous) { + Selection->Previous = FALSE; + } else { + UiFreeMenu (); + UiInitMenu (); + } + + StringPtr = GetToken (TitleToken, Handle); + + if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) { + gST->ConOut->SetAttribute (gST->ConOut, TITLE_TEXT | TITLE_BACKGROUND); + PrintStringAt ( + (LocalScreen.RightColumn + LocalScreen.LeftColumn - GetStringWidth (StringPtr) / 2) / 2, + LocalScreen.TopRow + 1, + StringPtr + ); + } + + if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) { + gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND); + + // + // Display the infrastructure strings + // + if (!IsListEmpty (&gMenuList)) { + PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.TopRow + 1, gFunctionTwoString); + } + + PrintStringAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 4, gFunctionOneString); + PrintStringAt ( + LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3, + LocalScreen.BottomRow - 4, + gFunctionNineString + ); + PrintStringAt ( + LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3, + LocalScreen.BottomRow - 4, + gFunctionTenString + ); + PrintAt (LocalScreen.LeftColumn + 2, LocalScreen.BottomRow - 3, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + PrintStringAt ( + LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3, + LocalScreen.BottomRow - 3, + gEscapeString + ); + } + // + // Remove Buffer allocated for StringPtr after it has been used. + // + gBS->FreePool (StringPtr); + + for (Index = 0; FormTags.Tags[Index].Operand != EFI_IFR_END_FORM_OP; Index++) { + GrayOut = FALSE; + Suppress = FALSE; + SuppressIf = FALSE; + Conditional = FALSE; + FileFormTags = FileFormTagsHead; + + if (FormTags.Tags[Index].Operand == EFI_IFR_FORM_OP) { + FormId = FormTags.Tags[Index].Id; + } + // + // This gives us visibility to the FileFormTags->NvRamMap to check things + // ActiveIfr is a global maintained by the menuing code to ensure that we + // are pointing to the correct formset's file data. + // + for (Count = 0; Count < gActiveIfr; Count++) { + FileFormTags = FileFormTags->NextFile; + } + // + // GrayoutIf [SuppressIf] + // + // OpCode(s) + // EndIf + // + // SuppressIf [GrayoutIf] + // + // OpCode(s) + // EndIf + // + Count = 0; + + do { + switch (FormTags.Tags[Index].Operand) { + case EFI_IFR_SUPPRESS_IF_OP: + SuppressIf = TRUE; + + case EFI_IFR_GRAYOUT_IF_OP: + + Conditional = TRUE; + + // + // Advance to the next op-code + // + Index++; + + // + // We are now pointing to the beginning of the consistency checking. Let's fast forward + // through the AND/OR/NOT data to come up with some meaningful ID data. + // + for (; + FormTags.Tags[Index].Operand == EFI_IFR_AND_OP || + FormTags.Tags[Index].Operand == EFI_IFR_OR_OP || + FormTags.Tags[Index].Operand == EFI_IFR_GT_OP || + FormTags.Tags[Index].Operand == EFI_IFR_GE_OP || + FormTags.Tags[Index].Operand == EFI_IFR_NOT_OP; + Index++ + ) + ; + + // + // We need to walk through the consistency checks until we hit the end of the consistency + // FALSE means evaluate this single expression + // The ConsistencyId refers to which expression in the Consistency database to use + // + if (SuppressIf) { + Suppress = ValueIsNotValid ( + FALSE, + FormTags.Tags[Index].ConsistencyId, + &FormTags.Tags[Index], + FileFormTags, + &String + ); + SuppressIf = FALSE; + } else { + GrayOut = ValueIsNotValid ( + FALSE, + FormTags.Tags[Index].ConsistencyId, + &FormTags.Tags[Index], + FileFormTags, + &String + ); + } + // + // Advance to the end of the expression (Will land us at a grayoutif/suppressif or the op-code being affected) + // + for (; + FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_VAL_OP || + FormTags.Tags[Index].Operand == EFI_IFR_EQ_VAR_VAL_OP || + FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_ID_OP || + FormTags.Tags[Index].Operand == EFI_IFR_EQ_ID_LIST_OP || + FormTags.Tags[Index].Operand == EFI_IFR_NOT_OP || + FormTags.Tags[Index].Operand == EFI_IFR_AND_OP || + FormTags.Tags[Index].Operand == EFI_IFR_OR_OP || + FormTags.Tags[Index].Operand == EFI_IFR_TRUE_OP || + FormTags.Tags[Index].Operand == EFI_IFR_FALSE_OP || + FormTags.Tags[Index].Operand == EFI_IFR_GT_OP || + FormTags.Tags[Index].Operand == EFI_IFR_GE_OP || + FormTags.Tags[Index].Operand == EFI_IFR_LABEL_OP; + Index++ + ) + ; + break; + + default: + goto GetOut; + } + // + // Do this two times (at most will see a suppress and grayout combination + // + Count++; + } while (Count < 2); + +GetOut: + do { + if (GrayOut) { + FormTags.Tags[Index].GrayOut = TRUE; + } else { + FormTags.Tags[Index].GrayOut = FALSE; + } + if (Suppress && FormTags.Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) { + // + // Only need .Suppress field when the tag is a one_of_option. For other cases, omit them directly. + // + FormTags.Tags[Index].Suppress = TRUE; + } else { + FormTags.Tags[Index].Suppress = FALSE; + } + + if (( + FormTags.Tags[Index].NumberOfLines > 0 || + FormTags.Tags[Index].Operand == EFI_IFR_DATE_OP || + FormTags.Tags[Index].Operand == EFI_IFR_TIME_OP + ) && + !Suppress + ) { + + StringPtr = GetToken (FormTags.Tags[Index].Text, Handle); + + Width = GetWidth (&FormTags.Tags[Index], Handle); + + // + // This data can be retrieved over and over again. Therefore, reset to original values + // before processing otherwise things will start growing linearly + // + if (FormTags.Tags[Index].NumberOfLines > 1) { + FormTags.Tags[Index].NumberOfLines = 1; + } + + for (Count = 0; GetLineByWidth (StringPtr, Width, &ArrayEntry, &OutputString) != 0x0000;) { + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&StringPtr[ArrayEntry])) { + FormTags.Tags[Index].NumberOfLines++; + } + + gBS->FreePool (OutputString); + } + + ArrayEntry = 0; + + // + // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do + // it in UiFreeMenu. + // + UiAddSubMenuOption (StringPtr, Handle, FormTags.Tags, Index, FormId, MenuItemCount); + MenuItemCount++; + } + // + // Keep processing menu entries based on the resultant suppress/grayout results until we hit an end-if + // + Index++; + } while (FormTags.Tags[Index].Operand != EFI_IFR_END_IF_OP && Conditional); + + // + // We advanced the index for the above conditional, rewind it to keep harmony with the for loop logic + // + Index--; + } + + Selection = UiDisplayMenu (TRUE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData); + + return Selection; +} + +VOID +InitializeBrowserStrings ( + VOID + ) +{ + gFunctionOneString = GetToken (STRING_TOKEN (FUNCTION_ONE_STRING), gHiiHandle); + gFunctionTwoString = GetToken (STRING_TOKEN (FUNCTION_TWO_STRING), gHiiHandle); + gFunctionNineString = GetToken (STRING_TOKEN (FUNCTION_NINE_STRING), gHiiHandle); + gFunctionTenString = GetToken (STRING_TOKEN (FUNCTION_TEN_STRING), gHiiHandle); + gEnterString = GetToken (STRING_TOKEN (ENTER_STRING), gHiiHandle); + gEnterCommitString = GetToken (STRING_TOKEN (ENTER_COMMIT_STRING), gHiiHandle); + gEscapeString = GetToken (STRING_TOKEN (ESCAPE_STRING), gHiiHandle); + gMoveHighlight = GetToken (STRING_TOKEN (MOVE_HIGHLIGHT), gHiiHandle); + gMakeSelection = GetToken (STRING_TOKEN (MAKE_SELECTION), gHiiHandle); + gNumericInput = GetToken (STRING_TOKEN (NUMERIC_INPUT), gHiiHandle); + gToggleCheckBox = GetToken (STRING_TOKEN (TOGGLE_CHECK_BOX), gHiiHandle); + gPromptForPassword = GetToken (STRING_TOKEN (PROMPT_FOR_PASSWORD), gHiiHandle); + gPromptForNewPassword = GetToken (STRING_TOKEN (PROMPT_FOR_NEW_PASSWORD), gHiiHandle); + gConfirmPassword = GetToken (STRING_TOKEN (CONFIRM_PASSWORD), gHiiHandle); + gConfirmError = GetToken (STRING_TOKEN (CONFIRM_ERROR), gHiiHandle); + gPressEnter = GetToken (STRING_TOKEN (PRESS_ENTER), gHiiHandle); + gEmptyString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); + gAreYouSure = GetToken (STRING_TOKEN (ARE_YOU_SURE), gHiiHandle); + gYesResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_YES), gHiiHandle); + gNoResponse = GetToken (STRING_TOKEN (ARE_YOU_SURE_NO), gHiiHandle); + gMiniString = GetToken (STRING_TOKEN (MINI_STRING), gHiiHandle); + gPlusString = GetToken (STRING_TOKEN (PLUS_STRING), gHiiHandle); + gMinusString = GetToken (STRING_TOKEN (MINUS_STRING), gHiiHandle); + gAdjustNumber = GetToken (STRING_TOKEN (ADJUST_NUMBER), gHiiHandle); + return ; +} + +VOID +UpdateKeyHelp ( + IN UI_MENU_OPTION *Selection, + IN BOOLEAN Selected + ) +/*++ +Routine Description: + Update key's help imformation + +Arguments: + Selection C The form that current display + Selected C Whether or not a tag be selected + +Returns: + None +--*/ +{ + UINTN SecCol; + UINTN ThdCol; + UINTN LeftColumnOfHelp; + UINTN RightColumnOfHelp; + UINTN TopRowOfHelp; + UINTN BottomRowOfHelp; + UINTN StartColumnOfHelp; + EFI_SCREEN_DESCRIPTOR LocalScreen; + + CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + + SecCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) / 3; + ThdCol = LocalScreen.LeftColumn + (LocalScreen.RightColumn - LocalScreen.LeftColumn) * 2 / 3; + + StartColumnOfHelp = LocalScreen.LeftColumn + 2; + LeftColumnOfHelp = LocalScreen.LeftColumn + 1; + RightColumnOfHelp = LocalScreen.RightColumn - 2; + TopRowOfHelp = LocalScreen.BottomRow - 4; + BottomRowOfHelp = LocalScreen.BottomRow - 3; + + if (gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS) { + return ; + } + + gST->ConOut->SetAttribute (gST->ConOut, KEYHELP_TEXT | KEYHELP_BACKGROUND); + + switch (Selection->ThisTag->Operand) { + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_DATE_OP: + ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND); + + if (!Selected) { + if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) { + PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString); + PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString); + PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString); + PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); + + } + + if ((Selection->ThisTag->Operand == EFI_IFR_DATE_OP) || (Selection->ThisTag->Operand == EFI_IFR_TIME_OP)) { + PrintAt ( + StartColumnOfHelp, + BottomRowOfHelp, + (CHAR16 *) L"%c%c%c%c%s", + ARROW_UP, + ARROW_DOWN, + ARROW_RIGHT, + ARROW_LEFT, + gMoveHighlight + ); + PrintStringAt (SecCol, BottomRowOfHelp, gAdjustNumber); + } else { + PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + PrintStringAt (SecCol, BottomRowOfHelp, gEnterString); + } + } else { + PrintStringAt (StartColumnOfHelp, BottomRowOfHelp, gEnterCommitString); + + // + // If it is a selected numeric with manual input, display different message + // + if ((Selection->ThisTag->Operand == EFI_IFR_NUMERIC_OP) && (Selection->ThisTag->Step == 0)) { + PrintStringAt (SecCol, TopRowOfHelp, gNumericInput); + } else if (Selection->ThisTag->Operand != EFI_IFR_ORDERED_LIST_OP) { + PrintAt (SecCol, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + } + + if (Selection->ThisTag->Operand == EFI_IFR_ORDERED_LIST_OP) { + PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gPlusString); + PrintStringAt (ThdCol, TopRowOfHelp, gMinusString); + } + + PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); + } + break; + + case EFI_IFR_CHECKBOX_OP: + ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND); + + if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) { + PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString); + PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString); + PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString); + PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); + } + + PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + PrintStringAt (SecCol, BottomRowOfHelp, gToggleCheckBox); + break; + + case EFI_IFR_REF_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + ClearLines (LeftColumnOfHelp, RightColumnOfHelp, TopRowOfHelp, BottomRowOfHelp, KEYHELP_TEXT | KEYHELP_BACKGROUND); + + if (!Selected) { + if (gClassOfVfr == EFI_SETUP_APPLICATION_SUBCLASS) { + PrintStringAt (StartColumnOfHelp, TopRowOfHelp, gFunctionOneString); + PrintStringAt (SecCol, TopRowOfHelp, gFunctionNineString); + PrintStringAt (ThdCol, TopRowOfHelp, gFunctionTenString); + PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); + } + + PrintAt (StartColumnOfHelp, BottomRowOfHelp, (CHAR16 *) L"%c%c%s", ARROW_UP, ARROW_DOWN, gMoveHighlight); + PrintStringAt (SecCol, BottomRowOfHelp, gEnterString); + } else { + if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) { + PrintStringAt ( + (LocalScreen.RightColumn - GetStringWidth (gEnterCommitString) / 2) / 2, + BottomRowOfHelp, + gEnterCommitString + ); + PrintStringAt (ThdCol, BottomRowOfHelp, gEscapeString); + } + } + break; + } + +} + +VOID +ExtractFormHandle ( + IN UI_MENU_OPTION *Selection, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN UINTN IdValue, + OUT UINT16 *FormHandle, + OUT UINT16 *TitleToken, + OUT EFI_FORM_TAGS *FormTags + ) +{ + UINTN Index; + EFI_FILE_FORM_TAGS *FileFormTags; + EFI_FORM_TAGS LocalTags; + + FileFormTags = FileFormTagsHead; + + // + // Advance FileFormTags to the correct file's tag information. + // For instance, if Selection->IfrNumber is 3, that means the 4th + // file (0-based) in the FileFormTags linked-list contains the tag + // information. + // + for (Index = 0; Index < Selection->IfrNumber; Index++) { + FileFormTags = FileFormTags->NextFile; + } + + LocalTags = FileFormTags->FormTags; + + if (IdValue == 0) { + // + // Advance Index to the first FormOp tag information + // + for (Index = 0; FileFormTags->FormTags.Tags[Index].Operand != EFI_IFR_FORM_OP; Index++) + ; + } else { + // + // Advance Index to the FormOp with the correct ID value + // + for (; LocalTags.Next != NULL; LocalTags = *LocalTags.Next) { + for (Index = 0; LocalTags.Tags[Index].Operand != EFI_IFR_FORM_OP; Index++) + ; + if (LocalTags.Tags[Index].Id == IdValue) { + break; + } + } + } + // + // return the Form Id, Text, and the File's FormTags structure + // + *FormHandle = LocalTags.Tags[Index].Id; + *TitleToken = LocalTags.Tags[Index].Text; + *FormTags = LocalTags; + return ; +} + +EFI_STATUS +UpdateNewTagData ( + IN UINT8 *FormData, + IN UINT16 ConsistencyId, + IN UINT16 CurrentVariable, + IN EFI_FORM_TAGS *FormTags, + OUT EFI_FILE_FORM_TAGS *FileFormTags + ) +{ + EFI_STATUS Status; + UINT16 Index; + UINT16 QuestionIndex; + UINT16 NumberOfTags; + INT16 CurrTag; + UINT8 TagLength; + UINTN Count; + BOOLEAN Finished; + + // + // Initialize some Index variable and Status + // + Count = 0; + QuestionIndex = 0; + NumberOfTags = 1; + Index = 0; + Status = EFI_SUCCESS; + Finished = FALSE; + + // + // Determine the number of tags for the first form + // + GetTagCount (&FormData[Index], &NumberOfTags); + + // + // Allocate memory for our tags on the first form + // + FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG)); + ASSERT (FormTags->Tags != NULL); + + for (CurrTag = 0; FormData[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) { + // + // Operand = IFR OpCode + // + FormTags->Tags[CurrTag].Operand = FormData[Index]; + + // + // Assume for now 0 lines occupied by this OpCode + // + FormTags->Tags[CurrTag].NumberOfLines = 0; + + // + // Determine the length of the Tag so we can later skip to the next tag in the form + // + // + // get the length + // + TagLength = FormData[Index + 1]; + // + // Operate on the Found OpCode + // + switch (FormData[Index]) { + + case EFI_IFR_FORM_OP: + case EFI_IFR_SUBTITLE_OP: + case EFI_IFR_TEXT_OP: + case EFI_IFR_REF_OP: + IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL); + break; + + case EFI_IFR_VARSTORE_SELECT_OP: + IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL); + CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) &FormData[Index])->VarId, sizeof (UINT16)); + break; + + case EFI_IFR_END_FORM_OP: + FormTags->Tags[CurrTag].Operand = FormData[Index]; + FormTags->Tags[CurrTag].NumberOfLines = 0; + + Finished = TRUE; + break; + + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_ONE_OF_OP: + GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable); + + // + // Store away the CurrTag since what follows will be the answer that we + // need to place into the appropriate location in the tag array + // + // + // record for setting default later + // + QuestionIndex = (UINT16) CurrTag; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL); + FormTags->Tags[QuestionIndex].Key = ((EFI_IFR_ONE_OF_OPTION *) &FormData[Index])->Key; + FormTags->Tags[QuestionIndex].ResetRequired = (BOOLEAN) (FormTags->Tags[QuestionIndex].Flags & EFI_IFR_FLAG_RESET_REQUIRED); + break; + + case EFI_IFR_CHECKBOX_OP: + GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable); + IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL); + break; + + case EFI_IFR_NUMERIC_OP: + GetNumericHeader (&FormTags->Tags[CurrTag], FormData, Index, (UINT16) 1, FileFormTags, CurrentVariable); + IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL); + break; + + case EFI_IFR_DATE_OP: + // + // Date elements come in as a Year, Month, Day. We need to process them as a country-based + // Order. It is much easier to do it here than anywhere else. + // + // For US standards - we want Month/Day/Year, thus we advance "i" +1, +2, +0 while CurrTag is +0, +1, +2 + // + GetNumericHeader ( + &FormTags->Tags[CurrTag], + FormData, + (UINT16) (Index + TagLength), + (UINT16) 0, + FileFormTags, + CurrentVariable + ); + + // + // The current language selected + the Date operand + // + FormTags->Tags[CurrTag + 1].Operand = FormData[Index]; + GetNumericHeader ( + &FormTags->Tags[CurrTag + 1], + FormData, + (UINT16) (Index + TagLength + FormData[Index + TagLength + 1]), + (UINT16) 0, + FileFormTags, + CurrentVariable + ); + + // + // The current language selected + the Date operand + // + FormTags->Tags[CurrTag + 2].Operand = FormData[Index]; + GetNumericHeader (&FormTags->Tags[CurrTag + 2], FormData, Index, (UINT16) 1, FileFormTags, CurrentVariable); + + CurrTag = (INT16) (CurrTag + 2); + + Index = (UINT16) (Index + TagLength); + // + // get the length + // + TagLength = FormData[Index + 1]; + Index = (UINT16) (Index + TagLength); + // + // get the length + // + TagLength = FormData[Index + 1]; + break; + + case EFI_IFR_TIME_OP: + GetNumericHeader (&FormTags->Tags[CurrTag], FormData, Index, (UINT16) 0, FileFormTags, CurrentVariable); + + if (Count == 2) { + // + // Override the GetQuestionHeader information - date/time are treated very differently + // + FormTags->Tags[CurrTag].NumberOfLines = 1; + Count = 0; + } else { + // + // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines + // associated with them, and the third has 1 line to allow to space beyond the choice. + // + Count++; + } + break; + + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + GetQuestionHeader (&FormTags->Tags[CurrTag], FormData, Index, FileFormTags, CurrentVariable); + IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL); + break; + + case EFI_IFR_INCONSISTENT_IF_OP: + case EFI_IFR_SUPPRESS_IF_OP: + case EFI_IFR_GRAYOUT_IF_OP: + ConsistencyId++; + break; + + case EFI_IFR_EQ_ID_VAL_OP: + IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL); + FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId; + break; + + case EFI_IFR_EQ_VAR_VAL_OP: + IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL); + FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId; + break; + + case EFI_IFR_EQ_ID_ID_OP: + IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL); + FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId; + break; + + case EFI_IFR_AND_OP: + case EFI_IFR_OR_OP: + case EFI_IFR_NOT_OP: + case EFI_IFR_TRUE_OP: + case EFI_IFR_FALSE_OP: + case EFI_IFR_GT_OP: + case EFI_IFR_GE_OP: + FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId; + break; + + case EFI_IFR_EQ_ID_LIST_OP: + IfrToFormTag (FormData[Index], &FormTags->Tags[CurrTag], (VOID *) &FormData[Index], NULL); + + FormTags->Tags[CurrTag].ConsistencyId = ConsistencyId; + break; + + default: + break; + } + // + // End of switch + // + if (Finished) { + break; + } + // + // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag + // + Index = (UINT16) (Index + TagLength); + } + // + // End of Index + // + return Status; +} + +VOID +ExtractDynamicFormHandle ( + IN UI_MENU_OPTION *Selection, + IN UINT8 *CallbackData, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN UINTN IdValue, + OUT UINT16 *FormHandle, + OUT UINT16 *TitleToken, + OUT EFI_FORM_TAGS *FormTags + ) +/*++ + +Routine Description: + + The function does the most of the works when the EFI_TAG that + user selects on is EFI_IFR_FLAG_INTERACTIVE or EFI_IFR_PASSWORD_OP: + invoke CallBack, update the new form data. + +Arguments: + + Selection - The current selection of the form. + CallbackData - The pointer to host the data passed back by the callback function. + FileFormTagsHead - Prompt string token of the one-of box + IdValue - The current page number. + FormHandle - Output the the handle of the form. + TitleToken - Output the TitleToken of the new page. + FormTags - Output the FormFags of the new page. + +Returns: + VOID + +--*/ +{ + UINTN Index; + UINTN BackupIndex; + EFI_FILE_FORM_TAGS *FileFormTags; + EFI_FORM_TAGS *LocalTags; + EFI_FORM_CALLBACK_PROTOCOL *FormCallback; + EFI_STATUS Status; + UINTN Length; + UINT8 *Buffer; + EFI_PHYSICAL_ADDRESS CallbackHandle; + EFI_GUID TagGuid; + UINT16 TargetPage; + EFI_HII_CALLBACK_PACKET *Packet; + UINTN ScreenSize; + CHAR16 NullCharacter; + EFI_INPUT_KEY Key; + UINT16 ConsistencyId; + UINT16 CurrentVariable; + EFI_VARIABLE_DEFINITION *VariableDefinition; + EFI_IFR_DATA_ENTRY *DataEntry; + + VariableDefinition = NULL; + NullCharacter = CHAR_NULL; + + CurrentVariable = 0; + FileFormTags = FileFormTagsHead; + Length = 0; + CallbackHandle = 0; + TargetPage = (UINT16) IdValue; + Packet = NULL; + ConsistencyId = 0; + + // + // Advance FileFormTags to the correct file's tag information. + // For instance, if Selection->IfrNumber is 3, that means the 4th + // file (0-based) in the FileFormTags linked-list contains the tag + // information. + // + for (Index = 0; Index < Selection->IfrNumber; Index++) { + FileFormTags = FileFormTags->NextFile; + } + + LocalTags = &FileFormTags->FormTags; + + // + // Advance Index to the FormOp with the correct ID value + // + for (; LocalTags->Next != NULL; LocalTags = LocalTags->Next) { + if ((LocalTags->Tags[0].CallbackHandle != 0) && (CallbackHandle == 0)) { + CallbackHandle = LocalTags->Tags[0].CallbackHandle; + CopyMem (&TagGuid, &LocalTags->Tags[0].GuidValue, sizeof (EFI_GUID)); + } + + for (Index = 0; LocalTags->Tags[Index].Operand != EFI_IFR_FORM_OP; Index++) + ; + if (LocalTags->Tags[Index].Id == IdValue) { + break; + } + } + // + // If we are going to callback on a non-goto opcode, make sure we don't change pages + // + if (Selection->ThisTag->Operand != EFI_IFR_REF_OP) { + TargetPage = Selection->FormId; + } + // + // The first tag below should be the form op-code. We need to store away the + // current variable setting to ensure if we have to reload the page, that we + // can correctly restore the values for the active variable + // + CurrentVariable = Selection->Tags[0].VariableNumber; + + // + // Remember that dynamic pages in an environment where all pages are not + // dynamic require us to call back to the user to give them an opportunity + // to register fresh information in the HII database so that we can extract it. + // + Status = gBS->HandleProtocol ( + (VOID *) (UINTN) CallbackHandle, + &gEfiFormCallbackProtocolGuid, + (VOID **) &FormCallback + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (LocalTags->Tags); + return ; + } + + ExtractRequestedNvMap (FileFormTags, CurrentVariable, &VariableDefinition); + + if (Selection->ThisTag->Flags & (EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS)) { + ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = VariableDefinition->NvRamMap; + } else { + ((EFI_IFR_DATA_ARRAY *) CallbackData)->NvRamMap = NULL; + } + + if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) { + Status = FormCallback->Callback ( + FormCallback, + Selection->ThisTag->Key, + (EFI_IFR_DATA_ARRAY *) CallbackData, + &Packet + ); + } + + if (EFI_ERROR (Status)) { + // + // Restore Previous Value + // + CopyMem ( + &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart], + gPreviousValue, + Selection->ThisTag->StorageWidth + ); + + if (Packet != NULL) { + // + // Upon error, we will likely receive a string to print out + // + ScreenSize = GetStringWidth (Packet->String) / 2; + + // + // Display error popup + // + CreatePopUp (ScreenSize, 3, &NullCharacter, Packet->String, &NullCharacter); + + do { + Status = WaitForKeyStroke (&Key); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + } else { + UpdateStatusBar (INPUT_ERROR, (UINT8) 0, TRUE); + } + + } else { + if (Packet != NULL) { + // + // We need to on a non-error, look in the outbound Packet for information and update the NVRAM + // location associated with the op-code specified there. This is used on single op-code instances + // and not for when a hyperlink sent us a whole page of data. + // + DataEntry = (EFI_IFR_DATA_ENTRY *) (&Packet->DataArray + 1); + if (Packet->DataArray.EntryCount == 1) { + switch (DataEntry->OpCode) { + case EFI_IFR_STRING_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_CHECKBOX_OP: + CopyMem ( + &VariableDefinition->NvRamMap[Selection->ThisTag->StorageStart], + &DataEntry->Data, + Selection->ThisTag->StorageWidth + ); + break; + + case EFI_IFR_NV_ACCESS_COMMAND: + CopyMem ( + &VariableDefinition->NvRamMap[((EFI_IFR_NV_DATA *) Packet)->QuestionId], + ((EFI_IFR_NV_DATA *) Packet) + 1, + ((EFI_IFR_NV_DATA *) Packet)->StorageWidth + ); + break; + + } + + if (DataEntry->Flags & RESET_REQUIRED) { + gResetRequired = TRUE; + } + + if (DataEntry->Flags & EXIT_REQUIRED) { + gExitRequired = TRUE; + } + + if (DataEntry->Flags & SAVE_REQUIRED) { + gSaveRequired = TRUE; + } + + if (DataEntry->Flags & NV_CHANGED) { + gNvUpdateRequired = TRUE; + } + + if (DataEntry->Flags & NV_NOT_CHANGED) { + gNvUpdateRequired = FALSE; + } + } + } + } + + if (Packet != NULL) { + gBS->FreePool (Packet); + } + + for (BackupIndex = 0; LocalTags->Tags[BackupIndex].Operand != EFI_IFR_END_FORM_OP; BackupIndex++) { + switch (LocalTags->Tags[BackupIndex].Operand) { + case EFI_IFR_EQ_VAR_VAL_OP: + case EFI_IFR_EQ_ID_VAL_OP: + case EFI_IFR_EQ_ID_ID_OP: + case EFI_IFR_AND_OP: + case EFI_IFR_OR_OP: + case EFI_IFR_NOT_OP: + case EFI_IFR_TRUE_OP: + case EFI_IFR_FALSE_OP: + case EFI_IFR_GT_OP: + case EFI_IFR_GE_OP: + case EFI_IFR_EQ_ID_LIST_OP: + // + // If we encountered a ConsistencyId value, on this page they will be incremental + // So register the first value we encounter. We will pass this in when we re-create this page + // + if ((LocalTags->Tags[BackupIndex].ConsistencyId != 0) && (ConsistencyId == 0)) { + ConsistencyId = (UINT16) (LocalTags->Tags[BackupIndex].ConsistencyId - 1); + } + break; + } + } + // + // Delete the buffer associated with previous dynamic page + // We will re-allocate a buffer.... + // + gBS->FreePool (LocalTags->Tags); + + Length = 0xF000; + Buffer = AllocateZeroPool (Length); + ASSERT (Buffer != NULL); + + // + // Get the form that was updated by the callback + // + Hii->GetForms ( + Hii, + Selection->Handle, + TargetPage, + &Length, + Buffer + ); + + // + // Ok, we have the new page.....now we must purge the old page and re-allocate + // the tag page with the new data + // + UpdateNewTagData ( + Buffer, + ConsistencyId, + CurrentVariable, + LocalTags, + FileFormTags + ); + + // + // return the Form Id, Text, and the File's FormTags structure + // + *FormHandle = LocalTags->Tags[0].Id; + *TitleToken = LocalTags->Tags[0].Text; + *FormTags = *LocalTags; + + FormTags->Tags[0].CallbackHandle = CallbackHandle; + CopyMem (&FormTags->Tags[0].GuidValue, &TagGuid, sizeof (EFI_GUID)); + + return ; +} + +UI_MENU_OPTION * +SetupBrowser ( + IN UI_MENU_OPTION *Selection, + IN BOOLEAN Callback, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN UINT8 *CallbackData + ) +{ + UINT16 FormHandle; + UINT16 TitleToken; + EFI_FORM_TAGS FormTags; + + gEntryNumber = -1; + gLastOpr = FALSE; + // + // Displays the Header and Footer borders + // + DisplayPageFrame (); + + // + // Id of 0 yields the getting of the top form whatever the ID is. Usually the first form in the IFR + // + ExtractFormHandle (Selection, FileFormTagsHead, 0, &FormHandle, &TitleToken, &FormTags); + + Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData); + + // + // If selection is null use the former selection + // + if (Selection == NULL) { + return Selection; + } + + if (Callback) { + return Selection; + } + + while (Selection->Tags != NULL) { + if (Selection->Previous) { + ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags); + } else { + // + // True if a hyperlink/jump is selected + // + if (Selection->ThisTag->Operand == EFI_IFR_REF_OP && Selection->ThisTag->Id != 0x0000) { + if (Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) { + ExtractDynamicFormHandle ( + Selection, + CallbackData, + FileFormTagsHead, + Selection->ThisTag->Id, + &FormHandle, + &TitleToken, + &FormTags + ); + goto DisplayPage; + } else { + ExtractFormHandle (Selection, FileFormTagsHead, Selection->ThisTag->Id, &FormHandle, &TitleToken, &FormTags); + goto DisplayPage; + } + } + + if ((Selection->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) && + (Selection->ThisTag->Operand != EFI_IFR_PASSWORD_OP) + ) { + ExtractDynamicFormHandle ( + Selection, + CallbackData, + FileFormTagsHead, + Selection->FormId, + &FormHandle, + &TitleToken, + &FormTags + ); + } else { + ExtractFormHandle (Selection, FileFormTagsHead, Selection->FormId, &FormHandle, &TitleToken, &FormTags); + } + } + +DisplayPage: + // + // Displays the Header and Footer borders + // + DisplayPageFrame (); + + Selection = DisplayForm (Selection, FormHandle, TitleToken, FormTags, FileFormTagsHead, CallbackData); + + if (Selection == NULL) { + break; + } + }; + + return Selection; +} diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Print.c b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Print.c new file mode 100644 index 0000000000..ec7bb1e174 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Print.c @@ -0,0 +1,338 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Print.c + +Abstract: + + Basic Ascii AvSPrintf() function named VSPrint(). VSPrint() enables very + simple implemenation of SPrint() and Print() to support debug. + + You can not Print more than EFI_DRIVER_LIB_MAX_PRINT_BUFFER characters at a + time. This makes the implementation very simple. + + VSPrint, Print, SPrint format specification has the follwoing form + + %type + + type: + 'S','s' - argument is an Unicode string + 'c' - argument is an ascii character + '%' - Print a % + +--*/ + +#include "print.h" + +STATIC +UINTN +_IPrint ( + IN UINTN Column, + IN UINTN Row, + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *Out, + IN CHAR16 *fmt, + IN VA_LIST args + ) +// +// Display string worker for: Print, PrintAt, IPrint, IPrintAt +// +{ + CHAR16 *Buffer; + CHAR16 *BackupBuffer; + UINTN Index; + UINTN PreviousIndex; + + // + // For now, allocate an arbitrarily long buffer + // + Buffer = AllocateZeroPool (0x10000); + BackupBuffer = AllocateZeroPool (0x10000); + ASSERT (Buffer); + ASSERT (BackupBuffer); + + if (Column != (UINTN) -1) { + Out->SetCursorPosition (Out, Column, Row); + } + + UnicodeVSPrint (Buffer, 0x10000, fmt, args); + + Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; + + Out->SetAttribute (Out, Out->Mode->Attribute); + + Index = 0; + PreviousIndex = 0; + + do { + for (; (Buffer[Index] != NARROW_CHAR) && (Buffer[Index] != WIDE_CHAR) && (Buffer[Index] != 0); Index++) { + BackupBuffer[Index] = Buffer[Index]; + } + + if (Buffer[Index] == 0) { + break; + } + // + // Null-terminate the temporary string + // + BackupBuffer[Index] = 0; + + // + // Print this out, we are about to switch widths + // + Out->OutputString (Out, &BackupBuffer[PreviousIndex]); + + // + // Preserve the current index + 1, since this is where we will start printing from next + // + PreviousIndex = Index + 1; + + // + // We are at a narrow or wide character directive. Set attributes and strip it and print it + // + if (Buffer[Index] == NARROW_CHAR) { + // + // Preserve bits 0 - 6 and zero out the rest + // + Out->Mode->Attribute = Out->Mode->Attribute & 0x7f; + Out->SetAttribute (Out, Out->Mode->Attribute); + } else { + // + // Must be wide, set bit 7 ON + // + Out->Mode->Attribute = Out->Mode->Attribute | EFI_WIDE_ATTRIBUTE; + Out->SetAttribute (Out, Out->Mode->Attribute); + } + + Index++; + + } while (Buffer[Index] != 0); + + // + // We hit the end of the string - print it + // + Out->OutputString (Out, &BackupBuffer[PreviousIndex]); + + gBS->FreePool (Buffer); + gBS->FreePool (BackupBuffer); + return EFI_SUCCESS; +} + +UINTN +Print ( + IN CHAR16 *fmt, + ... + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to the default console + +Arguments: + + fmt - Format string + +Returns: + + Length of string printed to the console + +--*/ +{ + VA_LIST args; + + VA_START (args, fmt); + return _IPrint ((UINTN) -1, (UINTN) -1, gST->ConOut, fmt, args); +} + +UINTN +PrintString ( + CHAR16 *String + ) +/*++ + +Routine Description: + + Prints a unicode string to the default console, + using L"%s" format. + +Arguments: + + String - String pointer. + +Returns: + + Length of string printed to the console + +--*/ +{ + return Print ((CHAR16 *) L"%s", String); +} + +UINTN +PrintChar ( + CHAR16 Character + ) +/*++ + +Routine Description: + + Prints a chracter to the default console, + using L"%c" format. + +Arguments: + + Character - Character to print. + +Returns: + + Length of string printed to the console. + +--*/ +{ + return Print ((CHAR16 *) L"%c", Character); +} + +/* +UINTN +PrintToken ( + IN EFI_HII_HANDLE Handle, + IN UINT16 Token, + IN CHAR16 *Language, + ... + ) +{ + VA_LIST args; + UINTN NumberOfHiiHandles; + EFI_HANDLE *HandleBuffer; + EFI_HII_PROTOCOL *Hii; + + // + // There should only be one HII image + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiHiiProtocolGuid, + NULL, + &NumberOfHiiHandles, + &HandleBuffer + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Retrieve the Hii protocol interface + // + Status = gBS->HandleProtocol ( + HandleBuffer[0], + &gEfiHiiProtocolGuid, + &Hii + ); + + Hii->GetString (Hii, Handle, Token, FALSE, Language, + + VA_START (args, fmt); + return _IPrint ((UINTN) -1, (UINTN) -1, gST->ConOut, fmt, args); +} + +*/ +UINTN +PrintAt ( + IN UINTN Column, + IN UINTN Row, + IN CHAR16 *fmt, + ... + ) +/*++ + +Routine Description: + + Prints a formatted unicode string to the default console, at + the supplied cursor position + +Arguments: + + Column, Row - The cursor position to print the string at + + fmt - Format string + +Returns: + + Length of string printed to the console + +--*/ +{ + VA_LIST args; + + VA_START (args, fmt); + return _IPrint (Column, Row, gST->ConOut, fmt, args); +} + +UINTN +PrintStringAt ( + IN UINTN Column, + IN UINTN Row, + CHAR16 *String + ) +/*++ + +Routine Description: + + Prints a unicode string to the default console, at + the supplied cursor position, using L"%s" format. + +Arguments: + + Column, Row - The cursor position to print the string at + + String - String pointer. + +Returns: + + Length of string printed to the console + +--*/ +{ + return PrintAt (Column, Row, (CHAR16 *) L"%s", String); +} + +UINTN +PrintCharAt ( + IN UINTN Column, + IN UINTN Row, + CHAR16 Character + ) +/*++ + +Routine Description: + + Prints a chracter to the default console, at + the supplied cursor position, using L"%c" format. + +Arguments: + + Column, Row - The cursor position to print the string at + + Character - Character to print. + +Returns: + + Length of string printed to the console. + +--*/ +{ + return PrintAt (Column, Row, (CHAR16 *) L"%c", Character); +} + + diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Print.h b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Print.h new file mode 100644 index 0000000000..86feb88bdf --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Print.h @@ -0,0 +1,37 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Print.h + +Abstract: + + Private data for Print.c + +--*/ + +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#define LEFT_JUSTIFY 0x01 +#define PREFIX_SIGN 0x02 +#define PREFIX_BLANK 0x04 +#define COMMA_TYPE 0x08 +#define LONG_TYPE 0x10 +#define PREFIX_ZERO 0x20 + +// +// Largest number of characters that can be printed out. +// +#define EFI_DRIVER_LIB_MAX_PRINT_BUFFER (80 * 4) + +#endif diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/ProcessOptions.c b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/ProcessOptions.c new file mode 100644 index 0000000000..8a878bcf71 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/ProcessOptions.c @@ -0,0 +1,1677 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ProcessOptions.c + +Abstract: + + Implementation for handling the User Interface option processing. + +Revision History + +--*/ + +#include "Setup.h" +#include "Ui.h" + +EFI_STATUS +ExtractRequestedNvMap ( + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UINT16 VariableId, + OUT EFI_VARIABLE_DEFINITION **VariableDefinition + ) +{ + *VariableDefinition = FileFormTags->VariableDefinitions; + + // + // Extract the data from the NV variable - consumer will free the buffer. + // + for (; *VariableDefinition != NULL; *VariableDefinition = (*VariableDefinition)->Next) { + // + // If there is a variable with this ID return with EFI_SUCCESS + // + if (!CompareMem (&(*VariableDefinition)->VariableId, &VariableId, sizeof (UINT16))) { + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +ExtractNvValue ( + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UINT16 VariableId, + IN UINT16 VariableSize, + IN UINT16 OffsetValue, + OUT VOID **Buffer + ) +{ + EFI_STATUS Status; + EFI_VARIABLE_DEFINITION *VariableDefinition; + + Status = ExtractRequestedNvMap (FileFormTags, VariableId, &VariableDefinition); + + if (!EFI_ERROR (Status)) { + // + // Allocate sufficient space for the data and copy it into the outgoing buffer + // + if (VariableSize != 0) { + *Buffer = AllocateZeroPool (VariableSize); + ASSERT (*Buffer != NULL); + CopyMem (*Buffer, &VariableDefinition->NvRamMap[OffsetValue], VariableSize); + } + return EFI_SUCCESS; + } + + return Status; +} + +VOID +AdjustNvMap ( + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UI_MENU_OPTION *MenuOption + ) +{ + CHAR8 *NvRamMap; + UINTN SizeRequired; + UINTN Index; + UINTN CachedStart; + EFI_VARIABLE_DEFINITION *VariableDefinition; + + CachedStart = 0; + + SizeRequired = MenuOption->ThisTag->StorageStart + MenuOption->ThisTag->StorageWidth; + + ExtractRequestedNvMap (FileFormTags, MenuOption->Tags->VariableNumber, &VariableDefinition); + + // + // We arrived here because the current NvRamMap is too small for the new op-code to store things and + // we need to adjust the buffer to support this. + // + NvRamMap = AllocateZeroPool (SizeRequired + 1); + ASSERT (NvRamMap != NULL); + + // + // Copy current NvRamMap to the new NvRamMap + // + CopyMem (NvRamMap, VariableDefinition->NvRamMap, VariableDefinition->VariableFakeSize); + + // + // Remember, the only time we come here is because we are in the NVPlus section of the NvRamMap + // + for (Index = MenuOption->TagIndex; + (MenuOption->Tags[Index].Operand != EFI_IFR_END_FORM_OP) && (MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP); + Index++ + ) { + + switch (MenuOption->Tags[Index].Operand) { + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_ONE_OF_OP: + CachedStart = MenuOption->Tags[Index].StorageStart; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + if (MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_DEFAULT) { + CopyMem (&NvRamMap[CachedStart], &MenuOption->Tags[Index].Value, 2); + } + break; + + case EFI_IFR_CHECKBOX_OP: + CopyMem (&NvRamMap[MenuOption->Tags[Index].StorageStart], &MenuOption->Tags[Index].Flags, 1); + break; + + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_DATE_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_STRING_OP: + case EFI_IFR_PASSWORD_OP: + CopyMem ( + &NvRamMap[MenuOption->Tags[Index].StorageStart], + &MenuOption->Tags[Index].Value, + MenuOption->Tags[Index].StorageWidth + ); + break; + + } + } + + gBS->FreePool (VariableDefinition->NvRamMap); + VariableDefinition->NvRamMap = NvRamMap; + VariableDefinition->VariableFakeSize = (UINT16) SizeRequired; +} + +EFI_STATUS +ProcessOptions ( + IN UI_MENU_OPTION *MenuOption, + IN BOOLEAN Selected, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN EFI_IFR_DATA_ARRAY *PageData, + OUT CHAR16 **OptionString + ) +{ + EFI_STATUS Status; + CHAR16 *StringPtr; + UINTN Index; + UINTN CachedIndex; + EFI_FILE_FORM_TAGS *FileFormTags; + EFI_TAG *Tag; + CHAR16 FormattedNumber[6]; + UINT16 Number; + UINT16 Value; + UINT16 *ValueArray; + UINT16 *NvRamMap; + CHAR8 *TmpNvRamMap; + UINTN Default; + UINTN StringCount; + CHAR16 Character[2]; + UINTN Count; + EFI_TIME Time; + EFI_FORM_CALLBACK_PROTOCOL *FormCallback; + STRING_REF PopUp; + CHAR16 NullCharacter; + EFI_INPUT_KEY Key; + EFI_VARIABLE_DEFINITION *VariableDefinition; + BOOLEAN OrderedList; + BOOLEAN Initialized; + UINT16 KeyValue; + BOOLEAN Skip; + + FileFormTags = FileFormTagsHead; + + for (Index = 0; Index < MenuOption->IfrNumber; Index++) { + FileFormTags = FileFormTags->NextFile; + } + + OrderedList = FALSE; + Initialized = FALSE; + ValueArray = NULL; + VariableDefinition = NULL; + Skip = FALSE; + + ZeroMem (&Time, sizeof (EFI_TIME)); + + StringPtr = (CHAR16 *) L"\0"; + Tag = MenuOption->ThisTag; + ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition); + + if (Tag->StorageStart > VariableDefinition->VariableSize) { + NvRamMap = (UINT16 *) &VariableDefinition->FakeNvRamMap[Tag->StorageStart]; + } else { + NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart]; + } + + StringCount = 0; + Character[1] = 0; + Count = 0; + Default = 0; + NullCharacter = CHAR_NULL; + FormCallback = NULL; + + if (MenuOption->ThisTag->Operand == EFI_IFR_ORDERED_LIST_OP) { + OrderedList = TRUE; + if (((UINT8 *) NvRamMap)[0] != 0x00) { + Initialized = TRUE; + } + } + + ZeroMem (FormattedNumber, 12); + + Status = gBS->HandleProtocol ( + (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle, + &gEfiFormCallbackProtocolGuid, + (VOID **) &FormCallback + ); + + if (*OptionString != NULL) { + gBS->FreePool (*OptionString); + *OptionString = NULL; + } + + switch (Tag->Operand) { + + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_ONE_OF_OP: + // + // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically + // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust + // the NvMap so that we can properly display the information + // + if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) { + AdjustNvMap (FileFormTags, MenuOption); + NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart]; + } + + CachedIndex = MenuOption->TagIndex; + + // + // search for EFI_IFR_ONE_OF_OPTION_OP until you hit the EFI_IFR_END_ONE_OF_OP, + // each of the .Text in the options are going to be what gets displayed. Break each into 26 char chunks + // when hit right/left arrow allows for selection - then repopulate Tag[TagIndex] with the choice + // + for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; Index++) { + // + // We found an option - which assumedly has a string. We will eventually have to support + // wrapping of strings. For now, let's pretend they don't wrap and code that up. + // + // Count how many strings there are + // + if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) { + // + // If one of the options for the one-of has an interactive flag, back-define the oneof to have one too + // + if (MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_INTERACTIVE) { + MenuOption->Tags[CachedIndex].Flags = (UINT8) (MenuOption->Tags[CachedIndex].Flags | EFI_IFR_FLAG_INTERACTIVE); + } + + StringCount++; + } + } + // + // We now know how many strings we will have, so we can allocate the + // space required for the array or strings. + // + *OptionString = AllocateZeroPool (StringCount * (gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow); + ASSERT (*OptionString); + + // + // Add left delimeter to string + // + *OptionString[0] = LEFT_ONEOF_DELIMITER; + + // + // Retrieve the current OneOf value + // + if (Selected) { + // + // Auto selection from list + // + Value = 0; + // + // Copy current setting to the seed Value + // + if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) { + ValueArray = AllocateZeroPool (MenuOption->ThisTag->StorageWidth); + ASSERT (ValueArray != NULL); + CopyMem (ValueArray, NvRamMap, MenuOption->ThisTag->StorageWidth); + } else { + CopyMem (&Value, NvRamMap, MenuOption->ThisTag->StorageWidth); + CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth); + } + + Number = Value; + if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) { + Status = GetSelectionInputPopUp (MenuOption, Tag, MenuOption->ThisTag->StorageWidth, ValueArray, &KeyValue); + } else { + Status = GetSelectionInputPopUp (MenuOption, Tag, 1, &Value, &KeyValue); + } + + if (!EFI_ERROR (Status)) { + if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) { + CopyMem (NvRamMap, ValueArray, MenuOption->ThisTag->StorageWidth); + gBS->FreePool (ValueArray); + } else { + // + // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth + // + CopyMem (NvRamMap, &Value, Tag->StorageWidth); + MenuOption->ThisTag->Key = KeyValue; + } + // + // If a late check is required save off the information. This is used when consistency checks + // are required, but certain values might be bound by an impossible consistency check such as + // if two questions are bound by consistency checks and each only has two possible choices, there + // would be no way for a user to switch the values. Thus we require late checking. + // + if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) { + CopyMem (&Tag->OldValue, &Value, Tag->StorageWidth); + } else { + // + // In theory, passing the value and the Id are sufficient to determine what needs + // to be done. The Id is the key to look for the entry needed in the Inconsistency + // database. That will yields operand and ID data - and since the ID's correspond + // to the NV storage, we can determine the values for other IDs there. + // + if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) { + if (PopUp == 0x0000) { + // + // Restore Old Value + // + if (!Tag->Suppress && !Tag->GrayOut) { + CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth); + } + break; + } + + StringPtr = GetToken (PopUp, MenuOption->Handle); + + CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter); + + do { + Status = WaitForKeyStroke (&Key); + + switch (Key.UnicodeChar) { + + case CHAR_CARRIAGE_RETURN: + // + // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth + // + CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth); + gBS->FreePool (StringPtr); + break; + + default: + break; + } + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + } + } + + UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE); + } else { + if (Tag->Operand == EFI_IFR_ORDERED_LIST_OP) { + gBS->FreePool (ValueArray); + } + + return EFI_SUCCESS; + } + } else { + for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand != EFI_IFR_END_ONE_OF_OP; Index++) { + // + // We found an option - which assumedly has a string. We will eventually have to support + // wrapping of strings. For now, let's pretend they don't wrap and code that up. + // + if (MenuOption->Tags[Index].Operand == EFI_IFR_ONE_OF_OPTION_OP) { + if (OrderedList) { + if (!Initialized) { + // + // If the first entry is invalid, then the "default" settings are based on what is reflected + // in the order of the op-codes + // + ((UINT8 *) NvRamMap)[Index - MenuOption->TagIndex - 1] = (UINT8) MenuOption->Tags[Index].Value; + } + // + // Only display 3 lines of stuff at most + // + if ((Index - MenuOption->TagIndex) > ORDERED_LIST_SIZE) { + break; + } + + if (((Index - MenuOption->TagIndex) != 1) && !Skip) { + Character[0] = LEFT_ONEOF_DELIMITER; + NewStrCat (OptionString[0], Character); + } + + MenuOption->ThisTag->NumberOfLines = (UINT16) (Index - MenuOption->TagIndex); + if (!Initialized) { + StringPtr = GetToken (MenuOption->Tags[Index].Text, MenuOption->Handle); + } else { + for (Value = (UINT16) (MenuOption->TagIndex + 1); + MenuOption->Tags[Value].Operand != EFI_IFR_END_ONE_OF_OP; + Value++ + ) { + if (MenuOption->Tags[Value].Value == ((UINT8 *) NvRamMap)[Index - MenuOption->TagIndex - 1]) { + StringPtr = GetToken (MenuOption->Tags[Value].Text, MenuOption->Handle); + break; + } + } + + if (MenuOption->Tags[Value].Operand == EFI_IFR_END_ONE_OF_OP) { + Skip = TRUE; + continue; + } + } + + Skip = FALSE; + NewStrCat (OptionString[0], StringPtr); + Character[0] = RIGHT_ONEOF_DELIMITER; + NewStrCat (OptionString[0], Character); + Character[0] = CHAR_CARRIAGE_RETURN; + NewStrCat (OptionString[0], Character); + + // + // Remove Buffer allocated for StringPtr after it has been used. + // + gBS->FreePool (StringPtr); + } else { + // + // The option value is the same as what is stored in NV store. Print this. + // + if (!CompareMem (&(MenuOption->Tags[Index].Value), NvRamMap, MenuOption->ThisTag->StorageWidth)) { + StringPtr = GetToken (MenuOption->Tags[Index].Text, MenuOption->Handle); + NewStrCat (OptionString[0], StringPtr); + Character[0] = RIGHT_ONEOF_DELIMITER; + NewStrCat (OptionString[0], Character); + // + // Remove Buffer allocated for StringPtr after it has been used. + // + gBS->FreePool (StringPtr); + Default = 0; + break; + } + + if ((MenuOption->Tags[Index].Flags & EFI_IFR_FLAG_DEFAULT) == 1) { + Default = MenuOption->Tags[Index].Text; + Value = MenuOption->Tags[Index].Value; + }; + } + } + } + // + // We didn't find a value that matched a setting in the NVRAM Map - display default - set default + // + if (Default != 0) { + // + // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth + // + CopyMem (NvRamMap, &Value, MenuOption->ThisTag->StorageWidth); + + StringPtr = GetToken ((UINT16) Default, MenuOption->Handle); + NewStrCat (OptionString[0], StringPtr); + Character[0] = RIGHT_ONEOF_DELIMITER; + NewStrCat (OptionString[0], Character); + // + // Remove Buffer allocated for StringPtr after it has been used. + // + gBS->FreePool (StringPtr); + } + } + break; + + case EFI_IFR_CHECKBOX_OP: + // + // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically + // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust + // the NvMap so that we can properly display the information + // + if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) { + AdjustNvMap (FileFormTags, MenuOption); + NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart]; + } + + Default = Tag->Flags & 1; + // + // If hit spacebar, set or unset Tag[TagIndex].Flags based on it's previous value - BOOLEAN + // + *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow); + ASSERT (*OptionString); + + // + // Since Checkboxes are BOOLEAN values, bit 0 of the Flags bit defines the default option, therefore, if + // the default option (only one option for checkboxes) is on, then the default value is on. Tag.Default is not + // an active field for Checkboxes. + // + StrnCpy (OptionString[0], (CHAR16 *) LEFT_CHECKBOX_DELIMITER, 1); + + // + // Since this is a BOOLEAN operation, flip bit 0 upon selection + // + if (Selected) { + Tag->Value = (UINT16) (Tag->Value ^ 1); + *(UINT8 *) NvRamMap = (UINT8) (Tag->Value & 1); + UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE); + } + + if ((*(UINT8 *) NvRamMap & 1) == 0x01) { + NewStrCat (OptionString[0], (CHAR16 *) CHECK_ON); + // + // If someone reset default variables - we may need to reload from our NvMapping.... + // + Tag->Value = *(UINT8 *) NvRamMap; + } else { + // + // If someone reset default variables - we may need to reload from our NvMapping.... + // + NewStrCat (OptionString[0], (CHAR16 *) CHECK_OFF); + Tag->Value = *(UINT8 *) NvRamMap; + } + + NewStrCat (OptionString[0], (CHAR16 *) RIGHT_CHECKBOX_DELIMITER); + NewStrCat (OptionString[0], StringPtr); + break; + + case EFI_IFR_NUMERIC_OP: + // + // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically + // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust + // the NvMap so that we can properly display the information + // + if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) { + AdjustNvMap (FileFormTags, MenuOption); + NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart]; + } + + *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow); + ASSERT (*OptionString); + + // + // Add left delimeter to string + // + *OptionString[0] = LEFT_NUMERIC_DELIMITER; + + // + // Retrieve the current numeric value + // + if (Selected) { + // + // Go ask for input + // + if (Tag->Step == 0) { + // + // Manual Input + // + Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, REGULAR_NUMERIC, &Number); + if (!EFI_ERROR (Status)) { + CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth); + UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE); + + // + // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth + // + CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth); + } else { + return EFI_SUCCESS; + } + } else { + // + // Auto selection from list + // + if ((((Tag->StorageWidth == 1) && (UINT8) (*NvRamMap) > Tag->Maximum) || ((UINT8) (*NvRamMap) < Tag->Minimum)) || + (((Tag->StorageWidth == 2) && *NvRamMap > Tag->Maximum) || (*NvRamMap < Tag->Minimum)) + ) { + // + // Seed Number with valid value if currently invalid + // + Number = Tag->Default; + } else { + if (Tag->StorageWidth == 1) { + Number = (UINT8) (*NvRamMap); + } else { + Number = *NvRamMap; + } + } + + Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, REGULAR_NUMERIC, &Number); + if (!EFI_ERROR (Status)) { + CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth); + UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE); + + // + // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth + // + CopyMem (NvRamMap, &Number, MenuOption->ThisTag->StorageWidth); + } else { + return EFI_SUCCESS; + } + } + } else { + if (((Tag->StorageWidth == 1) && (UINT8) (*NvRamMap) <= Tag->Maximum && (UINT8) (*NvRamMap) >= Tag->Minimum) || + ((Tag->StorageWidth == 2) && *NvRamMap <= Tag->Maximum && *NvRamMap >= Tag->Minimum) + ) { + if (Tag->StorageWidth == 1) { + Number = (UINT8) (*NvRamMap); + } else { + Number = *NvRamMap; + } + UnicodeValueToString ( + FormattedNumber, + FALSE, + (UINTN) Number, + (sizeof (FormattedNumber) / sizeof (FormattedNumber[0])) + ); + Number = (UINT16) GetStringWidth (FormattedNumber); + StrnCpy (OptionString[0] + 1, FormattedNumber, Number); + } else { + // + // If *NvRamMap isn't within parameters, set it to within parameters + // + // + // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth + // + CopyMem (NvRamMap, &Tag->Default, MenuOption->ThisTag->StorageWidth); + Number = Tag->Default; + + UnicodeValueToString ( + FormattedNumber, + FALSE, + (UINTN) Number, + (sizeof (FormattedNumber) / sizeof (FormattedNumber[0])) + ); + Number = (UINT16) GetStringWidth (FormattedNumber); + StrnCpy (OptionString[0] + 1, FormattedNumber, Number); + } + + *(OptionString[0] + Number / 2) = RIGHT_NUMERIC_DELIMITER; + NewStrCat (OptionString[0] + (Number / 2) + 1, StringPtr); + } + break; + + case EFI_IFR_DATE_OP: + // + // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically + // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust + // the NvMap so that we can properly display the information + // + if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) { + AdjustNvMap (FileFormTags, MenuOption); + NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart]; + } + + Status = gRT->GetTime (&Time, NULL); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + // + // This for loop advances Index till it points immediately after a date entry. We can then + // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date + // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index + // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3 + // date operands. + // + // + // This has BUGBUG potential....fix this - if someone wants to ask two DATE questions in a row.....code + // against such silliness. + // + // Also, we want to internationalize the order of the date information. We need to code for it as well. + // + for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand == EFI_IFR_DATE_OP; Index++) + ; + + // + // Count 0 = We entered on the first Date operand + // Count 1 = We entered on the second Date operand + // Count 2 = We entered on the third Date operand + // + Count = 3 - (Index - MenuOption->TagIndex); + if (Count > 2) { + return EFI_SUCCESS; + } + // + // This is similar to numerics, except for the following: + // We will under normal circumstances get 3 consecutive calls + // to process this opcodes data. + // + *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow); + ASSERT (*OptionString); + + switch (Count) { + case 0: + if (Selected) { + Number = (UINT16) Time.Month; + + if (Tag->Step == 0) { + MenuOption->OptCol++; + Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, DATE_NUMERIC, &Number); + } else { + // + // Seed value with current setting + // + Tag->Value = (UINT16) Time.Month; + Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, DATE_NUMERIC, &Number); + } + + if (!EFI_ERROR (Status)) { + Time.Month = (UINT8) Number; + gRT->SetTime (&Time); + } + } + + VariableDefinition->FakeNvRamMap[Tag->Id] = Time.Month; + *OptionString[0] = LEFT_NUMERIC_DELIMITER; + + UnicodeValueToString ( + FormattedNumber, + FALSE, + (UINTN) Time.Month, + (sizeof (FormattedNumber) / sizeof (FormattedNumber[0])) + ); + Number = (UINT16) GetStringWidth (FormattedNumber); + + if (Number == 4) { + FormattedNumber[2] = FormattedNumber[1]; + FormattedNumber[1] = FormattedNumber[0]; + FormattedNumber[0] = L'0'; + Number = 6; + } + + StrnCpy (OptionString[0] + 1, FormattedNumber, Number); + *(OptionString[0] + Number / 2) = DATE_SEPARATOR; + StrCat (OptionString[0] + (Number / 2) + 1, StringPtr); + break; + + case 1: + if (Selected) { + Number = (UINT16) Time.Day; + + if (Tag->Step == 0) { + Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, DATE_NUMERIC, &Number); + } else { + // + // Seed value with current setting + // + Tag->Value = (UINT16) Time.Day; + Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, DATE_NUMERIC, &Number); + } + + if (!EFI_ERROR (Status)) { + Time.Day = (UINT8) Number; + gRT->SetTime (&Time); + } + } + + VariableDefinition->FakeNvRamMap[Tag->Id] = Time.Day; + SetUnicodeMem (OptionString[0], 4, L' '); + + UnicodeValueToString ( + FormattedNumber, + FALSE, + (UINTN) Time.Day, + (sizeof (FormattedNumber) / sizeof (FormattedNumber[0])) + ); + Number = (UINT16) GetStringWidth (FormattedNumber); + if (Number == 4) { + FormattedNumber[2] = FormattedNumber[1]; + FormattedNumber[1] = FormattedNumber[0]; + FormattedNumber[0] = L'0'; + Number = 6; + } + + StrnCpy (OptionString[0] + 4, FormattedNumber, Number); + *(OptionString[0] + Number / 2 + 3) = DATE_SEPARATOR; + StrCat (OptionString[0] + (Number / 2) + 4, StringPtr); + break; + + case 2: + if (Selected) { + Number = (UINT16) Time.Year; + + if (Tag->Step == 0) { + Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, DATE_NUMERIC, &Number); + } else { + // + // Seed value with current setting + // + Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, DATE_NUMERIC, &Number); + } + + if (!EFI_ERROR (Status)) { + Time.Year = (UINT16) Number; + gRT->SetTime (&Time); + } + } + + Tag->Value = (UINT16) Time.Year; + VariableDefinition->FakeNvRamMap[Tag->Id] = (UINT8) Tag->Value; + VariableDefinition->FakeNvRamMap[Tag->Id + 1] = (UINT8) (Tag->Value >> 8); + SetUnicodeMem (OptionString[0], 7, L' '); + UnicodeValueToString ( + FormattedNumber, + FALSE, + (UINTN) Time.Year, + (sizeof (FormattedNumber) / sizeof (FormattedNumber[0])) + ); + Number = (UINT16) GetStringWidth (FormattedNumber); + StrnCpy (OptionString[0] + 7, FormattedNumber, Number); + *(OptionString[0] + Number / 2 + 6) = RIGHT_NUMERIC_DELIMITER; + StrCat (OptionString[0] + (Number / 2) + 7, StringPtr); + break; + } + + break; + + // + // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG + // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone + // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction + // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG + // + case EFI_IFR_TIME_OP: + // + // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically + // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust + // the NvMap so that we can properly display the information + // + if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) { + AdjustNvMap (FileFormTags, MenuOption); + NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart]; + } + + Status = gRT->GetTime (&Time, NULL); + if (EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + // + // This is similar to numerics, except for the following: + // We will under normal circumstances get 3 consecutive calls + // to process this opcodes data. + // + *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow); + ASSERT (*OptionString); + + // + // This for loop advances Index till it points immediately after a date entry. We can then + // subtract MenuOption->TagIndex from Index and find out relative to the start of the Date + // structure which field we were in. For instance, if TagIndex was 52, and we advanced Index + // to 53 and found it to no longer point to a date operand, we were pointing to the last of 3 + // date operands. + // + for (Index = MenuOption->TagIndex; MenuOption->Tags[Index].Operand == EFI_IFR_TIME_OP; Index++) + ; + // + // Count 0 = We entered on the first Date operand + // Count 1 = We entered on the second Date operand + // Count 2 = We entered on the third Date operand + // + Count = 3 - (Index - MenuOption->TagIndex); + if (Count > 2) { + return EFI_SUCCESS; + } + + switch (Count) { + case 0: + Number = Time.Hour; + break; + + case 1: + Number = Time.Minute; + break; + + case 2: + Number = Time.Second; + } + // + // Retrieve the current numeric value + // + if (Selected) { + // + // Go ask for input + // + if (Tag->Step == 0) { + // + // Manual Input + // + Status = GetNumericInput (MenuOption, FileFormTagsHead, TRUE, Tag, TIME_NUMERIC, &Number); + if (!EFI_ERROR (Status)) { + *NvRamMap = Number; + Time.Nanosecond = 0; + gRT->SetTime (&Time); + } else { + return EFI_SUCCESS; + } + } else { + // + // Auto selection from list + // + Status = GetNumericInput (MenuOption, FileFormTagsHead, FALSE, Tag, TIME_NUMERIC, &Number); + if (!EFI_ERROR (Status)) { + *NvRamMap = Number; + } else { + return EFI_SUCCESS; + } + } + + switch (Count) { + case 0: + Time.Hour = (UINT8) Number; + break; + + case 1: + Time.Minute = (UINT8) Number; + break; + + case 2: + Time.Second = (UINT8) Number; + } + + Time.Nanosecond = 0; + gRT->SetTime (&Time); + } else { + switch (Count) { + case 0: + *OptionString[0] = LEFT_NUMERIC_DELIMITER; + UnicodeValueToString ( + FormattedNumber, + FALSE, + (UINTN) Time.Hour, + (sizeof (FormattedNumber) / sizeof (FormattedNumber[0])) + ); + Number = (UINT16) GetStringWidth (FormattedNumber); + if (Number == 4) { + FormattedNumber[2] = FormattedNumber[1]; + FormattedNumber[1] = FormattedNumber[0]; + FormattedNumber[0] = L'0'; + Number = 6; + } + + StrnCpy (OptionString[0] + 1, FormattedNumber, Number); + *(OptionString[0] + Number / 2) = TIME_SEPARATOR; + StrCat (OptionString[0] + (Number / 2) + 1, StringPtr); + break; + + case 1: + SetUnicodeMem (OptionString[0], 4, L' '); + UnicodeValueToString ( + FormattedNumber, + FALSE, + (UINTN) Time.Minute, + (sizeof (FormattedNumber) / sizeof (FormattedNumber[0])) + ); + Number = (UINT16) GetStringWidth (FormattedNumber); + if (Number == 4) { + FormattedNumber[2] = FormattedNumber[1]; + FormattedNumber[1] = FormattedNumber[0]; + FormattedNumber[0] = L'0'; + Number = 6; + } + + StrnCpy (OptionString[0] + 4, FormattedNumber, Number); + *(OptionString[0] + Number / 2 + 3) = TIME_SEPARATOR; + StrCat (OptionString[0] + (Number / 2) + 4, StringPtr); + break; + + case 2: + SetUnicodeMem (OptionString[0], 7, L' '); + UnicodeValueToString ( + FormattedNumber, + FALSE, + (UINTN) Time.Second, + (sizeof (FormattedNumber) / sizeof (FormattedNumber[0])) + ); + Number = (UINT16) GetStringWidth (FormattedNumber); + if (Number == 4) { + FormattedNumber[2] = FormattedNumber[1]; + FormattedNumber[1] = FormattedNumber[0]; + FormattedNumber[0] = L'0'; + Number = 6; + } + + StrnCpy (OptionString[0] + 7, FormattedNumber, Number); + *(OptionString[0] + Number / 2 + 6) = RIGHT_NUMERIC_DELIMITER; + StrCat (OptionString[0] + (Number / 2) + 7, StringPtr); + break; + } + // + // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG + // We need to add code to support the NVRam storage version of Date - this is the 1% case where someone + // might want to set an alarm and actually preserve the data in NVRam so a driver can pick up the instruction + // BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG BUGBUG + // + } + break; + + case EFI_IFR_STRING_OP: + // + // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically + // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust + // the NvMap so that we can properly display the information + // + if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) { + AdjustNvMap (FileFormTags, MenuOption); + NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart]; + } + + *OptionString = AllocateZeroPool ((gOptionBlockWidth + 1) * 2 * gScreenDimensions.BottomRow); + ASSERT (*OptionString); + + if (Selected) { + StringPtr = AllocateZeroPool (Tag->Maximum); + ASSERT (StringPtr); + + Status = ReadString (MenuOption, StringPtr); + + if (!EFI_ERROR (Status)) { + CopyMem (gPreviousValue, NvRamMap, MenuOption->ThisTag->StorageWidth); + CopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth); + + UpdateStatusBar (NV_UPDATE_REQUIRED, Tag->Flags, TRUE); + } + + gBS->FreePool (StringPtr); + return Status; + } else { + for (Index = 0; Index < gOptionBlockWidth; Index++) { + if (VariableDefinition->NvRamMap[Tag->StorageStart + (Index * 2)] != 0x0000) { + CopyMem (OptionString[0] + Index, &VariableDefinition->NvRamMap[Tag->StorageStart + (Index * 2)], 2); + } else { + if (Index == 0) { + *(OptionString[0] + Index) = '_'; + *(OptionString[0] + 1 + Index) = 0; + } + break; + } + } + + return Status; + } + + case EFI_IFR_PASSWORD_OP: + // + // If the op-code we are looking at is larger than the latest created NvMap - we likely encountered a dynamically + // created entry which has an expanded NvMap requirement. We won't save this information - but we need to adjust + // the NvMap so that we can properly display the information + // + if ((UINTN) (Tag->StorageStart + Tag->StorageWidth) > VariableDefinition->VariableFakeSize) { + AdjustNvMap (FileFormTags, MenuOption); + NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart]; + } + + if (Selected) { + StringPtr = AllocateZeroPool (Tag->Maximum); + ASSERT (StringPtr); + + // + // If interactive, read the password and do the appropriate callbacks in that routine. + // Since interactive passwords assume to handle the password data in a separate variable + // storage, we don't need to do more than what is below for password callbacks + // + if (Tag->Flags & EFI_IFR_FLAG_INTERACTIVE) { + MenuOption->Tags[0].CallbackHandle = FileFormTags->FormTags.Tags[0].CallbackHandle; + Status = ReadPassword (MenuOption, TRUE, Tag, PageData, FALSE, FileFormTags, StringPtr); + ZeroMem (StringPtr, Tag->Maximum); + + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_READY) { + gBS->FreePool (StringPtr); + return EFI_SUCCESS; + } + } + + Status = ReadPassword (MenuOption, TRUE, Tag, PageData, TRUE, FileFormTags, StringPtr); + gBS->FreePool (StringPtr); + return EFI_SUCCESS; + } + + for (Index = 0; Index < Tag->Maximum; Index++) { + if (VariableDefinition->NvRamMap[Tag->StorageStart + Index] != 0x00) { + // + // There is something there! Prompt for password + // + Status = ReadPassword (MenuOption, TRUE, Tag, PageData, FALSE, FileFormTags, StringPtr); + if (EFI_ERROR (Status)) { + gBS->FreePool (StringPtr); + return EFI_SUCCESS; + } + + if (Tag->Encoding == 1) { + EncodePassword (StringPtr, (UINT8) Tag->Maximum); + Status = CompareMem (StringPtr, &VariableDefinition->NvRamMap[Tag->StorageStart], Tag->Maximum); + } else { + Status = CompareMem (StringPtr, &VariableDefinition->NvRamMap[Tag->StorageStart], Tag->Maximum); + } + + if (Status != 0) { + gBS->FreePool (StringPtr); + return EFI_SUCCESS; + } else { + break; + } + } + } + // + // Clean the string + // + ZeroMem (StringPtr, Tag->Maximum); + + // + // No password set! Go ahead and prompt the user for a password. + // + Status = ReadPassword (MenuOption, FALSE, Tag, PageData, FALSE, FileFormTags, StringPtr); + + if (EFI_ERROR (Status)) { + // + // User couldn't figure out how to type two identical passwords + // + gBS->FreePool (StringPtr); + return EFI_SUCCESS; + } + // + // Very simple example of how one MIGHT do password encoding + // + if (Tag->Encoding == 1) { + EncodePassword (StringPtr, (UINT8) Tag->Maximum); + } + + TmpNvRamMap = AllocatePool (VariableDefinition->VariableSize); + ASSERT (TmpNvRamMap != NULL); + + Count = VariableDefinition->VariableSize; + + if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) { + Status = FormCallback->NvRead ( + FormCallback, + VariableDefinition->VariableName, + &VariableDefinition->Guid, + NULL, + &Count, + (VOID *) TmpNvRamMap + ); + } else { + Status = gRT->GetVariable ( + VariableDefinition->VariableName, + &VariableDefinition->Guid, + NULL, + &Count, + (VOID *) TmpNvRamMap + ); + } + + CopyMem (&VariableDefinition->NvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth); + CopyMem (&TmpNvRamMap[Tag->StorageStart], StringPtr, Tag->StorageWidth); + + if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) { + Status = FormCallback->NvWrite ( + FormCallback, + VariableDefinition->VariableName, + &VariableDefinition->Guid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VariableDefinition->VariableSize, + (VOID *) TmpNvRamMap, + &gResetRequired + ); + } else { + Status = gRT->SetVariable ( + VariableDefinition->VariableName, + &VariableDefinition->Guid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VariableDefinition->VariableSize, + (VOID *) TmpNvRamMap + ); + } + + gBS->FreePool (TmpNvRamMap); + gBS->FreePool (StringPtr); + break; + } + + default: + break; + } + + return EFI_SUCCESS; +} + +VOID +ProcessHelpString ( + IN CHAR16 *StringPtr, + OUT CHAR16 **FormattedString, + IN UINTN RowCount + ) +{ + UINTN CurrIndex; + UINTN PrevIndex; + UINTN SearchIndex; + UINTN PrevSearchIndex; + UINTN StringCount; + UINTN PageCount; + + StringCount = 0; + PrevIndex = 0; + CurrIndex = gHelpBlockWidth - 1; + + if (*FormattedString != NULL) { + gBS->FreePool (*FormattedString); + *FormattedString = NULL; + } + + for (; CurrIndex > PrevIndex; CurrIndex--) { + // + // In the case where the string ended and a new one is immediately after it + // we need to check for the null-terminator and reset the CurrIndex + // + SearchIndex = CurrIndex; + PrevSearchIndex = PrevIndex; + + for (; SearchIndex > PrevSearchIndex; PrevSearchIndex++) { + if ((StringPtr[PrevSearchIndex] == CHAR_NULL) || (StringPtr[PrevSearchIndex] == CHAR_LINEFEED)) { + CurrIndex = PrevSearchIndex; + break; + } + + if (StringPtr[PrevSearchIndex] == CHAR_CARRIAGE_RETURN) { + if (StringPtr[PrevSearchIndex + 1] == CHAR_LINEFEED) { + // + // Found a "\n",advance to the next new line. + // + CurrIndex = PrevSearchIndex + 1; + break; + } else { + // + // Found a "\r",return to the start of the current line. + // + PrevIndex = PrevSearchIndex + 1; + CurrIndex = PrevSearchIndex + gHelpBlockWidth; + continue; + } + } + } + + // + // End of the string, thus stop counting. + // + if (StringPtr[CurrIndex] == CHAR_NULL) { + StringCount++; + break; + } + // + // The premise is that for every HELP_BLOCK_WIDTH we rewind + // until we find the first space. That is the delimiter for + // the string, and we will then advance our CurrIndex another + // HELP_BLOCK_WIDTH and continue the process breaking the larger + // string into chunks that fit within the HELP_BLOCK_WIDTH requirements. + // + if (StringPtr[CurrIndex] == CHAR_SPACE) { + // + // How many strings have been found? + // + StringCount++; + PrevIndex = CurrIndex + 1; + CurrIndex = CurrIndex + gHelpBlockWidth; + } + // + // Found a Linefeed, advance to the next line. + // + if (StringPtr[CurrIndex] == CHAR_LINEFEED) { + StringCount++; + PrevIndex = CurrIndex + 1; + CurrIndex = CurrIndex + gHelpBlockWidth; + } + } + // + // endfor + // + // Round the value up one (doesn't hurt) + // + StringCount++; + + // + // Determine the number of pages this help string occupies + // + PageCount = StringCount / RowCount; + if (StringCount % RowCount > 0) { + PageCount++; + } + // + // Convert the PageCount into lines so we can allocate the correct buffer size + // + StringCount = PageCount * RowCount; + + // + // We now know how many strings we will have, so we can allocate the + // space required for the array or strings. + // + *FormattedString = AllocateZeroPool ((StringCount) * (gHelpBlockWidth + 1) * 2); + ASSERT (*FormattedString); + + StringCount = 0; + PrevIndex = 0; + CurrIndex = gHelpBlockWidth - 1; + + for (; CurrIndex > PrevIndex; CurrIndex--) { + // + // In the case where the string ended and a new one is immediately after it + // we need to check for the null-terminator and reset the CurrIndex + // + SearchIndex = CurrIndex; + PrevSearchIndex = PrevIndex; + + for (; SearchIndex > PrevSearchIndex; PrevSearchIndex++) { + if ((StringPtr[PrevSearchIndex] == CHAR_NULL) || (StringPtr[PrevSearchIndex] == CHAR_LINEFEED)) { + CurrIndex = PrevSearchIndex; + break; + } + + if (StringPtr[PrevSearchIndex] == CHAR_CARRIAGE_RETURN) { + if (StringPtr[PrevSearchIndex + 1] == CHAR_LINEFEED) { + // + // Found a "\n",advance to the next new line. + // + CurrIndex = PrevSearchIndex + 1; + break; + } else { + // + // Found a "\r",return to the start of the current line. + // + PrevIndex = PrevSearchIndex + 1; + CurrIndex = PrevSearchIndex + gHelpBlockWidth; + continue; + } + } + } + + // + // End of the string, thus stop counting. + // + if (StringPtr[CurrIndex] == CHAR_NULL) { + // + // Copy the fragment to the FormattedString buffer + // + StrnCpy ((FormattedString[0] + StringCount * gHelpBlockWidth), &StringPtr[PrevIndex], CurrIndex - PrevIndex); + StringCount++; + break; + } + // + // The premise is that for every HELP_BLOCK_WIDTH we rewind + // until we find the first space. That is the delimiter for + // the string, and we will then advance our CurrIndex another + // HELP_BLOCK_WIDTH and continue the process breaking the larger + // string into chunks that fit within the HELP_BLOCK_WIDTH requirements. + // + if (StringPtr[CurrIndex] == CHAR_SPACE) { + // + // Copy the fragment to the FormattedString buffer + // + StrnCpy ((FormattedString[0] + StringCount * gHelpBlockWidth), &StringPtr[PrevIndex], CurrIndex - PrevIndex); + StringCount++; + PrevIndex = CurrIndex + 1; + CurrIndex = CurrIndex + gHelpBlockWidth; + } + // + // Found a LineFeed, advance to the next line. + // + if (StringPtr[CurrIndex] == CHAR_LINEFEED) { + StringPtr[CurrIndex] = CHAR_SPACE; + // + // "\n" is represented as CHAR_CARRIAGE_RETURN + CHAR_LINEFEED,check this. + // + if (StringPtr[CurrIndex - 1] == CHAR_CARRIAGE_RETURN) { + StringPtr[CurrIndex - 1] = CHAR_SPACE; + } + + StrnCpy ((FormattedString[0] + StringCount * gHelpBlockWidth), &StringPtr[PrevIndex], CurrIndex - PrevIndex); + StringCount++; + PrevIndex = CurrIndex + 1; + CurrIndex = CurrIndex + gHelpBlockWidth; + } + } + // + // endfor + // + return ; +} + +VOID +IfrToFormTag ( + IN UINT8 OpCode, + IN EFI_TAG *TargetTag, + IN VOID *FormData, + EFI_VARIABLE_DEFINITION *VariableDefinitionsHead + ) +{ + UINT16 TempValue; + CHAR16 *VariableName; + CHAR8 *AsciiString; + EFI_VARIABLE_DEFINITION *VariableDefinitions; + EFI_VARIABLE_DEFINITION *PreviousVariableDefinitions; + STATIC UINT16 VariableSize; + EFI_GUID Guid; + STATIC UINT16 CurrentVariable; + STATIC UINT16 CurrentVariable2; + UINTN Index; + + switch (OpCode) { + case EFI_IFR_FORM_OP: + CopyMem (&TargetTag->Id, &((EFI_IFR_FORM *) FormData)->FormId, sizeof (UINT16)); + CopyMem (&TargetTag->Text, &((EFI_IFR_FORM *) FormData)->FormTitle, sizeof (UINT16)); + TargetTag->VariableNumber = CurrentVariable; + if (VariableDefinitionsHead != NULL) { + VariableName = AllocateZeroPool (12); + ASSERT (VariableName != NULL); + CopyMem (VariableName, L"Setup", 12); + VariableDefinitionsHead->VariableName = VariableName; + VariableDefinitionsHead->VariableSize = VariableSize; + CopyMem (&VariableDefinitionsHead->Guid, &Guid, sizeof (EFI_GUID)); + } + break; + + case EFI_IFR_SUBTITLE_OP: + TargetTag->NumberOfLines = 1; + CopyMem (&TargetTag->Text, &((EFI_IFR_SUBTITLE *) FormData)->SubTitle, sizeof (UINT16)); + TargetTag->VariableNumber = CurrentVariable; + break; + + case EFI_IFR_TEXT_OP: + TargetTag->NumberOfLines = 1; + CopyMem (&TargetTag->Text, &((EFI_IFR_TEXT *) FormData)->Text, sizeof (UINT16)); + CopyMem (&TargetTag->Help, &((EFI_IFR_TEXT *) FormData)->Help, sizeof (UINT16)); + TargetTag->VariableNumber = CurrentVariable; + + // + // To optimize the encoding size, certain opcodes have optional fields such as those + // inside the if() statement. If the encoded length is the complete size, then we + // know we have valid data encoded that we want to integrate + // + if (((EFI_IFR_TEXT *) FormData)->Header.Length == sizeof (EFI_IFR_TEXT)) { + // + // Text has no help associated with it, but in case there is a second entry due to + // dynamic/interactive flags being active, bring this data over. + // + CopyMem (&TargetTag->TextTwo, &((EFI_IFR_TEXT *) FormData)->TextTwo, sizeof (UINT16)); + TargetTag->Flags = ((EFI_IFR_TEXT *) FormData)->Flags; + CopyMem (&TargetTag->Key, &((EFI_IFR_TEXT *) FormData)->Key, sizeof (UINT16)); + } + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + CopyMem (&TargetTag->Text, &((EFI_IFR_ONE_OF_OPTION *) FormData)->Option, sizeof (UINT16)); + CopyMem (&TargetTag->Value, &((EFI_IFR_ONE_OF_OPTION *) FormData)->Value, sizeof (UINT16)); + TargetTag->Flags = ((EFI_IFR_ONE_OF_OPTION *) FormData)->Flags; + CopyMem (&TargetTag->Key, &((EFI_IFR_ONE_OF_OPTION *) FormData)->Key, sizeof (UINT16)); + TargetTag->VariableNumber = CurrentVariable; + break; + + case EFI_IFR_CHECKBOX_OP: + TargetTag->Flags = ((EFI_IFR_CHECKBOX *) FormData)->Flags; + TargetTag->ResetRequired = (BOOLEAN) (TargetTag->Flags & EFI_IFR_FLAG_RESET_REQUIRED); + CopyMem (&TargetTag->Key, &((EFI_IFR_CHECKBOX *) FormData)->Key, sizeof (UINT16)); + TargetTag->VariableNumber = CurrentVariable; + break; + + case EFI_IFR_NUMERIC_OP: + TargetTag->Flags = ((EFI_IFR_NUMERIC *) FormData)->Flags; + CopyMem (&TargetTag->Key, &((EFI_IFR_NUMERIC *) FormData)->Key, sizeof (UINT16)); + TargetTag->VariableNumber = CurrentVariable; + break; + + case EFI_IFR_STRING_OP: + TempValue = 0; + CopyMem (&TempValue, &((EFI_IFR_STRING *) FormData)->MinSize, sizeof (UINT8)); + TempValue = (UINT16) (TempValue * 2); + CopyMem (&TargetTag->Minimum, &TempValue, sizeof (UINT16)); + + CopyMem (&TempValue, &((EFI_IFR_STRING *) FormData)->MaxSize, sizeof (UINT8)); + TempValue = (UINT16) (TempValue * 2); + CopyMem (&TargetTag->Maximum, &TempValue, sizeof (UINT16)); + CopyMem (&TargetTag->StorageWidth, &TempValue, sizeof (UINT16)); + TargetTag->Flags = (UINT8) (((EFI_IFR_STRING *) FormData)->Flags); + TargetTag->ResetRequired = (BOOLEAN) (TargetTag->Flags & EFI_IFR_FLAG_RESET_REQUIRED); + CopyMem (&TargetTag->Key, &((EFI_IFR_STRING *) FormData)->Key, sizeof (UINT16)); + TargetTag->VariableNumber = CurrentVariable; + break; + + case EFI_IFR_PASSWORD_OP: + TempValue = 0; + CopyMem (&TempValue, &((EFI_IFR_PASSWORD *) FormData)->MinSize, sizeof (UINT8)); + TempValue = (UINT16) (TempValue * 2); + CopyMem (&TargetTag->Minimum, &TempValue, sizeof (UINT16)); + + CopyMem (&TempValue, &((EFI_IFR_PASSWORD *) FormData)->MaxSize, sizeof (UINT8)); + TempValue = (UINT16) (TempValue * 2); + CopyMem (&TargetTag->Maximum, &TempValue, sizeof (UINT16)); + CopyMem (&TargetTag->StorageWidth, &TempValue, sizeof (UINT16)); + TargetTag->Flags = ((EFI_IFR_PASSWORD *) FormData)->Flags; + TargetTag->ResetRequired = (BOOLEAN) (TargetTag->Flags & EFI_IFR_FLAG_RESET_REQUIRED); + CopyMem (&TargetTag->Key, &((EFI_IFR_PASSWORD *) FormData)->Key, sizeof (UINT16)); + CopyMem (&TargetTag->Encoding, &((EFI_IFR_PASSWORD *) FormData)->Encoding, sizeof (UINT16)); + TargetTag->VariableNumber = CurrentVariable; + break; + + case EFI_IFR_VARSTORE_OP: + // + // It should NEVER be NULL + // + if (VariableDefinitionsHead == NULL) { + break; + } + + VariableDefinitions = VariableDefinitionsHead; + + // + // Advance VariableDefinitions to the last entry + // + for (; VariableDefinitions != NULL; VariableDefinitions = VariableDefinitions->Next) { + PreviousVariableDefinitions = VariableDefinitions; + // + // If there is a variable with this GUID and ID already, we need to bail out + // + if (!CompareMem (&VariableDefinitions->Guid, &((EFI_IFR_VARSTORE *) FormData)->Guid, sizeof (EFI_GUID)) && + !CompareMem (&VariableDefinitions->VariableId, &((EFI_IFR_VARSTORE *) FormData)->VarId, sizeof (UINT16)) + ) { + return ; + } + + if (VariableDefinitions->Next == NULL) { + break; + } + } + // + // If the last entry has a variable in it already, allocate a new entry and use it + // + if (VariableDefinitions->VariableName != NULL) { + VariableDefinitions->Next = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION)); + ASSERT (VariableDefinitions->Next != NULL); + PreviousVariableDefinitions = VariableDefinitions; + VariableDefinitions = VariableDefinitions->Next; + VariableDefinitions->Previous = PreviousVariableDefinitions; + } + // + // Copy the Variable data to our linked list + // + CopyMem (&VariableDefinitions->VariableId, &((EFI_IFR_VARSTORE *) FormData)->VarId, sizeof (UINT16)); + CopyMem (&VariableDefinitions->VariableSize, &((EFI_IFR_VARSTORE *) FormData)->Size, sizeof (UINT16)); + CopyMem (&VariableDefinitions->Guid, &((EFI_IFR_VARSTORE *) FormData)->Guid, sizeof (EFI_GUID)); + + // + // The ASCII String which is immediately past the EFI_IFR_VARSTORE is inferred by the structure definition + // due to it being variable sized. There are rules preventing it from being > 40 characters long and should + // be enforced by the compiler. + // + AsciiString = (CHAR8 *) (&((EFI_IFR_VARSTORE *) FormData)->Size); + AsciiString = AsciiString + 2; + VariableDefinitions->VariableName = AllocateZeroPool ((AsciiStrLen (AsciiString) + 1) * 2); + ASSERT (VariableDefinitions->VariableName != NULL); + for (Index = 0; AsciiString[Index] != 0; Index++) { + VariableDefinitions->VariableName[Index] = (CHAR16) AsciiString[Index]; + } + + VariableDefinitions->VariableName[Index] = 0; + + // + // Propogate the tag information for this op-code + // + CopyMem (&TargetTag->VariableNumber, &((EFI_IFR_VARSTORE *) FormData)->VarId, sizeof (UINT16)); + CopyMem (&TargetTag->GuidValue, &((EFI_IFR_VARSTORE *) FormData)->Guid, sizeof (EFI_GUID)); + CopyMem (&TargetTag->StorageWidth, &((EFI_IFR_VARSTORE *) FormData)->Size, sizeof (UINT16)); + CopyMem (&TargetTag->Maximum, &((EFI_IFR_VARSTORE *) FormData)->Size, sizeof (UINT16)); + break; + + case EFI_IFR_VARSTORE_SELECT_OP: + CopyMem (&TargetTag->VariableNumber, &((EFI_IFR_VARSTORE_SELECT *) FormData)->VarId, sizeof (UINT16)); + CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) FormData)->VarId, sizeof (UINT16)); + CurrentVariable2 = CurrentVariable; + break; + + case EFI_IFR_VARSTORE_SELECT_PAIR_OP: + CopyMem (&TargetTag->VariableNumber, &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->VarId, sizeof (UINT16)); + CopyMem ( + &TargetTag->VariableNumber2, + &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->SecondaryVarId, + sizeof (UINT16) + ); + CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->VarId, sizeof (UINT16)); + CopyMem (&CurrentVariable2, &((EFI_IFR_VARSTORE_SELECT_PAIR *) FormData)->SecondaryVarId, sizeof (UINT16)); + break; + + case EFI_IFR_REF_OP: + TargetTag->NumberOfLines = 1; + CopyMem (&TargetTag->Id, &((EFI_IFR_REF *) FormData)->FormId, sizeof (UINT16)); + CopyMem (&TargetTag->Key, &((EFI_IFR_REF *) FormData)->Key, sizeof (UINT16)); + CopyMem (&TargetTag->Text, &((EFI_IFR_REF *) FormData)->Prompt, sizeof (UINT16)); + CopyMem (&TargetTag->Help, &((EFI_IFR_REF *) FormData)->Help, sizeof (UINT16)); + TargetTag->Flags = ((EFI_IFR_REF *) FormData)->Flags; + TargetTag->VariableNumber = CurrentVariable; + break; + + case EFI_IFR_EQ_ID_VAL_OP: + CopyMem (&TargetTag->Value, &((EFI_IFR_EQ_ID_VAL *) FormData)->Value, sizeof (UINT16)); + CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_ID_VAL *) FormData)->QuestionId, sizeof (UINT16)); + TargetTag->StorageWidth = ((EFI_IFR_EQ_ID_VAL *) FormData)->Width; + TargetTag->VariableNumber = CurrentVariable; + break; + + case EFI_IFR_EQ_VAR_VAL_OP: + CopyMem (&TargetTag->Value, &((EFI_IFR_EQ_VAR_VAL *) FormData)->Value, sizeof (UINT16)); + CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_VAR_VAL *) FormData)->VariableId, sizeof (UINT16)); + TargetTag->VariableNumber = CurrentVariable; + break; + + case EFI_IFR_EQ_ID_ID_OP: + CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_ID_ID *) FormData)->QuestionId1, sizeof (UINT16)); + CopyMem (&TargetTag->Id2, &((EFI_IFR_EQ_ID_ID *) FormData)->QuestionId2, sizeof (UINT16)); + TargetTag->StorageWidth = ((EFI_IFR_EQ_ID_ID *) FormData)->Width; + TargetTag->VariableNumber = CurrentVariable; + TargetTag->VariableNumber = CurrentVariable2; + break; + + case EFI_IFR_EQ_ID_LIST_OP: + CopyMem (&TargetTag->Id, &((EFI_IFR_EQ_ID_LIST *) FormData)->QuestionId, sizeof (UINT16)); + CopyMem (&TargetTag->Id2, &((EFI_IFR_EQ_ID_LIST *) FormData)->ListLength, sizeof (UINT16)); + TargetTag->StorageWidth = ((EFI_IFR_EQ_ID_LIST *) FormData)->Width; + + TargetTag->IntList = AllocateZeroPool (TargetTag->Id2 * sizeof (UINT16)); + ASSERT (TargetTag->IntList); + + for (TempValue = 0; TempValue < TargetTag->Id2; TempValue++) { + CopyMem ( + &TargetTag->IntList[TempValue], + &((EFI_IFR_EQ_ID_LIST *) FormData)->ValueList[TempValue], + sizeof (UINT16) + ); + } + + TargetTag->VariableNumber = CurrentVariable; + break; + + case EFI_IFR_FORM_SET_OP: + CopyMem (&VariableSize, &((EFI_IFR_FORM_SET *) FormData)->NvDataSize, sizeof (UINT16)); + CopyMem (&Guid, &((EFI_IFR_FORM_SET *) FormData)->Guid, sizeof (EFI_GUID)); + // + // If there is a size specified in the formste, we will establish a "default" variable + // + if (VariableDefinitionsHead != NULL) { + VariableName = AllocateZeroPool (12); + ASSERT (VariableName != NULL); + CopyMem (VariableName, L"Setup", 12); + VariableDefinitionsHead->VariableName = VariableName; + VariableDefinitionsHead->VariableSize = VariableSize; + CopyMem (&VariableDefinitionsHead->Guid, &Guid, sizeof (EFI_GUID)); + } + break; + + case EFI_IFR_END_FORM_SET_OP: + CurrentVariable = 0; + CurrentVariable2 = 0; + break; + } + + return ; +} diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Setup.c b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Setup.c new file mode 100644 index 0000000000..f62bc120f0 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Setup.c @@ -0,0 +1,2217 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + Setup.c + +Abstract: + + Entry and initialization module for the browser + +Revision History: +--*/ + +#include "Setup.h" +#include "Ui.h" + +FUNCTIION_KEY_SETTING gFunctionKeySettingTable[] = { + // + // Boot Manager + // + { + { + 0x847bc3fe, + 0xb974, + 0x446d, + { + 0x94, + 0x49, + 0x5a, + 0xd5, + 0x41, + 0x2e, + 0x99, + 0x3b + } + }, + NONE_FUNCTION_KEY_SETTING + }, + // + // Device Manager + // + { + { + 0x3ebfa8e6, + 0x511d, + 0x4b5b, + { + 0xa9, + 0x5f, + 0xfb, + 0x38, + 0x26, + 0xf, + 0x1c, + 0x27 + } + }, + NONE_FUNCTION_KEY_SETTING + }, + // + // BMM Formset. + // + { + { + 0x642237c7, + 0x35d4, + 0x472d, + { + 0x83, + 0x65, + 0x12, + 0xe0, + 0xcc, + 0xf2, + 0x7a, + 0x22 + } + }, + NONE_FUNCTION_KEY_SETTING + }, + // + // BMM File Explorer Formset. + // + { + { + 0x1f2d63e1, + 0xfebd, + 0x4dc7, + { + 0x9c, + 0xc5, + 0xba, + 0x2b, + 0x1c, + 0xef, + 0x9c, + 0x5b + } + }, + NONE_FUNCTION_KEY_SETTING + }, +}; + +EFI_STATUS +InitializeBinaryStructures ( + IN EFI_HII_HANDLE *Handle, + IN BOOLEAN UseDatabase, + IN EFI_IFR_PACKET *Packet, + IN UINT8 *NvMapOverride, + IN UINTN NumberOfIfrImages, + EFI_FILE_FORM_TAGS **FileFormTagsHead + ); + +EFI_STATUS +InitializeTagStructures ( + IN EFI_IFR_BINARY *BinaryData, + OUT EFI_FILE_FORM_TAGS *FileFormTags + ); + +UI_MENU_OPTION * +DisplayHomePage ( + IN UINTN NumberOfIfrImages, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN UINT8 *CallbackData + ); + +EFI_STATUS +GetIfrBinaryData ( + IN EFI_HII_PROTOCOL *Hii, + IN EFI_HII_HANDLE HiiHandle, + IN EFI_IFR_PACKET *Packet, + IN EFI_IFR_BINARY *BinaryData + ); + +EFI_STATUS +InstallPrint ( + VOID + ); + +EFI_STATUS +EFIAPI +SendForm ( + IN EFI_FORM_BROWSER_PROTOCOL * This, + IN BOOLEAN UseDatabase, + IN EFI_HII_HANDLE * Handle, + IN UINTN HandleCount, + IN EFI_IFR_PACKET * Packet, + IN EFI_HANDLE CallbackHandle, + IN UINT8 *NvMapOverride, + IN EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL + OUT BOOLEAN *ResetRequired OPTIONAL + ) +/*++ + +Routine Description: + + This is the routine which an external caller uses to direct the browser + where to obtain it's information. + +Arguments: + + UseDatabase - If set to TRUE, then all information is retrieved from the HII database handle specified + If set to FALSE, then the passed in Packet and CallbackHandle is used and Handle is ignored + + Handle - A pointer to an array of Handles. If HandleCount > 1 we display a list of the formsets for the handles specified + + HandleCount - The number of Handles specified in Handle. + + Packet - Valid only if UseDatabase is FALSE. Packet defines the pages being passed into + the browser. This is composed of IFR data as well as String information. + + CallbackHandle - The handle which contains the calling driver's EFI_FORM_CALLBACK_PROTOCOL interface. + + ScreenDimenions - This allows the browser to be called so that it occupies a portion of the physical screen instead of + dynamically determining the screen dimensions. + + NvMapOverride - This buffer is used only when there is no NV variable to define the current settings and the caller + needs to provide to the browser the current settings for the "fake" NV variable. If used, no saving + of an NV variable will be possible. This parameter is also ignored if HandleCount > 1. + +Returns: + +--*/ +{ + EFI_FORM_CONFIGURATION_DATA *FormData; + EFI_FORM_CALLBACK_PROTOCOL *FormCallback; + EFI_FILE_FORM_TAGS *FileFormTagsHead; + UI_MENU_OPTION *Selection; + UI_MENU_OPTION *AltSelection; + EFI_STATUS Status; + BOOLEAN Callback; + VOID *CallbackData; + EFI_HII_HANDLE BackupHandle; + + ZeroMem (&gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + + gPreviousValue = AllocatePool (0x1000); + CallbackData = AllocatePool (0x10000); + ASSERT (gPreviousValue != NULL); + ASSERT (CallbackData != NULL); + + do { + // + // Seed the dimensions in the global + // + gST->ConOut->QueryMode ( + gST->ConOut, + gST->ConOut->Mode->Mode, + &gScreenDimensions.RightColumn, + &gScreenDimensions.BottomRow + ); + + if (ScreenDimensions != NULL) { + // + // Check local dimension vs. global dimension. + // + if ((gScreenDimensions.RightColumn < ScreenDimensions->RightColumn) || + (gScreenDimensions.BottomRow < ScreenDimensions->BottomRow) + ) { + return EFI_INVALID_PARAMETER; + } else { + // + // Local dimension validation. + // + if ((ScreenDimensions->RightColumn > ScreenDimensions->LeftColumn) && + (ScreenDimensions->BottomRow > ScreenDimensions->TopRow) && + ((ScreenDimensions->RightColumn - ScreenDimensions->LeftColumn) > 2) && + ( + (ScreenDimensions->BottomRow - ScreenDimensions->TopRow) > STATUS_BAR_HEIGHT + + SCROLL_ARROW_HEIGHT * + 2 + + FRONT_PAGE_HEADER_HEIGHT + + FOOTER_HEIGHT + + 1 + ) + ) { + CopyMem (&gScreenDimensions, ScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + } else { + return EFI_INVALID_PARAMETER; + } + } + } + + gOptionBlockWidth = (CHAR16) ((gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn) / 3); + gHelpBlockWidth = gOptionBlockWidth; + gPromptBlockWidth = gOptionBlockWidth; + + // + // Initialize the strings for the browser, upon exit of the browser, the strings will be freed + // + InitializeBrowserStrings (); + + gFunctionKeySetting = DEFAULT_FUNCTION_KEY_SETTING; + gClassOfVfr = EFI_SETUP_APPLICATION_SUBCLASS; + gResetRequired = FALSE; + gExitRequired = FALSE; + gSaveRequired = FALSE; + gNvUpdateRequired = FALSE; + gActiveIfr = 0; + gConsistencyId = 0; + gPriorMenuEntry = 0; + BackupHandle = *Handle; + gMenuRefreshHead = NULL; + ASSERT (CallbackData); + ZeroMem (CallbackData, 0x10000); + + // + // We can recurse through this and might need to re-allocate this particular buffer + // + if (gPreviousValue == NULL) { + gPreviousValue = AllocatePool (0x1000); + ASSERT (gPreviousValue != NULL); + } + + FormData = EFI_FORM_DATA_FROM_THIS (This); + Callback = FALSE; + FormCallback = NULL; + + if (CallbackHandle != NULL) { + // + // Retrieve the Callback protocol interface + // + Status = gBS->HandleProtocol ( + CallbackHandle, + &gEfiFormCallbackProtocolGuid, + (VOID **) &FormCallback + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (CallbackData); + return Status;; + } + + Callback = TRUE; + } + // + // Initializes all the internal state structures for all IFR images in system + // + Status = InitializeBinaryStructures (Handle, UseDatabase, Packet, NvMapOverride, HandleCount, &FileFormTagsHead); + + if (EFI_ERROR (Status)) { + gBS->FreePool (CallbackData); + return Status; + } + // + // Beginning of the Presentation of the Data + // + if (UseDatabase && (HandleCount > 1)) { + Selection = DisplayHomePage (HandleCount, FileFormTagsHead, CallbackData); + } else { + // + // If passing something specific, we know there is only one Ifr + // + Selection = AllocateZeroPool (sizeof (UI_MENU_OPTION)); + ASSERT (Selection != NULL); + Selection->IfrNumber = 0; + Selection->Handle = Handle[0]; + UiInitMenu (); + } + + UiInitMenuList (); + + if (UseDatabase && (HandleCount > 1)) { + if (Selection == NULL) { + gBS->FreePool (CallbackData); + return EFI_SUCCESS; + } + } + // + // Launch the setup browser with the user's selection information + // + AltSelection = SetupBrowser (Selection, Callback, FileFormTagsHead, CallbackData); + + // + // If the caller cares about Reset status, we can return to the caller if something happened that required a reset + // + if (ResetRequired != NULL) { + *ResetRequired = gResetRequired; + } + + if (Callback && (AltSelection != NULL)) { + if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) { + Status = FormCallback->Callback ( + FormCallback, + AltSelection->ThisTag->Key, + CallbackData, + (EFI_HII_CALLBACK_PACKET **) &Packet + ); + } + } + + *Handle = BackupHandle; + + if (EFI_ERROR (Status)) { + gBS->FreePool (CallbackData); + return Status; + } + + if (Callback && (AltSelection == NULL)) { + gBS->FreePool (CallbackData); + return Status; + } + + if (UseDatabase && (HandleCount > 1)) { + } else { + + if (gBinaryDataHead->UnRegisterOnExit) { + Hii->RemovePack (Hii, Handle[0]); + } + + if (Callback && + ((AltSelection->ThisTag->SubClass == EFI_FRONT_PAGE_SUBCLASS) || + (AltSelection->ThisTag->SubClass == EFI_SINGLE_USE_SUBCLASS))) { + // + // If this is the FrontPage, return after every selection + // + gBS->FreePool (Selection); + UiFreeMenu (); + + // + // Clean up the allocated data buffers + // + FreeData (FileFormTagsHead, NULL, NULL); + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->ClearScreen (gST->ConOut); + + gBS->FreePool (CallbackData); + return EFI_SUCCESS; + } + + gBS->FreePool (Selection); + UiFreeMenu (); + + // + // Clean up the allocated data buffers + // + FreeData (FileFormTagsHead, NULL, NULL); + + gST->ConOut->ClearScreen (gST->ConOut); + + if (!Callback) { + gBS->FreePool (CallbackData); + return EFI_SUCCESS; + } + } + + } while (!EFI_ERROR (Status)); + + gBS->FreePool (CallbackData); + return Status; +} + +EFI_STATUS +EFIAPI +InitializeSetup ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Initialize Setup + +Arguments: + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + EFI_SUCCESS - Setup loaded. + other - Setup Error + +--*/ +{ + EFI_STATUS Status; + EFI_FORM_CONFIGURATION_DATA *FormData; + EFI_FORM_BROWSER_PROTOCOL *FormBrowser; + EFI_HANDLE Handle; + EFI_HII_PACKAGES *PackageList; + + // + // There will be only one FormConfig in the system + // If there is another out there, someone is trying to install us + // again. Fail that scenario. + // + Status = gBS->LocateProtocol ( + &gEfiFormBrowserProtocolGuid, + NULL, + (VOID **) &FormBrowser + ); + + gFirstIn = TRUE; + + // + // If there was no error, assume there is an installation and fail to load + // + if (!EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + FormData = AllocatePool (sizeof (EFI_FORM_CONFIGURATION_DATA)); + + if (FormData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Fill in HII data + // + FormData->Signature = EFI_FORM_DATA_SIGNATURE; + FormData->FormConfig.SendForm = SendForm; + FormData->FormConfig.CreatePopUp = CreateDialog; + + // + // There should only be one HII image + // + Status = gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + (VOID **) &FormData->Hii + ); + + ASSERT_EFI_ERROR (Status); + + Hii = FormData->Hii; + + PackageList = PreparePackages (1, &gEfiFormBrowserProtocolGuid, SetupBrowserStrings); + + Status = Hii->NewPack (Hii, PackageList, &gHiiHandle); + + gBS->FreePool (PackageList); + + // + // Install protocol interface + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiFormBrowserProtocolGuid, + EFI_NATIVE_INTERFACE, + &FormData->FormConfig + ); + + ASSERT_EFI_ERROR (Status); + + BannerData = AllocateZeroPool (sizeof (BANNER_DATA)); + ASSERT (BannerData != NULL); + + Status = InstallPrint (); + return Status; +} + +VOID +GetQuestionHeader ( + IN EFI_TAG *Tag, + IN UINT8 *RawFormSet, + IN UINT16 Index, + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UINT16 CurrentVariable + ) +/*++ + +Routine Description: + Initialize question tag's members. + +Arguments: + Tag - Pointer of the current EFI_TAG structure. + RawFormSet - Pointer of the formset raw data. + Index - Offset of the current opcode in the Ifr raw data. + FileFormTags - Pointer of current EFI_FILE_FORM_TAGS structure. + CurrentVariable - Current variable number. + +Returns: + None. +--*/ +{ + EFI_VARIABLE_DEFINITION *VariableDefinition; + + Tag->NumberOfLines = 1; + Tag->VariableNumber = CurrentVariable; + CopyMem (&Tag->Id, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16)); + CopyMem (&Tag->StorageStart, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16)); + CopyMem (&Tag->StorageWidth, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Width, sizeof (UINT8)); + CopyMem (&Tag->Text, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Prompt, sizeof (UINT16)); + CopyMem (&Tag->Help, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Help, sizeof (UINT16)); + + VariableDefinition = FileFormTags->VariableDefinitions; + + for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) { + // + // Have we found the correct variable for the request? + // + if (CurrentVariable == VariableDefinition->VariableId) { + if (VariableDefinition->VariableSize < (UINTN) (Tag->StorageStart + Tag->StorageWidth)) { + VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + Tag->StorageWidth); + } + + if (VariableDefinition->NvRamMap != NULL) { + // + // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise + // we will never be looking for the data in Tag->Value (e.g. strings, password, etc) + // + if (Tag->StorageWidth == (UINT16) 1) { + CopyMem (&Tag->Value, &VariableDefinition->NvRamMap[Tag->StorageStart], sizeof (UINT16)); + } + + if (Tag->StorageWidth == (UINT16) 2) { + Index = (UINT16) + ( + VariableDefinition->NvRamMap[Tag->StorageStart] + + (VariableDefinition->NvRamMap[Tag->StorageStart + 1] * 0x100) + ); + CopyMem (&Tag->Value, &Index, sizeof (UINT16)); + } + } else { + Index = 0; + CopyMem (&Tag->Value, &Index, sizeof (UINT16)); + } + break; + } else { + continue; + } + } +} + +VOID +GetNumericHeader ( + IN EFI_TAG *Tag, + IN UINT8 *RawFormSet, + IN UINT16 Index, + IN UINT16 NumberOfLines, + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UINT16 CurrentVariable + ) +/*++ + +Routine Description: + Initialize numeric tag's members. + +Arguments: + Tag - Pointer of the current EFI_TAG structure. + RawFormSet - Pointer of the formset raw data. + Index - Offset of the current opcode in the Ifr raw data. + NumberOfLines - Number of lines this opcode occupied. + FileFormTags - Pointer of current EFI_FILE_FORM_TAGS structure. + CurrentVariable - Current variable number. + +Returns: + None. +--*/ +{ + EFI_VARIABLE_DEFINITION *VariableDefinition; + + Tag->NumberOfLines = NumberOfLines; + Tag->VariableNumber = CurrentVariable; + CopyMem (&Tag->Id, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16)); + CopyMem (&Tag->StorageStart, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->QuestionId, sizeof (UINT16)); + CopyMem (&Tag->StorageWidth, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Width, sizeof (UINT8)); + CopyMem (&Tag->Text, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Prompt, sizeof (UINT16)); + CopyMem (&Tag->Help, &((EFI_IFR_ONE_OF *) &RawFormSet[Index])->Help, sizeof (UINT16)); + CopyMem (&Tag->Minimum, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Minimum, sizeof (UINT16)); + CopyMem (&Tag->Maximum, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Maximum, sizeof (UINT16)); + CopyMem (&Tag->Step, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Step, sizeof (UINT16)); + CopyMem (&Tag->Default, &((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Default, sizeof (UINT16)); + Tag->ResetRequired = (BOOLEAN) (((EFI_IFR_NUMERIC *) &RawFormSet[Index])->Flags & EFI_IFR_FLAG_RESET_REQUIRED); + + VariableDefinition = FileFormTags->VariableDefinitions; + + for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) { + // + // Have we found the correct variable for the request? + // + if (CurrentVariable == VariableDefinition->VariableId) { + if (VariableDefinition->VariableSize <= (UINTN) (Tag->StorageStart + Tag->StorageWidth)) { + if (Tag->StorageWidth == 0) { + VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + 2); + } else { + VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + Tag->StorageWidth); + } + } + + if (VariableDefinition->NvRamMap != NULL) { + // + // If it is an 8bit or 16bit width, then move it to Tag->Value, otherwise + // we will never be looking for the data in Tag->Value (e.g. strings, password, etc) + // + if (Tag->StorageWidth == (UINT16) 1) { + CopyMem (&Tag->Value, &VariableDefinition->NvRamMap[Tag->StorageStart], sizeof (UINT16)); + } + + if (Tag->StorageWidth == (UINT16) 2) { + Index = (UINT16) + ( + VariableDefinition->NvRamMap[Tag->StorageStart] + + (VariableDefinition->NvRamMap[Tag->StorageStart + 1] * 0x100) + ); + CopyMem (&Tag->Value, &Index, sizeof (UINT16)); + } + } else { + CopyMem (&Tag->Value, &Tag->Default, sizeof (UINT16)); + } + break; + } else { + continue; + } + } +} + +VOID +GetTagCount ( + IN UINT8 *RawFormSet, + IN OUT UINT16 *NumberOfTags + ) +{ + UINT16 Index; + + // + // Assume on entry we are pointing to an OpCode - reasonably this should + // be a FormOp since the purpose is to count the tags in a particular Form. + // + for (Index = 0; RawFormSet[Index] != EFI_IFR_END_FORM_OP;) { + // + // If we encounter the end of a form set, bail out + // + if (RawFormSet[Index] == EFI_IFR_END_FORM_SET_OP) { + break; + } + // + // We treat date/time internally as three op-codes + // + if (RawFormSet[Index] == EFI_IFR_DATE_OP || RawFormSet[Index] == EFI_IFR_TIME_OP) { + *NumberOfTags = (UINT16) (*NumberOfTags + 3); + } else { + // + // Assume that we could have no more tags than op-codes + // + (*NumberOfTags)++; + } + + Index = (UINT16) (Index + RawFormSet[Index + 1]); + } + // + // Increase the tag count by one so it is inclusive of the end_form_op + // + (*NumberOfTags)++; +} + +VOID +AddNextInconsistentTag ( + IN OUT EFI_INCONSISTENCY_DATA **InconsistentTagsPtr + ) +/*++ + +Routine Description: + Initialize the next inconsistent tag data and add it to the inconsistent tag list. + +Arguments: + InconsistentTagsPtr - Pointer of the inconsistent tag's pointer. + +Returns: + None. + +--*/ +{ + EFI_INCONSISTENCY_DATA *PreviousInconsistentTags; + EFI_INCONSISTENCY_DATA *InconsistentTags; + + InconsistentTags = *InconsistentTagsPtr; + // + // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure + // + InconsistentTags->Next = AllocatePool (sizeof (EFI_INCONSISTENCY_DATA)); + ASSERT (InconsistentTags->Next != NULL); + + // + // Preserve current Tag entry + // + PreviousInconsistentTags = InconsistentTags; + + InconsistentTags = InconsistentTags->Next; + + // + // This will zero on the entry including the ->Next so I don't have to do it + // + ZeroMem (InconsistentTags, sizeof (EFI_INCONSISTENCY_DATA)); + + // + // Point our Previous field to the previous entry + // + InconsistentTags->Previous = PreviousInconsistentTags; + + *InconsistentTagsPtr = InconsistentTags; + + return ; +} + +EFI_STATUS +InitializeTagStructures ( + IN EFI_IFR_BINARY *BinaryData, + OUT EFI_FILE_FORM_TAGS *FileFormTags + ) +{ + EFI_STATUS Status; + UINT8 *RawFormSet; + UINT16 Index; + UINT16 QuestionIndex; + UINT16 NumberOfTags; + INT16 CurrTag; + UINT8 TagLength; + EFI_FORM_TAGS *FormTags; + EFI_FORM_TAGS *SavedFormTags; + EFI_INCONSISTENCY_DATA *InconsistentTags; + EFI_VARIABLE_DEFINITION *VariableDefinitions; + UINTN Count; + UINT16 Class; + UINT16 SubClass; + UINT16 TempValue; + UINT16 CurrentVariable; + UINT16 CurrentVariable2; + + // + // Initialize some Index variable and Status + // + Count = 0; + Class = 0; + SubClass = 0; + CurrentVariable = 0; + CurrentVariable2 = 0; + QuestionIndex = 0; + NumberOfTags = 1; + Status = EFI_SUCCESS; + FormTags = &FileFormTags->FormTags; + FormTags->Next = NULL; + if (FileFormTags->InconsistentTags == NULL) { + InconsistentTags = NULL; + } else { + InconsistentTags = FileFormTags->InconsistentTags; + } + + if (FileFormTags->VariableDefinitions == NULL) { + VariableDefinitions = NULL; + } else { + VariableDefinitions = FileFormTags->VariableDefinitions; + } + // + // RawFormSet now points to the beginning of the forms portion of + // the specific IFR Binary. + // + RawFormSet = (UINT8 *) BinaryData->FormBinary; + + // + // Determine the number of tags for the first form + // + GetTagCount (&RawFormSet[0], &NumberOfTags); + + SavedFormTags = FormTags; + + if (FormTags->Tags != NULL) { + do { + // + // Advance FormTags to the last entry + // + for (; FormTags->Next != NULL; FormTags = FormTags->Next) + ; + + // + // Walk through each of the tags and free the IntList allocation + // + for (Index = 0; Index < NumberOfTags; Index++) { + if (FormTags->Tags[Index].IntList != NULL) { + gBS->FreePool (FormTags->Tags[Index].IntList); + } + } + + gBS->FreePool (FormTags->Tags); + gBS->FreePool (FormTags->Next); + FormTags->Next = NULL; + FormTags->Tags = NULL; + + FormTags = SavedFormTags; + + } while (FormTags->Next != NULL); + } + + Index = 0; + + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (FormTags->Tags == NULL) { + // + // Allocate memory for our tags on the first form + // + FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG)); + ASSERT (FormTags->Tags); + } + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (InconsistentTags == NULL) { + // + // We just hit the end of an inconsistent expression. Let's allocate the ->Next structure + // + InconsistentTags = AllocateZeroPool (sizeof (EFI_INCONSISTENCY_DATA)); + ASSERT (InconsistentTags != NULL); + + FileFormTags->InconsistentTags = InconsistentTags; + } + + ZeroMem (FormTags->Tags, NumberOfTags * sizeof (EFI_TAG)); + + for (CurrTag = 0; RawFormSet[Index] != EFI_IFR_END_FORM_SET_OP; CurrTag++) { + // + // Operand = IFR OpCode + // + FormTags->Tags[CurrTag].Operand = RawFormSet[Index]; + + // + // Assume for now 0 lines occupied by this OpCode + // + FormTags->Tags[CurrTag].NumberOfLines = 0; + + FormTags->Tags[CurrTag].Class = Class; + FormTags->Tags[CurrTag].SubClass = SubClass; + + // + // Determine the length of the Tag so we can later skip to the next tag in the form + // + TagLength = RawFormSet[Index + 1]; + // + // get the length + // + // Operate on the Found OpCode + // + switch (RawFormSet[Index]) { + + case EFI_IFR_FORM_OP: + // + // If there was no variable op-code defined, create a dummy entry for one + // + if (FileFormTags->VariableDefinitions == NULL) { + FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION)); + ASSERT (FileFormTags->VariableDefinitions != NULL); + IfrToFormTag ( + RawFormSet[Index], + &FormTags->Tags[CurrTag], + (VOID *) &RawFormSet[Index], + FileFormTags->VariableDefinitions + ); + } else { + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + } + break; + + case EFI_IFR_SUBTITLE_OP: + case EFI_IFR_TEXT_OP: + case EFI_IFR_REF_OP: + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + break; + + case EFI_IFR_VARSTORE_OP: + if (FileFormTags->VariableDefinitions == NULL) { + VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION)); + ASSERT (VariableDefinitions != NULL); + FileFormTags->VariableDefinitions = VariableDefinitions; + } + + IfrToFormTag ( + RawFormSet[Index], + &FormTags->Tags[CurrTag], + (VOID *) &RawFormSet[Index], + FileFormTags->VariableDefinitions + ); + break; + + case EFI_IFR_VARSTORE_SELECT_OP: + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + CopyMem (&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT *) &RawFormSet[Index])->VarId, sizeof (UINT16)); + CurrentVariable2 = CurrentVariable; + break; + + case EFI_IFR_VARSTORE_SELECT_PAIR_OP: + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + CopyMem(&CurrentVariable, &((EFI_IFR_VARSTORE_SELECT_PAIR *)&RawFormSet[Index])->VarId, sizeof (UINT16)); + CopyMem ( + &CurrentVariable2, + &((EFI_IFR_VARSTORE_SELECT_PAIR *) &RawFormSet[Index])->SecondaryVarId, + sizeof (UINT16) + ); + break; + + case EFI_IFR_END_FORM_OP: + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (FormTags->Next == NULL) { + // + // We just hit the end of a form. Let's allocate the ->Next structure + // + FormTags->Next = AllocatePool (sizeof (EFI_FORM_TAGS)); + ASSERT (FormTags->Next); + } + + FormTags = FormTags->Next; + ZeroMem (FormTags, sizeof (EFI_FORM_TAGS)); + + // + // Reset the tag count to one + // + NumberOfTags = 1; + + // + // Reset the CurrTag value (it will be incremented, after this case statement + // so set to a negative one so that we get the desired effect.) Fish can beat me later. + // + CurrTag = -1; + + // + // Determine the number of tags after this form. If this is the last + // form, then we will count the endformset and preserve that information + // in the tag structure. + // + GetTagCount (&RawFormSet[Index + TagLength], &NumberOfTags); + + // + // Allocate memory for our tags + // + FormTags->Tags = AllocateZeroPool (NumberOfTags * sizeof (EFI_TAG)); + ASSERT (FormTags->Tags); + break; + + // + // Two types of tags constitute the One Of question: a one-of header and + // several one-of options. + // + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_ORDERED_LIST_OP: + GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable); + + // + // Store away the CurrTag since what follows will be the answer that we + // need to place into the appropriate location in the tag array + // + // + // record for setting default later + // + QuestionIndex = (UINT16) CurrTag; + break; + + case EFI_IFR_ONE_OF_OPTION_OP: + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + FormTags->Tags[QuestionIndex].Flags = ((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Flags; + CopyMem ( + &FormTags->Tags[QuestionIndex].Key, + &((EFI_IFR_ONE_OF_OPTION *) &RawFormSet[Index])->Key, + sizeof (UINT16) + ); + FormTags->Tags[QuestionIndex].ResetRequired = (BOOLEAN) (FormTags->Tags[QuestionIndex].Flags & EFI_IFR_FLAG_RESET_REQUIRED); + break; + + case EFI_IFR_CHECKBOX_OP: + GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable); + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + break; + + case EFI_IFR_NUMERIC_OP: + GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable); + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + break; + + case EFI_IFR_DATE_OP: + // + // Date elements come in as a Year, Month, Day. We need to process them as a country-based + // Order. It is much easier to do it here than anywhere else. + // + // For US standards - we want Month/Day/Year, thus we advance "Index" +1, +2, +0 while CurrTag is +0, +1, +2 + // + GetNumericHeader ( + &FormTags->Tags[CurrTag], + RawFormSet, + (UINT16) (Index + TagLength), + (UINT16) 0, + FileFormTags, + CurrentVariable + ); + + // + // The current language selected + the Date operand + // + FormTags->Tags[CurrTag + 1].Operand = RawFormSet[Index]; + GetNumericHeader ( + &FormTags->Tags[CurrTag + 1], + RawFormSet, + (UINT16) (Index + TagLength + RawFormSet[Index + TagLength + 1]), + (UINT16) 0, + FileFormTags, + CurrentVariable + ); + + // + // The current language selected + the Date operand + // + FormTags->Tags[CurrTag + 2].Operand = RawFormSet[Index]; + GetNumericHeader (&FormTags->Tags[CurrTag + 2], RawFormSet, Index, (UINT16) 1, FileFormTags, CurrentVariable); + + CurrTag = (INT16) (CurrTag + 2); + + Index = (UINT16) (Index + TagLength); + // + // get the length + // + TagLength = RawFormSet[Index + 1]; + Index = (UINT16) (Index + TagLength); + // + // get the length + // + TagLength = RawFormSet[Index + 1]; + break; + + case EFI_IFR_TIME_OP: + GetNumericHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, (UINT16) 0, FileFormTags, CurrentVariable); + + if (Count == 2) { + // + // Override the GetQuestionHeader information - date/time are treated very differently + // + FormTags->Tags[CurrTag].NumberOfLines = 1; + Count = 0; + } else { + // + // The premise is that every date/time op-code have 3 elements, the first 2 have 0 lines + // associated with them, and the third has 1 line to allow to space beyond the choice. + // + Count++; + } + break; + + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_STRING_OP: + GetQuestionHeader (&FormTags->Tags[CurrTag], RawFormSet, Index, FileFormTags, CurrentVariable); + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + break; + + case EFI_IFR_SUPPRESS_IF_OP: + case EFI_IFR_GRAYOUT_IF_OP: + InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode; + gConsistencyId++; + + // + // Since this op-code doesn't use the next field(s), initialize them with something invalid. + // Unfortunately 0 is a valid offset value for a QuestionId + // + InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE; + InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE; + + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (InconsistentTags->Next == NULL) { + AddNextInconsistentTag (&InconsistentTags); + break; + } + + InconsistentTags = InconsistentTags->Next; + break; + + case EFI_IFR_FORM_SET_OP: + CopyMem ( + &FormTags->Tags[CurrTag].GuidValue, + &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Guid, + sizeof (EFI_GUID) + ); + CopyMem ( + &FormTags->Tags[CurrTag].CallbackHandle, + &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->CallbackHandle, + sizeof (EFI_PHYSICAL_ADDRESS) + ); + CopyMem (&FormTags->Tags[CurrTag].Class, &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class, sizeof (UINT8)); + CopyMem ( + &FormTags->Tags[CurrTag].SubClass, + &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass, + sizeof (UINT8) + ); + CopyMem ( + &FormTags->Tags[CurrTag].NvDataSize, + &((EFI_IFR_FORM_SET *) &RawFormSet[Index])->NvDataSize, + sizeof (UINT16) + ); + Class = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->Class; + SubClass = ((EFI_IFR_FORM_SET *) &RawFormSet[Index])->SubClass; + // + // If the formset has a size value, that means someone must be using this, so create a variable + // We also shall reserve the formid of 0 for this specific purpose. + // + if ((FileFormTags->VariableDefinitions == NULL) && (FormTags->Tags[CurrTag].NvDataSize > 0)) { + FileFormTags->VariableDefinitions = AllocateZeroPool (sizeof (EFI_VARIABLE_DEFINITION)); + ASSERT (FileFormTags->VariableDefinitions != NULL); + IfrToFormTag ( + RawFormSet[Index], + &FormTags->Tags[CurrTag], + (VOID *) &RawFormSet[Index], + FileFormTags->VariableDefinitions + ); + } else { + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + } + break; + + case EFI_IFR_BANNER_OP: + if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) { + TempValue = 0; + CopyMem (&TempValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment, sizeof (UINT8)); + // + // If this is the special timeout value, we will dynamically figure out where to put it + // Also the least significant byte refers to the TimeOut desired. + // + if (TempValue == EFI_IFR_BANNER_TIMEOUT) { + CopyMem (&FrontPageTimeOutTitle, &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title, sizeof (UINT16)); + if (FrontPageTimeOutValue != (INT16) -1) { + CopyMem (&FrontPageTimeOutValue, &((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber, sizeof (UINT16)); + } + break; + } + + CopyMem ( + &BannerData->Banner[((EFI_IFR_BANNER *) &RawFormSet[Index])->LineNumber][ + ((EFI_IFR_BANNER *) &RawFormSet[Index])->Alignment], + &((EFI_IFR_BANNER *) &RawFormSet[Index])->Title, + sizeof (STRING_REF) + ); + } + break; + + case EFI_IFR_INCONSISTENT_IF_OP: + CopyMem ( + &FormTags->Tags[CurrTag].Text, + &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup, + sizeof (UINT16) + ); + gConsistencyId++; + + InconsistentTags->Operand = ((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Header.OpCode; + CopyMem (&InconsistentTags->Popup, &((EFI_IFR_INCONSISTENT *) &RawFormSet[Index])->Popup, sizeof (UINT16)); + + // + // Since this op-code doesn't use the next field(s), initialize them with something invalid. + // Unfortunately 0 is a valid offset value for a QuestionId + // + InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE; + InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE; + + InconsistentTags->VariableNumber = CurrentVariable; + + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (InconsistentTags->Next == NULL) { + AddNextInconsistentTag (&InconsistentTags); + break; + } + + InconsistentTags = InconsistentTags->Next; + break; + + case EFI_IFR_EQ_ID_VAL_OP: + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + + InconsistentTags->Operand = ((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Header.OpCode; + CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16)); + CopyMem ( + &InconsistentTags->QuestionId1, + &((EFI_IFR_EQ_ID_VAL *) &RawFormSet[Index])->QuestionId, + sizeof (UINT16) + ); + + // + // Since this op-code doesn't use the next field(s), initialize them with something invalid. + // Unfortunately 0 is a valid offset value for a QuestionId + // + InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth; + InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE; + InconsistentTags->ConsistencyId = gConsistencyId; + FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId; + + InconsistentTags->VariableNumber = CurrentVariable; + + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (InconsistentTags->Next == NULL) { + AddNextInconsistentTag (&InconsistentTags); + break; + } + + InconsistentTags = InconsistentTags->Next; + break; + + case EFI_IFR_EQ_VAR_VAL_OP: + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + + InconsistentTags->Operand = ((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Header.OpCode; + CopyMem (&InconsistentTags->Value, &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->Value, sizeof (UINT16)); + CopyMem ( + &InconsistentTags->QuestionId1, + &((EFI_IFR_EQ_VAR_VAL *) &RawFormSet[Index])->VariableId, + sizeof (UINT16) + ); + + // + // Since this op-code doesn't use the next field(s), initialize them with something invalid. + // Unfortunately 0 is a valid offset value for a QuestionId + // + InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE; + InconsistentTags->ConsistencyId = gConsistencyId; + FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId; + + InconsistentTags->VariableNumber = CurrentVariable; + + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (InconsistentTags->Next == NULL) { + AddNextInconsistentTag (&InconsistentTags); + break; + } + + InconsistentTags = InconsistentTags->Next; + break; + + case EFI_IFR_EQ_ID_ID_OP: + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + + InconsistentTags->Operand = ((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->Header.OpCode; + CopyMem ( + &InconsistentTags->QuestionId1, + &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId1, + sizeof (UINT16) + ); + CopyMem ( + &InconsistentTags->QuestionId2, + &((EFI_IFR_EQ_ID_ID *) &RawFormSet[Index])->QuestionId2, + sizeof (UINT16) + ); + + InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth; + InconsistentTags->ConsistencyId = gConsistencyId; + FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId; + + InconsistentTags->VariableNumber = CurrentVariable; + InconsistentTags->VariableNumber2 = CurrentVariable2; + + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (InconsistentTags->Next == NULL) { + AddNextInconsistentTag (&InconsistentTags); + break; + } + + InconsistentTags = InconsistentTags->Next; + break; + + case EFI_IFR_AND_OP: + case EFI_IFR_OR_OP: + case EFI_IFR_NOT_OP: + case EFI_IFR_GT_OP: + case EFI_IFR_GE_OP: + case EFI_IFR_TRUE_OP: + case EFI_IFR_FALSE_OP: + InconsistentTags->Operand = ((EFI_IFR_NOT *) &RawFormSet[Index])->Header.OpCode; + + // + // Since this op-code doesn't use the next field(s), initialize them with something invalid. + // Unfortunately 0 is a valid offset value for a QuestionId + // + + // + // Reserve INVALID_OFFSET_VALUE - 1 for TRUE or FALSE because they are inconsistency tags also, but + // have no coresponding id. The examination of id is needed by evaluating boolean expression. + // + if (RawFormSet[Index] == EFI_IFR_TRUE_OP || + RawFormSet[Index] == EFI_IFR_FALSE_OP) { + InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE - 1; + } else { + InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE; + } + InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE; + InconsistentTags->ConsistencyId = gConsistencyId; + FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId; + + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (InconsistentTags->Next == NULL) { + AddNextInconsistentTag (&InconsistentTags); + break; + } + + InconsistentTags = InconsistentTags->Next; + break; + + case EFI_IFR_EQ_ID_LIST_OP: + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + + InconsistentTags->Operand = ((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->Header.OpCode; + CopyMem ( + &InconsistentTags->QuestionId1, + &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->QuestionId, + sizeof (UINT16) + ); + CopyMem ( + &InconsistentTags->ListLength, + &((EFI_IFR_EQ_ID_LIST *) &RawFormSet[Index])->ListLength, + sizeof (UINT16) + ); + InconsistentTags->ValueList = FormTags->Tags[CurrTag].IntList; + + // + // Since this op-code doesn't use the next field(s), initialize them with something invalid. + // Unfortunately 0 is a valid offset value for a QuestionId + // + InconsistentTags->Width = FormTags->Tags[CurrTag].StorageWidth; + InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE; + InconsistentTags->ConsistencyId = gConsistencyId; + FormTags->Tags[CurrTag].ConsistencyId = gConsistencyId; + + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (InconsistentTags->Next == NULL) { + AddNextInconsistentTag (&InconsistentTags); + break; + } + + InconsistentTags = InconsistentTags->Next; + break; + + case EFI_IFR_END_IF_OP: + InconsistentTags->Operand = ((EFI_IFR_END_EXPR *) &RawFormSet[Index])->Header.OpCode; + + // + // Since this op-code doesn't use the next field(s), initialize them with something invalid. + // Unfortunately 0 is a valid offset value for a QuestionId + // + InconsistentTags->QuestionId1 = INVALID_OFFSET_VALUE; + InconsistentTags->QuestionId2 = INVALID_OFFSET_VALUE; + + // + // Test for an allocated buffer. If already allocated this is due to having called this routine + // once for sizing of the NV storage. We then loaded the NV variable and can correctly initialize + // the tag structure with current values from the NV + // + if (InconsistentTags->Next == NULL) { + AddNextInconsistentTag (&InconsistentTags); + break; + } + + InconsistentTags = InconsistentTags->Next; + break; + + case EFI_IFR_END_ONE_OF_OP: + break; + + default: + break; + } + // + // End of switch + // + // Per spec., we ignore ops that we don't know how to deal with. Skip to next tag + // + Index = (UINT16) (Index + TagLength); + } + // + // End of Index + // + // When we eventually exit, make sure we mark the last tag with an op-code + // + FormTags->Tags[CurrTag].Operand = RawFormSet[Index]; + + IfrToFormTag (RawFormSet[Index], &FormTags->Tags[CurrTag], (VOID *) &RawFormSet[Index], NULL); + + // + // Place this as an end of the database marker + // + InconsistentTags->Operand = 0xFF; + + // + // This is the Head of the linked list of pages. Each page is an array of tags + // + FormTags = &FileFormTags->FormTags; + InconsistentTags = FileFormTags->InconsistentTags; + + for (; InconsistentTags->Operand != 0xFF;) { + if (InconsistentTags->QuestionId1 != INVALID_OFFSET_VALUE) { + // + // Search the tags for the tag which corresponds to this ID + // + for (CurrTag = 0; FormTags->Tags[0].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) { + // + // If we hit the end of a form, go to the next set of Tags. + // Remember - EndFormSet op-codes sit on their own page after an end form. + // + if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) { + // + // Reset the CurrTag value (it will be incremented, after this case statement + // so set to a negative one so that we get the desired effect.) Fish can beat me later. + // + CurrTag = -1; + FormTags = FormTags->Next; + continue; + } + + if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId1) { + FormTags->Tags[CurrTag].Consistency++; + } + } + } + + FormTags = &FileFormTags->FormTags; + + if (InconsistentTags->QuestionId2 != INVALID_OFFSET_VALUE) { + // + // Search the tags for the tag which corresponds to this ID + // + for (CurrTag = 0; FormTags->Tags[CurrTag].Operand != EFI_IFR_END_FORM_SET_OP; CurrTag++) { + // + // If we hit the end of a form, go to the next set of Tags. + // Remember - EndFormSet op-codes sit on their own page after an end form. + // + if (FormTags->Tags[CurrTag].Operand == EFI_IFR_END_FORM_OP) { + // + // Reset the CurrTag value (it will be incremented, after this case statement + // so set to a negative one so that we get the desired effect.) Fish can beat me later. + // + CurrTag = -1; + FormTags = FormTags->Next; + continue; + } + + if (FormTags->Tags[CurrTag].Id == InconsistentTags->QuestionId2) { + FormTags->Tags[CurrTag].Consistency++; + } + } + } + + InconsistentTags = InconsistentTags->Next; + } + + return Status; +} + +VOID +InitPage ( + VOID + ) +{ + CHAR16 *HomePageString; + CHAR16 *HomeEscapeString; + + // + // Displays the Header and Footer borders + // + DisplayPageFrame (); + + HomePageString = GetToken (STRING_TOKEN (HOME_PAGE_TITLE), gHiiHandle); + HomeEscapeString = GetToken (STRING_TOKEN (HOME_ESCAPE_STRING), gHiiHandle); + + gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT); + // + // PrintStringAt ((gScreenDimensions.RightColumn - GetStringWidth(HomePageString)/2)/2, 1, HomePageString); + // + PrintStringAt ( + (gScreenDimensions.RightColumn + gScreenDimensions.LeftColumn - GetStringWidth (HomePageString) / 2) / 2, + 1, + HomePageString + ); + PrintAt ( + gScreenDimensions.LeftColumn + 2, + gScreenDimensions.BottomRow - 3, + (CHAR16 *) L"%c%c%s", + ARROW_UP, + ARROW_DOWN, + gMoveHighlight + ); + PrintAt ( + gScreenDimensions.RightColumn - (GetStringWidth (HomeEscapeString) / 2) - 2, + gScreenDimensions.BottomRow - 3, + (CHAR16 *) L" %s", + HomeEscapeString + ); + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gBS->FreePool (HomeEscapeString); + gBS->FreePool (HomePageString); + + return ; +} + +CHAR16 * +GetToken ( + IN STRING_REF Token, + IN EFI_HII_HANDLE HiiHandle + ) +/*++ + +Routine Description: + + Get the string based on the TokenID and HII Handle. + +Arguments: + + Token - The Token ID. + HiiHandle - Handle of Ifr to be fetched. + +Returns: + + The output string. + +--*/ +{ + CHAR16 *Buffer; + UINTN BufferLength; + EFI_STATUS Status; + + // + // Set default string size assumption at no more than 256 bytes + // + BufferLength = 0x100; + + Buffer = AllocateZeroPool (BufferLength); + ASSERT (Buffer != NULL); + + Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer); + + if (EFI_ERROR (Status)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Free the old pool + // + gBS->FreePool (Buffer); + + // + // Allocate new pool with correct value + // + Buffer = AllocatePool (BufferLength); + ASSERT (Buffer != NULL); + + Status = Hii->GetString (Hii, HiiHandle, Token, TRUE, NULL, &BufferLength, Buffer); + + if (!EFI_ERROR (Status)) { + return Buffer; + } + } + + ASSERT_EFI_ERROR (Status); + } + + return Buffer; +} + +EFI_STATUS +PopulateHomePage ( + IN UINTN NumberOfIfrImages, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_IFR_BINARY *IfrBinary; + CHAR16 *StringPtr; + EFI_FILE_FORM_TAGS *FileFormTags; + EFI_FORM_TAGS LocalTags; + + FileFormTags = FileFormTagsHead; + + UiInitMenu (); + + Status = EFI_SUCCESS; + + // + // If there are no images + // + if (NumberOfIfrImages == 0) { + Status = EFI_NO_MEDIA; + return Status; + } + // + // IfrBinary points to the beginning of the Binary data linked-list + // + IfrBinary = gBinaryDataHead; + + // + // Print the entries which were in the default language. + // + for (Index = 0; Index < NumberOfIfrImages; Index++) { + LocalTags = FileFormTags->FormTags; + + // + // Populate the Menu + // + StringPtr = GetToken (IfrBinary->TitleToken, IfrBinary->Handle); + + // + // If the default language doesn't exist, don't add a menu option yet + // + if (StringPtr[0] != CHAR_NULL) { + // + // We are NOT!! removing this StringPtr buffer via FreePool since it is being used in the menuoptions, we will do + // it in UiFreeMenu. + // + UiAddMenuOption (StringPtr, IfrBinary->Handle, LocalTags.Tags, IfrBinary->FormBinary, Index); + } + // + // Advance to the next HII handle + // + IfrBinary = IfrBinary->Next; + FileFormTags = FileFormTags->NextFile; + } + + return Status; +} + +UI_MENU_OPTION * +DisplayHomePage ( + IN UINTN NumberOfIfrImages, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN UINT8 *CallbackData + ) +{ + EFI_STATUS Status; + UI_MENU_OPTION *Selection; + + // + // This prints the basic home page template which the user sees + // + InitPage (); + + Status = PopulateHomePage (NumberOfIfrImages, FileFormTagsHead); + + if (EFI_ERROR (Status)) { + Selection = NULL; + return Selection; + } + + Selection = UiDisplayMenu (FALSE, FileFormTagsHead, (EFI_IFR_DATA_ARRAY *) CallbackData); + + return Selection; +} + +EFI_STATUS +InitializeBinaryStructures ( + IN EFI_HII_HANDLE *Handle, + IN BOOLEAN UseDatabase, + IN EFI_IFR_PACKET *Packet, + IN UINT8 *NvMapOverride, + IN UINTN NumberOfIfrImages, + OUT EFI_FILE_FORM_TAGS **FileFormTagsHead + ) +{ + UINTN HandleIndex; + EFI_STATUS Status; + EFI_IFR_BINARY *BinaryData; + EFI_FILE_FORM_TAGS *FileFormTags; + UINTN SizeOfNvStore; + EFI_FORM_CALLBACK_PROTOCOL *FormCallback; + EFI_VARIABLE_DEFINITION *VariableDefinition; + EFI_VARIABLE_DEFINITION *OverrideDefinition; + VOID *NvMap; + UINTN NvMapSize; + EFI_HII_VARIABLE_PACK_LIST *NvMapListHead; + EFI_HII_VARIABLE_PACK_LIST *NvMapListNode; + + // + // Initialize some variables to avoid warnings + // + BinaryData = NULL; + *FileFormTagsHead = NULL; + FileFormTags = NULL; + gBinaryDataHead = NULL; + Status = EFI_SUCCESS; + FormCallback = NULL; + NvMap = NULL; + NvMapSize = 0; + + if (NumberOfIfrImages > 1) { + NvMapOverride = NULL; + } + + for (HandleIndex = 0; HandleIndex < NumberOfIfrImages; HandleIndex += 1) { + // + // If the buffers are uninitialized, allocate them, otherwise work on the ->Next members + // + if ((BinaryData == NULL) || (FileFormTags == NULL)) { + // + // Allocate memory for our Binary Data + // + BinaryData = AllocateZeroPool (sizeof (EFI_IFR_BINARY)); + ASSERT (BinaryData); + + // + // Preserve the Head of what will be a linked-list. + // + gBinaryDataHead = BinaryData; + gBinaryDataHead->Next = NULL; + + if (UseDatabase) { + Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData); + } else { + Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData); + } + // + // Allocate memory for our File Form Tags + // + FileFormTags = AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS)); + ASSERT (FileFormTags); + + // + // Preserve the Head of what will be a linked-list. + // + *FileFormTagsHead = FileFormTags; + (*FileFormTagsHead)->NextFile = NULL; + + } else { + // + // Allocate memory for our Binary Data linked-list + // Each handle represents a Binary and we will store that data away. + // + BinaryData->Next = AllocateZeroPool (sizeof (EFI_IFR_BINARY)); + ASSERT (BinaryData->Next); + + BinaryData = BinaryData->Next; + BinaryData->Next = NULL; + + if (UseDatabase) { + Status = GetIfrBinaryData (Hii, Handle[HandleIndex], NULL, BinaryData); + } else { + Status = GetIfrBinaryData (Hii, Handle[HandleIndex], Packet, BinaryData); + } + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + // + // Allocate memory for our FileFormTags linked-list + // Each allocation reserves handle represents a Binary and we will store that data away. + // + FileFormTags->NextFile = AllocateZeroPool (sizeof (EFI_FILE_FORM_TAGS)); + ASSERT (FileFormTags->NextFile); + + FileFormTags = FileFormTags->NextFile; + } + // + // endif + // + // Tag Structure Initialization + // + Status = InitializeTagStructures (BinaryData, FileFormTags); + + VariableDefinition = FileFormTags->VariableDefinitions; + + // + // Allocate memory for our NVRAM Maps for all of our variables + // + for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) { + // + // Pad the fake variable size accordingly - this value should reflect the size of information that is not accounted by + // the mainstream NVRAM variable such as DATE/TIME information that the browser needs to track but is saved to an RTC + // + VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableSize + VariableDefinition->VariableFakeSize); + + // + // In the case where a file has no "real" NV data, we should pad the buffer accordingly + // + if (VariableDefinition->VariableSize == 0) { + if (VariableDefinition->VariableFakeSize != 0) { + VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableFakeSize); + ASSERT (VariableDefinition->NvRamMap != NULL); + } + } else { + VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableSize); + ASSERT (VariableDefinition->NvRamMap != NULL); + } + + if (VariableDefinition->VariableFakeSize != 0) { + VariableDefinition->FakeNvRamMap = AllocateZeroPool (VariableDefinition->VariableFakeSize); + ASSERT (VariableDefinition->FakeNvRamMap != NULL); + } + } + + Status = gBS->HandleProtocol ( + (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle, + &gEfiFormCallbackProtocolGuid, + (VOID **) &FormCallback + ); + + // + // Since we might have multiple variables, if there is an NvMapOverride we need to use the EFI_VARIABLE_DEFINITION + // information as the information that we pass back and forth. NOTE that callbacks that are initiated will only have the + // NVRAM data refreshed based on the op-code that initiated the callback. In other words, we will pass to the caller a single + // NVRAM map for a single variable based on the op-code that the user selected. + // + if (NvMapOverride != NULL) { + VariableDefinition = FileFormTags->VariableDefinitions; + OverrideDefinition = ((EFI_VARIABLE_DEFINITION *) NvMapOverride); + + // + // Search through the variable definitions. There should be sufficient passed in settings for the variable op-codes specified + // + for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) { + if ((!CompareMem (VariableDefinition->VariableName, L"Setup", 10)) && (VariableDefinition->Next == NULL)) { + if (VariableDefinition->VariableSize != 0) { + CopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableSize); + } else { + CopyMem (VariableDefinition->NvRamMap, NvMapOverride, VariableDefinition->VariableFakeSize); + } + break; + } else { + VariableDefinition->NvRamMap = OverrideDefinition->NvRamMap; + } + // + // There should NEVER be a ->Next for VariableDefinition and a NULL ->Next for the OverrideDefinition + // + ASSERT (OverrideDefinition->Next); + OverrideDefinition = OverrideDefinition->Next; + } + } else { + VariableDefinition = FileFormTags->VariableDefinitions; + + // + // Search through the variable definitions. There should be sufficient passed in settings for the variable op-codes specified + // + for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) { + SizeOfNvStore = VariableDefinition->VariableSize; + + // + // Getting the NvStore and placing it into our Global Data + // + if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) { + Status = FormCallback->NvRead ( + FormCallback, + VariableDefinition->VariableName, + &VariableDefinition->Guid, + NULL, + &SizeOfNvStore, + (VOID *) VariableDefinition->NvRamMap + ); + } else { + Status = gRT->GetVariable ( + VariableDefinition->VariableName, + &VariableDefinition->Guid, + NULL, + &SizeOfNvStore, + (VOID *) VariableDefinition->NvRamMap + ); + } + + if (EFI_ERROR (Status)) { + // + // If there is a variable that exists already and it is larger than what we calculated the + // storage needs to be, we must assume the variable size from GetVariable is correct and not + // allow the truncation of the variable. It is very possible that the user who created the IFR + // we are cracking is not referring to a variable that was in a previous map, however we cannot + // allow it's truncation. + // + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // If the buffer was too small, we should have the expanded size requirement in SizeOfNvStore now. + // + VariableDefinition->VariableSize = (UINT16) SizeOfNvStore; + + // + // Free the buffer that was allocated that was too small + // + gBS->FreePool (VariableDefinition->NvRamMap); + gBS->FreePool (VariableDefinition->FakeNvRamMap); + + VariableDefinition->NvRamMap = AllocateZeroPool (SizeOfNvStore); + VariableDefinition->FakeNvRamMap = AllocateZeroPool (SizeOfNvStore + VariableDefinition->VariableFakeSize); + ASSERT (VariableDefinition->NvRamMap); + ASSERT (VariableDefinition->FakeNvRamMap); + + if ((FormCallback != NULL) && (FormCallback->NvRead != NULL)) { + Status = FormCallback->NvRead ( + FormCallback, + VariableDefinition->VariableName, + &VariableDefinition->Guid, + NULL, + &SizeOfNvStore, + (VOID *) VariableDefinition->NvRamMap + ); + } else { + Status = gRT->GetVariable ( + VariableDefinition->VariableName, + &VariableDefinition->Guid, + NULL, + &SizeOfNvStore, + (VOID *) VariableDefinition->NvRamMap + ); + } + } + // + // if the variable was not found, we will retrieve default values + // + if (Status == EFI_NOT_FOUND) { + + if (0 == CompareMem (VariableDefinition->VariableName, L"Setup", 10)) { + + NvMapListHead = NULL; + + Status = Hii->GetDefaultImage (Hii, Handle[HandleIndex], EFI_IFR_FLAG_DEFAULT, &NvMapListHead); + + if (!EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (NULL != NvMapListHead); + + NvMapListNode = NvMapListHead; + + while (NULL != NvMapListNode) { + if (VariableDefinition->VariableId == NvMapListNode->VariablePack->VariableId) { + NvMap = (VOID *) ((CHAR8 *) NvMapListNode->VariablePack + sizeof (EFI_HII_VARIABLE_PACK) + NvMapListNode->VariablePack->VariableNameLength); + NvMapSize = NvMapListNode->VariablePack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - NvMapListNode->VariablePack->VariableNameLength; + break; + } + NvMapListNode = NvMapListNode->NextVariablePack; + } + + // + // Free the buffer that was allocated. + // + gBS->FreePool (VariableDefinition->NvRamMap); + gBS->FreePool (VariableDefinition->FakeNvRamMap); + + // + // Allocate, copy the NvRamMap. + // + VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize - VariableDefinition->VariableSize); + VariableDefinition->VariableSize = (UINT16) NvMapSize; + VariableDefinition->VariableFakeSize = (UINT16) (VariableDefinition->VariableFakeSize + VariableDefinition->VariableSize); + + VariableDefinition->NvRamMap = AllocateZeroPool (VariableDefinition->VariableSize); + VariableDefinition->FakeNvRamMap = AllocateZeroPool (NvMapSize + VariableDefinition->VariableFakeSize); + + CopyMem (VariableDefinition->NvRamMap, NvMap, NvMapSize); + gBS->FreePool (NvMapListHead); + } + + } + Status = EFI_SUCCESS; + } + } + } + } + + InitializeTagStructures (BinaryData, FileFormTags); + } + // + // endfor + // + return Status; +} + +EFI_STATUS +GetIfrBinaryData ( + IN EFI_HII_PROTOCOL *Hii, + IN EFI_HII_HANDLE HiiHandle, + IN EFI_IFR_PACKET *Packet, + IN OUT EFI_IFR_BINARY *BinaryData + ) +/*++ + +Routine Description: + Fetch the Ifr binary data. + +Arguments: + Hii - Point to HII protocol. + HiiHandle - Handle of Ifr to be fetched. + Packet - Pointer to IFR packet. + BinaryData - Buffer to copy the string into + +Returns: + Returns the number of CHAR16 characters that were copied into the OutputString buffer. + + +--*/ +{ + EFI_STATUS Status; + EFI_HII_PACKAGES *PackageList; + UINTN BufferSize; + VOID *Buffer; + UINT8 *RawFormBinary; + EFI_IFR_FORM_SET *FormOp; + UINT16 Index; + UINT16 Index2; + UINT16 TitleToken; + + // + // Initialize the TitleToken to 0 just in case not found + // + TitleToken = 0; + + // + // Try for a 32K Buffer + // + BufferSize = 0x8000; + + // + // Allocate memory for our Form binary + // + Buffer = AllocateZeroPool (BufferSize); + ASSERT (Buffer); + + if (Packet == NULL) { + Status = Hii->GetForms (Hii, HiiHandle, 0, &BufferSize, Buffer); + + if (Status == EFI_BUFFER_TOO_SMALL) { + + gBS->FreePool (Buffer); + + // + // Allocate memory for our Form binary + // + Buffer = AllocatePool (BufferSize); + ASSERT (Buffer); + + Status = Hii->GetForms (Hii, HiiHandle, 0, &BufferSize, Buffer); + } + } else { + // + // Copies the data to local usable buffer + // + CopyMem (Buffer, Packet->IfrData, Packet->IfrData->Header.Length); + + // + // Register the string data with HII + // + PackageList = PreparePackages (2, NULL, Packet->IfrData, Packet->StringData); + + Status = Hii->NewPack (Hii, PackageList, &HiiHandle); + + gBS->FreePool (PackageList); + } + + if (EFI_ERROR (Status)) { + return Status; + } + // + // We now have the IFR binary in our Buffer + // + BinaryData->IfrPackage = Buffer; + RawFormBinary = (UINT8 *) ((CHAR8 *) (Buffer) + sizeof (EFI_HII_PACK_HEADER)); + BinaryData->FormBinary = (UINT8 *) ((CHAR8 *) (Buffer) + sizeof (EFI_HII_PACK_HEADER)); + BinaryData->Handle = HiiHandle; + + // + // If a packet was passed in, remove the string data when exiting. + // + if (Packet != NULL) { + BinaryData->UnRegisterOnExit = TRUE; + } else { + BinaryData->UnRegisterOnExit = FALSE; + } + // + // Walk through the FormSet Opcodes looking for the FormSet opcode + // If we hit EFI_IFR_END_SET_OP we know we hit the end of the FormSet. + // + for (Index = 0; RawFormBinary[Index] != EFI_IFR_END_FORM_SET_OP;) { + FormOp = (EFI_IFR_FORM_SET *) &RawFormBinary[Index]; + Index = (UINT16) (Index + FormOp->Header.Length); + + if (FormOp->Header.OpCode == EFI_IFR_FORM_SET_OP) { + TitleToken = FormOp->FormSetTitle; + // + // If displaying FrontPage - set the flag signifying it + // + switch (FormOp->SubClass) { + case EFI_FRONT_PAGE_SUBCLASS: + FrontPageHandle = HiiHandle; + + default: + gClassOfVfr = FormOp->SubClass; + } + // + // Match GUID to find out the function key setting. If match fail, use the default setting. + // + for (Index2 = 0; Index2 < sizeof (gFunctionKeySettingTable) / sizeof (FUNCTIION_KEY_SETTING); Index2++) { + if (CompareGuid ((EFI_GUID *)(UINTN)&FormOp->Guid, &(gFunctionKeySettingTable[Index2].FormSetGuid))) { + // + // Update the function key setting. + // + gFunctionKeySetting = gFunctionKeySettingTable[Index2].KeySetting; + // + // Function key prompt can not be displayed if the function key has been disabled. + // + if ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE) { + gFunctionOneString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); + } + + if ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO) { + gFunctionTwoString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); + } + + if ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE) { + gFunctionNineString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); + } + + if ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN) { + gFunctionTenString = GetToken (STRING_TOKEN (EMPTY_STRING), gHiiHandle); + } + } + } + } + } + + BinaryData->TitleToken = TitleToken; + + return Status; +} + +EFI_HANDLE PrintHandle = NULL; +EFI_PRINT_PROTOCOL mPrintProtocol = { UnicodeVSPrint }; + +EFI_STATUS +InstallPrint ( + VOID + ) +{ + return gBS->InstallProtocolInterface ( + &PrintHandle, + &gEfiPrintProtocolGuid, + EFI_NATIVE_INTERFACE, + &mPrintProtocol + ); +} diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Setup.h b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Setup.h new file mode 100644 index 0000000000..6089d765ce --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Setup.h @@ -0,0 +1,504 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Setup.h + +Abstract: + + +Revision History + +--*/ + +#ifndef _SETUP_H +#define _SETUP_H + +// +// This is the generated header file which includes whatever needs to be exported (strings + IFR) +// +#include "SetupBrowserStrDefs.h" +extern UINT8 SetupBrowserStrings[]; + +// +// Screen definitions +// +#define BANNER_HEIGHT 4 +#define BANNER_COLUMNS 3 + +#define FRONT_PAGE_HEADER_HEIGHT 4 +#define NONE_FRONT_PAGE_HEADER_HEIGHT 3 +#define LEFT_SKIPPED_COLUMNS 4 +#define FOOTER_HEIGHT 4 +#define STATUS_BAR_HEIGHT 1 +#define SCROLL_ARROW_HEIGHT 1 +#define POPUP_PAD_SPACE_COUNT 5 +#define POPUP_FRAME_WIDTH 2 + + +#define EFI_SETUP_APPLICATION_SUBCLASS 0x00 +#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01 +#define EFI_FRONT_PAGE_SUBCLASS 0x02 +#define EFI_SINGLE_USE_SUBCLASS 0x03 // Used to display a single entity and then exit +// +// Definition for function key setting +// +#define NONE_FUNCTION_KEY_SETTING 0 +#define DEFAULT_FUNCTION_KEY_SETTING (FUNCTION_ONE | FUNCTION_TWO | FUNCTION_NINE | FUNCTION_TEN) + +#define FUNCTION_ONE (1 << 0) +#define FUNCTION_TWO (1 << 1) +#define FUNCTION_NINE (1 << 2) +#define FUNCTION_TEN (1 << 3) + +typedef struct { + EFI_GUID FormSetGuid; + UINTN KeySetting; +} FUNCTIION_KEY_SETTING; + +// +// Character definitions +// +#define CHAR_SPACE 0x0020 +#define UPPER_LOWER_CASE_OFFSET 0x20 + +// +// Time definitions +// +#define ONE_SECOND 10000000 + +// +// Display definitions +// +#define LEFT_HYPER_DELIMITER L'<' +#define RIGHT_HYPER_DELIMITER L'>' + +#define LEFT_ONEOF_DELIMITER L'<' +#define RIGHT_ONEOF_DELIMITER L'>' + +#define LEFT_NUMERIC_DELIMITER L'[' +#define RIGHT_NUMERIC_DELIMITER L']' + +#define LEFT_CHECKBOX_DELIMITER L"[" +#define RIGHT_CHECKBOX_DELIMITER L"]" + +#define CHECK_ON L"X" +#define CHECK_OFF L" " + +#define TIME_SEPARATOR L':' +#define DATE_SEPARATOR L'/' + +#define YES_ANSWER L'Y' +#define NO_ANSWER L'N' + +// +// Up to how many lines does the ordered list display +// +#define ORDERED_LIST_SIZE 4 + +// +// This is the Input Error Message +// +#define INPUT_ERROR 1 + +// +// This is the NV RAM update required Message +// +#define NV_UPDATE_REQUIRED 2 + +// +// Refresh the Status Bar with flags +// +#define REFRESH_STATUS_BAR 0xff + +// +// This width is basically the sum of the prompt and option widths +// +#define QUESTION_BLOCK_WIDTH 50 + +// +// Width of the Language Description (Using ISO-639-2 3 ASCII letter standard) +// +#define LANG_DESC_WIDTH 3 + +// +// Maximum Number of Binaries we can see +// +#define MAX_BINARIES 255 + +// +// Invalid Handle +// +#define EFI_HII_INVALID_HANDLE 0xFFFF + +// +// Invalid Offset Value +// +#define INVALID_OFFSET_VALUE 0xFFFF + +struct StringPart { + struct StringPart *Next; + CHAR8 String[QUESTION_BLOCK_WIDTH + 2]; +}; + +// +// The tag definition defines the data associated with a tag (an operation +// in the IFR lingo). The tag is thus a modified union of all the data +// required for tags. The user should be careful to only rely upon information +// relevant to that tag as the contents of other fields is undefined. +// +// The intent here is for this to be all of the data associated with a particular tag. +// Some of this data is extracted from the IFR and left alone. Other data will be derived +// when the page is selected (since that's the first time we really know what language the +// page is to be displayed in) and still other data will vary based on the selection. +// If you'd like to consider alternatives, let me know. This structure has grown somewhat organically. +// It gets a new item stuffed in it when a new item is needed. When I finally decided I needed the +// StringPart structure, items got added here, for example. +// +typedef struct { + UINT8 Operand; // The operand (first byte) of the variable length tag. + EFI_GUID GuidValue; // Primarily for FormSet data + EFI_PHYSICAL_ADDRESS CallbackHandle; + UINT16 Class; + UINT16 SubClass; + UINT16 NumberOfLines; // The number of lines the tag takes up on the page. Adjusted when we display the page as it can change from language to language. + UINT16 PageLine; + UINT16 PageColumn; + UINT16 OptionWidth; // The option can be wider than the column usually associated with options. This is the width on the last option line + STRING_REF Text; // Used for title, subtitle, prompt, etc. This is the string token associated with the string. This token is language independent. + STRING_REF TextTwo; // Used for title, subtitle, prompt, etc. This is the string token associated with the string. This token is language independent. + STRING_REF Help; // Null means no help Same as above but for languages. + UINT16 Consistency; // Do we need to check this opcode against consistency? If > 0, yes. + UINT16 Id; + UINT16 Id2; // The questions (mainly) have identifiers associated with them. These are filled in from the IFR tags and used by e.g. the RPN calculations. (com1 is set to, versus com2 is set to) + // + // These are the three values that are created to determine where in the variable the data is stored. This should, in general, + // be allocated by the build tool. The one major issue is, once storage is allocated for something, it can't be reallocated or we will get a mess. + // + UINT16 StorageStart; + // + // These are the three values that are created to determine where in the variable the data is stored. This should, in general, + // be allocated by the build tool. The one major issue is, once storage is allocated for something, it can't be reallocated or we will get a mess. + // + UINT8 StorageWidth; + // + // These are the three values that are created to determine where in the variable the data is stored. This should, in general, + // be allocated by the build tool. The one major issue is, once storage is allocated for something, it can't be reallocated or we will get a mess. + // + UINT16 Value; + // + // (Default or current) + // + UINT8 Flags; + UINT16 Key; + // + // Used to preserve a value during late consistency checking + // + UINT16 OldValue; + UINT16 Minimum; + UINT16 Maximum; + UINT16 Step; + UINT16 Default; + UINT16 NvDataSize; + UINT16 ConsistencyId; + BOOLEAN GrayOut; + BOOLEAN Suppress; + UINT16 Encoding; // Data from the tags. The first three are used by the numeric input. Encoding is used by the password stuff (a placeholder today - may go away). + UINT16 *IntList; // List of the values possible for a list question + // + // The string is obtained from the string list and formatted into lines and the lines are held in this linked list. + // If we have more than a screen's worth of items, we will end up with cases where we have to display the last couple + // lines of a tag's string above the currently selected one, or, display a few lines of a tag at the bottom of a screen. + // + struct StringPart *StringList; + BOOLEAN ResetRequired; // Primarily used to determine if a reset is required by changing this op-code. + UINT16 VariableNumber; // Used to define which variable the StorageStart will be pertinent for (0-based) For single variable VFR this will always be 0. + // + // Used to define which variable the StorageStart will be pertinent for (0-based) This is used for boolean check of ID versus ID + // so that a user can compare the value of one variable.field content versus another variable.field content. + // + UINT16 VariableNumber2; +} EFI_TAG; + +#define EFI_FORM_DATA_SIGNATURE EFI_SIGNATURE_32 ('F', 'o', 'r', 'm') + +typedef struct { + UINTN Signature; + + EFI_HII_PROTOCOL *Hii; + EFI_FORM_BROWSER_PROTOCOL FormConfig; +} EFI_FORM_CONFIGURATION_DATA; + +#define EFI_FORM_DATA_FROM_THIS(a) CR (a, EFI_FORM_CONFIGURATION_DATA, FormConfig, EFI_FORM_DATA_SIGNATURE) + +typedef struct _EFI_VARIABLE_DEFINITION { + CHAR8 *NvRamMap; + CHAR8 *FakeNvRamMap; // This is where the storage for NULL devices go (e.g. RTC) + EFI_GUID Guid; + UINT16 VariableId; + UINT16 VariableSize; + UINT16 VariableFakeSize; // For dynamically created and NULL device options, this is the latest size + CHAR16 *VariableName; + struct _EFI_VARIABLE_DEFINITION *Next; + struct _EFI_VARIABLE_DEFINITION *Previous; +} EFI_VARIABLE_DEFINITION; + +typedef struct { + UINT32 Length; // Length in bytes between beginning of struc and end of Strings + CHAR8 LanguageCode[4]; // ISO-639-2 language code with a null-terminator + RELOFST PrintableLanguageName; // Translated name of the Language, "English"/"Espanol" etc + UINT32 Attributes; // If on, the language is intended to be printed right to left. The default (off) is to print left to right. + RELOFST StringsPointers[1]; // Pointing to string offset from beginning of String Binary + EFI_STRING Strings[1]; // Array of String Entries. Note the number of entries for Strings and StringsPointers will be the same +} EFI_LANGUAGE_SET; + +// +// This encapsulates all the pointers associated with found IFR binaries +// +typedef struct _EFI_IFR_BINARY { + struct _EFI_IFR_BINARY *Next; + VOID *IfrPackage; // Handy for use in freeing the data later since this is the header of the buffer + VOID *FormBinary; + EFI_HII_HANDLE Handle; + STRING_REF TitleToken; + BOOLEAN UnRegisterOnExit; +} EFI_IFR_BINARY; + +// +// This encapsulates all the questions (tags) for a particular Form Set +// +typedef struct _EFI_FORM_TAGS { + struct _EFI_FORM_TAGS *Next; + EFI_TAG *Tags; +} EFI_FORM_TAGS; + +// +// This is the database of all inconsistency data. Each op-code associated +// with inconsistency will be tracked here. This optimizes the search requirement +// since we will back mark the main tag structure with the op-codes that have reference +// to inconsistency data. This way when parsing the main tag structure and encountering +// the inconsistency mark - we can search this database to know what the inconsistency +// parameters are for that entry. +// +typedef struct _EFI_INCONSISTENCY_DATA { + struct _EFI_INCONSISTENCY_DATA *Next; + struct _EFI_INCONSISTENCY_DATA *Previous; + UINT8 Operand; + STRING_REF Popup; + UINT16 QuestionId1; + UINT16 QuestionId2; + UINT16 Value; + UINT16 ListLength; + UINT16 ConsistencyId; + UINT16 *ValueList; + UINT16 VariableNumber; + UINT16 VariableNumber2; + UINT8 Width; +} EFI_INCONSISTENCY_DATA; + +// +// Encapsulating all found Tag information from all sources +// Each encapsulation also contains the NvRamMap buffer and the Size of the NV store +// +typedef struct _EFI_FILE_FORM_TAGS { + struct _EFI_FILE_FORM_TAGS *NextFile; + EFI_INCONSISTENCY_DATA *InconsistentTags; + EFI_VARIABLE_DEFINITION *VariableDefinitions; + EFI_FORM_TAGS FormTags; +} EFI_FILE_FORM_TAGS; + +typedef struct { + STRING_REF Banner[BANNER_HEIGHT][BANNER_COLUMNS]; +} BANNER_DATA; + +// +// Head of the Binary structures +// +EFI_IFR_BINARY *gBinaryDataHead; + +// +// The IFR binary that the user chose to run +// +UINTN gActiveIfr; + +EFI_HII_PROTOCOL *Hii; + +VOID *CachedNVEntry; +BANNER_DATA *BannerData; +EFI_HII_HANDLE FrontPageHandle; +STRING_REF FrontPageTimeOutTitle; +INT16 FrontPageTimeOutValue; +UINTN gClassOfVfr; +UINTN gFunctionKeySetting; +BOOLEAN gResetRequired; +BOOLEAN gExitRequired; +BOOLEAN gSaveRequired; +BOOLEAN gNvUpdateRequired; +UINT16 gConsistencyId; +UINTN gPriorMenuEntry; +EFI_HII_HANDLE gHiiHandle; +BOOLEAN gFirstIn; +VOID *gPreviousValue; +UINT16 gDirection; +EFI_SCREEN_DESCRIPTOR gScreenDimensions; +BOOLEAN gUpArrow; +BOOLEAN gDownArrow; +BOOLEAN gTimeOnScreen; +BOOLEAN gDateOnScreen; + +// +// Browser Global Strings +// +CHAR16 *gFunctionOneString; +CHAR16 *gFunctionTwoString; +CHAR16 *gFunctionNineString; +CHAR16 *gFunctionTenString; +CHAR16 *gEnterString; +CHAR16 *gEnterCommitString; +CHAR16 *gEscapeString; +CHAR16 *gMoveHighlight; +CHAR16 *gMakeSelection; +CHAR16 *gNumericInput; +CHAR16 *gToggleCheckBox; +CHAR16 *gPromptForPassword; +CHAR16 *gPromptForNewPassword; +CHAR16 *gConfirmPassword; +CHAR16 *gConfirmError; +CHAR16 *gPressEnter; +CHAR16 *gEmptyString; +CHAR16 *gAreYouSure; +CHAR16 *gYesResponse; +CHAR16 *gNoResponse; +CHAR16 *gMiniString; +CHAR16 *gPlusString; +CHAR16 *gMinusString; +CHAR16 *gAdjustNumber; + +CHAR16 gPromptBlockWidth; +CHAR16 gOptionBlockWidth; +CHAR16 gHelpBlockWidth; + +// +// Global Procedure Defines +// +VOID +InitializeBrowserStrings ( + VOID + ) +; + +UINTN +Print ( + IN CHAR16 *fmt, + ... + ) +; + +UINTN +PrintString ( + CHAR16 *String + ) +; + +UINTN +PrintChar ( + CHAR16 Character + ) +; + +UINTN +PrintAt ( + IN UINTN Column, + IN UINTN Row, + IN CHAR16 *fmt, + ... + ) +; + +UINTN +PrintStringAt ( + IN UINTN Column, + IN UINTN Row, + CHAR16 *String + ) +; + +UINTN +PrintCharAt ( + IN UINTN Column, + IN UINTN Row, + CHAR16 Character + ) +; + +VOID +DisplayPageFrame ( + VOID + ) +; + +CHAR16 * +GetToken ( + IN STRING_REF IfrBinaryTitle, + IN EFI_HII_HANDLE HiiHandle + ) +; + +VOID +GetTagCount ( + IN UINT8 *RawFormSet, + IN OUT UINT16 *NumberOfTags + ) +; + +VOID +GetNumericHeader ( + IN EFI_TAG *Tag, + IN UINT8 *RawFormSet, + IN UINT16 Index, + IN UINT16 NumberOfLines, + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UINT16 CurrentVariable + ) +; + +VOID +GetQuestionHeader ( + IN EFI_TAG *Tag, + IN UINT8 *RawFormSet, + IN UINT16 Index, + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UINT16 CurrentVariable + ) +; + +VOID +CreateSharedPopUp ( + IN UINTN RequestedWidth, + IN UINTN NumberOfLines, + IN CHAR16 **ArrayOfStrings + ) +; + +EFI_STATUS +CreateDialog ( + IN UINTN NumberOfLines, + IN BOOLEAN HotKey, + IN UINTN MaximumStringSize, + OUT CHAR16 *StringBuffer, + OUT EFI_INPUT_KEY *KeyValue, + IN CHAR16 *String, + ... + ) +; + +#endif diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/SetupBrowser.mbd b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/SetupBrowser.mbd new file mode 100644 index 0000000000..6a3eec14b1 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/SetupBrowser.mbd @@ -0,0 +1,43 @@ + + + + + SetupBrowser + EBf342FE-B1D3-4EF8-957C-8048606FF670 + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseLib + BaseDebugLibNull + BaseMemoryLib + BasePrintLib + UefiDriverEntryPoint + DxeMemoryAllocationLib + EdkGraphicsLib + DxeReportStatusCodeLib + HiiLib + + diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/SetupBrowser.msa b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/SetupBrowser.msa new file mode 100644 index 0000000000..c0e40a3993 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/SetupBrowser.msa @@ -0,0 +1,82 @@ + + + + + SetupBrowser + DXE_DRIVER + BS_DRIVER + EBf342FE-B1D3-4EF8-957C-8048606FF670 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + BaseLib + DebugLib + BaseMemoryLib + MemoryAllocationLib + UefiDriverEntryPoint + EdkIfrSupportLib + PrintLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + HiiLib + EdkGraphicsLib + + + SetupBrowserStr.uni + Setup.c + Setup.h + Boolean.c + InputHandler.c + Print.c + Print.h + Presentation.c + ProcessOptions.c + Ui.c + Ui.h + + + MdePkg + EdkModulePkg + + + Hii + FormCallback + FormBrowser + Print + + + + + EFI_EVENT_TIMER + + + + + + InitializeSetup + + + diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/SetupBrowserStr.uni b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/SetupBrowserStr.uni new file mode 100644 index 0000000000..1dfd9247a3 Binary files /dev/null and b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/SetupBrowserStr.uni differ diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Ui.c b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Ui.c new file mode 100644 index 0000000000..0d512fd34e --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Ui.c @@ -0,0 +1,3143 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Ui.c + +Abstract: + + Implementation for UI. + +Revision History + +--*/ + +#include "Setup.h" +#include "Ui.h" +#include "Colors.h" + +// +// Implementation +// +VOID +SetUnicodeMem ( + IN VOID *Buffer, + IN UINTN Size, + IN CHAR16 Value + ) +/*++ + +Routine Description: + + Set Buffer to Value for Size bytes. + +Arguments: + + Buffer - Memory to set. + + Size - Number of bytes to set + + Value - Value of the set operation. + +Returns: + + None + +--*/ +{ + CHAR16 *Ptr; + + Ptr = Buffer; + while (Size--) { + *(Ptr++) = Value; + } +} + +VOID +UiInitMenu ( + VOID + ) +/*++ + +Routine Description: + Initialize Menu option list. + +Arguments: + +Returns: + +--*/ +{ + InitializeListHead (&Menu); +} + +VOID +UiInitMenuList ( + VOID + ) +/*++ + +Routine Description: + Initialize Menu option list. + +Arguments: + +Returns: + +--*/ +{ + InitializeListHead (&gMenuList); +} + +VOID +UiRemoveMenuListEntry ( + IN UI_MENU_OPTION *Selection, + OUT UI_MENU_OPTION **PreviousSelection + ) +/*++ + +Routine Description: + Remove Menu option list. + +Arguments: + +Returns: + +--*/ +{ + UI_MENU_LIST *UiMenuList; + + *PreviousSelection = AllocateZeroPool (sizeof (UI_MENU_OPTION)); + ASSERT (*PreviousSelection != NULL); + + if (!IsListEmpty (&gMenuList)) { + UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE); + (*PreviousSelection)->IfrNumber = UiMenuList->Selection.IfrNumber; + (*PreviousSelection)->FormId = UiMenuList->Selection.FormId; + (*PreviousSelection)->Tags = UiMenuList->Selection.Tags; + (*PreviousSelection)->ThisTag = UiMenuList->Selection.ThisTag; + (*PreviousSelection)->Handle = UiMenuList->Selection.Handle; + gEntryNumber = UiMenuList->FormerEntryNumber; + RemoveEntryList (&UiMenuList->MenuLink); + gBS->FreePool (UiMenuList); + } +} + +VOID +UiFreeMenuList ( + VOID + ) +/*++ + +Routine Description: + Free Menu option linked list. + +Arguments: + +Returns: + +--*/ +{ + UI_MENU_LIST *UiMenuList; + + while (!IsListEmpty (&gMenuList)) { + UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE); + RemoveEntryList (&UiMenuList->MenuLink); + gBS->FreePool (UiMenuList); + } +} + +VOID +UiAddMenuListEntry ( + IN UI_MENU_OPTION *Selection + ) +/*++ + +Routine Description: + Add one menu entry to the linked lst + +Arguments: + +Returns: + +--*/ +{ + UI_MENU_LIST *UiMenuList; + + UiMenuList = AllocateZeroPool (sizeof (UI_MENU_LIST)); + ASSERT (UiMenuList != NULL); + + UiMenuList->Signature = UI_MENU_LIST_SIGNATURE; + CopyMem (&UiMenuList->Selection, Selection, sizeof (UI_MENU_OPTION)); + + InsertHeadList (&gMenuList, &UiMenuList->MenuLink); +} + +VOID +UiFreeMenu ( + VOID + ) +/*++ + +Routine Description: + Free Menu option linked list. + +Arguments: + +Returns: + +--*/ +{ + UI_MENU_OPTION *MenuOption; + + while (!IsListEmpty (&Menu)) { + MenuOption = CR (Menu.ForwardLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + RemoveEntryList (&MenuOption->Link); + + // + // We allocated space for this description when we did a GetToken, free it here + // + gBS->FreePool (MenuOption->Description); + gBS->FreePool (MenuOption); + } +} + +VOID +UpdateDateAndTime ( + VOID + ) +/*++ + +Routine Description: + Refresh screen with current date and/or time based on screen context + +Arguments: + +Returns: + +--*/ +{ + CHAR16 *OptionString; + MENU_REFRESH_ENTRY *MenuRefreshEntry; + UINTN Index; + UINTN Loop; + + OptionString = NULL; + + if (gMenuRefreshHead != NULL) { + + MenuRefreshEntry = gMenuRefreshHead; + + do { + gST->ConOut->SetAttribute (gST->ConOut, MenuRefreshEntry->CurrentAttribute); + ProcessOptions (MenuRefreshEntry->MenuOption, FALSE, MenuRefreshEntry->FileFormTagsHead, NULL, &OptionString); + + if (OptionString != NULL) { + // + // If leading spaces on OptionString - remove the spaces + // + for (Index = 0; OptionString[Index] == L' '; Index++) + ; + + for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) { + OptionString[Loop] = OptionString[Index]; + Loop++; + } + + OptionString[Loop] = CHAR_NULL; + + PrintStringAt (MenuRefreshEntry->CurrentColumn, MenuRefreshEntry->CurrentRow, OptionString); + } + + MenuRefreshEntry = MenuRefreshEntry->Next; + + } while (MenuRefreshEntry != NULL); + } + + if (OptionString != NULL) { + gBS->FreePool (OptionString); + } +} + +EFI_STATUS +UiWaitForSingleEvent ( + IN EFI_EVENT Event, + IN UINT64 Timeout OPTIONAL + ) +/*++ + +Routine Description: + Wait for a given event to fire, or for an optional timeout to expire. + +Arguments: + Event - The event to wait for + + Timeout - An optional timeout value in 100 ns units. + +Returns: + + EFI_SUCCESS - Event fired before Timeout expired. + EFI_TIME_OUT - Timout expired before Event fired. + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_EVENT TimerEvent; + EFI_EVENT WaitList[2]; + + if (Timeout) { + // + // Create a timer event + // + Status = gBS->CreateEvent (EFI_EVENT_TIMER, 0, NULL, NULL, &TimerEvent); + if (!EFI_ERROR (Status)) { + // + // Set the timer event + // + gBS->SetTimer ( + TimerEvent, + TimerRelative, + Timeout + ); + + // + // Wait for the original event or the timer + // + WaitList[0] = Event; + WaitList[1] = TimerEvent; + Status = gBS->WaitForEvent (2, WaitList, &Index); + gBS->CloseEvent (TimerEvent); + + // + // If the timer expired, change the return to timed out + // + if (!EFI_ERROR (Status) && Index == 1) { + Status = EFI_TIMEOUT; + } + } + } else { + // + // Update screen every second + // + Timeout = ONE_SECOND; + + do { + Status = gBS->CreateEvent (EFI_EVENT_TIMER, 0, NULL, NULL, &TimerEvent); + + // + // Set the timer event + // + gBS->SetTimer ( + TimerEvent, + TimerRelative, + Timeout + ); + + // + // Wait for the original event or the timer + // + WaitList[0] = Event; + WaitList[1] = TimerEvent; + Status = gBS->WaitForEvent (2, WaitList, &Index); + + // + // If the timer expired, update anything that needs a refresh and keep waiting + // + if (!EFI_ERROR (Status) && Index == 1) { + Status = EFI_TIMEOUT; + UpdateDateAndTime (); + } + + gBS->CloseEvent (TimerEvent); + } while (Status == EFI_TIMEOUT); + } + + return Status; +} + +VOID +UiAddMenuOption ( + IN CHAR16 *String, + IN EFI_HII_HANDLE Handle, + IN EFI_TAG *Tags, + IN VOID *FormBinary, + IN UINTN IfrNumber + ) +/*++ + +Routine Description: + Add one menu option by specified description and context. + +Arguments: + String - String description for this option. + Context - Context data for entry. + +Returns: + +--*/ +{ + UI_MENU_OPTION *MenuOption; + + MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION)); + ASSERT (MenuOption); + + MenuOption->Signature = UI_MENU_OPTION_SIGNATURE; + MenuOption->Description = String; + MenuOption->Handle = Handle; + MenuOption->FormBinary = FormBinary; + MenuOption->IfrNumber = IfrNumber; + MenuOption->Skip = 1; + MenuOption->Tags = Tags; + MenuOption->TagIndex = 0; + MenuOption->ThisTag = &(MenuOption->Tags[MenuOption->TagIndex]); + MenuOption->EntryNumber = (UINT16) IfrNumber; + + InsertTailList (&Menu, &MenuOption->Link); +} + +VOID +UiAddSubMenuOption ( + IN CHAR16 *String, + IN EFI_HII_HANDLE Handle, + IN EFI_TAG *Tags, + IN UINTN TagIndex, + IN UINT16 FormId, + IN UINT16 MenuItemCount + ) +/*++ + +Routine Description: + Add one menu option by specified description and context. + +Arguments: + String - String description for this option. + Context - Context data for entry. + +Returns: + +--*/ +{ + UI_MENU_OPTION *MenuOption; + + MenuOption = AllocateZeroPool (sizeof (UI_MENU_OPTION)); + ASSERT (MenuOption); + + MenuOption->Signature = UI_MENU_OPTION_SIGNATURE; + MenuOption->Description = String; + MenuOption->Handle = Handle; + MenuOption->Skip = Tags[TagIndex].NumberOfLines; + MenuOption->IfrNumber = gActiveIfr; + MenuOption->Tags = Tags; + MenuOption->TagIndex = TagIndex; + MenuOption->ThisTag = &(MenuOption->Tags[MenuOption->TagIndex]); + MenuOption->Consistency = Tags[TagIndex].Consistency; + MenuOption->FormId = FormId; + MenuOption->GrayOut = Tags[TagIndex].GrayOut; + MenuOption->EntryNumber = MenuItemCount; + + InsertTailList (&Menu, &MenuOption->Link); +} + +EFI_STATUS +CreateDialog ( + IN UINTN NumberOfLines, + IN BOOLEAN HotKey, + IN UINTN MaximumStringSize, + OUT CHAR16 *StringBuffer, + OUT EFI_INPUT_KEY *KeyValue, + IN CHAR16 *String, + ... + ) +/*++ + +Routine Description: + Routine used to abstract a generic dialog interface and return the selected key or string + +Arguments: + NumberOfLines - The number of lines for the dialog box + HotKey - Defines whether a single character is parsed (TRUE) and returned in KeyValue + or a string is returned in StringBuffer. Two special characters are considered when entering a string, a SCAN_ESC and + an CHAR_CARRIAGE_RETURN. SCAN_ESC terminates string input and returns + MaximumStringSize - The maximum size in bytes of a typed in string (each character is a CHAR16) and the minimum string returned is two bytes + StringBuffer - The passed in pointer to the buffer which will hold the typed in string if HotKey is FALSE + KeyValue - The EFI_KEY value returned if HotKey is TRUE.. + String - Pointer to the first string in the list + ... - A series of (quantity == NumberOfLines) text strings which will be used to construct the dialog box + +Returns: + EFI_SUCCESS - Displayed dialog and received user interaction + EFI_INVALID_PARAMETER - One of the parameters was invalid (e.g. (StringBuffer == NULL) && (HotKey == FALSE)) + EFI_DEVICE_ERROR - User typed in an ESC character to exit the routine + +--*/ +{ + VA_LIST Marker; + UINTN Count; + EFI_INPUT_KEY Key; + UINTN LargestString; + CHAR16 *TempString; + CHAR16 *BufferedString; + CHAR16 *StackString; + CHAR16 KeyPad[2]; + UINTN Start; + UINTN Top; + UINTN Index; + EFI_STATUS Status; + BOOLEAN SelectionComplete; + UINTN InputOffset; + UINTN CurrentAttribute; + UINTN DimensionsWidth; + UINTN DimensionsHeight; + + DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; + DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; + + SelectionComplete = FALSE; + InputOffset = 0; + TempString = AllocateZeroPool (MaximumStringSize * 2); + BufferedString = AllocateZeroPool (MaximumStringSize * 2); + CurrentAttribute = gST->ConOut->Mode->Attribute; + + ASSERT (TempString); + ASSERT (BufferedString); + + VA_START (Marker, String); + + // + // Zero the outgoing buffer + // + ZeroMem (StringBuffer, MaximumStringSize); + + if (HotKey) { + if (KeyValue == NULL) { + return EFI_INVALID_PARAMETER; + } + } else { + if (StringBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + } + // + // Disable cursor + // + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + LargestString = (GetStringWidth (String) / 2); + + if (LargestString == L' ') { + InputOffset = 1; + } + // + // Determine the largest string in the dialog box + // Notice we are starting with 1 since String is the first string + // + for (Count = 1; Count < NumberOfLines; Count++) { + StackString = VA_ARG (Marker, CHAR16 *); + + if (StackString[0] == L' ') { + InputOffset = Count + 1; + } + + if ((GetStringWidth (StackString) / 2) > LargestString) { + // + // Size of the string visually and subtract the width by one for the null-terminator + // + LargestString = (GetStringWidth (StackString) / 2); + } + } + + Start = (DimensionsWidth - LargestString - 2) / 2 + gScreenDimensions.LeftColumn + 1; + Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1; + + Count = 0; + + // + // Display the Popup + // + CreateSharedPopUp (LargestString, NumberOfLines, &String); + + // + // Take the first key typed and report it back? + // + if (HotKey) { + Status = WaitForKeyStroke (&Key); + CopyMem (KeyValue, &Key, sizeof (EFI_INPUT_KEY)); + + } else { + do { + Status = WaitForKeyStroke (&Key); + + switch (Key.UnicodeChar) { + case CHAR_NULL: + switch (Key.ScanCode) { + case SCAN_ESC: + gBS->FreePool (TempString); + gBS->FreePool (BufferedString); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_DEVICE_ERROR; + + default: + break; + } + + break; + + case CHAR_CARRIAGE_RETURN: + SelectionComplete = TRUE; + gBS->FreePool (TempString); + gBS->FreePool (BufferedString); + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_SUCCESS; + break; + + case CHAR_BACKSPACE: + if (StringBuffer[0] != CHAR_NULL) { + for (Index = 0; StringBuffer[Index] != CHAR_NULL; Index++) { + TempString[Index] = StringBuffer[Index]; + } + // + // Effectively truncate string by 1 character + // + TempString[Index - 1] = CHAR_NULL; + StrCpy (StringBuffer, TempString); + } + + default: + // + // If it is the beginning of the string, don't worry about checking maximum limits + // + if ((StringBuffer[0] == CHAR_NULL) && (Key.UnicodeChar != CHAR_BACKSPACE)) { + StrnCpy (StringBuffer, &Key.UnicodeChar, 1); + StrnCpy (TempString, &Key.UnicodeChar, 1); + } else if ((GetStringWidth (StringBuffer) < MaximumStringSize) && (Key.UnicodeChar != CHAR_BACKSPACE)) { + KeyPad[0] = Key.UnicodeChar; + KeyPad[1] = CHAR_NULL; + StrCat (StringBuffer, KeyPad); + StrCat (TempString, KeyPad); + } + // + // If the width of the input string is now larger than the screen, we nee to + // adjust the index to start printing portions of the string + // + SetUnicodeMem (BufferedString, LargestString, L' '); + + PrintStringAt (Start + 1, Top + InputOffset, BufferedString); + + if ((GetStringWidth (StringBuffer) / 2) > (DimensionsWidth - 2)) { + Index = (GetStringWidth (StringBuffer) / 2) - DimensionsWidth + 2; + } else { + Index = 0; + } + + for (Count = 0; Index + 1 < GetStringWidth (StringBuffer) / 2; Index++, Count++) { + BufferedString[Count] = StringBuffer[Index]; + } + + PrintStringAt (Start + 1, Top + InputOffset, BufferedString); + break; + } + } while (!SelectionComplete); + } + + gST->ConOut->SetAttribute (gST->ConOut, CurrentAttribute); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + return EFI_SUCCESS; +} + +VOID +CreateSharedPopUp ( + IN UINTN RequestedWidth, + IN UINTN NumberOfLines, + IN CHAR16 **ArrayOfStrings + ) +{ + UINTN Index; + UINTN Count; + CHAR16 Character; + UINTN Start; + UINTN End; + UINTN Top; + UINTN Bottom; + CHAR16 *String; + + UINTN DimensionsWidth; + UINTN DimensionsHeight; + + DimensionsWidth = gScreenDimensions.RightColumn - gScreenDimensions.LeftColumn; + DimensionsHeight = gScreenDimensions.BottomRow - gScreenDimensions.TopRow; + + Count = 0; + + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + + if ((RequestedWidth + 2) > DimensionsWidth) { + RequestedWidth = DimensionsWidth - 2; + } + // + // Subtract the PopUp width from total Columns, allow for one space extra on + // each end plus a border. + // + Start = (DimensionsWidth - RequestedWidth - 2) / 2 + gScreenDimensions.LeftColumn + 1; + End = Start + RequestedWidth + 1; + + Top = ((DimensionsHeight - NumberOfLines - 2) / 2) + gScreenDimensions.TopRow - 1; + Bottom = Top + NumberOfLines + 2; + + Character = (CHAR16) BOXDRAW_DOWN_RIGHT; + PrintCharAt (Start, Top, Character); + Character = (CHAR16) BOXDRAW_HORIZONTAL; + for (Index = Start; Index + 2 < End; Index++) { + PrintChar (Character); + } + + Character = (CHAR16) BOXDRAW_DOWN_LEFT; + PrintChar (Character); + Character = (CHAR16) BOXDRAW_VERTICAL; + for (Index = Top; Index + 2 < Bottom; Index++) { + String = ArrayOfStrings[Count]; + Count++; + + // + // This will clear the background of the line - we never know who might have been + // here before us. This differs from the next clear in that it used the non-reverse + // video for normal printing. + // + if (GetStringWidth (String) / 2 > 1) { + ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND); + } + // + // Passing in a space results in the assumption that this is where typing will occur + // + if (String[0] == L' ') { + ClearLines (Start + 1, End - 1, Index + 1, Index + 1, POPUP_INVERSE_TEXT | POPUP_INVERSE_BACKGROUND); + } + // + // Passing in a NULL results in a blank space + // + if (String[0] == CHAR_NULL) { + ClearLines (Start, End, Index + 1, Index + 1, POPUP_TEXT | POPUP_BACKGROUND); + } + + PrintStringAt ( + ((DimensionsWidth - GetStringWidth (String) / 2) / 2) + gScreenDimensions.LeftColumn + 1, + Index + 1, + String + ); + gST->ConOut->SetAttribute (gST->ConOut, POPUP_TEXT | POPUP_BACKGROUND); + PrintCharAt (Start, Index + 1, Character); + PrintCharAt (End - 1, Index + 1, Character); + } + + Character = (CHAR16) BOXDRAW_UP_RIGHT; + PrintCharAt (Start, Bottom - 1, Character); + Character = (CHAR16) BOXDRAW_HORIZONTAL; + for (Index = Start; Index + 2 < End; Index++) { + PrintChar (Character); + } + + Character = (CHAR16) BOXDRAW_UP_LEFT; + PrintChar (Character); +} + +VOID +CreatePopUp ( + IN UINTN RequestedWidth, + IN UINTN NumberOfLines, + IN CHAR16 *ArrayOfStrings, + ... + ) +{ + CreateSharedPopUp (RequestedWidth, NumberOfLines, &ArrayOfStrings); +} + +VOID +UpdateStatusBar ( + IN UINTN MessageType, + IN UINT8 Flags, + IN BOOLEAN State + ) +{ + UINTN Index; + STATIC BOOLEAN InputError; + CHAR16 *NvUpdateMessage; + CHAR16 *InputErrorMessage; + + NvUpdateMessage = GetToken (STRING_TOKEN (NV_UPDATE_MESSAGE), gHiiHandle); + InputErrorMessage = GetToken (STRING_TOKEN (INPUT_ERROR_MESSAGE), gHiiHandle); + + switch (MessageType) { + case INPUT_ERROR: + if (State) { + gST->ConOut->SetAttribute (gST->ConOut, ERROR_TEXT); + PrintStringAt ( + gScreenDimensions.LeftColumn + gPromptBlockWidth, + gScreenDimensions.BottomRow - 1, + InputErrorMessage + ); + InputError = TRUE; + } else { + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT); + for (Index = 0; Index < (GetStringWidth (InputErrorMessage) - 2) / 2; Index++) { + PrintAt (gScreenDimensions.LeftColumn + gPromptBlockWidth + Index, gScreenDimensions.BottomRow - 1, (CHAR16 *) L" "); + } + + InputError = FALSE; + } + break; + + case NV_UPDATE_REQUIRED: + if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) { + if (State) { + gST->ConOut->SetAttribute (gST->ConOut, INFO_TEXT); + PrintStringAt ( + gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth, + gScreenDimensions.BottomRow - 1, + NvUpdateMessage + ); + gResetRequired = (BOOLEAN) (gResetRequired | (Flags & RESET_REQUIRED)); + + gNvUpdateRequired = TRUE; + } else { + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT); + for (Index = 0; Index < (GetStringWidth (NvUpdateMessage) - 2) / 2; Index++) { + PrintAt ( + (gScreenDimensions.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + Index), + gScreenDimensions.BottomRow - 1, + (CHAR16 *) L" " + ); + } + + gNvUpdateRequired = FALSE; + } + } + break; + + case REFRESH_STATUS_BAR: + if (InputError) { + UpdateStatusBar (INPUT_ERROR, Flags, TRUE); + } + + if (gNvUpdateRequired) { + UpdateStatusBar (NV_UPDATE_REQUIRED, Flags, TRUE); + } + break; + + default: + break; + } + + gBS->FreePool (InputErrorMessage); + gBS->FreePool (NvUpdateMessage); + return ; +} + +VOID +FreeData ( + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN CHAR16 *FormattedString, + IN CHAR16 *OptionString + ) +/*++ + +Routine Description: + + Used to remove the allocated data instances + +Arguments: + +Returns: + +--*/ +{ + EFI_FILE_FORM_TAGS *FileForm; + EFI_FILE_FORM_TAGS *PreviousFileForm; + EFI_FORM_TAGS *FormTags; + EFI_FORM_TAGS *PreviousFormTags; + EFI_IFR_BINARY *IfrBinary; + EFI_IFR_BINARY *PreviousIfrBinary; + EFI_INCONSISTENCY_DATA *Inconsistent; + EFI_VARIABLE_DEFINITION *VariableDefinition; + EFI_VARIABLE_DEFINITION *PreviousVariableDefinition; + VOID *Buffer; + UINTN Index; + + FileForm = FileFormTagsHead; + + if (FormattedString != NULL) { + gBS->FreePool (FormattedString); + } + + if (OptionString != NULL) { + gBS->FreePool (OptionString); + } + + for (; FileForm != NULL;) { + PreviousFileForm = NULL; + + // + // Advance FileForm to the last entry + // + for (; FileForm->NextFile != NULL; FileForm = FileForm->NextFile) { + PreviousFileForm = FileForm; + } + + FormTags = &FileForm->FormTags; + + for (; FormTags != NULL;) { + FormTags = &FileForm->FormTags; + PreviousFormTags = NULL; + + // + // Advance FormTags to the last entry + // + for (; FormTags->Next != NULL; FormTags = FormTags->Next) { + PreviousFormTags = FormTags; + } + // + // Walk through each of the tags and free the IntList allocation + // + for (Index = 0; FormTags->Tags[Index].Operand != EFI_IFR_END_FORM_OP; Index++) { + // + // It is more than likely that the very last page will contain an end formset + // + if (FormTags->Tags[Index].Operand == EFI_IFR_END_FORM_SET_OP) { + break; + } + + if (FormTags->Tags[Index].IntList != NULL) { + gBS->FreePool (FormTags->Tags[Index].IntList); + } + } + + if (PreviousFormTags != NULL) { + gBS->FreePool (FormTags->Tags); + FormTags = PreviousFormTags; + gBS->FreePool (FormTags->Next); + FormTags->Next = NULL; + } else { + gBS->FreePool (FormTags->Tags); + FormTags = NULL; + } + } + // + // Last FileForm entry's Inconsistent database + // + Inconsistent = FileForm->InconsistentTags; + + // + // Advance Inconsistent to the last entry + // + for (; Inconsistent->Next != NULL; Inconsistent = Inconsistent->Next) + ; + + for (; Inconsistent != NULL;) { + // + // Preserve the Previous pointer + // + Buffer = (VOID *) Inconsistent->Previous; + + // + // Free the current entry + // + gBS->FreePool (Inconsistent); + + // + // Restore the Previous pointer + // + Inconsistent = (EFI_INCONSISTENCY_DATA *) Buffer; + } + + VariableDefinition = FileForm->VariableDefinitions; + + for (; VariableDefinition != NULL;) { + VariableDefinition = FileForm->VariableDefinitions; + PreviousVariableDefinition = NULL; + + // + // Advance VariableDefinitions to the last entry + // + for (; VariableDefinition->Next != NULL; VariableDefinition = VariableDefinition->Next) { + PreviousVariableDefinition = VariableDefinition; + } + + gBS->FreePool (VariableDefinition->VariableName); + gBS->FreePool (VariableDefinition->NvRamMap); + gBS->FreePool (VariableDefinition->FakeNvRamMap); + + if (PreviousVariableDefinition != NULL) { + VariableDefinition = PreviousVariableDefinition; + gBS->FreePool (VariableDefinition->Next); + VariableDefinition->Next = NULL; + } else { + gBS->FreePool (VariableDefinition); + VariableDefinition = NULL; + } + } + + if (PreviousFileForm != NULL) { + FileForm = PreviousFileForm; + gBS->FreePool (FileForm->NextFile); + FileForm->NextFile = NULL; + } else { + gBS->FreePool (FileForm); + FileForm = NULL; + } + } + + IfrBinary = gBinaryDataHead; + + for (; IfrBinary != NULL;) { + IfrBinary = gBinaryDataHead; + PreviousIfrBinary = NULL; + + // + // Advance IfrBinary to the last entry + // + for (; IfrBinary->Next != NULL; IfrBinary = IfrBinary->Next) { + PreviousIfrBinary = IfrBinary; + } + + gBS->FreePool (IfrBinary->IfrPackage); + + if (PreviousIfrBinary != NULL) { + IfrBinary = PreviousIfrBinary; + gBS->FreePool (IfrBinary->Next); + IfrBinary->Next = NULL; + } else { + gBS->FreePool (IfrBinary); + IfrBinary = NULL; + } + } + + gBS->FreePool (gPreviousValue); + gPreviousValue = NULL; + + // + // Free Browser Strings + // + gBS->FreePool (gPressEnter); + gBS->FreePool (gConfirmError); + gBS->FreePool (gConfirmPassword); + gBS->FreePool (gPromptForNewPassword); + gBS->FreePool (gPromptForPassword); + gBS->FreePool (gToggleCheckBox); + gBS->FreePool (gNumericInput); + gBS->FreePool (gMakeSelection); + gBS->FreePool (gMoveHighlight); + gBS->FreePool (gEscapeString); + gBS->FreePool (gEnterCommitString); + gBS->FreePool (gEnterString); + gBS->FreePool (gFunctionOneString); + gBS->FreePool (gFunctionTwoString); + gBS->FreePool (gFunctionNineString); + gBS->FreePool (gFunctionTenString); + return ; +} + +BOOLEAN +SelectionsAreValid ( + IN UI_MENU_OPTION *MenuOption, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead + ) +/*++ + +Routine Description: + Initiate late consistency checks against the current page. + +Arguments: + None + +Returns: + +--*/ +{ + LIST_ENTRY *Link; + EFI_TAG *Tag; + EFI_FILE_FORM_TAGS *FileFormTags; + CHAR16 *StringPtr; + CHAR16 NullCharacter; + EFI_STATUS Status; + UINTN Index; + UINT16 *NvRamMap; + STRING_REF PopUp; + EFI_INPUT_KEY Key; + EFI_VARIABLE_DEFINITION *VariableDefinition; + + StringPtr = (CHAR16 *) L"\0"; + NullCharacter = CHAR_NULL; + + FileFormTags = FileFormTagsHead; + + for (Index = 0; Index < MenuOption->IfrNumber; Index++) { + FileFormTags = FileFormTags->NextFile; + } + + for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) { + MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + + Tag = MenuOption->ThisTag; + + ExtractRequestedNvMap (FileFormTags, Tag->VariableNumber, &VariableDefinition); + NvRamMap = (UINT16 *) &VariableDefinition->NvRamMap[Tag->StorageStart]; + + // + // If the op-code has a late check, ensure consistency checks are now applied + // + if (Tag->Flags & EFI_IFR_FLAG_LATE_CHECK) { + if (ValueIsNotValid (TRUE, 0, Tag, FileFormTags, &PopUp)) { + if (PopUp != 0x0000) { + StringPtr = GetToken (PopUp, MenuOption->Handle); + + CreatePopUp (GetStringWidth (StringPtr) / 2, 3, &NullCharacter, StringPtr, &NullCharacter); + + do { + Status = WaitForKeyStroke (&Key); + + switch (Key.UnicodeChar) { + + case CHAR_CARRIAGE_RETURN: + // + // Since the value can be one byte long or two bytes long, do a CopyMem based on StorageWidth + // + CopyMem (NvRamMap, &Tag->OldValue, Tag->StorageWidth); + gBS->FreePool (StringPtr); + break; + + default: + break; + } + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + } + + return FALSE; + } + } + } + + return TRUE; +} + +UINT16 +GetWidth ( + IN EFI_TAG *Tag, + IN EFI_HII_HANDLE Handle + ) +/*++ + +Routine Description: + Get the supported width for a particular op-code + +Arguments: + Tag - The Tag structure passed in. + Handle - The handle in the HII database being used + +Returns: + Returns the number of CHAR16 characters that is support. + + +--*/ +{ + CHAR16 *String; + UINTN Size; + + Size = 0x00; + + // + // See if the second text parameter is really NULL + // + if ((Tag->Operand == EFI_IFR_TEXT_OP) && (Tag->TextTwo != 0)) { + String = GetToken (Tag->TextTwo, Handle); + Size = StrLen (String); + gBS->FreePool (String); + } + + if ((Tag->Operand == EFI_IFR_SUBTITLE_OP) || + (Tag->Operand == EFI_IFR_REF_OP) || + (Tag->Operand == EFI_IFR_PASSWORD_OP) || + (Tag->Operand == EFI_IFR_STRING_OP) || + (Tag->Operand == EFI_IFR_INVENTORY_OP) || + // + // Allow a wide display if text op-code and no secondary text op-code + // + ((Tag->Operand == EFI_IFR_TEXT_OP) && (Size == 0x0000)) + ) { + return (UINT16) (gPromptBlockWidth + gOptionBlockWidth); + } else { + return (UINT16) gPromptBlockWidth; + } +} + +UINT16 +GetLineByWidth ( + IN CHAR16 *InputString, + IN UINT16 LineWidth, + IN OUT UINTN *Index, + OUT CHAR16 **OutputString + ) +/*++ + +Routine Description: + Will copy LineWidth amount of a string in the OutputString buffer and return the + number of CHAR16 characters that were copied into the OutputString buffer. + +Arguments: + InputString - String description for this option. + LineWidth - Width of the desired string to extract in CHAR16 characters + Index - Where in InputString to start the copy process + OutputString - Buffer to copy the string into + +Returns: + Returns the number of CHAR16 characters that were copied into the OutputString buffer. + + +--*/ +{ + static BOOLEAN Finished; + UINT16 Count; + UINT16 Count2; + + if (Finished) { + Finished = FALSE; + return (UINT16) 0; + } + + Count = LineWidth; + Count2 = 0; + + *OutputString = AllocateZeroPool (((UINTN) (LineWidth + 1) * 2)); + + // + // Ensure we have got a valid buffer + // + if (*OutputString != NULL) { + // + // Fast-forward the string and see if there is a carriage-return in the string + // + for (; (InputString[*Index + Count2] != CHAR_CARRIAGE_RETURN) && (Count2 != LineWidth); Count2++) + ; + + // + // Copy the desired LineWidth of data to the output buffer. + // Also make sure that we don't copy more than the string. + // Also make sure that if there are linefeeds, we account for them. + // + if ((StrSize (&InputString[*Index]) <= ((UINTN) (LineWidth + 1) * 2)) && + (StrSize (&InputString[*Index]) <= ((UINTN) (Count2 + 1) * 2)) + ) { + // + // Convert to CHAR16 value and show that we are done with this operation + // + LineWidth = (UINT16) ((StrSize (&InputString[*Index]) - 2) / 2); + if (LineWidth != 0) { + Finished = TRUE; + } + } else { + if (Count2 == LineWidth) { + // + // Rewind the string from the maximum size until we see a space to break the line + // + for (; (InputString[*Index + LineWidth] != CHAR_SPACE) && (LineWidth != 0); LineWidth--) + ; + if (LineWidth == 0) { + LineWidth = Count; + } + } else { + LineWidth = Count2; + } + } + + CopyMem (*OutputString, &InputString[*Index], LineWidth * 2); + + // + // If currently pointing to a space, increment the index to the first non-space character + // + for (; + (InputString[*Index + LineWidth] == CHAR_SPACE) || (InputString[*Index + LineWidth] == CHAR_CARRIAGE_RETURN); + (*Index)++ + ) + ; + *Index = (UINT16) (*Index + LineWidth); + return LineWidth; + } else { + return (UINT16) 0; + } +} + +VOID +UpdateOptionSkipLines ( + IN EFI_IFR_DATA_ARRAY *PageData, + IN UI_MENU_OPTION *MenuOption, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN CHAR16 **OptionalString, + IN UINTN SkipValue + ) +{ + UINTN Index; + UINTN Loop; + UINT16 Width; + UINTN Row; + UINTN OriginalRow; + CHAR16 *OutputString; + CHAR16 *OptionString; + + Row = 0; + OptionString = *OptionalString; + OutputString = NULL; + + ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString); + + if (OptionString != NULL) { + // + // If leading spaces on OptionString - remove the spaces + // + for (Index = 0; OptionString[Index] == L' '; Index++) + ; + + for (Loop = 0; OptionString[Index] != CHAR_NULL; Index++) { + OptionString[Loop] = OptionString[Index]; + Loop++; + } + + OptionString[Loop] = CHAR_NULL; + + Width = (UINT16) gOptionBlockWidth; + + OriginalRow = Row; + + for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&OptionString[Index])) { + if (SkipValue == 0) { + Row++; + // + // Since the Number of lines for this menu entry may or may not be reflected accurately + // since the prompt might be 1 lines and option might be many, and vice versa, we need to do + // some testing to ensure we are keeping this in-sync. + // + // If the difference in rows is greater than or equal to the skip value, increase the skip value + // + if ((Row - OriginalRow) >= MenuOption->Skip) { + MenuOption->Skip++; + } + } + } + + gBS->FreePool (OutputString); + if (SkipValue != 0) { + SkipValue--; + } + } + + Row = OriginalRow; + } + + *OptionalString = OptionString; +} +// +// Search table for UiDisplayMenu() +// +SCAN_CODE_TO_SCREEN_OPERATION gScanCodeToOperation[] = { + { SCAN_UP, UiUp }, + { SCAN_DOWN, UiDown }, + { SCAN_PAGE_UP, UiPageUp }, + { SCAN_PAGE_DOWN, UiPageDown}, + { SCAN_ESC, UiReset}, + { SCAN_F2, UiPrevious}, + { SCAN_LEFT, UiLeft }, + { SCAN_RIGHT, UiRight }, + { SCAN_F9, UiDefault}, + { SCAN_F10, UiSave } +}; + +SCREEN_OPERATION_T0_CONTROL_FLAG gScreenOperationToControlFlag[] = { + { UiNoOperation, CfUiNoOperation }, + { UiDefault, CfUiDefault }, + { UiSelect, CfUiSelect }, + { UiUp, CfUiUp}, + { UiDown, CfUiDown }, + { UiLeft, CfUiLeft }, + { UiRight, CfUiRight }, + { UiReset, CfUiReset }, + { UiSave, CfUiSave }, + { UiPrevious, CfUiPrevious }, + { UiPageUp, CfUiPageUp }, + { UiPageDown, CfUiPageDown } +}; + +UI_MENU_OPTION * +UiDisplayMenu ( + IN BOOLEAN SubMenu, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + OUT EFI_IFR_DATA_ARRAY *PageData + ) +/*++ + +Routine Description: + Display menu and wait for user to select one menu option, then return it. + If AutoBoot is enabled, then if user doesn't select any option, + after period of time, it will automatically return the first menu option. + +Arguments: + SubMenu - Indicate is sub menu. + FileFormTagsHead - A pointer to the EFI_FILE_FORM_TAGS structure. + PageData - A pointer to the EFI_IFR_DATA_ARRAY. + +Returns: + Return the pointer of the menu which selected, + otherwise return NULL. + +--*/ +{ + INTN SkipValue; + INTN Difference; + INTN OldSkipValue; + UINTN Row; + UINTN Col; + UINTN Temp; + UINTN Temp2; + UINTN TopRow; + UINTN BottomRow; + UINTN OriginalRow; + UINTN Index; + UINTN DataAndTimeLineNumberPad; + UINT32 Count; + INT16 OriginalTimeOut; + UINT8 *Location; + UINT16 Width; + CHAR16 *StringPtr; + CHAR16 *OptionString; + CHAR16 *OutputString; + CHAR16 *FormattedString; + CHAR16 YesResponse; + CHAR16 NoResponse; + BOOLEAN NewLine; + BOOLEAN Repaint; + BOOLEAN SavedValue; + EFI_STATUS Status; + UI_MENU_LIST *UiMenuList; + EFI_INPUT_KEY Key; + LIST_ENTRY *Link; + LIST_ENTRY *NewPos; + LIST_ENTRY *TopOfScreen; + LIST_ENTRY *SavedListEntry; + UI_MENU_OPTION *Selection; + UI_MENU_OPTION *MenuOption; + UI_MENU_OPTION *NextMenuOption; + UI_MENU_OPTION *SavedMenuOption; + UI_MENU_OPTION *PreviousMenuOption; + EFI_IFR_BINARY *IfrBinary; + UI_CONTROL_FLAG ControlFlag; + EFI_SCREEN_DESCRIPTOR LocalScreen; + EFI_FILE_FORM_TAGS *FileFormTags; + MENU_REFRESH_ENTRY *MenuRefreshEntry; + MENU_REFRESH_ENTRY *OldMenuRefreshEntry; + UI_SCREEN_OPERATION ScreenOperation; + EFI_VARIABLE_DEFINITION *VariableDefinition; + EFI_FORM_CALLBACK_PROTOCOL *FormCallback; + EFI_HII_VARIABLE_PACK_LIST *NvMapListHead; + EFI_HII_VARIABLE_PACK_LIST *NvMapListNode; + VOID *NvMap; + UINTN NvMapSize; + + CopyMem (&LocalScreen, &gScreenDimensions, sizeof (EFI_SCREEN_DESCRIPTOR)); + + VariableDefinition = NULL; + Status = EFI_SUCCESS; + FormattedString = NULL; + OptionString = NULL; + ScreenOperation = UiNoOperation; + NewLine = TRUE; + FormCallback = NULL; + FileFormTags = NULL; + OutputString = NULL; + gUpArrow = FALSE; + gDownArrow = FALSE; + SkipValue = 0; + OldSkipValue = 0; + MenuRefreshEntry = gMenuRefreshHead; + OldMenuRefreshEntry = gMenuRefreshHead; + NextMenuOption = NULL; + PreviousMenuOption = NULL; + SavedMenuOption = NULL; + IfrBinary = NULL; + NvMap = NULL; + NvMapSize = 0; + + ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); + + if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) { + TopRow = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; + Row = LocalScreen.TopRow + FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; + } else { + TopRow = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; + Row = LocalScreen.TopRow + NONE_FRONT_PAGE_HEADER_HEIGHT + SCROLL_ARROW_HEIGHT; + } + + if (SubMenu) { + Col = LocalScreen.LeftColumn; + } else { + Col = LocalScreen.LeftColumn + LEFT_SKIPPED_COLUMNS; + } + + BottomRow = LocalScreen.BottomRow - STATUS_BAR_HEIGHT - FOOTER_HEIGHT - SCROLL_ARROW_HEIGHT - 1; + + TopOfScreen = Menu.ForwardLink; + Repaint = TRUE; + MenuOption = NULL; + + // + // Get user's selection + // + Selection = NULL; + NewPos = Menu.ForwardLink; + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + UpdateStatusBar (REFRESH_STATUS_BAR, (UINT8) 0, TRUE); + + ControlFlag = CfInitialization; + + while (TRUE) { + switch (ControlFlag) { + case CfInitialization: + ControlFlag = CfCheckSelection; + if (gExitRequired) { + ScreenOperation = UiReset; + ControlFlag = CfScreenOperation; + } else if (gSaveRequired) { + ScreenOperation = UiSave; + ControlFlag = CfScreenOperation; + } else if (IsListEmpty (&Menu)) { + ControlFlag = CfReadKey; + } + break; + + case CfCheckSelection: + if (Selection != NULL) { + ControlFlag = CfExit; + } else { + ControlFlag = CfRepaint; + } + + FileFormTags = FileFormTagsHead; + break; + + case CfRepaint: + ControlFlag = CfRefreshHighLight; + + if (Repaint) { + // + // Display menu + // + SavedMenuOption = MenuOption; + gDownArrow = FALSE; + gUpArrow = FALSE; + Row = TopRow; + + Temp = SkipValue; + Temp2 = SkipValue; + + ClearLines ( + LocalScreen.LeftColumn, + LocalScreen.RightColumn, + TopRow - SCROLL_ARROW_HEIGHT, + BottomRow + SCROLL_ARROW_HEIGHT, + FIELD_TEXT | FIELD_BACKGROUND + ); + + while (gMenuRefreshHead != NULL) { + OldMenuRefreshEntry = gMenuRefreshHead->Next; + + gBS->FreePool (gMenuRefreshHead); + + gMenuRefreshHead = OldMenuRefreshEntry; + } + + for (Link = TopOfScreen; Link != &Menu; Link = Link->ForwardLink) { + MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + MenuOption->Row = Row; + OriginalRow = Row; + MenuOption->Col = Col; + MenuOption->OptCol = gPromptBlockWidth + 1 + LocalScreen.LeftColumn; + + if (SubMenu) { + if (MenuOption->ThisTag->GrayOut) { + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND); + } else { + if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) { + gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND); + } + } + + Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle); + + OriginalRow = Row; + + for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) { + if ((Temp == 0) && (Row <= BottomRow)) { + PrintStringAt (Col, Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&MenuOption->Description[Index])) { + if (Temp == 0) { + Row++; + } + } + + gBS->FreePool (OutputString); + if (Temp != 0) { + Temp--; + } + } + + Temp = 0; + + Row = OriginalRow; + + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString); + + if (OptionString != NULL) { + // + // If leading spaces on OptionString - remove the spaces + // + for (Index = 0; OptionString[Index] == L' '; Index++) { + MenuOption->OptCol++; + } + + for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) { + OptionString[Count] = OptionString[Index]; + Count++; + } + + OptionString[Count] = CHAR_NULL; + + // + // If this is a date or time op-code and is used to reflect an RTC, register the op-code + // + if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP || + MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP) && + (MenuOption->ThisTag->StorageStart >= FileFormTags->FormTags.Tags[0].NvDataSize)) { + + if (gMenuRefreshHead == NULL) { + MenuRefreshEntry = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY)); + ASSERT (MenuRefreshEntry != NULL); + MenuRefreshEntry->MenuOption = MenuOption; + MenuRefreshEntry->FileFormTagsHead = FileFormTagsHead; + MenuRefreshEntry->CurrentColumn = MenuOption->OptCol; + MenuRefreshEntry->CurrentRow = MenuOption->Row; + MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND; + gMenuRefreshHead = MenuRefreshEntry; + } else { + // + // Advance to the last entry + // + for (MenuRefreshEntry = gMenuRefreshHead; + MenuRefreshEntry->Next != NULL; + MenuRefreshEntry = MenuRefreshEntry->Next + ) + ; + MenuRefreshEntry->Next = AllocateZeroPool (sizeof (MENU_REFRESH_ENTRY)); + ASSERT (MenuRefreshEntry->Next != NULL); + MenuRefreshEntry = MenuRefreshEntry->Next; + MenuRefreshEntry->MenuOption = MenuOption; + MenuRefreshEntry->FileFormTagsHead = FileFormTagsHead; + MenuRefreshEntry->CurrentColumn = MenuOption->OptCol; + MenuRefreshEntry->CurrentRow = MenuOption->Row; + MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND; + } + } + + Width = (UINT16) gOptionBlockWidth; + + OriginalRow = Row; + + for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { + if ((Temp2 == 0) && (Row <= BottomRow)) { + PrintStringAt (MenuOption->OptCol, Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&OptionString[Index])) { + if (Temp2 == 0) { + Row++; + // + // Since the Number of lines for this menu entry may or may not be reflected accurately + // since the prompt might be 1 lines and option might be many, and vice versa, we need to do + // some testing to ensure we are keeping this in-sync. + // + // If the difference in rows is greater than or equal to the skip value, increase the skip value + // + if ((Row - OriginalRow) >= MenuOption->Skip) { + MenuOption->Skip++; + } + } + } + + gBS->FreePool (OutputString); + if (Temp2 != 0) { + Temp2--; + } + } + + Temp2 = 0; + Row = OriginalRow; + } + // + // If this is a text op with secondary text information + // + if ((MenuOption->ThisTag->Operand == EFI_IFR_TEXT_OP) && (MenuOption->ThisTag->TextTwo != 0)) { + StringPtr = GetToken (MenuOption->ThisTag->TextTwo, MenuOption->Handle); + + Width = (UINT16) gOptionBlockWidth; + + OriginalRow = Row; + + for (Index = 0; GetLineByWidth (StringPtr, Width, &Index, &OutputString) != 0x0000;) { + if ((Temp == 0) && (Row <= BottomRow)) { + PrintStringAt (MenuOption->OptCol, Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&StringPtr[Index])) { + if (Temp2 == 0) { + Row++; + // + // Since the Number of lines for this menu entry may or may not be reflected accurately + // since the prompt might be 1 lines and option might be many, and vice versa, we need to do + // some testing to ensure we are keeping this in-sync. + // + // If the difference in rows is greater than or equal to the skip value, increase the skip value + // + if ((Row - OriginalRow) >= MenuOption->Skip) { + MenuOption->Skip++; + } + } + } + + gBS->FreePool (OutputString); + if (Temp2 != 0) { + Temp2--; + } + } + + Row = OriginalRow; + gBS->FreePool (StringPtr); + } + } else { + // + // For now, assume left-justified 72 width max setup entries + // + PrintStringAt (Col, Row, MenuOption->Description); + } + // + // Tracker 6210 - need to handle the bottom of the display + // + if (MenuOption->Skip > 1) { + Row += MenuOption->Skip - SkipValue; + SkipValue = 0; + } else { + Row += MenuOption->Skip; + } + + if (Row > BottomRow) { + if (!ValueIsScroll (FALSE, Link)) { + gDownArrow = TRUE; + } + + Row = BottomRow + 1; + break; + } + } + + if (!ValueIsScroll (TRUE, TopOfScreen)) { + gUpArrow = TRUE; + } + + if (gUpArrow) { + gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND); + PrintAt ( + LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1, + TopRow - SCROLL_ARROW_HEIGHT, + (CHAR16 *) L"%c", + ARROW_UP + ); + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + } + + if (gDownArrow) { + gST->ConOut->SetAttribute (gST->ConOut, ARROW_TEXT | ARROW_BACKGROUND); + PrintAt ( + LocalScreen.LeftColumn + gPromptBlockWidth + gOptionBlockWidth + 1, + BottomRow + SCROLL_ARROW_HEIGHT, + (CHAR16 *) L"%c", + ARROW_DOWN + ); + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + } + + if (SavedMenuOption != NULL) { + MenuOption = SavedMenuOption; + } + } + break; + + case CfRefreshHighLight: + ControlFlag = CfUpdateHelpString; + // + // Repaint flag is normally reset when finish processing CfUpdateHelpString. Temporarily + // reset Repaint flag because we may break halfway and skip CfUpdateHelpString processing. + // + SavedValue = Repaint; + Repaint = FALSE; + + if (NewPos != NULL) { + gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); + if (SubMenu) { + if (gLastOpr && (gEntryNumber != -1)) { + MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + if (gEntryNumber != MenuOption->EntryNumber) { + ScreenOperation = UiDown; + ControlFlag = CfScreenOperation; + break; + } else { + gLastOpr = FALSE; + } + } + + ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString); + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + if (OptionString != NULL) { + // + // If leading spaces on OptionString - remove the spaces + // + for (Index = 0; OptionString[Index] == L' '; Index++) + ; + + for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) { + OptionString[Count] = OptionString[Index]; + Count++; + } + + OptionString[Count] = CHAR_NULL; + + Width = (UINT16) gOptionBlockWidth; + + OriginalRow = MenuOption->Row; + + for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { + if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { + PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&OptionString[Index])) { + MenuOption->Row++; + } + + gBS->FreePool (OutputString); + } + + MenuOption->Row = OriginalRow; + } else { + if (NewLine) { + if (MenuOption->ThisTag->GrayOut) { + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_GRAYED | FIELD_BACKGROUND); + } else { + if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP) { + gST->ConOut->SetAttribute (gST->ConOut, SUBTITLE_TEXT | FIELD_BACKGROUND); + } + } + + OriginalRow = MenuOption->Row; + Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle); + + for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) { + if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { + PrintStringAt (Col, MenuOption->Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&MenuOption->Description[Index])) { + MenuOption->Row++; + } + + gBS->FreePool (OutputString); + } + + MenuOption->Row = OriginalRow; + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + } + } + } else { + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + gST->ConOut->OutputString (gST->ConOut, MenuOption->Description); + } + + MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + + if ((gPriorMenuEntry != 0) && (MenuOption->EntryNumber != gPriorMenuEntry) && (NewPos->ForwardLink != &Menu)) { + ScreenOperation = UiDown; + ControlFlag = CfScreenOperation; + break; + } else { + gPriorMenuEntry = 0; + } + // + // This is only possible if we entered this page and the first menu option is + // a "non-menu" item. In that case, force it UiDown + // + if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) { + // + // If we previously hit an UP command and we are still sitting on a text operation + // we must continue going up + // + if (ScreenOperation == UiUp) { + ControlFlag = CfScreenOperation; + break; + } else { + ScreenOperation = UiDown; + ControlFlag = CfScreenOperation; + break; + } + } + // + // Set reverse attribute + // + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT); + gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); + + // + // Assuming that we have a refresh linked-list created, lets annotate the + // appropriate entry that we are highlighting with its new attribute. Just prior to this + // lets reset all of the entries' attribute so we do not get multiple highlights in he refresh + // + if (gMenuRefreshHead != NULL) { + for (MenuRefreshEntry = gMenuRefreshHead; MenuRefreshEntry != NULL; MenuRefreshEntry = MenuRefreshEntry->Next) { + MenuRefreshEntry->CurrentAttribute = FIELD_TEXT | FIELD_BACKGROUND; + if (MenuRefreshEntry->MenuOption == MenuOption) { + MenuRefreshEntry->CurrentAttribute = FIELD_TEXT_HIGHLIGHT | FIELD_BACKGROUND_HIGHLIGHT; + } + } + } + + if (SubMenu) { + ProcessOptions (MenuOption, FALSE, FileFormTagsHead, PageData, &OptionString); + if (OptionString != NULL) { + // + // If leading spaces on OptionString - remove the spaces + // + for (Index = 0; OptionString[Index] == L' '; Index++) + ; + + for (Count = 0; OptionString[Index] != CHAR_NULL; Index++) { + OptionString[Count] = OptionString[Index]; + Count++; + } + + OptionString[Count] = CHAR_NULL; + + Width = (UINT16) gOptionBlockWidth; + + OriginalRow = MenuOption->Row; + + for (Index = 0; GetLineByWidth (OptionString, Width, &Index, &OutputString) != 0x0000;) { + if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { + PrintStringAt (MenuOption->OptCol, MenuOption->Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&OptionString[Index])) { + MenuOption->Row++; + } + + gBS->FreePool (OutputString); + } + + MenuOption->Row = OriginalRow; + } else { + if (NewLine) { + OriginalRow = MenuOption->Row; + + Width = GetWidth (MenuOption->ThisTag, MenuOption->Handle); + + for (Index = 0; GetLineByWidth (MenuOption->Description, Width, &Index, &OutputString) != 0x0000;) { + if (MenuOption->Row >= TopRow && MenuOption->Row <= BottomRow) { + PrintStringAt (Col, MenuOption->Row, OutputString); + } + // + // If there is more string to process print on the next row and increment the Skip value + // + if (StrLen (&MenuOption->Description[Index])) { + MenuOption->Row++; + } + + gBS->FreePool (OutputString); + } + + MenuOption->Row = OriginalRow; + + } + } + + if (((NewPos->ForwardLink != &Menu) && (ScreenOperation == UiDown)) || + ((NewPos->BackLink != &Menu) && (ScreenOperation == UiUp)) || + (ScreenOperation == UiNoOperation) + ) { + UpdateKeyHelp (MenuOption, FALSE); + } + } else { + gST->ConOut->OutputString (gST->ConOut, MenuOption->Description); + } + // + // Clear reverse attribute + // + gST->ConOut->SetAttribute (gST->ConOut, FIELD_TEXT | FIELD_BACKGROUND); + } + // + // Repaint flag will be used when process CfUpdateHelpString, so restore its value + // if we didn't break halfway when process CfRefreshHighLight. + // + Repaint = SavedValue; + break; + + case CfUpdateHelpString: + ControlFlag = CfPrepareToReadKey; + + if (SubMenu && + (Repaint || NewLine || + (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || + (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) && + !(gClassOfVfr == EFI_GENERAL_APPLICATION_SUBCLASS)) { + // + // Don't print anything if it is a NULL help token + // + if (MenuOption->ThisTag->Help == 0x00000000) { + StringPtr = (CHAR16 *) L"\0"; + } else { + StringPtr = GetToken (MenuOption->ThisTag->Help, MenuOption->Handle); + } + + ProcessHelpString (StringPtr, &FormattedString, BottomRow - TopRow); + + gST->ConOut->SetAttribute (gST->ConOut, HELP_TEXT | FIELD_BACKGROUND); + + for (Index = 0; Index < BottomRow - TopRow; Index++) { + // + // Pad String with spaces to simulate a clearing of the previous line + // + for (; GetStringWidth (&FormattedString[Index * gHelpBlockWidth]) / 2 < gHelpBlockWidth;) { + StrCat (&FormattedString[Index * gHelpBlockWidth], (CHAR16 *) L" "); + } + + PrintStringAt ( + LocalScreen.RightColumn - gHelpBlockWidth, + Index + TopRow, + &FormattedString[Index * gHelpBlockWidth] + ); + } + } + // + // Reset this flag every time we finish using it. + // + Repaint = FALSE; + NewLine = FALSE; + break; + + case CfPrepareToReadKey: + ControlFlag = CfReadKey; + + for (Index = 0; Index < MenuOption->IfrNumber; Index++) { + FileFormTags = FileFormTags->NextFile; + } + + ScreenOperation = UiNoOperation; + + Status = gBS->HandleProtocol ( + (VOID *) (UINTN) FileFormTags->FormTags.Tags[0].CallbackHandle, + &gEfiFormCallbackProtocolGuid, + (VOID **) &FormCallback + ); + + break; + + case CfReadKey: + ControlFlag = CfScreenOperation; + + OriginalTimeOut = FrontPageTimeOutValue; + do { + if (FrontPageTimeOutValue >= 0 && (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) && FrontPageTimeOutValue != (INT16) -1) { + // + // Remember that if set to 0, must immediately boot an option + // + if (FrontPageTimeOutValue == 0) { + FrontPageTimeOutValue = 0xFFFF; + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (EFI_ERROR (Status)) { + Status = EFI_TIMEOUT; + } + break; + } + + Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, ONE_SECOND); + if (Status == EFI_TIMEOUT) { + EFI_IFR_DATA_ENTRY *DataEntry; + + DataEntry = (EFI_IFR_DATA_ENTRY *) (PageData + 1); + + PageData->EntryCount = 1; + Count = (UINT32) ((OriginalTimeOut - FrontPageTimeOutValue) * 100 / OriginalTimeOut); + CopyMem (&DataEntry->Data, &Count, sizeof (UINT32)); + + if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) { + FormCallback->Callback ( + FormCallback, + 0xFFFF, + (EFI_IFR_DATA_ARRAY *) PageData, + NULL + ); + } + // + // Count down 1 second + // + FrontPageTimeOutValue--; + + } else { + ASSERT (!EFI_ERROR (Status)); + PageData->EntryCount = 0; + if ((FormCallback != NULL) && (FormCallback->Callback != NULL)) { + FormCallback->Callback ( + FormCallback, + 0xFFFE, + (EFI_IFR_DATA_ARRAY *) PageData, + NULL + ); + } + + FrontPageTimeOutValue = 0xFFFF; + } + } else { + // + // Wait for user's selection, no auto boot + // + Status = UiWaitForSingleEvent (gST->ConIn->WaitForKey, 0); + } + } while (Status == EFI_TIMEOUT); + + if (gFirstIn) { + gFirstIn = FALSE; + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + DisableQuietBoot (); + } + + if (Status == EFI_TIMEOUT) { + Key.UnicodeChar = CHAR_CARRIAGE_RETURN; + } else { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + // + // if we encounter error, continue to read another key in. + // + if (EFI_ERROR (Status)) { + ControlFlag = CfReadKey; + continue; + } + } + + switch (Key.UnicodeChar) { + case CHAR_CARRIAGE_RETURN: + Selection = MenuOption; + ScreenOperation = UiSelect; + gDirection = 0; + break; + + // + // We will push the adjustment of these numeric values directly to the input handler + // + case '+': + case '-': + if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { + + if (Key.UnicodeChar == '+') { + gDirection = SCAN_RIGHT; + } else { + gDirection = SCAN_LEFT; + } + + Status = ProcessOptions (MenuOption, TRUE, FileFormTagsHead, NULL, &OptionString); + } + break; + + case '^': + ScreenOperation = UiUp; + break; + + case 'V': + case 'v': + ScreenOperation = UiDown; + break; + + case ' ': + if (gClassOfVfr != EFI_FRONT_PAGE_SUBCLASS) { + if (SubMenu) { + if (MenuOption->ThisTag->Operand == EFI_IFR_CHECKBOX_OP && !(MenuOption->ThisTag->GrayOut)) { + gST->ConOut->SetCursorPosition (gST->ConOut, MenuOption->Col, MenuOption->Row); + gST->ConOut->OutputString (gST->ConOut, MenuOption->Description); + Selection = MenuOption; + ScreenOperation = UiSelect; + } + } + } + break; + + case CHAR_NULL: + if (((Key.ScanCode == SCAN_F1) && ((gFunctionKeySetting & FUNCTION_ONE) != FUNCTION_ONE)) || + ((Key.ScanCode == SCAN_F2) && ((gFunctionKeySetting & FUNCTION_TWO) != FUNCTION_TWO)) || + ((Key.ScanCode == SCAN_F9) && ((gFunctionKeySetting & FUNCTION_NINE) != FUNCTION_NINE)) || + ((Key.ScanCode == SCAN_F10) && ((gFunctionKeySetting & FUNCTION_TEN) != FUNCTION_TEN)) + ) { + // + // If the function key has been disabled, just ignore the key. + // + } else { + for (Index = 0; Index < sizeof (gScanCodeToOperation) / sizeof (gScanCodeToOperation[0]); Index++) { + if (Key.ScanCode == gScanCodeToOperation[Index].ScanCode) { + if ((Key.ScanCode == SCAN_F9) || (Key.ScanCode == SCAN_F10)) { + if (SubMenu) { + ScreenOperation = gScanCodeToOperation[Index].ScreenOperation; + } + } else { + ScreenOperation = gScanCodeToOperation[Index].ScreenOperation; + } + } + } + } + break; + } + break; + + case CfScreenOperation: + IfrBinary = gBinaryDataHead; + + // + // Advance to the Ifr we are using + // + for (Index = 0; Index < gActiveIfr; Index++) { + IfrBinary = IfrBinary->Next; + } + + if (ScreenOperation != UiPrevious && ScreenOperation != UiReset) { + // + // If the screen has no menu items, and the user didn't select UiPrevious, or UiReset + // ignore the selection and go back to reading keys. + // + if (IsListEmpty (&Menu)) { + ControlFlag = CfReadKey; + break; + } + // + // if there is nothing logical to place a cursor on, just move on to wait for a key. + // + for (Link = Menu.ForwardLink; Link != &Menu; Link = Link->ForwardLink) { + NextMenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + if (!(NextMenuOption->ThisTag->GrayOut) && (NextMenuOption->ThisTag->Operand != EFI_IFR_SUBTITLE_OP)) { + break; + } + } + + if (Link == &Menu) { + ControlFlag = CfPrepareToReadKey; + break; + } + } + + for (Index = 0; + Index < sizeof (gScreenOperationToControlFlag) / sizeof (gScreenOperationToControlFlag[0]); + Index++ + ) { + if (ScreenOperation == gScreenOperationToControlFlag[Index].ScreenOperation) { + ControlFlag = gScreenOperationToControlFlag[Index].ControlFlag; + } + } + + break; + + case CfUiPrevious: + ControlFlag = CfCheckSelection; + // + // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data. + // + if (MenuOption != NULL) { + if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) { + Selection = NULL; + Repaint = TRUE; + break; + } + } + + if (IsListEmpty (&gMenuList)) { + Selection = NULL; + if (IsListEmpty (&Menu)) { + ControlFlag = CfReadKey; + } + break; + } + + gLastOpr = TRUE; + + while (gMenuRefreshHead != NULL) { + OldMenuRefreshEntry = gMenuRefreshHead->Next; + + gBS->FreePool (gMenuRefreshHead); + + gMenuRefreshHead = OldMenuRefreshEntry; + } + // + // Remove the Cached page entry, free and init the menus, flag Selection as jumping to previous page and a valid Tag + // + if (SubMenu) { + UiRemoveMenuListEntry (MenuOption, &Selection); + Selection->Previous = TRUE; + UiFreeMenu (); + UiInitMenu (); + } + + gActiveIfr = Selection->IfrNumber; + return Selection; + + case CfUiSelect: + ControlFlag = CfCheckSelection; + + ExtractRequestedNvMap (FileFormTags, MenuOption->ThisTag->VariableNumber, &VariableDefinition); + + if (SubMenu) { + if ((MenuOption->ThisTag->Operand == EFI_IFR_TEXT_OP && + !(MenuOption->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE)) || + (MenuOption->ThisTag->GrayOut) || + (MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || + (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { + Selection = NULL; + break; + } + + NewLine = TRUE; + UpdateKeyHelp (MenuOption, TRUE); + Status = ProcessOptions (MenuOption, TRUE, FileFormTagsHead, PageData, &OptionString); + + if (EFI_ERROR (Status)) { + Selection = NULL; + Repaint = TRUE; + break; + } + + if (OptionString != NULL) { + PrintStringAt (LocalScreen.LeftColumn + gPromptBlockWidth + 1, MenuOption->Row, OptionString); + } + + if (MenuOption->ThisTag->Flags & EFI_IFR_FLAG_INTERACTIVE) { + Selection = MenuOption; + } + + if (Selection == NULL) { + break; + } + + Location = (UINT8 *) &PageData->EntryCount; + + // + // If not a goto, dump single piece of data, otherwise dump everything + // + if (Selection->ThisTag->Operand == EFI_IFR_REF_OP) { + // + // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data. + // + if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) { + Selection = NULL; + Repaint = TRUE; + break; + } + + UiAddMenuListEntry (Selection); + gPriorMenuEntry = 0; + + // + // Now that we added a menu entry specific to a goto, we can always go back when someone hits the UiPrevious + // + UiMenuList = CR (gMenuList.ForwardLink, UI_MENU_LIST, MenuLink, UI_MENU_LIST_SIGNATURE); + UiMenuList->FormerEntryNumber = MenuOption->EntryNumber; + + gLastOpr = FALSE; + + // + // Rewind to the beginning of the menu + // + for (; NewPos->BackLink != &Menu; NewPos = NewPos->BackLink) + ; + + // + // Get Total Count of Menu entries + // + for (Count = 1; NewPos->ForwardLink != &Menu; NewPos = NewPos->ForwardLink) { + Count++; + } + // + // Rewind to the beginning of the menu + // + for (; NewPos->BackLink != &Menu; NewPos = NewPos->BackLink) + ; + + // + // Copy the number of entries being described to the PageData location + // + CopyMem (&Location[0], &Count, sizeof (UINT32)); + + for (Index = 4; NewPos->ForwardLink != &Menu; Index = Index + MenuOption->ThisTag->StorageWidth + 2) { + + MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + Location[Index] = MenuOption->ThisTag->Operand; + Location[Index + 1] = (UINT8) (MenuOption->ThisTag->StorageWidth + 4); + CopyMem ( + &Location[Index + 4], + &VariableDefinition->NvRamMap[MenuOption->ThisTag->StorageStart], + MenuOption->ThisTag->StorageWidth + ); + NewPos = NewPos->ForwardLink; + } + } else { + + gPriorMenuEntry = MenuOption->EntryNumber; + + Count = 1; + + // + // Copy the number of entries being described to the PageData location + // + CopyMem (&Location[0], &Count, sizeof (UINT32)); + + // + // Start at PageData[4] since the EntryCount is a UINT32 + // + Index = 4; + + // + // Copy data to destination + // + Location[Index] = MenuOption->ThisTag->Operand; + Location[Index + 1] = (UINT8) (MenuOption->ThisTag->StorageWidth + 4); + CopyMem ( + &Location[Index + 4], + &VariableDefinition->NvRamMap[MenuOption->ThisTag->StorageStart], + MenuOption->ThisTag->StorageWidth + ); + } + } + break; + + case CfUiReset: + ControlFlag = CfCheckSelection; + gLastOpr = FALSE; + if (gClassOfVfr == EFI_FRONT_PAGE_SUBCLASS) { + break; + } + // + // If NV flag is up, prompt user + // + if (gNvUpdateRequired) { + Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + + YesResponse = gYesResponse[0]; + NoResponse = gNoResponse[0]; + + do { + CreateDialog (3, TRUE, 0, NULL, &Key, gEmptyString, gAreYouSure, gEmptyString); + } while + ( + (Key.ScanCode != SCAN_ESC) && + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (NoResponse | UPPER_LOWER_CASE_OFFSET)) && + ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) != (YesResponse | UPPER_LOWER_CASE_OFFSET)) + ); + + // + // If the user hits the YesResponse key + // + if ((Key.UnicodeChar | UPPER_LOWER_CASE_OFFSET) == (YesResponse | UPPER_LOWER_CASE_OFFSET)) { + } else { + Repaint = TRUE; + NewLine = TRUE; + break; + } + } + // + // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data. + // + if (MenuOption != NULL) { + if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) { + Selection = NULL; + Repaint = TRUE; + NewLine = TRUE; + break; + } + } + + gST->ConOut->SetAttribute (gST->ConOut, EFI_TEXT_ATTR (EFI_LIGHTGRAY, EFI_BLACK)); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + + if (SubMenu) { + UiFreeMenuList (); + gST->ConOut->ClearScreen (gST->ConOut); + return NULL; + } + + UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE); + UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, FALSE); + + if (IfrBinary->UnRegisterOnExit) { + Hii->RemovePack (Hii, MenuOption->Handle); + } + + UiFreeMenu (); + + // + // Clean up the allocated data buffers + // + FreeData (FileFormTagsHead, FormattedString, OptionString); + + gST->ConOut->ClearScreen (gST->ConOut); + return NULL; + + case CfUiLeft: + ControlFlag = CfCheckSelection; + if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { + if (MenuOption->Skip == 1) { + // + // In the tail of the Date/Time op-code set, go left. + // + NewPos = NewPos->BackLink; + } else { + // + // In the middle of the Data/Time op-code set, go left. + // + NextMenuOption = CR (NewPos->ForwardLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + if (NextMenuOption->Skip == 1) { + NewPos = NewPos->BackLink; + } + } + } + break; + + case CfUiRight: + ControlFlag = CfCheckSelection; + if ((MenuOption->Skip == 0) && + ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) + ) { + // + // We are in the head or middle of the Date/Time op-code set, advance right. + // + NewPos = NewPos->ForwardLink; + } + break; + + case CfUiUp: + ControlFlag = CfCheckSelection; + + if (NewPos->BackLink != &Menu) { + NewLine = TRUE; + // + // Adjust Date/Time position before we advance forward. + // + AdjustDateAndTimePosition (TRUE, &NewPos); + + // + // Caution that we have already rewind to the top, don't go backward in this situation. + // + if (NewPos->BackLink != &Menu) { + NewPos = NewPos->BackLink; + } + + PreviousMenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + + // + // Since the behavior of hitting the up arrow on a Date/Time op-code is intended + // to be one that back to the previous set of op-codes, we need to advance to the sencond + // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate + // checking can be done. + // + DataAndTimeLineNumberPad = AdjustDateAndTimePosition (TRUE, &NewPos); + + if (SubMenu) { + // + // If the previous MenuOption contains a display-only op-code, skip to the next one + // + if (PreviousMenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || PreviousMenuOption->ThisTag->GrayOut) { + // + // This is ok as long as not at the end of the list + // + if (NewPos->BackLink == &Menu) { + // + // If we are at the start of the list, then this list must start with a display only + // piece of data, so do not allow the backward motion + // + ScreenOperation = UiDown; + + if (PreviousMenuOption->Row <= TopRow) { + if (TopOfScreen->BackLink != &Menu) { + TopOfScreen = TopOfScreen->BackLink; + Repaint = TRUE; + } + } + + UpdateStatusBar (INPUT_ERROR, PreviousMenuOption->ThisTag->Flags, FALSE); + break; + } + } + } + // + // Check the previous menu entry to see if it was a zero-length advance. If it was, + // don't worry about a redraw. + // + if ((MenuOption->Row - PreviousMenuOption->Skip - DataAndTimeLineNumberPad < TopRow) || + (PreviousMenuOption->Skip > MenuOption->Row) + ) { + do { + if (TopOfScreen->BackLink == &Menu) { + break; + } + + Repaint = TRUE; + + // + // Is the current top of screen a zero-advance op-code? + // If so, keep moving forward till we hit a >0 advance op-code + // + SavedMenuOption = CR (TopOfScreen->BackLink, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + TopOfScreen = TopOfScreen->BackLink; + } while (SavedMenuOption->Skip == 0); + // + // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. + // + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + } + + UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE); + } else { + if (SubMenu) { + SavedMenuOption = MenuOption; + MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) { + // + // If we are at the end of the list and sitting on a text op, we need to more forward + // + ScreenOperation = UiDown; + ControlFlag = CfScreenOperation; + break; + } + + MenuOption = SavedMenuOption; + } + } + break; + + case CfUiPageUp: + ControlFlag = CfCheckSelection; + + SavedListEntry = NewPos; + Link = TopOfScreen; + for (Index = BottomRow; Index >= TopRow + 1; Index -= MenuOption->Skip) { + if (Link->BackLink == &Menu) { + TopOfScreen = Link; + Link = SavedListEntry; + MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + break; + } + + NewLine = TRUE; + Repaint = TRUE; + Link = Link->BackLink; + MenuOption = CR (Link, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + TopOfScreen = Link; + SavedListEntry = Link; + } + + NewPos = Link; + + // + // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. + // Don't do this when we are already in the first page. + // + if (Repaint) { + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + AdjustDateAndTimePosition (TRUE, &NewPos); + MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + } + break; + + case CfUiPageDown: + ControlFlag = CfCheckSelection; + + SavedListEntry = NewPos; + Link = TopOfScreen; + NewPos = TopOfScreen; + for (Index = TopRow; Index <= BottomRow - 1; Index += MenuOption->Skip) { + if (NewPos->ForwardLink == &Menu) { + NewPos = SavedListEntry; + MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + Link = TopOfScreen; + NewLine = FALSE; + Repaint = FALSE; + break; + } + + NewLine = TRUE; + Repaint = TRUE; + MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + NewPos = NewPos->ForwardLink; + Link = NewPos; + } + + TopOfScreen = Link; + + // + // If we encounter a Date/Time op-code set, rewind to the first op-code of the set. + // Don't do this when we are already in the last page. + // + if (Repaint) { + AdjustDateAndTimePosition (TRUE, &TopOfScreen); + AdjustDateAndTimePosition (TRUE, &NewPos); + MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + } + break; + + case CfUiDown: + ControlFlag = CfCheckSelection; + // + // Since the behavior of hitting the down arrow on a Date/Time op-code is intended + // to be one that progresses to the next set of op-codes, we need to advance to the last + // Date/Time op-code and leave the remaining logic in UiDown intact so the appropriate + // checking can be done. The only other logic we need to introduce is that if a Date/Time + // op-code is the last entry in the menu, we need to rewind back to the first op-code of + // the Date/Time op-code. + // + DataAndTimeLineNumberPad = AdjustDateAndTimePosition (FALSE, &NewPos); + + if (NewPos->ForwardLink != &Menu) { + NewLine = TRUE; + NewPos = NewPos->ForwardLink; + NextMenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + + if (SubMenu) { + // + // If the next MenuOption contains a display-only op-code, skip to the next one + // Also if the next MenuOption is date or time, + // + if (NextMenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || NextMenuOption->ThisTag->GrayOut) { + // + // This is ok as long as not at the end of the list + // + if (NewPos == &Menu) { + // + // If we are at the end of the list, then this list must end with a display only + // piece of data, so do not allow the forward motion + // + UpdateStatusBar (INPUT_ERROR, NextMenuOption->ThisTag->Flags, FALSE); + NewPos = NewPos->BackLink; + ScreenOperation = UiUp; + break; + } + } + } + // + // An option might be multi-line, so we need to reflect that data in the overall skip value + // + UpdateOptionSkipLines (PageData, NextMenuOption, FileFormTagsHead, &OptionString, SkipValue); + + if (NextMenuOption->Skip > 1) { + Temp = MenuOption->Row + MenuOption->Skip + NextMenuOption->Skip - 1; + } else { + Temp = MenuOption->Row + MenuOption->Skip + DataAndTimeLineNumberPad; + } + // + // If we are going to scroll + // + if (Temp > BottomRow) { + do { + // + // Is the current top of screen a zero-advance op-code? + // If so, keep moving forward till we hit a >0 advance op-code + // + SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + + // + // If bottom op-code is more than one line or top op-code is more than one line + // + if ((NextMenuOption->Skip > 1) || (MenuOption->Skip > 1)) { + // + // Is the bottom op-code greater than or equal in size to the top op-code? + // + if ((Temp - BottomRow) >= (SavedMenuOption->Skip - OldSkipValue)) { + // + // Skip the top op-code + // + TopOfScreen = TopOfScreen->ForwardLink; + Difference = (Temp - BottomRow) - (SavedMenuOption->Skip - OldSkipValue); + + OldSkipValue = Difference; + + SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + + // + // If we have a remainder, skip that many more op-codes until we drain the remainder + // + for (; + Difference >= (INTN) SavedMenuOption->Skip; + Difference = Difference - (INTN) SavedMenuOption->Skip + ) { + // + // Since the Difference is greater than or equal to this op-code's skip value, skip it + // + TopOfScreen = TopOfScreen->ForwardLink; + SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + if (Difference < (INTN) SavedMenuOption->Skip) { + Difference = SavedMenuOption->Skip - Difference - 1; + break; + } else { + if (Difference == (INTN) SavedMenuOption->Skip) { + TopOfScreen = TopOfScreen->ForwardLink; + SavedMenuOption = CR (TopOfScreen, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + Difference = SavedMenuOption->Skip - Difference; + break; + } + } + } + // + // Since we will act on this op-code in the next routine, and increment the + // SkipValue, set the skips to one less than what is required. + // + SkipValue = Difference - 1; + + } else { + // + // Since we will act on this op-code in the next routine, and increment the + // SkipValue, set the skips to one less than what is required. + // + SkipValue = OldSkipValue + (Temp - BottomRow) - 1; + } + } else { + if ((OldSkipValue + 1) == (INTN) SavedMenuOption->Skip) { + TopOfScreen = TopOfScreen->ForwardLink; + break; + } else { + SkipValue = OldSkipValue; + } + } + // + // If the op-code at the top of the screen is more than one line, let's not skip it yet + // Let's set a skip flag to smoothly scroll the top of the screen. + // + if (SavedMenuOption->Skip > 1) { + if (SavedMenuOption == NextMenuOption) { + SkipValue = 0; + } else { + SkipValue++; + } + } else { + SkipValue = 0; + TopOfScreen = TopOfScreen->ForwardLink; + } + } while (SavedMenuOption->Skip == 0); + + Repaint = TRUE; + OldSkipValue = SkipValue; + } + + UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE); + + } else { + if (SubMenu) { + SavedMenuOption = MenuOption; + MenuOption = CR (NewPos, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + if (MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut) { + // + // If we are at the end of the list and sitting on a text op, we need to more forward + // + ScreenOperation = UiUp; + ControlFlag = CfScreenOperation; + break; + } + + MenuOption = SavedMenuOption; + // + // If we are at the end of the list and sitting on a Date/Time op, rewind to the head. + // + AdjustDateAndTimePosition (TRUE, &NewPos); + } + } + break; + + case CfUiSave: + ControlFlag = CfCheckSelection; + // + // Check for tags that might have LATE_CHECK enabled. If they do, we can't switch pages or save NV data. + // + if (MenuOption != NULL) { + if (!SelectionsAreValid (MenuOption, FileFormTagsHead)) { + Selection = NULL; + Repaint = TRUE; + break; + } + } + // + // If callbacks are active, and the callback has a Write method, try to use it + // + if (FileFormTags->VariableDefinitions->VariableName == NULL) { + if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) { + Status = FormCallback->NvWrite ( + FormCallback, + (CHAR16 *) L"Setup", + &FileFormTags->FormTags.Tags[0].GuidValue, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VariableDefinition->VariableSize, + (VOID *) VariableDefinition->NvRamMap, + &gResetRequired + ); + + } else { + Status = gRT->SetVariable ( + (CHAR16 *) L"Setup", + &FileFormTags->FormTags.Tags[0].GuidValue, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VariableDefinition->VariableSize, + (VOID *) VariableDefinition->NvRamMap + ); + } + } else { + VariableDefinition = FileFormTags->VariableDefinitions; + + for (; VariableDefinition != NULL; VariableDefinition = VariableDefinition->Next) { + if ((FormCallback != NULL) && (FormCallback->NvWrite != NULL)) { + Status = FormCallback->NvWrite ( + FormCallback, + VariableDefinition->VariableName, + &VariableDefinition->Guid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VariableDefinition->VariableSize, + (VOID *) VariableDefinition->NvRamMap, + &gResetRequired + ); + + } else { + Status = gRT->SetVariable ( + VariableDefinition->VariableName, + &VariableDefinition->Guid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + VariableDefinition->VariableSize, + (VOID *) VariableDefinition->NvRamMap + ); + } + } + } + + UpdateStatusBar (INPUT_ERROR, MenuOption->ThisTag->Flags, FALSE); + UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, FALSE); + break; + + case CfUiDefault: + ControlFlag = CfCheckSelection; + + NvMapListHead = NULL; + + Status = Hii->GetDefaultImage (Hii, MenuOption->Handle, EFI_IFR_FLAG_DEFAULT, &NvMapListHead); + + if (!EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (NULL != NvMapListHead); + + NvMapListNode = NvMapListHead; + + while (NULL != NvMapListNode) { + if (FileFormTags->VariableDefinitions->VariableId == NvMapListNode->VariablePack->VariableId) { + NvMap = (VOID *) ((CHAR8 *) NvMapListNode->VariablePack + sizeof (EFI_HII_VARIABLE_PACK) + NvMapListNode->VariablePack->VariableNameLength); + NvMapSize = NvMapListNode->VariablePack->Header.Length - sizeof (EFI_HII_VARIABLE_PACK) - NvMapListNode->VariablePack->VariableNameLength; + break; + } + NvMapListNode = NvMapListNode->NextVariablePack; + } + + // + // Free the buffer that was allocated. + // + gBS->FreePool (FileFormTags->VariableDefinitions->NvRamMap); + gBS->FreePool (FileFormTags->VariableDefinitions->FakeNvRamMap); + + // + // Allocate, copy the NvRamMap. + // + FileFormTags->VariableDefinitions->VariableFakeSize = (UINT16) (FileFormTags->VariableDefinitions->VariableFakeSize - FileFormTags->VariableDefinitions->VariableSize); + FileFormTags->VariableDefinitions->VariableSize = (UINT16) NvMapSize; + FileFormTags->VariableDefinitions->VariableFakeSize = (UINT16) (FileFormTags->VariableDefinitions->VariableFakeSize + FileFormTags->VariableDefinitions->VariableSize); + + FileFormTags->VariableDefinitions->NvRamMap = AllocateZeroPool (FileFormTags->VariableDefinitions->VariableSize); + FileFormTags->VariableDefinitions->FakeNvRamMap = AllocateZeroPool (NvMapSize + FileFormTags->VariableDefinitions->VariableFakeSize); + + CopyMem (FileFormTags->VariableDefinitions->NvRamMap, NvMap, NvMapSize); + gBS->FreePool (NvMapListHead); + } + + UpdateStatusBar (NV_UPDATE_REQUIRED, MenuOption->ThisTag->Flags, TRUE); + Repaint = TRUE; + // + // After the repaint operation, we should refresh the highlight. + // + NewLine = TRUE; + break; + + case CfUiNoOperation: + ControlFlag = CfCheckSelection; + break; + + case CfExit: + while (gMenuRefreshHead != NULL) { + OldMenuRefreshEntry = gMenuRefreshHead->Next; + + gBS->FreePool (gMenuRefreshHead); + + gMenuRefreshHead = OldMenuRefreshEntry; + } + + gST->ConOut->SetCursorPosition (gST->ConOut, 0, Row + 4); + gST->ConOut->EnableCursor (gST->ConOut, TRUE); + gST->ConOut->OutputString (gST->ConOut, (CHAR16 *) L"\n"); + + gActiveIfr = MenuOption->IfrNumber; + return Selection; + + default: + break; + } + } +} + +BOOLEAN +ValueIsScroll ( + IN BOOLEAN Direction, + IN LIST_ENTRY *CurrentPos + ) +/*++ + +Routine Description: + Determine if the menu is the last menu that can be selected. + +Arguments: + Direction - the scroll direction. False is down. True is up. + +Returns: + FALSE -- the menu isn't the last menu that can be selected. + TRUE -- the menu is the last menu that can be selected. +--*/ +{ + LIST_ENTRY *Temp; + UI_MENU_OPTION *MenuOption; + MenuOption = NULL; + + Temp = Direction ? CurrentPos->BackLink : CurrentPos->ForwardLink; + + if (Temp == &Menu) { + return TRUE; + } + + for (; Temp != &Menu; Temp = Direction ? Temp->BackLink : Temp->ForwardLink) { + MenuOption = CR (Temp, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + if (!(MenuOption->ThisTag->Operand == EFI_IFR_SUBTITLE_OP || MenuOption->ThisTag->GrayOut)) { + return FALSE; + } + } + + return TRUE; +} + +UINTN +AdjustDateAndTimePosition ( + IN BOOLEAN DirectionUp, + IN LIST_ENTRY **CurrentPosition + ) +/*++ +Routine Description: + Adjust Data and Time tag position accordingly. + Data format : [01/02/2004] [11:22:33] + Line number : 0 0 1 0 0 1 + +Arguments: + Direction - the up or down direction. False is down. True is up. + CurrentPos - Current position. + +Returns: + Return line number to pad. It is possible that we stand on a zero-advance + data or time opcode, so pad one line when we judge if we are going to scroll outside. +--*/ +{ + UINTN Count; + LIST_ENTRY *NewPosition; + UI_MENU_OPTION *MenuOption; + UINTN PadLineNumber; + + PadLineNumber = 0; + NewPosition = *CurrentPosition; + MenuOption = CR (NewPosition, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + + if ((MenuOption->ThisTag->Operand == EFI_IFR_DATE_OP) || (MenuOption->ThisTag->Operand == EFI_IFR_TIME_OP)) { + // + // Calculate the distance from current position to the last Date/Time op-code. + // + Count = 0; + while (MenuOption->ThisTag->NumberOfLines == 0) { + Count++; + NewPosition = NewPosition->ForwardLink; + MenuOption = CR (NewPosition, UI_MENU_OPTION, Link, UI_MENU_OPTION_SIGNATURE); + PadLineNumber = 1; + } + + NewPosition = *CurrentPosition; + if (DirectionUp) { + // + // Since the behavior of hitting the up arrow on a Date/Time op-code is intended + // to be one that back to the previous set of op-codes, we need to advance to the first + // Date/Time op-code and leave the remaining logic in CfUiUp intact so the appropriate + // checking can be done. + // + while (Count++ < 2) { + NewPosition = NewPosition->BackLink; + } + } else { + // + // Since the behavior of hitting the down arrow on a Date/Time op-code is intended + // to be one that progresses to the next set of op-codes, we need to advance to the last + // Date/Time op-code and leave the remaining logic in CfUiDown intact so the appropriate + // checking can be done. + // + while (Count-- > 0) { + NewPosition = NewPosition->ForwardLink; + } + } + + *CurrentPosition = NewPosition; + } + + return PadLineNumber; +} diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Ui.h b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Ui.h new file mode 100644 index 0000000000..522f4ce5b8 --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/Ui.h @@ -0,0 +1,435 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Ui.h + +Abstract: + + Head file UI + +Revision History + +--*/ + +#ifndef _UI_H +#define _UI_H + +// +// Globals +// +#define REGULAR_NUMERIC 0 +#define TIME_NUMERIC 1 +#define DATE_NUMERIC 2 + +typedef enum { + UiNoOperation, + UiDefault, + UiSelect, + UiUp, + UiDown, + UiLeft, + UiRight, + UiReset, + UiSave, + UiPrevious, + UiPageUp, + UiPageDown, + UiMaxOperation +} UI_SCREEN_OPERATION; + +typedef enum { + CfInitialization, + CfCheckSelection, + CfRepaint, + CfRefreshHighLight, + CfUpdateHelpString, + CfPrepareToReadKey, + CfReadKey, + CfScreenOperation, + CfUiPrevious, + CfUiSelect, + CfUiReset, + CfUiLeft, + CfUiRight, + CfUiUp, + CfUiPageUp, + CfUiPageDown, + CfUiDown, + CfUiSave, + CfUiDefault, + CfUiNoOperation, + CfExit, + CfMaxControlFlag +} UI_CONTROL_FLAG; + +#define UI_MENU_OPTION_SIGNATURE EFI_SIGNATURE_32 ('u', 'i', 'm', 'm') +#define UI_MENU_LIST_SIGNATURE EFI_SIGNATURE_32 ('u', 'i', 'm', 'l') + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + + UINTN Row; + UINTN Col; + UINTN OptCol; + CHAR16 *Description; + UINTN Skip; + + UINTN IfrNumber; + VOID *FormBinary; + EFI_HII_HANDLE Handle; + EFI_TAG *Tags; + UINTN TagIndex; + EFI_TAG *ThisTag; + UINT16 FormId; + BOOLEAN Previous; + UINT16 EntryNumber; + UINT16 Consistency; + BOOLEAN GrayOut; +} UI_MENU_OPTION; + +typedef struct { + UINTN Signature; + LIST_ENTRY MenuLink; + + UI_MENU_OPTION Selection; + UINTN FormerEntryNumber; +} UI_MENU_LIST; + +typedef struct _MENU_REFRESH_ENTRY { + struct _MENU_REFRESH_ENTRY *Next; + EFI_FILE_FORM_TAGS *FileFormTagsHead; + UINTN CurrentColumn; + UINTN CurrentRow; + UINTN CurrentAttribute; + UI_MENU_OPTION *MenuOption; // Describes the entry needing an update +} MENU_REFRESH_ENTRY; + +typedef struct { + UINT16 ScanCode; + UI_SCREEN_OPERATION ScreenOperation; +} SCAN_CODE_TO_SCREEN_OPERATION; + +typedef struct { + UI_SCREEN_OPERATION ScreenOperation; + UI_CONTROL_FLAG ControlFlag; +} SCREEN_OPERATION_T0_CONTROL_FLAG; + +LIST_ENTRY Menu; +LIST_ENTRY gMenuList; +MENU_REFRESH_ENTRY *gMenuRefreshHead; + +INTN gEntryNumber; +BOOLEAN gLastOpr; +// +// Global Functions +// +VOID +UiInitMenu ( + VOID + ) +; + +VOID +UiInitMenuList ( + VOID + ) +; + +VOID +UiRemoveMenuListEntry ( + IN UI_MENU_OPTION *Selection, + OUT UI_MENU_OPTION **PreviousSelection + ) +; + +VOID +UiFreeMenuList ( + VOID + ) +; + +VOID +UiAddMenuListEntry ( + IN UI_MENU_OPTION *Selection + ) +; + +VOID +UiFreeMenu ( + VOID + ) +; + +VOID +UiAddMenuOption ( + IN CHAR16 *String, + IN EFI_HII_HANDLE Handle, + IN EFI_TAG *Tag, + IN VOID *FormBinary, + IN UINTN IfrNumber + ) +; + +VOID +UiAddSubMenuOption ( + IN CHAR16 *String, + IN EFI_HII_HANDLE Handle, + IN EFI_TAG *Tag, + IN UINTN TagIndex, + IN UINT16 FormId, + IN UINT16 MenuItemCount + ) +; + +UI_MENU_OPTION * +UiDisplayMenu ( + IN BOOLEAN SubMenu, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + OUT EFI_IFR_DATA_ARRAY *PageData + ) +; + +VOID +InitPage ( + VOID + ) +; + +UI_MENU_OPTION * +SetupBrowser ( + IN UI_MENU_OPTION *Selection, + IN BOOLEAN Callback, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN UINT8 *CallbackData + ) +; + + +VOID +SetUnicodeMem ( + IN VOID *Buffer, + IN UINTN Size, + IN CHAR16 Value + ) +; + +EFI_STATUS +UiWaitForSingleEvent ( + IN EFI_EVENT Event, + IN UINT64 Timeout OPTIONAL + ) +; + +VOID +CreatePopUp ( + IN UINTN ScreenWidth, + IN UINTN NumberOfLines, + IN CHAR16 *ArrayOfStrings, + ... + ) +; + +EFI_STATUS +ReadString ( + IN UI_MENU_OPTION *MenuOption, + OUT CHAR16 *StringPtr + ) +; + +EFI_STATUS +ReadPassword ( + IN UI_MENU_OPTION *MenuOption, + IN BOOLEAN PromptForPassword, + IN EFI_TAG *Tag, + IN EFI_IFR_DATA_ARRAY *PageData, + IN BOOLEAN SecondEntry, + IN EFI_FILE_FORM_TAGS *FileFormTags, + OUT CHAR16 *StringPtr + ) +; + +VOID +EncodePassword ( + IN CHAR16 *Password, + IN UINT8 MaxSize + ) +; + +EFI_STATUS +GetSelectionInputPopUp ( + IN UI_MENU_OPTION *MenuOption, + IN EFI_TAG *Tag, + IN UINTN ValueCount, + OUT UINT16 *Value, + OUT UINT16 *KeyValue + ) +; + +EFI_STATUS +GetSelectionInputLeftRight ( + IN UI_MENU_OPTION *MenuOption, + IN EFI_TAG *Tag, + IN UINTN ValueCount, + OUT UINT16 *Value + ) +; + +EFI_STATUS +GetNumericInput ( + IN UI_MENU_OPTION *MenuOption, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN BOOLEAN ManualInput, + IN EFI_TAG *Tag, + IN UINTN NumericType, + OUT UINT16 *Value + ) +; + +VOID +UpdateStatusBar ( + IN UINTN MessageType, + IN UINT8 Flags, + IN BOOLEAN State + ) +; + +EFI_STATUS +ProcessOptions ( + IN UI_MENU_OPTION *MenuOption, + IN BOOLEAN Selected, + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN EFI_IFR_DATA_ARRAY *PageData, + OUT CHAR16 **OptionString + ) +; + +VOID +ProcessHelpString ( + IN CHAR16 *StringPtr, + OUT CHAR16 **FormattedString, + IN UINTN RowCount + ) +; + +VOID +UpdateKeyHelp ( + IN UI_MENU_OPTION *Selection, + IN BOOLEAN Selected + ) +; + +BOOLEAN +ValueIsNotValid ( + IN BOOLEAN Complex, + IN UINT16 Value, + IN EFI_TAG *Tag, + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN STRING_REF *PopUp + ) +; + +VOID +FreeData ( + IN EFI_FILE_FORM_TAGS *FileFormTagsHead, + IN CHAR16 *FormattedString, + IN CHAR16 *OptionString + ) +; + +VOID +ClearLines ( + UINTN LeftColumn, + UINTN RightColumn, + UINTN TopRow, + UINTN BottomRow, + UINTN TextAttribute + ) +; + +UINTN +GetStringWidth ( + CHAR16 *String + ) +; + +UINT16 +GetLineByWidth ( + IN CHAR16 *InputString, + IN UINT16 LineWidth, + IN OUT UINTN *Index, + OUT CHAR16 **OutputString + ) +; + +UINT16 +GetWidth ( + IN EFI_TAG *Tag, + IN EFI_HII_HANDLE Handle + ) +; + +VOID +NewStrCat ( + CHAR16 *Destination, + CHAR16 *Source + ) +; + +VOID +IfrToFormTag ( + IN UINT8 OpCode, + IN EFI_TAG *TargetTag, + IN VOID *FormData, + EFI_VARIABLE_DEFINITION *VariableDefinitionsHead + ) +; + +EFI_STATUS +ExtractNvValue ( + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UINT16 VariableId, + IN UINT16 VariableSize, + IN UINT16 OffsetValue, + OUT VOID **Buffer + ) +; + +EFI_STATUS +ExtractRequestedNvMap ( + IN EFI_FILE_FORM_TAGS *FileFormTags, + IN UINT16 VariableId, + OUT EFI_VARIABLE_DEFINITION **VariableDefinition + ) +; + +BOOLEAN +ValueIsScroll ( + IN BOOLEAN Direction, + IN LIST_ENTRY *CurrentPos + ) +; + +UINTN +AdjustDateAndTimePosition ( + IN BOOLEAN DirectionUp, + IN LIST_ENTRY **CurrentPosition + ) +; + +EFI_STATUS +WaitForKeyStroke ( + OUT EFI_INPUT_KEY *Key + ) +; +#endif // _UI_H diff --git a/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/build.xml b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/build.xml new file mode 100644 index 0000000000..a94cdfa58c --- /dev/null +++ b/EdkModulePkg/Universal/UserInterface/SetupBrowser/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Variable/Pei/Ia32/VarMachine.h b/EdkModulePkg/Universal/Variable/Pei/Ia32/VarMachine.h new file mode 100644 index 0000000000..83031e9788 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/Pei/Ia32/VarMachine.h @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + VarMachine.h + +Abstract: + + Variable Machine Type + +--*/ + +#ifndef _VAR_MACHINE_H +#define _VAR_MACHINE_H + +#define ALIGNMENT 1 + +#endif diff --git a/EdkModulePkg/Universal/Variable/Pei/Ipf/VarMachine.h b/EdkModulePkg/Universal/Variable/Pei/Ipf/VarMachine.h new file mode 100644 index 0000000000..c5b5753f9e --- /dev/null +++ b/EdkModulePkg/Universal/Variable/Pei/Ipf/VarMachine.h @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + VarMachine.h + +Abstract: + + Variable Machine Type + +--*/ + +#ifndef _VAR_MACHINE_H +#define _VAR_MACHINE_H + +#define ALIGNMENT 8 + +#endif diff --git a/EdkModulePkg/Universal/Variable/Pei/Variable.c b/EdkModulePkg/Universal/Variable/Pei/Variable.c new file mode 100644 index 0000000000..b2286c1860 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/Pei/Variable.c @@ -0,0 +1,563 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Variable.c + +Abstract: + + Framework PEIM to provide the Variable functionality + +--*/ + + +#include +#include +#include + +// +// Module globals +// +static EFI_PEI_READ_ONLY_VARIABLE_PPI mVariablePpi = { + PeiGetVariable, + PeiGetNextVariableName +}; + +static EFI_PEI_PPI_DESCRIPTOR mPpiListVariable = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiReadOnlyVariablePpiGuid, + &mVariablePpi +}; + +EFI_GUID gEfiVariableIndexTableGuid = EFI_VARIABLE_INDEX_TABLE_GUID; + +EFI_STATUS +EFIAPI +PeimInitializeVariableServices ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Provide the functionality of the variable services. + +Arguments: + + FfsHeadher - The FFS file header + PeiServices - General purpose services available to every PEIM. + +Returns: + + Status - EFI_SUCCESS if the interface could be successfully + installed + +--*/ +{ + // + // Publish the variable capability to other modules + // + return (**PeiServices).InstallPpi (PeiServices, &mPpiListVariable); + +} + +VARIABLE_HEADER * +GetNextVariablePtr ( + IN VARIABLE_HEADER *Variable + ) +/*++ + +Routine Description: + + This code checks if variable header is valid or not. + +Arguments: + Variable Pointer to the Variable Header. + +Returns: + TRUE Variable header is valid. + FALSE Variable header is not valid. + +--*/ +{ + return (VARIABLE_HEADER *) ((UINTN) GET_VARIABLE_DATA_PTR (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize)); +} + +BOOLEAN +EFIAPI +IsValidVariableHeader ( + IN VARIABLE_HEADER *Variable + ) +/*++ + +Routine Description: + + This code checks if variable header is valid or not. + +Arguments: + Variable Pointer to the Variable Header. + +Returns: + TRUE Variable header is valid. + FALSE Variable header is not valid. + +--*/ +{ + if (Variable == NULL || + Variable->StartId != VARIABLE_DATA || + (sizeof (VARIABLE_HEADER) + Variable->DataSize + Variable->NameSize) > MAX_VARIABLE_SIZE + ) { + return FALSE; + } + + return TRUE; +} + +VARIABLE_STORE_STATUS +EFIAPI +GetVariableStoreStatus ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ) +/*++ + +Routine Description: + + This code gets the pointer to the variable name. + +Arguments: + + VarStoreHeader Pointer to the Variable Store Header. + +Returns: + + EfiRaw Variable store is raw + EfiValid Variable store is valid + EfiInvalid Variable store is invalid + +--*/ +{ + if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE && + VarStoreHeader->Format == VARIABLE_STORE_FORMATTED && + VarStoreHeader->State == VARIABLE_STORE_HEALTHY + ) { + + return EfiValid; + } + + if (VarStoreHeader->Signature == 0xffffffff && + VarStoreHeader->Size == 0xffffffff && + VarStoreHeader->Format == 0xff && + VarStoreHeader->State == 0xff + ) { + + return EfiRaw; + } else { + return EfiInvalid; + } +} + +EFI_STATUS +CompareWithValidVariable ( + IN VARIABLE_HEADER *Variable, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack + ) +/*++ + +Routine Description: + + This function compares a variable with variable entries in database + +Arguments: + + Variable - Pointer to the variable in our database + VariableName - Name of the variable to compare to 'Variable' + VendorGuid - GUID of the variable to compare to 'Variable' + PtrTrack - Variable Track Pointer structure that contains + Variable Information. + +Returns: + + EFI_SUCCESS - Found match variable + EFI_NOT_FOUND - Variable not found + +--*/ +{ + if (VariableName[0] == 0) { + PtrTrack->CurrPtr = Variable; + return EFI_SUCCESS; + } else { + // + // Don't use CompareGuid function here for performance reasons. + // Instead we compare the GUID a UINT32 at a time and branch + // on the first failed comparison. + // + if ((((INT32 *) VendorGuid)[0] == ((INT32 *) &Variable->VendorGuid)[0]) && + (((INT32 *) VendorGuid)[1] == ((INT32 *) &Variable->VendorGuid)[1]) && + (((INT32 *) VendorGuid)[2] == ((INT32 *) &Variable->VendorGuid)[2]) && + (((INT32 *) VendorGuid)[3] == ((INT32 *) &Variable->VendorGuid)[3]) + ) { + if (!StrCmp (VariableName, GET_VARIABLE_NAME_PTR (Variable))) { + PtrTrack->CurrPtr = Variable; + return EFI_SUCCESS; + } + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +FindVariable ( + IN EFI_PEI_SERVICES **PeiServices, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack + ) +/*++ + +Routine Description: + + This code finds variable in storage blocks (Non-Volatile) + +Arguments: + + PeiServices - General purpose services available to every PEIM. + VariableName - Name of the variable to be found + VendorGuid - Vendor GUID to be found. + PtrTrack - Variable Track Pointer structure that contains + Variable Information. + +Returns: + + EFI_SUCCESS - Variable found successfully + EFI_NOT_FOUND - Variable not found + EFI_INVALID_PARAMETER - Invalid variable name + +--*/ +{ + PEI_FLASH_MAP_PPI *FlashMapPpi; + EFI_FLASH_SUBAREA_ENTRY *VariableStoreEntry; + UINT32 NumEntries; + EFI_HOB_GUID_TYPE *GuidHob; + VARIABLE_STORE_HEADER *VariableStoreHeader; + VARIABLE_HEADER *Variable; + + EFI_STATUS Status; + + VARIABLE_HEADER *MaxIndex; + VARIABLE_INDEX_TABLE *IndexTable; + UINT32 Count; + + if (VariableName != 0 && VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // No Variable Address equals zero, so 0 as initial value is safe. + // + MaxIndex = 0; + + GuidHob = GetFirstGuidHob (&gEfiVariableIndexTableGuid); + if (GuidHob == NULL) { + IndexTable = BuildGuidHob (&gEfiVariableIndexTableGuid, sizeof (VARIABLE_INDEX_TABLE)); + IndexTable->Length = 0; + IndexTable->StartPtr = NULL; + IndexTable->EndPtr = NULL; + IndexTable->GoneThrough = 0; + } else { + IndexTable = GET_GUID_HOB_DATA (GuidHob); + for (Count = 0; Count < IndexTable->Length; Count++) + { +#if ALIGNMENT <= 1 + MaxIndex = (VARIABLE_HEADER *) (UINTN) (IndexTable->Index[Count] + ((UINTN) IndexTable->StartPtr & 0xFFFF0000)); +#else +#if ALIGNMENT >= 4 + MaxIndex = (VARIABLE_HEADER *) (UINTN) ((((UINT32)IndexTable->Index[Count]) << 2) + ((UINT32)(UINTN)IndexTable->StartPtr & 0xFFFC0000) ); +#endif +#endif + if (CompareWithValidVariable (MaxIndex, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) { + PtrTrack->StartPtr = IndexTable->StartPtr; + PtrTrack->EndPtr = IndexTable->EndPtr; + + return EFI_SUCCESS; + } + } + + if (IndexTable->GoneThrough) { + return EFI_NOT_FOUND; + } + } + // + // If not found in HOB, then let's start from the MaxIndex we've found. + // + if (MaxIndex != NULL) { + Variable = GetNextVariablePtr (MaxIndex); + } else { + if (IndexTable->StartPtr || IndexTable->EndPtr) { + Variable = IndexTable->StartPtr; + } else { + // + // Locate FlashMap PPI + // + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPeiFlashMapPpiGuid, + 0, + NULL, + (VOID **) &FlashMapPpi + ); + ASSERT_EFI_ERROR (Status); + + // + // Get flash area info for variables + // + Status = FlashMapPpi->GetAreaInfo ( + PeiServices, + FlashMapPpi, + EFI_FLASH_AREA_EFI_VARIABLES, + NULL, + &NumEntries, + &VariableStoreEntry + ); + + // + // Currently only one non-volatile variable store is supported + // + if (NumEntries != 1) { + return EFI_UNSUPPORTED; + } + + VariableStoreHeader = (VARIABLE_STORE_HEADER *) (UINTN) (VariableStoreEntry->Base); + + if (GetVariableStoreStatus (VariableStoreHeader) != EfiValid) { + return EFI_UNSUPPORTED; + } + + if (~VariableStoreHeader->Size == 0) { + return EFI_NOT_FOUND; + } + // + // Find the variable by walk through non-volatile variable store + // + IndexTable->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader + 1); + IndexTable->EndPtr = (VARIABLE_HEADER *) ((UINTN) VariableStoreHeader + VariableStoreHeader->Size); + + // + // Start Pointers for the variable. + // Actual Data Pointer where data can be written. + // + Variable = IndexTable->StartPtr; + } + } + // + // Find the variable by walk through non-volatile variable store + // + PtrTrack->StartPtr = IndexTable->StartPtr; + PtrTrack->EndPtr = IndexTable->EndPtr; + + while (IsValidVariableHeader (Variable) && (Variable <= IndexTable->EndPtr)) { + if (Variable->State == VAR_ADDED) { + // + // Record Variable in VariableIndex HOB + // + if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) + { +#if ALIGNMENT <= 1 + IndexTable->Index[IndexTable->Length++] = (UINT16) (UINTN) Variable; +#else +#if ALIGNMENT >= 4 + IndexTable->Index[IndexTable->Length++] = (UINT16) (((UINT32)(UINTN) Variable) >> 2); +#endif +#endif + } + + if (CompareWithValidVariable (Variable, VariableName, VendorGuid, PtrTrack) == EFI_SUCCESS) { + return EFI_SUCCESS; + } + } + + Variable = GetNextVariablePtr (Variable); + } + // + // If gone through the VariableStore, that means we never find in Firmware any more. + // + if (IndexTable->Length < VARIABLE_INDEX_TABLE_VOLUME) { + IndexTable->GoneThrough = 1; + } + + PtrTrack->CurrPtr = NULL; + + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +PeiGetVariable ( + IN EFI_PEI_SERVICES **PeiServices, + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +/*++ + +Routine Description: + + Provide the read variable functionality of the variable services. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + + VariableName - The variable name + + VendorGuid - The vendor's GUID + + Attributes - Pointer to the attribute + + DataSize - Size of data + + Data - Pointer to data + +Returns: + + EFI_SUCCESS - The interface could be successfully installed + + EFI_NOT_FOUND - The variable could not be discovered + + EFI_BUFFER_TOO_SMALL - The caller buffer is not large enough + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + UINTN VarDataSize; + EFI_STATUS Status; + + if (VariableName == NULL || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Find existing variable + // + Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable); + + if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) { + return Status; + } + // + // Get data size + // + VarDataSize = Variable.CurrPtr->DataSize; + if (*DataSize >= VarDataSize) { + (*PeiServices)->CopyMem (Data, GET_VARIABLE_DATA_PTR (Variable.CurrPtr), VarDataSize); + + if (Attributes != NULL) { + *Attributes = Variable.CurrPtr->Attributes; + } + + *DataSize = VarDataSize; + return EFI_SUCCESS; + } else { + *DataSize = VarDataSize; + return EFI_BUFFER_TOO_SMALL; + } +} + +EFI_STATUS +EFIAPI +PeiGetNextVariableName ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +/*++ + +Routine Description: + + Provide the get next variable functionality of the variable services. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + VariabvleNameSize - The variable name's size. + VariableName - A pointer to the variable's name. + VendorGuid - A pointer to the EFI_GUID structure. + + VariableNameSize - Size of the variable name + + VariableName - The variable name + + VendorGuid - The vendor's GUID + +Returns: + + EFI_SUCCESS - The interface could be successfully installed + + EFI_NOT_FOUND - The variable could not be discovered + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + UINTN VarNameSize; + EFI_STATUS Status; + + if (VariableName == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FindVariable (PeiServices, VariableName, VendorGuid, &Variable); + + if (Variable.CurrPtr == NULL || Status != EFI_SUCCESS) { + return Status; + } + + if (VariableName[0] != 0) { + // + // If variable name is not NULL, get next variable + // + Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); + } + + while (!(Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL)) { + if (IsValidVariableHeader (Variable.CurrPtr)) { + if (Variable.CurrPtr->State == VAR_ADDED) { + VarNameSize = (UINTN) Variable.CurrPtr->NameSize; + if (VarNameSize <= *VariableNameSize) { + (*PeiServices)->CopyMem (VariableName, GET_VARIABLE_NAME_PTR (Variable.CurrPtr), VarNameSize); + + (*PeiServices)->CopyMem (VendorGuid, &Variable.CurrPtr->VendorGuid, sizeof (EFI_GUID)); + + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + + *VariableNameSize = VarNameSize; + return Status; + // + // Variable is found + // + } else { + Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); + } + } else { + break; + } + } + + return EFI_NOT_FOUND; +} diff --git a/EdkModulePkg/Universal/Variable/Pei/Variable.dxs b/EdkModulePkg/Universal/Variable/Pei/Variable.dxs new file mode 100644 index 0000000000..d16ad10db2 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/Pei/Variable.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Variable.dxs + +Abstract: + + Dependency expression file for Variable PEIM. + +--*/ +#include +#include + +DEPENDENCY_START + PEI_FLASH_MAP_PPI_GUID +DEPENDENCY_END + + diff --git a/EdkModulePkg/Universal/Variable/Pei/Variable.h b/EdkModulePkg/Universal/Variable/Pei/Variable.h new file mode 100644 index 0000000000..2a6f861def --- /dev/null +++ b/EdkModulePkg/Universal/Variable/Pei/Variable.h @@ -0,0 +1,154 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Variable.h + +Abstract: + + Tiano PEIM to provide the variable functionality + +--*/ + +#ifndef _PEI_VARIABLE_H +#define _PEI_VARIABLE_H + +// +// BugBug: We need relcate the head file. +// +#include + +#define ALIGNMENT 1 + +// +// Define GET_PAD_SIZE to optimize compiler +// +#if ((ALIGNMENT == 0) || (ALIGNMENT == 1)) +#define GET_PAD_SIZE(a) (0) +#else +#define GET_PAD_SIZE(a) (((~a) + 1) & (ALIGNMENT - 1)) +#endif + +#define GET_VARIABLE_NAME_PTR(a) (CHAR16 *) ((UINTN) (a) + sizeof (VARIABLE_HEADER)) + +#define GET_VARIABLE_DATA_PTR(a) \ + (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (a) + (a)->NameSize + GET_PAD_SIZE ((a)->NameSize)) + +typedef struct { + VARIABLE_HEADER *CurrPtr; + VARIABLE_HEADER *EndPtr; + VARIABLE_HEADER *StartPtr; +} VARIABLE_POINTER_TRACK; + +#define VARIABLE_INDEX_TABLE_VOLUME 122 + +#define EFI_VARIABLE_INDEX_TABLE_GUID \ + { 0x8cfdb8c8, 0xd6b2, 0x40f3, { 0x8e, 0x97, 0x02, 0x30, 0x7c, 0xc9, 0x8b, 0x7c } } + +typedef struct { + UINT16 Length; + UINT16 GoneThrough; + VARIABLE_HEADER *EndPtr; + VARIABLE_HEADER *StartPtr; + UINT16 Index[VARIABLE_INDEX_TABLE_VOLUME]; +} VARIABLE_INDEX_TABLE; + +extern EFI_GUID gEfiVariableIndexTableGuid; + +// +// Functions +// +EFI_STATUS +EFIAPI +PeimInitializeVariableServices ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + FfsHeader - TODO: add argument description + PeiServices - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PeiGetVariable ( + IN EFI_PEI_SERVICES **PeiServices, + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PeiServices - TODO: add argument description + VariableName - TODO: add argument description + VendorGuid - TODO: add argument description + Attributes - TODO: add argument description + DataSize - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +PeiGetNextVariableName ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PeiServices - TODO: add argument description + VariableNameSize - TODO: add argument description + VariableName - TODO: add argument description + VendorGuid - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif // _PEI_VARIABLE_H diff --git a/EdkModulePkg/Universal/Variable/Pei/Variable.mbd b/EdkModulePkg/Universal/Variable/Pei/Variable.mbd new file mode 100644 index 0000000000..036758dc62 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/Pei/Variable.mbd @@ -0,0 +1,43 @@ + + + + + PeiVariable + 34C8C28F-B61C-45a2-8F2E-89E46BECC63B + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + PeiMemoryLib + PeiCoreLib + PeiServicesTablePointerLib + PeiHobLib + PeimEntryPoint + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/Variable/Pei/Variable.msa b/EdkModulePkg/Universal/Variable/Pei/Variable.msa new file mode 100644 index 0000000000..79c086bdb1 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/Pei/Variable.msa @@ -0,0 +1,57 @@ + + + + + PeiVariable + PEIM + PE32_PEIM + 34C8C28F-B61C-45a2-8F2E-89E46BECC63B + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + PeimEntryPoint + PeiCoreLib + HobLib + + + Variable.c + Variable.dxs + + + MdePkg + EdkModulePkg + + + FlashMap + ReadOnlyVariable + + + + PeimInitializeVariableServices + + + diff --git a/EdkModulePkg/Universal/Variable/Pei/build.xml b/EdkModulePkg/Universal/Variable/Pei/build.xml new file mode 100644 index 0000000000..c6b57f9f77 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/Pei/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Variable/Pei/x64/VarMachine.h b/EdkModulePkg/Universal/Variable/Pei/x64/VarMachine.h new file mode 100644 index 0000000000..83031e9788 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/Pei/x64/VarMachine.h @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + VarMachine.h + +Abstract: + + Variable Machine Type + +--*/ + +#ifndef _VAR_MACHINE_H +#define _VAR_MACHINE_H + +#define ALIGNMENT 1 + +#endif diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.c b/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.c new file mode 100644 index 0000000000..beb404f42c --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.c @@ -0,0 +1,754 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EmuVariable.c + +Abstract: + +Revision History + +--*/ + +#include "Variable.h" + +// +// Don't use module globals after the SetVirtualAddress map is signaled +// +ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal; + +UINT32 +EFIAPI +ArrayLength ( + IN CHAR16 *String + ) +/*++ + +Routine Description: + + Determine the length of null terminated char16 array. + +Arguments: + + String Null-terminated CHAR16 array pointer. + +Returns: + + UINT32 Number of bytes in the string, including the double NULL at the end; + +--*/ +{ + UINT32 Count; + + if (NULL == String) { + return 0; + } + + Count = 0; + + while (0 != String[Count]) { + Count++; + } + + return (Count * 2) + 2; +} + +UINTN +EFIAPI +GetPadSize ( + IN UINTN Value + ) +/*++ + +Routine Description: + + This function return the pad size for alignment + +Arguments: + + Value The value need to align + +Returns: + + Pad size for value + +--*/ +{ + // + // If alignment is 0 or 1, means no alignment required + // + if (ALIGNMENT == 0 || ALIGNMENT == 1) { + return 0; + } + + return ALIGNMENT - (Value % ALIGNMENT); +} + +VARIABLE_STORE_STATUS +EFIAPI +GetVariableStoreStatus ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ) +/*++ + +Routine Description: + + This code gets the pointer to the variable name. + +Arguments: + + VarStoreHeader Pointer to the Variable Store Header. + +Returns: + + EfiHealthy Variable store is healthy + EfiRaw Variable store is raw + EfiInvalid Variable store is invalid + +--*/ +{ + if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE && + VarStoreHeader->Format == VARIABLE_STORE_FORMATTED && + VarStoreHeader->State == VARIABLE_STORE_HEALTHY + ) { + + return EfiValid; + } else if (VarStoreHeader->Signature == 0xffffffff && + VarStoreHeader->Size == 0xffffffff && + VarStoreHeader->Format == 0xff && + VarStoreHeader->State == 0xff + ) { + + return EfiRaw; + } else { + return EfiInvalid; + } +} + +UINT8 * +EFIAPI +GetVariableDataPtr ( + IN VARIABLE_HEADER *Variable + ) +/*++ + +Routine Description: + + This code gets the pointer to the variable data. + +Arguments: + + Variable Pointer to the Variable Header. + +Returns: + + UINT8* Pointer to Variable Data + +--*/ +{ + if (Variable->StartId != VARIABLE_DATA) { + return NULL; + } + // + // Be careful about pad size for alignment + // + return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GetPadSize (Variable->NameSize)); +} + +VARIABLE_HEADER * +EFIAPI +GetNextVariablePtr ( + IN VARIABLE_HEADER *Variable + ) +/*++ + +Routine Description: + + This code gets the pointer to the next variable header. + +Arguments: + + Variable Pointer to the Variable Header. + +Returns: + + VARIABLE_HEADER* Pointer to next variable header. + +--*/ +{ + VARIABLE_HEADER *VarHeader; + + if (Variable->StartId != VARIABLE_DATA) { + return NULL; + } + // + // Be careful about pad size for alignment + // + VarHeader = (VARIABLE_HEADER *) (GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize)); + + if (VarHeader->StartId != VARIABLE_DATA || + (sizeof (VARIABLE_HEADER) + VarHeader->DataSize + VarHeader->NameSize) > MAX_VARIABLE_SIZE + ) { + return NULL; + } + + return VarHeader; +} + +VARIABLE_HEADER * +EFIAPI +GetEndPointer ( + IN VARIABLE_STORE_HEADER *VolHeader + ) +/*++ + +Routine Description: + + This code gets the pointer to the last variable memory pointer byte + +Arguments: + + Variable Pointer to the Variable Header. + +Returns: + + VARIABLE_HEADER* Pointer to last unavailable Variable Header + +--*/ +{ + // + // The end of variable store + // + return (VARIABLE_HEADER *) ((UINTN) VolHeader + VolHeader->Size); +} + +EFI_STATUS +EFIAPI +FindVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack, + IN VARIABLE_GLOBAL *Global + ) +/*++ + +Routine Description: + + This code finds variable in storage blocks (Volatile or Non-Volatile) + +Arguments: + + VariableName Name of the variable to be found + VendorGuid Vendor GUID to be found. + PtrTrack Variable Track Pointer structure that contains + Variable Information. + Contains the pointer of Variable header. + Global VARIABLE_GLOBAL pointer + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_HEADER *Variable[2]; + VARIABLE_STORE_HEADER *VariableStoreHeader[2]; + UINTN Index; + + // + // 0: Non-Volatile, 1: Volatile + // + VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase); + VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase); + + // + // Start Pointers for the variable. + // Actual Data Pointer where data can be written. + // + Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1); + Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1); + + if (VariableName[0] != 0 && VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Find the variable by walk through non-volatile and volatile variable store + // + for (Index = 0; Index < 2; Index++) { + PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1); + PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]); + + while ((Variable[Index] != NULL) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) { + if (Variable[Index]->StartId == VARIABLE_DATA && Variable[Index]->State == VAR_ADDED) { + if (!(EfiAtRuntime () && !(Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) { + if (VariableName[0] == 0) { + PtrTrack->CurrPtr = Variable[Index]; + PtrTrack->Volatile = (BOOLEAN) Index; + return EFI_SUCCESS; + } else { + if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) { + if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), ArrayLength (VariableName))) { + PtrTrack->CurrPtr = Variable[Index]; + PtrTrack->Volatile = (BOOLEAN) Index; + return EFI_SUCCESS; + } + } + } + } + } + + Variable[Index] = GetNextVariablePtr (Variable[Index]); + } + } + PtrTrack->CurrPtr = NULL; + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +GetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data, + IN VARIABLE_GLOBAL * Global, + IN UINT32 Instance + ) +/*++ + +Routine Description: + + This code finds variable in storage blocks (Volatile or Non-Volatile) + +Arguments: + + VariableName Name of Variable to be found + VendorGuid Variable vendor GUID + Attributes OPTIONAL Attribute value of the variable found + DataSize Size of Data found. If size is less than the + data, this value contains the required size. + Data Data pointer + Global Pointer to VARIABLE_GLOBAL structure + Instance Instance of the Firmware Volume. + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + UINTN VarDataSize; + EFI_STATUS Status; + + if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Find existing variable + // + Status = FindVariable (VariableName, VendorGuid, &Variable, Global); + + if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) { + return Status; + } + // + // Get data size + // + VarDataSize = Variable.CurrPtr->DataSize; + if (*DataSize >= VarDataSize) { + CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize); + if (Attributes) { + *Attributes = Variable.CurrPtr->Attributes; + } + + *DataSize = VarDataSize; + return EFI_SUCCESS; + } else { + *DataSize = VarDataSize; + return EFI_BUFFER_TOO_SMALL; + } +} + +EFI_STATUS +EFIAPI +GetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid, + IN VARIABLE_GLOBAL *Global, + IN UINT32 Instance + ) +/*++ + +Routine Description: + + This code Finds the Next available variable + +Arguments: + + VariableNameSize Size of the variable + VariableName Pointer to variable name + VendorGuid Variable Vendor Guid + Global VARIABLE_GLOBAL structure pointer. + Instance FV instance + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + UINTN VarNameSize; + EFI_STATUS Status; + + if (VariableNameSize == NULL || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FindVariable (VariableName, VendorGuid, &Variable, Global); + + if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) { + return Status; + } + + while (TRUE) { + if (VariableName[0] != 0) { + // + // If variable name is not NULL, get next variable + // + Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); + } + // + // If both volatile and non-volatile variable store are parsed, + // return not found + // + if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) { + Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1)); + if (Variable.Volatile) { + Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER))); + Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase)); + } else { + return EFI_NOT_FOUND; + } + + Variable.CurrPtr = Variable.StartPtr; + if (Variable.CurrPtr->StartId != VARIABLE_DATA) { + continue; + } + } + // + // Variable is found + // + if (Variable.CurrPtr->StartId == VARIABLE_DATA && Variable.CurrPtr->State == VAR_ADDED) { + if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) { + VarNameSize = Variable.CurrPtr->NameSize; + if (VarNameSize <= *VariableNameSize) { + CopyMem ( + VariableName, + GET_VARIABLE_NAME_PTR (Variable.CurrPtr), + VarNameSize + ); + CopyMem ( + VendorGuid, + &Variable.CurrPtr->VendorGuid, + sizeof (EFI_GUID) + ); + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + + *VariableNameSize = VarNameSize; + return Status; + } + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +SetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data, + IN VARIABLE_GLOBAL *Global, + IN UINTN *VolatileOffset, + IN UINTN *NonVolatileOffset, + IN UINT32 Instance + ) +/*++ + +Routine Description: + + This code sets variable in storage blocks (Volatile or Non-Volatile) + +Arguments: + + VariableName Name of Variable to be found + VendorGuid Variable vendor GUID + Attributes Attribute value of the variable found + DataSize Size of Data found. If size is less than the + data, this value contains the required size. + Data Data pointer + Global Pointer to VARIABLE_GLOBAL structure + VolatileOffset The offset of last volatile variable + NonVolatileOffset The offset of last non-volatile variable + Instance Instance of the Firmware Volume. + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + EFI_STATUS Status; + VARIABLE_HEADER *NextVariable; + UINTN VarNameSize; + UINTN VarNameOffset; + UINTN VarDataOffset; + UINTN VarSize; + + if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FindVariable (VariableName, VendorGuid, &Variable, Global); + + if (Status == EFI_INVALID_PARAMETER) { + return Status; + } + // + // The size of the VariableName, including the Unicode Null in bytes plus + // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes. + // + else if (sizeof (VARIABLE_HEADER) + (ArrayLength (VariableName) + DataSize) > MAX_VARIABLE_SIZE) { + return EFI_INVALID_PARAMETER; + } + // + // Make sure if runtime bit is set, boot service bit is set also + // + else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS + ) { + return EFI_INVALID_PARAMETER; + } + // + // Runtime but Attribute is not Runtime + // + else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) { + return EFI_INVALID_PARAMETER; + } + // + // Cannot set volatile variable in Runtime + // + else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) { + return EFI_INVALID_PARAMETER; + } + // + // Setting a data variable with no access, or zero DataSize attributes + // specified causes it to be deleted. + // + else if (DataSize == 0 || Attributes == 0) { + if (!EFI_ERROR (Status)) { + Variable.CurrPtr->State &= VAR_DELETED; + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; + } else { + if (!EFI_ERROR (Status)) { + // + // If the variable is marked valid and the same data has been passed in + // then return to the caller immediately. + // + if (Variable.CurrPtr->DataSize == DataSize && + !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize) + ) { + return EFI_SUCCESS; + } else if (Variable.CurrPtr->State == VAR_ADDED) { + // + // Mark the old variable as in delete transition + // + Variable.CurrPtr->State &= VAR_IN_DELETED_TRANSITION; + } + } + // + // Create a new variable and copy the data. + // + VarNameOffset = sizeof (VARIABLE_HEADER); + VarNameSize = ArrayLength (VariableName); + VarDataOffset = VarNameOffset + VarNameSize + GetPadSize (VarNameSize); + VarSize = VarDataOffset + DataSize + GetPadSize (DataSize); + + if (Attributes & EFI_VARIABLE_NON_VOLATILE) { + if ((UINT32) (VarSize +*NonVolatileOffset) > + ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size + ) { + return EFI_OUT_OF_RESOURCES; + } + + NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*NonVolatileOffset + (UINTN) Global->NonVolatileVariableBase); + *NonVolatileOffset = *NonVolatileOffset + VarSize; + } else { + if (EfiAtRuntime ()) { + return EFI_INVALID_PARAMETER; + } + + if ((UINT32) (VarSize +*VolatileOffset) > + ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size + ) { + return EFI_OUT_OF_RESOURCES; + } + + NextVariable = (VARIABLE_HEADER *) (UINT8 *) (*VolatileOffset + (UINTN) Global->VolatileVariableBase); + *VolatileOffset = *VolatileOffset + VarSize; + } + + NextVariable->StartId = VARIABLE_DATA; + NextVariable->Attributes = Attributes; + NextVariable->State = VAR_ADDED; + NextVariable->Reserved = 0; + + // + // There will be pad bytes after Data, the NextVariable->NameSize and + // NextVariable->NameSize should not include pad size so that variable + // service can get actual size in GetVariable + // + NextVariable->NameSize = (UINT32)VarNameSize; + NextVariable->DataSize = (UINT32)DataSize; + + CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID)); + CopyMem ( + (UINT8 *) ((UINTN) NextVariable + VarNameOffset), + VariableName, + VarNameSize + ); + CopyMem ( + (UINT8 *) ((UINTN) NextVariable + VarDataOffset), + Data, + DataSize + ); + + // + // Mark the old variable as deleted + // + if (!EFI_ERROR (Status)) { + Variable.CurrPtr->State &= VAR_DELETED; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +InitializeVariableStore ( + OUT EFI_PHYSICAL_ADDRESS *VariableBase, + OUT UINTN *LastVariableOffset + ) +/*++ + +Routine Description: + This function initializes variable store + +Arguments: + +Returns: + +--*/ +{ + VARIABLE_STORE_HEADER *VariableStore; + + // + // Allocate memory for volatile variable store + // + VariableStore = (VARIABLE_STORE_HEADER *) AllocateRuntimePool ( + VARIABLE_STORE_SIZE + ); + if (NULL == VariableStore) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (VariableStore, VARIABLE_STORE_SIZE, 0xff); + + // + // Variable Specific Data + // + *VariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VariableStore; + *LastVariableOffset = sizeof (VARIABLE_STORE_HEADER); + + VariableStore->Signature = VARIABLE_STORE_SIGNATURE; + VariableStore->Size = VARIABLE_STORE_SIZE; + VariableStore->Format = VARIABLE_STORE_FORMATTED; + VariableStore->State = VARIABLE_STORE_HEALTHY; + VariableStore->Reserved = 0; + VariableStore->Reserved1 = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VariableCommonInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This function does common initialization for variable services + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + + // + // Allocate memory for mVariableModuleGlobal + // + mVariableModuleGlobal = (ESAL_VARIABLE_GLOBAL *) AllocateRuntimePool ( + sizeof (ESAL_VARIABLE_GLOBAL) + ); + if (NULL == mVariableModuleGlobal) { + return EFI_OUT_OF_RESOURCES; + } + // + // Intialize volatile variable store + // + Status = InitializeVariableStore ( + &mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase, + &mVariableModuleGlobal->VolatileLastVariableOffset + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Intialize non volatile variable store + // + Status = InitializeVariableStore ( + &mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase, + &mVariableModuleGlobal->NonVolatileLastVariableOffset + ); + + return Status; +} diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.dxs b/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.dxs new file mode 100644 index 0000000000..51c93d7657 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.dxs @@ -0,0 +1,25 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EmuVariable.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include "DxeDepex.h" + +DEPENDENCY_START + TRUE +DEPENDENCY_END \ No newline at end of file diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.mbd b/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.mbd new file mode 100644 index 0000000000..4cc2c2085d --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.mbd @@ -0,0 +1,45 @@ + + + + + EmuVariable + CBD2E4D5-7068-4FF5-B866-9822B4AD8D60 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-23 16:05 + + + UefiBootServicesTableLib + BaseMemoryLib + BaseDebugLibReportStatusCode + UefiDriverEntryPoint + EdkDxeRuntimeDriverLib + DxeMemoryAllocationLib + BaseLib + DxeReportStatusCodeLib + + EdkDxeSalLib + + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.msa b/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.msa new file mode 100644 index 0000000000..5a7a5f8447 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/EmuVariable.msa @@ -0,0 +1,73 @@ + + + + + EmuVariable + DXE_RUNTIME_DRIVER + RT_DRIVER + CBD2E4D5-7068-4FF5-B866-9822B4AD8D60 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-23 16:05 + + + BaseLib + BaseMemoryLib + MemoryAllocationLib + DebugLib + DxeRuntimeDriverLib + UefiDriverEntryPoint + EdkDxeSalLib + UefiBootServicesTableLib + + + EmuVariable.c + EmuVariable.dxs + + ..\Ia32\Ia32Variable.c + + + ..\x64\x64Variable.c + + + ..\Ipf\IpfVariable.c + + + + MdePkg + EdkModulePkg + + + VariableWrite + Variable + VariableWrite + Variable + ExtendedSalVariableServices + ExtendedSalBootService + + + + VariableServiceInitialize + + + diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/build.xml b/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/build.xml new file mode 100644 index 0000000000..0035ab957b --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Emu/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Ia32Variable.dxs b/EdkModulePkg/Universal/Variable/RuntimeDxe/Ia32Variable.dxs new file mode 100644 index 0000000000..821e27df4a --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Ia32Variable.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Ia32Variable.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID AND + EFI_ALTERNATE_FV_BLOCK_GUID AND + EFI_FTW_LITE_PROTOCOL_GUID +DEPENDENCY_END \ No newline at end of file diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/InitVariable.c b/EdkModulePkg/Universal/Variable/RuntimeDxe/InitVariable.c new file mode 100644 index 0000000000..0ad86642ea --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/InitVariable.c @@ -0,0 +1,185 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + InitVariable.c + +Abstract: + +Revision History + +--*/ + +#include "Variable.h" + +// +// Don't use module globals after the SetVirtualAddress map is signaled +// +extern ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal; + +EFI_STATUS +EFIAPI +RuntimeServiceGetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return GetVariable ( + VariableName, + VendorGuid, + Attributes OPTIONAL, + DataSize, + Data, + &mVariableModuleGlobal->VariableBase[Physical], + mVariableModuleGlobal->FvbInstance + ); +} + +EFI_STATUS +EFIAPI +RuntimeServiceGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return GetNextVariableName ( + VariableNameSize, + VariableName, + VendorGuid, + &mVariableModuleGlobal->VariableBase[Physical], + mVariableModuleGlobal->FvbInstance + ); +} + +EFI_STATUS +EFIAPI +RuntimeServiceSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + return SetVariable ( + VariableName, + VendorGuid, + Attributes, + DataSize, + Data, + &mVariableModuleGlobal->VariableBase[Physical], + &mVariableModuleGlobal->VolatileLastVariableOffset, + &mVariableModuleGlobal->NonVolatileLastVariableOffset, + mVariableModuleGlobal->FvbInstance + ); +} + +VOID +EFIAPI +VariableClassAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EfiConvertPointer ( + 0x0, + (VOID **) &mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase + ); + EfiConvertPointer ( + 0x0, + (VOID **) &mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase + ); + EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal); +} + +EFI_STATUS +EFIAPI +VariableServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_HANDLE NewHandle; + EFI_STATUS Status; + + Status = VariableCommonInitialize (ImageHandle, SystemTable); + ASSERT_EFI_ERROR (Status); + + SystemTable->RuntimeServices->GetVariable = RuntimeServiceGetVariable; + SystemTable->RuntimeServices->GetNextVariableName = RuntimeServiceGetNextVariableName; + SystemTable->RuntimeServices->SetVariable = RuntimeServiceSetVariable; + + // + // Now install the Variable Runtime Architectural Protocol on a new handle + // + NewHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &NewHandle, + &gEfiVariableArchProtocolGuid, + NULL, + &gEfiVariableWriteArchProtocolGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Ipf/InitVariable.c b/EdkModulePkg/Universal/Variable/RuntimeDxe/Ipf/InitVariable.c new file mode 100644 index 0000000000..061e6db73d --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Ipf/InitVariable.c @@ -0,0 +1,167 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + IpfVariable.c + +Abstract: + +Revision History + +--*/ + +#include "Variable.h" + +// +// Don't use module globals after the SetVirtualAddress map is signaled +// +extern ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal; + +SAL_RETURN_REGS +EsalVariableCommonEntry ( + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8, + IN SAL_EXTENDED_SAL_PROC ExtendedSalProc, + IN BOOLEAN VirtualMode, + IN ESAL_VARIABLE_GLOBAL *Global + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + SAL_RETURN_REGS ReturnVal; + + switch (FunctionId) { + case EsalGetVariable: + ReturnVal.Status = GetVariable ( + (CHAR16 *) Arg2, + (EFI_GUID *) Arg3, + (UINT32 *) Arg4, + (UINTN *) Arg5, + (VOID *) Arg6, + &Global->VariableBase[VirtualMode], + Global->FvbInstance + ); + return ReturnVal; + + case EsalGetNextVariableName: + ReturnVal.Status = GetNextVariableName ( + (UINTN *) Arg2, + (CHAR16 *) Arg3, + (EFI_GUID *) Arg4, + &Global->VariableBase[VirtualMode], + Global->FvbInstance + ); + return ReturnVal; + + case EsalSetVariable: + ReturnVal.Status = SetVariable ( + (CHAR16 *) Arg2, + (EFI_GUID *) Arg3, + (UINT32) Arg4, + (UINTN) Arg5, + (VOID *) Arg6, + &Global->VariableBase[VirtualMode], + (UINTN *) &Global->VolatileLastVariableOffset, + (UINTN *) &Global->NonVolatileLastVariableOffset, + Global->FvbInstance + ); + return ReturnVal; + + default: + ReturnVal.Status = EFI_SAL_INVALID_ARGUMENT; + return ReturnVal; + } +} + + +VOID +VariableClassAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + CopyMem ( + &mVariableModuleGlobal->VariableBase[Virtual], + &mVariableModuleGlobal->VariableBase[Physical], + sizeof (VARIABLE_GLOBAL) + ); + + EfiConvertPointer ( + 0x0, + (VOID **) &mVariableModuleGlobal->VariableBase[Virtual].NonVolatileVariableBase + ); + EfiConvertPointer ( + 0x0, + (VOID **) &mVariableModuleGlobal->VariableBase[Virtual].VolatileVariableBase + ); + EfiConvertPointer (0x0, (VOID **) &mVariableModuleGlobal); +} + +EFI_STATUS +VariableServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + + Status = VariableCommonInitialize (ImageHandle, SystemTable); + ASSERT_EFI_ERROR (Status); + + // + // Register All the Functions with Extended Sal. + // + RegisterEsalClass ( + &gEfiExtendedSalVariableServicesProtocolGuid, + mVariableModuleGlobal, + EsalVariableCommonEntry, + EsalGetVariable, + EsalVariableCommonEntry, + EsalGetNextVariableName, + EsalVariableCommonEntry, + EsalSetVariable, + NULL + ); + + return EFI_SUCCESS; +} diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/IpfVariable.dxs b/EdkModulePkg/Universal/Variable/RuntimeDxe/IpfVariable.dxs new file mode 100644 index 0000000000..a11dae680c --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/IpfVariable.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + IpfVariable.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + EXTENDED_SAL_BOOT_SERVICE_PROTOCOL_GUID AND + EFI_EXTENDED_SAL_FV_BLOCK_SERVICES_PROTOCOL_GUID AND + EFI_FTW_LITE_PROTOCOL_GUID +DEPENDENCY_END \ No newline at end of file diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c new file mode 100644 index 0000000000..0d91520d97 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.c @@ -0,0 +1,1311 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Variable.c + +Abstract: + +Revision History + +--*/ + +#include "Variable.h" +#include "reclaim.h" + +// +// Don't use module globals after the SetVirtualAddress map is signaled +// +ESAL_VARIABLE_GLOBAL *mVariableModuleGlobal; + +UINT32 +EFIAPI +ArrayLength ( + IN CHAR16 *String + ) +/*++ + +Routine Description: + + Determine the length of null terminated char16 array. + +Arguments: + + String Null-terminated CHAR16 array pointer. + +Returns: + + UINT32 Number of bytes in the string, including the double NULL at the end; + +--*/ +{ + UINT32 Count; + + if (NULL == String) { + return 0; + } + + Count = 0; + + while (0 != String[Count]) { + Count++; + } + + return (Count * 2) + 2; +} + +BOOLEAN +EFIAPI +IsValidVariableHeader ( + IN VARIABLE_HEADER *Variable + ) +/*++ + +Routine Description: + + This code checks if variable header is valid or not. + +Arguments: + Variable Pointer to the Variable Header. + +Returns: + TRUE Variable header is valid. + FALSE Variable header is not valid. + +--*/ +{ + if (Variable == NULL || + Variable->StartId != VARIABLE_DATA || + (sizeof (VARIABLE_HEADER) + Variable->NameSize + Variable->DataSize) > MAX_VARIABLE_SIZE + ) { + return FALSE; + } + + return TRUE; +} + +EFI_STATUS +EFIAPI +UpdateVariableStore ( + IN VARIABLE_GLOBAL *Global, + IN BOOLEAN Volatile, + IN BOOLEAN SetByIndex, + IN UINTN Instance, + IN UINTN DataPtrIndex, + IN UINT32 DataSize, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + + This function writes data to the FWH at the correct LBA even if the LBAs + are fragmented. + +Arguments: + + Global Pointer to VARAIBLE_GLOBAL structure + Volatile If the Variable is Volatile or Non-Volatile + SetByIndex TRUE: Target pointer is given as index + FALSE: Target pointer is absolute + Instance Instance of FV Block services + DataPtrIndex Pointer to the Data from the end of VARIABLE_STORE_HEADER + structure + DataSize Size of data to be written. + Buffer Pointer to the buffer from which data is written + +Returns: + + EFI STATUS + +--*/ +{ + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + UINTN BlockIndex2; + UINTN LinearOffset; + UINTN CurrWriteSize; + UINTN CurrWritePtr; + UINT8 *CurrBuffer; + EFI_LBA LbaNumber; + UINTN Size; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + VARIABLE_STORE_HEADER *VolatileBase; + EFI_PHYSICAL_ADDRESS FvVolHdr; + EFI_PHYSICAL_ADDRESS DataPtr; + EFI_STATUS Status; + + FwVolHeader = NULL; + DataPtr = DataPtrIndex; + + // + // Check if the Data is Volatile + // + if (!Volatile) { + EfiFvbGetPhysicalAddress (Instance, &FvVolHdr); + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr); + // + // Data Pointer should point to the actual Address where data is to be + // written + // + if (SetByIndex) { + DataPtr += Global->NonVolatileVariableBase; + } + + if ((DataPtr + DataSize) >= ((EFI_PHYSICAL_ADDRESS) (UINTN) ((UINT8 *) FwVolHeader + FwVolHeader->FvLength))) { + return EFI_INVALID_PARAMETER; + } + } else { + // + // Data Pointer should point to the actual Address where data is to be + // written + // + VolatileBase = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase); + if (SetByIndex) { + DataPtr += Global->VolatileVariableBase; + } + + if ((DataPtr + DataSize) >= ((UINTN) ((UINT8 *) VolatileBase + VolatileBase->Size))) { + return EFI_INVALID_PARAMETER; + } + } + // + // If Volatile Variable just do a simple mem copy. + // + if (Volatile) { + CopyMem ((UINT8 *) ((UINTN) DataPtr), Buffer, DataSize); + return EFI_SUCCESS; + } + // + // If we are here we are dealing with Non-Volatile Variables + // + LinearOffset = (UINTN) FwVolHeader; + CurrWritePtr = (UINTN) DataPtr; + CurrWriteSize = DataSize; + CurrBuffer = Buffer; + LbaNumber = 0; + + if (CurrWritePtr < LinearOffset) { + return EFI_INVALID_PARAMETER; + } + + for (PtrBlockMapEntry = FwVolHeader->FvBlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { + for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) { + // + // Check to see if the Variable Writes are spanning through multiple + // blocks. + // + if ((CurrWritePtr >= LinearOffset) && (CurrWritePtr < LinearOffset + PtrBlockMapEntry->BlockLength)) { + if ((CurrWritePtr + CurrWriteSize) <= (LinearOffset + PtrBlockMapEntry->BlockLength)) { + Status = EfiFvbWriteBlock ( + Instance, + LbaNumber, + (UINTN) (CurrWritePtr - LinearOffset), + &CurrWriteSize, + CurrBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + } else { + Size = (UINT32) (LinearOffset + PtrBlockMapEntry->BlockLength - CurrWritePtr); + Status = EfiFvbWriteBlock ( + Instance, + LbaNumber, + (UINTN) (CurrWritePtr - LinearOffset), + &Size, + CurrBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + CurrWritePtr = LinearOffset + PtrBlockMapEntry->BlockLength; + CurrBuffer = CurrBuffer + Size; + CurrWriteSize = CurrWriteSize - Size; + } + } + + LinearOffset += PtrBlockMapEntry->BlockLength; + LbaNumber++; + } + } + + return EFI_SUCCESS; +} + +VARIABLE_STORE_STATUS +EFIAPI +GetVariableStoreStatus ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ) +/*++ + +Routine Description: + + This code gets the current status of Variable Store. + +Arguments: + + VarStoreHeader Pointer to the Variable Store Header. + +Returns: + + EfiRaw Variable store status is raw + EfiValid Variable store status is valid + EfiInvalid Variable store status is invalid + +--*/ +{ + if (VarStoreHeader->Signature == VARIABLE_STORE_SIGNATURE && + VarStoreHeader->Format == VARIABLE_STORE_FORMATTED && + VarStoreHeader->State == VARIABLE_STORE_HEALTHY + ) { + + return EfiValid; + } else if (VarStoreHeader->Signature == 0xffffffff && + VarStoreHeader->Size == 0xffffffff && + VarStoreHeader->Format == 0xff && + VarStoreHeader->State == 0xff + ) { + + return EfiRaw; + } else { + return EfiInvalid; + } +} + +UINT8 * +EFIAPI +GetVariableDataPtr ( + IN VARIABLE_HEADER *Variable + ) +/*++ + +Routine Description: + + This code gets the pointer to the variable data. + +Arguments: + + Variable Pointer to the Variable Header. + +Returns: + + UINT8* Pointer to Variable Data + +--*/ +{ + // + // Be careful about pad size for alignment + // + return (UINT8 *) ((UINTN) GET_VARIABLE_NAME_PTR (Variable) + Variable->NameSize + GET_PAD_SIZE (Variable->NameSize)); +} + +VARIABLE_HEADER * +EFIAPI +GetNextVariablePtr ( + IN VARIABLE_HEADER *Variable + ) +/*++ + +Routine Description: + + This code gets the pointer to the next variable header. + +Arguments: + + Variable Pointer to the Variable Header. + +Returns: + + VARIABLE_HEADER* Pointer to next variable header. + +--*/ +{ + if (!IsValidVariableHeader (Variable)) { + return NULL; + } + // + // Be careful about pad size for alignment + // + return (VARIABLE_HEADER *) ((UINTN) GetVariableDataPtr (Variable) + Variable->DataSize + GET_PAD_SIZE (Variable->DataSize)); +} + +VARIABLE_HEADER * +EFIAPI +GetEndPointer ( + IN VARIABLE_STORE_HEADER *VarStoreHeader + ) +/*++ + +Routine Description: + + This code gets the pointer to the last variable memory pointer byte + +Arguments: + + VarStoreHeader Pointer to the Variable Store Header. + +Returns: + + VARIABLE_HEADER* Pointer to last unavailable Variable Header + +--*/ +{ + // + // The end of variable store + // + return (VARIABLE_HEADER *) ((UINTN) VarStoreHeader + VarStoreHeader->Size); +} + +EFI_STATUS +EFIAPI +Reclaim ( + IN EFI_PHYSICAL_ADDRESS VariableBase, + OUT UINTN *LastVariableOffset, + IN BOOLEAN IsVolatile + ) +/*++ + +Routine Description: + + Variable store garbage collection and reclaim operation + +Arguments: + + VariableBase Base address of variable store + LastVariableOffset Offset of last variable + IsVolatile The variable store is volatile or not, + if it is non-volatile, need FTW + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_HEADER *Variable; + VARIABLE_HEADER *NextVariable; + VARIABLE_STORE_HEADER *VariableStoreHeader; + UINT8 *ValidBuffer; + UINTN ValidBufferSize; + UINTN VariableSize; + UINT8 *CurrPtr; + EFI_STATUS Status; + + VariableStoreHeader = (VARIABLE_STORE_HEADER *) ((UINTN) VariableBase); + + // + // Start Pointers for the variable. + // + Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1); + + ValidBufferSize = sizeof (VARIABLE_STORE_HEADER); + + while (IsValidVariableHeader (Variable)) { + NextVariable = GetNextVariablePtr (Variable); + if (Variable->State == VAR_ADDED) { + VariableSize = (UINTN) NextVariable - (UINTN) Variable; + ValidBufferSize += VariableSize; + } + + Variable = NextVariable; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + ValidBufferSize, + (VOID **) &ValidBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SetMem (ValidBuffer, ValidBufferSize, 0xff); + + CurrPtr = ValidBuffer; + + // + // Copy variable store header + // + CopyMem (CurrPtr, VariableStoreHeader, sizeof (VARIABLE_STORE_HEADER)); + CurrPtr += sizeof (VARIABLE_STORE_HEADER); + + // + // Start Pointers for the variable. + // + Variable = (VARIABLE_HEADER *) (VariableStoreHeader + 1); + + while (IsValidVariableHeader (Variable)) { + NextVariable = GetNextVariablePtr (Variable); + if (Variable->State == VAR_ADDED) { + VariableSize = (UINTN) NextVariable - (UINTN) Variable; + CopyMem (CurrPtr, (UINT8 *) Variable, VariableSize); + CurrPtr += VariableSize; + } + + Variable = NextVariable; + } + + if (IsVolatile) { + // + // If volatile variable store, just copy valid buffer + // + SetMem ((UINT8 *) (UINTN) VariableBase, VariableStoreHeader->Size, 0xff); + CopyMem ((UINT8 *) (UINTN) VariableBase, ValidBuffer, ValidBufferSize); + *LastVariableOffset = ValidBufferSize; + Status = EFI_SUCCESS; + } else { + // + // If non-volatile variable store, perform FTW here. + // + Status = FtwVariableSpace ( + VariableBase, + ValidBuffer, + ValidBufferSize + ); + if (!EFI_ERROR (Status)) { + *LastVariableOffset = ValidBufferSize; + } + } + + gBS->FreePool (ValidBuffer); + + if (EFI_ERROR (Status)) { + *LastVariableOffset = 0; + } + + return Status; +} + +EFI_STATUS +EFIAPI +FindVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT VARIABLE_POINTER_TRACK *PtrTrack, + IN VARIABLE_GLOBAL *Global + ) +/*++ + +Routine Description: + + This code finds variable in storage blocks (Volatile or Non-Volatile) + +Arguments: + + VariableName Name of the variable to be found + VendorGuid Vendor GUID to be found. + PtrTrack Variable Track Pointer structure that contains + Variable Information. + Contains the pointer of Variable header. + Global VARIABLE_GLOBAL pointer + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_HEADER *Variable[2]; + VARIABLE_STORE_HEADER *VariableStoreHeader[2]; + UINTN Index; + + // + // 0: Non-Volatile, 1: Volatile + // + VariableStoreHeader[0] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->NonVolatileVariableBase); + VariableStoreHeader[1] = (VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase); + + // + // Start Pointers for the variable. + // Actual Data Pointer where data can be written. + // + Variable[0] = (VARIABLE_HEADER *) (VariableStoreHeader[0] + 1); + Variable[1] = (VARIABLE_HEADER *) (VariableStoreHeader[1] + 1); + + if (VariableName[0] != 0 && VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Find the variable by walk through non-volatile and volatile variable store + // + for (Index = 0; Index < 2; Index++) { + PtrTrack->StartPtr = (VARIABLE_HEADER *) (VariableStoreHeader[Index] + 1); + PtrTrack->EndPtr = GetEndPointer (VariableStoreHeader[Index]); + + while (IsValidVariableHeader (Variable[Index]) && (Variable[Index] <= GetEndPointer (VariableStoreHeader[Index]))) { + if (Variable[Index]->State == VAR_ADDED) { + if (!(EfiAtRuntime () && !(Variable[Index]->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) { + if (VariableName[0] == 0) { + PtrTrack->CurrPtr = Variable[Index]; + PtrTrack->Volatile = (BOOLEAN) Index; + return EFI_SUCCESS; + } else { + if (CompareGuid (VendorGuid, &Variable[Index]->VendorGuid)) { + if (!CompareMem (VariableName, GET_VARIABLE_NAME_PTR (Variable[Index]), ArrayLength (VariableName))) { + PtrTrack->CurrPtr = Variable[Index]; + PtrTrack->Volatile = (BOOLEAN) Index; + return EFI_SUCCESS; + } + } + } + } + } + + Variable[Index] = GetNextVariablePtr (Variable[Index]); + } + // + // While (...) + // + } + // + // for (...) + // + PtrTrack->CurrPtr = NULL; + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +GetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data, + IN VARIABLE_GLOBAL * Global, + IN UINT32 Instance + ) +/*++ + +Routine Description: + + This code finds variable in storage blocks (Volatile or Non-Volatile) + +Arguments: + + VariableName Name of Variable to be found + VendorGuid Variable vendor GUID + Attributes OPTIONAL Attribute value of the variable found + DataSize Size of Data found. If size is less than the + data, this value contains the required size. + Data Data pointer + Global Pointer to VARIABLE_GLOBAL structure + Instance Instance of the Firmware Volume. + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + UINTN VarDataSize; + EFI_STATUS Status; + + if (VariableName == NULL || VendorGuid == NULL || DataSize == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Find existing variable + // + Status = FindVariable (VariableName, VendorGuid, &Variable, Global); + + if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) { + return Status; + } + // + // Get data size + // + VarDataSize = Variable.CurrPtr->DataSize; + if (*DataSize >= VarDataSize) { + if (Data == NULL) { + return EFI_INVALID_PARAMETER; + } + + CopyMem (Data, GetVariableDataPtr (Variable.CurrPtr), VarDataSize); + if (Attributes != NULL) { + *Attributes = Variable.CurrPtr->Attributes; + } + + *DataSize = VarDataSize; + return EFI_SUCCESS; + } else { + *DataSize = VarDataSize; + return EFI_BUFFER_TOO_SMALL; + } +} + +EFI_STATUS +EFIAPI +GetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid, + IN VARIABLE_GLOBAL *Global, + IN UINT32 Instance + ) +/*++ + +Routine Description: + + This code Finds the Next available variable + +Arguments: + + VariableNameSize Size of the variable + VariableName Pointer to variable name + VendorGuid Variable Vendor Guid + Global VARIABLE_GLOBAL structure pointer. + Instance FV instance + +Returns: + + EFI STATUS + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + UINTN VarNameSize; + EFI_STATUS Status; + + if (VariableNameSize == NULL || VariableName == NULL || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FindVariable (VariableName, VendorGuid, &Variable, Global); + + if (Variable.CurrPtr == NULL || EFI_ERROR (Status)) { + return Status; + } + + if (VariableName[0] != 0) { + // + // If variable name is not NULL, get next variable + // + Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); + } + + while (TRUE) { + // + // If both volatile and non-volatile variable store are parsed, + // return not found + // + if (Variable.CurrPtr >= Variable.EndPtr || Variable.CurrPtr == NULL) { + Variable.Volatile = (BOOLEAN) (Variable.Volatile ^ ((BOOLEAN) 0x1)); + if (Variable.Volatile) { + Variable.StartPtr = (VARIABLE_HEADER *) ((UINTN) (Global->VolatileVariableBase + sizeof (VARIABLE_STORE_HEADER))); + Variable.EndPtr = (VARIABLE_HEADER *) GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase)); + } else { + return EFI_NOT_FOUND; + } + + Variable.CurrPtr = Variable.StartPtr; + if (!IsValidVariableHeader (Variable.CurrPtr)) { + continue; + } + } + // + // Variable is found + // + if (IsValidVariableHeader (Variable.CurrPtr) && Variable.CurrPtr->State == VAR_ADDED) { + if (!(EfiAtRuntime () && !(Variable.CurrPtr->Attributes & EFI_VARIABLE_RUNTIME_ACCESS))) { + VarNameSize = Variable.CurrPtr->NameSize; + if (VarNameSize <= *VariableNameSize) { + CopyMem ( + VariableName, + GET_VARIABLE_NAME_PTR (Variable.CurrPtr), + VarNameSize + ); + CopyMem ( + VendorGuid, + &Variable.CurrPtr->VendorGuid, + sizeof (EFI_GUID) + ); + Status = EFI_SUCCESS; + } else { + Status = EFI_BUFFER_TOO_SMALL; + } + + *VariableNameSize = VarNameSize; + return Status; + } + } + + Variable.CurrPtr = GetNextVariablePtr (Variable.CurrPtr); + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +SetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data, + IN VARIABLE_GLOBAL *Global, + IN UINTN *VolatileOffset, + IN UINTN *NonVolatileOffset, + IN UINT32 Instance + ) +/*++ + +Routine Description: + + This code sets variable in storage blocks (Volatile or Non-Volatile) + +Arguments: + + VariableName Name of Variable to be found + VendorGuid Variable vendor GUID + Attributes Attribute value of the variable found + DataSize Size of Data found. If size is less than the + data, this value contains the required size. + Data Data pointer + Global Pointer to VARIABLE_GLOBAL structure + VolatileOffset The offset of last volatile variable + NonVolatileOffset The offset of last non-volatile variable + Instance Instance of the Firmware Volume. + +Returns: + + EFI STATUS + EFI_INVALID_PARAMETER - Invalid parameter + EFI_SUCCESS - Set successfully + EFI_OUT_OF_RESOURCES - Resource not enough to set variable + EFI_NOT_FOUND - Not found + +--*/ +{ + VARIABLE_POINTER_TRACK Variable; + EFI_STATUS Status; + VARIABLE_HEADER *NextVariable; + UINTN VarNameSize; + UINTN VarNameOffset; + UINTN VarDataOffset; + UINTN VarSize; + UINT8 State; + BOOLEAN Reclaimed; + + Reclaimed = FALSE; + + if (VariableName == NULL || VariableName[0] == 0 || VendorGuid == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FindVariable (VariableName, VendorGuid, &Variable, Global); + + if (Status == EFI_INVALID_PARAMETER) { + return Status; + } + // + // The size of the VariableName, including the Unicode Null in bytes plus + // the DataSize is limited to maximum size of MAX_VARIABLE_SIZE (1024) bytes. + // + else if (sizeof (VARIABLE_HEADER) + ArrayLength (VariableName) + DataSize > MAX_VARIABLE_SIZE) { + return EFI_INVALID_PARAMETER; + } + // + // Make sure if runtime bit is set, boot service bit is set also + // + else if ((Attributes & (EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS)) == EFI_VARIABLE_RUNTIME_ACCESS + ) { + return EFI_INVALID_PARAMETER; + } + // + // Runtime but Attribute is not Runtime + // + else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_RUNTIME_ACCESS)) { + return EFI_INVALID_PARAMETER; + } + // + // Cannot set volatile variable in Runtime + // + else if (EfiAtRuntime () && Attributes && !(Attributes & EFI_VARIABLE_NON_VOLATILE)) { + return EFI_INVALID_PARAMETER; + } + // + // Setting a data variable with no access, or zero DataSize attributes + // specified causes it to be deleted. + // + else if (DataSize == 0 || Attributes == 0) { + if (!EFI_ERROR (Status)) { + State = Variable.CurrPtr->State; + State &= VAR_DELETED; + + Status = UpdateVariableStore ( + Global, + Variable.Volatile, + FALSE, + Instance, + (UINTN) &Variable.CurrPtr->State, + sizeof (UINT8), + &State + ); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; + } else { + if (!EFI_ERROR (Status)) { + // + // If the variable is marked valid and the same data has been passed in + // then return to the caller immediately. + // + if (Variable.CurrPtr->DataSize == DataSize && + !CompareMem (Data, GetVariableDataPtr (Variable.CurrPtr), DataSize) + ) { + return EFI_SUCCESS; + } else if (Variable.CurrPtr->State == VAR_ADDED) { + // + // Mark the old variable as in delete transition + // + State = Variable.CurrPtr->State; + State &= VAR_IN_DELETED_TRANSITION; + + Status = UpdateVariableStore ( + Global, + Variable.Volatile, + FALSE, + Instance, + (UINTN) &Variable.CurrPtr->State, + sizeof (UINT8), + &State + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + } + // + // Create a new variable and copy the data. + // + // Tricky part: Use scratch data area at the end of volatile variable store + // as a temporary storage. + // + NextVariable = GetEndPointer ((VARIABLE_STORE_HEADER *) ((UINTN) Global->VolatileVariableBase)); + + SetMem (NextVariable, SCRATCH_SIZE, 0xff); + + NextVariable->StartId = VARIABLE_DATA; + NextVariable->Attributes = Attributes; + // + // NextVariable->State = VAR_ADDED; + // + NextVariable->Reserved = 0; + VarNameOffset = sizeof (VARIABLE_HEADER); + VarNameSize = ArrayLength (VariableName); + CopyMem ( + (UINT8 *) ((UINTN) NextVariable + VarNameOffset), + VariableName, + VarNameSize + ); + VarDataOffset = VarNameOffset + VarNameSize + GET_PAD_SIZE (VarNameSize); + CopyMem ( + (UINT8 *) ((UINTN) NextVariable + VarDataOffset), + Data, + DataSize + ); + CopyMem (&NextVariable->VendorGuid, VendorGuid, sizeof (EFI_GUID)); + // + // There will be pad bytes after Data, the NextVariable->NameSize and + // NextVariable->DataSize should not include pad size so that variable + // service can get actual size in GetVariable + // + NextVariable->NameSize = (UINT32)VarNameSize; + NextVariable->DataSize = (UINT32)DataSize; + + // + // The actual size of the variable that stores in storage should + // include pad size. + // + VarSize = VarDataOffset + DataSize + GET_PAD_SIZE (DataSize); + if (Attributes & EFI_VARIABLE_NON_VOLATILE) { + if ((UINT32) (VarSize +*NonVolatileOffset) > + ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size + ) { + if (EfiAtRuntime ()) { + return EFI_OUT_OF_RESOURCES; + } + // + // Perform garbage collection & reclaim operation + // + Status = Reclaim (Global->NonVolatileVariableBase, NonVolatileOffset, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + // + // If still no enough space, return out of resources + // + if ((UINT32) (VarSize +*NonVolatileOffset) > + ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->NonVolatileVariableBase)))->Size + ) { + return EFI_OUT_OF_RESOURCES; + } + + Reclaimed = TRUE; + } + // + // Three steps + // 1. Write variable header + // 2. Write variable data + // 3. Set variable state to valid + // + // + // Step 1: + // + Status = UpdateVariableStore ( + Global, + FALSE, + TRUE, + Instance, + *NonVolatileOffset, + sizeof (VARIABLE_HEADER), + (UINT8 *) NextVariable + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Step 2: + // + Status = UpdateVariableStore ( + Global, + FALSE, + TRUE, + Instance, + *NonVolatileOffset + sizeof (VARIABLE_HEADER), + (UINT32) VarSize - sizeof (VARIABLE_HEADER), + (UINT8 *) NextVariable + sizeof (VARIABLE_HEADER) + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Step 3: + // + NextVariable->State = VAR_ADDED; + Status = UpdateVariableStore ( + Global, + FALSE, + TRUE, + Instance, + *NonVolatileOffset, + sizeof (VARIABLE_HEADER), + (UINT8 *) NextVariable + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + *NonVolatileOffset = *NonVolatileOffset + VarSize; + + } else { + if (EfiAtRuntime ()) { + return EFI_INVALID_PARAMETER; + } + + if ((UINT32) (VarSize +*VolatileOffset) > + ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size + ) { + // + // Perform garbage collection & reclaim operation + // + Status = Reclaim (Global->VolatileVariableBase, VolatileOffset, TRUE); + if (EFI_ERROR (Status)) { + return Status; + } + // + // If still no enough space, return out of resources + // + if ((UINT32) (VarSize +*VolatileOffset) > + ((VARIABLE_STORE_HEADER *) ((UINTN) (Global->VolatileVariableBase)))->Size + ) { + return EFI_OUT_OF_RESOURCES; + } + + Reclaimed = TRUE; + } + + NextVariable->State = VAR_ADDED; + Status = UpdateVariableStore ( + Global, + TRUE, + TRUE, + Instance, + *VolatileOffset, + (UINT32) VarSize, + (UINT8 *) NextVariable + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + *VolatileOffset = *VolatileOffset + VarSize; + } + // + // Mark the old variable as deleted + // + if (!Reclaimed && !EFI_ERROR (Status) && Variable.CurrPtr != NULL) { + State = Variable.CurrPtr->State; + State &= VAR_DELETED; + + Status = UpdateVariableStore ( + Global, + Variable.Volatile, + FALSE, + Instance, + (UINTN) &Variable.CurrPtr->State, + sizeof (UINT8), + &State + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +VariableCommonInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This function does common initialization for variable services + +Arguments: + + ImageHandle - The firmware allocated handle for the EFI image. + SystemTable - A pointer to the EFI System Table. + +Returns: + + Status code. + + EFI_NOT_FOUND - Variable store area not found. + EFI_UNSUPPORTED - Currently only one non-volatile variable store is supported. + EFI_SUCCESS - Variable services successfully initialized. + +--*/ +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + CHAR8 *CurrPtr; + VARIABLE_STORE_HEADER *VolatileVariableStore; + VARIABLE_STORE_HEADER *VariableStoreHeader; + VARIABLE_HEADER *NextVariable; + UINT32 Instance; + EFI_PHYSICAL_ADDRESS FvVolHdr; + + EFI_FLASH_MAP_ENTRY_DATA *FlashMapEntryData; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR GcdDescriptor; + EFI_FLASH_SUBAREA_ENTRY VariableStoreEntry; + UINT64 BaseAddress; + UINT64 Length; + UINTN Index; + UINT8 Data; + EFI_PEI_HOB_POINTERS GuidHob; + + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (ESAL_VARIABLE_GLOBAL), + (VOID **) &mVariableModuleGlobal + ); + + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate memory for volatile variable store + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + VARIABLE_STORE_SIZE + SCRATCH_SIZE, + (VOID **) &VolatileVariableStore + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (mVariableModuleGlobal); + return Status; + } + + SetMem (VolatileVariableStore, VARIABLE_STORE_SIZE + SCRATCH_SIZE, 0xff); + + // + // Variable Specific Data + // + mVariableModuleGlobal->VariableBase[Physical].VolatileVariableBase = (EFI_PHYSICAL_ADDRESS) (UINTN) VolatileVariableStore; + mVariableModuleGlobal->VolatileLastVariableOffset = sizeof (VARIABLE_STORE_HEADER); + + VolatileVariableStore->Signature = VARIABLE_STORE_SIGNATURE; + VolatileVariableStore->Size = VARIABLE_STORE_SIZE; + VolatileVariableStore->Format = VARIABLE_STORE_FORMATTED; + VolatileVariableStore->State = VARIABLE_STORE_HEALTHY; + VolatileVariableStore->Reserved = 0; + VolatileVariableStore->Reserved1 = 0; + + // + // Get non volatile varaible store + // + + FlashMapEntryData = NULL; + + GuidHob.Raw = GetHobList (); + while (NULL != (GuidHob.Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, GuidHob.Raw))) { + FlashMapEntryData = (EFI_FLASH_MAP_ENTRY_DATA *) GET_GUID_HOB_DATA (GuidHob.Guid); + + if (FlashMapEntryData->AreaType == EFI_FLASH_AREA_EFI_VARIABLES) { + break; + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + + if (NULL == GuidHob.Raw || FlashMapEntryData == NULL) { + gBS->FreePool (mVariableModuleGlobal); + gBS->FreePool (VolatileVariableStore); + return EFI_NOT_FOUND; + } + + // + // Currently only one non-volatile variable store is supported + // + if (FlashMapEntryData->NumEntries != 1) { + gBS->FreePool (mVariableModuleGlobal); + gBS->FreePool (VolatileVariableStore); + return EFI_UNSUPPORTED; + } + + CopyMem (&VariableStoreEntry, &FlashMapEntryData->Entries[0], sizeof (VariableStoreEntry)); + + // + // Mark the variable storage region of the FLASH as RUNTIME + // + BaseAddress = VariableStoreEntry.Base & (~EFI_PAGE_MASK); + Length = VariableStoreEntry.Length + (VariableStoreEntry.Base - BaseAddress); + Length = (Length + EFI_PAGE_SIZE - 1) & (~EFI_PAGE_MASK); + + Status = gDS->GetMemorySpaceDescriptor (BaseAddress, &GcdDescriptor); + if (EFI_ERROR (Status)) { + gBS->FreePool (mVariableModuleGlobal); + gBS->FreePool (VolatileVariableStore); + return EFI_UNSUPPORTED; + } + + Status = gDS->SetMemorySpaceAttributes ( + BaseAddress, + Length, + GcdDescriptor.Attributes | EFI_MEMORY_RUNTIME + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (mVariableModuleGlobal); + gBS->FreePool (VolatileVariableStore); + return EFI_UNSUPPORTED; + } + // + // Get address of non volatile variable store base + // + mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase = VariableStoreEntry.Base; + + // + // Check Integrity + // + // + // Find the Correct Instance of the FV Block Service. + // + Instance = 0; + CurrPtr = (CHAR8 *) ((UINTN) mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase); + while (EfiFvbGetPhysicalAddress (Instance, &FvVolHdr) == EFI_SUCCESS) { + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvVolHdr); + if (CurrPtr >= (CHAR8 *) FwVolHeader && CurrPtr < (((CHAR8 *) FwVolHeader) + FwVolHeader->FvLength)) { + mVariableModuleGlobal->FvbInstance = Instance; + break; + } + + Instance++; + } + + VariableStoreHeader = (VARIABLE_STORE_HEADER *) CurrPtr; + if (GetVariableStoreStatus (VariableStoreHeader) == EfiValid) { + if (~VariableStoreHeader->Size == 0) { + Status = UpdateVariableStore ( + &mVariableModuleGlobal->VariableBase[Physical], + FALSE, + FALSE, + mVariableModuleGlobal->FvbInstance, + (UINTN) &VariableStoreHeader->Size, + sizeof (UINT32), + (UINT8 *) &VariableStoreEntry.Length + ); + + if (EFI_ERROR (Status)) { + return Status; + } + } + + mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase = (EFI_PHYSICAL_ADDRESS) ((UINTN) CurrPtr); + // + // Parse non-volatile variable data and get last variable offset + // + NextVariable = (VARIABLE_HEADER *) (CurrPtr + sizeof (VARIABLE_STORE_HEADER)); + Status = EFI_SUCCESS; + + while (IsValidVariableHeader (NextVariable)) { + NextVariable = GetNextVariablePtr (NextVariable); + } + + mVariableModuleGlobal->NonVolatileLastVariableOffset = (UINTN) NextVariable - (UINTN) CurrPtr; + + // + // Check if the free area is really free. + // + for (Index = mVariableModuleGlobal->NonVolatileLastVariableOffset; Index < VariableStoreHeader->Size; Index++) { + Data = ((UINT8 *) (UINTN) mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase)[Index]; + if (Data != 0xff) { + // + // There must be something wrong in variable store, do reclaim operation. + // + Status = Reclaim ( + mVariableModuleGlobal->VariableBase[Physical].NonVolatileVariableBase, + &mVariableModuleGlobal->NonVolatileLastVariableOffset, + FALSE + ); + break; + } + } + } + + if (EFI_ERROR (Status)) { + gBS->FreePool (mVariableModuleGlobal); + gBS->FreePool (VolatileVariableStore); + } + + return Status; +} diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.h b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.h new file mode 100644 index 0000000000..d1fd5e271e --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.h @@ -0,0 +1,143 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Variable.h + +Abstract: + +--*/ + +#ifndef _VARIABLE_H +#define _VARIABLE_H + +// +// Statements that include other header files +// + +// +// BugBug: We need relcate the head file. +// +#include + +#if defined (MDE_CPU_IPF) +#define ALIGNMENT 8 +#else +#define ALIGNMENT 1 +#endif + + +#define VARIABLE_STORE_SIZE (64 * 1024) +#define SCRATCH_SIZE (4 * 1024) + +// +// Define GET_PAD_SIZE to optimize compiler +// +#if ((ALIGNMENT == 0) || (ALIGNMENT == 1)) +#define GET_PAD_SIZE(a) (0) +#else +#define GET_PAD_SIZE(a) (((~a) + 1) & (ALIGNMENT - 1)) +#endif + +#define GET_VARIABLE_NAME_PTR(a) (CHAR16 *) ((UINTN) (a) + sizeof (VARIABLE_HEADER)) + +typedef enum { + Physical, + Virtual +} VARIABLE_POINTER_TYPE; + +typedef struct { + VARIABLE_HEADER *CurrPtr; + VARIABLE_HEADER *EndPtr; + VARIABLE_HEADER *StartPtr; + BOOLEAN Volatile; +} VARIABLE_POINTER_TRACK; + +typedef struct { + EFI_PHYSICAL_ADDRESS VolatileVariableBase; + EFI_PHYSICAL_ADDRESS NonVolatileVariableBase; +} VARIABLE_GLOBAL; + +typedef struct { + VARIABLE_GLOBAL VariableBase[2]; + UINTN VolatileLastVariableOffset; + UINTN NonVolatileLastVariableOffset; + UINT32 FvbInstance; +} ESAL_VARIABLE_GLOBAL; + +// +// Functions +// +EFI_STATUS +EFIAPI +VariableCommonInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +EFI_STATUS +EFIAPI +VariableServiceInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +VOID +EFIAPI +VariableClassAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +EFI_STATUS +EFIAPI +GetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID * VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data, + IN VARIABLE_GLOBAL * Global, + IN UINT32 Instance + ) +; + +EFI_STATUS +EFIAPI +GetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid, + IN VARIABLE_GLOBAL *Global, + IN UINT32 Instance + ) +; + +EFI_STATUS +EFIAPI +SetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data, + IN VARIABLE_GLOBAL *Global, + IN UINTN *VolatileOffset, + IN UINTN *NonVolatileOffset, + IN UINT32 Instance + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.mbd b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.mbd new file mode 100644 index 0000000000..6a5be9d885 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.mbd @@ -0,0 +1,51 @@ + + + + + Variable + CBD2E4D5-7068-4FF5-B462-9822B4AD8D60 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + BaseLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + DxeServicesTableLib + BaseDebugLibNull + BasePrintLib + EdkDxeRuntimeDriverLib + DxeHobLib + DxeMemoryAllocationLib + EdkFvbServiceLib + + EdkDxeSalLib + + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.msa b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.msa new file mode 100644 index 0000000000..a4399bc0d2 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/Variable.msa @@ -0,0 +1,109 @@ + + + + + Variable + DXE_RUNTIME_DRIVER + RT_DRIVER + CBD2E4D5-7068-4FF5-B462-9822B4AD8D60 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + BaseLib + UefiLib + UefiDriverEntryPoint + DxeServicesTableLib + DxeRuntimeDriverLib + DebugLib + HobLib + BaseMemoryLib + EdkFvbServiceLib + EdkDxeSalLib + UefiBootServicesTableLib + + + Variable.c + Reclaim.c + + InitVariable.c + Ia32Variable.dxs + + + InitVariable.c + x64Variable.dxs + + + InitVariable.c + x64Variable.dxs + + + Ipf\InitVariable.c + IpfVariable.dxs + + + + MdePkg + EdkModulePkg + + + Variable + VariableWrite + FaultTolerantWriteLite + CpuIo + FvbExtension + FirmwareVolumeBlock + Variable + VariableWrite + FaultTolerantWriteLite + CpuIo + FvbExtension + FirmwareVolumeBlock + ExtendedSalBootService + ExtendedSalVariableServices + + + + FlashMapHob + + + Hob + + + SystemNvData + + + AlternateFvBlock + + + + + VariableServiceInitialize + + + VariableClassAddressChangeEvent + + + diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/build.xml b/EdkModulePkg/Universal/Variable/RuntimeDxe/build.xml new file mode 100644 index 0000000000..4eba6a6933 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/reclaim.c b/EdkModulePkg/Universal/Variable/RuntimeDxe/reclaim.c new file mode 100644 index 0000000000..a4bcdd67ce --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/reclaim.c @@ -0,0 +1,240 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + reclaim.c + +Abstract: + + Handles non-volatile variable store garbage collection, using FTW + (Fault Tolerant Write) protocol. + +Revision History + +--*/ + +#include "reclaim.h" +#include "Common/Variable.h" + +EFI_STATUS +GetFvbHandleByAddress ( + IN EFI_PHYSICAL_ADDRESS Address, + OUT EFI_HANDLE *FvbHandle + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_PHYSICAL_ADDRESS FvbBaseAddress; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + + *FvbHandle = NULL; + // + // Locate all handles of Fvb protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeBlockProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + // + // Get the FVB to access variable store + // + for (Index = 0; Index < HandleCount; Index += 1) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &Fvb + ); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + break; + } + // + // Compare the address and select the right one + // + Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress); + if (EFI_ERROR (Status)) { + continue; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress); + if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) { + *FvbHandle = HandleBuffer[Index]; + Status = EFI_SUCCESS; + break; + } + } + + gBS->FreePool (HandleBuffer); + return Status; +} + +EFI_STATUS +GetLbaAndOffsetByAddress ( + IN EFI_PHYSICAL_ADDRESS Address, + OUT EFI_LBA *Lba, + OUT UINTN *Offset + ) +{ + EFI_STATUS Status; + EFI_HANDLE FvbHandle; + EFI_PHYSICAL_ADDRESS FvbBaseAddress; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_FV_BLOCK_MAP_ENTRY *FvbMapEntry; + UINT32 LbaIndex; + + *Lba = (EFI_LBA) (-1); + *Offset = 0; + + // + // Get the proper FVB + // + Status = GetFvbHandleByAddress (Address, &FvbHandle); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->HandleProtocol ( + FvbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + (VOID **) &Fvb + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get the Base Address of FV + // + Status = Fvb->GetPhysicalAddress (Fvb, &FvbBaseAddress); + if (EFI_ERROR (Status)) { + return Status; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) FvbBaseAddress); + + // + // Get the (LBA, Offset) of Address + // + if ((Address >= FvbBaseAddress) && (Address <= (FvbBaseAddress + FwVolHeader->FvLength))) { + if ((FwVolHeader->FvLength) > (FwVolHeader->HeaderLength)) { + // + // BUGBUG: Assume one FV has one type of BlockLength + // + FvbMapEntry = &FwVolHeader->FvBlockMap[0]; + for (LbaIndex = 1; LbaIndex <= FvbMapEntry->NumBlocks; LbaIndex += 1) { + if (Address < (FvbBaseAddress + FvbMapEntry->BlockLength * LbaIndex)) { + // + // Found the (Lba, Offset) + // + *Lba = LbaIndex - 1; + *Offset = (UINTN) (Address - (FvbBaseAddress + FvbMapEntry->BlockLength * (LbaIndex - 1))); + return EFI_SUCCESS; + } + } + } + } + + return EFI_ABORTED; +} + +EFI_STATUS +FtwVariableSpace ( + IN EFI_PHYSICAL_ADDRESS VariableBase, + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + Write a buffer to Variable space, in the working block. + +Arguments: + FvbHandle - Indicates a handle to FVB to access variable store + Buffer - Point to the input buffer + BufferSize - The number of bytes of the input Buffer + +Returns: + EFI_SUCCESS - The function completed successfully + EFI_ABORTED - The function could not complete successfully + EFI_NOT_FOUND - Locate FVB protocol by handle fails + +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE FvbHandle; + EFI_FTW_LITE_PROTOCOL *FtwLiteProtocol; + EFI_LBA VarLba; + UINTN VarOffset; + UINT8 *FtwBuffer; + UINTN FtwBufferSize; + + // + // Locate fault tolerant write protocol + // + Status = gBS->LocateProtocol ( + &gEfiFaultTolerantWriteLiteProtocolGuid, + NULL, + (VOID **) &FtwLiteProtocol + ); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + // + // Locate Fvb handle by address + // + Status = GetFvbHandleByAddress (VariableBase, &FvbHandle); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Get LBA and Offset by address + // + Status = GetLbaAndOffsetByAddress (VariableBase, &VarLba, &VarOffset); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Prepare for the variable data + // + FtwBufferSize = ((VARIABLE_STORE_HEADER *) ((UINTN) VariableBase))->Size; + Status = gBS->AllocatePool (EfiRuntimeServicesData, FtwBufferSize, (VOID **) &FtwBuffer); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + SetMem (FtwBuffer, FtwBufferSize, (UINT8) 0xff); + CopyMem (FtwBuffer, Buffer, BufferSize); + + // + // FTW write record + // + Status = FtwLiteProtocol->Write ( + FtwLiteProtocol, + FvbHandle, + VarLba, // LBA + VarOffset, // Offset + &FtwBufferSize, // NumBytes, + FtwBuffer + ); + + gBS->FreePool (FtwBuffer); + return Status; +} diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/reclaim.h b/EdkModulePkg/Universal/Variable/RuntimeDxe/reclaim.h new file mode 100644 index 0000000000..7bc1020ba3 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/reclaim.h @@ -0,0 +1,45 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + reclaim.h + +Abstract: + + Definitions for non-volatile variable store garbage collection + +Revision History + +--*/ + +#ifndef _VAR_RECLAIM_H +#define _VAR_RECLAIM_H + +// +// Functions +// +EFI_STATUS +GetFvbHandleByAddress ( + IN EFI_PHYSICAL_ADDRESS VariableStoreBase, + OUT EFI_HANDLE *FvbHandle + ) +; + +EFI_STATUS +FtwVariableSpace ( + IN EFI_PHYSICAL_ADDRESS VariableBaseAddress, + IN UINT8 *Buffer, + IN UINTN BufferSize + ) +; + +#endif diff --git a/EdkModulePkg/Universal/Variable/RuntimeDxe/x64Variable.dxs b/EdkModulePkg/Universal/Variable/RuntimeDxe/x64Variable.dxs new file mode 100644 index 0000000000..c9f2f694e7 --- /dev/null +++ b/EdkModulePkg/Universal/Variable/RuntimeDxe/x64Variable.dxs @@ -0,0 +1,26 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + x64Variable.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include "DxeDepex.h" + +DEPENDENCY_START + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID AND EFI_ALTERNATE_FV_BLOCK_GUID +DEPENDENCY_END \ No newline at end of file diff --git a/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.c b/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.c new file mode 100644 index 0000000000..b54b25ee83 --- /dev/null +++ b/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.c @@ -0,0 +1,310 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WatchDogTimer.c + +Abstract: + + Generic watchdog timer implemenetation using EFI APIs + +Revision History + +--*/ + +#include "WatchDogTimer.h" + +// +// Handle for the Watchdog Timer Architectural Protocol instance produced by this driver +// +EFI_HANDLE mWatchdogTimerHandle = NULL; + +// +// The Watchdog Timer Architectural Protocol instance produced by this driver +// +EFI_WATCHDOG_TIMER_ARCH_PROTOCOL mWatchdogTimer = { + WatchdogTimerDriverRegisterHandler, + WatchdogTimerDriverSetTimerPeriod, + WatchdogTimerDriverGetTimerPeriod +}; + +// +// The watchdog timer period in 100 nS units +// +UINT64 mWatchdogTimerPeriod = 0; + +// +// The notification function to call if the watchdig timer fires +// +EFI_WATCHDOG_TIMER_NOTIFY mWatchdogTimerNotifyFunction = NULL; + +// +// The one-shot timer event that is armed when the watchdog timer is enabled +// +EFI_EVENT mWatchdogTimerEvent; + +// +// Worker Functions +// +VOID +EFIAPI +WatchdogTimerDriverExpires ( + IN EFI_EVENT Timer, + IN VOID *Context + ) +/*++ + + Routine Description: + + Notification function that is called if the watchdog timer is fired. If a + handler has been registered with the Watchdog Timer Architectural Protocol, + then that handler is called passing in the time period that has passed that + cause the watchdog timer to fire. Then, a call to the Runtime Service + ResetSystem() is made to reset the platform. + + Arguments: + + Timer - The one-shot timer event that was signaled when the watchdog timer + expired. + + Context - The context that was registered when the event Timer was created. + + Returns: + + None. + +--*/ +{ + // + // Report error code before exiting + // + REPORT_STATUS_CODE ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_CU_HP_EC_TIMER_EXPIRED) + ); + + // + // If a notification function has been registered, then call it + // + if (mWatchdogTimerNotifyFunction != NULL) { + mWatchdogTimerNotifyFunction (mWatchdogTimerPeriod); + } + // + // Reset the platform + // + gRT->ResetSystem (EfiResetCold, EFI_TIMEOUT, 0, NULL); +} + +EFI_STATUS +EFIAPI +WatchdogTimerDriverRegisterHandler ( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction + ) +/*++ + +Routine Description: + + This function registers a handler that is to be invoked when the watchdog + timer fires. By default, the EFI_WATCHDOG_TIMER protocol will call the + Runtime Service ResetSystem() when the watchdog timer fires. If a + NotifyFunction is registered, then the NotifyFunction will be called before + the Runtime Service ResetSystem() is called. If NotifyFunction is NULL, then + the watchdog handler is unregistered. If a watchdog handler is registered, + then EFI_SUCCESS is returned. If an attempt is made to register a handler + when a handler is already registered, then EFI_ALREADY_STARTED is returned. + If an attempt is made to uninstall a handler when a handler is not installed, + then return EFI_INVALID_PARAMETER. + +Arguments: + + This - The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. + + NotifyFunction - The function to call when the watchdog timer fires. If this + is NULL, then the handler will be unregistered. + +Returns: + + EFI_SUCCESS - The watchdog timer handler was registered or + unregistered. + + EFI_ALREADY_STARTED - NotifyFunction is not NULL, and a handler is already + registered. + + EFI_INVALID_PARAMETER - NotifyFunction is NULL, and a handler was not + previously registered. + +--*/ +{ + if (NotifyFunction == NULL && mWatchdogTimerNotifyFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (NotifyFunction != NULL && mWatchdogTimerNotifyFunction != NULL) { + return EFI_ALREADY_STARTED; + } + + mWatchdogTimerNotifyFunction = NotifyFunction; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +WatchdogTimerDriverSetTimerPeriod ( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +/*++ + +Routine Description: + + This function sets the amount of time to wait before firing the watchdog + timer to TimerPeriod 100 nS units. If TimerPeriod is 0, then the watchdog + timer is disabled. + +Arguments: + + This - The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. + + TimerPeriod - The amount of time in 100 nS units to wait before the watchdog + timer is fired. If TimerPeriod is zero, then the watchdog + timer is disabled. + +Returns: + + EFI_SUCCESS - The watchdog timer has been programmed to fire in Time + 100 nS units. + + EFI_DEVICE_ERROR - A watchdog timer could not be programmed due to a device + error. + +--*/ +{ + mWatchdogTimerPeriod = TimerPeriod; + + return gBS->SetTimer ( + mWatchdogTimerEvent, + (mWatchdogTimerPeriod == 0) ? TimerCancel : TimerRelative, + mWatchdogTimerPeriod + ); +} + +EFI_STATUS +EFIAPI +WatchdogTimerDriverGetTimerPeriod ( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + IN UINT64 *TimerPeriod + ) +/*++ + +Routine Description: + + This function retrieves the amount of time the system will wait before firing + the watchdog timer. This period is returned in TimerPeriod, and EFI_SUCCESS + is returned. If TimerPeriod is NULL, then EFI_INVALID_PARAMETER is returned. + +Arguments: + + This - The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. + + TimerPeriod - A pointer to the amount of time in 100 nS units that the system + will wait before the watchdog timer is fired. If TimerPeriod of + zero is returned, then the watchdog timer is disabled. + +Returns: + + EFI_SUCCESS - The amount of time that the system will wait before + firing the watchdog timer was returned in TimerPeriod. + + EFI_INVALID_PARAMETER - TimerPeriod is NULL. + +--*/ +{ + if (TimerPeriod == NULL) { + return EFI_INVALID_PARAMETER; + } + + *TimerPeriod = mWatchdogTimerPeriod; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +WatchdogTimerDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initialize the Watchdog Timer Architectural Protocol driver + +Arguments: + + ImageHandle - ImageHandle of the loaded driver + + SystemTable - Pointer to the System Table + +Returns: + + EFI_SUCCESS - Timer Architectural Protocol created + + EFI_OUT_OF_RESOURCES - Not enough resources available to initialize driver. + + EFI_DEVICE_ERROR - A device error occured attempting to initialize the driver. + +--*/ +{ + EFI_STATUS Status; + + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_SW_PC_INIT_BEGIN) + ); + // + // Make sure the Watchdog Timer Architectural Protocol is not already installed in the system + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiWatchdogTimerArchProtocolGuid); + + // + // Create the timer event used to implement a simple watchdog timer + // + Status = gBS->CreateEvent ( + EFI_EVENT_TIMER | EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_NOTIFY, + WatchdogTimerDriverExpires, + NULL, + &mWatchdogTimerEvent + ); + ASSERT_EFI_ERROR (Status); + + // + // Install the Watchdog Timer Arch Protocol onto a new handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &mWatchdogTimerHandle, + &gEfiWatchdogTimerArchProtocolGuid, + &mWatchdogTimer, + NULL + ); + ASSERT_EFI_ERROR (Status); + + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_COMPUTING_UNIT_HOST_PROCESSOR | EFI_SW_PC_INIT_END) + ); + + return Status; +} diff --git a/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.dxs b/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.dxs new file mode 100644 index 0000000000..da8c297342 --- /dev/null +++ b/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WatchDogTimer.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + +DEPENDENCY_START + EFI_TIMER_ARCH_PROTOCOL_GUID +DEPENDENCY_END + diff --git a/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.h b/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.h new file mode 100644 index 0000000000..bb1936b90e --- /dev/null +++ b/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.h @@ -0,0 +1,62 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WatchDogTimer.h + +Abstract: + + Generic watchdog timer implemenetation using EFI APIs + +Revision History + +--*/ + +#ifndef _WATCHDOG_TIMER_H_ +#define _WATCHDOG_TIMER_H_ + +// +// Function Prototypes +// +EFI_STATUS +EFIAPI +WatchdogTimerDriverRegisterHandler ( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction + ) +; + +EFI_STATUS +EFIAPI +WatchdogTimerDriverSetTimerPeriod ( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +; + +EFI_STATUS +EFIAPI +WatchdogTimerDriverGetTimerPeriod ( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + IN UINT64 *TimerPeriod + ) +; + +EFI_STATUS +EFIAPI +WatchdogTimerDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + +#endif diff --git a/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.mbd b/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.mbd new file mode 100644 index 0000000000..17bd6ea24f --- /dev/null +++ b/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.mbd @@ -0,0 +1,44 @@ + + + + + WatchDogTimer + F099D67F-71AE-4c36-B2A3-DCEB0EB2B7D8 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-12 17:09 + 2006-03-19 15:19 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + + + _ModuleEntryPoint + + diff --git a/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.msa b/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.msa new file mode 100644 index 0000000000..4cccdc7ce5 --- /dev/null +++ b/EdkModulePkg/Universal/WatchdogTimer/Dxe/WatchDogTimer.msa @@ -0,0 +1,61 @@ + + + + + WatchDogTimer + DXE_DRIVER + BS_DRIVER + F099D67F-71AE-4c36-B2A3-DCEB0EB2B7D8 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-12 17:09 + 2006-03-19 15:19 + + + DebugLib + UefiDriverEntryPoint + ReportStatusCodeLib + UefiLib + BaseLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + + + WatchDogTimer.c + WatchDogTimer.h + WatchDogTimer.dxs + + + MdePkg + EdkModulePkg + + + StatusCode + WatchdogTimer + + + + WatchdogTimerDriverInitialize + + + diff --git a/EdkModulePkg/Universal/WatchdogTimer/Dxe/build.xml b/EdkModulePkg/Universal/WatchdogTimer/Dxe/build.xml new file mode 100644 index 0000000000..76f67c162e --- /dev/null +++ b/EdkModulePkg/Universal/WatchdogTimer/Dxe/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkModulePkg/build.xml b/EdkModulePkg/build.xml new file mode 100644 index 0000000000..41712df4e8 --- /dev/null +++ b/EdkModulePkg/build.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EdkModulePkg/genbuildfile.xml b/EdkModulePkg/genbuildfile.xml new file mode 100644 index 0000000000..77702ef12d --- /dev/null +++ b/EdkModulePkg/genbuildfile.xml @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/EdkNt32Pkg/Build/AprioriList.mbd b/EdkNt32Pkg/Build/AprioriList.mbd new file mode 100644 index 0000000000..36b39b164b --- /dev/null +++ b/EdkNt32Pkg/Build/AprioriList.mbd @@ -0,0 +1,32 @@ + + + + + + $(EFI_APRIORI_GUID) + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + + diff --git a/EdkNt32Pkg/Build/AprioriList.msa b/EdkNt32Pkg/Build/AprioriList.msa new file mode 100644 index 0000000000..94850edd8c --- /dev/null +++ b/EdkNt32Pkg/Build/AprioriList.msa @@ -0,0 +1,44 @@ + + + + + AprioriList + USER_DEFINED + APRIORI + 0xfc510ee7, 0xffdc, 0x11d4, 0xbd, 0x41, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 + 0 + Component description file for creating an Apriori file. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + $(BUILD_DIR)\Fv\$(FV).apr + + + + + + + + + diff --git a/EdkNt32Pkg/Build/Nt32Common.xml b/EdkNt32Pkg/Build/Nt32Common.xml new file mode 100644 index 0000000000..7d996fe5c9 --- /dev/null +++ b/EdkNt32Pkg/Build/Nt32Common.xml @@ -0,0 +1,183 @@ + + + + + + + + +
+
+
+ + + + + + + +
+ + + + + + +
+ + + + + + + +
+ + + + + + + +
+ + + + + + + +
+ + + + + + + + +
+ + + + + + + +
+
+
+
+ + + + + + +
+ + + + + + + +
+
+
+
+
+ + + + + + + + + +
+
+
+ + + + + + +
+
+
+
+ + + + + + +
+
+ + + + + + +
+ +
+
+
+ + + + + + + +
+
+
+
+
+ + + + + + +
+
+
+ + + + + + + +
+
+
+
+ + + + + + + + +
+ + + diff --git a/EdkNt32Pkg/Build/component.def b/EdkNt32Pkg/Build/component.def new file mode 100644 index 0000000000..1e8484653b --- /dev/null +++ b/EdkNt32Pkg/Build/component.def @@ -0,0 +1,12 @@ +; Copyright (c) 2006, 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. + +LIBRARY +EXPORTS + InitializeDriver=_ModuleEntryPoint diff --git a/EdkNt32Pkg/Dxe/ConPlatform/ComponentName.c b/EdkNt32Pkg/Dxe/ConPlatform/ComponentName.c new file mode 100644 index 0000000000..f854499937 --- /dev/null +++ b/EdkNt32Pkg/Dxe/ConPlatform/ComponentName.c @@ -0,0 +1,141 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "ConPlatform.h" +#include "ComponentName.h" + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gConPlatformComponentName = { + ConPlatformComponentNameGetDriverName, + ConPlatformComponentNameGetControllerName, + "eng" +}; + +STATIC EFI_UNICODE_STRING_TABLE mConPlatformDriverNameTable[] = { + { + "eng", + L"Platform Console Management Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +ConPlatformComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gConPlatformComponentName.SupportedLanguages, + mConPlatformDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +ConPlatformComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language + specified by Language from the point of view of the + driver specified by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkNt32Pkg/Dxe/ConPlatform/ComponentName.h b/EdkNt32Pkg/Dxe/ConPlatform/ComponentName.h new file mode 100644 index 0000000000..3bada842d7 --- /dev/null +++ b/EdkNt32Pkg/Dxe/ConPlatform/ComponentName.h @@ -0,0 +1,44 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.h + +Abstract: + +--*/ + +#ifndef CON_MANAGE_COMPONENT_NAME_H_ +#define CON_MANAGE_COMPONENT_NAME_H_ + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +ConPlatformComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +ConPlatformComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +#endif diff --git a/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.c b/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.c new file mode 100644 index 0000000000..4b7d2796d0 --- /dev/null +++ b/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.c @@ -0,0 +1,811 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ConPlatform.c + +Abstract: + +--*/ + +#include "ConPlatform.h" + +EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextInDriverBinding = { + ConPlatformTextInDriverBindingSupported, + ConPlatformTextInDriverBindingStart, + ConPlatformDriverBindingStop, + 0x10, + NULL, + NULL +}; + +EFI_DRIVER_BINDING_PROTOCOL gConPlatformTextOutDriverBinding = { + ConPlatformTextOutDriverBindingSupported, + ConPlatformTextOutDriverBindingStart, + ConPlatformDriverBindingStop, + 0x10, + NULL, + NULL +}; + +STATIC +EFI_STATUS +EFIAPI +ConPlatformTextInDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Supported + +Arguments: + (Standard DriverBinding Protocol Supported() function) + +Returns: + + None + +--*/ +{ + return ConPlatformDriverBindingSupported ( + This, + ControllerHandle, + RemainingDevicePath, + &gEfiSimpleTextInProtocolGuid + ); +} + +STATIC +EFI_STATUS +EFIAPI +ConPlatformTextOutDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + Supported + +Arguments: + (Standard DriverBinding Protocol Supported() function) + +Returns: + + None + +--*/ +{ + return ConPlatformDriverBindingSupported ( + This, + ControllerHandle, + RemainingDevicePath, + &gEfiSimpleTextOutProtocolGuid + ); +} + +EFI_STATUS +ConPlatformDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, + IN EFI_GUID *ProtocolGuid + ) +/*++ + +Routine Description: + Supported + +Arguments: + (Standard DriverBinding Protocol Supported() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + VOID *Interface; + + // + // Test to see if this is a physical device by checking to see if + // it has a Device Path Protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + NULL, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Test to see if this device supports the Simple Text Output Protocol + // + Status = gBS->OpenProtocol ( + ControllerHandle, + ProtocolGuid, + (VOID **) &Interface, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + ControllerHandle, + ProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +ConPlatformTextInDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + +Arguments: + (Standard DriverBinding Protocol Start() function) + +Returns: + + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_SIMPLE_TEXT_IN_PROTOCOL *TextIn; + + // + // Get the Device Path Protocol so the environment variables can be updated + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open the Simple Input Protocol BY_DRIVER + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + (VOID **) &TextIn, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the device handle, if it is a hot plug device, + // do not put the device path into ConInDev, and install + // gEfiConsoleInDeviceGuid to the device handle directly. + // The policy is, make hot plug device plug in and play immediately. + // + if (IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) { + gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiConsoleInDeviceGuid, + NULL, + NULL + ); + } else { + // + // Append the device path to the ConInDev environment variable + // + ConPlatformUpdateDeviceVariable ( + VarConsoleInpDev, + DevicePath, + APPEND + ); + + // + // If the device path is an instance in the ConIn environment variable, + // then install EfiConsoleInDeviceGuid onto ControllerHandle + // + Status = ConPlatformUpdateDeviceVariable ( + VarConsoleInp, + DevicePath, + CHECK + ); + + if (!EFI_ERROR (Status)) { + gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiConsoleInDeviceGuid, + NULL, + NULL + ); + } else { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +ConPlatformTextOutDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + +Arguments: + (Standard DriverBinding Protocol Start() function) + +Returns: + + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *TextOut; + + BOOLEAN NeedClose; + + NeedClose = TRUE; + + // + // Get the Device Path Protocol so the environment variables can be updated + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Open the Simple Text Output Protocol BY_DRIVER + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + (VOID **) &TextOut, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check the device handle, if it is a hot plug device, + // do not put the device path into ConOutDev and StdErrDev, + // and install gEfiConsoleOutDeviceGuid to the device handle directly. + // The policy is, make hot plug device plug in and play immediately. + // + if (IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) { + gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiConsoleOutDeviceGuid, + NULL, + NULL + ); + } else { + // + // Append the device path to the ConOutDev environment variable + // + ConPlatformUpdateDeviceVariable ( + VarConsoleOutDev, + DevicePath, + APPEND + ); + // + // Append the device path to the StdErrDev environment variable + // + ConPlatformUpdateDeviceVariable ( + VarErrorOutDev, + DevicePath, + APPEND + ); + + // + // If the device path is an instance in the ConOut environment variable, + // then install EfiConsoleOutDeviceGuid onto ControllerHandle + // + Status = ConPlatformUpdateDeviceVariable ( + VarConsoleOut, + DevicePath, + CHECK + ); + if (!EFI_ERROR (Status)) { + NeedClose = FALSE; + Status = gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiConsoleOutDeviceGuid, + NULL, + NULL + ); + } + // + // If the device path is an instance in the StdErr environment variable, + // then install EfiStandardErrorDeviceGuid onto ControllerHandle + // + Status = ConPlatformUpdateDeviceVariable ( + VarErrorOut, + DevicePath, + CHECK + ); + if (!EFI_ERROR (Status)) { + NeedClose = FALSE; + gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiStandardErrorDeviceGuid, + NULL, + NULL + ); + } + + if (NeedClose) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +ConPlatformDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + (Standard DriverBinding Protocol Stop() function) + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // hot plug device is not included into the console associated variables, + // so no need to check variable for those hot plug devices. + // + if (!IsHotPlugDevice (This->DriverBindingHandle, ControllerHandle)) { + // + // Get the Device Path Protocol so the environment variables can be updated + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + (VOID **) &DevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + // + // Remove DevicePath from ConInDev, ConOutDev, and StdErrDev + // + ConPlatformUpdateDeviceVariable ( + VarConsoleInpDev, + DevicePath, + DELETE + ); + ConPlatformUpdateDeviceVariable ( + VarConsoleOutDev, + DevicePath, + DELETE + ); + ConPlatformUpdateDeviceVariable ( + VarErrorOutDev, + DevicePath, + DELETE + ); + } + } + // + // Uninstall the Console Device GUIDs from Controller Handle + // + ConPlatformUnInstallProtocol ( + This, + ControllerHandle, + &gEfiConsoleInDeviceGuid + ); + + ConPlatformUnInstallProtocol ( + This, + ControllerHandle, + &gEfiConsoleOutDeviceGuid + ); + + ConPlatformUnInstallProtocol ( + This, + ControllerHandle, + &gEfiStandardErrorDeviceGuid + ); + + // + // Close the Simple Input and Simple Text Output Protocols + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSimpleTextInProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return EFI_SUCCESS; +} + +VOID +ConPlatformUnInstallProtocol ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_GUID *ProtocolGuid + ) +{ + EFI_STATUS Status; + + Status = gBS->OpenProtocol ( + Handle, + ProtocolGuid, + NULL, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + + if (!EFI_ERROR (Status)) { + gBS->UninstallMultipleProtocolInterfaces ( + Handle, + ProtocolGuid, + NULL, + NULL + ); + } + + return ; +} + +VOID * +ConPlatformGetVariable ( + IN CHAR16 *Name + ) +/*++ + +Routine Description: + Read the EFI variable (Name) and return a dynamically allocated + buffer, and the size of the buffer. On failure return NULL. + +Arguments: + Name - String part of EFI variable name + +Returns: + Dynamically allocated memory that contains a copy of the EFI variable. + Caller is repsoncible freeing the buffer. + + NULL - Variable was not read + +--*/ +{ + EFI_STATUS Status; + VOID *Buffer; + UINTN BufferSize; + + BufferSize = 0; + Buffer = NULL; + + // + // Test to see if the variable exists. If it doesn't reuturn NULL + // + Status = gRT->GetVariable ( + Name, + &gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Allocate the buffer to return + // + Status = gBS->AllocatePool (EfiBootServicesData, BufferSize, &Buffer); + if (EFI_ERROR (Status)) { + return NULL; + } + // + // Read variable into the allocated buffer. + // + Status = gRT->GetVariable ( + Name, + &gEfiGlobalVariableGuid, + NULL, + &BufferSize, + Buffer + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Buffer); + Buffer = NULL; + } + } + + return Buffer; +} + +EFI_STATUS +ConPlatformMatchDevicePaths ( + IN EFI_DEVICE_PATH_PROTOCOL * Multi, + IN EFI_DEVICE_PATH_PROTOCOL * Single, + IN EFI_DEVICE_PATH_PROTOCOL **NewDevicePath OPTIONAL, + IN BOOLEAN Delete + ) +/*++ + +Routine Description: + Function compares a device path data structure to that of all the nodes of a + second device path instance. + +Arguments: + Multi - A pointer to a multi-instance device path data structure. + + Single - A pointer to a single-instance device path data structure. + + NewDevicePath - If Delete is TRUE, this parameter must not be null, and it + points to the remaining device path data structure. + (remaining device path = Multi - Single.) + + Delete - If TRUE, means removing Single from Multi. + If FALSE, the routine just check whether Single matches + with any instance in Multi. + +Returns: + + The function returns EFI_SUCCESS if the Single is contained within Multi. + Otherwise, EFI_NOT_FOUND is returned. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath1; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath2; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + UINTN Size; + + // + // The passed in DevicePath should not be NULL + // + if ((!Multi) || (!Single)) { + return EFI_NOT_FOUND; + } + // + // if performing Delete operation, the NewDevicePath must not be NULL. + // + TempDevicePath1 = NULL; + + DevicePath = Multi; + DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); + + // + // search for the match of 'Single' in 'Multi' + // + while (DevicePathInst) { + if (CompareMem (Single, DevicePathInst, Size) == 0) { + if (!Delete) { + gBS->FreePool (DevicePathInst); + return EFI_SUCCESS; + } + } else { + if (Delete) { + TempDevicePath2 = AppendDevicePathInstance ( + TempDevicePath1, + DevicePathInst + ); + gBS->FreePool (TempDevicePath1); + TempDevicePath1 = TempDevicePath2; + } + } + + gBS->FreePool (DevicePathInst); + DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); + } + + if (Delete) { + *NewDevicePath = TempDevicePath1; + return EFI_SUCCESS; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +ConPlatformUpdateDeviceVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONPLATFORM_VAR_OPERATION Operation + ) +/*++ + +Routine Description: + + +Arguments: + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *VariableDevicePath; + EFI_DEVICE_PATH_PROTOCOL *NewVariableDevicePath; + + VariableDevicePath = NULL; + NewVariableDevicePath = NULL; + + // + // Get Variable according to variable name. + // The memory for Variable is allocated within ConPlatformGetVarible(), + // it is the caller's responsibility to free the memory before return. + // + VariableDevicePath = ConPlatformGetVariable (VariableName); + + if (Operation != DELETE) { + + Status = ConPlatformMatchDevicePaths ( + VariableDevicePath, + DevicePath, + NULL, + FALSE + ); + + if ((Operation == CHECK) || (!EFI_ERROR (Status))) { + // + // The device path is already in the variable + // + gBS->FreePool (VariableDevicePath); + + return Status; + } + // + // The device path is not in variable. Append DevicePath to the + // environment variable that is a multi-instance device path. + // + Status = EFI_SUCCESS; + NewVariableDevicePath = AppendDevicePathInstance ( + VariableDevicePath, + DevicePath + ); + if (NewVariableDevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + } + + } else { + // + // Remove DevicePath from the environment variable that + // is a multi-instance device path. + // + Status = ConPlatformMatchDevicePaths ( + VariableDevicePath, + DevicePath, + &NewVariableDevicePath, + TRUE + ); + } + + gBS->FreePool (VariableDevicePath); + + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + GetDevicePathSize (NewVariableDevicePath), + NewVariableDevicePath + ); + + gBS->FreePool (NewVariableDevicePath); + + return Status; +} + +BOOLEAN +IsHotPlugDevice ( + EFI_HANDLE DriverBindingHandle, + EFI_HANDLE ControllerHandle + ) +{ + EFI_STATUS Status; + + // + // HotPlugDeviceGuid indicates ControllerHandle stands for a hot plug device. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiHotPlugDeviceGuid, + NULL, + DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_TEST_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + return TRUE; +} diff --git a/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.h b/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.h new file mode 100644 index 0000000000..41b025625b --- /dev/null +++ b/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.h @@ -0,0 +1,126 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ConPlatform.h + +Abstract: + +--*/ + +#ifndef CON_MANAGE_H_ +#define CON_MANAGE_H_ + +// +// +// +#define VarConsoleInpDev L"ConInDev" +#define VarConsoleInp L"ConIn" +#define VarConsoleOutDev L"ConOutDev" +#define VarConsoleOut L"ConOut" +#define VarErrorOutDev L"ErrOutDev" +#define VarErrorOut L"ErrOut" + +typedef enum { + CHECK, + APPEND, + DELETE +} CONPLATFORM_VAR_OPERATION; + +EFI_STATUS +ConPlatformDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, + IN EFI_GUID *ProtocolGuid + ); + +STATIC +EFI_STATUS +EFIAPI +ConPlatformTextInDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +ConPlatformTextOutDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +ConPlatformTextInDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +ConPlatformTextOutDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +STATIC +EFI_STATUS +EFIAPI +ConPlatformDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +VOID +ConPlatformUnInstallProtocol ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_GUID *ProtocolGuid + ); + +VOID * +ConPlatformGetVariable ( + IN CHAR16 *Name + ); + +EFI_STATUS +ConPlatformMatchDevicePaths ( + IN EFI_DEVICE_PATH_PROTOCOL * Multi, + IN EFI_DEVICE_PATH_PROTOCOL * Single, + IN EFI_DEVICE_PATH_PROTOCOL **NewDevicePath OPTIONAL, + IN BOOLEAN Delete + ); + +EFI_STATUS +ConPlatformUpdateDeviceVariable ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONPLATFORM_VAR_OPERATION Operation + ); + +BOOLEAN +IsHotPlugDevice ( + EFI_HANDLE DriverBindingHandle, + EFI_HANDLE ControllerHandle + ); + +#endif diff --git a/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.mbd b/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.mbd new file mode 100644 index 0000000000..6aaa24512b --- /dev/null +++ b/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.mbd @@ -0,0 +1,44 @@ + + + + + ConPlatform + 51ccf399-4fdf-4e55-a45b-e123f84d456a + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-13 17:06 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + UefiMemoryLib + UefiLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkDxePrintLib + BaseLib + DxeMemoryAllocationLib + UefiDevicePathLib + + diff --git a/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.msa b/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.msa new file mode 100644 index 0000000000..30bd63cbff --- /dev/null +++ b/EdkNt32Pkg/Dxe/ConPlatform/ConPlatform.msa @@ -0,0 +1,116 @@ + + + + + ConPlatform + UEFI_DRIVER + BS_DRIVER + 51ccf399-4fdf-4e55-a45b-e123f84d456a + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-13 17:06 + 2006-03-19 15:17 + + + DebugLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DevicePathLib + + + ConPlatform.c + ConPlatform.h + ComponentName.c + + + MdePkg + EdkModulePkg + + + SimpleTextOut + SimpleTextIn + DevicePath + + + + ConInDev + 0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C + + + ConIn + 0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C + + + ConOutDev + 0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C + + + ConOut + 0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C + + + ErrOutDev + 0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C + + + ErrOut + 0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C + + + + + ConsoleInDevice + + + ConsoleOutDevice + + + StandardErrorDevice + + + HotPlugDevice + + + GlobalVariable + + + + + + + + gConPlatformTextInDriverBinding + gConPlatformComponentName + + + gConPlatformTextOutDriverBinding + gConPlatformComponentName + + + diff --git a/EdkNt32Pkg/Dxe/ConPlatform/build.xml b/EdkNt32Pkg/Dxe/ConPlatform/build.xml new file mode 100644 index 0000000000..52d84eb934 --- /dev/null +++ b/EdkNt32Pkg/Dxe/ConPlatform/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBaseBoardManufacturer.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBaseBoardManufacturer.uni new file mode 100644 index 0000000000..14a68936ef Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBaseBoardManufacturer.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBaseBoardManufacturerData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBaseBoardManufacturerData.c new file mode 100644 index 0000000000..9536c88aa4 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBaseBoardManufacturerData.c @@ -0,0 +1,57 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscBaseBoardManufacturerData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_BASE_BOARD_MANUFACTURER_DATA, MiscBaseBoardManufacturer) = { + STRING_TOKEN(STR_MISC_BASE_BOARD_MANUFACTURER), + STRING_TOKEN(STR_MISC_BASE_BOARD_PRODUCT_NAME), + STRING_TOKEN(STR_MISC_BASE_BOARD_VERSION), + STRING_TOKEN(STR_MISC_BASE_BOARD_SERIAL_NUMBER), + STRING_TOKEN(STR_MISC_BASE_BOARD_ASSET_TAG), + STRING_TOKEN(STR_MISC_BASE_BOARD_CHASSIS_LOCATION), + { // BaseBoardFeatureFlags + 1, // Motherboard + 0, // RequiresDaughterCard + 0, // Removable + 1, // Replaceable, + 0, // HotSwappable + 0, // Reserved + }, + EfiBaseBoardTypeUnknown, // BaseBoardType + { // BaseBoardChassisLink + EFI_MISC_SUBCLASS_GUID, // ProducerName + 1, // Instance + 1, // SubInstance + }, + 0, // BaseBoardNumberLinks + { // LinkN + EFI_MISC_SUBCLASS_GUID, // ProducerName + 1, // Instance + 1, // SubInstance + }, +}; + +/* eof - MiscBaseBoardManufacturerData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBiosLanguageData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBiosLanguageData.c new file mode 100644 index 0000000000..652acacb54 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBiosLanguageData.c @@ -0,0 +1,45 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscBiosLanguageData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES_DATA, NumberOfInstallableLangauges) = { + 1, // NumberOfInstallableLanguages + { // LanguageFlags + 0, // AbbreviatedLanguageFormat + 0 // Reserved + }, + 0 // CurrentLanguageNumber +}; + +// +// +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_SYSTEM_LANGUAGE_STRING_DATA, SystemLanguageString) = { + 0, // LanguageId + STR_MISC_SYSTEM_LANGUAGE_STRING // SystemLanguageString +}; + +/* eof - MiscBiosLanguageData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBiosVendor.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBiosVendor.uni new file mode 100644 index 0000000000..b1e7e520fc Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBiosVendor.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBiosVendorData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBiosVendorData.c new file mode 100644 index 0000000000..3187aba2a0 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBiosVendorData.c @@ -0,0 +1,88 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscBiosVendorData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_BIOS_VENDOR_DATA, MiscBiosVendor) = { + STRING_TOKEN(STR_MISC_BIOS_VENDOR), // BiosVendor + STRING_TOKEN(STR_MISC_BIOS_VERSION), // BiosVersion + STRING_TOKEN(STR_MISC_BIOS_RELEASE_DATE), // BiosReleaseDate + 0xBABE, // BiosStartingAddress + { // BiosPhysicalDeviceSize + 2, // Value + 3, // Exponent + }, + { // BiosCharacteristics1 + 0, // Reserved1 :2 + 0, // Unknown :1 + 1, // BiosCharacteristicsNotSupported :1 + 0, // IsaIsSupported :1 + 0, // McaIsSupported :1 + 0, // EisaIsSupported :1 + 0, // PciIsSupported :1 + 0, // PcmciaIsSupported :1 + 0, // PlugAndPlayIsSupported :1 + 0, // ApmIsSupported :1 + 0, // BiosIsUpgradable :1 + 0, // BiosShadowingAllowed :1 + 0, // VlVesaIsSupported :1 + 0, // EscdSupportIsAvailable :1 + 0, // BootFromCdIsSupported :1 + 0, // SelectableBootIsSupported :1 + 0, // RomBiosIsSocketed :1 + 0, // BootFromPcmciaIsSupported :1 + 0, // EDDSpecificationIsSupported :1 + 0, // JapaneseNecFloppyIsSupported :1 + 0, // JapaneseToshibaFloppyIsSupported :1 + 0, // Floppy525_360IsSupported :1 + 0, // Floppy525_12IsSupported :1 + 0, // Floppy35_720IsSupported :1 + 0, // Floppy35_288IsSupported :1 + 0, // PrintScreenIsSupported :1 + 0, // Keyboard8042IsSupported :1 + 0, // SerialIsSupported :1 + 0, // PrinterIsSupported :1 + 0, // CgaMonoIsSupported :1 + 0, // NecPc98 :1 + 0, // AcpiIsSupported :1 + 0, // UsbLegacyIsSupported :1 + 0, // AgpIsSupported :1 + 0, // I20BootIsSupported :1 + 0, // Ls120BootIsSupported :1 + 0, // AtapiZipDriveBootIsSupported :1 + 0, // Boot1394IsSupported :1 + 0, // SmartBatteryIsSupported :1 + 0, // BiosBootSpecIsSupported :1 + 0, // FunctionKeyNetworkBootIsSupported :1 + 0 // Reserved :22 + }, + { // BiosCharacteristics2 + 0, // BiosReserved :16 + 0, // SystemReserved :16 + 0 // Reserved :32 + }, +}; + +/* eof - MiscBiosVendorData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBootInformationData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBootInformationData.c new file mode 100644 index 0000000000..1bf280b141 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscBootInformationData.c @@ -0,0 +1,33 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscBootInformationData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_BOOT_INFORMATION_STATUS_DATA, BootInformationStatus) = { + EfiBootInformationStatusNoError, // BootInformationStatus + 0 // BootInformationData +}; + +/* eof - MiscBootInformationData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscChassisManufacturer.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscChassisManufacturer.uni new file mode 100644 index 0000000000..67bee85037 Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscChassisManufacturer.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscChassisManufacturerData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscChassisManufacturerData.c new file mode 100644 index 0000000000..5c657eef15 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscChassisManufacturerData.c @@ -0,0 +1,45 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscChassisManufacturerData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Chassis Manufacturer data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_CHASSIS_MANUFACTURER_DATA, MiscChassisManufacturer) = { + STRING_TOKEN(STR_MISC_CHASSIS_MANUFACTURER), // ChassisManufactrurer + STRING_TOKEN(STR_MISC_CHASSIS_VERSION), // ChassisVersion + STRING_TOKEN(STR_MISC_CHASSIS_SERIAL_NUMBER), // ChassisSerialNumber + STRING_TOKEN(STR_MISC_CHASSIS_ASSET_TAG), // ChassisAssetTag + { // ChassisTypeStatus + EfiMiscChassisTypeOther, // ChassisType + 0, // ChassisLockPresent + 0 // Reserved + }, + EfiChassisStateOther, // ChassisBootupState + EfiChassisStateOther, // ChassisPowerSupplyState + EfiChassisStateOther, // ChassisThermalState + EfiChassisSecurityStatusOther, // ChassisSecurityState + 0 // ChassisOemDefined +}; + +/* eof - MiscChassisManufacaturerData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscDevicePath.h b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscDevicePath.h new file mode 100644 index 0000000000..1568e27b32 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscDevicePath.h @@ -0,0 +1,175 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscDevicePath.h + +Abstract: + + Misc class required EFI Device Path definitions (Ports, slots & + onboard devices) + +--*/ + +#ifndef _MISC_DEVICE_PATH_H +#define _MISC_DEVICE_PATH_H + + +#pragma pack(1) +// +// USB +// + +/* For reference: +#define USB1_1_STR "ACPI(PNP0A03,0)/PCI(1D,0)." +#define USB1_2_STR "ACPI(PNP0A03,0)/PCI(1D,1)." +#define USB1_3_STR "ACPI(PNP0A03,0)/PCI(1D,2)." +#define USB2_1_STR "ACPI(PNP0A03,0)/PCI(1D,7)." +*/ + +// +// #define acpi { 0x02, 0x01, 0x00, 0x0C, 0x0a0341d0, 0x00000000 } +// #define pci( device,function) { 0x01, 0x01, 0x00, 0x06, device, function } +// #define end { 0xFF, 0xFF, 0x00, 0x04 } +// +#define ACPI \ + { \ + ACPI_DEVICE_PATH, ACPI_DP, (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), (UINT8) \ + ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8), EISA_PNP_ID (0x0A03), 0 \ + } +#define PCI(device, function) \ + { \ + HARDWARE_DEVICE_PATH, HW_PCI_DP, (UINT8) (sizeof (PCI_DEVICE_PATH)), (UINT8) \ + ((sizeof (PCI_DEVICE_PATH)) >> 8), function, device \ + } +#define END \ + { \ + END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, END_DEVICE_PATH_LENGTH, 0 \ + } + +#define LPC(eisaid, function) \ + { \ + ACPI_DEVICE_PATH, ACPI_DP, (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)), (UINT8) \ + ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8), EISA_PNP_ID (eisaid), function \ + } + +// +// Shanmu >> moved to TianoDevicePath.h +// + +/* +typedef struct _USB_PORT_DEVICE_PATH +{ + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH PciBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} USB_PORT_DEVICE_PATH; + + +//IDE ??I am not sure. Should this be ATAPI_DEVICE_PATH +typedef struct _IDE_DEVICE_PATH +{ + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH PciBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} IDE_DEVICE_PATH; + +//RMC Connector +typedef struct _RMC_CONN_DEVICE_PATH +{ + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH PciBridgeDevicePath; + PCI_DEVICE_PATH PciBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} RMC_CONN_DEVICE_PATH; + +//static RMC_CONN_DEVICE_PATH mRmcConnDevicePath = { acpi, pci( 0x1E,0x00 ),pci( 0x0A,0x00 ), end }; + +//RIDE +typedef struct _RIDE_DEVICE_PATH +{ + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH PciBridgeDevicePath; + PCI_DEVICE_PATH PciBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} RIDE_DEVICE_PATH; + +//static RIDE_DEVICE_PATH mRideDevicePath = { acpi, pci( 0x1E,0x00 ),pci( 0x02,0x00 ), end }; + +//Gigabit NIC +//typedef struct _GB_NIC_DEVICE_PATH +//{ +// ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; +// PCI_DEVICE_PATH PciBridgeDevicePath; +// PCI_DEVICE_PATH PciXBridgeDevicePath; +// PCI_DEVICE_PATH PciXBusDevicePath; +// EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +//} GB_NIC_DEVICE_PATH; + +//static GB_NIC_DEVICE_PATH mGbNicDevicePath = { acpi, pci( 0x03,0x00 ),pci( 0x1F,0x00 ),pci( 0x07,0x00 ), end }; + + +//P/S2 Connector +typedef struct _PS2_CONN_DEVICE_PATH +{ + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH LpcBridgeDevicePath; + ACPI_HID_DEVICE_PATH LpcBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} PS2_CONN_DEVICE_PATH; + +//static PS2_CONN_DEVICE_PATH mPs2KeyboardDevicePath = { acpi, pci( 0x1F,0x00 ),lpc( 0x0303,0 ), end }; +//static PS2_CONN_DEVICE_PATH mPs2MouseDevicePath = { acpi, pci( 0x1F,0x00 ),lpc( 0x0303,1 ), end }; + +//Serial Port Connector +typedef struct _SERIAL_CONN_DEVICE_PATH +{ + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH LpcBridgeDevicePath; + ACPI_HID_DEVICE_PATH LpcBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} SERIAL_CONN_DEVICE_PATH; + +//static SERIAL_CONN_DEVICE_PATH mCom1DevicePath = { acpi, pci( 0x1F,0x00 ),lpc( 0x0501,0 ), end }; +//static SERIAL_CONN_DEVICE_PATH mCom2DevicePath = { acpi, pci( 0x1F,0x00 ),lpc( 0x0501,1 ), end }; + +//Parallel Port Connector +typedef struct _PARALLEL_CONN_DEVICE_PATH +{ + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH LpcBridgeDevicePath; + ACPI_HID_DEVICE_PATH LpcBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} PARALLEL_CONN_DEVICE_PATH; + +//static PARALLEL_CONN_DEVICE_PATH mLpt1DevicePath = { acpi, pci( 0x1F,0x00 ),lpc( 0x0401,0 ), end }; + +//Floopy Connector +typedef struct _FLOOPY_CONN_DEVICE_PATH +{ + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH LpcBridgeDevicePath; + ACPI_HID_DEVICE_PATH LpcBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} FLOOPY_CONN_DEVICE_PATH; + +//static FLOOPY_CONN_DEVICE_PATH mFloopyADevicePath = { acpi, pci( 0x1F,0x00 ),lpc( 0x0604,0 ), end }; +//static FLOOPY_CONN_DEVICE_PATH mFloopyBDevicePath = { acpi, pci( 0x1F,0x00 ),lpc( 0x0604,1 ), end }; + +*/ + +// +// End Shanmu +// +#pragma pack() + +#endif diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscNumberOfInstallableLanguagesData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscNumberOfInstallableLanguagesData.c new file mode 100644 index 0000000000..008425987b --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscNumberOfInstallableLanguagesData.c @@ -0,0 +1,37 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscNumberOfInstallableLanguagesData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES_DATA, NumberOfInstallableLanguages) = { + 1, // NumberOfInstallableLanguages + { // LanguageFlags + 0, // AbbreviatedLanguageFormat + 0 // Reserved + }, + 0, // CurrentLanguageNumber +}; + +/* eof - MiscNumberOfInstallableLanguagesData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOemString.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOemString.uni new file mode 100644 index 0000000000..fb79bdbde1 Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOemString.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOemStringData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOemStringData.c new file mode 100644 index 0000000000..fdfbd1f2e1 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOemStringData.c @@ -0,0 +1,32 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscOemStringData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_OEM_STRING_DATA, OemString) = { + STRING_TOKEN(STR_MISC_OEM_STRING) +}; + +/* eof - MiscOemStringData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOnboardDevice.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOnboardDevice.uni new file mode 100644 index 0000000000..b24529b804 Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOnboardDevice.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOnboardDeviceData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOnboardDeviceData.c new file mode 100644 index 0000000000..e7fa04a29b --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOnboardDeviceData.c @@ -0,0 +1,36 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscOnboardDeviceData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_ONBOARD_DEVICE_DATA, MiscOnboardDevice) = { + STRING_TOKEN(STR_MISC_ONBOARD_DEVICE_DESCRIPTION), // OnBoardDeviceDescription + { // OnBoardDeviceStatus + EfiOnBoardDeviceTypeOther, // DeviceType + 0, // DeviceEnabled + 0 // Reserved + }, + 0 // OnBoardDevicePath +}; diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOnboardDeviceFunction.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOnboardDeviceFunction.c new file mode 100644 index 0000000000..d96b6cc2ad --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscOnboardDeviceFunction.c @@ -0,0 +1,164 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscOnboardDeviceFunction.c + +Abstract: + + Onboard device information boot time changes. + Misc. subclass type 8. + SMBIOS type 10. + +--*/ + +#include "MiscSubclassDriver.h" +#include "winntio/winntio.h" +#include "winntthunk/winntthunk.h" + +#pragma pack(1) + +typedef struct _VENDOR_DEVICE { + EFI_DEVICE_PATH_PROTOCOL Platform; + EFI_GUID PlatformGuid; + EFI_DEVICE_PATH_PROTOCOL Device; + EFI_GUID DeviceGuid; + UINT8 DeviceData[4]; + EFI_DEVICE_PATH_PROTOCOL End; + +} VENDOR_DEVICE; +#pragma pack() + +MISC_SUBCLASS_TABLE_FUNCTION ( + MiscOnboardDeviceVideo + ) +/*++ +Description: + + This function makes boot time changes to the contents of the + MiscOnboardDevice structure. + +Parameters: + + RecordType + Type of record to be processed from the Data Table. + mMiscSubclassDataTable[].RecordType + + RecordLen + Size of static RecordData from the Data Table. + mMiscSubclassDataTable[].RecordLen + + RecordData + Pointer to copy of RecordData from the Data Table. Changes made + to this copy will be written to the Data Hub but will not alter + the contents of the static Data Table. + + LogRecordData + Set *LogRecordData to TRUE to log RecordData to Data Hub. + Set *LogRecordData to FALSE when there is no more data to log. + +Returns: + + EFI_SUCCESS + All parameters were valid and *RecordData and *LogRecordData have + been set. + + EFI_UNSUPPORTED + Unexpected RecordType value. + + EFI_INVALID_PARAMETER + One of the following parameter conditions was true: + RecordLen was zero. + RecordData was NULL. + LogRecordData was NULL. +--*/ +{ + STATIC VENDOR_DEVICE mVideoDevicePath = { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + 0x14 + }, + EFI_WIN_NT_THUNK_PROTOCOL_GUID, + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + 0x18 + }, + EFI_WIN_NT_UGA_GUID, + 0, + 0, + 0, + 0, + END + }; + + STATIC BOOLEAN Done = FALSE; + + // + // First check for invalid parameters. + // + if (RecordLen == 0 || RecordData == NULL || LogRecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Then check for unsupported RecordType. + // + if (RecordType != EFI_MISC_ONBOARD_DEVICE_DATA_RECORD_NUMBER) { + return EFI_UNSUPPORTED; + } + // + // Is this the first time through this function? + // + if (!Done) { + // + // Yes, this is the first time. Inspect/Change the contents of the + // RecordData structure. + // + // + // Any time changes? + // + // %%TBD + // + // Set Done flag to TRUE for next pass through this function. + // Set *LogRecordData to TRUE so data will get logged to Data Hub. + // + switch (((EFI_MISC_ONBOARD_DEVICE_DATA *) RecordData)->OnBoardDeviceDescription) { + case STR_MISC_ONBOARD_DEVICE_VIDEO_DESCRIPTION: + { + CopyMem ( + &((EFI_MISC_ONBOARD_DEVICE_DATA *) RecordData)->OnBoardDevicePath, + &mVideoDevicePath, + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mVideoDevicePath) + ); + *RecordLen = *RecordLen - sizeof (EFI_DEVICE_PATH_PROTOCOL) + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mVideoDevicePath); + } + break; + } + + Done = TRUE; + *LogRecordData = TRUE; + } else { + // + // No, this is the second time. Reset the state of the Done flag + // to FALSE and tell the data logger that there is no more data + // to be logged for this record type. If any memory allocations + // were made by earlier passes, they must be released now. + // + Done = FALSE; + *LogRecordData = FALSE; + } + + return EFI_SUCCESS; +} + +/* eof - MiscOnboardDeviceFunction.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscPortInternalConnectorDesignator.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscPortInternalConnectorDesignator.uni new file mode 100644 index 0000000000..b6a617b75e Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscPortInternalConnectorDesignator.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscPortInternalConnectorDesignatorData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscPortInternalConnectorDesignatorData.c new file mode 100644 index 0000000000..d886a9d8c4 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscPortInternalConnectorDesignatorData.c @@ -0,0 +1,99 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscPortInternalConnectorDesignatorData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortInternalConnectorDesignator) = { + STRING_TOKEN(STR_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR), // PortInternalConnectorDesignator + STRING_TOKEN(STR_MISC_PORT_EXTERNAL_CONNECTOR_DESIGNATOR), // PortExternalConnectorDesignator + EfiPortConnectorTypeOther, // PortInternalConnectorType + EfiPortConnectorTypeOther, // PortExternalConnectorType + EfiPortTypeNone, // PortType + 0 // PortPath +}; + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortKeyboard) = { + STRING_TOKEN (STR_MISC_PORT_INTERNAL_KEYBOARD), // PortInternalConnectorDesignator + STRING_TOKEN (STR_MISC_PORT_EXTERNAL_KEYBOARD), // PortExternalConnectorDesignator + EfiPortConnectorTypeNone, // PortInternalConnectorType + EfiPortConnectorTypePS2, // PortExternalConnectorType + EfiPortTypeKeyboard, // PortType + // mPs2KbyboardDevicePath // PortPath + // + 0 +}; + +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortMouse) = { + STRING_TOKEN (STR_MISC_PORT_INTERNAL_MOUSE), // PortInternalConnectorDesignator + STRING_TOKEN (STR_MISC_PORT_EXTERNAL_MOUSE), // PortExternalConnectorDesignator + EfiPortConnectorTypeNone, // PortInternalConnectorType + EfiPortConnectorTypePS2, // PortExternalConnectorType + EfiPortTypeMouse, // PortType + // mPs2MouseDevicePath // PortPath + // + 0 +}; + + +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortCom1) = { + STRING_TOKEN(STR_MISC_PORT_INTERNAL_COM1), + STRING_TOKEN(STR_MISC_PORT_EXTERNAL_COM1), + EfiPortConnectorTypeNone, + EfiPortConnectorTypeDB9Female, + EfiPortTypeSerial16550ACompatible, + 0 +}; + +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortCom2) = { + STRING_TOKEN(STR_MISC_PORT_INTERNAL_COM2), + STRING_TOKEN(STR_MISC_PORT_EXTERNAL_COM2), + EfiPortConnectorTypeNone, + EfiPortConnectorTypeDB9Female, + EfiPortTypeSerial16550ACompatible, + 0 +}; + +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortExtensionPower) = { + STRING_TOKEN(STR_MISC_PORT_INTERNAL_EXTENSION_POWER), + STRING_TOKEN(STR_MISC_PORT_EXTERNAL_EXTENSION_POWER), + EfiPortConnectorTypeOther, + EfiPortConnectorTypeNone, + EfiPortTypeOther, + 0 +}; + +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, MiscPortFloppy) = { + STRING_TOKEN(STR_MISC_PORT_INTERNAL_FLOPPY), + STRING_TOKEN(STR_MISC_PORT_EXTERNAL_FLOPPY), + EfiPortConnectorTypeOnboardFloppy, + EfiPortConnectorTypeNone, + EfiPortTypeOther, + 0 +}; + +/* eof - MiscPortInternalConnectorDesignatorData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscPortInternalConnectorDesignatorFunction.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscPortInternalConnectorDesignatorFunction.c new file mode 100644 index 0000000000..a57c18c69b --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscPortInternalConnectorDesignatorFunction.c @@ -0,0 +1,266 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscPortInternalConnectorDesignatorFunction.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// +// +MISC_SUBCLASS_TABLE_FUNCTION ( + MiscPortInternalConnectorDesignator + ) +/*++ +Description: + + This function makes boot time changes to the contents of the + MiscPortConnectorInformation (Type 8). + +Parameters: + + RecordType + Type of record to be processed from the Data Table. + mMiscSubclassDataTable[].RecordType + + RecordLen + Size of static RecordData from the Data Table. + mMiscSubclassDataTable[].RecordLen + + RecordData + Pointer to copy of RecordData from the Data Table. Changes made + to this copy will be written to the Data Hub but will not alter + the contents of the static Data Table. + + LogRecordData + Set *LogRecordData to TRUE to log RecordData to Data Hub. + Set *LogRecordData to FALSE when there is no more data to log. + +Returns: + + EFI_SUCCESS + All parameters were valid and *RecordData and *LogRecordData have + been set. + + EFI_UNSUPPORTED + Unexpected RecordType value. + + EFI_INVALID_PARAMETER + One of the following parameter conditions was true: + RecordLen was zero. + RecordData was NULL. + LogRecordData was NULL. +--*/ +{ + STATIC BOOLEAN Done = FALSE; + STATIC PS2_CONN_DEVICE_PATH mPs2KeyboardDevicePath = { ACPI, PCI (0x1F, 0x00), LPC (0x0303, 0), END }; + STATIC PS2_CONN_DEVICE_PATH mPs2MouseDevicePath = { ACPI, PCI (0x1F, 0x00), LPC (0x0303, 1), END }; + STATIC SERIAL_CONN_DEVICE_PATH mCom1DevicePath = { ACPI, PCI (0x1F, 0x00), LPC (0x0501, 0), END }; + STATIC SERIAL_CONN_DEVICE_PATH mCom2DevicePath = { ACPI, PCI (0x1F, 0x00), LPC (0x0501, 1), END }; + STATIC PARALLEL_CONN_DEVICE_PATH mLpt1DevicePath = { ACPI, PCI (0x1F, 0x00), LPC (0x0401, 0), END }; + STATIC FLOOPY_CONN_DEVICE_PATH mFloopyADevicePath = { ACPI, PCI (0x1F, 0x00), LPC (0x0604, 0), END }; + STATIC FLOOPY_CONN_DEVICE_PATH mFloopyBDevicePath = { ACPI, PCI (0x1F, 0x00), LPC (0x0604, 1), END }; + STATIC USB_PORT_DEVICE_PATH mUsb0DevicePath = { ACPI, PCI (0x1d, 0x00), END }; + STATIC USB_PORT_DEVICE_PATH mUsb1DevicePath = { ACPI, PCI (0x1d, 0x01), END }; + STATIC USB_PORT_DEVICE_PATH mUsb2DevicePath = { ACPI, PCI (0x1d, 0x02), END }; + STATIC USB_PORT_DEVICE_PATH mUsb3DevicePath = { ACPI, PCI (0x1d, 0x07), END }; + STATIC IDE_DEVICE_PATH mIdeDevicePath = { ACPI, PCI (0x1F, 0x01), END }; + STATIC GB_NIC_DEVICE_PATH mGbNicDevicePath = { ACPI, PCI( 0x03,0x00 ),PCI( 0x1F,0x00 ),PCI( 0x07,0x00 ), END }; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath = END; + + // + // First check for invalid parameters. + // + // Shanmu >> to fix the Device Path Issue... + // if (RecordLen == 0 || RecordData == NULL || LogRecordData == NULL) { + // + if (*RecordLen == 0 || RecordData == NULL || LogRecordData == NULL) { + // + // End Shanmu + // + return EFI_INVALID_PARAMETER; + } + // + // Then check for unsupported RecordType. + // + if (RecordType != EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER) { + return EFI_UNSUPPORTED; + } + // + // Is this the first time through this function? + // + if (!Done) { + // + // Yes, this is the first time. Inspect/Change the contents of the + // RecordData structure. + // + // + // Device path is only updated here as it was not taking that in static data + // + // Shanmu >> to fix the Device Path Issue... + // + + /* + switch (((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortInternalConnectorDesignator) + { + case STR_MISC_PORT_INTERNAL_MOUSE: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mPs2MouseDevicePath); + }break; + case STR_MISC_PORT_INTERNAL_KEYBOARD: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mPs2KeyboardDevicePath); + }break; + case STR_MISC_PORT_INTERNAL_COM1: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mCom1DevicePath); + }break; + case STR_MISC_PORT_INTERNAL_COM2: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mCom2DevicePath); + }break; + case STR_MISC_PORT_INTERNAL_LPT1: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mLpt1DevicePath); + }break; + case STR_MISC_PORT_INTERNAL_USB1: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mUsb0DevicePath); + }break; + case STR_MISC_PORT_INTERNAL_USB2: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mUsb1DevicePath); + }break; + case STR_MISC_PORT_INTERNAL_USB3: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mUsb2DevicePath); + }break; + case STR_MISC_PORT_INTERNAL_NETWORK: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mGbNicDevicePath); + }break; + case STR_MISC_PORT_INTERNAL_FLOPPY: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mFloopyADevicePath); + }break; + case STR_MISC_PORT_INTERNAL_IDE1: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mIdeDevicePath); + }break; + case STR_MISC_PORT_INTERNAL_IDE2: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = *((EFI_DEVICE_PATH_PROTOCOL*)&mIdeDevicePath); + }break; + default: + { + (EFI_DEVICE_PATH_PROTOCOL)((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *)RecordData)->PortPath = EndDevicePath; + }break; + } + */ + switch (((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) RecordData)->PortInternalConnectorDesignator) { + case STR_MISC_PORT_INTERNAL_MOUSE: + { + CopyMem ( + &((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) RecordData)->PortPath, + &mPs2MouseDevicePath, + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mPs2MouseDevicePath) + ); + *RecordLen = *RecordLen - sizeof (EFI_MISC_PORT_DEVICE_PATH) + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mPs2MouseDevicePath); + } + break; + + case STR_MISC_PORT_INTERNAL_KEYBOARD: + { + CopyMem ( + &((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) RecordData)->PortPath, + &mPs2KeyboardDevicePath, + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mPs2KeyboardDevicePath) + ); + *RecordLen = *RecordLen - sizeof (EFI_MISC_PORT_DEVICE_PATH) + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mPs2KeyboardDevicePath); + } + break; + + case STR_MISC_PORT_INTERNAL_COM1: + { + CopyMem ( + &((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) RecordData)->PortPath, + &mCom1DevicePath, + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mCom1DevicePath) + ); + *RecordLen = *RecordLen - sizeof (EFI_MISC_PORT_DEVICE_PATH) + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mCom1DevicePath); + } + break; + + case STR_MISC_PORT_INTERNAL_COM2: + { + CopyMem ( + &((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) RecordData)->PortPath, + &mCom2DevicePath, + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mCom2DevicePath) + ); + *RecordLen = *RecordLen - sizeof (EFI_MISC_PORT_DEVICE_PATH) + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mCom2DevicePath); + } + break; + + case STR_MISC_PORT_INTERNAL_FLOPPY: + { + CopyMem ( + &((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) RecordData)->PortPath, + &mFloopyADevicePath, + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mFloopyADevicePath) + ); + *RecordLen = *RecordLen - sizeof (EFI_MISC_PORT_DEVICE_PATH) + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &mFloopyADevicePath); + } + break; + + default: + { + CopyMem ( + &((EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) RecordData)->PortPath, + &EndDevicePath, + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &EndDevicePath) + ); + *RecordLen = *RecordLen - sizeof (EFI_MISC_PORT_DEVICE_PATH) + GetDevicePathSize ((EFI_DEVICE_PATH_PROTOCOL *) &EndDevicePath); + } + break; + } + // + // End Shanmu + // + // Set Done flag to TRUE for next pass through this function. + // Set *LogRecordData to TRUE so data will get logged to Data Hub. + // + Done = TRUE; + *LogRecordData = TRUE; + } else { + // + // No, this is the second time. Reset the state of the Done flag + // to FALSE and tell the data logger that there is no more data + // to be logged for this record type. If any memory allocations + // were made by earlier passes, they must be released now. + // + Done = FALSE; + *LogRecordData = FALSE; + } + + return EFI_SUCCESS; +} + +/* eof - MiscSystemManufacturerFunction.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscResetCapabilitiesData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscResetCapabilitiesData.c new file mode 100644 index 0000000000..6e0c1bb5ad --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscResetCapabilitiesData.c @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscResetCapabilitiesData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_RESET_CAPABILITIES, MiscResetCapabilities) = { + { // ResetCapabilities + 0, // Status + 0, // BootOption + 0, // BootOptionOnLimit + 0, // WatchdogTimerPresent + 0 // Reserved + }, + 0, // ResetCount + 0, // ResetLimit + 0, // ResetTimerInterval + 0 // ResetTimeout +}; + +/* eof - MiscResetCapabilities.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.dxs b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.dxs new file mode 100644 index 0000000000..8698317e55 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscSubclassDriver.dxs + +Abstract: + + Dependency expression file for MiscSubclass Driver. + +--*/ + +#include +#include + +DEPENDENCY_START + EFI_DATA_HUB_PROTOCOL_GUID AND EFI_HII_PROTOCOL_GUID +DEPENDENCY_END diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.h b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.h new file mode 100644 index 0000000000..32f591fdf1 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.h @@ -0,0 +1,104 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscSubclassDriver.h + +Abstract: + + Header file for MiscSubclass Driver. + +--*/ + +#ifndef _MISC_SUBCLASS_DRIVER_H +#define _MISC_SUBCLASS_DRIVER_H + + +#include + +// +// Autogen string file +// +#include + +// +// Data table entry update function. +// +typedef +EFI_STATUS +(EFIAPI EFI_MISC_SUBCLASS_DATA_FUNCTION) ( + IN UINT16 RecordType, + IN UINT32 *RecordLen, + IN OUT EFI_MISC_SUBCLASS_RECORDS *RecordData, + OUT BOOLEAN *LogRecordData + ); + +// +// Data table entry definition. +// +typedef struct { + UINT16 RecordType; + UINT32 RecordLen; + VOID *RecordData; + EFI_MISC_SUBCLASS_DATA_FUNCTION *Function; +} EFI_MISC_SUBCLASS_DATA_TABLE; + +// +// Data Table extern definitions. +// +#define MISC_SUBCLASS_TABLE_EXTERNS(NAME1, NAME2) \ + extern NAME1 NAME2 ## Data; \ + extern EFI_MISC_SUBCLASS_DATA_FUNCTION NAME2 ## Function + +// +// Data Table entries +// +#define MISC_SUBCLASS_TABLE_ENTRY_DATA_ONLY(NAME1, NAME2) { \ + NAME1 ## _RECORD_NUMBER, sizeof (NAME1 ## _DATA), &NAME2 ## Data, NULL \ + } + +#define MISC_SUBCLASS_TABLE_ENTRY_FUNCTION_ONLY(NAME1, NAME2) \ + { \ + NAME1 ## _RECORD_NUMBER, 0, NULL, &NAME2 ## Function \ + } + +#define MISC_SUBCLASS_TABLE_ENTRY_DATA_AND_FUNCTION(NAME1, NAME2, NAME3) \ + { \ + NAME1 ## _RECORD_NUMBER, sizeof (NAME1 ## _DATA), &NAME2 ## Data, &NAME3 ## Function \ + } + +// +// Global definition macros. +// +#define MISC_SUBCLASS_TABLE_DATA(NAME1, NAME2) NAME1 NAME2 ## Data + +#define MISC_SUBCLASS_TABLE_FUNCTION(NAME2) \ + EFI_STATUS EFIAPI NAME2 ## Function ( \ + IN UINT16 RecordType, \ + IN UINT32 *RecordLen, \ + IN OUT EFI_MISC_SUBCLASS_RECORDS * RecordData, \ + OUT BOOLEAN *LogRecordData \ + ) + +// +// Data Table Array +// +extern EFI_MISC_SUBCLASS_DATA_TABLE mMiscSubclassDataTable[]; + +// +// Data Table Array Entries +// +extern UINTN mMiscSubclassDataTableEntries; + +#endif /* _MISC_SUBCLASS_DRIVER_H */ + +/* eof - MiscSubclassDriver.h */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.mbd b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.mbd new file mode 100644 index 0000000000..921c5c5e41 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.mbd @@ -0,0 +1,45 @@ + + + + + MiscSubclass + 4A9B9DB8-EC62-4A92-818F-8AA0246D246E + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-13 17:07 + 2006-03-23 13:50 + + + UefiBootServicesTableLib + BaseLib + UefiLib + HiiLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeMemoryAllocationLib + UefiDevicePathLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.msa b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.msa new file mode 100644 index 0000000000..fb5252f0c0 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.msa @@ -0,0 +1,114 @@ + + + + + MiscSubclass + DXE_DRIVER + BS_DRIVER + 4A9B9DB8-EC62-4A92-818F-8AA0246D246E + 0 + Component description file for MiscSubclass Driver module + FIX ME! + Copyright (c) 2006, 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. + + 0 + 2006-03-13 17:07 + 2006-03-23 13:50 + + + BaseLib + DebugLib + HiiLib + UefiLib + UefiDriverEntryPoint + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + DevicePathLib + + + MiscSubclassDriver.uni + MiscSubclassDriver.h + MiscSubclassDriverEntryPoint.c + MiscSubclassDriverDataTable.c + MiscBaseBoardManufacturerData.c + MiscBiosVendorData.c + MiscBootInformationData.c + MiscChassisManufacturerData.c + MiscNumberOfInstallableLanguagesData.c + MiscOemStringData.c + MiscOnboardDeviceData.c + MiscPortInternalConnectorDesignatorData.c + MiscResetCapabilitiesData.c + MiscSystemLanguageStringData.c + MiscSystemManufacturerData.c + MiscSystemManufacturerFunction.c + MiscSystemOptionStringData.c + MiscSystemSlotDesignationData.c + MiscPortInternalConnectorDesignatorFunction.c + MiscSubclassDriver.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + DataHub + Hii + WinNtIo + + + MiscPortKeyboard + MiscPortMouse + MiscPortCom1 + MiscPortCom2 + MiscBiosVendor + MiscSystemManufacturer + MiscBaseBoardManufacturer + MiscChassisManufacturer + MiscSystemSlotDesignation + OemString + SystemOptionString + ProcessorSubClassData + MemorySubClassData + + + + MiscSubClass + + + ProcessorSubClass + + + MemoryProducer + + + MemorySubClass + + + WinNtMemory + + + + + MiscSubclassDriverEntryPoint + + + diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.uni new file mode 100644 index 0000000000..1d6899c81c Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriverDataTable.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriverDataTable.c new file mode 100644 index 0000000000..c2d149631a --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriverDataTable.c @@ -0,0 +1,103 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscSubclassDriverDataTable.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// External definitions referenced by Data Table entries. +// +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_CHASSIS_MANUFACTURER_DATA, + MiscChassisManufacturer + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_BIOS_VENDOR_DATA, + MiscBiosVendor + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_SYSTEM_MANUFACTURER_DATA, + MiscSystemManufacturer + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_BASE_BOARD_MANUFACTURER_DATA, + MiscBaseBoardManufacturer + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, + MiscPortInternalConnectorDesignator + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, + MiscPortKeyboard + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, + MiscPortMouse + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, + MiscPortCom1 + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA, + MiscPortCom2 + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, + MiscSystemSlotDesignation + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_ONBOARD_DEVICE_DATA, + MiscOnboardDevice + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_OEM_STRING_DATA, + OemString + ); +MISC_SUBCLASS_TABLE_EXTERNS ( + EFI_MISC_SYSTEM_OPTION_STRING_DATA, + SystemOptionString + ); + +// +// Data Table. +// +EFI_MISC_SUBCLASS_DATA_TABLE mMiscSubclassDataTable[] = { + MISC_SUBCLASS_TABLE_ENTRY_DATA_AND_FUNCTION(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortKeyboard, MiscPortInternalConnectorDesignator), + MISC_SUBCLASS_TABLE_ENTRY_DATA_AND_FUNCTION(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortMouse, MiscPortInternalConnectorDesignator), + MISC_SUBCLASS_TABLE_ENTRY_DATA_AND_FUNCTION(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortCom1, MiscPortInternalConnectorDesignator), + MISC_SUBCLASS_TABLE_ENTRY_DATA_AND_FUNCTION(EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR, MiscPortCom2, MiscPortInternalConnectorDesignator), + MISC_SUBCLASS_TABLE_ENTRY_DATA_ONLY(EFI_MISC_BIOS_VENDOR, MiscBiosVendor), + MISC_SUBCLASS_TABLE_ENTRY_DATA_ONLY(EFI_MISC_SYSTEM_MANUFACTURER, MiscSystemManufacturer), + MISC_SUBCLASS_TABLE_ENTRY_DATA_ONLY(EFI_MISC_BASE_BOARD_MANUFACTURER, MiscBaseBoardManufacturer), + MISC_SUBCLASS_TABLE_ENTRY_DATA_ONLY(EFI_MISC_CHASSIS_MANUFACTURER, MiscChassisManufacturer), + MISC_SUBCLASS_TABLE_ENTRY_DATA_ONLY(EFI_MISC_SYSTEM_SLOT_DESIGNATION, MiscSystemSlotDesignation), + MISC_SUBCLASS_TABLE_ENTRY_DATA_ONLY(EFI_MISC_OEM_STRING, OemString), + MISC_SUBCLASS_TABLE_ENTRY_DATA_ONLY(EFI_MISC_SYSTEM_OPTION_STRING, SystemOptionString), +}; + +// +// Number of Data Table entries. +// +UINTN mMiscSubclassDataTableEntries = (sizeof mMiscSubclassDataTable) / sizeof (EFI_MISC_SUBCLASS_DATA_TABLE); + +/* eof - MiscSubclassDriverDataTable.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriverEntryPoint.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriverEntryPoint.c new file mode 100644 index 0000000000..f0e09a6152 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriverEntryPoint.c @@ -0,0 +1,518 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscSubclassDriverEntryPoint.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + + +extern UINT8 MiscSubclassStrings[]; + +VOID +EFIAPI +WinNtIoProtocolNotifyFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// +// +EFI_STATUS +LogRecordDataToDataHub ( + EFI_DATA_HUB_PROTOCOL *DataHub, + UINT32 RecordType, + UINT32 RecordLen, + VOID *RecordData + ) +/*++ +Description: + +Parameters: + + DataHub + %%TBD + + RecordType + %%TBD + + RecordLen + %%TBD + + RecordData + %%TBD + +Returns: + + EFI_INVALID_PARAMETER + + EFI_SUCCESS + + Other Data Hub errors + +--*/ +{ + EFI_MISC_SUBCLASS_DRIVER_DATA MiscSubclass; + EFI_STATUS EfiStatus; + + // + // Do nothing if data parameters are not valid. + // + if (RecordLen == 0 || RecordData == NULL) { + DEBUG ( + (EFI_D_ERROR, + "RecordLen == %d RecordData == %xh\n", + RecordLen, + RecordData) + ); + + return EFI_INVALID_PARAMETER; + } + // + // Assemble Data Hub record. + // + MiscSubclass.Header.Version = EFI_MISC_SUBCLASS_VERSION; + MiscSubclass.Header.HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER); + MiscSubclass.Header.Instance = 1; + MiscSubclass.Header.SubInstance = 1; + MiscSubclass.Header.RecordType = RecordType; + + CopyMem ( + &MiscSubclass.Record, + RecordData, + RecordLen + ); + + // + // Log Data Hub record. + // + EfiStatus = DataHub->LogData ( + DataHub, + &gEfiMiscSubClassGuid, + &gEfiMiscSubClassGuid, + EFI_DATA_RECORD_CLASS_DATA, + &MiscSubclass, + sizeof (EFI_SUBCLASS_TYPE1_HEADER) + RecordLen + ); + + if (EFI_ERROR (EfiStatus)) { + DEBUG ( + (EFI_D_ERROR, + "LogData(%d bytes) == %r\n", + sizeof (EFI_SUBCLASS_TYPE1_HEADER) + RecordLen, + EfiStatus) + ); + } + + return EfiStatus; +} + + +EFI_STATUS +EFIAPI +MiscSubclassDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ +Description: + + Standard EFI driver point. This driver parses the mMiscSubclassDataTable + structure and reports any generated data to the DataHub. + +Arguments: + + ImageHandle + Handle for the image of this driver + + SystemTable + Pointer to the EFI System Table + +Returns: + + EFI_SUCCESS + The data was successfully reported to the Data Hub. + +--*/ +{ + EFI_MISC_SUBCLASS_DRIVER_DATA RecordData; + EFI_DATA_HUB_PROTOCOL *DataHub; + EFI_HII_PROTOCOL *Hii; + EFI_HII_PACKAGES *PackageList; + EFI_HII_HANDLE HiiHandle; + EFI_STATUS EfiStatus; + UINTN Index; + BOOLEAN LogRecordData; + EFI_EVENT Event; + VOID *Registration; + + + // + // Initialize constant portion of subclass header. + // + RecordData.Header.Version = EFI_MISC_SUBCLASS_VERSION; + RecordData.Header.HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER); + RecordData.Header.Instance = 1; + RecordData.Header.SubInstance = 1; + + // + // Locate data hub protocol. + // + EfiStatus = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub); + + if (EFI_ERROR (EfiStatus)) { + DEBUG ((EFI_D_ERROR, "Could not locate DataHub protocol. %r\n", EfiStatus)); + return EfiStatus; + } else if (DataHub == NULL) { + DEBUG ((EFI_D_ERROR, "LocateProtocol(DataHub) returned NULL pointer!\n")); + return EFI_DEVICE_ERROR; + } + // + // Locate hii protocol. + // + EfiStatus = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, &Hii); + + if (EFI_ERROR (EfiStatus)) { + DEBUG ((EFI_D_ERROR, "Could not locate Hii protocol. %r\n", EfiStatus)); + return EfiStatus; + } else if (Hii == NULL) { + DEBUG ((EFI_D_ERROR, "LocateProtocol(Hii) returned NULL pointer!\n")); + return EFI_DEVICE_ERROR; + } + // + // Add our default strings to the HII database. They will be modified later. + // + PackageList = PreparePackages (1, &gEfiMiscSubClassGuid, MiscSubclassStrings); + EfiStatus = Hii->NewPack (Hii, PackageList, &HiiHandle); + gBS->FreePool (PackageList); + + if (EFI_ERROR (EfiStatus)) { + DEBUG ((EFI_D_ERROR, "Could not log default strings to Hii. %r\n", EfiStatus)); + return EfiStatus; + } + // + // + // + for (Index = 0; Index < mMiscSubclassDataTableEntries; ++Index) { + // + // Stupidity check! Do nothing if RecordLen is zero. + // %%TBD - Should this be an error or a mechanism for ignoring + // records in the Data Table? + // + if (mMiscSubclassDataTable[Index].RecordLen == 0) { + DEBUG ( + (EFI_D_ERROR, + "mMiscSubclassDataTable[%d].RecordLen == 0\n", + Index) + ); + + continue; + } + // + // Initialize per-record portion of subclass header and + // copy static data into data portion of subclass record. + // + RecordData.Header.RecordType = mMiscSubclassDataTable[Index].RecordType; + + if (mMiscSubclassDataTable[Index].RecordData == NULL) { + ZeroMem ( + &RecordData.Record, + mMiscSubclassDataTable[Index].RecordLen + ); + } else { + CopyMem ( + &RecordData.Record, + mMiscSubclassDataTable[Index].RecordData, + mMiscSubclassDataTable[Index].RecordLen + ); + } + // + // If the entry does not have a function pointer, just log the data. + // + if (mMiscSubclassDataTable[Index].Function == NULL) { + // + // Log RecordData to Data Hub. + // + EfiStatus = DataHub->LogData ( + DataHub, + &gEfiMiscSubClassGuid, + &gEfiMiscSubClassGuid, + EFI_DATA_RECORD_CLASS_DATA, + &RecordData, + sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen + ); + + if (EFI_ERROR (EfiStatus)) { + DEBUG ( + (EFI_D_ERROR, + "LogData(%d bytes) == %r\n", + sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen, + EfiStatus) + ); + } + + continue; + } + // + // The entry has a valid function pointer. + // Keep calling the function and logging data until there + // is no more data to log. + // + for (;;) { + // + // + // + EfiStatus = (*mMiscSubclassDataTable[Index].Function) + ( + mMiscSubclassDataTable[Index].RecordType, &mMiscSubclassDataTable[Index].RecordLen, &RecordData.Record, & + LogRecordData + ); + + // + // + // + if (EFI_ERROR (EfiStatus)) { + break; + } + + if (!LogRecordData) { + break; + } + // + // + // + EfiStatus = DataHub->LogData ( + DataHub, + &gEfiMiscSubClassGuid, + &gEfiMiscSubClassGuid, + EFI_DATA_RECORD_CLASS_DATA, + &RecordData, + sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen + ); + + if (EFI_ERROR (EfiStatus)) { + DEBUG ( + (EFI_D_ERROR, + "LogData(%d bytes) == %r\n", + sizeof (EFI_SUBCLASS_TYPE1_HEADER) + mMiscSubclassDataTable[Index].RecordLen, + EfiStatus) + ); + } + } + } + // + // Install notify function to fetch memory data through WinNtIo protocol and store to data hub. + // + EfiStatus = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + WinNtIoProtocolNotifyFunction, + ImageHandle, + &Event + ); + ASSERT (!EFI_ERROR (EfiStatus)); + + EfiStatus = gBS->RegisterProtocolNotify ( + &gEfiWinNtIoProtocolGuid, + Event, + &Registration + ); + ASSERT (!EFI_ERROR (EfiStatus)); + + return EFI_SUCCESS; +} + +UINTN +Atoi ( + CHAR16 *String + ) +/*++ + +Routine Description: + Convert a unicode string to a UINTN + +Arguments: + String - Unicode string. + +Returns: + UINTN of the number represented by String. + +--*/ +{ + UINTN Number; + CHAR16 *Str; + + // + // skip preceeding white space + // + Str = String; + while ((*Str) && (*Str == ' ' || *Str == '"')) { + Str++; + } + // + // Convert ot a Number + // + Number = 0; + while (*Str != '\0') { + if ((*Str >= '0') && (*Str <= '9')) { + Number = (Number * 10) +*Str - '0'; + } else { + break; + } + + Str++; + } + + return Number; +} + +VOID +EFIAPI +WinNtIoProtocolNotifyFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + This function will log memory size data to data hub. + +Arguments: +Event - Event whose notification function is being invoked. +Context - Pointer to the notification function's context. + +Returns: + EFI_STATUS. + +--*/ +{ + EFI_STATUS Status; + EFI_MEMORY_SUBCLASS_DRIVER_DATA MemorySubClassData; + EFI_DATA_RECORD_HEADER *Record; + EFI_SUBCLASS_TYPE1_HEADER *DataHeader; + UINTN HandleCount; + UINTN HandleIndex; + UINT64 MonotonicCount; + BOOLEAN RecordFound; + EFI_HANDLE *HandleBuffer; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + EFI_DATA_HUB_PROTOCOL *DataHub; + UINT64 TotalMemorySize; + + DataHub = NULL; + MonotonicCount = 0; + RecordFound = FALSE; + + // + // Retrieve the list of all handles from the handle database. + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + &gEfiWinNtIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return ; + } + // + // Locate DataHub protocol. + // + Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub); + if (EFI_ERROR (Status)) { + return ; + } + // + // Search the Handle array to find the meory size information. + // + for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { + Status = gBS->OpenProtocol ( + HandleBuffer[HandleIndex], + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + Context, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + continue; + } + + if ((WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) && + CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtMemoryGuid) + ) { + // + // Check if this record has been stored in data hub. + // + do { + Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record); + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1); + if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) && + (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER) + ) { + RecordFound = TRUE; + } + } + } while (MonotonicCount != 0); + + if (RecordFound) { + RecordFound = FALSE; + continue; + } + // + // Initialize data record. + // + MemorySubClassData.Header.Instance = 1; + MemorySubClassData.Header.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE; + MemorySubClassData.Header.RecordType = EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER; + + TotalMemorySize = (UINT64) Atoi (WinNtIo->EnvString); + + MemorySubClassData.Record.ArrayStartAddress.MemoryArrayStartAddress = 0; + MemorySubClassData.Record.ArrayStartAddress.MemoryArrayEndAddress = LShiftU64 (TotalMemorySize, 20) - 1; + MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.ProducerName = gEfiMemoryProducerGuid; + MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.Instance = 1; + MemorySubClassData.Record.ArrayStartAddress.PhysicalMemoryArrayLink.SubInstance = EFI_SUBCLASS_INSTANCE_NON_APPLICABLE; + MemorySubClassData.Record.ArrayStartAddress.MemoryArrayPartitionWidth = 0; + + // + // Store memory size data record to data hub. + // + Status = DataHub->LogData ( + DataHub, + &gEfiMemorySubClassGuid, + &gEfiMemoryProducerGuid, + EFI_DATA_RECORD_CLASS_DATA, + &MemorySubClassData, + sizeof (EFI_SUBCLASS_TYPE1_HEADER) + sizeof (EFI_MEMORY_ARRAY_START_ADDRESS_DATA) + ); + } + + gBS->CloseProtocol ( + HandleBuffer[HandleIndex], + &gEfiWinNtIoProtocolGuid, + Context, + NULL + ); + } +} + diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemLanguageString.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemLanguageString.uni new file mode 100644 index 0000000000..36dacf066a Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemLanguageString.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemLanguageStringData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemLanguageStringData.c new file mode 100644 index 0000000000..ef52513d58 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemLanguageStringData.c @@ -0,0 +1,33 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscSystemLanguageStringData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_SYSTEM_LANGUAGE_STRING_DATA, SystemLanguageString) = { + 0, + STRING_TOKEN(STR_MISC_SYSTEM_LANGUAGE_STRING) +}; + +/* eof - MiscSystemLanguageStringData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemManufacturer.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemManufacturer.uni new file mode 100644 index 0000000000..204588ef8c Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemManufacturer.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemManufacturerData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemManufacturerData.c new file mode 100644 index 0000000000..be53e39a71 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemManufacturerData.c @@ -0,0 +1,55 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscSystemManufacturerData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) System Manufacturer data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_SYSTEM_MANUFACTURER_DATA, MiscSystemManufacturer) += { + STRING_TOKEN(STR_MISC_SYSTEM_MANUFACTURER), + // SystemManufactrurer + STRING_TOKEN(STR_MISC_SYSTEM_PRODUCT_NAME), + // SystemProductName + STRING_TOKEN(STR_MISC_SYSTEM_VERSION), + // SystemVersion + STRING_TOKEN(STR_MISC_SYSTEM_SERIAL_NUMBER), + // SystemSerialNumber + { + 0xbadfaced, + 0xdead, + 0xbeef, + 0x13, + 0x13, + 0x13, + 0x13, + 0x13, + 0x13, + 0x13, + 0x13 + }, + // SystemUuid + EfiSystemWakeupTypePowerSwitch // SystemWakeupType +}; + +/* eof - MiscSystemManufacturerData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemManufacturerFunction.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemManufacturerFunction.c new file mode 100644 index 0000000000..ddd749bfdb --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemManufacturerFunction.c @@ -0,0 +1,122 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscSystemManufacturerFunction.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// +// +MISC_SUBCLASS_TABLE_FUNCTION ( + MiscSystemManufacturer + ) +/*++ +Description: + + This function makes boot time changes to the contents of the + MiscSystemManufacturer (Type 13). + +Parameters: + + RecordType + Type of record to be processed from the Data Table. + mMiscSubclassDataTable[].RecordType + + RecordLen + Size of static RecordData from the Data Table. + mMiscSubclassDataTable[].RecordLen + + RecordData + Pointer to copy of RecordData from the Data Table. Changes made + to this copy will be written to the Data Hub but will not alter + the contents of the static Data Table. + + LogRecordData + Set *LogRecordData to TRUE to log RecordData to Data Hub. + Set *LogRecordData to FALSE when there is no more data to log. + +Returns: + + EFI_SUCCESS + All parameters were valid and *RecordData and *LogRecordData have + been set. + + EFI_UNSUPPORTED + Unexpected RecordType value. + + EFI_INVALID_PARAMETER + One of the following parameter conditions was true: + RecordLen was zero. + RecordData was NULL. + LogRecordData was NULL. +--*/ +{ + STATIC BOOLEAN Done = FALSE; + + // + // First check for invalid parameters. + // + if (*RecordLen == 0 || RecordData == NULL || LogRecordData == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Then check for unsupported RecordType. + // + if (RecordType != EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER) { + return EFI_UNSUPPORTED; + } + // + // Is this the first time through this function? + // + if (!Done) { + // + // Yes, this is the first time. Inspect/Change the contents of the + // RecordData structure. + // + // + // Set system GUID. + // + // ((EFI_MISC_SYSTEM_MANUFACTURER_DATA *)RecordData)->SystemUuid = %%TBD + // + // Set power-on type. + // + // ((EFI_MISC_SYSTEM_MANUFACTURER_DATA *)RecordData)->SystemWakeupType = %%TBD + // + // Set Done flag to TRUE for next pass through this function. + // Set *LogRecordData to TRUE so data will get logged to Data Hub. + // + Done = TRUE; + *LogRecordData = TRUE; + } else { + // + // No, this is the second time. Reset the state of the Done flag + // to FALSE and tell the data logger that there is no more data + // to be logged for this record type. If any memory allocations + // were made by earlier passes, they must be released now. + // + Done = FALSE; + *LogRecordData = FALSE; + } + + return EFI_SUCCESS; +} + +/* eof - MiscSystemManufacturerFunction.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemOptionString.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemOptionString.uni new file mode 100644 index 0000000000..617578d6a3 Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemOptionString.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemOptionStringData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemOptionStringData.c new file mode 100644 index 0000000000..8c00350f64 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemOptionStringData.c @@ -0,0 +1,32 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscSystemOptionStringData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_SYSTEM_OPTION_STRING_DATA, SystemOptionString) = { + STRING_TOKEN(STR_MISC_SYSTEM_OPTION_STRING) +}; + +/* eof - MiscSystemOptionStringData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemSlotDesignation.uni b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemSlotDesignation.uni new file mode 100644 index 0000000000..f279ff960d Binary files /dev/null and b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemSlotDesignation.uni differ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemSlotDesignationData.c b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemSlotDesignationData.c new file mode 100644 index 0000000000..d5e1474fe2 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/MiscSystemSlotDesignationData.c @@ -0,0 +1,52 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MiscSystemSlotDesignationData.c + +Abstract: + + This driver parses the mMiscSubclassDataTable structure and reports + any generated data to the DataHub. + +--*/ + +#include "MiscSubclassDriver.h" + +// +// Static (possibly build generated) Bios Vendor data. +// +MISC_SUBCLASS_TABLE_DATA(EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA, MiscSystemSlotDesignation) = { + STRING_TOKEN(STR_MISC_SYSTEM_SLOT_DESIGNATION), // SlotDesignation + EfiSlotTypeOther, // SlotType + EfiSlotDataBusWidthOther, // SlotDataBusWidth + EfiSlotUsageOther, // SlotUsage + EfiSlotLengthOther, // SlotLength + 0, // SlotId + { // SlotCharacteristics + 0, // CharacteristicsUnknown :1; + 0, // Provides50Volts :1; + 0, // Provides33Volts :1; + 0, // SharedSlot :1; + 0, // PcCard16Supported :1; + 0, // CardBusSupported :1; + 0, // ZoomVideoSupported :1; + 0, // ModemRingResumeSupported:1; + 0, // PmeSignalSupported :1; + 0, // HotPlugDevicesSupported :1; + 0, // SmbusSignalSupported :1; + 0 // Reserved :21; + }, + 0 // SlotDevicePath +}; + +/* eof - MiscSystemSlotsData.c */ diff --git a/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/build.xml b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/build.xml new file mode 100644 index 0000000000..7265194134 --- /dev/null +++ b/EdkNt32Pkg/Dxe/Nt32Platform/MiscSubclass/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.c b/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.c new file mode 100644 index 0000000000..38863b8a02 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.c @@ -0,0 +1,557 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PcdEmulator.c + +Abstract: + Platform Configuration Database (PCD) Protocol + +--*/ + +#include + +UINTN mSkuId = 0; + +STATIC UINTN +GetPcdDataEntryCount ( + VOID +) { + return gEmulatedPcdDatabaseEx->Count; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSetSku ( + IN UINTN SkuId + ) +{ + mSkuId = SkuId; + return EFI_SUCCESS; +} + +UINT8 +EFIAPI +PcdEmulatorGet8 ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + ASSERT (Pcd->DatumSize == 1); + + return (UINT8)Pcd->Datum; +} + +UINT16 +EFIAPI +PcdEmulatorGet16 ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + ASSERT (Pcd->DatumSize == 2); + + return (UINT16)Pcd->Datum; +} + +UINT32 +EFIAPI +PcdEmulatorGet32 ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + ASSERT (Pcd->DatumSize == 4); + + return (UINT32)Pcd->Datum; +} + +UINT64 +EFIAPI +PcdEmulatorGet64 ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + ASSERT (Pcd->DatumSize == sizeof (UINT64)); + + return (UINT64)Pcd->Datum; +} + +VOID * +EFIAPI +PcdEmulatorGetPtr ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + + return (VOID *)(UINTN)Pcd->ExtendedData; +} + +BOOLEAN +EFIAPI +PcdEmulatorGetBoolean ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + ASSERT (Pcd->DatumSize == 1); + + return (BOOLEAN)Pcd->Datum; +} + +UINTN +EFIAPI +PcdEmulatorGetSize ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + return Pcd->DatumSize; +} + +UINT8 +EFIAPI +PcdEmulatorGet8Ex ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT16 +EFIAPI +PcdEmulatorGet16Ex ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT32 +EFIAPI +PcdEmulatorGet32Ex ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT64 +EFIAPI +PcdEmulatorGet64Ex ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +VOID * +EFIAPI +PcdEmulatorGetPtrEx ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +BOOLEAN +EFIAPI +PcdEmulatorGetBooleanEx ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +UINTN +EFIAPI +PcdEmulatorGetSizeEx ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + return Pcd->DatumSize; +} + + +EFI_STATUS +EFIAPI +PcdEmulatorSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + + ASSERT (Pcd->DatumSize == sizeof (UINT8)); + + Pcd->Datum = Value; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + + ASSERT (Pcd->DatumSize == sizeof (UINT32)); + + Pcd->Datum = Value; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSetPtr ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSetBoolean ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet8Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet16Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet32Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet64Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSetPtrEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSetBooleanEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + + if (Pcd->CallBackListSize == Pcd->CallBackEntries) { + return EFI_OUT_OF_RESOURCES; + } + + Pcd->CallBackList[Pcd->CallBackEntries++] = CallBackFunction; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorUnregisterCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackfunction + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + UINT32 Index; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + + for (Index = 0; Index < Pcd->CallBackListSize; Index++) { + if (Pcd->CallBackList[Index] == CallBackfunction) { + Pcd->CallBackList[Index] = NULL; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +PcdEmulatorGetNextToken ( + IN CONST EFI_GUID *Guid, OPTIONAL + IN UINTN *Token + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + EMULATED_PCD_ENTRY_EX *LastPcdEntry; + + if (*Token == PCD_INVALID_TOKEN) { + // + // BugBug: Due to variable size array, ensure we convert this to a reasonable database + // that can accomodate array references for simplicity's sake + *Token = gEmulatedPcdEntryEx[0].Token; + return EFI_SUCCESS; + } + + Pcd = GetPcdEntry (*Token); + if (Pcd == NULL) { + return EFI_NOT_FOUND; + } + + LastPcdEntry = gEmulatedPcdEntryEx + GetPcdDataEntryCount (); + if (++Pcd >= LastPcdEntry) { + return EFI_NOT_FOUND; + } + + *Token = Pcd->Token; + return EFI_SUCCESS; +} + +PCD_PROTOCOL mPcdProtocolInstance = { + PcdEmulatorSetSku, + + PcdEmulatorGet8, + PcdEmulatorGet16, + PcdEmulatorGet32, + PcdEmulatorGet64, + PcdEmulatorGetPtr, + PcdEmulatorGetBoolean, + PcdEmulatorGetSize, + + PcdEmulatorGet8Ex, + PcdEmulatorGet16Ex, + PcdEmulatorGet32Ex, + PcdEmulatorGet64Ex, + PcdEmulatorGetPtrEx, + PcdEmulatorGetBooleanEx, + PcdEmulatorGetSizeEx, + + PcdEmulatorSet8, + PcdEmulatorSet16, + PcdEmulatorSet32, + PcdEmulatorSet64, + PcdEmulatorSetPtr, + PcdEmulatorSetBoolean, + + PcdEmulatorSet8Ex, + PcdEmulatorSet16Ex, + PcdEmulatorSet32Ex, + PcdEmulatorSet64Ex, + PcdEmulatorSetPtrEx, + PcdEmulatorSetBooleanEx, + + PcdEmulatorCallBackOnSet, + PcdEmulatorUnregisterCallBackOnSet, + PcdEmulatorGetNextToken +}; + + +EFI_STATUS +EFIAPI +PcdEmulatorEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = GetFirstGuidHob (&gPcdHobGuid); + gEmulatedPcdDatabaseEx = (EMULATED_PCD_DATABASE_EX *) GET_GUID_HOB_DATA(GuidHob); + ASSERT (gEmulatedPcdDatabaseEx != NULL); + gEmulatedPcdEntryEx = gEmulatedPcdDatabaseEx->Entry; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ImageHandle, + &gPcdProtocolGuid, &mPcdProtocolInstance, + NULL + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + + +EMULATED_PCD_ENTRY_EX * +GetPcdEntry ( + IN UINTN TokenNumber + ) +{ + UINTN Index; + UINTN Count; + + Count = GetPcdDataEntryCount (); + for (Index = 0; Index < Count; Index++) { + if (gEmulatedPcdEntryEx[Index].Token == TokenNumber) { + return &gEmulatedPcdEntryEx[Index]; + } + } + return NULL; +} diff --git a/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.dxs b/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.dxs new file mode 100644 index 0000000000..9e814a6f85 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PcdEmulator.dxs + +Abstract: + + Dependency expression source file. + +--*/ + +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.h b/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.h new file mode 100644 index 0000000000..b49afb188d --- /dev/null +++ b/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.h @@ -0,0 +1,43 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PcdEmulator.h + +Abstract: + Platform Configuration Database (PCD) + +--*/ + +#ifndef __PCD_EMULATOR_H__ +#define __PCD_EMULATOR_H__ + + + +// +// BugBug: Not very sure, where to put this "extern" +// +extern GUID gPcdHobGuid; + +// +// BugBug: Hack max number of callbacks per token +// +#define MAX_PCD_CALLBACK 0x10 + +EMULATED_PCD_ENTRY_EX *gEmulatedPcdEntryEx; +EMULATED_PCD_DATABASE_EX *gEmulatedPcdDatabaseEx; + +EMULATED_PCD_ENTRY_EX * +GetPcdEntry ( + IN UINTN TokenNumber + ); + +#endif diff --git a/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.mbd b/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.mbd new file mode 100644 index 0000000000..93000692ef --- /dev/null +++ b/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.mbd @@ -0,0 +1,46 @@ + + + + + PcdEmulator + 80CF7257-87AB-47f9-A3FE-D50B76D89541 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + BaseLib + DxeHobLib + UefiLib + HiiLib + DxeWinNtLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.msa b/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.msa new file mode 100644 index 0000000000..ec4a0c1d71 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PcdEmulator/PcdEmulator.msa @@ -0,0 +1,75 @@ + + + + + PcdEmulator + DXE_DRIVER + BS_DRIVER + 80CF7257-87AB-47f9-A3FE-D50B76D89541 + 0 + Component description file for DxeIpl module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + BaseLib + DebugLib + HiiLib + UefiLib + UefiDriverEntryPoint + PcdLib + WinNtLib + HobLib + MemoryAllocationLib + UefiBootServicesTableLib + + + PcdEmulator.c + PcdEmulator.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + Pcd + + + + PcdDataBase + gPcdHobGuid + 0x582e7ca1, 0x68cd, 0x4d44, 0xb4, 0x3b, 0xf2, 0x98, 0xed, 0x58, 0x7b, 0xa6 + + + + + PcdHob + + + + + PcdEmulatorEntry + + + diff --git a/EdkNt32Pkg/Dxe/PcdEmulator/build.xml b/EdkNt32Pkg/Dxe/PcdEmulator/build.xml new file mode 100644 index 0000000000..603876b2c3 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PcdEmulator/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/PlatformBds/BdsPlatform.c b/EdkNt32Pkg/Dxe/PlatformBds/BdsPlatform.c new file mode 100644 index 0000000000..d1edef3d7e --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/BdsPlatform.c @@ -0,0 +1,517 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BdsPlatform.c + +Abstract: + + This file include all platform action which can be customized + by IBV/OEM. + +--*/ + +#include "Generic/Bds.h" +#include "BdsPlatform.h" +#include "Generic/String.h" +#include "Generic/Language.h" +#include "Generic/FrontPage.h" + +CHAR16 mFirmwareVendor[] = L"TianoCore.org"; + +// +// BDS Platform Functions +// +VOID +PlatformBdsInit ( + IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData + ) +/*++ + +Routine Description: + + Platform Bds init. Incude the platform firmware vendor, revision + and so crc check. + +Arguments: + + PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance + +Returns: + + None. + +--*/ +{ + // + // set firmwarevendor, here can be IBV/OEM customize + // + gST->FirmwareVendor = AllocateRuntimeCopyPool ( + sizeof (mFirmwareVendor), + &mFirmwareVendor + ); + ASSERT (gST->FirmwareVendor != NULL); + + gST->FirmwareRevision = EFI_FIRMWARE_REVISION; + + // + // Fixup Tasble CRC after we updated Firmware Vendor and Revision + // + gBS->CalculateCrc32 ((VOID *) gST, sizeof (EFI_SYSTEM_TABLE), &gST->Hdr.CRC32); + + // + // Initialize the platform specific string and language + // + InitializeStringSupport (); + InitializeLanguage (TRUE); + InitializeFrontPage (FALSE); + +} + +EFI_STATUS +PlatformBdsConnectConsole ( + IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole + ) +/*++ + +Routine Description: + + Connect the predefined platform default console device. Always try to find + and enable the vga device if have. + +Arguments: + + PlatformConsole - Predfined platform default console device array. + +Returns: + + EFI_SUCCESS - Success connect at least one ConIn and ConOut + device, there must have one ConOut device is + active vga device. + + EFI_STATUS - Return the status of + BdsLibConnectAllDefaultConsoles () + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + + Index = 0; + Status = EFI_SUCCESS; + + // + // Have chance to connect the platform default console, + // the platform default console is the minimue device group + // the platform should support + // + while (PlatformConsole[Index].DevicePath != NULL) { + // + // Update the console variable with the connect type + // + if ((PlatformConsole[Index].ConnectType & CONSOLE_IN) == CONSOLE_IN) { + BdsLibUpdateConsoleVariable (L"ConIn", PlatformConsole[Index].DevicePath, NULL); + } + + if ((PlatformConsole[Index].ConnectType & CONSOLE_OUT) == CONSOLE_OUT) { + BdsLibUpdateConsoleVariable (L"ConOut", PlatformConsole[Index].DevicePath, NULL); + } + + if ((PlatformConsole[Index].ConnectType & STD_ERROR) == STD_ERROR) { + BdsLibUpdateConsoleVariable (L"ErrOut", PlatformConsole[Index].DevicePath, NULL); + } + + Index++; + } + // + // Connect the all the default console with current cosole variable + // + Status = BdsLibConnectAllDefaultConsoles (); + if (EFI_ERROR (Status)) { + return Status; + } + + return EFI_SUCCESS; +} + +VOID +PlatformBdsConnectSequence ( + VOID + ) +/*++ + +Routine Description: + + Connect with predeined platform connect sequence, + the OEM/IBV can customize with their own connect sequence. + +Arguments: + + None. + +Returns: + + None. + +--*/ +{ + UINTN Index; + + Index = 0; + + // + // Here we can get the customized platform connect sequence + // Notes: we can connect with new variable which record the + // last time boots connect device path sequence + // + while (gPlatformConnectSequence[Index] != NULL) { + // + // Build the platform boot option + // + BdsLibConnectDevicePath (gPlatformConnectSequence[Index]); + Index++; + } + +} + +VOID +PlatformBdsGetDriverOption ( + IN OUT LIST_ENTRY *BdsDriverLists + ) +/*++ + +Routine Description: + + Load the predefined driver option, OEM/IBV can customize this + to load their own drivers + +Arguments: + + BdsDriverLists - The header of the driver option link list. + +Returns: + + None. + +--*/ +{ + UINTN Index; + + Index = 0; + + // + // Here we can get the customized platform driver option + // + while (gPlatformDriverOption[Index] != NULL) { + // + // Build the platform boot option + // + BdsLibRegisterNewOption (BdsDriverLists, gPlatformDriverOption[Index], NULL, L"DriverOrder"); + Index++; + } + +} + +VOID +PlatformBdsDiagnostics ( + IN EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel, + IN BOOLEAN QuietBoot + ) +/*++ + +Routine Description: + + Perform the platform diagnostic, such like test memory. OEM/IBV also + can customize this fuction to support specific platform diagnostic. + +Arguments: + + MemoryTestLevel - The memory test intensive level + + QuietBoot - Indicate if need to enable the quiet boot + +Returns: + + None. + +--*/ +{ + EFI_STATUS Status; + + // + // Here we can decide if we need to show + // the diagnostics screen + // Notes: this quiet boot code should be remove + // from the graphic lib + // + if (QuietBoot) { + EnableQuietBoot (&gEfiUgaSplashProtocolGuid); + // + // Perform system diagnostic + // + Status = BdsMemoryTest (MemoryTestLevel); + if (EFI_ERROR (Status)) { + DisableQuietBoot (); + } + + return ; + } + // + // Perform system diagnostic + // + Status = BdsMemoryTest (MemoryTestLevel); +} + +VOID +PlatformBdsPolicyBehavior ( + IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData, + IN OUT LIST_ENTRY *DriverOptionList, + IN OUT LIST_ENTRY *BootOptionList + ) +/*++ + +Routine Description: + + The function will excute with as the platform policy, current policy + is driven by boot mode. IBV/OEM can customize this code for their specific + policy action. + +Arguments: + + PrivateData - The EFI_BDS_ARCH_PROTOCOL_INSTANCE instance + + DriverOptionList - The header of the driver option link list + + BootOptionList - The header of the boot option link list + +Returns: + + None. + +--*/ +{ + EFI_STATUS Status; + UINT16 Timeout; + + // + // Init the time out value + // + Timeout = BdsLibGetTimeout (); + + // + // Load the driver option as the driver option list + // + PlatformBdsGetDriverOption (DriverOptionList); + + // + // Get current Boot Mode + // + Status = BdsLibGetBootMode (&PrivateData->BootMode); + + // + // Go the different platform policy with different boot mode + // Notes: this part code can be change with the table policy + // + switch (PrivateData->BootMode) { + + case BOOT_ASSUMING_NO_CONFIGURATION_CHANGES: + case BOOT_WITH_MINIMAL_CONFIGURATION: + // + // In no-configuration boot mode, we can connect the + // console directly. + // + BdsLibConnectAllDefaultConsoles (); + PlatformBdsDiagnostics (IGNORE, TRUE); + + // + // Perform some platform specific connect sequence + // + PlatformBdsConnectSequence (); + + // + // Notes: current time out = 0 can not enter the + // front page + // + PlatformBdsEnterFrontPage (Timeout, FALSE); + + // + // Check the boot option with the boot option list + // + BdsLibBuildOptionFromVar (BootOptionList, L"BootOrder"); + break; + + case BOOT_ON_FLASH_UPDATE: + // + // Boot with the specific configuration + // + PlatformBdsConnectConsole (gPlatformConsole); + PlatformBdsDiagnostics (EXTENSIVE, FALSE); + BdsLibConnectAll (); + ProcessCapsules (BOOT_ON_FLASH_UPDATE); + break; + + case BOOT_IN_RECOVERY_MODE: + // + // In recovery mode, just connect platform console + // and show up the front page + // + PlatformBdsConnectConsole (gPlatformConsole); + PlatformBdsDiagnostics (EXTENSIVE, FALSE); + + // + // In recovery boot mode, we still enter to the + // frong page now + // + PlatformBdsEnterFrontPage (Timeout, FALSE); + break; + + case BOOT_WITH_FULL_CONFIGURATION: + case BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS: + case BOOT_WITH_DEFAULT_SETTINGS: + default: + // + // Connect platform console + // + Status = PlatformBdsConnectConsole (gPlatformConsole); + if (EFI_ERROR (Status)) { + // + // Here OEM/IBV can customize with defined action + // + PlatformBdsNoConsoleAction (); + } + + PlatformBdsDiagnostics (IGNORE, TRUE); + + // + // Perform some platform specific connect sequence + // + PlatformBdsConnectSequence (); + + // + // Give one chance to enter the setup if we + // have the time out + // + PlatformBdsEnterFrontPage (Timeout, FALSE); + + // + // Here we have enough time to do the enumeration of boot device + // + BdsLibEnumerateAllBootOption (BootOptionList); + break; + } + + return ; + +} + +VOID +PlatformBdsBootSuccess ( + IN BDS_COMMON_OPTION *Option + ) +/*++ + +Routine Description: + + Hook point after a boot attempt succeeds. We don't expect a boot option to + return, so the EFI 1.0 specification defines that you will default to an + interactive mode and stop processing the BootOrder list in this case. This + is alos a platform implementation and can be customized by IBV/OEM. + +Arguments: + + Option - Pointer to Boot Option that succeeded to boot. + +Returns: + + None. + +--*/ +{ + CHAR16 *TmpStr; + + // + // If Boot returned with EFI_SUCCESS and there is not in the boot device + // select loop then we need to pop up a UI and wait for user input. + // + TmpStr = GetStringById (STRING_TOKEN (STR_BOOT_SUCCEEDED)); + if (TmpStr != NULL) { + BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); + gBS->FreePool (TmpStr); + } +} + +VOID +PlatformBdsBootFail ( + IN BDS_COMMON_OPTION *Option, + IN EFI_STATUS Status, + IN CHAR16 *ExitData, + IN UINTN ExitDataSize + ) +/*++ + +Routine Description: + + Hook point after a boot attempt fails. + +Arguments: + + Option - Pointer to Boot Option that failed to boot. + + Status - Status returned from failed boot. + + ExitData - Exit data returned from failed boot. + + ExitDataSize - Exit data size returned from failed boot. + +Returns: + + None. + +--*/ +{ + CHAR16 *TmpStr; + + // + // If Boot returned with failed status then we need to pop up a UI and wait + // for user input. + // + TmpStr = GetStringById (STRING_TOKEN (STR_BOOT_FAILED)); + if (TmpStr != NULL) { + BdsLibOutputStrings (gST->ConOut, TmpStr, Option->Description, L"\n\r", NULL); + gBS->FreePool (TmpStr); + } + +} + +EFI_STATUS +PlatformBdsNoConsoleAction ( + VOID + ) +/*++ + +Routine Description: + + This function is remained for IBV/OEM to do some platform action, + if there no console device can be connected. + +Arguments: + + None. + +Returns: + + EFI_SUCCESS - Direct return success now. + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/BdsPlatform.h b/EdkNt32Pkg/Dxe/PlatformBds/BdsPlatform.h new file mode 100644 index 0000000000..f3679fb88d --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/BdsPlatform.h @@ -0,0 +1,140 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BdsPlatform.h + +Abstract: + + Head file for BDS Platform specific code + +--*/ + +#ifndef _BDS_PLATFORM_H +#define _BDS_PLATFORM_H + +#include "IndustryStandard/Pci22.h" + +extern BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[]; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[]; +extern EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[]; + +#define gEndEntire \ + { \ + END_DEVICE_PATH_TYPE,\ + END_ENTIRE_DEVICE_PATH_SUBTYPE,\ + END_DEVICE_PATH_LENGTH,\ + 0\ + } + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + UINT32 Instance; +} WIN_NT_VENDOR_DEVICE_PATH_NODE; + +// +// Below is the platform console device path +// +typedef struct { + VENDOR_DEVICE_PATH NtBus; + WIN_NT_VENDOR_DEVICE_PATH_NODE SerialDevice; + UART_DEVICE_PATH Uart; + VENDOR_DEVICE_PATH TerminalType; + EFI_DEVICE_PATH_PROTOCOL End; +} NT_ISA_SERIAL_DEVICE_PATH; + +typedef struct { + VENDOR_DEVICE_PATH NtBus; + WIN_NT_VENDOR_DEVICE_PATH_NODE NtUgaDevice; + EFI_DEVICE_PATH_PROTOCOL End; +} NT_PLATFORM_UGA_DEVICE_PATH; + +// +// Platform BDS Functions +// +VOID +PlatformBdsInit ( + IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData + ) +; + +VOID +PlatformBdsPolicyBehavior ( + IN EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData, + IN LIST_ENTRY *DriverOptionList, + IN LIST_ENTRY *BootOptionList + ) +; + +VOID +PlatformBdsGetDriverOption ( + IN LIST_ENTRY *BdsDriverLists + ) +; + +EFI_STATUS +BdsMemoryTest ( + EXTENDMEM_COVERAGE_LEVEL Level + ) +; + +EFI_STATUS +PlatformBdsShowProgress ( + EFI_UGA_PIXEL TitleForeground, + EFI_UGA_PIXEL TitleBackground, + CHAR16 *Title, + EFI_UGA_PIXEL ProgressColor, + UINTN Progress, + UINTN PreviousValue + ) +; + +VOID +PlatformBdsConnectSequence ( + VOID + ) +; + +VOID +PlatformBdsBootFail ( + IN BDS_COMMON_OPTION *Option, + IN EFI_STATUS Status, + IN CHAR16 *ExitData, + IN UINTN ExitDataSize + ) +; + +VOID +PlatformBdsBootSuccess ( + IN BDS_COMMON_OPTION *Option + ) +; + +EFI_STATUS +ProcessCapsules ( + EFI_BOOT_MODE BootMode + ) +; + +EFI_STATUS +PlatformBdsConnectConsole ( + IN BDS_CONSOLE_CONNECT_ENTRY *PlatformConsole + ) +; + +EFI_STATUS +PlatformBdsNoConsoleAction ( + VOID + ) +; + +#endif // _BDS_PLATFORM_H diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/Bds.dxs b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Bds.dxs new file mode 100644 index 0000000000..6647561959 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Bds.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Bds.dxs + +Abstract: + + Dependency expression source file. This driver produces an arch protocol, so + must dipatch early. + +--*/ +#include +#include + +DEPENDENCY_START + EFI_HII_PROTOCOL_GUID +DEPENDENCY_END \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/Bds.h b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Bds.h new file mode 100644 index 0000000000..2d9d199610 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Bds.h @@ -0,0 +1,83 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Bds.h + +Abstract: + + Head file for BDS Architectural Protocol implementation + +Revision History + +--*/ + +#ifndef _BDS_H +#define _BDS_H + +// +// Bds AP Context data +// +#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 's', 'A') +typedef struct { + UINTN Signature; + + EFI_HANDLE Handle; + + EFI_BDS_ARCH_PROTOCOL Bds; + + // + // Save the current boot mode + // + EFI_BOOT_MODE BootMode; + + // + // Set true if boot with default settings + // + BOOLEAN DefaultBoot; + + // + // The system default timeout for choose the boot option + // + UINT16 TimeoutDefault; + + // + // Memory Test Level + // + EXTENDMEM_COVERAGE_LEVEL MemoryTestLevel; + +} EFI_BDS_ARCH_PROTOCOL_INSTANCE; + +#define EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS(_this) \ + CR (_this, \ + EFI_BDS_ARCH_PROTOCOL_INSTANCE, \ + Bds, \ + EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE \ + ) + +// +// Prototypes +// +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +EFI_STATUS +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ); + +#endif diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BdsEntry.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BdsEntry.c new file mode 100644 index 0000000000..ddd6b4f78e --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BdsEntry.c @@ -0,0 +1,356 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BdsEntry.c + +Abstract: + + The entry of the bds + +--*/ + +#include "Bds.h" +#include "BdsPlatform.h" +#include "FrontPage.h" + +EFI_BDS_ARCH_PROTOCOL_INSTANCE gBdsInstanceTemplate = { + EFI_BDS_ARCH_PROTOCOL_INSTANCE_SIGNATURE, + NULL, + BdsEntry, + 0xFFFF, + TRUE, + EXTENSIVE +}; + +UINT16 *mBootNext = NULL; + +EFI_HANDLE mBdsImageHandle; + +EFI_STATUS +EFIAPI +BdsInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Install Boot Device Selection Protocol + +Arguments: + + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + EFI_SUCEESS - BDS has finished initializing. + Rerun the + dispatcher and recall BDS.Entry + + Other - Return value from EfiLibAllocatePool() + or gBS->InstallProtocolInterface + +--*/ +{ + EFI_STATUS Status; + + mBdsImageHandle = ImageHandle; + + // + // Install protocol interface + // + Status = gBS->InstallProtocolInterface ( + &gBdsInstanceTemplate.Handle, + &gEfiBdsArchProtocolGuid, + EFI_NATIVE_INTERFACE, + &gBdsInstanceTemplate.Bds + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +VOID +BdsBootDeviceSelect ( + VOID + ) +/*++ + +Routine Description: + + In the loop of attempt to boot for the boot order + +Arguments: + + None. + +Returns: + + None. + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + BDS_COMMON_OPTION *BootOption; + UINTN ExitDataSize; + CHAR16 *ExitData; + UINT16 Timeout; + LIST_ENTRY BootLists; + CHAR16 Buffer[20]; + BOOLEAN BootNextExist; + LIST_ENTRY *LinkBootNext; + + // + // Got the latest boot option + // + BootNextExist = FALSE; + LinkBootNext = NULL; + InitializeListHead (&BootLists); + + // + // First check the boot next option + // + ZeroMem (Buffer, sizeof (Buffer)); + + if (mBootNext != NULL) { + // + // Indicate we have the boot next variable, so this time + // boot will always have this boot option + // + BootNextExist = TRUE; + + // + // Clear the this variable so it's only exist in this time boot + // + gRT->SetVariable ( + L"BootNext", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + mBootNext + ); + + // + // Add the boot next boot option + // + UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *mBootNext); + BootOption = BdsLibVariableToOption (&BootLists, Buffer); + } + // + // Parse the boot order to get boot option + // + BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); + Link = BootLists.ForwardLink; + + // + // Parameter check, make sure the loop will be valid + // + if (Link == NULL) { + return ; + } + // + // Here we make the boot in a loop, every boot success will + // return to the front page + // + for (;;) { + // + // Check the boot option list first + // + if (Link == &BootLists) { + // + // There are two ways to enter here: + // 1. There is no active boot option, give user chance to + // add new boot option + // 2. All the active boot option processed, and there is no + // one is success to boot, then we back here to allow user + // add new active boot option + // + Timeout = 0xffff; + PlatformBdsEnterFrontPage (Timeout, FALSE); + InitializeListHead (&BootLists); + BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); + Link = BootLists.ForwardLink; + continue; + } + // + // Get the boot option from the link list + // + BootOption = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + + // + // According to EFI Specification, if a load option is not marked + // as LOAD_OPTION_ACTIVE, the boot manager will not automatically + // load the option. + // + if (!IS_LOAD_OPTION_TYPE (BootOption->Attribute, LOAD_OPTION_ACTIVE)) { + // + // skip the header of the link list, becuase it has no boot option + // + Link = Link->ForwardLink; + continue; + } + // + // Make sure the boot option device path connected, + // but ignore the BBS device path + // + if (DevicePathType (BootOption->DevicePath) != BBS_DEVICE_PATH) { + // + // Notes: the internal shell can not been connected with device path + // so we do not check the status here + // + BdsLibConnectDevicePath (BootOption->DevicePath); + } + // + // All the driver options should have been processed since + // now boot will be performed. + // + PERF_END (0, BDS_TOK, NULL, 0); + Status = BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData); + if (EFI_ERROR (Status)) { + // + // Call platform action to indicate the boot fail + // + PlatformBdsBootFail (BootOption, Status, ExitData, ExitDataSize); + + // + // Check the next boot option + // + Link = Link->ForwardLink; + + } else { + // + // Call platform action to indicate the boot success + // + PlatformBdsBootSuccess (BootOption); + + // + // Boot success, then stop process the boot order, and + // present the boot manager menu, front page + // + Timeout = 0xffff; + PlatformBdsEnterFrontPage (Timeout, FALSE); + + // + // Rescan the boot option list, avoid pertential risk of the boot + // option change in front page + // + if (BootNextExist) { + LinkBootNext = BootLists.ForwardLink; + } + + InitializeListHead (&BootLists); + if (LinkBootNext != NULL) { + // + // Reserve the boot next option + // + InsertTailList (&BootLists, LinkBootNext); + } + + BdsLibBuildOptionFromVar (&BootLists, L"BootOrder"); + Link = BootLists.ForwardLink; + } + } + + return ; + +} + +EFI_STATUS +EFIAPI +BdsEntry ( + IN EFI_BDS_ARCH_PROTOCOL *This + ) +/*++ + +Routine Description: + + Service routine for BdsInstance->Entry(). Devices are connected, the + consoles are initialized, and the boot options are tried. + +Arguments: + + This - Protocol Instance structure. + +Returns: + + EFI_SUCEESS - BDS->Entry has finished executing. + +--*/ +{ + EFI_BDS_ARCH_PROTOCOL_INSTANCE *PrivateData; + LIST_ENTRY DriverOptionList; + LIST_ENTRY BootOptionList; + UINTN BootNextSize; + + // + // Insert the performance probe + // + PERF_END (0, DXE_TOK, NULL, 0); + PERF_START (0, BDS_TOK, NULL, 0); + + // + // Initialize the global system boot option and driver option + // + InitializeListHead (&DriverOptionList); + InitializeListHead (&BootOptionList); + + // + // Get the BDS private data + // + PrivateData = EFI_BDS_ARCH_PROTOCOL_INSTANCE_FROM_THIS (This); + + // + // Do the platform init, can be customized by OEM/IBV + // + PERF_START (0, "PlatformBds", "BDS", 0); + PlatformBdsInit (PrivateData); + + // + // Set up the device list based on EFI 1.1 variables + // process Driver#### and Load the driver's in the + // driver option list + // + BdsLibBuildOptionFromVar (&DriverOptionList, L"DriverOrder"); + if (!IsListEmpty (&DriverOptionList)) { + BdsLibLoadDrivers (&DriverOptionList); + } + // + // Check if we have the boot next option + // + mBootNext = BdsLibGetVariableAndSize ( + L"BootNext", + &gEfiGlobalVariableGuid, + &BootNextSize + ); + + // + // Setup some platform policy here + // + PlatformBdsPolicyBehavior (PrivateData, &DriverOptionList, &BootOptionList); + PERF_END (0, L"PlatformBds", L"BDS", 0); + + // + // BDS select the boot device to load OS + // + BdsBootDeviceSelect (); + + // + // Only assert here since this is the right behavior, we should never + // return back to DxeCore. + // + ASSERT (FALSE); + + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BBSsupport.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BBSsupport.c new file mode 100644 index 0000000000..a33be4b046 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BBSsupport.c @@ -0,0 +1,1515 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BBSsupport.c + +Abstract: + + This function deal with the legacy boot option, it create, delete + and manage the legacy boot option, all legacy boot option is getting from + the legacy BBS table. + +--*/ + +#include "BBSsupport.h" + +EFI_DEVICE_PATH_PROTOCOL EndDevicePath[] = { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + END_DEVICE_PATH_LENGTH, + 0 +}; + +VOID +AsciiToUnicodeSize ( + IN UINT8 *a, + IN UINTN Size, + OUT UINT16 *u + ) +{ + UINTN i; + + i = 0; + while (a[i] != 0) { + u[i] = (CHAR16) a[i]; + if (i == Size) { + u[i] = 0; + break; + } + + i++; + } +} + +VOID +BdsBuildLegacyDevNameString ( + IN BBS_TABLE *CurBBSEntry, + IN UINTN Index, + IN UINTN BufSize, + OUT CHAR16 *BootString + ) +{ + CHAR16 *Fmt; + CHAR16 *Type; + UINT8 *StringDesc; + CHAR16 temp[80]; + + switch (Index) { + // + // Primary Master + // + case 1: + Fmt = L"Primary Master %s"; + break; + + // + // Primary Slave + // + case 2: + Fmt = L"Primary Slave %s"; + break; + + // + // Secondary Master + // + case 3: + Fmt = L"Secondary Master %s"; + break; + + // + // Secondary Slave + // + case 4: + Fmt = L"Secondary Slave %s"; + break; + + default: + Fmt = L"%s"; + break; + } + + switch (CurBBSEntry->DeviceType) { + case BBS_FLOPPY: + Type = L"Floppy"; + break; + + case BBS_HARDDISK: + Type = L"Harddisk"; + break; + + case BBS_CDROM: + Type = L"CDROM"; + break; + + case BBS_PCMCIA: + Type = L"PCMCIAe"; + break; + + case BBS_USB: + Type = L"USB"; + break; + + case BBS_EMBED_NETWORK: + Type = L"Network"; + break; + + case BBS_BEV_DEVICE: + Type = L"BEVe"; + break; + + case BBS_UNKNOWN: + default: + Type = L"Unknown"; + break; + } + // + // If current BBS entry has its description then use it. + // + StringDesc = (UINT8 *) (UINTN) ((CurBBSEntry->DescStringSegment << 4) + CurBBSEntry->DescStringOffset); + if (NULL != StringDesc) { + // + // Only get fisrt 32 characters, this is suggested by BBS spec + // + AsciiToUnicodeSize (StringDesc, 32, temp); + Fmt = L"%s"; + Type = temp; + } + + UnicodeSPrint (BootString, BufSize, Fmt, Type); +} + +EFI_STATUS +BdsCreateLegacyBootOption ( + IN BBS_TABLE *CurrentBbsEntry, + IN EFI_DEVICE_PATH_PROTOCOL *CurrentBbsDevPath, + IN UINTN Index, + IN OUT UINT16 **BootOrderList, + IN OUT UINTN *BootOrderListSize + ) +{ + EFI_STATUS Status; + UINT16 CurrentBootOptionNo; + UINT16 BootString[10]; + UINT16 BootDesc[100]; + UINT16 *NewBootOrderList; + UINTN BufferSize; + VOID *Buffer; + UINT8 *Ptr; + UINT16 CurrentBbsDevPathSize; + UINTN BootOrderIndex; + UINTN BootOrderLastIndex; + UINTN ArrayIndex; + BOOLEAN IndexNotFound; + + if (NULL == (*BootOrderList)) { + CurrentBootOptionNo = 0; + } else { + for (ArrayIndex = 0; ArrayIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); ArrayIndex++) { + IndexNotFound = TRUE; + for (BootOrderIndex = 0; BootOrderIndex < (UINTN) (*BootOrderListSize / sizeof (UINT16)); BootOrderIndex++) { + if ((*BootOrderList)[BootOrderIndex] == ArrayIndex) { + IndexNotFound = FALSE; + break; + } + } + + if (!IndexNotFound) { + continue; + } else { + break; + } + } + + CurrentBootOptionNo = (UINT16) ArrayIndex; + } + + UnicodeSPrint ( + BootString, + sizeof (BootString), + L"Boot%04x", + CurrentBootOptionNo + ); + + BdsBuildLegacyDevNameString (CurrentBbsEntry, Index, sizeof (BootDesc), BootDesc); + + CurrentBbsDevPathSize = (UINT16) (GetDevicePathSize (CurrentBbsDevPath)); + + BufferSize = sizeof (UINT32) + + sizeof (UINT16) + + StrSize (BootDesc) + + CurrentBbsDevPathSize + + sizeof (BBS_TABLE) + + sizeof (UINT16); + + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Ptr = (UINT8 *) Buffer; + + *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE; + Ptr += sizeof (UINT32); + + *((UINT16 *) Ptr) = CurrentBbsDevPathSize; + Ptr += sizeof (UINT16); + + CopyMem ( + Ptr, + BootDesc, + StrSize (BootDesc) + ); + Ptr += StrSize (BootDesc); + + CopyMem ( + Ptr, + CurrentBbsDevPath, + CurrentBbsDevPathSize + ); + Ptr += CurrentBbsDevPathSize; + + CopyMem ( + Ptr, + CurrentBbsEntry, + sizeof (BBS_TABLE) + ); + + Ptr += sizeof (BBS_TABLE); + *((UINT16 *) Ptr) = (UINT16) Index; + + Status = gRT->SetVariable ( + BootString, + &gEfiGlobalVariableGuid, + VAR_FLAG, + BufferSize, + Buffer + ); + + SafeFreePool (Buffer); + Buffer = NULL; + + NewBootOrderList = AllocateZeroPool (*BootOrderListSize + sizeof (UINT16)); + if (NULL == NewBootOrderList) { + return EFI_OUT_OF_RESOURCES; + } + + if (NULL != *BootOrderList) { + CopyMem (NewBootOrderList, *BootOrderList, *BootOrderListSize); + } + + BootOrderLastIndex = (UINTN) (*BootOrderListSize / sizeof (UINT16)); + NewBootOrderList[BootOrderLastIndex] = CurrentBootOptionNo; + *BootOrderListSize += sizeof (UINT16); + *BootOrderList = NewBootOrderList; + + return Status; +} + +BOOLEAN +BdsIsLegacyBootOption ( + IN UINT8 *BootOptionVar, + OUT BBS_TABLE **BbsEntry, + OUT UINT16 *BbsIndex + ) +{ + UINT8 *Ptr; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN Ret; + UINT16 DevPathLen; + + Ptr = BootOptionVar; + Ptr += sizeof (UINT32); + DevPathLen = *(UINT16 *) Ptr; + Ptr += sizeof (UINT16); + Ptr += StrSize ((UINT16 *) Ptr); + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { + Ptr += DevPathLen; + *BbsEntry = (BBS_TABLE *) Ptr; + Ptr += sizeof (BBS_TABLE); + *BbsIndex = *(UINT16 *) Ptr; + Ret = TRUE; + } else { + *BbsEntry = NULL; + Ret = FALSE; + } + + return Ret; +} + +EFI_STATUS +BdsDeleteBootOption ( + IN UINTN OptionNumber, + IN OUT UINT16 *BootOrder, + IN OUT UINTN *BootOrderSize + ) +{ + UINT16 BootOption[100]; + UINTN Index; + EFI_STATUS Status; + UINTN Index2Del; + + Status = EFI_SUCCESS; + Index2Del = 0; + + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", OptionNumber); + Status = EfiLibDeleteVariable (BootOption, &gEfiGlobalVariableGuid); + // + // adjust boot order array + // + for (Index = 0; Index < *BootOrderSize / sizeof (UINT16); Index++) { + if (BootOrder[Index] == OptionNumber) { + Index2Del = Index; + break; + } + } + + if (Index != *BootOrderSize / sizeof (UINT16)) { + for (Index = 0; Index < *BootOrderSize / sizeof (UINT16) - 1; Index++) { + if (Index >= Index2Del) { + BootOrder[Index] = BootOrder[Index + 1]; + } + } + + *BootOrderSize -= sizeof (UINT16); + } + + return Status; + +} + +EFI_STATUS +BdsDeleteAllInvalidLegacyBootOptions ( + VOID + ) +{ + UINT16 *BootOrder; + UINT8 *BootOptionVar; + UINTN BootOrderSize; + UINTN BootOptionSize; + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + BBS_TABLE *BbsEntry; + UINT16 BbsIndex; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + UINT16 BootOption[10]; + + Status = EFI_SUCCESS; + BootOrder = NULL; + BootOrderSize = 0; + HddCount = 0; + BbsCount = 0; + LocalHddInfo = NULL; + LocalBbsTable = NULL; + BbsEntry = NULL; + + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + if (NULL == BootOrder) { + return EFI_NOT_FOUND; + } + + Index = 0; + while (Index < BootOrderSize / sizeof (UINT16)) { + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (NULL == BootOptionVar) { + SafeFreePool (BootOrder); + return EFI_OUT_OF_RESOURCES; + } + + if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, &BbsIndex)) { + SafeFreePool (BootOptionVar); + Index++; + continue; + } + + if (!((LocalBbsTable[BbsIndex].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[BbsIndex].BootPriority == BBS_DO_NOT_BOOT_FROM) || + (LocalBbsTable[BbsIndex].BootPriority == BBS_LOWEST_PRIORITY)) && + LocalBbsTable[BbsIndex].DeviceType == BbsEntry->DeviceType) { + Index++; + continue; + } + + SafeFreePool (BootOptionVar); + // + // should delete + // + BdsDeleteBootOption ( + BootOrder[Index], + BootOrder, + &BootOrderSize + ); + } + + if (BootOrderSize) { + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderSize, + BootOrder + ); + } else { + EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + } + + SafeFreePool (BootOrder); + + return Status; +} + +BOOLEAN +BdsFindLegacyBootOptionByDevType ( + IN UINT16 *BootOrder, + IN UINTN BootOptionNum, + IN UINT16 DevType, + OUT UINT32 *Attribute, + OUT UINT16 *BbsIndex, + OUT UINTN *OptionNumber + ) +{ + UINTN Index; + UINTN BootOrderIndex; + UINT16 BootOption[100]; + UINTN BootOptionSize; + UINT8 *BootOptionVar; + BBS_TABLE *BbsEntry; + BOOLEAN Found; + + BbsEntry = NULL; + Found = FALSE; + + if (NULL == BootOrder) { + return Found; + } + + for (BootOrderIndex = 0; BootOrderIndex < BootOptionNum; BootOrderIndex++) { + Index = (UINTN) BootOrder[BootOrderIndex]; + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", Index); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (NULL == BootOptionVar) { + continue; + } + + if (!BdsIsLegacyBootOption (BootOptionVar, &BbsEntry, BbsIndex)) { + SafeFreePool (BootOptionVar); + continue; + } + + if (BbsEntry->DeviceType != DevType) { + SafeFreePool (BootOptionVar); + continue; + } + + *Attribute = *(UINT32 *) BootOptionVar; + *OptionNumber = Index; + Found = TRUE; + SafeFreePool (BootOptionVar); + break; + } + + return Found; +} + +EFI_STATUS +BdsCreateOneLegacyBootOption ( + IN BBS_TABLE *BbsItem, + IN UINTN Index, + IN OUT UINT16 **BootOrderList, + IN OUT UINTN *BootOrderListSize + ) +{ + BBS_BBS_DEVICE_PATH BbsDevPathNode; + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + + DevPath = NULL; + + BbsDevPathNode.Header.Type = BBS_DEVICE_PATH; + BbsDevPathNode.Header.SubType = BBS_BBS_DP; + SetDevicePathNodeLength (&BbsDevPathNode.Header, sizeof (BBS_BBS_DEVICE_PATH)); + BbsDevPathNode.DeviceType = BbsItem->DeviceType; + CopyMem (&BbsDevPathNode.StatusFlag, &BbsItem->StatusFlags, sizeof (UINT16)); + + DevPath = AppendDevicePathNode ( + EndDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevPathNode + ); + if (NULL == DevPath) { + return EFI_OUT_OF_RESOURCES; + } + + Status = BdsCreateLegacyBootOption ( + BbsItem, + DevPath, + Index, + BootOrderList, + BootOrderListSize + ); + BbsItem->BootPriority = 0x00; + + gBS->FreePool (DevPath); + + return Status; +} + +EFI_STATUS +BdsAddNonExistingLegacyBootOptions ( + VOID + ) +/*++ + +Routine Description: + + Add the legacy boot options from BBS table if they do not exist. + +Arguments: + + None. + +Returns: + + EFI_SUCCESS - The boot options are added successfully or they are already in boot options. + others - An error occurred when creating legacy boot options. + +--*/ +{ + UINT16 *BootOrder; + UINTN BootOrderSize; + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINT16 BbsIndex; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + UINT32 Attribute; + UINTN OptionNumber; + BOOLEAN Ret; + + BootOrder = NULL; + HddCount = 0; + BbsCount = 0; + LocalHddInfo = NULL; + LocalBbsTable = NULL; + + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + BootOrder = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + if (NULL == BootOrder) { + BootOrderSize = 0; + } + + for (Index = 0; Index < BbsCount; Index++) { + if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) + ) { + continue; + } + + Ret = BdsFindLegacyBootOptionByDevType ( + BootOrder, + BootOrderSize / sizeof (UINT16), + LocalBbsTable[Index].DeviceType, + &Attribute, + &BbsIndex, + &OptionNumber + ); + if (Ret && (Attribute & LOAD_OPTION_ACTIVE) != 0) { + continue; + } + + if (Ret) { + if (Index != BbsIndex) { + BdsDeleteBootOption ( + OptionNumber, + BootOrder, + &BootOrderSize + ); + } else { + continue; + } + } + // + // Not found such type of legacy device in boot options or we found but it's disabled + // so we have to create one and put it to the tail of boot order list + // + Status = BdsCreateOneLegacyBootOption ( + &LocalBbsTable[Index], + Index, + &BootOrder, + &BootOrderSize + ); + if (EFI_ERROR (Status)) { + break; + } + } + + if (BootOrderSize > 0) { + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderSize, + BootOrder + ); + } else { + EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + } + + if (BootOrder != NULL) { + SafeFreePool (BootOrder); + } + + return Status; +} + +UINT16 * +BdsFillDevOrderBuf ( + IN BBS_TABLE *BbsTable, + IN BBS_TYPE BbsType, + IN UINTN BbsCount, + IN UINT16 *Buf + ) +{ + UINTN Index; + + for (Index = 0; Index < BbsCount; Index++) { + if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) { + continue; + } + + if (BbsTable[Index].DeviceType != BbsType) { + continue; + } + + *Buf = (UINT16) (Index & 0xFF); + Buf++; + } + + return Buf; +} + +EFI_STATUS +BdsCreateDevOrder ( + IN BBS_TABLE *BbsTable, + IN UINT16 BbsCount + ) +{ + UINTN Index; + UINTN FDCount; + UINTN HDCount; + UINTN CDCount; + UINTN NETCount; + UINTN BEVCount; + UINTN TotalSize; + UINTN HeaderSize; + UINT8 *DevOrder; + UINT8 *Ptr; + EFI_STATUS Status; + + FDCount = 0; + HDCount = 0; + CDCount = 0; + NETCount = 0; + BEVCount = 0; + TotalSize = 0; + HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16); + DevOrder = NULL; + Ptr = NULL; + Status = EFI_SUCCESS; + + for (Index = 0; Index < BbsCount; Index++) { + if (BbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) { + continue; + } + + switch (BbsTable[Index].DeviceType) { + case BBS_FLOPPY: + FDCount++; + break; + + case BBS_HARDDISK: + HDCount++; + break; + + case BBS_CDROM: + CDCount++; + break; + + case BBS_EMBED_NETWORK: + NETCount++; + break; + + case BBS_BEV_DEVICE: + BEVCount++; + break; + + default: + break; + } + } + + TotalSize += (HeaderSize + sizeof (UINT16) * FDCount); + TotalSize += (HeaderSize + sizeof (UINT16) * HDCount); + TotalSize += (HeaderSize + sizeof (UINT16) * CDCount); + TotalSize += (HeaderSize + sizeof (UINT16) * NETCount); + TotalSize += (HeaderSize + sizeof (UINT16) * BEVCount); + + DevOrder = AllocateZeroPool (TotalSize); + if (NULL == DevOrder) { + return EFI_OUT_OF_RESOURCES; + } + + Ptr = DevOrder; + + *((BBS_TYPE *) Ptr) = BBS_FLOPPY; + Ptr += sizeof (BBS_TYPE); + *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + if (FDCount) { + Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_FLOPPY, BbsCount, (UINT16 *) Ptr); + } + + *((BBS_TYPE *) Ptr) = BBS_HARDDISK; + Ptr += sizeof (BBS_TYPE); + *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + if (HDCount) { + Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_HARDDISK, BbsCount, (UINT16 *) Ptr); + } + + *((BBS_TYPE *) Ptr) = BBS_CDROM; + Ptr += sizeof (BBS_TYPE); + *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + if (CDCount) { + Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_CDROM, BbsCount, (UINT16 *) Ptr); + } + + *((BBS_TYPE *) Ptr) = BBS_EMBED_NETWORK; + Ptr += sizeof (BBS_TYPE); + *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + if (NETCount) { + Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_EMBED_NETWORK, BbsCount, (UINT16 *) Ptr); + } + + *((BBS_TYPE *) Ptr) = BBS_BEV_DEVICE; + Ptr += sizeof (BBS_TYPE); + *((UINT16 *) Ptr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + if (BEVCount) { + Ptr = (UINT8 *) BdsFillDevOrderBuf (BbsTable, BBS_BEV_DEVICE, BbsCount, (UINT16 *) Ptr); + } + + Status = gRT->SetVariable ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + VAR_FLAG, + TotalSize, + DevOrder + ); + SafeFreePool (DevOrder); + + return Status; +} + +EFI_STATUS +BdsUpdateLegacyDevOrder ( + VOID + ) +/*++ +Format of LegacyDevOrder variable: +|----------------------------------------------------------------------------------------------------------------- +| BBS_FLOPPY | Length | Index0 | Index1 | ... | BBS_HARDDISK | Length | Index0 | Index1 | ... | BBS_CDROM | Length | Index0 | ... +|----------------------------------------------------------------------------------------------------------------- + +Length is a 16 bit integer, it indicates how many Indexes follows, including the size of itself. +Index# is a 16 bit integer, the low byte of it stands for the index in BBS table + the high byte of it only have two value 0 and 0xFF, 0xFF means this device has been + disabled by user. +--*/ +{ + UINT8 *DevOrder; + UINT8 *NewDevOrder; + UINTN DevOrderSize; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINTN Index; + UINTN Index2; + UINTN *Idx; + UINTN FDCount; + UINTN HDCount; + UINTN CDCount; + UINTN NETCount; + UINTN BEVCount; + UINTN TotalSize; + UINTN HeaderSize; + UINT8 *Ptr; + UINT8 *NewPtr; + UINT16 *NewFDPtr; + UINT16 *NewHDPtr; + UINT16 *NewCDPtr; + UINT16 *NewNETPtr; + UINT16 *NewBEVPtr; + UINT16 *NewDevPtr; + UINT16 Length; + UINT16 tmp; + UINTN FDIndex; + UINTN HDIndex; + UINTN CDIndex; + UINTN NETIndex; + UINTN BEVIndex; + + LocalHddInfo = NULL; + LocalBbsTable = NULL; + Idx = NULL; + FDCount = 0; + HDCount = 0; + CDCount = 0; + NETCount = 0; + BEVCount = 0; + TotalSize = 0; + HeaderSize = sizeof (BBS_TYPE) + sizeof (UINT16); + FDIndex = 0; + HDIndex = 0; + CDIndex = 0; + NETIndex = 0; + BEVIndex = 0; + NewDevPtr = NULL; + + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + + DevOrder = (UINT8 *) BdsLibGetVariableAndSize ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + &DevOrderSize + ); + if (NULL == DevOrder) { + return BdsCreateDevOrder (LocalBbsTable, BbsCount); + } + // + // First we figure out how many boot devices with same device type respectively + // + for (Index = 0; Index < BbsCount; Index++) { + if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) || + (LocalBbsTable[Index].BootPriority == BBS_LOWEST_PRIORITY) + ) { + continue; + } + + switch (LocalBbsTable[Index].DeviceType) { + case BBS_FLOPPY: + FDCount++; + break; + + case BBS_HARDDISK: + HDCount++; + break; + + case BBS_CDROM: + CDCount++; + break; + + case BBS_EMBED_NETWORK: + NETCount++; + break; + + case BBS_BEV_DEVICE: + BEVCount++; + break; + + default: + break; + } + } + + TotalSize += (HeaderSize + FDCount * sizeof (UINT16)); + TotalSize += (HeaderSize + HDCount * sizeof (UINT16)); + TotalSize += (HeaderSize + CDCount * sizeof (UINT16)); + TotalSize += (HeaderSize + NETCount * sizeof (UINT16)); + TotalSize += (HeaderSize + BEVCount * sizeof (UINT16)); + + NewDevOrder = AllocateZeroPool (TotalSize); + if (NULL == NewDevOrder) { + return EFI_OUT_OF_RESOURCES; + } + + NewFDPtr = (UINT16 *) (NewDevOrder + HeaderSize); + NewHDPtr = (UINT16 *) ((UINT8 *) NewFDPtr + FDCount * sizeof (UINT16) + HeaderSize); + NewCDPtr = (UINT16 *) ((UINT8 *) NewHDPtr + HDCount * sizeof (UINT16) + HeaderSize); + NewNETPtr = (UINT16 *) ((UINT8 *) NewCDPtr + CDCount * sizeof (UINT16) + HeaderSize); + NewBEVPtr = (UINT16 *) ((UINT8 *) NewNETPtr + NETCount * sizeof (UINT16) + HeaderSize); + + // + // copy FD + // + Ptr = DevOrder; + NewPtr = NewDevOrder; + *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr); + Ptr += sizeof (BBS_TYPE); + NewPtr += sizeof (BBS_TYPE); + Length = *((UINT16 *) Ptr); + *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + FDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + + for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[*Ptr].DeviceType != BBS_FLOPPY + ) { + Ptr += sizeof (UINT16); + continue; + } + + NewFDPtr[FDIndex] = *(UINT16 *) Ptr; + FDIndex++; + Ptr += sizeof (UINT16); + } + // + // copy HD + // + NewPtr = (UINT8 *) NewHDPtr - HeaderSize; + *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr); + Ptr += sizeof (BBS_TYPE); + NewPtr += sizeof (BBS_TYPE); + Length = *((UINT16 *) Ptr); + *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + HDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + + for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[*Ptr].DeviceType != BBS_HARDDISK + ) { + Ptr += sizeof (UINT16); + continue; + } + + NewHDPtr[HDIndex] = *(UINT16 *) Ptr; + HDIndex++; + Ptr += sizeof (UINT16); + } + // + // copy CD + // + NewPtr = (UINT8 *) NewCDPtr - HeaderSize; + *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr); + Ptr += sizeof (BBS_TYPE); + NewPtr += sizeof (BBS_TYPE); + Length = *((UINT16 *) Ptr); + *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + CDCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + + for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[*Ptr].DeviceType != BBS_CDROM + ) { + Ptr += sizeof (UINT16); + continue; + } + + NewCDPtr[CDIndex] = *(UINT16 *) Ptr; + CDIndex++; + Ptr += sizeof (UINT16); + } + // + // copy NET + // + NewPtr = (UINT8 *) NewNETPtr - HeaderSize; + *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr); + Ptr += sizeof (BBS_TYPE); + NewPtr += sizeof (BBS_TYPE); + Length = *((UINT16 *) Ptr); + *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + NETCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + + for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[*Ptr].DeviceType != BBS_EMBED_NETWORK + ) { + Ptr += sizeof (UINT16); + continue; + } + + NewNETPtr[NETIndex] = *(UINT16 *) Ptr; + NETIndex++; + Ptr += sizeof (UINT16); + } + // + // copy BEV + // + NewPtr = (UINT8 *) NewBEVPtr - HeaderSize; + *((BBS_TYPE *) NewPtr) = *((BBS_TYPE *) Ptr); + Ptr += sizeof (BBS_TYPE); + NewPtr += sizeof (BBS_TYPE); + Length = *((UINT16 *) Ptr); + *((UINT16 *) NewPtr) = (UINT16) (sizeof (UINT16) + BEVCount * sizeof (UINT16)); + Ptr += sizeof (UINT16); + + for (Index = 0; Index < Length / sizeof (UINT16) - 1; Index++) { + if (LocalBbsTable[*Ptr].BootPriority == BBS_IGNORE_ENTRY || + LocalBbsTable[*Ptr].BootPriority == BBS_DO_NOT_BOOT_FROM || + LocalBbsTable[*Ptr].BootPriority == BBS_LOWEST_PRIORITY || + LocalBbsTable[*Ptr].DeviceType != BBS_BEV_DEVICE + ) { + Ptr += sizeof (UINT16); + continue; + } + + NewBEVPtr[BEVIndex] = *(UINT16 *) Ptr; + BEVIndex++; + Ptr += sizeof (UINT16); + } + + for (Index = 0; Index < BbsCount; Index++) { + if ((LocalBbsTable[Index].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Index].BootPriority == BBS_DO_NOT_BOOT_FROM) || + (LocalBbsTable[Index].BootPriority == BBS_LOWEST_PRIORITY) + ) { + continue; + } + + switch (LocalBbsTable[Index].DeviceType) { + case BBS_FLOPPY: + Idx = &FDIndex; + NewDevPtr = NewFDPtr; + break; + + case BBS_HARDDISK: + Idx = &HDIndex; + NewDevPtr = NewHDPtr; + break; + + case BBS_CDROM: + Idx = &CDIndex; + NewDevPtr = NewCDPtr; + break; + + case BBS_EMBED_NETWORK: + Idx = &NETIndex; + NewDevPtr = NewNETPtr; + break; + + case BBS_BEV_DEVICE: + Idx = &BEVIndex; + NewDevPtr = NewBEVPtr; + break; + + default: + Idx = NULL; + break; + } + // + // at this point we have copied those valid indexes to new buffer + // and we should check if there is any new appeared boot device + // + if (Idx) { + for (Index2 = 0; Index2 < *Idx; Index2++) { + if ((NewDevPtr[Index2] & 0xFF) == (UINT16) Index) { + break; + } + } + + if (Index2 == *Idx) { + // + // Index2 == *Idx means we didn't find Index + // so Index is a new appeared device's index in BBS table + // save it. + // + NewDevPtr[*Idx] = (UINT16) (Index & 0xFF); + (*Idx)++; + } + } + } + + if (FDCount) { + // + // Just to make sure that disabled indexes are all at the end of the array + // + for (Index = 0; Index < FDIndex - 1; Index++) { + if (0xFF00 != (NewFDPtr[Index] & 0xFF00)) { + continue; + } + + for (Index2 = Index + 1; Index2 < FDIndex; Index2++) { + if (0 == (NewFDPtr[Index2] & 0xFF00)) { + tmp = NewFDPtr[Index]; + NewFDPtr[Index] = NewFDPtr[Index2]; + NewFDPtr[Index2] = tmp; + break; + } + } + } + } + + if (HDCount) { + // + // Just to make sure that disabled indexes are all at the end of the array + // + for (Index = 0; Index < HDIndex - 1; Index++) { + if (0xFF00 != (NewHDPtr[Index] & 0xFF00)) { + continue; + } + + for (Index2 = Index + 1; Index2 < HDIndex; Index2++) { + if (0 == (NewHDPtr[Index2] & 0xFF00)) { + tmp = NewHDPtr[Index]; + NewHDPtr[Index] = NewHDPtr[Index2]; + NewHDPtr[Index2] = tmp; + break; + } + } + } + } + + if (CDCount) { + // + // Just to make sure that disabled indexes are all at the end of the array + // + for (Index = 0; Index < CDIndex - 1; Index++) { + if (0xFF00 != (NewCDPtr[Index] & 0xFF00)) { + continue; + } + + for (Index2 = Index + 1; Index2 < CDIndex; Index2++) { + if (0 == (NewCDPtr[Index2] & 0xFF00)) { + tmp = NewCDPtr[Index]; + NewCDPtr[Index] = NewCDPtr[Index2]; + NewCDPtr[Index2] = tmp; + break; + } + } + } + } + + if (NETCount) { + // + // Just to make sure that disabled indexes are all at the end of the array + // + for (Index = 0; Index < NETIndex - 1; Index++) { + if (0xFF00 != (NewNETPtr[Index] & 0xFF00)) { + continue; + } + + for (Index2 = Index + 1; Index2 < NETIndex; Index2++) { + if (0 == (NewNETPtr[Index2] & 0xFF00)) { + tmp = NewNETPtr[Index]; + NewNETPtr[Index] = NewNETPtr[Index2]; + NewNETPtr[Index2] = tmp; + break; + } + } + } + } + + if (BEVCount) { + // + // Just to make sure that disabled indexes are all at the end of the array + // + for (Index = 0; Index < BEVIndex - 1; Index++) { + if (0xFF00 != (NewBEVPtr[Index] & 0xFF00)) { + continue; + } + + for (Index2 = Index + 1; Index2 < BEVIndex; Index2++) { + if (0 == (NewBEVPtr[Index2] & 0xFF00)) { + tmp = NewBEVPtr[Index]; + NewBEVPtr[Index] = NewBEVPtr[Index2]; + NewBEVPtr[Index2] = tmp; + break; + } + } + } + } + + SafeFreePool (DevOrder); + + Status = gRT->SetVariable ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + VAR_FLAG, + TotalSize, + NewDevOrder + ); + SafeFreePool (NewDevOrder); + + return Status; +} + +EFI_STATUS +BdsSetBootPriority4SameTypeDev ( + IN UINT16 DeviceType, + IN OUT BBS_TABLE *LocalBbsTable, + IN OUT UINT16 *Priority + ) +/*++ +DeviceType - BBS_FLOPPY, BBS_HARDDISK, BBS_CDROM and so on +LocalBbsTable - BBS table instance +Priority - As input arg, it is the start point of boot priority, as output arg, it is the start point of boot + priority can be used next time. +--*/ +{ + UINT8 *DevOrder; + + UINT8 *OrigBuffer; + UINT16 *DevIndex; + UINTN DevOrderSize; + UINTN DevCount; + UINTN Index; + + DevOrder = BdsLibGetVariableAndSize ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + &DevOrderSize + ); + if (NULL == DevOrder) { + return EFI_OUT_OF_RESOURCES; + } + + OrigBuffer = DevOrder; + while (DevOrder < OrigBuffer + DevOrderSize) { + if (DeviceType == * (BBS_TYPE *) DevOrder) { + break; + } + + DevOrder += sizeof (BBS_TYPE); + DevOrder += *(UINT16 *) DevOrder; + } + + if (DevOrder >= OrigBuffer + DevOrderSize) { + SafeFreePool (OrigBuffer); + return EFI_NOT_FOUND; + } + + DevOrder += sizeof (BBS_TYPE); + DevCount = (*((UINT16 *) DevOrder) - sizeof (UINT16)) / sizeof (UINT16); + DevIndex = (UINT16 *) (DevOrder + sizeof (UINT16)); + // + // If the high byte of the DevIndex is 0xFF, it indicates that this device has been disabled. + // + for (Index = 0; Index < DevCount; Index++) { + if ((DevIndex[Index] & 0xFF00) == 0xFF00) { + // + // LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = BBS_DISABLED_ENTRY; + // + } else { + LocalBbsTable[DevIndex[Index] & 0xFF].BootPriority = *Priority; + (*Priority)++; + } + } + + SafeFreePool (OrigBuffer); + return EFI_SUCCESS; +} + +VOID +PrintBbsTable ( + IN BBS_TABLE *LocalBbsTable + ) +{ + UINT16 Idx; + + DEBUG ((EFI_D_ERROR, "\n")); + DEBUG ((EFI_D_ERROR, " NO Prio bb/dd/ff cl/sc Type Stat segm:offs\n")); + DEBUG ((EFI_D_ERROR, "=============================================\n")); + for (Idx = 0; Idx < MAX_BBS_ENTRIES; Idx++) { + if ((LocalBbsTable[Idx].BootPriority == BBS_IGNORE_ENTRY) || + (LocalBbsTable[Idx].BootPriority == BBS_DO_NOT_BOOT_FROM) || + (LocalBbsTable[Idx].BootPriority == BBS_LOWEST_PRIORITY) + ) { + continue; + } + + DEBUG ( + (EFI_D_ERROR, + " %02x: %04x %02x/%02x/%02x %02x/02%x %04x %04x %04x:%04x\n", + (UINTN) Idx, + (UINTN) LocalBbsTable[Idx].BootPriority, + (UINTN) LocalBbsTable[Idx].Bus, + (UINTN) LocalBbsTable[Idx].Device, + (UINTN) LocalBbsTable[Idx].Function, + (UINTN) LocalBbsTable[Idx].Class, + (UINTN) LocalBbsTable[Idx].SubClass, + (UINTN) LocalBbsTable[Idx].DeviceType, + (UINTN) * (UINT16 *) &LocalBbsTable[Idx].StatusFlags, + (UINTN) LocalBbsTable[Idx].BootHandlerSegment, + (UINTN) LocalBbsTable[Idx].BootHandlerOffset, + (UINTN) ((LocalBbsTable[Idx].MfgStringSegment << 4) + LocalBbsTable[Idx].MfgStringOffset), + (UINTN) ((LocalBbsTable[Idx].DescStringSegment << 4) + LocalBbsTable[Idx].DescStringOffset)) + ); + } + + DEBUG ((EFI_D_ERROR, "\n")); +} + +EFI_STATUS +BdsRefreshBbsTableForBoot ( + IN BDS_COMMON_OPTION *Entry + ) +{ + EFI_STATUS Status; + UINT16 HddCount; + UINT16 BbsCount; + HDD_INFO *LocalHddInfo; + BBS_TABLE *LocalBbsTable; + UINT16 DevType; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINTN Index; + UINT16 Priority; + UINT16 *BootOrder; + UINTN BootOrderSize; + UINT8 *BootOptionVar; + UINTN BootOptionSize; + UINT16 BootOption[100]; + UINT8 *Ptr; + UINT16 DevPathLen; + EFI_DEVICE_PATH_PROTOCOL *DevPath; + + HddCount = 0; + BbsCount = 0; + LocalHddInfo = NULL; + LocalBbsTable = NULL; + DevType = BBS_UNKNOWN; + + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios); + if (EFI_ERROR (Status)) { + return Status; + } + + LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &LocalHddInfo, + &BbsCount, + &LocalBbsTable + ); + // + // First, set all the present devices' boot priority to BBS_UNPRIORITIZED_ENTRY + // We will set them according to the settings setup by user + // + for (Index = 0; Index < BbsCount; Index++) { + if (!((BBS_IGNORE_ENTRY == LocalBbsTable[Index].BootPriority) || + (BBS_DO_NOT_BOOT_FROM == LocalBbsTable[Index].BootPriority) || + (BBS_LOWEST_PRIORITY == LocalBbsTable[Index].BootPriority))) { + LocalBbsTable[Index].BootPriority = BBS_UNPRIORITIZED_ENTRY; + } + } + // + // boot priority always starts at 0 + // + Priority = 0; + if (Entry->LoadOptionsSize == sizeof (BBS_TABLE) + sizeof (UINT16)) { + // + // If Entry stands for a legacy boot option, we prioritize the devices with the same type first. + // + DevType = ((BBS_TABLE *) Entry->LoadOptions)->DeviceType; + Status = BdsSetBootPriority4SameTypeDev ( + DevType, + LocalBbsTable, + &Priority + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + // + // we have to set the boot priority for other BBS entries with different device types + // + BootOrder = (UINT16 *) BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderSize + ); + for (Index = 0; BootOrder && Index < BootOrderSize / sizeof (UINT16); Index++) { + UnicodeSPrint (BootOption, sizeof (BootOption), L"Boot%04x", BootOrder[Index]); + BootOptionVar = BdsLibGetVariableAndSize ( + BootOption, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (NULL == BootOptionVar) { + continue; + } + + Ptr = BootOptionVar; + + Ptr += sizeof (UINT32); + DevPathLen = *(UINT16 *) Ptr; + Ptr += sizeof (UINT16); + Ptr += StrSize ((UINT16 *) Ptr); + DevPath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + if (BBS_DEVICE_PATH != DevPath->Type || BBS_BBS_DP != DevPath->SubType) { + SafeFreePool (BootOptionVar); + continue; + } + + Ptr += DevPathLen; + if (DevType == ((BBS_TABLE *) Ptr)->DeviceType) { + // + // We don't want to process twice for a device type + // + SafeFreePool (BootOptionVar); + continue; + } + + Status = BdsSetBootPriority4SameTypeDev ( + ((BBS_TABLE *) Ptr)->DeviceType, + LocalBbsTable, + &Priority + ); + SafeFreePool (BootOptionVar); + if (EFI_ERROR (Status)) { + break; + } + } + + if (BootOrder) { + SafeFreePool (BootOrder); + } + // + // For debug + // + PrintBbsTable (LocalBbsTable); + + return Status; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BBSsupport.h b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BBSsupport.h new file mode 100644 index 0000000000..37778f4421 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BBSsupport.h @@ -0,0 +1,83 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BBSsupport.h + +Abstract: + + declares interface functions + +Revision History + +--*/ + +#ifndef _EFI_BDS_BBS_SUPPORT_H +#define _EFI_BDS_BBS_SUPPORT_H + +#include "Generic/BootMaint/BootMaint.h" + +#ifdef EFI32 +#define REFRESH_LEGACY_BOOT_OPTIONS \ + BdsDeleteAllInvalidLegacyBootOptions ();\ + BdsAddNonExistingLegacyBootOptions (); \ + BdsUpdateLegacyDevOrder () +#else +#define REFRESH_LEGACY_BOOT_OPTIONS +#endif + +VOID +BdsBuildLegacyDevNameString ( + IN BBS_TABLE *CurBBSEntry, + IN UINTN Index, + IN UINTN BufSize, + OUT CHAR16 *BootString + ); + +EFI_STATUS +BdsDeleteAllInvalidLegacyBootOptions ( + VOID + ); + +EFI_STATUS +BdsAddNonExistingLegacyBootOptions ( + VOID + ) +/*++ + +Routine Description: + + Add the legacy boot options from BBS table if they do not exist. + +Arguments: + + None. + +Returns: + + EFI_SUCCESS - The boot options are added successfully or they are already in boot options. + others - An error occurred when creating legacy boot options. + +--*/ +; + +EFI_STATUS +BdsUpdateLegacyDevOrder ( + VOID + ); + +EFI_STATUS +BdsRefreshBbsTableForBoot ( + IN BDS_COMMON_OPTION *Entry + ); + +#endif diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BmLib.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BmLib.c new file mode 100644 index 0000000000..201339e896 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BmLib.c @@ -0,0 +1,626 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + bmlib.c + +AgBStract: + + Boot Maintainence Helper functions + +--*/ + +#include "bootmaint.h" + +EFI_STATUS +EfiLibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ) +/*++ + +Routine Description: + + Find the first instance of this Protocol + in the system and return it's interface + +Arguments: + + ProtocolGuid - Provides the protocol to search for + Interface - On return, a pointer to the first interface + that matches ProtocolGuid + +Returns: + + EFI_SUCCESS - A protocol instance matching ProtocolGuid was found + + EFI_NOT_FOUND - No protocol instances were found that match ProtocolGuid + +--*/ +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + ProtocolGuid, + NULL, + Interface + ); + return Status; +} + +EFI_FILE_HANDLE +EfiLibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ) +/*++ + +Routine Description: + + Function opens and returns a file handle to the root directory of a volume. + +Arguments: + + DeviceHandle - A handle for a device + +Returns: + + A valid file handle or NULL is returned + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Volume; + EFI_FILE_HANDLE File; + + File = NULL; + + // + // File the file system interface to the device + // + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiSimpleFileSystemProtocolGuid, + (VOID *) &Volume + ); + + // + // Open the root directory of the volume + // + if (!EFI_ERROR (Status)) { + Status = Volume->OpenVolume ( + Volume, + &File + ); + } + // + // Done + // + return EFI_ERROR (Status) ? NULL : File; +} + +BOOLEAN +EfiGrowBuffer ( + IN OUT EFI_STATUS *Status, + IN OUT VOID **Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + Helper function called as part of the code needed + to allocate the proper sized buffer for various + EFI interfaces. + +Arguments: + + Status - Current status + + Buffer - Current allocated buffer, or NULL + + BufferSize - Current buffer size needed + +Returns: + + TRUE - if the buffer was reallocated and the caller + should try the API again. + +--*/ +{ + BOOLEAN TryAgain; + + // + // If this is an initial request, buffer will be null with a new buffer size + // + if (!*Buffer && BufferSize) { + *Status = EFI_BUFFER_TOO_SMALL; + } + // + // If the status code is "buffer too small", resize the buffer + // + TryAgain = FALSE; + if (*Status == EFI_BUFFER_TOO_SMALL) { + + SafeFreePool (*Buffer); + + *Buffer = AllocateZeroPool (BufferSize); + + if (*Buffer) { + TryAgain = TRUE; + } else { + *Status = EFI_OUT_OF_RESOURCES; + } + } + // + // If there's an error, free the buffer + // + if (!TryAgain && EFI_ERROR (*Status) && *Buffer) { + SafeFreePool (*Buffer); + *Buffer = NULL; + } + + return TryAgain; +} + +VOID * +EfiLibGetVariable ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid + ) +/*++ + +Routine Description: + Function returns the value of the specified variable. + +Arguments: + Name - A Null-terminated Unicode string that is + the name of the vendor's variable. + + VendorGuid - A unique identifier for the vendor. + +Returns: + + None + +--*/ +{ + UINTN VarSize; + + return BdsLibGetVariableAndSize (Name, VendorGuid, &VarSize); +} + +EFI_STATUS +EfiLibDeleteVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid + ) +/*++ + +Routine Description: + Function deletes the variable specified by VarName and VarGuid. + +Arguments: + VarName - A Null-terminated Unicode string that is + the name of the vendor's variable. + + VendorGuid - A unique identifier for the vendor. + +Returns: + + EFI_SUCCESS - The variable was found and removed + + EFI_UNSUPPORTED - The variable store was inaccessible + + EFI_OUT_OF_RESOURCES - The temporary buffer was not available + + EFI_NOT_FOUND - The variable was not found + +--*/ +{ + VOID *VarBuf; + EFI_STATUS Status; + + VarBuf = EfiLibGetVariable (VarName, VarGuid); + Status = EFI_NOT_FOUND; + + if (VarBuf) { + // + // Delete variable from Storage + // + Status = gRT->SetVariable (VarName, VarGuid, VAR_FLAG, 0, NULL); + ASSERT (!EFI_ERROR (Status)); + SafeFreePool (VarBuf); + } + + return Status; +} + +EFI_FILE_SYSTEM_VOLUME_LABEL_INFO * +EfiLibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ) +/*++ + +Routine Description: + + Function gets the file system information from an open file descriptor, + and stores it in a buffer allocated from pool. + +Arguments: + + Fhand - A file handle + +Returns: + + A pointer to a buffer with file information or NULL is returned + +--*/ +{ + EFI_STATUS Status; + EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Buffer; + UINTN BufferSize; + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO + 200; + + // + // Call the real function + // + while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileSystemVolumeLabelInfoIdGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +CHAR16 * +EfiStrDuplicate ( + IN CHAR16 *Src + ) +{ + CHAR16 *Dest; + UINTN Size; + + Size = StrSize (Src); + Dest = AllocateZeroPool (Size); + ASSERT (Dest != NULL); + if (Dest) { + CopyMem (Dest, Src, Size); + } + + return Dest; +} + +EFI_FILE_INFO * +EfiLibFileInfo ( + IN EFI_FILE_HANDLE FHand + ) +/*++ + +Routine Description: + + Function gets the file information from an open file descriptor, and stores it + in a buffer allocated from pool. + +Arguments: + + Fhand - A file handle + +Returns: + + A pointer to a buffer with file information or NULL is returned + +--*/ +{ + EFI_STATUS Status; + EFI_FILE_INFO *Buffer; + UINTN BufferSize; + + // + // Initialize for GrowBuffer loop + // + Buffer = NULL; + BufferSize = SIZE_OF_EFI_FILE_INFO + 200; + + // + // Call the real function + // + while (EfiGrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) { + Status = FHand->GetInfo ( + FHand, + &gEfiFileInfoGuid, + &BufferSize, + Buffer + ); + } + + return Buffer; +} + +UINTN +EfiDevicePathInstanceCount ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Function is used to determine the number of device path instances + that exist in a device path. + +Arguments: + DevicePath - A pointer to a device path data structure. + +Returns: + + This function counts and returns the number of device path instances + in DevicePath. + +--*/ +{ + UINTN Count; + UINTN Size; + + Count = 0; + while (GetNextDevicePathInstance (&DevicePath, &Size)) { + Count += 1; + } + + return Count; +} + +VOID * +EfiReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ) +/*++ + +Routine Description: + Adjusts the size of a previously allocated buffer. + +Arguments: + OldPool - A pointer to the buffer whose size is being adjusted. + OldSize - The size of the current buffer. + NewSize - The size of the new buffer. + +Returns: + + EFI_SUCEESS - The requested number of bytes were allocated. + + EFI_OUT_OF_RESOURCES - The pool requested could not be allocated. + + EFI_INVALID_PARAMETER - The buffer was invalid. + +--*/ +{ + VOID *NewPool; + + NewPool = NULL; + if (NewSize) { + NewPool = AllocateZeroPool (NewSize); + } + + if (OldPool) { + if (NewPool) { + CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); + } + + SafeFreePool (OldPool); + } + + return NewPool; +} + +EFI_STATUS +EfiLibGetStringFromToken ( + IN EFI_GUID *ProducerGuid, + IN STRING_REF Token, + OUT CHAR16 **String + ) +/*++ + +Routine Description: + + Acquire the string associated with the ProducerGuid and return it. + +Arguments: + + ProducerGuid - The Guid to search the HII database for + Token - The token value of the string to extract + String - The string that is extracted + +Returns: + + EFI_SUCCESS - Buffer filled with the requested forms. BufferLength + was updated. + EFI_BUFFER_TOO_SMALL - The buffer provided was not large enough to allow the form to be stored. + +--*/ +{ + EFI_STATUS Status; + UINT16 HandleBufferLength; + EFI_HII_HANDLE *HiiHandleBuffer; + UINTN StringBufferLength; + UINTN NumberOfHiiHandles; + UINTN Index; + UINT16 Length; + EFI_GUID HiiGuid; + EFI_HII_PROTOCOL *Hii; + + HandleBufferLength = 0x1000; + HiiHandleBuffer = NULL; + Status = gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + &Hii + ); + if (EFI_ERROR (Status)) { + *String = NULL; + return Status; + } + // + // Get all the Hii handles + // + HiiHandleBuffer = AllocateZeroPool (HandleBufferLength); + ASSERT (HiiHandleBuffer != NULL); + + Status = Hii->FindHandles (Hii, &HandleBufferLength, HiiHandleBuffer); + ASSERT_EFI_ERROR (Status); + + // + // Get the Hii Handle that matches the StructureNode->ProducerName + // + NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE); + for (Index = 0; Index < NumberOfHiiHandles; Index++) { + Length = 0; + Status = ExtractDataFromHiiHandle ( + HiiHandleBuffer[Index], + &Length, + NULL, + &HiiGuid + ); + if (CompareGuid (ProducerGuid, &HiiGuid)) { + break; + } + } + // + // Find the string based on the current language + // + StringBufferLength = 0x100; + *String = AllocateZeroPool (0x100); + ASSERT (*String != NULL); + + Status = Hii->GetString ( + Hii, + HiiHandleBuffer[Index], + Token, + FALSE, + NULL, + &StringBufferLength, + *String + ); + + gBS->FreePool (HiiHandleBuffer); + + return Status; +} + +BOOLEAN +TimeCompare ( + IN EFI_TIME *FirstTime, + IN EFI_TIME *SecondTime + ) +/*++ + +Routine Description: + Compare two EFI_TIME data. + +Arguments: + + FirstTime - A pointer to the first EFI_TIME data. + SecondTime - A pointer to the second EFI_TIME data. + +Returns: + TRUE The FirstTime is not later than the SecondTime. + FALSE The FirstTime is later than the SecondTime. + +--*/ +{ + if (FirstTime->Year != SecondTime->Year) { + return (BOOLEAN) (FirstTime->Year < SecondTime->Year); + } else if (FirstTime->Month != SecondTime->Month) { + return (BOOLEAN) (FirstTime->Month < SecondTime->Month); + } else if (FirstTime->Day != SecondTime->Day) { + return (BOOLEAN) (FirstTime->Day < SecondTime->Day); + } else if (FirstTime->Hour != SecondTime->Hour) { + return (BOOLEAN) (FirstTime->Hour < SecondTime->Hour); + } else if (FirstTime->Minute != SecondTime->Minute) { + return (BOOLEAN) (FirstTime->Minute < FirstTime->Minute); + } else if (FirstTime->Second != SecondTime->Second) { + return (BOOLEAN) (FirstTime->Second < SecondTime->Second); + } + + return (BOOLEAN) (FirstTime->Nanosecond <= SecondTime->Nanosecond); +} + +UINT16 * +EfiLibStrFromDatahub ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +{ + EFI_STATUS Status; + UINT16 *Desc; + EFI_DATA_HUB_PROTOCOL *Datahub; + UINT64 Count; + EFI_DATA_RECORD_HEADER *Record; + EFI_SUBCLASS_TYPE1_HEADER *DataHdr; + EFI_GUID MiscGuid = EFI_MISC_SUBCLASS_GUID; + EFI_MISC_ONBOARD_DEVICE_DATA *ob; + EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *Port; + EFI_TIME CurTime; + + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + &Datahub + ); + if (EFI_ERROR (Status)) { + return NULL; + } + + Status = gRT->GetTime (&CurTime, NULL); + if (EFI_ERROR (Status)) { + return NULL; + } + + Count = 0; + do { + Status = Datahub->GetNextRecord (Datahub, &Count, NULL, &Record); + + if (EFI_ERROR (Status)) { + break; + } + + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA && CompareGuid (&Record->DataRecordGuid, &MiscGuid)) { + // + // This record is what we need + // + DataHdr = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1); + if (EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER == DataHdr->RecordType) { + ob = (EFI_MISC_ONBOARD_DEVICE_DATA *) (DataHdr + 1); + if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &ob->OnBoardDevicePath, DevPath)) { + EfiLibGetStringFromToken (&Record->ProducerName, ob->OnBoardDeviceDescription, &Desc); + return Desc; + } + } + + if (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER == DataHdr->RecordType) { + Port = (EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA *) (DataHdr + 1); + if (BdsLibMatchDevicePaths ((EFI_DEVICE_PATH_PROTOCOL *) &Port->PortPath, DevPath)) { + EfiLibGetStringFromToken (&Record->ProducerName, Port->PortExternalConnectorDesignator, &Desc); + return Desc; + } + } + } + + } while (TimeCompare (&Record->LogTime, &CurTime) && Count != 0); + + return NULL; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BootMaint.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BootMaint.c new file mode 100644 index 0000000000..c4b3211dfd --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BootMaint.c @@ -0,0 +1,1305 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BootMaint.c + +Abstract: + + Boot Maintainence Main File + +--*/ + +#include "Generic/Bds.h" +#include "BootMaint.h" +#include "BdsStrDefs.h" +#include "formguid.h" + +// +// Form binary for Boot Maintenance +// +extern UINT8 bmBin[]; +extern UINT8 FEBin[]; +extern EFI_GUID gBdsStringPackGuid; +extern BOOLEAN gConnectAllHappened; + +EFI_GUID EfiLegacyDevOrderGuid = EFI_LEGACY_DEV_ORDER_VARIABLE_GUID; + +VOID +InitAllMenu ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +FreeAllMenu ( + VOID + ); + +EFI_STATUS +CreateMenuStringToken ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN BM_MENU_OPTION *MenuOption + ) +/*++ +Routine Description: + + Create string tokens for a menu from its help strings and display strings + +Arguments: + + HiiHandle - Hii Handle of the package to be updated. + + MenuOption - The Menu whose string tokens need to be created + +Returns: + + EFI_SUCCESS - string tokens created successfully + + others - contain some errors + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + UINTN Index; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + HiiHandle, + &NewMenuEntry->DisplayStringToken, + NewMenuEntry->DisplayString + ); + + if (NULL == NewMenuEntry->HelpString) { + NewMenuEntry->HelpStringToken = NewMenuEntry->DisplayStringToken; + } else { + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + HiiHandle, + &NewMenuEntry->HelpStringToken, + NewMenuEntry->HelpString + ); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +DriverCallback ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *Data, + OUT EFI_HII_CALLBACK_PACKET **Packet + ) +/*++ +Routine Description: + + Callback Function for boot maintenance utility user interface interaction. + +Arguments: + + This - File explorer callback protocol pointer. + KeyValue - Key value to identify the type of data to expect. + Data - A pointer to the data being sent to the original exporting driver. + Packet - A pointer to a packet of information which a driver passes back to the browser. + +Returns: + + EFI_SUCCESS - Callback ended successfully. + Others - Contain some errors. + +--*/ +{ + BMM_CALLBACK_DATA *Private; + BM_MENU_ENTRY *NewMenuEntry; + BMM_FAKE_NV_DATA *CurrentFakeNVMap; + EFI_STATUS Status; + UINTN OldValue; + UINTN NewValue; + UINTN Number; + UINTN Pos; + UINTN Bit; + UINT16 NewValuePos; + UINT16 Index2; + UINT16 Index; + UINT8 *OldLegacyDev; + UINT8 *NewLegacyDev; + UINT8 *Location; + UINT8 *DisMap; + FORM_ID FormId; + + OldValue = 0; + NewValue = 0; + Number = 0; + OldLegacyDev = NULL; + NewLegacyDev = NULL; + NewValuePos = 0; + DisMap = NULL; + + Private = BMM_CALLBACK_DATA_FROM_THIS (This); + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->BmmCallbackHandle; + CurrentFakeNVMap = (BMM_FAKE_NV_DATA *) Data->NvRamMap; + Private->BmmFakeNvData = CurrentFakeNVMap; + Location = (UINT8 *) &UpdateData->Data; + + UpdatePageId (Private, KeyValue); + + // + // need to be subtituded. + // + // Update Select FD/HD/CD/NET/BEV Order Form + // + if (FORM_SET_FD_ORDER_ID == Private->BmmPreviousPageId || + FORM_SET_HD_ORDER_ID == Private->BmmPreviousPageId || + FORM_SET_CD_ORDER_ID == Private->BmmPreviousPageId || + FORM_SET_NET_ORDER_ID == Private->BmmPreviousPageId || + FORM_SET_BEV_ORDER_ID == Private->BmmPreviousPageId || + ((FORM_BOOT_SETUP_ID == Private->BmmPreviousPageId) && + (KeyValue >= LEGACY_FD_QUESTION_ID) && + (KeyValue < (LEGACY_BEV_QUESTION_ID + 100)) ) + ) { + + DisMap = Private->BmmOldFakeNVData.DisableMap; + + FormId = Private->BmmPreviousPageId; + if (FormId == FORM_BOOT_SETUP_ID) { + FormId = Private->BmmCurrentPageId; + } + + switch (FormId) { + case FORM_SET_FD_ORDER_ID: + Number = (UINT16) LegacyFDMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyFD; + NewLegacyDev = CurrentFakeNVMap->LegacyFD; + break; + + case FORM_SET_HD_ORDER_ID: + Number = (UINT16) LegacyHDMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyHD; + NewLegacyDev = CurrentFakeNVMap->LegacyHD; + break; + + case FORM_SET_CD_ORDER_ID: + Number = (UINT16) LegacyCDMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyCD; + NewLegacyDev = CurrentFakeNVMap->LegacyCD; + break; + + case FORM_SET_NET_ORDER_ID: + Number = (UINT16) LegacyNETMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyNET; + NewLegacyDev = CurrentFakeNVMap->LegacyNET; + break; + + case FORM_SET_BEV_ORDER_ID: + Number = (UINT16) LegacyBEVMenu.MenuNumber; + OldLegacyDev = Private->BmmOldFakeNVData.LegacyBEV; + NewLegacyDev = CurrentFakeNVMap->LegacyBEV; + break; + + default: + break; + } + // + // First, find the different position + // if there is change, it should be only one + // + for (Index = 0; Index < Number; Index++) { + if (OldLegacyDev[Index] != NewLegacyDev[Index]) { + OldValue = OldLegacyDev[Index]; + NewValue = NewLegacyDev[Index]; + break; + } + } + + if (Index != Number) { + // + // there is change, now process + // + if (0xFF == NewValue) { + // + // This item will be disable + // Just move the items behind this forward to overlap it + // + Pos = OldValue / 8; + Bit = 7 - (OldValue % 8); + DisMap[Pos] |= (UINT8) (1 << Bit); + for (Index2 = Index; Index2 < Number - 1; Index2++) { + NewLegacyDev[Index2] = NewLegacyDev[Index2 + 1]; + } + + NewLegacyDev[Index2] = 0xFF; + } else { + for (Index2 = 0; Index2 < Number; Index2++) { + if (Index2 == Index) { + continue; + } + + if (OldLegacyDev[Index2] == NewValue) { + // + // If NewValue is in OldLegacyDev array + // remember its old position + // + NewValuePos = Index2; + break; + } + } + + if (Index2 != Number) { + // + // We will change current item to an existing item + // (It's hard to describe here, please read code, it's like a cycle-moving) + // + for (Index2 = NewValuePos; Index2 != Index;) { + if (NewValuePos < Index) { + NewLegacyDev[Index2] = OldLegacyDev[Index2 + 1]; + Index2++; + } else { + NewLegacyDev[Index2] = OldLegacyDev[Index2 - 1]; + Index2--; + } + } + } else { + // + // If NewValue is not in OldlegacyDev array, we are changing to a disabled item + // so we should modify DisMap to reflect the change + // + Pos = NewValue / 8; + Bit = 7 - (NewValue % 8); + DisMap[Pos] &= ~ (UINT8) (1 << Bit); + if (0xFF != OldValue) { + // + // Because NewValue is a item that was disabled before + // so after changing the OldValue should be disabled + // actually we are doing a swap of enable-disable states of two items + // + Pos = OldValue / 8; + Bit = 7 - (OldValue % 8); + DisMap[Pos] |= (UINT8) (1 << Bit); + } + } + } + // + // To prevent DISABLE appears in the middle of the list + // we should perform a re-ordering + // + Index = 0; + while (Index < Number) { + if (0xFF != NewLegacyDev[Index]) { + Index++; + continue; + } + + Index2 = Index; + Index2++; + while (Index2 < Number) { + if (0xFF != NewLegacyDev[Index2]) { + break; + } + + Index2++; + } + + if (Index2 < Number) { + NewLegacyDev[Index] = NewLegacyDev[Index2]; + NewLegacyDev[Index2] = 0xFF; + } + + Index++; + } + + CopyMem ( + OldLegacyDev, + NewLegacyDev, + Number + ); + } + } + + if (KeyValue < FILE_OPTION_OFFSET) { + if (KeyValue < NORMAL_GOTO_OFFSET) { + switch (KeyValue) { + case KEY_VALUE_BOOT_FROM_FILE: + Private->FeCurrentState = BOOT_FROM_FILE_STATE; + + // + // Exit Bmm main formset to send File Explorer formset. + // + CreateCallbackPacket (Packet, EXIT_REQUIRED); + + break; + + case FORM_BOOT_ADD_ID: + Private->FeCurrentState = ADD_BOOT_OPTION_STATE; + + // + // Exit Bmm main formset to send File Explorer formset. + // + CreateCallbackPacket (Packet, EXIT_REQUIRED); + break; + + case FORM_DRV_ADD_FILE_ID: + Private->FeCurrentState = ADD_DRIVER_OPTION_STATE; + + // + // Exit Bmm main formset to send File Explorer formset. + // + CreateCallbackPacket (Packet, EXIT_REQUIRED); + + break; + + case FORM_DRV_ADD_HANDLE_ID: + CleanUpPage (FORM_DRV_ADD_HANDLE_ID, Private); + UpdateDrvAddHandlePage (Private); + break; + + case FORM_BOOT_DEL_ID: + CleanUpPage (FORM_BOOT_DEL_ID, Private); + UpdateBootDelPage (Private); + break; + + case FORM_BOOT_CHG_ID: + case FORM_DRV_CHG_ID: + UpdatePageBody (KeyValue, Private); + break; + + case FORM_DRV_DEL_ID: + CleanUpPage (FORM_DRV_DEL_ID, Private); + UpdateDrvDelPage (Private); + break; + + case FORM_BOOT_NEXT_ID: + CleanUpPage (FORM_BOOT_NEXT_ID, Private); + UpdateBootNextPage (Private); + break; + + case FORM_TIME_OUT_ID: + CleanUpPage (FORM_TIME_OUT_ID, Private); + UpdateTimeOutPage (Private); + break; + + case FORM_RESET: + gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL); + return EFI_UNSUPPORTED; + + case FORM_CON_IN_ID: + case FORM_CON_OUT_ID: + case FORM_CON_ERR_ID: + UpdatePageBody (KeyValue, Private); + break; + + case FORM_CON_COM_ID: + CleanUpPage (FORM_CON_COM_ID, Private); + UpdateConCOMPage (Private); + break; + + case FORM_SET_FD_ORDER_ID: + case FORM_SET_HD_ORDER_ID: + case FORM_SET_CD_ORDER_ID: + case FORM_SET_NET_ORDER_ID: + case FORM_SET_BEV_ORDER_ID: + CleanUpPage (KeyValue, Private); + UpdateSetLegacyDeviceOrderPage (KeyValue, Private); + break; + + case KEY_VALUE_SAVE_AND_EXIT: + case KEY_VALUE_NO_SAVE_AND_EXIT: + + if (KeyValue == KEY_VALUE_SAVE_AND_EXIT) { + Status = ApplyChangeHandler (Private, CurrentFakeNVMap, Private->BmmPreviousPageId); + if (EFI_ERROR (Status)) { + return Status; + } + } else if (KeyValue == KEY_VALUE_NO_SAVE_AND_EXIT) { + DiscardChangeHandler (Private, CurrentFakeNVMap); + } + // + // Tell browser not to ask for confirmation of changes, + // since we have already applied or discarded. + // + CreateCallbackPacket (Packet, NV_NOT_CHANGED); + break; + + default: + break; + } + } else if ((KeyValue >= TERMINAL_OPTION_OFFSET) && (KeyValue < CONSOLE_OPTION_OFFSET)) { + Index2 = (UINT16) (KeyValue - TERMINAL_OPTION_OFFSET); + Private->CurrentTerminal = Index2; + + CleanUpPage (FORM_CON_COM_SETUP_ID, Private); + UpdateTerminalPage (Private); + + } else if (KeyValue >= HANDLE_OPTION_OFFSET) { + Index2 = (UINT16) (KeyValue - HANDLE_OPTION_OFFSET); + + NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index2); + Private->HandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; + + CleanUpPage (FORM_DRV_ADD_HANDLE_DESC_ID, Private); + + Private->MenuEntry = NewMenuEntry; + Private->LoadContext->FilePathList = Private->HandleContext->DevicePath; + + UpdateDriverAddHandleDescPage (Private); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +ApplyChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap, + IN FORM_ID FormId + ) +/*++ + +Routine Description: + + Function handling request to apply changes for BMM pages. + +Arguments: + + Private - Pointer to callback data buffer. + CurrentFakeNVMap - Pointer to buffer holding data of various values used by BMM + FormId - ID of the form which has sent the request to apply change. + +Returns: + + EFI_SUCCESS - Change successfully applied. + Other - Error occurs while trying to apply changes. + +--*/ +{ + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_LOAD_CONTEXT *NewLoadContext; + BM_MENU_ENTRY *NewMenuEntry; + EFI_STATUS Status; + UINT16 Index; + + Status = EFI_SUCCESS; + + switch (FormId) { + case FORM_SET_FD_ORDER_ID: + case FORM_SET_HD_ORDER_ID: + case FORM_SET_CD_ORDER_ID: + case FORM_SET_NET_ORDER_ID: + case FORM_SET_BEV_ORDER_ID: + Var_UpdateBBSOption (Private); + break; + + case FORM_BOOT_DEL_ID: + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = CurrentFakeNVMap->BootOptionDel[Index]; + } + + Var_DelBootOption (); + break; + + case FORM_DRV_DEL_ID: + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = CurrentFakeNVMap->DriverOptionDel[Index]; + } + + Var_DelDriverOption (); + break; + + case FORM_BOOT_CHG_ID: + Status = Var_UpdateBootOrder (Private); + break; + + case FORM_DRV_CHG_ID: + Status = Var_UpdateDriverOrder (Private); + break; + + case FORM_TIME_OUT_ID: + Status = gRT->SetVariable ( + L"Timeout", + &gEfiGlobalVariableGuid, + VAR_FLAG, + sizeof (UINT16), + &(CurrentFakeNVMap->BootTimeOut) + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + Private->BmmOldFakeNVData.BootTimeOut = CurrentFakeNVMap->BootTimeOut; + break; + + case FORM_BOOT_NEXT_ID: + Status = Var_UpdateBootNext (Private); + break; + + case FORM_CON_COM_ID: + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Private->CurrentTerminal); + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + NewTerminalContext->BaudRateIndex = CurrentFakeNVMap->COMBaudRate; + NewTerminalContext->BaudRate = BaudRateList[CurrentFakeNVMap->COMBaudRate].Value; + NewTerminalContext->DataBitsIndex = CurrentFakeNVMap->COMDataRate; + NewTerminalContext->DataBits = (UINT8) DataBitsList[CurrentFakeNVMap->COMDataRate].Value; + NewTerminalContext->StopBitsIndex = CurrentFakeNVMap->COMStopBits; + NewTerminalContext->StopBits = (UINT8) StopBitsList[CurrentFakeNVMap->COMStopBits].Value; + NewTerminalContext->ParityIndex = CurrentFakeNVMap->COMParity; + NewTerminalContext->Parity = (UINT8) ParityList[CurrentFakeNVMap->COMParity].Value; + NewTerminalContext->TerminalType = CurrentFakeNVMap->COMTerminalType; + + ChangeTerminalDevicePath ( + NewTerminalContext->DevicePath, + FALSE + ); + + Var_UpdateConsoleInpOption (); + Var_UpdateConsoleOutOption (); + Var_UpdateErrorOutOption (); + break; + + case FORM_CON_IN_ID: + for (Index = 0; Index < ConsoleInpMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleInpMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + NewTerminalContext->IsConIn = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleInpMenu.MenuNumber]; + } + + Var_UpdateConsoleInpOption (); + break; + + case FORM_CON_OUT_ID: + for (Index = 0; Index < ConsoleOutMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleOutMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + NewTerminalContext->IsConOut = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleOutMenu.MenuNumber]; + } + + Var_UpdateConsoleOutOption (); + break; + + case FORM_CON_ERR_ID: + for (Index = 0; Index < ConsoleErrMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&ConsoleErrMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + NewConsoleContext->IsActive = CurrentFakeNVMap->ConsoleCheck[Index]; + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + NewTerminalContext->IsStdErr = CurrentFakeNVMap->ConsoleCheck[Index + ConsoleErrMenu.MenuNumber]; + } + + Var_UpdateErrorOutOption (); + break; + + case FORM_DRV_ADD_HANDLE_DESC_ID: + Status = Var_UpdateDriverOption ( + Private, + Private->BmmHiiHandle, + CurrentFakeNVMap->DriverAddHandleDesc, + CurrentFakeNVMap->DriverAddHandleOptionalData, + CurrentFakeNVMap->DriverAddForceReconnect + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + BOpt_GetDriverOptions (Private); + CreateMenuStringToken (Private, Private->BmmHiiHandle, &DriverOptionMenu); + break; + + default: + break; + } + +Error: + return Status; +} + +VOID +DiscardChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap + ) +{ + UINT16 Index; + + switch (Private->BmmPreviousPageId) { + case FORM_BOOT_CHG_ID: + case FORM_DRV_CHG_ID: + CopyMem (CurrentFakeNVMap->OptionOrder, Private->BmmOldFakeNVData.OptionOrder, 100); + break; + + case FORM_BOOT_DEL_ID: + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + CurrentFakeNVMap->BootOptionDel[Index] = 0x00; + } + break; + + case FORM_DRV_DEL_ID: + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + CurrentFakeNVMap->DriverOptionDel[Index] = 0x00; + } + break; + + case FORM_BOOT_NEXT_ID: + CurrentFakeNVMap->BootNext = Private->BmmOldFakeNVData.BootNext; + break; + + case FORM_TIME_OUT_ID: + CurrentFakeNVMap->BootTimeOut = Private->BmmOldFakeNVData.BootTimeOut; + break; + + case FORM_DRV_ADD_HANDLE_DESC_ID: + case FORM_DRV_ADD_FILE_ID: + case FORM_DRV_ADD_HANDLE_ID: + CurrentFakeNVMap->DriverAddHandleDesc[0] = 0x0000; + CurrentFakeNVMap->DriverAddHandleOptionalData[0] = 0x0000; + break; + + default: + break; + } +} + +EFI_STATUS +EFIAPI +NvWrite ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 Attributes OPTIONAL, + IN OUT UINTN DataSize, + OUT VOID *Buffer, + OUT BOOLEAN *ResetRequired + ) +{ + // + // Do nothing here. Just to catch the F10, we use "Apply Changes" tag to save. + // + return EFI_SUCCESS; +} + +EFI_STATUS +InitializeBM ( + VOID + ) +/*++ +Routine Description: + + Initialize the Boot Maintenance Utitliy + +Arguments: + + ImageHandle - caller provided handle + + SystemTable - caller provided system tables + +Returns: + + EFI_SUCCESS - utility ended successfully + + others - contain some errors + +--*/ +{ + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + EFI_HII_PACKAGES *PackageList; + BMM_CALLBACK_DATA *BmmCallbackInfo; + EFI_HII_PROTOCOL *Hii; + EFI_HII_HANDLE HiiHandle; + EFI_STATUS Status; + EFI_HANDLE Handle; + UINT8 *Ptr; + UINT8 *Location; + + Status = EFI_SUCCESS; + UpdateData = NULL; + // + // Initialize EfiUtilityLib and EfiDriverLib + // Since many functions in UtilityLib must be used and + // SetupBrowser use DriverLib + // + // + // There should be only one EFI_HII_PROTOCOL Image + // + Status = EfiLibLocateProtocol (&gEfiHiiProtocolGuid, &Hii); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Create CallbackData structures for Driver Callback + // + BmmCallbackInfo = AllocateZeroPool (sizeof (BMM_CALLBACK_DATA)); + if (!BmmCallbackInfo) { + return EFI_OUT_OF_RESOURCES; + } + // + // Create LoadOption in BmmCallbackInfo for Driver Callback + // + Ptr = AllocateZeroPool (sizeof (BM_LOAD_CONTEXT) + sizeof (BM_FILE_CONTEXT) + sizeof (BM_HANDLE_CONTEXT) + sizeof (BM_MENU_ENTRY)); + if (!Ptr) { + SafeFreePool (BmmCallbackInfo); + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize Bmm callback data. + // + BmmCallbackInfo->LoadContext = (BM_LOAD_CONTEXT *) Ptr; + Ptr += sizeof (BM_LOAD_CONTEXT); + + BmmCallbackInfo->FileContext = (BM_FILE_CONTEXT *) Ptr; + Ptr += sizeof (BM_FILE_CONTEXT); + + BmmCallbackInfo->HandleContext = (BM_HANDLE_CONTEXT *) Ptr; + Ptr += sizeof (BM_HANDLE_CONTEXT); + + BmmCallbackInfo->MenuEntry = (BM_MENU_ENTRY *) Ptr; + + BmmCallbackInfo->BmmFakeNvData = &BmmCallbackInfo->BmmOldFakeNVData; + + ZeroMem (BmmCallbackInfo->BmmFakeNvData, sizeof (BMM_FAKE_NV_DATA)); + + BmmCallbackInfo->Signature = BMM_CALLBACK_DATA_SIGNATURE; + BmmCallbackInfo->Hii = Hii; + BmmCallbackInfo->BmmDriverCallback.NvRead = NULL; + BmmCallbackInfo->BmmDriverCallback.NvWrite = NvWrite; + BmmCallbackInfo->BmmDriverCallback.Callback = DriverCallback; + BmmCallbackInfo->BmmPreviousPageId = FORM_MAIN_ID; + BmmCallbackInfo->BmmCurrentPageId = FORM_MAIN_ID; + BmmCallbackInfo->FeDriverCallback.NvRead = NULL; + BmmCallbackInfo->FeDriverCallback.NvWrite = NvWrite; + BmmCallbackInfo->FeDriverCallback.Callback = FileExplorerCallback; + BmmCallbackInfo->FeCurrentState = INACTIVE_STATE; + BmmCallbackInfo->FeDisplayContext = UNKNOWN_CONTEXT; + + // + // Install bmm callback protocol interface + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiFormCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &BmmCallbackInfo->BmmDriverCallback + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + BmmCallbackInfo->BmmCallbackHandle = Handle; + + // + // Install file explorer callback protocol interface + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiFormCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &BmmCallbackInfo->FeDriverCallback + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + BmmCallbackInfo->FeCallbackHandle = Handle; + + // + // Post our VFR to the HII database. + // + PackageList = PreparePackages (1, &gBdsStringPackGuid, bmBin); + Status = Hii->NewPack (Hii, PackageList, &HiiHandle); + gBS->FreePool (PackageList); + + BmmCallbackInfo->BmmHiiHandle = HiiHandle; + + PackageList = PreparePackages (1, &gBdsStringPackGuid, FEBin); + Status = Hii->NewPack (Hii, PackageList, &HiiHandle); + gBS->FreePool (PackageList); + + BmmCallbackInfo->FeHiiHandle = HiiHandle; + + // + // Allocate space for creation of Buffer + // + UpdateData = AllocateZeroPool (UPDATE_DATA_SIZE); + if (!UpdateData) { + SafeFreePool (BmmCallbackInfo->LoadContext); + SafeFreePool (BmmCallbackInfo); + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize UpdateData structure + // + RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) BmmCallbackInfo->BmmCallbackHandle, FALSE, 0, 0); + + Location = (UINT8 *) &UpdateData->Data; + + InitializeStringDepository (); + + InitAllMenu (BmmCallbackInfo); + + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleInpMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleOutMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &ConsoleErrMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &BootOptionMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverOptionMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &TerminalMenu); + CreateMenuStringToken (BmmCallbackInfo, BmmCallbackInfo->BmmHiiHandle, &DriverMenu); + + UpdateBootDelPage (BmmCallbackInfo); + UpdateDrvDelPage (BmmCallbackInfo); + + if (TerminalMenu.MenuNumber > 0) { + BmmCallbackInfo->CurrentTerminal = 0; + UpdateTerminalPage (BmmCallbackInfo); + } + + Location = (UINT8 *) &UpdateData->Data; + Status = EfiLibLocateProtocol (&gEfiLegacyBiosProtocolGuid, &LegacyBios); + if (!EFI_ERROR (Status)) { + // + // If LegacyBios Protocol is installed, add 3 tags about legacy boot option + // in BootOption form: legacy FD/HD/CD/NET/BEV + // + UpdateData->DataCount = 5; + CreateGotoOpCode ( + FORM_SET_FD_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_FD_ORDER_TITLE), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_SET_FD_ORDER_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateGotoOpCode ( + FORM_SET_HD_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_HD_ORDER_TITLE), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_SET_HD_ORDER_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateGotoOpCode ( + FORM_SET_CD_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_CD_ORDER_TITLE), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_SET_CD_ORDER_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateGotoOpCode ( + FORM_SET_NET_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_NET_ORDER_TITLE), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_SET_NET_ORDER_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateGotoOpCode ( + FORM_SET_BEV_ORDER_ID, + STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), + STRING_TOKEN (STR_FORM_SET_BEV_ORDER_TITLE), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_SET_BEV_ORDER_ID, + Location + ); + + Hii->UpdateForm ( + Hii, + BmmCallbackInfo->BmmHiiHandle, + (EFI_FORM_LABEL) FORM_BOOT_LEGACY_DEVICE_ID, + TRUE, + UpdateData + ); + } + // + // Dispatch BMM main formset and File Explorer formset. + // + FormSetDispatcher (BmmCallbackInfo); + + Hii->ResetStrings (Hii, HiiHandle); + + CleanUpStringDepository (); + + if (EFI_ERROR (Status)) { + return Status; + } + + FreeAllMenu (); + + SafeFreePool (BmmCallbackInfo->LoadContext); + BmmCallbackInfo->LoadContext = NULL; + SafeFreePool (BmmCallbackInfo); + BmmCallbackInfo = NULL; + SafeFreePool (UpdateData); + UpdateData = NULL; + + return Status; +} + +VOID +InitAllMenu ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + InitializeListHead (&BootOptionMenu.Head); + InitializeListHead (&DriverOptionMenu.Head); + BOpt_GetBootOptions (CallbackData); + BOpt_GetDriverOptions (CallbackData); + BOpt_GetLegacyOptions (); + InitializeListHead (&FsOptionMenu.Head); + BOpt_FindDrivers (); + InitializeListHead (&DirectoryMenu.Head); + InitializeListHead (&ConsoleInpMenu.Head); + InitializeListHead (&ConsoleOutMenu.Head); + InitializeListHead (&ConsoleErrMenu.Head); + InitializeListHead (&TerminalMenu.Head); + LocateSerialIo (); + GetAllConsoles (); +} + +VOID +FreeAllMenu ( + VOID + ) +{ + BOpt_FreeMenu (&DirectoryMenu); + BOpt_FreeMenu (&FsOptionMenu); + BOpt_FreeMenu (&BootOptionMenu); + BOpt_FreeMenu (&DriverOptionMenu); + BOpt_FreeMenu (&DriverMenu); + BOpt_FreeLegacyOptions (); + FreeAllConsoles (); +} + +VOID +InitializeStringDepository ( + VOID + ) +/*++ +Routine Description: + Intialize all the string depositories. + +Arguments: + None. + +Returns: + None. +--*/ +{ + STRING_DEPOSITORY *StringDepository; + StringDepository = AllocateZeroPool (sizeof (STRING_DEPOSITORY) * STRING_DEPOSITORY_NUMBER); + FileOptionStrDepository = StringDepository++; + ConsoleOptionStrDepository = StringDepository++; + BootOptionStrDepository = StringDepository++; + BootOptionHelpStrDepository = StringDepository++; + DriverOptionStrDepository = StringDepository++; + DriverOptionHelpStrDepository = StringDepository++; + TerminalStrDepository = StringDepository; +} + +STRING_REF +GetStringTokenFromDepository ( + IN BMM_CALLBACK_DATA *CallbackData, + IN STRING_DEPOSITORY *StringDepository + ) +/*++ +Routine Description: + Fetch a usable string node from the string depository and return the string token. + +Arguments: + StringDepository - Pointer of the string depository. + +Returns: + STRING_REF - String token. +--*/ +{ + STRING_LIST_NODE *CurrentListNode; + STRING_LIST_NODE *NextListNode; + + CurrentListNode = StringDepository->CurrentNode; + + if ((NULL != CurrentListNode) && (NULL != CurrentListNode->Next)) { + // + // Fetch one reclaimed node from the list. + // + NextListNode = StringDepository->CurrentNode->Next; + } else { + // + // If there is no usable node in the list, update the list. + // + NextListNode = AllocateZeroPool (sizeof (STRING_LIST_NODE)); + + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + CallbackData->BmmHiiHandle, + &(NextListNode->StringToken), + L" " + ); + + ASSERT (NextListNode->StringToken != 0); + + StringDepository->TotalNodeNumber++; + + if (NULL == CurrentListNode) { + StringDepository->ListHead = NextListNode; + } else { + CurrentListNode->Next = NextListNode; + } + } + + StringDepository->CurrentNode = NextListNode; + + return StringDepository->CurrentNode->StringToken; +} + +VOID +ReclaimStringDepository ( + VOID + ) +/*++ +Routine Description: + Reclaim string depositories by moving the current node pointer to list head.. + +Arguments: + None. + +Returns: + None. +--*/ +{ + UINTN DepositoryIndex; + STRING_DEPOSITORY *StringDepository; + + StringDepository = FileOptionStrDepository; + for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { + StringDepository->CurrentNode = StringDepository->ListHead; + StringDepository++; + } +} + +VOID +CleanUpStringDepository ( + VOID + ) +/*++ +Routine Description: + Release resource for all the string depositories. + +Arguments: + None. + +Returns: + None. +--*/ +{ + UINTN NodeIndex; + UINTN DepositoryIndex; + STRING_LIST_NODE *CurrentListNode; + STRING_LIST_NODE *NextListNode; + STRING_DEPOSITORY *StringDepository; + + // + // Release string list nodes. + // + StringDepository = FileOptionStrDepository; + for (DepositoryIndex = 0; DepositoryIndex < STRING_DEPOSITORY_NUMBER; DepositoryIndex++) { + CurrentListNode = StringDepository->ListHead; + for (NodeIndex = 0; NodeIndex < StringDepository->TotalNodeNumber; NodeIndex++) { + NextListNode = CurrentListNode->Next; + SafeFreePool (CurrentListNode); + CurrentListNode = NextListNode; + } + + StringDepository++; + } + // + // Release string depository. + // + SafeFreePool (FileOptionStrDepository); +} + +EFI_STATUS +BdsStartBootMaint ( + VOID + ) +/*++ + +Routine Description: + Start boot maintenance manager + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY BdsBootOptionList; + + InitializeListHead (&BdsBootOptionList); + + // + // Connect all prior to entering the platform setup menu. + // + if (!gConnectAllHappened) { + BdsLibConnectAllDriversToAllControllers (); + gConnectAllHappened = TRUE; + } + // + // Have chance to enumerate boot device + // + BdsLibEnumerateAllBootOption (&BdsBootOptionList); + + // + // Init the BMM + // + Status = InitializeBM (); + + return Status; +} + +EFI_STATUS +FormSetDispatcher ( + IN BMM_CALLBACK_DATA *CallbackData + ) +/*++ + +Routine Description: + Dispatch BMM formset and FileExplorer formset. + +Arguments: + +Returns: + +--*/ +{ + EFI_FORM_BROWSER_PROTOCOL *FormConfig; + UINT8 *Location; + EFI_STATUS Status; + UINTN Index; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *NewFileContext; + + Location = NULL; + Index = 0; + NewMenuEntry = NULL; + NewFileContext = NULL; + + // + // There should only be one Form Configuration protocol + // + Status = EfiLibLocateProtocol (&gEfiFormBrowserProtocolGuid, &FormConfig); + if (EFI_ERROR (Status)) { + return Status; + } + + while (1) { + UpdatePageId (CallbackData, FORM_MAIN_ID); + + Status = FormConfig->SendForm ( + FormConfig, + TRUE, + &(CallbackData->BmmHiiHandle), + 1, + NULL, + NULL, + (UINT8 *) CallbackData->BmmFakeNvData, + NULL, + NULL + ); + + ReclaimStringDepository (); + + // + // When this Formset returns, check if we are going to explore files. + // + if (INACTIVE_STATE != CallbackData->FeCurrentState) { + UpdateFileExplorer (CallbackData, 0); + + Status = FormConfig->SendForm ( + FormConfig, + TRUE, + &(CallbackData->FeHiiHandle), + 1, + NULL, + NULL, + NULL, + NULL, + NULL + ); + + CallbackData->FeCurrentState = INACTIVE_STATE; + CallbackData->FeDisplayContext = UNKNOWN_CONTEXT; + ReclaimStringDepository (); + } else { + break; + } + } + + return Status; +} + +VOID +CreateCallbackPacket ( + OUT EFI_HII_CALLBACK_PACKET **Packet, + IN UINT16 Flags + ) +{ + *Packet = (EFI_HII_CALLBACK_PACKET *) AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2); + ASSERT (*Packet != NULL); + + (*Packet)->DataArray.EntryCount = 1; + (*Packet)->DataArray.NvRamMap = NULL; + ((EFI_IFR_DATA_ENTRY *) (&((*Packet)->DataArray) + 1))->Flags = Flags; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BootMaint.h b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BootMaint.h new file mode 100644 index 0000000000..1e0dc8de87 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BootMaint.h @@ -0,0 +1,1161 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + bootmaint.h + +Abstract: + +Revision History + +--*/ + +#ifndef _BOOT_MAINT_H +#define _BOOT_MAINT_H + +#include "BdsStrDefs.h" +#include "Generic/BootMaint/BBSsupport.h" + +// +// Constants which are variable names used to access variables +// +#define VarLegacyDevOrder L"LegacyDevOrder" + +// +// Guid of a NV Variable which store the information about the +// FD/HD/CD/NET/BEV order +// +#define EFI_LEGACY_DEV_ORDER_VARIABLE_GUID \ + { \ + 0xa56074db, 0x65fe, 0x45f7, {0xbd, 0x21, 0x2d, 0x2b, 0xdd, 0x8e, 0x96, 0x52 } \ + } + +// +// String Contant +// +#define StrFloppy L"Floppy Drive #%02x" +#define StrHardDisk L"HardDisk Drive #%02x" +#define StrCDROM L"ATAPI CDROM Drive #%02x" +#define StrNET L"NET Drive #%02x" +#define StrBEV L"BEV Drive #%02x" +#define StrFloppyHelp L"Select Floppy Drive #%02x" +#define StrHardDiskHelp L"Select HardDisk Drive #%02x" +#define StrCDROMHelp L"Select ATAPI CDROM Drive #%02x" +#define StrNETHelp L"NET Drive #%02x" +#define StrBEVHelp L"BEV Drive #%02x" + +// +// Constant will be used in display and file system navigation +// +#define UPDATE_DATA_SIZE 0x100000 +#define MAX_BBS_OFFSET 0xE000 +#define NET_OPTION_OFFSET 0xD800 +#define BEV_OPTION_OFFSET 0xD000 +#define FD_OPTION_OFFSET 0xC000 +#define HD_OPTION_OFFSET 0xB000 +#define CD_OPTION_OFFSET 0xA000 +#define FILE_OPTION_OFFSET 0x8000 +#define FILE_OPTION_MASK 0x7FFF +#define HANDLE_OPTION_OFFSET 0x7000 +#define CONSOLE_OPTION_OFFSET 0x0A00 +#define TERMINAL_OPTION_OFFSET 0x0700 +#define NORMAL_GOTO_OFFSET 0x0100 +#define MAX_STRING_TOKEN_COUNT 0x00FF +// +// Variable created with this flag will be "Efi:...." +// +#define VAR_FLAG EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE + +// +// Define Maxmim characters that will be accepted +// +#define MAX_CHAR 480 +#define MAX_CHAR_SIZE (MAX_CHAR * 2) + +// +// Check to see if current build support option active feature of +// some driver option +// +#ifndef LOAD_OPTION_ACTIVE +#define LOAD_OPTION_ACTIVE 0x00000001 +#endif +// +// Check to see if current build support force reconnect feature of +// some driver option +// +#ifndef LOAD_OPTION_FORCE_RECONNECT +#define LOAD_OPTION_FORCE_RECONNECT 0x00000002 +#endif +// +// Below are the form ids for display, form id is used as callback key value, +// some key value definitions are also defined here. By defining this enum type, +// We can easy know where we are. The int to UINT16 convertion should be ok because +// there is a MAXIMUM_FORM_ID which in within the range of UINT16. +// +typedef enum { + IplRelative, + BcvRelative +} BBS_TYPE; + +typedef enum { + FORM_RESERVED_ID = 0, + FORM_MAIN_ID, // 0x0001 + FORM_BOOT_ADD_ID, // 0x0002 + FORM_BOOT_DEL_ID, // 0x0003 + FORM_BOOT_CHG_ID, // 0x0004 + FORM_DRV_ADD_ID, // 0x0005 + FORM_DRV_DEL_ID, // 0x0006 + FORM_DRV_CHG_ID, // 0x0007 + FORM_CON_MAIN_ID, // 0x0008 + FORM_CON_IN_ID, // 0x0009 + FORM_CON_OUT_ID, // 0x000A + FORM_CON_ERR_ID, // 0x000B + FORM_FILE_SEEK_ID, // 0x000C + FORM_FILE_NEW_SEEK_ID, // 0x000D + FORM_DRV_ADD_FILE_ID, // 0x000E + FORM_DRV_ADD_HANDLE_ID, // 0x000F + FORM_DRV_ADD_HANDLE_DESC_ID, // 0x0010 + FORM_BOOT_NEXT_ID, // 0x0011 + FORM_TIME_OUT_ID, // 0x0012 + FORM_RESET, // 0x0013 + FORM_BOOT_SETUP_ID, // 0x0014 + FORM_DRIVER_SETUP_ID, // 0x0015 + FORM_BOOT_LEGACY_DEVICE_ID, // 0x0016 + FORM_CON_COM_ID, // 0x0017 + FORM_CON_COM_SETUP_ID, // 0x0018 + FORM_SET_FD_ORDER_ID, // 0x0019 + FORM_SET_HD_ORDER_ID, // 0x001A + FORM_SET_CD_ORDER_ID, // 0x001B + FORM_SET_NET_ORDER_ID, // 0x001C + FORM_SET_BEV_ORDER_ID, // 0x001D + FORM_FILE_EXPLORER_ID, // 0x001E + FORM_BOOT_ADD_DESCRIPTION_ID, // 0x001F + FORM_DRIVER_ADD_FILE_DESCRIPTION_ID, // 0x0020 +} FORM_ID; + +#define MAXIMUM_FORM_ID 0x007F + +#define KEY_VALUE_COM_SET_BAUD_RATE 0x0080 +#define KEY_VALUE_COM_SET_DATA_BITS 0x0081 +#define KEY_VALUE_COM_SET_STOP_BITS 0x0082 +#define KEY_VALUE_COM_SET_PARITY 0x0083 +#define KEY_VALUE_COM_SET_TERMI_TYPE 0x0084 +#define KEY_VALUE_MAIN_BOOT_NEXT 0x0085 +#define KEY_VALUE_BOOT_ADD_DESC_DATA 0x0086 +#define KEY_VALUE_BOOT_ADD_OPT_DATA 0x0087 +#define KEY_VALUE_DRIVER_ADD_DESC_DATA 0x0088 +#define KEY_VALUE_DRIVER_ADD_OPT_DATA 0x0089 +#define KEY_VALUE_SAVE_AND_EXIT 0x0090 +#define KEY_VALUE_NO_SAVE_AND_EXIT 0x0091 +#define KEY_VALUE_BOOT_FROM_FILE 0x0092 + +#define MAXIMUM_NORMAL_KEY_VALUE NORMAL_GOTO_OFFSET +// +// Below are the number of options in Baudrate, Databits, +// Parity and Stopbits selection for serial ports. +// +#define BM_COM_ATTR_BUADRATE 19 +#define BM_COM_ATTR_DATABITS 4 +#define BM_COM_ATTR_PARITY 5 +#define BM_COM_ATTR_STOPBITS 3 + +// +// Callback function helper +// +#define BMM_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('C', 'b', 'c', 'k') +#define BMM_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, BmmDriverCallback, BMM_CALLBACK_DATA_SIGNATURE) + +#define FE_CALLBACK_DATA_FROM_THIS(a) CR (a, BMM_CALLBACK_DATA, FeDriverCallback, BMM_CALLBACK_DATA_SIGNATURE) + +// +// Enumeration type definition +// +typedef enum { + PC_ANSI = 0, + VT_100, + VT_100_PLUS, + VT_UTF8 +} TYPE_OF_TERMINAL; + +typedef enum { + COM1 = 0, + COM2, + UNKNOW_COM +} TYPE_OF_COM; + +typedef enum { + CONIN = 0, + CONOUT, + CONERR, + UNKNOWN_CON +} TYPE_OF_CON; + +typedef enum { + BAUDRATE = 0, + DATABITS, + PARITY, + STOPBITS, + UNKNOW_ATTR +} TYPE_OF_ATTRIBUTE; + +typedef enum { + MANNER_GOTO = 0, + MANNER_CHECK, + MANNER_ONEOF, + MANNER_USER_DEFINE +} TYPE_OF_UPATE_MANNER; + +typedef enum { + INACTIVE_STATE = 0, + BOOT_FROM_FILE_STATE, + ADD_BOOT_OPTION_STATE, + ADD_DRIVER_OPTION_STATE, + UNKNOWN_STATE +} FILE_EXPLORER_STATE; + +typedef enum { + FILE_SYSTEM, + DIRECTORY, + UNKNOWN_CONTEXT +} FILE_EXPLORER_DISPLAY_CONTEXT; + +// +// All of the signatures that will be used in list structure +// +#define BM_MENU_OPTION_SIGNATURE 'menu' +#define BM_LOAD_OPTION_SIGNATURE 'load' +#define BM_CONSOLE_OPTION_SIGNATURE 'cnsl' +#define BM_FILE_OPTION_SIGNATURE 'file' +#define BM_HANDLE_OPTION_SIGNATURE 'hndl' +#define BM_TERMINAL_OPTION_SIGNATURE 'trml' +#define BM_MENU_ENTRY_SIGNATURE 'entr' + +#define BM_LOAD_CONTEXT_SELECT 0x0 +#define BM_CONSOLE_CONTEXT_SELECT 0x1 +#define BM_FILE_CONTEXT_SELECT 0x2 +#define BM_HANDLE_CONTEXT_SELECT 0x3 +#define BM_TERMINAL_CONTEXT_SELECT 0x5 + +#define BM_CONSOLE_IN_CONTEXT_SELECT 0x6 +#define BM_CONSOLE_OUT_CONTEXT_SELECT 0x7 +#define BM_CONSOLE_ERR_CONTEXT_SELECT 0x8 +#define BM_LEGACY_DEV_CONTEXT_SELECT 0x9 + +// +// Question Id that will be used to create question +// all these values are computed from the structure +// defined below +// +#define QUESTION_ID(Field) ((UINTN) &(((BMM_FAKE_NV_DATA *) 0)->Field)) + +#define BOOT_TIME_OUT_QUESTION_ID QUESTION_ID (BootTimeOut) +#define BOOT_NEXT_QUESTION_ID QUESTION_ID (BootNext) +#define COM1_BAUD_RATE_QUESTION_ID QUESTION_ID (COM1BaudRate) +#define COM1_DATA_RATE_QUESTION_ID QUESTION_ID (COM1DataRate) +#define COM1_STOP_BITS_QUESTION_ID QUESTION_ID (COM1StopBits) +#define COM1_PARITY_QUESTION_ID QUESTION_ID (COM1Parity) +#define COM1_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType) +#define COM2_BAUD_RATE_QUESTION_ID QUESTION_ID (COM2BaudRate) +#define COM2_DATA_RATE_QUESTION_ID QUESTION_ID (COM2DataRate) +#define COM2_STOP_BITS_QUESTION_ID QUESTION_ID (COM2StopBits) +#define COM2_PARITY_QUESTION_ID QUESTION_ID (COM2Parity) +#define COM2_TERMINAL_QUESTION_ID QUESTION_ID (COM2TerminalType) +#define DRV_ADD_HANDLE_DESC_QUESTION_ID QUESTION_ID (DriverAddHandleDesc) +#define DRV_ADD_ACTIVE_QUESTION_ID QUESTION_ID (DriverAddActive) +#define DRV_ADD_RECON_QUESTION_ID QUESTION_ID (DriverAddForceReconnect) +#define CON_IN_COM1_QUESTION_ID QUESTION_ID (ConsoleInputCOM1) +#define CON_IN_COM2_QUESTION_ID QUESTION_ID (ConsoleInputCOM2) +#define CON_OUT_COM1_QUESTION_ID QUESTION_ID (ConsoleOutputCOM1) +#define CON_OUT_COM2_QUESTION_ID QUESTION_ID (ConsoleOutputCOM2) +#define CON_ERR_COM1_QUESTION_ID QUESTION_ID (ConsoleErrorCOM1) +#define CON_ERR_COM2_QUESTION_ID QUESTION_ID (ConsoleErrorCOM2) +#define CON_DEVICE_QUESTION_ID QUESTION_ID (ConsoleCheck) +#define OPTION_ORDER_QUESTION_ID QUESTION_ID (OptionOrder) +#define DRIVER_OPTION_ORDER_QUESTION_ID QUESTION_ID (DriverOptionToBeDeleted) +#define BOOT_OPTION_DEL_QUESTION_ID QUESTION_ID (BootOptionDel) +#define DRIVER_OPTION_DEL_QUESTION_ID QUESTION_ID (DriverOptionDel) +#define DRIVER_ADD_OPTION_QUESTION_ID QUESTION_ID (DriverAddHandleOptionalData) +#define COM_BAUD_RATE_QUESTION_ID QUESTION_ID (COMBaudRate) +#define COM_DATA_RATE_QUESTION_ID QUESTION_ID (COMDataRate) +#define COM_STOP_BITS_QUESTION_ID QUESTION_ID (COMStopBits) +#define COM_PARITY_QUESTION_ID QUESTION_ID (COMParity) +#define COM_TERMINAL_QUESTION_ID QUESTION_ID (COMTerminalType) +#define LEGACY_FD_QUESTION_ID QUESTION_ID (LegacyFD) +#define LEGACY_HD_QUESTION_ID QUESTION_ID (LegacyHD) +#define LEGACY_CD_QUESTION_ID QUESTION_ID (LegacyCD) +#define LEGACY_NET_QUESTION_ID QUESTION_ID (LegacyNET) +#define LEGACY_BEV_QUESTION_ID QUESTION_ID (LegacyBEV) + +#define STRING_DEPOSITORY_NUMBER 8 + +// +// #pragma pack(1) +// +// Serial Ports attributes, first one is the value for +// return from callback function, stringtoken is used to +// display the value properly +// +typedef struct { + UINTN Value; + UINT16 StringToken; +} COM_ATTR; + +// +// This is the structure that will be used to store the +// question's current value. Use it at initialize time to +// set default value for each question. When using at run +// time, this map is returned by the callback function, +// so dynamically changing the question's value will be +// possible through this mechanism +// +typedef struct { + // + // Three questions displayed at the main page + // for Timeout, BootNext Variables respectively + // + UINT16 BootTimeOut; + UINT16 BootNext; + + // + // This is the COM1 Attributes value storage + // + UINT8 COM1BaudRate; + UINT8 COM1DataRate; + UINT8 COM1StopBits; + UINT8 COM1Parity; + UINT8 COM1TerminalType; + + // + // This is the COM2 Attributes value storage + // + UINT8 COM2BaudRate; + UINT8 COM2DataRate; + UINT8 COM2StopBits; + UINT8 COM2Parity; + UINT8 COM2TerminalType; + + // + // Driver Option Add Handle page storage + // + UINT16 DriverAddHandleDesc[75]; + UINT16 DriverAddHandleOptionalData[75]; + UINT8 DriverAddActive; + UINT8 DriverAddForceReconnect; + + // + // Console Input/Output/Errorout using COM port check storage + // + UINT8 ConsoleInputCOM1; + UINT8 ConsoleInputCOM2; + UINT8 ConsoleOutputCOM1; + UINT8 ConsoleOutputCOM2; + UINT8 ConsoleErrorCOM1; + UINT8 ConsoleErrorCOM2; + + // + // At most 100 input/output/errorout device for console storage + // + UINT8 ConsoleCheck[100]; + + // + // Boot or Driver Option Order storage + // + UINT8 OptionOrder[100]; + UINT8 DriverOptionToBeDeleted[100]; + + // + // Boot Option Delete storage + // + UINT8 BootOptionDel[100]; + UINT8 DriverOptionDel[100]; + + // + // This is the Terminal Attributes value storage + // + UINT8 COMBaudRate; + UINT8 COMDataRate; + UINT8 COMStopBits; + UINT8 COMParity; + UINT8 COMTerminalType; + + // + // Legacy Device Order Selection Storage + // + UINT8 LegacyFD[100]; + UINT8 LegacyHD[100]; + UINT8 LegacyCD[100]; + UINT8 LegacyNET[100]; + UINT8 LegacyBEV[100]; + + // + // We use DisableMap array to record the enable/disable state of each boot device + // It should be taken as a bit array, from left to right there are totally 256 bits + // the most left one stands for BBS table item 0, and the most right one stands for item 256 + // If the bit is 1, it means the boot device has been disabled. + // + UINT8 DisableMap[32]; + + // + // UINT16 PadArea[10]; + // +} BMM_FAKE_NV_DATA; + +typedef struct { + UINT16 DescriptionData[75]; + UINT16 OptionalData[127]; + UINT8 Active; + UINT8 ForceReconnect; +} FILE_EXPLORER_NV_DATA; + +typedef struct { + BBS_TYPE BbsType; + // + // Length = sizeof (UINT16) + SIZEOF (Data) + // + UINT16 Length; + UINT16 *Data; +} BM_LEGACY_DEV_ORDER_CONTEXT; + +typedef struct { + UINT64 BaudRate; + UINT8 DataBits; + UINT8 Parity; + UINT8 StopBits; + + UINT8 BaudRateIndex; + UINT8 DataBitsIndex; + UINT8 ParityIndex; + UINT8 StopBitsIndex; + + UINT8 IsConIn; + UINT8 IsConOut; + UINT8 IsStdErr; + UINT8 TerminalType; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_TERMINAL_CONTEXT; + +typedef struct { + BOOLEAN IsBootNext; + BOOLEAN LoadOptionModified; + BOOLEAN Deleted; + + BOOLEAN IsLegacy; + BOOLEAN IsActive; + BOOLEAN ForceReconnect; + UINTN OptionalDataSize; + + UINTN LoadOptionSize; + UINT8 *LoadOption; + + UINT32 Attributes; + UINT16 FilePathListLength; + UINT16 *Description; + EFI_DEVICE_PATH_PROTOCOL *FilePathList; + UINT8 *OptionalData; + + UINT16 BbsIndex; +} BM_LOAD_CONTEXT; + +typedef struct { + BBS_TABLE *BbsTable; + UINTN Index; + UINTN BbsCount; + UINT16 *Description; +} BM_LEGACY_DEVICE_CONTEXT; + +typedef struct { + + BOOLEAN IsActive; + + BOOLEAN IsTerminal; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_CONSOLE_CONTEXT; + +typedef struct { + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_FILE_HANDLE FHandle; + UINT16 *FileName; + EFI_FILE_SYSTEM_VOLUME_LABEL_INFO *Info; + + BOOLEAN IsRoot; + BOOLEAN IsDir; + BOOLEAN IsRemovableMedia; + BOOLEAN IsLoadFile; + BOOLEAN IsBootLegacy; +} BM_FILE_CONTEXT; + +typedef struct { + EFI_HANDLE Handle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; +} BM_HANDLE_CONTEXT; + +typedef struct { + UINTN Signature; + LIST_ENTRY Head; + UINTN MenuNumber; +} BM_MENU_OPTION; + +typedef struct { + UINTN Signature; + LIST_ENTRY Link; + UINTN OptionNumber; + UINT16 *DisplayString; + UINT16 *HelpString; + STRING_REF DisplayStringToken; + STRING_REF HelpStringToken; + UINTN ContextSelection; + VOID *VariableContext; +} BM_MENU_ENTRY; + +typedef struct { + // + // Shared callback data. + // + UINTN Signature; + EFI_HII_PROTOCOL *Hii; + BM_MENU_ENTRY *MenuEntry; + BM_HANDLE_CONTEXT *HandleContext; + BM_FILE_CONTEXT *FileContext; + BM_LOAD_CONTEXT *LoadContext; + BM_TERMINAL_CONTEXT *TerminalContext; + UINTN CurrentTerminal; + BBS_TYPE BbsType; + + // + // BMM main formset callback data. + // + EFI_HII_HANDLE BmmHiiHandle; + EFI_HANDLE BmmCallbackHandle; + EFI_FORM_CALLBACK_PROTOCOL BmmDriverCallback; + FORM_ID BmmCurrentPageId; + FORM_ID BmmPreviousPageId; + BOOLEAN BmmAskSaveOrNot; + BMM_FAKE_NV_DATA *BmmFakeNvData; + BMM_FAKE_NV_DATA BmmOldFakeNVData; + + // + // File explorer formset callback data. + // + EFI_HII_HANDLE FeHiiHandle; + EFI_HANDLE FeCallbackHandle; + EFI_FORM_CALLBACK_PROTOCOL FeDriverCallback; + FILE_EXPLORER_STATE FeCurrentState; + FILE_EXPLORER_DISPLAY_CONTEXT FeDisplayContext; +} BMM_CALLBACK_DATA; + +typedef struct _STRING_LIST_NODE { + STRING_REF StringToken; + struct _STRING_LIST_NODE *Next; +} STRING_LIST_NODE; + +typedef struct _STRING_DEPOSITORY { + UINTN TotalNodeNumber; + STRING_LIST_NODE *CurrentNode; + STRING_LIST_NODE *ListHead; +} STRING_DEPOSITORY; + +// +// #pragma pack() +// +// For initializing File System menu +// +EFI_STATUS +BOpt_FindFileSystem ( + IN BMM_CALLBACK_DATA *CallbackData + ) +; + +// +// For cleaning up File System menu +// +VOID +BOpt_FreeFileSystem ( + VOID + ) +; + +// +// For initializing File Navigation menu +// +EFI_STATUS +BOpt_FindFiles ( + IN BMM_CALLBACK_DATA *CallbackData, + IN BM_MENU_ENTRY *MenuEntry + ) +; + +// +// For cleaning up File Navigation menu +// +VOID +BOpt_FreeFiles ( + VOID + ) +; + +// +// For Initializing handle navigation menu +// +EFI_STATUS +BOpt_FindDrivers ( + VOID + ) +; + +// +// For Cleaning up handle navigation menu +// +VOID +BOpt_FreeDrivers(); + +// +// For initializing Boot Option menu +// +EFI_STATUS +BOpt_GetBootOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// For Initializing Driver option menu +// +EFI_STATUS +BOpt_GetDriverOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// For Cleaning up boot option menu +// +VOID +BOpt_FreeBootOptions (); + +// +// For cleaning up driver option menu +// +VOID +BOpt_FreeDriverOptions(); + +// +// For Initializing HD/FD/CD/NET/BEV option menu +// +EFI_STATUS +BOpt_GetLegacyOptions(); + +// +// For cleaning up driver option menu +// +VOID +BOpt_FreeLegacyOptions(); + +// +// this function is used to take place of all other free menu actions +// +VOID +BOpt_FreeMenu ( + BM_MENU_OPTION *FreeMenu + ); + + +// +// Following are the helper functions used +// +CHAR16 * +BOpt_AppendFileName ( + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ); + +BOOLEAN +BOpt_IsEfiImageName ( + IN UINT16 *FileName + ); + +BOOLEAN +BOpt_IsEfiApp ( + IN EFI_FILE_HANDLE Dir, + IN UINT16 *FileName + ); + +// +// Get current unused boot option number +// +UINT16 +BOpt_GetBootOptionNumber (); + +// +// Get current unused driver option number +// +UINT16 +BOpt_GetDriverOptionNumber (); + +BM_MENU_ENTRY * +BOpt_CreateMenuEntry ( + UINTN MenuType + ); + +VOID +BOpt_DestroyMenuEntry ( + BM_MENU_ENTRY *MenuEntry + ); + +BM_MENU_ENTRY * +BOpt_GetMenuEntry ( + BM_MENU_OPTION *MenuOption, + UINTN MenuNumber + ); + +// +// a helper function used to free pool type memory +// +VOID +SafeFreePool ( + IN VOID *Buffer + ); + +// +// Locate all serial io devices for console +// +EFI_STATUS +LocateSerialIo (); + +// +// Initializing Console menu +// +EFI_STATUS +GetAllConsoles(); + +// +// Cleaning up console menu +// +EFI_STATUS +FreeAllConsoles(); + +VOID +ChangeVariableDevicePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath +); + +EFI_STATUS +ChangeTerminalDevicePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath, + BOOLEAN ChangeTerminal +); +// +// Variable operation by menu selection +// +EFI_STATUS +Var_UpdateBootOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN FILE_EXPLORER_NV_DATA *NvRamMap + ); + +EFI_STATUS +Var_DelBootOption (); + +EFI_STATUS +Var_ChangeBootOrder (); + +EFI_STATUS +Var_UpdateDriverOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 *DescriptionData, + IN UINT16 *OptionalData, + IN UINT8 ForceReconnect + ); + +EFI_STATUS +Var_DelDriverOption (); + +EFI_STATUS +Var_ChangeDriverOrder (); + +EFI_STATUS +Var_UpdateConsoleInpOption (); + +EFI_STATUS +Var_UpdateConsoleOutOption (); + +EFI_STATUS +Var_UpdateErrorOutOption (); + +VOID +Var_UpdateAllConsoleOption (); + +EFI_STATUS +Var_UpdateBootNext ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +EFI_STATUS +Var_UpdateBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +EFI_STATUS +Var_UpdateDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +EFI_STATUS +Var_UpdateBBSOption ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +// +// Following are page create and refresh functions +// +VOID +RefreshUpdateData ( + IN BOOLEAN FormSetUpdate, + IN EFI_PHYSICAL_ADDRESS FormCallbackHandle, + IN BOOLEAN FormUpdate, + IN STRING_REF FormTitle, + IN UINT16 DataCount + ); + +VOID +CleanUpPage ( + IN EFI_FORM_LABEL LabelId, + IN BMM_CALLBACK_DATA *CallbackData + ); + +EFI_STATUS +UpdatePage ( + IN BMM_CALLBACK_DATA *CallbackData, + IN BM_MENU_OPTION *UpdatingMenu, + IN UINT16 UpdatingPage, + IN UINT16 UpdatingManner, + IN UINT16 QuestionIdStart, + IN UINT16 GotoForm, + IN UINT16 GotoAlternateForm, + IN STRING_REF DisplayTokenStart, + IN STRING_REF HelpTokenStart, + IN UINT16 KeyValueStart + ); + +VOID +UpdateBootAddPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateBootDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateDrvAddFilePage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateDrvAddHandlePage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateDrvDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateDriverAddHandleDescPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateBootTimeOut ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateConInPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateConOutPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateStdErrPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdatePageBody ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateCOM1Page ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateCOM2Page ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateBootOrderPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateDriverOrderPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateBootNextPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateTimeOutPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateTerminalPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateConCOMPage ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID +UpdateSetLegacyDeviceOrderPage ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData +); + +EFI_STATUS +BootLegacy ( + IN UINT16 BbsType, + IN UINT16 BbsFlag +); + +BM_MENU_ENTRY * +GetCurrentTerminal ( + UINTN TerminalNumber +); + +EFI_FILE_HANDLE +EfiLibOpenRoot ( + IN EFI_HANDLE DeviceHandle + ); + +EFI_FILE_SYSTEM_VOLUME_LABEL_INFO * +EfiLibFileSystemVolumeLabelInfo ( + IN EFI_FILE_HANDLE FHand + ); + +EFI_FILE_INFO * +EfiLibFileInfo ( + IN EFI_FILE_HANDLE FHand + ); + +CHAR16 * +DevicePathToStr ( + EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +EFI_STATUS +EfiLibLocateProtocol ( + IN EFI_GUID *ProtocolGuid, + OUT VOID **Interface + ); + +VOID * +EfiReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ); + +CHAR16 * +DevicePathToStr ( + EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +VOID * +BdsLibGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VarSize + ); + +EFI_STATUS +EfiLibDeleteVariable ( + IN CHAR16 *VarName, + IN EFI_GUID *VarGuid + ); + +CHAR16 * +EfiStrDuplicate ( + IN CHAR16 *Src + ); + +BOOLEAN +EfiLibMatchDevicePaths ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ); + +UINTN +EfiDevicePathInstanceCount ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +EFI_STATUS +CreateMenuStringToken ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN BM_MENU_OPTION *MenuOption + ); + +UINT16 * +EfiLibStrFromDatahub ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +VOID * +GetLegacyBootOptionVar ( + IN UINTN DeviceType, + OUT UINTN *OptionIndex, + OUT UINTN *OptionSize + ); + +EFI_STATUS +InitializeBM ( + VOID + ); + +EFI_STATUS +BdsStartBootMaint ( + VOID + ); + +VOID +InitializeStringDepository (); + +STRING_REF +GetStringTokenFromDepository ( + IN BMM_CALLBACK_DATA *CallbackData, + IN STRING_DEPOSITORY *StringDepository + ) ; + +VOID +ReclaimStringDepository ( + VOID + ); + +VOID +CleanUpStringDepository ( + VOID + ); + +EFI_STATUS +ApplyChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap, + IN FORM_ID FormId + ); + +VOID +DiscardChangeHandler ( + IN BMM_CALLBACK_DATA *Private, + IN BMM_FAKE_NV_DATA *CurrentFakeNVMap + ); + +VOID +UpdatePageId ( + BMM_CALLBACK_DATA *Private, + UINT16 NewPageId + ); + +EFI_STATUS +BootThisFile ( + IN BM_FILE_CONTEXT *FileContext + ); + +BOOLEAN +UpdateFileExplorer ( + IN BMM_CALLBACK_DATA *CallbackData, + IN UINT16 KeyValue + ); + +EFI_STATUS +EFIAPI +FileExplorerCallback ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *Data, + OUT EFI_HII_CALLBACK_PACKET **Packet + ); + +EFI_STATUS +FormSetDispatcher ( + IN BMM_CALLBACK_DATA *CallbackData + ); + +VOID CreateCallbackPacket ( + OUT EFI_HII_CALLBACK_PACKET **Packet, + IN UINT16 Flags + ); + +// +// Global variable in this program (defined in data.c) +// +extern BM_MENU_OPTION BootOptionMenu; +extern BM_MENU_OPTION DriverOptionMenu; +extern BM_MENU_OPTION FsOptionMenu; +extern BM_MENU_OPTION ConsoleInpMenu; +extern BM_MENU_OPTION ConsoleOutMenu; +extern BM_MENU_OPTION ConsoleErrMenu; +extern BM_MENU_OPTION DirectoryMenu; +extern BM_MENU_OPTION DriverMenu; +extern BM_MENU_OPTION TerminalMenu; +extern BM_MENU_OPTION LegacyFDMenu; +extern BM_MENU_OPTION LegacyHDMenu; +extern BM_MENU_OPTION LegacyCDMenu; +extern BM_MENU_OPTION LegacyNETMenu; +extern BM_MENU_OPTION LegacyBEVMenu; +extern UINT16 TerminalType[]; +extern COM_ATTR BaudRateList[19]; +extern COM_ATTR DataBitsList[4]; +extern COM_ATTR ParityList[5]; +extern COM_ATTR StopBitsList[3]; +extern EFI_GUID Guid[4]; +extern EFI_HII_UPDATE_DATA *UpdateData; +extern STRING_DEPOSITORY *FileOptionStrDepository; +extern STRING_DEPOSITORY *ConsoleOptionStrDepository; +extern STRING_DEPOSITORY *BootOptionStrDepository; +extern STRING_DEPOSITORY *BootOptionHelpStrDepository; +extern STRING_DEPOSITORY *DriverOptionStrDepository; +extern STRING_DEPOSITORY *DriverOptionHelpStrDepository; +extern STRING_DEPOSITORY *TerminalStrDepository; +extern EFI_DEVICE_PATH_PROTOCOL EndDevicePath[]; +extern EFI_GUID EfiLegacyDevOrderGuid; + +#endif diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BootOption.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BootOption.c new file mode 100644 index 0000000000..35187bf58f --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/BootOption.c @@ -0,0 +1,1657 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + bootoption.c + +Abstract: + + Provide boot option support for Application "BootMaint" + + Include file system navigation, system handle selection + + Boot option manipulation + +Revision History + +--*/ + +#include "bootmaint.h" +#include "BBSsupport.h" + +BM_MENU_ENTRY * +BOpt_CreateMenuEntry ( + UINTN MenuType + ) +/*++ + +Routine Description + Create Menu Entry for future use, make all types together + in order to reduce code size + +Arguments: + MenuType Use this parameter to identify current + Menu type + +Returns: + NULL Cannot allocate memory for current menu + entry + Others A valid pointer pointing to the allocated + memory pool for current menu entry + +--*/ +{ + BM_MENU_ENTRY *MenuEntry; + UINTN ContextSize; + + switch (MenuType) { + case BM_LOAD_CONTEXT_SELECT: + ContextSize = sizeof (BM_LOAD_CONTEXT); + break; + + case BM_FILE_CONTEXT_SELECT: + ContextSize = sizeof (BM_FILE_CONTEXT); + break; + + case BM_CONSOLE_CONTEXT_SELECT: + ContextSize = sizeof (BM_CONSOLE_CONTEXT); + break; + + case BM_TERMINAL_CONTEXT_SELECT: + ContextSize = sizeof (BM_TERMINAL_CONTEXT); + break; + + case BM_HANDLE_CONTEXT_SELECT: + ContextSize = sizeof (BM_HANDLE_CONTEXT); + break; + + case BM_LEGACY_DEV_CONTEXT_SELECT: + ContextSize = sizeof (BM_LEGACY_DEVICE_CONTEXT); + break; + + default: + ContextSize = 0; + break; + + } + + if (0 == ContextSize) { + return NULL; + } + + MenuEntry = AllocateZeroPool (sizeof (BM_MENU_ENTRY)); + if (NULL == MenuEntry) { + return MenuEntry; + } + + MenuEntry->VariableContext = AllocateZeroPool (ContextSize); + if (NULL == MenuEntry->VariableContext) { + SafeFreePool (MenuEntry); + MenuEntry = NULL; + return MenuEntry; + } + + MenuEntry->Signature = BM_MENU_ENTRY_SIGNATURE; + MenuEntry->ContextSelection = MenuType; + return MenuEntry; +} + +VOID +BOpt_DestroyMenuEntry ( + BM_MENU_ENTRY *MenuEntry + ) +/*++ + Routine Description : + Destroy the menu entry passed in + + Arguments : + The menu entry need to be destroyed + + Returns : + None + +--*/ +{ + BM_LOAD_CONTEXT *LoadContext; + BM_FILE_CONTEXT *FileContext; + BM_CONSOLE_CONTEXT *ConsoleContext; + BM_TERMINAL_CONTEXT *TerminalContext; + BM_HANDLE_CONTEXT *HandleContext; + BM_LEGACY_DEVICE_CONTEXT *LegacyDevContext; + + // + // Select by the type in Menu entry for current context type + // + switch (MenuEntry->ContextSelection) { + case BM_LOAD_CONTEXT_SELECT: + LoadContext = (BM_LOAD_CONTEXT *) MenuEntry->VariableContext; + SafeFreePool (LoadContext->FilePathList); + SafeFreePool (LoadContext->LoadOption); + SafeFreePool (LoadContext->OptionalData); + SafeFreePool (LoadContext); + break; + + case BM_FILE_CONTEXT_SELECT: + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + if (!FileContext->IsRoot) { + SafeFreePool (FileContext->DevicePath); + } else { + if (FileContext->FHandle != NULL) { + FileContext->FHandle->Close (FileContext->FHandle); + } + } + + SafeFreePool (FileContext->FileName); + SafeFreePool (FileContext->Info); + SafeFreePool (FileContext); + break; + + case BM_CONSOLE_CONTEXT_SELECT: + ConsoleContext = (BM_CONSOLE_CONTEXT *) MenuEntry->VariableContext; + SafeFreePool (ConsoleContext->DevicePath); + SafeFreePool (ConsoleContext); + break; + + case BM_TERMINAL_CONTEXT_SELECT: + TerminalContext = (BM_TERMINAL_CONTEXT *) MenuEntry->VariableContext; + SafeFreePool (TerminalContext->DevicePath); + SafeFreePool (TerminalContext); + break; + + case BM_HANDLE_CONTEXT_SELECT: + HandleContext = (BM_HANDLE_CONTEXT *) MenuEntry->VariableContext; + SafeFreePool (HandleContext); + break; + + case BM_LEGACY_DEV_CONTEXT_SELECT: + LegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) MenuEntry->VariableContext; + SafeFreePool (LegacyDevContext); + + default: + break; + } + + SafeFreePool (MenuEntry->DisplayString); + if (NULL != MenuEntry->HelpString) { + SafeFreePool (MenuEntry->HelpString); + } + + SafeFreePool (MenuEntry); +} + +BM_MENU_ENTRY * +BOpt_GetMenuEntry ( + BM_MENU_OPTION *MenuOption, + UINTN MenuNumber + ) +/*++ + Rountine Description : + Use this routine to get one particular menu entry in specified + menu + + Arguments : + MenuOption The menu that we will search + + MenuNumber The menunubmer that we want + + Returns : + The desired menu entry + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + UINTN Index; + LIST_ENTRY *List; + + if (MenuNumber >= MenuOption->MenuNumber) { + return NULL; + } + + List = MenuOption->Head.ForwardLink; + for (Index = 0; Index < MenuNumber; Index++) { + List = List->ForwardLink; + } + + NewMenuEntry = CR (List, BM_MENU_ENTRY, Link, BM_MENU_ENTRY_SIGNATURE); + + return NewMenuEntry; +} + +EFI_STATUS +BOpt_FindFileSystem ( + IN BMM_CALLBACK_DATA *CallbackData + ) +/*++ + +Routine Description + Find file systems for current Extensible Firmware + Including Handles that support Simple File System + protocol, Load File protocol. + + Building up the FileSystem Menu for user selection + All file system will be stored in FsOptionMenu + for future use. + +Arguments: + CallbackData - BMM context data + +Returns: + EFI_SUCCESS - Success find the file system + EFI_OUT_OF_RESOURCES - Can not create menu entry + +--*/ +{ + UINTN NoSimpleFsHandles; + UINTN NoLoadFileHandles; + EFI_HANDLE *SimpleFsHandle; + EFI_HANDLE *LoadFileHandle; + UINT16 *VolumeLabel; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + UINTN Index; + EFI_STATUS Status; + BM_MENU_ENTRY *MenuEntry; + BM_FILE_CONTEXT *FileContext; + UINT16 *TempStr; + UINTN OptionNumber; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT16 DeviceType; + BBS_BBS_DEVICE_PATH BbsDevicePathNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BOOLEAN RemovableMedia; + + + NoSimpleFsHandles = 0; + NoLoadFileHandles = 0; + OptionNumber = 0; + InitializeListHead (&FsOptionMenu.Head); + + // + // Locate Handles that support Simple File System protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NoSimpleFsHandles, + &SimpleFsHandle + ); + if (!EFI_ERROR (Status)) { + // + // Find all the instances of the File System prototocol + // + for (Index = 0; Index < NoSimpleFsHandles; Index++) { + Status = gBS->HandleProtocol ( + SimpleFsHandle[Index], + &gEfiBlockIoProtocolGuid, + &BlkIo + ); + if (EFI_ERROR (Status)) { + // + // If no block IO exists assume it's NOT a removable media + // + RemovableMedia = FALSE; + } else { + // + // If block IO exists check to see if it's remobable media + // + RemovableMedia = BlkIo->Media->RemovableMedia; + } + + // + // Allocate pool for this load option + // + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + SafeFreePool (SimpleFsHandle); + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + FileContext->Handle = SimpleFsHandle[Index]; + MenuEntry->OptionNumber = Index; + FileContext->FHandle = EfiLibOpenRoot (FileContext->Handle); + if (!FileContext->FHandle) { + BOpt_DestroyMenuEntry (MenuEntry); + continue; + } + + MenuEntry->HelpString = DevicePathToStr (DevicePathFromHandle (FileContext->Handle)); + FileContext->Info = EfiLibFileSystemVolumeLabelInfo (FileContext->FHandle); + FileContext->FileName = EfiStrDuplicate (L"\\"); + FileContext->DevicePath = FileDevicePath ( + FileContext->Handle, + FileContext->FileName + ); + FileContext->IsDir = TRUE; + FileContext->IsRoot = TRUE; + FileContext->IsRemovableMedia = FALSE; + FileContext->IsLoadFile = FALSE; + + // + // Get current file system's Volume Label + // + if (FileContext->Info == NULL) { + VolumeLabel = L"NO FILE SYSTEM INFO"; + } else { + if (FileContext->Info->VolumeLabel == NULL) { + VolumeLabel = L"NULL VOLUME LABEL"; + } else { + VolumeLabel = FileContext->Info->VolumeLabel; + if (*VolumeLabel == 0x0000) { + VolumeLabel = L"NO VOLUME LABEL"; + } + } + } + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"%s, [%s]", + VolumeLabel, + TempStr + ); + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + + if (NoSimpleFsHandles != 0) { + SafeFreePool (SimpleFsHandle); + } + // + // Searching for handles that support Load File protocol + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiLoadFileProtocolGuid, + NULL, + &NoLoadFileHandles, + &LoadFileHandle + ); + + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < NoLoadFileHandles; Index++) { + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + SafeFreePool (LoadFileHandle); + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + FileContext->IsRemovableMedia = FALSE; + FileContext->IsLoadFile = TRUE; + FileContext->Handle = LoadFileHandle[Index]; + FileContext->IsRoot = TRUE; + + FileContext->DevicePath = DevicePathFromHandle (FileContext->Handle); + + MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath); + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"Load File [%s]", + TempStr + ); + + MenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + + if (NoLoadFileHandles != 0) { + SafeFreePool (LoadFileHandle); + } + + // + // Add Legacy Boot Option Support Here + // + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + &LegacyBios + ); + if (!EFI_ERROR (Status)) { + + for (Index = BBS_TYPE_FLOPPY; Index <= BBS_TYPE_EMBEDDED_NETWORK; Index++) { + MenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == MenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + + FileContext->IsRemovableMedia = FALSE; + FileContext->IsLoadFile = TRUE; + FileContext->IsBootLegacy = TRUE; + DeviceType = (UINT16) Index; + BbsDevicePathNode.Header.Type = BBS_DEVICE_PATH; + BbsDevicePathNode.Header.SubType = BBS_BBS_DP; + SetDevicePathNodeLength ( + &BbsDevicePathNode.Header, + sizeof (BBS_BBS_DEVICE_PATH) + ); + BbsDevicePathNode.DeviceType = DeviceType; + BbsDevicePathNode.StatusFlag = 0; + BbsDevicePathNode.String[0] = 0; + DevicePath = AppendDevicePathNode ( + EndDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &BbsDevicePathNode + ); + + FileContext->DevicePath = DevicePath; + MenuEntry->HelpString = DevicePathToStr (FileContext->DevicePath); + + TempStr = MenuEntry->HelpString; + MenuEntry->DisplayString = AllocateZeroPool (MAX_CHAR); + ASSERT (MenuEntry->DisplayString != NULL); + UnicodeSPrint ( + MenuEntry->DisplayString, + MAX_CHAR, + L"Boot Legacy [%s]", + TempStr + ); + MenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&FsOptionMenu.Head, &MenuEntry->Link); + } + } + // + // Remember how many file system options are here + // + FsOptionMenu.MenuNumber = OptionNumber; + return EFI_SUCCESS; +} + +VOID +BOpt_FreeMenu ( + BM_MENU_OPTION *FreeMenu + ) +/*++ + +Routine Description + Free resources allocated in Allocate Rountine + +Arguments: + FreeMenu Menu to be freed + +Returns: + VOID + +--*/ +{ + BM_MENU_ENTRY *MenuEntry; + while (!IsListEmpty (&FreeMenu->Head)) { + MenuEntry = CR ( + FreeMenu->Head.ForwardLink, + BM_MENU_ENTRY, + Link, + BM_MENU_ENTRY_SIGNATURE + ); + RemoveEntryList (&MenuEntry->Link); + BOpt_DestroyMenuEntry (MenuEntry); + } +} + +EFI_STATUS +BOpt_FindFiles ( + IN BMM_CALLBACK_DATA *CallbackData, + IN BM_MENU_ENTRY *MenuEntry + ) +/*++ + +Routine Description + Find files under current directory + All files and sub-directories in current directory + will be stored in DirectoryMenu for future use. + +Arguments: + FileOption -- Pointer for Dir to explore + +Returns: + TRUE -- Get files from current dir successfully + FALSE -- Can't get files from current dir + +--*/ +{ + EFI_FILE_HANDLE NewDir; + EFI_FILE_HANDLE Dir; + EFI_FILE_INFO *DirInfo; + UINTN BufferSize; + UINTN DirBufferSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *FileContext; + BM_FILE_CONTEXT *NewFileContext; + UINTN Pass; + EFI_STATUS Status; + UINTN OptionNumber; + + FileContext = (BM_FILE_CONTEXT *) MenuEntry->VariableContext; + Dir = FileContext->FHandle; + OptionNumber = 0; + // + // Open current directory to get files from it + // + Status = Dir->Open ( + Dir, + &NewDir, + FileContext->FileName, + EFI_FILE_READ_ONLY, + 0 + ); + if (!FileContext->IsRoot) { + Dir->Close (Dir); + } + + if (EFI_ERROR (Status)) { + return Status; + } + + DirInfo = EfiLibFileInfo (NewDir); + if (!DirInfo) { + return EFI_NOT_FOUND; + } + + if (!(DirInfo->Attribute & EFI_FILE_DIRECTORY)) { + return EFI_INVALID_PARAMETER; + } + + FileContext->DevicePath = FileDevicePath ( + FileContext->Handle, + FileContext->FileName + ); + + DirBufferSize = sizeof (EFI_FILE_INFO) + 1024; + DirInfo = AllocateZeroPool (DirBufferSize); + if (!DirInfo) { + return EFI_OUT_OF_RESOURCES; + } + // + // Get all files in current directory + // Pass 1 to get Directories + // Pass 2 to get files that are EFI images + // + for (Pass = 1; Pass <= 2; Pass++) { + NewDir->SetPosition (NewDir, 0); + for (;;) { + BufferSize = DirBufferSize; + Status = NewDir->Read (NewDir, &BufferSize, DirInfo); + if (EFI_ERROR (Status) || BufferSize == 0) { + break; + } + + if ((DirInfo->Attribute & EFI_FILE_DIRECTORY && Pass == 2) || + (!(DirInfo->Attribute & EFI_FILE_DIRECTORY) && Pass == 1) + ) { + // + // Pass 1 is for Directories + // Pass 2 is for file names + // + continue; + } + + if (!(BOpt_IsEfiImageName (DirInfo->FileName) || DirInfo->Attribute & EFI_FILE_DIRECTORY)) { + // + // Slip file unless it is a directory entry or a .EFI file + // + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_FILE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + NewFileContext->Handle = FileContext->Handle; + NewFileContext->FileName = BOpt_AppendFileName ( + FileContext->FileName, + DirInfo->FileName + ); + NewFileContext->FHandle = NewDir; + NewFileContext->DevicePath = FileDevicePath ( + NewFileContext->Handle, + NewFileContext->FileName + ); + NewMenuEntry->HelpString = NULL; + + MenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + FileOptionStrDepository + ); + + NewFileContext->IsDir = (BOOLEAN) ((DirInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY); + + if (NewFileContext->IsDir) { + BufferSize = StrLen (DirInfo->FileName) * 2 + 6; + NewMenuEntry->DisplayString = AllocateZeroPool (BufferSize); + + UnicodeSPrint ( + NewMenuEntry->DisplayString, + BufferSize, + L"<%s>", + DirInfo->FileName + ); + + } else { + NewMenuEntry->DisplayString = EfiStrDuplicate (DirInfo->FileName); + } + + NewFileContext->IsRoot = FALSE; + NewFileContext->IsLoadFile = FALSE; + NewFileContext->IsRemovableMedia = FALSE; + + NewMenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&DirectoryMenu.Head, &NewMenuEntry->Link); + } + } + + DirectoryMenu.MenuNumber = OptionNumber; + SafeFreePool (DirInfo); + return TRUE; +} + +EFI_STATUS +BOpt_GetLegacyOptions ( + VOID + ) +/*++ +Routine Description: + + Build the LegacyFDMenu LegacyHDMenu LegacyCDMenu according to LegacyBios.GetBbsInfo(). + +Arguments: + None + +Returns: + The device info of legacy device. + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LEGACY_DEVICE_CONTEXT *NewLegacyDevContext; + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + UINT16 HddCount; + HDD_INFO *HddInfo; + UINT16 BbsCount; + BBS_TABLE *BbsTable; + UINTN Index; + CHAR16 DescString[100]; + UINTN FDNum; + UINTN HDNum; + UINTN CDNum; + UINTN NETNum; + UINTN BEVNum; + + NewMenuEntry = NULL; + HddInfo = NULL; + BbsTable = NULL; + BbsCount = 0; + + // + // Initialize Bbs Table Context from BBS info data + // + InitializeListHead (&LegacyFDMenu.Head); + InitializeListHead (&LegacyHDMenu.Head); + InitializeListHead (&LegacyCDMenu.Head); + InitializeListHead (&LegacyNETMenu.Head); + InitializeListHead (&LegacyBEVMenu.Head); + + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + &LegacyBios + ); + if (!EFI_ERROR (Status)) { + Status = LegacyBios->GetBbsInfo ( + LegacyBios, + &HddCount, + &HddInfo, + &BbsCount, + &BbsTable + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + FDNum = 0; + HDNum = 0; + CDNum = 0; + NETNum = 0; + BEVNum = 0; + + for (Index = 0; Index < BbsCount; Index++) { + if ((BBS_IGNORE_ENTRY == BbsTable[Index].BootPriority) || + (BBS_DO_NOT_BOOT_FROM == BbsTable[Index].BootPriority) || + (BBS_LOWEST_PRIORITY == BbsTable[Index].BootPriority) + ) { + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LEGACY_DEV_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + break; + } + + NewLegacyDevContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext; + NewLegacyDevContext->BbsTable = &BbsTable[Index]; + NewLegacyDevContext->Index = Index; + NewLegacyDevContext->BbsCount = BbsCount; + BdsBuildLegacyDevNameString ( + &BbsTable[Index], + Index, + sizeof (DescString), + DescString + ); + NewLegacyDevContext->Description = AllocateZeroPool (StrSize (DescString)); + if (NULL == NewLegacyDevContext->Description) { + break; + } + + CopyMem (NewLegacyDevContext->Description, DescString, StrSize (DescString)); + NewMenuEntry->DisplayString = NewLegacyDevContext->Description; + NewMenuEntry->HelpString = NULL; + + switch (BbsTable[Index].DeviceType) { + case BBS_FLOPPY: + InsertTailList (&LegacyFDMenu.Head, &NewMenuEntry->Link); + FDNum++; + break; + + case BBS_HARDDISK: + InsertTailList (&LegacyHDMenu.Head, &NewMenuEntry->Link); + HDNum++; + break; + + case BBS_CDROM: + InsertTailList (&LegacyCDMenu.Head, &NewMenuEntry->Link); + CDNum++; + break; + + case BBS_EMBED_NETWORK: + InsertTailList (&LegacyNETMenu.Head, &NewMenuEntry->Link); + NETNum++; + break; + + case BBS_BEV_DEVICE: + InsertTailList (&LegacyBEVMenu.Head, &NewMenuEntry->Link); + BEVNum++; + break; + } + } + + if (Index != BbsCount) { + BOpt_FreeLegacyOptions (); + return EFI_OUT_OF_RESOURCES; + } + + LegacyFDMenu.MenuNumber = FDNum; + LegacyHDMenu.MenuNumber = HDNum; + LegacyCDMenu.MenuNumber = CDNum; + LegacyNETMenu.MenuNumber = NETNum; + LegacyBEVMenu.MenuNumber = BEVNum; + return EFI_SUCCESS; +} + +VOID +BOpt_FreeLegacyOptions ( + VOID + ) +{ + BOpt_FreeMenu (&LegacyFDMenu); + BOpt_FreeMenu (&LegacyHDMenu); + BOpt_FreeMenu (&LegacyCDMenu); + BOpt_FreeMenu (&LegacyNETMenu); + BOpt_FreeMenu (&LegacyBEVMenu); +} + +EFI_STATUS +BOpt_GetBootOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ) +/*++ + +Routine Description: + + Build the BootOptionMenu according to BootOrder Variable. + This Routine will access the Boot#### to get EFI_LOAD_OPTION + +Arguments: + None + +Returns: + The number of the Var Boot#### + +--*/ +{ + UINTN Index; + UINT16 BootString[10]; + UINT8 *LoadOptionFromVar; + UINT8 *LoadOption; + UINTN BootOptionSize; + BOOLEAN BootNextFlag; + UINT16 *BootOrderList; + UINTN BootOrderListSize; + UINT16 *BootNext; + UINTN BootNextSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT8 *LoadOptionPtr; + UINTN StringSize; + UINTN OptionalDataSize; + UINT8 *LoadOptionEnd; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN MenuCount; + UINT8 *Ptr; + + MenuCount = 0; + BootOrderListSize = 0; + BootNextSize = 0; + BootOrderList = NULL; + BootNext = NULL; + LoadOptionFromVar = NULL; + BOpt_FreeMenu (&BootOptionMenu); + InitializeListHead (&BootOptionMenu.Head); + + // + // Get the BootOrder from the Var + // + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + + // + // Get the BootNext from the Var + // + BootNext = BdsLibGetVariableAndSize ( + L"BootNext", + &gEfiGlobalVariableGuid, + &BootNextSize + ); + + if (BootNext) { + if (BootNextSize != sizeof (UINT16)) { + SafeFreePool (BootNext); + BootNext = NULL; + } + } + + for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) { + UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", BootOrderList[Index]); + // + // Get all loadoptions from the VAR + // + LoadOptionFromVar = BdsLibGetVariableAndSize ( + BootString, + &gEfiGlobalVariableGuid, + &BootOptionSize + ); + if (!LoadOptionFromVar) { + continue; + } + + LoadOption = AllocateZeroPool (BootOptionSize); + if (!LoadOption) { + continue; + } + + CopyMem (LoadOption, LoadOptionFromVar, BootOptionSize); + SafeFreePool (LoadOptionFromVar); + + if (BootNext) { + BootNextFlag = (BOOLEAN) (*BootNext == BootOrderList[Index]); + } else { + BootNextFlag = FALSE; + } + + if (0 == (*((UINT32 *) LoadOption) & LOAD_OPTION_ACTIVE)) { + SafeFreePool (LoadOption); + continue; + } + // + // BUGBUG: could not return EFI_OUT_OF_RESOURCES here directly. + // the buffer allocated already should be freed before returning. + // + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + + LoadOptionPtr = LoadOption; + LoadOptionEnd = LoadOption + BootOptionSize; + + NewMenuEntry->OptionNumber = BootOrderList[Index]; + NewLoadContext->LoadOptionModified = FALSE; + NewLoadContext->Deleted = FALSE; + NewLoadContext->IsBootNext = BootNextFlag; + + // + // Is a Legacy Device? + // + Ptr = (UINT8 *) LoadOption; + + // + // Attribute = *(UINT32 *)Ptr; + // + Ptr += sizeof (UINT32); + + // + // FilePathSize = *(UINT16 *)Ptr; + // + Ptr += sizeof (UINT16); + + // + // Description = (CHAR16 *)Ptr; + // + Ptr += StrSize ((CHAR16 *) Ptr); + + // + // Now Ptr point to Device Path + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + if ((BBS_DEVICE_PATH == DevicePath->Type) && (BBS_BBS_DP == DevicePath->SubType)) { + NewLoadContext->IsLegacy = TRUE; + } else { + NewLoadContext->IsLegacy = FALSE; + } + // + // LoadOption is a pointer type of UINT8 + // for easy use with following LOAD_OPTION + // embedded in this struct + // + NewLoadContext->LoadOption = LoadOption; + NewLoadContext->LoadOptionSize = BootOptionSize; + + NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; + NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE); + + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + LoadOptionPtr += sizeof (UINT32); + + NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; + LoadOptionPtr += sizeof (UINT16); + + StringSize = StrSize ((UINT16 *) LoadOptionPtr); + NewLoadContext->Description = AllocateZeroPool (StringSize); + ASSERT (NewLoadContext->Description != NULL); + CopyMem ( + NewLoadContext->Description, + (UINT16 *) LoadOptionPtr, + StringSize + ); + NewMenuEntry->DisplayString = NewLoadContext->Description; + + LoadOptionPtr += StringSize; + + NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); + ASSERT (NewLoadContext->FilePathList != NULL); + CopyMem ( + NewLoadContext->FilePathList, + (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, + NewLoadContext->FilePathListLength + ); + + NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionStrDepository + ); + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionHelpStrDepository + ); + LoadOptionPtr += NewLoadContext->FilePathListLength; + + if (LoadOptionPtr < LoadOptionEnd) { + OptionalDataSize = BootOptionSize - + sizeof (UINT32) - + sizeof (UINT16) - + StringSize - + NewLoadContext->FilePathListLength; + + NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); + ASSERT (NewLoadContext->OptionalData != NULL); + CopyMem ( + NewLoadContext->OptionalData, + LoadOptionPtr, + OptionalDataSize + ); + + NewLoadContext->OptionalDataSize = OptionalDataSize; + } + + InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); + MenuCount++; + } + + SafeFreePool (BootNext); + SafeFreePool (BootOrderList); + BootOptionMenu.MenuNumber = MenuCount; + return MenuCount; +} + +CHAR16 * +BOpt_AppendFileName ( + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ) +/*++ + +Routine Description + Append file name to existing file name. + +Arguments: + Str1 - existing file name + Str2 - file name to be appended + +Returns: + Allocate a new string to hold the appended result. + Caller is responsible to free the returned string. + +--*/ +{ + UINTN Size1; + UINTN Size2; + CHAR16 *Str; + CHAR16 *Ptr; + CHAR16 *LastSlash; + + Size1 = StrSize (Str1); + Size2 = StrSize (Str2); + Str = AllocateZeroPool (Size1 + Size2 + sizeof (CHAR16)); + ASSERT (Str != NULL); + + StrCat (Str, Str1); + if (!((*Str == '\\') && (*(Str + 1) == 0))) { + StrCat (Str, L"\\"); + } + + StrCat (Str, Str2); + + Ptr = Str; + LastSlash = Str; + while (*Ptr != 0) { + if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '.' && *(Ptr + 3) != 0) { + // + // Convert \Name\..\ to \ + // DO NOT convert the .. if it is at the end of the string. This will + // break the .. behavior in changing directories. + // + StrCpy (LastSlash, Ptr + 3); + Ptr = LastSlash; + } else if (*Ptr == '\\' && *(Ptr + 1) == '.' && *(Ptr + 2) == '\\') { + // + // Convert a \.\ to a \ + // + StrCpy (Ptr, Ptr + 2); + Ptr = LastSlash; + } else if (*Ptr == '\\') { + LastSlash = Ptr; + } + + Ptr++; + } + + return Str; +} + +BOOLEAN +BOpt_IsEfiImageName ( + IN UINT16 *FileName + ) +/*++ + +Routine Description + Check whether current FileName point to a valid + Efi Image File. + +Arguments: + FileName - File need to be checked. + +Returns: + TRUE - Is Efi Image + FALSE - Not a valid Efi Image + +--*/ +{ + // + // Search for ".efi" extension + // + while (*FileName) { + if (FileName[0] == '.') { + if (FileName[1] == 'e' || FileName[1] == 'E') { + if (FileName[2] == 'f' || FileName[2] == 'F') { + if (FileName[3] == 'i' || FileName[3] == 'I') { + return TRUE; + } else if (FileName[3] == 0x0000) { + return FALSE; + } + } else if (FileName[2] == 0x0000) { + return FALSE; + } + } else if (FileName[1] == 0x0000) { + return FALSE; + } + } + + FileName += 1; + } + + return FALSE; +} + +BOOLEAN +BOpt_IsEfiApp ( + IN EFI_FILE_HANDLE Dir, + IN UINT16 *FileName + ) +/*++ + +Routine Description: + Check whether current FileName point to a valid Efi Application + +Arguments: + Dir - Pointer to current Directory + FileName - Pointer to current File name. + +Returns: + TRUE - Is a valid Efi Application + FALSE - not a valid Efi Application + +--*/ +{ + UINTN BufferSize; + EFI_IMAGE_DOS_HEADER DosHdr; + EFI_IMAGE_NT_HEADERS PeHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *PeOpt32; + EFI_IMAGE_OPTIONAL_HEADER64 *PeOpt64; + UINT16 Subsystem; + EFI_FILE_HANDLE File; + EFI_STATUS Status; + + Status = Dir->Open (Dir, &File, FileName, EFI_FILE_MODE_READ, 0); + + if (EFI_ERROR (Status)) { + return FALSE; + } + + BufferSize = sizeof (EFI_IMAGE_DOS_HEADER); + File->Read (File, &BufferSize, &DosHdr); + if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) { + File->Close (File); + return FALSE; + } + + File->SetPosition (File, DosHdr.e_lfanew); + BufferSize = sizeof (EFI_IMAGE_NT_HEADERS); + File->Read (File, &BufferSize, &PeHdr); + if (PeHdr.Signature != EFI_IMAGE_NT_SIGNATURE) { + File->Close (File); + return FALSE; + } + // + // Determine PE type and read subsytem + // BugBug : We should be using EFI_IMAGE_MACHINE_TYPE_SUPPORTED (machine) + // macro to detect the machine type. + // We should not be using EFI_IMAGE_OPTIONAL_HEADER32 and + // EFI_IMAGE_OPTIONAL_HEADER64 + // + if (PeHdr.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + PeOpt32 = (EFI_IMAGE_OPTIONAL_HEADER32 *) &(PeHdr.OptionalHeader); + Subsystem = PeOpt32->Subsystem; + } else if (PeHdr.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + PeOpt64 = (EFI_IMAGE_OPTIONAL_HEADER64 *) &(PeHdr.OptionalHeader); + Subsystem = PeOpt64->Subsystem; + } else { + return FALSE; + } + + if (Subsystem == EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION) { + File->Close (File); + return TRUE; + } else { + File->Close (File); + return FALSE; + } +} + +EFI_STATUS +BOpt_FindDrivers ( + VOID + ) +/*++ + +Routine Description + Find drivers that will be added as Driver#### variables from handles + in current system environment + All valid handles in the system except those consume SimpleFs, LoadFile + are stored in DriverMenu for future use. + +Arguments: + None + +Returns: + EFI_SUCCESS + Others + +--*/ +{ + UINTN NoDevicePathHandles; + EFI_HANDLE *DevicePathHandle; + UINTN Index; + EFI_STATUS Status; + BM_MENU_ENTRY *NewMenuEntry; + BM_HANDLE_CONTEXT *NewHandleContext; + EFI_HANDLE CurHandle; + UINTN OptionNumber; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFs; + EFI_LOAD_FILE_PROTOCOL *LoadFile; + + SimpleFs = NULL; + LoadFile = NULL; + + InitializeListHead (&DriverMenu.Head); + + // + // At first, get all handles that support Device Path + // protocol which is the basic requirement for + // Driver#### + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiDevicePathProtocolGuid, + NULL, + &NoDevicePathHandles, + &DevicePathHandle + ); + if (EFI_ERROR (Status)) { + return Status; + } + + OptionNumber = 0; + for (Index = 0; Index < NoDevicePathHandles; Index++) { + CurHandle = DevicePathHandle[Index]; + + // + // Check whether this handle support + // driver binding + // + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiSimpleFileSystemProtocolGuid, + &SimpleFs + ); + if (Status == EFI_SUCCESS) { + continue; + } + + Status = gBS->HandleProtocol ( + CurHandle, + &gEfiLoadFileProtocolGuid, + &LoadFile + ); + if (Status == EFI_SUCCESS) { + continue; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_HANDLE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewHandleContext = (BM_HANDLE_CONTEXT *) NewMenuEntry->VariableContext; + NewHandleContext->Handle = CurHandle; + NewHandleContext->DevicePath = DevicePathFromHandle (CurHandle); + NewMenuEntry->DisplayString = DevicePathToStr (NewHandleContext->DevicePath); + NewMenuEntry->HelpString = NULL; + NewMenuEntry->OptionNumber = OptionNumber; + OptionNumber++; + InsertTailList (&DriverMenu.Head, &NewMenuEntry->Link); + + } + + DriverMenu.MenuNumber = OptionNumber; + return EFI_SUCCESS; +} + +UINT16 +BOpt_GetBootOptionNumber ( + VOID + ) +/*++ + +Routine Description: + Get the Option Number that does not used + +Arguments: + +Returns: + The Option Number + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 *BootOrderList; + UINTN BootOrderListSize; + UINT16 Number; + UINTN Index; + UINTN Index2; + BOOLEAN Found; + + BootOrderListSize = 0; + BootOrderList = NULL; + + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + if (BootOrderList) { + // + // already have Boot#### + // + // AlreadyBootNumbers = BootOrderListSize / sizeof(UINT16); + // + for (Index = 0; Index < BootOrderListSize / sizeof (UINT16); Index++) { + Found = TRUE; + for (Index2 = 0; Index2 < BootOptionMenu.MenuNumber; Index2++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index2); + if (Index == NewMenuEntry->OptionNumber) { + Found = FALSE; + break; + } + } + + if (Found) { + break; + } + } + // + // end for Index + // + Number = (UINT16) Index; + } else { + // + // No Boot#### + // + Number = 0; + } + + return Number; +} + +UINT16 +BOpt_GetDriverOptionNumber ( + VOID + ) +/*++ + +Routine Description: + Get the Option Number that does not used + +Arguments: + +Returns: + The Option Number + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 *DriverOrderList; + UINTN DriverOrderListSize; + UINT16 Number; + UINTN Index; + UINTN Index2; + BOOLEAN Found; + + DriverOrderListSize = 0; + DriverOrderList = NULL; + + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + if (DriverOrderList) { + // + // already have Driver#### + // + // AlreadyDriverNumbers = DriverOrderListSize / sizeof(UINT16); + // + for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) { + Found = TRUE; + for (Index2 = 0; Index2 < DriverOptionMenu.MenuNumber; Index2++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index2); + if (Index == NewMenuEntry->OptionNumber) { + Found = FALSE; + break; + } + } + + if (Found) { + break; + } + } + // + // end for Index + // + Number = (UINT16) Index; + } else { + // + // No Driver#### + // + Number = 0; + } + + return Number; +} + +EFI_STATUS +BOpt_GetDriverOptions ( + IN BMM_CALLBACK_DATA *CallbackData + ) +/*++ + +Routine Description: + Build up all DriverOptionMenu + +Arguments: + +Returns: + The Option Number + +--*/ +{ + UINTN Index; + UINT16 DriverString[12]; + UINT8 *LoadOptionFromVar; + UINT8 *LoadOption; + UINTN DriverOptionSize; + + UINT16 *DriverOrderList; + UINTN DriverOrderListSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT8 *LoadOptionPtr; + UINTN StringSize; + UINTN OptionalDataSize; + UINT8 *LoadOptionEnd; + + DriverOrderListSize = 0; + DriverOrderList = NULL; + DriverOptionSize = 0; + LoadOptionFromVar = NULL; + BOpt_FreeMenu (&DriverOptionMenu); + InitializeListHead (&DriverOptionMenu.Head); + // + // Get the DriverOrder from the Var + // + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + + for (Index = 0; Index < DriverOrderListSize / sizeof (UINT16); Index++) { + UnicodeSPrint ( + DriverString, + sizeof (DriverString), + L"Driver%04x", + DriverOrderList[Index] + ); + // + // Get all loadoptions from the VAR + // + LoadOptionFromVar = BdsLibGetVariableAndSize ( + DriverString, + &gEfiGlobalVariableGuid, + &DriverOptionSize + ); + if (!LoadOptionFromVar) { + continue; + } + + LoadOption = AllocateZeroPool (DriverOptionSize); + if (!LoadOption) { + continue; + } + + CopyMem (LoadOption, LoadOptionFromVar, DriverOptionSize); + SafeFreePool (LoadOptionFromVar); + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + LoadOptionPtr = LoadOption; + LoadOptionEnd = LoadOption + DriverOptionSize; + NewMenuEntry->OptionNumber = DriverOrderList[Index]; + NewLoadContext->LoadOptionModified = FALSE; + NewLoadContext->Deleted = FALSE; + NewLoadContext->IsLegacy = FALSE; + + // + // LoadOption is a pointer type of UINT8 + // for easy use with following LOAD_OPTION + // embedded in this struct + // + NewLoadContext->LoadOption = LoadOption; + NewLoadContext->LoadOptionSize = DriverOptionSize; + + NewLoadContext->Attributes = *(UINT32 *) LoadOptionPtr; + NewLoadContext->IsActive = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_ACTIVE); + + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + LoadOptionPtr += sizeof (UINT32); + + NewLoadContext->FilePathListLength = *(UINT16 *) LoadOptionPtr; + LoadOptionPtr += sizeof (UINT16); + + StringSize = StrSize ((UINT16 *) LoadOptionPtr); + NewLoadContext->Description = AllocateZeroPool (StringSize); + ASSERT (NewLoadContext->Description != NULL); + CopyMem ( + NewLoadContext->Description, + (UINT16 *) LoadOptionPtr, + StringSize + ); + NewMenuEntry->DisplayString = NewLoadContext->Description; + + LoadOptionPtr += StringSize; + + NewLoadContext->FilePathList = AllocateZeroPool (NewLoadContext->FilePathListLength); + ASSERT (NewLoadContext->FilePathList != NULL); + CopyMem ( + NewLoadContext->FilePathList, + (EFI_DEVICE_PATH_PROTOCOL *) LoadOptionPtr, + NewLoadContext->FilePathListLength + ); + + NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionStrDepository + ); + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionHelpStrDepository + ); + LoadOptionPtr += NewLoadContext->FilePathListLength; + + if (LoadOptionPtr < LoadOptionEnd) { + OptionalDataSize = DriverOptionSize - + sizeof (UINT32) - + sizeof (UINT16) - + StringSize - + NewLoadContext->FilePathListLength; + + NewLoadContext->OptionalData = AllocateZeroPool (OptionalDataSize); + ASSERT (NewLoadContext->OptionalData != NULL); + CopyMem ( + NewLoadContext->OptionalData, + LoadOptionPtr, + OptionalDataSize + ); + + NewLoadContext->OptionalDataSize = OptionalDataSize; + } + + InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); + + } + + SafeFreePool (DriverOrderList); + DriverOptionMenu.MenuNumber = Index; + return EFI_SUCCESS; + +} + +VOID +SafeFreePool ( + IN VOID *Buffer + ) +/*++ + +Routine Description: + Wrap original FreePool gBS call + in order to decrease code length + +Arguments: + +Returns: + +--*/ +{ + if (Buffer != NULL) { + gBS->FreePool (Buffer); + Buffer = NULL; + } +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/ConsoleOption.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/ConsoleOption.c new file mode 100644 index 0000000000..9deb5fa912 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/ConsoleOption.c @@ -0,0 +1,840 @@ +/*++ +Copyright (c) 2006, 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. + +Module Name: + + consoleoption.c + +Abstract: + + handles console redirection from boot manager + + +Revision History + +--*/ + +#include "bootmaint.h" + +EFI_DEVICE_PATH_PROTOCOL * +DevicePathInstanceDup ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +EFI_STATUS +UpdateComAttributeFromVariable ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +EFI_STATUS +ChangeTerminalDevicePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath, + BOOLEAN ChangeTerminal + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *Node1; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UART_DEVICE_PATH *Uart1; + UINTN Com; + UINT32 Match; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_MENU_ENTRY *NewMenuEntry; + + Match = EISA_PNP_ID (0x0501); + Node = DevicePath; + Node = NextDevicePathNode (Node); + Com = 0; + while (!IsDevicePathEnd (Node)) { + if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) { + CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); + } + } + + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Com); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + Uart = (UART_DEVICE_PATH *) Node; + CopyMem ( + &Uart->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + // + // Change the device path in the ComPort + // + if (ChangeTerminal) { + Node1 = NewTerminalContext->DevicePath; + Node1 = NextDevicePathNode (Node1); + while (!IsDevicePathEnd (Node1)) { + if ((DevicePathType (Node1) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node1) == MSG_UART_DP)) { + Uart1 = (UART_DEVICE_PATH *) Node1; + CopyMem ( + &Uart1->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart1->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart1->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart1->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + break; + } + // + // end if + // + Node1 = NextDevicePathNode (Node1); + } + // + // end while + // + break; + } + } + + Node = NextDevicePathNode (Node); + } + + return EFI_SUCCESS; + +} + +VOID +ChangeVariableDevicePath ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UINTN Com; + UINT32 Match; + BM_TERMINAL_CONTEXT *NewTerminalContext; + BM_MENU_ENTRY *NewMenuEntry; + + Match = EISA_PNP_ID (0x0501); + Node = DevicePath; + Node = NextDevicePathNode (Node); + Com = 0; + while (!IsDevicePathEnd (Node)) { + if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) { + CopyMem (&Com, &Acpi->UID, sizeof (UINT32)); + } + } + + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + NewMenuEntry = BOpt_GetMenuEntry ( + &TerminalMenu, + Com + ); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + Uart = (UART_DEVICE_PATH *) Node; + CopyMem ( + &Uart->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &Uart->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + } + + Node = NextDevicePathNode (Node); + } + + return ; +} + +BOOLEAN +IsTerminalDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT TYPE_OF_TERMINAL *Termi, + OUT UINTN *Com + ); + +EFI_STATUS +LocateSerialIo ( + VOID + ) +/*++ + +Routine Description: + Build a list containing all serial devices + +Arguments: + +Returns: + +--*/ +{ + UINT8 *Ptr; + UINTN Index; + UINTN Index2; + UINTN NoHandles; + EFI_HANDLE *Handles; + EFI_STATUS Status; + ACPI_HID_DEVICE_PATH *Acpi; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINT32 Match; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; + EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + VENDOR_DEVICE_PATH Vendor; + // + // Get all handles that have SerialIo protocol installed + // + InitializeListHead (&TerminalMenu.Head); + TerminalMenu.MenuNumber = 0; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSerialIoProtocolGuid, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + // + // No serial ports present + // + return EFI_UNSUPPORTED; + } + + for (Index = 0; Index < NoHandles; Index++) { + // + // Check to see whether the handle has DevicePath Protocol installed + // + gBS->HandleProtocol ( + Handles[Index], + &gEfiDevicePathProtocolGuid, + &DevicePath + ); + Ptr = (UINT8 *) DevicePath; + while (*Ptr != END_DEVICE_PATH_TYPE) { + Ptr++; + } + + Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH); + Acpi = (ACPI_HID_DEVICE_PATH *) Ptr; + Match = EISA_PNP_ID (0x0501); + + if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) { + NewMenuEntry = BOpt_CreateMenuEntry (BM_TERMINAL_CONTEXT_SELECT); + if (!NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + CopyMem (&NewMenuEntry->OptionNumber, &Acpi->UID, sizeof (UINT32)); + NewTerminalContext->DevicePath = DevicePathInstanceDup (DevicePath); + // + // BugBug: I have no choice, calling EfiLibStrFromDatahub will hang the system! + // coz' the misc data for each platform is not correct, actually it's the device path stored in + // datahub which is not completed, so a searching for end of device path will enter a + // dead-loop. + // + NewMenuEntry->DisplayString = EfiLibStrFromDatahub (DevicePath); + if (NULL == NewMenuEntry->DisplayString) { + NewMenuEntry->DisplayString = DevicePathToStr (DevicePath); + } + + NewMenuEntry->HelpString = NULL; + + gBS->HandleProtocol ( + Handles[Index], + &gEfiSerialIoProtocolGuid, + &SerialIo + ); + + CopyMem ( + &NewTerminalContext->BaudRate, + &SerialIo->Mode->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &NewTerminalContext->DataBits, + &SerialIo->Mode->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->Parity, + &SerialIo->Mode->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->StopBits, + &SerialIo->Mode->StopBits, + sizeof (UINT8) + ); + InsertTailList (&TerminalMenu.Head, &NewMenuEntry->Link); + TerminalMenu.MenuNumber++; + } + } + // + // Get L"ConOut", L"ConIn" and L"ErrOut" from the Var + // + OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid); + InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid); + ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid); + if (OutDevicePath) { + UpdateComAttributeFromVariable (OutDevicePath); + } + + if (InpDevicePath) { + UpdateComAttributeFromVariable (InpDevicePath); + } + + if (ErrDevicePath) { + UpdateComAttributeFromVariable (ErrDevicePath); + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + NewTerminalContext->TerminalType = 0; + NewTerminalContext->IsConIn = FALSE; + NewTerminalContext->IsConOut = FALSE; + NewTerminalContext->IsStdErr = FALSE; + + Vendor.Header.Type = MESSAGING_DEVICE_PATH; + Vendor.Header.SubType = MSG_VENDOR_DP; + + for (Index2 = 0; Index2 < 4; Index2++) { + CopyMem (&Vendor.Guid, &Guid[Index2], sizeof (EFI_GUID)); + SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); + NewDevicePath = AppendDevicePathNode ( + NewTerminalContext->DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Vendor + ); + SafeFreePool (NewMenuEntry->HelpString); + // + // NewMenuEntry->HelpString = DevicePathToStr (NewDevicePath); + // NewMenuEntry->DisplayString = NewMenuEntry->HelpString; + // + NewMenuEntry->HelpString = NULL; + + if (BdsLibMatchDevicePaths (OutDevicePath, NewDevicePath)) { + NewTerminalContext->IsConOut = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + + if (BdsLibMatchDevicePaths (InpDevicePath, NewDevicePath)) { + NewTerminalContext->IsConIn = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + + if (BdsLibMatchDevicePaths (ErrDevicePath, NewDevicePath)) { + NewTerminalContext->IsStdErr = TRUE; + NewTerminalContext->TerminalType = (UINT8) Index2; + } + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdateComAttributeFromVariable ( + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +/*++ + +Routine Description: + Update Com Ports attributes from DevicePath + +Arguments: + DevicePath - DevicePath that contains Com ports + +Returns: + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + EFI_DEVICE_PATH_PROTOCOL *SerialNode; + ACPI_HID_DEVICE_PATH *Acpi; + UART_DEVICE_PATH *Uart; + UART_DEVICE_PATH *Uart1; + UINT32 Match; + UINTN TerminalNumber; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + UINTN Index; + + Match = EISA_PNP_ID (0x0501); + Node = DevicePath; + Node = NextDevicePathNode (Node); + TerminalNumber = 0; + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + while (!IsDevicePathEnd (Node)) { + if ((DevicePathType (Node) == ACPI_DEVICE_PATH) && (DevicePathSubType (Node) == ACPI_DP)) { + Acpi = (ACPI_HID_DEVICE_PATH *) Node; + if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) { + CopyMem (&TerminalNumber, &Acpi->UID, sizeof (UINT32)); + } + } + + if ((DevicePathType (Node) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (Node) == MSG_UART_DP)) { + Uart = (UART_DEVICE_PATH *) Node; + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, TerminalNumber); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + CopyMem ( + &NewTerminalContext->BaudRate, + &Uart->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &NewTerminalContext->DataBits, + &Uart->DataBits, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->Parity, + &Uart->Parity, + sizeof (UINT8) + ); + + CopyMem ( + &NewTerminalContext->StopBits, + &Uart->StopBits, + sizeof (UINT8) + ); + + SerialNode = NewTerminalContext->DevicePath; + SerialNode = NextDevicePathNode (SerialNode); + while (!IsDevicePathEnd (SerialNode)) { + if ((DevicePathType (SerialNode) == MESSAGING_DEVICE_PATH) && (DevicePathSubType (SerialNode) == MSG_UART_DP)) { + // + // Update following device paths according to + // previous acquired uart attributes + // + Uart1 = (UART_DEVICE_PATH *) SerialNode; + CopyMem ( + &Uart1->BaudRate, + &NewTerminalContext->BaudRate, + sizeof (UINT64) + ); + + CopyMem ( + &Uart1->DataBits, + &NewTerminalContext->DataBits, + sizeof (UINT8) + ); + CopyMem ( + &Uart1->Parity, + &NewTerminalContext->Parity, + sizeof (UINT8) + ); + CopyMem ( + &Uart1->StopBits, + &NewTerminalContext->StopBits, + sizeof (UINT8) + ); + + break; + } + + SerialNode = NextDevicePathNode (SerialNode); + } + // + // end while + // + } + + Node = NextDevicePathNode (Node); + } + // + // end while + // + } + + return EFI_SUCCESS; +} + +EFI_DEVICE_PATH_PROTOCOL * +DevicePathInstanceDup ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +/*++ + +Routine Description: + Function creates a device path data structure that identically matches the + device path passed in. + +Arguments: + DevPath - A pointer to a device path data structure. + +Returns: + + The new copy of DevPath is created to identically match the input. + Otherwise, NULL is returned. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevPath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + EFI_DEVICE_PATH_PROTOCOL *Temp; + UINT8 *Ptr; + UINTN Size; + + // + // get the size of an instance from the input + // + Temp = DevPath; + DevicePathInst = GetNextDevicePathInstance (&Temp, &Size); + + // + // Make a copy and set proper end type + // + NewDevPath = NULL; + if (Size) { + NewDevPath = AllocateZeroPool (Size); + ASSERT (NewDevPath != NULL); + } + + if (NewDevPath) { + CopyMem (NewDevPath, DevicePathInst, Size); + Ptr = (UINT8 *) NewDevPath; + Ptr += Size - sizeof (EFI_DEVICE_PATH_PROTOCOL); + Temp = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + SetDevicePathEndNode (Temp); + } + + return NewDevPath; +} + +EFI_STATUS +GetConsoleMenu ( + IN UINTN ConsoleMenuType + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *AllDevicePath; + EFI_DEVICE_PATH_PROTOCOL *MultiDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + UINTN Size; + UINTN AllCount; + UINTN Index; + UINTN Index2; + BM_MENU_ENTRY *NewMenuEntry; + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + TYPE_OF_TERMINAL Terminal; + BM_MENU_ENTRY *NewTerminalMenuEntry; + UINTN Com; + BM_MENU_OPTION *ConsoleMenu; + + DevicePath = NULL; + AllDevicePath = NULL; + AllCount = 0; + switch (ConsoleMenuType) { + case BM_CONSOLE_IN_CONTEXT_SELECT: + ConsoleMenu = &ConsoleInpMenu; + DevicePath = EfiLibGetVariable ( + L"ConIn", + &gEfiGlobalVariableGuid + ); + + AllDevicePath = EfiLibGetVariable ( + L"ConInDev", + &gEfiGlobalVariableGuid + ); + break; + + case BM_CONSOLE_OUT_CONTEXT_SELECT: + ConsoleMenu = &ConsoleOutMenu; + DevicePath = EfiLibGetVariable ( + L"ConOut", + &gEfiGlobalVariableGuid + ); + + AllDevicePath = EfiLibGetVariable ( + L"ConOutDev", + &gEfiGlobalVariableGuid + ); + break; + + case BM_CONSOLE_ERR_CONTEXT_SELECT: + ConsoleMenu = &ConsoleErrMenu; + DevicePath = EfiLibGetVariable ( + L"ErrOut", + &gEfiGlobalVariableGuid + ); + + AllDevicePath = EfiLibGetVariable ( + L"ErrOutDev", + &gEfiGlobalVariableGuid + ); + break; + + default: + return EFI_UNSUPPORTED; + } + + if (NULL == AllDevicePath) { + return EFI_NOT_FOUND; + } + + InitializeListHead (&ConsoleMenu->Head); + + AllCount = EfiDevicePathInstanceCount (AllDevicePath); + ConsoleMenu->MenuNumber = 0; + // + // Following is menu building up for Console Out Devices + // + MultiDevicePath = AllDevicePath; + Index2 = 0; + for (Index = 0; Index < AllCount; Index++) { + DevicePathInst = GetNextDevicePathInstance (&MultiDevicePath, &Size); + + NewMenuEntry = BOpt_CreateMenuEntry (BM_CONSOLE_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + NewMenuEntry->OptionNumber = Index2; + + NewConsoleContext->DevicePath = DevicePathInstanceDup (DevicePathInst); + NewMenuEntry->DisplayString = EfiLibStrFromDatahub (NewConsoleContext->DevicePath); + if (NULL == NewMenuEntry->DisplayString) { + NewMenuEntry->DisplayString = DevicePathToStr (NewConsoleContext->DevicePath); + } + + NewConsoleContext->IsTerminal = IsTerminalDevicePath ( + NewConsoleContext->DevicePath, + &Terminal, + &Com + ); + + NewConsoleContext->IsActive = BdsLibMatchDevicePaths ( + DevicePath, + NewConsoleContext->DevicePath + ); + NewTerminalMenuEntry = NULL; + NewTerminalContext = NULL; + + if (NewConsoleContext->IsTerminal) { + BOpt_DestroyMenuEntry (NewMenuEntry); + } else { + Index2++; + ConsoleMenu->MenuNumber++; + InsertTailList (&ConsoleMenu->Head, &NewMenuEntry->Link); + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetAllConsoles ( + VOID + ) +/*++ + +Routine Description: + Build up ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + +Arguments: + +Returns: + EFI_SUCCESS + Others + +--*/ +{ + GetConsoleMenu (BM_CONSOLE_IN_CONTEXT_SELECT); + GetConsoleMenu (BM_CONSOLE_OUT_CONTEXT_SELECT); + GetConsoleMenu (BM_CONSOLE_ERR_CONTEXT_SELECT); + return EFI_SUCCESS; +} + +EFI_STATUS +FreeAllConsoles ( + VOID + ) +/*++ + +Routine Description: + Free ConsoleOutMenu, ConsoleInpMenu and ConsoleErrMenu + +Arguments: + +Returns: + EFI_SUCCESS + Others + +--*/ +{ + BOpt_FreeMenu (&ConsoleOutMenu); + BOpt_FreeMenu (&ConsoleInpMenu); + BOpt_FreeMenu (&ConsoleErrMenu); + BOpt_FreeMenu (&TerminalMenu); + return EFI_SUCCESS; +} + +BOOLEAN +IsTerminalDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT TYPE_OF_TERMINAL *Termi, + OUT UINTN *Com + ) +/*++ + +Routine Description: + Test whether DevicePath is a valid Terminal + +Arguments: + DevicePath - DevicePath to be checked + Termi - If is terminal, give its type + Com - If is Com Port, give its type + +Returns: + TRUE - If DevicePath point to a Terminal + FALSE + +--*/ +{ + UINT8 *Ptr; + BOOLEAN IsTerminal; + VENDOR_DEVICE_PATH *Vendor; + ACPI_HID_DEVICE_PATH *Acpi; + UINT32 Match; + EFI_GUID TempGuid; + + IsTerminal = FALSE; + + // + // Parse the Device Path, should be change later!!! + // + Ptr = (UINT8 *) DevicePath; + while (*Ptr != END_DEVICE_PATH_TYPE) { + Ptr++; + } + + Ptr = Ptr - sizeof (VENDOR_DEVICE_PATH); + Vendor = (VENDOR_DEVICE_PATH *) Ptr; + + // + // There are four kinds of Terminal types + // check to see whether this devicepath + // is one of that type + // + CopyMem (&TempGuid, &Vendor->Guid, sizeof (EFI_GUID)); + + if (CompareGuid (&TempGuid, &Guid[0])) { + *Termi = PC_ANSI; + IsTerminal = TRUE; + } else { + if (CompareGuid (&TempGuid, &Guid[1])) { + *Termi = VT_100; + IsTerminal = TRUE; + } else { + if (CompareGuid (&TempGuid, &Guid[2])) { + *Termi = VT_100_PLUS; + IsTerminal = TRUE; + } else { + if (CompareGuid (&TempGuid, &Guid[3])) { + *Termi = VT_UTF8; + IsTerminal = TRUE; + } else { + IsTerminal = FALSE; + } + } + } + } + + if (!IsTerminal) { + return FALSE; + } + + Ptr = Ptr - sizeof (UART_DEVICE_PATH) - sizeof (ACPI_HID_DEVICE_PATH); + Acpi = (ACPI_HID_DEVICE_PATH *) Ptr; + Match = EISA_PNP_ID (0x0501); + if (CompareMem (&Acpi->HID, &Match, sizeof (UINT32)) == 0) { + CopyMem (Com, &Acpi->UID, sizeof (UINT32)); + } else { + return FALSE; + } + + return TRUE; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/Data.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/Data.c new file mode 100644 index 0000000000..3c0c1cc7e3 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/Data.c @@ -0,0 +1,324 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + data.c + +Abstract: + + Define some data used for Boot Maint + +Revision History + +--*/ + +#include "bootmaint.h" + +EFI_HII_UPDATE_DATA *UpdateData; +STRING_DEPOSITORY *FileOptionStrDepository; +STRING_DEPOSITORY *ConsoleOptionStrDepository; +STRING_DEPOSITORY *BootOptionStrDepository; +STRING_DEPOSITORY *BootOptionHelpStrDepository; +STRING_DEPOSITORY *DriverOptionStrDepository; +STRING_DEPOSITORY *DriverOptionHelpStrDepository; +STRING_DEPOSITORY *TerminalStrDepository; + +// +// Terminal type string token storage +// +UINT16 TerminalType[] = { + STRING_TOKEN(STR_COM_TYPE_0), + STRING_TOKEN(STR_COM_TYPE_1), + STRING_TOKEN(STR_COM_TYPE_2), + STRING_TOKEN(STR_COM_TYPE_3), +}; + +// +// File system selection menu +// +BM_MENU_OPTION FsOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Console Input Device Selection Menu +// +BM_MENU_OPTION ConsoleInpMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Console Output Device Selection Menu +// +BM_MENU_OPTION ConsoleOutMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Error Output Device Selection Menu +// +BM_MENU_OPTION ConsoleErrMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Boot Option from variable Menu +// +BM_MENU_OPTION BootOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Driver Option from variable menu +// +BM_MENU_OPTION DriverOptionMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Legacy FD Info from LegacyBios.GetBbsInfo() +// +BM_MENU_OPTION LegacyFDMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Legacy HD Info from LegacyBios.GetBbsInfo() +// +BM_MENU_OPTION LegacyHDMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Legacy CD Info from LegacyBios.GetBbsInfo() +// +BM_MENU_OPTION LegacyCDMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Legacy NET Info from LegacyBios.GetBbsInfo() +// +BM_MENU_OPTION LegacyNETMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Legacy NET Info from LegacyBios.GetBbsInfo() +// +BM_MENU_OPTION LegacyBEVMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Files and sub-directories in current directory menu +// +BM_MENU_OPTION DirectoryMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Handles in current system selection menu +// +BM_MENU_OPTION DriverMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +BM_MENU_OPTION TerminalMenu = { + BM_MENU_OPTION_SIGNATURE, + NULL, + 0 +}; + +// +// Value and string token correspondency for BaudRate +// +COM_ATTR BaudRateList[19] = { + { + 115200, + STRING_TOKEN(STR_COM_BAUD_RATE_0) + }, + { + 57600, + STRING_TOKEN(STR_COM_BAUD_RATE_1) + }, + { + 38400, + STRING_TOKEN(STR_COM_BAUD_RATE_2) + }, + { + 19200, + STRING_TOKEN(STR_COM_BAUD_RATE_3) + }, + { + 9600, + STRING_TOKEN(STR_COM_BAUD_RATE_4) + }, + { + 7200, + STRING_TOKEN(STR_COM_BAUD_RATE_5) + }, + { + 4800, + STRING_TOKEN(STR_COM_BAUD_RATE_6) + }, + { + 3600, + STRING_TOKEN(STR_COM_BAUD_RATE_7) + }, + { + 2400, + STRING_TOKEN(STR_COM_BAUD_RATE_8) + }, + { + 2000, + STRING_TOKEN(STR_COM_BAUD_RATE_9) + }, + { + 1800, + STRING_TOKEN(STR_COM_BAUD_RATE_10) + }, + { + 1200, + STRING_TOKEN(STR_COM_BAUD_RATE_11) + }, + { + 600, + STRING_TOKEN(STR_COM_BAUD_RATE_12) + }, + { + 300, + STRING_TOKEN(STR_COM_BAUD_RATE_13) + }, + { + 150, + STRING_TOKEN(STR_COM_BAUD_RATE_14) + }, + { + 134, + STRING_TOKEN(STR_COM_BAUD_RATE_15) + }, + { + 110, + STRING_TOKEN(STR_COM_BAUD_RATE_16) + }, + { + 75, + STRING_TOKEN(STR_COM_BAUD_RATE_17) + }, + { + 50, + STRING_TOKEN(STR_COM_BAUD_RATE_18) + } +}; + +// +// Value and string token correspondency for DataBits +// +COM_ATTR DataBitsList[4] = { + { + 5, + STRING_TOKEN(STR_COM_DATA_BITS_0) + }, + { + 6, + STRING_TOKEN(STR_COM_DATA_BITS_1) + }, + { + 7, + STRING_TOKEN(STR_COM_DATA_BITS_2) + }, + { + 8, + STRING_TOKEN(STR_COM_DATA_BITS_3) + } +}; + +// +// Value and string token correspondency for Parity +// +COM_ATTR ParityList[5] = { + { + NoParity, + STRING_TOKEN(STR_COM_PAR_0) + }, + { + EvenParity, + STRING_TOKEN(STR_COM_PAR_1) + }, + { + OddParity, + STRING_TOKEN(STR_COM_PAR_2) + }, + { + MarkParity, + STRING_TOKEN(STR_COM_PAR_3) + }, + { + SpaceParity, + STRING_TOKEN(STR_COM_PAR_4) + } +}; + +// +// Value and string token correspondency for Baudreate +// +COM_ATTR StopBitsList[3] = { + { + OneStopBit, + STRING_TOKEN(STR_COM_STOP_BITS_0) + }, + { + OneFiveStopBits, + STRING_TOKEN(STR_COM_STOP_BITS_1) + }, + { + TwoStopBits, + STRING_TOKEN(STR_COM_STOP_BITS_2) + } +}; + +// +// Guid for messaging path, used in Serial port setting. +// +EFI_GUID Guid[4] = { + DEVICE_PATH_MESSAGING_PC_ANSI, + DEVICE_PATH_MESSAGING_VT_100, + DEVICE_PATH_MESSAGING_VT_100_PLUS, + DEVICE_PATH_MESSAGING_VT_UTF8 +}; diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/FE.vfr b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/FE.vfr new file mode 100644 index 0000000000..998a4a68f5 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/FE.vfr @@ -0,0 +1,138 @@ +// *++ +// +// Copyright (c) 2006, 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. +// +// Module Name: +// +// FE.vfr +// +// Abstract: +// +// File Explorer Formset +// +// Revision History: +// +// --*/ + +#include "BdsStrDefs.h" +#include "formguid.h" + +#pragma pack(1) +typedef struct { + UINT16 DescriptionData[75]; + UINT16 OptionalData[127]; + UINT8 Active; + UINT8 ForceReconnect; +} FILE_EXPLORER_NV_DATA; +#pragma pack() + +#define FORM_FILE_EXPLORER_ID 0x001E +#define FORM_BOOT_ADD_DESCRIPTION_ID 0x001F +#define FORM_DRIVER_ADD_FILE_DESCRIPTION_ID 0x0020 +#define KEY_VALUE_SAVE_AND_EXIT 0x0090 +#define KEY_VALUE_NO_SAVE_AND_EXIT 0x0091 + + + +formset + guid = FILE_EXPLORE_FORMSET_GUID, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + class = 0, + subclass = 0, + + form formid = FORM_FILE_EXPLORER_ID, + title = STRING_TOKEN(STR_FILE_EXPLORER_TITLE); + + label FORM_FILE_EXPLORER_ID; + endform; + + form formid = FORM_BOOT_ADD_DESCRIPTION_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_DESC_TITLE); + + label FORM_BOOT_ADD_DESCRIPTION_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + string varid = FILE_EXPLORER_NV_DATA.DescriptionData, + prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 6, + maxsize = 75, + endstring; + + string varid = FILE_EXPLORER_NV_DATA.OptionalData, + prompt = STRING_TOKEN(STR_OPTIONAL_DATA), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 0, + maxsize = 120, + endstring; + + text + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | NV_ACCESS, + key = KEY_VALUE_SAVE_AND_EXIT; + + text + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | NV_ACCESS, + key = KEY_VALUE_NO_SAVE_AND_EXIT; + + endform; + + form formid = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); + + label FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + string varid = FILE_EXPLORER_NV_DATA.DescriptionData, + prompt = STRING_TOKEN(STR_LOAD_OPTION_DESC), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 6, + maxsize = 75, + endstring; + + string varid = FILE_EXPLORER_NV_DATA.OptionalData, + prompt = STRING_TOKEN(STR_OPTIONAL_DATA), + help = STRING_TOKEN(STR_NULL_STRING), + minsize = 0, + maxsize = 120, + endstring; + + checkbox varid = FILE_EXPLORER_NV_DATA.ForceReconnect, + prompt = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), + help = STRING_TOKEN(STR_LOAD_OPTION_FORCE_RECON), + flags = 1, + key = 0, + endcheckbox; + + text + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | NV_ACCESS, + key = KEY_VALUE_SAVE_AND_EXIT; + + text + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | NV_ACCESS, + key = KEY_VALUE_NO_SAVE_AND_EXIT; + + endform; + +endformset; \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/FileExplorer.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/FileExplorer.c new file mode 100644 index 0000000000..0c8c74c604 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/FileExplorer.c @@ -0,0 +1,335 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FileExplorer.c + +AgBStract: + + File explorer related functions. + +--*/ + +#include "Generic/Bds.h" +#include "bootmaint.h" +#include "BdsPlatform.h" + +VOID +UpdateFileExplorePage ( + IN BMM_CALLBACK_DATA *CallbackData, + BM_MENU_OPTION *MenuOption + ) +/*++ +Routine Description: + Update the File Explore page. + +Arguments: + MenuOption - Pointer to menu options to display. + +Returns: + None. + +--*/ +{ + UINT8 *Location; + UINTN Index; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *NewFileContext; + FORM_ID FormId; + + NewMenuEntry = NULL; + NewFileContext = NULL; + FormId = 0; + + // + // Clean up file explore page. + // + RefreshUpdateData (FALSE, 0, FALSE, 0, 0xff); + + // + // Remove all op-codes from dynamic page + // + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->FeHiiHandle, + FORM_FILE_EXPLORER_ID, + FALSE, + UpdateData + ); + + RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->FeCallbackHandle, FALSE, 0, 0); + + Location = (UINT8 *) &UpdateData->Data; + + for (Index = 0; Index < MenuOption->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (MenuOption, Index); + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewFileContext->IsBootLegacy) { + continue; + } + + if ((NewFileContext->IsDir) || (BOOT_FROM_FILE_STATE == CallbackData->FeCurrentState)) { + // + // Create Text opcode for directory, also create Text opcode for file in BOOT_FROM_FILE_STATE. + // + CreateTextOpCode ( + NewMenuEntry->DisplayStringToken, + STR_NULL_STRING, + STR_NULL_STRING, + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) (FILE_OPTION_OFFSET + Index), + Location + ); + } else { + // + // Create Goto opcode for file in ADD_BOOT_OPTION_STATE or ADD_DRIVER_OPTION_STATE. + // + if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) { + FormId = FORM_BOOT_ADD_DESCRIPTION_ID; + } else if (ADD_DRIVER_OPTION_STATE == CallbackData->FeCurrentState) { + FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + } + + CreateGotoOpCode ( + FormId, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) (FILE_OPTION_OFFSET + Index), + Location + ); + } + + UpdateData->DataCount++; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + } + + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->FeHiiHandle, + FORM_FILE_EXPLORER_ID, + TRUE, + UpdateData + ); +} + +BOOLEAN +UpdateFileExplorer ( + IN BMM_CALLBACK_DATA *CallbackData, + IN UINT16 KeyValue + ) +/*++ + +Routine Description: + Update the file explower page with the refershed file system. + +Arguments: + CallbackData - BMM context data + KeyValue - Key value to identify the type of data to expect. + +Returns: + TRUE - Inform the caller to create a callback packet to exit file explorer. + FALSE - Indicate that there is no need to exit file explorer. + +--*/ +{ + UINT16 FileOptionMask; + BM_MENU_ENTRY *NewMenuEntry; + BM_FILE_CONTEXT *NewFileContext; + FORM_ID FormId; + BOOLEAN ExitFileExplorer; + + NewMenuEntry = NULL; + NewFileContext = NULL; + ExitFileExplorer = FALSE; + + FileOptionMask = (UINT16) (FILE_OPTION_MASK & KeyValue); + + if (UNKNOWN_CONTEXT == CallbackData->FeDisplayContext) { + // + // First in, display file system. + // + BOpt_FreeMenu (&FsOptionMenu); + BOpt_FindFileSystem (CallbackData); + CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &FsOptionMenu); + + UpdateFileExplorePage (CallbackData, &FsOptionMenu); + + CallbackData->FeDisplayContext = FILE_SYSTEM; + } else { + if (FILE_SYSTEM == CallbackData->FeDisplayContext) { + NewMenuEntry = BOpt_GetMenuEntry (&FsOptionMenu, FileOptionMask); + } else if (DIRECTORY == CallbackData->FeDisplayContext) { + NewMenuEntry = BOpt_GetMenuEntry (&DirectoryMenu, FileOptionMask); + } + + CallbackData->FeDisplayContext = DIRECTORY; + + NewFileContext = (BM_FILE_CONTEXT *) NewMenuEntry->VariableContext; + + if (NewFileContext->IsDir ) { + RemoveEntryList (&NewMenuEntry->Link); + BOpt_FreeMenu (&DirectoryMenu); + BOpt_FindFiles (CallbackData, NewMenuEntry); + CreateMenuStringToken (CallbackData, CallbackData->FeHiiHandle, &DirectoryMenu); + BOpt_DestroyMenuEntry (NewMenuEntry); + + UpdateFileExplorePage (CallbackData, &DirectoryMenu); + + } else { + switch (CallbackData->FeCurrentState) { + case BOOT_FROM_FILE_STATE: + // + // Here boot from file + // + BootThisFile (NewFileContext); + ExitFileExplorer = TRUE; + break; + + case ADD_BOOT_OPTION_STATE: + case ADD_DRIVER_OPTION_STATE: + if (ADD_BOOT_OPTION_STATE == CallbackData->FeCurrentState) { + FormId = FORM_BOOT_ADD_DESCRIPTION_ID; + } else { + FormId = FORM_DRIVER_ADD_FILE_DESCRIPTION_ID; + } + + CallbackData->MenuEntry = NewMenuEntry; + CallbackData->LoadContext->FilePathList = ((BM_FILE_CONTEXT *) (CallbackData->MenuEntry->VariableContext))->DevicePath; + + // + // Clean up file explore page. + // + RefreshUpdateData (FALSE, 0, FALSE, 0, 1); + + // + // Remove the Subtitle op-code. + // + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->FeHiiHandle, + FormId, + FALSE, + UpdateData + ); + + // + // Create Subtitle op-code for the display string of the option. + // + RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->FeCallbackHandle, FALSE, 0, 1); + + CreateSubTitleOpCode ( + NewMenuEntry->DisplayStringToken, + &UpdateData->Data + ); + + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->FeHiiHandle, + FormId, + TRUE, + UpdateData + ); + break; + + default: + break; + } + } + } + + return ExitFileExplorer; +} + +EFI_STATUS +EFIAPI +FileExplorerCallback ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *Data, + OUT EFI_HII_CALLBACK_PACKET **Packet + ) +/*++ +Routine Description: + Callback Function for file exploration and file interaction. + +Arguments: + This - File explorer callback protocol pointer. + KeyValue - Key value to identify the type of data to expect. + Data - A pointer to the data being sent to the original exporting driver. + Packet - A pointer to a packet of information which a driver passes back to the browser. + +Returns: + EFI_SUCCESS - Callback ended successfully. + Others - Contain some errors. + +--*/ +{ + BMM_CALLBACK_DATA *Private; + FILE_EXPLORER_NV_DATA *NvRamMap; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + Private = FE_CALLBACK_DATA_FROM_THIS (This); + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) Private->FeCallbackHandle; + NvRamMap = (FILE_EXPLORER_NV_DATA *) Data->NvRamMap; + + if (KEY_VALUE_SAVE_AND_EXIT == KeyValue) { + // + // Apply changes and exit formset. + // + if (ADD_BOOT_OPTION_STATE == Private->FeCurrentState) { + Status = Var_UpdateBootOption (Private, NvRamMap); + if (EFI_ERROR (Status)) { + return Status; + } + + BOpt_GetBootOptions (Private); + CreateMenuStringToken (Private, Private->FeHiiHandle, &BootOptionMenu); + } else if (ADD_DRIVER_OPTION_STATE == Private->FeCurrentState) { + Status = Var_UpdateDriverOption ( + Private, + Private->FeHiiHandle, + NvRamMap->DescriptionData, + NvRamMap->OptionalData, + NvRamMap->ForceReconnect + ); + if (EFI_ERROR (Status)) { + return Status; + } + + BOpt_GetDriverOptions (Private); + CreateMenuStringToken (Private, Private->FeHiiHandle, &DriverOptionMenu); + } + + CreateCallbackPacket (Packet, EXIT_REQUIRED | NV_NOT_CHANGED); + } else if (KEY_VALUE_NO_SAVE_AND_EXIT == KeyValue) { + // + // Discard changes and exit formset. + // + NvRamMap->OptionalData[0] = 0x0000; + NvRamMap->DescriptionData[0] = 0x0000; + CreateCallbackPacket (Packet, EXIT_REQUIRED | NV_NOT_CHANGED); + } else if (KeyValue < FILE_OPTION_OFFSET) { + // + // Exit File Explorer formset. + // + CreateCallbackPacket (Packet, EXIT_REQUIRED); + } else { + if (UpdateFileExplorer (Private, KeyValue)) { + CreateCallbackPacket (Packet, EXIT_REQUIRED); + } + } + + return Status; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/FormGuid.h b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/FormGuid.h new file mode 100644 index 0000000000..3d4cd4a027 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/FormGuid.h @@ -0,0 +1,32 @@ +// *++ +// +// Copyright (c) 2006, 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. +// +// Module Name: +// +// formguid.h +// +// Abstract: +// +// Formset guids for Boot Maintenance Manager +// +// Revision History: +// +// --*/ +// +#define MAIN_FORMSET_GUID \ + { \ + 0x642237c7, 0x35d4, 0x472d, { 0x83, 0x65, 0x12, 0xe0, 0xcc, 0xf2, 0x7a, 0x22 } \ + } + +#define FILE_EXPLORE_FORMSET_GUID \ + { \ + 0x1f2d63e1, 0xfebd, 0x4dc7, { 0x9c, 0xc5, 0xba, 0x2b, 0x1c, 0xef, 0x9c, 0x5b } \ + } diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/UpdatePage.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/UpdatePage.c new file mode 100644 index 0000000000..65ee289968 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/UpdatePage.c @@ -0,0 +1,1275 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + UpdatePage.c + +AgBStract: + + Dynamically Update the pages + +--*/ + +#include "Generic/Bds.h" +#include "bootmaint.h" +#include "BdsPlatform.h" + +EFI_GUID gTerminalDriverGuid = { + 0x10634d8e, 0x1c05, 0x46cb, 0xbb, 0xc, 0x5a, 0xfd, 0xc8, 0x29, 0xa8, 0xc8 +}; + +VOID +RefreshUpdateData ( + IN BOOLEAN FormSetUpdate, + IN EFI_PHYSICAL_ADDRESS FormCallbackHandle, + IN BOOLEAN FormUpdate, + IN STRING_REF FormTitle, + IN UINT16 DataCount + ) +/*++ +Routine Description: + Refresh the global UpdateData structure. + +Arguments: + FormSetUpdate - If TRUE, next variable is significant + FormCallbackHandle - If not 0, will update FormSet with this info + FormUpdate - If TRUE, next variable is significant + FormTitle - If not 0, will update Form with this info + DataCount - The number of Data entries in this structure + +Returns: + None. +--*/ +{ + UpdateData->FormSetUpdate = FormSetUpdate; + if (FormSetUpdate) { + ASSERT (0 != FormCallbackHandle); + UpdateData->FormCallbackHandle = FormCallbackHandle; + } + + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = FormTitle; + UpdateData->DataCount = DataCount; +} + +VOID +UpdatePageStart ( + IN BMM_CALLBACK_DATA *CallbackData, + IN OUT UINT8 **CurrentLocation + ) +{ + RefreshUpdateData (TRUE, (EFI_PHYSICAL_ADDRESS) (UINTN) CallbackData->BmmCallbackHandle, FALSE, 0, 0); + + if (!(CallbackData->BmmAskSaveOrNot)) { + // + // Add a "Go back to main page" tag in front of the form when there are no + // "Apply changes" and "Discard changes" tags in the end of the form. + // + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_FORM_GOTO_MAIN), + STRING_TOKEN (STR_FORM_GOTO_MAIN), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + FORM_MAIN_ID, + *CurrentLocation + ); + + UpdateData->DataCount++; + + *CurrentLocation = *CurrentLocation + ((EFI_IFR_OP_HEADER *) (*CurrentLocation))->Length; + } + +} + +VOID +UpdatePageEnd ( + IN BMM_CALLBACK_DATA *CallbackData, + IN UINT8 *CurrentLocation + ) +{ + // + // Create the "Apply changes" and "Discard changes" tags. + // + if (CallbackData->BmmAskSaveOrNot) { + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_SAVE_AND_EXIT, + CurrentLocation + ); + + UpdateData->DataCount++; + + CurrentLocation = CurrentLocation + ((EFI_IFR_OP_HEADER *) CurrentLocation)->Length; + + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_NO_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_NO_SAVE_AND_EXIT, + CurrentLocation + ); + + UpdateData->DataCount++; + } + // + // Ensure user can return to the main page. + // + if (0 == UpdateData->DataCount) { + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_NO_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_NO_SAVE_AND_EXIT, + CurrentLocation + ); + + UpdateData->DataCount++; + } + + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->BmmHiiHandle, + CallbackData->BmmCurrentPageId, + TRUE, + UpdateData + ); +} + +VOID +CleanUpPage ( + IN EFI_FORM_LABEL LabelId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + RefreshUpdateData (FALSE, 0, FALSE, 0, 0xff); + + // + // Remove all op-codes from dynamic page + // + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->BmmHiiHandle, + LabelId, + FALSE, + UpdateData + ); +} + +EFI_STATUS +BootThisFile ( + IN BM_FILE_CONTEXT *FileContext + ) +{ + EFI_STATUS Status; + UINTN ExitDataSize; + CHAR16 *ExitData; + BDS_COMMON_OPTION *Option; + + Status = gBS->AllocatePool (EfiBootServicesData, sizeof (BDS_COMMON_OPTION), &Option); + Option->Description = FileContext->FileName; + Option->DevicePath = FileContext->DevicePath; + Option->LoadOptionsSize = 0; + Option->LoadOptions = NULL; + + // + // Since current no boot from removable media directly is allowed */ + // + gST->ConOut->ClearScreen (gST->ConOut); + + ExitDataSize = 0; + + Status = BdsLibBootViaBootOption (Option, Option->DevicePath, &ExitDataSize, &ExitData); + + return Status; + +} + +VOID +UpdateConCOMPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + UINT8 *Location; + EFI_STATUS Status; + VOID *Interface; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = FALSE; + + UpdatePageStart (CallbackData, &Location); + + Status = EfiLibLocateProtocol (&gTerminalDriverGuid, &Interface); + if (!EFI_ERROR (Status)) { + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + + CreateGotoOpCode ( + FORM_CON_COM_SETUP_ID, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) (TERMINAL_OPTION_OFFSET + Index), + Location + ); + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + } + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateBootDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + UINT8 *Location; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu); + + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (NewLoadContext->IsLegacy) { + continue; + } + + NewLoadContext->Deleted = FALSE; + CallbackData->BmmFakeNvData->BootOptionDel[Index] = 0x00; + + CreateCheckBoxOpCode ( + (UINT16) (BOOT_OPTION_DEL_QUESTION_ID + Index), + (UINT8) 1, + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) BOOT_OPTION_DEL_QUESTION_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateDrvAddHandlePage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + UINT8 *Location; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = FALSE; + + UpdatePageStart (CallbackData, &Location); + + for (Index = 0; Index < DriverMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverMenu, Index); + + CreateGotoOpCode ( + FORM_DRV_ADD_HANDLE_DESC_ID, + NewMenuEntry->DisplayStringToken, + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) (HANDLE_OPTION_OFFSET + Index), + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateDrvDelPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + UINT16 Index; + UINT8 *Location; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &DriverOptionMenu); + + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = FALSE; + CallbackData->BmmFakeNvData->DriverOptionDel[Index] = 0x00; + + CreateCheckBoxOpCode ( + (UINT16) (DRIVER_OPTION_DEL_QUESTION_ID + Index), + (UINT8) 1, + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + (UINT16) DRIVER_OPTION_DEL_QUESTION_ID, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateDriverAddHandleDescPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT8 *Location; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmFakeNvData->DriverAddActive = 0x01; + CallbackData->BmmFakeNvData->DriverAddForceReconnect = 0x00; + CallbackData->BmmAskSaveOrNot = TRUE; + NewMenuEntry = CallbackData->MenuEntry; + + UpdatePageStart (CallbackData, &Location); + + UpdateData->DataCount += (UINT16) 4; + + CreateSubTitleOpCode ( + NewMenuEntry->DisplayStringToken, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateStringOpCode ( + DRV_ADD_HANDLE_DESC_QUESTION_ID, + (UINT8) 150, + STRING_TOKEN (STR_LOAD_OPTION_DESC), + STRING_TOKEN (STR_NULL_STRING), + 6, + 75, + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_DRIVER_ADD_DESC_DATA, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateCheckBoxOpCode ( + DRV_ADD_RECON_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON), + STRING_TOKEN (STR_LOAD_OPTION_FORCE_RECON), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + DRV_ADD_RECON_QUESTION_ID, + Location + ); + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + CreateStringOpCode ( + DRIVER_ADD_OPTION_QUESTION_ID, + (UINT8) 150, + STRING_TOKEN (STR_OPTIONAL_DATA), + STRING_TOKEN (STR_NULL_STRING), + 6, + 75, + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_DRIVER_ADD_OPT_DATA, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateConsolePage ( + IN UINT16 UpdatePageId, + IN BM_MENU_OPTION *ConsoleMenu, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + UINT16 Index; + UINT16 Index2; + UINT8 *Location; + UINT8 CheckFlags; + EFI_STATUS Status; + VOID *Interface; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + + for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + if (NewConsoleContext->IsActive) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + CallbackData->BmmFakeNvData->ConsoleCheck[Index] = TRUE; + } else { + CallbackData->BmmFakeNvData->ConsoleCheck[Index] = FALSE; + } + + CreateCheckBoxOpCode ( + (UINT16) (CON_DEVICE_QUESTION_ID + Index), + (UINT8) 1, + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + CheckFlags, + (UINT16) (CONSOLE_OPTION_OFFSET + Index), + Location + ); + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + } + + Status = EfiLibLocateProtocol (&gTerminalDriverGuid, &Interface); + if (!EFI_ERROR (Status)) { + for (Index2 = 0; Index2 < TerminalMenu.MenuNumber; Index2++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index2); + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) || + (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) || + (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID)) + ) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + CallbackData->BmmFakeNvData->ConsoleCheck[Index] = TRUE; + } else { + CallbackData->BmmFakeNvData->ConsoleCheck[Index] = FALSE; + } + + CreateCheckBoxOpCode ( + (UINT16) (CON_DEVICE_QUESTION_ID + Index), + (UINT8) 1, + NewMenuEntry->DisplayStringToken, + NewMenuEntry->HelpStringToken, + CheckFlags, + (UINT16) (CONSOLE_OPTION_OFFSET + Index), + Location + ); + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + Index++; + } + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateOrderPage ( + IN UINT16 UpdatePageId, + IN BM_MENU_OPTION *OptionMenu, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + UINT16 Index; + UINT8 *Location; + IFR_OPTION *IfrOptionList; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu); + + ZeroMem (CallbackData->BmmFakeNvData->OptionOrder, 100); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * OptionMenu->MenuNumber); + if (NULL == IfrOptionList) { + return ; + } + + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index); + IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken; + IfrOptionList[Index].Value = (UINT16) (NewMenuEntry->OptionNumber + 1); + IfrOptionList[Index].OptionString = NULL; + CallbackData->BmmFakeNvData->OptionOrder[Index] = (UINT8) (IfrOptionList[Index].Value); + } + + if (OptionMenu->MenuNumber > 0) { + CreateOrderedListOpCode ( + (UINT16) OPTION_ORDER_QUESTION_ID, + (UINT8) 100, + STRING_TOKEN (STR_CHANGE_ORDER), + STRING_TOKEN (STR_CHANGE_ORDER), + IfrOptionList, + OptionMenu->MenuNumber, + Location + ); + + for (Index = 0; Index < OptionMenu->MenuNumber + 2; Index++) { + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + } + + UpdateData->DataCount = (UINT16) (UpdateData->DataCount + OptionMenu->MenuNumber + 2); + } + + SafeFreePool (IfrOptionList); + + UpdatePageEnd (CallbackData, Location); + + CopyMem ( + CallbackData->BmmOldFakeNVData.OptionOrder, + CallbackData->BmmFakeNvData->OptionOrder, + 100 + ); +} + +VOID +UpdateBootNextPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT8 *Location; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + IFR_OPTION *IfrOptionList; + UINTN NumberOfOptions; + UINT16 Index; + + Location = (UINT8 *) &UpdateData->Data; + IfrOptionList = NULL; + NumberOfOptions = BootOptionMenu.MenuNumber; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, &BootOptionMenu); + + if (NumberOfOptions > 0) { + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + NumberOfOptions); + IfrOptionList = AllocateZeroPool ((NumberOfOptions + 1) * sizeof (IFR_OPTION)); + + ASSERT (IfrOptionList); + + CallbackData->BmmFakeNvData->BootNext = (UINT16) (BootOptionMenu.MenuNumber); + + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (NewLoadContext->IsBootNext) { + IfrOptionList[Index].Flags = EFI_IFR_FLAG_DEFAULT | EFI_IFR_FLAG_INTERACTIVE; + CallbackData->BmmFakeNvData->BootNext = Index; + } else { + IfrOptionList[Index].Flags = EFI_IFR_FLAG_INTERACTIVE; + } + + IfrOptionList[Index].Key = (UINT16) KEY_VALUE_MAIN_BOOT_NEXT; + IfrOptionList[Index].Value = Index; + IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken; + IfrOptionList[Index].OptionString = NULL; + } + + IfrOptionList[Index].Key = (UINT16) KEY_VALUE_MAIN_BOOT_NEXT; + IfrOptionList[Index].Value = Index; + IfrOptionList[Index].StringToken = STRING_TOKEN (STR_NONE); + IfrOptionList[Index].Flags = EFI_IFR_FLAG_INTERACTIVE; + if (CallbackData->BmmFakeNvData->BootNext == Index) { + IfrOptionList[Index].Flags |= EFI_IFR_FLAG_DEFAULT; + } + + IfrOptionList[Index].OptionString = NULL; + + CreateOneOfOpCode ( + (UINT16) BOOT_NEXT_QUESTION_ID, + (UINT8) 2, + STRING_TOKEN (STR_BOOT_NEXT), + STRING_TOKEN (STR_BOOT_NEXT_HELP), + IfrOptionList, + (UINTN) (NumberOfOptions + 1), + Location + ); + Location = Location + (NumberOfOptions + 2) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + UpdateData->DataCount += 3; + SafeFreePool (IfrOptionList); + IfrOptionList = NULL; + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateTimeOutPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT8 *Location; + UINT16 BootTimeOut; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + + BootTimeOut = BdsLibGetTimeout (); + + CreateNumericOpCode ( + (UINT16) BOOT_TIME_OUT_QUESTION_ID, + (UINT8) 2, + STRING_TOKEN (STR_NUM_AUTO_BOOT), + STRING_TOKEN (STR_HLP_AUTO_BOOT), + 0, + 65535, + 0, + 10, + 0, + 0, + Location + ); + + CallbackData->BmmFakeNvData->BootTimeOut = (UINT16) BootTimeOut; + UpdateData->DataCount++; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdateTerminalPage ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINT16 Index; + UINT8 *Location; + UINT8 CheckFlags; + IFR_OPTION *IfrOptionList; + BM_MENU_ENTRY *NewMenuEntry; + BM_TERMINAL_CONTEXT *NewTerminalContext; + + ZeroMem (UpdateData, UPDATE_DATA_SIZE); + Location = (UINT8 *) &UpdateData->Data; + UpdatePageStart (CallbackData, &Location); + + NewMenuEntry = BOpt_GetMenuEntry ( + &TerminalMenu, + CallbackData->CurrentTerminal + ); + + if (!NewMenuEntry) { + return ; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 19); + if (!IfrOptionList) { + return ; + } + + for (Index = 0; Index < 19; Index++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + if (NewTerminalContext->BaudRate == (UINT64) (BaudRateList[Index].Value)) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + NewTerminalContext->BaudRateIndex = (UINT8) Index; + CallbackData->BmmFakeNvData->COMBaudRate = NewTerminalContext->BaudRateIndex; + } + + IfrOptionList[Index].Flags = CheckFlags; + IfrOptionList[Index].Key = KEY_VALUE_COM_SET_BAUD_RATE; + IfrOptionList[Index].StringToken = BaudRateList[Index].StringToken; + IfrOptionList[Index].Value = Index; + } + + CreateOneOfOpCode ( + (UINT16) COM_BAUD_RATE_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_COM_BAUD_RATE), + STRING_TOKEN (STR_COM_BAUD_RATE), + IfrOptionList, + 19, + Location + ); + + Location = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index); + UpdateData->DataCount += 2; + + SafeFreePool (IfrOptionList); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 4); + if (!IfrOptionList) { + return ; + } + + for (Index = 0; Index < 4; Index++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + + if (NewTerminalContext->DataBits == DataBitsList[Index].Value) { + NewTerminalContext->DataBitsIndex = (UINT8) Index; + CallbackData->BmmFakeNvData->COMDataRate = NewTerminalContext->DataBitsIndex; + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + } + + IfrOptionList[Index].Flags = CheckFlags; + IfrOptionList[Index].Key = KEY_VALUE_COM_SET_DATA_BITS; + IfrOptionList[Index].StringToken = DataBitsList[Index].StringToken; + IfrOptionList[Index].Value = Index; + } + + CreateOneOfOpCode ( + (UINT16) COM_DATA_RATE_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_COM_DATA_BITS), + STRING_TOKEN (STR_COM_DATA_BITS), + IfrOptionList, + 4, + Location + ); + + Location = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index); + UpdateData->DataCount += 2; + + SafeFreePool (IfrOptionList); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 5); + if (!IfrOptionList) { + return ; + } + + for (Index = 0; Index < 5; Index++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + if (NewTerminalContext->Parity == ParityList[Index].Value) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + NewTerminalContext->ParityIndex = (UINT8) Index; + CallbackData->BmmFakeNvData->COMParity = NewTerminalContext->ParityIndex; + } + + IfrOptionList[Index].Flags = CheckFlags; + IfrOptionList[Index].Key = KEY_VALUE_COM_SET_PARITY; + IfrOptionList[Index].StringToken = ParityList[Index].StringToken; + IfrOptionList[Index].Value = Index; + } + + CreateOneOfOpCode ( + (UINT16) COM_PARITY_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_COM_PARITY), + STRING_TOKEN (STR_COM_PARITY), + IfrOptionList, + 5, + Location + ); + + Location = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index); + UpdateData->DataCount += 2; + + SafeFreePool (IfrOptionList); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 3); + if (!IfrOptionList) { + return ; + } + + for (Index = 0; Index < 3; Index++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + if (NewTerminalContext->StopBits == StopBitsList[Index].Value) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + NewTerminalContext->StopBitsIndex = (UINT8) Index; + CallbackData->BmmFakeNvData->COMStopBits = NewTerminalContext->StopBitsIndex; + } + + IfrOptionList[Index].Flags = CheckFlags; + IfrOptionList[Index].Key = KEY_VALUE_COM_SET_STOP_BITS; + IfrOptionList[Index].StringToken = StopBitsList[Index].StringToken; + IfrOptionList[Index].Value = Index; + } + + CreateOneOfOpCode ( + (UINT16) COM_STOP_BITS_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_COM_STOP_BITS), + STRING_TOKEN (STR_COM_STOP_BITS), + IfrOptionList, + 3, + Location + ); + + Location = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index); + UpdateData->DataCount += 2; + + SafeFreePool (IfrOptionList); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * 4); + if (!IfrOptionList) { + return ; + } + + for (Index = 0; Index < 4; Index++) { + CheckFlags = EFI_IFR_FLAG_INTERACTIVE; + if (NewTerminalContext->TerminalType == Index) { + CheckFlags |= EFI_IFR_FLAG_DEFAULT; + CallbackData->BmmFakeNvData->COMTerminalType = NewTerminalContext->TerminalType; + } + + IfrOptionList[Index].Flags = CheckFlags; + IfrOptionList[Index].Key = KEY_VALUE_COM_SET_TERMI_TYPE; + IfrOptionList[Index].StringToken = (STRING_REF) TerminalType[Index]; + IfrOptionList[Index].Value = Index; + } + + CreateOneOfOpCode ( + (UINT16) COM_TERMINAL_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_COM_TERMI_TYPE), + STRING_TOKEN (STR_COM_TERMI_TYPE), + IfrOptionList, + 4, + Location + ); + + Location = Location + (Index + 1) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT8) (UpdateData->DataCount + Index); + UpdateData->DataCount += 2; + + SafeFreePool (IfrOptionList); + + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_SAVE_AND_EXIT, + Location + ); + + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount++; + + CreateGotoOpCode ( + FORM_MAIN_ID, + STRING_TOKEN (STR_NO_SAVE_AND_EXIT), + STRING_TOKEN (STR_NULL_STRING), + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, + KEY_VALUE_NO_SAVE_AND_EXIT, + Location + ); + + UpdateData->DataCount++; + + CallbackData->Hii->UpdateForm ( + CallbackData->Hii, + CallbackData->BmmHiiHandle, + (EFI_FORM_LABEL) FORM_CON_COM_SETUP_ID, + TRUE, + UpdateData + ); + +} + +VOID +UpdatePageBody ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + CleanUpPage (UpdatePageId, CallbackData); + switch (UpdatePageId) { + case FORM_CON_IN_ID: + UpdateConsolePage (UpdatePageId, &ConsoleInpMenu, CallbackData); + break; + + case FORM_CON_OUT_ID: + UpdateConsolePage (UpdatePageId, &ConsoleOutMenu, CallbackData); + break; + + case FORM_CON_ERR_ID: + UpdateConsolePage (UpdatePageId, &ConsoleErrMenu, CallbackData); + break; + + case FORM_BOOT_CHG_ID: + UpdateOrderPage (UpdatePageId, &BootOptionMenu, CallbackData); + break; + + case FORM_DRV_CHG_ID: + UpdateOrderPage (UpdatePageId, &DriverOptionMenu, CallbackData); + break; + + default: + break; + } +} + +VOID * +GetLegacyBootOptionVar ( + IN UINTN DeviceType, + OUT UINTN *OptionIndex, + OUT UINTN *OptionSize + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + VOID *OptionBuffer; + UINTN OrderSize; + UINTN Index; + UINT32 Attribute; + UINT16 *OrderBuffer; + CHAR16 StrTemp[100]; + UINT16 FilePathSize; + CHAR16 *Description; + UINT8 *Ptr; + UINT8 *OptionalData; + + // + // Get Boot Option number from the size of BootOrder + // + OrderBuffer = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &OrderSize + ); + + for (Index = 0; Index < OrderSize / sizeof (UINT16); Index++) { + UnicodeSPrint (StrTemp, 100, L"Boot%04x", OrderBuffer[Index]); + OptionBuffer = BdsLibGetVariableAndSize ( + StrTemp, + &gEfiGlobalVariableGuid, + OptionSize + ); + if (NULL == OptionBuffer) { + continue; + } + + Ptr = (UINT8 *) OptionBuffer; + Attribute = *(UINT32 *) Ptr; + Ptr += sizeof (UINT32); + + FilePathSize = *(UINT16 *) Ptr; + Ptr += sizeof (UINT16); + + Description = (CHAR16 *) Ptr; + Ptr += StrSize ((CHAR16 *) Ptr); + + // + // Now Ptr point to Device Path + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) Ptr; + Ptr += FilePathSize; + + // + // Now Ptr point to Optional Data + // + OptionalData = Ptr; + + if ((DeviceType == ((BBS_TABLE *) OptionalData)->DeviceType) && + (BBS_DEVICE_PATH == DevicePath->Type) && + (BBS_BBS_DP == DevicePath->SubType) + ) { + *OptionIndex = OrderBuffer[Index]; + SafeFreePool (OrderBuffer); + return OptionBuffer; + } else { + SafeFreePool (OptionBuffer); + } + } + + SafeFreePool (OrderBuffer); + return NULL; +} + +VOID +UpdateSetLegacyDeviceOrderPage ( + IN UINT16 UpdatePageId, + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder; + BM_MENU_OPTION *OptionMenu; + BM_MENU_ENTRY *NewMenuEntry; + IFR_OPTION *IfrOptionList; + STRING_REF StrRef; + STRING_REF StrRefHelp; + BBS_TYPE BbsType; + UINTN VarSize; + UINTN Pos; + UINTN Bit; + UINT16 Index; + UINT16 Index2; + UINT16 Key; + CHAR16 String[100]; + CHAR16 *TypeStr; + CHAR16 *TypeStrHelp; + UINT16 VarDevOrder; + UINT8 *Location; + UINT8 *VarData; + UINT8 *OriginalPtr; + UINT8 *LegacyOrder; + UINT8 *OldData; + UINT8 *DisMap; + + OptionMenu = NULL; + Key = 0; + StrRef = 0; + StrRefHelp = 0; + TypeStr = NULL; + TypeStrHelp = NULL; + BbsType = BBS_FLOPPY; + LegacyOrder = NULL; + OldData = NULL; + DisMap = NULL; + + Location = (UINT8 *) &UpdateData->Data; + CallbackData->BmmAskSaveOrNot = TRUE; + + UpdatePageStart (CallbackData, &Location); + + DisMap = CallbackData->BmmOldFakeNVData.DisableMap; + + SetMem (DisMap, 32, 0); + // + // Create oneof option list + // + switch (UpdatePageId) { + case FORM_SET_FD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu; + Key = LEGACY_FD_QUESTION_ID; + TypeStr = StrFloppy; + TypeStrHelp = StrFloppyHelp; + BbsType = BBS_FLOPPY; + LegacyOrder = CallbackData->BmmFakeNvData->LegacyFD; + OldData = CallbackData->BmmOldFakeNVData.LegacyFD; + break; + + case FORM_SET_HD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu; + Key = LEGACY_HD_QUESTION_ID; + TypeStr = StrHardDisk; + TypeStrHelp = StrHardDiskHelp; + BbsType = BBS_HARDDISK; + LegacyOrder = CallbackData->BmmFakeNvData->LegacyHD; + OldData = CallbackData->BmmOldFakeNVData.LegacyHD; + break; + + case FORM_SET_CD_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu; + Key = LEGACY_CD_QUESTION_ID; + TypeStr = StrCDROM; + TypeStrHelp = StrCDROMHelp; + BbsType = BBS_CDROM; + LegacyOrder = CallbackData->BmmFakeNvData->LegacyCD; + OldData = CallbackData->BmmOldFakeNVData.LegacyCD; + break; + + case FORM_SET_NET_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu; + Key = LEGACY_NET_QUESTION_ID; + TypeStr = StrNET; + TypeStrHelp = StrNETHelp; + BbsType = BBS_EMBED_NETWORK; + LegacyOrder = CallbackData->BmmFakeNvData->LegacyNET; + OldData = CallbackData->BmmOldFakeNVData.LegacyNET; + break; + + case FORM_SET_BEV_ORDER_ID: + OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu; + Key = LEGACY_BEV_QUESTION_ID; + TypeStr = StrBEV; + TypeStrHelp = StrBEVHelp; + BbsType = BBS_BEV_DEVICE; + LegacyOrder = CallbackData->BmmFakeNvData->LegacyBEV; + OldData = CallbackData->BmmOldFakeNVData.LegacyBEV; + break; + + } + + CreateMenuStringToken (CallbackData, CallbackData->BmmHiiHandle, OptionMenu); + + IfrOptionList = AllocateZeroPool (sizeof (IFR_OPTION) * (OptionMenu->MenuNumber + 1)); + if (NULL == IfrOptionList) { + return ; + } + + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index); + IfrOptionList[Index].Flags = EFI_IFR_FLAG_INTERACTIVE; + if (0 == Index) { + IfrOptionList[Index].Flags |= EFI_IFR_FLAG_DEFAULT; + } + + IfrOptionList[Index].Key = Key; + IfrOptionList[Index].StringToken = NewMenuEntry->DisplayStringToken; + IfrOptionList[Index].Value = (UINT16) ((BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext)->Index; + IfrOptionList[Index].OptionString = NULL; + } + // + // for item "Disabled" + // + IfrOptionList[Index].Flags = EFI_IFR_FLAG_INTERACTIVE; + IfrOptionList[Index].Key = Key; + IfrOptionList[Index].StringToken = STRING_TOKEN (STR_DISABLE_LEGACY_DEVICE); + IfrOptionList[Index].Value = 0xFF; + IfrOptionList[Index].OptionString = NULL; + + // + // Get Device Order from variable + // + VarData = BdsLibGetVariableAndSize ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + &VarSize + ); + + if (NULL != VarData) { + OriginalPtr = VarData; + DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData; + while (VarData < VarData + VarSize) { + if (DevOrder->BbsType == BbsType) { + break; + } + + VarData += sizeof (BBS_TYPE); + VarData += *(UINT16 *) VarData; + DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData; + } + // + // Create oneof tag here for FD/HD/CD #1 #2 + // + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + for (Index2 = 0; Index2 <= OptionMenu->MenuNumber; Index2++) { + IfrOptionList[Index2].Key = (UINT16) (Key + Index); + } + // + // Create the string for oneof tag + // + UnicodeSPrint (String, sizeof (String), TypeStr, Index); + StrRef = 0; + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + CallbackData->BmmHiiHandle, + &StrRef, + String + ); + + UnicodeSPrint (String, sizeof (String), TypeStrHelp, Index); + StrRefHelp = 0; + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + CallbackData->BmmHiiHandle, + &StrRefHelp, + String + ); + + CreateOneOfOpCode ( + (UINT16) (Key + Index), + (UINT8) 1, + StrRef, + StrRefHelp, + IfrOptionList, + OptionMenu->MenuNumber + 1, + Location + ); + + VarDevOrder = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index * sizeof (UINT16)); + + if (0xFF00 == (VarDevOrder & 0xFF00)) { + LegacyOrder[Index] = 0xFF; + Pos = (VarDevOrder & 0xFF) / 8; + Bit = 7 - ((VarDevOrder & 0xFF) % 8); + DisMap[Pos] |= (UINT8) (1 << Bit); + } else { + LegacyOrder[Index] = (UINT8) (VarDevOrder & 0xFF); + } + + Location = Location + (OptionMenu->MenuNumber + 2) * ((EFI_IFR_OP_HEADER *) Location)->Length; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + UpdateData->DataCount = (UINT16) (UpdateData->DataCount + (OptionMenu->MenuNumber + 3)); + } + } + + CopyMem ( + OldData, + LegacyOrder, + 100 + ); + + if (IfrOptionList != NULL) { + SafeFreePool (IfrOptionList); + IfrOptionList = NULL; + } + + UpdatePageEnd (CallbackData, Location); +} + +VOID +UpdatePageId ( + BMM_CALLBACK_DATA *Private, + UINT16 NewPageId + ) +{ + UINT16 FileOptionMask; + + FileOptionMask = (UINT16) (FILE_OPTION_MASK & NewPageId); + + if ((NewPageId < FILE_OPTION_OFFSET) && (NewPageId >= HANDLE_OPTION_OFFSET)) { + // + // If we select a handle to add driver option, advance to the add handle description page. + // + NewPageId = FORM_DRV_ADD_HANDLE_DESC_ID; + } else if ((NewPageId == KEY_VALUE_SAVE_AND_EXIT) || (NewPageId == KEY_VALUE_NO_SAVE_AND_EXIT)) { + // + // Return to main page after "Save Changes" or "Discard Changes". + // + NewPageId = FORM_MAIN_ID; + } + + if ((NewPageId > 0) && (NewPageId < MAXIMUM_FORM_ID)) { + Private->BmmPreviousPageId = Private->BmmCurrentPageId; + Private->BmmCurrentPageId = NewPageId; + } +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/Variable.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/Variable.c new file mode 100644 index 0000000000..d0c5c9bafb --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/Variable.c @@ -0,0 +1,1279 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Variable.c + +Abstract: + + Variable operation that will be used by bootmaint + +--*/ + +#include "Generic/Bds.h" +#include "bootmaint.h" +#include "bdsplatform.h" + +EFI_STATUS +Var_DelBootOption ( + VOID + ) +/*++ + +Routine Description: + Delete Boot Option that represent a Deleted state in BootOptionMenu. + After deleting this boot option, call Var_ChangeBootOrder to + make sure BootOrder is in valid state. + +Arguments: + LoadOption -- Pointer to the boot option that to be deleted + +Returns: + EFI_SUCCESS + Others + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + + UINT16 BootString[10]; + EFI_STATUS Status; + UINTN Index; + UINTN Index2; + + Status = EFI_SUCCESS; + Index2 = 0; + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, (Index - Index2)); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (!NewLoadContext->Deleted) { + continue; + } + + UnicodeSPrint ( + BootString, + sizeof (BootString), + L"Boot%04x", + NewMenuEntry->OptionNumber + ); + + EfiLibDeleteVariable (BootString, &gEfiGlobalVariableGuid); + Index2++; + // + // If current Load Option is the same as BootNext, + // must delete BootNext in order to make sure + // there will be no panic on next boot + // + if (NewLoadContext->IsBootNext) { + EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid); + } + + RemoveEntryList (&NewMenuEntry->Link); + BOpt_DestroyMenuEntry (NewMenuEntry); + NewMenuEntry = NULL; + } + + BootOptionMenu.MenuNumber -= Index2; + + Status = Var_ChangeBootOrder (); + return Status; +} + +EFI_STATUS +Var_ChangeBootOrder ( + VOID + ) +/*++ + +Routine Description: + After any operation on Boot####, there will be a discrepancy in BootOrder. + Since some are missing but in BootOrder, while some are present but are + not reflected by BootOrder. Then a function rebuild BootOrder from + scratch by content from BootOptionMenu is needed. + +Arguments: + +Returns: + EFI_SUCCESS + Others + +--*/ +{ + + EFI_STATUS Status; + BM_MENU_ENTRY *NewMenuEntry; + UINT16 *BootOrderList; + UINT16 *BootOrderListPtr; + UINTN BootOrderListSize; + UINTN Index; + + BootOrderList = NULL; + BootOrderListSize = 0; + + // + // First check whether BootOrder is present in current configuration + // + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + + // + // If exists, delete it to hold new BootOrder + // + if (BootOrderList) { + EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + SafeFreePool (BootOrderList); + BootOrderList = NULL; + } + // + // Maybe here should be some check method to ensure that + // no new added boot options will be added + // but the setup engine now will give only one callback + // that is to say, user are granted only one chance to + // decide whether the boot option will be added or not + // there should be no indictor to show whether this + // is a "new" boot option + // + BootOrderListSize = BootOptionMenu.MenuNumber; + + if (BootOrderListSize > 0) { + BootOrderList = AllocateZeroPool (BootOrderListSize * sizeof (UINT16)); + ASSERT (BootOrderList != NULL); + BootOrderListPtr = BootOrderList; + + // + // Get all current used Boot#### from BootOptionMenu. + // OptionNumber in each BM_LOAD_OPTION is really its + // #### value. + // + for (Index = 0; Index < BootOrderListSize; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + *BootOrderList = (UINT16) NewMenuEntry->OptionNumber; + BootOrderList++; + } + + BootOrderList = BootOrderListPtr; + + // + // After building the BootOrderList, write it back + // + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderListSize * sizeof (UINT16), + BootOrderList + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + return EFI_SUCCESS; +} + +EFI_STATUS +Var_DelDriverOption ( + VOID + ) +/*++ + +Routine Description: + Delete Load Option that represent a Deleted state in BootOptionMenu. + After deleting this Driver option, call Var_ChangeDriverOrder to + make sure DriverOrder is in valid state. + +Arguments: + LoadOption -- Pointer to the Driver option that to be deleted + +Returns: + EFI_SUCCESS + Others + +--*/ +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + + UINT16 DriverString[12]; + EFI_STATUS Status; + UINTN Index; + UINTN Index2; + + Status = EFI_SUCCESS; + Index2 = 0; + for (Index = 0; Index < DriverOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, (Index - Index2)); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + if (!NewLoadContext->Deleted) { + continue; + } + + UnicodeSPrint ( + DriverString, + sizeof (DriverString), + L"Driver%04x", + NewMenuEntry->OptionNumber + ); + + EfiLibDeleteVariable (DriverString, &gEfiGlobalVariableGuid); + Index2++; + + RemoveEntryList (&NewMenuEntry->Link); + BOpt_DestroyMenuEntry (NewMenuEntry); + NewMenuEntry = NULL; + } + + DriverOptionMenu.MenuNumber -= Index2; + + Status = Var_ChangeDriverOrder (); + return Status; +} + +EFI_STATUS +Var_ChangeDriverOrder ( + VOID + ) +/*++ + +Routine Description: + After any operation on Driver####, there will be a discrepancy in + DriverOrder. Since some are missing but in DriverOrder, while some + are present but are not reflected by DriverOrder. Then a function + rebuild DriverOrder from scratch by content from DriverOptionMenu is + needed. + +Arguments: + +Returns: + EFI_SUCCESS + Others + +--*/ +{ + EFI_STATUS Status; + BM_MENU_ENTRY *NewMenuEntry; + UINT16 *DriverOrderList; + UINT16 *DriverOrderListPtr; + UINTN DriverOrderListSize; + UINTN Index; + + DriverOrderList = NULL; + DriverOrderListSize = 0; + + // + // First check whether DriverOrder is present in current configuration + // + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + + // + // If exists, delete it to hold new DriverOrder + // + if (DriverOrderList) { + EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); + SafeFreePool (DriverOrderList); + DriverOrderList = NULL; + } + + DriverOrderListSize = DriverOptionMenu.MenuNumber; + + if (DriverOrderListSize > 0) { + DriverOrderList = AllocateZeroPool (DriverOrderListSize * sizeof (UINT16)); + ASSERT (DriverOrderList != NULL); + DriverOrderListPtr = DriverOrderList; + + // + // Get all current used Driver#### from DriverOptionMenu. + // OptionNumber in each BM_LOAD_OPTION is really its + // #### value. + // + for (Index = 0; Index < DriverOrderListSize; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&DriverOptionMenu, Index); + *DriverOrderList = (UINT16) NewMenuEntry->OptionNumber; + DriverOrderList++; + } + + DriverOrderList = DriverOrderListPtr; + + // + // After building the DriverOrderList, write it back + // + Status = gRT->SetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + DriverOrderListSize * sizeof (UINT16), + DriverOrderList + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + return EFI_SUCCESS; +} + +VOID +Var_UpdateAllConsoleOption ( + VOID + ) +{ + EFI_DEVICE_PATH_PROTOCOL *OutDevicePath; + EFI_DEVICE_PATH_PROTOCOL *InpDevicePath; + EFI_DEVICE_PATH_PROTOCOL *ErrDevicePath; + EFI_STATUS Status; + + OutDevicePath = EfiLibGetVariable (L"ConOut", &gEfiGlobalVariableGuid); + InpDevicePath = EfiLibGetVariable (L"ConIn", &gEfiGlobalVariableGuid); + ErrDevicePath = EfiLibGetVariable (L"ErrOut", &gEfiGlobalVariableGuid); + if (OutDevicePath) { + ChangeVariableDevicePath (OutDevicePath); + Status = gRT->SetVariable ( + L"ConOut", + &gEfiGlobalVariableGuid, + VAR_FLAG, + GetDevicePathSize (OutDevicePath), + OutDevicePath + ); + ASSERT (!EFI_ERROR (Status)); + } + + if (InpDevicePath) { + ChangeVariableDevicePath (InpDevicePath); + Status = gRT->SetVariable ( + L"ConIn", + &gEfiGlobalVariableGuid, + VAR_FLAG, + GetDevicePathSize (InpDevicePath), + InpDevicePath + ); + ASSERT (!EFI_ERROR (Status)); + } + + if (ErrDevicePath) { + ChangeVariableDevicePath (ErrDevicePath); + Status = gRT->SetVariable ( + L"ErrOut", + &gEfiGlobalVariableGuid, + VAR_FLAG, + GetDevicePathSize (ErrDevicePath), + ErrDevicePath + ); + ASSERT (!EFI_ERROR (Status)); + } +} + +EFI_STATUS +Var_UpdateConsoleOption ( + IN UINT16 *ConsoleName, + IN BM_MENU_OPTION *ConsoleMenu, + IN UINT16 UpdatePageId + ) +{ + EFI_DEVICE_PATH_PROTOCOL *ConDevicePath; + BM_MENU_ENTRY *NewMenuEntry; + BM_CONSOLE_CONTEXT *NewConsoleContext; + BM_TERMINAL_CONTEXT *NewTerminalContext; + EFI_STATUS Status; + VENDOR_DEVICE_PATH Vendor; + EFI_DEVICE_PATH_PROTOCOL *TerminalDevicePath; + UINTN Index; + UINT16 *Temp; + + ConDevicePath = EfiLibGetVariable (ConsoleName, &gEfiGlobalVariableGuid); + if (ConDevicePath != NULL) { + EfiLibDeleteVariable (ConsoleName, &gEfiGlobalVariableGuid); + SafeFreePool (ConDevicePath); + ConDevicePath = NULL; + }; + + // + // First add all console input device to it from console input menu + // + for (Index = 0; Index < ConsoleMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (ConsoleMenu, Index); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewConsoleContext = (BM_CONSOLE_CONTEXT *) NewMenuEntry->VariableContext; + if (NewConsoleContext->IsActive) { + ConDevicePath = AppendDevicePathInstance ( + ConDevicePath, + NewConsoleContext->DevicePath + ); + } + } + + for (Index = 0; Index < TerminalMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&TerminalMenu, Index); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewTerminalContext = (BM_TERMINAL_CONTEXT *) NewMenuEntry->VariableContext; + if ((NewTerminalContext->IsConIn && (UpdatePageId == FORM_CON_IN_ID)) || + (NewTerminalContext->IsConOut && (UpdatePageId == FORM_CON_OUT_ID)) || + (NewTerminalContext->IsStdErr && (UpdatePageId == FORM_CON_ERR_ID)) + ) { + Vendor.Header.Type = MESSAGING_DEVICE_PATH; + Vendor.Header.SubType = MSG_VENDOR_DP; + CopyMem ( + &Vendor.Guid, + &Guid[NewTerminalContext->TerminalType], + sizeof (EFI_GUID) + ); + SetDevicePathNodeLength (&Vendor.Header, sizeof (VENDOR_DEVICE_PATH)); + TerminalDevicePath = AppendDevicePathNode ( + NewTerminalContext->DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Vendor + ); + ChangeTerminalDevicePath (TerminalDevicePath, TRUE); + Temp = DevicePathToStr (TerminalDevicePath); + ConDevicePath = AppendDevicePathInstance ( + ConDevicePath, + TerminalDevicePath + ); + } + } + + if (ConDevicePath) { + Status = gRT->SetVariable ( + ConsoleName, + &gEfiGlobalVariableGuid, + VAR_FLAG, + GetDevicePathSize (ConDevicePath), + ConDevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +Var_UpdateConsoleInpOption ( + VOID + ) +{ + return Var_UpdateConsoleOption (L"ConIn", &ConsoleInpMenu, FORM_CON_IN_ID); +} + +EFI_STATUS +Var_UpdateConsoleOutOption ( + VOID + ) +{ + return Var_UpdateConsoleOption (L"ConOut", &ConsoleOutMenu, FORM_CON_OUT_ID); +} + +EFI_STATUS +Var_UpdateErrorOutOption ( + VOID + ) +{ + return Var_UpdateConsoleOption (L"ErrOut", &ConsoleErrMenu, FORM_CON_ERR_ID); +} + +EFI_STATUS +Var_UpdateDriverOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN EFI_HII_HANDLE HiiHandle, + IN UINT16 *DescriptionData, + IN UINT16 *OptionalData, + IN UINT8 ForceReconnect + ) +{ + UINT16 Index; + UINT16 *DriverOrderList; + UINT16 *NewDriverOrderList; + UINT16 DriverString[12]; + UINTN DriverOrderListSize; + VOID *Buffer; + UINTN BufferSize; + UINT8 *Ptr; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + BOOLEAN OptionalDataExist; + EFI_STATUS Status; + + OptionalDataExist = FALSE; + + Index = BOpt_GetDriverOptionNumber (); + UnicodeSPrint ( + DriverString, + sizeof (DriverString), + L"Driver%04x", + Index + ); + + if (*DescriptionData == 0x0000) { + StrCpy (DescriptionData, DriverString); + } + + BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescriptionData) + GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + if (*OptionalData != 0x0000) { + OptionalDataExist = TRUE; + BufferSize += StrSize (OptionalData); + } + + Buffer = AllocateZeroPool (BufferSize); + if (NULL == Buffer) { + return EFI_OUT_OF_RESOURCES; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = FALSE; + NewLoadContext->LoadOptionSize = BufferSize; + Ptr = (UINT8 *) Buffer; + NewLoadContext->LoadOption = Ptr; + *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE | (ForceReconnect << 1); + NewLoadContext->Attributes = *((UINT32 *) Ptr); + NewLoadContext->IsActive = TRUE; + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + Ptr += sizeof (UINT32); + *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); + + Ptr += sizeof (UINT16); + CopyMem ( + Ptr, + DescriptionData, + StrSize (DescriptionData) + ); + + NewLoadContext->Description = AllocateZeroPool (StrSize (DescriptionData)); + ASSERT (NewLoadContext->Description != NULL); + NewMenuEntry->DisplayString = NewLoadContext->Description; + CopyMem ( + NewLoadContext->Description, + (VOID *) Ptr, + StrSize (DescriptionData) + ); + + Ptr += StrSize (DescriptionData); + CopyMem ( + Ptr, + CallbackData->LoadContext->FilePathList, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); + ASSERT (NewLoadContext->FilePathList != NULL); + + CopyMem ( + NewLoadContext->FilePathList, + (VOID *) Ptr, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->OptionNumber = Index; + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionStrDepository + ); + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + HiiHandle, + &NewMenuEntry->DisplayStringToken, + NewMenuEntry->DisplayString + ); + + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + DriverOptionHelpStrDepository + ); + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + HiiHandle, + &NewMenuEntry->HelpStringToken, + NewMenuEntry->HelpString + ); + + if (OptionalDataExist) { + Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + CopyMem ( + Ptr, + OptionalData, + StrSize (OptionalData) + ); + } + + Status = gRT->SetVariable ( + DriverString, + &gEfiGlobalVariableGuid, + VAR_FLAG, + BufferSize, + Buffer + ); + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + NewDriverOrderList = AllocateZeroPool (DriverOrderListSize + sizeof (UINT16)); + ASSERT (NewDriverOrderList != NULL); + CopyMem (NewDriverOrderList, DriverOrderList, DriverOrderListSize); + NewDriverOrderList[DriverOrderListSize / sizeof (UINT16)] = Index; + if (DriverOrderList != NULL) { + EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); + } + + Status = gRT->SetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + DriverOrderListSize + sizeof (UINT16), + NewDriverOrderList + ); + SafeFreePool (DriverOrderList); + DriverOrderList = NULL; + SafeFreePool (NewDriverOrderList); + NewDriverOrderList = NULL; + InsertTailList (&DriverOptionMenu.Head, &NewMenuEntry->Link); + DriverOptionMenu.MenuNumber++; + + *DescriptionData = 0x0000; + *OptionalData = 0x0000; + return EFI_SUCCESS; +} + +EFI_STATUS +Var_UpdateBootOption ( + IN BMM_CALLBACK_DATA *CallbackData, + IN FILE_EXPLORER_NV_DATA *NvRamMap + ) +{ + UINT16 *BootOrderList; + UINT16 *NewBootOrderList; + UINTN BootOrderListSize; + UINT16 BootString[10]; + VOID *Buffer; + UINTN BufferSize; + UINT8 *Ptr; + UINT16 Index; + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + BOOLEAN OptionalDataExist; + EFI_STATUS Status; + + OptionalDataExist = FALSE; + + Index = BOpt_GetBootOptionNumber (); + UnicodeSPrint (BootString, sizeof (BootString), L"Boot%04x", Index); + + if (NvRamMap->DescriptionData[0] == 0x0000) { + StrCpy (NvRamMap->DescriptionData, BootString); + } + + BufferSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (NvRamMap->DescriptionData) + GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + if (NvRamMap->OptionalData[0] != 0x0000) { + OptionalDataExist = TRUE; + BufferSize += StrSize (NvRamMap->OptionalData); + } + + Buffer = AllocateZeroPool (BufferSize); + if (NULL == Buffer) { + return EFI_OUT_OF_RESOURCES; + } + + NewMenuEntry = BOpt_CreateMenuEntry (BM_LOAD_CONTEXT_SELECT); + if (NULL == NewMenuEntry) { + return EFI_OUT_OF_RESOURCES; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->Deleted = FALSE; + NewLoadContext->LoadOptionSize = BufferSize; + Ptr = (UINT8 *) Buffer; + NewLoadContext->LoadOption = Ptr; + *((UINT32 *) Ptr) = LOAD_OPTION_ACTIVE; + NewLoadContext->Attributes = *((UINT32 *) Ptr); + NewLoadContext->IsActive = TRUE; + NewLoadContext->ForceReconnect = (BOOLEAN) (NewLoadContext->Attributes & LOAD_OPTION_FORCE_RECONNECT); + + Ptr += sizeof (UINT32); + *((UINT16 *) Ptr) = (UINT16) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + NewLoadContext->FilePathListLength = *((UINT16 *) Ptr); + Ptr += sizeof (UINT16); + + CopyMem ( + Ptr, + NvRamMap->DescriptionData, + StrSize (NvRamMap->DescriptionData) + ); + + NewLoadContext->Description = AllocateZeroPool (StrSize (NvRamMap->DescriptionData)); + ASSERT (NewLoadContext->Description != NULL); + + NewMenuEntry->DisplayString = NewLoadContext->Description; + CopyMem ( + NewLoadContext->Description, + (VOID *) Ptr, + StrSize (NvRamMap->DescriptionData) + ); + + Ptr += StrSize (NvRamMap->DescriptionData); + CopyMem ( + Ptr, + CallbackData->LoadContext->FilePathList, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewLoadContext->FilePathList = AllocateZeroPool (GetDevicePathSize (CallbackData->LoadContext->FilePathList)); + ASSERT (NewLoadContext->FilePathList != NULL); + + CopyMem ( + NewLoadContext->FilePathList, + (VOID *) Ptr, + GetDevicePathSize (CallbackData->LoadContext->FilePathList) + ); + + NewMenuEntry->HelpString = DevicePathToStr (NewLoadContext->FilePathList); + NewMenuEntry->OptionNumber = Index; + NewMenuEntry->DisplayStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionStrDepository + ); + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + CallbackData->FeHiiHandle, + &NewMenuEntry->DisplayStringToken, + NewMenuEntry->DisplayString + ); + + NewMenuEntry->HelpStringToken = GetStringTokenFromDepository ( + CallbackData, + BootOptionHelpStrDepository + ); + + CallbackData->Hii->NewString ( + CallbackData->Hii, + NULL, + CallbackData->FeHiiHandle, + &NewMenuEntry->HelpStringToken, + NewMenuEntry->HelpString + ); + + if (OptionalDataExist) { + Ptr += (UINT8) GetDevicePathSize (CallbackData->LoadContext->FilePathList); + + CopyMem (Ptr, NvRamMap->OptionalData, StrSize (NvRamMap->OptionalData)); + } + + Status = gRT->SetVariable ( + BootString, + &gEfiGlobalVariableGuid, + VAR_FLAG, + BufferSize, + Buffer + ); + + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + + NewBootOrderList = AllocateZeroPool (BootOrderListSize + sizeof (UINT16)); + ASSERT (NewBootOrderList != NULL); + CopyMem (NewBootOrderList, BootOrderList, BootOrderListSize); + NewBootOrderList[BootOrderListSize / sizeof (UINT16)] = Index; + + if (BootOrderList != NULL) { + EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + } + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderListSize + sizeof (UINT16), + NewBootOrderList + ); + + SafeFreePool (BootOrderList); + BootOrderList = NULL; + SafeFreePool (NewBootOrderList); + NewBootOrderList = NULL; + InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); + BootOptionMenu.MenuNumber++; + + NvRamMap->DescriptionData[0] = 0x0000; + NvRamMap->OptionalData[0] = 0x0000; + return EFI_SUCCESS; +} + +EFI_STATUS +Var_UpdateBootNext ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + BM_MENU_ENTRY *NewMenuEntry; + BM_LOAD_CONTEXT *NewLoadContext; + BMM_FAKE_NV_DATA *CurrentFakeNVMap; + UINT16 Index; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + CurrentFakeNVMap = CallbackData->BmmFakeNvData; + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (&BootOptionMenu, Index); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + NewLoadContext->IsBootNext = FALSE; + } + + if (CurrentFakeNVMap->BootNext == BootOptionMenu.MenuNumber) { + EfiLibDeleteVariable (L"BootNext", &gEfiGlobalVariableGuid); + return EFI_SUCCESS; + } + + NewMenuEntry = BOpt_GetMenuEntry ( + &BootOptionMenu, + CurrentFakeNVMap->BootNext + ); + if (NULL == NewMenuEntry) { + return EFI_NOT_FOUND; + } + + NewLoadContext = (BM_LOAD_CONTEXT *) NewMenuEntry->VariableContext; + Status = gRT->SetVariable ( + L"BootNext", + &gEfiGlobalVariableGuid, + VAR_FLAG, + sizeof (UINT16), + &NewMenuEntry->OptionNumber + ); + NewLoadContext->IsBootNext = TRUE; + CallbackData->BmmOldFakeNVData.BootNext = CurrentFakeNVMap->BootNext; + return Status; +} + +EFI_STATUS +Var_UpdateBootOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + EFI_STATUS Status; + UINT16 Index; + UINT16 *BootOrderList; + UINT16 *NewBootOrderList; + UINTN BootOrderListSize; + UINT8 *Map; + + BootOrderList = NULL; + BootOrderListSize = 0; + + // + // First check whether BootOrder is present in current configuration + // + BootOrderList = BdsLibGetVariableAndSize ( + L"BootOrder", + &gEfiGlobalVariableGuid, + &BootOrderListSize + ); + + NewBootOrderList = AllocateZeroPool (BootOrderListSize); + if (!NewBootOrderList) { + return EFI_OUT_OF_RESOURCES; + } + + Map = AllocateZeroPool (BootOrderListSize / sizeof (UINT16)); + if (!Map) { + return EFI_OUT_OF_RESOURCES; + } + // + // If exists, delete it to hold new BootOrder + // + if (BootOrderList) { + EfiLibDeleteVariable (L"BootOrder", &gEfiGlobalVariableGuid); + } + + for (Index = 0; Index < BootOptionMenu.MenuNumber; Index++) { + NewBootOrderList[Index] = CallbackData->BmmFakeNvData->OptionOrder[Index] - 1; + } + + Status = gRT->SetVariable ( + L"BootOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + BootOrderListSize, + NewBootOrderList + ); + SafeFreePool (BootOrderList); + SafeFreePool (NewBootOrderList); + SafeFreePool (Map); + if (EFI_ERROR (Status)) { + return Status; + } + + BOpt_FreeMenu (&BootOptionMenu); + BOpt_GetBootOptions (CallbackData); + + return EFI_SUCCESS; + +} + +EFI_STATUS +Var_UpdateDriverOrder ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + EFI_STATUS Status; + UINT16 Index; + UINT16 *DriverOrderList; + UINT16 *NewDriverOrderList; + UINTN DriverOrderListSize; + + DriverOrderList = NULL; + DriverOrderListSize = 0; + + // + // First check whether DriverOrder is present in current configuration + // + DriverOrderList = BdsLibGetVariableAndSize ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + &DriverOrderListSize + ); + + NewDriverOrderList = AllocateZeroPool (DriverOrderListSize); + + if (!NewDriverOrderList) { + return EFI_OUT_OF_RESOURCES; + } + // + // If exists, delete it to hold new DriverOrder + // + if (DriverOrderList) { + EfiLibDeleteVariable (L"DriverOrder", &gEfiGlobalVariableGuid); + } + + for (Index = 0; Index < DriverOrderListSize; Index++) { + NewDriverOrderList[Index] = CallbackData->BmmFakeNvData->OptionOrder[Index] - 1; + } + + Status = gRT->SetVariable ( + L"DriverOrder", + &gEfiGlobalVariableGuid, + VAR_FLAG, + DriverOrderListSize, + NewDriverOrderList + ); + if (EFI_ERROR (Status)) { + return Status; + } + + SafeFreePool (DriverOrderList); + + BOpt_FreeMenu (&DriverOptionMenu); + BOpt_GetDriverOptions (CallbackData); + return EFI_SUCCESS; +} + +EFI_STATUS +Var_UpdateBBSOption ( + IN BMM_CALLBACK_DATA *CallbackData + ) +{ + UINTN Index; + UINTN Index2; + VOID *BootOptionVar; + CHAR16 VarName[100]; + UINTN OptionSize; + UINT16 FilePathSize; + UINT8 *Ptr; + EFI_STATUS Status; + CHAR16 DescString[100]; + UINTN NewOptionSize; + UINT8 *NewOptionPtr; + UINT8 *TempPtr; + UINT32 *Attribute; + + BM_MENU_OPTION *OptionMenu; + BM_LEGACY_DEVICE_CONTEXT *LegacyDeviceContext; + UINT8 *LegacyDev; + UINT8 *VarData; + UINTN VarSize; + BM_MENU_ENTRY *NewMenuEntry; + BM_LEGACY_DEV_ORDER_CONTEXT *DevOrder; + UINT8 *OriginalPtr; + UINT8 *DisMap; + UINTN Pos; + UINTN Bit; + UINT16 *NewOrder; + UINT16 Tmp; + + LegacyDeviceContext = NULL; + DisMap = NULL; + NewOrder = NULL; + + if (FORM_SET_FD_ORDER_ID == CallbackData->BmmPreviousPageId) { + OptionMenu = (BM_MENU_OPTION *) &LegacyFDMenu; + LegacyDev = CallbackData->BmmFakeNvData->LegacyFD; + CallbackData->BbsType = BBS_FLOPPY; + } else { + if (FORM_SET_HD_ORDER_ID == CallbackData->BmmPreviousPageId) { + OptionMenu = (BM_MENU_OPTION *) &LegacyHDMenu; + LegacyDev = CallbackData->BmmFakeNvData->LegacyHD; + CallbackData->BbsType = BBS_HARDDISK; + } else { + if (FORM_SET_CD_ORDER_ID == CallbackData->BmmPreviousPageId) { + OptionMenu = (BM_MENU_OPTION *) &LegacyCDMenu; + LegacyDev = CallbackData->BmmFakeNvData->LegacyCD; + CallbackData->BbsType = BBS_CDROM; + } else { + if (FORM_SET_NET_ORDER_ID == CallbackData->BmmPreviousPageId) { + OptionMenu = (BM_MENU_OPTION *) &LegacyNETMenu; + LegacyDev = CallbackData->BmmFakeNvData->LegacyNET; + CallbackData->BbsType = BBS_EMBED_NETWORK; + } else { + OptionMenu = (BM_MENU_OPTION *) &LegacyBEVMenu; + LegacyDev = CallbackData->BmmFakeNvData->LegacyBEV; + CallbackData->BbsType = BBS_BEV_DEVICE; + } + } + } + } + + DisMap = CallbackData->BmmOldFakeNVData.DisableMap; + Status = EFI_SUCCESS; + + // + // Find the first device's context + // If all devices are disabled( 0xFF == LegacyDev[0]), LegacyDeviceContext can be set to any VariableContext + // because we just use it to fill the desc string, and user can not see the string in UI + // + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + NewMenuEntry = BOpt_GetMenuEntry (OptionMenu, Index); + LegacyDeviceContext = (BM_LEGACY_DEVICE_CONTEXT *) NewMenuEntry->VariableContext; + if (0xFF != LegacyDev[0] && LegacyDev[0] == LegacyDeviceContext->Index) { + DEBUG ((EFI_D_ERROR, "DescStr: %s\n", LegacyDeviceContext->Description)); + break; + } + } + // + // Update the Variable "LegacyDevOrder" + // + VarData = (UINT8 *) BdsLibGetVariableAndSize ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + &VarSize + ); + + if (NULL == VarData) { + return EFI_NOT_FOUND; + } + + OriginalPtr = VarData; + DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData; + + while (VarData < VarData + VarSize) { + if (DevOrder->BbsType == CallbackData->BbsType) { + break; + } + + VarData += sizeof (BBS_TYPE); + VarData += *(UINT16 *) VarData; + DevOrder = (BM_LEGACY_DEV_ORDER_CONTEXT *) VarData; + } + + if (VarData >= VarData + VarSize) { + SafeFreePool (OriginalPtr); + return EFI_NOT_FOUND; + } + + NewOrder = (UINT16 *) AllocateZeroPool (DevOrder->Length - sizeof (UINT16)); + if (NULL == NewOrder) { + SafeFreePool (VarData); + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < OptionMenu->MenuNumber; Index++) { + if (0xFF == LegacyDev[Index]) { + break; + } + + NewOrder[Index] = LegacyDev[Index]; + } + // + // Only the enable/disable state of each boot device with same device type can be changed, + // so we can count on the index information in DevOrder. + // DisMap bit array is the only reliable source to check a device's en/dis state, + // so we use DisMap to set en/dis state of each item in NewOrder array + // + for (Index2 = 0; Index2 < OptionMenu->MenuNumber; Index2++) { + Tmp = *(UINT16 *) ((UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16) + Index2 * sizeof (UINT16)); + Tmp &= 0xFF; + Pos = Tmp / 8; + Bit = 7 - (Tmp % 8); + if (DisMap[Pos] & (1 << Bit)) { + NewOrder[Index] = (UINT16) (0xFF00 | Tmp); + Index++; + } + } + + CopyMem ( + (UINT8 *) DevOrder + sizeof (BBS_TYPE) + sizeof (UINT16), + NewOrder, + DevOrder->Length - sizeof (UINT16) + ); + SafeFreePool (NewOrder); + + Status = gRT->SetVariable ( + VarLegacyDevOrder, + &EfiLegacyDevOrderGuid, + VAR_FLAG, + VarSize, + OriginalPtr + ); + + SafeFreePool (OriginalPtr); + + // + // Update Optional Data of Boot#### + // + BootOptionVar = GetLegacyBootOptionVar (CallbackData->BbsType, &Index, &OptionSize); + + if (NULL != BootOptionVar) { + CopyMem ( + DescString, + LegacyDeviceContext->Description, + StrSize (LegacyDeviceContext->Description) + ); + + NewOptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (DescString) + sizeof (BBS_TABLE) + sizeof (UINT16); + + UnicodeSPrint (VarName, 100, L"Boot%04x", Index); + + Ptr = BootOptionVar; + + Attribute = (UINT32 *) Ptr; + *Attribute |= LOAD_OPTION_ACTIVE; + if (0xFF == LegacyDev[0]) { + // + // Disable this legacy boot option + // + *Attribute &= ~LOAD_OPTION_ACTIVE; + } + + Ptr += sizeof (UINT32); + + FilePathSize = *(UINT16 *) Ptr; + Ptr += sizeof (UINT16); + + NewOptionSize += FilePathSize; + + NewOptionPtr = AllocateZeroPool (NewOptionSize); + if (NULL == NewOptionPtr) { + return EFI_OUT_OF_RESOURCES; + } + + TempPtr = NewOptionPtr; + + // + // Copy previous option data to new option except the description string + // + CopyMem ( + TempPtr, + BootOptionVar, + sizeof (UINT32) + sizeof (UINT16) + ); + + TempPtr += (sizeof (UINT32) + sizeof (UINT16)); + + CopyMem ( + TempPtr, + DescString, + StrSize (DescString) + ); + + TempPtr += StrSize (DescString); + + // + // Description = (CHAR16 *)Ptr; + // + Ptr += StrSize ((CHAR16 *) Ptr); + + CopyMem ( + TempPtr, + Ptr, + FilePathSize + ); + + TempPtr += FilePathSize; + + // + // DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)Ptr; + // + Ptr += FilePathSize; + + // + // Now Ptr point to optional data, i.e. Bbs Table + // + CopyMem ( + TempPtr, + LegacyDeviceContext->BbsTable, + sizeof (BBS_TABLE) + ); + + TempPtr += sizeof (BBS_TABLE); + *((UINT16 *) TempPtr) = (UINT16) LegacyDeviceContext->Index; + + Status = gRT->SetVariable ( + VarName, + &gEfiGlobalVariableGuid, + VAR_FLAG, + NewOptionSize, + NewOptionPtr + ); + + SafeFreePool (NewOptionPtr); + SafeFreePool (BootOptionVar); + } + + BOpt_GetBootOptions (CallbackData); + return Status; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/bm.vfr b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/bm.vfr new file mode 100644 index 0000000000..e907e18d6c --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/bm.vfr @@ -0,0 +1,495 @@ +// *++ +// +// Copyright (c) 2006, 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. +// +// Module Name: +// +// bm.vfr +// +// Abstract: +// +// Boot Maintenance Utility Formset +// +// Revision History: +// +// --*/ + +#include "BdsStrDefs.h" +#include "formguid.h" + +#pragma pack(1) + +// +// This is the structure that will be used to store the +// question's current value. Use it at initialize time to +// set default value for each question. When using at run +// time, this map is returned by the callback function, +// so dynamically changing the question's value will be +// possible through this mechanism +// +typedef struct { + +// +// Three questions displayed at the main page +// for Timeout, BootNext Variables respectively +// + UINT16 BootTimeOut; + UINT16 BootNext; + +// +// This is the COM1 Attributes value storage +// + UINT8 COM1BaudRate; + UINT8 COM1DataRate; + UINT8 COM1StopBits; + UINT8 COM1Parity; + UINT8 COM1TerminalType; + +// +// This is the COM2 Attributes value storage +// + UINT8 COM2BaudRate; + UINT8 COM2DataRate; + UINT8 COM2StopBits; + UINT8 COM2Parity; + UINT8 COM2TerminalType; + +// +// Driver Option Add Handle page storage +// + UINT16 DriverAddHandleDesc[100]; + UINT16 DriverAddHandleOptionalData[100]; + UINT8 DriverAddActive; + UINT8 DriverAddForceReconnect; + +// +// Console Input/Output/Errorout using COM port check storage +// + UINT8 ConsoleInputCOM1; + UINT8 ConsoleInputCOM2; + UINT8 ConsoleOutputCOM1; + UINT8 ConsoleOutputCOM2; + UINT8 ConsoleErrorCOM1; + UINT8 ConsoleErrorCOM2; + +// +// At most 100 input/output/errorout device for console storage +// + UINT8 ConsoleCheck[100]; + +// +// Boot or Driver Option Order storage +// + UINT8 OptionOrder[100]; + UINT8 DriverOptionToBeDeleted[100]; + +// +// Boot Option Delete storage +// + UINT8 BootOptionDel[100]; + UINT8 DriverOptionDel[100]; + +// +// This is the Terminal Attributes value storage +// + UINT8 COMBaudRate; + UINT8 COMDataRate; + UINT8 COMStopBits; + UINT8 COMParity; + UINT8 COMTerminalType; + +// +// Legacy Device Order Selection Storage +// + UINT8 LegacyFD[100]; + UINT8 LegacyHD[100]; + UINT8 LegacyCD[100]; + UINT8 LegacyNET[100]; + UINT8 LegacyBEV[100]; +} BMM_FAKE_NV_DATA; +#pragma pack() + + +#define FORM_MAIN_ID 0x0001 +#define FORM_BOOT_ADD_ID 0x0002 +#define FORM_BOOT_DEL_ID 0x0003 +#define FORM_BOOT_CHG_ID 0x0004 +#define FORM_DRV_ADD_ID 0x0005 +#define FORM_DRV_DEL_ID 0x0006 +#define FORM_DRV_CHG_ID 0x0007 +#define FORM_CON_MAIN_ID 0x0008 +#define FORM_CON_IN_ID 0x0009 +#define FORM_CON_OUT_ID 0x000A +#define FORM_CON_ERR_ID 0x000B +#define FORM_FILE_SEEK_ID 0x000C +#define FORM_FILE_NEW_SEEK_ID 0x000D +#define FORM_DRV_ADD_FILE_ID 0x000E +#define FORM_DRV_ADD_HANDLE_ID 0x000F +#define FORM_DRV_ADD_HANDLE_DESC_ID 0x0010 +#define FORM_BOOT_NEXT_ID 0x0011 +#define FORM_TIME_OUT_ID 0x0012 +#define FORM_RESET 0x0013 +#define FORM_BOOT_SETUP_ID 0x0014 +#define FORM_DRIVER_SETUP_ID 0x0015 +#define FORM_BOOT_LEGACY_DEVICE_ID 0x0016 +#define FORM_CON_COM_ID 0x0017 +#define FORM_CON_COM_SETUP_ID 0x0018 +#define FORM_SET_FD_ORDER_ID 0x0019 +#define FORM_SET_HD_ORDER_ID 0x001A +#define FORM_SET_CD_ORDER_ID 0x001B +#define FORM_SET_NET_ORDER_ID 0x001C +#define FORM_SET_BEV_ORDER_ID 0x001D + +#define KEY_VALUE_BOOT_FROM_FILE 0x0092 + +formset + guid = MAIN_FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_MAIN_TITLE), // uint8 opcode, uint8 length, guid Handle, uint16 Title + help = STRING_TOKEN(STR_NULL_STRING), + class = 0, + subclass = 0, + + form formid = FORM_MAIN_ID, + title = STRING_TOKEN(STR_FORM_MAIN_TITLE); + + goto FORM_BOOT_SETUP_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_SETUP_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_BOOT_SETUP_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_DRIVER_SETUP_ID, + prompt = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE), + help = STRING_TOKEN(STR_FORM_DRIVER_SETUP_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_DRIVER_SETUP_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_CON_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE), + help = STRING_TOKEN(STR_FORM_CON_MAIN_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_CON_MAIN_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + text + help = STRING_TOKEN(STR_BOOT_FROM_FILE_HELP), + text = STRING_TOKEN(STR_BOOT_FROM_FILE), + text = STRING_TOKEN(STR_NULL_STRING), + flags = INTERACTIVE | NV_ACCESS, + key = KEY_VALUE_BOOT_FROM_FILE; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + +// label FORM_MAIN_ID; + + goto FORM_BOOT_NEXT_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_NEXT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_BOOT_NEXT_ID; + + goto FORM_TIME_OUT_ID, + prompt = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE), + help = STRING_TOKEN(STR_FORM_TIME_OUT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_TIME_OUT_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_RESET), + help = STRING_TOKEN(STR_RESET), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_RESET; + + endform; + + form formid = FORM_BOOT_SETUP_ID, + title = STRING_TOKEN(STR_FORM_BOOT_SETUP_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_MAIN_ID; + + goto FORM_BOOT_ADD_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_ADD_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_BOOT_ADD_ID; + + goto FORM_BOOT_DEL_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_BOOT_DEL_ID; + + goto FORM_BOOT_CHG_ID, + prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_BOOT_CHG_ID; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + // + // We will add "Select Legacy Boot Floppy Drive" and "Select Legacy Boot Hard Drive" + // here dynamically + // + label FORM_BOOT_LEGACY_DEVICE_ID; + + endform; + + form formid = FORM_DRIVER_SETUP_ID, + title = STRING_TOKEN(STR_FORM_DRIVER_SETUP_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_MAIN_ID; + + goto FORM_DRV_ADD_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE), + help = STRING_TOKEN(STR_FORM_DRV_ADD_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_DRV_ADD_ID; + + goto FORM_DRV_DEL_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_DRV_DEL_ID; + + goto FORM_DRV_CHG_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_NEXT_BOOT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_DRV_CHG_ID; + endform; + + form formid = FORM_BOOT_ADD_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); + + label FORM_BOOT_ADD_ID; + endform; + + form formid = FORM_BOOT_DEL_ID, + title = STRING_TOKEN(STR_FORM_BOOT_DEL_TITLE); + + label FORM_BOOT_DEL_ID; + endform; + + form formid = FORM_BOOT_CHG_ID, + title = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE); + + label FORM_BOOT_CHG_ID; + + // + // This tag is added for bypassing issue of setup browser + // setup browser could not support dynamic form very well. + // + checkbox varid = BMM_FAKE_NV_DATA.OptionOrder[0], + prompt = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_BOOT_CHG_TITLE), + flags = 1, + key = 0, + endcheckbox; + + endform; + + form formid = FORM_BOOT_NEXT_ID, + title = STRING_TOKEN(STR_FORM_BOOT_NEXT_TITLE); + + label FORM_BOOT_NEXT_ID; + endform; + + form formid = FORM_TIME_OUT_ID, + title = STRING_TOKEN(STR_FORM_TIME_OUT_TITLE); + + label FORM_TIME_OUT_ID; + endform; + + form formid = FORM_DRV_ADD_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_MAIN_ID; + + goto FORM_DRV_ADD_FILE_ID, + prompt = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), + help = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_DRV_ADD_FILE_ID; + + endform; + + form formid = FORM_DRV_DEL_ID, + title = STRING_TOKEN(STR_FORM_DRV_DEL_TITLE); + + label FORM_DRV_DEL_ID; + + endform; + + form formid = FORM_DRV_CHG_ID, + title = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE); + + label FORM_DRV_CHG_ID; + + // + // This tag is added for bypassing issue of setup browser + // setup browser could not support dynamic form very well. + // + checkbox varid = BMM_FAKE_NV_DATA.OptionOrder[0], + prompt = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE), + help = STRING_TOKEN(STR_FORM_DRV_CHG_TITLE), + flags = 1, + key = 0, + endcheckbox; + + endform; + + form formid = FORM_CON_MAIN_ID, + title = STRING_TOKEN(STR_FORM_CON_MAIN_TITLE); + + goto FORM_MAIN_ID, + prompt = STRING_TOKEN(STR_FORM_GOTO_MAIN), + help = STRING_TOKEN(STR_FORM_GOTO_MAIN), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_MAIN_ID; + + goto FORM_CON_IN_ID, + prompt = STRING_TOKEN(STR_FORM_CON_IN_TITLE), + help = STRING_TOKEN(STR_FORM_CON_IN_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_CON_IN_ID; + + goto FORM_CON_OUT_ID, + prompt = STRING_TOKEN(STR_FORM_CON_OUT_TITLE), + help = STRING_TOKEN(STR_FORM_CON_OUT_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_CON_OUT_ID; + + goto FORM_CON_ERR_ID, + prompt = STRING_TOKEN(STR_FORM_STD_ERR_TITLE), + help = STRING_TOKEN(STR_FORM_STD_ERR_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_CON_ERR_ID; + + goto FORM_CON_COM_ID, + prompt = STRING_TOKEN(STR_FORM_COM_TITLE), + help = STRING_TOKEN(STR_FORM_COM_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = FORM_CON_COM_ID; + endform; + + form formid = FORM_CON_COM_ID, + title = STRING_TOKEN(STR_FORM_COM_TITLE); + + label FORM_CON_COM_ID; + endform; + + form formid = FORM_CON_COM_SETUP_ID, + title = STRING_TOKEN(STR_CON_COM_SETUP); + + label FORM_CON_COM_SETUP_ID; + endform; + + form formid = FORM_FILE_SEEK_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); + + label FORM_FILE_SEEK_ID; + endform; + + form formid = FORM_FILE_NEW_SEEK_ID, + title = STRING_TOKEN(STR_FORM_BOOT_ADD_TITLE); + + label FORM_FILE_NEW_SEEK_ID; + endform; + + form formid = FORM_DRV_ADD_FILE_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_FILE_TITLE); + + label FORM_DRV_ADD_FILE_ID; + endform; + + form formid = FORM_DRV_ADD_HANDLE_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_HANDLE_TITLE); + + label FORM_DRV_ADD_HANDLE_ID; + endform; + + form formid = FORM_DRV_ADD_HANDLE_DESC_ID, + title = STRING_TOKEN(STR_FORM_DRV_ADD_DESC_TITLE); + + label FORM_DRV_ADD_HANDLE_DESC_ID; + + endform; + + form formid = FORM_CON_IN_ID, + title = STRING_TOKEN(STR_FORM_CON_IN_TITLE); + + label FORM_CON_IN_ID; + + endform; + + form formid = FORM_CON_OUT_ID, + title = STRING_TOKEN(STR_FORM_CON_OUT_TITLE); + + label FORM_CON_OUT_ID; + + endform; + + form formid = FORM_CON_ERR_ID, + title = STRING_TOKEN(STR_FORM_STD_ERR_TITLE); + + label FORM_CON_ERR_ID; + + endform; + + form formid = FORM_SET_FD_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_FD_ORDER_TITLE); + + label FORM_SET_FD_ORDER_ID; + endform; + + form formid = FORM_SET_HD_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_HD_ORDER_TITLE); + + label FORM_SET_HD_ORDER_ID; + endform; + + form formid = FORM_SET_CD_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_CD_ORDER_TITLE); + + label FORM_SET_CD_ORDER_ID; + endform; + + form formid = FORM_SET_NET_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_NET_ORDER_TITLE); + + label FORM_SET_NET_ORDER_ID; + endform; + + form formid = FORM_SET_BEV_ORDER_ID, + title = STRING_TOKEN(STR_FORM_SET_BEV_ORDER_TITLE); + + label FORM_SET_BEV_ORDER_ID; + endform; + +endformset; diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/bmstring.uni b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/bmstring.uni new file mode 100644 index 0000000000..f646d8b331 Binary files /dev/null and b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMaint/bmstring.uni differ diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManager.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManager.c new file mode 100644 index 0000000000..d90cfaa0a8 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManager.c @@ -0,0 +1,333 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BootManager.c + +Abstract: + + The platform boot manager reference implement + +--*/ +#include "BootManager.h" + +UINT16 mKeyInput; +LIST_ENTRY *mBootOptionsList; +BDS_COMMON_OPTION *gOption; +EFI_HII_HANDLE gBootManagerHandle; +EFI_HANDLE BootManagerCallbackHandle; +EFI_FORM_CALLBACK_PROTOCOL BootManagerCallback; +EFI_GUID gBmGuid = BOOT_MANAGER_GUID; + +extern EFI_FORM_BROWSER_PROTOCOL *gBrowser; +extern UINT8 BootManagerVfrBin[]; +extern UINT8 BdsStrings[]; +extern BOOLEAN gConnectAllHappened; + +EFI_STATUS +EFIAPI +BootManagerCallbackRoutine ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *DataArray, + OUT EFI_HII_CALLBACK_PACKET **Packet + ) +/*++ + +Routine Description: + + This is the function that is called to provide results data to the driver. This data + consists of a unique key which is used to identify what data is either being passed back + or being asked for. + +Arguments: + + KeyValue - A unique value which is sent to the original exporting driver so that it + can identify the type of data to expect. The format of the data tends to + vary based on the op-code that geerated the callback. + + Data - A pointer to the data being sent to the original exporting driver. + +Returns: + +--*/ +{ + BDS_COMMON_OPTION *Option; + LIST_ENTRY *Link; + UINT16 KeyCount; + EFI_HII_CALLBACK_PACKET *DataPacket; + + // + // Initialize the key count + // + KeyCount = 0; + + for (Link = mBootOptionsList->ForwardLink; Link != mBootOptionsList; Link = Link->ForwardLink) { + Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + + KeyCount++; + + gOption = Option; + + // + // Is this device the one chosen? + // + if (KeyCount == KeyValue) { + // + // Assigning the returned Key to a global allows the original routine to know what was chosen + // + mKeyInput = KeyValue; + + *Packet = AllocateZeroPool (sizeof (EFI_HII_CALLBACK_PACKET) + 2); + ASSERT (*Packet != NULL); + + // + // Assign the buffer address to DataPacket + // + DataPacket = *Packet; + + DataPacket->DataArray.EntryCount = 1; + DataPacket->DataArray.NvRamMap = NULL; + ((EFI_IFR_DATA_ENTRY *) (((EFI_IFR_DATA_ARRAY *)DataPacket) + 1))->Flags = EXIT_REQUIRED | NV_NOT_CHANGED; + return EFI_SUCCESS; + } else { + continue; + } + } + + return EFI_SUCCESS; +} + +VOID +CallBootManager ( + VOID + ) +/*++ + +Routine Description: + Hook to enable UI timeout override behavior. + +Arguments: + BdsDeviceList - Device List that BDS needs to connect. + + Entry - Pointer to current Boot Entry. + +Returns: + NONE + +--*/ +{ + EFI_STATUS Status; + EFI_HII_PACKAGES *PackageList; + BDS_COMMON_OPTION *Option; + LIST_ENTRY *Link; + EFI_HII_UPDATE_DATA *UpdateData; + CHAR16 *ExitData; + UINTN ExitDataSize; + STRING_REF Token; + STRING_REF LastToken; + EFI_INPUT_KEY Key; + UINT8 *Location; + EFI_GUID BmGuid; + LIST_ENTRY BdsBootOptionList; + + gOption = NULL; + InitializeListHead (&BdsBootOptionList); + + // + // Connect all prior to entering the platform setup menu. + // + if (!gConnectAllHappened) { + BdsLibConnectAllDriversToAllControllers (); + gConnectAllHappened = TRUE; + } + // + // BugBug: Here we can not remove the legacy refresh macro, so we need + // get the boot order every time from "BootOrder" variable. + // Recreate the boot option list base on the BootOrder variable + // + BdsLibEnumerateAllBootOption (&BdsBootOptionList); + + // + // This GUID must be the same as what is defined in BootManagerVfr.vfr + // + BmGuid = gBmGuid; + + mBootOptionsList = &BdsBootOptionList; + + // + // Post our VFR to the HII database + // + PackageList = PreparePackages (2, &BmGuid, BootManagerVfrBin, BdsStrings); + Status = Hii->NewPack (Hii, PackageList, &gBootManagerHandle); + gBS->FreePool (PackageList); + + // + // This example does not implement worker functions + // for the NV accessor functions. Only a callback evaluator + // + BootManagerCallback.NvRead = NULL; + BootManagerCallback.NvWrite = NULL; + BootManagerCallback.Callback = BootManagerCallbackRoutine; + + // + // Install protocol interface + // + BootManagerCallbackHandle = NULL; + Status = gBS->InstallProtocolInterface ( + &BootManagerCallbackHandle, + &gEfiFormCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &BootManagerCallback + ); + ASSERT_EFI_ERROR (Status); + + LastToken = 0; + Hii->NewString (Hii, NULL, gBootManagerHandle, &LastToken, L" "); + + // + // Allocate space for creation of UpdateData Buffer + // + UpdateData = AllocateZeroPool (0x1000); + ASSERT (UpdateData != NULL); + + // + // Flag update pending in FormSet + // + UpdateData->FormSetUpdate = TRUE; + // + // Register CallbackHandle data for FormSet + // + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) BootManagerCallbackHandle; + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = 0; + UpdateData->DataCount = 1; + + // + // Create blank space. Since when we update the contents of IFR data at a label, it is + // inserted at the location of the label. So if you want to add a string with an empty + // space afterwards, you need to add the space first and then the string like below. + // + Status = CreateSubTitleOpCode ( + LastToken, // Token Value for the string + &UpdateData->Data // Buffer containing created op-code + ); + + Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData); + + // + // Create "Boot Option Menu" title + // + Status = CreateSubTitleOpCode ( + STRING_TOKEN (STR_BOOT_OPTION_BANNER), // Token Value for the string + &UpdateData->Data // Buffer containing created op-code + ); + + Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData); + + Token = LastToken; + mKeyInput = 0; + + UpdateData->DataCount = 0; + Location = (UINT8 *) &UpdateData->Data; + + for (Link = BdsBootOptionList.ForwardLink; Link != &BdsBootOptionList; Link = Link->ForwardLink) { + Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + + // + // At this stage we are creating a menu entry, thus the Keys are reproduceable + // + mKeyInput++; + Token++; + + Status = Hii->NewString (Hii, NULL, gBootManagerHandle, &Token, Option->Description); + + // + // If we got an error it is almost certainly due to the token value being invalid. + // Therefore we will set the Token to 0 to automatically add a token. + // + if (EFI_ERROR (Status)) { + Token = 0; + Status = Hii->NewString (Hii, NULL, gBootManagerHandle, &Token, Option->Description); + } + + Status = CreateGotoOpCode ( + 0x1000, // Form ID + Token, // Token Value for the string + 0, // Help String (none) + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, // The Op-Code flags + mKeyInput, // The Key to get a callback on + Location // Buffer containing created op-code + ); + + UpdateData->DataCount++; + Location = Location + ((EFI_IFR_OP_HEADER *) Location)->Length; + + } + + Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0001, TRUE, UpdateData); + + UpdateData->DataCount = 1; + + // + // Create "Boot Option Menu" title + // + Status = CreateSubTitleOpCode ( + STRING_TOKEN (STR_HELP_FOOTER), // Token Value for the string + &UpdateData->Data // Buffer containing created op-code + ); + + Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData); + + Status = CreateSubTitleOpCode ( + LastToken, // Token Value for the string + &UpdateData->Data // Buffer containing created op-code + ); + + Hii->UpdateForm (Hii, gBootManagerHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData); + + gBS->FreePool (UpdateData); + + ASSERT (gBrowser); + + gBrowser->SendForm (gBrowser, TRUE, &gBootManagerHandle, 1, NULL, NULL, NULL, NULL, NULL); + + Hii->ResetStrings (Hii, gBootManagerHandle); + + if (gOption == NULL) { + return ; + } + // + // BugBug: This code looks repeated from the BDS. Need to save code space. + // + + // + // parse the selected option + // + Status = BdsLibBootViaBootOption (gOption, gOption->DevicePath, &ExitDataSize, &ExitData); + + if (!EFI_ERROR (Status)) { + PlatformBdsBootSuccess (gOption); + } else { + PlatformBdsBootFail (gOption, Status, ExitData, ExitDataSize); + gST->ConOut->OutputString ( + gST->ConOut, + GetStringById (STRING_TOKEN (STR_ANY_KEY_CONTINUE)) + ); + + // + // BdsLibUiWaitForSingleEvent (gST->ConIn->WaitForKey, 0); + // + + gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + } +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManager.h b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManager.h new file mode 100644 index 0000000000..3a90932695 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManager.h @@ -0,0 +1,50 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BootManager.h + +Abstract: + + The platform boot manager reference implement + +Revision History + +--*/ + +#ifndef _EFI_BOOT_MANAGER_H +#define _EFI_BOOT_MANAGER_H + +#include "Generic/Bds.h" +#include "BdsPlatform.h" +#include "Generic/String.h" + +EFI_STATUS +EFIAPI +BootManagerCallbackRoutine ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *DataArray, + OUT EFI_HII_CALLBACK_PACKET **Packet + ); + +VOID +CallBootManager ( + VOID +); + +#define BOOT_MANAGER_GUID \ + { \ + 0x847bc3fe, 0xb974, 0x446d, {0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b } \ + } + +#endif diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManagerStrings.uni b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManagerStrings.uni new file mode 100644 index 0000000000..e875cfbee1 Binary files /dev/null and b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManagerStrings.uni differ diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManagerVfr.Vfr b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManagerVfr.Vfr new file mode 100644 index 0000000000..7fb193ac1b --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/BootMngr/BootManagerVfr.Vfr @@ -0,0 +1,55 @@ +// *++ +// +// Copyright (c) 2006, 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. +// +// Module Name: +// +// BootManager.vfr +// +// Abstract: +// +// Browser formset. +// +// Revision History: +// +// --*/ + +#include "BdsStrDefs.h" + +#define FORMSET_GUID { 0x847bc3fe, 0xb974, 0x446d, { 0x94, 0x49, 0x5a, 0xd5, 0x41, 0x2e, 0x99, 0x3b } } + +#define BOOT_MANAGER_HEADER 0x00 +#define BOOT_MANAGER_LABEL 0x01 +#define BOOT_MANAGER_TAIL 0x02 + + +#define BOOT_MANAGER_CLASS 0x00 +#define BOOT_MANAGER_SUBCLASS 0x01 + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(STR_BM_BANNER), + help = STRING_TOKEN(STR_LAST_STRING), + class = BOOT_MANAGER_CLASS, + subclass = BOOT_MANAGER_SUBCLASS, + + form formid = 0x1000, + title = STRING_TOKEN(STR_BM_BANNER); + + label BOOT_MANAGER_HEADER; + label BOOT_MANAGER_LABEL; + // + // This is where we will dynamically add choices for the Boot Manager + // + + label BOOT_MANAGER_TAIL; + endform; + +endformset; diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/Capsules.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Capsules.c new file mode 100644 index 0000000000..b33af03bb7 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Capsules.c @@ -0,0 +1,213 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Capsules.c + +Abstract: + + BDS routines to handle capsules. + +--*/ + + +#include + +VOID +BdsLockFv ( + IN EFI_CPU_IO_PROTOCOL *CpuIo, + IN EFI_FLASH_SUBAREA_ENTRY *FlashEntry + ); + +VOID +BdsLockFv ( + IN EFI_CPU_IO_PROTOCOL *CpuIo, + IN EFI_FLASH_SUBAREA_ENTRY *FlashEntry + ) +{ + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + UINT64 BaseAddress; + UINT8 Data; + UINT32 BlockLength; + UINTN Index; + + BaseAddress = FlashEntry->Base - 0x400000 + 2; + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINTN) (FlashEntry->Base)); + BlockMap = &(FvHeader->FvBlockMap[0]); + + while ((BlockMap->NumBlocks != 0) && (BlockMap->BlockLength != 0)) { + BlockLength = BlockMap->BlockLength; + for (Index = 0; Index < BlockMap->NumBlocks; Index++) { + CpuIo->Mem.Read ( + CpuIo, + EfiCpuIoWidthUint8, + BaseAddress, + 1, + &Data + ); + Data = (UINT8) (Data | 0x3); + CpuIo->Mem.Write ( + CpuIo, + EfiCpuIoWidthUint8, + BaseAddress, + 1, + &Data + ); + BaseAddress += BlockLength; + } + + BlockMap++; + } +} + +VOID +BdsLockNonUpdatableFlash ( + VOID + ) +{ + EFI_FLASH_MAP_ENTRY_DATA *FlashMapEntryData; + EFI_PEI_HOB_POINTERS GuidHob; + EFI_STATUS Status; + EFI_CPU_IO_PROTOCOL *CpuIo; + + Status = gBS->LocateProtocol (&gEfiCpuIoProtocolGuid, NULL, &CpuIo); + ASSERT_EFI_ERROR (Status); + + GuidHob.Raw = GetHobList (); + while ((GuidHob.Raw = GetNextGuidHob (&gEfiFlashMapHobGuid, GuidHob.Raw)) != NULL) { + FlashMapEntryData = (EFI_FLASH_MAP_ENTRY_DATA *) GET_GUID_HOB_DATA (GuidHob.Guid); + + // + // Get the variable store area + // + if ((FlashMapEntryData->AreaType == EFI_FLASH_AREA_RECOVERY_BIOS) || + (FlashMapEntryData->AreaType == EFI_FLASH_AREA_MAIN_BIOS) + ) { + BdsLockFv (CpuIo, &(FlashMapEntryData->Entries[0])); + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + + return ; +} + +EFI_STATUS +ProcessCapsules ( + EFI_BOOT_MODE BootMode + ) +/*++ + +Routine Description: + + This routine is called to see if there are any capsules we need to process. + If the boot mode is not UPDATE, then we do nothing. Otherwise find the + capsule HOBS and produce firmware volumes for them via the DXE service. + Then call the dispatcher to dispatch drivers from them. Finally, check + the status of the updates. + +Arguments: + + BootMode - the current boot mode + +Returns: + + EFI_INVALID_PARAMETER - boot mode is not correct for an update + +Note: + + This function should be called by BDS in case we need to do some + sort of processing even if there is no capsule to process. We + need to do this if an earlier update went awry and we need to + clear the capsule variable so on the next reset PEI does not see it and + think there is a capsule available. + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_CAPSULE_VOLUME *CvHob; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_HANDLE FvProtocolHandle; + + // + // We don't do anything else if the boot mode is not flash-update + // + if (BootMode != BOOT_ON_FLASH_UPDATE) { + return EFI_INVALID_PARAMETER; + } + // + // Only one capsule HOB allowed. + // + CvHob = GetFirstHob (EFI_HOB_TYPE_CV); + if (CvHob == NULL) { + // + // We didn't find a hob, so had no errors. + // + BdsLockNonUpdatableFlash (); + return EFI_SUCCESS; + } + + BaseAddress = CvHob->BaseAddress; + Length = CvHob->Length; + + Status = EFI_SUCCESS; + // + // Now walk the capsule and call the core to process each + // firmware volume in it. + // + while (Length != 0) { + // + // Point to the next firmware volume header, and then + // call the DXE service to process it. + // + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; + if (FwVolHeader->FvLength > Length) { + // + // Notes: need to stuff this status somewhere so that the + // error can be detected at OS runtime + // + Status = EFI_VOLUME_CORRUPTED; + break; + } + + Status = gDS->ProcessFirmwareVolume ( + (VOID *) (UINTN) BaseAddress, + (UINTN) FwVolHeader->FvLength, + &FvProtocolHandle + ); + if (EFI_ERROR (Status)) { + break; + } + // + // Call the dispatcher to dispatch any drivers from the produced firmware volume + // + gDS->Dispatch (); + // + // On to the next FV in the capsule + // + Length -= FwVolHeader->FvLength; + BaseAddress = (EFI_PHYSICAL_ADDRESS) ((UINTN) BaseAddress + FwVolHeader->FvLength); + // + // Notes: when capsule spec is finalized, if the requirement is made to + // have each FV in a capsule aligned, then we will need to align the + // BaseAddress and Length here. + // + } + + + BdsLockNonUpdatableFlash (); + + return Status; +} + diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManager.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManager.c new file mode 100644 index 0000000000..0e73a4e3fe --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManager.c @@ -0,0 +1,482 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DeviceManager.c + +Abstract: + + The platform device manager reference implement + +--*/ +#include "DeviceManager.h" + +STATIC UINT16 mTokenCount; +EFI_FRONTPAGE_CALLBACK_INFO FPCallbackInfo; +extern UINTN gCallbackKey; +extern EFI_FORM_BROWSER_PROTOCOL *gBrowser; +extern EFI_GUID gBdsStringPackGuid; +extern BOOLEAN gConnectAllHappened; + +STRING_REF gStringTokenTable[] = { + STR_VIDEO_DEVICE, + STR_NETWORK_DEVICE, + STR_INPUT_DEVICE, + STR_ON_BOARD_DEVICE, + STR_OTHER_DEVICE, + STR_EMPTY_STRING, + 0xFFFF +}; + +EFI_STATUS +EFIAPI +DeviceManagerCallbackRoutine ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *DataArray, + OUT EFI_HII_CALLBACK_PACKET **Packet + ) +/*++ + +Routine Description: + + This is the function that is called to provide results data to the driver. This data + consists of a unique key which is used to identify what data is either being passed back + or being asked for. + +Arguments: + + KeyValue - A unique value which is sent to the original exporting driver so that it + can identify the type of data to expect. The format of the data tends to + vary based on the op-code that geerated the callback. + + Data - A pointer to the data being sent to the original exporting driver. + +Returns: + +--*/ +{ + // + // The KeyValue corresponds in this case to the handle which was requested to be displayed + // + EFI_FRONTPAGE_CALLBACK_INFO *CallbackInfo; + + CallbackInfo = EFI_FP_CALLBACK_DATA_FROM_THIS (This); + switch (KeyValue) { + case 0x2000: + CallbackInfo->Data.VideoBIOS = (UINT8) (UINTN) (((EFI_IFR_DATA_ENTRY *)(DataArray + 1))->Data); + gRT->SetVariable ( + L"VBIOS", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (UINT8), + &CallbackInfo->Data.VideoBIOS + ); + break; + + default: + break; + } + + gCallbackKey = KeyValue; + return EFI_SUCCESS; +} + +EFI_STATUS +InitializeDeviceManager ( + VOID + ) +/*++ + +Routine Description: + + Initialize HII information for the FrontPage + +Arguments: + None + +Returns: + +--*/ +{ + EFI_STATUS Status; + EFI_HII_PACKAGES *PackageList; + EFI_HII_UPDATE_DATA *UpdateData; + + // + // Allocate space for creation of UpdateData Buffer + // + UpdateData = AllocateZeroPool (0x1000); + ASSERT (UpdateData != NULL); + + PackageList = PreparePackages (1, &gBdsStringPackGuid, DeviceManagerVfrBin); + Status = Hii->NewPack (Hii, PackageList, &FPCallbackInfo.DevMgrHiiHandle); + gBS->FreePool (PackageList); + + // + // This example does not implement worker functions for the NV accessor functions. Only a callback evaluator + // + FPCallbackInfo.Signature = EFI_FP_CALLBACK_DATA_SIGNATURE; + FPCallbackInfo.DevMgrCallback.NvRead = NULL; + FPCallbackInfo.DevMgrCallback.NvWrite = NULL; + FPCallbackInfo.DevMgrCallback.Callback = DeviceManagerCallbackRoutine; + + // + // Install protocol interface + // + FPCallbackInfo.CallbackHandle = NULL; + + Status = gBS->InstallProtocolInterface ( + &FPCallbackInfo.CallbackHandle, + &gEfiFormCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &FPCallbackInfo.DevMgrCallback + ); + + ASSERT_EFI_ERROR (Status); + + // + // Flag update pending in FormSet + // + UpdateData->FormSetUpdate = TRUE; + // + // Register CallbackHandle data for FormSet + // + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) FPCallbackInfo.CallbackHandle; + // + // Simply registering the callback handle + // + Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) 0x0000, TRUE, UpdateData); + + gBS->FreePool (UpdateData); + return Status; +} + +EFI_STATUS +CallDeviceManager ( + VOID + ) +/*++ + +Routine Description: + + Call the browser and display the device manager + +Arguments: + + None + +Returns: + EFI_SUCCESS - Operation is successful. + EFI_INVALID_PARAMETER - If the inputs to SendForm function is not valid. + +--*/ +{ + EFI_STATUS Status; + UINTN BufferSize; + UINTN Count; + EFI_HII_HANDLE Index; + UINT8 *Buffer; + EFI_IFR_FORM_SET *FormSetData; + CHAR16 *String; + UINTN StringLength; + EFI_HII_UPDATE_DATA *UpdateData; + STRING_REF Token; + STRING_REF TokenHelp; + IFR_OPTION *IfrOptionList; + UINT8 *VideoOption; + UINTN VideoOptionSize; + EFI_HII_HANDLE *HiiHandles; + UINT16 HandleBufferLength; + + IfrOptionList = NULL; + VideoOption = NULL; + HandleBufferLength = 0; + + // + // Connect all prior to entering the platform setup menu. + // + if (!gConnectAllHappened) { + BdsLibConnectAllDriversToAllControllers (); + gConnectAllHappened = TRUE; + } + // + // Allocate space for creation of UpdateData Buffer + // + UpdateData = AllocateZeroPool (0x1000); + ASSERT (UpdateData != NULL); + + Status = EFI_SUCCESS; + Buffer = NULL; + FormSetData = NULL; + gCallbackKey = 0; + if (mTokenCount == 0) { + Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &mTokenCount, L" "); + } + + Token = mTokenCount; + TokenHelp = (UINT16) (Token + 1); + + // + // Reset the menu + // + for (Index = 0, Count = 1; Count < 0x10000; Count <<= 1, Index++) { + // + // We will strip off all previous menu entries + // + UpdateData->DataCount = 0xFF; + + // + // Erase entries on this label + // + Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, FALSE, UpdateData); + + // + // Did we reach the end of the Token Table? + // + if (gStringTokenTable[Index] == 0xFFFF) { + break; + } + + CreateSubTitleOpCode (gStringTokenTable[Index], &UpdateData->Data); + // + // Add a single menu item - in this case a subtitle for the device type + // + UpdateData->DataCount = 1; + + // + // Add default title for this label + // + Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData); + } + // + // Add a space and an exit string. Remember since we add things at the label and push other things beyond the + // label down, we add this in reverse order + // + CreateSubTitleOpCode (STRING_TOKEN (STR_EXIT_STRING), &UpdateData->Data); + Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData); + CreateSubTitleOpCode (STR_EMPTY_STRING, &UpdateData->Data); + Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) Count, TRUE, UpdateData); + + HiiHandles = AllocateZeroPool (HandleBufferLength); + Hii->FindHandles (Hii, &HandleBufferLength, HiiHandles); + + for (Index = 1, BufferSize = 0; Index < HandleBufferLength; Index++) { + // + // Am not initializing Buffer since the first thing checked is the size + // this way I can get the real buffersize in the smallest code size + // + Status = Hii->GetForms (Hii, Index, 0, &BufferSize, Buffer); + + if (Status != EFI_NOT_FOUND) { + // + // BufferSize should have the real size of the forms now + // + Buffer = AllocateZeroPool (BufferSize); + ASSERT (Buffer != NULL); + + // + // Am not initializing Buffer since the first thing checked is the size + // this way I can get the real buffersize in the smallest code size + // + Status = Hii->GetForms (Hii, Index, 0, &BufferSize, Buffer); + + // + // Skip EFI_HII_PACK_HEADER, advance to EFI_IFR_FORM_SET data. + // + FormSetData = (EFI_IFR_FORM_SET *) (Buffer + sizeof (EFI_HII_PACK_HEADER)); + + // + // If this formset belongs in the device manager, add it to the menu + // + if (FormSetData->Class != EFI_NON_DEVICE_CLASS) { + + StringLength = 0x1000; + String = AllocateZeroPool (StringLength); + ASSERT (String != NULL); + + Status = Hii->GetString (Hii, Index, FormSetData->FormSetTitle, TRUE, NULL, &StringLength, String); + Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &Token, String); + + // + // If token value exceeded real token value - we need to add a new token values + // + if (Status == EFI_INVALID_PARAMETER) { + Token = 0; + TokenHelp = 0; + Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &Token, String); + } + + StringLength = 0x1000; + if (FormSetData->Help == 0) { + TokenHelp = 0; + } else { + Status = Hii->GetString (Hii, Index, FormSetData->Help, TRUE, NULL, &StringLength, String); + if (StringLength == 0x02) { + TokenHelp = 0; + } else { + Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &TokenHelp, String); + if (Status == EFI_INVALID_PARAMETER) { + TokenHelp = 0; + Status = Hii->NewString (Hii, NULL, FPCallbackInfo.DevMgrHiiHandle, &TokenHelp, String); + } + } + } + + gBS->FreePool (String); + + CreateGotoOpCode ( + 0x1000, // Device Manager Page + Token, // Description String Token + TokenHelp, // Description Help String Token + EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS, // Flag designating callback is active + (UINT16) Index, // Callback key value + &UpdateData->Data // Buffer to fill with op-code + ); + + // + // In the off-chance that we have lots of extra tokens allocated to the DeviceManager + // this ensures we are fairly re-using the tokens instead of constantly growing the token + // storage for this one handle. If we incremented the token value beyond what it normally + // would use, we will fall back into the error path which seeds the token value with a 0 + // so that we can correctly add a token value. + // + if (TokenHelp == 0) { + // + // Since we didn't add help, only advance Token by 1 + // + Token++; + } else { + Token = (UINT16) (Token + 2); + TokenHelp = (UINT16) (TokenHelp + 2); + } + // + // This for loop basically will take the Class value which is a bitmask and + // update the form for every active bit. There will be a label at each bit + // location. So if someone had a device which a class of EFI_DISK_DEVICE_CLASS | + // EFI_ON_BOARD_DEVICE_CLASS, this routine will unwind that mask and drop the menu entry + // on each corresponding label. + // + for (Count = 1; Count < 0x10000; Count <<= 1) { + // + // This is an active bit, so update the form + // + if (FormSetData->Class & Count) { + Hii->UpdateForm ( + Hii, + FPCallbackInfo.DevMgrHiiHandle, + (EFI_FORM_LABEL) (FormSetData->Class & Count), + TRUE, + UpdateData + ); + } + } + } + + BufferSize = 0; + // + // Reset Buffer pointer to original location + // + gBS->FreePool (Buffer); + } + } + // + // Add oneof for video BIOS selection + // + VideoOption = BdsLibGetVariableAndSize ( + L"VBIOS", + &gEfiGlobalVariableGuid, + &VideoOptionSize + ); + if (NULL == VideoOption) { + FPCallbackInfo.Data.VideoBIOS = 0; + } else { + FPCallbackInfo.Data.VideoBIOS = VideoOption[0]; + gBS->FreePool (VideoOption); + } + + ASSERT (FPCallbackInfo.Data.VideoBIOS <= 1); + + Status = gBS->AllocatePool (EfiBootServicesData, 2 * sizeof (IFR_OPTION), &IfrOptionList); + if (IfrOptionList != NULL) { + IfrOptionList[0].Flags = EFI_IFR_FLAG_INTERACTIVE; + IfrOptionList[0].Key = SET_VIDEO_BIOS_TYPE_QUESTION_ID + 0x2000; + IfrOptionList[0].StringToken = STRING_TOKEN (STR_ONE_OF_PCI); + IfrOptionList[0].Value = 0; + IfrOptionList[0].OptionString = NULL; + IfrOptionList[1].Flags = EFI_IFR_FLAG_INTERACTIVE; + IfrOptionList[1].Key = SET_VIDEO_BIOS_TYPE_QUESTION_ID + 0x2000; + IfrOptionList[1].StringToken = STRING_TOKEN (STR_ONE_OF_AGP); + IfrOptionList[1].Value = 1; + IfrOptionList[1].OptionString = NULL; + IfrOptionList[FPCallbackInfo.Data.VideoBIOS].Flags |= EFI_IFR_FLAG_DEFAULT; + + CreateOneOfOpCode ( + SET_VIDEO_BIOS_TYPE_QUESTION_ID, + (UINT8) 1, + STRING_TOKEN (STR_ONE_OF_VBIOS), + STRING_TOKEN (STR_ONE_OF_VBIOS_HELP), + IfrOptionList, + 2, + &UpdateData->Data + ); + + UpdateData->DataCount = 4; + Hii->UpdateForm (Hii, FPCallbackInfo.DevMgrHiiHandle, (EFI_FORM_LABEL) EFI_VBIOS_CLASS, TRUE, UpdateData); + gBS->FreePool (IfrOptionList); + } + + Status = gBrowser->SendForm ( + gBrowser, + TRUE, // Use the database + &FPCallbackInfo.DevMgrHiiHandle, // The HII Handle + 1, + NULL, + FPCallbackInfo.CallbackHandle, + (UINT8 *) &FPCallbackInfo.Data, + NULL, + NULL + ); + + Hii->ResetStrings (Hii, FPCallbackInfo.DevMgrHiiHandle); + + // + // We will have returned from processing a callback - user either hit ESC to exit, or selected + // a target to display + // + if (gCallbackKey != 0 && gCallbackKey < 0x2000) { + Status = gBrowser->SendForm ( + gBrowser, + TRUE, // Use the database + (EFI_HII_HANDLE *) &gCallbackKey, // The HII Handle + 1, + NULL, + NULL, // This is the handle that the interface to the callback was installed on + NULL, + NULL, + NULL + ); + + // + // Force return to Device Manager + // + gCallbackKey = 4; + } + + if (gCallbackKey >= 0x2000) { + gCallbackKey = 4; + } + + gBS->FreePool (UpdateData); + + return Status; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManager.h b/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManager.h new file mode 100644 index 0000000000..dd6d935e45 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManager.h @@ -0,0 +1,59 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DeviceManager.c + +Abstract: + + The platform device manager reference implement + +Revision History + +--*/ + +#ifndef _DEVICE_MANAGER_H +#define _DEVICE_MANAGER_H + +#include "Generic/FrontPage.h" + +#define EFI_NON_DEVICE_CLASS 0x00 // Useful when you do not want something in the Device Manager +#define EFI_DISK_DEVICE_CLASS 0x01 +#define EFI_VIDEO_DEVICE_CLASS 0x02 +#define EFI_NETWORK_DEVICE_CLASS 0x04 +#define EFI_INPUT_DEVICE_CLASS 0x08 +#define EFI_ON_BOARD_DEVICE_CLASS 0x10 +#define EFI_OTHER_DEVICE_CLASS 0x20 + +EFI_STATUS +EFIAPI +DeviceManagerCallbackRoutine ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *DataArray, + OUT EFI_HII_CALLBACK_PACKET **Packet + ) +; + +EFI_STATUS +InitializeDeviceManager ( + VOID + ) +; + +EFI_STATUS +CallDeviceManager ( + VOID + ) +; + +#endif diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManagerStrings.uni b/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManagerStrings.uni new file mode 100644 index 0000000000..f549ff28ac Binary files /dev/null and b/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManagerStrings.uni differ diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManagerVfr.Vfr b/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManagerVfr.Vfr new file mode 100644 index 0000000000..5497c6df15 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/DeviceMngr/DeviceManagerVfr.Vfr @@ -0,0 +1,75 @@ +// *++ +// +// Copyright (c) 2006, 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. +// +// Module Name: +// +// DeviceManagerVfr.vfr +// +// Abstract: +// +// Device Manager formset. +// +// Revision History: +// +// --*/ + +#include "BdsStrDefs.h" + +#define FORMSET_GUID { 0x3ebfa8e6, 0x511d, 0x4b5b, { 0xa9, 0x5f, 0xfb, 0x38, 0x26, 0xf, 0x1c, 0x27 } } + +#define EFI_DISK_DEVICE_CLASS 0x01 +#define EFI_VIDEO_DEVICE_CLASS 0x02 +#define EFI_NETWORK_DEVICE_CLASS 0x04 +#define EFI_INPUT_DEVICE_CLASS 0x08 +#define EFI_ON_BOARD_DEVICE_CLASS 0x10 +#define EFI_OTHER_DEVICE_CLASS 0x20 +#define EFI_VBIOS_CLASS 0x40 + +#define DEVICE_MANAGER_CLASS 0x0000 +#define FRONT_PAGE_SUBCLASS 0x0003 + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE), + help = STRING_TOKEN(STR_EMPTY_STRING), + class = DEVICE_MANAGER_CLASS, + subclass = FRONT_PAGE_SUBCLASS, + + form formid = 0x1000, + title = STRING_TOKEN(STR_DEVICE_MANAGER_TITLE); + + // + // This is where devices get added to the device manager hierarchy + // + subtitle text = STRING_TOKEN(STR_DISK_DEVICE); + label EFI_DISK_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_VIDEO_DEVICE); + label EFI_VIDEO_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_NETWORK_DEVICE); + label EFI_NETWORK_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_INPUT_DEVICE); + label EFI_INPUT_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_ON_BOARD_DEVICE); + label EFI_ON_BOARD_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_OTHER_DEVICE); + label EFI_OTHER_DEVICE_CLASS; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + label EFI_VBIOS_CLASS; + + endform; +endformset; + diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPage.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPage.c new file mode 100644 index 0000000000..69b2fb5078 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPage.c @@ -0,0 +1,888 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FrontPage.c + +Abstract: + + FrontPage routines to handle the callbacks and browser calls + +--*/ + +#include "Bds.h" +#include "BdsPlatform.h" +#include "FrontPage.h" +#include "String.h" + +EFI_GUID mProcessorSubClass = EFI_PROCESSOR_SUBCLASS_GUID; +EFI_GUID mMemorySubClass = EFI_MEMORY_SUBCLASS_GUID; +EFI_GUID mMiscSubClass = EFI_MISC_SUBCLASS_GUID; + +UINT16 mLastSelection; +EFI_HII_HANDLE gFrontPageHandle; +EFI_HANDLE FrontPageCallbackHandle; +EFI_FORM_CALLBACK_PROTOCOL FrontPageCallback; +EFI_FORM_BROWSER_PROTOCOL *gBrowser; +UINTN gCallbackKey; +BOOLEAN gConnectAllHappened = FALSE; + +extern EFI_HII_HANDLE gFrontPageHandle; +extern EFI_GUID gBdsStringPackGuid; + +EFI_STATUS +EFIAPI +FrontPageCallbackRoutine ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *DataArray, + OUT EFI_HII_CALLBACK_PACKET **Packet + ) +/*++ + +Routine Description: + + This is the function that is called to provide results data to the driver. This data + consists of a unique key which is used to identify what data is either being passed back + or being asked for. + +Arguments: + + KeyValue - A unique value which is sent to the original exporting driver so that it + can identify the type of data to expect. The format of the data tends to + vary based on the op-code that geerated the callback. + + Data - A pointer to the data being sent to the original exporting driver. + +Returns: + +--*/ +{ + CHAR16 *LanguageString; + UINTN Count; + CHAR16 UnicodeLang[3]; + CHAR8 Lang[3]; + EFI_STATUS Status; + UINTN Index; + CHAR16 *TmpStr; + EFI_UGA_PIXEL Foreground; + EFI_UGA_PIXEL Background; + EFI_UGA_PIXEL Color; + + SetMem (&Foreground, sizeof (EFI_UGA_PIXEL), 0xff); + SetMem (&Background, sizeof (EFI_UGA_PIXEL), 0x0); + SetMem (&Color, sizeof (EFI_UGA_PIXEL), 0xff); + + Count = 0; + + // + // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can + // describe to their customers in documentation how to find their setup information (namely + // under the device manager and specific buckets) + // + switch (KeyValue) { + case 0x0001: + // + // This is the continue - clear the screen and return an error to get out of FrontPage loop + // + gCallbackKey = 1; + break; + + case 0x1234: + // + // Collect the languages from what our current Language support is based on our VFR + // + Hii->GetPrimaryLanguages (Hii, gFrontPageHandle, &LanguageString); + + // + // Based on the DataArray->Data->Data value, we can determine + // which language was chosen by the user + // + for (Index = 0; Count != (UINTN) (((EFI_IFR_DATA_ENTRY *) (DataArray + 1))->Data); Index += 3) { + Count++; + } + // + // Preserve the choice the user made + // + mLastSelection = (UINT16) Count; + + // + // The Language (in Unicode format) the user chose + // + CopyMem (UnicodeLang, &LanguageString[Index], 6); + + // + // Convert Unicode to ASCII (Since the ISO standard assumes ASCII equivalent abbreviations + // we can be safe in converting this Unicode stream to ASCII without any loss in meaning. + // + for (Index = 0; Index < 3; Index++) { + Lang[Index] = (CHAR8) UnicodeLang[Index]; + } + + Status = gRT->SetVariable ( + L"Lang", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + 3, + Lang + ); + + gBS->FreePool (LanguageString); + gCallbackKey = 2; + break; + + case 0x1064: + // + // Boot Manager + // + gCallbackKey = 3; + break; + + case 0x8567: + // + // Device Manager + // + gCallbackKey = 4; + break; + + case 0x9876: + // + // Boot Maintenance Manager + // + gCallbackKey = 5; + break; + + case 0xFFFE: + + break; + + case 0xFFFF: + // + // FrontPage TimeOut Callback + // + TmpStr = GetStringById (STRING_TOKEN (STR_START_BOOT_OPTION)); + if (TmpStr != NULL) { + PlatformBdsShowProgress ( + Foreground, + Background, + TmpStr, + Color, + (UINTN) (((EFI_IFR_DATA_ENTRY *) (DataArray+1))->Data), + 0 + ); + gBS->FreePool (TmpStr); + } + break; + + default: + gCallbackKey = 0; + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +InitializeFrontPage ( + BOOLEAN ReInitializeStrings + ) +/*++ + +Routine Description: + + Initialize HII information for the FrontPage + +Arguments: + None + +Returns: + EFI_SUCCESS - The operation is successful. + EFI_DEVICE_ERROR - If the dynamic opcode creation failed. + +--*/ +{ + EFI_STATUS Status; + EFI_HII_PACKAGES *PackageList; + EFI_HII_UPDATE_DATA *UpdateData; + IFR_OPTION *OptionList; + CHAR16 *LanguageString; + UINTN OptionCount; + UINTN Index; + STRING_REF Token; + UINT16 Key; + CHAR8 AsciiLang[4]; + CHAR16 UnicodeLang[4]; + CHAR16 Lang[4]; + CHAR16 *StringBuffer; + UINTN BufferSize; + UINT8 *TempBuffer; + + UpdateData = NULL; + OptionList = NULL; + + if (ReInitializeStrings) { + // + // BugBug: Dont' use a goto + // + goto ReInitStrings; + } + // + // Go ahead and initialize the Device Manager + // + InitializeDeviceManager (); + + // + // BugBug: if FrontPageVfrBin is generated by a tool, why are we patching it here + // + TempBuffer = (UINT8 *) FrontPageVfrBin; + TempBuffer = TempBuffer + sizeof (EFI_HII_PACK_HEADER); + TempBuffer = (UINT8 *) &((EFI_IFR_FORM_SET *) TempBuffer)->NvDataSize; + *TempBuffer = 1; + + gCallbackKey = 0; + + PackageList = PreparePackages (1, &gBdsStringPackGuid, FrontPageVfrBin); + + Status = Hii->NewPack (Hii, PackageList, &gFrontPageHandle); + + gBS->FreePool (PackageList); + + // + // There will be only one FormConfig in the system + // If there is another out there, someone is trying to install us + // again. Fail that scenario. + // + Status = gBS->LocateProtocol ( + &gEfiFormBrowserProtocolGuid, + NULL, + &gBrowser + ); + + // + // This example does not implement worker functions + // for the NV accessor functions. Only a callback evaluator + // + FrontPageCallback.NvRead = NULL; + FrontPageCallback.NvWrite = NULL; + FrontPageCallback.Callback = FrontPageCallbackRoutine; + + // + // Install protocol interface + // + FrontPageCallbackHandle = NULL; + Status = gBS->InstallProtocolInterface ( + &FrontPageCallbackHandle, + &gEfiFormCallbackProtocolGuid, + EFI_NATIVE_INTERFACE, + &FrontPageCallback + ); + ASSERT_EFI_ERROR (Status); + +ReInitStrings: + // + // BugBug: This logic is in BdsInitLanguage. It should not be in two places! + // + BufferSize = 4; + Status = gRT->GetVariable ( + L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &BufferSize, + AsciiLang + ); + + for (Index = 0; Index < 3; Index++) { + UnicodeLang[Index] = (CHAR16) AsciiLang[Index]; + } + + UnicodeLang[3] = 0; + + // + // Allocate space for creation of UpdateData Buffer + // + UpdateData = AllocateZeroPool (0x1000); + ASSERT (UpdateData != NULL); + + OptionList = AllocateZeroPool (0x1000); + ASSERT (OptionList != NULL); + + // + // Flag update pending in FormSet + // + UpdateData->FormSetUpdate = TRUE; + // + // Register CallbackHandle data for FormSet + // + UpdateData->FormCallbackHandle = (EFI_PHYSICAL_ADDRESS) (UINTN) FrontPageCallbackHandle; + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = 0; + UpdateData->DataCount = 1; + + // + // Collect the languages from what our current Language support is based on our VFR + // + Hii->GetPrimaryLanguages (Hii, gFrontPageHandle, &LanguageString); + + OptionCount = 0; + + // + // Try for a 512 byte Buffer + // + BufferSize = 0x200; + + // + // Allocate memory for our Form binary + // + StringBuffer = AllocateZeroPool (BufferSize); + ASSERT (StringBuffer != NULL); + + for (Index = 0; LanguageString[Index] != 0; Index += 3) { + Token = 0; + CopyMem (Lang, &LanguageString[Index], 6); + Lang[3] = 0; + + if (!StrCmp (Lang, UnicodeLang)) { + mLastSelection = (UINT16) OptionCount; + } + + Status = Hii->GetString (Hii, gStringPackHandle, 1, TRUE, Lang, &BufferSize, StringBuffer); + Hii->NewString (Hii, NULL, gStringPackHandle, &Token, StringBuffer); + CopyMem (&OptionList[OptionCount].StringToken, &Token, sizeof (UINT16)); + CopyMem (&OptionList[OptionCount].Value, &OptionCount, sizeof (UINT16)); + Key = 0x1234; + CopyMem (&OptionList[OptionCount].Key, &Key, sizeof (UINT16)); + OptionList[OptionCount].Flags = EFI_IFR_FLAG_INTERACTIVE | EFI_IFR_FLAG_NV_ACCESS; + OptionCount++; + } + + gBS->FreePool (LanguageString); + + if (ReInitializeStrings) { + gBS->FreePool (StringBuffer); + gBS->FreePool (OptionList); + return EFI_SUCCESS; + } + + Status = CreateOneOfOpCode ( + FRONT_PAGE_QUESTION_ID, // Question ID + FRONT_PAGE_DATA_WIDTH, // Data Width + (STRING_REF) STRING_TOKEN (STR_LANGUAGE_SELECT), // Prompt Token + (STRING_REF) STRING_TOKEN (STR_LANGUAGE_SELECT_HELP), // Help Token + OptionList, // List of Options + OptionCount, // Number of Options + &UpdateData->Data // Data Buffer + ); + + // + // Assign the number of options and the oneof and endoneof op-codes to count + // + UpdateData->DataCount = (UINT8) (OptionCount + 2); + + Hii->UpdateForm (Hii, gFrontPageHandle, (EFI_FORM_LABEL) 0x0002, TRUE, UpdateData); + + gBS->FreePool (UpdateData); + // + // gBS->FreePool (OptionList); + // + gBS->FreePool (StringBuffer); + return Status; +} + +EFI_STATUS +CallFrontPage ( + VOID + ) +/*++ + +Routine Description: + + Call the browser and display the front page + +Arguments: + + None + +Returns: + +--*/ +{ + EFI_STATUS Status; + UINT8 FakeNvRamMap[1]; + + // + // Begin waiting for USER INPUT + // + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_INPUT_WAIT) + ); + + FakeNvRamMap[0] = (UINT8) mLastSelection; + Status = gBrowser->SendForm ( + gBrowser, + TRUE, // Use the database + &gFrontPageHandle, // The HII Handle + 1, + NULL, + FrontPageCallbackHandle, // This is the handle that the interface to the callback was installed on + FakeNvRamMap, + NULL, + NULL + ); + + Hii->ResetStrings (Hii, gFrontPageHandle); + + return Status; +} + +EFI_STATUS +GetStringFromToken ( + IN EFI_GUID *ProducerGuid, + IN STRING_REF Token, + OUT CHAR16 **String + ) +/*++ + +Routine Description: + + Acquire the string associated with the ProducerGuid and return it. + +Arguments: + + ProducerGuid - The Guid to search the HII database for + Token - The token value of the string to extract + String - The string that is extracted + +Returns: + + EFI_SUCCESS - The function returns EFI_SUCCESS always. + +--*/ +{ + EFI_STATUS Status; + UINT16 HandleBufferLength; + EFI_HII_HANDLE *HiiHandleBuffer; + UINTN StringBufferLength; + UINTN NumberOfHiiHandles; + UINTN Index; + UINT16 Length; + EFI_GUID HiiGuid; + + HandleBufferLength = 0x1000; + HiiHandleBuffer = NULL; + + // + // Get all the Hii handles + // + HiiHandleBuffer = AllocateZeroPool (HandleBufferLength); + + Status = Hii->FindHandles (Hii, &HandleBufferLength, HiiHandleBuffer); + ASSERT_EFI_ERROR (Status); + + // + // Get the Hii Handle that matches the StructureNode->ProducerName + // + NumberOfHiiHandles = HandleBufferLength / sizeof (EFI_HII_HANDLE); + for (Index = 0; Index < NumberOfHiiHandles; Index++) { + Length = 0; + Status = ExtractDataFromHiiHandle ( + HiiHandleBuffer[Index], + &Length, + NULL, + &HiiGuid + ); + if (CompareGuid (ProducerGuid, &HiiGuid)) { + break; + } + } + // + // Find the string based on the current language + // + StringBufferLength = 0x100; + *String = AllocateZeroPool (0x100); + Status = Hii->GetString ( + Hii, + HiiHandleBuffer[Index], + Token, + FALSE, + NULL, + &StringBufferLength, + *String + ); + + if (EFI_ERROR (Status)) { + gBS->FreePool (*String); + *String = GetStringById (STRING_TOKEN (STR_MISSING_STRING)); + } + + gBS->FreePool (HiiHandleBuffer); + return EFI_SUCCESS; +} + +VOID +ConvertProcessorToString ( + IN EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency, + OUT CHAR16 **String + ) +/*++ + +Routine Description: + + Convert Processor Frequency Data to a string + +Arguments: + + ProcessorFrequency - The frequency data to process + String - The string that is created + +Returns: + +--*/ +{ + CHAR16 *StringBuffer; + UINTN Index; + UINT32 FreqMhz; + + if (ProcessorFrequency->Exponent >= 6) { + FreqMhz = ProcessorFrequency->Value; + for (Index = 0; Index < (UINTN) (ProcessorFrequency->Exponent - 6); Index++) { + FreqMhz *= 10; + } + } else { + FreqMhz = 0; + } + + StringBuffer = AllocateZeroPool (0x20); + ASSERT (StringBuffer != NULL); + Index = UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, FreqMhz / 1000, 3); + StrCat (StringBuffer, L"."); + UnicodeValueToString (StringBuffer + Index + 1, PREFIX_ZERO, (FreqMhz % 1000) / 10, 2); + StrCat (StringBuffer, L" GHz"); + + *String = (CHAR16 *) StringBuffer; + + return ; +} + +VOID +ConvertMemorySizeToString ( + IN UINT32 MemorySize, + OUT CHAR16 **String + ) +/*++ + +Routine Description: + + Convert Memory Size to a string + +Arguments: + + MemorySize - The size of the memory to process + String - The string that is created + +Returns: + +--*/ +{ + CHAR16 *StringBuffer; + + StringBuffer = AllocateZeroPool (0x20); + ASSERT (StringBuffer != NULL); + UnicodeValueToString (StringBuffer, LEFT_JUSTIFY, MemorySize, 6); + StrCat (StringBuffer, L" MB RAM"); + + *String = (CHAR16 *) StringBuffer; + + return ; +} + +VOID +UpdateFrontPageStrings ( + VOID + ) +/*++ + +Routine Description: + + Update the banner information for the Front Page based on DataHub information + +Arguments: + + None + +Returns: + +--*/ +{ + EFI_STATUS Status; + STRING_REF TokenToUpdate; + CHAR16 *NewString; + UINT64 MonotonicCount; + EFI_DATA_HUB_PROTOCOL *DataHub; + EFI_DATA_RECORD_HEADER *Record; + EFI_SUBCLASS_TYPE1_HEADER *DataHeader; + EFI_MISC_BIOS_VENDOR_DATA *BiosVendor; + EFI_MISC_SYSTEM_MANUFACTURER_DATA *SystemManufacturer; + EFI_PROCESSOR_VERSION_DATA *ProcessorVersion; + EFI_PROCESSOR_CORE_FREQUENCY_DATA *ProcessorFrequency; + EFI_MEMORY_ARRAY_START_ADDRESS_DATA *MemoryArray; + CHAR8 LangCode[3]; + CHAR16 Lang[3]; + UINTN Size; + UINTN Index; + BOOLEAN Find[5]; + + ZeroMem (Find, sizeof (Find)); + + // + // Update Front Page strings + // + Status = gBS->LocateProtocol ( + &gEfiDataHubProtocolGuid, + NULL, + &DataHub + ); + ASSERT_EFI_ERROR (Status); + + Size = 3; + + Status = gRT->GetVariable ( + L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &Size, + LangCode + ); + + for (Index = 0; Index < 3; Index++) { + Lang[Index] = (CHAR16) LangCode[Index]; + } + + MonotonicCount = 0; + Record = NULL; + do { + Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record); + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1); + if (CompareGuid (&Record->DataRecordGuid, &mMiscSubClass) && + (DataHeader->RecordType == EFI_MISC_BIOS_VENDOR_RECORD_NUMBER) + ) { + BiosVendor = (EFI_MISC_BIOS_VENDOR_DATA *) (DataHeader + 1); + GetStringFromToken (&Record->ProducerName, BiosVendor->BiosVersion, &NewString); + TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_BIOS_VERSION; + Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString); + gBS->FreePool (NewString); + Find[0] = TRUE; + } + + if (CompareGuid (&Record->DataRecordGuid, &mMiscSubClass) && + (DataHeader->RecordType == EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER) + ) { + SystemManufacturer = (EFI_MISC_SYSTEM_MANUFACTURER_DATA *) (DataHeader + 1); + GetStringFromToken (&Record->ProducerName, SystemManufacturer->SystemProductName, &NewString); + TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_COMPUTER_MODEL; + Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString); + gBS->FreePool (NewString); + Find[1] = TRUE; + } + + if (CompareGuid (&Record->DataRecordGuid, &mProcessorSubClass) && + (DataHeader->RecordType == ProcessorVersionRecordType) + ) { + ProcessorVersion = (EFI_PROCESSOR_VERSION_DATA *) (DataHeader + 1); + GetStringFromToken (&Record->ProducerName, *ProcessorVersion, &NewString); + TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_CPU_MODEL; + Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString); + gBS->FreePool (NewString); + Find[2] = TRUE; + } + + if (CompareGuid (&Record->DataRecordGuid, &mProcessorSubClass) && + (DataHeader->RecordType == ProcessorCoreFrequencyRecordType) + ) { + ProcessorFrequency = (EFI_PROCESSOR_CORE_FREQUENCY_DATA *) (DataHeader + 1); + ConvertProcessorToString (ProcessorFrequency, &NewString); + TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_CPU_SPEED; + Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString); + gBS->FreePool (NewString); + Find[3] = TRUE; + } + + if (CompareGuid (&Record->DataRecordGuid, &mMemorySubClass) && + (DataHeader->RecordType == EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER) + ) { + MemoryArray = (EFI_MEMORY_ARRAY_START_ADDRESS_DATA *) (DataHeader + 1); + ConvertMemorySizeToString((UINT32)(RShiftU64((MemoryArray->MemoryArrayEndAddress - + MemoryArray->MemoryArrayStartAddress + 1), 20)), + &NewString); + TokenToUpdate = (STRING_REF) STR_FRONT_PAGE_MEMORY_SIZE; + Hii->NewString (Hii, Lang, gFrontPageHandle, &TokenToUpdate, NewString); + gBS->FreePool (NewString); + Find[4] = TRUE; + } + } + } while (!EFI_ERROR (Status) && (MonotonicCount != 0) && !(Find[0] && Find[1] && Find[2] && Find[3] && Find[4])); + + return ; +} + +VOID +PlatformBdsEnterFrontPage ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ) +/*++ + +Routine Description: + This function is the main entry of the platform setup entry. + The function will present the main menu of the system setup, + this is the platform reference part and can be customize. + +Arguments: + TimeoutDefault - The fault time out value before the system + continue to boot. + ConnectAllHappened - The indicater to check if the connect all have + already happended. + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + EFI_HII_UPDATE_DATA *UpdateData; + EFI_CONSOLE_CONTROL_PROTOCOL *ConsoleControl; + + // + // Indicate if we need connect all in the platform setup + // + if (ConnectAllHappened) { + gConnectAllHappened = TRUE; + } + // + // Allocate space for creation of Buffer + // + UpdateData = AllocateZeroPool (0x1000); + ASSERT (UpdateData != NULL); + + UpdateData->FormSetUpdate = FALSE; + UpdateData->FormCallbackHandle = 0; + UpdateData->FormUpdate = FALSE; + UpdateData->FormTitle = 0; + UpdateData->DataCount = 1; + + // + // Remove Banner Op-code if any at this label + // + Hii->UpdateForm (Hii, gFrontPageHandle, (EFI_FORM_LABEL) 0xFFFF, FALSE, UpdateData); + + // + // Create Banner Op-code which reflects correct timeout value + // + CreateBannerOpCode ( + STRING_TOKEN (STR_TIME_OUT_PROMPT), + TimeoutDefault, + (UINT8) EFI_IFR_BANNER_TIMEOUT, + &UpdateData->Data + ); + + // + // Add Banner Op-code at this label + // + Hii->UpdateForm (Hii, gFrontPageHandle, (EFI_FORM_LABEL) 0xFFFF, TRUE, UpdateData); + + do { + + InitializeFrontPage (TRUE); + + // + // Update Front Page strings + // + UpdateFrontPageStrings (); + + gCallbackKey = 0; + PERF_START (0, "BdsTimeOut", "BDS", 0); + Status = CallFrontPage (); + PERF_END (0, "BdsTimeOut", "BDS", 0); + + // + // If gCallbackKey is greater than 1 and less or equal to 5, + // it will lauch configuration utilities. + // 2 = set language + // 3 = boot manager + // 4 = device manager + // 5 = boot maintainenance manager + // + if ((gCallbackKey > 0x0001) && (gCallbackKey <= 0x0005)) { + REPORT_STATUS_CODE ( + EFI_PROGRESS_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_PC_USER_SETUP) + ); + } + // + // Based on the key that was set, we can determine what to do + // + switch (gCallbackKey) { + // + // The first 4 entries in the Front Page are to be GUARANTEED to remain constant so IHV's can + // describe to their customers in documentation how to find their setup information (namely + // under the device manager and specific buckets) + // + // These entries consist of the Continue, Select language, Boot Manager, and Device Manager + // + case 0x0001: + // + // User hit continue + // + break; + + case 0x0002: + // + // User made a language setting change - display front page again + // + break; + + case 0x0003: + // + // User chose to run the Boot Manager + // + CallBootManager (); + break; + + case 0x0004: + // + // Display the Device Manager + // + do { + CallDeviceManager(); + } while (gCallbackKey == 4); + break; + + case 0x0005: + // + // Display the Boot Maintenance Manager + // + BdsStartBootMaint (); + break; + } + + } while ((Status == EFI_SUCCESS) && (gCallbackKey != 1)); + + // + // Automatically load current entry + // Note: The following lines of code only execute when Auto boot + // takes affect + // + Status = gBS->LocateProtocol (&gEfiConsoleControlProtocolGuid, NULL, &ConsoleControl); + ConsoleControl->SetMode (ConsoleControl, EfiConsoleControlScreenText); + +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPage.h b/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPage.h new file mode 100644 index 0000000000..82aa380b46 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPage.h @@ -0,0 +1,100 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FrontPage.h + +Abstract: + + FrontPage routines to handle the callbacks and browser calls + +Revision History + +--*/ + +#ifndef _FRONT_PAGE_H +#define _FRONT_PAGE_H + +#include "Generic/DeviceMngr/DeviceManager.h" +#include "Generic/BootMaint/bootmaint.h" +#include "Generic/BootMngr/BootManager.h" + +// +// This is the VFR compiler generated header file which defines the +// string identifiers. +// +#include "BdsStrDefs.h" +#define EFI_DISK_DEVICE_CLASS 0x01 +#define EFI_VIDEO_DEVICE_CLASS 0x02 +#define EFI_NETWORK_DEVICE_CLASS 0x04 +#define EFI_INPUT_DEVICE_CLASS 0x08 +#define EFI_ON_BOARD_DEVICE_CLASS 0x10 +#define EFI_OTHER_DEVICE_CLASS 0x20 +#define EFI_VBIOS_CLASS 0x40 + +#define SET_VIDEO_BIOS_TYPE_QUESTION_ID 0x00 + +#pragma pack(1) +typedef struct { + UINT8 VideoBIOS; +} MyDevMgrIfrNVData; +#pragma pack() + +#define EFI_FP_CALLBACK_DATA_SIGNATURE EFI_SIGNATURE_32 ('F', 'P', 'C', 'B') +#define EFI_FP_CALLBACK_DATA_FROM_THIS(a) \ + CR (a, \ + EFI_FRONTPAGE_CALLBACK_INFO, \ + DevMgrCallback, \ + EFI_FP_CALLBACK_DATA_SIGNATURE \ + ) + +typedef struct { + UINTN Signature; + MyDevMgrIfrNVData Data; + EFI_HII_HANDLE DevMgrHiiHandle; + EFI_HANDLE CallbackHandle; + EFI_FORM_CALLBACK_PROTOCOL DevMgrCallback; +} EFI_FRONTPAGE_CALLBACK_INFO; + +// +// These are the VFR compiler generated data representing our VFR data. +// +// BugBug: we should put g in front of these tool generated globals. +// maybe even gVrf would be a better prefix +// +extern UINT8 FrontPageVfrBin[]; +extern UINT8 FrontPageStringsStr[]; +extern UINT8 DeviceManagerVfrBin[]; +extern UINT8 DeviceManagerStringsStr[]; + +#define FRONT_PAGE_QUESTION_ID 0x0000 +#define FRONT_PAGE_DATA_WIDTH 0x01 + +EFI_STATUS +InitializeFrontPage ( + IN BOOLEAN ReInitializeStrings + ); + +BOOLEAN +TimeCompare ( + IN EFI_TIME *FirstTime, + IN EFI_TIME *SecondTime + ); + +VOID +PlatformBdsEnterFrontPage ( + IN UINT16 TimeoutDefault, + IN BOOLEAN ConnectAllHappened + ); + +#endif // _FRONT_PAGE_H_ + diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPageStrings.uni b/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPageStrings.uni new file mode 100644 index 0000000000..76dbdcfd4f Binary files /dev/null and b/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPageStrings.uni differ diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPageVfr.Vfr b/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPageVfr.Vfr new file mode 100644 index 0000000000..77efd2d949 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/FrontPageVfr.Vfr @@ -0,0 +1,159 @@ +// *++ +// +// Copyright (c) 2006, 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. +// +// Module Name: +// +// FrontPageVfr.vfr +// +// Abstract: +// +// Browser formset. +// +// Revision History: +// +// --*/ + +#include "BdsStrDefs.h" + +#define FORMSET_GUID { 0x9e0c30bc, 0x3f06, 0x4ba6, { 0x82, 0x88, 0x9, 0x17, 0x9b, 0x85, 0x5d, 0xbe } } + +#define FRONT_PAGE_ITEM_ONE 0x0001 +#define FRONT_PAGE_ITEM_TWO 0x0002 +#define FRONT_PAGE_ITEM_THREE 0x0003 +#define FRONT_PAGE_ITEM_FOUR 0x0004 +#define FRONT_PAGE_ITEM_FIVE 0x0005 + +#define FRONT_PAGE_TIMEOUT 0xFFFF +#define FRONT_PAGE_CLASS 0x0000 +#define FRONT_PAGE_SUBCLASS 0x0002 + +formset + guid = FORMSET_GUID, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE), + help = STRING_TOKEN(STR_NULL_STRING), + class = FRONT_PAGE_CLASS, + subclass = FRONT_PAGE_SUBCLASS, + + form formid = 0x1000, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_COMPUTER_MODEL), + line 0, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_CPU_MODEL), + line 1, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_CPU_SPEED), + line 1, + align right; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_BIOS_VERSION), + line 2, + align left; + + banner + title = STRING_TOKEN(STR_FRONT_PAGE_MEMORY_SIZE), + line 2, + align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_LEFT), +// line 0, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_0_RIGHT), +// line 0, +// align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_LEFT), +// line 1, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_1_RIGHT), +// line 1, +// align right; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_2_LEFT), +// line 2, +// align left; + +// banner +// title = STRING_TOKEN(STR_FRONT_PAGE_BANNER_3_LEFT), +// line 3, +// align left; + + goto FRONT_PAGE_ITEM_ONE, + prompt = STRING_TOKEN(STR_CONTINUE_PROMPT), + help = STRING_TOKEN(STR_CONTINUE_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = 0x0001; + + label FRONT_PAGE_ITEM_TWO; + // + // This is where we will dynamically add a OneOf type op-code to select Languages from the + // currently available choices + // + + goto FRONT_PAGE_ITEM_THREE, + prompt = STRING_TOKEN(STR_BOOT_MANAGER), + help = STRING_TOKEN(STR_BOOT_MANAGER_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = 0x1064; + + goto FRONT_PAGE_ITEM_FOUR, + prompt = STRING_TOKEN(STR_DEVICE_MANAGER), + help = STRING_TOKEN(STR_DEVICE_MANAGER_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = 0x8567; + + goto FRONT_PAGE_ITEM_FIVE, + prompt = STRING_TOKEN(STR_BOOT_MAINT_MANAGER), + help = STRING_TOKEN(STR_BOOT_MAINT_MANAGER_HELP), + flags = INTERACTIVE | NV_ACCESS, + key = 0x9876; + + label FRONT_PAGE_TIMEOUT; +// If one wanted to hard-code a value one could do it below, but our implementation follows EFI architecture +// and honors the TimeOut NV variable +// +// banner +// title = STRING_TOKEN(STR_TIME_OUT_PROMPT), +// timeout = 0x000A; + + endform; + + form formid = FRONT_PAGE_ITEM_ONE, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + endform; + + form formid = FRONT_PAGE_ITEM_THREE, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + endform; + + form formid = FRONT_PAGE_ITEM_FOUR, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + endform; + + form formid = FRONT_PAGE_ITEM_FIVE, + title = STRING_TOKEN(STR_FRONT_PAGE_TITLE); + endform; + +endformset; diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/Language.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Language.c new file mode 100644 index 0000000000..21d61f1135 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Language.c @@ -0,0 +1,431 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + language.c + +Abstract: + + Language settings + +Revision History + +--*/ + +#include "String.h" +#include "Language.h" + +#define NARROW_GLYPH_NUMBER 8 +#define WIDE_GLYPH_NUMBER 75 + +// +// Default language code, currently is English +// +CHAR8 *mDefaultLangCode = "eng"; + +typedef struct { + EFI_HII_FONT_PACK FixedLength; + EFI_NARROW_GLYPH NarrowArray[NARROW_GLYPH_NUMBER]; + EFI_WIDE_GLYPH WideArray[WIDE_GLYPH_NUMBER]; +} FONT_PACK; + +FONT_PACK mFontPack = { + sizeof (EFI_HII_FONT_PACK) + (NARROW_GLYPH_NUMBER * sizeof (EFI_NARROW_GLYPH)) + (WIDE_GLYPH_NUMBER * sizeof (EFI_WIDE_GLYPH)), + EFI_HII_FONT, + NARROW_GLYPH_NUMBER, + WIDE_GLYPH_NUMBER, + { // Narrow Glyphs + { + 0x05d0, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x4E, + 0x6E, + 0x62, + 0x32, + 0x32, + 0x3C, + 0x68, + 0x4C, + 0x4C, + 0x46, + 0x76, + 0x72, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d1, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x78, + 0x7C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x7E, + 0x7E, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d2, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x78, + 0x7C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x1C, + 0x3E, + 0x66, + 0x66, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d3, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x7E, + 0x7E, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d4, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x7C, + 0x7E, + 0x06, + 0x06, + 0x06, + 0x06, + 0x66, + 0x66, + 0x66, + 0x66, + 0x66, + 0x66, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d5, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x3C, + 0x3C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x0C, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x05d6, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x38, + 0x38, + 0x1E, + 0x1E, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x18, + 0x00, + 0x00, + 0x00, + 0x00 + } + }, + { + 0x0000, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + } + } + }, + { // Wide Glyphs + { + 0x0020, + 0x00, + { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + }, + { + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + }, + { + 0x00, + 0x00, + 0x00 + } + }, // + } +}; + +VOID +ExportFonts ( + VOID + ) +/*++ + +Routine Description: + Routine to export glyphs to the HII database. This is in addition to whatever is defined in the Graphics Console driver. + +Arguments: + None + +Returns: + +--*/ +{ + EFI_HII_HANDLE HiiHandle; + EFI_HII_PACKAGES *PackageList; + + PackageList = PreparePackages (1, NULL, &mFontPack); + // + // Register our Fonts into the global database + // + HiiHandle = 0; + Hii->NewPack (Hii, PackageList, &HiiHandle); + + gBS->FreePool (PackageList); +} + +VOID +InitializeLanguage ( + BOOLEAN LangCodesSettingRequired + ) +/*++ + +Routine Description: + Determine the current language that will be used + based on language related EFI Variables + +Arguments: + LangCodesSettingRequired - If required to set LangCode variable + +Returns: + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + UINTN Size; + CHAR8 LangCode[ISO_639_2_ENTRY_SIZE]; + CHAR8 *LangCodes; + CHAR16 *LanguageString; + + LanguageString = NULL; + LangCodes = NULL; + + ExportFonts (); + + // + // Collect the languages from what our current Language support is based on our VFR + // + Hii->GetPrimaryLanguages (Hii, gStringPackHandle, &LanguageString); + + LangCodes = AllocatePool (StrLen (LanguageString)); + ASSERT (LangCodes); + + // + // Convert LanguageString from Unicode to EFI defined ASCII LangCodes + // + for (Index = 0; LanguageString[Index] != 0x0000; Index++) { + LangCodes[Index] = (CHAR8) LanguageString[Index]; + } + + LangCodes[Index] = 0; + + if (LangCodesSettingRequired) { + Status = gRT->SetVariable ( + L"LangCodes", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + AsciiStrLen (LangCodes), + LangCodes + ); + } + // + // Find current LangCode from Lang NV Variable + // + Size = ISO_639_2_ENTRY_SIZE; + Status = gRT->GetVariable ( + L"Lang", + &gEfiGlobalVariableGuid, + NULL, + &Size, + &LangCode + ); + + if (!EFI_ERROR (Status)) { + Status = EFI_NOT_FOUND; + for (Index = 0; LangCodes[Index] != 0; Index += ISO_639_2_ENTRY_SIZE) { + if (CompareMem (&LangCodes[Index], LangCode, ISO_639_2_ENTRY_SIZE) == 0) { + Status = EFI_SUCCESS; + break; + } + } + } + // + // If we cannot get language code from Lang variable, + // or LangCode cannot be found from language table, + // set the mDefaultLangCode to Lang variable. + // + if (EFI_ERROR (Status)) { + Status = gRT->SetVariable ( + L"Lang", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + ISO_639_2_ENTRY_SIZE, + mDefaultLangCode + ); + } + + if (LangCodes) { + gBS->FreePool (LangCodes); + } + + if (LanguageString != NULL) { + gBS->FreePool (LanguageString); + } + +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/Language.h b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Language.h new file mode 100644 index 0000000000..6b6d887040 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Language.h @@ -0,0 +1,36 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Language.h + +Abstract: + + Language setting + +Revision History + +--*/ + +#ifndef _LANGUAGE_H +#define _LANGUAGE_H + +#ifndef ISO_639_2_ENTRY_SIZE +#define ISO_639_2_ENTRY_SIZE 3 +#endif + +VOID +InitializeLanguage ( + BOOLEAN LangCodesSettingRequired + ); + +#endif // _LANGUAGE_H_ diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/MemoryTest.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/MemoryTest.c new file mode 100644 index 0000000000..f1fedf391a --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/MemoryTest.c @@ -0,0 +1,386 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MemoryTest.c + +Abstract: + + Perform the platform memory test + +--*/ + +#include "bds.h" +#include "BdsPlatform.h" +#include "String.h" + +// +// BDS Platform Functions +// +EFI_STATUS +PlatformBdsShowProgress ( + IN EFI_UGA_PIXEL TitleForeground, + IN EFI_UGA_PIXEL TitleBackground, + IN CHAR16 *Title, + IN EFI_UGA_PIXEL ProgressColor, + IN UINTN Progress, + IN UINTN PreviousValue + ) +/*++ + +Routine Description: + + Show progress bar with title above it. It only works in UGA mode. + +Arguments: + + TitleForeground - Foreground color for Title. + TitleBackground - Background color for Title. + Title - Title above progress bar. + ProgressColor - Progress bar color. + Progress - Progress (0-100) + +Returns: + + EFI_STATUS - Success update the progress bar + +--*/ +{ + EFI_STATUS Status; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + UINT32 SizeOfX; + UINT32 SizeOfY; + UINT32 ColorDepth; + UINT32 RefreshRate; + EFI_UGA_PIXEL Color; + UINTN BlockHeight; + UINTN BlockWidth; + UINTN BlockNum; + UINTN PosX; + UINTN PosY; + UINTN Index; + + if (Progress > 100) { + return EFI_INVALID_PARAMETER; + } + + Status = gBS->HandleProtocol ( + gST->ConsoleOutHandle, + &gEfiUgaDrawProtocolGuid, + &UgaDraw + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Status = UgaDraw->GetMode ( + UgaDraw, + &SizeOfX, + &SizeOfY, + &ColorDepth, + &RefreshRate + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + BlockWidth = SizeOfX / 100; + BlockHeight = SizeOfY / 50; + + BlockNum = Progress; + + PosX = 0; + PosY = SizeOfY * 48 / 50; + + if (BlockNum == 0) { + // + // Clear progress area + // + SetMem (&Color, sizeof (EFI_UGA_PIXEL), 0x0); + + Status = UgaDraw->Blt ( + UgaDraw, + &Color, + EfiUgaVideoFill, + 0, + 0, + 0, + PosY - GLYPH_HEIGHT - 1, + SizeOfX, + SizeOfY - (PosY - GLYPH_HEIGHT - 1), + SizeOfX * sizeof (EFI_UGA_PIXEL) + ); + } + // + // Show progress by drawing blocks + // + for (Index = PreviousValue; Index < BlockNum; Index++) { + PosX = Index * BlockWidth; + Status = UgaDraw->Blt ( + UgaDraw, + &ProgressColor, + EfiUgaVideoFill, + 0, + 0, + PosX, + PosY, + BlockWidth - 1, + BlockHeight, + (BlockWidth) * sizeof (EFI_UGA_PIXEL) + ); + } + + PrintXY ( + (SizeOfX - StrLen (Title) * GLYPH_WIDTH) / 2, + PosY - GLYPH_HEIGHT - 1, + &TitleForeground, + &TitleBackground, + Title + ); + + return EFI_SUCCESS; +} + +EFI_STATUS +BdsMemoryTest ( + IN EXTENDMEM_COVERAGE_LEVEL Level + ) +/*++ + +Routine Description: + + Perform the memory test base on the memory test intensive level, + and update the memory resource. + +Arguments: + + Level - The memory test intensive level. + +Returns: + + EFI_STATUS - Success test all the system memory and update + the memory resource + +--*/ +{ + EFI_STATUS Status; + EFI_STATUS InitStatus; + EFI_STATUS KeyStatus; + EFI_STATUS ReturnStatus; + BOOLEAN RequireSoftECCInit; + EFI_GENERIC_MEMORY_TEST_PROTOCOL *GenMemoryTest; + UINT64 TestedMemorySize; + UINT64 TotalMemorySize; + UINTN TestPercent; + UINT64 PreviousValue; + BOOLEAN ErrorOut; + BOOLEAN TestAbort; + EFI_INPUT_KEY Key; + CHAR16 StrPercent[16]; + CHAR16 *StrTotalMemory; + CHAR16 *Pos; + CHAR16 *TmpStr; + EFI_UGA_PIXEL Foreground; + EFI_UGA_PIXEL Background; + EFI_UGA_PIXEL Color; + UINT8 Value; + UINTN DataSize; + UINT32 Attributes; + + ReturnStatus = EFI_SUCCESS; + ZeroMem (&Key, sizeof (EFI_INPUT_KEY)); + + Pos = AllocatePool (128); + + if (Pos == NULL) { + return ReturnStatus; + } + + StrTotalMemory = Pos; + + TestedMemorySize = 0; + TotalMemorySize = 0; + PreviousValue = 0; + ErrorOut = FALSE; + TestAbort = FALSE; + + SetMem (&Foreground, sizeof (EFI_UGA_PIXEL), 0xff); + SetMem (&Background, sizeof (EFI_UGA_PIXEL), 0x0); + SetMem (&Color, sizeof (EFI_UGA_PIXEL), 0xff); + + RequireSoftECCInit = FALSE; + + gST->ConOut->ClearScreen (gST->ConOut); + gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT); + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + + Status = gBS->LocateProtocol ( + &gEfiGenericMemTestProtocolGuid, + NULL, + &GenMemoryTest + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (Pos); + return EFI_SUCCESS; + } + + InitStatus = GenMemoryTest->MemoryTestInit ( + GenMemoryTest, + Level, + &RequireSoftECCInit + ); + if (InitStatus == EFI_NO_MEDIA) { + // + // The PEI codes also have the relevant memory test code to check the memory, + // it can select to test some range of the memory or all of them. If PEI code + // checks all the memory, this BDS memory test will has no not-test memory to + // do the test, and then the status of EFI_NO_MEDIA will be returned by + // "MemoryTestInit". So it does not need to test memory again, just return. + // + gBS->FreePool (Pos); + return EFI_SUCCESS; + } + + gST->ConOut->SetCursorPosition (gST->ConOut, 0, 2); + TmpStr = GetStringById (STRING_TOKEN (STR_ESC_TO_SKIP_MEM_TEST)); + + if (TmpStr != NULL) { + gST->ConOut->OutputString (gST->ConOut, TmpStr); + gBS->FreePool (TmpStr); + } + + do { + Status = GenMemoryTest->PerformMemoryTest ( + GenMemoryTest, + &TestedMemorySize, + &TotalMemorySize, + &ErrorOut, + TestAbort + ); + if (ErrorOut && (Status == EFI_DEVICE_ERROR)) { + TmpStr = GetStringById (STRING_TOKEN (STR_SYSTEM_MEM_ERROR)); + if (TmpStr != NULL) { + PrintXY (10, 10, NULL, NULL, TmpStr); + gST->ConOut->SetCursorPosition (gST->ConOut, 0, 4); + gST->ConOut->OutputString (gST->ConOut, TmpStr); + gBS->FreePool (TmpStr); + } + + ASSERT (0); + } + + TestPercent = (UINTN) DivU64x32 ( + DivU64x32 (MultU64x32 (TestedMemorySize, 100), 16), + (UINTN)DivU64x32 (TotalMemorySize, 16) + ); + if (TestPercent != PreviousValue) { + UnicodeValueToString (StrPercent, 0, TestPercent, 0); + gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0); + TmpStr = GetStringById (STRING_TOKEN (STR_MEMORY_TEST_PERCENT)); + if (TmpStr != NULL) { + BdsLibOutputStrings (gST->ConOut, StrPercent, TmpStr, NULL); + gBS->FreePool (TmpStr); + } + + TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); + if (TmpStr != NULL) { + PlatformBdsShowProgress ( + Foreground, + Background, + TmpStr, + Color, + TestPercent, + (UINTN) PreviousValue + ); + gBS->FreePool (TmpStr); + } + } + + PreviousValue = TestPercent; + + KeyStatus = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); + if (Key.ScanCode == SCAN_ESC) { + if (!RequireSoftECCInit) { + TmpStr = GetStringById (STRING_TOKEN (STR_PERFORM_MEM_TEST)); + if (TmpStr != NULL) { + PlatformBdsShowProgress ( + Foreground, + Background, + TmpStr, + Color, + 100, + (UINTN) PreviousValue + ); + gBS->FreePool (TmpStr); + } + + gST->ConOut->SetCursorPosition (gST->ConOut, 0, 0); + gST->ConOut->OutputString (gST->ConOut, L"100"); + Status = GenMemoryTest->Finished (GenMemoryTest); + goto Done; + } + + TestAbort = TRUE; + } + } while (Status != EFI_NOT_FOUND); + + Status = GenMemoryTest->Finished (GenMemoryTest); + +Done: + UnicodeValueToString (StrTotalMemory, COMMA_TYPE, (UINTN) TotalMemorySize, 0); + if (StrTotalMemory[0] == L',') { + StrTotalMemory++; + } + + TmpStr = GetStringById (STRING_TOKEN (STR_MEM_TEST_COMPLETED)); + if (TmpStr != NULL) { + StrCat (StrTotalMemory, TmpStr); + gBS->FreePool (TmpStr); + } + + gST->ConOut->ClearScreen (gST->ConOut); + gST->ConOut->SetAttribute (gST->ConOut, EFI_YELLOW | EFI_BRIGHT); + gST->ConOut->EnableCursor (gST->ConOut, FALSE); + gST->ConOut->OutputString (gST->ConOut, StrTotalMemory); + PlatformBdsShowProgress ( + Foreground, + Background, + StrTotalMemory, + Color, + 100, + (UINTN) PreviousValue + ); + + gBS->FreePool (Pos); + + DataSize = sizeof (Value); + Status = gRT->GetVariable ( + L"BootState", + &gEfiBootStateGuid, + &Attributes, + &DataSize, + &Value + ); + + if (EFI_ERROR (Status)) { + Value = 1; + gRT->SetVariable ( + L"BootState", + &gEfiBootStateGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (Value), + &Value + ); + } + + return ReturnStatus; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/String.c b/EdkNt32Pkg/Dxe/PlatformBds/Generic/String.c new file mode 100644 index 0000000000..412b7f8f17 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/String.c @@ -0,0 +1,133 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + string.c + +Abstract: + + String support + +Revision History + +--*/ + +#include "Bds.h" +#include "String.h" +#include "Language.h" + +extern UINT8 BdsStrings[]; + +EFI_GUID gBdsStringPackGuid = { 0x7bac95d3, 0xddf, 0x42f3, 0x9e, 0x24, 0x7c, 0x64, 0x49, 0x40, 0x37, 0x9a }; + +EFI_STATUS +InitializeStringSupport ( + VOID + ) +/*++ + +Routine Description: + + Initialize HII global accessor for string support + +Arguments: + None + +Returns: + String from ID. + +--*/ +{ + EFI_STATUS Status; + EFI_HII_PACKAGES *PackageList; + // + // There should only ever be one HII protocol + // + Status = gBS->LocateProtocol ( + &gEfiHiiProtocolGuid, + NULL, + &Hii + ); + if (!EFI_ERROR (Status)) { + PackageList = PreparePackages (1, &gBdsStringPackGuid, BdsStrings); + Status = Hii->NewPack (Hii, PackageList, &gStringPackHandle); + gBS->FreePool (PackageList); + } + + return Status; +} + +CHAR16 * +GetStringById ( + IN STRING_REF Id + ) +/*++ + +Routine Description: + + Get string by string id from HII Interface + +Arguments: + + Id - String ID. + +Returns: + + CHAR16 * - String from ID. + NULL - If error occurs. + +--*/ +{ + CHAR16 *String; + UINTN StringLength; + EFI_STATUS Status; + + // + // Set default string size assumption at no more than 256 bytes + // + StringLength = 0x100; + + String = AllocateZeroPool (StringLength); + if (String == NULL) { + // + // If this happens, we are oh-so-dead, but return a NULL in any case. + // + return NULL; + } + // + // Get the current string for the current Language + // + Status = Hii->GetString (Hii, gStringPackHandle, Id, FALSE, NULL, &StringLength, String); + if (EFI_ERROR (Status)) { + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Free the old pool + // + gBS->FreePool (String); + + // + // Allocate new pool with correct value + // + String = AllocatePool (StringLength); + ASSERT (String != NULL); + + Status = Hii->GetString (Hii, gStringPackHandle, Id, FALSE, NULL, &StringLength, String); + if (!EFI_ERROR (Status)) { + return String; + } + } + + return NULL; + } + + return String; +} diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/String.h b/EdkNt32Pkg/Dxe/PlatformBds/Generic/String.h new file mode 100644 index 0000000000..0800febc5e --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/Generic/String.h @@ -0,0 +1,59 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + string.h + +Abstract: + + String support + +Revision History + +--*/ + +#ifndef _STRING_H_ +#define _STRING_H_ + +// +// This is the VFR compiler generated header file which defines the +// string identifiers. +// +#include "BdsStrDefs.h" + +// +// String Definition Guid for BDS Platform +// +#define EFI_BDS_PLATFORM_GUID \ + { \ + 0x7777E939, 0xD57E, 0x4DCB, {0xA0, 0x8E, 0x64, 0xD7, 0x98, 0x57, 0x1E, 0x0F } \ + } + +EFI_HII_HANDLE gStringPackHandle; +EFI_HII_PROTOCOL *Hii; + +CHAR16 * +GetStringById ( + IN STRING_REF Id + ); + +EFI_STATUS +InitializeStringSupport ( + VOID + ); + +EFI_STATUS +CallFrontPage ( + VOID + ); + +#endif // _STRING_H_ diff --git a/EdkNt32Pkg/Dxe/PlatformBds/Generic/Strings.uni b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Strings.uni new file mode 100644 index 0000000000..41a6b9acde Binary files /dev/null and b/EdkNt32Pkg/Dxe/PlatformBds/Generic/Strings.uni differ diff --git a/EdkNt32Pkg/Dxe/PlatformBds/PlatformBds.mbd b/EdkNt32Pkg/Dxe/PlatformBds/PlatformBds.mbd new file mode 100644 index 0000000000..cda7d5b774 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/PlatformBds.mbd @@ -0,0 +1,54 @@ + + + + + Bds + A6F691AC-31C8-4444-854C-E2C1A6950F92 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-13 17:04 + 2006-03-23 14:14 + + + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + BaseLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + DxeServicesTableLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + EdkGenericBdsLib + BasePrintLib + EdkGraphicsLib + EdkIfrSupportLib + HiiLib + DxeHobLib + DxeMemoryAllocationLib + UefiDevicePathLib + BasePerformanceLibNull + + + _ModuleEntryPoint + + + diff --git a/EdkNt32Pkg/Dxe/PlatformBds/PlatformBds.msa b/EdkNt32Pkg/Dxe/PlatformBds/PlatformBds.msa new file mode 100644 index 0000000000..c46396e95e --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/PlatformBds.msa @@ -0,0 +1,151 @@ + + + + + Bds + DXE_DRIVER + BS_DRIVER + A6F691AC-31C8-4444-854C-E2C1A6950F92 + 0 + Component description file for DxeIpl module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-13 17:04 + 2006-03-23 14:14 + + + DebugLib + UefiLib + UefiDriverEntryPoint + PcdLib + BaseLib + EdkGraphicsLib + DxeServicesTableLib + PerformanceLib + PrintLib + EdkIfrSupportLib + ReportStatusCodeLib + HobLib + EdkGenericBdsLib + MemoryAllocationLib + BaseMemoryLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DevicePathLib + HiiLib + + + PlatformData.c + BdsPlatform.c + Generic\BdsEntry.c + Generic\FrontPage.c + Generic\FrontPageStrings.uni + Generic\FrontPageVfr.vfr + Generic\Language.c + Generic\String.c + Generic\Strings.uni + Generic\Capsules.c + Generic\MemoryTest.c + Generic\BootMaint\BmString.uni + Generic\BootMaint\bm.vfr + Generic\BootMaint\BmLib.c + Generic\BootMaint\BootOption.c + Generic\BootMaint\ConsoleOption.c + Generic\BootMaint\Data.c + Generic\BootMaint\Variable.c + Generic\BootMaint\UpdatePage.c + Generic\BootMaint\BBSsupport.c + Generic\BootMaint\BootMaint.c + Generic\BootMaint\FileExplorer.c + Generic\BootMaint\FE.vfr + Generic\BootMngr\BootManager.c + Generic\BootMngr\BootManagerStrings.uni + Generic\BootMngr\BootManagerVfr.Vfr + Generic\DeviceMngr\DeviceManager.c + Generic\DeviceMngr\DeviceManagerStrings.uni + Generic\DeviceMngr\DeviceManagerVfr.Vfr + Generic\Bds.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + Bds + LegacyBios + UgaSplash + Hii + FormCallback + DataHub + FormBrowser + ConsoleControl + CpuIo + UgaDraw + LoadFile + SimpleFileSystem + DevicePath + BlockIo + SerialIo + GenericMemTest + Cpu + DriverBinding + + + + FlashMapEntryData + gEfiFlashMapHobGuid + 0xb091e7d2, 0x5a0, 0x4198, 0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 + + + + + BiosVendor + SystemManufacturer + ProcessorVersion + ProcessorFrequency + MemoryArray + SerialIoDevice + SerialIoPort + + + + BootState + + + GlobalVariable + + + FlashMapHob + + + FileSystemVolumeLabelInfoId + + + FileInfo + + + + + BdsInitialize + + + diff --git a/EdkNt32Pkg/Dxe/PlatformBds/PlatformData.c b/EdkNt32Pkg/Dxe/PlatformBds/PlatformData.c new file mode 100644 index 0000000000..e9885b7957 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/PlatformData.c @@ -0,0 +1,182 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PlatformData.c + +Abstract: + + Defined the platform specific device path which will be used by + platform Bbd to perform the platform policy connect. + +--*/ + +#include "Generic/Bds.h" +#include "BdsPlatform.h" + +// +// Predefined platform default time out value +// +UINT16 gPlatformBootTimeOutDefault = 10; + +// +// Platform specific keyboard device path +// +NT_PLATFORM_UGA_DEVICE_PATH gUgaDevicePath0 = { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), + EFI_WIN_NT_THUNK_PROTOCOL_GUID + }, + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8) (sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)), + (UINT8) ((sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)) >> 8), + EFI_WIN_NT_UGA_GUID, + 0 + }, + gEndEntire +}; + +NT_PLATFORM_UGA_DEVICE_PATH gUgaDevicePath1 = { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), + EFI_WIN_NT_THUNK_PROTOCOL_GUID + }, + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8) (sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)), + (UINT8) ((sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)) >> 8), + EFI_WIN_NT_UGA_GUID, + 1 + }, + gEndEntire +}; + +// +// Platform specific serial device path +// +NT_ISA_SERIAL_DEVICE_PATH gNtSerialDevicePath0 = { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), + EFI_WIN_NT_THUNK_PROTOCOL_GUID + }, + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8) (sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)), + (UINT8) ((sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)) >> 8), + EFI_WIN_NT_SERIAL_PORT_GUID + }, + { + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + (UINT8) (sizeof (UART_DEVICE_PATH)), + (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8), + 0, + 115200, + 8, + 1, + 1 + }, + { + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), + DEVICE_PATH_MESSAGING_PC_ANSI + }, + gEndEntire +}; + +NT_ISA_SERIAL_DEVICE_PATH gNtSerialDevicePath1 = { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), + EFI_WIN_NT_THUNK_PROTOCOL_GUID + }, + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8) (sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)), + (UINT8) ((sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)) >> 8), + EFI_WIN_NT_SERIAL_PORT_GUID, + 1 + }, + { + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + (UINT8) (sizeof (UART_DEVICE_PATH)), + (UINT8) ((sizeof (UART_DEVICE_PATH)) >> 8), + 0, + 115200, + 8, + 1, + 1 + }, + { + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), + DEVICE_PATH_MESSAGING_PC_ANSI + }, + gEndEntire +}; + +// +// Predefined platform default console device path +// +BDS_CONSOLE_CONNECT_ENTRY gPlatformConsole[] = { + { + (EFI_DEVICE_PATH_PROTOCOL *) &gNtSerialDevicePath0, + (CONSOLE_OUT | CONSOLE_IN) + }, + { + (EFI_DEVICE_PATH_PROTOCOL *) &gNtSerialDevicePath1, + (CONSOLE_OUT | CONSOLE_IN) + }, + { + (EFI_DEVICE_PATH_PROTOCOL *) &gUgaDevicePath0, + (CONSOLE_OUT | CONSOLE_IN) + }, + { + (EFI_DEVICE_PATH_PROTOCOL *) &gUgaDevicePath1, + (CONSOLE_OUT | CONSOLE_IN) + }, + { + NULL, + 0 + } +}; + +// +// Predefined platform specific driver option +// +EFI_DEVICE_PATH_PROTOCOL *gPlatformDriverOption[] = { NULL }; + +// +// Predefined platform connect sequence +// +EFI_DEVICE_PATH_PROTOCOL *gPlatformConnectSequence[] = { NULL }; diff --git a/EdkNt32Pkg/Dxe/PlatformBds/build.xml b/EdkNt32Pkg/Dxe/PlatformBds/build.xml new file mode 100644 index 0000000000..d30fd98a89 --- /dev/null +++ b/EdkNt32Pkg/Dxe/PlatformBds/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/ComponentName.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/ComponentName.c new file mode 100644 index 0000000000..a24f6da602 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/ComponentName.c @@ -0,0 +1,187 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "WinNtBlockIo.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +WinNtBlockIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +WinNtBlockIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gWinNtBlockIoComponentName = { + WinNtBlockIoComponentNameGetDriverName, + WinNtBlockIoComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mWinNtBlockIoDriverNameTable[] = { + { "eng", L"Windows Block I/O Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +WinNtBlockIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gWinNtBlockIoComponentName.SupportedLanguages, + mWinNtBlockIoDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +WinNtBlockIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + WIN_NT_BLOCK_IO_PRIVATE *Private; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiBlockIoProtocolGuid, + &BlockIo, + gWinNtBlockIoDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo); + + return LookupUnicodeString ( + Language, + gWinNtBlockIoComponentName.SupportedLanguages, + Private->ControllerNameTable, + ControllerName + ); +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/DriverConfiguration.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/DriverConfiguration.c new file mode 100644 index 0000000000..672ea5ffd0 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/DriverConfiguration.c @@ -0,0 +1,338 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DriverConfiguration.c + +Abstract: + +--*/ + +#include "WinNtBlockIo.h" + +// +// EFI Driver Configuration Functions +// +EFI_STATUS +EFIAPI +WinNtBlockIoDriverConfigurationSetOptions ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverConfigurationOptionsValid ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL + ); + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverConfigurationForceDefaults ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN UINT32 DefaultType, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + +// +// EFI Driver Configuration Protocol +// +EFI_DRIVER_CONFIGURATION_PROTOCOL gWinNtBlockIoDriverConfiguration = { + WinNtBlockIoDriverConfigurationSetOptions, + WinNtBlockIoDriverConfigurationOptionsValid, + WinNtBlockIoDriverConfigurationForceDefaults, + LANGUAGESUPPORTED +}; + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverConfigurationSetOptions ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ) +/*++ + + Routine Description: + Allows the user to set controller specific options for a controller that a + driver is currently managing. + + Arguments: + This - A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + ControllerHandle - The handle of the controller to set options on. + ChildHandle - The handle of the child controller to set options on. This + is an optional parameter that may be NULL. It will be NULL + for device drivers, and for a bus drivers that wish to set + options for the bus controller. It will not be NULL for a + bus driver that wishes to set options for one of its child + controllers. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the user interface that should be + presented to the user, and it must match one of the languages + specified in SupportedLanguages. The number of languages + supported by a driver is up to the driver writer. + ActionRequired - A pointer to the action that the calling agent is required + to perform when this function returns. See "Related + Definitions" for a list of the actions that the calling + agent is required to perform prior to accessing + ControllerHandle again. + + Returns: + EFI_SUCCESS - The driver specified by This successfully set the + configuration options for the controller specified + by ControllerHandle.. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ActionRequired is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support setting + configuration options for the controller specified by + ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + EFI_DEVICE_ERROR - A device error occurred while attempt to set the + configuration options for the controller specified + by ControllerHandle and ChildHandle. + EFI_OUT_RESOURCES - There are not enough resources available to set the + configuration options for the controller specified + by ControllerHandle and ChildHandle. + +--*/ +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + CHAR8 *SupportedLanguage; + + SupportedLanguage = This->SupportedLanguages; + + Status = EFI_UNSUPPORTED; + while (*SupportedLanguage != 0) { + if (AsciiStrnCmp (Language, SupportedLanguage, 3) == 0) { + Status = EFI_SUCCESS; + } + + SupportedLanguage += 3; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + if (ActionRequired == NULL || ControllerHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Validate controller handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + &BlockIo, + gWinNtBlockIoDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + gWinNtBlockIoDriverBinding.DriverBindingHandle, + ControllerHandle + ); + + return EFI_UNSUPPORTED; + } + + if (Status == EFI_UNSUPPORTED) { + return Status; + } else if (Status != EFI_ALREADY_STARTED) { + return EFI_INVALID_PARAMETER; + } + + *ActionRequired = EfiDriverConfigurationActionNone; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverConfigurationOptionsValid ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL + ) +/*++ + + Routine Description: + Tests to see if a controller's current configuration options are valid. + + Arguments: + This - A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. + ControllerHandle - The handle of the controller to test if it's current + configuration options are valid. + ChildHandle - The handle of the child controller to test if it's current + configuration options are valid. This is an optional + parameter that may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers that wish + to test the configuration options for the bus controller. + It will not be NULL for a bus driver that wishes to test + configuration options for one of its child controllers. + + Returns: + EFI_SUCCESS - The controller specified by ControllerHandle and + ChildHandle that is being managed by the driver + specified by This has a valid set of configuration + options. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_UNSUPPORTED - The driver specified by This is not currently + managing the controller specified by ControllerHandle + and ChildHandle. + EFI_DEVICE_ERROR - The controller specified by ControllerHandle and + ChildHandle that is being managed by the driver + specified by This has an invalid set of configuration + options. + +--*/ +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + if (ControllerHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Validate controller handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + &BlockIo, + gWinNtBlockIoDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + gWinNtBlockIoDriverBinding.DriverBindingHandle, + ControllerHandle + ); + + return EFI_UNSUPPORTED; + } + + if (Status == EFI_UNSUPPORTED) { + return Status; + } else if (Status != EFI_ALREADY_STARTED) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverConfigurationForceDefaults ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN UINT32 DefaultType, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ) +/*++ + + Routine Description: + Forces a driver to set the default configuration options for a controller. + + Arguments: + This - A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + ControllerHandle - The handle of the controller to force default configuration options on. + ChildHandle - The handle of the child controller to force default configuration options on This is an optional parameter that may be NULL. It will be NULL for device drivers. It will also be NULL for a bus drivers that wish to force default configuration options for the bus controller. It will not be NULL for a bus driver that wishes to force default configuration options for one of its child controllers. + DefaultType - The type of default configuration options to force on the controller specified by ControllerHandle and ChildHandle. See Table 9-1 for legal values. A DefaultType of 0x00000000 must be supported by this protocol. + ActionRequired - A pointer to the action that the calling agent is required to perform when this function returns. See "Related Definitions" in Section 9.1for a list of the actions that the calling agent is required to perform prior to accessing ControllerHandle again. + + Returns: + EFI_SUCCESS - The driver specified by This successfully forced the default configuration options on the controller specified by ControllerHandle and ChildHandle. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ActionRequired is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support forcing the default configuration options on the controller specified by ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the configuration type specified by DefaultType. + EFI_DEVICE_ERROR - A device error occurred while attempt to force the default configuration options on the controller specified by ControllerHandle and ChildHandle. + EFI_OUT_RESOURCES - There are not enough resources available to force the default configuration options on the controller specified by ControllerHandle and ChildHandle. + +--*/ +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + if (ActionRequired == NULL || ControllerHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Validate controller handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + &BlockIo, + gWinNtBlockIoDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + gWinNtBlockIoDriverBinding.DriverBindingHandle, + ControllerHandle + ); + + return EFI_UNSUPPORTED; + } + + if (Status == EFI_UNSUPPORTED) { + return Status; + } else if (Status != EFI_ALREADY_STARTED) { + return EFI_INVALID_PARAMETER; + } + + *ActionRequired = EfiDriverConfigurationActionNone; + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/DriverDiagnostics.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/DriverDiagnostics.c new file mode 100644 index 0000000000..dd815789c6 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/DriverDiagnostics.c @@ -0,0 +1,186 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DriverDiagnostics.c + +Abstract: + +--*/ + +#include "WinNtBlockIo.h" + +// +// EFI Driver Diagnostics Functions +// +EFI_STATUS +EFIAPI +WinNtBlockIoDriverDiagnosticsRunDiagnostics ( + IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, + IN CHAR8 *Language, + OUT EFI_GUID **ErrorType, + OUT UINTN *BufferSize, + OUT CHAR16 **Buffer + ); + +// +// EFI Driver Diagnostics Protocol +// +EFI_DRIVER_DIAGNOSTICS_PROTOCOL gWinNtBlockIoDriverDiagnostics = { + WinNtBlockIoDriverDiagnosticsRunDiagnostics, + LANGUAGESUPPORTED +}; + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverDiagnosticsRunDiagnostics ( + IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, + IN CHAR8 *Language, + OUT EFI_GUID **ErrorType, + OUT UINTN *BufferSize, + OUT CHAR16 **Buffer + ) +/*++ + + Routine Description: + Runs diagnostics on a controller. + + Arguments: + This - A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOL instance. + ControllerHandle - The handle of the controller to run diagnostics on. + ChildHandle - The handle of the child controller to run diagnostics on + This is an optional parameter that may be NULL. It will + be NULL for device drivers. It will also be NULL for a + bus drivers that wish to run diagnostics on the bus + controller. It will not be NULL for a bus driver that + wishes to run diagnostics on one of its child controllers. + DiagnosticType - Indicates type of diagnostics to perform on the controller + specified by ControllerHandle and ChildHandle. See + "Related Definitions" for the list of supported types. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language in which the optional + error message should be returned in Buffer, and it must + match one of the languages specified in SupportedLanguages. + The number of languages supported by a driver is up to + the driver writer. + ErrorType - A GUID that defines the format of the data returned in + Buffer. + BufferSize - The size, in bytes, of the data returned in Buffer. + Buffer - A buffer that contains a Null-terminated Unicode string + plus some additional data whose format is defined by + ErrorType. Buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility + to free it with a call to FreePool(). + + Returns: + EFI_SUCCESS - The controller specified by ControllerHandle and + ChildHandle passed the diagnostic. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid + EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ErrorType is NULL. + EFI_INVALID_PARAMETER - BufferType is NULL. + EFI_INVALID_PARAMETER - Buffer is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support + running diagnostics for the controller specified + by ControllerHandle and ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + type of diagnostic specified by DiagnosticType. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + EFI_OUT_OF_RESOURCES - There are not enough resources available to complete + the diagnostics. + EFI_OUT_OF_RESOURCES - There are not enough resources available to return + the status information in ErrorType, BufferSize, + and Buffer. + EFI_DEVICE_ERROR - The controller specified by ControllerHandle and + ChildHandle did not pass the diagnostic. + +--*/ +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + CHAR8 *SupportedLanguage; + + if (Language == NULL || + ErrorType == NULL || + Buffer == NULL || + ControllerHandle == NULL || + BufferSize == NULL) { + + return EFI_INVALID_PARAMETER; + } + + SupportedLanguage = This->SupportedLanguages; + + Status = EFI_UNSUPPORTED; + while (*SupportedLanguage != 0) { + if (AsciiStrnCmp (Language, SupportedLanguage, 3) == 0) { + Status = EFI_SUCCESS; + break; + } + + SupportedLanguage += 3; + } + + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + *ErrorType = NULL; + *BufferSize = 0; + if (DiagnosticType != EfiDriverDiagnosticTypeStandard) { + *ErrorType = &gEfiBlockIoProtocolGuid; + *BufferSize = 0x60; + gBS->AllocatePool (EfiBootServicesData, (UINTN) (*BufferSize), Buffer); + CopyMem (*Buffer, L"Windows Block I/O Driver Diagnostics Failed\n", *BufferSize); + return EFI_DEVICE_ERROR; + } + + // + // Validate controller handle + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + &BlockIo, + gWinNtBlockIoDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + + if (!EFI_ERROR (Status)) { + gBS->CloseProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + gWinNtBlockIoDriverBinding.DriverBindingHandle, + ControllerHandle + ); + + return EFI_UNSUPPORTED; + } + + if (Status == EFI_UNSUPPORTED) { + return Status; + } else if (Status != EFI_ALREADY_STARTED) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.c new file mode 100644 index 0000000000..2f65092747 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.c @@ -0,0 +1,1085 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtBlockIo.c + +Abstract: + + Produce block IO abstractions for real devices on your PC using Win32 APIs. + The configuration of what devices to mount or emulate comes from NT + environment variables. The variables must be visible to the Microsoft* + Developer Studio for them to work. + + ixed - Fixed disk like a hard drive. + emovable - Removable media like a floppy or CD-ROM. + Read nly - Write protected device. + Read rite - Read write device. + - Decimal number of blocks a device supports. + - Decimal number of bytes per block. + + NT envirnonment variable contents. '<' and '>' are not part of the variable, + they are just used to make this help more readable. There should be no + spaces between the ';'. Extra spaces will break the variable. A '!' is + used to seperate multiple devices in a variable. + + EFI_WIN_NT_VIRTUAL_DISKS = + ;;[!...] + + EFI_WIN_NT_PHYSICAL_DISKS = + :;;[!...] + + Virtual Disks: These devices use a file to emulate a hard disk or removable + media device. + + Thus a 20 MB emulated hard drive would look like: + EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512 + + A 1.44MB emulated floppy with a block size of 1024 would look like: + EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024 + + Physical Disks: These devices use NT to open a real device in your system + + Thus a 120 MB floppy would look like: + EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512 + + Thus a standard CD-ROM floppy would look like: + EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048 + + + * Other names and brands may be claimed as the property of others. + +--*/ + +#include "WinNtBlockIo.h" + +EFI_DRIVER_BINDING_PROTOCOL gWinNtBlockIoDriverBinding = { + WinNtBlockIoDriverBindingSupported, + WinNtBlockIoDriverBindingStart, + WinNtBlockIoDriverBindingStop, + 0x10, + NULL, + NULL +}; + + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure the WinNtThunkProtocol is valid + // + Status = EFI_UNSUPPORTED; + if (WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) { + + // + // Check the GUID to see if this is a handle type the driver supports + // + if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtVirtualDisksGuid) || + CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtPhysicalDisksGuid) ) { + Status = EFI_SUCCESS; + } + } + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + WIN_NT_RAW_DISK_DEVICE_TYPE DiskType; + UINT16 Buffer[FILENAME_BUFFER_SIZE]; + CHAR16 *Str; + BOOLEAN RemovableMedia; + BOOLEAN WriteProtected; + UINTN NumberOfBlocks; + UINTN BlockSize; + + // + // Grab the protocols we need + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Set DiskType + // + if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtVirtualDisksGuid)) { + DiskType = EfiWinNtVirtualDisks; + } else if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtPhysicalDisksGuid)) { + DiskType = EfiWinNtPhysicalDisks; + } else { + Status = EFI_UNSUPPORTED; + goto Done; + } + + Status = EFI_NOT_FOUND; + Str = WinNtIo->EnvString; + if (DiskType == EfiWinNtVirtualDisks) { + WinNtIo->WinNtThunk->SPrintf ( + Buffer, + L"Diskfile%d", + WinNtIo->InstanceNumber + ); + } else { + if (*Str >= 'A' && *Str <= 'Z' || *Str >= 'a' && *Str <= 'z') { + WinNtIo->WinNtThunk->SPrintf (Buffer, L"\\\\.\\%c:", *Str); + } else { + WinNtIo->WinNtThunk->SPrintf (Buffer, L"\\\\.\\PHYSICALDRIVE%c", *Str); + } + + Str++; + if (*Str != ':') { + Status = EFI_NOT_FOUND; + goto Done; + } + + Str++; + } + + if (*Str == 'R' || *Str == 'F') { + RemovableMedia = (BOOLEAN) (*Str == 'R'); + Str++; + if (*Str == 'O' || *Str == 'W') { + WriteProtected = (BOOLEAN) (*Str == 'O'); + Str = GetNextElementPastTerminator (Str, ';'); + + NumberOfBlocks = Atoi (Str); + if (NumberOfBlocks != 0) { + Str = GetNextElementPastTerminator (Str, ';'); + BlockSize = Atoi (Str); + if (BlockSize != 0) { + // + // If we get here the variable is valid so do the work. + // + Status = WinNtBlockIoCreateMapping ( + WinNtIo, + Handle, + Buffer, + WriteProtected, + RemovableMedia, + NumberOfBlocks, + BlockSize, + DiskType + ); + + } + } + } + } + +Done: + if (EFI_ERROR (Status)) { + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + EFI_UNSUPPORTED - TODO: Add description for return value + +--*/ +{ + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status; + WIN_NT_BLOCK_IO_PRIVATE *Private; + + // + // Get our context back + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiBlockIoProtocolGuid, + &BlockIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (BlockIo); + + // + // BugBug: If we need to kick people off, we need to make Uninstall Close the handles. + // We could pass in our image handle or FLAG our open to be closed via + // Unistall (== to saying any CloseProtocol will close our open) + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->EfiHandle, + &gEfiBlockIoProtocolGuid, + &Private->BlockIo, + NULL + ); + if (!EFI_ERROR (Status)) { + + Status = gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + // + // Shut down our device + // + Private->WinNtThunk->CloseHandle (Private->NtHandle); + + // + // Free our instance data + // + FreeUnicodeStringTable (Private->ControllerNameTable); + + gBS->FreePool (Private); + } + + return Status; +} + +STATIC +CHAR16 * +GetNextElementPastTerminator ( + IN CHAR16 *EnvironmentVariable, + IN CHAR16 Terminator + ) +/*++ + +Routine Description: + + Worker function to parse environment variables. + +Arguments: + EnvironmentVariable - Envirnment variable to parse. + + Terminator - Terminator to parse for. + +Returns: + + Pointer to next eliment past the first occurence of Terminator or the '\0' + at the end of the string. + +--*/ +{ + CHAR16 *Ptr; + + for (Ptr = EnvironmentVariable; *Ptr != '\0'; Ptr++) { + if (*Ptr == Terminator) { + Ptr++; + break; + } + } + + return Ptr; +} + +STATIC +EFI_STATUS +WinNtBlockIoCreateMapping ( + IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo, + IN EFI_HANDLE EfiDeviceHandle, + IN CHAR16 *Filename, + IN BOOLEAN ReadOnly, + IN BOOLEAN RemovableMedia, + IN UINTN NumberOfBlocks, + IN UINTN BlockSize, + IN WIN_NT_RAW_DISK_DEVICE_TYPE DeviceType + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + WinNtIo - TODO: add argument description + EfiDeviceHandle - TODO: add argument description + Filename - TODO: add argument description + ReadOnly - TODO: add argument description + RemovableMedia - TODO: add argument description + NumberOfBlocks - TODO: add argument description + BlockSize - TODO: add argument description + DeviceType - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_STATUS Status; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + WIN_NT_BLOCK_IO_PRIVATE *Private; + UINTN Index; + + WinNtIo->WinNtThunk->SetErrorMode (SEM_FAILCRITICALERRORS); + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (WIN_NT_BLOCK_IO_PRIVATE), + &Private + ); + ASSERT_EFI_ERROR (Status); + + EfiInitializeLock (&Private->Lock, EFI_TPL_NOTIFY); + + Private->WinNtThunk = WinNtIo->WinNtThunk; + + Private->Signature = WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE; + Private->LastBlock = NumberOfBlocks - 1; + Private->BlockSize = BlockSize; + + for (Index = 0; Filename[Index] != 0; Index++) { + Private->Filename[Index] = Filename[Index]; + } + + Private->Filename[Index] = 0; + + Private->ReadMode = GENERIC_READ | (ReadOnly ? 0 : GENERIC_WRITE); + Private->ShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + + Private->NumberOfBlocks = NumberOfBlocks; + Private->DeviceType = DeviceType; + Private->NtHandle = INVALID_HANDLE_VALUE; + + Private->ControllerNameTable = NULL; + + AddUnicodeString ( + "eng", + gWinNtBlockIoComponentName.SupportedLanguages, + &Private->ControllerNameTable, + Private->Filename + ); + + BlockIo = &Private->BlockIo; + BlockIo->Revision = EFI_BLOCK_IO_PROTOCOL_REVISION; + BlockIo->Media = &Private->Media; + BlockIo->Media->BlockSize = Private->BlockSize; + BlockIo->Media->LastBlock = Private->NumberOfBlocks - 1; + BlockIo->Media->MediaId = 0;; + + BlockIo->Reset = WinNtBlockIoResetBlock; + BlockIo->ReadBlocks = WinNtBlockIoReadBlocks; + BlockIo->WriteBlocks = WinNtBlockIoWriteBlocks; + BlockIo->FlushBlocks = WinNtBlockIoFlushBlocks; + + BlockIo->Media->ReadOnly = ReadOnly; + BlockIo->Media->RemovableMedia = RemovableMedia; + BlockIo->Media->LogicalPartition = FALSE; + BlockIo->Media->MediaPresent = TRUE; + BlockIo->Media->WriteCaching = FALSE; + + if (DeviceType == EfiWinNtVirtualDisks) { + BlockIo->Media->IoAlign = 1; + + // + // Create a file to use for a virtual disk even if it does not exist. + // + Private->OpenMode = OPEN_ALWAYS; + } else if (DeviceType == EfiWinNtPhysicalDisks) { + // + // Physical disk and floppy devices require 4 byte alignment. + // + BlockIo->Media->IoAlign = 4; + + // + // You can only open a physical device if it exists. + // + Private->OpenMode = OPEN_EXISTING; + } else { + ASSERT (FALSE); + } + + Private->EfiHandle = EfiDeviceHandle; + Status = WinNtBlockIoOpenDevice (Private); + if (!EFI_ERROR (Status)) { + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->EfiHandle, + &gEfiBlockIoProtocolGuid, + &Private->BlockIo, + NULL + ); + if (EFI_ERROR (Status)) { + FreeUnicodeStringTable (Private->ControllerNameTable); + gBS->FreePool (Private); + } + + DEBUG ((EFI_D_INIT, "BlockDevice added: %s\n", Filename)); + } + + return Status; +} + +STATIC +EFI_STATUS +WinNtBlockIoOpenDevice ( + WIN_NT_BLOCK_IO_PRIVATE *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_STATUS Status; + UINT64 FileSize; + UINT64 EndOfFile; + EFI_BLOCK_IO_PROTOCOL *BlockIo; + + BlockIo = &Private->BlockIo; + EfiAcquireLock (&Private->Lock); + + // + // If the device is already opened, close it + // + if (Private->NtHandle != INVALID_HANDLE_VALUE) { + BlockIo->Reset (BlockIo, FALSE); + } + + // + // Open the device + // + Private->NtHandle = Private->WinNtThunk->CreateFile ( + Private->Filename, + Private->ReadMode, + Private->ShareMode, + NULL, + Private->OpenMode, + 0, + NULL + ); + + Status = Private->WinNtThunk->GetLastError (); + + if (Private->NtHandle == INVALID_HANDLE_VALUE) { + DEBUG ((EFI_D_INFO, "PlOpenBlock: Could not open %s, %x\n", Private->Filename, Private->WinNtThunk->GetLastError ())); + BlockIo->Media->MediaPresent = FALSE; + Status = EFI_NO_MEDIA; + goto Done; + } + + if (!BlockIo->Media->MediaPresent) { + // + // BugBug: try to emulate if a CD appears - notify drivers to check it out + // + BlockIo->Media->MediaPresent = TRUE; + EfiReleaseLock (&Private->Lock); + EfiAcquireLock (&Private->Lock); + } + + // + // get the size of the file + // + Status = SetFilePointer64 (Private, 0, &FileSize, FILE_END); + + if (EFI_ERROR (Status)) { + FileSize = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize); + if (Private->DeviceType == EfiWinNtVirtualDisks) { + DEBUG ((EFI_D_ERROR, "PlOpenBlock: Could not get filesize of %s\n", Private->Filename)); + Status = EFI_UNSUPPORTED; + goto Done; + } + } + + if (Private->NumberOfBlocks == 0) { + Private->NumberOfBlocks = DivU64x32 (FileSize, Private->BlockSize); + } + + EndOfFile = MultU64x32 (Private->NumberOfBlocks, Private->BlockSize); + + if (FileSize != EndOfFile) { + // + // file is not the proper size, change it + // + DEBUG ((EFI_D_INIT, "PlOpenBlock: Initializing block device: %hs\n", Private->Filename)); + + // + // first set it to 0 + // + SetFilePointer64 (Private, 0, NULL, FILE_BEGIN); + Private->WinNtThunk->SetEndOfFile (Private->NtHandle); + + // + // then set it to the needed file size (OS will zero fill it) + // + SetFilePointer64 (Private, EndOfFile, NULL, FILE_BEGIN); + Private->WinNtThunk->SetEndOfFile (Private->NtHandle); + } + + DEBUG ((EFI_D_INIT, "%HPlOpenBlock: opened %s%N\n", Private->Filename)); + Status = EFI_SUCCESS; + +Done: + if (EFI_ERROR (Status)) { + if (Private->NtHandle != INVALID_HANDLE_VALUE) { + BlockIo->Reset (BlockIo, FALSE); + } + } + + EfiReleaseLock (&Private->Lock); + return Status; +} + +STATIC +EFI_STATUS +WinNtBlockIoError ( + IN WIN_NT_BLOCK_IO_PRIVATE *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_BLOCK_IO_PROTOCOL *BlockIo; + EFI_STATUS Status; + BOOLEAN ReinstallBlockIoFlag; + + BlockIo = &Private->BlockIo; + + switch (Private->WinNtThunk->GetLastError ()) { + + case ERROR_NOT_READY: + Status = EFI_NO_MEDIA; + BlockIo->Media->ReadOnly = FALSE; + BlockIo->Media->MediaPresent = FALSE; + ReinstallBlockIoFlag = FALSE; + break; + + case ERROR_WRONG_DISK: + BlockIo->Media->ReadOnly = FALSE; + BlockIo->Media->MediaPresent = TRUE; + BlockIo->Media->MediaId += 1; + ReinstallBlockIoFlag = TRUE; + Status = EFI_MEDIA_CHANGED; + break; + + case ERROR_WRITE_PROTECT: + BlockIo->Media->ReadOnly = TRUE; + ReinstallBlockIoFlag = FALSE; + Status = EFI_WRITE_PROTECTED; + break; + + default: + ReinstallBlockIoFlag = FALSE; + Status = EFI_DEVICE_ERROR; + break; + } + + if (ReinstallBlockIoFlag) { + BlockIo->Reset (BlockIo, FALSE); + + gBS->ReinstallProtocolInterface ( + Private->EfiHandle, + &gEfiBlockIoProtocolGuid, + BlockIo, + BlockIo + ); + } + + return Status; +} + +STATIC +EFI_STATUS +WinNtBlockIoReadWriteCommon ( + IN WIN_NT_BLOCK_IO_PRIVATE *Private, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer, + IN CHAR8 *CallerName + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + MediaId - TODO: add argument description + Lba - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + CallerName - TODO: add argument description + +Returns: + + EFI_NO_MEDIA - TODO: Add description for return value + EFI_MEDIA_CHANGED - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + EFI_BAD_BUFFER_SIZE - TODO: Add description for return value + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + UINTN BlockSize; + UINT64 LastBlock; + INT64 DistanceToMove; + UINT64 DistanceMoved; + + if (Private->NtHandle == INVALID_HANDLE_VALUE) { + Status = WinNtBlockIoOpenDevice (Private); + if (EFI_ERROR (Status)) { + return Status; + } + } + + if (!Private->Media.MediaPresent) { + DEBUG ((EFI_D_INIT, "%s: No Media\n", CallerName)); + return EFI_NO_MEDIA; + } + + if (Private->Media.MediaId != MediaId) { + return EFI_MEDIA_CHANGED; + } + + if ((UINT32) Buffer % Private->Media.IoAlign != 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Verify buffer size + // + BlockSize = Private->BlockSize; + if (BufferSize == 0) { + DEBUG ((EFI_D_INIT, "%s: Zero length read\n", CallerName)); + return EFI_SUCCESS; + } + + if ((BufferSize % BlockSize) != 0) { + DEBUG ((EFI_D_INIT, "%s: Invalid read size\n", CallerName)); + return EFI_BAD_BUFFER_SIZE; + } + + LastBlock = Lba + (BufferSize / BlockSize) - 1; + if (LastBlock > Private->LastBlock) { + DEBUG ((EFI_D_INIT, "ReadBlocks: Attempted to read off end of device\n")); + return EFI_INVALID_PARAMETER; + } + // + // Seek to End of File + // + DistanceToMove = MultU64x32 (Lba, BlockSize); + Status = SetFilePointer64 (Private, DistanceToMove, &DistanceMoved, FILE_BEGIN); + + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INIT, "WriteBlocks: SetFilePointer failed\n")); + return WinNtBlockIoError (Private); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + + Routine Description: + Read BufferSize bytes from Lba into Buffer. + + Arguments: + This - Protocol instance pointer. + MediaId - Id of the media, changes every time the media is replaced. + Lba - The starting Logical Block Address to read from + BufferSize - Size of Buffer, must be a multiple of device block size. + Buffer - Buffer containing read data + + Returns: + EFI_SUCCESS - The data was read correctly from the device. + EFI_DEVICE_ERROR - The device reported an error while performing the read. + EFI_NO_MEDIA - There is no media in the device. + EFI_MEDIA_CHANGED - The MediaId does not matched the current device. + EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the + device. + EFI_INVALID_PARAMETER - The read request contains device addresses that are not + valid for the device. + +--*/ +{ + WIN_NT_BLOCK_IO_PRIVATE *Private; + BOOL Flag; + EFI_STATUS Status; + DWORD BytesRead; + + Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "WinNtReadBlocks"); + if (EFI_ERROR (Status)) { + return Status; + } + + Flag = Private->WinNtThunk->ReadFile (Private->NtHandle, Buffer, (DWORD) BufferSize, (LPDWORD) &BytesRead, NULL); + if (!Flag || (BytesRead != BufferSize)) { + DEBUG ((EFI_D_INIT, "ReadBlocks: ReadFile failed. (%d)\n", Private->WinNtThunk->GetLastError ())); + return WinNtBlockIoError (Private); + } + + // + // If we wrote then media is present. + // + This->Media->MediaPresent = TRUE; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + + Routine Description: + Write BufferSize bytes from Lba into Buffer. + + Arguments: + This - Protocol instance pointer. + MediaId - Id of the media, changes every time the media is replaced. + Lba - The starting Logical Block Address to read from + BufferSize - Size of Buffer, must be a multiple of device block size. + Buffer - Buffer containing read data + + Returns: + EFI_SUCCESS - The data was written correctly to the device. + EFI_WRITE_PROTECTED - The device can not be written to. + EFI_DEVICE_ERROR - The device reported an error while performing the write. + EFI_NO_MEDIA - There is no media in the device. + EFI_MEDIA_CHNAGED - The MediaId does not matched the current device. + EFI_BAD_BUFFER_SIZE - The Buffer was not a multiple of the block size of the + device. + EFI_INVALID_PARAMETER - The write request contains a LBA that is not + valid for the device. + +--*/ +{ + WIN_NT_BLOCK_IO_PRIVATE *Private; + UINTN BytesWritten; + BOOL Flag; + EFI_STATUS Status; + + Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + Status = WinNtBlockIoReadWriteCommon (Private, MediaId, Lba, BufferSize, Buffer, "WinNtWriteBlocks"); + if (EFI_ERROR (Status)) { + return Status; + } + + Flag = Private->WinNtThunk->WriteFile (Private->NtHandle, Buffer, (DWORD) BufferSize, (LPDWORD) &BytesWritten, NULL); + if (!Flag || (BytesWritten != BufferSize)) { + DEBUG ((EFI_D_INIT, "ReadBlocks: WriteFile failed. (%d)\n", Private->WinNtThunk->GetLastError ())); + return WinNtBlockIoError (Private); + } + + // + // If the write succeeded, we are not write protected and media is present. + // + This->Media->MediaPresent = TRUE; + This->Media->ReadOnly = FALSE; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + + Routine Description: + Flush the Block Device. + + Arguments: + This - Protocol instance pointer. + + Returns: + EFI_SUCCESS - All outstanding data was written to the device + EFI_DEVICE_ERROR - The device reported an error while writting back the data + EFI_NO_MEDIA - There is no media in the device. + +--*/ +{ + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtBlockIoResetBlock ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + + Routine Description: + Reset the Block Device. + + Arguments: + This - Protocol instance pointer. + ExtendedVerification - Driver may perform diagnostics on reset. + + Returns: + EFI_SUCCESS - The device was reset. + EFI_DEVICE_ERROR - The device is not functioning properly and could + not be reset. + +--*/ +{ + WIN_NT_BLOCK_IO_PRIVATE *Private; + + Private = WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS (This); + + if (Private->NtHandle != INVALID_HANDLE_VALUE) { + Private->WinNtThunk->CloseHandle (Private->NtHandle); + Private->NtHandle = INVALID_HANDLE_VALUE; + } + + return EFI_SUCCESS; +} + +UINTN +Atoi ( + CHAR16 *String + ) +/*++ + +Routine Description: + + Convert a unicode string to a UINTN + +Arguments: + + String - Unicode string. + +Returns: + + UINTN of the number represented by String. + +--*/ +{ + UINTN Number; + CHAR16 *Str; + + // + // skip preceeding white space + // + Str = String; + while ((*Str) && (*Str == ' ')) { + Str++; + } + // + // Convert ot a Number + // + Number = 0; + while (*Str != '\0') { + if ((*Str >= '0') && (*Str <= '9')) { + Number = (Number * 10) +*Str - '0'; + } else { + break; + } + + Str++; + } + + return Number; +} + +EFI_STATUS +SetFilePointer64 ( + IN WIN_NT_BLOCK_IO_PRIVATE *Private, + IN INT64 DistanceToMove, + OUT UINT64 *NewFilePointer, + IN DWORD MoveMethod + ) +/*++ + +This function extends the capability of SetFilePointer to accept 64 bit parameters + +--*/ +// TODO: function comment is missing 'Routine Description:' +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: Private - add argument and description to function comment +// TODO: DistanceToMove - add argument and description to function comment +// TODO: NewFilePointer - add argument and description to function comment +// TODO: MoveMethod - add argument and description to function comment +{ + EFI_STATUS Status; + LARGE_INTEGER LargeInt; + UINT32 ErrorCode; + + LargeInt.QuadPart = DistanceToMove; + Status = EFI_SUCCESS; + + LargeInt.LowPart = Private->WinNtThunk->SetFilePointer ( + Private->NtHandle, + LargeInt.LowPart, + &LargeInt.HighPart, + MoveMethod + ); + + if (LargeInt.LowPart == -1 && + (ErrorCode = Private->WinNtThunk->GetLastError ()) != NO_ERROR) { + Status = EFI_INVALID_PARAMETER; + } + + if (NewFilePointer != NULL) { + *NewFilePointer = LargeInt.QuadPart; + } + + return Status; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.h b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.h new file mode 100644 index 0000000000..59d4b54f64 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.h @@ -0,0 +1,471 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtBlockIo.h + +Abstract: + + Produce block IO abstractions for real devices on your PC using Win32 APIs. + The configuration of what devices to mount or emulate comes from NT + environment variables. The variables must be visible to the Microsoft* + Developer Studio for them to work. + + * Other names and brands may be claimed as the property of others. + +--*/ + +#ifndef _WIN_NT_BLOCK_IO_H_ +#define _WIN_NT_BLOCK_IO_H_ + + + +#define FILENAME_BUFFER_SIZE 80 + +// +// Language supported for driverconfiguration protocol +// +#define LANGUAGESUPPORTED "eng" + +typedef enum { + EfiWinNtVirtualDisks, + EfiWinNtPhysicalDisks, + EifWinNtMaxTypeDisks +} WIN_NT_RAW_DISK_DEVICE_TYPE; + +#define WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE EFI_SIGNATURE_32 ('N', 'T', 'b', 'k') +typedef struct { + UINTN Signature; + + EFI_LOCK Lock; + + CHAR16 Filename[FILENAME_BUFFER_SIZE]; + UINTN ReadMode; + UINTN ShareMode; + UINTN OpenMode; + + HANDLE NtHandle; + WIN_NT_RAW_DISK_DEVICE_TYPE DeviceType; + + UINT64 LastBlock; + UINTN BlockSize; + UINT64 NumberOfBlocks; + + EFI_HANDLE EfiHandle; + EFI_BLOCK_IO_PROTOCOL BlockIo; + EFI_BLOCK_IO_MEDIA Media; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + +} WIN_NT_BLOCK_IO_PRIVATE; + +#define WIN_NT_BLOCK_IO_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, WIN_NT_BLOCK_IO_PRIVATE, BlockIo, WIN_NT_BLOCK_IO_PRIVATE_SIGNATURE) + +#define LIST_BUFFER_SIZE 512 + +// +// Block I/O Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gWinNtBlockIoDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gWinNtBlockIoComponentName; +extern EFI_DRIVER_CONFIGURATION_PROTOCOL gWinNtBlockIoDriverConfiguration; +extern EFI_DRIVER_DIAGNOSTICS_PROTOCOL gWinNtBlockIoDriverDiagnostics; + +// +// EFI Driver Binding Functions +// +EFI_STATUS +EFIAPI +WinNtBlockIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtBlockIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// Block IO protocol member functions +// +STATIC +EFI_STATUS +EFIAPI +WinNtBlockIoReadBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + Lba - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtBlockIoWriteBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + MediaId - TODO: add argument description + Lba - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtBlockIoFlushBlocks ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtBlockIoResetBlock ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// Private Worker functions +// +STATIC +EFI_STATUS +WinNtBlockIoCreateMapping ( + IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo, + IN EFI_HANDLE EfiDeviceHandle, + IN CHAR16 *Filename, + IN BOOLEAN ReadOnly, + IN BOOLEAN RemovableMedia, + IN UINTN NumberOfBlocks, + IN UINTN BlockSize, + IN WIN_NT_RAW_DISK_DEVICE_TYPE DeviceType + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + WinNtIo - TODO: add argument description + EfiDeviceHandle - TODO: add argument description + Filename - TODO: add argument description + ReadOnly - TODO: add argument description + RemovableMedia - TODO: add argument description + NumberOfBlocks - TODO: add argument description + BlockSize - TODO: add argument description + DeviceType - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +WinNtBlockIoReadWriteCommon ( + IN WIN_NT_BLOCK_IO_PRIVATE *Private, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer, + IN CHAR8 *CallerName + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + MediaId - TODO: add argument description + Lba - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + CallerName - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +WinNtBlockIoError ( + IN WIN_NT_BLOCK_IO_PRIVATE *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +WinNtBlockIoOpenDevice ( + WIN_NT_BLOCK_IO_PRIVATE *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +CHAR16 * +GetNextElementPastTerminator ( + IN CHAR16 *EnvironmentVariable, + IN CHAR16 Terminator + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + EnvironmentVariable - TODO: add argument description + Terminator - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + + + +EFI_STATUS +SetFilePointer64 ( + IN WIN_NT_BLOCK_IO_PRIVATE *Private, + IN INT64 DistanceToMove, + OUT UINT64 *NewFilePointer, + IN DWORD MoveMethod + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + DistanceToMove - TODO: add argument description + NewFilePointer - TODO: add argument description + MoveMethod - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +UINTN +Atoi ( + CHAR16 *String + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + String - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.mbd new file mode 100644 index 0000000000..078350addc --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.mbd @@ -0,0 +1,41 @@ + + + + + WinNtBlockIo + F479E147-A125-11d4-BCFC-0080C73C8881 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + BaseLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + UefiDriverModelLib + UefiDebugLibStdErr + BasePrintLib + DxeMemoryAllocationLib + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.msa new file mode 100644 index 0000000000..c261d234cd --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.msa @@ -0,0 +1,78 @@ + + + + + WinNtBlockIo + UEFI_DRIVER + BS_DRIVER + F479E147-A125-11d4-BCFC-0080C73C8881 + 0 + Component description file for WinNtBlockIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + DebugLib + BaseLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + WinNtBlockIo.h + WinNtBlockIo.c + ComponentName.c + DriverConfiguration.c + DriverDiagnostics.c + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + WinNtIo + BlockIo + + + + WinNtVirtualDisks + + + WinNtPhysicalDisks + + + + + + + + gWinNtBlockIoDriverBinding + gWinNtBlockIoComponentName + gWinNtBlockIoDriverDiagnostics + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/build.xml new file mode 100644 index 0000000000..b03cad7e05 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/BlockIo/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/ComponentName.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/ComponentName.c new file mode 100644 index 0000000000..d10f9ab68e --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/ComponentName.c @@ -0,0 +1,187 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "Console.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +WinNtConsoleComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +WinNtConsoleComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gWinNtConsoleComponentName = { + WinNtConsoleComponentNameGetDriverName, + WinNtConsoleComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mWinNtConsoleDriverNameTable[] = { + { "eng", L"Windows Text Console Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +WinNtConsoleComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gWinNtConsoleComponentName.SupportedLanguages, + mWinNtConsoleDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +WinNtConsoleComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *SimpleTextOut; + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get out context back + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleTextOutProtocolGuid, + &SimpleTextOut, + gWinNtConsoleDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (SimpleTextOut); + + return LookupUnicodeString ( + Language, + gWinNtConsoleComponentName.SupportedLanguages, + Private->ControllerNameTable, + ControllerName + ); +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/Console.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/Console.c new file mode 100644 index 0000000000..0bc344c1ec --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/Console.c @@ -0,0 +1,307 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Console.c + +Abstract: + + Console based on Win32 APIs. + +--*/ + +#include "Console.h" + +EFI_STATUS +EFIAPI +WinNtConsoleDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +WinNtConsoleDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ); + +EFI_STATUS +EFIAPI +WinNtConsoleDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ); + +EFI_DRIVER_BINDING_PROTOCOL gWinNtConsoleDriverBinding = { + WinNtConsoleDriverBindingSupported, + WinNtConsoleDriverBindingStart, + WinNtConsoleDriverBindingStop, + 0x10, + NULL, + NULL +}; + + +EFI_STATUS +EFIAPI +WinNtConsoleDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure that the WinNt Thunk Protocol is valid + // + Status = EFI_UNSUPPORTED; + if (WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) { + + // + // Check the GUID to see if this is a handle type the driver supports + // + if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtConsoleGuid)) { + Status = EFI_SUCCESS; + } + } + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtConsoleDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + + // + // Grab the IO abstraction we need to get any work done + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (WIN_NT_SIMPLE_TEXT_PRIVATE_DATA), + &Private + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + ZeroMem (Private, sizeof (WIN_NT_SIMPLE_TEXT_PRIVATE_DATA)); + + Private->Signature = WIN_NT_SIMPLE_TEXT_PRIVATE_DATA_SIGNATURE; + Private->Handle = Handle; + Private->WinNtIo = WinNtIo; + Private->WinNtThunk = WinNtIo->WinNtThunk; + + WinNtSimpleTextOutOpenWindow (Private); + WinNtSimpleTextInAttachToWindow (Private); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiSimpleTextOutProtocolGuid, + &Private->SimpleTextOut, + &gEfiSimpleTextInProtocolGuid, + &Private->SimpleTextIn, + NULL + ); + if (!EFI_ERROR (Status)) { + return Status; + } + +Done: + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + if (Private != NULL) { + + FreeUnicodeStringTable (Private->ControllerNameTable); + + if (Private->NtOutHandle != NULL) { + Private->WinNtThunk->CloseHandle (Private->NtOutHandle); + } + + if (Private->SimpleTextIn.WaitForKey != NULL) { + gBS->CloseEvent (Private->SimpleTextIn.WaitForKey); + } + + gBS->FreePool (Private); + } + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtConsoleDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + EFI_UNSUPPORTED - TODO: Add description for return value + +--*/ +{ + EFI_SIMPLE_TEXT_OUT_PROTOCOL *SimpleTextOut; + EFI_STATUS Status; + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + + // + // Kick people off our interface??? + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiSimpleTextOutProtocolGuid, + &SimpleTextOut, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (SimpleTextOut); + + ASSERT (Private->Handle == Handle); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + Handle, + &gEfiSimpleTextOutProtocolGuid, + &Private->SimpleTextOut, + &gEfiSimpleTextInProtocolGuid, + &Private->SimpleTextIn, + NULL + ); + if (!EFI_ERROR (Status)) { + + // + // Shut down our device + // + Status = gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + Status = gBS->CloseEvent (Private->SimpleTextIn.WaitForKey); + ASSERT_EFI_ERROR (Status); + + Private->WinNtThunk->CloseHandle (Private->NtOutHandle); + // + // DO NOT close Private->NtInHandle. It points to StdIn and not + // the Private->NtOutHandle is StdIn and should not be closed! + // + FreeUnicodeStringTable (Private->ControllerNameTable); + + gBS->FreePool (Private); + } + + return Status; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/Console.h b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/Console.h new file mode 100644 index 0000000000..1c8a26bddc --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/Console.h @@ -0,0 +1,512 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Console.h + +Abstract: + + Console based on Win32 APIs. + + This file attaches a SimpleTextIn protocol to a previously open window. + + The constructor for this protocol depends on an open window. Currently + the SimpleTextOut protocol creates a window when it's constructor is called. + Thus this code must run after the constructor for the SimpleTextOut + protocol + +--*/ + +#ifndef _CONSOLE_H_ +#define _CONSOLE_H_ + + + +#define WIN_NT_SIMPLE_TEXT_PRIVATE_DATA_SIGNATURE \ + EFI_SIGNATURE_32('N','T','s','c') + +typedef struct { + UINT64 Signature; + + EFI_HANDLE Handle; + + EFI_SIMPLE_TEXT_OUT_PROTOCOL SimpleTextOut; + EFI_SIMPLE_TEXT_OUTPUT_MODE SimpleTextOutMode; + + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + + // + // SimpleTextOut Private Data including Win32 types. + // + HANDLE NtOutHandle; + HANDLE NtInHandle; + + COORD MaxScreenSize; + COORD Possition; + WORD Attribute; + BOOLEAN CursorEnable; + + EFI_SIMPLE_TEXT_IN_PROTOCOL SimpleTextIn; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + +} WIN_NT_SIMPLE_TEXT_PRIVATE_DATA; + +#define WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, WIN_NT_SIMPLE_TEXT_PRIVATE_DATA, SimpleTextOut, WIN_NT_SIMPLE_TEXT_PRIVATE_DATA_SIGNATURE) + +#define WIN_NT_SIMPLE_TEXT_IN_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, WIN_NT_SIMPLE_TEXT_PRIVATE_DATA, SimpleTextIn, WIN_NT_SIMPLE_TEXT_PRIVATE_DATA_SIGNATURE) + +// +// Console Globale Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gWinNtConsoleDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gWinNtConsoleComponentName; + +typedef struct { + UINTN ColumnsX; + UINTN RowsY; +} WIN_NT_SIMPLE_TEXT_OUT_MODE; + +// +// Simple Text Out protocol member functions +// + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutReset ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutOutputString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *String + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + String - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutTestString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *String + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + String - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ModeNumber - TODO: add argument description + Columns - TODO: add argument description + Rows - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutSetMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ModeNumber - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Attribute - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Column - TODO: add argument description + Row - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Enable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Enable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// Simple Text Out constructor and destructor. +// +EFI_STATUS +WinNtSimpleTextOutOpenWindow ( + IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +WinNtSimpleTextOutCloseWindow ( + IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Console - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// Simple Text In protocol member functions. +// +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextInReset ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Key - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +VOID +EFIAPI +WinNtSimpleTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Event - TODO: add argument description + Context - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// Simple Text In constructor +// +EFI_STATUS +WinNtSimpleTextInAttachToWindow ( + IN WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// Main Entry Point +// +EFI_STATUS +EFIAPI +InitializeWinNtConsole ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + SystemTable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +AppendDevicePathInstanceToVar ( + IN CHAR16 *VariableName, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + VariableName - TODO: add argument description + DevicePathInstance - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/ConsoleIn.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/ConsoleIn.c new file mode 100644 index 0000000000..3af1ce6570 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/ConsoleIn.c @@ -0,0 +1,361 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ConsoleIn.c + +Abstract: + + Console based on Win32 APIs. + + This file attaches a SimpleTextIn protocol to a previously open window. + + The constructor for this protocol depends on an open window. Currently + the SimpleTextOut protocol creates a window when it's constructor is called. + Thus this code must run after the constructor for the SimpleTextOut + protocol + +--*/ + +#include "Console.h" + +// +// Private worker functions +// +STATIC +EFI_STATUS +WinNtSimpleTextInCheckKey ( + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private + ); + +EFI_STATUS +EFIAPI +WinNtSimpleTextInReset ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + + Private = WIN_NT_SIMPLE_TEXT_IN_PRIVATE_DATA_FROM_THIS (This); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +WinNtConvertInputRecordToEfiKey ( + IN INPUT_RECORD *InputRecord, + OUT EFI_INPUT_KEY *Key + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + InputRecord - TODO: add argument description + Key - TODO: add argument description + +Returns: + + EFI_NOT_READY - TODO: Add description for return value + EFI_NOT_READY - TODO: Add description for return value + EFI_NOT_READY - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + // + // Make sure InputRecord is an event that represents a keypress + // + if (InputRecord->EventType == KEY_EVENT) { + if (!InputRecord->Event.KeyEvent.bKeyDown) { + return EFI_NOT_READY; + } + } else { + return EFI_NOT_READY; + } + + // + // Check to see if we should return a scan code in place of Unicode character. + // + Key->ScanCode = 0; + Key->UnicodeChar = 0; + if ((InputRecord->Event.KeyEvent.dwControlKeyState & (NUMLOCK_ON | ENHANCED_KEY)) != NUMLOCK_ON) { + // + // Only check these scan codes if num lock is off. + // + switch (InputRecord->Event.KeyEvent.wVirtualScanCode) { + case 0x48: Key->ScanCode = SCAN_UP; break; + case 0x50: Key->ScanCode = SCAN_DOWN; break; + case 0x4d: Key->ScanCode = SCAN_RIGHT; break; + case 0x4b: Key->ScanCode = SCAN_LEFT; break; + case 0x47: Key->ScanCode = SCAN_HOME; break; + case 0x4F: Key->ScanCode = SCAN_END; break; + case 0x52: Key->ScanCode = SCAN_INSERT; break; + case 0x53: Key->ScanCode = SCAN_DELETE; break; + case 0x49: Key->ScanCode = SCAN_PAGE_UP; break; + case 0x51: Key->ScanCode = SCAN_PAGE_DOWN; break; + } + } + + switch (InputRecord->Event.KeyEvent.wVirtualScanCode) { + case 0x3b: Key->ScanCode = SCAN_F1; break; + case 0x3c: Key->ScanCode = SCAN_F2; break; + case 0x3d: Key->ScanCode = SCAN_F3; break; + case 0x3e: Key->ScanCode = SCAN_F4; break; + case 0x3f: Key->ScanCode = SCAN_F5; break; + case 0x40: Key->ScanCode = SCAN_F6; break; + case 0x41: Key->ScanCode = SCAN_F7; break; + case 0x42: Key->ScanCode = SCAN_F8; break; + case 0x43: Key->ScanCode = SCAN_F9; break; + case 0x44: Key->ScanCode = SCAN_F10; break; + case 0x01: Key->ScanCode = SCAN_ESC; break; + } + + // + // If there's a scan code pass it, and don't pass the char code + // + if (Key->ScanCode == 0) { + Key->UnicodeChar = InputRecord->Event.KeyEvent.uChar.UnicodeChar; + if (Key->UnicodeChar == 0) { + return EFI_NOT_READY; + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Key - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_NOT_READY - TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + INPUT_RECORD InputRecord; + DWORD NtEventCount; + + Private = WIN_NT_SIMPLE_TEXT_IN_PRIVATE_DATA_FROM_THIS (This); + + Status = WinNtSimpleTextInCheckKey (Private); + if (EFI_ERROR (Status)) { + return Status; + } + + do { + + if (!Private->WinNtThunk->ReadConsoleInput (Private->NtInHandle, &InputRecord, 1, &NtEventCount)) { + return EFI_DEVICE_ERROR; + } + + if (NtEventCount == 0) { + return EFI_NOT_READY; + } + + // + // Convert the Input Record to an EFI Keystroke. + // + Status = WinNtConvertInputRecordToEfiKey (&InputRecord, Key); + } while (EFI_ERROR (Status)); + + return Status; +} + +STATIC +VOID +EFIAPI +WinNtSimpleTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Event - TODO: add argument description + Context - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + EFI_STATUS Status; + + Private = (WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *) Context; + Status = WinNtSimpleTextInCheckKey (Private); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (Event); + } +} + +STATIC +EFI_STATUS +WinNtSimpleTextInCheckKey ( + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + INPUT_RECORD *InputRecord; + DWORD NtEventCount; + DWORD ActualNtEventCount; + EFI_STATUS Status; + BOOLEAN Success; + UINTN Index; + EFI_INPUT_KEY Key; + + InputRecord = NULL; + NtEventCount = 0; + Private->WinNtThunk->GetNumberOfConsoleInputEvents (Private->NtInHandle, &NtEventCount); + if (NtEventCount == 0) { + Status = EFI_NOT_READY; + goto Done; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (INPUT_RECORD) * NtEventCount, + &InputRecord + ); + if (EFI_ERROR (Status)) { + Status = EFI_NOT_READY; + goto Done; + } + + Success = (BOOLEAN) Private->WinNtThunk->PeekConsoleInput ( + Private->NtInHandle, + InputRecord, + NtEventCount, + &ActualNtEventCount + ); + if (!Success) { + Status = EFI_NOT_READY; + goto Done; + } + + Status = EFI_NOT_READY; + for (Index = 0; Index < (UINTN) ActualNtEventCount; Index++) { + // + // Convert the Input Record to an EFI Keystroke. + // + Status = WinNtConvertInputRecordToEfiKey (&InputRecord[Index], &Key); + if (!EFI_ERROR (Status)) { + Status = EFI_SUCCESS; + goto Done; + } + } + +Done: + if (InputRecord != NULL) { + gBS->FreePool (InputRecord); + } + + return Status; +} + +EFI_STATUS +WinNtSimpleTextInAttachToWindow ( + IN WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_STATUS Status; + + Private->NtInHandle = Private->WinNtThunk->GetStdHandle (STD_INPUT_HANDLE); + + Private->SimpleTextIn.Reset = WinNtSimpleTextInReset; + Private->SimpleTextIn.ReadKeyStroke = WinNtSimpleTextInReadKeyStroke; + + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_WAIT, + EFI_TPL_NOTIFY, + WinNtSimpleTextInWaitForKey, + Private, + &Private->SimpleTextIn.WaitForKey + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/ConsoleOut.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/ConsoleOut.c new file mode 100644 index 0000000000..cab3768b1c --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/ConsoleOut.c @@ -0,0 +1,638 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ConsoleOut.c + +Abstract: + + Console based on Win32 APIs. + + This file creates an Win32 window and attaches a SimpleTextOut protocol. + +--*/ + +#include "Console.h" +// +// Private worker functions. +// + +STATIC +VOID +WinNtSimpleTextOutScrollScreen ( + IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console + ); + +STATIC +VOID +WinNtSimpleTextOutPutChar ( + IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console, + IN CHAR16 Char + ); + +// +// Modeule Global for Simple Text Out Mode. +// +#define MAX_SIMPLE_TEXT_OUT_MODE \ + (sizeof(mWinNtSimpleTextOutSupportedModes)/sizeof(WIN_NT_SIMPLE_TEXT_OUT_MODE)) + +STATIC WIN_NT_SIMPLE_TEXT_OUT_MODE mWinNtSimpleTextOutSupportedModes[] = { + { 80, 25 }, + { 80, 50 }, + { 80, 43 }, + { 100, 100 }, + { 100, 999 } +}; + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutReset ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This); + + WinNtSimpleTextOutSetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)); + + WinNtSimpleTextOutSetMode (This, 0); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutOutputString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *String + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + String - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + CHAR16 *Str; + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This); + + for (Str = String; *Str != '\0'; Str++) { + switch (*Str) { + case '\n': + if (Private->Possition.Y == (Private->MaxScreenSize.Y - 1)) { + WinNtSimpleTextOutScrollScreen (Private); + } + + if (Private->Possition.Y < (Private->MaxScreenSize.Y - 1)) { + Private->Possition.Y++; + This->Mode->CursorRow++; + } + break; + + case '\r': + Private->Possition.X = 0; + This->Mode->CursorColumn = 0; + break; + + case '\b': + if (Private->Possition.X > 0) { + Private->Possition.X--; + This->Mode->CursorColumn--; + } + break; + + default: + WinNtSimpleTextOutPutChar (Private, *Str); + } + } + + return EFI_SUCCESS; +} + +STATIC +VOID +WinNtSimpleTextOutPutChar ( + IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console, + IN CHAR16 Char + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Console - TODO: add argument description + Char - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + SMALL_RECT Region; + COORD StrCoordinate; + COORD StrSize; + CHAR_INFO CharInfo; + BOOL Flag; + + CharInfo.Char.UnicodeChar = Char; + CharInfo.Attributes = Console->Attribute; + + StrSize.X = 1; + StrSize.Y = 1; + StrCoordinate.X = 0; + StrCoordinate.Y = 0; + + Region.Left = (INT16) Console->Possition.X; + Region.Top = (INT16) Console->Possition.Y; + Region.Right = (INT16) (Console->Possition.X + 1); + Region.Bottom = (INT16) Console->Possition.Y; + + Console->WinNtThunk->WriteConsoleOutput ( + Console->NtOutHandle, + &CharInfo, + StrSize, + StrCoordinate, + &Region + ); + + if (Console->Possition.X >= (Console->MaxScreenSize.X - 1)) { + // + // If you print off the end wrap around + // + Console->SimpleTextOut.OutputString (&Console->SimpleTextOut, L"\n\r"); + } else { + Console->Possition.X++; + Console->SimpleTextOut.Mode->CursorColumn++; + } + + Flag = Console->WinNtThunk->SetConsoleCursorPosition (Console->NtOutHandle, Console->Possition); +} + +STATIC +VOID +WinNtSimpleTextOutScrollScreen ( + IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Console - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + SMALL_RECT Scroll; + CHAR_INFO CharInfo; + COORD Origin; + + CharInfo.Char.UnicodeChar = ' '; + CharInfo.Attributes = Console->Attribute; + + Origin.X = 0; + Origin.Y = 0; + + Scroll.Top = 1; + Scroll.Left = 0; + Scroll.Right = (INT16) Console->MaxScreenSize.X; + Scroll.Bottom = (INT16) Console->MaxScreenSize.Y; + + Console->WinNtThunk->ScrollConsoleScreenBuffer ( + Console->NtOutHandle, + &Scroll, + NULL, + Origin, + &CharInfo + ); +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutTestString ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *String + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + String - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This); + + // + // BugBug: The correct answer would be a function of what code pages + // are currently loaded? For now we will just return success. + // + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ModeNumber - TODO: add argument description + Columns - TODO: add argument description + Rows - TODO: add argument description + +Returns: + + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This); + + if (ModeNumber > MAX_SIMPLE_TEXT_OUT_MODE) { + return EFI_INVALID_PARAMETER; + } + + *Columns = mWinNtSimpleTextOutSupportedModes[ModeNumber].ColumnsX; + *Rows = mWinNtSimpleTextOutSupportedModes[ModeNumber].RowsY; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutSetMode ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ModeNumber - TODO: add argument description + +Returns: + + EFI_INVALID_PARAMETER - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This); + + if (ModeNumber > MAX_SIMPLE_TEXT_OUT_MODE) { + return EFI_INVALID_PARAMETER; + } + + Private->MaxScreenSize.X = (WORD) mWinNtSimpleTextOutSupportedModes[ModeNumber].ColumnsX; + Private->MaxScreenSize.Y = (WORD) mWinNtSimpleTextOutSupportedModes[ModeNumber].RowsY; + + Private->WinNtThunk->SetConsoleScreenBufferSize (Private->NtOutHandle, Private->MaxScreenSize); + Private->WinNtThunk->SetConsoleActiveScreenBuffer (Private->NtOutHandle); + + This->Mode->Mode = (INT32) ModeNumber; + + This->EnableCursor (This, TRUE); + This->ClearScreen (This); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Attribute - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This); + + Private->Attribute = (WORD) Attribute; + This->Mode->Attribute = (INT32) Attribute; + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + DWORD ConsoleWindow; + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This); + + This->SetCursorPosition (This, 0, 0); + + Private->WinNtThunk->FillConsoleOutputCharacter ( + Private->NtOutHandle, + ' ', + Private->MaxScreenSize.X * Private->MaxScreenSize.Y, + Private->Possition, + &ConsoleWindow + ); + Private->WinNtThunk->FillConsoleOutputAttribute ( + Private->NtOutHandle, + Private->Attribute, + Private->MaxScreenSize.X * Private->MaxScreenSize.Y, + Private->Possition, + &ConsoleWindow + ); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Column - TODO: add argument description + Row - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This); + + Private->Possition.X = (WORD) Column; + This->Mode->CursorColumn = (INT32) Column; + + Private->Possition.Y = (WORD) Row; + This->Mode->CursorRow = (INT32) Row; + Private->WinNtThunk->SetConsoleCursorPosition (Private->NtOutHandle, Private->Possition); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSimpleTextOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Enable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Enable - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private; + CONSOLE_CURSOR_INFO Info; + + Private = WIN_NT_SIMPLE_TEXT_OUT_PRIVATE_DATA_FROM_THIS (This); + Private->CursorEnable = Enable; + This->Mode->CursorVisible = Enable; + + Private->WinNtThunk->GetConsoleCursorInfo (Private->NtOutHandle, &Info); + Info.bVisible = Enable; + Private->WinNtThunk->SetConsoleCursorInfo (Private->NtOutHandle, &Info); + + return EFI_SUCCESS; +} + +EFI_STATUS +WinNtSimpleTextOutOpenWindow ( + IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_SIMPLE_TEXT_OUT_PROTOCOL *SimpleTextOut; + CHAR16 *WindowName; + + WindowName = Private->WinNtIo->EnvString; + Private->Attribute = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_INTENSITY; + if (*WindowName == '?') { + Private->Attribute = BACKGROUND_RED | FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN; + WindowName = L"EFI Emulator Error Console"; + } + + AddUnicodeString ( + "eng", + gWinNtConsoleComponentName.SupportedLanguages, + &Private->ControllerNameTable, + WindowName + ); + + // + // Fill in protocol member functions + // + SimpleTextOut = &Private->SimpleTextOut; + SimpleTextOut->Reset = WinNtSimpleTextOutReset; + SimpleTextOut->OutputString = WinNtSimpleTextOutOutputString; + SimpleTextOut->TestString = WinNtSimpleTextOutTestString; + SimpleTextOut->QueryMode = WinNtSimpleTextOutQueryMode; + SimpleTextOut->SetMode = WinNtSimpleTextOutSetMode; + SimpleTextOut->SetAttribute = WinNtSimpleTextOutSetAttribute; + SimpleTextOut->ClearScreen = WinNtSimpleTextOutClearScreen; + SimpleTextOut->SetCursorPosition = WinNtSimpleTextOutSetCursorPosition; + SimpleTextOut->EnableCursor = WinNtSimpleTextOutEnableCursor; + + // + // Initialize SimpleTextOut protocol mode structure + // + SimpleTextOut->Mode = &Private->SimpleTextOutMode; + SimpleTextOut->Mode->MaxMode = MAX_SIMPLE_TEXT_OUT_MODE; + SimpleTextOut->Mode->Attribute = (INT32) Private->Attribute; + + // + // Open the window an initialize it! + // + Private->NtOutHandle = Private->WinNtThunk->CreateConsoleScreenBuffer ( + GENERIC_WRITE | GENERIC_READ, + FILE_SHARE_WRITE | FILE_SHARE_READ, + NULL, + CONSOLE_TEXTMODE_BUFFER, + NULL + ); + Private->WinNtThunk->SetConsoleTitle (WindowName); + + return SimpleTextOut->SetMode (SimpleTextOut, 0); +} + +EFI_STATUS +WinNtSimpleTextOutCloseWindow ( + IN OUT WIN_NT_SIMPLE_TEXT_PRIVATE_DATA *Console + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Console - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + Console->WinNtThunk->CloseHandle (Console->NtOutHandle); + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/WinNtConsole.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/WinNtConsole.mbd new file mode 100644 index 0000000000..566a7481af --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/WinNtConsole.mbd @@ -0,0 +1,41 @@ + + + + + WinNtConsole + 263631d7-5836-4b74-be48-ee22e92ce5d3 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + BaseLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + UefiDriverModelLib + UefiDebugLibStdErr + BasePrintLib + DxeMemoryAllocationLib + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/WinNtConsole.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/WinNtConsole.msa new file mode 100644 index 0000000000..95f7595961 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/WinNtConsole.msa @@ -0,0 +1,75 @@ + + + + + WinNtConsole + UEFI_DRIVER + BS_DRIVER + 263631d7-5836-4b74-be48-ee22e92ce5d3 + 0 + Component description file for WinNtConsole module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + DebugLib + BaseLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + Console.h + Console.c + ConsoleIn.c + ConsoleOut.c + ComponentName.c + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + WinNtIo + SimpleTextOut + SimpleTextIn + + + + WinNtConsole + + + + + + + + gWinNtConsoleDriverBinding + gWinNtConsoleComponentName + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/build.xml new file mode 100644 index 0000000000..9d227c7f0e --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Console/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/ComponentName.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/ComponentName.c new file mode 100644 index 0000000000..82057866c7 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/ComponentName.c @@ -0,0 +1,187 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "WinNtSerialIo.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +WinNtSerialIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +WinNtSerialIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gWinNtSerialIoComponentName = { + WinNtSerialIoComponentNameGetDriverName, + WinNtSerialIoComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mWinNtSerialIoDriverNameTable[] = { + { "eng", L"Windows Serial I/O Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +WinNtSerialIoComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gWinNtSerialIoComponentName.SupportedLanguages, + mWinNtSerialIoDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +WinNtSerialIoComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; + + // + // This is a bus driver, so ChildHandle must not be NULL. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiSerialIoProtocolGuid, + &SerialIo, + gWinNtSerialIoDriverBinding.DriverBindingHandle, + ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo); + + return LookupUnicodeString ( + Language, + gWinNtSerialIoComponentName.SupportedLanguages, + Private->ControllerNameTable, + ControllerName + ); +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.c new file mode 100644 index 0000000000..38c03a8bbc --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.c @@ -0,0 +1,1410 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtSerialIo.c + +Abstract: + + Our DriverBinding member functions operate on the handles + created by the NT Bus driver. + + Handle(1) - WinNtIo - DevicePath(1) + + If a serial port is added to the system this driver creates a new handle. + The new handle is required, since the serial device must add an UART device + pathnode. + + Handle(2) - SerialIo - DevicePath(1)\UART + + The driver then adds a gEfiWinNtSerialPortGuid as a protocol to Handle(1). + The instance data for this protocol is the private data used to create + Handle(2). + + Handle(1) - WinNtIo - DevicePath(1) - WinNtSerialPort + + If the driver is unloaded Handle(2) is removed from the system and + gEfiWinNtSerialPortGuid is removed from Handle(1). + + Note: Handle(1) is any handle created by the Win NT Bus driver that is passed + into the DriverBinding member functions of this driver. This driver requires + a Handle(1) to contain a WinNtIo protocol, a DevicePath protocol, and + the TypeGuid in the WinNtIo must be gEfiWinNtSerialPortGuid. + + If Handle(1) contains a gEfiWinNtSerialPortGuid protocol then the driver is + loaded on the device. + +--*/ + +#include "WinNtSerialIo.h" + +EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding = { + WinNtSerialIoDriverBindingSupported, + WinNtSerialIoDriverBindingStart, + WinNtSerialIoDriverBindingStop, + 0x10, + NULL, + NULL +}; + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + UART_DEVICE_PATH *UartNode; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + &ParentDevicePath, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure that the WinNt Thunk Protocol is valid + // + if (WinNtIo->WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) { + Status = EFI_UNSUPPORTED; + goto Error; + } + + // + // Check the GUID to see if this is a handle type the driver supports + // + if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtSerialPortGuid)) { + Status = EFI_UNSUPPORTED; + goto Error; + } + + if (RemainingDevicePath != NULL) { + Status = EFI_UNSUPPORTED; + UartNode = (UART_DEVICE_PATH *) RemainingDevicePath; + if (UartNode->Header.Type != MESSAGING_DEVICE_PATH || + UartNode->Header.SubType != MSG_UART_DP || + DevicePathNodeLength((EFI_DEVICE_PATH_PROTOCOL *)UartNode) != sizeof(UART_DEVICE_PATH)) { + goto Error; + } + if (UartNode->BaudRate < 0 || UartNode->BaudRate > SERIAL_PORT_MAX_BAUD_RATE) { + goto Error; + } + if (UartNode->Parity < NoParity || UartNode->Parity > SpaceParity) { + goto Error; + } + if (UartNode->DataBits < 5 || UartNode->DataBits > 8) { + goto Error; + } + if (UartNode->StopBits < OneStopBit || UartNode->StopBits > TwoStopBits) { + goto Error; + } + if ((UartNode->DataBits == 5) && (UartNode->StopBits == TwoStopBits)) { + goto Error; + } + if ((UartNode->DataBits >= 6) && (UartNode->DataBits <= 8) && (UartNode->StopBits == OneFiveStopBits)) { + goto Error; + } + Status = EFI_SUCCESS; + } + +Error: + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; + HANDLE NtHandle; + UART_DEVICE_PATH Node; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfoBuffer; + UINTN EntryCount; + UINTN Index; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + + Private = NULL; + NtHandle = INVALID_HANDLE_VALUE; + + // + // Grab the protocols we need + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + &ParentDevicePath, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + // + // Grab the IO abstraction we need to get any work done + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + gBS->CloseProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Handle + ); + return Status; + } + + if (Status == EFI_ALREADY_STARTED) { + + if (RemainingDevicePath == NULL) { + return EFI_SUCCESS; + } + + // + // Make sure a child handle does not already exist. This driver can only + // produce one child per serial port. + // + Status = gBS->OpenProtocolInformation ( + Handle, + &gEfiWinNtIoProtocolGuid, + &OpenInfoBuffer, + &EntryCount + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = EFI_ALREADY_STARTED; + for (Index = 0; Index < EntryCount; Index++) { + if (OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { + Status = gBS->OpenProtocol ( + OpenInfoBuffer[Index].ControllerHandle, + &gEfiSerialIoProtocolGuid, + &SerialIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + CopyMem (&Node, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); + Status = SerialIo->SetAttributes ( + SerialIo, + Node.BaudRate, + SerialIo->Mode->ReceiveFifoDepth, + SerialIo->Mode->Timeout, + Node.Parity, + Node.DataBits, + Node.StopBits + ); + } + break; + } + } + + gBS->FreePool (OpenInfoBuffer); + return Status; + } + + // + // Check to see if we can access the hardware device. If it's Open in NT we + // will not get access. + // + NtHandle = WinNtIo->WinNtThunk->CreateFile ( + WinNtIo->EnvString, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + if (NtHandle == INVALID_HANDLE_VALUE) { + Status = EFI_DEVICE_ERROR; + goto Error; + } + + // + // Construct Private data + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (WIN_NT_SERIAL_IO_PRIVATE_DATA), + &Private + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // This signature must be valid before any member function is called + // + Private->Signature = WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE; + Private->NtHandle = NtHandle; + Private->ControllerHandle = Handle; + Private->Handle = NULL; + Private->WinNtThunk = WinNtIo->WinNtThunk; + Private->ParentDevicePath = ParentDevicePath; + Private->ControllerNameTable = NULL; + + Private->SoftwareLoopbackEnable = FALSE; + Private->HardwareLoopbackEnable = FALSE; + Private->HardwareFlowControl = FALSE; + Private->Fifo.First = 0; + Private->Fifo.Last = 0; + Private->Fifo.Surplus = SERIAL_MAX_BUFFER_SIZE; + + AddUnicodeString ( + "eng", + gWinNtSerialIoComponentName.SupportedLanguages, + &Private->ControllerNameTable, + WinNtIo->EnvString + ); + + Private->SerialIo.Revision = SERIAL_IO_INTERFACE_REVISION; + Private->SerialIo.Reset = WinNtSerialIoReset; + Private->SerialIo.SetAttributes = WinNtSerialIoSetAttributes; + Private->SerialIo.SetControl = WinNtSerialIoSetControl; + Private->SerialIo.GetControl = WinNtSerialIoGetControl; + Private->SerialIo.Write = WinNtSerialIoWrite; + Private->SerialIo.Read = WinNtSerialIoRead; + Private->SerialIo.Mode = &Private->SerialIoMode; + + if (RemainingDevicePath != NULL) { + // + // Match the configuration of the RemainingDevicePath. IsHandleSupported() + // already checked to make sure the RemainingDevicePath contains settings + // that we can support. + // + CopyMem (&Private->UartDevicePath, RemainingDevicePath, sizeof (UART_DEVICE_PATH)); + } else { + // + // Build the device path by appending the UART node to the ParentDevicePath + // from the WinNtIo handle. The Uart setings are zero here, since + // SetAttribute() will update them to match the default setings. + // + ZeroMem (&Private->UartDevicePath, sizeof (UART_DEVICE_PATH)); + Private->UartDevicePath.Header.Type = MESSAGING_DEVICE_PATH; + Private->UartDevicePath.Header.SubType = MSG_UART_DP; + SetDevicePathNodeLength ((EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath, sizeof (UART_DEVICE_PATH)); + } + + // + // Build the device path by appending the UART node to the ParentDevicePath + // from the WinNtIo handle. The Uart setings are zero here, since + // SetAttribute() will update them to match the current setings. + // + Private->DevicePath = AppendDevicePathNode ( + ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath + ); + if (Private->DevicePath == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Error; + } + + // + // Fill in Serial I/O Mode structure based on either the RemainingDevicePath or defaults. + // + Private->SerialIoMode.ControlMask = SERIAL_CONTROL_MASK; + Private->SerialIoMode.Timeout = SERIAL_TIMEOUT_DEFAULT; + Private->SerialIoMode.BaudRate = Private->UartDevicePath.BaudRate; + Private->SerialIoMode.ReceiveFifoDepth = SERIAL_FIFO_DEFAULT; + Private->SerialIoMode.DataBits = Private->UartDevicePath.DataBits; + Private->SerialIoMode.Parity = Private->UartDevicePath.Parity; + Private->SerialIoMode.StopBits = Private->UartDevicePath.StopBits; + + // + // Issue a reset to initialize the COM port + // + Status = Private->SerialIo.Reset (&Private->SerialIo); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Create new child handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->Handle, + &gEfiSerialIoProtocolGuid, + &Private->SerialIo, + &gEfiDevicePathProtocolGuid, + Private->DevicePath, + NULL + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + // + // Open For Child Device + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Private->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + goto Error; + } + + return EFI_SUCCESS; + +Error: + // + // Use the Stop() function to free all resources allocated in Start() + // + if (Private != NULL) { + if (Private->Handle != NULL) { + This->Stop (This, Handle, 1, &Private->Handle); + } else { + if (NtHandle != INVALID_HANDLE_VALUE) { + Private->WinNtThunk->CloseHandle (NtHandle); + } + + if (Private->DevicePath != NULL) { + gBS->FreePool (Private->DevicePath); + } + + FreeUnicodeStringTable (Private->ControllerNameTable); + + gBS->FreePool (Private); + } + } + + This->Stop (This, Handle, 0, NULL); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + BOOLEAN AllChildrenStopped; + EFI_SERIAL_IO_PROTOCOL *SerialIo; + WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + + // + // Complete all outstanding transactions to Controller. + // Don't allow any new transaction to Controller to be started. + // + + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + Status = gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + Status = gBS->CloseProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + Handle + ); + return Status; + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiSerialIoProtocolGuid, + &SerialIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (SerialIo); + + ASSERT (Private->Handle == ChildHandleBuffer[Index]); + + Status = gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + ChildHandleBuffer[Index] + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + ChildHandleBuffer[Index], + &gEfiSerialIoProtocolGuid, + &Private->SerialIo, + &gEfiDevicePathProtocolGuid, + Private->DevicePath, + NULL + ); + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + (VOID **) &WinNtIo, + This->DriverBindingHandle, + ChildHandleBuffer[Index], + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + Private->WinNtThunk->CloseHandle (Private->NtHandle); + + gBS->FreePool (Private->DevicePath); + + FreeUnicodeStringTable (Private->ControllerNameTable); + + gBS->FreePool (Private); + } + } + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +// +// Serial IO Protocol member functions +// + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoReset ( + IN EFI_SERIAL_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; + EFI_TPL Tpl; + + Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); + + Private->WinNtThunk->PurgeComm ( + Private->NtHandle, + PURGE_TXCLEAR | PURGE_RXCLEAR + ); + + gBS->RestoreTPL (Tpl); + + return This->SetAttributes ( + This, + This->Mode->BaudRate, + This->Mode->ReceiveFifoDepth, + This->Mode->Timeout, + This->Mode->Parity, + (UINT8) This->Mode->DataBits, + This->Mode->StopBits + ); +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoSetAttributes ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ) +/*++ + +Routine Description: + + This function is used to set the attributes. + +Arguments: + + This - A pointer to the EFI_SERIAL_IO_PROTOCOL structrue. + BaudRate - The Baud rate of the serial device. + ReceiveFifoDepth - The request depth of fifo on receive side. + Timeout - the request timeout for a single charact. + Parity - The type of parity used in serial device. + DataBits - Number of deata bits used in serial device. + StopBits - Number of stop bits used in serial device. + +Returns: + Status code + + None + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; + COMMTIMEOUTS PortTimeOuts; + DWORD ConvertedTime; + BOOL Result; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_TPL Tpl; + + Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); + + // + // Some of our arguments have defaults if a null value is passed in, and + // we must set the default values if a null argument is passed in. + // + if (BaudRate == 0) { + BaudRate = SERIAL_BAUD_DEFAULT; + } + + if (ReceiveFifoDepth == 0) { + ReceiveFifoDepth = SERIAL_FIFO_DEFAULT; + } + + if (Timeout == 0) { + Timeout = SERIAL_TIMEOUT_DEFAULT; + } + + if (Parity == DefaultParity) { + Parity = NoParity; + } + + if (DataBits == 0) { + DataBits = SERIAL_DATABITS_DEFAULT; + } + + if (StopBits == DefaultStopBits) { + StopBits = OneStopBit; + } + // + // See if the new attributes already match the current attributes + // + if (Private->UartDevicePath.BaudRate == BaudRate && + Private->UartDevicePath.DataBits == DataBits && + Private->UartDevicePath.Parity == Parity && + Private->UartDevicePath.StopBits == StopBits && + Private->SerialIoMode.ReceiveFifoDepth == ReceiveFifoDepth && + Private->SerialIoMode.Timeout == Timeout ) { + gBS->RestoreTPL(Tpl); + return EFI_SUCCESS; + } + + // + // Get current values from NT + // + ZeroMem (&Private->NtDCB, sizeof (DCB)); + Private->NtDCB.DCBlength = sizeof (DCB); + + if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Private->NtDCB)) { + Private->NtError = Private->WinNtThunk->GetLastError (); + DEBUG ((EFI_D_ERROR, "SerialSetAttributes: GetCommState %d\n", Private->NtError)); + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + + // + // Map EFI com setting to NT + // + Private->NtDCB.BaudRate = ConvertBaud2Nt (BaudRate); + Private->NtDCB.ByteSize = ConvertData2Nt (DataBits); + Private->NtDCB.Parity = ConvertParity2Nt (Parity); + Private->NtDCB.StopBits = ConvertStop2Nt (StopBits); + + Private->NtDCB.fBinary = TRUE; + Private->NtDCB.fParity = Private->NtDCB.Parity == NOPARITY ? FALSE : TRUE; + Private->NtDCB.fOutxCtsFlow = FALSE; + Private->NtDCB.fOutxDsrFlow = FALSE; + Private->NtDCB.fDtrControl = DTR_CONTROL_ENABLE; + Private->NtDCB.fDsrSensitivity = FALSE; + Private->NtDCB.fOutX = FALSE; + Private->NtDCB.fInX = FALSE; + Private->NtDCB.fRtsControl = RTS_CONTROL_ENABLE; + Private->NtDCB.fNull = FALSE; + + // + // Set new values + // + Result = Private->WinNtThunk->SetCommState (Private->NtHandle, &Private->NtDCB); + if (!Result) { + Private->NtError = Private->WinNtThunk->GetLastError (); + DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommState %d\n", Private->NtError)); + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + + // + // Set com port read/write timeout values + // + ConvertedTime = ConvertTime2Nt (Timeout); + PortTimeOuts.ReadIntervalTimeout = MAXDWORD; + PortTimeOuts.ReadTotalTimeoutMultiplier = 0; + PortTimeOuts.ReadTotalTimeoutConstant = ConvertedTime; + PortTimeOuts.WriteTotalTimeoutMultiplier = ConvertedTime == 0 ? 1 : ConvertedTime; + PortTimeOuts.WriteTotalTimeoutConstant = 0; + + if (!Private->WinNtThunk->SetCommTimeouts (Private->NtHandle, &PortTimeOuts)) { + Private->NtError = Private->WinNtThunk->GetLastError (); + DEBUG ((EFI_D_ERROR, "SerialSetAttributes: SetCommTimeouts %d\n", Private->NtError)); + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + + // + // Update mode + // + Private->SerialIoMode.BaudRate = BaudRate; + Private->SerialIoMode.ReceiveFifoDepth = ReceiveFifoDepth; + Private->SerialIoMode.Timeout = Timeout; + Private->SerialIoMode.Parity = Parity; + Private->SerialIoMode.DataBits = DataBits; + Private->SerialIoMode.StopBits = StopBits; + + // + // See if Device Path Node has actually changed + // + if (Private->UartDevicePath.BaudRate == BaudRate && + Private->UartDevicePath.DataBits == DataBits && + Private->UartDevicePath.Parity == Parity && + Private->UartDevicePath.StopBits == StopBits ) { + gBS->RestoreTPL(Tpl); + return EFI_SUCCESS; + } + + // + // Update the device path + // + Private->UartDevicePath.BaudRate = BaudRate; + Private->UartDevicePath.DataBits = DataBits; + Private->UartDevicePath.Parity = (UINT8) Parity; + Private->UartDevicePath.StopBits = (UINT8) StopBits; + + NewDevicePath = AppendDevicePathNode ( + Private->ParentDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &Private->UartDevicePath + ); + if (NewDevicePath == NULL) { + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + + if (Private->Handle != NULL) { + Status = gBS->ReinstallProtocolInterface ( + Private->Handle, + &gEfiDevicePathProtocolGuid, + Private->DevicePath, + NewDevicePath + ); + if (EFI_ERROR (Status)) { + gBS->RestoreTPL (Tpl); + return Status; + } + } + + if (Private->DevicePath != NULL) { + gBS->FreePool (Private->DevicePath); + } + + Private->DevicePath = NewDevicePath; + + gBS->RestoreTPL (Tpl); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoSetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Control - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; + BOOL Result; + DCB Dcb; + EFI_TPL Tpl; + + Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); + + Result = Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb); + + if (!Result) { + Private->NtError = Private->WinNtThunk->GetLastError (); + DEBUG ((EFI_D_ERROR, "SerialSetControl: GetCommState %d\n", Private->NtError)); + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + + Dcb.fRtsControl = RTS_CONTROL_DISABLE; + Dcb.fDtrControl = DTR_CONTROL_DISABLE; + Private->HardwareFlowControl = FALSE; + Private->SoftwareLoopbackEnable = FALSE; + Private->HardwareLoopbackEnable = FALSE; + + if (Control & EFI_SERIAL_REQUEST_TO_SEND) { + Dcb.fRtsControl = RTS_CONTROL_ENABLE; + } + + if (Control & EFI_SERIAL_DATA_TERMINAL_READY) { + Dcb.fDtrControl = DTR_CONTROL_ENABLE; + } + + if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) { + Private->HardwareFlowControl = TRUE; + } + + if (Control & EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE) { + Private->SoftwareLoopbackEnable = TRUE; + } + + if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) { + Private->HardwareLoopbackEnable = TRUE; + } + + Result = Private->WinNtThunk->SetCommState ( + Private->NtHandle, + &Dcb + ); + + if (!Result) { + Private->NtError = Private->WinNtThunk->GetLastError (); + DEBUG ((EFI_D_ERROR, "SerialSetControl: SetCommState %d\n", Private->NtError)); + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + + gBS->RestoreTPL (Tpl); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoGetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Control - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; + DWORD ModemStatus; + DWORD Errors; + UINT32 Bits; + DCB Dcb; + EFI_TPL Tpl; + + Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); + + // + // Get modem status + // + if (!Private->WinNtThunk->GetCommModemStatus (Private->NtHandle, &ModemStatus)) { + Private->NtError = Private->WinNtThunk->GetLastError (); + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + + Bits = 0; + if (ModemStatus & MS_CTS_ON) { + Bits |= EFI_SERIAL_CLEAR_TO_SEND; + } + + if (ModemStatus & MS_DSR_ON) { + Bits |= EFI_SERIAL_DATA_SET_READY; + } + + if (ModemStatus & MS_RING_ON) { + Bits |= EFI_SERIAL_RING_INDICATE; + } + + if (ModemStatus & MS_RLSD_ON) { + Bits |= EFI_SERIAL_CARRIER_DETECT; + } + + // + // Get ctrl status + // + if (!Private->WinNtThunk->GetCommState (Private->NtHandle, &Dcb)) { + Private->NtError = Private->WinNtThunk->GetLastError (); + DEBUG ((EFI_D_ERROR, "SerialGetControl: GetCommState %d\n", Private->NtError)); + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + + if (Dcb.fDtrControl == DTR_CONTROL_ENABLE) { + Bits |= EFI_SERIAL_DATA_TERMINAL_READY; + } + + if (Dcb.fRtsControl == RTS_CONTROL_ENABLE) { + Bits |= EFI_SERIAL_REQUEST_TO_SEND; + } + + if (Private->HardwareFlowControl) { + Bits |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE; + } + + if (Private->SoftwareLoopbackEnable) { + Bits |= EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE; + } + + if (Private->HardwareLoopbackEnable) { + Bits |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE; + } + + // + // Get input buffer status + // + if (!Private->WinNtThunk->ClearCommError (Private->NtHandle, &Errors, &Private->NtComStatus)) { + Private->NtError = Private->WinNtThunk->GetLastError (); + DEBUG ((EFI_D_ERROR, "SerialGetControl: ClearCommError %d\n", Private->NtError)); + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + + if (Private->NtComStatus.cbInQue == 0) { + Bits |= EFI_SERIAL_INPUT_BUFFER_EMPTY; + } + + *Control = Bits; + + gBS->RestoreTPL (Tpl); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoWrite ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; + UINT8 *ByteBuffer; + UINTN TotalBytesWritten; + DWORD BytesToGo; + DWORD BytesWritten; + BOOL Result; + UINT32 Index; + UINT32 Control; + EFI_TPL Tpl; + + Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); + + ByteBuffer = (UINT8 *) Buffer; + TotalBytesWritten = 0; + + if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) { + for (Index = 0; Index < *BufferSize; Index++) { + if (IsaSerialFifoAdd (&Private->Fifo, ByteBuffer[Index]) == EFI_SUCCESS) { + TotalBytesWritten++; + } else { + break; + } + } + } else { + BytesToGo = (DWORD) (*BufferSize); + + do { + if (Private->HardwareFlowControl) { + // + // Send RTS + // + WinNtSerialIoGetControl (&Private->SerialIo, &Control); + Control |= EFI_SERIAL_REQUEST_TO_SEND; + WinNtSerialIoSetControl (&Private->SerialIo, Control); + } + + // + // Do the write + // + Result = Private->WinNtThunk->WriteFile ( + Private->NtHandle, + &ByteBuffer[TotalBytesWritten], + BytesToGo, + &BytesWritten, + NULL + ); + + if (Private->HardwareFlowControl) { + // + // Assert RTS + // + WinNtSerialIoGetControl (&Private->SerialIo, &Control); + Control &= ~ (UINT32) EFI_SERIAL_REQUEST_TO_SEND; + WinNtSerialIoSetControl (&Private->SerialIo, Control); + } + + TotalBytesWritten += BytesWritten; + BytesToGo -= BytesWritten; + if (!Result) { + Private->NtError = Private->WinNtThunk->GetLastError (); + DEBUG ((EFI_D_ERROR, "SerialWrite: FileWrite %d\n", Private->NtError)); + *BufferSize = TotalBytesWritten; + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + } while (BytesToGo > 0); + } + + *BufferSize = TotalBytesWritten; + + gBS->RestoreTPL (Tpl); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoRead ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - TODO: Add description for return value + +--*/ +{ + WIN_NT_SERIAL_IO_PRIVATE_DATA *Private; + BOOL Result; + DWORD BytesRead; + EFI_STATUS Status; + UINT32 Index; + UINT8 Data; + UINT32 Control; + EFI_TPL Tpl; + + Tpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + Private = WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS (This); + + // + // Do the read + // + if (Private->SoftwareLoopbackEnable || Private->HardwareLoopbackEnable) { + for (Index = 0, BytesRead = 0; Index < *BufferSize; Index++) { + if (IsaSerialFifoRemove (&Private->Fifo, &Data) == EFI_SUCCESS) { + ((UINT8 *) Buffer)[Index] = Data; + BytesRead++; + } else { + break; + } + } + } else { + if (Private->HardwareFlowControl) { + WinNtSerialIoGetControl (&Private->SerialIo, &Control); + Control |= EFI_SERIAL_DATA_TERMINAL_READY; + WinNtSerialIoSetControl (&Private->SerialIo, Control); + } + + Result = Private->WinNtThunk->ReadFile ( + Private->NtHandle, + Buffer, + (DWORD) *BufferSize, + &BytesRead, + NULL + ); + + if (Private->HardwareFlowControl) { + WinNtSerialIoGetControl (&Private->SerialIo, &Control); + Control &= ~ (UINT32) EFI_SERIAL_DATA_TERMINAL_READY; + WinNtSerialIoSetControl (&Private->SerialIo, Control); + } + + if (!Result) { + Private->NtError = Private->WinNtThunk->GetLastError (); + gBS->RestoreTPL (Tpl); + return EFI_DEVICE_ERROR; + } + } + + if (BytesRead != *BufferSize) { + Status = EFI_TIMEOUT; + } else { + Status = EFI_SUCCESS; + } + + *BufferSize = (UINTN) BytesRead; + + gBS->RestoreTPL (Tpl); + + return Status; +} + +BOOLEAN +IsaSerialFifoFull ( + IN SERIAL_DEV_FIFO *Fifo + ) +/*++ + + Routine Description: + Detect whether specific FIFO is full or not + + Arguments: + Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO + + Returns: + TRUE: the FIFO is full + FALSE: the FIFO is not full + +--*/ +{ + if (Fifo->Surplus == 0) { + return TRUE; + } + + return FALSE; +} + +BOOLEAN +IsaSerialFifoEmpty ( + IN SERIAL_DEV_FIFO *Fifo + ) +/*++ + + Routine Description: + Detect whether specific FIFO is empty or not + + Arguments: + Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO + + Returns: + TRUE: the FIFO is empty + FALSE: the FIFO is not empty + +--*/ +{ + if (Fifo->Surplus == SERIAL_MAX_BUFFER_SIZE) { + return TRUE; + } + + return FALSE; +} + +EFI_STATUS +IsaSerialFifoAdd ( + IN SERIAL_DEV_FIFO *Fifo, + IN UINT8 Data + ) +/*++ + + Routine Description: + Add data to specific FIFO + + Arguments: + Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO + Data UINT8: the data added to FIFO + + Returns: + EFI_SUCCESS: Add data to specific FIFO successfully + EFI_OUT_RESOURCE: Failed to add data because FIFO is already full + +--*/ +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +{ + // + // if FIFO full can not add data + // + if (IsaSerialFifoFull (Fifo)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // FIFO is not full can add data + // + Fifo->Data[Fifo->Last] = Data; + Fifo->Surplus--; + Fifo->Last++; + if (Fifo->Last >= SERIAL_MAX_BUFFER_SIZE) { + Fifo->Last = 0; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +IsaSerialFifoRemove ( + IN SERIAL_DEV_FIFO *Fifo, + OUT UINT8 *Data + ) +/*++ + + Routine Description: + Remove data from specific FIFO + + Arguments: + Fifo SERIAL_DEV_FIFO *: A pointer to the Data Structure SERIAL_DEV_FIFO + Data UINT8*: the data removed from FIFO + + Returns: + EFI_SUCCESS: Remove data from specific FIFO successfully + EFI_OUT_RESOURCE: Failed to remove data because FIFO is empty + +--*/ +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +{ + // + // if FIFO is empty, no data can remove + // + if (IsaSerialFifoEmpty (Fifo)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // FIFO is not empty, can remove data + // + *Data = Fifo->Data[Fifo->First]; + Fifo->Surplus++; + Fifo->First++; + if (Fifo->First >= SERIAL_MAX_BUFFER_SIZE) { + Fifo->First = 0; + } + + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.h b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.h new file mode 100644 index 0000000000..79e905c5ad --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.h @@ -0,0 +1,513 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtSerialIo.h + +Abstract: + + +--*/ + +#ifndef _WIN_NT_SERIAL_IO_ +#define _WIN_NT_SERIAL_IO_ + + + +#define SERIAL_MAX_BUFFER_SIZE 256 +#define TIMEOUT_STALL_INTERVAL 10 + +typedef struct { + UINT32 First; + UINT32 Last; + UINT32 Surplus; + UINT8 Data[SERIAL_MAX_BUFFER_SIZE]; +} SERIAL_DEV_FIFO; + +#define WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('N', 'T', 's', 'i') +typedef struct { + UINT64 Signature; + + // + // Protocol data for the new handle we are going to add + // + EFI_HANDLE Handle; + EFI_SERIAL_IO_PROTOCOL SerialIo; + EFI_SERIAL_IO_MODE SerialIoMode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // Private Data + // + EFI_HANDLE ControllerHandle; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + UART_DEVICE_PATH UartDevicePath; + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + + // + // Private NT type Data; + // + HANDLE NtHandle; + DCB NtDCB; + DWORD NtError; + COMSTAT NtComStatus; + + BOOLEAN SoftwareLoopbackEnable; + BOOLEAN HardwareFlowControl; + BOOLEAN HardwareLoopbackEnable; + + SERIAL_DEV_FIFO Fifo; + +} WIN_NT_SERIAL_IO_PRIVATE_DATA; + +#define WIN_NT_SERIAL_IO_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, WIN_NT_SERIAL_IO_PRIVATE_DATA, SerialIo, WIN_NT_SERIAL_IO_PRIVATE_DATA_SIGNATURE) + +// +// Global Protocol Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gWinNtSerialIoDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gWinNtSerialIoComponentName; + +// +// Macros to convert EFI serial types to NT serial types. +// + +// +// one second +// +#define SERIAL_TIMEOUT_DEFAULT (1000 * 1000) +#define SERIAL_BAUD_DEFAULT 115200 +#define SERIAL_FIFO_DEFAULT 14 +#define SERIAL_DATABITS_DEFAULT 8 +#define SERIAL_PARITY_DEFAULT DefaultParity +#define SERIAL_STOPBITS_DEFAULT DefaultStopBits + +#define SERIAL_CONTROL_MASK (EFI_SERIAL_CLEAR_TO_SEND | \ + EFI_SERIAL_DATA_SET_READY | \ + EFI_SERIAL_RING_INDICATE | \ + EFI_SERIAL_CARRIER_DETECT | \ + EFI_SERIAL_REQUEST_TO_SEND | \ + EFI_SERIAL_DATA_TERMINAL_READY | \ + EFI_SERIAL_INPUT_BUFFER_EMPTY) + +#define ConvertBaud2Nt(x) (DWORD) x +#define ConvertData2Nt(x) (BYTE) x + +#define ConvertParity2Nt(x) \ + (BYTE) ( \ + x == DefaultParity ? NOPARITY : \ + x == NoParity ? NOPARITY : \ + x == EvenParity ? EVENPARITY : \ + x == OddParity ? ODDPARITY : \ + x == MarkParity ? MARKPARITY : \ + x == SpaceParity ? SPACEPARITY : 0 \ + ) + +#define ConvertStop2Nt(x) \ + (BYTE) ( \ + x == DefaultParity ? ONESTOPBIT : \ + x == OneFiveStopBits ? ONE5STOPBITS : \ + x == TwoStopBits ? TWOSTOPBITS : 0 \ + ) + +#define ConvertTime2Nt(x) ((x) / 1000) + +// +// 115400 baud with rounding errors +// +#define SERIAL_PORT_MAX_BAUD_RATE 115400 + +// +// Function Prototypes +// +EFI_STATUS +EFIAPI +InitializeWinNtSerialIo ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + SystemTable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoReset ( + IN EFI_SERIAL_IO_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoSetAttributes ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + BaudRate - TODO: add argument description + ReceiveFifoDepth - TODO: add argument description + Timeout - TODO: add argument description + Parity - TODO: add argument description + DataBits - TODO: add argument description + StopBits - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoSetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Control - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoGetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Control - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoWrite ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +STATIC +EFI_STATUS +EFIAPI +WinNtSerialIoRead ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsaSerialFifoFull ( + IN SERIAL_DEV_FIFO *Fifo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Fifo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +BOOLEAN +IsaSerialFifoEmpty ( + IN SERIAL_DEV_FIFO *Fifo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Fifo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +IsaSerialFifoAdd ( + IN SERIAL_DEV_FIFO *Fifo, + IN UINT8 Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Fifo - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +IsaSerialFifoRemove ( + IN SERIAL_DEV_FIFO *Fifo, + OUT UINT8 *Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Fifo - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +IsaSerialReceiveTransmit ( + WIN_NT_SERIAL_IO_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.mbd new file mode 100644 index 0000000000..a5b19f99c4 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.mbd @@ -0,0 +1,42 @@ + + + + + WinNtSerialIo + 6B41B553-A649-11d4-BD02-0080C73C8881 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-13 17:02 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + BaseLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + UefiDriverModelLib + UefiDebugLibStdErr + BasePrintLib + DxeMemoryAllocationLib + UefiDevicePathLib + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.msa new file mode 100644 index 0000000000..cf987e2230 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.msa @@ -0,0 +1,74 @@ + + + + + WinNtSerialIo + UEFI_DRIVER + BS_DRIVER + 6B41B553-A649-11d4-BD02-0080C73C8881 + 0 + Component description file for WinNtSerialIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-13 17:02 + 2006-03-19 15:17 + + + DebugLib + BaseLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + DevicePathLib + + + WinNtSerialIo.h + WinNtSerialIo.c + ComponentName.c + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + WinNtIo + DevicePath + SerialIo + + + + WinNtSerialPort + + + + + + + + gWinNtSerialIoDriverBinding + gWinNtSerialIoComponentName + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/build.xml new file mode 100644 index 0000000000..7114d3bae2 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SerialIo/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/ComponentName.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/ComponentName.c new file mode 100644 index 0000000000..de4abd73e7 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/ComponentName.c @@ -0,0 +1,193 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "WinNtSimpleFileSystem.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gWinNtSimpleFileSystemComponentName = { + WinNtSimpleFileSystemComponentNameGetDriverName, + WinNtSimpleFileSystemComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mWinNtSimpleFileSystemDriverNameTable[] = { + { + "eng", + L"Windows Simple File System Driver" + }, + { + NULL, + NULL + } +}; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gWinNtSimpleFileSystemComponentName.SupportedLanguages, + mWinNtSimpleFileSystemDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; + WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + &SimpleFileSystem, + gWinNtSimpleFileSystemDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem); + + return LookupUnicodeString ( + Language, + gWinNtSimpleFileSystemComponentName.SupportedLanguages, + Private->ControllerNameTable, + ControllerName + ); +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.c new file mode 100644 index 0000000000..5552bc28be --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.c @@ -0,0 +1,2615 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtSimpleFileSystem.c + +Abstract: + + Produce Simple File System abstractions for directories on your PC using Win32 APIs. + The configuration of what devices to mount or emulate comes from NT + environment variables. The variables must be visible to the Microsoft* + Developer Studio for them to work. + + * Other names and brands may be claimed as the property of others. + +--*/ + +#include "WinNtSimpleFileSystem.h" + +EFI_DRIVER_BINDING_PROTOCOL gWinNtSimpleFileSystemDriverBinding = { + WinNtSimpleFileSystemDriverBindingSupported, + WinNtSimpleFileSystemDriverBindingStart, + WinNtSimpleFileSystemDriverBindingStop, + 0x10, + NULL, + NULL +}; + + +CHAR16 * +EfiStrChr ( + IN CHAR16 *Str, + IN CHAR16 Chr + ) +/*++ + +Routine Description: + + Locate the first occurance of a character in a string. + +Arguments: + + Str - Pointer to NULL terminated unicode string. + Chr - Character to locate. + +Returns: + + If Str is NULL, then NULL is returned. + If Chr is not contained in Str, then NULL is returned. + If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned. + +--*/ +{ + if (Str == NULL) { + return Str; + } + + while (*Str != '\0' && *Str != Chr) { + ++Str; + } + + return (*Str == Chr) ? Str : NULL; +} + +BOOLEAN +IsZero ( + IN VOID *Buffer, + IN UINTN Length + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Buffer - TODO: add argument description + Length - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + if (Buffer == NULL || Length == 0) { + return FALSE; + } + + if (*(UINT8 *) Buffer != 0) { + return FALSE; + } + + if (Length > 1) { + if (!CompareMem (Buffer, (UINT8 *) Buffer + 1, Length - 1)) { + return FALSE; + } + } + + return TRUE; +} + +VOID +CutPrefix ( + IN CHAR16 *Str, + IN UINTN Count + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Str - TODO: add argument description + Count - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + CHAR16 *Pointer; + + if (StrLen (Str) < Count) { + ASSERT (0); + } + + for (Pointer = Str; *(Pointer + Count); Pointer++) { + *Pointer = *(Pointer + Count); + } + + *Pointer = *(Pointer + Count); +} + + + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Check to see if the driver supports a given controller. + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - EFI handle of the controller to test. + + RemainingDevicePath - Pointer to remaining portion of a device path. + +Returns: + + EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver + specified by This. + + EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by + the driver specified by This. + + EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by + a different driver or an application that requires exclusive access. + + EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the + driver specified by This. + +--*/ +{ + EFI_STATUS Status; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure GUID is for a File System handle. + // + Status = EFI_UNSUPPORTED; + if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtFileSystemGuid)) { + Status = EFI_SUCCESS; + } + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + Starts a device controller or a bus controller. + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - EFI handle of the controller to start. + + RemainingDevicePath - Pointer to remaining portion of a device path. + +Returns: + + EFI_SUCCESS - The device or bus controller has been started. + + EFI_DEVICE_ERROR - The device could not be started due to a device failure. + + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +{ + EFI_STATUS Status; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + + Private = NULL; + + // + // Open the IO Abstraction(s) needed + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Validate GUID + // + if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtFileSystemGuid)) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE), + &Private + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + Private->Signature = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE; + Private->WinNtThunk = WinNtIo->WinNtThunk; + + Private->FilePath = WinNtIo->EnvString; + + Private->VolumeLabel = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (L"EFI_EMULATED"), + &Private->VolumeLabel + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (Private->VolumeLabel, L"EFI_EMULATED"); + + Private->SimpleFileSystem.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION; + Private->SimpleFileSystem.OpenVolume = WinNtSimpleFileSystemOpenVolume; + + Private->WinNtThunk->SetErrorMode (SEM_FAILCRITICALERRORS); + + Private->ControllerNameTable = NULL; + + AddUnicodeString ( + "eng", + gWinNtSimpleFileSystemComponentName.SupportedLanguages, + &Private->ControllerNameTable, + WinNtIo->EnvString + ); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + &Private->SimpleFileSystem, + NULL + ); + +Done: + if (EFI_ERROR (Status)) { + + if (Private != NULL) { + + FreeUnicodeStringTable (Private->ControllerNameTable); + + gBS->FreePool (Private); + } + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - A handle to the device to be stopped. + + NumberOfChildren - The number of child device handles in ChildHandleBuffer. + + ChildHandleBuffer - An array of child device handles to be freed. + +Returns: + + EFI_SUCCESS - The device has been stopped. + + EFI_DEVICE_ERROR - The device could not be stopped due to a device failure. + +--*/ +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_STATUS Status; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; + WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + &SimpleFileSystem, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem); + + // + // Uninstall the Simple File System Protocol from ControllerHandle + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + ControllerHandle, + &gEfiSimpleFileSystemProtocolGuid, + &Private->SimpleFileSystem, + NULL + ); + if (!EFI_ERROR (Status)) { + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + } + + if (!EFI_ERROR (Status)) { + // + // Free our instance data + // + FreeUnicodeStringTable (Private->ControllerNameTable); + + gBS->FreePool (Private); + } + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemOpenVolume ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE **Root + ) +/*++ + +Routine Description: + + Open the root directory on a volume. + +Arguments: + + This - A pointer to the volume to open. + + Root - A pointer to storage for the returned opened file handle of the root directory. + +Returns: + + EFI_SUCCESS - The volume was opened. + + EFI_UNSUPPORTED - The volume does not support the requested file system type. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_ACCESS_DENIED - The service denied access to the file. + + EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources. + + EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private; + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + + if (This == NULL || Root == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This); + + PrivateFile = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (WIN_NT_EFI_FILE_PRIVATE), + &PrivateFile + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + PrivateFile->FileName = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (Private->FilePath), + &PrivateFile->FileName + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + PrivateFile->FilePath = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (Private->FilePath), + &PrivateFile->FilePath + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (PrivateFile->FilePath, Private->FilePath); + StrCpy (PrivateFile->FileName, PrivateFile->FilePath); + PrivateFile->Signature = WIN_NT_EFI_FILE_PRIVATE_SIGNATURE; + PrivateFile->WinNtThunk = Private->WinNtThunk; + PrivateFile->SimpleFileSystem = This; + PrivateFile->IsRootDirectory = TRUE; + PrivateFile->IsDirectoryPath = TRUE; + PrivateFile->IsOpenedByRead = TRUE; + PrivateFile->EfiFile.Revision = EFI_FILE_HANDLE_REVISION; + PrivateFile->EfiFile.Open = WinNtSimpleFileSystemOpen; + PrivateFile->EfiFile.Close = WinNtSimpleFileSystemClose; + PrivateFile->EfiFile.Delete = WinNtSimpleFileSystemDelete; + PrivateFile->EfiFile.Read = WinNtSimpleFileSystemRead; + PrivateFile->EfiFile.Write = WinNtSimpleFileSystemWrite; + PrivateFile->EfiFile.GetPosition = WinNtSimpleFileSystemGetPosition; + PrivateFile->EfiFile.SetPosition = WinNtSimpleFileSystemSetPosition; + PrivateFile->EfiFile.GetInfo = WinNtSimpleFileSystemGetInfo; + PrivateFile->EfiFile.SetInfo = WinNtSimpleFileSystemSetInfo; + PrivateFile->EfiFile.Flush = WinNtSimpleFileSystemFlush; + PrivateFile->LHandle = INVALID_HANDLE_VALUE; + PrivateFile->DirHandle = INVALID_HANDLE_VALUE; + PrivateFile->IsValidFindBuf = FALSE; + + *Root = &PrivateFile->EfiFile; + + Status = EFI_SUCCESS; + +Done: + if (EFI_ERROR (Status)) { + if (PrivateFile) { + if (PrivateFile->FileName) { + gBS->FreePool (PrivateFile->FileName); + } + + if (PrivateFile->FilePath) { + gBS->FreePool (PrivateFile->FilePath); + } + + gBS->FreePool (PrivateFile); + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemOpen ( + IN EFI_FILE *This, + OUT EFI_FILE **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + Open a file relative to the source file location. + +Arguments: + + This - A pointer to the source file location. + + NewHandle - Pointer to storage for the new file handle. + + FileName - Pointer to the file name to be opened. + + OpenMode - File open mode information. + + Attributes - File creation attributes. + +Returns: + + EFI_SUCCESS - The file was opened. + + EFI_NOT_FOUND - The file could not be found in the volume. + + EFI_NO_MEDIA - The device has no media. + + EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_WRITE_PROTECTED - The volume or file is write protected. + + EFI_ACCESS_DENIED - The service denied access to the file. + + EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file. + + EFI_VOLUME_FULL - There is not enough space left to create the new file. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_FILE *Root; + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + WIN_NT_EFI_FILE_PRIVATE *NewPrivateFile; + WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot; + EFI_STATUS Status; + CHAR16 *RealFileName; + CHAR16 *TempFileName; + CHAR16 *ParseFileName; + CHAR16 *GuardPointer; + CHAR16 TempChar; + DWORD LastError; + UINTN Count; + BOOLEAN TrailingDash; + BOOLEAN LoopFinish; + UINTN InfoSize; + EFI_FILE_INFO *Info; + + TrailingDash = FALSE; + + // + // Check for obvious invalid parameters. + // + if (This == NULL || NewHandle == NULL || FileName == NULL) { + return EFI_INVALID_PARAMETER; + } + + switch (OpenMode) { + case EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE: + if (Attributes &~EFI_FILE_VALID_ATTR) { + return EFI_INVALID_PARAMETER; + } + + if (Attributes & EFI_FILE_READ_ONLY) { + return EFI_INVALID_PARAMETER; + } + + // + // fall through + // + case EFI_FILE_MODE_READ: + case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE: + break; + + default: + return EFI_INVALID_PARAMETER; + } + + // + // + // + PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem); + NewPrivateFile = NULL; + + // + // BUGBUG: assume an open of root + // if current location, return current data + // + if (StrCmp (FileName, L"\\") == 0 || (StrCmp (FileName, L".") == 0 && PrivateFile->IsRootDirectory)) { + // + // BUGBUG: assume an open root + // +OpenRoot: + Status = WinNtSimpleFileSystemOpenVolume (PrivateFile->SimpleFileSystem, &Root); + NewPrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root); + goto Done; + } + + if (FileName[StrLen (FileName) - 1] == L'\\') { + TrailingDash = TRUE; + FileName[StrLen (FileName) - 1] = 0; + } + + // + // Attempt to open the file + // + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (WIN_NT_EFI_FILE_PRIVATE), + &NewPrivateFile + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + CopyMem (NewPrivateFile, PrivateFile, sizeof (WIN_NT_EFI_FILE_PRIVATE)); + + NewPrivateFile->FilePath = NULL; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (PrivateFile->FileName), + &NewPrivateFile->FilePath + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + if (PrivateFile->IsDirectoryPath) { + StrCpy (NewPrivateFile->FilePath, PrivateFile->FileName); + } else { + StrCpy (NewPrivateFile->FilePath, PrivateFile->FilePath); + } + + NewPrivateFile->FileName = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (NewPrivateFile->FilePath) + StrSize (L"\\") + StrSize (FileName), + &NewPrivateFile->FileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + if (*FileName == L'\\') { + StrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath); + StrCat (NewPrivateFile->FileName, L"\\"); + StrCat (NewPrivateFile->FileName, FileName + 1); + } else { + StrCpy (NewPrivateFile->FileName, NewPrivateFile->FilePath); + StrCat (NewPrivateFile->FileName, L"\\"); + StrCat (NewPrivateFile->FileName, FileName); + } + + // + // Get rid of . and .., except leading . or .. + // + + // + // GuardPointer protect simplefilesystem root path not be destroyed + // + GuardPointer = NewPrivateFile->FileName + StrLen (PrivateRoot->FilePath); + + LoopFinish = FALSE; + + while (!LoopFinish) { + + LoopFinish = TRUE; + + for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) { + if (*ParseFileName == L'.' && + (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == L'\\') && + *(ParseFileName - 1) == L'\\' + ) { + + // + // cut \. + // + CutPrefix (ParseFileName - 1, 2); + LoopFinish = FALSE; + break; + } + + if (*ParseFileName == L'.' && + *(ParseFileName + 1) == L'.' && + (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == L'\\') && + *(ParseFileName - 1) == L'\\' + ) { + + ParseFileName--; + Count = 3; + + while (ParseFileName != GuardPointer) { + ParseFileName--; + Count++; + if (*ParseFileName == L'\\') { + break; + } + } + + // + // cut \.. and its left directory + // + CutPrefix (ParseFileName, Count); + LoopFinish = FALSE; + break; + } + } + } + + if (StrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) { + NewPrivateFile->IsRootDirectory = TRUE; + gBS->FreePool (NewPrivateFile->FilePath); + gBS->FreePool (NewPrivateFile->FileName); + gBS->FreePool (NewPrivateFile); + goto OpenRoot; + } + + RealFileName = NewPrivateFile->FileName; + while (EfiStrChr (RealFileName, L'\\') != NULL) { + RealFileName = EfiStrChr (RealFileName, L'\\') + 1; + } + + TempChar = *(RealFileName - 1); + *(RealFileName - 1) = 0; + + gBS->FreePool (NewPrivateFile->FilePath); + NewPrivateFile->FilePath = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (NewPrivateFile->FileName), + &NewPrivateFile->FilePath + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (NewPrivateFile->FilePath, NewPrivateFile->FileName); + + *(RealFileName - 1) = TempChar; + + NewPrivateFile->IsRootDirectory = FALSE; + + // + // Test whether file or directory + // + if (OpenMode & EFI_FILE_MODE_CREATE) { + if (Attributes & EFI_FILE_DIRECTORY) { + NewPrivateFile->IsDirectoryPath = TRUE; + } else { + NewPrivateFile->IsDirectoryPath = FALSE; + } + } else { + NewPrivateFile->LHandle = INVALID_HANDLE_VALUE; + NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile ( + NewPrivateFile->FileName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + + if (NewPrivateFile->LHandle != INVALID_HANDLE_VALUE) { + NewPrivateFile->IsDirectoryPath = FALSE; + NewPrivateFile->WinNtThunk->CloseHandle (NewPrivateFile->LHandle); + } else { + NewPrivateFile->IsDirectoryPath = TRUE; + } + + NewPrivateFile->LHandle = INVALID_HANDLE_VALUE; + } + + if (OpenMode & EFI_FILE_MODE_WRITE) { + NewPrivateFile->IsOpenedByRead = FALSE; + } else { + NewPrivateFile->IsOpenedByRead = TRUE; + } + + Status = EFI_SUCCESS; + + // + // deal with directory + // + if (NewPrivateFile->IsDirectoryPath) { + + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (NewPrivateFile->FileName) + StrSize (L"\\*"), + &TempFileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (TempFileName, NewPrivateFile->FileName); + + if ((OpenMode & EFI_FILE_MODE_CREATE)) { + // + // Create a directory + // + if (!NewPrivateFile->WinNtThunk->CreateDirectory (TempFileName, NULL)) { + + LastError = PrivateFile->WinNtThunk->GetLastError (); + if (LastError != ERROR_ALREADY_EXISTS) { + gBS->FreePool (TempFileName); + Status = EFI_ACCESS_DENIED; + goto Done; + } + } + } + + NewPrivateFile->DirHandle = NewPrivateFile->WinNtThunk->CreateFile ( + TempFileName, + NewPrivateFile->IsOpenedByRead ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE), + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); + + if (NewPrivateFile->DirHandle == INVALID_HANDLE_VALUE) { + + NewPrivateFile->DirHandle = NewPrivateFile->WinNtThunk->CreateFile ( + TempFileName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); + + if (NewPrivateFile->DirHandle != INVALID_HANDLE_VALUE) { + NewPrivateFile->WinNtThunk->CloseHandle (NewPrivateFile->DirHandle); + NewPrivateFile->DirHandle = INVALID_HANDLE_VALUE; + Status = EFI_ACCESS_DENIED; + } else { + Status = EFI_NOT_FOUND; + } + + goto Done; + } + + // + // Find the first file under it + // + StrCat (TempFileName, L"\\*"); + NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->FindFirstFile (TempFileName, &NewPrivateFile->FindBuf); + + if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) { + NewPrivateFile->IsValidFindBuf = FALSE; + } else { + NewPrivateFile->IsValidFindBuf = TRUE; + } + } else { + // + // deal with file + // + if (!NewPrivateFile->IsOpenedByRead) { + NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile ( + NewPrivateFile->FileName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + (OpenMode & EFI_FILE_MODE_CREATE) ? OPEN_ALWAYS : OPEN_EXISTING, + 0, + NULL + ); + + if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) { + NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile ( + NewPrivateFile->FileName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + + if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) { + Status = EFI_NOT_FOUND; + } else { + Status = EFI_ACCESS_DENIED; + NewPrivateFile->WinNtThunk->CloseHandle (NewPrivateFile->LHandle); + NewPrivateFile->LHandle = INVALID_HANDLE_VALUE; + } + } + } else { + NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile ( + NewPrivateFile->FileName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + + if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) { + Status = EFI_NOT_FOUND; + } + } + } + + if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) { + // + // Set the attribute + // + InfoSize = 0; + Info = NULL; + + Status = WinNtSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info); + + if (Status != EFI_BUFFER_TOO_SMALL) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + InfoSize, + &Info + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = WinNtSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info); + + if (EFI_ERROR (Status)) { + goto Done; + } + + Info->Attribute = Attributes; + + WinNtSimpleFileSystemSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info); + } + +Done: ; + if (TrailingDash) { + FileName[StrLen (FileName) + 1] = 0; + FileName[StrLen (FileName)] = L'\\'; + } + + if (EFI_ERROR (Status)) { + if (NewPrivateFile) { + if (NewPrivateFile->FileName) { + gBS->FreePool (NewPrivateFile->FileName); + } + + if (NewPrivateFile->FilePath) { + gBS->FreePool (NewPrivateFile->FilePath); + } + + gBS->FreePool (NewPrivateFile); + } + } else { + *NewHandle = &NewPrivateFile->EfiFile; + } + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemClose ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Close the specified file handle. + +Arguments: + + This - Pointer to a returned opened file handle. + +Returns: + + EFI_SUCCESS - The file handle has been closed. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) { + if (PrivateFile->IsDirectoryPath) { + PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle); + } else { + PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle); + } + + PrivateFile->LHandle = INVALID_HANDLE_VALUE; + } + + if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) { + PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle); + PrivateFile->DirHandle = INVALID_HANDLE_VALUE; + } + + if (PrivateFile->FileName) { + gBS->FreePool (PrivateFile->FileName); + } + + gBS->FreePool (PrivateFile); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemDelete ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Close and delete a file. + +Arguments: + + This - Pointer to a returned opened file handle. + +Returns: + + EFI_SUCCESS - The file handle was closed and deleted. + + EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + Status = EFI_WARN_DELETE_FAILURE; + + if (PrivateFile->IsDirectoryPath) { + if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) { + PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle); + } + + if (PrivateFile->DirHandle != INVALID_HANDLE_VALUE) { + PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle); + PrivateFile->DirHandle = INVALID_HANDLE_VALUE; + } + + if (PrivateFile->WinNtThunk->RemoveDirectory (PrivateFile->FileName)) { + Status = EFI_SUCCESS; + } + } else { + PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle); + PrivateFile->LHandle = INVALID_HANDLE_VALUE; + + if (!PrivateFile->IsOpenedByRead) { + if (PrivateFile->WinNtThunk->DeleteFile (PrivateFile->FileName)) { + Status = EFI_SUCCESS; + } + } + } + + gBS->FreePool (PrivateFile->FileName); + gBS->FreePool (PrivateFile); + + return Status; +} + +STATIC +VOID +WinNtSystemTimeToEfiTime ( + IN SYSTEMTIME *SystemTime, + IN TIME_ZONE_INFORMATION *TimeZone, + OUT EFI_TIME *Time + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SystemTime - TODO: add argument description + TimeZone - TODO: add argument description + Time - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + Time->Year = (UINT16) SystemTime->wYear; + Time->Month = (UINT8) SystemTime->wMonth; + Time->Day = (UINT8) SystemTime->wDay; + Time->Hour = (UINT8) SystemTime->wHour; + Time->Minute = (UINT8) SystemTime->wMinute; + Time->Second = (UINT8) SystemTime->wSecond; + Time->Nanosecond = (UINT32) SystemTime->wMilliseconds * 1000000; + Time->TimeZone = (INT16) TimeZone->Bias; + + if (TimeZone->StandardDate.wMonth) { + Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT; + } +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemRead ( + IN EFI_FILE *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Read data from a file. + +Arguments: + + This - Pointer to a returned open file handle. + + BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer. + + Buffer - Pointer to the first byte of the read Buffer. + +Returns: + + EFI_SUCCESS - The data was read. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry. + *BufferSize has been updated with the size needed to complete the request. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + EFI_STATUS Status; + UINTN Size; + UINTN NameSize; + UINTN ResultSize; + UINTN Index; + SYSTEMTIME SystemTime; + EFI_FILE_INFO *Info; + WCHAR *pw; + TIME_ZONE_INFORMATION TimeZone; + EFI_FILE_INFO *FileInfo; + UINT64 Pos; + UINT64 FileSize; + UINTN FileInfoSize; + + if (This == NULL || BufferSize == NULL || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) { + return EFI_DEVICE_ERROR; + } + + if (!PrivateFile->IsDirectoryPath) { + + if (This->GetPosition (This, &Pos) != EFI_SUCCESS) { + return EFI_DEVICE_ERROR; + } + + FileInfoSize = SIZE_OF_EFI_FILE_SYSTEM_INFO; + gBS->AllocatePool ( + EfiBootServicesData, + FileInfoSize, + &FileInfo + ); + + Status = This->GetInfo ( + This, + &gEfiFileInfoGuid, + &FileInfoSize, + FileInfo + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + gBS->FreePool (FileInfo); + gBS->AllocatePool ( + EfiBootServicesData, + FileInfoSize, + &FileInfo + ); + Status = This->GetInfo ( + This, + &gEfiFileInfoGuid, + &FileInfoSize, + FileInfo + ); + } + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + FileSize = FileInfo->FileSize; + + gBS->FreePool (FileInfo); + + if (Pos >= FileSize) { + *BufferSize = 0; + if (Pos == FileSize) { + return EFI_SUCCESS; + } else { + return EFI_DEVICE_ERROR; + } + } + + return PrivateFile->WinNtThunk->ReadFile ( + PrivateFile->LHandle, + Buffer, + *BufferSize, + BufferSize, + NULL + ) ? EFI_SUCCESS : EFI_DEVICE_ERROR; + } + + // + // Read on a directory. Perform a find next + // + if (!PrivateFile->IsValidFindBuf) { + *BufferSize = 0; + return EFI_SUCCESS; + } + + Size = SIZE_OF_EFI_FILE_INFO; + + NameSize = StrSize (PrivateFile->FindBuf.cFileName); + + ResultSize = Size + NameSize; + + Status = EFI_BUFFER_TOO_SMALL; + + if (*BufferSize >= ResultSize) { + Status = EFI_SUCCESS; + + Info = Buffer; + ZeroMem (Info, ResultSize); + + Info->Size = ResultSize; + + PrivateFile->WinNtThunk->GetTimeZoneInformation (&TimeZone); + + PrivateFile->WinNtThunk->FileTimeToLocalFileTime ( + &PrivateFile->FindBuf.ftCreationTime, + &PrivateFile->FindBuf.ftCreationTime + ); + + PrivateFile->WinNtThunk->FileTimeToSystemTime (&PrivateFile->FindBuf.ftCreationTime, &SystemTime); + + WinNtSystemTimeToEfiTime (&SystemTime, &TimeZone, &Info->CreateTime); + + PrivateFile->WinNtThunk->FileTimeToLocalFileTime ( + &PrivateFile->FindBuf.ftLastWriteTime, + &PrivateFile->FindBuf.ftLastWriteTime + ); + + PrivateFile->WinNtThunk->FileTimeToSystemTime (&PrivateFile->FindBuf.ftLastWriteTime, &SystemTime); + + WinNtSystemTimeToEfiTime (&SystemTime, &TimeZone, &Info->ModificationTime); + + Info->FileSize = PrivateFile->FindBuf.nFileSizeLow; + + Info->PhysicalSize = PrivateFile->FindBuf.nFileSizeLow; + + if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) { + Info->Attribute |= EFI_FILE_ARCHIVE; + } + + if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) { + Info->Attribute |= EFI_FILE_HIDDEN; + } + + if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) { + Info->Attribute |= EFI_FILE_SYSTEM; + } + + if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + Info->Attribute |= EFI_FILE_READ_ONLY; + } + + if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + Info->Attribute |= EFI_FILE_DIRECTORY; + } + + NameSize = NameSize / sizeof (WCHAR); + + pw = (WCHAR *) (((CHAR8 *) Buffer) + Size); + + for (Index = 0; Index < NameSize; Index++) { + pw[Index] = PrivateFile->FindBuf.cFileName[Index]; + } + + if (PrivateFile->WinNtThunk->FindNextFile (PrivateFile->LHandle, &PrivateFile->FindBuf)) { + PrivateFile->IsValidFindBuf = TRUE; + } else { + PrivateFile->IsValidFindBuf = FALSE; + } + } + + *BufferSize = ResultSize; + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemWrite ( + IN EFI_FILE *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Write data to a file. + +Arguments: + + This - Pointer to an opened file handle. + + BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes + of data written to the file. + + Buffer - Pointer to the first by of data in the buffer to write to the file. + +Returns: + + EFI_SUCCESS - The data was written to the file. + + EFI_UNSUPPORTED - Writes to an open directory are not supported. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + + if (This == NULL || BufferSize == NULL || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) { + return EFI_DEVICE_ERROR; + } + + if (PrivateFile->IsDirectoryPath) { + return EFI_UNSUPPORTED; + } + + if (PrivateFile->IsOpenedByRead) { + return EFI_ACCESS_DENIED; + } + + return PrivateFile->WinNtThunk->WriteFile ( + PrivateFile->LHandle, + Buffer, + *BufferSize, + BufferSize, + NULL + ) ? EFI_SUCCESS : EFI_DEVICE_ERROR; + + // + // bugbug: need to access windows error reporting + // +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemSetPosition ( + IN EFI_FILE *This, + IN UINT64 Position + ) +/*++ + +Routine Description: + + Set a file's current position. + +Arguments: + + This - Pointer to an opened file handle. + + Position - The byte position from the start of the file to set. + +Returns: + + EFI_SUCCESS - The file position has been changed. + + EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + UINT32 PosLow; + UINT32 PosHigh; + CHAR16 *FileName; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->IsDirectoryPath) { + if (Position != 0) { + return EFI_UNSUPPORTED; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (PrivateFile->FileName) + StrSize (L"\\*"), + &FileName + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + StrCpy (FileName, PrivateFile->FileName); + StrCat (FileName, L"\\*"); + + if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) { + PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle); + } + + PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (FileName, &PrivateFile->FindBuf); + + if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) { + PrivateFile->IsValidFindBuf = FALSE; + } else { + PrivateFile->IsValidFindBuf = TRUE; + } + + gBS->FreePool (FileName); + + Status = (PrivateFile->LHandle == INVALID_HANDLE_VALUE) ? EFI_DEVICE_ERROR : EFI_SUCCESS; + } else { + if (Position == (UINT64) -1) { + PosLow = PrivateFile->WinNtThunk->SetFilePointer (PrivateFile->LHandle, (ULONG) 0, NULL, FILE_END); + } else { + PosHigh = (UINT32) RShiftU64 (Position, 32); + + PosLow = PrivateFile->WinNtThunk->SetFilePointer (PrivateFile->LHandle, (ULONG) Position, &PosHigh, FILE_BEGIN); + } + + Status = (PosLow == 0xFFFFFFFF) ? EFI_DEVICE_ERROR : EFI_SUCCESS; + } + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemGetPosition ( + IN EFI_FILE *This, + OUT UINT64 *Position + ) +/*++ + +Routine Description: + + Get a file's current position. + +Arguments: + + This - Pointer to an opened file handle. + + Position - Pointer to storage for the current position. + +Returns: + + EFI_SUCCESS - The file position has been reported. + + EFI_UNSUPPORTED - Not valid for directories. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + INT32 PositionHigh; + UINT64 PosHigh64; + + if (This == NULL || Position == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + PositionHigh = 0; + PosHigh64 = 0; + + if (PrivateFile->IsDirectoryPath) { + + return EFI_UNSUPPORTED; + + } else { + + PositionHigh = 0; + *Position = PrivateFile->WinNtThunk->SetFilePointer ( + PrivateFile->LHandle, + 0, + &PositionHigh, + FILE_CURRENT + ); + + Status = *Position == 0xffffffff ? EFI_DEVICE_ERROR : EFI_SUCCESS; + if (EFI_ERROR (Status)) { + goto Done; + } + + PosHigh64 = PositionHigh; + *Position += LShiftU64 (PosHigh64, 32); + } + +Done: + return Status; +} + +STATIC +EFI_STATUS +WinNtSimpleFileSystemFileInfo ( + IN WIN_NT_EFI_FILE_PRIVATE *PrivateFile, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PrivateFile - TODO: add argument description + BufferSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_STATUS Status; + UINTN Size; + UINTN NameSize; + UINTN ResultSize; + EFI_FILE_INFO *Info; + BY_HANDLE_FILE_INFORMATION FileInfo; + SYSTEMTIME SystemTime; + CHAR16 *RealFileName; + CHAR16 *TempPointer; + + Size = SIZE_OF_EFI_FILE_INFO; + NameSize = StrSize (PrivateFile->FileName); + ResultSize = Size + NameSize; + + Status = EFI_BUFFER_TOO_SMALL; + if (*BufferSize >= ResultSize) { + Status = EFI_SUCCESS; + + Info = Buffer; + ZeroMem (Info, ResultSize); + + Info->Size = ResultSize; + PrivateFile->WinNtThunk->GetFileInformationByHandle ( + PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle, + &FileInfo + ); + Info->FileSize = FileInfo.nFileSizeLow; + Info->PhysicalSize = Info->FileSize; + + PrivateFile->WinNtThunk->FileTimeToSystemTime (&FileInfo.ftCreationTime, &SystemTime); + Info->CreateTime.Year = SystemTime.wYear; + Info->CreateTime.Month = (UINT8) SystemTime.wMonth; + Info->CreateTime.Day = (UINT8) SystemTime.wDay; + Info->CreateTime.Hour = (UINT8) SystemTime.wHour; + Info->CreateTime.Minute = (UINT8) SystemTime.wMinute; + Info->CreateTime.Second = (UINT8) SystemTime.wSecond; + + PrivateFile->WinNtThunk->FileTimeToSystemTime (&FileInfo.ftLastAccessTime, &SystemTime); + Info->LastAccessTime.Year = SystemTime.wYear; + Info->LastAccessTime.Month = (UINT8) SystemTime.wMonth; + Info->LastAccessTime.Day = (UINT8) SystemTime.wDay; + Info->LastAccessTime.Hour = (UINT8) SystemTime.wHour; + Info->LastAccessTime.Minute = (UINT8) SystemTime.wMinute; + Info->LastAccessTime.Second = (UINT8) SystemTime.wSecond; + + PrivateFile->WinNtThunk->FileTimeToSystemTime (&FileInfo.ftLastWriteTime, &SystemTime); + Info->ModificationTime.Year = SystemTime.wYear; + Info->ModificationTime.Month = (UINT8) SystemTime.wMonth; + Info->ModificationTime.Day = (UINT8) SystemTime.wDay; + Info->ModificationTime.Hour = (UINT8) SystemTime.wHour; + Info->ModificationTime.Minute = (UINT8) SystemTime.wMinute; + Info->ModificationTime.Second = (UINT8) SystemTime.wSecond; + + if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) { + Info->Attribute |= EFI_FILE_ARCHIVE; + } + + if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) { + Info->Attribute |= EFI_FILE_HIDDEN; + } + + if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + Info->Attribute |= EFI_FILE_READ_ONLY; + } + + if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) { + Info->Attribute |= EFI_FILE_SYSTEM; + } + + if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { + Info->Attribute |= EFI_FILE_DIRECTORY; + } + + if (PrivateFile->IsDirectoryPath) { + Info->Attribute |= EFI_FILE_DIRECTORY; + } + + RealFileName = PrivateFile->FileName; + TempPointer = RealFileName; + + while (*TempPointer) { + if (*TempPointer == '\\') { + RealFileName = TempPointer + 1; + } + + TempPointer++; + } + + if (PrivateFile->IsRootDirectory) { + *((CHAR8 *) Buffer + Size) = 0; + } else { + CopyMem ((CHAR8 *) Buffer + Size, RealFileName, NameSize); + } + } + + *BufferSize = ResultSize; + return Status; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemGetInfo ( + IN EFI_FILE *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Return information about a file or volume. + +Arguments: + + This - Pointer to an opened file handle. + + InformationType - GUID describing the type of information to be returned. + + BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the + information buffer. + + Buffer - Pointer to the first byte of the information buffer. + +Returns: + + EFI_SUCCESS - The requested information has been written into the buffer. + + EFI_UNSUPPORTED - The InformationType is not known. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has + been updated with the size needed to complete the requested operation. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + EFI_STATUS Status; + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer; + UINT32 SectorsPerCluster; + UINT32 BytesPerSector; + UINT32 FreeClusters; + UINT32 TotalClusters; + UINT32 BytesPerCluster; + CHAR16 *DriveName; + BOOLEAN DriveNameFound; + BOOL NtStatus; + UINTN Index; + WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot; + + if (This == NULL || InformationType == NULL || BufferSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem); + + Status = EFI_UNSUPPORTED; + + if (CompareGuid (InformationType, &gEfiFileInfoGuid)) { + Status = WinNtSimpleFileSystemFileInfo (PrivateFile, BufferSize, Buffer); + } + + if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { + if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) { + *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel); + return EFI_BUFFER_TOO_SMALL; + } + + FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer; + FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel); + FileSystemInfoBuffer->ReadOnly = FALSE; + + // + // Try to get the drive name + // + DriveName = NULL; + DriveNameFound = FALSE; + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (PrivateFile->FilePath) + 1, + &DriveName + ); + if (EFI_ERROR (Status)) { + return Status; + } + + StrCpy (DriveName, PrivateFile->FilePath); + for (Index = 0; DriveName[Index] != 0 && DriveName[Index] != ':'; Index++) { + ; + } + + if (DriveName[Index] == ':') { + DriveName[Index + 1] = '\\'; + DriveName[Index + 2] = 0; + DriveNameFound = TRUE; + } else if (DriveName[0] == '\\' && DriveName[1] == '\\') { + for (Index = 2; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) { + ; + } + + if (DriveName[Index] == '\\') { + DriveNameFound = TRUE; + for (Index++; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) { + ; + } + + DriveName[Index] = '\\'; + DriveName[Index + 1] = 0; + } + } + + // + // Try GetDiskFreeSpace first + // + NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpace ( + DriveNameFound ? DriveName : NULL, + &SectorsPerCluster, + &BytesPerSector, + &FreeClusters, + &TotalClusters + ); + if (DriveName) { + gBS->FreePool (DriveName); + } + + if (NtStatus) { + // + // Succeeded + // + BytesPerCluster = BytesPerSector * SectorsPerCluster; + FileSystemInfoBuffer->VolumeSize = MultU64x32 (TotalClusters, BytesPerCluster); + FileSystemInfoBuffer->FreeSpace = MultU64x32 (FreeClusters, BytesPerCluster); + FileSystemInfoBuffer->BlockSize = BytesPerCluster; + + } else { + // + // try GetDiskFreeSpaceEx then + // + FileSystemInfoBuffer->BlockSize = 0; + NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpaceEx ( + PrivateFile->FilePath, + (PULARGE_INTEGER) (&FileSystemInfoBuffer->FreeSpace), + (PULARGE_INTEGER) (&FileSystemInfoBuffer->VolumeSize), + NULL + ); + if (!NtStatus) { + return EFI_DEVICE_ERROR; + } + } + + StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel); + *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel); + Status = EFI_SUCCESS; + } + + if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { + if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) { + *BufferSize = StrSize (PrivateRoot->VolumeLabel); + return EFI_BUFFER_TOO_SMALL; + } + + StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel); + *BufferSize = StrSize (PrivateRoot->VolumeLabel); + Status = EFI_SUCCESS; + } + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemSetInfo ( + IN EFI_FILE *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Set information about a file or volume. + +Arguments: + + This - Pointer to an opened file handle. + + InformationType - GUID identifying the type of information to set. + + BufferSize - Number of bytes of data in the information buffer. + + Buffer - Pointer to the first byte of data in the information buffer. + +Returns: + + EFI_SUCCESS - The file or volume information has been updated. + + EFI_UNSUPPORTED - The information identifier is not recognised. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + + EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot; + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + EFI_FILE_INFO *OldFileInfo; + EFI_FILE_INFO *NewFileInfo; + EFI_STATUS Status; + UINTN OldInfoSize; + INTN NtStatus; + UINT32 NewAttr; + UINT32 OldAttr; + CHAR16 *OldFileName; + CHAR16 *NewFileName; + CHAR16 *TempFileName; + CHAR16 *CharPointer; + BOOLEAN AttrChangeFlag; + BOOLEAN NameChangeFlag; + BOOLEAN SizeChangeFlag; + BOOLEAN TimeChangeFlag; + UINT64 CurPos; + SYSTEMTIME NewCreationSystemTime; + SYSTEMTIME NewLastAccessSystemTime; + SYSTEMTIME NewLastWriteSystemTime; + FILETIME NewCreationFileTime; + FILETIME NewLastAccessFileTime; + FILETIME NewLastWriteFileTime; + WIN32_FIND_DATA FindBuf; + EFI_FILE_SYSTEM_INFO *NewFileSystemInfo; + + // + // Check for invalid parameters. + // + if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialise locals. + // + PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem); + + Status = EFI_UNSUPPORTED; + OldFileInfo = NewFileInfo = NULL; + OldFileName = NewFileName = NULL; + AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE; + + // + // Set file system information. + // + if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) { + if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) { + return EFI_BAD_BUFFER_SIZE; + } + + NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer; + + gBS->FreePool (PrivateRoot->VolumeLabel); + + PrivateRoot->VolumeLabel = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (NewFileSystemInfo->VolumeLabel), + &PrivateRoot->VolumeLabel + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel); + + return EFI_SUCCESS; + } + + // + // Set volume label information. + // + if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) { + if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) { + return EFI_BAD_BUFFER_SIZE; + } + + StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer); + + return EFI_SUCCESS; + } + + if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) { + return EFI_UNSUPPORTED; + } + + if (BufferSize < SIZE_OF_EFI_FILE_INFO) { + return EFI_BAD_BUFFER_SIZE; + } + + // + // Set file/directory information. + // + + // + // Check for invalid set file information parameters. + // + NewFileInfo = (EFI_FILE_INFO *) Buffer; + + if (NewFileInfo->Size <= sizeof (EFI_FILE_INFO) || + (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) || + (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF) + ) { + return EFI_INVALID_PARAMETER; + } + + // + // bugbug: - This is not safe. We need something like EfiStrMaxSize() + // that would have an additional parameter that would be the size + // of the string array just in case there are no NULL characters in + // the string array. + // + // + // Get current file information so we can determine what kind + // of change request this is. + // + OldInfoSize = 0; + Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, NULL); + + if (Status != EFI_BUFFER_TOO_SMALL) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + Status = gBS->AllocatePool (EfiBootServicesData, OldInfoSize, &OldFileInfo); + + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, OldFileInfo); + + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (PrivateFile->FileName), + &OldFileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (OldFileName, PrivateFile->FileName); + + // + // Make full pathname from new filename and rootpath. + // + if (NewFileInfo->FileName[0] == '\\') { + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (PrivateRoot->FilePath) + StrSize (L"\\") + StrSize (NewFileInfo->FileName), + &NewFileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (NewFileName, PrivateRoot->FilePath); + StrCat (NewFileName, L"\\"); + StrCat (NewFileName, NewFileInfo->FileName + 1); + } else { + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (PrivateFile->FilePath) + StrSize (L"\\") + StrSize (NewFileInfo->FileName), + &NewFileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (NewFileName, PrivateFile->FilePath); + StrCat (NewFileName, L"\\"); + StrCat (NewFileName, NewFileInfo->FileName); + } + + // + // Is there an attribute change request? + // + if (NewFileInfo->Attribute != OldFileInfo->Attribute) { + if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) { + Status = EFI_INVALID_PARAMETER; + goto Done; + } + + AttrChangeFlag = TRUE; + } + + // + // Is there a name change request? + // bugbug: - Need EfiStrCaseCmp() + // + if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) { + NameChangeFlag = TRUE; + } + + // + // Is there a size change request? + // + if (NewFileInfo->FileSize != OldFileInfo->FileSize) { + SizeChangeFlag = TRUE; + } + + // + // Is there a time stamp change request? + // + if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) && + CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME)) + ) { + TimeChangeFlag = TRUE; + } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) && + CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME)) + ) { + TimeChangeFlag = TRUE; + } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) && + CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME)) + ) { + TimeChangeFlag = TRUE; + } + + // + // All done if there are no change requests being made. + // + if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) { + Status = EFI_SUCCESS; + goto Done; + } + + // + // Set file or directory information. + // + OldAttr = PrivateFile->WinNtThunk->GetFileAttributes (OldFileName); + + // + // Name change. + // + if (NameChangeFlag) { + // + // Close the handles first + // + if (PrivateFile->IsOpenedByRead) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) { + } + + if (*CharPointer != 0) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) { + if (PrivateFile->IsDirectoryPath) { + PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle); + } else { + PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle); + PrivateFile->LHandle = INVALID_HANDLE_VALUE; + } + } + + if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) { + PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle); + PrivateFile->DirHandle = INVALID_HANDLE_VALUE; + } + + NtStatus = PrivateFile->WinNtThunk->MoveFile (OldFileName, NewFileName); + + if (NtStatus) { + // + // modify file name + // + gBS->FreePool (PrivateFile->FileName); + + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (NewFileName), + &PrivateFile->FileName + ); + + if (EFI_ERROR (Status)) { + goto Done; + } + + StrCpy (PrivateFile->FileName, NewFileName); + + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (NewFileName) + StrSize (L"\\*"), + &TempFileName + ); + + StrCpy (TempFileName, NewFileName); + + if (!PrivateFile->IsDirectoryPath) { + PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile ( + TempFileName, + PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + + gBS->FreePool (TempFileName); + + // + // Flush buffers just in case + // + if (PrivateFile->WinNtThunk->FlushFileBuffers (PrivateFile->LHandle) == 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + } else { + PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile ( + TempFileName, + PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); + + StrCat (TempFileName, L"\\*"); + PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &FindBuf); + + gBS->FreePool (TempFileName); + } + } else { +Reopen: ; + Status = EFI_DEVICE_ERROR; + + NtStatus = PrivateFile->WinNtThunk->SetFileAttributes (OldFileName, OldAttr); + + if (!NtStatus) { + goto Done; + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + StrSize (OldFileName) + StrSize (L"\\*"), + &TempFileName + ); + + StrCpy (TempFileName, OldFileName); + + if (!PrivateFile->IsDirectoryPath) { + PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile ( + TempFileName, + PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + } else { + PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile ( + TempFileName, + PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS, + NULL + ); + + StrCat (TempFileName, L"\\*"); + PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &FindBuf); + } + + gBS->FreePool (TempFileName); + + goto Done; + + } + } + + // + // Size change + // + if (SizeChangeFlag) { + if (PrivateFile->IsDirectoryPath) { + Status = EFI_UNSUPPORTED; + goto Done; + } + + if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) { + Status = EFI_ACCESS_DENIED; + goto Done; + } + + Status = This->GetPosition (This, &CurPos); + if (EFI_ERROR (Status)) { + goto Done; + } + + Status = This->SetPosition (This, NewFileInfo->FileSize); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (PrivateFile->WinNtThunk->SetEndOfFile (PrivateFile->LHandle) == 0) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + Status = This->SetPosition (This, CurPos); + if (EFI_ERROR (Status)) { + goto Done; + } + } + + // + // Time change + // + if (TimeChangeFlag) { + + NewCreationSystemTime.wYear = NewFileInfo->CreateTime.Year; + NewCreationSystemTime.wMonth = NewFileInfo->CreateTime.Month; + NewCreationSystemTime.wDay = NewFileInfo->CreateTime.Day; + NewCreationSystemTime.wHour = NewFileInfo->CreateTime.Hour; + NewCreationSystemTime.wMinute = NewFileInfo->CreateTime.Minute; + NewCreationSystemTime.wSecond = NewFileInfo->CreateTime.Second; + NewCreationSystemTime.wMilliseconds = 0; + + if (!PrivateFile->WinNtThunk->SystemTimeToFileTime ( + &NewCreationSystemTime, + &NewCreationFileTime + )) { + goto Done; + } + + NewLastAccessSystemTime.wYear = NewFileInfo->LastAccessTime.Year; + NewLastAccessSystemTime.wMonth = NewFileInfo->LastAccessTime.Month; + NewLastAccessSystemTime.wDay = NewFileInfo->LastAccessTime.Day; + NewLastAccessSystemTime.wHour = NewFileInfo->LastAccessTime.Hour; + NewLastAccessSystemTime.wMinute = NewFileInfo->LastAccessTime.Minute; + NewLastAccessSystemTime.wSecond = NewFileInfo->LastAccessTime.Second; + NewLastAccessSystemTime.wMilliseconds = 0; + + if (!PrivateFile->WinNtThunk->SystemTimeToFileTime ( + &NewLastAccessSystemTime, + &NewLastAccessFileTime + )) { + goto Done; + } + + NewLastWriteSystemTime.wYear = NewFileInfo->ModificationTime.Year; + NewLastWriteSystemTime.wMonth = NewFileInfo->ModificationTime.Month; + NewLastWriteSystemTime.wDay = NewFileInfo->ModificationTime.Day; + NewLastWriteSystemTime.wHour = NewFileInfo->ModificationTime.Hour; + NewLastWriteSystemTime.wMinute = NewFileInfo->ModificationTime.Minute; + NewLastWriteSystemTime.wSecond = NewFileInfo->ModificationTime.Second; + NewLastWriteSystemTime.wMilliseconds = 0; + + if (!PrivateFile->WinNtThunk->SystemTimeToFileTime ( + &NewLastWriteSystemTime, + &NewLastWriteFileTime + )) { + goto Done; + } + + if (!PrivateFile->WinNtThunk->SetFileTime ( + PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle, + &NewCreationFileTime, + &NewLastAccessFileTime, + &NewLastWriteFileTime + )) { + Status = EFI_DEVICE_ERROR; + goto Done; + } + + } + + // + // No matter about AttrChangeFlag, Attribute must be set. + // Because operation before may cause attribute change. + // + NewAttr = OldAttr; + + if (NewFileInfo->Attribute & EFI_FILE_ARCHIVE) { + NewAttr |= FILE_ATTRIBUTE_ARCHIVE; + } else { + NewAttr &= ~FILE_ATTRIBUTE_ARCHIVE; + } + + if (NewFileInfo->Attribute & EFI_FILE_HIDDEN) { + NewAttr |= FILE_ATTRIBUTE_HIDDEN; + } else { + NewAttr &= ~FILE_ATTRIBUTE_HIDDEN; + } + + if (NewFileInfo->Attribute & EFI_FILE_SYSTEM) { + NewAttr |= FILE_ATTRIBUTE_SYSTEM; + } else { + NewAttr &= ~FILE_ATTRIBUTE_SYSTEM; + } + + if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) { + NewAttr |= FILE_ATTRIBUTE_READONLY; + } else { + NewAttr &= ~FILE_ATTRIBUTE_READONLY; + } + + NtStatus = PrivateFile->WinNtThunk->SetFileAttributes (NewFileName, NewAttr); + + if (!NtStatus) { + goto Reopen; + } + +Done: + if (OldFileInfo != NULL) { + gBS->FreePool (OldFileInfo); + } + + if (OldFileName != NULL) { + gBS->FreePool (OldFileName); + } + + if (NewFileName != NULL) { + gBS->FreePool (NewFileName); + } + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemFlush ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Flush all modified data to the media. + +Arguments: + + This - Pointer to an opened file handle. + +Returns: + + EFI_SUCCESS - The data has been flushed. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures have been corrupted. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + BY_HANDLE_FILE_INFORMATION FileInfo; + WIN_NT_EFI_FILE_PRIVATE *PrivateFile; + + if (This == NULL) { + return EFI_INVALID_PARAMETER; + } + + PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This); + + if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) { + return EFI_DEVICE_ERROR; + } + + if (PrivateFile->IsDirectoryPath) { + return EFI_SUCCESS; + } + + if (PrivateFile->IsOpenedByRead) { + return EFI_ACCESS_DENIED; + } + + PrivateFile->WinNtThunk->GetFileInformationByHandle (PrivateFile->LHandle, &FileInfo); + + if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) { + return EFI_ACCESS_DENIED; + } + + return PrivateFile->WinNtThunk->FlushFileBuffers (PrivateFile->LHandle) ? EFI_SUCCESS : EFI_DEVICE_ERROR; + + // + // bugbug: - Use Windows error reporting. + // +} + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.h b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.h new file mode 100644 index 0000000000..eeb373d7d5 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.h @@ -0,0 +1,587 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtSimpleFileSystem.h + +Abstract: + + Produce Simple File System abstractions for a directory on your PC using Win32 APIs. + The configuration of what devices to mount or emulate comes from NT + environment variables. The variables must be visible to the Microsoft* + Developer Studio for them to work. + + * Other names and brands may be claimed as the property of others. + +--*/ + +#ifndef _WIN_NT_SIMPLE_FILE_SYSTEM_H_ +#define _WIN_NT_SIMPLE_FILE_SYSTEM_H_ + + + +#define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE EFI_SIGNATURE_32 ('N', 'T', 'f', 's') + +typedef struct { + UINTN Signature; + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFileSystem; + CHAR16 *FilePath; + CHAR16 *VolumeLabel; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE; + +#define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE, \ + SimpleFileSystem, \ + WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE \ + ) + +#define WIN_NT_EFI_FILE_PRIVATE_SIGNATURE EFI_SIGNATURE_32 ('l', 'o', 'f', 's') + +typedef struct { + UINTN Signature; + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem; + EFI_FILE EfiFile; + HANDLE LHandle; + HANDLE DirHandle; + BOOLEAN IsRootDirectory; + BOOLEAN IsDirectoryPath; + BOOLEAN IsOpenedByRead; + CHAR16 *FilePath; + WCHAR *FileName; + BOOLEAN IsValidFindBuf; + WIN32_FIND_DATA FindBuf; +} WIN_NT_EFI_FILE_PRIVATE; + +#define WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + WIN_NT_EFI_FILE_PRIVATE, \ + EfiFile, \ + WIN_NT_EFI_FILE_PRIVATE_SIGNATURE \ + ) + +// +// Global Protocol Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gWinNtSimpleFileSystemDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gWinNtSimpleFileSystemComponentName; + +// +// Driver Binding protocol member functions +// +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +/*++ + +Routine Description: + + Check to see if the driver supports a given controller. + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - EFI handle of the controller to test. + + RemainingDevicePath - Pointer to remaining portion of a device path. + +Returns: + + EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver + specified by This. + + EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by + the driver specified by This. + + EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by + a different driver or an application that requires exclusive access. + + EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the + driver specified by This. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +/*++ + +Routine Description: + + Starts a device controller or a bus controller. + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - EFI handle of the controller to start. + + RemainingDevicePath - Pointer to remaining portion of a device path. + +Returns: + + EFI_SUCCESS - The device or bus controller has been started. + + EFI_DEVICE_ERROR - The device could not be started due to a device failure. + + EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL. + + ControllerHandle - A handle to the device to be stopped. + + NumberOfChildren - The number of child device handles in ChildHandleBuffer. + + ChildHandleBuffer - An array of child device handles to be freed. + +Returns: + + EFI_SUCCESS - The device has been stopped. + + EFI_DEVICE_ERROR - The device could not be stopped due to a device failure. + +--*/ +; + +// +// Simple File System protocol member functions +// +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemOpenVolume ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE **Root + ) +/*++ + +Routine Description: + + Open the root directory on a volume. + +Arguments: + + This - A pointer to the volume to open. + + Root - A pointer to storage for the returned opened file handle of the root directory. + +Returns: + + EFI_SUCCESS - The volume was opened. + + EFI_UNSUPPORTED - The volume does not support the requested file system type. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_ACCESS_DENIED - The service denied access to the file. + + EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources. + + EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemOpen ( + IN EFI_FILE *This, + OUT EFI_FILE **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + Open a file relative to the source file location. + +Arguments: + + This - A pointer to the source file location. + + NewHandle - Pointer to storage for the new file handle. + + FileName - Pointer to the file name to be opened. + + OpenMode - File open mode information. + + Attributes - File creation attributes. + +Returns: + + EFI_SUCCESS - The file was opened. + + EFI_NOT_FOUND - The file could not be found in the volume. + + EFI_NO_MEDIA - The device has no media. + + EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_WRITE_PROTECTED - The volume or file is write protected. + + EFI_ACCESS_DENIED - The service denied access to the file. + + EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file. + + EFI_VOLUME_FULL - There is not enough space left to create the new file. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemClose ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Close the specified file handle. + +Arguments: + + This - Pointer to a returned opened file handle. + +Returns: + + EFI_SUCCESS - The file handle has been closed. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemDelete ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Close and delete a file. + +Arguments: + + This - Pointer to a returned opened file handle. + +Returns: + + EFI_SUCCESS - The file handle was closed and deleted. + + EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemRead ( + IN EFI_FILE *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Read data from a file. + +Arguments: + + This - Pointer to a returned open file handle. + + BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer. + + Buffer - Pointer to the first byte of the read Buffer. + +Returns: + + EFI_SUCCESS - The data was read. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupted. + + EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry. + *BufferSize has been updated with the size needed to complete the request. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemWrite ( + IN EFI_FILE *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Write data to a file. + +Arguments: + + This - Pointer to an opened file handle. + + BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes + of data written to the file. + + Buffer - Pointer to the first by of data in the buffer to write to the file. + +Returns: + + EFI_SUCCESS - The data was written to the file. + + EFI_UNSUPPORTED - Writes to an open directory are not supported. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemSetPosition ( + IN EFI_FILE *This, + IN UINT64 Position + ) +/*++ + +Routine Description: + + Set a file's current position. + +Arguments: + + This - Pointer to an opened file handle. + + Position - The byte position from the start of the file to set. + +Returns: + + EFI_SUCCESS - The file position has been changed. + + EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemGetPosition ( + IN EFI_FILE *This, + OUT UINT64 *Position + ) +/*++ + +Routine Description: + + Get a file's current position. + +Arguments: + + This - Pointer to an opened file handle. + + Position - Pointer to storage for the current position. + +Returns: + + EFI_SUCCESS - The file position has been reported. + + EFI_UNSUPPORTED - Not valid for directories. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemGetInfo ( + IN EFI_FILE *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Return information about a file or volume. + +Arguments: + + This - Pointer to an opened file handle. + + InformationType - GUID describing the type of information to be returned. + + BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the + information buffer. + + Buffer - Pointer to the first byte of the information buffer. + +Returns: + + EFI_SUCCESS - The requested information has been written into the buffer. + + EFI_UNSUPPORTED - The InformationType is not known. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has + been updated with the size needed to complete the requested operation. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemSetInfo ( + IN EFI_FILE *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +/*++ + +Routine Description: + + Set information about a file or volume. + +Arguments: + + This - Pointer to an opened file handle. + + InformationType - GUID identifying the type of information to set. + + BufferSize - Number of bytes of data in the information buffer. + + Buffer - Pointer to the first byte of data in the information buffer. + +Returns: + + EFI_SUCCESS - The file or volume information has been updated. + + EFI_UNSUPPORTED - The information identifier is not recognised. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures are corrupt. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + + EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType. + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtSimpleFileSystemFlush ( + IN EFI_FILE *This + ) +/*++ + +Routine Description: + + Flush all modified data to the media. + +Arguments: + + This - Pointer to an opened file handle. + +Returns: + + EFI_SUCCESS - The data has been flushed. + + EFI_NO_MEDIA - The device has no media. + + EFI_DEVICE_ERROR - The device reported an error. + + EFI_VOLUME_CORRUPTED - The file system structures have been corrupted. + + EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected. + + EFI_ACCESS_DENIED - The file was opened read-only. + + EFI_VOLUME_FULL - The volume is full. + +--*/ +; + +#endif /* _WIN_NT_SIMPLE_FILE_SYSTEM_H_ */ + +/* eof - WinNtSimpleFileSystem.h */ diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.mbd new file mode 100644 index 0000000000..3a3e7845c6 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.mbd @@ -0,0 +1,41 @@ + + + + + WinNtSimpleFileSystem + 9C25E18B-76BA-43da-A132-DBB0997CEFEF + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + BaseLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + UefiDriverModelLib + UefiDebugLibStdErr + BasePrintLib + DxeMemoryAllocationLib + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.msa new file mode 100644 index 0000000000..654340e2f8 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.msa @@ -0,0 +1,81 @@ + + + + + WinNtSimpleFileSystem + UEFI_DRIVER + BS_DRIVER + 9C25E18B-76BA-43da-A132-DBB0997CEFEF + 0 + Component description file for WinNtSimpleFileSystem module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + DebugLib + BaseLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + WinNtSimpleFileSystem.h + WinNtSimpleFileSystem.c + ComponentName.c + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + WinNtIo + SimpleFileSystem + + + + WinNtFileSystem + + + FileSystemInfo + + + FileInfo + + + FileSystemVolumeLabelInfoId + + + + + + + + gWinNtSimpleFileSystemDriverBinding + gWinNtSimpleFileSystemComponentName + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/build.xml new file mode 100644 index 0000000000..fc39519781 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/SimpleFileSystem/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/ComponentName.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/ComponentName.c new file mode 100644 index 0000000000..7b9c2972d0 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/ComponentName.c @@ -0,0 +1,187 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "WinNtUga.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +WinNtUgaComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +WinNtUgaComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gWinNtUgaComponentName = { + WinNtUgaComponentNameGetDriverName, + WinNtUgaComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mWinNtUgaDriverNameTable[] = { + { "eng", L"Windows Universal Graphics Adapter Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +WinNtUgaComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gWinNtUgaComponentName.SupportedLanguages, + mWinNtUgaDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +WinNtUgaComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + UGA_PRIVATE_DATA *Private; + + // + // This is a device driver, so ChildHandle must be NULL. + // + if (ChildHandle != NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiUgaDrawProtocolGuid, + &UgaDraw, + gWinNtUgaDriverBinding.DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = UGA_DRAW_PRIVATE_DATA_FROM_THIS (UgaDraw); + + return LookupUnicodeString ( + Language, + gWinNtUgaComponentName.SupportedLanguages, + Private->ControllerNameTable, + ControllerName + ); +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUga.h b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUga.h new file mode 100644 index 0000000000..defe3913fc --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUga.h @@ -0,0 +1,363 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtUga.h + +Abstract: + + Private data for the Uga driver that is bound to the WinNt Thunk protocol + +--*/ + +#ifndef _WIN_NT_UGA_H_ +#define _WIN_NT_UGA_H_ + + + +#define MAX_Q 256 + +typedef struct { + UINTN Front; + UINTN Rear; + UINTN Count; + EFI_INPUT_KEY Q[MAX_Q]; +} UGA_QUEUE_FIXED; + +#define WIN_NT_UGA_CLASS_NAME L"WinNtUgaWindow" + +#define UGA_PRIVATE_DATA_SIGNATURE EFI_SIGNATURE_32 ('S', 'g', 'o', 'N') +typedef struct { + UINT64 Signature; + + EFI_HANDLE Handle; + EFI_UGA_DRAW_PROTOCOL UgaDraw; + EFI_SIMPLE_TEXT_IN_PROTOCOL SimpleTextIn; + + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + + // + // UGA Private Data for GetMode () + // + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + UINT32 ColorDepth; + UINT32 RefreshRate; + + // + // UGA Private Data knowing when to start hardware + // + BOOLEAN HardwareNeedsStarting; + + CHAR16 *WindowName; + CHAR16 Buffer[160]; + + HANDLE ThreadInited; // Semaphore + HANDLE ThreadHandle; // Thread + DWORD ThreadId; + + HWND WindowHandle; + WNDCLASSEX WindowsClass; + + // + // This screen is used to redraw the scree when windows events happen. It's + // updated in the main thread and displayed in the windows thread. + // + BITMAPV4HEADER *VirtualScreenInfo; + RGBQUAD *VirtualScreen; + + EFI_UGA_PIXEL *FillLine; + + // + // Keyboard Queue used by Simple Text In. WinProc thread adds, and main + // thread removes. + // + CRITICAL_SECTION QCriticalSection; + UGA_QUEUE_FIXED Queue; + +} UGA_PRIVATE_DATA; + +#define UGA_DRAW_PRIVATE_DATA_FROM_THIS(a) \ + CR(a, UGA_PRIVATE_DATA, UgaDraw, UGA_PRIVATE_DATA_SIGNATURE) + +#define UGA_PRIVATE_DATA_FROM_TEXT_IN_THIS(a) \ + CR(a, UGA_PRIVATE_DATA, SimpleTextIn, UGA_PRIVATE_DATA_SIGNATURE) + +// +// Global Protocol Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gWinNtUgaDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gWinNtUgaComponentName; + +// +// Uga Hardware abstraction internal worker functions +// +EFI_STATUS +WinNtUgaSupported ( + IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + WinNtIo - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +WinNtUgaConstructor ( + IN UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +WinNtUgaDestructor ( + IN UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// EFI 1.1 driver model prototypes for Win NT UGA +// + +EFI_STATUS +EFIAPI +WinNtUgaInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + SystemTable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtUgaDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtUgaDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtUgaDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +UgaPrivateAddQ ( + IN UGA_PRIVATE_DATA *Private, + IN EFI_INPUT_KEY Key + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + Key - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +WinNtUgaInitializeSimpleTextInForWindow ( + IN UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +WinNtUgaDestroySimpleTextInForWindow ( + IN UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +UINTN +Atoi ( + IN CHAR16 *String + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + String - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUga.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUga.mbd new file mode 100644 index 0000000000..18add2fe18 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUga.mbd @@ -0,0 +1,41 @@ + + + + + WinNtUga + AB248E8D-ABE1-11d4-BD0D-0080C73C8881 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + BaseLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + UefiDriverModelLib + UefiDebugLibStdErr + BasePrintLib + DxeMemoryAllocationLib + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUga.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUga.msa new file mode 100644 index 0000000000..f83a41dda3 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUga.msa @@ -0,0 +1,83 @@ + + + + + WinNtUga + UEFI_DRIVER + BS_DRIVER + AB248E8D-ABE1-11d4-BD0D-0080C73C8881 + 0 + Component description file for UGA module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + DebugLib + BaseLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + WinNtUga.h + WinNtUgaInput.c + WinNtUgaDriver.c + WinNtUgaScreen.c + ComponentName.c + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + WinNtIo + UgaDraw + SimpleTextIn + + + + + gEfiEventExitBootServicesGuid + 0x27abf055, 0xb1b8, 0x4c26, 0x80, 0x48, 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf + + + + + + WinNtUga + + + + + + + + gWinNtUgaDriverBinding + gWinNtUgaComponentName + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUgaDriver.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUgaDriver.c new file mode 100644 index 0000000000..58908d9f07 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUgaDriver.c @@ -0,0 +1,343 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtUgaDriver.c + +Abstract: + + This file implements the EFI 1.1 Device Driver model requirements for UGA + + UGA is short hand for Universal Graphics Abstraction protocol. + + This file is a verision of UgaIo the uses WinNtThunk system calls as an IO + abstraction. For a PCI device WinNtIo would be replaced with + a PCI IO abstraction that abstracted a specific PCI device. + +--*/ + +#include "WinNtUga.h" + +EFI_DRIVER_BINDING_PROTOCOL gWinNtUgaDriverBinding = { + WinNtUgaDriverBindingSupported, + WinNtUgaDriverBindingStart, + WinNtUgaDriverBindingStop, + 0x10, + NULL, + NULL +}; + + +EFI_STATUS +EFIAPI +WinNtUgaDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = WinNtUgaSupported (WinNtIo); + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtUgaDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + EFI_STATUS Status; + UGA_PRIVATE_DATA *Private; + + // + // Grab the protocols we need + // + Status = gBS->OpenProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + // + // Allocate Private context data for SGO inteface. + // + Private = NULL; + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (UGA_PRIVATE_DATA), + &Private + ); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Set up context record + // + Private->Signature = UGA_PRIVATE_DATA_SIGNATURE; + Private->Handle = Handle; + Private->WinNtThunk = WinNtIo->WinNtThunk; + + Private->ControllerNameTable = NULL; + + AddUnicodeString ( + "eng", + gWinNtUgaComponentName.SupportedLanguages, + &Private->ControllerNameTable, + WinNtIo->EnvString + ); + + Private->WindowName = WinNtIo->EnvString; + + Status = WinNtUgaConstructor (Private); + if (EFI_ERROR (Status)) { + goto Done; + } + // + // Publish the Uga interface to the world + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->Handle, + &gEfiUgaDrawProtocolGuid, + &Private->UgaDraw, + &gEfiSimpleTextInProtocolGuid, + &Private->SimpleTextIn, + NULL + ); + +Done: + if (EFI_ERROR (Status)) { + + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + if (Private != NULL) { + // + // On Error Free back private data + // + if (Private->ControllerNameTable != NULL) { + FreeUnicodeStringTable (Private->ControllerNameTable); + } + + gBS->FreePool (Private); + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtUgaDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: Handle - add argument and description to function comment +// TODO: NumberOfChildren - add argument and description to function comment +// TODO: ChildHandleBuffer - add argument and description to function comment +// TODO: EFI_NOT_STARTED - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +{ + EFI_UGA_DRAW_PROTOCOL *UgaDraw; + EFI_STATUS Status; + UGA_PRIVATE_DATA *Private; + + Status = gBS->OpenProtocol ( + Handle, + &gEfiUgaDrawProtocolGuid, + &UgaDraw, + This->DriverBindingHandle, + Handle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + // + // If the UGA interface does not exist the driver is not started + // + return EFI_NOT_STARTED; + } + + // + // Get our private context information + // + Private = UGA_DRAW_PRIVATE_DATA_FROM_THIS (UgaDraw); + + // + // Remove the SGO interface from the system + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + Private->Handle, + &gEfiUgaDrawProtocolGuid, + &Private->UgaDraw, + &gEfiSimpleTextInProtocolGuid, + &Private->SimpleTextIn, + NULL + ); + if (!EFI_ERROR (Status)) { + // + // Shutdown the hardware + // + Status = WinNtUgaDestructor (Private); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + gBS->CloseProtocol ( + Handle, + &gEfiWinNtIoProtocolGuid, + This->DriverBindingHandle, + Handle + ); + + // + // Free our instance data + // + FreeUnicodeStringTable (Private->ControllerNameTable); + + gBS->FreePool (Private); + + } + + return Status; +} + +UINTN +Atoi ( + CHAR16 *String + ) +/*++ + +Routine Description: + + Convert a unicode string to a UINTN + +Arguments: + + String - Unicode string. + +Returns: + + UINTN of the number represented by String. + +--*/ +{ + UINTN Number; + CHAR16 *Str; + + // + // skip preceeding white space + // + Str = String; + while ((*Str) && (*Str == ' ' || *Str == '"')) { + Str++; + } + + // + // Convert ot a Number + // + Number = 0; + while (*Str != '\0') { + if ((*Str >= '0') && (*Str <= '9')) { + Number = (Number * 10) +*Str - '0'; + } else { + break; + } + + Str++; + } + + return Number; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUgaInput.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUgaInput.c new file mode 100644 index 0000000000..19bca36359 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUgaInput.c @@ -0,0 +1,411 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtUgaInput.c + +Abstract: + + This file produces the Simple Text In for an Uga window. + + This stuff is linked at the hip to the Window, since the window + processing is done in a thread kicked off in WinNtUgaImplementation.c + + Since the window information is processed in an other thread we need + a keyboard Queue to pass data about. The Simple Text In code just + takes data off the Queue. The WinProc message loop takes keyboard input + and places it in the Queue. + +--*/ + +#include "WinNtUga.h" + +EFI_STATUS +UgaPrivateCreateQ ( + IN UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + Private->WinNtThunk->InitializeCriticalSection (&Private->QCriticalSection); + + Private->Queue.Front = 0; + Private->Queue.Rear = MAX_Q - 1; + Private->Queue.Count = 0; + return EFI_SUCCESS; +} + +EFI_STATUS +UgaPrivateDestroyQ ( + IN UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + Private->Queue.Count = 0; + Private->WinNtThunk->DeleteCriticalSection (&Private->QCriticalSection); + return EFI_SUCCESS; +} + +EFI_STATUS +UgaPrivateAddQ ( + IN UGA_PRIVATE_DATA *Private, + IN EFI_INPUT_KEY Key + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + Key - TODO: add argument description + +Returns: + + EFI_NOT_READY - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + Private->WinNtThunk->EnterCriticalSection (&Private->QCriticalSection); + + if (Private->Queue.Count == MAX_Q) { + Private->WinNtThunk->LeaveCriticalSection (&Private->QCriticalSection); + return EFI_NOT_READY; + } + + Private->Queue.Rear = (Private->Queue.Rear + 1) % MAX_Q; + Private->Queue.Q[Private->Queue.Rear] = Key; + Private->Queue.Count++; + + Private->WinNtThunk->LeaveCriticalSection (&Private->QCriticalSection); + return EFI_SUCCESS; +} + +EFI_STATUS +UgaPrivateDeleteQ ( + IN UGA_PRIVATE_DATA *Private, + OUT EFI_INPUT_KEY *Key + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + Key - TODO: add argument description + +Returns: + + EFI_NOT_READY - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + Private->WinNtThunk->EnterCriticalSection (&Private->QCriticalSection); + + if (Private->Queue.Count == 0) { + Private->WinNtThunk->LeaveCriticalSection (&Private->QCriticalSection); + return EFI_NOT_READY; + } + + *Key = Private->Queue.Q[Private->Queue.Front]; + Private->Queue.Front = (Private->Queue.Front + 1) % MAX_Q; + Private->Queue.Count--; + + Private->WinNtThunk->LeaveCriticalSection (&Private->QCriticalSection); + return EFI_SUCCESS; +} + +EFI_STATUS +UgaPrivateCheckQ ( + IN UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + EFI_NOT_READY - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + if (Private->Queue.Count == 0) { + return EFI_NOT_READY; + } + + return EFI_SUCCESS; +} + +// +// Simple Text In implementation. +// + +EFI_STATUS +EFIAPI +WinNtUgaSimpleTextInReset ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ExtendedVerification - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + UGA_PRIVATE_DATA *Private; + EFI_INPUT_KEY Key; + EFI_TPL OldTpl; + + Private = UGA_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + // + // A reset is draining the Queue + // + while (UgaPrivateDeleteQ (Private, &Key) == EFI_SUCCESS) + ; + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtUgaSimpleTextInReadKeyStroke ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Key - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UGA_PRIVATE_DATA *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + + Private = UGA_PRIVATE_DATA_FROM_TEXT_IN_THIS (This); + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + Status = UgaPrivateCheckQ (Private); + if (!EFI_ERROR (Status)) { + // + // If a Key press exists try and read it. + // + Status = UgaPrivateDeleteQ (Private, Key); + } + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); + + return Status; +} + +STATIC +VOID +EFIAPI +WinNtUgaSimpleTextInWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Event - TODO: add argument description + Context - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + UGA_PRIVATE_DATA *Private; + EFI_STATUS Status; + EFI_TPL OldTpl; + + Private = (UGA_PRIVATE_DATA *) Context; + + // + // Enter critical section + // + OldTpl = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + Status = UgaPrivateCheckQ (Private); + if (!EFI_ERROR (Status)) { + // + // If a there is a key in the queue signal our event. + // + gBS->SignalEvent (Event); + } else { + // + // We need to sleep or NT will schedule this thread with such high + // priority that WinProc thread will never run and we will not see + // keyboard input. This Sleep makes the syste run 10x faster, so don't + // remove it. + // + Private->WinNtThunk->Sleep (1); + } + + // + // Leave critical section and return + // + gBS->RestoreTPL (OldTpl); +} + +EFI_STATUS +WinNtUgaInitializeSimpleTextInForWindow ( + IN UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_STATUS Status; + + UgaPrivateCreateQ (Private); + + // + // Initialize Simple Text In protoocol + // + Private->SimpleTextIn.Reset = WinNtUgaSimpleTextInReset; + Private->SimpleTextIn.ReadKeyStroke = WinNtUgaSimpleTextInReadKeyStroke; + + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_WAIT, + EFI_TPL_NOTIFY, + WinNtUgaSimpleTextInWaitForKey, + Private, + &Private->SimpleTextIn.WaitForKey + ); + + return Status; +} + +EFI_STATUS +WinNtUgaDestroySimpleTextInForWindow ( + IN UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + UgaPrivateDestroyQ (Private); + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUgaScreen.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUgaScreen.c new file mode 100644 index 0000000000..ed35a01c32 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/WinNtUgaScreen.c @@ -0,0 +1,992 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtUgaScreen.c + +Abstract: + + This file produces the graphics abstration of UGA. It is called by + WinNtUgaDriver.c file which deals with the EFI 1.1 driver model. + This file just does graphics. + +--*/ + +#include "WinNtUga.h" + +EFI_WIN_NT_THUNK_PROTOCOL *mWinNt; +DWORD mTlsIndex = TLS_OUT_OF_INDEXES; +DWORD mTlsIndexUseCount = 0; // lets us know when we can free mTlsIndex. +static EFI_EVENT mUgaScreenExitBootServicesEvent; + +EFI_STATUS +WinNtUgaStartWindow ( + IN UGA_PRIVATE_DATA *Private, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ); + +STATIC +VOID +EFIAPI +KillNtUgaThread ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// +// UGA Protocol Member Functions +// + +EFI_STATUS +EFIAPI +WinNtUgaGetMode ( + EFI_UGA_DRAW_PROTOCOL *This, + UINT32 *HorizontalResolution, + UINT32 *VerticalResolution, + UINT32 *ColorDepth, + UINT32 *RefreshRate + ) +/*++ + + Routine Description: + Return the current video mode information. + + Arguments: + This - Protocol instance pointer. + HorizontalResolution - Current video horizontal resolution in pixels + VerticalResolution - Current video Vertical resolution in pixels + ColorDepth - Current video color depth in bits per pixel + RefreshRate - Current video refresh rate in Hz. + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_NOT_STARTED - Video display is not initialized. Call SetMode () + EFI_INVALID_PARAMETER - One of the input args was NULL. + +--*/ +// TODO: ADD IN/OUT description here +{ + UGA_PRIVATE_DATA *Private; + + Private = UGA_DRAW_PRIVATE_DATA_FROM_THIS (This); + + if (Private->HardwareNeedsStarting) { + return EFI_NOT_STARTED; + } + + if ((HorizontalResolution == NULL) || + (VerticalResolution == NULL) || + (ColorDepth == NULL) || + (RefreshRate == NULL)) { + return EFI_INVALID_PARAMETER; + } + + *HorizontalResolution = Private->HorizontalResolution; + *VerticalResolution = Private->VerticalResolution; + *ColorDepth = Private->ColorDepth; + *RefreshRate = Private->RefreshRate; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +WinNtUgaSetMode ( + EFI_UGA_DRAW_PROTOCOL *This, + UINT32 HorizontalResolution, + UINT32 VerticalResolution, + UINT32 ColorDepth, + UINT32 RefreshRate + ) +/*++ + + Routine Description: + Return the current video mode information. + + Arguments: + This - Protocol instance pointer. + HorizontalResolution - Current video horizontal resolution in pixels + VerticalResolution - Current video Vertical resolution in pixels + ColorDepth - Current video color depth in bits per pixel + RefreshRate - Current video refresh rate in Hz. + + Returns: + EFI_SUCCESS - Mode information returned. + EFI_NOT_STARTED - Video display is not initialized. Call SetMode () + EFI_INVALID_PARAMETER - One of the input args was NULL. + +--*/ +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: ADD IN/OUT description here +{ + EFI_STATUS Status; + UGA_PRIVATE_DATA *Private; + EFI_UGA_PIXEL Fill; + EFI_UGA_PIXEL *NewFillLine; + RECT Rect; + UINTN Size; + UINTN Width; + UINTN Height; + + Private = UGA_DRAW_PRIVATE_DATA_FROM_THIS (This); + + if (Private->HardwareNeedsStarting) { + Status = WinNtUgaStartWindow ( + Private, + HorizontalResolution, + VerticalResolution, + ColorDepth, + RefreshRate + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Private->HardwareNeedsStarting = FALSE; + } else { + // + // Change the resolution and resize of the window + // + + // + // Free the old buffer. We do not save the content of the old buffer since the + // screen is to be cleared anyway. Clearing the screen is required by the EFI spec. + // See EFI spec chepter 10.5-EFI_UGA_DRAW_PROTOCOL.SetMode() + // + Private->WinNtThunk->HeapFree (Private->WinNtThunk->GetProcessHeap (), 0, Private->VirtualScreenInfo); + + // + // Allocate DIB frame buffer directly from NT for performance enhancement + // This buffer is the virtual screen/frame buffer. This buffer is not the + // same a a frame buffer. The first row of this buffer will be the bottom + // line of the image. This is an artifact of the way we draw to the screen. + // + Size = HorizontalResolution * VerticalResolution * sizeof (RGBQUAD) + sizeof (BITMAPV4HEADER); + Private->VirtualScreenInfo = Private->WinNtThunk->HeapAlloc ( + Private->WinNtThunk->GetProcessHeap (), + HEAP_ZERO_MEMORY, + Size + ); + + // + // Update the virtual screen info data structure + // + Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER); + Private->VirtualScreenInfo->bV4Width = HorizontalResolution; + Private->VirtualScreenInfo->bV4Height = VerticalResolution; + Private->VirtualScreenInfo->bV4Planes = 1; + Private->VirtualScreenInfo->bV4BitCount = 32; + // + // uncompressed + // + Private->VirtualScreenInfo->bV4V4Compression = BI_RGB; + + // + // The rest of the allocated memory block is the virtual screen buffer + // + Private->VirtualScreen = (RGBQUAD *) (Private->VirtualScreenInfo + 1); + + // + // Use the AdjuctWindowRect fuction to calculate the real width and height + // of the new window including the border and caption + // + Rect.left = 0; + Rect.top = 0; + Rect.right = HorizontalResolution; + Rect.bottom = VerticalResolution; + + Private->WinNtThunk->AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0); + + Width = Rect.right - Rect.left; + Height = Rect.bottom - Rect.top; + + // + // Retrieve the original window position information + // + Private->WinNtThunk->GetWindowRect (Private->WindowHandle, &Rect); + + // + // Adjust the window size + // + Private->WinNtThunk->MoveWindow (Private->WindowHandle, Rect.left, Rect.top, Width, Height, TRUE); + + } + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (EFI_UGA_PIXEL) * HorizontalResolution, + &NewFillLine + ); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + if (Private->FillLine != NULL) { + gBS->FreePool (Private->FillLine); + } + + Private->FillLine = NewFillLine; + + Private->HorizontalResolution = HorizontalResolution; + Private->VerticalResolution = VerticalResolution; + Private->ColorDepth = ColorDepth; + Private->RefreshRate = RefreshRate; + + Fill.Red = 0x00; + Fill.Green = 0x00; + Fill.Blue = 0x00; + This->Blt ( + This, + &Fill, + EfiUgaVideoFill, + 0, + 0, + 0, + 0, + HorizontalResolution, + VerticalResolution, + HorizontalResolution * sizeof (EFI_UGA_PIXEL) + ); + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +WinNtUgaBlt ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN EFI_UGA_PIXEL *BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ) +/*++ + + Routine Description: + Blt pixels from the rectangle (Width X Height) formed by the BltBuffer + onto the graphics screen starting a location (X, Y). (0, 0) is defined as + the upper left hand side of the screen. (X, Y) can be outside of the + current screen geometry and the BltBuffer will be cliped when it is + displayed. X and Y can be negative or positive. If Width or Height is + bigger than the current video screen the image will be clipped. + + Arguments: + This - Protocol instance pointer. + X - X location on graphics screen. + Y - Y location on the graphics screen. + Width - Width of BltBuffer. + Height - Hight of BltBuffer + BltOperation - Operation to perform on BltBuffer and video memory + BltBuffer - Buffer containing data to blt into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL) + SourceX - If the BltOperation is a EfiCopyBlt this is the source + of the copy. For other BLT operations this argument is not + used. + SourceX - If the BltOperation is a EfiCopyBlt this is the source + of the copy. For other BLT operations this argument is not + used. + + Returns: + EFI_SUCCESS - The palette is updated with PaletteArray. + EFI_INVALID_PARAMETER - BltOperation is not valid. + EFI_DEVICE_ERROR - A hardware error occured writting to the video + buffer. + +--*/ +// TODO: SourceY - add argument and description to function comment +// TODO: DestinationX - add argument and description to function comment +// TODO: DestinationY - add argument and description to function comment +// TODO: Delta - add argument and description to function comment +{ + UGA_PRIVATE_DATA *Private; + EFI_TPL OriginalTPL; + UINTN DstY; + UINTN SrcY; + RGBQUAD *VScreen; + RGBQUAD *VScreenSrc; + EFI_UGA_PIXEL *Blt; + UINTN Index; + RECT Rect; + EFI_UGA_PIXEL *FillPixel; + + Private = UGA_DRAW_PRIVATE_DATA_FROM_THIS (This); + + if ((BltOperation < 0) || (BltOperation >= EfiUgaBltMax)) { + return EFI_INVALID_PARAMETER; + } + + if (Width == 0 || Height == 0) { + return EFI_INVALID_PARAMETER; + } + // + // If Delta is zero, then the entire BltBuffer is being used, so Delta + // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size, + // the number of bytes in each row can be computed. + // + if (Delta == 0) { + Delta = Width * sizeof (EFI_UGA_PIXEL); + } + + // + // We need to fill the Virtual Screen buffer with the blt data. + // The virtual screen is upside down, as the first row is the bootom row of + // the image. + // + + if (BltOperation == EfiUgaVideoToBltBuffer) { + + // + // Video to BltBuffer: Source is Video, destination is BltBuffer + // + if (SourceY + Height > Private->VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (SourceX + Width > Private->HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + // + // We have to raise to TPL Notify, so we make an atomic write the frame buffer. + // We would not want a timer based event (Cursor, ...) to come in while we are + // doing this operation. + // + OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + for (SrcY = SourceY, DstY = DestinationY; DstY < (Height + DestinationY); SrcY++, DstY++) { + Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (DstY * Delta) + DestinationX * sizeof (EFI_UGA_PIXEL)); + VScreen = &Private->VirtualScreen[(Private->VerticalResolution - SrcY - 1) * Private->HorizontalResolution + SourceX]; + CopyMem (Blt, VScreen, sizeof (EFI_UGA_PIXEL) * Width); + } + } else { + // + // BltBuffer to Video: Source is BltBuffer, destination is Video + // + if (DestinationY + Height > Private->VerticalResolution) { + return EFI_INVALID_PARAMETER; + } + + if (DestinationX + Width > Private->HorizontalResolution) { + return EFI_INVALID_PARAMETER; + } + + // + // We have to raise to TPL Notify, so we make an atomic write the frame buffer. + // We would not want a timer based event (Cursor, ...) to come in while we are + // doing this operation. + // + OriginalTPL = gBS->RaiseTPL (EFI_TPL_NOTIFY); + + if (BltOperation == EfiUgaVideoFill) { + FillPixel = BltBuffer; + for (Index = 0; Index < Width; Index++) { + Private->FillLine[Index] = *FillPixel; + } + } + + for (Index = 0; Index < Height; Index++) { + if (DestinationY <= SourceY) { + SrcY = SourceY + Index; + DstY = DestinationY + Index; + } else { + SrcY = SourceY + Height - Index - 1; + DstY = DestinationY + Height - Index - 1; + } + + VScreen = &Private->VirtualScreen[(Private->VerticalResolution - DstY - 1) * Private->HorizontalResolution + DestinationX]; + switch (BltOperation) { + case EfiUgaBltBufferToVideo: + Blt = (EFI_UGA_PIXEL *) ((UINT8 *) BltBuffer + (SrcY * Delta) + SourceX * sizeof (EFI_UGA_PIXEL)); + CopyMem (VScreen, Blt, Width * sizeof (EFI_UGA_PIXEL)); + break; + + case EfiUgaVideoToVideo: + VScreenSrc = &Private->VirtualScreen[(Private->VerticalResolution - SrcY - 1) * Private->HorizontalResolution + SourceX]; + CopyMem (VScreen, VScreenSrc, Width * sizeof (EFI_UGA_PIXEL)); + break; + + case EfiUgaVideoFill: + CopyMem (VScreen, Private->FillLine, Width * sizeof (EFI_UGA_PIXEL)); + break; + } + } + } + + if (BltOperation != EfiUgaVideoToBltBuffer) { + // + // Mark the area we just blted as Invalid so WM_PAINT will update. + // + Rect.left = DestinationX; + Rect.top = DestinationY; + Rect.right = DestinationX + Width; + Rect.bottom = DestinationY + Height; + Private->WinNtThunk->InvalidateRect (Private->WindowHandle, &Rect, FALSE); + + // + // Send the WM_PAINT message to the thread that is drawing the window. We + // are in the main thread and the window drawing is in a child thread. + // There is a child thread per window. We have no CriticalSection or Mutex + // since we write the data and the other thread displays the data. While + // we may miss some data for a short period of time this is no different than + // a write combining on writes to a frame buffer. + // + + Private->WinNtThunk->UpdateWindow (Private->WindowHandle); + } + + gBS->RestoreTPL (OriginalTPL); + + return EFI_SUCCESS; +} + + +// +// Construction and Destruction functions +// + +EFI_STATUS +WinNtUgaSupported ( + IN EFI_WIN_NT_IO_PROTOCOL *WinNtIo + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: WinNtIo - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + // + // Check to see if the IO abstraction represents a device type we support. + // + // This would be replaced a check of PCI subsystem ID, etc. + // + if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtUgaGuid)) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +LRESULT +CALLBACK +WinNtUgaThreadWindowProc ( + IN HWND hwnd, + IN UINT iMsg, + IN WPARAM wParam, + IN LPARAM lParam + ) +/*++ + +Routine Description: + Win32 Windows event handler. + +Arguments: + See Win32 Book + +Returns: + See Win32 Book + +--*/ +// TODO: hwnd - add argument and description to function comment +// TODO: iMsg - add argument and description to function comment +// TODO: wParam - add argument and description to function comment +// TODO: lParam - add argument and description to function comment +{ + UGA_PRIVATE_DATA *Private; + UINTN Size; + HDC Handle; + PAINTSTRUCT PaintStruct; + LPARAM Index; + EFI_INPUT_KEY Key; + + // + // BugBug - if there are two instances of this DLL in memory (such as is + // the case for ERM), the correct instance of this function may not be called. + // This also means that the address of the mTlsIndex value will be wrong, and + // the value may be wrong too. + // + + + // + // Use mTlsIndex global to get a Thread Local Storage version of Private. + // This works since each Uga protocol has a unique Private data instance and + // a unique thread. + // + Private = mWinNt->TlsGetValue (mTlsIndex); + ASSERT (NULL != Private); + + switch (iMsg) { + case WM_CREATE: + Size = Private->HorizontalResolution * Private->VerticalResolution * sizeof (RGBQUAD); + + // + // Allocate DIB frame buffer directly from NT for performance enhancement + // This buffer is the virtual screen/frame buffer. This buffer is not the + // same a a frame buffer. The first fow of this buffer will be the bottom + // line of the image. This is an artifact of the way we draw to the screen. + // + Private->VirtualScreenInfo = Private->WinNtThunk->HeapAlloc ( + Private->WinNtThunk->GetProcessHeap (), + HEAP_ZERO_MEMORY, + Size + ); + + Private->VirtualScreenInfo->bV4Size = sizeof (BITMAPV4HEADER); + Private->VirtualScreenInfo->bV4Width = Private->HorizontalResolution; + Private->VirtualScreenInfo->bV4Height = Private->VerticalResolution; + Private->VirtualScreenInfo->bV4Planes = 1; + Private->VirtualScreenInfo->bV4BitCount = 32; + // + // uncompressed + // + Private->VirtualScreenInfo->bV4V4Compression = BI_RGB; + Private->VirtualScreen = (RGBQUAD *) (Private->VirtualScreenInfo + 1); + return 0; + + case WM_PAINT: + // + // I have not found a way to convert hwnd into a Private context. So for + // now we use this API to convert hwnd to Private data. + // + + Handle = mWinNt->BeginPaint (hwnd, &PaintStruct); + + mWinNt->SetDIBitsToDevice ( + Handle, // Destination Device Context + 0, // Destination X - 0 + 0, // Destination Y - 0 + Private->HorizontalResolution, // Width + Private->VerticalResolution, // Height + 0, // Source X + 0, // Source Y + 0, // DIB Start Scan Line + Private->VerticalResolution, // Number of scan lines + Private->VirtualScreen, // Address of array of DIB bits + (BITMAPINFO *) Private->VirtualScreenInfo, // Address of structure with bitmap info + DIB_RGB_COLORS // RGB or palette indexes + ); + + mWinNt->EndPaint (hwnd, &PaintStruct); + return 0; + + // + // F10 and the ALT key do not create a WM_KEYDOWN message, thus this special case + // + case WM_SYSKEYDOWN: + Key.ScanCode = 0; + switch (wParam) { + case VK_F10: + Key.ScanCode = SCAN_F10; + Key.UnicodeChar = 0; + UgaPrivateAddQ (Private, Key); + return 0; + } + break; + + case WM_KEYDOWN: + Key.ScanCode = 0; + switch (wParam) { + case VK_HOME: Key.ScanCode = SCAN_HOME; break; + case VK_END: Key.ScanCode = SCAN_END; break; + case VK_LEFT: Key.ScanCode = SCAN_LEFT; break; + case VK_RIGHT: Key.ScanCode = SCAN_RIGHT; break; + case VK_UP: Key.ScanCode = SCAN_UP; break; + case VK_DOWN: Key.ScanCode = SCAN_DOWN; break; + case VK_DELETE: Key.ScanCode = SCAN_DELETE; break; + case VK_INSERT: Key.ScanCode = SCAN_INSERT; break; + case VK_PRIOR: Key.ScanCode = SCAN_PAGE_UP; break; + case VK_NEXT: Key.ScanCode = SCAN_PAGE_DOWN; break; + case VK_ESCAPE: Key.ScanCode = SCAN_ESC; break; + + case VK_F1: Key.ScanCode = SCAN_F1; break; + case VK_F2: Key.ScanCode = SCAN_F2; break; + case VK_F3: Key.ScanCode = SCAN_F3; break; + case VK_F4: Key.ScanCode = SCAN_F4; break; + case VK_F5: Key.ScanCode = SCAN_F5; break; + case VK_F6: Key.ScanCode = SCAN_F6; break; + case VK_F7: Key.ScanCode = SCAN_F7; break; + case VK_F8: Key.ScanCode = SCAN_F8; break; + case VK_F9: Key.ScanCode = SCAN_F9; break; + } + + if (Key.ScanCode != 0) { + Key.UnicodeChar = 0; + UgaPrivateAddQ (Private, Key); + } + + return 0; + + case WM_CHAR: + // + // The ESC key also generate WM_CHAR. + // + if (wParam == 0x1B) { + return 0; + } + + for (Index = 0; Index < (lParam & 0xffff); Index++) { + if (wParam != 0) { + Key.UnicodeChar = (CHAR16) wParam; + Key.ScanCode = 0; + UgaPrivateAddQ (Private, Key); + } + } + + return 0; + + case WM_CLOSE: + // + // This close message is issued by user, core is not aware of this, + // so don't release the window display resource, just hide the window. + // + Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_HIDE); + return 0; + + case WM_DESTROY: + mWinNt->DestroyWindow (hwnd); + mWinNt->PostQuitMessage (0); + + mWinNt->HeapFree (Private->WinNtThunk->GetProcessHeap (), 0, Private->VirtualScreenInfo); + + mWinNt->ExitThread (0); + return 0; + + default: + break; + }; + + return mWinNt->DefWindowProc (hwnd, iMsg, wParam, lParam); +} + +DWORD +WINAPI +WinNtUgaThreadWinMain ( + LPVOID lpParameter + ) +/*++ + +Routine Description: + + This thread simulates the end of WinMain () aplication. Each Winow nededs + to process it's events. The messages are dispatched to + WinNtUgaThreadWindowProc (). + + Be very careful sine WinNtUgaThreadWinMain () and WinNtUgaThreadWindowProc () + are running in a seperate thread. We have to do this to process the events. + +Arguments: + + lpParameter - Handle of window to manage. + +Returns: + + if a WM_QUIT message is returned exit. + +--*/ +{ + MSG Message; + UGA_PRIVATE_DATA *Private; + ATOM Atom; + RECT Rect; + + Private = (UGA_PRIVATE_DATA *) lpParameter; + ASSERT (NULL != Private); + + // + // Since each thread has unique private data, save the private data in Thread + // Local Storage slot. Then the shared global mTlsIndex can be used to get + // thread specific context. + // + Private->WinNtThunk->TlsSetValue (mTlsIndex, Private); + + Private->ThreadId = Private->WinNtThunk->GetCurrentThreadId (); + + Private->WindowsClass.cbSize = sizeof (WNDCLASSEX); + Private->WindowsClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + Private->WindowsClass.lpfnWndProc = WinNtUgaThreadWindowProc; + Private->WindowsClass.cbClsExtra = 0; + Private->WindowsClass.cbWndExtra = 0; + Private->WindowsClass.hInstance = NULL; + Private->WindowsClass.hIcon = Private->WinNtThunk->LoadIcon (NULL, IDI_APPLICATION); + Private->WindowsClass.hCursor = Private->WinNtThunk->LoadCursor (NULL, IDC_ARROW); + Private->WindowsClass.hbrBackground = (HBRUSH) COLOR_WINDOW; + Private->WindowsClass.lpszMenuName = NULL; + Private->WindowsClass.lpszClassName = WIN_NT_UGA_CLASS_NAME; + Private->WindowsClass.hIconSm = Private->WinNtThunk->LoadIcon (NULL, IDI_APPLICATION); + + // + // This call will fail after the first time, but thats O.K. since we only need + // WIN_NT_UGA_CLASS_NAME to exist to create the window. + // + // Note: Multiple instances of this DLL will use the same instance of this + // Class, including the callback function, unless the Class is unregistered and + // successfully registered again. + // + Atom = Private->WinNtThunk->RegisterClassEx (&Private->WindowsClass); + + // + // Setting Rect values to allow for the AdjustWindowRect to provide + // us the correct sizes for the client area when doing the CreateWindowEx + // + Rect.top = 0; + Rect.bottom = Private->VerticalResolution; + Rect.left = 0; + Rect.right = Private->HorizontalResolution; + + Private->WinNtThunk->AdjustWindowRect (&Rect, WS_OVERLAPPEDWINDOW, 0); + + Private->WindowHandle = Private->WinNtThunk->CreateWindowEx ( + 0, + WIN_NT_UGA_CLASS_NAME, + Private->WindowName, + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + Rect.right - Rect.left, + Rect.bottom - Rect.top, + NULL, + NULL, + NULL, + &Private + ); + + // + // The reset of this thread is the standard winows program. We need a sperate + // thread since we must process the message loop to make windows act like + // windows. + // + + Private->WinNtThunk->ShowWindow (Private->WindowHandle, SW_SHOW); + Private->WinNtThunk->UpdateWindow (Private->WindowHandle); + + // + // Let the main thread get some work done + // + Private->WinNtThunk->ReleaseSemaphore (Private->ThreadInited, 1, NULL); + + // + // This is the message loop that all Windows programs need. + // + while (Private->WinNtThunk->GetMessage (&Message, Private->WindowHandle, 0, 0)) { + Private->WinNtThunk->TranslateMessage (&Message); + Private->WinNtThunk->DispatchMessage (&Message); + } + + return Message.wParam; +} + +EFI_STATUS +WinNtUgaStartWindow ( + IN UGA_PRIVATE_DATA *Private, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Private - TODO: add argument description + HorizontalResolution - TODO: add argument description + VerticalResolution - TODO: add argument description + ColorDepth - TODO: add argument description + RefreshRate - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_STATUS Status; + DWORD NewThreadId; + + + mWinNt = Private->WinNtThunk; + + // + // Initialize a Thread Local Storge variable slot. We use TLS to get the + // correct Private data instance into the windows thread. + // + if (mTlsIndex == TLS_OUT_OF_INDEXES) { + ASSERT (0 == mTlsIndexUseCount); + mTlsIndex = Private->WinNtThunk->TlsAlloc (); + } + + // + // always increase the use count! + // + mTlsIndexUseCount++; + + Private->HorizontalResolution = HorizontalResolution; + Private->VerticalResolution = VerticalResolution; + + // + // Register to be notified on exit boot services so we can destroy the window. + // + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES, + EFI_TPL_CALLBACK, + KillNtUgaThread, + Private, + &mUgaScreenExitBootServicesEvent + ); + + Private->ThreadInited = Private->WinNtThunk->CreateSemaphore (NULL, 0, 1, NULL); + Private->ThreadHandle = Private->WinNtThunk->CreateThread ( + NULL, + 0, + WinNtUgaThreadWinMain, + (VOID *) Private, + 0, + &NewThreadId + ); + + // + // The other thread has entered the windows message loop so we can + // continue our initialization. + // + Private->WinNtThunk->WaitForSingleObject (Private->ThreadInited, INFINITE); + Private->WinNtThunk->CloseHandle (Private->ThreadInited); + + return Status; +} + +EFI_STATUS +WinNtUgaConstructor ( + UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Private - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + + Private->UgaDraw.GetMode = WinNtUgaGetMode; + Private->UgaDraw.SetMode = WinNtUgaSetMode; + Private->UgaDraw.Blt = WinNtUgaBlt; + + Private->HardwareNeedsStarting = TRUE; + Private->FillLine = NULL; + + WinNtUgaInitializeSimpleTextInForWindow (Private); + + return EFI_SUCCESS; +} + +EFI_STATUS +WinNtUgaDestructor ( + UGA_PRIVATE_DATA *Private + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: Private - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + UINT32 UnregisterReturn; + + if (!Private->HardwareNeedsStarting) { + // + // BugBug: Shutdown Uga Hardware and any child devices. + // + Private->WinNtThunk->SendMessage (Private->WindowHandle, WM_DESTROY, 0, 0); + Private->WinNtThunk->CloseHandle (Private->ThreadHandle); + + mTlsIndexUseCount--; + + // + // The callback function for another window could still be called, + // so we need to make sure there are no more users of mTlsIndex. + // + if (0 == mTlsIndexUseCount) { + ASSERT (TLS_OUT_OF_INDEXES != mTlsIndex); + + Private->WinNtThunk->TlsFree (mTlsIndex); + mTlsIndex = TLS_OUT_OF_INDEXES; + + UnregisterReturn = Private->WinNtThunk->UnregisterClass ( + Private->WindowsClass.lpszClassName, + Private->WindowsClass.hInstance + ); + } + + WinNtUgaDestroySimpleTextInForWindow (Private); + } + + return EFI_SUCCESS; +} + +STATIC +VOID +EFIAPI +KillNtUgaThread ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + This is the UGA screen's callback notification function for exit-boot-services. + All we do here is call WinNtUgaDestructor(). + +Arguments: + + Event - not used + Context - pointer to the Private structure. + +Returns: + + None. + +--*/ +{ + EFI_STATUS Status; + Status = WinNtUgaDestructor (Context); +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/build.xml new file mode 100644 index 0000000000..4d5022a84b --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/Uga/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/ComponentName.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/ComponentName.c new file mode 100644 index 0000000000..7dee4bd9a4 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/ComponentName.c @@ -0,0 +1,187 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ComponentName.c + +Abstract: + +--*/ + +#include "WinNtBusDriver.h" + +// +// EFI Component Name Functions +// +EFI_STATUS +EFIAPI +WinNtBusDriverComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + +EFI_STATUS +EFIAPI +WinNtBusDriverComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// EFI Component Name Protocol +// +EFI_COMPONENT_NAME_PROTOCOL gWinNtBusDriverComponentName = { + WinNtBusDriverComponentNameGetDriverName, + WinNtBusDriverComponentNameGetControllerName, + "eng" +}; + +static EFI_UNICODE_STRING_TABLE mWinNtBusDriverNameTable[] = { + { "eng", L"Windows Bus Driver" }, + { NULL , NULL } +}; + +EFI_STATUS +EFIAPI +WinNtBusDriverComponentNameGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + Language - A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + DriverName - A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + Returns: + EFI_SUCCESS - The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - DriverName is NULL. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + return LookupUnicodeString ( + Language, + gWinNtBusDriverComponentName.SupportedLanguages, + mWinNtBusDriverNameTable, + DriverName + ); +} + +EFI_STATUS +EFIAPI +WinNtBusDriverComponentNameGetControllerName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +/*++ + + Routine Description: + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + Arguments: + This - A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + ControllerHandle - The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + ChildHandle - The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + Language - A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + ControllerName - A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + Returns: + EFI_SUCCESS - The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + EFI_INVALID_PARAMETER - ControllerHandle is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - ChildHandle is not NULL and it is not a valid EFI_HANDLE. + EFI_INVALID_PARAMETER - Language is NULL. + EFI_INVALID_PARAMETER - ControllerName is NULL. + EFI_UNSUPPORTED - The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + EFI_UNSUPPORTED - The driver specified by This does not support the + language specified by Language. + +--*/ +{ + EFI_STATUS Status; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + WIN_NT_IO_DEVICE *Private; + + // + // This is a bus driver, so ChildHandle can not be NULL. + // + if (ChildHandle == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Get our context back + // + Status = gBS->OpenProtocol ( + ChildHandle, + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + gWinNtBusDriverBinding.DriverBindingHandle, + ChildHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + Private = WIN_NT_IO_DEVICE_FROM_THIS (WinNtIo); + + return LookupUnicodeString ( + Language, + gWinNtBusDriverComponentName.SupportedLanguages, + Private->ControllerNameTable, + ControllerName + ); +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.c b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.c new file mode 100644 index 0000000000..eb071575e0 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.c @@ -0,0 +1,744 @@ +/*+++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtBusDriver.c + +Abstract: + +This following section documents the envirnoment variables for the Win NT +build. These variables are used to define the (virtual) hardware +configuration of the NT environment + +A ! can be used to seperate multiple instances in a variable. Each +instance represents a seperate hardware device. + +EFI_WIN_NT_PHYSICAL_DISKS - maps to drives on your system +EFI_WIN_NT_VIRTUAL_DISKS - maps to a device emulated by a file +EFI_WIN_NT_FILE_SYSTEM - mouts a directory as a file system +EFI_WIN_NT_CONSOLE - make a logical comand line window (only one!) +EFI_WIN_NT_UGA - Builds UGA Windows of Width and Height +EFI_WIN_NT_SERIAL_PORT - maps physical serial ports + + ixed - Fixed disk like a hard drive. + emovable - Removable media like a floppy or CD-ROM. + Read nly - Write protected device. + Read rite - Read write device. + - Decimal number of blocks a device supports. + - Decimal number of bytes per block. + + NT envirnonment variable contents. '<' and '>' are not part of the variable, + they are just used to make this help more readable. There should be no + spaces between the ';'. Extra spaces will break the variable. A '!' is + used to seperate multiple devices in a variable. + + EFI_WIN_NT_VIRTUAL_DISKS = + ;;[!...] + + EFI_WIN_NT_PHYSICAL_DISKS = + :;;[!...] + + Virtual Disks: These devices use a file to emulate a hard disk or removable + media device. + + Thus a 20 MB emulated hard drive would look like: + EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512 + + A 1.44MB emulated floppy with a block size of 1024 would look like: + EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024 + + Physical Disks: These devices use NT to open a real device in your system + + Thus a 120 MB floppy would look like: + EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512 + + Thus a standard CD-ROM floppy would look like: + EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048 + + EFI_WIN_NT_FILE_SYSTEM = + [!...] + + Mounting the two directories C:\FOO and C:\BAR would look like: + EFI_WIN_NT_FILE_SYSTEM=c:\foo!c:\bar + + EFI_WIN_NT_CONSOLE = + + + Declaring a text console window with the title "My EFI Console" woild look like: + EFI_WIN_NT_CONSOLE=My EFI Console + + EFI_WIN_NT_UGA = + [!...] + + Declaring a two UGA windows with resolutions of 800x600 and 1024x768 would look like: + Example : EFI_WIN_NT_UGA=800 600!1024 768 + + EFI_WIN_NT_SERIAL_PORT = + [!...] + + Declaring two serial ports on COM1 and COM2 would look like: + Example : EFI_WIN_NT_SERIAL_PORT=COM1!COM2 + + EFI_WIN_NT_PASS_THROUGH = + ;;; + + Declaring a base address of 0xE0000000 (used for PCI Express devices) + and having NT32 talk to a device located at bus 0, device 1, function 0: + Example : EFI_WIN_NT_PASS_THROUGH=E000000;0;1;0 + +---*/ + +#include "WinNtBusDriver.h" +//#include "PciHostBridge.h" + +// +// Define GUID for the WinNt Bus Driver +// +static EFI_GUID gWinNtBusDriverGuid = { + 0x419f582, 0x625, 0x4531, 0x8a, 0x33, 0x85, 0xa9, 0x96, 0x5c, 0x95, 0xbc +}; + +// +// DriverBinding protocol global +// +EFI_DRIVER_BINDING_PROTOCOL gWinNtBusDriverBinding = { + WinNtBusDriverBindingSupported, + WinNtBusDriverBindingStart, + WinNtBusDriverBindingStop, + 0x10, + NULL, + NULL +}; + +#define NT_PCD_ARRAY_SIZE (sizeof(mPcdEnvironment)/sizeof(NT_PCD_ENTRY)) + +// +// Table to map NT Environment variable to the GUID that should be in +// device path. +// +static NT_PCD_ENTRY mPcdEnvironment[] = { + PcdToken(PcdWinNtConsole), &gEfiWinNtConsoleGuid, + PcdToken(PcdWinNtUga), &gEfiWinNtUgaGuid, + PcdToken(PcdWinNtSerialPort), &gEfiWinNtSerialPortGuid, + PcdToken(PcdWinNtFileSystem), &gEfiWinNtFileSystemGuid, + PcdToken(PcdWinNtVirtualDisk), &gEfiWinNtVirtualDisksGuid, + PcdToken(PcdWinNtPhysicalDisk), &gEfiWinNtPhysicalDisksGuid, + PcdToken(PcdWinNtCpuModel), &gEfiWinNtCPUModelGuid, + PcdToken(PcdWinNtCpuSpeed), &gEfiWinNtCPUSpeedGuid, + PcdToken(PcdWinNtMemorySize), &gEfiWinNtMemoryGuid +}; + +VOID * +AllocateMemory ( + IN UINTN Size + ) +{ + EFI_STATUS Status; + VOID *Buffer; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + Size, + (VOID *)&Buffer + ); + if (EFI_ERROR (Status)) { + ASSERT (FALSE); + return NULL; + } + return Buffer; +} + + +EFI_STATUS +EFIAPI +WinNtBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: ControllerHandle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + UINTN Index; + + // + // Check the contents of the first Device Path Node of RemainingDevicePath to make sure + // it is a legal Device Path Node for this bus driver's children. + // + if (RemainingDevicePath != NULL) { + if (RemainingDevicePath->Type != HARDWARE_DEVICE_PATH || + RemainingDevicePath->SubType != HW_VENDOR_DP || + DevicePathNodeLength(RemainingDevicePath) != sizeof(WIN_NT_VENDOR_DEVICE_PATH_NODE)) { + return EFI_UNSUPPORTED; + } + + for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) { + if (CompareGuid (&((VENDOR_DEVICE_PATH *) RemainingDevicePath)->Guid, mPcdEnvironment[Index].DevicePathGuid)) { + break; + } + } + + if (Index >= NT_PCD_ARRAY_SIZE) { + return EFI_UNSUPPORTED; + } + } + + // + // Open the IO Abstraction(s) needed to perform the supported test + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + &ParentDevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiWinNtThunkProtocolGuid, + &WinNtThunk, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (Status == EFI_ALREADY_STARTED) { + return EFI_SUCCESS; + } + + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Since we call through WinNtThunk we need to make sure it's valid + // + Status = EFI_SUCCESS; + if (WinNtThunk->Signature != EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) { + Status = EFI_UNSUPPORTED; + } + + // + // Close the I/O Abstraction(s) used to perform the supported test + // + gBS->CloseProtocol ( + ControllerHandle, + &gEfiWinNtThunkProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + return Status; +} + +EFI_STATUS +EFIAPI +WinNtBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: ControllerHandle - add argument and description to function comment +// TODO: RemainingDevicePath - add argument and description to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_OUT_OF_RESOURCES - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + EFI_STATUS InstallStatus; + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + WIN_NT_BUS_DEVICE *WinNtBusDevice; + WIN_NT_IO_DEVICE *WinNtDevice; + UINTN Index; + CHAR16 *StartString; + CHAR16 *SubString; + UINT16 Count; + UINTN StringSize; + UINT16 ComponentName[MAX_NT_ENVIRNMENT_VARIABLE_LENGTH]; + WIN_NT_VENDOR_DEVICE_PATH_NODE *Node; + BOOLEAN CreateDevice; + CHAR16 *TempStr; + CHAR16 *PcdTempStr; + UINTN TempStrSize; + + // + // Test Feature Set and Binary Patchable Case + // + if (FeaturePcdGet (PcdWinNtFeatureFlag1)) { + TempStrSize = PatchPcdGet32(PcdWinNtBinaryPatch1) + PatchPcdGet32(PcdWinNtBinaryPatch2); + } + + if (0) { + // + // Test Dynamic and DynamicEx + // (Please add PcdWinNtConsole in "WinNtBusDriver.inf" before enable this code!!!) + // + PcdTempStr = PcdGetPtr (PcdWinNtConsole); + } + + // + // Test Dynamic Set and Dynamic Set Ex + // + PcdSet32 (PcdWinNtDynamicUINT32, 2006); + + Status = EFI_UNSUPPORTED; + + // + // Grab the protocols we need + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + &ParentDevicePath, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiWinNtThunkProtocolGuid, + &WinNtThunk, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) { + return Status; + } + + if (Status != EFI_ALREADY_STARTED) { + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (WIN_NT_BUS_DEVICE), + (VOID *) &WinNtBusDevice + ); + if (EFI_ERROR (Status)) { + return Status; + } + + WinNtBusDevice->Signature = WIN_NT_BUS_DEVICE_SIGNATURE; + WinNtBusDevice->ControllerNameTable = NULL; + + AddUnicodeString ( + "eng", + gWinNtBusDriverComponentName.SupportedLanguages, + &WinNtBusDevice->ControllerNameTable, + L"Windows Bus Controller" + ); + + Status = gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gWinNtBusDriverGuid, + WinNtBusDevice, + NULL + ); + if (EFI_ERROR (Status)) { + FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable); + gBS->FreePool (WinNtBusDevice); + return Status; + } + } + + // + // Loop on the Variable list. Parse each variable to produce a set of handles that + // represent virtual hardware devices. + // + InstallStatus = EFI_NOT_FOUND; + for (Index = 0; Index < NT_PCD_ARRAY_SIZE; Index++) { + PcdTempStr = (VOID *)LibPcdGetPtr (mPcdEnvironment[Index].Token); + ASSERT (PcdTempStr != NULL); + + TempStrSize = StrLen (PcdTempStr); + TempStr = AllocateMemory ((TempStrSize * sizeof (CHAR16)) + 1); + StrCpy (TempStr, PcdTempStr); + + StartString = TempStr; + + // + // Parse the envirnment variable into sub strings using '!' as a delimator. + // Each substring needs it's own handle to be added to the system. This code + // does not understand the sub string. Thats the device drivers job. + // + Count = 0; + while (*StartString != '\0') { + + // + // Find the end of the sub string + // + SubString = StartString; + while (*SubString != '\0' && *SubString != '!') { + SubString++; + } + + if (*SubString == '!') { + // + // Replace token with '\0' to make sub strings. If this is the end + // of the string SubString will already point to NULL. + // + *SubString = '\0'; + SubString++; + } + + CreateDevice = TRUE; + if (RemainingDevicePath != NULL) { + CreateDevice = FALSE; + Node = (WIN_NT_VENDOR_DEVICE_PATH_NODE *) RemainingDevicePath; + if (Node->VendorDevicePath.Header.Type == HARDWARE_DEVICE_PATH && + Node->VendorDevicePath.Header.SubType == HW_VENDOR_DP && + DevicePathNodeLength (&Node->VendorDevicePath.Header) == sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE) + ) { + if (CompareGuid (&Node->VendorDevicePath.Guid, mPcdEnvironment[Index].DevicePathGuid) && + Node->Instance == Count + ) { + CreateDevice = TRUE; + } + } + } + + if (CreateDevice) { + + // + // Allocate instance structure, and fill in parent information. + // + WinNtDevice = AllocateMemory (sizeof (WIN_NT_IO_DEVICE)); + if (WinNtDevice == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + WinNtDevice->Handle = NULL; + WinNtDevice->ControllerHandle = ControllerHandle; + WinNtDevice->ParentDevicePath = ParentDevicePath; + + WinNtDevice->WinNtIo.WinNtThunk = WinNtThunk; + + // + // Plus 2 to account for the NULL at the end of the Unicode string + // + StringSize = (UINTN) ((UINT8 *) SubString - (UINT8 *) StartString) + sizeof (CHAR16); + WinNtDevice->WinNtIo.EnvString = AllocateMemory (StringSize); + if (WinNtDevice->WinNtIo.EnvString != NULL) { + CopyMem (WinNtDevice->WinNtIo.EnvString, StartString, StringSize); + } + + WinNtDevice->ControllerNameTable = NULL; + + WinNtThunk->SPrintf (ComponentName, L"%s", WinNtDevice->WinNtIo.EnvString); + + WinNtDevice->DevicePath = WinNtBusCreateDevicePath ( + ParentDevicePath, + mPcdEnvironment[Index].DevicePathGuid, + Count + ); + if (WinNtDevice->DevicePath == NULL) { + gBS->FreePool (WinNtDevice); + return EFI_OUT_OF_RESOURCES; + } + + AddUnicodeString ( + "eng", + gWinNtBusDriverComponentName.SupportedLanguages, + &WinNtDevice->ControllerNameTable, + ComponentName + ); + + WinNtDevice->WinNtIo.TypeGuid = mPcdEnvironment[Index].DevicePathGuid; + WinNtDevice->WinNtIo.InstanceNumber = Count; + + WinNtDevice->Signature = WIN_NT_IO_DEVICE_SIGNATURE; + + Status = gBS->InstallMultipleProtocolInterfaces ( + &WinNtDevice->Handle, + &gEfiDevicePathProtocolGuid, + WinNtDevice->DevicePath, + &gEfiWinNtIoProtocolGuid, + &WinNtDevice->WinNtIo, + NULL + ); + if (EFI_ERROR (Status)) { + FreeUnicodeStringTable (WinNtDevice->ControllerNameTable); + gBS->FreePool (WinNtDevice); + } else { + // + // Open For Child Device + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiWinNtThunkProtocolGuid, + &WinNtThunk, + This->DriverBindingHandle, + WinNtDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (!EFI_ERROR (Status)) { + InstallStatus = EFI_SUCCESS; + } + } + } + + // + // Parse Next sub string. This will point to '\0' if we are at the end. + // + Count++; + StartString = SubString; + } + + gBS->FreePool (TempStr); + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +WinNtBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + + None + +--*/ +// TODO: This - add argument and description to function comment +// TODO: ControllerHandle - add argument and description to function comment +// TODO: NumberOfChildren - add argument and description to function comment +// TODO: ChildHandleBuffer - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_DEVICE_ERROR - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + UINTN Index; + BOOLEAN AllChildrenStopped; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + WIN_NT_BUS_DEVICE *WinNtBusDevice; + WIN_NT_IO_DEVICE *WinNtDevice; + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + + // + // Complete all outstanding transactions to Controller. + // Don't allow any new transaction to Controller to be started. + // + + if (NumberOfChildren == 0) { + // + // Close the bus driver + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gWinNtBusDriverGuid, + &WinNtBusDevice, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->UninstallMultipleProtocolInterfaces ( + ControllerHandle, + &gWinNtBusDriverGuid, + WinNtBusDevice, + NULL + ); + + FreeUnicodeStringTable (WinNtBusDevice->ControllerNameTable); + + gBS->FreePool (WinNtBusDevice); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiWinNtThunkProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + + gBS->CloseProtocol ( + ControllerHandle, + &gEfiDevicePathProtocolGuid, + This->DriverBindingHandle, + ControllerHandle + ); + return EFI_SUCCESS; + } + + AllChildrenStopped = TRUE; + + for (Index = 0; Index < NumberOfChildren; Index++) { + + Status = gBS->OpenProtocol ( + ChildHandleBuffer[Index], + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + This->DriverBindingHandle, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (!EFI_ERROR (Status)) { + + WinNtDevice = WIN_NT_IO_DEVICE_FROM_THIS (WinNtIo); + + Status = gBS->CloseProtocol ( + ControllerHandle, + &gEfiWinNtThunkProtocolGuid, + This->DriverBindingHandle, + WinNtDevice->Handle + ); + + Status = gBS->UninstallMultipleProtocolInterfaces ( + WinNtDevice->Handle, + &gEfiDevicePathProtocolGuid, + WinNtDevice->DevicePath, + &gEfiWinNtIoProtocolGuid, + &WinNtDevice->WinNtIo, + NULL + ); + + if (EFI_ERROR (Status)) { + gBS->OpenProtocol ( + ControllerHandle, + &gEfiWinNtThunkProtocolGuid, + (VOID **) &WinNtThunk, + This->DriverBindingHandle, + WinNtDevice->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + } else { + // + // Close the child handle + // + FreeUnicodeStringTable (WinNtDevice->ControllerNameTable); + gBS->FreePool (WinNtDevice); + } + } + + if (EFI_ERROR (Status)) { + AllChildrenStopped = FALSE; + } + } + + if (!AllChildrenStopped) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_DEVICE_PATH_PROTOCOL * +WinNtBusCreateDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath, + IN EFI_GUID *Guid, + IN UINT16 InstanceNumber + ) +/*++ + +Routine Description: + Create a device path node using Guid and InstanceNumber and append it to + the passed in RootDevicePath + +Arguments: + RootDevicePath - Root of the device path to return. + + Guid - GUID to use in vendor device path node. + + InstanceNumber - Instance number to use in the vendor device path. This + argument is needed to make sure each device path is unique. + +Returns: + + EFI_DEVICE_PATH_PROTOCOL + +--*/ +{ + WIN_NT_VENDOR_DEVICE_PATH_NODE DevicePath; + + DevicePath.VendorDevicePath.Header.Type = HARDWARE_DEVICE_PATH; + DevicePath.VendorDevicePath.Header.SubType = HW_VENDOR_DP; + SetDevicePathNodeLength (&DevicePath.VendorDevicePath.Header, sizeof (WIN_NT_VENDOR_DEVICE_PATH_NODE)); + + // + // The GUID defines the Class + // + CopyMem (&DevicePath.VendorDevicePath.Guid, Guid, sizeof (EFI_GUID)); + + // + // Add an instance number so we can make sure there are no Device Path + // duplication. + // + DevicePath.Instance = InstanceNumber; + + return AppendDevicePathNode ( + RootDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *) &DevicePath + ); +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.h b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.h new file mode 100644 index 0000000000..414465b8b2 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.h @@ -0,0 +1,297 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtBusDriver.h + +Abstract: + +This following section documents the envirnoment variables for the Win NT +build. These variables are used to define the (virtual) hardware +configuration of the NT environment + +A ! can be used to seperate multiple instances in a variable. Each +instance represents a seperate hardware device. + +EFI_WIN_NT_PHYSICAL_DISKS - maps to drives on your system +EFI_WIN_NT_VIRTUAL_DISKS - maps to a device emulated by a file +EFI_WIN_NT_FILE_SYSTEM - mouts a directory as a file system +EFI_WIN_NT_CONSOLE - make a logical comand line window (only one!) +EFI_WIN_NT_UGA - Builds UGA Windows of Width and Height +EFI_WIN_NT_SERIAL_PORT - maps physical serial ports +EFI_WIN_NT_PASS_THRU - associates a device with our PCI support + + ixed - Fixed disk like a hard drive. + emovable - Removable media like a floppy or CD-ROM. + Read nly - Write protected device. + Read rite - Read write device. + - Decimal number of blocks a device supports. + - Decimal number of bytes per block. + + NT envirnonment variable contents. '<' and '>' are not part of the variable, + they are just used to make this help more readable. There should be no + spaces between the ';'. Extra spaces will break the variable. A '!' is + used to seperate multiple devices in a variable. + + EFI_WIN_NT_VIRTUAL_DISKS = + ;;[!...] + + EFI_WIN_NT_PHYSICAL_DISKS = + :;;[!...] + + Virtual Disks: These devices use a file to emulate a hard disk or removable + media device. + + Thus a 20 MB emulated hard drive would look like: + EFI_WIN_NT_VIRTUAL_DISKS=FW;40960;512 + + A 1.44MB emulated floppy with a block size of 1024 would look like: + EFI_WIN_NT_VIRTUAL_DISKS=RW;1440;1024 + + Physical Disks: These devices use NT to open a real device in your system + + Thus a 120 MB floppy would look like: + EFI_WIN_NT_PHYSICAL_DISKS=B:RW;245760;512 + + Thus a standard CD-ROM floppy would look like: + EFI_WIN_NT_PHYSICAL_DISKS=Z:RO;307200;2048 + + EFI_WIN_NT_FILE_SYSTEM = + [!...] + + Mounting the two directories C:\FOO and C:\BAR would look like: + EFI_WIN_NT_FILE_SYSTEM=c:\foo!c:\bar + + EFI_WIN_NT_CONSOLE = + + + Declaring a text console window with the title "My EFI Console" woild look like: + EFI_WIN_NT_CONSOLE=My EFI Console + + EFI_WIN_NT_UGA = + [!...] + + Declaring a two UGA windows with resolutions of 800x600 and 1024x768 would look like: + Example : EFI_WIN_NT_UGA=800 600!1024 768 + + EFI_WIN_NT_SERIAL_PORT = + [!...] + + Declaring two serial ports on COM1 and COM2 would look like: + Example : EFI_WIN_NT_SERIAL_PORT=COM1!COM2 + + EFI_WIN_NT_PASS_THROUGH = + ;;; + + Declaring a base address of 0xE0000000 (used for PCI Express devices) + and having NT32 talk to a device located at bus 0, device 1, function 0: + Example : EFI_WIN_NT_PASS_THROUGH=E000000;0;1;0 + +---*/ + +#ifndef __NT_BUS_DRIVER_H__ +#define __NT_BUS_DRIVER_H__ + + + +// +// WinNt Bus Driver Global Variables +// +extern EFI_DRIVER_BINDING_PROTOCOL gWinNtBusDriverBinding; +extern EFI_COMPONENT_NAME_PROTOCOL gWinNtBusDriverComponentName; + +// +// WinNt Bus Controller Structure +// +#define WIN_NT_BUS_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('N', 'T', 'B', 'D') + +typedef struct { + UINT64 Signature; + EFI_UNICODE_STRING_TABLE *ControllerNameTable; +} WIN_NT_BUS_DEVICE; + +// +// WinNt Child Device Controller Structure +// +#define WIN_NT_IO_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('N', 'T', 'V', 'D') + +typedef struct { + UINT64 Signature; + EFI_HANDLE Handle; + EFI_WIN_NT_IO_PROTOCOL WinNtIo; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + // + // Private data about the parent + // + EFI_HANDLE ControllerHandle; + EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; + + EFI_UNICODE_STRING_TABLE *ControllerNameTable; + +} WIN_NT_IO_DEVICE; + +#define WIN_NT_IO_DEVICE_FROM_THIS(a) \ + CR(a, WIN_NT_IO_DEVICE, WinNtIo, WIN_NT_IO_DEVICE_SIGNATURE) + +// +// This is the largest env variable we can parse +// +#define MAX_NT_ENVIRNMENT_VARIABLE_LENGTH 512 + +typedef struct { + UINTN Token; + EFI_GUID *DevicePathGuid; +} NT_PCD_ENTRY; + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + UINT32 Instance; +} WIN_NT_VENDOR_DEVICE_PATH_NODE; + +EFI_STATUS +EFIAPI +CpuIoInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + SystemTable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// Driver Binding Protocol function prototypes +// +EFI_STATUS +EFIAPI +WinNtBusDriverBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtBusDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ParentHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + ParentHandle - TODO: add argument description + RemainingDevicePath - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtBusDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE Handle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + Handle - TODO: add argument description + NumberOfChildren - TODO: add argument description + ChildHandleBuffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +// +// WinNt Bus Driver private worker functions +// +EFI_DEVICE_PATH_PROTOCOL * +WinNtBusCreateDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *RootDevicePath, + IN EFI_GUID *Guid, + IN UINT16 InstanceNumber + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + RootDevicePath - TODO: add argument description + Guid - TODO: add argument description + InstanceNumber - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + + +#endif diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.mbd new file mode 100644 index 0000000000..eb50771993 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.mbd @@ -0,0 +1,43 @@ + + + + + WinNtBusDriver + BD7E9A27-D6C5-416a-B245-5F507D95B2BD + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-13 17:02 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + BaseLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + UefiDriverModelLib + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxePcdLib + DxeMemoryAllocationLib + UefiDevicePathLib + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.msa new file mode 100644 index 0000000000..56ce4337bb --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.msa @@ -0,0 +1,167 @@ + + + + + WinNtBusDriver + UEFI_DRIVER + BS_DRIVER + BD7E9A27-D6C5-416a-B245-5F507D95B2BD + 0 + Component description file for WinNtBusDriver module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-13 17:02 + 2006-03-19 15:17 + + + DebugLib + BaseLib + UefiDriverModelLib + UefiDriverEntryPoint + UefiLib + PcdLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + DevicePathLib + + + WinNtBusDriver.h + WinNtBusDriver.c + ComponentName.c + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + WinNtIo + WinNtThunk + DevicePath + Pcd + + + + WinNtVirtualDisks + + + WinNtPhysicalDisks + + + WinNtFileSystem + + + WinNtSerialPort + + + WinNtUga + + + WinNtConsole + + + WinNtMemory + + + WinNtCPUModel + + + WinNtCPUSpeed + + + + + + + + gWinNtBusDriverBinding + gWinNtBusDriverComponentName + + + + + PcdWinNtConsole + 0x0000100a + VOID* + + + PcdWinNtUga + 0x00001003 + VOID* + + + PcdWinNtSerialPort + 0x00001002 + VOID* + + + PcdWinNtFileSystem + 0x00001004 + VOID* + + + PcdWinNtVirtualDisk + 0x00001001 + VOID* + + + PcdWinNtPhysicalDisk + 0x00001000 + VOID* + + + PcdWinNtCpuModel + 0x00001007 + VOID* + + + PcdWinNtCpuSpeed + 0x00001008 + VOID* + + + PcdWinNtMemorySize + 0x00001005 + VOID* + + + PcdWinNtBinaryPatch1 + 0x0001000b + UINT32 + + + PcdWinNtBinaryPatch2 + 0x0001000c + UINT32 + + + PcdWinNtFeatureFlag1 + 0x0001000d + BOOLEAN + + + PcdWinNtDynamicUINT32 + 0x0001000e + UINT32 + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/build.xml new file mode 100644 index 0000000000..93d853bfd1 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Bus/WinNtBusDriver/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.c b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.c new file mode 100644 index 0000000000..394ca6e717 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.c @@ -0,0 +1,129 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Metronome.c + +Abstract: + + NT Emulation Metronome Architectural Protocol Driver as defined in DXE CIS + +--*/ + +#include "Metronome.h" + +// +// Global Variables +// +EFI_METRONOME_ARCH_PROTOCOL mMetronome = { + WinNtMetronomeDriverWaitForTick, + TICK_PERIOD +}; + +// +// Worker Functions +// + +EFI_STATUS +EFIAPI +WinNtMetronomeDriverWaitForTick ( + IN EFI_METRONOME_ARCH_PROTOCOL *This, + IN UINT32 TickNumber + ) +/*++ + +Routine Description: + + The WaitForTick() function waits for the number of ticks specified by + TickNumber from a known time source in the platform. If TickNumber of + ticks are detected, then EFI_SUCCESS is returned. The actual time passed + between entry of this function and the first tick is between 0 and + TickPeriod 100 nS units. If you want to guarantee that at least TickPeriod + time has elapsed, wait for two ticks. This function waits for a hardware + event to determine when a tick occurs. It is possible for interrupt + processing, or exception processing to interrupt the execution of the + WaitForTick() function. Depending on the hardware source for the ticks, it + is possible for a tick to be missed. This function cannot guarantee that + ticks will not be missed. If a timeout occurs waiting for the specified + number of ticks, then EFI_TIMEOUT is returned. + +Arguments: + + This - The EFI_METRONOME_ARCH_PROTOCOL instance. + TickNumber - Number of ticks to wait. + +Returns: + + EFI_SUCCESS - The wait for the number of ticks specified by TickNumber + succeeded. + +--*/ +{ + UINT64 SleepTime; + + // + // Calculate the time to sleep. Win API smallest unit to sleep is 1 millisec + // Tick Period is in 100ns units, divide by 10000 to convert to ms + // + SleepTime = DivU64x32 (MultU64x32 ((UINT64) TickNumber, TICK_PERIOD) + 9999, 10000); + gWinNt->Sleep ((UINT32) SleepTime); + + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +WinNtMetronomeDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initialize the Metronome Architectural Protocol driver + +Arguments: + + ImageHandle - ImageHandle of the loaded driver + + + SystemTable - Pointer to the System Table + +Returns: + + EFI_SUCCESS - Metronome Architectural Protocol created + + EFI_OUT_OF_RESOURCES - Not enough resources available to initialize driver. + + EFI_DEVICE_ERROR - A device error occured attempting to initialize the driver. + +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + + // + // Install the Metronome Architectural Protocol onto a new handle + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiMetronomeArchProtocolGuid, + EFI_NATIVE_INTERFACE, + &mMetronome + ); + + return Status; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.dxs b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.dxs new file mode 100644 index 0000000000..d11f48a5c9 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Metronome.dxs + +Abstract: + + Dependency expression source file. + +--*/ + +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.h b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.h new file mode 100644 index 0000000000..d89a149a1c --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.h @@ -0,0 +1,84 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Metronome.h + +Abstract: + + NT Emulation Metronome Architectural Protocol Driver as defined in DXE CIS + +--*/ + +#ifndef _NT_THUNK_METRONOME_H_ +#define _NT_THUNK_METRONOME_H_ + + + +// +// Period of on tick in 100 nanosecond units +// +#define TICK_PERIOD 2000 + +// +// Function Prototypes +// + +EFI_STATUS +EFIAPI +WinNtMetronomeDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + SystemTable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtMetronomeDriverWaitForTick ( + IN EFI_METRONOME_ARCH_PROTOCOL *This, + IN UINT32 TickNumber + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + TickNumber - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.mbd new file mode 100644 index 0000000000..f510b4250d --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.mbd @@ -0,0 +1,45 @@ + + + + + Metronome + 154CAB4A-52B5-46CD-99C3-4368ABBACFFD + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + DxeHobLib + BaseLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeWinNtLib + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.msa new file mode 100644 index 0000000000..0966e8294c --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/Metronome.msa @@ -0,0 +1,61 @@ + + + + + Metronome + DXE_DRIVER + BS_DRIVER + 154CAB4A-52B5-46CD-99C3-4368ABBACFFD + 0 + Component description file for Metronome module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + BaseLib + DebugLib + UefiLib + UefiDriverEntryPoint + WinNtLib + MemoryAllocationLib + UefiBootServicesTableLib + + + Metronome.c + Metronome.h + Metronome.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + Metronome + + + + WinNtMetronomeDriverInitialize + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/build.xml new file mode 100644 index 0000000000..5922fac8f1 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Metronome/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.c b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.c new file mode 100644 index 0000000000..b705ee6874 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.c @@ -0,0 +1,391 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RealTimeClock.c + +Abstract: + + NT Emulation Architectural Protocol Driver as defined in Tiano + +--*/ + + + +BOOLEAN +DayValid ( + IN EFI_TIME *Time + ); + +BOOLEAN +IsLeapYear ( + IN EFI_TIME *Time + ); + +EFI_STATUS +RtcTimeFieldsValid ( + IN EFI_TIME *Time + ); + +EFI_STATUS +EFIAPI +InitializeRealTimeClock ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +STATIC +EFI_STATUS +EFIAPI +WinNtGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL + ) +/*++ + +Routine Description: + Service routine for RealTimeClockInstance->GetTime + +Arguments: + + Time - A pointer to storage that will receive a snapshot of the current time. + + Capabilities - A pointer to storage that will receive the capabilities of the real time clock + in the platform. This includes the real time clock's resolution and accuracy. + All reported device capabilities are rounded up. This is an OPTIONAL argument. + +Returns: + + EFI_SUCEESS - The underlying GetSystemTime call occurred and returned + Note that in the NT32 emulation, the GetSystemTime call has no return value + thus you will always receive a EFI_SUCCESS on this. + +--*/ +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + SYSTEMTIME SystemTime; + TIME_ZONE_INFORMATION TimeZone; + + // + // Check parameter for null pointer + // + if (Time == NULL) { + return EFI_INVALID_PARAMETER; + + } + + gWinNt->GetLocalTime (&SystemTime); + gWinNt->GetTimeZoneInformation (&TimeZone); + + Time->Year = (UINT16) SystemTime.wYear; + Time->Month = (UINT8) SystemTime.wMonth; + Time->Day = (UINT8) SystemTime.wDay; + Time->Hour = (UINT8) SystemTime.wHour; + Time->Minute = (UINT8) SystemTime.wMinute; + Time->Second = (UINT8) SystemTime.wSecond; + Time->Nanosecond = (UINT32) (SystemTime.wMilliseconds * 1000000); + Time->TimeZone = (INT16) TimeZone.Bias; + + if (Capabilities != NULL) { + Capabilities->Resolution = 1; + Capabilities->Accuracy = 50000000; + Capabilities->SetsToZero = FALSE; + } + + Time->Daylight = 0; + if (TimeZone.StandardDate.wMonth) { + Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSetTime ( + IN EFI_TIME *Time + ) +/*++ + +Routine Description: + Service routine for RealTimeClockInstance->SetTime + +Arguments: + + Time - A pointer to storage containing the time and date information to + program into the real time clock. + +Returns: + + EFI_SUCEESS - The operation completed successfully. + + EFI_INVALID_PARAMETER - One of the fields in Time is out of range. + + EFI_DEVICE_ERROR - The operation could not be complete due to a device error. + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + TIME_ZONE_INFORMATION TimeZone; + EFI_STATUS Status; + SYSTEMTIME SystemTime; + BOOL Flag; + + if (Time == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Make sure that the time fields are valid + // + Status = RtcTimeFieldsValid (Time); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Set Daylight savings time information and Time Zone + // + gWinNt->GetTimeZoneInformation (&TimeZone); + TimeZone.StandardDate.wMonth = Time->Daylight; + TimeZone.Bias = Time->TimeZone; + gWinNt->SetTimeZoneInformation (&TimeZone); + + SystemTime.wYear = Time->Year; + SystemTime.wMonth = Time->Month; + SystemTime.wDay = Time->Day; + SystemTime.wHour = Time->Hour; + SystemTime.wMinute = Time->Minute; + SystemTime.wSecond = Time->Second; + SystemTime.wMilliseconds = (INT16) (Time->Nanosecond / 1000000); + + Flag = gWinNt->SetLocalTime (&SystemTime); + + if (!Flag) { + return EFI_DEVICE_ERROR; + } else { + return EFI_SUCCESS; + } +} + +STATIC +EFI_STATUS +EFIAPI +WinNtGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ) +/*++ + +Routine Description: + Service routine for RealTimeClockInstance->GetWakeupTime + +Arguments: + This - Indicates the protocol instance structure. + + Enabled - Indicates if the alarm is currently enabled or disabled. + + Pending - Indicates if the alarm signal is pending and requires + acknowledgement. + + Time - The current alarm setting. + +Returns: + + EFI_SUCEESS - The operation completed successfully. + + EFI_DEVICE_ERROR - The operation could not be complete due to a device error. + + EFI_UNSUPPORTED - The operation is not supported on this platform. + +--*/ +{ + return EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSetWakeupTime ( + IN BOOLEAN Enable, + OUT EFI_TIME *Time + ) +/*++ + +Routine Description: + Service routine for RealTimeClockInstance->SetWakeupTime + +Arguments: + + Enabled - Enable or disable the wakeup alarm. + + Time - If enable is TRUE, the time to set the wakup alarm for. + If enable is FALSE, then this parameter is optional, and + may be NULL. + +Returns: + + EFI_SUCEESS - The operation completed successfully. + + EFI_DEVICE_ERROR - The operation could not be complete due to a device error. + + EFI_INVALID_PARAMETER - A field in Time is out of range. + + EFI_UNSUPPORTED - The operation is not supported on this platform. + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +EFIAPI +InitializeRealTimeClock ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Install Real Time Clock Protocol + +Arguments: + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + EFI_SUCEESS - Real Time Clock Services are installed into the Runtime Services Table + +--*/ +// TODO: ImageHandle - add argument and description to function comment +// TODO: SystemTable - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + + SystemTable->RuntimeServices->GetTime = WinNtGetTime; + SystemTable->RuntimeServices->SetTime = WinNtSetTime; + SystemTable->RuntimeServices->GetWakeupTime = WinNtGetWakeupTime; + SystemTable->RuntimeServices->SetWakeupTime = WinNtSetWakeupTime; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiRealTimeClockArchProtocolGuid, + NULL, + NULL + ); + return Status; +} + +EFI_STATUS +RtcTimeFieldsValid ( + IN EFI_TIME *Time + ) +/*++ + +Routine Description: + + Arguments: + + Returns: +--*/ +// TODO: Time - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + if (Time->Year < 1998 || + Time->Year > 2099 || + Time->Month < 1 || + Time->Month > 12 || + (!DayValid (Time)) || + Time->Hour > 23 || + Time->Minute > 59 || + Time->Second > 59 || + Time->Nanosecond > 999999999 || + (!(Time->TimeZone == EFI_UNSPECIFIED_TIMEZONE || (Time->TimeZone >= -1440 && Time->TimeZone <= 1440))) || + (Time->Daylight & (~(EFI_TIME_ADJUST_DAYLIGHT | EFI_TIME_IN_DAYLIGHT))) + ) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +BOOLEAN +DayValid ( + IN EFI_TIME *Time + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Time - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + + INTN DayOfMonth[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + + if (Time->Day < 1 || + Time->Day > DayOfMonth[Time->Month - 1] || + (Time->Month == 2 && (!IsLeapYear (Time) && Time->Day > 28)) + ) { + return FALSE; + } + + return TRUE; +} + +BOOLEAN +IsLeapYear ( + IN EFI_TIME *Time + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Time - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + if (Time->Year % 4 == 0) { + if (Time->Year % 100 == 0) { + if (Time->Year % 400 == 0) { + return TRUE; + } else { + return FALSE; + } + } else { + return TRUE; + } + } else { + return FALSE; + } +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.dxs b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.dxs new file mode 100644 index 0000000000..01f441c562 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + RealTimeClock.dxs + +Abstract: + + Dependency expression source file. + +--*/ + +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.mbd new file mode 100644 index 0000000000..2eeac01ee9 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.mbd @@ -0,0 +1,45 @@ + + + + + RealTimeClock + 27F05AF5-1644-4EF4-8944-48C4F75675A0 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + DxeHobLib + DxeWinNtLib + BaseLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.msa new file mode 100644 index 0000000000..fd0761a7a0 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.msa @@ -0,0 +1,60 @@ + + + + + RealTimeClock + DXE_DRIVER + BS_DRIVER + 27F05AF5-1644-4EF4-8944-48C4F75675A0 + 0 + Component description file for RealTimeClock module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + BaseLib + DebugLib + UefiLib + UefiDriverEntryPoint + WinNtLib + MemoryAllocationLib + UefiBootServicesTableLib + + + RealTimeClock.c + RealTimeClock.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + RealTimeClock + + + + InitializeRealTimeClock + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/build.xml new file mode 100644 index 0000000000..b649e11eb5 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/RealTimeClock/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/Reset.dxs b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/Reset.dxs new file mode 100644 index 0000000000..5dfb191aef --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/Reset.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Reset.dxs + +Abstract: + + Dependency expression source file. + +--*/ + +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/Reset.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/Reset.mbd new file mode 100644 index 0000000000..817bc4ed18 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/Reset.mbd @@ -0,0 +1,45 @@ + + + + + Reset + BA929954-35B0-4dd3-90CD-9634BD7E1CF1 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + DxeHobLib + BaseLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeWinNtLib + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/Reset.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/Reset.msa new file mode 100644 index 0000000000..8887df13d9 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/Reset.msa @@ -0,0 +1,60 @@ + + + + + Reset + DXE_DRIVER + BS_DRIVER + BA929954-35B0-4dd3-90CD-9634BD7E1CF1 + 0 + description of file contents + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + BaseLib + DebugLib + UefiLib + UefiDriverEntryPoint + WinNtLib + MemoryAllocationLib + UefiBootServicesTableLib + + + Reset.c + Reset.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + Reset + + + + InitializeNtReset + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/build.xml new file mode 100644 index 0000000000..f924c6b261 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/reset.c b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/reset.c new file mode 100644 index 0000000000..d1b841de39 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Reset/reset.c @@ -0,0 +1,121 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Reset.c + +Abstract: + + Reset Architectural Protocol as defined in Tiano under NT Emulation + +--*/ + + + +EFI_STATUS +EFIAPI +InitializeNtReset ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +STATIC +EFI_STATUS +EFIAPI +WinNtResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData OPTIONAL + ); + + +EFI_STATUS +EFIAPI +InitializeNtReset ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + +Arguments: + + ImageHandle of the loaded driver + Pointer to the System Table + +Returns: + + Status +--*/ +// TODO: SystemTable - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + SystemTable->RuntimeServices->ResetSystem = WinNtResetSystem; + + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiResetArchProtocolGuid, + NULL, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData OPTIONAL + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ResetType - TODO: add argument description + ResetStatus - TODO: add argument description + DataSize - TODO: add argument description + ResetData - TODO: add argument description + +Returns: + + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + // + // BUGBUG Need to kill all console windows later + // + // + // Discard ResetType, always return 0 as exit code + // + gWinNt->ExitProcess (0); + + // + // Should never go here + // + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.c b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.c new file mode 100644 index 0000000000..18779a6b5e --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.c @@ -0,0 +1,597 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Timer.c + +Abstract: + + NT Emulation Timer Architectural Protocol Driver as defined in DXE CIS + + This Timer module uses an NT Thread to simulate the timer-tick driven + timer service. In the future, the Thread creation should possibly be + abstracted by the CPU architectural protocol + +--*/ + +#include "Timer.h" + +// +// Pointer to the CPU Architectural Protocol instance +// +EFI_CPU_ARCH_PROTOCOL *mCpu; + +// +// The Timer Architectural Protocol that this driver produces +// +EFI_TIMER_ARCH_PROTOCOL mTimer = { + WinNtTimerDriverRegisterHandler, + WinNtTimerDriverSetTimerPeriod, + WinNtTimerDriverGetTimerPeriod, + WinNtTimerDriverGenerateSoftInterrupt +}; + +// +// Define a global that we can use to shut down the NT timer thread when +// the timer is canceled. +// +BOOLEAN mCancelTimerThread = FALSE; + +// +// The notification function to call on every timer interrupt +// +EFI_TIMER_NOTIFY mTimerNotifyFunction = NULL; + +// +// The current period of the timer interrupt +// +UINT64 mTimerPeriod; + +// +// The thread handle for this driver +// +HANDLE mNtMainThreadHandle; + +// +// The timer value from the last timer interrupt +// +UINT32 mNtLastTick; + +// +// Critical section used to update varibles shared between the main thread and +// the timer interrupt thread. +// +CRITICAL_SECTION mNtCriticalSection; + +// +// Worker Functions +// +UINT mMMTimerThreadID = 0; + +VOID +CALLBACK +MMTimerThread ( + UINT wTimerID, + UINT msg, + DWORD dwUser, + DWORD dw1, + DWORD dw2 + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + wTimerID - TODO: add argument description + msg - TODO: add argument description + dwUser - TODO: add argument description + dw1 - TODO: add argument description + dw2 - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +{ + EFI_TPL OriginalTPL; + UINT32 CurrentTick; + UINT32 Delta; + EFI_TIMER_NOTIFY CallbackFunction; + BOOLEAN InterruptState; + + if (!mCancelTimerThread) { + + // + // Suspend the main thread until we are done + // + + gWinNt->SuspendThread (mNtMainThreadHandle); + + // + // If the timer thread is being canceled, then bail immediately. + // We check again here because there's a small window of time from when + // this thread was kicked off and when we suspended the main thread above. + // + if (mCancelTimerThread) { + gWinNt->ResumeThread (mNtMainThreadHandle); + gWinNt->timeKillEvent (wTimerID); + mMMTimerThreadID = 0; + return ; + } + + mCpu->GetInterruptState (mCpu, &InterruptState); + while (!InterruptState) { + // + // Resume the main thread + // + gWinNt->ResumeThread (mNtMainThreadHandle); + + // + // Wait for interrupts to be enabled. + // + mCpu->GetInterruptState (mCpu, &InterruptState); + while (!InterruptState) { + gWinNt->Sleep (0); + mCpu->GetInterruptState (mCpu, &InterruptState); + } + + // + // Suspend the main thread until we are done + // + gWinNt->SuspendThread (mNtMainThreadHandle); + mCpu->GetInterruptState (mCpu, &InterruptState); + } + + // + // Get the current system tick + // + CurrentTick = gWinNt->GetTickCount (); + Delta = CurrentTick - mNtLastTick; + mNtLastTick = CurrentTick; + + // + // If delay was more then 1 second, ignore it (probably debugging case) + // + if (Delta < 1000) { + + OriginalTPL = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL); + + // + // Inform the firmware of an "timer interrupt". The time + // expired since the last call is 10,000 times the number + // of ms. (or 100ns units) + // + gWinNt->EnterCriticalSection (&mNtCriticalSection); + CallbackFunction = mTimerNotifyFunction; + gWinNt->LeaveCriticalSection (&mNtCriticalSection); + + // + // Only invoke the callback function if a Non-NULL handler has been + // registered. Assume all other handlers are legal. + // + if (CallbackFunction != NULL) { + CallbackFunction ((UINT64) (Delta * 10000)); + } + + gBS->RestoreTPL (OriginalTPL); + + } + + // + // Resume the main thread + // + gWinNt->ResumeThread (mNtMainThreadHandle); + } else { + gWinNt->timeKillEvent (wTimerID); + mMMTimerThreadID = 0; + } + +} + +UINT +CreateNtTimer ( + VOID + ) +/*++ + +Routine Description: + + It is used to emulate a platform + timer-driver interrupt handler. + +Returns: + + Timer ID + +--*/ +// TODO: function comment is missing 'Arguments:' +{ + UINT32 SleepCount; + + // + // Set our thread priority higher than the "main" thread. + // + gWinNt->SetThreadPriority ( + gWinNt->GetCurrentThread (), + THREAD_PRIORITY_HIGHEST + ); + + // + // Calc the appropriate interval + // + gWinNt->EnterCriticalSection (&mNtCriticalSection); + SleepCount = (UINT32) (mTimerPeriod + 5000) / 10000; + gWinNt->LeaveCriticalSection (&mNtCriticalSection); + + return gWinNt->timeSetEvent ( + SleepCount, + 0, + MMTimerThread, + (DWORD_PTR) NULL, + TIME_PERIODIC | TIME_KILL_SYNCHRONOUS | TIME_CALLBACK_FUNCTION + ); + +} + +EFI_STATUS +EFIAPI +WinNtTimerDriverRegisterHandler ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction + ) +/*++ + +Routine Description: + + This function registers the handler NotifyFunction so it is called every time + the timer interrupt fires. It also passes the amount of time since the last + handler call to the NotifyFunction. If NotifyFunction is NULL, then the + handler is unregistered. If the handler is registered, then EFI_SUCCESS is + returned. If the CPU does not support registering a timer interrupt handler, + then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler + when a handler is already registered, then EFI_ALREADY_STARTED is returned. + If an attempt is made to unregister a handler when a handler is not registered, + then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to + register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR + is returned. + +Arguments: + + This - The EFI_TIMER_ARCH_PROTOCOL instance. + + NotifyFunction - The function to call when a timer interrupt fires. This + function executes at TPL_HIGH_LEVEL. The DXE Core will + register a handler for the timer interrupt, so it can know + how much time has passed. This information is used to + signal timer based events. NULL will unregister the handler. + +Returns: + + EFI_SUCCESS - The timer handler was registered. + + EFI_UNSUPPORTED - The platform does not support timer interrupts. + + EFI_ALREADY_STARTED - NotifyFunction is not NULL, and a handler is already + registered. + + EFI_INVALID_PARAMETER - NotifyFunction is NULL, and a handler was not + previously registered. + + EFI_DEVICE_ERROR - The timer handler could not be registered. + +--*/ +{ + // + // Check for invalid parameters + // + if (NotifyFunction == NULL && mTimerNotifyFunction == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (NotifyFunction != NULL && mTimerNotifyFunction != NULL) { + return EFI_ALREADY_STARTED; + } + + // + // Use Critical Section to update the notification function that is + // used from the timer interrupt thread. + // + gWinNt->EnterCriticalSection (&mNtCriticalSection); + + mTimerNotifyFunction = NotifyFunction; + + gWinNt->LeaveCriticalSection (&mNtCriticalSection); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +WinNtTimerDriverSetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +/*++ + +Routine Description: + + This function adjusts the period of timer interrupts to the value specified + by TimerPeriod. If the timer period is updated, then the selected timer + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. + If an error occurs while attempting to update the timer period, then the + timer hardware will be put back in its state prior to this call, and + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt + is disabled. This is not the same as disabling the CPU's interrupts. + Instead, it must either turn off the timer hardware, or it must adjust the + interrupt controller so that a CPU interrupt is not generated when the timer + interrupt fires. + +Arguments: + + This - The EFI_TIMER_ARCH_PROTOCOL instance. + + TimerPeriod - The rate to program the timer interrupt in 100 nS units. If + the timer hardware is not programmable, then EFI_UNSUPPORTED is + returned. If the timer is programmable, then the timer period + will be rounded up to the nearest timer period that is supported + by the timer hardware. If TimerPeriod is set to 0, then the + timer interrupts will be disabled. + +Returns: + + EFI_SUCCESS - The timer period was changed. + + EFI_UNSUPPORTED - The platform cannot change the period of the timer interrupt. + + EFI_DEVICE_ERROR - The timer period could not be changed due to a device error. + +--*/ +{ + + // + // If TimerPeriod is 0, then the timer thread should be canceled + // + if (TimerPeriod == 0) { + // + // Cancel the timer thread + // + gWinNt->EnterCriticalSection (&mNtCriticalSection); + + mCancelTimerThread = TRUE; + + gWinNt->LeaveCriticalSection (&mNtCriticalSection); + + // + // Wait for the timer thread to exit + // + + if (mMMTimerThreadID) { + gWinNt->timeKillEvent (mMMTimerThreadID); + } + + mMMTimerThreadID = 0; + + // + // Update the timer period + // + gWinNt->EnterCriticalSection (&mNtCriticalSection); + + mTimerPeriod = TimerPeriod; + + gWinNt->LeaveCriticalSection (&mNtCriticalSection); + + // + // NULL out the thread handle so it will be re-created if the timer is enabled again + // + + } else if ((TimerPeriod > TIMER_MINIMUM_VALUE) && (TimerPeriod < TIMER_MAXIMUM_VALUE)) { + // + // If the TimerPeriod is valid, then create and/or adjust the period of the timer thread + // + gWinNt->EnterCriticalSection (&mNtCriticalSection); + + mTimerPeriod = TimerPeriod; + + mCancelTimerThread = FALSE; + + gWinNt->LeaveCriticalSection (&mNtCriticalSection); + + // + // Get the starting tick location if we are just starting the timer thread + // + mNtLastTick = gWinNt->GetTickCount (); + + if (mMMTimerThreadID) { + gWinNt->timeKillEvent (mMMTimerThreadID); + } + + mMMTimerThreadID = 0; + + mMMTimerThreadID = CreateNtTimer (); + + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +WinNtTimerDriverGetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ) +/*++ + +Routine Description: + + This function retrieves the period of timer interrupts in 100 ns units, + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is + returned, then the timer is currently disabled. + +Arguments: + + This - The EFI_TIMER_ARCH_PROTOCOL instance. + + TimerPeriod - A pointer to the timer period to retrieve in 100 ns units. If + 0 is returned, then the timer is currently disabled. + +Returns: + + EFI_SUCCESS - The timer period was returned in TimerPeriod. + + EFI_INVALID_PARAMETER - TimerPeriod is NULL. + +--*/ +{ + if (TimerPeriod == NULL) { + return EFI_INVALID_PARAMETER; + } + + *TimerPeriod = mTimerPeriod; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +WinNtTimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ) +/*++ + +Routine Description: + + This function generates a soft timer interrupt. If the platform does not support soft + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned. + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler() + service, then a soft timer interrupt will be generated. If the timer interrupt is + enabled when this service is called, then the registered handler will be invoked. The + registered handler should not be able to distinguish a hardware-generated timer + interrupt from a software-generated timer interrupt. + +Arguments: + + This - The EFI_TIMER_ARCH_PROTOCOL instance. + +Returns: + + EFI_SUCCESS - The soft timer interrupt was generated. + + EFI_UNSUPPORTEDT - The platform does not support the generation of soft timer interrupts. + +--*/ +{ + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +WinNtTimerDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initialize the Timer Architectural Protocol driver + +Arguments: + + ImageHandle - ImageHandle of the loaded driver + + SystemTable - Pointer to the System Table + +Returns: + + EFI_SUCCESS - Timer Architectural Protocol created + + EFI_OUT_OF_RESOURCES - Not enough resources available to initialize driver. + + EFI_DEVICE_ERROR - A device error occured attempting to initialize the driver. + +--*/ +{ + EFI_STATUS Status; + UINTN Result; + EFI_HANDLE Handle; + + // + // Make sure the Timer Architectural Protocol is not already installed in the system + // + ASSERT_PROTOCOL_ALREADY_INSTALLED (NULL, &gEfiTimerArchProtocolGuid); + + // + // Get the CPU Architectural Protocol instance + // + Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, &mCpu); + ASSERT_EFI_ERROR (Status); + + // + // Get our handle so the timer tick thread can suspend + // + Result = gWinNt->DuplicateHandle ( + gWinNt->GetCurrentProcess (), + gWinNt->GetCurrentThread (), + gWinNt->GetCurrentProcess (), + &mNtMainThreadHandle, + 0, + FALSE, + DUPLICATE_SAME_ACCESS + ); + if (Result == 0) { + return EFI_DEVICE_ERROR; + } + + // + // Initialize Critical Section used to update variables shared between the main + // thread and the timer interrupt thread. + // + gWinNt->InitializeCriticalSection (&mNtCriticalSection); + + // + // Start the timer thread at the default timer period + // + Status = mTimer.SetTimerPeriod (&mTimer, DEFAULT_TIMER_TICK_DURATION); + if (EFI_ERROR (Status)) { + gWinNt->DeleteCriticalSection (&mNtCriticalSection); + return Status; + } + + // + // Install the Timer Architectural Protocol onto a new handle + // + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + &gEfiTimerArchProtocolGuid, + EFI_NATIVE_INTERFACE, + &mTimer + ); + if (EFI_ERROR (Status)) { + // + // Cancel the timer + // + mTimer.SetTimerPeriod (&mTimer, 0); + gWinNt->DeleteCriticalSection (&mNtCriticalSection); + return Status; + } + + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.dxs b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.dxs new file mode 100644 index 0000000000..6e6638331b --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Timer.dxs + +Abstract: + + Dependency expression source file. + +--*/ + + +#include +#include + +DEPENDENCY_START + EFI_CPU_ARCH_PROTOCOL_GUID +DEPENDENCY_END diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.h b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.h new file mode 100644 index 0000000000..218ece65a5 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.h @@ -0,0 +1,162 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Timer.h + +Abstract: + + NT Emulation Architectural Protocol Driver as defined in Tiano. + This Timer module uses an NT Thread to simulate the timer-tick driven + timer service. + +--*/ + +#ifndef _TIMER_H_ +#define _TIMER_H_ + + + + +// +// Legal timer value range in 100 ns units +// +#define TIMER_MINIMUM_VALUE 0 +#define TIMER_MAXIMUM_VALUE (0x100000000 - 1) + +// +// Default timer value in 100 ns units (10 ms) +// +#define DEFAULT_TIMER_TICK_DURATION 100000 + +// +// Function Prototypes +// +EFI_STATUS +EFIAPI +WinNtTimerDriverInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageHandle - TODO: add argument description + SystemTable - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtTimerDriverRegisterHandler ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + NotifyFunction - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtTimerDriverSetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + TimerPeriod - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtTimerDriverGetTimerPeriod ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + TimerPeriod - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +WinNtTimerDriverGenerateSoftInterrupt ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + This - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.mbd new file mode 100644 index 0000000000..3b8602d4f2 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.mbd @@ -0,0 +1,46 @@ + + + + + Timer + C3811036-710B-4E39-8CF1-0AF9BE3A8198 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + BaseDebugLibReportStatusCode + DxeHobLib + BaseLib + UefiLib + HiiLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + DxeWinNtLib + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.msa new file mode 100644 index 0000000000..d89ddf7433 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/Timer.msa @@ -0,0 +1,62 @@ + + + + + Timer + DXE_DRIVER + BS_DRIVER + C3811036-710B-4E39-8CF1-0AF9BE3A8198 + 0 + Component description file for Timer module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + BaseLib + DebugLib + UefiLib + UefiDriverEntryPoint + WinNtLib + MemoryAllocationLib + UefiBootServicesTableLib + + + Timer.h + Timer.c + Timer.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + Timer + Cpu + + + + WinNtTimerDriverInitialize + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/build.xml new file mode 100644 index 0000000000..fac1fa4061 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Chipset/Timer/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.c b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.c new file mode 100644 index 0000000000..8633327263 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.c @@ -0,0 +1,736 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Cpu.c + +Abstract: + + NT Emulation Architectural Protocol Driver as defined in Tiano. + This CPU module abstracts the interrupt subsystem of a platform and + the CPU-specific setjump/long pair. Other services are not implemented + in this driver. + +--*/ + +#include "CpuDriver.h" + +// +// This is the VFR compiler generated header file which defines the +// string identifiers. +// +#include STRING_DEFINES_FILE + +#define EFI_CPU_DATA_MAXIMUM_LENGTH 0x100 + +EFI_STATUS +EFIAPI +InitializeCpu ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +VOID +EFIAPI +WinNtIoProtocolNotifyFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +typedef union { + EFI_CPU_DATA_RECORD *DataRecord; + UINT8 *Raw; +} EFI_CPU_DATA_RECORD_BUFFER; + +EFI_SUBCLASS_TYPE1_HEADER mCpuDataRecordHeader = { + EFI_PROCESSOR_SUBCLASS_VERSION, // Version + sizeof (EFI_SUBCLASS_TYPE1_HEADER), // Header Size + 0, // Instance, Initialize later + EFI_SUBCLASS_INSTANCE_NON_APPLICABLE, // SubInstance + 0 // RecordType, Initialize later +}; + +// +// Service routines for the driver +// +STATIC +EFI_STATUS +EFIAPI +WinNtFlushCpuDataCache ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ) +/*++ + +Routine Description: + + This routine would provide support for flushing the CPU data cache. + In the case of NT emulation environment, this flushing is not necessary and + is thus not implemented. + +Arguments: + + Pointer to CPU Architectural Protocol interface + Start adddress in memory to flush + Length of memory to flush + Flush type + +Returns: + + Status + EFI_SUCCESS + +--*/ +// TODO: This - add argument and description to function comment +// TODO: FlushType - add argument and description to function comment +// TODO: EFI_UNSUPPORTED - add return value to function comment +{ + if (FlushType == EfiCpuFlushTypeWriteBackInvalidate) { + // + // Only WB flush is supported. We actually need do nothing on NT emulator + // environment. Classify this to follow EFI spec + // + return EFI_SUCCESS; + } + // + // Other flush types are not supported by NT emulator + // + return EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtEnableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +/*++ + +Routine Description: + + This routine provides support for emulation of the interrupt enable of the + the system. For our purposes, CPU enable is just a BOOLEAN that the Timer + Architectural Protocol observes in order to defer behaviour while in its + emulated interrupt, or timer tick. + +Arguments: + + Pointer to CPU Architectural Protocol interface + +Returns: + + Status + EFI_SUCCESS + +--*/ +// TODO: This - add argument and description to function comment +{ + CPU_ARCH_PROTOCOL_PRIVATE *Private; + + Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This); + Private->InterruptState = TRUE; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtDisableInterrupt ( + IN EFI_CPU_ARCH_PROTOCOL *This + ) +/*++ + +Routine Description: + + This routine provides support for emulation of the interrupt disable of the + the system. For our purposes, CPU enable is just a BOOLEAN that the Timer + Architectural Protocol observes in order to defer behaviour while in its + emulated interrupt, or timer tick. + +Arguments: + + Pointer to CPU Architectural Protocol interface + +Returns: + + Status + EFI_SUCCESS + +--*/ +// TODO: This - add argument and description to function comment +{ + CPU_ARCH_PROTOCOL_PRIVATE *Private; + + Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This); + Private->InterruptState = FALSE; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtGetInterruptState ( + IN EFI_CPU_ARCH_PROTOCOL *This, + OUT BOOLEAN *State + ) +/*++ + +Routine Description: + + This routine provides support for emulation of the interrupt disable of the + the system. For our purposes, CPU enable is just a BOOLEAN that the Timer + Architectural Protocol observes in order to defer behaviour while in its + emulated interrupt, or timer tick. + +Arguments: + + Pointer to CPU Architectural Protocol interface + +Returns: + + Status + EFI_SUCCESS + +--*/ +// TODO: This - add argument and description to function comment +// TODO: State - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + CPU_ARCH_PROTOCOL_PRIVATE *Private; + + if (State == NULL) { + return EFI_INVALID_PARAMETER; + } + + Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This); + *State = Private->InterruptState; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtInit ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_INIT_TYPE InitType + ) +/*++ + +Routine Description: + + This routine would support generation of a CPU INIT. At + present, this code does not provide emulation. + +Arguments: + + Pointer to CPU Architectural Protocol interface + INIT Type + +Returns: + + Status + EFI_UNSUPPORTED - not yet implemented + +--*/ +// TODO: This - add argument and description to function comment +// TODO: InitType - add argument and description to function comment +{ + CPU_ARCH_PROTOCOL_PRIVATE *Private; + + Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This); + return EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtRegisterInterruptHandler ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ) +/*++ + +Routine Description: + + This routine would support registration of an interrupt handler. At + present, this code does not provide emulation. + +Arguments: + + Pointer to CPU Architectural Protocol interface + Pointer to interrupt handlers + Interrupt type + +Returns: + + Status + EFI_UNSUPPORTED - not yet implemented + +--*/ +// TODO: This - add argument and description to function comment +// TODO: InterruptType - add argument and description to function comment +// TODO: InterruptHandler - add argument and description to function comment +{ + CPU_ARCH_PROTOCOL_PRIVATE *Private; + + // + // Do parameter checking for EFI spec conformance + // + if (InterruptType < 0 || InterruptType > 0xff) { + return EFI_UNSUPPORTED; + } + // + // Do nothing for Nt32 emulation + // + Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This); + return EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtGetTimerValue ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ) +/*++ + +Routine Description: + + This routine would support querying of an on-CPU timer. At present, + this code does not provide timer emulation. + +Arguments: + + This - Pointer to CPU Architectural Protocol interface + TimerIndex - Index of given CPU timer + TimerValue - Output of the timer + TimerPeriod - Output of the timer period + +Returns: + + EFI_UNSUPPORTED - not yet implemented + EFI_INVALID_PARAMETER - TimeValue is NULL + +--*/ +{ + if (TimerValue == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // No timer supported + // + return EFI_UNSUPPORTED; +} + +STATIC +EFI_STATUS +EFIAPI +WinNtSetMemoryAttributes ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +/*++ + +Routine Description: + + This routine would support querying of an on-CPU timer. At present, + this code does not provide timer emulation. + +Arguments: + + Pointer to CPU Architectural Protocol interface + Start address of memory region + The size in bytes of the memory region + The bit mask of attributes to set for the memory region + +Returns: + + Status + EFI_UNSUPPORTED - not yet implemented + +--*/ +// TODO: This - add argument and description to function comment +// TODO: BaseAddress - add argument and description to function comment +// TODO: Length - add argument and description to function comment +// TODO: Attributes - add argument and description to function comment +// TODO: EFI_INVALID_PARAMETER - add return value to function comment +{ + CPU_ARCH_PROTOCOL_PRIVATE *Private; + + // + // Check for invalid parameter for Spec conformance + // + if (Length == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Do nothing for Nt32 emulation + // + Private = CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS (This); + return EFI_UNSUPPORTED; +} + + +EFI_STATUS +EFIAPI +InitializeCpu ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Initialize the state information for the CPU Architectural Protocol + +Arguments: + + ImageHandle of the loaded driver + Pointer to the System Table + +Returns: + + Status + + EFI_SUCCESS - protocol instance can be published + EFI_OUT_OF_RESOURCES - cannot allocate protocol data structure + EFI_DEVICE_ERROR - cannot create the thread + +--*/ +// TODO: SystemTable - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_EVENT Event; + CPU_ARCH_PROTOCOL_PRIVATE *Private; + VOID *Registration; + + Status = gBS->AllocatePool ( + EfiBootServicesData, + sizeof (CPU_ARCH_PROTOCOL_PRIVATE), + &Private + ); + ASSERT_EFI_ERROR (Status); + + Private->Signature = CPU_ARCH_PROT_PRIVATE_SIGNATURE; + Private->Cpu.FlushDataCache = WinNtFlushCpuDataCache; + Private->Cpu.EnableInterrupt = WinNtEnableInterrupt; + Private->Cpu.DisableInterrupt = WinNtDisableInterrupt; + Private->Cpu.GetInterruptState = WinNtGetInterruptState; + Private->Cpu.Init = WinNtInit; + Private->Cpu.RegisterInterruptHandler = WinNtRegisterInterruptHandler; + Private->Cpu.GetTimerValue = WinNtGetTimerValue; + Private->Cpu.SetMemoryAttributes = WinNtSetMemoryAttributes; + + Private->Cpu.NumberOfTimers = 0; + Private->Cpu.DmaBufferAlignment = 4; + + Private->InterruptState = TRUE; + + Private->CpuIo.Mem.Read = CpuMemoryServiceRead; + Private->CpuIo.Mem.Write = CpuMemoryServiceWrite; + Private->CpuIo.Io.Read = CpuIoServiceRead; + Private->CpuIo.Io.Write = CpuIoServiceWrite; + + + Private->Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Private->Handle, + &gEfiCpuArchProtocolGuid, &Private->Cpu, + &gEfiCpuIoProtocolGuid, &Private->CpuIo, + NULL + ); + ASSERT_EFI_ERROR (Status); + + // + // Install notify function to store processor data to HII database and data hub. + // + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + WinNtIoProtocolNotifyFunction, + ImageHandle, + &Event + ); + ASSERT (!EFI_ERROR (Status)); + + Status = gBS->RegisterProtocolNotify ( + &gEfiWinNtIoProtocolGuid, + Event, + &Registration + ); + ASSERT (!EFI_ERROR (Status)); + + // + // Should be at EFI_D_INFO, but lets us now things are running + // + DEBUG ((EFI_D_ERROR, "CPU Architectural Protocol Loaded\n")); + + + + return Status; +} + +UINTN +Atoi ( + CHAR16 *String + ) +/*++ + +Routine Description: + Convert a unicode string to a UINTN + +Arguments: + String - Unicode string. + +Returns: + UINTN of the number represented by String. + +--*/ +{ + UINTN Number; + CHAR16 *Str; + + // + // skip preceeding white space + // + Str = String; + while ((*Str) && (*Str == ' ' || *Str == '"')) { + Str++; + } + // + // Convert ot a Number + // + Number = 0; + while (*Str != '\0') { + if ((*Str >= '0') && (*Str <= '9')) { + Number = (Number * 10) +*Str - '0'; + } else { + break; + } + + Str++; + } + + return Number; +} + +VOID +EFIAPI +WinNtIoProtocolNotifyFunction ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + This function will log processor version and frequency data to data hub. + +Arguments: + Event - Event whose notification function is being invoked. + Context - Pointer to the notification function's context. + +Returns: + None. + +--*/ +{ + EFI_STATUS Status; + EFI_CPU_DATA_RECORD_BUFFER RecordBuffer; + EFI_DATA_RECORD_HEADER *Record; + EFI_SUBCLASS_TYPE1_HEADER *DataHeader; + UINT32 HeaderSize; + UINT32 TotalSize; + UINTN HandleCount; + UINTN HandleIndex; + UINT64 MonotonicCount; + BOOLEAN RecordFound; + EFI_HANDLE *HandleBuffer; + EFI_WIN_NT_IO_PROTOCOL *WinNtIo; + EFI_DATA_HUB_PROTOCOL *DataHub; + EFI_HII_PROTOCOL *Hii; + EFI_HII_HANDLE StringHandle; + EFI_HII_PACKAGES *PackageList; + STRING_REF Token; + + DataHub = NULL; + Token = 0; + MonotonicCount = 0; + RecordFound = FALSE; + + // + // Retrieve the list of all handles from the handle database + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + &gEfiWinNtIoProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return ; + } + // + // Locate HII protocol + // + Status = gBS->LocateProtocol (&gEfiHiiProtocolGuid, NULL, &Hii); + if (EFI_ERROR (Status)) { + return ; + } + // + // Locate DataHub protocol. + // + Status = gBS->LocateProtocol (&gEfiDataHubProtocolGuid, NULL, &DataHub); + if (EFI_ERROR (Status)) { + return ; + } + // + // Initialize data record header + // + mCpuDataRecordHeader.Instance = 1; + HeaderSize = sizeof (EFI_SUBCLASS_TYPE1_HEADER); + + RecordBuffer.Raw = AllocatePool (HeaderSize + EFI_CPU_DATA_MAXIMUM_LENGTH); + if (RecordBuffer.Raw == NULL) { + return ; + } + + CopyMem (RecordBuffer.Raw, &mCpuDataRecordHeader, HeaderSize); + + // + // Search the Handle array to find the CPU model and speed information + // + for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) { + Status = gBS->OpenProtocol ( + HandleBuffer[HandleIndex], + &gEfiWinNtIoProtocolGuid, + &WinNtIo, + Context, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + continue; + } + + if ((WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) && + CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtCPUModelGuid) + ) { + // + // Check if this record has been stored in data hub + // + do { + Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record); + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1); + if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) && + (DataHeader->RecordType == ProcessorVersionRecordType) + ) { + RecordFound = TRUE; + } + } + } while (MonotonicCount != 0); + + if (RecordFound) { + RecordFound = FALSE; + continue; + } + // + // Initialize strings to HII database + // + PackageList = PreparePackages (1, &gEfiProcessorProducerGuid, STRING_ARRAY_NAME); + + Status = Hii->NewPack (Hii, PackageList, &StringHandle); + ASSERT (!EFI_ERROR (Status)); + + gBS->FreePool (PackageList); + + // + // Store processor version data record to data hub + // + Status = Hii->NewString (Hii, NULL, StringHandle, &Token, WinNtIo->EnvString); + ASSERT (!EFI_ERROR (Status)); + + RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorVersionRecordType; + RecordBuffer.DataRecord->VariableRecord.ProcessorVersion = Token; + TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_VERSION_DATA); + + Status = DataHub->LogData ( + DataHub, + &gEfiProcessorSubClassGuid, + &gEfiProcessorProducerGuid, + EFI_DATA_RECORD_CLASS_DATA, + RecordBuffer.Raw, + TotalSize + ); + } + + if ((WinNtIo->WinNtThunk->Signature == EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE) && + CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtCPUSpeedGuid) + ) { + // + // Check if this record has been stored in data hub + // + do { + Status = DataHub->GetNextRecord (DataHub, &MonotonicCount, NULL, &Record); + if (Record->DataRecordClass == EFI_DATA_RECORD_CLASS_DATA) { + DataHeader = (EFI_SUBCLASS_TYPE1_HEADER *) (Record + 1); + if (CompareGuid (&Record->DataRecordGuid, &gEfiProcessorSubClassGuid) && + (DataHeader->RecordType == ProcessorCoreFrequencyRecordType) + ) { + RecordFound = TRUE; + } + } + } while (MonotonicCount != 0); + + if (RecordFound) { + RecordFound = FALSE; + continue; + } + // + // Store CPU frequency data record to data hub + // + RecordBuffer.DataRecord->DataRecordHeader.RecordType = ProcessorCoreFrequencyRecordType; + RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Value = (UINT16) Atoi (WinNtIo->EnvString); + RecordBuffer.DataRecord->VariableRecord.ProcessorCoreFrequency.Exponent = 6; + TotalSize = HeaderSize + sizeof (EFI_PROCESSOR_CORE_FREQUENCY_DATA); + + Status = DataHub->LogData ( + DataHub, + &gEfiProcessorSubClassGuid, + &gEfiProcessorProducerGuid, + EFI_DATA_RECORD_CLASS_DATA, + RecordBuffer.Raw, + TotalSize + ); + + gBS->FreePool (RecordBuffer.Raw); + } + + gBS->CloseProtocol ( + HandleBuffer[HandleIndex], + &gEfiWinNtIoProtocolGuid, + Context, + NULL + ); + } +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.dxs b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.dxs new file mode 100644 index 0000000000..4f87af4ca9 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Cpu.dxs + +Abstract: + + Dependency expression source file. + +--*/ + +#include +#include + +DEPENDENCY_START + EFI_DATA_HUB_PROTOCOL_GUID AND + EFI_HII_PROTOCOL_GUID +DEPENDENCY_END diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.mbd new file mode 100644 index 0000000000..f2d25fecb0 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.mbd @@ -0,0 +1,46 @@ + + + + + Cpu + ee993080-5197-4d4e-b63c-f1f7413e33ce + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-23 16:17 + + + UefiBootServicesTableLib + BaseLib + UefiLib + HiiLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.msa b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.msa new file mode 100644 index 0000000000..36fbd12401 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Cpu.msa @@ -0,0 +1,86 @@ + + + + + Cpu + DXE_DRIVER + BS_DRIVER + ee993080-5197-4d4e-b63c-f1f7413e33ce + 0 + Component description file for Cpu module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-23 16:17 + + + BaseLib + DebugLib + HiiLib + UefiLib + UefiDriverEntryPoint + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + Strings.uni + CpuDriver.h + Cpu.c + CpuIo.c + Cpu.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + Cpu + CpuIo + Hii + DataHub + WinNtIo + + + ProcessorVersion + ProcessorCoreFrequency + + + + ProcessorProducer + + + ProcessorSubClass + + + WinNtCPUModel + + + WinNtCPUSpeed + + + + + InitializeCpu + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/CpuDriver.h b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/CpuDriver.h new file mode 100644 index 0000000000..e5b952f938 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/CpuDriver.h @@ -0,0 +1,97 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CpuDriver.h + +Abstract: + + NT Emulation Architectural Protocol Driver as defined in Tiano. + +--*/ + +#ifndef _CPU_ARCHITECTURAL_PROTOCOL_DRIVER_H_ +#define _CPU_ARCHITECTURAL_PROTOCOL_DRIVER_H_ + + + +extern UINT8 STRING_ARRAY_NAME[]; + +// +// Internal Data Structures +// +#define CPU_ARCH_PROT_PRIVATE_SIGNATURE EFI_SIGNATURE_32 ('c', 'a', 'p', 'd') + +typedef struct { + UINTN Signature; + EFI_HANDLE Handle; + + EFI_CPU_ARCH_PROTOCOL Cpu; + EFI_CPU_IO_PROTOCOL CpuIo; + + // + // Local Data for CPU interface goes here + // + CRITICAL_SECTION NtCriticalSection; + BOOLEAN InterruptState; + +} CPU_ARCH_PROTOCOL_PRIVATE; + +#define CPU_ARCH_PROTOCOL_PRIVATE_DATA_FROM_THIS(a) \ + CR (a, \ + CPU_ARCH_PROTOCOL_PRIVATE, \ + Cpu, \ + CPU_ARCH_PROT_PRIVATE_SIGNATURE \ + ) + +EFI_STATUS +EFIAPI +CpuMemoryServiceRead ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +CpuMemoryServiceWrite ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +EFI_STATUS +EFIAPI +CpuIoServiceRead ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ); + +EFI_STATUS +EFIAPI +CpuIoServiceWrite ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ); + + +#endif diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/CpuIo.c b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/CpuIo.c new file mode 100644 index 0000000000..4aaa431d54 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/CpuIo.c @@ -0,0 +1,335 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + CpuIo.c + +Abstract: + + This is the code that publishes the CPU I/O Protocol. + The intent herein is to have a single I/O service that can load + as early as possible, extend into runtime, and be layered upon by + the implementations of architectural protocols and the PCI Root + Bridge I/O Protocol. + +--*/ + +#include + +#define IA32_MAX_IO_ADDRESS 0xFFFF +#define IA32_MAX_MEM_ADDRESS 0xFFFFFFFF + +EFI_CPU_IO_PROTOCOL mCpuIoProtocol; + +EFI_STATUS +CpuIoCheckAddressRange ( + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer, + IN UINT64 Limit + ); + +EFI_STATUS +EFIAPI +CpuMemoryServiceRead ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform the Memory Access Read service for the CPU I/O Protocol + +Arguments: + + Pointer to an instance of the CPU I/O Protocol + Width of the Memory Access + Address of the Memory access + Count of the number of accesses to perform + Pointer to the buffer to read or write from memory + +Returns: + + Status + + EFI_SUCCESS - The data was read from or written to the EFI + System. + EFI_INVALID_PARAMETER - Width is invalid for this EFI System. + EFI_INVALID_PARAMETER - Buffer is NULL. + EFI_UNSUPPORTED - The Buffer is not aligned for the given Width. + EFI_UNSUPPORTED - The address range specified by Address, Width, + and Count is not valid for this EFI System. + +--*/ +// TODO: This - add argument and description to function comment +{ + EFI_STATUS Status; + + if (!Buffer) { + return EFI_INVALID_PARAMETER; + } + + Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Do nothing for Nt32 version + // + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CpuMemoryServiceWrite ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Perform the Memory Access Read service for the CPU I/O Protocol + +Arguments: + + Pointer to an instance of the CPU I/O Protocol + Width of the Memory Access + Address of the Memory access + Count of the number of accesses to perform + Pointer to the buffer to read or write from memory + +Returns: + + Status + + EFI_SUCCESS - The data was read from or written to the EFI System. + EFI_INVALID_PARAMETER - Width is invalid for this EFI System. + EFI_INVALID_PARAMETER - Buffer is NULL. + EFI_UNSUPPORTED - The Buffer is not aligned for the given Width. + EFI_UNSUPPORTED - The address range specified by Address, Width, and + Count is not valid for this EFI System. + +--*/ +// TODO: This - add argument and description to function comment +{ + EFI_STATUS Status; + + if (!Buffer) { + return EFI_INVALID_PARAMETER; + } + + Status = CpuIoCheckAddressRange (Width, Address, Count, Buffer, IA32_MAX_MEM_ADDRESS); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Do nothing for Nt32 version + // + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CpuIoServiceRead ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ) +/*++ + +Routine Description: + + This is the service that implements the I/O read + +Arguments: + + Pointer to an instance of the CPU I/O Protocol + Width of the Memory Access + Address of the I/O access + Count of the number of accesses to perform + Pointer to the buffer to read or write from I/O space + +Returns: + + Status + EFI_SUCCESS - The data was read from or written to the EFI System. + EFI_INVALID_PARAMETER - Width is invalid for this EFI System. + EFI_INVALID_PARAMETER - Buffer is NULL. + EFI_UNSUPPORTED - The Buffer is not aligned for the given Width. + EFI_UNSUPPORTED - The address range specified by Address, Width, and + Count is not valid for this EFI System. +--*/ +// TODO: This - add argument and description to function comment +// TODO: UserAddress - add argument and description to function comment +// TODO: UserBuffer - add argument and description to function comment +{ + UINTN Address; + EFI_STATUS Status; + + if (!UserBuffer) { + return EFI_INVALID_PARAMETER; + } + + Address = (UINTN) UserAddress; + + if (Width >= EfiCpuIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Do nothing for Nt32 version + // + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +CpuIoServiceWrite ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 UserAddress, + IN UINTN Count, + IN OUT VOID *UserBuffer + ) +/*++ + +Routine Description: + + + This is the service that implements the I/O Write + +Arguments: + + Pointer to an instance of the CPU I/O Protocol + Width of the Memory Access + Address of the I/O access + Count of the number of accesses to perform + Pointer to the buffer to read or write from I/O space + +Returns: + + Status + + Status + EFI_SUCCESS - The data was read from or written to the EFI System. + EFI_INVALID_PARAMETER - Width is invalid for this EFI System. + EFI_INVALID_PARAMETER - Buffer is NULL. + EFI_UNSUPPORTED - The Buffer is not aligned for the given Width. + EFI_UNSUPPORTED - The address range specified by Address, Width, and + Count is not valid for this EFI System. + +--*/ +// TODO: This - add argument and description to function comment +// TODO: UserAddress - add argument and description to function comment +// TODO: UserBuffer - add argument and description to function comment +{ + UINTN Address; + EFI_STATUS Status; + + if (!UserBuffer) { + return EFI_INVALID_PARAMETER; + } + + Address = (UINTN) UserAddress; + + if (Width >= EfiCpuIoWidthMaximum) { + return EFI_INVALID_PARAMETER; + } + + Status = CpuIoCheckAddressRange (Width, Address, Count, UserBuffer, IA32_MAX_IO_ADDRESS); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Do nothing for Nt32 version + // + return EFI_SUCCESS; +} + + +EFI_STATUS +CpuIoCheckAddressRange ( + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN VOID *Buffer, + IN UINT64 Limit + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Width - TODO: add argument description + Address - TODO: add argument description + Count - TODO: add argument description + Buffer - TODO: add argument description + Limit - TODO: add argument description + +Returns: + + EFI_UNSUPPORTED - TODO: Add description for return value + EFI_UNSUPPORTED - TODO: Add description for return value + EFI_UNSUPPORTED - TODO: Add description for return value + EFI_SUCCESS - TODO: Add description for return value + +--*/ +{ + UINTN AlignMask; + + if (Address > Limit) { + return EFI_UNSUPPORTED; + } + + // + // For FiFo type, the target address won't increase during the access, so treat count as 1 + // + if (Width >= EfiCpuIoWidthFifoUint8 && Width <= EfiCpuIoWidthFifoUint64) { + Count = 1; + } + + Width = Width & 0x03; + if (Address - 1 + (1 << Width) * Count > Limit) { + return EFI_UNSUPPORTED; + } + + AlignMask = (1 << Width) - 1; + if ((UINTN) Buffer & AlignMask) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Strings.uni b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Strings.uni new file mode 100644 index 0000000000..fd70fb9068 Binary files /dev/null and b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/Strings.uni differ diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/build.xml new file mode 100644 index 0000000000..91fe4e49ad --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/Cpu/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.c b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.c new file mode 100644 index 0000000000..b1f139f4c2 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.c @@ -0,0 +1,87 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtThunk.c + +Abstract: + + Produce WinNtThunk protocol and it's associated device path and controller + state protocols. WinNtThunk is to the NT emulation environment as + PCI_ROOT_BRIGE is to real hardware. The WinNtBusDriver is the child of this + driver. + + Since we are a root hardware abstraction we do not install a Driver Binding + protocol on this handle. This driver can only support one one WinNtThunk protocol + in the system, since the device path is hard coded. + +--*/ + +#include "WinNtThunk.h" + +// +// WinNtThunk Device Path Protocol Instance +// +static WIN_NT_THUNK_DEVICE_PATH mWinNtThunkDevicePath = { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8), + EFI_WIN_NT_THUNK_PROTOCOL_GUID, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + END_DEVICE_PATH_LENGTH, + 0 + } +}; + + +EFI_STATUS +EFIAPI +InitializeWinNtThunk ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + Install WinNtThunk Protocol and it's associated Device Path protocol + +Arguments: + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + EFI_SUCEESS - WinNtThunk protocol is added or error status from + gBS->InstallMultiProtocolInterfaces(). + +--*/ +// TODO: ImageHandle - add argument and description to function comment +// TODO: SystemTable - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_HANDLE ControllerHandle; + + ControllerHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &ControllerHandle, + &gEfiWinNtThunkProtocolGuid, + gWinNt, + &gEfiDevicePathProtocolGuid, + &mWinNtThunkDevicePath, + NULL + ); + + return Status; +} diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.dxs b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.dxs new file mode 100644 index 0000000000..8a59515da7 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtThunk.dxs + +Abstract: + + Dependency expression source file. + +--*/ + +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.h b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.h new file mode 100644 index 0000000000..6f474b3d29 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.h @@ -0,0 +1,30 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtThunk.h + +Abstract: + +--*/ + +// TODO: add protective #ifndef + + +// +// WinNtThunk Device Path Protocol Instance Type +// +typedef struct { + VENDOR_DEVICE_PATH Vendor; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} WIN_NT_THUNK_DEVICE_PATH; + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.mbd b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.mbd new file mode 100644 index 0000000000..01f9f6ddf8 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.mbd @@ -0,0 +1,45 @@ + + + + + WinNtThunk + 0C95A916-A006-11d4-BCFA-0080C73C8881 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + BaseLib + DxeHobLib + UefiLib + UefiMemoryLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + BaseDebugLibReportStatusCode + DxeWinNtLib + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.msa b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.msa new file mode 100644 index 0000000000..6dbdfaba23 --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/WinNtThunk.msa @@ -0,0 +1,61 @@ + + + + + WinNtThunk + DXE_DRIVER + BS_DRIVER + 0C95A916-A006-11d4-BCFA-0080C73C8881 + 0 + Component description file for WinNtThunk module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + DebugLib + UefiLib + UefiDriverEntryPoint + WinNtLib + MemoryAllocationLib + UefiBootServicesTableLib + + + WinNtThunk.h + WinNtThunk.c + WinNtThunk.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + WinNtThunk + DevicePath + + + + InitializeWinNtThunk + + + diff --git a/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/build.xml b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/build.xml new file mode 100644 index 0000000000..938e55f47d --- /dev/null +++ b/EdkNt32Pkg/Dxe/WinNtThunk/WinNtThunk/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/EdkNt32Pkg.spd b/EdkNt32Pkg/EdkNt32Pkg.spd new file mode 100644 index 0000000000..1667af21f7 --- /dev/null +++ b/EdkNt32Pkg/EdkNt32Pkg.spd @@ -0,0 +1,383 @@ + + + + + EdkNt32Pkg + 0fb2aa2d-10d5-40a5-a9dc-060c12a4a3f3 + 0 + This is the NT32 Emulation Environment Platform + Reference platform implementation using an emulator. + Copyright (c) 2006, 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. + + 2006-02-22 13:25 + 2006-03-22 16:18 + http://www.TianoCore.org + SOURCE + true + false + + + + EdkGenericBdsLib + Include/Library/EdkGenericBdsLib.h + + + WinNtLib + Include/Library/WinNtLib.h + + + + + + Dxe/ConPlatform/ConPlatform.msa + + + Dxe/Nt32Platform/MiscSubclass/MiscSubclassDriver.msa + + + Dxe/PcdEmulator/PcdEmulator.msa + + + Dxe/PlatformBds/PlatformBds.msa + + + Dxe/WinNtThunk/Bus/BlockIo/WinNtBlockIo.msa + + + Dxe/WinNtThunk/Bus/Console/WinNtConsole.msa + + + Dxe/WinNtThunk/Bus/SerialIo/WinNtSerialIo.msa + + + Dxe/WinNtThunk/Bus/SimpleFileSystem/WinNtSimpleFileSystem.msa + + + Dxe/WinNtThunk/Bus/Uga/WinNtUga.msa + + + Dxe/WinNtThunk/Bus/WinNtBusDriver/WinNtBusDriver.msa + + + Dxe/WinNtThunk/Chipset/Metronome/Metronome.msa + + + Dxe/WinNtThunk/Chipset/RealTimeClock/RealTimeClock.msa + + + Dxe/WinNtThunk/Chipset/Reset/Reset.msa + + + Dxe/WinNtThunk/Chipset/Timer/Timer.msa + + + Dxe/WinNtThunk/Cpu/Cpu.msa + + + Dxe/WinNtThunk/WinNtThunk/WinNtThunk.msa + + + Library/DxeWinNtLib/DxeWinNtLib.msa + + + Library/EdkGenericBdsLib/EdkGenericBdsLib.msa + + + Library/EdkNt32PeiPeCoffGetEntryPointLib/EdkNt32PeiPeCoffGetEntryPointLib.msa + + + Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.msa + + + Logo/Logo.msa + + + Pei/Autoscan/WinNtAutoScan.msa + + + Pei/BootMode/BootMode.msa + + + Pei/FirmwareVolume/WinNtFwh.msa + + + Pei/FlashMap/FlashMap.msa + + + Pei/MonoStatusCode/Nt32/MonoStatusCode.msa + + + Pei/PcdEmulator/PcdEmulator.msa + + + Pei/WinNtStuff/WinNtStuff.msa + + + RuntimeDxe/FvbServices/Nt32Fwh.msa + + + Sec/SecMain.msa + + + + Include/WinNtPeim.h + Include/WinNtPeim.h + Include/WinNtDxe.h + Include/WinNtDxe.h + Include/WinNtDxe.h + Include/WinNtDxe.h + Include/WinNtDxe.h + + + + gEfiWinNtVirtualDisksGuid + 0xc95a928, 0xa006, 0x11d4, 0xbc, 0xfa, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiWinNtPhysicalDisksGuid + 0xc95a92f, 0xa006, 0x11d4, 0xbc, 0xfa, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiWinNtFileSystemGuid + 0xc95a935, 0xa006, 0x11d4, 0xbc, 0xfa, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiWinNtSerialPortGuid + 0xc95a93d, 0xa006, 0x11d4, 0xbc, 0xfa, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiWinNtUgaGuid + 0xab248e99, 0xabe1, 0x11d4, 0xbd, 0x0d, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiWinNtConsoleGuid + 0xba73672c, 0xa5d3, 0x11d4, 0xbd, 0x00, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiWinNtMemoryGuid + 0x99042912, 0x122a, 0x11d4, 0xbd, 0x0d, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiWinNtCPUModelGuid + 0xbee9b6ce, 0x2f8a, 0x11d4, 0xbd, 0x0d, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiWinNtCPUSpeedGuid + 0xd4f29055, 0xe1fb, 0x11d4, 0xbd, 0x0d, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiWinNtPassThroughGuid + 0xcc664eb8, 0x3c24, 0x4086, 0xb6, 0xf6, 0x34, 0xe8, 0x56, 0xbc, 0xe3, 0x6e + + + gPcdHobGuid + 0x582e7ca1, 0x68cd, 0x4d44, 0xb4, 0x3b, 0xf2, 0x98, 0xed, 0x58, 0x7b, 0xa6 + + + + + gEfiWinNtIoProtocolGuid + 0x96eb4ad6, 0xa32a, 0x11d4, 0xbc, 0xfd, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiWinNtThunkProtocolGuid + 0x58c518b1, 0x76f3, 0x11d4, 0xbc, 0xea, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + + + gPeiNtAutoScanPpiGuid + 0xdce384d, 0x7c, 0x4ba5, 0x94, 0xbd, 0x0f, 0x6e, 0xb6, 0x4d, 0x2a, 0xa9 + + + gNtFwhPpiGuid + 0x4e76928f, 0x50ad, 0x4334, 0xb0, 0x6b, 0xa8, 0x42, 0x13, 0x10, 0x8a, 0x57 + + + gNtPeiLoadFilePpiGuid + 0xfd0c65eb, 0x405, 0x4cd2, 0x8a, 0xee, 0xf4, 0x00, 0xef, 0x13, 0xba, 0xc2 + + + gPeiNtThunkPpiGuid + 0x98c281e5, 0xf906, 0x43dd, 0xa9, 0x2b, 0xb0, 0x03, 0xbf, 0x27, 0x65, 0xda + + + + + PcdMaximumUnicodeStringLength + 0x00000001 + UINT32 + 1000000 + + + PcdMaximumAsciiStringLength + 0x00000002 + UINT32 + 1000000 + + + PcdMaximumLinkedListLength + 0x00000003 + UINT32 + 1000000 + + + PcdSpinLockTimeout + 0x00000004 + UINT32 + 10000000 + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + 0x0f + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + 0x80000000 + + + PcdReportStatusCodePropertyMask + 0x00000007 + UINT8 + 0x07 + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + 0xAF + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + 0xAF + + + PcdPerformanceLibraryPropertyMask + 0x00000009 + UINT8 + 0 + + + PcdWinNtPhysicalDisk + 0x00001000 + VOID* + L"FW;40960;512" + + + PcdWinNtVirtualDisk + 0x00001001 + VOID* + L"FW;40960;512" + + + PcdWinNtSerialPort + 0x00001002 + VOID* + L"COM1!COM2" + + + PcdWinNtUga + 0x00001003 + VOID* + L"UGA Window 1!UGA Window 2" + + + PcdWinNtFileSystem + 0x00001004 + VOID* + L".!C:\\D\\work\\Remodel\\mdk\\EdkShellBinPkg\\bin\\ia32\\Apps" + + + PcdWinNtMemorySize + 0x00001005 + VOID* + L"64!64" + + + PcdWinNtBootMode + 0x00001006 + UINT32 + 1 + + + PcdWinNtCpuModel + 0x00001007 + VOID* + L"Intel(R) Processor Model" + + + PcdWinNtCpuSpeed + 0x00001008 + VOID* + L"3000" + + + PcdWinNtFirmwareVolume + 0x00001009 + VOID* + L"..\\..\\Fv\\Fv_Recovery.fd" + + + PcdWinNtConsole + 0x0000100a + VOID* + L"Bus Driver Console Window" + + + PcdRothmanTest + 0x0000100b + UINT32 + 0 + + + PcdWinNtBinaryPatch1 + 0x0001000b + UINT32 + 0x1234 + + + PcdWinNtBinaryPatch2 + 0x0001000c + UINT32 + 0x5678 + + + PcdWinNtFeatureFlag1 + 0x0001000d + BOOLEAN + 0x1 + + + PcdWinNtDynamicUINT32 + 0x0001000e + UINT32 + 0x0 + + + diff --git a/EdkNt32Pkg/Include/Common/WinNTInclude.h b/EdkNt32Pkg/Include/Common/WinNTInclude.h new file mode 100644 index 0000000000..a8d31c3518 --- /dev/null +++ b/EdkNt32Pkg/Include/Common/WinNTInclude.h @@ -0,0 +1,71 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + WinNtLib.h + +Abstract: + Public include file for the WinNt Library + +--*/ + +#ifndef __WIN_NT_INCLUDE_H__ +#define __WIN_NT_INCLUDE_H__ + +// +// Win32 include files do not compile clean with /W4, so we use the warning +// pragma to suppress the warnings for Win32 only. This way our code can stil +// compile at /W4 (highest warning level) with /WX (warnings cause build +// errors). +// +#pragma warning(disable : 4115) +#pragma warning(disable : 4201) +#pragma warning(disable : 4214) +#pragma warning(disable : 4028) +#pragma warning(disable : 4133) + +#define GUID _WINNT_DUP_GUID_____ +#define _LIST_ENTRY _WINNT_DUP_LIST_ENTRY_FORWARD +#define LIST_ENTRY _WINNT_DUP_LIST_ENTRY +#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement +#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement +#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64 +#undef UNALIGNED +#undef CONST +#undef VOID + +#include "windows.h" + +#undef GUID +#undef _LIST_ENTRY +#undef LIST_ENTRY +#undef InterlockedIncrement +#undef InterlockedDecrement +#undef InterlockedCompareExchange64 +#undef InterlockedCompareExchangePointer + +#define VOID void + +// +// Prevent collisions with Windows API name macros that deal with Unicode/Not issues +// +#undef LoadImage +#undef CreateEvent + +// +// Set the warnings back on as the EFI code must be /W4. +// +#pragma warning(default : 4115) +#pragma warning(default : 4201) +#pragma warning(default : 4214) + + +#endif diff --git a/EdkNt32Pkg/Include/FlashLayout.h b/EdkNt32Pkg/Include/FlashLayout.h new file mode 100644 index 0000000000..5a95961709 --- /dev/null +++ b/EdkNt32Pkg/Include/FlashLayout.h @@ -0,0 +1,64 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FlashLayout.h + +Abstract: + + Platform specific flash layout + + BugBug: We need a better way + +--*/ + +#ifndef __EFI_FLASH_LAYOUT__ +#define __EFI_FLASH_LAYOUT__ + +// +// Firmware Volume Information for Nt32 +// adding one working block before FFS FV, +// and another one for spare block behind FFS FV +// +// +// Note: When block number is changed in .dsc file, +// this value should be changed accordingly!!! +// +#define FIRMWARE_BLOCK_NUMBER 0x28 + +#define EFI_WINNT_FIRMWARE_OFFSET 0x0 +#define EFI_WINNT_FIRMWARE_LENGTH (0x10000 * FIRMWARE_BLOCK_NUMBER) + +#define EFI_WINNT_RUNTIME_UPDATABLE_OFFSET (EFI_WINNT_FIRMWARE_OFFSET + EFI_WINNT_FIRMWARE_LENGTH) + +#define EFI_WINNT_RUNTIME_UPDATABLE_LENGTH 0x10000 + +#define EFI_WINNT_FTW_SPARE_BLOCK_OFFSET (EFI_WINNT_RUNTIME_UPDATABLE_OFFSET + EFI_WINNT_RUNTIME_UPDATABLE_LENGTH) + +#define EFI_WINNT_FTW_SPARE_BLOCK_LENGTH 0x10000 + +#define EFI_WINNT_RUNTIME_UPDATABLE_FV_HEADER_LENGTH 0x48 + +#define EFI_VARIABLE_STORE_OFFSET (EFI_WINNT_RUNTIME_UPDATABLE_OFFSET + EFI_WINNT_RUNTIME_UPDATABLE_FV_HEADER_LENGTH) + +#define EFI_VARIABLE_STORE_LENGTH (0x00C000 - EFI_WINNT_RUNTIME_UPDATABLE_FV_HEADER_LENGTH) + +#define EFI_EVENT_LOG_OFFSET (EFI_VARIABLE_STORE_OFFSET + EFI_VARIABLE_STORE_LENGTH) + +#define EFI_EVENT_LOG_LENGTH 0x002000 + +#define EFI_FTW_WORKING_OFFSET (EFI_EVENT_LOG_OFFSET + EFI_EVENT_LOG_LENGTH) + +#define EFI_FTW_WORKING_LENGTH 0x002000 + +#endif + diff --git a/EdkNt32Pkg/Include/Ppi/NtAutoscan.h b/EdkNt32Pkg/Include/Ppi/NtAutoscan.h new file mode 100644 index 0000000000..6098819f3f --- /dev/null +++ b/EdkNt32Pkg/Include/Ppi/NtAutoscan.h @@ -0,0 +1,66 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + NtAutoscan.h + +Abstract: + +Nt Autoscan PPI + +--*/ + +#ifndef __NT_PEI_AUTOSCAN_H__ +#define __NT_PEI_AUTOSCAN_H__ + +#include + +#define PEI_NT_AUTOSCAN_PPI_GUID \ + { \ + 0xdce384d, 0x7c, 0x4ba5, {0x94, 0xbd, 0xf, 0x6e, 0xb6, 0x4d, 0x2a, 0xa9 } \ + } + +typedef +EFI_STATUS +(EFIAPI *PEI_NT_AUTOSCAN) ( + IN UINTN Index, + OUT EFI_PHYSICAL_ADDRESS * MemoryBase, + OUT UINT64 *MemorySize + ); + +/*++ + +Routine Description: + This service is called from Index == 0 until it returns EFI_UNSUPPORTED. + It allows discontiguous memory regions to be supported by the emulator. + It uses gSystemMemory[] and gSystemMemoryCount that were created by + parsing the Windows environment variable EFI_MEMORY_SIZE. + The size comes from the varaible and the address comes from the call to + WinNtOpenFile. + +Arguments: + Index - Which memory region to use + MemoryBase - Return Base address of memory region + MemorySize - Return size in bytes of the memory region + +Returns: + EFI_SUCCESS - If memory region was mapped + EFI_UNSUPPORTED - If Index is not supported + +--*/ +typedef struct { + PEI_NT_AUTOSCAN NtAutoScan; +} PEI_NT_AUTOSCAN_PPI; + +extern EFI_GUID gPeiNtAutoScanPpiGuid; + +#endif diff --git a/EdkNt32Pkg/Include/Ppi/NtFwh.h b/EdkNt32Pkg/Include/Ppi/NtFwh.h new file mode 100644 index 0000000000..90b41094cf --- /dev/null +++ b/EdkNt32Pkg/Include/Ppi/NtFwh.h @@ -0,0 +1,62 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + NtFwh.h + +Abstract: + + WinNt FWH PPI as defined in Tiano + +--*/ + +#ifndef __NT_PEI_FWH_H__ +#define __NT_PEI_FWH_H__ + +#include + +#define NT_FWH_PPI_GUID \ + { \ + 0x4e76928f, 0x50ad, 0x4334, {0xb0, 0x6b, 0xa8, 0x42, 0x13, 0x10, 0x8a, 0x57 } \ + } + +typedef +EFI_STATUS +(EFIAPI *NT_FWH_INFORMATION) ( + IN UINTN Index, + IN OUT EFI_PHYSICAL_ADDRESS * FdBase, + IN OUT UINT64 *FdSize + ); + +/*++ + +Routine Description: + Return the FD Size and base address. Since the FD is loaded from a + file into Windows memory only the SEC will know it's address. + +Arguments: + Index - Which FD, starts at zero. + FdSize - Size of the FD in bytes + FdBase - Start address of the FD. Assume it points to an FV Header + +Returns: + EFI_SUCCESS - Return the Base address and size of the FV + EFI_UNSUPPORTED - Index does nto map to an FD in the system + +--*/ +typedef struct { + NT_FWH_INFORMATION NtFwh; +} NT_FWH_PPI; + +extern EFI_GUID gNtFwhPpiGuid; + +#endif diff --git a/EdkNt32Pkg/Include/Ppi/NtPeiLoadFile.h b/EdkNt32Pkg/Include/Ppi/NtPeiLoadFile.h new file mode 100644 index 0000000000..622e01a145 --- /dev/null +++ b/EdkNt32Pkg/Include/Ppi/NtPeiLoadFile.h @@ -0,0 +1,65 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + NtPeiLoadFile.h + +Abstract: + + WinNt Load File PPI. + + When the PEI core is done it calls the DXE IPL via PPI + +--*/ + +#ifndef __NT_PEI_LOAD_FILE_H__ +#define __NT_PEI_LOAD_FILE_H__ + +#include + +#define NT_PEI_LOAD_FILE_GUID \ + { \ + 0xfd0c65eb, 0x405, 0x4cd2, {0x8a, 0xee, 0xf4, 0x0, 0xef, 0x13, 0xba, 0xc2 } \ + } + +typedef +EFI_STATUS +(EFIAPI *NT_PEI_LOAD_FILE) ( + VOID *Pe32Data, + EFI_PHYSICAL_ADDRESS *ImageAddress, + UINT64 *ImageSize, + EFI_PHYSICAL_ADDRESS *EntryPoint + ); + +/*++ + +Routine Description: + Loads and relocates a PE/COFF image into memory. + +Arguments: + Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated + ImageAddress - The base address of the relocated PE/COFF image + ImageSize - The size of the relocated PE/COFF image + EntryPoint - The entry point of the relocated PE/COFF image + +Returns: + EFI_SUCCESS - The file was loaded and relocated + EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file + +--*/ +typedef struct { + NT_PEI_LOAD_FILE PeiLoadFileService; +} NT_PEI_LOAD_FILE_PPI; + +extern EFI_GUID gNtPeiLoadFilePpiGuid; + +#endif diff --git a/EdkNt32Pkg/Include/Ppi/NtThunk.h b/EdkNt32Pkg/Include/Ppi/NtThunk.h new file mode 100644 index 0000000000..782c510a30 --- /dev/null +++ b/EdkNt32Pkg/Include/Ppi/NtThunk.h @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + NtThunk.h + +Abstract: + + WinNt Thunk interface PPI + +--*/ + +#ifndef __NT_PEI_WIN_NT_THUNK_H__ +#define __NT_PEI_WIN_NT_THUNK_H__ + +#include + +#define PEI_NT_THUNK_PPI_GUID \ + { \ + 0x98c281e5, 0xf906, 0x43dd, {0xa9, 0x2b, 0xb0, 0x3, 0xbf, 0x27, 0x65, 0xda } \ + } + +typedef +VOID * +(EFIAPI *PEI_NT_THUNK_INTERFACE) ( + VOID + ); + +/*++ + +Routine Description: + Export of EFI_WIN_NT_THUNK_PROTOCOL from the Windows SEC. + +Arguments: + InterfaceBase - Address of the EFI_WIN_NT_THUNK_PROTOCOL + +Returns: + EFI_SUCCESS - Data returned + +--*/ +typedef struct { + PEI_NT_THUNK_INTERFACE NtThunk; +} PEI_NT_THUNK_PPI; + +extern EFI_GUID gPeiNtThunkPpiGuid; + +#endif diff --git a/EdkNt32Pkg/Include/Protocol/WinNtIo.h b/EdkNt32Pkg/Include/Protocol/WinNtIo.h new file mode 100644 index 0000000000..85d99feac9 --- /dev/null +++ b/EdkNt32Pkg/Include/Protocol/WinNtIo.h @@ -0,0 +1,141 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtIo.h + +Abstract: + +--*/ + +#ifndef __WIN_NT_IO_H__ +#define __WIN_NT_IO_H__ + +#define EFI_WIN_NT_IO_PROTOCOL_GUID \ + { 0x96eb4ad6, 0xa32a, 0x11d4, { 0xbc, 0xfd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +typedef struct { + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + EFI_GUID *TypeGuid; + CHAR16 *EnvString; + UINT16 InstanceNumber; +} EFI_WIN_NT_IO_PROTOCOL; + + +extern EFI_GUID gEfiWinNtIoProtocolGuid; + +// +// The following GUIDs are used in EFI_WIN_NT_IO_PROTOCOL_GUID +// Device paths. They map 1:1 with NT envirnment variables. The variables +// define what virtual hardware the emulator/WinNtBusDriver will produce. +// +// +// EFI_WIN_NT_VIRTUAL_DISKS +// +#define EFI_WIN_NT_VIRTUAL_DISKS_GUID \ + { \ + 0xc95a928, 0xa006, 0x11d4, {0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gEfiWinNtVirtualDisksGuid; + +// +// EFI_WIN_NT_PHYSICAL_DISKS +// +#define EFI_WIN_NT_PHYSICAL_DISKS_GUID \ + { \ + 0xc95a92f, 0xa006, 0x11d4, {0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gEfiWinNtPhysicalDisksGuid; + +// +// EFI_WIN_NT_FILE_SYSTEM +// +#define EFI_WIN_NT_FILE_SYSTEM_GUID \ + { \ + 0xc95a935, 0xa006, 0x11d4, {0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gEfiWinNtFileSystemGuid; + +// +// EFI_WIN_NT_SERIAL_PORT +// +#define EFI_WIN_NT_SERIAL_PORT_GUID \ + { \ + 0xc95a93d, 0xa006, 0x11d4, {0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gEfiWinNtSerialPortGuid; + +// +// EFI_WIN_NT_UGA +// +#define EFI_WIN_NT_UGA_GUID \ + { \ + 0xab248e99, 0xabe1, 0x11d4, {0xbd, 0xd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gEfiWinNtUgaGuid; + +// +// EFI_WIN_NT_CONSOLE +// +#define EFI_WIN_NT_CONSOLE_GUID \ + { \ + 0xba73672c, 0xa5d3, 0x11d4, {0xbd, 0x0, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gEfiWinNtConsoleGuid; + +// +// EFI_WIN_NT_MEMORY +// +#define EFI_WIN_NT_MEMORY_GUID \ + { \ + 0x99042912, 0x122a, 0x11d4, {0xbd, 0xd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gEfiWinNtMemoryGuid; + +// +// EFI_WIN_NT_CPU_MODEL +// +#define EFI_WIN_NT_CPU_MODEL_GUID \ + { \ + 0xbee9b6ce, 0x2f8a, 0x11d4, {0xbd, 0xd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gEfiWinNtCPUModelGuid; + +// +// EFI_WIN_NT_CPU_SPEED +// +#define EFI_WIN_NT_CPU_SPEED_GUID \ + { \ + 0xd4f29055, 0xe1fb, 0x11d4, {0xbd, 0xd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gEfiWinNtCPUSpeedGuid; + +// +// EFI_WIN_NT_PASS_THROUGH +// +#define EFI_WIN_NT_PASS_THROUGH_GUID \ + { \ + 0xcc664eb8, 0x3c24, 0x4086, {0xb6, 0xf6, 0x34, 0xe8, 0x56, 0xbc, 0xe3, 0x6e } \ + } + +extern EFI_GUID gEfiWinNtPassThroughGuid; + +#endif diff --git a/EdkNt32Pkg/Include/Protocol/WinNtThunk.h b/EdkNt32Pkg/Include/Protocol/WinNtThunk.h new file mode 100644 index 0000000000..6ebc93fb6f --- /dev/null +++ b/EdkNt32Pkg/Include/Protocol/WinNtThunk.h @@ -0,0 +1,1264 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtThunk.h + +Abstract: + + This protocol allows an EFI driver (DLL) in the NT emulation envirnment + to make Win32 API calls. + + NEVER make a Win32 call directly, always make the call via this protocol. + + There are no This pointers on the protocol member functions as they map + exactly into Win32 system calls. + + YOU MUST include EfiWinNT.h in place of Efi.h to make this file compile. + +--*/ + +#ifndef __WIN_NT_THUNK_H__ +#define __WIN_NT_THUNK_H__ + +#define EFI_WIN_NT_THUNK_PROTOCOL_GUID \ + { 0x58c518b1, 0x76f3, 0x11d4, { 0xbc, 0xea, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtSleep) ( + DWORD Milliseconds + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtSuspendThread) ( + HANDLE hThread + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtGetCurrentThread) ( + VOID + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetCurrentThreadId) ( + VOID + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtGetCurrentProcess) ( + VOID + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtCreateThread) ( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtTerminateThread) ( + HANDLE hThread, + DWORD dwExitCode + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSendMessage) ( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtExitThread) ( + DWORD dwExitCode + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtResumeThread) ( + HANDLE hThread + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetThreadPriority) ( + HANDLE hThread, + INTN nPriority + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtInitializeCriticalSection) ( + LPCRITICAL_SECTION lpCriticalSection + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtDeleteCriticalSection) ( + LPCRITICAL_SECTION lpCriticalSection + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtEnterCriticalSection) ( + LPCRITICAL_SECTION lpCriticalSection + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtLeaveCriticalSection) ( + LPCRITICAL_SECTION lpCriticalSection + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtTlsAlloc) ( + VOID + ); + +typedef +WINBASEAPI +LPVOID +(WINAPI *WinNtTlsGetValue) ( + DWORD dwTlsIndex + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtTlsSetValue) ( + DWORD dwTlsIndex, + LPVOID lpTlsValue + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtTlsFree) ( + DWORD dwTlsIndex + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtCreateSemaphore) ( + LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + LONG lInitialCount, + LONG lMaximumCount, + LPCWSTR lpName + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtWaitForSingleObject) ( + HANDLE hHandle, + DWORD dwMilliseconds + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtReleaseSemaphore) ( + HANDLE hSemaphore, + LONG lReleaseCount, + LPLONG lpPreviousCount + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtDuplicateHandle) ( + HANDLE hSourceProcessHandle, + HANDLE hSourceHandle, + HANDLE hTargetProcessHandle, + LPHANDLE lpTargetHandle, + DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwOptions + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtCreateConsoleScreenBuffer) ( + DWORD DesiredAccess, + DWORD ShareMode, + CONST SECURITY_ATTRIBUTES *SecurityAttributes, + DWORD Flags, + LPVOID ScreenBufferData + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetConsoleScreenBufferSize) ( + HANDLE ConsoleOutput, + COORD Size + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetConsoleActiveScreenBuffer) ( + HANDLE ConsoleOutput + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFillConsoleOutputAttribute) ( + HANDLE ConsoleOutput, + WORD Attribute, + DWORD Length, + COORD WriteCoord, + LPDWORD NumberOfAttrsWritten + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFillConsoleOutputCharacter) ( + HANDLE ConsoleOutput, + TCHAR Character, + DWORD Length, + COORD WriteCoord, + LPDWORD NumberOfCharsWritten + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtWriteConsoleOutput) ( + HANDLE ConsoleOutput, + CONST CHAR_INFO *Buffer, + COORD BufferSize, + COORD BufferCoord, + PSMALL_RECT WriteRegion + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtScrollConsoleScreenBuffer) ( + HANDLE ConsoleOutput, + CONST SMALL_RECT *ScrollRectangle, + CONST SMALL_RECT *ClipRectangle, + COORD DestinationOrigin, + CONST CHAR_INFO *Fill + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetConsoleTitleW) ( + LPCTSTR ConsoleTitle + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetConsoleCursorInfo) ( + HANDLE ConsoleOutput, + PCONSOLE_CURSOR_INFO ConsoleCursorInfo + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetConsoleCursorInfo) ( + HANDLE ConsoleOutput, + CONST CONSOLE_CURSOR_INFO *ConsoleCursorInfo + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetPriorityClass) ( + HANDLE Process, + DWORD PriorityClass + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtWriteConsoleInput) ( + HANDLE ConsoleInput, + CONST INPUT_RECORD *Buffer, + DWORD Legnth, + LPDWORD NumberOfEventsWritten + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetNumberOfConsoleInputEvents) ( + HANDLE ConsoleInput, + LPDWORD NumberOfEvents + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtGetStdHandle) ( + DWORD StdHandle + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtReadConsoleInput) ( + HANDLE ConsoleInput, + PINPUT_RECORD Buffer, + DWORD Length, + LPDWORD NumberOfEventsRead + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtPeekConsoleInput) ( + HANDLE ConsoleInput, + PINPUT_RECORD Buffer, + DWORD Length, + LPDWORD NumberOfEventsRead + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetConsoleCursorPosition) ( + HANDLE ConsoleInput, + COORD CursorPosition + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtCreateFile) ( + LPCWSTR FileName, + DWORD DesiredAccess, + DWORD SharedMode, + LPSECURITY_ATTRIBUTES SecurityAttributes, + DWORD CreationDisposition, + DWORD FlagsAndAttributes, + HANDLE TemplateFile + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtDeviceIoControl) ( + HANDLE DeviceHandle, + DWORD IoControlCode, + LPVOID InBuffer, + DWORD InBufferSize, + LPVOID OutBuffer, + DWORD OutBufferSize, + LPDWORD BytesReturned, + LPOVERLAPPED Overlapped + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtCreateDirectory) ( + LPCWSTR PathName, + LPSECURITY_ATTRIBUTES SecurityAttributes + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtRemoveDirectory) ( + LPCWSTR PathName + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetFileAttributes) ( + LPCWSTR FileName + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetFileAttributes) ( + LPCWSTR FileName, + DWORD FileAttributes + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtCreateFileMapping) ( + HANDLE FileHandle, + LPSECURITY_ATTRIBUTES Attributes, + DWORD Protect, + DWORD MaximumSizeHigh, + DWORD MaximumSizeLow, + LPCTSTR Name + ); + +typedef +WINBASEAPI +LPVOID +(WINAPI *WinNtMapViewOfFileEx) ( + HANDLE FileHandle, + DWORD DesiredAccess, + DWORD FileOffsetHigh, + DWORD FileOffsetLow, + DWORD NumberOfBytesToMap, + LPVOID BaseAddress + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetEnvironmentVariable) ( + LPCTSTR Name, + LPTSTR Buffer, + DWORD Size + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtCloseHandle) ( + HANDLE Object + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtSetFilePointer) ( + HANDLE FileHandle, + LONG DistanceToMove, + PLONG DistanceToHoveHigh, + DWORD MoveMethod + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetEndOfFile) ( + HANDLE FileHandle + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtReadFile) ( + HANDLE FileHandle, + LPVOID Buffer, + DWORD NumberOfBytesToRead, + LPDWORD NumberOfBytesRead, + LPOVERLAPPED Overlapped + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtWriteFile) ( + HANDLE FileHandle, + LPCVOID Buffer, + DWORD NumberOfBytesToWrite, + LPDWORD NumberOfBytesWritten, + LPOVERLAPPED Overlapped + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetFileInformationByHandle) ( + HANDLE FileHandle, + BY_HANDLE_FILE_INFORMATION *FileInfo + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetDiskFreeSpace) ( + LPCTSTR RootPathName, + LPDWORD SectorsPerCluster, + LPDWORD BytesPerSector, + LPDWORD NumberOfFreeClusters, + LPDWORD TotalNumberOfClusters + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetDiskFreeSpaceEx) ( + LPCTSTR DirectoryName, + PULARGE_INTEGER FreeBytesAvailable, + PULARGE_INTEGER TotalNumberOfBytes, + PULARGE_INTEGER TotoalNumberOfFreeBytes + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtMoveFile) ( + LPCTSTR ExistingFileName, + LPCTSTR NewFileName + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetFileTime) ( + HANDLE FileHandle, + FILETIME *CreationTime, + FILETIME *LastAccessTime, + FILETIME *LastWriteTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSystemTimeToFileTime) ( + SYSTEMTIME * SystemTime, + FILETIME * FileTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtDeleteFile) ( + LPCTSTR FileName + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFlushFileBuffers) ( + HANDLE + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetLastError) ( + VOID + ); + +typedef +WINBASEAPI +UINT +(WINAPI *WinNtSetErrorMode) ( + UINT Mode + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetTickCount) ( + VOID + ); + +typedef +WINBASEAPI +HMODULE +(WINAPI *WinNtLoadLibraryEx) ( + LPCTSTR LibFileName, + HANDLE FileHandle, + DWORD Flags + ); + +typedef +WINBASEAPI +FARPROC +(WINAPI *WinNtGetProcAddress) ( + HMODULE Module, + LPCSTR ProcName + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetTimeZoneInformation) ( + LPTIME_ZONE_INFORMATION timeZoneInformation + ); + +typedef +WINBASEAPI +MMRESULT +(WINAPI *WinNttimeSetEvent) ( + UINT uDelay, + UINT uResolution, + LPTIMECALLBACK lpTimeProc, + DWORD_PTR dwUser, + UINT fuEvent + ); + +typedef +WINBASEAPI +MMRESULT +(WINAPI *WinNttimeKillEvent) ( + UINT uTimerID + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtSetTimeZoneInformation) ( + LPTIME_ZONE_INFORMATION timeZoneInformation + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtGetSystemTime) ( + LPSYSTEMTIME SystemTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetSystemTime) ( + CONST SYSTEMTIME *SystemTime + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtGetLocalTime) ( + LPSYSTEMTIME SystemTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetLocalTime) ( + CONST SYSTEMTIME *SystemTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFileTimeToLocalFileTime) ( + CONST FILETIME *FileTime, + LPFILETIME LocalFileTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFileTimeToSystemTime) ( + CONST FILETIME *FileTime, + LPSYSTEMTIME SystemTime + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtFindFirstFile) ( + LPCTSTR FileName, + LPWIN32_FIND_DATA FindFileData + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFindNextFile) ( + HANDLE FindFile, + LPWIN32_FIND_DATA FindFileData + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFindClose) ( + HANDLE FindFile + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetCommState) ( + HANDLE FileHandle, + LPDCB DCB + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetCommState) ( + HANDLE FileHandle, + LPDCB DCB + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetCommState) ( + HANDLE FileHandle, + LPDCB DCB + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetCommTimeouts) ( + HANDLE FileHandle, + LPCOMMTIMEOUTS CommTimeouts + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtExitProcess) ( + UINT uExitCode // exit code for all threads + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtPurgeComm) ( + HANDLE FileHandle, + DWORD Flags + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtEscapeCommFunction) ( + HANDLE FileHandle, + DWORD Func + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetCommModemStatus) ( + HANDLE FileHandle, + LPDWORD ModemStat + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtClearCommError) ( + HANDLE FileHandle, + LPDWORD Errors, + LPCOMSTAT Stat + ); + +typedef +WINUSERAPI +INT32 +(WINAPIV *WinNtSprintf) ( + LPWSTR Buffer, + LPCWSTR String, + ... + ); + +typedef +WINUSERAPI +HWND +(WINAPI *WinNtGetDesktopWindow) ( + VOID + ); + +typedef +WINUSERAPI +HWND +(WINAPI *WinNtGetForegroundWindow) ( + VOID + ); + +typedef +WINUSERAPI +HWND +(WINAPI *WinNtCreateWindowEx) ( + DWORD dwExStyle, + LPCTSTR lpClassName, + LPCTSTR lpWindowName, + DWORD dwStyle, + INT32 x, + INT32 y, + INT32 nWidth, + INT32 nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID *lpParam + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtUpdateWindow) ( + HWND hWnd + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtShowWindow) ( + HWND hWnd, + INT32 nCmdShow + ); + +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtDestroyWindow) ( + HWND hWnd + ); + +typedef +WINUSERAPI +HDC +(WINAPI *WinNtGetWindowDC) ( + HWND hWnd + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtGetClientRect) ( + HWND hWnd, + LPRECT lpRect + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtAdjustWindowRect) ( + LPRECT lpRect, + DWORD dwStyle, + BOOL bMenu + ); + +typedef +WINGDIAPI +INT32 +(WINAPI *WinNtSetDIBitsToDevice) ( + HDC, + INT32, + INT32, + DWORD, + DWORD, + INT32, + INT32, + UINT, + UINT, + CONST VOID *, + CONST BITMAPINFO *, + UINT + ); + +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtBitBlt) ( + HDC, + INT32, + INT32, + INT32, + INT32, + HDC, + INT32, + INT32, + DWORD + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtInvalidateRect) ( + HWND hWnd, + CONST RECT *lpRect, + BOOL bErase + ); + +typedef +WINUSERAPI +HDC +(WINAPI *WinNtGetDC) ( + HWND hWnd + ); + +typedef +WINUSERAPI +INT32 +(WINAPI *WinNtReleaseDC) ( + HWND hWnd, + HDC hDC + ); + +typedef +WINUSERAPI +ATOM +(WINAPI *WinNtRegisterClassEx) ( + CONST WNDCLASSEX * + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtUnregisterClass) ( + LPCTSTR lpClassName, + HINSTANCE hInstance + ); + +typedef +WINUSERAPI +HDC +(WINAPI *WinNtBeginPaint) ( + HWND hWnd, + LPPAINTSTRUCT lpPaint + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtEndPaint) ( + HWND hWnd, + CONST PAINTSTRUCT *lpPaint + ); + +typedef +WINUSERAPI +VOID +(WINAPI *WinNtPostQuitMessage) ( + INT32 nExitCode + ); + +typedef +WINUSERAPI +LRESULT +(WINAPI *WinNtDefWindowProc) ( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam + ); + +typedef +WINUSERAPI +HICON +(WINAPI *WinNtLoadIcon) ( + HINSTANCE hInstance, + LPCTSTR lpIconName + ); + +typedef +WINUSERAPI +HCURSOR +(WINAPI *WinNtLoadCursor) ( + HINSTANCE hInstance, + LPCTSTR lpCursorName + ); + +typedef +WINGDIAPI +HGDIOBJ +(WINAPI *WinNtGetStockObject) ( + INT32 + ); + +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtSetViewportOrgEx) ( + HDC, + INT32, + INT32, + LPPOINT + ); + +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtSetWindowOrgEx) ( + HDC, + INT32, + INT32, + LPPOINT + ); +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtMoveWindow) ( + HWND, + INT32, + INT32, + INT32, + INT32, + BOOL + ); + +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtGetWindowRect) ( + HWND, + LPRECT + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtGetMessage) ( + LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtTranslateMessage) ( + CONST MSG *lpMsg + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtDispatchMessage) ( + CONST MSG *lpMsg + ); + +typedef +WINUSERAPI +HANDLE +(WINAPI *WinNtGetProcessHeap) (); + +typedef +WINUSERAPI +LPVOID +(WINAPI *WinNtHeapAlloc) ( + HANDLE hHeap, + DWORD dwFlags, + SIZE_T dwBytes + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtHeapFree) ( + HANDLE hHeap, + DWORD dwFlags, + LPVOID lpMem + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFreeLibrary) ( + HANDLE ModHandle + ); +// +// +// + +#define EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE EFI_SIGNATURE_32 ('N', 'T', 'T', 'T') + +typedef struct { + UINT64 Signature; + + // + // Win32 Process APIs + // + WinNtGetProcAddress GetProcAddress; + WinNtGetTickCount GetTickCount; + WinNtLoadLibraryEx LoadLibraryEx; + WinNtFreeLibrary FreeLibrary; + + WinNtSetPriorityClass SetPriorityClass; + WinNtSetThreadPriority SetThreadPriority; + WinNtSleep Sleep; + + WinNtSuspendThread SuspendThread; + WinNtGetCurrentThread GetCurrentThread; + WinNtGetCurrentThreadId GetCurrentThreadId; + WinNtGetCurrentProcess GetCurrentProcess; + WinNtCreateThread CreateThread; + WinNtTerminateThread TerminateThread; + WinNtSendMessage SendMessage; + WinNtExitThread ExitThread; + WinNtResumeThread ResumeThread; + WinNtDuplicateHandle DuplicateHandle; + + // + // Wint32 Mutex primitive + // + WinNtInitializeCriticalSection InitializeCriticalSection; + WinNtEnterCriticalSection EnterCriticalSection; + WinNtLeaveCriticalSection LeaveCriticalSection; + WinNtDeleteCriticalSection DeleteCriticalSection; + WinNtTlsAlloc TlsAlloc; + WinNtTlsFree TlsFree; + WinNtTlsSetValue TlsSetValue; + WinNtTlsGetValue TlsGetValue; + WinNtCreateSemaphore CreateSemaphore; + WinNtWaitForSingleObject WaitForSingleObject; + WinNtReleaseSemaphore ReleaseSemaphore; + + // + // Win32 Console APIs + // + WinNtCreateConsoleScreenBuffer CreateConsoleScreenBuffer; + WinNtFillConsoleOutputAttribute FillConsoleOutputAttribute; + WinNtFillConsoleOutputCharacter FillConsoleOutputCharacter; + WinNtGetConsoleCursorInfo GetConsoleCursorInfo; + WinNtGetNumberOfConsoleInputEvents GetNumberOfConsoleInputEvents; + WinNtPeekConsoleInput PeekConsoleInput; + WinNtScrollConsoleScreenBuffer ScrollConsoleScreenBuffer; + WinNtReadConsoleInput ReadConsoleInput; + + WinNtSetConsoleActiveScreenBuffer SetConsoleActiveScreenBuffer; + WinNtSetConsoleCursorInfo SetConsoleCursorInfo; + WinNtSetConsoleCursorPosition SetConsoleCursorPosition; + WinNtSetConsoleScreenBufferSize SetConsoleScreenBufferSize; + WinNtSetConsoleTitleW SetConsoleTitleW; + WinNtWriteConsoleInput WriteConsoleInput; + WinNtWriteConsoleOutput WriteConsoleOutput; + + // + // Win32 File APIs + // + WinNtCreateFile CreateFile; + WinNtDeviceIoControl DeviceIoControl; + WinNtCreateDirectory CreateDirectory; + WinNtRemoveDirectory RemoveDirectory; + WinNtGetFileAttributes GetFileAttributes; + WinNtSetFileAttributes SetFileAttributes; + WinNtCreateFileMapping CreateFileMapping; + WinNtCloseHandle CloseHandle; + WinNtDeleteFile DeleteFile; + WinNtFindFirstFile FindFirstFile; + WinNtFindNextFile FindNextFile; + WinNtFindClose FindClose; + WinNtFlushFileBuffers FlushFileBuffers; + WinNtGetEnvironmentVariable GetEnvironmentVariable; + WinNtGetLastError GetLastError; + WinNtSetErrorMode SetErrorMode; + WinNtGetStdHandle GetStdHandle; + WinNtMapViewOfFileEx MapViewOfFileEx; + WinNtReadFile ReadFile; + WinNtSetEndOfFile SetEndOfFile; + WinNtSetFilePointer SetFilePointer; + WinNtWriteFile WriteFile; + WinNtGetFileInformationByHandle GetFileInformationByHandle; + WinNtGetDiskFreeSpace GetDiskFreeSpace; + WinNtGetDiskFreeSpaceEx GetDiskFreeSpaceEx; + WinNtMoveFile MoveFile; + WinNtSetFileTime SetFileTime; + WinNtSystemTimeToFileTime SystemTimeToFileTime; + + // + // Win32 Time APIs + // + WinNtFileTimeToLocalFileTime FileTimeToLocalFileTime; + WinNtFileTimeToSystemTime FileTimeToSystemTime; + WinNtGetSystemTime GetSystemTime; + WinNtSetSystemTime SetSystemTime; + WinNtGetLocalTime GetLocalTime; + WinNtSetLocalTime SetLocalTime; + WinNtGetTimeZoneInformation GetTimeZoneInformation; + WinNtSetTimeZoneInformation SetTimeZoneInformation; + WinNttimeSetEvent timeSetEvent; + WinNttimeKillEvent timeKillEvent; + + // + // Win32 Serial APIs + // + WinNtClearCommError ClearCommError; + WinNtEscapeCommFunction EscapeCommFunction; + WinNtGetCommModemStatus GetCommModemStatus; + WinNtGetCommState GetCommState; + WinNtSetCommState SetCommState; + WinNtPurgeComm PurgeComm; + WinNtSetCommTimeouts SetCommTimeouts; + + WinNtExitProcess ExitProcess; + + WinNtSprintf SPrintf; + + WinNtGetDesktopWindow GetDesktopWindow; + WinNtGetForegroundWindow GetForegroundWindow; + WinNtCreateWindowEx CreateWindowEx; + WinNtShowWindow ShowWindow; + WinNtUpdateWindow UpdateWindow; + WinNtDestroyWindow DestroyWindow; + WinNtInvalidateRect InvalidateRect; + WinNtGetWindowDC GetWindowDC; + WinNtGetClientRect GetClientRect; + WinNtAdjustWindowRect AdjustWindowRect; + WinNtSetDIBitsToDevice SetDIBitsToDevice; + WinNtBitBlt BitBlt; + WinNtGetDC GetDC; + WinNtReleaseDC ReleaseDC; + WinNtRegisterClassEx RegisterClassEx; + WinNtUnregisterClass UnregisterClass; + + WinNtBeginPaint BeginPaint; + WinNtEndPaint EndPaint; + WinNtPostQuitMessage PostQuitMessage; + WinNtDefWindowProc DefWindowProc; + WinNtLoadIcon LoadIcon; + WinNtLoadCursor LoadCursor; + WinNtGetStockObject GetStockObject; + WinNtSetViewportOrgEx SetViewportOrgEx; + WinNtSetWindowOrgEx SetWindowOrgEx; + WinNtMoveWindow MoveWindow; + WinNtGetWindowRect GetWindowRect; + + WinNtGetMessage GetMessage; + WinNtTranslateMessage TranslateMessage; + WinNtDispatchMessage DispatchMessage; + + WinNtGetProcessHeap GetProcessHeap; + WinNtHeapAlloc HeapAlloc; + WinNtHeapFree HeapFree; + +} EFI_WIN_NT_THUNK_PROTOCOL; + +extern EFI_GUID gEfiWinNtThunkProtocolGuid; + +#endif diff --git a/EdkNt32Pkg/Include/WinNtDxe.h b/EdkNt32Pkg/Include/WinNtDxe.h new file mode 100644 index 0000000000..d82b2a2c45 --- /dev/null +++ b/EdkNt32Pkg/Include/WinNtDxe.h @@ -0,0 +1,38 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + WinNtLib.h + +Abstract: + Public include file for the WinNt Library + +--*/ + +#ifndef __WIN_NT_DXE_H__ +#define __WIN_NT_DXE_H__ + +#include +#include +#include +#include + +// +// This forces Windows.h WIN32 include file to be included +// it's needed for WinNtThunk.h +// WinNtIo.h depends on WinNtThunk.h +// +#include + +#include +#include + +#endif diff --git a/EdkNt32Pkg/Include/WinNtPeim.h b/EdkNt32Pkg/Include/WinNtPeim.h new file mode 100644 index 0000000000..0b2240b2f1 --- /dev/null +++ b/EdkNt32Pkg/Include/WinNtPeim.h @@ -0,0 +1,36 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + WinNtLib.h + +Abstract: + Public include file for the WinNt Library + +--*/ + +#ifndef __WIN_NT_PEIM_H__ +#define __WIN_NT_PEIM_H__ + +#include +#include +#include +#include + +// +// This forces Windows.h WIN32 include file to be included +// it's needed for WinNtThunk.h +// +#include + +#include + +#endif diff --git a/EdkNt32Pkg/Include/library/EdkGenericBdsLib.h b/EdkNt32Pkg/Include/library/EdkGenericBdsLib.h new file mode 100644 index 0000000000..3f01119041 --- /dev/null +++ b/EdkNt32Pkg/Include/library/EdkGenericBdsLib.h @@ -0,0 +1,332 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BdsLib.h + +Abstract: + + BDS library definition, include the file and data structure + +--*/ + +#ifndef _BDS_LIB_H_ +#define _BDS_LIB_H_ + +extern EFI_HANDLE mBdsImageHandle; + +// +// Constants which are variable names used to access variables +// +#define VarLegacyDevOrder L"LegacyDevOrder" + +// +// Data structures and defines +// +#define FRONT_PAGE_QUESTION_ID 0x0000 +#define FRONT_PAGE_DATA_WIDTH 0x01 + +// +// ConnectType +// +#define CONSOLE_OUT 0x00000001 +#define STD_ERROR 0x00000002 +#define CONSOLE_IN 0x00000004 +#define CONSOLE_ALL (CONSOLE_OUT | CONSOLE_IN | STD_ERROR) + +// +// Load Option Attributes defined in EFI Specification +// +#define LOAD_OPTION_ACTIVE 0x00000001 +#define LOAD_OPTION_FORCE_RECONNECT 0x00000002 +#define IS_LOAD_OPTION_TYPE(_c, _Mask) (BOOLEAN) (((_c) & (_Mask)) != 0) + +// +// Define Maxmim characters that will be accepted +// +#define MAX_CHAR 480 +#define MAX_CHAR_SIZE (MAX_CHAR * 2) + +#define MIN_ALIGNMENT_SIZE 4 +#define ALIGN_SIZE(a) ((a % MIN_ALIGNMENT_SIZE) ? MIN_ALIGNMENT_SIZE - (a % MIN_ALIGNMENT_SIZE) : 0) + +// +// This data structure is the part of BDS_CONNECT_ENTRY that we can hard code. +// +#define BDS_LOAD_OPTION_SIGNATURE EFI_SIGNATURE_32 ('B', 'd', 'C', 'O') + +typedef struct { + + UINTN Signature; + LIST_ENTRY Link; + + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + CHAR16 *OptionName; + UINTN OptionNumber; + UINT16 BootCurrent; + UINT32 Attribute; + CHAR16 *Description; + VOID *LoadOptions; + UINT32 LoadOptionsSize; + +} BDS_COMMON_OPTION; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN ConnectType; +} BDS_CONSOLE_CONNECT_ENTRY; + +// +// Lib Functions +// + +// +// Bds boot relate lib functions +// +EFI_STATUS +BdsLibUpdateBootOrderList ( + IN LIST_ENTRY *BdsOptionList, + IN CHAR16 *VariableName + ); + +VOID +BdsLibBootNext ( + VOID + ); + +EFI_STATUS +BdsLibBootViaBootOption ( + IN BDS_COMMON_OPTION * Option, + IN EFI_DEVICE_PATH_PROTOCOL * DevicePath, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ); + +EFI_STATUS +BdsLibEnumerateAllBootOption ( + IN OUT LIST_ENTRY *BdsBootOptionList + ); + +VOID +BdsLibBuildOptionFromHandle ( + IN EFI_HANDLE Handle, + IN LIST_ENTRY *BdsBootOptionList + ); + +VOID +BdsLibBuildOptionFromShell ( + IN EFI_HANDLE Handle, + IN LIST_ENTRY *BdsBootOptionList + ); + +// +// Bds misc lib functions +// +UINT16 +BdsLibGetTimeout ( + VOID + ); + +EFI_STATUS +BdsLibGetBootMode ( + OUT EFI_BOOT_MODE *BootMode + ); + +VOID +BdsLibLoadDrivers ( + IN LIST_ENTRY *BdsDriverLists + ); + +EFI_STATUS +BdsLibBuildOptionFromVar ( + IN LIST_ENTRY *BdsCommonOptionList, + IN CHAR16 *VariableName + ); + +VOID * +BdsLibGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ); + +EFI_STATUS +BdsLibOutputStrings ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *ConOut, + ... + ); + +BDS_COMMON_OPTION * +BdsLibVariableToOption ( + IN OUT LIST_ENTRY *BdsCommonOptionList, + IN CHAR16 *VariableName + ); + +EFI_STATUS +BdsLibRegisterNewOption ( + IN LIST_ENTRY *BdsOptionList, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CHAR16 *String, + IN CHAR16 *VariableName + ); + +// +// Bds connect or disconnect driver lib funcion +// +VOID +BdsLibConnectAllDriversToAllControllers ( + VOID + ); + +VOID +BdsLibConnectAll ( + VOID + ); + +EFI_STATUS +BdsLibConnectDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect + ); + +EFI_STATUS +BdsLibConnectAllEfi ( + VOID + ); + +EFI_STATUS +BdsLibDisconnectAllEfi ( + VOID + ); + +// +// Bds console relate lib functions +// +VOID +BdsLibConnectAllConsoles ( + VOID + ); + +EFI_STATUS +BdsLibConnectAllDefaultConsoles ( + VOID + ); + +EFI_STATUS +BdsLibUpdateConsoleVariable ( + IN CHAR16 *ConVarName, + IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath + ); + +EFI_STATUS +BdsLibConnectConsoleVariable ( + IN CHAR16 *ConVarName + ); + +// +// Bds device path relate lib functions +// +EFI_DEVICE_PATH_PROTOCOL * +BdsLibUnpackDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +BOOLEAN +BdsLibMatchDevicePaths ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ); + +CHAR16 * +DevicePathToStr ( + EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + +VOID * +EfiLibGetVariable ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid + ); + +// +// Internal definitions +// +typedef struct { + CHAR16 *str; + UINTN len; + UINTN maxlen; +} POOL_PRINT; + +typedef struct { + UINT8 Type; + UINT8 SubType; + VOID (*Function) (POOL_PRINT *, VOID *); +} DEVICE_PATH_STRING_TABLE; + +// +// Internal functions +// +EFI_STATUS +BdsBootByDiskSignatureAndPartition ( + IN BDS_COMMON_OPTION * Option, + IN HARDDRIVE_DEVICE_PATH * HardDriveDevicePath, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ); + +// +// Notes: EFI 64 shadow all option rom +// +#ifdef EFI64 +#define EFI64_SHADOW_ALL_LEGACY_ROM() ShadowAllOptionRom (); +VOID +ShadowAllOptionRom(); +#else +#define EFI64_SHADOW_ALL_LEGACY_ROM() +#endif + +// +// BBS support macros and functions +// +#ifdef EFI32 +#define REFRESH_LEGACY_BOOT_OPTIONS \ + BdsDeleteAllInvalidLegacyBootOptions ();\ + BdsAddNonExistingLegacyBootOptions (); \ + BdsUpdateLegacyDevOrder () +#else +#define REFRESH_LEGACY_BOOT_OPTIONS +#endif + +EFI_STATUS +BdsDeleteAllInvalidLegacyBootOptions ( + VOID + ); + +EFI_STATUS +BdsAddNonExistingLegacyBootOptions ( + VOID + ); + +EFI_STATUS +BdsUpdateLegacyDevOrder ( + VOID + ); + +EFI_STATUS +BdsRefreshBbsTableForBoot ( + IN BDS_COMMON_OPTION *Entry + ); + +#endif // _BDS_LIB_H_ diff --git a/EdkNt32Pkg/Include/library/WinNtLib.h b/EdkNt32Pkg/Include/library/WinNtLib.h new file mode 100644 index 0000000000..b9bccfc008 --- /dev/null +++ b/EdkNt32Pkg/Include/library/WinNtLib.h @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtLib.h + +Abstract: + + Public include file for the WinNt Library + +--*/ + +#ifndef __WIN_NT_LIB_H__ +#define __WIN_NT_LIB_H__ + +extern EFI_WIN_NT_THUNK_PROTOCOL *gWinNt; + +#endif \ No newline at end of file diff --git a/EdkNt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.mbd b/EdkNt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.mbd new file mode 100644 index 0000000000..a054a89442 --- /dev/null +++ b/EdkNt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.mbd @@ -0,0 +1,30 @@ + + + + + DxeWinNtLib + f6b5871d-5226-41b3-a569-3ff893fdc7bc + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-31 13:20 + + diff --git a/EdkNt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.msa b/EdkNt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.msa new file mode 100644 index 0000000000..d20cf4d350 --- /dev/null +++ b/EdkNt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.msa @@ -0,0 +1,55 @@ + + + + + DxeWinNtLib + DXE_DRIVER + LIBRARY + f6b5871d-5226-41b3-a569-3ff893fdc7bc + EDK_RELEASE_VERSION 0x00020000 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-14 17:04 + 2006-03-31 13:20 + + + WinNtLib + DebugLib + HobLib + + + WinNtLib.c + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + WinNtThunk + + + + WinNtLibConstructor + + + diff --git a/EdkNt32Pkg/Library/DxeWinNtLib/WinNtLib.c b/EdkNt32Pkg/Library/DxeWinNtLib/WinNtLib.c new file mode 100644 index 0000000000..9010d8ae24 --- /dev/null +++ b/EdkNt32Pkg/Library/DxeWinNtLib/WinNtLib.c @@ -0,0 +1,48 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtLib.c + +Abstract: + + WinNt Library + +--*/ + + + +EFI_WIN_NT_THUNK_PROTOCOL *gWinNt; + +EFI_STATUS +WinNtLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + EFI_HOB_GUID_TYPE *GuidHob; + + GuidHob = GetFirstGuidHob (&gEfiWinNtThunkProtocolGuid); + ASSERT (GuidHob != NULL); + gWinNt = (EFI_WIN_NT_THUNK_PROTOCOL *)(*(UINTN *)(GET_GUID_HOB_DATA (GuidHob))); + ASSERT (gWinNt != NULL); + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Library/DxeWinNtLib/build.xml b/EdkNt32Pkg/Library/DxeWinNtLib/build.xml new file mode 100644 index 0000000000..5d4ab2c855 --- /dev/null +++ b/EdkNt32Pkg/Library/DxeWinNtLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c b/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c new file mode 100644 index 0000000000..c9b1eede1c --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsBoot.c @@ -0,0 +1,795 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BdsBoot.c + +Abstract: + + BDS Lib functions which relate with create or process the boot + option. + +--*/ +#include "Performance.h" + +BOOLEAN mEnumBootDevice = FALSE; + +EFI_STATUS +BdsLibDoLegacyBoot ( + IN BDS_COMMON_OPTION *Option + ) +/*++ + +Routine Description: + + Boot the legacy system with the boot option + +Arguments: + + Option - The legacy boot option which have BBS device path + +Returns: + + EFI_UNSUPPORTED - There is no legacybios protocol, do not support + legacy boot. + + EFI_STATUS - Return the status of LegacyBios->LegacyBoot (). + +--*/ +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + + Status = gBS->LocateProtocol (&gEfiLegacyBiosProtocolGuid, NULL, &LegacyBios); + if (EFI_ERROR (Status)) { + // + // If no LegacyBios protocol we do not support legacy boot + // + return EFI_UNSUPPORTED; + } + // + // Notes: if we seperate the int 19, then we don't need to refresh BBS + // + BdsRefreshBbsTableForBoot (Option); + + // + // Write boot to OS performance data to a file + // + PERF_CODE ( + WriteBootToOsPerformanceData (); + ); + + + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Legacy Boot: %S\n", Option->Description)); + return LegacyBios->LegacyBoot ( + LegacyBios, + (BBS_BBS_DEVICE_PATH *) Option->DevicePath, + Option->LoadOptionsSize, + Option->LoadOptions + ); +} + +EFI_STATUS +BdsLibBootViaBootOption ( + IN BDS_COMMON_OPTION * Option, + IN EFI_DEVICE_PATH_PROTOCOL * DevicePath, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ) +/*++ + +Routine Description: + + Process the boot option follow the EFI 1.1 specification and + special treat the legacy boot option with BBS_DEVICE_PATH. + +Arguments: + + Option - The boot option need to be processed + + DevicePath - The device path which describe where to load + the boot image or the legcy BBS device path + to boot the legacy OS + + ExitDataSize - Returned directly from gBS->StartImage () + + ExitData - Returned directly from gBS->StartImage () + +Returns: + + EFI_SUCCESS - Status from gBS->StartImage (), + or BdsBootByDiskSignatureAndPartition () + + EFI_NOT_FOUND - If the Device Path is not found in the system + +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + EFI_HANDLE ImageHandle; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; + EFI_ACPI_S3_SAVE_PROTOCOL *AcpiS3Save; + + *ExitDataSize = 0; + *ExitData = NULL; + + // + // Notes: put EFI64 ROM Shadow Solution + // + EFI64_SHADOW_ALL_LEGACY_ROM (); + + // + // Notes: this code can be remove after the s3 script table + // hook on the event EFI_EVENT_SIGNAL_READY_TO_BOOT or + // EFI_EVENT_SIGNAL_LEGACY_BOOT + // + Status = gBS->LocateProtocol (&gEfiAcpiS3SaveProtocolGuid, NULL, &AcpiS3Save); + if (!EFI_ERROR (Status)) { + AcpiS3Save->S3Save (AcpiS3Save, NULL); + } + // + // If it's Device Path that starts with a hard drive path, + // this routine will do the booting. + // + Status = BdsBootByDiskSignatureAndPartition ( + Option, + (HARDDRIVE_DEVICE_PATH *) DevicePath, + Option->LoadOptionsSize, + Option->LoadOptions, + ExitDataSize, + ExitData + ); + if (!EFI_ERROR (Status)) { + // + // If we found a disk signature and partition device path return success + // + return EFI_SUCCESS; + } + + EfiSignalEventReadyToBoot (); + + // + // Set Boot Current + // + gRT->SetVariable ( + L"BootCurrent", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (UINT16), + &Option->BootCurrent + ); + + if ((DevicePathType (Option->DevicePath) == BBS_DEVICE_PATH) && + (DevicePathSubType (Option->DevicePath) == BBS_BBS_DP) + ) { + // + // Check to see if we should legacy BOOT. If yes then do the legacy boot + // + return BdsLibDoLegacyBoot (Option); + } + + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Booting EFI 1.1 way %S\n", Option->Description)); + + Status = gBS->LoadImage ( + TRUE, + mBdsImageHandle, + DevicePath, + NULL, + 0, + &ImageHandle + ); + + // + // If we didn't find an image, we may need to load the default + // boot behavior for the device. + // + if (EFI_ERROR (Status)) { + // + // Find a Simple File System protocol on the device path. If the remaining + // device path is set to end then no Files are being specified, so try + // the removable media file name. + // + TempDevicePath = DevicePath; + Status = gBS->LocateDevicePath ( + &gEfiSimpleFileSystemProtocolGuid, + &TempDevicePath, + &Handle + ); + if (!EFI_ERROR (Status) && IsDevicePathEnd (TempDevicePath)) { + FilePath = FileDevicePath (Handle, EFI_REMOVABLE_MEDIA_FILE_NAME); + if (FilePath) { + Status = gBS->LoadImage ( + TRUE, + mBdsImageHandle, + FilePath, + NULL, + 0, + &ImageHandle + ); + if (EFI_ERROR (Status)) { + // + // The DevicePath failed, and it's not a valid + // removable media device. + // + goto Done; + } + } + } else { + Status = EFI_NOT_FOUND; + } + } + + if (EFI_ERROR (Status)) { + // + // It there is any error from the Boot attempt exit now. + // + goto Done; + } + // + // Provide the image with it's load options + // + Status = gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, &ImageInfo); + ASSERT_EFI_ERROR (Status); + + if (Option->LoadOptionsSize != 0) { + ImageInfo->LoadOptionsSize = Option->LoadOptionsSize; + ImageInfo->LoadOptions = Option->LoadOptions; + } + // + // Before calling the image, enable the Watchdog Timer for + // the 5 Minute period + // + gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL); + + Status = gBS->StartImage (ImageHandle, ExitDataSize, ExitData); + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Image Return Status = %r\n", Status)); + + // + // Clear the Watchdog Timer after the image returns + // + gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL); + +Done: + // + // Clear Boot Current + // + gRT->SetVariable ( + L"BootCurrent", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + 0, + &Option->BootCurrent + ); + + return Status; +} + +EFI_STATUS +BdsBootByDiskSignatureAndPartition ( + IN BDS_COMMON_OPTION * Option, + IN HARDDRIVE_DEVICE_PATH * HardDriveDevicePath, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ) +/*++ + +Routine Description: + + Check to see if a hard ware device path was passed in. If it was then search + all the block IO devices for the passed in hard drive device path. + +Arguments: + + Option - The current processing boot option. + + HardDriveDevicePath - EFI Device Path to boot, if it starts with a hard + drive device path. + + LoadOptionsSize - Passed into gBS->StartImage () + via the loaded image protocol. + + LoadOptions - Passed into gBS->StartImage () + via the loaded image protocol. + + ExitDataSize - returned directly from gBS->StartImage () + + ExitData - returned directly from gBS->StartImage () + +Returns: + + EFI_SUCCESS - Status from gBS->StartImage (), + or BootByDiskSignatureAndPartition () + + EFI_NOT_FOUND - If the Device Path is not found in the system + +--*/ +{ + EFI_STATUS Status; + UINTN BlockIoHandleCount; + EFI_HANDLE *BlockIoBuffer; + EFI_DEVICE_PATH_PROTOCOL *BlockIoDevicePath; + EFI_DEVICE_PATH_PROTOCOL *BlockIoHdDevicePath; + HARDDRIVE_DEVICE_PATH *TmpHdPath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + UINTN Index; + BOOLEAN DevicePathMatch; + HARDDRIVE_DEVICE_PATH *TempPath; + + *ExitDataSize = 0; + *ExitData = NULL; + + if ( !((DevicePathType (&HardDriveDevicePath->Header) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (&HardDriveDevicePath->Header) == MEDIA_HARDDRIVE_DP)) + ) { + // + // If the HardDriveDevicePath does not start with a Hard Drive Device Path + // exit. + // + return EFI_NOT_FOUND; + } + // + // The boot device have already been connected + // + Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiBlockIoProtocolGuid, NULL, &BlockIoHandleCount, &BlockIoBuffer); + if (EFI_ERROR (Status) || BlockIoHandleCount == 0) { + // + // If there was an error or there are no device handles that support + // the BLOCK_IO Protocol, then return. + // + return EFI_NOT_FOUND; + } + // + // Loop through all the device handles that support the BLOCK_IO Protocol + // + for (Index = 0; Index < BlockIoHandleCount; Index++) { + + Status = gBS->HandleProtocol (BlockIoBuffer[Index], &gEfiDevicePathProtocolGuid, (VOID *) &BlockIoDevicePath); + if (EFI_ERROR (Status) || BlockIoDevicePath == NULL) { + continue; + } + // + // Make PreviousDevicePath == the device path node before the end node + // + DevicePath = BlockIoDevicePath; + BlockIoHdDevicePath = NULL; + + // + // find HardDriver device path node + // + while (!IsDevicePathEnd (DevicePath)) { + if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP) + ) { + BlockIoHdDevicePath = DevicePath; + break; + } + + DevicePath = NextDevicePathNode (DevicePath); + } + + if (BlockIoHdDevicePath == NULL) { + continue; + } + // + // See if the harddrive device path in blockio matches the orig Hard Drive Node + // + DevicePathMatch = FALSE; + + TmpHdPath = (HARDDRIVE_DEVICE_PATH *) BlockIoHdDevicePath; + TempPath = (HARDDRIVE_DEVICE_PATH *) BdsLibUnpackDevicePath ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath); + + // + // Only several fields will be checked. NOT whole NODE + // + if ( TmpHdPath->PartitionNumber == TempPath->PartitionNumber && + TmpHdPath->MBRType == TempPath->MBRType && + TmpHdPath->SignatureType == TempPath->SignatureType && + CompareGuid ((EFI_GUID *) TmpHdPath->Signature, (EFI_GUID *) TempPath->Signature)) { + // + // Get the matched device path + // + DevicePathMatch = TRUE; + } + // + // Only do the boot, when devicepath match + // + if (DevicePathMatch) { + // + // Combine the Block IO and Hard Drive Device path together and try + // to boot from it. + // + DevicePath = NextDevicePathNode ((EFI_DEVICE_PATH_PROTOCOL *) HardDriveDevicePath); + NewDevicePath = AppendDevicePath (BlockIoDevicePath, DevicePath); + + // + // Recursive boot with new device path + // + Status = BdsLibBootViaBootOption (Option, NewDevicePath, ExitDataSize, ExitData); + if (!EFI_ERROR (Status)) { + break; + } + } + } + + gBS->FreePool (BlockIoBuffer); + return Status; +} + +EFI_STATUS +BdsLibEnumerateAllBootOption ( + IN OUT LIST_ENTRY *BdsBootOptionList + ) +/*++ + +Routine Description: + + This function will enumerate all possible boot device in the system, + it will only excute once of every boot. + +Arguments: + + BdsBootOptionList - The header of the link list which indexed all + current boot options + +Returns: + + EFI_SUCCESS - Finished all the boot device enumerate and create + the boot option base on that boot device + +--*/ +{ + EFI_STATUS Status; + UINT16 BootOptionNumber; + UINTN NumberFileSystemHandles; + EFI_HANDLE *FileSystemHandles; + UINTN NumberBlkIoHandles; + EFI_HANDLE *BlkIoHandles; + EFI_BLOCK_IO_PROTOCOL *BlkIo; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN NumberLoadFileHandles; + EFI_HANDLE *LoadFileHandles; + VOID *ProtocolInstance; + EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; + UINTN FvHandleCount; + EFI_HANDLE *FvHandleBuffer; + EFI_FV_FILETYPE Type; + UINTN Size; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINT32 AuthenticationStatus; + + BootOptionNumber = 0; + + // + // If the boot device enumerate happened, just get the boot + // device from the boot order variable + // + if (mEnumBootDevice) { + BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder"); + return EFI_SUCCESS; + } + // + // Notes: this dirty code is to get the legacy boot option from the + // BBS table and create to variable as the EFI boot option, it should + // be removed after the CSM can provide legacy boot option directly + // + REFRESH_LEGACY_BOOT_OPTIONS; + + // + // Check all the block IO to create boot option + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiBlockIoProtocolGuid, + NULL, + &NumberBlkIoHandles, + &BlkIoHandles + ); + for (Index = 0; Index < NumberBlkIoHandles; Index++) { + Status = gBS->HandleProtocol ( + BlkIoHandles[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (!BlkIo->Media->RemovableMedia) { + // + // Skip fixed Media device on first loop interration + // + continue; + } + + DevicePath = DevicePathFromHandle (BlkIoHandles[Index]); + if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP) + ) { + // + // Build the boot option + // + BdsLibBuildOptionFromHandle (BlkIoHandles[Index], BdsBootOptionList); + BootOptionNumber++; + } + } + + if (NumberBlkIoHandles) { + gBS->FreePool (BlkIoHandles); + } + // + // Parse Fixed Disk Devices. + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleFileSystemProtocolGuid, + NULL, + &NumberFileSystemHandles, + &FileSystemHandles + ); + for (Index = 0; Index < NumberFileSystemHandles; Index++) { + Status = gBS->HandleProtocol ( + FileSystemHandles[Index], + &gEfiBlockIoProtocolGuid, + (VOID **) &BlkIo + ); + if (!EFI_ERROR (Status)) { + if (BlkIo->Media->RemovableMedia) { + // + // If the file system handle supports a BlkIo protocol, + // skip the removable media devices + // + continue; + } + } + + DevicePath = DevicePathFromHandle (FileSystemHandles[Index]); + if ((DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) && + (DevicePathSubType (DevicePath) == MEDIA_HARDDRIVE_DP) + ) { + // + // If the FileSystem protocol does not contain a BlkIo protocol, + // then build it + // + BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList); + BootOptionNumber++; + } + } + + if (NumberFileSystemHandles) { + gBS->FreePool (FileSystemHandles); + } + // + // Parse Network Boot Device + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleNetworkProtocolGuid, + NULL, + &NumberLoadFileHandles, + &LoadFileHandles + ); + for (Index = 0; Index < NumberLoadFileHandles; Index++) { + Status = gBS->HandleProtocol ( + LoadFileHandles[Index], + &gEfiLoadFileProtocolGuid, + (VOID **) &ProtocolInstance + ); + if (EFI_ERROR (Status)) { + continue; + } + + BdsLibBuildOptionFromHandle (LoadFileHandles[Index], BdsBootOptionList); + BootOptionNumber++; + } + + if (NumberLoadFileHandles) { + gBS->FreePool (LoadFileHandles); + } + // + // Check if we have on flash shell + // + gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolumeProtocolGuid, + NULL, + &FvHandleCount, + &FvHandleBuffer + ); + for (Index = 0; Index < FvHandleCount; Index++) { + gBS->HandleProtocol ( + FvHandleBuffer[Index], + &gEfiFirmwareVolumeProtocolGuid, + (VOID **) &Fv + ); + + Status = Fv->ReadFile ( + Fv, + &gEfiShellFileGuid, + NULL, + &Size, + &Type, + &Attributes, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + // + // Skip if no shell file in the FV + // + continue; + } + // + // Build the shell boot option + // + BdsLibBuildOptionFromShell (FvHandleBuffer[Index], BdsBootOptionList); + BootOptionNumber++; + } + + if (FvHandleCount) { + gBS->FreePool (FvHandleBuffer); + } + // + // Make sure every boot only have one time + // boot device enumerate + // + BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder"); + mEnumBootDevice = TRUE; + + return EFI_SUCCESS; +} + +VOID +BdsLibBuildOptionFromHandle ( + IN EFI_HANDLE Handle, + IN LIST_ENTRY *BdsBootOptionList + ) +/*++ + +Routine Description: + + Build the boot option with the handle parsed in + +Arguments: + + Handle - The handle which present the device path to create boot option + + BdsBootOptionList - The header of the link list which indexed all current + boot options + +Returns: + + VOID + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + CHAR16 *TempString; + + DevicePath = DevicePathFromHandle (Handle); + TempString = DevicePathToStr (DevicePath); + + // + // Create and register new boot option + // + BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, TempString, L"BootOrder"); +} + +VOID +BdsLibBuildOptionFromShell ( + IN EFI_HANDLE Handle, + IN OUT LIST_ENTRY *BdsBootOptionList + ) +/*++ + +Routine Description: + + Build the on flash shell boot option with the handle parsed in + +Arguments: + + Handle - The handle which present the device path to create on flash shell + boot option + + BdsBootOptionList - The header of the link list which indexed all current + boot options + +Returns: + + None + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH ShellNode; + + DevicePath = DevicePathFromHandle (Handle); + + // + // Build the shell device path + // + EfiInitializeFwVolDevicepathNode (&ShellNode, &gEfiShellFileGuid); + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) &ShellNode); + + // + // Create and register the shell boot option + // + BdsLibRegisterNewOption (BdsBootOptionList, DevicePath, L"Internal EFI Shell", L"BootOrder"); + +} + +VOID +BdsLibBootNext ( + VOID + ) +/*++ + +Routine Description: + + Boot from the EFI1.1 spec defined "BootNext" variable + +Arguments: + + None + +Returns: + + None + +--*/ +{ + UINT16 *BootNext; + UINTN BootNextSize; + CHAR16 Buffer[20]; + BDS_COMMON_OPTION *BootOption; + LIST_ENTRY TempList; + UINTN ExitDataSize; + CHAR16 *ExitData; + + // + // Init the boot option name buffer and temp link list + // + InitializeListHead (&TempList); + ZeroMem (Buffer, sizeof (Buffer)); + + BootNext = BdsLibGetVariableAndSize ( + L"BootNext", + &gEfiGlobalVariableGuid, + &BootNextSize + ); + + // + // Clear the boot next variable first + // + if (BootNext != NULL) { + gRT->SetVariable ( + L"BootNext", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + 0, + BootNext + ); + + // + // Start to build the boot option and try to boot + // + UnicodeSPrint (Buffer, sizeof (Buffer), L"Boot%04x", *BootNext); + BootOption = BdsLibVariableToOption (&TempList, Buffer); + BdsLibConnectDevicePath (BootOption->DevicePath); + BdsLibBootViaBootOption (BootOption, BootOption->DevicePath, &ExitDataSize, &ExitData); + } + +} diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsConnect.c b/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsConnect.c new file mode 100644 index 0000000000..9c649f1f82 --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsConnect.c @@ -0,0 +1,357 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BdsConnect.c + +Abstract: + + BDS Lib functions which relate with connect the device + +--*/ + +VOID +BdsLibConnectAll ( + VOID + ) +/*++ + +Routine Description: + + This function will connect all the system driver to controller + first, and then special connect the default console, this make + sure all the system controller avialbe and the platform default + console connected. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + // + // Connect the platform console first + // + BdsLibConnectAllDefaultConsoles (); + + // + // Generic way to connect all the drivers + // + BdsLibConnectAllDriversToAllControllers (); + + // + // Here we have the assumption that we have already had + // platform default console + // + BdsLibConnectAllDefaultConsoles (); +} + +VOID +BdsLibGenericConnectAll ( + VOID + ) +/*++ + +Routine Description: + + This function will connect all the system drivers to all controllers + first, and then connect all the console devices the system current + have. After this we should get all the device work and console avariable + if the system have console device. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + // + // Most generic way to connect all the drivers + // + BdsLibConnectAllDriversToAllControllers (); + BdsLibConnectAllConsoles (); +} + +EFI_STATUS +BdsLibConnectDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect + ) +/*++ + +Routine Description: + This function will create all handles associate with every device + path node. If the handle associate with one device path node can not + be created success, then still give one chance to do the dispatch, + which load the missing drivers if possible. + +Arguments: + + DevicePathToConnect - The device path which will be connected, it can + be a multi-instance device path + +Returns: + + EFI_SUCCESS - All handles associate with every device path + node have been created + + EFI_OUT_OF_RESOURCES - There is no resource to create new handles + + EFI_NOT_FOUND - Create the handle associate with one device + path node failed + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath; + EFI_DEVICE_PATH_PROTOCOL *Next; + EFI_HANDLE Handle; + EFI_HANDLE PreviousHandle; + UINTN Size; + + if (DevicePathToConnect == NULL) { + return EFI_SUCCESS; + } + + DevicePath = DuplicateDevicePath (DevicePathToConnect); + CopyOfDevicePath = DevicePath; + if (DevicePath == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + do { + // + // The outer loop handles multi instance device paths. + // Only console variables contain multiple instance device paths. + // + // After this call DevicePath points to the next Instance + // + Instance = GetNextDevicePathInstance (&DevicePath, &Size); + Next = Instance; + while (!IsDevicePathEndType (Next)) { + Next = NextDevicePathNode (Next); + } + + SetDevicePathEndNode (Next); + + // + // Start the real work of connect with RemainingDevicePath + // + PreviousHandle = NULL; + do { + // + // Find the handle that best matches the Device Path. If it is only a + // partial match the remaining part of the device path is returned in + // RemainingDevicePath. + // + RemainingDevicePath = Instance; + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle); + + if (!EFI_ERROR (Status)) { + if (Handle == PreviousHandle) { + // + // If no forward progress is made try invoking the Dispatcher. + // A new FV may have been added to the system an new drivers + // may now be found. + // Status == EFI_SUCCESS means a driver was dispatched + // Status == EFI_NOT_FOUND means no new drivers were dispatched + // + Status = gDS->Dispatch (); + } + + if (!EFI_ERROR (Status)) { + PreviousHandle = Handle; + // + // Connect all drivers that apply to Handle and RemainingDevicePath, + // the Recursive flag is FALSE so only one level will be expanded. + // + // Do not check the connect status here, if the connect controller fail, + // then still give the chance to do dispatch, because partial + // RemainingDevicepath may be in the new FV + // + // 1. If the connect fail, RemainingDevicepath and handle will not + // change, so next time will do the dispatch, then dispatch's status + // will take effect + // 2. If the connect success, the RemainingDevicepath and handle will + // change, then avoid the dispatch, we have chance to continue the + // next connection + // + gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE); + } + } + // + // Loop until RemainingDevicePath is an empty device path + // + } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath)); + + } while (DevicePath != NULL); + + if (CopyOfDevicePath != NULL) { + gBS->FreePool (CopyOfDevicePath); + } + // + // All handle with DevicePath exists in the handle database + // + return Status; +} + +EFI_STATUS +BdsLibConnectAllEfi ( + VOID + ) +/*++ + +Routine Description: + + This function will connect all current system handles recursively. The + connection will finish until every handle's child handle created if it have. + +Arguments: + + None + +Returns: + + EFI_SUCCESS - All handles and it's child handle have been connected + + EFI_STATUS - Return the status of gBS->LocateHandleBuffer(). + +--*/ +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE); + } + + gBS->FreePool (HandleBuffer); + + return EFI_SUCCESS; +} + +EFI_STATUS +BdsLibDisconnectAllEfi ( + VOID + ) +/*++ + +Routine Description: + + This function will disconnect all current system handles. The disconnection + will finish until every handle have been disconnected. + +Arguments: + + None + +Returns: + + EFI_SUCCESS - All handles have been disconnected + + EFI_STATUS - Return the status of gBS->LocateHandleBuffer(). + +--*/ +{ + EFI_STATUS Status; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + UINTN Index; + + // + // Disconnect all + // + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->DisconnectController (HandleBuffer[Index], NULL, NULL); + } + + gBS->FreePool (HandleBuffer); + + return EFI_SUCCESS; +} + +VOID +BdsLibConnectAllDriversToAllControllers ( + VOID + ) +/*++ + +Routine Description: + + Connects all drivers to all controllers. + This function make sure all the current system driver will manage + the correspoinding controllers if have. And at the same time, make + sure all the system controllers have driver to manage it if have. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + + do { + // + // Connect All EFI 1.10 drivers following EFI 1.10 algorithm + // + BdsLibConnectAllEfi (); + + // + // Check to see if it's possible to dispatch an more DXE drivers. + // The BdsLibConnectAllEfi () may have made new DXE drivers show up. + // If anything is Dispatched Status == EFI_SUCCESS and we will try + // the connect again. + // + Status = gDS->Dispatch (); + + } while (!EFI_ERROR (Status)); + +} diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsConsole.c b/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsConsole.c new file mode 100644 index 0000000000..721d74363a --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsConsole.c @@ -0,0 +1,370 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BdsConsole.c + +Abstract: + + BDS Lib functions which contain all the code to connect console device + +--*/ + +EFI_STATUS +BdsLibUpdateConsoleVariable ( + IN CHAR16 *ConVarName, + IN EFI_DEVICE_PATH_PROTOCOL *CustomizedConDevicePath, + IN EFI_DEVICE_PATH_PROTOCOL *ExclusiveDevicePath + ) +/*++ + +Routine Description: + + This function update console variable based on ConVarName, it can + add or remove one specific console device path from the variable + +Arguments: + + ConVarName - Console related variable name, ConIn, ConOut, ErrOut. + + CustomizedConDevicePath - The console device path which will be added to + the console variable ConVarName, this parameter + can not be multi-instance. + + ExclusiveDevicePath - The console device path which will be removed + from the console variable ConVarName, this + parameter can not be multi-instance. + +Returns: + + EFI_UNSUPPORTED - Add or remove the same device path. + + EFI_SUCCESS - Success add or remove the device path from + the console variable. + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *VarConsole; + UINTN DevicePathSize; + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + + VarConsole = NULL; + DevicePathSize = 0; + NewDevicePath = NULL; + Status = EFI_UNSUPPORTED; + + // + // Notes: check the device path point, here should check + // with compare memory + // + if (CustomizedConDevicePath == ExclusiveDevicePath) { + return EFI_UNSUPPORTED; + } + // + // Delete the ExclusiveDevicePath from current default console + // + VarConsole = BdsLibGetVariableAndSize ( + ConVarName, + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + + if (ExclusiveDevicePath != NULL && VarConsole != NULL) { + if (BdsLibMatchDevicePaths (VarConsole, ExclusiveDevicePath)) { + + Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize); + + while (VarConsole != NULL) { + if (CompareMem ( + Instance, + ExclusiveDevicePath, + DevicePathSize - sizeof (EFI_DEVICE_PATH_PROTOCOL) + ) == 0) { + // + // Remove the match part + // + NewDevicePath = AppendDevicePathInstance (NewDevicePath, VarConsole); + break; + } else { + // + // Continue the next instance + // + NewDevicePath = AppendDevicePathInstance (NewDevicePath, Instance); + } + + Instance = GetNextDevicePathInstance (&VarConsole, &DevicePathSize); + } + // + // Reset the console variable with new device path + // + gRT->SetVariable ( + ConVarName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + GetDevicePathSize (NewDevicePath), + NewDevicePath + ); + } + } + // + // Try to append customized device path + // + VarConsole = BdsLibGetVariableAndSize ( + ConVarName, + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + + if (CustomizedConDevicePath != NULL) { + if (!BdsLibMatchDevicePaths (VarConsole, CustomizedConDevicePath)) { + // + // In the first check, the default console variable will be null, + // just append current customized device path + // + VarConsole = AppendDevicePathInstance (VarConsole, CustomizedConDevicePath); + + // + // Update the variable of the default console + // + gRT->SetVariable ( + ConVarName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + GetDevicePathSize (VarConsole), + VarConsole + ); + } + } + + return EFI_SUCCESS; + +} + +EFI_STATUS +BdsLibConnectConsoleVariable ( + IN CHAR16 *ConVarName + ) +/*++ + +Routine Description: + + Connect the console device base on the variable ConVarName, if + device path of the ConVarName is multi-instance device path, if + anyone of the instances is connected success, then this function + will return success. + +Arguments: + + ConVarName - Console related variable name, ConIn, ConOut, ErrOut. + +Returns: + + EFI_NOT_FOUND - There is not any console devices connected success + + EFI_SUCCESS - Success connect any one instance of the console + device path base on the variable ConVarName. + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *StartDevicePath; + UINTN VariableSize; + EFI_DEVICE_PATH_PROTOCOL *Instance; + EFI_DEVICE_PATH_PROTOCOL *Next; + EFI_DEVICE_PATH_PROTOCOL *CopyOfDevicePath; + UINTN Size; + BOOLEAN DeviceExist; + + Status = EFI_SUCCESS; + DeviceExist = FALSE; + + // + // Check if the console variable exist + // + StartDevicePath = BdsLibGetVariableAndSize ( + ConVarName, + &gEfiGlobalVariableGuid, + &VariableSize + ); + if (StartDevicePath == NULL) { + return EFI_UNSUPPORTED; + } + + CopyOfDevicePath = DuplicateDevicePath (StartDevicePath); + do { + // + // Check every instance of the console variable + // + Instance = GetNextDevicePathInstance (&CopyOfDevicePath, &Size); + Next = Instance; + while (!IsDevicePathEndType (Next)) { + Next = NextDevicePathNode (Next); + } + + SetDevicePathEndNode (Next); + + // + // Connect the instance device path + // + Status = BdsLibConnectDevicePath (Instance); + if (EFI_ERROR (Status)) { + // + // Delete the instance from the console varialbe + // + BdsLibUpdateConsoleVariable (ConVarName, NULL, Instance); + } else { + DeviceExist = TRUE; + } + + } while (CopyOfDevicePath != NULL); + + gBS->FreePool (StartDevicePath); + + if (DeviceExist == FALSE) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +VOID +BdsLibConnectAllConsoles ( + VOID + ) +/*++ + +Routine Description: + + This function will search every simpletxt devive in current system, + and make every simpletxt device as pertantial console device. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_DEVICE_PATH_PROTOCOL *ConDevicePath; + UINTN HandleCount; + EFI_HANDLE *HandleBuffer; + + Index = 0; + HandleCount = 0; + HandleBuffer = NULL; + ConDevicePath = NULL; + + // + // Update all the console varables + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleTextInProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID **) &ConDevicePath + ); + BdsLibUpdateConsoleVariable (L"ConIn", ConDevicePath, NULL); + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiSimpleTextOutProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + for (Index = 0; Index < HandleCount; Index++) { + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiDevicePathProtocolGuid, + (VOID **) &ConDevicePath + ); + BdsLibUpdateConsoleVariable (L"ConOut", ConDevicePath, NULL); + BdsLibUpdateConsoleVariable (L"ErrOut", ConDevicePath, NULL); + } + // + // Connect all console variables + // + BdsLibConnectAllDefaultConsoles (); + +} + +EFI_STATUS +BdsLibConnectAllDefaultConsoles ( + VOID + ) +/*++ + +Routine Description: + + This function will connect console device base on the console + device variable ConIn, ConOut and ErrOut. + +Arguments: + + None + +Returns: + + EFI_SUCCESS - At least one of the ConIn and ConOut device have + been connected success. + + EFI_STATUS - Return the status of BdsLibConnectConsoleVariable (). + +--*/ +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *VarErrout; + UINTN DevicePathSize; + + // + // Connect all default console variables + // + Status = BdsLibConnectConsoleVariable (L"ConIn"); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = BdsLibConnectConsoleVariable (L"ConOut"); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Special treat the err out device, becaues the null + // err out var is legal. + // + VarErrout = BdsLibGetVariableAndSize ( + L"ErrOut", + &gEfiGlobalVariableGuid, + &DevicePathSize + ); + if (VarErrout != NULL) { + BdsLibConnectConsoleVariable (L"ErrOut"); + } + + return EFI_SUCCESS; + +} diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsMisc.c b/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsMisc.c new file mode 100644 index 0000000000..576ae7237f --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/BdsMisc.c @@ -0,0 +1,764 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BdsMisc.c + +Abstract: + + Misc BDS library function + +--*/ + +extern UINT16 gPlatformBootTimeOutDefault; + +UINT16 +BdsLibGetTimeout ( + VOID + ) +/*++ + +Routine Description: + + Return the default value for system Timeout variable. + +Arguments: + + None + +Returns: + + Timeout value. + +--*/ +{ + UINT16 Timeout; + UINTN Size; + EFI_STATUS Status; + + // + // Return Timeout variable or 0xffff if no valid + // Timeout variable exists. + // + Size = sizeof (UINT16); + Status = gRT->GetVariable (L"Timeout", &gEfiGlobalVariableGuid, NULL, &Size, &Timeout); + if (!EFI_ERROR (Status)) { + return Timeout; + } + // + // To make the current EFI Automatic-Test activity possible, just add + // following code to make AutoBoot enabled when this variable is not + // present. + // This code should be removed later. + // + Timeout = gPlatformBootTimeOutDefault; + + // + // Notes: Platform should set default variable if non exists on all error cases!!! + // + Status = gRT->SetVariable ( + L"Timeout", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + sizeof (UINT16), + &Timeout + ); + return Timeout; +} + +VOID +BdsLibLoadDrivers ( + IN LIST_ENTRY *BdsDriverLists + ) +/*++ + +Routine Description: + + The function will go through the driver optoin link list, load and start + every driver the driver optoin device path point to. + +Arguments: + + BdsDriverLists - The header of the current driver option link list + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + LIST_ENTRY *Link; + BDS_COMMON_OPTION *Option; + EFI_HANDLE ImageHandle; + EFI_LOADED_IMAGE_PROTOCOL *ImageInfo; + UINTN ExitDataSize; + CHAR16 *ExitData; + BOOLEAN ReconnectAll; + + ReconnectAll = FALSE; + + // + // Process the driver option + // + for (Link = BdsDriverLists->ForwardLink; Link != BdsDriverLists; Link = Link->ForwardLink) { + Option = CR (Link, BDS_COMMON_OPTION, Link, BDS_LOAD_OPTION_SIGNATURE); + // + // If a load option is not marked as LOAD_OPTION_ACTIVE, + // the boot manager will not automatically load the option. + // + if (!IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_ACTIVE)) { + continue; + } + // + // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT, + // then all of the EFI drivers in the system will be disconnected and + // reconnected after the last driver load option is processed. + // + if (IS_LOAD_OPTION_TYPE (Option->Attribute, LOAD_OPTION_FORCE_RECONNECT)) { + ReconnectAll = TRUE; + } + // + // Make sure the driver path is connected. + // + BdsLibConnectDevicePath (Option->DevicePath); + + // + // Load and start the image that Driver#### describes + // + Status = gBS->LoadImage ( + FALSE, + mBdsImageHandle, + Option->DevicePath, + NULL, + 0, + &ImageHandle + ); + + if (!EFI_ERROR (Status)) { + gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, &ImageInfo); + + // + // Verify whether this image is a driver, if not, + // exit it and continue to parse next load option + // + if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) { + gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL); + continue; + } + + if (Option->LoadOptionsSize != 0) { + ImageInfo->LoadOptionsSize = Option->LoadOptionsSize; + ImageInfo->LoadOptions = Option->LoadOptions; + } + // + // Before calling the image, enable the Watchdog Timer for + // the 5 Minute period + // + gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL); + + Status = gBS->StartImage (ImageHandle, &ExitDataSize, &ExitData); + DEBUG ((EFI_D_INFO | EFI_D_LOAD, "Driver Return Status = %r\n", Status)); + + // + // Clear the Watchdog Timer after the image returns + // + gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL); + } + } + // + // Process the LOAD_OPTION_FORCE_RECONNECT driver option + // + if (ReconnectAll) { + BdsLibDisconnectAllEfi (); + BdsLibConnectAll (); + } + +} + +EFI_STATUS +BdsLibRegisterNewOption ( + IN LIST_ENTRY *BdsOptionList, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CHAR16 *String, + IN CHAR16 *VariableName + ) +/*++ + +Routine Description: + + This function will register the new boot#### or driver#### option base on + the VariableName. The new registered boot#### or driver#### will be linked + to BdsOptionList and also update to the VariableName. After the boot#### or + driver#### updated, the BootOrder or DriverOrder will also be updated. + +Arguments: + + BdsOptionList - The header of the boot#### or driver#### link list + + DevicePath - The device path which the boot#### + or driver#### option present + + String - The description of the boot#### or driver#### + + VariableName - Indicate if the boot#### or driver#### option + +Returns: + + EFI_SUCCESS - The boot#### or driver#### have been success registered + + EFI_STATUS - Return the status of gRT->SetVariable (). + +--*/ +{ + EFI_STATUS Status; + UINTN Index; + UINT16 MaxOptionNumber; + UINT16 RegisterOptionNumber; + UINT16 *TempOptionPtr; + UINTN TempOptionSize; + UINT16 *OptionOrderPtr; + VOID *OptionPtr; + UINTN OptionSize; + UINT8 *TempPtr; + EFI_DEVICE_PATH_PROTOCOL *OptionDevicePath; + CHAR16 *Description; + CHAR16 OptionName[10]; + BOOLEAN UpdateBootDevicePath; + + OptionPtr = NULL; + OptionSize = 0; + TempPtr = NULL; + OptionDevicePath = NULL; + Description = NULL; + MaxOptionNumber = 0; + OptionOrderPtr = NULL; + UpdateBootDevicePath = FALSE; + ZeroMem (OptionName, sizeof (OptionName)); + + TempOptionSize = 0; + TempOptionPtr = BdsLibGetVariableAndSize ( + VariableName, + &gEfiGlobalVariableGuid, + &TempOptionSize + ); + // + // Compare with current option variable + // + for (Index = 0; Index < TempOptionSize / sizeof (UINT16); Index++) { + // + // Got the max option#### number + // + if (MaxOptionNumber < TempOptionPtr[Index]) { + MaxOptionNumber = TempOptionPtr[Index]; + } + + if (*VariableName == 'B') { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", TempOptionPtr[Index]); + } else { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", TempOptionPtr[Index]); + } + + OptionPtr = BdsLibGetVariableAndSize ( + OptionName, + &gEfiGlobalVariableGuid, + &OptionSize + ); + TempPtr = OptionPtr; + TempPtr += sizeof (UINT32) + sizeof (UINT16); + Description = (CHAR16 *) TempPtr; + TempPtr += StrSize ((CHAR16 *) TempPtr); + OptionDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr; + + // + // Notes: the description may will change base on the GetStringToken + // + if (CompareMem (Description, String, StrSize (Description)) == 0) { + if (CompareMem (OptionDevicePath, DevicePath, GetDevicePathSize (OptionDevicePath)) == 0) { + // + // Got the option, so just return + // + gBS->FreePool (OptionPtr); + gBS->FreePool (TempOptionPtr); + return EFI_SUCCESS; + } else { + // + // Boot device path changed, need update. + // + UpdateBootDevicePath = TRUE; + break; + } + } + + gBS->FreePool (OptionPtr); + } + + OptionSize = sizeof (UINT32) + sizeof (UINT16) + StrSize (String) + GetDevicePathSize (DevicePath); + OptionPtr = AllocateZeroPool (OptionSize); + TempPtr = OptionPtr; + *(UINT32 *) TempPtr = LOAD_OPTION_ACTIVE; + TempPtr += sizeof (UINT32); + *(UINT16 *) TempPtr = (UINT16) GetDevicePathSize (DevicePath); + TempPtr += sizeof (UINT16); + CopyMem (TempPtr, String, StrSize (String)); + TempPtr += StrSize (String); + CopyMem (TempPtr, DevicePath, GetDevicePathSize (DevicePath)); + + if (UpdateBootDevicePath) { + // + // The number in option#### to be updated + // + RegisterOptionNumber = TempOptionPtr[Index]; + } else { + // + // The new option#### number + // + RegisterOptionNumber = MaxOptionNumber + 1; + } + + if (*VariableName == 'B') { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", RegisterOptionNumber); + } else { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", RegisterOptionNumber); + } + + Status = gRT->SetVariable ( + OptionName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + OptionSize, + OptionPtr + ); + if (EFI_ERROR (Status) || UpdateBootDevicePath) { + gBS->FreePool (OptionPtr); + gBS->FreePool (TempOptionPtr); + return Status; + } + + gBS->FreePool (OptionPtr); + + // + // Update the option order variable + // + OptionOrderPtr = AllocateZeroPool ((Index + 1) * sizeof (UINT16)); + CopyMem (OptionOrderPtr, TempOptionPtr, Index * sizeof (UINT16)); + OptionOrderPtr[Index] = RegisterOptionNumber; + Status = gRT->SetVariable ( + VariableName, + &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, + (Index + 1) * sizeof (UINT16), + OptionOrderPtr + ); + if (EFI_ERROR (Status)) { + gBS->FreePool (TempOptionPtr); + gBS->FreePool (OptionOrderPtr); + return Status; + } + + gBS->FreePool (TempOptionPtr); + gBS->FreePool (OptionOrderPtr); + + return EFI_SUCCESS; +} + +BDS_COMMON_OPTION * +BdsLibVariableToOption ( + IN OUT LIST_ENTRY *BdsCommonOptionList, + IN CHAR16 *VariableName + ) +/*++ + +Routine Description: + + Build the boot#### or driver#### option from the VariableName, the + build boot#### or driver#### will also be linked to BdsCommonOptionList + +Arguments: + + BdsCommonOptionList - The header of the boot#### or driver#### option link list + + VariableName - EFI Variable name indicate if it is boot#### or driver#### + +Returns: + + BDS_COMMON_OPTION - Get the option just been created + + NULL - Failed to get the new option + +--*/ +{ + UINT32 Attribute; + UINT16 FilePathSize; + UINT8 *Variable; + UINT8 *TempPtr; + UINTN VariableSize; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + BDS_COMMON_OPTION *Option; + VOID *LoadOptions; + UINT32 LoadOptionsSize; + CHAR16 *Description; + + // + // Read the variable. We will never free this data. + // + Variable = BdsLibGetVariableAndSize ( + VariableName, + &gEfiGlobalVariableGuid, + &VariableSize + ); + if (Variable == NULL) { + return NULL; + } + // + // Notes: careful defined the variable of Boot#### or + // Driver####, consider use some macro to abstract the code + // + // + // Get the option attribute + // + TempPtr = Variable; + Attribute = *(UINT32 *) Variable; + TempPtr += sizeof (UINT32); + + // + // Get the option's device path size + // + FilePathSize = *(UINT16 *) TempPtr; + TempPtr += sizeof (UINT16); + + // + // Get the option's description string + // + Description = (CHAR16 *) TempPtr; + + // + // Get the option's description string size + // + TempPtr += StrSize ((CHAR16 *) TempPtr); + + // + // Get the option's device path + // + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) TempPtr; + TempPtr += FilePathSize; + + LoadOptions = TempPtr; + LoadOptionsSize = (UINT32) (VariableSize - (UINTN) (TempPtr - Variable)); + + // + // The Console variables may have multiple device paths, so make + // an Entry for each one. + // + Option = AllocateZeroPool (sizeof (BDS_COMMON_OPTION)); + if (Option == NULL) { + return NULL; + } + + Option->Signature = BDS_LOAD_OPTION_SIGNATURE; + Option->DevicePath = AllocateZeroPool (GetDevicePathSize (DevicePath)); + CopyMem (Option->DevicePath, DevicePath, GetDevicePathSize (DevicePath)); + Option->Attribute = Attribute; + Option->Description = AllocateZeroPool (StrSize (Description)); + CopyMem (Option->Description, Description, StrSize (Description)); + Option->LoadOptions = AllocateZeroPool (LoadOptionsSize); + CopyMem (Option->LoadOptions, LoadOptions, LoadOptionsSize); + Option->LoadOptionsSize = LoadOptionsSize; + + // + // Insert active entry to BdsDeviceList + // + if ((Option->Attribute & LOAD_OPTION_ACTIVE) == LOAD_OPTION_ACTIVE) { + InsertTailList (BdsCommonOptionList, &Option->Link); + gBS->FreePool (Variable); + return Option; + } + + gBS->FreePool (Variable); + gBS->FreePool (Option); + return NULL; + +} + +EFI_STATUS +BdsLibBuildOptionFromVar ( + IN LIST_ENTRY *BdsCommonOptionList, + IN CHAR16 *VariableName + ) +/*++ + +Routine Description: + + Process BootOrder, or DriverOrder variables, by calling + BdsLibVariableToOption () for each UINT16 in the variables. + +Arguments: + + BdsCommonOptionList - The header of the option list base on variable + VariableName + + VariableName - EFI Variable name indicate the BootOrder or DriverOrder + +Returns: + + EFI_SUCCESS - Success create the boot option or driver option list + + EFI_OUT_OF_RESOURCES - Failed to get the boot option or driver option list + +--*/ +{ + UINT16 *OptionOrder; + UINTN OptionOrderSize; + UINTN Index; + BDS_COMMON_OPTION *Option; + CHAR16 OptionName[20]; + + // + // Zero Buffer in order to get all BOOT#### variables + // + ZeroMem (OptionName, sizeof (OptionName)); + + // + // Read the BootOrder, or DriverOrder variable. + // + OptionOrder = BdsLibGetVariableAndSize ( + VariableName, + &gEfiGlobalVariableGuid, + &OptionOrderSize + ); + if (OptionOrder == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0; Index < OptionOrderSize / sizeof (UINT16); Index++) { + if (*VariableName == 'B') { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Boot%04x", OptionOrder[Index]); + } else { + UnicodeSPrint (OptionName, sizeof (OptionName), L"Driver%04x", OptionOrder[Index]); + } + Option = BdsLibVariableToOption (BdsCommonOptionList, OptionName); + Option->BootCurrent = OptionOrder[Index]; + + } + + gBS->FreePool (OptionOrder); + + return EFI_SUCCESS; +} + +EFI_STATUS +BdsLibGetBootMode ( + OUT EFI_BOOT_MODE *BootMode + ) +/*++ + +Routine Description: + + Get boot mode by looking up configuration table and parsing HOB list + +Arguments: + + BootMode - Boot mode from PEI handoff HOB. + +Returns: + + EFI_SUCCESS - Successfully get boot mode + + EFI_NOT_FOUND - Can not find the current system boot mode + +--*/ +{ + EFI_HOB_HANDOFF_INFO_TABLE *HobList; + + HobList = GetHobList (); + ASSERT (HobList->Header.HobType == EFI_HOB_TYPE_HANDOFF); + *BootMode = HobList->BootMode; + + return EFI_SUCCESS; +} + +VOID * +BdsLibGetVariableAndSize ( + IN CHAR16 *Name, + IN EFI_GUID *VendorGuid, + OUT UINTN *VariableSize + ) +/*++ + +Routine Description: + + Read the EFI variable (VendorGuid/Name) and return a dynamically allocated + buffer, and the size of the buffer. If failure return NULL. + +Arguments: + + Name - String part of EFI variable name + + VendorGuid - GUID part of EFI variable name + + VariableSize - Returns the size of the EFI variable that was read + +Returns: + + Dynamically allocated memory that contains a copy of the EFI variable. + Caller is responsible freeing the buffer. + + NULL - Variable was not read + +--*/ +{ + EFI_STATUS Status; + UINTN BufferSize; + VOID *Buffer; + + Buffer = NULL; + + // + // Pass in a zero size buffer to find the required buffer size. + // + BufferSize = 0; + Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); + if (Status == EFI_BUFFER_TOO_SMALL) { + // + // Allocate the buffer to return + // + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + return NULL; + } + // + // Read variable into the allocated buffer. + // + Status = gRT->GetVariable (Name, VendorGuid, NULL, &BufferSize, Buffer); + if (EFI_ERROR (Status)) { + BufferSize = 0; + } + } + + *VariableSize = BufferSize; + return Buffer; +} + +BOOLEAN +BdsLibMatchDevicePaths ( + IN EFI_DEVICE_PATH_PROTOCOL *Multi, + IN EFI_DEVICE_PATH_PROTOCOL *Single + ) +/*++ + +Routine Description: + + Function compares a device path data structure to that of all the nodes of a + second device path instance. + +Arguments: + + Multi - A pointer to a multi-instance device path data structure. + + Single - A pointer to a single-instance device path data structure. + +Returns: + + TRUE - If the Single is contained within Multi + + FALSE - The Single is not match within Multi + + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + UINTN Size; + + if (!Multi || !Single) { + return FALSE; + } + + DevicePath = Multi; + DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); + Size -= sizeof (EFI_DEVICE_PATH_PROTOCOL); + + // + // Search for the match of 'Single' in 'Multi' + // + while (DevicePathInst != NULL) { + // + // If the single device path is found in multiple device paths, + // return success + // + if (Size == 0) { + return FALSE; + } + + if (CompareMem (Single, DevicePathInst, Size) == 0) { + return TRUE; + } + + gBS->FreePool (DevicePathInst); + DevicePathInst = GetNextDevicePathInstance (&DevicePath, &Size); + Size -= sizeof (EFI_DEVICE_PATH_PROTOCOL); + } + + return FALSE; +} + +EFI_STATUS +BdsLibOutputStrings ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *ConOut, + ... + ) +/*++ + +Routine Description: + + This function prints a series of strings. + +Arguments: + + ConOut - Pointer to EFI_SIMPLE_TEXT_OUT_PROTOCOL + + ... - A variable argument list containing series of strings, + the last string must be NULL. + +Returns: + + EFI_SUCCESS - Success print out the string using ConOut. + + EFI_STATUS - Return the status of the ConOut->OutputString (). + +--*/ +{ + VA_LIST args; + EFI_STATUS Status; + CHAR16 *String; + + Status = EFI_SUCCESS; + VA_START (args, ConOut); + + while (!EFI_ERROR (Status)) { + // + // If String is NULL, then it's the end of the list + // + String = VA_ARG (args, CHAR16 *); + if (!String) { + break; + } + + Status = ConOut->OutputString (ConOut, String); + + if (EFI_ERROR (Status)) { + break; + } + } + + return Status; +} diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/DevicePath.c b/EdkNt32Pkg/Library/EdkGenericBdsLib/DevicePath.c new file mode 100644 index 0000000000..de854103cb --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/DevicePath.c @@ -0,0 +1,988 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + DevicePath.c + +Abstract: + + BDS internal function define the default device path string, it can be + replaced by platform device path. + +--*/ + + +#ifdef TIANO_EXTENSION_FLAG +EFI_GUID UnknownDeviceGuid = UNKNOWN_DEVICE_GUID; +#endif + +EFI_GUID mEfiWinNtThunkProtocolGuid = EFI_WIN_NT_THUNK_PROTOCOL_GUID; +EFI_GUID mEfiWinNtUgaGuid = EFI_WIN_NT_UGA_GUID; +EFI_GUID mEfiWinNtSerialPortGuid = EFI_WIN_NT_SERIAL_PORT_GUID; +EFI_GUID mEfiMsgPcAnsiGuid = DEVICE_PATH_MESSAGING_PC_ANSI; +EFI_GUID mEfiMsgVt100Guid = DEVICE_PATH_MESSAGING_VT_100; +EFI_GUID mEfiMsgVt100PlusGuid = DEVICE_PATH_MESSAGING_VT_100_PLUS; +EFI_GUID mEfiMsgVt100Utf8Guid = DEVICE_PATH_MESSAGING_VT_UTF8; + +VOID * +ReallocatePool ( + IN VOID *OldPool, + IN UINTN OldSize, + IN UINTN NewSize + ) +/*++ + +Routine Description: + + Adjusts the size of a previously allocated buffer. + +Arguments: + + OldPool - A pointer to the buffer whose size is being adjusted. + + OldSize - The size of the current buffer. + + NewSize - The size of the new buffer. + +Returns: + + EFI_SUCEESS - The requested number of bytes were allocated. + + EFI_OUT_OF_RESOURCES - The pool requested could not be allocated. + + EFI_INVALID_PARAMETER - The buffer was invalid. + +--*/ +{ + VOID *NewPool; + + NewPool = NULL; + if (NewSize) { + NewPool = AllocateZeroPool (NewSize); + } + + if (OldPool) { + if (NewPool) { + CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize); + } + + gBS->FreePool (OldPool); + } + + return NewPool; +} + +CHAR16 * +CatPrint ( + IN OUT POOL_PRINT *Str, + IN CHAR16 *fmt, + ... + ) +/*++ + +Routine Description: + + Concatenates a formatted unicode string to allocated pool. + The caller must free the resulting buffer. + +Arguments: + + Str - Tracks the allocated pool, size in use, and + amount of pool allocated. + + fmt - The format string + +Returns: + + Allocated buffer with the formatted string printed in it. + The caller must free the allocated buffer. The buffer + allocation is not packed. + +--*/ +{ + UINT16 *AppendStr; + VA_LIST args; + UINTN strsize; + + AppendStr = AllocateZeroPool (0x1000); + if (AppendStr == NULL) { + return Str->str; + } + + VA_START (args, fmt); + UnicodeVSPrint (AppendStr, 0x1000, fmt, args); + VA_END (args); + if (NULL == Str->str) { + strsize = StrSize (AppendStr); + Str->str = AllocateZeroPool (strsize); + ASSERT (Str->str != NULL); + } else { + strsize = StrSize (AppendStr) + StrSize (Str->str) - sizeof (UINT16); + Str->str = ReallocatePool ( + Str->str, + StrSize (Str->str), + strsize + ); + ASSERT (Str->str != NULL); + } + + Str->maxlen = MAX_CHAR * sizeof (UINT16); + if (strsize < Str->maxlen) { + StrCat (Str->str, AppendStr); + Str->len = strsize - sizeof (UINT16); + } + + gBS->FreePool (AppendStr); + return Str->str; +} + +EFI_DEVICE_PATH_PROTOCOL * +BdsLibUnpackDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +/*++ + +Routine Description: + + Function unpacks a device path data structure so that all the nodes + of a device path are naturally aligned. + +Arguments: + + DevPath - A pointer to a device path data structure + +Returns: + + If the memory for the device path is successfully allocated, then a + pointer to the new device path is returned. Otherwise, NULL is returned. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *Src; + EFI_DEVICE_PATH_PROTOCOL *Dest; + EFI_DEVICE_PATH_PROTOCOL *NewPath; + UINTN Size; + + // + // Walk device path and round sizes to valid boundries + // + Src = DevPath; + Size = 0; + for (;;) { + Size += DevicePathNodeLength (Src); + Size += ALIGN_SIZE (Size); + + if (IsDevicePathEnd (Src)) { + break; + } + + Src = NextDevicePathNode (Src); + } + // + // Allocate space for the unpacked path + // + NewPath = AllocateZeroPool (Size); + if (NewPath) { + + ASSERT (((UINTN) NewPath) % MIN_ALIGNMENT_SIZE == 0); + + // + // Copy each node + // + Src = DevPath; + Dest = NewPath; + for (;;) { + Size = DevicePathNodeLength (Src); + CopyMem (Dest, Src, Size); + Size += ALIGN_SIZE (Size); + SetDevicePathNodeLength (Dest, Size); + Dest->Type |= EFI_DP_TYPE_UNPACKED; + Dest = (EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) Dest) + Size); + + if (IsDevicePathEnd (Src)) { + break; + } + + Src = NextDevicePathNode (Src); + } + } + + return NewPath; +} + +VOID +DevPathPci ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + PCI_DEVICE_PATH *Pci; + + Pci = DevPath; + CatPrint (Str, L"Pci(%x|%x)", Pci->Device, Pci->Function); +} + +VOID +DevPathPccard ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + PCCARD_DEVICE_PATH *Pccard; + + Pccard = DevPath; + CatPrint (Str, L"Pcmcia(Function%x)", Pccard->FunctionNumber); +} + +VOID +DevPathMemMap ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MEMMAP_DEVICE_PATH *MemMap; + + MemMap = DevPath; + CatPrint ( + Str, + L"MemMap(%d:%.lx-%.lx)", + MemMap->MemoryType, + MemMap->StartingAddress, + MemMap->EndingAddress + ); +} + +VOID +DevPathController ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + CONTROLLER_DEVICE_PATH *Controller; + + Controller = DevPath; + CatPrint (Str, L"Ctrl(%d)", Controller->ControllerNumber); +} + +VOID +DevPathVendor ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +/*++ + +Routine Description: + + Convert Vendor device path to device name + +Arguments: + + Str - The buffer store device name + DevPath - Pointer to vendor device path + +Returns: + + When it return, the device name have been stored in *Str. + +--*/ +{ + VENDOR_DEVICE_PATH *Vendor; + CHAR16 *Type; + INT32 *Temp; + + Vendor = DevPath; + Temp = (INT32 *) (&Vendor->Guid); + + switch (DevicePathType (&Vendor->Header)) { + case HARDWARE_DEVICE_PATH: + // + // If the device is a winntbus device, we will give it a readable device name. + // + if (CompareGuid (&Vendor->Guid, &mEfiWinNtThunkProtocolGuid)) { + CatPrint (Str, L"%s", L"WinNtBus"); + return ; + } else if (CompareGuid (&Vendor->Guid, &mEfiWinNtUgaGuid)) { + CatPrint (Str, L"%s", L"UGA"); + return ; + } else if (CompareGuid (&Vendor->Guid, &mEfiWinNtSerialPortGuid)) { + CatPrint (Str, L"%s", L"Serial"); + return ; + } else { + Type = L"Hw"; + break; + } + + case MESSAGING_DEVICE_PATH: + // + // If the device is a winntbus device, we will give it a readable device name. + // + if (CompareGuid (&Vendor->Guid, &mEfiMsgPcAnsiGuid)) { + CatPrint (Str, L"%s", L"PC-ANSI"); + return ; + } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100Guid)) { + CatPrint (Str, L"%s", L"VT100"); + return ; + } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100PlusGuid)) { + CatPrint (Str, L"%s", L"VT100+"); + return ; + } else if (CompareGuid (&Vendor->Guid, &mEfiMsgVt100Utf8Guid)) { + CatPrint (Str, L"%s", L"VT100-UTF8"); + return ; + } else { + Type = L"Msg"; + break; + } + + case MEDIA_DEVICE_PATH: + Type = L"Media"; + break; + + default: + Type = L"?"; + break; + } + + CatPrint (Str, L"Ven%s(%g)", Type, &Vendor->Guid); +} + +VOID +DevPathAcpi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + ACPI_HID_DEVICE_PATH *Acpi; + + Acpi = DevPath; + if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) { + CatPrint (Str, L"Acpi(PNP%04x,%x)", EISA_ID_TO_NUM (Acpi->HID), Acpi->UID); + } else { + CatPrint (Str, L"Acpi(%08x,%x)", Acpi->HID, Acpi->UID); + } +} + +VOID +DevPathAtapi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + ATAPI_DEVICE_PATH *Atapi; + + Atapi = DevPath; + CatPrint ( + Str, + L"Ata(%s,%s)", + Atapi->PrimarySecondary ? L"Secondary" : L"Primary", + Atapi->SlaveMaster ? L"Slave" : L"Master" + ); +} + +VOID +DevPathScsi ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + SCSI_DEVICE_PATH *Scsi; + + Scsi = DevPath; + CatPrint (Str, L"Scsi(Pun%x,Lun%x)", Scsi->Pun, Scsi->Lun); +} + +VOID +DevPathFibre ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + FIBRECHANNEL_DEVICE_PATH *Fibre; + + Fibre = DevPath; + CatPrint (Str, L"Fibre(Wwn%lx,Lun%x)", Fibre->WWN, Fibre->Lun); +} + +VOID +DevPath1394 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + F1394_DEVICE_PATH *F1394; + + F1394 = DevPath; + CatPrint (Str, L"1394(%g)", &F1394->Guid); +} + +VOID +DevPathUsb ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + USB_DEVICE_PATH *Usb; + + Usb = DevPath; + CatPrint (Str, L"Usb(%x, %x)", Usb->ParentPortNumber, Usb->InterfaceNumber); +} + +VOID +DevPathUsbClass ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + USB_CLASS_DEVICE_PATH *UsbClass; + + UsbClass = DevPath; + CatPrint ( + Str, + L"Usb Class(%x, %x, %x, %x, %x)", + UsbClass->VendorId, + UsbClass->ProductId, + UsbClass->DeviceClass, + UsbClass->DeviceSubClass, + UsbClass->DeviceProtocol + ); +} + +VOID +DevPathI2O ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + I2O_DEVICE_PATH *I2O; + + I2O = DevPath; + CatPrint (Str, L"I2O(%x)", I2O->Tid); +} + +VOID +DevPathMacAddr ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MAC_ADDR_DEVICE_PATH *MAC; + UINTN HwAddressSize; + UINTN Index; + + MAC = DevPath; + + HwAddressSize = sizeof (EFI_MAC_ADDRESS); + if (MAC->IfType == 0x01 || MAC->IfType == 0x00) { + HwAddressSize = 6; + } + + CatPrint (Str, L"Mac("); + + for (Index = 0; Index < HwAddressSize; Index++) { + CatPrint (Str, L"%02x", MAC->MacAddress.Addr[Index]); + } + + CatPrint (Str, L")"); +} + +VOID +DevPathIPv4 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + IPv4_DEVICE_PATH *IP; + + IP = DevPath; + CatPrint ( + Str, + L"IPv4(%d.%d.%d.%d:%d)", + IP->RemoteIpAddress.Addr[0], + IP->RemoteIpAddress.Addr[1], + IP->RemoteIpAddress.Addr[2], + IP->RemoteIpAddress.Addr[3], + IP->RemotePort + ); +} + +VOID +DevPathIPv6 ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + IPv6_DEVICE_PATH *IP; + + IP = DevPath; + CatPrint (Str, L"IP-v6(not-done)"); +} + +VOID +DevPathInfiniBand ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + INFINIBAND_DEVICE_PATH *InfiniBand; + + InfiniBand = DevPath; + CatPrint (Str, L"InfiniBand(not-done)"); +} + +VOID +DevPathUart ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + UART_DEVICE_PATH *Uart; + CHAR8 Parity; + + Uart = DevPath; + switch (Uart->Parity) { + case 0: + Parity = 'D'; + break; + + case 1: + Parity = 'N'; + break; + + case 2: + Parity = 'E'; + break; + + case 3: + Parity = 'O'; + break; + + case 4: + Parity = 'M'; + break; + + case 5: + Parity = 'S'; + break; + + default: + Parity = 'x'; + break; + } + + if (Uart->BaudRate == 0) { + CatPrint (Str, L"Uart(DEFAULT %c", Parity); + } else { + CatPrint (Str, L"Uart(%d %c", Uart->BaudRate, Parity); + } + + if (Uart->DataBits == 0) { + CatPrint (Str, L"D"); + } else { + CatPrint (Str, L"%d", Uart->DataBits); + } + + switch (Uart->StopBits) { + case 0: + CatPrint (Str, L"D)"); + break; + + case 1: + CatPrint (Str, L"1)"); + break; + + case 2: + CatPrint (Str, L"1.5)"); + break; + + case 3: + CatPrint (Str, L"2)"); + break; + + default: + CatPrint (Str, L"x)"); + break; + } +} + +VOID +DevPathHardDrive ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + HARDDRIVE_DEVICE_PATH *Hd; + + Hd = DevPath; + switch (Hd->SignatureType) { + case SIGNATURE_TYPE_MBR: + CatPrint ( + Str, + L"HD(Part%d,Sig%08x)", + Hd->PartitionNumber, + *((UINT32 *) (&(Hd->Signature[0]))) + ); + break; + + case SIGNATURE_TYPE_GUID: + CatPrint ( + Str, + L"HD(Part%d,Sig%g)", + Hd->PartitionNumber, + (EFI_GUID *) &(Hd->Signature[0]) + ); + break; + + default: + CatPrint ( + Str, + L"HD(Part%d,MBRType=%02x,SigType=%02x)", + Hd->PartitionNumber, + Hd->MBRType, + Hd->SignatureType + ); + break; + } +} + +VOID +DevPathCDROM ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + CDROM_DEVICE_PATH *Cd; + + Cd = DevPath; + CatPrint (Str, L"CDROM(Entry%x)", Cd->BootEntry); +} + +VOID +DevPathFilePath ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + FILEPATH_DEVICE_PATH *Fp; + + Fp = DevPath; + CatPrint (Str, L"%s", Fp->PathName); +} + +VOID +DevPathMediaProtocol ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MEDIA_PROTOCOL_DEVICE_PATH *MediaProt; + + MediaProt = DevPath; + CatPrint (Str, L"%g", &MediaProt->Protocol); +} + +VOID +DevPathFvFilePath ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFilePath; + + FvFilePath = DevPath; + CatPrint (Str, L"%g", &FvFilePath->NameGuid); +} + +VOID +DevPathBssBss ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + BBS_BBS_DEVICE_PATH *Bbs; + CHAR16 *Type; + + Bbs = DevPath; + switch (Bbs->DeviceType) { + case BBS_TYPE_FLOPPY: + Type = L"Floppy"; + break; + + case BBS_TYPE_HARDDRIVE: + Type = L"Harddrive"; + break; + + case BBS_TYPE_CDROM: + Type = L"CDROM"; + break; + + case BBS_TYPE_PCMCIA: + Type = L"PCMCIA"; + break; + + case BBS_TYPE_USB: + Type = L"Usb"; + break; + + case BBS_TYPE_EMBEDDED_NETWORK: + Type = L"Net"; + break; + + default: + Type = L"?"; + break; + } + // + // Since current Print function hasn't implemented %a (for ansi string) + // we will only print Unicode strings. + // + CatPrint (Str, L"Legacy-%s", Type); +} + +VOID +DevPathEndInstance ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + CatPrint (Str, L","); +} + +VOID +DevPathNodeUnknown ( + IN OUT POOL_PRINT *Str, + IN VOID *DevPath + ) +{ + CatPrint (Str, L"?"); +} + +DEVICE_PATH_STRING_TABLE DevPathTable[] = { + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + DevPathPci, + HARDWARE_DEVICE_PATH, + HW_PCCARD_DP, + DevPathPccard, + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + DevPathMemMap, + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + DevPathVendor, + HARDWARE_DEVICE_PATH, + HW_CONTROLLER_DP, + DevPathController, + ACPI_DEVICE_PATH, + ACPI_DP, + DevPathAcpi, + MESSAGING_DEVICE_PATH, + MSG_ATAPI_DP, + DevPathAtapi, + MESSAGING_DEVICE_PATH, + MSG_SCSI_DP, + DevPathScsi, + MESSAGING_DEVICE_PATH, + MSG_FIBRECHANNEL_DP, + DevPathFibre, + MESSAGING_DEVICE_PATH, + MSG_1394_DP, + DevPath1394, + MESSAGING_DEVICE_PATH, + MSG_USB_DP, + DevPathUsb, + MESSAGING_DEVICE_PATH, + MSG_USB_CLASS_DP, + DevPathUsbClass, + MESSAGING_DEVICE_PATH, + MSG_I2O_DP, + DevPathI2O, + MESSAGING_DEVICE_PATH, + MSG_MAC_ADDR_DP, + DevPathMacAddr, + MESSAGING_DEVICE_PATH, + MSG_IPv4_DP, + DevPathIPv4, + MESSAGING_DEVICE_PATH, + MSG_IPv6_DP, + DevPathIPv6, + MESSAGING_DEVICE_PATH, + MSG_INFINIBAND_DP, + DevPathInfiniBand, + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + DevPathUart, + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + DevPathVendor, + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP, + DevPathHardDrive, + MEDIA_DEVICE_PATH, + MEDIA_CDROM_DP, + DevPathCDROM, + MEDIA_DEVICE_PATH, + MEDIA_VENDOR_DP, + DevPathVendor, + MEDIA_DEVICE_PATH, + MEDIA_FILEPATH_DP, + DevPathFilePath, + MEDIA_DEVICE_PATH, + MEDIA_PROTOCOL_DP, + DevPathMediaProtocol, + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) + MEDIA_DEVICE_PATH, + MEDIA_FV_FILEPATH_DP, + DevPathFvFilePath, +#endif + + BBS_DEVICE_PATH, + BBS_BBS_DP, + DevPathBssBss, + END_DEVICE_PATH_TYPE, + END_INSTANCE_DEVICE_PATH_SUBTYPE, + DevPathEndInstance, + 0, + 0, + NULL +}; + +CHAR16 * +DevicePathToStr ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +/*++ + + Turns the Device Path into a printable string. Allcoates + the string from pool. The caller must SafeFreePool the returned + string. + +--*/ +{ + POOL_PRINT Str; + EFI_DEVICE_PATH_PROTOCOL *DevPathNode; + VOID (*DumpNode) (POOL_PRINT *, VOID *); + + UINTN Index; + UINTN NewSize; + + ZeroMem (&Str, sizeof (Str)); + + if (DevPath == NULL) { + goto Done; + } + // + // Unpacked the device path + // + DevPath = BdsLibUnpackDevicePath (DevPath); + ASSERT (DevPath); + + // + // Process each device path node + // + DevPathNode = DevPath; + while (!IsDevicePathEnd (DevPathNode)) { + // + // Find the handler to dump this device path node + // + DumpNode = NULL; + for (Index = 0; DevPathTable[Index].Function; Index += 1) { + + if (DevicePathType (DevPathNode) == DevPathTable[Index].Type && + DevicePathSubType (DevPathNode) == DevPathTable[Index].SubType + ) { + DumpNode = DevPathTable[Index].Function; + break; + } + } + // + // If not found, use a generic function + // + if (!DumpNode) { + DumpNode = DevPathNodeUnknown; + } + // + // Put a path seperator in if needed + // + if (Str.len && DumpNode != DevPathEndInstance) { + CatPrint (&Str, L"/"); + } + // + // Print this node of the device path + // + DumpNode (&Str, DevPathNode); + + // + // Next device path node + // + DevPathNode = NextDevicePathNode (DevPathNode); + } + // + // Shrink pool used for string allocation + // + gBS->FreePool (DevPath); + +Done: + NewSize = (Str.len + 1) * sizeof (CHAR16); + Str.str = ReallocatePool (Str.str, NewSize, NewSize); + ASSERT (Str.str != NULL); + Str.str[Str.len] = 0; + return Str.str; +} + +EFI_DEVICE_PATH_PROTOCOL * +LibDuplicateDevicePathInstance ( + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ) +/*++ + +Routine Description: + + Function creates a device path data structure that identically matches the + device path passed in. + +Arguments: + + DevPath - A pointer to a device path data structure. + +Returns: + + The new copy of DevPath is created to identically match the input. + Otherwise, NULL is returned. + +--*/ +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevPath; + EFI_DEVICE_PATH_PROTOCOL *DevicePathInst; + EFI_DEVICE_PATH_PROTOCOL *Temp; + UINTN Size; + + // + // get the size of an instance from the input + // + Temp = DevPath; + DevicePathInst = GetNextDevicePathInstance (&Temp, &Size); + + // + // Make a copy + // + NewDevPath = NULL; + if (Size) { + NewDevPath = AllocateZeroPool (Size); + ASSERT (NewDevPath != NULL); + } + + if (NewDevPath) { + CopyMem (NewDevPath, DevicePathInst, Size); + } + + return NewDevPath; +} diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/EdkGenericBdsLib.mbd b/EdkNt32Pkg/Library/EdkGenericBdsLib/EdkGenericBdsLib.mbd new file mode 100644 index 0000000000..ca083fe61d --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/EdkGenericBdsLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkGenericBdsLib + 1ec995b2-d15b-44f6-abd2-050ea7dd37d2 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-13 17:00 + 2006-03-23 12:01 + + diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/EdkGenericBdsLib.msa b/EdkNt32Pkg/Library/EdkGenericBdsLib/EdkGenericBdsLib.msa new file mode 100644 index 0000000000..e09537b723 --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/EdkGenericBdsLib.msa @@ -0,0 +1,78 @@ + + + + + EdkGenericBdsLib + DXE_DRIVER + LIBRARY + 1ec995b2-d15b-44f6-abd2-050ea7dd37d2 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-13 17:00 + 2006-03-23 12:01 + + + EdkGenericBdsLib + BaseLib + UefiLib + DxeServicesTableLib + DebugLib + PrintLib + HobLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + DevicePathLib + PerformanceLib + + + BdsBoot.c + BdsConsole.c + BdsConnect.c + DevicePath.c + Performance.c + BdsMisc.c + + Ipf\ShadowRom.c + + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + LoadedImage + FirmwareVolume + AcpiS3Save + SimpleTextOut + SimpleTextIn + SimpleNetwork + + + + ShellFile + + + diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/Ipf/ShadowRom.c b/EdkNt32Pkg/Library/EdkGenericBdsLib/Ipf/ShadowRom.c new file mode 100644 index 0000000000..44a643d9b8 --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/Ipf/ShadowRom.c @@ -0,0 +1,53 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + ShadowRom.c + +Abstract: + + Shadow all option rom + +Revision History + +--*/ + +#include "Tiano.h" +#include "EfiDriverLib.h" + +#include EFI_PROTOCOL_DEFINITION (LegacyBios) + +UINT8 mShadowRomFlag = 0; + +VOID +ShadowAllOptionRom() +{ + EFI_STATUS Status; + EFI_LEGACY_BIOS_PROTOCOL *LegacyBios; + // + // Rom shadow only do once. + // + if (mShadowRomFlag == 0) { + Status = gBS->LocateProtocol ( + &gEfiLegacyBiosProtocolGuid, + NULL, + &LegacyBios + ); + if (!EFI_ERROR (Status)) { + LegacyBios->PrepareToBootEfi (LegacyBios, NULL, NULL); + } + + mShadowRomFlag = 1; + } + + return ; +} diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/Performance.c b/EdkNt32Pkg/Library/EdkGenericBdsLib/Performance.c new file mode 100644 index 0000000000..320d6b7c44 --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/Performance.c @@ -0,0 +1,426 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Performance.c + +Abstract: + + This file include the file which can help to get the system + performance, all the function will only include if the performance + switch is set. + +--*/ + +#include "Performance.h" + +VOID +ClearDebugRegisters ( + VOID + ) +{ + AsmWriteDr0 (0); + AsmWriteDr1 (0); +} + +STATIC +VOID +GetShortPdbFileName ( + CHAR8 *PdbFileName, + CHAR8 *GaugeString + ) +/*++ + +Routine Description: + +Arguments: + +Returns: + +--*/ +{ + UINTN Index; + UINTN Index1; + UINTN StartIndex; + UINTN EndIndex; + + if (PdbFileName == NULL) { + AsciiStrCpy (GaugeString, " "); + } else { + StartIndex = 0; + for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++) + ; + + for (Index = 0; PdbFileName[Index] != 0; Index++) { + if (PdbFileName[Index] == '\\') { + StartIndex = Index + 1; + } + + if (PdbFileName[Index] == '.') { + EndIndex = Index; + } + } + + Index1 = 0; + for (Index = StartIndex; Index < EndIndex; Index++) { + GaugeString[Index1] = PdbFileName[Index]; + Index1++; + if (Index1 == PERF_TOKEN_LENGTH - 1) { + break; + } + } + + GaugeString[Index1] = 0; + } + + return ; +} + +STATIC +CHAR8 * +GetPdbPath ( + VOID *ImageBase + ) +/*++ + +Routine Description: + + Located PDB path name in PE image + +Arguments: + + ImageBase - base of PE to search + +Returns: + + Pointer into image at offset of PDB file name if PDB file name is found, + Otherwise a pointer to an empty string. + +--*/ +{ + CHAR8 *PdbPath; + UINT32 DirCount; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_NT_HEADERS *NtHdr; + EFI_IMAGE_OPTIONAL_HEADER *OptionalHdr; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + VOID *CodeViewEntryPointer; + + CodeViewEntryPointer = NULL; + PdbPath = NULL; + DosHdr = ImageBase; + + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + NtHdr = (EFI_IMAGE_NT_HEADERS *) ((UINT8 *) DosHdr + DosHdr->e_lfanew); + OptionalHdr = (VOID *) &NtHdr->OptionalHeader; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionalHdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + if (DirectoryEntry->VirtualAddress != 0) { + for (DirCount = 0; + (DirCount < DirectoryEntry->Size / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) && CodeViewEntryPointer == NULL; + DirCount++ + ) { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (DirectoryEntry->VirtualAddress + (UINTN) ImageBase + DirCount * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + (UINTN) ImageBase); + switch (*(UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + PdbPath = (CHAR8 *) CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + break; + } + } + } + } + } + + return PdbPath; +} + +STATIC +VOID +GetNameFromHandle ( + IN EFI_HANDLE Handle, + OUT CHAR8 *GaugeString + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *Image; + CHAR8 *PdbFileName; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + + AsciiStrCpy (GaugeString, " "); + + // + // Get handle name from image protocol + // + Status = gBS->HandleProtocol ( + Handle, + &gEfiLoadedImageProtocolGuid, + &Image + ); + + if (EFI_ERROR (Status)) { + Status = gBS->OpenProtocol ( + Handle, + &gEfiDriverBindingProtocolGuid, + (VOID **) &DriverBinding, + NULL, + NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return ; + } + // + // Get handle name from image protocol + // + Status = gBS->HandleProtocol ( + DriverBinding->ImageHandle, + &gEfiLoadedImageProtocolGuid, + &Image + ); + } + + PdbFileName = GetPdbPath (Image->ImageBase); + + if (PdbFileName != NULL) { + GetShortPdbFileName (PdbFileName, GaugeString); + } + + return ; +} + + + +VOID +WriteBootToOsPerformanceData ( + VOID + ) +/*++ + +Routine Description: + + Allocates a block of memory and writes performance data of booting to OS into it. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_CPU_ARCH_PROTOCOL *Cpu; + EFI_PHYSICAL_ADDRESS mAcpiLowMemoryBase; + UINT32 mAcpiLowMemoryLength; + UINT32 LimitCount; + PERF_HEADER mPerfHeader; + PERF_DATA mPerfData; + EFI_HANDLE *Handles; + UINTN NoHandles; + CHAR8 GaugeString[PERF_TOKEN_LENGTH]; + UINT8 *Ptr; + UINT32 mIndex; + UINT64 Ticker; + UINT64 Freq; + UINT32 Duration; + UINT64 CurrentTicker; + UINT64 TimerPeriod; + UINTN LogEntryKey; + CONST VOID *Handle; + CONST CHAR8 *Token; + CONST CHAR8 *Module; + UINT64 StartTicker; + UINT64 EndTicker; + + // + // Retrive time stamp count as early as possilbe + // + Ticker = AsmReadTsc (); + + // + // Allocate a block of memory that contain performance data to OS + // + Status = gBS->AllocatePages ( + AllocateAnyPages, + EfiACPIReclaimMemory, + 4, + &mAcpiLowMemoryBase + ); + if (EFI_ERROR (Status)) { + return ; + } + + mAcpiLowMemoryLength = 0x1000; + + Ptr = (UINT8 *) ((UINT32) mAcpiLowMemoryBase + sizeof (PERF_HEADER)); + LimitCount = (mAcpiLowMemoryLength - sizeof (PERF_HEADER)) / sizeof (PERF_DATA); + + // + // Initialize performance data structure + // + ZeroMem (&mPerfHeader, sizeof (PERF_HEADER)); + + // + // Get CPU frequency + // + Status = gBS->LocateProtocol ( + &gEfiCpuArchProtocolGuid, + NULL, + &Cpu + ); + if (EFI_ERROR (Status)) { + gBS->FreePages (mAcpiLowMemoryBase, 1); + return ; + } + // + // Get Cpu Frequency + // + Status = Cpu->GetTimerValue (Cpu, 0, &(CurrentTicker), &TimerPeriod); + if (EFI_ERROR (Status)) { + gBS->FreePages (mAcpiLowMemoryBase, 1); + return ; + } + + Freq = DivU64x32 (1000000000000, (UINTN) TimerPeriod); + + mPerfHeader.CpuFreq = Freq; + + // + // Record BDS raw performance data + // + mPerfHeader.BDSRaw = Ticker; + + // + // Put Detailed performance data into memory + // + Handles = NULL; + Status = gBS->LocateHandleBuffer ( + AllHandles, + NULL, + NULL, + &NoHandles, + &Handles + ); + if (EFI_ERROR (Status)) { + gBS->FreePages (mAcpiLowMemoryBase, 1); + return ; + } + // + // Get DXE drivers performance + // + for (mIndex = 0; mIndex < NoHandles; mIndex++) { + Ticker = 0; + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Handle, + &Token, + &Module, + &StartTicker, + &EndTicker)) != 0) { + if ((Handle == Handles[mIndex]) && (StartTicker < EndTicker)) { + Ticker += (EndTicker - StartTicker); + } + } + + Duration = (UINT32) DivU64x32 ( + Ticker, + (UINT32) Freq + ); + + if (Duration > 0) { + ZeroMem (&mPerfData, sizeof (PERF_DATA)); + + GetNameFromHandle (Handles[mIndex], GaugeString); + + AsciiStrCpy (mPerfData.Token, GaugeString); + mPerfData.Duration = Duration; + + CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA)); + Ptr += sizeof (PERF_DATA); + + mPerfHeader.Count++; + if (mPerfHeader.Count == LimitCount) { + goto Done; + } + } + } + + gBS->FreePool (Handles); + + // + // Get inserted performance data + // + LogEntryKey = 0; + while ((LogEntryKey = GetPerformanceMeasurement ( + LogEntryKey, + &Handle, + &Token, + &Module, + &StartTicker, + &EndTicker)) != 0) { + if ((Handle == NULL) && (StartTicker <= EndTicker)) { + + ZeroMem (&mPerfData, sizeof (PERF_DATA)); + + AsciiStrnCpy (mPerfData.Token, Token, DXE_PERFORMANCE_STRING_SIZE); + mPerfData.Duration = (UINT32) DivU64x32 ( + EndTicker - StartTicker, + (UINT32) Freq + ); + + CopyMem (Ptr, &mPerfData, sizeof (PERF_DATA)); + Ptr += sizeof (PERF_DATA); + + mPerfHeader.Count++; + if (mPerfHeader.Count == LimitCount) { + goto Done; + } + } + } + +Done: + + ClearDebugRegisters (); + + mPerfHeader.Signiture = 0x66726550; + + // + // Put performance data to memory + // + CopyMem ( + (UINT32 *) (UINT32) mAcpiLowMemoryBase, + &mPerfHeader, + sizeof (PERF_HEADER) + ); + + gRT->SetVariable ( + L"PerfDataMemAddr", + &gEfiGlobalVariableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof (UINT32), + (VOID *) &mAcpiLowMemoryBase + ); + + return ; +} diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/Performance.h b/EdkNt32Pkg/Library/EdkGenericBdsLib/Performance.h new file mode 100644 index 0000000000..e7f80ab2c0 --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/Performance.h @@ -0,0 +1,55 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Performance.h + +Abstract: + + This file included the performance relete function header and + definition. + +--*/ + +#ifndef _PERF_H_ +#define _PERF_H_ + +#define PERF_TOKEN_LENGTH 28 +#define PERF_PEI_ENTRY_MAX_NUM 50 + +typedef struct { + CHAR8 Token[PERF_TOKEN_LENGTH]; + UINT32 Duration; +} PERF_DATA; + +typedef struct { + UINT64 BootToOs; + UINT64 S3Resume; + UINT32 S3EntryNum; + PERF_DATA S3Entry[PERF_PEI_ENTRY_MAX_NUM]; + UINT64 CpuFreq; + UINT64 BDSRaw; + UINT32 Count; + UINT32 Signiture; +} PERF_HEADER; + +VOID +WriteBootToOsPerformanceData ( + VOID + ); + +VOID +ClearDebugRegisters ( + VOID + ); + +#endif diff --git a/EdkNt32Pkg/Library/EdkGenericBdsLib/build.xml b/EdkNt32Pkg/Library/EdkGenericBdsLib/build.xml new file mode 100644 index 0000000000..ad30c96192 --- /dev/null +++ b/EdkNt32Pkg/Library/EdkGenericBdsLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/EdkNt32PeiPeCoffGetEntryPointLib.mbd b/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/EdkNt32PeiPeCoffGetEntryPointLib.mbd new file mode 100644 index 0000000000..8e23782db8 --- /dev/null +++ b/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/EdkNt32PeiPeCoffGetEntryPointLib.mbd @@ -0,0 +1,30 @@ + + + + + EdkNt32PeiPeCoffGetEntryPointLib + 434b164e-5fa6-4a3d-bc04-02da2a4eeb26 + 0 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + diff --git a/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/EdkNt32PeiPeCoffGetEntryPointLib.msa b/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/EdkNt32PeiPeCoffGetEntryPointLib.msa new file mode 100644 index 0000000000..bbed045ba4 --- /dev/null +++ b/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/EdkNt32PeiPeCoffGetEntryPointLib.msa @@ -0,0 +1,48 @@ + + + + + EdkNt32PeiPeCoffGetEntryPointLib + PEIM + LIBRARY + 434b164e-5fa6-4a3d-bc04-02da2a4eeb26 + 0 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + PeCoffGetEntryPointLib + PeiCoreLib + + + PeCoffGetEntryPoint.c + + + MdePkg + EdkNt32Pkg + + + NtPeiLoadFile + + diff --git a/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/PeCoffGetEntryPoint.c b/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/PeCoffGetEntryPoint.c new file mode 100644 index 0000000000..ed64158df7 --- /dev/null +++ b/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/PeCoffGetEntryPoint.c @@ -0,0 +1,75 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PeCoffGetEntryPoint.c + +Abstract: + + Tiano PE/COFF loader + +Revision History + +--*/ + + +RETURN_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + IN OUT VOID **EntryPoint + ) +/*++ + +Routine Description: + + Loads a PE/COFF image into memory + +Arguments: + + Pe32Data - Pointer to a PE/COFF Image + + EntryPoint - Pointer to the entry point of the PE/COFF image + +Returns: + + EFI_SUCCESS if the EntryPoint was returned + EFI_INVALID_PARAMETER if the EntryPoint could not be found from Pe32Data + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + NT_PEI_LOAD_FILE_PPI *PeiNtService; + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS ImageEntryPoint; + + Status = PeiCoreLocatePpi ( + &gNtPeiLoadFilePpiGuid, + 0, + &PpiDescriptor, + &PeiNtService + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = PeiNtService->PeiLoadFileService ( + Pe32Data, + &ImageAddress, + &ImageSize, + &ImageEntryPoint + ); + *EntryPoint = (VOID*)(UINTN)ImageEntryPoint; + return Status; +} \ No newline at end of file diff --git a/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/build.xml b/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/build.xml new file mode 100644 index 0000000000..c558a9b47f --- /dev/null +++ b/EdkNt32Pkg/Library/EdkNt32PeiPeCoffGetEntryPointLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoader.c b/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoader.c new file mode 100644 index 0000000000..d06e57a6d7 --- /dev/null +++ b/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoader.c @@ -0,0 +1,51 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + TianoPeCoffLoader.c + +Abstract: + + Wrap the Base PE/COFF loader with the PE COFF Protocol + + +--*/ + + + +EFI_PEI_PE_COFF_LOADER_PROTOCOL *mPeiEfiPeiPeCoffLoader; + +EFI_STATUS +PeCoffLoaderConstructor ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiPeCoffLoaderGuid, + 0, + NULL, + &mPeiEfiPeiPeCoffLoader + ); + return Status; +} + +EFI_PEI_PE_COFF_LOADER_PROTOCOL * +EFIAPI +GetPeCoffLoaderProtocol ( + ) +{ + return mPeiEfiPeiPeCoffLoader; +} diff --git a/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.mbd b/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.mbd new file mode 100644 index 0000000000..233d7d3c59 --- /dev/null +++ b/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.mbd @@ -0,0 +1,30 @@ + + + + + Nt32PeCoffLoaderLib + 3c5702f2-9b17-4273-b60c-b96e6cd13066 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-03-14 17:04 + 2006-03-31 13:20 + + diff --git a/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.msa b/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.msa new file mode 100644 index 0000000000..68a5ca2a6b --- /dev/null +++ b/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/Nt32PeCoffLoaderLib.msa @@ -0,0 +1,53 @@ + + + + + Nt32PeCoffLoaderLib + PEIM + LIBRARY + 3c5702f2-9b17-4273-b60c-b96e6cd13066 + EDK_RELEASE_VERSION 0x00020000 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-14 17:04 + 2006-03-31 13:20 + + + EdkPeCoffLoaderLib + + + Nt32PeCoffLoader.c + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + PeCoffLoader + + + + PeCoffLoaderConstructor + + + diff --git a/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/build.xml b/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/build.xml new file mode 100644 index 0000000000..1ca1244559 --- /dev/null +++ b/EdkNt32Pkg/Library/Nt32PeCoffLoaderLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Logo/Logo.mbd b/EdkNt32Pkg/Logo/Logo.mbd new file mode 100644 index 0000000000..346ff12fb8 --- /dev/null +++ b/EdkNt32Pkg/Logo/Logo.mbd @@ -0,0 +1,30 @@ + + + + + Logo + 7BB28B99-61BB-11D5-9A5D-0090273FC14D + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + diff --git a/EdkNt32Pkg/Logo/Logo.msa b/EdkNt32Pkg/Logo/Logo.msa new file mode 100644 index 0000000000..958dbbc36e --- /dev/null +++ b/EdkNt32Pkg/Logo/Logo.msa @@ -0,0 +1,48 @@ + + + + + Logo + BASE + LOGO + 7BB28B99-61BB-11D5-9A5D-0090273FC14D + 0 + Component description file for creating a Logo file. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + Logo.bmp + + + MdePkg + + + + + + + + + + diff --git a/EdkNt32Pkg/Logo/Logo_build.xml b/EdkNt32Pkg/Logo/Logo_build.xml new file mode 100644 index 0000000000..bbc8b000a4 --- /dev/null +++ b/EdkNt32Pkg/Logo/Logo_build.xml @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EdkNt32Pkg/Logo/build.xml b/EdkNt32Pkg/Logo/build.xml new file mode 100644 index 0000000000..f9828f3cfc --- /dev/null +++ b/EdkNt32Pkg/Logo/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Logo/logo.bmp b/EdkNt32Pkg/Logo/logo.bmp new file mode 100644 index 0000000000..5acbc17c5c Binary files /dev/null and b/EdkNt32Pkg/Logo/logo.bmp differ diff --git a/EdkNt32Pkg/Nt32.fpd b/EdkNt32Pkg/Nt32.fpd new file mode 100644 index 0000000000..38b2e48050 --- /dev/null +++ b/EdkNt32Pkg/Nt32.fpd @@ -0,0 +1,683 @@ + + + + + NT32 + EFI/Tiano Emulation Platform + The Emulation Platform can be used to debug individual modules, prior to creating a real platform. This also provides an example for how an FPD is created. + 2006-02-23 18:21 + lhauch + + + FlashMap.fdf + + + + + + + FV_RECOVERY + + NV_STORAGE + + + + FV_RECOVERY + NV_STORAGE + FV_FILE + + + EFI_READ_DISABLED_CAP + EFI_READ_ENABLED_CAP + EFI_READ_STATUS + EFI_WRITE_DISABLED_CAP + EFI_WRITE_ENABLED_CAP + EFI_WRITE_STATUS + EFI_LOCK_CAP + EFI_LOCK_STATUS + EFI_MEMORY_MAPPED + EFI_ALIGNMENT_CAP + EFI_ALIGNMENT_2 + EFI_ALIGNMENT_4 + EFI_ALIGNMENT_8 + EFI_ALIGNMENT_16 + EFI_ALIGNMENT_32 + EFI_ALIGNMENT_64 + EFI_ALIGNMENT_128 + EFI_ALIGNMENT_256 + EFI_ALIGNMENT_512 + EFI_ALIGNMENT_1K + EFI_ALIGNMENT_2K + EFI_ALIGNMENT_4K + EFI_ALIGNMENT_8K + EFI_ALIGNMENT_16K + EFI_ALIGNMENT_32K + EFI_ALIGNMENT_64K + EFI_STICKY_WRITE + + + + + NV_STORAGE + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + A + + + + + + + + + + + + + + + + + + EdkNt32Pkg + + + + + EdkNt32PeiPeCoffGetEntryPointLib + + + + + + + + + + + + + + + + + + Nt32PeCoffLoaderLib + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PcdMaximumUnicodeStringLength + 0x00000001 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 1000000 + + + PcdMaximumAsciiStringLength + 0x00000002 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 1000000 + + + PcdMaximumLinkedListLength + 0x00000003 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 1000000 + + + PcdSpinLockTimeout + 0x00000004 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 10000000 + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 0x0f + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 0x80000000 + + + PcdReportStatusCodePropertyMask + 0x00000007 + UINT8 + false + false + false + false + false + 0x00 + 0x00 + 1 + 0 + L"" + 0 + 0 + 0x07 + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + false + false + false + false + false + 0 + 0 + 1 + 0 + L"" + 0 + 0 + 0xAF + + + PcdPerformanceLibraryPropertyMask + 0x00000009 + UINT8 + false + false + false + false + false + 0x00 + 0x00 + 1 + 0 + L"" + 0 + 0 + 0 + + + PcdWinNtPhysicalDisk + 0x00001000 + VOID* + false + false + false + false + false + 0x00 + 0x00 + 24 + 0 + L"" + 0 + 0 + L"FW;40960;512" + + + PcdWinNtVirtualDisk + 0x00001001 + VOID* + false + false + false + false + false + 0x00 + 0x00 + 24 + 0 + L"" + 0 + 0 + L"FW;40960;512" + + + PcdWinNtSerialPort + 0x00001002 + VOID* + false + false + false + false + false + 0x00 + 0x00 + 20 + 0 + L"" + 0 + 0 + L"COM1!COM2" + + + PcdWinNtUga + 0x00001003 + VOID* + false + false + false + false + false + 0x00 + 0x00 + 50 + 0 + L"" + 0 + 0 + L"UGA Window 1!UGA Window 2" + + + PcdWinNtFileSystem + 0x00001004 + VOID* + false + false + false + false + false + 0x00 + 0x00 + 120 + 0 + L"" + 0 + 0 + L".!C:\\D\\work\\Remodel\\mdk\\EdkShellBinPkg\\bin\\ia32\\Apps" + + + PcdWinNtMemorySize + 0x00001005 + VOID* + false + false + false + false + false + 0x00 + 0x00 + 10 + 0 + L"" + 0 + 0 + L"64!64" + + + PcdWinNtBootMode + 0x00001006 + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 1 + + + PcdWinNtCpuModel + 0x00001007 + VOID* + false + false + false + false + false + 0x00 + 0x00 + 48 + 0 + L"" + 0 + 0 + L"Intel(R) Processor Model" + + + PcdWinNtCpuSpeed + 0x00001008 + VOID* + false + false + false + false + false + 0x00 + 0x00 + 8 + 0 + L"" + 0 + 0 + L"3000" + + + PcdWinNtFirmwareVolume + 0x00001009 + VOID* + false + false + false + false + false + 0x00 + 0x00 + 44 + 0 + L"" + 0 + 0 + L"..\\..\\Fv\\Fv_Recovery.fd" + + + PcdWinNtConsole + 0x0000100a + VOID* + false + false + false + false + false + 0x00 + 0x00 + 50 + 0 + L"" + 0 + 0 + L"Bus Driver Console Window" + + + PcdRothmanTest + 0x0000100b + UINT32 + true + false + false + false + false + 0x00 + 0x00 + 4 + 0B3ADA4F-AE56-4c24-8DEA-F03B7558AE50 + L"RothmanVariable" + 0 + 0 + 0 + + + PcdWinNtBinaryPatch1 + 0x0001000b + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 0x1234 + + + PcdWinNtBinaryPatch2 + 0x0001000c + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 0x5678 + + + PcdWinNtFeatureFlag1 + 0x0001000d + BOOLEAN + false + false + false + false + false + 0x00 + 0x00 + 1 + 0 + L"" + 0 + 0 + 0x1 + + + PcdWinNtDynamicUINT32 + 0x0001000e + UINT32 + false + false + false + false + false + 0x00 + 0x00 + 4 + 0 + L"" + 0 + 0 + 0x0 + + + + + + + + + + diff --git a/EdkNt32Pkg/Pei/Autoscan/WinNtAutoScan.mbd b/EdkNt32Pkg/Pei/Autoscan/WinNtAutoScan.mbd new file mode 100644 index 0000000000..c6a123ddf9 --- /dev/null +++ b/EdkNt32Pkg/Pei/Autoscan/WinNtAutoScan.mbd @@ -0,0 +1,43 @@ + + + + + WinNtAutoScan + BE0FEABA-3443-4919-9F3A-2D4216329EA9 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + PeimEntryPoint + PeiMemoryLib + PeiCoreLib + PeiServicesTablePointerLib + PeiHobLib + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Pei/Autoscan/WinNtAutoScan.msa b/EdkNt32Pkg/Pei/Autoscan/WinNtAutoScan.msa new file mode 100644 index 0000000000..5141634516 --- /dev/null +++ b/EdkNt32Pkg/Pei/Autoscan/WinNtAutoScan.msa @@ -0,0 +1,68 @@ + + + + + WinNtAutoScan + PEIM + PE32_PEIM + BE0FEABA-3443-4919-9F3A-2D4216329EA9 + 0 + Component description file for WinNtAutoScan module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + DebugLib + PeimEntryPoint + BaseLib + BaseMemoryLib + HobLib + PeiCoreLib + PeiServicesTablePointerLib + + + WinNtAutoScan.c + WinNtAutoscan.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + + EFI_RESOURCE_SYSTEM_MEMORY + + + + + NtAutoScan + BaseMemoryTest + MemoryDiscovered + + + + PeimInitializeWinNtAutoScan + + + diff --git a/EdkNt32Pkg/Pei/Autoscan/WinNtAutoscan.dxs b/EdkNt32Pkg/Pei/Autoscan/WinNtAutoscan.dxs new file mode 100644 index 0000000000..5b3af0e337 --- /dev/null +++ b/EdkNt32Pkg/Pei/Autoscan/WinNtAutoscan.dxs @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtAutoscan.dxs + +Abstract: + + Dependency expression file for WinNtAutoscan. + +--*/ + +#include +#include + +DEPENDENCY_START + PEI_NT_AUTOSCAN_PPI_GUID AND EFI_PEI_MASTER_BOOT_MODE_PEIM_PPI AND PEI_BASE_MEMORY_TEST_GUID +DEPENDENCY_END + + diff --git a/EdkNt32Pkg/Pei/Autoscan/WinntAutoscan.c b/EdkNt32Pkg/Pei/Autoscan/WinntAutoscan.c new file mode 100644 index 0000000000..c465ce68ca --- /dev/null +++ b/EdkNt32Pkg/Pei/Autoscan/WinntAutoscan.c @@ -0,0 +1,132 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + WinNtAutoscan.c + +Abstract: + Tiano PEIM to abstract memory auto-scan in a Windows NT environment. + +Revision History + +--*/ + +EFI_STATUS +EFIAPI +PeimInitializeWinNtAutoScan ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + Perform a call-back into the SEC simulator to get a memory value + +Arguments: + FfsHeader - General purpose data available to every PEIM + PeiServices - General purpose services available to every PEIM. + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + PEI_NT_AUTOSCAN_PPI *PeiNtService; + UINT64 MemorySize; + EFI_PHYSICAL_ADDRESS MemoryBase; + PEI_BASE_MEMORY_TEST_PPI *MemoryTestPpi; + EFI_PHYSICAL_ADDRESS ErrorAddress; + UINTN Index; + EFI_RESOURCE_ATTRIBUTE_TYPE Attributes; + + + DEBUG ((EFI_D_ERROR, "NT 32 Autoscan PEIM Loaded\n")); + + // + // Get the PEI NT Autoscan PPI + // + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPeiNtAutoScanPpiGuid, // GUID + 0, // INSTANCE + &PpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR + &PeiNtService // PPI + ); + ASSERT_EFI_ERROR (Status); + + // + // Get the Memory Test PPI + // + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPeiBaseMemoryTestPpiGuid, + 0, + NULL, + &MemoryTestPpi + ); + ASSERT_EFI_ERROR (Status); + + Index = 0; + do { + Status = PeiNtService->NtAutoScan (Index, &MemoryBase, &MemorySize); + if (!EFI_ERROR (Status)) { + Attributes = + ( + EFI_RESOURCE_ATTRIBUTE_PRESENT | + EFI_RESOURCE_ATTRIBUTE_INITIALIZED | + EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE | + EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE + ); + + if (Index == 0) { + // + // For the first area register it as PEI tested memory + // + Status = MemoryTestPpi->BaseMemoryTest ( + PeiServices, + MemoryTestPpi, + MemoryBase, + MemorySize, + Quick, + &ErrorAddress + ); + ASSERT_EFI_ERROR (Status); + + // + // Register the "tested" memory with the PEI Core + // + Status = (**PeiServices).InstallPeiMemory (PeiServices, MemoryBase, MemorySize); + ASSERT_EFI_ERROR (Status); + + Attributes |= EFI_RESOURCE_ATTRIBUTE_TESTED; + } + + BuildResourceDescriptorHob ( + EFI_RESOURCE_SYSTEM_MEMORY, + Attributes, + MemoryBase, + MemorySize + ); + } + Index++; + } while (!EFI_ERROR (Status)); + + // + // Build the CPU hob with 36-bit addressing and 16-bits of IO space. + // + BuildCpuHob (36, 16); + + return Status; +} diff --git a/EdkNt32Pkg/Pei/Autoscan/build.xml b/EdkNt32Pkg/Pei/Autoscan/build.xml new file mode 100644 index 0000000000..bdbd4c930e --- /dev/null +++ b/EdkNt32Pkg/Pei/Autoscan/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Pei/BootMode/BootMode.c b/EdkNt32Pkg/Pei/BootMode/BootMode.c new file mode 100644 index 0000000000..955c7595dc --- /dev/null +++ b/EdkNt32Pkg/Pei/BootMode/BootMode.c @@ -0,0 +1,85 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BootMode.c + +Abstract: + + Tiano PEIM to provide the platform support functionality within Windows + +--*/ + + + +// +// Module globals +// +EFI_PEI_PPI_DESCRIPTOR mPpiListBootMode = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiMasterBootModePpiGuid, + NULL +}; + +EFI_PEI_PPI_DESCRIPTOR mPpiListRecoveryBootMode = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiBootInRecoveryModePpiGuid, + NULL +}; + +EFI_STATUS +EFIAPI +InitializeBootMode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Peform the boot mode determination logic + +Arguments: + + PeiServices - General purpose services available to every PEIM. + +Returns: + + Status - EFI_SUCCESS if the boot mode could be set + +--*/ +// TODO: FfsHeader - add argument and description to function comment +{ + EFI_STATUS Status; + UINTN BootMode; + + DEBUG ((EFI_D_ERROR, "NT32 Boot Mode PEIM Loaded\n")); + + // + // Let's assume things are OK if not told otherwise + // Should we read an environment variable in order to easily change this? + // + BootMode = BOOT_WITH_FULL_CONFIGURATION; + + Status = (**PeiServices).SetBootMode (PeiServices, (UINT8) BootMode); + ASSERT_EFI_ERROR (Status); + + Status = (**PeiServices).InstallPpi (PeiServices, &mPpiListBootMode); + ASSERT_EFI_ERROR (Status); + + if (BootMode == BOOT_IN_RECOVERY_MODE) { + Status = (**PeiServices).InstallPpi (PeiServices, &mPpiListRecoveryBootMode); + ASSERT_EFI_ERROR (Status); + } + + return Status; +} diff --git a/EdkNt32Pkg/Pei/BootMode/BootMode.dxs b/EdkNt32Pkg/Pei/BootMode/BootMode.dxs new file mode 100644 index 0000000000..fd91a09892 --- /dev/null +++ b/EdkNt32Pkg/Pei/BootMode/BootMode.dxs @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + BootMode.dxs + +Abstract: + + Dependency expression file for BootMode. + +--*/ + +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END + + diff --git a/EdkNt32Pkg/Pei/BootMode/BootMode.mbd b/EdkNt32Pkg/Pei/BootMode/BootMode.mbd new file mode 100644 index 0000000000..5dd1a6fe20 --- /dev/null +++ b/EdkNt32Pkg/Pei/BootMode/BootMode.mbd @@ -0,0 +1,42 @@ + + + + + BootMode + B7611005-1F26-45ba-A3DB-01F39DDB2785 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + PeimEntryPoint + PeiMemoryLib + PeiCoreLib + PeiServicesTablePointerLib + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Pei/BootMode/BootMode.msa b/EdkNt32Pkg/Pei/BootMode/BootMode.msa new file mode 100644 index 0000000000..accb0b5ba3 --- /dev/null +++ b/EdkNt32Pkg/Pei/BootMode/BootMode.msa @@ -0,0 +1,59 @@ + + + + + BootMode + PEIM + PE32_PEIM + B7611005-1F26-45ba-A3DB-01F39DDB2785 + 0 + Component description file for Fwh module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + DebugLib + PeimEntryPoint + BaseLib + PeiCoreLib + PeiServicesTablePointerLib + + + BootMode.c + BootMode.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + BootInRecoveryMode + MasterBootMode + + + + InitializeBootMode + + + diff --git a/EdkNt32Pkg/Pei/BootMode/build.xml b/EdkNt32Pkg/Pei/BootMode/build.xml new file mode 100644 index 0000000000..cd67235b3a --- /dev/null +++ b/EdkNt32Pkg/Pei/BootMode/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Pei/FirmwareVolume/WinNtFwh.dxs b/EdkNt32Pkg/Pei/FirmwareVolume/WinNtFwh.dxs new file mode 100644 index 0000000000..6270ef0db7 --- /dev/null +++ b/EdkNt32Pkg/Pei/FirmwareVolume/WinNtFwh.dxs @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtFwh.dxs + +Abstract: + + Dependency expression file for WinNtFwh PEIM. + +--*/ + +#include +#include + +DEPENDENCY_START + NT_FWH_PPI_GUID AND EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID +DEPENDENCY_END + + diff --git a/EdkNt32Pkg/Pei/FirmwareVolume/WinNtFwh.mbd b/EdkNt32Pkg/Pei/FirmwareVolume/WinNtFwh.mbd new file mode 100644 index 0000000000..3c61664ecc --- /dev/null +++ b/EdkNt32Pkg/Pei/FirmwareVolume/WinNtFwh.mbd @@ -0,0 +1,43 @@ + + + + + WinNtFwh + F0384FFD-8633-452f-9010-F6B7D2EAE2F1 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-23 10:33 + + + PeimEntryPoint + PeiMemoryLib + PeiCoreLib + PeiServicesTablePointerLib + PeiHobLib + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Pei/FirmwareVolume/WinNtFwh.msa b/EdkNt32Pkg/Pei/FirmwareVolume/WinNtFwh.msa new file mode 100644 index 0000000000..3101d4866e --- /dev/null +++ b/EdkNt32Pkg/Pei/FirmwareVolume/WinNtFwh.msa @@ -0,0 +1,69 @@ + + + + + WinNtFwh + PEIM + PE32_PEIM + F0384FFD-8633-452f-9010-F6B7D2EAE2F1 + 0 + Component description file for WinNtFwh module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-23 10:33 + + + DebugLib + PeimEntryPoint + HobLib + PeiCoreLib + PeiServicesTablePointerLib + + + WinNtFwh.c + WinNtFwh.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + + FvRecovery.fv + + + EFI_RESOURCE_FIRMWARE_DEVICE + + + NVSTORAGE.fv + + + + NtFwh + + + + PeimInitializeWinNtFwh + + + diff --git a/EdkNt32Pkg/Pei/FirmwareVolume/WinntFwh.c b/EdkNt32Pkg/Pei/FirmwareVolume/WinntFwh.c new file mode 100644 index 0000000000..3764cb78ca --- /dev/null +++ b/EdkNt32Pkg/Pei/FirmwareVolume/WinntFwh.c @@ -0,0 +1,123 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + WinNtFwh.c + +Abstract: + PEIM to abstract construction of firmware volume in a Windows NT environment. + +Revision History + +--*/ + + +#include + + +EFI_STATUS +EFIAPI +PeimInitializeWinNtFwh ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + Perform a call-back into the SEC simulator to get address of the Firmware Hub + +Arguments: + FfsHeader - Ffs Header availible to every PEIM + PeiServices - General purpose services available to every PEIM. + +Returns: + None + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + NT_FWH_PPI *FwhPpi; + EFI_PHYSICAL_ADDRESS FdBase; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + UINT64 FdSize; + UINTN Index; + + DEBUG ((EFI_D_ERROR, "NT 32 Firmware Volume PEIM Loaded\n")); + + // + // Get the Fwh Information PPI + // + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gNtFwhPpiGuid, // GUID + 0, // INSTANCE + &PpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR + &FwhPpi // PPI + ); + ASSERT_EFI_ERROR (Status); + + Index = 0; + do { + // + // Get information about all the FD's in the system + // + Status = FwhPpi->NtFwh (Index, &FdBase, &FdSize); + if (!EFI_ERROR (Status)) { + // + // Assume the FD starts with an FV header + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) FdBase; + + // + // Make an FV Hob for the first FV in the FD + // + BuildFvHob (FdBase, FvHeader->FvLength); + + if (Index == 0) { + // + // Assume the first FD was produced by the NT32.DSC + // All these strange offests are needed to keep in + // sync with the FlashMap and NT32.dsc file + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_FIRMWARE_DEVICE, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + FdBase, + (FvHeader->FvLength + EFI_WINNT_RUNTIME_UPDATABLE_LENGTH + EFI_WINNT_FTW_SPARE_BLOCK_LENGTH) + ); + + // + // Hard code the address of the spare block and variable services. + // Assume it's a hard coded offset from FV0 in FD0. + // + FdBase = FdBase + EFI_WINNT_RUNTIME_UPDATABLE_OFFSET; + FdSize = EFI_WINNT_RUNTIME_UPDATABLE_LENGTH + EFI_WINNT_FTW_SPARE_BLOCK_LENGTH; + + BuildFvHob (FdBase, FdSize); + } else { + // + // For other FD's just map them in. + // + BuildResourceDescriptorHob ( + EFI_RESOURCE_FIRMWARE_DEVICE, + (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE), + FdBase, + FdSize + ); + } + } + + Index++; + } while (!EFI_ERROR (Status)); + + return Status; +} diff --git a/EdkNt32Pkg/Pei/FirmwareVolume/build.xml b/EdkNt32Pkg/Pei/FirmwareVolume/build.xml new file mode 100644 index 0000000000..7aa147bb9e --- /dev/null +++ b/EdkNt32Pkg/Pei/FirmwareVolume/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Pei/FlashMap/FlashMap.c b/EdkNt32Pkg/Pei/FlashMap/FlashMap.c new file mode 100644 index 0000000000..a8f7ba06ad --- /dev/null +++ b/EdkNt32Pkg/Pei/FlashMap/FlashMap.c @@ -0,0 +1,273 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FlashMap.c + +Abstract: + + PEIM to build GUIDed HOBs for platform specific flash map + +--*/ + + +#include + +EFI_STATUS +EFIAPI +GetAreaInfo ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_FLASH_MAP_PPI *This, + IN EFI_FLASH_AREA_TYPE AreaType, + IN EFI_GUID *AreaTypeGuid, + OUT UINT32 *NumEntries, + OUT EFI_FLASH_SUBAREA_ENTRY **Entries + ); + +EFI_STATUS +EFIAPI +MemoryDiscoveredPpiNotifyCallback ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +// +// Module globals +// +static PEI_FLASH_MAP_PPI mFlashMapPpi = { GetAreaInfo }; + +static EFI_PEI_PPI_DESCRIPTOR mPpiListFlashMap = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiFlashMapPpiGuid, + &mFlashMapPpi +}; + +static EFI_FLASH_AREA_DATA mFlashAreaData[] = { + // + // Variable area + // + { + EFI_VARIABLE_STORE_OFFSET, + EFI_VARIABLE_STORE_LENGTH, + EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, + EFI_FLASH_AREA_EFI_VARIABLES + }, + // + // FTW spare (backup) block + // + { + EFI_WINNT_FTW_SPARE_BLOCK_OFFSET, + EFI_WINNT_FTW_SPARE_BLOCK_LENGTH, + EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, + EFI_FLASH_AREA_FTW_BACKUP + }, + // + // FTW private working (state) area + // + { + EFI_FTW_WORKING_OFFSET, + EFI_FTW_WORKING_LENGTH, + EFI_FLASH_AREA_SUBFV | EFI_FLASH_AREA_MEMMAPPED_FV, + EFI_FLASH_AREA_FTW_STATE + }, + // + // Recovery FV + // + { + EFI_WINNT_FIRMWARE_OFFSET, + EFI_WINNT_FIRMWARE_LENGTH, + EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV, + EFI_FLASH_AREA_RECOVERY_BIOS + }, + // + // System Non-Volatile Storage FV + // + { + EFI_WINNT_RUNTIME_UPDATABLE_OFFSET, + EFI_WINNT_RUNTIME_UPDATABLE_LENGTH + EFI_WINNT_FTW_SPARE_BLOCK_LENGTH, + EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV, + EFI_FLASH_AREA_GUID_DEFINED + }, +}; + + +EFI_STATUS +EFIAPI +PeimInitializeFlashMap ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + Build GUIDed HOBs for platform specific flash map + +Arguments: + FfsHeader - A pointer to the EFI_FFS_FILE_HEADER structure. + PeiServices - General purpose services available to every PEIM. + +Returns: + EFI_STATUS + +--*/ +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + NT_FWH_PPI *NtFwhPpi; + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + EFI_PHYSICAL_ADDRESS FdBase; + UINT64 FdSize; + UINTN NumOfHobData; + UINTN Index; + EFI_FLASH_AREA_HOB_DATA FlashHobData; + + DEBUG ((EFI_D_ERROR, "NT 32 Flash Map PEIM Loaded\n")); + + // + // Install FlashMap PPI + // + Status = PeiCoreInstallPpi (&mPpiListFlashMap); + ASSERT_EFI_ERROR (Status); + + + // + // Get the Fwh Information PPI + // + Status = PeiCoreLocatePpi ( + &gNtFwhPpiGuid, // GUID + 0, // INSTANCE + &PpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR + &NtFwhPpi // PPI + ); + ASSERT_EFI_ERROR (Status); + + // + // Assume that FD0 contains the Flash map. + // + Status = NtFwhPpi->NtFwh (0, &FdBase, &FdSize); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Get number of types + // + NumOfHobData = sizeof (mFlashAreaData) / sizeof (EFI_FLASH_AREA_DATA); + + // + // Build flash area entries as GUIDed HOBs. + // + for (Index = 0; Index < NumOfHobData; Index++) { + (*PeiServices)->SetMem (&FlashHobData, sizeof (EFI_FLASH_AREA_HOB_DATA), 0); + + FlashHobData.AreaType = mFlashAreaData[Index].AreaType; + FlashHobData.NumberOfEntries = 1; + FlashHobData.SubAreaData.Attributes = mFlashAreaData[Index].Attributes; + FlashHobData.SubAreaData.Base = FdBase + (EFI_PHYSICAL_ADDRESS) (UINTN) mFlashAreaData[Index].Base; + FlashHobData.SubAreaData.Length = (EFI_PHYSICAL_ADDRESS) (UINTN) mFlashAreaData[Index].Length; + + switch (FlashHobData.AreaType) { + case EFI_FLASH_AREA_RECOVERY_BIOS: + case EFI_FLASH_AREA_MAIN_BIOS: + (*PeiServices)->CopyMem ( + &FlashHobData.AreaTypeGuid, + &gEfiFirmwareFileSystemGuid, + sizeof (EFI_GUID) + ); + (*PeiServices)->CopyMem ( + &FlashHobData.SubAreaData.FileSystem, + &gEfiFirmwareVolumeBlockProtocolGuid, + sizeof (EFI_GUID) + ); + break; + + case EFI_FLASH_AREA_GUID_DEFINED: + (*PeiServices)->CopyMem ( + &FlashHobData.AreaTypeGuid, + &gEfiSystemNvDataHobGuid, + sizeof (EFI_GUID) + ); + (*PeiServices)->CopyMem ( + &FlashHobData.SubAreaData.FileSystem, + &gEfiFirmwareVolumeBlockProtocolGuid, + sizeof (EFI_GUID) + ); + break; + + default: + break; + } + + BuildGuidDataHob ( + &gEfiFlashMapHobGuid, + &FlashHobData, + sizeof (EFI_FLASH_AREA_HOB_DATA) + ); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +GetAreaInfo ( + IN EFI_PEI_SERVICES **PeiServices, + IN PEI_FLASH_MAP_PPI *This, + IN EFI_FLASH_AREA_TYPE AreaType, + IN EFI_GUID *AreaTypeGuid, + OUT UINT32 *NumEntries, + OUT EFI_FLASH_SUBAREA_ENTRY **Entries + ) +/*++ + + Routine Description: + Implementation of Flash Map PPI + +--*/ +// TODO: function comment is missing 'Arguments:' +// TODO: function comment is missing 'Returns:' +// TODO: PeiServices - add argument and description to function comment +// TODO: This - add argument and description to function comment +// TODO: AreaType - add argument and description to function comment +// TODO: AreaTypeGuid - add argument and description to function comment +// TODO: NumEntries - add argument and description to function comment +// TODO: Entries - add argument and description to function comment +// TODO: EFI_SUCCESS - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +{ + EFI_STATUS Status; + EFI_PEI_HOB_POINTERS Hob; + EFI_HOB_FLASH_MAP_ENTRY_TYPE *FlashMapEntry; + + Status = PeiCoreGetHobList (&Hob.Raw); + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION && CompareGuid (&Hob.Guid->Name, &gEfiFlashMapHobGuid)) { + FlashMapEntry = (EFI_HOB_FLASH_MAP_ENTRY_TYPE *) Hob.Raw; + if (AreaType == FlashMapEntry->AreaType) { + if (AreaType == EFI_FLASH_AREA_GUID_DEFINED) { + if (!CompareGuid (AreaTypeGuid, &FlashMapEntry->AreaTypeGuid)) { + continue; + } + } + + *NumEntries = FlashMapEntry->NumEntries; + *Entries = FlashMapEntry->Entries; + return EFI_SUCCESS; + } + } + + Hob.Raw = GET_NEXT_HOB (Hob); + } + + return EFI_NOT_FOUND; +} diff --git a/EdkNt32Pkg/Pei/FlashMap/FlashMap.dxs b/EdkNt32Pkg/Pei/FlashMap/FlashMap.dxs new file mode 100644 index 0000000000..0c197de817 --- /dev/null +++ b/EdkNt32Pkg/Pei/FlashMap/FlashMap.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FlashMap.dxs + +Abstract: + + Dependency expression file for FindFv. + +--*/ + +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END + diff --git a/EdkNt32Pkg/Pei/FlashMap/FlashMap.mbd b/EdkNt32Pkg/Pei/FlashMap/FlashMap.mbd new file mode 100644 index 0000000000..8c38ee9f59 --- /dev/null +++ b/EdkNt32Pkg/Pei/FlashMap/FlashMap.mbd @@ -0,0 +1,43 @@ + + + + + PeiFlashMap + 681F3771-6F1D-42DE-9AA2-F82BBCDBC5F9 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-23 10:43 + + + PeimEntryPoint + PeiMemoryLib + PeiCoreLib + PeiServicesTablePointerLib + PeiHobLib + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Pei/FlashMap/FlashMap.msa b/EdkNt32Pkg/Pei/FlashMap/FlashMap.msa new file mode 100644 index 0000000000..c199978fb6 --- /dev/null +++ b/EdkNt32Pkg/Pei/FlashMap/FlashMap.msa @@ -0,0 +1,101 @@ + + + + + PeiFlashMap + PEIM + PE32_PEIM + 681F3771-6F1D-42DE-9AA2-F82BBCDBC5F9 + 0 + Component description file for FlashMap PEI module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-23 10:43 + + + DebugLib + PeimEntryPoint + HobLib + PeiCoreLib + PeiServicesTablePointerLib + BaseMemoryLib + + + FlashMap.c + FlashMap.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + FirmwareVolumeBlock + + + + VariableArea + gEfiFlashMapHobGuid + 0xb091e7d2, 0x5a0, 0x4198, 0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 + + + FtwBackupBlock + gEfiFlashMapHobGuid + 0xb091e7d2, 0x5a0, 0x4198, 0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 + + + FtwStateArea + gEfiFlashMapHobGuid + 0xb091e7d2, 0x5a0, 0x4198, 0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 + + + RecoveryBios + gEfiFlashMapHobGuid + 0xb091e7d2, 0x5a0, 0x4198, 0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 + + + SystemNvDataHob + gEfiFlashMapHobGuid + 0xb091e7d2, 0x5a0, 0x4198, 0x94, 0xf0, 0x74, 0xb7, 0xb8, 0xc5, 0x54, 0x59 + + + + FlashMap + NtFwh + + + + FlashMapHob + + + FirmwareFileSystem + + + SystemNvDataHob + + + + + PeimInitializeFlashMap + + + diff --git a/EdkNt32Pkg/Pei/FlashMap/build.xml b/EdkNt32Pkg/Pei/FlashMap/build.xml new file mode 100644 index 0000000000..b388551a3a --- /dev/null +++ b/EdkNt32Pkg/Pei/FlashMap/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Pei/MonoStatusCode/MonoStatusCode.c b/EdkNt32Pkg/Pei/MonoStatusCode/MonoStatusCode.c new file mode 100644 index 0000000000..27c73f576e --- /dev/null +++ b/EdkNt32Pkg/Pei/MonoStatusCode/MonoStatusCode.c @@ -0,0 +1,150 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MonoStatusCode.c + +Abstract: + + PEIM to provide the status code functionality, to aid in system debug. + It includes output to 0x80 port and/or to serial port. + This PEIM is monolithic. Different platform should provide different library. + +--*/ + +#include "MonoStatusCode.h" + +// +// Module globals +// +// +EFI_PEI_PROGRESS_CODE_PPI mStatusCodePpi = { PlatformReportStatusCode }; + +EFI_PEI_PPI_DESCRIPTOR mPpiListStatusCode = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEfiPeiStatusCodePpiGuid, + &mStatusCodePpi +}; + +// +// Function implemenations +// +EFI_STATUS +EFIAPI +TranslateDxeStatusCodeToPeiStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +/*++ + +Routine Description: + + Translate from a DXE status code interface into a PEI-callable + interface, making the PEI the least common denominator.. + +Arguments: + + Same as DXE ReportStatusCode RT service + +Returns: + + None + +--*/ +{ + return PlatformReportStatusCode (NULL, CodeType, Value, Instance, CallerId, Data); +} + +EFI_STATUS +EFIAPI +InitializeDxeReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Build a hob describing the status code listener that has been installed. + This will be used by DXE code until a runtime status code listener is + installed. + +Arguments: + + PeiServices - General purpose services available to every PEIM. + +Returns: + + Status - EFI_SUCCESS if the interface could be successfully + installed + +--*/ +{ + VOID *Instance; + VOID *HobData; + + Instance = (VOID *) (UINTN) TranslateDxeStatusCodeToPeiStatusCode; + + HobData = BuildGuidDataHob ( + &gEfiStatusCodeRuntimeProtocolGuid, + &Instance, + sizeof (VOID *) + ); + + ASSERT (HobData != NULL); + return EFI_SUCCESS; +} + +VOID +EFIAPI +InitializeMonoStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Initialize the platform status codes and publish the platform status code + PPI. + +Arguments: + + FfsHeader - FV this PEIM was loaded from. + PeiServices - General purpose services available to every PEIM. + +Returns: + + Status - EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + // + // Initialize status code listeners. + // + PlatformInitializeStatusCode (FfsHeader, PeiServices); + + // + // Publish the status code capability to other modules + // + Status = (*PeiServices)->InstallPpi (PeiServices, &mPpiListStatusCode); + + ASSERT_EFI_ERROR (Status); + + DEBUG ((EFI_D_ERROR, "\nMono Status Code PEIM Loaded\n")); + + return ; +} diff --git a/EdkNt32Pkg/Pei/MonoStatusCode/MonoStatusCode.dxs b/EdkNt32Pkg/Pei/MonoStatusCode/MonoStatusCode.dxs new file mode 100644 index 0000000000..3c86da0c63 --- /dev/null +++ b/EdkNt32Pkg/Pei/MonoStatusCode/MonoStatusCode.dxs @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MonoStatusCode.dxs + +Abstract: + + Dependency expression file for monolithic Status Code PEIM. + +--*/ +#include +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END + + diff --git a/EdkNt32Pkg/Pei/MonoStatusCode/MonoStatusCode.h b/EdkNt32Pkg/Pei/MonoStatusCode/MonoStatusCode.h new file mode 100644 index 0000000000..38a9022558 --- /dev/null +++ b/EdkNt32Pkg/Pei/MonoStatusCode/MonoStatusCode.h @@ -0,0 +1,111 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + MonoStatusCode.h + +Abstract: + + Monolithic single PEIM to provide the status code functionality. + The PEIM is a blend of libraries that correspond to the different status code + listeners that a platform installs. + +--*/ + +#ifndef _MONO_STATUS_CODE_H_ +#define _MONO_STATUS_CODE_H_ + +// +// Platform specific function Declarations. These must be implemented in a +// subdirectory named PlatformName in a file named PlatformStatusCode.c. +// See D845GRG\PlatformStatusCode.c for an example of a simple status code +// implementation. +// See Nt32\PlatformStatusCode.c for an example of a status code implementation +// that relocates itself into memory. +// +// +// This is the driver entry point and must be defined. +// +EFI_STATUS +EFIAPI +InstallMonoStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +; + +// +// This is the platform function to initialize the listeners desired by the +// platform. +// +VOID +PlatformInitializeStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +; + +// +// This is the platform function that calls all of the listeners desired by the +// platform. +// +EFI_STATUS +EFIAPI +PlatformReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +; + +// +// Platform independent function Declarations +// +// +// Initialize the status code listeners and publish the status code PPI. +// +VOID +EFIAPI +InitializeMonoStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +; + +// +// Convert a DXE status code call into a PEI status code call. +// +EFI_STATUS +EFIAPI +TranslateDxeStatusCodeToPeiStatusCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +; + +// +// Publish a HOB that contains the listener to be used by DXE. +// +EFI_STATUS +EFIAPI +InitializeDxeReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices + ) +; + +#endif diff --git a/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/MonoStatusCode.mbd b/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/MonoStatusCode.mbd new file mode 100644 index 0000000000..f48b4c7f0e --- /dev/null +++ b/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/MonoStatusCode.mbd @@ -0,0 +1,44 @@ + + + + + MonoStatusCode + 1501614E-0E6C-4ef4-8B8F-C276CDFB646F + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + PeiMemoryLib + PeiServicesTablePointerLib + PeiHobLib + PeimEntryPoint + EdkMemoryStatusCodeLib + PeiCoreLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/MonoStatusCode.msa b/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/MonoStatusCode.msa new file mode 100644 index 0000000000..a1e96c7bf9 --- /dev/null +++ b/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/MonoStatusCode.msa @@ -0,0 +1,70 @@ + + + + + MonoStatusCode + PEIM + PE32_PEIM + 1501614E-0E6C-4ef4-8B8F-C276CDFB646F + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + DebugLib + PeimEntryPoint + EdkMemoryStatusCodeLib + HobLib + + + ..\MonoStatusCode.c + ..\MonoStatusCode.h + PlatformStatusCode.c + ..\MonoStatusCode.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + StatusCode + + + + TranslateDxeStatusCodeToPeiStatusCode + gEfiStatusCodeRuntimeProtocolGuid + 0xd2b2b828, 0x826, 0x48a7, 0xb3, 0xdf, 0x98, 0x3c, 0x0, 0x60, 0x24, 0xf0 + + + + StatusCode + FvFileLoader + + + + InstallMonoStatusCode + + + diff --git a/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/PlatformStatusCode.c b/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/PlatformStatusCode.c new file mode 100644 index 0000000000..9d1a57b2ee --- /dev/null +++ b/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/PlatformStatusCode.c @@ -0,0 +1,162 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PlatformStatusCode.c + +Abstract: + + Contains NT32 specific implementations required to use status codes. + +--*/ + +#include "../MonoStatusCode.h" + + +BOOLEAN gRunningFromMemory = FALSE; +// +// Platform definitions +// +EFI_PEI_REPORT_STATUS_CODE mSecReportStatusCode = NULL; + +extern EFI_PEI_PROGRESS_CODE_PPI mStatusCodePpi; + +// +// Function implementations +// +EFI_STATUS +EFIAPI +PlatformReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +/*++ + +Routine Description: + + Call all status code listeners in the MonoStatusCode. + +Arguments: + + Same as ReportStatusCode service + +Returns: + + EFI_SUCCESS Always returns success. + +--*/ +{ + mSecReportStatusCode (PeiServices, CodeType, Value, Instance, CallerId, Data); + MemoryReportStatusCode (CodeType, Value, Instance, CallerId, Data); + return EFI_SUCCESS; +} + +VOID +PlatformInitializeStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Initialize the status code listeners. This consists of locating the + listener produced by SecMain.exe. + +Arguments: + + FfsHeader - FV this PEIM was loaded from. + PeiServices - General purpose services available to every PEIM. + +Returns: + + None + +--*/ +{ + EFI_STATUS Status; + EFI_PEI_PROGRESS_CODE_PPI *ReportStatusCodePpi; + EFI_PEI_PPI_DESCRIPTOR *ReportStatusCodeDescriptor; + + // + // Cache the existing status code listener installed by the SEC core. + // We should actually do a heap allocate, install a PPI, etc, but since we + // know that we are running from a DLL, we can use global variables, and + // directly update the status code PPI descriptor + // + // + // Locate SEC status code PPI + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiStatusCodePpiGuid, + 0, + &ReportStatusCodeDescriptor, + &ReportStatusCodePpi + ); + if (EFI_ERROR (Status)) { + return ; + } + + mSecReportStatusCode = ReportStatusCodePpi->ReportStatusCode; + ReportStatusCodeDescriptor->Ppi = &mStatusCodePpi; + + // + // Always initialize memory status code listener. + // + MemoryStatusCodeInitialize (FfsHeader, PeiServices); + +} + +EFI_STATUS +EFIAPI +InstallMonoStatusCode ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Install the PEIM. Publish the DXE callback as well. + +Arguments: + + FfsHeader - FV this PEIM was loaded from. + PeiServices - General purpose services available to every PEIM. + +Returns: + + EFI_SUCCESS The function always returns success. + +--*/ +{ + if (!gRunningFromMemory) { + // + // First pass, running from flash, initialize everything + // + InitializeMonoStatusCode (FfsHeader, PeiServices); + } else { + // + // Second pass, running from memory, initialize memory listener and + // publish the DXE listener in a HOB. + // + MemoryStatusCodeInitialize (FfsHeader, PeiServices); + InitializeDxeReportStatusCode (PeiServices); + } + + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/build.xml b/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/build.xml new file mode 100644 index 0000000000..e6c8551241 --- /dev/null +++ b/EdkNt32Pkg/Pei/MonoStatusCode/Nt32/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.c b/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.c new file mode 100644 index 0000000000..69261b952b --- /dev/null +++ b/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.c @@ -0,0 +1,657 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PcdEmulator.c + +Abstract: + Platform Configuration Database (PCD) Service PEIM + +--*/ + +#include + +// +// BugBug: PEI early phase does not support global variable!!! +// This is only a temperary solution. +// + +UINTN mSkuId = 0; + + +STATIC EMULATED_PCD_DATABASE_EX * +GetPcdDataBaseEx ( + VOID +) { + EFI_HOB_GUID_TYPE *GuidHob; + EMULATED_PCD_DATABASE_EX *EmulatedPcdDatabaseEx; + + GuidHob = GetFirstGuidHob (&gPcdHobGuid); + EmulatedPcdDatabaseEx = (EMULATED_PCD_DATABASE_EX *) GET_GUID_HOB_DATA(GuidHob); + + return EmulatedPcdDatabaseEx; +} + +STATIC UINTN +GetPcdDataBaseExEntryCount ( + EMULATED_PCD_DATABASE_EX * Database +) { + return Database->Count; +} + +STATIC UINTN +GetPcdDataBaseExSize ( + EMULATED_PCD_DATABASE_EX * Database +) { + UINTN Size; + + Size = sizeof (Database->Count) + + (sizeof (Database->Entry[0]) * Database->Count); + + return Size; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSetSku ( + IN UINTN SkuId + ) +{ + mSkuId = SkuId; + return EFI_SUCCESS; +} + +UINT8 +EFIAPI +PcdEmulatorGet8 ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + ASSERT (Pcd->DatumSize == 1); + + return (UINT8)Pcd->Datum; +} + +UINT16 +EFIAPI +PcdEmulatorGet16 ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + ASSERT (Pcd->DatumSize == 2); + + return (UINT16)Pcd->Datum; +} + +UINT32 +EFIAPI +PcdEmulatorGet32 ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + ASSERT (Pcd->DatumSize == 4); + + return (UINT32)Pcd->Datum; +} + +UINT64 +EFIAPI +PcdEmulatorGet64 ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + ASSERT (Pcd->DatumSize == sizeof (UINT64)); + + return (UINT64)Pcd->Datum; +} + +VOID * +EFIAPI +PcdEmulatorGetPtr ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + + return (VOID *)(UINTN)Pcd->ExtendedData; +} + +BOOLEAN +EFIAPI +PcdEmulatorGetBoolean ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + ASSERT (Pcd->DatumSize == 1); + + return (BOOLEAN)Pcd->Datum; +} + +UINTN +EFIAPI +PcdEmulatorGetSize ( + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + return Pcd->DatumSize; +} + +UINT8 +EFIAPI +PcdEmulatorGet8Ex ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT16 +EFIAPI +PcdEmulatorGet16Ex ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT32 +EFIAPI +PcdEmulatorGet32Ex ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +UINT64 +EFIAPI +PcdEmulatorGet64Ex ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +VOID * +EFIAPI +PcdEmulatorGetPtrEx ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +BOOLEAN +EFIAPI +PcdEmulatorGetBooleanEx ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + ASSERT (FALSE); + return 0; +} + +UINTN +EFIAPI +PcdEmulatorGetSizeEx ( + IN CONST EFI_GUID *PcdDataBaseName, + IN UINTN TokenNumber + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + return Pcd->DatumSize; +} + + +EFI_STATUS +EFIAPI +PcdEmulatorSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + + ASSERT (Pcd->DatumSize == sizeof (UINT8)); + + Pcd->Datum = Value; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + + ASSERT (Pcd->DatumSize == sizeof (UINT32)); + + Pcd->Datum = Value; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSetPtr ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSetBoolean ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet8Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet16Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet32Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSet64Ex ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSetPtrEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorSetBooleanEx ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + + ASSERT (FALSE); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PPI_CALLBACK CallBackFunction + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + + if (Pcd->CallBackListSize == Pcd->CallBackEntries) { + return EFI_OUT_OF_RESOURCES; + } + + Pcd->CallBackList[Pcd->CallBackEntries++] = CallBackFunction; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PcdEmulatorUnregisterCallBackOnSet ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PPI_CALLBACK CallBackfunction + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + UINT32 Index; + + Pcd = GetPcdEntry (TokenNumber); + ASSERT (Pcd != NULL); + + for (Index = 0; Index < Pcd->CallBackListSize; Index++) { + if (Pcd->CallBackList[Index] == CallBackfunction) { + Pcd->CallBackList[Index] = NULL; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +EFIAPI +PcdEmulatorGetNextToken ( + IN CONST EFI_GUID *Guid, OPTIONAL + IN UINTN *Token + ) +{ + EMULATED_PCD_ENTRY_EX *Pcd; + EMULATED_PCD_ENTRY_EX *LastPcdEntry; + EMULATED_PCD_DATABASE_EX *PcdDatabase; + EMULATED_PCD_ENTRY_EX *PcdEntry; + + PcdDatabase = GetPcdDataBaseEx (); + PcdEntry = PcdDatabase->Entry; + + if (*Token == PCD_INVALID_TOKEN) { + // + // BugBug: Due to variable size array, ensure we convert this to a reasonable database + // that can accomodate array references for simplicity's sake + *Token = PcdEntry[0].Token; + return EFI_SUCCESS; + } + + Pcd = GetPcdEntry (*Token); + if (Pcd == NULL) { + return EFI_NOT_FOUND; + } + + LastPcdEntry = PcdEntry + GetPcdDataBaseExEntryCount (PcdDatabase); + if (++Pcd >= LastPcdEntry) { + return EFI_NOT_FOUND; + } + + *Token = Pcd->Token; + return EFI_SUCCESS; +} + +PCD_PPI mPcdPpiInstance = { + PcdEmulatorSetSku, + + PcdEmulatorGet8, + PcdEmulatorGet16, + PcdEmulatorGet32, + PcdEmulatorGet64, + PcdEmulatorGetPtr, + PcdEmulatorGetBoolean, + PcdEmulatorGetSize, + + PcdEmulatorGet8Ex, + PcdEmulatorGet16Ex, + PcdEmulatorGet32Ex, + PcdEmulatorGet64Ex, + PcdEmulatorGetPtrEx, + PcdEmulatorGetBooleanEx, + PcdEmulatorGetSizeEx, + + PcdEmulatorSet8, + PcdEmulatorSet16, + PcdEmulatorSet32, + PcdEmulatorSet64, + PcdEmulatorSetPtr, + PcdEmulatorSetBoolean, + + PcdEmulatorSet8Ex, + PcdEmulatorSet16Ex, + PcdEmulatorSet32Ex, + PcdEmulatorSet64Ex, + PcdEmulatorSetPtrEx, + PcdEmulatorSetBooleanEx, + + PcdEmulatorCallBackOnSet, + PcdEmulatorUnregisterCallBackOnSet, + PcdEmulatorGetNextToken +}; + +STATIC EFI_PEI_PPI_DESCRIPTOR mPpiPCD = { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPcdPpiGuid, + &mPcdPpiInstance +}; + +EFI_STATUS +EFIAPI +PeimPcdEmulatorEntry ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + UINTN Index; + UINTN Count; + UINTN Calculation; + UINT8 *AllocatedBuffer; + EMULATED_PCD_DATABASE_EX *EmulatedPcdDatabaseEx; + EMULATED_PCD_ENTRY_EX *EmulatedPcdEntryEx; + + // + // BugBug: Normally, we would read an FFS file for this data + // We need to remember, that when we read the FFS file, items such as the VariableName will not be encoded as a pointer + // but as an array of content. In this emulation, our init is encoding this data as a pointer. + // In the FFS version, we will depend on the proper Entry Count in the FFS data since the structures will + // now be variable length. + // + // + + // + // We should now read from the FFS file into the cache - for now, we fake this. + // + Count = GetPcdDataBaseSize () / sizeof (EMULATED_PCD_ENTRY); + + // + // Let's now determine how big of a buffer we need for our database + // For the FFS version, we need to calculate/consider the VariableName/ExtendedData size!!! + // + Calculation = sizeof (UINTN) + (Count * sizeof (EMULATED_PCD_ENTRY_EX)); + + EmulatedPcdDatabaseEx = (EMULATED_PCD_DATABASE_EX *) BuildGuidHob (&gPcdHobGuid, Calculation); + + EmulatedPcdDatabaseEx->Count = Count; + EmulatedPcdEntryEx = EmulatedPcdDatabaseEx->Entry; + + AllocatedBuffer = AllocatePool (Count * sizeof (PCD_PPI_CALLBACK) * MAX_PCD_CALLBACK); + ASSERT (AllocatedBuffer != NULL); + + for (Index = 0; Index < Count; Index++) { + // + // Copy from source to our own allocated buffer - normally an FFS read + // + (*PeiServices)->CopyMem ( + (VOID *) (EmulatedPcdEntryEx + Index), + (VOID *) (gEmulatedPcdEntry + Index), + sizeof (EMULATED_PCD_ENTRY) + ); + + // + // All the CallBackList worker functions refer to this CallBackList as CallBackList[CallbackEntry] + // so we seed the same buffer address here. + // + EmulatedPcdEntryEx[Index].CallBackList = (PCD_PPI_CALLBACK *)AllocatedBuffer; + AllocatedBuffer+= (sizeof (PCD_PPI_CALLBACK) * MAX_PCD_CALLBACK); + EmulatedPcdEntryEx[Index].CallBackEntries = 0; + EmulatedPcdEntryEx[Index].CallBackListSize = MAX_PCD_CALLBACK; + } + + // + // Install PCD service PPI + // + Status = PeiCoreInstallPpi (&mPpiPCD); + + ASSERT_EFI_ERROR (Status); + return Status; +} + + +EMULATED_PCD_ENTRY_EX * +GetPcdEntry ( + IN UINTN TokenNumber + ) +{ + UINTN Index; + UINTN Count; + EMULATED_PCD_DATABASE_EX *EmulatedPcdDatabaseEx; + EMULATED_PCD_ENTRY_EX *EmulatedPcdEntryEx; + + CpuBreakpoint (); + + EmulatedPcdDatabaseEx = GetPcdDataBaseEx (); + // + // BugBug: This Count will change when we flip over to FFS version + // + Count = EmulatedPcdDatabaseEx->Count; + EmulatedPcdEntryEx = EmulatedPcdDatabaseEx->Entry; + for (Index = 0; Index < Count; Index++) { + if (EmulatedPcdEntryEx[Index].Token == TokenNumber) { + return &EmulatedPcdEntryEx[Index]; + } + } + return NULL; +} + + diff --git a/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.dxs b/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.dxs new file mode 100644 index 0000000000..ea579976c8 --- /dev/null +++ b/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.dxs @@ -0,0 +1,25 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + PcdEmulator.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include + +DEPENDENCY_START + TRUE +DEPENDENCY_END diff --git a/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.h b/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.h new file mode 100644 index 0000000000..e97c2a1201 --- /dev/null +++ b/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.h @@ -0,0 +1,53 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + PcdEmulator.h + +Abstract: + Platform Configuration Database (PCD) + +--*/ + +#ifndef __PCD_EMULATOR_H__ +#define __PCD_EMULATOR_H__ + + + +// +// BugBug: Not very sure, where to put this "extern" +// +extern GUID gPcdHobGuid; + +// +// BugBug: Hack max number of callbacks per token +// +#define MAX_PCD_CALLBACK 0x10 + +extern EMULATED_PCD_ENTRY gEmulatedPcdEntry[]; + +UINTN +GetPcdDataBaseSize ( + VOID + ); + +EMULATED_PCD_ENTRY_EX * +GetPcdEntry ( + IN UINTN TokenNumber + ); + +EFI_STATUS +InstallMyHob ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); +#endif diff --git a/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.mbd b/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.mbd new file mode 100644 index 0000000000..816cf6f869 --- /dev/null +++ b/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.mbd @@ -0,0 +1,41 @@ + + + + + PcdEmulatorPeim + 9B3ADA4F-AE56-4c24-8DEA-F03B7558AE50 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-24 18:54 + + + PeimEntryPoint + BaseLib + PeiCoreLib + PeiServicesTablePointerLib + PeiHobLib + BaseDebugLibReportStatusCode + PeiMemoryLib + PeiReportStatusCodeLib + PeiMemoryAllocationLib + + diff --git a/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.msa b/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.msa new file mode 100644 index 0000000000..9a329a2b66 --- /dev/null +++ b/EdkNt32Pkg/Pei/PcdEmulator/PcdEmulator.msa @@ -0,0 +1,72 @@ + + + + + PcdEmulatorPeim + PEIM + PE32_PEIM + 9B3ADA4F-AE56-4c24-8DEA-F03B7558AE50 + EDK_RELEASE_VERSION 0x00020000 + Component description file for PcdEmulator PEIM module + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-14 17:04 + 2006-03-24 18:54 + + + DebugLib + PeimEntryPoint + BaseLib + HobLib + PeiCoreLib + PcdLib + PeiServicesTablePointerLib + MemoryAllocationLib + + + PcdEmulator.dxs + PcdEmulator.c + + + MdePkg + EdkNt32Pkg + + + + PcdDataBase + gPcdHobGuid + 0x582e7ca1, 0x68cd, 0x4d44, 0xb4, 0x3b, 0xf2, 0x98, 0xed, 0x58, 0x7b, 0xa6 + + + + Pcd + + + + PcdHob + + + + + PeimPcdEmulatorEntry + + + diff --git a/EdkNt32Pkg/Pei/PcdEmulator/build.xml b/EdkNt32Pkg/Pei/PcdEmulator/build.xml new file mode 100644 index 0000000000..86e0d1fc8e --- /dev/null +++ b/EdkNt32Pkg/Pei/PcdEmulator/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Pei/WinNtStuff/WinNtStuff.dxs b/EdkNt32Pkg/Pei/WinNtStuff/WinNtStuff.dxs new file mode 100644 index 0000000000..107ddee3e1 --- /dev/null +++ b/EdkNt32Pkg/Pei/WinNtStuff/WinNtStuff.dxs @@ -0,0 +1,29 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtStuff.dxs + +Abstract: + + Dependency expression file for WinNtStuff PEIM. + +--*/ + +#include +#include + +DEPENDENCY_START + PEI_NT_THUNK_PPI_GUID AND EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID +DEPENDENCY_END + + diff --git a/EdkNt32Pkg/Pei/WinNtStuff/WinNtStuff.mbd b/EdkNt32Pkg/Pei/WinNtStuff/WinNtStuff.mbd new file mode 100644 index 0000000000..ab862efcae --- /dev/null +++ b/EdkNt32Pkg/Pei/WinNtStuff/WinNtStuff.mbd @@ -0,0 +1,43 @@ + + + + + WinNtStuff + D3AAD8DC-3A48-46ac-B1C7-28A9D3CF6755 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + PeimEntryPoint + PeiMemoryLib + PeiCoreLib + PeiServicesTablePointerLib + PeiHobLib + PeiReportStatusCodeLib + BaseDebugLibReportStatusCode + BaseLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/Pei/WinNtStuff/WinNtStuff.msa b/EdkNt32Pkg/Pei/WinNtStuff/WinNtStuff.msa new file mode 100644 index 0000000000..11aa06a21b --- /dev/null +++ b/EdkNt32Pkg/Pei/WinNtStuff/WinNtStuff.msa @@ -0,0 +1,68 @@ + + + + + WinNtStuff + PEIM + PE32_PEIM + D3AAD8DC-3A48-46ac-B1C7-28A9D3CF6755 + 0 + Component description file for WinNtStuff module + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + DebugLib + PeimEntryPoint + HobLib + PeiCoreLib + PeiServicesTablePointerLib + + + WinNtStuff.c + WinNtStuff.dxs + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + WinNtThunk + + + + WinNtThunkProtocol + gEfiWinNtThunkProtocolGuid + 0x58c518b1, 0x76f3, 0x11d4, 0xbc, 0xea, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + + NtThunk + + + + PeimInitializeWinNtStuff + + + diff --git a/EdkNt32Pkg/Pei/WinNtStuff/build.xml b/EdkNt32Pkg/Pei/WinNtStuff/build.xml new file mode 100644 index 0000000000..885bacb1a2 --- /dev/null +++ b/EdkNt32Pkg/Pei/WinNtStuff/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/Pei/WinNtStuff/winntstuff.c b/EdkNt32Pkg/Pei/WinNtStuff/winntstuff.c new file mode 100644 index 0000000000..46859286ea --- /dev/null +++ b/EdkNt32Pkg/Pei/WinNtStuff/winntstuff.c @@ -0,0 +1,73 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtStuff.c + +Abstract: + + Tiano PEIM to abstract construction of firmware volume in a Windows NT environment. + +Revision History + +--*/ + + + +EFI_STATUS +EFIAPI +PeimInitializeWinNtStuff ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +/*++ + +Routine Description: + + Perform a call-back into the SEC simulator to get NT Stuff + +Arguments: + + PeiServices - General purpose services available to every PEIM. + +Returns: + + None + +--*/ +// TODO: FfsHeader - add argument and description to function comment +{ + EFI_STATUS Status; + EFI_PEI_PPI_DESCRIPTOR *PpiDescriptor; + PEI_NT_THUNK_PPI *PeiNtService; + VOID *Ptr; + + DEBUG ((EFI_D_ERROR, "NT 32 WinNT Stuff PEIM Loaded\n")); + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPeiNtThunkPpiGuid, // GUID + 0, // INSTANCE + &PpiDescriptor, // EFI_PEI_PPI_DESCRIPTOR + &PeiNtService // PPI + ); + ASSERT_EFI_ERROR (Status); + + Ptr = PeiNtService->NtThunk (); + + BuildGuidDataHob ( + &gEfiWinNtThunkProtocolGuid, // Guid + &Ptr, // Buffer + sizeof (VOID *) // Sizeof Buffer + ); + return Status; +} diff --git a/EdkNt32Pkg/RuntimeDxe/FvbServices/Common/FWBlockService.c b/EdkNt32Pkg/RuntimeDxe/FvbServices/Common/FWBlockService.c new file mode 100644 index 0000000000..e22a3233c4 --- /dev/null +++ b/EdkNt32Pkg/RuntimeDxe/FvbServices/Common/FWBlockService.c @@ -0,0 +1,1939 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FWBlockService.c + +Abstract: + +Revision History + +--*/ + +#include "FWBlockService.h" +#include "EfiFlashMap.h" +#include EFI_GUID_DEFINITION (FlashMapHob) + +ESAL_FWB_GLOBAL *mFvbModuleGlobal; + +EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = { + FVB_DEVICE_SIGNATURE, + { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { + sizeof (MEMMAP_DEVICE_PATH), + 0 + } + }, + EfiMemoryMappedIO, + 0, + 0, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + sizeof (EFI_DEVICE_PATH_PROTOCOL), + 0 + } + } + }, + 0, + { + FvbProtocolGetAttributes, + FvbProtocolSetAttributes, + FvbProtocolGetPhysicalAddress, + FvbProtocolGetBlockSize, + FvbProtocolRead, + FvbProtocolWrite, + FvbProtocolEraseBlocks, + NULL + }, + { + FvbExtendProtocolEraseCustomBlockRange + } +}; + +EFI_DRIVER_ENTRY_POINT (FvbInitialize) + + +VOID +EFIAPI +FvbVirtualddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Fixup internal data so that EFI and SAL can be call in virtual mode. + Call the passed in Child Notify event and convert the mFvbModuleGlobal + date items to there virtual address. + + mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] - Physical copy of instance data + mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] - Virtual pointer to common + instance data. + +Arguments: + + (Standard EFI notify event - EFI_EVENT_NOTIFY) + +Returns: + + None + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN Index; + + EfiConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]); + + // + // Convert the base address of all the instances + // + Index = 0; + FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; + while (Index < mFvbModuleGlobal->NumFv) { + EfiConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]); + EfiConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &FwhInstance->FvWriteBase[FVB_VIRTUAL]); + FwhInstance = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhInstance) + FwhInstance->VolumeHeader.HeaderLength + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))); + Index++; + } + + EfiConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]); + EfiConvertPointer (EFI_INTERNAL_POINTER, (VOID **) &mFvbModuleGlobal); +} + +VOID +FvbMemWrite8 ( + IN UINT64 Dest, + IN UINT8 Byte + ) +{ + EfiMemWrite (EfiCpuIoWidthUint8, Dest, 1, &Byte); + + return ; +} + +EFI_STATUS +GetFvbInstance ( + IN UINTN Instance, + IN ESAL_FWB_GLOBAL *Global, + OUT EFI_FW_VOL_INSTANCE **FwhInstance, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Retrieves the physical address of a memory mapped FV + +Arguments: + Instance - The FV instance whose base address is going to be + returned + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhRecord; + + if (Instance >= Global->NumFv) { + return EFI_INVALID_PARAMETER; + } + // + // Find the right instance of the FVB private data + // + FwhRecord = Global->FvInstance[Virtual]; + while (Instance > 0) { + FwhRecord = (EFI_FW_VOL_INSTANCE *) ((UINTN)((UINT8 *)FwhRecord) + FwhRecord->VolumeHeader.HeaderLength + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER))); + Instance--; + } + + *FwhInstance = FwhRecord; + + return EFI_SUCCESS; +} + +EFI_STATUS +FvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *Address, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Retrieves the physical address of a memory mapped FV + +Arguments: + Instance - The FV instance whose base address is going to be + returned + Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS + that on successful return, contains the base address + of the firmware volume. + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + *Address = FwhInstance->FvBase[Virtual]; + + return EFI_SUCCESS; +} + +EFI_STATUS +FvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + +Arguments: + Instance - The FV instance whose attributes is going to be + returned + Attributes - Output buffer which contains attributes + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + *Attributes = FwhInstance->VolumeHeader.Attributes; + + return EFI_SUCCESS; +} + +EFI_STATUS +FvbGetLbaAddress ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaWriteAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Retrieves the starting address of an LBA in an FV + +Arguments: + Instance - The FV instance which the Lba belongs to + Lba - The logical block address + LbaAddress - On output, contains the physical starting address + of the Lba + LbaWriteAddress - On output, contains the physical starting address + of the Lba for writing + LbaLength - On output, contains the length of the block + NumOfBlocks - A pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + UINT32 NumBlocks; + UINT32 BlockLength; + UINTN Offset; + EFI_LBA StartLba; + EFI_LBA NextLba; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + + StartLba = 0; + Offset = 0; + BlockMap = &(FwhInstance->VolumeHeader.FvBlockMap[0]); + + // + // Parse the blockmap of the FV to find which map entry the Lba belongs to + // + while (TRUE) { + NumBlocks = BlockMap->NumBlocks; + BlockLength = BlockMap->BlockLength; + + if (NumBlocks == 0 || BlockLength == 0) { + return EFI_INVALID_PARAMETER; + } + + NextLba = StartLba + NumBlocks; + + // + // The map entry found + // + if (Lba >= StartLba && Lba < NextLba) { + Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength); + if (LbaAddress) { + *LbaAddress = FwhInstance->FvBase[Virtual] + Offset; + } + + if (LbaWriteAddress) { + *LbaWriteAddress = FwhInstance->FvWriteBase[Virtual] + Offset; + } + + if (LbaLength) { + *LbaLength = BlockLength; + } + + if (NumOfBlocks) { + *NumOfBlocks = (UINTN) (NextLba - Lba); + } + + return EFI_SUCCESS; + } + + StartLba = NextLba; + Offset = Offset + NumBlocks * BlockLength; + BlockMap++; + } +} + +EFI_STATUS +FvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Reads specified number of bytes into a buffer from the specified block + +Arguments: + Instance - The FV instance to be read from + Lba - The logical block address to be read from + BlockOffset - Offset into the block at which to begin reading + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes read + Buffer - Pointer to a caller allocated buffer that will be + used to hold the data read + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes returned + in Buffer + EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be read + EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL + +--*/ +{ + EFI_FVB_ATTRIBUTES Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + + // + // Check for invalid conditions + // + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (*NumBytes == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, NULL, &LbaLength, NULL, Global, Virtual); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check if the FV is read enabled + // + FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); + + if ((Attributes & EFI_FVB_READ_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + // + // Perform boundary checks and adjust NumBytes + // + if (BlockOffset > LbaLength) { + return EFI_INVALID_PARAMETER; + } + + if (LbaLength < (*NumBytes + BlockOffset)) { + *NumBytes = (UINT32) (LbaLength - BlockOffset); + Status = EFI_BAD_BUFFER_SIZE; + } + + EfiMemRead (EfiCpuIoWidthUint8, LbaAddress + BlockOffset, (UINTN) *NumBytes, Buffer); + + return Status; +} + +EFI_STATUS +FlashFdWrite ( + IN UINTN WriteAddress, + IN UINTN Address, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN UINTN LbaLength + ) +/*++ + +Routine Description: + Writes specified number of bytes from the input buffer to the address + +Arguments: + +Returns: + +--*/ +{ + UINT8 *Src; + UINT8 *Dest; + UINTN Count; + EFI_STATUS Status; + UINT8 HubCommand; + UINT8 HubData; + UINTN RetryTimes; + + Status = EFI_SUCCESS; + + EnableFvbWrites (TRUE); + + // + // Grab the lock before entering critical code section + // + // bugbug + // Commented out since locking mechanisium is not correctly implemented + // on IA32 so that it will assert in runtime environment. + // + // EfiAcquireLock(&(FwhInstance->FvbDevLock)); + // + // Write data one byte at a time, don't write if the src and dest bytes match + // + Dest = (UINT8 *) WriteAddress; + Src = Buffer; + + for (Count = 0; Count < *NumBytes; Count++, Dest++, Src++) { + + HubCommand = FWH_WRITE_SETUP_COMMAND; + FvbMemWrite8 ((UINT64) ((UINTN) Dest), HubCommand); + FvbMemWrite8 ((UINT64) ((UINTN) Dest), *Src); + HubCommand = FWH_READ_STATUS_COMMAND; + FvbMemWrite8 ((UINT64) ((UINTN) Dest), HubCommand); + + // + // Device error if time out occurs + // + RetryTimes = 0; + while (RetryTimes < FVB_MAX_RETRY_TIMES) { + EfiMemRead (EfiCpuIoWidthUint8, (UINT64) ((UINTN) Dest), 0x1, &HubData); + if (HubData & FWH_WRITE_STATE_STATUS) { + break; + } + + RetryTimes++; + } + + if (RetryTimes >= FVB_MAX_RETRY_TIMES) { + *NumBytes = Count; + Status = EFI_DEVICE_ERROR; + break; + } + } + // + // Clear status register + // + HubCommand = FWH_CLEAR_STATUS_COMMAND; + FvbMemWrite8 ((UINT64) ((UINTN) Dest), HubCommand); + + // + // Issue read array command to return the FWH state machine to the + // normal operational state + // + HubCommand = FWH_READ_ARRAY_COMMAND; + FvbMemWrite8 ((UINT64) ((UINTN) WriteAddress), HubCommand); + // + // Flush the changed area to make the cache consistent + // + EfiCpuFlushCache (WriteAddress, *NumBytes); + + // + // End of critical code section, release lock. + // + // EfiReleaseLock(&(FwhInstance->FvbDevLock)); + // + EnableFvbWrites (FALSE); + + return Status; +} + +EFI_STATUS +FlashFdErase ( + IN UINTN WriteAddress, + IN UINTN Address, + IN UINTN LbaLength + ) +/*++ + +Routine Description: + Erase a certain block from address LbaWriteAddress + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + UINT8 HubCommand; + UINT8 HubData; + UINTN RetryTimes; + + Status = EFI_SUCCESS; + + EnableFvbWrites (TRUE); + + // + // Grab the lock before entering critical code section + // + // EfiAcquireLock(&(FwhInstance->FvbDevLock)); + // + // Send erase commands to FWH + // + HubCommand = FWH_BLOCK_ERASE_SETUP_COMMAND; + FvbMemWrite8 ((UINT64) WriteAddress, HubCommand); + HubCommand = FWH_BLOCK_ERASE_CONFIRM_COMMAND; + FvbMemWrite8 ((UINT64) WriteAddress, HubCommand); + HubCommand = FWH_READ_STATUS_COMMAND; + FvbMemWrite8 ((UINT64) WriteAddress, HubCommand); + + // + // Wait for completion. Indicated by FWH_WRITE_STATE_STATUS bit becoming 0 + // Device error if time out occurs + // + RetryTimes = 0; + while (RetryTimes < FVB_MAX_RETRY_TIMES) { + EfiMemRead (EfiCpuIoWidthUint8, (UINT64) WriteAddress, 0x1, &HubData); + if (HubData & FWH_WRITE_STATE_STATUS) { + break; + } + + RetryTimes++; + } + + if (RetryTimes >= FVB_MAX_RETRY_TIMES) { + Status = EFI_DEVICE_ERROR; + } + // + // Clear status register + // + HubCommand = FWH_CLEAR_STATUS_COMMAND; + FvbMemWrite8 ((UINT64) WriteAddress, HubCommand); + + // + // Issue read array command to return the FWH state machine to the normal op state + // + HubCommand = FWH_READ_ARRAY_COMMAND; + FvbMemWrite8 ((UINT64) ((UINTN) WriteAddress), HubCommand); + + EfiCpuFlushCache (Address, LbaLength); + + // + // End of critical code section, release lock. + // + // EfiReleaseLock(&(FwhInstance->FvbDevLock)); + // + EnableFvbWrites (FALSE); + + return Status; +} + +EFI_STATUS +FvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Writes specified number of bytes from the input buffer to the block + +Arguments: + Instance - The FV instance to be written to + Lba - The starting logical block index to write to + BlockOffset - Offset into the block at which to begin writing + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes actually written + Buffer - Pointer to a caller allocated buffer that contains + the source for the write + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - The firmware volume was written successfully + EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually written + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written + EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL + +--*/ +{ + EFI_FVB_ATTRIBUTES Attributes; + UINTN LbaAddress; + UINTN LbaWriteAddress; + UINTN LbaLength; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_STATUS Status; + EFI_STATUS ReturnStatus; + + // + // Find the right instance of the FVB private data + // + Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + + // + // Writes are enabled in the init routine itself + // + if (!FwhInstance->WriteEnabled) { + return EFI_ACCESS_DENIED; + } + // + // Check for invalid conditions + // + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (*NumBytes == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check if the FV is write enabled + // + FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); + + if ((Attributes & EFI_FVB_WRITE_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + // + // Perform boundary checks and adjust NumBytes + // + if (BlockOffset > LbaLength) { + return EFI_INVALID_PARAMETER; + } + + if (LbaLength < (*NumBytes + BlockOffset)) { + *NumBytes = (UINT32) (LbaLength - BlockOffset); + Status = EFI_BAD_BUFFER_SIZE; + } + + ReturnStatus = FlashFdWrite ( + LbaWriteAddress + BlockOffset, + LbaAddress, + NumBytes, + Buffer, + LbaLength + ); + if (EFI_ERROR (ReturnStatus)) { + return ReturnStatus; + } + + return Status; +} + +EFI_STATUS +FvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Erases and initializes a firmware volume block + +Arguments: + Instance - The FV instance to be erased + Lba - The logical block index to be erased + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - The erase request was successfully completed + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + + EFI_FVB_ATTRIBUTES Attributes; + UINTN LbaAddress; + UINTN LbaWriteAddress; + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN LbaLength; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + + // + // Writes are enabled in the init routine itself + // + if (!FwhInstance->WriteEnabled) { + return EFI_ACCESS_DENIED; + } + // + // Check if the FV is write enabled + // + FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); + + if ((Attributes & EFI_FVB_WRITE_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + // + // Get the starting address of the block for erase. For debug reasons, + // LbaWriteAddress may not be the same as LbaAddress. + // + Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaWriteAddress, &LbaLength, NULL, Global, Virtual); + if (EFI_ERROR (Status)) { + return Status; + } + + return FlashFdErase ( + LbaWriteAddress, + LbaAddress, + LbaLength + ); +} + +EFI_STATUS +FvbEraseCustomBlockRange ( + IN UINTN Instance, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Erases and initializes a specified range of a firmware volume + +Arguments: + Instance - The FV instance to be erased + StartLba - The starting logical block index to be erased + OffsetStartLba - Offset into the starting block at which to + begin erasing + LastLba - The last logical block index to be erased + OffsetStartLba - Offset into the last block at which to end erasing + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - The firmware volume was erased successfully + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_LBA Index; + UINTN LbaSize; + UINTN ScratchLbaSizeData; + + // + // First LBA. + // + FvbGetLbaAddress (Instance, StartLba, NULL, NULL, &LbaSize, NULL, Global, Virtual); + + // + // Use the scratch space as the intermediate buffer to transfer data + // Back up the first LBA in scratch space. + // + FvbReadBlock (Instance, StartLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual); + + // + // erase now + // + FvbEraseBlock (Instance, StartLba, Global, Virtual); + ScratchLbaSizeData = OffsetStartLba; + + // + // write the data back to the first block + // + if (ScratchLbaSizeData > 0) { + FvbWriteBlock (Instance, StartLba, 0, &ScratchLbaSizeData, Global->FvbScratchSpace[Virtual], Global, Virtual); + } + // + // Middle LBAs + // + if (LastLba > (StartLba + 1)) { + for (Index = (StartLba + 1); Index <= (LastLba - 1); Index++) { + FvbEraseBlock (Instance, Index, Global, Virtual); + } + } + // + // Last LBAs, the same as first LBAs + // + if (LastLba > StartLba) { + FvbGetLbaAddress (Instance, LastLba, NULL, NULL, &LbaSize, NULL, Global, Virtual); + FvbReadBlock (Instance, LastLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual); + FvbEraseBlock (Instance, LastLba, Global, Virtual); + } + + ScratchLbaSizeData = LbaSize - (OffsetStartLba + 1); + + return FvbWriteBlock ( + Instance, + LastLba, + (OffsetLastLba + 1), + &ScratchLbaSizeData, + Global->FvbScratchSpace[Virtual], + Global, + Virtual + ); +} + +EFI_STATUS +FvbSetVolumeAttributes ( + IN UINTN Instance, + IN OUT EFI_FVB_ATTRIBUTES *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + +Arguments: + Instance - The FV instance whose attributes is going to be + modified + Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES + containing the desired firmware volume settings. + On successful return, it contains the new settings + of the firmware volume + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - Successfully returns + EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified + EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are + in conflict with the capabilities as declared in the + firmware volume header + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FVB_ATTRIBUTES OldAttributes; + EFI_FVB_ATTRIBUTES *AttribPtr; + UINT32 Capabilities; + UINT32 OldStatus; + UINT32 NewStatus; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + + AttribPtr = (EFI_FVB_ATTRIBUTES *) &(FwhInstance->VolumeHeader.Attributes); + OldAttributes = *AttribPtr; + Capabilities = OldAttributes & EFI_FVB_CAPABILITIES; + OldStatus = OldAttributes & EFI_FVB_STATUS; + NewStatus = *Attributes & EFI_FVB_STATUS; + + // + // If firmware volume is locked, no status bit can be updated + // + if (OldAttributes & EFI_FVB_LOCK_STATUS) { + if (OldStatus ^ NewStatus) { + return EFI_ACCESS_DENIED; + } + } + // + // Test read disable + // + if ((Capabilities & EFI_FVB_READ_DISABLED_CAP) == 0) { + if ((NewStatus & EFI_FVB_READ_STATUS) == 0) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test read enable + // + if ((Capabilities & EFI_FVB_READ_ENABLED_CAP) == 0) { + if (NewStatus & EFI_FVB_READ_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test write disable + // + if ((Capabilities & EFI_FVB_WRITE_DISABLED_CAP) == 0) { + if ((NewStatus & EFI_FVB_WRITE_STATUS) == 0) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test write enable + // + if ((Capabilities & EFI_FVB_WRITE_ENABLED_CAP) == 0) { + if (NewStatus & EFI_FVB_WRITE_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test lock + // + if ((Capabilities & EFI_FVB_LOCK_CAP) == 0) { + if (NewStatus & EFI_FVB_LOCK_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB_STATUS)); + *AttribPtr = (*AttribPtr) | NewStatus; + *Attributes = *AttribPtr; + + return EFI_SUCCESS; +} +// +// FVB protocol APIs +// +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +/*++ + +Routine Description: + + Retrieves the physical address of the device. + +Arguments: + + This - Calling context + Address - Output buffer containing the address. + +Returns: + +Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ()); +} + +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +/*++ + +Routine Description: + Retrieve the size of a logical block + +Arguments: + This - Calling context + Lba - Indicates which block to return the size for. + BlockSize - A pointer to a caller allocated UINTN in which + the size of the block is returned + NumOfBlocks - a pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + +Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbGetLbaAddress ( + FvbDevice->Instance, + Lba, + NULL, + NULL, + BlockSize, + NumOfBlocks, + mFvbModuleGlobal, + EfiGoneVirtual () + ); +} + +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves Volume attributes. No polarity translations are done. + +Arguments: + This - Calling context + Attributes - output buffer which contains attributes + +Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); +} + +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Sets Volume attributes. No polarity translations are done. + +Arguments: + This - Calling context + Attributes - output buffer which contains attributes + +Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); +} + +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +/*++ + +Routine Description: + + The EraseBlock() function erases one or more blocks as denoted by the + variable argument list. The entire parameter list of blocks must be verified + prior to erasing any blocks. If a block is requested that does not exist + within the associated firmware volume (it has a larger index than the last + block of the firmware volume), the EraseBlock() function must return + EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. + +Arguments: + This - Calling context + ... - Starting LBA followed by Number of Lba to erase. + a -1 to terminate the list. + +Returns: + EFI_SUCCESS - The erase request was successfully completed + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN NumOfBlocks; + VA_LIST args; + EFI_LBA StartingLba; + UINTN NumOfLba; + EFI_STATUS Status; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ()); + ASSERT_EFI_ERROR (Status); + + NumOfBlocks = FwhInstance->NumOfBlocks; + + VA_START (args, This); + + do { + StartingLba = VA_ARG (args, EFI_LBA); + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba = VA_ARG (args, UINT32); + + // + // Check input parameters + // + if ((NumOfLba == 0) || ((StartingLba + NumOfLba) > NumOfBlocks)) { + VA_END (args); + return EFI_INVALID_PARAMETER; + } + } while (1); + + VA_END (args); + + VA_START (args, This); + do { + StartingLba = VA_ARG (args, EFI_LBA); + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba = VA_ARG (args, UINT32); + + while (NumOfLba > 0) { + Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ()); + if (EFI_ERROR (Status)) { + VA_END (args); + return Status; + } + + StartingLba++; + NumOfLba--; + } + + } while (1); + + VA_END (args); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + + Writes data beginning at Lba:Offset from FV. The write terminates either + when *NumBytes of data have been written, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + +Arguments: + This - Calling context + Lba - Block in which to begin write + Offset - Offset in the block at which to begin write + NumBytes - On input, indicates the requested write size. On + output, indicates the actual number of bytes written + Buffer - Buffer containing source data for the write. + +Returns: + EFI_SUCCESS - The firmware volume was written successfully + EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually written + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written + EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL + +--*/ +{ + + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); +} + +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + + Reads data beginning at Lba:Offset from FV. The Read terminates either + when *NumBytes of data have been read, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + +Arguments: + This - Calling context + Lba - Block in which to begin Read + Offset - Offset in the block at which to begin Read + NumBytes - On input, indicates the requested write size. On + output, indicates the actual number of bytes Read + Buffer - Buffer containing source data for the Read. + +Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes returned + in Buffer + EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be read + EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL + +--*/ +{ + + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); +} +// +// FVB Extension Protocols +// +EFI_STATUS +EFIAPI +FvbExtendProtocolEraseCustomBlockRange ( + IN EFI_FVB_EXTENSION_PROTOCOL *This, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba + ) +/*++ + +Routine Description: + Erases and initializes a specified range of a firmware volume + +Arguments: + This - Calling context + StartLba - The starting logical block index to be erased + OffsetStartLba - Offset into the starting block at which to + begin erasing + LastLba - The last logical block index to be erased + OffsetStartLba - Offset into the last block at which to end erasing + +Returns: + EFI_SUCCESS - The firmware volume was erased successfully + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_EXTEND_DEVICE_FROM_THIS (This); + + return FvbEraseCustomBlockRange ( + FvbDevice->Instance, + StartLba, + OffsetStartLba, + LastLba, + OffsetLastLba, + mFvbModuleGlobal, + EfiGoneVirtual () + ); +} + +STATIC +EFI_STATUS +ValidateFvHeader ( + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +/*++ + +Routine Description: + Check the integrity of firmware volume header + +Arguments: + FwVolHeader - A pointer to a firmware volume header + +Returns: + EFI_SUCCESS - The firmware volume is consistent + EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an FV + +--*/ +{ + UINT16 *Ptr; + UINT16 HeaderLength; + UINT16 Checksum; + + // + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number + // + if ((FwVolHeader->Revision != EFI_FVH_REVISION) || + (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || + (FwVolHeader->FvLength == ((UINTN) -1)) || + ((FwVolHeader->HeaderLength & 0x01) != 0) + ) { + return EFI_NOT_FOUND; + } + // + // Verify the header checksum + // + HeaderLength = (UINT16) (FwVolHeader->HeaderLength / 2); + Ptr = (UINT16 *) FwVolHeader; + Checksum = 0; + while (HeaderLength > 0) { + Checksum = *Ptr++; + HeaderLength--; + } + + if (Checksum != 0) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +BOOLEAN +FvbGetCfiSupported ( + IN UINTN LbaAddress + ) +/*++ + +Routine Description: + Check if the firmware volume is CFI typed flash + +Arguments: + LbaAddress - The physical address of the firmware volume + +Returns: + TRUE - CFI supported + FALSE - CFI un-supported + +--*/ +{ + UINT8 HubData[8]; + UINT8 HubCommand; + BOOLEAN Supported; + + Supported = TRUE; + + // + // Issue CFI Query (98h) to address 55h + // + HubCommand = CFI_QUERY; + FvbMemWrite8 ((LbaAddress + 0x55), HubCommand); + // + // x8 device in 8-bit mode? + // + EfiMemRead (EfiCpuIoWidthUint8, (LbaAddress + 0x10), 0x3, &HubData); + if (!EfiCompareMem (HubData, "QRY", 3)) { + goto Done; + } + // + // paired x8 devices? + // + EfiMemRead (EfiCpuIoWidthUint8, (LbaAddress + 0x20), 0x6, &HubData); + if (!EfiCompareMem (HubData, "QQRRYY", 6)) { + goto Done; + } + // + // x16 device in 16-bit mode? + // + EfiMemRead (EfiCpuIoWidthUint8, (LbaAddress + 0x20), 0x4, &HubData); + if ((!EfiCompareMem (&HubData[0], "R", 2)) && (!EfiCompareMem (&HubData[2], "Q", 2))) { + goto Done; + } + // + // x16 device in 8-bit mode? + // + EfiMemRead (EfiCpuIoWidthUint8, (LbaAddress + 0x20), 0x3, &HubData); + if (!EfiCompareMem (HubData, "QQR", 3)) { + goto Done; + } + // + // 2 x16 devices in 8-bit mode (paired chip configuration)? + // + EfiMemRead (EfiCpuIoWidthUint8, (LbaAddress + 0x40), 0x6, &HubData); + if (!EfiCompareMem (HubData, "QQQQRR", 6)) { + goto Done; + } + // + // x32 device in 8-bit mode + // + EfiMemRead (EfiCpuIoWidthUint8, (LbaAddress + 0x40), 0x5, &HubData); + if (!EfiCompareMem (HubData, "QQQQR", 5)) { + goto Done; + } + // + // x32 device in 32-bit mode + // + if ((!EfiCompareMem (&HubData[0], "R", 2)) && (((UINT16) HubData[2]) == 0) && (HubData[4] == 'Q')) { + goto Done; + } + // + // If it got to here, CFI is not supported + // + Supported = FALSE; + +Done: + // + // Bug Fix #4071: + // Issue command FWH_READ_ARRAY_COMMAND (0xff) at the end of this service to + // guarantee that the FWH is back in read mode again + // + HubCommand = FWH_READ_ARRAY_COMMAND; + FvbMemWrite8 (LbaAddress, HubCommand); + + return Supported; +} + +EFI_STATUS +GetFvbHeader ( + VOID **HobList, + EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader, + EFI_PHYSICAL_ADDRESS *BaseAddress, + BOOLEAN *WriteBack + ) +{ + EFI_STATUS Status; + VOID *Buffer; + EFI_FLASH_MAP_ENTRY_DATA *FlashMapEntry; + EFI_FLASH_SUBAREA_ENTRY *FlashMapSubEntry; + + Status = EFI_SUCCESS; + *FwVolHeader = NULL; + *WriteBack = FALSE; + + Status = GetNextGuidHob (HobList, &gEfiFlashMapHobGuid, &Buffer, NULL); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + FlashMapEntry = (EFI_FLASH_MAP_ENTRY_DATA *) Buffer; + FlashMapSubEntry = &FlashMapEntry->Entries[0]; + // + // Check if it is a "FVB" area + // + if (!EfiCompareGuid (&FlashMapSubEntry->FileSystem, &gEfiFirmwareVolumeBlockProtocolGuid)) { + return Status; + } + // + // Check if it is a "real" flash + // + if (FlashMapSubEntry->Attributes != (EFI_FLASH_AREA_FV | EFI_FLASH_AREA_MEMMAPPED_FV)) { + return Status; + } + + *BaseAddress = FlashMapSubEntry->Base; + DEBUG ((EFI_D_ERROR, "FlashMap HOB: BaseAddress = 0x%lx\n", *BaseAddress)); + + *FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) (*BaseAddress); + Status = ValidateFvHeader (*FwVolHeader); + if (EFI_ERROR (Status)) { + // + // Get FvbInfo + // + *WriteBack = TRUE; + DEBUG ((EFI_D_ERROR, "BaseAddress = 0x%lx\n", BaseAddress)); + Status = GetFvbInfo (*BaseAddress, FwVolHeader); + DEBUG ((EFI_D_ERROR, "Fvb: FV header invalid, GetFvbInfo - %r\n", Status)); + ASSERT_EFI_ERROR (Status); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This function does common initialization for FVB services + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + VOID *HobList; + VOID *FirmwareVolumeHobList; + UINT32 BufferSize; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + UINTN LbaAddress; + UINT8 Data; + UINTN BlockIndex2; + BOOLEAN WriteEnabled; + BOOLEAN WriteLocked; + EFI_HANDLE FwbHandle; + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; + EFI_DEVICE_PATH_PROTOCOL *TempFwbDevicePath; + FV_DEVICE_PATH TempFvbDevicePathData; + UINT32 MaxLbaSize; + BOOLEAN CfiEnabled; + EFI_PHYSICAL_ADDRESS BaseAddress; + BOOLEAN WriteBack; + UINTN NumOfBlocks; + UINTN HeaderLength; + + INITIALIZE_SCRIPT (ImageHandle, SystemTable); + + EfiInitializeRuntimeDriverLib (ImageHandle, SystemTable, FvbVirtualddressChangeEvent); + + Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &HobList); + HeaderLength = 0; + // + // No FV HOBs found + // + ASSERT_EFI_ERROR (Status); + + // + // Allocate runtime services data for global variable, which contains + // the private data of all firmware volume block instances + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (ESAL_FWB_GLOBAL), + &mFvbModuleGlobal + ); + ASSERT_EFI_ERROR (Status); + + EnablePlatformFvb (); + EnableFvbWrites (TRUE); + + // + // Calculate the total size for all firmware volume block instances + // + BufferSize = 0; + FirmwareVolumeHobList = HobList; + do { + Status = GetFvbHeader (&FirmwareVolumeHobList, &FwVolHeader, &BaseAddress, &WriteBack); + if (EFI_ERROR (Status)) { + break; + } + + if (FwVolHeader) { + BufferSize += (FwVolHeader->HeaderLength + sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + } + } while (TRUE); + + // + // Only need to allocate once. There is only one copy of physical memory for + // the private data of each FV instance. But in virtual mode or in physical + // mode, the address of the the physical memory may be different. + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + BufferSize, + &mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] + ); + ASSERT_EFI_ERROR (Status); + + // + // Make a virtual copy of the FvInstance pointer. + // + FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; + mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance; + + mFvbModuleGlobal->NumFv = 0; + FirmwareVolumeHobList = HobList; + + MaxLbaSize = 0; + + // + // Fill in the private data of each firmware volume block instance + // + do { + Status = GetFvbHeader (&FirmwareVolumeHobList, &FwVolHeader, &BaseAddress, &WriteBack); + if (EFI_ERROR (Status)) { + break; + } + + if (!FwVolHeader) { + continue; + } + + EfiCopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength); + FwVolHeader = &(FwhInstance->VolumeHeader); + + FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress; + FwhInstance->FvBase[FVB_VIRTUAL] = (UINTN) BaseAddress; + + // + // FwhInstance->FvWriteBase may not be the same as FwhInstance->FvBase + // + PlatformGetFvbWriteBase ( + (UINTN) BaseAddress, + (UINTN *) &(FwhInstance->FvWriteBase[FVB_PHYSICAL]), + &WriteEnabled + ); + // + // Every pointer should have a virtual copy. + // + FwhInstance->FvWriteBase[FVB_VIRTUAL] = FwhInstance->FvWriteBase[FVB_PHYSICAL]; + + FwhInstance->WriteEnabled = WriteEnabled; + EfiInitializeLock (&(FwhInstance->FvbDevLock), EFI_TPL_HIGH_LEVEL); + + LbaAddress = (UINTN) FwhInstance->FvWriteBase[0]; + NumOfBlocks = 0; + WriteLocked = FALSE; + + if (WriteEnabled) { + CfiEnabled = FvbGetCfiSupported (LbaAddress); + for (PtrBlockMapEntry = FwVolHeader->FvBlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { + + for (BlockIndex2 = 0; BlockIndex2 < PtrBlockMapEntry->NumBlocks; BlockIndex2++) { + + if (SetPlatformFvbLock (LbaAddress)) { + // + // Clear all write-lock and read-lock HW bits + // For sync3, the software will enforce the protection + // + if (CfiEnabled) { + Data = CFI_BLOCK_LOCK_UNLOCK; + FvbMemWrite8 (LbaAddress, Data); + Data = CFI_BLOCK_UNLOCK_CONFIRM; + FvbMemWrite8 (LbaAddress, Data); + while (TRUE) { + EfiMemRead (EfiCpuIoWidthUint8, (LbaAddress + 2), 1, &Data); + if (Data & 0x80) { + break; + } + } + + Data = FWH_READ_ARRAY_COMMAND; + FvbMemWrite8 (LbaAddress, Data); + } else { + EfiMemRead (EfiCpuIoWidthUint8, (LbaAddress - 0x400000 + 2), 0x1, &Data); + // + // bugbug: lock down is block based, not FV based. Here we assume that + // the FV is locked if one of its block is locked + // + if ((Data & FWH_WRITE_LOCK) && (Data & FWH_LOCK_DOWN)) { + // + // the flash is locked and locked down + // + WriteLocked = TRUE; + } else { + Data &= ~(FWH_WRITE_LOCK | FWH_READ_LOCK | FWH_LOCK_DOWN); + + // + // Save boot script for S3 resume + // + SCRIPT_MEM_WRITE ( + EFI_ACPI_S3_RESUME_SCRIPT_TABLE, + EfiBootScriptWidthUint8, + (UINT64) (LbaAddress - 0x400000 + 2), + 1, + &Data + ); + + FvbMemWrite8 ((LbaAddress - 0x400000 + 2), Data); + } + } + } + + LbaAddress += PtrBlockMapEntry->BlockLength; + } + // + // Get the maximum size of a block. The size will be used to allocate + // buffer for Scratch space, the intermediate buffer for FVB extension + // protocol + // + if (MaxLbaSize < PtrBlockMapEntry->BlockLength) { + MaxLbaSize = PtrBlockMapEntry->BlockLength; + } + + NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks; + } + // + // Write back a healthy FV header + // + if (WriteBack && (!WriteLocked)) { + Status = FlashFdErase ( + (UINTN) FwhInstance->FvWriteBase[0], + (UINTN) BaseAddress, + FwVolHeader->FvBlockMap->BlockLength + ); + + HeaderLength = (UINTN) FwVolHeader->HeaderLength; + Status = FlashFdWrite ( + (UINTN) FwhInstance->FvWriteBase[0], + (UINTN) BaseAddress, + (UINTN *) &HeaderLength, + (UINT8 *) FwVolHeader, + FwVolHeader->FvBlockMap->BlockLength + ); + + FwVolHeader->HeaderLength = (UINT16) HeaderLength; + DEBUG ((EFI_D_ERROR, "Fvb: FV header invalid, write back - %r\n", Status)); + } + } + // + // The total number of blocks in the FV. + // + FwhInstance->NumOfBlocks = NumOfBlocks; + + // + // If the FV is write locked, set the appropriate attributes + // + if (WriteLocked) { + // + // write disabled + // + FwhInstance->VolumeHeader.Attributes &= ~EFI_FVB_WRITE_STATUS; + // + // lock enabled + // + FwhInstance->VolumeHeader.Attributes |= EFI_FVB_LOCK_STATUS; + } + // + // Add a FVB Protocol Instance + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (EFI_FW_VOL_BLOCK_DEVICE), + &FvbDevice + ); + ASSERT_EFI_ERROR (Status); + + EfiCopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE)); + + FvbDevice->Instance = mFvbModuleGlobal->NumFv; + mFvbModuleGlobal->NumFv++; + + // + // Set up the devicepath + // + FvbDevice->DevicePath.MemMapDevPath.StartingAddress = BaseAddress; + FvbDevice->DevicePath.MemMapDevPath.EndingAddress = BaseAddress + (FwVolHeader->FvLength - 1); + + // + // Find a handle with a matching device path that has supports FW Block protocol + // + TempFwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &TempFvbDevicePathData; + EfiCopyMem (TempFwbDevicePath, &FvbDevice->DevicePath, sizeof (FV_DEVICE_PATH)); + Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle); + if (EFI_ERROR (Status)) { + // + // LocateDevicePath fails so install a new interface and device path + // + FwbHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->FwVolBlockInstance, + &gEfiDevicePathProtocolGuid, + &FvbDevice->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else if (EfiIsDevicePathEnd (TempFwbDevicePath)) { + // + // Device allready exists, so reinstall the FVB protocol + // + Status = gBS->HandleProtocol ( + FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + &OldFwbInterface + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->ReinstallProtocolInterface ( + FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + OldFwbInterface, + &FvbDevice->FwVolBlockInstance + ); + ASSERT_EFI_ERROR (Status); + + } else { + // + // There was a FVB protocol on an End Device Path node + // + ASSERT (FALSE); + } + // + // Install FVB Extension Protocol on the same handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &FwbHandle, + &gEfiFvbExtensionProtocolGuid, + &FvbDevice->FvbExtension, + &gEfiAlternateFvBlockGuid, + NULL, + NULL + ); + + ASSERT_EFI_ERROR (Status); + + FwhInstance = (EFI_FW_VOL_INSTANCE *) + ( + (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) + ); + } while (TRUE); + + // + // Allocate for scratch space, an intermediate buffer for FVB extention + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + MaxLbaSize, + &mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL] + ); + ASSERT_EFI_ERROR (Status); + + mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL] = mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]; + + FvbSpecificInitialize (mFvbModuleGlobal); + + return EnableFvbWrites (FALSE); +} diff --git a/EdkNt32Pkg/RuntimeDxe/FvbServices/Common/FwBlockService.h b/EdkNt32Pkg/RuntimeDxe/FvbServices/Common/FwBlockService.h new file mode 100644 index 0000000000..1fad9bd6ba --- /dev/null +++ b/EdkNt32Pkg/RuntimeDxe/FvbServices/Common/FwBlockService.h @@ -0,0 +1,324 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FwBlockService.h + +Abstract: + + Firmware volume block driver for Intel Firmware Hub (FWH) device + +--*/ + +#ifndef _FW_BLOCK_SERVICE_H +#define _FW_BLOCK_SERVICE_H + +// +// Statements that include other header files +// +#include "Tiano.h" +#include "EfiFirmwareVolumeHeader.h" +#include "EfiRuntimeLib.h" +#include "EfiHobLib.h" +#include "EfiScriptLib.h" + +#include EFI_PROTOCOL_PRODUCER (FirmwareVolumeBlock) +#include EFI_PROTOCOL_PRODUCER (FvbExtension) +#include EFI_GUID_DEFINITION (AlternateFvBlock) +#include EFI_GUID_DEFINITION (Hob) +#include EFI_GUID_DEFINITION (DxeServices) +#include EFI_PROTOCOL_CONSUMER (CpuIo) + +#define FVB_MAX_RETRY_TIMES 10000000 +#define FWH_BLOCK_ERASE_SETUP_COMMAND 0x20 +#define FWH_BLOCK_ERASE_CONFIRM_COMMAND 0xd0 +#define FWH_READ_STATUS_COMMAND 0x70 +#define FWH_CLEAR_STATUS_COMMAND 0x50 +#define FWH_READ_ARRAY_COMMAND 0xff +#define FWH_WRITE_SETUP_COMMAND 0x40 +#define FWH_OPEN_FEATURE_SPACE_COMMAND 0x91 +#define FWH_READ_LOCK (1 << 2) +#define FWH_WRITE_LOCK (1 << 1) +#define FWH_LOCK_DOWN 1 +#define FWH_WRITE_STATE_STATUS (1 << 7) +#define FWH_ERASE_STATUS (1 << 5) +#define FWH_PROGRAM_STATUS (1 << 4) +#define FWH_VPP_STATUS (1 << 3) +#define STALL_TIME 5 +#define FWH_ERASE_STATUS_BITS (FWH_ERASE_STATUS || FWH_VPP_STATUS) +#define FWH_WRITE_STATUS_BITS (FWH_WRITE_STATUS || FWH_VPP_STATUS) +#define CFI_BLOCK_LOCK_UNLOCK 0x60 +#define CFI_BLOCK_LOCK_CONFIRM 1 +#define CFI_BLOCK_UNLOCK_CONFIRM 0xD0 +#define CFI_QUERY 0x98 + +// +// BugBug: Add documentation here for data structure!!!! +// +#define FVB_PHYSICAL 0 +#define FVB_VIRTUAL 1 + +typedef struct { + EFI_LOCK FvbDevLock; + UINTN FvBase[2]; + UINTN FvWriteBase[2]; + UINTN NumOfBlocks; + BOOLEAN WriteEnabled; + EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; +} EFI_FW_VOL_INSTANCE; + +typedef struct { + UINT32 NumFv; + EFI_FW_VOL_INSTANCE *FvInstance[2]; + UINT8 *FvbScratchSpace[2]; +} ESAL_FWB_GLOBAL; + +// +// Fvb Protocol instance data +// +#define FVB_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE) +#define FVB_EXTEND_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, FvbExtension, FVB_DEVICE_SIGNATURE) +#define FVB_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('F', 'V', 'B', 'C') + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_DEVICE_PATH; + +typedef struct { + UINTN Signature; + FV_DEVICE_PATH DevicePath; + UINTN Instance; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance; + EFI_FVB_EXTENSION_PROTOCOL FvbExtension; +} EFI_FW_VOL_BLOCK_DEVICE; + +EFI_STATUS +GetFvbInfo ( + IN EFI_PHYSICAL_ADDRESS FvBaseAddress, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ) +; + +EFI_STATUS +EnableFvbWrites ( + IN BOOLEAN EnableWrites + ) +; + +EFI_STATUS +PlatformGetFvbWriteBase ( + IN UINTN CurrentBaseAddress, + IN UINTN *NewBaseAddress, + IN BOOLEAN *WriteEnabled + ) +; + +EFI_STATUS +EnablePlatformFvb ( + VOID + ) +; + +BOOLEAN +SetPlatformFvbLock ( + IN UINTN LbaAddress + ) +; + +EFI_STATUS +FvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbSetVolumeAttributes ( + IN UINTN Instance, + IN OUT EFI_FVB_ATTRIBUTES *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *Address, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + + +VOID +EFIAPI +FvbClassAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +EFI_STATUS +FvbSpecificInitialize ( + IN ESAL_FWB_GLOBAL *mFvbModuleGlobal + ) +; + +EFI_STATUS +FvbGetLbaAddress ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaWriteAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbEraseCustomBlockRange ( + IN UINTN Instance, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +// +// Protocol APIs +// +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES *Attributes + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +; + +EFI_STATUS +EFIAPI +FvbExtendProtocolEraseCustomBlockRange ( + IN EFI_FVB_EXTENSION_PROTOCOL *This, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba + ) +; + +#endif diff --git a/EdkNt32Pkg/RuntimeDxe/FvbServices/Common/ia32/Ia32Fwh.c b/EdkNt32Pkg/RuntimeDxe/FvbServices/Common/ia32/Ia32Fwh.c new file mode 100644 index 0000000000..00998f8c67 --- /dev/null +++ b/EdkNt32Pkg/RuntimeDxe/FvbServices/Common/ia32/Ia32Fwh.c @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Ia32Fwh.c + +Abstract: + +Revision History + +--*/ + +#include "FWBlockService.h" + +EFI_STATUS +FvbSpecificInitialize ( + IN ESAL_FWB_GLOBAL *mFvbModuleGlobal + ) +/*++ + +Routine Description: + Additional initialize code for IA32 platform. + +Arguments: + ESAL_FWB_GLOBAL - Global pointer that points to the instance data + +Returns: + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/RuntimeDxe/FvbServices/Nt32Fwh.dxs b/EdkNt32Pkg/RuntimeDxe/FvbServices/Nt32Fwh.dxs new file mode 100644 index 0000000000..3cb311228e --- /dev/null +++ b/EdkNt32Pkg/RuntimeDxe/FvbServices/Nt32Fwh.dxs @@ -0,0 +1,27 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + Nt32Fwh.dxs + +Abstract: + + Dependency expression source file. + +--*/ +#include +#include + + +DEPENDENCY_START + TRUE +DEPENDENCY_END \ No newline at end of file diff --git a/EdkNt32Pkg/RuntimeDxe/FvbServices/Nt32Fwh.mbd b/EdkNt32Pkg/RuntimeDxe/FvbServices/Nt32Fwh.mbd new file mode 100644 index 0000000000..7f83760ff2 --- /dev/null +++ b/EdkNt32Pkg/RuntimeDxe/FvbServices/Nt32Fwh.mbd @@ -0,0 +1,47 @@ + + + + + FwBlockService + BDFE5FAA-2A35-44bb-B17A-8084D4E2B9E9 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + BaseLib + BaseMemoryLib + UefiLib + UefiDriverEntryPoint + DxeReportStatusCodeLib + DxeServicesTableLib + BaseDebugLibNull + EdkDxePrintLib + EdkDxeRuntimeDriverLib + DxeHobLib + DxeMemoryAllocationLib + + + _ModuleEntryPoint + + diff --git a/EdkNt32Pkg/RuntimeDxe/FvbServices/Nt32Fwh.msa b/EdkNt32Pkg/RuntimeDxe/FvbServices/Nt32Fwh.msa new file mode 100644 index 0000000000..711e4e4874 --- /dev/null +++ b/EdkNt32Pkg/RuntimeDxe/FvbServices/Nt32Fwh.msa @@ -0,0 +1,89 @@ + + + + + FwBlockService + DXE_RUNTIME_DRIVER + RT_DRIVER + BDFE5FAA-2A35-44bb-B17A-8084D4E2B9E9 + 0 + Component description file for DiskIo module. + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + UefiLib + UefiDriverEntryPoint + BaseLib + DxeServicesTableLib + DxeRuntimeDriverLib + DebugLib + HobLib + BaseMemoryLib + MemoryAllocationLib + UefiBootServicesTableLib + + + Nt32Fwh.dxs + + nt32\FwBlockService.c + nt32\FwBlockService.h + nt32\FvbInfo.c + + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + DevicePath + FirmwareVolumeBlock + FvbExtension + + + + + gEfiEventVirtualAddressChangeGuid + 0x13fa7698, 0xc831, 0x49c7, 0x87, 0xea, 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96 + + + + + + + + + AlternateFvBlock + + + + + FvbInitialize + + + + + + + diff --git a/EdkNt32Pkg/RuntimeDxe/FvbServices/build.xml b/EdkNt32Pkg/RuntimeDxe/FvbServices/build.xml new file mode 100644 index 0000000000..60d06c448b --- /dev/null +++ b/EdkNt32Pkg/RuntimeDxe/FvbServices/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/RuntimeDxe/FvbServices/nt32/FWBlockService.c b/EdkNt32Pkg/RuntimeDxe/FvbServices/nt32/FWBlockService.c new file mode 100644 index 0000000000..1f2f8fd2b4 --- /dev/null +++ b/EdkNt32Pkg/RuntimeDxe/FvbServices/nt32/FWBlockService.c @@ -0,0 +1,1493 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FWBlockService.c + +Abstract: + +Revision History + +--*/ + +#include "FWBlockService.h" + +ESAL_FWB_GLOBAL *mFvbModuleGlobal; + +EFI_FW_VOL_BLOCK_DEVICE mFvbDeviceTemplate = { + FVB_DEVICE_SIGNATURE, + { + { + { + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + { + sizeof (MEMMAP_DEVICE_PATH), + 0 + } + }, + EfiMemoryMappedIO, + 0, + 0, + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + sizeof (EFI_DEVICE_PATH_PROTOCOL), + 0 + } + } + }, + 0, + { + FvbProtocolGetAttributes, + FvbProtocolSetAttributes, + FvbProtocolGetPhysicalAddress, + FvbProtocolGetBlockSize, + FvbProtocolRead, + FvbProtocolWrite, + FvbProtocolEraseBlocks, + NULL + }, + { + FvbExtendProtocolEraseCustomBlockRange + } +}; + + + +VOID +EFIAPI +FvbVirtualddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +/*++ + +Routine Description: + + Fixup internal data so that EFI and SAL can be call in virtual mode. + Call the passed in Child Notify event and convert the mFvbModuleGlobal + date items to there virtual address. + + mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] - Physical copy of instance data + mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] - Virtual pointer to common + instance data. + +Arguments: + + (Standard EFI notify event - EFI_EVENT_NOTIFY) + +Returns: + + None + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN Index; + + EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal->FvInstance[FVB_VIRTUAL]); + + // + // Convert the base address of all the instances + // + Index = 0; + FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; + while (Index < mFvbModuleGlobal->NumFv) { + EfiConvertPointer (0x0, (VOID **) &FwhInstance->FvBase[FVB_VIRTUAL]); + FwhInstance = (EFI_FW_VOL_INSTANCE *) + ( + (UINTN) ((UINT8 *) FwhInstance) + FwhInstance->VolumeHeader.HeaderLength + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) + ); + Index++; + } + + EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL]); + EfiConvertPointer (0x0, (VOID **) &mFvbModuleGlobal); +} + +EFI_STATUS +GetFvbInstance ( + IN UINTN Instance, + IN ESAL_FWB_GLOBAL *Global, + OUT EFI_FW_VOL_INSTANCE **FwhInstance, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Retrieves the physical address of a memory mapped FV + +Arguments: + Instance - The FV instance whose base address is going to be + returned + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + FwhInstance - The EFI_FW_VOL_INSTANCE fimrware instance structure + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhRecord; + + if (Instance >= Global->NumFv) { + return EFI_INVALID_PARAMETER; + } + // + // Find the right instance of the FVB private data + // + FwhRecord = Global->FvInstance[Virtual]; + while (Instance > 0) { + FwhRecord = (EFI_FW_VOL_INSTANCE *) + ( + (UINTN) ((UINT8 *) FwhRecord) + FwhRecord->VolumeHeader.HeaderLength + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) + ); + Instance--; + } + + *FwhInstance = FwhRecord; + + return EFI_SUCCESS; +} + +EFI_STATUS +FvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *Address, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Retrieves the physical address of a memory mapped FV + +Arguments: + Instance - The FV instance whose base address is going to be + returned + Address - Pointer to a caller allocated EFI_PHYSICAL_ADDRESS + that on successful return, contains the base address + of the firmware volume. + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + *Address = FwhInstance->FvBase[Virtual]; + + return EFI_SUCCESS; +} + +EFI_STATUS +FvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + +Arguments: + Instance - The FV instance whose attributes is going to be + returned + Attributes - Output buffer which contains attributes + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + *Attributes = FwhInstance->VolumeHeader.Attributes; + + return EFI_SUCCESS; +} + +EFI_STATUS +FvbGetLbaAddress ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Retrieves the starting address of an LBA in an FV + +Arguments: + Instance - The FV instance which the Lba belongs to + Lba - The logical block address + LbaAddress - On output, contains the physical starting address + of the Lba + LbaLength - On output, contains the length of the block + NumOfBlocks - A pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - Successfully returns + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + UINT32 NumBlocks; + UINT32 BlockLength; + UINTN Offset; + EFI_LBA StartLba; + EFI_LBA NextLba; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FV_BLOCK_MAP_ENTRY *BlockMap; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + + StartLba = 0; + Offset = 0; + BlockMap = &(FwhInstance->VolumeHeader.FvBlockMap[0]); + + // + // Parse the blockmap of the FV to find which map entry the Lba belongs to + // + while (TRUE) { + NumBlocks = BlockMap->NumBlocks; + BlockLength = BlockMap->BlockLength; + + if (NumBlocks == 0 || BlockLength == 0) { + return EFI_INVALID_PARAMETER; + } + + NextLba = StartLba + NumBlocks; + + // + // The map entry found + // + if (Lba >= StartLba && Lba < NextLba) { + Offset = Offset + (UINTN) MultU64x32 ((Lba - StartLba), BlockLength); + if (LbaAddress != NULL) { + *LbaAddress = FwhInstance->FvBase[Virtual] + Offset; + } + + if (LbaLength != NULL) { + *LbaLength = BlockLength; + } + + if (NumOfBlocks != NULL) { + *NumOfBlocks = (UINTN) (NextLba - Lba); + } + + return EFI_SUCCESS; + } + + StartLba = NextLba; + Offset = Offset + NumBlocks * BlockLength; + BlockMap++; + } +} + +EFI_STATUS +FvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Reads specified number of bytes into a buffer from the specified block + +Arguments: + Instance - The FV instance to be read from + Lba - The logical block address to be read from + BlockOffset - Offset into the block at which to begin reading + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes read + Buffer - Pointer to a caller allocated buffer that will be + used to hold the data read + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes returned + in Buffer + EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be read + EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL + +--*/ +{ + EFI_FVB_ATTRIBUTES Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + + // + // Check for invalid conditions + // + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (*NumBytes == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check if the FV is read enabled + // + FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); + + if ((Attributes & EFI_FVB_READ_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + // + // Perform boundary checks and adjust NumBytes + // + if (BlockOffset > LbaLength) { + return EFI_INVALID_PARAMETER; + } + + if (LbaLength < (*NumBytes + BlockOffset)) { + *NumBytes = (UINT32) (LbaLength - BlockOffset); + Status = EFI_BAD_BUFFER_SIZE; + } + + CopyMem (Buffer, (UINT8 *) (LbaAddress + BlockOffset), (UINTN) (*NumBytes)); + + return Status; +} + +EFI_STATUS +FvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Writes specified number of bytes from the input buffer to the block + +Arguments: + Instance - The FV instance to be written to + Lba - The starting logical block index to write to + BlockOffset - Offset into the block at which to begin writing + NumBytes - Pointer that on input contains the total size of + the buffer. On output, it contains the total number + of bytes actually written + Buffer - Pointer to a caller allocated buffer that contains + the source for the write + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - The firmware volume was written successfully + EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually written + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written + EFI_INVALID_PARAMETER - Instance not found, or NumBytes, Buffer are NULL + +--*/ +{ + EFI_FVB_ATTRIBUTES Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + + // + // Check for invalid conditions + // + if ((NumBytes == NULL) || (Buffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (*NumBytes == 0) { + return EFI_INVALID_PARAMETER; + } + + Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Check if the FV is write enabled + // + FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); + + if ((Attributes & EFI_FVB_WRITE_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + // + // Perform boundary checks and adjust NumBytes + // + if (BlockOffset > LbaLength) { + return EFI_INVALID_PARAMETER; + } + + if (LbaLength < (*NumBytes + BlockOffset)) { + *NumBytes = (UINT32) (LbaLength - BlockOffset); + Status = EFI_BAD_BUFFER_SIZE; + } + // + // Write data + // + CopyMem ((UINT8 *) (LbaAddress + BlockOffset), Buffer, (UINTN) (*NumBytes)); + + return Status; +} + +EFI_STATUS +FvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Erases and initializes a firmware volume block + +Arguments: + Instance - The FV instance to be erased + Lba - The logical block index to be erased + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - The erase request was successfully completed + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + + EFI_FVB_ATTRIBUTES Attributes; + UINTN LbaAddress; + UINTN LbaLength; + EFI_STATUS Status; + UINT8 Data; + + // + // Check if the FV is write enabled + // + FvbGetVolumeAttributes (Instance, &Attributes, Global, Virtual); + + if ((Attributes & EFI_FVB_WRITE_STATUS) == 0) { + return EFI_ACCESS_DENIED; + } + // + // Get the starting address of the block for erase. + // + Status = FvbGetLbaAddress (Instance, Lba, &LbaAddress, &LbaLength, NULL, Global, Virtual); + + if (EFI_ERROR (Status)) { + return Status; + } + + if ((Attributes & EFI_FVB_ERASE_POLARITY) != 0) { + Data = 0xFF; + } else { + Data = 0x0; + } + + SetMem ((UINT8 *) LbaAddress, LbaLength, Data); + + return EFI_SUCCESS; +} + +EFI_STATUS +FvbEraseCustomBlockRange ( + IN UINTN Instance, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Erases and initializes a specified range of a firmware volume + +Arguments: + Instance - The FV instance to be erased + StartLba - The starting logical block index to be erased + OffsetStartLba - Offset into the starting block at which to + begin erasing + LastLba - The last logical block index to be erased + OffsetStartLba - Offset into the last block at which to end erasing + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - The firmware volume was erased successfully + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + EFI_INVALID_PARAMETER - Instance not found + +--*/ +{ + EFI_LBA Index; + UINTN LbaSize; + UINTN ScratchLbaSizeData; + + // + // First LBA + // + FvbGetLbaAddress (Instance, StartLba, NULL, &LbaSize, NULL, Global, Virtual); + + // + // Use the scratch space as the intermediate buffer to transfer data + // Back up the first LBA in scratch space. + // + FvbReadBlock (Instance, StartLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual); + + // + // erase now + // + FvbEraseBlock (Instance, StartLba, Global, Virtual); + ScratchLbaSizeData = OffsetStartLba; + + // + // write the data back to the first block + // + if (ScratchLbaSizeData > 0) { + FvbWriteBlock (Instance, StartLba, 0, &ScratchLbaSizeData, Global->FvbScratchSpace[Virtual], Global, Virtual); + } + // + // Middle LBAs + // + if (LastLba > (StartLba + 1)) { + for (Index = (StartLba + 1); Index <= (LastLba - 1); Index++) { + FvbEraseBlock (Instance, Index, Global, Virtual); + } + } + // + // Last LBAs, the same as first LBAs + // + if (LastLba > StartLba) { + FvbGetLbaAddress (Instance, LastLba, NULL, &LbaSize, NULL, Global, Virtual); + FvbReadBlock (Instance, LastLba, 0, &LbaSize, Global->FvbScratchSpace[Virtual], Global, Virtual); + FvbEraseBlock (Instance, LastLba, Global, Virtual); + } + + ScratchLbaSizeData = LbaSize - (OffsetStartLba + 1); + + return FvbWriteBlock ( + Instance, + LastLba, + (OffsetLastLba + 1), + &ScratchLbaSizeData, + Global->FvbScratchSpace[Virtual], + Global, + Virtual + ); +} + +EFI_STATUS +FvbSetVolumeAttributes ( + IN UINTN Instance, + IN OUT EFI_FVB_ATTRIBUTES *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +/*++ + +Routine Description: + Modifies the current settings of the firmware volume according to the + input parameter, and returns the new setting of the volume + +Arguments: + Instance - The FV instance whose attributes is going to be + modified + Attributes - On input, it is a pointer to EFI_FVB_ATTRIBUTES + containing the desired firmware volume settings. + On successful return, it contains the new settings + of the firmware volume + Global - Pointer to ESAL_FWB_GLOBAL that contains all + instance data + Virtual - Whether CPU is in virtual or physical mode + +Returns: + EFI_SUCCESS - Successfully returns + EFI_ACCESS_DENIED - The volume setting is locked and cannot be modified + EFI_INVALID_PARAMETER - Instance not found, or The attributes requested are + in conflict with the capabilities as declared in the + firmware volume header + +--*/ +{ + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FVB_ATTRIBUTES OldAttributes; + EFI_FVB_ATTRIBUTES *AttribPtr; + UINT32 Capabilities; + UINT32 OldStatus; + UINT32 NewStatus; + EFI_STATUS Status; + + // + // Find the right instance of the FVB private data + // + Status = GetFvbInstance (Instance, Global, &FwhInstance, Virtual); + ASSERT_EFI_ERROR (Status); + + AttribPtr = (EFI_FVB_ATTRIBUTES *) &(FwhInstance->VolumeHeader.Attributes); + OldAttributes = *AttribPtr; + Capabilities = OldAttributes & EFI_FVB_CAPABILITIES; + OldStatus = OldAttributes & EFI_FVB_STATUS; + NewStatus = *Attributes & EFI_FVB_STATUS; + + // + // If firmware volume is locked, no status bit can be updated + // + if (OldAttributes & EFI_FVB_LOCK_STATUS) { + if (OldStatus ^ NewStatus) { + return EFI_ACCESS_DENIED; + } + } + // + // Test read disable + // + if ((Capabilities & EFI_FVB_READ_DISABLED_CAP) == 0) { + if ((NewStatus & EFI_FVB_READ_STATUS) == 0) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test read enable + // + if ((Capabilities & EFI_FVB_READ_ENABLED_CAP) == 0) { + if (NewStatus & EFI_FVB_READ_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test write disable + // + if ((Capabilities & EFI_FVB_WRITE_DISABLED_CAP) == 0) { + if ((NewStatus & EFI_FVB_WRITE_STATUS) == 0) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test write enable + // + if ((Capabilities & EFI_FVB_WRITE_ENABLED_CAP) == 0) { + if (NewStatus & EFI_FVB_WRITE_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + // + // Test lock + // + if ((Capabilities & EFI_FVB_LOCK_CAP) == 0) { + if (NewStatus & EFI_FVB_LOCK_STATUS) { + return EFI_INVALID_PARAMETER; + } + } + + *AttribPtr = (*AttribPtr) & (0xFFFFFFFF & (~EFI_FVB_STATUS)); + *AttribPtr = (*AttribPtr) | NewStatus; + *Attributes = *AttribPtr; + + return EFI_SUCCESS; +} +// +// FVB protocol APIs +// +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +/*++ + +Routine Description: + + Retrieves the physical address of the device. + +Arguments: + + This - Calling context + Address - Output buffer containing the address. + +Returns: + +Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbGetPhysicalAddress (FvbDevice->Instance, Address, mFvbModuleGlobal, EfiGoneVirtual ()); +} + +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +/*++ + +Routine Description: + Retrieve the size of a logical block + +Arguments: + This - Calling context + Lba - Indicates which block to return the size for. + BlockSize - A pointer to a caller allocated UINTN in which + the size of the block is returned + NumOfBlocks - a pointer to a caller allocated UINTN in which the + number of consecutive blocks starting with Lba is + returned. All blocks in this range have a size of + BlockSize + +Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbGetLbaAddress ( + FvbDevice->Instance, + Lba, + NULL, + BlockSize, + NumOfBlocks, + mFvbModuleGlobal, + EfiGoneVirtual () + ); +} + +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Retrieves Volume attributes. No polarity translations are done. + +Arguments: + This - Calling context + Attributes - output buffer which contains attributes + +Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbGetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); +} + +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES *Attributes + ) +/*++ + +Routine Description: + Sets Volume attributes. No polarity translations are done. + +Arguments: + This - Calling context + Attributes - output buffer which contains attributes + +Returns: + EFI_SUCCESS - Successfully returns + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbSetVolumeAttributes (FvbDevice->Instance, Attributes, mFvbModuleGlobal, EfiGoneVirtual ()); +} + +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +/*++ + +Routine Description: + + The EraseBlock() function erases one or more blocks as denoted by the + variable argument list. The entire parameter list of blocks must be verified + prior to erasing any blocks. If a block is requested that does not exist + within the associated firmware volume (it has a larger index than the last + block of the firmware volume), the EraseBlock() function must return + EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. + +Arguments: + This - Calling context + ... - Starting LBA followed by Number of Lba to erase. + a -1 to terminate the list. + +Returns: + EFI_SUCCESS - The erase request was successfully completed + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FW_VOL_INSTANCE *FwhInstance; + UINTN NumOfBlocks; + VA_LIST args; + EFI_LBA StartingLba; + UINTN NumOfLba; + EFI_STATUS Status; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + Status = GetFvbInstance (FvbDevice->Instance, mFvbModuleGlobal, &FwhInstance, EfiGoneVirtual ()); + ASSERT_EFI_ERROR (Status); + + NumOfBlocks = FwhInstance->NumOfBlocks; + + VA_START (args, This); + + do { + StartingLba = VA_ARG (args, EFI_LBA); + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba = VA_ARG (args, UINT32); + + // + // Check input parameters + // + if (NumOfLba == 0) { + VA_END (args); + return EFI_INVALID_PARAMETER; + } + + if ((StartingLba + NumOfLba) > NumOfBlocks) { + return EFI_INVALID_PARAMETER; + } + } while (1); + + VA_END (args); + + VA_START (args, This); + do { + StartingLba = VA_ARG (args, EFI_LBA); + if (StartingLba == EFI_LBA_LIST_TERMINATOR) { + break; + } + + NumOfLba = VA_ARG (args, UINT32); + + while (NumOfLba > 0) { + Status = FvbEraseBlock (FvbDevice->Instance, StartingLba, mFvbModuleGlobal, EfiGoneVirtual ()); + if (EFI_ERROR (Status)) { + VA_END (args); + return Status; + } + + StartingLba++; + NumOfLba--; + } + + } while (1); + + VA_END (args); + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + + Writes data beginning at Lba:Offset from FV. The write terminates either + when *NumBytes of data have been written, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + +Arguments: + This - Calling context + Lba - Block in which to begin write + Offset - Offset in the block at which to begin write + NumBytes - On input, indicates the requested write size. On + output, indicates the actual number of bytes written + Buffer - Buffer containing source data for the write. + +Returns: + EFI_SUCCESS - The firmware volume was written successfully + EFI_BAD_BUFFER_SIZE - Write attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes + actually written + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written + EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL + +--*/ +{ + + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbWriteBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); +} + +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +/*++ + +Routine Description: + + Reads data beginning at Lba:Offset from FV. The Read terminates either + when *NumBytes of data have been read, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. The write opertion does not include erase. This routine will + attempt to write only the specified bytes. If the writes do not stick, + it will return an error. + +Arguments: + This - Calling context + Lba - Block in which to begin Read + Offset - Offset in the block at which to begin Read + NumBytes - On input, indicates the requested write size. On + output, indicates the actual number of bytes Read + Buffer - Buffer containing source data for the Read. + +Returns: + EFI_SUCCESS - The firmware volume was read successfully and + contents are in Buffer + EFI_BAD_BUFFER_SIZE - Read attempted across a LBA boundary. On output, + NumBytes contains the total number of bytes returned + in Buffer + EFI_ACCESS_DENIED - The firmware volume is in the ReadDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be read + EFI_INVALID_PARAMETER - NumBytes or Buffer are NULL + +--*/ +{ + + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_DEVICE_FROM_THIS (This); + + return FvbReadBlock (FvbDevice->Instance, Lba, Offset, NumBytes, Buffer, mFvbModuleGlobal, EfiGoneVirtual ()); +} +// +// FVB Extension Protocols +// +EFI_STATUS +EFIAPI +FvbExtendProtocolEraseCustomBlockRange ( + IN EFI_FVB_EXTENSION_PROTOCOL *This, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba + ) +/*++ + +Routine Description: + Erases and initializes a specified range of a firmware volume + +Arguments: + This - Calling context + StartLba - The starting logical block index to be erased + OffsetStartLba - Offset into the starting block at which to + begin erasing + LastLba - The last logical block index to be erased + OffsetStartLba - Offset into the last block at which to end erasing + +Returns: + EFI_SUCCESS - The firmware volume was erased successfully + EFI_ACCESS_DENIED - The firmware volume is in the WriteDisabled state + EFI_DEVICE_ERROR - The block device is not functioning correctly and + could not be written. Firmware device may have been + partially erased + +--*/ +{ + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + + FvbDevice = FVB_EXTEND_DEVICE_FROM_THIS (This); + + return FvbEraseCustomBlockRange ( + FvbDevice->Instance, + StartLba, + OffsetStartLba, + LastLba, + OffsetLastLba, + mFvbModuleGlobal, + EfiGoneVirtual () + ); +} + +STATIC +EFI_STATUS +ValidateFvHeader ( + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader + ) +/*++ + +Routine Description: + Check the integrity of firmware volume header + +Arguments: + FwVolHeader - A pointer to a firmware volume header + +Returns: + EFI_SUCCESS - The firmware volume is consistent + EFI_NOT_FOUND - The firmware volume has corrupted. So it is not an FV + +--*/ +{ + UINT16 *Ptr; + UINT16 HeaderLength; + UINT16 Checksum; + + // + // Verify the header revision, header signature, length + // Length of FvBlock cannot be 2**64-1 + // HeaderLength cannot be an odd number + // + if ((FwVolHeader->Revision != EFI_FVH_REVISION) || + (FwVolHeader->Signature != EFI_FVH_SIGNATURE) || + (FwVolHeader->FvLength == ((UINTN) -1)) || + ((FwVolHeader->HeaderLength & 0x01) != 0) + ) { + return EFI_NOT_FOUND; + } + // + // Verify the header checksum + // + HeaderLength = (UINT16) (FwVolHeader->HeaderLength / 2); + Ptr = (UINT16 *) FwVolHeader; + Checksum = 0; + while (HeaderLength > 0) { + Checksum = *Ptr++; + HeaderLength--; + } + + if (Checksum != 0) { + return EFI_NOT_FOUND; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + This function does common initialization for FVB services + +Arguments: + +Returns: + +--*/ +{ + EFI_STATUS Status; + EFI_FW_VOL_INSTANCE *FwhInstance; + EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader; + EFI_DXE_SERVICES *DxeServices; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR Descriptor; + UINT32 BufferSize; + EFI_FV_BLOCK_MAP_ENTRY *PtrBlockMapEntry; + EFI_HANDLE FwbHandle; + EFI_FW_VOL_BLOCK_DEVICE *FvbDevice; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *OldFwbInterface; + EFI_DEVICE_PATH_PROTOCOL *TempFwbDevicePath; + FV_DEVICE_PATH TempFvbDevicePathData; + UINT32 MaxLbaSize; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; + UINTN NumOfBlocks; + EFI_PEI_HOB_POINTERS FvHob; + + // + // Get the DXE services table + // + DxeServices = gDS; + + // + // Allocate runtime services data for global variable, which contains + // the private data of all firmware volume block instances + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (ESAL_FWB_GLOBAL), + &mFvbModuleGlobal + ); + ASSERT_EFI_ERROR (Status); + + // + // Calculate the total size for all firmware volume block instances + // + BufferSize = 0; + + FvHob.Raw = GetHobList (); + while ((FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw)) != NULL) { + BaseAddress = FvHob.FirmwareVolume->BaseAddress; + Length = FvHob.FirmwareVolume->Length; + // + // Check if it is a "real" flash + // + Status = DxeServices->GetMemorySpaceDescriptor ( + BaseAddress, + &Descriptor + ); + if (EFI_ERROR (Status)) { + break; + } + + if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) { + FvHob.Raw = GET_NEXT_HOB (FvHob); + continue; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; + Status = ValidateFvHeader (FwVolHeader); + if (EFI_ERROR (Status)) { + // + // Get FvbInfo + // + Status = GetFvbInfo (Length, &FwVolHeader); + if (EFI_ERROR (Status)) { + FvHob.Raw = GET_NEXT_HOB (FvHob); + continue; + } + } + + BufferSize += (sizeof (EFI_FW_VOL_INSTANCE) + FwVolHeader->HeaderLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER)); + FvHob.Raw = GET_NEXT_HOB (FvHob); + } + + // + // Only need to allocate once. There is only one copy of physical memory for + // the private data of each FV instance. But in virtual mode or in physical + // mode, the address of the the physical memory may be different. + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + BufferSize, + &mFvbModuleGlobal->FvInstance[FVB_PHYSICAL] + ); + ASSERT_EFI_ERROR (Status); + + // + // Make a virtual copy of the FvInstance pointer. + // + FwhInstance = mFvbModuleGlobal->FvInstance[FVB_PHYSICAL]; + mFvbModuleGlobal->FvInstance[FVB_VIRTUAL] = FwhInstance; + + mFvbModuleGlobal->NumFv = 0; + MaxLbaSize = 0; + + FvHob.Raw = GetHobList (); + while (NULL != (FvHob.Raw = GetNextHob (EFI_HOB_TYPE_FV, FvHob.Raw))) { + BaseAddress = FvHob.FirmwareVolume->BaseAddress; + Length = FvHob.FirmwareVolume->Length; + // + // Check if it is a "real" flash + // + Status = DxeServices->GetMemorySpaceDescriptor ( + BaseAddress, + &Descriptor + ); + if (EFI_ERROR (Status)) { + break; + } + + if (Descriptor.GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) { + FvHob.Raw = GET_NEXT_HOB (FvHob); + continue; + } + + FwVolHeader = (EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) BaseAddress; + Status = ValidateFvHeader (FwVolHeader); + if (EFI_ERROR (Status)) { + // + // Get FvbInfo to provide in FwhInstance. + // + Status = GetFvbInfo (Length, &FwVolHeader); + if (EFI_ERROR (Status)) { + FvHob.Raw = GET_NEXT_HOB (FvHob); + continue; + } + // + // Write healthy FV header back. + // + CopyMem ( + (VOID *) (UINTN) BaseAddress, + (VOID *) FwVolHeader, + FwVolHeader->HeaderLength + ); + } + + FwhInstance->FvBase[FVB_PHYSICAL] = (UINTN) BaseAddress; + FwhInstance->FvBase[FVB_VIRTUAL] = (UINTN) BaseAddress; + + CopyMem ((UINTN *) &(FwhInstance->VolumeHeader), (UINTN *) FwVolHeader, FwVolHeader->HeaderLength); + FwVolHeader = &(FwhInstance->VolumeHeader); + EfiInitializeLock (&(FwhInstance->FvbDevLock), EFI_TPL_HIGH_LEVEL); + + NumOfBlocks = 0; + + for (PtrBlockMapEntry = FwVolHeader->FvBlockMap; PtrBlockMapEntry->NumBlocks != 0; PtrBlockMapEntry++) { + // + // Get the maximum size of a block. The size will be used to allocate + // buffer for Scratch space, the intermediate buffer for FVB extension + // protocol + // + if (MaxLbaSize < PtrBlockMapEntry->BlockLength) { + MaxLbaSize = PtrBlockMapEntry->BlockLength; + } + + NumOfBlocks = NumOfBlocks + PtrBlockMapEntry->NumBlocks; + } + // + // The total number of blocks in the FV. + // + FwhInstance->NumOfBlocks = NumOfBlocks; + + // + // Add a FVB Protocol Instance + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + sizeof (EFI_FW_VOL_BLOCK_DEVICE), + &FvbDevice + ); + ASSERT_EFI_ERROR (Status); + + CopyMem (FvbDevice, &mFvbDeviceTemplate, sizeof (EFI_FW_VOL_BLOCK_DEVICE)); + + FvbDevice->Instance = mFvbModuleGlobal->NumFv; + mFvbModuleGlobal->NumFv++; + + // + // Set up the devicepath + // + FvbDevice->DevicePath.MemMapDevPath.StartingAddress = BaseAddress; + FvbDevice->DevicePath.MemMapDevPath.EndingAddress = BaseAddress + (FwVolHeader->FvLength - 1); + + // + // Find a handle with a matching device path that has supports FW Block protocol + // + TempFwbDevicePath = (EFI_DEVICE_PATH_PROTOCOL *) &TempFvbDevicePathData; + CopyMem (TempFwbDevicePath, &FvbDevice->DevicePath, sizeof (FV_DEVICE_PATH)); + Status = gBS->LocateDevicePath (&gEfiFirmwareVolumeBlockProtocolGuid, &TempFwbDevicePath, &FwbHandle); + if (EFI_ERROR (Status)) { + // + // LocateDevicePath fails so install a new interface and device path + // + FwbHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + &FvbDevice->FwVolBlockInstance, + &gEfiDevicePathProtocolGuid, + &FvbDevice->DevicePath, + NULL + ); + ASSERT_EFI_ERROR (Status); + } else if (EfiIsDevicePathEnd (TempFwbDevicePath)) { + // + // Device allready exists, so reinstall the FVB protocol + // + Status = gBS->HandleProtocol ( + FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + &OldFwbInterface + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->ReinstallProtocolInterface ( + FwbHandle, + &gEfiFirmwareVolumeBlockProtocolGuid, + OldFwbInterface, + &FvbDevice->FwVolBlockInstance + ); + ASSERT_EFI_ERROR (Status); + + } else { + // + // There was a FVB protocol on an End Device Path node + // + ASSERT (FALSE); + } + // + // Install FVB Extension Protocol on the same handle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + &FwbHandle, + &gEfiFvbExtensionProtocolGuid, + &FvbDevice->FvbExtension, + &gEfiAlternateFvBlockGuid, + NULL, + NULL + ); + + ASSERT_EFI_ERROR (Status); + + FwhInstance = (EFI_FW_VOL_INSTANCE *) + ( + (UINTN) ((UINT8 *) FwhInstance) + FwVolHeader->HeaderLength + + (sizeof (EFI_FW_VOL_INSTANCE) - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) + ); + + FvHob.Raw = GET_NEXT_HOB (FvHob); + } + + // + // Allocate for scratch space, an intermediate buffer for FVB extention + // + Status = gBS->AllocatePool ( + EfiRuntimeServicesData, + MaxLbaSize, + &mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL] + ); + ASSERT_EFI_ERROR (Status); + + mFvbModuleGlobal->FvbScratchSpace[FVB_VIRTUAL] = mFvbModuleGlobal->FvbScratchSpace[FVB_PHYSICAL]; + + return EFI_SUCCESS; +} diff --git a/EdkNt32Pkg/RuntimeDxe/FvbServices/nt32/FvbInfo.c b/EdkNt32Pkg/RuntimeDxe/FvbServices/nt32/FvbInfo.c new file mode 100644 index 0000000000..d079423af8 --- /dev/null +++ b/EdkNt32Pkg/RuntimeDxe/FvbServices/nt32/FvbInfo.c @@ -0,0 +1,125 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FvbInfo.c + +Abstract: + + Defines data structure that is the volume header found.These data is intent + to decouple FVB driver with FV header. + +--*/ + +#include "FlashLayout.h" + +#define FIRMWARE_BLOCK_SIZE 0x10000 + +typedef struct { + UINT64 FvLength; + EFI_FIRMWARE_VOLUME_HEADER FvbInfo; + // + // EFI_FV_BLOCK_MAP_ENTRY ExtraBlockMap[n];//n=0 + // + EFI_FV_BLOCK_MAP_ENTRY End[1]; +} EFI_FVB_MEDIA_INFO; + +#define FVB_MEDIA_BLOCK_SIZE FIRMWARE_BLOCK_SIZE +#define RECOVERY_BOIS_BLOCK_NUM FIRMWARE_BLOCK_NUMBER +#define SYSTEM_NV_BLOCK_NUM 2 + +EFI_FVB_MEDIA_INFO mPlatformFvbMediaInfo[] = { + // + // Recovery BOIS FVB + // + { + EFI_WINNT_FIRMWARE_LENGTH, + { + { + 0, + }, // ZeroVector[16] + EFI_FIRMWARE_FILE_SYSTEM_GUID, + FVB_MEDIA_BLOCK_SIZE * RECOVERY_BOIS_BLOCK_NUM, + EFI_FVH_SIGNATURE, + EFI_FVB_READ_ENABLED_CAP | + EFI_FVB_READ_STATUS | + EFI_FVB_WRITE_ENABLED_CAP | + EFI_FVB_WRITE_STATUS | + EFI_FVB_ERASE_POLARITY, + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), + 0, // CheckSum + { + 0, + }, // Reserved[3] + 1, // Revision + { + RECOVERY_BOIS_BLOCK_NUM, + FVB_MEDIA_BLOCK_SIZE, + } + }, + { + 0, + 0 + } + }, + // + // Systen NvStorage FVB + // + { + EFI_WINNT_RUNTIME_UPDATABLE_LENGTH + EFI_WINNT_FTW_SPARE_BLOCK_LENGTH, + { + { + 0, + }, // ZeroVector[16] + EFI_SYSTEM_NV_DATA_HOB_GUID, + FVB_MEDIA_BLOCK_SIZE * SYSTEM_NV_BLOCK_NUM, + EFI_FVH_SIGNATURE, + EFI_FVB_READ_ENABLED_CAP | + EFI_FVB_READ_STATUS | + EFI_FVB_WRITE_ENABLED_CAP | + EFI_FVB_WRITE_STATUS | + EFI_FVB_ERASE_POLARITY, + sizeof (EFI_FIRMWARE_VOLUME_HEADER) + sizeof (EFI_FV_BLOCK_MAP_ENTRY), + 0, // CheckSum + { + 0, + }, // Reserved[3] + 1, // Revision + { + SYSTEM_NV_BLOCK_NUM, + FVB_MEDIA_BLOCK_SIZE, + } + }, + { + 0, + 0 + } + } +}; + +EFI_STATUS +GetFvbInfo ( + IN UINT64 FvLength, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ) +{ + UINTN Index; + + for (Index = 0; Index < sizeof (mPlatformFvbMediaInfo) / sizeof (EFI_FVB_MEDIA_INFO); Index += 1) { + if (mPlatformFvbMediaInfo[Index].FvLength == FvLength) { + *FvbInfo = &mPlatformFvbMediaInfo[Index].FvbInfo; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} diff --git a/EdkNt32Pkg/RuntimeDxe/FvbServices/nt32/FwBlockService.h b/EdkNt32Pkg/RuntimeDxe/FvbServices/nt32/FwBlockService.h new file mode 100644 index 0000000000..6f949d37ec --- /dev/null +++ b/EdkNt32Pkg/RuntimeDxe/FvbServices/nt32/FwBlockService.h @@ -0,0 +1,238 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + FwBlockService.h + +Abstract: + + Firmware volume block driver for Intel Firmware Hub (FWH) device + +--*/ + +#ifndef _FW_BLOCK_SERVICE_H +#define _FW_BLOCK_SERVICE_H + +// +// BugBug: Add documentation here for data structure!!!! +// +#define FVB_PHYSICAL 0 +#define FVB_VIRTUAL 1 + +typedef struct { + EFI_LOCK FvbDevLock; + UINTN FvBase[2]; + UINTN NumOfBlocks; + EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; +} EFI_FW_VOL_INSTANCE; + +typedef struct { + UINT32 NumFv; + EFI_FW_VOL_INSTANCE *FvInstance[2]; + UINT8 *FvbScratchSpace[2]; +} ESAL_FWB_GLOBAL; + +// +// Fvb Protocol instance data +// +#define FVB_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, FwVolBlockInstance, FVB_DEVICE_SIGNATURE) +#define FVB_EXTEND_DEVICE_FROM_THIS(a) CR (a, EFI_FW_VOL_BLOCK_DEVICE, FvbExtension, FVB_DEVICE_SIGNATURE) +#define FVB_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('F', 'V', 'B', 'N') + +typedef struct { + MEMMAP_DEVICE_PATH MemMapDevPath; + EFI_DEVICE_PATH_PROTOCOL EndDevPath; +} FV_DEVICE_PATH; + +typedef struct { + UINTN Signature; + FV_DEVICE_PATH DevicePath; + UINTN Instance; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL FwVolBlockInstance; + EFI_FVB_EXTENSION_PROTOCOL FvbExtension; +} EFI_FW_VOL_BLOCK_DEVICE; + +EFI_STATUS +GetFvbInfo ( + IN UINT64 FvLength, + OUT EFI_FIRMWARE_VOLUME_HEADER **FvbInfo + ) +; + +EFI_STATUS +FvbReadBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbWriteBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN UINTN BlockOffset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbEraseBlock ( + IN UINTN Instance, + IN EFI_LBA Lba, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbSetVolumeAttributes ( + IN UINTN Instance, + IN OUT EFI_FVB_ATTRIBUTES *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbGetVolumeAttributes ( + IN UINTN Instance, + OUT EFI_FVB_ATTRIBUTES *Attributes, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +FvbGetPhysicalAddress ( + IN UINTN Instance, + OUT EFI_PHYSICAL_ADDRESS *Address, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +EFI_STATUS +EFIAPI +FvbInitialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +; + + +VOID +EFIAPI +FvbClassAddressChangeEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +; + +EFI_STATUS +FvbGetLbaAddress ( + IN UINTN Instance, + IN EFI_LBA Lba, + OUT UINTN *LbaAddress, + OUT UINTN *LbaLength, + OUT UINTN *NumOfBlocks, + IN ESAL_FWB_GLOBAL *Global, + IN BOOLEAN Virtual + ) +; + +// +// Protocol APIs +// +EFI_STATUS +EFIAPI +FvbProtocolGetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolSetAttributes ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES *Attributes + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolGetPhysicalAddress ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolGetBlockSize ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumOfBlocks + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolRead ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolWrite ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +; + +EFI_STATUS +EFIAPI +FvbProtocolEraseBlocks ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +; + +EFI_STATUS +EFIAPI +FvbExtendProtocolEraseCustomBlockRange ( + IN EFI_FVB_EXTENSION_PROTOCOL *This, + IN EFI_LBA StartLba, + IN UINTN OffsetStartLba, + IN EFI_LBA LastLba, + IN UINTN OffsetLastLba + ) +; + +#endif diff --git a/EdkNt32Pkg/Sec/FwVol.c b/EdkNt32Pkg/Sec/FwVol.c new file mode 100644 index 0000000000..25ebe07c83 --- /dev/null +++ b/EdkNt32Pkg/Sec/FwVol.c @@ -0,0 +1,314 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + FwVol.c + +Abstract: + A simple FV stack so the SEC can extract the SEC Core from an + FV. + +--*/ + +#include "SecMain.h" + +#define GET_OCCUPIED_SIZE(ActualSize, Alignment) \ + (ActualSize) + (((Alignment) - ((ActualSize) & ((Alignment) - 1))) & ((Alignment) - 1)) + +EFI_FFS_FILE_STATE +GetFileState ( + IN UINT8 ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + Returns the highest bit set of the State field + +Arguments: + ErasePolarity - Erase Polarity as defined by EFI_FVB_ERASE_POLARITY + in the Attributes field. + FfsHeader - Pointer to FFS File Header. + +Returns: + Returns the highest bit in the State field + +--*/ +{ + EFI_FFS_FILE_STATE FileState; + EFI_FFS_FILE_STATE HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity != 0) { + FileState = (EFI_FFS_FILE_STATE)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} + +UINT8 +CalculateHeaderChecksum ( + IN EFI_FFS_FILE_HEADER *FileHeader + ) +/*++ + +Routine Description: + Calculates the checksum of the header of a file. + +Arguments: + FileHeader - Pointer to FFS File Header. + +Returns: + Checksum of the header. + +--*/ +{ + UINT8 *ptr; + UINTN Index; + UINT8 Sum; + + Sum = 0; + ptr = (UINT8 *) FileHeader; + + for (Index = 0; Index < sizeof (EFI_FFS_FILE_HEADER) - 3; Index += 4) { + Sum = (UINT8) (Sum + ptr[Index]); + Sum = (UINT8) (Sum + ptr[Index + 1]); + Sum = (UINT8) (Sum + ptr[Index + 2]); + Sum = (UINT8) (Sum + ptr[Index + 3]); + } + + for (; Index < sizeof (EFI_FFS_FILE_HEADER); Index++) { + Sum = (UINT8) (Sum + ptr[Index]); + } + // + // State field (since this indicates the different state of file). + // + Sum = (UINT8) (Sum - FileHeader->State); + // + // Checksum field of the file is not part of the header checksum. + // + Sum = (UINT8) (Sum - FileHeader->IntegrityCheck.Checksum.File); + + return Sum; +} + +EFI_STATUS +SecFfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching file in the + FFS volume as defined by SearchType. The search starts from FileHeader inside + the Firmware Volume defined by FwVolHeader. + +Arguments: + SearchType - Filter to find only files of this type. + Type EFI_FV_FILETYPE_ALL causes no filtering to be done. + FwVolHeader - Pointer to the FV header of the volume to search. + This parameter must point to a valid FFS volume. + FileHeader - Pointer to the current file from which to begin searching. + This pointer will be updated upon return to reflect the file + found. + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + EFI_FFS_FILE_HEADER *FfsFileHeader; + UINT32 FileLength; + UINT32 FileOccupiedSize; + UINT32 FileOffset; + UINT64 FvLength; + UINT8 ErasePolarity; + UINT8 FileState; + + FvLength = FwVolHeader->FvLength; + if (FwVolHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + ErasePolarity = 1; + } else { + ErasePolarity = 0; + } + // + // If FileHeader is not specified (NULL) start with the first file in the + // firmware volume. Otherwise, start from the FileHeader. + // + if (*FileHeader == NULL) { + FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FwVolHeader + FwVolHeader->HeaderLength); + } else { + // + // Length is 24 bits wide so mask upper 8 bits + // FileLength is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + FileLength = *(UINT32 *) (*FileHeader)->Size & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); + FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) *FileHeader + FileOccupiedSize); + } + + FileOffset = (UINT32) ((UINT8 *) FfsFileHeader - (UINT8 *) FwVolHeader); + + while (FileOffset < (FvLength - sizeof (EFI_FFS_FILE_HEADER))) { + // + // Get FileState which is the highest bit of the State + // + FileState = GetFileState (ErasePolarity, FfsFileHeader); + + switch (FileState) { + + case EFI_FILE_HEADER_INVALID: + FileOffset += sizeof (EFI_FFS_FILE_HEADER); + FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + sizeof (EFI_FFS_FILE_HEADER)); + break; + + case EFI_FILE_DATA_VALID: + case EFI_FILE_MARKED_FOR_UPDATE: + if (CalculateHeaderChecksum (FfsFileHeader) == 0) { + FileLength = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); + + if ((SearchType == FfsFileHeader->Type) || (SearchType == EFI_FV_FILETYPE_ALL)) { + + *FileHeader = FfsFileHeader; + + return EFI_SUCCESS; + } + + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize); + } else { + return EFI_NOT_FOUND; + } + break; + + case EFI_FILE_DELETED: + FileLength = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF; + FileOccupiedSize = GET_OCCUPIED_SIZE (FileLength, 8); + FileOffset += FileOccupiedSize; + FfsFileHeader = (EFI_FFS_FILE_HEADER *) ((UINT8 *) FfsFileHeader + FileOccupiedSize); + break; + + default: + return EFI_NOT_FOUND; + + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +SecFfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +/*++ + +Routine Description: + Given the input file pointer, search for the next matching section in the + FFS volume. + +Arguments: + SearchType - Filter to find only sections of this type. + FfsFileHeader - Pointer to the current file to search. + SectionData - Pointer to the Section matching SectionType in FfsFileHeader. + NULL if section not found + +Returns: + EFI_NOT_FOUND - No files matching the search criteria were found + EFI_SUCCESS + +--*/ +{ + UINT32 FileSize; + EFI_COMMON_SECTION_HEADER *Section; + UINT32 SectionLength; + UINT32 ParsedLength; + + // + // Size is 24 bits wide so mask upper 8 bits. + // Does not include FfsFileHeader header size + // FileSize is adjusted to FileOccupiedSize as it is 8 byte aligned. + // + Section = (EFI_COMMON_SECTION_HEADER *) (FfsFileHeader + 1); + FileSize = *(UINT32 *) (FfsFileHeader->Size) & 0x00FFFFFF; + FileSize -= sizeof (EFI_FFS_FILE_HEADER); + + *SectionData = NULL; + ParsedLength = 0; + while (ParsedLength < FileSize) { + if (Section->Type == SectionType) { + *SectionData = (VOID *) (Section + 1); + return EFI_SUCCESS; + } + // + // Size is 24 bits wide so mask upper 8 bits. + // SectionLength is adjusted it is 4 byte aligned. + // Go to the next section + // + SectionLength = *(UINT32 *) Section->Size & 0x00FFFFFF; + SectionLength = GET_OCCUPIED_SIZE (SectionLength, 4); + + ParsedLength += SectionLength; + Section = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) Section + SectionLength); + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +SecFfsFindPeiCore ( + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + OUT VOID **Pe32Data + ) +/*++ + +Routine Description: + Given the pointer to the Firmware Volume Header find the SEC + core and return it's PE32 image. + +Arguments: + FwVolHeader - Pointer to memory mapped FV + Pe32Data - Pointer to SEC PE32 iamge. + +Returns: + EFI_SUCCESS - Pe32Data is valid + other - Failure + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *FileHeader; + EFI_FV_FILETYPE SearchType; + + SearchType = EFI_FV_FILETYPE_PEI_CORE; + FileHeader = NULL; + do { + Status = SecFfsFindNextFile (SearchType, FwVolHeader, &FileHeader); + if (!EFI_ERROR (Status)) { + Status = SecFfsFindSectionData (EFI_SECTION_PE32, FileHeader, Pe32Data); + return Status; + } + } while (!EFI_ERROR (Status)); + + return Status; +} diff --git a/EdkNt32Pkg/Sec/SecMain.c b/EdkNt32Pkg/Sec/SecMain.c new file mode 100644 index 0000000000..2c3d08e062 --- /dev/null +++ b/EdkNt32Pkg/Sec/SecMain.c @@ -0,0 +1,1163 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + SecMain.c + +Abstract: + WinNt emulator of SEC phase. It's really a Win32 application, but this is + Ok since all the other modules for NT32 are NOT Win32 applications. + + This program processes Windows environment variables and figures out + what the memory layout will be, how may FD's will be loaded and also + what the boot mode is. + + The SEC registers a set of services with the SEC core. gPrivateDispatchTable + is a list of PPI's produced by the SEC that are availble for usage in PEI. + + This code produces 128 K of temporary memory for the PEI stack by opening a + Windows file and mapping it directly to memory addresses. + + The system.cmd script is used to set windows environment variables that drive + the configuration opitons of the SEC. + +--*/ + +#include "SecMain.h" + +// +// Globals +// +EFI_PEI_PE_COFF_LOADER_PROTOCOL_INSTANCE mPeiEfiPeiPeCoffLoaderInstance = { + { + SecNt32PeCoffGetImageInfo, + SecNt32PeCoffLoadImage, + SecNt32PeCoffRelocateImage, + SecNt32PeCoffUnloadimage + }, + NULL +}; + + + +EFI_PEI_PE_COFF_LOADER_PROTOCOL *gPeiEfiPeiPeCoffLoader = &mPeiEfiPeiPeCoffLoaderInstance.PeCoff; + +NT_PEI_LOAD_FILE_PPI mSecNtLoadFilePpi = { SecWinNtPeiLoadFile }; + +PEI_NT_AUTOSCAN_PPI mSecNtAutoScanPpi = { SecWinNtPeiAutoScan }; + +PEI_NT_THUNK_PPI mSecWinNtThunkPpi = { SecWinNtWinNtThunkAddress }; + +EFI_PEI_PROGRESS_CODE_PPI mSecStatusCodePpi = { SecPeiReportStatusCode }; + +NT_FWH_PPI mSecFwhInformationPpi = { SecWinNtFdAddress }; + + +EFI_PEI_PPI_DESCRIPTOR gPrivateDispatchTable[] = { + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiPeiPeCoffLoaderGuid, + NULL + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gNtPeiLoadFilePpiGuid, + &mSecNtLoadFilePpi + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gPeiNtAutoScanPpiGuid, + &mSecNtAutoScanPpi + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gPeiNtThunkPpiGuid, + &mSecWinNtThunkPpi + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI, + &gEfiPeiStatusCodePpiGuid, + &mSecStatusCodePpi + }, + { + EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST, + &gNtFwhPpiGuid, + &mSecFwhInformationPpi + } +}; + + +// +// Default information about where the FD is located. +// This array gets filled in with information from EFI_FIRMWARE_VOLUMES +// EFI_FIRMWARE_VOLUMES is a Windows environment variable set by system.cmd. +// The number of array elements is allocated base on parsing +// EFI_FIRMWARE_VOLUMES and the memory is never freed. +// +UINTN gFdInfoCount = 0; +NT_FD_INFO *gFdInfo; + +// +// Array that supports seperate memory rantes. +// The memory ranges are set in system.cmd via the EFI_MEMORY_SIZE variable. +// The number of array elements is allocated base on parsing +// EFI_MEMORY_SIZE and the memory is never freed. +// +UINTN gSystemMemoryCount = 0; +NT_SYSTEM_MEMORY *gSystemMemory; + + +UINTN mPdbNameModHandleArraySize = 0; +PDB_NAME_TO_MOD_HANDLE *mPdbNameModHandleArray = NULL; + + + + +INTN +EFIAPI +main ( + IN INTN Argc, + IN CHAR8 **Argv, + IN CHAR8 **Envp + ) +/*++ + +Routine Description: + Main entry point to SEC for WinNt. This is a Windows program + +Arguments: + Argc - Number of command line arguments + Argv - Array of command line argument strings + Envp - Array of environmemt variable strings + +Returns: + 0 - Normal exit + 1 - Abnormal exit + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS InitialStackMemory; + UINT64 InitialStackMemorySize; + UINTN Index; + UINTN Index1; + UINTN Index2; + UINTN PeiIndex; + CHAR16 *FileName; + CHAR16 *FileNamePtr; + BOOLEAN Done; + VOID *PeiCoreFile; + CHAR16 *MemorySizeStr; + CHAR16 *FirmwareVolumesStr; + + MemorySizeStr = (CHAR16 *)FixedPcdGetPtr (PcdWinNtMemorySize); + FirmwareVolumesStr = (CHAR16 *)FixedPcdGetPtr (PcdWinNtFirmwareVolume); + + printf ("\nEDK SEC Main NT Emulation Environment from www.TianoCore.org\n"); + + // + // Make some Windows calls to Set the process to the highest priority in the + // idle class. We need this to have good performance. + // + SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS); + SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_HIGHEST); + + // + // Allocate space for gSystemMemory Array + // + gSystemMemoryCount = CountSeperatorsInString (MemorySizeStr, '!') + 1; + gSystemMemory = calloc (gSystemMemoryCount, sizeof (NT_SYSTEM_MEMORY)); + if (gSystemMemory == NULL) { + printf ("ERROR : Can not allocate memory for %s. Exiting.\n", MemorySizeStr); + exit (1); + } + // + // Allocate space for gSystemMemory Array + // + gFdInfoCount = CountSeperatorsInString (FirmwareVolumesStr, '!') + 1; + gFdInfo = calloc (gFdInfoCount, sizeof (NT_FD_INFO)); + if (gFdInfo == NULL) { + printf ("ERROR : Can not allocate memory for %s. Exiting.\n", FirmwareVolumesStr); + exit (1); + } + // + // Setup Boot Mode. If BootModeStr == "" then BootMode = 0 (BOOT_WITH_FULL_CONFIGURATION) + // + printf (" BootMode 0x%02x\n", FixedPcdGet32 (PcdWinNtBootMode)); + + // + // Open up a 128K file to emulate temp memory for PEI. + // on a real platform this would be SRAM, or using the cache as RAM. + // Set InitialStackMemory to zero so WinNtOpenFile will allocate a new mapping + // + InitialStackMemory = 0; + InitialStackMemorySize = 0x20000; + Status = WinNtOpenFile ( + L"SecStack", + (UINT32) InitialStackMemorySize, + OPEN_ALWAYS, + &InitialStackMemory, + &InitialStackMemorySize + ); + if (EFI_ERROR (Status)) { + printf ("ERROR : Can not open SecStack Exiting\n"); + exit (1); + } + + printf (" SEC passing in %d bytes of temp RAM to PEI\n", InitialStackMemorySize); + + // + // Open All the firmware volumes and remember the info in the gFdInfo global + // + FileNamePtr = (CHAR16 *)malloc (StrLen ((CHAR16 *)FirmwareVolumesStr) * sizeof(CHAR16)); + if (FileNamePtr == NULL) { + printf ("ERROR : Can not allocate memory for firmware volume string\n"); + exit (1); + } + + StrCpy (FileNamePtr, (CHAR16*)FirmwareVolumesStr); + + for (Done = FALSE, Index = 0, PeiIndex = 0, PeiCoreFile = NULL; !Done; Index++) { + FileName = FileNamePtr; + for (Index1 = 0; (FileNamePtr[Index1] != '!') && (FileNamePtr[Index1] != 0); Index1++) + ; + if (FileNamePtr[Index1] == 0) { + Done = TRUE; + } else { + FileNamePtr[Index1] = '\0'; + FileNamePtr = FileNamePtr + Index1 + 1; + } + + // + // Open the FD and remmeber where it got mapped into our processes address space + // + Status = WinNtOpenFile ( + FileName, + 0, + OPEN_EXISTING, + &gFdInfo[Index].Address, + &gFdInfo[Index].Size + ); + if (EFI_ERROR (Status)) { + printf ("ERROR : Can not open Firmware Device File %S (%r). Exiting.\n", FileName, Status); + exit (1); + } + + printf (" FD loaded from"); + // + // printf can't print filenames directly as the \ gets interperted as an + // escape character. + // + for (Index2 = 0; FileName[Index2] != '\0'; Index2++) { + printf ("%c", FileName[Index2]); + } + + if (PeiCoreFile == NULL) { + // + // Assume the beginning of the FD is an FV and look for the PEI Core. + // Load the first one we find. + // + Status = SecFfsFindPeiCore ((EFI_FIRMWARE_VOLUME_HEADER *) (UINTN) gFdInfo[Index].Address, &PeiCoreFile); + if (!EFI_ERROR (Status)) { + PeiIndex = Index; + printf (" contains SEC Core"); + } + } + + printf ("\n"); + } + // + // Calculate memory regions and store the information in the gSystemMemory + // global for later use. The autosizing code will use this data to + // map this memory into the SEC process memory space. + // + for (Index = 0, Done = FALSE; !Done; Index++) { + // + // Save the size of the memory and make a Unicode filename SystemMemory00, ... + // + gSystemMemory[Index].Size = _wtoi (MemorySizeStr) * 0x100000; + _snwprintf (gSystemMemory[Index].FileName, NT_SYSTEM_MEMORY_FILENAME_SIZE, L"SystemMemory%02d", Index); + + // + // Find the next region + // + for (Index1 = 0; MemorySizeStr[Index1] != '!' && MemorySizeStr[Index1] != 0; Index1++) + ; + if (MemorySizeStr[Index1] == 0) { + Done = TRUE; + } + + MemorySizeStr = MemorySizeStr + Index1 + 1; + } + + printf ("\n"); + + // + // Hand off to PEI Core + // + SecLoadFromCore ((UINTN) InitialStackMemory, (UINTN) InitialStackMemorySize, (UINTN) gFdInfo[0].Address, PeiCoreFile); + + // + // If we get here, then the PEI Core returned. This is an error as PEI should + // always hand off to DXE. + // + printf ("ERROR : PEI Core returned\n"); + exit (1); +} + +EFI_STATUS +WinNtOpenFile ( + IN CHAR16 *FileName, + IN UINT32 MapSize, + IN DWORD CreationDisposition, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + OUT UINT64 *Length + ) +/*++ + +Routine Description: + Opens and memory maps a file using WinNt services. If BaseAddress is non zero + the process will try and allocate the memory starting at BaseAddress. + +Arguments: + FileName - The name of the file to open and map + MapSize - The amount of the file to map in bytes + CreationDisposition - The flags to pass to CreateFile(). Use to create new files for + memory emulation, and exiting files for firmware volume emulation + BaseAddress - The base address of the mapped file in the user address space. + If passed in as NULL the a new memory region is used. + If passed in as non NULL the request memory region is used for + the mapping of the file into the process space. + Length - The size of the mapped region in bytes + +Returns: + EFI_SUCCESS - The file was opened and mapped. + EFI_NOT_FOUND - FileName was not found in the current directory + EFI_DEVICE_ERROR - An error occured attempting to map the opened file + +--*/ +{ + HANDLE NtFileHandle; + HANDLE NtMapHandle; + VOID *VirtualAddress; + UINTN FileSize; + + // + // Use Win API to open/create a file + // + NtFileHandle = CreateFile ( + FileName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + CreationDisposition, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if (NtFileHandle == INVALID_HANDLE_VALUE) { + return EFI_NOT_FOUND; + } + // + // Map the open file into a memory range + // + NtMapHandle = CreateFileMapping ( + NtFileHandle, + NULL, + PAGE_READWRITE, + 0, + MapSize, + NULL + ); + if (NtMapHandle == NULL) { + return EFI_DEVICE_ERROR; + } + // + // Get the virtual address (address in the emulator) of the mapped file + // + VirtualAddress = MapViewOfFileEx ( + NtMapHandle, + FILE_MAP_ALL_ACCESS, + 0, + 0, + MapSize, + (LPVOID) (UINTN) *BaseAddress + ); + if (VirtualAddress == NULL) { + return EFI_DEVICE_ERROR; + } + + if (MapSize == 0) { + // + // Seek to the end of the file to figure out the true file size. + // + FileSize = SetFilePointer ( + NtFileHandle, + 0, + NULL, + FILE_END + ); + if (FileSize == -1) { + return EFI_DEVICE_ERROR; + } + + *Length = (UINT64) FileSize; + } else { + *Length = (UINT64) MapSize; + } + + *BaseAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) VirtualAddress; + + return EFI_SUCCESS; +} + +#define BYTES_PER_RECORD 512 + +EFI_STATUS +EFIAPI +SecPeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +/*++ + +Routine Description: + + This routine produces the ReportStatusCode PEI service. It's passed + up to the PEI Core via a PPI. T + + This code currently uses the NT clib printf. This does not work the same way + as the EFI Print (), as %t, %g, %s as Unicode are not supported. + +Arguments: + (see EFI_PEI_REPORT_STATUS_CODE) + +Returns: + EFI_SUCCESS - Always return success + +--*/ +// TODO: PeiServices - add argument and description to function comment +// TODO: CodeType - add argument and description to function comment +// TODO: Value - add argument and description to function comment +// TODO: Instance - add argument and description to function comment +// TODO: CallerId - add argument and description to function comment +// TODO: Data - add argument and description to function comment +{ + CHAR8 *Format; + EFI_DEBUG_INFO *DebugInfo; + VA_LIST Marker; + CHAR8 PrintBuffer[BYTES_PER_RECORD * 2]; + CHAR8 *Filename; + CHAR8 *Description; + UINT32 LineNumber; + + if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) { + // + // This supports DEBUG () marcos + // Data format + // EFI_STATUS_CODE_DATA + // EFI_DEBUG_INFO + // + // The first 12 * UINT64 bytes of the string are really an + // arguement stack to support varargs on the Format string. + // + DebugInfo = (EFI_DEBUG_INFO *) (Data + 1); + Marker = (VA_LIST) (DebugInfo + 1); + Format = (CHAR8 *) (((UINT64 *) Marker) + 12); + + AsciiVSPrint (PrintBuffer, BYTES_PER_RECORD, Format, Marker); + printf (PrintBuffer); + } + + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) && + ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) + ) { + if (ReportStatusCodeExtractAssertInfo (CodeType, Value, Data, &Filename, &Description, &LineNumber)) { + // + // Support ASSERT () macro + // + printf ("ASSERT %s(%d): %s\n", Filename, LineNumber, Description); + CpuBreakpoint (); + } + } + + return EFI_SUCCESS; +} + + +VOID +SecLoadFromCore ( + IN UINTN LargestRegion, + IN UINTN LargestRegionSize, + IN UINTN BootFirmwareVolumeBase, + IN VOID *PeiCorePe32File + ) +/*++ + +Routine Description: + This is the service to load the PEI Core from the Firmware Volume + +Arguments: + LargestRegion - Memory to use for PEI. + LargestRegionSize - Size of Memory to use for PEI + BootFirmwareVolumeBase - Start of the Boot FV + PeiCorePe32File - PEI Core PE32 + +Returns: + Success means control is transfered and thus we should never return + +--*/ +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS TopOfMemory; + VOID *TopOfStack; + UINT64 PeiCoreSize; + EFI_PHYSICAL_ADDRESS PeiCoreEntryPoint; + EFI_PHYSICAL_ADDRESS PeiImageAddress; + EFI_PEI_STARTUP_DESCRIPTOR *PeiStartup; + + // + // Compute Top Of Memory for Stack and PEI Core Allocations + // + TopOfMemory = LargestRegion + ((LargestRegionSize) & (~15)); + + // + // Allocate 128KB for the Stack + // + TopOfStack = (VOID *) (UINTN) (TopOfMemory - sizeof (EFI_PEI_STARTUP_DESCRIPTOR)); + TopOfMemory = TopOfMemory - STACK_SIZE; + + // + // Patch value in dispatch table values + // + gPrivateDispatchTable[0].Ppi = gPeiEfiPeiPeCoffLoader; + + // + // Bind this information into the SEC hand-off state + // + PeiStartup = (EFI_PEI_STARTUP_DESCRIPTOR *) (UINTN) TopOfStack; + PeiStartup->DispatchTable = (EFI_PEI_PPI_DESCRIPTOR *) &gPrivateDispatchTable; + PeiStartup->SizeOfCacheAsRam = STACK_SIZE; + PeiStartup->BootFirmwareVolume = BootFirmwareVolumeBase; + + // + // Load the PEI Core from a Firmware Volume + // + Status = SecWinNtPeiLoadFile ( + PeiCorePe32File, + &PeiImageAddress, + &PeiCoreSize, + &PeiCoreEntryPoint + ); + if (EFI_ERROR (Status)) { + return ; + } + // + // Transfer control to the PEI Core + // + SwitchStack ( + (SWITCH_STACK_ENTRY_POINT) (UINTN) PeiCoreEntryPoint, + PeiStartup, + NULL, + TopOfStack + ); + // + // If we get here, then the PEI Core returned. This is an error + // + return ; +} + +EFI_STATUS +EFIAPI +SecWinNtPeiAutoScan ( + IN UINTN Index, + OUT EFI_PHYSICAL_ADDRESS *MemoryBase, + OUT UINT64 *MemorySize + ) +/*++ + +Routine Description: + This service is called from Index == 0 until it returns EFI_UNSUPPORTED. + It allows discontiguous memory regions to be supported by the emulator. + It uses gSystemMemory[] and gSystemMemoryCount that were created by + parsing the Windows environment variable EFI_MEMORY_SIZE. + The size comes from the varaible and the address comes from the call to + WinNtOpenFile. + +Arguments: + Index - Which memory region to use + MemoryBase - Return Base address of memory region + MemorySize - Return size in bytes of the memory region + +Returns: + EFI_SUCCESS - If memory region was mapped + EFI_UNSUPPORTED - If Index is not supported + +--*/ +{ + EFI_STATUS Status; + + if (Index >= gSystemMemoryCount) { + return EFI_UNSUPPORTED; + } + + *MemoryBase = 0; + Status = WinNtOpenFile ( + gSystemMemory[Index].FileName, + (UINT32) gSystemMemory[Index].Size, + OPEN_ALWAYS, + MemoryBase, + MemorySize + ); + + gSystemMemory[Index].Memory = *MemoryBase; + + return Status; +} + +VOID * +EFIAPI +SecWinNtWinNtThunkAddress ( + VOID + ) +/*++ + +Routine Description: + Since the SEC is the only Windows program in stack it must export + an interface to do Win API calls. That's what the WinNtThunk address + is for. gWinNt is initailized in WinNtThunk.c. + +Arguments: + InterfaceSize - sizeof (EFI_WIN_NT_THUNK_PROTOCOL); + InterfaceBase - Address of the gWinNt global + +Returns: + EFI_SUCCESS - Data returned + +--*/ +{ + return gWinNt; +} + + +EFI_STATUS +EFIAPI +SecWinNtPeiLoadFile ( + IN VOID *Pe32Data, + IN EFI_PHYSICAL_ADDRESS *ImageAddress, + IN UINT64 *ImageSize, + IN EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + Loads and relocates a PE/COFF image into memory. + +Arguments: + Pe32Data - The base address of the PE/COFF file that is to be loaded and relocated + ImageAddress - The base address of the relocated PE/COFF image + ImageSize - The size of the relocated PE/COFF image + EntryPoint - The entry point of the relocated PE/COFF image + +Returns: + EFI_SUCCESS - The file was loaded and relocated + EFI_OUT_OF_RESOURCES - There was not enough memory to load and relocate the PE/COFF file + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = Pe32Data; + + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecImageRead; + + Status = gPeiEfiPeiPeCoffLoader->GetImageInfo (gPeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Allocate space in NT (not emulator) memory. Extra space is for alignment + // + ImageContext.ImageAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) malloc ((UINTN) (ImageContext.ImageSize + (ImageContext.SectionAlignment * 2))); + if (ImageContext.ImageAddress == 0) { + return EFI_OUT_OF_RESOURCES; + } + // + // Align buffer on section boundry + // + ImageContext.ImageAddress += ImageContext.SectionAlignment; + ImageContext.ImageAddress &= ~(ImageContext.SectionAlignment - 1); + + Status = gPeiEfiPeiPeCoffLoader->LoadImage (gPeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = gPeiEfiPeiPeCoffLoader->RelocateImage (gPeiEfiPeiPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // BugBug: Flush Instruction Cache Here when CPU Lib is ready + // + + *ImageAddress = ImageContext.ImageAddress; + *ImageSize = ImageContext.ImageSize; + *EntryPoint = ImageContext.EntryPoint; + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SecWinNtFdAddress ( + IN UINTN Index, + IN OUT EFI_PHYSICAL_ADDRESS *FdBase, + IN OUT UINT64 *FdSize + ) +/*++ + +Routine Description: + Return the FD Size and base address. Since the FD is loaded from a + file into Windows memory only the SEC will know it's address. + +Arguments: + Index - Which FD, starts at zero. + FdSize - Size of the FD in bytes + FdBase - Start address of the FD. Assume it points to an FV Header + +Returns: + EFI_SUCCESS - Return the Base address and size of the FV + EFI_UNSUPPORTED - Index does nto map to an FD in the system + +--*/ +{ + if (Index >= gFdInfoCount) { + return EFI_UNSUPPORTED; + } + + *FdBase = gFdInfo[Index].Address; + *FdSize = gFdInfo[Index].Size; + + if (*FdBase == 0 && *FdSize == 0) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +SecImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + FileHandle - The handle to the PE/COFF file + FileOffset - The offset, in bytes, into the file to read + ReadSize - The number of bytes to read from the file starting at FileOffset + Buffer - A pointer to the buffer to read the data into. + +Returns: + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINTN Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +CHAR16 * +AsciiToUnicode ( + IN CHAR8 *Ascii, + IN UINTN *StrLen OPTIONAL + ) +/*++ + +Routine Description: + Convert the passed in Ascii string to Unicode. + Optionally return the length of the strings. + +Arguments: + Ascii - Ascii string to convert + StrLen - Length of string + +Returns: + Pointer to malloc'ed Unicode version of Ascii + +--*/ +{ + UINTN Index; + CHAR16 *Unicode; + + // + // Allocate a buffer for unicode string + // + for (Index = 0; Ascii[Index] != '\0'; Index++) + ; + Unicode = malloc ((Index + 1) * sizeof (CHAR16)); + if (Unicode == NULL) { + return NULL; + } + + for (Index = 0; Ascii[Index] != '\0'; Index++) { + Unicode[Index] = (CHAR16) Ascii[Index]; + } + + Unicode[Index] = '\0'; + + if (StrLen != NULL) { + *StrLen = Index; + } + + return Unicode; +} + +UINTN +CountSeperatorsInString ( + IN const CHAR16 *String, + IN CHAR16 Seperator + ) +/*++ + +Routine Description: + Count the number of seperators in String + +Arguments: + String - String to process + Seperator - Item to count + +Returns: + Number of Seperator in String + +--*/ +{ + UINTN Count; + + for (Count = 0; *String != '\0'; String++) { + if (*String == Seperator) { + Count++; + } + } + + return Count; +} + + +EFI_STATUS +AddModHandle ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN VOID *ModHandle + ) +/*++ + +Routine Description: + Store the ModHandle in an array indexed by the Pdb File name. + The ModHandle is needed to unload the image. + +Arguments: + ImageContext - Input data returned from PE Laoder Library. Used to find the + .PDB file name of the PE Image. + ModHandle - Returned from LoadLibraryEx() and stored for call to + FreeLibrary(). + +Returns: + EFI_SUCCESS - ModHandle was stored. + +--*/ +{ + UINTN Index; + PDB_NAME_TO_MOD_HANDLE *Array; + UINTN PreviousSize; + + + Array = mPdbNameModHandleArray; + for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) { + if (Array->PdbPointer == NULL) { + // + // Make a copy of the stirng and store the ModHandle + // + Array->PdbPointer = malloc (strlen (ImageContext->PdbPointer) + 1); + ASSERT (Array->PdbPointer != NULL); + + strcpy (Array->PdbPointer, ImageContext->PdbPointer); + Array->ModHandle = ModHandle; + return EFI_SUCCESS; + } + } + + // + // No free space in mPdbNameModHandleArray so grow it by + // MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE entires. realloc will + // copy the old values to the new locaiton. But it does + // not zero the new memory area. + // + PreviousSize = mPdbNameModHandleArraySize * sizeof (PDB_NAME_TO_MOD_HANDLE); + mPdbNameModHandleArraySize += MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE; + + mPdbNameModHandleArray = realloc (mPdbNameModHandleArray, mPdbNameModHandleArraySize * sizeof (PDB_NAME_TO_MOD_HANDLE)); + if (mPdbNameModHandleArray == NULL) { + ASSERT (FALSE); + return EFI_OUT_OF_RESOURCES; + } + + memset (mPdbNameModHandleArray + PreviousSize, 0, MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE * sizeof (PDB_NAME_TO_MOD_HANDLE)); + + return AddModHandle (ImageContext, ModHandle); +} + + +VOID * +RemoveModeHandle ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + Return the ModHandle and delete the entry in the array. + +Arguments: + ImageContext - Input data returned from PE Laoder Library. Used to find the + .PDB file name of the PE Image. + +Returns: + ModHandle - ModHandle assoicated with ImageContext is returned + NULL - No ModHandle associated with ImageContext + +--*/ +{ + UINTN Index; + PDB_NAME_TO_MOD_HANDLE *Array; + + if (ImageContext->PdbPointer == NULL) { + // + // If no PDB pointer there is no ModHandle so return NULL + // + return NULL; + } + + Array = mPdbNameModHandleArray; + for (Index = 0; Index < mPdbNameModHandleArraySize; Index++, Array++) { + if ((Array->PdbPointer != NULL) && (strcmp(Array->PdbPointer, ImageContext->PdbPointer) == 0)) { + // + // If you find a match return it and delete the entry + // + free (Array->PdbPointer); + Array->PdbPointer = NULL; + return Array->ModHandle; + } + } + + return NULL; +} + + + +EFI_STATUS +EFIAPI +SecNt32PeCoffGetImageInfo ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + EFI_STATUS Status; + + Status = PeCoffLoaderGetImageInfo (ImageContext); + if (EFI_ERROR (Status)) { + return Status; + } + + switch (ImageContext->ImageType) { + + case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: + ImageContext->ImageCodeMemoryType = EfiLoaderCode; + ImageContext->ImageDataMemoryType = EfiLoaderData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: + ImageContext->ImageCodeMemoryType = EfiBootServicesCode; + ImageContext->ImageDataMemoryType = EfiBootServicesData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER: + ImageContext->ImageCodeMemoryType = EfiRuntimeServicesCode; + ImageContext->ImageDataMemoryType = EfiRuntimeServicesData; + break; + + default: + ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM; + return RETURN_UNSUPPORTED; + } + + return Status; +} + +EFI_STATUS +EFIAPI +SecNt32PeCoffLoadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + EFI_STATUS Status; + + Status = PeCoffLoaderLoadImage (ImageContext); + return Status; +} + +EFI_STATUS +EFIAPI +SecNt32PeCoffRelocateImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + EFI_STATUS Status; + VOID *DllEntryPoint; + CHAR16 *DllFileName; + HMODULE Library; + UINTN Index; + + + Status = PeCoffLoaderRelocateImage (ImageContext); + if (EFI_ERROR (Status)) { + // + // We could not relocated the image in memory properly + // + return Status; + } + + // + // If we load our own PE COFF images the Windows debugger can not source + // level debug our code. If a valid PDB pointer exists usw it to load + // the *.dll file as a library using Windows* APIs. This allows + // source level debug. The image is still loaded and reloaced + // in the Framework memory space like on a real system (by the code above), + // but the entry point points into the DLL loaded by the code bellow. + // + + DllEntryPoint = NULL; + + // + // Load the DLL if it's not an EBC image. + // + if ((ImageContext->PdbPointer != NULL) && + (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC)) { + // + // Convert filename from ASCII to Unicode + // + DllFileName = AsciiToUnicode (ImageContext->PdbPointer, &Index); + + // + // Check that we have a valid filename + // + if (Index < 5 || DllFileName[Index - 4] != '.') { + free (DllFileName); + + // + // Never return an error if PeCoffLoaderRelocateImage() succeeded. + // The image will run, but we just can't source level debug. If we + // return an error the image will not run. + // + return EFI_SUCCESS; + } + // + // Replace .PDB with .DLL on the filename + // + DllFileName[Index - 3] = 'D'; + DllFileName[Index - 2] = 'L'; + DllFileName[Index - 1] = 'L'; + + // + // Load the .DLL file into the user process's address space for source + // level debug + // + Library = LoadLibraryEx (DllFileName, NULL, DONT_RESOLVE_DLL_REFERENCES); + if (Library != NULL) { + // + // InitializeDriver is the entry point we put in all our EFI DLL's. The + // DONT_RESOLVE_DLL_REFERENCES argument to LoadLIbraryEx() supresses the + // normal DLL entry point of DllMain, and prevents other modules that are + // referenced in side the DllFileName from being loaded. There is no error + // checking as the we can point to the PE32 image loaded by Tiano. This + // step is only needed for source level debuging + // + DllEntryPoint = (VOID *) (UINTN) GetProcAddress (Library, "InitializeDriver"); + + } + + if ((Library != NULL) && (DllEntryPoint != NULL)) { + AddModHandle (ImageContext, Library); + ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint; + wprintf (L"LoadLibraryEx (%s,\n NULL, DONT_RESOLVE_DLL_REFERENCES)\n", DllFileName); + } else { + wprintf (L"WARNING: No source level debug %s. \n", DllFileName); + } + + free (DllFileName); + } + + // + // Never return an error if PeCoffLoaderRelocateImage() succeeded. + // The image will run, but we just can't source level debug. If we + // return an error the image will not run. + // + return EFI_SUCCESS; +} + + +EFI_STATUS +EFIAPI +SecNt32PeCoffUnloadimage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + VOID *ModHandle; + + ModHandle = RemoveModeHandle (ImageContext); + if (ModHandle != NULL) { + FreeLibrary (ModHandle); + } + return EFI_SUCCESS; +} + +VOID +_ModuleEntryPoint ( + VOID + ) +{ +} diff --git a/EdkNt32Pkg/Sec/SecMain.h b/EdkNt32Pkg/Sec/SecMain.h new file mode 100644 index 0000000000..7943b837c8 --- /dev/null +++ b/EdkNt32Pkg/Sec/SecMain.h @@ -0,0 +1,570 @@ +/*++ + +Copyright (c) 2006, 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. + + +Module Name: + SecMain.h + +Abstract: + Include file for Windows API based SEC + +--*/ + +#include + + +#define STACK_SIZE 0x20000 + +typedef struct { + EFI_PHYSICAL_ADDRESS Address; + UINT64 Size; +} NT_FD_INFO; + +#define NT_SYSTEM_MEMORY_FILENAME_SIZE 40 + +typedef struct { + CHAR16 FileName[NT_SYSTEM_MEMORY_FILENAME_SIZE]; + EFI_PHYSICAL_ADDRESS Memory; + UINT64 Size; +} NT_SYSTEM_MEMORY; + + +#define MAX_PDB_NAME_TO_MOD_HANDLE_ARRAY_SIZE 0x100 + +typedef struct { + CHAR8 *PdbPointer; + VOID *ModHandle; +} PDB_NAME_TO_MOD_HANDLE; + + + + +EFI_STATUS +EFIAPI +SecWinNtPeiLoadFile ( + VOID *Pe32Data, // TODO: add IN/OUT modifier to Pe32Data + EFI_PHYSICAL_ADDRESS *ImageAddress, // TODO: add IN/OUT modifier to ImageAddress + UINT64 *ImageSize, // TODO: add IN/OUT modifier to ImageSize + EFI_PHYSICAL_ADDRESS *EntryPoint // TODO: add IN/OUT modifier to EntryPoint + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Pe32Data - TODO: add argument description + ImageAddress - TODO: add argument description + ImageSize - TODO: add argument description + EntryPoint - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +SecWinNtPeiAutoScan ( + IN UINTN Index, + OUT EFI_PHYSICAL_ADDRESS *MemoryBase, + OUT UINT64 *MemorySize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Index - TODO: add argument description + MemoryBase - TODO: add argument description + MemorySize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID * +EFIAPI +SecWinNtWinNtThunkAddress ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + InterfaceSize - TODO: add argument description + InterfaceBase - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +SecWinNtWinNtFwhAddress ( + IN OUT UINT64 *FwhSize, + IN OUT EFI_PHYSICAL_ADDRESS *FwhBase + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + FwhSize - TODO: add argument description + FwhBase - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +SecPeiReportStatusCode ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID * CallerId, + IN EFI_STATUS_CODE_DATA * Data OPTIONAL + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PeiServices - TODO: add argument description + CodeType - TODO: add argument description + Value - TODO: add argument description + Instance - TODO: add argument description + CallerId - TODO: add argument description + Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +INTN +EFIAPI +main ( + IN INTN Argc, + IN CHAR8 **Argv, + IN CHAR8 **Envp + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Argc - TODO: add argument description + Argv - TODO: add argument description + Envp - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +WinNtOpenFile ( + CHAR16 *FileName, + UINT32 MapSize, + DWORD CreationDispostion, + EFI_PHYSICAL_ADDRESS *BaseAddress, + UINT64 *Length + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + FileName - TODO: add argument description + MapSize - TODO: add argument description + CreationDispostion - TODO: add argument description + BaseAddress - TODO: add argument description + Length - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +VOID +SecLoadFromCore ( + IN UINTN LargestRegion, + IN UINTN LargestRegionSize, + IN UINTN BootFirmwareVolumeBase, + IN VOID *PeiCoreFile + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + LargestRegion - TODO: add argument description + LargestRegionSize - TODO: add argument description + BootFirmwareVolumeBase - TODO: add argument description + PeiCoreFile - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SecLoadFile ( + IN VOID *Pe32Data, + IN EFI_PHYSICAL_ADDRESS *ImageAddress, + IN UINT64 *ImageSize, + IN EFI_PHYSICAL_ADDRESS *EntryPoint + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Pe32Data - TODO: add argument description + ImageAddress - TODO: add argument description + ImageSize - TODO: add argument description + EntryPoint - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SecFfsFindPeiCore ( + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + OUT VOID **Pe32Data + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + FwVolHeader - TODO: add argument description + Pe32Data - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SecFfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SearchType - TODO: add argument description + FwVolHeader - TODO: add argument description + FileHeader - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +SecFfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + SectionType - TODO: add argument description + FfsFileHeader - TODO: add argument description + SectionData - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +SecWinNtPeCoffLoaderLoadAsDll ( + IN CHAR8 *PdbFileName, + IN VOID **ImageEntryPoint, + OUT VOID **ModHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + PdbFileName - TODO: add argument description + ImageEntryPoint - TODO: add argument description + ModHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +SecWinNtPeCoffLoaderFreeLibrary ( + OUT VOID *ModHandle + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ModHandle - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +SecWinNtFdAddress ( + IN UINTN Index, + IN OUT EFI_PHYSICAL_ADDRESS *FdBase, + IN OUT UINT64 *FdSize + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Index - TODO: add argument description + FdBase - TODO: add argument description + FdSize - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +GetImageReadFunction ( + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_PHYSICAL_ADDRESS *TopOfMemory + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + ImageContext - TODO: add argument description + TopOfMemory - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +SecImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + FileHandle - TODO: add argument description + FileOffset - TODO: add argument description + ReadSize - TODO: add argument description + Buffer - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +CHAR16 * +AsciiToUnicode ( + IN CHAR8 *Ascii, + IN UINTN *StrLen OPTIONAL + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + Ascii - TODO: add argument description + StrLen - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +UINTN +CountSeperatorsInString ( + IN const CHAR16 *String, + IN CHAR16 Seperator + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + String - TODO: add argument description + Seperator - TODO: add argument description + +Returns: + + TODO: add return values + +--*/ +; + +EFI_STATUS +EFIAPI +SecNt32PeCoffGetImageInfo ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +SecNt32PeCoffLoadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +SecNt32PeCoffRelocateImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +SecNt32PeCoffUnloadimage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + + +typedef struct { + EFI_PEI_PE_COFF_LOADER_PROTOCOL PeCoff; + VOID *ModHandle; +} EFI_PEI_PE_COFF_LOADER_PROTOCOL_INSTANCE; + +extern EFI_WIN_NT_THUNK_PROTOCOL *gWinNt; diff --git a/EdkNt32Pkg/Sec/SecMain.mbd b/EdkNt32Pkg/Sec/SecMain.mbd new file mode 100644 index 0000000000..f310571a7c --- /dev/null +++ b/EdkNt32Pkg/Sec/SecMain.mbd @@ -0,0 +1,38 @@ + + + + + SecMain + 4b837b03-6587-4d19-b82b-edfad836c0a0 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-14 17:04 + 2006-03-19 15:17 + + + BaseLib + BaseMemoryLib + BasePeCoffLib + BasePrintLib + BaseReportStatusCodeLibNull + BaseDebugLibNull + + diff --git a/EdkNt32Pkg/Sec/SecMain.msa b/EdkNt32Pkg/Sec/SecMain.msa new file mode 100644 index 0000000000..fd46656138 --- /dev/null +++ b/EdkNt32Pkg/Sec/SecMain.msa @@ -0,0 +1,96 @@ + + + + + SecMain + SEC + SEC + 4b837b03-6587-4d19-b82b-edfad836c0a0 + 0 + Component description file for NT32 Sec.Warning the [sources.*] does not work like you think!If you add a file you need to update the makefile in the NT32 build tipSEC_OBJECTS needs to get the OBJ of the new C file added in.We keep [sources.*] synced up with SEC_OBJECTS so dependencies workproperly.Libraries.Common does not work you must update SEC_OBJECTS in the platformmakefile + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-14 17:04 + 2006-03-19 15:17 + + + PeCoffLib + BaseLib + BaseMemoryLib + PrintLib + ReportStatusCodeLib + PcdLib + DebugLib + + + SecMain.c + FwVol.c + WinNtThunk.c + SecMain.h + + + MdePkg + EdkModulePkg + EdkNt32Pkg + + + NtThunk + NtAutoScan + NtFwh + StatusCode + NtPeiLoadFile + + + + PeiPeCoffLoader + + + + + + + + + + PcdWinNtCpuSpeed + 0x00001008 + VOID* + + + PcdWinNtMemorySize + 0x00001005 + VOID* + + + PcdWinNtFirmwareVolume + 0x00001009 + VOID* + + + PcdWinNtBootMode + 0x00001006 + UINT32 + + + + + + diff --git a/EdkNt32Pkg/Sec/SecMain_build.xml b/EdkNt32Pkg/Sec/SecMain_build.xml new file mode 100644 index 0000000000..b0436d385b --- /dev/null +++ b/EdkNt32Pkg/Sec/SecMain_build.xml @@ -0,0 +1,154 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "${LINK}" /LIBPATH:"${env.MSVCDir}\Lib" /LIBPATH:"${env.MSVCDir}\PlatformSdk\Lib" /NOLOGO /SUBSYSTEM:CONSOLE /NODEFAULTLIB /IGNORE:4086 /MAP /OPT:REF /DEBUG /MACHINE:I386 /LTCG Kernel32.lib MsvcRt.lib Gdi32.lib User32.lib Winmm.lib ${OBJECTS} ${LIBS} /base:0x10000000 /out:${BIN_DIR}\SecMain.exe /pdb:${DEST_DIR_DEBUG}\SecMain.pdb + + + + + + + + + diff --git a/EdkNt32Pkg/Sec/WinNtThunk.c b/EdkNt32Pkg/Sec/WinNtThunk.c new file mode 100644 index 0000000000..d064fae73d --- /dev/null +++ b/EdkNt32Pkg/Sec/WinNtThunk.c @@ -0,0 +1,178 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + WinNtThunk.c + +Abstract: + + Since the SEC is the only windows program in our emulation we + must use a Tiano mechanism to export Win32 APIs to other modules. + This is the role of the EFI_WIN_NT_THUNK_PROTOCOL. + + The mWinNtThunkTable exists so that a change to EFI_WIN_NT_THUNK_PROTOCOL + will cause an error in initializing the array if all the member functions + are not added. It looks like adding a element to end and not initializing + it may cause the table to be initaliized with the members at the end being + set to zero. This is bad as jumping to zero will case the NT32 to crash. + + All the member functions in mWinNtThunkTable are Win32 + API calls, so please reference Microsoft documentation. + + + gWinNt is a a public exported global that contains the initialized + data. + +--*/ + +#include "SecMain.h" + +// +// This pragma is needed for all the DLL entry points to be asigned to the array. +// if warning 4232 is not dissabled a warning will be generated as a DLL entry +// point could be modified dynamically. The SEC does not do that, so we must +// disable the warning so we can compile the SEC. The previous method was to +// asign each element in code. The disadvantage to that approach is it's harder +// to tell if all the elements have been initailized properly. +// +#pragma warning(disable : 4232) + +EFI_WIN_NT_THUNK_PROTOCOL mWinNtThunkTable = { + EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE, + GetProcAddress, + GetTickCount, + LoadLibraryEx, + FreeLibrary, + SetPriorityClass, + SetThreadPriority, + Sleep, + SuspendThread, + GetCurrentThread, + GetCurrentThreadId, + GetCurrentProcess, + CreateThread, + TerminateThread, + SendMessage, + ExitThread, + ResumeThread, + DuplicateHandle, + InitializeCriticalSection, + EnterCriticalSection, + LeaveCriticalSection, + DeleteCriticalSection, + TlsAlloc, + TlsFree, + TlsSetValue, + TlsGetValue, + CreateSemaphore, + WaitForSingleObject, + ReleaseSemaphore, + CreateConsoleScreenBuffer, + FillConsoleOutputAttribute, + FillConsoleOutputCharacter, + GetConsoleCursorInfo, + GetNumberOfConsoleInputEvents, + PeekConsoleInput, + ScrollConsoleScreenBuffer, + ReadConsoleInput, + SetConsoleActiveScreenBuffer, + SetConsoleCursorInfo, + SetConsoleCursorPosition, + SetConsoleScreenBufferSize, + SetConsoleTitleW, + WriteConsoleInput, + WriteConsoleOutput, + CreateFile, + DeviceIoControl, + CreateDirectory, + RemoveDirectory, + GetFileAttributes, + SetFileAttributes, + CreateFileMapping, + CloseHandle, + DeleteFile, + FindFirstFile, + FindNextFile, + FindClose, + FlushFileBuffers, + GetEnvironmentVariable, + GetLastError, + SetErrorMode, + GetStdHandle, + MapViewOfFileEx, + ReadFile, + SetEndOfFile, + SetFilePointer, + WriteFile, + GetFileInformationByHandle, + GetDiskFreeSpace, + GetDiskFreeSpaceEx, + MoveFile, + SetFileTime, + SystemTimeToFileTime, + FileTimeToLocalFileTime, + FileTimeToSystemTime, + GetSystemTime, + SetSystemTime, + GetLocalTime, + SetLocalTime, + GetTimeZoneInformation, + SetTimeZoneInformation, + timeSetEvent, + timeKillEvent, + ClearCommError, + EscapeCommFunction, + GetCommModemStatus, + GetCommState, + SetCommState, + PurgeComm, + SetCommTimeouts, + ExitProcess, + swprintf, + GetDesktopWindow, + GetForegroundWindow, + CreateWindowEx, + ShowWindow, + UpdateWindow, + DestroyWindow, + InvalidateRect, + GetWindowDC, + GetClientRect, + AdjustWindowRect, + SetDIBitsToDevice, + BitBlt, + GetDC, + ReleaseDC, + RegisterClassEx, + UnregisterClass, + BeginPaint, + EndPaint, + PostQuitMessage, + DefWindowProc, + LoadIcon, + LoadCursor, + GetStockObject, + SetViewportOrgEx, + SetWindowOrgEx, + MoveWindow, + GetWindowRect, + GetMessage, + TranslateMessage, + DispatchMessage, + GetProcessHeap, + HeapAlloc, + HeapFree +}; + +#pragma warning(default : 4232) + +EFI_WIN_NT_THUNK_PROTOCOL *gWinNt = &mWinNtThunkTable; diff --git a/EdkNt32Pkg/Sec/build.xml b/EdkNt32Pkg/Sec/build.xml new file mode 100644 index 0000000000..4140a8ab0f --- /dev/null +++ b/EdkNt32Pkg/Sec/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkNt32Pkg/build.xml b/EdkNt32Pkg/build.xml new file mode 100644 index 0000000000..d6ca4b81b5 --- /dev/null +++ b/EdkNt32Pkg/build.xml @@ -0,0 +1,105 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cd ${WORKSPACE_DIR}\EdkNt32Pkg\Build\DEBUG\IA32 + SecMain.exe + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EdkNt32Pkg/genbuildfile.xml b/EdkNt32Pkg/genbuildfile.xml new file mode 100644 index 0000000000..77702ef12d --- /dev/null +++ b/EdkNt32Pkg/genbuildfile.xml @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/EdkNt32Pkg/run.cmd b/EdkNt32Pkg/run.cmd new file mode 100644 index 0000000000..167cfc9685 --- /dev/null +++ b/EdkNt32Pkg/run.cmd @@ -0,0 +1,18 @@ +@REM +@REM Copyright (c) 2006, Intel Corporation +@REM All rights reserved. This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@REM +@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +@REM + +@echo off +pushd . +cd Build\DEBUG\IA32 +SecMain.exe +popd +@echo on + diff --git a/EdkShellBinPkg/EdkShellBinPkg.spd b/EdkShellBinPkg/EdkShellBinPkg.spd new file mode 100644 index 0000000000..439ecbc69a --- /dev/null +++ b/EdkShellBinPkg/EdkShellBinPkg.spd @@ -0,0 +1,40 @@ + + + + + EdkShellBinPkg + d4266a1b-1d38-4116-93ae-60dc3e2012a6 + 0 + Reference package showing multiple binaries + This package contains multiple binary drivers, using only one MSA, one MBD and a single SPD. + Copyright (c) 2006, 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. + + 2006-03-05 10:13 + 2006-03-18 20:23 + http://www.TianoCore.org + BINARY + true + false + + + + bin/Shell.msa + + + diff --git a/EdkShellBinPkg/bin/Shell.mbd b/EdkShellBinPkg/bin/Shell.mbd new file mode 100644 index 0000000000..ad7211e6fc --- /dev/null +++ b/EdkShellBinPkg/bin/Shell.mbd @@ -0,0 +1,33 @@ + + + + + Shell + c57ad6b7-0515-40a8-9d21-551652854e37 + EDK_RELEASE_VERSION 0x00020000 + + This is a binary package containing multiple binary files, however there is + only a single MSA and MBD file. + + + Copyright (c) 2004-2006, 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. + + 2006-03-17 20:56 + + diff --git a/EdkShellBinPkg/bin/Shell.msa b/EdkShellBinPkg/bin/Shell.msa new file mode 100644 index 0000000000..5fe1f2a527 --- /dev/null +++ b/EdkShellBinPkg/bin/Shell.msa @@ -0,0 +1,47 @@ + + + + + Shell + UEFI_APPLICATION + APPLICATION + c57ad6b7-0515-40a8-9d21-551652854e37 + 0x00090000 + Component description file for EFI Shell module. + + This is a binary package containing multiple binary files, however there is + only a single MSA and MBD file. + + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-17 20:56 + + + Shell_Full.efi + + + Shell_Full.efi + + + diff --git a/EdkShellBinPkg/bin/build.xml b/EdkShellBinPkg/bin/build.xml new file mode 100644 index 0000000000..807380107d --- /dev/null +++ b/EdkShellBinPkg/bin/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EdkShellBinPkg/bin/ia32/Apps/Attrib.efi b/EdkShellBinPkg/bin/ia32/Apps/Attrib.efi new file mode 100644 index 0000000000..c3a45f2874 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Attrib.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Cls.efi b/EdkShellBinPkg/bin/ia32/Apps/Cls.efi new file mode 100644 index 0000000000..489a67866b Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Cls.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Cp.efi b/EdkShellBinPkg/bin/ia32/Apps/Cp.efi new file mode 100644 index 0000000000..af8be91b1f Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Cp.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Date.efi b/EdkShellBinPkg/bin/ia32/Apps/Date.efi new file mode 100644 index 0000000000..ea0a8028e6 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Date.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Dblk.efi b/EdkShellBinPkg/bin/ia32/Apps/Dblk.efi new file mode 100644 index 0000000000..055dedf231 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Dblk.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Devices.efi b/EdkShellBinPkg/bin/ia32/Apps/Devices.efi new file mode 100644 index 0000000000..40af8f25c1 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Devices.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Devtree.efi b/EdkShellBinPkg/bin/ia32/Apps/Devtree.efi new file mode 100644 index 0000000000..7ec5ad34fa Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Devtree.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Drivers.efi b/EdkShellBinPkg/bin/ia32/Apps/Drivers.efi new file mode 100644 index 0000000000..5523691ffd Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Drivers.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Drvcfg.efi b/EdkShellBinPkg/bin/ia32/Apps/Drvcfg.efi new file mode 100644 index 0000000000..c3fba1f320 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Drvcfg.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Drvdiag.efi b/EdkShellBinPkg/bin/ia32/Apps/Drvdiag.efi new file mode 100644 index 0000000000..7ec7aeb9b6 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Drvdiag.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Guid.efi b/EdkShellBinPkg/bin/ia32/Apps/Guid.efi new file mode 100644 index 0000000000..00ec9a077e Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Guid.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/IpConfig.efi b/EdkShellBinPkg/bin/ia32/Apps/IpConfig.efi new file mode 100644 index 0000000000..d121b0a028 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/IpConfig.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Load.efi b/EdkShellBinPkg/bin/ia32/Apps/Load.efi new file mode 100644 index 0000000000..0c1459fa96 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Load.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/LoadPciRom.efi b/EdkShellBinPkg/bin/ia32/Apps/LoadPciRom.efi new file mode 100644 index 0000000000..0a14c710b8 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/LoadPciRom.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Ls.efi b/EdkShellBinPkg/bin/ia32/Apps/Ls.efi new file mode 100644 index 0000000000..606099bac1 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Ls.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Mkdir.efi b/EdkShellBinPkg/bin/ia32/Apps/Mkdir.efi new file mode 100644 index 0000000000..79ddd6dd48 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Mkdir.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Mount.efi b/EdkShellBinPkg/bin/ia32/Apps/Mount.efi new file mode 100644 index 0000000000..43e4c22220 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Mount.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Mv.efi b/EdkShellBinPkg/bin/ia32/Apps/Mv.efi new file mode 100644 index 0000000000..fa4b309801 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Mv.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/NShell.efi b/EdkShellBinPkg/bin/ia32/Apps/NShell.efi new file mode 100644 index 0000000000..9d1b2d12a8 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/NShell.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Openinfo.efi b/EdkShellBinPkg/bin/ia32/Apps/Openinfo.efi new file mode 100644 index 0000000000..b73b3e6c70 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Openinfo.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Resets.efi b/EdkShellBinPkg/bin/ia32/Apps/Resets.efi new file mode 100644 index 0000000000..ec6a92a449 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Resets.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Rm.efi b/EdkShellBinPkg/bin/ia32/Apps/Rm.efi new file mode 100644 index 0000000000..17fe4be8e8 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Rm.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/SmbiosView.efi b/EdkShellBinPkg/bin/ia32/Apps/SmbiosView.efi new file mode 100644 index 0000000000..b571eeee4e Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/SmbiosView.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/TelnetMgmt.efi b/EdkShellBinPkg/bin/ia32/Apps/TelnetMgmt.efi new file mode 100644 index 0000000000..9183f3b931 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/TelnetMgmt.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Time.efi b/EdkShellBinPkg/bin/ia32/Apps/Time.efi new file mode 100644 index 0000000000..2266815a09 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Time.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Touch.efi b/EdkShellBinPkg/bin/ia32/Apps/Touch.efi new file mode 100644 index 0000000000..af485b323c Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Touch.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Type.efi b/EdkShellBinPkg/bin/ia32/Apps/Type.efi new file mode 100644 index 0000000000..1c73377258 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Type.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Unload.efi b/EdkShellBinPkg/bin/ia32/Apps/Unload.efi new file mode 100644 index 0000000000..68173480d6 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Unload.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Ver.efi b/EdkShellBinPkg/bin/ia32/Apps/Ver.efi new file mode 100644 index 0000000000..c4f6bef838 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Ver.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/Vol.efi b/EdkShellBinPkg/bin/ia32/Apps/Vol.efi new file mode 100644 index 0000000000..ed1272c013 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/Vol.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/comp.efi b/EdkShellBinPkg/bin/ia32/Apps/comp.efi new file mode 100644 index 0000000000..a07d009422 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/comp.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/dmem.efi b/EdkShellBinPkg/bin/ia32/Apps/dmem.efi new file mode 100644 index 0000000000..21fd2bd98a Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/dmem.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/dmpstore.efi b/EdkShellBinPkg/bin/ia32/Apps/dmpstore.efi new file mode 100644 index 0000000000..ff5d478efb Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/dmpstore.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/edit.efi b/EdkShellBinPkg/bin/ia32/Apps/edit.efi new file mode 100644 index 0000000000..d3bc52aaad Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/edit.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/eficompress.efi b/EdkShellBinPkg/bin/ia32/Apps/eficompress.efi new file mode 100644 index 0000000000..17dc9b38b6 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/eficompress.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/efidecompress.efi b/EdkShellBinPkg/bin/ia32/Apps/efidecompress.efi new file mode 100644 index 0000000000..8b5102190d Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/efidecompress.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/err.efi b/EdkShellBinPkg/bin/ia32/Apps/err.efi new file mode 100644 index 0000000000..ffc65b6d96 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/err.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/hexedit.efi b/EdkShellBinPkg/bin/ia32/Apps/hexedit.efi new file mode 100644 index 0000000000..ca7d54df6a Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/hexedit.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/legacyboot.efi b/EdkShellBinPkg/bin/ia32/Apps/legacyboot.efi new file mode 100644 index 0000000000..98e49c3389 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/legacyboot.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/loadfv.efi b/EdkShellBinPkg/bin/ia32/Apps/loadfv.efi new file mode 100644 index 0000000000..9c24b10347 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/loadfv.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/mem.efi b/EdkShellBinPkg/bin/ia32/Apps/mem.efi new file mode 100644 index 0000000000..551ea79046 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/mem.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/memmap.efi b/EdkShellBinPkg/bin/ia32/Apps/memmap.efi new file mode 100644 index 0000000000..e7ac7d5c16 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/memmap.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/mm.efi b/EdkShellBinPkg/bin/ia32/Apps/mm.efi new file mode 100644 index 0000000000..564ed828ff Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/mm.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/mode.efi b/EdkShellBinPkg/bin/ia32/Apps/mode.efi new file mode 100644 index 0000000000..004e0f47a1 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/mode.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/pci.efi b/EdkShellBinPkg/bin/ia32/Apps/pci.efi new file mode 100644 index 0000000000..e10e432e94 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/pci.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/sermode.efi b/EdkShellBinPkg/bin/ia32/Apps/sermode.efi new file mode 100644 index 0000000000..a2f66b46c7 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/sermode.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/stall.efi b/EdkShellBinPkg/bin/ia32/Apps/stall.efi new file mode 100644 index 0000000000..5884e51d0f Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/stall.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Apps/timezone.efi b/EdkShellBinPkg/bin/ia32/Apps/timezone.efi new file mode 100644 index 0000000000..625b4fc7f2 Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Apps/timezone.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Shell.efi b/EdkShellBinPkg/bin/ia32/Shell.efi new file mode 100644 index 0000000000..a1aa70945f Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Shell.efi differ diff --git a/EdkShellBinPkg/bin/ia32/Shell_Full.efi b/EdkShellBinPkg/bin/ia32/Shell_Full.efi new file mode 100644 index 0000000000..b90893717e Binary files /dev/null and b/EdkShellBinPkg/bin/ia32/Shell_Full.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Attrib.efi b/EdkShellBinPkg/bin/ipf/Apps/Attrib.efi new file mode 100644 index 0000000000..589c2d84df Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Attrib.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Cls.efi b/EdkShellBinPkg/bin/ipf/Apps/Cls.efi new file mode 100644 index 0000000000..84f34015e0 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Cls.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Cp.efi b/EdkShellBinPkg/bin/ipf/Apps/Cp.efi new file mode 100644 index 0000000000..3137ac65fa Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Cp.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Date.efi b/EdkShellBinPkg/bin/ipf/Apps/Date.efi new file mode 100644 index 0000000000..77631c6caa Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Date.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Dblk.efi b/EdkShellBinPkg/bin/ipf/Apps/Dblk.efi new file mode 100644 index 0000000000..553fce54fe Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Dblk.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Devices.efi b/EdkShellBinPkg/bin/ipf/Apps/Devices.efi new file mode 100644 index 0000000000..840ab76584 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Devices.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Devtree.efi b/EdkShellBinPkg/bin/ipf/Apps/Devtree.efi new file mode 100644 index 0000000000..09e9d2bf63 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Devtree.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Drivers.efi b/EdkShellBinPkg/bin/ipf/Apps/Drivers.efi new file mode 100644 index 0000000000..7b41202ef6 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Drivers.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Drvcfg.efi b/EdkShellBinPkg/bin/ipf/Apps/Drvcfg.efi new file mode 100644 index 0000000000..b50987f9e2 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Drvcfg.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Drvdiag.efi b/EdkShellBinPkg/bin/ipf/Apps/Drvdiag.efi new file mode 100644 index 0000000000..8ab4ee01c9 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Drvdiag.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Guid.efi b/EdkShellBinPkg/bin/ipf/Apps/Guid.efi new file mode 100644 index 0000000000..cd720233da Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Guid.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/IpConfig.efi b/EdkShellBinPkg/bin/ipf/Apps/IpConfig.efi new file mode 100644 index 0000000000..b42161066f Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/IpConfig.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Load.efi b/EdkShellBinPkg/bin/ipf/Apps/Load.efi new file mode 100644 index 0000000000..ee5b2f9031 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Load.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/LoadPciRom.efi b/EdkShellBinPkg/bin/ipf/Apps/LoadPciRom.efi new file mode 100644 index 0000000000..892787fd13 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/LoadPciRom.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Ls.efi b/EdkShellBinPkg/bin/ipf/Apps/Ls.efi new file mode 100644 index 0000000000..2c051942aa Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Ls.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Mkdir.efi b/EdkShellBinPkg/bin/ipf/Apps/Mkdir.efi new file mode 100644 index 0000000000..f738570ca5 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Mkdir.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Mount.efi b/EdkShellBinPkg/bin/ipf/Apps/Mount.efi new file mode 100644 index 0000000000..a26a5cd200 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Mount.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Mv.efi b/EdkShellBinPkg/bin/ipf/Apps/Mv.efi new file mode 100644 index 0000000000..8410dca2a3 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Mv.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/NShell.efi b/EdkShellBinPkg/bin/ipf/Apps/NShell.efi new file mode 100644 index 0000000000..a14252cc3e Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/NShell.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Openinfo.efi b/EdkShellBinPkg/bin/ipf/Apps/Openinfo.efi new file mode 100644 index 0000000000..3b4484737f Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Openinfo.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Resets.efi b/EdkShellBinPkg/bin/ipf/Apps/Resets.efi new file mode 100644 index 0000000000..b2cd1542f3 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Resets.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Rm.efi b/EdkShellBinPkg/bin/ipf/Apps/Rm.efi new file mode 100644 index 0000000000..bba6bbcd26 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Rm.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/SmbiosView.efi b/EdkShellBinPkg/bin/ipf/Apps/SmbiosView.efi new file mode 100644 index 0000000000..95c7d9fb5d Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/SmbiosView.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/TelnetMgmt.efi b/EdkShellBinPkg/bin/ipf/Apps/TelnetMgmt.efi new file mode 100644 index 0000000000..4c0158c3d1 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/TelnetMgmt.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Time.efi b/EdkShellBinPkg/bin/ipf/Apps/Time.efi new file mode 100644 index 0000000000..1944c91103 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Time.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Touch.efi b/EdkShellBinPkg/bin/ipf/Apps/Touch.efi new file mode 100644 index 0000000000..ed652a583b Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Touch.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Type.efi b/EdkShellBinPkg/bin/ipf/Apps/Type.efi new file mode 100644 index 0000000000..c7ad4ab8bc Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Type.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Unload.efi b/EdkShellBinPkg/bin/ipf/Apps/Unload.efi new file mode 100644 index 0000000000..03f637a4e7 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Unload.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Ver.efi b/EdkShellBinPkg/bin/ipf/Apps/Ver.efi new file mode 100644 index 0000000000..846421f28b Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Ver.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/Vol.efi b/EdkShellBinPkg/bin/ipf/Apps/Vol.efi new file mode 100644 index 0000000000..dfc321953a Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/Vol.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/comp.efi b/EdkShellBinPkg/bin/ipf/Apps/comp.efi new file mode 100644 index 0000000000..49ef20e1d5 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/comp.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/dmem.efi b/EdkShellBinPkg/bin/ipf/Apps/dmem.efi new file mode 100644 index 0000000000..1ec5813868 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/dmem.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/dmpstore.efi b/EdkShellBinPkg/bin/ipf/Apps/dmpstore.efi new file mode 100644 index 0000000000..79ed4c4d9a Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/dmpstore.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/edit.efi b/EdkShellBinPkg/bin/ipf/Apps/edit.efi new file mode 100644 index 0000000000..dd21c6699d Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/edit.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/eficompress.efi b/EdkShellBinPkg/bin/ipf/Apps/eficompress.efi new file mode 100644 index 0000000000..89328be0be Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/eficompress.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/efidecompress.efi b/EdkShellBinPkg/bin/ipf/Apps/efidecompress.efi new file mode 100644 index 0000000000..565ccccc9f Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/efidecompress.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/err.efi b/EdkShellBinPkg/bin/ipf/Apps/err.efi new file mode 100644 index 0000000000..1b59ba67b2 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/err.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/hexedit.efi b/EdkShellBinPkg/bin/ipf/Apps/hexedit.efi new file mode 100644 index 0000000000..d8001e3ff9 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/hexedit.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/mem.efi b/EdkShellBinPkg/bin/ipf/Apps/mem.efi new file mode 100644 index 0000000000..5a3cc910d3 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/mem.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/memmap.efi b/EdkShellBinPkg/bin/ipf/Apps/memmap.efi new file mode 100644 index 0000000000..61fbe7e7e2 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/memmap.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/mm.efi b/EdkShellBinPkg/bin/ipf/Apps/mm.efi new file mode 100644 index 0000000000..f0e06b6091 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/mm.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/mode.efi b/EdkShellBinPkg/bin/ipf/Apps/mode.efi new file mode 100644 index 0000000000..3ba30ca2f4 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/mode.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/pci.efi b/EdkShellBinPkg/bin/ipf/Apps/pci.efi new file mode 100644 index 0000000000..9fe76ef0b6 Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/pci.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/sermode.efi b/EdkShellBinPkg/bin/ipf/Apps/sermode.efi new file mode 100644 index 0000000000..8e33a0d1dd Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/sermode.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/stall.efi b/EdkShellBinPkg/bin/ipf/Apps/stall.efi new file mode 100644 index 0000000000..8a4202e31e Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/stall.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Apps/timezone.efi b/EdkShellBinPkg/bin/ipf/Apps/timezone.efi new file mode 100644 index 0000000000..d1cc96e80b Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Apps/timezone.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Shell.efi b/EdkShellBinPkg/bin/ipf/Shell.efi new file mode 100644 index 0000000000..b90893717e Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Shell.efi differ diff --git a/EdkShellBinPkg/bin/ipf/Shell_Full.efi b/EdkShellBinPkg/bin/ipf/Shell_Full.efi new file mode 100644 index 0000000000..b4b6cc6dff Binary files /dev/null and b/EdkShellBinPkg/bin/ipf/Shell_Full.efi differ diff --git a/EdkShellBinPkg/genbuildfile.xml b/EdkShellBinPkg/genbuildfile.xml new file mode 100644 index 0000000000..81a2900a92 --- /dev/null +++ b/EdkShellBinPkg/genbuildfile.xml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/MdePkg/Include/Base.h b/MdePkg/Include/Base.h new file mode 100644 index 0000000000..99ed686644 --- /dev/null +++ b/MdePkg/Include/Base.h @@ -0,0 +1,28 @@ +/** @file + + Root include file for Mde Package Base type modules + + This is the include file for any module of type base. Base modules only use + types defined via this include file and can be ported easily to any + environment. There are a set of base libraries in the Mde Package that can + be used to implement base modules. + +Copyright (c) 2006, 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 __BASE_H__ +#define __BASE_H__ + +#include +#include + +#endif diff --git a/MdePkg/Include/Common/BaseTypes.h b/MdePkg/Include/Common/BaseTypes.h new file mode 100644 index 0000000000..86c3c71fb3 --- /dev/null +++ b/MdePkg/Include/Common/BaseTypes.h @@ -0,0 +1,206 @@ +/** @file + Processor or Compiler specific defines for all supported processors. + + This file is stand alone self consistent set of definitions. + + Copyright (c) 2006, 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. + + Module Name: BaseTypes.h + +**/ + +#ifndef __BASE_TYPES_H__ +#define __BASE_TYPES_H__ + +// +// Include processor specific binding +// +#include + +#define MEMORY_FENCE() MemoryFence () +#define BREAKPOINT() CpuBreakpoint () +#define DEADLOOP() CpuDeadLoop () + +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} GUID; + + +// +// Modifiers to absract standard types to aid in debug of problems +// +#define CONST const +#define STATIC static +#define VOID void + +// +// Modifiers for Data Types used to self document code. +// This concept is borrowed for UEFI specification. +// +#ifndef IN +// +// Some other envirnments use this construct, so #ifndef to prevent +// mulitple definition. +// +#define IN +#define OUT +#define OPTIONAL +#endif + +// +// Constants. They may exist in other build structures, so #ifndef them. +// +#ifndef TRUE +// +// BugBug: UEFI specification claims 1 and 0. We are concerned about the +// complier portability so we did it this way. +// +#define TRUE ((BOOLEAN)(1==1)) +#endif + +#ifndef FALSE +#define FALSE ((BOOLEAN)(0==1)) +#endif + +#ifndef NULL +#define NULL ((VOID *) 0) +#endif + +// +// Support for variable length argument lists using the ANSI standard. +// +// Since we are using the ANSI standard we used the standard nameing and +// did not folow the coding convention +// +// VA_LIST - typedef for argument list. +// VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use. +// VA_END (VA_LIST Marker) - Clear Marker +// VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argumnet from +// the ... list. You must know the size and pass it in this macro. +// +// example: +// +// UINTN +// ExampleVarArg ( +// IN UINTN NumberOfArgs, +// ... +// ) +// { +// VA_LIST Marker; +// UINTN Index; +// UINTN Result; +// +// // +// // Initialize the Marker +// // +// VA_START (Marker, NumberOfArgs); +// for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) { +// // +// // The ... list is a series of UINTN values, so average them up. +// // +// Result += VA_ARG (Marker, UINTN); +// } +// +// VA_END (Marker); +// return Result +// } +// + +#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1)) + +// +// Also support coding convention rules for var arg macros +// +#ifndef VA_START + +typedef CHAR8 *VA_LIST; +#define VA_START(ap, v) (ap = (VA_LIST) & (v) + _INT_SIZE_OF (v)) +#define VA_ARG(ap, t) (*(t *) ((ap += _INT_SIZE_OF (t)) - _INT_SIZE_OF (t))) +#define VA_END(ap) (ap = (VA_LIST) 0) + +#endif + +/// +/// CONTAINING_RECORD - returns a pointer to the structure +/// from one of it's elements. +/// +#define _CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field))) + +/// +/// ALIGN_POINTER - aligns a pointer to the lowest boundry +/// +#define ALIGN_POINTER(p, s) ((VOID *) ((p) + (((s) - ((UINTN) (p))) & ((s) - 1)))) + +/// +/// ALIGN_VARIABLE - aligns a variable up to the next natural boundry for int size of a processor +/// +#define ALIGN_VARIABLE(Value, Adjustment) \ + Adjustment = 0U; \ + if ((UINTN) (Value) % sizeof (UINTN)) { \ + (Adjustment) = (UINTN)(sizeof (UINTN) - ((UINTN) (Value) % sizeof (UINTN))); \ + } \ + (Value) = (UINTN)((UINTN) (Value) + (UINTN) (Adjustment)) + +// +// EFI Error Codes common to all execution phases +// + +typedef INTN RETURN_STATUS; + +/// +/// Set the upper bit to indicate EFI Error. +/// +#define ENCODE_ERROR(a) (MAX_BIT | (a)) + +#define ENCODE_WARNING(a) (a) +#define RETURN_ERROR(a) ((a) < 0) + +#define RETURN_SUCCESS 0 +#define RETURN_LOAD_ERROR ENCODE_ERROR (1) +#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2) +#define RETURN_UNSUPPORTED ENCODE_ERROR (3) +#define RETURN_BAD_BUFFER_SIZE ENCODE_ERROR (4) +#define RETURN_BUFFER_TOO_SMALL ENCODE_ERROR (5) +#define RETURN_NOT_READY ENCODE_ERROR (6) +#define RETURN_DEVICE_ERROR ENCODE_ERROR (7) +#define RETURN_WRITE_PROTECTED ENCODE_ERROR (8) +#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9) +#define RETURN_VOLUME_CORRUPTED ENCODE_ERROR (10) +#define RETURN_VOLUME_FULL ENCODE_ERROR (11) +#define RETURN_NO_MEDIA ENCODE_ERROR (12) +#define RETURN_MEDIA_CHANGED ENCODE_ERROR (13) +#define RETURN_NOT_FOUND ENCODE_ERROR (14) +#define RETURN_ACCESS_DENIED ENCODE_ERROR (15) +#define RETURN_NO_RESPONSE ENCODE_ERROR (16) +#define RETURN_NO_MAPPING ENCODE_ERROR (17) +#define RETURN_TIMEOUT ENCODE_ERROR (18) +#define RETURN_NOT_STARTED ENCODE_ERROR (19) +#define RETURN_ALREADY_STARTED ENCODE_ERROR (20) +#define RETURN_ABORTED ENCODE_ERROR (21) +#define RETURN_ICMP_ERROR ENCODE_ERROR (22) +#define RETURN_TFTP_ERROR ENCODE_ERROR (23) +#define RETURN_PROTOCOL_ERROR ENCODE_ERROR (24) +#define RETURN_INCOMPATIBLE_VERSION ENCODE_ERROR (25) +#define RETURN_SECURITY_VIOLATION ENCODE_ERROR (26) +#define RETURN_CRC_ERROR ENCODE_ERROR (27) +#define RETURN_END_OF_MEDIA ENCODE_ERROR (28) +#define RETURN_END_OF_FILE ENCODE_ERROR (31) + +#define RETURN_WARN_UNKNOWN_GLYPH ENCODE_WARNING (1) +#define RETURN_WARN_DELETE_FAILURE ENCODE_WARNING (2) +#define RETURN_WARN_WRITE_FAILURE ENCODE_WARNING (3) +#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4) + +typedef UINT64 PHYSICAL_ADDRESS; + +#endif diff --git a/MdePkg/Include/Common/BootMode.h b/MdePkg/Include/Common/BootMode.h new file mode 100644 index 0000000000..2f2c516d10 --- /dev/null +++ b/MdePkg/Include/Common/BootMode.h @@ -0,0 +1,37 @@ +/** @file + This includes for the Boot mode information. + + Copyright (c) 2006, 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. + + Module Name: BootMode.h + + @par Revision Reference: + These definitions are from PeiCis 0.91 spec. + +**/ + +#ifndef __EFI_BOOT_MODE_H__ +#define __EFI_BOOT_MODE_H__ + +#define BOOT_WITH_FULL_CONFIGURATION 0x00 +#define BOOT_WITH_MINIMAL_CONFIGURATION 0x01 +#define BOOT_ASSUMING_NO_CONFIGURATION_CHANGES 0x02 +#define BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS 0x03 +#define BOOT_WITH_DEFAULT_SETTINGS 0x04 +#define BOOT_ON_S4_RESUME 0x05 +#define BOOT_ON_S5_RESUME 0x06 +#define BOOT_ON_S2_RESUME 0x10 +#define BOOT_ON_S3_RESUME 0x11 +#define BOOT_ON_FLASH_UPDATE 0x12 +#define BOOT_IN_RECOVERY_MODE 0x20 +#define BOOT_IN_RECOVERY_MODE_MASK 0x40 +#define BOOT_SPECIAL_MASK 0x80 + +#endif diff --git a/MdePkg/Include/Common/BootScript.h b/MdePkg/Include/Common/BootScript.h new file mode 100644 index 0000000000..12bcc5bef7 --- /dev/null +++ b/MdePkg/Include/Common/BootScript.h @@ -0,0 +1,198 @@ +/** @file + This file declares the related BootScript definitions and some SMBus definitions. + + Copyright (c) 2006, 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. + + Module Name: BootScript.h + + @par Revision Reference: + These definitions are defined in BootScript Spec 0.91 and SmBus PPI spec 0.9. + +**/ + +#ifndef _EFI_SCRIPT_H_ +#define _EFI_SCRIPT_H_ + +#define EFI_ACPI_S3_RESUME_SCRIPT_TABLE 0x00 + +// +// Boot Script Opcode Definitions +// + +#define EFI_BOOT_SCRIPT_IO_WRITE_OPCODE 0x00 +#define EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE 0x01 +#define EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE 0x02 +#define EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE 0x03 +#define EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE 0x04 +#define EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE 0x05 +#define EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE 0x06 +#define EFI_BOOT_SCRIPT_STALL_OPCODE 0x07 +#define EFI_BOOT_SCRIPT_DISPATCH_OPCODE 0x08 + +#define EFI_BOOT_SCRIPT_TABLE_OPCODE 0xAA +#define EFI_BOOT_SCRIPT_TERMINATE_OPCODE 0xFF + +// +// EFI Boot Script Width +// +typedef enum { + EfiBootScriptWidthUint8, + EfiBootScriptWidthUint16, + EfiBootScriptWidthUint32, + EfiBootScriptWidthUint64, + EfiBootScriptWidthFifoUint8, + EfiBootScriptWidthFifoUint16, + EfiBootScriptWidthFifoUint32, + EfiBootScriptWidthFifoUint64, + EfiBootScriptWidthFillUint8, + EfiBootScriptWidthFillUint16, + EfiBootScriptWidthFillUint32, + EfiBootScriptWidthFillUint64, + EfiBootScriptWidthMaximum +} EFI_BOOT_SCRIPT_WIDTH; + +// +// EFI Smbus Device Address, Smbus Device Command, Smbus Operation +// +typedef struct { + UINTN SmbusDeviceAddress : 7; +} EFI_SMBUS_DEVICE_ADDRESS; + +typedef UINTN EFI_SMBUS_DEVICE_COMMAND; + +typedef enum _EFI_SMBUS_OPERATION +{ + EfiSmbusQuickRead, + EfiSmbusQuickWrite, + EfiSmbusReceiveByte, + EfiSmbusSendByte, + EfiSmbusReadByte, + EfiSmbusWriteByte, + EfiSmbusReadWord, + EfiSmbusWriteWord, + EfiSmbusReadBlock, + EfiSmbusWriteBlock, + EfiSmbusProcessCall, + EfiSmbusBWBRProcessCall +} EFI_SMBUS_OPERATION; + +// +// Boot Script Opcode Header Structure Definitions +// + +typedef struct { + UINT16 OpCode; + UINT8 Length; +} EFI_BOOT_SCRIPT_GENERIC_HEADER; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + UINT16 Version; + UINT32 TableLength; + UINT16 Reserved[2]; +} EFI_BOOT_SCRIPT_TABLE_HEADER; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + EFI_BOOT_SCRIPT_WIDTH Width; +} EFI_BOOT_SCRIPT_COMMON_HEADER; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + EFI_BOOT_SCRIPT_WIDTH Width; + UINTN Count; + UINT64 Address; +} EFI_BOOT_SCRIPT_IO_WRITE; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + EFI_BOOT_SCRIPT_WIDTH Width; + UINT64 Address; +} EFI_BOOT_SCRIPT_IO_READ_WRITE; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + EFI_BOOT_SCRIPT_WIDTH Width; + UINTN Count; + UINT64 Address; +} EFI_BOOT_SCRIPT_MEM_WRITE; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + EFI_BOOT_SCRIPT_WIDTH Width; + UINT64 Address; +} EFI_BOOT_SCRIPT_MEM_READ_WRITE; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + EFI_BOOT_SCRIPT_WIDTH Width; + UINTN Count; + UINT64 Address; +} EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + EFI_BOOT_SCRIPT_WIDTH Width; + UINT64 Address; +} EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + EFI_SMBUS_DEVICE_ADDRESS SlaveAddress; + EFI_SMBUS_DEVICE_COMMAND Command; + EFI_SMBUS_OPERATION Operation; + BOOLEAN PecCheck; + UINTN DataSize; +} EFI_BOOT_SCRIPT_SMBUS_EXECUTE; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + UINTN Duration; +} EFI_BOOT_SCRIPT_STALL; + +typedef struct { + UINT16 OpCode; + UINT8 Length; + EFI_PHYSICAL_ADDRESS EntryPoint; +} EFI_BOOT_SCRIPT_DISPATCH; + +typedef struct { + UINT16 OpCode; + UINT8 Length; +} EFI_BOOT_SCRIPT_TERMINATE; + +typedef union { + EFI_BOOT_SCRIPT_GENERIC_HEADER *Header; + EFI_BOOT_SCRIPT_TABLE_HEADER *TableInfo; + EFI_BOOT_SCRIPT_IO_WRITE *IoWrite; + EFI_BOOT_SCRIPT_IO_READ_WRITE *IoReadWrite; + EFI_BOOT_SCRIPT_MEM_WRITE *MemWrite; + EFI_BOOT_SCRIPT_MEM_READ_WRITE *MemReadWrite; + EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE *PciWrite; + EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE *PciReadWrite; + EFI_BOOT_SCRIPT_SMBUS_EXECUTE *SmbusExecute; + EFI_BOOT_SCRIPT_STALL *Stall; + EFI_BOOT_SCRIPT_DISPATCH *Dispatch; + EFI_BOOT_SCRIPT_TERMINATE *Terminate; + EFI_BOOT_SCRIPT_COMMON_HEADER *CommonHeader; + UINT8 *Raw; +} BOOT_SCRIPT_POINTERS; + +#endif diff --git a/MdePkg/Include/Common/Capsule.h b/MdePkg/Include/Common/Capsule.h new file mode 100644 index 0000000000..0434fdf7f2 --- /dev/null +++ b/MdePkg/Include/Common/Capsule.h @@ -0,0 +1,67 @@ +/** @file + Defines for the EFI Capsule functionality. + + Copyright (c) 2006, 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. + + Module Name: Capsule.h + + @par Revision Reference: + These definitions are from Capsule Spec Version 0.9. + +**/ + +#ifndef _EFI_CAPSULE_H_ +#define _EFI_CAPSULE_H_ + +// +// Bits in the flags field of the capsule header +// +#define EFI_CAPSULE_HEADER_FLAG_SETUP 0x00000001 // supports setup changes + + +#define CAPSULE_BLOCK_DESCRIPTOR_SIGNATURE EFI_SIGNATURE_32 ('C', 'B', 'D', 'S') + +// +// An array of these describe the blocks that make up a capsule for +// a capsule update. +// +typedef struct { + UINT64 Length; // length of the data block + EFI_PHYSICAL_ADDRESS Data; // physical address of the data block + UINT32 Signature; // CBDS + UINT32 CheckSum; // to sum this structure to 0 +} EFI_CAPSULE_BLOCK_DESCRIPTOR; + +typedef struct { + EFI_GUID OemGuid; + UINT32 HeaderSize; + // + // UINT8 OemHdrData[]; + // +} EFI_CAPSULE_OEM_HEADER; + +typedef struct { + EFI_GUID CapsuleGuid; + UINT32 HeaderSize; + UINT32 Flags; + UINT32 CapsuleImageSize; + UINT32 SequenceNumber; + EFI_GUID InstanceId; + UINT32 OffsetToSplitInformation; + UINT32 OffsetToCapsuleBody; + UINT32 OffsetToOemDefinedHeader; + UINT32 OffsetToAuthorInformation; + UINT32 OffsetToRevisionInformation; + UINT32 OffsetToShortDescription; + UINT32 OffsetToLongDescription; + UINT32 OffsetToApplicableDevices; +} EFI_CAPSULE_HEADER; + +#endif // #ifndef _EFI_CAPSULE_H_ diff --git a/MdePkg/Include/Common/DataHubRecords.h b/MdePkg/Include/Common/DataHubRecords.h new file mode 100644 index 0000000000..0bc8f23d75 --- /dev/null +++ b/MdePkg/Include/Common/DataHubRecords.h @@ -0,0 +1,1847 @@ +/** @file + This file defines GUIDs and associated data structures for records + posted to the Data Hub. + The producers of these records use these definitions to construct + records. + The consumers of these records use these definitions to retrieve, + filter and parse records. + + Copyright (c) 2006, 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. + + Module Name: DataHubRecords.h + + @par Revision Reference: + DataHubRecord.h include all data hub sub class defitions from Cache subclass + spec 0.9, DataHub SubClass spec 0.9, Memory SubClass Spec 0.9, Processor + Subclass spec 0.9,Misc SubClass spec 0.9. + +**/ + +#ifndef _DATAHUB_RECORDS_H_ +#define _DATAHUB_RECORDS_H_ + +#define EFI_PROCESSOR_SUBCLASS_VERSION 0x00010000 + + +#pragma pack(1) + +typedef struct _USB_PORT_DEVICE_PATH { + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH PciBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} USB_PORT_DEVICE_PATH; + +// +// IDE +// +typedef struct _IDE_DEVICE_PATH { + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH PciBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} IDE_DEVICE_PATH; + +// +// RMC Connector +// +typedef struct _RMC_CONN_DEVICE_PATH { + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH PciBridgeDevicePath; + PCI_DEVICE_PATH PciBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} RMC_CONN_DEVICE_PATH; + +// +// RIDE +// +typedef struct _RIDE_DEVICE_PATH { + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH PciBridgeDevicePath; + PCI_DEVICE_PATH PciBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} RIDE_DEVICE_PATH; + +// +// Gigabit NIC +// +typedef struct _GB_NIC_DEVICE_PATH { + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH PciBridgeDevicePath; + PCI_DEVICE_PATH PciXBridgeDevicePath; + PCI_DEVICE_PATH PciXBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} GB_NIC_DEVICE_PATH; + +// +// P/S2 Connector +// +typedef struct _PS2_CONN_DEVICE_PATH { + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH LpcBridgeDevicePath; + ACPI_HID_DEVICE_PATH LpcBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} PS2_CONN_DEVICE_PATH; + +// +// Serial Port Connector +// +typedef struct _SERIAL_CONN_DEVICE_PATH { + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH LpcBridgeDevicePath; + ACPI_HID_DEVICE_PATH LpcBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} SERIAL_CONN_DEVICE_PATH; + +// +// Parallel Port Connector +// +typedef struct _PARALLEL_CONN_DEVICE_PATH { + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH LpcBridgeDevicePath; + ACPI_HID_DEVICE_PATH LpcBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} PARALLEL_CONN_DEVICE_PATH; + +// +// Floopy Connector +// +typedef struct _FLOOPY_CONN_DEVICE_PATH { + ACPI_HID_DEVICE_PATH PciRootBridgeDevicePath; + PCI_DEVICE_PATH LpcBridgeDevicePath; + ACPI_HID_DEVICE_PATH LpcBusDevicePath; + EFI_DEVICE_PATH_PROTOCOL EndDevicePath; +} FLOOPY_CONN_DEVICE_PATH; + +typedef union _EFI_MISC_PORT_DEVICE_PATH { + USB_PORT_DEVICE_PATH UsbDevicePath; + IDE_DEVICE_PATH IdeDevicePath; + RMC_CONN_DEVICE_PATH RmcConnDevicePath; + RIDE_DEVICE_PATH RideDevicePath; + GB_NIC_DEVICE_PATH GbNicDevicePath; + PS2_CONN_DEVICE_PATH Ps2ConnDevicePath; + SERIAL_CONN_DEVICE_PATH SerialConnDevicePath; + PARALLEL_CONN_DEVICE_PATH ParallelConnDevicePath; + FLOOPY_CONN_DEVICE_PATH FloppyConnDevicePath; +} EFI_MISC_PORT_DEVICE_PATH; + +#pragma pack() + +// +// String Token Definition +// +#define EFI_STRING_TOKEN UINT16 + +typedef struct { + UINT32 Version; + UINT32 HeaderSize; + UINT16 Instance; + UINT16 SubInstance; + UINT32 RecordType; +} EFI_SUBCLASS_TYPE1_HEADER; + +typedef struct { + EFI_GUID ProducerName; + UINT16 Instance; + UINT16 SubInstance; +} EFI_INTER_LINK_DATA; + + +// +// EXP data +// + +typedef struct { + UINT16 Value; + UINT16 Exponent; +} EFI_EXP_BASE2_DATA; + + +typedef EFI_EXP_BASE10_DATA EFI_PROCESSOR_MAX_CORE_FREQUENCY_DATA; + +typedef EFI_EXP_BASE10_DATA EFI_PROCESSOR_MAX_FSB_FREQUENCY_DATA; + +typedef EFI_EXP_BASE10_DATA EFI_PROCESSOR_CORE_FREQUENCY_DATA; + +typedef EFI_EXP_BASE10_DATA *EFI_PROCESSOR_CORE_FREQUENCY_LIST_DATA; + +typedef EFI_EXP_BASE10_DATA *EFI_PROCESSOR_FSB_FREQUENCY_LIST_DATA; + +typedef EFI_EXP_BASE10_DATA EFI_PROCESSOR_FSB_FREQUENCY_DATA; + +typedef STRING_REF EFI_PROCESSOR_VERSION_DATA; + +typedef STRING_REF EFI_PROCESSOR_MANUFACTURER_DATA; + +typedef STRING_REF EFI_PROCESSOR_SERIAL_NUMBER_DATA; + +typedef STRING_REF EFI_PROCESSOR_ASSET_TAG_DATA; + +typedef struct { + UINT32 ProcessorSteppingId:4; + UINT32 ProcessorModel: 4; + UINT32 ProcessorFamily: 4; + UINT32 ProcessorType: 2; + UINT32 ProcessorReserved1: 2; + UINT32 ProcessorXModel: 4; + UINT32 ProcessorXFamily: 8; + UINT32 ProcessorReserved2: 4; +} EFI_PROCESSOR_SIGNATURE; + +typedef struct { + UINT32 ProcessorBrandIndex :8; + UINT32 ProcessorClflush :8; + UINT32 ProcessorReserved :8; + UINT32 ProcessorDfltApicId :8; +} EFI_PROCESSOR_MISC_INFO; + +typedef struct { + UINT32 ProcessorFpu: 1; + UINT32 ProcessorVme: 1; + UINT32 ProcessorDe: 1; + UINT32 ProcessorPse: 1; + UINT32 ProcessorTsc: 1; + UINT32 ProcessorMsr: 1; + UINT32 ProcessorPae: 1; + UINT32 ProcessorMce: 1; + UINT32 ProcessorCx8: 1; + UINT32 ProcessorApic: 1; + UINT32 ProcessorReserved1: 1; + UINT32 ProcessorSep: 1; + UINT32 ProcessorMtrr: 1; + UINT32 ProcessorPge: 1; + UINT32 ProcessorMca: 1; + UINT32 ProcessorCmov: 1; + UINT32 ProcessorPat: 1; + UINT32 ProcessorPse36: 1; + UINT32 ProcessorPsn: 1; + UINT32 ProcessorClfsh: 1; + UINT32 ProcessorReserved2: 1; + UINT32 ProcessorDs: 1; + UINT32 ProcessorAcpi: 1; + UINT32 ProcessorMmx: 1; + UINT32 ProcessorFxsr: 1; + UINT32 ProcessorSse: 1; + UINT32 ProcessorSse2: 1; + UINT32 ProcessorSs: 1; + UINT32 ProcessorReserved3: 1; + UINT32 ProcessorTm: 1; + UINT32 ProcessorReserved4: 2; +} EFI_PROCESSOR_FEATURE_FLAGS; + +typedef struct { + EFI_PROCESSOR_SIGNATURE Signature; + EFI_PROCESSOR_MISC_INFO MiscInfo; + UINT32 Reserved; + EFI_PROCESSOR_FEATURE_FLAGS FeatureFlags; +} EFI_PROCESSOR_ID_DATA; + +typedef enum { + EfiProcessorOther = 1, + EfiProcessorUnknown = 2, + EfiCentralProcessor = 3, + EfiMathProcessor = 4, + EfiDspProcessor = 5, + EfiVideoProcessor = 6 +} EFI_PROCESSOR_TYPE_DATA; + +typedef enum { + EfiProcessorFamilyOther = 1, + EfiProcessorFamilyUnknown = 2, + EfiProcessorFamily8086 = 3, + EfiProcessorFamily80286 = 4, + EfiProcessorFamilyIntel386 = 5, + EfiProcessorFamilyIntel486 = 6, + EfiProcessorFamily8087 = 7, + EfiProcessorFamily80287 = 8, + EfiProcessorFamily80387 = 9, + EfiProcessorFamily80487 = 0x0A, + EfiProcessorFamilyPentium = 0x0B, + EfiProcessorFamilyPentiumPro = 0x0C, + EfiProcessorFamilyPentiumII = 0x0D, + EfiProcessorFamilyPentiumMMX = 0x0E, + EfiProcessorFamilyCeleron = 0x0F, + EfiProcessorFamilyPentiumIIXeon = 0x10, + EfiProcessorFamilyPentiumIII = 0x11, + EfiProcessorFamilyM1 = 0x12, + EfiProcessorFamilyM1Reserved1 = 0x13, + EfiProcessorFamilyM1Reserved2 = 0x14, + EfiProcessorFamilyM1Reserved3 = 0x15, + EfiProcessorFamilyM1Reserved4 = 0x16, + EfiProcessorFamilyM1Reserved5 = 0x17, + EfiProcessorFamilyM1Reserved6 = 0x18, + EfiProcessorFamilyK5 = 0x19, + EfiProcessorFamilyK5Reserved1 = 0x1A, + EfiProcessorFamilyK5Reserved2 = 0x1B, + EfiProcessorFamilyK5Reserved3 = 0x1C, + EfiProcessorFamilyK5Reserved4 = 0x1D, + EfiProcessorFamilyK5Reserved5 = 0x1E, + EfiProcessorFamilyK5Reserved6 = 0x1F, + EfiProcessorFamilyPowerPC = 0x20, + EfiProcessorFamilyPowerPC601 = 0x21, + EfiProcessorFamilyPowerPC603 = 0x22, + EfiProcessorFamilyPowerPC603Plus = 0x23, + EfiProcessorFamilyPowerPC604 = 0x24, + EfiProcessorFamilyAlpha2 = 0x30, + EfiProcessorFamilyMips = 0x40, + EfiProcessorFamilySparc = 0x50, + EfiProcessorFamily68040 = 0x60, + EfiProcessorFamily68xxx = 0x61, + EfiProcessorFamily68000 = 0x62, + EfiProcessorFamily68010 = 0x63, + EfiProcessorFamily68020 = 0x64, + EfiProcessorFamily68030 = 0x65, + EfiProcessorFamilyHobbit = 0x70, + EfiProcessorFamilyWeitek = 0x80, + EfiProcessorFamilyPARISC = 0x90, + EfiProcessorFamilyV30 = 0xA0, + EfiProcessorFamilyPentiumIIIXeon = 0xB0, + EfiProcessorFamilyPentiumIIISpeedStep = 0xB1, + EfiProcessorFamilyPentium4 = 0xB2, + EfiProcessorFamilyIntelXeon = 0xB3, + EfiProcessorFamilyAS400 = 0xB4, + EfiProcessorFamilyIntelXeonMP = 0xB5, + EfiProcessorFamilyAMDAthlonXP = 0xB6, + EfiProcessorFamilyAMDAthlonMP = 0xB7, + EfiProcessorFamilyIBM390 = 0xC8, + EfiProcessorFamilyG4 = 0xC9, + EfiProcessorFamilyG5 = 0xCA, + EfiProcessorFamilyi860 = 0xFA, + EfiProcessorFamilyi960 = 0xFB +} EFI_PROCESSOR_FAMILY_DATA; + +typedef EFI_EXP_BASE10_DATA EFI_PROCESSOR_VOLTAGE_DATA; + +typedef EFI_PHYSICAL_ADDRESS EFI_PROCESSOR_APIC_BASE_ADDRESS_DATA; + +typedef UINT32 EFI_PROCESSOR_APIC_ID_DATA; + +typedef UINT32 EFI_PROCESSOR_APIC_VERSION_NUMBER_DATA; + +typedef enum { + EfiProcessorIa32Microcode = 1, + EfiProcessorIpfPalAMicrocode = 2, + EfiProcessorIpfPalBMicrocode = 3 +} EFI_PROCESSOR_MICROCODE_TYPE; + +typedef struct { + EFI_PROCESSOR_MICROCODE_TYPE ProcessorMicrocodeType; + UINT32 ProcessorMicrocodeRevisionNumber; +} EFI_PROCESSOR_MICROCODE_REVISION_DATA; + +typedef struct { + UINT32 CpuStatus :3; + UINT32 Reserved1 :3; + UINT32 SocketPopulated :1; + UINT32 Reserved2 :1; + UINT32 ApicEnable :1; + UINT32 BootApplicationProcessor :1; + UINT32 Reserved3 :22; +} EFI_PROCESSOR_STATUS_DATA; + +typedef enum { + EfiCpuStatusUnknown = 0, + EfiCpuStatusEnabled = 1, + EfiCpuStatusDisabledByUser = 2, + EfiCpuStatusDisabledbyBios = 3, + EfiCpuStatusIdle = 4, + EfiCpuStatusOther = 7 +} EFI_CPU_STATUS; + +typedef enum { + EfiProcessorSocketOther = 1, + EfiProcessorSocketUnknown = 2, + EfiProcessorSocketDaughterBoard = 3, + EfiProcessorSocketZIF = 4, + EfiProcessorSocketReplacePiggyBack = 5, + EfiProcessorSocketNone = 6, + EfiProcessorSocketLIF = 7, + EfiProcessorSocketSlot1 = 8, + EfiProcessorSocketSlot2 = 9, + EfiProcessorSocket370Pin = 0xA, + EfiProcessorSocketSlotA = 0xB, + EfiProcessorSocketSlotM = 0xC, + EfiProcessorSocket423 = 0xD, + EfiProcessorSocketA462 = 0xE, + EfiProcessorSocket478 = 0xF, + EfiProcessorSocket754 = 0x10, + EfiProcessorSocket940 = 0x11, + EfiProcessorSocketLG775 = 0x12 + +} EFI_PROCESSOR_SOCKET_TYPE_DATA; + +typedef STRING_REF EFI_PROCESSOR_SOCKET_NAME_DATA; + +typedef EFI_INTER_LINK_DATA EFI_CACHE_ASSOCIATION_DATA; + +typedef enum { + EfiProcessorHealthy = 1, + EfiProcessorPerfRestricted = 2, + EfiProcessorFuncRestricted = 3 +} EFI_PROCESSOR_HEALTH_STATUS; + +typedef UINTN EFI_PROCESSOR_PACKAGE_NUMBER_DATA; + + +typedef enum { + ProcessorCoreFrequencyRecordType = 1, + ProcessorFsbFrequencyRecordType = 2, + ProcessorVersionRecordType = 3, + ProcessorManufacturerRecordType = 4, + ProcessorSerialNumberRecordType = 5, + ProcessorIdRecordType = 6, + ProcessorTypeRecordType = 7, + ProcessorFamilyRecordType = 8, + ProcessorVoltageRecordType = 9, + ProcessorApicBaseAddressRecordType = 10, + ProcessorApicIdRecordType = 11, + ProcessorApicVersionNumberRecordType = 12, + CpuUcodeRevisionDataRecordType = 13, + ProcessorStatusRecordType = 14, + ProcessorSocketTypeRecordType = 15, + ProcessorSocketNameRecordType = 16, + CacheAssociationRecordType = 17, + ProcessorMaxCoreFrequencyRecordType = 18, + ProcessorAssetTagRecordType = 19, + ProcessorMaxFsbFrequencyRecordType = 20, + ProcessorPackageNumberRecordType = 21, + ProcessorCoreFrequencyListRecordType = 22, + ProcessorFsbFrequencyListRecordType = 23, + ProcessorHealthStatusRecordType = 24 +} EFI_CPU_VARIABLE_RECORD_TYPE; + +typedef union { + EFI_PROCESSOR_CORE_FREQUENCY_LIST_DATA ProcessorCoreFrequencyList; + EFI_PROCESSOR_FSB_FREQUENCY_LIST_DATA ProcessorFsbFrequencyList; + EFI_PROCESSOR_SERIAL_NUMBER_DATA ProcessorSerialNumber; + EFI_PROCESSOR_CORE_FREQUENCY_DATA ProcessorCoreFrequency; + EFI_PROCESSOR_FSB_FREQUENCY_DATA ProcessorFsbFrequency; + EFI_PROCESSOR_MAX_CORE_FREQUENCY_DATA ProcessorMaxCoreFrequency; + EFI_PROCESSOR_MAX_FSB_FREQUENCY_DATA ProcessorMaxFsbFrequency; + EFI_PROCESSOR_VERSION_DATA ProcessorVersion; + EFI_PROCESSOR_MANUFACTURER_DATA ProcessorManufacturer; + EFI_PROCESSOR_ID_DATA ProcessorId; + EFI_PROCESSOR_TYPE_DATA ProcessorType; + EFI_PROCESSOR_FAMILY_DATA ProcessorFamily; + EFI_PROCESSOR_VOLTAGE_DATA ProcessorVoltage; + EFI_PROCESSOR_APIC_BASE_ADDRESS_DATA ProcessorApicBase; + EFI_PROCESSOR_APIC_ID_DATA ProcessorApicId; + EFI_PROCESSOR_APIC_VERSION_NUMBER_DATA ProcessorApicVersionNumber; + EFI_PROCESSOR_MICROCODE_REVISION_DATA CpuUcodeRevisionData; + EFI_PROCESSOR_STATUS_DATA ProcessorStatus; + EFI_PROCESSOR_SOCKET_TYPE_DATA ProcessorSocketType; + EFI_PROCESSOR_SOCKET_NAME_DATA ProcessorSocketName; + EFI_PROCESSOR_ASSET_TAG_DATA ProcessorAssetTag; + EFI_PROCESSOR_HEALTH_STATUS ProcessorHealthStatus; + EFI_PROCESSOR_PACKAGE_NUMBER_DATA ProcessorPackageNumber; +} EFI_CPU_VARIABLE_RECORD; + +typedef struct { + EFI_SUBCLASS_TYPE1_HEADER DataRecordHeader; + EFI_CPU_VARIABLE_RECORD VariableRecord; +} EFI_CPU_DATA_RECORD; + +#define EFI_CACHE_SUBCLASS_VERSION 0x00010000 + + +typedef EFI_EXP_BASE2_DATA EFI_CACHE_SIZE_DATA; + +typedef EFI_EXP_BASE2_DATA EFI_MAXIMUM_CACHE_SIZE_DATA; + +typedef EFI_EXP_BASE10_DATA EFI_CACHE_SPEED_DATA; + +typedef STRING_REF EFI_CACHE_SOCKET_DATA; + +typedef struct { + UINT32 Other :1; + UINT32 Unknown :1; + UINT32 NonBurst :1; + UINT32 Burst :1; + UINT32 PipelineBurst :1; + UINT32 Asynchronous :1; + UINT32 Synchronous :1; + UINT32 Reserved :25; +} EFI_CACHE_SRAM_TYPE_DATA; + +typedef enum { + EfiCacheErrorOther = 1, + EfiCacheErrorUnknown = 2, + EfiCacheErrorNone = 3, + EfiCacheErrorParity = 4, + EfiCacheErrorSingleBit = 5, + EfiCacheErrorMultiBit = 6 +} EFI_CACHE_ERROR_TYPE_DATA; + +typedef enum { + EfiCacheTypeOther = 1, + EfiCacheTypeUnknown = 2, + EfiCacheTypeInstruction = 3, + EfiCacheTypeData = 4, + EfiCacheTypeUnified = 5 +} EFI_CACHE_TYPE_DATA; + +typedef enum { + EfiCacheAssociativityOther = 1, + EfiCacheAssociativityUnknown = 2, + EfiCacheAssociativityDirectMapped = 3, + EfiCacheAssociativity2Way = 4, + EfiCacheAssociativity4Way = 5, + EfiCacheAssociativityFully = 6, + EfiCacheAssociativity8Way = 7, + EfiCacheAssociativity16Way = 8 +} EFI_CACHE_ASSOCIATIVITY_DATA; + +typedef struct { + UINT32 Level :3; + UINT32 Socketed :1; + UINT32 Reserved2 :1; + UINT32 Location :2; + UINT32 Enable :1; + UINT32 OperationalMode :2; + UINT32 Reserved1 :22; +} EFI_CACHE_CONFIGURATION_DATA; + +#define EFI_CACHE_L1 1 +#define EFI_CACHE_L2 2 +#define EFI_CACHE_L3 3 +#define EFI_CACHE_L4 4 +#define EFI_CACHE_LMAX EFI_CACHE_L4 + +#define EFI_CACHE_SOCKETED 1 +#define EFI_CACHE_NOT_SOCKETED 0 + +typedef enum { + EfiCacheInternal = 0, + EfiCacheExternal = 1, + EfiCacheReserved = 2, + EfiCacheUnknown = 3 +} EFI_CACHE_LOCATION; + +#define EFI_CACHE_ENABLED 1 +#define EFI_CACHE_DISABLED 0 + +typedef enum { + EfiCacheWriteThrough = 0, + EfiCacheWriteBack = 1, + EfiCacheDynamicMode = 2, + EfiCacheUnknownMode = 3 +} EFI_CACHE_OPERATIONAL_MODE; + + + +typedef enum { + CacheSizeRecordType = 1, + MaximumSizeCacheRecordType = 2, + CacheSpeedRecordType = 3, + CacheSocketRecordType = 4, + CacheSramTypeRecordType = 5, + CacheInstalledSramTypeRecordType = 6, + CacheErrorTypeRecordType = 7, + CacheTypeRecordType = 8, + CacheAssociativityRecordType = 9, + CacheConfigRecordType = 10 +} EFI_CACHE_VARIABLE_RECORD_TYPE; + + +typedef union { + EFI_CACHE_SIZE_DATA CacheSize; + EFI_MAXIMUM_CACHE_SIZE_DATA MaximumCacheSize; + EFI_CACHE_SPEED_DATA CacheSpeed; + EFI_CACHE_SOCKET_DATA CacheSocket; + EFI_CACHE_SRAM_TYPE_DATA CacheSramType; + EFI_CACHE_SRAM_TYPE_DATA CacheInstalledSramType; + EFI_CACHE_ERROR_TYPE_DATA CacheErrorType; + EFI_CACHE_TYPE_DATA CacheType; + EFI_CACHE_ASSOCIATIVITY_DATA CacheAssociativity; + EFI_CACHE_CONFIGURATION_DATA CacheConfig; + EFI_CACHE_ASSOCIATION_DATA CacheAssociation; +} EFI_CACHE_VARIABLE_RECORD; + +typedef struct { + EFI_SUBCLASS_TYPE1_HEADER DataRecordHeader; + EFI_CACHE_VARIABLE_RECORD VariableRecord; +} EFI_CACHE_DATA_RECORD; + +#define EFI_MEMORY_SUBCLASS_VERSION 0x0100 + + +#define EFI_MEMORY_SIZE_RECORD_NUMBER 0x00000001 + +typedef enum _EFI_MEMORY_REGION_TYPE { + EfiMemoryRegionMemory = 0x01, + EfiMemoryRegionReserved = 0x02, + EfiMemoryRegionAcpi = 0x03, + EfiMemoryRegionNvs = 0x04 +} EFI_MEMORY_REGION_TYPE; + +typedef struct { + UINT32 ProcessorNumber; + UINT16 StartBusNumber; + UINT16 EndBusNumber; + EFI_MEMORY_REGION_TYPE MemoryRegionType; + EFI_EXP_BASE2_DATA MemorySize; + EFI_PHYSICAL_ADDRESS MemoryStartAddress; +} EFI_MEMORY_SIZE_DATA; + + +#define EFI_MEMORY_ARRAY_LOCATION_RECORD_NUMBER 0x00000002 + +typedef enum _EFI_MEMORY_ARRAY_LOCATION { + EfiMemoryArrayLocationOther = 0x01, + EfiMemoryArrayLocationUnknown = 0x02, + EfiMemoryArrayLocationSystemBoard = 0x03, + EfiMemoryArrayLocationIsaAddonCard = 0x04, + EfiMemoryArrayLocationEisaAddonCard = 0x05, + EfiMemoryArrayLocationPciAddonCard = 0x06, + EfiMemoryArrayLocationMcaAddonCard = 0x07, + EfiMemoryArrayLocationPcmciaAddonCard = 0x08, + EfiMemoryArrayLocationProprietaryAddonCard = 0x09, + EfiMemoryArrayLocationNuBus = 0x0A, + EfiMemoryArrayLocationPc98C20AddonCard = 0xA0, + EfiMemoryArrayLocationPc98C24AddonCard = 0xA1, + EfiMemoryArrayLocationPc98EAddonCard = 0xA2, + EfiMemoryArrayLocationPc98LocalBusAddonCard = 0xA3 +} EFI_MEMORY_ARRAY_LOCATION; + +typedef enum _EFI_MEMORY_ARRAY_USE { + EfiMemoryArrayUseOther = 0x01, + EfiMemoryArrayUseUnknown = 0x02, + EfiMemoryArrayUseSystemMemory = 0x03, + EfiMemoryArrayUseVideoMemory = 0x04, + EfiMemoryArrayUseFlashMemory = 0x05, + EfiMemoryArrayUseNonVolatileRam = 0x06, + EfiMemoryArrayUseCacheMemory = 0x07, +} EFI_MEMORY_ARRAY_USE; + +typedef enum _EFI_MEMORY_ERROR_CORRECTION { + EfiMemoryErrorCorrectionOther = 0x01, + EfiMemoryErrorCorrectionUnknown = 0x02, + EfiMemoryErrorCorrectionNone = 0x03, + EfiMemoryErrorCorrectionParity = 0x04, + EfiMemoryErrorCorrectionSingleBitEcc = 0x05, + EfiMemoryErrorCorrectionMultiBitEcc = 0x06, + EfiMemoryErrorCorrectionCrc = 0x07, +} EFI_MEMORY_ERROR_CORRECTION; + +typedef struct { + EFI_MEMORY_ARRAY_LOCATION MemoryArrayLocation; + EFI_MEMORY_ARRAY_USE MemoryArrayUse; + EFI_MEMORY_ERROR_CORRECTION MemoryErrorCorrection; + EFI_EXP_BASE2_DATA MaximumMemoryCapacity; + UINT16 NumberMemoryDevices; +} EFI_MEMORY_ARRAY_LOCATION_DATA; + + +#define EFI_MEMORY_ARRAY_LINK_RECORD_NUMBER 0x00000003 + +typedef enum _EFI_MEMORY_FORM_FACTOR { + EfiMemoryFormFactorOther = 0x01, + EfiMemoryFormFactorUnknown = 0x02, + EfiMemoryFormFactorSimm = 0x03, + EfiMemoryFormFactorSip = 0x04, + EfiMemoryFormFactorChip = 0x05, + EfiMemoryFormFactorDip = 0x06, + EfiMemoryFormFactorZip = 0x07, + EfiMemoryFormFactorProprietaryCard = 0x08, + EfiMemoryFormFactorDimm = 0x09, + EfiMemoryFormFactorTsop = 0x0A, + EfiMemoryFormFactorRowOfChips = 0x0B, + EfiMemoryFormFactorRimm = 0x0C, + EfiMemoryFormFactorSodimm = 0x0D, + EfiMemoryFormFactorSrimm = 0x0E +} EFI_MEMORY_FORM_FACTOR; + +typedef enum _EFI_MEMORY_ARRAY_TYPE { + EfiMemoryTypeOther = 0x01, + EfiMemoryTypeUnknown = 0x02, + EfiMemoryTypeDram = 0x03, + EfiMemoryTypeEdram = 0x04, + EfiMemoryTypeVram = 0x05, + EfiMemoryTypeSram = 0x06, + EfiMemoryTypeRam = 0x07, + EfiMemoryTypeRom = 0x08, + EfiMemoryTypeFlash = 0x09, + EfiMemoryTypeEeprom = 0x0A, + EfiMemoryTypeFeprom = 0x0B, + EfiMemoryTypeEprom = 0x0C, + EfiMemoryTypeCdram = 0x0D, + EfiMemoryType3Dram = 0x0E, + EfiMemoryTypeSdram = 0x0F, + EfiMemoryTypeSgram = 0x10, + EfiMemoryTypeRdram = 0x11, + EfiMemoryTypeDdr = 0x12 +} EFI_MEMORY_ARRAY_TYPE; + +typedef struct { + UINT32 Reserved :1; + UINT32 Other :1; + UINT32 Unknown :1; + UINT32 FastPaged :1; + UINT32 StaticColumn :1; + UINT32 PseudoStatic :1; + UINT32 Rambus :1; + UINT32 Synchronous :1; + UINT32 Cmos :1; + UINT32 Edo :1; + UINT32 WindowDram :1; + UINT32 CacheDram :1; + UINT32 Nonvolatile :1; + UINT32 Reserved1 :19; +} EFI_MEMORY_TYPE_DETAIL; + +typedef enum { + EfiMemoryStateEnabled = 0, + EfiMemoryStateUnknown = 1, + EfiMemoryStateUnsupported = 2, + EfiMemoryStateError = 3, + EfiMemoryStateAbsent = 4, + EfiMemoryStateDisabled = 5, + EfiMemoryStatePartial = 6 +} EFI_MEMORY_STATE; + +typedef struct { + STRING_REF MemoryDeviceLocator; + STRING_REF MemoryBankLocator; + STRING_REF MemoryManufacturer; + STRING_REF MemorySerialNumber; + STRING_REF MemoryAssetTag; + STRING_REF MemoryPartNumber; + EFI_INTER_LINK_DATA MemoryArrayLink; + EFI_INTER_LINK_DATA MemorySubArrayLink; + UINT16 MemoryTotalWidth; + UINT16 MemoryDataWidth; + EFI_EXP_BASE2_DATA MemoryDeviceSize; + EFI_MEMORY_FORM_FACTOR MemoryFormFactor; + UINT8 MemoryDeviceSet; + EFI_MEMORY_ARRAY_TYPE MemoryType; + EFI_MEMORY_TYPE_DETAIL MemoryTypeDetail; + EFI_EXP_BASE10_DATA MemorySpeed; + EFI_MEMORY_STATE MemoryState; +} EFI_MEMORY_ARRAY_LINK_DATA; + + +#define EFI_MEMORY_ARRAY_START_ADDRESS_RECORD_NUMBER 0x00000004 + +typedef struct { + EFI_PHYSICAL_ADDRESS MemoryArrayStartAddress; + EFI_PHYSICAL_ADDRESS MemoryArrayEndAddress; + EFI_INTER_LINK_DATA PhysicalMemoryArrayLink; + UINT16 MemoryArrayPartitionWidth; +} EFI_MEMORY_ARRAY_START_ADDRESS_DATA; + + +#define EFI_MEMORY_DEVICE_START_ADDRESS_RECORD_NUMBER 0x00000005 + +typedef struct { + EFI_PHYSICAL_ADDRESS MemoryDeviceStartAddress; + EFI_PHYSICAL_ADDRESS MemoryDeviceEndAddress; + EFI_INTER_LINK_DATA PhysicalMemoryDeviceLink; + EFI_INTER_LINK_DATA PhysicalMemoryArrayLink; + UINT8 MemoryDevicePartitionRowPosition; + UINT8 MemoryDeviceInterleavePosition; + UINT8 MemoryDeviceInterleaveDataDepth; +} EFI_MEMORY_DEVICE_START_ADDRESS_DATA; + + +// +// Memory. Channel Device Type - SMBIOS Type 37 +// + +#define EFI_MEMORY_CHANNEL_TYPE_RECORD_NUMBER 0x00000006 + +typedef enum _EFI_MEMORY_CHANNEL_TYPE { + EfiMemoryChannelTypeOther = 1, + EfiMemoryChannelTypeUnknown = 2, + EfiMemoryChannelTypeRambus = 3, + EfiMemoryChannelTypeSyncLink = 4 +} EFI_MEMORY_CHANNEL_TYPE; + +typedef struct { + EFI_MEMORY_CHANNEL_TYPE MemoryChannelType; + UINT8 MemoryChannelMaximumLoad; + UINT8 MemoryChannelDeviceCount; +} EFI_MEMORY_CHANNEL_TYPE_DATA; + +#define EFI_MEMORY_CHANNEL_DEVICE_RECORD_NUMBER 0x00000007 + +typedef struct { + UINT8 DeviceId; + EFI_INTER_LINK_DATA DeviceLink; + UINT8 MemoryChannelDeviceLoad; +} EFI_MEMORY_CHANNEL_DEVICE_DATA; + + + +typedef union _EFI_MEMORY_SUBCLASS_RECORDS { + EFI_MEMORY_SIZE_DATA SizeData; + EFI_MEMORY_ARRAY_LOCATION_DATA ArrayLocationData; + EFI_MEMORY_ARRAY_LINK_DATA ArrayLink; + EFI_MEMORY_ARRAY_START_ADDRESS_DATA ArrayStartAddress; + EFI_MEMORY_DEVICE_START_ADDRESS_DATA DeviceStartAddress; + EFI_MEMORY_CHANNEL_TYPE_DATA ChannelTypeData; + EFI_MEMORY_CHANNEL_DEVICE_DATA ChannelDeviceData; +} EFI_MEMORY_SUBCLASS_RECORDS; + +typedef struct { + EFI_SUBCLASS_TYPE1_HEADER Header; + EFI_MEMORY_SUBCLASS_RECORDS Record; +} EFI_MEMORY_SUBCLASS_DRIVER_DATA; + +#define EFI_MISC_SUBCLASS_VERSION 0x0100 + +#pragma pack(1) +// +////////////////////////////////////////////////////////////////////////////// +// +// Last PCI Bus Number +// +#define EFI_MISC_LAST_PCI_BUS_RECORD_NUMBER 0x00000001 + +typedef struct { + UINT8 LastPciBus; +} EFI_MISC_LAST_PCI_BUS_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. BIOS Vendor - SMBIOS Type 0 +// +#define EFI_MISC_BIOS_VENDOR_RECORD_NUMBER 0x00000002 + +typedef struct { + UINT32 Reserved1 :2; + UINT32 Unknown :1; + UINT32 BiosCharacteristicsNotSupported :1; + UINT32 IsaIsSupported :1; + UINT32 McaIsSupported :1; + UINT32 EisaIsSupported :1; + UINT32 PciIsSupported :1; + UINT32 PcmciaIsSupported :1; + UINT32 PlugAndPlayIsSupported :1; + UINT32 ApmIsSupported :1; + UINT32 BiosIsUpgradable :1; + UINT32 BiosShadowingAllowed :1; + UINT32 VlVesaIsSupported :1; + UINT32 EscdSupportIsAvailable :1; + UINT32 BootFromCdIsSupported :1; + UINT32 SelectableBootIsSupported :1; + UINT32 RomBiosIsSocketed :1; + UINT32 BootFromPcmciaIsSupported :1; + UINT32 EDDSpecificationIsSupported :1; + UINT32 JapaneseNecFloppyIsSupported :1; + UINT32 JapaneseToshibaFloppyIsSupported :1; + UINT32 Floppy525_360IsSupported :1; + UINT32 Floppy525_12IsSupported :1; + UINT32 Floppy35_720IsSupported :1; + UINT32 Floppy35_288IsSupported :1; + UINT32 PrintScreenIsSupported :1; + UINT32 Keyboard8042IsSupported :1; + UINT32 SerialIsSupported :1; + UINT32 PrinterIsSupported :1; + UINT32 CgaMonoIsSupported :1; + UINT32 NecPc98 :1; + UINT32 AcpiIsSupported :1; + UINT32 UsbLegacyIsSupported :1; + UINT32 AgpIsSupported :1; + UINT32 I20BootIsSupported :1; + UINT32 Ls120BootIsSupported :1; + UINT32 AtapiZipDriveBootIsSupported :1; + UINT32 Boot1394IsSupported :1; + UINT32 SmartBatteryIsSupported :1; + UINT32 BiosBootSpecIsSupported :1; + UINT32 FunctionKeyNetworkBootIsSupported :1; + UINT32 Reserved :22; +} EFI_MISC_BIOS_CHARACTERISTICS; + +typedef struct { + UINT32 BiosReserved :16; + UINT32 SystemReserved :16; + UINT32 Reserved :32; +} EFI_MISC_BIOS_CHARACTERISTICS_EXTENSION; + +typedef struct { + STRING_REF BiosVendor; + STRING_REF BiosVersion; + STRING_REF BiosReleaseDate; + EFI_PHYSICAL_ADDRESS BiosStartingAddress; + EFI_EXP_BASE2_DATA BiosPhysicalDeviceSize; + EFI_MISC_BIOS_CHARACTERISTICS BiosCharacteristics1; + EFI_MISC_BIOS_CHARACTERISTICS_EXTENSION BiosCharacteristics2; +} EFI_MISC_BIOS_VENDOR_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. System Manufacturer - SMBIOS Type 1 +// +#define EFI_MISC_SYSTEM_MANUFACTURER_RECORD_NUMBER 0x00000003 + +typedef enum { + EfiSystemWakeupTypeReserved = 0, + EfiSystemWakeupTypeOther = 1, + EfiSystemWakeupTypeUnknown = 2, + EfiSystemWakeupTypeApmTimer = 3, + EfiSystemWakeupTypeModemRing = 4, + EfiSystemWakeupTypeLanRemote = 5, + EfiSystemWakeupTypePowerSwitch = 6, + EfiSystemWakeupTypePciPme = 7, + EfiSystemWakeupTypeAcPowerRestored = 8, +} EFI_MISC_SYSTEM_WAKEUP_TYPE; + +typedef struct { + STRING_REF SystemManufacturer; + STRING_REF SystemProductName; + STRING_REF SystemVersion; + STRING_REF SystemSerialNumber; + EFI_GUID SystemUuid; + EFI_MISC_SYSTEM_WAKEUP_TYPE SystemWakeupType; +} EFI_MISC_SYSTEM_MANUFACTURER_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. Base Board Manufacturer - SMBIOS Type 2 +// +#define EFI_MISC_BASE_BOARD_MANUFACTURER_RECORD_NUMBER 0x00000004 + +typedef struct { + UINT32 Motherboard :1; + UINT32 RequiresDaughterCard :1; + UINT32 Removable :1; + UINT32 Replaceable :1; + UINT32 HotSwappable :1; + UINT32 Reserved :27; +} EFI_BASE_BOARD_FEATURE_FLAGS; + +typedef enum { + EfiBaseBoardTypeUnknown = 1, + EfiBaseBoardTypeOther = 2, + EfiBaseBoardTypeServerBlade = 3, + EfiBaseBoardTypeConnectivitySwitch = 4, + EfiBaseBoardTypeSystemManagementModule = 5, + EfiBaseBoardTypeProcessorModule = 6, + EfiBaseBoardTypeIOModule = 7, + EfiBaseBoardTypeMemoryModule = 8, + EfiBaseBoardTypeDaughterBoard = 9, + EfiBaseBoardTypeMotherBoard = 0xA, + EfiBaseBoardTypeProcessorMemoryModule = 0xB, + EfiBaseBoardTypeProcessorIOModule = 0xC, + EfiBaseBoardTypeInterconnectBoard = 0xD, +} EFI_BASE_BOARD_TYPE; + +typedef struct { + STRING_REF BaseBoardManufacturer; + STRING_REF BaseBoardProductName; + STRING_REF BaseBoardVersion; + STRING_REF BaseBoardSerialNumber; + STRING_REF BaseBoardAssetTag; + STRING_REF BaseBoardChassisLocation; + EFI_BASE_BOARD_FEATURE_FLAGS BaseBoardFeatureFlags; + EFI_BASE_BOARD_TYPE BaseBoardType; + EFI_INTER_LINK_DATA BaseBoardChassisLink; + UINT32 BaseBoardNumberLinks; + EFI_INTER_LINK_DATA LinkN; +} EFI_MISC_BASE_BOARD_MANUFACTURER_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. System/Chassis Enclosure - SMBIOS Type 3 +// +#define EFI_MISC_CHASSIS_MANUFACTURER_RECORD_NUMBER 0x00000005 + +typedef enum { + EfiMiscChassisTypeOther = 0x1, + EfiMiscChassisTypeUnknown = 0x2, + EfiMiscChassisTypeDeskTop = 0x3, + EfiMiscChassisTypeLowProfileDesktop = 0x4, + EfiMiscChassisTypePizzaBox = 0x5, + EfiMiscChassisTypeMiniTower = 0x6, + EfiMiscChassisTypeTower = 0x7, + EfiMiscChassisTypePortable = 0x8, + EfiMiscChassisTypeLapTop = 0x9, + EfiMiscChassisTypeNotebook = 0xA, + EfiMiscChassisTypeHandHeld = 0xB, + EfiMiscChassisTypeDockingStation = 0xC, + EfiMiscChassisTypeAllInOne = 0xD, + EfiMiscChassisTypeSubNotebook = 0xE, + EfiMiscChassisTypeSpaceSaving = 0xF, + EfiMiscChassisTypeLunchBox = 0x10, + EfiMiscChassisTypeMainServerChassis = 0x11, + EfiMiscChassisTypeExpansionChassis = 0x12, + EfiMiscChassisTypeSubChassis = 0x13, + EfiMiscChassisTypeBusExpansionChassis = 0x14, + EfiMiscChassisTypePeripheralChassis = 0x15, + EfiMiscChassisTypeRaidChassis = 0x16, + EfiMiscChassisTypeRackMountChassis = 0x17, + EfiMiscChassisTypeSealedCasePc = 0x18, + EfiMiscChassisMultiSystemChassis = 0x19, +} EFI_MISC_CHASSIS_TYPE; + +typedef struct { + UINT32 ChassisType :16; + UINT32 ChassisLockPresent:1; + UINT32 Reserved :15; +} EFI_MISC_CHASSIS_STATUS; + +typedef enum { + EfiChassisStateOther = 0x01, + EfiChassisStateUnknown = 0x02, + EfiChassisStateSafe = 0x03, + EfiChassisStateWarning = 0x04, + EfiChassisStateCritical = 0x05, + EfiChassisStateNonRecoverable = 0x06, +} EFI_MISC_CHASSIS_STATE; + +typedef enum { + EfiChassisSecurityStatusOther = 0x01, + EfiChassisSecurityStatusUnknown = 0x02, + EfiChassisSecurityStatusNone = 0x03, + EfiChassisSecurityStatusExternalInterfaceLockedOut = 0x04, + EfiChassisSecurityStatusExternalInterfaceLockedEnabled = 0x05, +} EFI_MISC_CHASSIS_SECURITY_STATE; + +typedef struct { + UINT32 RecordType :1; + UINT32 Reserved :24; +} EFI_MISC_ELEMENT_TYPE; + +typedef struct { + EFI_MISC_ELEMENT_TYPE ChassisElementType; + EFI_INTER_LINK_DATA ChassisElementStructure; + EFI_BASE_BOARD_TYPE ChassisBaseBoard; + UINT32 ChassisElementMinimum; + UINT32 ChassisElementMaximum; +} EFI_MISC_ELEMENTS; + +typedef struct { + STRING_REF ChassisManufacturer; + STRING_REF ChassisVersion; + STRING_REF ChassisSerialNumber; + STRING_REF ChassisAssetTag; + EFI_MISC_CHASSIS_STATUS ChassisType; + EFI_MISC_CHASSIS_STATE ChassisBootupState; + EFI_MISC_CHASSIS_STATE ChassisPowerSupplyState; + EFI_MISC_CHASSIS_STATE ChassisThermalState; + EFI_MISC_CHASSIS_SECURITY_STATE ChassisSecurityState; + UINT32 ChassisOemDefined; + UINT32 ChassisHeight; + UINT32 ChassisNumberPowerCords; + UINT32 ChassisElementCount; + UINT32 ChassisElementRecordLength;// + EFI_MISC_ELEMENTS ChassisElements; +} EFI_MISC_CHASSIS_MANUFACTURER_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. Port Connector Information - SMBIOS Type 8 +// +#define EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_RECORD_NUMBER 0x00000006 + +typedef enum { + EfiPortConnectorTypeNone = 0x00, + EfiPortConnectorTypeCentronics = 0x01, + EfiPortConnectorTypeMiniCentronics = 0x02, + EfiPortConnectorTypeProprietary = 0x03, + EfiPortConnectorTypeDB25Male = 0x04, + EfiPortConnectorTypeDB25Female = 0x05, + EfiPortConnectorTypeDB15Male = 0x06, + EfiPortConnectorTypeDB15Female = 0x07, + EfiPortConnectorTypeDB9Male = 0x08, + EfiPortConnectorTypeDB9Female = 0x09, + EfiPortConnectorTypeRJ11 = 0x0A, + EfiPortConnectorTypeRJ45 = 0x0B, + EfiPortConnectorType50PinMiniScsi = 0x0C, + EfiPortConnectorTypeMiniDin = 0x0D, + EfiPortConnectorTypeMicriDin = 0x0E, + EfiPortConnectorTypePS2 = 0x0F, + EfiPortConnectorTypeInfrared = 0x10, + EfiPortConnectorTypeHpHil = 0x11, + EfiPortConnectorTypeUsb = 0x12, + EfiPortConnectorTypeSsaScsi = 0x13, + EfiPortConnectorTypeCircularDin8Male = 0x14, + EfiPortConnectorTypeCircularDin8Female = 0x15, + EfiPortConnectorTypeOnboardIde = 0x16, + EfiPortConnectorTypeOnboardFloppy = 0x17, + EfiPortConnectorType9PinDualInline = 0x18, + EfiPortConnectorType25PinDualInline = 0x19, + EfiPortConnectorType50PinDualInline = 0x1A, + EfiPortConnectorType68PinDualInline = 0x1B, + EfiPortConnectorTypeOnboardSoundInput = 0x1C, + EfiPortConnectorTypeMiniCentronicsType14 = 0x1D, + EfiPortConnectorTypeMiniCentronicsType26 = 0x1E, + EfiPortConnectorTypeHeadPhoneMiniJack = 0x1F, + EfiPortConnectorTypeBNC = 0x20, + EfiPortConnectorType1394 = 0x21, + EfiPortConnectorTypePC98 = 0xA0, + EfiPortConnectorTypePC98Hireso = 0xA1, + EfiPortConnectorTypePCH98 = 0xA2, + EfiPortConnectorTypePC98Note = 0xA3, + EfiPortConnectorTypePC98Full = 0xA4, + EfiPortConnectorTypeOther = 0xFF, +} EFI_MISC_PORT_CONNECTOR_TYPE; + +typedef enum { + EfiPortTypeNone = 0x00, + EfiPortTypeParallelXtAtCompatible = 0x01, + EfiPortTypeParallelPortPs2 = 0x02, + EfiPortTypeParallelPortEcp = 0x03, + EfiPortTypeParallelPortEpp = 0x04, + EfiPortTypeParallelPortEcpEpp = 0x05, + EfiPortTypeSerialXtAtCompatible = 0x06, + EfiPortTypeSerial16450Compatible = 0x07, + EfiPortTypeSerial16550Compatible = 0x08, + EfiPortTypeSerial16550ACompatible = 0x09, + EfiPortTypeScsi = 0x0A, + EfiPortTypeMidi = 0x0B, + EfiPortTypeJoyStick = 0x0C, + EfiPortTypeKeyboard = 0x0D, + EfiPortTypeMouse = 0x0E, + EfiPortTypeSsaScsi = 0x0F, + EfiPortTypeUsb = 0x10, + EfiPortTypeFireWire = 0x11, + EfiPortTypePcmciaTypeI = 0x12, + EfiPortTypePcmciaTypeII = 0x13, + EfiPortTypePcmciaTypeIII = 0x14, + EfiPortTypeCardBus = 0x15, + EfiPortTypeAccessBusPort = 0x16, + EfiPortTypeScsiII = 0x17, + EfiPortTypeScsiWide = 0x18, + EfiPortTypePC98 = 0x19, + EfiPortTypePC98Hireso = 0x1A, + EfiPortTypePCH98 = 0x1B, + EfiPortTypeVideoPort = 0x1C, + EfiPortTypeAudioPort = 0x1D, + EfiPortTypeModemPort = 0x1E, + EfiPortTypeNetworkPort = 0x1F, + EfiPortType8251Compatible = 0xA0, + EfiPortType8251FifoCompatible = 0xA1, + EfiPortTypeOther = 0xFF, +} EFI_MISC_PORT_TYPE; + +typedef struct { + STRING_REF PortInternalConnectorDesignator; + STRING_REF PortExternalConnectorDesignator; + EFI_MISC_PORT_CONNECTOR_TYPE PortInternalConnectorType; + EFI_MISC_PORT_CONNECTOR_TYPE PortExternalConnectorType; + EFI_MISC_PORT_TYPE PortType; + EFI_MISC_PORT_DEVICE_PATH PortPath; +} EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. System Slots - SMBIOS Type 9 +// +#define EFI_MISC_SYSTEM_SLOT_DESIGNATION_RECORD_NUMBER 0x00000007 + +typedef enum { + EfiSlotTypeOther = 0x01, + EfiSlotTypeUnknown = 0x02, + EfiSlotTypeIsa = 0x03, + EfiSlotTypeMca = 0x04, + EfiSlotTypeEisa = 0x05, + EfiSlotTypePci = 0x06, + EfiSlotTypePcmcia = 0x07, + EfiSlotTypeVlVesa = 0x08, + EfiSlotTypeProprietary = 0x09, + EfiSlotTypeProcessorCardSlot = 0x0A, + EfiSlotTypeProprietaryMemoryCardSlot = 0x0B, + EfiSlotTypeIORiserCardSlot = 0x0C, + EfiSlotTypeNuBus = 0x0D, + EfiSlotTypePci66MhzCapable = 0x0E, + EfiSlotTypeAgp = 0x0F, + EfiSlotTypeApg2X = 0x10, + EfiSlotTypeAgp4X = 0x11, + EfiSlotTypePciX = 0x12, + EfiSlotTypeAgp4x = 0x13, + EfiSlotTypePC98C20 = 0xA0, + EfiSlotTypePC98C24 = 0xA1, + EfiSlotTypePC98E = 0xA2, + EfiSlotTypePC98LocalBus = 0xA3, + EfiSlotTypePC98Card = 0xA4, +} EFI_MISC_SLOT_TYPE; + +typedef enum { + EfiSlotDataBusWidthOther = 0x01, + EfiSlotDataBusWidthUnknown = 0x02, + EfiSlotDataBusWidth8Bit = 0x03, + EfiSlotDataBusWidth16Bit = 0x04, + EfiSlotDataBusWidth32Bit = 0x05, + EfiSlotDataBusWidth64Bit = 0x06, + EfiSlotDataBusWidth128Bit = 0x07, +} EFI_MISC_SLOT_DATA_BUS_WIDTH; + +typedef enum { + EfiSlotUsageOther = 1, + EfiSlotUsageUnknown = 2, + EfiSlotUsageAvailable = 3, + EfiSlotUsageInUse = 4, +} EFI_MISC_SLOT_USAGE; + +typedef enum { + EfiSlotLengthOther = 1, + EfiSlotLengthUnknown = 2, + EfiSlotLengthShort = 3, + EfiSlotLengthLong = 4 +} EFI_MISC_SLOT_LENGTH; + +typedef struct { + UINT32 CharacteristicsUnknown :1; + UINT32 Provides50Volts :1; + UINT32 Provides33Volts :1; + UINT32 SharedSlot :1; + UINT32 PcCard16Supported :1; + UINT32 CardBusSupported :1; + UINT32 ZoomVideoSupported :1; + UINT32 ModemRingResumeSupported:1; + UINT32 PmeSignalSupported :1; + UINT32 HotPlugDevicesSupported :1; + UINT32 SmbusSignalSupported :1; + UINT32 Reserved :21; +} EFI_MISC_SLOT_CHARACTERISTICS; + +typedef struct { + STRING_REF SlotDesignation; + EFI_MISC_SLOT_TYPE SlotType; + EFI_MISC_SLOT_DATA_BUS_WIDTH SlotDataBusWidth; + EFI_MISC_SLOT_USAGE SlotUsage; + EFI_MISC_SLOT_LENGTH SlotLength; + UINT16 SlotId; + EFI_MISC_SLOT_CHARACTERISTICS SlotCharacteristics; + EFI_DEVICE_PATH_PROTOCOL SlotDevicePath; +} EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. Onboard Device - SMBIOS Type 10 +// +#define EFI_MISC_ONBOARD_DEVICE_RECORD_NUMBER 0x00000008 + +typedef enum { + EfiOnBoardDeviceTypeOther = 1, + EfiOnBoardDeviceTypeUnknown = 2, + EfiOnBoardDeviceTypeVideo = 3, + EfiOnBoardDeviceTypeScsiController = 4, + EfiOnBoardDeviceTypeEthernet = 5, + EfiOnBoardDeviceTypeTokenRing = 6, + EfiOnBoardDeviceTypeSound = 7, +} EFI_MISC_ONBOARD_DEVICE_TYPE; + +typedef struct { + UINT32 DeviceType :16; + UINT32 DeviceEnabled :1; + UINT32 Reserved :15; +} EFI_MISC_ONBOARD_DEVICE_STATUS; + +typedef struct { + STRING_REF OnBoardDeviceDescription; + EFI_MISC_ONBOARD_DEVICE_STATUS OnBoardDeviceStatus; + EFI_DEVICE_PATH_PROTOCOL OnBoardDevicePath; +} EFI_MISC_ONBOARD_DEVICE_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. BIOS Language Information - SMBIOS Type 11 +// +#define EFI_MISC_OEM_STRING_RECORD_NUMBER 0x00000009 + +typedef struct { + STRING_REF OemStringRef[1]; +} EFI_MISC_OEM_STRING_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. System Options - SMBIOS Type 12 +// +typedef struct { + STRING_REF SystemOptionStringRef[1]; +} EFI_MISC_SYSTEM_OPTION_STRING_DATA; + +#define EFI_MISC_SYSTEM_OPTION_STRING_RECORD_NUMBER 0x0000000A + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. Number of Installable Languages - SMBIOS Type 13 +// +#define EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES_RECORD_NUMBER 0x0000000B + +typedef struct { + UINT32 AbbreviatedLanguageFormat :1; + UINT32 Reserved :31; +} EFI_MISC_LANGUAGE_FLAGS; + +typedef struct { + UINT16 NumberOfInstallableLanguages; + EFI_MISC_LANGUAGE_FLAGS LanguageFlags; + UINT16 CurrentLanguageNumber; +} EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. System Language String +// +#define EFI_MISC_SYSTEM_LANGUAGE_STRING_RECORD_NUMBER 0x0000000C + +typedef struct { + UINT16 LanguageId; + STRING_REF SystemLanguageString; +} EFI_MISC_SYSTEM_LANGUAGE_STRING_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Group Associations - SMBIOS Type 14 +// +#define EFI_MISC_GROUP_NAME_RECORD_NUMBER 0x0000000D + +typedef struct { + STRING_REF GroupName; + UINT16 NumberGroupItems; + UINT16 GroupId; +} EFI_MISC_GROUP_NAME_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Group Item Set Element +// +#define EFI_MISC_GROUP_ITEM_SET_RECORD_NUMBER 0x0000000E + +typedef struct { + EFI_GUID SubClass; + EFI_INTER_LINK_DATA GroupLink; + UINT16 GroupId; + UINT16 GroupElementId; +} EFI_MISC_GROUP_ITEM_SET_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. Pointing Device Type - SMBIOS Type 21 +// +#define EFI_MISC_POINTING_DEVICE_TYPE_RECORD_NUMBER 0x0000000F + +typedef enum { + EfiPointingDeviceTypeOther = 0x01, + EfiPointingDeviceTypeUnknown = 0x02, + EfiPointingDeviceTypeMouse = 0x03, + EfiPointingDeviceTypeTrackBall = 0x04, + EfiPointingDeviceTypeTrackPoint = 0x05, + EfiPointingDeviceTypeGlidePoint = 0x06, + EfiPointingDeviceTouchPad = 0x07, + EfiPointingDeviceTouchScreen = 0x08, + EfiPointingDeviceOpticalSensor = 0x09, +} EFI_MISC_POINTING_DEVICE_TYPE; + +typedef enum { + EfiPointingDeviceInterfaceOther = 0x01, + EfiPointingDeviceInterfaceUnknown = 0x02, + EfiPointingDeviceInterfaceSerial = 0x03, + EfiPointingDeviceInterfacePs2 = 0x04, + EfiPointingDeviceInterfaceInfrared = 0x05, + EfiPointingDeviceInterfaceHpHil = 0x06, + EfiPointingDeviceInterfaceBusMouse = 0x07, + EfiPointingDeviceInterfaceADB = 0x08, + EfiPointingDeviceInterfaceBusMouseDB9 = 0xA0, + EfiPointingDeviceInterfaceBusMouseMicroDin = 0xA1, + EfiPointingDeviceInterfaceUsb = 0xA2, +} EFI_MISC_POINTING_DEVICE_INTERFACE; + +typedef struct { + EFI_MISC_POINTING_DEVICE_TYPE PointingDeviceType; + EFI_MISC_POINTING_DEVICE_INTERFACE PointingDeviceInterface; + UINT16 NumberPointingDeviceButtons; + EFI_DEVICE_PATH_PROTOCOL PointingDevicePath; +} EFI_MISC_PORTING_DEVICE_TYPE_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Portable Battery - SMBIOS Type 22 +// +#define EFI_MISC_BATTERY_LOCATION_RECORD_NUMBER 0x00000010 + +typedef enum { + EfiBatteryDeviceChemistryTypeOther = 0x01, + EfiBatteryDeviceChemistryTypeUnknown = 0x02, + EfiBatteryDeviceChemistryTypeLeadAcid = 0x03, + EfiBatteryDeviceChemistryTypeNickelCadmium = 0x04, + EfiBatteryDeviceChemistryTypeNickelMetalHydride = 0x05, + EfiBatteryDeviceChemistryTypeLithiumIon = 0x06, + EfiBatteryDeviceChemistryTypeZincAir = 0x07, + EfiBatteryDeviceChemistryTypeLithiumPolymer = 0x08, +} EFI_MISC_BATTERY_DEVICE_CHEMISTRY; + +typedef struct { + UINT32 Date :5; + UINT32 Month :4; + UINT32 Year :7; + UINT32 Reserved :16; +} EFI_MISC_BATTERY_SBDS_MANUFACTURE_DATE; + +typedef struct { + STRING_REF BatteryLocation; + STRING_REF BatteryManufacturer; + STRING_REF BatteryManufactureDate; + STRING_REF BatterySerialNumber; + STRING_REF BatteryDeviceName; + STRING_REF BatterySbdsVersionNumber; + STRING_REF BatterySbdsDeviceChemistry; + EFI_MISC_BATTERY_DEVICE_CHEMISTRY BatteryDeviceChemistry; + EFI_EXP_BASE10_DATA BatteryDesignCapacity; + EFI_EXP_BASE10_DATA BatteryDesignVoltage; + UINT16 BatteryMaximumError; + UINT16 BatterySbdsSerialNumber; + EFI_MISC_BATTERY_SBDS_MANUFACTURE_DATE + BatterySbdsManufacturingDate; + UINT32 BatteryOemSpecific; +} EFI_MISC_BATTERY_LOCATION_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. Reset Capabilities - SMBIOS Type 23 +// +#define EFI_MISC_RESET_CAPABILITIES_RECORD_NUMBER 0x00000011 + +typedef struct { + UINT32 Status :1; + UINT32 BootOption :2; + UINT32 BootOptionOnLimit :2; + UINT32 WatchdogTimerPresent:1; + UINT32 Reserved :26; +} EFI_MISC_RESET_CAPABILITIES_TYPE; + +typedef struct { + EFI_MISC_RESET_CAPABILITIES_TYPE ResetCapabilities; + UINT16 ResetCount; + UINT16 ResetLimit; + UINT16 ResetTimerInterval; + UINT16 ResetTimeout; +} EFI_MISC_RESET_CAPABILITIES; + +typedef struct { + EFI_MISC_RESET_CAPABILITIES ResetCapabilities; + UINT16 ResetCount; + UINT16 ResetLimit; + UINT16 ResetTimerInterval; + UINT16 ResetTimeout; +} EFI_MISC_RESET_CAPABILITIES_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. Hardware Security - SMBIOS Type 24 +// +#define EFI_MISC_HARDWARE_SECURITY_RECORD_NUMBER 0x00000012 + +typedef enum { + EfiHardwareSecurityStatusDisabled = 0, + EfiHardwareSecurityStatusEnabled = 1, + EfiHardwareSecurityStatusNotImplemented = 2, + EfiHardwareSecurityStatusUnknown = 3 +} EFI_MISC_HARDWARE_SECURITY_STATUS; + +typedef struct { + EFI_MISC_HARDWARE_SECURITY_STATUS FrontPanelResetStatus :2; + EFI_MISC_HARDWARE_SECURITY_STATUS AdministratorPasswordStatus :2; + EFI_MISC_HARDWARE_SECURITY_STATUS KeyboardPasswordStatus :2; + EFI_MISC_HARDWARE_SECURITY_STATUS PowerOnPasswordStatus :2; + EFI_MISC_HARDWARE_SECURITY_STATUS Reserved :24; +} EFI_MISC_HARDWARE_SECURITY_SETTINGS; + +typedef struct { + EFI_MISC_HARDWARE_SECURITY_SETTINGS HardwareSecuritySettings; +} EFI_MISC_HARDWARE_SECURITY_SETTINGS_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// System Power Controls - SMBIOS Type 25 +// +#define EFI_MISC_SCHEDULED_POWER_ON_MONTH_RECORD_NUMBER 0x00000013 + +typedef struct { + UINT16 ScheduledPoweronMonth; + UINT16 ScheduledPoweronDayOfMonth; + UINT16 ScheduledPoweronHour; + UINT16 ScheduledPoweronMinute; + UINT16 ScheduledPoweronSecond; +} EFI_MISC_SCHEDULED_POWER_ON_MONTH_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Voltage Probe - SMBIOS Type 26 +// +#define EFI_MISC_VOLTAGE_PROBE_DESCRIPTION_RECORD_NUMBER 0x00000014 + +typedef struct { + UINT32 VoltageProbeSite :5; + UINT32 VoltageProbeStatus :3; + UINT32 Reserved :24; +} EFI_MISC_VOLTAGE_PROBE_LOCATION; + +typedef struct { + STRING_REF VoltageProbeDescription; + EFI_MISC_VOLTAGE_PROBE_LOCATION VoltageProbeLocation; + EFI_EXP_BASE10_DATA VoltageProbeMaximumValue; + EFI_EXP_BASE10_DATA VoltageProbeMinimumValue; + EFI_EXP_BASE10_DATA VoltageProbeResolution; + EFI_EXP_BASE10_DATA VoltageProbeTolerance; + EFI_EXP_BASE10_DATA VoltageProbeAccuracy; + EFI_EXP_BASE10_DATA VoltageProbeNominalValue; + EFI_EXP_BASE10_DATA MDLowerNoncriticalThreshold; + EFI_EXP_BASE10_DATA MDUpperNoncriticalThreshold; + EFI_EXP_BASE10_DATA MDLowerCriticalThreshold; + EFI_EXP_BASE10_DATA MDUpperCriticalThreshold; + EFI_EXP_BASE10_DATA MDLowerNonrecoverableThreshold; + EFI_EXP_BASE10_DATA MDUpperNonrecoverableThreshold; + UINT32 VoltageProbeOemDefined; +} EFI_MISC_VOLTAGE_PROBE_DESCRIPTION_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Cooling Device - SMBIOS Type 27 +// +#define EFI_MISC_COOLING_DEVICE_TEMP_LINK_RECORD_NUMBER 0x00000015 + +typedef struct { + UINT32 CoolingDevice :5; + UINT32 CoolingDeviceStatus :3; + UINT32 Reserved :24; +} EFI_MISC_COOLING_DEVICE_TYPE; + +typedef struct { + EFI_MISC_COOLING_DEVICE_TYPE CoolingDeviceType; + EFI_INTER_LINK_DATA CoolingDeviceTemperatureLink; + UINT16 CoolingDeviceUnitGroup; + EFI_EXP_BASE10_DATA CoolingDeviceNominalSpeed; + UINT32 CoolingDeviceOemDefined; +} EFI_MISC_COOLING_DEVICE_TEMP_LINK_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Temperature Probe - SMBIOS Type 28 +// +#define EFI_MISC_TEMPERATURE_PROBE_DESCRIPTION_RECORD_NUMBER 0x00000016 + +typedef struct { + UINT32 TemperatureProbeSite :5; + UINT32 TemperatureProbeStatus :3; + UINT32 Reserved :24; +} EFI_MISC_TEMPERATURE_PROBE_LOCATION; + +typedef struct { + STRING_REF TemperatureProbeDescription; + EFI_MISC_TEMPERATURE_PROBE_LOCATION + TemperatureProbeLocation; + EFI_EXP_BASE10_DATA TemperatureProbeMaximumValue; + EFI_EXP_BASE10_DATA TemperatureProbeMinimumValue; + EFI_EXP_BASE10_DATA TemperatureProbeResolution; + EFI_EXP_BASE10_DATA TemperatureProbeTolerance; + EFI_EXP_BASE10_DATA TemperatureProbeAccuracy; + EFI_EXP_BASE10_DATA TemperatureProbeNominalValue; + EFI_EXP_BASE10_DATA MDLowerNoncriticalThreshold; + EFI_EXP_BASE10_DATA MDUpperNoncriticalThreshold; + EFI_EXP_BASE10_DATA MDLowerCriticalThreshold; + EFI_EXP_BASE10_DATA MDUpperCriticalThreshold; + EFI_EXP_BASE10_DATA MDLowerNonrecoverableThreshold; + EFI_EXP_BASE10_DATA MDUpperNonrecoverableThreshold; + UINT32 TemperatureProbeOemDefined; +} EFI_MISC_TEMPERATURE_PROBE_DESCRIPTION_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Electrical Current Probe - SMBIOS Type 29 +// + +#define EFI_MISC_ELECTRICAL_CURRENT_PROBE_DESCRIPTION_RECORD_NUMBER 0x00000017 + +typedef struct { + UINT32 ElectricalCurrentProbeSite :5; + UINT32 ElectricalCurrentProbeStatus :3; + UINT32 Reserved :24; +} EFI_MISC_ELECTRICAL_CURRENT_PROBE_LOCATION; + +typedef struct { + STRING_REF ElectricalCurrentProbeDescription; + EFI_MISC_ELECTRICAL_CURRENT_PROBE_LOCATION + ElectricalCurrentProbeLocation; + EFI_EXP_BASE10_DATA ElectricalCurrentProbeMaximumValue; + EFI_EXP_BASE10_DATA ElectricalCurrentProbeMinimumValue; + EFI_EXP_BASE10_DATA ElectricalCurrentProbeResolution; + EFI_EXP_BASE10_DATA ElectricalCurrentProbeTolerance; + EFI_EXP_BASE10_DATA ElectricalCurrentProbeAccuracy; + EFI_EXP_BASE10_DATA ElectricalCurrentProbeNominalValue; + EFI_EXP_BASE10_DATA MDLowerNoncriticalThreshold; + EFI_EXP_BASE10_DATA MDUpperNoncriticalThreshold; + EFI_EXP_BASE10_DATA MDLowerCriticalThreshold; + EFI_EXP_BASE10_DATA MDUpperCriticalThreshold; + EFI_EXP_BASE10_DATA MDLowerNonrecoverableThreshold; + EFI_EXP_BASE10_DATA MDUpperNonrecoverableThreshold; + UINT32 ElectricalCurrentProbeOemDefined; +} EFI_MISC_ELECTRICAL_CURRENT_PROBE_DESCRIPTION_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Out-of-Band Remote Access - SMBIOS Type 30 +// + +#define EFI_MISC_REMOTE_ACCESS_MANUFACTURER_DESCRIPTION_RECORD_NUMBER 0x00000018 + +typedef struct { + UINT32 InboundConnectionEnabled :1; + UINT32 OutboundConnectionEnabled :1; + UINT32 Reserved :30; +} EFI_MISC_REMOTE_ACCESS_CONNECTIONS; + +typedef struct { + STRING_REF RemoteAccessManufacturerNameDescription; + EFI_MISC_REMOTE_ACCESS_CONNECTIONS RemoteAccessConnections; +} EFI_MISC_REMOTE_ACCESS_MANUFACTURER_DESCRIPTION_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. BIS Entry Point - SMBIOS Type 31 +// +#define EFI_MISC_BIS_ENTRY_POINT_RECORD_NUMBER 0x00000019 + +typedef struct { + EFI_PHYSICAL_ADDRESS BisEntryPoint; +} EFI_MISC_BIS_ENTRY_POINT_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Misc. Boot Information - SMBIOS Type 32 +// +#define EFI_MISC_BOOT_INFORMATION_STATUS_RECORD_NUMBER 0x0000001A + +typedef enum { + EfiBootInformationStatusNoError = 0x00, + EfiBootInformationStatusNoBootableMedia = 0x01, + EfiBootInformationStatusNormalOSFailedLoading = 0x02, + EfiBootInformationStatusFirmwareDetectedFailure = 0x03, + EfiBootInformationStatusOSDetectedFailure = 0x04, + EfiBootInformationStatusUserRequestedBoot = 0x05, + EfiBootInformationStatusSystemSecurityViolation = 0x06, + EfiBootInformationStatusPreviousRequestedImage = 0x07, + EfiBootInformationStatusWatchdogTimerExpired = 0x08, + EfiBootInformationStatusStartReserved = 0x09, + EfiBootInformationStatusStartOemSpecific = 0x80, + EfiBootInformationStatusStartProductSpecific = 0xC0, +} EFI_MISC_BOOT_INFORMATION_STATUS_DATA_TYPE; + +typedef struct { + EFI_MISC_BOOT_INFORMATION_STATUS_DATA_TYPE BootInformationStatus; + UINT8 BootInformationData[9]; +} EFI_MISC_BOOT_INFORMATION_STATUS_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Management Device - SMBIOS Type 34 +// +#define EFI_MISC_MANAGEMENT_DEVICE_DESCRIPTION_RECORD_NUMBER 0x0000001B + +typedef enum { + EfiManagementDeviceTypeOther = 0x01, + EfiManagementDeviceTypeUnknown = 0x02, + EfiManagementDeviceTypeLm75 = 0x03, + EfiManagementDeviceTypeLm78 = 0x04, + EfiManagementDeviceTypeLm79 = 0x05, + EfiManagementDeviceTypeLm80 = 0x06, + EfiManagementDeviceTypeLm81 = 0x07, + EfiManagementDeviceTypeAdm9240 = 0x08, + EfiManagementDeviceTypeDs1780 = 0x09, + EfiManagementDeviceTypeMaxim1617 = 0x0A, + EfiManagementDeviceTypeGl518Sm = 0x0B, + EfiManagementDeviceTypeW83781D = 0x0C, + EfiManagementDeviceTypeHt82H791 = 0x0D, +} EFI_MISC_MANAGEMENT_DEVICE_TYPE; + +typedef enum { + EfiManagementDeviceAddressTypeOther = 1, + EfiManagementDeviceAddressTypeUnknown = 2, + EfiManagementDeviceAddressTypeIOPort = 3, + EfiManagementDeviceAddressTypeMemory = 4, + EfiManagementDeviceAddressTypeSmbus = 5 +} EFI_MISC_MANAGEMENT_DEVICE_ADDRESS_TYPE; + +typedef struct { + STRING_REF ManagementDeviceDescription; + EFI_MISC_MANAGEMENT_DEVICE_TYPE ManagementDeviceType; + UINTN ManagementDeviceAddress; + EFI_MISC_MANAGEMENT_DEVICE_ADDRESS_TYPE + ManagementDeviceAddressType; +} EFI_MISC_MANAGEMENT_DEVICE_DESCRIPTION_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// Management Device Component - SMBIOS Type 35 +// + +#define EFI_MISC_MANAGEMENT_DEVICE_COMPONENT_DESCRIPTION_RECORD_NUMBER 0x0000001C + +typedef struct { + STRING_REF ManagementDeviceComponentDescription; + EFI_INTER_LINK_DATA ManagementDeviceLink; + EFI_INTER_LINK_DATA ManagementDeviceComponentLink; +} EFI_MISC_MANAGEMENT_DEVICE_COMPONENT_DESCRIPTION_DATA; + +// +////////////////////////////////////////////////////////////////////////////// +// +// IPMI Data Record - SMBIOS Type 38 +// +typedef enum { + EfiIpmiOther = 0, + EfiIpmiKcs = 1, + EfiIpmiSmic = 2, + EfiIpmiBt = 3, +} EFI_MISC_IPMI_INTERFACE_TYPE; + +typedef struct { + UINT16 IpmiSpecLeastSignificantDigit:4; + UINT16 IpmiSpecMostSignificantDigit: 4; + UINT16 Reserved: 8; +} EFI_MISC_IPMI_SPECIFICATION_REVISION; + +typedef struct { + EFI_MISC_IPMI_INTERFACE_TYPE IpmiInterfaceType; + EFI_MISC_IPMI_SPECIFICATION_REVISION IpmiSpecificationRevision; + UINT16 IpmiI2CSlaveAddress; + UINT16 IpmiNvDeviceAddress; + UINT64 IpmiBaseAddress; + EFI_DEVICE_PATH_PROTOCOL IpmiDevicePath; +} EFI_MISC_IPMI_INTERFACE_TYPE_DATA; + +#define EFI_MISC_IPMI_INTERFACE_TYPE_RECORD_NUMBER 0x0000001D + +// +////////////////////////////////////////////////////////////////////////////// +// +//System Power supply Record - SMBIOS Type 39 +// +typedef struct { + UINT16 PowerSupplyHotReplaceable :1; + UINT16 PowerSupplyPresent :1; + UINT16 PowerSupplyUnplugged :1; + UINT16 InputVoltageRangeSwitch :4; + UINT16 PowerSupplyStatus :3; + UINT16 PowerSupplyType :4; + UINT16 Reserved :2; +} POWER_SUPPLY_CHARACTERISTICS; + +typedef struct { + UINT16 PowerUnitGroup; + STRING_REF PowerSupplyLocation; + STRING_REF PowerSupplyDeviceName; + STRING_REF PowerSupplyManufacturer; + STRING_REF PowerSupplySerialNumber; + STRING_REF PowerSupplyAssetTagNumber; + STRING_REF PowerSupplyModelPartNumber; + STRING_REF PowerSupplyRevisionLevel; + UINT16 PowerSupplyMaxPowerCapacity; + POWER_SUPPLY_CHARACTERISTICS PowerSupplyCharacteristics; + EFI_INTER_LINK_DATA PowerSupplyInputVoltageProbeLink; + EFI_INTER_LINK_DATA PowerSupplyCoolingDeviceLink; + EFI_INTER_LINK_DATA PowerSupplyInputCurrentProbeLink; +} EFI_MISC_SYSTEM_POWER_SUPPLY_DATA; + +#define EFI_MISC_SYSTEM_POWER_SUPPLY_RECORD_NUMBER 0x0000001E + +// +////////////////////////////////////////////////////////////////////////////// +// +// OEM Data Record - SMBIOS Type 0x80-0xFF +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Handle; +} SMBIOS_STRUCTURE_HDR; + +typedef struct { + SMBIOS_STRUCTURE_HDR Header; + UINT8 RawData[1]; +} EFI_MISC_SMBIOS_STRUCT_ENCAPSULATION_DATA; + +#define EFI_MISC_SMBIOS_STRUCT_ENCAP_RECORD_NUMBER 0x0000001F + +// +////////////////////////////////////////////////////////////////////////////// +// +typedef union { + EFI_MISC_LAST_PCI_BUS_DATA LastPciBus; + EFI_MISC_BIOS_VENDOR_DATA MiscBiosVendor; + EFI_MISC_SYSTEM_MANUFACTURER_DATA MiscSystemManufacturer; + EFI_MISC_BASE_BOARD_MANUFACTURER_DATA MiscBaseBoardManufacturer; + EFI_MISC_CHASSIS_MANUFACTURER_DATA MiscChassisManufacturer; + EFI_MISC_PORT_INTERNAL_CONNECTOR_DESIGNATOR_DATA MiscPortInternalConnectorDesignator; + EFI_MISC_SYSTEM_SLOT_DESIGNATION_DATA MiscSystemSlotDesignation; + EFI_MISC_ONBOARD_DEVICE_DATA MiscOnboardDevice; + EFI_MISC_OEM_STRING_DATA MiscOemString; + EFI_MISC_SYSTEM_OPTION_STRING_DATA MiscOptionString; + EFI_MISC_NUMBER_OF_INSTALLABLE_LANGUAGES_DATA NumberOfInstallableLanguages; + EFI_MISC_SYSTEM_LANGUAGE_STRING_DATA MiscSystemLanguageString; + EFI_MISC_GROUP_NAME_DATA MiscGroupNameData; + EFI_MISC_GROUP_ITEM_SET_DATA MiscGroupItemSetData; + EFI_MISC_PORTING_DEVICE_TYPE_DATA MiscPortingDeviceTypeData; + EFI_MISC_RESET_CAPABILITIES_DATA MiscResetCapablilitiesData; + EFI_MISC_HARDWARE_SECURITY_SETTINGS_DATA MiscHardwareSecuritySettingsData; + EFI_MISC_SCHEDULED_POWER_ON_MONTH_DATA MiscScheduledPowerOnMonthData; + EFI_MISC_VOLTAGE_PROBE_DESCRIPTION_DATA MiscVoltagePorbeDescriptionData; + EFI_MISC_COOLING_DEVICE_TEMP_LINK_DATA MiscCoolingDeviceTempLinkData; + EFI_MISC_TEMPERATURE_PROBE_DESCRIPTION_DATA MiscTemperatureProbeDescriptionData; + EFI_MISC_ELECTRICAL_CURRENT_PROBE_DESCRIPTION_DATA MiscElectricalCurrentProbeDescriptionData; + EFI_MISC_REMOTE_ACCESS_MANUFACTURER_DESCRIPTION_DATA + MiscRemoteAccessManufacturerDescriptionData; + EFI_MISC_BIS_ENTRY_POINT_DATA MiscBisEntryPoint; + EFI_MISC_BOOT_INFORMATION_STATUS_DATA MiscBootInformationStatus; + EFI_MISC_MANAGEMENT_DEVICE_DESCRIPTION_DATA MiscMangementDeviceDescriptionData; + EFI_MISC_MANAGEMENT_DEVICE_COMPONENT_DESCRIPTION_DATA + MiscmangementDeviceComponentDescriptionData; + EFI_MISC_IPMI_INTERFACE_TYPE_DATA MiscIpmiInterfaceTypeData; + EFI_MISC_SYSTEM_POWER_SUPPLY_DATA MiscPowerSupplyInfo; + EFI_MISC_SMBIOS_STRUCT_ENCAPSULATION_DATA MiscSmbiosStructEncapsulation; +} EFI_MISC_SUBCLASS_RECORDS; + +// +// +// +typedef struct { + EFI_SUBCLASS_TYPE1_HEADER Header; + EFI_MISC_SUBCLASS_RECORDS Record; +} EFI_MISC_SUBCLASS_DRIVER_DATA; + +#pragma pack() + +// +// Sub Class Header type1 +// + +#define EFI_SUBCLASS_INSTANCE_RESERVED 0 +#define EFI_SUBCLASS_INSTANCE_NON_APPLICABLE 0xFFFF //16 bit + +#endif + diff --git a/MdePkg/Include/Common/Dependency.h b/MdePkg/Include/Common/Dependency.h new file mode 100644 index 0000000000..744027d2f3 --- /dev/null +++ b/MdePkg/Include/Common/Dependency.h @@ -0,0 +1,50 @@ +/** @file + This module contains data specific to dependency expressions + and local function prototypes. + + Copyright (c) 2006, 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. + + Module Name: Dependency.h + +**/ + +#ifndef __DEPENDENCY_H__ +#define __DEPENDENCY_H__ + +/// EFI_DEP_BEFORE - If present, this must be the first and only opcode +#define EFI_DEP_BEFORE 0x00 + +/// EFI_DEP_AFTER - If present, this must be the first and only opcode +#define EFI_DEP_AFTER 0x01 + +#define EFI_DEP_PUSH 0x02 +#define EFI_DEP_AND 0x03 +#define EFI_DEP_OR 0x04 +#define EFI_DEP_NOT 0x05 +#define EFI_DEP_TRUE 0x06 +#define EFI_DEP_FALSE 0x07 +#define EFI_DEP_END 0x08 + +/// EFI_DEP_SOR - If present, this must be the first opcode +#define EFI_DEP_SOR 0x09 + +/// +/// EFI_DEP_REPLACE_TRUE - Used to dynamically patch the dependecy expression +/// to save time. A EFI_DEP_PUSH is evauated one an +/// replaced with EFI_DEP_REPLACE_TRUE +/// +#define EFI_DEP_REPLACE_TRUE 0xff + +/// +/// Define the initial size of the dependency expression evaluation stack +/// +#define DEPEX_STACK_SIZE_INCREMENT 0x1000 + +#endif diff --git a/MdePkg/Include/Common/EfiImage.h b/MdePkg/Include/Common/EfiImage.h new file mode 100644 index 0000000000..ebe251e479 --- /dev/null +++ b/MdePkg/Include/Common/EfiImage.h @@ -0,0 +1,698 @@ +/** @file + EFI image format for PE32+. Please note some data structures are different + for IA-32 and Itanium-based images, look for UINTN and the #ifdef EFI_IA64 + + @bug Fix text - doc as defined in MSFT EFI specification. + + Copyright (c) 2006, 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. + + Module Name: EfiImage.h + +**/ + +#ifndef __EFI_IMAGE_H__ +#define __EFI_IMAGE_H__ + +// +// PE32+ Subsystem type for EFI images +// +#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 + +// +// BugBug: Need to get a real answer for this problem. This is not in the +// PE specification. +// +// A SAL runtime driver does not get fixed up when a transition to +// virtual mode is made. In all other cases it should be treated +// like a EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER image +// +#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 + +// +// PE32+ Machine type for EFI images +// +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_IA64 0x0200 +#define IMAGE_FILE_MACHINE_EBC 0x0EBC +#define IMAGE_FILE_MACHINE_X64 0x8664 +// +// Support old names for backward compatible +// +#define EFI_IMAGE_MACHINE_IA32 IMAGE_FILE_MACHINE_I386 +#define EFI_IMAGE_MACHINE_IA64 IMAGE_FILE_MACHINE_IA64 +#define EFI_IMAGE_MACHINE_IPF IMAGE_FILE_MACHINE_IA64 +#define EFI_IMAGE_MACHINE_EBC IMAGE_FILE_MACHINE_EBC +#define EFI_IMAGE_MACHINE_X64 IMAGE_FILE_MACHINE_X64 + +#define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define EFI_IMAGE_OS2_SIGNATURE 0x454E // NE +#define EFI_IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define EFI_IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define EFI_IMAGE_EDOS_SIGNATURE 0x44454550 // PEED + +/// +/// PE images can start with an optional DOS header, so if an image is run +/// under DOS it can print an error message. +/// +typedef struct { + UINT16 e_magic; // Magic number + UINT16 e_cblp; // Bytes on last page of file + UINT16 e_cp; // Pages in file + UINT16 e_crlc; // Relocations + UINT16 e_cparhdr; // Size of header in paragraphs + UINT16 e_minalloc; // Minimum extra paragraphs needed + UINT16 e_maxalloc; // Maximum extra paragraphs needed + UINT16 e_ss; // Initial (relative) SS value + UINT16 e_sp; // Initial SP value + UINT16 e_csum; // Checksum + UINT16 e_ip; // Initial IP value + UINT16 e_cs; // Initial (relative) CS value + UINT16 e_lfarlc; // File address of relocation table + UINT16 e_ovno; // Overlay number + UINT16 e_res[4]; // Reserved words + UINT16 e_oemid; // OEM identifier (for e_oeminfo) + UINT16 e_oeminfo; // OEM information; e_oemid specific + UINT16 e_res2[10]; // Reserved words + UINT32 e_lfanew; // File address of new exe header +} EFI_IMAGE_DOS_HEADER; + +/// +/// File header format. +/// +typedef struct { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} EFI_IMAGE_FILE_HEADER; + +#define EFI_IMAGE_SIZEOF_FILE_HEADER 20 + +#define EFI_IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define EFI_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define EFI_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define EFI_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define EFI_IMAGE_FILE_SYSTEM 0x1000 // System File. +#define EFI_IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define EFI_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. +#define EFI_IMAGE_FILE_MACHINE_UNKNOWN 0 +#define EFI_IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define EFI_IMAGE_FILE_MACHINE_R3000 0x162 // MIPS* little-endian, 0540 big-endian +#define EFI_IMAGE_FILE_MACHINE_R4000 0x166 // MIPS* little-endian +#define EFI_IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP* +#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM* PowerPC Little-Endian +#define EFI_IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine +// +// * Other names and brands may be claimed as the property of others. +// + +/// +/// Directory format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 Size; +} EFI_IMAGE_DATA_DIRECTORY; + +#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16 + +typedef struct { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + UINT32 BaseOfBss; + UINT32 GprMask; + UINT32 CprMask[4]; + UINT32 GpValue; +} EFI_IMAGE_ROM_OPTIONAL_HEADER; + +#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 +#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER) + +typedef struct { + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} EFI_IMAGE_ROM_HEADERS; + +/// +/// @attention +/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64 +/// are for use ONLY by tools. All proper EFI code MUST use +/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!! +/// +#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b + +typedef struct { + // + // Standard fields. + // + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + // + // NT additional fields. + // + UINT32 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Win32VersionValue; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT32 SizeOfStackReserve; + UINT32 SizeOfStackCommit; + UINT32 SizeOfHeapReserve; + UINT32 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; +} EFI_IMAGE_OPTIONAL_HEADER32; + +/// +/// @attention +/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64 +/// are for use ONLY by tools. All proper EFI code MUST use +/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!! +/// +#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b + +typedef struct { + // + // Standard fields. + // + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + // + // NT additional fields. + // + UINT64 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Win32VersionValue; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT64 SizeOfStackReserve; + UINT64 SizeOfStackCommit; + UINT64 SizeOfHeapReserve; + UINT64 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; +} EFI_IMAGE_OPTIONAL_HEADER64; + +/// +/// @attention +/// EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY +/// by tools. All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!! +/// +typedef struct { + UINT32 Signature; + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader; +} EFI_IMAGE_NT_HEADERS32; + +#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32) + +typedef struct { + UINT32 Signature; + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} EFI_IMAGE_NT_HEADERS64; + +#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64) + +// +// Processor specific definition of EFI_IMAGE_OPTIONAL_HEADER so the +// type name EFI_IMAGE_OPTIONAL_HEADER is appropriate to the build. Same for +// EFI_IMAGE_NT_HEADERS. These definitions MUST be used by ALL EFI code. +// +#if defined (MDE_CPU_IA32) + +typedef EFI_IMAGE_OPTIONAL_HEADER32 EFI_IMAGE_OPTIONAL_HEADER; +typedef EFI_IMAGE_NT_HEADERS32 EFI_IMAGE_NT_HEADERS; + +#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#elif defined (MDE_CPU_IPF) + +typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER; +typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS; + +#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_IPF) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#elif defined (MDE_CPU_X64) + +typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER; +typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS; + +#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#elif defined (MDE_CPU_EBC) + +// +// This is just to make sure you can cross compile with the EBC compiiler. +// It does not make sense to have a PE loader coded in EBC. You need to +// understand the basic +// +typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER; +typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS; + +#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC) + +#else +#error Unknown Processor Type +#endif + + +#define EFI_IMAGE_FIRST_SECTION(ntheader) \ + ( \ + (EFI_IMAGE_SECTION_HEADER *) \ + ( \ + (UINT32) ntheader + \ + FIELD_OFFSET (EFI_IMAGE_NT_HEADERS, OptionalHeader) + \ + ((EFI_IMAGE_NT_HEADERS *) (ntheader))->FileHeader.SizeOfOptionalHeader \ + ) \ + ) + +// +// Subsystem Values +// +#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0 +#define EFI_IMAGE_SUBSYSTEM_NATIVE 1 +#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3. +#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5 +#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7 + +// +// Directory Entries +// +#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0 +#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1 +#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 +#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4 +#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5 +#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6 +#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 +#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 +#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9 +#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 + +// +// Section header format. +// +#define EFI_IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct { + UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} EFI_IMAGE_SECTION_HEADER; + +#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40 + +#define EFI_IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. +#define EFI_IMAGE_SCN_CNT_CODE 0x00000020 +#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 + +#define EFI_IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define EFI_IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +#define EFI_IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define EFI_IMAGE_SCN_LNK_COMDAT 0x00001000 + +#define EFI_IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define EFI_IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define EFI_IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define EFI_IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define EFI_IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define EFI_IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define EFI_IMAGE_SCN_ALIGN_64BYTES 0x00700000 + +#define EFI_IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define EFI_IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define EFI_IMAGE_SCN_MEM_NOT_PAGED 0x08000000 +#define EFI_IMAGE_SCN_MEM_SHARED 0x10000000 +#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define EFI_IMAGE_SCN_MEM_READ 0x40000000 +#define EFI_IMAGE_SCN_MEM_WRITE 0x80000000 + +/// +/// Symbol format. +/// +#define EFI_IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// +#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 // Symbol is undefined or is common. +#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 // Symbol is an absolute value. +#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 // Symbol is a special debug item. +// +// Type (fundamental) values. +// +#define EFI_IMAGE_SYM_TYPE_NULL 0 // no type. +#define EFI_IMAGE_SYM_TYPE_VOID 1 // +#define EFI_IMAGE_SYM_TYPE_CHAR 2 // type character. +#define EFI_IMAGE_SYM_TYPE_SHORT 3 // type short integer. +#define EFI_IMAGE_SYM_TYPE_INT 4 +#define EFI_IMAGE_SYM_TYPE_LONG 5 +#define EFI_IMAGE_SYM_TYPE_FLOAT 6 +#define EFI_IMAGE_SYM_TYPE_DOUBLE 7 +#define EFI_IMAGE_SYM_TYPE_STRUCT 8 +#define EFI_IMAGE_SYM_TYPE_UNION 9 +#define EFI_IMAGE_SYM_TYPE_ENUM 10 // enumeration. +#define EFI_IMAGE_SYM_TYPE_MOE 11 // member of enumeration. +#define EFI_IMAGE_SYM_TYPE_BYTE 12 +#define EFI_IMAGE_SYM_TYPE_WORD 13 +#define EFI_IMAGE_SYM_TYPE_UINT 14 +#define EFI_IMAGE_SYM_TYPE_DWORD 15 + +// +// Type (derived) values. +// +#define EFI_IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define EFI_IMAGE_SYM_DTYPE_POINTER 1 +#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2 +#define EFI_IMAGE_SYM_DTYPE_ARRAY 3 + +// +// Storage classes. +// +#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION (UINT8) -1 +#define EFI_IMAGE_SYM_CLASS_NULL 0 +#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1 +#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2 +#define EFI_IMAGE_SYM_CLASS_STATIC 3 +#define EFI_IMAGE_SYM_CLASS_REGISTER 4 +#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define EFI_IMAGE_SYM_CLASS_LABEL 6 +#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9 +#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12 +#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18 +#define EFI_IMAGE_SYM_CLASS_BLOCK 100 +#define EFI_IMAGE_SYM_CLASS_FUNCTION 101 +#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define EFI_IMAGE_SYM_CLASS_FILE 103 +#define EFI_IMAGE_SYM_CLASS_SECTION 104 +#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// +// type packing constants +// +#define EFI_IMAGE_N_BTMASK 017 +#define EFI_IMAGE_N_TMASK 060 +#define EFI_IMAGE_N_TMASK1 0300 +#define EFI_IMAGE_N_TMASK2 0360 +#define EFI_IMAGE_N_BTSHFT 4 +#define EFI_IMAGE_N_TSHIFT 2 + +// +// Communal selection types. +// +#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define EFI_IMAGE_COMDAT_SELECT_ANY 2 +#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + +/// +/// Relocation format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} EFI_IMAGE_RELOCATION; + +#define EFI_IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// +#define EFI_IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define EFI_IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address +#define EFI_IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address +#define EFI_IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address +#define EFI_IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included +#define EFI_IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define EFI_IMAGE_REL_I386_SECTION 012 +#define EFI_IMAGE_REL_I386_SECREL 013 +#define EFI_IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address + +/// +/// Based relocation format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +} EFI_IMAGE_BASE_RELOCATION; + +#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// +#define EFI_IMAGE_REL_BASED_ABSOLUTE 0 +#define EFI_IMAGE_REL_BASED_HIGH 1 +#define EFI_IMAGE_REL_BASED_LOW 2 +#define EFI_IMAGE_REL_BASED_HIGHLOW 3 +#define EFI_IMAGE_REL_BASED_HIGHADJ 4 +#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define EFI_IMAGE_REL_BASED_IA64_IMM64 9 +#define EFI_IMAGE_REL_BASED_DIR64 10 + +/// +/// Line number format. +/// +typedef struct { + union { + UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; // Virtual address of line number. + } Type; + UINT16 Linenumber; // Line number. +} EFI_IMAGE_LINENUMBER; + +#define EFI_IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// +#define EFI_IMAGE_ARCHIVE_START_SIZE 8 +#define EFI_IMAGE_ARCHIVE_START "!\n" +#define EFI_IMAGE_ARCHIVE_END "`\n" +#define EFI_IMAGE_ARCHIVE_PAD "\n" +#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct { + UINT8 Name[16]; // File member name - `/' terminated. + UINT8 Date[12]; // File member date - decimal. + UINT8 UserID[6]; // File member user id - decimal. + UINT8 GroupID[6]; // File member group id - decimal. + UINT8 Mode[8]; // File member mode - octal. + UINT8 Size[10]; // File member size - decimal. + UINT8 EndHeader[2]; // String to end header. +} EFI_IMAGE_ARCHIVE_MEMBER_HEADER; + +#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +/// +/// DLL Export Format +/// +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32 AddressOfFunctions; + UINT32 AddressOfNames; + UINT32 AddressOfNameOrdinals; +} EFI_IMAGE_EXPORT_DIRECTORY; + +/// +/// DLL support. +/// Import Format +/// +typedef struct { + UINT16 Hint; + UINT8 Name[1]; +} EFI_IMAGE_IMPORT_BY_NAME; + +typedef struct { + union { + UINT32 Function; + UINT32 Ordinal; + EFI_IMAGE_IMPORT_BY_NAME *AddressOfData; + } u1; +} EFI_IMAGE_THUNK_DATA; + +#define EFI_IMAGE_ORDINAL_FLAG 0x80000000 +#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0) +#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + EFI_IMAGE_THUNK_DATA *FirstThunk; +} EFI_IMAGE_IMPORT_DESCRIPTOR; + +/// +/// Debug Format +/// +#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 + +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Type; + UINT32 SizeOfData; + UINT32 RVA; + UINT32 FileOffset; +} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY; + +#define CODEVIEW_SIGNATURE_NB10 0x3031424E // "NB10" +typedef struct { + UINT32 Signature; // "NB10" + UINT32 Unknown; + UINT32 Unknown2; + UINT32 Unknown3; + // + // Filename of .PDB goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY; + +#define CODEVIEW_SIGNATURE_RSDS 0x53445352 // "RSDS" +typedef struct { + UINT32 Signature; // "RSDS" + UINT32 Unknown; + UINT32 Unknown2; + UINT32 Unknown3; + UINT32 Unknown4; + UINT32 Unknown5; + // + // Filename of .PDB goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY; + +/// +/// Header format for TE images +/// +typedef struct { + UINT16 Signature; // signature for TE format = "VZ" + UINT16 Machine; // from the original file header + UINT8 NumberOfSections; // from the original file header + UINT8 Subsystem; // from original optional header + UINT16 StrippedSize; // how many bytes we removed from the header + UINT32 AddressOfEntryPoint; // offset to entry point -- from original optional header + UINT32 BaseOfCode; // from original image -- required for ITP debug + UINT64 ImageBase; // from original file header + EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; // only base relocation and debug directory +} EFI_TE_IMAGE_HEADER; + +#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56 // "VZ" + +// +// Data directory indexes in our TE image header +// +#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0 +#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1 + +#endif diff --git a/MdePkg/Include/Common/FirmwareFileSystem.h b/MdePkg/Include/Common/FirmwareFileSystem.h new file mode 100644 index 0000000000..5678a95524 --- /dev/null +++ b/MdePkg/Include/Common/FirmwareFileSystem.h @@ -0,0 +1,98 @@ +/** @file + This file defines the data structures that comprise the FFS file system. + + Copyright (c) 2006, 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. + + Module Name: FirmwareFileSystem.h + + @par Revision Reference: + These definitions are from Firmware File System Spec 0.9. + +**/ + +#ifndef __EFI_FFS_FILE_SYSTEM_H__ +#define __EFI_FFS_FILE_SYSTEM_H__ + +/// +/// FFS specific file types +/// +#define EFI_FV_FILETYPE_FFS_PAD 0xF0 + +// +// FFS File Attributes +// +#define FFS_ATTRIB_TAIL_PRESENT 0x01 +#define FFS_ATTRIB_RECOVERY 0x02 +#define FFS_ATTRIB_HEADER_EXTENSION 0x04 +#define FFS_ATTRIB_DATA_ALIGNMENT 0x38 +#define FFS_ATTRIB_CHECKSUM 0x40 + +/// +/// FFS_FIXED_CHECKSUM is the default checksum value used when the +/// FFS_ATTRIB_CHECKSUM attribute bit is clear +/// note this is NOT an architecturally defined value, but is in this file for +/// implementation convenience +/// +#define FFS_FIXED_CHECKSUM 0x5A + +// +// File state definitions +// +#define EFI_FILE_HEADER_CONSTRUCTION 0x01 +#define EFI_FILE_HEADER_VALID 0x02 +#define EFI_FILE_DATA_VALID 0x04 +#define EFI_FILE_MARKED_FOR_UPDATE 0x08 +#define EFI_FILE_DELETED 0x10 +#define EFI_FILE_HEADER_INVALID 0x20 + +#define EFI_FILE_ALL_STATE_BITS (EFI_FILE_HEADER_CONSTRUCTION | \ + EFI_FILE_HEADER_VALID | \ + EFI_FILE_DATA_VALID | \ + EFI_FILE_MARKED_FOR_UPDATE | \ + EFI_FILE_DELETED | \ + EFI_FILE_HEADER_INVALID \ + ) + +#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \ + ( \ + (BOOLEAN) ( \ + (FvbAttributes & EFI_FVB_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \ + ) \ + ) + +typedef UINT16 EFI_FFS_FILE_TAIL; + +/// +/// FFS file integrity check structure +/// +typedef union { + struct { + UINT8 Header; + UINT8 File; + } Checksum; + UINT16 TailReference; +} EFI_FFS_INTEGRITY_CHECK; + +// +// FFS file header definition +// +typedef UINT8 EFI_FFS_FILE_ATTRIBUTES; +typedef UINT8 EFI_FFS_FILE_STATE; + +typedef struct { + EFI_GUID Name; + EFI_FFS_INTEGRITY_CHECK IntegrityCheck; + EFI_FV_FILETYPE Type; + EFI_FFS_FILE_ATTRIBUTES Attributes; + UINT8 Size[3]; + EFI_FFS_FILE_STATE State; +} EFI_FFS_FILE_HEADER; + +#endif diff --git a/MdePkg/Include/Common/FirmwareVolumeHeader.h b/MdePkg/Include/Common/FirmwareVolumeHeader.h new file mode 100644 index 0000000000..038dce6f7f --- /dev/null +++ b/MdePkg/Include/Common/FirmwareVolumeHeader.h @@ -0,0 +1,109 @@ +/** @file + Defines data structure that is the volume header found at the beginning of + all firmware volumes that are either memory mapped, or have an + associated FirmwareVolumeBlock protocol. + + Copyright (c) 2006, 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. + + Module Name: FirmwareVolumeHeader.h + + @par Revision Reference: + These definitions are from Firmware Volume Block Spec 0.9. + +**/ + +#ifndef __EFI_FIRMWARE_VOLUME_HEADER_H__ +#define __EFI_FIRMWARE_VOLUME_HEADER_H__ + +// +// Firmware Volume Block Attributes definition +// +typedef UINT32 EFI_FVB_ATTRIBUTES; + +// +// Firmware Volume Block Attributes bit definitions +// +#define EFI_FVB_READ_DISABLED_CAP 0x00000001 +#define EFI_FVB_READ_ENABLED_CAP 0x00000002 +#define EFI_FVB_READ_STATUS 0x00000004 + +#define EFI_FVB_WRITE_DISABLED_CAP 0x00000008 +#define EFI_FVB_WRITE_ENABLED_CAP 0x00000010 +#define EFI_FVB_WRITE_STATUS 0x00000020 + +#define EFI_FVB_LOCK_CAP 0x00000040 +#define EFI_FVB_LOCK_STATUS 0x00000080 + +#define EFI_FVB_STICKY_WRITE 0x00000200 +#define EFI_FVB_MEMORY_MAPPED 0x00000400 +#define EFI_FVB_ERASE_POLARITY 0x00000800 + +#define EFI_FVB_ALIGNMENT_CAP 0x00008000 +#define EFI_FVB_ALIGNMENT_2 0x00010000 +#define EFI_FVB_ALIGNMENT_4 0x00020000 +#define EFI_FVB_ALIGNMENT_8 0x00040000 +#define EFI_FVB_ALIGNMENT_16 0x00080000 +#define EFI_FVB_ALIGNMENT_32 0x00100000 +#define EFI_FVB_ALIGNMENT_64 0x00200000 +#define EFI_FVB_ALIGNMENT_128 0x00400000 +#define EFI_FVB_ALIGNMENT_256 0x00800000 +#define EFI_FVB_ALIGNMENT_512 0x01000000 +#define EFI_FVB_ALIGNMENT_1K 0x02000000 +#define EFI_FVB_ALIGNMENT_2K 0x04000000 +#define EFI_FVB_ALIGNMENT_4K 0x08000000 +#define EFI_FVB_ALIGNMENT_8K 0x10000000 +#define EFI_FVB_ALIGNMENT_16K 0x20000000 +#define EFI_FVB_ALIGNMENT_32K 0x40000000 +#define EFI_FVB_ALIGNMENT_64K 0x80000000 + +#define EFI_FVB_CAPABILITIES (EFI_FVB_READ_DISABLED_CAP | \ + EFI_FVB_READ_ENABLED_CAP | \ + EFI_FVB_WRITE_DISABLED_CAP | \ + EFI_FVB_WRITE_ENABLED_CAP | \ + EFI_FVB_LOCK_CAP \ + ) + +#define EFI_FVB_STATUS (EFI_FVB_READ_STATUS | EFI_FVB_WRITE_STATUS | EFI_FVB_LOCK_STATUS) + +/// +/// Firmware Volume Header Revision definition +/// +#define EFI_FVH_REVISION 0x01 + +/// +/// Firmware Volume Header Signature definition +/// +#define EFI_FVH_SIGNATURE EFI_SIGNATURE_32 ('_', 'F', 'V', 'H') + +/// +/// Firmware Volume Header Block Map Entry definition +/// +typedef struct { + UINT32 NumBlocks; + UINT32 BlockLength; +} EFI_FV_BLOCK_MAP_ENTRY; + +/// +/// Firmware Volume Header definition +/// +typedef struct { + UINT8 ZeroVector[16]; + EFI_GUID FileSystemGuid; + UINT64 FvLength; + UINT32 Signature; + EFI_FVB_ATTRIBUTES Attributes; + UINT16 HeaderLength; + UINT16 Checksum; + UINT8 Reserved[3]; + UINT8 Revision; + EFI_FV_BLOCK_MAP_ENTRY FvBlockMap[1]; +} EFI_FIRMWARE_VOLUME_HEADER; + +#endif diff --git a/MdePkg/Include/Common/FirmwareVolumeImageFormat.h b/MdePkg/Include/Common/FirmwareVolumeImageFormat.h new file mode 100644 index 0000000000..14fa41bf26 --- /dev/null +++ b/MdePkg/Include/Common/FirmwareVolumeImageFormat.h @@ -0,0 +1,277 @@ +/** @file + This file defines the data structures that are architecturally defined for file + images loaded via the FirmwareVolume protocol. The Firmware Volume specification + is the basis for these definitions. + + Copyright (c) 2006, 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. + + Module Name: FimrwareVolumeImageFormat.h + + @par Revision Reference: + These definitions are from Firmware Volume Spec 0.9. + +**/ + +#ifndef __FIRMWARE_VOLUME_IMAGE_FORMAT_H__ +#define __FIRMWARE_VOLUME_IMAGE_FORMAT_H__ + +// +// pack all data structures since this is actually a binary format and we cannot +// allow internal padding in the data structures because of some compilerism.. +// +#pragma pack(1) +// +// //////////////////////////////////////////////////////////////////////////// +// +// Architectural file types +// +typedef UINT8 EFI_FV_FILETYPE; + +#define EFI_FV_FILETYPE_ALL 0x00 +#define EFI_FV_FILETYPE_RAW 0x01 +#define EFI_FV_FILETYPE_FREEFORM 0x02 +#define EFI_FV_FILETYPE_SECURITY_CORE 0x03 +#define EFI_FV_FILETYPE_PEI_CORE 0x04 +#define EFI_FV_FILETYPE_DXE_CORE 0x05 +#define EFI_FV_FILETYPE_PEIM 0x06 +#define EFI_FV_FILETYPE_DRIVER 0x07 +#define EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER 0x08 +#define EFI_FV_FILETYPE_APPLICATION 0x09 +// +// File type 0x0A is reserved and should not be used +// +#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Section types +// +typedef UINT8 EFI_SECTION_TYPE; + +// +// ************************************************************ +// The section type EFI_SECTION_ALL is a psuedo type. It is +// used as a wildcard when retrieving sections. The section +// type EFI_SECTION_ALL matches all section types. +// ************************************************************ +// +#define EFI_SECTION_ALL 0x00 + +// +// ************************************************************ +// Encapsulation section Type values +// ************************************************************ +// +#define EFI_SECTION_COMPRESSION 0x01 +#define EFI_SECTION_GUID_DEFINED 0x02 + +// +// ************************************************************ +// Leaf section Type values +// ************************************************************ +// +#define EFI_SECTION_FIRST_LEAF_SECTION_TYPE 0x10 + +#define EFI_SECTION_PE32 0x10 +#define EFI_SECTION_PIC 0x11 +#define EFI_SECTION_TE 0x12 +#define EFI_SECTION_DXE_DEPEX 0x13 +#define EFI_SECTION_VERSION 0x14 +#define EFI_SECTION_USER_INTERFACE 0x15 +#define EFI_SECTION_COMPATIBILITY16 0x16 +#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE 0x17 +#define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18 +#define EFI_SECTION_RAW 0x19 +#define EFI_SECTION_PEI_DEPEX 0x1B + +#define EFI_SECTION_LAST_LEAF_SECTION_TYPE 0x1B +#define EFI_SECTION_LAST_SECTION_TYPE 0x1B + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Common section header +// +typedef struct { + UINT8 Size[3]; + UINT8 Type; +} EFI_COMMON_SECTION_HEADER; + +#define SECTION_SIZE(SectionHeaderPtr) \ + ((UINT32) (*((UINT32 *) ((EFI_COMMON_SECTION_HEADER *) SectionHeaderPtr)->Size) & 0x00ffffff)) + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Compression section +// +// +// CompressionType values +// +#define EFI_NOT_COMPRESSED 0x00 +#define EFI_STANDARD_COMPRESSION 0x01 +#define EFI_CUSTOMIZED_COMPRESSION 0x02 + +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + UINT32 UncompressedLength; + UINT8 CompressionType; +} EFI_COMPRESSION_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// GUID defined section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + EFI_GUID SectionDefinitionGuid; + UINT16 DataOffset; + UINT16 Attributes; +} EFI_GUID_DEFINED_SECTION; + +// +// Bit values for Attributes +// +#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01 +#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02 + +// +// Bit values for AuthenticationStatus +// +#define EFI_AGGREGATE_AUTH_STATUS_PLATFORM_OVERRIDE 0x000001 +#define EFI_AGGREGATE_AUTH_STATUS_IMAGE_SIGNED 0x000002 +#define EFI_AGGREGATE_AUTH_STATUS_NOT_TESTED 0x000004 +#define EFI_AGGREGATE_AUTH_STATUS_TEST_FAILED 0x000008 +#define EFI_AGGREGATE_AUTH_STATUS_ALL 0x00000f + +#define EFI_LOCAL_AUTH_STATUS_PLATFORM_OVERRIDE 0x010000 +#define EFI_LOCAL_AUTH_STATUS_IMAGE_SIGNED 0x020000 +#define EFI_LOCAL_AUTH_STATUS_NOT_TESTED 0x040000 +#define EFI_LOCAL_AUTH_STATUS_TEST_FAILED 0x080000 +#define EFI_LOCAL_AUTH_STATUS_ALL 0x0f0000 + +// +// //////////////////////////////////////////////////////////////////////////// +// +// PE32+ section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_PE32_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// PIC section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_PIC_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// PEIM header section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_PEIM_HEADER_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// DEPEX section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_DEPEX_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Version section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + UINT16 BuildNumber; + INT16 VersionString[1]; +} EFI_VERSION_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// User interface section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + INT16 FileNameString[1]; +} EFI_USER_INTERFACE_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Code16 section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_CODE16_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Firmware Volume Image section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_FIRMWARE_VOLUME_IMAGE_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Freeform subtype GUID section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + EFI_GUID SubTypeGuid; +} EFI_FREEFORM_SUBTYPE_GUID_SECTION; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// Raw section +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; +} EFI_RAW_SECTION; + +// +// undo the pragma from the beginning... +// +#pragma pack() + +typedef union { + EFI_COMMON_SECTION_HEADER *CommonHeader; + EFI_COMPRESSION_SECTION *CompressionSection; + EFI_GUID_DEFINED_SECTION *GuidDefinedSection; + EFI_PE32_SECTION *Pe32Section; + EFI_PIC_SECTION *PicSection; + EFI_PEIM_HEADER_SECTION *PeimHeaderSection; + EFI_DEPEX_SECTION *DependencySection; + EFI_VERSION_SECTION *VersionSection; + EFI_USER_INTERFACE_SECTION *UISection; + EFI_CODE16_SECTION *Code16Section; + EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FVImageSection; + EFI_FREEFORM_SUBTYPE_GUID_SECTION *FreeformSubtypeSection; + EFI_RAW_SECTION *RawSection; +} EFI_FILE_SECTION_POINTER; + +#endif diff --git a/MdePkg/Include/Common/Hob.h b/MdePkg/Include/Common/Hob.h new file mode 100644 index 0000000000..b6ae6de009 --- /dev/null +++ b/MdePkg/Include/Common/Hob.h @@ -0,0 +1,235 @@ +/** @file + Hand Off Block (HOB) definition. + + The HOB is a memory data structure used to hand-off system information from + PEI to DXE (the next phase). + + Copyright (c) 2006, 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. + + Module Name: Hob.h + + @par Revision Reference: + These definitions are from Hand Off Block (HOB) Spec Version 0.9. + +**/ + +#ifndef __HOB_H__ +#define __HOB_H__ + + +// +// Every Hob must start with this data structure. +// +typedef struct { + UINT16 HobType; + UINT16 HobLength; + UINT32 Reserved; +} EFI_HOB_GENERIC_HEADER; + +// +// End of HOB List HOB +// +#define EFI_HOB_TYPE_END_OF_HOB_LIST 0xffff + +// +// Handoff Information Table HOB +// +#define EFI_HOB_TYPE_HANDOFF 0x0001 + +#define EFI_HOB_HANDOFF_TABLE_VERSION 0x0009 + +typedef UINT32 EFI_BOOT_MODE; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + UINT32 Version; + EFI_BOOT_MODE BootMode; + EFI_PHYSICAL_ADDRESS EfiMemoryTop; + EFI_PHYSICAL_ADDRESS EfiMemoryBottom; + EFI_PHYSICAL_ADDRESS EfiFreeMemoryTop; + EFI_PHYSICAL_ADDRESS EfiFreeMemoryBottom; + EFI_PHYSICAL_ADDRESS EfiEndOfHobList; +} EFI_HOB_HANDOFF_INFO_TABLE; + +// +// Memory Descriptor HOB +// +#define EFI_HOB_TYPE_MEMORY_ALLOCATION 0x0002 + +typedef struct { + EFI_GUID Name; + EFI_PHYSICAL_ADDRESS MemoryBaseAddress; + UINT64 MemoryLength; + EFI_MEMORY_TYPE MemoryType; + UINT8 Reserved[4]; +} EFI_HOB_MEMORY_ALLOCATION_HEADER; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor; + // + // Additional data pertaining to the "Name" Guid memory + // may go here. + // +} EFI_HOB_MEMORY_ALLOCATION; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor; +} EFI_HOB_MEMORY_ALLOCATION_BSP_STORE; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_HOB_MEMORY_ALLOCATION_HEADER AllocDescriptor; +} EFI_HOB_MEMORY_ALLOCATION_STACK; + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_HOB_MEMORY_ALLOCATION_HEADER MemoryAllocationHeader; + EFI_GUID ModuleName; + EFI_PHYSICAL_ADDRESS EntryPoint; +} EFI_HOB_MEMORY_ALLOCATION_MODULE; + +#define EFI_HOB_TYPE_RESOURCE_DESCRIPTOR 0x0003 + +typedef UINT32 EFI_RESOURCE_TYPE; + +#define EFI_RESOURCE_SYSTEM_MEMORY 0 +#define EFI_RESOURCE_MEMORY_MAPPED_IO 1 +#define EFI_RESOURCE_IO 2 +#define EFI_RESOURCE_FIRMWARE_DEVICE 3 +#define EFI_RESOURCE_MEMORY_MAPPED_IO_PORT 4 +#define EFI_RESOURCE_MEMORY_RESERVED 5 +#define EFI_RESOURCE_IO_RESERVED 6 +#define EFI_RESOURCE_MAX_MEMORY_TYPE 7 + +typedef UINT32 EFI_RESOURCE_ATTRIBUTE_TYPE; + +#define EFI_RESOURCE_ATTRIBUTE_PRESENT 0x00000001 +#define EFI_RESOURCE_ATTRIBUTE_INITIALIZED 0x00000002 +#define EFI_RESOURCE_ATTRIBUTE_TESTED 0x00000004 +#define EFI_RESOURCE_ATTRIBUTE_SINGLE_BIT_ECC 0x00000008 +#define EFI_RESOURCE_ATTRIBUTE_MULTIPLE_BIT_ECC 0x00000010 +#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_1 0x00000020 +#define EFI_RESOURCE_ATTRIBUTE_ECC_RESERVED_2 0x00000040 +#define EFI_RESOURCE_ATTRIBUTE_READ_PROTECTED 0x00000080 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_PROTECTED 0x00000100 +#define EFI_RESOURCE_ATTRIBUTE_EXECUTION_PROTECTED 0x00000200 +#define EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE 0x00000400 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE 0x00000800 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE 0x00001000 +#define EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE 0x00002000 +#define EFI_RESOURCE_ATTRIBUTE_16_BIT_IO 0x00004000 +#define EFI_RESOURCE_ATTRIBUTE_32_BIT_IO 0x00008000 +#define EFI_RESOURCE_ATTRIBUTE_64_BIT_IO 0x00010000 +#define EFI_RESOURCE_ATTRIBUTE_UNCACHED_EXPORTED 0x00020000 + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_GUID Owner; + EFI_RESOURCE_TYPE ResourceType; + EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute; + EFI_PHYSICAL_ADDRESS PhysicalStart; + UINT64 ResourceLength; +} EFI_HOB_RESOURCE_DESCRIPTOR; + +// +// GUID Extension HOB +// The HobLength is variable as it includes the GUID specific data. +// +#define EFI_HOB_TYPE_GUID_EXTENSION 0x0004 + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_GUID Name; + + // + // Guid specific data goes here + // +} EFI_HOB_GUID_TYPE; + +// +// Firmware Volume HOB +// +#define EFI_HOB_TYPE_FV 0x0005 + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; +} EFI_HOB_FIRMWARE_VOLUME; + +// +// CPU HOB +// +#define EFI_HOB_TYPE_CPU 0x0006 + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + UINT8 SizeOfMemorySpace; + UINT8 SizeOfIoSpace; + UINT8 Reserved[6]; +} EFI_HOB_CPU; + +// +// PEI Core Memory Pool HOB +// The HobLength is variable as the HOB contains pool allocations by +// the PeiServices AllocatePool function +// +#define EFI_HOB_TYPE_PEI_MEMORY_POOL 0x0007 + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; +} EFI_HOB_MEMORY_POOL; + +// +// Capsule volume HOB -- identical to a firmware volume +// +#define EFI_HOB_TYPE_CV 0x0008 + +typedef struct { + EFI_HOB_GENERIC_HEADER Header; + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; +} EFI_HOB_CAPSULE_VOLUME; + +#define EFI_HOB_TYPE_UNUSED 0xFFFE + +// +// Union of all the possible HOB Types +// +typedef union { + EFI_HOB_GENERIC_HEADER *Header; + EFI_HOB_HANDOFF_INFO_TABLE *HandoffInformationTable; + EFI_HOB_MEMORY_ALLOCATION *MemoryAllocation; + EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *MemoryAllocationBspStore; + EFI_HOB_MEMORY_ALLOCATION_STACK *MemoryAllocationStack; + EFI_HOB_MEMORY_ALLOCATION_MODULE *MemoryAllocationModule; + EFI_HOB_RESOURCE_DESCRIPTOR *ResourceDescriptor; + EFI_HOB_GUID_TYPE *Guid; + EFI_HOB_FIRMWARE_VOLUME *FirmwareVolume; + EFI_HOB_CPU *Cpu; + EFI_HOB_MEMORY_POOL *Pool; + EFI_HOB_CAPSULE_VOLUME *CapsuleVolume; + UINT8 *Raw; +} EFI_PEI_HOB_POINTERS; + +#define GET_HOB_TYPE(Hob) ((Hob).Header->HobType) +#define GET_HOB_LENGTH(Hob) ((Hob).Header->HobLength) +#define GET_NEXT_HOB(Hob) ((Hob).Raw + GET_HOB_LENGTH (Hob)) +#define END_OF_HOB_LIST(Hob) (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_END_OF_HOB_LIST) + +// +// Get the data and data size field of GUID +// +#define GET_GUID_HOB_DATA(GuidHob) ((VOID *) (((UINT8 *) &((GuidHob)->Name)) + sizeof (EFI_GUID))) +#define GET_GUID_HOB_DATA_SIZE(GuidHob) (((GuidHob)->Header).HobLength - sizeof (EFI_HOB_GUID_TYPE)) + +#endif diff --git a/MdePkg/Include/Common/InternalFormRepresentation.h b/MdePkg/Include/Common/InternalFormRepresentation.h new file mode 100644 index 0000000000..bf3d824fbd --- /dev/null +++ b/MdePkg/Include/Common/InternalFormRepresentation.h @@ -0,0 +1,422 @@ +/** @file + This file defines the encoding for the VFR (Visual Form Representation) language. + IFR is primarily consumed by the EFI presentation engine, and produced by EFI + internal application and drivers as well as all add-in card option-ROM drivers + + Copyright (c) 2006, 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. + + Module Name: InternalFormRepresentation.h + + @par Revision Reference: + These definitions are from Human Interface Infrastructure Spec Version 0.92. + +**/ + +#ifndef __EFI_INTERNAL_FORM_REPRESENTATION_H__ +#define __EFI_INTERNAL_FORM_REPRESENTATION_H__ + +// +// The following types are currently defined: +// +typedef UINT32 RELOFST; +typedef CHAR16 *EFI_STRING; + +// +// IFR Op codes +// +#define EFI_IFR_FORM_OP 0x01 +#define EFI_IFR_SUBTITLE_OP 0x02 +#define EFI_IFR_TEXT_OP 0x03 +#define EFI_IFR_GRAPHIC_OP 0x04 +#define EFI_IFR_ONE_OF_OP 0x05 +#define EFI_IFR_CHECKBOX_OP 0x06 +#define EFI_IFR_NUMERIC_OP 0x07 +#define EFI_IFR_PASSWORD_OP 0x08 +#define EFI_IFR_ONE_OF_OPTION_OP 0x09 // ONEOF OPTION field +#define EFI_IFR_SUPPRESS_IF_OP 0x0A +#define EFI_IFR_END_FORM_OP 0x0B +#define EFI_IFR_HIDDEN_OP 0x0C +#define EFI_IFR_END_FORM_SET_OP 0x0D +#define EFI_IFR_FORM_SET_OP 0x0E +#define EFI_IFR_REF_OP 0x0F +#define EFI_IFR_END_ONE_OF_OP 0x10 +#define EFI_IFR_END_OP EFI_IFR_END_ONE_OF_OP +#define EFI_IFR_INCONSISTENT_IF_OP 0x11 +#define EFI_IFR_EQ_ID_VAL_OP 0x12 +#define EFI_IFR_EQ_ID_ID_OP 0x13 +#define EFI_IFR_EQ_ID_LIST_OP 0x14 +#define EFI_IFR_AND_OP 0x15 +#define EFI_IFR_OR_OP 0x16 +#define EFI_IFR_NOT_OP 0x17 +#define EFI_IFR_END_IF_OP 0x18 // for endif of inconsistentif, suppressif, grayoutif +#define EFI_IFR_GRAYOUT_IF_OP 0x19 +#define EFI_IFR_DATE_OP 0x1A +#define EFI_IFR_TIME_OP 0x1B +#define EFI_IFR_STRING_OP 0x1C +#define EFI_IFR_LABEL_OP 0x1D +#define EFI_IFR_SAVE_DEFAULTS_OP 0x1E +#define EFI_IFR_RESTORE_DEFAULTS_OP 0x1F +#define EFI_IFR_BANNER_OP 0x20 +#define EFI_IFR_INVENTORY_OP 0x21 +#define EFI_IFR_EQ_VAR_VAL_OP 0x22 +#define EFI_IFR_ORDERED_LIST_OP 0x23 +#define EFI_IFR_VARSTORE_OP 0x24 +#define EFI_IFR_VARSTORE_SELECT_OP 0x25 +#define EFI_IFR_VARSTORE_SELECT_PAIR_OP 0x26 +#define EFI_IFR_TRUE_OP 0x27 +#define EFI_IFR_FALSE_OP 0x28 +#define EFI_IFR_GT_OP 0x29 +#define EFI_IFR_GE_OP 0x2A +#define EFI_IFR_OEM_DEFINED_OP 0x2B +#define EFI_IFR_LAST_OPCODE EFI_IFR_OEM_DEFINED_OP +#define EFI_IFR_OEM_OP 0xFE +#define EFI_IFR_NV_ACCESS_COMMAND 0xFF + +// +// Define values for the flags fields in some VFR opcodes. These are +// bitmasks. +// +#define EFI_IFR_FLAG_DEFAULT 0x01 +#define EFI_IFR_FLAG_MANUFACTURING 0x02 +#define EFI_IFR_FLAG_INTERACTIVE 0x04 +#define EFI_IFR_FLAG_NV_ACCESS 0x08 +#define EFI_IFR_FLAG_RESET_REQUIRED 0x10 +#define EFI_IFR_FLAG_LATE_CHECK 0x20 + +#define EFI_NON_DEVICE_CLASS 0x00 // Useful when you do not want something in the Device Manager +#define EFI_DISK_DEVICE_CLASS 0x01 +#define EFI_VIDEO_DEVICE_CLASS 0x02 +#define EFI_NETWORK_DEVICE_CLASS 0x04 +#define EFI_INPUT_DEVICE_CLASS 0x08 +#define EFI_ON_BOARD_DEVICE_CLASS 0x10 +#define EFI_OTHER_DEVICE_CLASS 0x20 + +#define EFI_SETUP_APPLICATION_SUBCLASS 0x00 +#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01 +#define EFI_FRONT_PAGE_SUBCLASS 0x02 +#define EFI_SINGLE_USE_SUBCLASS 0x03 // Used to display a single entity and then exit + +// +// Used to flag dynamically created op-codes. This is meaningful to the IFR Library set +// and the browser since we need to distinguish between compiled NV map data and created data. +// We do not allow new entries to be created in the NV map dynamically however we still need +// to display this information correctly. To dynamically create op-codes and assume that their +// data will be saved, ensure that the NV starting location they refer to is pre-defined in the +// NV map. +// +#define EFI_IFR_FLAG_CREATED 128 + +#pragma pack(1) +// +// IFR Structure definitions +// +typedef struct { + UINT8 OpCode; + UINT8 Length; +} EFI_IFR_OP_HEADER; + +typedef struct { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + STRING_REF FormSetTitle; + STRING_REF Help; + EFI_PHYSICAL_ADDRESS CallbackHandle; + UINT16 Class; + UINT16 SubClass; + UINT16 NvDataSize; // set once, size of the NV data as defined in the script +} EFI_IFR_FORM_SET; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 FormId; + STRING_REF FormTitle; +} EFI_IFR_FORM; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 LabelId; +} EFI_IFR_LABEL; + +typedef struct { + EFI_IFR_OP_HEADER Header; + STRING_REF SubTitle; +} EFI_IFR_SUBTITLE; + +typedef struct { + EFI_IFR_OP_HEADER Header; + STRING_REF Help; + STRING_REF Text; + STRING_REF TextTwo; + UINT8 Flags; // This is included solely for purposes of interactive/dynamic support. + UINT16 Key; // Value to be passed to caller to identify this particular op-code +} EFI_IFR_TEXT; + +// +// goto +// +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 FormId; + STRING_REF Prompt; + STRING_REF Help; // The string Token for the context-help + UINT8 Flags; // This is included solely for purposes of interactive/dynamic support. + UINT16 Key; // Value to be passed to caller to identify this particular op-code +} EFI_IFR_REF; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_END_FORM; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_END_FORM_SET; + +// +// Also notice that the IFR_ONE_OF and IFR_CHECK_BOX are identical in structure......code assumes this to be true, if this ever +// changes we need to revisit the InitializeTagStructures code +// +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name + UINT8 Width; // The Size of the Data being saved + STRING_REF Prompt; // The String Token for the Prompt + STRING_REF Help; // The string Token for the context-help +} EFI_IFR_ONE_OF; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; // The offset in NV for storage of the data + UINT8 MaxEntries; // The maximum number of options in the ordered list (=size of NVStore) + STRING_REF Prompt; // The string token for the prompt + STRING_REF Help; // The string token for the context-help +} EFI_IFR_ORDERED_LIST; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name + UINT8 Width; // The Size of the Data being saved + STRING_REF Prompt; // The String Token for the Prompt + STRING_REF Help; // The string Token for the context-help + UINT8 Flags; // For now, if non-zero, means that it is the default option, - further definition likely + UINT16 Key; // Value to be passed to caller to identify this particular op-code +} EFI_IFR_CHECKBOX, EFI_IFR_CHECK_BOX; + +typedef struct { + EFI_IFR_OP_HEADER Header; + STRING_REF Option; // The string token describing the option + UINT16 Value; // The value associated with this option that is stored in the NVRAM if chosen + UINT8 Flags; // For now, if non-zero, means that it is the default option, - further definition likely above + UINT16 Key; // Value to be passed to caller to identify this particular op-code +} EFI_IFR_ONE_OF_OPTION; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name + UINT8 Width; // The Size of the Data being saved + STRING_REF Prompt; // The String Token for the Prompt + STRING_REF Help; // The string Token for the context-help + UINT8 Flags; // This is included solely for purposes of interactive/dynamic support. + UINT16 Key; // Value to be passed to caller to identify this particular op-code + UINT16 Minimum; + UINT16 Maximum; + UINT16 Step; // If step is 0, then manual input is specified, otherwise, left/right arrow selection is called for + UINT16 Default; +} EFI_IFR_NUMERIC; + +// +// There is an interesting twist with regards to Time and Date. This is one of the few items which can accept input from +// a user, however may or may not need to use storage in the NVRAM space. The decided method for determining if NVRAM space +// will be used (only for a TimeOp or DateOp) is: If .QuestionId == 0 && .Width == 0 (normally an impossibility) then use system +// resources to store the data away and not NV resources. In other words, the setup engine will call gRT->SetTime, and gRT->SetDate +// for the saving of data, and the values displayed will be from the gRT->GetXXXX series of calls. +// +typedef struct { + EFI_IFR_NUMERIC Hour; + EFI_IFR_NUMERIC Minute; + EFI_IFR_NUMERIC Second; +} EFI_IFR_TIME; + +typedef struct { + EFI_IFR_NUMERIC Year; + EFI_IFR_NUMERIC Month; + EFI_IFR_NUMERIC Day; +} EFI_IFR_DATE; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name + UINT8 Width; // The Size of the Data being saved -- BUGBUG -- remove someday + STRING_REF Prompt; // The String Token for the Prompt + STRING_REF Help; // The string Token for the context-help + UINT8 Flags; // This is included solely for purposes of interactive/dynamic support. + UINT16 Key; // Value to be passed to caller to identify this particular op-code + UINT8 MinSize; // Minimum allowable sized password + UINT8 MaxSize; // Maximum allowable sized password + UINT16 Encoding; +} EFI_IFR_PASSWORD; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; // The ID designating what the question is about...sucked in from a #define, likely in the form of a variable name + UINT8 Width; // The Size of the Data being saved -- BUGBUG -- remove someday + STRING_REF Prompt; // The String Token for the Prompt + STRING_REF Help; // The string Token for the context-help + UINT8 Flags; // This is included solely for purposes of interactive/dynamic support. + UINT16 Key; // Value to be passed to caller to identify this particular op-code + UINT8 MinSize; // Minimum allowable sized password + UINT8 MaxSize; // Maximum allowable sized password +} EFI_IFR_STRING; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_END_ONE_OF; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 Value; + UINT16 Key; +} EFI_IFR_HIDDEN; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT8 Flags; +} EFI_IFR_SUPPRESS; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT8 Flags; +} EFI_IFR_GRAY_OUT; + +typedef struct { + EFI_IFR_OP_HEADER Header; + STRING_REF Popup; + UINT8 Flags; +} EFI_IFR_INCONSISTENT; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; // offset into variable storage + UINT8 Width; // size of variable storage + UINT16 Value; // value to compare against +} EFI_IFR_EQ_ID_VAL; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; // offset into variable storage + UINT8 Width; // size of variable storage + UINT16 ListLength; + UINT16 ValueList[1]; +} EFI_IFR_EQ_ID_LIST; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 QuestionId1; // offset into variable storage for first value to compare + UINT8 Width; // size of variable storage (must be same for both) + UINT16 QuestionId2; // offset into variable storage for second value to compare +} EFI_IFR_EQ_ID_ID; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 VariableId; // offset into variable storage + UINT16 Value; // value to compare against +} EFI_IFR_EQ_VAR_VAL; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_AND; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_OR; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_NOT; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_END_EXPR, EFI_IFR_END_IF; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 FormId; + STRING_REF Prompt; + STRING_REF Help; + UINT8 Flags; + UINT16 Key; +} EFI_IFR_SAVE_DEFAULTS; + +typedef struct { + EFI_IFR_OP_HEADER Header; + STRING_REF Help; + STRING_REF Text; + STRING_REF TextTwo; // optional text +} EFI_IFR_INVENTORY; + +typedef struct { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; // GUID for the variable + UINT16 VarId; // variable store ID, as referenced elsewhere in the form + UINT16 Size; // size of the variable storage +} EFI_IFR_VARSTORE; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 VarId; // variable store ID, as referenced elsewhere in the form +} EFI_IFR_VARSTORE_SELECT; + +// +// Used for the ideqid VFR statement where two variable stores may be referenced in the +// same VFR statement. +// A browser should treat this as an EFI_IFR_VARSTORE_SELECT statement and assume that all following +// IFR opcodes use the VarId as defined here. +// +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 VarId; // variable store ID, as referenced elsewhere in the form + UINT16 SecondaryVarId; // variable store ID, as referenced elsewhere in the form +} EFI_IFR_VARSTORE_SELECT_PAIR; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TRUE; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_FALSE; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GT; + +typedef struct { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GE; + +// +// Save defaults and restore defaults have same structure +// +#define EFI_IFR_RESTORE_DEFAULTS EFI_IFR_SAVE_DEFAULTS + +typedef struct { + EFI_IFR_OP_HEADER Header; + STRING_REF Title; // The string token for the banner title + UINT16 LineNumber; // 1-based line number + UINT8 Alignment; // left, center, or right-aligned +} EFI_IFR_BANNER; + +#define EFI_IFR_BANNER_ALIGN_LEFT 0 +#define EFI_IFR_BANNER_ALIGN_CENTER 1 +#define EFI_IFR_BANNER_ALIGN_RIGHT 2 +#define EFI_IFR_BANNER_TIMEOUT 0xFF + +#pragma pack() + +#endif diff --git a/MdePkg/Include/Common/Legacy16.h b/MdePkg/Include/Common/Legacy16.h new file mode 100644 index 0000000000..1f8b9bf324 --- /dev/null +++ b/MdePkg/Include/Common/Legacy16.h @@ -0,0 +1,310 @@ +/** @file + API between 16-bit Legacy BIOS and EFI + + We need to figure out what the 16-bit code is going to use to + represent these data structures. Is a pointer SEG:OFF or 32-bit... + + Copyright (c) 2006, 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. + + Module Name: Legacy16.h + + @par Revision Reference: + These definitions are from Compatibility Support Module Spec Version 0.96. + +**/ + +#ifndef LEGACY_16_H_ +#define LEGACY_16_H_ + +#define EFI_TO_LEGACY_MAJOR_VERSION 0x02 +#define EFI_TO_LEGACY_MINOR_VERSION 0x00 + +#pragma pack(1) +// +// EFI Legacy to Legacy16 data +// EFI_COMPATIBILITY16_TABLE has been moved to LegacyBios protocol defn file. +// +typedef struct { + // + // Memory map used to start up Legacy16 code + // + UINT32 BiosLessThan1MB; + UINT32 HiPmmMemory; + UINT32 PmmMemorySizeInBytes; + + UINT16 ReverseThunkCallSegment; + UINT16 ReverseThunkCallOffset; + UINT32 NumberE820Entries; + UINT32 OsMemoryAbove1Mb; + UINT32 ThunkStart; + UINT32 ThunkSizeInBytes; + UINT32 LowPmmMemory; + UINT32 LowPmmMemorySizeInBytes; +} EFI_TO_COMPATIBILITY16_INIT_TABLE; + +#pragma pack() +// +// Legacy16 Call types +// +typedef enum { + Legacy16InitializeYourself = 0x0000, + Legacy16UpdateBbs = 0x0001, + Legacy16PrepareToBoot = 0x0002, + Legacy16Boot = 0x0003, + Legacy16RetrieveLastBootDevice= 0x0004, + Legacy16DispatchOprom = 0x0005, + Legacy16GetTableAddress = 0x0006, + Legacy16SetKeyboardLeds = 0x0007, + Legacy16InstallPciHandler = 0x0008, +} EFI_COMPATIBILITY_FUNCTIONS; + +#define F0000Region 0x01 +#define E0000Region 0x02 +// +// Legacy16 call prototypes +// Input: AX = EFI_COMPATIBILITY16_FUNCTIONS for all functions. +// Output: AX = Return status for all functions. It follows EFI error +// codes. +// +// Legacy16InitializeYourself +// Description: This is the first call to 16-bit code. It allows the +// 16-bit to perform any internal initialization. +// Input: ES:BX pointer to EFI_TO_LEGACY16_INIT_TABLE +// Output: +// Legacy16UpdateBbs +// Description: The 16-bit code updates the BBS table for non-compliant +// devices. +// Input: ES:BX pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE +// Output: +// Legacy16PrepareToBoot +// Description: This is the last call to 16-bit code where 0xE0000 -0xFFFFF +// is read/write. 16-bit code does any final clean up. +// Input: ES:BX pointer to EFI_TO_COMPATIBILITY16_BOOT_TABLE +// Output: +// Legacy16Boot +// Description: Do INT19. +// Input: +// Output: +// Legacy16RetrieveLastBootDevice +// Description: Return the priority number of the device that booted. +// Input: +// Output: BX = priority number of the last attempted boot device. +// Legacy16DispatchOprom +// Description: Pass control to the specified OPROM. Allows the 16-bit +// code to rehook INT 13,18 and/or 19 from non-BBS +// compliant devices. +// Input: ES:DI = Segment:Offset of PnPInstallationCheck +// SI = OPROM segment. Offset assumed to be 3. +// BH = PCI bus number. +// BL = PCI device * 8 | PCI function. +// Output: BX = Number of BBS non-compliant drives detected. Return +// zero for BBS compliant devices. +// Legacy16GetTableAddress +// Description: Allocate an area in the 0xE0000-0xFFFFF region. +// Input: BX = Allocation region. +// 0x0 = Any region +// Bit 0 = 0xF0000 region +// Bit 1 = 0xE0000 region +// Multiple bits can be set. +// CX = Length in bytes requested +// DX = Required address alignment +// Bit mapped. First non-zero bit from right to left is +// alignment. +// Output: DS:BX is assigned region. +// AX = EFI_OUT_OF_RESOURCES if request cannot be granted. +// Legacy16SetKeyboardLeds +// Description: Perform any special action when keyboard LEDS change. +// Other code performs the LED change and updates standard +// BDA locations. This is for non-standard operations. +// Input: CL = LED status. 1 = set. +// Bit 0 = Scroll lock +// Bit 1 = Num lock +// Bit 2 = Caps lock +// Output: +// Legacy16InstallPciHandler +// Description: Provides 16-bit code a hook to establish an interrupt +// handler for any PCI device requiring a PCI interrupt +// but having no OPROM. This is called before interrupt +// is assigned. 8259 will be disabled(even if sharded) +// and PCI Interrupt Line unprogrammed. Other code will +// program 8259 and PCI Interrupt Line. +// Input: ES:BX Pointer to EFI_LEGACY_INSTALL_PCI_HANDLER strcture +// Output: +// +typedef UINT8 SERIAL_MODE; +typedef UINT8 PARALLEL_MODE; + +#pragma pack(1) + +#define DEVICE_SERIAL_MODE_NORMAL 0x00 +#define DEVICE_SERIAL_MODE_IRDA 0x01 +#define DEVICE_SERIAL_MODE_ASK_IR 0x02 +#define DEVICE_SERIAL_MODE_DUPLEX_HALF 0x00 +#define DEVICE_SERIAL_MODE_DUPLEX_FULL 0x10 + +#define DEVICE_PARALLEL_MODE_MODE_OUTPUT_ONLY 0x00 +#define DEVICE_PARALLEL_MODE_MODE_BIDIRECTIONAL 0x01 +#define DEVICE_PARALLEL_MODE_MODE_EPP 0x02 +#define DEVICE_PARALLEL_MODE_MODE_ECP 0x03 + +typedef struct { + UINT16 Address; + UINT8 Irq; + SERIAL_MODE Mode; +} DEVICE_PRODUCER_SERIAL; + +typedef struct { + UINT16 Address; + UINT8 Irq; + UINT8 Dma; + PARALLEL_MODE Mode; +} DEVICE_PRODUCER_PARALLEL; + +typedef struct { + UINT16 Address; + UINT8 Irq; + UINT8 Dma; + UINT8 NumberOfFloppy; +} DEVICE_PRODUCER_FLOPPY; + +typedef struct { + UINT32 A20Kybd : 1; + UINT32 A20Port90 : 1; + UINT32 Reserved : 30; +} LEGACY_DEVICE_FLAGS; + +typedef struct { + DEVICE_PRODUCER_SERIAL Serial[4]; + DEVICE_PRODUCER_PARALLEL Parallel[3]; + DEVICE_PRODUCER_FLOPPY Floppy; + UINT8 MousePresent; + LEGACY_DEVICE_FLAGS Flags; +} DEVICE_PRODUCER_DATA_HEADER; +// +// SMM Table definitions +// SMM table has a header that provides the number of entries. Following +// the header is a variable length amount of data. +// + +#define STANDARD_IO 0x00 +#define STANDARD_MEMORY 0x01 + +#define PORT_SIZE_8 0x00 +#define PORT_SIZE_16 0x01 +#define PORT_SIZE_32 0x02 +#define PORT_SIZE_64 0x03 + +#define DATA_SIZE_8 0x00 +#define DATA_SIZE_16 0x01 +#define DATA_SIZE_32 0x02 +#define DATA_SIZE_64 0x03 + +typedef struct { + UINT16 Type : 3; + UINT16 PortGranularity : 3; + UINT16 DataGranularity : 3; + UINT16 Reserved : 7; +} SMM_ATTRIBUTES; + +#define INT15_D042 0x0000 +#define GET_USB_BOOT_INFO 0x0001 +#define DMI_PNP_50_57 0x0002 + +#define STANDARD_OWNER 0x0 +#define OEM_OWNER 0x1 + +typedef struct { + UINT16 Function : 15; + UINT16 Owner : 1; +} SMM_FUNCTION; + +typedef struct { + SMM_ATTRIBUTES SmmAttributes; + SMM_FUNCTION SmmFunction; + // + // Data size depends upon SmmAttributes and ranges from 2 bytes to + // 16 bytes + // + // bugbug how to do variable length Data + // + UINT8 SmmPort; + UINT8 SmmData; +} SMM_ENTRY; + +typedef struct { + UINT16 NumSmmEntries; + SMM_ENTRY SmmEntry; +} SMM_TABLE; + +// +// If MAX_IDE_CONTROLLER changes value 16-bit legacy code needs to change +// +#define MAX_IDE_CONTROLLER 8 + +typedef struct { + UINT16 MajorVersion; + UINT16 MinorVersion; + + UINT32 AcpiTable; // 4 GB range + UINT32 SmbiosTable; // 4 GB range + UINT32 SmbiosTableLength; + + // + // Legacy SIO state + // + DEVICE_PRODUCER_DATA_HEADER SioData; + + UINT16 DevicePathType; + UINT16 PciIrqMask; + UINT32 NumberE820Entries; + // + // Controller & Drive Identify[2] per controller information + // + HDD_INFO HddInfo[MAX_IDE_CONTROLLER]; + UINT32 NumberBbsEntries; + UINT32 BbsTable; + UINT32 SmmTable; + UINT32 OsMemoryAbove1Mb; + UINT32 UnconventionalDeviceTable; +} EFI_TO_COMPATIBILITY16_BOOT_TABLE; + +typedef struct { + UINT8 PciBus; + UINT8 PciDeviceFun; + UINT8 PciSegment; + UINT8 PciClass; + UINT8 PciSubclass; + UINT8 PciInterface; + UINT8 PrimaryIrq; + UINT8 PrimaryReserved; + UINT16 PrimaryControl; + UINT16 PrimaryBase; + UINT16 PrimaryBusMaster; + UINT8 SecondaryIrq; + UINT8 SecondaryReserved; + UINT16 SecondaryControl; + UINT16 SecondaryBase; + UINT16 SecondaryBusMaster; +} EFI_LEGACY_INSTALL_PCI_HANDLER; + +typedef struct { + UINT16 PnPInstallationCheckSegment; + UINT16 PnPInstallationCheckOffset; + UINT16 OpromSegment; + UINT8 PciBus; + UINT8 PciDeviceFunction; + UINT8 NumberBbsEntries; + VOID *BbsTablePointer; + +} EFI_DISPATCH_OPROM_TABLE; + +#pragma pack() + +#endif diff --git a/MdePkg/Include/Common/MultiPhase.h b/MdePkg/Include/Common/MultiPhase.h new file mode 100644 index 0000000000..93867a5e8a --- /dev/null +++ b/MdePkg/Include/Common/MultiPhase.h @@ -0,0 +1,84 @@ +/** @file + This includes some definitions that will be used in both PEI and DXE phases. + + Copyright (c) 2006, 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. + + Module Name: MultiPhase.h + +**/ + +#ifndef __MULTI_PHASE_H__ +#define __MULTI_PHASE_H__ + +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// +// Needed EFI defines for PEI +// +typedef UINT64 EFI_PHYSICAL_ADDRESS; + +typedef enum { + EfiReservedMemoryType, + EfiLoaderCode, + EfiLoaderData, + EfiBootServicesCode, + EfiBootServicesData, + EfiRuntimeServicesCode, + EfiRuntimeServicesData, + EfiConventionalMemory, + EfiUnusableMemory, + EfiACPIReclaimMemory, + EfiACPIMemoryNVS, + EfiMemoryMappedIO, + EfiMemoryMappedIOPortSpace, + EfiPalCode, + EfiMaxMemoryType +} EFI_MEMORY_TYPE; + +typedef UINT32 EFI_STATUS_CODE_TYPE; +typedef UINT32 EFI_STATUS_CODE_VALUE; + +typedef struct { + UINT16 HeaderSize; + UINT16 Size; + EFI_GUID Type; +} EFI_STATUS_CODE_DATA; + +typedef struct { + UINT64 Signature; + UINT32 Revision; + UINT32 HeaderSize; + UINT32 CRC32; + UINT32 Reserved; +} EFI_TABLE_HEADER; + +#define EFI_PAGE_SIZE 4096 + + +typedef VOID *EFI_HANDLE; +typedef UINT16 EFI_HII_HANDLE; +typedef UINT16 STRING_REF; +typedef struct { + INT16 Value; + INT16 Exponent; +} EFI_EXP_BASE10_DATA; + +// +// Define macros to build data structure signatures from characters. +// +#define EFI_SIGNATURE_16(A, B) ((A) | (B << 8)) +#define EFI_SIGNATURE_32(A, B, C, D) (EFI_SIGNATURE_16 (A, B) | (EFI_SIGNATURE_16 (C, D) << 16)) +#define EFI_SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (EFI_SIGNATURE_32 (A, B, C, D) | ((UINT64) (EFI_SIGNATURE_32 (E, F, G, H)) << 32)) + + +#include + +#endif diff --git a/MdePkg/Include/Common/Pcd.h b/MdePkg/Include/Common/Pcd.h new file mode 100644 index 0000000000..7d1362ccf3 --- /dev/null +++ b/MdePkg/Include/Common/Pcd.h @@ -0,0 +1,33 @@ +/** @file + This file defines the common macro and data structure shared between PCD PEIM and + PCD DXE driver. + + Copyright (c) 2006, 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. + + Module Name: Pcd.h + +**/ +#ifndef _COMMON_PCD_H +#define _COMMON_PCD_H + +typedef UINT32 PCD_TOKEN_NUMBER; +typedef UINT8 SKU_ID; + +#define PCD_INVALID_TOKEN ((PCD_TOKEN_NUMBER)(-1)) + +typedef +VOID +(EFIAPI *PCD_PROTOCOL_CALLBACK) ( + IN UINT32 CallBackToken, + IN VOID *TokenData, + IN UINTN TokenDataSize + ); + +#endif diff --git a/MdePkg/Include/Common/PcdTemp.h b/MdePkg/Include/Common/PcdTemp.h new file mode 100644 index 0000000000..3428b4f6fe --- /dev/null +++ b/MdePkg/Include/Common/PcdTemp.h @@ -0,0 +1,91 @@ +/** @file + +Copyright (c) 2006, 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 __PCD_TEMP_H__ +#define __PCD_TEMP_H__ + +#define PCD_INVALID_TOKEN ((UINTN)(-1)) + +/* + * The following structure will be removed soon after the real + * PCD service PEIM and DXE driver are implmented. + */ + +/// +/// I have rearranged the data so that the variable length items are at the end of the structure +/// and we have a reasonable change of interpreting the other stuff properly. +/// +typedef struct { + UINTN Token; + + // + // HII Knowledge - non optimized for now + // + UINT8 HiiData; // If TRUE, use Variable Data + UINT8 SKUEnabled; // If TRUE, there might be various SKU data entries for this Token + UINT8 MaxSKUCount; // Up to 256 entries - limits the search space + UINT8 SKUId; // ID of the SKU + + GUID VariableGuid; // Variable GUID + UINT32 DatumSize; + UINT64 Datum; + CHAR16 *VariableName; // Null-terminated Variable Name (remember to calculate size) + // We still need Offset information for the variable + // So naturally we can use DatumSize as the Length Field + // And we can overload the use of Datum for the Offset information + VOID *ExtendedData; // VOID* data of size DatumSize +} EMULATED_PCD_ENTRY; + +typedef +VOID +(EFIAPI *PCD_TEMP_CALLBACK) ( + IN CONST EFI_GUID *CallBackGuid, OPTIONAL + IN UINTN CallBackToken, + IN VOID *TokenData, + IN UINTN TokenDataSize + ); + +/// +/// Used by the PCD Database - never contained in an FFS file +/// +typedef struct { + UINTN Token; + + // + // HII Knowledge - non optimized for now + // + UINT8 HiiData; // If TRUE, use Variable Data + UINT8 SKUEnabled; // If TRUE, there might be various SKU data entries for this Token + UINT8 MaxSKUCount; // Up to 256 entries - limits the search space + UINT8 SKUId; // ID of the SKU + + GUID VariableGuid; // Variable GUID + UINT32 DatumSize; + UINT64 Datum; + CHAR16 *VariableName; // Null-terminated Variable Name (remember to calculate size) + // We still need Offset information for the variable + // So naturally we can use DatumSize as the Length Field + // And we can overload the use of Datum for the Offset information + VOID *ExtendedData; // VOID* data of size DatumSize + + PCD_TEMP_CALLBACK *CallBackList; + UINT32 CallBackEntries; + UINT32 CallBackListSize; +} EMULATED_PCD_ENTRY_EX; // This exists to facilitate PCD Database implementation only + +typedef struct { + UINTN Count; + EMULATED_PCD_ENTRY_EX Entry[1]; // This exists to facilitate PCD Database implementation only +} EMULATED_PCD_DATABASE_EX; + +#endif diff --git a/MdePkg/Include/Common/StatusCode.h b/MdePkg/Include/Common/StatusCode.h new file mode 100644 index 0000000000..474ed106f8 --- /dev/null +++ b/MdePkg/Include/Common/StatusCode.h @@ -0,0 +1,912 @@ +/** @file + Status Code Definitions, according to Intel Platform Innovation Framework + for EFI Status Codes Specification + + The file is divided into sections for ease of use. + +
+  Section:    Contents:
+  1           General Status Code Definitions
+  2           Class definitions
+  3           Computing Unit Subclasses, Progress and Error Codes
+  4           Peripheral Subclasses, Progress and Error Codes.
+  5           IO Bus Subclasses, Progress and Error Codes.
+  6           Software Subclasses, Progress and Error Codes.
+  7           Debug Codes
+
+ + Copyright (c) 2006, 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. + + Module Name: StatusCode.h + + @par Revision Reference: + Version 0.92. + +**/ + +#ifndef _EFI_STATUS_CODE_H_ +#define _EFI_STATUS_CODE_H_ + + +// +// ///////////////////////////////////////////////////////////////////////////// +// Section 1 +/////////////////////////////////////////////////////////////////////////////// + +// +// A Status Code Type is made up of the code type and severity +// All values masked by EFI_STATUS_CODE_RESERVED_MASK are +// reserved for use by this specification. +// +#define EFI_STATUS_CODE_TYPE_MASK 0x000000FF +#define EFI_STATUS_CODE_SEVERITY_MASK 0xFF000000 +#define EFI_STATUS_CODE_RESERVED_MASK 0x00FFFF00 + +// +// Definition of code types, all other values masked by +// EFI_STATUS_CODE_TYPE_MASK are reserved for use by +// this specification. +// +#define EFI_PROGRESS_CODE 0x00000001 +#define EFI_ERROR_CODE 0x00000002 +#define EFI_DEBUG_CODE 0x00000003 + +// +// Definitions of severities, all other values masked by +// EFI_STATUS_CODE_SEVERITY_MASK are reserved for use by +// this specification. +// +#define EFI_ERROR_MINOR 0x40000000 +#define EFI_ERROR_MAJOR 0x80000000 +#define EFI_ERROR_UNRECOVERED 0x90000000 +#define EFI_ERROR_UNCONTAINED 0xA0000000 + +// +// A Status Code Value is made up of the class, subclass, and +// an operation. Classes, subclasses, and operations are defined +// in the following sections. +// +#define EFI_STATUS_CODE_CLASS_MASK 0xFF000000 +#define EFI_STATUS_CODE_SUBCLASS_MASK 0x00FF0000 +#define EFI_STATUS_CODE_OPERATION_MASK 0x0000FFFF + +// +// Data Hub Status Code class record definition +// +typedef struct { + EFI_STATUS_CODE_TYPE CodeType; + EFI_STATUS_CODE_VALUE Value; + UINT32 Instance; + EFI_GUID CallerId; + EFI_STATUS_CODE_DATA Data; +} DATA_HUB_STATUS_CODE_DATA_RECORD; + +// +// ///////////////////////////////////////////////////////////////////////////// +// Section 2 +/////////////////////////////////////////////////////////////////////////////// +// +// Class definitions +// Values of 4-127 are reserved for future use by this +// specification. +// Values in the range 127-255 are reserved for OEM use. +// +#define EFI_COMPUTING_UNIT 0x00000000 +#define EFI_PERIPHERAL 0x01000000 +#define EFI_IO_BUS 0x02000000 +#define EFI_SOFTWARE 0x03000000 + +// +// General partitioning scheme for Progress and Error Codes are +// 0x0000-0x0FFF - Shared by all sub-classes in a given class +// 0x1000-0x7FFF - Subclass Specific +// 0x8000-0xFFFF - OEM specific +// +#define EFI_SUBCLASS_SPECIFIC 0x1000 +#define EFI_OEM_SPECIFIC 0x8000 + +// +// ///////////////////////////////////////////////////////////////////////////// +// Section 3 +/////////////////////////////////////////////////////////////////////////////// +// +// Computing Unit Subclass definitions. +// Values of 8-127 are reserved for future use by this +// specification. +// Values of 128-255 are reserved for OEM use. +// +#define EFI_COMPUTING_UNIT_UNSPECIFIED (EFI_COMPUTING_UNIT | 0x00000000) +#define EFI_COMPUTING_UNIT_HOST_PROCESSOR (EFI_COMPUTING_UNIT | 0x00010000) +#define EFI_COMPUTING_UNIT_FIRMWARE_PROCESSOR (EFI_COMPUTING_UNIT | 0x00020000) +#define EFI_COMPUTING_UNIT_IO_PROCESSOR (EFI_COMPUTING_UNIT | 0x00030000) +#define EFI_COMPUTING_UNIT_CACHE (EFI_COMPUTING_UNIT | 0x00040000) +#define EFI_COMPUTING_UNIT_MEMORY (EFI_COMPUTING_UNIT | 0x00050000) +#define EFI_COMPUTING_UNIT_CHIPSET (EFI_COMPUTING_UNIT | 0x00060000) + +// +// Computing Unit Class Progress Code definitions. +// These are shared by all subclasses. +// +#define EFI_CU_PC_INIT_BEGIN 0x00000000 +#define EFI_CU_PC_INIT_END 0x00000001 + +// +// Computing Unit Unspecified Subclass Progress Code definitions. +// +// +// Computing Unit Host Processor Subclass Progress Code definitions. +// +#define EFI_CU_HP_PC_POWER_ON_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_HP_PC_CACHE_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_HP_PC_RAM_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_HP_PC_MEMORY_CONTROLLER_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_CU_HP_PC_IO_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_CU_HP_PC_BSP_SELECT (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_CU_HP_PC_BSP_RESELECT (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_CU_HP_PC_AP_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_CU_HP_PC_SMM_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000008) + +// +// Computing Unit Firmware Processor Subclass Progress Code definitions. +// +// +// Computing Unit IO Processor Subclass Progress Code definitions. +// +// +// Computing Unit Cache Subclass Progress Code definitions. +// +#define EFI_CU_CACHE_PC_PRESENCE_DETECT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_CACHE_PC_CONFIGURATION (EFI_SUBCLASS_SPECIFIC | 0x00000001) + +// +// Computing Unit Memory Subclass Progress Code definitions. +// +#define EFI_CU_MEMORY_PC_SPD_READ (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_MEMORY_PC_PRESENCE_DETECT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_MEMORY_PC_TIMING (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_MEMORY_PC_CONFIGURING (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_CU_MEMORY_PC_OPTIMIZING (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_CU_MEMORY_PC_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_CU_MEMORY_PC_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000006) + +// +// Computing Unit Chipset Subclass Progress Code definitions. +// +// +// Computing Unit Class Error Code definitions. +// These are shared by all subclasses. +// +#define EFI_CU_EC_NON_SPECIFIC 0x00000000 +#define EFI_CU_EC_DISABLED 0x00000001 +#define EFI_CU_EC_NOT_SUPPORTED 0x00000002 +#define EFI_CU_EC_NOT_DETECTED 0x00000003 +#define EFI_CU_EC_NOT_CONFIGURED 0x00000004 + +// +// Computing Unit Unspecified Subclass Error Code definitions. +// +// +// Computing Unit Host Processor Subclass Error Code definitions. +// +#define EFI_CU_HP_EC_INVALID_TYPE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_HP_EC_INVALID_SPEED (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_HP_EC_MISMATCH (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_HP_EC_TIMER_EXPIRED (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_CU_HP_EC_SELF_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_CU_HP_EC_INTERNAL (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_CU_HP_EC_THERMAL (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_CU_HP_EC_LOW_VOLTAGE (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_CU_HP_EC_HIGH_VOLTAGE (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_CU_HP_EC_CACHE (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_CU_HP_EC_MICROCODE_UPDATE (EFI_SUBCLASS_SPECIFIC | 0x0000000A) +#define EFI_CU_HP_EC_CORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x0000000B) +#define EFI_CU_HP_EC_UNCORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x0000000C) +#define EFI_CU_HP_EC_NO_MICROCODE_UPDATE (EFI_SUBCLASS_SPECIFIC | 0x0000000D) + +// +// Computing Unit Firmware Processor Subclass Error Code definitions. +// +#define EFI_CU_FP_EC_HARD_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_FP_EC_SOFT_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_FP_EC_COMM_ERROR (EFI_SUBCLASS_SPECIFIC | 0x00000002) + +// +// Computing Unit IO Processor Subclass Error Code definitions. +// +// +// Computing Unit Cache Subclass Error Code definitions. +// +#define EFI_CU_CACHE_EC_INVALID_TYPE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_CACHE_EC_INVALID_SPEED (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_CACHE_EC_INVALID_SIZE (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_CACHE_EC_MISMATCH (EFI_SUBCLASS_SPECIFIC | 0x00000003) + +// +// Computing Unit Memory Subclass Error Code definitions. +// +#define EFI_CU_MEMORY_EC_INVALID_TYPE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_CU_MEMORY_EC_INVALID_SPEED (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_CU_MEMORY_EC_CORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_CU_MEMORY_EC_UNCORRECTABLE (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_CU_MEMORY_EC_SPD_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_CU_MEMORY_EC_INVALID_SIZE (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_CU_MEMORY_EC_MISMATCH (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_CU_MEMORY_EC_S3_RESUME_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_CU_MEMORY_EC_UPDATE_FAIL (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_CU_MEMORY_EC_NONE_DETECTED (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_CU_MEMORY_EC_NONE_USEFUL (EFI_SUBCLASS_SPECIFIC | 0x0000000A) + +// +// Computing Unit Chipset Subclass Error Code definitions. +// + +/////////////////////////////////////////////////////////////////////////////// +// Section 4 +/////////////////////////////////////////////////////////////////////////////// +// +// Peripheral Subclass definitions. +// Values of 12-127 are reserved for future use by this +// specification. +// Values of 128-255 are reserved for OEM use. +// +#define EFI_PERIPHERAL_UNSPECIFIED (EFI_PERIPHERAL | 0x00000000) +#define EFI_PERIPHERAL_KEYBOARD (EFI_PERIPHERAL | 0x00010000) +#define EFI_PERIPHERAL_MOUSE (EFI_PERIPHERAL | 0x00020000) +#define EFI_PERIPHERAL_LOCAL_CONSOLE (EFI_PERIPHERAL | 0x00030000) +#define EFI_PERIPHERAL_REMOTE_CONSOLE (EFI_PERIPHERAL | 0x00040000) +#define EFI_PERIPHERAL_SERIAL_PORT (EFI_PERIPHERAL | 0x00050000) +#define EFI_PERIPHERAL_PARALLEL_PORT (EFI_PERIPHERAL | 0x00060000) +#define EFI_PERIPHERAL_FIXED_MEDIA (EFI_PERIPHERAL | 0x00070000) +#define EFI_PERIPHERAL_REMOVABLE_MEDIA (EFI_PERIPHERAL | 0x00080000) +#define EFI_PERIPHERAL_AUDIO_INPUT (EFI_PERIPHERAL | 0x00090000) +#define EFI_PERIPHERAL_AUDIO_OUTPUT (EFI_PERIPHERAL | 0x000A0000) +#define EFI_PERIPHERAL_LCD_DEVICE (EFI_PERIPHERAL | 0x000B0000) +#define EFI_PERIPHERAL_NETWORK (EFI_PERIPHERAL | 0x000C0000) + +// +// Peripheral Class Progress Code definitions. +// These are shared by all subclasses. +// +#define EFI_P_PC_INIT 0x00000000 +#define EFI_P_PC_RESET 0x00000001 +#define EFI_P_PC_DISABLE 0x00000002 +#define EFI_P_PC_PRESENCE_DETECT 0x00000003 +#define EFI_P_PC_ENABLE 0x00000004 +#define EFI_P_PC_RECONFIG 0x00000005 +#define EFI_P_PC_DETECTED 0x00000006 + +// +// Peripheral Class Unspecified Subclass Progress Code definitions. +// +// +// Peripheral Class Keyboard Subclass Progress Code definitions. +// +#define EFI_P_KEYBOARD_PC_CLEAR_BUFFER (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_P_KEYBOARD_PC_SELF_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000001) + +// +// Peripheral Class Mouse Subclass Progress Code definitions. +// +#define EFI_P_MOUSE_PC_SELF_TEST (EFI_SUBCLASS_SPECIFIC | 0x00000000) + +// +// Peripheral Class Local Console Subclass Progress Code definitions. +// +// +// Peripheral Class Remote Console Subclass Progress Code definitions. +// +// +// Peripheral Class Serial Port Subclass Progress Code definitions. +// +#define EFI_P_SERIAL_PORT_PC_CLEAR_BUFFER (EFI_SUBCLASS_SPECIFIC | 0x00000000) + +// +// Peripheral Class Parallel Port Subclass Progress Code definitions. +// +// +// Peripheral Class Fixed Media Subclass Progress Code definitions. +// +// +// Peripheral Class Removable Media Subclass Progress Code definitions. +// +// +// Peripheral Class Audio Input Subclass Progress Code definitions. +// +// +// Peripheral Class Audio Output Subclass Progress Code definitions. +// +// +// Peripheral Class LCD Device Subclass Progress Code definitions. +// +// +// Peripheral Class Network Subclass Progress Code definitions. +// +// +// Peripheral Class Error Code definitions. +// These are shared by all subclasses. +// +#define EFI_P_EC_NON_SPECIFIC 0x00000000 +#define EFI_P_EC_DISABLED 0x00000001 +#define EFI_P_EC_NOT_SUPPORTED 0x00000002 +#define EFI_P_EC_NOT_DETECTED 0x00000003 +#define EFI_P_EC_NOT_CONFIGURED 0x00000004 +#define EFI_P_EC_INTERFACE_ERROR 0x00000005 +#define EFI_P_EC_CONTROLLER_ERROR 0x00000006 +#define EFI_P_EC_INPUT_ERROR 0x00000007 +#define EFI_P_EC_OUTPUT_ERROR 0x00000008 +#define EFI_P_EC_RESOURCE_CONFLICT 0x00000009 + +// +// Peripheral Class Unspecified Subclass Error Code definitions. +// +// +// Peripheral Class Keyboard Subclass Error Code definitions. +// +#define EFI_P_KEYBOARD_EC_LOCKED (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_P_KEYBOARD_EC_STUCK_KEY (EFI_SUBCLASS_SPECIFIC | 0x00000001) + +// +// Peripheral Class Mouse Subclass Error Code definitions. +// +#define EFI_P_MOUSE_EC_LOCKED (EFI_SUBCLASS_SPECIFIC | 0x00000000) + +// +// Peripheral Class Local Console Subclass Error Code definitions. +// +// +// Peripheral Class Remote Console Subclass Error Code definitions. +// +// +// Peripheral Class Serial Port Subclass Error Code definitions. +// +// +// Peripheral Class Parallel Port Subclass Error Code definitions. +// +// +// Peripheral Class Fixed Media Subclass Error Code definitions. +// +// +// Peripheral Class Removable Media Subclass Error Code definitions. +// +// +// Peripheral Class Audio Input Subclass Error Code definitions. +// +// +// Peripheral Class Audio Output Subclass Error Code definitions. +// +// +// Peripheral Class LCD Device Subclass Error Code definitions. +// +// +// Peripheral Class Network Subclass Error Code definitions. +// + +/////////////////////////////////////////////////////////////////////////////// +// Section 5 +/////////////////////////////////////////////////////////////////////////////// +// +// IO Bus Subclass definitions. +// Values of 14-127 are reserved for future use by this +// specification. +// Values of 128-255 are reserved for OEM use. +// +#define EFI_IO_BUS_UNSPECIFIED (EFI_IO_BUS | 0x00000000) +#define EFI_IO_BUS_PCI (EFI_IO_BUS | 0x00010000) +#define EFI_IO_BUS_USB (EFI_IO_BUS | 0x00020000) +#define EFI_IO_BUS_IBA (EFI_IO_BUS | 0x00030000) +#define EFI_IO_BUS_AGP (EFI_IO_BUS | 0x00040000) +#define EFI_IO_BUS_PC_CARD (EFI_IO_BUS | 0x00050000) +#define EFI_IO_BUS_LPC (EFI_IO_BUS | 0x00060000) +#define EFI_IO_BUS_SCSI (EFI_IO_BUS | 0x00070000) +#define EFI_IO_BUS_ATA_ATAPI (EFI_IO_BUS | 0x00080000) +#define EFI_IO_BUS_FC (EFI_IO_BUS | 0x00090000) +#define EFI_IO_BUS_IP_NETWORK (EFI_IO_BUS | 0x000A0000) +#define EFI_IO_BUS_SMBUS (EFI_IO_BUS | 0x000B0000) +#define EFI_IO_BUS_I2C (EFI_IO_BUS | 0x000C0000) + +// +// IO Bus Class Progress Code definitions. +// These are shared by all subclasses. +// +#define EFI_IOB_PC_INIT 0x00000000 +#define EFI_IOB_PC_RESET 0x00000001 +#define EFI_IOB_PC_DISABLE 0x00000002 +#define EFI_IOB_PC_DETECT 0x00000003 +#define EFI_IOB_PC_ENABLE 0x00000004 +#define EFI_IOB_PC_RECONFIG 0x00000005 +#define EFI_IOB_PC_HOTPLUG 0x00000006 + +// +// IO Bus Class Unspecified Subclass Progress Code definitions. +// +// +// IO Bus Class PCI Subclass Progress Code definitions. +// +#define EFI_IOB_PCI_PC_BUS_ENUM (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_IOB_PCI_PC_RES_ALLOC (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_IOB_PCI_PC_HPC_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000002) + +// +// IO Bus Class USB Subclass Progress Code definitions. +// +// +// IO Bus Class IBA Subclass Progress Code definitions. +// +// +// IO Bus Class AGP Subclass Progress Code definitions. +// +// +// IO Bus Class PC Card Subclass Progress Code definitions. +// +// +// IO Bus Class LPC Subclass Progress Code definitions. +// +// +// IO Bus Class SCSI Subclass Progress Code definitions. +// +// +// IO Bus Class ATA/ATAPI Subclass Progress Code definitions. +// +#define EFI_IOB_ATA_BUS_SMART_ENABLE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_IOB_ATA_BUS_SMART_DISABLE (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_IOB_ATA_BUS_SMART_OVERTHRESHOLD (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_IOB_ATA_BUS_SMART_UNDERTHRESHOLD (EFI_SUBCLASS_SPECIFIC | 0x00000003) + +// +// IO Bus Class FC Subclass Progress Code definitions. +// +// +// IO Bus Class IP Network Subclass Progress Code definitions. +// +// +// IO Bus Class SMBUS Subclass Progress Code definitions. +// +// +// IO Bus Class I2C Subclass Progress Code definitions. +// +// +// IO Bus Class Error Code definitions. +// These are shared by all subclasses. +// +#define EFI_IOB_EC_NON_SPECIFIC 0x00000000 +#define EFI_IOB_EC_DISABLED 0x00000001 +#define EFI_IOB_EC_NOT_SUPPORTED 0x00000002 +#define EFI_IOB_EC_NOT_DETECTED 0x00000003 +#define EFI_IOB_EC_NOT_CONFIGURED 0x00000004 +#define EFI_IOB_EC_INTERFACE_ERROR 0x00000005 +#define EFI_IOB_EC_CONTROLLER_ERROR 0x00000006 +#define EFI_IOB_EC_READ_ERROR 0x00000007 +#define EFI_IOB_EC_WRITE_ERROR 0x00000008 +#define EFI_IOB_EC_RESOURCE_CONFLICT 0x00000009 + +// +// IO Bus Class Unspecified Subclass Error Code definitions. +// +// +// IO Bus Class PCI Subclass Error Code definitions. +// +#define EFI_IOB_PCI_EC_PERR (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_IOB_PCI_EC_SERR (EFI_SUBCLASS_SPECIFIC | 0x00000001) + +// +// IO Bus Class USB Subclass Error Code definitions. +// +// +// IO Bus Class IBA Subclass Error Code definitions. +// +// +// IO Bus Class AGP Subclass Error Code definitions. +// +// +// IO Bus Class PC Card Subclass Error Code definitions. +// +// +// IO Bus Class LPC Subclass Error Code definitions. +// +// +// IO Bus Class SCSI Subclass Error Code definitions. +// +// +// IO Bus Class ATA/ATAPI Subclass Error Code definitions. +// +#define EFI_IOB_ATA_BUS_SMART_NOTSUPPORTED (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_IOB_ATA_BUS_SMART_DISABLED (EFI_SUBCLASS_SPECIFIC | 0x00000001) + +// +// IO Bus Class FC Subclass Error Code definitions. +// +// +// IO Bus Class IP Network Subclass Error Code definitions. +// +// +// IO Bus Class SMBUS Subclass Error Code definitions. +// +// +// IO Bus Class I2C Subclass Error Code definitions. +// + +/////////////////////////////////////////////////////////////////////////////// +// Section 6 +/////////////////////////////////////////////////////////////////////////////// +// +// Software Subclass definitions. +// Values of 14-127 are reserved for future use by this +// specification. +// Values of 128-255 are reserved for OEM use. +// +#define EFI_SOFTWARE_UNSPECIFIED (EFI_SOFTWARE | 0x00000000) +#define EFI_SOFTWARE_SEC (EFI_SOFTWARE | 0x00010000) +#define EFI_SOFTWARE_PEI_CORE (EFI_SOFTWARE | 0x00020000) +#define EFI_SOFTWARE_PEI_MODULE (EFI_SOFTWARE | 0x00030000) +#define EFI_SOFTWARE_DXE_CORE (EFI_SOFTWARE | 0x00040000) +#define EFI_SOFTWARE_DXE_BS_DRIVER (EFI_SOFTWARE | 0x00050000) +#define EFI_SOFTWARE_DXE_RT_DRIVER (EFI_SOFTWARE | 0x00060000) +#define EFI_SOFTWARE_SMM_DRIVER (EFI_SOFTWARE | 0x00070000) +#define EFI_SOFTWARE_EFI_APPLICATION (EFI_SOFTWARE | 0x00080000) +#define EFI_SOFTWARE_EFI_OS_LOADER (EFI_SOFTWARE | 0x00090000) +#define EFI_SOFTWARE_RT (EFI_SOFTWARE | 0x000A0000) +#define EFI_SOFTWARE_AL (EFI_SOFTWARE | 0x000B0000) +#define EFI_SOFTWARE_EBC_EXCEPTION (EFI_SOFTWARE | 0x000C0000) +#define EFI_SOFTWARE_IA32_EXCEPTION (EFI_SOFTWARE | 0x000D0000) +#define EFI_SOFTWARE_IPF_EXCEPTION (EFI_SOFTWARE | 0x000E0000) +#define EFI_SOFTWARE_PEI_SERVICE (EFI_SOFTWARE | 0x000F0000) +#define EFI_SOFTWARE_EFI_BOOT_SERVICE (EFI_SOFTWARE | 0x00100000) +#define EFI_SOFTWARE_EFI_RUNTIME_SERVICE (EFI_SOFTWARE | 0x00110000) +#define EFI_SOFTWARE_EFI_DXE_SERVICE (EFI_SOFTWARE | 0x00120000) + +// +// Software Class Progress Code definitions. +// These are shared by all subclasses. +// +#define EFI_SW_PC_INIT 0x00000000 +#define EFI_SW_PC_LOAD 0x00000001 +#define EFI_SW_PC_INIT_BEGIN 0x00000002 +#define EFI_SW_PC_INIT_END 0x00000003 +#define EFI_SW_PC_AUTHENTICATE_BEGIN 0x00000004 +#define EFI_SW_PC_AUTHENTICATE_END 0x00000005 +#define EFI_SW_PC_INPUT_WAIT 0x00000006 +#define EFI_SW_PC_USER_SETUP 0x00000007 + +// +// Software Class Unspecified Subclass Progress Code definitions. +// +// +// Software Class SEC Subclass Progress Code definitions. +// +#define EFI_SW_SEC_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_SEC_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001) + +// +// Software Class PEI Core Subclass Progress Code definitions. +// +#define EFI_SW_PEI_CORE_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PEI_CORE_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_PEI_CORE_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002) + +// +// Software Class PEI Module Subclass Progress Code definitions. +// +#define EFI_SW_PEIM_PC_RECOVERY_BEGIN (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PEIM_PC_CAPSULE_LOAD (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_PEIM_PC_CAPSULE_START (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_PEIM_PC_RECOVERY_USER (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_PEIM_PC_RECOVERY_AUTO (EFI_SUBCLASS_SPECIFIC | 0x00000004) + +// +// Software Class DXE Core Subclass Progress Code definitions. +// +#define EFI_SW_DXE_CORE_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DXE_CORE_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DXE_CORE_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DXE_CORE_PC_START_DRIVER (EFI_SUBCLASS_SPECIFIC | 0x00000003) + +// +// Software Class DXE BS Driver Subclass Progress Code definitions. +// +#define EFI_SW_DXE_BS_PC_LEGACY_OPROM_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DXE_BS_PC_READY_TO_BOOT_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DXE_BS_PC_LEGACY_BOOT_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DXE_BS_PC_EXIT_BOOT_SERVICES_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DXE_BS_PC_VIRTUAL_ADDRESS_CHANGE_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_DXE_BS_PC_VERIFYING_PASSWORD (EFI_SUBCLASS_SPECIFIC | 0x00000006) + +// +// Software Class DXE RT Driver Subclass Progress Code definitions. +// +#define EFI_SW_DXE_RT_PC_S0 (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DXE_RT_PC_S1 (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DXE_RT_PC_S2 (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DXE_RT_PC_S3 (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DXE_RT_PC_S4 (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_DXE_RT_PC_S5 (EFI_SUBCLASS_SPECIFIC | 0x00000005) + +// +// Software Class SMM Driver Subclass Progress Code definitions. +// +// +// Software Class EFI Application Subclass Progress Code definitions. +// +// +// Software Class EFI OS Loader Subclass Progress Code definitions. +// +// +// Software Class EFI RT Subclass Progress Code definitions. +// +#define EFI_SW_RT_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_RT_PC_HANDOFF_TO_NEXT (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_RT_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000002) + +// +// Software Class EFI AL Subclass Progress Code definitions. +// +#define EFI_SW_AL_PC_ENTRY_POINT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_AL_PC_RETURN_TO_LAST (EFI_SUBCLASS_SPECIFIC | 0x00000001) + +// +// Software Class EBC Exception Subclass Progress Code definitions. +// +// +// Software Class IA32 Exception Subclass Progress Code definitions. +// +// +// Software Class IPF Exception Subclass Progress Code definitions. +// +// +// Software Class PEI Services Subclass Progress Code definitions. +// +#define EFI_SW_PS_PC_INSTALL_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PS_PC_REINSTALL_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_PS_PC_LOCATE_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_PS_PC_NOTIFY_PPI (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_PS_PC_GET_BOOT_MODE (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_PS_PC_SET_BOOT_MODE (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_PS_PC_GET_HOB_LIST (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_SW_PS_PC_CREATE_HOB (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_SW_PS_PC_FFS_FIND_NEXT_VOLUME (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_SW_PS_PC_FFS_FIND_NEXT_FILE (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_SW_PS_PC_FFS_FIND_SECTION_DATA (EFI_SUBCLASS_SPECIFIC | 0x0000000A) +#define EFI_SW_PS_PC_INSTALL_PEI_MEMORY (EFI_SUBCLASS_SPECIFIC | 0x0000000B) +#define EFI_SW_PS_PC_ALLOCATE_PAGES (EFI_SUBCLASS_SPECIFIC | 0x0000000C) +#define EFI_SW_PS_PC_ALLOCATE_POOL (EFI_SUBCLASS_SPECIFIC | 0x0000000D) +#define EFI_SW_PS_PC_COPY_MEM (EFI_SUBCLASS_SPECIFIC | 0x0000000E) +#define EFI_SW_PS_PC_SET_MEM (EFI_SUBCLASS_SPECIFIC | 0x0000000F) + +// +// Software Class EFI Boot Services Subclass Progress Code definitions. +// +#define EFI_SW_BS_PC_RAISE_TPL (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_BS_PC_RESTORE_TPL (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_BS_PC_ALLOCATE_PAGES (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_BS_PC_FREE_PAGES (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_BS_PC_GET_MEMORY_MAP (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_BS_PC_ALLOCATE_POOL (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_BS_PC_FREE_POOL (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_SW_BS_PC_CREATE_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_SW_BS_PC_SET_TIMER (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_SW_BS_PC_WAIT_FOR_EVENT (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_SW_BS_PC_SIGNAL_EVENT (EFI_SUBCLASS_SPECIFIC | 0x0000000A) +#define EFI_SW_BS_PC_CLOSE_EVENT (EFI_SUBCLASS_SPECIFIC | 0x0000000B) +#define EFI_SW_BS_PC_CHECK_EVENT (EFI_SUBCLASS_SPECIFIC | 0x0000000C) +#define EFI_SW_BS_PC_INSTALL_PROTOCOL_INTERFACE (EFI_SUBCLASS_SPECIFIC | 0x0000000D) +#define EFI_SW_BS_PC_REINSTALL_PROTOCOL_INTERFACE (EFI_SUBCLASS_SPECIFIC | 0x0000000E) +#define EFI_SW_BS_PC_UNINSTALL_PROTOCOL_INTERFACE (EFI_SUBCLASS_SPECIFIC | 0x0000000F) +#define EFI_SW_BS_PC_HANDLE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000010) +#define EFI_SW_BS_PC_PC_HANDLE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000011) +#define EFI_SW_BS_PC_REGISTER_PROTOCOL_NOTIFY (EFI_SUBCLASS_SPECIFIC | 0x00000012) +#define EFI_SW_BS_PC_LOCATE_HANDLE (EFI_SUBCLASS_SPECIFIC | 0x00000013) +#define EFI_SW_BS_PC_INSTALL_CONFIGURATION_TABLE (EFI_SUBCLASS_SPECIFIC | 0x00000014) +#define EFI_SW_BS_PC_LOAD_IMAGE (EFI_SUBCLASS_SPECIFIC | 0x00000015) +#define EFI_SW_BS_PC_START_IMAGE (EFI_SUBCLASS_SPECIFIC | 0x00000016) +#define EFI_SW_BS_PC_EXIT (EFI_SUBCLASS_SPECIFIC | 0x00000017) +#define EFI_SW_BS_PC_UNLOAD_IMAGE (EFI_SUBCLASS_SPECIFIC | 0x00000018) +#define EFI_SW_BS_PC_EXIT_BOOT_SERVICES (EFI_SUBCLASS_SPECIFIC | 0x00000019) +#define EFI_SW_BS_PC_GET_NEXT_MONOTONIC_COUNT (EFI_SUBCLASS_SPECIFIC | 0x0000001A) +#define EFI_SW_BS_PC_STALL (EFI_SUBCLASS_SPECIFIC | 0x0000001B) +#define EFI_SW_BS_PC_SET_WATCHDOG_TIMER (EFI_SUBCLASS_SPECIFIC | 0x0000001C) +#define EFI_SW_BS_PC_CONNECT_CONTROLLER (EFI_SUBCLASS_SPECIFIC | 0x0000001D) +#define EFI_SW_BS_PC_DISCONNECT_CONTROLLER (EFI_SUBCLASS_SPECIFIC | 0x0000001E) +#define EFI_SW_BS_PC_OPEN_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x0000001F) +#define EFI_SW_BS_PC_CLOSE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000020) +#define EFI_SW_BS_PC_OPEN_PROTOCOL_INFORMATION (EFI_SUBCLASS_SPECIFIC | 0x00000021) +#define EFI_SW_BS_PC_PROTOCOLS_PER_HANDLE (EFI_SUBCLASS_SPECIFIC | 0x00000022) +#define EFI_SW_BS_PC_LOCATE_HANDLE_BUFFER (EFI_SUBCLASS_SPECIFIC | 0x00000023) +#define EFI_SW_BS_PC_LOCATE_PROTOCOL (EFI_SUBCLASS_SPECIFIC | 0x00000024) +#define EFI_SW_BS_PC_INSTALL_MULTIPLE_INTERFACES (EFI_SUBCLASS_SPECIFIC | 0x00000025) +#define EFI_SW_BS_PC_UNINSTALL_MULTIPLE_INTERFACES (EFI_SUBCLASS_SPECIFIC | 0x00000026) +#define EFI_SW_BS_PC_CALCULATE_CRC_32 (EFI_SUBCLASS_SPECIFIC | 0x00000027) +#define EFI_SW_BS_PC_COPY_MEM (EFI_SUBCLASS_SPECIFIC | 0x00000028) +#define EFI_SW_BS_PC_SET_MEM (EFI_SUBCLASS_SPECIFIC | 0x00000029) + +// +// Software Class EFI Runtime Services Subclass Progress Code definitions. +// +#define EFI_SW_RS_PC_GET_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_RS_PC_SET_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_RS_PC_GET_WAKEUP_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_RS_PC_SET_WAKEUP_TIME (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_RS_PC_SET_VIRTUAL_ADDRESS_MAP (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_RS_PC_CONVERT_POINTER (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_RS_PC_GET_VARIABLE (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_SW_RS_PC_GET_NEXT_VARIABLE_NAME (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_SW_RS_PC_SET_VARIABLE (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_SW_RS_PC_GET_NEXT_HIGH_MONOTONIC_COUNT (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_SW_RS_PC_RESET_SYSTEM (EFI_SUBCLASS_SPECIFIC | 0x0000000A) + +// +// Software Class EFI DXE Services Subclass Progress Code definitions +// +#define EFI_SW_DS_PC_ADD_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_DS_PC_ALLOCATE_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000001) +#define EFI_SW_DS_PC_FREE_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000002) +#define EFI_SW_DS_PC_REMOVE_MEMORY_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000003) +#define EFI_SW_DS_PC_GET_MEMORY_SPACE_DESCRIPTOR (EFI_SUBCLASS_SPECIFIC | 0x00000004) +#define EFI_SW_DS_PC_SET_MEMORY_SPACE_ATTRIBUTES (EFI_SUBCLASS_SPECIFIC | 0x00000005) +#define EFI_SW_DS_PC_GET_MEMORY_SPACE_MAP (EFI_SUBCLASS_SPECIFIC | 0x00000006) +#define EFI_SW_DS_PC_ADD_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000007) +#define EFI_SW_DS_PC_ALLOCATE_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000008) +#define EFI_SW_DS_PC_FREE_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000009) +#define EFI_SW_DS_PC_REMOVE_IO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x0000000A) +#define EFI_SW_DS_PC_GET_IO_SPACE_DESCRIPTOR (EFI_SUBCLASS_SPECIFIC | 0x0000000B) +#define EFI_SW_DS_PC_GET_IO_SPACE_MAP (EFI_SUBCLASS_SPECIFIC | 0x0000000C) +#define EFI_SW_DS_PC_DISPATCH (EFI_SUBCLASS_SPECIFIC | 0x0000000D) +#define EFI_SW_DS_PC_SCHEDULE (EFI_SUBCLASS_SPECIFIC | 0x0000000E) +#define EFI_SW_DS_PC_TRUST (EFI_SUBCLASS_SPECIFIC | 0x0000000F) +#define EFI_SW_DS_PC_PROCESS_FIRMWARE_VOLUME (EFI_SUBCLASS_SPECIFIC | 0x00000010) + +// +// Software Class Error Code definitions. +// These are shared by all subclasses. +// +#define EFI_SW_EC_NON_SPECIFIC 0x00000000 +#define EFI_SW_EC_LOAD_ERROR 0x00000001 +#define EFI_SW_EC_INVALID_PARAMETER 0x00000002 +#define EFI_SW_EC_UNSUPPORTED 0x00000003 +#define EFI_SW_EC_INVALID_BUFFER 0x00000004 +#define EFI_SW_EC_OUT_OF_RESOURCES 0x00000005 +#define EFI_SW_EC_ABORTED 0x00000006 +#define EFI_SW_EC_ILLEGAL_SOFTWARE_STATE 0x00000007 +#define EFI_SW_EC_ILLEGAL_HARDWARE_STATE 0x00000008 +#define EFI_SW_EC_START_ERROR 0x00000009 +#define EFI_SW_EC_BAD_DATE_TIME 0x0000000A +#define EFI_SW_EC_CFG_INVALID 0x0000000B +#define EFI_SW_EC_CFG_CLR_REQUEST 0x0000000C +#define EFI_SW_EC_CFG_DEFAULT 0x0000000D +#define EFI_SW_EC_PWD_INVALID 0x0000000E +#define EFI_SW_EC_PWD_CLR_REQUEST 0x0000000F +#define EFI_SW_EC_PWD_CLEARED 0x00000010 +#define EFI_SW_EC_EVENT_LOG_FULL 0x00000011 + +// +// Software Class Unspecified Subclass Error Code definitions. +// +// +// Software Class SEC Subclass Error Code definitions. +// +// +// Software Class PEI Core Subclass Error Code definitions. +// +#define EFI_SW_PEI_CORE_EC_DXE_CORRUPT (EFI_SUBCLASS_SPECIFIC | 0x00000000) + +// +// Software Class PEI Module Subclass Error Code definitions. +// +#define EFI_SW_PEIM_EC_NO_RECOVERY_CAPSULE (EFI_SUBCLASS_SPECIFIC | 0x00000000) +#define EFI_SW_PEIM_EC_INVALID_CAPSULE_DESCRIPTOR (EFI_SUBCLASS_SPECIFIC | 0x00000001) + +// +// Software Class DXE Core Subclass Error Code definitions. +// +#define EFI_SW_CSM_LEGACY_ROM_INIT (EFI_SUBCLASS_SPECIFIC | 0x00000000) +// +// Software Class DXE Boot Service Driver Subclass Error Code definitions. +// +#define EFI_SW_DXE_BS_EC_LEGACY_OPROM_NO_SPACE (EFI_SUBCLASS_SPECIFIC | 0x00000000) + +// +// Software Class DXE Runtime Service Driver Subclass Error Code definitions. +// +// +// Software Class SMM Driver Subclass Error Code definitions. +// +// +// Software Class EFI Application Subclass Error Code definitions. +// +// +// Software Class EFI OS Loader Subclass Error Code definitions. +// +// +// Software Class EFI RT Subclass Error Code definitions. +// +// +// Software Class EFI AL Subclass Error Code definitions. +// +// +// Software Class EBC Exception Subclass Error Code definitions. +// These exceptions are derived from the debug protocol definitions in the EFI +// specification. +// +#define EFI_SW_EC_EBC_UNDEFINED 0x00000000 +#define EFI_SW_EC_EBC_DIVIDE_ERROR EXCEPT_EBC_DIVIDE_ERROR +#define EFI_SW_EC_EBC_DEBUG EXCEPT_EBC_DEBUG +#define EFI_SW_EC_EBC_BREAKPOINT EXCEPT_EBC_BREAKPOINT +#define EFI_SW_EC_EBC_OVERFLOW EXCEPT_EBC_OVERFLOW +#define EFI_SW_EC_EBC_INVALID_OPCODE EXCEPT_EBC_INVALID_OPCODE +#define EFI_SW_EC_EBC_STACK_FAULT EXCEPT_EBC_STACK_FAULT +#define EFI_SW_EC_EBC_ALIGNMENT_CHECK EXCEPT_EBC_ALIGNMENT_CHECK +#define EFI_SW_EC_EBC_INSTRUCTION_ENCODING EXCEPT_EBC_INSTRUCTION_ENCODING +#define EFI_SW_EC_EBC_BAD_BREAK EXCEPT_EBC_BAD_BREAK +#define EFI_SW_EC_EBC_STEP EXCEPT_EBC_STEP + +// +// Software Class IA32 Exception Subclass Error Code definitions. +// These exceptions are derived from the debug protocol definitions in the EFI +// specification. +// +#define EFI_SW_EC_IA32_DIVIDE_ERROR EXCEPT_IA32_DIVIDE_ERROR +#define EFI_SW_EC_IA32_DEBUG EXCEPT_IA32_DEBUG +#define EFI_SW_EC_IA32_NMI EXCEPT_IA32_NMI +#define EFI_SW_EC_IA32_BREAKPOINT EXCEPT_IA32_BREAKPOINT +#define EFI_SW_EC_IA32_OVERFLOW EXCEPT_IA32_OVERFLOW +#define EFI_SW_EC_IA32_BOUND EXCEPT_IA32_BOUND +#define EFI_SW_EC_IA32_INVALID_OPCODE EXCEPT_IA32_INVALID_OPCODE +#define EFI_SW_EC_IA32_DOUBLE_FAULT EXCEPT_IA32_DOUBLE_FAULT +#define EFI_SW_EC_IA32_INVALID_TSS EXCEPT_IA32_INVALID_TSS +#define EFI_SW_EC_IA32_SEG_NOT_PRESENT EXCEPT_IA32_SEG_NOT_PRESENT +#define EFI_SW_EC_IA32_STACK_FAULT EXCEPT_IA32_STACK_FAULT +#define EFI_SW_EC_IA32_GP_FAULT EXCEPT_IA32_GP_FAULT +#define EFI_SW_EC_IA32_PAGE_FAULT EXCEPT_IA32_PAGE_FAULT +#define EFI_SW_EC_IA32_FP_ERROR EXCEPT_IA32_FP_ERROR +#define EFI_SW_EC_IA32_ALIGNMENT_CHECK EXCEPT_IA32_ALIGNMENT_CHECK +#define EFI_SW_EC_IA32_MACHINE_CHECK EXCEPT_IA32_MACHINE_CHECK +#define EFI_SW_EC_IA32_SIMD EXCEPT_IA32_SIMD + +// +// Software Class IPF Exception Subclass Error Code definitions. +// These exceptions are derived from the debug protocol definitions in the EFI +// specification. +// +#define EFI_SW_EC_IPF_ALT_DTLB EXCEPT_IPF_ALT_DTLB +#define EFI_SW_EC_IPF_DNESTED_TLB EXCEPT_IPF_DNESTED_TLB +#define EFI_SW_EC_IPF_BREAKPOINT EXCEPT_IPF_BREAKPOINT +#define EFI_SW_EC_IPF_EXTERNAL_INTERRUPT EXCEPT_IPF_EXTERNAL_INTERRUPT +#define EFI_SW_EC_IPF_GEN_EXCEPT EXCEPT_IPF_GEN_EXCEPT +#define EFI_SW_EC_IPF_NAT_CONSUMPTION EXCEPT_IPF_NAT_CONSUMPTION +#define EFI_SW_EC_IPF_DEBUG_EXCEPT EXCEPT_IPF_DEBUG_EXCEPT +#define EFI_SW_EC_IPF_UNALIGNED_ACCESS EXCEPT_IPF_UNALIGNED_ACCESS +#define EFI_SW_EC_IPF_FP_FAULT EXCEPT_IPF_FP_FAULT +#define EFI_SW_EC_IPF_FP_TRAP EXCEPT_IPF_FP_TRAP +#define EFI_SW_EC_IPF_TAKEN_BRANCH EXCEPT_IPF_TAKEN_BRANCH +#define EFI_SW_EC_IPF_SINGLE_STEP EXCEPT_IPF_SINGLE_STEP + +// +// Software Class PEI Service Subclass Error Code definitions. +// +// +// Software Class EFI Boot Service Subclass Error Code definitions. +// +// +// Software Class EFI Runtime Service Subclass Error Code definitions. +// +// +// Software Class EFI DXE Service Subclass Error Code definitions. +// + +/////////////////////////////////////////////////////////////////////////////// +// Section 7 +/////////////////////////////////////////////////////////////////////////////// +// +// Debug Code definitions for all classes and subclass +// Only one debug code is defined at this point and should +// be used for anything that gets sent to debug stream. +// +#define EFI_DC_UNSPECIFIED 0x0 + +#endif diff --git a/MdePkg/Include/Common/StatusCodeDataTypeId.h b/MdePkg/Include/Common/StatusCodeDataTypeId.h new file mode 100644 index 0000000000..49bea6122e --- /dev/null +++ b/MdePkg/Include/Common/StatusCodeDataTypeId.h @@ -0,0 +1,336 @@ +/** @file + This file defines the data structures to support Status Code Data. + + Copyright (c) 2006, 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. + + Module Name: StatusCodeDataTypeId.h + + @par Revision Reference: + These definitions are from Framework of EFI Status Code Spec + Version 0.92. + +**/ + +#ifndef __STATUS_CODE_DATA_TYPE_ID_H__ +#define __STATUS_CODE_DATA_TYPE_ID_H__ + + +/// +/// The size of string +/// +#define EFI_STATUS_CODE_DATA_MAX_STRING_SIZE 150 + +/// +/// This is the max data size including all the headers which can be passed +/// as Status Code data. This data should be multiple of 8 byte +/// to avoid any kind of boundary issue. Also, sum of this data size (inclusive +/// of size of EFI_STATUS_CODE_DATA should not exceed the max record size of +/// data hub +/// +#define EFI_STATUS_CODE_DATA_MAX_SIZE 200 + +#pragma pack(1) +typedef enum { + EfiStringAscii, + EfiStringUnicode, + EfiStringToken +} EFI_STRING_TYPE; + +typedef struct { + EFI_HII_HANDLE Handle; + STRING_REF Token; +} EFI_STATUS_CODE_STRING_TOKEN; + +typedef union { + CHAR8 *Ascii; + CHAR16 *Unicode; + EFI_STATUS_CODE_STRING_TOKEN Hii; +} EFI_STATUS_CODE_STRING; + +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_STRING_TYPE StringType; + EFI_STATUS_CODE_STRING String; +} EFI_STATUS_CODE_STRING_DATA; + +#pragma pack() + +#pragma pack(1) + +typedef struct { + UINT32 ErrorLevel; + // + // 12 * sizeof (UINT64) Var Arg stack + // + // ascii DEBUG () Format string + // +} EFI_DEBUG_INFO; + +#pragma pack() + +// +// declaration for EFI_EXP_DATA. This may change +// +// typedef UINTN EFI_EXP_DATA; + +/// +/// Voltage Extended Error Data +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_EXP_BASE10_DATA Voltage; + EFI_EXP_BASE10_DATA Threshold; +} EFI_COMPUTING_UNIT_VOLTAGE_ERROR_DATA; + +/// +/// Microcode Update Extended Error Data +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + UINT32 Version; +} EFI_COMPUTING_UNIT_MICROCODE_UPDATE_ERROR_DATA; + +/// +/// Asynchronous Timer Extended Error Data +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_EXP_BASE10_DATA TimerLimit; +} EFI_COMPUTING_UNIT_TIMER_EXPIRED_ERROR_DATA; + +/// +/// Host Processor Mismatch Extended Error Data +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + UINT32 Instance; + UINT16 Attributes; +} EFI_HOST_PROCESSOR_MISMATCH_ERROR_DATA; + +// +// EFI_COMPUTING_UNIT_MISMATCH_ATTRIBUTES +// All other attributes are reserved for future use and +// must be initialized to 0. +// +#define EFI_COMPUTING_UNIT_MISMATCH_SPEED 0x0001 +#define EFI_COMPUTING_UNIT_MISMATCH_FSB_SPEED 0x0002 +#define EFI_COMPUTING_UNIT_MISMATCH_FAMILY 0x0004 +#define EFI_COMPUTING_UNIT_MISMATCH_MODEL 0x0008 +#define EFI_COMPUTING_UNIT_MISMATCH_STEPPING 0x0010 +#define EFI_COMPUTING_UNIT_MISMATCH_CACHE_SIZE 0x0020 +#define EFI_COMPUTING_UNIT_MISMATCH_OEM1 0x1000 +#define EFI_COMPUTING_UNIT_MISMATCH_OEM2 0x2000 +#define EFI_COMPUTING_UNIT_MISMATCH_OEM3 0x4000 +#define EFI_COMPUTING_UNIT_MISMATCH_OEM4 0x8000 + +/// +/// Thermal Extended Error Data +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_EXP_BASE10_DATA Temperature; + EFI_EXP_BASE10_DATA Threshold; +} EFI_COMPUTING_UNIT_THERMAL_ERROR_DATA; + +/// +/// Processor Disabled Extended Error Data +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + UINT32 Cause; + BOOLEAN SoftwareDisabled; +} EFI_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA; + +typedef enum { + EfiInitCacheDataOnly, + EfiInitCacheInstrOnly, + EfiInitCacheBoth, + EfiInitCacheUnspecified +} EFI_INIT_CACHE_TYPE; + +/// +/// Embedded cache init extended data +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + UINT32 Level; + EFI_INIT_CACHE_TYPE Type; +} EFI_CACHE_INIT_DATA; + +// +// Memory Extended Error Data +// + +/// +/// Memory Error Granularity Definition +/// +typedef UINT8 EFI_MEMORY_ERROR_GRANULARITY; + +/// +/// Memory Error Operation Definition +/// +typedef UINT8 EFI_MEMORY_ERROR_OPERATION; + +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_MEMORY_ERROR_GRANULARITY Granularity; + EFI_MEMORY_ERROR_OPERATION Operation; + UINTN Syndrome; + EFI_PHYSICAL_ADDRESS Address; + UINTN Resolution; +} EFI_MEMORY_EXTENDED_ERROR_DATA; + +// +// Memory Error Granularities +// +#define EFI_MEMORY_ERROR_OTHER 0x01 +#define EFI_MEMORY_ERROR_UNKNOWN 0x02 +#define EFI_MEMORY_ERROR_DEVICE 0x03 +#define EFI_MEMORY_ERROR_PARTITION 0x04 + +// +// Memory Error Operations +// +#define EFI_MEMORY_OPERATION_OTHER 0x01 +#define EFI_MEMORY_OPERATION_UNKNOWN 0x02 +#define EFI_MEMORY_OPERATION_READ 0x03 +#define EFI_MEMORY_OPERATION_WRITE 0x04 +#define EFI_MEMORY_OPERATION_PARTIAL_WRITE 0x05 + +// +// Define shorthands to describe Group Operations +// Many memory init operations are essentially group +// operations. + +/// A shorthand to describe that the operation is performed +/// on multiple devices within the array +/// +#define EFI_MULTIPLE_MEMORY_DEVICE_OPERATION 0xfffe +/// +/// A shorthand to describe that the operation is performed on all devices within the array +/// +#define EFI_ALL_MEMORY_DEVICE_OPERATION 0xffff +/// +/// A shorthand to describe that the operation is performed on multiple arrays +/// +#define EFI_MULTIPLE_MEMORY_ARRAY_OPERATION 0xfffe +/// +/// A shorthand to describe that the operation is performed on all the arrays +/// +#define EFI_ALL_MEMORY_ARRAY_OPERATION 0xffff + +// +// DIMM number +// +#pragma pack(1) +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + UINT16 Array; + UINT16 Device; +} EFI_STATUS_CODE_DIMM_NUMBER; +#pragma pack() + +/// +/// Memory Module Mismatch Extended Error Data +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_STATUS_CODE_DIMM_NUMBER Instance; +} EFI_MEMORY_MODULE_MISMATCH_ERROR_DATA; + +/// +/// Memory Range Extended Data +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_PHYSICAL_ADDRESS Start; + EFI_PHYSICAL_ADDRESS Length; +} EFI_MEMORY_RANGE_EXTENDED_DATA; + +/// +/// Device handle Extended Data. Used for many +/// errors and progress codes to point to the device. +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_HANDLE Handle; +} EFI_DEVICE_HANDLE_EXTENDED_DATA; + +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + UINT8 *DevicePath; +} EFI_DEVICE_PATH_EXTENDED_DATA; + +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_HANDLE ControllerHandle; + EFI_HANDLE DriverBindingHandle; + UINT16 DevicePathSize; + UINT8 *RemainingDevicePath; +} EFI_STATUS_CODE_START_EXTENDED_DATA; + +/// +/// Resource Allocation Failure Extended Error Data +/// + +/* +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINT32 Bar; + VOID *ReqRes; + VOID *AllocRes; +} EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA; +*/ +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + UINT32 Bar; + UINT16 DevicePathSize; + UINT16 ReqResSize; + UINT16 AllocResSize; + UINT8 *DevicePath; + UINT8 *ReqRes; + UINT8 *AllocRes; +} EFI_RESOURCE_ALLOC_FAILURE_ERROR_DATA; + +/// +/// Extended Error Data for Assert +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + UINT32 LineNumber; + UINT32 FileNameSize; + EFI_STATUS_CODE_STRING_DATA *FileName; +} EFI_DEBUG_ASSERT_DATA; + +/// +/// System Context Data EBC/IA32/IPF +/// +typedef union { + EFI_SYSTEM_CONTEXT_EBC SystemContextEbc; + EFI_SYSTEM_CONTEXT_IA32 SystemContextIa32; + EFI_SYSTEM_CONTEXT_IPF SystemContextIpf; +} EFI_STATUS_CODE_EXCEP_SYSTEM_CONTEXT; + +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_STATUS_CODE_EXCEP_SYSTEM_CONTEXT Context; +} EFI_STATUS_CODE_EXCEP_EXTENDED_DATA; + +/// +/// Legacy Oprom extended data +/// +typedef struct { + EFI_STATUS_CODE_DATA DataHeader; + EFI_HANDLE DeviceHandle; + EFI_PHYSICAL_ADDRESS RomImageBase; +} EFI_LEGACY_OPROM_EXTENDED_DATA; + +#endif diff --git a/MdePkg/Include/Common/UefiBaseTypes.h b/MdePkg/Include/Common/UefiBaseTypes.h new file mode 100644 index 0000000000..4954c10bf2 --- /dev/null +++ b/MdePkg/Include/Common/UefiBaseTypes.h @@ -0,0 +1,85 @@ +/** @file + This file makes the BaseTypes.h backward compatible with the ones used in the + past for EFI and Tiano development. It's mostly just prepending an EFI_ on the + definitions. + + Copyright (c) 2006, 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. + + Module Name: UefiBaseTypes.h + +**/ + +#ifndef __UEFI_BASE_TYPES_H__ +#define __UEFI_BASE_TYPES_H__ + +#include + +typedef UINT64 EFI_LBA; + +#define EFIERR(_a) ENCODE_ERROR(_a) + +#define EFI_MAX_BIT MAX_BIT +#define EFI_MAX_ADDRESS MAX_ADDRESS +#define EFI_BREAKPOINT() CpuBreakpoint () +#define EFI_DEADLOOP() CpuDeadLoop () +#define EFI_ERROR(A) RETURN_ERROR(A) + +typedef GUID EFI_GUID; +typedef RETURN_STATUS EFI_STATUS; + +#define EFI_SUCCESS RETURN_SUCCESS +#define EFI_LOAD_ERROR RETURN_LOAD_ERROR +#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER +#define EFI_UNSUPPORTED RETURN_UNSUPPORTED +#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE +#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL +#define EFI_NOT_READY RETURN_NOT_READY +#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR +#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED +#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES +#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED +#define EFI_VOLUME_FULL RETURN_VOLUME_FULL +#define EFI_NO_MEDIA RETURN_NO_MEDIA +#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED +#define EFI_NOT_FOUND RETURN_NOT_FOUND +#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED +#define EFI_NO_RESPONSE RETURN_NO_RESPONSE +#define EFI_NO_MAPPING RETURN_NO_MAPPING +#define EFI_TIMEOUT RETURN_TIMEOUT +#define EFI_NOT_STARTED RETURN_NOT_STARTED +#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED +#define EFI_ABORTED RETURN_ABORTED +#define EFI_ICMP_ERROR RETURN_ICMP_ERROR +#define EFI_TFTP_ERROR RETURN_TFTP_ERROR +#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR +#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION +#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION +#define EFI_CRC_ERROR RETURN_CRC_ERROR +#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA +#define EFI_END_OF_FILE RETURN_END_OF_FILE + +#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH +#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE +#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE +#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL + +// +// The EFI memory allocation functions work in units of EFI_PAGEs that are +// 4K. This should in no way be confused with the page size of the processor. +// An EFI_PAGE is just the quanta of memory in EFI. +// +#define EFI_PAGE_MASK 0xFFF +#define EFI_PAGE_SHIFT 12 + +#define EFI_SIZE_TO_PAGES(a) (((a) >> EFI_PAGE_SHIFT) + (((a) & EFI_PAGE_MASK) ? 1 : 0)) + +#define EFI_PAGES_TO_SIZE(a) ( (a) << EFI_PAGE_SHIFT) + +#endif diff --git a/MdePkg/Include/Dxe.h b/MdePkg/Include/Dxe.h new file mode 100644 index 0000000000..020c51e5fa --- /dev/null +++ b/MdePkg/Include/Dxe.h @@ -0,0 +1,51 @@ +/** @file + + Root include file for Mde Package DXE modules + + DXE modules follow the public Framework specifications and the UEFI + specifiations. The build infrastructure must set + EFI_SPECIFICATION_VERSION before including this file. To support + R9/UEFI2.0 set EFI_SPECIFIATION_VERSION to 0x00020000. To support + R8.5/EFI 1.10 set EFI_SPECIFIATION_VERSION to 0x00010010. + EDK_RELEASE_VERSION must be set to a non zero value. + EFI_SPECIFIATION_VERSION and EDK_RELEASE_VERSION are set automatically + by the build infrastructure for every module. + + +Copyright (c) 2006, 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 __DXE_H__ +#define __DXE_H__ + +// +// Check to make sure EFI_SPECIFICATION_VERSION and EDK_RELEASE_VERSION are defined. +// +#if !defined(EFI_SPECIFICATION_VERSION) + #error EFI_SPECIFICATION_VERSION not defined +#elif !defined(EDK_RELEASE_VERSION) + #error EDK_RELEASE_VERSION not defined +#elif (EDK_RELEASE_VERSION == 0) + #error EDK_RELEASE_VERSION can not be zero +#endif + + +#include +#include +#include + +#include +#include + +#include +#include //This will be removed when PCD PEIM is completed! + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/Bds.h b/MdePkg/Include/Dxe/ArchProtocol/Bds.h new file mode 100644 index 0000000000..f6b72d2b00 --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/Bds.h @@ -0,0 +1,87 @@ +/** @file + Boot Device Selection Architectural Protocol as defined in DXE CIS + + When the DXE core is done it calls the BDS via this protocol. + + Copyright (c) 2006, 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. + + Module Name: Bds.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_BDS_H__ +#define __ARCH_PROTOCOL_BDS_H__ + +// +// Global ID for the BDS Architectural Protocol +// +#define EFI_BDS_ARCH_PROTOCOL_GUID \ + { 0x665E3FF6, 0x46CC, 0x11d4, {0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } } + +// +// Declare forward reference for the BDS Architectural Protocol +// +typedef struct _EFI_BDS_ARCH_PROTOCOL EFI_BDS_ARCH_PROTOCOL; + +/** + This function uses policy data from the platform to determine what operating + system or system utility should be loaded and invoked. This function call + also optionally make the use of user input to determine the operating system + or system utility to be loaded and invoked. When the DXE Core has dispatched + all the drivers on the dispatch queue, this function is called. This + function will attempt to connect the boot devices required to load and invoke + the selected operating system or system utility. During this process, + additional firmware volumes may be discovered that may contain addition DXE + drivers that can be dispatched by the DXE Core. If a boot device cannot be + fully connected, this function calls the DXE Service Dispatch() to allow the + DXE drivers from any newly discovered firmware volumes to be dispatched. + Then the boot device connection can be attempted again. If the same boot + device connection operation fails twice in a row, then that boot device has + failed, and should be skipped. This function should never return. + + @param This The EFI_BDS_ARCH_PROTOCOL instance. + + @return None. + +**/ +typedef +VOID +(EFIAPI *EFI_BDS_ENTRY) ( + IN EFI_BDS_ARCH_PROTOCOL *This + ); + +/** + Interface stucture for the BDS Architectural Protocol. + + @par Protocol Description: + The EFI_BDS_ARCH_PROTOCOL transfers control from DXE to an operating + system or a system utility. If there are not enough drivers initialized + when this protocol is used to access the required boot device(s), then + this protocol should add drivers to the dispatch queue and return control + back to the dispatcher. Once the required boot devices are available, then + the boot device can be used to load and invoke an OS or a system utility. + + @par Protocol Parameters: + Entry - The entry point to BDS. This call does not take any parameters, + and the return value can be ignored. If it returns, then the + dispatcher must be invoked again, if it never returns, then an + operating system or a system utility have been invoked. + +**/ +struct _EFI_BDS_ARCH_PROTOCOL { + EFI_BDS_ENTRY Entry; +}; + +extern EFI_GUID gEfiBdsArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/Cpu.h b/MdePkg/Include/Dxe/ArchProtocol/Cpu.h new file mode 100644 index 0000000000..975a816356 --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/Cpu.h @@ -0,0 +1,326 @@ +/** @file + CPU Architectural Protocol as defined in DXE CIS + + This code abstracts the DXE core from processor implementation details. + + Copyright (c) 2006, 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. + + Module Name: Cpu.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_CPU_H__ +#define __ARCH_PROTOCOL_CPU_H__ + + +#define EFI_CPU_ARCH_PROTOCOL_GUID \ + { 0x26baccb1, 0x6f42, 0x11d4, {0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +typedef struct _EFI_CPU_ARCH_PROTOCOL EFI_CPU_ARCH_PROTOCOL; + +typedef enum { + EfiCpuFlushTypeWriteBackInvalidate, + EfiCpuFlushTypeWriteBack, + EfiCpuFlushTypeInvalidate, + EfiCpuMaxFlushType +} EFI_CPU_FLUSH_TYPE; + +typedef enum { + EfiCpuInit, + EfiCpuMaxInitType +} EFI_CPU_INIT_TYPE; + +/** + EFI_CPU_INTERRUPT_HANDLER that is called when a processor interrupt occurs. + + @param InterruptType Defines the type of interrupt or exception that + occurred on the processor.This parameter is processor architecture specific. + + @param SystemContext A pointer to the processor context when + the interrupt occurred on the processor. + + @return None + +**/ +typedef +VOID +(*EFI_CPU_INTERRUPT_HANDLER) ( + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_SYSTEM_CONTEXT SystemContext + ); + +/** + This function flushes the range of addresses from Start to Start+Length + from the processor's data cache. If Start is not aligned to a cache line + boundary, then the bytes before Start to the preceding cache line boundary + are also flushed. If Start+Length is not aligned to a cache line boundary, + then the bytes past Start+Length to the end of the next cache line boundary + are also flushed. The FlushType of EfiCpuFlushTypeWriteBackInvalidate must be + supported. If the data cache is fully coherent with all DMA operations, then + this function can just return EFI_SUCCESS. If the processor does not support + flushing a range of the data cache, then the entire data cache can be flushed. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param Start The beginning physical address to flush from the processor's data + cache. + @param Length The number of bytes to flush from the processor's data cache. This + function may flush more bytes than Length specifies depending upon + the granularity of the flush operation that the processor supports. + @param FlushType Specifies the type of flush operation to perform. + + @retval EFI_SUCCESS The address range from Start to Start+Length was flushed from + the processor's data cache. + @retval EFI_UNSUPPORTEDT The processor does not support the cache flush type specified + by FlushType. + @retval EFI_DEVICE_ERROR The address range from Start to Start+Length could not be flushed + from the processor's data cache. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_FLUSH_DATA_CACHE) ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length, + IN EFI_CPU_FLUSH_TYPE FlushType + ); + + +/** + This function enables interrupt processing by the processor. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS Interrupts are enabled on the processor. + @retval EFI_DEVICE_ERROR Interrupts could not be enabled on the processor. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_ENABLE_INTERRUPT) ( + IN EFI_CPU_ARCH_PROTOCOL *This + ); + + +/** + This function disables interrupt processing by the processor. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS Interrupts are disabled on the processor. + @retval EFI_DEVICE_ERROR Interrupts could not be disabled on the processor. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_DISABLE_INTERRUPT) ( + IN EFI_CPU_ARCH_PROTOCOL *This + ); + + +/** + This function retrieves the processor's current interrupt state a returns it in + State. If interrupts are currently enabled, then TRUE is returned. If interrupts + are currently disabled, then FALSE is returned. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param State A pointer to the processor's current interrupt state. Set to TRUE if + interrupts are enabled and FALSE if interrupts are disabled. + + @retval EFI_SUCCESS The processor's current interrupt state was returned in State. + @retval EFI_INVALID_PARAMETER State is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_GET_INTERRUPT_STATE) ( + IN EFI_CPU_ARCH_PROTOCOL *This, + OUT BOOLEAN *State + ); + + +/** + This function generates an INIT on the processor. If this function succeeds, then the + processor will be reset, and control will not be returned to the caller. If InitType is + not supported by this processor, or the processor cannot programmatically generate an + INIT without help from external hardware, then EFI_UNSUPPORTED is returned. If an error + occurs attempting to generate an INIT, then EFI_DEVICE_ERROR is returned. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param InitType The type of processor INIT to perform. + + @retval EFI_SUCCESS The processor INIT was performed. This return code should never be seen. + @retval EFI_UNSUPPORTED The processor INIT operation specified by InitType is not supported + by this processor. + @retval EFI_DEVICE_ERROR The processor INIT failed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_INIT) ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_CPU_INIT_TYPE InitType + ); + + +/** + This function registers and enables the handler specified by InterruptHandler for a processor + interrupt or exception type specified by InterruptType. If InterruptHandler is NULL, then the + handler for the processor interrupt or exception type specified by InterruptType is uninstalled. + The installed handler is called once for each processor interrupt or exception. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param InterruptType A pointer to the processor's current interrupt state. Set to TRUE if interrupts + are enabled and FALSE if interrupts are disabled. + @param InterruptHandler A pointer to a function of type EFI_CPU_INTERRUPT_HANDLER that is called + when a processor interrupt occurs. If this parameter is NULL, then the handler + will be uninstalled. + + @retval EFI_SUCCESS The handler for the processor interrupt was successfully installed or uninstalled. + @retval EFI_ALREADY_STARTED InterruptHandler is not NULL, and a handler for InterruptType was + previously installed. + @retval EFI_INVALID_PARAMETER InterruptHandler is NULL, and a handler for InterruptType was not + previously installed. + @retval EFI_UNSUPPORTED The interrupt specified by InterruptType is not supported. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_REGISTER_INTERRUPT_HANDLER) ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_EXCEPTION_TYPE InterruptType, + IN EFI_CPU_INTERRUPT_HANDLER InterruptHandler + ); + + +/** + This function reads the processor timer specified by TimerIndex and returns it in TimerValue. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param TimerIndex Specifies which processor timer is to be returned in TimerValue. This parameter + must be between 0 and NumberOfTimers-1. + @param TimerValue Pointer to the returned timer value. + @param TimerPeriod A pointer to the amount of time that passes in femtoseconds for each increment + of TimerValue. + + @retval EFI_SUCCESS The processor timer value specified by TimerIndex was returned in TimerValue. + @retval EFI_DEVICE_ERROR An error occurred attempting to read one of the processor's timers. + @retval EFI_INVALID_PARAMETER TimerValue is NULL or TimerIndex is not valid. + @retval EFI_UNSUPPORTED The processor does not have any readable timers. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_GET_TIMER_VALUE) ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN UINT32 TimerIndex, + OUT UINT64 *TimerValue, + OUT UINT64 *TimerPeriod OPTIONAL + ); + + +/** + This function modifies the attributes for the memory region specified by BaseAddress and + Length from their current attributes to the attributes specified by Attributes. + + @param This The EFI_CPU_ARCH_PROTOCOL instance. + @param BaseAddress The physical address that is the start address of a memory region. + @param Length The size in bytes of the memory region. + @param Attributes The bit mask of attributes to set for the memory region. + + @retval EFI_SUCCESS The attributes were set for the memory region. + @retval EFI_ACCESS_DENIED The attributes for the memory resource range specified by + BaseAddress and Length cannot be modified. + @retval EFI_INVALID_PARAMETER Length is zero. + @retval EFI_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of + the memory resource range. + @retval EFI_UNSUPPORTED The processor does not support one or more bytes of the memory + resource range specified by BaseAddress and Length. + The bit mask of attributes is not support for the memory resource + range specified by BaseAddress and Length. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_SET_MEMORY_ATTRIBUTES) ( + IN EFI_CPU_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ); + + +/** + @par Protocol Description: + The EFI_CPU_ARCH_PROTOCOL is used to abstract processor-specific functions from the DXE + Foundation. This includes flushing caches, enabling and disabling interrupts, hooking interrupt + vectors and exception vectors, reading internal processor timers, resetting the processor, and + determining the processor frequency. + + @param FlushDataCache + Flushes a range of the processor's data cache. If the processor does + not contain a data cache, or the data cache is fully coherent, then this + function can just return EFI_SUCCESS. If the processor does not support + flushing a range of addresses from the data cache, then the entire data + cache must be flushed. + + @param EnableInterrupt Enables interrupt processing by the processor. + + @param DisableInterrupt Disables interrupt processing by the processor. + + @param GetInterruptState Retrieves the processor's current interrupt state. + + @param Init + Generates an INIT on the processor. If a processor cannot programmatically + generate an INIT without help from external hardware, then this function + returns EFI_UNSUPPORTED. + + @param RegisterInterruptHandler + Associates an interrupt service routine with one of the processor's interrupt + vectors. This function is typically used by the EFI_TIMER_ARCH_PROTOCOL to + hook the timer interrupt in a system. It can also be used by the debugger to + hook exception vectors. + + @param GetTimerValue Returns the value of one of the processor's internal timers. + + @param SetMemoryAttributes Attempts to set the attributes of a memory region. + + @param NumberOfTimers + The number of timers that are available in a processor. The value in this + field is a constant that must not be modified after the CPU Architectural + Protocol is installed. All consumers must treat this as a read-only field. + + @param DmaBufferAlignment + The size, in bytes, of the alignment required for DMA buffer allocations. + This is typically the size of the largest data cache line in the platform. + The value in this field is a constant that must not be modified after the + CPU Architectural Protocol is installed. All consumers must treat this as + a read-only field. + +**/ +struct _EFI_CPU_ARCH_PROTOCOL { + EFI_CPU_FLUSH_DATA_CACHE FlushDataCache; + EFI_CPU_ENABLE_INTERRUPT EnableInterrupt; + EFI_CPU_DISABLE_INTERRUPT DisableInterrupt; + EFI_CPU_GET_INTERRUPT_STATE GetInterruptState; + EFI_CPU_INIT Init; + EFI_CPU_REGISTER_INTERRUPT_HANDLER RegisterInterruptHandler; + EFI_CPU_GET_TIMER_VALUE GetTimerValue; + EFI_CPU_SET_MEMORY_ATTRIBUTES SetMemoryAttributes; + UINT32 NumberOfTimers; + UINT32 DmaBufferAlignment; +}; + +extern EFI_GUID gEfiCpuArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/Metronome.h b/MdePkg/Include/Dxe/ArchProtocol/Metronome.h new file mode 100644 index 0000000000..a07003e5cc --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/Metronome.h @@ -0,0 +1,100 @@ +/** @file + Metronome Architectural Protocol as defined in DXE CIS + + This code abstracts the DXE core to provide delay services. + + Copyright (c) 2006, 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. + + Module Name: Metronome.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_METRONOME_H__ +#define __ARCH_PROTOCOL_METRONOME_H__ + +// +// Global ID for the Metronome Architectural Protocol +// +#define EFI_METRONOME_ARCH_PROTOCOL_GUID \ + { 0x26baccb2, 0x6f42, 0x11d4, {0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +// +// Declare forward reference for the Metronome Architectural Protocol +// +typedef struct _EFI_METRONOME_ARCH_PROTOCOL EFI_METRONOME_ARCH_PROTOCOL; + +/** + The WaitForTick() function waits for the number of ticks specified by + TickNumber from a known time source in the platform. If TickNumber of + ticks are detected, then EFI_SUCCESS is returned. The actual time passed + between entry of this function and the first tick is between 0 and + TickPeriod 100 nS units. If you want to guarantee that at least TickPeriod + time has elapsed, wait for two ticks. This function waits for a hardware + event to determine when a tick occurs. It is possible for interrupt + processing, or exception processing to interrupt the execution of the + WaitForTick() function. Depending on the hardware source for the ticks, it + is possible for a tick to be missed. This function cannot guarantee that + ticks will not be missed. If a timeout occurs waiting for the specified + number of ticks, then EFI_TIMEOUT is returned. + + @param This The EFI_METRONOME_ARCH_PROTOCOL instance. + + @param TickNumber Number of ticks to wait. + + @retval EFI_SUCCESS The wait for the number of ticks specified by TickNumber + succeeded. + + @retval EFI_TIMEOUT A timeout occurred waiting for the specified number of ticks. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_METRONOME_WAIT_FOR_TICK) ( + IN EFI_METRONOME_ARCH_PROTOCOL *This, + IN UINT32 TickNumber + ); + +// +// + +/** + Interface stucture for the Metronome Architectural Protocol. + + @par Protocol Description: + This protocol provides access to a known time source in the platform to the + core. The core uses this known time source to produce core services that + require calibrated delays. + + @param WaitForTick + Waits for a specified number of ticks from a known time source + in the platform. The actual time passed between entry of this + function and the first tick is between 0 and TickPeriod 100 nS + units. If you want to guarantee that at least TickPeriod time + has elapsed, wait for two ticks. + + @param TickPeriod + The period of platform's known time source in 100 nS units. + This value on any platform must be at least 10 uS, and must not + exceed 200 uS. The value in this field is a constant that must + not be modified after the Metronome architectural protocol is + installed. All consumers must treat this as a read-only field. + +**/ +struct _EFI_METRONOME_ARCH_PROTOCOL { + EFI_METRONOME_WAIT_FOR_TICK WaitForTick; + UINT32 TickPeriod; +}; + +extern EFI_GUID gEfiMetronomeArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/MonotonicCounter.h b/MdePkg/Include/Dxe/ArchProtocol/MonotonicCounter.h new file mode 100644 index 0000000000..d25374074d --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/MonotonicCounter.h @@ -0,0 +1,33 @@ +/** @file + Monotonic Counter Architectural Protocol as defined in DXE CIS + + This code provides the services required to access the systems monotonic counter + + Copyright (c) 2006, 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. + + Module Name: MonotonicCounter.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_MONTONIC_COUNTER_H__ +#define __ARCH_PROTOCOL_MONTONIC_COUNTER_H__ + +/// +/// Global ID for the Monotonic Counter Architectural Protocol +/// +#define EFI_MONTONIC_COUNTER_ARCH_PROTOCOL_GUID \ + {0x1da97072, 0xbddc, 0x4b30, {0x99, 0xf1, 0x72, 0xa0, 0xb5, 0x6f, 0xff, 0x2a} } + +extern EFI_GUID gEfiMonotonicCounterArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/RealTimeClock.h b/MdePkg/Include/Dxe/ArchProtocol/RealTimeClock.h new file mode 100644 index 0000000000..dc968e1666 --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/RealTimeClock.h @@ -0,0 +1,41 @@ +/** @file + Real Time clock Architectural Protocol as defined in DXE CIS + + This code abstracts time and data functions. Used to provide + Time and date related EFI runtime services. + + The GetTime (), SetTime (), GetWakeupTime (), and SetWakeupTime () EFI 1.0 + services are added to the EFI system table and the + EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL_GUID protocol is registered with a NULL + pointer. + + No CRC of the EFI system table is required, as it is done in the DXE core. + + Copyright (c) 2006, 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. + + Module Name: RealTimeClock.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_REAL_TIME_CLOCK_H__ +#define __ARCH_PROTOCOL_REAL_TIME_CLOCK_H__ + +// +// Global ID for the Real Time Clock Architectural Protocol +// +#define EFI_REAL_TIME_CLOCK_ARCH_PROTOCOL_GUID \ + { 0x27CFAC87, 0x46CC, 0x11d4, {0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } } + +extern EFI_GUID gEfiRealTimeClockArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/Reset.h b/MdePkg/Include/Dxe/ArchProtocol/Reset.h new file mode 100644 index 0000000000..80befae95f --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/Reset.h @@ -0,0 +1,38 @@ +/** @file + Reset Architectural Protocol as defined in the DXE CIS + + Used to provide ResetSystem runtime services + + The ResetSystem () EFI 1.0 service is added to the EFI system table and the + EFI_RESET_ARCH_PROTOCOL_GUID protocol is registered with a NULL pointer. + + No CRC of the EFI system table is required, as it is done in the DXE core. + + Copyright (c) 2006, 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. + + Module Name: Reset.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_RESET_H__ +#define __ARCH_PROTOCOL_RESET_H__ + +// +// Global ID for the Reset Architectural Protocol +// +#define EFI_RESET_ARCH_PROTOCOL_GUID \ + { 0x27CFAC88, 0x46CC, 0x11d4, {0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } } + +extern EFI_GUID gEfiResetArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/Runtime.h b/MdePkg/Include/Dxe/ArchProtocol/Runtime.h new file mode 100644 index 0000000000..bbd4c1a699 --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/Runtime.h @@ -0,0 +1,162 @@ +/** @file + Runtime Architectural Protocol as defined in DXE CIS + + This code is used to produce the EFI 1.0 runtime virtual switch over + + This driver must add SetVirtualAddressMap () and ConvertPointer () to + the EFI system table. This driver is not responcible for CRCing the + EFI system table. + + This driver will add EFI_RUNTIME_ARCH_PROTOCOL_GUID protocol with a + pointer to the Runtime Arch Protocol instance structure. The protocol + member functions are used by the DXE core to export information need + by this driver to produce the runtime transition to virtual mode + calling. + + Copyright (c) 2006, 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. + + Module Name: Runtime.h + + @par Revision Reference: + Version 0.90. + +**/ + +#ifndef __ARCH_PROTOCOL_RUNTIME_H__ +#define __ARCH_PROTOCOL_RUNTIME_H__ + +// +// Global ID for the Runtime Architectural Protocol +// +#define EFI_RUNTIME_ARCH_PROTOCOL_GUID \ + { 0x96d08253, 0x8483, 0x11d4, {0xbc, 0xf1, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +typedef struct _EFI_RUNTIME_ARCH_PROTOCOL EFI_RUNTIME_ARCH_PROTOCOL; + +/** + When a SetVirtualAddressMap() is performed all the runtime images loaded by + DXE must be fixed up with the new virtual address map. To facilitate this the + Runtime Architectural Protocol needs to be informed of every runtime driver + that is registered. All the runtime images loaded by DXE should be registered + with this service by the DXE Core when ExitBootServices() is called. The + images that are registered with this service must have successfully been + loaded into memory with the Boot Service LoadImage(). As a result, no + parameter checking needs to be performed. + + @param This The EFI_RUNTIME_ARCH_PROTOCOL instance. + + @param ImageBase Start of image that has been loaded in memory. It is either + a pointer to the DOS or PE header of the image. + + @param ImageSize Size of the image in bytes. + + @param RelocationData Information about the fixups that were performed on ImageBase + when it was loaded into memory. This information is needed + when the virtual mode fix-ups are reapplied so that data that + has been programmatically updated will not be fixed up. If + code updates a global variable the code is responsible for + fixing up the variable for virtual mode. + + @retval EFI_SUCCESS The ImageBase has been registered. + + @retval EFI_OUT_OF_RESOURCES There are not enough resources to register ImageBase. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_RUNTIME_REGISTER_IMAGE) ( + IN EFI_RUNTIME_ARCH_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS ImageBase, + IN UINTN ImageSize, + IN VOID *RelocationData + ); + + +/** + This function is used to support the required runtime events. Currently only + runtime events of type EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE needs to be + registered with this service. All the runtime events that exist in the DXE + Core should be registered with this service when ExitBootServices() is called. + All the events that are registered with this service must have been created + with the Boot Service CreateEvent(). As a result, no parameter checking needs + to be performed. + + @param This The EFI_RUNTIME_ARCH_PROTOCOL instance. + + @param Type The same as Type passed into CreateEvent(). + + @param NotifyTpl The same as NotifyTpl passed into CreateEvent(). + + @param NotifyFunction The same as NotifyFunction passed into CreateEvent(). + + @param NotifyContext The same as NotifyContext passed into CreateEvent(). + + @param Event The EFI_EVENT returned by CreateEvent(). Event must be in + runtime memory. + + @retval EFI_SUCCESS The Event has been registered. + + @retval EFI_OUT_OF_RESOURCES There are not enough resources to register Event. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_RUNTIME_REGISTER_EVENT) ( + IN EFI_RUNTIME_ARCH_PROTOCOL *This, + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + IN EFI_EVENT *Event + ); + +// +// Interface stucture for the Runtime Architectural Protocol +// +/** + @par Protocol Description: + The DXE driver that produces this protocol must be a runtime driver. This + driver is responsible for initializing the SetVirtualAddressMap() and + ConvertPointer() fields of the EFI Runtime Services Table and the + CalculateCrc32() field of the EFI Boot Services Table. See the Runtime + Services chapter and the Boot Services chapter for details on these services. + After the two fields of the EFI Runtime Services Table and the one field of + the EFI Boot Services Table have been initialized, the driver must install + the EFI_RUNTIME_ARCH_PROTOCOL_GUID on a new handle with an EFI_RUNTIME_ARCH_ + PROTOCOL interface pointer. The installation of this protocol informs the + DXE core that the virtual memory services and the 32-bit CRC services are + now available, and the DXE core must update the 32-bit CRC of the EFI Runtime + Services Table and the 32-bit CRC of the EFI Boot Services Table. + + All runtime core services are provided by the EFI_RUNTIME_ARCH_PROTOCOL. + This includes the support for registering runtime images that must be + re-fixed up when a transition is made from physical mode to virtual mode. + This protocol also supports all events that are defined to fire at runtime. + This protocol also contains a CRC-32 function that will be used by the DXE + core as a boot service. The EFI_RUNTIME_ARCH_PROTOCOL needs the CRC-32 + function when a transition is made from physical mode to virtual mode and + the EFI System Table and EFI Runtime Table are fixed up with virtual pointers. + + @param RegisterRuntimeImage + Register a runtime image so it can be converted to virtual mode if the EFI Runtime Services + SetVirtualAddressMap() is called. + + @param RegisterRuntimeEvent + Register an event than needs to be notified at runtime. + +**/ +struct _EFI_RUNTIME_ARCH_PROTOCOL { + EFI_RUNTIME_REGISTER_IMAGE RegisterImage; + EFI_RUNTIME_REGISTER_EVENT RegisterEvent; +}; + +extern EFI_GUID gEfiRuntimeArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/Security.h b/MdePkg/Include/Dxe/ArchProtocol/Security.h new file mode 100644 index 0000000000..3598199b84 --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/Security.h @@ -0,0 +1,136 @@ +/** @file + Security Architectural Protocol as defined in the DXE CIS + + Used to provide Security services. Specifically, dependening upon the + authentication state of a discovered driver in a Firmware Volume, the + portable DXE Core Dispatcher will call into the Security Architectural + Protocol (SAP) with the authentication state of the driver. + + This call-out allows for OEM-specific policy decisions to be made, such + as event logging for attested boots, locking flash in response to discovering + an unsigned driver or failed signature check, or other exception response. + + The SAP can also change system behavior by having the DXE core put a driver + in the Schedule-On-Request (SOR) state. This will allow for later disposition + of the driver by platform agent, such as Platform BDS. + + Copyright (c) 2006, 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. + + Module Name: Security.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_SECURITY_H__ +#define __ARCH_PROTOCOL_SECURITY_H__ + +// +// Global ID for the Security Code Architectural Protocol +// +#define EFI_SECURITY_ARCH_PROTOCOL_GUID \ + { 0xA46423E3, 0x4617, 0x49f1, {0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 } } + +typedef struct _EFI_SECURITY_ARCH_PROTOCOL EFI_SECURITY_ARCH_PROTOCOL; + +/** + The EFI_SECURITY_ARCH_PROTOCOL (SAP) is used to abstract platform-specific + policy from the DXE core response to an attempt to use a file that returns a + given status for the authentication check from the section extraction protocol. + + The possible responses in a given SAP implementation may include locking + flash upon failure to authenticate, attestation logging for all signed drivers, + and other exception operations. The File parameter allows for possible logging + within the SAP of the driver. + + If File is NULL, then EFI_INVALID_PARAMETER is returned. + + If the file specified by File with an authentication status specified by + AuthenticationStatus is safe for the DXE Core to use, then EFI_SUCCESS is returned. + + If the file specified by File with an authentication status specified by + AuthenticationStatus is not safe for the DXE Core to use under any circumstances, + then EFI_ACCESS_DENIED is returned. + + If the file specified by File with an authentication status specified by + AuthenticationStatus is not safe for the DXE Core to use right now, but it + might be possible to use it at a future time, then EFI_SECURITY_VIOLATION is + returned. + + @param This The EFI_SECURITY_ARCH_PROTOCOL instance. + + @param AuthenticationStatus This is the authentication type returned from the Section + Extraction protocol. See the Section Extraction Protocol + Specification for details on this type. + + @param File This is a pointer to the device path of the file that is + being dispatched. This will optionally be used for logging. + + @retval EFI_SUCCESS The file specified by File did authenticate, and the + platform policy dictates that the DXE Core may use File. + + @retval EFI_INVALID_PARAMETER Driver is NULL. + + @retval EFI_SECURITY_VIOLATION The file specified by File did not authenticate, and + the platform policy dictates that File should be placed + in the untrusted state. A file may be promoted from + the untrusted to the trusted state at a future time + with a call to the Trust() DXE Service. + + @retval EFI_ACCESS_DENIED The file specified by File did not authenticate, and + the platform policy dictates that File should not be + used for any purpose. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SECURITY_FILE_AUTHENTICATION_STATE) ( + IN EFI_SECURITY_ARCH_PROTOCOL *This, + IN UINT32 AuthenticationStatus, + IN EFI_DEVICE_PATH_PROTOCOL *File + ) +; + +// +// Interface stucture for the Timer Architectural Protocol +// +/** + @par Protocol Description: + + The EFI_SECURITY_ARCH_PROTOCOL is used to abstract platform-specific policy + from the DXE core. This includes locking flash upon failure to authenticate, + attestation logging, and other exception operations. + + The driver that produces the EFI_SECURITY_ARCH_PROTOCOL may also optionally + install the EFI_SECURITY_POLICY_PROTOCOL_GUID onto a new handle with a NULL + interface. The existence of this GUID in the protocol database means that + the GUIDed Section Extraction Protocol should authenticate the contents of + an Authentication Section. The expectation is that the GUIDed Section + Extraction protocol will look for the existence of the EFI_SECURITY_POLICY_ + PROTOCOL_GUID in the protocol database. If it exists, then the publication + thereof is taken as an injunction to attempt an authentication of any section + wrapped in an Authentication Section. See the Firmware File System + Specification for details on the GUIDed Section Extraction Protocol and + Authentication Sections. + + @par Protocol Parameters: + + FileAuthenticationState - This service is called upon fault with respect to + the authentication of a section of a file. + +**/ +struct _EFI_SECURITY_ARCH_PROTOCOL { + EFI_SECURITY_FILE_AUTHENTICATION_STATE FileAuthenticationState; +}; + +extern EFI_GUID gEfiSecurityArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/SecurityPolicy.h b/MdePkg/Include/Dxe/ArchProtocol/SecurityPolicy.h new file mode 100644 index 0000000000..b46267e10a --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/SecurityPolicy.h @@ -0,0 +1,31 @@ +/** @file + Security Policy protocol as defined in the DXE CIS + + Copyright (c) 2006, 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. + + Module Name: SecurityPolicy.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef _SECURITY_POLICY_H_ +#define _SECURITY_POLICY_H_ + +// +// Security policy protocol GUID definition +// +#define EFI_SECURITY_POLICY_PROTOCOL_GUID \ + {0x78E4D245, 0xCD4D, 0x4a05, {0xA2, 0xBA, 0x47, 0x43, 0xE8, 0x6C, 0xFC, 0xAB} } + +extern EFI_GUID gEfiSecurityPolicyProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/StatusCode.h b/MdePkg/Include/Dxe/ArchProtocol/StatusCode.h new file mode 100644 index 0000000000..6440dc3388 --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/StatusCode.h @@ -0,0 +1,82 @@ +/** @file + Status code Runtime Protocol as defined in the DXE CIS + + The StatusCode () Tiano service is added to the EFI system table and the + EFI_STATUS_CODE_ARCH_PROTOCOL_GUID protocol is registered with a NULL + pointer. + + No CRC of the EFI system table is required, as it is done in the DXE core. + + This code abstracts Status Code reporting. + + Copyright (c) 2006, 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. + + Module Name: StatusCode.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __STATUS_CODE_RUNTIME_PROTOCOL_H__ +#define __STATUS_CODE_RUNTIME_PROTOCOL_H__ + +#define EFI_STATUS_CODE_RUNTIME_PROTOCOL_GUID \ +{ 0xd2b2b828, 0x826, 0x48a7, { 0xb3, 0xdf, 0x98, 0x3c, 0x0, 0x60, 0x24, 0xf0 } } + +/** + Provides an interface that a software module can call to report a status code. + + @param Type Indicates the type of status code being reported. + + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully + + @retval EFI_DEVICE_ERROR The function should not be completed due to a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REPORT_STATUS_CODE) ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/** + @par Protocol Description: + Provides the service required to report a status code to the platform firmware. + This protocol must be produced by a runtime DXE driver and may be consumed + only by the DXE Foundation. + + @param ReportStatusCode Emit a status code. + +**/ +typedef struct _EFI_STATUS_CODE_PROTOCOL { + EFI_REPORT_STATUS_CODE ReportStatusCode; +} EFI_STATUS_CODE_PROTOCOL; + +extern EFI_GUID gEfiStatusCodeRuntimeProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/Timer.h b/MdePkg/Include/Dxe/ArchProtocol/Timer.h new file mode 100644 index 0000000000..330f4cfd68 --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/Timer.h @@ -0,0 +1,222 @@ +/** @file + Timer Architectural Protocol as defined in the DXE CIS + + This code is used to provide the timer tick for the DXE core. + + Copyright (c) 2006, 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. + + Module Name: Timer.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_TIMER_H__ +#define __ARCH_PROTOCOL_TIMER_H__ + +// +// Global ID for the Timer Architectural Protocol +// +#define EFI_TIMER_ARCH_PROTOCOL_GUID \ + { 0x26baccb3, 0x6f42, 0x11d4, {0xbc, 0xe7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +// +// Declare forward reference for the Timer Architectural Protocol +// +typedef struct _EFI_TIMER_ARCH_PROTOCOL EFI_TIMER_ARCH_PROTOCOL; + +/** + This function of this type is called when a timer interrupt fires. This + function executes at TPL_HIGH_LEVEL. The DXE Core will register a funtion + of tyis type to be called for the timer interrupt, so it can know how much + time has passed. This information is used to signal timer based events. + + @param Time Time since the last timer interrupt in 100 ns units. This will + typically be TimerPeriod, but if a timer interrupt is missed, and the + EFI_TIMER_ARCH_PROTOCOL driver can detect missed interrupts, then Time + will contain the actual amount of time since the last interrupt. + + None. + +**/ +typedef +VOID +(EFIAPI *EFI_TIMER_NOTIFY) ( + IN UINT64 Time + ); + +/** + This function registers the handler NotifyFunction so it is called every time + the timer interrupt fires. It also passes the amount of time since the last + handler call to the NotifyFunction. If NotifyFunction is NULL, then the + handler is unregistered. If the handler is registered, then EFI_SUCCESS is + returned. If the CPU does not support registering a timer interrupt handler, + then EFI_UNSUPPORTED is returned. If an attempt is made to register a handler + when a handler is already registered, then EFI_ALREADY_STARTED is returned. + If an attempt is made to unregister a handler when a handler is not registered, + then EFI_INVALID_PARAMETER is returned. If an error occurs attempting to + register the NotifyFunction with the timer interrupt, then EFI_DEVICE_ERROR + is returned. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + + @param NotifyFunction The function to call when a timer interrupt fires. This + function executes at TPL_HIGH_LEVEL. The DXE Core will + register a handler for the timer interrupt, so it can know + how much time has passed. This information is used to + signal timer based events. NULL will unregister the handler. + + @retval EFI_SUCCESS The timer handler was registered. + + @retval EFI_UNSUPPORTED The platform does not support timer interrupts. + + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already + registered. + + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not + previously registered. + + @retval EFI_DEVICE_ERROR The timer handler could not be registered. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TIMER_REGISTER_HANDLER) ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN EFI_TIMER_NOTIFY NotifyFunction +); + +/** + This function adjusts the period of timer interrupts to the value specified + by TimerPeriod. If the timer period is updated, then the selected timer + period is stored in EFI_TIMER.TimerPeriod, and EFI_SUCCESS is returned. If + the timer hardware is not programmable, then EFI_UNSUPPORTED is returned. + If an error occurs while attempting to update the timer period, then the + timer hardware will be put back in its state prior to this call, and + EFI_DEVICE_ERROR is returned. If TimerPeriod is 0, then the timer interrupt + is disabled. This is not the same as disabling the CPU's interrupts. + Instead, it must either turn off the timer hardware, or it must adjust the + interrupt controller so that a CPU interrupt is not generated when the timer + interrupt fires. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + + @param TimerPeriod The rate to program the timer interrupt in 100 nS units. If + the timer hardware is not programmable, then EFI_UNSUPPORTED is + returned. If the timer is programmable, then the timer period + will be rounded up to the nearest timer period that is supported + by the timer hardware. If TimerPeriod is set to 0, then the + timer interrupts will be disabled. + + @retval EFI_SUCCESS The timer period was changed. + + @retval EFI_UNSUPPORTED The platform cannot change the period of the timer interrupt. + + @retval EFI_DEVICE_ERROR The timer period could not be changed due to a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TIMER_SET_TIMER_PERIOD) ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ); + +/** + This function retrieves the period of timer interrupts in 100 ns units, + returns that value in TimerPeriod, and returns EFI_SUCCESS. If TimerPeriod + is NULL, then EFI_INVALID_PARAMETER is returned. If a TimerPeriod of 0 is + returned, then the timer is currently disabled. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + + @param TimerPeriod A pointer to the timer period to retrieve in 100 ns units. If + 0 is returned, then the timer is currently disabled. + + @retval EFI_SUCCESS The timer period was returned in TimerPeriod. + + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TIMER_GET_TIMER_PERIOD) ( + IN EFI_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ); + +/** + This function generates a soft timer interrupt. If the platform does not support soft + timer interrupts, then EFI_UNSUPPORTED is returned. Otherwise, EFI_SUCCESS is returned. + If a handler has been registered through the EFI_TIMER_ARCH_PROTOCOL.RegisterHandler() + service, then a soft timer interrupt will be generated. If the timer interrupt is + enabled when this service is called, then the registered handler will be invoked. The + registered handler should not be able to distinguish a hardware-generated timer + interrupt from a software-generated timer interrupt. + + @param This The EFI_TIMER_ARCH_PROTOCOL instance. + + @retval EFI_SUCCESS The soft timer interrupt was generated. + + @retval EFI_UNSUPPORTEDT The platform does not support the generation of soft timer interrupts. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TIMER_GENERATE_SOFT_INTERRUPT) ( + IN EFI_TIMER_ARCH_PROTOCOL *This + ); + + +/** + Interface stucture for the Timer Architectural Protocol. + + @par Protocol Description: + This protocol provides the services to initialize a periodic timer + interrupt, and to register a handler that is called each time the timer + interrupt fires. It may also provide a service to adjust the rate of the + periodic timer interrupt. When a timer interrupt occurs, the handler is + passed the amount of time that has passed since the previous timer + interrupt. + + @param RegisterHandler + Registers a handler that will be called each time the + timer interrupt fires. TimerPeriod defines the minimum + time between timer interrupts, so TimerPeriod will also + be the minimum time between calls to the registered + handler. + + @param SetTimerPeriod + Sets the period of the timer interrupt in 100 nS units. + This function is optional, and may return EFI_UNSUPPORTED. + If this function is supported, then the timer period will + be rounded up to the nearest supported timer period. + + @param GetTimerPeriod + Retrieves the period of the timer interrupt in 100 nS units. + + @param GenerateSoftInterrupt + Generates a soft timer interrupt that simulates the firing of + the timer interrupt. This service can be used to invoke the + registered handler if the timer interrupt has been masked for + a period of time. + +**/ +struct _EFI_TIMER_ARCH_PROTOCOL { + EFI_TIMER_REGISTER_HANDLER RegisterHandler; + EFI_TIMER_SET_TIMER_PERIOD SetTimerPeriod; + EFI_TIMER_GET_TIMER_PERIOD GetTimerPeriod; + EFI_TIMER_GENERATE_SOFT_INTERRUPT GenerateSoftInterrupt; +}; + +extern EFI_GUID gEfiTimerArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/Variable.h b/MdePkg/Include/Dxe/ArchProtocol/Variable.h new file mode 100644 index 0000000000..13eb113bcc --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/Variable.h @@ -0,0 +1,39 @@ +/** @file + Variable Architectural Protocol as defined in the DXE CIS + + This code is used to produce the EFI 1.0 runtime variable services + + The GetVariable (), GetNextVariableName (), and SetVariable () EFI 1.0 + services are added to the EFI system table and the + EFI_VARIABLE_ARCH_PROTOCOL_GUID protocol is registered with a NULL pointer. + + No CRC of the EFI system table is required, as it is done in the DXE core. + + Copyright (c) 2006, 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. + + Module Name: Variable.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_VARIABLE_ARCH_H__ +#define __ARCH_PROTOCOL_VARIABLE_ARCH_H__ + +// +// Global ID for the Variable Architectural Protocol +// +#define EFI_VARIABLE_ARCH_PROTOCOL_GUID \ + { 0x1e5668e2, 0x8481, 0x11d4, {0xbc, 0xf1, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } } + +extern EFI_GUID gEfiVariableArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/VariableWrite.h b/MdePkg/Include/Dxe/ArchProtocol/VariableWrite.h new file mode 100644 index 0000000000..8c21df54f1 --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/VariableWrite.h @@ -0,0 +1,38 @@ +/** @file + Variable Write Architectural Protocol as defined in the DXE CIS + + This code is used to produce the EFI 1.0 runtime variable services + + The SetVariable () EFI 1.0 services may be updated to the EFI system table and the + EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID protocol is registered with a NULL pointer. + + No CRC of the EFI system table is required, as it is done in the DXE core. + + Copyright (c) 2006, 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. + + Module Name: VariableWrite.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_VARIABLE_WRITE_ARCH_H__ +#define __ARCH_PROTOCOL_VARIABLE_WRITE_ARCH_H__ + +// +// Global ID for the Variable Write Architectural Protocol +// +#define EFI_VARIABLE_WRITE_ARCH_PROTOCOL_GUID \ + { 0x6441f818, 0x6362, 0x4e44, {0xb5, 0x70, 0x7d, 0xba, 0x31, 0xdd, 0x24, 0x53 } } + +extern EFI_GUID gEfiVariableWriteArchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Dxe/ArchProtocol/WatchdogTimer.h b/MdePkg/Include/Dxe/ArchProtocol/WatchdogTimer.h new file mode 100644 index 0000000000..a8d84b18da --- /dev/null +++ b/MdePkg/Include/Dxe/ArchProtocol/WatchdogTimer.h @@ -0,0 +1,172 @@ +/** @file + Watchdog Timer Architectural Protocol as defined in the DXE CIS + + Used to provide system watchdog timer services + + Copyright (c) 2006, 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. + + Module Name: WatchdogTimer.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __ARCH_PROTOCOL_WATCHDOG_TIMER_H__ +#define __ARCH_PROTOCOL_WATCHDOG_TIMER_H__ + +// +// Global ID for the Watchdog Timer Architectural Protocol +// +#define EFI_WATCHDOG_TIMER_ARCH_PROTOCOL_GUID \ + { 0x665E3FF5, 0x46CC, 0x11d4, {0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } } + +// +// Declare forward reference for the Timer Architectural Protocol +// +typedef struct _EFI_WATCHDOG_TIMER_ARCH_PROTOCOL EFI_WATCHDOG_TIMER_ARCH_PROTOCOL; + +/** + A function of this type is called when the watchdog timer fires if a + handler has been registered. + + @param Time The time in 100 ns units that has passed since the watchdog + timer was armed. For the notify function to be called, this + must be greater than TimerPeriod. + + @return None. + +**/ +typedef +VOID +(EFIAPI *EFI_WATCHDOG_TIMER_NOTIFY) ( + IN UINT64 Time + ); + +/** + This function registers a handler that is to be invoked when the watchdog + timer fires. By default, the EFI_WATCHDOG_TIMER protocol will call the + Runtime Service ResetSystem() when the watchdog timer fires. If a + NotifyFunction is registered, then the NotifyFunction will be called before + the Runtime Service ResetSystem() is called. If NotifyFunction is NULL, then + the watchdog handler is unregistered. If a watchdog handler is registered, + then EFI_SUCCESS is returned. If an attempt is made to register a handler + when a handler is already registered, then EFI_ALREADY_STARTED is returned. + If an attempt is made to uninstall a handler when a handler is not installed, + then return EFI_INVALID_PARAMETER. + + @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. + + @param NotifyFunction The function to call when the watchdog timer fires. If this + is NULL, then the handler will be unregistered. + + @retval EFI_SUCCESS The watchdog timer handler was registered or + unregistered. + + @retval EFI_ALREADY_STARTED NotifyFunction is not NULL, and a handler is already + registered. + + @retval EFI_INVALID_PARAMETER NotifyFunction is NULL, and a handler was not + previously registered. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_TIMER_REGISTER_HANDLER) ( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + IN EFI_WATCHDOG_TIMER_NOTIFY NotifyFunction + ); + +/** + This function sets the amount of time to wait before firing the watchdog + timer to TimerPeriod 100 nS units. If TimerPeriod is 0, then the watchdog + timer is disabled. + + @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. + + @param TimerPeriod The amount of time in 100 nS units to wait before the watchdog + timer is fired. If TimerPeriod is zero, then the watchdog + timer is disabled. + + @retval EFI_SUCCESS The watchdog timer has been programmed to fire in Time + 100 nS units. + + @retval EFI_DEVICE_ERROR A watchdog timer could not be programmed due to a device + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_TIMER_SET_TIMER_PERIOD) ( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + IN UINT64 TimerPeriod + ); + +/** + This function retrieves the amount of time the system will wait before firing + the watchdog timer. This period is returned in TimerPeriod, and EFI_SUCCESS + is returned. If TimerPeriod is NULL, then EFI_INVALID_PARAMETER is returned. + + @param This The EFI_WATCHDOG_TIMER_ARCH_PROTOCOL instance. + + @param TimerPeriod A pointer to the amount of time in 100 nS units that the system + will wait before the watchdog timer is fired. If TimerPeriod of + zero is returned, then the watchdog timer is disabled. + + @retval EFI_SUCCESS The amount of time that the system will wait before + firing the watchdog timer was returned in TimerPeriod. + + @retval EFI_INVALID_PARAMETER TimerPeriod is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WATCHDOG_TIMER_GET_TIMER_PERIOD) ( + IN EFI_WATCHDOG_TIMER_ARCH_PROTOCOL *This, + OUT UINT64 *TimerPeriod + ); + + +/** + Interface stucture for the Watchdog Timer Architectural Protocol. + + @par Protocol Description: + This protocol provides the services required to implement the Boot Service + SetWatchdogTimer(). It provides a service to set the amount of time to wait + before firing the watchdog timer, and it also provides a service to register + a handler that is invoked when the watchdog timer fires. This protocol can + implement the watchdog timer by using the event and timer Boot Services, or + it can make use of custom hardware. When the watchdog timer fires, control + will be passed to a handler if one has been registered. If no handler has + been registered, or the registered handler returns, then the system will be + reset by calling the Runtime Service ResetSystem(). + + @param RegisterHandler - Registers a handler that is invoked when the watchdog + timer fires. + + @param SetTimerPeriod - Sets the amount of time in 100 ns units to wait before the + watchdog timer is fired. If this function is supported, + then the watchdog timer period will be rounded up to the + nearest supported watchdog timer period. + + @param GetTimerPeriod - Retrieves the amount of time in 100 ns units that the + system will wait before the watchdog timer is fired. + +**/ +struct _EFI_WATCHDOG_TIMER_ARCH_PROTOCOL { + EFI_WATCHDOG_TIMER_REGISTER_HANDLER RegisterHandler; + EFI_WATCHDOG_TIMER_SET_TIMER_PERIOD SetTimerPeriod; + EFI_WATCHDOG_TIMER_GET_TIMER_PERIOD GetTimerPeriod; +}; + +extern EFI_GUID gEfiWatchdogTimerArchProtocolGuid; + +#endif + diff --git a/MdePkg/Include/Dxe/DxeCis.h b/MdePkg/Include/Dxe/DxeCis.h new file mode 100644 index 0000000000..a36481c817 --- /dev/null +++ b/MdePkg/Include/Dxe/DxeCis.h @@ -0,0 +1,589 @@ +/** @file + Include file matches things in the DXE CIS. + + Copyright (c) 2006, 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. + + Module Name: DxeCis.h + + @par Revision Reference: + Version 0.91B. + +**/ + +#ifndef __DXE_CIS__ +#define __DXE_CIS__ + +#include + + +#define TIANO_ERROR(a) (MAX_2_BITS | (a)) + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) +// +// Tiano added a couple of return types. These are owned by UEFI specification +// and Tiano can not use them. Thus for UEFI 2.0/R9 support we moved the values +// to a UEFI OEM extension range to conform to UEFI specification. +// +#define EFI_NOT_AVAILABLE_YET EFIERR (28) +#define EFI_UNLOAD_IMAGE EFIERR (29) +#else +#define EFI_NOT_AVAILABLE_YET TIANO_ERROR (0) +#define EFI_UNLOAD_IMAGE TIANO_ERROR (1) +#endif + +// +// BugBug: Implementation contamination of UEFI 2.0 +// Pointer to internal runtime pointer +// +#define EFI_IPF_GP_POINTER 0x00000008 + + +// +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// + +// +// attributes for reserved memory before it is promoted to system memory +// +#define EFI_MEMORY_PRESENT 0x0100000000000000ULL +#define EFI_MEMORY_INITIALIZED 0x0200000000000000ULL +#define EFI_MEMORY_TESTED 0x0400000000000000ULL + +// +// range for memory mapped port I/O on IPF +// +#define EFI_MEMORY_PORT_IO 0x4000000000000000ULL + +// +// Modifier for EFI DXE Services +// +#define EFI_DXESERVICE + + +// +// Global Coherencey Domain types +// +typedef enum { + EfiGcdMemoryTypeNonExistent, + EfiGcdMemoryTypeReserved, + EfiGcdMemoryTypeSystemMemory, + EfiGcdMemoryTypeMemoryMappedIo, + EfiGcdMemoryTypeMaximum +} EFI_GCD_MEMORY_TYPE; + +typedef enum { + EfiGcdIoTypeNonExistent, + EfiGcdIoTypeReserved, + EfiGcdIoTypeIo, + EfiGcdIoTypeMaximum +} EFI_GCD_IO_TYPE; + +typedef enum { + EfiGcdAllocateAnySearchBottomUp, + EfiGcdAllocateMaxAddressSearchBottomUp, + EfiGcdAllocateAddress, + EfiGcdAllocateAnySearchTopDown, + EfiGcdAllocateMaxAddressSearchTopDown, + EfiGcdMaxAllocateType +} EFI_GCD_ALLOCATE_TYPE; + +typedef struct { + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; + UINT64 Capabilities; + UINT64 Attributes; + EFI_GCD_MEMORY_TYPE GcdMemoryType; + EFI_HANDLE ImageHandle; + EFI_HANDLE DeviceHandle; +} EFI_GCD_MEMORY_SPACE_DESCRIPTOR; + +typedef struct { + EFI_PHYSICAL_ADDRESS BaseAddress; + UINT64 Length; + EFI_GCD_IO_TYPE GcdIoType; + EFI_HANDLE ImageHandle; + EFI_HANDLE DeviceHandle; +} EFI_GCD_IO_SPACE_DESCRIPTOR; + +/** + Adds reserved memory, system memory, or memory-mapped I/O resources to the + global coherency domain of the processor. + + @param GcdMemoryType Memory type of the memory space. + + @param BaseAddress Base address of the memory space. + + @param Length Length of the memory space. + + @param Capabilities alterable attributes of the memory space. + + @retval EFI_SUCCESS Merged this memory space into GCD map. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ADD_MEMORY_SPACE) ( + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Capabilities + ) +; + +/** + Allocates nonexistent memory, reserved memory, system memory, or memorymapped + I/O resources from the global coherency domain of the processor. + + @param GcdAllocateType The type of allocate operation + + @param GcdMemoryType The desired memory type + + @param Alignment Align with 2^Alignment + + @param Length Length to allocate + + @param BaseAddress Base address to allocate + + @param Imagehandle The image handle consume the allocated space. + + @param DeviceHandle The device handle consume the allocated space. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + + @retval EFI_NOT_FOUND No descriptor contains the desired space. + + @retval EFI_SUCCESS Memory space successfully allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_MEMORY_SPACE) ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_MEMORY_TYPE GcdMemoryType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ) +; + +/** + Frees nonexistent memory, reserved memory, system memory, or memory-mapped + I/O resources from the global coherency domain of the processor. + + @param BaseAddress Base address of the segment. + + @param Length Length of the segment. + + @retval EFI_SUCCESS Space successfully freed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_MEMORY_SPACE) ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +; + +/** + Removes reserved memory, system memory, or memory-mapped I/O resources from + the global coherency domain of the processor. + + @param BaseAddress Base address of the memory space. + + @param Length Length of the memory space. + + @retval EFI_SUCCESS Successfully remove a segment of memory space. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REMOVE_MEMORY_SPACE) ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +; + +/** + Retrieves the descriptor for a memory region containing a specified address. + + @param BaseAddress Specified start address + + @param Descriptor Specified length + + @retval EFI_INVALID_PARAMETER Invalid parameter + + @retval EFI_SUCCESS Successfully get memory space descriptor. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MEMORY_SPACE_DESCRIPTOR) ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Descriptor + ) +; + +/** + Modifies the attributes for a memory region in the global coherency domain of the + processor. + + @param BaseAddress Specified start address + + @param Length Specified length + + @param Attributes Specified attributes + + @retval EFI_SUCCESS Successfully set attribute of a segment of memory space. + +**/ +typedef + +EFI_STATUS +(EFIAPI *EFI_SET_MEMORY_SPACE_ATTRIBUTES) ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 Attributes + ) +; + +/** + Returns a map of the memory resources in the global coherency domain of the + processor. + + @param NumberOfDescriptors Number of descriptors. + + @param MemorySpaceMap Descriptor array + + @retval EFI_INVALID_PARAMETER Invalid parameter + + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + + @retval EFI_SUCCESS Successfully get memory space map. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MEMORY_SPACE_MAP) ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_MEMORY_SPACE_DESCRIPTOR **MemorySpaceMap + ) +; + +/** + Adds reserved I/O or I/O resources to the global coherency domain of the processor. + + @param GcdIoType IO type of the segment. + + @param BaseAddress Base address of the segment. + + @param Length Length of the segment. + + @retval EFI_SUCCESS Merged this segment into GCD map. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ADD_IO_SPACE) ( + IN EFI_GCD_IO_TYPE GcdIoType, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +; + +/** + Allocates nonexistent I/O, reserved I/O, or I/O resources from the global coherency + domain of the processor. + + @param GcdAllocateType The type of allocate operation + + @param GcdIoType The desired IO type + + @param Alignment Align with 2^Alignment + + @param Length Length to allocate + + @param BaseAddress Base address to allocate + + @param Imagehandle The image handle consume the allocated space. + + @param DeviceHandle The device handle consume the allocated space. + + @retval EFI_INVALID_PARAMETER Invalid parameter. + + @retval EFI_NOT_FOUND No descriptor contains the desired space. + + @retval EFI_SUCCESS IO space successfully allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_IO_SPACE) ( + IN EFI_GCD_ALLOCATE_TYPE GcdAllocateType, + IN EFI_GCD_IO_TYPE GcdIoType, + IN UINTN Alignment, + IN UINT64 Length, + IN OUT EFI_PHYSICAL_ADDRESS *BaseAddress, + IN EFI_HANDLE ImageHandle, + IN EFI_HANDLE DeviceHandle OPTIONAL + ) +; + +/** + Frees nonexistent I/O, reserved I/O, or I/O resources from the global coherency + domain of the processor. + + @param BaseAddress Base address of the segment. + + @param Length Length of the segment. + + @retval EFI_SUCCESS Space successfully freed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_IO_SPACE) ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +; + +/** + Removes reserved I/O or I/O resources from the global coherency domain of the + processor. + + @param BaseAddress Base address of the segment. + + @param Length Length of the segment. + + @retval EFI_SUCCESS Successfully removed a segment of IO space. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REMOVE_IO_SPACE) ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +; + +/** + Retrieves the descriptor for an I/O region containing a specified address. + + @param BaseAddress Specified start address + + @param Descriptor Specified length + + @retval EFI_INVALID_PARAMETER Descriptor is NULL. + + @retval EFI_SUCCESS Successfully get the IO space descriptor. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_IO_SPACE_DESCRIPTOR) ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR *Descriptor + ) +; + +/** + Returns a map of the I/O resources in the global coherency domain of the processor. + + @param NumberOfDescriptors Number of descriptors. + + @param MemorySpaceMap Descriptor array + + @retval EFI_INVALID_PARAMETER Invalid parameter + + @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate + + @retval EFI_SUCCESS Successfully get IO space map. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_IO_SPACE_MAP) ( + OUT UINTN *NumberOfDescriptors, + OUT EFI_GCD_IO_SPACE_DESCRIPTOR **IoSpaceMap + ) +; + +/** + Loads and executed DXE drivers from firmware volumes. + + @return Status code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISPATCH) (VOID) +; + +/** + Clears the Schedule on Request (SOR) flag for a component that is stored in a firmware volume. + + @param FirmwareVolumeHandle The handle of the firmware volume that contains the file specified by FileName. + + @param DriverName A pointer to the name of the file in a firmware volume. + + @return Status code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCHEDULE) ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ) +; + +/** + Promotes a file stored in a firmware volume from the untrusted to the trusted state. + + @param FirmwareVolumeHandle The handle of the firmware volume that contains the file specified by FileName. + + @param DriverName A pointer to the name of the file in a firmware volume. + + @return Status code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TRUST) ( + IN EFI_HANDLE FirmwareVolumeHandle, + IN EFI_GUID *DriverName + ) +; + +/** + Creates a firmware volume handle for a firmware volume that is present in system memory. + + @param FirmwareVolumeHeader A pointer to the header of the firmware volume. + @param Size The size, in bytes, of the firmware volume. + @param FirmwareVolumeHandle On output, a pointer to the created handle. + + @return Status code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PROCESS_FIRMWARE_VOLUME) ( + IN VOID *FvHeader, + IN UINTN Size, + OUT EFI_HANDLE *FirmwareVolumeHandle + ) +; + +// +// DXE Services Table +// +#define EFI_DXE_SERVICES_SIGNATURE 0x565245535f455844ULL +#define EFI_DXE_SERVICES_REVISION ((0 << 16) | (25)) + +typedef struct { + EFI_TABLE_HEADER Hdr; + + // + // Global Coherency Domain Services + // + EFI_ADD_MEMORY_SPACE AddMemorySpace; + EFI_ALLOCATE_MEMORY_SPACE AllocateMemorySpace; + EFI_FREE_MEMORY_SPACE FreeMemorySpace; + EFI_REMOVE_MEMORY_SPACE RemoveMemorySpace; + EFI_GET_MEMORY_SPACE_DESCRIPTOR GetMemorySpaceDescriptor; + EFI_SET_MEMORY_SPACE_ATTRIBUTES SetMemorySpaceAttributes; + EFI_GET_MEMORY_SPACE_MAP GetMemorySpaceMap; + EFI_ADD_IO_SPACE AddIoSpace; + EFI_ALLOCATE_IO_SPACE AllocateIoSpace; + EFI_FREE_IO_SPACE FreeIoSpace; + EFI_REMOVE_IO_SPACE RemoveIoSpace; + EFI_GET_IO_SPACE_DESCRIPTOR GetIoSpaceDescriptor; + EFI_GET_IO_SPACE_MAP GetIoSpaceMap; + + // + // Dispatcher Services + // + EFI_DISPATCH Dispatch; + EFI_SCHEDULE Schedule; + EFI_TRUST Trust; + // + // Service to process a single firmware volume found in a capsule + // + EFI_PROCESS_FIRMWARE_VOLUME ProcessFirmwareVolume; +} EFI_DXE_SERVICES; + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif diff --git a/MdePkg/Include/Dxe/SmmCis.h b/MdePkg/Include/Dxe/SmmCis.h new file mode 100644 index 0000000000..35a1a64682 --- /dev/null +++ b/MdePkg/Include/Dxe/SmmCis.h @@ -0,0 +1,526 @@ +/** @file + Include file matches things in the Smm CIS spec. + + Copyright (c) 2006, 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. + + Module Name: SmmCis.h + + @par Revision Reference: + Version 0.9. + +**/ + +#ifndef __SMM_CIS__ +#define __SMM_CIS__ + +#define EFI_SMM_CPU_IO_GUID \ + { \ + 0x5f439a0b, 0x45d8, 0x4682, {0xa4, 0xf4, 0xf0, 0x57, 0x6b, 0x51, 0x34, 0x41 } \ + } + +typedef struct _EFI_SMM_SYSTEM_TABLE EFI_SMM_SYSTEM_TABLE; +typedef struct _EFI_SMM_CPU_IO_INTERFACE EFI_SMM_CPU_IO_INTERFACE; + + +// +// SMM Base specification constant and types +// +#define SMM_SMST_SIGNATURE EFI_SIGNATURE_32 ('S', 'M', 'S', 'T') +#define EFI_SMM_SYSTEM_TABLE_REVISION (0 << 16) | (0x09) + +// +// ******************************************************* +// EFI_SMM_IO_WIDTH +// ******************************************************* +// +typedef enum { + SMM_IO_UINT8 = 0, + SMM_IO_UINT16 = 1, + SMM_IO_UINT32 = 2, + SMM_IO_UINT64 = 3 +} EFI_SMM_IO_WIDTH; + +/** + Provides the basic memory and I/O interfaces that are used to + abstract accesses to devices. + + @param This The EFI_SMM_CPU_IO_INTERFACE instance. + + @param Width Signifies the width of the I/O operations. + + @param Address The base address of the I/O operations. + + @param Count The number of I/O operations to perform. + + @param Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the device. + + @retval EFI_UNSUPPORTED The Address is not valid for this system. + + @retval EFI_INVALID_PARAMETER Width or Count, or both, were invalid. + + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_CPU_IO) ( + IN EFI_SMM_CPU_IO_INTERFACE *This, + IN EFI_SMM_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + EFI_SMM_CPU_IO Read; + EFI_SMM_CPU_IO Write; +} EFI_SMM_IO_ACCESS; + +struct _EFI_SMM_CPU_IO_INTERFACE { + EFI_SMM_IO_ACCESS Mem; + EFI_SMM_IO_ACCESS Io; +}; + +/** + Allocates pool memory from SMRAM for IA-32 or runtime memory for + the Itanium processor family. + + @param PoolType The type of pool to allocate.The only supported type is EfiRuntimeServicesData + + @param Size The number of bytes to allocate from the pool. + + @param Buffer A pointer to a pointer to the allocated buffer if the call + succeeds; undefined otherwise. + + @retval EFI_SUCCESS The requested number of bytes was allocated. + + @retval EFI_OUT_OF_RESOURCES The pool requested could not be allocated. + + @retval EFI_UNSUPPORTED In runtime. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMMCORE_ALLOCATE_POOL) ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + Returns pool memory to the system. + + @param Buffer Pointer to the buffer to free. + + @retval EFI_SUCCESS The memory was returned to the system. + + @retval EFI_INVALID_PARAMETER Buffer was invalid. + + @retval EFI_UNSUPPORTED In runtime. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMMCORE_FREE_POOL) ( + IN VOID *Buffer + ); + +/** + Allocates memory pages from the system. + + @param Type The type of allocation to perform. + + @param MemoryType The only supported type is EfiRuntimeServicesData + + @param NumberofPages The number of contiguous 4 KB pages to allocate + + @param Memory Pointer to a physical address. On input, the way in which + the address is used depends on the value of Type. On output, the address + is set to the base of the page range that was allocated. + + @retval EFI_SUCCESS The requested pages were allocated. + + @retval EFI_OUT_OF_RESOURCES The pages requested could not be allocated. + + @retval EFI_NOT_FOUND The requested pages could not be found. + + @retval EFI_INVALID_PARAMETER Type is not AllocateAnyPages or AllocateMaxAddress + or AllocateAddress. Or MemoryType is in the range EfiMaxMemoryType..0x7FFFFFFF. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMMCORE_ALLOCATE_PAGES) ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN NumberOfPages, + OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + Frees memory pages for the system. + + @param Memory The base physical address of the pages to be freed + + @param NumberOfPages The number of contiguous 4 KB pages to free. + + @retval EFI_SUCCESS The requested memory pages were freed. + + @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or NumberOfPages is invalid. + + @retval EFI_NOT_FOUND The requested memory pages were not allocated with SmmAllocatePages(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMMCORE_FREE_PAGES) ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NumberOfPages + ); + +typedef +VOID +(EFIAPI *EFI_AP_PROCEDURE) ( + IN VOID *Buffer + ); + +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_STARTUP_THIS_AP) ( + IN EFI_AP_PROCEDURE Procedure, + IN UINTN CpuNumber, + IN OUT VOID *ProcArguments OPTIONAL + ); + +typedef struct { + UINT8 Reserved1[248]; + UINT32 SMBASE; + UINT32 SMMRevId; + UINT16 IORestart; + UINT16 AutoHALTRestart; + UINT8 Reserved2[164]; + UINT32 ES; + UINT32 CS; + UINT32 SS; + UINT32 DS; + UINT32 FS; + UINT32 GS; + UINT32 LDTBase; + UINT32 TR; + UINT32 DR7; + UINT32 DR6; + UINT32 EAX; + UINT32 ECX; + UINT32 EDX; + UINT32 EBX; + UINT32 ESP; + UINT32 EBP; + UINT32 ESI; + UINT32 EDI; + UINT32 EIP; + UINT32 EFLAGS; + UINT32 CR3; + UINT32 CR0; +} EFI_SMI_CPU_SAVE_STATE; + +typedef struct { + UINT64 reserved; + UINT64 r1; + UINT64 r2; + UINT64 r3; + UINT64 r4; + UINT64 r5; + UINT64 r6; + UINT64 r7; + UINT64 r8; + UINT64 r9; + UINT64 r10; + UINT64 r11; + UINT64 r12; + UINT64 r13; + UINT64 r14; + UINT64 r15; + UINT64 r16; + UINT64 r17; + UINT64 r18; + UINT64 r19; + UINT64 r20; + UINT64 r21; + UINT64 r22; + UINT64 r23; + UINT64 r24; + UINT64 r25; + UINT64 r26; + UINT64 r27; + UINT64 r28; + UINT64 r29; + UINT64 r30; + UINT64 r31; + + UINT64 pr; + + UINT64 b0; + UINT64 b1; + UINT64 b2; + UINT64 b3; + UINT64 b4; + UINT64 b5; + UINT64 b6; + UINT64 b7; + + // application registers + UINT64 ar_rsc; + UINT64 ar_bsp; + UINT64 ar_bspstore; + UINT64 ar_rnat; + + UINT64 ar_fcr; + + UINT64 ar_eflag; + UINT64 ar_csd; + UINT64 ar_ssd; + UINT64 ar_cflg; + UINT64 ar_fsr; + UINT64 ar_fir; + UINT64 ar_fdr; + + UINT64 ar_ccv; + + UINT64 ar_unat; + + UINT64 ar_fpsr; + + UINT64 ar_pfs; + UINT64 ar_lc; + UINT64 ar_ec; + + // control registers + UINT64 cr_dcr; + UINT64 cr_itm; + UINT64 cr_iva; + UINT64 cr_pta; + UINT64 cr_ipsr; + UINT64 cr_isr; + UINT64 cr_iip; + UINT64 cr_ifa; + UINT64 cr_itir; + UINT64 cr_iipa; + UINT64 cr_ifs; + UINT64 cr_iim; + UINT64 cr_iha; + + // debug registers + UINT64 dbr0; + UINT64 dbr1; + UINT64 dbr2; + UINT64 dbr3; + UINT64 dbr4; + UINT64 dbr5; + UINT64 dbr6; + UINT64 dbr7; + + UINT64 ibr0; + UINT64 ibr1; + UINT64 ibr2; + UINT64 ibr3; + UINT64 ibr4; + UINT64 ibr5; + UINT64 ibr6; + UINT64 ibr7; + + // virtual registers + UINT64 int_nat; // nat bits for R1-R31 + +} EFI_PMI_SYSTEM_CONTEXT; + +typedef union { + EFI_SMI_CPU_SAVE_STATE Ia32SaveState; + EFI_PMI_SYSTEM_CONTEXT ItaniumSaveState; +} EFI_SMM_CPU_SAVE_STATE; + +typedef struct { + UINT16 Fcw; + UINT16 Fsw; + UINT16 Ftw; + UINT16 Opcode; + UINT32 Eip; + UINT16 Cs; + UINT16 Rsvd1; + UINT32 DataOffset; + UINT16 Ds; + UINT8 Rsvd2[10]; + UINT8 St0Mm0[10], Rsvd3[6]; + UINT8 St0Mm1[10], Rsvd4[6]; + UINT8 St0Mm2[10], Rsvd5[6]; + UINT8 St0Mm3[10], Rsvd6[6]; + UINT8 St0Mm4[10], Rsvd7[6]; + UINT8 St0Mm5[10], Rsvd8[6]; + UINT8 St0Mm6[10], Rsvd9[6]; + UINT8 St0Mm7[10], Rsvd10[6]; + UINT8 Rsvd11[22*16]; +} EFI_SMI_OPTIONAL_FPSAVE_STATE; + +typedef struct { + UINT64 f2[2]; + UINT64 f3[2]; + UINT64 f4[2]; + UINT64 f5[2]; + UINT64 f6[2]; + UINT64 f7[2]; + UINT64 f8[2]; + UINT64 f9[2]; + UINT64 f10[2]; + UINT64 f11[2]; + UINT64 f12[2]; + UINT64 f13[2]; + UINT64 f14[2]; + UINT64 f15[2]; + UINT64 f16[2]; + UINT64 f17[2]; + UINT64 f18[2]; + UINT64 f19[2]; + UINT64 f20[2]; + UINT64 f21[2]; + UINT64 f22[2]; + UINT64 f23[2]; + UINT64 f24[2]; + UINT64 f25[2]; + UINT64 f26[2]; + UINT64 f27[2]; + UINT64 f28[2]; + UINT64 f29[2]; + UINT64 f30[2]; + UINT64 f31[2]; +} EFI_PMI_OPTIONAL_FLOATING_POINT_CONTEXT; + +typedef union { + EFI_SMI_OPTIONAL_FPSAVE_STATE Ia32FpSave; + EFI_PMI_OPTIONAL_FLOATING_POINT_CONTEXT ItaniumFpSave; +} EFI_SMM_FLOATING_POINT_SAVE_STATE; + +/** + This function is the main entry point for an SMM handler dispatch + or communicate-based callback. + + @param SmmImageHandle A unique value returned by the SMM infrastructure + in response to registration for a communicate-based callback or dispatch. + + @param CommunicationBuffer An optional buffer that will be populated + by the SMM infrastructure in response to a non-SMM agent (preboot or runtime) + invoking the EFI_SMM_BASE_PROTOCOL.Communicate() service. + + @param SourceSize If CommunicationBuffer is non-NULL, this field + indicates the size of the data payload in this buffer. + + @return Status Code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_HANDLER_ENTRY_POINT) ( + IN EFI_HANDLE SmmImageHandle, + IN OUT VOID *CommunicationBuffer OPTIONAL, + IN OUT UINTN *SourceSize OPTIONAL + ); + +/** + The SmmInstallConfigurationTable() function is used to maintain the list + of configuration tables that are stored in the System Management System + Table. The list is stored as an array of (GUID, Pointer) pairs. The list + must be allocated from pool memory with PoolType set to EfiRuntimeServicesData. + + @param SystemTable A pointer to the SMM System Table. + @param Guid A pointer to the GUID for the entry to add, update, or remove. + @param Table A pointer to the buffer of the table to add. + @param TableSize The size of the table to install. + + @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed. + @retval EFI_INVALID_PARAMETER Guid is not valid. + @retval EFI_NOT_FOUND An attempt was made to delete a non-existent entry. + @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_INSTALL_CONFIGURATION_TABLE) ( + IN EFI_SMM_SYSTEM_TABLE *SystemTable, + IN EFI_GUID *Guid, + IN VOID *Table, + IN UINTN TableSize + ) +; + +// +// System Management System Table (SMST) +// +struct _EFI_SMM_SYSTEM_TABLE { + EFI_TABLE_HEADER Hdr; + + CHAR16 *SmmFirmwareVendor; + UINT32 SmmFirmwareRevision; + + EFI_SMM_INSTALL_CONFIGURATION_TABLE SmmInstallConfigurationTable; + + // + // I/O Services + // + EFI_GUID EfiSmmCpuIoGuid; + EFI_SMM_CPU_IO_INTERFACE SmmIo; + + // + // Runtime memory service + // + EFI_SMMCORE_ALLOCATE_POOL SmmAllocatePool; + EFI_SMMCORE_FREE_POOL SmmFreePool; + EFI_SMMCORE_ALLOCATE_PAGES SmmAllocatePages; + EFI_SMMCORE_FREE_PAGES SmmFreePages; + + // + // MP service + // + EFI_SMM_STARTUP_THIS_AP SmmStartupThisAp; + + // + // CPU information records + // + UINTN CurrentlyExecutingCpu; + UINTN NumberOfCpus; + EFI_SMM_CPU_SAVE_STATE *CpuSaveState; + EFI_SMM_FLOATING_POINT_SAVE_STATE *CpuOptionalFloatingPointState; + + // + // Extensibility table + // + UINTN NumberOfTableEntries; + EFI_CONFIGURATION_TABLE *SmmConfigurationTable; + +}; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern EFI_GUID gEfiSmmCpuIoGuid; + +#endif diff --git a/MdePkg/Include/DxeCore.h b/MdePkg/Include/DxeCore.h new file mode 100644 index 0000000000..9554fb8c23 --- /dev/null +++ b/MdePkg/Include/DxeCore.h @@ -0,0 +1,50 @@ +/** @file + + Root include file for DXE Core + + The DXE Core has its own module type since its entry point definition is + unique. This module type should only be used by the DXE core. The build + infrastructure must set EFI_SPECIFICATION_VERSION before including this + file. To support R9/UEFI2.0 set EFI_SPECIFIATION_VERSION to 0x00020000. To + support R8.5/EFI 1.10 set EFI_SPECIFIATION_VERSION to 0x00010010. + EDK_RELEASE_VERSION must be set to a non zero value. + EFI_SPECIFIATION_VERSION and EDK_RELEASE_VERSION are set automatically + by the build infrastructure for every module. + + +Copyright (c) 2006, 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 __DXE_CORE_H__ +#define __DXE_CORE_H__ + + +// +// Check to make sure EFI_SPECIFICATION_VERSION and EDK_RELEASE_VERSION are defined. +// also check for legal combinations +// +#if !defined(EFI_SPECIFICATION_VERSION) + #error EFI_SPECIFICATION_VERSION not defined +#elif !defined(EDK_RELEASE_VERSION) + #error EDK_RELEASE_VERSION not defined +#elif (EDK_RELEASE_VERSION == 0) + #error EDK_RELEASE_VERSION can not be zero +#endif + + + +#include +#include + +#include + +#endif diff --git a/MdePkg/Include/DxeDepex.h b/MdePkg/Include/DxeDepex.h new file mode 100644 index 0000000000..e91f35083d --- /dev/null +++ b/MdePkg/Include/DxeDepex.h @@ -0,0 +1,58 @@ +/** @file + Include file for DXE Dependency Expression *.DXS file. + + This include file is only for Dependency Expression *.DXS files and + should not be include directly in modules. + + DEPEX (DEPendency EXpresion) BNF Grammer for DXE: + The BNF grammar is thus: +
+        ::= before GUID       
+                 | after GUID                  
+                 | SOR 
+                 |                  
+         ::=  and  
+                 |  or   
+                 |             
+         ::= not       
+                 |           
+       ::=             
+                 |          
+                 |          
+                 |          
+      ::= true              
+                 | false             
+      ::= push GUID         
+      ::= end               
+
+ +Copyright (c) 2006, 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 __DXE_DEPEX_H__ +#define __DXE_DEPEX_H__ + +// +// The Depex grammer needs the following strings so we must undo +// any pre-processor redefinitions +// +#undef DEPENDENCY_START +#undef BEFORE +#undef AFTER +#undef SOR +#undef AND +#undef OR +#undef NOT +#undef TRUE +#undef FALSE +#undef DEPENDENCY_END + +#endif diff --git a/MdePkg/Include/Ebc/ProcessorBind.h b/MdePkg/Include/Ebc/ProcessorBind.h new file mode 100644 index 0000000000..cef769241b --- /dev/null +++ b/MdePkg/Include/Ebc/ProcessorBind.h @@ -0,0 +1,81 @@ +/** @file + Processor or compiler specific defines and types for EBC. + + We currently only have one EBC complier so there may be some Intel compiler + specific functions in this file. + + Copyright (c) 2006, 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. + + Module Name: ProcessorBind.h + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +// +// Define the processor type so other code can make processor based choices +// +#define MDE_CPU_EBC + +// +// Native integer types +// +typedef char INT8; +typedef unsigned char BOOLEAN; +typedef unsigned char UINT8; +typedef unsigned char CHAR8; + +typedef short INT16; +typedef unsigned short UINT16; +typedef unsigned short CHAR16; + +typedef int INT32; +typedef unsigned int UINT32; + +typedef __int64 INT64; +typedef unsigned __int64 UINT64; + +// +// "long" type scales to the processor native size with EBC compiler +// +typedef long INTN; +typedef unsigned long UINTN; + +#define UINT8_MAX 0xff + +// +// Scalable macro to set the most significant bit in a natural number +// +#define MAX_BIT 0x8000000000000000ULL +#define MAX_2_BITS 0xC000000000000000ULL + + +// +// Maximum legal EBC address +// +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify thier member functions with EFIAPI. +// +#define EFIAPI + +// +// The Microsoft* C compiler can removed references to unreferenced data items +// if the /OPT:REF linker option is used. We defined a macro as this is a +// a non standard extension. Currently not supported by the EBC compiler +// +#define GLOBAL_REMOVE_IF_UNREFERENCED + +#endif + diff --git a/MdePkg/Include/Guid/Acpi.h b/MdePkg/Include/Guid/Acpi.h new file mode 100644 index 0000000000..a64f1b7ea0 --- /dev/null +++ b/MdePkg/Include/Guid/Acpi.h @@ -0,0 +1,48 @@ +/** @file + GUIDs used for ACPI entries in the EFI 1.0 system table + + These GUIDs point the ACPI tables as defined in the ACPI specifications. + ACPI 2.0 specification defines the ACPI 2.0 GUID. UEFI 2.0 defines the + ACPI 2.0 Table GUID and ACPI Table GUID. + + Copyright (c) 2006, 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. + + Module Name: Acpi.h + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __ACPI_GUID_H__ +#define __ACPI_GUID_H__ + +#define EFI_ACPI_10_TABLE_GUID \ + { \ + 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_ACPI_TABLE_GUID \ + { \ + 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define ACPI_10_TABLE_GUID EFI_ACPI_10_TABLE_GUID +// +// ACPI 2.0 or newer tables should use EFI_ACPI_TABLE_GUID. +// +#define EFI_ACPI_20_TABLE_GUID EFI_ACPI_TABLE_GUID +#define EFI_ACPI_30_TABLE_GUID EFI_ACPI_TABLE_GUID + +extern EFI_GUID gEfiAcpi10TableGuid; +extern EFI_GUID gEfiAcpi20TableGuid; +extern EFI_GUID gEfiAcpi30TableGuid; + +#endif diff --git a/MdePkg/Include/Guid/AcpiTableStorage.h b/MdePkg/Include/Guid/AcpiTableStorage.h new file mode 100644 index 0000000000..80b1154828 --- /dev/null +++ b/MdePkg/Include/Guid/AcpiTableStorage.h @@ -0,0 +1,30 @@ +/** @file + The ACPI table storage file is fully FFS compliant. + The file is a number of sections of type EFI_SECTION_RAW. + This GUID is used to identify the file as an ACPI table storage file. + + Copyright (c) 2006, 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. + + Module Name: AcpiTableStorage.h + + @par Revision Reference: + GUID defined in ACPI Table Storage Spec Version 0.9. + +**/ + +#ifndef _ACPI_TABLE_STORAGE_H_ +#define _ACPI_TABLE_STORAGE_H_ + +#define EFI_ACPI_TABLE_STORAGE_GUID \ + { 0x7e374e25, 0x8e01, 0x4fee, {0x87, 0xf2, 0x39, 0xc, 0x23, 0xc6, 0x6, 0xcd } } + +extern EFI_GUID gEfiAcpiTableStorageGuid; + +#endif diff --git a/MdePkg/Include/Guid/Apriori.h b/MdePkg/Include/Guid/Apriori.h new file mode 100644 index 0000000000..ba92560d7e --- /dev/null +++ b/MdePkg/Include/Guid/Apriori.h @@ -0,0 +1,32 @@ +/** @file + GUID used as an FV filename for A Priori file. The A Priori file contains a + list of FV filenames that the DXE dispatcher will schedule reguardless of + the dependency grammer. + + Copyright (c) 2006, 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. + + Module Name: Apriori.h + + @par Revision Reference: + GUID defined in DXE CIS spec version 0.91B + +**/ + +#ifndef __APRIORI_GUID_H__ +#define __APRIORI_GUID_H__ + +#define EFI_APRIORI_GUID \ + { \ + 0xfc510ee7, 0xffdc, 0x11d4, {0xbd, 0x41, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +extern EFI_GUID gAprioriGuid; + +#endif diff --git a/MdePkg/Include/Guid/Capsule.h b/MdePkg/Include/Guid/Capsule.h new file mode 100644 index 0000000000..7864b924de --- /dev/null +++ b/MdePkg/Include/Guid/Capsule.h @@ -0,0 +1,43 @@ +/** @file + GUIDs used for EFI Capsule + + Copyright (c) 2006, 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. + + Module Name: Capsule.h + + @par Revision Reference: + GUIDs defined in Capsule Spec Version 0.9 + +**/ + +#ifndef __CAPSULE_GUID_H__ +#define __CAPSULE_GUID_H__ + +// +// This is the GUID of the capsule header of the image on disk. +// +#define EFI_CAPSULE_GUID \ + { \ + 0x3B6686BD, 0x0D76, 0x4030, {0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 } \ + } + +// +// This is the GUID of the configuration results file created by the capsule +// application. +// +#define EFI_CONFIG_FILE_NAME_GUID \ + { \ + 0x98B8D59B, 0xE8BA, 0x48EE, {0x98, 0xDD, 0xC2, 0x95, 0x39, 0x2F, 0x1E, 0xDB } \ + } + +extern EFI_GUID gEfiCapsuleGuid; +extern EFI_GUID gEfiConfigFileNameGuid; + +#endif diff --git a/MdePkg/Include/Guid/DataHubRecords.h b/MdePkg/Include/Guid/DataHubRecords.h new file mode 100644 index 0000000000..f29a5a474f --- /dev/null +++ b/MdePkg/Include/Guid/DataHubRecords.h @@ -0,0 +1,66 @@ +/** @file + DataHubRecord.h include all data hub sub class GUID defitions. + + Copyright (c) 2006, 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. + + Module Name: DataHubRecords.h + + @par Revision Reference: + These GUID are from Cache subclass spec 0.9, DataHub SubClass spec 0.9, Memory SubClass Spec 0.9, + Processor Subclass spec 0.9, Misc SubClass spec 0.9. + +**/ +#ifndef _DATAHUB_RECORDS_GUID_H_ +#define _DATAHUB_RECORDS_GUID_H_ + +#define EFI_PROCESSOR_PRODUCER_GUID \ + { 0x1bf06aea, 0x5bec, 0x4a8d, {0x95, 0x76, 0x74, 0x9b, 0x09, 0x56, 0x2d, 0x30 } } + +extern EFI_GUID gEfiProcessorProducerGuid; + + +#define EFI_PROCESSOR_SUBCLASS_GUID \ + { 0x26fdeb7e, 0xb8af, 0x4ccf, {0xaa, 0x97, 0x02, 0x63, 0x3c, 0xe4, 0x8c, 0xa7 } } + +extern EFI_GUID gEfiProcessorSubClassGuid; + + +#define EFI_CACHE_SUBCLASS_GUID \ + { 0x7f0013a7, 0xdc79, 0x4b22, {0x80, 0x99, 0x11, 0xf7, 0x5f, 0xdc, 0x82, 0x9d } } + +extern EFI_GUID gEfiCacheSubClassGuid; + + +#define EFI_MEMORY_PRODUCER_GUID \ + { 0x1d7add6e, 0xb2da, 0x4b0b, {0xb2, 0x9f, 0x49, 0xcb, 0x42, 0xf4, 0x63, 0x56 } } + +extern EFI_GUID gEfiMemoryProducerGuid; + + +#define EFI_MEMORY_SUBCLASS_GUID \ + {0x4E8F4EBB, 0x64B9, 0x4e05, {0x9B, 0x18, 0x4C, 0xFE, 0x49, 0x23, 0x50, 0x97} } + +extern EFI_GUID gEfiMemorySubClassGuid; + + +#define EFI_MISC_PRODUCER_GUID \ + { 0x62512c92, 0x63c4, 0x4d80, {0x82, 0xb1, 0xc1, 0xa4, 0xdc, 0x44, 0x80, 0xe5 } } + +extern EFI_GUID gEfiMiscProducerGuid; + + +#define EFI_MISC_SUBCLASS_GUID \ + { 0x772484B2, 0x7482, 0x4b91, {0x9F, 0x9A, 0xAD, 0x43, 0xF8, 0x1C, 0x58, 0x81 } } + +extern EFI_GUID gEfiMiscSubClassGuid; + + +#endif + diff --git a/MdePkg/Include/Guid/DebugImageInfoTable.h b/MdePkg/Include/Guid/DebugImageInfoTable.h new file mode 100644 index 0000000000..f050a2e610 --- /dev/null +++ b/MdePkg/Include/Guid/DebugImageInfoTable.h @@ -0,0 +1,58 @@ +/** @file + GUID and related data structures used with the Debug Image Info Table. + + Copyright (c) 2006, 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. + + Module Name: DebugImageInfoTable.h + + @par Revision Reference: + GUID defined in UEFI 2.0 spec. + +**/ + +#ifndef __DEBUG_IMAGE_INFO_GUID_H__ +#define __DEBUG_IMAGE_INFO_GUID_H__ + +#define EFI_DEBUG_IMAGE_INFO_TABLE_GUID \ + { \ + 0x49152e77, 0x1ada, 0x4764, {0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b } \ + } + +extern EFI_GUID gEfiDebugImageInfoTableGuid; + +#define EFI_DEBUG_IMAGE_INFO_UPDATE_IN_PROGRESS 0x01 +#define EFI_DEBUG_IMAGE_INFO_TABLE_MODIFIED 0x02 +#define EFI_DEBUG_IMAGE_INFO_INITIAL_SIZE (EFI_PAGE_SIZE / sizeof (UINTN)) +#define EFI_DEBUG_IMAGE_INFO_TYPE_NORMAL 0x01 + +typedef struct { + UINT64 Signature; + EFI_PHYSICAL_ADDRESS EfiSystemTableBase; + UINT32 Crc32; +} EFI_SYSTEM_TABLE_POINTER; + +typedef struct { + UINT32 ImageInfoType; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImageProtocolInstance; + EFI_HANDLE ImageHandle; +} EFI_DEBUG_IMAGE_INFO_NORMAL; + +typedef union { + UINTN *ImageInfoType; + EFI_DEBUG_IMAGE_INFO_NORMAL *NormalImage; +} EFI_DEBUG_IMAGE_INFO; + +typedef struct { + volatile UINT32 UpdateStatus; + UINT32 TableSize; + EFI_DEBUG_IMAGE_INFO *EfiDebugImageInfoTable; +} EFI_DEBUG_IMAGE_INFO_TABLE_HEADER; + +#endif diff --git a/MdePkg/Include/Guid/DxeServices.h b/MdePkg/Include/Guid/DxeServices.h new file mode 100644 index 0000000000..70e4304a4b --- /dev/null +++ b/MdePkg/Include/Guid/DxeServices.h @@ -0,0 +1,30 @@ +/** @file + GUID used to identify the DXE Services Table + + Copyright (c) 2006, 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. + + Module Name: DxeServices.h + + @par Revision Reference: + GUID defined in DXE CIS spec version 0.91B + +**/ + +#ifndef __DXE_SERVICES_GUID_H__ +#define __DXE_SERVICES_GUID_H__ + +#define EFI_DXE_SERVICES_TABLE_GUID \ + { \ + 0x5ad34ba, 0x6f02, 0x4214, {0x95, 0x2e, 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9 } \ + } + +extern EFI_GUID gEfiDxeServicesTableGuid; + +#endif diff --git a/MdePkg/Include/Guid/EventGroup.h b/MdePkg/Include/Guid/EventGroup.h new file mode 100644 index 0000000000..f86abd4788 --- /dev/null +++ b/MdePkg/Include/Guid/EventGroup.h @@ -0,0 +1,45 @@ +/** @file + GUIDs for gBS->CreateEventEx Event Groups. Defined in EFI 2.0. + + Copyright (c) 2006, 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. + + Module Name: EventGroup.h + +**/ + +#ifndef __EVENT_GROUP_GUID__ +#define __EVENT_GROUP_GUID__ + + +#define EFI_EVENT_GROUP_EXIT_BOOT_SERVICES \ + { 0x27abf055, 0xb1b8, 0x4c26, { 0x80, 0x48, 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf } } + +extern EFI_GUID gEfiEventExitBootServicesGuid; + + +#define EFI_EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE \ + { 0x13fa7698, 0xc831, 0x49c7, { 0x87, 0xea, 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96 } } + +extern EFI_GUID gEfiEventVirtualAddressChangeGuid; + + +#define EFI_EVENT_GROUP_MEMORY_MAP_CHANGE \ + { 0x78bee926, 0x692f, 0x48fd, { 0x9e, 0xdb, 0x1, 0x42, 0x2e, 0xf0, 0xd7, 0xab } } + +extern EFI_GUID gEfiEventMemoryMapChangeGuid; + + +#define EFI_EVENT_GROUP_READY_TO_BOOT \ + { 0x7ce88fb3, 0x4bd7, 0x4679, { 0x87, 0xa8, 0xa8, 0xd8, 0xde, 0xe5, 0x0d, 0x2b } } + +extern EFI_GUID gEfiEventReadyToBootGuid; + + +#endif diff --git a/MdePkg/Include/Guid/EventLegacyBios.h b/MdePkg/Include/Guid/EventLegacyBios.h new file mode 100644 index 0000000000..6700a2d767 --- /dev/null +++ b/MdePkg/Include/Guid/EventLegacyBios.h @@ -0,0 +1,28 @@ +/** @file + GUID is the name of events used with CreateEventEx in order to be notified when the EFI boot manager is about to boot a legacy boot option. Events of this type are notificated just before Int19h is invoked. + + Copyright (c) 2006, 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. + + Module Name: EventLegacyBios.h + + @par Revision Reference: + GUIDs defined in DXE CIS 0.91b. + +**/ + +#ifndef __EVENT_LEGACY_BIOS_GUID_H__ +#define __EVENT_LEGACY_BIOS_GUID_H__ + +#define EFI_EVENT_LEGACY_BOOT_GUID \ + { 0x2a571201, 0x4966, 0x47f6, {0x8b, 0x86, 0xf3, 0x1e, 0x41, 0xf3, 0x2f, 0x10 } } + +extern EFI_GUID gEfiEventLegacyBootGuid; + +#endif diff --git a/MdePkg/Include/Guid/FirmwareFileSystem.h b/MdePkg/Include/Guid/FirmwareFileSystem.h new file mode 100644 index 0000000000..06bfa7d583 --- /dev/null +++ b/MdePkg/Include/Guid/FirmwareFileSystem.h @@ -0,0 +1,40 @@ +/** @file + Guid used to define the Firmware File System. See the Framework Firmware + File System Specification for more details. + + Copyright (c) 2006, 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. + + Module Name: FirmwareFileSystem.h + + @par Revision Reference: + Guids defined in Firmware File System Spec 0.9 + +**/ + +#ifndef __FIRMWARE_FILE_SYSTEM_GUID_H__ +#define __FIRMWARE_FILE_SYSTEM_GUID_H__ + +// +// GUIDs defined by the FFS specification. +// +#define EFI_FIRMWARE_FILE_SYSTEM_GUID \ + { \ + 0x7A9354D9, 0x0468, 0x444a, {0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF } \ + } + +#define EFI_FFS_VOLUME_TOP_FILE_GUID \ + { \ + 0x1BA0062E, 0xC779, 0x4582, {0x85, 0x66, 0x33, 0x6A, 0xE8, 0xF7, 0x8F, 0x9 } \ + } + +extern EFI_GUID gEfiFirmwareFileSystemGuid; +extern EFI_GUID gEfiFirmwareVolumeTopFileGuid; + +#endif diff --git a/MdePkg/Include/Guid/FrameworkDevicePath.h b/MdePkg/Include/Guid/FrameworkDevicePath.h new file mode 100644 index 0000000000..74c17ea625 --- /dev/null +++ b/MdePkg/Include/Guid/FrameworkDevicePath.h @@ -0,0 +1,29 @@ +/** @file + This GUID is used to define a vendor specific device path being owned by the + Framework specificaitons. + + Copyright (c) 2006, 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. + + Module Name: FrameworkDevicePath.h + + @par Revision Reference: + Spec Version 0.9 + +**/ + +#ifndef __FRAMEWORK_DEVICE_PATH_GUID_H__ +#define __FRAMEWORK_DEVICE_PATH_GUID_H__ + +#define EFI_FRAMEWORK_DEVICE_PATH_GUID \ + { 0xb7084e63, 0x46b7, 0x4d1a, { 0x86, 0x77, 0xe3, 0x0b, 0x53, 0xdb, 0xf0, 0x50 } } + +extern EFI_GUID gEfiFrameworkDevicePathGuid; + +#endif diff --git a/MdePkg/Include/Guid/GlobalVariable.h b/MdePkg/Include/Guid/GlobalVariable.h new file mode 100644 index 0000000000..4a774a5d76 --- /dev/null +++ b/MdePkg/Include/Guid/GlobalVariable.h @@ -0,0 +1,31 @@ +/** @file + GUID for EFI (NVRAM) Variables. + + Copyright (c) 2006, 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. + + Module Name: GlobalVariable.h + + @par Revision Reference: + GUID defined in UEFI 2.0 +**/ + +#ifndef __GLOBAL_VARIABLE_GUID_H__ +#define __GLOBAL_VARIABLE_GUID_H__ + +#define EFI_GLOBAL_VARIABLE_GUID \ + { \ + 0x8BE4DF61, 0x93CA, 0x11d2, {0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C } \ + } + +#define EFI_GLOBAL_VARIABLE EFI_GLOBAL_VARIABLE_GUID + +extern EFI_GUID gEfiGlobalVariableGuid; + +#endif diff --git a/MdePkg/Include/Guid/Gpt.h b/MdePkg/Include/Guid/Gpt.h new file mode 100644 index 0000000000..7124511ac5 --- /dev/null +++ b/MdePkg/Include/Guid/Gpt.h @@ -0,0 +1,45 @@ +/** @file + Guids used for the GPT (GUID Partition Table) + + GPT defines a new disk partitioning scheme and also describes + usage of the legacy Master Boot Record (MBR) partitioning scheme. + + Copyright (c) 2006, 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. + + Module Name: Gpt.h + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __GPT_GUID_H__ +#define __GPT_GUID_H__ + +#define EFI_PART_TYPE_UNUSED_GUID \ + { \ + 0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } \ + } + +#define EFI_PART_TYPE_EFI_SYSTEM_PART_GUID \ + { \ + 0xc12a7328, 0xf81f, 0x11d2, {0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b } \ + } + +#define EFI_PART_TYPE_LEGACY_MBR_GUID \ + { \ + 0x024dee41, 0x33e7, 0x11d3, {0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xf3, 0x9f } \ + } + +extern EFI_GUID gEfiPartTypeUnusedGuid; +extern EFI_GUID gEfiPartTypeSystemPartGuid; +extern EFI_GUID gEfiPartTypeLegacyMbrGuid; + +#endif diff --git a/MdePkg/Include/Guid/HobList.h b/MdePkg/Include/Guid/HobList.h new file mode 100644 index 0000000000..24932921fc --- /dev/null +++ b/MdePkg/Include/Guid/HobList.h @@ -0,0 +1,32 @@ +/** @file + GUIDs used for HOB List entries + + These GUIDs point the HOB List passed from PEI to DXE. + + Copyright (c) 2006, 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. + + Module Name: HobList.h + + @par Revision Reference: + GUID defined in DXE CIS spec version 0.91 + +**/ + +#ifndef __HOB_LIST_GUID_H__ +#define __HOB_LIST_GUID_H__ + +#define EFI_HOB_LIST_GUID \ + { \ + 0x7739f24c, 0x93d7, 0x11d4, {0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +extern EFI_GUID gEfiHobListGuid; + +#endif diff --git a/MdePkg/Include/Guid/MemoryAllocationHob.h b/MdePkg/Include/Guid/MemoryAllocationHob.h new file mode 100644 index 0000000000..140d8b8f2d --- /dev/null +++ b/MdePkg/Include/Guid/MemoryAllocationHob.h @@ -0,0 +1,36 @@ +/** @file + GUIDs for HOBs used in memory allcation + + Copyright (c) 2006, 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. + + Module Name: MemoryAllocationHob.h + + @par Revision Reference: + GUID defined in Hob Spec Version 0.9 + +**/ + +#ifndef __MEMORY_ALLOCATION_GUID_H__ +#define __MEMORY_ALLOCATION_GUID_H__ + +#define EFI_HOB_MEMORY_ALLOC_BSP_STORE_GUID \ + {0x564b33cd, 0xc92a, 0x4593, {0x90, 0xbf, 0x24, 0x73, 0xe4, 0x3c, 0x63, 0x22} }; + +#define EFI_HOB_MEMORY_ALLOC_STACK_GUID \ + {0x4ed4bf27, 0x4092, 0x42e9, {0x80, 0x7d, 0x52, 0x7b, 0x1d, 0x0, 0xc9, 0xbd} } + +#define EFI_HOB_MEMORY_ALLOC_MODULE_GUID \ + {0xf8e21975, 0x899, 0x4f58, {0xa4, 0xbe, 0x55, 0x25, 0xa9, 0xc6, 0xd7, 0x7a} } + +extern EFI_GUID gEfiHobMemoryAllocBspStoreGuid; +extern EFI_GUID gEfiHobMemoryAllocStackGuid; +extern EFI_GUID gEfiHobMemoryAllocModuleGuid; + +#endif diff --git a/MdePkg/Include/Guid/Mps.h b/MdePkg/Include/Guid/Mps.h new file mode 100644 index 0000000000..4596a3f76d --- /dev/null +++ b/MdePkg/Include/Guid/Mps.h @@ -0,0 +1,37 @@ +/** @file + GUIDs used for MPS entries in the EFI 1.0 system table + ACPI is the primary means of exporting MP information to the OS. MPS obly was + included to support Itanium-based platform power on. So don't use it if you don't have too. + + Copyright (c) 2006, 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. + + Module Name: Mps.h + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __MPS_GUID_H__ +#define __MPS_GUID_H__ + +#define EFI_MPS_TABLE_GUID \ + { \ + 0xeb9d2d2f, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +// +// GUID name defined in spec. +// +#define MPS_TABLE_GUID EFI_MPS_TABLE_GUID + +extern EFI_GUID gEfiMpsTableGuid; + +#endif diff --git a/MdePkg/Include/Guid/PcAnsi.h b/MdePkg/Include/Guid/PcAnsi.h new file mode 100644 index 0000000000..c9b74ab03e --- /dev/null +++ b/MdePkg/Include/Guid/PcAnsi.h @@ -0,0 +1,48 @@ +/** @file + Terminal Device Path Vendor Guid. + + Copyright (c) 2006, 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. + + Module Name: PcAnsi.h + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __PC_ANSI_H__ +#define __PC_ANSI_H__ + +#define EFI_PC_ANSI_GUID \ + { \ + 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_VT_100_GUID \ + { \ + 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_VT_100_PLUS_GUID \ + { \ + 0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43 } \ + } + +#define EFI_VT_UTF8_GUID \ + { \ + 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88 } \ + } + +extern EFI_GUID gEfiPcAnsiGuid; +extern EFI_GUID gEfiVT100Guid; +extern EFI_GUID gEfiVT100PlusGuid; +extern EFI_GUID gEfiVTUTF8Guid; + +#endif diff --git a/MdePkg/Include/Guid/SalSystemTable.h b/MdePkg/Include/Guid/SalSystemTable.h new file mode 100644 index 0000000000..30c830f319 --- /dev/null +++ b/MdePkg/Include/Guid/SalSystemTable.h @@ -0,0 +1,38 @@ +/** @file + GUIDs used for SAL system table entries in the EFI system table. + + SAL System Table contains Itanium-based processor centric information about + the system. + + Copyright (c) 2006, 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. + + Module Name: SalSystemTable.h + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __SAL_SYSTEM_TABLE_GUID_H__ +#define __SAL_SYSTEM_TABLE_GUID_H__ + +#define EFI_SAL_SYSTEM_TABLE_GUID \ + { \ + 0xeb9d2d32, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +// +// GUID name defined in spec. +// +#define SAL_SYSTEM_TABLE_GUID EFI_SAL_SYSTEM_TABLE_GUID + +extern EFI_GUID gEfiSalSystemTableGuid; + +#endif diff --git a/MdePkg/Include/Guid/SmBios.h b/MdePkg/Include/Guid/SmBios.h new file mode 100644 index 0000000000..f02f9fee31 --- /dev/null +++ b/MdePkg/Include/Guid/SmBios.h @@ -0,0 +1,68 @@ +/** @file + GUIDs used to locate the SMBIOS tables in the EFI 1.0 system table. + + This GUID in the system table is the only legal way to search for and + locate the SMBIOS tables. Do not search the 0xF0000 segment to find SMBIOS + tables. + + Copyright (c) 2006, 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. + + Module Name: SmBios.h + + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + +**/ + +#ifndef __SMBIOS_GUID_H__ +#define __SMBIOS_GUID_H__ + +#define EFI_SMBIOS_TABLE_GUID \ + { \ + 0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define SMBIOS_TABLE_GUID EFI_SMBIOS_TABLE_GUID + +// +// Smbios Table Entry Point Structure +// +#pragma pack(1) +typedef struct { + UINT8 AnchorString[4]; + UINT8 EntryPointStructureChecksum; + UINT8 EntryPointLength; + UINT8 MajorVersion; + UINT8 MinorVersion; + UINT16 MaxStructureSize; + UINT8 EntryPointRevision; + UINT8 FormattedArea[5]; + UINT8 IntermediateAnchorString[5]; + UINT8 IntermediateChecksum; + UINT16 TableLength; + UINT32 TableAddress; + UINT16 NumberOfSmbiosStructures; + UINT8 SmbiosBcdRevision; +} SMBIOS_TABLE_ENTRY_POINT; + +// +// The Smbios structure header +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Handle; +} SMBIOS_STRUCTURE; + +#pragma pack() + +extern EFI_GUID gEfiSmbiosTableGuid; + +#endif diff --git a/MdePkg/Include/Guid/SmmCommunicate.h b/MdePkg/Include/Guid/SmmCommunicate.h new file mode 100644 index 0000000000..2ec200b708 --- /dev/null +++ b/MdePkg/Include/Guid/SmmCommunicate.h @@ -0,0 +1,39 @@ +/** @file + Definitions EFI_SMM_COMMUNICATE_HEADER used by EFI_SMM_BASE_PROTOCOL.Communicate() functions + + Copyright (c) 2006, 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. + + Module Name: SmmCommunicate.h + + @par Revision Reference: + GUIDs defined in SmmCis spec version 0.9 + +**/ + +#ifndef __SMM_COMMUNICATE_GUID_H__ +#define __SMM_COMMUNICATE_GUID_H__ + +//****************************************************** +// EFI_SMM_COMMUNICATE_HEADER +//****************************************************** +#define SMM_COMMUNICATE_HEADER_GUID \ + { \ + 0xf328e36c, 0x23b6, 0x4a95, {0x85, 0x4b, 0x32, 0xe1, 0x95, 0x34, 0xcd, 0x75 } \ + } + +typedef struct { + EFI_GUID HeaderGuid; + UINTN MessageLength; + UINT8 Data[1]; +} EFI_SMM_COMMUNICATE_HEADER; + +extern EFI_GUID gSmmCommunicateHeaderGuid; + +#endif diff --git a/MdePkg/Include/Guid/SmramMemoryReserve.h b/MdePkg/Include/Guid/SmramMemoryReserve.h new file mode 100644 index 0000000000..fc49092b93 --- /dev/null +++ b/MdePkg/Include/Guid/SmramMemoryReserve.h @@ -0,0 +1,67 @@ +/** @file + GUID for use in reserving SMRAM regions. + + Copyright (c) 2006, 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. + + Module Name: SmramMemoryReserve.h + + @par Revision Reference: + GUIDs defined in SmmCis spec version 0.9 + +**/ + +#ifndef _EFI_SMM_PEI_SMRAM_MEMORY_RESERVE_H_ +#define _EFI_SMM_PEI_SMRAM_MEMORY_RESERVE_H_ + +#define EFI_SMM_PEI_SMRAM_MEMORY_RESERVE \ + { \ + 0x6dadf1d1, 0xd4cc, 0x4910, {0xbb, 0x6e, 0x82, 0xb1, 0xfd, 0x80, 0xff, 0x3d } \ + } + +// +// ******************************************************* +// EFI_SMRAM_DESCRIPTOR +// ******************************************************* +// +typedef struct { + EFI_PHYSICAL_ADDRESS PhysicalStart; // Phsyical location in DRAM + EFI_PHYSICAL_ADDRESS CpuStart; // Address CPU uses to access the SMI handler + // May or may not match PhysicalStart + // + UINT64 PhysicalSize; + UINT64 RegionState; +} EFI_SMRAM_DESCRIPTOR; + +// +// ******************************************************* +// EFI_SMRAM_STATE +// ******************************************************* +// +#define EFI_SMRAM_OPEN 0x00000001 +#define EFI_SMRAM_CLOSED 0x00000002 +#define EFI_SMRAM_LOCKED 0x00000004 +#define EFI_CACHEABLE 0x00000008 +#define EFI_ALLOCATED 0x00000010 +#define EFI_NEEDS_TESTING 0x00000020 +#define EFI_NEEDS_ECC_INITIALIZATION 0x00000040 + +// +// ******************************************************* +// EFI_SMRAM_HOB_DESCRIPTOR_BLOCK +// ******************************************************* +// +typedef struct { + UINTN NumberOfSmmReservedRegions; + EFI_SMRAM_DESCRIPTOR Descriptor[1]; +} EFI_SMRAM_HOB_DESCRIPTOR_BLOCK; + +extern EFI_GUID gEfiSmmPeiSmramMemoryReserve; + +#endif diff --git a/MdePkg/Include/Guid/StatusCodeDataTypeId.h b/MdePkg/Include/Guid/StatusCodeDataTypeId.h new file mode 100644 index 0000000000..f747af07f7 --- /dev/null +++ b/MdePkg/Include/Guid/StatusCodeDataTypeId.h @@ -0,0 +1,82 @@ +/** @file + GUID used to identify id for the caller who is initiating the Status Code. + + Copyright (c) 2006, 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. + + Module Name: StatusCodeDataTypeId.h + + @par Revision Reference: + GUIDs defined in Status Codes Specification 0.92 + +**/ + +#ifndef __STATUS_CODE_DATA_TYPE_ID_GUID_H__ +#define __STATUS_CODE_DATA_TYPE_ID_GUID_H__ + +// +// String Data Type defintion. This is part of Status Code Specification +// +#define EFI_STATUS_CODE_DATA_TYPE_STRING_GUID \ + { 0x92D11080, 0x496F, 0x4D95, { 0xBE, 0x7E, 0x03, 0x74, 0x88, 0x38, 0x2B, 0x0A } } + +extern EFI_GUID gEfiStatusCodeDataTypeStringGuid; + +// +// This GUID indicates that the format of the accompanying data depends +// upon the Status Code Value, but follows this Specification +// +#define EFI_STATUS_CODE_SPECIFIC_DATA_GUID \ + { 0x335984bd, 0xe805, 0x409a, { 0xb8, 0xf8, 0xd2, 0x7e, 0xce, 0x5f, 0xf7, 0xa6 } } + +extern EFI_GUID gEfiStatusCodeSpecificDataGuid; + +// +// Debug Assert Data. This is part of Status Code Specification +// +#define EFI_STATUS_CODE_DATA_TYPE_ASSERT_GUID \ + { 0xDA571595, 0x4D99, 0x487C, { 0x82, 0x7C, 0x26, 0x22, 0x67, 0x7D, 0x33, 0x07 } } + + +extern EFI_GUID gEfiStatusCodeDataTypeAssertGuid; + +// +// Exception Data type (CPU REGS) +// +#define EFI_STATUS_CODE_DATA_TYPE_EXCEPTION_HANDLER_GUID \ + { 0x3BC2BD12, 0xAD2E, 0x11D5, { 0x87, 0xDD, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xB9 } } + +extern EFI_GUID gEfiStatusCodeDataTypeExceptionHandlerGuid; + +// +// Debug DataType defintions. User Defined Data Types. +// +#define EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID \ + { 0x9A4E9246, 0xD553, 0x11D5, { 0x87, 0xE2, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xb9 } } + +extern EFI_GUID gEfiStatusCodeDataTypeDebugGuid; + +// +// Progress Code. User Defined Data Type Guid. +// +#define EFI_STATUS_CODE_DATA_TYPE_ERROR_GUID \ + 0xAB359CE3, 0x99B3, 0xAE18, { 0xC8, 0x9D, 0x95, 0xD3, 0xB0, 0x72, 0xE1, 0x9B } } + +extern EFI_GUID gEfiStatusCodeDataTypeErrorGuid; + + +// +// Progress Code. User Defined Data Type Guid. +// +#define EFI_STATUS_CODE_DATA_TYPE_PROGRESS_CODE_GUID \ + { 0xA356AB39, 0x35C4, 0x35DA, { 0xB3, 0x7A, 0xF8, 0xEA, 0x9E, 0x8B, 0x36, 0xA3 } } + +extern EFI_GUID gEfiStatusCodeDataTypeProgressCodeGuid; + +#endif diff --git a/MdePkg/Include/Ia32/ProcessorBind.h b/MdePkg/Include/Ia32/ProcessorBind.h new file mode 100644 index 0000000000..587d8a69ab --- /dev/null +++ b/MdePkg/Include/Ia32/ProcessorBind.h @@ -0,0 +1,167 @@ +/** @file + Processor or Compiler specific defines and types for x64. + + Copyright (c) 2006, 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. + + Module Name: ProcessorBind.h + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +// +// Define the processor type so other code can make processor based choices +// +#define MDE_CPU_IA32 + +// +// Make sure we are useing the correct packing rules per EFI specification +// +#ifndef __GNUC__ +#pragma pack() +#endif + +#if _MSC_EXTENSIONS + +// +// Disable warning that make it impossible to compile at /W4 +// This only works for Microsoft* tools +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning +// +#pragma warning ( disable : 4127 ) + + +#endif + + +#if !defined(__GNUC__) && (__STDC_VERSION__ < 199901L) + // + // No ANSI C 2000 stdint.h integer width declarations, so define equivalents + // + + #if _MSC_EXTENSIONS + + // + // use Microsoft* C complier dependent interger width types + // + typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int32 UINT32; + typedef __int32 INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #else + + // + // Assume standard IA-32 alignment. + // BugBug: Need to check portability of long long + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #endif + + #define UINT8_MAX 0xff + +#else + // + // Use ANSI C 2000 stdint.h integer width declarations + // + #include "stdint.h" + typedef uint8_t BOOLEAN; + typedef int8_t INT8; + typedef uint8_t UINT8; + typedef int16_t INT16; + typedef uint16_t UINT16; + typedef int32_t INT32; + typedef uint32_t UINT32; + typedef int64_t INT64; + typedef uint64_t UINT64; + typedef char CHAR8; + typedef uint16_t CHAR16; + +#endif + +typedef UINT32 UINTN; +typedef INT32 INTN; + + +// +// Processor specific defines +// +#define MAX_BIT 0x80000000 +#define MAX_2_BITS 0xC0000000 + +// +// Maximum legal IA-32 address +// +#define MAX_ADDRESS 0xFFFFFFFF + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify thier member functions with EFIAPI. +// +#if _MSC_EXTENSIONS + // + // Microsoft* compiler requires _EFIAPI useage, __cdecl is Microsoft* specific C. + // + #define EFIAPI __cdecl +#endif + +#if __GNUC__ + #define EFIAPI __attribute__((cdecl)) +#endif + +// +// The Microsoft* C compiler can removed references to unreferenced data items +// if the /OPT:REF linker option is used. We defined a macro as this is a +// a non standard extension +// +#if _MSC_EXTENSIONS + #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany) +#else + #define GLOBAL_REMOVE_IF_UNREFERENCED +#endif + +#endif diff --git a/MdePkg/Include/IndustryStandard/Acpi.h b/MdePkg/Include/IndustryStandard/Acpi.h new file mode 100644 index 0000000000..d2fe3459c2 --- /dev/null +++ b/MdePkg/Include/IndustryStandard/Acpi.h @@ -0,0 +1,91 @@ +/** @file + This file contains some basic ACPI definitions that are consumed by drivers + that do not care about ACPI versions. + + Copyright (c) 2006, 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. + + Module Name: Acpi.h + +**/ + +#ifndef _ACPI_H_ +#define _ACPI_H_ + +// +// Common table header, this prefaces all ACPI tables, including FACS, but +// excluding the RSD PTR structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_COMMON_HEADER; + +// +// Common ACPI description table header. This structure prefaces most ACPI tables. +// +#pragma pack(1) + +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT8 Revision; + UINT8 Checksum; + UINT8 OemId[6]; + UINT64 OemTableId; + UINT32 OemRevision; + UINT32 CreatorId; + UINT32 CreatorRevision; +} EFI_ACPI_DESCRIPTION_HEADER; + +#pragma pack() +// +// Define for Pci Host Bridge Resource Allocation +// +#define ACPI_ADDRESS_SPACE_DESCRIPTOR 0x8A +#define ACPI_END_TAG_DESCRIPTOR 0x79 + +#define ACPI_ADDRESS_SPACE_TYPE_MEM 0x00 +#define ACPI_ADDRESS_SPACE_TYPE_IO 0x01 +#define ACPI_ADDRESS_SPACE_TYPE_BUS 0x02 + +// +// Make sure structures match spec +// +#pragma pack(1) + +typedef struct { + UINT8 Desc; + UINT16 Len; + UINT8 ResType; + UINT8 GenFlag; + UINT8 SpecificFlag; + UINT64 AddrSpaceGranularity; + UINT64 AddrRangeMin; + UINT64 AddrRangeMax; + UINT64 AddrTranslationOffset; + UINT64 AddrLen; +} EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR; + +typedef struct { + UINT8 Desc; + UINT8 Checksum; +} EFI_ACPI_END_TAG_DESCRIPTOR; + +// +// General use definitions +// +#define EFI_ACPI_RESERVED_BYTE 0x00 +#define EFI_ACPI_RESERVED_WORD 0x0000 +#define EFI_ACPI_RESERVED_DWORD 0x00000000 +#define EFI_ACPI_RESERVED_QWORD 0x0000000000000000 + +#pragma pack() + +#endif diff --git a/MdePkg/Include/IndustryStandard/Usb.h b/MdePkg/Include/IndustryStandard/Usb.h new file mode 100644 index 0000000000..dca7351ff1 --- /dev/null +++ b/MdePkg/Include/IndustryStandard/Usb.h @@ -0,0 +1,282 @@ +/** @file + Support for USB 1.1 standard. + + Copyright (c) 2006, 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. + + Module Name: Usb.h + +**/ + +#ifndef __USB_H__ +#define __USB_H__ + +// +// USB Descriptor types +// +#define USB_DT_DEVICE 0x01 +#define USB_DT_CONFIG 0x02 +#define USB_DT_STRING 0x03 +#define USB_DT_INTERFACE 0x04 +#define USB_DT_ENDPOINT 0x05 +#define USB_DT_HUB 0x29 +#define USB_DT_HID 0x21 + +// +// USB request type +// +#define USB_TYPE_STANDARD (0x00 << 5) +#define USB_TYPE_CLASS (0x01 << 5) +#define USB_TYPE_VENDOR (0x02 << 5) +#define USB_TYPE_RESERVED (0x03 << 5) + +// +// USB request targer device +// +#define USB_RECIP_DEVICE 0x00 +#define USB_RECIP_INTERFACE 0x01 +#define USB_RECIP_ENDPOINT 0x02 +#define USB_RECIP_OTHER 0x03 + +// +// Request target types. +// +#define USB_RT_DEVICE 0x00 +#define USB_RT_INTERFACE 0x01 +#define USB_RT_ENDPOINT 0x02 +#define USB_RT_HUB (USB_TYPE_CLASS | USB_RECIP_DEVICE) +#define USB_RT_PORT (USB_TYPE_CLASS | USB_RECIP_OTHER) + +// +// USB Transfer Results +// +#define EFI_USB_NOERROR 0x00 +#define EFI_USB_ERR_NOTEXECUTE 0x01 +#define EFI_USB_ERR_STALL 0x02 +#define EFI_USB_ERR_BUFFER 0x04 +#define EFI_USB_ERR_BABBLE 0x08 +#define EFI_USB_ERR_NAK 0x10 +#define EFI_USB_ERR_CRC 0x20 +#define EFI_USB_ERR_TIMEOUT 0x40 +#define EFI_USB_ERR_BITSTUFF 0x80 +#define EFI_USB_ERR_SYSTEM 0x100 + +// +//Use 200 ms to increase the error handling response time +// +#define EFI_USB_INTERRUPT_DELAY 2000000 + +// +// USB transation direction +// +typedef enum { + EfiUsbDataOut, + EfiUsbDataIn, + EfiUsbNoData +} EFI_USB_DATA_DIRECTION; + +// +// Usb Data recipient type +// +typedef enum { + EfiUsbDevice, + EfiUsbInterface, + EfiUsbEndpoint +} EFI_USB_RECIPIENT; + +typedef enum { + EfiUsbEndpointHalt, + EfiUsbDeviceRemoteWakeup +} EFI_USB_STANDARD_FEATURE_SELECTOR; + +#pragma pack(1) +// +// Usb device request structure +// +typedef struct { + UINT8 RequestType; + UINT8 Request; + UINT16 Value; + UINT16 Index; + UINT16 Length; +} EFI_USB_DEVICE_REQUEST; + +// +// Standard USB request +// +#define USB_DEV_GET_STATUS 0x00 + +#define USB_DEV_CLEAR_FEATURE 0x01 + +#define USB_DEV_SET_FEATURE 0x03 + +#define USB_DEV_SET_ADDRESS 0x05 +#define USB_DEV_SET_ADDRESS_REQ_TYPE 0x00 + +#define USB_DEV_GET_DESCRIPTOR 0x06 +#define USB_DEV_GET_DESCRIPTOR_REQ_TYPE 0x80 + +#define USB_DEV_SET_DESCRIPTOR 0x07 +#define USB_DEV_SET_DESCRIPTOR_REQ_TYPE 0x00 + +#define USB_DEV_GET_CONFIGURATION 0x08 +#define USB_DEV_GET_CONFIGURATION_REQ_TYPE 0x80 + +#define USB_DEV_SET_CONFIGURATION 0x09 +#define USB_DEV_SET_CONFIGURATION_REQ_TYPE 0x00 + +#define USB_DEV_GET_INTERFACE 0x0A +#define USB_DEV_GET_INTERFACE_REQ_TYPE 0x81 + +#define USB_DEV_SET_INTERFACE 0x0B +#define USB_DEV_SET_INTERFACE_REQ_TYPE 0x01 + +#define USB_DEV_SYNCH_FRAME 0x0C +#define USB_DEV_SYNCH_FRAME_REQ_TYPE 0x82 + +// +// Device descriptor. refer USB1.1 +// +typedef struct usb_device_descriptor { + UINT8 Length; + UINT8 DescriptorType; + UINT16 BcdUSB; + UINT8 DeviceClass; + UINT8 DeviceSubClass; + UINT8 DeviceProtocol; + UINT8 MaxPacketSize0; + UINT16 IdVendor; + UINT16 IdProduct; + UINT16 BcdDevice; + UINT8 StrManufacturer; + UINT8 StrProduct; + UINT8 StrSerialNumber; + UINT8 NumConfigurations; +} EFI_USB_DEVICE_DESCRIPTOR; + +// +// Endpoint descriptor +// +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + UINT8 EndpointAddress; + UINT8 Attributes; + UINT16 MaxPacketSize; + UINT8 Interval; +} EFI_USB_ENDPOINT_DESCRIPTOR; + +// +// Interface descriptor +// +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + UINT8 InterfaceNumber; + UINT8 AlternateSetting; + UINT8 NumEndpoints; + UINT8 InterfaceClass; + UINT8 InterfaceSubClass; + UINT8 InterfaceProtocol; + UINT8 Interface; +} EFI_USB_INTERFACE_DESCRIPTOR; + +// +// USB alternate setting +// +typedef struct { + EFI_USB_INTERFACE_DESCRIPTOR *Interface; +} USB_ALT_SETTING; + +// +// Configuration descriptor +// +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + UINT16 TotalLength; + UINT8 NumInterfaces; + UINT8 ConfigurationValue; + UINT8 Configuration; + UINT8 Attributes; + UINT8 MaxPower; +} EFI_USB_CONFIG_DESCRIPTOR; + +// +// Supported String Languages +// +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + UINT16 SupportedLanID[1]; +} EFI_USB_SUPPORTED_LANGUAGES; + +// +// String descriptor +// +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + CHAR16 String[1]; +} EFI_USB_STRING_DESCRIPTOR; + +// +// Hub descriptor +// +#define MAXBYTES 8 +typedef struct { + UINT8 Length; + UINT8 DescriptorType; + UINT8 NbrPorts; + UINT8 HubCharacteristics[2]; + UINT8 PwrOn2PwrGood; + UINT8 HubContrCurrent; + UINT8 Filler[MAXBYTES]; +} EFI_USB_HUB_DESCRIPTOR; + +typedef struct { + UINT16 PortStatus; + UINT16 PortChangeStatus; +} EFI_USB_PORT_STATUS; + +// +// Constant value for Port Status & Port Change Status +// +#define USB_PORT_STAT_CONNECTION 0x0001 +#define USB_PORT_STAT_ENABLE 0x0002 +#define USB_PORT_STAT_SUSPEND 0x0004 +#define USB_PORT_STAT_OVERCURRENT 0x0008 +#define USB_PORT_STAT_RESET 0x0010 +#define USB_PORT_STAT_POWER 0x0100 +#define USB_PORT_STAT_LOW_SPEED 0x0200 + +#define USB_PORT_STAT_C_CONNECTION 0x0001 +#define USB_PORT_STAT_C_ENABLE 0x0002 +#define USB_PORT_STAT_C_SUSPEND 0x0004 +#define USB_PORT_STAT_C_OVERCURRENT 0x0008 +#define USB_PORT_STAT_C_RESET 0x0010 + +// +// Used for set/clear port feature request +// +typedef enum { + EfiUsbPortEnable = 1, + EfiUsbPortSuspend = 2, + EfiUsbPortReset = 4, + EfiUsbPortPower = 8, + EfiUsbPortConnectChange = 16, + EfiUsbPortEnableChange = 17, + EfiUsbPortSuspendChange = 18, + EfiUsbPortOverCurrentChange = 19, + EfiUsbPortResetChange = 20 +} EFI_USB_PORT_FEATURE; + +#pragma pack() + +#endif diff --git a/MdePkg/Include/IndustryStandard/pci22.h b/MdePkg/Include/IndustryStandard/pci22.h new file mode 100644 index 0000000000..7fee279e80 --- /dev/null +++ b/MdePkg/Include/IndustryStandard/pci22.h @@ -0,0 +1,481 @@ +/** @file + Support for PCI 2.2 standard. + + Copyright (c) 2006, 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. + + Module Name: pci22.h + +**/ + +#ifndef _PCI22_H +#define _PCI22_H + +#define PCI_MAX_SEGMENT 0 + +#define PCI_MAX_BUS 255 + +#define PCI_MAX_DEVICE 31 +#define PCI_MAX_FUNC 7 + +// +// Command +// +#define PCI_VGA_PALETTE_SNOOP_DISABLED 0x20 + +#pragma pack(push, 1) +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Command; + UINT16 Status; + UINT8 RevisionID; + UINT8 ClassCode[3]; + UINT8 CacheLineSize; + UINT8 LatencyTimer; + UINT8 HeaderType; + UINT8 BIST; +} PCI_DEVICE_INDEPENDENT_REGION; + +typedef struct { + UINT32 Bar[6]; + UINT32 CISPtr; + UINT16 SubsystemVendorID; + UINT16 SubsystemID; + UINT32 ExpansionRomBar; + UINT8 CapabilityPtr; + UINT8 Reserved1[3]; + UINT32 Reserved2; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT8 MinGnt; + UINT8 MaxLat; +} PCI_DEVICE_HEADER_TYPE_REGION; + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_DEVICE_HEADER_TYPE_REGION Device; +} PCI_TYPE00; + +typedef struct { + UINT32 Bar[2]; + UINT8 PrimaryBus; + UINT8 SecondaryBus; + UINT8 SubordinateBus; + UINT8 SecondaryLatencyTimer; + UINT8 IoBase; + UINT8 IoLimit; + UINT16 SecondaryStatus; + UINT16 MemoryBase; + UINT16 MemoryLimit; + UINT16 PrefetchableMemoryBase; + UINT16 PrefetchableMemoryLimit; + UINT32 PrefetchableBaseUpper32; + UINT32 PrefetchableLimitUpper32; + UINT16 IoBaseUpper16; + UINT16 IoLimitUpper16; + UINT8 CapabilityPtr; + UINT8 Reserved[3]; + UINT32 ExpansionRomBAR; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT16 BridgeControl; +} PCI_BRIDGE_CONTROL_REGISTER; + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_BRIDGE_CONTROL_REGISTER Bridge; +} PCI_TYPE01; + +typedef union { + PCI_TYPE00 Device; + PCI_TYPE01 Bridge; +} PCI_TYPE_GENERIC; + +typedef struct { + UINT32 CardBusSocketReg; // Cardus Socket/ExCA Base + // Address Register + // + UINT16 Reserved; + UINT16 SecondaryStatus; // Secondary Status + UINT8 PciBusNumber; // PCI Bus Number + UINT8 CardBusBusNumber; // CardBus Bus Number + UINT8 SubordinateBusNumber; // Subordinate Bus Number + UINT8 CardBusLatencyTimer; // CardBus Latency Timer + UINT32 MemoryBase0; // Memory Base Register 0 + UINT32 MemoryLimit0; // Memory Limit Register 0 + UINT32 MemoryBase1; + UINT32 MemoryLimit1; + UINT32 IoBase0; + UINT32 IoLimit0; // I/O Base Register 0 + UINT32 IoBase1; // I/O Limit Register 0 + UINT32 IoLimit1; + UINT8 InterruptLine; // Interrupt Line + UINT8 InterruptPin; // Interrupt Pin + UINT16 BridgeControl; // Bridge Control +} PCI_CARDBUS_CONTROL_REGISTER; + +// +// Definitions of PCI class bytes and manipulation macros. +// +#define PCI_CLASS_OLD 0x00 +#define PCI_CLASS_OLD_OTHER 0x00 +#define PCI_CLASS_OLD_VGA 0x01 + +#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_CLASS_MASS_STORAGE_SCSI 0x00 +#define PCI_CLASS_MASS_STORAGE_IDE 0x01 // obsolete +#define PCI_CLASS_IDE 0x01 +#define PCI_CLASS_MASS_STORAGE_FLOPPY 0x02 +#define PCI_CLASS_MASS_STORAGE_IPI 0x03 +#define PCI_CLASS_MASS_STORAGE_RAID 0x04 +#define PCI_CLASS_MASS_STORAGE_OTHER 0x80 + +#define PCI_CLASS_NETWORK 0x02 +#define PCI_CLASS_NETWORK_ETHERNET 0x00 +#define PCI_CLASS_ETHERNET 0x00 // obsolete +#define PCI_CLASS_NETWORK_TOKENRING 0x01 +#define PCI_CLASS_NETWORK_FDDI 0x02 +#define PCI_CLASS_NETWORK_ATM 0x03 +#define PCI_CLASS_NETWORK_ISDN 0x04 +#define PCI_CLASS_NETWORK_OTHER 0x80 + +#define PCI_CLASS_DISPLAY 0x03 +#define PCI_CLASS_DISPLAY_CTRL 0x03 // obsolete +#define PCI_CLASS_DISPLAY_VGA 0x00 +#define PCI_CLASS_VGA 0x00 // obsolete +#define PCI_CLASS_DISPLAY_XGA 0x01 +#define PCI_CLASS_DISPLAY_3D 0x02 +#define PCI_CLASS_DISPLAY_OTHER 0x80 +#define PCI_CLASS_DISPLAY_GFX 0x80 +#define PCI_CLASS_GFX 0x80 // obsolete +#define PCI_CLASS_BRIDGE 0x06 +#define PCI_CLASS_BRIDGE_HOST 0x00 +#define PCI_CLASS_BRIDGE_ISA 0x01 +#define PCI_CLASS_ISA 0x01 // obsolete +#define PCI_CLASS_BRIDGE_EISA 0x02 +#define PCI_CLASS_BRIDGE_MCA 0x03 +#define PCI_CLASS_BRIDGE_P2P 0x04 +#define PCI_CLASS_BRIDGE_PCMCIA 0x05 +#define PCI_CLASS_BRIDGE_NUBUS 0x06 +#define PCI_CLASS_BRIDGE_CARDBUS 0x07 +#define PCI_CLASS_BRIDGE_RACEWAY 0x08 +#define PCI_CLASS_BRIDGE_ISA_PDECODE 0x80 +#define PCI_CLASS_ISA_POSITIVE_DECODE 0x80 // obsolete +#define PCI_CLASS_SERIAL 0x0C +#define PCI_CLASS_SERIAL_FIREWIRE 0x00 +#define PCI_CLASS_SERIAL_ACCESS_BUS 0x01 +#define PCI_CLASS_SERIAL_SSA 0x02 +#define PCI_CLASS_SERIAL_USB 0x03 +#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04 +#define PCI_CLASS_SERIAL_SMB 0x05 + +#define IS_CLASS1(_p, c) ((_p)->Hdr.ClassCode[2] == (c)) +#define IS_CLASS2(_p, c, s) (IS_CLASS1 (_p, c) && ((_p)->Hdr.ClassCode[1] == (s))) +#define IS_CLASS3(_p, c, s, p) (IS_CLASS2 (_p, c, s) && ((_p)->Hdr.ClassCode[0] == (p))) + +#define IS_PCI_DISPLAY(_p) IS_CLASS1 (_p, PCI_CLASS_DISPLAY) +#define IS_PCI_VGA(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 0) +#define IS_PCI_8514(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 1) +#define IS_PCI_GFX(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_GFX, 0) +#define IS_PCI_OLD(_p) IS_CLASS1 (_p, PCI_CLASS_OLD) +#define IS_PCI_OLD_VGA(_p) IS_CLASS2 (_p, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) +#define IS_PCI_IDE(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_IDE) +#define IS_PCI_SCSI(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SCSI, 0) +#define IS_PCI_RAID(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_RAID, 0) +#define IS_PCI_LPC(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA, 0) +#define IS_PCI_P2P(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 0) +#define IS_PCI_P2P_SUB(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 1) +#define IS_PCI_USB(_p) IS_CLASS2 (_p, PCI_CLASS_SERIAL, PCI_CLASS_SERIAL_USB) + +#define HEADER_TYPE_DEVICE 0x00 +#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01 +#define HEADER_TYPE_CARDBUS_BRIDGE 0x02 + +#define HEADER_TYPE_MULTI_FUNCTION 0x80 +#define HEADER_LAYOUT_CODE 0x7f + +#define IS_PCI_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_PCI_TO_PCI_BRIDGE)) +#define IS_CARDBUS_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) +#define IS_PCI_MULTI_FUNC(_p) ((_p)->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) + +#define PCI_DEVICE_ROMBAR 0x30 +#define PCI_BRIDGE_ROMBAR 0x38 + +#define PCI_MAX_BAR 6 +#define PCI_MAX_CONFIG_OFFSET 0x100 +// +// bugbug: this is supported in PCI spec v2.3 +// +#define PCI_EXP_MAX_CONFIG_OFFSET 0x1000 + +#define PCI_VENDOR_ID_OFFSET 0x00 +#define PCI_DEVICE_ID_OFFSET 0x02 +#define PCI_COMMAND_OFFSET 0x04 +#define PCI_PRIMARY_STATUS_OFFSET 0x06 +#define PCI_REVISION_ID_OFFSET 0x08 +#define PCI_CLASSCODE_OFFSET 0x09 +#define PCI_CACHELINE_SIZE_OFFSET 0x0C +#define PCI_LATENCY_TIMER_OFFSET 0x0D +#define PCI_HEADER_TYPE_OFFSET 0x0E +#define PCI_BIST_OFFSET 0x0F + +#define PCI_BRIDGE_CONTROL_REGISTER_OFFSET 0x3E +#define PCI_BRIDGE_STATUS_REGISTER_OFFSET 0x1E + +#define PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET 0x18 +#define PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET 0x19 +#define PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET 0x1a + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT8 Reserved[4]; +} DEFIO_PCI_ADDR; + +typedef union { + struct { + UINT32 Reg : 8; + UINT32 Func : 3; + UINT32 Dev : 5; + UINT32 Bus : 8; + UINT32 Reserved : 7; + UINT32 Enable : 1; + } Bits; + UINT32 Uint32; +} PCI_CONFIG_ACCESS_CF8; + +#pragma pack() + +#define EFI_ROOT_BRIDGE_LIST 'eprb' +#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55 +#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1 +#define PCI_DATA_STRUCTURE_SIGNATURE EFI_SIGNATURE_32 ('P', 'C', 'I', 'R') +#define PCI_CODE_TYPE_PCAT_IMAGE 0x00 +#define PCI_CODE_TYPE_EFI_IMAGE 0x03 +#define EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED 0x0001 + +#define EFI_PCI_COMMAND_IO_SPACE 0x0001 +#define EFI_PCI_COMMAND_MEMORY_SPACE 0x0002 +#define EFI_PCI_COMMAND_BUS_MASTER 0x0004 +#define EFI_PCI_COMMAND_SPECIAL_CYCLE 0x0008 +#define EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE 0x0010 +#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP 0x0020 +#define EFI_PCI_COMMAND_PARITY_ERROR_RESPOND 0x0040 +#define EFI_PCI_COMMAND_STEPPING_CONTROL 0x0080 +#define EFI_PCI_COMMAND_SERR 0x0100 +#define EFI_PCI_COMMAND_FAST_BACK_TO_BACK 0x0200 + +#define EFI_PCI_BRIDGE_CONTROL_PARITY_ERROR_RESPONSE 0x0001 +#define EFI_PCI_BRIDGE_CONTROL_SERR 0x0002 +#define EFI_PCI_BRIDGE_CONTROL_ISA 0x0004 +#define EFI_PCI_BRIDGE_CONTROL_VGA 0x0008 +#define EFI_PCI_BRIDGE_CONTROL_VGA_16 0x0010 +#define EFI_PCI_BRIDGE_CONTROL_MASTER_ABORT 0x0020 +#define EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS 0x0040 +#define EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK 0x0080 +#define EFI_PCI_BRIDGE_CONTROL_PRIMARY_DISCARD_TIMER 0x0100 +#define EFI_PCI_BRIDGE_CONTROL_SECONDARY_DISCARD_TIMER 0x0200 +#define EFI_PCI_BRIDGE_CONTROL_TIMER_STATUS 0x0400 +#define EFI_PCI_BRIDGE_CONTROL_DISCARD_TIMER_SERR 0x0800 + +// +// Following are the PCI-CARDBUS bridge control bit +// +#define EFI_PCI_BRIDGE_CONTROL_IREQINT_ENABLE 0x0080 +#define EFI_PCI_BRIDGE_CONTROL_RANGE0_MEMORY_TYPE 0x0100 +#define EFI_PCI_BRIDGE_CONTROL_RANGE1_MEMORY_TYPE 0x0200 +#define EFI_PCI_BRIDGE_CONTROL_WRITE_POSTING_ENABLE 0x0400 + +// +// Following are the PCI status control bit +// +#define EFI_PCI_STATUS_CAPABILITY 0x0010 +#define EFI_PCI_STATUS_66MZ_CAPABLE 0x0020 +#define EFI_PCI_FAST_BACK_TO_BACK_CAPABLE 0x0080 +#define EFI_PCI_MASTER_DATA_PARITY_ERROR 0x0100 + +#define EFI_PCI_CAPABILITY_PTR 0x34 +#define EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR 0x14 + +#pragma pack(1) +typedef struct { + UINT16 Signature; // 0xaa55 + UINT8 Reserved[0x16]; + UINT16 PcirOffset; +} PCI_EXPANSION_ROM_HEADER; + +typedef struct { + UINT16 Signature; // 0xaa55 + UINT16 InitializationSize; + UINT32 EfiSignature; // 0x0EF1 + UINT16 EfiSubsystem; + UINT16 EfiMachineType; + UINT16 CompressionType; + UINT8 Reserved[8]; + UINT16 EfiImageHeaderOffset; + UINT16 PcirOffset; +} EFI_PCI_EXPANSION_ROM_HEADER; + +typedef struct { + UINT16 Signature; // 0xaa55 + UINT8 Size512; + UINT8 Reserved[15]; + UINT16 PcirOffset; +} EFI_LEGACY_EXPANSION_ROM_HEADER; + +typedef union { + UINT8 *Raw; + PCI_EXPANSION_ROM_HEADER *Generic; + EFI_PCI_EXPANSION_ROM_HEADER *Efi; + EFI_LEGACY_EXPANSION_ROM_HEADER *PcAt; +} EFI_PCI_ROM_HEADER; + +typedef struct { + UINT32 Signature; // "PCIR" + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Reserved0; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 Reserved1; +} PCI_DATA_STRUCTURE; + +// +// PCI Capability List IDs and records +// +#define EFI_PCI_CAPABILITY_ID_PMI 0x01 +#define EFI_PCI_CAPABILITY_ID_AGP 0x02 +#define EFI_PCI_CAPABILITY_ID_VPD 0x03 +#define EFI_PCI_CAPABILITY_ID_SLOTID 0x04 +#define EFI_PCI_CAPABILITY_ID_MSI 0x05 +#define EFI_PCI_CAPABILITY_ID_HOTPLUG 0x06 +#define EFI_PCI_CAPABILITY_ID_PCIX 0x07 +// +// bugbug: this ID is defined in PCI spec v2.3 +// +#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10 + +typedef struct { + UINT8 CapabilityID; + UINT8 NextItemPtr; +} EFI_PCI_CAPABILITY_HDR; + +// +// Capability EFI_PCI_CAPABILITY_ID_PMI +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 PMC; + UINT16 PMCSR; + UINT8 BridgeExtention; + UINT8 Data; +} EFI_PCI_CAPABILITY_PMI; + +// +// Capability EFI_PCI_CAPABILITY_ID_AGP +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT8 Rev; + UINT8 Reserved; + UINT32 Status; + UINT32 Command; +} EFI_PCI_CAPABILITY_AGP; + +// +// Capability EFI_PCI_CAPABILITY_ID_VPD +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 AddrReg; + UINT32 DataReg; +} EFI_PCI_CAPABILITY_VPD; + +// +// Capability EFI_PCI_CAPABILITY_ID_SLOTID +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT8 ExpnsSlotReg; + UINT8 ChassisNo; +} EFI_PCI_CAPABILITY_SLOTID; + +// +// Capability EFI_PCI_CAPABILITY_ID_MSI +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 MsgCtrlReg; + UINT32 MsgAddrReg; + UINT16 MsgDataReg; +} EFI_PCI_CAPABILITY_MSI32; + +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 MsgCtrlReg; + UINT32 MsgAddrRegLsdw; + UINT32 MsgAddrRegMsdw; + UINT16 MsgDataReg; +} EFI_PCI_CAPABILITY_MSI64; + +// +// Capability EFI_PCI_CAPABILITY_ID_HOTPLUG +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + // + // not finished - fields need to go here + // +} EFI_PCI_CAPABILITY_HOTPLUG; + +// +// Capability EFI_PCI_CAPABILITY_ID_PCIX +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 CommandReg; + UINT32 StatusReg; +} EFI_PCI_CAPABILITY_PCIX; + +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 SecStatusReg; + UINT32 StatusReg; + UINT32 SplitTransCtrlRegUp; + UINT32 SplitTransCtrlRegDn; +} EFI_PCI_CAPABILITY_PCIX_BRDG; + +#define DEVICE_ID_NOCARE 0xFFFF + +#define PCI_ACPI_UNUSED 0 +#define PCI_BAR_NOCHANGE 0 +#define PCI_BAR_OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL +#define PCI_BAR_EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL +#define PCI_BAR_SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL +#define PCI_BAR_DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL + +#define PCI_BAR_IDX0 0x00 +#define PCI_BAR_IDX1 0x01 +#define PCI_BAR_IDX2 0x02 +#define PCI_BAR_IDX3 0x03 +#define PCI_BAR_IDX4 0x04 +#define PCI_BAR_IDX5 0x05 +#define PCI_BAR_ALL 0xFF + +#pragma pack(pop) + +#endif diff --git a/MdePkg/Include/IndustryStandard/scsi.h b/MdePkg/Include/IndustryStandard/scsi.h new file mode 100644 index 0000000000..41023094f5 --- /dev/null +++ b/MdePkg/Include/IndustryStandard/scsi.h @@ -0,0 +1,282 @@ +/** @file + support for SCSI standard + + Copyright (c) 2006, 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. + + Module Name: scsi.h + +**/ + +#ifndef _SCSI_H +#define _SCSI_H + +// +// SCSI command OP Code +// +// +// Commands for all device types +// +#define EFI_SCSI_OP_CHANGE_DEFINITION 0x40 +#define EFI_SCSI_OP_COMPARE 0x39 +#define EFI_SCSI_OP_COPY 0x18 +#define EFI_SCSI_OP_COPY_VERIFY 0x3a +#define EFI_SCSI_OP_INQUIRY 0x12 +#define EFI_SCSI_OP_LOG_SELECT 0x4c +#define EFI_SCSI_OP_LOG_SENSE 0x4d +#define EFI_SCSI_OP_MODE_SEL6 0x15 +#define EFI_SCSI_OP_MODE_SEL10 0x55 +#define EFI_SCSI_OP_MODE_SEN6 0x1a +#define EFI_SCSI_OP_MODE_SEN10 0x5a +#define EFI_SCSI_OP_READ_BUFFER 0x3c +#define EFI_SCSI_OP_REQUEST_SENSE 0x03 +#define EFI_SCSI_OP_SEND_DIAG 0x1d +#define EFI_SCSI_OP_TEST_UNIT_READY 0x00 +#define EFI_SCSI_OP_WRITE_BUFF 0x3b + +// +// Commands unique to Direct Access Devices +// +#define EFI_SCSI_OP_COMPARE 0x39 +#define EFI_SCSI_OP_FORMAT 0x04 +#define EFI_SCSI_OP_LOCK_UN_CACHE 0x36 +#define EFI_SCSI_OP_PREFETCH 0x34 +#define EFI_SCSI_OP_MEDIA_REMOVAL 0x1e +#define EFI_SCSI_OP_READ6 0x08 +#define EFI_SCSI_OP_READ10 0x28 +#define EFI_SCSI_OP_READ_CAPACITY 0x25 +#define EFI_SCSI_OP_READ_DEFECT 0x37 +#define EFI_SCSI_OP_READ_LONG 0x3e +#define EFI_SCSI_OP_REASSIGN_BLK 0x07 +#define EFI_SCSI_OP_RECEIVE_DIAG 0x1c +#define EFI_SCSI_OP_RELEASE 0x17 +#define EFI_SCSI_OP_REZERO 0x01 +#define EFI_SCSI_OP_SEARCH_DATA_E 0x31 +#define EFI_SCSI_OP_SEARCH_DATA_H 0x30 +#define EFI_SCSI_OP_SEARCH_DATA_L 0x32 +#define EFI_SCSI_OP_SEEK6 0x0b +#define EFI_SCSI_OP_SEEK10 0x2b +#define EFI_SCSI_OP_SEND_DIAG 0x1d +#define EFI_SCSI_OP_SET_LIMIT 0x33 +#define EFI_SCSI_OP_START_STOP_UNIT 0x1b +#define EFI_SCSI_OP_SYNC_CACHE 0x35 +#define EFI_SCSI_OP_VERIFY 0x2f +#define EFI_SCSI_OP_WRITE6 0x0a +#define EFI_SCSI_OP_WRITE10 0x2a +#define EFI_SCSI_OP_WRITE_VERIFY 0x2e +#define EFI_SCSI_OP_WRITE_LONG 0x3f +#define EFI_SCSI_OP_WRITE_SAME 0x41 + +// +// Commands unique to Sequential Access Devices +// +#define EFI_SCSI_OP_ERASE 0x19 +#define EFI_SCSI_OP_LOAD_UNLOAD 0x1b +#define EFI_SCSI_OP_LOCATE 0x2b +#define EFI_SCSI_OP_READ_BLOCK_LIMIT 0x05 +#define EFI_SCSI_OP_READ_POS 0x34 +#define EFI_SCSI_OP_READ_REVERSE 0x0f +#define EFI_SCSI_OP_RECOVER_BUF_DATA 0x14 +#define EFI_SCSI_OP_RESERVE_UNIT 0x16 +#define EFI_SCSI_OP_REWIND 0x01 +#define EFI_SCSI_OP_SPACE 0x11 +#define EFI_SCSI_OP_VERIFY_TAPE 0x13 +#define EFI_SCSI_OP_WRITE_FILEMARK 0x10 + +// +// Commands unique to Printer Devices +// +#define EFI_SCSI_OP_PRINT 0x0a +#define EFI_SCSI_OP_SLEW_PRINT 0x0b +#define EFI_SCSI_OP_STOP_PRINT 0x1b +#define EFI_SCSI_OP_SYNC_BUFF 0x10 + +// +// Commands unique to Processor Devices +// +#define EFI_SCSI_OP_RECEIVE 0x08 +#define EFI_SCSI_OP_SEND 0x0a + +// +// Commands unique to Write-Once Devices +// +#define EFI_SCSI_OP_MEDIUM_SCAN 0x38 +#define EFI_SCSI_OP_SEARCH_DAT_E10 0x31 +#define EFI_SCSI_OP_SEARCH_DAT_E12 0xb1 +#define EFI_SCSI_OP_SEARCH_DAT_H10 0x30 +#define EFI_SCSI_OP_SEARCH_DAT_H12 0xb0 +#define EFI_SCSI_OP_SEARCH_DAT_L10 0x32 +#define EFI_SCSI_OP_SEARCH_DAT_L12 0xb2 +#define EFI_SCSI_OP_SET_LIMIT10 0x33 +#define EFI_SCSI_OP_SET_LIMIT12 0xb3 +#define EFI_SCSI_OP_VERIFY10 0x2f +#define EFI_SCSI_OP_VERIFY12 0xaf +#define EFI_SCSI_OP_WRITE12 0xaa +#define EFI_SCSI_OP_WRITE_VERIFY10 0x2e +#define EFI_SCSI_OP_WRITE_VERIFY12 0xae + +// +// Commands unique to CD-ROM Devices +// +#define EFI_SCSI_OP_PLAY_AUD_10 0x45 +#define EFI_SCSI_OP_PLAY_AUD_12 0xa5 +#define EFI_SCSI_OP_PLAY_AUD_MSF 0x47 +#define EFI_SCSI_OP_PLAY_AUD_TKIN 0x48 +#define EFI_SCSI_OP_PLAY_TK_REL10 0x49 +#define EFI_SCSI_OP_PLAY_TK_REL12 0xa9 +#define EFI_SCSI_OP_READ_CD_CAPACITY 0x25 +#define EFI_SCSI_OP_READ_HEADER 0x44 +#define EFI_SCSI_OP_READ_SUB_CHANNEL 0x42 +#define EFI_SCSI_OP_READ_TOC 0x43 + +// +// Commands unique to Scanner Devices +// +#define EFI_SCSI_OP_GET_DATABUFF_STAT 0x34 +#define EFI_SCSI_OP_GET_WINDOW 0x25 +#define EFI_SCSI_OP_OBJECT_POS 0x31 +#define EFI_SCSI_OP_SCAN 0x1b +#define EFI_SCSI_OP_SET_WINDOW 0x24 + +// +// Commands unique to Optical Memory Devices +// +#define EFI_SCSI_OP_UPDATE_BLOCK 0x3d + +// +// Commands unique to Medium Changer Devices +// +#define EFI_SCSI_OP_EXCHANGE_MEDIUM 0xa6 +#define EFI_SCSI_OP_INIT_ELEMENT_STAT 0x07 +#define EFI_SCSI_OP_POS_TO_ELEMENT 0x2b +#define EFI_SCSI_OP_REQUEST_VE_ADDR 0xb5 +#define EFI_SCSI_OP_SEND_VOL_TAG 0xb6 + +// +// Commands unique to Communition Devices +// +#define EFI_SCSI_OP_GET_MESSAGE6 0x08 +#define EFI_SCSI_OP_GET_MESSAGE10 0x28 +#define EFI_SCSI_OP_GET_MESSAGE12 0xa8 +#define EFI_SCSI_OP_SEND_MESSAGE6 0x0a +#define EFI_SCSI_OP_SEND_MESSAGE10 0x2a +#define EFI_SCSI_OP_SEND_MESSAGE12 0xaa + +// +// SCSI Data Transfer Direction +// +#define EFI_SCSI_DATA_IN 0 +#define EFI_SCSI_DATA_OUT 1 + +// +// Peripheral Device Type Definitions +// +#define EFI_SCSI_TYPE_DISK 0x00 // Disk device +#define EFI_SCSI_TYPE_TAPE 0x01 // Tape device +#define EFI_SCSI_TYPE_PRINTER 0x02 // Printer +#define EFI_SCSI_TYPE_PROCESSOR 0x03 // Processor +#define EFI_SCSI_TYPE_WORM 0x04 // Write-once read-multiple +#define EFI_SCSI_TYPE_CDROM 0x05 // CD-ROM device +#define EFI_SCSI_TYPE_SCANNER 0x06 // Scanner device +#define EFI_SCSI_TYPE_OPTICAL 0x07 // Optical memory device +#define EFI_SCSI_TYPE_MEDIUMCHANGER 0x08 // Medium Changer device +#define EFI_SCSI_TYPE_COMMUNICATION 0x09 // Communications device +#define EFI_SCSI_TYPE_RESERVED_LOW 0x0A // Reserved (low) +#define EFI_SCSI_TYPE_RESERVED_HIGH 0x1E // Reserved (high) +#define EFI_SCSI_TYPE_UNKNOWN 0x1F // Unknown or no device type +#pragma pack(1) +// +// Data structures for scsi command use +// +typedef struct { + UINT8 Peripheral_Type : 5; + UINT8 Peripheral_Qualifier : 3; + UINT8 DeviceType_Modifier : 7; + UINT8 RMB : 1; + UINT8 Version; + UINT8 Response_Data_Format; + UINT8 Addnl_Length; + UINT8 Reserved_5_95[95 - 5 + 1]; +} EFI_SCSI_INQUIRY_DATA; + +typedef struct { + UINT8 Error_Code : 7; + UINT8 Valid : 1; + UINT8 Segment_Number; + UINT8 Sense_Key : 4; + UINT8 Reserved_21 : 1; + UINT8 ILI : 1; + UINT8 Reserved_22 : 2; + UINT8 Information_3_6[4]; + UINT8 Addnl_Sense_Length; // n - 7 + UINT8 Vendor_Specific_8_11[4]; + UINT8 Addnl_Sense_Code; // mandatory + UINT8 Addnl_Sense_Code_Qualifier; // mandatory + UINT8 Field_Replaceable_Unit_Code; // optional + UINT8 Reserved_15_17[3]; +} EFI_SCSI_SENSE_DATA; + +typedef struct { + UINT8 LastLba3; + UINT8 LastLba2; + UINT8 LastLba1; + UINT8 LastLba0; + UINT8 BlockSize3; + UINT8 BlockSize2; + UINT8 BlockSize1; + UINT8 BlockSize0; +} EFI_SCSI_DISK_CAPACITY_DATA; + +#pragma pack() +// +// Sense Key +// +#define EFI_SCSI_REQUEST_SENSE_ERROR (0x70) +#define EFI_SCSI_SK_NO_SENSE (0x0) +#define EFI_SCSI_SK_RECOVERY_ERROR (0x1) +#define EFI_SCSI_SK_NOT_READY (0x2) +#define EFI_SCSI_SK_MEDIUM_ERROR (0x3) +#define EFI_SCSI_SK_HARDWARE_ERROR (0x4) +#define EFI_SCSI_SK_ILLEGAL_REQUEST (0x5) +#define EFI_SCSI_SK_UNIT_ATTENTION (0x6) +#define EFI_SCSI_SK_DATA_PROTECT (0x7) +#define EFI_SCSI_SK_BLANK_CHECK (0x8) +#define EFI_SCSI_SK_VENDOR_SPECIFIC (0x9) +#define EFI_SCSI_SK_RESERVED_A (0xA) +#define EFI_SCSI_SK_ABORT (0xB) +#define EFI_SCSI_SK_RESERVED_C (0xC) +#define EFI_SCSI_SK_OVERFLOW (0xD) +#define EFI_SCSI_SK_MISCOMPARE (0xE) +#define EFI_SCSI_SK_RESERVED_F (0xF) + +// +// Additional Sense Codes +// +#define EFI_SCSI_ASC_NOT_READY (0x04) +#define EFI_SCSI_ASC_MEDIA_ERR1 (0x10) +#define EFI_SCSI_ASC_MEDIA_ERR2 (0x11) +#define EFI_SCSI_ASC_MEDIA_ERR3 (0x14) +#define EFI_SCSI_ASC_MEDIA_ERR4 (0x30) +#define EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN (0x06) +#define EFI_SCSI_ASC_INVALID_CMD (0x20) +#define EFI_SCSI_ASC_LBA_OUT_OF_RANGE (0x21) +#define EFI_SCSI_ASC_INVALID_FIELD (0x24) +#define EFI_SCSI_ASC_WRITE_PROTECTED (0x27) +#define EFI_SCSI_ASC_MEDIA_CHANGE (0x28) +#define EFI_SCSI_ASC_RESET (0x29) /* Power On Reset or Bus Reset occurred */ +#define EFI_SCSI_ASC_ILLEGAL_FIELD (0x26) +#define EFI_SCSI_ASC_NO_MEDIA (0x3A) +#define EFI_SCSI_ASC_ILLEGAL_MODE_FOR_THIS_TRACK (0x64) + +// +// Additional Sense Code Qualifier +// +#define EFI_SCSI_ASCQ_IN_PROGRESS (0x01) + +#endif diff --git a/MdePkg/Include/Ipf/IpfDefines.h b/MdePkg/Include/Ipf/IpfDefines.h new file mode 100644 index 0000000000..4b9c1adee0 --- /dev/null +++ b/MdePkg/Include/Ipf/IpfDefines.h @@ -0,0 +1,553 @@ +///** @file +// IPF Processor Defines for assembly code +// +// @note +// This file is included by assembly files as well. The assmber can NOT deal +// with /* */ commnets this is why this file is commented not following the +// coding standard +// +//Copyright (c) 2006, 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. +// +//Module Name: IpfDefines.h +// +//**/ + +#ifndef _IPFDEFINES_H +#define _IPFDEFINES_H + +// +// IPI DElivery Methods +// +#define IPI_INT_DELIVERY 0x0 +#define IPI_PMI_DELIVERY 0x2 +#define IPI_NMI_DELIVERY 0x4 +#define IPI_INIT_DELIVERY 0x5 +#define IPI_ExtINT_DELIVERY 0x7 + +// +// Define Itanium-based system registers. +// +// Define Itanium-based system register bit field offsets. +// +// Processor Status Register (PSR) Bit positions +// +// User / System mask +// +#define PSR_RV0 0 +#define PSR_BE 1 +#define PSR_UP 2 +#define PSR_AC 3 +#define PSR_MFL 4 +#define PSR_MFH 5 + +// +// PSR bits 6-12 reserved (must be zero) +// +#define PSR_MBZ0 6 +#define PSR_MBZ0_V 0x1ffUL L + +// +// System only mask +// +#define PSR_IC 13 +#define PSR_IC_MASK (1 << 13) +#define PSR_I 14 +#define PSR_PK 15 +#define PSR_MBZ1 16 +#define PSR_MBZ1_V 0x1UL L +#define PSR_DT 17 +#define PSR_DFL 18 +#define PSR_DFH 19 +#define PSR_SP 20 +#define PSR_PP 21 +#define PSR_DI 22 +#define PSR_SI 23 +#define PSR_DB 24 +#define PSR_LP 25 +#define PSR_TB 26 +#define PSR_RT 27 + +// +// PSR bits 28-31 reserved (must be zero) +// +#define PSR_MBZ2 28 +#define PSR_MBZ2_V 0xfUL L + +// +// Neither mask +// +#define PSR_CPL 32 +#define PSR_CPL_LEN 2 +#define PSR_IS 34 +#define PSR_MC 35 +#define PSR_IT 36 +#define PSR_IT_MASK 0x1000000000 +#define PSR_ID 37 +#define PSR_DA 38 +#define PSR_DD 39 +#define PSR_SS 40 +#define PSR_RI 41 +#define PSR_RI_LEN 2 +#define PSR_ED 43 +#define PSR_BN 44 + +// +// PSR bits 45-63 reserved (must be zero) +// +#define PSR_MBZ3 45 +#define PSR_MBZ3_V 0xfffffUL L + +// +// Floating Point Status Register (FPSR) Bit positions +// +// +// Traps +// +#define FPSR_VD 0 +#define FPSR_DD 1 +#define FPSR_ZD 2 +#define FPSR_OD 3 +#define FPSR_UD 4 +#define FPSR_ID 5 + +// +// Status Field 0 - Controls +// +#define FPSR0_FTZ0 6 +#define FPSR0_WRE0 7 +#define FPSR0_PC0 8 +#define FPSR0_RC0 10 +#define FPSR0_TD0 12 + +// +// Status Field 0 - Flags +// +#define FPSR0_V0 13 +#define FPSR0_D0 14 +#define FPSR0_Z0 15 +#define FPSR0_O0 16 +#define FPSR0_U0 17 +#define FPSR0_I0 18 + +// +// Status Field 1 - Controls +// +#define FPSR1_FTZ0 19 +#define FPSR1_WRE0 20 +#define FPSR1_PC0 21 +#define FPSR1_RC0 23 +#define FPSR1_TD0 25 + +// +// Status Field 1 - Flags +// +#define FPSR1_V0 26 +#define FPSR1_D0 27 +#define FPSR1_Z0 28 +#define FPSR1_O0 29 +#define FPSR1_U0 30 +#define FPSR1_I0 31 + +// +// Status Field 2 - Controls +// +#define FPSR2_FTZ0 32 +#define FPSR2_WRE0 33 +#define FPSR2_PC0 34 +#define FPSR2_RC0 36 +#define FPSR2_TD0 38 + +// +// Status Field 2 - Flags +// +#define FPSR2_V0 39 +#define FPSR2_D0 40 +#define FPSR2_Z0 41 +#define FPSR2_O0 42 +#define FPSR2_U0 43 +#define FPSR2_I0 44 + +// +// Status Field 3 - Controls +// +#define FPSR3_FTZ0 45 +#define FPSR3_WRE0 46 +#define FPSR3_PC0 47 +#define FPSR3_RC0 49 +#define FPSR3_TD0 51 + +// +// Status Field 0 - Flags +// +#define FPSR3_V0 52 +#define FPSR3_D0 53 +#define FPSR3_Z0 54 +#define FPSR3_O0 55 +#define FPSR3_U0 56 +#define FPSR3_I0 57 + +// +// FPSR bits 58-63 Reserved -- Must be zero +// +#define FPSR_MBZ0 58 +#define FPSR_MBZ0_V 0x3fUL L + +// +// For setting up FPSR on kernel entry +// All traps are disabled. +// +#define FPSR_FOR_KERNEL 0x3f + +#define FP_REG_SIZE 16 // 16 byte spill size +#define HIGHFP_REGS_LENGTH (96 * 16) + +// +// Define hardware Task Priority Register (TPR) +// +// +// TPR bit positions +// +#define TPR_MIC 4 // Bits 0 - 3 ignored +#define TPR_MIC_LEN 4 +#define TPR_MMI 16 // Mask Maskable Interrupt +// +// Define hardware Interrupt Status Register (ISR) +// +// +// ISR bit positions +// +#define ISR_CODE 0 +#define ISR_CODE_LEN 16 +#define ISR_CODE_MASK 0xFFFF +#define ISR_IA_VECTOR 16 +#define ISR_IA_VECTOR_LEN 8 +#define ISR_MBZ0 24 +#define ISR_MBZ0_V 0xff +#define ISR_X 32 +#define ISR_W 33 +#define ISR_R 34 +#define ISR_NA 35 +#define ISR_SP 36 +#define ISR_RS 37 +#define ISR_IR 38 +#define ISR_NI 39 +#define ISR_MBZ1 40 +#define ISR_EI 41 +#define ISR_ED 43 +#define ISR_MBZ2 44 +#define ISR_MBZ2_V 0xfffff + +// +// ISR codes +// +// For General exceptions: ISR{3:0} +// +#define ISR_ILLEGAL_OP 0 // Illegal operation fault +#define ISR_PRIV_OP 1 // Privileged operation fault +#define ISR_PRIV_REG 2 // Privileged register fauls +#define ISR_RESVD_REG 3 // Reserved register/field flt +#define ISR_ILLEGAL_ISA 4 // Disabled instruction set transition fault +// +// Define hardware Default Control Register (DCR) +// +// +// DCR bit positions +// +#define DCR_PP 0 +#define DCR_BE 1 +#define DCR_LC 2 +#define DCR_MBZ0 4 +#define DCR_MBZ0_V 0xf +#define DCR_DM 8 +#define DCR_DP 9 +#define DCR_DK 10 +#define DCR_DX 11 +#define DCR_DR 12 +#define DCR_DA 13 +#define DCR_DD 14 +#define DCR_DEFER_ALL 0x7f00 +#define DCR_MBZ1 2 +#define DCR_MBZ1_V 0xffffffffffffUL L + +// +// Define hardware RSE Configuration Register +// +// RS Configuration (RSC) bit field positions +// +#define RSC_MODE 0 +#define RSC_PL 2 +#define RSC_BE 4 +#define RSC_MBZ0 5 +#define RSC_MBZ0_V 0x3ff +#define RSC_LOADRS 16 +#define RSC_LOADRS_LEN 14 +#define RSC_MBZ1 30 +#define RSC_MBZ1_V 0x3ffffffffUL L + +// +// RSC modes +// +#define RSC_MODE_LY (0x0) // Lazy +#define RSC_MODE_SI (0x1) // Store intensive +#define RSC_MODE_LI (0x2) // Load intensive +#define RSC_MODE_EA (0x3) // Eager +// +// RSC Endian bit values +// +#define RSC_BE_LITTLE 0 +#define RSC_BE_BIG 1 + +// +// Define Interruption Function State (IFS) Register +// +// IFS bit field positions +// +#define IFS_IFM 0 +#define IFS_IFM_LEN 38 +#define IFS_MBZ0 38 +#define IFS_MBZ0_V 0x1ffffff +#define IFS_V 63 +#define IFS_V_LEN 1 + +// +// IFS is valid when IFS_V = IFS_VALID +// +#define IFS_VALID 1 + +// +// Define Page Table Address (PTA) +// +#define PTA_VE 0 +#define PTA_VF 8 +#define PTA_SIZE 2 +#define PTA_SIZE_LEN 6 +#define PTA_BASE 15 + +// +// Define Region Register (RR) +// +// +// RR bit field positions +// +#define RR_VE 0 +#define RR_MBZ0 1 +#define RR_PS 2 +#define RR_PS_LEN 6 +#define RR_RID 8 +#define RR_RID_LEN 24 +#define RR_MBZ1 32 + +// +// SAL uses region register 0 and RID of 1000 +// +#define SAL_RID 0x1000 +#define SAL_RR_REG 0x0 +#define SAL_TR 0x0 + +// +// Total number of region registers +// +#define RR_SIZE 8 + +// +// Define Protection Key Register (PKR) +// +// PKR bit field positions +// +#define PKR_V 0 +#define PKR_WD 1 +#define PKR_RD 2 +#define PKR_XD 3 +#define PKR_MBZ0 4 +#define PKR_KEY 8 +#define PKR_KEY_LEN 24 +#define PKR_MBZ1 32 + +#define PKR_VALID (1 << PKR_V) + +// +// Number of protection key registers +// +#define PKRNUM 8 + +// +// Define Interruption TLB Insertion register (ITIR) +// +// +// Define Translation Insertion Format (TR) +// +// PTE0 bit field positions +// +#define PTE0_P 0 +#define PTE0_MBZ0 1 +#define PTE0_MA 2 +#define PTE0_A 5 +#define PTE0_D 6 +#define PTE0_PL 7 +#define PTE0_AR 9 +#define PTE0_PPN 12 +#define PTE0_MBZ1 48 +#define PTE0_ED 52 +#define PTE0_IGN0 53 + +// +// ITIR bit field positions +// +#define ITIR_MBZ0 0 +#define ITIR_PS 2 +#define ITIR_PS_LEN 6 +#define ITIR_KEY 8 +#define ITIR_KEY_LEN 24 +#define ITIR_MBZ1 32 +#define ITIR_MBZ1_LEN 16 +#define ITIR_PPN 48 +#define ITIR_PPN_LEN 15 +#define ITIR_MBZ2 63 + +#define ATTR_IPAGE 0x661 // Access Rights = RWX (bits 11-9=011), PL 0(8-7=0) +#define ATTR_DEF_BITS 0x661 // Access Rights = RWX (bits 11-9=010), PL 0(8-7=0) +// Dirty (bit 6=1), Accessed (bit 5=1), +// MA WB (bits 4-2=000), Present (bit 0=1) +// +// Memory access rights +// +#define AR_UR_KR 0x0 // user/kernel read +#define AR_URX_KRX 0x1 // user/kernel read and execute +#define AR_URW_KRW 0x2 // user/kernel read & write +#define AR_URWX_KRWX 0x3 // user/kernel read,write&execute +#define AR_UR_KRW 0x4 // user read/kernel read,write +#define AR_URX_KRWX 0x5 // user read/execute, kernel all +#define AR_URWX_KRW 0x6 // user all, kernel read & write +#define AR_UX_KRX 0x7 // user execute only, kernel read and execute +// +// Memory attribute values +// +// +// The next 4 are all cached, non-sequential & speculative, coherent +// +#define MA_WBU 0x0 // Write back, unordered +// +// The next 3 are all non-cached, sequential & non-speculative +// +#define MA_UC 0x4 // Non-coalescing, sequential & non-speculative +#define MA_UCE 0x5 // Non-coalescing, sequential, non-speculative +// & fetchadd exported +// +#define MA_WC 0x6 // Non-cached, Coalescing, non-seq., spec. +#define MA_NAT 0xf // NaT page +// +// Definition of the offset of TRAP/INTERRUPT/FAULT handlers from the +// base of IVA (Interruption Vector Address) +// +#define IVT_SIZE 0x8000 +#define EXTRA_ALIGNMENT 0x1000 + +#define OFF_VHPTFLT 0x0000 // VHPT Translation fault +#define OFF_ITLBFLT 0x0400 // Instruction TLB fault +#define OFF_DTLBFLT 0x0800 // Data TLB fault +#define OFF_ALTITLBFLT 0x0C00 // Alternate ITLB fault +#define OFF_ALTDTLBFLT 0x1000 // Alternate DTLB fault +#define OFF_NESTEDTLBFLT 0x1400 // Nested TLB fault +#define OFF_IKEYMISSFLT 0x1800 // Inst Key Miss fault +#define OFF_DKEYMISSFLT 0x1C00 // Data Key Miss fault +#define OFF_DIRTYBITFLT 0x2000 // Dirty-Bit fault +#define OFF_IACCESSBITFLT 0x2400 // Inst Access-Bit fault +#define OFF_DACCESSBITFLT 0x2800 // Data Access-Bit fault +#define OFF_BREAKFLT 0x2C00 // Break Inst fault +#define OFF_EXTINT 0x3000 // External Interrupt +// +// Offset 0x3400 to 0x0x4C00 are reserved +// +#define OFF_PAGENOTPFLT 0x5000 // Page Not Present fault +#define OFF_KEYPERMFLT 0x5100 // Key Permission fault +#define OFF_IACCESSRTFLT 0x5200 // Inst Access-Rights flt +#define OFF_DACCESSRTFLT 0x5300 // Data Access-Rights fault +#define OFF_GPFLT 0x5400 // General Exception fault +#define OFF_FPDISFLT 0x5500 // Disable-FP fault +#define OFF_NATFLT 0x5600 // NAT Consumption fault +#define OFF_SPECLNFLT 0x5700 // Speculation fault +#define OFF_DBGFLT 0x5900 // Debug fault +#define OFF_ALIGNFLT 0x5A00 // Unaligned Reference fault +#define OFF_LOCKDREFFLT 0x5B00 // Locked Data Reference fault +#define OFF_FPFLT 0x5C00 // Floating Point fault +#define OFF_FPTRAP 0x5D00 // Floating Point Trap +#define OFF_LOPRIVTRAP 0x5E00 // Lower-Privilege Transfer Trap +#define OFF_TAKENBRTRAP 0x5F00 // Taken Branch Trap +#define OFF_SSTEPTRAP 0x6000 // Single Step Trap +// +// Offset 0x6100 to 0x6800 are reserved +// +#define OFF_IA32EXCEPTN 0x6900 // iA32 Exception +#define OFF_IA32INTERCEPT 0x6A00 // iA32 Intercept +#define OFF_IA32INT 0x6B00 // iA32 Interrupt +#define NUMBER_OF_VECTORS 0x100 +// +// Privilege levels +// +#define PL_KERNEL 0 +#define PL_USER 3 + +// +// Instruction set (IS) bits +// +#define IS_IA64 0 +#define IS_IA 1 + +// +// RSC while in kernel: enabled, little endian, PL = 0, eager mode +// +#define RSC_KERNEL ((RSC_MODE_EA << RSC_MODE) | (RSC_BE_LITTLE << RSC_BE)) + +// +// Lazy RSC in kernel: enabled, little endian, pl = 0, lazy mode +// +#define RSC_KERNEL_LAZ ((RSC_MODE_LY << RSC_MODE) | (RSC_BE_LITTLE << RSC_BE)) + +// +// RSE disabled: disabled, PL = 0, little endian, eager mode +// +#define RSC_KERNEL_DISABLED ((RSC_MODE_LY << RSC_MODE) | (RSC_BE_LITTLE << RSC_BE)) + +#define NAT_BITS_PER_RNAT_REG 63 + +// +// Macros for generating PTE0 and PTE1 value +// +#define PTE0(ed, ppn12_47, ar, pl, d, a, ma, p) \ + ( ( ed << PTE0_ED ) | \ + ( ppn12_47 << PTE0_PPN ) | \ + ( ar << PTE0_AR ) | \ + ( pl << PTE0_PL ) | \ + ( d << PTE0_D ) | \ + ( a << PTE0_A ) | \ + ( ma << PTE0_MA ) | \ + ( p << PTE0_P ) \ + ) + +#define ITIR(ppn48_63, key, ps) \ + ( ( ps << ITIR_PS ) | \ + ( key << ITIR_KEY ) | \ + ( ppn48_63 << ITIR_PPN ) \ + ) + +// +// Macro to generate mask value from bit position. The result is a +// 64-bit. +// +#define BITMASK(bp, value) (value << bp) + +#define BUNDLE_SIZE 16 +#define SPURIOUS_INT 0xF + +#define FAST_DISABLE_INTERRUPTS rsm BITMASK (PSR_I, 1);; + +#define FAST_ENABLE_INTERRUPTS ssm BITMASK (PSR_I, 1);; + +#endif diff --git a/MdePkg/Include/Ipf/IpfMacro.i b/MdePkg/Include/Ipf/IpfMacro.i new file mode 100644 index 0000000000..506b4b328c --- /dev/null +++ b/MdePkg/Include/Ipf/IpfMacro.i @@ -0,0 +1,64 @@ +//++ +// Copyright (c) 2006, 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. +// +// Module Name: +// IpfMacro.i +// +// Abstract: +// Contains the macros needed for calling procedures in Itanium-based assembly code. +// +// +// Revision History: +// +//-- + +#ifndef __IA64PROC_I__ +#define __IA64PROC_I__ + + +#define PROCEDURE_ENTRY(name) .##text; \ + .##type name, @function; \ + .##proc name; \ +name:: + +#define PROCEDURE_EXIT(name) .##endp name + +// Note: use of NESTED_SETUP requires number of locals (l) >= 3 + +#define NESTED_SETUP(i,l,o,r) \ + alloc loc1=ar##.##pfs,i,l,o,r ;\ + mov loc0=b0 + +#define NESTED_RETURN \ + mov b0=loc0 ;\ + mov ar##.##pfs=loc1 ;;\ + br##.##ret##.##dpnt b0;; + + +#define INTERRUPT_HANDLER_BEGIN(name) \ +PROCEDURE_ENTRY(name##HandlerBegin) \ +;; \ +PROCEDURE_EXIT(name##HandlerBegin) + +#define INTERRUPT_HANDLER_END(name) \ +PROCEDURE_ENTRY(name##HandlerEnd) \ +;; \ +PROCEDURE_EXIT(name##HandlerEnd) + + +#define INTERRUPT_HANDLER_BLOCK_BEGIN \ +INTERRUPT_HANDLER_BEGIN(First) + +#define INTERRUPT_HANDLER_BLOCK_END \ +INTERRUPT_HANDLER_END(Last) + + + +#endif diff --git a/MdePkg/Include/Ipf/ProcessorBind.h b/MdePkg/Include/Ipf/ProcessorBind.h new file mode 100644 index 0000000000..99da96ca05 --- /dev/null +++ b/MdePkg/Include/Ipf/ProcessorBind.h @@ -0,0 +1,202 @@ +/** @file + Processor or Compiler specific defines and types for Intel Itanium(TM). + + Copyright (c) 2006, 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. + + Module Name: ProcessorBind.h + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + + +// +// Define the processor type so other code can make processor based choices +// +#define MDE_CPU_IPF + + +// +// Make sure we are useing the correct packing rules per EFI specification +// +#pragma pack() + + +#if _MSC_EXTENSIONS + +// +// Disable warning that make it impossible to compile at /W4 +// This only works for Microsoft tools. Copied from the +// IA-32 version of efibind.h +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + + +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning +// +#pragma warning ( disable : 4127 ) + +// +// Can not cast a function pointer to a data pointer. We need to do this on +// IPF to get access to the PLABEL. +// +#pragma warning ( disable : 4514 ) + + +#endif + + +#if (__STDC_VERSION__ < 199901L) + // + // No ANSI C 2000 stdint.h integer width declarations, so define equivalents + // + + #if _MSC_EXTENSIONS + + + // + // use Microsoft C complier dependent interger width types + // + typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int32 UINT32; + typedef __int32 INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #else + #ifdef _EFI_P64 + // + // P64 - is Intel Itanium(TM) speak for pointers being 64-bit and longs and ints + // are 32-bits + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short CHAR16; + typedef unsigned short UINT16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #else + // + // Assume LP64 - longs and pointers are 64-bit. Ints are 32-bit. + // + typedef unsigned long UINT64; + typedef long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #endif + #endif + + #define UINT8_MAX 0xff + +#else + // + // Use ANSI C 2000 stdint.h integer width declarations + // + #include + typedef uint8_t BOOLEAN; + typedef int8_t INT8; + typedef uint8_t UINT8; + typedef int16_t INT16; + typedef uint16_t UINT16; + typedef int32_t INT32; + typedef uint32_t UINT32; + typedef int64_t INT64; + typedef uint64_t UINT64; + typedef char CHAR8; + typedef uint16_t CHAR16; + +#endif + +typedef UINT64 UINTN; +typedef INT64 INTN; + + +// +// Processor specific defines +// +#define MAX_BIT 0x8000000000000000ULL +#define MAX_2_BITS 0xC000000000000000ULL + +// +// Maximum legal Itanium-based address +// +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFFULL + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify thier member functions with EFIAPI. +// +#if _MSC_EXTENSIONS + // + // Microsoft* compiler requires _EFIAPI useage, __cdecl is Microsoft* specific C. + // + #define EFIAPI __cdecl +#else + #define EFIAPI +#endif + +// +// The Microsoft* C compiler can removed references to unreferenced data items +// if the /OPT:REF linker option is used. We defined a macro as this is a +// a non standard extension +// +#define GLOBAL_REMOVE_IF_UNREFERENCED + +// +// A pointer to a function in IPF points to a plabel. +// +typedef struct { + UINT64 EntryPoint; + UINT64 GP; +} EFI_PLABEL; + +typedef struct { + UINTN BootPhase; // entry r20 value + UINTN UniqueId; // PAL arbitration ID + UINTN HealthStat; // Health Status + UINTN PALRetAddress; // return address to PAL +} IPF_HANDOFF_STATUS; + +#endif + diff --git a/MdePkg/Include/Ipf/SalApi.h b/MdePkg/Include/Ipf/SalApi.h new file mode 100644 index 0000000000..cbaf4ac41a --- /dev/null +++ b/MdePkg/Include/Ipf/SalApi.h @@ -0,0 +1,691 @@ +/** @file + Main SAL API's defined in SAL 3.0 specification. + + Copyright (c) 2006, 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. + + Module Name: SalApi.h + +**/ + +#ifndef __SAL_API_H__ +#define __SAL_API_H__ + +typedef UINTN EFI_SAL_STATUS; + +// +// EFI_SAL_STATUS defines +// +#define EFI_SAL_SUCCESS ((EFI_SAL_STATUS) 0) +#define EFI_SAL_MORE_RECORDS ((EFI_SAL_STATUS) 3) +#define EFI_SAL_NOT_IMPLEMENTED ((EFI_SAL_STATUS) - 1) +#define EFI_SAL_INVALID_ARGUMENT ((EFI_SAL_STATUS) - 2) +#define EFI_SAL_ERROR ((EFI_SAL_STATUS) - 3) +#define EFI_SAL_VIRTUAL_ADDRESS_ERROR ((EFI_SAL_STATUS) - 4) +#define EFI_SAL_NO_INFORMATION ((EFI_SAL_STATUS) - 5) +#define EFI_SAL_NOT_ENOUGH_SCRATCH ((EFI_SAL_STATUS) - 9) + +// +// Return values from SAL +// +typedef struct { + EFI_SAL_STATUS Status; // register r8 + UINTN r9; + UINTN r10; + UINTN r11; +} SAL_RETURN_REGS; + +typedef SAL_RETURN_REGS (EFIAPI *SAL_PROC) + ( + IN UINT64 FunctionId, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4, + IN UINT64 Arg5, + IN UINT64 Arg6, + IN UINT64 Arg7, + IN UINT64 Arg8 + ); + +// +// SAL Procedure FunctionId definition +// +#define EFI_SAL_SET_VECTORS 0x01000000 +#define EFI_SAL_GET_STATE_INFO 0x01000001 +#define EFI_SAL_GET_STATE_INFO_SIZE 0x01000002 +#define EFI_SAL_CLEAR_STATE_INFO 0x01000003 +#define EFI_SAL_MC_RENDEZ 0x01000004 +#define EFI_SAL_MC_SET_PARAMS 0x01000005 +#define EFI_SAL_REGISTER_PHYSICAL_ADDR 0x01000006 +#define EFI_SAL_CACHE_FLUSH 0x01000008 +#define EFI_SAL_CACHE_INIT 0x01000009 +#define EFI_SAL_PCI_CONFIG_READ 0x01000010 +#define EFI_SAL_PCI_CONFIG_WRITE 0x01000011 +#define EFI_SAL_FREQ_BASE 0x01000012 +#define EFI_SAL_UPDATE_PAL 0x01000020 + +#define EFI_SAL_FUNCTION_ID_MASK 0x0000ffff +#define EFI_SAL_MAX_SAL_FUNCTION_ID 0x00000021 + +// +// SAL Procedure parameter definitions +// Not much point in using typedefs or enums because all params +// are UINT64 and the entry point is common +// +// EFI_SAL_SET_VECTORS +// +#define EFI_SAL_SET_MCA_VECTOR 0x0 +#define EFI_SAL_SET_INIT_VECTOR 0x1 +#define EFI_SAL_SET_BOOT_RENDEZ_VECTOR 0x2 + +typedef struct { + UINT64 Length : 32; + UINT64 ChecksumValid : 1; + UINT64 Reserved1 : 7; + UINT64 ByteChecksum : 8; + UINT64 Reserved2 : 16; +} SAL_SET_VECTORS_CS_N; + +// +// EFI_SAL_GET_STATE_INFO, EFI_SAL_GET_STATE_INFO_SIZE, +// EFI_SAL_CLEAR_STATE_INFO +// +#define EFI_SAL_MCA_STATE_INFO 0x0 +#define EFI_SAL_INIT_STATE_INFO 0x1 +#define EFI_SAL_CMC_STATE_INFO 0x2 +#define EFI_SAL_CP_STATE_INFO 0x3 + +// +// EFI_SAL_MC_SET_PARAMS +// +#define EFI_SAL_MC_SET_RENDEZ_PARAM 0x1 +#define EFI_SAL_MC_SET_WAKEUP_PARAM 0x2 +#define EFI_SAL_MC_SET_CPE_PARAM 0x3 + +#define EFI_SAL_MC_SET_INTR_PARAM 0x1 +#define EFI_SAL_MC_SET_MEM_PARAM 0x2 + +// +// EFI_SAL_REGISTER_PAL_PHYSICAL_ADDR +// +#define EFI_SAL_REGISTER_PAL_ADDR 0x0 + +// +// EFI_SAL_CACHE_FLUSH +// +#define EFI_SAL_FLUSH_I_CACHE 0x01 +#define EFI_SAL_FLUSH_D_CACHE 0x02 +#define EFI_SAL_FLUSH_BOTH_CACHE 0x03 +#define EFI_SAL_FLUSH_MAKE_COHERENT 0x04 + +// +// EFI_SAL_PCI_CONFIG_READ, EFI_SAL_PCI_CONFIG_WRITE +// +#define EFI_SAL_PCI_CONFIG_ONE_BYTE 0x1 +#define EFI_SAL_PCI_CONFIG_TWO_BYTES 0x2 +#define EFI_SAL_PCI_CONFIG_FOUR_BYTES 0x4 + +typedef struct { + UINT64 Register : 8; + UINT64 Function : 3; + UINT64 Device : 5; + UINT64 Bus : 8; + UINT64 Segment : 8; + UINT64 Reserved : 32; +} SAL_PCI_ADDRESS; + +// +// EFI_SAL_FREQ_BASE +// +#define EFI_SAL_CPU_INPUT_FREQ_BASE 0x0 +#define EFI_SAL_PLATFORM_IT_FREQ_BASE 0x1 +#define EFI_SAL_PLATFORM_RTC_FREQ_BASE 0x2 + +// +// EFI_SAL_UPDATE_PAL +// +#define EFI_SAL_UPDATE_BAD_PAL_VERSION ((UINT64) -1) +#define EFI_SAL_UPDATE_PAL_AUTH_FAIL ((UINT64) -2) +#define EFI_SAL_UPDATE_PAL_BAD_TYPE ((UINT64) -3) +#define EFI_SAL_UPDATE_PAL_READONLY ((UINT64) -4) +#define EFI_SAL_UPDATE_PAL_WRITE_FAIL ((UINT64) -10) +#define EFI_SAL_UPDATE_PAL_ERASE_FAIL ((UINT64) -11) +#define EFI_SAL_UPDATE_PAL_READ_FAIL ((UINT64) -12) +#define EFI_SAL_UPDATE_PAL_CANT_FIT ((UINT64) -13) + +typedef struct { + UINT32 Size; + UINT32 MmddyyyyDate; + UINT16 Version; + UINT8 Type; + UINT8 Reserved[5]; + UINT64 FwVendorId; +} SAL_UPDATE_PAL_DATA_BLOCK; + +typedef struct _SAL_UPDATE_PAL_INFO_BLOCK { + struct _SAL_UPDATE_PAL_INFO_BLOCK *Next; + struct SAL_UPDATE_PAL_DATA_BLOCK *DataBlock; + UINT8 StoreChecksum; + UINT8 Reserved[15]; +} SAL_UPDATE_PAL_INFO_BLOCK; + +// +// SAL System Table Definitions +// +#pragma pack(1) +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT16 SalRevision; + UINT16 EntryCount; + UINT8 CheckSum; + UINT8 Reserved[7]; + UINT16 SalAVersion; + UINT16 SalBVersion; + UINT8 OemId[32]; + UINT8 ProductId[32]; + UINT8 Reserved2[8]; +} SAL_SYSTEM_TABLE_HEADER; +#pragma pack() + +#define EFI_SAL_ST_HEADER_SIGNATURE "SST_" +#define EFI_SAL_REVISION 0x0300 +// +// SAL System Types +// +#define EFI_SAL_ST_ENTRY_POINT 0 +#define EFI_SAL_ST_MEMORY_DESCRIPTOR 1 +#define EFI_SAL_ST_PLATFORM_FEATURES 2 +#define EFI_SAL_ST_TR_USAGE 3 +#define EFI_SAL_ST_PTC 4 +#define EFI_SAL_ST_AP_WAKEUP 5 + +#pragma pack(1) +typedef struct { + UINT8 Type; // Type == 0 + UINT8 Reserved[7]; + UINT64 PalProcEntry; + UINT64 SalProcEntry; + UINT64 SalGlobalDataPointer; + UINT64 Reserved2[2]; +} SAL_ST_ENTRY_POINT_DESCRIPTOR; + +// +// Not needed for Itanium-based OS boot +// +typedef struct { + UINT8 Type; // Type == 1 + UINT8 NeedVirtualRegistration; + UINT8 MemoryAttributes; + UINT8 PageAccessRights; + UINT8 SupportedAttributes; + UINT8 Reserved; + UINT8 MemoryType; + UINT8 MemoryUsage; + UINT64 PhysicalMemoryAddress; + UINT32 Length; + UINT32 Reserved1; + UINT64 OemReserved; +} SAL_ST_MEMORY_DESCRIPTOR_ENTRY; + +#pragma pack() +// +// Memory Attributes +// +#define SAL_MDT_ATTRIB_WB 0x00 +// +// #define SAL_MDT_ATTRIB_UC 0x02 +// +#define SAL_MDT_ATTRIB_UC 0x04 +#define SAL_MDT_ATTRIB_UCE 0x05 +#define SAL_MDT_ATTRIB_WC 0x06 + +// +// Supported memory Attributes +// +#define SAL_MDT_SUPPORT_WB 0x1 +#define SAL_MDT_SUPPORT_UC 0x2 +#define SAL_MDT_SUPPORT_UCE 0x4 +#define SAL_MDT_SUPPORT_WC 0x8 + +// +// Virtual address registration +// +#define SAL_MDT_NO_VA 0x00 +#define SAL_MDT_NEED_VA 0x01 +// +// MemoryType info +// +#define SAL_REGULAR_MEMORY 0x0000 +#define SAL_MMIO_MAPPING 0x0001 +#define SAL_SAPIC_IPI_BLOCK 0x0002 +#define SAL_IO_PORT_MAPPING 0x0003 +#define SAL_FIRMWARE_MEMORY 0x0004 +#define SAL_BLACK_HOLE 0x000A +// +// Memory Usage info +// +#define SAL_MDT_USAGE_UNSPECIFIED 0x00 +#define SAL_PAL_CODE 0x01 +#define SAL_BOOTSERVICE_CODE 0x02 +#define SAL_BOOTSERVICE_DATA 0x03 +#define SAL_RUNTIMESERVICE_CODE 0x04 +#define SAL_RUNTIMESERVICE_DATA 0x05 +#define SAL_IA32_OPTIONROM 0x06 +#define SAL_IA32_SYSTEMROM 0x07 +#define SAL_PMI_CODE 0x0a +#define SAL_PMI_DATA 0x0b + +#pragma pack(1) +typedef struct { + UINT8 Type; // Type == 2 + UINT8 PlatformFeatures; + UINT8 Reserved[14]; +} SAL_ST_PLATFORM_FEATURES; +#pragma pack() + +#define SAL_PLAT_FEAT_BUS_LOCK 0x01 +#define SAL_PLAT_FEAT_PLAT_IPI_HINT 0x02 +#define SAL_PLAT_FEAT_PROC_IPI_HINT 0x04 + +#pragma pack(1) +typedef struct { + UINT8 Type; // Type == 3 + UINT8 TRType; + UINT8 TRNumber; + UINT8 Reserved[5]; + UINT64 VirtualAddress; + UINT64 EncodedPageSize; + UINT64 Reserved1; +} SAL_ST_TR_DECRIPTOR; +#pragma pack() + +#define EFI_SAL_ST_TR_USAGE_INSTRUCTION 00 +#define EFI_SAL_ST_TR_USAGE_DATA 01 + +#pragma pack(1) +typedef struct { + UINT64 NumberOfProcessors; + UINT64 LocalIDRegister; +} SAL_COHERENCE_DOMAIN_INFO; +#pragma pack() + +#pragma pack(1) +typedef struct { + UINT8 Type; // Type == 4 + UINT8 Reserved[3]; + UINT32 NumberOfDomains; + SAL_COHERENCE_DOMAIN_INFO *DomainInformation; +} SAL_ST_CACHE_COHERENCE_DECRIPTOR; +#pragma pack() + +#pragma pack(1) +typedef struct { + UINT8 Type; // Type == 5 + UINT8 WakeUpType; + UINT8 Reserved[6]; + UINT64 ExternalInterruptVector; +} SAL_ST_AP_WAKEUP_DECRIPTOR; +#pragma pack() +// +// FIT Entry +// +#define EFI_SAL_FIT_ENTRY_PTR (0x100000000 - 32) // 4GB - 24 +#define EFI_SAL_FIT_PALA_ENTRY (0x100000000 - 48) // 4GB - 32 +#define EFI_SAL_FIT_PALB_TYPE 01 + +typedef struct { + UINT64 Address; + UINT8 Size[3]; + UINT8 Reserved; + UINT16 Revision; + UINT8 Type : 7; + UINT8 CheckSumValid : 1; + UINT8 CheckSum; +} EFI_SAL_FIT_ENTRY; + +// +// SAL Common Record Header +// +typedef struct { + UINT16 Length; + UINT8 Data[1024]; +} SAL_OEM_DATA; + +typedef struct { + UINT8 Seconds; + UINT8 Minutes; + UINT8 Hours; + UINT8 Reserved; + UINT8 Day; + UINT8 Month; + UINT8 Year; + UINT8 Century; +} SAL_TIME_STAMP; + +typedef struct { + UINT64 RecordId; + UINT16 Revision; + UINT8 ErrorSeverity; + UINT8 ValidationBits; + UINT32 RecordLength; + SAL_TIME_STAMP TimeStamp; + UINT8 OemPlatformId[16]; +} SAL_RECORD_HEADER; + +typedef struct { + EFI_GUID Guid; + UINT16 Revision; + UINT8 ErrorRecoveryInfo; + UINT8 Reserved; + UINT32 SectionLength; +} SAL_SEC_HEADER; + +// +// SAL Processor Record +// +#define SAL_PROCESSOR_ERROR_RECORD_INFO \ + { \ + 0xe429faf1, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define CHECK_INFO_VALID_BIT_MASK 0x1 +#define REQUESTOR_ID_VALID_BIT_MASK 0x2 +#define RESPONDER_ID_VALID_BIT_MASK 0x4 +#define TARGER_ID_VALID_BIT_MASK 0x8 +#define PRECISE_IP_VALID_BIT_MASK 0x10 + +typedef struct { + UINT64 InfoValid : 1; + UINT64 ReqValid : 1; + UINT64 RespValid : 1; + UINT64 TargetValid : 1; + UINT64 IpValid : 1; + UINT64 Reserved : 59; + UINT64 Info; + UINT64 Req; + UINT64 Resp; + UINT64 Target; + UINT64 Ip; +} MOD_ERROR_INFO; + +typedef struct { + UINT8 CpuidInfo[40]; + UINT8 Reserved; +} CPUID_INFO; + +typedef struct { + UINT64 FrLow; + UINT64 FrHigh; +} FR_STRUCT; + +#define MIN_STATE_VALID_BIT_MASK 0x1 +#define BR_VALID_BIT_MASK 0x2 +#define CR_VALID_BIT_MASK 0x4 +#define AR_VALID_BIT_MASK 0x8 +#define RR_VALID_BIT_MASK 0x10 +#define FR_VALID_BIT_MASK 0x20 + +typedef struct { + UINT64 ValidFieldBits; + UINT8 MinStateInfo[1024]; + UINT64 Br[8]; + UINT64 Cr[128]; + UINT64 Ar[128]; + UINT64 Rr[8]; + FR_STRUCT Fr[128]; +} PSI_STATIC_STRUCT; + +#define PROC_ERROR_MAP_VALID_BIT_MASK 0x1 +#define PROC_STATE_PARAMETER_VALID_BIT_MASK 0x2 +#define PROC_CR_LID_VALID_BIT_MASK 0x4 +#define PROC_STATIC_STRUCT_VALID_BIT_MASK 0x8 +#define CPU_INFO_VALID_BIT_MASK 0x1000000 + +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT64 ProcErrorMap; + UINT64 ProcStateParameter; + UINT64 ProcCrLid; + MOD_ERROR_INFO CacheError[15]; + MOD_ERROR_INFO TlbError[15]; + MOD_ERROR_INFO BusError[15]; + MOD_ERROR_INFO RegFileCheck[15]; + MOD_ERROR_INFO MsCheck[15]; + CPUID_INFO CpuInfo; + PSI_STATIC_STRUCT PsiValidData; +} SAL_PROCESSOR_ERROR_RECORD; + +// +// Sal Platform memory Error Record +// +#define SAL_MEMORY_ERROR_RECORD_INFO \ + { \ + 0xe429faf2, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define MEMORY_ERROR_STATUS_VALID_BIT_MASK 0x1 +#define MEMORY_PHYSICAL_ADDRESS_VALID_BIT_MASK 0x2 +#define MEMORY_ADDR_BIT_MASK 0x4 +#define MEMORY_NODE_VALID_BIT_MASK 0x8 +#define MEMORY_CARD_VALID_BIT_MASK 0x10 +#define MEMORY_MODULE_VALID_BIT_MASK 0x20 +#define MEMORY_BANK_VALID_BIT_MASK 0x40 +#define MEMORY_DEVICE_VALID_BIT_MASK 0x80 +#define MEMORY_ROW_VALID_BIT_MASK 0x100 +#define MEMORY_COLUMN_VALID_BIT_MASK 0x200 +#define MEMORY_BIT_POSITION_VALID_BIT_MASK 0x400 +#define MEMORY_PLATFORM_REQUESTOR_ID_VALID_BIT_MASK 0x800 +#define MEMORY_PLATFORM_RESPONDER_ID_VALID_BIT_MASK 0x1000 +#define MEMORY_PLATFORM_TARGET_VALID_BIT_MASK 0x2000 +#define MEMORY_PLATFORM_BUS_SPECIFIC_DATA_VALID_BIT_MASK 0x4000 +#define MEMORY_PLATFORM_OEM_ID_VALID_BIT_MASK 0x8000 +#define MEMORY_PLATFORM_OEM_DATA_STRUCT_VALID_BIT_MASK 0x10000 + +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT64 MemErrorStatus; + UINT64 MemPhysicalAddress; + UINT64 MemPhysicalAddressMask; + UINT16 MemNode; + UINT16 MemCard; + UINT16 MemModule; + UINT16 MemBank; + UINT16 MemDevice; + UINT16 MemRow; + UINT16 MemColumn; + UINT16 MemBitPosition; + UINT64 ModRequestorId; + UINT64 ModResponderId; + UINT64 ModTargetId; + UINT64 BusSpecificData; + UINT8 MemPlatformOemId[16]; +} SAL_MEMORY_ERROR_RECORD; + +// +// PCI BUS Errors +// +#define SAL_PCI_BUS_ERROR_RECORD_INFO \ + { \ + 0xe429faf4, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define PCI_BUS_ERROR_STATUS_VALID_BIT_MASK 0x1 +#define PCI_BUS_ERROR_TYPE_VALID_BIT_MASK 0x2 +#define PCI_BUS_ID_VALID_BIT_MASK 0x4 +#define PCI_BUS_ADDRESS_VALID_BIT_MASK 0x8 +#define PCI_BUS_DATA_VALID_BIT_MASK 0x10 +#define PCI_BUS_CMD_VALID_BIT_MASK 0x20 +#define PCI_BUS_REQUESTOR_ID_VALID_BIT_MASK 0x40 +#define PCI_BUS_RESPONDER_ID_VALID_BIT_MASK 0x80 +#define PCI_BUS_TARGET_VALID_BIT_MASK 0x100 +#define PCI_BUS_OEM_ID_VALID_BIT_MASK 0x200 +#define PCI_BUS_OEM_DATA_STRUCT_VALID_BIT_MASK 0x400 + +typedef struct { + UINT8 BusNumber; + UINT8 SegmentNumber; +} PCI_BUS_ID; + +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT64 PciBusErrorStatus; + UINT16 PciBusErrorType; + PCI_BUS_ID PciBusId; + UINT32 Reserved; + UINT64 PciBusAddress; + UINT64 PciBusData; + UINT64 PciBusCommand; + UINT64 PciBusRequestorId; + UINT64 PciBusResponderId; + UINT64 PciBusTargetId; + UINT8 PciBusOemId[16]; +} SAL_PCI_BUS_ERROR_RECORD; + +// +// PCI Component Errors +// +#define SAL_PCI_COMP_ERROR_RECORD_INFO \ + { \ + 0xe429faf6, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define PCI_COMP_ERROR_STATUS_VALID_BIT_MASK 0x1 +#define PCI_COMP_INFO_VALID_BIT_MASK 0x2 +#define PCI_COMP_MEM_NUM_VALID_BIT_MASK 0x4 +#define PCI_COMP_IO_NUM_VALID_BIT_MASK 0x8 +#define PCI_COMP_REG_DATA_PAIR_VALID_BIT_MASK 0x10 +#define PCI_COMP_OEM_DATA_STRUCT_VALID_BIT_MASK 0x20 + +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT8 ClassCode[3]; + UINT8 FunctionNumber; + UINT8 DeviceNumber; + UINT8 BusNumber; + UINT8 SegmentNumber; + UINT8 Reserved[5]; +} PCI_COMP_INFO; + +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT64 PciComponentErrorStatus; + PCI_COMP_INFO PciComponentInfo; + UINT32 PciComponentMemNum; + UINT32 PciComponentIoNum; + UINT8 PciBusOemId[16]; +} SAL_PCI_COMPONENT_ERROR_RECORD; + +// +// Sal Device Errors Info. +// +#define SAL_DEVICE_ERROR_RECORD_INFO \ + { \ + 0xe429faf3, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define SEL_RECORD_ID_VALID_BIT_MASK 0x1; +#define SEL_RECORD_TYPE_VALID_BIT_MASK 0x2; +#define SEL_GENERATOR_ID_VALID_BIT_MASK 0x4; +#define SEL_EVM_REV_VALID_BIT_MASK 0x8; +#define SEL_SENSOR_TYPE_VALID_BIT_MASK 0x10; +#define SEL_SENSOR_NUM_VALID_BIT_MASK 0x20; +#define SEL_EVENT_DIR_TYPE_VALID_BIT_MASK 0x40; +#define SEL_EVENT_DATA1_VALID_BIT_MASK 0x80; +#define SEL_EVENT_DATA2_VALID_BIT_MASK 0x100; +#define SEL_EVENT_DATA3_VALID_BIT_MASK 0x200; + +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT16 SelRecordId; + UINT8 SelRecordType; + UINT32 TimeStamp; + UINT16 GeneratorId; + UINT8 EvmRevision; + UINT8 SensorType; + UINT8 SensorNum; + UINT8 EventDirType; + UINT8 Data1; + UINT8 Data2; + UINT8 Data3; +} SAL_DEVICE_ERROR_RECORD; + +// +// Sal SMBIOS Device Errors Info. +// +#define SAL_SMBIOS_ERROR_RECORD_INFO \ + { \ + 0xe429faf5, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define SMBIOS_EVENT_TYPE_VALID_BIT_MASK 0x1 +#define SMBIOS_LENGTH_VALID_BIT_MASK 0x2 +#define SMBIOS_TIME_STAMP_VALID_BIT_MASK 0x4 +#define SMBIOS_DATA_VALID_BIT_MASK 0x8 + +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT8 SmbiosEventType; + UINT8 SmbiosLength; + UINT8 SmbiosBcdTimeStamp[6]; +} SAL_SMBIOS_DEVICE_ERROR_RECORD; + +// +// Sal Platform Specific Errors Info. +// +#define SAL_PLATFORM_ERROR_RECORD_INFO \ + { \ + 0xe429faf7, 0x3cb7, 0x11d4, {0xbc, 0xa7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +#define PLATFORM_ERROR_STATUS_VALID_BIT_MASK 0x1 +#define PLATFORM_REQUESTOR_ID_VALID_BIT_MASK 0x2 +#define PLATFORM_RESPONDER_ID_VALID_BIT_MASK 0x4 +#define PLATFORM_TARGET_VALID_BIT_MASK 0x8 +#define PLATFORM_SPECIFIC_DATA_VALID_BIT_MASK 0x10 +#define PLATFORM_OEM_ID_VALID_BIT_MASK 0x20 +#define PLATFORM_OEM_DATA_STRUCT_VALID_BIT_MASK 0x40 +#define PLATFORM_OEM_DEVICE_PATH_VALID_BIT_MASK 0x80 + +typedef struct { + SAL_SEC_HEADER SectionHeader; + UINT64 ValidationBits; + UINT64 PlatformErrorStatus; + UINT64 PlatformRequestorId; + UINT64 PlatformResponderId; + UINT64 PlatformTargetId; + UINT64 PlatformBusSpecificData; + UINT8 OemComponentId[16]; +} SAL_PLATFORM_SPECIFIC_ERROR_RECORD; + +// +// Union of all the possible Sal Record Types +// +typedef union { + SAL_RECORD_HEADER *RecordHeader; + SAL_PROCESSOR_ERROR_RECORD *SalProcessorRecord; + SAL_PCI_BUS_ERROR_RECORD *SalPciBusRecord; + SAL_PCI_COMPONENT_ERROR_RECORD *SalPciComponentRecord; + SAL_DEVICE_ERROR_RECORD *ImpiRecord; + SAL_SMBIOS_DEVICE_ERROR_RECORD *SmbiosRecord; + SAL_PLATFORM_SPECIFIC_ERROR_RECORD *PlatformRecord; + SAL_MEMORY_ERROR_RECORD *MemoryRecord; + UINT8 *Raw; +} SAL_ERROR_RECORDS_POINTERS; + +#pragma pack() + +#endif diff --git a/MdePkg/Include/Library/BaseLib.h b/MdePkg/Include/Library/BaseLib.h new file mode 100644 index 0000000000..ff663c91b7 --- /dev/null +++ b/MdePkg/Include/Library/BaseLib.h @@ -0,0 +1,4861 @@ +/** @file + Memory-only library functions with no library constructor/destructor + + Copyright (c) 2006, 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. + + Module Name: BaseLib.h + +**/ + +#ifndef __BASE_LIB__ +#define __BASE_LIB__ + +// +// Definitions for architecture specific types +// These include SPIN_LOCK and BASE_LIBRARY_JUMP_BUFFER +// + +// +// SPIN_LOCK +// +typedef UINTN SPIN_LOCK; + +#if defined (MDE_CPU_IA32) +// +// IA32 context buffer used by SetJump() and LongJump() +// +typedef struct { + UINT32 Ebx; + UINT32 Esi; + UINT32 Edi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Eip; +} BASE_LIBRARY_JUMP_BUFFER; + +#elif defined (MDE_CPU_IPF) +// +// IPF context buffer used by SetJump() and LongJump() +// +typedef struct { + UINT64 InitialUNAT; + UINT64 AfterSpillUNAT; + UINT64 PFS; + UINT64 BSP; + UINT64 RNAT; + UINT64 Predicates; + UINT64 LoopCount; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 SP; + UINT64 F2Low; + UINT64 F2High; + UINT64 F3Low; + UINT64 F3High; + UINT64 F4Low; + UINT64 F4High; + UINT64 F5Low; + UINT64 F5High; + UINT64 F16Low; + UINT64 F16High; + UINT64 F17Low; + UINT64 F17High; + UINT64 F18Low; + UINT64 F18High; + UINT64 F19Low; + UINT64 F19High; + UINT64 F20Low; + UINT64 F20High; + UINT64 F21Low; + UINT64 F21High; + UINT64 F22Low; + UINT64 F22High; + UINT64 F23Low; + UINT64 F23High; + UINT64 F24Low; + UINT64 F24High; + UINT64 F25Low; + UINT64 F25High; + UINT64 F26Low; + UINT64 F26High; + UINT64 F27Low; + UINT64 F27High; + UINT64 F28Low; + UINT64 F28High; + UINT64 F29Low; + UINT64 F29High; + UINT64 F30Low; + UINT64 F30High; + UINT64 F31Low; + UINT64 F31High; + UINT64 FPSR; + UINT64 BR0; + UINT64 BR1; + UINT64 BR2; + UINT64 BR3; + UINT64 BR4; + UINT64 BR5; +} BASE_LIBRARY_JUMP_BUFFER; + +#elif defined (MDE_CPU_X64) +// +// X64 context buffer used by SetJump() and LongJump() +// +typedef struct { + UINT64 Rbx; + UINT64 Rsp; + UINT64 Rbp; + UINT64 Rdi; + UINT64 Rsi; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 Rip; +} BASE_LIBRARY_JUMP_BUFFER; + +#elif defined (MDE_CPU_EBC) +// +// EBC context buffer used by SetJump() and LongJump() +// +typedef struct { + UINT64 R0; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 IP; +} BASE_LIBRARY_JUMP_BUFFER; + +#else +#error Unknown Processor Type +#endif + +// +// String Services +// + +/** + Copies one Null-terminated Unicode string to another Null-terminated Unicode + string and returns the new Unicode string. + + This function copies the contents of the Unicode string Source to the Unicode + string Destination, and returns Destination. If Source and Destination + overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated Unicode string. + @param Source Pointer to a Null-terminated Unicode string. + + @return Destiantion + +**/ +CHAR16 * +EFIAPI +StrCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ); + +/** + Copies one Null-terminated Unicode string with a maximum length to another + Null-terminated Unicode string with a maximum length and returns the new + Unicode string. + + This function copies the contents of the Unicode string Source to the Unicode + string Destination, and returns Destination. At most, Length Unicode + characters are copied from Source to Destination. If Length is 0, then + Destination is returned unmodified. If Length is greater that the number of + Unicode characters in Source, then Destination is padded with Null Unicode + characters. If Source and Destination overlap, then the results are + undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated Unicode string. + @param Source Pointer to a Null-terminated Unicode string. + @param Length Maximum number of Unicode characters to copy. + + @return Destination + +**/ +CHAR16 * +EFIAPI +StrnCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source, + IN UINTN Length + ); + +/** + Returns the length of a Null-terminated Unicode string. + + This function returns the number of Unicode characters in the Null-terminated + Unicode string specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + + @return The length of String. + +**/ +UINTN +EFIAPI +StrLen ( + IN CONST CHAR16 *String + ); + +/** + Returns the size of a Null-terminated Unicode string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated Unicode + string specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + + @return The size of String. + +**/ +UINTN +EFIAPI +StrSize ( + IN CONST CHAR16 *String + ); + +/** + Compares two Null-terminated Unicode strings, and returns the difference + between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched Unicode character in SecondString subtracted from the first + mismatched Unicode character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param FirstString Pointer to a Null-terminated Unicode string. + @param SecondString Pointer to a Null-terminated Unicode string. + + @retval 0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString + ); + +/** + Compares two Null-terminated Unicode strings with maximum lengths, and + returns the difference between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. At most, Length Unicode + characters will be compared. If Length is 0, then 0 is returned. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched Unicode character in SecondString + subtracted from the first mismatched Unicode character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param FirstString Pointer to a Null-terminated Unicode string. + @param SecondString Pointer to a Null-terminated Unicode string. + @param Length Maximum number of Unicode characters to compare. + + @retval 0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrnCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString, + IN UINTN Length + ); + +/** + Concatenates one Null-terminated Unicode string to another Null-terminated + Unicode string, and returns the concatenated Unicode string. + + This function concatenates two Null-terminated Unicode strings. The contents + of Null-terminated Unicode string Source are concatenated to the end of + Null-terminated Unicode string Destination. The Null-terminated concatenated + Unicode String is returned. If Source and Destination overlap, then the + results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Destination contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination + and Source results in a Unicode string with more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated Unicode string. + @param Source Pointer to a Null-terminated Unicode string. + + @return Destination + +**/ +CHAR16 * +EFIAPI +StrCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ); + +/** + Concatenates one Null-terminated Unicode string with a maximum length to the + end of another Null-terminated Unicode string, and returns the concatenated + Unicode string. + + This function concatenates two Null-terminated Unicode strings. The contents + of Null-terminated Unicode string Source are concatenated to the end of + Null-terminated Unicode string Destination, and Destination is returned. At + most, Length Unicode characters are concatenated from Source to the end of + Destination, and Destination is always Null-terminated. If Length is 0, then + Destination is returned unmodified. If Source and Destination overlap, then + the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Destination contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination + and Source results in a Unicode string with more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated Unicode string. + @param Source Pointer to a Null-terminated Unicode string. + @param Length Maximum number of Unicode characters to concatenate from + Source. + + @return Destination + +**/ +CHAR16 * +EFIAPI +StrnCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source, + IN UINTN Length + ); + +/** + Copies one Null-terminated ASCII string to another Null-terminated ASCII + string and returns the new ASCII string. + + This function copies the contents of the ASCII string Source to the ASCII + string Destination, and returns Destination. If Source and Destination + overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated ASCII string. + @param Source Pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ); + +/** + Copies one Null-terminated ASCII string with a maximum length to another + Null-terminated ASCII string with a maximum length and returns the new ASCII + string. + + This function copies the contents of the ASCII string Source to the ASCII + string Destination, and returns Destination. At most, Length ASCII characters + are copied from Source to Destination. If Length is 0, then Destination is + returned unmodified. If Length is greater that the number of ASCII characters + in Source, then Destination is padded with Null ASCII characters. If Source + and Destination overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated ASCII string. + @param Source Pointer to a Null-terminated ASCII string. + @param Length Maximum number of ASCII characters to copy. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrnCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source, + IN UINTN Length + ); + +/** + Returns the length of a Null-terminated ASCII string. + + This function returns the number of ASCII characters in the Null-terminated + ASCII string specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param String Pointer to a Null-terminated ASCII string. + + @return The length of String. + +**/ +UINTN +EFIAPI +AsciiStrLen ( + IN CONST CHAR8 *String + ); + +/** + Returns the size of a Null-terminated ASCII string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated ASCII string + specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param String Pointer to a Null-terminated ASCII string. + + @return The size of String. + +**/ +UINTN +EFIAPI +AsciiStrSize ( + IN CONST CHAR8 *String + ); + +/** + Compares two Null-terminated ASCII strings, and returns the difference + between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched ASCII character in SecondString subtracted from the first + mismatched ASCII character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param FirstString Pointer to a Null-terminated ASCII string. + @param SecondString Pointer to a Null-terminated ASCII string. + + @retval 0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ); + +/** + Performs a case insensitive comparison of two Null-terminated ASCII strings, + and returns the difference between the first mismatched ASCII characters. + + This function performs a case insensitive comparison of the Null-terminated + ASCII string FirstString to the Null-terminated ASCII string SecondString. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched lower case ASCII character in + SecondString subtracted from the first mismatched lower case ASCII character + in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param FirstString Pointer to a Null-terminated ASCII string. + @param SecondString Pointer to a Null-terminated ASCII string. + + @retval 0 FirstString is identical to SecondString using case insensitive + comparisons. + @retval !=0 FirstString is not identical to SecondString using case + insensitive comparisons. + +**/ +INTN +EFIAPI +AsciiStriCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ); + +/** + Compares two Null-terminated ASCII strings with maximum lengths, and returns + the difference between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. At most, Length ASCII characters + will be compared. If Length is 0, then 0 is returned. If FirstString is + identical to SecondString, then 0 is returned. Otherwise, the value returned + is the first mismatched ASCII character in SecondString subtracted from the + first mismatched ASCII character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param FirstString Pointer to a Null-terminated ASCII string. + @param SecondString Pointer to a Null-terminated ASCII string. + + @retval 0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrnCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString, + IN UINTN Length + ); + +/** + Concatenates one Null-terminated ASCII string to another Null-terminated + ASCII string, and returns the concatenated ASCII string. + + This function concatenates two Null-terminated ASCII strings. The contents of + Null-terminated ASCII string Source are concatenated to the end of Null- + terminated ASCII string Destination. The Null-terminated concatenated ASCII + String is returned. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Destination contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and concatenating Destination and + Source results in a ASCII string with more than PcdMaximumAsciiStringLength + ASCII characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated ASCII string. + @param Source Pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ); + +/** + Concatenates one Null-terminated ASCII string with a maximum length to the + end of another Null-terminated ASCII string, and returns the concatenated + ASCII string. + + This function concatenates two Null-terminated ASCII strings. The contents + of Null-terminated ASCII string Source are concatenated to the end of Null- + terminated ASCII string Destination, and Destination is returned. At most, + Length ASCII characters are concatenated from Source to the end of + Destination, and Destination is always Null-terminated. If Length is 0, then + Destination is returned unmodified. If Source and Destination overlap, then + the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Destination contains more + than PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and concatenating Destination and + Source results in a ASCII string with more than PcdMaximumAsciiStringLength + ASCII characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated ASCII string. + @param Source Pointer to a Null-terminated ASCII string. + @param Length Maximum number of ASCII characters to concatenate from + Source. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrnCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source, + IN UINTN Length + ); + +// +// LIST_ENTRY definition +// +typedef struct _LIST_ENTRY LIST_ENTRY; + +struct _LIST_ENTRY { + LIST_ENTRY *ForwardLink; + LIST_ENTRY *BackLink; +}; + +// +// Linked List Functions and Macros +// + +/** + Initializes the head node of a doubly linked list that is declared as a + global variable in a module. + + Initializes the forward and backward links of a new linked list. After + initializing a linked list with this macro, the other linked list functions + may be used to add and remove nodes from the linked list. This macro results + in smaller executables by initializing the linked list in the data section, + instead if calling the InitializeListHead() function to perform the + equivalent operation. + + @param ListHead The head note of a list to initiailize. + +**/ +#define INITIALIZE_LIST_HEAD_VARIABLE(ListHead) {&ListHead, &ListHead} + +/** + Initializes the head node of a doubly linked list, and returns the pointer to + the head node of the doubly linked list. + + Initializes the forward and backward links of a new linked list. After + initializing a linked list with this function, the other linked list + functions may be used to add and remove nodes from the linked list. It is up + to the caller of this function to allocate the memory for ListHead. + + If ListHead is NULL, then ASSERT(). + + @param ListHead A pointer to the head node of a new doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InitializeListHead ( + IN LIST_ENTRY *ListHead + ); + +/** + Adds a node to the beginning of a doubly linked list, and returns the pointer + to the head node of the doubly linked list. + + Adds the node Entry at the beginning of the doubly linked list denoted by + ListHead, and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and ListHead contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + @param Entry A pointer to a node that is to be inserted at the beginning + of a doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertHeadList ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Entry + ); + +/** + Adds a node to the end of a doubly linked list, and returns the pointer to + the head node of the doubly linked list. + + Adds the node Entry to the end of the doubly linked list denoted by ListHead, + and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and ListHead contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + @param Entry A pointer to a node that is to be added at the end of the + doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertTailList ( + IN LIST_ENTRY *ListHead, + IN LIST_ENTRY *Entry + ); + +/** + Retrieves the first node of a doubly linked list. + + Returns the first node of a doubly linked list. List must have been + initialized with InitializeListHead(). If List is empty, then NULL is + returned. + + If List is NULL, then ASSERT(). + If List was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + + @return The first node of a doubly linked list. + @retval NULL The list is empty. + +**/ +LIST_ENTRY * +EFIAPI +GetFirstNode ( + IN CONST LIST_ENTRY *List + ); + +/** + Retrieves the next node of a doubly linked list. + + Returns the node of a doubly linked list that follows Node. List must have + been initialized with InitializeListHead(). If List is empty, then List is + returned. + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + If Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @return Pointer to the next node if one exists. Otherwise a null value which + is actually List is returned. + +**/ +LIST_ENTRY * +EFIAPI +GetNextNode ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + +/** + Checks to see if a doubly linked list is empty or not. + + Checks to see if the doubly linked list is empty. If the linked list contains + zero nodes, this function returns TRUE. Otherwise, it returns FALSE. + + If ListHead is NULL, then ASSERT(). + If ListHead was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + + @retval TRUE The linked list is empty. + @retval FALSE The linked list is not empty. + +**/ +BOOLEAN +EFIAPI +IsListEmpty ( + IN CONST LIST_ENTRY *ListHead + ); + +/** + Determines if a node in a doubly linked list is null. + + Returns FALSE if Node is one of the nodes in the doubly linked list specified + by List. Otherwise, TRUE is returned. List must have been initialized with + InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + If Node is not a node in List and Node is not equal to List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @retval TRUE Node is one of the nodes in the doubly linked list. + @retval FALSE Node is not one of the nodes in the doubly linked list. + +**/ +BOOLEAN +EFIAPI +IsNull ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + +/** + Determines if a node the last node in a doubly linked list. + + Returns TRUE if Node is the last node in the doubly linked list specified by + List. Otherwise, FALSE is returned. List must have been initialized with + InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + If Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @retval TRUE Node is the last node in the linked list. + @retval FALSE Node is not the last node in the linked list. + +**/ +BOOLEAN +EFIAPI +IsNodeAtEnd ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ); + +/** + Swaps the location of two nodes in a doubly linked list, and returns the + first node after the swap. + + If FirstEntry is identical to SecondEntry, then SecondEntry is returned. + Otherwise, the location of the FirstEntry node is swapped with the location + of the SecondEntry node in a doubly linked list. SecondEntry must be in the + same double linked list as FirstEntry and that double linked list must have + been initialized with InitializeListHead(). SecondEntry is returned after the + nodes are swapped. + + If FirstEntry is NULL, then ASSERT(). + If SecondEntry is NULL, then ASSERT(). + If SecondEntry and FirstEntry are not in the same linked list, then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the linked list containing + FirstEntry and SecondEntry contains more than PcdMaximumLinkedListLenth + nodes, then ASSERT(). + + @param FirstEntry A pointer to a node in a linked list. + @param SecondEntry A pointer to another node in the same linked list. + +**/ +LIST_ENTRY * +EFIAPI +SwapListEntries ( + IN LIST_ENTRY *FirstEntry, + IN LIST_ENTRY *SecondEntry + ); + +/** + Removes a node from a doubly linked list, and returns the node that follows + the removed node. + + Removes the node Entry from a doubly linked list. It is up to the caller of + this function to release the memory used by this node if that is required. On + exit, the node following Entry in the doubly linked list is returned. If + Entry is the only node in the linked list, then the head node of the linked + list is returned. + + If Entry is NULL, then ASSERT(). + If Entry is the head node of an empty list, then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the linked list containing + Entry contains more than PcdMaximumLinkedListLenth nodes, then ASSERT(). + + @param Entry A pointer to a node in a linked list + + @return Entry + +**/ +LIST_ENTRY * +EFIAPI +RemoveEntryList ( + IN CONST LIST_ENTRY *Entry + ); + +// +// Math Services +// + +/** + Shifts a 64-bit integer left between 0 and 63 bits. The low bits are filled + with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the left by Count bits. The + low Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift left. + @param Count The number of bits to shift left. + + @return Operand << Count + +**/ +UINT64 +EFIAPI +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Shifts a 64-bit integer right between 0 and 63 bits. This high bits are + filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits are filled + with original integer's bit 63. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to bit 63 of Operand. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +ARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Rotates a 32-bit integer left between 0 and 31 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 32-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand <<< Count + +**/ +UINT32 +EFIAPI +LRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ); + +/** + Rotates a 32-bit integer right between 0 and 31 bits, filling the high bits + with the low bits that were rotated. + + This function rotates the 32-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >>> Count + +**/ +UINT32 +EFIAPI +RRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ); + +/** + Rotates a 64-bit integer left between 0 and 63 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 64-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand <<< Count + +**/ +UINT64 +EFIAPI +LRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Rotates a 64-bit integer right between 0 and 63 bits, filling the high bits + with the high low bits that were rotated. + + This function rotates the 64-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >>> Count + +**/ +UINT64 +EFIAPI +RRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +/** + Returns the bit position of the lowest bit set in a 32-bit value. + + This function computes the bit position of the lowest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @return Position of the lowest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +LowBitSet32 ( + IN UINT32 Operand + ); + +/** + Returns the bit position of the lowest bit set in a 64-bit value. + + This function computes the bit position of the lowest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @return Position of the lowest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +LowBitSet64 ( + IN UINT64 Operand + ); + +/** + Returns the bit position of the highest bit set in a 32-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @return Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet32 ( + IN UINT32 Operand + ); + +/** + Returns the bit position of the highest bit set in a 64-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @return Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet64 ( + IN UINT64 Operand + ); + +/** + Returns the value of the highest bit set in a 32-bit value. Equivalent to + 1 << HighBitSet32(x). + + This function computes the value of the highest bit set in the 32-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 32-bit operand to evaluate. + + @return 1 << HighBitSet32(Operand) + @retval 0 Operand is zero. + +**/ +UINT32 +EFIAPI +GetPowerOfTwo32 ( + IN UINT32 Operand + ); + +/** + Returns the value of the highest bit set in a 64-bit value. Equivalent to + 1 << HighBitSet64(x). + + This function computes the value of the highest bit set in the 64-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 64-bit operand to evaluate. + + @return 1 << HighBitSet64(Operand) + @retval 0 Operand is zero. + +**/ +UINT64 +EFIAPI +GetPowerOfTwo64 ( + IN UINT64 Operand + ); + +/** + Switches the endianess of a 16-bit integer. + + This function swaps the bytes in a 16-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Operand A 16-bit unsigned value. + + @return The byte swaped Operand. + +**/ +UINT16 +EFIAPI +SwapBytes16 ( + IN UINT16 Value + ); + +/** + Switches the endianess of a 32-bit integer. + + This function swaps the bytes in a 32-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Operand A 32-bit unsigned value. + + @return The byte swaped Operand. + +**/ +UINT32 +EFIAPI +SwapBytes32 ( + IN UINT32 Value + ); + +/** + Switches the endianess of a 64-bit integer. + + This function swaps the bytes in a 64-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Operand A 64-bit unsigned value. + + @return The byte swaped Operand. + +**/ +UINT64 +EFIAPI +SwapBytes64 ( + IN UINT64 Value + ); + +/** + Multiples a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiples the 64-bit unsigned value Multiplicand by the 32-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + If the result overflows, then ASSERT(). + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 32-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ); + +/** + Multiples a 64-bit unsigned integer by a 64-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiples the 64-bit unsigned value Multiplicand by the 64-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + If the result overflows, then ASSERT(). + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +MultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ); + +/** + Multiples a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result. + + This function multiples the 64-bit signed value Multiplicand by the 64-bit + signed value Multiplier and generates a 64-bit signed result. This 64-bit + signed result is returned. + + If the result overflows, then ASSERT(). + + @param Multiplicand A 64-bit signed value. + @param Multiplier A 64-bit signed value. + + @return Multiplicand * Multiplier + +**/ +INT64 +EFIAPI +MultS64x64 ( + IN INT64 Multiplicand, + IN INT64 Multiplier + ); + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. This + function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 32-bit remainder. This function + returns the 32-bit unsigned remainder. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend % Divisor + +**/ +UINT32 +EFIAPI +ModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result and an optional 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 32-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x32Remainder ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder OPTIONAL + ); + +/** + Divides a 64-bit unsigned integer by a 64-bit unsigned integer and generates + a 64-bit unsigned result and an optional 64-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 64-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 64-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 64-bit unsigned value. + @param Remainder A pointer to a 64-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x64Remainder ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder OPTIONAL + ); + +/** + Divides a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result and a optional 64-bit signed remainder. + + This function divides the 64-bit signed value Dividend by the 64-bit signed + value Divisor and generates a 64-bit signed quotient. If Remainder is not + NULL, then the 64-bit signed remainder is returned in Remainder. This + function returns the 64-bit signed quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit signed value. + @param Divisor A 64-bit signed value. + @param Remainder A pointer to a 64-bit signed value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +INT64 +EFIAPI +DivS64x64Remainder ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder OPTIONAL + ); + +/** + Reads a 16-bit value from memory that may be unaligned. + + This function returns the 16-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 16-bit value that may be unaligned. + + @return *Uint16 + +**/ +UINT16 +EFIAPI +ReadUnaligned16 ( + IN CONST UINT16 *Uint16 + ); + +/** + Writes a 16-bit value to memory that may be unaligned. + + This function writes the 16-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 16-bit value that may be unaligned. + @param Value 16-bit value to write to Buffer. + + @return Value + +**/ +UINT16 +EFIAPI +WriteUnaligned16 ( + OUT UINT16 *Uint16, + IN UINT16 Value + ); + +/** + Reads a 24-bit value from memory that may be unaligned. + + This function returns the 24-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 24-bit value that may be unaligned. + + @return The value read. + +**/ +UINT32 +EFIAPI +ReadUnaligned24 ( + IN CONST UINT32 *Buffer + ); + +/** + Writes a 24-bit value to memory that may be unaligned. + + This function writes the 24-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 24-bit value that may be unaligned. + @param Value 24-bit value to write to Buffer. + + @return The value written. + +**/ +UINT32 +EFIAPI +WriteUnaligned24 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ); + +/** + Reads a 32-bit value from memory that may be unaligned. + + This function returns the 32-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 32-bit value that may be unaligned. + + @return *Uint32 + +**/ +UINT32 +EFIAPI +ReadUnaligned32 ( + IN CONST UINT32 *Uint32 + ); + +/** + Writes a 32-bit value to memory that may be unaligned. + + This function writes the 32-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 32-bit value that may be unaligned. + @param Value 32-bit value to write to Buffer. + + @return Value + +**/ +UINT32 +EFIAPI +WriteUnaligned32 ( + OUT UINT32 *Uint32, + IN UINT32 Value + ); + +/** + Reads a 64-bit value from memory that may be unaligned. + + This function returns the 64-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 64-bit value that may be unaligned. + + @return *Uint64 + +**/ +UINT64 +EFIAPI +ReadUnaligned64 ( + IN CONST UINT64 *Uint64 + ); + +/** + Writes a 64-bit value to memory that may be unaligned. + + This function writes the 64-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 64-bit value that may be unaligned. + @param Value 64-bit value to write to Buffer. + + @return Value + +**/ +UINT64 +EFIAPI +WriteUnaligned64 ( + OUT UINT64 *Uint64, + IN UINT64 Value + ); + +// +// Bit Field Functions +// + +/** + Returns a bit field from an 8-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The bit field read. + +**/ +UINT8 +EFIAPI +BitFieldRead8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to an 8-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 8-bit value is + returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldWrite8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ); + +/** + Reads a bit field from an 8-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise inclusive OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the value + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ); + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAnd8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ); + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + inclusive OR with value specified by OrData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAndThenOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Returns a bit field from a 16-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The bit field read. + +**/ +UINT16 +EFIAPI +BitFieldRead16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a 16-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 16-bit value is + returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldWrite16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ); + +/** + Reads a bit field from a 16-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise inclusive OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the value + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ); + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAnd16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ); + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + inclusive OR with value specified by OrData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAndThenOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Returns a bit field from a 32-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read. + +**/ +UINT32 +EFIAPI +BitFieldRead32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a 32-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 32-bit value is + returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldWrite32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + +/** + Reads a bit field from a 32-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise inclusive OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the value + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAnd32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + inclusive OR with value specified by OrData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAndThenOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Returns a bit field from a 64-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The bit field read. + +**/ +UINT64 +EFIAPI +BitFieldRead64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a 64-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 64-bit value is + returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldWrite64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ); + +/** + Reads a bit field from a 64-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise inclusive OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the value + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ); + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAnd64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ); + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + inclusive OR with value specified by OrData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAndThenOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ); + +// +// Base Library Synchronization Functions +// + +/** + Retrieves the architecture specific spin lock alignment requirements for + optimal spin lock performance. + + This function retrieves the spin lock alignment requirements for optimal + performance on a given CPU architecture. The spin lock alignment must be a + power of two and is returned by this function. If there are no alignment + requirements, then 1 must be returned. The spin lock synchronization + functions must function correctly if the spin lock size and alignment values + returned by this function are not used at all. These values are hints to the + consumers of the spin lock synchronization functions to obtain optimal spin + lock performance. + + @return The architecture specific spin lock alignment. + +**/ +UINTN +EFIAPI +GetSpinLockProperties ( + VOID + ); + +/** + Initializes a spin lock to the released state and returns the spin lock. + + This function initializes the spin lock specified by SpinLock to the released + state, and returns SpinLock. Optimal performance can be achieved by calling + GetSpinLockProperties() to determine the size and alignment requirements for + SpinLock. + + If SpinLock is NULL, then ASSERT(). + + @param SpinLock A pointer to the spin lock to initialize to the released + state. + + @return SpinLock + +**/ +SPIN_LOCK * +EFIAPI +InitializeSpinLock ( + IN SPIN_LOCK *SpinLock + ); + +/** + Waits until a spin lock can be placed in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns SpinLock. Otherwise, this function waits + indefinitely for the spin lock to be released, and then places it in the + acquired state and returns SpinLock. All state transitions of SpinLock must + be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in + PcdSpinLockTimeout microseconds, then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @return SpinLock + +**/ +SPIN_LOCK * +EFIAPI +AcquireSpinLock ( + IN SPIN_LOCK *SpinLock + ); + +/** + Attempts to place a spin lock in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns TRUE. Otherwise, FALSE is returned. All state + transitions of SpinLock must be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @retval TRUE SpinLock was placed in the acquired state. + @retval FALSE SpinLock could not be acquired. + +**/ +BOOLEAN +EFIAPI +AcquireSpinLockOrFail ( + IN SPIN_LOCK *SpinLock + ); + +/** + Releases a spin lock. + + This function places the spin lock specified by SpinLock in the release state + and returns SpinLock. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to release. + + @return SpinLock + +**/ +SPIN_LOCK * +EFIAPI +ReleaseSpinLock ( + IN SPIN_LOCK *SpinLock + ); + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InterlockedIncrement ( + IN UINT32 *Value + ); + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InterlockedDecrement ( + IN UINT32 *Value + ); + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InterlockedCompareExchange32 ( + IN UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ); + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InterlockedCompareExchange64 ( + IN UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ); + +/** + Performs an atomic compare exchange operation on a pointer value. + + Performs an atomic compare exchange operation on the pointer value specified + by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the pointer value for the compare exchange + operation. + @param CompareValue Pointer value used in compare operation. + @param ExchangeValue Pointer value used in exchange operation. + +**/ +VOID * +EFIAPI +InterlockedCompareExchangePointer ( + IN VOID **Value, + IN VOID *CompareValue, + IN VOID *ExchangeValue + ); + +// +// Base Library CPU Functions +// +typedef +VOID +(EFIAPI *SWITCH_STACK_ENTRY_POINT) ( + IN VOID *Context1, OPTIONAL + IN VOID *Context2 OPTIONAL + ); + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ); + +/** + Saves the current CPU context that can be restored with a call to LongJump() + and returns 0. + + Saves the current CPU context in the buffer specified by JumpBuffer and + returns 0. The initial call to SetJump() must always return 0. Subsequent + calls to LongJump() cause a non-zero value to be returned by SetJump(). + + If JumpBuffer is NULL, then ASSERT(). + + @param JumpBuffer A pointer to CPU context buffer. + + @retval 0 Indicates a return from SetJump(). + +**/ +UINTN +EFIAPI +SetJump ( + OUT BASE_LIBRARY_JUMP_BUFFER *JumpBuffer + ); + +/** + Restores the CPU context that was saved with SetJump(). + + Restores the CPU context from the buffer specified by JumpBuffer. This + function never returns to the caller. Instead is resumes execution based on + the state of JumpBuffer. + + If JumpBuffer is NULL, then ASSERT(). + If Value is 0, then ASSERT(). + + @param JumpBuffer A pointer to CPU context buffer. + @param Value The value to return when the SetJump() context is + restored and must be non-zero. + +**/ +VOID +EFIAPI +LongJump ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, + IN UINTN Value + ); + +/** + Enables CPU interrupts. + + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ); + +/** + Disables CPU interrupts. + + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ); + +/** + Disables CPU interrupts and returns the interrupt state prior to the disable + operation. + + Disables CPU interrupts and returns the interrupt state prior to the disable + operation. + + @retval TRUE CPU interrupts were enabled on entry to this call. + @retval FALSE CPU interrupts were disabled on entry to this call. + +**/ +BOOLEAN +EFIAPI +SaveAndDisableInterrupts ( + VOID + ); + +/** + Enables CPU interrupts for the smallest window required to capture any + pending interrupts. + + Enables CPU interrupts for the smallest window required to capture any + pending interrupts. + +**/ +VOID +EFIAPI +EnableDisableInterrupts ( + VOID + ); + +/** + Retrieves the current CPU interrupt state. + + Retrieves the current CPU interrupt state. Returns TRUE is interrupts are + currently enabled. Otherwise returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + VOID + ); + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +EFIAPI +SetInterruptState ( + IN BOOLEAN InterruptState + ); + +/** + Places the CPU in a sleep state until an interrupt is received. + + Places the CPU in a sleep state until an interrupt is received. If interrupts + are disabled prior to calling this function, then the CPU will be placed in a + sleep state indefinitely. + +**/ +VOID +EFIAPI +CpuSleep ( + VOID + ); + +/** + Requests CPU to pause for a short period of time. + + Requests CPU to pause for a short period of time. Typically used in MP + systems to prevent memory starvation while waiting for a spin lock. + +**/ +VOID +EFIAPI +CpuPause ( + VOID + ); + +/** + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + + Flushes all the Translation Lookaside Buffers(TLB) entries in a CPU. + +**/ +VOID +EFIAPI +CpuFlushTlb ( + VOID + ); + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + +**/ +VOID +EFIAPI +SwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ); + +/** + Executes an infinite loop. + + Forces the CPU to execute an infinite loop. A debugger may be used to skip + past the loop and the code that follows the loop must execute properly. This + implies that the infinite loop must not cause the code that follow it to be + optimized away. + +**/ +VOID +EFIAPI +CpuDeadLoop ( + VOID + ); + +// +// IA32 and X64 Specific Functions +// +// +// Byte packed structure for 16-bit Real Mode EFLAGS +// +typedef union { + struct { + UINT32 CF:1; // Carry Flag + UINT32 Reserved_0:1; // Reserved + UINT32 PF:1; // Parity Flag + UINT32 Reserved_1:1; // Reserved + UINT32 AF:1; // Auxiliary Carry Flag + UINT32 Reserved_2:1; // Reserved + UINT32 ZF:1; // Zero Flag + UINT32 SF:1; // Sign Flag + UINT32 TF:1; // Trap Flag + UINT32 IF:1; // Interrupt Enable Flag + UINT32 DF:1; // Direction Flag + UINT32 OF:1; // Overflow Flag + UINT32 IOPL:2; // I/O Privilege Level + UINT32 NT:1; // Nested Task + UINT32 Reserved_3:1; // Reserved + } Bits; + UINT16 Uint16; +} IA32_FLAGS16; + +// +// Byte packed structure for EFLAGS/RFLAGS +// 32-bits on IA-32 +// 64-bits on X64. The upper 32-bits on X64 are reserved +// +typedef union { + struct { + UINT32 CF:1; // Carry Flag + UINT32 Reserved_0:1; // Reserved + UINT32 PF:1; // Parity Flag + UINT32 Reserved_1:1; // Reserved + UINT32 AF:1; // Auxiliary Carry Flag + UINT32 Reserved_2:1; // Reserved + UINT32 ZF:1; // Zero Flag + UINT32 SF:1; // Sign Flag + UINT32 TF:1; // Trap Flag + UINT32 IF:1; // Interrupt Enable Flag + UINT32 DF:1; // Direction Flag + UINT32 OF:1; // Overflow Flag + UINT32 IOPL:2; // I/O Privilege Level + UINT32 NT:1; // Nested Task + UINT32 Reserved_3:1; // Reserved + UINT32 RF:1; // Resume Flag + UINT32 VM:1; // Virtual 8086 Mode + UINT32 AC:1; // Alignment Check + UINT32 VIF:1; // Virtual Interrupt Flag + UINT32 VIP:1; // Virtual Interrupt Pending + UINT32 ID:1; // ID Flag + UINT32 Reserved_4:10; // Reserved + } Bits; + UINTN UintN; +} IA32_EFLAGS32; + +// +// Byte packed structure for Control Register 0 (CR0) +// 32-bits on IA-32 +// 64-bits on X64. The upper 32-bits on X64 are reserved +// +typedef union { + struct { + UINT32 PE:1; // Protection Enable + UINT32 MP:1; // Monitor Coprocessor + UINT32 EM:1; // Emulation + UINT32 TS:1; // Task Switched + UINT32 ET:1; // Extension Type + UINT32 NE:1; // Numeric Error + UINT32 Reserved_0:10; // Reserved + UINT32 WP:1; // Write Protect + UINT32 Reserved_1:1; // Reserved + UINT32 AM:1; // Alignment Mask + UINT32 Reserved_2:10; // Reserved + UINT32 NW:1; // Mot Write-through + UINT32 CD:1; // Cache Disable + UINT32 PG:1; // Paging + } Bits; + UINTN UintN; +} IA32_CR0; + +// +// Byte packed structure for Control Register 4 (CR4) +// 32-bits on IA-32 +// 64-bits on X64. The upper 32-bits on X64 are reserved +// +typedef union { + struct { + UINT32 VME:1; // Virtual-8086 Mode Extensions + UINT32 PVI:1; // Protected-Mode Virtual Interrupts + UINT32 TSD:1; // Time Stamp Disable + UINT32 DE:1; // Debugging Extensions + UINT32 PSE:1; // Page Size Extensions + UINT32 PAE:1; // Physical Address Extension + UINT32 MCE:1; // Machine Check Enable + UINT32 PGE:1; // Page Global Enable + UINT32 PCE:1; // Performance Monitoring Counter + // Enable + UINT32 OSFXSR:1; // Operating System Support for + // FXSAVE and FXRSTOR instructions + UINT32 OSXMMEXCPT:1; // Operating System Support for + // Unmasked SIMD Floating Point + // Exceptions + UINT32 Reserved_0:2; // Reserved + UINT32 VMXE:1; // VMX Enable + UINT32 Reserved_1:18; // Reseved + } Bits; + UINTN UintN; +} IA32_CR4; + +// +// Byte packed structure for an IDTR, GDTR, LDTR descriptor +// +typedef struct { + UINT16 Limit; + UINTN Base; +} IA32_DESCRIPTOR; + +#define IA32_IDT_GATE_TYPE_TASK 0x85 +#define IA32_IDT_GATE_TYPE_INTERRUPT_16 0x86 +#define IA32_IDT_GATE_TYPE_TRAP_16 0x87 +#define IA32_IDT_GATE_TYPE_INTERRUPT_32 0x8E +#define IA32_IDT_GATE_TYPE_TRAP_32 0x8F + +// +// Byte packed structure for an Interrupt Gate Descriptor +// +typedef union { + struct { + UINT32 OffsetLow:16; // Offset bits 15..0 + UINT32 Selector:16; // Selector + UINT32 Reserved_0:8; // Reserved + UINT32 GateType:8; // Gate Type. See #defines above + UINT32 OffsetHigh:16; // Offset bits 31..16 + } Bits; + UINT64 Uint64; +} IA32_IDT_GATE_DESCRIPTOR; + +// +// Byte packed structure for an FP/SSE/SSE2 context +// +typedef struct { + UINT8 Buffer[512]; +} IA32_FX_BUFFER; + +// +// Structures for the 16-bit real mode thunks +// +typedef struct { + UINT32 Reserved1; + UINT32 Reserved2; + UINT32 Reserved3; + UINT32 Reserved4; + UINT8 BL; + UINT8 BH; + UINT16 Reserved5; + UINT8 DL; + UINT8 DH; + UINT16 Reserved6; + UINT8 CL; + UINT8 CH; + UINT16 Reserved7; + UINT8 AL; + UINT8 AH; + UINT16 Reserved8; +} IA32_BYTE_REGS; + +typedef struct { + UINT16 DI; + UINT16 Reserved1; + UINT16 SI; + UINT16 Reserved2; + UINT16 BP; + UINT16 Reserved3; + UINT16 SP; + UINT16 Reserved4; + UINT16 BX; + UINT16 Reserved5; + UINT16 DX; + UINT16 Reserved6; + UINT16 CX; + UINT16 Reserved7; + UINT16 AX; + UINT16 Reserved8; +} IA32_WORD_REGS; + +typedef struct { + UINT32 EDI; + UINT32 ESI; + UINT32 EBP; + UINT32 ESP; + UINT32 EBX; + UINT32 EDX; + UINT32 ECX; + UINT32 EAX; + UINT16 DS; + UINT16 ES; + UINT16 FS; + UINT16 GS; + IA32_EFLAGS32 EFLAGS; + UINT32 Eip; + UINT16 CS; + UINT16 SS; +} IA32_DWORD_REGS; + +typedef union { + IA32_DWORD_REGS E; + IA32_WORD_REGS X; + IA32_BYTE_REGS H; +} IA32_REGISTER_SET; + +// +// Byte packed structure for an 16-bit real mode thunks +// +typedef struct { + IA32_REGISTER_SET RealModeState; + VOID *RealModeBuffer; + UINTN RealModeBufferSize; + VOID *CallStack; + UINTN CallStackSize; + VOID *RealModeCode; + UINTN RealModeCodeSize; +} THUNK_CONTEXT; + +/** + Retrieves CPUID information. + + Executes the CPUID instruction with EAX set to the value specified by Index. + This function always returns Index. + If Eax is not NULL, then the value of EAX after CPUID is returned in Eax. + If Ebx is not NULL, then the value of EBX after CPUID is returned in Ebx. + If Ecx is not NULL, then the value of ECX after CPUID is returned in Ecx. + If Edx is not NULL, then the value of EDX after CPUID is returned in Edx. + This function is only available on IA-32 and X64. + + @param Index The 32-bit value to load into EAX prior to invoking the CPUID + instruction. + @param Eax Pointer to the 32-bit EAX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Ebx Pointer to the 32-bit EBX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Ecx Pointer to the 32-bit ECX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + @param Edx Pointer to the 32-bit EDX value returned by the CPUID + instruction. This is an optional parameter that may be NULL. + + @return Index + +**/ +UINT32 +EFIAPI +AsmCpuid ( + IN UINT32 Index, + OUT UINT32 *Eax, OPTIONAL + OUT UINT32 *Ebx, OPTIONAL + OUT UINT32 *Ecx, OPTIONAL + OUT UINT32 *Edx OPTIONAL + ); + +/** + Returns the lower 32-bits of a Machine Specific Register(MSR). + + Reads and returns the lower 32-bits of the MSR specified by Index. + No parameter checking is performed on Index, and some Index values may cause + CPU exceptions. The caller must either guarantee that Index is valid, or the + caller must set up exception handlers to catch the exceptions. This function + is only available on IA-32 and X64. + + @param Index The 32-bit MSR index to read. + + @return The lower 32 bits of the MSR identified by Index. + +**/ +UINT32 +EFIAPI +AsmReadMsr32 ( + IN UINT32 Index + ); + +/** + Zero-extend a 32-bit value and writes it to a Machine Specific Register(MSR). + + Writes the 32-bit value specified by Value to the MSR specified by Index. The + upper 32-bits of the MSR write are set to zero. The 32-bit value written to + the MSR is returned. No parameter checking is performed on Index or Value, + and some of these may cause CPU exceptions. The caller must either guarantee + that Index and Value are valid, or the caller must establish proper exception + handlers. This function is only available on IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param Value The 32-bit value to write to the MSR. + + @return Value + +**/ +UINT32 +EFIAPI +AsmWriteMsr32 ( + IN UINT32 Index, + IN UINT32 Value + ); + +/** + Reads a 64-bit MSR, performs a bitwise inclusive OR on the lower 32-bits, and + writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise inclusive OR + between the lower 32-bits of the read result and the value specified by + OrData, and writes the result to the 64-bit MSR specified by Index. The lower + 32-bits of the value written to the MSR is returned. No parameter checking is + performed on Index or OrData, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and OrData are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param OrData The value to OR with the read value from the MSR. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrOr32 ( + IN UINT32 Index, + IN UINT32 OrData + ); + +/** + Reads a 64-bit MSR, performs a bitwise AND on the lower 32-bits, and writes + the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + lower 32-bits of the read result and the value specified by AndData, and + writes the result to the 64-bit MSR specified by Index. The lower 32-bits of + the value written to the MSR is returned. No parameter checking is performed + on Index or AndData, and some of these may cause CPU exceptions. The caller + must either guarantee that Index and AndData are valid, or the caller must + establish proper exception handlers. This function is only available on IA-32 + and X64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrAnd32 ( + IN UINT32 Index, + IN UINT32 AndData + ); + +/** + Reads a 64-bit MSR, performs a bitwise AND followed by a bitwise inclusive OR + on the lower 32-bits, and writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + lower 32-bits of the read result and the value specified by AndData + preserving the upper 32-bits, performs a bitwise inclusive OR between the + result of the AND operation and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Address. The lower 32-bits of the value + written to the MSR is returned. No parameter checking is performed on Index, + AndData, or OrData, and some of these may cause CPU exceptions. The caller + must either guarantee that Index, AndData, and OrData are valid, or the + caller must establish proper exception handlers. This function is only + available on IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrAndThenOr32 ( + IN UINT32 Index, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a bit field of an MSR. + + Reads the bit field in the lower 32-bits of a 64-bit MSR. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. The caller must either guarantee that Index is valid, or the caller + must set up exception handlers to catch the exceptions. This function is only + available on IA-32 and X64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read from the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldRead32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to an MSR. + + Writes Value to a bit field in the lower 32-bits of a 64-bit MSR. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination MSR are preserved. The lower 32-bits of the MSR written is + returned. Extra left bits in Value are stripped. The caller must either + guarantee that Index and the data written is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and X64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldWrite32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The lower 32-bits of the value + written to the MSR are returned. Extra left bits in OrData are stripped. The + caller must either guarantee that Index and the data written is valid, or + the caller must set up exception handlers to catch the exceptions. This + function is only available on IA-32 and X64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the MSR. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldOr32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by AndData, and writes the result to the + 64-bit MSR specified by Index. The lower 32-bits of the value written to the + MSR are returned. Extra left bits in AndData are stripped. The caller must + either guarantee that Index and the data written is valid, or the caller must + set up exception handlers to catch the exceptions. This function is only + available on IA-32 and X64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MSR. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldAnd32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND followed by a + bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 64-bit MSR specified by Index. The + lower 32-bits of the value written to the MSR are returned. Extra left bits + in both AndData and OrData are stripped. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 + and X64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldAndThenOr32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Returns a 64-bit Machine Specific Register(MSR). + + Reads and returns the 64-bit MSR specified by Index. No parameter checking is + performed on Index, and some Index values may cause CPU exceptions. The + caller must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and X64. + + @param Index The 32-bit MSR index to read. + + @return The value of the MSR identified by Index. + +**/ +UINT64 +EFIAPI +AsmReadMsr64 ( + IN UINT32 Index + ); + +/** + Writes a 64-bit value to a Machine Specific Register(MSR), and returns the + value. + + Writes the 64-bit value specified by Value to the MSR specified by Index. The + 64-bit value written to the MSR is returned. No parameter checking is + performed on Index or Value, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and Value are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param Value The 64-bit value to write to the MSR. + + @return Value + +**/ +UINT64 +EFIAPI +AsmWriteMsr64 ( + IN UINT32 Index, + IN UINT64 Value + ); + +/** + Reads a 64-bit MSR, performs a bitwise inclusive OR, and writes the result + back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The value written to the MSR is + returned. No parameter checking is performed on Index or OrData, and some of + these may cause CPU exceptions. The caller must either guarantee that Index + and OrData are valid, or the caller must establish proper exception handlers. + This function is only available on IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param OrData The value to OR with the read value from the MSR. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrOr64 ( + IN UINT32 Index, + IN UINT64 OrData + ); + +/** + Reads a 64-bit MSR, performs a bitwise AND, and writes the result back to the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by OrData, and writes the result to the + 64-bit MSR specified by Index. The value written to the MSR is returned. No + parameter checking is performed on Index or OrData, and some of these may + cause CPU exceptions. The caller must either guarantee that Index and OrData + are valid, or the caller must establish proper exception handlers. This + function is only available on IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrAnd64 ( + IN UINT32 Index, + IN UINT64 AndData + ); + +/** + Reads a 64-bit MSR, performs a bitwise AND followed by a bitwise inclusive + OR, and writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between read + result and the value specified by AndData, performs a bitwise inclusive OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit MSR specified by Index. The value written + to the MSR is returned. No parameter checking is performed on Index, AndData, + or OrData, and some of these may cause CPU exceptions. The caller must either + guarantee that Index, AndData, and OrData are valid, or the caller must + establish proper exception handlers. This function is only available on IA-32 + and X64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrAndThenOr64 ( + IN UINT32 Index, + IN UINT64 AndData, + IN UINT64 OrData + ); + +/** + Reads a bit field of an MSR. + + Reads the bit field in the 64-bit MSR. The bit field is specified by the + StartBit and the EndBit. The value of the bit field is returned. The caller + must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and X64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read from the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldRead64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to an MSR. + + Writes Value to a bit field in a 64-bit MSR. The bit field is specified by + the StartBit and the EndBit. All other bits in the destination MSR are + preserved. The MSR written is returned. Extra left bits in Value are + stripped. The caller must either guarantee that Index and the data written is + valid, or the caller must set up exception handlers to catch the exceptions. + This function is only available on IA-32 and X64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldWrite64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ); + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise inclusive OR, and + writes the result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The value written to the MSR is + returned. Extra left bits in OrData are stripped. The caller must either + guarantee that Index and the data written is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and X64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldOr64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ); + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by AndData, and writes the result to the + 64-bit MSR specified by Index. The value written to the MSR is returned. + Extra left bits in AndData are stripped. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 + and X64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldAnd64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ); + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND followed by + a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 64-bit MSR specified by Index. The + value written to the MSR is returned. Extra left bits in both AndData and + OrData are stripped. The caller must either guarantee that Index and the data + written is valid, or the caller must set up exception handlers to catch the + exceptions. This function is only available on IA-32 and X64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the bit field. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldAndThenOr64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ); + +/** + Reads the current value of the EFLAGS register. + + Reads and returns the current value of the EFLAGS register. This function is + only available on IA-32 and X64. This returns a 32-bit value on IA-32 and a + 64-bit value on X64. + + @return EFLAGS on IA-32 or RFLAGS on X64. + +**/ +UINTN +EFIAPI +AsmReadEflags ( + VOID + ); + +/** + Reads the current value of the Control Register 0 (CR0). + + Reads and returns the current value of CR0. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 0 (CR0). + +**/ +UINTN +EFIAPI +AsmReadCr0 ( + VOID + ); + +/** + Reads the current value of the Control Register 2 (CR2). + + Reads and returns the current value of CR2. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 2 (CR2). + +**/ +UINTN +EFIAPI +AsmReadCr2 ( + VOID + ); + +/** + Reads the current value of the Control Register 3 (CR3). + + Reads and returns the current value of CR3. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 3 (CR3). + +**/ +UINTN +EFIAPI +AsmReadCr3 ( + VOID + ); + +/** + Reads the current value of the Control Register 4 (CR4). + + Reads and returns the current value of CR4. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of the Control Register 4 (CR4). + +**/ +UINTN +EFIAPI +AsmReadCr4 ( + VOID + ); + +/** + Writes a value to Control Register 0 (CR0). + + Writes and returns a new value to CR0. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr0 The value to write to CR0. + + @return The value written to CR0. + +**/ +UINTN +EFIAPI +AsmWriteCr0 ( + UINTN Cr0 + ); + +/** + Writes a value to Control Register 2 (CR2). + + Writes and returns a new value to CR2. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr2 The value to write to CR2. + + @return The value written to CR2. + +**/ +UINTN +EFIAPI +AsmWriteCr2 ( + UINTN Cr2 + ); + +/** + Writes a value to Control Register 3 (CR3). + + Writes and returns a new value to CR3. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr3 The value to write to CR3. + + @return The value written to CR3. + +**/ +UINTN +EFIAPI +AsmWriteCr3 ( + UINTN Cr3 + ); + +/** + Writes a value to Control Register 4 (CR4). + + Writes and returns a new value to CR4. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Cr4 The value to write to CR4. + + @return The value written to CR4. + +**/ +UINTN +EFIAPI +AsmWriteCr4 ( + UINTN Cr4 + ); + +/** + Reads the current value of Debug Register 0 (DR0). + + Reads and returns the current value of DR0. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmReadDr0 ( + VOID + ); + +/** + Reads the current value of Debug Register 1 (DR1). + + Reads and returns the current value of DR1. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmReadDr1 ( + VOID + ); + +/** + Reads the current value of Debug Register 2 (DR2). + + Reads and returns the current value of DR2. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmReadDr2 ( + VOID + ); + +/** + Reads the current value of Debug Register 3 (DR3). + + Reads and returns the current value of DR3. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmReadDr3 ( + VOID + ); + +/** + Reads the current value of Debug Register 4 (DR4). + + Reads and returns the current value of DR4. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmReadDr4 ( + VOID + ); + +/** + Reads the current value of Debug Register 5 (DR5). + + Reads and returns the current value of DR5. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmReadDr5 ( + VOID + ); + +/** + Reads the current value of Debug Register 6 (DR6). + + Reads and returns the current value of DR6. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmReadDr6 ( + VOID + ); + +/** + Reads the current value of Debug Register 7 (DR7). + + Reads and returns the current value of DR7. This function is only available + on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on + X64. + + @return The value of Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmReadDr7 ( + VOID + ); + +/** + Writes a value to Debug Register 0 (DR0). + + Writes and returns a new value to DR0. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr0 The value to write to Dr0. + + @return The value written to Debug Register 0 (DR0). + +**/ +UINTN +EFIAPI +AsmWriteDr0 ( + UINTN Dr0 + ); + +/** + Writes a value to Debug Register 1 (DR1). + + Writes and returns a new value to DR1. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr1 The value to write to Dr1. + + @return The value written to Debug Register 1 (DR1). + +**/ +UINTN +EFIAPI +AsmWriteDr1 ( + UINTN Dr1 + ); + +/** + Writes a value to Debug Register 2 (DR2). + + Writes and returns a new value to DR2. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr2 The value to write to Dr2. + + @return The value written to Debug Register 2 (DR2). + +**/ +UINTN +EFIAPI +AsmWriteDr2 ( + UINTN Dr2 + ); + +/** + Writes a value to Debug Register 3 (DR3). + + Writes and returns a new value to DR3. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr3 The value to write to Dr3. + + @return The value written to Debug Register 3 (DR3). + +**/ +UINTN +EFIAPI +AsmWriteDr3 ( + UINTN Dr3 + ); + +/** + Writes a value to Debug Register 4 (DR4). + + Writes and returns a new value to DR4. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr4 The value to write to Dr4. + + @return The value written to Debug Register 4 (DR4). + +**/ +UINTN +EFIAPI +AsmWriteDr4 ( + UINTN Dr4 + ); + +/** + Writes a value to Debug Register 5 (DR5). + + Writes and returns a new value to DR5. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr5 The value to write to Dr5. + + @return The value written to Debug Register 5 (DR5). + +**/ +UINTN +EFIAPI +AsmWriteDr5 ( + UINTN Dr5 + ); + +/** + Writes a value to Debug Register 6 (DR6). + + Writes and returns a new value to DR6. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr6 The value to write to Dr6. + + @return The value written to Debug Register 6 (DR6). + +**/ +UINTN +EFIAPI +AsmWriteDr6 ( + UINTN Dr6 + ); + +/** + Writes a value to Debug Register 7 (DR7). + + Writes and returns a new value to DR7. This function is only available on + IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64. + + @param Dr7 The value to write to Dr7. + + @return The value written to Debug Register 7 (DR7). + +**/ +UINTN +EFIAPI +AsmWriteDr7 ( + UINTN Dr7 + ); + +/** + Reads the current value of Code Segment Register (CS). + + Reads and returns the current value of CS. This function is only available on + IA-32 and X64. + + @return The current value of CS. + +**/ +UINT16 +EFIAPI +AsmReadCs ( + VOID + ); + +/** + Reads the current value of Data Segment Register (DS). + + Reads and returns the current value of DS. This function is only available on + IA-32 and X64. + + @return The current value of DS. + +**/ +UINT16 +EFIAPI +AsmReadDs ( + VOID + ); + +/** + Reads the current value of Extra Segment Register (ES). + + Reads and returns the current value of ES. This function is only available on + IA-32 and X64. + + @return The current value of ES. + +**/ +UINT16 +EFIAPI +AsmReadEs ( + VOID + ); + +/** + Reads the current value of FS Data Segment Register (FS). + + Reads and returns the current value of FS. This function is only available on + IA-32 and X64. + + @return The current value of FS. + +**/ +UINT16 +EFIAPI +AsmReadFs ( + VOID + ); + +/** + Reads the current value of GS Data Segment Register (GS). + + Reads and returns the current value of GS. This function is only available on + IA-32 and X64. + + @return The current value of GS. + +**/ +UINT16 +EFIAPI +AsmReadGs ( + VOID + ); + +/** + Reads the current value of Stack Segment Register (SS). + + Reads and returns the current value of SS. This function is only available on + IA-32 and X64. + + @return The current value of SS. + +**/ +UINT16 +EFIAPI +AsmReadSs ( + VOID + ); + +/** + Reads the current value of Task Register (TR). + + Reads and returns the current value of TR. This function is only available on + IA-32 and X64. + + @return The current value of TR. + +**/ +UINT16 +EFIAPI +AsmReadTr ( + VOID + ); + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and X64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr Pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ); + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and X64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr Pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ); + +/** + Reads the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and X64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr Pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ); + +/** + Writes the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and X64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr Pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ); + +/** + Reads the current Local Descriptor Table Register(LDTR) selector. + + Reads and returns the current 16-bit LDTR descriptor value. This function is + only available on IA-32 and X64. + + @return The current selector of LDT. + +**/ +UINT16 +EFIAPI +AsmReadLdtr ( + VOID + ); + +/** + Writes the current Local Descriptor Table Register (GDTR) selector. + + Writes and the current LDTR descriptor specified by Ldtr. This function is + only available on IA-32 and X64. + + @param Ldtr 16-bit LDTR selector value. + +**/ +VOID +EFIAPI +AsmWriteLdtr ( + IN UINT16 Ldtr + ); + +/** + Save the current floating point/SSE/SSE2 context to a buffer. + + Saves the current floating point/SSE/SSE2 state to the buffer specified by + Buffer. Buffer must be aligned on a 16-byte boundary. This function is only + available on IA-32 and X64. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-byte boundary, then ASSERT(). + + @param Buffer Pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxSave ( + OUT IA32_FX_BUFFER *Buffer + ); + +/** + Restores the current floating point/SSE/SSE2 context from a buffer. + + Restores the current floating point/SSE/SSE2 state from the buffer specified + by Buffer. Buffer must be aligned on a 16-byte boundary. This function is + only available on IA-32 and X64. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-byte boundary, then ASSERT(). + If Buffer was not saved with AsmFxSave(), then ASSERT(). + + @param Buffer Pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ); + +/** + Reads the current value of 64-bit MMX Register #0 (MM0). + + Reads and returns the current value of MM0. This function is only available + on IA-32 and X64. + + @return The current value of MM0. + +**/ +UINT64 +EFIAPI +AsmReadMm0 ( + VOID + ); + +/** + Reads the current value of 64-bit MMX Register #1 (MM1). + + Reads and returns the current value of MM1. This function is only available + on IA-32 and X64. + + @return The current value of MM1. + +**/ +UINT64 +EFIAPI +AsmReadMm1 ( + VOID + ); + +/** + Reads the current value of 64-bit MMX Register #2 (MM2). + + Reads and returns the current value of MM2. This function is only available + on IA-32 and X64. + + @return The current value of MM2. + +**/ +UINT64 +EFIAPI +AsmReadMm2 ( + VOID + ); + +/** + Reads the current value of 64-bit MMX Register #3 (MM3). + + Reads and returns the current value of MM3. This function is only available + on IA-32 and X64. + + @return The current value of MM3. + +**/ +UINT64 +EFIAPI +AsmReadMm3 ( + VOID + ); + +/** + Reads the current value of 64-bit MMX Register #4 (MM4). + + Reads and returns the current value of MM4. This function is only available + on IA-32 and X64. + + @return The current value of MM4. + +**/ +UINT64 +EFIAPI +AsmReadMm4 ( + VOID + ); + +/** + Reads the current value of 64-bit MMX Register #5 (MM5). + + Reads and returns the current value of MM5. This function is only available + on IA-32 and X64. + + @return The current value of MM5. + +**/ +UINT64 +EFIAPI +AsmReadMm5 ( + VOID + ); + +/** + Reads the current value of 64-bit MMX Register #6 (MM6). + + Reads and returns the current value of MM6. This function is only available + on IA-32 and X64. + + @return The current value of MM6. + +**/ +UINT64 +EFIAPI +AsmReadMm6 ( + VOID + ); + +/** + Reads the current value of 64-bit MMX Register #7 (MM7). + + Reads and returns the current value of MM7. This function is only available + on IA-32 and X64. + + @return The current value of MM7. + +**/ +UINT64 +EFIAPI +AsmReadMm7 ( + VOID + ); + +/** + Writes the current value of 64-bit MMX Register #0 (MM0). + + Writes the current value of MM0. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM0. + +**/ +VOID +EFIAPI +AsmWriteMm0 ( + IN UINT64 Value + ); + +/** + Writes the current value of 64-bit MMX Register #1 (MM1). + + Writes the current value of MM1. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM1. + +**/ +VOID +EFIAPI +AsmWriteMm1 ( + IN UINT64 Value + ); + +/** + Writes the current value of 64-bit MMX Register #2 (MM2). + + Writes the current value of MM2. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM2. + +**/ +VOID +EFIAPI +AsmWriteMm2 ( + IN UINT64 Value + ); + +/** + Writes the current value of 64-bit MMX Register #3 (MM3). + + Writes the current value of MM3. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM3. + +**/ +VOID +EFIAPI +AsmWriteMm3 ( + IN UINT64 Value + ); + +/** + Writes the current value of 64-bit MMX Register #4 (MM4). + + Writes the current value of MM4. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM4. + +**/ +VOID +EFIAPI +AsmWriteMm4 ( + IN UINT64 Value + ); + +/** + Writes the current value of 64-bit MMX Register #5 (MM5). + + Writes the current value of MM5. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM5. + +**/ +VOID +EFIAPI +AsmWriteMm5 ( + IN UINT64 Value + ); + +/** + Writes the current value of 64-bit MMX Register #6 (MM6). + + Writes the current value of MM6. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM6. + +**/ +VOID +EFIAPI +AsmWriteMm6 ( + IN UINT64 Value + ); + +/** + Writes the current value of 64-bit MMX Register #7 (MM7). + + Writes the current value of MM7. This function is only available on IA32 and + X64. + + @param Value The 64-bit value to write to MM7. + +**/ +VOID +EFIAPI +AsmWriteMm7 ( + IN UINT64 Value + ); + +/** + Reads the current value of Time Stamp Counter (TSC). + + Reads and returns the current value of TSC. This function is only available + on IA-32 and X64. + + @return The current value of TSC + +**/ +UINT64 +EFIAPI +AsmReadTsc ( + VOID + ); + +/** + Reads the current value of a Performance Counter (PMC). + + Reads and returns the current value of performance counter specified by + Index. This function is only available on IA-32 and X64. + + @param Index The 32-bit Performance Counter index to read. + + @return The value of the PMC specified by Index. + +**/ +UINT64 +EFIAPI +AsmReadPmc ( + IN UINT32 Index + ); + +/** + Sets up a monitor buffer that is used by AsmMwait(). + + Executes a MONITOR instruction with the register state specified by Eax, Ecx + and Edx. Returns Eax. This function is only available on IA-32 and X64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + @param Edx The value to load into EDX or RDX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +AsmMonitor ( + IN UINTN Eax, + IN UINTN Ecx, + IN UINTN Edx + ); + +/** + Executes an MWAIT instruction. + + Executes an MWAIT instruction with the register state specified by Eax and + Ecx. Returns Eax. This function is only available on IA-32 and X64. + + @param Eax The value to load into EAX or RAX before executing the MONITOR + instruction. + @param Ecx The value to load into ECX or RCX before executing the MONITOR + instruction. + + @return Eax + +**/ +UINTN +EFIAPI +AsmMwait ( + IN UINTN Eax, + IN UINTN Ecx + ); + +/** + Executes a WBINVD instruction. + + Executes a WBINVD instruction. This function is only available on IA-32 and + X64. + +**/ +VOID +EFIAPI +AsmWbinvd ( + VOID + ); + +/** + Executes a INVD instruction. + + Executes a INVD instruction. This function is only available on IA-32 and + X64. + +**/ +VOID +EFIAPI +AsmInvd ( + VOID + ); + +/** + Flushes a cache line from all the instruction and data caches within the + coherency domain of the CPU. + + Flushed the cache line specified by LinearAddress, and returns LinearAddress. + This function is only available on IA-32 and X64. + + @param LinearAddress The address of the cache line to flush. If the CPU is + in a physical addressing mode, then LinearAddress is a + physical address. If the CPU is in a virtual + addressing mode, then LinearAddress is a virtual + address. + + @return LinearAddress +**/ +VOID * +EFIAPI +AsmFlushCacheLine ( + IN VOID *LinearAddress + ); + +/** + Enables the 32-bit paging mode on the CPU. + + Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode. This function is + only available on IA-32. After the 32-bit paging mode is enabled, control is + transferred to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit protected mode with flat descriptors. This + means all descriptors must have a base of 0 and a limit of 4GB. + 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat + descriptors. + 4) CR3 must point to valid page tables that will be used once the transition + is complete, and those page tables must guarantee that the pages for this + function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is enabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is enabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is enabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + +/** + Disables the 32-bit paging mode on the CPU. + + Disables the 32-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 32-paged protected + mode. This function is only available on IA-32. After the 32-bit paging mode + is disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be NULL. The function EntryPoint must never return. + + If the current execution mode is not 32-bit paged mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit paged mode. + 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode. + 4) CR3 must point to valid page tables that guarantee that the pages for + this function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is disabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is disabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is + disabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + +/** + Enables the 64-bit paging mode on the CPU. + + Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode with flat + descriptors. This function is only available on IA-32. After the 64-bit + paging mode is enabled, control is transferred to the function specified by + EntryPoint using the new stack specified by NewStack and passing in the + parameters specified by Context1 and Context2. Context1 and Context2 are + optional and may be 0. The function EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode with flat + descriptors, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for long mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is enabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is enabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is enabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging64 ( + IN UINT16 CodeSelector, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ); + +/** + Disables the 64-bit paging mode on the CPU. + + Disables the 64-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 64-paging mode. + This function is only available on X64. After the 64-bit paging mode is + disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be 0. The function EntryPoint must never return. + + If the current execution mode is not 64-bit paged mode, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for 32-bit protected mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is disabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is disabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is disabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging64 ( + IN UINT16 CodeSelector, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ); + +// +// 16-bit thunking services +// + +/** + Prepares all structures a code required to use AsmThunk16(). + + Prepares all structures and code required to use AsmThunk16(). + + If ThunkContext is NULL, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareThunk16 ( + OUT THUNK_CONTEXT *ThunkContext + ); + +/** + Transfers control to a 16-bit real mode entry point and returns the results. + + Transfers control to a 16-bit real mode entry point and returns the results. + AsmPrepareThunk16() must be called with ThunkContext before this function is + used. + + If ThunkContext is NULL, then ASSERT(). + If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ); + +/** + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. + + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. If the + caller only need to perform a single 16-bit real mode thunk, then this + service should be used. If the caller intends to make more than one 16-bit + real mode thunk, then it is more efficient if AsmPrepareThunk16() is called + once and AsmThunk16() can be called for each 16-bit real mode thunk. + + If ThunkContext is NULL, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareAndThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ); + +#endif diff --git a/MdePkg/Include/Library/BaseMemoryLib.h b/MdePkg/Include/Library/BaseMemoryLib.h new file mode 100644 index 0000000000..5994530b55 --- /dev/null +++ b/MdePkg/Include/Library/BaseMemoryLib.h @@ -0,0 +1,395 @@ +/** @file + Memory-only library functions with no library constructor/destructor + + Copyright (c) 2006, 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. + + Module Name: BaseMemoryLib.h + +**/ + +#ifndef __BASE_MEMORY_LIB__ +#define __BASE_MEMORY_LIB__ + +/** + Copy Length bytes from Source to Destination. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and + returns DestinationBuffer. The implementation must be reentrant, and it must + handle the case where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +ZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + This function compares Length bytes of SourceBuffer to Length bytes of + DestinationBuffer. If all Length bytes of the two buffers are identical, then + 0 is returned. Otherwise, the value returned is the first mismatched byte in + SourceBuffer subtracted from the first mismatched byte in DestinationBuffer. + + If DestinationBuffer is NULL and Length > 0, then ASSERT(). + If SourceBuffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare + + @retval 0 if DestinationBuffer == SourceBuffer + @retval Non-zero if DestinationBuffer != SourceBuffer + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address for an 8-bit value that matches + Value. If a match is found, then a pointer to the matching byte in the target + buffer is returned. If no match is found, then NULL is returned. If Length is + 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 16-bit increments for a 16-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 32-bit increments for a 32-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 64-bit increments for a 64-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + This function copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid + to DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid Pointer to the destination GUID. + @param SourceGuid Pointer to the source GUID. + + @return DestinationGuid + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ); + +/** + Compares two GUIDs + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE + is returned. If there are any bit differences in the two GUIDs, then FALSE is + returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 guid to compare + @param Guid2 guid to compare + + @retval TRUE if Guid1 == Guid2 + @retval FALSE if Guid1 != Guid2 + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ); + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the + 128-bit GUID value that matches Guid. If a match is found, then a pointer to + the matching GUID in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Guid Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Guid was not found. +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ); + +#endif diff --git a/MdePkg/Include/Library/CacheMaintenanceLib.h b/MdePkg/Include/Library/CacheMaintenanceLib.h new file mode 100644 index 0000000000..74d2ab7e8a --- /dev/null +++ b/MdePkg/Include/Library/CacheMaintenanceLib.h @@ -0,0 +1,72 @@ +/** @file + Cache Maintenance Functions + + Copyright (c) 2006, 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. + + Module Name: CacheMaintenanceLib.h + +**/ + +#ifndef __CACHE_MAINTENANCE_LIB__ +#define __CACHE_MAINTENANCE_LIB__ + +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ); + +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ); + +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ); + +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ); + +VOID +EFIAPI +WriteBackDataCache ( + VOID + ); + +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ); + +VOID +EFIAPI +InvalidateDataCache ( + VOID + ); + +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ); + +#endif diff --git a/MdePkg/Include/Library/CpuLib.h b/MdePkg/Include/Library/CpuLib.h new file mode 100644 index 0000000000..d79c002cc0 --- /dev/null +++ b/MdePkg/Include/Library/CpuLib.h @@ -0,0 +1,20 @@ +/** @file + Library that provides processor specific library services + + Copyright (c) 2006, 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. + + Module Name: CpuLib.h + +**/ + +#ifndef __CPU_LIB_H__ +#define __CPU_LIB_H__ + +#endif \ No newline at end of file diff --git a/MdePkg/Include/Library/DebugLib.h b/MdePkg/Include/Library/DebugLib.h new file mode 100644 index 0000000000..625bcfbf24 --- /dev/null +++ b/MdePkg/Include/Library/DebugLib.h @@ -0,0 +1,439 @@ +/** @file + Public include file for the Debug Library + + Copyright (c) 2006, 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 __DEBUG_LIB_H__ +#define __DEBUG_LIB_H__ + +// +// Declare bits for PcdDebugPropertyMask +// +#define DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED 0x01 +#define DEBUG_PROPERTY_DEBUG_PRINT_ENABLED 0x02 +#define DEBUG_PROPERTY_DEBUG_CODE_ENABLED 0x04 +#define DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED 0x08 +#define DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED 0x10 +#define DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED 0x20 + +// +// Declare bits for PcdDebugPrintErrorLevel and the ErrorLevel parameter of DebugPrint() +// +#define EFI_D_INIT 0x00000001 // Initialization style messages +#define EFI_D_WARN 0x00000002 // Warnings +#define EFI_D_LOAD 0x00000004 // Load events +#define EFI_D_FS 0x00000008 // EFI File system +#define EFI_D_POOL 0x00000010 // Alloc & Free's +#define EFI_D_PAGE 0x00000020 // Alloc & Free's +#define EFI_D_INFO 0x00000040 // Verbose +#define EFI_D_VARIABLE 0x00000100 // Variable +#define EFI_D_BM 0x00000400 // Boot Manager (BDS) +#define EFI_D_BLKIO 0x00001000 // BlkIo Driver +#define EFI_D_NET 0x00004000 // SNI Driver +#define EFI_D_UNDI 0x00010000 // UNDI Driver +#define EFI_D_LOADFILE 0x00020000 // UNDI Driver +#define EFI_D_EVENT 0x00080000 // Event messages +#define EFI_D_ERROR 0x80000000 // Error + +/** + + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print + the message specified by Format and the associated variable argument list to + the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ); + + +/** + + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form “ASSERT (): \n” + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recusrsion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a string of “(NULL) Filename” is printed. + + If Description is NULL, then a string of “(NULL) Description” is printed. + + @param FileName Pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description Pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ); + + +/** + + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + + If Length is greater than (MAX_ADDRESS – Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ); + + +/** + + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ); + + +/** + + Returns TRUE if DEBUG()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ); + + +/** + + Returns TRUE if DEBUG_CODE()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ); + + +/** + + Returns TRUE if DEBUG_CLEAR_MEMORY()macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ); + + +/** + + Internal worker macro that calls DebugAssert(). + + This macro calls DebugAssert() passing in the filename, line number, and + expression that evailated to FALSE. + + @param Expression Boolean expression that evailated to FALSE + +**/ +#define _ASSERT(Expression) DebugAssert (__FILE__, __LINE__, #Expression) + + +/** + + Internal worker macro that calls DebugPrint(). + + This macro calls DebugPrint() passing in the debug error level, a format + string, and a variable argument list. + + @param Expression Expression containing an error level, a format string, + and a variable argument list based on the format string. + +**/ +#define _DEBUG(Expression) DebugPrint Expression + + +/** + + Macro that calls DebugAssert() if a expression evaluates to FALSE. + + If the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set, + then this macro evaluates the Boolean expression specified by Expression. If + Expression evaluates to FALSE, then DebugAssert() is called passing in the + source filename, source line number, and Expression. + + @param Expression Boolean expression + +**/ +#define ASSERT(Expression) \ + do { \ + if (DebugAssertEnabled ()) { \ + if (!(Expression)) { \ + _ASSERT (Expression); \ + } \ + } \ + } while (FALSE) + + +/** + + Macro that calls DebugPrint(). + + If the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set, + then this macro passes Expression to DebugPrint(). + + @param Expression Expression containing an error level, a format string, + and a variable argument list based on the format string. + + +**/ +#define DEBUG(Expression) \ + do { \ + if (DebugPrintEnabled ()) { \ + _DEBUG (Expression); \ + } \ + } while (FALSE) + + +/** + + Macro that calls DebugAssert() if an EFI_STATUS evaluates to an error code. + + If the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set, + then this macro evaluates the EFI_STATUS value specified by StatusParameter. + If StatusParameter is an error code, then DebugAssert() is called passing in + the source filename, source line number, and StatusParameter. + + @param StatusParameter EFI_STATUS value to evaluate. + +**/ +#define ASSERT_EFI_ERROR(StatusParameter) \ + do { \ + if (DebugAssertEnabled ()) { \ + if (EFI_ERROR (StatusParameter)) { \ + DEBUG ((EFI_D_ERROR, "\nASSERT_EFI_ERROR (Status = %r)\n", StatusParameter)); \ + _ASSERT (!EFI_ERROR (StatusParameter)); \ + } \ + } \ + } while (FALSE) + + +/** + + Macro that calls DebugAssert() if a protocol is already installed in the + handle database. + + If the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear, + then return. + + If Handle is NULL, then a check is made to see if the protocol specified by Guid + is present on any handle in the handle database. If Handle is not NULL, then + a check is made to see if the protocol specified by Guid is present on the + handle specified by Handle. If the check finds the protocol, then DebugAssert() + is called passing in the source filename, source line number, and Guid. + + If Guid is NULL, then ASSERT(). + + @param Handle The handle to check for the protocol. This is an optional + parameter that may be NULL. If it is NULL, then the entire + handle database is searched. + + @param Guid Pointer to a protocol GUID. + +**/ +#define ASSERT_PROTOCOL_ALREADY_INSTALLED(Handle, Guid) \ + do { \ + if (DebugAssertEnabled ()) { \ + VOID *Instance; \ + ASSERT (Guid != NULL); \ + if (Handle == NULL) { \ + if (!EFI_ERROR (gBS->LocateProtocol (Guid, NULL, &Instance))) { \ + _ASSERT (Guid already installed in database); \ + } \ + } else { \ + if (!EFI_ERROR (gBS->LocateProtocol (Handle, Guid, &Instance))) { \ + _ASSERT (Guid already installed on Handle); \ + } \ + } \ + } \ + } while (FALSE) + + +/** + Macro that marks the beginning of debug source code. + + If the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set, + then this macro marks the beginning of source code that is included in a module. + Otherwise, the source lines between DEBUG_CODE_BEGIN() and DEBUG_CODE_END() + are not included in a module. + +**/ +#define DEBUG_CODE_BEGIN() do { if (DebugCodeEnabled ()) { UINT8 __DebugCodeLocal + + +/** + + Macro that marks the end of debug source code. + + If the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set, + then this macro marks the end of source code that is included in a module. + Otherwise, the source lines between DEBUG_CODE_BEGIN() and DEBUG_CODE_END() + are not included in a module. + +**/ +#define DEBUG_CODE_END() __DebugCodeLocal = 0; } } while (FALSE) + + +/** + + Macro that declares a section of debug source code. + + If the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set, + then the source code specified by Expression is included in a module. + Otherwise, the source specified by Expression is not included in a module. + +**/ +#define DEBUG_CODE(Expression) \ + DEBUG_CODE_BEGIN (); \ + Expression \ + DEBUG_CODE_END () + + +/** + + Macro that calls DebugClearMemory() to clear a buffer to a default value. + + If the DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set, + then this macro calls DebugClearMemory() passing in Address and Length. + + @param Address Pointer to a buffer. + @param Length The number of bytes in the buffer to set. + +**/ +#define DEBUG_CLEAR_MEMORY(Address, Length) \ + do { \ + if (DebugClearMemoryEnabled ()) { \ + DebugClearMemory (Address, Length); \ + } \ + } while (FALSE) + + +/** + + Macro that calls DebugAssert() if the containing record does not have a + matching signature. If the signatures matches, then a pointer to the data + structure that contains a specified field of that data structure is returned. + This is a light weight method hide information by placing a public data + structure inside a larger private data structure and using a pointer to the + public data structure to retrieve a pointer to the private data structure. + + If the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear, + then this macro computes the offset, in bytes, of field specified by Field + from the beginning of the data structure specified by TYPE. This offset is + subtracted from Record, and is used to return a pointer to a data structure + of the type specified by TYPE. + + If the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set, + then this macro computes the offset, in bytes, of field specified by Field from + the beginning of the data structure specified by TYPE. This offset is + subtracted from Record, and is used to compute a pointer to a data structure of + the type specified by TYPE. The Signature field of the data structure specified + by TYPE is compared to TestSignature. If the signatures match, then a pointer + to the pointer to a data structure of the type specified by TYPE is returned. + If the signatures do not match, then DebugAssert() is called with a description + of “CR has a bad signature” and Record is returned. + + If the data type specified by TYPE does not contain the field specified by Field, + then the module will not compile. + + If TYPE does not contain a field called Signature, then the module will not + compile. + + @param Record Pointer to the field specified by Field within a data + structure of type TYPE. + + @param TYPE The name of the data structure type to return This + data structure must contain the field specified by Field. + + @param Field The name of the field in the data structure specified + by TYPE to which Record points. + + @param TestSignature The 32-bit signature value to match. + +**/ +#define CR(Record, TYPE, Field, TestSignature) \ + (DebugAssertEnabled () && (_CR (Record, TYPE, Field)->Signature != TestSignature)) ? \ + (TYPE *) (_ASSERT (CR has Bad Signature), Record) : \ + _CR (Record, TYPE, Field) + +#endif diff --git a/MdePkg/Include/Library/DevicePathLib.h b/MdePkg/Include/Library/DevicePathLib.h new file mode 100644 index 0000000000..bedbd1c0d4 --- /dev/null +++ b/MdePkg/Include/Library/DevicePathLib.h @@ -0,0 +1,197 @@ +/** @file + Entry point to a DXE Boot Services Driver + + Copyright (c) 2006, 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. + + Module Name: DevicePathLib.h + +**/ + +#ifndef __DEVICE_PATH_LIB_H__ +#define __DEVICE_PATH_LIB_H__ + +/** + This function returns the size, in bytes, + of the device path data structure specified by DevicePath. + If DevicePath is NULL, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @return The size of a device path in bytes. + +**/ +UINTN +EFIAPI +GetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +; + +/** + This function allocates space for a new copy of the device path + specified by DevicePath. + + @param DevicePath A pointer to a device path data structure. + + @return The duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +; + +/** + This function appends the device path SecondDevicePath + to every device path instance in FirstDevicePath. + + @param FirstDevicePath A pointer to a device path data structure. + + @param SecondDevicePath A pointer to a device path data structure. + + @return + A pointer to the new device path is returned. + NULL is returned if space for the new device path could not be allocated from pool. + It is up to the caller to free the memory used by FirstDevicePath and SecondDevicePath + if they are no longer needed. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath + ) +; + +/** + This function appends the device path node SecondDevicePath + to every device path instance in FirstDevicePath. + + @param FirstDevicePath A pointer to a device path data structure. + + @param SecondDevicePath A pointer to a single device path node. + + @return + A pointer to the new device path. + If there is not enough temporary pool memory available to complete this function, + then NULL is returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath + ) +; + +/** + This function appends the device path instance Instance to the device path Source. + If Source is NULL, then a new device path with one instance is created. + + @param Source A pointer to a device path data structure. + @param Instance A pointer to a device path instance. + + @return + A pointer to the new device path. + If there is not enough temporary pool memory available to complete this function, + then NULL is returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Source, + IN CONST EFI_DEVICE_PATH_PROTOCOL *Instance + ) +; + +/** + Function retrieves the next device path instance from a device path data structure. + + @param DevicePath A pointer to a device path data structure. + + @param Size A pointer to the size of a device path instance in bytes. + + @return + This function returns a pointer to the current device path instance. + In addition, it returns the size in bytes of the current device path instance in Size, + and a pointer to the next device path instance in DevicePath. + If there are no more device path instances in DevicePath, then DevicePath will be set to NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +GetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ) +; + +/** + Return TRUE is this is a multi instance device path. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE If DevicePath is multi-instance. + @retval FALSE If DevicePath is not multi-instance or DevicePath is NULL. + +**/ +BOOLEAN +EFIAPI +IsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +; + +/** + This function retrieves the device path protocol from a handle. + + @param Handle The handle from which to retrieve the device path protocol. + + @return + This function returns the device path protocol from the handle specified by Handle. + If Handle is NULL or Handle does not contain a device path protocol, then NULL is returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DevicePathFromHandle ( + IN EFI_HANDLE Handle + ) +; + +/** + This function allocates a device path for a file and appends it to an existing device path. + + @param Device A pointer to a device handle. This parameter is optional and may be NULL. + @param FileName A pointer to a Null-terminated Unicode string. + + @return + If Device is a valid device handle that contains a device path protocol, + then a device path for the file specified by FileName is allocated + and appended to the device path associated with the handle Device. The allocated device path is returned. + If Device is NULL or Device is a handle that does not support the device path protocol, + then a device path containing a single device path node for the file specified by FileName + is allocated and returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +FileDevicePath ( + IN EFI_HANDLE Device, OPTIONAL + IN CONST CHAR16 *FileName + ) +; + +#endif diff --git a/MdePkg/Include/Library/DxeCoreEntryPoint.h b/MdePkg/Include/Library/DxeCoreEntryPoint.h new file mode 100644 index 0000000000..1de2798b9f --- /dev/null +++ b/MdePkg/Include/Library/DxeCoreEntryPoint.h @@ -0,0 +1,77 @@ +/** @file + Entry point to the DXE Core + + Copyright (c) 2006, 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 __MODULE_ENTRY_POINT_H__ +#define __MODULE_ENTRY_POINT_H__ + +// +// Declare the cache of copy of HobList. +// +extern VOID *gHobList; + + +/** + Enrty point to DXE core. + + @param HobStart Pointer of HobList. + +**/ +VOID +EFIAPI +_ModuleEntryPoint ( + IN VOID *HobStart + ); + + +/** + Wrapper of enrty point to DXE CORE. + + @param HobStart Pointer of HobList. + +**/ +VOID +EFIAPI +EfiMain ( + IN VOID *HobStart + ); + + +/** + Call constructs for all libraries. Automatics Generated by tool. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Call the list of driver entry points. Automatics Generated by tool. + + @param HobStart Pointer to HobList. + +**/ +VOID +EFIAPI +ProcessModuleEntryPointList ( + IN VOID *HobStart + ); + +#endif diff --git a/MdePkg/Include/Library/DxeRuntimeDriverLib.h b/MdePkg/Include/Library/DxeRuntimeDriverLib.h new file mode 100644 index 0000000000..7f6f0eb50d --- /dev/null +++ b/MdePkg/Include/Library/DxeRuntimeDriverLib.h @@ -0,0 +1,332 @@ +/** @file + Library to abstract runtime services + + Copyright (c) 2006, 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. + + Module Name: DxeRuntimeDriverLib.h + +**/ + +#ifndef __DXE_RUNTIME_DRIVER_LIB__ +#define __DXE_RUNTIME_DRIVER_LIB__ + + +extern const EFI_EVENT_NOTIFY _gDriverExitBootServicesEvent[]; + +extern const EFI_EVENT_NOTIFY _gDriverSetVirtualAddressMapEvent[]; + +/** + Check to see if the execute context is in Runtime phase or not. + + @param None. + + @retval TRUE The driver is in SMM. + @retval FALSE The driver is not in SMM. + +**/ +BOOLEAN +EFIAPI +EfiAtRuntime ( + VOID + ); + +/** + Check to see if the SetVirtualAddressMsp() is invoked or not. + + @retval TRUE SetVirtualAddressMsp() has been called. + @retval FALSE SetVirtualAddressMsp() has not been called. + +**/ +BOOLEAN +EFIAPI +EfiGoneVirtual ( + VOID + ); + +/** + Return current time and date information, and time-keeping + capabilities of hardware platform. + + @param Time A pointer to storage to receive a snapshot of the current time. + @param Capabilities An optional pointer to a buffer to receive the real time clock device¡¯s + capabilities. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +EFI_STATUS +EFIAPI +EfiGetTime ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities + ); + +/** + Set current time and date information. + + @param Time A pointer to cache of time setting. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to execute the function. + +**/ +EFI_STATUS +EFIAPI +EfiSetTime ( + IN EFI_TIME *Time + ); + +/** + Return current wakeup alarm clock setting. + + @param Enabled Indicate if the alarm clock is enabled or disabled. + @param Pending Indicate if the alarm signal is pending and requires acknowledgement. + @param Time Current alarm clock setting. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +EFI_STATUS +EFIAPI +EfiGetWakeupTime ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ); + +/** + Set current wakeup alarm clock. + + @param Enable Enable or disable current alarm clock.. + @param Time Point to alarm clock setting. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +EFI_STATUS +EFIAPI +EfiSetWakeupTime ( + IN BOOLEAN Enable, + IN EFI_TIME *Time + ); + +/** + Return value of variable. + + @param VariableName the name of the vendor's variable, it's a + Null-Terminated Unicode String + @param VendorGuid Unify identifier for vendor. + @param Attributes Point to memory location to return the attributes of variable. If the point + is NULL, the parameter would be ignored. + @param DataSize As input, point to the maxinum size of return Data-Buffer. + As output, point to the actual size of the returned Data-Buffer. + @param Data Point to return Data-Buffer. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +EFI_STATUS +EFIAPI +EfiGetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, + IN OUT UINTN *DataSize, + OUT VOID *Data + ) +; + +/** + Enumerates variable's name. + + @param VariableNameSize As input, point to maxinum size of variable name. + As output, point to actual size of varaible name. + @param VariableName As input, supplies the last VariableName that was returned by + GetNextVariableName(). + As output, returns the name of variable. The name + string is Null-Terminated Unicode string. + @param VendorGuid As input, supplies the last VendorGuid that was returned by + GetNextVriableName(). + As output, returns the VendorGuid of the current variable. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +EFI_STATUS +EFIAPI +EfiGetNextVariableName ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ); + +/** + Sets value of variable. + + @param VariableName the name of the vendor's variable, it's a + Null-Terminated Unicode String + @param VendorGuid Unify identifier for vendor. + @param Attributes Point to memory location to return the attributes of variable. If the point + is NULL, the parameter would be ignored. + @param DataSize The size in bytes of Data-Buffer. + @param Data Point to the content of the variable. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +EFI_STATUS +EFIAPI +EfiSetVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ); + +/** + Returns the next high 32 bits of platform's monotonic counter. + + @param HighCount Pointer to returned value. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +EFI_STATUS +EFIAPI +EfiGetNextHighMonotonicCount ( + OUT UINT32 *HighCount + ); + +/** + Resets the entire platform. + + @param ResetType The type of reset to perform. + @param ResetStatus The status code for reset. + @param DataSize The size in bytes of reset data. + @param ResetData Pointer to data buffer that includes + Null-Terminated Unicode string. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +VOID +EfiResetSystem ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData + ); + +/** + Determines the new virtual address that is to be used on subsequent memory accesses. + + @param DebugDisposition Supplies type information for the pointer being converted. + @param Address The pointer to a pointer that is to be fixed to be the + value needed for the new virtual address mapping being + applied. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +EFI_STATUS +EFIAPI +EfiConvertPointer ( + IN UINTN DebugDisposition, + IN OUT VOID *Address + ); + + +/** + Change the runtime addressing mode of EFI firmware from physical to virtual. + + @param MemoryMapSize The size in bytes of VirtualMap. + @param DescriptorSize The size in bytes of an entry in the VirtualMap. + @param DescriptorVersion The version of the structure entries in VirtualMap. + @param VirtualMap An array of memory descriptors which contain new virtual + address mapping information for all runtime ranges. Type + EFI_MEMORY_DESCRIPTOR is defined in the + GetMemoryMap() function description. + + @retval EFI_SUCCESS The virtual address map has been applied. + @retval EFI_UNSUPPORTED EFI firmware is not at runtime, or the EFI firmware is already in + virtual address mapped mode. + @retval EFI_INVALID_PARAMETER DescriptorSize or DescriptorVersion is + invalid. + @retval EFI_NO_MAPPING A virtual address was not supplied for a range in the memory + map that requires a mapping. + @retval EFI_NOT_FOUND A virtual address was supplied for an address that is not found + in the memory map. +**/ +EFI_STATUS +EFIAPI +EfiSetVirtualAddressMap ( + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize, + IN UINT32 DescriptorVersion, + IN CONST EFI_MEMORY_DESCRIPTOR *VirtualMap + ); + + +/** + Conver the standard Lib double linked list to a virtual mapping. + + @param DebugDisposition Supplies type information for the pointer being converted. + @param ListHead Head of linked list to convert. + + @retval EFI_SUCCESS Success to execute the function. + @retval !EFI_SUCCESS Failed to e3xecute the function. + +**/ +EFI_STATUS +EFIAPI +EfiConvertList ( + IN UINTN DebugDisposition, + IN OUT LIST_ENTRY *ListHead + ); + + +EFI_STATUS +EFIAPI +EfiUpdateCapsule ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList + ); + + +EFI_STATUS +EFIAPI +EfiQueryCapsuleCapabilities ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaximumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ); + +EFI_STATUS +EFIAPI +EfiQueryVariableInfo ( + IN UINT32 Attrubutes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ); + +#endif diff --git a/MdePkg/Include/Library/DxeServicesTableLib.h b/MdePkg/Include/Library/DxeServicesTableLib.h new file mode 100644 index 0000000000..f473a1721c --- /dev/null +++ b/MdePkg/Include/Library/DxeServicesTableLib.h @@ -0,0 +1,26 @@ +/** @file + Library that provides a global pointer to the DXE Services Table + + Copyright (c) 2006, 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. + + Module Name: DxeServicesTableLib.h + +**/ + +#ifndef __DXE_SERVICES_TABLE_LIB_H__ +#define __DXE_SERVICES_TABLE_LIB_H__ + +// +// +// +extern EFI_DXE_SERVICES *gDS; + +#endif + diff --git a/MdePkg/Include/Library/DxeSmmDriverEntryPoint.h b/MdePkg/Include/Library/DxeSmmDriverEntryPoint.h new file mode 100644 index 0000000000..12d35d5f52 --- /dev/null +++ b/MdePkg/Include/Library/DxeSmmDriverEntryPoint.h @@ -0,0 +1,140 @@ +/** @file + Entry point to a DXE SMM Driver + +Copyright (c) 2006, 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 __MODULE_ENTRY_POINT_H__ +#define __MODULE_ENTRY_POINT_H__ + +// +// Declare the EFI/UEFI Specification Revision to which this driver is implemented +// +extern const UINT32 _gUefiDriverRevision; + +// +// Declare the number of entry points in the image. +// +extern const UINT8 _gDriverEntryPointCount; + +// +// Declare the number of unload handler in the image. +// +extern const UINT8 _gDriverUnloadImageCount; + +/** + Enrty point to DXE SMM Driver. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @retval EFI_SUCCESS One or more of the drivers returned a success code. + @retval !EFI_SUCESS The return status from the last driver entry point in the list. + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Enrty point wrapper of DXE SMM Driver. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @retval EFI_SUCCESS One or more of the drivers returned a success code. + @retval !EFI_SUCESS The return status from the last driver entry point in the list. + +**/ +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Computes the cummulative return status for the driver entry point and perform + a long jump back into DriverEntryPoint(). + + @param Status Status returned by the driver that is exiting. + +**/ +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ); + +/** + Call constructs for all libraries. Automatics Generated by tool. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Call destructors for all libraries. Automatics Generated by tool. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + +**/ +VOID +EFIAPI +ProcessLibraryDestructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Call the list of driver entry points. Automatics Generated by tool. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @return Status returned by entry points of drivers. + +**/ +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Call the unload handlers for all the modules. Automatics Generated by tool. + + @param ImageHandle ImageHandle of the loaded driver. + + @return Status returned by unload handlers of drivers. + +**/ +EFI_STATUS +EFIAPI +ProcessModuleUnloadList ( + IN EFI_HANDLE ImageHandle + ); + +#endif diff --git a/MdePkg/Include/Library/HiiLib.h b/MdePkg/Include/Library/HiiLib.h new file mode 100644 index 0000000000..05824a6e33 --- /dev/null +++ b/MdePkg/Include/Library/HiiLib.h @@ -0,0 +1,44 @@ +/** @file + Public include file for the HII Library + + Copyright (c) 2006, 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. + + Module Name: HiiLib.h + +**/ + +#ifndef __HII_LIB_H__ +#define __HII_LIB_H__ + +/** + This function allocates pool for an EFI_HII_PACKAGES structure + with enough space for the variable argument list of package pointers. + The allocated structure is initialized using NumberOfPackages, Guid, + and the variable length argument list of package pointers. + + @param NumberOfPackages The number of HII packages to prepare. + @param Guid Package GUID. + + @return + The allocated and initialized packages. + +**/ +EFI_HII_PACKAGES * +EFIAPI +PreparePackages ( + IN UINTN NumberOfPackages, + IN CONST EFI_GUID *Guid OPTIONAL, + ... + ) +; + + + +#endif diff --git a/MdePkg/Include/Library/HobLib.h b/MdePkg/Include/Library/HobLib.h new file mode 100644 index 0000000000..cac9c4fa09 --- /dev/null +++ b/MdePkg/Include/Library/HobLib.h @@ -0,0 +1,275 @@ +/** @file + Public include file for the HOB Library + + Copyright (c) 2006, 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. + + Module Name: HobLib.h + +**/ + +#ifndef __HOB_LIB_H__ +#define __HOB_LIB_H__ + +/** + Returns the pointer to the HOB list. + + @return The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ) +; + +/** + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ) +; + +/** + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ) +; + +/** + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ) +; + +/** + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ) +; + +/** + This function builds a HOB for a loaded PE32 module. + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the moduleÂ’s entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +; + +/** + Builds a HOB that describes a chunk of system memory. + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +; + +/** + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +; + +/** + This function builds a customized HOB tagged with a GUID for identification, + copies the input data to the HOB data field, and returns the start address of GUID HOB data. + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +; + +/** + Builds a Firmware Volume HOB. + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +; + +/** + Builds a Capsule Volume HOB. + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +; + +/** + Builds a HOB for the CPU. + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +; + +/** + Builds a HOB for the Stack. + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +; + +/** + Builds a HOB for the BSP store. + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +; + +/** + Builds a HOB for the memory allocation. + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +; + +#endif diff --git a/MdePkg/Include/Library/IoLib.h b/MdePkg/Include/Library/IoLib.h new file mode 100644 index 0000000000..532c26b0e5 --- /dev/null +++ b/MdePkg/Include/Library/IoLib.h @@ -0,0 +1,2311 @@ +/** @file + I/O and MMIO Library Services + + Copyright (c) 2006, 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. + + Module Name: IoLib.h + +**/ + +#ifndef __IO_LIB_H__ +#define __IO_LIB_H__ + +#define IO_LIB_ADDRESS(Segment,Port) \ + ( ((Port) & 0xffff) | (((Segment) & 0xffff) << 16) ) + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ); + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ); + +/** + Reads an 8-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoOr8 ( + IN UINTN Port, + IN UINT8 OrData + ); + +/** + Reads an 8-bit I/O port, performs a bitwise AND, and writes the result back + to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAnd8 ( + IN UINTN Port, + IN UINT8 AndData + ); + +/** + Reads an 8-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAndThenOr8 ( + IN UINTN Port, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Reads a bit field of an I/O register. + + Reads the bit field in an 8-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoBitFieldRead8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldWrite8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ); + +/** + Reads a bit field in an 8-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ); + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAnd8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ); + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 8-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAndThenOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ); + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ); + +/** + Reads a 16-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoOr16 ( + IN UINTN Port, + IN UINT16 OrData + ); + +/** + Reads a 16-bit I/O port, performs a bitwise AND, and writes the result back + to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAnd16 ( + IN UINTN Port, + IN UINT16 AndData + ); + +/** + Reads a 16-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAndThenOr16 ( + IN UINTN Port, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 16-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoBitFieldRead16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldWrite16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ); + +/** + Reads a bit field in a 16-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ); + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAnd16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ); + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 16-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAndThenOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ); + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ); + +/** + Reads a 32-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoOr32 ( + IN UINTN Port, + IN UINT32 OrData + ); + +/** + Reads a 32-bit I/O port, performs a bitwise AND, and writes the result back + to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAnd32 ( + IN UINTN Port, + IN UINT32 AndData + ); + +/** + Reads a 32-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAndThenOr32 ( + IN UINTN Port, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 32-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoBitFieldRead32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldWrite32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + +/** + Reads a bit field in a 32-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAnd32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 32-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAndThenOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoRead64 ( + IN UINTN Port + ); + +/** + Writes a 64-bit I/O port. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT64 +EFIAPI +IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ); + +/** + Reads a 64-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoOr64 ( + IN UINTN Port, + IN UINT64 OrData + ); + +/** + Reads a 64-bit I/O port, performs a bitwise AND, and writes the result back + to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAnd64 ( + IN UINTN Port, + IN UINT64 AndData + ); + +/** + Reads a 64-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAndThenOr64 ( + IN UINTN Port, + IN UINT64 AndData, + IN UINT64 OrData + ); + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 64-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoBitFieldRead64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldWrite64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ); + +/** + Reads a bit field in a 64-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ); + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAnd64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ); + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 64-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAndThenOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ); + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8 ( + IN UINTN Address + ); + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ); + +/** + Reads an 8-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioOr8 ( + IN UINTN Address, + IN UINT8 OrData + ); + +/** + Reads an 8-bit MMIO register, performs a bitwise AND, and writes the result + back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ); + +/** + Reads an 8-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 8-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in an 8-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 8-bit register is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ); + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ); + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ); + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 8-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16 ( + IN UINTN Address + ); + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ); + +/** + Reads a 16-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioOr16 ( + IN UINTN Address, + IN UINT16 OrData + ); + +/** + Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result + back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ); + +/** + Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 16-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 16-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 16-bit register is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ); + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ); + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ); + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 16-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32 ( + IN UINTN Address + ); + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ); + +/** + Reads a 32-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioOr32 ( + IN UINTN Address, + IN UINT32 OrData + ); + +/** + Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result + back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ); + +/** + Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 32-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 32-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 32-bit register is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 32-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64 ( + IN UINTN Address + ); + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ); + +/** + Reads a 64-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioOr64 ( + IN UINTN Address, + IN UINT64 OrData + ); + +/** + Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result + back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAnd64 ( + IN UINTN Address, + IN UINT64 AndData + ); + +/** + Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 64-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAndThenOr64 ( + IN UINTN Address, + IN UINT64 AndData, + IN UINT64 OrData + ); + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 64-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioBitFieldRead64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 64-bit register is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldWrite64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ); + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ); + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAnd64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ); + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 64-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAndThenOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ); + +#endif diff --git a/MdePkg/Include/Library/MemoryAllocationLib.h b/MdePkg/Include/Library/MemoryAllocationLib.h new file mode 100644 index 0000000000..4e76684f77 --- /dev/null +++ b/MdePkg/Include/Library/MemoryAllocationLib.h @@ -0,0 +1,547 @@ +/** @file + Memory Allocation Library Services + + Copyright (c) 2006, 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. + + Module Name: MemoryAllocationLib.h + +**/ + +#ifndef __MEMORY_ALLOCATION_LIB_H__ +#define __MEMORY_ALLOCATION_LIB_H__ + +/** + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData. + + @param Pages The number of 4 KB pages to allocate. + + @return + A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +; + +/** + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData. + + @param Pages The number of 4 KB pages to allocate. + + @return + A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimePages ( + IN UINTN Pages + ) +; + +/** + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType. + + @param Pages The number of 4 KB pages to allocate. + + @return + A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedPages ( + IN UINTN Pages + ) +; + +/** + Frees one or more 4KB pages that were previously allocated with + one of the page allocation functions in the Memory Allocation Library. + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + + None. + +**/ +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +; + +/** + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData with an alignment specified by Alignment. + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +; + +/** + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData with an alignment specified by Alignment. + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +; + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +; + +/** + Frees one or more 4KB pages that were previously allocated with + one of the aligned page allocation functions in the Memory Allocation Library. + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + + None. + +**/ +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +; + +/** + Allocates a buffer of type EfiBootServicesData. + + @param AllocationSize The number of bytes to allocate. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +; + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + @param AllocationSize The number of bytes to allocate. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimePool ( + IN UINTN AllocationSize + ) +; + +/** + Allocates a buffer of type EfiReservedMemoryType. + + @param AllocationSize The number of bytes to allocate. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedPool ( + IN UINTN AllocationSize + ) +; + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + @param AllocationSize The number of bytes to allocate and zero. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +; + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + @param AllocationSize The number of bytes to allocate and zero. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +; + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + @param AllocationSize The number of bytes to allocate and zero. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +; + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +; + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +; + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +; + +/** + Frees a buffer that was previously allocated with one of the pool allocation functions + in the Memory Allocation Library. + + @param Buffer Pointer to the buffer to free. + + None. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +; + +/** + Allocates a buffer of type EfiBootServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +; + +/** + Allocates a buffer of type EfiRuntimeServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +; + +/** + Allocates a buffer of type EfiReservedMemoryType at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +; + +/** + Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +; + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimeZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +; + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +; + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +; + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +; + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +; + +/** + Frees a buffer that was previously allocated with one of the aligned pool allocation functions + in the Memory Allocation Library. + + @param Buffer Pointer to the buffer to free. + + None. + +**/ +VOID +EFIAPI +FreeAlignedPool ( + IN VOID *Buffer + ) +; + +#endif diff --git a/MdePkg/Include/Library/PcdLib.h b/MdePkg/Include/Library/PcdLib.h new file mode 100644 index 0000000000..1375e0039f --- /dev/null +++ b/MdePkg/Include/Library/PcdLib.h @@ -0,0 +1,690 @@ +/** @file +PCD Library Class Interface Declarations + +Copyright (c) 2006, 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. + + +Module Name: PcdLib.h + +**/ + +#ifndef __PCD_LIB_H__ +#define __PCD_LIB_H__ + + +#define PcdToken(TokenName) _PCD_TOKEN_##TokenName + + +// +// Feature Flag is in the form of a global constant +// +#define FeaturePcdGet(TokenName) _gPcd_FixedAtBuild_##TokenName + + +// +// Fixed is fixed at build time +// +#define FixedPcdGet8(TokenName) _gPcd_FixedAtBuild_##TokenName +#define FixedPcdGet16(TokenName) _gPcd_FixedAtBuild_##TokenName +#define FixedPcdGet32(TokenName) _gPcd_FixedAtBuild_##TokenName +#define FixedPcdGet64(TokenName) _gPcd_FixedAtBuild_##TokenName +#define FixedPcdGetBool(TokenName) _gPcd_FixedAtBuild_##TokenName + + +// +// BugBug: This works for strings, but not constants. +// +#define FixedPcdGetPtr(TokenName) ((VOID *)_gPcd_FixedAtBuild_##TokenName) + + +// +// (Binary) Patch is in the form of a global variable +// +#define PatchPcdGet8(TokenName) _gPcd_BinaryPatch_##TokenName +#define PatchPcdGet16(TokenName) _gPcd_BinaryPatch_##TokenName +#define PatchPcdGet32(TokenName) _gPcd_BinaryPatch_##TokenName +#define PatchPcdGet64(TokenName) _gPcd_BinaryPatch_##TokenName +#define PatchPcdGetBool(TokenName) _gPcd_BinaryPatch_##TokenName +#define PatchPcdGetPtr(TokenName) ((VOID *)_gPcd_BinaryPatch_##TokenName) + + +// +// Dynamic is via the protocol with only the TokenNumber as argument +// It can also be Patch or Fixed type based on a build option +// +#define PcdGet8(TokenName) _PCD_MODE_8_##TokenName +#define PcdGet16(TokenName) _PCD_MODE_16_##TokenName +#define PcdGet32(TokenName) _PCD_MODE_32_##TokenName +#define PcdGet64(TokenName) _PCD_MODE_64_##TokenName +#define PcdGetPtr(TokenName) _PCD_MODE_PTR_##TokenName +#define PcdGetBool(TokenName) _PCD_MODE_BOOL_##TokenName + + +// +// Dynamic Ex is to support binary distribution +// +#define PcdGetEx8(Guid, TokenName) LibPcdGetEx8 (Guid, _PCD_TOKEN_##TokenName) +#define PcdGetEx16(Guid, TokenName) LibPcdGetEx16 (Guid, _PCD_TOKEN_##TokenName) +#define PcdGetEx32(Guid, TokenName) LibPcdGetEx32 (Guid, _PCD_TOKEN_##TokenName) +#define PcdGetEx64(Guid, TokenName) LibPcdGetEx64 (Guid, _PCD_TOKEN_##TokenName) +#define PcdGetExPtr(Guid, TokenName) LibPcdGetExPtr (Guid, _PCD_TOKEN_##TokenName) +#define PcdGetExBool(Guid, TokenName) LibPcdGetExBool (Guid, _PCD_TOKEN_##TokenName) + + +// +// Dynamic Set +// +#define PcdSet8(TokenName, Value) LibPcdSet8 (_PCD_TOKEN_##TokenName, Value) +#define PcdSet16(TokenName, Value) LibPcdSet16 (_PCD_TOKEN_##TokenName, Value) +#define PcdSet32(TokenName, Value) LibPcdSet32 (_PCD_TOKEN_##TokenName, Value) +#define PcdSet64(TokenName, Value) LibPcdSet64 (_PCD_TOKEN_##TokenName, Value) +#define PcdSetPtr(TokenName, Value) LibPcdSetPtr (_PCD_TOKEN_##TokenName, Value) +#define PcdSetBool(TokenName, Value) LibPcdSetBool(_PCD_TOKEN_##TokenName, Value) + + +// +// Dynamic Set Ex +// +#define PcdSetEx8 (Guid, TokenName, Value) LibPcdSetEx8 (Guid, _PCD_TOKEN_##TokenName, Value) +#define PcdSetEx16 (Guid, TokenName, Value) LibPcdSetEx16 (Guid, _PCD_TOKEN_##TokenName, Value) +#define PcdSetEx32 (Guid, TokenName, Value) LibPcdSetEx32 (Guid, _PCD_TOKEN_##TokenName, Value) +#define PcdSetEx64 (Guid, TokenName, Value) LibPcdSetEx64 (Guid, _PCD_TOKEN_##TokenName, Value) +#define PcdSetExPtr (Guid, TokenName, Value) LibPcdSetExPtr (Guid, _PCD_TOKEN_##TokenName, Value) +#define PcdSetExBool(Guid, TokenName, Value) LibPcdSetExBool(Guid, _PCD_TOKEN_##TokenName, Value) + + +/** + Sets the current SKU in the PCD database to the value specified by SkuId. SkuId is returned. + + @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and + set values associated with a PCD token. + + @retval UINTN Return the SKU ID that just be set. + +**/ +UINTN +EFIAPI +LibPcdSetSku ( + IN UINTN SkuId + ); + + +/** + Returns the 8-bit value for the token specified by TokenNumber. + + @param[in] The PCD token number to retrieve a current value for. + + @retval UINT8 Returns the 8-bit value for the token specified by TokenNumber. + +**/ +UINT8 +EFIAPI +LibPcdGet8 ( + IN UINTN TokenNumber + ); + + +/** + Returns the 16-bit value for the token specified by TokenNumber. + + @param[in] The PCD token number to retrieve a current value for. + + @retval UINT16 Returns the 16-bit value for the token specified by TokenNumber. + +**/ +UINT16 +EFIAPI +LibPcdGet16 ( + IN UINTN TokenNumber + ); + + +/** + Returns the 32-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT32 Returns the 32-bit value for the token specified by TokenNumber. + +**/ +UINT32 +EFIAPI +LibPcdGet32 ( + IN UINTN TokenNumber + ); + + +/** + Returns the 64-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT64 Returns the 64-bit value for the token specified by TokenNumber. + +**/ +UINT64 +EFIAPI +LibPcdGet64 ( + IN UINTN TokenNumber + ); + + +/** + Returns the pointer to the buffer of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval VOID* Returns the pointer to the token specified by TokenNumber. + +**/ +VOID * +EFIAPI +LibPcdGetPtr ( + IN UINTN TokenNumber + ); + + +/** + Returns the Boolean value of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval BOOLEAN Returns the Boolean value of the token specified by TokenNumber. + +**/ +BOOLEAN +EFIAPI +LibPcdGetBool ( + IN UINTN TokenNumber + ); + + +/** + Returns the size of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINTN Returns the size of the token specified by TokenNumber. + +**/ +UINTN +EFIAPI +LibPcdGetSize ( + IN UINTN TokenNumber + ); + + +/** + Returns the 8-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT8 Return the UINT8. + +**/ +UINT8 +EFIAPI +LibPcdGetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ); + + +/** + Returns the 16-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT16 Return the UINT16. + +**/ +UINT16 +EFIAPI +LibPcdGetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ); + + +/** + Returns the 32-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT32 Return the UINT32. + +**/ +UINT32 +EFIAPI +LibPcdGetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ); + + +/** + Returns the 64-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT64 Return the UINT64. + +**/ +UINT64 +EFIAPI +LibPcdGetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ); + + +/** + Returns the pointer to the buffer of token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval VOID* Return the VOID* pointer. + +**/ +VOID * +EFIAPI +LibPcdGetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ); + + +/** + Returns the Boolean value of the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval BOOLEAN Return the BOOLEAN. + +**/ +BOOLEAN +EFIAPI +LibPcdGetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ); + + +/** + Returns the size of the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINTN Return the size. + +**/ +UINTN +EFIAPI +LibPcdGetExSize ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ); + + +/** + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT8 +EFIAPI +LibPcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ); + + +/** + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @retval UINT16 Return the value been set. + +**/ +UINT16 +EFIAPI +LibPcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ); + + +/** + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @retval UINT32 Return the value been set. + +**/ +UINT32 +EFIAPI +LibPcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ); + + +/** + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @retval UINT64 Return the value been set. + +**/ +UINT64 +EFIAPI +LibPcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ); + + +/** + Sets a buffer for the token specified by TokenNumber to + the value specified by Value. Value is returned. + If Value is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value A pointer to the buffer to set. + + @retval VOID* Return the pointer for the buffer been set. + +**/ +VOID* +EFIAPI +LibPcdSetPtr ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ); + + +/** + Sets the Boolean value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @retval BOOLEAN Return the value been set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ); + + +/** + Sets the 8-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT8 +EFIAPI +LibPcdSetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ); + + +/** + Sets the 16-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT16 +EFIAPI +LibPcdSetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ); + + +/** + Sets the 32-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @retval UINT32 Return the value been set. + +**/ +UINT32 +EFIAPI +LibPcdSetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ); + + +/** + Sets the 64-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @retval UINT64 Return the value been set. + +**/ +UINT64 +EFIAPI +LibPcdSetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ); + + +/** + Sets a buffer for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + If Value is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval VOID * Return the value been set. + +**/ +VOID * +EFIAPI +LibPcdSetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ); + + +/** + Sets the Boolean value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The Boolean value to set. + + @retval Boolean Return the value been set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ); + + +/** + When the token specified by TokenNumber and Guid is set, + then notification function specified by NotificationFunction is called. + If Guid is NULL, then the default token space is used. + If NotificationFunction is NULL, then ASSERT(). + + @param[in] CallBackGuid The PCD token GUID being set. + @param[in] CallBackToken The PCD token number being set. + @param[in] TokenData A pointer to the token data being set. + @param[in] TokenDataSize The size, in bytes, of the data being set. + + @retval VOID + +**/ +typedef +VOID +(EFIAPI *PCD_CALLBACK) ( + IN CONST GUID *CallBackGuid, OPTIONAL + IN UINTN CallBackToken, + IN VOID *TokenData, + IN UINTN TokenDataSize + ); + + +/** + When the token specified by TokenNumber and Guid is set, + then notification function specified by NotificationFunction is called. + If Guid is NULL, then the default token space is used. + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates which + namespace to set a value from. If NULL, then the default + token space is used. + @param[in] TokenNumber The PCD token number to monitor. + @param[in] NotificationFunction The function to call when the token + specified by Guid and TokenNumber is set. + + @retval VOID + +**/ +VOID +EFIAPI +LibPcdCallbackOnSet ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ); + + +/** + Disable a notification function that was established with LibPcdCallbackonSet(). + + @param[in] Guid Specify the GUID token space. + @param[in] TokenNumber Specify the token number. + @param[in] NotificationFunction The callback function to be unregistered. + + @retval VOID + +**/ +VOID +EFIAPI +LibPcdCancelCallback ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ); + + +/** + Retrieves the next PCD token number from the token space specified by Guid. + If Guid is NULL, then the default token space is used. If TokenNumber is 0, + then the first token number is returned. Otherwise, the token number that + follows TokenNumber in the token space is returned. If TokenNumber is the last + token number in the token space, then 0 is returned. If TokenNumber is not 0 and + is not in the token space specified by Guid, then ASSERT(). + + @param[in] Pointer to a 128-bit unique value that designates which namespace + to set a value from. If NULL, then the default token space is used. + @param[in] The previous PCD token number. If 0, then retrieves the first PCD + token number. + + @retval UINTN The next valid token number. + +**/ +UINTN +EFIAPI +LibPcdGetNextToken ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN *TokenNumber + ); + +#endif diff --git a/MdePkg/Include/Library/PciCf8Lib.h b/MdePkg/Include/Library/PciCf8Lib.h new file mode 100644 index 0000000000..a1023916ba --- /dev/null +++ b/MdePkg/Include/Library/PciCf8Lib.h @@ -0,0 +1,1052 @@ +/** @file + PCI CF8 Library Services for PCI Segment #0 + + Copyright (c) 2006, 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. + + Module Name: PciCf8Lib.h + +**/ + +#ifndef __PCI_CF8_LIB_H__ +#define __PCI_CF8_LIB_H__ + +#include + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + address that can be passed to the PCI Library functions. + + Computes an address that is compatible with the PCI Library functions. The + unused upper bits of Bus, Device, Function and Register are stripped prior to + the generation of the address. + + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..255. + + @return The encode PCI address. + +**/ +#define PCI_CF8_LIB_ADDRESS(Bus,Device,Function,Offset) \ + PCI_LIB_ADDRESS (Bus, Device, Function, Offset) + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8Read8 ( + IN UINTN Address + ); + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8Write8 ( + IN UINTN Address, + IN UINT8 Data + ); + +/** + Performs a bitwise inclusive OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8Or8 ( + IN UINTN Address, + IN UINT8 OrData + ); + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8And8 ( + IN UINTN Address, + IN UINT8 AndData + ); + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise inclusive OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8AndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ); + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ); + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ); + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8Read16 ( + IN UINTN Address + ); + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8Write16 ( + IN UINTN Address, + IN UINT16 Data + ); + +/** + Performs a bitwise inclusive OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8Or16 ( + IN UINTN Address, + IN UINT16 OrData + ); + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8And16 ( + IN UINTN Address, + IN UINT16 AndData + ); + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise inclusive OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8AndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ); + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ); + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ); + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8Read32 ( + IN UINTN Address + ); + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8Write32 ( + IN UINTN Address, + IN UINT32 Data + ); + +/** + Performs a bitwise inclusive OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8Or32 ( + IN UINTN Address, + IN UINT32 OrData + ); + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8And32 ( + IN UINTN Address, + IN UINT32 AndData + ); + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise inclusive OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8AndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If the register specified by StartAddress >= 0x100, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x100, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciCf8ReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ); + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If the register specified by StartAddress >= 0x100, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x100, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return Size + +**/ +UINTN +EFIAPI +PciCf8WriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ); + +#endif diff --git a/MdePkg/Include/Library/PciExpressLib.h b/MdePkg/Include/Library/PciExpressLib.h new file mode 100644 index 0000000000..b773e72fd8 --- /dev/null +++ b/MdePkg/Include/Library/PciExpressLib.h @@ -0,0 +1,1020 @@ +/** @file + Pci Express Library Services for PCI Segment #0 + + Copyright (c) 2006, 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. + + Module Name: PciExpressLib.h + +**/ + +#ifndef __PCI_EXPRESS_LIB_H__ +#define __PCI_EXPRESS_LIB_H__ + +#include + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + address that can be passed to the PCI Library functions. + + Computes an address that is compatible with the PCI Library functions. The + unused upper bits of Bus, Device, Function and Register are stripped prior to + the generation of the address. + + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..4095. + + @return The encode PCI address. + +**/ +#define PCI_EXPRESS_LIB_ADDRESS(Bus,Device,Function,Offset) \ + PCI_LIB_ADDRESS (Bus, Device, Function, Offset) + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressRead8 ( + IN UINTN Address + ); + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressWrite8 ( + IN UINTN Address, + IN UINT8 Data + ); + +/** + Performs a bitwise inclusive OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressOr8 ( + IN UINTN Address, + IN UINT8 OrData + ); + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ); + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise inclusive OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ); + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ); + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ); + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressRead16 ( + IN UINTN Address + ); + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressWrite16 ( + IN UINTN Address, + IN UINT16 Data + ); + +/** + Performs a bitwise inclusive OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressOr16 ( + IN UINTN Address, + IN UINT16 OrData + ); + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ); + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise inclusive OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ); + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ); + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ); + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressRead32 ( + IN UINTN Address + ); + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressWrite32 ( + IN UINTN Address, + IN UINT32 Data + ); + +/** + Performs a bitwise inclusive OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressOr32 ( + IN UINTN Address, + IN UINT32 OrData + ); + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ); + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise inclusive OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciExpressReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ); + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return Size + +**/ +UINTN +EFIAPI +PciExpressWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ); + +#endif diff --git a/MdePkg/Include/Library/PciLib.h b/MdePkg/Include/Library/PciLib.h new file mode 100644 index 0000000000..55edf4082f --- /dev/null +++ b/MdePkg/Include/Library/PciLib.h @@ -0,0 +1,1015 @@ +/** @file + PCI Library Services for PCI Segment #0 + + Copyright (c) 2006, 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. + + Module Name: PciLib.h + +**/ + +#ifndef __PCI_LIB_H__ +#define __PCI_LIB_H__ + +/** + Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an + address that can be passed to the PCI Library functions. + + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..255 for PCI. Range 0..4095 + for PCI Express. + + @return The encoded PCI address. + +**/ +#define PCI_LIB_ADDRESS(Bus,Device,Function,Offset) \ + (((Offset) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20)) + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciRead8 ( + IN UINTN Address + ); + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciWrite8 ( + IN UINTN Address, + IN UINT8 Data + ); + +/** + Performs a bitwise inclusive OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciOr8 ( + IN UINTN Address, + IN UINT8 OrData + ); + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ); + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise inclusive OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ); + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ); + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ); + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ); + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciRead16 ( + IN UINTN Address + ); + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciWrite16 ( + IN UINTN Address, + IN UINT16 Data + ); + +/** + Performs a bitwise inclusive OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciOr16 ( + IN UINTN Address, + IN UINT16 OrData + ); + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ); + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise inclusive OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ); + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ); + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ); + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ); + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciRead32 ( + IN UINTN Address + ); + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciWrite32 ( + IN UINTN Address, + IN UINT32 Data + ); + +/** + Performs a bitwise inclusive OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciOr32 ( + IN UINTN Address, + IN UINT32 OrData + ); + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ); + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise inclusive OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ); + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ); + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ); + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ); + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ); + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ); + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return Size + +**/ +UINTN +EFIAPI +PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ); + +#endif diff --git a/MdePkg/Include/Library/PciSegmentLib.h b/MdePkg/Include/Library/PciSegmentLib.h new file mode 100644 index 0000000000..eaca938762 --- /dev/null +++ b/MdePkg/Include/Library/PciSegmentLib.h @@ -0,0 +1,924 @@ +/** @file + Functions accessing PCI configuration registers on any supported PCI segment + + Copyright (c) 2006, 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. + + Module Name: PciSegmentLib.h + +**/ + +#ifndef __PCI_SEGMENT_LIB__ +#define __PCI_SEGMENT_LIB__ + + +/** + Macro that converts PCI Segment, PCI Bus, PCI Device, PCI Function, + and PCI Register to an address that can be passed to the PCI Segment Library functions. + + Computes an address that is compatible with the PCI Segment Library functions. + The unused upper bits of Segment, Bus, Device, Function, + and Register are stripped prior to the generation of the address. + + @param Segment PCI Segment number. Range 0..65535. + @param Bus PCI Bus number. Range 0..255. + @param Device PCI Device number. Range 0..31. + @param Function PCI Function number. Range 0..7. + @param Register PCI Register number. Range 0..255 for PCI. Range 0..4095 for PCI Express. + + @return The address that is compatible with the PCI Segment Library functions. + +**/ +#define PCI_SEGMENT_LIB_ADDRESS(Segment,Bus,Device,Function,Register) \ + ( ((Register) & 0xfff) | \ + (((Function) & 0x07) << 12) | \ + (((Device) & 0x1f) << 15) | \ + (((Bus) & 0xff) << 20) | \ + (LShiftU64((Segment) & 0xffff, 32)) \ + ) + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 8-bit PCI configuration register specified by Address. + +**/ +UINT8 +EFIAPI +PciSegmentRead8 ( + IN UINT64 Address + ) +; + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +PciSegmentWrite8 ( + IN UINT64 Address, + IN UINT8 Value + ) +; + +/** + Performs a bitwise inclusive OR of an 8-bit PCI configuration register with an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise inclusive OR between the read result and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentOr8 ( + IN UINT64 Address, + IN UINT8 OrData + ) +; + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Andata The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAnd8 ( + IN UINT64 Address, + IN UINT8 AndData + ) +; + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit value, + followed a bitwise inclusive OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Andata The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentAndThenOr8 ( + IN UINT64 Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +; + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. + The bit field is specified by the StartBit and the EndBit. + The value of the bit field is returned. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + + @return The value of the bit field. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldRead8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +; + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. + The bit field is specified by the StartBit and the EndBit. + All other bits in the destination PCI configuration register are preserved. + The new value of the 8-bit register is returned. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param Value New value of the bit field. + + @return The new value of the 8-bit register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldWrite8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +; + +/** + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise inclusive OR between the read result and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param OrData The value to OR with the read value from the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +; + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, + and writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise inclusive OR between the read result and the value specified by OrData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + Extra left bits in OrData are stripped. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param AndData The value to AND with the read value from the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAnd8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +; + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise AND, + and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 8-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + Extra left bits in AndData are stripped. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param AndData The value to AND with the read value from the PCI configuration register. + @param OrData The value to OR with the read value from the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciSegmentBitFieldAndThenOr8 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +; + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 16-bit PCI configuration register specified by Address. + +**/ +UINT16 +EFIAPI +PciSegmentRead16 ( + IN UINT64 Address + ) +; + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +PciSegmentWrite16 ( + IN UINT64 Address, + IN UINT16 Value + ) +; + +/** + Performs a bitwise inclusive OR of a 16-bit PCI configuration register with a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise inclusive OR between the read result and the value specified by OrData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentOr16 ( + IN UINT64 Address, + IN UINT16 OrData + ) +; + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Andata The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAnd16 ( + IN UINT64 Address, + IN UINT16 AndData + ) +; + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit value, + followed a bitwise inclusive OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Andata The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentAndThenOr16 ( + IN UINT64 Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +; + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. + The bit field is specified by the StartBit and the EndBit. + The value of the bit field is returned. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + + @return The value of the bit field. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldRead16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +; + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. + The bit field is specified by the StartBit and the EndBit. + All other bits in the destination PCI configuration register are preserved. + The new value of the 16-bit register is returned. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param Value New value of the bit field. + + @return The new value of the 16-bit register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldWrite16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +; + +/** + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise inclusive OR between the read result and the value specified by OrData, + and writes the result to the 16-bit PCI configuration register specified by Address. + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param OrData The value to OR with the read value from the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +; + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, + and writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise inclusive OR between the read result and the value specified by OrData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + Extra left bits in OrData are stripped. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param AndData The value to AND with the read value from the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAnd16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +; + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise AND, + and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 16-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + Extra left bits in AndData are stripped. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param AndData The value to AND with the read value from the PCI configuration register. + @param OrData The value to OR with the read value from the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciSegmentBitFieldAndThenOr16 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +; + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + + @return The 32-bit PCI configuration register specified by Address. + +**/ +UINT32 +EFIAPI +PciSegmentRead32 ( + IN UINT64 Address + ) +; + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the value specified by Value. + Value is returned. This function must guarantee that all PCI read and write operations are serialized. + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Value The value to write. + + @return The parameter of Value. + +**/ +UINT32 +EFIAPI +PciSegmentWrite32 ( + IN UINT64 Address, + IN UINT32 Value + ) +; + +/** + Performs a bitwise inclusive OR of a 32-bit PCI configuration register with a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise inclusive OR between the read result and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentOr32 ( + IN UINT64 Address, + IN UINT32 OrData + ) +; + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Andata The value to AND with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAnd32 ( + IN UINT64 Address, + IN UINT32 AndData + ) +; + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit value, + followed a bitwise inclusive OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + If any reserved bits in Address are set, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Andata The value to AND with the PCI configuration register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentAndThenOr32 ( + IN UINT64 Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +; + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. + The bit field is specified by the StartBit and the EndBit. + The value of the bit field is returned. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + + @return The value of the bit field. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldRead32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +; + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. + The bit field is specified by the StartBit and the EndBit. + All other bits in the destination PCI configuration register are preserved. + The new value of the 32-bit register is returned. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param Value New value of the bit field. + + @return The new value of the 32-bit register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldWrite32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +; + +/** + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise inclusive OR between the read result and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param OrData The value to OR with the read value from the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +; + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, + and writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise inclusive OR between the read result and the value specified by OrData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + Extra left bits in OrData are stripped. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param AndData The value to AND with the read value from the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAnd32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +; + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise AND, + and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, + performs a bitwise AND between the read result and the value specified by AndData, + and writes the result to the 32-bit PCI configuration register specified by Address. + The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are serialized. + Extra left bits in AndData are stripped. + If any reserved bits in Address are set, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address Address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param StartBit The ordinal of the least significant bit in the bit field. + The ordinal of the least significant bit in a byte is bit 0. + @param EndBit The ordinal of the most significant bit in the bit field. + The ordinal of the most significant bit in a byte is bit 7. + @param AndData The value to AND with the read value from the PCI configuration register. + @param OrData The value to OR with the read value from the PCI configuration register. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciSegmentBitFieldAndThenOr32 ( + IN UINT64 Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +; + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress + and Size into the buffer specified by Buffer. + This function only allows the PCI configuration registers from a single PCI function to be read. + Size is returned. + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return The paramter of Size. + +**/ +UINTN +EFIAPI +PciSegmentReadBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +; + +/** + Copies the data in a caller supplied buffer to a specified range of PCI configuration space. + + Writes the range of PCI configuration registers specified by StartAddress + and Size from the buffer specified by Buffer. + This function only allows the PCI configuration registers from a single PCI function to be written. + Size is returned. + If any reserved bits in StartAddress are set, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Segment, Bus, Device, Function, and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return The paramter of Size. + +**/ +UINTN +EFIAPI +PciSegmentWriteBuffer ( + IN UINT64 StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +; + +#endif diff --git a/MdePkg/Include/Library/PeCoffGetEntryPointLib.h b/MdePkg/Include/Library/PeCoffGetEntryPointLib.h new file mode 100644 index 0000000000..f20562eef9 --- /dev/null +++ b/MdePkg/Include/Library/PeCoffGetEntryPointLib.h @@ -0,0 +1,39 @@ +/** @file + Memory Only PE COFF loader + + Copyright (c) 2006, 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. + + Module Name: PeCoffGetEntryPointLib.h + +**/ + +#ifndef __PE_COFF_GET_ENTRY_POINT_LIB_H__ +#define __PE_COFF_GET_ENTRY_POINT_LIB_H__ + +/** + Loads a PE/COFF image into memory + + @param Pe32Data Pointer to a PE/COFF Image + + @param EntryPoint Pointer to the entry point of the PE/COFF image + + @retval EFI_SUCCESS if the EntryPoint was returned + @retval EFI_INVALID_PARAMETER if the EntryPoint could not be found from Pe32Data + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + IN OUT VOID **EntryPoint + ) +; + +#endif diff --git a/MdePkg/Include/Library/PeCoffLib.h b/MdePkg/Include/Library/PeCoffLib.h new file mode 100644 index 0000000000..08e8195a8a --- /dev/null +++ b/MdePkg/Include/Library/PeCoffLib.h @@ -0,0 +1,131 @@ +/** @file + Memory Only PE COFF loader + + Copyright (c) 2006, 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. + + Module Name: PeCoffLib.h + +**/ + +#ifndef __BASE_PE_COFF_LIB_H__ +#define __BASE_PE_COFF_LIB_H__ + +// +// Return status codes from the PE/COFF Loader services +// BUGBUG: Find where used and see if can be replaced by RETURN_STATUS codes +// +#define IMAGE_ERROR_SUCCESS 0 +#define IMAGE_ERROR_IMAGE_READ 1 +#define IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE 2 +#define IMAGE_ERROR_INVALID_MACHINE_TYPE 3 +#define IMAGE_ERROR_INVALID_SUBSYSTEM 4 +#define IMAGE_ERROR_INVALID_IMAGE_ADDRESS 5 +#define IMAGE_ERROR_INVALID_IMAGE_SIZE 6 +#define IMAGE_ERROR_INVALID_SECTION_ALIGNMENT 7 +#define IMAGE_ERROR_SECTION_NOT_LOADED 8 +#define IMAGE_ERROR_FAILED_RELOCATION 9 +#define IMAGE_ERROR_FAILED_ICACHE_FLUSH 10 + + +// +// PE/COFF Loader Read Function passed in by caller +// +typedef +RETURN_STATUS +(EFIAPI *PE_COFF_LOADER_READ_FILE) ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ); + +// +// Context structure used while PE/COFF image is being loaded and relocated +// +typedef struct { + PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + PHYSICAL_ADDRESS DestinationAddress; + PHYSICAL_ADDRESS EntryPoint; + PE_COFF_LOADER_READ_FILE ImageRead; + VOID *Handle; + VOID *FixupData; + UINT32 SectionAlignment; + UINT32 PeCoffHeaderOffset; + UINT32 DebugDirectoryEntryRva; + VOID *CodeView; + CHAR8 *PdbPointer; + UINTN SizeOfHeaders; + UINT32 ImageCodeMemoryType; + UINT32 ImageDataMemoryType; + UINT32 ImageError; + UINTN FixupDataSize; + UINT16 Machine; + UINT16 ImageType; + BOOLEAN RelocationsStripped; + BOOLEAN IsTeImage; +} PE_COFF_LOADER_IMAGE_CONTEXT; + + +/** + Retrieves information on a PE/COFF image + + @param ImageContext The context of the image being loaded + + @retval EFI_SUCCESS The information on the PE/COFF image was collected. + @retval EFI_INVALID_PARAMETER ImageContext is NULL. + @retval EFI_UNSUPPORTED The PE/COFF image is not supported. + @retval Otherwise The error status from reading the PE/COFF image using the + ImageContext->ImageRead() function + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderGetImageInfo ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +; + +/** + Relocates a PE/COFF image in memory + + @param ImageContext Contains information on the loaded image to relocate + + @retval EFI_SUCCESS if the PE/COFF image was relocated + @retval EFI_LOAD_ERROR if the image is not a valid PE/COFF image + @retval EFI_UNSUPPORTED not support + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderRelocateImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +; + +/** + Loads a PE/COFF image into memory + + @param ImageContext Contains information on image to load into memory + + @retval EFI_SUCCESS if the PE/COFF image was loaded + @retval EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer + @retval EFI_LOAD_ERROR if the image is a runtime driver with no relocations + @retval EFI_INVALID_PARAMETER if the image address is invalid + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderLoadImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +; + +#endif diff --git a/MdePkg/Include/Library/PeiCoreEntryPoint.h b/MdePkg/Include/Library/PeiCoreEntryPoint.h new file mode 100644 index 0000000000..4f88223d73 --- /dev/null +++ b/MdePkg/Include/Library/PeiCoreEntryPoint.h @@ -0,0 +1,50 @@ +/** @file + Entry point to the PEI Core + +Copyright (c) 2006, 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 __MODULE_ENTRY_POINT_H__ +#define __MODULE_ENTRY_POINT_H__ + + +/** + Call constructs for all libraries. Automatics Generated by tool. + + @param FfsHeader Pointer to header of FFS. + @param PeiServices Pointer to the PEI Services Table. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ); + + +/** + Call the list of driver entry points. Automatics Generated by tool. + + @param PeiStartupDescriptor Pointer to startup information . + @param OldCoreData Pointer to Original startup information. + + @return Status returned by entry points of drivers. + +**/ +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor, + IN VOID *OldCoreData + ); + +#endif diff --git a/MdePkg/Include/Library/PeiCoreLib.h b/MdePkg/Include/Library/PeiCoreLib.h new file mode 100644 index 0000000000..dfbe51c5da --- /dev/null +++ b/MdePkg/Include/Library/PeiCoreLib.h @@ -0,0 +1,306 @@ +/** @file + PEI Core Library implementation + + Copyright (c) 2006, 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. + + Module Name: PeiCoreLib.h + +**/ + +#ifndef __PEI_CORE_LIB_H__ +#define __PEI_CORE_LIB_H__ + +/** + This service enables a given PEIM to register an interface into the PEI Foundation. + + @param PpiList A pointer to the list of interfaces that the caller shall install. + + @retval EFI_SUCCESS The interface was successfully installed. + @retval EFI_INVALID_PARAMETER The PpiList pointer is NULL. + @retval EFI_INVALID_PARAMETER Any of the PEI PPI descriptors in the list do not have + the EFI_PEI_PPI_DESCRIPTOR_PPI bit set in the Flags field. + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + +**/ +EFI_STATUS +EFIAPI +PeiCoreInstallPpi ( + IN EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +; + +/** + This service enables PEIMs to replace an entry in the PPI database with an alternate entry. + + @param OldPpi Pointer to the old PEI PPI Descriptors. + @param NewPpi Pointer to the new PEI PPI Descriptors. + + @retval EFI_SUCCESS The interface was successfully installed. + @retval EFI_INVALID_PARAMETER The OldPpi or NewPpi is NULL. + @retval EFI_INVALID_PARAMETER Any of the PEI PPI descriptors in the list do not have + the EFI_PEI_PPI_DESCRIPTOR_PPI bit set in the Flags field. + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + @retval EFI_NOT_FOUND The PPI for which the reinstallation was requested has not been installed. + +**/ +EFI_STATUS +EFIAPI +PeiCoreReinstallPpi ( + IN EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +; + +/** + This service enables PEIMs to discover a given instance of an interface. + + @param Guid A pointer to the GUID whose corresponding interface needs to be found. + @param Instance The N-th instance of the interface that is required. + @param PpiDescriptor A pointer to instance of the EFI_PEI_PPI_DESCRIPTOR. + @param Ppi A pointer to the instance of the interface. + + @retval EFI_SUCCESS The interface was successfully returned. + @retval EFI_NOT_FOUND The PPI descriptor is not found in the database. + +**/ +EFI_STATUS +EFIAPI +PeiCoreLocatePpi ( + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +; + +/** + This service enables PEIMs to register a given service to be invoked + when another service is installed or reinstalled. + + @param NotifyList A pointer to the list of notification interfaces that the caller shall install. + + @retval EFI_SUCCESS The interface was successfully installed. + @retval EFI_INVALID_PARAMETER The NotifyList pointer is NULL. + @retval EFI_INVALID_PARAMETER Any of the PEI notify descriptors in the list do not have + the EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES bit set in the Flags field. + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + +**/ +EFI_STATUS +EFIAPI +PeiCoreNotifyPpi ( + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +; + +/** + This service enables PEIMs to ascertain the present value of the boot mode. + + @param BootMode A pointer to contain the value of the boot mode. + + @retval EFI_SUCCESS The boot mode was returned successfully. + @retval EFI_INVALID_PARAMETER BootMode is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiCoreGetBootMode ( + IN OUT EFI_BOOT_MODE *BootMode + ) +; + +/** + This service enables PEIMs to update the boot mode variable. + + @param BootMode The value of the boot mode to set. + + @retval EFI_SUCCESS The value was successfully updated + +**/ +EFI_STATUS +EFIAPI +PeiCoreSetBootMode ( + IN EFI_BOOT_MODE BootMode + ) +; + +/** + This service enables a PEIM to ascertain the address of the list of HOBs in memory. + + @param HobList A pointer to the list of HOBs that the PEI Foundation will initialize. + + @retval EFI_SUCCESS The list was successfully returned. + @retval EFI_NOT_AVAILABLE_YET The HOB list is not yet published. + +**/ +EFI_STATUS +EFIAPI +PeiCoreGetHobList ( + IN OUT VOID **HobList + ) +; + +/** + This service enables PEIMs to create various types of HOBs. + + @param Type The type of HOB to be installed. + @param Length The length of the HOB to be added. + @param Hob The address of a pointer that will contain the HOB header. + + @retval EFI_SUCCESS The HOB was successfully created. + @retval EFI_OUT_OF_RESOURCES There is no additional space for HOB creation. + +**/ +EFI_STATUS +EFIAPI +PeiCoreCreateHob ( + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +; + +/** + This service enables PEIMs to discover additional firmware volumes. + + @param Instance This instance of the firmware volume to find. + The value 0 is the Boot Firmware Volume (BFV). + @param FwVolHeader Pointer to the firmware volume header of the volume to return. + + @retval EFI_SUCCESS The volume was found. + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_INVALID_PARAMETER FwVolHeader is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiCoreFfsFindNextVolume ( + IN UINTN Instance, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +; + +/** + This service enables PEIMs to discover additional firmware files. + + @param SearchType A filter to find files only of this type. + @param FwVolHeader Pointer to the firmware volume header of the volume to search. + This parameter must point to a valid FFS volume. + @param FileHeader Pointer to the current file from which to begin searching. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + +**/ +EFI_STATUS +EFIAPI +PeiCoreFfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +; + +/** + This service enables PEIMs to discover sections of a given type within a valid FFS file. + + @param SearchType The value of the section type to find. + @param FfsFileHeader A pointer to the file header that contains the set of sections to be searched. + @param SectionData A pointer to the discovered section, if successful. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +PeiCoreFfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +; + +/** + This service enables PEIMs to register the permanent memory configuration + that has been initialized with the PEI Foundation. + + @param MemoryBegin The value of a region of installed memory. + @param MemoryLength The corresponding length of a region of installed memory. + + @retval EFI_SUCCESS The region was successfully installed in a HOB. + @retval EFI_INVALID_PARAMETER MemoryBegin and MemoryLength are illegal for this system. + @retval EFI_OUT_OF_RESOURCES There is no additional space for HOB creation. + +**/ +EFI_STATUS +EFIAPI +PeiCoreInstallPeiMemory ( + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +; + +/** + This service enables PEIMs to allocate memory after the permanent memory has been installed by a PEIM. + + @param MemoryType Type of memory to allocate. + @param Pages Number of pages to allocate. + @param Memory Pointer of memory allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + @retval EFI_INVALID_PARAMETER Type is not equal to AllocateAnyPages. + @retval EFI_NOT_AVAILABLE_YET Called with permanent memory not available. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + +**/ +EFI_STATUS +EFIAPI +PeiCoreAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ) +; + +/** + This service allocates memory from the Hand-Off Block (HOB) heap. + + @param Size The number of bytes to allocate from the pool. + @param Buffer If the call succeeds, a pointer to a pointer to the allocated buffer; + undefined otherwise. + + @retval EFI_SUCCESS The allocation was successful + @retval EFI_OUT_OF_RESOURCES There is not enough heap to allocate the requested size. + +**/ +EFI_STATUS +EFIAPI +PeiCoreAllocatePool ( + IN UINTN Size, + OUT VOID **Buffer + ) +; + +/** + This service resets the entire platform, including all processors and devices, and reboots the system. + + @retval EFI_NOT_AVAILABLE_YET The service has not been installed yet. + +**/ +EFI_STATUS +EFIAPI +PeiCoreResetSystem ( + VOID + ) +; + +#endif diff --git a/MdePkg/Include/Library/PeiServicesTablePointerLib.h b/MdePkg/Include/Library/PeiServicesTablePointerLib.h new file mode 100644 index 0000000000..815e722b6c --- /dev/null +++ b/MdePkg/Include/Library/PeiServicesTablePointerLib.h @@ -0,0 +1,26 @@ +/** @file + PEI Services Table Pointer Library services + + Copyright (c) 2006, 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. + + Module Name: PeiServicesTablePointerLib.h + +**/ + +#ifndef __PEI_SERVICES_TABLE_POINTER_LIB_H__ +#define __PEI_SERVICES_TABLE_POINTER_LIB_H__ + +EFI_PEI_SERVICES ** +GetPeiServicesTablePointer ( + VOID + ); + +#endif + diff --git a/MdePkg/Include/Library/PeimEntryPoint.h b/MdePkg/Include/Library/PeimEntryPoint.h new file mode 100644 index 0000000000..e08845926d --- /dev/null +++ b/MdePkg/Include/Library/PeimEntryPoint.h @@ -0,0 +1,103 @@ +/** @file + Entry point to a PEIM + +Copyright (c) 2006, 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 __MODULE_ENTRY_POINT_H__ +#define __MODULE_ENTRY_POINT_H__ + +// +// Declare the EFI/UEFI Specification Revision to which this driver is implemented +// +extern const UINT32 _gPeimRevision; + +/** + Image entry point of Peim. + + @param FfsHeader Pointer to FFS header the loaded driver. + @param PeiServices Pointer to the PEI services. + + @return Status returned by entry points of Peims. + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ); + + +/** + Wrapper of Peim image entry point. + + @param FfsHeader Pointer to FFS header the loaded driver. + @param PeiServices Pointer to the PEI services. + + @return Status returned by entry points of Peims. + +**/ +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ); + + +/** + Call constructs for all libraries. Automatics Generated by tool. + + @param FfsHeader Pointer to FFS header the loaded driver. + @param PeiServices Pointer to the PEI services. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ); + + +/** + Call destructors for all libraries. Automatics Generated by tool. + + @param FfsHeader Pointer to FFS header the loaded driver. + @param PeiServices Pointer to the PEI services. + +**/ +VOID +EFIAPI +ProcessLibraryDestructorList ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ); + + +/** + Call the list of driver entry points. Automatics Generated by tool. + + @param FfsHeader Pointer to FFS header the loaded driver. + @param PeiServices Pointer to the PEI services. + + @return Status returned by entry points of drivers. + +**/ +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ); + +#endif diff --git a/MdePkg/Include/Library/PerformanceLib.h b/MdePkg/Include/Library/PerformanceLib.h new file mode 100644 index 0000000000..36564095e9 --- /dev/null +++ b/MdePkg/Include/Library/PerformanceLib.h @@ -0,0 +1,201 @@ +/** @file + Library that provides services to measure module execution performance + + Copyright (c) 2004, 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. + + Module Name: PerformanceLib.h + +**/ + +#ifndef __PERFORMANCE_LIB_H__ +#define __PERFORMANCE_LIB_H__ + +// +// Performance library propery mask bits +// +#define PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED 0x00000001 + +/** + Creates a record for the beginning of a performance measurement. + + Creates a record that contains the Handle, Token, and Module. + If TimeStamp is not zero, then TimeStamp is added to the record as the start time. + If TimeStamp is zero, then this function reads the current time stamp + and adds that time stamp value to the record as the start time. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The start of the measurement was recorded. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement. + +**/ +RETURN_STATUS +EFIAPI +StartPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ); + +/** + Fills in the end time of a performance measurement. + + Looks up the record that matches Handle, Token, and Module. + If the record can not be found then return RETURN_NOT_FOUND. + If the record is found and TimeStamp is not zero, + then TimeStamp is added to the record as the end time. + If the record is found and TimeStamp is zero, then this function reads + the current time stamp and adds that time stamp value to the record as the end time. + If this function is called multiple times for the same record, then the end time is overwritten. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The end of the measurement was recorded. + @retval RETURN_NOT_FOUND The specified measurement record could not be found. + +**/ +RETURN_STATUS +EFIAPI +EndPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, OPTIONAL + IN CONST CHAR8 *Module, OPTIONAL + IN UINT64 TimeStamp + ); + +/** + Retrieves a previously logged performance measurement. + + Looks up the record that matches Handle, Token, and Module. + If the record can not be found then return RETURN_NOT_FOUND. + If the record is found then the start of the measurement is returned in StartTimeStamp, + and the end of the measurement is returned in EndTimeStamp. + + @param LogEntryKey The key for the previous performance measurement log entry. + If 0, then the first performance measurement log entry is retrieved. + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param StartTimeStamp The 64-bit time stamp that was recorded when the measurement was started. + @param EndTimeStamp The 64-bit time stamp that was recorded when the measurement was ended. + + @return The key for the current performance log entry. + +**/ +UINTN +EFIAPI +GetPerformanceMeasurement ( + UINTN LogEntryKey, + OUT CONST VOID **Handle, + OUT CONST CHAR8 **Token, + OUT CONST CHAR8 **Module, + OUT UINT64 *StartTimeStamp, + OUT UINT64 *EndTimeStamp + ); + +/** + Returns TRUE if the performance measurement macros are enabled. + + This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. + @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is clear. + +**/ +BOOLEAN +EFIAPI +PerformanceMeasurementEnabled ( + VOID + ); + +/** + Macro that calls EndPerformanceMeasurement(). + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then EndPerformanceMeasurement() is called. + +**/ +#define PERF_END(Handle, Token, Module, TimeStamp) \ + do { \ + if (PerformanceMeasurementEnabled ()) { \ + EndPerformanceMeasurement (Handle, Token, Module, TimeStamp); \ + } \ + } while (FALSE) + +/** + Macro that calls StartPerformanceMeasurement(). + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then StartPerformanceMeasurement() is called. + +**/ +#define PERF_START(Handle, Token, Module, TimeStamp) \ + do { \ + if (PerformanceMeasurementEnabled ()) { \ + StartPerformanceMeasurement (Handle, Token, Module, TimeStamp); \ + } \ + } while (FALSE) + +/** + Macro that marks the beginning of performance measurement source code. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then this macro marks the beginning of source code that is included in a module. + Otherwise, the source lines between PERF_CODE_BEGIN() and PERF_CODE_END() are not included in a module. + +**/ +#define PERF_CODE_BEGIN() do { if (PerformanceMeasurementEnabled ()) { UINT8 __PerformanceCodeLocal + +/** + Macro that marks the end of performance measurement source code. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then this macro marks the end of source code that is included in a module. + Otherwise, the source lines between PERF_CODE_BEGIN() and PERF_CODE_END() are not included in a module. + +**/ +#define PERF_CODE_END() __PerformanceCodeLocal = 0; } } while (FALSE) + +/** + Macro that declares a section of performance measurement source code. + + If the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of PcdPerformanceLibraryPropertyMask is set, + then the source code specified by Expression is included in a module. + Otherwise, the source specified by Expression is not included in a module. + + @param Expression Performance measurement source code to include in a module. + +**/ +#define PERF_CODE(Expression) \ + PERF_CODE_BEGIN (); \ + Expression \ + PERF_CODE_END () + + +#endif diff --git a/MdePkg/Include/Library/PrintLib.h b/MdePkg/Include/Library/PrintLib.h new file mode 100644 index 0000000000..c84b7c36aa --- /dev/null +++ b/MdePkg/Include/Library/PrintLib.h @@ -0,0 +1,116 @@ +/** @file + Library that provides print services + + Copyright (c) 2006, 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. + + Module Name: PrintLib.h + +**/ + +#ifndef __PRINT_LIB_H__ +#define __PRINT_LIB_H__ + +// +// Print primitives +// +#define LEFT_JUSTIFY 0x01 +#define COMMA_TYPE 0x08 +#define PREFIX_ZERO 0x20 + +UINTN +EFIAPI +UnicodeVSPrint ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + IN VA_LIST Marker + ); + +UINTN +EFIAPI +UnicodeSPrint ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + ... + ); + +UINTN +EFIAPI +UnicodeVSPrintAsciiFormat ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + IN VA_LIST Marker + ); + + +UINTN +EFIAPI +UnicodeSPrintAsciiFormat ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + ... + ); + +UINTN +EFIAPI +AsciiVSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + IN VA_LIST Marker + ); + +UINTN +EFIAPI +AsciiSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + ... + ); + +UINTN +EFIAPI +AsciiVSPrintUnicodeFormat ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + IN VA_LIST Marker + ); + +UINTN +EFIAPI +AsciiSPrintUnicodeFormat ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + ... + ); + +UINTN +UnicodeValueToString ( + IN OUT CHAR16 *Buffer, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width + ); + +UINTN +AsciiValueToString ( + IN OUT CHAR8 *Buffer, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width + ); + +#endif diff --git a/MdePkg/Include/Library/ReportStatusCodeLib.h b/MdePkg/Include/Library/ReportStatusCodeLib.h new file mode 100644 index 0000000000..b05bcc6593 --- /dev/null +++ b/MdePkg/Include/Library/ReportStatusCodeLib.h @@ -0,0 +1,763 @@ +/** @file + Report Status Code Library public .h file + + Copyright (c) 2006, 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 __REPORT_STATUS_CODE_LIB_H__ +#define __REPORT_STATUS_CODE_LIB_H__ + +// +// Declare bits for PcdReportStatusCodePropertyMask +// +#define REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED 0x00000001 +#define REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED 0x00000002 +#define REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED 0x00000004 +#define REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED 0x00000008 +#define REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED 0x00000010 + +// +// Extended Data structure definitions with EFI_STATUS_CODE_DATA headers removed +// + +/// +/// Voltage Extended Error Data +/// +typedef struct { + EFI_EXP_BASE10_DATA Voltage; + EFI_EXP_BASE10_DATA Threshold; +} REPORT_STATUS_CODE_LIBRARY_COMPUTING_UNIT_VOLTAGE_ERROR_DATA; + +/// +/// Microcode Update Extended Error Data +/// +typedef struct { + UINT32 Version; +} REPORT_STATUS_CODE_LIBRARY_COMPUTING_UNIT_MICROCODE_UPDATE_ERROR_DATA; + +/// +/// Asynchronous Timer Extended Error Data +/// +typedef struct { + EFI_EXP_BASE10_DATA TimerLimit; +} REPORT_STATUS_CODE_LIBRARY_COMPUTING_UNIT_TIMER_EXPIRED_ERROR_DATA; + +/// +/// Host Processor Mismatch Extended Error Data +/// +typedef struct { + UINT32 Instance; + UINT16 Attributes; +} REPORT_STATUS_CODE_LIBRARY_HOST_PROCESSOR_MISMATCH_ERROR_DATA; + +/// +/// Thermal Extended Error Data +/// +typedef struct { + EFI_EXP_BASE10_DATA Temperature; + EFI_EXP_BASE10_DATA Threshold; +} REPORT_STATUS_CODE_LIBRARY_COMPUTING_UNIT_THERMAL_ERROR_DATA; + +/// +/// Processor Disabled Extended Error Data +/// +typedef struct { + UINT32 Cause; + BOOLEAN SoftwareDisabled; +} REPORT_STATUS_CODE_LIBRARY_COMPUTING_UNIT_CPU_DISABLED_ERROR_DATA; + +/// +/// Embedded cache init extended data +/// +typedef struct { + UINT32 Level; + EFI_INIT_CACHE_TYPE Type; +} REPORT_STATUS_CODE_LIBRARY_CACHE_INIT_DATA; + +/// +/// Memory Extended Error Data +/// +typedef struct { + EFI_MEMORY_ERROR_GRANULARITY Granularity; + EFI_MEMORY_ERROR_OPERATION Operation; + UINTN Syndrome; + EFI_PHYSICAL_ADDRESS Address; + UINTN Resolution; +} REPORT_STATUS_CODE_LIBRARY_MEMORY_EXTENDED_ERROR_DATA; + +/// +/// DIMM number +/// +typedef struct { + UINT16 Array; + UINT16 Device; +} REPORT_STATUS_CODE_LIBRARY_STATUS_CODE_DIMM_NUMBER; + +/// +/// Memory Module Mismatch Extended Error Data +/// +typedef struct { + EFI_STATUS_CODE_DIMM_NUMBER Instance; +} REPORT_STATUS_CODE_LIBRARY_MEMORY_MODULE_MISMATCH_ERROR_DATA; + +/// +/// Memory Range Extended Data +/// +typedef struct { + EFI_PHYSICAL_ADDRESS Start; + EFI_PHYSICAL_ADDRESS Length; +} REPORT_STATUS_CODE_LIBRARY_MEMORY_RANGE_EXTENDED_DATA; + +/// +/// Device handle Extended Data. Used for many +/// errors and progress codes to point to the device. +/// +typedef struct { + EFI_HANDLE Handle; +} REPORT_STATUS_CODE_LIBRARY_DEVICE_HANDLE_EXTENDED_DATA; + +typedef struct { + UINT8 *DevicePath; +} REPORT_STATUS_CODE_LIBRARY_DEVICE_PATH_EXTENDED_DATA; + +typedef struct { + EFI_HANDLE ControllerHandle; + EFI_HANDLE DriverBindingHandle; + UINT16 DevicePathSize; + UINT8 *RemainingDevicePath; +} REPORT_STATUS_CODE_LIBRARY_STATUS_CODE_START_EXTENDED_DATA; + +/// +/// Resource Allocation Failure Extended Error Data +/// +typedef struct { + UINT32 Bar; + UINT16 DevicePathSize; + UINT16 ReqResSize; + UINT16 AllocResSize; + UINT8 *DevicePath; + UINT8 *ReqRes; + UINT8 *AllocRes; +} REPORT_STATUS_CODE_LIBRARY_RESOURCE_ALLOC_FAILURE_ERROR_DATA; + +/// +/// Extended Error Data for Assert +/// +typedef struct { + UINT32 LineNumber; + UINT32 FileNameSize; + EFI_STATUS_CODE_STRING_DATA *FileName; +} REPORT_STATUS_CODE_LIBRARY_DEBUG_ASSERT_DATA; + +/// +/// System Context Data EBC/IA32/IPF +/// +typedef struct { + EFI_STATUS_CODE_EXCEP_SYSTEM_CONTEXT Context; +} REPORT_STATUS_CODE_LIBRARY_STATUS_CODE_EXCEP_EXTENDED_DATA; + +/// +/// Legacy Oprom extended data +/// +typedef struct { + EFI_HANDLE DeviceHandle; + EFI_PHYSICAL_ADDRESS RomImageBase; +} REPORT_STATUS_CODE_LIBRARY_LEGACY_OPROM_EXTENDED_DATA; + +// +// Extern for the modules Caller ID GUID +// +extern EFI_GUID gEfiCallerIdGuid; + +/** + Converts a status code to an 8-bit POST code value. + + Converts the status code specified by CodeType and Value to an 8-bit POST code + and returns the 8-bit POST code in PostCode. If CodeType is an + EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode + are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits + 24..26 of Value., and TRUE is returned. Otherwise, FALSE is returned. + + If PostCode is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param PostCode A pointer to the 8-bit POST code value to return. + + @retval TRUE The status code specified by CodeType and Value was converted + to an 8-bit POST code and returned in PostCode. + @retval FALSE The status code specified by CodeType and Value could not be + converted to an 8-bit POST code value. + +**/ +BOOLEAN +EFIAPI +CodeTypeToPostCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + OUT UINT8 *PostCode + ); + + +/** + Extracts ASSERT() information from a status code structure. + + Converts the status code specified by CodeType, Value, and Data to the ASSERT() + arguments specified by Filename, Description, and LineNumber. If CodeType is + an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and + Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract + Filename, Description, and LineNumber from the optional data area of the + status code buffer specified by Data. The optional data area of Data contains + a Null-terminated ASCII string for the FileName, followed by a Null-terminated + ASCII string for the Description, followed by a 32-bit LineNumber. If the + ASSERT() information could be extracted from Data, then return TRUE. + Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If Filename is NULL, then ASSERT(). + If Description is NULL, then ASSERT(). + If LineNumber is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param Data Pointer to status code data buffer. + @param Filename Pointer to the source file name that generated the ASSERT(). + @param Description Pointer to the description of the ASSERT(). + @param LineNumber Pointer to source line number that generated the ASSERT(). + + @retval TRUE The status code specified by CodeType, Value, and Data was + converted ASSERT() arguments specified by Filename, Description, + and LineNumber. + @retval FALSE The status code specified by CodeType, Value, and Data could + not be converted to ASSERT() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractAssertInfo ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_STATUS_CODE_DATA *Data, + OUT CHAR8 **Filename, + OUT CHAR8 **Description, + OUT UINT32 *LineNumber + ); + + +/** + Extracts DEBUG() information from a status code structure. + + Converts the status code specified by Data to the DEBUG() arguments specified + by ErrorLevel, Marker, and Format. If type GUID in Data is + EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and + Format from the optional data area of the status code buffer specified by Data. + The optional data area of Data contains a 32-bit ErrorLevel followed by Marker + which is 12 UINTN parameters, followed by a Null-terminated ASCII string for + the Format. If the DEBUG() information could be extracted from Data, then + return TRUE. Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If ErrorLevel is NULL, then ASSERT(). + If Marker is NULL, then ASSERT(). + If Format is NULL, then ASSERT(). + + @param Data Pointer to status code data buffer. + @param ErrorLevel Pointer to error level mask for a debug message. + @param Marker Pointer to the variable argument list associated with Format. + @param Format Pointer to a Null-terminated ASCII format string of a + debug message. + + @retval TRUE The status code specified by Data was converted DEBUG() arguments + specified by ErrorLevel, Marker, and Format. + @retval FALSE The status code specified by Data could not be converted to + DEBUG() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractDebugInfo ( + IN EFI_STATUS_CODE_DATA *Data, + OUT UINT32 *ErrorLevel, + OUT VA_LIST *Marker, + OUT CHAR8 **Format + ); + + +/** + Reports a status code. + + Reports the status code specified by the parameters Type and Value. Status + code also require an instance, caller ID, and extended data. This function + passed in a zero instance, NULL extended data, and a caller ID of + gEfiCallerIdGuid, which is the GUID for the module. + + ReportStatusCode()must actively prevent recusrsion. If ReportStatusCode() + is called while processing another any other Report Status Code Library function, + then ReportStatusCode() must return immediately. + + @param Type Status code type. + @param Value Status code value. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_DEVICE_ERROR There status code could not be reported due to a + device error. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value + ); + + +/** + Reports a status code with a Device Path Protocol as the extended data. + + Allocates and fills in the extended data section of a status code with the + Device Path Protocol specified by DevicePath. This function is responsible + for allocating a buffer large enough for the standard header and the device + path. The standard header is filled in with a GUID of + gEfiStatusCodeSpecificDataGuid. The status code is reported with a zero + instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithDevicePath()must actively prevent recursion. If + ReportStatusCodeWithDevicePath() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithDevicePath() + must return EFI_DEVICE_ERROR immediately. + + If DevicePath is NULL, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param DevicePath Pointer to the Device Path Protocol to be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by DevicePath. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithDevicePath ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + + +/** + Reports a status code with an extended data buffer. + + Allocates and fills in the extended data section of a status code with the + extended data specified by ExtendedData and ExtendedDataSize. ExtendedData + is assumed to be one of the data structures specified in Related Definitions. + These data structure do not have the standard header, so this function is + responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled + in with a GUID of gEfiStatusCodeSpecificDataGuid. The status code is reported + with a zero instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithExtendedData()must actively prevent recursion. If + ReportStatusCodeWithExtendedData() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithExtendedData() + must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL, then ASSERT(). + If ExtendedDataSize is 0, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param ExtendedData Pointer to the extended data buffer to be reported. + @param ExtendedDataSize The size, in bytes, of the extended data buffer to + be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by ExtendedData and ExtendedDataSize. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithExtendedData ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN VOID *ExtendedData, + IN UINTN ExtendedDataSize + ); + + +/** + Reports a status code with full parameters. + + The function reports a status code. If ExtendedData is NULL and ExtendedDataSize + is 0, then an extended data buffer is not reported. If ExtendedData is not + NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. + ExtendedData is assumed not have the standard status code header, so this function + is responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled in + with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a + GUID of gEfiStatusCodeSpecificDatauid is used. The status code is reported with + an instance specified by Instance and a caller ID specified by CallerId. If + CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. + + ReportStatusCodeEx()must actively prevent recursion. If ReportStatusCodeEx() + is called while processing another any other Report Status Code Library function, + then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). + If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. If this parameter is NULL, then a caller + ID of gEfiCallerIdGuid is used. + @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. + If this parameter is NULL, then a the status code + standard header is filled in with + gEfiStatusCodeSpecificDataGuid. + @param ExtendedData Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + @param ExtendedDataSize The size, in bytes, of the extended data buffer. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate + the extended data section if it was specified. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeEx ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_GUID *ExtendedDataGuid OPTIONAL, + IN VOID *ExtendedData OPTIONAL, + IN UINTN ExtendedDataSize + ); + + +/** + Sends an 32-bit value to a POST card. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + Some implementations of this library function may perform I/O operations + directly to a POST card device. Other implementations may send Value to + ReportStatusCode(), and the status code reporting mechanism will eventually + display the 32-bit value on the status reporting device. + + PostCode() must actively prevent recursion. If PostCode() is called while + processing another any other Report Status Code Library function, then + PostCode() must return Value immediately. + + @param Value The 32-bit value to write to the POST card. + + @return Value + +**/ +UINT32 +EFIAPI +PostCode ( + IN UINT32 Value + ); + + +/** + Sends an 32-bit value to a POST and associated ASCII string. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + If Description is not NULL, then the ASCII string specified by Description is + also passed to the handler that displays the POST card value. Some + implementations of this library function may perform I/O operations directly + to a POST card device. Other implementations may send Value to ReportStatusCode(), + and the status code reporting mechanism will eventually display the 32-bit + value on the status reporting device. + + PostCodeWithDescription()must actively prevent recursion. If + PostCodeWithDescription() is called while processing another any other Report + Status Code Library function, then PostCodeWithDescription() must return Value + immediately. + + @param Value The 32-bit value to write to the POST card. + @param Description Pointer to an ASCII string that is a description of the + POST code value. This is an optional parameter that may + be NULL. + + @return Value + +**/ +UINT32 +EFIAPI +PostCodeWithDescription ( + IN UINT32 Value, + IN CONST CHAR8 *Description OPTIONAL + ); + + +/** + Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportProgressCodeEnabled ( + VOID + ); + + +/** + Returns TRUE if status codes of type EFI_ERROR_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportErrorCodeEnabled ( + VOID + ); + + +/** + Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportDebugCodeEnabled ( + VOID + ); + + +/** + Returns TRUE if POST Codes are enabled. + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportPostCodeEnabled ( + VOID + ); + + +/** + Returns TRUE if POST code descriptions are enabled. + + This function returns TRUE if the + REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED bit of + PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED + bit of PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED + bit of PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportPostCodeDescriptionEnabled ( + VOID + ); + + +/** + Reports a status code with minimal parameters if the status code type is enabled. + + If the status code type specified by Type is enabled in + PcdReportStatusCodeProperyMask, then call ReportStatusCode() passing in Type + and Value. + + @param Type Status code type. + @param Value Status code value. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_DEVICE_ERROR There status code could not be reported due to a device error. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +#define REPORT_STATUS_CODE(Type,Value) \ + (ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ? \ + ReportStatusCode(Type,Value) : \ + (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ? \ + ReportStatusCode(Type,Value) : \ + (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) ? \ + ReportStatusCode(Type,Value) : \ + EFI_UNSUPPORTED + + +/** + Reports a status code with a Device Path Protocol as the extended data if the + status code type is enabled. + + If the status code type specified by Type is enabled in + PcdReportStatusCodeProperyMask, then call ReportStatusCodeWithDevicePath() + passing in Type, Value, and DevicePath. + + @param Type Status code type. + @param Value Status code value. + @param DevicePath Pointer to the Device Path Protocol to be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by DevicePath. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +#define REPORT_STATUS_CODE_WITH_DEVICE_PATH(Type,Value,DevicePathParameter) \ + (ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ? \ + ReportStatusCodeWithDevicePath(Type,Value,DevicePathParameter) : \ + (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ? \ + ReportStatusCodeWithDevicePath(Type,Value,DevicePathParameter) : \ + (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) ? \ + ReportStatusCodeWithDevicePath(Type,Value,DevicePathParameter) : \ + EFI_UNSUPPORTED + + +/** + Reports a status code with an extended data buffer if the status code type + is enabled. + + If the status code type specified by Type is enabled in + PcdReportStatusCodeProperyMask, then call ReportStatusCodeWithExtendedData() + passing in Type, Value, ExtendedData, and ExtendedDataSize. + + @param Type Status code type. + @param Value Status code value. + @param ExtendedData Pointer to the extended data buffer to be reported. + @param ExtendedDataSize The size, in bytes, of the extended data buffer to + be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by ExtendedData and ExtendedDataSize. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +#define REPORT_STATUS_CODE_WITH_EXTENDED_DATA(Type,Value,ExtendedData,ExtendedDataSize) \ + (ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ? \ + ReportStatusCodeWithExtendedData(Type,Value,ExtendedData,ExtendedDataSize) : \ + (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ? \ + ReportStatusCodeWithExtendedData(Type,Value,ExtendedData,ExtendedDataSize) : \ + (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) ? \ + ReportStatusCodeWithExtendedData(Type,Value,ExtendedData,ExtendedDataSize) : \ + EFI_UNSUPPORTED + +/** + Reports a status code specifying all parameters if the status code type is enabled. + + If the status code type specified by Type is enabled in + PcdReportStatusCodeProperyMask, then call ReportStatusCodeEx() passing in Type, + Value, Instance, CallerId, ExtendedDataGuid, ExtendedData, and ExtendedDataSize. + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. If this parameter is NULL, then a caller + ID of gEfiCallerIdGuid is used. + @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. + If this parameter is NULL, then a the status code + standard header is filled in with + gEfiStatusCodeSpecificDataGuid. + @param ExtendedData Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + @param ExtendedDataSize The size, in bytes, of the extended data buffer. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section if it was specified. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +#define REPORT_STATUS_CODE_EX(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize) \ + (ReportProgressCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) ? \ + ReportStatusCodeEx(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize) : \ + (ReportErrorCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ? \ + ReportStatusCodeEx(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize) : \ + (ReportDebugCodeEnabled() && ((Type) & EFI_STATUS_CODE_TYPE_MASK) == EFI_DEBUG_CODE) ? \ + ReportStatusCodeEx(Type,Value,Instance,CallerId,ExtendedDataGuid,ExtendedData,ExtendedDataSize) : \ + EFI_UNSUPPORTED + +/** + Sends an 32-bit value to a POST card. + + If POST codes are enabled in PcdReportStatusCodeProperyMask, then call PostCode() + passing in Value. Value is returned. + + @param Value The 32-bit value to write to the POST card. + + @return Value + +**/ +#define POST_CODE(Value) ReportPostCodeEnabled() ? PostCode(Value) : Value + +/** + Sends an 32-bit value to a POST and associated ASCII string. + + If POST codes and POST code descriptions are enabled in + PcdReportStatusCodeProperyMask, then call PostCodeWithDescription() passing in + Value and Description. If only POST codes are enabled, then call PostCode() + passing in Value. Value is returned. + + @param Value The 32-bit value to write to the POST card. + @param Description Pointer to an ASCII string that is a description of the + POST code value. + +**/ +#define POST_CODE_WITH_DESCRIPTION(Value,Description) \ + ReportPostCodeEnabled() ? \ + (ReportPostCodeDescriptionEnabled() ? \ + PostCodeWithDescription(Value,Description) : \ + PostCode(Value)) : \ + Value + +#endif diff --git a/MdePkg/Include/Library/ResourcePublicationLib.h b/MdePkg/Include/Library/ResourcePublicationLib.h new file mode 100644 index 0000000000..2aa0040bf7 --- /dev/null +++ b/MdePkg/Include/Library/ResourcePublicationLib.h @@ -0,0 +1,44 @@ +/** @file + Declare presence of resources in the platform + + Copyright (c) 2006, 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. + + Module Name: ResourcePublicationLib.h + +**/ + +#ifndef __RESOURCE_PUBLICATION_LIB__ +#define __RESOURCE_PUBLICATION_LIB__ + +/** + + Declares the presence of permanent system memory in the platform. + + Declares that the system memory buffer specified by MemoryBegin and MemoryLength + as permanent memory that may be used for general purpose use by software. + The amount of memory available to software may be less than MemoryLength + if published memory has alignment restrictions. + + @param MemoryBegin The start address of the memory being declared. + @param MemoryLength The number of bytes of memory being declared. + + @retval RETURN_SUCCESS The memory buffer was published. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources to publish the memory buffer + +**/ +RETURN_STATUS +EFIAPI +PublishSystemMemory ( + IN PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +; + +#endif diff --git a/MdePkg/Include/Library/SmbusLib.h b/MdePkg/Include/Library/SmbusLib.h new file mode 100644 index 0000000000..55aae1211e --- /dev/null +++ b/MdePkg/Include/Library/SmbusLib.h @@ -0,0 +1,474 @@ +/** @file + SMBUS Functions + + Copyright (c) 2006, 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. + + Module Name: SmbusLib.h + +**/ + +#ifndef __SMBUS_LIB__ +#define __SMBUS_LIB__ + +/** + Macro that converts SMBUS slave address, SMBUS command, SMBUS data length, + and PEC to a value that can be passed to the SMBUS Library functions. + + Computes an address that is compatible with the SMBUS Library functions. + The unused upper bits of SlaveAddress, Command, and Length are stripped + prior to the generation of the address. + + @param SlaveAddress SMBUS Slave Address. Range 0..127. + @param Command SMBUS Command. Range 0..255. + @param Length SMBUS Data Length. Range 0..32. + @param Pec TRUE if Packet Error Checking is enabled. Otherwise FALSE. + +**/ +#define SMBUS_LIB_ADDRESS(SlaveAddress,Command,Length,Pec) \ + ( ((Pec) ? MAX_BIT : 0) | \ + (((SlaveAddress) & 0x7f) << 1) | \ + (((Command) & 0xff) << 8) | \ + (((Length) & 0x1f) << 16) \ + ) + +/** + Executes an SMBUS quick read command. + + Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + +**/ +VOID +EFIAPI +SmBusQuickRead ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS quick write command. + + Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + +**/ +BOOLEAN +EFIAPI +SmBusQuickWrite ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS receive byte command. + + Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + The byte received from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte received from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReceiveByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS send byte command. + + Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress. + The byte specified by Value is sent. + Only the SMBUS slave address field of SmBusAddress is required. Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to send. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusSendByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS read data byte command. + + Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 8-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte read from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReadDataByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS write data byte command. + + Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress. + The 8-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusWriteDataByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS read data word command. + + Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte read from the SMBUS. + +**/ +UINT16 +EFIAPI +SmBusReadDataWord ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS write data word command. + + Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +SmBusWriteDataWord ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS process call command. + + Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value returned by the process call command is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The 16-bit value returned by the process call command. + +**/ +UINT16 +EFIAPI +SmBusProcessCall ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS read block command. + + Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Bytes are read from the SMBUS and stored in Buffer. + The number of bytes read is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller¡¯s responsibility to make sure Buffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is not zero, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes read. + +**/ +UINTN +EFIAPI +SmBusReadBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS write block command. + + Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from Buffer. + The number of bytes written is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusWriteBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Executes an SMBUS block process call command. + + Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from OutBuffer. Bytes are then read from the SMBUS into InBuffer. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller¡¯s responsibility to make sure InBuffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If OutBuffer is NULL, then ASSERT(). + If InBuffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param OutBuffer Pointer to the buffer of bytes to write to the SMBUS. + @param InBuffer Pointer to the buffer of bytes to read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusBlockProcessCall ( + IN UINTN SmBusAddress, + OUT VOID *OutBuffer, + OUT VOID *InBuffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +; + +/** + Enumerates the SMBUS and assigns slave addresses. + + Executes the SMBUS enumeration algorithm and assigns a valid address to all SMBUS slave devices. + The total number of SMBUS slave devices detected is returned. + The status of the executed command is returned. + If Slave Address in SmBusAddress is not zero, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +EFIAPI +SmBusArpAll ( + IN UINTN SmBusAddress + ) +; + +/** + Assigns an SMBUS slave addresses. + + Assigns the SMBUS device specified by Uuid the slave address specified by SmBusAddress. + The status of the executed command is returned. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Uuid Pointer to the UUID of the device to assign a slave address. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +EFIAPI +SmBusArpDevice ( + IN UINTN SmBusAddress, + IN CONST GUID *Uuid + ) +; + +/** + Retrieves the UUID associated with an SMBUS slave device. + + Retrieves the UUID associated with the slave address specified + by SmBusAddress and returns the UUID in Uuid. + The status of the executed command is returned. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If Uuid is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Uuid Pointer to the UUID retrieved from the SMBUS slave device. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +EFIAPI +SmBusGetUuid ( + IN UINTN SmBusAddress, + OUT GUID *Uuid + ) +; + +#endif diff --git a/MdePkg/Include/Library/TimerLib.h b/MdePkg/Include/Library/TimerLib.h new file mode 100644 index 0000000000..3d0f03eda0 --- /dev/null +++ b/MdePkg/Include/Library/TimerLib.h @@ -0,0 +1,100 @@ +/** @file + Timer Library Functions + + Copyright (c) 2006, 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. + + Module Name: TimerLib.h + +**/ + +#ifndef __TIMER_LIB__ +#define __TIMER_LIB__ + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return Return value depends on implementation. + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ); + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return Return value depends on implementation. + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ); + +/** + Retrieves the current value of a 64-bit free running performance counter. + + Retrieves the current value of a 64-bit free running performance counter. The + counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ); + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + IN UINT64 *StartValue, OPTIONAL + IN UINT64 *EndValue OPTIONAL + ); + +#endif diff --git a/MdePkg/Include/Library/UefiBootServicesTableLib.h b/MdePkg/Include/Library/UefiBootServicesTableLib.h new file mode 100644 index 0000000000..52b5e23692 --- /dev/null +++ b/MdePkg/Include/Library/UefiBootServicesTableLib.h @@ -0,0 +1,27 @@ +/** @file + Library that provides a global pointer to the UEFI Boot Services Tables + + Copyright (c) 2006, 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. + + Module Name: UefiBootServicesTableLib.h + +**/ + +#ifndef __UEFI_BOOT_SERVICES_TABLE_LIB_H__ +#define __UEFI_BOOT_SERVICES_TABLE_LIB_H__ + +// +// +// +extern EFI_HANDLE gImageHandle; +extern EFI_SYSTEM_TABLE *gST; +extern EFI_BOOT_SERVICES *gBS; + +#endif diff --git a/MdePkg/Include/Library/UefiDecompressLib.h b/MdePkg/Include/Library/UefiDecompressLib.h new file mode 100644 index 0000000000..d2a379310f --- /dev/null +++ b/MdePkg/Include/Library/UefiDecompressLib.h @@ -0,0 +1,37 @@ +/** @file + Return UEFI Decompress Protocol + + Copyright (c) 2006, 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. + + Module Name: UefiDecompressLib.h + +**/ + +#ifndef __UEFI_DECPOMPRESS_LIB_H__ +#define __UEFI_DECPOMPRESS_LIB_H__ + +RETURN_STATUS +EFIAPI +UefiDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +RETURN_STATUS +EFIAPI +UefiDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ); + +#endif diff --git a/MdePkg/Include/Library/UefiDriverEntryPoint.h b/MdePkg/Include/Library/UefiDriverEntryPoint.h new file mode 100644 index 0000000000..6269876738 --- /dev/null +++ b/MdePkg/Include/Library/UefiDriverEntryPoint.h @@ -0,0 +1,154 @@ +/** @file + Entry point to a DXE Boot Services Driver + +Copyright (c) 2006, 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 __MODULE_ENTRY_POINT_H__ +#define __MODULE_ENTRY_POINT_H__ + +// +// Declare the EFI/UEFI Specification Revision to which this driver is implemented +// +extern const UINT32 _gUefiDriverRevision; + +// +// Declare the number of entry points in the image. +// +extern const UINT8 _gDriverEntryPointCount; + +// +// Declare the number of unload handler in the image. +// +extern const UINT8 _gDriverUnloadImageCount; + +// +// Declare the arrary of Boot Sevice Exit Event callbacks . +// +extern const EFI_EVENT_NOTIFY _gDriverExitBootServicesEvent[]; + +// +// Declare the arrary of Virtual Address Change Event callbacks . +// +extern const EFI_EVENT_NOTIFY _gDriverSetVirtualAddressMapEvent[]; + +/** + Enrty point to DXE SMM Driver. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @retval EFI_SUCCESS One or more of the drivers returned a success code. + @retval !EFI_SUCESS The return status from the last driver entry point in the list. + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Enrty point wrapper of DXE Driver. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @retval EFI_SUCCESS One or more of the drivers returned a success code. + @retval !EFI_SUCESS The return status from the last driver entry point in the list. + +**/ +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Computes the cummulative return status for the driver entry point and perform + a long jump back into DriverEntryPoint(). + + @param Status Status returned by the driver that is exiting. + +**/ +VOID +EFIAPI +ExitDriver ( + IN EFI_STATUS Status + ); + + +/** + Call constructs for all libraries. Automatics Generated by tool. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + +**/ +VOID +EFIAPI +ProcessLibraryConstructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Call destructors for all libraries. Automatics Generated by tool. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + +**/ +VOID +EFIAPI +ProcessLibraryDestructorList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Call the list of driver entry points. Automatics Generated by tool. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @return Status returned by entry points of drivers. + +**/ + +EFI_STATUS +EFIAPI +ProcessModuleEntryPointList ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + + +/** + Call the unload handlers for all the modules. Automatics Generated by tool. + + @param ImageHandle ImageHandle of the loaded driver. + + @return Status returned by unload handlers of drivers. + +**/ +EFI_STATUS +EFIAPI +ProcessModuleUnloadList ( + IN EFI_HANDLE ImageHandle + ); + +#endif diff --git a/MdePkg/Include/Library/UefiDriverModelLib.h b/MdePkg/Include/Library/UefiDriverModelLib.h new file mode 100644 index 0000000000..b6532f15c3 --- /dev/null +++ b/MdePkg/Include/Library/UefiDriverModelLib.h @@ -0,0 +1,48 @@ +/** @file + UEFI Driver Model Library Services + + Copyright (c) 2006, 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. + + Module Name: UefiDriverModelLib.h + +**/ + +#ifndef __UEFI_DRIVER_MODEL_LIB_H__ +#define __UEFI_DRIVER_MODEL_LIB_H__ + +// +// Declare bitmask values for the protocols that are enabled +// +#define UEFI_DRIVER_MODEL_LIBRARY_COMPONENT_NAME_PROTOCOL_ENABLED 0x01 +#define UEFI_DRIVER_MODEL_LIBRARY_DRIVER_DIAGNOSTICS_PROTOCOL_ENABLED 0x02 +#define UEFI_DRIVER_MODEL_LIBRARY_DRIVER_CONFIGURATION_PROTOCOL_ENABLED 0x04 + +// +// +// +extern const UINT8 _gDriverModelProtocolBitmask; + +// +// +// +typedef struct { + const EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + const EFI_COMPONENT_NAME_PROTOCOL *ComponentName; + const EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration; + const EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics; +} EFI_DRIVER_MODEL_PROTOCOL_LIST; + +// +// +// +extern const UINTN _gDriverModelProtocolListEntries; +extern const EFI_DRIVER_MODEL_PROTOCOL_LIST _gDriverModelProtocolList[]; + +#endif diff --git a/MdePkg/Include/Library/UefiLib.h b/MdePkg/Include/Library/UefiLib.h new file mode 100644 index 0000000000..73b761f790 --- /dev/null +++ b/MdePkg/Include/Library/UefiLib.h @@ -0,0 +1,486 @@ +/** @file + MDE UEFI library functions and macros + + Copyright (c) 2006, 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 __UEFI_LIB_H__ +#define __UEFI_LIB_H__ + +// +// Unicode String Table +// +typedef struct { + CHAR8 *Language; + CHAR16 *UnicodeString; +} EFI_UNICODE_STRING_TABLE; + +// +// EFI Lock Status +// +typedef enum { + EfiLockUninitialized = 0, + EfiLockReleased = 1, + EfiLockAcquired = 2 +} EFI_LOCK_STATE; + +// +// EFI Lock +// +typedef struct { + EFI_TPL Tpl; + EFI_TPL OwnerTpl; + EFI_LOCK_STATE Lock; +} EFI_LOCK; + + +/** + This function searches the list of configuration tables stored in the EFI System + Table for a table with a GUID that matches TableGuid. If a match is found, + then a pointer to the configuration table is returned in Table, and EFI_SUCCESS + is returned. If a matching GUID is not found, then EFI_NOT_FOUND is returned. + + @param TableGuid Pointer to table's GUID type.. + @param Table Pointer to the table associated with TableGuid in the EFI System Table. + + @retval EFI_SUCCESS A configuration table matching TableGuid was found. + @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found. + +**/ +EFI_STATUS +EFIAPI +EfiGetSystemConfigurationTable ( + IN EFI_GUID *TableGuid, + OUT VOID **Table + ); + +/** + This function causes the notification function to be executed for every protocol + of type ProtocolGuid instance that exists in the system when this function is + invoked. In addition, every time a protocol of type ProtocolGuid instance is + installed or reinstalled, the notification function is also executed. + + @param ProtocolGuid Supplies GUID of the protocol upon whose installation the event is fired. + @param NotifyTpl Supplies the task priority level of the event notifications. + @param NotifyFunction Supplies the function to notify when the event is signaled. + @param NotifyContext The context parameter to pass to NotifyFunction. + @param Registration A pointer to a memory location to receive the registration value. + + @return The notification event that was created. + +**/ +EFI_EVENT +EFIAPI +EfiCreateProtocolNotifyEvent( + IN EFI_GUID *ProtocolGuid, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, OPTIONAL + OUT VOID *Registration + ); + +/** + This function creates an event using NotifyTpl, NoifyFunction, and NotifyContext. + This event is signaled with EfiNamedEventSignal(). This provide the ability for + one or more listeners on the same event named by the GUID specified by Name. + + @param Name Supplies GUID name of the event. + @param NotifyTpl Supplies the task priority level of the event notifications. + @param NotifyFunction Supplies the function to notify when the event is signaled. + @param NotifyContext The context parameter to pass to NotifyFunction. + @param Registration A pointer to a memory location to receive the registration value. + + @retval EFI_SUCCESS A named event was created. + @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event. + +**/ +EFI_STATUS +EFIAPI +EfiNamedEventListen ( + IN CONST EFI_GUID *Name, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN CONST VOID *NotifyContext, OPTIONAL + OUT VOID *Registration OPTIONAL + ); + +/** + This function signals the named event specified by Name. The named event must + have been created with EfiNamedEventListen(). + + @param Name Supplies GUID name of the event. + + @retval EFI_SUCCESS A named event was signaled. + @retval EFI_OUT_OF_RESOURCES There are not enough resource to signal the named event. + +**/ +EFI_STATUS +EFIAPI +EfiNamedEventSignal ( + IN CONST EFI_GUID *Name + ); + +/** + This function initializes a basic mutual exclusion lock to the released state + and returns the lock. Each lock provides mutual exclusion access at its task + priority level. Since there is no preemption or multiprocessor support in EFI, + acquiring the lock only consists of raising to the locks TPL. + + @param Lock A pointer to the lock data structure to initialize. + @param Priority EFI TPL associated with the lock. + + @return The lock. + +**/ +EFI_LOCK * +EFIAPI +EfiInitializeLock ( + IN OUT EFI_LOCK *Lock, + IN EFI_TPL Priority + ); + +/** + This macro initializes the contents of a basic mutual exclusion lock to the + released state. Each lock provides mutual exclusion access at its task + priority level. Since there is no preemption or multiprocessor support in EFI, + acquiring the lock only consists of raising to the locks TPL. + + @param Lock A pointer to the lock data structure to initialize. + @param Priority The task priority level of the lock. + + @return The lock. + +**/ +#define EFI_INITIALIZE_LOCK_VARIABLE(Priority) \ + {Priority, EFI_TPL_APPLICATION, EfiLockReleased } + + +/** + + Macro that calls DebugAssert() if an EFI_LOCK structure is not in the locked state. + + If the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set, + then this macro evaluates the EFI_LOCK structure specified by Lock. If Lock + is not in the locked state, then DebugAssert() is called passing in the source + filename, source line number, and Lock. + + If Lock is NULL, then ASSERT(). + + @param LockParameter A pointer to the lock to acquire. + +**/ +#define ASSERT_LOCKED(LockParameter) \ + do { \ + if (DebugAssertEnabled ()) { \ + ASSERT (LockParameter != NULL); \ + if ((LockParameter)->Lock != EfiLockAcquired) { \ + _ASSERT (LockParameter not locked); \ + } \ + } \ + } while (FALSE) + + +/** + This function raises the system¡¯s current task priority level to the task + priority level of the mutual exclusion lock. Then, it places the lock in the + acquired state. + + @param Priority The task priority level of the lock. + +**/ +VOID +EFIAPI +EfiAcquireLock ( + IN EFI_LOCK *Lock + ); + +/** + This function raises the system¡¯s current task priority level to the task + priority level of the mutual exclusion lock. Then, it attempts to place the + lock in the acquired state. + + @param Lock A pointer to the lock to acquire. + + @retval EFI_SUCCESS The lock was acquired. + @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned. + +**/ +EFI_STATUS +EFIAPI +EfiAcquireLockOrFail ( + IN EFI_LOCK *Lock + ); + +/** + This function transitions a mutual exclusion lock from the acquired state to + the released state, and restores the system¡¯s task priority level to its + previous level. + + @param Lock A pointer to the lock to release. + +**/ +VOID +EFIAPI +EfiReleaseLock ( + IN EFI_LOCK *Lock + ); + +/** + This function looks up a Unicode string in UnicodeStringTable. If Language is + a member of SupportedLanguages and a Unicode string is found in UnicodeStringTable + that matches the language code specified by Language, then it is returned in + UnicodeString. + + @param Language A pointer to the ISO 639-2 language code for the + Unicode string to look up and return. + @param SupportedLanguages A pointer to the set of ISO 639-2 language codes + that the Unicode string table supports. Language + must be a member of this set. + @param UnicodeStringTable A pointer to the table of Unicode strings. + @param UnicodeString A pointer to the Unicode string from UnicodeStringTable + that matches the language specified by Language. + + @retval EFI_SUCCESS The Unicode string that matches the language + specified by Language was found + in the table of Unicoide strings UnicodeStringTable, + and it was returned in UnicodeString. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is NULL. + @retval EFI_UNSUPPORTED SupportedLanguages is NULL. + @retval EFI_UNSUPPORTED UnicodeStringTable is NULL. + @retval EFI_UNSUPPORTED The language specified by Language is not a + member of SupportedLanguages. + @retval EFI_UNSUPPORTED The language specified by Language is not + supported by UnicodeStringTable. + +**/ +EFI_STATUS +EFIAPI +LookupUnicodeString ( + IN CONST CHAR8 *Language, + IN CONST CHAR8 *SupportedLanguages, + IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable, + OUT CHAR16 **UnicodeString + ); + +/** + This function adds a Unicode string to UnicodeStringTable. + If Language is a member of SupportedLanguages then UnicodeString is added to + UnicodeStringTable. New buffers are allocated for both Language and + UnicodeString. The contents of Language and UnicodeString are copied into + these new buffers. These buffers are automatically freed when + FreeUnicodeStringTable() is called. + + @param Language A pointer to the ISO 639-2 language code for the Unicode + string to add. + @param SupportedLanguages A pointer to the set of ISO 639-2 language codes + that the Unicode string table supports. + Language must be a member of this set. + @param UnicodeStringTable A pointer to the table of Unicode strings. + @param UnicodeString A pointer to the Unicode string to add. + + @retval EFI_SUCCESS The Unicode string that matches the language + specified by Language was found in the table of + Unicode strings UnicodeStringTable, and it was + returned in UnicodeString. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is an empty string. + @retval EFI_UNSUPPORTED SupportedLanguages is NULL. + @retval EFI_ALREADY_STARTED A Unicode string with language Language is + already present in UnicodeStringTable. + @retval EFI_OUT_OF_RESOURCES There is not enough memory to add another + Unicode string to UnicodeStringTable. + @retval EFI_UNSUPPORTED The language specified by Language is not a + member of SupportedLanguages. + +**/ +EFI_STATUS +EFIAPI +AddUnicodeString ( + IN CONST CHAR8 *Language, + IN CONST CHAR8 *SupportedLanguages, + IN EFI_UNICODE_STRING_TABLE **UnicodeStringTable, + IN CONST CHAR16 *UnicodeString + ); + +/** + This function frees the table of Unicode strings in UnicodeStringTable. + If UnicodeStringTable is NULL, then EFI_SUCCESS is returned. + Otherwise, each language code, and each Unicode string in the Unicode string + table are freed, and EFI_SUCCESS is returned. + + @param UnicodeStringTable A pointer to the table of Unicode strings. + + @retval EFI_SUCCESS The Unicode string table was freed. + +**/ +EFI_STATUS +EFIAPI +FreeUnicodeStringTable ( + IN EFI_UNICODE_STRING_TABLE *UnicodeStringTable + ); + +/** + This function computes and returns the width of the Unicode character + specified by UnicodeChar. + + @param UnicodeChar A Unicode character. + + @retval 0 The width if UnicodeChar could not be determined. + @retval 1 UnicodeChar is a narrow glyph. + @retval 2 UnicodeChar is a wide glyph. + +**/ +UINTN +EFIAPI +GetGlyphWidth ( + IN CHAR16 UnicodeChar + ); + +/** + This function computes and returns the display length of + the Null-terminated Unicode string specified by String. + If String is NULL, then 0 is returned. + If any of the widths of the Unicode characters in String + can not be determined, then 0 is returned. + + @param String A pointer to a Null-terminated Unicode string. + + @return The display length of the Null-terminated Unicode string specified by String. + +**/ +UINTN +EFIAPI +UnicodeStringDisplayLength ( + IN CONST CHAR16 *String + ); + +// +// Functions that abstract early Framework contamination of UEFI. +// +/** + Signal a Ready to Boot Event. + + Create a Ready to Boot Event. Signal it and close it. This causes other + events of the same event group to be signaled in other modules. + +**/ +VOID +EFIAPI +EfiSignalEventReadyToBoot ( + VOID + ); + +/** + Signal a Legacy Boot Event. + + Create a legacy Boot Event. Signal it and close it. This causes other + events of the same event group to be signaled in other modules. + +**/ +VOID +EFIAPI +EfiSignalEventLegacyBoot ( + VOID + ); + +/** + Create a Legacy Boot Event. + + Tiano extended the CreateEvent Type enum to add a legacy boot event type. + This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was + added and now it's possible to not voilate the UEFI specification by + declaring a GUID for the legacy boot event class. This library supports + the R8.5/EFI 1.10 form and R9/UEFI 2.0 form and allows common code to + work both ways. + + @param LegacyBootEvent Returns the EFI event returned from gBS->CreateEvent(Ex). + + @retval EFI_SUCCESS Event was created. + @retval Other Event was not created. + +**/ +EFI_STATUS +EFIAPI +EfiCreateEventLegacyBoot ( + OUT EFI_EVENT *LegacyBootEvent + ); + +/** + Create a Read to Boot Event. + + Tiano extended the CreateEvent Type enum to add a ready to boot event type. + This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was + added and now it's possible to not voilate the UEFI specification and use + the ready to boot event class defined in UEFI 2.0. This library supports + the R8.5/EFI 1.10 form and R9/UEFI 2.0 form and allows common code to + work both ways. + + @param LegacyBootEvent Returns the EFI event returned from gBS->CreateEvent(Ex). + + @retval EFI_SUCCESS Event was created. + @retval Other Event was not created. + +**/ +EFI_STATUS +EFIAPI +EfiCreateEventReadyToBoot ( + OUT EFI_EVENT *ReadyToBootEvent + ); + +/** + Initialize a Firmware Volume (FV) Media Device Path node. + + Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum + so as we move to UEFI 2.0 support we must use a mechanism that conforms with + the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed + device path is defined for PIWG extensions of device path. If the code + is compiled to conform with the UEFI 2.0 specification use the new device path + else use the old form for backwards compatability. + + @param FvDevicePathNode Pointer to a FV device path node to initialize + @param NameGuid FV file name to use in FvDevicePathNode + +**/ +VOID +EFIAPI +EfiInitializeFwVolDevicepathNode ( + IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode, + IN EFI_GUID *NameGuid + ); + +/** + Check to see if the Firmware Volume (FV) Media Device Path is valid + + Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum + so as we move to UEFI 2.0 support we must use a mechanism that conforms with + the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed + device path is defined for PIWG extensions of device path. If the code + is compiled to conform with the UEFI 2.0 specification use the new device path + else use the old form for backwards compatability. The return value to this + function points to a location in FvDevicePathNode and it does not allocate + new memory for the GUID pointer that is returned. + + @param FvDevicePathNode Pointer to FV device path to check. + + @retval NULL FvDevicePathNode is not valid. + @retval Other FvDevicePathNode is valid and pointer to NameGuid was returned. + +**/ +EFI_GUID * +EFIAPI +EfiGetNameGuidFromFwVolDevicePathNode ( + IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode + ); + + +#endif diff --git a/MdePkg/Include/Library/UefiRuntimeServicesTableLib.h b/MdePkg/Include/Library/UefiRuntimeServicesTableLib.h new file mode 100644 index 0000000000..c59851e435 --- /dev/null +++ b/MdePkg/Include/Library/UefiRuntimeServicesTableLib.h @@ -0,0 +1,25 @@ +/** @file + Library that provides a global pointer to the UEFI Runtime Services Tables + + Copyright (c) 2006, 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. + + Module Name: UefiRuntimeServicesTableLib.h + +**/ + +#ifndef __UEFI_RUNTIME_SERVICES_TABLE_LIB_H__ +#define __UEFI_RUNTIME_SERVICES_TABLE_LIB_H__ + +// +// +// +extern EFI_RUNTIME_SERVICES *gRT; + +#endif diff --git a/MdePkg/Include/PeiCore.h b/MdePkg/Include/PeiCore.h new file mode 100644 index 0000000000..f0879c7c47 --- /dev/null +++ b/MdePkg/Include/PeiCore.h @@ -0,0 +1,48 @@ +/** @file + + Root include file for PEI Core. + + The PEI Core has its own module type since its entry point definition is + unique. This module type should only be used by the PEI core. The build + infrastructure automatically sets EDK_RELEASE_VERSION before including + this file. + +Copyright (c) 2006, 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 __PEI_CORE_H__ +#define __PEI_CORE_H__ + + +// +// Check to make sure EDK_RELEASE_VERSION is defined +// +#if !defined(EDK_RELEASE_VERSION) + #error EDK_RELEASE_VERSION not defined +#elif (EDK_RELEASE_VERSION == 0) + #error EDK_RELEASE_VERSION can not be zero +#endif + + + +#include +#include + +// +//StatusCodeDataTypeId needs DebugSupport Protocol definition +// +#include +#include +#include + +#include + +#endif diff --git a/MdePkg/Include/Peim.h b/MdePkg/Include/Peim.h new file mode 100644 index 0000000000..d2773cee4e --- /dev/null +++ b/MdePkg/Include/Peim.h @@ -0,0 +1,53 @@ +/** @file + + Root include file for PEI Modules using the Mde Package. + + PEI Modules follow the public Framwork specifications. This include + file supports all the public Framework specificaitons and if you + only want to support PIWG specifications you need to use PiwgPeim.h + The build infrastructure automatically sets EDK_RELEASE_VERSION + before including this file. + + +Copyright (c) 2006, 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 __PEIM_H__ +#define __PEIM_H__ + + +// +// Check to make sure EDK_RELEASE_VERSION is defined +// +#if !defined(EDK_RELEASE_VERSION) + #error EDK_RELEASE_VERSION not defined +#elif (EDK_RELEASE_VERSION == 0) + #error EDK_RELEASE_VERSION can not be zero +#endif + + +#include +#include + +#include + +// +//StatusCodeDataTypeId needs DebugSupport Protocol definition +// +#include +#include +#include + +#include +#include //This will be removed when PCD PEIM is completed! + +#endif diff --git a/MdePkg/Include/Peim/PeiCis.h b/MdePkg/Include/Peim/PeiCis.h new file mode 100644 index 0000000000..ecc128bda5 --- /dev/null +++ b/MdePkg/Include/Peim/PeiCis.h @@ -0,0 +1,670 @@ +/** @file + Framework PEI master include file. This file should match the PEI CIS spec. + + Copyright (c) 2006, 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. + + Module Name: PeiCis.h + + @par Revision Reference: + Version 0.91. + +**/ + +#ifndef __PEIM_CIS_H__ +#define __PEIM_CIS_H__ + +#include +#include +#include +#include +#include +#include +#include + +#define TIANO_ERROR(a) (MAX_2_BITS | (a)) + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) +// +// Tiano added a couple of return types. These are owned by UEFI specification +// and Tiano can not use them. Thus for UEFI 2.0/R9 support we moved the values +// to a UEFI OEM extension range to conform to UEFI specification. +// +#define EFI_NOT_AVAILABLE_YET EFIERR (28) +#define EFI_UNLOAD_IMAGE EFIERR (29) +#else +#define EFI_NOT_AVAILABLE_YET TIANO_ERROR (0) +#define EFI_UNLOAD_IMAGE TIANO_ERROR (1) +#endif + +// +// Declare forward referenced data structures +// +typedef struct _EFI_PEI_SERVICES EFI_PEI_SERVICES; +typedef struct _EFI_PEI_NOTIFY_DESCRIPTOR EFI_PEI_NOTIFY_DESCRIPTOR; + + +#include +#include + +// +// PEI Specification Revision information +// +#define PEI_SPECIFICATION_MAJOR_REVISION 0 +#define PEI_SPECIFICATION_MINOR_REVISION 91 + +/** + The PEI Dispatcher will invoke each PEIM one time. During this pass, the PEI + Dispatcher will pass control to the PEIM at the AddressOfEntryPoint in the PE Header. + + @param FfsHeader Pointer to the FFS file header. + + @param PeiServices Describes the list of possible PEI Services. + + @return Status code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEIM_ENTRY_POINT)( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + Entry point of the notification callback function itself within the PEIM. + + @param PeiServices Indirect reference to the PEI Services Table. + + @param NotifyDescriptor Address of the notification descriptor data structure. + + @param Ppi Address of the PPI that was installed. + + @return Status code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEIM_NOTIFY_ENTRY_POINT) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor, + IN VOID *Ppi + ); + +// +// PEI Ppi Services List Descriptors +// +#define EFI_PEI_PPI_DESCRIPTOR_PIC 0x00000001 +#define EFI_PEI_PPI_DESCRIPTOR_PPI 0x00000010 +#define EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK 0x00000020 +#define EFI_PEI_PPI_DESCRIPTOR_NOTIFY_DISPATCH 0x00000040 +#define EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES 0x00000060 +#define EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST 0x80000000 + +typedef struct { + UINTN Flags; + EFI_GUID *Guid; + VOID *Ppi; +} EFI_PEI_PPI_DESCRIPTOR; + +struct _EFI_PEI_NOTIFY_DESCRIPTOR { + UINTN Flags; + EFI_GUID *Guid; + EFI_PEIM_NOTIFY_ENTRY_POINT Notify; +}; + +/** + This service is the first one provided by the PEI Foundation. This function + installs an interface in the PEI PPI database by GUID. The purpose of the + service is to publish an interface that other parties can use to call + additional PEIMs. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table + published by the PEI Foundation. + + @param PpiList A pointer to the list of interfaces that the caller shall install. + + @retval EFI_SUCCESS The interface was successfully installed. + + @retval EFI_INVALID_PARAMETER The PpiList pointer is NULL or Any of the PEI PPI descriptors in the list do not have the EFI_PEI_PPI_DESCRIPTOR_PPI bit set in the Flags field. + + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_INSTALL_PPI) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *PpiList + ); + +/** + This function reinstalls an interface in the PEI PPI database by GUID. + The purpose of the service is to publish an interface that other parties + can use to replace a same-named interface in the protocol database + with a different interface. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table + published by the PEI Foundation. + + @param OldPpi A pointer to the former PPI in the database. + + @param NewPpi A pointer to the new interfaces that the caller shall install. + + @retval EFI_SUCCESS The interface was successfully installed. + + @retval EFI_INVALID_PARAMETER The PpiList pointer is NULL or Any of the PEI PPI descriptors in the list do not have the EFI_PEI_PPI_DESCRIPTOR_PPI bit set in the Flags field. + + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + + @retval EFI_NOT_FOUND The PPI for which the reinstallation was requested has not been installed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_REINSTALL_PPI) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN EFI_PEI_PPI_DESCRIPTOR *NewPpi + ); + +/** + This function locates an interface in the PEI PPI database by GUID. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES published by the PEI Foundation. + + @param Guid A pointer to the GUID whose corresponding interface needs to be found. + + @param Instance The N-th instance of the interface that is required. + + @param PpiDescriptor A pointer to instance of the EFI_PEI_PPI_DESCRIPTOR. + + @param Ppi A pointer to the instance of the interface. + + @retval EFI_SUCCESS The interface was successfully returned. + + @retval EFI_NOT_FOUND The PPI descriptor is not found in the database. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_LOCATE_PPI) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ); + +/** + This function installs a notification service to be called back when a + given interface is installed or reinstalled. The purpose of the service + is to publish an interface that other parties can use to call additional PPIs + that may materialize later. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + + @param NotifyList A pointer to the list of notification interfaces that the caller shall install. + + @retval EFI_SUCCESS The interface was successfully installed. + + @retval EFI_INVALID_PARAMETER The PpiList pointer is NULL or Any of the PEI PPI descriptors in the list do not have the EFI_PEI_PPI_DESCRIPTOR_PPI bit set in the Flags field. + + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_NOTIFY_PPI) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ); + +/** + This function returns the present value of the boot mode. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @param BootMode A pointer to contain the value of the boot mode. + + @retval EFI_SUCCESS The boot mode was returned successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_BOOT_MODE) ( + IN EFI_PEI_SERVICES **PeiServices, + OUT EFI_BOOT_MODE *BootMode + ); + +/** + This function sets the value of the boot mode. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + + @param BootMode The value of the boot mode to set. + + @retval EFI_SUCCESS The boot mode was returned successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SET_BOOT_MODE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_BOOT_MODE BootMode + ); + +/** + This function returns the pointer to the list of Hand-Off Blocks (HOBs) in memory. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation + + @param HobList A pointer to the list of HOBs that the PEI Foundation will initialize + + @retval EFI_SUCCESS The list was successfully returned. + + @retval EFI_NOT_AVAILABLE_YET The HOB list is not yet published. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_HOB_LIST) ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT VOID **HobList + ); + +/** + This service published by the PEI Foundation abstracts the creation of a Hand-Off Block's (HOB¡¯s) headers. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @param Type The type of HOB to be installed. + + @param Length The length of the HOB to be added. + + @param Hob The address of a pointer that will contain the HOB header. + + @retval EFI_SUCCESS The HOB was successfully created. + + @retval EFI_OUT_OF_RESOURCES There is no additional space for HOB creation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_CREATE_HOB) ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ); + +/** + The purpose of the service is to abstract the capability of the PEI + Foundation to discover instances of firmware volumes in the system. + Given the input file pointer, this service searches for the next + matching file in the Firmware File System (FFS) volume. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @param Instance This instance of the firmware volume to find. The value 0 is the Boot Firmware Volume (BFV). + + @param FwVolHeader Pointer to the firmware volume header of the volume to return. + + @retval EFI_SUCCESS The volume was found. + + @retval EFI_NOT_FOUND The volume was not found. + + @retval EFI_INVALID_PARAMETER FwVolHeader is NULL + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_FIND_NEXT_VOLUME) ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Instance, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ); + +/** + The purpose of the service is to abstract the capability of the PEI + Foundation to discover instances of firmware files in the system. + Given the input file pointer, this service searches for the next matching + file in the Firmware File System (FFS) volume. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @param SearchType A filter to find files only of this type. + + @param FwVolHeader Pointer to the firmware volume header of the volume to search.This parameter must point to a valid FFS volume. + + @param FileHeader Pointer to the current file from which to begin searching.This pointer will be updated upon return to reflect the file found. + + @retval EFI_SUCCESS The file was found. + + @retval EFI_NOT_FOUND The file was not found. + + @retval EFI_NOT_FOUND The header checksum was not zero. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_FIND_NEXT_FILE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ); + +/** + Given the input file pointer, this service searches for the next + matching file in the Firmware File System (FFS) volume. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @param SectionType The value of the section type to find. + + @param FfsFileHeader A pointer to the file header that contains the set of sections to be searched. + + @param SectionData A pointer to the discovered section, if successful. + + @retval EFI_SUCCESS The section was found. + + @retval EFI_NOT_FOUND The section was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FFS_FIND_SECTION_DATA) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ); + +/** + This function registers the found memory configuration with the PEI Foundation. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @param MemoryBegin The value of a region of installed memory + + @param MemoryLength The corresponding length of a region of installed memory. + + @retval EFI_SUCCESS The region was successfully installed in a HOB. + + @retval EFI_INVALID_PARAMETER MemoryBegin and MemoryLength are illegal for this system. + + @retval EFI_OUT_OF_RESOURCES There is no additional space for HOB creation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_INSTALL_PEI_MEMORY) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ); + +/** + The purpose of the service is to publish an interface that allows + PEIMs to allocate memory ranges that are managed by the PEI Foundation. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @param MemoryType The type of memory to allocate. + + @param Pages The number of contiguous 4 KB pages to allocate. + + @param Memory Pointer to a physical address. On output, the address is set to the base of the page range that was allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + + @retval EFI_INVALID_PARAMETER Type is not equal to AllocateAnyPages. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_ALLOCATE_PAGES) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + The purpose of this service is to publish an interface that + allows PEIMs to allocate memory ranges that are managed by the PEI Foundation. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @param Size The number of bytes to allocate from the pool. + + @param Buffer If the call succeeds, a pointer to a pointer to the allocated buffer; undefined otherwise. + + @retval EFI_SUCCESS The allocation was successful. + + @retval EFI_OUT_OF_RESOURCES There is not enough heap to allocate the requested size. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_ALLOCATE_POOL) ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + This service copies the contents of one buffer to another buffer. + + @param Destination Pointer to the destination buffer of the memory copy. + + @param Source Pointer to the source buffer of the memory copy + + @param Length Number of bytes to copy from Source to Destination. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_COPY_MEM) ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +/** + The service fills a buffer with a specified value. + + @param Buffer Pointer to the buffer to fill. + + @param Size Number of bytes in Buffer to fill. + + @param Value Value to fill Buffer with + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_SET_MEM) ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +/** + This service publishes an interface that allows PEIMs to report status codes. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES table published by the PEI Foundation. + + @param Type Indicates the type of status code being reported. + + @param Value Describes the current status of a hardware or + software entity. This includes information about the class and + subclass that is used to classify the entity as well as an operation. + For progress codes, the operation is the current activity. + For error codes, it is the exception.For debug codes,it is not defined at this time. + + @param Instance The enumeration of a hardware or software entity within + the system. A system may contain multiple entities that match a class/subclass + pairing. The instance differentiates between them. An instance of 0 indicates + that instance information is unavailable, not meaningful, or not relevant. + Valid instance numbers start with 1. + + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_NOT_AVAILABLE_YET No progress code provider has installed an interface in the system. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_REPORT_STATUS_CODE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/** + Resets the entire platform. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES + table published by the PEI Foundation. + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_NOT_AVAILABLE_YET The service has not been installed yet. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_RESET_SYSTEM) ( + IN EFI_PEI_SERVICES **PeiServices + ); + +// +// EFI PEI Services Table +// +#define PEI_SERVICES_SIGNATURE 0x5652455320494550ULL +#define PEI_SERVICES_REVISION ((PEI_SPECIFICATION_MAJOR_REVISION << 16) | (PEI_SPECIFICATION_MINOR_REVISION)) + +struct _EFI_PEI_SERVICES { + EFI_TABLE_HEADER Hdr; + + // + // PPI Functions + // + EFI_PEI_INSTALL_PPI InstallPpi; + EFI_PEI_REINSTALL_PPI ReInstallPpi; + EFI_PEI_LOCATE_PPI LocatePpi; + EFI_PEI_NOTIFY_PPI NotifyPpi; + + // + // Boot Mode Functions + // + EFI_PEI_GET_BOOT_MODE GetBootMode; + EFI_PEI_SET_BOOT_MODE SetBootMode; + + // + // HOB Functions + // + EFI_PEI_GET_HOB_LIST GetHobList; + EFI_PEI_CREATE_HOB CreateHob; + + // + // Filesystem Functions + // + EFI_PEI_FFS_FIND_NEXT_VOLUME FfsFindNextVolume; + EFI_PEI_FFS_FIND_NEXT_FILE FfsFindNextFile; + EFI_PEI_FFS_FIND_SECTION_DATA FfsFindSectionData; + + // + // Memory Functions + // + EFI_PEI_INSTALL_PEI_MEMORY InstallPeiMemory; + EFI_PEI_ALLOCATE_PAGES AllocatePages; + EFI_PEI_ALLOCATE_POOL AllocatePool; + EFI_PEI_COPY_MEM CopyMem; + EFI_PEI_SET_MEM SetMem; + + // + // Status Code + // + EFI_PEI_REPORT_STATUS_CODE PeiReportStatusCode; + + // + // Reset + // + EFI_PEI_RESET_SYSTEM PeiResetSystem; + + // + // Pointer to PPI interface + // + EFI_PEI_CPU_IO_PPI *CpuIo; + EFI_PEI_PCI_CFG_PPI *PciCfg; + +}; + +typedef struct { + UINTN BootFirmwareVolume; + UINTN SizeOfCacheAsRam; + EFI_PEI_PPI_DESCRIPTOR *DispatchTable; +} EFI_PEI_STARTUP_DESCRIPTOR; + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#endif diff --git a/MdePkg/Include/PeimDepex.h b/MdePkg/Include/PeimDepex.h new file mode 100644 index 0000000000..a392e505f8 --- /dev/null +++ b/MdePkg/Include/PeimDepex.h @@ -0,0 +1,54 @@ +/** @file + + Include file for PEI Dependency Expresion *.DXS file. + + This include file is only for Dependency Expression *.DXS files and + should not be include directly in modules. + + DEPEX (DEPendency EXpresion) BNF Grammer for PEI: + The BNF grammar is thus: +
+        ::=             
+         ::=  and  
+                 |  or   
+                 |             
+         ::= not       
+                 |           
+       ::=             
+                 |          
+                 |          
+                 |          
+      ::= true              
+                 | false             
+      ::= push GUID         
+      ::= end               
+
+ +Copyright (c) 2006, 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 __PEIM_DEPEX_H__ +#define __PEIM_DEPEX_H__ + +// +// The Depex grammer needs the following strings so we must undo +// any pre-processor redefinitions +// +#undef DEPENDENCY_START +#undef AND +#undef OR +#undef NOT +#undef TRUE +#undef FALSE +#undef DEPENDENCY_END + +#endif diff --git a/MdePkg/Include/PiwgDxe.h b/MdePkg/Include/PiwgDxe.h new file mode 100644 index 0000000000..a8310bca38 --- /dev/null +++ b/MdePkg/Include/PiwgDxe.h @@ -0,0 +1,26 @@ +/** @file + + Root include file for Mde Package PIWG DXE modules. + + This file is currently not implement since the PIWG has not yet released + an official specificaiton. In the future it will allow the construction + of a DXE module that strictly follows PIWG specifications. + +Copyright (c) 2006, 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 __PIWG_DXE_H__ +#define __PIWG_DXE_H__ + +#error No Approved PIWG specification exists + +#endif diff --git a/MdePkg/Include/PiwgPeim.h b/MdePkg/Include/PiwgPeim.h new file mode 100644 index 0000000000..aaa5f5a99d --- /dev/null +++ b/MdePkg/Include/PiwgPeim.h @@ -0,0 +1,25 @@ +/** @file + + Root include file for Mde Package PIWG PEIM modules. + + This file is currently not implement since the PIWG has not yet released + an official specificaiton. In the future it will allow the construction + of a PEIM module that strictly follows PIWG specifications. + +Copyright (c) 2006, 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 __PIWG_PEIM_H__ +#define __PIWG_PEIM_H__ + +#error No approved PIWG Specification exists + +#endif diff --git a/MdePkg/Include/Ppi/BlockIo.h b/MdePkg/Include/Ppi/BlockIo.h new file mode 100644 index 0000000000..debcc0c8e4 --- /dev/null +++ b/MdePkg/Include/Ppi/BlockIo.h @@ -0,0 +1,161 @@ +/** @file + This file declares BlockIo PPI used to access block-oriented storage devices + + Copyright (c) 2006, 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. + + Module Name: BlockIo.h + + @par Revision Reference: + This PPI is defined in Framework of EFI Recovery Spec + Version 0.9 + +**/ + +#ifndef _PEI_BLOCK_IO_H_ +#define _PEI_BLOCK_IO_H_ + +#define EFI_PEI_VIRTUAL_BLOCK_IO_PPI \ + { \ + 0x695d8aa1, 0x42ee, 0x4c46, {0x80, 0x5c, 0x6e, 0xa6, 0xbc, 0xe7, 0x99, 0xe3 } \ + } + +typedef struct _EFI_PEI_RECOVERY_BLOCK_IO_PPI EFI_PEI_RECOVERY_BLOCK_IO_PPI; + +typedef UINT64 EFI_PEI_LBA; + +typedef enum { + LegacyFloppy = 0, + IdeCDROM = 1, + IdeLS120 = 2, + UsbMassStorage= 3, + MaxDeviceType +} EFI_PEI_BLOCK_DEVICE_TYPE; + +typedef struct { + EFI_PEI_BLOCK_DEVICE_TYPE DeviceType; + BOOLEAN MediaPresent; + UINTN LastBlock; + UINTN BlockSize; +} EFI_PEI_BLOCK_IO_MEDIA; + +/** + Gets the count of block I/O devices that one specific block driver detects. + + @param PeiServices General-purpose services that are available to every PEIM. + + @param This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + + @param NumberBlockDevices The number of block I/O devices discovered. + + @return Status code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_NUMBER_BLOCK_DEVICES) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + OUT UINTN *NumberBlockDevices + ); + +/** + Gets a block device¡¯s media information. + + @param PeiServices General-purpose services that are available to every PEIM + + @param This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + + @param DeviceIndex Specifies the block device to which the function + wants to talk. Because the driver that implements Block I/O PPIs + will manage multiple block devices, the PPIs that want to talk to a single + device must specify the device index that was assigned during the enumeration + process. This index is a number from one to NumberBlockDevices. + + @param MediaInfo The media information of the specified block media. + + @retval EFI_SUCCESS Media information about the specified block device was obtained successfully. + + @retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_DEVICE_MEDIA_INFORMATION) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo + ); + +/** + Reads the requested number of blocks from the specified block device. + + @param PeiServices General-purpose services that are available to every PEIM. + + @param This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance. + + @param DeviceIndex Specifies the block device to which the function wants to talk. + + @param StartLBA The starting logical block address (LBA) to read from on the device + + @param BufferSize The size of the Buffer in bytes. This number must + be a multiple of the intrinsic block size of the device. + + @param Buffer A pointer to the destination buffer for the data. + The caller is responsible for the ownership of the buffer. + + @retval EFI_SUCCESS The data was read correctly from the device. + + @retval EFI_DEVICE_ERROR The device reported an error while attempting to perform the read operation. + + @retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid, + or the buffer is not properly aligned. + + @retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of + the intrinsic block size of the device. + + @retval EFI_NO_MEDIA There is no media in the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_READ_BLOCKS) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This, + IN UINTN DeviceIndex, + IN EFI_PEI_LBA StartLBA, + IN UINTN BufferSize, + OUT VOID *Buffer + ); + +/** + @par Ppi Description: + EFI_PEI_RECOVERY_BLOCK_IO_PPI provides the services that are required + to access a block I/O device during PEI recovery boot mode. + + @param GetNumberOfBlockDevices + Gets the number of block I/O devices that the specific block driver manages. + + @param GetBlockDeviceMediaInfo + Gets the specified media information. + + @param ReadBlocks + Reads the requested number of blocks from the specified block device. + +**/ +struct _EFI_PEI_RECOVERY_BLOCK_IO_PPI { + EFI_PEI_GET_NUMBER_BLOCK_DEVICES GetNumberOfBlockDevices; + EFI_PEI_GET_DEVICE_MEDIA_INFORMATION GetBlockDeviceMediaInfo; + EFI_PEI_READ_BLOCKS ReadBlocks; +}; + +extern EFI_GUID gEfiPeiBlockIoPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/BootInRecoveryMode.h b/MdePkg/Include/Ppi/BootInRecoveryMode.h new file mode 100644 index 0000000000..f15d570591 --- /dev/null +++ b/MdePkg/Include/Ppi/BootInRecoveryMode.h @@ -0,0 +1,33 @@ +/** @file + This PPI is installed by the platform PEIM to designate that a recovery boot + is in progress. + + Copyright (c) 2006, 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. + + Module Name: BootInRecoveryMode.h + + @par Revision Reference: + This PPI is defined in PEI CIS spec + Version 0.91. + +**/ + +#ifndef __BOOT_IN_RECOVERY_MODE_PPI_H__ +#define __BOOT_IN_RECOVERY_MODE_PPI_H__ + +#define EFI_PEI_BOOT_IN_RECOVERY_MODE_PEIM_PPI \ + { \ + 0x17ee496a, 0xd8e4, 0x4b9a, {0x94, 0xd1, 0xce, 0x82, 0x72, 0x30, 0x8, 0x50 } \ + } + + +extern EFI_GUID gEfiPeiBootInRecoveryModePpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/BootScriptExecuter.h b/MdePkg/Include/Ppi/BootScriptExecuter.h new file mode 100644 index 0000000000..b73396d7fa --- /dev/null +++ b/MdePkg/Include/Ppi/BootScriptExecuter.h @@ -0,0 +1,78 @@ +/** @file + This file declares Boot Script Executer PPI. + + Copyright (c) 2006, 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. + + Module Name: BootScriptExecuter.h + + @par Revision Reference: + This PPI is defined in Framework of EFI BootScript spec. + Version 0.91. + +**/ + +#ifndef _PEI_BOOT_SCRIPT_EXECUTER_PPI_H +#define _PEI_BOOT_SCRIPT_EXECUTER_PPI_H + +#define EFI_PEI_BOOT_SCRIPT_EXECUTER_PPI_GUID \ + { \ + 0xabd42895, 0x78cf, 0x4872, {0x84, 0x44, 0x1b, 0x5c, 0x18, 0x0b, 0xfb, 0xff } \ + } + +typedef struct _EFI_PEI_BOOT_SCRIPT_EXECUTER_PPI EFI_PEI_BOOT_SCRIPT_EXECUTER_PPI; + +/** + Executes the Framework boot script table. + + @param PeiServices A pointer to the system PEI Services Table. + + @param This A pointer to the EFI_PEI_BOOT_SCRIPT_EXECUTER_PPI instance. + + @param Address The physical memory address where the table is stored. + It must be zero if the table to be executed is stored in a firmware volume file. + + @param FvFile The firmware volume file name that contains the table to + be executed. It must be NULL if the table to be executed is stored in physical memory. + + @retval EFI_SUCCESS The boot script table was executed successfully. + + @retval EFI_INVALID_PARAMETER Address is zero and FvFile is NULL. + + @retval EFI_NOT_FOUND The file name specified in FvFile cannot be found. + + @retval EFI_UNSUPPORTED The format of the boot script table is invalid. + Or An unsupported opcode occurred in the table. + Or There were opcode execution errors, such as an insufficient dependency. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_BOOT_SCRIPT_EXECUTE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_BOOT_SCRIPT_EXECUTER_PPI *This, + IN EFI_PHYSICAL_ADDRESS Address, + IN EFI_GUID *FvFile OPTIONAL + ); + +/** + @par Ppi Description: + This PPI produces functions to interpret and execute the Framework boot script table. + + @param Execute + Executes a boot script table. + +**/ +struct _EFI_PEI_BOOT_SCRIPT_EXECUTER_PPI { + EFI_PEI_BOOT_SCRIPT_EXECUTE Execute; +}; + +extern EFI_GUID gEfiPeiBootScriptExecuterPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/CpuIo.h b/MdePkg/Include/Ppi/CpuIo.h new file mode 100644 index 0000000000..038703386d --- /dev/null +++ b/MdePkg/Include/Ppi/CpuIo.h @@ -0,0 +1,520 @@ +/** @file + This file declares CPU IO PPI that abstracts CPU IO access + + Copyright (c) 2006, 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. + + Module Name: CpuIo.h + + @par Revision Reference: + This PPI is defined in PEI CIS. + Version 0.91. + +**/ + +#ifndef __PEI_CPUIO_PPI_H__ +#define __PEI_CPUIO_PPI_H__ + +#define EFI_PEI_CPU_IO_PPI_INSTALLED_GUID \ + { \ + 0xe6af1f7b, 0xfc3f, 0x46da, {0xa8, 0x28, 0xa3, 0xb4, 0x57, 0xa4, 0x42, 0x82 } \ + } + +typedef struct _EFI_PEI_CPU_IO_PPI EFI_PEI_CPU_IO_PPI; + +// +// ******************************************************* +// EFI_PEI_CPU_IO_PPI_WIDTH +// ******************************************************* +// +typedef enum { + EfiPeiCpuIoWidthUint8, + EfiPeiCpuIoWidthUint16, + EfiPeiCpuIoWidthUint32, + EfiPeiCpuIoWidthUint64, + EfiPeiCpuIoWidthFifoUint8, + EfiPeiCpuIoWidthFifoUint16, + EfiPeiCpuIoWidthFifoUint32, + EfiPeiCpuIoWidthFifoUint64, + EfiPeiCpuIoWidthFillUint8, + EfiPeiCpuIoWidthFillUint16, + EfiPeiCpuIoWidthFillUint32, + EfiPeiCpuIoWidthFillUint64, + EfiPeiCpuIoWidthMaximum +} EFI_PEI_CPU_IO_PPI_WIDTH; + +/** + Memory-based access services and I/O-based access services. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Width The width of the access. Enumerated in bytes. + + @param Address The physical address of the access. + + @param Count The number of accesses to perform. + + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_MEM) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN EFI_PEI_CPU_IO_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +// +// ******************************************************* +// EFI_PEI_CPU_IO_PPI_ACCESS +// ******************************************************* +// +typedef struct { + EFI_PEI_CPU_IO_PPI_IO_MEM Read; + EFI_PEI_CPU_IO_PPI_IO_MEM Write; +} EFI_PEI_CPU_IO_PPI_ACCESS; + +/** + 8-bit I/O read operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @return UINT8 + +**/ +typedef +UINT8 +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_READ8) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 16-bit I/O read operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @return UINT16 + +**/ +typedef +UINT16 +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_READ16) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 32-bit I/O read operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @return UINT32 + +**/ +typedef +UINT32 +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_READ32) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 64-bit I/O read operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @return UINT64 + +**/ +typedef +UINT64 +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_READ64) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 8-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @param Data The data to write. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_WRITE8) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ); + +/** + 16-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @param Data The data to write. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_WRITE16) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ); + +/** + 32-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @param Data The data to write. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_WRITE32) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ); + +/** + 64-bit I/O write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @param Data The data to write. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_IO_WRITE64) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ); + +/** + 8-bit Memory read operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @return UINT8 + +**/ +typedef +UINT8 +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_READ8) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 16-bit Memory read operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @return UINT16 + +**/ +typedef +UINT16 +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_READ16) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 32-bit Memory read operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @return UINT32 + +**/ +typedef +UINT32 +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_READ32) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 64-bit Memory read operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @return UINT64 + +**/ +typedef +UINT64 +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_READ64) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address + ); + +/** + 8-bit Memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @param Data The data to write. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_WRITE8) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT8 Data + ); + +/** + 16-bit Memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @param Data The data to write. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_WRITE16) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT16 Data + ); + +/** + 32-bit Memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @param Data The data to write. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_WRITE32) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT32 Data + ); + +/** + 64-bit Memory write operations. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Address The physical address of the access. + + @param Data The data to write. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_PEI_CPU_IO_PPI_MEM_WRITE64) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_CPU_IO_PPI *This, + IN UINT64 Address, + IN UINT64 Data + ); + +/** + @par Ppi Description: + EFI_PEI_CPU_IO_PPI provides a set of memory and I/O-based services. + The perspective of the services is that of the processor, not the bus or system. + + @param Mem + Collection of memory-access services. + + @param I/O + Collection of I/O-access services. + + @param IoRead8 + 8-bit read service. + + @param IoRead16 + 16-bit read service. + + @param IoRead32 + 32-bit read service. + + @param IoRead64 + 64-bit read service. + + @param IoWrite8 + 8-bit write service. + + @param IoWrite16 + 16-bit write service. + + @param IoWrite32 + 32-bit write service. + + @param IoWrite64 + 64-bit write service. + + @param MemRead8 + 8-bit read service. + + @param MemRead16 + 16-bit read service. + + @param MemRead32 + 32-bit read service. + + @param MemRead64 + 64-bit read service. + + @param MemWrite8 + 8-bit write service. + + @param MemWrite16 + 16-bit write service. + + @param MemWrite32 + 32-bit write service. + + @param MemWrite64 + 64-bit write service. + +**/ +struct _EFI_PEI_CPU_IO_PPI { + EFI_PEI_CPU_IO_PPI_ACCESS Mem; + EFI_PEI_CPU_IO_PPI_ACCESS Io; + EFI_PEI_CPU_IO_PPI_IO_READ8 IoRead8; + EFI_PEI_CPU_IO_PPI_IO_READ16 IoRead16; + EFI_PEI_CPU_IO_PPI_IO_READ32 IoRead32; + EFI_PEI_CPU_IO_PPI_IO_READ64 IoRead64; + EFI_PEI_CPU_IO_PPI_IO_WRITE8 IoWrite8; + EFI_PEI_CPU_IO_PPI_IO_WRITE16 IoWrite16; + EFI_PEI_CPU_IO_PPI_IO_WRITE32 IoWrite32; + EFI_PEI_CPU_IO_PPI_IO_WRITE64 IoWrite64; + EFI_PEI_CPU_IO_PPI_MEM_READ8 MemRead8; + EFI_PEI_CPU_IO_PPI_MEM_READ16 MemRead16; + EFI_PEI_CPU_IO_PPI_MEM_READ32 MemRead32; + EFI_PEI_CPU_IO_PPI_MEM_READ64 MemRead64; + EFI_PEI_CPU_IO_PPI_MEM_WRITE8 MemWrite8; + EFI_PEI_CPU_IO_PPI_MEM_WRITE16 MemWrite16; + EFI_PEI_CPU_IO_PPI_MEM_WRITE32 MemWrite32; + EFI_PEI_CPU_IO_PPI_MEM_WRITE64 MemWrite64; +}; + +extern EFI_GUID gEfiPeiCpuIoPpiInServiceTableGuid; + +#endif diff --git a/MdePkg/Include/Ppi/DeviceRecoveryModule.h b/MdePkg/Include/Ppi/DeviceRecoveryModule.h new file mode 100644 index 0000000000..3847686b04 --- /dev/null +++ b/MdePkg/Include/Ppi/DeviceRecoveryModule.h @@ -0,0 +1,143 @@ +/** @file + This file declares Device Recovery Module PPI. + + Copyright (c) 2006, 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. + + Module Name: DeviceRecoveryModule.h + + @par Revision Reference: + This PPI is defined in Framework of EFI Recovery spec. + Version 0.9 + +**/ + +#ifndef _PEI_DEVICE_RECOVERY_MODULE_PPI_H +#define _PEI_DEVICE_RECOVERY_MODULE_PPI_H + +#define EFI_PEI_DEVICE_RECOVERY_MODULE_PPI_GUID \ + { \ + 0x0DE2CE25, 0x446A, 0x45a7, {0xBF, 0xC9, 0x37, 0xDA, 0x26, 0x34, 0x4B, 0x37 } \ + } + +typedef struct _EFI_PEI_DEVICE_RECOVERY_MODULE_PPI EFI_PEI_DEVICE_RECOVERY_MODULE_PPI; + +/** + This function, by whatever mechanism, searches for DXE capsules from the + associated device and returns the number and maximum size in bytes of + the capsules discovered. Entry 1 is assumed to be the highest load priority + and entry N is assumed to be the lowest priority. + + @param PeiServices General-purpose services that are available to every PEIM + + @param This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI instance. + + @param NumberRecoveryCapsules Pointer to a caller-allocated UINTN. On output, + *NumberRecoveryCapsules contains the number of recovery capsule images available + for retrieval from this PEIM instance. + + @retval EFI_SUCCESS One or more capsules were discovered. + + @retval EFI_DEVICE_ERROR A device error occurred. + + @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_DEVICE_GET_NUMBER_RECOVERY_CAPSULE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This, + OUT UINTN *NumberRecoveryCapsules + ); + +/** + This function gets the size and type of the requested recovery capsule. + + @param PeiServices General-purpose services that are available to every PEIM + + @param This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI instance. + + @param CapsuleInstance Specifies for which capsule instance to retrieve the information. + + @param Size A pointer to a caller-allocated UINTN in which the size of + the requested recovery module is returned. + + @param CapsuleType A pointer to a caller-allocated EFI_GUID in + which the type of the requested recovery capsule is returned. + + @retval EFI_SUCCESS One or more capsules were discovered. + + @retval EFI_DEVICE_ERROR A device error occurred. + + @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_DEVICE_GET_RECOVERY_CAPSULE_INFO) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This, + IN UINTN CapsuleInstance, + OUT UINTN *Size, + OUT EFI_GUID *CapsuleType + ); + +/** + This function, by whatever mechanism, retrieves a DXE capsule from some device + and loads it into memory. Note that the published interface is device neutral. + + @param PeiServices General-purpose services that are available to every PEIM + + @param This Indicates the EFI_PEI_DEVICE_RECOVERY_MODULE_PPI instance. + + @param CapsuleInstance Specifies which capsule instance to retrieve. + + @param Buffer Specifies a caller-allocated buffer in which the requested recovery capsule will be returned. + + @retval EFI_SUCCESS One or more capsules were discovered. + + @retval EFI_DEVICE_ERROR A device error occurred. + + @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_DEVICE_LOAD_RECOVERY_CAPSULE) ( + IN OUT EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_DEVICE_RECOVERY_MODULE_PPI *This, + IN UINTN CapsuleInstance, + OUT VOID *Buffer + ); + +/** + @par Ppi Description: + Presents a standard interface to EFI_PEI_DEVICE_RECOVERY_MODULE_PPI, + regardless of the underlying device(s). + + @param GetNumberRecoveryCapsules + Returns the number of DXE capsules that were found. + + @param GetRecoveryCapsuleInfo + Returns the capsule image type and the size of a given image. + + @param LoadRecoveryCapsule + Loads a DXE capsule into memory + +**/ +struct _EFI_PEI_DEVICE_RECOVERY_MODULE_PPI { + EFI_PEI_DEVICE_GET_NUMBER_RECOVERY_CAPSULE GetNumberRecoveryCapsules; + EFI_PEI_DEVICE_GET_RECOVERY_CAPSULE_INFO GetRecoveryCapsuleInfo; + EFI_PEI_DEVICE_LOAD_RECOVERY_CAPSULE LoadRecoveryCapsule; +}; + +extern EFI_GUID gEfiPeiDeviceRecoveryModulePpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/DxeIpl.h b/MdePkg/Include/Ppi/DxeIpl.h new file mode 100644 index 0000000000..bed579522c --- /dev/null +++ b/MdePkg/Include/Ppi/DxeIpl.h @@ -0,0 +1,70 @@ +/** @file + This file declares DXE Initial Program Load PPI. + When the PEI core is done it calls the DXE IPL via this PPI. + + Copyright (c) 2006, 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. + + Module Name: DxeIpl.h + + @par Revision Reference: + This PPI is defined in PEI CIS. + Version 0.91. + +**/ + +#ifndef __DXE_IPL_H__ +#define __DXE_IPL_H__ + +#define EFI_DXE_IPL_PPI_GUID \ + { \ + 0xae8ce5d, 0xe448, 0x4437, {0xa8, 0xd7, 0xeb, 0xf5, 0xf1, 0x94, 0xf7, 0x31 } \ + } + +typedef struct _EFI_DXE_IPL_PPI EFI_DXE_IPL_PPI; + +/** + The architectural PPI that the PEI Foundation invokes when + there are no additional PEIMs to invoke. + + @param This Pointer to the DXE IPL PPI instance + + @param PeiServices Pointer to the PEI Services Table. + + @param HobList Pointer to the list of Hand-Off Block (HOB) entries. + + @retval EFI_SUCCESS Upon this return code, the PEI Foundation should enter + some exception handling.Under normal circumstances, the DXE IPL PPI should not return. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DXE_IPL_ENTRY) ( + IN EFI_DXE_IPL_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_HOB_POINTERS HobList + ); + +/** + @par Ppi Description: + Final service to be invoked by the PEI Foundation. + The DXE IPL PPI is responsible for locating and loading the DXE Foundation. + The DXE IPL PPI may use PEI services to locate and load the DXE Foundation. + + @param Entry + The entry point to the DXE IPL PPI. + +**/ +struct _EFI_DXE_IPL_PPI { + EFI_DXE_IPL_ENTRY Entry; +}; + +extern EFI_GUID gEfiDxeIplPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/EndOfPeiPhase.h b/MdePkg/Include/Ppi/EndOfPeiPhase.h new file mode 100644 index 0000000000..e58fa03b09 --- /dev/null +++ b/MdePkg/Include/Ppi/EndOfPeiPhase.h @@ -0,0 +1,31 @@ +/** @file + PPI to be used to signal when the PEI ownership of the memory map + officially ends and DXE will take over + + Copyright (c) 2006, 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. + + Module Name: EndOfPeiSignal.h + + @par Revision Reference: + This PPI is defined in PEI CIS spec Version 0.91. + +**/ + +#ifndef __END_OF_PEI_SIGNAL_PPI_H__ +#define __END_OF_PEI_SIGNAL_PPI_H__ + +#define EFI_PEI_END_OF_PEI_PHASE_PPI_GUID \ + { \ + 0x605EA650, 0xC65C, 0x42e1, {0xBA, 0x80, 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 } \ + } + +extern EFI_GUID gEfiEndOfPeiSignalPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/FindFv.h b/MdePkg/Include/Ppi/FindFv.h new file mode 100644 index 0000000000..971512558b --- /dev/null +++ b/MdePkg/Include/Ppi/FindFv.h @@ -0,0 +1,76 @@ +/** @file + This file declares FindFv PPI used to locate FVs that contain PEIMs in PEI + + Copyright (c) 2006, 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. + + Module Name: FindFv.h + + @par Revision Reference: + This PPI is defined in PEI CIS + Version 0.91 + +**/ + +#ifndef __FIND_FV_H__ +#define __FIND_FV_H__ + +#define EFI_PEI_FIND_FV_PPI_GUID \ + { \ + 0x36164812, 0xa023, 0x44e5, {0xbd, 0x85, 0x5, 0xbf, 0x3c, 0x77, 0x0, 0xaa } \ + } + +typedef struct _EFI_PEI_FIND_FV_PPI EFI_PEI_FIND_FV_PPI; + +/** + This interface returns the base address of the firmware volume whose index + was passed in FvNumber.Once this function reports a firmware volume + index/base address pair, that index/address pairing must continue throughout PEI. + + @param PeiServices Pointer to the PEI Services Table. + + @param This Interface pointer that implements the Find FV service. + + @param FvNumber The index of the firmware volume to locate. + + @param FvAddress The address of the volume to discover. + + @retval EFI_SUCCESS An additional firmware volume was found. + + @retval EFI_OUT_OF_RESOURCES There are no firmware volumes for the given FvNumber. + + @retval EFI_INVALID_PARAMETER *FvAddress is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FIND_FV_FINDFV) ( + IN EFI_PEI_FIND_FV_PPI *This, + IN EFI_PEI_SERVICES **PeiServices, + UINT8 *FvNumber, + EFI_FIRMWARE_VOLUME_HEADER **FVAddress + ); + +/** + @par Ppi Description: + Hardware mechanisms for locating FVs in a platform vary widely. + EFI_PEI_FIND_FV_PPI serves to abstract this variation so that the + PEI Foundation can remain standard across a wide variety of platforms. + + @param FindFv + Service that abstracts the location of additional firmware volumes. + +**/ +struct _EFI_PEI_FIND_FV_PPI { + EFI_PEI_FIND_FV_FINDFV FindFv; +}; + +extern EFI_GUID gEfiFindFvPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/LoadFile.h b/MdePkg/Include/Ppi/LoadFile.h new file mode 100644 index 0000000000..af02be7c9e --- /dev/null +++ b/MdePkg/Include/Ppi/LoadFile.h @@ -0,0 +1,78 @@ +/** @file + Load image file from fv to memory. + + Copyright (c) 2006, 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. + + Module Name: LoadFile.h + + @par Revision Reference: + This PPI is defined in PEI CIS spec Version 0.91. + +**/ + +#ifndef __FV_FILE_LOADER_PPI_H__ +#define __FV_FILE_LOADER_PPI_H__ + +#define EFI_PEI_FV_FILE_LOADER_GUID \ + { \ + 0x7e1f0d85, 0x4ff, 0x4bb2, {0x86, 0x6a, 0x31, 0xa2, 0x99, 0x6a, 0x48, 0xa8 } \ + } + +typedef struct _EFI_PEI_FV_FILE_LOADER_PPI EFI_PEI_FV_FILE_LOADER_PPI; + +/** + Loads a PEIM into memory for subsequent execution. + + @param This Interface pointer that implements the Load File PPI instance. + + @param FfsHeader Pointer to the FFS header of the file to load. + + @param ImageAddress Pointer to the address of the loaded Image + + @param ImageSize Pointer to the size of the loaded image. + + @param EntryPoint Pointer to the entry point of the image. + + @retval EFI_SUCCESS The image was loaded successfully. + + @retval EFI_OUT_OF_RESOURCES There was not enough memory. + + @retval EFI_INVALID_PARAMETER The contents of the FFS file did not + contain a valid PE/COFF image that could be loaded. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_FV_LOAD_FILE) ( + IN EFI_PEI_FV_FILE_LOADER_PPI *This, + IN EFI_FFS_FILE_HEADER *FfsHeader, + OUT EFI_PHYSICAL_ADDRESS *ImageAddress, + OUT UINT64 *ImageSize, + OUT EFI_PHYSICAL_ADDRESS *EntryPoint + ); + +/** + @par Ppi Description: + This PPI is a pointer to the Load File service. This service will be + published by a PEIM.The PEI Foundation will use this service to + launch the known non-XIP PE/COFF PEIM images. This service may + depend upon the presence of the EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI. + + @param FvLoadFile + Loads a PEIM into memory for subsequent execution + +**/ +struct _EFI_PEI_FV_FILE_LOADER_PPI { + EFI_PEI_FV_LOAD_FILE FvLoadFile; +}; + +extern EFI_GUID gEfiPeiFvFileLoaderPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/MasterBootMode.h b/MdePkg/Include/Ppi/MasterBootMode.h new file mode 100644 index 0000000000..010055c7fd --- /dev/null +++ b/MdePkg/Include/Ppi/MasterBootMode.h @@ -0,0 +1,34 @@ +/** @file + This file declares Boot Mode PPI + The Master Boot Mode PPI is installed by a PEIM to signal that a final + boot has been determined and set. This signal is useful in that PEIMs + with boot-mode-specific behavior can put this PPI in their dependency expression. + + Copyright (c) 2006, 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. + + Module Name: MasterBootMode.h + + @par Revision Reference: + This PPI is defined in PEI CIS + Version 0.91. + +**/ + +#ifndef __MASTER_BOOT_MODE_PPI_H__ +#define __MASTER_BOOT_MODE_PPI_H__ + +#define EFI_PEI_MASTER_BOOT_MODE_PEIM_PPI \ + { \ + 0x7408d748, 0xfc8c, 0x4ee6, {0x92, 0x88, 0xc4, 0xbe, 0xc0, 0x92, 0xa4, 0x10 } \ + } + +extern EFI_GUID gEfiPeiMasterBootModePpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/MemoryDiscovered.h b/MdePkg/Include/Ppi/MemoryDiscovered.h new file mode 100644 index 0000000000..414926c265 --- /dev/null +++ b/MdePkg/Include/Ppi/MemoryDiscovered.h @@ -0,0 +1,34 @@ +/** @file + This file declares Memory Discovered PPI. + This PPI is installed by the PEI Foundation at the point of system + evolution when the permanent memory size has been registered and + waiting PEIMs can use the main memory store. + + Copyright (c) 2006, 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. + + Module Name: MemoryDiscovered.h + + @par Revision Reference: + This PPI is defined in PEI CIS + Version 0.91. + +**/ + +#ifndef __PEI_MEMORY_DISCOVERED_PPI_H__ +#define __PEI_MEMORY_DISCOVERED_PPI_H__ + +#define EFI_PEI_PERMANENT_MEMORY_INSTALLED_PPI_GUID \ + { \ + 0xf894643d, 0xc449, 0x42d1, {0x8e, 0xa8, 0x85, 0xbd, 0xd8, 0xc6, 0x5b, 0xde } \ + } + +extern EFI_GUID gEfiPeiMemoryDiscoveredPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/Pcd.h b/MdePkg/Include/Ppi/Pcd.h new file mode 100644 index 0000000000..2b968f0d80 --- /dev/null +++ b/MdePkg/Include/Ppi/Pcd.h @@ -0,0 +1,294 @@ +/** @file + Platform Configuration Database (PCD) Protocol + + Copyright (c) 2006, 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. + + Module Name: Pcd.h + +**/ + +#ifndef __PCD_H__ +#define __PCD_H__ + +extern EFI_GUID gPcdPpiGuid; + +#define PCD_PPI_GUID \ + { 0x632df884, 0x8023, 0x4872, { 0xb6, 0x70, 0xb7, 0x4a, 0x30, 0x19, 0x16, 0xe9 } } + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_SKU) ( + IN UINTN SkuId + ); + +typedef +UINT8 +(EFIAPI *PCD_PPI_GET8) ( + IN UINTN TokenNumber + ); + +typedef +UINT16 +(EFIAPI *PCD_PPI_GET16) ( + IN UINTN TokenNumber + ); + +typedef +UINT32 +(EFIAPI *PCD_PPI_GET32) ( + IN UINTN TokenNumber + ); + +typedef +UINT64 +(EFIAPI *PCD_PPI_GET64) ( + IN UINTN TokenNumber + ); + +typedef +VOID * +(EFIAPI *PCD_PPI_GET_POINTER) ( + IN UINTN TokenNumber + ); + +typedef +BOOLEAN +(EFIAPI *PCD_PPI_GET_BOOLEAN) ( + IN UINTN TokenNumber + ); + +typedef +UINTN +(EFIAPI *PCD_PPI_GET_SIZE) ( + IN UINTN TokenNumber + ); + +typedef +UINT8 +(EFIAPI *PCD_PPI_GET_EX_8) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +UINT16 +(EFIAPI *PCD_PPI_GET_EX_16) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +UINT32 +(EFIAPI *PCD_PPI_GET_EX_32) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +UINT64 +(EFIAPI *PCD_PPI_GET_EX_64) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +VOID * +(EFIAPI *PCD_PPI_GET_EX_POINTER) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +BOOLEAN +(EFIAPI *PCD_PPI_GET_EX_BOOLEAN) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +UINTN +(EFIAPI *PCD_PPI_GET_EX_SIZE) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET8) ( + IN UINTN TokenNumber, + IN UINT8 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET16) ( + IN UINTN TokenNumber, + IN UINT16 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET32) ( + IN UINTN TokenNumber, + IN UINT32 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET64) ( + IN UINTN TokenNumber, + IN UINT64 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_POINTER) ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_BOOLEAN) ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_8) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_16) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_32) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_64) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_POINTER) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_SET_EX_BOOLEAN) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ); + +/** + Callback on SET function prototype definition. + + @param[in] CallBackGuid The PCD token GUID being set. + @param[in] CallBackToken The PCD token number being set. + @param[in] TokenData A pointer to the token data being set. + @param[in] TokenDataSize The size, in bytes, of the data being set. + + @retval VOID + +--*/ +typedef +VOID +(EFIAPI *PCD_PPI_CALLBACK) ( + IN CONST EFI_GUID *CallBackGuid, OPTIONAL + IN UINTN CallBackToken, + IN VOID *TokenData, + IN UINTN TokenDataSize + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_CALLBACK_ONSET) ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PPI_CALLBACK CallBackFunction + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_CANCEL_CALLBACK) ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PPI_CALLBACK CallBackFunction + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PPI_GET_NEXT_TOKEN) ( + IN CONST EFI_GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ); + +typedef struct { + PCD_PPI_SET_SKU SetSku; + + PCD_PPI_GET8 Get8; + PCD_PPI_GET16 Get16; + PCD_PPI_GET32 Get32; + PCD_PPI_GET64 Get64; + PCD_PPI_GET_POINTER GetPtr; + PCD_PPI_GET_BOOLEAN GetBool; + PCD_PPI_GET_SIZE GetSize; + + PCD_PPI_GET_EX_8 Get8Ex; + PCD_PPI_GET_EX_16 Get16Ex; + PCD_PPI_GET_EX_32 Get32Ex; + PCD_PPI_GET_EX_64 Get64Ex; + PCD_PPI_GET_EX_POINTER GetPtrEx; + PCD_PPI_GET_EX_BOOLEAN GetBoolEx; + PCD_PPI_GET_EX_SIZE GetSizeEx; + + PCD_PPI_SET8 Set8; + PCD_PPI_SET16 Set16; + PCD_PPI_SET32 Set32; + PCD_PPI_SET64 Set64; + PCD_PPI_SET_POINTER SetPtr; + PCD_PPI_SET_BOOLEAN SetBool; + + PCD_PPI_SET_EX_8 Set8Ex; + PCD_PPI_SET_EX_16 Set16Ex; + PCD_PPI_SET_EX_32 Set32Ex; + PCD_PPI_SET_EX_64 Set64Ex; + PCD_PPI_SET_EX_POINTER SetPtrEx; + PCD_PPI_SET_EX_BOOLEAN SetBoolEx; + + PCD_PPI_CALLBACK_ONSET CallbackOnSet; + PCD_PPI_CANCEL_CALLBACK CancelCallback; + PCD_PPI_GET_NEXT_TOKEN GetNextToken; +} PCD_PPI; + + +#endif diff --git a/MdePkg/Include/Ppi/PciCfg.h b/MdePkg/Include/Ppi/PciCfg.h new file mode 100644 index 0000000000..b38a0db3ce --- /dev/null +++ b/MdePkg/Include/Ppi/PciCfg.h @@ -0,0 +1,133 @@ +/** @file + This file declares PciCfg PPI used to access PCI configuration space in PEI + + Copyright (c) 2006, 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. + + Module Name: PciCfg.h + + @par Revision Reference: + This PPI is defined in PEI CIS + Version 0.91. + +**/ + +#ifndef __PEI_PCI_CFG_H__ +#define __PEI_PCI_CFG_H__ + +#define EFI_PEI_PCI_CFG_PPI_INSTALLED_GUID \ + { \ + 0xe1f2eba0, 0xf7b9, 0x4a26, {0x86, 0x20, 0x13, 0x12, 0x21, 0x64, 0x2a, 0x90 } \ + } + +typedef struct _EFI_PEI_PCI_CFG_PPI EFI_PEI_PCI_CFG_PPI; + +#define PEI_PCI_CFG_ADDRESS(bus, dev, func, reg) ( \ + (UINT64) ((((UINTN) bus) << 24) + (((UINTN) dev) << 16) + (((UINTN) func) << 8) + ((UINTN) reg)) \ + ) & 0x00000000ffffffff + +typedef enum { + EfiPeiPciCfgWidthUint8 = 0, + EfiPeiPciCfgWidthUint16 = 1, + EfiPeiPciCfgWidthUint32 = 2, + EfiPeiPciCfgWidthUint64 = 3, + EfiPeiPciCfgWidthMaximum +} EFI_PEI_PCI_CFG_PPI_WIDTH; + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT8 Reserved[4]; +} EFI_PEI_PCI_CFG_PPI_PCI_ADDRESS; + +/** + PCI read and write operation. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Width The width of the access. Enumerated in bytes. + + @param Address The physical address of the access. + + @param Buffer A pointer to the buffer of data. + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_NOT_YET_AVAILABLE The service has not been installed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCI_CFG_PPI_IO) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PCI_CFG_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN OUT VOID *Buffer + ); + +/** + PCI read-modify-write operation. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + + @param This Pointer to local data for the interface. + + @param Width The width of the access. Enumerated in bytes. + + @param Address The physical address of the access. + + @param SetBits Value of the bits to set. + + @param ClearBits Value of the bits to clear. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_PCI_CFG_PPI_RW) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PCI_CFG_PPI *This, + IN EFI_PEI_PCI_CFG_PPI_WIDTH Width, + IN UINT64 Address, + IN UINTN SetBits, + IN UINTN ClearBits + ); + +/** + @par Ppi Description: + The EFI_PEI_PCI_CFG_PPI interfaces are used to abstract accesses to PCI + controllers behind a PCI root bridge controller. + + @param Read + PCI read services. See the Read() function description. + + @param Write + PCI write services. See the Write() function description. + + @param Modify +PCI read-modify-write services. See the Modify() function description. + +**/ +struct _EFI_PEI_PCI_CFG_PPI { + EFI_PEI_PCI_CFG_PPI_IO Read; + EFI_PEI_PCI_CFG_PPI_IO Write; + EFI_PEI_PCI_CFG_PPI_RW Modify; +}; + +extern EFI_GUID gEfiPciCfgPpiInServiceTableGuid; + +#endif diff --git a/MdePkg/Include/Ppi/ReadOnlyVariable.h b/MdePkg/Include/Ppi/ReadOnlyVariable.h new file mode 100644 index 0000000000..3ea3c77535 --- /dev/null +++ b/MdePkg/Include/Ppi/ReadOnlyVariable.h @@ -0,0 +1,136 @@ +/** @file + This file declares Read-only Variable Service PPI + + Copyright (c) 2006, 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. + + Module Name: ReadOnlyVariable.h + + @par Revision Reference: + This PPI is defined in PEI CIS + Version 0.91. + +**/ + +#ifndef __PEI_READ_ONLY_VARIABLE_PPI_H__ +#define __PEI_READ_ONLY_VARIABLE_PPI_H__ + +#define EFI_PEI_READ_ONLY_VARIABLE_ACCESS_PPI_GUID \ + { \ + 0x3cdc90c6, 0x13fb, 0x4a75, {0x9e, 0x79, 0x59, 0xe9, 0xdd, 0x78, 0xb9, 0xfa } \ + } + +typedef struct _EFI_PEI_READ_ONLY_VARIABLE_PPI EFI_PEI_READ_ONLY_VARIABLE_PPI; + +// +// Variable attributes +// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +#define EFI_VARIABLE_READ_ONLY 0x00000008 + +/** + Get Variable value by Name and GUID pair + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param VariableName A NULL-terminated Unicode string that is the name of the vendor¡¯s variable. + + @param VendorGuid A unique identifier for the vendor. + + @param Attributes If not NULL, a pointer to the memory location to return + the attributes bitmask for the variable. + + @param DataSize On input, the size in bytes of the return Data buffer. + On output, the size of data returned in Data. + + @param Data The buffer to return the contents of the variable. + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_NOT_FOUND The variable was not found. + + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. + + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_VARIABLE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Data + ); + +/** + This function can be called multiple times to retrieve the VariableName + and VendorGuid of all variables currently available in the system. On each call + to GetNextVariableName() the previous results are passed into the interface, + and on output the interface returns the next variable name data. When the + entire variable list has been returned, the error EFI_NOT_FOUND is returned. + + @param PeiServices An indirect pointer to the PEI Services Table published by the PEI Foundation. + + @param VariableNameSize The size of the VariableName buffer. + + @param VariableName On input, supplies the last VariableName that was + returned by GetNextVariableName(). On output, returns the Null-terminated + Unicode string of the current variable. + + @param VendorGuid On input, supplies the last VendorGuid that was + returned by GetNextVariableName(). On output, returns the VendorGuid + of the current variable. + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_NOT_FOUND The next variable was not found. + + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the result. + + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + + @retval EFI_DEVICE_ERROR The variable name could not be retrieved due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_NEXT_VARIABLE_NAME) ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ); + +/** + @par Ppi Description: + This PPI provides a lightweight, read-only variant of the full EFI + variable services. + + @param GetVariable + A service to ascertain a given variable name. + + @param GetNextVariableName + A service to ascertain a variable based upon a given, known variable + +**/ +struct _EFI_PEI_READ_ONLY_VARIABLE_PPI { + EFI_PEI_GET_VARIABLE PeiGetVariable; + EFI_PEI_GET_NEXT_VARIABLE_NAME PeiGetNextVariableName; +}; + +extern EFI_GUID gEfiPeiReadOnlyVariablePpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/RecoveryModule.h b/MdePkg/Include/Ppi/RecoveryModule.h new file mode 100644 index 0000000000..044a68aa72 --- /dev/null +++ b/MdePkg/Include/Ppi/RecoveryModule.h @@ -0,0 +1,67 @@ +/** @file + This file declares Recovery Module PPI. + + Copyright (c) 2006, 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. + + Module Name: RecoveryModule.h + + @par Revision Reference: + This PPI is defined in Framework of EFI Recovery Spec. + Version 0.9 + +**/ + +#ifndef __PEI_RECOVERY_MODULE_PPI_H__ +#define __PEI_RECOVERY_MODULE_PPI_H__ + +#define EFI_PEI_RECOVERY_MODULE_PPI_GUID \ + { \ + 0xFB6D9542, 0x612D, 0x4f45, {0x87, 0x2F, 0x5C, 0xFF, 0x52, 0xE9, 0x3D, 0xCF } \ + } + +typedef struct _EFI_PEI_RECOVERY_MODULE_PPI EFI_PEI_RECOVERY_MODULE_PPI; + +/** + Loads a DXE capsule from some media into memory and updates the HOB table + with the DXE firmware volume information. + + @param PeiServices General-purpose services that are available to every PEIM. + + @param This Indicates the EFI_PEI_RECOVERY_MODULE_PPI instance. + + @retval EFI_SUCCESS The capsule was loaded correctly. + + @retval EFI_DEVICE_ERROR A device error occurred. + + @retval EFI_NOT_FOUND A recovery DXE capsule cannot be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_LOAD_RECOVERY_CAPSULE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_RECOVERY_MODULE_PPI *This + ); + +/** + @par Ppi Description: + Finds and loads the recovery files. + + @param LoadRecoveryCapsule + Loads a DXE binary capsule into memory. + +**/ +struct _EFI_PEI_RECOVERY_MODULE_PPI { + EFI_PEI_LOAD_RECOVERY_CAPSULE LoadRecoveryCapsule; +}; + +extern EFI_GUID gEfiPeiRecoveryModulePpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/Reset.h b/MdePkg/Include/Ppi/Reset.h new file mode 100644 index 0000000000..be35e70d9a --- /dev/null +++ b/MdePkg/Include/Ppi/Reset.h @@ -0,0 +1,35 @@ +/** @file + This file declares Reset PPI used to reset the platform + + Copyright (c) 2006, 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. + + Module Name: Reset.h + + @par Revision Reference: + This PPI is defined in PEI CIS + Version 0.91. + +**/ + +#ifndef __RESET_PPI_H__ +#define __RESET_PPI_H__ + +#define EFI_PEI_RESET_PPI_GUID \ + { \ + 0xef398d58, 0x9dfd, 0x4103, {0xbf, 0x94, 0x78, 0xc6, 0xf4, 0xfe, 0x71, 0x2f } \ + } + +typedef struct { + EFI_PEI_RESET_SYSTEM ResetSystem; +} EFI_PEI_RESET_PPI; + +extern EFI_GUID gEfiPeiResetPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/S3Resume.h b/MdePkg/Include/Ppi/S3Resume.h new file mode 100644 index 0000000000..c458430b98 --- /dev/null +++ b/MdePkg/Include/Ppi/S3Resume.h @@ -0,0 +1,65 @@ +/** @file + This file declares S3 Resume PPI. + + Copyright (c) 2006, 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. + + Module Name: S3Resume.h + + @par Revision Reference: + This PPI is defined in Framework of EFI S3 Resume Boot Path spec. + Version 0.9 + +**/ + +#ifndef __PEI_S3_RESUME_PPI_H__ +#define __PEI_S3_RESUME_PPI_H__ + +#define EFI_PEI_S3_RESUME_PPI_GUID \ + { \ + 0x4426CCB2, 0xE684, 0x4a8a, {0xAE, 0x40, 0x20, 0xD4, 0xB0, 0x25, 0xB7, 0x10 } \ + } + +typedef struct _EFI_PEI_S3_RESUME_PPI EFI_PEI_S3_RESUME_PPI; + +/** + Restores the platform to its preboot configuration for an S3 resume and + jumps to the OS waking vector. + + @param PeiServices Pointer to the PEI Services Table + + @retval EFI_ABORTED Execution of the S3 resume boot script table failed. + + @retval EFI_NOT_FOUND Some necessary information that is used for + the S3 resume boot path could not be located. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_S3_RESUME_PPI_RESTORE_CONFIG) ( + IN EFI_PEI_SERVICES **PeiServices + ); + +/** + @par Ppi Description: + EFI_PEI_S3_RESUME_PPI accomplishes the firmware S3 resume boot + path and transfers control to OS. + + @param S3RestoreConfig + Restores the platform to its preboot configuration for an S3 resume and + jumps to the OS waking vector. + +**/ +struct _EFI_PEI_S3_RESUME_PPI { + EFI_PEI_S3_RESUME_PPI_RESTORE_CONFIG S3RestoreConfig; +}; + +extern EFI_GUID gEfiPeiS3ResumePpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/SecPlatformInformation.h b/MdePkg/Include/Ppi/SecPlatformInformation.h new file mode 100644 index 0000000000..1e9625923c --- /dev/null +++ b/MdePkg/Include/Ppi/SecPlatformInformation.h @@ -0,0 +1,86 @@ +/** @file + This file declares Sec Platform Information PPI. + + Copyright (c) 2006, 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. + + Module Name: SecPlatformInformation.h + + @par Revision Reference: + This PPI is defined in PEI CIS. + Version 0.91. + +**/ + +#ifndef __SEC_PLATFORM_INFORMATION_PPI_H__ +#define __SEC_PLATFORM_INFORMATION_PPI_H__ + +#define EFI_SEC_PLATFORM_INFORMATION_GUID \ + { \ + 0x6f8c2b35, 0xfef4, 0x448d, {0x82, 0x56, 0xe1, 0x1b, 0x19, 0xd6, 0x10, 0x77 } \ + } + +typedef struct _EFI_SEC_PLATFORM_INFORMATION_PPI EFI_SEC_PLATFORM_INFORMATION_PPI; + +extern EFI_GUID gEfiSecPlatformInformationPpiGuid; + +/// +/// EFI_HEALTH_FLAGS +/// +typedef union { + struct { + UINT32 Status : 2; + UINT32 Tested : 1; + UINT32 Reserved1 :13; + UINT32 VirtualMemoryUnavailable : 1; + UINT32 Ia32ExecutionUnavailable : 1; + UINT32 FloatingPointUnavailable : 1; + UINT32 MiscFeaturesUnavailable : 1; + UINT32 Reserved2 :12; + } Bits; + UINT32 Uint32; +} EFI_HEALTH_FLAGS; + +typedef struct { + EFI_HEALTH_FLAGS HealthFlags; +} EFI_SEC_PLATFORM_INFORMATION_RECORD; + +/** + This interface conveys state information out of the Security (SEC) phase into PEI. + + @param PeiServices Pointer to the PEI Services Table. + + @param StructureSize Pointer to the variable describing size of the input buffer. + + @param PlatformInformationRecord Pointer to the EFI_SEC_PLATFORM_INFORMATION_RECORD. + + @retval EFI_SUCCESS The data was successfully returned. + + @retval EFI_BUFFER_TOO_SMALL The buffer was too small. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SEC_PLATFORM_INFORMATION) ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT UINT64 *StructureSize, + OUT EFI_SEC_PLATFORM_INFORMATION_RECORD *PlatformInformationRecord + ); + +/** + @par Ppi Description: + + @param Name + +**/ +struct _EFI_SEC_PLATFORM_INFORMATION_PPI { + EFI_SEC_PLATFORM_INFORMATION PlatformInformation; +}; + +#endif diff --git a/MdePkg/Include/Ppi/SectionExtraction.h b/MdePkg/Include/Ppi/SectionExtraction.h new file mode 100644 index 0000000000..afa473d9ef --- /dev/null +++ b/MdePkg/Include/Ppi/SectionExtraction.h @@ -0,0 +1,118 @@ +/** @file + This file declares Section Extraction PPI. + + Copyright (c) 2006, 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. + + Module Name: SectionExtraction.h + + @par Revision Reference: + This PPI is defined in PEI CIS. + Version 0.91. + +**/ + +#ifndef __SECTION_EXTRACTION_PPI_H__ +#define __SECTION_EXTRACTION_PPI_H__ + +#define EFI_PEI_SECTION_EXTRACTION_PPI_GUID \ + { \ + 0x4F89E208, 0xE144, 0x4804, {0x9E, 0xC8, 0x0F, 0x89, 0x4F, 0x7E, 0x36, 0xD7 } \ + } + +typedef struct _EFI_PEI_SECTION_EXTRACTION_PPI EFI_PEI_SECTION_EXTRACTION_PPI; + +// +// Bit values for AuthenticationStatus +// +#define EFI_PEI_AUTH_STATUS_PLATFORM_OVERRIDE 0x01 +#define EFI_PEI_AUTH_STATUS_IMAGE_SIGNED 0x02 +#define EFI_PEI_AUTH_STATUS_NOT_TESTED 0x04 +#define EFI_PEI_AUTH_STATUS_TEST_FAILED 0x08 + +/** + The function is used to retrieve a section from within a section file. + It will retrieve both encapsulation sections and leaf sections in their entirety, + exclusive of the section header. + + @param PeiServices Pointer to the PEI Services Table. + + @param This Indicates the calling context + + @param SectionType Pointer to an EFI_SECTION_TYPE. If SectionType == NULL, + the contents of the entire section are returned in Buffer. If SectionType + is not NULL, only the requested section is returned. + + @param SectionDefinitionGuid Pointer to an EFI_GUID. + If SectionType == EFI_SECTION_GUID_DEFINED, SectionDefinitionGuid + indicates for which section GUID to search. + If SectionType != EFI_SECTION_GUID_DEFINED, SectionDefinitionGuid + is unused and is ignored. + + @param SectionInstance If SectionType is not NULL, indicates which + instance of the requested section type to return. + + @param Buffer Pointer to a pointer to a buffer in which the section + contents are returned. + + @param BufferSize A pointer to a caller-allocated UINT32.On input, *BufferSize + indicates the size in bytes of the memory region pointed to by Buffer.On output, + *BufferSize contains the number of bytes required to read the section. + + @param AuthenticationStatus A pointer to a caller-allocated UINT32 in + which any metadata from encapsulating GUID-defined sections is returned. + + @retval EFI_SUCCESS The section was successfully processed and the section + contents were returned in Buffer. + + @retval EFI_PROTOCOL_ERROR A GUID-defined section was encountered in + the file with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED bit set, but + there was no corresponding GUIDed Section Extraction Protocol in the + handle database.*Buffer is unmodified. + + @retval EFI_NOT_FOUND The requested section does not exist.*Buffer is unmodified. + + @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process the request. + + @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist. + + @retval EFI_WARN_TOO_SMALL The size of the input buffer is insufficient to + contain the requested section. The input buffer is filled and contents are + section contents are truncated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_GET_SECTION) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_SECTION_EXTRACTION_PPI *This, + IN EFI_SECTION_TYPE *SectionType, + IN EFI_GUID *SectionDefinitionGuid, OPTIONAL + IN UINTN SectionInstance, + IN VOID **Buffer, + IN OUT UINT32 *BufferSize, + OUT UINT32 *AuthenticationStatus + ); + +/** + @par Ppi Description: + This PPI supports encapsulating sections, such as GUIDed sections used to + authenticate the file encapsulation of other domain-specific wrapping. + + @param GetSection + Retrieves a section from within a section file. + +**/ +struct _EFI_PEI_SECTION_EXTRACTION_PPI { + EFI_PEI_GET_SECTION PeiGetSection; +}; + +extern EFI_GUID gEfiPeiSectionExtractionPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/Security.h b/MdePkg/Include/Ppi/Security.h new file mode 100644 index 0000000000..cc59023bf5 --- /dev/null +++ b/MdePkg/Include/Ppi/Security.h @@ -0,0 +1,77 @@ +/** @file + This file declares Security Architectural PPI. + + Copyright (c) 2006, 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. + + Module Name: Security.h + + @par Revision Reference: + This PPI is defined in PEI CIS. + Version 0.91. + +**/ + +#ifndef __SECURITY_PPI_H__ +#define __SECURITY_PPI_H__ + +#define EFI_PEI_SECURITY_PPI_GUID \ + { \ + 0x1388066e, 0x3a57, 0x4efa, {0x98, 0xf3, 0xc1, 0x2f, 0x3a, 0x95, 0x8a, 0x29 } \ + } + +typedef struct _EFI_PEI_SECURITY_PPI EFI_PEI_SECURITY_PPI; + +/** + Allows the platform builder to implement a security policy in response + to varying file authentication states. + + @param PeiServices Pointer to the PEI Services Table. + + @param This Interface pointer that implements the particular EFI_PEI_SECURITY_PPI instance. + + @param AuthenticationStatus Status returned by the verification service as part of section extraction. + + @param FfsFileHeader Pointer to the file under review. + + @param DeferExecution Pointer to a variable that alerts the PEI Foundation to defer execution of a PEIM. + + @retval EFI_SUCCESS The service performed its action successfully. + + @retval EFI_SECURITY_VIOLATION The object cannot be trusted + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SECURITY_AUTHENTICATION_STATE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_SECURITY_PPI *This, + IN UINT32 AuthenticationStatus, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT BOOLEAN *StartCrisisRecovery + ); + +/** + @par Ppi Description: + This PPI is installed by some platform PEIM that abstracts the security + policy to the PEI Foundation, namely the case of a PEIM¡¯s authentication + state being returned during the PEI section extraction process. + + @param AuthenticationState + Allows the platform builder to implement a security policy in response + to varying file authentication states. + +**/ +struct _EFI_PEI_SECURITY_PPI { + EFI_PEI_SECURITY_AUTHENTICATION_STATE AuthenticationState; +}; + +extern EFI_GUID gEfiPeiSecurityPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/Smbus.h b/MdePkg/Include/Ppi/Smbus.h new file mode 100644 index 0000000000..7360e5b12f --- /dev/null +++ b/MdePkg/Include/Ppi/Smbus.h @@ -0,0 +1,258 @@ +/** @file + This file declares Smbus PPI. + + Copyright (c) 2006, 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. + + Module Name: Smbus.h + + @par Revision Reference: + This PPI is defined in Framework of EFI SmBus PPI spec. + Version 0.9 + +**/ + +#ifndef _PEI_SMBUS_PPI_H +#define _PEI_SMBUS_PPI_H + +#define EFI_PEI_SMBUS_PPI_GUID \ + { \ + 0xabd42895, 0x78cf, 0x4872, {0x84, 0x44, 0x1b, 0x5c, 0x18, 0xb, 0xfb, 0xda } \ + } + +typedef struct _EFI_PEI_SMBUS_PPI EFI_PEI_SMBUS_PPI; + +/** + Executes an SMBus operation to an SMBus controller. + + @param PeiServices A pointer to the system PEI Services Table. + + @param This A pointer to the EFI_PEI_SMBUS_PPI instance. + + @param SlaveAddress The SMBUS hardware address to which the SMBUS + device is preassigned or allocated. + + @param Command This command is transmitted by the SMBus host + controller to the SMBus slave device and the interpretation is + SMBus slave device specific. + + @param Operation Signifies which particular SMBus hardware protocol + instance that it will use to execute the SMBus transactions. + + @param PecCheck Defines if Packet Error Code (PEC) checking is required + for this operation. + + @param Length Signifies the number of bytes that this operation will do. + + @param Buffer Contains the value of data to execute to the SMBus slave device. + + @retval EFI_SUCCESS The last data that was returned from the access + matched the poll exit criteria. + + @retval EFI_CRC_ERROR The checksum is not correct (PEC is incorrect) + + @retval EFI_TIMEOUT Timeout expired before the operation was completed. + Timeout is determined by the SMBus host controller device. + + @retval EFI_OUT_OF_RESOURCES The request could not be completed + due to a lack of resources. + + @retval EFI_DEVICE_ERROR The request was not completed because + a failure reflected in the Host Status Register bit. + + @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION. + Or Length/Buffer is NULL for operations except for EfiSmbusQuickRead and + EfiSmbusQuickWrite. Length is outside the range of valid values. + + @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported. + + @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SMBUS_PPI_EXECUTE_OPERATION) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_SMBUS_PPI *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN EFI_SMBUS_DEVICE_COMMAND Command, + IN EFI_SMBUS_OPERATION Operation, + IN BOOLEAN PecCheck, + IN OUT UINTN *Length, + IN OUT VOID *Buffer + ); + +typedef struct { + UINT32 VendorSpecificId; + UINT16 SubsystemDeviceId; + UINT16 SubsystemVendorId; + UINT16 Interface; + UINT16 DeviceId; + UINT16 VendorId; + UINT8 VendorRevision; + UINT8 DeviceCapabilities; +} EFI_SMBUS_UDID; + +/** + CallBack function can be registered in EFI_PEI_SMBUS_PPI_NOTIFY. + + @param PeiServices A pointer to the system PEI Services Table. + + @param This A pointer to the EFI_PEI_SMBUS_PPI instance. + + @param SlaveAddress The SMBUS hardware address to which the SMBUS + device is preassigned or allocated. + + @param Data Data of the SMBus host notify command that + the caller wants to be called. + + @return Status Code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SMBUS_NOTIFY_FUNCTION) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_SMBUS_PPI *SmbusPpi, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data + ); + +/** + The ArpDevice() function enumerates the entire bus or enumerates a specific + device that is identified by SmbusUdid. + + @param PeiServices A pointer to the system PEI Services Table. + + @param This A pointer to the EFI_PEI_SMBUS_PPI instance. + + @param ArpAll A Boolean expression that indicates if the host drivers need + to enumerate all the devices or enumerate only the device that is identified + by SmbusUdid. If ArpAll is TRUE, SmbusUdid and SlaveAddress are optional. + If ArpAll is FALSE, ArpDevice will enumerate SmbusUdid and the address + will be at SlaveAddress. + + @param SmbusUdid The targeted SMBus Unique Device Identifier (UDID). + The UDID may not exist for SMBus devices with fixed addresses. + + @param SlaveAddress The new SMBus address for the slave device for + which the operation is targeted. + + @retval EFI_SUCCESS The SMBus slave device address was set. + + @retval EFI_INVALID_PARAMETER SlaveAddress is NULL. + + @retval EFI_OUT_OF_RESOURCES The request could not be completed + due to a lack of resources. + + @retval EFI_TIMEOUT The SMBus slave device did not respond. + + @retval EFI_DEVICE_ERROR The request was not completed because the transaction failed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SMBUS_PPI_ARP_DEVICE) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_SMBUS_PPI *This, + IN BOOLEAN ArpAll, + IN EFI_SMBUS_UDID *SmbusUdid, OPTIONAL + IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL + ); + +typedef struct { + EFI_SMBUS_DEVICE_ADDRESS SmbusDeviceAddress; + EFI_SMBUS_UDID SmbusDeviceUdid; +} EFI_SMBUS_DEVICE_MAP; + +/** + The GetArpMap() function returns the mapping of all the SMBus devices + that are enumerated by the SMBus host driver. + + @param PeiServices A pointer to the system PEI Services Table. + + @param This A pointer to the EFI_PEI_SMBUS_PPI instance. + + @param Length Size of the buffer that contains the SMBus device map. + + @param SmbusDeviceMap The pointer to the device map as enumerated + by the SMBus controller driver. + + @retval EFI_SUCCESS The device map was returned correctly in the buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SMBUS_PPI_GET_ARP_MAP) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_SMBUS_PPI *This, + IN OUT UINTN *Length, + IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap + ); + +/** + The Notify() function registers all the callback functions to allow the + bus driver to call these functions when the SlaveAddress/Data pair happens. + + @param PeiServices A pointer to the system PEI Services Table. + + @param This A pointer to the EFI_PEI_SMBUS_PPI instance. + + @param SlaveAddress Address that the host controller detects as + sending a message and calls all the registered functions. + + @param Data Data that the host controller detects as sending a message + and calls all the registered functions. + + @param NotifyFunction The function to call when the bus driver + detects the SlaveAddress and Data pair. + + @retval EFI_SUCCESS NotifyFunction has been registered. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_SMBUS_PPI_NOTIFY) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_SMBUS_PPI *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data, + IN EFI_PEI_SMBUS_NOTIFY_FUNCTION NotifyFunction + ); + +/** + @par Ppi Description: + Provides the basic I/O interfaces that a PEIM uses to access + its SMBus controller and the slave devices attached to it. + + @param Execute + Executes the SMBus operation to an SMBus slave device. + + @param ArpDevice + Allows an SMBus 2.0 device(s) to be Address Resolution Protocol (ARP) + + @param GetArpMap + Allows a PEIM to retrieve the address that was allocated by the SMBus + host controller during enumeration/ARP. + + @param Notify + Allows a driver to register for a callback to the SMBus host + controller driver when the bus issues a notification to the bus controller PEIM. + +**/ +struct _EFI_PEI_SMBUS_PPI { + EFI_PEI_SMBUS_PPI_EXECUTE_OPERATION Execute; + EFI_PEI_SMBUS_PPI_ARP_DEVICE ArpDevice; + EFI_PEI_SMBUS_PPI_GET_ARP_MAP GetArpMap; + EFI_PEI_SMBUS_PPI_NOTIFY Notify; +}; + +extern EFI_GUID gEfiPeiSmbusPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/Stall.h b/MdePkg/Include/Ppi/Stall.h new file mode 100644 index 0000000000..363baa6d39 --- /dev/null +++ b/MdePkg/Include/Ppi/Stall.h @@ -0,0 +1,73 @@ +/** @file + This file declares Stall PPI. + + This code abstracts the PEI core to provide Stall services. + + Copyright (c) 2006, 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. + + Module Name: Stall.h + + @par Revision Reference: + This PPI is defined in PEI CIS. + Version 0.91. + +**/ + +#ifndef __STALL_PPI_H__ +#define __STALL_PPI_H__ + +#define EFI_PEI_STALL_PPI_GUID \ + { \ + 0x1f4c6f90, 0xb06b, 0x48d8, {0xa2, 0x01, 0xba, 0xe5, 0xf1, 0xcd, 0x7d, 0x56 } \ + } + +typedef struct _EFI_PEI_STALL_PPI EFI_PEI_STALL_PPI; + +/** + The Stall() function provides a blocking stall for at least the number + of microseconds stipulated in the final argument of the API. + + @param PeiServices An indirect pointer to the PEI Services Table + published by the PEI Foundation. + + @param This Pointer to the local data for the interface. + + @param Microseconds Number of microseconds for which to stall. + + @retval EFI_SUCCESS The service provided at least the required delay. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PEI_STALL) ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_STALL_PPI *This, + IN UINTN Microseconds + ); + +/** + @par Ppi Description: + This service provides a simple, blocking stall with platform-specific resolution. + + @param Resolution + The resolution in microseconds of the stall services. + + @param Stall + The actual stall procedure call. + +**/ +struct _EFI_PEI_STALL_PPI { + UINTN Resolution; + EFI_PEI_STALL Stall; +}; + +extern EFI_GUID gEfiPeiStallPpiGuid; + +#endif diff --git a/MdePkg/Include/Ppi/StatusCode.h b/MdePkg/Include/Ppi/StatusCode.h new file mode 100644 index 0000000000..5470222c5b --- /dev/null +++ b/MdePkg/Include/Ppi/StatusCode.h @@ -0,0 +1,42 @@ +/** @file + This file declares Status Code PPI. + + Copyright (c) 2006, 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. + + Module Name: StatusCode.h + + @par Revision Reference: + This PPI is defined in PEI CIS. + Version 0.91. + +**/ + +#ifndef __STATUS_CODE_PPI_H__ +#define __STATUS_CODE_PPI_H__ + +#define EFI_PEI_REPORT_PROGRESS_CODE_PPI_GUID \ + { 0x229832d3, 0x7a30, 0x4b36, {0xb8, 0x27, 0xf4, 0xc, 0xb7, 0xd4, 0x54, 0x36 } } + +/** + @par Ppi Description: + This ppi provides the sevice to report status code. There can be only one instance + of this service in the system. + + @param ReportStatusCode + Service that allows PEIMs to report status codes. This function is defined in Peicis.h + +**/ +typedef struct { + EFI_PEI_REPORT_STATUS_CODE ReportStatusCode; +} EFI_PEI_PROGRESS_CODE_PPI; + +extern EFI_GUID gEfiPeiStatusCodePpiGuid; + +#endif diff --git a/MdePkg/Include/Protocol/AcpiSupport.h b/MdePkg/Include/Protocol/AcpiSupport.h new file mode 100644 index 0000000000..8602b67f85 --- /dev/null +++ b/MdePkg/Include/Protocol/AcpiSupport.h @@ -0,0 +1,173 @@ +/** @file + Definition of the ACPI Support protocol. + + Copyright (c) 2006, 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. + + Module Name: AcpiSupport.h + + @par Revision Reference: + This is defined in the ACPI Specification 0.9. + +**/ + +#ifndef _ACPI_SUPPORT_PROTOCOL_H_ +#define _ACPI_SUPPORT_PROTOCOL_H_ + +typedef struct _EFI_ACPI_SUPPORT_PROTOCOL EFI_ACPI_SUPPORT_PROTOCOL; + +// +// ACPI Support Protocol GUID +// +#define EFI_ACPI_SUPPORT_GUID \ + { \ + 0xdbff9d55, 0x89b7, 0x46da, {0xbd, 0xdf, 0x67, 0x7d, 0x3d, 0xc0, 0x24, 0x1d } \ + } + +// +// Protocol Data Definitions +// +// +// ACPI Version bitmap definition: +// +// EFI_ACPI_TABLE_VERSION_1_0B - ACPI Version 1.0b +// EFI_ACPI_TABLE_VERSION_2_0 - ACPI Version 2.0 +// EFI_ACPI_TABLE_VERSION_3_0 - ACPI Version 3.0 +// EFI_ACPI_TABLE_VERSION_NONE - No ACPI Versions. This might be used +// to create memory-based operation regions or other information +// that is not part of the ACPI "tree" but must still be found +// in ACPI memory space and/or managed by the core ACPI driver. +// +// Note that EFI provides discrete GUIDs for each version of ACPI +// that is supported. It is expected that each EFI GUIDed +// version of ACPI will also have a corresponding bitmap +// definition. This allows maintenance of separate ACPI trees +// for each distinctly different version of ACPI. +// +#define EFI_ACPI_TABLE_VERSION UINT32 + +#define EFI_ACPI_TABLE_VERSION_NONE (1 << 0) +#define EFI_ACPI_TABLE_VERSION_1_0B (1 << 1) +#define EFI_ACPI_TABLE_VERSION_2_0 (1 << 2) +#define EFI_ACPI_TABLE_VERSION_3_0 (1 << 3) + +// +// Protocol Member Functions +// + +/** + Returns a requested ACPI table. + + @param This A pointer to the EFI_ACPI_SUPPORT_PROTOCOL instance. + + @param Index The zero-based index of the table to retrieve. + + @param Table Pointer for returning the table buffer. + + @param Version Updated with the ACPI versions to which this table belongs. + + @param Handle Pointer for identifying the table. + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_NOT_FOUND The requested index is too large and a table was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_GET_ACPI_TABLE) ( + IN EFI_ACPI_SUPPORT_PROTOCOL *This, + IN INTN Index, + OUT VOID **Table, + OUT EFI_ACPI_TABLE_VERSION *Version, + OUT UINTN *Handle + ); + +/** + Used to add, remove, or update ACPI tables. + + @param This A pointer to the EFI_ACPI_SUPPORT_PROTOCOL instance. + + @param Table Pointer to the new table to add or update. + + @param Checksum If TRUE, indicates that the checksum should be + calculated for this table. + + @param Version Indicates to which version(s) of ACPI the table should be added. + + @param Pointer to the handle of the table to remove or update. + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_INVALID_PARAMETER *Handle was zero and Table was NULL. + + @retval EFI_ABORTED Could not complete the desired action. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_SET_ACPI_TABLE) ( + IN EFI_ACPI_SUPPORT_PROTOCOL *This, + IN VOID *Table OPTIONAL, + IN BOOLEAN Checksum, + IN EFI_ACPI_TABLE_VERSION Version, + IN OUT UINTN *Handle + ); + +/** + Causes one or more versions of the ACPI tables to be published in + the EFI system configuration tables. + + @param This A pointer to the EFI_ACPI_SUPPORT_PROTOCOL instance. + + @param Version Indicates to which version(s) of ACPI that the table should be published. + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_ABORTED An error occurred and the function could not complete successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ACPI_PUBLISH_TABLES) ( + IN EFI_ACPI_SUPPORT_PROTOCOL *This, + IN EFI_ACPI_TABLE_VERSION Version + ); + +// +// ACPI Support Protocol +// +/** + @par Protocol Description: + This protocol provides some basic services to support publishing ACPI system + tables. The services handle many of the more mundane tasks that are required + to publish a set of tables. + + @param GetAcpiTable + Returns a table specified by an index if it exists. + + @param SetAcpiTable + Adds, removes, or updates ACPI tables + + @param PublishTables + Publishes the ACPI tables. + +**/ +struct _EFI_ACPI_SUPPORT_PROTOCOL { + EFI_ACPI_GET_ACPI_TABLE GetAcpiTable; + EFI_ACPI_SET_ACPI_TABLE SetAcpiTable; + EFI_ACPI_PUBLISH_TABLES PublishTables; +}; + +// +// Extern the GUID for protocol users. +// +extern EFI_GUID gEfiAcpiSupportGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Arp.h b/MdePkg/Include/Protocol/Arp.h new file mode 100644 index 0000000000..7394f3fb6a --- /dev/null +++ b/MdePkg/Include/Protocol/Arp.h @@ -0,0 +1,259 @@ +/** @file + Copyright (c) 2006, 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. + + Module Name: Arp.h + +**/ + +#ifndef __EFI_ARP_PROTOCOL_H__ +#define __EFI_ARP_PROTOCOL_H__ + +#define EFI_ARP_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xf44c00ee, 0x1f2c, 0x4a00, {0xaa, 0x9, 0x1c, 0x9f, 0x3e, 0x8, 0x0, 0xa3 } \ + } + +#define EFI_ARP_PROTOCOL_GUID \ + { \ + 0xf4b427bb, 0xba21, 0x4f16, {0xbc, 0x4e, 0x43, 0xe4, 0x16, 0xab, 0x61, 0x9c } \ + } + +typedef struct _EFI_ARP_PROTOCOL EFI_ARP_PROTOCOL; + +typedef struct { +UINT32 Size; +BOOLEAN DenyFlag; +BOOLEAN StaticFlag; +UINT16 HwAddressType; +UINT16 SwAddressType; +UINT8 HwAddressLength; +UINT8 SwAddressLength; +} EFI_ARP_FIND_DATA; + +typedef struct { + UINT16 SwAddressType; // Host byte order + UINT8 SwAddressLength; + VOID *StationAddress; // Network byte order + UINT32 EntryTimeOut; + UINT32 RetryCount; + UINT32 RetryTimeOut; +} EFI_ARP_CONFIG_DATA; + + +/** + Assigns a station address (protocol type and network address) to this instance of the ARP cache. + + @param This A pointer to the EFI_ARP_PROTOCOL instance. + @param ConfigData A pointer to the EFI_ARP_CONFIG_DATA structure.Buffer + + @retval EFI_SUCCESS The new station address was successfully registered. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + @retval EFI_ACCESS_DENIED The SwAddressType, SwAddressLength, or + StationAddress is different from the one that is already + registered. + @retval EFI_OUT_OF_RESOURCES Storage for the new StationAddress could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_CONFIGURE) ( + IN EFI_ARP_PROTOCOL *This, + IN EFI_ARP_CONFIG_DATA *ConfigData OPTIONAL + ) +; + +/** + Inserts an entry to the ARP cache. + + @param This A pointer to the EFI_ARP_PROTOCOL instance. + @param DenyFlag Set to TRUE if this entry is a ¡°deny¡± entry. Set to FALSE if this + entry is a ¡°normal¡± entry. + @param TargetSwAddress Pointer to a protocol address to add (or deny). May be set to + NULL if DenyFlag is TRUE. + @param TargetHwAddress Pointer to a hardware address to add (or deny). May be set to + NULL if DenyFlag is TRUE. + @param TimeoutValue Time in 100-ns units that this entry will remain in the ARP + cache. A value of zero means that the entry is permanent. A + nonzero value will override the one given by Configure() if + the entry to be added is dynamic entry. + @param Overwrite If TRUE, the matching cache entry will be overwritten with the + supplied parameters. If FALSE, EFI_ACCESS_DENIED + + @retval EFI_SUCCESS The entry has been added or updated. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + @retval EFI_OUT_OF_RESOURCES The new ARP cache entry could not be allocated. + @retval EFI_ACCESS_DENIED The ARP cache entry already exists and Overwrite is not true. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_ADD) ( + IN EFI_ARP_PROTOCOL *This, + IN BOOLEAN DenyFlag, + IN VOID *TargetSwAddress OPTIONAL, + IN VOID *TargetHwAddress OPTIONAL, + IN UINT32 TimeoutValue, + IN BOOLEAN Overwrite + ) +; + +/** + Locates one or more entries in the ARP cache. + + @param This A pointer to the EFI_ARP_PROTOCOL instance. + @param BySwAddress Set to TRUE to look for matching software protocol addresses. + Set to FALSE to look for matching hardware protocol addresses. + @param AddressBuffer Pointer to address buffer. Set to NULL to match all addresses. + @param EntryLength The size of an entry in the entries buffer. To keep the + EFI_ARP_FIND_DATA structure properly aligned, this field + may be longer than sizeof(EFI_ARP_FIND_DATA) plus + the length of the software and hardware addresses. + @param EntryCount The number of ARP cache entries that are found by the specified criteria. + @param Entries Pointer to the buffer that will receive the ARP cache entries. + @param Refresh Set to TRUE to refresh the timeout value of the matching ARP + cache entry. + + @retval EFI_SUCCESS The requested ARP cache entries were copied into the buffer. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + @retval EFI_NOT_FOUND No matching entries were found. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_FIND) ( + IN EFI_ARP_PROTOCOL *This, + IN BOOLEAN BySwAddress, + IN VOID *AddressBuffer OPTIONAL, + OUT UINT32 *EntryLength OPTIONAL, + OUT UINT32 *EntryCount OPTIONAL, + OUT EFI_ARP_FIND_DATA **Entries OPTIONAL, + IN BOOLEAN Refresh + ) +; + + +/** + Removes entries from the ARP cache. + + @param This A pointer to the EFI_ARP_PROTOCOL instance. + @param BySwAddress Set to TRUE to delete matching protocol addresses. + Set to FALSE to delete matching hardware addresses. + @param AddressBuffer Pointer to the address buffer that is used as a key to look for the + cache entry. Set to NULL to delete all entries. + + @retval EFI_SUCCESS The entry was removed from the ARP cache. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_FOUND The specified deletion key was not found. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_DELETE) ( + IN EFI_ARP_PROTOCOL *This, + IN BOOLEAN BySwAddress, + IN VOID *AddressBuffer OPTIONAL + ) +; + +/** + Removes all dynamic ARP cache entries that were added by this interface. + + @param This A pointer to the EFI_ARP_PROTOCOL instance. + + @retval EFI_SUCCESS The cache has been flushed. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_FOUND There are no matching dynamic cache entries. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_FLUSH) ( + IN EFI_ARP_PROTOCOL *This + ) +; + +/** + Starts an ARP request session. + + @param This A pointer to the EFI_ARP_PROTOCOL instance. + @param TargetSwAddress Pointer to the protocol address to resolve. + @param ResolvedEvent Pointer to the event that will be signaled when the address is + resolved or some error occurs. + @param TargetHwAddress Pointer to the buffer for the resolved hardware address in + network byte order. The buffer must be large enough to hold the + resulting hardware address. TargetHwAddress must not be + NULL. + + @retval EFI_SUCCESS The data was copied from the ARP cache into the + TargetHwAddress buffer. + @retval EFI_INVALID_PARAMETER This or TargetHwAddress is NULL. + @retval EFI_ACCESS_DENIED The requested address is not present in the normal ARP cache but + is present in the deny address list. Outgoing traffic to that address is + forbidden. + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + @retval EFI_NOT_READY The request has been started and is not finished. + @retval EFI_UNSUPPORTED The requested conversion is not supported in this implementation or + configuration. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_REQUEST) ( + IN EFI_ARP_PROTOCOL *This, + IN VOID *TargetSwAddress OPTIONAL, + IN EFI_EVENT ResolvedEvent OPTIONAL, + OUT VOID *TargetHwAddress + ) +; + +/** + Cancels an ARP request session. + + @param This A pointer to the EFI_ARP_PROTOCOL instance. + @param TargetSwAddress Pointer to the protocol address in previous request session. + @param ResolvedEvent Pointer to the event that is used as the notification event in + previous request session. + + @retval EFI_SUCCESS The pending request session(s) is/are aborted and corresponding + event(s) is/are signaled. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + @retval EFI_NOT_STARTED The ARP driver instance has not been configured. + @retval EFI_NOT_FOUND The request is not issued by + EFI_ARP_PROTOCOL.Request(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ARP_CANCEL) ( + IN EFI_ARP_PROTOCOL *This, + IN VOID *TargetSwAddress OPTIONAL, + IN EFI_EVENT ResolvedEvent OPTIONAL + ) +; + +struct _EFI_ARP_PROTOCOL { + EFI_ARP_CONFIGURE Configure; + EFI_ARP_ADD Add; + EFI_ARP_FIND Find; + EFI_ARP_DELETE Delete; + EFI_ARP_FLUSH Flush; + EFI_ARP_REQUEST Request; + EFI_ARP_CANCEL Cancel; +}; + + +extern EFI_GUID gEfiArpServiceBindingProtocolGuid; +extern EFI_GUID gEfiArpProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/AuthenticationInfo.h b/MdePkg/Include/Protocol/AuthenticationInfo.h new file mode 100644 index 0000000000..f80dbf362b --- /dev/null +++ b/MdePkg/Include/Protocol/AuthenticationInfo.h @@ -0,0 +1,125 @@ +/** @file + EFI_AUTHENTICATION_INFO_PROTOCOL as defined in UEFI 2.0. + This protocol is used on any device handle to obtain authentication information + associated with the physical or logical device. + + Copyright (c) 2006, 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. + + Module Name: AuthenticationInfo.h + +**/ + +#ifndef __AUTHENTICATION_INFO_H__ +#define __AUTHENTICATION_INFO_H__ + +#define EFI_AUTHENTICATION_INFO_PROTOCOL_GUID \ + { \ + 0x7671d9d0, 0x53db, 0x4173, {0xaa, 0x69, 0x23, 0x27, 0xf2, 0x1f, 0x0b, 0xc7 } \ + } + +#define EFI_AUTHENTICATION_CHAP_RADIUS_GUID \ + { \ + 0xd6062b50, 0x15ca, 0x11da, {0x92, 0x19, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \ + } + +#define EFI_AUTHENTICATION_CHAP_LOCAL_GUID \ + { \ + 0xc280c73e, 0x15ca, 0x11da, {0xb0, 0xca, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \ + } + +typedef struct _EFI_AUTHENTICATION_INFO_PROTOCOL EFI_AUTHENTICATION_INFO_PROTOCOL; + +typedef struct { + EFI_GUID Guid; + UINT16 Length; +} AUTH_NODE_HEADER; + +typedef struct { + AUTH_NODE_HEADER Header; + EFI_IPv6_ADDRESS RadiusIpAddr; // IPv4 or IPv6 address + UINT16 Reserved; + EFI_IPv6_ADDRESS NasIpAddr; // IPv4 or IPv6 address + UINT16 NasSecretLength; + UINT8 *NasSecret; + UINT16 ChapSecretLength; + UINT8 *ChapSecret; + UINT16 ChapNameLength; + UINT8 *ChapName; +} CHAP_RADIUS_AUTH_NODE; + +typedef struct { + AUTH_NODE_HEADER Header; + UINT16 Reserved; + UINT16 UserSecretLength; + UINT8 *UserSecret; + UINT16 UserNameLength; + UINT8 *UserName; + UINT16 ChapSecretLength; + UINT8 *ChapSecret; + UINT16 ChapNameLength; + UINT8 *ChapName; +} CHAP_LOCAL_AUTH_NODE; + +/** + Retrieves the Authentication information associated with a particular controller handle. + + @param This Pointer to the EFI_AUTHENTICATION_INFO_PROTOCOL + @param ControllerHandle Handle to the Controller + @param Buffer Pointer to the authentication information. + + @retval EFI_SUCCESS Successfully retrieved Authentication information for the given ControllerHandle + @retval EFI_INVALID_PARAMETER No matching Authentication information found for the given ControllerHandle + @retval EFI_DEVICE_ERROR The authentication information could not be retrieved due to a + hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_AUTHENTICATION_PROTOCOL_INFO_GET) ( + IN EFI_AUTHENTICATION_INFO_PROTOCOL *This, + IN EFI_HANDLE *ControllerHandle, + OUT VOID *Buffer + ) +; + +/** + Set the Authentication information for a given controller handle. + + @param This Pointer to the EFI_AUTHENTICATION_INFO_PROTOCOL + @param ControllerHandle Handle to the Controller + @param Buffer Pointer to the authentication information. + + @retval EFI_SUCCESS Successfully set Authentication information for the given ControllerHandle + @retval EFI_UNSUPPORTED If the platform policies do not allow setting of the Authentication + information. + @retval EFI_DEVICE_ERROR The authentication information could not be configured due to a + hardware error. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_AUTHENTICATION_PROTOCOL_INFO_SET) ( + IN EFI_AUTHENTICATION_INFO_PROTOCOL *This, + IN EFI_HANDLE *ControllerHandle, + IN VOID *Buffer + ) +; + +struct _EFI_AUTHENTICATION_INFO_PROTOCOL { + EFI_AUTHENTICATION_PROTOCOL_INFO_GET Get; + EFI_AUTHENTICATION_PROTOCOL_INFO_SET Set; +}; + +extern EFI_GUID gEfiAuthenticationInfoProtocolGuid; +extern EFI_GUID gEfiAuthenticationChapRadiusGuid; +extern EFI_GUID gEfiAuthenticationChapLocalGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Bis.h b/MdePkg/Include/Protocol/Bis.h new file mode 100644 index 0000000000..ffc66f622a --- /dev/null +++ b/MdePkg/Include/Protocol/Bis.h @@ -0,0 +1,418 @@ +/** @file + This file defines the BIS protocol. + + Copyright (c) 2006, 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. + + Module Name: Bis.h + +**/ + +#ifndef __BIS_H__ +#define __BIS_H__ + +#define EFI_BIS_PROTOCOL_GUID \ + { \ + 0x0b64aab0, 0x5429, 0x11d4, {0x98, 0x16, 0x00, 0xa0, 0xc9, 0x1f, 0xad, 0xcf } \ + } + +typedef struct _EFI_BIS_PROTOCOL EFI_BIS_PROTOCOL; + + +// +// Basic types +// +typedef VOID *BIS_APPLICATION_HANDLE; +typedef UINT16 BIS_ALG_ID; +typedef UINT32 BIS_CERT_ID; + +// +// EFI_BIS_DATA type. +// +// EFI_BIS_DATA instances obtained from BIS must be freed by calling Free( ). +// +typedef struct { + UINT32 Length; // Length of Data in 8 bit bytes. + UINT8 *Data; // 32 Bit Flat Address of data. +} EFI_BIS_DATA; + +// +// EFI_BIS_VERSION type. +// +typedef struct { + UINT32 Major; // BIS Interface version number. + UINT32 Minor; // Build number. +} EFI_BIS_VERSION; + +// +// ----------------------------------------------------// +// Use these values to initialize EFI_BIS_VERSION.Major +// and to interpret results of Initialize. +// ----------------------------------------------------// +// +#define BIS_CURRENT_VERSION_MAJOR BIS_VERSION_1 +#define BIS_VERSION_1 1 + +// +// EFI_BIS_SIGNATURE_INFO type. +// +typedef struct { + BIS_CERT_ID CertificateID; // Truncated hash of platform Boot Object + // authorization certificate. + // + BIS_ALG_ID AlgorithmID; // A signature algorithm number. + UINT16 KeyLength; // Length of alg. keys in bits. +} EFI_BIS_SIGNATURE_INFO; + +// +// Currently defined values for EFI_BIS_SIGNATURE_INFO.AlgorithmID. +// The exact numeric values come from +// "Common Data Security Architecture (CDSA) Specification". +// +#define BIS_ALG_DSA (41) // CSSM_ALGID_DSA +#define BIS_ALG_RSA_MD5 (42) // CSSM_ALGID_MD5_WITH_RSA +// Currently defined values for EFI_BIS_SIGNATURE_INFO.CertificateId. +// +#define BIS_CERT_ID_DSA BIS_ALG_DSA // CSSM_ALGID_DSA +#define BIS_CERT_ID_RSA_MD5 BIS_ALG_RSA_MD5 // CSSM_ALGID_MD5_WITH_RSA +// The following is a mask value that gets applied to the truncated hash of a +// platform Boot Object Authorization Certificate to create the certificateID. +// A certificateID must not have any bits set to the value 1 other than bits in +// this mask. +// +#define BIS_CERT_ID_MASK (0xFF7F7FFF) + +// +// Macros for dealing with the EFI_BIS_DATA object obtained +// from BIS_GetSignatureInfo() +// BIS_GET_SIGINFO_COUNT - tells how many EFI_BIS_SIGNATURE_INFO +// elements are contained in a EFI_BIS_DATA struct pointed to +// by the provided EFI_BIS_DATA*. +// +#define BIS_GET_SIGINFO_COUNT(BisDataPtr) ((BisDataPtr)->Length / sizeof (EFI_BIS_SIGNATURE_INFO)) + +// +// BIS_GET_SIGINFO_ARRAY - produces a EFI_BIS_SIGNATURE_INFO* +// from a given EFI_BIS_DATA*. +// +#define BIS_GET_SIGINFO_ARRAY(BisDataPtr) ((EFI_BIS_SIGNATURE_INFO *) (BisDataPtr)->Data) + +// +// Binary Value of "X-Intel-BIS-ParameterSet" Attribute. +// (Value is Base64 encoded in actual signed manifest). +// {EDD35E31-07B9-11d2-83A3-00A0C91FADCF} +// +#define BOOT_OBJECT_AUTHORIZATION_PARMSET_GUID \ + { \ + 0xedd35e31, 0x7b9, 0x11d2, \ + { \ + 0x83, 0xa3, 0x0, 0xa0, 0xc9, 0x1f, 0xad, 0xcf \ + } \ + } + +// +// Support old name for backward compatible +// +#define BOOT_OBJECT_AUTHORIZATION_PARMSET_GUIDVALUE \ + BOOT_OBJECT_AUTHORIZATION_PARMSET_GUID + +/** + Initializes the BIS service, checking that it is compatible with the version requested by the caller. + After this call, other BIS functions may be invoked. + + @param This A pointer to the EFI_BIS_PROTOCOL object. + @param AppHandle The function writes the new BIS_APPLICATION_HANDLE if + successful, otherwise it writes NULL. The caller must eventually + destroy this handle by calling Shutdown(). + @param InterfaceVersion On input, the caller supplies the major version number of the + interface version desired. + On output, both the major and minor + version numbers are updated with the major and minor version + numbers of the interface + @param TargetAddress Indicates a network or device address of the BIS platform to connect to. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INCOMPATIBLE_VERSION The InterfaceVersion.Major requested by the + caller was not compatible with the interface version of the + @retval EFI_UNSUPPORTED This is a local-platform implementation and + TargetAddress.Data was not NULL, or + TargetAddress.Data was any other value that was not + supported by the implementation. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_DEVICE_ERROR The function encountered an unexpected internal failure. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_INITIALIZE) ( + IN EFI_BIS_PROTOCOL *This, + OUT BIS_APPLICATION_HANDLE *AppHandle, + IN OUT EFI_BIS_VERSION *InterfaceVersion, + IN EFI_BIS_DATA *TargetAddress + ); + +/** + Frees memory structures allocated and returned by other functions in the EFI_BIS protocol. + + @param AppHandle An opaque handle that identifies the caller¡¯s instance of initialization + of the BIS service. + @param ToFree An EFI_BIS_DATA* and associated memory block to be freed. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER The ToFree parameter is not or is no longer a memory resource + associated with this AppHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_FREE) ( + IN BIS_APPLICATION_HANDLE AppHandle, + IN EFI_BIS_DATA *ToFree + ); + +/** + Shuts down an application¡¯s instance of the BIS service, invalidating the application handle. After + this call, other BIS functions may no longer be invoked using the application handle value. + + @param AppHandle An opaque handle that identifies the caller¡¯s instance of initialization + of the BIS service. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_DEVICE_ERROR The function encountered an unexpected internal failure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_SHUTDOWN) ( + IN BIS_APPLICATION_HANDLE AppHandle + ); + +/** + Retrieves the certificate that has been configured as the identity of the organization designated as + the source of authorization for signatures of boot objects. + + @param AppHandle An opaque handle that identifies the caller¡¯s instance of initialization + of the BIS service. + @param Certificate The function writes an allocated EFI_BIS_DATA* containing the Boot + Object Authorization Certificate object. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_NOT_FOUND There is no Boot Object Authorization Certificate currently installed. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER The Certificate parameter supplied by the caller is NULL or + an invalid memory reference. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_CERTIFICATE) ( + IN BIS_APPLICATION_HANDLE AppHandle, + OUT EFI_BIS_DATA **Certificate + ); + +/** + Verifies the integrity and authorization of the indicated data object according to the + indicated credentials. + + @param AppHandle An opaque handle that identifies the caller¡¯s instance of initialization + of the BIS service. + @param Credentials A Signed Manifest containing verification information for the indicated + data object. + @param DataObject An in-memory copy of the raw data object to be verified. + @param IsVerified The function writes TRUE if the verification succeeded, otherwise + FALSE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_SECURITY_VIOLATION The signed manifest supplied as the Credentials parameter + was invalid (could not be parsed) or Platform-specific authorization failed, etc. + @retval EFI_DEVICE_ERROR An unexpected internal error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_VERIFY_BOOT_OBJECT) ( + IN BIS_APPLICATION_HANDLE AppHandle, + IN EFI_BIS_DATA *Credentials, + IN EFI_BIS_DATA *DataObject, + OUT BOOLEAN *IsVerified + ); + +/** + Retrieves the current status of the Boot Authorization Check Flag. + + @param AppHandle An opaque handle that identifies the caller¡¯s instance of initialization + of the BIS service. + @param CheckIsRequired The function writes the value TRUE if a Boot Authorization Check is + currently required on this platform, otherwise the function writes + FALSE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER The CheckIsRequired parameter supplied by the caller is + NULL or an invalid memory reference. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_CHECKFLAG) ( + IN BIS_APPLICATION_HANDLE AppHandle, + OUT BOOLEAN *CheckIsRequired + ); + +/** + Retrieves a unique token value to be included in the request credential for the next update of any + parameter in the Boot Object Authorization set + + @param AppHandle An opaque handle that identifies the caller¡¯s instance of initialization + of the BIS service. + @param UpdateToken The function writes an allocated EFI_BIS_DATA* containing the new + unique update token value. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER The UpdateToken parameter supplied by the caller is NULL or + an invalid memory reference. + @retval EFI_DEVICE_ERROR An unexpected internal error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_UPDATE_TOKEN) ( + IN BIS_APPLICATION_HANDLE AppHandle, + OUT EFI_BIS_DATA **UpdateToken + ); + +/** + Updates one of the configurable parameters of the Boot Object Authorization set. + + @param AppHandle An opaque handle that identifies the caller¡¯s instance of initialization + of the BIS service. + @param RequestCredential This is a Signed Manifest with embedded attributes that carry the details + of the requested update. + @param NewUpdateToken The function writes an allocated EFI_BIS_DATA* containing the new + unique update token value. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_SECURITY_VIOLATION The signed manifest supplied as the RequestCredential parameter + was invalid (could not be parsed) or Platform-specific authorization failed, etc. + @retval EFI_DEVICE_ERROR An unexpected internal error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_UPDATE_BOOT_OBJECT_AUTHORIZATION) ( + IN BIS_APPLICATION_HANDLE AppHandle, + IN EFI_BIS_DATA *RequestCredential, + OUT EFI_BIS_DATA **NewUpdateToken + ); + +/** + Verifies the integrity and authorization of the indicated data object according to the indicated + credentials and authority certificate. + + @param AppHandle An opaque handle that identifies the caller¡¯s instance of initialization + of the BIS service. + @param Credentials A Signed Manifest containing verification information for the + indicated data object. + @param DataObject An in-memory copy of the raw data object to be verified. + @param SectionName An ASCII (not Unicode) string giving the section name in the + manifest holding the verification information (in other words, + hash value) that corresponds to DataObject. + @param AuthorityCertificate A digital certificate whose public key must match the signer¡¯s + public key which is found in the credentials. + @param IsVerified The function writes TRUE if the verification was successful. + Otherwise, the function writes FALSE. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_SECURITY_VIOLATION The Credentials.Data supplied by the caller is NULL, + or the AuthorityCertificate supplied by the caller was + invalid (could not be parsed), + or Platform-specific authorization failed, etc. + @retval EFI_DEVICE_ERROR An unexpected internal error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_VERIFY_OBJECT_WITH_CREDENTIAL) ( + IN BIS_APPLICATION_HANDLE AppHandle, + IN EFI_BIS_DATA *Credentials, + IN EFI_BIS_DATA *DataObject, + IN EFI_BIS_DATA *SectionName, + IN EFI_BIS_DATA *AuthorityCertificate, + OUT BOOLEAN *IsVerified + ); + +/** + Retrieves a list of digital certificate identifier, digital signature algorithm, hash algorithm, and keylength + combinations that the platform supports. + + @param AppHandle An opaque handle that identifies the caller¡¯s instance of initialization + of the BIS service. + @param SignatureInfo The function writes an allocated EFI_BIS_DATA* containing the array + of EFI_BIS_SIGNATURE_INFO structures representing the supported + digital certificate identifier, algorithm, and key length combinations. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NO_MAPPING The AppHandle parameter is not or is no longer a valid + application instance handle associated with the EFI_BIS protocol. + @retval EFI_OUT_OF_RESOURCES The function failed due to lack of memory or other resources. + @retval EFI_INVALID_PARAMETER The SignatureInfo parameter supplied by the caller is NULL + or an invalid memory reference. + @retval EFI_DEVICE_ERROR An unexpected internal error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BIS_GET_SIGNATURE_INFO) ( + IN BIS_APPLICATION_HANDLE AppHandle, + OUT EFI_BIS_DATA **SignatureInfo + ); + +struct _EFI_BIS_PROTOCOL { + EFI_BIS_INITIALIZE Initialize; + EFI_BIS_SHUTDOWN Shutdown; + EFI_BIS_FREE Free; + EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_CERTIFICATE GetBootObjectAuthorizationCertificate; + EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_CHECKFLAG GetBootObjectAuthorizationCheckFlag; + EFI_BIS_GET_BOOT_OBJECT_AUTHORIZATION_UPDATE_TOKEN GetBootObjectAuthorizationUpdateToken; + EFI_BIS_GET_SIGNATURE_INFO GetSignatureInfo; + EFI_BIS_UPDATE_BOOT_OBJECT_AUTHORIZATION UpdateBootObjectAuthorization; + EFI_BIS_VERIFY_BOOT_OBJECT VerifyBootObject; + EFI_BIS_VERIFY_OBJECT_WITH_CREDENTIAL VerifyObjectWithCredential; +}; + +extern EFI_GUID gEfiBisProtocolGuid; +extern EFI_GUID gBootObjectAuthorizationParmsetGuid; + +#endif diff --git a/MdePkg/Include/Protocol/BlockIo.h b/MdePkg/Include/Protocol/BlockIo.h new file mode 100644 index 0000000000..4c7e8b4270 --- /dev/null +++ b/MdePkg/Include/Protocol/BlockIo.h @@ -0,0 +1,173 @@ +/** @file + Block IO protocol as defined in the EFI 1.0 specification. + + The Block IO protocol is used to abstract block devices like hard drives, + DVD-ROMs and floppy drives. + + Copyright (c) 2006, 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. + + Module Name: BlockIo.h + +**/ + +#ifndef __BLOCK_IO_H__ +#define __BLOCK_IO_H__ + +#define EFI_BLOCK_IO_PROTOCOL_GUID \ + { \ + 0x964e5b21, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_BLOCK_IO_PROTOCOL EFI_BLOCK_IO_PROTOCOL; + +/** + Reset the Block Device. + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could + not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_RESET) ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +/** + Read BufferSize bytes from Lba into Buffer. + + @param This Protocol instance pointer. + @param MediaId Id of the media, changes every time the media is replaced. + @param Lba The starting Logical Block Address to read from + @param BufferSize Size of Buffer, must be a multiple of device block size. + @param Buffer Buffer containing read data + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while performing the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHANGED The MediaId does not matched the current device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not + valid for the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_READ) ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +; + +/** + Write BufferSize bytes from Lba into Buffer. + + @param This Protocol instance pointer. + @param MediaId Id of the media, changes every time the media is replaced. + @param Lba The starting Logical Block Address to read from + @param BufferSize Size of Buffer, must be a multiple of device block size. + @param Buffer Buffer containing read data + + @retval EFI_SUCCESS The data was written correctly to the device. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device. + @retval EFI_INVALID_PARAMETER The write request contains a LBA that is not + valid for the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_WRITE) ( + IN EFI_BLOCK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN EFI_LBA Lba, + IN UINTN BufferSize, + IN VOID *Buffer + ) +; + +/** + Flush the Block Device. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS All outstanding data was written to the device + @retval EFI_DEVICE_ERROR The device reported an error while writting back the data + @retval EFI_NO_MEDIA There is no media in the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BLOCK_FLUSH) ( + IN EFI_BLOCK_IO_PROTOCOL *This + ) +; + +/** + Block IO read only mode data and updated only via members of BlockIO + +**/ +typedef struct { + UINT32 MediaId; ///< The curent media Id. If the media changes, this value is changed. + BOOLEAN RemovableMedia; ///< TRUE if the media is removable; otherwise, FALSE. + BOOLEAN MediaPresent; /**< TRUE if there is a media currently present in the device; + othersise, FALSE. THis field shows the media present status + as of the most recent ReadBlocks() or WriteBlocks() call. + **/ + BOOLEAN LogicalPartition; /**< TRUE if LBA 0 is the first block of a partition; otherwise + FALSE. For media with only one partition this would be TRUE. + **/ + BOOLEAN ReadOnly; /**< TRUE if the media is marked read-only otherwise, FALSE. + This field shows the read-only status as of the most recent WriteBlocks () call. + **/ + BOOLEAN WriteCaching; ///< TRUE if the WriteBlock () function caches write data. + + UINT32 BlockSize; /**< The intrinsic block size of the device. If the media changes, then + this field is updated. + **/ + UINT32 IoAlign; ///< Supplies the alignment requirement for any buffer to read or write block(s). + + EFI_LBA LastBlock; /**< The last logical block address on the device. + If the media changes, then this field is updated. + **/ +} EFI_BLOCK_IO_MEDIA; + +#define EFI_BLOCK_IO_PROTOCOL_REVISION 0x00010000 + +struct _EFI_BLOCK_IO_PROTOCOL { + UINT64 Revision; + + EFI_BLOCK_IO_MEDIA *Media; + + EFI_BLOCK_RESET Reset; + EFI_BLOCK_READ ReadBlocks; + EFI_BLOCK_WRITE WriteBlocks; + EFI_BLOCK_FLUSH FlushBlocks; + +}; + +extern EFI_GUID gEfiBlockIoProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/BootScriptSave.h b/MdePkg/Include/Protocol/BootScriptSave.h new file mode 100644 index 0000000000..496f79f012 --- /dev/null +++ b/MdePkg/Include/Protocol/BootScriptSave.h @@ -0,0 +1,110 @@ +/** @file + Definition of the Boot Script Save protocol. + + Copyright (c) 2006, 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. + + Module Name: BootScriptSave.h + + @par Revision Reference: + This protocol defined in the Boot Script Specification, Version 0.91. + +**/ + +#ifndef _BOOT_SCRIPT_SAVE_PROTOCOL_H +#define _BOOT_SCRIPT_SAVE_PROTOCOL_H + +// +// S3 Save Protocol GUID +// +#define EFI_BOOT_SCRIPT_SAVE_PROTOCOL_GUID \ + { \ + 0x470e1529, 0xb79e, 0x4e32, {0xa0, 0xfe, 0x6a, 0x15, 0x6d, 0x29, 0xf9, 0xb2 } \ + } + +typedef struct _EFI_BOOT_SCRIPT_SAVE_PROTOCOL EFI_BOOT_SCRIPT_SAVE_PROTOCOL; + +// +// Protocol Member_Function +// +/** + Adds a record into a specified Framework boot script table. + + @param This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance. + + @param TableName Name of the script table.Currently, the only meaningful + value is EFI_ACPI_S3_RESUME_SCRIPT_TABLE. + + @param OpCode The operation code (opcode) number. + + @param ... Argument list that is specific to each opcode. + + @retval EFI_SUCCESS The operation succeeded. A record was added into the specified script table. + + @retval EFI_INVALID_PARAMETER The parameter is illegal or the given boot script is not supported. + + @retval EFI_OUT_OF_RESOURCES There is insufficient memory to store the boot script. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BOOT_SCRIPT_WRITE) ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + IN UINT16 TableName, + IN UINT16 OpCode, + ... + ); + +/** + Closes the specified script table. + + @param This A pointer to the EFI_BOOT_SCRIPT_SAVE_PROTOCOL instance. + + @param TableName Name of the script table. + + @param Address A pointer to the physical address where the table begins. + + @retval EFI_SUCCESS The table was successfully returned. + + @retval EFI_NOT_FOUND The specified table was not created previously. + + @retval EFI_OUT_OF_RESOURCES Memory is insufficient to hold the reorganized boot script table. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BOOT_SCRIPT_CLOSE_TABLE) ( + IN EFI_BOOT_SCRIPT_SAVE_PROTOCOL *This, + IN UINT16 TableName, + OUT EFI_PHYSICAL_ADDRESS *Address + ); + +// +// S3 Save Protocol data structure +// +/** + @par Protocol Description: + The EFI_BOOT_SCRIPT_SAVE_PROTOCOL publishes the Framework boot script abstractions + to store or record various boot scripts into boot script tables. + + @param Write + Writes various boot scripts to a boot script table. + + @param CloseTable + Retrieves and closes a script table. + +**/ +struct _EFI_BOOT_SCRIPT_SAVE_PROTOCOL { + EFI_BOOT_SCRIPT_WRITE Write; + EFI_BOOT_SCRIPT_CLOSE_TABLE CloseTable; +}; + +extern EFI_GUID gEfiBootScriptSaveGuid; + +#endif diff --git a/MdePkg/Include/Protocol/BusSpecificDriverOverride.h b/MdePkg/Include/Protocol/BusSpecificDriverOverride.h new file mode 100644 index 0000000000..c446940567 --- /dev/null +++ b/MdePkg/Include/Protocol/BusSpecificDriverOverride.h @@ -0,0 +1,66 @@ +/** @file + Bus Specific Driver Override protocol as defined in the EFI 1.1 specification. + + Copyright (c) 2006, 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. + + Module Name: BusSpecificDriverOverride.h + +**/ + +#ifndef _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_H_ +#define _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_H_ + +// +// Global ID for the Bus Specific Driver Override Protocol +// +#define EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL_GUID \ + { \ + 0x3bc1b285, 0x8a15, 0x4a82, {0xaa, 0xbf, 0x4d, 0x7d, 0x13, 0xfb, 0x32, 0x65 } \ + } + +typedef struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL; + +// +// Prototypes for the Bus Specific Driver Override Protocol +// + +/** + Uses a bus specific algorithm to retrieve a driver image handle for a controller. + + @param This A pointer to the EFI_BUS_SPECIFIC_DRIVER_ + OVERRIDE_PROTOCOL instance. + @param DriverImageHandle On input, a pointer to the previous driver image handle returned + by GetDriver(). On output, a pointer to the next driver + image handle. Passing in a NULL, will return the first driver + image handle. + + @retval EFI_SUCCESS A bus specific override driver is returned in DriverImageHandle. + @retval EFI_NOT_FOUND The end of the list of override drivers was reached. + @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a + previous call to GetDriver(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_GET_DRIVER) ( + IN EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL *This, + IN OUT EFI_HANDLE *DriverImageHandle + ); + +// +// Interface structure for the Bus Specific Driver Override Protocol +// +struct _EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_PROTOCOL { + EFI_BUS_SPECIFIC_DRIVER_OVERRIDE_GET_DRIVER GetDriver; +}; + +extern EFI_GUID gEfiBusSpecificDriverOverrideProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/ComponentName.h b/MdePkg/Include/Protocol/ComponentName.h new file mode 100644 index 0000000000..68fd31ba8b --- /dev/null +++ b/MdePkg/Include/Protocol/ComponentName.h @@ -0,0 +1,123 @@ +/** @file + EFI Component Name Protocol + + Copyright (c) 2006, 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. + + Module Name: ComponentName.h + +**/ + +#ifndef __EFI_COMPONENT_NAME_H__ +#define __EFI_COMPONENT_NAME_H__ + +// +// Global ID for the Component Name Protocol +// +#define EFI_COMPONENT_NAME_PROTOCOL_GUID \ + { \ + 0x107a772c, 0xd5e1, 0x11d4, {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_COMPONENT_NAME_PROTOCOL EFI_COMPONENT_NAME_PROTOCOL; + + +/** + Retrieves a Unicode string that is the user readable name of the EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the driver name that that the caller + is requesting, and it must match one of the languages specified + in SupportedLanguages. The number of languages supported by a + driver is up to the driver writer. + @param DriverName A pointer to the Unicode string to return. This Unicode string + is the name of the driver specified by This in the language + specified by Language. + + @retval EFI_SUCCESS The Unicode string for the Driver specified by This + and the language specified by Language was returned + in DriverName. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER DriverName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_COMPONENT_NAME_GET_DRIVER_NAME) ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ); + + +/** + Retrieves a Unicode string that is the user readable name of the controller + that is being managed by an EFI Driver. + + @param This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance. + @param ControllerHandle The handle of a controller that the driver specified by + This is managing. This handle specifies the controller + whose name is to be returned. + @param ChildHandle The handle of the child controller to retrieve the name + of. This is an optional parameter that may be NULL. It + will be NULL for device drivers. It will also be NULL + for a bus drivers that wish to retrieve the name of the + bus controller. It will not be NULL for a bus driver + that wishes to retrieve the name of a child controller. + @param Language A pointer to a three character ISO 639-2 language + identifier. This is the language of the controller name + that that the caller is requesting, and it must match one + of the languages specified in SupportedLanguages. The + number of languages supported by a driver is up to the + driver writer. + @param ControllerName A pointer to the Unicode string to return. This Unicode + string is the name of the controller specified by + ControllerHandle and ChildHandle in the language specified + by Language from the point of view of the driver specified + by This. + + @retval EFI_SUCCESS The Unicode string for the user readable name in the + language specified by Language for the driver + specified by This was returned in DriverName. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ControllerName is NULL. + @retval EFI_UNSUPPORTED The driver specified by This is not currently managing + the controller specified by ControllerHandle and + ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ); + +// +// Interface structure for the Component Name Protocol +// +struct _EFI_COMPONENT_NAME_PROTOCOL { + EFI_COMPONENT_NAME_GET_DRIVER_NAME GetDriverName; + EFI_COMPONENT_NAME_GET_CONTROLLER_NAME GetControllerName; + CHAR8 *SupportedLanguages; +}; + +extern EFI_GUID gEfiComponentNameProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/CpuIo.h b/MdePkg/Include/Protocol/CpuIo.h new file mode 100644 index 0000000000..619878c042 --- /dev/null +++ b/MdePkg/Include/Protocol/CpuIo.h @@ -0,0 +1,131 @@ +/** @file + This code abstracts the CPU IO Protocol + + Copyright (c) 2006, 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. + + Module Name: CpuIO.h + + @par Revision Reference: + CPU IO Protocol is defined in Framework of EFI CPU IO Protocol Spec + Version 0.9 + +**/ + +#ifndef _CPUIO_H_ +#define _CPUIO_H_ + +#define EFI_CPU_IO_PROTOCOL_GUID \ + { \ + 0xB0732526, 0x38C8, 0x4b40, {0x88, 0x77, 0x61, 0xC7, 0xB0, 0x6A, 0xAC, 0x45 } \ + } + +typedef struct _EFI_CPU_IO_PROTOCOL EFI_CPU_IO_PROTOCOL; + +// +// ******************************************************* +// EFI_CPU_IO_PROTOCOL_WIDTH +// ******************************************************* +// +typedef enum { + EfiCpuIoWidthUint8, + EfiCpuIoWidthUint16, + EfiCpuIoWidthUint32, + EfiCpuIoWidthUint64, + EfiCpuIoWidthFifoUint8, + EfiCpuIoWidthFifoUint16, + EfiCpuIoWidthFifoUint32, + EfiCpuIoWidthFifoUint64, + EfiCpuIoWidthFillUint8, + EfiCpuIoWidthFillUint16, + EfiCpuIoWidthFillUint32, + EfiCpuIoWidthFillUint64, + EfiCpuIoWidthMaximum +} EFI_CPU_IO_PROTOCOL_WIDTH; + +// +// ******************************************************* +// EFI_CPU_IO_PROTOCOL_IO_MEM +// ******************************************************* +// +/** + Enables a driver to access memory-mapped registers in the EFI system memory space. + Or, Enables a driver to access registers in the EFI CPU I/O space. + + @param This A pointer to the EFI_CPU_IO_PROTOCOL instance. + + @param Width Signifies the width of the I/O or Memory operation. + + @param Address The base address of the I/O or Memoryoperation. + + @param Count The number of I/O or Memory operations to perform. + The number of bytes moved is Width size * Count, starting at Address. + + @param Buffer For read operations, the destination buffer to store the results. + For write operations, the source buffer from which to write data. + + @retval EFI_SUCCESS The data was read from or written to the EFI system. + + @retval EFI_INVALID_PARAMETER Width is invalid for this EFI system.Or Buffer is NULL. + + @retval EFI_UNSUPPORTED The Buffer is not aligned for the given Width. + Or,The address range specified by Address, Width, and Count is not valid for this EFI system. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CPU_IO_PROTOCOL_IO_MEM) ( + IN EFI_CPU_IO_PROTOCOL *This, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +// +// ******************************************************* +// EFI_CPU_IO_PROTOCOL_ACCESS +// ******************************************************* +// +typedef struct { + EFI_CPU_IO_PROTOCOL_IO_MEM Read; + EFI_CPU_IO_PROTOCOL_IO_MEM Write; +} EFI_CPU_IO_PROTOCOL_ACCESS; + +// +// ******************************************************* +// EFI_CPU_IO_PROTOCOL +// ******************************************************* +// +/** + @par Protocol Description: + Provides the basic memory and I/O interfaces that are used to abstract + accesses to devices in a system. + + @param Mem.Read + Allows reads from memory-mapped I/O space. + + @param Mem.Write + Allows writes to memory-mapped I/O space. + + @param Io.Read + Allows reads from I/O space. + + @param Io.Write + Allows writes to I/O space. + +**/ +struct _EFI_CPU_IO_PROTOCOL { + EFI_CPU_IO_PROTOCOL_ACCESS Mem; + EFI_CPU_IO_PROTOCOL_ACCESS Io; +}; + +extern EFI_GUID gEfiCpuIoProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/DataHub.h b/MdePkg/Include/Protocol/DataHub.h new file mode 100644 index 0000000000..15d3cc618e --- /dev/null +++ b/MdePkg/Include/Protocol/DataHub.h @@ -0,0 +1,233 @@ +/** @file + The data hub protocol is used both by agents wishing to log + data and those wishing to be made aware of all information that + has been logged. + + For more information please look at Intel Platform Innovation + Framework for EFI Data Hub Specification. + + Copyright (c) 2006, 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. + + Module Name: DataHub.h + + @par Revision Reference: + This protocol is defined in Framework for EFI Data Hub Specification. + Version 0.9. + +**/ + +#ifndef __DATA_HUB_H__ +#define __DATA_HUB_H__ + +#define EFI_DATA_HUB_PROTOCOL_GUID \ + { \ + 0xae80d021, 0x618e, 0x11d4, {0xbc, 0xd7, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \ + } + +// +// EFI generic Data Hub Header +// +// A Data Record is an EFI_DATA_RECORD_HEADER followed by RecordSize bytes of +// data. The format of the data is defined by the DataRecordGuid. +// +// If EFI_DATA_RECORD_HEADER is extended in the future the Version number must +// change and the HeaderSize will change if the definition of +// EFI_DATA_RECORD_HEADER is extended. +// +// The logger is responcible for initializing: +// Version, HeaderSize, RecordSize, DataRecordGuid, DataRecordClass +// +// The Data Hub driver is responcible for initializing: +// LogTime and LogMonotonicCount. +// +#define EFI_DATA_RECORD_HEADER_VERSION 0x0100 +typedef struct { + UINT16 Version; + UINT16 HeaderSize; + UINT32 RecordSize; + EFI_GUID DataRecordGuid; + EFI_GUID ProducerName; + UINT64 DataRecordClass; + EFI_TIME LogTime; + UINT64 LogMonotonicCount; +} EFI_DATA_RECORD_HEADER; + +// +// Definition of DataRecordClass. These are used to filter out class types +// at a very high level. The DataRecordGuid still defines the format of +// the data. See DateHub.doc for rules on what can and can not be a +// new DataRecordClass +// +#define EFI_DATA_RECORD_CLASS_DEBUG 0x0000000000000001 +#define EFI_DATA_RECORD_CLASS_ERROR 0x0000000000000002 +#define EFI_DATA_RECORD_CLASS_DATA 0x0000000000000004 +#define EFI_DATA_RECORD_CLASS_PROGRESS_CODE 0x0000000000000008 + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_DATA_HUB_PROTOCOL EFI_DATA_HUB_PROTOCOL; + +/** + Logs a data record to the system event log. + + @param This The EFI_DATA_HUB_PROTOCOL instance. + + @param description + + @param DataRecordGuid A GUID that indicates the format of the data passed into RawData. + + @param ProducerName A GUID that indicates the identity of the caller to this API. + + @param DataRecordClass This class indicates the generic type of the data record. + + @param RawData The DataRecordGuid-defined data to be logged. + + @param RawDataSize The size in bytes of RawData. + + @retval EFI_SUCCESS Data was logged. + + @retval EFI_OUT_OF_RESOURCES Data was not logged due to lack of system resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DATA_HUB_LOG_DATA) ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_GUID *DataRecordGuid, + IN EFI_GUID *ProducerName, + IN UINT64 DataRecordClass, + IN VOID *RawData, + IN UINT32 RawDataSize + ); + +/** + Allows the system data log to be searched. + + @param This The EFI_DATA_HUB_PROTOCOL instance. + + @param MonotonicCount On input, it specifies the Record to return. + An input of zero means to return the first record. + + @param FilterDriver If FilterDriver is not passed in a MonotonicCount of zero, + it means to return the first data record. If FilterDriver is passed in, + then a MonotonicCount of zero means to return the first data not yet read + by FilterDriver. + + @param Record Returns a dynamically allocated memory buffer with a data + record that matches MonotonicCount. + + @retval EFI_SUCCESS Data was returned in Record. + + @retval EFI_INVALID_PARAMETER FilterDriver was passed in but does not exist. + + @retval EFI_NOT_FOUND MonotonicCount does not match any data record + in the system. If a MonotonicCount of zero was passed in, then no + data records exist in the system. + + @retval EFI_OUT_OF_RESOURCES Record was not returned due to lack + of system resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DATA_HUB_GET_NEXT_RECORD) ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN OUT UINT64 *MonotonicCount, + IN EFI_EVENT *FilterDriver OPTIONAL, + OUT EFI_DATA_RECORD_HEADER **Record + ); + +/** + Registers an event to be signaled every time a data record is logged in the system. + + @param This The EFI_DATA_HUB_PROTOCOL instance. + + @param FilterEvent The EFI_EVENT to signal whenever data that matches + FilterClass is logged in the system. + + @param FilterTpl The maximum EFI_TPL at which FilterEvent can be signaled. + It is strongly recommended that you use the lowest EFI_TPL possible. + + @param FilterClass FilterEvent will be signaled whenever a bit + in EFI_DATA_RECORD_HEADER.DataRecordClass is also set in FilterClass. + If FilterClass is zero, no class-based filtering will be performed. + + @param FilterDataRecordGuid FilterEvent will be signaled whenever + FilterDataRecordGuid matches EFI_DATA_RECORD_HEADER.DataRecordGuid. + If FilterDataRecordGuid is NULL, then no GUID-based filtering will be performed. + + @retval EFI_SUCCESS The filter driver event was registered + + @retval EFI_ALREADY_STARTED FilterEvent was previously registered and cannot be registered again. + + @retval EFI_OUT_OF_RESOURCES The filter driver event was not registered + due to lack of system resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DATA_HUB_REGISTER_FILTER_DRIVER) ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_EVENT FilterEvent, + IN EFI_TPL FilterTpl, + IN UINT64 FilterClass, + IN EFI_GUID *FilterDataRecordGuid OPTIONAL + ); + +/** + Stops a filter driver from being notified when data records are logged. + + @param This The EFI_DATA_HUB_PROTOCOL instance. + + @param FilterEvent The EFI_EVENT to remove from the list of events to be + signaled every time errors are logged. + + @retval EFI_SUCCESS The filter driver represented by FilterEvent was shut off. + + @retval EFI_NOT_FOUND FilterEvent did not exist. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DATA_HUB_UNREGISTER_FILTER_DRIVER) ( + IN EFI_DATA_HUB_PROTOCOL *This, + IN EFI_EVENT FilterEvent + ); + +/** + @par Protocol Description: + This protocol is used to log information and register filter drivers + to receive data records. + + @param LogData + Logs a data record. + + @param GetNextDataRecord + Gets a data record. Used both to view the memory-based log and to + get information about which data records have been consumed by a filter driver. + + @param RegisterFilterDriver + Allows the registration of an EFI event to act as a filter driver for all data records that are logged. + + @param UnregisterFilterDriver + Used to remove a filter driver that was added with RegisterFilterDriver(). + +**/ +struct _EFI_DATA_HUB_PROTOCOL { + EFI_DATA_HUB_LOG_DATA LogData; + EFI_DATA_HUB_GET_NEXT_RECORD GetNextRecord; + EFI_DATA_HUB_REGISTER_FILTER_DRIVER RegisterFilterDriver; + EFI_DATA_HUB_UNREGISTER_FILTER_DRIVER UnregisterFilterDriver; +}; + +extern EFI_GUID gEfiDataHubProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/DebugPort.h b/MdePkg/Include/Protocol/DebugPort.h new file mode 100644 index 0000000000..ceffaf6954 --- /dev/null +++ b/MdePkg/Include/Protocol/DebugPort.h @@ -0,0 +1,141 @@ +/** @file + Copyright (c) 2006, 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. + + Module Name: DebugPort.h + +**/ + +#ifndef __DEBUG_PORT_H__ +#define __DEBUG_PORT_H__ + + +// +// DebugPortIo protocol {EBA4E8D2-3858-41EC-A281-2647BA9660D0} +// +#define EFI_DEBUGPORT_PROTOCOL_GUID \ + { \ + 0xEBA4E8D2, 0x3858, 0x41EC, {0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 } \ + } + +extern EFI_GUID gEfiDebugPortProtocolGuid; + +typedef struct _EFI_DEBUGPORT_PROTOCOL EFI_DEBUGPORT_PROTOCOL; + +// +// DebugPort member functions +// + +/** + Resets the debugport. + + @param This A pointer to the EFI_DEBUGPORT_PROTOCOL instance. + + @retval EFI_SUCCESS The debugport device was reset and is in usable state. + @retval EFI_DEVICE_ERROR The debugport device could not be reset and is unusable. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_RESET) ( + IN EFI_DEBUGPORT_PROTOCOL *This + ); + +/** + Writes data to the debugport. + + @param This A pointer to the EFI_DEBUGPORT_PROTOCOL instance. + @param Timeout The number of microseconds to wait before timing out a write operation. + @param BufferSize On input, the requested number of bytes of data to write. On output, the + number of bytes of data actually written. + @param Buffer A pointer to a buffer containing the data to write. + + @retval EFI_SUCCESS The data was written. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_WRITE) ( + IN EFI_DEBUGPORT_PROTOCOL *This, + IN UINT32 Timeout, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ); + +/** + Reads data from the debugport. + + @param This A pointer to the EFI_DEBUGPORT_PROTOCOL instance. + @param Timeout The number of microseconds to wait before timing out a read operation. + @param BufferSize On input, the requested number of bytes of data to read. On output, the + number of bytes of data actually number of bytes + of data read and returned in Buffer. + @param Buffer A pointer to a buffer into which the data read will be saved. + + @retval EFI_SUCCESS The data was read. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The operation was stopped due to a timeout or overrun. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_READ) ( + IN EFI_DEBUGPORT_PROTOCOL *This, + IN UINT32 Timeout, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Checks to see if any data is available to be read from the debugport device. + + @param This A pointer to the EFI_DEBUGPORT_PROTOCOL instance. + + @retval EFI_SUCCESS At least one byte of data is available to be read. + @retval EFI_DEVICE_ERROR The debugport device is not functioning correctly. + @retval EFI_NOT_READY No data is available to be read. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEBUGPORT_POLL) ( + IN EFI_DEBUGPORT_PROTOCOL *This + ); + +// +// DebugPort protocol definition +// +struct _EFI_DEBUGPORT_PROTOCOL { + EFI_DEBUGPORT_RESET Reset; + EFI_DEBUGPORT_WRITE Write; + EFI_DEBUGPORT_READ Read; + EFI_DEBUGPORT_POLL Poll; +}; + +// +// DEBUGPORT variable definitions... +// +#define EFI_DEBUGPORT_VARIABLE_NAME L"DEBUGPORT" +#define EFI_DEBUGPORT_VARIABLE_GUID EFI_DEBUGPORT_PROTOCOL_GUID +#define gEfiDebugPortVariableGuid gEfiDebugPortProtocolGuid + +// +// DebugPort device path definitions... +// +#define DEVICE_PATH_MESSAGING_DEBUGPORT EFI_DEBUGPORT_PROTOCOL_GUID +#define gEfiDebugPortDevicePathGuid gEfiDebugPortProtocolGuid + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; +} DEBUGPORT_DEVICE_PATH; + +#endif diff --git a/MdePkg/Include/Protocol/DebugSupport.h b/MdePkg/Include/Protocol/DebugSupport.h new file mode 100644 index 0000000000..1b782cf6a5 --- /dev/null +++ b/MdePkg/Include/Protocol/DebugSupport.h @@ -0,0 +1,517 @@ +/** @file + DebugSupport protocol and supporting definitions as defined in the EFI 1.1 + specification. + + The DebugSupport protocol is used by source level debuggers to abstract the + processor and handle context save and restore operations. + + Copyright (c) 2006, 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. + + Module Name: DebugSupport.h + +**/ + +#ifndef __DEBUG_SUPPORT_H__ +#define __DEBUG_SUPPORT_H__ + +typedef struct _EFI_DEBUG_SUPPORT_PROTOCOL EFI_DEBUG_SUPPORT_PROTOCOL; + +// +// Debug Support protocol {2755590C-6F3C-42FA-9EA4-A3BA543CDA25} +// +#define EFI_DEBUG_SUPPORT_PROTOCOL_GUID \ + { \ + 0x2755590C, 0x6F3C, 0x42FA, {0x9E, 0xA4, 0xA3, 0xBA, 0x54, 0x3C, 0xDA, 0x25 } \ + } + +// +// Debug Support definitions +// +typedef INTN EFI_EXCEPTION_TYPE; + +// +// IA-32 processor exception types +// +#define EXCEPT_IA32_DIVIDE_ERROR 0 +#define EXCEPT_IA32_DEBUG 1 +#define EXCEPT_IA32_NMI 2 +#define EXCEPT_IA32_BREAKPOINT 3 +#define EXCEPT_IA32_OVERFLOW 4 +#define EXCEPT_IA32_BOUND 5 +#define EXCEPT_IA32_INVALID_OPCODE 6 +#define EXCEPT_IA32_DOUBLE_FAULT 8 +#define EXCEPT_IA32_INVALID_TSS 10 +#define EXCEPT_IA32_SEG_NOT_PRESENT 11 +#define EXCEPT_IA32_STACK_FAULT 12 +#define EXCEPT_IA32_GP_FAULT 13 +#define EXCEPT_IA32_PAGE_FAULT 14 +#define EXCEPT_IA32_FP_ERROR 16 +#define EXCEPT_IA32_ALIGNMENT_CHECK 17 +#define EXCEPT_IA32_MACHINE_CHECK 18 +#define EXCEPT_IA32_SIMD 19 + +// +// IA-32 processor context definition +// +// +// FXSAVE_STATE +// FP / MMX / XMM registers (see fxrstor instruction definition) +// +typedef struct { + UINT16 Fcw; + UINT16 Fsw; + UINT16 Ftw; + UINT16 Opcode; + UINT32 Eip; + UINT16 Cs; + UINT16 Reserved1; + UINT32 DataOffset; + UINT16 Ds; + UINT8 Reserved2[10]; + UINT8 St0Mm0[10], Reserved3[6]; + UINT8 St0Mm1[10], Reserved4[6]; + UINT8 St0Mm2[10], Reserved5[6]; + UINT8 St0Mm3[10], Reserved6[6]; + UINT8 St0Mm4[10], Reserved7[6]; + UINT8 St0Mm5[10], Reserved8[6]; + UINT8 St0Mm6[10], Reserved9[6]; + UINT8 St0Mm7[10], Reserved10[6]; + UINT8 Reserved11[22 * 16]; +} EFI_FX_SAVE_STATE_IA32; + +typedef struct { + UINT32 ExceptionData; + EFI_FX_SAVE_STATE_IA32 FxSaveState; + UINT32 Dr0; + UINT32 Dr1; + UINT32 Dr2; + UINT32 Dr3; + UINT32 Dr6; + UINT32 Dr7; + UINT32 Cr0; + UINT32 Cr1; + UINT32 Cr2; + UINT32 Cr3; + UINT32 Cr4; + UINT32 Eflags; + UINT32 Ldtr; + UINT32 Tr; + UINT32 Gdtr[2]; + UINT32 Idtr[2]; + UINT32 Eip; + UINT32 Gs; + UINT32 Fs; + UINT32 Es; + UINT32 Ds; + UINT32 Cs; + UINT32 Ss; + UINT32 Edi; + UINT32 Esi; + UINT32 Ebp; + UINT32 Esp; + UINT32 Ebx; + UINT32 Edx; + UINT32 Ecx; + UINT32 Eax; +} EFI_SYSTEM_CONTEXT_IA32; + +// +// IPF processor exception types +// +#define EXCEPT_IPF_VHTP_TRANSLATION 0 +#define EXCEPT_IPF_INSTRUCTION_TLB 1 +#define EXCEPT_IPF_DATA_TLB 2 +#define EXCEPT_IPF_ALT_INSTRUCTION_TLB 3 +#define EXCEPT_IPF_ALT_DATA_TLB 4 +#define EXCEPT_IPF_DATA_NESTED_TLB 5 +#define EXCEPT_IPF_INSTRUCTION_KEY_MISSED 6 +#define EXCEPT_IPF_DATA_KEY_MISSED 7 +#define EXCEPT_IPF_DIRTY_BIT 8 +#define EXCEPT_IPF_INSTRUCTION_ACCESS_BIT 9 +#define EXCEPT_IPF_DATA_ACCESS_BIT 10 +#define EXCEPT_IPF_BREAKPOINT 11 +#define EXCEPT_IPF_EXTERNAL_INTERRUPT 12 +// +// 13 - 19 reserved +// +#define EXCEPT_IPF_PAGE_NOT_PRESENT 20 +#define EXCEPT_IPF_KEY_PERMISSION 21 +#define EXCEPT_IPF_INSTRUCTION_ACCESS_RIGHTS 22 +#define EXCEPT_IPF_DATA_ACCESS_RIGHTS 23 +#define EXCEPT_IPF_GENERAL_EXCEPTION 24 +#define EXCEPT_IPF_DISABLED_FP_REGISTER 25 +#define EXCEPT_IPF_NAT_CONSUMPTION 26 +#define EXCEPT_IPF_SPECULATION 27 +// +// 28 reserved +// +#define EXCEPT_IPF_DEBUG 29 +#define EXCEPT_IPF_UNALIGNED_REFERENCE 30 +#define EXCEPT_IPF_UNSUPPORTED_DATA_REFERENCE 31 +#define EXCEPT_IPF_FP_FAULT 32 +#define EXCEPT_IPF_FP_TRAP 33 +#define EXCEPT_IPF_LOWER_PRIVILEGE_TRANSFER_TRAP 34 +#define EXCEPT_IPF_TAKEN_BRANCH 35 +#define EXCEPT_IPF_SINGLE_STEP 36 +// +// 37 - 44 reserved +// +#define EXCEPT_IPF_IA32_EXCEPTION 45 +#define EXCEPT_IPF_IA32_INTERCEPT 46 +#define EXCEPT_IPF_IA32_INTERRUPT 47 + +// +// IPF processor context definition +// +typedef struct { + // + // The first reserved field is necessary to preserve alignment for the correct + // bits in UNAT and to insure F2 is 16 byte aligned.. + // + UINT64 Reserved; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 R8; + UINT64 R9; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; + UINT64 R16; + UINT64 R17; + UINT64 R18; + UINT64 R19; + UINT64 R20; + UINT64 R21; + UINT64 R22; + UINT64 R23; + UINT64 R24; + UINT64 R25; + UINT64 R26; + UINT64 R27; + UINT64 R28; + UINT64 R29; + UINT64 R30; + UINT64 R31; + + UINT64 F2[2]; + UINT64 F3[2]; + UINT64 F4[2]; + UINT64 F5[2]; + UINT64 F6[2]; + UINT64 F7[2]; + UINT64 F8[2]; + UINT64 F9[2]; + UINT64 F10[2]; + UINT64 F11[2]; + UINT64 F12[2]; + UINT64 F13[2]; + UINT64 F14[2]; + UINT64 F15[2]; + UINT64 F16[2]; + UINT64 F17[2]; + UINT64 F18[2]; + UINT64 F19[2]; + UINT64 F20[2]; + UINT64 F21[2]; + UINT64 F22[2]; + UINT64 F23[2]; + UINT64 F24[2]; + UINT64 F25[2]; + UINT64 F26[2]; + UINT64 F27[2]; + UINT64 F28[2]; + UINT64 F29[2]; + UINT64 F30[2]; + UINT64 F31[2]; + + UINT64 Pr; + + UINT64 B0; + UINT64 B1; + UINT64 B2; + UINT64 B3; + UINT64 B4; + UINT64 B5; + UINT64 B6; + UINT64 B7; + + // + // application registers + // + UINT64 ArRsc; + UINT64 ArBsp; + UINT64 ArBspstore; + UINT64 ArRnat; + + UINT64 ArFcr; + + UINT64 ArEflag; + UINT64 ArCsd; + UINT64 ArSsd; + UINT64 ArCflg; + UINT64 ArFsr; + UINT64 ArFir; + UINT64 ArFdr; + + UINT64 ArCcv; + + UINT64 ArUnat; + + UINT64 ArFpsr; + + UINT64 ArPfs; + UINT64 ArLc; + UINT64 ArEc; + + // + // control registers + // + UINT64 CrDcr; + UINT64 CrItm; + UINT64 CrIva; + UINT64 CrPta; + UINT64 CrIpsr; + UINT64 CrIsr; + UINT64 CrIip; + UINT64 CrIfa; + UINT64 CrItir; + UINT64 CrIipa; + UINT64 CrIfs; + UINT64 CrIim; + UINT64 CrIha; + + // + // debug registers + // + UINT64 Dbr0; + UINT64 Dbr1; + UINT64 Dbr2; + UINT64 Dbr3; + UINT64 Dbr4; + UINT64 Dbr5; + UINT64 Dbr6; + UINT64 Dbr7; + + UINT64 Ibr0; + UINT64 Ibr1; + UINT64 Ibr2; + UINT64 Ibr3; + UINT64 Ibr4; + UINT64 Ibr5; + UINT64 Ibr6; + UINT64 Ibr7; + + // + // virtual registers - nat bits for R1-R31 + // + UINT64 IntNat; + +} EFI_SYSTEM_CONTEXT_IPF; + +// +// EBC processor exception types +// +#define EXCEPT_EBC_UNDEFINED 0 +#define EXCEPT_EBC_DIVIDE_ERROR 1 +#define EXCEPT_EBC_DEBUG 2 +#define EXCEPT_EBC_BREAKPOINT 3 +#define EXCEPT_EBC_OVERFLOW 4 +#define EXCEPT_EBC_INVALID_OPCODE 5 // opcode out of range +#define EXCEPT_EBC_STACK_FAULT 6 +#define EXCEPT_EBC_ALIGNMENT_CHECK 7 +#define EXCEPT_EBC_INSTRUCTION_ENCODING 8 // malformed instruction +#define EXCEPT_EBC_BAD_BREAK 9 // BREAK 0 or undefined BREAK +#define EXCEPT_EBC_STEP 10 // to support debug stepping +// +// For coding convenience, define the maximum valid EBC exception. +// +#define MAX_EBC_EXCEPTION EXCEPT_EBC_STEP + +// +// EBC processor context definition +// +typedef struct { + UINT64 R0; + UINT64 R1; + UINT64 R2; + UINT64 R3; + UINT64 R4; + UINT64 R5; + UINT64 R6; + UINT64 R7; + UINT64 Flags; + UINT64 ControlFlags; + UINT64 Ip; +} EFI_SYSTEM_CONTEXT_EBC; + +// +// Universal EFI_SYSTEM_CONTEXT definition +// +typedef union { + EFI_SYSTEM_CONTEXT_EBC *SystemContextEbc; + EFI_SYSTEM_CONTEXT_IA32 *SystemContextIa32; + EFI_SYSTEM_CONTEXT_IPF *SystemContextIpf; +} EFI_SYSTEM_CONTEXT; + +// +// DebugSupport callback function prototypes +// + +/** + Registers and enables an exception callback function for the specified exception. + + @param ExceptionType Exception types in EBC, IA-32, X64, or IPF + @param SystemContext Exception content. + +**/ +typedef +VOID +(*EFI_EXCEPTION_CALLBACK) ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + +/** + Registers and enables the on-target debug agent¡¯s periodic entry point. + + @param SystemContext Exception content. + +**/ +typedef +VOID +(*EFI_PERIODIC_CALLBACK) ( + IN OUT EFI_SYSTEM_CONTEXT SystemContext + ); + +// +// Machine type definition +// +typedef enum { + IsaIa32 = IMAGE_FILE_MACHINE_I386, // 0x014C + IsaX64 = IMAGE_FILE_MACHINE_X64, // 0x8664 + IsaIpf = IMAGE_FILE_MACHINE_IA64, // 0x0200 + IsaEbc = IMAGE_FILE_MACHINE_EBC // 0x0EBC +} EFI_INSTRUCTION_SET_ARCHITECTURE; + + +// +// DebugSupport member function definitions +// + +/** + Returns the maximum value that may be used for the ProcessorIndex parameter in + RegisterPeriodicCallback() and RegisterExceptionCallback(). + + @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance. + @param MaxProcessorIndex Pointer to a caller-allocated UINTN in which the maximum supported + processor index is returned. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MAXIMUM_PROCESSOR_INDEX) ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + OUT UINTN *MaxProcessorIndex + ); + +/** + Registers a function to be called back periodically in interrupt context. + + @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance. + @param ProcessorIndex Specifies which processor the callback function applies to. + @param PeriodicCallback A pointer to a function of type PERIODIC_CALLBACK that is the main + periodic entry point of the debug agent. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback + function was previously registered. + @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback + function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_PERIODIC_CALLBACK) ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_PERIODIC_CALLBACK PeriodicCallback + ); + +/** + Registers a function to be called when a given processor exception occurs. + + @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance. + @param ProcessorIndex Specifies which processor the callback function applies to. + @param PeriodicCallback A pointer to a function of type EXCEPTION_CALLBACK that is called + when the processor exception specified by ExceptionType occurs. + @param ExceptionType Specifies which processor exception to hook. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_ALREADY_STARTED Non-NULL PeriodicCallback parameter when a callback + function was previously registered. + @retval EFI_OUT_OF_RESOURCES System has insufficient memory resources to register new callback + function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_EXCEPTION_CALLBACK) ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN EFI_EXCEPTION_CALLBACK ExceptionCallback, + IN EFI_EXCEPTION_TYPE ExceptionType + ); + +/** + Invalidates processor instruction cache for a memory range. Subsequent execution in this range + causes a fresh memory fetch to retrieve code to be executed. + + @param This A pointer to the EFI_DEBUG_SUPPORT_PROTOCOL instance. + @param ProcessorIndex Specifies which processor¡¯s instruction cache is to be invalidated. + @param Start Specifies the physical base of the memory range to be invalidated. + @param Length Specifies the minimum number of bytes in the processor¡¯s instruction + cache to invalidate. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INVALIDATE_INSTRUCTION_CACHE) ( + IN EFI_DEBUG_SUPPORT_PROTOCOL *This, + IN UINTN ProcessorIndex, + IN VOID *Start, + IN UINT64 Length + ); + +// +// DebugSupport protocol definition +// +struct _EFI_DEBUG_SUPPORT_PROTOCOL { + EFI_INSTRUCTION_SET_ARCHITECTURE Isa; + EFI_GET_MAXIMUM_PROCESSOR_INDEX GetMaximumProcessorIndex; + EFI_REGISTER_PERIODIC_CALLBACK RegisterPeriodicCallback; + EFI_REGISTER_EXCEPTION_CALLBACK RegisterExceptionCallback; + EFI_INVALIDATE_INSTRUCTION_CACHE InvalidateInstructionCache; +}; + +extern EFI_GUID gEfiDebugSupportProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Decompress.h b/MdePkg/Include/Protocol/Decompress.h new file mode 100644 index 0000000000..7c295f310e --- /dev/null +++ b/MdePkg/Include/Protocol/Decompress.h @@ -0,0 +1,121 @@ +/** @file + The Decompress Protocol Interface + + Copyright (c) 2006, 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. + + Module Name: Decompress.h + +**/ + +#ifndef __DECOMPRESS_H__ +#define __DECOMPRESS_H__ + +#define EFI_DECOMPRESS_PROTOCOL_GUID \ + { \ + 0xd8117cfe, 0x94a6, 0x11d4, {0x9a, 0x3a, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_DECOMPRESS_PROTOCOL EFI_DECOMPRESS_PROTOCOL; + +/** + The GetInfo() function retrieves the size of the uncompressed buffer + and the temporary scratch buffer required to decompress the buffer + specified by Source and SourceSize. If the size of the uncompressed + buffer or the size of the scratch buffer cannot be determined from + the compressed data specified by Source and SourceData, then + EFI_INVALID_PARAMETER is returned. Otherwise, the size of the uncompressed + buffer is returned in DestinationSize, the size of the scratch buffer is + returned in ScratchSize, and EFI_SUCCESS is returned. + + The GetInfo() function does not have scratch buffer available to perform + a thorough checking of the validity of the source data. It just retrieves + the 'Original Size' field from the beginning bytes of the source data and + output it as DestinationSize. And ScratchSize is specific to the decompression + implementation. + + @param This The protocol instance pointer + @param Source The source buffer containing the compressed data. + @param SourceSize The size, in bytes, of source buffer. + @param DestinationSize A pointer to the size, in bytes, of the uncompressed buffer + that will be generated when the compressed buffer specified + by Source and SourceSize is decompressed. + @param ScratchSize A pointer to the size, in bytes, of the scratch buffer that + is required to decompress the compressed buffer specified by + Source and SourceSize. + + @retval EFI_SUCCESS The size of the uncompressed data was returned in DestinationSize + and the size of the scratch buffer was returned in ScratchSize. + @retval EFI_INVALID_PARAMETER The size of the uncompressed data or the size of the scratch + buffer cannot be determined from the compressed data specified by + Source and SourceData. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DECOMPRESS_GET_INFO) ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ); + +/** + The Decompress() function extracts decompressed data to its original form. + + This protocol is designed so that the decompression algorithm can be + implemented without using any memory services. As a result, the + Decompress() function is not allowed to call AllocatePool() or + AllocatePages() in its implementation. It is the caller's responsibility + to allocate and free the Destination and Scratch buffers. + + If the compressed source data specified by Source and SourceSize is + sucessfully decompressed into Destination, then EFI_SUCCESS is returned. + If the compressed source data specified by Source and SourceSize is not in + a valid compressed data format, then EFI_INVALID_PARAMETER is returned. + + @param This The protocol instance pointer + @param Source The source buffer containing the compressed data. + @param SourceSize The size of source data. + @param Destination On output, the destination buffer that contains + the uncompressed data. + @param DestinationSize The size of destination buffer. The size of destination + buffer needed is obtained from GetInfo(). + @param Scratch A temporary scratch buffer that is used to perform the + decompression. + @param ScratchSize The size of scratch buffer. The size of scratch buffer needed + is obtained from GetInfo(). + + @retval EFI_SUCCESS Decompression completed successfully, and the uncompressed + buffer is returned in Destination. + @retval EFI_INVALID_PARAMETER The source buffer specified by Source and SourceSize is + corrupted (not in a valid compressed format). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DECOMPRESS_DECOMPRESS) ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SourceSize, + IN OUT VOID *Destination, + IN UINT32 DestinationSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +struct _EFI_DECOMPRESS_PROTOCOL { + EFI_DECOMPRESS_GET_INFO GetInfo; + EFI_DECOMPRESS_DECOMPRESS Decompress; +}; + +extern EFI_GUID gEfiDecompressProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/DeviceIo.h b/MdePkg/Include/Protocol/DeviceIo.h new file mode 100644 index 0000000000..0d70632fd9 --- /dev/null +++ b/MdePkg/Include/Protocol/DeviceIo.h @@ -0,0 +1,222 @@ +/** @file + Device IO protocol as defined in the EFI 1.0 specification. + + Device IO is used to abstract hardware access to devices. It includes + memory mapped IO, IO, PCI Config space, and DMA. + + Copyright (c) 2006, 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. + + Module Name: DeviceIo.h + +**/ + +#ifndef __DEVICE_IO_H__ +#define __DEVICE_IO_H__ + +#define EFI_DEVICE_IO_PROTOCOL_GUID \ + { \ + 0xaf6ac311, 0x84c3, 0x11d2, {0x8e, 0x3c, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct _EFI_DEVICE_IO_PROTOCOL EFI_DEVICE_IO_PROTOCOL; + +typedef enum { + IO_UINT8, + IO_UINT16, + IO_UINT32, + IO_UINT64, + MMIO_COPY_UINT8, + MMIO_COPY_UINT16, + MMIO_COPY_UINT32, + MMIO_COPY_UINT64 +} EFI_IO_WIDTH; + +/** + Enables a driver to access device registers in the appropriate memory or I/O space. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @param Width Signifies the width of the I/O operations. + @param Address The base address of the I/O operations. + @param Count The number of I/O 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 device. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Width is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DEVICE_IO) ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_WIDTH Width, + IN UINT64 Address, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + EFI_DEVICE_IO Read; + EFI_DEVICE_IO Write; +} EFI_IO_ACCESS; + +/** + Provides an EFI Device Path for a PCI device with the given PCI configuration space address. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @param PciAddress The PCI configuration space address of the device whose Device Path + is going to be returned. + @param PciDevicePath A pointer to the pointer for the EFI Device Path for PciAddress. + Memory for the Device Path is allocated from the pool. + + @retval EFI_SUCCESS The PciDevicePath returns a pointer to a valid EFI Device Path. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_UNSUPPORTED The PciAddress does not map to a valid EFI Device Path. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_DEVICE_PATH) ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN UINT64 PciAddress, + IN OUT EFI_DEVICE_PATH_PROTOCOL **PciDevicePath + ); + +typedef enum { + EfiBusMasterRead, + EfiBusMasterWrite, + EfiBusMasterCommonBuffer +} EFI_IO_OPERATION_TYPE; + +/** + Provides the device-specific addresses needed to access system memory. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @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 device. + @param NumberOfBytes On input the number of bytes to map. + @param DeviceAddress The resulting map address for the bus master device 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_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer. + @retval EFI_INVALID_PARAMETER The Operation or HostAddress is undefined. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IO_MAP) ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_IO_OPERATION_TYPE Operation, + IN EFI_PHYSICAL_ADDRESS *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_DEVICE_IO_INTERFACE instance. + @param Mapping A resulting value to pass to Unmap(). + + @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes. + @retval EFI_DEVICE_ERROR The system hardware could not map the requested address. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IO_UNMAP) ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an EFIBusMasterCommonBuffer mapping. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @param Type The type allocation to perform. + @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 address of the allocated range. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated. + @retval EFI_INVALID_PARAMETER The requested memory type is invalid. + @retval EFI_UNSUPPORTED The requested HostAddress is not supported on + this platform. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IO_ALLOCATE_BUFFER) ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *HostAddress + ); + +/** + Flushes any posted write data to the device. + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + + @retval EFI_SUCCESS The buffers were flushed. + @retval EFI_DEVICE_ERROR The buffers were not flushed due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IO_FLUSH) ( + IN EFI_DEVICE_IO_PROTOCOL *This + ); + +/** + Frees pages that were allocated with AllocateBuffer(). + + @param This A pointer to the EFI_DEVICE_IO_INTERFACE instance. + @param Pages The number of pages to free. + @param HostAddress The base address of the range to free. + + @retval EFI_SUCCESS The requested memory pages were allocated. + @retval EFI_NOT_FOUND The requested memory pages were not allocated with + AllocateBuffer(). + @retval EFI_INVALID_PARAMETER HostAddress is not page aligned or Pages is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IO_FREE_BUFFER) ( + IN EFI_DEVICE_IO_PROTOCOL *This, + IN UINTN Pages, + IN EFI_PHYSICAL_ADDRESS HostAddress + ); + +struct _EFI_DEVICE_IO_PROTOCOL { + EFI_IO_ACCESS Mem; + EFI_IO_ACCESS Io; + EFI_IO_ACCESS Pci; + EFI_IO_MAP Map; + EFI_PCI_DEVICE_PATH PciDevicePath; + EFI_IO_UNMAP Unmap; + EFI_IO_ALLOCATE_BUFFER AllocateBuffer; + EFI_IO_FLUSH Flush; + EFI_IO_FREE_BUFFER FreeBuffer; +}; + +extern EFI_GUID gEfiDeviceIoProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/DevicePath.h b/MdePkg/Include/Protocol/DevicePath.h new file mode 100644 index 0000000000..d01999904f --- /dev/null +++ b/MdePkg/Include/Protocol/DevicePath.h @@ -0,0 +1,94 @@ +/** @file + The device path protocol as defined in EFI 1.0. + + The device path represents a programatic path to a device. It's the view + from a software point of view. It also must persist from boot to boot, so + it can not contain things like PCI bus numbers that change from boot to boot. + + Copyright (c) 2006, 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. + + Module Name: DevicePath.h + +**/ + +#ifndef __EFI_DEVICE_PATH_PROTOCOL_H__ +#define __EFI_DEVICE_PATH_PROTOCOL_H__ + +// +// Device Path protocol +// +#define EFI_DEVICE_PATH_PROTOCOL_GUID \ + { \ + 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +#pragma pack(1) + +typedef struct { + UINT8 Type; + UINT8 SubType; + UINT8 Length[2]; +} EFI_DEVICE_PATH_PROTOCOL; + +#pragma pack() + +#define EFI_DP_TYPE_MASK 0x7F +#define EFI_DP_TYPE_UNPACKED 0x80 +#define END_DEVICE_PATH_TYPE 0x7f + +#define EFI_END_ENTIRE_DEVICE_PATH 0xff +#define EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE 0xff +#define EFI_END_INSTANCE_DEVICE_PATH 0x01 +#define END_ENTIRE_DEVICE_PATH_SUBTYPE EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE +#define END_INSTANCE_DEVICE_PATH_SUBTYPE EFI_END_INSTANCE_DEVICE_PATH + +#define EFI_END_DEVICE_PATH_LENGTH (sizeof (EFI_DEVICE_PATH_PROTOCOL)) +#define END_DEVICE_PATH_LENGTH EFI_END_DEVICE_PATH_LENGTH + +#define DP_IS_END_TYPE(a) +#define DP_IS_END_SUBTYPE(a) (((a)->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE) +#define DevicePathSubType(a) ((a)->SubType) +#define IsDevicePathUnpacked(a) ((a)->Type & EFI_DP_TYPE_UNPACKED) + +#define EfiDevicePathNodeLength(a) (((a)->Length[0]) | ((a)->Length[1] << 8)) +#define DevicePathNodeLength(a) (EfiDevicePathNodeLength(a)) +#define EfiNextDevicePathNode(a) ((EFI_DEVICE_PATH_PROTOCOL *) (((UINT8 *) (a)) + EfiDevicePathNodeLength (a))) +#define NextDevicePathNode(a) (EfiNextDevicePathNode(a)) + +#define EfiDevicePathType(a) (((a)->Type) & EFI_DP_TYPE_MASK) +#define DevicePathType(a) (EfiDevicePathType(a)) +#define EfiIsDevicePathEndType(a) (EfiDevicePathType (a) == END_DEVICE_PATH_TYPE) +#define IsDevicePathEndType(a) (EfiIsDevicePathEndType(a)) + + +#define EfiIsDevicePathEndSubType(a) ((a)->SubType == EFI_END_ENTIRE_DEVICE_PATH_SUBTYPE) +#define IsDevicePathEndSubType(a) (EfiIsDevicePathEndSubType(a)) +#define EfiIsDevicePathEndInstanceSubType(a) ((a)->SubType == EFI_END_INSTANCE_DEVICE_PATH) + +#define EfiIsDevicePathEnd(a) (EfiIsDevicePathEndType (a) && EfiIsDevicePathEndSubType (a)) +#define IsDevicePathEnd(a) (EfiIsDevicePathEnd(a)) +#define EfiIsDevicePathEndInstance(a) (EfiIsDevicePathEndType (a) && EfiIsDevicePathEndInstanceSubType (a)) + + +#define SetDevicePathNodeLength(a,l) { \ + (a)->Length[0] = (UINT8) (l); \ + (a)->Length[1] = (UINT8) ((l) >> 8); \ + } + +#define SetDevicePathEndNode(a) { \ + (a)->Type = END_DEVICE_PATH_TYPE; \ + (a)->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; \ + (a)->Length[0] = sizeof(EFI_DEVICE_PATH_PROTOCOL); \ + (a)->Length[1] = 0; \ + } + +extern EFI_GUID gEfiDevicePathProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/DevicePathFromText.h b/MdePkg/Include/Protocol/DevicePathFromText.h new file mode 100644 index 0000000000..a3a6c431ca --- /dev/null +++ b/MdePkg/Include/Protocol/DevicePathFromText.h @@ -0,0 +1,73 @@ +/** @file + EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL as defined in UEFI 2.0. + This protocol provides service to convert text to device paths and device nodes. + + Copyright (c) 2006, 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. + + Module Name: DevicePathFromText.h + +**/ + +#ifndef __DEVICE_PATH_FROM_TEXT_PROTOCOL_H__ +#define __DEVICE_PATH_FROM_TEXT_PROTOCOL_H__ + +// +// Device Path From Text protocol +// +#define EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL_GUID \ + { \ + 0x5c99a21, 0xc70f, 0x4ad2, {0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e } \ + } + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @retval a_pointer Pointer to the EFI device node. + @retval NULL if TextDeviceNode is NULL or there was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_FROM_TEXT_NODE) ( + IN CONST CHAR16 *TextDeviceNode + ) +; + + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device path character. + + @retval a_pointer Pointer to the allocated device path. + @retval NULL if TextDeviceNode is NULL or there was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_FROM_TEXT_PATH) ( + IN CONST CHAR16 *TextDevicePath + ) +; + +typedef struct { + EFI_DEVICE_PATH_FROM_TEXT_NODE ConvertDeviceNodeFromText; + EFI_DEVICE_PATH_FROM_TEXT_PATH ConvertDevicePathFromText; +} EFI_DEVICE_PATH_FROM_TEXT_PROTOCOL; + +extern EFI_GUID gEfiDevicePathFromTextProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/DevicePathToText.h b/MdePkg/Include/Protocol/DevicePathToText.h new file mode 100644 index 0000000000..d888562b12 --- /dev/null +++ b/MdePkg/Include/Protocol/DevicePathToText.h @@ -0,0 +1,86 @@ +/** @file + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL as defined in UEFI 2.0. + This protocol provides service to convert device nodes and paths to text. + + Copyright (c) 2006, 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. + + Module Name: DevicePathToText.h + +**/ + +#ifndef __DEVICE_PATH_TO_TEXT_PROTOCOL_H__ +#define __DEVICE_PATH_TO_TEXT_PROTOCOL_H__ + +// +// Device Path To Text protocol +// +#define EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID \ + { \ + 0x8b843e20, 0x8132, 0x4852, {0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c } \ + } + +/** + Convert a device node to its text representation. + + @param DeviceNode Points to the device node to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts If AllowShortcuts is TRUE, then the shortcut forms of text + representation for a device node can be used, where applicable. + + @retval a_pointer a pointer to the allocated text representation of the device node data + @retval NULL if DeviceNode is NULL or there was insufficient memory. + +**/ +typedef +CHAR16* +(EFIAPI *EFI_DEVICE_PATH_TO_TEXT_NODE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +; + +/** + Convert a device path to its text representation. + + @param DevicePath Points to the device path to be converted. + @param DisplayOnly If DisplayOnly is TRUE, then the shorter text representation + of the display node is used, where applicable. If DisplayOnly + is FALSE, then the longer text representation of the display node + is used. + @param AllowShortcuts The AllowShortcuts is FALSE, then the shortcut forms of + text representation for a device node cannot be used. + + @retval a_pointer a pointer to the allocated text representation of the device node. + @retval NULL if DevicePath is NULL or there was insufficient memory. + +**/ +typedef +CHAR16* +(EFIAPI *EFI_DEVICE_PATH_TO_TEXT_PATH) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN BOOLEAN DisplayOnly, + IN BOOLEAN AllowShortcuts + ) +; + +typedef struct { + EFI_DEVICE_PATH_TO_TEXT_NODE ConvertDeviceNodeToText; + EFI_DEVICE_PATH_TO_TEXT_PATH ConvertDevicePathToText; +} EFI_DEVICE_PATH_TO_TEXT_PROTOCOL; + +extern EFI_GUID gEfiDevicePathToTextProtocolGuid; + +#endif + + diff --git a/MdePkg/Include/Protocol/DevicePathUtilities.h b/MdePkg/Include/Protocol/DevicePathUtilities.h new file mode 100644 index 0000000000..e72f57cf8f --- /dev/null +++ b/MdePkg/Include/Protocol/DevicePathUtilities.h @@ -0,0 +1,194 @@ +/** @file + EFI_DEVICE_PATH_UTILITIES_PROTOCOL as defined in UEFI 2.0. + Use to create and manipulate device paths and device nodes. + + Copyright (c) 2006, 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. + + Module Name: DevicePathUtilities.h + +**/ + +#ifndef __DEVICE_PATH_UTILITIES_PROTOCOL_H__ +#define __DEVICE_PATH_UTILITIES_PROTOCOL_H__ + +// +// Device Path Utilities protocol +// +#define EFI_DEVICE_PATH_UTILITIES_PROTOCOL_GUID \ + { \ + 0x379be4e, 0xd706, 0x437d, {0xb0, 0x37, 0xed, 0xb8, 0x2f, 0xb7, 0x72, 0xa4 } \ + } + +/** + Returns the size of the device path, in bytes. + + @param DevicePath Points to the start of the EFI device path. + + @revtal Size Size of the specified device path, in bytes, including the end-of-path tag. + +**/ +typedef +UINTN +(EFIAPI *EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +; + + +/** + Create a duplicate of the specified path. + + @param DevicePath Points to the source EFI device path. + + @retval Pointer A pointer to the duplicate device path. + @retval NULL insufficient memory + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +; + +/** + Create a new path by appending the second device path to the first. + + @param Src1 Points to the first device path. If NULL, then it is ignored. + @param Src2 Points to the second device path. If NULL, then it is ignored. + + @retval Pointer A pointer to the newly created device path. + @retval NULL Memory could not be allocated + or either DevicePath or DeviceNode is NULL. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_APPEND_PATH) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src1, + IN CONST EFI_DEVICE_PATH_PROTOCOL *Src2 + ) +; + +/** + Creates a new path by appending the device node to the device path. + + @param DevicePath Points to the device path. + @param DeviceNode Points to the device node. + + @retval Pointer A pointer to the allocated device node. + @retval NULL Memory could not be allocated + or either DevicePath or DeviceNode is NULL. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_APPEND_NODE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode + ) +; + +/** + Creates a new path by appending the specified device path instance to the specified device path. + + @param DevicePath Points to the device path. If NULL, then ignored. + @param DevicePathInstance Points to the device path instance. + + @retval Pointer A pointer to the newly created device path + @retval NULL Memory could not be allocated or DevicePathInstance is NULL. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance + ) +; + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + @param DevicePathInstance On input, this holds the pointer to the current device path + instance. On output, this holds the pointer to the next + device path instance or NULL if there are no more device + path instances in the device path. + @param DevicePathInstanceSize On output, this holds the size of the device path instance, + in bytes or zero, if DevicePathInstance is zero. + + @retval Pointer A pointer to the copy of the current device path instance. + @retval NULL DevicePathInstace was NULL on entry or there was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE) ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePathInstance, + OUT UINTN *DevicePathInstanceSize + ) +; + +/** + Creates a device node + + @param NodeType NodeType is the device node type (EFI_DEVICE_PATH.Type) for + the new device node. + @param NodeSubType NodeSubType is the device node sub-type + EFI_DEVICE_PATH.SubType) for the new device node. + @param NodeLength NodeLength is the length of the device node + (EFI_DEVICE_PATH.Length) for the new device node. + + @retval Pointer A pointer to the newly created device node. + @retval NULL NodeLength is less than + the size of the header or there was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +(EFIAPI *EFI_DEVICE_PATH_CREATE_NODE) ( + IN UINT8 NodeType, + IN UINT8 NodeSubType, + IN UINT16 NodeLength +) +; + +/** + Returns whether a device path is multi-instance. + + @param DevicePath Points to the device path. If NULL, then ignored. + + @retval TRUE The device path has more than one instance + @retval FALSE The device path is empty or contains only a single instance. + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE) ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +; + + +typedef struct { + EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE GetDevicePathSize; + EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH DuplicateDevicePath; + EFI_DEVICE_PATH_UTILS_APPEND_PATH AppendDevicePath; + EFI_DEVICE_PATH_UTILS_APPEND_NODE AppendDeviceNode; + EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE AppendDevicePathInstance; + EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE GetNextDevicePathInstance; + EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE IsDevicePathMultiInstance; + EFI_DEVICE_PATH_CREATE_NODE CreateDeviceNode; +} EFI_DEVICE_PATH_UTILITIES_PROTOCOL; + +extern EFI_GUID gEfiDevicePathUtilitiesProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Dhcp4.h b/MdePkg/Include/Protocol/Dhcp4.h new file mode 100644 index 0000000000..3adce1a04a --- /dev/null +++ b/MdePkg/Include/Protocol/Dhcp4.h @@ -0,0 +1,442 @@ +/** @file + EFI_DHCP4_PROTOCOL as defined in UEFI 2.0. + EFI_DHCP4_SERVICE_BINDING_PROTOCOL as defined in UEFI 2.0. + These protocols are used to collect configuration information for the EFI IPv4 Protocol + drivers and to provide DHCPv4 server and PXE boot server discovery services. + + Copyright (c) 2006, 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. + + Module Name: DHCP4.h + +**/ + +#ifndef __EFI_DHCP4_PROTOCOL_H__ +#define __EFI_DHCP4_PROTOCOL_H__ + +#define EFI_DHCP4_PROTOCOL_GUID \ + { \ + 0x8a219718, 0x4ef5, 0x4761, {0x91, 0xc8, 0xc0, 0xf0, 0x4b, 0xda, 0x9e, 0x56 } \ + } + +#define EFI_DHCP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x9d9a39d8, 0xbd42, 0x4a73, {0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80 } \ + } + +typedef struct _EFI_DHCP4_PROTOCOL EFI_DHCP4_PROTOCOL; + + +#pragma pack(1) +typedef struct { + UINT8 OpCode; + UINT8 Length; + UINT8 Data[1]; +} EFI_DHCP4_PACKET_OPTION; +#pragma pack() + + +#pragma pack(1) +typedef struct { + UINT8 OpCode; + UINT8 HwType; + UINT8 HwAddrLen; + UINT8 Hops; + UINT32 Xid; + UINT16 Seconds; + UINT16 Reserved; + EFI_IPv4_ADDRESS ClientAddr; //Client IP address from client + EFI_IPv4_ADDRESS YourAddr; //Client IP address from server + EFI_IPv4_ADDRESS ServerAddr; //IP address of next server in bootstrap + EFI_IPv4_ADDRESS GatewayAddr; //Relay agent IP address + UINT8 ClientHwAddr[16]; //Client hardware address + CHAR8 ServerName[64]; + CHAR8 BootFileName[128]; +}EFI_DHCP4_HEADER; +#pragma pack() + + +#pragma pack(1) +typedef struct { + UINT32 Size; + UINT32 Length; + + struct { + EFI_DHCP4_HEADER Header; + UINT32 Magik; + UINT8 Option[1]; + } Dhcp4; +} EFI_DHCP4_PACKET; +#pragma pack() + + +typedef enum { + Dhcp4Stopped = 0x0, + Dhcp4Init = 0x1, + Dhcp4Selecting = 0x2, + Dhcp4Requesting = 0x3, + Dhcp4Bound = 0x4, + Dhcp4Renewing = 0x5, + Dhcp4Rebinding = 0x6, + Dhcp4InitReboot = 0x7, + Dhcp4Rebooting = 0x8 +} EFI_DHCP4_STATE; + + +typedef enum{ + Dhcp4SendDiscover = 0x01, + Dhcp4RcvdOffer = 0x02, + Dhcp4SelectOffer = 0x03, + Dhcp4SendRequest = 0x04, + Dhcp4RcvdAck = 0x05, + Dhcp4RcvdNak = 0x06, + Dhcp4SendDecline = 0x07, + Dhcp4BoundCompleted = 0x08, + Dhcp4EnterRenewing = 0x09, + Dhcp4EnterRebinding = 0x0a, + Dhcp4AddressLost = 0x0b, + Dhcp4Fail = 0x0c +} EFI_DHCP4_EVENT; + +/** + Callback routine + + @param This Pointer to the EFI DHCPv4 Protocol instance that is used to + configure this callback function. + @param Context Pointer to the context that is initialized by + EFI_DHCP4_PROTOCOL.Configure(). + @param CurrentState The current operational state of the EFI DHCPv4 Protocol + driver. + @param Dhcp4Event The event that occurs in the current state, which usually means a + state transition. + @param Packet The DHCP packet that is going to be sent or already received. + @param NewPacket The packet that is used to replace the above Packet. + + @retval EFI_SUCCESS Tells the EFI DHCPv4 Protocol driver to continue the DHCP process. + @retval EFI_NOT_READY Only used in the Dhcp4Selecting state. The EFI DHCPv4 Protocol + driver will continue to wait for more DHCPOFFER packets until the retry + timeout expires. + @retval EFI_ABORTED Tells the EFI DHCPv4 Protocol driver to abort the current process and + return to the Dhcp4Init or Dhcp4InitReboot state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_CALLBACK) ( + IN EFI_DHCP4_PROTOCOL *This, + IN VOID *Context, + IN EFI_DHCP4_STATE CurrentState, + IN EFI_DHCP4_EVENT Dhcp4Event, + IN EFI_DHCP4_PACKET *Packet OPTIONAL, + OUT EFI_DHCP4_PACKET **NewPacket OPTIONAL + ); + + +typedef struct { + UINT32 DiscoverTryCount; + UINT32 *DiscoverTimeout; + UINT32 RequestTryCount; + UINT32 *RequestTimeout; + EFI_IPv4_ADDRESS ClientAddress; + EFI_DHCP4_CALLBACK Dhcp4Callback; + void *CallbackContext; + UINT32 OptionCount; + EFI_DHCP4_PACKET_OPTION **OptionList; +} EFI_DHCP4_CONFIG_DATA; + + +typedef struct { + EFI_DHCP4_STATE State; + EFI_DHCP4_CONFIG_DATA ConfigData; + EFI_IPv4_ADDRESS ClientAddress; + EFI_MAC_ADDRESS ClientMacAddress; + EFI_IPv4_ADDRESS ServerAddress; + EFI_IPv4_ADDRESS RouterAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT32 LeaseTime; + EFI_DHCP4_PACKET *ReplyPacket; +} EFI_DHCP4_MODE_DATA; + + +typedef struct { + EFI_IPv4_ADDRESS ListenAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 ListenPort; +} EFI_DHCP4_LISTEN_POINT; + + +typedef struct { + OUT EFI_STATUS Status; + IN EFI_EVENT CompletionEvent; + IN EFI_IPv4_ADDRESS RemoteAddress; + IN UINT16 RemotePort; + IN EFI_IPv4_ADDRESS GatewayAddress; + IN UINT32 ListenPointCount; + IN EFI_DHCP4_LISTEN_POINT *ListenPoints; + IN UINT32 TimeoutValue; + IN EFI_DHCP4_PACKET *Packet; + OUT UINT32 ResponseCount; + OUT EFI_DHCP4_PACKET *ResponseList; +} EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN; + + +/** + Returns the current operating mode and cached data packet for the EFI DHCPv4 Protocol driver. + + @param This Pointer to the EFI_DHCP4_PROTOCOL instance. + @param Dhcp4ModeData Pointer to storage for the EFI_DHCP4_MODE_DATA structure. + + @retval EFI_SUCCESS The mode data was returned. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_GET_MODE_DATA)( + IN EFI_DHCP4_PROTOCOL *This, + OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData + ) +; + +/** + Initializes, changes, or resets the operational settings for the EFI DHCPv4 Protocol driver. + + @param This Pointer to the EFI_DHCP4_PROTOCOL instance. + @param Dhcp4CfgData Pointer to the EFI_DHCP4_CONFIG_DATA. + + @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init or + Dhcp4InitReboot state, if the original state of this driver + was Dhcp4Stopped and the value of Dhcp4CfgData was + not NULL. Otherwise, the state was left unchanged. + @retval EFI_ACCESS_DENIED This instance of the EFI DHCPv4 Protocol driver was not in the + Dhcp4Stopped, Dhcp4Init, Dhcp4InitReboot, or Dhcp4Bound state; + Or onother instance of this EFI DHCPv4 Protocol driver is already + in a valid configured state. + @retval EFI_INVALID_PARAMETER Some parameter is NULL. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_CONFIGURE) ( + IN EFI_DHCP4_PROTOCOL *This, + IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL + ) +; + + +/** + Starts the DHCP configuration process. + + @param This Pointer to the EFI_DHCP4_PROTOCOL instance. + @param CompletionEvent If not NULL, indicates the event that will be signaled when the + EFI DHCPv4 Protocol driver is transferred into the + Dhcp4Bound state or when the DHCP process is aborted. + EFI_DHCP4_PROTOCOL.GetModeData() can be called to + check the completion status. If NULL, + EFI_DHCP4_PROTOCOL.Start() will wait until the driver + is transferred into the Dhcp4Bound state or the process fails. + + @retval EFI_SUCCESS The DHCP configuration process has started, or it has completed + when CompletionEvent is NULL. + @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped + state. EFI_DHCP4_PROTOCOL. Configure() needs to be called. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_TIMEOUT The DHCP configuration process failed because no response was + received from the server within the specified timeout value. + @retval EFI_ABORTED The user aborted the DHCP process. + @retval EFI_ALREADY_STARTED Some other EFI DHCPv4 Protocol instance already started the + DHCP process. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_START) ( + IN EFI_DHCP4_PROTOCOL *This, + IN EFI_EVENT CompletionEvent OPTIONAL + ) +; + +/** + Extends the lease time by sending a request packet. + + @param This Pointer to the EFI_DHCP4_PROTOCOL instance. + @param RebindRequest If TRUE, this function broadcasts the request packets and enters + the Dhcp4Rebinding state. Otherwise, it sends a unicast + request packet and enters the Dhcp4Renewing state. + @param CompletionEvent If not NULL, this event is signaled when the renew/rebind phase + completes or some error occurs. + EFI_DHCP4_PROTOCOL.GetModeData() can be called to + check the completion status. If NULL, + EFI_DHCP4_PROTOCOL.RenewRebind() will busy-wait + until the DHCP process finishes. + + @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the + Dhcp4Renewing state or is back to the Dhcp4Bound state. + @retval EFI_NOT_STARTED The EFI DHCPv4 Protocol driver is in the Dhcp4Stopped + state. EFI_DHCP4_PROTOCOL.Configure() needs to + be called. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_TIMEOUT There was no response from the server when the try count was + exceeded. + @retval EFI_ACCESS_DENIED The driver is not in the Dhcp4Bound state. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_RENEW_REBIND) ( + IN EFI_DHCP4_PROTOCOL *This, + IN BOOLEAN RebindRequest, + IN EFI_EVENT CompletionEvent OPTIONAL + ) +; + +/** + Releases the current address configuration. + + @param This Pointer to the EFI_DHCP4_PROTOCOL instance. + + @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Init phase. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_ACCESS_DENIED The EFI DHCPv4 Protocol driver is not Dhcp4InitReboot state. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_RELEASE) ( + IN EFI_DHCP4_PROTOCOL *This + ) +; + +/** + Stops the current address configuration. + + @param This Pointer to the EFI_DHCP4_PROTOCOL instance. + + @retval EFI_SUCCESS The EFI DHCPv4 Protocol driver is now in the Dhcp4Stopped phase. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_STOP) ( + IN EFI_DHCP4_PROTOCOL *This + ) +; + +/** + Builds a DHCP packet, given the options to be appended or deleted or replaced. + + @param This Pointer to the EFI_DHCP4_PROTOCOL instance. + @param SeedPacket Initial packet to be used as a base for building new packet. + @param DeleteCount Number of opcodes in the DeleteList. + @param DeleteList List of opcodes to be deleted from the seed packet. + Ignored if DeleteCount is zero. + @param AppendCount Number of entries in the OptionList. + @param AppendList Pointer to a DHCP option list to be appended to SeedPacket. + If SeedPacket also contains options in this list, they are + replaced by new options (except pad option). Ignored if + AppendCount is zero. Type EFI_DHCP4_PACKET_OPTION + @param NewPacket Pointer to storage for the pointer to the new allocated packet. + Use the EFI Boot Service FreePool() on the resulting pointer + when done with the packet. + + @retval EFI_SUCCESS The new packet was built. + @retval EFI_OUT_OF_RESOURCES Storage for the new packet could not be allocated. + @retval EFI_INVALID_PARAMETER Some parameter is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_BUILD) ( + IN EFI_DHCP4_PROTOCOL *This, + IN EFI_DHCP4_PACKET *SeedPacket, + IN UINT32 DeleteCount, + IN UINT8 *DeleteList OPTIONAL, + IN UINT32 AppendCount, + IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL, + OUT EFI_DHCP4_PACKET **NewPacket + ); +; + +/** + Transmits a DHCP formatted packet and optionally waits for responses. + + @param This Pointer to the EFI_DHCP4_PROTOCOL instance. + @param Token Pointer to the EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN structure. + + @retval EFI_SUCCESS The packet was successfully queued for transmission. + @retval EFI_INVALID_PARAMETER Some parameter is NULL. + @retval EFI_NOT_READY The previous call to this function has not finished yet. Try to call + this function after collection process completes. + @retval EFI_NO_MAPPING The default station address is not available yet. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval Others Some other unexpected error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_TRANSMIT_RECEIVE) ( + IN EFI_DHCP4_PROTOCOL *This, + IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token + ) +; + + +/** + Parses the packed DHCP option data. + + @param This Pointer to the EFI_DHCP4_PROTOCOL instance. + @param Packet Pointer to packet to be parsed. + @param OptionCount On input, the number of entries in the PacketOptionList. + On output, the number of entries that were written into the + PacketOptionList. + @param PacketOptionList List of packet option entries to be filled in. End option or pad + options are not included. + + @retval EFI_SUCCESS The packet was successfully parsed. + @retval EFI_INVALID_PARAMETER Some parameter is NULL. + @retval EFI_BUFFER_TOO_SMALL One or more of the following conditions is TRUE: + 1) *OptionCount is smaller than the number of options that + were found in the Packet. + 2) PacketOptionList is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DHCP4_PARSE) ( + IN EFI_DHCP4_PROTOCOL *This, + IN EFI_DHCP4_PACKET *Packet, + IN OUT UINT32 *OptionCount, + OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL + ) +; + + +struct _EFI_DHCP4_PROTOCOL { + EFI_DHCP4_GET_MODE_DATA GetModeData; + EFI_DHCP4_CONFIGURE Configure; + EFI_DHCP4_START Start; + EFI_DHCP4_RENEW_REBIND RenewRebind; + EFI_DHCP4_RELEASE Release; + EFI_DHCP4_STOP Stop; + EFI_DHCP4_BUILD Build; + EFI_DHCP4_TRANSMIT_RECEIVE TransmitReceive; + EFI_DHCP4_PARSE Parse; +}; + +extern EFI_GUID gEfiDhcp4ProtocolGuid; +extern EFI_GUID gEfiDhcp4ServiceBindingProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/DiskIo.h b/MdePkg/Include/Protocol/DiskIo.h new file mode 100644 index 0000000000..e36792c7cd --- /dev/null +++ b/MdePkg/Include/Protocol/DiskIo.h @@ -0,0 +1,98 @@ +/** @file + Disk IO protocol as defined in the EFI 1.0 specification. + + The Disk IO protocol is used to convert block oriented devices into byte + oriented devices. The Disk IO protocol is intended to layer on top of the + Block IO protocol. + + Copyright (c) 2006, 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. + + Module Name: DiskIo.h + +**/ + +#ifndef __DISK_IO_H__ +#define __DISK_IO_H__ + +#define EFI_DISK_IO_PROTOCOL_GUID \ + { \ + 0xce345171, 0xba0b, 0x11d2, {0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct _EFI_DISK_IO_PROTOCOL EFI_DISK_IO_PROTOCOL; + +/** + Read BufferSize bytes from Offset into Buffer. + + @param This Protocol instance pointer. + @param MediaId Id of the media, changes every time the media is replaced. + @param Offset The starting byte offset to read from + @param BufferSize Size of Buffer + @param Buffer Buffer containing read data + + @retval EFI_SUCCESS The data was read correctly from the device. + @retval EFI_DEVICE_ERROR The device reported an error while performing the read. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_INVALID_PARAMETER The read request contains device addresses that are not + valid for the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_READ) ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + OUT VOID *Buffer + ) +; + +/** + Read BufferSize bytes from Offset into Buffer. + + @param This Protocol instance pointer. + @param MediaId Id of the media, changes every time the media is replaced. + @param Offset The starting byte offset to read from + @param BufferSize Size of Buffer + @param Buffer Buffer containing read data + + @retval EFI_SUCCESS The data was written correctly to the device. + @retval EFI_WRITE_PROTECTED The device can not be written to. + @retval EFI_DEVICE_ERROR The device reported an error while performing the write. + @retval EFI_NO_MEDIA There is no media in the device. + @retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device. + @retval EFI_INVALID_PARAMETER The write request contains device addresses that are not + valid for the device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISK_WRITE) ( + IN EFI_DISK_IO_PROTOCOL *This, + IN UINT32 MediaId, + IN UINT64 Offset, + IN UINTN BufferSize, + IN VOID *Buffer + ) +; + +#define EFI_DISK_IO_PROTOCOL_REVISION 0x00010000 + +struct _EFI_DISK_IO_PROTOCOL { + UINT64 Revision; + EFI_DISK_READ ReadDisk; + EFI_DISK_WRITE WriteDisk; +}; + +extern EFI_GUID gEfiDiskIoProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/DriverBinding.h b/MdePkg/Include/Protocol/DriverBinding.h new file mode 100644 index 0000000000..5f5d90963e --- /dev/null +++ b/MdePkg/Include/Protocol/DriverBinding.h @@ -0,0 +1,111 @@ +/** @file + EFI ControllerHandle Driver Protocol + + Copyright (c) 2006, 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. + + Module Name: DriverBinding.h + +**/ + +#ifndef __EFI_DRIVER_BINDING_H__ +#define __EFI_DRIVER_BINDING_H__ + +// +// Global ID for the ControllerHandle Driver Protocol +// +#define EFI_DRIVER_BINDING_PROTOCOL_GUID \ + { \ + 0x18a031ab, 0xb443, 0x4d1a, {0xa5, 0xc0, 0xc, 0x9, 0x26, 0x1e, 0x9f, 0x71 } \ + } + +typedef struct _EFI_DRIVER_BINDING_PROTOCOL EFI_DRIVER_BINDING_PROTOCOL; + +/** + Test to see if this driver supports ControllerHandle. + + @param This Protocol instance pointer. + @param ControllerHandle Handle of device to test + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver supports this device + @retval EFI_ALREADY_STARTED This driver is already running on this device + @retval other This driver does not support this device + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_BINDING_SUPPORTED) ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +; + +/** + Start this driver on ControllerHandle. + + @param This Protocol instance pointer. + @param ControllerHandle Handle of device to bind driver to + @param RemainingDevicePath Optional parameter use to pick a specific child + device to start. + + @retval EFI_SUCCESS This driver is added to ControllerHandle + @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle + @retval other This driver does not support this device + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_BINDING_START) ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL + ) +; + +/** + Stop this driver on ControllerHandle. + + @param This Protocol instance pointer. + @param ControllerHandle Handle of device to stop driver on + @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of + children is zero stop the entire bus driver. + @param ChildHandleBuffer List of Child Handles to Stop. + + @retval EFI_SUCCESS This driver is removed ControllerHandle + @retval other This driver was not removed from this device + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_BINDING_STOP) ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer OPTIONAL + ) +; + +// +// Interface structure for the ControllerHandle Driver Protocol +// +struct _EFI_DRIVER_BINDING_PROTOCOL { + EFI_DRIVER_BINDING_SUPPORTED Supported; + EFI_DRIVER_BINDING_START Start; + EFI_DRIVER_BINDING_STOP Stop; + UINT32 Version; + EFI_HANDLE ImageHandle; + EFI_HANDLE DriverBindingHandle; +}; + +extern EFI_GUID gEfiDriverBindingProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/DriverConfiguration.h b/MdePkg/Include/Protocol/DriverConfiguration.h new file mode 100644 index 0000000000..f4f0c7aeb2 --- /dev/null +++ b/MdePkg/Include/Protocol/DriverConfiguration.h @@ -0,0 +1,203 @@ +/** @file + EFI Driver Configuration Protocol + + Copyright (c) 2006, 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. + + Module Name: DriverConfiguration.h + +**/ + +#ifndef __EFI_DRIVER_CONFIGURATION_H__ +#define __EFI_DRIVER_CONFIGURATION_H__ + +// +// Global ID for the Driver Configuration Protocol defined in EFI 1.10 +// +#define EFI_DRIVER_CONFIGURATION_PROTOCOL_GUID \ + { \ + 0x107a772b, 0xd5e1, 0x11d4, {0x9a, 0x46, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +// +// Global ID for the Driver Configuration Protocol defined in UEFI 2.0 +// +#define UEFI_DRIVER_CONFIGURATION_PROTOCOL_GUID \ + { \ + 0xbfd7dc1d, 0x24f1, 0x40d9, {0x82, 0xe7, 0x2e, 0x09, 0xbb, 0x6b, 0x4e, 0xbe } \ + } + +typedef struct _EFI_DRIVER_CONFIGURATION_PROTOCOL EFI_DRIVER_CONFIGURATION_PROTOCOL; + +typedef enum { + EfiDriverConfigurationActionNone = 0, + EfiDriverConfigurationActionStopController = 1, + EfiDriverConfigurationActionRestartController = 2, + EfiDriverConfigurationActionRestartPlatform = 3, + EfiDriverConfigurationActionMaximum +} EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED; + +#define EFI_DRIVER_CONFIGURATION_SAFE_DEFAULTS 0x00000000 +#define EFI_DRIVER_CONFIGURATION_MANUFACTURING_DEFAULTS 0x00000001 +#define EFI_DRIVER_CONFIGURATION_CUSTOM_DEFAULTS 0x00000002 +#define EFI_DRIVER_CONFIGURATION_PERORMANCE_DEFAULTS 0x00000003 + +/** + Allows the user to set controller specific options for a controller that a + driver is currently managing. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + @param ControllerHandle The handle of the controller to set options on. + @param ChildHandle The handle of the child controller to set options on. This + is an optional parameter that may be NULL. It will be NULL + for device drivers, and for a bus drivers that wish to set + options for the bus controller. It will not be NULL for a + bus driver that wishes to set options for one of its child + controllers. + @param Language A pointer to a three character ISO 639-2 language identifier. + This is the language of the user interface that should be + presented to the user, and it must match one of the languages + specified in SupportedLanguages. The number of languages + supported by a driver is up to the driver writer. + @param ActionRequired A pointer to the action that the calling agent is required + to perform when this function returns. See "Related + Definitions" for a list of the actions that the calling + agent is required to perform prior to accessing + ControllerHandle again. + + @retval EFI_SUCCESS The driver specified by This successfully set the + configuration options for the controller specified + by ControllerHandle.. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support setting + configuration options for the controller specified by + ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to set the + configuration options for the controller specified + by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to set the + configuration options for the controller specified + by ControllerHandle and ChildHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_CONFIGURATION_SET_OPTIONS) ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN CHAR8 *Language, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + +/** + Tests to see if a controller's current configuration options are valid. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_PROTOCOL instance. + @param ControllerHandle The handle of the controller to test if it's current + configuration options are valid. + @param ChildHandle The handle of the child controller to test if it's current + configuration options are valid. This is an optional + parameter that may be NULL. It will be NULL for device + drivers. It will also be NULL for a bus drivers that wish + to test the configuration options for the bus controller. + It will not be NULL for a bus driver that wishes to test + configuration options for one of its child controllers. + + @retval EFI_SUCCESS The controller specified by ControllerHandle and + ChildHandle that is being managed by the driver + specified by This has a valid set of configuration + options. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_UNSUPPORTED The driver specified by This is not currently + managing the controller specified by ControllerHandle + and ChildHandle. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and + ChildHandle that is being managed by the driver + specified by This has an invalid set of configuration + options. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_CONFIGURATION_OPTIONS_VALID) ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL + ); + +/** + Forces a driver to set the default configuration options for a controller. + + @param This A pointer to the EFI_DRIVER_CONFIGURATION_ PROTOCOL instance. + @param ControllerHandle The handle of the controller to force default configuration options on. + @param ChildHandle The handle of the child controller to force default configuration options on This is an optional parameter that may be NULL. It will be NULL for device drivers. It will also be NULL for a bus drivers that wish to force default configuration options for the bus controller. It will not be NULL for a bus driver that wishes to force default configuration options for one of its child controllers. + @param DefaultType The type of default configuration options to force on the controller specified by ControllerHandle and ChildHandle. See Table 9-1 for legal values. A DefaultType of 0x00000000 must be supported by this protocol. + @param ActionRequired A pointer to the action that the calling agent is required to perform when this function returns. See "Related Definitions" in Section 9.1for a list of the actions that the calling agent is required to perform prior to accessing ControllerHandle again. + + @retval EFI_SUCCESS The driver specified by This successfully forced the default configuration options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ActionRequired is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support forcing the default configuration options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the configuration type specified by DefaultType. + @retval EFI_DEVICE_ERROR A device error occurred while attempt to force the default configuration options on the controller specified by ControllerHandle and ChildHandle. + @retval EFI_OUT_RESOURCES There are not enough resources available to force the default configuration options on the controller specified by ControllerHandle and ChildHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_CONFIGURATION_FORCE_DEFAULTS) ( + IN EFI_DRIVER_CONFIGURATION_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN UINT32 DefaultType, + OUT EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED *ActionRequired + ); + + +// +// +struct _EFI_DRIVER_CONFIGURATION_PROTOCOL { + EFI_DRIVER_CONFIGURATION_SET_OPTIONS SetOptions; + EFI_DRIVER_CONFIGURATION_OPTIONS_VALID OptionsValid; + EFI_DRIVER_CONFIGURATION_FORCE_DEFAULTS ForceDefaults; + CHAR8 *SupportedLanguages; +}; + +/** + Interface structure for the Driver Configuration Protocol. + + @par Protocol Description: + Used to set configuration options for a controller that an EFI Driver is managing. + + @param SetOptions Allows the use to set drivers specific configuration + options for a controller that the driver is currently managing. + + @param OptionsValid Tests to see if a controller's current configuration + options are valid. + + @param ForceDefaults Forces a driver to set the default configuration options + for a controller. + + @param SupportedLanguages A Null-terminated ASCII string that contains one or more + ISO 639-2 language codes. This is the list of language + codes that this protocol supports. + +**/ + +extern EFI_GUID gEfiDriverConfigurationProtocolGuid; +extern EFI_GUID gUefiDriverConfigurationProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/DriverDiagnostics.h b/MdePkg/Include/Protocol/DriverDiagnostics.h new file mode 100644 index 0000000000..c0a0cbc63b --- /dev/null +++ b/MdePkg/Include/Protocol/DriverDiagnostics.h @@ -0,0 +1,134 @@ +/** @file + EFI Driver Diagnostics Protocol + + Copyright (c) 2006, 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. + + Module Name: DriverDiagnostics.h + +**/ + +#ifndef __EFI_DRIVER_DIAGNOSTICS_H__ +#define __EFI_DRIVER_DIAGNOSTICS_H__ + +// +// Global ID for the Driver Diagnostics Protocol as defined in EFI 1.10. +// +#define EFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID \ + { \ + 0x0784924f, 0xe296, 0x11d4, {0x9a, 0x49, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +// +// Global ID for the Driver Diagnostics Protocol as defined in UEFI 2.0. +// +#define UEFI_DRIVER_DIAGNOSTICS_PROTOCOL_GUID \ + { \ + 0x4d330321, 0x025f, 0x4aac, {0x90, 0xd8, 0x5e, 0xd9, 0x00, 0x17, 0x3b, 0x63 } \ + } + +typedef struct _EFI_DRIVER_DIAGNOSTICS_PROTOCOL EFI_DRIVER_DIAGNOSTICS_PROTOCOL; + +typedef enum { + EfiDriverDiagnosticTypeStandard = 0, + EfiDriverDiagnosticTypeExtended = 1, + EfiDriverDiagnosticTypeManufacturing= 2, + EfiDriverDiagnosticTypeMaximum +} EFI_DRIVER_DIAGNOSTIC_TYPE; + +/** + Runs diagnostics on a controller. + + @param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOL instance. + @param ControllerHandle The handle of the controller to run diagnostics on. + @param ChildHandle The handle of the child controller to run diagnostics on + This is an optional parameter that may be NULL. It will + be NULL for device drivers. It will also be NULL for a + bus drivers that wish to run diagnostics on the bus + controller. It will not be NULL for a bus driver that + wishes to run diagnostics on one of its child controllers. + @param DiagnosticType Indicates type of diagnostics to perform on the controller + specified by ControllerHandle and ChildHandle. See + "Related Definitions" for the list of supported types. + @param Language A pointer to a three character ISO 639-2 language + identifier. This is the language in which the optional + error message should be returned in Buffer, and it must + match one of the languages specified in SupportedLanguages. + The number of languages supported by a driver is up to + the driver writer. + @param ErrorType A GUID that defines the format of the data returned in Buffer. + @param BufferSize The size, in bytes, of the data returned in Buffer. + @param Buffer A buffer that contains a Null-terminated Unicode string + plus some additional data whose format is defined by + ErrorType. Buffer is allocated by this function with + AllocatePool(), and it is the caller's responsibility + to free it with a call to FreePool(). + + @retval EFI_SUCCESS The controller specified by ControllerHandle and + ChildHandle passed the diagnostic. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER ErrorType is NULL. + @retval EFI_INVALID_PARAMETER BufferType is NULL. + @retval EFI_INVALID_PARAMETER Buffer is NULL. + @retval EFI_UNSUPPORTED The driver specified by This does not support + running diagnostics for the controller specified + by ControllerHandle and ChildHandle. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + type of diagnostic specified by DiagnosticType. + @retval EFI_UNSUPPORTED The driver specified by This does not support the + language specified by Language. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete + the diagnostics. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to return + the status information in ErrorType, BufferSize, + and Buffer. + @retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and + ChildHandle did not pass the diagnostic. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DRIVER_DIAGNOSTICS_RUN_DIAGNOSTICS) ( + IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE ChildHandle OPTIONAL, + IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType, + IN CHAR8 *Language, + OUT EFI_GUID **ErrorType, + OUT UINTN *BufferSize, + OUT CHAR16 **Buffer + ); + + +// +// + +/** + Interface structure for the Driver Diagnostics Protocol. + + @par Protocol Description: + Used to perform diagnostics on a controller that an EFI Driver is managing. + + @param RunDiagnostics Runs diagnostics on a controller. + @param SupportedLanguages A Null-terminated ASCII string that contains one or more + ISO 639-2 language codes. This is the list of language + codes that this protocol supports. + +**/ +struct _EFI_DRIVER_DIAGNOSTICS_PROTOCOL { + EFI_DRIVER_DIAGNOSTICS_RUN_DIAGNOSTICS RunDiagnostics; + CHAR8 *SupportedLanguages; +}; + +extern EFI_GUID gEfiDriverDiagnosticsProtocolGuid; +extern EFI_GUID gUefiDriverDiagnosticsProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Ebc.h b/MdePkg/Include/Protocol/Ebc.h new file mode 100644 index 0000000000..c1abcbac5b --- /dev/null +++ b/MdePkg/Include/Protocol/Ebc.h @@ -0,0 +1,148 @@ +/** @file + Describes the protocol interface to the EBC interpreter. + + Copyright (c) 2006, 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. + + Module Name: Ebc.h + +**/ + +#ifndef __EFI_EBC_PROTOCOL_H__ +#define __EFI_EBC_PROTOCOL_H__ + +#define EFI_EBC_INTERPRETER_PROTOCOL_GUID \ + { \ + 0x13AC6DD1, 0x73D0, 0x11D4, {0xB0, 0x6B, 0x00, 0xAA, 0x00, 0xBD, 0x6D, 0xE7 } \ + } + +// +// Protocol Guid Name defined in spec. +// +#define EFI_EBC_PROTOCOL_GUID EFI_EBC_INTERPRETER_PROTOCOL_GUID + +// +// Define for forward reference. +// +typedef struct _EFI_EBC_PROTOCOL EFI_EBC_PROTOCOL; + +/** + Create a thunk for an image entry point. In short, given the physical address + of the entry point for a loaded image, create a thunk that does some + fixup of arguments (and perform any other necessary overhead) and then + calls the original entry point. The caller can then use the returned pointer + to the created thunk as the new entry point to image. + + @param This protocol instance pointer + @param ImageHandle handle to the image. The EBC interpreter may use this to keep + track of any resource allocations performed in loading and + executing the image. + @param EbcEntryPoint the entry point for the image (as defined in the file header) + @param Thunk pointer to thunk pointer where the address of the created + thunk is returned. + + @return Standard EFI_STATUS + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_CREATE_THUNK) ( + IN EFI_EBC_PROTOCOL *This, + IN EFI_HANDLE ImageHandle, + IN VOID *EbcEntryPoint, + OUT VOID **Thunk + ); + +/** + Perform any cleanup necessary when an image is unloaded. Basically it gives + the EBC interpreter the chance to free up any resources allocated during + load and execution of an EBC image. + + @param This protocol instance pointer + @param ImageHandle the handle of the image being unloaded. + + @return Standard EFI_STATUS. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_UNLOAD_IMAGE) ( + IN EFI_EBC_PROTOCOL *This, + IN EFI_HANDLE ImageHandle + ); + +/** + The I-Cache-flush registration service takes a pointer to a function to + call to flush the I-Cache. Here's the prototype for that function pointer. + + @param Start physical start address of CPU instruction cache to flush. + @param Length how many bytes to flush of the instruction cache. + + @return Standard EFI_STATUS. + +**/ +typedef +EFI_STATUS +(EFIAPI *EBC_ICACHE_FLUSH) ( + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + +/** + This routine is called by the core firmware to provide the EBC driver with + a function to call to flush the CPU's instruction cache following creation + of a thunk. It is not required. + + @param This protocol instance pointer + @param Flush pointer to the function to call to flush the CPU instruction + cache. + + @return Standard EFI_STATUS. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_REGISTER_ICACHE_FLUSH) ( + IN EFI_EBC_PROTOCOL *This, + IN EBC_ICACHE_FLUSH Flush + ); + +/** + This routine can be called to get the VM revision. It returns the same + value as the EBC BREAK 1 instruction returns. + + @param This protocol instance pointer + @param Version pointer to where to return the VM version + + @return Standard EFI_STATUS. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EBC_GET_VERSION) ( + IN EFI_EBC_PROTOCOL *This, + IN OUT UINT64 *Version + ); + +// +// Prototype for the actual EBC protocol interface +// +struct _EFI_EBC_PROTOCOL { + EFI_EBC_CREATE_THUNK CreateThunk; + EFI_EBC_UNLOAD_IMAGE UnloadImage; + EFI_EBC_REGISTER_ICACHE_FLUSH RegisterICacheFlush; + EFI_EBC_GET_VERSION GetVersion; +}; + +// +// Extern the global EBC protocol GUID +// +extern EFI_GUID gEfiEbcProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/EdidActive.h b/MdePkg/Include/Protocol/EdidActive.h new file mode 100644 index 0000000000..0562cbec36 --- /dev/null +++ b/MdePkg/Include/Protocol/EdidActive.h @@ -0,0 +1,34 @@ +/** @file + EDID Active Protocol from the UEFI 2.0 specification. + + Placed on the video output device child handle that are actively displaying output. + + Copyright (c) 2006, 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. + + Module Name: EdidActive.h + +**/ + +#ifndef __EDID_ACTIVE_H__ +#define __EDID_ACTIVE_H__ + +#define EFI_EDID_ACTIVE_PROTOCOL_GUID \ + { \ + 0xbd8c1056, 0x9f36, 0x44ec, {0x92, 0xa8, 0xa6, 0x33, 0x7f, 0x81, 0x79, 0x86 } \ + } + +typedef struct { + UINT32 SizeOfEdid; + UINT8 *Edid; +} EFI_EDID_ACTIVE_PROTOCOL; + +extern EFI_GUID gEfiEdidActiveProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/EdidDiscovered.h b/MdePkg/Include/Protocol/EdidDiscovered.h new file mode 100644 index 0000000000..6790666b67 --- /dev/null +++ b/MdePkg/Include/Protocol/EdidDiscovered.h @@ -0,0 +1,35 @@ +/** @file + EDID Discovered Protocol from the UEFI 2.0 specification. + + This protocol is placed on the video output device child handle and it represents + the EDID information being used for output device represented by the child handle. + + Copyright (c) 2006, 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. + + Module Name: EdidDiscovered.h + +**/ + +#ifndef __EDID_DISCOVERED_H__ +#define __EDID_DISCOVERED_H__ + +#define EFI_EDID_DISCOVERED_PROTOCOL_GUID \ + { \ + 0x1c0c34f6, 0xd380, 0x41fa, {0xa0, 0x49, 0x8a, 0xd0, 0x6c, 0x1a, 0x66, 0xaa } \ + } + +typedef struct { + UINT32 SizeOfEdid; + UINT8 *Edid; +} EFI_EDID_DISCOVERED_PROTOCOL; + +extern EFI_GUID gEfiEdidDiscoveredProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/EdidOverride.h b/MdePkg/Include/Protocol/EdidOverride.h new file mode 100644 index 0000000000..3f4c5762e7 --- /dev/null +++ b/MdePkg/Include/Protocol/EdidOverride.h @@ -0,0 +1,66 @@ +/** @file + EDID Override Protocol from the UEFI 2.0 specification. + + Allow platform to provide EDID information to producer of the Graphics Output + protocol. + + Copyright (c) 2006, 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. + + Module Name: EdidOverride.h + +**/ + +#ifndef __EDID_OVERRIDE_H__ +#define __EDID_OVERRIDE_H__ + +#define EFI_EDID_OVERRIDE_PROTOCOL_GUID \ + { \ + 0x48ecb431, 0xfb72, 0x45c0, {0xa9, 0x22, 0xf4, 0x58, 0xfe, 0x4, 0xb, 0xd5 } \ + } + +typedef struct _EFI_EDID_OVERRIDE_PROTOCOL EFI_EDID_OVERRIDE_PROTOCOL; + +#define EFI_EDID_OVERRIDE_DONT_OVERRIDE 0x01 +#define EFI_EDID_OVERRIDE_ENABLE_HOT_PLUG 0x02 + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ChildHandle A child handle produced by the Graphics Output EFI + driver that represents a video output device. + @param Attributes The attributes associated with ChildHandle video output device. + @param EdidSize A pointer to the size, in bytes, of the Edid buffer. + @param Edid A pointer to callee allocated buffer that contains the EDID that + should be used for ChildHandle. A value of NULL + represents no EDID override for ChildHandle. + + @retval EFI_SUCCESS Valid overrides returned for ChildHandle. + @retval EFI_UNSUPPORTED ChildHandle has no overrides. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID) ( + IN EFI_EDID_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE *ChildHandle, + OUT UINT32 *Attributes, + IN OUT UINTN *EdidSize, + IN OUT UINT8 **Edid + ) +; + +struct _EFI_EDID_OVERRIDE_PROTOCOL { + EFI_EDID_OVERRIDE_PROTOCOL_GET_EDID GetEdid; +}; + +extern EFI_GUID gEfiEdidOverrideProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/EfiNetworkInterfaceIdentifier.h b/MdePkg/Include/Protocol/EfiNetworkInterfaceIdentifier.h new file mode 100644 index 0000000000..98f1c597a4 --- /dev/null +++ b/MdePkg/Include/Protocol/EfiNetworkInterfaceIdentifier.h @@ -0,0 +1,92 @@ +/** @file + Revision history: + + Copyright (c) 2006, 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. + + Module name: + + EfiNetworkInterfaceIdentifier.h + +**/ + +#ifndef __EFI_NETWORK_INTERFACE_IDENTIFER_H__ +#define __EFI_NETWORK_INTERFACE_IDENTIFER_H__ + + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_GUID \ + { \ + 0xE18541CD, 0xF755, 0x4f73, {0x92, 0x8D, 0x64, 0x3C, 0x8A, 0x79, 0xB2, 0x29 } \ + } + +#define EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL_REVISION 0x00010000 + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL; + +typedef enum { + EfiNetworkInterfaceUndi = 1 +} EFI_NETWORK_PROTOCOL_TYPE; + +struct _EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL { + + UINT64 Revision; + // + // Revision of the network interface identifier protocol interface. + // + UINT64 ID; + // + // Address of the first byte of the identifying structure for this + // network interface. This is set to zero if there is no structure. + // + // For PXE/UNDI this is the first byte of the !PXE structure. + // + UINT64 ImageAddr; + // + // Address of the UNrelocated driver/ROM image. This is set + // to zero if there is no driver/ROM image. + // + // For 16-bit UNDI, this is the first byte of the option ROM in + // upper memory. + // + // For 32/64-bit S/W UNDI, this is the first byte of the EFI ROM + // image. + // + // For H/W UNDI, this is set to zero. + // + UINT32 ImageSize; + // + // Size of the UNrelocated driver/ROM image of this network interface. + // This is set to zero if there is no driver/ROM image. + // + CHAR8 StringId[4]; + // + // 4 char ASCII string to go in class identifier (option 60) in DHCP + // and Boot Server discover packets. + // For EfiNetworkInterfaceUndi this field is "UNDI". + // For EfiNetworkInterfaceSnp this field is "SNPN". + // + UINT8 Type; + UINT8 MajorVer; + UINT8 MinorVer; + // + // Information to be placed into the PXE DHCP and Discover packets. + // This is the network interface type and version number that will + // be placed into DHCP option 94 (client network interface identifier). + // + BOOLEAN Ipv6Supported; + UINT8 IfNum; // interface number to be used with pxeid structure +}; + +extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid; +extern EFI_GUID gEfiNetworkInterfaceIdentifierProtocolGuid_31; + +#endif // _EFI_NII_H diff --git a/MdePkg/Include/Protocol/FileInfo.h b/MdePkg/Include/Protocol/FileInfo.h new file mode 100644 index 0000000000..55cf6ae38e --- /dev/null +++ b/MdePkg/Include/Protocol/FileInfo.h @@ -0,0 +1,53 @@ +/** @file + SimpleFileSystem protocol as defined in the EFI 1.0 specification. + + The SimpleFileSystem protocol is the programatic access to the FAT (12,16,32) + file system specified in EFI 1.0. It can also be used to abstract any + file system other than FAT. + + EFI 1.0 can boot from any valid EFI image contained in a SimpleFileSystem + + Copyright (c) 2006, 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. + + Module Name: FileInfo.c + +**/ + +#ifndef __FILE_INFO_H__ +#define __FILE_INFO_H__ + +#define EFI_FILE_INFO_ID \ + { \ + 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct { + UINT64 Size; + UINT64 FileSize; + UINT64 PhysicalSize; + EFI_TIME CreateTime; + EFI_TIME LastAccessTime; + EFI_TIME ModificationTime; + UINT64 Attribute; + CHAR16 FileName[1]; +} EFI_FILE_INFO; + +// +// The FileName field of the EFI_FILE_INFO data structure is variable length. +// Whenever code needs to know the size of the EFI_FILE_INFO data structure, it needs to +// be the size of the data structure without the FileName field. The following macro +// computes this size correctly no matter how big the FileName array is declared. +// This is required to make the EFI_FILE_INFO data structure ANSI compilant. +// +#define SIZE_OF_EFI_FILE_INFO EFI_FIELD_OFFSET (EFI_FILE_INFO, FileName) + +extern EFI_GUID gEfiFileInfoGuid; + +#endif diff --git a/MdePkg/Include/Protocol/FileSystemInfo.h b/MdePkg/Include/Protocol/FileSystemInfo.h new file mode 100644 index 0000000000..f6e7488a08 --- /dev/null +++ b/MdePkg/Include/Protocol/FileSystemInfo.h @@ -0,0 +1,45 @@ +/** @file + FileSystemInfo protocol as defined in the EFI 1.0 specification. + + Copyright (c) 2006, 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. + + Module Name: FileSystemInfo.h + +**/ + +#ifndef __FILE_SYSTEM_INFO_H__ +#define __FILE_SYSTEM_INFO_H__ + +#define EFI_FILE_SYSTEM_INFO_ID_GUID \ + { \ + 0x9576e93, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct { + UINT64 Size; + BOOLEAN ReadOnly; + UINT64 VolumeSize; + UINT64 FreeSpace; + UINT32 BlockSize; + CHAR16 VolumeLabel[1]; +} EFI_FILE_SYSTEM_INFO; + +// +// The VolumeLabel field of the EFI_FILE_SYSTEM_INFO data structure is variable length. +// Whenever code needs to know the size of the EFI_FILE_SYSTEM_INFO data structure, it needs +// to be the size of the data structure without the VolumeLable field. The following macro +// computes this size correctly no matter how big the VolumeLable array is declared. +// This is required to make the EFI_FILE_SYSTEM_INFO data structure ANSI compilant. +// +#define SIZE_OF_EFI_FILE_SYSTEM_INFO EFI_FIELD_OFFSET (EFI_FILE_SYSTEM_INFO, VolumeLabel) + +extern EFI_GUID gEfiFileSystemInfoGuid; + +#endif diff --git a/MdePkg/Include/Protocol/FileSystemVolumeLabelInfo.h b/MdePkg/Include/Protocol/FileSystemVolumeLabelInfo.h new file mode 100644 index 0000000000..baba2764db --- /dev/null +++ b/MdePkg/Include/Protocol/FileSystemVolumeLabelInfo.h @@ -0,0 +1,42 @@ +/** @file + FileSystemVolumeLabelInfo protocol as defined in the EFI 1.0 specification. + + Copyright (c) 2006, 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. + + Module Name: FileSystemVolumeLabelInfo.h + +**/ + +#ifndef __FILE_SYSTEM_VOLUME_LABEL_INFO_H__ +#define __FILE_SYSTEM_VOLUME_LABEL_INFO_H__ + +#define EFI_FILE_SYSTEM_VOLUME_LABEL_INFO_ID_GUID \ + { \ + 0xDB47D7D3, 0xFE81, 0x11d3, {0x9A, 0x35, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } \ + } + +// +// Protocol Name defined in spec. +// +#define EFI_FILE_SYSTEM_VOLUME_LABEL_ID \ + EFI_FILE_SYSTEM_VOLUME_LABEL_INFO_ID_GUID + +typedef struct { + CHAR16 VolumeLabel[1]; +} EFI_FILE_SYSTEM_VOLUME_LABEL_INFO; + +typedef EFI_FILE_SYSTEM_VOLUME_LABEL_INFO EFI_FILE_SYSTEM_VOLUME_LABEL; + +#define SIZE_OF_EFI_FILE_SYSTEM_VOLUME_LABEL_INFO \ + EFI_FIELD_OFFSET (EFI_FILE_SYSTEM_VOLUME_LABEL_INFO, VolumeLabel) + +extern EFI_GUID gEfiFileSystemVolumeLabelInfoIdGuid; + +#endif diff --git a/MdePkg/Include/Protocol/FirmwareVolume.h b/MdePkg/Include/Protocol/FirmwareVolume.h new file mode 100644 index 0000000000..7f86dbb853 --- /dev/null +++ b/MdePkg/Include/Protocol/FirmwareVolume.h @@ -0,0 +1,321 @@ +/** @file + This file declares Firmware Volume protocol. + + Copyright (c) 2006, 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. + + Module Name: FirmwareVolume.h + + @par Revision Reference: + This protocol is defined in Firmware Volume specification. + Version 0.9 + +**/ + +#ifndef __FIRMWARE_VOLUME_H__ +#define __FIRMWARE_VOLUME_H__ + + +// +// Firmware Volume Protocol GUID definition +// +#define EFI_FIRMWARE_VOLUME_PROTOCOL_GUID \ + { \ + 0x389F751F, 0x1838, 0x4388, {0x83, 0x90, 0xCD, 0x81, 0x54, 0xBD, 0x27, 0xF8 } \ + } + +#define FV_DEVICE_SIGNATURE EFI_SIGNATURE_32 ('_', 'F', 'V', '_') + +typedef struct _EFI_FIRMWARE_VOLUME_PROTOCOL EFI_FIRMWARE_VOLUME_PROTOCOL; + +// +// EFI_FV_ATTRIBUTES bit definitions +// +typedef UINT64 EFI_FV_ATTRIBUTES; + +// +// ************************************************************ +// EFI_FV_ATTRIBUTES bit definitions +// ************************************************************ +// +#define EFI_FV_READ_DISABLE_CAP 0x0000000000000001ULL +#define EFI_FV_READ_ENABLE_CAP 0x0000000000000002ULL +#define EFI_FV_READ_STATUS 0x0000000000000004ULL + +#define EFI_FV_WRITE_DISABLE_CAP 0x0000000000000008ULL +#define EFI_FV_WRITE_ENABLE_CAP 0x0000000000000010ULL +#define EFI_FV_WRITE_STATUS 0x0000000000000020ULL + +#define EFI_FV_LOCK_CAP 0x0000000000000040ULL +#define EFI_FV_LOCK_STATUS 0x0000000000000080ULL +#define EFI_FV_WRITE_POLICY_RELIABLE 0x0000000000000100ULL + +#define EFI_FV_ALIGNMENT_CAP 0x0000000000008000ULL +#define EFI_FV_ALIGNMENT_2 0x0000000000010000ULL +#define EFI_FV_ALIGNMENT_4 0x0000000000020000ULL +#define EFI_FV_ALIGNMENT_8 0x0000000000040000ULL +#define EFI_FV_ALIGNMENT_16 0x0000000000080000ULL +#define EFI_FV_ALIGNMENT_32 0x0000000000100000ULL +#define EFI_FV_ALIGNMENT_64 0x0000000000200000ULL +#define EFI_FV_ALIGNMENT_128 0x0000000000400000ULL +#define EFI_FV_ALIGNMENT_256 0x0000000000800000ULL +#define EFI_FV_ALIGNMENT_512 0x0000000001000000ULL +#define EFI_FV_ALIGNMENT_1K 0x0000000002000000ULL +#define EFI_FV_ALIGNMENT_2K 0x0000000004000000ULL +#define EFI_FV_ALIGNMENT_4K 0x0000000008000000ULL +#define EFI_FV_ALIGNMENT_8K 0x0000000010000000ULL +#define EFI_FV_ALIGNMENT_16K 0x0000000020000000ULL +#define EFI_FV_ALIGNMENT_32K 0x0000000040000000ULL +#define EFI_FV_ALIGNMENT_64K 0x0000000080000000ULL + +// +// Protocol API definitions +// + +/** + Retrieves attributes, insures positive polarity of attribute bits, returns + resulting attributes in output parameter + + @param This Calling context + @param Attributes output buffer which contains attributes + + @retval EFI_INVALID_PARAMETER + @retval EFI_SUCCESS + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FV_GET_ATTRIBUTES) ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + OUT EFI_FV_ATTRIBUTES *Attributes + ); + +/** + Sets volume attributes + + @param This Calling context + @param Attributes Buffer which contains attributes + + @retval EFI_INVALID_PARAMETER + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FV_SET_ATTRIBUTES) ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN OUT EFI_FV_ATTRIBUTES *Attributes + ); + +typedef UINT32 EFI_FV_FILE_ATTRIBUTES; + +#define EFI_FV_FILE_ATTRIB_ALIGNMENT 0x0000001F + +/** + Read the requested file (NameGuid) and returns data in Buffer. + + @param This Calling context + @param NameGuid Filename identifying which file to read + @param Buffer Pointer to pointer to buffer in which contents of file are returned. +
+ If Buffer is NULL, only type, attributes, and size are returned as + there is no output buffer. +
+ If Buffer != NULL and *Buffer == NULL, the output buffer is allocated + from BS pool by ReadFile +
+ If Buffer != NULL and *Buffer != NULL, the output buffer has been + allocated by the caller and is being passed in. + + @param BufferSize Indicates the buffer size passed in, and on output the size + required to complete the read + @param FoundType Indicates the type of the file who's data is returned + @param FileAttributes Indicates the attributes of the file who's data is resturned + @param AuthenticationStatus Indicates the authentication status of the data + + @retval EFI_SUCCESS + @retval EFI_WARN_BUFFER_TOO_SMALL + @retval EFI_NOT_FOUND + @retval EFI_DEVICE_ERROR + @retval EFI_ACCESS_DENIED + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FV_READ_FILE) ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN EFI_GUID *NameGuid, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT EFI_FV_FILETYPE *FoundType, + OUT EFI_FV_FILE_ATTRIBUTES *FileAttributes, + OUT UINT32 *AuthenticationStatus + ); + +/** + Read the requested section from the specified file and returns data in Buffer. + + @param This Calling context + @param NameGuid Filename identifying the file from which to read + @param SectionType Indicates what section type to retrieve + @param SectionInstance Indicates which instance of SectionType to retrieve + @param Buffer Pointer to pointer to buffer in which contents of file are returned. +
+ If Buffer is NULL, only type, attributes, and size are returned as + there is no output buffer. +
+ If Buffer != NULL and *Buffer == NULL, the output buffer is allocated + from BS pool by ReadFile +
+ If Buffer != NULL and *Buffer != NULL, the output buffer has been + allocated by the caller and is being passed in. + + @param BufferSize Indicates the buffer size passed in, and on output the size + required to complete the read + @param AuthenticationStatus Indicates the authentication status of the data + + @retval EFI_SUCCESS + @retval EFI_WARN_BUFFER_TOO_SMALL + @retval EFI_OUT_OF_RESOURCES + @retval EFI_NOT_FOUND + @retval EFI_DEVICE_ERROR + @retval EFI_ACCESS_DENIED + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FV_READ_SECTION) ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + IN OUT VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ); + +typedef UINT32 EFI_FV_WRITE_POLICY; + +#define EFI_FV_UNRELIABLE_WRITE 0x00000000 +#define EFI_FV_RELIABLE_WRITE 0x00000001 + +typedef struct { + EFI_GUID *NameGuid; + EFI_FV_FILETYPE Type; + EFI_FV_FILE_ATTRIBUTES FileAttributes; + VOID *Buffer; + UINT32 BufferSize; +} EFI_FV_WRITE_FILE_DATA; + +/** + Write the supplied file (NameGuid) to the FV. + + @param This Calling context + @param NumberOfFiles Indicates the number of file records pointed to by FileData + @param WritePolicy Indicates the level of reliability of the write with respect to + things like power failure events. + @param FileData A pointer to an array of EFI_FV_WRITE_FILE_DATA structures. Each + element in the array indicates a file to write, and there are + NumberOfFiles elements in the input array. + + @retval EFI_SUCCESS + @retval EFI_OUT_OF_RESOURCES + @retval EFI_DEVICE_ERROR + @retval EFI_WRITE_PROTECTED + @retval EFI_NOT_FOUND + @retval EFI_INVALID_PARAMETER + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FV_WRITE_FILE) ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN UINT32 NumberOfFiles, + IN EFI_FV_WRITE_POLICY WritePolicy, + IN EFI_FV_WRITE_FILE_DATA *FileData + ); + +/** + Given the input key, search for the next matching file in the volume. + + @param This Calling context + @param Key Pointer to a caller allocated buffer that contains an implementation + specific key that is used to track where to begin searching on + successive calls. + @param FileType Indicates the file type to filter for + @param NameGuid Guid filename of the file found + @param Attributes Attributes of the file found + @param Size Size in bytes of the file found + + @retval EFI_SUCCESS + @retval EFI_NOT_FOUND + @retval EFI_DEVICE_ERROR + @retval EFI_ACCESS_DENIED + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FV_GET_NEXT_FILE) ( + IN EFI_FIRMWARE_VOLUME_PROTOCOL *This, + IN OUT VOID *Key, + IN OUT EFI_FV_FILETYPE *FileType, + OUT EFI_GUID *NameGuid, + OUT EFI_FV_FILE_ATTRIBUTES *Attributes, + OUT UINTN *Size + ); + +/** + @par Protocol Description: + The Firmware Volume Protocol provides file-level access to the firmware volume. + Each firmware volume driver must produce an instance of the Firmware Volume + Protocol if the firmware volume is to be visible to the system. The Firmware + Volume Protocol also provides mechanisms for determining and modifying some + attributes of the firmware volume. + + @param GetVolumeAttributes + Retrieves volume capabilities and current settings. + + @param SetVolumeAttributes + Modifies the current settings of the firmware volume. + + @param ReadFile + Reads an entire file from the firmware volume. + + @param ReadSection + Reads a single section from a file into a buffer. + + @param WriteFile + Writes an entire file into the firmware volume. + + @param GetNextFile + Provides service to allow searching the firmware volume. + + @param KeySize + Data field that indicates the size in bytes of the Key input buffer for + the GetNextFile() API. + + @param ParentHandle + Handle of the parent firmware volume. + +**/ +struct _EFI_FIRMWARE_VOLUME_PROTOCOL { + EFI_FV_GET_ATTRIBUTES GetVolumeAttributes; + EFI_FV_SET_ATTRIBUTES SetVolumeAttributes; + EFI_FV_READ_FILE ReadFile; + EFI_FV_READ_SECTION ReadSection; + EFI_FV_WRITE_FILE WriteFile; + EFI_FV_GET_NEXT_FILE GetNextFile; + UINT32 KeySize; + EFI_HANDLE ParentHandle; +}; + +extern EFI_GUID gEfiFirmwareVolumeProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/FirmwareVolumeBlock.h b/MdePkg/Include/Protocol/FirmwareVolumeBlock.h new file mode 100644 index 0000000000..ee849a141e --- /dev/null +++ b/MdePkg/Include/Protocol/FirmwareVolumeBlock.h @@ -0,0 +1,251 @@ +/** @file + This file declares Firmware Volume Block protocol. + + Low level firmware device access routines to abstract firmware device + hardware. + + Copyright (c) 2006, 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. + + Module Name: FirmwareVolumeBlock.h + + @par Revision Reference: + This protocol is defined in Framework of EFI Firmware Volume Block specification. + Version 0.9 + +**/ + +#ifndef __FIRMWARE_VOLUME_BLOCK_H__ +#define __FIRMWARE_VOLUME_BLOCK_H__ + + +#define EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL_GUID \ + { \ + 0xDE28BC59, 0x6228, 0x41BD, {0xBD, 0xF6, 0xA3, 0xB9, 0xAD, 0xB5, 0x8D, 0xA1 } \ + } + +typedef struct _EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL; + +/** + Retrieves Volume attributes. No polarity translations are done. + + @param This Calling context + @param Attributes output buffer which contains attributes + + @retval EFI_INVALID_PARAMETER + @retval EFI_SUCCESS + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FVB_GET_ATTRIBUTES) ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_FVB_ATTRIBUTES *Attributes + ) +; + +/** + Sets Volume attributes. No polarity translations are done. + + @param This Calling context + @param Attributes On input: contains new attributes + On output: contains current attributes of FV + + @retval EFI_INVALID_PARAMETER + @retval EFI_SUCCESS + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FVB_SET_ATTRIBUTES) ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN OUT EFI_FVB_ATTRIBUTES *Attributes + ) +; + +/** + Retrieves the physical address of a memory mapped FV. + + @param This Calling context + @param Attributes Address is a pointer to a caller allocated EFI_PHYSICAL_ADDRESS + that on successful return from GetPhysicalAddress() contains the + base address of the firmware volume. + + @retval EFI_UNSUPPORTED + @retval EFI_SUCCESS + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FVB_GET_PHYSICAL_ADDRESS) ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + OUT EFI_PHYSICAL_ADDRESS *Address + ) +; + +/** + Retrieves the size in bytes of a specific block within an FV. + + @param This Calling context. + @param Lba Indicates which block to return the size for. + @param BlockSize BlockSize is a pointer to a caller allocated + UINTN in which the size of the block is returned. + @param NumberOfBlocks NumberOfBlocks is a pointer to a caller allocated + UINTN in which the number of consecutive blocks + starting with Lba is returned. All blocks in this + range have a size of BlockSize. + + @retval EFI_INVALID_PARAMETER + @retval EFI_SUCCESS + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FVB_GET_BLOCK_SIZE) ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + OUT UINTN *BlockSize, + OUT UINTN *NumberOfBlocks + ) +; + +/** + Reads data beginning at Lba:Offset from FV and places the data in Buffer. + The read terminates either when *NumBytes of data have been read, or when + a block boundary is reached. *NumBytes is updated to reflect the actual + number of bytes read. + + @param This Calling context + @param Lba Block in which to begin read + @param Offset Offset in the block at which to begin read + @param NumBytes At input, indicates the requested read size. At output, indicates + the actual number of bytes read. + @param Buffer Data buffer in which to place data read. + + @retval EFI_INVALID_PARAMETER + @retval EFI_NOT_FOUND + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FVB_READ) ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + OUT UINT8 *Buffer + ) +; + +/** + Writes data beginning at Lba:Offset from FV. The write terminates either + when *NumBytes of data have been written, or when a block boundary is + reached. *NumBytes is updated to reflect the actual number of bytes + written. + + @param This Calling context + @param Lba Block in which to begin write + @param Offset Offset in the block at which to begin write + @param NumBytes At input, indicates the requested write size. At output, indicates + the actual number of bytes written. + @param Buffer Buffer containing source data for the write. + + @retval EFI_INVALID_PARAMETER + @retval EFI_NOT_FOUND + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FVB_WRITE) ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + IN EFI_LBA Lba, + IN UINTN Offset, + IN OUT UINTN *NumBytes, + IN UINT8 *Buffer + ) +; + +#define EFI_LBA_LIST_TERMINATOR 0xFFFFFFFFFFFFFFFFULL + +/** + The EraseBlock() function erases one or more blocks as denoted by the + variable argument list. The entire parameter list of blocks must be verified + prior to erasing any blocks. If a block is requested that does not exist + within the associated firmware volume (it has a larger index than the last + block of the firmware volume), the EraseBlock() function must return + EFI_INVALID_PARAMETER without modifying the contents of the firmware volume. + + @param This Calling context + @param ... Starting LBA followed by Number of Lba to erase. a -1 to terminate + the list. + + @retval EFI_INVALID_PARAMETER + @retval EFI_DEVICE_ERROR + @retval EFI_SUCCESS + @retval EFI_ACCESS_DENIED + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FVB_ERASE_BLOCKS) ( + IN EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *This, + ... + ) +; + +/** + @par Protocol Description: + This protocol provides control over block-oriented firmware devices. + Typically, the FFS (or an alternate file system) driver consumes the + Firmware Volume Block Protocol and produces the Firmware Volume Protocol. + + @param GetAttributes + Retrieves the current volume attributes. + + @param SetAttributes + Sets the current volume attributes. + + @param GetPhysicalAddress + Retrieves the memory-mapped address of the firmware volume. + + @param GetBlockSize + Retrieves the size for a specific block. + + @param Read + Reads n bytes into a buffer from the firmware volume hardware. + + @param Write + Writes n bytes from a buffer into the firmware volume hardware. + + @param EraseBlocks + Erases specified block(s) and sets all values as indicated by + the EFI_FVB_ERASE_POLARITY bit. + + @param ParentHandle + Handle of the parent firmware volume. + +**/ +struct _EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL { + EFI_FVB_GET_ATTRIBUTES GetVolumeAttributes; + EFI_FVB_SET_ATTRIBUTES SetVolumeAttributes; + EFI_FVB_GET_PHYSICAL_ADDRESS GetPhysicalAddress; + EFI_FVB_GET_BLOCK_SIZE GetBlockSize; + EFI_FVB_READ Read; + EFI_FVB_WRITE Write; + EFI_FVB_ERASE_BLOCKS EraseBlocks; + EFI_HANDLE ParentHandle; +}; + +extern EFI_GUID gEfiFirmwareVolumeBlockProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/FirmwareVolumeDispatch.h b/MdePkg/Include/Protocol/FirmwareVolumeDispatch.h new file mode 100644 index 0000000000..249a476b77 --- /dev/null +++ b/MdePkg/Include/Protocol/FirmwareVolumeDispatch.h @@ -0,0 +1,33 @@ +/** @file + This file declares Firmware Volume Dispatch protocol. + + Presence of this protocol tells the dispatch to dispatch from this Firmware + Volume + + Copyright (c) 2006, 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. + + Module Name: FirmwareVolumeDispatch.h + + @par Revision Reference: + This protol will be defined in DXE CIS Spec. + Version 0.91C. + +**/ + +#ifndef __FIRMWARE_VOLUME_DISPATCH_H__ +#define __FIRMWARE_VOLUME_DISPATCH_H__ + +#define EFI_FIRMWARE_VOLUME_DISPATCH_PROTOCOL_GUID \ + { 0x7aa35a69, 0x506c, 0x444f, {0xa7, 0xaf, 0x69, 0x4b, 0xf5, 0x6f, 0x71, 0xc8 } } + + +extern EFI_GUID gEfiFirmwareVolumeDispatchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/FormBrowser.h b/MdePkg/Include/Protocol/FormBrowser.h new file mode 100644 index 0000000000..c0ee94ad65 --- /dev/null +++ b/MdePkg/Include/Protocol/FormBrowser.h @@ -0,0 +1,180 @@ +/** @file + The EFI_FORM_BROWSER_PROTOCOL is the interface to the EFI + Configuration Driver. This will allow the caller to direct the + configuration driver to use either the HII database or use the passed + in packet of data. This will also allow the caller to post messages + into the configuration drivers internal mailbox. + + Copyright (c) 2006, 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. + + Module Name: FormBrowser.h + + @par Revision Reference: + This protocol is defined in HII spec 0.92. + +**/ + +#ifndef __FORM_BROWSER_H__ +#define __FORM_BROWSER_H__ + + +#define EFI_FORM_BROWSER_PROTOCOL_GUID \ + { \ + 0xe5a1333e, 0xe1b4, 0x4d55, {0xce, 0xeb, 0x35, 0xc3, 0xef, 0x13, 0x34, 0x43 } \ + } + +typedef struct _EFI_FORM_BROWSER_PROTOCOL EFI_FORM_BROWSER_PROTOCOL; + +typedef struct { + UINT32 Length; + UINT16 Type; + UINT8 Data[1]; +} EFI_HII_PACKET; + +typedef struct { + EFI_HII_IFR_PACK *IfrData; + EFI_HII_STRING_PACK *StringData; +} EFI_IFR_PACKET; + +typedef struct { + UINTN LeftColumn; + UINTN RightColumn; + UINTN TopRow; + UINTN BottomRow; +} EFI_SCREEN_DESCRIPTOR; + +/** + Provides direction to the configuration driver whether to use the HII + database or a passed-in set of data. This function also establishes a + pointer to the calling driver¡¯s callback interface. + + @param This A pointer to the EFI_FORM_BROWSER_PROTOCOL instance. + + @param UseDatabase Determines whether the HII database is to be + used to gather information. If the value is FALSE, the configuration + driver will get the information provided in the passed-in Packet parameters. + + @param Handle A pointer to an array of HII handles to display. This value + should correspond to the value of the HII form package that is required to + be displayed. + + @param HandleCount The number of handles in the array specified by Handle. + + @param Packet A pointer to a set of data containing pointers to IFR + and/or string data. + + @param CallbackHandle The handle to the driver¡¯s callback interface. + This parameter is used only when the UseDatabase parameter is FALSE + and an application wants to register a callback with the browser + + @param NvMapOverride This buffer is used only when there is no NV variable + to define the current settings and the caller needs to provide to the browser + the current settings for the "fake" NV variable. + + @param ScreenDimensions Allows the browser to be called so that it occupies + a portion of the physical screen instead of dynamically determining the + screen dimensions. + + @param ResetRequired This BOOLEAN value will tell the caller if a reset + is required based on the data that might have been changed. The ResetRequired + parameter is primarily applicable for configuration applications, and is an + optional parameter. + + @retval EFI_SUCCESS The function completed successfully + + @retval EFI_NOT_FOUND The variable was not found. + + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. + DataSize has been updated with the size needed to complete the request. + + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + + @retval EFI_DEVICE_ERROR The variable could not be saved due to a hardware failure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SEND_FORM) ( + IN EFI_FORM_BROWSER_PROTOCOL *This, + IN BOOLEAN UseDatabase, + IN EFI_HII_HANDLE *Handle, + IN UINTN HandleCount, + IN EFI_IFR_PACKET *Packet, OPTIONAL + IN EFI_HANDLE CallbackHandle, OPTIONAL + IN UINT8 *NvMapOverride, OPTIONAL + IN EFI_SCREEN_DESCRIPTOR *ScreenDimensions, OPTIONAL + OUT BOOLEAN *ResetRequired OPTIONAL + ); + +/** + Routine used to abstract a generic dialog interface and return the selected + key or string. + + @param NumberOfLines The number of lines for the dialog box. + + @param HotKey Defines whether a single character is parsed (TRUE) + and returned in KeyValue or if a string is returned in StringBuffer. + + @param MaximumStringSize The maximum size in bytes of a typed-in string. + Because each character is a CHAR16, the minimum string returned is two bytes. + + @param StringBuffer The passed-in pointer to the buffer that will hold + the typed in string if HotKey is FALSE. + + @param KeyValue The EFI_INPUT_KEY value returned if HotKey is TRUE. + + @param String The pointer to the first string in the list of strings + that comprise the dialog box. + + @param ... A series of NumberOfLines text strings that will be used + to construct the dialog box. + + @retval EFI_SUCCESS The dialog was displayed and user interaction was received. + + @retval EFI_DEVICE_ERROR The user typed in an ESC character to exit the routine. + + @retval EFI_INVALID_PARAMETER One of the parameters was invalid + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREATE_POP_UP) ( + IN UINTN NumberOfLines, + IN BOOLEAN HotKey, + IN UINTN MaximumStringSize, + OUT CHAR16 *StringBuffer, + OUT EFI_INPUT_KEY *KeyValue, + IN CHAR16 *String, + ... + ); + +/** + @par Protocol Description: + The EFI_FORM_BROWSER_PROTOCOL is the interface to call for drivers to + leverage the EFI configuration driver interface. + + @param SendForm + Provides direction to the configuration driver whether to use the HII + database or to use a passed-in set of data. This functions also establishes + a pointer to the calling driver¡¯s callback interface. + + @param CreatePopUp + Routine used to abstract a generic dialog interface and return the + selected key or string. + +**/ +struct _EFI_FORM_BROWSER_PROTOCOL { + EFI_SEND_FORM SendForm; + EFI_CREATE_POP_UP CreatePopUp; +}; + +extern EFI_GUID gEfiFormBrowserProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/FormCallback.h b/MdePkg/Include/Protocol/FormCallback.h new file mode 100644 index 0000000000..7a1c5398b8 --- /dev/null +++ b/MdePkg/Include/Protocol/FormCallback.h @@ -0,0 +1,227 @@ +/** @file + The EFI_FORM_CALLBACK_PROTOCOL is the defined interface for access to custom + NV storage devices as well as communication of user selections in a more + interactive environment. This protocol should be published by hardware + specific drivers which want to export access to custom hardware storage or + publish IFR which has a requirement to call back the original driver. + + Copyright (c) 2006, 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. + + Module Name: FormCallback.h + + @par Revision Reference: + This protocol is defined in HII spec 0.92. + +**/ + +#ifndef __FORM_CALLBACK_H__ +#define __FORM_CALLBACK_H__ + + +#define EFI_FORM_CALLBACK_PROTOCOL_GUID \ + { \ + 0xf3e4543d, 0xcf35, 0x6cef, {0x35, 0xc4, 0x4f, 0xe6, 0x34, 0x4d, 0xfc, 0x54 } \ + } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_FORM_CALLBACK_PROTOCOL EFI_FORM_CALLBACK_PROTOCOL; + + +#define RESET_REQUIRED 1 // Flags setting to signify that the callback operation resulted in an eventual +// reset to be done upon exit of the browser +// +#define EXIT_REQUIRED 2 // Flags setting to signify that after the processing of the callback results - exit the browser +#define SAVE_REQUIRED 4 // Flags setting to signify that after the processing of the callback results - save the NV data +#define NV_CHANGED 8 // Flags setting to signify that after the processing of the callback results - turn the NV flag on +#define NV_NOT_CHANGED 16 // Flags setting to signify that after the processing of the callback results - turn the NV flag off +#pragma pack(1) +typedef struct { + UINT8 OpCode; // Likely a string, numeric, or one-of + UINT8 Length; // Length of the EFI_IFR_DATA_ENTRY packet + UINT16 Flags; // Flags settings to determine what behavior is desired from the browser after the callback + VOID *Data; // The data in the form based on the op-code type - this is not a pointer to the data, the data follows immediately + // If the OpCode is a OneOf or Numeric type - Data is a UINT16 value + // If the OpCode is a String type - Data is a CHAR16[x] type + // If the OpCode is a Checkbox type - Data is a UINT8 value + // If the OpCode is a NV Access type - Data is a EFI_IFR_NV_DATA structure + // +} EFI_IFR_DATA_ENTRY; + +typedef struct { + VOID *NvRamMap; // If the flag of the op-code specified retrieval of a copy of the NVRAM map, + // this is a pointer to a buffer copy + // + UINT32 EntryCount; // How many EFI_IFR_DATA_ENTRY entries + // + // EFI_IFR_DATA_ENTRY Data[1]; // The in-line Data entries. + // +} EFI_IFR_DATA_ARRAY; + +typedef union { + EFI_IFR_DATA_ARRAY DataArray; // Primarily used by those who call back to their drivers and use HII as a repository + EFI_IFR_PACKET DataPacket; // Primarily used by those which do not use HII as a repository + CHAR16 *String; // If returning an error - fill the string with null-terminated contents +} EFI_HII_CALLBACK_PACKET; + +typedef struct { + EFI_IFR_OP_HEADER Header; + UINT16 QuestionId; // Offset into the map + UINT8 StorageWidth; // Width of the value + // + // CHAR8 Data[1]; // The Data itself + // +} EFI_IFR_NV_DATA; + +#pragma pack() +// +// The following types are currently defined: +// +/** + Returns the value of a variable. + + @param This A pointer to the EFI_FORM_CALLBACK_PROTOCOL instance. + + @param VariableName A NULL-terminated Unicode string that is the + name of the vendor¡¯s variable. + + @param VendorGuid A unique identifier for the vendor. + + @param Attributes If not NULL, a pointer to the memory location to + return the attribute's bit-mask for the variable. + + @param DataSize The size in bytes of the Buffer. A size of zero causes + the variable to be deleted. + + @param Buffer The buffer to return the contents of the variable. + + @retval EFI_SUCCESS The function completed successfully. + + @retval EFI_NOT_FOUND The variable was not found. + + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. + DataSize has been updated with the size needed to complete the request. + + @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. + + @retval EFI_DEVICE_ERROR The variable could not be saved due to a hardware failure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_NV_READ) ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes OPTIONAL, + IN OUT UINTN *DataSize, + OUT VOID *Buffer + ); + +/** + Sets the value of a variable. + + @param This A pointer to the EFI_FORM_CALLBACK_PROTOCOL instance. + + @param VariableName A NULL-terminated Unicode string that is the + name of the vendor's variable. Each VariableName is unique for each VendorGuid. + + @param VendorGuid A unique identifier for the vendor. + + @param Attributes Attributes bit-mask to set for the variable. + + @param DataSize The size in bytes of the Buffer. A size of zero causes + the variable to be deleted. + + @param Buffer The buffer containing the contents of the variable. + + @param ResetRequired Returns a value from the driver that abstracts + this information and will enable a system to know if a system reset + is required to achieve the configuration changes being enabled through + this function. + + @retval EFI_SUCCESS The firmware has successfully stored the variable and + its data as defined by the Attributes. + + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold + the variable and its data. + + @retval EFI_INVALID_PARAMETER An invalid combination of Attributes bits + was supplied, or the DataSize exceeds the maximum allowed. + + @retval EFI_DEVICE_ERROR The variable could not be saved due to a hardware failure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_NV_WRITE) ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Buffer, + OUT BOOLEAN *ResetRequired + ); + +/** + This function is called to provide results data to the driver. + + @param This A pointer to the EFI_FORM_CALLBACK_PROTOCOL instance. + + @param KeyValue A unique value which is sent to the original exporting + driver so that it can identify the type of data to expect. The format of + the data tends to vary based on the opcode that generated the callback. + + @param Data A pointer to the data being sent to the original exporting driver. + + @param Packet A pointer to a packet of information which a driver passes + back to the browser. + + @return Status Code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FORM_CALLBACK) ( + IN EFI_FORM_CALLBACK_PROTOCOL *This, + IN UINT16 KeyValue, + IN EFI_IFR_DATA_ARRAY *Data, + OUT EFI_HII_CALLBACK_PACKET **Packet + ); + +/** + @par Protocol Description: + The EFI_FORM_CALLBACK_PROTOCOL is the defined interface for access to + custom NVS devices as well as communication of user selections in a more + interactive environment. This protocol should be published by hardware-specific + drivers that want to export access to custom hardware storage or publish IFR + that has a requirement to call back the original driver. + + @param NvRead + The read operation to access the NV data serviced by a hardware-specific driver. + + @param NvWrite + The write operation to access the NV data serviced by a hardware-specific driver. + + @param Callback + The function that is called from the configuration browser to communicate key value pairs. + +**/ +struct _EFI_FORM_CALLBACK_PROTOCOL { + EFI_NV_READ NvRead; + EFI_NV_WRITE NvWrite; + EFI_FORM_CALLBACK Callback; +}; + +extern EFI_GUID gEfiFormCallbackProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/GraphicsOutput.h b/MdePkg/Include/Protocol/GraphicsOutput.h new file mode 100644 index 0000000000..1b4e1fca06 --- /dev/null +++ b/MdePkg/Include/Protocol/GraphicsOutput.h @@ -0,0 +1,194 @@ +/** @file + Graphics Output Protocol from the UEFI 2.0 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006, 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. + + Module Name: GraphicsOutput.h + +**/ + +#ifndef __GRAPHICS_OUTPUT_H__ +#define __GRAPHICS_OUTPUT_H__ + +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + { \ + 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \ + } + +typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL; + +typedef struct { + UINT32 RedMask; + UINT32 GreenMask; + UINT32 BlueMask; + UINT32 ReservedMask; +} EFI_PIXEL_BITMASK; + +typedef enum { + PixelRedGreenBlueReserved8BitPerColor, + PixelBlueGreenRedReserved8BitPerColor, + PixelBitMask, + PixelBltOnly, + PixelFormatMax +} EFI_GRAPHICS_PIXEL_FORMAT; + +typedef struct { + UINT32 Version; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PIXEL_BITMASK PixelInformation; + UINT32 PixelsPerScanLine; +} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to be set. + + @retval EFI_SUCCESS Graphics mode was changed. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber + ) +; + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL; + +typedef union { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel; + UINT32 Raw; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION; + +typedef enum { + EfiBltVideoFill, + EfiBltVideoToBltBuffer, + EfiBltBufferToVideo, + EfiBltVideoToVideo, + EfiGraphicsOutputBltOperationMax +} EFI_GRAPHICS_OUTPUT_BLT_OPERATION; + +/** + The following table defines actions for BltOperations: + + EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + + EfiBltVideoToBltBuffer - Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + + EfiBltBufferToVideo - Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + + EfiBltVideoToVideo - Copy from the video display rectangle (SourceX, SourceY) + (SourceX + Width, SourceY + Height) .to the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + @param This Protocol instance pointer. + @param BltBuffer Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + @param BltOperation Operation to perform on BlitBuffer and video memory + @param SourceX X coordinate of source for the BltBuffer. + @param SourceY Y coordinate of source for the BltBuffer. + @param DestinationX X coordinate of destination for the BltBuffer. + @param DestinationY Y coordinate of destination for the BltBuffer. + @param Width Width of rectangle in BltBuffer in pixels. + @param Height Hight of rectangle in BltBuffer in pixels. + @param Delta OPTIONAL + + @retval EFI_SUCCESS The Blt operation completed. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR A hardware error occured writting to the video buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +typedef struct { + UINT32 MaxMode; + UINT32 Mode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINTN SizeOfInfo; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + UINTN FrameBufferSize; +} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; + +struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { + EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; +}; + +extern EFI_GUID gEfiGraphicsOutputProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/GuidedSectionExtraction.h b/MdePkg/Include/Protocol/GuidedSectionExtraction.h new file mode 100644 index 0000000000..d98c56a7bc --- /dev/null +++ b/MdePkg/Include/Protocol/GuidedSectionExtraction.h @@ -0,0 +1,102 @@ +/** @file + This file declares GUIDed section extraction protocol. + + This interface provides a means of decoding a GUID defined encapsulation + section. There may be multiple different GUIDs associated with the GUIDed + section extraction protocol. That is, all instances of the GUIDed section + extraction protocol must have the same interface structure. + + Copyright (c) 2006, 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. + + Module Name: GuidedSectionExtraction.h + + @par Revision Reference: + This protocol is defined in Firmware Volume Specification. + Version 0.9 + +**/ + +#ifndef __GUIDED_SECTION_EXTRACTION_PROTOCOL_H__ +#define __GUIDED_SECTION_EXTRACTION_PROTOCOL_H__ + + +// +// Protocol GUID definition. Each GUIDed section extraction protocol has the +// same interface but with different GUID. All the GUIDs is defined here. +// May add multiple GUIDs here. +// +#define EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID \ + { \ + 0xFC1BCDB0, 0x7D31, 0x49aa, {0x93, 0x6A, 0xA4, 0x60, 0x0D, 0x9D, 0xD0, 0x83 } \ + } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL; + +// +// Protocol member functions +// +/** + Processes the input section and returns the data contained therein along + with the authentication status. + + @param This Indicates the EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance. + @param InputSection Buffer containing the input GUIDed section to be processed. + @param OutputBuffer *OutputBuffer is allocated from boot services pool memory + and contains the new section stream. + @param OutputSize A pointer to a caller-allocated UINTN in which the size + of *OutputBuffer allocation is stored. + @param AuthenticationStatus A pointer to a caller-allocated UINT32 that + indicates the authentication status of the output buffer. + + @retval EFI_SUCCESS The InputSection was successfully processed and the + section contents were returned. + @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to + process the request. + @retval EFI_INVALID_PARAMETER The GUID in InputSection does not match + this instance of the GUIDed Section Extraction Protocol. + +**/ + +typedef +EFI_STATUS +(EFIAPI *EFI_EXTRACT_GUIDED_SECTION) ( + IN EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This, + IN VOID *InputSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize, + OUT UINT32 *AuthenticationStatus + ); + +// +// Protocol definition +// +/** + @par Protocol Description: + If a GUID-defined section is encountered when doing section extraction, + the section extraction driver calls the appropriate instance of the GUIDed + Section Extraction Protocol to extract the section stream contained therein. + + @param ExtractSection + Takes the GUIDed section as input and produces the section stream data. + +**/ +struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL { + EFI_EXTRACT_GUIDED_SECTION ExtractSection; +}; + +// +// may add other GUID here +// +extern EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Hash.h b/MdePkg/Include/Protocol/Hash.h new file mode 100644 index 0000000000..7007c78142 --- /dev/null +++ b/MdePkg/Include/Protocol/Hash.h @@ -0,0 +1,149 @@ +/** @file + EFI_HASH_SERVICE_BINDING_PROTOCOL as defined in UEFI 2.0. + EFI_HASH_PROTOCOL as defined in UEFI 2.0. + The EFI Hash Service Binding Protocol is used to locate hashing services support + provided by a driver and create and destroy instances of the EFI Hash Protocol + so that a multiple drivers can use the underlying hashing services. + The EFI Service Binding Protocol defines the generic Service Binding Protocol functions. + + Copyright (c) 2006, 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. + + Module Name: Hash.h + +**/ + +#ifndef __EFI_HASH_PROTOCOL_H__ +#define __EFI_HASH_PROTOCOL_H__ + +#define EFI_HASH_SERVICE_BINDING_PROTOCOL \ + { \ + 0x42881c98, 0xa4f3, 0x44b0, {0xa3, 0x9d, 0xdf, 0xa1, 0x86, 0x67, 0xd8, 0xcd } \ + } + +#define EFI_HASH_PROTOCOL_GUID \ + { \ + 0xc5184932, 0xdba5, 0x46db, {0xa5, 0xba, 0xcc, 0x0b, 0xda, 0x9c, 0x14, 0x35 } \ + } + +#define EFI_HASH_ALGORITHM_SHA1_GUID \ + { \ + 0x2ae9d80f, 0x3fb2, 0x4095, {0xb7, 0xb1, 0xe9, 0x31, 0x57, 0xb9, 0x46, 0xb6 } \ + } + +#define EFI_HASH_ALGORITHM_SHA224_GUID \ + { \ + 0x8df01a06, 0x9bd5, 0x4bf7, {0xb0, 0x21, 0xdb, 0x4f, 0xd9, 0xcc, 0xf4, 0x5b } \ + } + +#define EFI_HASH_ALGORITHM_SHA256_GUID \ + { \ + 0x51aa59de, 0xfdf2, 0x4ea3, {0xbc, 0x63, 0x87, 0x5f, 0xb7, 0x84, 0x2e, 0xe9 } \ + } + +#define EFI_HASH_ALGORITHM_SHA384_GUID \ + { \ + 0xefa96432, 0xde33, 0x4dd2, {0xae, 0xe6, 0x32, 0x8c, 0x33, 0xdf, 0x77, 0x7a } \ + } + +#define EFI_HASH_ALGORITHM_SHA512_GUID \ + { \ + 0xcaa4381e, 0x750c, 0x4770, {0xb8, 0x70, 0x7a, 0x23, 0xb4, 0xe4, 0x21, 0x30 } \ + } + +#define EFI_HASH_ALGORTIHM_MD5_GUID \ + { \ + 0xaf7c79c, 0x65b5, 0x4319, {0xb0, 0xae, 0x44, 0xec, 0x48, 0x4e, 0x4a, 0xd7 } \ + } + +typedef struct _EFI_HASH_PROTOCOL EFI_HASH_PROTOCOL; + +typedef UINT8 EFI_MD5_HASH[16]; +typedef UINT8 EFI_SHA1_HASH[20]; +typedef UINT8 EFI_SHA224_HASH[28]; +typedef UINT8 EFI_SHA256_HASH[32]; +typedef UINT8 EFI_SHA384_HASH[48]; +typedef UINT8 EFI_SHA512_HASH[64]; + +typedef union { + EFI_MD5_HASH *Md5Hash; + EFI_SHA1_HASH *Sha1Hash; + EFI_SHA224_HASH *Sha224Hash; + EFI_SHA256_HASH *Sha256Hash; + EFI_SHA384_HASH *Sha384Hash; + EFI_SHA512_HASH *Sha512Hash; +} EFI_HASH_OUTPUT; + +/** + Returns the size of the hash which results from a specific algorithm. + + @param This Points to this instance of EFI_HASH_PROTOCOL. + @param HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use. + @param HashSize Holds the returned size of the algorithm¡¯s hash. + + @retval EFI_SUCCESS Hash size returned successfully. + @retval EFI_INVALID_PARAMETER HashSize is NULL + @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported + by this driver. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HASH_GET_HASH_SIZE) ( + IN CONST EFI_HASH_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm, + OUT UINTN *HashSize + ) +; + +/** + Returns the size of the hash which results from a specific algorithm. + + @param This Points to this instance of EFI_HASH_PROTOCOL. + @param HashAlgorithm Points to the EFI_GUID which identifies the algorithm to use. + @param Extend Specifies whether to create a new hash (FALSE) or extend the specified + existing hash (TRUE). + @param Message Points to the start of the message. + @param MessageSize The size of Message, in bytes. + @param Hash On input, if Extend is TRUE, then this holds the hash to extend. On + output, holds the resulting hash computed from the message. + + @retval EFI_SUCCESS Hash returned successfully. + @retval EFI_INVALID_PARAMETER Message or Hash is NULL + @retval EFI_UNSUPPORTED The algorithm specified by HashAlgorithm is not supported by this + driver. Or extend is TRUE and the algorithm doesn¡¯t support extending the hash. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HASH_HASH) ( + IN CONST EFI_HASH_PROTOCOL *This, + IN CONST EFI_GUID *HashAlgorithm, + IN BOOLEAN Extend, + IN CONST UINT8 *Message, + IN UINT64 MessageSize, + IN OUT EFI_HASH_OUTPUT *Hash + ) +; + +struct _EFI_HASH_PROTOCOL { + EFI_HASH_GET_HASH_SIZE GetHashSize; + EFI_HASH_HASH Hash; +}; + +extern EFI_GUID gEfiHashServiceBindingProtocolGuid; +extern EFI_GUID gEfiHashProtocolGuid; +extern EFI_GUID gEfiHashAlgorithmSha1Guid; +extern EFI_GUID gEfiHashAlgorithmSha224Guid; +extern EFI_GUID gEfiHashAlgorithmSha256Guid; +extern EFI_GUID gEfiHashAlgorithmSha384Guid; +extern EFI_GUID gEfiHashAlgorithmSha512Guid; +extern EFI_GUID gEfiHashAlgorithmMD5Guid; + +#endif diff --git a/MdePkg/Include/Protocol/Hii.h b/MdePkg/Include/Protocol/Hii.h new file mode 100644 index 0000000000..ceeba1c7fb --- /dev/null +++ b/MdePkg/Include/Protocol/Hii.h @@ -0,0 +1,1024 @@ +/** @file + This file defines the Human Interface Infrastructure protocol which will + be used by resources which want to publish IFR/Font/String data and have it + collected by the Configuration engine. + + Copyright (c) 2006, 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. + + Module Name: Hii.h + + @par Revision Reference: + This protocol is defined in HII spec 0.92. + +**/ + +#ifndef __HII_H__ +#define __HII_H__ + + +#define EFI_HII_PROTOCOL_GUID \ + { \ + 0xea816d2c, 0xcee5, 0x4f02, {0x99, 0xb5, 0xd3, 0x90, 0x5c, 0xbb, 0xd0, 0x77 } \ + } + +// BugBug: +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// If UGA goes away we need to put this some place. I'm not sure where? +// +//typedef struct { +// UINT8 Blue; +// UINT8 Green; +// UINT8 Red; +// UINT8 Reserved; +//} EFI_UGA_PIXEL; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// + +typedef struct _EFI_HII_PROTOCOL EFI_HII_PROTOCOL; + +// +// Global definition +// +#define NARROW_CHAR 0xFFF0 +#define WIDE_CHAR 0xFFF1 +#define NON_BREAKING_CHAR 0xFFF2 +#define GLYPH_WIDTH 8 +#define GLYPH_HEIGHT 19 + +#define EFI_HII_FONT 1 +#define EFI_HII_STRING 2 +#define EFI_HII_IFR 3 +#define EFI_HII_KEYBOARD 4 +#define EFI_HII_HANDLES 5 +#define EFI_HII_VARIABLE 6 +#define EFI_HII_DEVICE_PATH 7 + + +// References to string tokens must use this macro to enable scanning for +// token usages. +// +#define STRING_TOKEN(t) t + +// +// The following types are currently defined: +// +typedef UINT16 EFI_FORM_ID; +typedef UINT16 EFI_FORM_LABEL; + +#pragma pack(1) + +typedef struct { + UINT32 Length; + UINT16 Type; +} EFI_HII_PACK_HEADER; + +// +// A form list consists of a large variety of structure +// possibilities so to represent the binary blob of data +// associated with a package of forms, we will assume a +// pointer to a self-describing data buffer. +// +typedef struct { + EFI_HII_PACK_HEADER Header; +} EFI_HII_IFR_PACK; + +typedef struct { + EFI_HII_PACK_HEADER Header; // Must be filled in + EFI_HANDLE ImageHandle; // Must be filled in + EFI_HANDLE DeviceHandle; // Optional + EFI_HANDLE ControllerHandle; // Optional + EFI_HANDLE CallbackHandle; // Optional + EFI_HANDLE COBExportHandle; // Optional +} EFI_HII_HANDLE_PACK; + +// +// ******************************************************** +// EFI_VARIABLE_CONTENTS +// ******************************************************** +// +typedef struct { + EFI_HII_PACK_HEADER Header; + EFI_GUID VariableGuid; + UINT32 VariableNameLength; + UINT16 VariableId; + // + // CHAR16 VariableName[]; //Null-terminated + // +} EFI_HII_VARIABLE_PACK; + +// +// ******************************************************** +// EFI_DEVICE_PATH_PACK +// ******************************************************** +// +typedef struct { + EFI_HII_PACK_HEADER Header; + // + // EFI_DEVICE_PATH DevicePath[]; + // +} EFI_HII_DEVICE_PATH_PACK; + +// +// ******************************************************** +// EFI_HII_DATA_TABLE +// ******************************************************** +// +typedef struct { + EFI_HII_HANDLE HiiHandle; + EFI_GUID PackageGuid; + UINT32 DataTableSize; + UINT32 IfrDataOffset; + UINT32 StringDataOffset; + UINT32 VariableDataOffset; + UINT32 DevicePathOffset; + UINT32 NumberOfVariableData; + UINT32 NumberOfLanguages; + // + // EFI_HII_DEVICE_PATH_PACK DevicePath[]; + // EFI_HII_VARIABLE_PACK VariableData[]; + // EFI_HII_IFR_PACK IfrData; + // EFI_HII_STRING_PACK StringData[]; + // +} EFI_HII_DATA_TABLE; + +// +// ******************************************************** +// EFI_HII_EXPORT_TABLE +// ******************************************************** +// +typedef struct { + UINT32 NumberOfHiiDataTables; + EFI_GUID Revision; + // + // EFI_HII_DATA_TABLE HiiDataTable[]; + // +} EFI_HII_EXPORT_TABLE; + +typedef struct { + BOOLEAN FormSetUpdate; // If TRUE, next variable is significant + EFI_PHYSICAL_ADDRESS FormCallbackHandle; // If not 0, will update Formset with this info + BOOLEAN FormUpdate; // If TRUE, next variable is significant + UINT16 FormValue; // specify which form is to be updated if FormUpdate value is TRUE. + STRING_REF FormTitle; // If not 0, will update Form with this info + UINT16 DataCount; // The number of Data entries in this structure + UINT8 *Data; // An array of 1+ op-codes, specified by DataCount +} EFI_HII_UPDATE_DATA; + +// +// String attributes +// +#define LANG_RIGHT_TO_LEFT 0x00000001 + +// +// A string package is used to localize strings to a particular +// language. The package is associated with a particular driver +// or set of drivers. Tools are used to associate tokens with +// string references in forms and in programs. These tokens are +// language agnostic. When paired with a language pack (directly +// or indirectly), the string token resolves into an actual +// UNICODE string. The NumStringPointers determines how many +// StringPointers (offset values) there are as well as the total +// number of Strings that are defined. +// +typedef struct { + EFI_HII_PACK_HEADER Header; + RELOFST LanguageNameString; + RELOFST PrintableLanguageName; + UINT32 NumStringPointers; + UINT32 Attributes; + // + // RELOFST StringPointers[]; + // EFI_STRING Strings[]; + // +} EFI_HII_STRING_PACK; + +// +// Glyph Attributes +// +#define EFI_GLYPH_NON_SPACING 1 +#define EFI_GLYPH_WIDE 2 + +typedef struct { + CHAR16 UnicodeWeight; + UINT8 Attributes; + UINT8 GlyphCol1[GLYPH_HEIGHT]; +} EFI_NARROW_GLYPH; + +typedef struct { + CHAR16 UnicodeWeight; + UINT8 Attributes; + UINT8 GlyphCol1[GLYPH_HEIGHT]; + UINT8 GlyphCol2[GLYPH_HEIGHT]; + UINT8 Pad[3]; +} EFI_WIDE_GLYPH; + +// +// A font list consists of a font header followed by a series +// of glyph structures. Note that fonts are not language specific. +// +typedef struct { + EFI_HII_PACK_HEADER Header; + UINT16 NumberOfNarrowGlyphs; + UINT16 NumberOfWideGlyphs; +} EFI_HII_FONT_PACK; + +// +// The IfrData in the EFI_HII_IFR_PACK structure definition +// is variable length, and not really part of the header. To +// simplify from code the size of the header, define an +// identical structure that does not include the IfrData field. +// Then use sizeof() this new structure to determine the +// actual size of the header. +// +typedef struct { + EFI_HII_PACK_HEADER Header; +} EFI_HII_IFR_PACK_HEADER; + +// +// pedef EFI_HII_PACK_HEADER EFI_HII_IFR_PACK_HEADER; +// +typedef enum { + EfiKeyLCtrl, + EfiKeyA0, + EfiKeyLAlt, + EfiKeySpaceBar, + EfiKeyA2, + EfiKeyA3, + EfiKeyA4, + EfiKeyRCtrl, + EfiKeyLeftArrow, + EfiKeyDownArrow, + EfiKeyRightArrow, + EfiKeyZero, + EfiKeyPeriod, + EfiKeyEnter, + EfiKeyLShift, + EfiKeyB0, + EfiKeyB1, + EfiKeyB2, + EfiKeyB3, + EfiKeyB4, + EfiKeyB5, + EfiKeyB6, + EfiKeyB7, + EfiKeyB8, + EfiKeyB9, + EfiKeyB10, + EfiKeyRshift, + EfiKeyUpArrow, + EfiKeyOne, + EfiKeyTwo, + EfiKeyThree, + EfiKeyCapsLock, + EfiKeyC1, + EfiKeyC2, + EfiKeyC3, + EfiKeyC4, + EfiKeyC5, + EfiKeyC6, + EfiKeyC7, + EfiKeyC8, + EfiKeyC9, + EfiKeyC10, + EfiKeyC11, + EfiKeyC12, + EfiKeyFour, + EfiKeyFive, + EfiKeySix, + EfiKeyPlus, + EfiKeyTab, + EfiKeyD1, + EfiKeyD2, + EfiKeyD3, + EfiKeyD4, + EfiKeyD5, + EfiKeyD6, + EfiKeyD7, + EfiKeyD8, + EfiKeyD9, + EfiKeyD10, + EfiKeyD11, + EfiKeyD12, + EfiKeyD13, + EfiKeyDel, + EfiKeyEnd, + EfiKeyPgDn, + EfiKeySeven, + EfiKeyEight, + EfiKeyNine, + EfiKeyE0, + EfiKeyE1, + EfiKeyE2, + EfiKeyE3, + EfiKeyE4, + EfiKeyE5, + EfiKeyE6, + EfiKeyE7, + EfiKeyE8, + EfiKeyE9, + EfiKeyE10, + EfiKeyE11, + EfiKeyE12, + EfiKeyBackSpace, + EfiKeyIns, + EfiKeyHome, + EfiKeyPgUp, + EfiKeyNLck, + EfiKeySlash, + EfiKeyAsterisk, + EfiKeyMinus, + EfiKeyEsc, + EfiKeyF1, + EfiKeyF2, + EfiKeyF3, + EfiKeyF4, + EfiKeyF5, + EfiKeyF6, + EfiKeyF7, + EfiKeyF8, + EfiKeyF9, + EfiKeyF10, + EfiKeyF11, + EfiKeyF12, + EfiKeyPrint, + EfiKeySLck, + EfiKeyPause +} EFI_KEY; + +typedef struct { + EFI_KEY Key; + CHAR16 Unicode; + CHAR16 ShiftedUnicode; + CHAR16 AltGrUnicode; + CHAR16 ShiftedAltGrUnicode; + UINT16 Modifier; +} EFI_KEY_DESCRIPTOR; + +// +// This structure allows a sparse set of keys to be redefined +// or a complete redefinition of the keyboard layout. Most +// keyboards have a lot of commonality in their layouts, therefore +// only defining those keys that need to change from the default +// minimizes the passed in information. +// +// Additionally, when an update occurs, the active keyboard layout +// will be switched to the newly updated keyboard layout. This +// allows for situations that when a keyboard layout driver is +// loaded as part of system initialization, the system will default +// the keyboard behavior to the new layout. +// +// Each call to update the keyboard mapping should contain the +// complete set of key descriptors to be updated, since every +// call to the HII which contains an EFI_HII_KEYBOARD_PACK will +// wipe the previous set of overrides. A call to +// +typedef struct { + EFI_HII_PACK_HEADER Header; + EFI_KEY_DESCRIPTOR *Descriptor; + UINT8 DescriptorCount; +} EFI_HII_KEYBOARD_PACK; + +// +// The EFI_HII_PACKAGES can contain different types of packages just +// after the structure as inline data. +// +typedef struct { + UINTN NumberOfPackages; + EFI_GUID *GuidId; + // + // EFI_HII_HANDLE_PACK *HandlePack; // Only one pack. + // EFI_HII_IFR_PACK *IfrPack; // Only one pack. + // EFI_HII_FONT_PACK *FontPack[]; // Multiple packs ok + // EFI_HII_STRING_PACK *StringPack[]; // Multiple packs ok + // EFI_HII_KEYBOARD_PACK *KeyboardPack[]; // Multiple packs ok + // +} EFI_HII_PACKAGES; + +typedef struct _EFI_HII_VARIABLE_PACK_LIST { + struct _EFI_HII_VARIABLE_PACK_LIST *NextVariablePack; + EFI_HII_VARIABLE_PACK *VariablePack; +} EFI_HII_VARIABLE_PACK_LIST; + +#pragma pack() + +/** + Registers the various packs that are passed in via the Packages parameter. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Packages A pointer to an EFI_HII_PACKAGES package instance. + + @param Handle A pointer to the EFI_HII_HANDLE instance. + + @retval EFI_SUCCESS Data was extracted from Packages, the database + was updated with the data, and Handle returned successfully. + + @retval EFI_INVALID_PARAMETER The content of Packages was invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_NEW_PACK) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACKAGES *Packages, + OUT EFI_HII_HANDLE *Handle + ); + +/** + Removes a package from the HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Handle The handle that was registered to the data that is requested + for removal. + + @retval EFI_SUCCESS The data associated with the Handle was removed + from the HII database. + + @retval EFI_INVALID_PARAMETER The Handle was not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_REMOVE_PACK) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ); + +/** + Determines the handles that are currently active in the database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param HandleBufferLength On input, a pointer to the length of the handle + buffer. On output, the length of the handle buffer that is required + for the handles found. + + @param Handle An array of EFI_HII_HANDLE instances returned. + + @retval EFI_SUCCESS Handle was updated successfully. + + @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter indicates + that Handle is too small to support the number of handles. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_FIND_HANDLES) ( + IN EFI_HII_PROTOCOL *This, + IN OUT UINT16 *HandleBufferLength, + OUT EFI_HII_HANDLE *Handle + ); + +/** + Exports the contents of the database into a buffer. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Handle An EFI_HII_HANDLE that corresponds to the desired + handle to export. If the value is 0, the entire database will be exported. + In either case, the data will be exported in a format described by the + structure definition of EFI_HII_EXPORT_TABLE. + + @param BufferSize + On input, a pointer to the length of the buffer. On output, the length + of the buffer that is required for the export data. + + @param Buffer A pointer to a buffer that will contain the results of the export function. + + @retval EFI_SUCCESS The buffer was successfully filled with BufferSize amount of data. + + @retval EFI_BUFFER_TOO_SMALL The value in BufferSize was too small to contain the export data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_EXPORT) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Remove any new strings that were added after the initial string export + for this handle. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Handle The handle on which the string resides. + + @retval EFI_SUCCESS Remove strings from the handle successfully. + + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_RESET_STRINGS) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ); + +/** + Tests if all of the characters in a string have corresponding font characters. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param StringToTest A pointer to a Unicode string. + + @param FirstMissing A pointer to an index into the string. On input, + the index of the first character in the StringToTest to examine. On exit, + the index of the first character encountered for which a glyph is unavailable. + If all glyphs in the string are available, the index is the index of the + terminator of the string. + + @param GlyphBufferSize A pointer to a value. On output, if the function + returns EFI_SUCCESS, it contains the amount of memory that is required to + store the string¡¯s glyph equivalent. + + @retval EFI_SUCCESS All glyphs are available. Note that an empty string + always returns this value. + + @retval EFI_NOT_FOUND A glyph was not found for a character. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_TEST_STRING) ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *StringToTest, + IN OUT UINT32 *FirstMissing, + OUT UINT32 *GlyphBufferSize + ); + +/** + Translates a Unicode character into the corresponding font glyph. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Source A pointer to a Unicode string. + + @param Index On input, the offset into the string from which to fetch + the character.On successful completion, the index is updated to the first + character past the character(s) making up the just extracted glyph. + + @param GlyphBuffer Pointer to an array where the glyphs corresponding + to the characters in the source may be stored. GlyphBuffer is assumed + to be wide enough to accept a wide glyph character. + + @param BitWidth If EFI_SUCCESS was returned, the UINT16 pointed to by + this value is filled with the length of the glyph in pixels. It is unchanged + if the call was unsuccessful. + + @param InternalStatus The cell pointed to by this parameter must be + initialized to zero prior to invoking the call the first time for any string. + + @retval EFI_SUCCESS It worked. + + @retval EFI_NOT_FOUND A glyph for a character was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_GLYPH) ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Source, + IN OUT UINT16 *Index, + OUT UINT8 **GlyphBuffer, + OUT UINT16 *BitWidth, + IN OUT UINT32 *InternalStatus + ); + +/** + Translates a glyph into the format required for input to the Universal + Graphics Adapter (UGA) Block Transfer (BLT) routines. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param GlyphBuffer A pointer to the buffer that contains glyph data. + + @param Foreground The foreground setting requested to be used for the + generated BltBuffer data. + + @param Background The background setting requested to be used for the + generated BltBuffer data. + + @param Count The entry in the BltBuffer upon which to act. + + @param Width The width in bits of the glyph being converted. + + @param Height The height in bits of the glyph being converted + + @param BltBuffer A pointer to the buffer that contains the data that is + ready to be used by the UGA BLT routines. + + @retval EFI_SUCCESS It worked. + + @retval EFI_NOT_FOUND A glyph for a character was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GLYPH_TO_BLT) ( + IN EFI_HII_PROTOCOL *This, + IN UINT8 *GlyphBuffer, + IN EFI_UGA_PIXEL Foreground, + IN EFI_UGA_PIXEL Background, + IN UINTN Count, + IN UINTN Width, + IN UINTN Height, + IN OUT EFI_UGA_PIXEL *BltBuffer + ); + +/** + Allows a new string to be added to an already existing string package. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Pointer to a NULL-terminated string containing a single ISO 639-2 + language identifier, indicating the language in which the string is translated. + + @param Handle The handle of the language pack to which the string is to be added. + + @param Reference The identifier of the string to be added. If the reference + value is zero, then the string will be assigned a new identifier on that + handle for the language specified. Otherwise, the string will be updated + with the NewString Value. + + @param NewString The string to be added. + + @retval EFI_SUCCESS The string was effectively registered. + + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_NEW_STRING) ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Language, + IN EFI_HII_HANDLE Handle, + IN OUT STRING_REF *Reference, + IN CHAR16 *NewString + ); + +/** + Allows a program to determine the primary languages that are supported + on a given handle. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Handle The handle on which the strings reside. + + @param LanguageString A string allocated by GetPrimaryLanguages() that + contains a list of all primary languages registered on the handle. + + @retval EFI_SUCCESS LanguageString was correctly returned. + + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_PRI_LANGUAGES) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + OUT EFI_STRING *LanguageString + ); + +/** + Allows a program to determine which secondary languages are supported + on a given handle for a given primary language. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Handle The handle on which the strings reside. + + @param PrimaryLanguage Pointer to a NULL-terminated string containing a single + ISO 639-2 language identifier, indicating the primary language. + + @param LanguageString A string allocated by GetSecondaryLanguages() + containing a list of all secondary languages registered on the handle. + + @retval EFI_SUCCESS LanguageString was correctly returned. + + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_SEC_LANGUAGES) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CHAR16 *PrimaryLanguage, + OUT EFI_STRING *LanguageString + ); + +/** + Extracts a string from a package already registered with the EFI HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Handle The handle on which the string resides. + + @param Token The string token assigned to the string. + + @param Raw If TRUE, the string is returned unedited in the internal + storage format described above. If false, the string returned is edited + by replacing with and by removing special characters such + as the prefix. + + @param LanguageString Pointer to a NULL-terminated string containing a + single ISO 639-2 language identifier, indicating the language to print. + If the LanguageString is empty (starts with a NULL), the default system + language will be used to determine the language. + + @param BufferLength Length of the StringBuffer. + + @param StringBuffer The buffer designed to receive the characters in the string. + + @retval EFI_SUCCESS StringBuffer is filled with a NULL-terminated string. + + @retval EFI_INVALID_PARAMETER The handle or string token is unknown. + + @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough to + allow the entire string to be stored. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_STRING) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN BOOLEAN Raw, + IN CHAR16 *LanguageString, + IN OUT UINTN *BufferLength, + OUT EFI_STRING StringBuffer + ); + +/** + Allows a program to extract a part of a string of not more than a given width. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Handle The handle on which the string resides. + + @param Token The string token assigned to the string. + + @param Index On input, the offset into the string where the line is to start. + On output, the index is updated to point to beyond the last character returned + in the call. + + @param LineWidth The maximum width of the line in units of narrow glyphs. + + @param LanguageString Pointer to a NULL-terminated string containing a + single ISO 639-2 language identifier, indicating the language to print. + + @param BufferLength Pointer to the length of the StringBuffer. + + @param StringBuffer The buffer designed to receive the characters in the string. + + @retval EFI_SUCCESS StringBuffer filled with characters that will fit on the line. + + @retval EFI_NOT_FOUND The font glyph for at least one of the characters in + the string is not in the font database. + + @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough + to allow the entire string to be stored. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_LINE) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN OUT UINT16 *Index, + IN UINT16 LineWidth, + IN CHAR16 *LanguageString, + IN OUT UINT16 *BufferLength, + OUT EFI_STRING StringBuffer + ); + +/** + Allows a program to extract a form or form package that has previously + been registered with the HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Handle Handle on which the form resides. + + @param FormId The ID of the form to return. If the ID is zero, + the entire form package is returned. + + @param BufferLength On input, the length of the Buffer. On output, + the length of the returned buffer, + + @param Buffer The buffer designed to receive the form(s). + + @retval EFI_SUCCESS Buffer filled with the requested forms. BufferLength + was updated. + + @retval EFI_INVALID_PARAMETER The handle is unknown. + + @retval EFI_NOT_FOUND A form on the requested handle cannot be found with + the requested FormId. + + @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough + to allow the form to be stored. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_FORMS) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID FormId, + IN OUT UINTN *BufferLength, + OUT UINT8 *Buffer + ); + +/** + Extracts the defaults that are associated with a given handle in the HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Handle The HII handle from which will have default data retrieved. + + @param DefaultMask The mask used to specify some type of default override when extracting + the default image data. + + @param VariablePackList A indirect pointer to the first entry of a link list with + type EFI_HII_VARIABLE_PACK_LIST. + + @retval EFI_SUCCESS The VariablePackList was populated with the appropriate + default setting data. + + @retval EFI_NOT_FOUND The IFR does not have any explicit or default map(s). + + @retval EFI_INVALID_PARAMETER The HII database entry associated with Handle + contain invalid data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_DEFAULT_IMAGE) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN UINTN DefaultMask, + OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList + ); + +/** + Allows the caller to update a form or form package that has previously been + registered with the EFI HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param Handle Handle of the package where the form to be updated resides. + + @param Label The label inside the form package where the update is to take place. + + @param AddData If TRUE, adding data at a given Label; otherwise, + if FALSE, removing data at a given Label. + + @param Data The buffer containing the new tags to insert after the Label + + @retval EFI_SUCCESS The form was updated with the new tags. + + @retval EFI_INVALID_PARAMETER The buffer for the buffer length does not + contain an integral number of tags. + + @retval EFI_NOT_FOUND The Handle, Label, or FormId was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_UPDATE_FORM) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_LABEL Label, + IN BOOLEAN AddData, + IN EFI_HII_UPDATE_DATA *Data + ); + +/** + Retrieves the current keyboard layout. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + + @param DescriptorCount A pointer to the number of Descriptor entries being + described in the keyboard layout being retrieved. + + @param Descriptor A pointer to a buffer containing an array of EFI_KEY_DESCRIPTOR + entries. Each entry will reflect the definition of a specific physical key. + + @retval EFI_SUCCESS The keyboard layout was retrieved successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_KEYBOARD_LAYOUT) ( + IN EFI_HII_PROTOCOL *This, + OUT UINT16 *DescriptorCount, + OUT EFI_KEY_DESCRIPTOR *Descriptor + ); + +/** + @par Protocol Description: + The HII Protocol manages the HII database, which is a repository for data + having to do with fonts, strings, forms, keyboards, and other future human + interface items. + + @param NewPack + Extracts the various packs from a package list. + + @param RemovePack + Removes a package from the HII database. + + @param FindHandles + Determines the handles that are currently active in the database. + + @param ExportDatabase + Export the entire contents of the database to a buffer. + + @param TestString + Tests if all of the characters in a string have corresponding font characters. + + @param GetGlyph + Translates a Unicode character into the corresponding font glyph. + + @param GlyphToBlt + Converts a glyph value into a format that is ready for a UGA BLT command. + + @param NewString + Allows a new string to be added to an already existing string package. + + @param GetPrimaryLanguages + Allows a program to determine the primary languages that are supported + on a given handle. + + @param GetSecondaryLanguages + Allows a program to determine which secondary languages are supported + on a given handle for a given primary language. + + @param GetString + Extracts a string from a package that is already registered with the + EFI HII database. + + @param ResetString + Remove any new strings that were added after the initial string export + for this handle. + + @param GetLine + Allows a program to extract a part of a string of not more than a given width. + + @param GetForms + Allows a program to extract a form or form package that has been previously registered. + + @param GetDefaultImage + Allows a program to extract the nonvolatile image that represents the default storage image. + + @param UpdateForm + Allows a program to update a previously registered form. + + @param GetKeyboardLayout + Allows a program to extract the current keyboard layout. + +**/ +struct _EFI_HII_PROTOCOL { + EFI_HII_NEW_PACK NewPack; + EFI_HII_REMOVE_PACK RemovePack; + EFI_HII_FIND_HANDLES FindHandles; + EFI_HII_EXPORT ExportDatabase; + + EFI_HII_TEST_STRING TestString; + EFI_HII_GET_GLYPH GetGlyph; + EFI_HII_GLYPH_TO_BLT GlyphToBlt; + + EFI_HII_NEW_STRING NewString; + EFI_HII_GET_PRI_LANGUAGES GetPrimaryLanguages; + EFI_HII_GET_SEC_LANGUAGES GetSecondaryLanguages; + EFI_HII_GET_STRING GetString; + EFI_HII_RESET_STRINGS ResetStrings; + EFI_HII_GET_LINE GetLine; + EFI_HII_GET_FORMS GetForms; + EFI_HII_GET_DEFAULT_IMAGE GetDefaultImage; + EFI_HII_UPDATE_FORM UpdateForm; + + EFI_HII_GET_KEYBOARD_LAYOUT GetKeyboardLayout; +}; + +extern EFI_GUID gEfiHiiProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/IP4.h b/MdePkg/Include/Protocol/IP4.h new file mode 100644 index 0000000000..0decc176d4 --- /dev/null +++ b/MdePkg/Include/Protocol/IP4.h @@ -0,0 +1,411 @@ +/** @file + Copyright (c) 2006, 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. + + Module Name: IP4.h + +**/ + +#ifndef __EFI_IP4_PROTOCOL_H__ +#define __EFI_IP4_PROTOCOL_H__ + +#define EFI_IP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xc51711e7, 0xb4bf, 0x404a, {0xbf, 0xb8, 0x0a, 0x04, 0x8e, 0xf1, 0xff, 0xe4 } \ + } + +#define EFI_IP4_PROTOCOL_GUID \ + { \ + 0x41d94cd2, 0x35b6, 0x455a, {0x82, 0x58, 0xd4, 0xe5, 0x13, 0x34, 0xaa, 0xdd } \ + } + +typedef struct _EFI_IP4_PROTOCOL EFI_IP4_PROTOCOL; + +typedef struct { + EFI_IPv4_ADDRESS Ip4Address; + EFI_IPv4_ADDRESS SubnetMask; +} EFI_IP4_ADDRESS_PAIR; + +typedef struct { + EFI_HANDLE DriverHandle; + UINT32 AddressCount; + EFI_IP4_ADDRESS_PAIR AddressPairs[1]; +} EFI_IP4_VARIABLE_DATA; + +typedef struct { + UINT8 DefaultProtocol; + BOOLEAN AcceptAnyProtocol; + BOOLEAN AcceptIcmpErrors; + BOOLEAN AcceptBroadcast; + BOOLEAN AcceptPromiscuous; + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; + BOOLEAN RawData; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; +} EFI_IP4_CONFIG_DATA; + + +typedef struct { + EFI_IPv4_ADDRESS SubnetAddress; + EFI_IPv4_ADDRESS SubnetMask; + EFI_IPv4_ADDRESS GatewayAddress; +} EFI_IP4_ROUTE_TABLE; + +typedef struct { + UINT8 Type; + UINT8 Code; +} EFI_IP4_ICMP_TYPE; + +typedef struct { + BOOLEAN IsStarted; + EFI_IP4_CONFIG_DATA ConfigData; + BOOLEAN IsConfigured; + UINT32 GroupCount; + EFI_IPv4_ADDRESS *GroupTable; + UINT32 RouteCount; + EFI_IP4_ROUTE_TABLE *RouteTable; + UINT32 IcmpTypeCount; + EFI_IP4_ICMP_TYPE *IcmpTypeList; +} EFI_IP4_MODE_DATA; + +#pragma pack(1) + +typedef struct { +#ifdef EFI_NET_LITTLE_ENDIAN + UINT8 HeaderLength:4; + UINT8 Version:4; +#else + UINT8 Version:4; + UINT8 HeaderLength:4; +#endif + UINT8 TypeOfService; + UINT16 TotalLength; + UINT16 Identification; + UINT16 Fragmentation; + UINT8 TimeToLive; + UINT8 Protocol; + UINT16 Checksum; + EFI_IPv4_ADDRESS SourceAddress; + EFI_IPv4_ADDRESS DestinationAddress; +} EFI_IP4_HEADER; +#pragma pack() + + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_IP4_FRAGMENT_DATA; + + +typedef struct { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + UINT32 HeaderLength; + EFI_IP4_HEADER *Header; + UINT32 OptionsLength; + VOID *Options; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_IP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP4_RECEIVE_DATA; + + +typedef struct { + EFI_IPv4_ADDRESS SourceAddress; + EFI_IPv4_ADDRESS GatewayAddress; + UINT8 Protocol; + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; +} EFI_IP4_OVERRIDE_DATA; + +typedef struct { + EFI_IPv4_ADDRESS DestinationAddress; + EFI_IP4_OVERRIDE_DATA *OverrideData; //OPTIONAL + UINT32 OptionsLength; //OPTIONAL + VOID *OptionsBuffer; //OPTIONAL + UINT32 TotalDataLength; + UINT32 FragmentCount; + EFI_IP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_IP4_TRANSMIT_DATA; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_IP4_RECEIVE_DATA *RxData; + EFI_IP4_TRANSMIT_DATA *TxData; + } Packet; +} EFI_IP4_COMPLETION_TOKEN; + +/** + Gets the current operational settings for this instance of the EFI IPv4 Protocol driver. + + @param This Pointer to the EFI_IP4_PROTOCOL instance. + @param Ip4ModeData Pointer to the EFI IPv4 Protocol mode data structure. + @param MnpConfigData Pointer to the managed network configuration data structure. + @param SnpData Pointer to the simple network mode data structure. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_GET_MODE_DATA) ( + IN EFI_IP4_PROTOCOL *This, + OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ) +; + +/** + Assigns an IPv4 address and subnet mask to this EFI IPv4 Protocol driver instance. + + @param This Pointer to the EFI_IP4_PROTOCOL instance. + @param IpConfigData Pointer to the EFI IPv4 Protocol configuration data structure. + + @retval EFI_SUCCESS The driver instance was successfully opened. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + @retval EFI_UNSUPPORTED One or more of the following conditions is TRUE: + A configuration protocol (DHCP, BOOTP, RARP, etc.) could + not be located when clients choose to use the default IPv4 + address. This EFI IPv4 Protocol implementation does not + support this requested filter or timeout setting. + @retval EFI_OUT_OF_RESOURCES The EFI IPv4 Protocol driver instance data could not be allocated. + @retval EFI_ALREADY_STARTED The interface is already open and must be stopped before the + IPv4 address or subnet mask can be changed. The interface must + also be stopped when switching to/from raw packet mode. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI IPv4 + Protocol driver instance is not opened. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIGURE) ( + IN EFI_IP4_PROTOCOL *This, + IN EFI_IP4_CONFIG_DATA *IpConfigData OPTIONAL + ) +; + +/** + Joins and leaves multicast groups. + + @param This Pointer to the EFI_IP4_PROTOCOL instance. + @param JoinFlag Set to TRUE to join the multicast group session and FALSE to leave. + @param GroupAddress Pointer to the IPv4 multicast address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following is TRUE: + - This is NULL. + - JoinFlag is TRUE and GroupAddress is NULL. + - GroupAddress is not NULL and *GroupAddress is + not a multicast IPv4 address. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_OUT_OF_RESOURCES System resources could not be allocated. + @retval EFI_UNSUPPORTED This EFI IPv4 Protocol implementation does not support multicast groups. + @retval EFI_ALREADY_STARTED The group address is already in the group table (when + JoinFlag is TRUE). + @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is FALSE). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_GROUPS) ( + IN EFI_IP4_PROTOCOL *This, + IN BOOLEAN JoinFlag, + IN EFI_IPv4_ADDRESS *GroupAddress OPTIONAL + ) +; + +/** + Adds and deletes routing table entries. + + @param This Pointer to the EFI_IP4_PROTOCOL instance. + @param DeleteRoute Set to TRUE to delete this route from the routing table. Set to + FALSE to add this route to the routing table. SubnetAddress + and SubnetMask are used as the key to each route entry. + @param SubnetAddress The address of the subnet that needs to be routed. + @param SubnetMask The subnet mask of SubnetAddress. + @param GatewayAddress The unicast gateway IPv4 address for this route. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED The driver instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - SubnetAddress is NULL. + - SubnetMask is NULL. + - GatewayAddress is NULL. + - *SubnetAddress is not a valid subnet address. + - *SubnetMask is not a valid subnet mask. + - *GatewayAddress is not a valid unicast IPv4 address. + @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table. + @retval EFI_NOT_FOUND This route is not in the routing table (when DeleteRoute is TRUE). + @retval EFI_ACCESS_DENIED The route is already defined in the routing table (when + DeleteRoute is FALSE). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_ROUTES) ( + IN EFI_IP4_PROTOCOL *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS *SubnetAddress, + IN EFI_IPv4_ADDRESS *SubnetMask, + IN EFI_IPv4_ADDRESS *GatewayAddress + ) +; + +/** + Places outgoing data packets into the transmit queue. + + @param This Pointer to the EFI_IP4_PROTOCOL instance. + @param Token Pointer to the transmit token. + + @retval EFI_SUCCESS The data has been queued for transmission. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more pameters are invalid. + @retval EFI_ACCESS_DENIED The transmit completion token with the same Token.Event + was already in the transmit queue. + @retval EFI_NOT_READY The completion token could not be queued because the transmit + queue is full. + @retval EFI_NOT_FOUND Not route is found to destination address. + @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data. + @retval EFI_BUFFER_TOO_SMALL Token.Packet.TxData.TotalDataLength is too + short to transmit. + @retval EFI_BAD_BUFFER_SIZE The length of the IPv4 header + option length + total data length is + greater than MTU (or greater than the maximum packet size if + Token.Packet.TxData.OverrideData. + DoNotFragment is TRUE.) + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_TRANSMIT) ( + IN EFI_IP4_PROTOCOL *This, + IN EFI_IP4_COMPLETION_TOKEN *Token + ) +; + +/** + Places a receiving request into the receiving queue. + + @param This Pointer to the EFI_IP4_PROTOCOL instance. + @param Token Pointer to a token that is associated with the receive data descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, RARP, etc.) + is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Token is NULL. + - Token.Event is NULL. + @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system + resources (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + The EFI IPv4 Protocol instance has been reset to startup defaults. + EFI_ACCESS_DENIED The receive completion token with the same Token.Event was already + in the receive queue. + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + @retval EFI_ICMP_ERROR An ICMP error packet was received. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_RECEIVE) ( + IN EFI_IP4_PROTOCOL *This, + IN EFI_IP4_COMPLETION_TOKEN *Token + ) +; + +/** + Abort an asynchronous transmit or receive request. + + @param This Pointer to the EFI_IP4_PROTOCOL instance. + @param Token Pointer to a token that has been issued by + EFI_IP4_PROTOCOL.Transmit() or + EFI_IP4_PROTOCOL.Receive(). If NULL, all pending + tokens are aborted. Type EFI_IP4_COMPLETION_TOKEN is + defined in EFI_IP4_PROTOCOL.Transmit(). + + @retval EFI_SUCCESS The asynchronous I/O request was aborted and + Token.->Event was signaled. When Token is NULL, all + pending requests were aborted and their events were signaled. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was + not found in the transmit or receive queue. It has either completed + or was not issued by Transmit() and Receive(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CANCEL) ( + IN EFI_IP4_PROTOCOL *This, + IN EFI_IP4_COMPLETION_TOKEN *Token OPTIONAL + ) +; + +/** + Polls for incoming data packets and processes outgoing data packets. + + @param This Pointer to the EFI_IP4_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI IPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY No incoming or outgoing data is processed. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_POLL) ( + IN EFI_IP4_PROTOCOL *This + ) +; + +struct _EFI_IP4_PROTOCOL { + EFI_IP4_GET_MODE_DATA GetModeData; + EFI_IP4_CONFIGURE Configure; + EFI_IP4_GROUPS Groups; + EFI_IP4_ROUTES Routes; + EFI_IP4_TRANSMIT Transmit; + EFI_IP4_RECEIVE Receive; + EFI_IP4_CANCEL Cancel; + EFI_IP4_POLL Poll; +}; + +extern EFI_GUID gEfiIp4ServiceBindingProtocolGuid; +extern EFI_GUID gEfiIp4ProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/IP4Config.h b/MdePkg/Include/Protocol/IP4Config.h new file mode 100644 index 0000000000..0212f35e81 --- /dev/null +++ b/MdePkg/Include/Protocol/IP4Config.h @@ -0,0 +1,121 @@ +/** @file + Copyright (c) 2006, 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. + + Module Name: IP4Config.h + +**/ + +#ifndef __EFI_IP4CONFIG_PROTOCOL_H__ +#define __EFI_IP4CONFIG_PROTOCOL_H__ + +#define EFI_IP4_CONFIG_PROTOCOL_GUID \ + { \ + 0x3b95aa31, 0x3793, 0x434b, {0x86, 0x67, 0xc8, 0x07, 0x08, 0x92, 0xe0, 0x5e } \ + } + +typedef struct _EFI_IP4_CONFIG_PROTOCOL EFI_IP4_CONFIG_PROTOCOL; + +#define IP4_CONFIG_VARIABLE_ATTRIBUTES \ + (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | \ + EFI_VARIABLE_RUNTIME_ACCESS ) + +typedef struct { + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT32 RouteTableSize; + EFI_IP4_ROUTE_TABLE *RouteTable; //OPTIONAL +} EFI_IP4_IPCONFIG_DATA; + + +/** + Starts running the configuration policy for the EFI IPv4 Protocol driver. + + @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance. + @param DoneEvent Event that will be signaled when the EFI IPv4 Protocol driver + configuration policy completes execution. This event must be of + type EVT_NOTIFY_SIGNAL. + @param ReconfigEvent Event that will be signaled when the EFI IPv4 Protocol driver + configuration needs to be updated. This event must be of type + EVT_NOTIFY_SIGNAL. + + @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol driver is now + running. + @retval EFI_INVALID_PARAMETER This, DoneEvent, or ReconfigEvent is NULL. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ALREADY_STARTED The configuration policy for the EFI IPv4 Protocol driver was + already started. + @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred. + @retval EFI_UNSUPPORTED This interface does not support the EFI IPv4 Protocol driver + configuration. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIG_START) ( + IN EFI_IP4_CONFIG_PROTOCOL *This, + IN EFI_EVENT DoneEvent, + IN EFI_EVENT ReconfigEvent + ) +; + +/** + Stops running the configuration policy for the EFI IPv4 Protocol driver. + + @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance. + + @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol driver has been stopped. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol driver was not started. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIG_STOP) ( + IN EFI_IP4_CONFIG_PROTOCOL *This + ) +; + +/** + Returns the default configuration data (if any) for the EFI IPv4 Protocol driver. + + @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance. + @param IpConfigDataSize On input, the size of the IpConfigData buffer. + On output, the count of bytes that were written into the IpConfigData buffer. + @param IpConfigData Pointer to the EFI IPv4 Configuration Protocol driver + configuration data structure. + + @retval EFI_SUCCESS The EFI IPv4 Protocol driver configuration has been returned. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol driver is not + running. + @retval EFI_NOT_READY EFI IPv4 Protocol driver configuration is still running. + @retval EFI_ABORTED EFI IPv4 Protocol driver configuration could not complete. + @retval EFI_BUFFER_TOO_SMALL *IpConfigDataSize is smaller than the configuration data + buffer or IpConfigData is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IP4_CONFIG_GET_DATA) ( + IN EFI_IP4_CONFIG_PROTOCOL *This, + IN OUT UINTN *IpConfigDataSize, + OUT EFI_IP4_IPCONFIG_DATA *IpConfigData OPTIONAL + ) +; + +struct _EFI_IP4_CONFIG_PROTOCOL { + EFI_IP4_CONFIG_START Start; + EFI_IP4_CONFIG_STOP Stop; + EFI_IP4_CONFIG_GET_DATA GetData; +}; + +extern EFI_GUID gEfiIp4ConfigProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/IScsiInitatorName.h b/MdePkg/Include/Protocol/IScsiInitatorName.h new file mode 100644 index 0000000000..48131e8e25 --- /dev/null +++ b/MdePkg/Include/Protocol/IScsiInitatorName.h @@ -0,0 +1,92 @@ +/** @file + EFI_ISCSI_INITIATOR_NAME_PROTOCOL as defined in UEFI 2.0. + It rovides the ability to get and set the iSCSI Initiator Name. + + Copyright (c) 2006, 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. + + Module Name: IScsiInitatorName.h + +**/ + +#ifndef __ISCSI_INITIATOR_NAME_H__ +#define __ISCSI_INITIATOR_NAME_H__ + +#define EFI_ISCSI_INITIATOR_NAME_PROTOCOL_GUID \ +{ \ + 0xa6a72875, 0x2962, 0x4c18, {0x9f, 0x46, 0x8d, 0xa6, 0x44, 0xcc, 0xfe } \ +} + +typedef struct _EFI_ISCSI_INITIATOR_NAME_PROTOCOL EFI_ISCSI_INITIATOR_NAME_PROTOCOL; + +/** + Retrieves the current set value of iSCSI Initiator Name. + + @param This Pointer to the EFI_ISCSI_INITIATOR_NAME_PROTOCOL instance. + @param BufferSize Size of the buffer in bytes pointed to by Buffer / Actual size of the + variable data buffer. + @param Buffer Pointer to the buffer for data to be read. + + @retval EFI_SUCCESS Data was successfully retrieved into the provided buffer and the + BufferSize was sufficient to handle the iSCSI initiator name + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small for the result. + @retval EFI_INVALID_PARAMETER BufferSize or Buffer is NULL. + @retval EFI_DEVICE_ERROR The iSCSI initiator name could not be retrieved due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ISCSI_INITIATOR_NAME_GET) ( + IN EFI_ISCSI_INITIATOR_NAME_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +; + + + +/** + Sets the iSCSI Initiator Name. + + @param This Pointer to the EFI_ISCSI_INITIATOR_NAME_PROTOCOL instance. + @param BufferSize Size of the buffer in bytes pointed to by Buffer. + @param Buffer Pointer to the buffer for data to be written. + + @retval EFI_SUCCESS Data was successfully stored by the protocol. + @retval EFI_UNSUPPORTED Platform policies do not allow for data to be written. + @retval EFI_INVALID_PARAMETER BufferSize or Buffer is NULL, or BufferSize exceeds the maximum allowed limit. + @retval EFI_DEVICE_ERROR The data could not be stored due to a hardware error. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the data. + @retval EFI_PROTOCOL_ERROR Input iSCSI initiator name does not adhere to RFC 3720 + (and other related protocols) + +**/ +typedef EFI_STATUS +(EFIAPI *EFI_ISCSI_INITIATOR_NAME_SET) ( + IN EFI_ISCSI_INITIATOR_NAME_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +; + +struct _EFI_ISCSI_INITIATOR_NAME_PROTOCOL { + EFI_ISCSI_INITIATOR_NAME_GET Get; + EFI_ISCSI_INITIATOR_NAME_SET Set; +}; + +extern EFI_GUID gEfiIScsiInitiatorNameProtocolGuid; + +#endif + + + + + + + diff --git a/MdePkg/Include/Protocol/IdeControllerInit.h b/MdePkg/Include/Protocol/IdeControllerInit.h new file mode 100644 index 0000000000..beaac30e5f --- /dev/null +++ b/MdePkg/Include/Protocol/IdeControllerInit.h @@ -0,0 +1,485 @@ +/** @file + This file declares EFI IDE Controller Init Protocol + + Copyright (c) 2006, 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. + + Module Name: IdeControllerInit.h + + @par Revision Reference: + This Protocol is defined in IDE Controller Initialization Protocol Specification + Version 0.9 + +**/ + +#ifndef _EFI_IDE_CONTROLLER_INIT_PROTOCOL_H +#define _EFI_IDE_CONTROLLER_INIT_PROTOCOL_H + +// +// Global ID for the EFI Platform IDE Protocol GUID +// +#define EFI_IDE_CONTROLLER_INIT_PROTOCOL_GUID \ + { 0xa1e37052, 0x80d9, 0x4e65, {0xa3, 0x17, 0x3e, 0x9a, 0x55, 0xc4, 0x3e, 0xc9 } } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_IDE_CONTROLLER_INIT_PROTOCOL EFI_IDE_CONTROLLER_INIT_PROTOCOL; + +// +////////////////////////////////////////////////////////////////////////////////////////// +// EFI_IDE_BUS_ENUMERATION_PHASE +// EFI_IDE_CONTROLLER_ENUM_PHASE +// +typedef enum{ + EfiIdeBeforeChannelEnumeration, + EfiIdeAfterChannelEnumeration, + EfiIdeBeforeChannelReset, + EfiIdeAfterChannelReset, + EfiIdeBusBeforeDevicePresenceDetection, + EfiIdeBusAfterDevicePresenceDetection, + EfiIdeResetMode, + EfiIdeBusPhaseMaximum +} EFI_IDE_CONTROLLER_ENUM_PHASE; + +// +//****************************************************** +// EFI_ATA_EXT_TRANSFER_PROTOCOL +//****************************************************** +// +// This extended mode describes the SATA physical protocol. +// SATA physical layers can operate at different speeds. +// These speeds are defined below. Various PATA protocols +// and associated modes are not applicable to SATA devices. +// + +typedef enum { + EfiAtaSataTransferProtocol +} EFI_ATA_EXT_TRANSFER_PROTOCOL; + +#define EFI_SATA_AUTO_SPEED 0 +#define EFI_SATA_GEN1_SPEED 1 +#define EFI_SATA_GEN2_SPEED 2 + +// +//******************************************************* +// EFI_IDE_CABLE_TYPE +//******************************************************* +// +typedef enum { + EfiIdeCableTypeUnknown, + EfiIdeCableType40pin, + EfiIdeCableType80Pin, + EfiIdeCableTypeSerial, + EfiIdeCableTypeMaximum +} EFI_IDE_CABLE_TYPE; + +// +//****************************************************** +// EFI_ATA_MODE +//****************************************************** +// +typedef struct { + BOOLEAN Valid; + UINT32 Mode; +} EFI_ATA_MODE; + +// +//****************************************************** +// EFI_ATA_EXTENDED_MODE +//****************************************************** +// +typedef struct { + EFI_ATA_EXT_TRANSFER_PROTOCOL TransferProtocol; + UINT32 Mode; +} EFI_ATA_EXTENDED_MODE; + +// +//****************************************************** +// EFI_ATA_COLLECTIVE_MODE +//****************************************************** +// +typedef struct { + EFI_ATA_MODE PioMode; + EFI_ATA_MODE SingleWordDmaMode; + EFI_ATA_MODE MultiWordDmaMode; + EFI_ATA_MODE UdmaMode; + UINT32 ExtModeCount; + EFI_ATA_EXTENDED_MODE ExtMode[1]; +} EFI_ATA_COLLECTIVE_MODE; + +// +//******************************************************* +// EFI_ATA_IDENTIFY_DATA +//******************************************************* +// + +#pragma pack(1) + +typedef struct { + UINT16 config; // General Configuration + UINT16 cylinders; // Number of Cylinders + UINT16 reserved_2; + UINT16 heads; //Number of logical heads + UINT16 vendor_data1; + UINT16 vendor_data2; + UINT16 sectors_per_track; + UINT16 vendor_specific_7_9[3]; + CHAR8 SerialNo[20]; // ASCII + UINT16 vendor_specific_20_21[2]; + UINT16 ecc_bytes_available; + CHAR8 FirmwareVer[8]; // ASCII + CHAR8 ModelName[40]; // ASCII + UINT16 multi_sector_cmd_max_sct_cnt; + UINT16 reserved_48; + UINT16 capabilities; + UINT16 reserved_50; + UINT16 pio_cycle_timing; + UINT16 reserved_52; + UINT16 field_validity; + UINT16 current_cylinders; + UINT16 current_heads; + UINT16 current_sectors; + UINT16 CurrentCapacityLsb; + UINT16 CurrentCapacityMsb; + UINT16 reserved_59; + UINT16 user_addressable_sectors_lo; + UINT16 user_addressable_sectors_hi; + UINT16 reserved_62; + UINT16 multi_word_dma_mode; + UINT16 advanced_pio_modes; + UINT16 min_multi_word_dma_cycle_time; + UINT16 rec_multi_word_dma_cycle_time; + UINT16 min_pio_cycle_time_without_flow_control; + UINT16 min_pio_cycle_time_with_flow_control; + UINT16 reserved_69_79[11]; + UINT16 major_version_no; + UINT16 minor_version_no; + UINT16 command_set_supported_82; // word 82 + UINT16 command_set_supported_83; // word 83 + UINT16 command_set_feature_extn; // word 84 + UINT16 command_set_feature_enb_85; // word 85 + UINT16 command_set_feature_enb_86; // word 86 + UINT16 command_set_feature_default; // word 87 + UINT16 ultra_dma_mode; // word 88 + UINT16 reserved_89_127[39]; + UINT16 security_status; + UINT16 vendor_data_129_159[31]; + UINT16 reserved_160_255[96]; +} EFI_ATA_IDENTIFY_DATA; + +#pragma pack() +// +//******************************************************* +// EFI_ATAPI_IDENTIFY_DATA +//******************************************************* +// +#pragma pack(1) +typedef struct { + UINT16 config; // General Configuration + UINT16 obsolete_1; + UINT16 specific_config; + UINT16 obsolete_3; + UINT16 retired_4_5[2]; + UINT16 obsolete_6; + UINT16 cfa_reserved_7_8[2]; + UINT16 retired_9; + CHAR8 SerialNo[20]; // ASCII + UINT16 retired_20_21[2]; + UINT16 obsolete_22; + CHAR8 FirmwareVer[8]; // ASCII + CHAR8 ModelName[40]; // ASCII + UINT16 multi_sector_cmd_max_sct_cnt; + UINT16 reserved_48; + UINT16 capabilities_49; + UINT16 capabilities_50; + UINT16 obsolete_51_52[2]; + UINT16 field_validity; + UINT16 obsolete_54_58[5]; + UINT16 mutil_sector_setting; + UINT16 user_addressable_sectors_lo; + UINT16 user_addressable_sectors_hi; + UINT16 obsolete_62; + UINT16 multi_word_dma_mode; + UINT16 advanced_pio_modes; + UINT16 min_multi_word_dma_cycle_time; + UINT16 rec_multi_word_dma_cycle_time; + UINT16 min_pio_cycle_time_without_flow_control; + UINT16 min_pio_cycle_time_with_flow_control; + UINT16 reserved_69_74[6]; + UINT16 queue_depth; + UINT16 reserved_76_79[4]; + UINT16 major_version_no; + UINT16 minor_version_no; + UINT16 cmd_set_support_82; + UINT16 cmd_set_support_83; + UINT16 cmd_feature_support; + UINT16 cmd_feature_enable_85; + UINT16 cmd_feature_enable_86; + UINT16 cmd_feature_default; + UINT16 ultra_dma_select; + UINT16 time_required_for_sec_erase; + UINT16 time_required_for_enhanced_sec_erase; + UINT16 current_advanced_power_mgmt_value; + UINT16 master_pwd_revison_code; + UINT16 hardware_reset_result; + UINT16 current_auto_acoustic_mgmt_value; + UINT16 reserved_95_99[5]; + UINT16 max_user_lba_for_48bit_addr[4]; + UINT16 reserved_104_126[23]; + UINT16 removable_media_status_notification_support; + UINT16 security_status; + UINT16 vendor_data_129_159[31]; + UINT16 cfa_power_mode; + UINT16 cfa_reserved_161_175[15]; + UINT16 current_media_serial_no[30]; + UINT16 reserved_206_254[49]; + UINT16 integrity_word; +} EFI_ATAPI_IDENTIFY_DATA; + +#pragma pack() +// +//******************************************************* +// EFI_IDENTIFY_DATA +//******************************************************* +// +typedef union { + EFI_ATA_IDENTIFY_DATA AtaData; + EFI_ATAPI_IDENTIFY_DATA AtapiData; +} EFI_IDENTIFY_DATA; + +#define EFI_ATAPI_DEVICE_IDENTIFY_DATA 0x8000 + +// +///////////////////////////////////////////////////////////////////////////////////////// +// Function prototype declaration, for ANSI compatability +// +/** + Returns the information about the specified IDE channel. + + @param This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + + @param Channel Zero-based channel number. + + @param Enabled TRUE if this channel is enabled. Disabled channels are not scanned + to see if any devices are present. + + @param MaxDevices The maximum number of IDE devices that the bus driver + can expect on this channel. + + @retval EFI_SUCCESS Information was returned without any errors. + + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_GET_CHANNEL_INFO) ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + OUT BOOLEAN *Enabled, + OUT UINT8 *MaxDevices +); + +/** + The notifications from the IDE bus driver that it is about to enter a certain + phase of the IDE channel enumeration process. + + @param This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + + @param Phase The phase during enumeration. + + @param Channel Zero-based channel number. + + @retval EFI_SUCCESS The notification was accepted without any errors. + + @retval EFI_NOT_SUPPORTED Phase is not supported. + + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + + @retval EFI_NOT_READY This phase cannot be entered at this time. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_NOTIFY_PHASE) ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN EFI_IDE_CONTROLLER_ENUM_PHASE Phase, + IN UINT8 Channel +); + +/** + Submits the device information to the IDE controller driver. + + @param This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + + @param Channel Zero-based channel number. + + @param Device Zero-based device number on the Channel. + + @param IdentifyData The device¡¯s response to the ATA IDENTIFY_DEVICE command. + + @retval EFI_SUCCESS The information was accepted without any errors. + + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + Or Device is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_SUBMIT_DATA) ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + IN EFI_IDENTIFY_DATA *IdentifyData +); + +/** + Disqualifies specific modes for an IDE device. + + @param This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + + @param Channel Zero-based channel number. + + @param Device Zero-based device number on the Channel. + + @param BadModes The modes that the device does not support and that + should be disqualified. + + @retval EFI_SUCCESS The modes were accepted without any errors. + + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + Or Device is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_DISQUALIFY_MODE) ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + IN EFI_ATA_COLLECTIVE_MODE *BadModes +); + +/** + Returns the information about the optimum modes for the specified IDE device. + + @param This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + + @param Channel Zero-based channel number. + + @param Device Zero-based device number on the Channel. + + @param SupportedModes The optimum modes for the device. + + @retval EFI_SUCCESS SupportedModes was returned. + + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + Or Device is invalid. Or SupportedModes is NULL. + + @retval EFI_NOT_READY Modes cannot be calculated due to a lack of data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_CALCULATE_MODE) ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + OUT EFI_ATA_COLLECTIVE_MODE **SupportedModes +); + +/** + Commands the IDE controller driver to program the IDE controller hardware + so that the specified device can operate at the specified mode. + + @param This Pointer to the EFI_IDE_CONTROLLER_INIT_PROTOCOL instance. + + @param Channel Zero-based channel number. + + @param Device Zero-based device number on the Channel. + + @param Modes The modes to set. + + @retval EFI_SUCCESS The command was accepted without any errors. + + @retval EFI_INVALID_PARAMETER Channel is invalid (Channel >= ChannelCount). + Or Device is invalid. + + @retval EFI_NOT_READY Modes cannot be set at this time due to lack of data. + + @retval EFI_DEVICE_ERROR Modes cannot be set due to hardware failure. + The IDE bus driver should not use this device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IDE_CONTROLLER_SET_TIMING) ( + IN EFI_IDE_CONTROLLER_INIT_PROTOCOL *This, + IN UINT8 Channel, + IN UINT8 Device, + IN EFI_ATA_COLLECTIVE_MODE *Modes +); + +// +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Interface structure +// EFI_IDE_CONTROLLER_INIT_PROTOCOL protocol provides the chipset specific information to the IDE bus driver. +// An IDE Bus driver wants to manage an IDE bus and possible IDE devices will have to retrieve the +// EFI_IDE_CONTROLLER_INIT_PROTOCOL instances. +// +/** + @par Protocol Description: + Provides the basic interfaces to abstract an IDE controller. + + @param GetChannelInfo + Returns the information about a specific channel. + + @param NotifyPhase + The notification that the IDE bus driver is about to enter the + specified phase during the enumeration process. + + @param SubmitData + Submits the Drive Identify data that was returned by the device. + + @param DisqualifyMode + Submits information about modes that should be disqualified. + + @param CalculateMode + Calculates and returns the optimum mode for a particular IDE device. + + @param SetTiming + Programs the IDE controller hardware to the default timing or per the modes + that were returned by the last call to CalculateMode(). + + @param EnumAll + Set to TRUE if the enumeration group includes all the channels that are + produced by this controller. FALSE if an enumeration group consists of + only one channel. + + @param ChannelCount + The number of channels that are produced by this controller. + +**/ +struct _EFI_IDE_CONTROLLER_INIT_PROTOCOL { + EFI_IDE_CONTROLLER_GET_CHANNEL_INFO GetChannelInfo; + EFI_IDE_CONTROLLER_NOTIFY_PHASE NotifyPhase; + EFI_IDE_CONTROLLER_SUBMIT_DATA SubmitData; + EFI_IDE_CONTROLLER_DISQUALIFY_MODE DisqualifyMode; + EFI_IDE_CONTROLLER_CALCULATE_MODE CalculateMode; + EFI_IDE_CONTROLLER_SET_TIMING SetTiming; + BOOLEAN EnumAll; + UINT8 ChannelCount; +}; + +extern EFI_GUID gEfiIdeControllerInitProtocolGuid; + +#endif + + diff --git a/MdePkg/Include/Protocol/IncompatiblePciDeviceSupport.h b/MdePkg/Include/Protocol/IncompatiblePciDeviceSupport.h new file mode 100644 index 0000000000..03a5b2ec08 --- /dev/null +++ b/MdePkg/Include/Protocol/IncompatiblePciDeviceSupport.h @@ -0,0 +1,84 @@ +/** @file + This file declares EFI Incompatible PCI Device Support Protocol + + Copyright (c) 2006, 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. + + Module Name: IncompatiblePciDeviceSupport.h + + @par Revision Reference: + This protocol is defined in Framework of EFI PCI Platform Support Specification. + Version0.9 + +**/ + +#ifndef _INCOMPATIBLE_PCI_DEVICE_SUPPORT_H_ +#define _INCOMPATIBLE_PCI_DEVICE_SUPPORT_H_ + +#define EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL_GUID \ + {0xeb23f55a, 0x7863, 0x4ac2, {0x8d, 0x3d, 0x95, 0x65, 0x35, 0xde, 0x03, 0x75} } + +typedef struct _EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL; + +/** + Returns a list of ACPI resource descriptors that detail the special + resource configuration requirements for an incompatible PCI device. + + @param This Pointer to the EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL instance. + + @param VendorID A unique ID to identify the manufacturer of the PCI device. + + @param DeviceID A unique ID to identify the particular PCI device. + + @param RevisionID A PCI device-specific revision identifier. + + @param SubsystemVendorId Specifies the subsystem vendor ID. + + @param SubsystemDeviceId Specifies the subsystem device ID. + + @param Configuration A list of ACPI resource descriptors that detail + the configuration requirement. + + @retval EFI_SUCCESS The function always returns EFI_SUCCESS. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_CHECK_DEVICE) ( + IN EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL *This, + IN UINTN VendorId, + IN UINTN DeviceId, + IN UINTN Revision, + IN UINTN SubVendorId,OPTIONAL + IN UINTN SubDeviceId,OPTIONAL + OUT VOID **Configuration +); + + +// +// Interface structure for the Incompatible PCI Device Support Protocol +// +/** + @par Protocol Description: + This protocol can find some incompatible PCI devices and report their + special resource requirements to the PCI bus driver. + + @param CheckDevice + Returns a list of ACPI resource descriptors that detail any special + resource configuration requirements if the specified device is a recognized + incompatible PCI device. + +**/ +struct _EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_PROTOCOL { + EFI_INCOMPATIBLE_PCI_DEVICE_SUPPORT_CHECK_DEVICE CheckDevice; +}; + +extern EFI_GUID gEfiIncompatiblePciDeviceSupportProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Legacy8259.h b/MdePkg/Include/Protocol/Legacy8259.h new file mode 100644 index 0000000000..c30a5e519c --- /dev/null +++ b/MdePkg/Include/Protocol/Legacy8259.h @@ -0,0 +1,307 @@ +/** @file + This protocol abstracts the 8259 interrupt controller. This includes + PCI IRQ routing need to program the PCI Interrupt Line register. + + Copyright (c) 2006, 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. + + Module Name: Legacy8259.h + + @par Revision Reference: + This protocol is defined in Framework for EFI Compatibility Support Module spec + Version 0.96 + +**/ + +#ifndef _EFI_LEGACY_8259_H +#define _EFI_LEGACY_8259_H + +#define EFI_LEGACY_8259_PROTOCOL_GUID \ + { \ + 0x38321dba, 0x4fe0, 0x4e17, {0x8a, 0xec, 0x41, 0x30, 0x55, 0xea, 0xed, 0xc1 } \ + } + +typedef struct _EFI_LEGACY_8259_PROTOCOL EFI_LEGACY_8259_PROTOCOL; + +typedef enum { + Efi8259Irq0, + Efi8259Irq1, + Efi8259Irq2, + Efi8259Irq3, + Efi8259Irq4, + Efi8259Irq5, + Efi8259Irq6, + Efi8259Irq7, + Efi8259Irq8, + Efi8259Irq9, + Efi8259Irq10, + Efi8259Irq11, + Efi8259Irq12, + Efi8259Irq13, + Efi8259Irq14, + Efi8259Irq15, + Efi8259IrqMax +} EFI_8259_IRQ; + +typedef enum { + Efi8259LegacyMode, + Efi8259ProtectedMode, + Efi8259MaxMode +} EFI_8259_MODE; + +/** + Get the 8259 interrupt masks for Irq0 - Irq15. A different mask exists for + the legacy mode mask and the protected mode mask. The base address for the 8259 + is different for legacy and protected mode, so two masks are required. + + @param This Protocol instance pointer. + @param MasterBase The base vector for the Master PIC in the 8259 controller + @param Slavebase The base vector for the Master PIC in the 8259 controller + + @retval EFI_SUCCESS The new bases were programmed + @retval EFI_DEVICE_ERROR A device erro occured programming the vector bases + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_8259_SET_VECTOR_BASE) ( + IN EFI_LEGACY_8259_PROTOCOL *This, + IN UINT8 MasterBase, + IN UINT8 SlaveBase + ) +; + +/** + Get the 8259 interrupt masks for Irq0 - Irq15. A different mask exists for + the legacy mode mask and the protected mode mask. The base address for the 8259 + is different for legacy and protected mode, so two masks are required. + + @param This Protocol instance pointer. + @param LegacyMask Bit 0 is Irq0 - Bit 15 is Irq15 + @param LegacyEdgeLevel Bit 0 is Irq0 - Bit 15 is Irq15 + @param ProtectedMask Bit 0 is Irq0 - Bit 15 is Irq15 + @param ProtectedEdgeLevel Bit 0 is Irq0 - Bit 15 is Irq15 + + @retval EFI_SUCCESS 8259 status returned + @retval EFI_DEVICE_ERROR Error reading 8259 + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_8259_GET_MASK) ( + IN EFI_LEGACY_8259_PROTOCOL *This, + OUT UINT16 *LegacyMask, OPTIONAL + OUT UINT16 *LegacyEdgeLevel, OPTIONAL + OUT UINT16 *ProtectedMask, OPTIONAL + OUT UINT16 *ProtectedEdgeLevel OPTIONAL + ) +; + +/** + Set the 8259 interrupt masks for Irq0 - Irq15. A different mask exists for + the legacy mode mask and the protected mode mask. The base address for the 8259 + is different for legacy and protected mode, so two masks are required. + Also set the edge/level masks. + + @param This Protocol instance pointer. + @param LegacyMask Bit 0 is Irq0 - Bit 15 is Irq15 + @param LegacyEdgeLevel Bit 0 is Irq0 - Bit 15 is Irq15 + @param ProtectedMask Bit 0 is Irq0 - Bit 15 is Irq15 + @param ProtectedEdgeLevel Bit 0 is Irq0 - Bit 15 is Irq15 + + @retval EFI_SUCCESS 8259 status returned + @retval EFI_DEVICE_ERROR Error reading 8259 + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_8259_SET_MASK) ( + IN EFI_LEGACY_8259_PROTOCOL *This, + IN UINT16 *LegacyMask, OPTIONAL + IN UINT16 *LegacyEdgeLevel, OPTIONAL + IN UINT16 *ProtectedMask, OPTIONAL + IN UINT16 *ProtectedEdgeLevel OPTIONAL + ) +; + +/** + Set the 8259 mode of operation. The base address for the 8259 is different for + legacy and protected mode. The legacy mode requires the master 8259 to have a + master base of 0x08 and the slave base of 0x70. The protected mode base locations + are not defined. Interrupts must be masked by the caller before this function + is called. The interrupt mask from the current mode is saved. The interrupt + mask for the new mode is Mask, or if Mask does not exist the previously saved + mask is used. + + @param This Protocol instance pointer. + @param Mode Mode of operation. i.e. real mode or protected mode + @param Mask Optional interupt mask for the new mode. + @param EdgeLevel Optional trigger mask for the new mode. + + @retval EFI_SUCCESS 8259 programmed + @retval EFI_DEVICE_ERROR Error writting to 8259 + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_8259_SET_MODE) ( + IN EFI_LEGACY_8259_PROTOCOL *This, + IN EFI_8259_MODE Mode, + IN UINT16 *Mask, OPTIONAL + IN UINT16 *EdgeLevel OPTIONAL + ) +; + +/** + Convert from IRQ to processor interrupt vector number. + + @param This Protocol instance pointer. + @param Irq 8259 IRQ0 - IRQ15 + @param Vector Processor vector number that matches Irq + + @retval EFI_SUCCESS The Vector matching Irq is returned + @retval EFI_INVALID_PARAMETER Irq not valid + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_8259_GET_VECTOR) ( + IN EFI_LEGACY_8259_PROTOCOL *This, + IN EFI_8259_IRQ Irq, + OUT UINT8 *Vector + ) +; + +/** + Enable Irq by unmasking interrupt in 8259 + + @param This Protocol instance pointer. + @param Irq 8259 IRQ0 - IRQ15 + @param LevelTriggered TRUE if level triggered. FALSE if edge triggered. + + @retval EFI_SUCCESS Irq enabled on 8259 + @retval EFI_INVALID_PARAMETER Irq not valid + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_8259_ENABLE_IRQ) ( + IN EFI_LEGACY_8259_PROTOCOL *This, + IN EFI_8259_IRQ Irq, + IN BOOLEAN LevelTriggered + ) +; + +/** + Disable Irq by masking interrupt in 8259 + + @param This Protocol instance pointer. + @param Irq 8259 IRQ0 - IRQ15 + + @retval EFI_SUCCESS Irq disabled on 8259 + @retval EFI_INVALID_PARAMETER Irq not valid + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_8259_DISABLE_IRQ) ( + IN EFI_LEGACY_8259_PROTOCOL *This, + IN EFI_8259_IRQ Irq + ) +; + +/** + PciHandle represents a PCI config space of a PCI function. Vector + represents Interrupt Pin (from PCI config space) and it is the data + that is programmed into the Interrupt Line (from the PCI config space) + register. + + @param This Protocol instance pointer. + @param PciHandle PCI function to return vector for + @param Vector Vector for fucntion that matches + + @retval EFI_SUCCESS A valid Vector is returned + @retval EFI_INVALID_PARAMETER PciHandle not valid + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_8259_GET_INTERRUPT_LINE) ( + IN EFI_LEGACY_8259_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT UINT8 *Vector + ) +; + +/** + Send an EOI to 8259 + + @param This Protocol instance pointer. + @param Irq 8259 IRQ0 - IRQ15 + + @retval EFI_SUCCESS EOI successfully sent to 8259 + @retval EFI_INVALID_PARAMETER Irq not valid + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_8259_END_OF_INTERRUPT) ( + IN EFI_LEGACY_8259_PROTOCOL *This, + IN EFI_8259_IRQ Irq + ) +; + +/** + @par Protocol Description: + Abstracts the 8259 and APIC hardware control between EFI usage and + Compatibility16 usage. + + @param SetVectorBase + Sets the vector bases for master and slave PICs. + + @param GetMask + Gets IRQ and edge/level masks for 16-bit real mode and 32-bit protected mode. + + @param SetMask + Sets the IRQ and edge\level masks for 16-bit real mode and 32-bit protected mode. + + @param SetMode + Sets PIC mode to 16-bit real mode or 32-bit protected mode. + + @param GetVector + Gets the base vector assigned to an IRQ. + + @param EnableIrq + Enables an IRQ. + + @param DisableIrq + Disables an IRQ. + + @param GetInterruptLine + Gets an IRQ that is assigned to a PCI device. + + @param EndOfInterrupt + Issues the end of interrupt command. + +**/ +struct _EFI_LEGACY_8259_PROTOCOL { + EFI_LEGACY_8259_SET_VECTOR_BASE SetVectorBase; + EFI_LEGACY_8259_GET_MASK GetMask; + EFI_LEGACY_8259_SET_MASK SetMask; + EFI_LEGACY_8259_SET_MODE SetMode; + EFI_LEGACY_8259_GET_VECTOR GetVector; + EFI_LEGACY_8259_ENABLE_IRQ EnableIrq; + EFI_LEGACY_8259_DISABLE_IRQ DisableIrq; + EFI_LEGACY_8259_GET_INTERRUPT_LINE GetInterruptLine; + EFI_LEGACY_8259_END_OF_INTERRUPT EndOfInterrupt; +}; + +extern EFI_GUID gEfiLegacy8259ProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/LegacyBios.h b/MdePkg/Include/Protocol/LegacyBios.h new file mode 100644 index 0000000000..aa94cfb74f --- /dev/null +++ b/MdePkg/Include/Protocol/LegacyBios.h @@ -0,0 +1,701 @@ +/** @file + The EFI Legacy BIOS Protocol is used to abstract legacy Option ROM usage + under EFI and Legacy OS boot. + + Note: The names for EFI_IA32_REGISTER_SET elements were picked to follow + well known naming conventions. + + Thunk - A thunk is a transition from one processor mode to another. A Thunk + is a transition from native EFI mode to 16-bit mode. A reverse thunk + would be a transition from 16-bit mode to native EFI mode. + + You most likely should not use this protocol! Find the EFI way to solve the + problem to make your code portable + + Copyright (c) 2006, 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. + + Module Name: LegacyBios.h + + @par Revision Reference: + This protocol is defined in Framework for EFI Compatibility Support Module spec + Version 0.96 + +**/ + +#ifndef _EFI_LEGACY_BIOS_H +#define _EFI_LEGACY_BIOS_H + +#define EFI_LEGACY_BIOS_PROTOCOL_GUID \ + { \ + 0xdb9a1e3d, 0x45cb, 0x4abb, {0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d } \ + } + +typedef struct _EFI_LEGACY_BIOS_PROTOCOL EFI_LEGACY_BIOS_PROTOCOL; + +// +// Convert from 32-bit address (_Adr) to Segment:Offset 16-bit form +// +#define EFI_SEGMENT(_Adr) (UINT16) ((UINT16) (((UINTN) (_Adr)) >> 4) & 0xf000) +#define EFI_OFFSET(_Adr) (UINT16) (((UINT16) ((UINTN) (_Adr))) & 0xffff) +#define BYTE_GRANULARITY 0x01 +#define WORD_GRANULARITY 0x02 +#define DWORD_GRANULARITY 0x04 +#define QWORD_GRANULARITY 0x08 +#define PARAGRAPH_GRANULARITY 0x10 + +#define CARRY_FLAG 0x01 + +//********************************************************* +// EFI_EFLAGS_REG +//********************************************************* +typedef struct { + UINT32 CF:1; + UINT32 Reserved1:1; + UINT32 PF:1; + UINT32 Reserved2:1; + UINT32 AF:1; + UINT32 Reserved3:1; + UINT32 ZF:1; + UINT32 SF:1; + UINT32 TF:1; + UINT32 IF:1; + UINT32 DF:1; + UINT32 OF:1; + UINT32 IOPL:2; + UINT32 NT:1; + UINT32 Reserved4:2; + UINT32 VM:1; + UINT32 Reserved5:14; +} EFI_EFLAGS_REG; + +//********************************************************* +// EFI_DWORD_REGS +//********************************************************* + +typedef struct { + UINT32 EAX; + UINT32 EBX; + UINT32 ECX; + UINT32 EDX; + UINT32 ESI; + UINT32 EDI; + EFI_EFLAGS_REG EFlags; + UINT16 ES; + UINT16 CS; + UINT16 SS; + UINT16 DS; + UINT16 FS; + UINT16 GS; + UINT32 EBP; + UINT32 ESP; +} EFI_DWORD_REGS; + +//******************************************* +// EFI_FLAGS_REG +//******************************************* +typedef struct { + UINT16 CF:1; + UINT16 Reserved1:1; + UINT16 PF:1; + UINT16 Reserved2:1; + UINT16 AF:1; + UINT16 Reserved3:1; + UINT16 ZF:1; + UINT16 SF:1; + UINT16 TF:1; + UINT16 IF:1; + UINT16 DF:1; + UINT16 OF:1; + UINT16 IOPL:2; + UINT16 NT:1; + UINT16 Reserved4:1; +} EFI_FLAGS_REG; + + +//********************************************************* +// EFI_WORD_REGS +//********************************************************* + +typedef struct { + UINT16 AX; + UINT16 ReservedAX; + UINT16 BX; + UINT16 ReservedBX; + UINT16 CX; + UINT16 ReservedCX; + UINT16 DX; + UINT16 ReservedDX; + UINT16 SI; + UINT16 ReservedSI; + UINT16 DI; + UINT16 ReservedDI; + EFI_FLAGS_REG Flags; + UINT16 ReservedFlags; + UINT16 ES; + UINT16 CS; + UINT16 SS; + UINT16 DS; + UINT16 FS; + UINT16 GS; + UINT16 BP; + UINT16 ReservedBP; + UINT16 SP; + UINT16 ReservedSP; +} EFI_WORD_REGS; + +//********************************************************* +// EFI_BYTE_REGS +//********************************************************* + +typedef struct { + UINT8 AL, AH; + UINT16 ReservedAX; + UINT8 BL, BH; + UINT16 ReservedBX; + UINT8 CL, CH; + UINT16 ReservedCX; + UINT8 DL, DH; + UINT16 ReservedDX; +} EFI_BYTE_REGS; + +typedef union { + EFI_DWORD_REGS E; + EFI_WORD_REGS X; + EFI_BYTE_REGS H; +} EFI_IA32_REGISTER_SET; + +#pragma pack(1) +// +// $EFI table created by Legacy16 code and consumed by EFI Legacy driver +// +typedef struct { + UINT32 Signature; // "$EFI" + UINT8 TableChecksum; + UINT8 TableLength; + UINT8 EfiMajorRevision; + UINT8 EfiMinorRevision; + UINT8 TableMajorRevision; + UINT8 TableMinorRevision; + UINT8 Reserved[2]; + UINT16 Legacy16CallSegment; + UINT16 Legacy16CallOffset; + + UINT16 PnPInstallationCheckSegment; + UINT16 PnPInstallationCheckOffset; + + UINT32 EfiSystemTable; + UINT32 OemStringPointer; + UINT32 AcpiRsdPtrPointer; + UINT16 OemRevision; + UINT32 E820Pointer; + UINT32 E820Length; + UINT32 IrqRoutingTablePointer; + UINT32 IrqRoutingTableLength; + UINT32 MpTablePtr; + UINT32 MpTableLength; + UINT16 OemIntSegment; + UINT16 OemIntOffset; + UINT16 Oem32Segment; + UINT16 Oem32Offset; + UINT16 Oem16Segment; + UINT16 Oem16Offset; + UINT16 TpmSegment; + UINT16 TpmOffset; + UINT32 IbvPointer; + UINT32 PciExpressBase; + UINT8 LastPciBus; +} EFI_COMPATIBILITY16_TABLE; +// +// define maximum number of HDD system supports +// +#define MAX_HDD_ENTRIES 0x30 + +typedef struct { + UINT16 Raw[256]; +} ATAPI_IDENTIFY; + +// +// HDD_INFO status +// +#define HDD_PRIMARY 0x01 +#define HDD_SECONDARY 0x02 +#define HDD_MASTER_ATAPI_CDROM 0x04 +#define HDD_SLAVE_ATAPI_CDROM 0x08 +#define HDD_MASTER_IDE 0x20 +#define HDD_SLAVE_IDE 0x40 +#define HDD_MASTER_ATAPI_ZIPDISK 0x10 +#define HDD_SLAVE_ATAPI_ZIPDISK 0x80 + +typedef struct { + UINT16 Status; + UINT32 Bus; + UINT32 Device; + UINT32 Function; + UINT16 CommandBaseAddress; + UINT16 ControlBaseAddress; + UINT16 BusMasterAddress; + UINT8 HddIrq; + ATAPI_IDENTIFY IdentifyDrive[2]; +} HDD_INFO; + +// +// Parties data structures +// +typedef struct { + UINT8 DirectoryServiceValidity : 1; + UINT8 RabcaUsedFlag : 1; + UINT8 ExecuteHddDiagnosticsFlag : 1; + UINT8 Reserved : 5; +} UDC_ATTRIBUTES; + +typedef struct { + UDC_ATTRIBUTES Attributes; + UINT8 DeviceNumber; + UINT8 BbsTableEntryNumberForParentDevice; + UINT8 BbsTableEntryNumberForBoot; + UINT8 BbsTableEntryNumberForHddDiag; + UINT8 BeerData[128]; + UINT8 ServiceAreaData[64]; +} UD_TABLE; + +// +// define BBS Device Types +// +#define BBS_FLOPPY 0x01 +#define BBS_HARDDISK 0x02 +#define BBS_CDROM 0x03 +#define BBS_PCMCIA 0x04 +#define BBS_USB 0x05 +#define BBS_EMBED_NETWORK 0x06 +#define BBS_BEV_DEVICE 0x80 +#define BBS_UNKNOWN 0xff + +typedef struct { + UINT16 OldPosition : 4; + UINT16 Reserved1 : 4; + UINT16 Enabled : 1; + UINT16 Failed : 1; + UINT16 MediaPresent : 2; + UINT16 Reserved2 : 4; +} BBS_STATUS_FLAGS; + +#define MAX_BBS_ENTRIES 0x100 +// +// BBS_IGNORE_ENTRY is placed in the BootPriority field if the entry is to +// be skipped. +// BBS_UNPRIORITIZED_ENTRY is placed in the BootPriority field before +// priority has been assigned but indicates valid entry. +// BBS_LOWEST_PRIORITY is normally used for removable media with no media +// inserted. This allows the 16-bit CSM to allocate a drive letter to +// the device. +// BBS_DO_NOT_BOOT_FROM is used for devices that the 16-bit CSM is to assign +// a drive letter to but never boot from. +// +// AdditionalIrq??Handler usage is IBV specific. The fields have been added +// for: +// 1. Saving non-BBS card info about IRQs taken by card. +// 2. For BBS compliant cards that hook IRQs in order to have their SETUP +// executed. +// +#define BBS_DO_NOT_BOOT_FROM 0xFFFC +#define BBS_LOWEST_PRIORITY 0xFFFD +#define BBS_UNPRIORITIZED_ENTRY 0xFFFE +#define BBS_IGNORE_ENTRY 0xFFFF + +typedef struct { + UINT16 BootPriority; + UINT32 Bus; + UINT32 Device; + UINT32 Function; + UINT8 Class; + UINT8 SubClass; + UINT16 MfgStringOffset; + UINT16 MfgStringSegment; + UINT16 DeviceType; + BBS_STATUS_FLAGS StatusFlags; + UINT16 BootHandlerOffset; + UINT16 BootHandlerSegment; + UINT16 DescStringOffset; + UINT16 DescStringSegment; + UINT32 InitPerReserved; + UINT32 AdditionalIrq13Handler; + UINT32 AdditionalIrq18Handler; + UINT32 AdditionalIrq19Handler; + UINT32 AdditionalIrq40Handler; + UINT8 AssignedDriveNumber; + UINT32 AdditionalIrq41Handler; + UINT32 AdditionalIrq46Handler; + UINT32 IBV1; + UINT32 IBV2; +} BBS_TABLE; + +#pragma pack() + +/** + Thunk to 16-bit real mode and execute a software interrupt with a vector + of BiosInt. Regs will contain the 16-bit register context on entry and + exit. + + @param This Protocol instance pointer. + @param BiosInt Processor interrupt vector to invoke + @param Reg Register contexted passed into (and returned) from thunk to + 16-bit mode + + @retval FALSE Thunk completed, and there were no BIOS errors in the target code. + See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_LEGACY_BIOS_INT86) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 BiosInt, + IN OUT EFI_IA32_REGISTER_SET *Regs + ) +; + +/** + Thunk to 16-bit real mode and call Segment:Offset. Regs will contain the + 16-bit register context on entry and exit. Arguments can be passed on + the Stack argument + + @param This Protocol instance pointer. + @param Segment Segemnt of 16-bit mode call + @param Offset Offset of 16-bit mdoe call + @param Reg Register contexted passed into (and returned) from thunk to + 16-bit mode + @param Stack Caller allocated stack used to pass arguments + @param StackSize Size of Stack in bytes + + @retval FALSE Thunk completed, and there were no BIOS errors in the target code. + See Regs for status. + @retval TRUE There was a BIOS erro in the target code. + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_LEGACY_BIOS_FARCALL86) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT16 Segment, + IN UINT16 Offset, + IN EFI_IA32_REGISTER_SET *Regs, + IN VOID *Stack, + IN UINTN StackSize + ) +; + +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_CHECK_ROM) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, OPTIONAL + OUT UINTN *RomSize, OPTIONAL + OUT UINTN *Flags + +/** + Test to see if a legacy PCI ROM exists for this device. Optionally return + the Legacy ROM instance for this PCI device. + + @param This Protocol instance pointer. + @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded + @param RomImage Return the legacy PCI ROM for this device + @param RomSize Size of ROM Image + @param Flags Indicates if ROM found and if PC-AT. + + @retval EFI_SUCCESS Legacy Option ROM availible for this device + @retval EFI_UNSUPPORTED Legacy Option ROM not supported. + +**/ + ) +; + +/** + Load a legacy PC-AT OPROM on the PciHandle device. Return information + about how many disks were added by the OPROM and the shadow address and + size. DiskStart & DiskEnd are INT 13h drive letters. Thus 0x80 is C: + + @param This Protocol instance pointer. + @param PciHandle The PCI PC-AT OPROM from this devices ROM BAR will be loaded. + This value is NULL if RomImage is non-NULL. This is the normal + case. + @param RomImage A PCI PC-AT ROM image. This argument is non-NULL if there is + no hardware associated with the ROM and thus no PciHandle, + otherwise is must be NULL. + Example is PXE base code. + @param Flags Return Status if ROM was found and if was Legacy OPROM. + @param DiskStart Disk number of first device hooked by the ROM. If DiskStart + is the same as DiskEnd no disked were hooked. + @param DiskEnd Disk number of the last device hooked by the ROM. + @param RomShadowAddress Shadow address of PC-AT ROM + @param RomShadowSize Size of RomShadowAddress in bytes + + @retval EFI_SUCCESS Thunk completed, see Regs for status. + @retval EFI_INVALID_PARAMETER PciHandle not found + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_INSTALL_ROM) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + IN VOID **RomImage, + OUT UINTN *Flags, + OUT UINT8 *DiskStart, OPTIONAL + OUT UINT8 *DiskEnd, OPTIONAL + OUT VOID **RomShadowAddress, OPTIONAL + OUT UINT32 *ShadowedRomSize OPTIONAL + ) +; + +/** + Attempt to legacy boot the BootOption. If the EFI contexted has been + compromised this function will not return. + + @param This Protocol instance pointer. + @param BootOption EFI Device Path from BootXXXX variable. + @param LoadOptionSize Size of LoadOption in size. + @param LoadOption LoadOption from BootXXXX variable + + @retval EFI_SUCCESS Removable media not present + +**/ +/** + Update BDA with current Scroll, Num & Cap lock LEDS + + @param This Protocol instance pointer. + @param Leds Status of current Scroll, Num & Cap lock LEDS + Bit 0 is Scroll Lock 0 = Not locked + Bit 1 is Num Lock + Bit 2 is Caps Lock + + @retval EFI_SUCCESS Removable media not present + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_BOOT) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BootOption, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions + ) +; +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_UPDATE_KEYBOARD_LED_STATUS) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINT8 Leds + ) +; + +/** + Retrieve legacy BBS info and assign boot priority. + + @param This Protocol instance pointer. + @param HddCount Number of HDD_INFO structures + @param HddInfo Onboard IDE controller information + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Tables returned + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_GET_BBS_INFO) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *HddCount, + OUT HDD_INFO **HddInfo, + OUT UINT16 *BbsCount, + OUT IN BBS_TABLE **BbsTable + ) +; + +/** + Assign drive number to legacy HDD drives prior to booting an EFI + aware OS so the OS can access drives without an EFI driver. + + @param This Protocol instance pointer. + @param BbsCount Number of BBS_TABLE structures + @param BbsTable List BBS entries + + @retval EFI_SUCCESS Drive numbers assigned + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PREPARE_TO_BOOT_EFI) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + OUT UINT16 *BbsCount, + OUT IN BBS_TABLE **BbsTable + ) +; + +/** + To boot from an unconventional device like parties and/or execute + HDD diagnostics. + + @param This Protocol instance pointer. + @param Attributes How to interpret the other input parameters + @param BbsEntry The 0-based index into the BbsTable for the parent + device. + @param BeerData Pointer to the 128 bytes of ram BEER data. + @param ServiceAreaData Pointer to the 64 bytes of raw Service Area data. The + caller must provide a pointer to the specific Service + Area and not the start all Service Areas. + + EFI_INVALID_PARAMETER if error. Does NOT return if no error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_BOOT_UNCONVENTIONAL_DEVICE) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UDC_ATTRIBUTES Attributes, + IN UINTN BbsEntry, + IN VOID *BeerData, + IN VOID *ServiceAreaData + ) +; + +/** + Shadow all legacy16 OPROMs that haven't been shadowed. + Warning: Use this with caution. This routine disconnects all EFI + drivers. If used externally then caller must re-connect EFI + drivers. + + @retval EFI_SUCCESS OPROMs shadowed + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_SHADOW_ALL_LEGACY_OPROMS) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This + ) +; + +/** + Get a region from the LegacyBios for S3 usage. + + @param This Protocol instance pointer. + @param LegacyMemorySize Size of required region + @param Region Region to use. + 00 = Either 0xE0000 or 0xF0000 block + Bit0 = 1 0xF0000 block + Bit1 = 1 0xE0000 block + @param Alignment Address alignment. Bit mapped. First non-zero + bit from right is alignment. + @param LegacyMemoryAddress Region Assigned + + @retval EFI_SUCCESS Region assigned + + @retval Other Region not assigned + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_GET_LEGACY_REGION) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN UINTN Region, + IN UINTN Alignment, + OUT VOID **LegacyMemoryAddress + ) +; + +/** + Get a region from the LegacyBios for Tiano usage. Can only be invoked once. + + @param This Protocol instance pointer. + @param LegacyMemorySize Size of data to copy + @param LegacyMemoryAddress Legacy Region destination address + Note: must be in region assigned by + LegacyBiosGetLegacyRegion + @param LegacyMemorySourceAddress Source of data + + @retval EFI_SUCCESS Region assigned + @retval EFI_ACCESS_DENIED Destination outside assigned region + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_COPY_LEGACY_REGION) ( + IN EFI_LEGACY_BIOS_PROTOCOL *This, + IN UINTN LegacyMemorySize, + IN VOID *LegacyMemoryAddress, + IN VOID *LegacyMemorySourceAddress + ) +; + +/** + @par Protocol Description: + Abstracts the traditional BIOS from the rest of EFI. The LegacyBoot() + member function allows the BDS to support booting a traditional OS. + EFI thunks drivers that make EFI bindings for BIOS INT services use + all the other member functions. + + @param Int86 + Performs traditional software INT. See the Int86() function description. + + @param FarCall86 + Performs a far call into Compatibility16 or traditional OpROM code. + + @param CheckPciRom + Checks if a traditional OpROM exists for this device. + + @param InstallPciRom + Loads a traditional OpROM in traditional OpROM address space. + + @param LegacyBoot + Boots a traditional OS. + + @param UpdateKeyboardLedStatus + Updates BDA to reflect the current EFI keyboard LED status. + + @param GetBbsInfo + Allows an external agent, such as BIOS Setup, to get the BBS data. + + @param ShadowAllLegacyOproms + Causes all legacy OpROMs to be shadowed. + + @param PrepareToBootEfi + Performs all actions prior to boot. Used when booting an EFI-aware OS + rather than a legacy OS. + + @param GetLegacyRegion + Allows EFI to reserve an area in the 0xE0000 or 0xF0000 block. + + @param CopyLegacyRegion + Allows EFI to copy data to the area specified by GetLegacyRegion. + + @param BootUnconventionalDevice + Allows the user to boot off an unconventional device such as a PARTIES partition. + +**/ +struct _EFI_LEGACY_BIOS_PROTOCOL { + EFI_LEGACY_BIOS_INT86 Int86; + EFI_LEGACY_BIOS_FARCALL86 FarCall86; + EFI_LEGACY_BIOS_CHECK_ROM CheckPciRom; + EFI_LEGACY_BIOS_INSTALL_ROM InstallPciRom; + EFI_LEGACY_BIOS_BOOT LegacyBoot; + EFI_LEGACY_BIOS_UPDATE_KEYBOARD_LED_STATUS UpdateKeyboardLedStatus; + EFI_LEGACY_BIOS_GET_BBS_INFO GetBbsInfo; + EFI_LEGACY_BIOS_PREPARE_TO_BOOT_EFI PrepareToBootEfi; + EFI_LEGACY_BIOS_SHADOW_ALL_LEGACY_OPROMS ShadowAllLegacyOproms; + EFI_LEGACY_BIOS_GET_LEGACY_REGION GetLegacyRegion; + EFI_LEGACY_BIOS_COPY_LEGACY_REGION CopyLegacyRegion; + EFI_LEGACY_BIOS_BOOT_UNCONVENTIONAL_DEVICE BootUnconventionalDevice; +}; + +extern EFI_GUID gEfiLegacyBiosProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/LegacyBiosPlatform.h b/MdePkg/Include/Protocol/LegacyBiosPlatform.h new file mode 100644 index 0000000000..56d6724180 --- /dev/null +++ b/MdePkg/Include/Protocol/LegacyBiosPlatform.h @@ -0,0 +1,307 @@ +/** @file + The EFI Legacy BIOS Patform Protocol is used to mate a Legacy16 + implementation with this EFI code. The EFI driver that produces + the Legacy BIOS protocol is generic and consumes this protocol. + A driver that matches the Legacy16 produces this protocol + + Copyright (c) 2006, 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. + + Module Name: LegacyBiosPlatform.h + + @par Revision Reference: + This protocol is defined in Framework for EFI Compatibility Support Module spec + Version 0.96 +**/ + +#ifndef _EFI_LEGACY_BIOS_PLATFORM_H +#define _EFI_LEGACY_BIOS_PLATFORM_H + +#define EFI_LEGACY_BIOS_PLATFORM_PROTOCOL_GUID \ + { \ + 0x783658a3, 0x4172, 0x4421, {0xa2, 0x99, 0xe0, 0x9, 0x7, 0x9c, 0xc, 0xb4 } \ + } + +typedef struct _EFI_LEGACY_BIOS_PLATFORM_PROTOCOL EFI_LEGACY_BIOS_PLATFORM_PROTOCOL; + +#pragma pack(1) +// +// Define structures for GetOemIntData +// Note: +// OemIntDataElenent is an array of structures from 0 to Count-1. +// RawData is an array of bytes from 0 to RamDataLength-1. +// +typedef struct { + UINT16 Int; + UINT16 Ax; + UINT32 RawDataLength; + UINT8 RawData[1]; +} EFI_OEM_INT_DATA_ELEMENT; + +typedef struct { + UINT16 Count; + EFI_OEM_INT_DATA_ELEMENT OemIntDataElement[1]; +} EFI_OEM_INT_DATA; +#pragma pack() + +typedef enum { + EfiGetPlatformBinaryMpTable = 0, + EfiGetPlatformBinaryOemIntData = 1, + EfiGetPlatformBinaryOem16Data = 2, + EfiGetPlatformBinaryOem32Data = 3, + EfiGetPlatformBinaryTpmBinary = 4, + EfiGetPlatformBinarySystemRom = 5, + EfiGetPlatformPciExpressBase = 6, + EfiGetPlatformPmmSize = 7, + EfiGetPlatformEndOpromShadowAddr = 8, + +} EFI_GET_PLATFORM_INFO_MODE; + +typedef enum { + EfiGetPlatformVgaHandle = 0, + EfiGetPlatformIdeHandle = 1, + EfiGetPlatformIsaBusHandle = 2, + EfiGetPlatformUsbHandle = 3 +} EFI_GET_PLATFORM_HANDLE_MODE; + +typedef enum { + EfiPlatformHookPrepareToScanRom = 0, + EfiPlatformHookShadowServiceRoms= 1, + EfiPlatformHookAfterRomInit = 2 +} EFI_GET_PLATFORM_HOOK_MODE; + +/** + Finds the binary data or other platform information. + + @param This Protocol instance pointer. + @param Mode Specifies what data to return + @param Table Pointer to MP table. + @param TableSize Size in bytes of table. + @param Location Legacy region requested + 0x00 = Any location + Bit 0 = 0xF0000 region + Bit 1 = 0xE0000 region + Multiple bits can be set + @param Alignment Address alignment for allocation. + Bit mapped. First non-zero bit from right + is alignment. + @param LegacySegment Segment in LegacyBios where Table is stored + @param LegacyOffset Offset in LegacyBios where Table is stored + + @retval EFI_SUCCESS Data was returned successfully. + @retval EFI_UNSUPPORTED Mode is not supported on the platform. + @retval EFI_NOT_FOUND Binary image or table not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_GET_PLATFORM_INFO) ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN EFI_GET_PLATFORM_INFO_MODE Mode, + OUT VOID **Table, + OUT UINTN *TableSize, + OUT UINTN *Location, + OUT UINTN *Alignment, + IN UINT16 LegacySegment, + IN UINT16 LegacyOffset + ) +; + +/** + Returns a buffer of handles for the requested sub-function. + + @param This Protocol instance pointer. + @param Mode Specifies what handle to return. + @param Type Type from Device Path for Handle to represent. + @param HandleBuffer Handles of the device/controller in priority order + with HandleBuffer[0] highest priority. + @param HandleCount Number of handles in the buffer. + @param AdditionalData Mode specific. + + @retval EFI_SUCCESS Handle is valid + @retval EFI_UNSUPPORTED Mode is not supported on the platform. + @retval EFI_NOT_FOUND Handle is not known + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_GET_PLATFORM_HANDLE) ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN EFI_GET_PLATFORM_HANDLE_MODE Mode, + IN UINT16 Type, + OUT EFI_HANDLE **HandleBuffer, + OUT UINTN *HandleCount, + IN VOID **AdditionalData OPTIONAL + ) +; + +/** + Load and initialize the Legacy BIOS SMM handler. + + @param This Protocol instance pointer. + @param EfiToLegacy16BootTable Pointer to Legacy16 boot table. + + @retval EFI_SUCCESS SMM code loaded. + @retval EFI_DEVICE_ERROR SMM code failed to load + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_SMM_INIT) ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN VOID *EfiToLegacy16BootTable + ) +; + +/** + Allows platform to perform any required action after a LegacyBios operation. + + @param This Protocol instance pointer. + @param Mode Specifies what handle to return. + @param Type Mode specific. + @param DeviceHandle List of PCI devices in the system. + @param ShadowAddress First free OpROM area, after other OpROMs have been dispatched. + @param Compatibility16Table Pointer to Compatibility16Table. + @param AdditionalData Mode specific Pointer to additional data returned ¨C mode specific. + + @retval EFI_SUCCESS RomImage is valid + @retval EFI_UNSUPPORTED Mode is not supported on the platform. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_HOOKS) ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN EFI_GET_PLATFORM_HOOK_MODE Mode, + IN UINT16 Type, + IN EFI_HANDLE DeviceHandle, + IN OUT UINTN *ShadowAddress, + IN EFI_COMPATIBILITY16_TABLE *Compatibility16Table, + IN VOID **AdditionalData OPTIONAL + ) +; + +/** + Returns information associated with PCI IRQ routing. + + @param This Protocol instance pointer. + @param RoutingTable Pointer to PCI IRQ Routing table. + @param RoutingTableEntries Number of entries in table. + @param LocalPirqTable $PIR table + @param PirqTableSize $PIR table size + @param LocalIrqPriorityTable List of interrupts in priority order to assign + @param IrqPriorityTableEntries- Number of entries in priority table + + @retval EFI_SUCCESS Data was successfully returned. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_GET_ROUTING_TABLE) ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + OUT VOID **RoutingTable, + OUT UINTN *RoutingTableEntries, + OUT VOID **LocalPirqTable, OPTIONAL + OUT UINTN *PirqTableSize, OPTIONAL + OUT VOID **LocalIrqPriorityTable, OPTIONAL + OUT UINTN *IrqPriorityTableEntries OPTIONAL + ) +; + +/** + Translates the given PIRQ accounting for bridge + + @param This Protocol instance pointer. + @param PciBus PCI bus number for this device. + @param PciDevice PCI device number for this device. + @param PciFunction PCI function number for this device. + @param Pirq Input is PIRQ reported by device, output is true PIRQ. + @param PciIrq The IRQ already assigned to the PIRQ or the IRQ to be + assigned to the PIRQ. + + @retval EFI_SUCCESS The PIRQ was translated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_TRANSLATE_PIRQ) ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN UINTN PciBus, + IN UINTN PciDevice, + IN UINTN PciFunction, + IN OUT UINT8 *Pirq, + OUT UINT8 *PciIrq + ) +; + +/** + Attempt to legacy boot the BootOption. If the EFI contexted has been + compromised this function will not return. + + @param This Protocol instance pointer. + @param BbsDevicePath EFI Device Path from BootXXXX variable. + @param BbsTable Internal BBS table. + @param LoadOptionSize Size of LoadOption in size. + @param LoadOption LoadOption from BootXXXX variable + @param EfiToLegacy16BootTable Pointer to BootTable structure + + @retval EFI_SUCCESS Ready to boot. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_BIOS_PLATFORM_PREPARE_TO_BOOT) ( + IN EFI_LEGACY_BIOS_PLATFORM_PROTOCOL *This, + IN BBS_BBS_DEVICE_PATH *BbsDevicePath, + IN VOID *BbsTable, + IN UINT32 LoadOptionsSize, + IN VOID *LoadOptions, + IN VOID *EfiToLegacy16BootTable + ) +; + +/** + @par Protocol Description: + Abstracts the platform portion of the traditional BIOS. + + @param GetPlatformInfo + Gets binary data or other platform information. + + @param GetPlatformHandle + Returns a buffer of all handles matching the requested subfunction. + + @param SmmInit + Loads and initializes the traditional BIOS SMM handler. + + @param PlatformHooks + Allows platform to perform any required actions after a LegacyBios operation. + + @param GetRoutingTable + Gets $PIR table. + + @param TranslatePirq + Translates the given PIRQ to the final value after traversing any PCI bridges. + + @param PrepareToBoot + Final platform function before the system attempts to boot to a traditional OS. + +**/ +struct _EFI_LEGACY_BIOS_PLATFORM_PROTOCOL { + EFI_LEGACY_BIOS_PLATFORM_GET_PLATFORM_INFO GetPlatformInfo; + EFI_LEGACY_BIOS_PLATFORM_GET_PLATFORM_HANDLE GetPlatformHandle; + EFI_LEGACY_BIOS_PLATFORM_SMM_INIT SmmInit; + EFI_LEGACY_BIOS_PLATFORM_HOOKS PlatformHooks; + EFI_LEGACY_BIOS_PLATFORM_GET_ROUTING_TABLE GetRoutingTable; + EFI_LEGACY_BIOS_PLATFORM_TRANSLATE_PIRQ TranslatePirq; + EFI_LEGACY_BIOS_PLATFORM_PREPARE_TO_BOOT PrepareToBoot; +}; + +extern EFI_GUID gEfiLegacyBiosPlatformProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/LegacyInterrupt.h b/MdePkg/Include/Protocol/LegacyInterrupt.h new file mode 100644 index 0000000000..54dc9aaa9b --- /dev/null +++ b/MdePkg/Include/Protocol/LegacyInterrupt.h @@ -0,0 +1,131 @@ +/** @file + This protocol manages the legacy memory regions between 0xc0000 - 0xfffff + + Copyright (c) 2006, 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. + + Module Name: LegacyInterrupt.h + + @par Revision Reference: + This protocol is defined in Framework for EFI Compatibility Support Module spec + Version 0.96 + +**/ + +#ifndef _EFI_LEGACY_INTERRUPT_H_ +#define _EFI_LEGACY_INTERRUPT_H_ + +#define EFI_LEGACY_INTERRUPT_PROTOCOL_GUID \ + { \ + 0x31ce593d, 0x108a, 0x485d, {0xad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66, 0xbe } \ + } + +typedef struct _EFI_LEGACY_INTERRUPT_PROTOCOL EFI_LEGACY_INTERRUPT_PROTOCOL; + +/** + Get the number of PIRQs this hardware supports. + + @param This Protocol instance pointer. + @param NumberPirsq Number of PIRQs. + + @retval EFI_SUCCESS Number of PIRQs returned. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_INTERRUPT_GET_NUMBER_PIRQS) ( + IN EFI_LEGACY_INTERRUPT_PROTOCOL *This, + OUT UINT8 *NumberPirqs + ); + +/** + Gets the PCI location associated with this protocol. + + @param This Protocol instance pointer. + @param Bus PCI Bus + @param Device PCI Device + @param Function PCI Function + + @retval EFI_SUCCESS Bus/Device/Function returned + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_INTERRUPT_GET_LOCATION) ( + IN EFI_LEGACY_INTERRUPT_PROTOCOL *This, + OUT UINT8 *Bus, + OUT UINT8 *Device, + OUT UINT8 *Function + ); + +/** + Read the PIRQ register and return the data + + @param This Protocol instance pointer. + @param PirqNumber PIRQ register to read + @param PirqData Data read + + @retval EFI_SUCCESS Data was read + @retval EFI_INVALID_PARAMETER Invalid PIRQ number + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_INTERRUPT_READ_PIRQ) ( + IN EFI_LEGACY_INTERRUPT_PROTOCOL *This, + IN UINT8 PirqNumber, + OUT UINT8 *PirqData + ); + +/** + Write the specified PIRQ register with the given data. + + @param This Protocol instance pointer. + @param PirqNumber PIRQ register to read. + @param PirqData Data written. + + @retval EFI_SUCCESS Table pointer returned + @retval EFI_INVALID_PARAMETER Invalid PIRQ number + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_INTERRUPT_WRITE_PIRQ) ( + IN EFI_LEGACY_INTERRUPT_PROTOCOL *This, + IN UINT8 PirqNumber, + IN UINT8 PirqData + ); + +/** + @par Protocol Description: + Abstracts the PIRQ programming from the generic EFI Compatibility Support Modules + + @param GetNumberPirqs + Gets the number of PIRQs supported. + + @param GetLocation + Gets the PCI bus, device, and function that associated with this protocol. + + @param ReadPirq + Reads the indicated PIRQ register. + + @param WritePirq + Writes to the indicated PIRQ register. + +**/ +struct _EFI_LEGACY_INTERRUPT_PROTOCOL { + EFI_LEGACY_INTERRUPT_GET_NUMBER_PIRQS GetNumberPirqs; + EFI_LEGACY_INTERRUPT_GET_LOCATION GetLocation; + EFI_LEGACY_INTERRUPT_READ_PIRQ ReadPirq; + EFI_LEGACY_INTERRUPT_WRITE_PIRQ WritePirq; +}; + +extern EFI_GUID gEfiLegacyInterruptProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/LegacyRegion.h b/MdePkg/Include/Protocol/LegacyRegion.h new file mode 100644 index 0000000000..db7d346186 --- /dev/null +++ b/MdePkg/Include/Protocol/LegacyRegion.h @@ -0,0 +1,152 @@ +/** @file + This protocol manages the legacy memory regions between 0xc0000 - 0xfffff + + Copyright (c) 2006, 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. + + Module Name: LegacyRegion.h + + @par Revision Reference: + This protocol is defined in Framework for EFI Compatibility Support Module spec + Version 0.96 + +**/ + +#ifndef _EFI_LEGACY_REGION_H_ +#define _EFI_LEGACY_REGION_H_ + +#define EFI_LEGACY_REGION_PROTOCOL_GUID \ + { \ + 0xfc9013a, 0x568, 0x4ba9, {0x9b, 0x7e, 0xc9, 0xc3, 0x90, 0xa6, 0x60, 0x9b } \ + } + +typedef struct _EFI_LEGACY_REGION_PROTOCOL EFI_LEGACY_REGION_PROTOCOL; + +/** + Sets hardware to decode or not decode a region. + + @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance + + @param Start Start of region to decode. + + @param Length Size in bytes of the region. + + @param On Decode/nondecode flag. + + @retval EFI_SUCCESS Decode range successfully changed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_REGION_DECODE) ( + IN EFI_LEGACY_REGION_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + IN BOOLEAN *On + ); + +/** + Sets a region to read only. + + @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance + + @param Start Start of region to lock. + + @param Length Size in bytes of the region. + + @param Granularity Lock attribute affects this granularity in bytes. + + @retval EFI_SUCCESS The region was made read only. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_REGION_LOCK) ( + IN EFI_LEGACY_REGION_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity OPTIONAL + ); + +/** + Sets a region to read only and ensures that flash is locked from being + inadvertently modified. + + @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance + + @param Start Start of region to lock. + + @param Length Size in bytes of the region. + + @param Granularity Lock attribute affects this granularity in bytes. + + @retval EFI_SUCCESS The region was made read only and flash is locked. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_REGION_BOOT_LOCK) ( + IN EFI_LEGACY_REGION_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity OPTIONAL + ); + +/** + Sets a region to read-write. + + @param This Indicates the EFI_LEGACY_REGION_PROTOCOL instance + + @param Start Start of region to lock. + + @param Length Size in bytes of the region. + + @param Granularity Lock attribute affects this granularity in bytes. + + @retval EFI_SUCCESS The region was successfully made read-write. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LEGACY_REGION_UNLOCK) ( + IN EFI_LEGACY_REGION_PROTOCOL *This, + IN UINT32 Start, + IN UINT32 Length, + OUT UINT32 *Granularity OPTIONAL + ); + +/** + @par Protocol Description: + Abstracts the hardware control of the physical address region 0xC0000¨C0xFFFFF + for the traditional BIOS. + + @param Decode + Specifies a region for the chipset to decode + + @param Lock + Makes the specified OpROM region read only or locked. + + @param BootLock + Sets a region to read only and ensures tat flash is locked from + inadvertent modification. + + @param Unlock + Makes the specified OpROM region read-write or unlocked. + +**/ +struct _EFI_LEGACY_REGION_PROTOCOL { + EFI_LEGACY_REGION_DECODE Decode; + EFI_LEGACY_REGION_LOCK Lock; + EFI_LEGACY_REGION_BOOT_LOCK BootLock; + EFI_LEGACY_REGION_UNLOCK UnLock; +}; + +extern EFI_GUID gEfiLegacyRegionProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/LoadFile.h b/MdePkg/Include/Protocol/LoadFile.h new file mode 100644 index 0000000000..346039fb61 --- /dev/null +++ b/MdePkg/Include/Protocol/LoadFile.h @@ -0,0 +1,83 @@ +/** @file + Load File protocol as defined in the EFI 1.0 specification. + + Load file protocol exists to supports the addition of new boot devices, + and to support booting from devices that do not map well to file system. + Network boot is done via a LoadFile protocol. + + EFI 1.0 can boot from any device that produces a LoadFile protocol. + + Copyright (c) 2006, 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. + + Module Name: LoadFile.h + +**/ + +#ifndef __EFI_LOAD_FILE_PROTOCOL_H__ +#define __EFI_LOAD_FILE_PROTOCOL_H__ + +#define LOAD_FILE_PROTOCOL_GUID \ + { \ + 0x56EC3091, 0x954C, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ + } + +// +// Protocol Guid Name defined by UEFI 2.0 spec. +// +#define EFI_LOAD_FILE_PROTOCOL_GUID LOAD_FILE_PROTOCOL_GUID + +typedef struct _EFI_LOAD_FILE_PROTOCOL EFI_LOAD_FILE_PROTOCOL; + +/** + Causes the driver to load a specified file. + + @param This Protocol instance pointer. + @param FilePath The device specific path of the file to load. + @param BootPolicy If TRUE, indicates that the request originates from the + boot manager is attempting to load FilePath as a boot + selection. If FALSE, then FilePath must match as exact file + to be loaded. + @param BufferSize On input the size of Buffer in bytes. On output with a return + code of EFI_SUCCESS, the amount of data transferred to + Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, + the size of Buffer required to retrieve the requested file. + @param Buffer The memory buffer to transfer the file to. IF Buffer is NULL, + then no the size of the requested file is returned in + BufferSize. + + @retval EFI_SUCCESS The file was loaded. + @retval EFI_UNSUPPORTED The device does not support the provided BootPolicy + @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or + BufferSize is NULL. + @retval EFI_NO_MEDIA No medium was present to load the file. + @retval EFI_DEVICE_ERROR The file was not loaded due to a device error. + @retval EFI_NO_RESPONSE The remote system did not respond. + @retval EFI_NOT_FOUND The file was not found + @retval EFI_ABORTED The file load process was manually cancelled. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOAD_FILE) ( + IN EFI_LOAD_FILE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN BOOLEAN BootPolicy, + IN OUT UINTN *BufferSize, + IN VOID *Buffer OPTIONAL + ) +; + +struct _EFI_LOAD_FILE_PROTOCOL { + EFI_LOAD_FILE LoadFile; +}; + +extern EFI_GUID gEfiLoadFileProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/LoadedImage.h b/MdePkg/Include/Protocol/LoadedImage.h new file mode 100644 index 0000000000..aee063c927 --- /dev/null +++ b/MdePkg/Include/Protocol/LoadedImage.h @@ -0,0 +1,69 @@ +/** @file + EFI 1.0 Loaded image protocol definition. + + Every EFI driver and application is passed an image handle when it is loaded. + This image handle will contain a Loaded Image Protocol. + + Copyright (c) 2006, 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. + + Module Name: LoadedImage.h + +**/ + +#ifndef __LOADED_IMAGE_PROTOCOL_H__ +#define __LOADED_IMAGE_PROTOCOL_H__ + +#define EFI_LOADED_IMAGE_PROTOCOL_GUID \ + { \ + 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B } \ + } + +// +// EFI_SYSTEM_TABLE & EFI_IMAGE_UNLOAD are defined in EfiApi.h +// +#define EFI_LOADED_IMAGE_INFORMATION_REVISION 0x1000 +#define EFI_LOADED_IMAGE_PROTOCOL_REVISION EFI_LOADED_IMAGE_INFORMATION_REVISION + +typedef struct { + UINT32 Revision; + EFI_HANDLE ParentHandle; + EFI_SYSTEM_TABLE *SystemTable; + + // + // Source location of image + // + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *FilePath; + VOID *Reserved; + + // + // Images load options + // + UINT32 LoadOptionsSize; + VOID *LoadOptions; + + // + // Location of where image was loaded + // + VOID *ImageBase; + UINT64 ImageSize; + EFI_MEMORY_TYPE ImageCodeType; + EFI_MEMORY_TYPE ImageDataType; + + // + // If the driver image supports a dynamic unload request + // + EFI_IMAGE_UNLOAD Unload; + +} EFI_LOADED_IMAGE_PROTOCOL; + +extern EFI_GUID gEfiLoadedImageProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/ManagedNetwork.h b/MdePkg/Include/Protocol/ManagedNetwork.h new file mode 100644 index 0000000000..1bf9a1305a --- /dev/null +++ b/MdePkg/Include/Protocol/ManagedNetwork.h @@ -0,0 +1,314 @@ +/** @file + EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL as defined in UEFI 2.0. + EFI_MANAGED_NETWORK_PROTOCOL as defined in UEFI 2.0. + + Copyright (c) 2006, 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. + + Module Name: ManagedNetwork.h + +**/ + +#ifndef _EFI_MANAGED_NETWORK_PROTOCOL_H +#define _EFI_MANAGED_NETWORK_PROTOCOL_H + +#define EFI_MANAGED_NETWORK_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0xf36ff770, 0xa7e1, 0x42cf, {0x9e, 0xd2, 0x56, 0xf0, 0xf2, 0x71, 0xf4, 0x4c } \ + } + +#define EFI_MANAGED_NETWORK_PROTOCOL_GUID \ + { \ + 0x3b95aa31, 0x3793, 0x434b, {0x86, 0x67, 0xc8, 0x7, 0x8, 0x92, 0xe0, 0x5e } \ + } + +typedef struct _EFI_MANAGED_NETWORK_PROTOCOL EFI_MANAGED_NETWORK_PROTOCOL; + +typedef struct { + UINT32 ReceivedQueueTimeoutValue; + UINT32 TransmitQueueTimeoutValue; + UINT16 ProtocolTypeFilter; + BOOLEAN EnableUnicastReceive; + BOOLEAN EnableMulticastReceive; + BOOLEAN EnableBroadcastReceive; + BOOLEAN EnablePromiscuousReceive; + BOOLEAN FlushQueuesOnReset; + BOOLEAN EnableReceiveTimestamps; + BOOLEAN DisableBackgroundPolling; +} EFI_MANAGED_NETWORK_CONFIG_DATA; + +typedef struct { + EFI_TIME Timestamp; + EFI_EVENT RecycleEvent; + UINT32 PacketLength; + UINT32 HeaderLength; + UINT32 AddressLength; + UINT32 DataLength; + BOOLEAN BroadcastFlag; + BOOLEAN MulticastFlag; + BOOLEAN PromiscuousFlag; + UINT16 ProtocolType; + VOID *DestinationAddress; + VOID *SourceAddress; + VOID *MediaHeader; + VOID *PacketData; +} EFI_MANAGED_NETWORK_RECEIVE_DATA; + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_MANAGED_NETWORK_FRAGMENT_DATA; + +typedef struct { + EFI_MAC_ADDRESS *DestinationAddress; //OPTIONAL + EFI_MAC_ADDRESS *SourceAddress; //OPTIONAL + UINT16 ProtocolType; //OPTIONAL + UINT32 DataLength; + UINT16 HeaderLength; //OPTIONAL + UINT16 FragmentCount; + EFI_MANAGED_NETWORK_FRAGMENT_DATA FragmentTable[1]; +} EFI_MANAGED_NETWORK_TRANSMIT_DATA; + + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_MANAGED_NETWORK_RECEIVE_DATA *RxData; + EFI_MANAGED_NETWORK_TRANSMIT_DATA *TxData; + } Packet; +} EFI_MANAGED_NETWORK_COMPLETION_TOKEN; + +/** + Returns the operational parameters for the current MNP child driver. + + @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param MnpConfigData Pointer to storage for MNP operational parameters. + @param SnpModeData Pointer to storage for SNP operational parameters. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_UNSUPPORTED The requested feature is unsupported in this MNP implementation. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. The default + values are returned in MnpConfigData if it is not NULL. + @retval Other The mode data could not be read. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_GET_MODE_DATA) ( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ) +; + +/** + Sets or clears the operational parameters for the MNP child driver. + + @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param MnpConfigData Pointer to configuration data that will be assigned to the MNP + child driver instance. If NULL, the MNP child driver instance is + reset to startup defaults and all pending transmit and receive + requests are flushed. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES Required system resources (usually memory) could not be + allocated. + @retval EFI_UNSUPPORTED The requested feature is unsupported in this [MNP] + implementation. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval Other The MNP child driver instance has been reset to startup defaults. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_CONFIGURE) ( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL + ) +; + +/** + Translates an IP multicast address to a hardware (MAC) multicast address. + + @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param Ipv6Flag Set to TRUE to if IpAddress is an IPv6 multicast address. + Set to FALSE if IpAddress is an IPv4 multicast address. + @param IpAddress Pointer to the multicast IP address (in network byte order) to convert. + @param MacAddress Pointer to the resulting multicast MAC address. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One of the following conditions is TRUE: + - This is NULL. + - IpAddress is NULL. + - *IpAddress is not a valid multicast IP address. + - MacAddress is NULL. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_UNSUPPORTED The requested feature is unsupported in this MNP implementation. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval Other The address could not be converted. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_MCAST_IP_TO_MAC) ( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN BOOLEAN Ipv6Flag, + IN EFI_IP_ADDRESS *IpAddress, + OUT EFI_MAC_ADDRESS *MacAddress + ) +; + +/** + Enables and disables receive filters for multicast address. + + @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param JoinFlag Set to TRUE to join this multicast group. + Set to FALSE to leave this multicast group. + @param MacAddress Pointer to the multicast MAC group (address) to join or leave. + + @retval EFI_SUCCESS The requested operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - JoinFlag is TRUE and MacAddress is NULL. + - *MacAddress is not a valid multicast MAC address. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_ALREADY_STARTED The supplied multicast group is already joined. + @retval EFI_NOT_FOUND The supplied multicast group is not joined. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval EFI_UNSUPPORTED The requested feature is unsupported in this MNP implementation. + @retval Other The requested operation could not be completed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_GROUPS) ( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN BOOLEAN JoinFlag, + IN EFI_MAC_ADDRESS *MacAddress OPTIONAL + ) +; + +/** + Places asynchronous outgoing data packets into the transmit queue. + + @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param Token Pointer to a token associated with the transmit data descriptor. + + @retval EFI_SUCCESS The transmit completion token was cached. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_ACCESS_DENIED The transmit completion token is already in the transmit queue. + @retval EFI_OUT_OF_RESOURCES The transmit data could not be queued due to a lack of system resources + (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY The transmit request could not be queued because the transmit queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_TRANSMIT) ( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token + ) +; + +/** + Places an asynchronous receiving request into the receiving queue. + + @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param Token Pointer to a token associated with the receive data descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Token is NULL. + - Token.Event is NULL + @retval EFI_OUT_OF_RESOURCES The transmit data could not be queued due to a lack of system resources + (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_ACCESS_DENIED The receive completion token was already in the receive queue. + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_RECEIVE) ( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token + ) +; + + +/** + Aborts an asynchronous transmit or receive request. + + @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + @param Token Pointer to a token that has been issued by + EFI_MANAGED_NETWORK_PROTOCOL.Transmit() or + EFI_MANAGED_NETWORK_PROTOCOL.Receive(). If + NULL, all pending tokens are aborted. + + @retval EFI_SUCCESS The asynchronous I/O request was aborted and Token.Event + was signaled. When Token is NULL, all pending requests were + aborted and their events were signaled. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was + not found in the transmit or receive queue. It has either completed + or was not issued by Transmit() and Receive(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_CANCEL) ( + IN EFI_MANAGED_NETWORK_PROTOCOL *This, + IN EFI_MANAGED_NETWORK_COMPLETION_TOKEN *Token OPTIONAL + ) +; + +/** + Polls for incoming data packets and processes outgoing data packets. + + @param This Pointer to the EFI_MANAGED_NETWORK_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This MNP child driver instance has not been configured. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY No incoming or outgoing data was processed. Consider increasing + the polling rate. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MANAGED_NETWORK_POLL) ( + IN EFI_MANAGED_NETWORK_PROTOCOL *This + ) +; + +struct _EFI_MANAGED_NETWORK_PROTOCOL { + EFI_MANAGED_NETWORK_GET_MODE_DATA GetModeData; + EFI_MANAGED_NETWORK_CONFIGURE Configure; + EFI_MANAGED_NETWORK_MCAST_IP_TO_MAC McastIpToMac; + EFI_MANAGED_NETWORK_GROUPS Groups; + EFI_MANAGED_NETWORK_TRANSMIT Transmit; + EFI_MANAGED_NETWORK_RECEIVE Receive; + EFI_MANAGED_NETWORK_CANCEL Cancel; + EFI_MANAGED_NETWORK_POLL Poll; +}; + +extern EFI_GUID gEfiManagedNetworkServiceBindingProtocolGuid; +extern EFI_GUID gEfiManagedNetworkProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Mtftp4.h b/MdePkg/Include/Protocol/Mtftp4.h new file mode 100644 index 0000000000..840e04b4f3 --- /dev/null +++ b/MdePkg/Include/Protocol/Mtftp4.h @@ -0,0 +1,508 @@ +/** @file + EFI Multicast Trivial File Tranfer Protocol Definition + + Copyright (c) 2006, 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. + + Module Name: Mtftp4.h + +**/ + +#ifndef __EFI_MTFTP4_PROTOCOL_H__ +#define __EFI_MTFTP4_PROTOCOL_H__ + +#define EFI_MTFTP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x2FE800BE, 0x8F01, 0x4aa6, {0x94, 0x6B, 0xD7, 0x13, 0x88, 0xE1, 0x83, 0x3F } \ + } + +#define EFI_MTFTP4_PROTOCOL_GUID \ + { \ + 0x3ad9df29, 0x4501, 0x478d, {0xb1, 0xf8, 0x7f, 0x7f, 0xe7, 0x0e, 0x50, 0xf3 } \ + } + +typedef struct _EFI_MTFTP4_PROTOCOL EFI_MTFTP4_PROTOCOL; +typedef struct _EFI_MTFTP4_TOKEN EFI_MTFTP4_TOKEN; + +// +//MTFTP4 packet opcode definition +// +#define EFI_MTFTP4_OPCODE_RRQ 1 +#define EFI_MTFTP4_OPCODE_WRQ 2 +#define EFI_MTFTP4_OPCODE_DATA 3 +#define EFI_MTFTP4_OPCODE_ACK 4 +#define EFI_MTFTP4_OPCODE_ERROR 5 +#define EFI_MTFTP4_OPCODE_OACK 6 +#define EFI_MTFTP4_OPCODE_DIR 7 +#define EFI_MTFTP4_OPCODE_DATA8 8 +#define EFI_MTFTP4_OPCODE_ACK8 9 + +// +// MTFTP4 error code definition +// +#define EFI_MTFTP4_ERRORCODE_NOT_DEFINED 0 +#define EFI_MTFTP4_ERRORCODE_FILE_NOT_FOUND 1 +#define EFI_MTFTP4_ERRORCODE_ACCESS_VIOLATION 2 +#define EFI_MTFTP4_ERRORCODE_DISK_FULL 3 +#define EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION 4 +#define EFI_MTFTP4_ERRORCODE_UNKNOWN_TRANSFER_ID 5 +#define EFI_MTFTP4_ERRORCODE_FILE_ALREADY_EXISTS 6 +#define EFI_MTFTP4_ERRORCODE_NO_SUCH_USER 7 +#define EFI_MTFTP4_ERRORCODE_REQUEST_DENIED 8 + +// +// MTFTP4 pacekt definitions +// +#pragma pack(1) + +typedef struct { + UINT16 OpCode; + UINT8 Filename[1]; +} EFI_MTFTP4_REQ_HEADER; + +typedef struct { + UINT16 OpCode; + UINT8 Data[1]; +} EFI_MTFTP4_OACK_HEADER; + +typedef struct { + UINT16 OpCode; + UINT16 Block; + UINT8 Data[1]; +} EFI_MTFTP4_DATA_HEADER; + +typedef struct { + UINT16 OpCode; + UINT16 Block[1]; +} EFI_MTFTP4_ACK_HEADER; + +typedef struct { + UINT16 OpCode; + UINT64 Block; + UINT8 Data[1]; +} EFI_MTFTP4_DATA8_HEADER; + +typedef struct { + UINT16 OpCode; + UINT64 Block[1]; +} EFI_MTFTP4_ACK8_HEADER; + +typedef struct { + UINT16 OpCode; + UINT16 ErrorCode; + UINT8 ErrorMessage[1]; +} EFI_MTFTP4_ERROR_HEADER; + +typedef union { + UINT16 OpCode; + EFI_MTFTP4_REQ_HEADER Rrq; + EFI_MTFTP4_REQ_HEADER Wrq; + EFI_MTFTP4_OACK_HEADER Oack; + EFI_MTFTP4_DATA_HEADER Data; + EFI_MTFTP4_ACK_HEADER Ack; + EFI_MTFTP4_DATA8_HEADER Data8; + EFI_MTFTP4_ACK8_HEADER Ack8; + EFI_MTFTP4_ERROR_HEADER Error; +} EFI_MTFTP4_PACKET; + +#pragma pack() + +// +// MTFTP4 option definition +// +typedef struct { + UINT8 *OptionStr; + UINT8 *ValueStr; +} EFI_MTFTP4_OPTION; + + +typedef struct { + BOOLEAN UseDefaultSetting; + EFI_IPv4_ADDRESS StationIp; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 LocalPort; + EFI_IPv4_ADDRESS GatewayIp; + EFI_IPv4_ADDRESS ServerIp; + UINT16 InitialServerPort; + UINT16 TryCount; + UINT16 TimeoutValue; +} EFI_MTFTP4_CONFIG_DATA; + + +typedef struct { + EFI_MTFTP4_CONFIG_DATA ConfigData; + UINT8 SupportedOptionCount; + UINT8 **SupportedOptoins; + UINT8 UnsupportedOptionCount; + UINT8 **UnsupportedOptoins; +} EFI_MTFTP4_MODE_DATA; + + +typedef struct { + EFI_IPv4_ADDRESS GatewayIp; + EFI_IPv4_ADDRESS ServerIp; + UINT16 ServerPort; + UINT16 TryCount; + UINT16 TimeoutValue; +} EFI_MTFTP4_OVERRIDE_DATA; + +// +// Protocol interfaces definition +// + +/** + a callback function that is provided by the caller to intercept + the EFI_MTFTP4_OPCODE_DATA or EFI_MTFTP4_OPCODE_DATA8 packets processed in the + EFI_MTFTP4_PROTOCOL.ReadFile() function, and alternatively to intercept + EFI_MTFTP4_OPCODE_OACK or EFI_MTFTP4_OPCODE_ERROR packets during a call to + EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory(). + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token The token that the caller provided in the + EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() + or ReadDirectory() function. + @param PacketLen Indicates the length of the packet. + @param Packet Pointer to an MTFTPv4 packet. + + @retval EFI_SUCCESS Operation sucess + @retval Others Abort transfer process + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_CHECK_PACKET)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token, + IN UINT16 PacketLen, + IN EFI_MTFTP4_PACKET *Paket + ) +; + +/** + Timeout callback funtion. + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token The token that is provided in the + EFI_MTFTP4_PROTOCOL.ReadFile() or + EFI_MTFTP4_PROTOCOL.WriteFile() or + EFI_MTFTP4_PROTOCOL.ReadDirectory() functions + by the caller. + + @retval EFI_SUCCESS Operation sucess + @retval Others Aborts download process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_TIMEOUT_CALLBACK)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token + ) +; + +/** + a callback function that the caller provides to feed data to the + EFI_MTFTP4_PROTOCOL.WriteFile() function. + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token The token provided in the + EFI_MTFTP4_PROTOCOL.WriteFile() by the caller. + @param Length Indicates the length of the raw data wanted on input, and the + length the data available on output. + @param Buffer Pointer to the buffer where the data is stored. + + @retval EFI_SUCCESS Operation sucess + @retval Others Aborts session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_PACKET_NEEDED)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token, + IN OUT UINT16 *Length, + OUT VOID **Buffer + ) +; + + +/** + Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device. + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + @param ModeData Pointer to storage for the EFI MTFTPv4 Protocol driver mode data. + + @retval EFI_SUCCESS The configuration data was successfully returned. + @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated. + @retval EFI_INVALID_PARAMETER This is NULL or ModeData is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_GET_MODE_DATA)( + IN EFI_MTFTP4_PROTOCOL *This, + OUT EFI_MTFTP4_MODE_DATA *ModeData + ) +; + + +/** + Initializes, changes, or resets the default operational setting for this + EFI MTFTPv4 Protocol driver instance. + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + @param MtftpConfigData Pointer to the configuration data structure. + + @retval EFI_SUCCESS The EFI MTFTPv4 Protocol driver was configured successfully. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_ACCESS_DENIED The EFI configuration could not be changed at this time because + there is one MTFTP background operation in progress. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) has not finished yet. + @retval EFI_UNSUPPORTED A configuration protocol (DHCP, BOOTP, RARP, etc.) could not + be located when clients choose to use the default address + settings. + @retval EFI_OUT_OF_RESOURCES The EFI MTFTPv4 Protocol driver instance data could not be + allocated. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. The EFI + MTFTPv4 Protocol driver instance is not configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_CONFIGURE)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_CONFIG_DATA *MtftpConfigData OPTIONAL + ) +; + + +/** + Gets information about a file from an MTFTPv4 server. + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + @param OverrideData Data that is used to override the existing parameters. If NULL, + the default parameters that were set in the + EFI_MTFTP4_PROTOCOL.Configure() function are used. + @param Filename Pointer to ASCIIZ file name string. + @param ModeStr Pointer to ASCIIZ mode string. If NULL, ¡°octet¡± will be used. + @param OptionCount Number of option/value string pairs in OptionList. + @param OptionList Pointer to array of option/value string pairs. Ignored if + OptionCount is zero. + @param PacketLength The number of bytes in the returned packet. + @param Packet The pointer to the received packet. This buffer must be freed by + the caller. + + @retval EFI_SUCCESS An MTFTPv4 OACK packet was received and is in the Buffer. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_UNSUPPORTED One or more options in the OptionList are in the + unsupported list of structure EFI_MTFTP4_MODE_DATA. + + @retval EFI_NOT_STARTED The EFI MTFTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) has not finished yet. + @retval EFI_ACCESS_DENIED The previous operation has not completed yet. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_TFTP_ERROR An MTFTPv4 ERROR packet was received and is in the buffer. + @retval EFI_ICMP_ERROR An ICMP ERROR packet was received and is in the Buffer. + @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv4 packet was received and is in the buffer. + @retval EFI_TIMEOUT No responses were received from the MTFTPv4 server. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_GET_INFO)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_OVERRIDE_DATA *OverrideData OPTIONAL, + IN UINT8 *Filename, + IN UINT8 *ModeStr OPTIONAL, + IN UINT8 OptionCount, + IN EFI_MTFTP4_OPTION *OptionList, + OUT UINT32 *PacketLength, + OUT EFI_MTFTP4_PACKET **Packet OPTIONAL + ) +; + +/** + Parses the options in an MTFTPv4 OACK packet. + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + @param PacketLen Length of the OACK packet to be parsed. + @param Packet Pointer to the OACK packet to be parsed. + @param OptionCount Pointer to the number of options in following OptionList. + @param OptionList Pointer to EFI_MTFTP4_OPTION storage. Call the EFI Boot + Service FreePool() to release each option if they are not + needed any more. + + @retval EFI_SUCCESS The OACK packet was valid and the OptionCount and + OptionList parameters have been updated. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - PacketLen is 0. + - Packet is NULL or Packet is not a valid MTFTPv4 packet. + - OptionCount is NULL. + @retval EFI_NOT_FOUND No options were found in the OACK packet. + @retval EFI_OUT_OF_RESOURCES Storage for the OptionList array cannot be allocated. + @retval EFI_PROTOCOL_ERROR One or more of the option fields is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_PARSE_OPTIONS)( + IN EFI_MTFTP4_PROTOCOL *This, + IN UINT32 PacketLen, + IN EFI_MTFTP4_PACKET *Packet, + OUT UINT32 *OptionCount, + OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL + ) +; + + +/** + Downloads a file from an MTFTPv4 server. + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token Pointer to the token structure to provide the parameters that are + used in this operation. + + @retval EFI_SUCCESS The data file has been transferred successfully. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_BUFFER_TOO_SMALL BufferSize is not large enough to hold the downloaded data + in downloading process. + @retval EFI_ABORTED Current operation is aborted by user. + @retval EFI_ICMP_ERROR An ICMP ERROR packet was received. + @retval EFI_TIMEOUT No responses were received from the MTFTPv4 server. + @retval EFI_TFTP_ERROR An MTFTPv4 ERROR packet was received. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_READ_FILE)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token + ) +; + + + +/** + Sends a file to an MTFTPv4 server. + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token Pointer to the token structure to provide the parameters that are + used in this operation. + + @retval EFI_SUCCESS The upload session has started. + @retval EFI_UNSUPPORTED The operation is not supported by this implementation. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_UNSUPPORTED One or more options in the Token.OptionList are in + the unsupported list of structure EFI_MTFTP4_MODE_DATA. + @retval EFI_NOT_STARTED The EFI MTFTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv4 session. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ACCESS_DENIED The previous operation has not completed yet. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_WRITE_FILE)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token + ) +; + + +/** + Downloads a data file ¡°directory¡± from an MTFTPv4 server. May be unsupported in some EFI + implementations. + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + @param Token Pointer to the token structure to provide the parameters that are + used in this operation. + + @retval EFI_SUCCESS The MTFTPv4 related file "directory" has been downloaded. + @retval EFI_UNSUPPORTED The operation is not supported by this implementation. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_UNSUPPORTED One or more options in the Token.OptionList are in + the unsupported list of structure EFI_MTFTP4_MODE_DATA. + @retval EFI_NOT_STARTED The EFI MTFTPv4 Protocol driver has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv4 session. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. + @retval EFI_ACCESS_DENIED The previous operation has not completed yet. + @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_READ_DIRECTORY)( + IN EFI_MTFTP4_PROTOCOL *This, + IN EFI_MTFTP4_TOKEN *Token + ) +; + +/** + Polls for incoming data packets and processes outgoing data packets. + + @param This Pointer to the EFI_MTFTP4_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_NOT_STARTED This EFI MTFTPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_MTFTP4_POLL) ( + IN EFI_MTFTP4_PROTOCOL *This + ) +; + + +struct _EFI_MTFTP4_PROTOCOL { + EFI_MTFTP4_GET_MODE_DATA GetModeData; + EFI_MTFTP4_CONFIGURE Configure; + EFI_MTFTP4_GET_INFO GetInfo; + EFI_MTFTP4_PARSE_OPTIONS ParseOptions; + EFI_MTFTP4_READ_FILE ReadFile; + EFI_MTFTP4_WRITE_FILE WriteFile; + EFI_MTFTP4_READ_DIRECTORY ReadDirectory; + EFI_MTFTP4_POLL Poll; +}; + +struct _EFI_MTFTP4_TOKEN { + OUT EFI_STATUS Status; + IN EFI_EVENT Event; + IN EFI_MTFTP4_OVERRIDE_DATA *OverrideData; + IN UINT8 *Filename; + IN UINT8 *ModeStr; + IN UINT32 OptionCount; + IN EFI_MTFTP4_OPTION *OptionList; + IN OUT UINT64 BufferSize; + IN OUT VOID *Buffer; + IN EFI_MTFTP4_CHECK_PACKET CheckPacket; + IN EFI_MTFTP4_TIMEOUT_CALLBACK TimeoutCallback; + IN EFI_MTFTP4_PACKET_NEEDED PacketNeeded; +}; + +extern EFI_GUID gEfiMtftp4ServiceBindingProtocolGuid; +extern EFI_GUID gEfiMtftp4ProtocolGuid; + +#endif + diff --git a/MdePkg/Include/Protocol/Pcd.h b/MdePkg/Include/Protocol/Pcd.h new file mode 100644 index 0000000000..880ae425b0 --- /dev/null +++ b/MdePkg/Include/Protocol/Pcd.h @@ -0,0 +1,293 @@ +/** @file + Platform Configuration Database (PCD) Protocol + + Copyright (c) 2006, 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. + + Module Name: Pcd.h + +**/ + +#ifndef __PCD_H__ +#define __PCD_H__ + +extern EFI_GUID gPcdProtocolGuid; + +#define PCD_PROTOCOL_GUID \ + { 0x11b34006, 0xd85b, 0x4d0a, { 0xa2, 0x90, 0xd5, 0xa5, 0x71, 0x31, 0xe, 0xf7 } } + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_SKU) ( + IN UINTN SkuId + ); + +typedef +UINT8 +(EFIAPI *PCD_PROTOCOL_GET8) ( + IN UINTN TokenNumber + ); + +typedef +UINT16 +(EFIAPI *PCD_PROTOCOL_GET16) ( + IN UINTN TokenNumber + ); + +typedef +UINT32 +(EFIAPI *PCD_PROTOCOL_GET32) ( + IN UINTN TokenNumber + ); + +typedef +UINT64 +(EFIAPI *PCD_PROTOCOL_GET64) ( + IN UINTN TokenNumber + ); + +typedef +VOID * +(EFIAPI *PCD_PROTOCOL_GET_POINTER) ( + IN UINTN TokenNumber + ); + +typedef +BOOLEAN +(EFIAPI *PCD_PROTOCOL_GET_BOOLEAN) ( + IN UINTN TokenNumber + ); + +typedef +UINTN +(EFIAPI *PCD_PROTOCOL_GET_SIZE) ( + IN UINTN TokenNumber + ); + +typedef +UINT8 +(EFIAPI *PCD_PROTOCOL_GET_EX_8) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +UINT16 +(EFIAPI *PCD_PROTOCOL_GET_EX_16) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +UINT32 +(EFIAPI *PCD_PROTOCOL_GET_EX_32) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +UINT64 +(EFIAPI *PCD_PROTOCOL_GET_EX_64) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +VOID * +(EFIAPI *PCD_PROTOCOL_GET_EX_POINTER) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +BOOLEAN +(EFIAPI *PCD_PROTOCOL_GET_EX_BOOLEAN) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +UINTN +(EFIAPI *PCD_PROTOCOL_GET_EX_SIZE) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET8) ( + IN UINTN TokenNumber, + IN UINT8 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET16) ( + IN UINTN TokenNumber, + IN UINT16 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET32) ( + IN UINTN TokenNumber, + IN UINT32 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET64) ( + IN UINTN TokenNumber, + IN UINT64 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_POINTER) ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_BOOLEAN) ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_8) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_16) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_32) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_64) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_POINTER) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_SET_EX_BOOLEAN) ( + IN CONST EFI_GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ); + +/** + Callback on SET function prototype definition. + + @param[in] CallBackGuid The PCD token GUID being set. + @param[in] CallBackToken The PCD token number being set. + @param[in] TokenData A pointer to the token data being set. + @param[in] TokenDataSize The size, in bytes, of the data being set. + + @retval VOID + +--*/ +typedef +VOID +(EFIAPI *PCD_PROTOCOL_CALLBACK) ( + IN CONST EFI_GUID *CallBackGuid, OPTIONAL + IN UINTN CallBackToken, + IN VOID *TokenData, + IN UINTN TokenDataSize + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_CALLBACK_ONSET) ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_CANCEL_CALLBACK) ( + IN UINTN TokenNumber, + IN CONST EFI_GUID *Guid, OPTIONAL + IN PCD_PROTOCOL_CALLBACK CallBackFunction + ); + +typedef +EFI_STATUS +(EFIAPI *PCD_PROTOCOL_GET_NEXT_TOKEN) ( + IN CONST EFI_GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ); + +typedef struct { + PCD_PROTOCOL_SET_SKU SetSku; + + PCD_PROTOCOL_GET8 Get8; + PCD_PROTOCOL_GET16 Get16; + PCD_PROTOCOL_GET32 Get32; + PCD_PROTOCOL_GET64 Get64; + PCD_PROTOCOL_GET_POINTER GetPtr; + PCD_PROTOCOL_GET_BOOLEAN GetBool; + PCD_PROTOCOL_GET_SIZE GetSize; + + PCD_PROTOCOL_GET_EX_8 Get8Ex; + PCD_PROTOCOL_GET_EX_16 Get16Ex; + PCD_PROTOCOL_GET_EX_32 Get32Ex; + PCD_PROTOCOL_GET_EX_64 Get64Ex; + PCD_PROTOCOL_GET_EX_POINTER GetPtrEx; + PCD_PROTOCOL_GET_EX_BOOLEAN GetBoolEx; + PCD_PROTOCOL_GET_EX_SIZE GetSizeEx; + + PCD_PROTOCOL_SET8 Set8; + PCD_PROTOCOL_SET16 Set16; + PCD_PROTOCOL_SET32 Set32; + PCD_PROTOCOL_SET64 Set64; + PCD_PROTOCOL_SET_POINTER SetPtr; + PCD_PROTOCOL_SET_BOOLEAN SetBool; + + PCD_PROTOCOL_SET_EX_8 Set8Ex; + PCD_PROTOCOL_SET_EX_16 Set16Ex; + PCD_PROTOCOL_SET_EX_32 Set32Ex; + PCD_PROTOCOL_SET_EX_64 Set64Ex; + PCD_PROTOCOL_SET_EX_POINTER SetPtrEx; + PCD_PROTOCOL_SET_EX_BOOLEAN SetBoolEx; + + PCD_PROTOCOL_CALLBACK_ONSET CallbackOnSet; + PCD_PROTOCOL_CANCEL_CALLBACK CancelCallback; + PCD_PROTOCOL_GET_NEXT_TOKEN GetNextToken; +} PCD_PROTOCOL; + +#endif diff --git a/MdePkg/Include/Protocol/PciHostBridgeResourceAllocation.h b/MdePkg/Include/Protocol/PciHostBridgeResourceAllocation.h new file mode 100644 index 0000000000..9d83c5aedb --- /dev/null +++ b/MdePkg/Include/Protocol/PciHostBridgeResourceAllocation.h @@ -0,0 +1,363 @@ +/** @file + This file declares Pci Host Bridge Resource Allocation Protocol + + Copyright (c) 2006, 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. + + Module Name: PciHostBridgeResourceAllocation.h + + @par Revision Reference: + This protocol is defined in Framework of EFI Pci Host Bridge Resource Allocation Protocol Spec + Version 0.9 + +**/ + +#ifndef _PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_H_ +#define _PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_H_ + +#define EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GUID \ + { 0xCF8034BE, 0x6768, 0x4d8b, {0xB7,0x39,0x7C,0xCE,0x68,0x3A,0x9F,0xBE }} + + +typedef struct _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL; + + +// +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES +// + +// If this bit is set, then the PCI Root Bridge does not +// support separate windows for Non-prefetchable and Prefetchable +// memory. A PCI bus driver needs to include requests for Prefetchable +// memory in the Non-prefetchable memory pool. +// +#define EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM 1 + +// +// If this bit is set, then the PCI Root Bridge supports +// 64 bit memory windows. If this bit is not set, +// the PCI bus driver needs to include requests for 64 bit +// memory address in the corresponding 32 bit memory pool. +// +#define EFI_PCI_HOST_BRIDGE_MEM64_DECODE 2 + + +// +// EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE +// +typedef enum { + EfiPciHostBridgeBeginEnumeration, + EfiPciHostBridgeBeginBusAllocation, + EfiPciHostBridgeEndBusAllocation, + EfiPciHostBridgeBeginResourceAllocation, + EfiPciHostBridgeAllocateResources, + EfiPciHostBridgeSetResources, + EfiPciHostBridgeFreeResources, + EfiPciHostBridgeEndResourceAllocation +} EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE; + +// +// EfiPciHostBridgeBeginEnumeration +// Reset the host bridge PCI apertures and internal data structures. +// PCI enumerator should issue this notification before starting fresh +// enumeration process. Enumeration cannot be restarted after sending +// any other notification such as EfiPciHostBridgeBeginBusAllocation. +// +// EfiPciHostBridgeBeginBusAllocation +// The bus allocation phase is about to begin. No specific action +// is required here. This notification can be used to perform any +// chipset specific programming. +// +// EfiPciHostBridgeEndBusAllocation +// The bus allocation and bus programming phase is complete. No specific +// action is required here. This notification can be used to perform any +// chipset specific programming. +// +// EfiPciHostBridgeBeginResourceAllocation +// The resource allocation phase is about to begin.No specific action is +// required here. This notification can be used to perform any chipset specific programming. +// +// EfiPciHostBridgeAllocateResources +// Allocate resources per previously submitted requests for all the PCI Root +// Bridges. These resource settings are returned on the next call to +// GetProposedResources(). +// +// EfiPciHostBridgeSetResources +// Program the Host Bridge hardware to decode previously allocated resources +// (proposed resources) for all the PCI Root Bridges. +// +// EfiPciHostBridgeFreeResources +// De-allocate previously allocated resources previously for all the PCI +// Root Bridges and reset the I/O and memory apertures to initial state. +// +// EfiPciHostBridgeEndResourceAllocation +// The resource allocation phase is completed. No specific action is required +// here. This notification can be used to perform any chipset specific programming. + + + +// +// EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE +// +typedef enum { + EfiPciBeforeChildBusEnumeration, + EfiPciBeforeResourceCollection +} EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE; + +// +// EfiPciBeforeChildBusEnumeration +// This notification is only applicable to PCI-PCI bridges and +// indicates that the PCI enumerator is about to begin enumerating +// the bus behind the PCI-PCI Bridge. This notification is sent after +// the primary bus number, the secondary bus number and the subordinate +// bus number registers in the PCI-PCI Bridge are programmed to valid +// (not necessary final) values +// +// EfiPciBeforeResourceCollection +// This notification is sent before the PCI enumerator probes BAR registers +// for every valid PCI function. +// + + +/** + Enter a certain phase of the PCI enumeration process + + @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance + @param Phase The phase during enumeration + + @retval EFI_SUCCESS Success + @retval EFI_OUT_OF_RESOURCES If SubmitResources ( ) could not allocate resources + @retval EFI_NOT_READY This phase cannot be entered at this time + @retval EFI_DEVICE_ERROR SetResources failed due to HW error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_NOTIFY_PHASE) ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase + ); + + +/** + Return the device handle of the next PCI root bridge that is associated with + this Host Bridge + + @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance + @param RootBridgeHandle Returns the device handle of the next PCI Root Bridge. + On input, it holds the RootBridgeHandle returned by the most + recent call to GetNextRootBridge().The handle for the first + PCI Root Bridge is returned if RootBridgeHandle is NULL on input + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER RootBridgeHandle is invalid + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_NEXT_ROOT_BRIDGE) ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN OUT EFI_HANDLE *RootBridgeHandle + ); + + +/** + Returns the attributes of a PCI Root Bridge. + + @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance + @param RootBridgeHandle The device handle of the PCI Root Bridge + that the caller is interested in + @param Attribute The pointer to attributes of the PCI Root Bridge + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER RootBridgeHandle is invalid + @retval EFI_INVALID_PARAMETER Attributes is NULL + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_ATTRIBUTES) ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT UINT64 *Attributes + ); + + +/** + This is the request from the PCI enumerator to set up + the specified PCI Root Bridge for bus enumeration process. + + @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance + @param RootBridgeHandle The PCI Root Bridge to be set up + @param Configuration Pointer to the pointer to the PCI bus resource descriptor + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER RootBridgeHandle is invalid + @retval EFI_DEVICE_ERROR Request failed due to hardware error + @retval EFI_OUT_OF_RESOURCES Request failed due to lack of resources + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_START_BUS_ENUMERATION) ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT VOID **Configuration + ); + + +/** + This function programs the PCI Root Bridge hardware so that + it decodes the specified PCI bus range + + @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance + @param RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed + @param Configuration The pointer to the PCI bus resource descriptor + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER RootBridgeHandle is invalid + @retval EFI_INVALID_PARAMETER Configuration is NULL + @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI resource descriptor + @retval EFI_INVALID_PARAMETER Configuration contains one or more memory or IO ACPI resource descriptor + @retval EFI_INVALID_PARAMETER Address Range Minimum or Address Range Length fields in Configuration + are invalid for this Root Bridge. + @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptor + @retval EFI_DEVICE_ERROR Request failed due to hardware error + @retval EFI_OUT_OF_RESOURCES Request failed due to lack of resources + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SET_BUS_NUMBERS) ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN VOID *Configuration + ); + + +/** + Submits the I/O and memory resource requirements for the specified PCI Root Bridge + + @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance + @param RootBridgeHandle The PCI Root Bridge whose I/O and memory resource requirements + are being submitted + @param Configuration The pointer to the PCI I/O and PCI memory resource descriptor + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER RootBridgeHandle is invalid + @retval EFI_INVALID_PARAMETER Configuration is NULL + @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI resource descriptor + @retval EFI_INVALID_PARAMETER Configuration includes a resource descriptor of unsupported type + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SUBMIT_RESOURCES) ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN VOID *Configuration + ); + + +/** + This function returns the proposed resource settings for the specified + PCI Root Bridge + + @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance + @param RootBridgeHandle The PCI Root Bridge handle + @param Configuration The pointer to the pointer to the PCI I/O + and memory resource descriptor + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER RootBridgeHandle is invalid + @retval EFI_DEVICE_ERROR Request failed due to hardware error + @retval EFI_OUT_OF_RESOURCES Request failed due to lack of resources + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_PROPOSED_RESOURCES) ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + OUT VOID **Configuration + ); + + + +/** + This function is called for all the PCI controllers that the PCI + bus driver finds. Can be used to Preprogram the controller. + + @param This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance + @param RootBridgeHandle The PCI Root Bridge handle + @param PciBusAddress Address of the controller on the PCI bus + @param Phase The Phase during resource allocation + + @retval EFI_SUCCESS Success + @retval EFI_INVALID_PARAMETER RootBridgeHandle is invalid + @retval EFI_DEVICE_ERROR Device pre-initialization failed due to hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_PREPROCESS_CONTROLLER) ( + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This, + IN EFI_HANDLE RootBridgeHandle, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress, + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase + ); + +/** + @par Protocol Description: + Provides the basic interfaces to abstract a PCI host bridge resource allocation. + + @param NotifyPhase + The notification from the PCI bus enumerator that it is about to enter + a certain phase during the enumeration process. + + @param GetNextRootBridge + Retrieves the device handle for the next PCI root bridge that is produced by the + host bridge to which this instance of the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is attached. + + @param GetAllocAttributes + Retrieves the allocation-related attributes of a PCI root bridge. + + @param StartBusEnumeration + Sets up a PCI root bridge for bus enumeration. + + @param SetBusNumbers + Sets up the PCI root bridge so that it decodes a specific range of bus numbers. + + @param SubmitResources + Submits the resource requirements for the specified PCI root bridge. + + @param GetProposedResources + Returns the proposed resource assignment for the specified PCI root bridges. + + @param PreprocessController + Provides hooks from the PCI bus driver to every PCI controller + (device/function) at various stages of the PCI enumeration process that + allow the host bridge driver to preinitialize individual PCI controllers + before enumeration. + +**/ +struct _EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL { + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_NOTIFY_PHASE NotifyPhase; + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_NEXT_ROOT_BRIDGE GetNextRootBridge; + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_ATTRIBUTES GetAllocAttributes; + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_START_BUS_ENUMERATION StartBusEnumeration; + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SET_BUS_NUMBERS SetBusNumbers; + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_SUBMIT_RESOURCES SubmitResources; + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_GET_PROPOSED_RESOURCES GetProposedResources; + EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL_PREPROCESS_CONTROLLER PreprocessController; +}; + +extern EFI_GUID gEfiPciHostBridgeResourceAllocationProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/PciHotPlugInit.h b/MdePkg/Include/Protocol/PciHotPlugInit.h new file mode 100644 index 0000000000..b4b5a3d4b9 --- /dev/null +++ b/MdePkg/Include/Protocol/PciHotPlugInit.h @@ -0,0 +1,185 @@ +/** @file + This file declares EFI PCI Hot Plug Init Protocol + + Copyright (c) 2006, 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. + + Module Name: PciHotPlugInit.h + + @par Revision Reference: + This protocol is defined in Framework of EFI Hot Plug Pci Initialization Protocol Spec + Version 0.9 + +**/ + +#ifndef _EFI_PCI_HOT_PLUG_INIT_H +#define _EFI_PCI_HOT_PLUG_INIT_H + +// +// Global ID for the PCI Hot Plug Protocol +// +#define EFI_PCI_HOT_PLUG_INIT_PROTOCOL_GUID \ + { 0xaa0e8bc1, 0xdabc, 0x46b0, {0xa8, 0x44, 0x37, 0xb8, 0x16, 0x9b, 0x2b, 0xea } } + + +typedef struct _EFI_PCI_HOT_PLUG_INIT_PROTOCOL EFI_PCI_HOT_PLUG_INIT_PROTOCOL; + +#define EFI_HPC_STATE_INITIALIZED 0x01 +#define EFI_HPC_STATE_ENABLED 0x02 + +typedef UINT16 EFI_HPC_STATE; + + +typedef struct{ + EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath; + EFI_DEVICE_PATH_PROTOCOL *HpbDevicePath; +} EFI_HPC_LOCATION; + + +typedef enum{ + EfiPaddingPciBus, + EfiPaddingPciRootBridge +} EFI_HPC_PADDING_ATTRIBUTES; + +/** + Returns a list of root Hot Plug Controllers (HPCs) that require initialization + during the boot process. + + @param This Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL instance. + + @param HpcCount The number of root HPCs that were returned. + + @param HpcList The list of root HPCs. HpcCount defines the number of + elements in this list. + + @retval EFI_SUCCESS HpcList was returned. + + @retval EFI_OUT_OF_RESOURCES HpcList was not returned due to insufficient resources. + + @retval EFI_INVALID_PARAMETER HpcCount is NULL or HpcList is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_ROOT_HPC_LIST) ( + IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This, + OUT UINTN *HpcCount, + OUT EFI_HPC_LOCATION **HpcList +); + +/** + Initializes one root Hot Plug Controller (HPC). This process may causes + initialization of its subordinate buses. + + @param This Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL instance. + + @param HpcDevicePath The device path to the HPC that is being initialized. + + @param HpcPciAddress The address of the HPC function on the PCI bus. + + @param Event The event that should be signaled when the HPC initialization + is complete. + + @param HpcState The state of the HPC hardware. + + @retval EFI_SUCCESS If Event is NULL, the specific HPC was successfully + initialized. If Event is not NULL, Event will be signaled at a later time + when initialization is complete. + + @retval EFI_UNSUPPORTED This instance of EFI_PCI_HOT_PLUG_INIT_PROTOCOL + does not support the specified HPC. + + @retval EFI_OUT_OF_RESOURCES Initialization failed due to insufficient + resources. + + @retval EFI_INVALID_PARAMETER HpcState is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INITIALIZE_ROOT_HPC) ( + IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + IN UINT64 HpcPciAddress, + IN EFI_EVENT Event, OPTIONAL + OUT EFI_HPC_STATE *HpcState +); + +/** + Returns the resource padding that is required by the PCI bus that is controlled + by the specified Hot Plug Controller (HPC). + + @param This Pointer to the EFI_PCI_HOT_PLUG_INIT_PROTOCOL instance. + + @param HpcDevicePath The device path to the HPC. + + @param HpcPciAddress The address of the HPC function on the PCI bus. + + @param HpcState The state of the HPC hardware. + + @param Padding The amount of resource padding that is required by the + PCI bus under the control of the specified HPC. + + @param Attributes Describes how padding is accounted for. The padding + is returned in the form of ACPI 2.0 resource descriptors. + + @retval EFI_SUCCESS The resource padding was successfully returned. + + @retval EFI_UNSUPPORTED This instance of the EFI_PCI_HOT_PLUG_INIT_PROTOCOL + does not support the specified HPC. + + @retval EFI_NOT_READY This function was called before HPC initialization is complete. + + @retval EFI_INVALID_PARAMETER HpcState or Padding or Attributes is NULL. + + @retval EFI_OUT_OF_RESOURCES ACPI 2.0 resource descriptors for Padding + cannot be allocated due to insufficient resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_PCI_HOT_PLUG_PADDING) ( + IN EFI_PCI_HOT_PLUG_INIT_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *HpcDevicePath, + IN UINT64 HpcPciAddress, + OUT EFI_HPC_STATE *HpcState, + OUT VOID **Padding, + OUT EFI_HPC_PADDING_ATTRIBUTES *Attributes +); + + +// +// Prototypes for the PCI Hot Plug Init Protocol +// + +/** + @par Protocol Description: + This protocol provides the necessary functionality to initialize the + Hot Plug Controllers (HPCs) and the buses that they control. This protocol + also provides information regarding resource padding. + + @param GetRootHpcList + Returns a list of root HPCs and the buses that they control. + + @param InitializeRootHpc + Initializes the specified root HPC. + + @param GetResourcePadding + Returns the resource padding that is required by the HPC. + +**/ +struct _EFI_PCI_HOT_PLUG_INIT_PROTOCOL { + EFI_GET_ROOT_HPC_LIST GetRootHpcList; + EFI_INITIALIZE_ROOT_HPC InitializeRootHpc; + EFI_GET_PCI_HOT_PLUG_PADDING GetResourcePadding; +}; + +extern EFI_GUID gEfiPciHotPlugInitProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/PciIo.h b/MdePkg/Include/Protocol/PciIo.h new file mode 100644 index 0000000000..18494b3394 --- /dev/null +++ b/MdePkg/Include/Protocol/PciIo.h @@ -0,0 +1,503 @@ +/** @file + EFI PCI I/O Protocol + + Copyright (c) 2006, 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. + + Module Name: PciIo.h + +**/ + +#ifndef __PCI_IO_H__ +#define __PCI_IO_H__ + +// +// Global ID for the PCI I/O Protocol +// +#define EFI_PCI_IO_PROTOCOL_GUID \ + { \ + 0x4cf5b200, 0x68b8, 0x4ca5, {0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a } \ + } + +typedef struct _EFI_PCI_IO_PROTOCOL EFI_PCI_IO_PROTOCOL; + +// +// Prototypes for the PCI I/O Protocol +// +typedef enum { + EfiPciIoWidthUint8 = 0, + EfiPciIoWidthUint16, + EfiPciIoWidthUint32, + EfiPciIoWidthUint64, + EfiPciIoWidthFifoUint8, + EfiPciIoWidthFifoUint16, + EfiPciIoWidthFifoUint32, + EfiPciIoWidthFifoUint64, + EfiPciIoWidthFillUint8, + EfiPciIoWidthFillUint16, + EfiPciIoWidthFillUint32, + EfiPciIoWidthFillUint64, + EfiPciIoWidthMaximum +} EFI_PCI_IO_PROTOCOL_WIDTH; + +// +// Complete PCI address generater +// +#define EFI_PCI_IO_PASS_THROUGH_BAR 0xff // Special BAR that passes a memory or I/O cycle through unchanged +#define EFI_PCI_IO_ATTRIBUTE_MASK 0x077f // All the following I/O and Memory cycles +#define EFI_PCI_IO_ATTRIBUTE_ISA_MOTHERBOARD_IO 0x0001 // I/O cycles 0x0000-0x00FF (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO 0x0002 // I/O cycles 0x0100-0x03FF or greater (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO 0x0004 // I/O cycles 0x3C6, 0x3C8, 0x3C9 (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY 0x0008 // MEM cycles 0xA0000-0xBFFFF (24 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO 0x0010 // I/O cycles 0x3B0-0x3BB and 0x3C0-0x3DF (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_IDE_PRIMARY_IO 0x0020 // I/O cycles 0x1F0-0x1F7, 0x3F6, 0x3F7 (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_IDE_SECONDARY_IO 0x0040 // I/O cycles 0x170-0x177, 0x376, 0x377 (10 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_WRITE_COMBINE 0x0080 // Map a memory range so write are combined +#define EFI_PCI_IO_ATTRIBUTE_IO 0x0100 // Enable the I/O decode bit in the PCI Config Header +#define EFI_PCI_IO_ATTRIBUTE_MEMORY 0x0200 // Enable the Memory decode bit in the PCI Config Header +#define EFI_PCI_IO_ATTRIBUTE_BUS_MASTER 0x0400 // Enable the DMA bit in the PCI Config Header +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_CACHED 0x0800 // Map a memory range so all r/w accesses are cached +#define EFI_PCI_IO_ATTRIBUTE_MEMORY_DISABLE 0x1000 // Disable a memory range +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_DEVICE 0x2000 // Clear for an add-in PCI Device +#define EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM 0x4000 // Clear for a physical PCI Option ROM accessed through ROM BAR +#define EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE 0x8000 // Clear for PCI controllers that can not genrate a DAC +#define EFI_PCI_IO_ATTRIBUTE_ISA_IO_16 0x10000 // I/O cycles 0x0100-0x03FF or greater (16 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO_16 0x20000 // I/O cycles 0x3C6, 0x3C8, 0x3C9 (16 bit decode) +#define EFI_PCI_IO_ATTRIBUTE_VGA_IO_16 0x30000 // I/O cycles 0x3B0-0x3BB and 0x3C0-0x3DF (16 bit decode) + +#define EFI_PCI_DEVICE_ENABLE (EFI_PCI_IO_ATTRIBUTE_IO | EFI_PCI_IO_ATTRIBUTE_MEMORY | EFI_PCI_IO_ATTRIBUTE_BUS_MASTER) +#define EFI_VGA_DEVICE_ENABLE (EFI_PCI_IO_ATTRIBUTE_VGA_PALETTE_IO | EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY | EFI_PCI_IO_ATTRIBUTE_VGA_IO | EFI_PCI_IO_ATTRIBUTE_IO) + +// +// ******************************************************* +// EFI_PCI_IO_PROTOCOL_OPERATION +// ******************************************************* +// +typedef enum { + EfiPciIoOperationBusMasterRead, + EfiPciIoOperationBusMasterWrite, + EfiPciIoOperationBusMasterCommonBuffer, + EfiPciIoOperationMaximum +} EFI_PCI_IO_PROTOCOL_OPERATION; + +// +// ******************************************************* +// EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION +// ******************************************************* +// +typedef enum { + EfiPciIoAttributeOperationGet, + EfiPciIoAttributeOperationSet, + EfiPciIoAttributeOperationEnable, + EfiPciIoAttributeOperationDisable, + EfiPciIoAttributeOperationSupported, + EfiPciIoAttributeOperationMaximum +} EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION; + +/** + Reads from the memory space of a PCI controller. Returns when either the polling exit criteria is + satisfied or after a defined duration. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Width Signifies the width of the memory or I/O operations. + @param BarIndex The BAR index of the standard PCI Configuration header to use as the + base address for the memory operation to perform. + @param Offset The offset within the selected BAR to start the memory operation. + @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_UNSUPPORTED BarIndex not valid for this PCI controller. + @retval EFI_UNSUPPORTED Offset is not valid for the BarIndex of this PCI controller. + @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_IO_PROTOCOL_POLL_IO_MEM) ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINT64 Mask, + IN UINT64 Value, + IN UINT64 Delay, + OUT UINT64 *Result + ); + +/** + Enable a PCI driver to access PCI controller registers in the PCI memory or I/O space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Width Signifies the width of the memory or I/O operations. + @param BarIndex The BAR index of the standard PCI Configuration header to use as the + base address for the memory or I/O operation to perform. + @param Offset The offset within the selected BAR to start the memory or I/O operation. + @param Count The number of memory or I/O 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 controller. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not + valid for the PCI BAR specified by BarIndex. + @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_IO_PROTOCOL_IO_MEM) ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 BarIndex, + IN UINT64 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + EFI_PCI_IO_PROTOCOL_IO_MEM Read; + EFI_PCI_IO_PROTOCOL_IO_MEM Write; +} EFI_PCI_IO_PROTOCOL_ACCESS; + +/** + Enable a PCI driver to access PCI controller registers in PCI configuration space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Width Signifies the width of the memory operations. + @param Offset The offset within the PCI configuration space for the PCI controller. + @param Count The number of PCI configuration 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 controller. + @retval EFI_UNSUPPORTED The address range specified by Offset, Width, and Count is not + valid for the PCI configuration header of the PCI controller. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Buffer is NULL or Width is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_CONFIG) ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT32 Offset, + IN UINTN Count, + IN OUT VOID *Buffer + ); + +typedef struct { + EFI_PCI_IO_PROTOCOL_CONFIG Read; + EFI_PCI_IO_PROTOCOL_CONFIG Write; +} EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS; + +/** + Enables a PCI driver to copy one region of PCI memory space to another region of PCI + memory space. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Width Signifies the width of the memory operations. + @param DestBarIndex The BAR index in the standard PCI Configuration header to use as the + base address for the memory operation to perform. + @param DestOffset The destination offset within the BAR specified by DestBarIndex to + start the memory writes for the copy operation. + @param SrcBarIndex The BAR index in the standard PCI Configuration header to use as the + base address for the memory operation to perform. + @param SrcOffset The source offset within the BAR specified by SrcBarIndex to start + the memory reads for the copy operation. + @param Count The number of memory operations to perform. Bytes moved is Width + size * Count, starting at DestOffset and SrcOffset. + + @retval EFI_SUCCESS The data was copied from one memory region to another memory region. + @retval EFI_UNSUPPORTED DestBarIndex not valid for this PCI controller. + @retval EFI_UNSUPPORTED SrcBarIndex not valid for this PCI controller. + @retval EFI_UNSUPPORTED The address range specified by DestOffset, Width, and Count + is not valid for the PCI BAR specified by DestBarIndex. + @retval EFI_UNSUPPORTED The address range specified by SrcOffset, Width, and Count is + not valid for the PCI BAR specified by SrcBarIndex. + @retval EFI_INVALID_PARAMETER Width is invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_COPY_MEM) ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_WIDTH Width, + IN UINT8 DestBarIndex, + IN UINT64 DestOffset, + IN UINT8 SrcBarIndex, + IN UINT64 SrcOffset, + IN UINTN Count + ); + +/** + Provides the PCI controller¨Cspecific addresses needed to access system memory. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @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_IO_PROTOCOL_MAP) ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_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_IO_PROTOCOL instance. + @param Mapping The mapping value returned from Map(). + + @retval EFI_SUCCESS The range was unmapped. + @retval EFI_DEVICE_ERROR The data was not committed to the target system memory. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_UNMAP) ( + IN EFI_PCI_IO_PROTOCOL *This, + IN VOID *Mapping + ); + +/** + Allocates pages that are suitable for an EfiPciIoOperationBusMasterCommonBuffer + mapping. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @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_IO_PROTOCOL_ALLOCATE_BUFFER) ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + OUT VOID **HostAddress, + IN UINT64 Attributes + ); + +/** + Frees memory that was allocated with AllocateBuffer(). + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @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_IO_PROTOCOL_FREE_BUFFER) ( + IN EFI_PCI_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_IO_PROTOCOL instance. + + @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_IO_PROTOCOL_FLUSH) ( + IN EFI_PCI_IO_PROTOCOL *This + ); + +/** + Retrieves this PCI controller¡¯s current PCI bus number, device number, and function number. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param SegmentNumber The PCI controller¡¯s current PCI segment number. + @param BusNumber The PCI controller¡¯s current PCI bus number. + @param DeviceNumber The PCI controller¡¯s current PCI device number. + @param FunctionNumber The PCI controller¡¯s current PCI function number. + + @retval EFI_SUCCESS The PCI controller location was returned. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_LOCATION) ( + IN EFI_PCI_IO_PROTOCOL *This, + OUT UINTN *SegmentNumber, + OUT UINTN *BusNumber, + OUT UINTN *DeviceNumber, + OUT UINTN *FunctionNumber + ); + +/** + Performs an operation on the attributes that this PCI controller supports. The operations include + getting the set of supported attributes, retrieving the current attributes, setting the current + attributes, enabling attributes, and disabling attributes. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Operation The operation to perform on the attributes for this PCI controller. + @param Attributes The mask of attributes that are used for Set, Enable, and Disable + operations. + @param Result A pointer to the result mask of attributes that are returned for the Get + and Supported operations. + + @retval EFI_SUCCESS The operation on the PCI controller's attributes was completed. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_UNSUPPORTED one or more of the bits set in + Attributes are not supported by this PCI controller or one of + its parent bridges when Operation is Set, Enable or Disable. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_ATTRIBUTES) ( + IN EFI_PCI_IO_PROTOCOL *This, + IN EFI_PCI_IO_PROTOCOL_ATTRIBUTE_OPERATION Operation, + IN UINT64 Attributes, + OUT UINT64 *Result OPTIONAL + ); + +/** + Gets the attributes that this PCI controller supports setting on a BAR using + SetBarAttributes(), and retrieves the list of resource descriptors for a BAR. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param BarIndex The BAR index of the standard PCI Configuration header to use as the + base address for resource range. The legal range for this field is 0..5. + @param Supports A pointer to the mask of attributes that this PCI controller supports + setting for this BAR with SetBarAttributes(). + @param Resources A pointer to the ACPI 2.0 resource descriptors that describe the current + configuration of this BAR of the PCI controller. + + @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI + controller supports are returned in Supports. If Resources + is not NULL, then the ACPI 2.0 resource descriptors that the PCI + controller is currently using are returned in Resources. + @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate + Resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES) ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT8 BarIndex, + OUT UINT64 *Supports, OPTIONAL + OUT VOID **Resources OPTIONAL + ); + +/** + Sets the attributes for a range of a BAR on a PCI controller. + + @param This A pointer to the EFI_PCI_IO_PROTOCOL instance. + @param Attributes The mask of attributes to set for the resource range specified by + BarIndex, Offset, and Length. + @param BarIndex The BAR index of the standard PCI Configuration header to use as the + base address for resource range. The legal range for this field is 0..5. + @param Offset A pointer to the BAR relative base address of the resource range to be + modified by the attributes specified by Attributes. + @param Length 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 BarIndex, Offset, and Length were + set on the PCI controller, and the actual resource range is returned + in Offset and Length. + @retval EFI_INVALID_PARAMETER Offset or Length is NULL. + @retval EFI_UNSUPPORTED BarIndex not valid for this PCI controller. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the attributes on the + resource range specified by BarIndex, Offset, and + Length. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES) ( + IN EFI_PCI_IO_PROTOCOL *This, + IN UINT64 Attributes, + IN UINT8 BarIndex, + IN OUT UINT64 *Offset, + IN OUT UINT64 *Length + ); + +// +// Interface structure for the PCI I/O Protocol +// +struct _EFI_PCI_IO_PROTOCOL { + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollMem; + EFI_PCI_IO_PROTOCOL_POLL_IO_MEM PollIo; + EFI_PCI_IO_PROTOCOL_ACCESS Mem; + EFI_PCI_IO_PROTOCOL_ACCESS Io; + EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS Pci; + EFI_PCI_IO_PROTOCOL_COPY_MEM CopyMem; + EFI_PCI_IO_PROTOCOL_MAP Map; + EFI_PCI_IO_PROTOCOL_UNMAP Unmap; + EFI_PCI_IO_PROTOCOL_ALLOCATE_BUFFER AllocateBuffer; + EFI_PCI_IO_PROTOCOL_FREE_BUFFER FreeBuffer; + EFI_PCI_IO_PROTOCOL_FLUSH Flush; + EFI_PCI_IO_PROTOCOL_GET_LOCATION GetLocation; + EFI_PCI_IO_PROTOCOL_ATTRIBUTES Attributes; + EFI_PCI_IO_PROTOCOL_GET_BAR_ATTRIBUTES GetBarAttributes; + EFI_PCI_IO_PROTOCOL_SET_BAR_ATTRIBUTES SetBarAttributes; + UINT64 RomSize; + VOID *RomImage; +}; + +extern EFI_GUID gEfiPciIoProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/PciPlatform.h b/MdePkg/Include/Protocol/PciPlatform.h new file mode 100644 index 0000000000..5b0add1ea7 --- /dev/null +++ b/MdePkg/Include/Protocol/PciPlatform.h @@ -0,0 +1,207 @@ +/** @file + This file declares PlatfromOpRom protocols. + + Copyright (c) 2006, 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. + + Module Name: PciPlatform.h + + @par Revision Reference: + This protocol is defined in PCI Platform Support Specification + Version 0.9 + +**/ + +#ifndef _PCI_PLATFORM_H_ +#define _PCI_PLATFORM_H_ + +// +// Protocol for GUID. +// + +#define EFI_PCI_PLATFORM_PROTOCOL_GUID \ +{ 0x7d75280, 0x27d4, 0x4d69, {0x90, 0xd0, 0x56, 0x43, 0xe2, 0x38, 0xb3, 0x41} } + +typedef struct _EFI_PCI_PLATFORM_PROTOCOL EFI_PCI_PLATFORM_PROTOCOL; + +typedef UINT32 EFI_PCI_PLATFORM_POLICY; + + +#define EFI_RESERVE_NONE_IO_ALIAS 0x0000 +#define EFI_RESERVE_ISA_IO_ALIAS 0x0001 +#define EFI_RESERVE_ISA_IO_NO_ALIAS 0x0002 +#define EFI_RESERVE_VGA_IO_ALIAS 0x0004 +#define EFI_RESERVE_VGA_IO_NO_ALIAS 0x0008 + + +typedef enum { + ChipsetEntry, + ChipsetExit, + MaximumChipsetPhase +} EFI_PCI_CHIPSET_EXECUTION_PHASE; + + +/** + The PlatformNotify() function can be used to notify the platform driver so that + it can perform platform-specific actions. No specific actions are required. + Eight notification points are defined at this time. More synchronization points + may be added as required in the future. The PCI bus driver calls the platform driver + twice for every Phase-once before the PCI Host Bridge Resource Allocation Protocol + driver is notified, and once after the PCI Host Bridge Resource Allocation Protocol + driver has been notified. + This member function may not perform any error checking on the input parameters. It + also does not return any error codes. If this member function detects any error condition, + it needs to handle those errors on its own because there is no way to surface any + errors to the caller. + + @param This Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance. + @param HostBridge The handle of the host bridge controller. + @param Phase The phase of the PCI bus enumeration. + @param ChipsetPhase Defines the execution phase of the PCI chipset driver. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_PLATFORM_PHASE_NOTIFY) ( + IN EFI_PCI_PLATFORM_PROTOCOL *This, + IN EFI_HANDLE HostBridge, + IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase, + IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase +) +; + + +/** + The PlatformPrepController() function can be used to notify the platform driver so that + it can perform platform-specific actions. No specific actions are required. + Several notification points are defined at this time. More synchronization points may be + added as required in the future. The PCI bus driver calls the platform driver twice for + every PCI controller-once before the PCI Host Bridge Resource Allocation Protocol driver + is notified, and once after the PCI Host Bridge Resource Allocation Protocol driver has + been notified. + This member function may not perform any error checking on the input parameters. It also + does not return any error codes. If this member function detects any error condition, it + needs to handle those errors on its own because there is no way to surface any errors to + the caller. + + @param This Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance. + @param HostBridge The associated PCI host bridge handle. + @param RootBridge The associated PCI root bridge handle. + @param PciAddress The address of the PCI device on the PCI bus. + @param Phase The phase of the PCI controller enumeration. + @param ChipsetPhase Defines the execution phase of the PCI chipset driver. + + @retval EFI_SUCCESS The function completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_PLATFORM_PREPROCESS_CONTROLLER) ( + IN EFI_PCI_PLATFORM_PROTOCOL *This, + IN EFI_HANDLE HostBridge, + IN EFI_HANDLE RootBridge, + IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress, + IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase, + IN EFI_PCI_CHIPSET_EXECUTION_PHASE ChipsetPhase +) +; + + +/** + The GetPlatformPolicy() function retrieves the platform policy regarding PCI + enumeration. The PCI bus driver and the PCI Host Bridge Resource Allocation Protocol + driver can call this member function to retrieve the policy. + + @param This Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance. + @param PciPolicy The platform policy with respect to VGA and ISA aliasing. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_INVALID_PARAMETER PciPolicy is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_PLATFORM_GET_PLATFORM_POLICY) ( + IN EFI_PCI_PLATFORM_PROTOCOL *This, + OUT EFI_PCI_PLATFORM_POLICY *PciPolicy +) +; + + +/** + The GetPciRom() function gets the PCI device's option ROM from a platform-specific location. + The option ROM will be loaded into memory. This member function is used to return an image + that is packaged as a PCI 2.2 option ROM. The image may contain both legacy and EFI option + ROMs. See the EFI 1.10 Specification for details. This member function can be used to return + option ROM images for embedded controllers. Option ROMs for embedded controllers are typically + stored in platform-specific storage, and this member function can retrieve it from that storage + and return it to the PCI bus driver. The PCI bus driver will call this member function before + scanning the ROM that is attached to any controller, which allows a platform to specify a ROM + image that is different from the ROM image on a PCI card. + + @param This Pointer to the EFI_PCI_PLATFORM_PROTOCOL instance. + @param PciHandle The handle of the PCI device. + @param RomImage If the call succeeds, the pointer to the pointer to the option ROM image. + Otherwise, this field is undefined. The memory for RomImage is allocated + by EFI_PCI_PLATFORM_PROTOCOL.GetPciRom() using the EFI Boot Service AllocatePool(). + It is the caller's responsibility to free the memory using the EFI Boot Service + FreePool(), when the caller is done with the option ROM. + @param RomSize If the call succeeds, a pointer to the size of the option ROM size. Otherwise, + this field is undefined. + + @retval EFI_SUCCESS The option ROM was available for this device and loaded into memory. + @retval EFI_NOT_FOUND No option ROM was available for this device. + @retval EFI_OUT_OF_RESOURCES No memory was available to load the option ROM. + @retval EFI_DEVICE_ERROR An error occurred in getting the option ROM. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PCI_PLATFORM_GET_PCI_ROM) ( + IN EFI_PCI_PLATFORM_PROTOCOL *This, + IN EFI_HANDLE PciHandle, + OUT VOID **RomImage, + OUT UINTN *RomSize +) +; + +/** + @par Protocol Description: + This protocol provides the interface between the PCI bus driver/PCI Host + Bridge Resource Allocation driver and a platform-specific driver to describe + the unique features of a platform. + + @param PlatformNotify + The notification from the PCI bus enumerator to the platform that it is + about to enter a certain phase during the enumeration process. + + @param PlatformPrepController + The notification from the PCI bus enumerator to the platform for each PCI + controller at several predefined points during PCI controller initialization. + + @param GetPlatformPolicy + Retrieves the platform policy regarding enumeration. + + @param GetPciRom + Gets the PCI device¡¯s option ROM from a platform-specific location. + +**/ +struct _EFI_PCI_PLATFORM_PROTOCOL { + EFI_PCI_PLATFORM_PHASE_NOTIFY PhaseNotify; + EFI_PCI_PLATFORM_PREPROCESS_CONTROLLER PlatformPrepController; + EFI_PCI_PLATFORM_GET_PLATFORM_POLICY GetPlatformPolicy; + EFI_PCI_PLATFORM_GET_PCI_ROM GetPciRom; +}; + +extern EFI_GUID gEfiPciPlatformProtocolGuid; + + +#endif diff --git a/MdePkg/Include/Protocol/PciRootBridgeIo.h b/MdePkg/Include/Protocol/PciRootBridgeIo.h new file mode 100644 index 0000000000..06912da283 --- /dev/null +++ b/MdePkg/Include/Protocol/PciRootBridgeIo.h @@ -0,0 +1,384 @@ +/** @file + PCI Root Bridge I/O protocol as defined in the EFI 1.1 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, 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. + + Module Name: PciRootBridgeIo.h + +**/ + +#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; + +typedef enum { + EfiPciWidthUint8, + EfiPciWidthUint16, + EfiPciWidthUint32, + EfiPciWidthUint64, + EfiPciWidthFifoUint8, + EfiPciWidthFifoUint16, + EfiPciWidthFifoUint32, + EfiPciWidthFifoUint64, + EfiPciWidthFillUint8, + EfiPciWidthFillUint16, + EfiPciWidthFillUint32, + EfiPciWidthFillUint64, + EfiPciWidthMaximum +} EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH; + +typedef enum { + EfiPciOperationBusMasterRead, + EfiPciOperationBusMasterWrite, + EfiPciOperationBusMasterCommonBuffer, + EfiPciOperationBusMasterRead64, + EfiPciOperationBusMasterWrite64, + 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_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) + +#define EFI_PCI_ADDRESS(bus, dev, func, reg) \ + ((UINT64) ((((UINTN) bus) << 24) + (((UINTN) dev) << 16) + (((UINTN) func) << 8) + ((UINTN) reg))) + +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 { + EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM Read; + 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¨Cspecific 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, + IN VOID **Resources + ); + +struct _EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL { + 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; + UINT32 SegmentNumber; +}; + +extern EFI_GUID gEfiPciRootBridgeIoProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/PlatformDriverOverride.h b/MdePkg/Include/Protocol/PlatformDriverOverride.h new file mode 100644 index 0000000000..1015c50d3e --- /dev/null +++ b/MdePkg/Include/Protocol/PlatformDriverOverride.h @@ -0,0 +1,135 @@ +/** @file + Platform Driver Override protocol as defined in the EFI 1.1 specification. + + Copyright (c) 2006, 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. + + Module Name: PlatformDriverOverride.h + +**/ + +#ifndef __EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_H__ +#define __EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_H__ + +// +// Global ID for the Platform Driver Override Protocol +// +#define EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL_GUID \ + { \ + 0x6b30c738, 0xa391, 0x11d4, {0x9a, 0x3b, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL; + +// +// Prototypes for the Platform Driver Override Protocol +// + +/** + Retrieves the image handle of the platform override driver for a controller in the system. + + @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_ + PROTOCOL instance. + @param ControllerHandle The device handle of the controller to check if a driver override + exists. + @param DriverImageHandle On input, a pointer to the previous driver image handle returned + by GetDriver(). On output, a pointer to the next driver + image handle. + + @retval EFI_SUCCESS The driver override for ControllerHandle was returned in + DriverImageHandle. + @retval EFI_NOT_FOUND A driver override for ControllerHandle was not found. + @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not a valid handle. + @retval EFI_INVALID_PARAMETER DriverImageHandle is not a handle that was returned on a + previous call to GetDriver(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER) ( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_HANDLE *DriverImageHandle + ); + +/** + Retrieves the device path of the platform override driver for a controller in the system. + + @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_ + PROTOCOL instance. + @param ControllerHandle The device handle of the controller to check if a driver override + exists. + @param DriverImageHandle On input, a pointer to the previous driver image handle returned + by GetDriverPath(). On output, a pointer to the next driver + device path. + + @retval EFI_SUCCESS The driver override for ControllerHandle was returned in + DriverImageHandle. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_NOT_FOUND A driver override for ControllerHandle was not found. + @retval EFI_INVALID_PARAMETER The handle specified by ControllerHandle is not a valid handle. + @retval EFI_INVALID_PARAMETER DriverImagePath is not a device path that was returned on a + previous call to GetDriverPath(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER_PATH) ( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DriverImagePath + ); + +/** + Used to associate a driver image handle with a device path that was returned on a prior call to the + GetDriverPath() service. This driver image handle will then be available through the + GetDriver() service. + + @param This A pointer to the EFI_PLATFORM_DRIVER_OVERRIDE_ + PROTOCOL instance. + @param ControllerHandle The device handle of the controller. + @param DriverImagePath A pointer to the driver device path that was returned in a prior + call to GetDriverPath(). + @param DriverImageHandle The driver image handle that was returned by LoadImage() + when the driver specified by DriverImagePath was loaded + into memory. + + @retval EFI_SUCCESS The association between DriverImagePath and + DriverImageHandle was established for the controller specified + by ControllerHandle. + @retval EFI_UNSUPPORTED The operation is not supported. + @retval EFI_NOT_FOUND DriverImagePath is not a device path that was returned on a prior + call to GetDriverPath() for the controller specified by + ControllerHandle. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid device handle. + @retval EFI_INVALID_PARAMETER DriverImagePath is not a valid device path. + @retval EFI_INVALID_PARAMETER DriverImageHandle is not a valid image handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PLATFORM_DRIVER_OVERRIDE_DRIVER_LOADED) ( + IN EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL *This, + IN EFI_HANDLE ControllerHandle, + IN EFI_DEVICE_PATH_PROTOCOL *DriverImagePath, + IN EFI_HANDLE DriverImageHandle + ); + +// +// Interface structure for the Platform Driver Override Protocol +// +struct _EFI_PLATFORM_DRIVER_OVERRIDE_PROTOCOL { + EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER GetDriver; + EFI_PLATFORM_DRIVER_OVERRIDE_GET_DRIVER_PATH GetDriverPath; + EFI_PLATFORM_DRIVER_OVERRIDE_DRIVER_LOADED DriverLoaded; +}; + +extern EFI_GUID gEfiPlatformDriverOverrideProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/PxeBaseCode.h b/MdePkg/Include/Protocol/PxeBaseCode.h new file mode 100644 index 0000000000..14a6848255 --- /dev/null +++ b/MdePkg/Include/Protocol/PxeBaseCode.h @@ -0,0 +1,622 @@ +/** @file + EFI PXE Base Code Protocol definitions. + + Copyright (c) 2006, 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. + + Module Name: PxeBaseCode.h + +**/ +#ifndef __PXE_BASE_CODE_PROTOCOL_H__ +#define __PXE_BASE_CODE_PROTOCOL_H__ + +// +// PXE Base Code protocol +// +#define EFI_PXE_BASE_CODE_PROTOCOL_GUID \ + { \ + 0x03c4e603, 0xac28, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_PXE_BASE_CODE_PROTOCOL EFI_PXE_BASE_CODE_PROTOCOL; + +// +// Default IP TTL and ToS. +// +#define DEFAULT_TTL 16 +#define DEFAULT_ToS 0 + +// +// ICMP error format +// +typedef struct { + UINT8 Type; + UINT8 Code; + UINT16 Checksum; + union { + UINT32 reserved; + UINT32 Mtu; + UINT32 Pointer; + struct { + UINT16 Identifier; + UINT16 Sequence; + } Echo; + } u; + UINT8 Data[494]; +} EFI_PXE_BASE_CODE_ICMP_ERROR; + +// +// TFTP error format +// +typedef struct { + UINT8 ErrorCode; + CHAR8 ErrorString[127]; +} EFI_PXE_BASE_CODE_TFTP_ERROR; + +// +// IP Receive Filter definitions +// +#define EFI_PXE_BASE_CODE_MAX_IPCNT 8 + +typedef struct { + UINT8 Filters; + UINT8 IpCnt; + UINT16 reserved; + EFI_IP_ADDRESS IpList[EFI_PXE_BASE_CODE_MAX_IPCNT]; +} EFI_PXE_BASE_CODE_IP_FILTER; + +#define EFI_PXE_BASE_CODE_IP_FILTER_STATION_IP 0x0001 +#define EFI_PXE_BASE_CODE_IP_FILTER_BROADCAST 0x0002 +#define EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS 0x0004 +#define EFI_PXE_BASE_CODE_IP_FILTER_PROMISCUOUS_MULTICAST 0x0008 + +// +// ARP Cache definitions +// +typedef struct { + EFI_IP_ADDRESS IpAddr; + EFI_MAC_ADDRESS MacAddr; +} EFI_PXE_BASE_CODE_ARP_ENTRY; + +typedef struct { + EFI_IP_ADDRESS IpAddr; + EFI_IP_ADDRESS SubnetMask; + EFI_IP_ADDRESS GwAddr; +} EFI_PXE_BASE_CODE_ROUTE_ENTRY; + +// +// UDP definitions +// +typedef UINT16 EFI_PXE_BASE_CODE_UDP_PORT; + +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP 0x0001 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_PORT 0x0002 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP 0x0004 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_PORT 0x0008 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_USE_FILTER 0x0010 +#define EFI_PXE_BASE_CODE_UDP_OPFLAGS_MAY_FRAGMENT 0x0020 + +// +// Discover() definitions +// +#define EFI_PXE_BASE_CODE_BOOT_TYPE_BOOTSTRAP 0 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_MS_WINNT_RIS 1 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_INTEL_LCM 2 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_DOSUNDI 3 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_NEC_ESMPRO 4 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_IBM_WSoD 5 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_IBM_LCCM 6 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_CA_UNICENTER_TNG 7 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_HP_OPENVIEW 8 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_9 9 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_10 10 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_ALTIRIS_11 11 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_NOT_USED_12 12 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_INSTALL 13 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REDHAT_BOOT 14 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_REMBO 15 +#define EFI_PXE_BASE_CODE_BOOT_TYPE_BEOBOOT 16 +// +// 17 through 32767 are reserved +// 32768 through 65279 are for vendor use +// 65280 through 65534 are reserved +// +#define EFI_PXE_BASE_CODE_BOOT_TYPE_PXETEST 65535 + +#define EFI_PXE_BASE_CODE_BOOT_LAYER_MASK 0x7FFF +#define EFI_PXE_BASE_CODE_BOOT_LAYER_INITIAL 0x0000 + +// +// Discover() server list structure. +// +typedef struct { + UINT16 Type; + BOOLEAN AcceptAnyResponse; + UINT8 Reserved; + EFI_IP_ADDRESS IpAddr; +} EFI_PXE_BASE_CODE_SRVLIST; + +// +// Discover() information override structure. +// +typedef struct { + BOOLEAN UseMCast; + BOOLEAN UseBCast; + BOOLEAN UseUCast; + BOOLEAN MustUseList; + EFI_IP_ADDRESS ServerMCastIp; + UINT16 IpCnt; + EFI_PXE_BASE_CODE_SRVLIST SrvList[1]; +} EFI_PXE_BASE_CODE_DISCOVER_INFO; + +// +// Mtftp() definitions +// +typedef enum { + EFI_PXE_BASE_CODE_TFTP_FIRST, + EFI_PXE_BASE_CODE_TFTP_GET_FILE_SIZE, + EFI_PXE_BASE_CODE_TFTP_READ_FILE, + EFI_PXE_BASE_CODE_TFTP_WRITE_FILE, + EFI_PXE_BASE_CODE_TFTP_READ_DIRECTORY, + EFI_PXE_BASE_CODE_MTFTP_GET_FILE_SIZE, + EFI_PXE_BASE_CODE_MTFTP_READ_FILE, + EFI_PXE_BASE_CODE_MTFTP_READ_DIRECTORY, + EFI_PXE_BASE_CODE_MTFTP_LAST +} EFI_PXE_BASE_CODE_TFTP_OPCODE; + +typedef struct { + EFI_IP_ADDRESS MCastIp; + EFI_PXE_BASE_CODE_UDP_PORT CPort; + EFI_PXE_BASE_CODE_UDP_PORT SPort; + UINT16 ListenTimeout; + UINT16 TransmitTimeout; +} EFI_PXE_BASE_CODE_MTFTP_INFO; + +// +// PXE Base Code Mode structure +// +#define EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES 8 +#define EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES 8 + +typedef struct { + BOOLEAN Started; + BOOLEAN Ipv6Available; + BOOLEAN Ipv6Supported; + BOOLEAN UsingIpv6; + BOOLEAN BisSupported; + BOOLEAN BisDetected; + BOOLEAN AutoArp; + BOOLEAN SendGUID; + BOOLEAN DhcpDiscoverValid; + BOOLEAN DhcpAckReceived; + BOOLEAN ProxyOfferReceived; + BOOLEAN PxeDiscoverValid; + BOOLEAN PxeReplyReceived; + BOOLEAN PxeBisReplyReceived; + BOOLEAN IcmpErrorReceived; + BOOLEAN TftpErrorReceived; + BOOLEAN MakeCallbacks; + UINT8 TTL; + UINT8 ToS; + EFI_IP_ADDRESS StationIp; + EFI_IP_ADDRESS SubnetMask; + EFI_PXE_BASE_CODE_PACKET DhcpDiscover; + EFI_PXE_BASE_CODE_PACKET DhcpAck; + EFI_PXE_BASE_CODE_PACKET ProxyOffer; + EFI_PXE_BASE_CODE_PACKET PxeDiscover; + EFI_PXE_BASE_CODE_PACKET PxeReply; + EFI_PXE_BASE_CODE_PACKET PxeBisReply; + EFI_PXE_BASE_CODE_IP_FILTER IpFilter; + UINT32 ArpCacheEntries; + EFI_PXE_BASE_CODE_ARP_ENTRY ArpCache[EFI_PXE_BASE_CODE_MAX_ARP_ENTRIES]; + UINT32 RouteTableEntries; + EFI_PXE_BASE_CODE_ROUTE_ENTRY RouteTable[EFI_PXE_BASE_CODE_MAX_ROUTE_ENTRIES]; + EFI_PXE_BASE_CODE_ICMP_ERROR IcmpError; + EFI_PXE_BASE_CODE_TFTP_ERROR TftpError; +} EFI_PXE_BASE_CODE_MODE; + +// +// PXE Base Code Interface Function definitions +// + +/** + Enables the use of the PXE Base Code Protocol functions. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param UseIpv6 Specifies the type of IP addresses that are to be used during the session + that is being started. Set to TRUE for IPv6 addresses, and FALSE for + IPv4 addresses. + + @retval EFI_SUCCESS The PXE Base Code Protocol was started. + @retval EFI_DEVICE_ERROR The network device encountered an error during this oper + @retval EFI_UNSUPPORTED UseIpv6 is TRUE, but the Ipv6Supported field of the + EFI_PXE_BASE_CODE_MODE structure is FALSE. + @retval EFI_ALREADY_STARTED The PXE Base Code Protocol is already in the started state. + @retval EFI_INVALID_PARAMETER The This parameter is NULL or does not point to a valid + EFI_PXE_BASE_CODE_PROTOCOL structure. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough memory or other resources to start the + PXE Base Code Protocol. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_START) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN UseIpv6 + ); + +/** + Disables the use of the PXE Base Code Protocol functions. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + + @retval EFI_SUCCESS The PXE Base Code Protocol was stopped. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is already in the stopped state. + @retval EFI_INVALID_PARAMETER The This parameter is NULL or does not point to a valid + EFI_PXE_BASE_CODE_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_STOP) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This + ); + +/** + Attempts to complete a DHCPv4 D.O.R.A. (discover / offer / request / acknowledge) or DHCPv6 + S.A.R.R (solicit / advertise / request / reply) sequence. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param SortOffers TRUE if the offers received should be sorted. Set to FALSE to try the + offers in the order that they are received. + + @retval EFI_SUCCESS Valid DHCP has completed. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER The This parameter is NULL or does not point to a valid + EFI_PXE_BASE_CODE_PROTOCOL structure. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough memory to complete the DHCP Protocol. + @retval EFI_ABORTED The callback function aborted the DHCP Protocol. + @retval EFI_TIMEOUT The DHCP Protocol timed out. + @retval EFI_ICMP_ERROR An ICMP error packet was received during the DHCP session. + @retval EFI_NO_RESPONSE Valid PXE offer was not received. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_DHCP) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN SortOffers + ); + +/** + Attempts to complete the PXE Boot Server and/or boot image discovery sequence. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param Type The type of bootstrap to perform. + @param Layer Pointer to the boot server layer number to discover, which must be + PXE_BOOT_LAYER_INITIAL when a new server type is being + discovered. + @param UseBis TRUE if Boot Integrity Services are to be used. FALSE otherwise. + @param Info Pointer to a data structure that contains additional information on the + type of discovery operation that is to be performed. + + @retval EFI_SUCCESS The Discovery sequence has been completed. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough memory to complete Discovery. + @retval EFI_ABORTED The callback function aborted the Discovery sequence. + @retval EFI_TIMEOUT The Discovery sequence timed out. + @retval EFI_ICMP_ERROR An ICMP error packet was received during the PXE discovery + session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_DISCOVER) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 Type, + IN UINT16 *Layer, + IN BOOLEAN UseBis, + IN EFI_PXE_BASE_CODE_DISCOVER_INFO *Info OPTIONAL + ); + +/** + Used to perform TFTP and MTFTP services. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param Operation The type of operation to perform. + @param BufferPtr A pointer to the data buffer. + @param Overwrite Only used on write file operations. TRUE if a file on a remote server can + be overwritten. + @param BufferSize For get-file-size operations, *BufferSize returns the size of the + requested file. + @param BlockSize The requested block size to be used during a TFTP transfer. + @param ServerIp The TFTP / MTFTP server IP address. + @param Filename A Null-terminated ASCII string that specifies a directory name or a file + name. + @param Info Pointer to the MTFTP information. + @param DontUseBuffer Set to FALSE for normal TFTP and MTFTP read file operation. + + @retval EFI_SUCCESS The TFTP/MTFTP operation was completed. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + @retval EFI_BUFFER_TOO_SMALL The buffer is not large enough to complete the read operation. + @retval EFI_ABORTED The callback function aborted the TFTP/MTFTP operation. + @retval EFI_TIMEOUT The TFTP/MTFTP operation timed out. + @retval EFI_ICMP_ERROR An ICMP error packet was received during the MTFTP session. + @retval EFI_TFTP_ERROR A TFTP error packet was received during the MTFTP session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_MTFTP) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_TFTP_OPCODE Operation, + IN OUT VOID *BufferPtr OPTIONAL, + IN BOOLEAN Overwrite, + IN OUT UINT64 *BufferSize, + IN UINTN *BlockSize OPTIONAL, + IN EFI_IP_ADDRESS *ServerIp, + IN UINT8 *Filename OPTIONAL, + IN EFI_PXE_BASE_CODE_MTFTP_INFO *Info OPTIONAL, + IN BOOLEAN DontUseBuffer + ); + +/** + Writes a UDP packet to the network interface. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param OpFlags The UDP operation flags. + @param DestIp The destination IP address. + @param DestPort The destination UDP port number. + @param GatewayIp The gateway IP address. + @param SrcIp The source IP address. + @param SrcPort The source UDP port number. + @param HeaderSize An optional field which may be set to the length of a header at + HeaderPtr to be prefixed to the data at BufferPtr. + @param HeaderPtr If HeaderSize is not NULL, a pointer to a header to be prefixed to the + data at BufferPtr. + @param BufferSize A pointer to the size of the data at BufferPtr. + @param BufferPtr A pointer to the data to be written. + + @retval EFI_SUCCESS The UDP Write operation was completed. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_BAD_BUFFER_SIZE The buffer is too long to be transmitted. + @retval EFI_ABORTED The callback function aborted the UDP Write operation. + @retval EFI_TIMEOUT The UDP Write operation timed out. + @retval EFI_ICMP_ERROR An ICMP error packet was received during the UDP write session. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_UDP_WRITE) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 OpFlags, + IN EFI_IP_ADDRESS *DestIp, + IN EFI_PXE_BASE_CODE_UDP_PORT *DestPort, + IN EFI_IP_ADDRESS *GatewayIp, OPTIONAL + IN EFI_IP_ADDRESS *SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL + IN UINTN *HeaderSize, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN UINTN *BufferSize, + IN VOID *BufferPtr + ); + +/** + Reads a UDP packet from the network interface. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param OpFlags The UDP operation flags. + @param DestIp The destination IP address. + @param DestPort The destination UDP port number. + @param GatewayIp The gateway IP address. + @param SrcIp The source IP address. + @param SrcPort The source UDP port number. + @param HeaderSize An optional field which may be set to the length of a header at + HeaderPtr to be prefixed to the data at BufferPtr. + @param HeaderPtr If HeaderSize is not NULL, a pointer to a header to be prefixed to the + data at BufferPtr. + @param BufferSize A pointer to the size of the data at BufferPtr. + @param BufferPtr A pointer to the data to be read. + + @retval EFI_SUCCESS The UDP Write operation was completed. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + @retval EFI_BUFFER_TOO_SMALL The packet is larger than Buffer can hold. + @retval EFI_ABORTED The callback function aborted the UDP Read operation. + @retval EFI_TIMEOUT The UDP Read operation timed out. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_UDP_READ) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN UINT16 OpFlags, + IN OUT EFI_IP_ADDRESS *DestIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *DestPort, OPTIONAL + IN OUT EFI_IP_ADDRESS *SrcIp, OPTIONAL + IN OUT EFI_PXE_BASE_CODE_UDP_PORT *SrcPort, OPTIONAL + IN UINTN *HeaderSize, OPTIONAL + IN VOID *HeaderPtr, OPTIONAL + IN OUT UINTN *BufferSize, + IN VOID *BufferPtr + ); + +/** + Updates the IP receive filters of a network device and enables software filtering. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param NewFilter Pointer to the new set of IP receive filters. + + @retval EFI_SUCCESS The IP receive filter settings were updated. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_IP_FILTER) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_IP_FILTER *NewFilter + ); + +/** + Uses the ARP protocol to resolve a MAC address. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param IpAddr Pointer to the IP address that is used to resolve a MAC address. + @param MacAddr If not NULL, a pointer to the MAC address that was resolved with the + ARP protocol. + + @retval EFI_SUCCESS The IP or MAC address was resolved. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. + @retval EFI_ABORTED The callback function aborted the ARP Protocol. + @retval EFI_TIMEOUT The ARP Protocol encountered a timeout condition. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_ARP) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_IP_ADDRESS *IpAddr, + IN EFI_MAC_ADDRESS *MacAddr OPTIONAL + ); + +/** + Updates the parameters that affect the operation of the PXE Base Code Protocol. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param NewAutoArp If not NULL, a pointer to a value that specifies whether to replace the + current value of AutoARP. + @param NewSendGUID If not NULL, a pointer to a value that specifies whether to replace the + current value of SendGUID. + @param NewTTL If not NULL, a pointer to be used in place of the current value of TTL, + the ¡°time to live¡± field of the IP header. + @param NewToS If not NULL, a pointer to be used in place of the current value of ToS, + the ¡°type of service¡± field of the IP header. + @param NewMakeCallback If not NULL, a pointer to a value that specifies whether to replace the + current value of the MakeCallback field of the Mode structure. + + @retval EFI_SUCCESS The new parameters values were updated. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_PARAMETERS) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN BOOLEAN *NewAutoArp, OPTIONAL + IN BOOLEAN *NewSendGUID, OPTIONAL + IN UINT8 *NewTTL, OPTIONAL + IN UINT8 *NewToS, OPTIONAL + IN BOOLEAN *NewMakeCallback OPTIONAL + ); + +/** + Updates the station IP address and/or subnet mask values of a network device. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param NewStationIp Pointer to the new IP address to be used by the network device. + @param NewSubnetMask Pointer to the new subnet mask to be used by the network device. + + @retval EFI_SUCCESS The new station IP address and/or subnet mask were updated. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_STATION_IP) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + IN EFI_IP_ADDRESS *NewStationIp, OPTIONAL + IN EFI_IP_ADDRESS *NewSubnetMask OPTIONAL + ); + +/** + Updates the contents of the cached DHCP and Discover packets. + + @param This Pointer to the EFI_PXE_BASE_CODE_PROTOCOL instance. + @param NewDhcpDiscoverValid Pointer to a value that will replace the current + DhcpDiscoverValid field. + @param NewDhcpAckReceived Pointer to a value that will replace the current + DhcpAckReceived field. + @param NewProxyOfferReceived Pointer to a value that will replace the current + ProxyOfferReceived field. + @param NewPxeDiscoverValid Pointer to a value that will replace the current + ProxyOfferReceived field. + @param NewPxeReplyReceived Pointer to a value that will replace the current + PxeReplyReceived field. + @param NewPxeBisReplyReceived Pointer to a value that will replace the current + PxeBisReplyReceived field. + @param NewDhcpDiscover Pointer to the new cached DHCP Discover packet contents. + @param NewDhcpAck Pointer to the new cached DHCP Ack packet contents. + @param NewProxyOffer Pointer to the new cached Proxy Offer packet contents. + @param NewPxeDiscover Pointer to the new cached PXE Discover packet contents. + @param NewPxeReply Pointer to the new cached PXE Reply packet contents. + @param NewPxeBisReply Pointer to the new cached PXE BIS Reply packet contents. + + @retval EFI_SUCCESS The cached packet contents were updated. + @retval EFI_NOT_STARTED The PXE Base Code Protocol is in the stopped state. + @retval EFI_INVALID_PARAMETER This is NULL or not point to a valid EFI_PXE_BASE_CODE_PROTOCOL structure. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PXE_BASE_CODE_SET_PACKETS) ( + IN EFI_PXE_BASE_CODE_PROTOCOL *This, + BOOLEAN *NewDhcpDiscoverValid, OPTIONAL + BOOLEAN *NewDhcpAckReceived, OPTIONAL + BOOLEAN *NewProxyOfferReceived, OPTIONAL + BOOLEAN *NewPxeDiscoverValid, OPTIONAL + BOOLEAN *NewPxeReplyReceived, OPTIONAL + BOOLEAN *NewPxeBisReplyReceived, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewDhcpDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewDhcpAck, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewProxyOffer, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewPxeDiscover, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewPxeReply, OPTIONAL + IN EFI_PXE_BASE_CODE_PACKET *NewPxeBisReply OPTIONAL + ); + +// +// PXE Base Code Protocol structure +// +#define EFI_PXE_BASE_CODE_INTERFACE_REVISION 0x00010000 +#define EFI_PXE_BASE_CODE_PROTOCOL_REVISION EFI_PXE_BASE_CODE_INTERFACE_REVISION + +struct _EFI_PXE_BASE_CODE_PROTOCOL { + UINT64 Revision; + EFI_PXE_BASE_CODE_START Start; + EFI_PXE_BASE_CODE_STOP Stop; + EFI_PXE_BASE_CODE_DHCP Dhcp; + EFI_PXE_BASE_CODE_DISCOVER Discover; + EFI_PXE_BASE_CODE_MTFTP Mtftp; + EFI_PXE_BASE_CODE_UDP_WRITE UdpWrite; + EFI_PXE_BASE_CODE_UDP_READ UdpRead; + EFI_PXE_BASE_CODE_SET_IP_FILTER SetIpFilter; + EFI_PXE_BASE_CODE_ARP Arp; + EFI_PXE_BASE_CODE_SET_PARAMETERS SetParameters; + EFI_PXE_BASE_CODE_SET_STATION_IP SetStationIp; + EFI_PXE_BASE_CODE_SET_PACKETS SetPackets; + EFI_PXE_BASE_CODE_MODE *Mode; +}; + +extern EFI_GUID gEfiPxeBaseCodeProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/PxeBaseCodeCallBack.h b/MdePkg/Include/Protocol/PxeBaseCodeCallBack.h new file mode 100644 index 0000000000..7f16701367 --- /dev/null +++ b/MdePkg/Include/Protocol/PxeBaseCodeCallBack.h @@ -0,0 +1,94 @@ +/** @file + EFI PXE Base Code CallBack Protocol + + Copyright (c) 2006, 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. + + Module Name: PxeBaseCodeCallBack.h + +**/ + +#ifndef _PXE_BASE_CODE_CALLBACK_H_ +#define _PXE_BASE_CODE_CALLBACK_H_ + +// +// Call Back Definitions +// +#define EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_GUID \ + { \ + 0x245dca21, 0xfb7b, 0x11d3, {0x8f, 0x01, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +// +// Revision Number +// +#define EFI_PXE_BASE_CODE_CALLBACK_INTERFACE_REVISION 0x00010000 +#define EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL_REVISION \ + EFI_PXE_BASE_CODE_CALLBACK_INTERFACE_REVISION + +// +// Protocol definition +// +typedef struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL; + +typedef enum { + EFI_PXE_BASE_CODE_FUNCTION_FIRST, + EFI_PXE_BASE_CODE_FUNCTION_DHCP, + EFI_PXE_BASE_CODE_FUNCTION_DISCOVER, + EFI_PXE_BASE_CODE_FUNCTION_MTFTP, + EFI_PXE_BASE_CODE_FUNCTION_UDP_WRITE, + EFI_PXE_BASE_CODE_FUNCTION_UDP_READ, + EFI_PXE_BASE_CODE_FUNCTION_ARP, + EFI_PXE_BASE_CODE_FUNCTION_IGMP, + EFI_PXE_BASE_CODE_PXE_FUNCTION_LAST +} EFI_PXE_BASE_CODE_FUNCTION; + +typedef enum { + EFI_PXE_BASE_CODE_CALLBACK_STATUS_FIRST, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT, + EFI_PXE_BASE_CODE_CALLBACK_STATUS_LAST +} EFI_PXE_BASE_CODE_CALLBACK_STATUS; + +/** + Callback function that is invoked when the PXE Base Code Protocol is about to transmit, has + received, or is waiting to receive a packet. + + @param This Pointer to the EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL instance. + @param Function The PXE Base Code Protocol function that is waiting for an event. + @param Received TRUE if the callback is being invoked due to a receive event. FALSE if + the callback is being invoked due to a transmit event. + @param PacketLen The length, in bytes, of Packet. This field will have a value of zero if + this is a wait for receive event. + @param Packet If Received is TRUE, a pointer to the packet that was just received; + otherwise a pointer to the packet that is about to be transmitted. + + @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE if Function specifies a continue operation + @retval EFI_PXE_BASE_CODE_CALLBACK_STATUS_ABORT if Function specifies an abort operation + +**/ +typedef +EFI_PXE_BASE_CODE_CALLBACK_STATUS +(EFIAPI *EFI_PXE_CALLBACK)( + IN EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *This, + IN EFI_PXE_BASE_CODE_FUNCTION Function, + IN BOOLEAN Received, + IN UINT32 PacketLen, + IN EFI_PXE_BASE_CODE_PACKET *Packet OPTIONAL + ); + +struct _EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL { + UINT64 Revision; + EFI_PXE_CALLBACK Callback; +}; + +extern EFI_GUID gEfiPxeBaseCodeCallbackProtocolGuid; + +#endif + diff --git a/MdePkg/Include/Protocol/ScsiIo.h b/MdePkg/Include/Protocol/ScsiIo.h new file mode 100644 index 0000000000..e1019bac44 --- /dev/null +++ b/MdePkg/Include/Protocol/ScsiIo.h @@ -0,0 +1,233 @@ +/** @file + EFI_SCSI_IO_PROTOCOL as defined in UEFI 2.0. + + Copyright (c) 2006, 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. + + Module Name: ScsiIo.h + +**/ + +#ifndef __EFI_SCSI_IO_PROTOCOL_H__ +#define __EFI_SCSI_IO_PROTOCOL_H__ + +#define EFI_SCSI_IO_PROTOCOL_GUID \ + { \ + 0x932f4736, 0x2362, 0x4002, {0x80, 0x3e, 0x3c, 0xd5, 0x4b, 0x13, 0x8f, 0x85 } \ + } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_SCSI_IO_PROTOCOL EFI_SCSI_IO_PROTOCOL; + +// +// SCSI Data Direction definition +// +#define EFI_SCSI_IO_DATA_DIRECTION_READ 0 +#define EFI_SCSI_IO_DATA_DIRECTION_WRITE 1 +#define EFI_SCSI_IO_DATA_DIRECTION_BIDIRECTIONAL 2 + +// +// SCSI Host Adapter Status definition +// +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_OK 0x00 +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND 0x09 // timeout when processing the command +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_TIMEOUT 0x0b // timeout when waiting for the command processing +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_MESSAGE_REJECT 0x0d // a message reject was received when processing command +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_RESET 0x0e // a bus reset was detected +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_PARITY_ERROR 0x0f +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED 0x10 // the adapter failed in issuing request sense command +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT 0x11 // selection timeout +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN 0x12 // data overrun or data underrun +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_BUS_FREE 0x13 // Unexepected bus free +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_PHASE_ERROR 0x14 // Target bus phase sequence failure +#define EFI_SCSI_IO_STATUS_HOST_ADAPTER_OTHER 0x7f + + +// +// SCSI Target Status definition +// +#define EFI_SCSI_IO_STATUS_TARGET_GOOD 0x00 +#define EFI_SCSI_IO_STATUS_TARGET_CHECK_CONDITION 0x02 // check condition +#define EFI_SCSI_IO_STATUS_TARGET_CONDITION_MET 0x04 // condition met +#define EFI_SCSI_IO_STATUS_TARGET_BUSY 0x08 // busy +#define EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE 0x10 // intermediate +#define EFI_SCSI_IO_STATUS_TARGET_INTERMEDIATE_CONDITION_MET 0x14 // intermediate-condition met +#define EFI_SCSI_IO_STATUS_TARGET_RESERVATION_CONFLICT 0x18 // reservation conflict +#define EFI_SCSI_IO_STATUS_TARGET_COMMOND_TERMINATED 0x22 // command terminated +#define EFI_SCSI_IO_STATUS_TARGET_QUEUE_FULL 0x28 // queue full + +typedef struct { + UINT64 Timeout; + VOID *InDataBuffer; + VOID *OutDataBuffer; + VOID *SenseData; + VOID *Cdb; + UINT32 InTransferLength; + UINT32 OutTransferLength; + UINT8 CdbLength; + UINT8 DataDirection; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + UINT8 SenseDataLength; +} EFI_SCSI_IO_SCSI_REQUEST_PACKET; + +/** + Retrieves the device type information of the SCSI Controller. + + @param This Protocol instance pointer. + @param DeviceType A pointer to the device type information + retrieved from the SCSI Controller. + + @retval EFI_SUCCESS Retrieves the device type information successfully. + @retval EFI_INVALID_PARAMETER The DeviceType is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_GET_DEVICE_TYPE) ( + IN EFI_SCSI_IO_PROTOCOL *This, + OUT UINT8 *DeviceType + ) +; + +/** + Retrieves the device location in the SCSI channel. + + @param This Protocol instance pointer. + @param Target A pointer to the Target ID of a SCSI device + on the SCSI channel. + @param Lun A pointer to the LUN of the SCSI device on + the SCSI channel. + + @retval EFI_SUCCESS Retrieves the device location successfully. + @retval EFI_INVALID_PARAMETER The Target or Lun is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_GET_DEVICE_LOCATION) ( + IN EFI_SCSI_IO_PROTOCOL *This, + IN OUT UINT8 **Target, + OUT UINT64 *Lun + ) +; + +/** + Resets the SCSI Bus that the SCSI Controller is attached to. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The SCSI bus is reset successfully. + @retval EFI_DEVICE_ERROR Errors encountered when resetting the SCSI bus. + @retval EFI_UNSUPPORTED The bus reset operation is not supported by the + SCSI Host Controller. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset + the SCSI bus. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_RESET_BUS) ( + IN EFI_SCSI_IO_PROTOCOL *This + ) +; + +/** + Resets the SCSI Controller that the device handle specifies. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS Reset the SCSI controller successfully. + @retval EFI_DEVICE_ERROR Errors are encountered when resetting the + SCSI Controller. + @retval EFI_UNSUPPORTED The SCSI bus does not support a device + reset operation. + @retval EFI_TIMEOUT A timeout occurred while attempting to + reset the SCSI Controller. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_RESET_DEVICE) ( + IN EFI_SCSI_IO_PROTOCOL *This + ) +; + + +/** + Sends a SCSI Request Packet to the SCSI Controller for execution. + + @param This Protocol instance pointer. + @param Packet The SCSI request packet to send to the SCSI + Controller specified by the device handle. + @param Event If the SCSI bus where the SCSI device is attached + does not support non-blocking I/O, then Event is + ignored, and blocking I/O is performed. + If Event is NULL, then blocking I/O is performed. + If Event is not NULL and non-blocking I/O is + supported, then non-blocking I/O is performed, + and Event will be signaled when the SCSI Request + Packet completes. + + @retval EFI_SUCCESS The SCSI Request Packet was sent by the host + successfully, and TransferLength bytes were + transferred to/from DataBuffer.See + HostAdapterStatus, TargetStatus, + SenseDataLength, and SenseData in that order + for additional status information. + @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, + but the entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in TransferLength. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because + there are too many SCSI Command Packets already + queued.The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send + the SCSI Request Packet. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + @retval EFI_INVALID_PARAMETER The contents of CommandPacket are invalid. + The SCSI Request Packet was not sent, so no + additional status information is available. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet + is not supported by the SCSI initiator(i.e., SCSI + Host Controller). The SCSI Request Packet was not + sent, so no additional status information is + available. + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI + Request Packet to execute. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_IO_PROTOCOL_EXEC_SCSI_COMMAND) ( + IN EFI_SCSI_IO_PROTOCOL *This, + IN OUT EFI_SCSI_IO_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ) +; + +struct _EFI_SCSI_IO_PROTOCOL { + EFI_SCSI_IO_PROTOCOL_GET_DEVICE_TYPE GetDeviceType; + EFI_SCSI_IO_PROTOCOL_GET_DEVICE_LOCATION GetDeviceLocation; + EFI_SCSI_IO_PROTOCOL_RESET_BUS ResetBus; + EFI_SCSI_IO_PROTOCOL_RESET_DEVICE ResetDevice; + EFI_SCSI_IO_PROTOCOL_EXEC_SCSI_COMMAND ExecuteSCSICommand; + UINT32 IoAlign; +}; + +extern EFI_GUID gEfiScsiIoProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/ScsiPassThru.h b/MdePkg/Include/Protocol/ScsiPassThru.h new file mode 100644 index 0000000000..a5aa6c47c0 --- /dev/null +++ b/MdePkg/Include/Protocol/ScsiPassThru.h @@ -0,0 +1,312 @@ +/** @file + SCSI Pass Through protocol. + + Copyright (c) 2006, 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. + + Module Name: ScsiPassThru.h + +**/ + +#ifndef __SCSI_PASS_THROUGH_H__ +#define __SCSI_PASS_THROUGH_H__ + +#define EFI_SCSI_PASS_THRU_PROTOCOL_GUID \ + { \ + 0xa59e8fcf, 0xbda0, 0x43bb, {0x90, 0xb1, 0xd3, 0x73, 0x2e, 0xca, 0xa8, 0x77 } \ + } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_SCSI_PASS_THRU_PROTOCOL EFI_SCSI_PASS_THRU_PROTOCOL; + +#define EFI_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL 0x0001 +#define EFI_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL 0x0002 +#define EFI_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO 0x0004 + +// +// SCSI Host Adapter Status definition +// +#define EFI_SCSI_STATUS_HOST_ADAPTER_OK 0x00 +#define EFI_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND 0x09 // timeout when processing the command +#define EFI_SCSI_STATUS_HOST_ADAPTER_TIMEOUT 0x0b // timeout when waiting for the command processing +#define EFI_SCSI_STATUS_HOST_ADAPTER_MESSAGE_REJECT 0x0d // a message reject was received when processing command +#define EFI_SCSI_STATUS_HOST_ADAPTER_BUS_RESET 0x0e // a bus reset was detected +#define EFI_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR 0x0f +#define EFI_SCSI_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED 0x10 // the adapter failed in issuing request sense command +#define EFI_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT 0x11 // selection timeout +#define EFI_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN 0x12 // data overrun or data underrun +#define EFI_SCSI_STATUS_HOST_ADAPTER_BUS_FREE 0x13 // Unexepected bus free +#define EFI_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR 0x14 // Target bus phase sequence failure +#define EFI_SCSI_STATUS_HOST_ADAPTER_OTHER 0x7f + +// +// SCSI Target Status definition +// +#define EFI_SCSI_STATUS_TARGET_GOOD 0x00 +#define EFI_SCSI_STATUS_TARGET_CHECK_CONDITION 0x02 // check condition +#define EFI_SCSI_STATUS_TARGET_CONDITION_MET 0x04 // condition met +#define EFI_SCSI_STATUS_TARGET_BUSY 0x08 // busy +#define EFI_SCSI_STATUS_TARGET_INTERMEDIATE 0x10 // intermediate +#define EFI_SCSI_STATUS_TARGET_INTERMEDIATE_CONDITION_MET 0x14 // intermediate-condition met +#define EFI_SCSI_STATUS_TARGET_RESERVATION_CONFLICT 0x18 // reservation conflict +#define EFI_SCSI_STATUS_TARGET_COMMOND_TERMINATED 0x22 // command terminated +#define EFI_SCSI_STATUS_TARGET_QUEUE_FULL 0x28 // queue full + +typedef struct { + UINT64 Timeout; + VOID *DataBuffer; + VOID *SenseData; + VOID *Cdb; + UINT32 TransferLength; + UINT8 CdbLength; + UINT8 DataDirection; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + UINT8 SenseDataLength; +} EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET; + +typedef struct { + CHAR16 *ControllerName; + CHAR16 *ChannelName; + UINT32 AdapterId; + UINT32 Attributes; + UINT32 IoAlign; +} EFI_SCSI_PASS_THRU_MODE; + +/** + Sends a SCSI Request Packet to a SCSI device that is attached to + the SCSI channel. This function supports both blocking I/O and + non-blocking I/O. The blocking I/O functionality is required, + and the non-blocking I/O functionality is optional. + + @param This Protocol instance pointer. + @param Target The Target ID of the SCSI device to + send the SCSI Request Packet. + @param Lun The LUN of the SCSI device to send the + SCSI Request Packet. + @param Packet A pointer to the SCSI Request Packet to send + to the SCSI device specified by Target and Lun. + @param Event If non-blocking I/O is not supported then Event + is ignored, and blocking I/O is performed. + If Event is NULL, then blocking I/O is performed. + If Event is not NULL and non blocking I/O is + supported, then non-blocking I/O is performed, + and Event will be signaled when the SCSI Request + Packet completes + + @retval EFI_SUCCESS The SCSI Request Packet was sent by the host, and + TransferLength bytes were transferred to/from + DataBuffer.See HostAdapterStatus, TargetStatus, + SenseDataLength,and SenseData in that order + for additional status information. + @retval EFI_WARN_BUFFER_TOO_SMALL The SCSI Request Packet was executed, but the + entire DataBuffer could not be transferred. + The actual number of bytes transferred is returned + in TransferLength. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because + there are too many SCSI Request Packets already + queued. The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send + the SCSI Request Packet. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + @retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket + are invalid. The SCSI Request Packet was not sent, + so no additional status information is available. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet + is not supported by the host adapter. The SCSI + Request Packet was not sent, so no additional + status information is available. + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI + Request Packet to execute. See HostAdapterStatus, + TargetStatus, SenseDataLength, and SenseData in + that order for additional status information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_PASSTHRU) ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ) +; + +/** + Used to retrieve the list of legal Target IDs for SCSI devices + on a SCSI channel. + + @param This Protocol instance pointer. + @param Target On input, a pointer to the Target ID of a + SCSI device present on the SCSI channel. + On output, a pointer to the Target ID of + the next SCSI device present on a SCSI channel. + An input value of 0xFFFFFFFF retrieves the + Target ID of the first SCSI device present on + a SCSI channel. + @param Lun On input, a pointer to the LUN of a SCSI device + present on the SCSI channel.On output, a pointer + to the LUN of the next SCSI device present on a + SCSI channel. + + @retval EFI_SUCCESS The Target ID of the next SCSI device on the SCSI + channel was returned in Target and Lun. + @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel. + @retval EFI_INVALID_PARAMETER Target is not 0xFFFFFFFF, and Target and Lun were + not returned on a previous call to GetNextDevice(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_GET_NEXT_DEVICE) ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT32 *Target, + IN OUT UINT64 *Lun + ) +; + +/** + Used to allocate and build a device path node for a SCSI device + on a SCSI channel. + + @param This Protocol instance pointer. + @param Target The Target ID of the SCSI device for which + a device path node is to be allocated and built. + @param Lun The LUN of the SCSI device for which a device + path node is to be allocated and built. + @param DevicePath A pointer to a single device path node that + describes the SCSI device specified by + Target and Lun. This function is responsible + for allocating the buffer DevicePath with the boot + service AllocatePool(). It is the caller's + responsibility to free DevicePath when the caller + is finished with DevicePath. + + @retval EFI_SUCCESS The device path node that describes the SCSI device + specified by Target and Lun was allocated and + returned in DevicePath. + @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does + not exist on the SCSI channel. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate + DevicePath. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_BUILD_DEVICE_PATH) ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +; + +/** + Used to translate a device path node to a Target ID and LUN. + + @param This Protocol instance pointer. + @param DevicePath A pointer to the device path node that + describes a SCSI device on the SCSI channel. + @param Target A pointer to the Target ID of a SCSI device + on the SCSI channel. + @param Lun A pointer to the LUN of a SCSI device on + the SCSI channel. + + @retval EFI_SUCCESS DevicePath was successfully translated to a + Target ID and LUN, and they were returned + in Target and Lun. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_INVALID_PARAMETER Target is NULL. + @retval EFI_INVALID_PARAMETER Lun is NULL. + @retval EFI_UNSUPPORTED This driver does not support the device path + node type in DevicePath. + @retval EFI_NOT_FOUND A valid translation from DevicePath to a + Target ID and LUN does not exist. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_GET_TARGET_LUN) ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT32 *Target, + OUT UINT64 *Lun + ) +; + +/** + Resets a SCSI channel.This operation resets all the + SCSI devices connected to the SCSI channel. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The SCSI channel was reset. + @retval EFI_UNSUPPORTED The SCSI channel does not support + a channel reset operation. + @retval EFI_DEVICE_ERROR A device error occurred while + attempting to reset the SCSI channel. + @retval EFI_TIMEOUT A timeout occurred while attempting + to reset the SCSI channel. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_RESET_CHANNEL) ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This + ) +; + +/** + Resets a SCSI device that is connected to a SCSI channel. + + @param This Protocol instance pointer. + @param Target The Target ID of the SCSI device to reset. + @param Lun The LUN of the SCSI device to reset. + + @retval EFI_SUCCESS The SCSI device specified by Target and + Lun was reset. + @retval EFI_UNSUPPORTED The SCSI channel does not support a target + reset operation. + @retval EFI_INVALID_PARAMETER Target or Lun are invalid. + @retval EFI_DEVICE_ERROR A device error occurred while attempting + to reset the SCSI device specified by Target + and Lun. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset + the SCSI device specified by Target and Lun. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SCSI_PASS_THRU_RESET_TARGET) ( + IN EFI_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT32 Target, + IN UINT64 Lun + ) +; + +struct _EFI_SCSI_PASS_THRU_PROTOCOL { + EFI_SCSI_PASS_THRU_MODE *Mode; + EFI_SCSI_PASS_THRU_PASSTHRU PassThru; + EFI_SCSI_PASS_THRU_GET_NEXT_DEVICE GetNextDevice; + EFI_SCSI_PASS_THRU_BUILD_DEVICE_PATH BuildDevicePath; + EFI_SCSI_PASS_THRU_GET_TARGET_LUN GetTargetLun; + EFI_SCSI_PASS_THRU_RESET_CHANNEL ResetChannel; + EFI_SCSI_PASS_THRU_RESET_TARGET ResetTarget; +}; + +extern EFI_GUID gEfiScsiPassThruProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/ScsiPassThruExt.h b/MdePkg/Include/Protocol/ScsiPassThruExt.h new file mode 100644 index 0000000000..b522792848 --- /dev/null +++ b/MdePkg/Include/Protocol/ScsiPassThruExt.h @@ -0,0 +1,332 @@ +/** @file + EFI_EXT_SCSI_PASS_THRU_PROTOCOL as defined in UEFI 2.0. + + Copyright (c) 2006, 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. + + Module Name: ScsiPassThruExt.h + +**/ + +#ifndef __EXT_SCSI_PASS_THROUGH_PROTOCOL_H__ +#define __EXT_SCSI_PASS_THROUGH_PROTOCOL_H__ + +#define EFI_EXT_SCSI_PASS_THRU_PROTOCOL_GUID \ + { \ + 0x1d3de7f0, 0x0807, 0x424f, {0xaa, 0x69, 0x11, 0xa5, 0x4e, 0x19, 0xa4, 0x6f } \ + } + +typedef struct _EFI_EXT_SCSI_PASS_THRU_PROTOCOL EFI_EXT_SCSI_PASS_THRU_PROTOCOL; + +#define TARGET_MAX_BYTES 0x10 + +#define EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_PHYSICAL 0x0001 +#define EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_LOGICAL 0x0002 +#define EFI_EXT_SCSI_PASS_THRU_ATTRIBUTES_NONBLOCKIO 0x0004 + +// +// DataDirection +// +#define EFI_EXT_SCSI_DATA_DIRECTION_READ 0 +#define EFI_EXT_SCSI_DATA_DIRECTION_WRITE 1 +#define EFI_EXT_SCSI_DATA_DIRECTION_BIDIRECTIONAL 2 +// +// HostAdapterStatus +// +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OK 0x00 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT_COMMAND 0x09 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_TIMEOUT 0x0b +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_MESSAGE_REJECT 0x0d +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_RESET 0x0e +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PARITY_ERROR 0x0f +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_REQUEST_SENSE_FAILED 0x10 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_SELECTION_TIMEOUT 0x11 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_DATA_OVERRUN_UNDERRUN 0x12 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_BUS_FREE 0x13 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_PHASE_ERROR 0x14 +#define EFI_EXT_SCSI_STATUS_HOST_ADAPTER_OTHER 0x7f +// +// TargetStatus +// +#define EFI_EXT_SCSI_STATUS_TARGET_GOOD 0x00 +#define EFI_EXT_SCSI_STATUS_TARGET_CHECK_CONDITION 0x02 +#define EFI_EXT_SCSI_STATUS_TARGET_CONDITION_MET 0x04 +#define EFI_EXT_SCSI_STATUS_TARGET_BUSY 0x08 +#define EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE 0x10 +#define EFI_EXT_SCSI_STATUS_TARGET_INTERMEDIATE_CONDITION_MET 0x14 +#define EFI_EXT_SCSI_STATUS_TARGET_RESERVATION_CONFLICT 0x18 +#define EFI_EXT_SCSI_STATUS_TARGET_TASK_SET_FULL 0x28 +#define EFI_EXT_SCSI_STATUS_TARGET_ACA_ACTIVE 0x30 +#define EFI_EXT_SCSI_STATUS_TARGET_TASK_ABORTED 0x40 + +typedef struct { + UINT32 AdapterId; + UINT32 Attributes; + UINT32 IoAlign; +} EFI_EXT_SCSI_PASS_THRU_MODE; + +typedef struct { + UINT64 Timeout; + VOID *InDataBuffer; + VOID *OutDataBuffer; + VOID *SenseData; + VOID *Cdb; + UINT32 InTransferLength; + UINT32 OutTransferLength; + UINT8 CdbLength; + UINT8 DataDirection; + UINT8 HostAdapterStatus; + UINT8 TargetStatus; + UINT8 SenseDataLength; +} EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET; + +/** + Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function + supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the + nonblocking I/O functionality is optional. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param Target The Target is an array of size TARGET_MAX_BYTES and it represents + the id of the SCSI device to send the SCSI Request Packet. Each + transport driver may chose to utilize a subset of this size to suit the needs + of transport target representation. For example, a Fibre Channel driver + may use only 8 bytes (WWN) to represent an FC target. + @param Lun The LUN of the SCSI device to send the SCSI Request Packet. + @param Packet A pointer to the SCSI Request Packet to send to the SCSI device + specified by Target and Lun. + @param Event If nonblocking I/O is not supported then Event is ignored, and blocking + I/O is performed. If Event is NULL, then blocking I/O is performed. If + Event is not NULL and non blocking I/O is supported, then + nonblocking I/O is performed, and Event will be signaled when the + SCSI Request Packet completes. + + @retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional + commands, InTransferLength bytes were transferred from + InDataBuffer. For write and bi-directional commands, + OutTransferLength bytes were transferred by + OutDataBuffer. + @retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was not executed. The number of bytes that + could be transferred is returned in InTransferLength. For write + and bi-directional commands, OutTransferLength bytes were + transferred by OutDataBuffer. + @retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many + SCSI Request Packets already queued. The caller may retry again later. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request + Packet. + @retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket are invalid. + @retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported + by the host adapter. This includes the case of Bi-directional SCSI + commands not supported by the implementation. The SCSI Request + Packet was not sent, so no additional status information is available. + @retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_PASSTHRU) ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT8 *Target, + IN UINT64 Lun, + IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet, + IN EFI_EVENT Event OPTIONAL + ) +; + +/** + Used to retrieve the list of legal Target IDs and LUNs for SCSI devices on a SCSI channel. These + can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal + Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the + Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI + channel. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param Target On input, a pointer to the Target ID (an array of size + TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel. + On output, a pointer to the Target ID (an array of + TARGET_MAX_BYTES) of the next SCSI device present on a SCSI + channel. An input value of 0xF(all bytes in the array are 0xF) in the + Target array retrieves the Target ID of the first SCSI device present on a + SCSI channel. + @param Lun On input, a pointer to the LUN of a SCSI device present on the SCSI + channel. On output, a pointer to the LUN of the next SCSI device present + on a SCSI channel. + + @retval EFI_SUCCESS The Target ID and LUN of the next SCSI device on the SCSI + channel was returned in Target and Lun. + @retval EFI_INVALID_PARAMETER Target array is not all 0xF, and Target and Lun were + not returned on a previous call to GetNextTargetLun(). + @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_GET_NEXT_TARGET_LUN) ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT8 **Target, + IN OUT UINT64 *Lun + ) +; + +/** + Used to allocate and build a device path node for a SCSI device on a SCSI channel. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param Target The Target is an array of size TARGET_MAX_BYTES and it specifies the + Target ID of the SCSI device for which a device path node is to be + allocated and built. Transport drivers may chose to utilize a subset of + this size to suit the representation of targets. For example, a Fibre + Channel driver may use only 8 bytes (WWN) in the array to represent a + FC target. + @param Lun The LUN of the SCSI device for which a device path node is to be + allocated and built. + + @param DevicePath A pointer to a single device path node that describes the SCSI device + specified by Target and Lun. This function is responsible for + allocating the buffer DevicePath with the boot service + AllocatePool(). It is the caller's responsibility to free + DevicePath when the caller is finished with DevicePath. + + @retval EFI_SUCCESS The device path node that describes the SCSI device specified by + Target and Lun was allocated and returned in + DevicePath. + @retval EFI_INVALID_PARAMETER DevicePath is NULL. + @retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does not exist + on the SCSI channel. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_BUILD_DEVICE_PATH) ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT8 *Target, + IN UINT64 Lun, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath + ) +; + +/** + Used to translate a device path node to a Target ID and LUN. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param DevicePath A pointer to a single device path node that describes the SCSI device + on the SCSI channel. + @param Target A pointer to the Target Array which represents the ID of a SCSI device + on the SCSI channel. + @param Lun A pointer to the LUN of a SCSI device on the SCSI channel. + + @retval EFI_SUCCESS DevicePath was successfully translated to a Target ID and + LUN, and they were returned in Target and Lun. + @retval EFI_INVALID_PARAMETER DevicePath or Target or Lun is NULL. + @retval EFI_NOT_FOUND A valid translation from DevicePath to a Target ID and LUN + does not exist. + @retval EFI_UNSUPPORTED This driver does not support the device path node type in + DevicePath. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_GET_TARGET_LUN) ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath, + OUT UINT8 **Target, + OUT UINT64 *Lun + ) +; + +/** + Resets a SCSI channel. This operation resets all the SCSI devices connected to the SCSI channel. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + + @retval EFI_SUCCESS The SCSI channel was reset. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI channel. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI channel. + @retval EFI_UNSUPPORTED The SCSI channel does not support a channel reset operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_RESET_CHANNEL) ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This + ) +; + +/** + Resets a SCSI logical unit that is connected to a SCSI channel. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param Target The Target is an array of size TARGET_MAX_BYTE and it represents the + target port ID of the SCSI device containing the SCSI logical unit to + reset. Transport drivers may chose to utilize a subset of this array to suit + the representation of their targets. + @param Lun The LUN of the SCSI device to reset. + + @retval EFI_SUCCESS The SCSI device specified by Target and Lun was reset. + @retval EFI_INVALID_PARAMETER Target or Lun is NULL. + @retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI device + specified by Target and Lun. + @retval EFI_UNSUPPORTED The SCSI channel does not support a target reset operation. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI device + specified by Target and Lun. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_RESET_TARGET_LUN) ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN UINT8 *Target, + IN UINT64 Lun + ) +; + +/** + Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either + be the list SCSI devices that are actually present on the SCSI channel, or the list of legal Target IDs + for the SCSI channel. Regardless, the caller of this function must probe the Target ID returned to + see if a SCSI device is actually present at that location on the SCSI channel. + + @param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance. + @param Target (TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel. + On output, a pointer to the Target ID (an array of + TARGET_MAX_BYTES) of the next SCSI device present on a SCSI + channel. An input value of 0xF(all bytes in the array are 0xF) in the + Target array retrieves the Target ID of the first SCSI device present on a + SCSI channel. + + @retval EFI_SUCCESS The Target ID of the next SCSI device on the SCSI + channel was returned in Target. + @retval EFI_INVALID_PARAMETER Target or Lun is NULL. + @retval EFI_TIMEOUT Target array is not all 0xF, and Target were not + returned on a previous call to GetNextTarget(). + @retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXT_SCSI_PASS_THRU_GET_NEXT_TARGET) ( + IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This, + IN OUT UINT8 **Target + ) +; + +struct _EFI_EXT_SCSI_PASS_THRU_PROTOCOL { + EFI_EXT_SCSI_PASS_THRU_MODE *Mode; + EFI_EXT_SCSI_PASS_THRU_PASSTHRU PassThru; + EFI_EXT_SCSI_PASS_THRU_GET_NEXT_TARGET_LUN GetNextTargetLun; + EFI_EXT_SCSI_PASS_THRU_BUILD_DEVICE_PATH BuildDevicePath; + EFI_EXT_SCSI_PASS_THRU_GET_TARGET_LUN GetTargetLun; + EFI_EXT_SCSI_PASS_THRU_RESET_CHANNEL ResetChannel; + EFI_EXT_SCSI_PASS_THRU_RESET_TARGET_LUN ResetTargetLun; + EFI_EXT_SCSI_PASS_THRU_GET_NEXT_TARGET GetNextTarget; +}; + +extern EFI_GUID gEfiExtScsiPassThruProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SectionExtraction.h b/MdePkg/Include/Protocol/SectionExtraction.h new file mode 100644 index 0000000000..9200f8a444 --- /dev/null +++ b/MdePkg/Include/Protocol/SectionExtraction.h @@ -0,0 +1,162 @@ +/** @file + This file declares Section Extraction protocols. + + This interface provides a means of decoding a set of sections into a linked list of + leaf sections. This provides for an extensible and flexible file format. + + Copyright (c) 2006, Intel Corporation + All rights reserved. This program and the 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. + + Module Name: SectionExtraction.h + + @par Revision Reference: + This protocol is defined in Firmware Volume Specification. + Version 0.9 + +**/ + +#ifndef __SECTION_EXTRACTION_PROTOCOL_H__ +#define __SECTION_EXTRACTION_PROTOCOL_H__ + + +// +// Protocol GUID definition +// +#define EFI_SECTION_EXTRACTION_PROTOCOL_GUID \ + { \ + 0x448F5DA4, 0x6DD7, 0x4FE1, {0x93, 0x07, 0x69, 0x22, 0x41, 0x92, 0x21, 0x5D } \ + } + +typedef struct _EFI_SECTION_EXTRACTION_PROTOCOL EFI_SECTION_EXTRACTION_PROTOCOL; + +// +// Protocol member functions +// +/** + Creates and returns a new section stream handle to represent the new section stream. + + @param This Indicates the EFI_SECTION_EXTRACTION_PROTOCOL instance. + @param SectionStreamLength Size in bytes of the section stream. + @param SectionStream Buffer containing the new section stream. + @param SectionStreamHandle A pointer to a caller-allocated UINTN that, + on output, contains the new section stream handle. + + @retval EFI_SUCCESS The SectionStream was successfully processed and + the section stream handle was returned. + @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to + process the request. + @retval EFI_INVALID_PARAMETER The section stream may be corrupt or the value + of SectionStreamLength may be incorrect. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_SECTION_STREAM) ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamLength, + IN VOID *SectionStream, + OUT UINTN *SectionStreamHandle + ); + +/** + Reads and returns a single section from a section stream. + + @param This Indicates the EFI_SECTION_EXTRACTION_PROTOCOL instance. + @param SectionStreamHandle Indicates from which section stream to read. + @param SectionType Pointer to an EFI_SECTION_TYPE. + @param SectionDefinitionGuid Pointer to an EFI_GUID.If SectionType == + EFI_SECTION_GUID_DEFINED, SectionDefinitionGuid indicates what section GUID + to search for.If SectionType !=EFI_SECTION_GUID_DEFINED, then + SectionDefinitionGuid is unused and is ignored. + @param SectionInstance Indicates which instance of the requested section + type to return when SectionType is not NULL. + @param SectionStreamHandle A pointer to a caller-allocated UINTN that, on output, + contains the new section stream handle. + @param Buffer Pointer to a pointer to a buffer in which the section + contents are returned. + @param BufferSize Pointer to a caller-allocated UINTN. + @param AuthenticationStatus Pointer to a caller-allocated UINT32 in + which any meta-data from encapsulation GUID-defined sections is returned. + + @retval EFI_SUCCESS The SectionStream was successfully processed and + the section contents were returned in Buffer. + @retval EFI_PROTOCOL_ERROR A GUID-defined section was encountered in + the section stream with its EFI_GUIDED_SECTION_PROCESSING_REQUIRED bit set, + but there was no corresponding GUIDed Section Extraction Protocol in + the handle database. + @retval EFI_NOT_FOUND An error was encountered when parsing the SectionStream, + which indicates that the SectionStream is not correctly formatted. + Or The requested section does not exist. + @retval EFI_OUT_OF_RESOURCES The system has insufficient resources to process + the request. + @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist. + @retval EFI_BUFFER_TOO_SMALL The size of the input buffer is insufficient to + contain the requested section. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_SECTION) ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamHandle, + IN EFI_SECTION_TYPE *SectionType, + IN EFI_GUID *SectionDefinitionGuid, + IN UINTN SectionInstance, + IN VOID **Buffer, + IN OUT UINTN *BufferSize, + OUT UINT32 *AuthenticationStatus + ); + +/** + Deletes a section stream handle and returns all associated resources to the system. + + @param This Indicates the EFI_SECTION_EXTRACTION_PROTOCOL instance. + @param SectionStreamHandle Indicates the section stream to close. + + @retval EFI_SUCCESS The SectionStream was successfully processed and + the section stream handle was returned. + + @retval EFI_INVALID_PARAMETER The SectionStreamHandle does not exist. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CLOSE_SECTION_STREAM) ( + IN EFI_SECTION_EXTRACTION_PROTOCOL *This, + IN UINTN SectionStreamHandle + ); + +// +// Protocol definition +// +/** + @par Protocol Description: + The Section Extraction Protocol provides a simple method of extracting + sections from arbitrarily complex files. + + @param OpenSectionStream + Takes a bounded stream of sections and returns a section stream handle. + + @param GetSection + Given a section stream handle, retrieves the requested section and + meta-data from the section stream. + + @param CloseSectionStream + Given a section stream handle, closes the section stream. + +**/ +struct _EFI_SECTION_EXTRACTION_PROTOCOL { + EFI_OPEN_SECTION_STREAM OpenSectionStream; + EFI_GET_SECTION GetSection; + EFI_CLOSE_SECTION_STREAM CloseSectionStream; +}; + +extern EFI_GUID gEfiSectionExtractionProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SerialIo.h b/MdePkg/Include/Protocol/SerialIo.h new file mode 100644 index 0000000000..89a73409d9 --- /dev/null +++ b/MdePkg/Include/Protocol/SerialIo.h @@ -0,0 +1,266 @@ +/** @file + Serial IO protocol as defined in the EFI 1.0 specification. + + Abstraction of a basic serial device. Targeted at 16550 UART, but + could be much more generic. + + Copyright (c) 2006, 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. + + Module Name: SerialIo.h + +**/ + +#ifndef __SERIAL_IO_PROTOCOL_H__ +#define __SERIAL_IO_PROTOCOL_H__ + +#define EFI_SERIAL_IO_PROTOCOL_GUID \ + { \ + 0xBB25CF6F, 0xF1D4, 0x11D2, {0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0xFD } \ + } + +typedef struct _EFI_SERIAL_IO_PROTOCOL EFI_SERIAL_IO_PROTOCOL; + +// +// Serial IO Data structures +// +typedef enum { + DefaultParity, + NoParity, + EvenParity, + OddParity, + MarkParity, + SpaceParity +} EFI_PARITY_TYPE; + +typedef enum { + DefaultStopBits, + OneStopBit, + OneFiveStopBits, + TwoStopBits +} EFI_STOP_BITS_TYPE; + +// +// define for Control bits, grouped by read only, write only, and read write +// +// +// Read Only +// +#define EFI_SERIAL_CLEAR_TO_SEND 0x00000010 +#define EFI_SERIAL_DATA_SET_READY 0x00000020 +#define EFI_SERIAL_RING_INDICATE 0x00000040 +#define EFI_SERIAL_CARRIER_DETECT 0x00000080 +#define EFI_SERIAL_INPUT_BUFFER_EMPTY 0x00000100 +#define EFI_SERIAL_OUTPUT_BUFFER_EMPTY 0x00000200 + +// +// Write Only +// +#define EFI_SERIAL_REQUEST_TO_SEND 0x00000002 +#define EFI_SERIAL_DATA_TERMINAL_READY 0x00000001 + +// +// Read Write +// +#define EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE 0x00001000 +#define EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE 0x00002000 +#define EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE 0x00004000 + +// +// Serial IO Member Functions +// +/** + Reset the serial device. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The serial device could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_RESET) ( + IN EFI_SERIAL_IO_PROTOCOL *This + ) +; + +/** + Sets the baud rate, receive FIFO depth, transmit/receice time out, parity, + data buts, and stop bits on a serial device. + + @param This Protocol instance pointer. + @param BaudRate The requested baud rate. A BaudRate value of 0 will use the the + device's default interface speed. + @param ReveiveFifoDepth The requested depth of the FIFO on the receive side of the + serial interface. A ReceiveFifoDepth value of 0 will use + the device's dfault FIFO depth. + @param Timeout The requested time out for a single character in microseconds. + This timeout applies to both the transmit and receive side of the + interface. A Timeout value of 0 will use the device's default time + out value. + @param Parity The type of parity to use on this serial device. A Parity value of + DefaultParity will use the device's default parity value. + @param DataBits The number of data bits to use on the serial device. A DataBits + vaule of 0 will use the device's default data bit setting. + @param StopBits The number of stop bits to use on this serial device. A StopBits + value of DefaultStopBits will use the device's default number of + stop bits. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The serial device could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_SET_ATTRIBUTES) ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ) +; + +/** + Set the control bits on a serial device + + @param This Protocol instance pointer. + @param Control Set the bits of Control that are settable. + + @retval EFI_SUCCESS The new control bits were set on the serial device. + @retval EFI_UNSUPPORTED The serial device does not support this operation. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_SET_CONTROL_BITS) ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ) +; + +/** + Retrieves the status of thecontrol bits on a serial device + + @param This Protocol instance pointer. + @param Control A pointer to return the current Control signals from the serial device. + + @retval EFI_SUCCESS The control bits were read from the serial device. + @retval EFI_DEVICE_ERROR The serial device is not functioning correctly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_GET_CONTROL_BITS) ( + IN EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ) +; + +/** + Writes data to a serial device. + + @param This Protocol instance pointer. + @param BufferSize On input, the size of the Buffer. On output, the amount of + data actually written. + @param Buffer The buffer of data to write + + @retval EFI_SUCCESS The data was written. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_WRITE) ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +; + +/** + Writes data to a serial device. + + @param This Protocol instance pointer. + @param BufferSize On input, the size of the Buffer. On output, the amount of + data returned in Buffer. + @param Buffer The buffer to return the data into. + + @retval EFI_SUCCESS The data was read. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_TIMEOUT The data write was stopped due to a timeout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERIAL_READ) ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +; + +/** + The data values in SERIAL_IO_MODE are read-only and are updated by the code + that produces the SERIAL_IO_PROTOCOL member functions. + + ControlMask - A mask fo the Control bits that the device supports. The device + must always support the Input Buffer Empty control bit. + TimeOut - If applicable, the number of microseconds to wait before timing out + a Read or Write operation. + BaudRate - If applicable, the current baud rate setting of the device; otherwise, + baud rate has the value of zero to indicate that device runs at the + device's designed speed. + ReceiveFifoDepth - The number of characters the device will buffer on input + DataBits - The number of characters the device will buffer on input + Parity - If applicable, this is the EFI_PARITY_TYPE that is computed or + checked as each character is transmitted or reveived. If the device + does not support parity the value is the default parity value. + StopBits - If applicable, the EFI_STOP_BITS_TYPE number of stop bits per + character. If the device does not support stop bits the value is + the default stop bit values. + +**/ +typedef struct { + UINT32 ControlMask; + + // + // current Attributes + // + UINT32 Timeout; + UINT64 BaudRate; + UINT32 ReceiveFifoDepth; + UINT32 DataBits; + UINT32 Parity; + UINT32 StopBits; +} EFI_SERIAL_IO_MODE; + +#define SERIAL_IO_INTERFACE_REVISION 0x00010000 +#define EFI_SERIAL_IO_PROTOCOL_REVISION SERIAL_IO_INTERFACE_REVISION + +struct _EFI_SERIAL_IO_PROTOCOL { + UINT32 Revision; + EFI_SERIAL_RESET Reset; + EFI_SERIAL_SET_ATTRIBUTES SetAttributes; + EFI_SERIAL_SET_CONTROL_BITS SetControl; + EFI_SERIAL_GET_CONTROL_BITS GetControl; + EFI_SERIAL_WRITE Write; + EFI_SERIAL_READ Read; + + EFI_SERIAL_IO_MODE *Mode; +}; + +extern EFI_GUID gEfiSerialIoProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/ServiceBinding.h b/MdePkg/Include/Protocol/ServiceBinding.h new file mode 100644 index 0000000000..57ce92f142 --- /dev/null +++ b/MdePkg/Include/Protocol/ServiceBinding.h @@ -0,0 +1,74 @@ +/** @file + Copyright (c) 2006, 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. + + Module Name: ServiceBinding.h + +**/ + +#ifndef __EFI_SERVICE_BINDING_H__ +#define __EFI_SERVICE_BINDING_H__ + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_SERVICE_BINDING_PROTOCOL EFI_SERVICE_BINDING_PROTOCOL; + +/** + Creates a child handle with a set of I/O services. + + @param This Protocol instance pointer. + @param ChildHandle Pointer to the handle of the child to create. If it is NULL, + then a new handle is created. If it is not NULL, then the + I/O services are added to the existing child handle. + + @retval EFI_SUCCES The child handle was created with the I/O services + @retval EFI_INVALID_PARAMETER ChildHandle is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create + the child + @retval other The child handle was not created + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERVICE_BINDING_CREATE_CHILD) ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN OUT EFI_HANDLE *ChildHandle + ) +; + +/** + Destroys a child handle with a set of I/O services. + + @param This Protocol instance pointer. + @param ChildHandle Handle of the child to destroy + + @retval EFI_SUCCES The I/O services were removed from the child handle + @retval EFI_UNSUPPORTED The child handle does not support the I/O services + that are being removed. + @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle. + @retval EFI_ACCESS_DENIED The child handle could not be destroyed because its + I/O services are being used. + @retval other The child handle was not destroyed + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SERVICE_BINDING_DESTROY_CHILD) ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE ChildHandle + ) +; + +struct _EFI_SERVICE_BINDING_PROTOCOL { + EFI_SERVICE_BINDING_CREATE_CHILD CreateChild; + EFI_SERVICE_BINDING_DESTROY_CHILD DestroyChild; +}; + +#endif diff --git a/MdePkg/Include/Protocol/SimpleFileSystem.h b/MdePkg/Include/Protocol/SimpleFileSystem.h new file mode 100644 index 0000000000..add8ad6eeb --- /dev/null +++ b/MdePkg/Include/Protocol/SimpleFileSystem.h @@ -0,0 +1,328 @@ +/** @file + SimpleFileSystem protocol as defined in the EFI 1.0 specification. + + The SimpleFileSystem protocol is the programatic access to the FAT (12,16,32) + file system specified in EFI 1.0. It can also be used to abstract a file + system other than FAT. + + EFI 1.0 can boot from any valid EFI image contained in a SimpleFileSystem + + Copyright (c) 2006, 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. + + Module Name: SimpleFileSystem.h + +**/ + +#ifndef __SIMPLE_FILE_SYSTEM_H__ +#define __SIMPLE_FILE_SYSTEM_H__ + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID \ + { \ + 0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +typedef struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL EFI_SIMPLE_FILE_SYSTEM_PROTOCOL; +typedef struct _EFI_FILE EFI_FILE; +typedef struct _EFI_FILE *EFI_FILE_HANDLE; +typedef struct _EFI_FILE EFI_FILE_PROTOCOL; + +/** + Open the root directory on a volume. + + @param This Protocol instance pointer. + @param Root Returns an Open file handle for the root directory + + @retval EFI_SUCCESS The device was opened. + @retval EFI_UNSUPPORTED This volume does not suppor the file system. + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted + @retval EFI_ACCESS_DENIED The service denied access to the file + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME) ( + IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This, + OUT EFI_FILE **Root + ) +; + +#define EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION 0x00010000 + +struct _EFI_SIMPLE_FILE_SYSTEM_PROTOCOL { + UINT64 Revision; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_OPEN_VOLUME OpenVolume; +}; + +/** + Open the root directory on a volume. + + @param This Protocol instance pointer. + @param NewHandle Returns File Handle for FileName + @param FileName Null terminated string. "\", ".", and ".." are supported + @param OpenMode Open mode for file. + @param Attributes Only used for EFI_FILE_MODE_CREATE + + @retval EFI_SUCCESS The device was opened. + @retval EFI_NOT_FOUND The specified file could not be found on the device + @retval EFI_NO_MEDIA The device has no media. + @retval EFI_MEDIA_CHANGED The media has changed + @retval EFI_DEVICE_ERROR The device reported an error. + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted + @retval EFI_ACCESS_DENIED The service denied access to the file + @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources + @retval EFI_VOLUME_FULL The volume is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_OPEN) ( + IN EFI_FILE *This, + OUT EFI_FILE **NewHandle, + IN CHAR16 *FileName, + IN UINT64 OpenMode, + IN UINT64 Attributes + ) +; + +// +// Open modes +// +#define EFI_FILE_MODE_READ 0x0000000000000001ULL +#define EFI_FILE_MODE_WRITE 0x0000000000000002ULL +#define EFI_FILE_MODE_CREATE 0x8000000000000000ULL + +// +// File attributes +// +#define EFI_FILE_READ_ONLY 0x0000000000000001ULL +#define EFI_FILE_HIDDEN 0x0000000000000002ULL +#define EFI_FILE_SYSTEM 0x0000000000000004ULL +#define EFI_FILE_RESERVED 0x0000000000000008ULL +#define EFI_FILE_DIRECTORY 0x0000000000000010ULL +#define EFI_FILE_ARCHIVE 0x0000000000000020ULL +#define EFI_FILE_VALID_ATTR 0x0000000000000037ULL + +/** + Close the file handle + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was opened. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_CLOSE) ( + IN EFI_FILE *This + ) +; + +/** + Close and delete the file handle + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The device was opened. + @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_DELETE) ( + IN EFI_FILE *This + ) +; + +/** + Read data from the file. + + @param This Protocol instance pointer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer in which data is read. + + @retval EFI_SUCCESS Data was read. + @retval EFI_NO_MEDIA The device has no media + @retval EFI_DEVICE_ERROR The device reported an error + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted + @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_READ) ( + IN EFI_FILE *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +; + +/** + Write data from to the file. + + @param This Protocol instance pointer. + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer in which data to write. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORT Writes to Open directory are not supported + @retval EFI_NO_MEDIA The device has no media + @retval EFI_DEVICE_ERROR The device reported an error + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted + @retval EFI_WRITE_PROTECTED The device is write protected + @retval EFI_ACCESS_DENIED The file was open for read only + @retval EFI_VOLUME_FULL The volume is full + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_WRITE) ( + IN EFI_FILE *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +; + +/** + Set a files current position + + @param This Protocol instance pointer. + @param Position Byte possition from the start of the file + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_SET_POSITION) ( + IN EFI_FILE *This, + IN UINT64 Position + ) +; + +/** + Get a files current position + + @param This Protocol instance pointer. + @param Position Byte possition from the start of the file + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_GET_POSITION) ( + IN EFI_FILE *This, + OUT UINT64 *Position + ) +; + +/** + Get information about a file + + @param This Protocol instance pointer. + @param InformationType Type of info to return in Buffer + @param BufferSize On input size of buffer, on output amount of data in buffer. + @param Buffer The buffer to return data. + + @retval EFI_SUCCESS Data was returned. + @retval EFI_UNSUPPORT InformationType is not supported + @retval EFI_NO_MEDIA The device has no media + @retval EFI_DEVICE_ERROR The device reported an error + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted + @retval EFI_WRITE_PROTECTED The device is write protected + @retval EFI_ACCESS_DENIED The file was open for read only + @retval EFI_BUFFER_TOO_SMALL Buffer was too small, required size returned in BufferSize + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_GET_INFO) ( + IN EFI_FILE *This, + IN EFI_GUID *InformationType, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +; + +/** + Set information about a file + + @param File Protocol instance pointer. + @param InformationType Type of info in Buffer + @param BufferSize Size of buffer. + @param Buffer The data to write. + + @retval EFI_SUCCESS Data was returned. + @retval EFI_UNSUPPORT InformationType is not supported + @retval EFI_NO_MEDIA The device has no media + @retval EFI_DEVICE_ERROR The device reported an error + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted + @retval EFI_WRITE_PROTECTED The device is write protected + @retval EFI_ACCESS_DENIED The file was open for read only + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_SET_INFO) ( + IN EFI_FILE *This, + IN EFI_GUID *InformationType, + IN UINTN BufferSize, + IN VOID *Buffer + ) +; + +/** + Flush data back for the file handle + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS Data was written. + @retval EFI_UNSUPPORT Writes to Open directory are not supported + @retval EFI_NO_MEDIA The device has no media + @retval EFI_DEVICE_ERROR The device reported an error + @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted + @retval EFI_WRITE_PROTECTED The device is write protected + @retval EFI_ACCESS_DENIED The file was open for read only + @retval EFI_VOLUME_FULL The volume is full + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FILE_FLUSH) ( + IN EFI_FILE *This + ) +; + +#define EFI_FILE_HANDLE_REVISION 0x00010000 +#define EFI_FILE_PROTOCOL_REVISION EFI_FILE_HANDLE_REVISION + +struct _EFI_FILE { + UINT64 Revision; + EFI_FILE_OPEN Open; + EFI_FILE_CLOSE Close; + EFI_FILE_DELETE Delete; + EFI_FILE_READ Read; + EFI_FILE_WRITE Write; + EFI_FILE_GET_POSITION GetPosition; + EFI_FILE_SET_POSITION SetPosition; + EFI_FILE_GET_INFO GetInfo; + EFI_FILE_SET_INFO SetInfo; + EFI_FILE_FLUSH Flush; +}; + + +extern EFI_GUID gEfiSimpleFileSystemProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SimpleNetwork.h b/MdePkg/Include/Protocol/SimpleNetwork.h new file mode 100644 index 0000000000..0da64bbe53 --- /dev/null +++ b/MdePkg/Include/Protocol/SimpleNetwork.h @@ -0,0 +1,580 @@ +/** @file + Simple Network protocol as defined in the EFI 1.0 specification. + + Basic network device abstraction. + + Rx - Received + Tx - Transmit + MCast - MultiCast + ... + + Copyright (c) 2006, 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. + + Module Name: SimpleNetwork.h + +**/ + +#ifndef __SIMPLE_NETWORK_H__ +#define __SIMPLE_NETWORK_H__ + +#define EFI_SIMPLE_NETWORK_PROTOCOL_GUID \ + { \ + 0xA19832B9, 0xAC25, 0x11D3, {0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } \ + } + +typedef struct _EFI_SIMPLE_NETWORK_PROTOCOL EFI_SIMPLE_NETWORK_PROTOCOL; + +// +// Simple Network Protocol data structures +// +typedef struct { + // + // Total number of frames received. Includes frames with errors and + // dropped frames. + // + UINT64 RxTotalFrames; + + // + // Number of valid frames received and copied into receive buffers. + // + UINT64 RxGoodFrames; + + // + // Number of frames below the minimum length for the media. + // This would be <64 for ethernet. + // + UINT64 RxUndersizeFrames; + + // + // Number of frames longer than the maxminum length for the + // media. This would be >1500 for ethernet. + // + UINT64 RxOversizeFrames; + + // + // Valid frames that were dropped because receive buffers were full. + // + UINT64 RxDroppedFrames; + + // + // Number of valid unicast frames received and not dropped. + // + UINT64 RxUnicastFrames; + + // + // Number of valid broadcast frames received and not dropped. + // + UINT64 RxBroadcastFrames; + + // + // Number of valid mutlicast frames received and not dropped. + // + UINT64 RxMulticastFrames; + + // + // Number of frames w/ CRC or alignment errors. + // + UINT64 RxCrcErrorFrames; + + // + // Total number of bytes received. Includes frames with errors + // and dropped frames. + // + UINT64 RxTotalBytes; + + // + // Transmit statistics. + // + UINT64 TxTotalFrames; + UINT64 TxGoodFrames; + UINT64 TxUndersizeFrames; + UINT64 TxOversizeFrames; + UINT64 TxDroppedFrames; + UINT64 TxUnicastFrames; + UINT64 TxBroadcastFrames; + UINT64 TxMulticastFrames; + UINT64 TxCrcErrorFrames; + UINT64 TxTotalBytes; + + // + // Number of collisions detection on this subnet. + // + UINT64 Collisions; + + // + // Number of frames destined for unsupported protocol. + // + UINT64 UnsupportedProtocol; + +} EFI_NETWORK_STATISTICS; + +typedef enum { + EfiSimpleNetworkStopped, + EfiSimpleNetworkStarted, + EfiSimpleNetworkInitialized, + EfiSimpleNetworkMaxState +} EFI_SIMPLE_NETWORK_STATE; + +#define EFI_SIMPLE_NETWORK_RECEIVE_UNICAST 0x01 +#define EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST 0x02 +#define EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST 0x04 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS 0x08 +#define EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST 0x10 + +#define EFI_SIMPLE_NETWORK_RECEIVE_INTERRUPT 0x01 +#define EFI_SIMPLE_NETWORK_TRANSMIT_INTERRUPT 0x02 +#define EFI_SIMPLE_NETWORK_COMMAND_INTERRUPT 0x04 +#define EFI_SIMPLE_NETWORK_SOFTWARE_INTERRUPT 0x08 + +#define MAX_MCAST_FILTER_CNT 16 +typedef struct { + UINT32 State; + UINT32 HwAddressSize; + UINT32 MediaHeaderSize; + UINT32 MaxPacketSize; + UINT32 NvRamSize; + UINT32 NvRamAccessSize; + UINT32 ReceiveFilterMask; + UINT32 ReceiveFilterSetting; + UINT32 MaxMCastFilterCount; + UINT32 MCastFilterCount; + EFI_MAC_ADDRESS MCastFilter[MAX_MCAST_FILTER_CNT]; + EFI_MAC_ADDRESS CurrentAddress; + EFI_MAC_ADDRESS BroadcastAddress; + EFI_MAC_ADDRESS PermanentAddress; + UINT8 IfType; + BOOLEAN MacAddressChangeable; + BOOLEAN MultipleTxSupported; + BOOLEAN MediaPresentSupported; + BOOLEAN MediaPresent; +} EFI_SIMPLE_NETWORK_MODE; + +// +// Protocol Member Functions +// +/** + Changes the state of a network interface from "stopped" to "started". + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was started. + @retval EFI_ALREADY_STARTED The network interface is already in the started state. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_START) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +; + +/** + Changes the state of a network interface from "started" to "stopped". + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was stopped. + @retval EFI_ALREADY_STARTED The network interface is already in the stopped state. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_STOP) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +; + +/** + Resets a network adapter and allocates the transmit and receive buffers + required by the network interface; optionally, also requests allocation + of additional transmit and receive buffers. + + @param This Protocol instance pointer. + @param ExtraRxBufferSize The size, in bytes, of the extra receive buffer space + that the driver should allocate for the network interface. + Some network interfaces will not be able to use the extra + buffer, and the caller will not know if it is actually + being used. + @param ExtraTxBufferSize The size, in bytes, of the extra transmit buffer space + that the driver should allocate for the network interface. + Some network interfaces will not be able to use the extra + buffer, and the caller will not know if it is actually + being used. + + @retval EFI_SUCCESS The network interface was initialized. + @retval EFI_NOT_STARTED The network interface has not been started + @retval EFI_OUT_OF_RESOURCES There was not enough memory for the transmit and + receive buffers. . + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_INITIALIZE) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN ExtraRxBufferSize OPTIONAL, + IN UINTN ExtraTxBufferSize OPTIONAL + ) +; + +/** + Resets a network adapter and re-initializes it with the parameters that were + provided in the previous call to Initialize(). + + @param This Protocol instance pointer. + @param ExtendedVerification Indicates that the driver may perform a more + exhaustive verification operation of the device + during reset. + + @retval EFI_SUCCESS The network interface was reset. + @retval EFI_NOT_STARTED The network interface has not been started + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_RESET) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +/** + Resets a network adapter and leaves it in a state that is safe for + another driver to initialize. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The network interface was shutdown. + @retval EFI_NOT_STARTED The network interface has not been started + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_SHUTDOWN) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This + ) +; + +/** + Manages the multicast receive filters of a network interface. + + @param This Protocol instance pointer. + @param Enable A bit mask of receive filters to enable on the network interface. + @param Disable A bit mask of receive filters to disable on the network interface. + @param ResetMCastFilter Set to TRUE to reset the contents of the multicast receive + filters on the network interface to their default values. + @param McastFilterCnt Number of multicast HW MAC addresses in the new + MCastFilter list. This value must be less than or equal to + the MCastFilterCnt field of EFI_SIMPLE_NETWORK_MODE. This + field is optional if ResetMCastFilter is TRUE. + @param MCastFilter A pointer to a list of new multicast receive filter HW MAC + addresses. This list will replace any existing multicast + HW MAC address list. This field is optional if + ResetMCastFilter is TRUE. + + @retval EFI_SUCCESS The multicast receive filter list was updated. + @retval EFI_NOT_STARTED The network interface has not been started + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_RECEIVE_FILTERS) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINT32 Enable, + IN UINT32 Disable, + IN BOOLEAN ResetMCastFilter, + IN UINTN MCastFilterCnt OPTIONAL, + IN EFI_MAC_ADDRESS *MCastFilter OPTIONAL + ) +; + +/** + Modifies or resets the current station address, if supported. + + @param This Protocol instance pointer. + @param Reset Flag used to reset the station address to the network interfaces + permanent address. + @param New New station address to be used for the network interface. + + @retval EFI_SUCCESS The network interfaces station address was updated. + @retval EFI_NOT_STARTED The network interface has not been started + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_STATION_ADDRESS) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN Reset, + IN EFI_MAC_ADDRESS *New OPTIONAL + ) +; + +/** + Resets or collects the statistics on a network interface. + + @param This Protocol instance pointer. + @param Reset Set to TRUE to reset the statistics for the network interface. + @param StatisticsSize On input the size, in bytes, of StatisticsTable. On + output the size, in bytes, of the resulting table of + statistics. + @param StatisticsTable A pointer to the EFI_NETWORK_STATISTICS structure that + contains the statistics. + + @retval EFI_SUCCESS The statistics were collected from the network interface. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer + size needed to hold the statistics is returned in + StatisticsSize. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_STATISTICS) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN Reset, + IN OUT UINTN *StatisticsSize OPTIONAL, + OUT EFI_NETWORK_STATISTICS *StatisticsTable OPTIONAL + ) +; + +/** + Converts a multicast IP address to a multicast HW MAC address. + + @param This Protocol instance pointer. + @param IPv6 Set to TRUE if the multicast IP address is IPv6 [RFC 2460]. Set + to FALSE if the multicast IP address is IPv4 [RFC 791]. + @param IP The multicast IP address that is to be converted to a multicast + HW MAC address. + @param MAC The multicast HW MAC address that is to be generated from IP. + + @retval EFI_SUCCESS The multicast IP address was mapped to the multicast + HW MAC address. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_BUFFER_TOO_SMALL The Statistics buffer was too small. The current buffer + size needed to hold the statistics is returned in + StatisticsSize. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN IPv6, + IN EFI_IP_ADDRESS *IP, + OUT EFI_MAC_ADDRESS *MAC + ) +; + +/** + Performs read and write operations on the NVRAM device attached to a + network interface. + + @param This Protocol instance pointer. + @param ReadWrite TRUE for read operations, FALSE for write operations. + @param Offset Byte offset in the NVRAM device at which to start the read or + write operation. This must be a multiple of NvRamAccessSize and + less than NvRamSize. + @param BufferSize The number of bytes to read or write from the NVRAM device. + This must also be a multiple of NvramAccessSize. + @param Buffer A pointer to the data buffer. + + @retval EFI_SUCCESS The NVRAM access was performed. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_NVDATA) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN BOOLEAN ReadWrite, + IN UINTN Offset, + IN UINTN BufferSize, + IN OUT VOID *Buffer + ) +; + +/** + Reads the current interrupt status and recycled transmit buffer status from + a network interface. + + @param This Protocol instance pointer. + @param InterruptStatus A pointer to the bit mask of the currently active interrupts + If this is NULL, the interrupt status will not be read from + the device. If this is not NULL, the interrupt status will + be read from the device. When the interrupt status is read, + it will also be cleared. Clearing the transmit interrupt + does not empty the recycled transmit buffer array. + @param TxBuf Recycled transmit buffer address. The network interface will + not transmit if its internal recycled transmit buffer array + is full. Reading the transmit buffer does not clear the + transmit interrupt. If this is NULL, then the transmit buffer + status will not be read. If there are no transmit buffers to + recycle and TxBuf is not NULL, * TxBuf will be set to NULL. + + @retval EFI_SUCCESS The status of the network interface was retrieved. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_GET_STATUS) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + OUT UINT32 *InterruptStatus OPTIONAL, + OUT VOID **TxBuf OPTIONAL + ) +; + +/** + Places a packet in the transmit queue of a network interface. + + @param This Protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header to be filled in by + the Transmit() function. If HeaderSize is non-zero, then it + must be equal to This->Mode->MediaHeaderSize and the DestAddr + and Protocol parameters must not be NULL. + @param BufferSize The size, in bytes, of the entire packet (media header and + data) to be transmitted through the network interface. + @param Buffer A pointer to the packet (media header followed by data) to be + transmitted. This parameter cannot be NULL. If HeaderSize is zero, + then the media header in Buffer must already be filled in by the + caller. If HeaderSize is non-zero, then the media header will be + filled in by the Transmit() function. + @param SrcAddr The source HW MAC address. If HeaderSize is zero, then this parameter + is ignored. If HeaderSize is non-zero and SrcAddr is NULL, then + This->Mode->CurrentAddress is used for the source HW MAC address. + @param DsetAddr The destination HW MAC address. If HeaderSize is zero, then this + parameter is ignored. + @param Protocol The type of header to build. If HeaderSize is zero, then this + parameter is ignored. See RFC 1700, section "Ether Types", for + examples. + + @retval EFI_SUCCESS The packet was placed on the transmit queue. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_TRANSMIT) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + IN UINTN HeaderSize, + IN UINTN BufferSize, + IN VOID *Buffer, + IN EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + IN EFI_MAC_ADDRESS *DestAddr OPTIONAL, + IN UINT16 *Protocol OPTIONAL + ) +; + +/** + Receives a packet from a network interface. + + @param This Protocol instance pointer. + @param HeaderSize The size, in bytes, of the media header received on the network + interface. If this parameter is NULL, then the media header size + will not be returned. + @param BufferSize On entry, the size, in bytes, of Buffer. On exit, the size, in + bytes, of the packet that was received on the network interface. + @param Buffer A pointer to the data buffer to receive both the media header and + the data. + @param SrcAddr The source HW MAC address. If this parameter is NULL, the + HW MAC source address will not be extracted from the media + header. + @param DsetAddr The destination HW MAC address. If this parameter is NULL, + the HW MAC destination address will not be extracted from the + media header. + @param Protocol The media header type. If this parameter is NULL, then the + protocol will not be extracted from the media header. See + RFC 1700 section "Ether Types" for examples. + + @retval EFI_SUCCESS The received data was stored in Buffer, and BufferSize has + been updated to the number of bytes received. + @retval EFI_NOT_STARTED The network interface has not been started. + @retval EFI_NOT_READY The network interface is too busy to accept this transmit + request. + @retval EFI_BUFFER_TOO_SMALL The BufferSize parameter is too small. + @retval EFI_INVALID_PARAMETER One or more of the parameters has an unsupported value. + @retval EFI_DEVICE_ERROR The command could not be sent to the network interface. + @retval EFI_UNSUPPORTED This function is not supported by the network interface. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_NETWORK_RECEIVE) ( + IN EFI_SIMPLE_NETWORK_PROTOCOL *This, + OUT UINTN *HeaderSize OPTIONAL, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer, + OUT EFI_MAC_ADDRESS *SrcAddr OPTIONAL, + OUT EFI_MAC_ADDRESS *DestAddr OPTIONAL, + OUT UINT16 *Protocol OPTIONAL + ) +; + +#define EFI_SIMPLE_NETWORK_PROTOCOL_REVISION 0x00010000 + +struct _EFI_SIMPLE_NETWORK_PROTOCOL { + UINT64 Revision; + EFI_SIMPLE_NETWORK_START Start; + EFI_SIMPLE_NETWORK_STOP Stop; + EFI_SIMPLE_NETWORK_INITIALIZE Initialize; + EFI_SIMPLE_NETWORK_RESET Reset; + EFI_SIMPLE_NETWORK_SHUTDOWN Shutdown; + EFI_SIMPLE_NETWORK_RECEIVE_FILTERS ReceiveFilters; + EFI_SIMPLE_NETWORK_STATION_ADDRESS StationAddress; + EFI_SIMPLE_NETWORK_STATISTICS Statistics; + EFI_SIMPLE_NETWORK_MCAST_IP_TO_MAC MCastIpToMac; + EFI_SIMPLE_NETWORK_NVDATA NvData; + EFI_SIMPLE_NETWORK_GET_STATUS GetStatus; + EFI_SIMPLE_NETWORK_TRANSMIT Transmit; + EFI_SIMPLE_NETWORK_RECEIVE Receive; + EFI_EVENT WaitForPacket; + EFI_SIMPLE_NETWORK_MODE *Mode; +}; + +extern EFI_GUID gEfiSimpleNetworkProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SimplePointer.h b/MdePkg/Include/Protocol/SimplePointer.h new file mode 100644 index 0000000000..a0e0804074 --- /dev/null +++ b/MdePkg/Include/Protocol/SimplePointer.h @@ -0,0 +1,97 @@ +/** @file + Simple Pointer protocol from the EFI 1.1 specification. + + Abstraction of a very simple pointer device like a mice or tracekballs. + + Copyright (c) 2006, 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. + + Module Name: SimplePointer.h + +**/ + +#ifndef __SIMPLE_POINTER_H__ +#define __SIMPLE_POINTER_H__ + +#define EFI_SIMPLE_POINTER_PROTOCOL_GUID \ + { \ + 0x31878c87, 0xb75, 0x11d5, {0x9a, 0x4f, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_SIMPLE_POINTER_PROTOCOL EFI_SIMPLE_POINTER_PROTOCOL; + +// +// Data structures +// +typedef struct { + INT32 RelativeMovementX; + INT32 RelativeMovementY; + INT32 RelativeMovementZ; + BOOLEAN LeftButton; + BOOLEAN RightButton; +} EFI_SIMPLE_POINTER_STATE; + +typedef struct { + UINT64 ResolutionX; + UINT64 ResolutionY; + UINT64 ResolutionZ; + BOOLEAN LeftButton; + BOOLEAN RightButton; +} EFI_SIMPLE_POINTER_MODE; + +/** + Resets the pointer device hardware. + + @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL + instance. + @param ExtendedVerification Indicates that the driver may perform a more exhaustive + verification operation of the device during reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_POINTER_RESET) ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +/** + Retrieves the current state of a pointer device. + + @param This A pointer to the EFI_SIMPLE_POINTER_PROTOCOL + instance. + @param State A pointer to the state information on the pointer device. + + @retval EFI_SUCCESS The state of the pointer device was returned in State. + @retval EFI_NOT_READY The state of the pointer device has not changed since the last call to + GetState(). + @retval EFI_DEVICE_ERROR A device error occurred while attempting to retrieve the pointer device's + current state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIMPLE_POINTER_GET_STATE) ( + IN EFI_SIMPLE_POINTER_PROTOCOL *This, + IN OUT EFI_SIMPLE_POINTER_STATE *State + ); + +struct _EFI_SIMPLE_POINTER_PROTOCOL { + EFI_SIMPLE_POINTER_RESET Reset; + EFI_SIMPLE_POINTER_GET_STATE GetState; + EFI_EVENT WaitForInput; + EFI_SIMPLE_POINTER_MODE *Mode; +}; + +extern EFI_GUID gEfiSimplePointerProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SimpleTextIn.h b/MdePkg/Include/Protocol/SimpleTextIn.h new file mode 100644 index 0000000000..053ed58b90 --- /dev/null +++ b/MdePkg/Include/Protocol/SimpleTextIn.h @@ -0,0 +1,126 @@ +/** @file + Simple Text In protocol from the EFI 1.0 specification. + + Abstraction of a very simple input device like a keyboard or serial + terminal. + + Copyright (c) 2006, 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. + + Module Name: SimpleTextIn.h + +**/ + +#ifndef __SIMPLE_TEXT_IN_PROTOCOL_H__ +#define __SIMPLE_TEXT_IN_PROTOCOL_H__ + +#define EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID \ + { \ + 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +#define EFI_SIMPLE_INPUT_PROTOCOL_GUID EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID +#define EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID EFI_SIMPLE_TEXT_IN_PROTOCOL_GUID + +typedef struct _EFI_SIMPLE_TEXT_IN_PROTOCOL EFI_SIMPLE_TEXT_IN_PROTOCOL; +typedef struct _EFI_SIMPLE_TEXT_IN_PROTOCOL EFI_SIMPLE_TEXT_INPUT_PROTOCOL; + +// +// Data structures +// +typedef struct { + UINT16 ScanCode; + CHAR16 UnicodeChar; +} EFI_INPUT_KEY; + +// +// Required unicode control chars +// +#define CHAR_NULL 0x0000 +#define CHAR_BACKSPACE 0x0008 +#define CHAR_TAB 0x0009 +#define CHAR_LINEFEED 0x000A +#define CHAR_CARRIAGE_RETURN 0x000D + +// +// EFI Scan codes +// +#define SCAN_NULL 0x0000 +#define SCAN_UP 0x0001 +#define SCAN_DOWN 0x0002 +#define SCAN_RIGHT 0x0003 +#define SCAN_LEFT 0x0004 +#define SCAN_HOME 0x0005 +#define SCAN_END 0x0006 +#define SCAN_INSERT 0x0007 +#define SCAN_DELETE 0x0008 +#define SCAN_PAGE_UP 0x0009 +#define SCAN_PAGE_DOWN 0x000A +#define SCAN_F1 0x000B +#define SCAN_F2 0x000C +#define SCAN_F3 0x000D +#define SCAN_F4 0x000E +#define SCAN_F5 0x000F +#define SCAN_F6 0x0010 +#define SCAN_F7 0x0011 +#define SCAN_F8 0x0012 +#define SCAN_F9 0x0013 +#define SCAN_F10 0x0014 +#define SCAN_F11 0x0015 +#define SCAN_F12 0x0016 +#define SCAN_ESC 0x0017 + +/** + Reset the input device and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The device was reset. + @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_RESET) ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +/** + Reads the next keystroke from the input device. The WaitForKey Event can + be used to test for existance of a keystroke via WaitForEvent () call. + + @param This Protocol instance pointer. + @param Key Driver may perform diagnostics on reset. + + @retval EFI_SUCCESS The keystroke information was returned. + @retval EFI_NOT_READY There was no keystroke data availiable. + @retval EFI_DEVICE_ERROR The keydtroke information was not returned due to + hardware errors. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INPUT_READ_KEY) ( + IN EFI_SIMPLE_TEXT_IN_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +; + +struct _EFI_SIMPLE_TEXT_IN_PROTOCOL { + EFI_INPUT_RESET Reset; + EFI_INPUT_READ_KEY ReadKeyStroke; + EFI_EVENT WaitForKey; +} EFI_SIMPLE_INPUT_PROTOCOL; + +extern EFI_GUID gEfiSimpleTextInProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SimpleTextOut.h b/MdePkg/Include/Protocol/SimpleTextOut.h new file mode 100644 index 0000000000..b568865f18 --- /dev/null +++ b/MdePkg/Include/Protocol/SimpleTextOut.h @@ -0,0 +1,390 @@ +/** @file + Simple Text Out protocol from the EFI 1.0 specification. + + Abstraction of a very simple text based output device like VGA text mode or + a serial terminal. The Simple Text Out protocol instance can represent + a single hardware device or a virtual device that is an agregation + of multiple physical devices. + + Copyright (c) 2006, 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. + + Module Name: SimpleTextOut.h + +**/ + +#ifndef __SIMPLE_TEXT_OUT_H__ +#define __SIMPLE_TEXT_OUT_H__ + +#define EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID \ + { \ + 0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +#define EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID EFI_SIMPLE_TEXT_OUT_PROTOCOL_GUID + +typedef struct _EFI_SIMPLE_TEXT_OUT_PROTOCOL EFI_SIMPLE_TEXT_OUT_PROTOCOL; +typedef struct _EFI_SIMPLE_TEXT_OUT_PROTOCOL EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL; + +// +// Define's for required EFI Unicode Box Draw characters +// +#define BOXDRAW_HORIZONTAL 0x2500 +#define BOXDRAW_VERTICAL 0x2502 +#define BOXDRAW_DOWN_RIGHT 0x250c +#define BOXDRAW_DOWN_LEFT 0x2510 +#define BOXDRAW_UP_RIGHT 0x2514 +#define BOXDRAW_UP_LEFT 0x2518 +#define BOXDRAW_VERTICAL_RIGHT 0x251c +#define BOXDRAW_VERTICAL_LEFT 0x2524 +#define BOXDRAW_DOWN_HORIZONTAL 0x252c +#define BOXDRAW_UP_HORIZONTAL 0x2534 +#define BOXDRAW_VERTICAL_HORIZONTAL 0x253c +#define BOXDRAW_DOUBLE_HORIZONTAL 0x2550 +#define BOXDRAW_DOUBLE_VERTICAL 0x2551 +#define BOXDRAW_DOWN_RIGHT_DOUBLE 0x2552 +#define BOXDRAW_DOWN_DOUBLE_RIGHT 0x2553 +#define BOXDRAW_DOUBLE_DOWN_RIGHT 0x2554 +#define BOXDRAW_DOWN_LEFT_DOUBLE 0x2555 +#define BOXDRAW_DOWN_DOUBLE_LEFT 0x2556 +#define BOXDRAW_DOUBLE_DOWN_LEFT 0x2557 +#define BOXDRAW_UP_RIGHT_DOUBLE 0x2558 +#define BOXDRAW_UP_DOUBLE_RIGHT 0x2559 +#define BOXDRAW_DOUBLE_UP_RIGHT 0x255a +#define BOXDRAW_UP_LEFT_DOUBLE 0x255b +#define BOXDRAW_UP_DOUBLE_LEFT 0x255c +#define BOXDRAW_DOUBLE_UP_LEFT 0x255d +#define BOXDRAW_VERTICAL_RIGHT_DOUBLE 0x255e +#define BOXDRAW_VERTICAL_DOUBLE_RIGHT 0x255f +#define BOXDRAW_DOUBLE_VERTICAL_RIGHT 0x2560 +#define BOXDRAW_VERTICAL_LEFT_DOUBLE 0x2561 +#define BOXDRAW_VERTICAL_DOUBLE_LEFT 0x2562 +#define BOXDRAW_DOUBLE_VERTICAL_LEFT 0x2563 +#define BOXDRAW_DOWN_HORIZONTAL_DOUBLE 0x2564 +#define BOXDRAW_DOWN_DOUBLE_HORIZONTAL 0x2565 +#define BOXDRAW_DOUBLE_DOWN_HORIZONTAL 0x2566 +#define BOXDRAW_UP_HORIZONTAL_DOUBLE 0x2567 +#define BOXDRAW_UP_DOUBLE_HORIZONTAL 0x2568 +#define BOXDRAW_DOUBLE_UP_HORIZONTAL 0x2569 +#define BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE 0x256a +#define BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL 0x256b +#define BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL 0x256c + +// +// EFI Required Block Elements Code Chart +// +#define BLOCKELEMENT_FULL_BLOCK 0x2588 +#define BLOCKELEMENT_LIGHT_SHADE 0x2591 + +// +// EFI Required Geometric Shapes Code Chart +// +#define GEOMETRICSHAPE_UP_TRIANGLE 0x25b2 +#define GEOMETRICSHAPE_RIGHT_TRIANGLE 0x25ba +#define GEOMETRICSHAPE_DOWN_TRIANGLE 0x25bc +#define GEOMETRICSHAPE_LEFT_TRIANGLE 0x25c4 + +// +// EFI Required Arrow shapes +// +#define ARROW_LEFT 0x2190 +#define ARROW_UP 0x2191 +#define ARROW_RIGHT 0x2192 +#define ARROW_DOWN 0x2193 + +// +// EFI Console Colours +// +#define EFI_BLACK 0x00 +#define EFI_BLUE 0x01 +#define EFI_GREEN 0x02 +#define EFI_CYAN (EFI_BLUE | EFI_GREEN) +#define EFI_RED 0x04 +#define EFI_MAGENTA (EFI_BLUE | EFI_RED) +#define EFI_BROWN (EFI_GREEN | EFI_RED) +#define EFI_LIGHTGRAY (EFI_BLUE | EFI_GREEN | EFI_RED) +#define EFI_BRIGHT 0x08 +#define EFI_DARKGRAY (EFI_BRIGHT) +#define EFI_LIGHTBLUE (EFI_BLUE | EFI_BRIGHT) +#define EFI_LIGHTGREEN (EFI_GREEN | EFI_BRIGHT) +#define EFI_LIGHTCYAN (EFI_CYAN | EFI_BRIGHT) +#define EFI_LIGHTRED (EFI_RED | EFI_BRIGHT) +#define EFI_LIGHTMAGENTA (EFI_MAGENTA | EFI_BRIGHT) +#define EFI_YELLOW (EFI_BROWN | EFI_BRIGHT) +#define EFI_WHITE (EFI_BLUE | EFI_GREEN | EFI_RED | EFI_BRIGHT) + +#define EFI_TEXT_ATTR(f, b) ((f) | ((b) << 4)) + +#define EFI_BACKGROUND_BLACK 0x00 +#define EFI_BACKGROUND_BLUE 0x10 +#define EFI_BACKGROUND_GREEN 0x20 +#define EFI_BACKGROUND_CYAN (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN) +#define EFI_BACKGROUND_RED 0x40 +#define EFI_BACKGROUND_MAGENTA (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_RED) +#define EFI_BACKGROUND_BROWN (EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) +#define EFI_BACKGROUND_LIGHTGRAY (EFI_BACKGROUND_BLUE | EFI_BACKGROUND_GREEN | EFI_BACKGROUND_RED) + +// +// We currently define attributes from 0 - 7F for color manipulations +// To internally handle the local display characteristics for a particular character, we are defining +// Bit 7 to signify the local glyph representation for a character. If turned on, glyphs will be +// pulled from the wide glyph database and will display locally as a wide character (16 X 19 versus 8 X 19) +// If bit 7 is off, the narrow glyph database will be used. This does NOT affect information that is sent to +// non-local displays (e.g. serial or LAN consoles). +// +#define EFI_WIDE_ATTRIBUTE 0x80 + +/** + Reset the text output device hardware and optionaly run diagnostics + + @param This Protocol instance pointer. + @param ExtendedVerification Driver may perform more exhaustive verfication + operation of the device during reset. + + @retval EFI_SUCCESS The text output device was reset. + @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and + could not be reset. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_RESET) ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +/** + Write a Unicode string to the output device. + + @param This Protocol instance pointer. + @param String The NULL-terminated Unicode string to be displayed on the output + device(s). All output devices must also support the Unicode + drawing defined in this file. + + @retval EFI_SUCCESS The string was output to the device. + @retval EFI_DEVICE_ERROR The device reported an error while attempting to output + the text. + @retval EFI_UNSUPPORTED The output device's mode is not currently in a + defined text mode. + @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the + characters in the Unicode string could not be + rendered and were skipped. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_STRING) ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *String + ) +; + +/** + Verifies that all characters in a Unicode string can be output to the + target device. + + @param This Protocol instance pointer. + @param String The NULL-terminated Unicode string to be examined for the output + device(s). + + @retval EFI_SUCCESS The device(s) are capable of rendering the output string. + @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be + rendered by one or more of the output devices mapped + by the EFI handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_TEST_STRING) ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN CHAR16 *String + ) +; + +/** + Returns information for an available text mode that the output device(s) + supports. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param Columns Returns the geometry of the text output device for the + requested ModeNumber. + @param Rows Returns the geometry of the text output device for the + requested ModeNumber. + + @retval EFI_SUCCESS The requested mode information was returned. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The mode number was not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_QUERY_MODE) ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +; + +/** + Sets the output device(s) to a specified mode. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to set. + + @retval EFI_SUCCESS The requested text mode was set. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The mode number was not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_SET_MODE) ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +; + +/** + Sets the background and foreground colors for the OutputString () and + ClearScreen () functions. + + @param This Protocol instance pointer. + @param Attribute The attribute to set. Bits 0..3 are the foreground color, and + bits 4..6 are the background color. All other bits are undefined + and must be zero. The valid Attributes are defined in this file. + + @retval EFI_SUCCESS The attribute was set. + @retval EFI_DEVICE_ ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The attribute requested is not defined. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_SET_ATTRIBUTE) ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Attribute + ) +; + +/** + Clears the output device(s) display to the currently selected background + color. + + @param This Protocol instance pointer. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_CLEAR_SCREEN) ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This + ) +; + +/** + Sets the current coordinates of the cursor position + + @param This Protocol instance pointer. + @param Column The position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + @param Row The position to set the cursor to. Must be greater than or + equal to zero and less than the number of columns and rows + by QueryMode (). + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the + cursor position is invalid for the current mode. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_SET_CURSOR_POSITION) ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +; + +/** + Makes the cursor visible or invisible + + @param This Protocol instance pointer. + @param Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is + set to be invisible. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the + request, or the device does not support changing + the cursor mode. + @retval EFI_UNSUPPORTED The output device is not in a valid text mode. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TEXT_ENABLE_CURSOR) ( + IN EFI_SIMPLE_TEXT_OUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +; + +/** + Mode Structure pointed to by Simple Text Out protocol. + + MaxMode - The number of modes supported by QueryMode () and SetMode (). + Mode - The text mode of the output device(s). + Attribute - The current character output attribute + CursorColumn - The cursor's column. + CursorRow - The cursor's row. + CursorVisible - The cursor is currently visbile or not. + +**/ +typedef struct { + INT32 MaxMode; + + // + // current settings + // + INT32 Mode; + INT32 Attribute; + INT32 CursorColumn; + INT32 CursorRow; + BOOLEAN CursorVisible; +} EFI_SIMPLE_TEXT_OUTPUT_MODE; + +struct _EFI_SIMPLE_TEXT_OUT_PROTOCOL { + EFI_TEXT_RESET Reset; + + EFI_TEXT_STRING OutputString; + EFI_TEXT_TEST_STRING TestString; + + EFI_TEXT_QUERY_MODE QueryMode; + EFI_TEXT_SET_MODE SetMode; + EFI_TEXT_SET_ATTRIBUTE SetAttribute; + + EFI_TEXT_CLEAR_SCREEN ClearScreen; + EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition; + EFI_TEXT_ENABLE_CURSOR EnableCursor; + + // + // Current mode + // + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; +}; + +extern EFI_GUID gEfiSimpleTextOutProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Smbus.h b/MdePkg/Include/Protocol/Smbus.h new file mode 100644 index 0000000000..8fe37b17d3 --- /dev/null +++ b/MdePkg/Include/Protocol/Smbus.h @@ -0,0 +1,237 @@ +/** @file + This file declares the EFI SMBus Host Controller protocol + + Copyright (c) 2006, 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. + + Module Name: Smbus.h + + @par Revision Reference: + This protocol is defined in Framework of EFI SMBus Host Controller Specification + Version 0.9 + +**/ + +#ifndef _EFI_SMBUS_H +#define _EFI_SMBUS_H + +#define EFI_SMBUS_HC_PROTOCOL_GUID \ + { \ + 0xe49d33ed, 0x513d, 0x4634, {0xb6, 0x98, 0x6f, 0x55, 0xaa, 0x75, 0x1c, 0x1b } \ + } + +typedef struct _EFI_SMBUS_HC_PROTOCOL EFI_SMBUS_HC_PROTOCOL; + +/** + Executes an SMBus operation to an SMBus controller. + + @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance. + + @param SlaveAddress The SMBus slave address of the device with which to communicate. + + @param Command This command is transmitted by the SMBus host + controller to the SMBus slave device and the interpretation is + SMBus slave device specific. + + @param Operation Signifies which particular SMBus hardware protocol + instance that it will use to execute the SMBus transactions. + + @param PecCheck Defines if Packet Error Code (PEC) checking is required + for this operation. + + @param Length Signifies the number of bytes that this operation will do. + + @param Buffer Contains the value of data to execute to the SMBus slave device. + + @retval EFI_SUCCESS The last data that was returned from the access + matched the poll exit criteria. + + @retval EFI_CRC_ERROR The checksum is not correct (PEC is incorrect) + + @retval EFI_TIMEOUT Timeout expired before the operation was completed. + Timeout is determined by the SMBus host controller device. + + @retval EFI_OUT_OF_RESOURCES The request could not be completed + due to a lack of resources. + + @retval EFI_DEVICE_ERROR The request was not completed because + a failure reflected in the Host Status Register bit. + + @retval EFI_INVALID_PARAMETER Operation is not defined in EFI_SMBUS_OPERATION. + Or Length/Buffer is NULL for operations except for EfiSmbusQuickRead and + EfiSmbusQuickWrite. Length is outside the range of valid values. + + @retval EFI_UNSUPPORTED The SMBus operation or PEC is not supported. + + @retval EFI_BUFFER_TOO_SMALL Buffer is not sufficient for this operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBUS_HC_EXECUTE_OPERATION) ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN EFI_SMBUS_DEVICE_COMMAND Command, + IN EFI_SMBUS_OPERATION Operation, + IN BOOLEAN PecCheck, + IN OUT UINTN *Length, + IN OUT VOID *Buffer + ); + +typedef struct { + UINT32 VendorSpecificId; + UINT16 SubsystemDeviceId; + UINT16 SubsystemVendorId; + UINT16 Interface; + UINT16 DeviceId; + UINT16 VendorId; + UINT8 VendorRevision; + UINT8 DeviceCapabilities; +} EFI_SMBUS_UDID; + +/** + CallBack function can be registered in EFI_SMBUS_HC_PROTOCOL_NOTIFY. + + @param SlaveAddress The SMBUS hardware address to which the SMBUS + device is preassigned or allocated. + + @param Data Data of the SMBus host notify command that + the caller wants to be called. + + @return Status Code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBUS_NOTIFY_FUNCTION) ( + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data + ); + +/** + Sets the SMBus slave device addresses for the device with a given unique ID + or enumerates the entire bus. + + @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance. + + @param ArpAll A Boolean expression that indicates if the host drivers need + to enumerate all the devices or enumerate only the device that is identified + by SmbusUdid. If ArpAll is TRUE, SmbusUdid and SlaveAddress are optional. + If ArpAll is FALSE, ArpDevice will enumerate SmbusUdid and the address + will be at SlaveAddress. + + @param SmbusUdid The Unique Device Identifier (UDID) that is associated + with this device. + + @param SlaveAddress The SMBus slave address that is associated with an SMBus UDID. + + @retval EFI_SUCCESS The SMBus slave device address was set. + + @retval EFI_INVALID_PARAMETER SlaveAddress is NULL. + + @retval EFI_OUT_OF_RESOURCES The request could not be completed + due to a lack of resources. + + @retval EFI_TIMEOUT The SMBus slave device did not respond. + + @retval EFI_DEVICE_ERROR The request was not completed because the transaction failed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBUS_HC_PROTOCOL_ARP_DEVICE) ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN BOOLEAN ArpAll, + IN EFI_SMBUS_UDID *SmbusUdid, OPTIONAL + IN OUT EFI_SMBUS_DEVICE_ADDRESS *SlaveAddress OPTIONAL + ); + +typedef struct { + EFI_SMBUS_DEVICE_ADDRESS SmbusDeviceAddress; + EFI_SMBUS_UDID SmbusDeviceUdid; +} EFI_SMBUS_DEVICE_MAP; + +/** + The GetArpMap() function returns the mapping of all the SMBus devices + that are enumerated by the SMBus host driver. + + @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance. + + @param Length Size of the buffer that contains the SMBus device map. + + @param SmbusDeviceMap The pointer to the device map as enumerated + by the SMBus controller driver. + + @retval EFI_SUCCESS The device map was returned correctly in the buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBUS_HC_PROTOCOL_GET_ARP_MAP) ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN OUT UINTN *Length, + IN OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap + ); + +/** + The Notify() function registers all the callback functions to allow the + bus driver to call these functions when the SlaveAddress/Data pair happens. + + @param This A pointer to the EFI_SMBUS_HC_PROTOCOL instance. + + @param SlaveAddress Address that the host controller detects as + sending a message and calls all the registered functions. + + @param Data Data that the host controller detects as sending a message + and calls all the registered functions. + + @param NotifyFunction The function to call when the bus driver + detects the SlaveAddress and Data pair. + + @retval EFI_SUCCESS NotifyFunction was registered. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMBUS_HC_PROTOCOL_NOTIFY) ( + IN EFI_SMBUS_HC_PROTOCOL *This, + IN EFI_SMBUS_DEVICE_ADDRESS SlaveAddress, + IN UINTN Data, + IN EFI_SMBUS_NOTIFY_FUNCTION NotifyFunction + ); + +/** + @par Protocol Description: + Provides basic SMBus host controller management and basic data + transactions over the SMBus. + + @param Execute + Executes the SMBus operation to an SMBus slave device. + + @param ArpDevice + Allows an SMBus 2.0 device(s) to be Address Resolution Protocol (ARP) + + @param GetArpMap + Allows a driver to retrieve the address that was allocated by the SMBus + host controller during enumeration/ARP. + + @param Notify + Allows a driver to register for a callback to the SMBus host + controller driver when the bus issues a notification to the bus controller driver. + +**/ +struct _EFI_SMBUS_HC_PROTOCOL { + EFI_SMBUS_HC_EXECUTE_OPERATION Execute; + EFI_SMBUS_HC_PROTOCOL_ARP_DEVICE ArpDevice; + EFI_SMBUS_HC_PROTOCOL_GET_ARP_MAP GetArpMap; + EFI_SMBUS_HC_PROTOCOL_NOTIFY Notify; +}; + +extern EFI_GUID gEfiSmbusProtocolGuid; +#endif diff --git a/MdePkg/Include/Protocol/SmmAccess.h b/MdePkg/Include/Protocol/SmmAccess.h new file mode 100644 index 0000000000..f405c8f13f --- /dev/null +++ b/MdePkg/Include/Protocol/SmmAccess.h @@ -0,0 +1,172 @@ +/** @file + This file declares SMM SMRAM Access abstraction protocol + + Copyright (c) 2006, 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. + + Module Name: SmmAccess.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. +**/ + +#ifndef _SMM_ACCESS_H_ +#define _SMM_ACCESS_H_ + +typedef struct _EFI_SMM_ACCESS_PROTOCOL EFI_SMM_ACCESS_PROTOCOL; + +#define EFI_SMM_ACCESS_PROTOCOL_GUID \ + { \ + 0x3792095a, 0xe309, 0x4c1e, {0xaa, 0x01, 0x85, 0xf5, 0x65, 0x5a, 0x17, 0xf1 } \ + } + +// +// SMM Access specification constant and types +// +// ******************************************************* +// EFI_SMRAM_STATE +// ******************************************************* +// +#define EFI_SMRAM_OPEN 0x00000001 +#define EFI_SMRAM_CLOSED 0x00000002 +#define EFI_SMRAM_LOCKED 0x00000004 +#define EFI_CACHEABLE 0x00000008 +#define EFI_ALLOCATED 0x00000010 + +// +// SMM Access specification Member Function +// +/** + Opens the SMRAM area to be accessible by a boot-service driver. + + @param This The EFI_SMM_ACCESS_PROTOCOL instance. + + @param DescriptorIndex Indicates that the driver wishes to open + the memory tagged by this index. + + @retval EFI_SUCCESS The operation was successful. + + @retval EFI_INVALID_PARAMETER The given DescriptorIndex is not supported. + + @retval EFI_NOT_STARTED The SMM base service has not been initialized. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_OPEN) ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + UINTN DescriptorIndex + ); + +/** + Inhibits access to the SMRAM. + + @param This The EFI_SMM_ACCESS_PROTOCOL instance. + + @param DescriptorIndex Indicates that the driver wishes to open + the memory tagged by this index. + + @retval EFI_SUCCESS The operation was successful. + + @retval EFI_DEVICE_ERROR The given DescriptorIndex is not open. + + @retval EFI_INVALID_PARAMETER The given DescriptorIndex is not supported. + + @retval EFI_NOT_STARTED The SMM base service has not been initialized. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_CLOSE) ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + UINTN DescriptorIndex + ); + +/** + Inhibits access to the SMRAM. + + @param This The EFI_SMM_ACCESS_PROTOCOL instance. + + @param DescriptorIndex Indicates that the driver wishes to open + the memory tagged by this index. + + @retval EFI_SUCCESS The operation was successful. + + @retval EFI_DEVICE_ERROR The given DescriptorIndex is not open. + + @retval EFI_INVALID_PARAMETER The given DescriptorIndex is not supported. + + @retval EFI_NOT_STARTED The SMM base service has not been initialized. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_LOCK) ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + UINTN DescriptorIndex + ); + +/** + Queries the memory controller for the possible regions that will support SMRAM. + + @param This The EFI_SMM_ACCESS_PROTOCOL instance. + + @param SmramMapSize A pointer to the size, in bytes, of the SmramMemoryMap buffer. + + @param SmramMap A pointer to the buffer in which firmware places the current memory map. + + @retval EFI_SUCCESS The chipset supported the given resource. + + @retval EFI_BUFFER_TOO_SMALL The SmramMap parameter was too small. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_CAPABILITIES) ( + IN EFI_SMM_ACCESS_PROTOCOL *This, + IN OUT UINTN *SmramMapSize, + IN OUT EFI_SMRAM_DESCRIPTOR *SmramMap + ); + +/** + @par Protocol Description: + This protocol is used to control the visibility of the SMRAM on the platform. + + @param Open + Opens the SMRAM. + + @param Close + Closes the SMRAM. + + @param Lock + Locks the SMRAM. + + @param GetCapabilities + Gets information on possible SMRAM regions. + + @param LockState +Indicates the current state of the SMRAM. Set to TRUE if any region is locked. + + @param OpenState +Indicates the current state of the SMRAM. Set to TRUE if any region is open. + +**/ +struct _EFI_SMM_ACCESS_PROTOCOL { + EFI_SMM_OPEN Open; + EFI_SMM_CLOSE Close; + EFI_SMM_LOCK Lock; + EFI_SMM_CAPABILITIES GetCapabilities; + BOOLEAN LockState; + BOOLEAN OpenState; +}; + +extern EFI_GUID gEfiSmmAccessProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SmmBase.h b/MdePkg/Include/Protocol/SmmBase.h new file mode 100644 index 0000000000..6dd3a5dd57 --- /dev/null +++ b/MdePkg/Include/Protocol/SmmBase.h @@ -0,0 +1,310 @@ +/** @file + This file declares SMM Base abstraction protocol. + This is the base level of compatiblity for SMM drivers. + + Copyright (c) 2006, 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. + + Module Name: SmmBase.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. + +**/ + +#ifndef _SMM_BASE_H_ +#define _SMM_BASE_H_ + +#define EFI_SMM_BASE_PROTOCOL_GUID \ + { \ + 0x1390954D, 0xda95, 0x4227, {0x93, 0x28, 0x72, 0x82, 0xc2, 0x17, 0xda, 0xa8 } \ + } + +typedef struct _EFI_SMM_BASE_PROTOCOL EFI_SMM_BASE_PROTOCOL; + +// +// SMM Handler Definition +// +#define EFI_HANDLER_SUCCESS 0x0000 +#define EFI_HANDLER_CRITICAL_EXIT 0x0001 +#define EFI_HANDLER_SOURCE_QUIESCED 0x0002 +#define EFI_HANDLER_SOURCE_PENDING 0x0003 + +/** + Entry Point to Callback service + + @param SmmImageHandle A handle allocated by the SMM infrastructure code + to uniquely designate a specific DXE SMM driver. + + @param CommunicationBuffer A pointer to a collection of data in memory + that will be conveyed from a non-SMM environment into an SMM environment. + The buffer must be contiguous, physically mapped, and be a physical address. + + @param SourceSize The size of the CommunicationBuffer. + + @return Status code + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_CALLBACK_ENTRY_POINT) ( + IN EFI_HANDLE SmmImageHandle, + IN OUT VOID *CommunicationBuffer OPTIONAL, + IN OUT UINTN *SourceSize OPTIONAL + ); + +// +// SMM Base Protocol Definition +// +/** + Register a given driver into SMRAM.This is the equivalent of performing + the LoadImage/StartImage into System Management Mode. + + @param This Protocol instance pointer. + @param FilePath Location of the image to be installed as the handler. + @param SourceBuffer Optional source buffer in case of the image file + being in memory. + @param SourceSize Size of the source image file, if in memory. + @param ImageHandle Pointer to the handle that reflects the driver + loaded into SMM. + @param LegacyIA32Binary The binary image to load is legacy 16 bit code. + + @retval EFI_SUCCESS The operation was successful. + @retval EFI_OUT_OF_RESOURCES There were no additional SMRAM resources to load the handler + @retval EFI_UNSUPPORTED This platform does not support 16-bit handlers. + @retval EFI_UNSUPPORTED In runtime. + @retval EFI_INVALID_PARAMETER The handlers was not the correct image type + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_REGISTER_HANDLER) ( + IN EFI_SMM_BASE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + OUT EFI_HANDLE *ImageHandle, + IN BOOLEAN LegacyIA32Binary OPTIONAL + ) +; + +/** + Remove a given driver SMRAM. This is the equivalent of performing + the UnloadImage System Management Mode. + + @param This Protocol instance pointer. + @param ImageHandle Pointer to the handle that reflects the driver + loaded into SMM. + + @retval EFI_SUCCESS The operation was successful + @retval EFI_INVALID_PARAMETER The handler did not exist + @retval EFI_UNSUPPORTED In runtime. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_UNREGISTER_HANDLER) ( + IN EFI_SMM_BASE_PROTOCOL *This, + IN EFI_HANDLE ImageHandle + ) +; + +/** + The SMM Inter-module Communicate Service Communicate() function + provides a services to send/received messages from a registered + EFI service. The BASE protocol driver is responsible for doing + any of the copies such that the data lives in boot-service accessible RAM. + + @param This Protocol instance pointer. + @param ImageHandle Pointer to the handle that reflects the driver + loaded into SMM. + @param CommunicationBuffer Pointer to the buffer to convey into SMRAM. + @param SourceSize Size of the contents of buffer.. + + @retval EFI_SUCCESS The message was successfully posted + @retval EFI_INVALID_PARAMETER The buffer was NULL + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_COMMUNICATE) ( + IN EFI_SMM_BASE_PROTOCOL *This, + IN EFI_HANDLE ImageHandle, + IN OUT VOID *CommunicationBuffer, + IN OUT UINTN *SourceSize + ) +; + +/** + Register a callback to execute within SMM. + This allows receipt of messages created with the Boot Service COMMUNICATE. + + @param This Protocol instance pointer. + @param CallbackAddress Address of the callback service + @param MakeFirst If present, will stipulate that the handler is posted + to be the first module executed in the dispatch table. + @param MakeLast If present, will stipulate that the handler is posted + to be last executed in the dispatch table. + @param FloatingPointSave This is an optional parameter which informs the + EFI_SMM_ACCESS_PROTOCOL Driver core if it needs to save + the floating point register state. If any of the handlers + require this, then the state will be saved for all of the handlers. + + @retval EFI_SUCCESS The operation was successful + @retval EFI_OUT_OF_RESOURCES Not enough space in the dispatch queue + @retval EFI_UNSUPPORTED In runtime. + @retval EFI_UNSUPPORTED Not in SMM. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_CALLBACK_SERVICE) ( + IN EFI_SMM_BASE_PROTOCOL *This, + IN EFI_HANDLE SmmImageHandle, + IN EFI_SMM_CALLBACK_ENTRY_POINT CallbackAddress, + IN BOOLEAN MakeLast OPTIONAL, + IN BOOLEAN FloatingPointSave OPTIONAL + ) +; + +/** + The SmmAllocatePool() function allocates a memory region of Size bytes from memory of + type PoolType and returns the address of the allocated memory in the location referenced + by Buffer. This function allocates pages from EFI SMRAM Memory as needed to grow the + requested pool type. All allocations are eight-byte aligned. + + @param This Protocol instance pointer. + @param PoolType The type of pool to allocate. + The only supported type is EfiRuntimeServicesData; + the interface will internally map this runtime request to SMRAM. + @param Size The number of bytes to allocate from the pool. + @param Buffer A pointer to a pointer to the allocated buffer if the call + succeeds; undefined otherwise. + + @retval EFI_SUCCESS The requested number of bytes was allocated. + @retval EFI_OUT_OF_RESOURCES The pool requested could not be allocated. + @retval EFI_INVALID_PARAMETER PoolType was invalid. + @retval EFI_UNSUPPORTED In runtime. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_ALLOCATE_POOL) ( + IN EFI_SMM_BASE_PROTOCOL *This, + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ) +; + +/** + The SmmFreePool() function returns the memory specified by Buffer to the system. + On return, the memory's type is EFI SMRAM Memory. The Buffer that is freed must + have been allocated by SmmAllocatePool(). + + @param This Protocol instance pointer. + @param Buffer Pointer to the buffer allocation. + + @retval EFI_SUCCESS The memory was returned to the system. + @retval EFI_INVALID_PARAMETER Buffer was invalid. + @retval EFI_UNSUPPORTED In runtime. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_FREE_POOL) ( + IN EFI_SMM_BASE_PROTOCOL *This, + IN VOID *Buffer + ) +; + +/** + This routine tells caller if execution context is SMM or not. + + @param This Protocol instance pointer. + @param InSmm Whether the caller is inside SMM for IA-32 or servicing a PMI for the Itanium processor family. + + @retval EFI_SUCCESS The operation was successful + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_INSIDE_OUT) ( + IN EFI_SMM_BASE_PROTOCOL *This, + OUT BOOLEAN *InSmm + ) +; + +/** + The GetSmstLocation() function returns the locatin of the System Management + Service Table. The use of the API is such that a driver can discover the + location of the SMST in its entry point and then cache it in some driver + global variable so that the SMST can be invoked in subsequent callbacks. + + @param This Protocol instance pointer. + @param Smst Pointer to the SMST. + + @retval EFI_SUCCESS The operation was successful + @retval EFI_INVALID_PARAMETER Smst was invalid. + @retval EFI_UNSUPPORTED Not in SMM. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_GET_SMST_LOCATION) ( + IN EFI_SMM_BASE_PROTOCOL *This, + IN OUT EFI_SMM_SYSTEM_TABLE **Smst + ) +; + +/** + @par Protocol Description: + This protocol is used to install SMM handlers for support of subsequent SMI/PMI + activations. This protocol is available on both IA-32 and Itanium-based systems. + + @param Register + Registers a handler to run in System Management RAM (SMRAM). + + @param UnRegister + Removes a handler from execution in SMRAM. + + @param Communicate + Sends/receives a message for a registered handler. + + @param RegisterCallback + Registers a callback from the constructor. + + @param InSmm + Detects whether the caller is inside or outside of SMM. SName + + @param SmmAllocatePool + Allocates SMRAM. + + @param SmmFreePool + Deallocates SMRAM. + + @param GetSmstLocation + Retrieves the location of the System Management System Table (SMST). + +**/ +struct _EFI_SMM_BASE_PROTOCOL { + EFI_SMM_REGISTER_HANDLER Register; + EFI_SMM_UNREGISTER_HANDLER UnRegister; + EFI_SMM_COMMUNICATE Communicate; + EFI_SMM_CALLBACK_SERVICE RegisterCallback; + EFI_SMM_INSIDE_OUT InSmm; + EFI_SMM_ALLOCATE_POOL SmmAllocatePool; + EFI_SMM_FREE_POOL SmmFreePool; + EFI_SMM_GET_SMST_LOCATION GetSmstLocation; +}; + +extern EFI_GUID gEfiSmmBaseProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SmmControl.h b/MdePkg/Include/Protocol/SmmControl.h new file mode 100644 index 0000000000..3bcd0f772e --- /dev/null +++ b/MdePkg/Include/Protocol/SmmControl.h @@ -0,0 +1,139 @@ +/** @file + This file declares SMM Control abstraction protocol. + + Copyright (c) 2006, 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. + + Module Name: SmmControl.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. + +**/ + +#ifndef _SMM_CONTROL_H_ +#define _SMM_CONTROL_H_ + +typedef struct _EFI_SMM_CONTROL_PROTOCOL EFI_SMM_CONTROL_PROTOCOL; + +#define EFI_SMM_CONTROL_PROTOCOL_GUID \ + { \ + 0x8d12e231, 0xc667, 0x4fd1, {0x98, 0xf2, 0x24, 0x49, 0xa7, 0xe7, 0xb2, 0xe5 } \ + } + +// SMM Access specification Data Structures +// +typedef struct { + UINT8 SmiTriggerRegister; + UINT8 SmiDataRegister; +} EFI_SMM_CONTROL_REGISTER; + +// +// SMM Control specification member function +// +/** + Invokes SMI activation from either the preboot or runtime environment. + + @param This The EFI_SMM_CONTROL_PROTOCOL instance. + + @param ArgumentBuffer Optional sized data to pass into the protocol activation. + + @param ArgumentBufferSize Optional size of the data. + + @param Periodic Optional mechanism to engender a periodic stream. + + @param ActivationInterval Optional parameter to repeat at this period one + time or, if the Periodic Boolean is set, periodically. + + @retval EFI_SUCCESS The SMI/PMI has been engendered. + + @retval EFI_DEVICE_ERROR The timing is unsupported. + + @retval EFI_INVALID_PARAMETER The activation period is unsupported. + + @retval EFI_NOT_STARTED The SMM base service has not been initialized. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_ACTIVATE) ( + IN EFI_SMM_CONTROL_PROTOCOL *This, + IN OUT INT8 *ArgumentBuffer OPTIONAL, + IN OUT UINTN *ArgumentBufferSize OPTIONAL, + IN BOOLEAN Periodic OPTIONAL, + IN UINTN ActivationInterval OPTIONAL + ); + +/** + Clears any system state that was created in response to the Active call. + + @param This The EFI_SMM_CONTROL_PROTOCOL instance. + + @param Periodic Optional parameter to repeat at this period one time + + @retval EFI_SUCCESS The SMI/PMI has been engendered. + + @retval EFI_DEVICE_ERROR The source could not be cleared. + + @retval EFI_INVALID_PARAMETER The service did not support the Periodic input argument. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_DEACTIVATE) ( + IN EFI_SMM_CONTROL_PROTOCOL *This, + IN BOOLEAN Periodic OPTIONAL + ); + +/** + Provides information on the source register used to generate the SMI. + + @param This The EFI_SMM_CONTROL_PROTOCOL instance. + + @param SmiRegister Pointer to the SMI register description structure + + @retval EFI_SUCCESS The register structure has been returned. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_GET_REGISTER_INFO) ( + IN EFI_SMM_CONTROL_PROTOCOL *This, + IN OUT EFI_SMM_CONTROL_REGISTER *SmiRegister + ); + +/** + @par Protocol Description: + This protocol is used initiate SMI/PMI activations. + + @param Trigger + Initiates the SMI/PMI activation. + + @param Clear + Quiesces the SMI/PMI activation. + + @param GetRegisterInfo + Provides data on the register used as the source of the SMI. + + @param MinimumTriggerPeriod + Minimum interval at which the platform can set the period. + +**/ + +struct _EFI_SMM_CONTROL_PROTOCOL { + EFI_SMM_ACTIVATE Trigger; + EFI_SMM_DEACTIVATE Clear; + EFI_SMM_GET_REGISTER_INFO GetRegisterInfo; + UINTN MinimumTriggerPeriod; +}; + +extern EFI_GUID gEfiSmmControlProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SmmGpiDispatch.h b/MdePkg/Include/Protocol/SmmGpiDispatch.h new file mode 100644 index 0000000000..b472e92c5a --- /dev/null +++ b/MdePkg/Include/Protocol/SmmGpiDispatch.h @@ -0,0 +1,150 @@ +/** @file + This file declares Smm Gpi Smi Child Protocol + + Copyright (c) 2006, 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. + + Module Name: SmmGpiDispatch.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. + +**/ + +#ifndef _EFI_SMM_GPI_DISPATCH_H_ +#define _EFI_SMM_GPI_DISPATCH_H_ + +// +// Global ID for the GPI SMI Protocol +// +#define EFI_SMM_GPI_DISPATCH_PROTOCOL_GUID \ + { \ + 0xe0744b81, 0x9513, 0x49cd, {0x8c, 0xea, 0xe9, 0x24, 0x5e, 0x70, 0x39, 0xda } \ + } + +typedef struct _EFI_SMM_GPI_DISPATCH_PROTOCOL EFI_SMM_GPI_DISPATCH_PROTOCOL; + +// +// Related Definitions +// +// +// GpiMask is a bit mask of 32 possible general purpose inputs that can generate a +// a SMI. Bit 0 corresponds to logical GPI[0], 1 corresponds to logical GPI[1], etc. +// +// The logical GPI index to physical pin on device is described by the GPI device name +// found on the same handle as the GpiSmi child dispatch protocol. The GPI device name +// is defined as protocol with a GUID name and NULL protocol pointer. +// +typedef struct { + UINTN GpiNum; +} EFI_SMM_GPI_DISPATCH_CONTEXT; + +// +// Member functions +// +/** + Dispatch function for a GPI SMI handler. + + @param DispatchHandle Handle of this dispatch function. + @param DispatchContext Pointer to the dispatch function's context. + The DispatchContext fields are filled in by the dispatching driver prior to + invoking this dispatch function. + + @return None + +**/ +typedef +VOID +(EFIAPI *EFI_SMM_GPI_DISPATCH) ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_GPI_DISPATCH_CONTEXT *DispatchContext + ); + +/** + Register a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchFunction Pointer to dispatch function to be invoked for + this SMI source + @param DispatchContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function the GPI(s) for which the dispatch function + should be invoked. + @param DispatchHandle Handle of dispatch function, for when interfacing + with the parent Sx state SMM driver. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source. + @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this + child. + @retval EFI_INVALID_PARAMETER DispatchContext is invalid. The GPI input value + is not within valid range. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_GPI_REGISTER) ( + IN EFI_SMM_GPI_DISPATCH_PROTOCOL *This, + IN EFI_SMM_GPI_DISPATCH DispatchFunction, + IN EFI_SMM_GPI_DISPATCH_CONTEXT *DispatchContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully + unregistered and the SMI source has been disabled + if there are no other registered child dispatch + functions for this SMI source. + @retval EFI_INVALID_PARAMETER Handle is invalid. + @retval other TBD + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_GPI_UNREGISTER) ( + IN EFI_SMM_GPI_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +// +// Interface structure for the SMM GPI SMI Dispatch Protocol +// +/** + @par Protocol Description: + Provides the parent dispatch service for the General Purpose Input + (GPI) SMI source generator. + + @param Register + Installs a child service to be dispatched by this protocol. + + @param UnRegister + Removes a child service dispatched by this protocol. + + @param NumSupportedGpis + Denotes the maximum value of inputs that can have handlers attached. + +**/ +struct _EFI_SMM_GPI_DISPATCH_PROTOCOL { + EFI_SMM_GPI_REGISTER Register; + EFI_SMM_GPI_UNREGISTER UnRegister; + UINTN NumSupportedGpis; +}; + +extern EFI_GUID gEfiSmmGpiDispatchProtocolGuid; + +#endif + diff --git a/MdePkg/Include/Protocol/SmmIchnDispatch.h b/MdePkg/Include/Protocol/SmmIchnDispatch.h new file mode 100644 index 0000000000..8829f85489 --- /dev/null +++ b/MdePkg/Include/Protocol/SmmIchnDispatch.h @@ -0,0 +1,193 @@ +/** @file + This file declares EFI Smm ICH [N] Specific Smi Child Protocol + + Copyright (c) 2006, 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. + + Module Name: SmmIchnDispatch.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. + +**/ + +#ifndef _EFI_SMM_ICHN_DISPATCH_H_ +#define _EFI_SMM_ICHN_DISPATCH_H_ + +// +// Global ID for the ICH SMI Protocol +// +#define EFI_SMM_ICHN_DISPATCH_PROTOCOL_GUID \ + { \ + 0xc50b323e, 0x9075, 0x4f2a, {0xac, 0x8e, 0xd2, 0x59, 0x6a, 0x10, 0x85, 0xcc } \ + } + +typedef struct _EFI_SMM_ICHN_DISPATCH_PROTOCOL EFI_SMM_ICHN_DISPATCH_PROTOCOL; + +// +// Related Definitions +// +// +// ICHN Specific SMIs. These are miscellaneous SMI sources that are supported by the +// ICHN specific SMI implementation. These may change over time. TrapNumber is only +// valid if the Type is Trap. +// +typedef enum { + // + // NOTE: NEVER delete items from this list/enumeration! Doing so will prevent other versions + // of the code from compiling. If the ICH version your driver is written for doesn't support + // some of these SMIs, then simply return EFI_UNSUPPORTED when a child/client tries to register + // for them. + // + IchnMch, + IchnPme, + IchnRtcAlarm, + IchnRingIndicate, + IchnAc97Wake, + IchnSerialIrq, + IchnY2KRollover, + IchnTcoTimeout, + IchnOsTco, + IchnNmi, + IchnIntruderDetect, + IchnBiosWp, + IchnMcSmi, + IchnPmeB0, + IchnThrmSts, + IchnSmBus, + IchnIntelUsb2, + IchnMonSmi7, + IchnMonSmi6, + IchnMonSmi5, + IchnMonSmi4, + IchnDevTrap13, + IchnDevTrap12, + IchnDevTrap11, + IchnDevTrap10, + IchnDevTrap9, + IchnDevTrap8, + IchnDevTrap7, + IchnDevTrap6, + IchnDevTrap5, + IchnDevTrap3, + IchnDevTrap2, + IchnDevTrap1, + IchnDevTrap0, + IchnIoTrap3, + IchnIoTrap2, + IchnIoTrap1, + IchnIoTrap0, + // + // INSERT NEW ITEMS JUST BEFORE THIS LINE + // + NUM_ICHN_TYPES // the number of items in this enumeration +} EFI_SMM_ICHN_SMI_TYPE; + +typedef struct { + EFI_SMM_ICHN_SMI_TYPE Type; +} EFI_SMM_ICHN_DISPATCH_CONTEXT; + +// +// Member functions +// +/** + Dispatch function for a ICH n specific SMI handler. + + @param DispatchHandle Handle of this dispatch function. + @param DispatchContext Pointer to the dispatch function's context. + The DispatchContext fields are filled in + by the dispatching driver prior to + invoking this dispatch function. + + Nothing + +**/ +typedef +VOID +(EFIAPI *EFI_SMM_ICHN_DISPATCH) ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_ICHN_DISPATCH_CONTEXT *DispatchContext + ); + +/** + Register a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchFunction Pointer to dispatch function to be invoked for + this SMI source + @param DispatchContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function the ICHN SMI source for which the dispatch + function should be invoked. + @param DispatchHandle Handle of dispatch function, for when interfacing + with the parent Sx state SMM driver. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source. + @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this + child. + @retval EFI_INVALID_PARAMETER DispatchContext is invalid. The ICHN input value + is not within valid range. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_ICHN_REGISTER) ( + IN EFI_SMM_ICHN_DISPATCH_PROTOCOL *This, + IN EFI_SMM_ICHN_DISPATCH DispatchFunction, + IN EFI_SMM_ICHN_DISPATCH_CONTEXT *DispatchContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully + unregistered and the SMI source has been disabled + if there are no other registered child dispatch + functions for this SMI source. + @retval EFI_INVALID_PARAMETER Handle is invalid. + @retval other TBD + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_ICHN_UNREGISTER) ( + IN EFI_SMM_ICHN_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +// +// Interface structure for the SMM Ich n specific SMI Dispatch Protocol +// +/** + @par Protocol Description: + Provides the parent dispatch service for a given SMI source generator. + + @param Register + Installs a child service to be dispatched by this protocol. + + @param UnRegister + Removes a child service dispatched by this protocol. + +**/ +struct _EFI_SMM_ICHN_DISPATCH_PROTOCOL { + EFI_SMM_ICHN_REGISTER Register; + EFI_SMM_ICHN_UNREGISTER UnRegister; +}; + +extern EFI_GUID gEfiSmmIchnDispatchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SmmPeriodicTimerDispatch.h b/MdePkg/Include/Protocol/SmmPeriodicTimerDispatch.h new file mode 100644 index 0000000000..c94843fcca --- /dev/null +++ b/MdePkg/Include/Protocol/SmmPeriodicTimerDispatch.h @@ -0,0 +1,194 @@ +/** @file + This file declares EFI Smm Periodic Timer Smi Child Protocol + + Copyright (c) 2006, 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. + + Module Name: SmmPeriodicTimerDispatch.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. + +**/ + +#ifndef _EFI_SMM_PERIODIC_TIMER_DISPATCH_H_ +#define _EFI_SMM_PERIODIC_TIMER_DISPATCH_H_ + +// +// Global ID for the Periodic Timer SMI Protocol +// +#define EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL_GUID \ + { \ + 0x9cca03fc, 0x4c9e, 0x4a19, {0x9b, 0x6, 0xed, 0x7b, 0x47, 0x9b, 0xde, 0x55 } \ + } + +typedef struct _EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL; + +// +// Related Definitions +// +// +// Period is the minimum period of time in 100 nanosecond units that child gets called. +// The child will be called back after a time greater than the time Period. +// +// SmiTickInterval is the period of time interval between SMIs. Children of this interface +// should use this field when registering for periodic timer intervals when a finer +// granularity periodic SMI is desired. Valid values for this field are those returned +// by GetNextInterval. A value of 0 indicates the parent is allowed to use any SMI +// interval period to satisfy the requested period. +// Example: A chipset supports periodic SMIs on every 64ms or 2 seconds. +// A child wishes schedule a period SMI to fire on a period of 3 seconds, there +// are several ways to approach the problem: +// 1. The child may accept a 4 second periodic rate, in which case it registers with +// Period = 40000 +// SmiTickInterval = 20000 +// The resulting SMI will occur every 2 seconds with the child called back on +// every 2nd SMI. +// NOTE: the same result would occur if the child set SmiTickInterval = 0. +// 2. The child may choose the finer granularity SMI (64ms): +// Period = 30000 +// SmiTickInterval = 640 +// The resulting SMI will occur every 64ms with the child called back on +// every 47th SMI. +// NOTE: the child driver should be aware that this will result in more +// SMIs occuring during system runtime which can negatively impact system +// performance. +// +// ElapsedTime is the actual time in 100 nanosecond units elapsed since last called, a +// value of 0 indicates an unknown amount of time. +// +typedef struct { + UINT64 Period; + UINT64 SmiTickInterval; + UINT64 ElapsedTime; +} EFI_SMM_PERIODIC_TIMER_DISPATCH_CONTEXT; + +// +// Member functions +// +/** + Dispatch function for a Periodic Timer SMI handler. + + @param DispatchHandle Handle of this dispatch function. + @param DispatchContext Pointer to the dispatch function's context. + The DispatchContext fields are filled in + by the dispatching driver prior to + invoking this dispatch function. + + Nothing + +**/ +typedef +VOID +(EFIAPI *EFI_SMM_PERIODIC_TIMER_DISPATCH) ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_PERIODIC_TIMER_DISPATCH_CONTEXT *DispatchContext + ); + +/** + Returns the next SMI tick period supported by the chipset. The order + returned is from longest to shortest interval period. + + @param This Protocol instance pointer. + @param SmiTickInterval Pointer to pointer of next shorter SMI interval + period supported by the child. This parameter works as a get-first, + get-next field.The first time this function is called, *SmiTickInterval + should be set to NULL to get the longest SMI interval.The returned + *SmiTickInterval should be passed in on subsequent calls to get the + next shorter interval period until *SmiTickInterval = NULL. + + @retval EFI_SUCCESS The service returned successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_PERIODIC_TIMER_INTERVAL) ( + IN EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL *This, + IN OUT UINT64 **SmiTickInterval + ); + +/** + Register a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchFunction Pointer to dispatch function to be invoked for + this SMI source + @param DispatchContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function the period at which the dispatch function + should be invoked. + @param DispatchHandle Handle of dispatch function, for when interfacing + with the parent Sx state SMM driver. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source. + @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this + child. + @retval EFI_INVALID_PARAMETER DispatchContext is invalid. The period input value + is not within valid range. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_PERIODIC_TIMER_REGISTER) ( + IN EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL *This, + IN EFI_SMM_PERIODIC_TIMER_DISPATCH DispatchFunction, + IN EFI_SMM_PERIODIC_TIMER_DISPATCH_CONTEXT *DispatchContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully + unregistered and the SMI source has been disabled + if there are no other registered child dispatch + functions for this SMI source. + @retval EFI_INVALID_PARAMETER Handle is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_PERIODIC_TIMER_UNREGISTER) ( + IN EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +// +// Interface structure for the SMM Periodic Timer Dispatch Protocol +// +/** + @par Protocol Description: + Provides the parent dispatch service for the periodical timer SMI source generator. + + @param Register + Installs a child service to be dispatched by this protocol. + + @param UnRegister + Removes a child service dispatched by this protocol. + + @param GetNextShorterInterval + Returns the next SMI tick period that is supported by the chipset. + +**/ +struct _EFI_SMM_PERIODIC_TIMER_DISPATCH_PROTOCOL { + EFI_SMM_PERIODIC_TIMER_REGISTER Register; + EFI_SMM_PERIODIC_TIMER_UNREGISTER UnRegister; + EFI_SMM_PERIODIC_TIMER_INTERVAL GetNextShorterInterval; +}; + +extern EFI_GUID gEfiSmmPeriodicTimerDispatchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SmmPowerButtonDispatch.h b/MdePkg/Include/Protocol/SmmPowerButtonDispatch.h new file mode 100644 index 0000000000..065d85f09e --- /dev/null +++ b/MdePkg/Include/Protocol/SmmPowerButtonDispatch.h @@ -0,0 +1,147 @@ +/** @file + This file declares EFI Smm Power Button Smi Child Protocol + + Copyright (c) 2006, 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. + + Module Name: SmmPowerButtonDispatch.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. + +**/ + +#ifndef _EFI_SMM_POWER_BUTTON_DISPATCH_H_ +#define _EFI_SMM_POWER_BUTTON_DISPATCH_H_ + +// +// Global ID for the Power Button SMI Protocol +// +#define EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL_GUID \ + { \ + 0xb709efa0, 0x47a6, 0x4b41, {0xb9, 0x31, 0x12, 0xec, 0xe7, 0xa8, 0xee, 0x56 } \ + } + +typedef struct _EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL; + +// +// Related Definitions +// +// +// Power Button. Example, Use for changing LEDs before ACPI OS is on. +// - DXE/BDS Phase +// - OS Install Phase +// +typedef enum { + PowerButtonEntry, + PowerButtonExit +} EFI_POWER_BUTTON_PHASE; + +typedef struct { + EFI_POWER_BUTTON_PHASE Phase; +} EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT; + +// +// Member functions +// +/** + Dispatch function for a Power Button SMI handler. + + @param DispatchHandle Handle of this dispatch function. + @param DispatchContext Pointer to the dispatch function's context. + The DispatchContext fields are filled in + by the dispatching driver prior to + invoking this dispatch function. + + Nothing + +**/ +typedef +VOID +(EFIAPI *EFI_SMM_POWER_BUTTON_DISPATCH) ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT *DispatchContext + ); + +/** + Register a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchFunction Pointer to dispatch function to be invoked for + this SMI source + @param DispatchContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function the Power Button SMI phase for which the dispatch + function should be invoked. + @param DispatchHandle Handle of dispatch function, for when interfacing + with the parent Sx state SMM driver. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source. + @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this + child. + @retval EFI_INVALID_PARAMETER DispatchContext is invalid. The Power Button SMI + phase is not within valid range. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_POWER_BUTTON_REGISTER) ( + IN EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL *This, + IN EFI_SMM_POWER_BUTTON_DISPATCH DispatchFunction, + IN EFI_SMM_POWER_BUTTON_DISPATCH_CONTEXT *DispatchContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully + unregistered and the SMI source has been disabled + if there are no other registered child dispatch + functions for this SMI source. + @retval EFI_INVALID_PARAMETER Handle is invalid. + @retval other TBD + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_POWER_BUTTON_UNREGISTER) ( + IN EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +// +// Interface structure for the SMM Power Button SMI Dispatch Protocol +// +/** + @par Protocol Description: + Provides the parent dispatch service for the SMM power button SMI source generator. + + @param Register + Installs a child service to be dispatched by this protocol. + + @param UnRegister + Removes a child service dispatched by this protocol. + +**/ +struct _EFI_SMM_POWER_BUTTON_DISPATCH_PROTOCOL { + EFI_SMM_POWER_BUTTON_REGISTER Register; + EFI_SMM_POWER_BUTTON_UNREGISTER UnRegister; +}; + +extern EFI_GUID gEfiSmmPowerButtonDispatchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SmmStandbyButtonDispatch.h b/MdePkg/Include/Protocol/SmmStandbyButtonDispatch.h new file mode 100644 index 0000000000..7c52eb1808 --- /dev/null +++ b/MdePkg/Include/Protocol/SmmStandbyButtonDispatch.h @@ -0,0 +1,147 @@ +/** @file + This file declares EFI Smm Standby Button Smi Child Protocol + + Copyright (c) 2006, 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. + + Module Name: SmmStandbyButtonDispatch.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. + +**/ + +#ifndef _EFI_SMM_STANDBY_BUTTON_DISPATCH_H_ +#define _EFI_SMM_STANDBY_BUTTON_DISPATCH_H_ + +// +// Global ID for the Standby Button SMI Protocol +// +#define EFI_SMM_STANDBY_BUTTON_DISPATCH_PROTOCOL_GUID \ + { \ + 0x78965b98, 0xb0bf, 0x449e, {0x8b, 0x22, 0xd2, 0x91, 0x4e, 0x49, 0x8a, 0x98 } \ + } + +typedef struct _EFI_SMM_STANDBY_BUTTON_DISPATCH_PROTOCOL EFI_SMM_STANDBY_BUTTON_DISPATCH_PROTOCOL; + +// +// Related Definitions +// +// +// Standby Button. Example, Use for changing LEDs before ACPI OS is on. +// - DXE/BDS Phase +// - OS Install Phase +// +typedef enum { + Entry, + Exit +} EFI_STANDBY_BUTTON_PHASE; + +typedef struct { + EFI_STANDBY_BUTTON_PHASE Phase; +} EFI_SMM_STANDBY_BUTTON_DISPATCH_CONTEXT; + +// +// Member functions +// +/** + Dispatch function for a Standby Button SMI handler. + + @param DispatchHandle Handle of this dispatch function. + @param DispatchContext Pointer to the dispatch function's context. + The DispatchContext fields are filled in + by the dispatching driver prior to + invoking this dispatch function. + + @return Nothing + +**/ +typedef +VOID +(EFIAPI *EFI_SMM_STANDBY_BUTTON_DISPATCH) ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_STANDBY_BUTTON_DISPATCH_CONTEXT *DispatchContext + ); + +/** + Register a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchFunction Pointer to dispatch function to be invoked for + this SMI source + @param DispatchContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function the Standby Button SMI phase for which the dispatch + function should be invoked. + @param DispatchHandle Handle of dispatch function, for when interfacing + with the parent Sx state SMM driver. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source. + @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this + child. + @retval EFI_INVALID_PARAMETER DispatchContext is invalid. The Standby Button SMI + phase is not within valid range. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_STANDBY_BUTTON_REGISTER) ( + IN EFI_SMM_STANDBY_BUTTON_DISPATCH_PROTOCOL *This, + IN EFI_SMM_STANDBY_BUTTON_DISPATCH DispatchFunction, + IN EFI_SMM_STANDBY_BUTTON_DISPATCH_CONTEXT *DispatchContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully + unregistered and the SMI source has been disabled + if there are no other registered child dispatch + functions for this SMI source. + @retval EFI_INVALID_PARAMETER Handle is invalid. + @retval other TBD + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_STANDBY_BUTTON_UNREGISTER) ( + IN EFI_SMM_STANDBY_BUTTON_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +// +// Interface structure for the SMM Standby Button SMI Dispatch Protocol +// +/** + @par Protocol Description: + Provides the parent dispatch service for the standby button SMI source generator. + + @param Register + Installs a child service to be dispatched by this protocol. + + @param UnRegister + Removes a child service dispatched by this protocol. + +**/ +struct _EFI_SMM_STANDBY_BUTTON_DISPATCH_PROTOCOL { + EFI_SMM_STANDBY_BUTTON_REGISTER Register; + EFI_SMM_STANDBY_BUTTON_UNREGISTER UnRegister; +}; + +extern EFI_GUID gEfiSmmStandbyButtonDispatchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SmmStatusCode.h b/MdePkg/Include/Protocol/SmmStatusCode.h new file mode 100644 index 0000000000..660871548b --- /dev/null +++ b/MdePkg/Include/Protocol/SmmStatusCode.h @@ -0,0 +1,86 @@ +/** @file + This file declares SMM Status code Protocol. + + This code abstracts SMM Status Code reporting. + + Copyright (c) 2006, 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. + + Module Name: SmmStatusCode.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. + +**/ + +#ifndef _PROTOCOL_SMM_STATUS_CODE_H__ +#define _PROTOCOL_SMM_STATUS_CODE_H__ + +// +// Global ID for the Smm Status Code Protocol +// +#define EFI_SMM_STATUS_CODE_PROTOCOL_GUID \ + { \ + 0x6afd2b77, 0x98c1, 0x4acd, {0xa6, 0xf9, 0x8a, 0x94, 0x39, 0xde, 0xf, 0xb1 } \ + } + +typedef struct _EFI_SMM_STATUS_CODE_PROTOCOL EFI_SMM_STATUS_CODE_PROTOCOL; + +/** + Service to emit the status code in SMM. + + @param This Pointer to EFI_SMM_STATUS_CODE_PROTOCOL instance. + + @param CodeType Indicates the type of status code being reported. + + @param Value Describes the current status of a hardware or software entity. + This included information about the class and subclass that is used to + classify the entity as well as an operation. + + @param Instance The enumeration of a hardware or software entity within + the system. Valid instance numbers start with 1. + + @param CallerId This optional parameter may be used to identify the caller. + This parameter allows the status code driver to apply different rules to + different callers. + + @param Data This optional parameter may be used to pass additional data. + + @retval EFI_SUCCESS The function completed successfully + + @retval EFI_DEVICE_ERROR The function should not be completed due to a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_REPORT_STATUS_CODE) ( + IN EFI_SMM_STATUS_CODE_PROTOCOL *This, + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ); + +/** + @par Protocol Description: + Provides status code services from SMM. + + @param ReportStatusCode + Allows for the SMM agent to produce a status code output. + +**/ +struct _EFI_SMM_STATUS_CODE_PROTOCOL { + EFI_SMM_REPORT_STATUS_CODE ReportStatusCode; +}; + +extern EFI_GUID gEfiSmmStatusCodeProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SmmSwDispatch.h b/MdePkg/Include/Protocol/SmmSwDispatch.h new file mode 100644 index 0000000000..bc456cb5f2 --- /dev/null +++ b/MdePkg/Include/Protocol/SmmSwDispatch.h @@ -0,0 +1,149 @@ +/** @file + This file declares EFI Smm Software Smi Child Protocol + + Copyright (c) 2006, 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. + + Module Name: SmmSwDispatch.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. + +**/ + +#ifndef _EFI_SMM_SW_DISPATCH_H_ +#define _EFI_SMM_SW_DISPATCH_H_ + +// +// Global ID for the SW SMI Protocol +// +#define EFI_SMM_SW_DISPATCH_PROTOCOL_GUID \ + { \ + 0xe541b773, 0xdd11, 0x420c, {0xb0, 0x26, 0xdf, 0x99, 0x36, 0x53, 0xf8, 0xbf } \ + } + +typedef struct _EFI_SMM_SW_DISPATCH_PROTOCOL EFI_SMM_SW_DISPATCH_PROTOCOL; + +// +// Related Definitions +// +// +// A particular chipset may not support all possible software SMI input values. +// For example, the ICH supports only values 00h to 0FFh. The parent only allows a single +// child registration for each SwSmiInputValue. +// +typedef struct { + UINTN SwSmiInputValue; +} EFI_SMM_SW_DISPATCH_CONTEXT; + +// +// Member functions +// +/** + Dispatch function for a Software SMI handler. + + @param DispatchHandle Handle of this dispatch function. + @param DispatchContext Pointer to the dispatch function's context. + The SwSmiInputValue field is filled in + by the software dispatch driver prior to + invoking this dispatch function. + The dispatch function will only be called + for input values for which it is registered. + + Nothing + +**/ +typedef +VOID +(EFIAPI *EFI_SMM_SW_DISPATCH) ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext + ); + +/** + Register a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchFunction Pointer to dispatch function to be invoked for + this SMI source + @param DispatchContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function which Software SMI input value the + dispatch function should be invoked for. + @param DispatchHandle Handle of dispatch function, for when interfacing + with the parent Sx state SMM driver. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The SW driver was unable to enable the SMI source. + @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this + child. + @retval EFI_INVALID_PARAMETER DispatchContext is invalid. The SW SMI input value + is not within valid range. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_SW_REGISTER) ( + IN EFI_SMM_SW_DISPATCH_PROTOCOL *This, + IN EFI_SMM_SW_DISPATCH DispatchFunction, + IN EFI_SMM_SW_DISPATCH_CONTEXT *DispatchContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully + unregistered and the SMI source has been disabled + if there are no other registered child dispatch + functions for this SMI source. + @retval EFI_INVALID_PARAMETER Handle is invalid. + @retval other TBD + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_SW_UNREGISTER) ( + IN EFI_SMM_SW_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +// +// Interface structure for the SMM Software SMI Dispatch Protocol +// +/** + @par Protocol Description: + Provides the parent dispatch service for a given SMI source generator. + + @param Register + Installs a child service to be dispatched by this protocol. + + @param UnRegister + Removes a child service dispatched by this protocol. + + @param MaximumSwiValue + A read-only field that describes the maximum value that can be used + in the EFI_SMM_SW_DISPATCH_PROTOCOL.Register() service. + +**/ +struct _EFI_SMM_SW_DISPATCH_PROTOCOL { + EFI_SMM_SW_REGISTER Register; + EFI_SMM_SW_UNREGISTER UnRegister; + UINTN MaximumSwiValue; +}; + +extern EFI_GUID gEfiSmmSwDispatchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SmmSxDispatch.h b/MdePkg/Include/Protocol/SmmSxDispatch.h new file mode 100644 index 0000000000..dcbc6a9b98 --- /dev/null +++ b/MdePkg/Include/Protocol/SmmSxDispatch.h @@ -0,0 +1,160 @@ +/** @file + This file declares EFI Smm Sx Smi Child Protocol + + Copyright (c) 2006, 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. + + Module Name: SmmSxDispatch.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. + +**/ + +#ifndef _EFI_SMM_SX_DISPATCH_H_ +#define _EFI_SMM_SX_DISPATCH_H_ + +// +// Global ID for the Sx SMI Protocol +// +#define EFI_SMM_SX_DISPATCH_PROTOCOL_GUID \ + { \ + 0x14fc52be, 0x1dc, 0x426c, {0x91, 0xae, 0xa2, 0x3c, 0x3e, 0x22, 0xa, 0xe8 } \ + } + +typedef struct _EFI_SMM_SX_DISPATCH_PROTOCOL EFI_SMM_SX_DISPATCH_PROTOCOL; +// +// Related Definitions +// +typedef enum { + SxS0, + SxS1, + SxS2, + SxS3, + SxS4, + SxS5, + EfiMaximumSleepType +} EFI_SLEEP_TYPE; + +typedef enum { + SxEntry, + SxExit, + EfiMaximumPhase +} EFI_SLEEP_PHASE; + +typedef struct { + EFI_SLEEP_TYPE Type; + EFI_SLEEP_PHASE Phase; +} EFI_SMM_SX_DISPATCH_CONTEXT; + +// +// Member functions +// +/** + Dispatch function for a Sx state SMI handler. + + @param DispatchHandle Handle of this dispatch function. + @param DispatchContext Pointer to the dispatch function¡¯s context. + The Type and Phase fields are filled in by the Sx dispatch driver + prior to invoking this dispatch function. For this interface, + the Sx driver will call the dispatch function for all Sx type + and phases, so the Sx state handler(s) must check the Type and + Phase field of EFI_SMM_SX_DISPATCH_CONTEXT and act accordingly. + + Nothing + +**/ +typedef +VOID +(EFIAPI *EFI_SMM_SX_DISPATCH) ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext + ); + +/** + Register a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchFunction Pointer to dispatch function to be invoked for + this SMI source + @param DispatchContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function which Sx state type and phase the caller + wishes to be called back on. For this intertace, + the Sx driver will call the registered handlers for + all Sx type and phases, so the Sx state handler(s) + must check the Type and Phase field of the Dispatch + context and act accordingly. + @param DispatchHandle Handle of dispatch function, for when interfacing + with the parent Sx state SMM driver. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_UNSUPPORTED The Sx driver or hardware does not support that + Sx Type/Phase. + @retval EFI_DEVICE_ERROR The Sx driver was unable to enable the SMI source. + @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this + child. + @retval EFI_INVALID_PARAMETER DispatchContext is invalid. Type & Phase are not + within valid range. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_SX_REGISTER) ( + IN EFI_SMM_SX_DISPATCH_PROTOCOL *This, + IN EFI_SMM_SX_DISPATCH DispatchFunction, + IN EFI_SMM_SX_DISPATCH_CONTEXT *DispatchContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully unregistered and the + SMI source has been disabled if there are no other registered child + dispatch functions for this SMI source. + @retval EFI_INVALID_PARAMETER Handle is invalid. + @retval other TBD + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_SX_UNREGISTER) ( + IN EFI_SMM_SX_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +// +// Interface structure for the SMM Child Dispatch Protocol +// +/** + @par Protocol Description: + Provides the parent dispatch service for a given Sx-state source generator. + + @param Register + Installs a child service to be dispatched by this protocol. + + @param UnRegister + Removes a child service dispatched by this protocol. + +**/ +struct _EFI_SMM_SX_DISPATCH_PROTOCOL { + EFI_SMM_SX_REGISTER Register; + EFI_SMM_SX_UNREGISTER UnRegister; +}; + +extern EFI_GUID gEfiSmmSxDispatchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/SmmUsbDispatch.h b/MdePkg/Include/Protocol/SmmUsbDispatch.h new file mode 100644 index 0000000000..f036171c49 --- /dev/null +++ b/MdePkg/Include/Protocol/SmmUsbDispatch.h @@ -0,0 +1,141 @@ +/** @file + This file declares EFI Smm USB Smi Child Protocol. + + Copyright (c) 2006, 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. + + Module Name: SmmUsbDispatch.h + + @par Revision Reference: + This Protocol is defined in Framework of EFI SMM Core Interface Spec + Version 0.9. +**/ + +#ifndef _EFI_SMM_USB_DISPATCH_H_ +#define _EFI_SMM_USB_DISPATCH_H_ + +// +// Global ID for the USB Protocol +// +#define EFI_SMM_USB_DISPATCH_PROTOCOL_GUID \ + { \ + 0xa05b6ffd, 0x87af, 0x4e42, {0x95, 0xc9, 0x62, 0x28, 0xb6, 0x3c, 0xf3, 0xf3 } \ + } + +typedef struct _EFI_SMM_USB_DISPATCH_PROTOCOL EFI_SMM_USB_DISPATCH_PROTOCOL; + +// +// Related Definitions +// +typedef enum { + UsbLegacy, + UsbWake +} EFI_USB_SMI_TYPE; + +typedef struct { + EFI_USB_SMI_TYPE Type; + EFI_DEVICE_PATH_PROTOCOL *Device; +} EFI_SMM_USB_DISPATCH_CONTEXT; + +// +// Member functions +// +/** + Dispatch function for a USB SMI handler. + + @param DispatchHandle Handle of this dispatch function. + @param DispatchContext Pointer to the dispatch function's context. + The DispatchContext fields are filled in + by the dispatching driver prior to + invoking this dispatch function. + + Nothing + +**/ +typedef +VOID +(EFIAPI *EFI_SMM_USB_DISPATCH) ( + IN EFI_HANDLE DispatchHandle, + IN EFI_SMM_USB_DISPATCH_CONTEXT *DispatchContext + ); + +/** + Register a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchFunction Pointer to dispatch function to be invoked for + this SMI source + @param DispatchContext Pointer to the dispatch function's context. + The caller fills this context in before calling + the register function to indicate to the register + function the USB SMI types for which the dispatch + function should be invoked. + @param DispatchHandle Handle of dispatch function, for when interfacing + with the parent Sx state SMM driver. + + @retval EFI_SUCCESS The dispatch function has been successfully + registered and the SMI source has been enabled. + @retval EFI_DEVICE_ERROR The driver was unable to enable the SMI source. + @retval EFI_OUT_OF_RESOURCES Not enough memory (system or SMM) to manage this + child. + @retval EFI_INVALID_PARAMETER DispatchContext is invalid. The USB SMI type + is not within valid range. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_USB_REGISTER) ( + IN EFI_SMM_USB_DISPATCH_PROTOCOL *This, + IN EFI_SMM_USB_DISPATCH DispatchFunction, + IN EFI_SMM_USB_DISPATCH_CONTEXT *DispatchContext, + OUT EFI_HANDLE *DispatchHandle + ); + +/** + Unregister a child SMI source dispatch function with a parent SMM driver + + @param This Protocol instance pointer. + @param DispatchHandle Handle of dispatch function to deregister. + + @retval EFI_SUCCESS The dispatch function has been successfully + unregistered and the SMI source has been disabled + if there are no other registered child dispatch + functions for this SMI source. + @retval EFI_INVALID_PARAMETER Handle is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SMM_USB_UNREGISTER) ( + IN EFI_SMM_USB_DISPATCH_PROTOCOL *This, + IN EFI_HANDLE DispatchHandle + ); + +// +// Interface structure for the SMM USB SMI Dispatch Protocol +// +/** + @par Protocol Description: + Provides the parent dispatch service for the USB SMI source generator. + + @param Register + Installs a child service to be dispatched by this protocol. + + @param UnRegister + Removes a child service dispatched by this protocol. + +**/ +struct _EFI_SMM_USB_DISPATCH_PROTOCOL { + EFI_SMM_USB_REGISTER Register; + EFI_SMM_USB_UNREGISTER UnRegister; +}; + +extern EFI_GUID gEfiSmmUsbDispatchProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/TapeIo.h b/MdePkg/Include/Protocol/TapeIo.h new file mode 100644 index 0000000000..8f15b3a2aa --- /dev/null +++ b/MdePkg/Include/Protocol/TapeIo.h @@ -0,0 +1,236 @@ +/** @file + EFI_TAPE_IO_PROTOCOL as defined in the UEFI 2.0. + Provide services to control and access a tape device. + + Copyright (c) 2006, 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. + + Module Name: TapeIo.h + +**/ + +#ifndef __EFI_TAPE_IO_PROTOCOL_H__ +#define __EFI_TAPE_IO_PROTOCOL_H__ + +#define EFI_TAPE_IO_PROTOCOL_GUID \ + { \ + 0x1e93e633, 0xd65a, 0x459e, {0xab, 0x84, 0x93, 0xd9, 0xec, 0x26, 0x6d, 0x18 } \ + } + +typedef struct _EFI_TAPE_IO_PROTOCOL EFI_TAPE_IO_PROTOCOL; + +typedef struct { + UINT64 Signature; + UINT32 Revision; + UINT32 BootDescSize; + UINT32 BootDescCRC; + EFI_GUID TapeGUID; + EFI_GUID TapeType; + EFI_GUID TapeUnique; + UINT32 BLLocation; + UINT32 BLBlocksize; + UINT32 BLFilesize; + CHAR8 OSVersion[40]; + CHAR8 AppVersion[40]; + CHAR8 CreationDate[10]; + CHAR8 CreationTime[10]; + CHAR8 SystemName[256]; // UTF-8 + CHAR8 TapeTitle[120]; // UTF-8 + CHAR8 pad[468]; // pad to 1024 +} TAPE_HEADER; + +/** + Reads from the tape. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + @param BufferSize Size of the buffer in bytes pointed to by Buffer. + @param Buffer Pointer to the buffer for data to be read into. + + @retval EFI_SUCCESS Data was successfully transferred from the media. + @retval EFI_END_OF_FILE A filemark was encountered which limited the data + transferred by the read operation or the head is positioned + just after a filemark. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY The transfer failed since the device was not ready (e.g. not + online). The transfer may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of transfer. + @retval EFI_TIMEOUT The transfer failed to complete within the timeout specified. + @retval EFI_MEDIA_CHANGED The media in the device was changed since the last access. + The transfer was aborted since the current position of the + media may be incorrect. + @retval EFI_INVALID_PARAMETER A NULL Buffer was specified with a non-zero + BufferSize or the device is operating in fixed block + size mode and the BufferSize was not a multiple of + device¡¯s fixed block size + @retval EFI_DEVICE_ERROR A device error occurred while attempting to transfer data + from the media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_READ) ( + IN EFI_TAPE_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +; + +/** + Writes to the tape. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + @param BufferSize Size of the buffer in bytes pointed to by Buffer. + @param Buffer Pointer to the buffer for data to be written from. + + @retval EFI_SUCCESS Data was successfully transferred to the media. + @retval EFI_END_OF_MEDIA The logical end of media has been reached. Data may have + been successfully transferred to the media. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY The transfer failed since the device was not ready (e.g. not + online). The transfer may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of transfer. + @retval EFI_TIMEOUT The transfer failed to complete within the timeout specified. + @retval EFI_MEDIA_CHANGED The media in the device was changed since the last access. + The transfer was aborted since the current position of the + media may be incorrect. + @retval EFI_WRITE_PROTECTED The media in the device is write-protected. The transfer + was aborted since a write cannot be completed. + @retval EFI_INVALID_PARAMETER A NULL Buffer was specified with a non-zero + BufferSize or the device is operating in fixed block + size mode and the BufferSize was not a multiple of + device¡¯s fixed block size + @retval EFI_DEVICE_ERROR A device error occurred while attempting to transfer data + from the media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_WRITE) ( + IN EFI_TAPE_IO_PROTOCOL *This, + IN UINTN *BufferSize, + IN VOID *Buffer + ) +; + + +/** + Rewinds the tape. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The media was successfully repositioned. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY Repositioning the media failed since the device was not + ready (e.g. not online). The transfer may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of media repositioning. + @retval EFI_TIMEOUT Repositioning of the media did not complete within the timeout specified. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reposition the media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_REWIND) ( + IN EFI_TAPE_IO_PROTOCOL *This + ) +; + + +/** + Positions the tape. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + @param Direction Direction and number of data blocks or filemarks to space over on media. + @param Type Type of mark to space over on media. + + @retval EFI_SUCCESS The media was successfully repositioned. + @retval EFI_END_OF_MEDIA Beginning or end of media was reached before the + indicated number of data blocks or filemarks were found. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY The reposition failed since the device was not ready (e.g. not + online). The reposition may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of repositioning. + @retval EFI_TIMEOUT The repositioning failed to complete within the timeout specified. + @retval EFI_MEDIA_CHANGED The media in the device was changed since the last access. + Repositioning the media was aborted since the current + position of the media may be incorrect. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reposition the media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_SPACE) ( + IN EFI_TAPE_IO_PROTOCOL *This, + INTN Direction, + UINTN Type + ) +; + + +/** + Writes filemarks to the media. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + @param Count Number of filemarks to write to the media. + + @retval EFI_SUCCESS Data was successfully transferred from the media. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY The transfer failed since the device was not ready (e.g. not + online). The transfer may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of repositioning. + @retval EFI_TIMEOUT The transfer failed to complete within the timeout specified. + @retval EFI_MEDIA_CHANGED The media in the device was changed since the last access. + The transfer was aborted since the current position of the + media may be incorrect. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to transfer data from the media. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_WRITEFM) ( + IN EFI_TAPE_IO_PROTOCOL *This, + IN UINTN Count + ) +; + + +/** + Resets the tape device. + + @param This A pointer to the EFI_TAPE_IO_PROTOCOL instance. + @param ExtendedVerification Indicates whether the parent bus should also be reset. + + @retval EFI_SUCCESS The bus and/or device were successfully reset. + @retval EFI_NO_MEDIA No media is loaded in the device. + @retval EFI_NOT_READY The reset failed since the device and/or bus was not ready. + The reset may be retried at a later time. + @retval EFI_UNSUPPORTED The device does not support this type of reset. + @retval EFI_TIMEOUT The reset did not complete within the timeout allowed. + @retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the bus and/or device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TAPE_RESET) ( + IN EFI_TAPE_IO_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +; + +struct _EFI_TAPE_IO_PROTOCOL { + EFI_TAPE_READ TapeRead; + EFI_TAPE_WRITE TapeWrite; + EFI_TAPE_REWIND TapeRewind; + EFI_TAPE_SPACE TapeSpace; + EFI_TAPE_WRITEFM TapeWriteFM; + EFI_TAPE_RESET TapeReset; +}; + +extern EFI_GUID gEfiTapeIoProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Tcp4.h b/MdePkg/Include/Protocol/Tcp4.h new file mode 100644 index 0000000000..87dea25e32 --- /dev/null +++ b/MdePkg/Include/Protocol/Tcp4.h @@ -0,0 +1,507 @@ +/** @file + EFI TCPv4 Protocol Definition + The EFI TCPv4 Service Binding Protocol is used to locate EFI TCPv4 Protocol drivers to create + and destroy child of the driver to communicate with other host using TCP protocol. + The EFI TCPv4 Protocol provides services to send and receive data stream. + + Copyright (c) 2006, 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. + + Module Name: Tcp4.h + +**/ + +#ifndef __EFI_TCP4_PROTOCOL_H__ +#define __EFI_TCP4_PROTOCOL_H__ + +#define EFI_TCP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x00720665, 0x67EB, 0x4a99, {0xBA, 0xF7, 0xD3, 0xC3, 0x3A, 0x1C, 0x7C, 0xC9 } \ + } + +#define EFI_TCP4_PROTOCOL_GUID \ + { \ + 0x65530BC7, 0xA359, 0x410f, {0xB0, 0x10, 0x5A, 0xAD, 0xC7, 0xEC, 0x2B, 0x62 } \ + } + +typedef struct _EFI_TCP4_PROTOCOL EFI_TCP4_PROTOCOL; + +typedef struct { + EFI_IPv4_ADDRESS LocalAddress; + UINT16 LocalPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; +} EFI_TCP4_SERVICE_POINT; + +typedef struct { + EFI_HANDLE DriverHandle; + UINTN ServiceCount; + EFI_TCP4_SERVICE_POINT Services[1]; +} EFI_TCP4_VARIABLE_DATA; + +typedef struct { + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 StationPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; + BOOLEAN ActiveFlag; +} EFI_TCP4_ACCESS_POINT; + +typedef struct { + UINTN ReceiveBufferSize; + UINTN SendBufferSize; + UINTN MaxSynBackLog; + UINTN ConnectionTimeout; + UINTN DataRetries; + UINTN FinTimeout; + UINTN TimeWaitTimeout; + UINTN KeepAliveProbes; + UINTN KeepAliveTime; + UINTN KeepAliveInterval; + BOOLEAN EnableNagle; + BOOLEAN EnableTimeStamp; + BOOLEAN EnableWindowScaling; + BOOLEAN EnableSelectiveAck; + BOOLEAN EnablePathMtuDiscovery; +} EFI_TCP4_OPTION; + +typedef struct { + // + // I/O parameters + // + UINT8 TypeOfService; + UINT8 TimeToLive; + + // + // Access Point + // + EFI_TCP4_ACCESS_POINT AccessPoint; + + // + // TCP Control Options + // + EFI_TCP4_OPTION *ControlOption; +} EFI_TCP4_CONFIG_DATA; + +typedef enum { + Tcp4StateClosed = 0, + Tcp4StateListen = 1, + Tcp4StateSynSent = 2, + Tcp4StateSynReceived = 3, + Tcp4StateEstablished = 4, + Tcp4StateFinWait1 = 5, + Tcp4StateFinWait2 = 6, + Tcp4StateClosing = 7, + Tcp4StateTimeWait = 8, + Tcp4StateCloseWait = 9, + Tcp4StateLastAck = 10 +} EFI_TCP4_CONNECTION_STATE; + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; +} EFI_TCP4_COMPLETION_TOKEN; + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; +} EFI_TCP4_CONNECTION_TOKEN; + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + EFI_HANDLE NewChildHandle; +} EFI_TCP4_LISTEN_TOKEN; + +typedef struct { + UINTN FragmentLength; + VOID *FragmentBuffer; +} EFI_TCP4_FRAGMENT_DATA; + +typedef struct { + BOOLEAN UrgentFlag; + IN OUT UINTN DataLength; + UINTN FragmentCount; + EFI_TCP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP4_RECEIVE_DATA; + +typedef struct { + BOOLEAN Push; + BOOLEAN Urgent; + UINTN DataLength; + UINTN FragmentCount; + EFI_TCP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_TCP4_TRANSMIT_DATA; + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + union { + EFI_TCP4_RECEIVE_DATA *RxData; + EFI_TCP4_TRANSMIT_DATA *TxData; + } Packet; +} EFI_TCP4_IO_TOKEN; + +typedef struct { + EFI_TCP4_COMPLETION_TOKEN CompletionToken; + BOOLEAN AbortOnClose; +} EFI_TCP4_CLOSE_TOKEN; + +// +// Interface definition for TCP4 protocol +// + +/** + Get the current operational status. + + @param This Pointer to the EFI_TCP4_PROTOCOL instance. + @param Tcp4State Pointer to the buffer to receive the current TCP state. + @param Tcp4ConfigData Pointer to the buffer to receive the current TCP configuration. + @param Ip4ModeData Pointer to the buffer to receive the current IPv4 configuration + data used by the TCPv4 instance. + @param MnpConfigData Pointer to the buffer to receive the current MNP configuration + data used indirectly by the TCPv4 instance. + @param SnpModeData Pointer to the buffer to receive the current SNP configuration + data used indirectly by the TCPv4 instance. + + @retval EFI_SUCCESS The mode data was read. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED No configuration data is available because this instance hasn¡¯t + been started. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_GET_MODE_DATA) ( + IN EFI_TCP4_PROTOCOL *This, + OUT EFI_TCP4_CONNECTION_STATE *Tcp4State OPTIONAL, + OUT EFI_TCP4_CONFIG_DATA *Tcp4ConfigData OPTIONAL, + OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ) +; + +/** + Initialize or brutally reset the operational parameters for this EFI TCPv4 instance. + + @param This Pointer to the EFI_TCP4_PROTOCOL instance. + @param Tcp4ConfigData Pointer to the configure data to configure the instance. + + @retval EFI_SUCCESS The operational settings are set, changed, or reset + successfully. + @retval EFI_INVALID_PARAMETER Some parameter is invalid. + @retval EFI_NO_MAPPING When using a default address, configuration (through + DHCP, BOOTP, RARP, etc.) is not finished yet. + @retval EFI_ACCESS_DENIED Configuring TCP instance when it is configured without + calling Configure() with NULL to reset it. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred. + @retval EFI_UNSUPPORTED One or more of the control options are not supported in + the implementation. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources when + executing Configure(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CONFIGURE) ( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_CONFIG_DATA *TcpConfigData OPTIONAL + ) +; + + +/** + Add or delete a route entry to the route table + + @param This Pointer to the EFI_TCP4_PROTOCOL instance. + @param DeleteRoute Set it to TRUE to delete this route from the routing table. Set it to + FALSE to add this route to the routing table. + DestinationAddress and SubnetMask are used as the + keywords to search route entry. + @param SubnetAddress The destination network. + @param SubnetMask The subnet mask of the destination network. + @param GatewayAddress The gateway address for this route. It must be on the same + subnet with the station address unless a direct route is specified. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED The EFI TCPv4 Protocol instance has not been configured. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - SubnetAddress is NULL. + - SubnetMask is NULL. + - GatewayAddress is NULL. + - *SubnetAddress is not NULL a valid subnet address. + - *SubnetMask is not a valid subnet mask. + - *GatewayAddress is not a valid unicast IP address or it + is not in the same subnet. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to add the entry to the + routing table. + @retval EFI_NOT_FOUND This route is not in the routing table. + @retval EFI_ACCESS_DENIED The route is already defined in the routing table. + @retval EFI_UNSUPPORTED The TCP driver does not support this operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_ROUTES) ( + IN EFI_TCP4_PROTOCOL *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS *SubnetAddress, + IN EFI_IPv4_ADDRESS *SubnetMask, + IN EFI_IPv4_ADDRESS *GatewayAddress + ) +; + +/** + Initiate a nonblocking TCP connection request for an active TCP instance. + + @param This Pointer to the EFI_TCP4_PROTOCOL instance. + @param ConnectionToken Pointer to the connection token to return when the TCP three + way handshake finishes. + + @retval EFI_SUCCESS The connection request is successfully initiated and the state + - of this TCPv4 instance has been changed to + - Tcp4StateSynSent. + @retval EFI_NOT_STARTED This EFI TCPv4 Protocol instance has not been configured. + @retval EFI_ACCESS_DENIED One or more of the following conditions are TRUE: + - This instance is not configured as an active one. + - This instance is not in Tcp4StateClosed state. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - ConnectionToken is NULL. + - ConnectionToken->CompletionToken.Event is NULL. + @retval EFI_OUT_OF_RESOURCES The driver can¡¯t allocate enough resource to initiate the activeopen. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CONNECT) ( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken + ) +; + + +/** + Listen on the passive instance to accept an incoming connection request. This is a nonblocking operation. + + @param This Pointer to the EFI_TCP4_PROTOCOL instance. + @param ListenToken Pointer to the listen token to return when operation finishes. + + @retval EFI_SUCCESS The listen token has been queued successfully. + @retval EFI_NOT_STARTED This EFI TCPv4 Protocol instance has not been configured. + @retval EFI_ACCESS_DENIED One or more of the following are TRUE: + - This instance is not a passive instance. + - This instance is not in Tcp4StateListen state. + - The same listen token has already existed in the listen + token queue of this TCP instance. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - ListenToken is NULL. + - ListentToken->CompletionToken.Event is NULL. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation. + @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_ACCEPT) ( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_LISTEN_TOKEN *ListenToken + ) +; + +/** + Queues outgoing data into the transmit queue. + + @param This Pointer to the EFI_TCP4_PROTOCOL instance. + @param Token Pointer to the completion token to queue to the transmit queue. + + @retval EFI_SUCCESS The data has been queued for transmission. + @retval EFI_NOT_STARTED This EFI TCPv4 Protocol instance has not been configured. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - Token is NULL. + - Token->CompletionToken.Event is NULL. + - Token->Packet.TxData is NULL L. + - Token->Packet.FragmentCount is zero. + - Token->Packet.DataLength is not equal to the sum of fragment lengths. + @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE: + - A transmit completion token with the same Token->CompletionToken.Event + was already in the transmission queue. + - The current instance is in Tcp4StateClosed state. + - The current instance is a passive one and it is in + Tcp4StateListen state. + - User has called Close() to disconnect this connection. + @retval EFI_NOT_READY The completion token could not be queued because the + transmit queue is full. + @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of resource + shortage. + @retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or address. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_TRANSMIT) ( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_IO_TOKEN *Token + ) +; + + +/** + Places an asynchronous receive request into the receiving queue. + + @param This Pointer to the EFI_TCP4_PROTOCOL instance. + @param Token Pointer to a token that is associated with the receive data + descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This EFI TCPv4 Protocol instance has not been configured. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, RARP, + etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - Token is NULL. + - Token->CompletionToken.Event is NULL. + - Token->Packet.RxData is NULL. + - Token->Packet.RxData->DataLength is 0. + - The Token->Packet.RxData->DataLength is not + the sum of all FragmentBuffer length in FragmentTable. + @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of + system resources (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE: + - A receive completion token with the same Token- + >CompletionToken.Event was already in the receive + queue. + - The current instance is in Tcp4StateClosed state. + - The current instance is a passive one and it is in + Tcp4StateListen state. + - User has called Close() to disconnect this connection. + @retval EFI_CONNECTION_FIN The communication peer has closed the connection and there is + no any buffered data in the receive buffer of this instance. + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_RECEIVE) ( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_IO_TOKEN *Token + ) +; + +/** + Disconnecting a TCP connection gracefully or reset a TCP connection. This function is a + nonblocking operation. + + @param This Pointer to the EFI_TCP4_PROTOCOL instance. + @param CloseToken Pointer to the close token to return when operation finishes. + + @retval EFI_SUCCESS The Close() is called successfully. + @retval EFI_NOT_STARTED This EFI TCPv4 Protocol instance has not been configured. + @retval EFI_ACCESS_DENIED One or more of the following are TRUE: + - Configure() has been called with + TcpConfigData set to NULL and this function has + not returned. + - Previous Close() call on this instance has not + finished. + @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: + - This is NULL. + - CloseToken is NULL. + - CloseToken->CompletionToken.Event is NULL. + @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the operation. + @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above category error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CLOSE) ( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_CLOSE_TOKEN *CloseToken + ) +; + +/** + Abort an asynchronous connection, listen, transmission or receive request. + + @param This Pointer to the EFI_TCP4_PROTOCOL instance. + @param Token Pointer to a token that has been issued by + EFI_TCP4_PROTOCOL.Connect(), + EFI_TCP4_PROTOCOL.Accept(), + EFI_TCP4_PROTOCOL.Transmit() or + EFI_TCP4_PROTOCOL.Receive(). If NULL, all pending + tokens issued by above four functions will be aborted. Type + EFI_TCP4_COMPLETION_TOKEN is defined in + EFI_TCP4_PROTOCOL.Connect(). + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY No incoming or outgoing data is processed. + @retval EFI_TIMEOUT Data was dropped out of the transmission or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_CANCEL) ( + IN EFI_TCP4_PROTOCOL *This, + IN EFI_TCP4_COMPLETION_TOKEN *Token OPTIONAL + ) +; + + +/** + Poll to receive incoming data and transmit outgoing segments. + + @param This Pointer to the EFI_TCP4_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_NOT_READY No incoming or outgoing data is processed. + @retval EFI_TIMEOUT Data was dropped out of the transmission or receive queue. + Consider increasing the polling rate. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_TCP4_POLL) ( + IN EFI_TCP4_PROTOCOL *This + ) +; + +struct _EFI_TCP4_PROTOCOL { + EFI_TCP4_GET_MODE_DATA GetModeData; + EFI_TCP4_CONFIGURE Configure; + EFI_TCP4_ROUTES Routes; + EFI_TCP4_CONNECT Connect; + EFI_TCP4_ACCEPT Accept; + EFI_TCP4_TRANSMIT Transmit; + EFI_TCP4_RECEIVE Receive; + EFI_TCP4_CLOSE Close; + EFI_TCP4_CANCEL Cancel; + EFI_TCP4_POLL Poll; +}; + +#define EFI_CONNECTION_FIN EFIERR (104) +#define EFI_CONNECTION_RESET EFIERR (105) +#define EFI_CONNECTION_REFUSED EFIERR (106) + +extern EFI_GUID gEfiTcp4ServiceBindingProtocolGuid; +extern EFI_GUID gEfiTcp4ProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Udp4.h b/MdePkg/Include/Protocol/Udp4.h new file mode 100644 index 0000000000..7ac3c80f6c --- /dev/null +++ b/MdePkg/Include/Protocol/Udp4.h @@ -0,0 +1,363 @@ +/** @file + Copyright (c) 2006, 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. + + Module Name: Udp4.h + +**/ + +#ifndef __EFI_UDP4_PROTOCOL_H__ +#define __EFI_UDP4_PROTOCOL_H__ + +// +//GUID definitions +// +#define EFI_UDP4_SERVICE_BINDING_PROTOCOL_GUID \ + { \ + 0x83f01464, 0x99bd, 0x45e5, {0xb3, 0x83, 0xaf, 0x63, 0x05, 0xd8, 0xe9, 0xe6 } \ + } + +#define EFI_UDP4_PROTOCOL_GUID \ + { \ + 0x3ad9df29, 0x4501, 0x478d, {0xb1, 0xf8, 0x7f, 0x7f, 0xe7, 0x0e, 0x50, 0xf3 } \ + } + +typedef struct _EFI_UDP4_PROTOCOL EFI_UDP4_PROTOCOL; + +typedef struct { + EFI_HANDLE InstanceHandle; + EFI_IPv4_ADDRESS LocalAddress; + UINT16 LocalPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; +} EFI_UDP4_SERVICE_POINT; + +typedef struct { + EFI_HANDLE DriverHandle; + UINT32 ServiceCount; + EFI_UDP4_SERVICE_POINT Services[1]; +} EFI_UDP4_VARIABLE_DATA; + +// +//ICMP error definitions +// +#define EFI_NETWORK_UNREACHABLE EFIERR(100) +#define EFI_HOST_UNREACHABLE EFIERR(101) +#define EFI_PROTOCOL_UNREACHABLE EFIERR(102) +#define EFI_PORT_UNREACHABLE EFIERR(103) + + +typedef struct { + UINT32 FragmentLength; + VOID *FragmentBuffer; +} EFI_UDP4_FRAGMENT_DATA; + +typedef struct { + EFI_IPv4_ADDRESS SourceAddress; + UINT16 SourcePort; + EFI_IPv4_ADDRESS DestinationAddress; + UINT16 DestinationPort; +} EFI_UDP4_SESSION_DATA; +typedef struct { + // + // Receiving Filters + // + BOOLEAN AcceptBroadcast; + BOOLEAN AcceptPromiscuous; + BOOLEAN AcceptAnyPort; + BOOLEAN AllowDuplicatePort; + // + // I/O parameters + // + UINT8 TypeOfService; + UINT8 TimeToLive; + BOOLEAN DoNotFragment; + UINT32 ReceiveTimeout; + UINT32 TransmitTimeout; + // + // Access Point + // + BOOLEAN UseDefaultAddress; + EFI_IPv4_ADDRESS StationAddress; + EFI_IPv4_ADDRESS SubnetMask; + UINT16 StationPort; + EFI_IPv4_ADDRESS RemoteAddress; + UINT16 RemotePort; +} EFI_UDP4_CONFIG_DATA; + +typedef struct { + EFI_UDP4_SESSION_DATA *UdpSessionData; //OPTIONAL + EFI_IPv4_ADDRESS *GatewayAddress; //OPTIONAL + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP4_TRANSMIT_DATA; + +typedef struct { + EFI_TIME TimeStamp; + EFI_EVENT RecycleSignal; + EFI_UDP4_SESSION_DATA UdpSession; + UINT32 DataLength; + UINT32 FragmentCount; + EFI_UDP4_FRAGMENT_DATA FragmentTable[1]; +} EFI_UDP4_RECEIVE_DATA; + + +typedef struct { + EFI_EVENT Event; + EFI_STATUS Status; + union { + EFI_UDP4_RECEIVE_DATA *RxData; + EFI_UDP4_TRANSMIT_DATA *TxData; + } Packet; +} EFI_UDP4_COMPLETION_TOKEN; + +/** + Reads the current operational settings. + + @param This Pointer to the EFI_UDP4_PROTOCOL instance. + @param Udp4ConfigData Pointer to the buffer to receive the current configuration data. + @param Ip4ModeData Pointer to the EFI IPv4 Protocol mode data structure. + @param MnpConfigData Pointer to the managed network configuration data structure. + @param SnpModeData Pointer to the simple network mode data structure. + + @retval EFI_SUCCESS The mode data was read. + @retval EFI_NOT_STARTED When Udp4ConfigData is queried, no configuration data is + available because this instance has not been started. + @retval EFI_INVALID_PARAMETER This is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_GET_MODE_DATA) ( + IN EFI_UDP4_PROTOCOL *This, + OUT EFI_UDP4_CONFIG_DATA *Udp4ConfigData OPTIONAL, + OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL, + OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL, + OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL + ) +; + + +/** + Initializes, changes, or resets the operational parameters for this instance of the EFI UDPv4 + Protocol. + + @param This Pointer to the EFI_UDP4_PROTOCOL instance. + @param Udp4ConfigData Pointer to the buffer to receive the current configuration data. + + @retval EFI_SUCCESS The configuration settings were set, changed, or reset successfully. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE: + @retval EFI_ALREADY_STARTED The EFI UDPv4 Protocol instance is already started/configured + and must be stopped/reset before it can be reconfigured. + @retval EFI_ACCESS_DENIED UdpConfigData. AllowDuplicatePort is FALSE + and UdpConfigData.StationPort is already used by + other instance. + @retval EFI_OUT_OF_RESOURCES The EFI UDPv4 Protocol driver cannot allocate memory for this + EFI UDPv4 Protocol instance. + @retval EFI_DEVICE_ERROR An unexpected network or system error occurred and this instance + was not opened. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_CONFIGURE) ( + IN EFI_UDP4_PROTOCOL *This, + IN EFI_UDP4_CONFIG_DATA *UdpConfigData OPTIONAL + ) +; + +/** + Joins and leaves multicast groups. + + @param This Pointer to the EFI_UDP4_PROTOCOL instance. + @param JoinFlag Set to TRUE to join a multicast group. Set to FALSE to leave one + or all multicast groups. + @param MulticastAddress Pointer to multicast group address to join or leave. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED The EFI UDPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_OUT_OF_RESOURCES Could not allocate resources to join the group. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + - This is NULL. + - JoinFlag is TRUE and MulticastAddress is NULL. + - JoinFlag is TRUE and *MulticastAddress is not + a valid multicast address. + @retval EFI_ALREADY_STARTED The group address is already in the group table (when + JoinFlag is TRUE). + @retval EFI_NOT_FOUND The group address is not in the group table (when JoinFlag is + FALSE). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_GROUPS) ( + IN EFI_UDP4_PROTOCOL *This, + IN BOOLEAN JoinFlag, + IN EFI_IPv4_ADDRESS *MulticastAddress OPTIONAL + ) +; + +/** + Adds and deletes routing table entries. + + @param This Pointer to the EFI_UDP4_PROTOCOL instance. + @param DeleteRoute Set to TRUE to delete this route from the routing table. + Set to FALSE to add this route to the routing table. + @param SubnetAddress The destination network address that needs to be routed. + @param SubnetMask The subnet mask of SubnetAddress. + @param GatewayAddress The gateway IP address for this route. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_NOT_STARTED The EFI UDPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + - RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table. + @retval EFI_NOT_FOUND This route is not in the routing table. + @retval EFI_ACCESS_DENIED The route is already defined in the routing table. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_ROUTES) ( + IN EFI_UDP4_PROTOCOL *This, + IN BOOLEAN DeleteRoute, + IN EFI_IPv4_ADDRESS *SubnetAddress, + IN EFI_IPv4_ADDRESS *SubnetMask, + IN EFI_IPv4_ADDRESS *GatewayAddress + ) +; + +/** + Polls for incoming data packets and processes outgoing data packets. + + @param This Pointer to the EFI_UDP4_PROTOCOL instance. + + @retval EFI_SUCCESS Incoming or outgoing data was processed. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive queue. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_POLL) ( + IN EFI_UDP4_PROTOCOL *This + ) +; + +/** + Places an asynchronous receive request into the receiving queue. + + @param This Pointer to the EFI_UDP4_PROTOCOL instance. + @param Token Pointer to a token that is associated with the receive data + descriptor. + + @retval EFI_SUCCESS The receive completion token was cached. + @retval EFI_NOT_STARTED This EFI UDPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, RARP, etc.) + is not finished yet. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued due to a lack of system + resources (usually memory). + @retval EFI_DEVICE_ERROR An unexpected system or network error occurred. + @retval EFI_ACCESS_DENIED A receive completion token with the same Token.Event was already in + the receive queue. + @retval EFI_NOT_READY The receive request could not be queued because the receive queue is full. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_RECEIVE) ( + IN EFI_UDP4_PROTOCOL *This, + IN EFI_UDP4_COMPLETION_TOKEN *Token + ) +; + +/** + Queues outgoing data packets into the transmit queue. + + @param This Pointer to the EFI_UDP4_PROTOCOL instance. + @param Token Pointer to the completion token that will be placed into the + transmit queue. + + @retval EFI_SUCCESS The data has been queued for transmission. + @retval EFI_NOT_STARTED This EFI UDPv4 Protocol instance has not been started. + @retval EFI_NO_MAPPING When using a default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_ACCESS_DENIED The transmit completion token with the same + Token.Event was already in the transmit queue. + @retval EFI_NOT_READY The completion token could not be queued because the + transmit queue is full. + @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data. + @retval EFI_NOT_FOUND There is no route to the destination network or address. + @retval EFI_BAD_BUFFER_SIZE The data length is greater than the maximum UDP packet + size. Or the length of the IP header + UDP header + data + length is greater than MTU if DoNotFragment is TRUE. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_TRANSMIT) ( + IN EFI_UDP4_PROTOCOL *This, + IN EFI_UDP4_COMPLETION_TOKEN *Token + ) +; + +/** + Aborts an asynchronous transmit or receive request. + + @param This Pointer to the EFI_UDP4_PROTOCOL instance. + @param Token Pointer to a token that has been issued by + EFI_UDP4_PROTOCOL.Transmit() or + EFI_UDP4_PROTOCOL.Receive().If NULL, all pending + tokens are aborted. + + @retval EFI_SUCCESS The asynchronous I/O request was aborted and Token.Event + was signaled. When Token is NULL, all pending requests are + aborted and their events are signaled. + @retval EFI_INVALID_PARAMETER This is NULL. + @retval EFI_NOT_STARTED This instance has not been started. + @retval EFI_NO_MAPPING When using the default address, configuration (DHCP, BOOTP, + RARP, etc.) is not finished yet. + @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O request was + not found in the transmit or receive queue. It has either completed + or was not issued by Transmit() and Receive(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UDP4_CANCEL)( + IN EFI_UDP4_PROTOCOL *This, + IN EFI_UDP4_COMPLETION_TOKEN *Token OPTIONAL + ) +; + +struct _EFI_UDP4_PROTOCOL { + EFI_UDP4_GET_MODE_DATA GetModeData; + EFI_UDP4_CONFIGURE Configure; + EFI_UDP4_GROUPS Groups; + EFI_UDP4_ROUTES Routes; + EFI_UDP4_TRANSMIT Transmit; + EFI_UDP4_RECEIVE Receive; + EFI_UDP4_CANCEL Cancel; + EFI_UDP4_POLL Poll; +}; + +extern EFI_GUID gEfiUdp4ServiceBindingProtocolGuid; +extern EFI_GUID gEfiUdp4ProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/UgaDraw.h b/MdePkg/Include/Protocol/UgaDraw.h new file mode 100644 index 0000000000..5586bdfffb --- /dev/null +++ b/MdePkg/Include/Protocol/UgaDraw.h @@ -0,0 +1,168 @@ +/** @file + UGA Draw protocol from the EFI 1.1 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006, 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. + + Module Name: UgaDraw.h + +**/ + +#ifndef __UGA_DRAW_H__ +#define __UGA_DRAW_H__ + +#define EFI_UGA_DRAW_PROTOCOL_GUID \ + { \ + 0x982c298b, 0xf4fa, 0x41cb, {0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 } \ + } + +typedef struct _EFI_UGA_DRAW_PROTOCOL EFI_UGA_DRAW_PROTOCOL; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param HorizontalResolution Current video horizontal resolution in pixels + @param VerticalResolution Current video vertical resolution in pixels + @param ColorDepth Current video color depth in bits per pixel + @param RefreshRate Current video refresh rate in Hz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_GET_MODE) ( + IN EFI_UGA_DRAW_PROTOCOL *This, + OUT UINT32 *HorizontalResolution, + OUT UINT32 *VerticalResolution, + OUT UINT32 *ColorDepth, + OUT UINT32 *RefreshRate + ) +; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param HorizontalResolution Current video horizontal resolution in pixels + @param VerticalResolution Current video vertical resolution in pixels + @param ColorDepth Current video color depth in bits per pixel + @param RefreshRate Current video refresh rate in Hz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_SET_MODE) ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ) +; + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_UGA_PIXEL; + +typedef union { + EFI_UGA_PIXEL Pixel; + UINT32 Raw; +} EFI_UGA_PIXEL_UNION; + +typedef enum { + EfiUgaVideoFill, + EfiUgaVideoToBltBuffer, + EfiUgaBltBufferToVideo, + EfiUgaVideoToVideo, + EfiUgaBltMax +} EFI_UGA_BLT_OPERATION; + +/** + Type specifying a pointer to a function to perform an UGA Blt operation. + + The following table defines actions for BltOperations: + + EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + + EfiUgaVideoToBltBuffer - Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + + EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + + EfiUgaVideoToVideo - Copy from the video display rectangle (SourceX, SourceY) + (SourceX + Width, SourceY + Height) .to the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + + @param[in] This - Protocol instance pointer. + @param[in] BltBuffer - Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL) + @param[in] BltOperation - Operation to perform on BlitBuffer and video memory + @param[in] SourceX - X coordinate of source for the BltBuffer. + @param[in] SourceY - Y coordinate of source for the BltBuffer. + @param[in] DestinationX - X coordinate of destination for the BltBuffer. + @param[in] DestinationY - Y coordinate of destination for the BltBuffer. + @param[in] Width - Width of rectangle in BltBuffer in pixels. + @param[in] Height - Hight of rectangle in BltBuffer in pixels. + @param[in] Delta - OPTIONAL + + @retval EFI_SUCCESS - The Blt operation completed. + @retval EFI_INVALID_PARAMETER - BltOperation is not valid. + @retval EFI_DEVICE_ERROR - A hardware error occured writting to the video buffer. + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_BLT) ( + IN EFI_UGA_DRAW_PROTOCOL * This, + IN EFI_UGA_PIXEL * BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +struct _EFI_UGA_DRAW_PROTOCOL { + EFI_UGA_DRAW_PROTOCOL_GET_MODE GetMode; + EFI_UGA_DRAW_PROTOCOL_SET_MODE SetMode; + EFI_UGA_DRAW_PROTOCOL_BLT Blt; +}; + +extern EFI_GUID gEfiUgaDrawProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/UnicodeCollation.h b/MdePkg/Include/Protocol/UnicodeCollation.h new file mode 100644 index 0000000000..e0278038f7 --- /dev/null +++ b/MdePkg/Include/Protocol/UnicodeCollation.h @@ -0,0 +1,183 @@ +/** @file + Unicode Collation protocol that follows the EFI 1.0 specification. + + Copyright (c) 2006, 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. + + Module Name: UnicodeCollation.h + +**/ + +#ifndef __UNICODE_COLLATION_H__ +#define __UNICODE_COLLATION_H__ + +#define EFI_UNICODE_COLLATION_PROTOCOL_GUID \ + { \ + 0x1d85cd7f, 0xf43d, 0x11d2, {0x9a, 0xc, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +typedef struct _EFI_UNICODE_COLLATION_PROTOCOL EFI_UNICODE_COLLATION_PROTOCOL; + +// +// Protocol data structures and defines +// +#define EFI_UNICODE_BYTE_ORDER_MARK (CHAR16) (0xfeff) + +// +// Protocol member functions +// +/** + Performs a case-insensitive comparison of two Null-terminated Unicode + strings. + + @param This Protocol instance pointer. + @param Str1 A pointer to a Null-terminated Unicode string. + @param Str2 A pointer to a Null-terminated Unicode string. + + @retval 0 Str1 is equivalent to Str2 + @retval >_0 Str1 is lexically greater than Str2 + @retval <_0 Str1 is lexically less than Str2 + +**/ +typedef +INTN +(EFIAPI *EFI_UNICODE_COLLATION_STRICOLL) ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *Str1, + IN CHAR16 *Str2 + ) +; + +/** + Performs a case-insensitive comparison of a Null-terminated Unicode + pattern string and a Null-terminated Unicode string. + + @param This Protocol instance pointer. + @param String A pointer to a Null-terminated Unicode string. + @param Pattern A pointer to a Null-terminated Unicode pattern string. + + @retval TRUE Pattern was found in String. + @retval FALSE Pattern was not found in String. + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_UNICODE_COLLATION_METAIMATCH) ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN CHAR16 *Pattern + ) +; + +/** + Converts all the Unicode characters in a Null-terminated Unicode string to + lower case Unicode characters. + + @param This Protocol instance pointer. + @param String A pointer to a Null-terminated Unicode string. + + NONE + +**/ +typedef +VOID +(EFIAPI *EFI_UNICODE_COLLATION_STRLWR) ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ) +; + +/** + Converts all the Unicode characters in a Null-terminated Unicode string to upper + case Unicode characters. + + @param This Protocol instance pointer. + @param String A pointer to a Null-terminated Unicode string. + + NONE + +**/ +typedef +VOID +(EFIAPI *EFI_UNICODE_COLLATION_STRUPR) ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN OUT CHAR16 *Str + ) +; + +/** + Converts an 8.3 FAT file name in an OEM character set to a Null-terminated + Unicode string. + + @param This Protocol instance pointer. + @param FatSize The size of the string Fat in bytes. + @param Fat A pointer to a Null-terminated string that contains an 8.3 file + name using an OEM character set. + @param String A pointer to a Null-terminated Unicode string. The string must + be preallocated to hold FatSize Unicode characters. + + NONE + +**/ +typedef +VOID +(EFIAPI *EFI_UNICODE_COLLATION_FATTOSTR) ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN UINTN FatSize, + IN CHAR8 *Fat, + OUT CHAR16 *String + ) +; + +/** + Converts a Null-terminated Unicode string to legal characters in a FAT + filename using an OEM character set. + + @param This Protocol instance pointer. + @param String A pointer to a Null-terminated Unicode string. The string must + be preallocated to hold FatSize Unicode characters. + @param FatSize The size of the string Fat in bytes. + @param Fat A pointer to a Null-terminated string that contains an 8.3 file + name using an OEM character set. + + @retval TRUE Fat is a Long File Name + @retval FALSE Fat is an 8.3 file name + +**/ +typedef +BOOLEAN +(EFIAPI *EFI_UNICODE_COLLATION_STRTOFAT) ( + IN EFI_UNICODE_COLLATION_PROTOCOL *This, + IN CHAR16 *String, + IN UINTN FatSize, + OUT CHAR8 *Fat + ) +; + +struct _EFI_UNICODE_COLLATION_PROTOCOL { + // + // general + // + EFI_UNICODE_COLLATION_STRICOLL StriColl; + EFI_UNICODE_COLLATION_METAIMATCH MetaiMatch; + EFI_UNICODE_COLLATION_STRLWR StrLwr; + EFI_UNICODE_COLLATION_STRUPR StrUpr; + + // + // for supporting fat volumes + // + EFI_UNICODE_COLLATION_FATTOSTR FatToStr; + EFI_UNICODE_COLLATION_STRTOFAT StrToFat; + + CHAR8 *SupportedLanguages; +}; + +extern EFI_GUID gEfiUnicodeCollationProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/Usb2HostController.h b/MdePkg/Include/Protocol/Usb2HostController.h new file mode 100644 index 0000000000..5326d5b623 --- /dev/null +++ b/MdePkg/Include/Protocol/Usb2HostController.h @@ -0,0 +1,497 @@ +/** @file + EFI_USB2_HC_PROTOCOL as defined in UEFI 2.0. + + Copyright (c) 2006, 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. + + Module Name: Usb2HostController.h + +**/ + +#ifndef _USB2_HOSTCONTROLLER_H_ +#define _USB2_HOSTCONTROLLER_H_ + +#define EFI_USB2_HC_PROTOCOL_GUID \ + { \ + 0x3e745226, 0x9818, 0x45b6, {0xa2, 0xac, 0xd7, 0xcd, 0xe, 0x8b, 0xa2, 0xbc } \ + } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_USB2_HC_PROTOCOL EFI_USB2_HC_PROTOCOL; + +#define EFI_USB_SPEED_FULL 0x0000 // 12 Mb/s, USB 1.1 OHCI and UHCI HC. +#define EFI_USB_SPEED_LOW 0x0001 // 1 Mb/s, USB 1.1 OHCI and UHCI HC. +#define EFI_USB_SPEED_HIGH 0x0002 // 480 Mb/s, USB 2.0 EHCI HC. + +typedef struct { + UINT8 TranslatorHubAddress; + UINT8 TranslatorPortNumber; +} EFI_USB2_HC_TRANSACTION_TRANSLATOR; + +// +// Protocol definitions +// + +/** + Retrieves the Host Controller capabilities. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param MaxSpeed Host controller data transfer speed. + @param PortNumber Number of the root hub ports. + @param Is64BitCapable TRUE if controller supports 64-bit memory addressing, + FALSE otherwise. + + @retval EFI_SUCCESS The host controller capabilities were retrieved successfully. + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to + retrieve the capabilities. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_GET_CAPABILITY) ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT UINT8 *MaxSpeed, + OUT UINT8 *PortNumber, + OUT UINT8 *Is64BitCapable + ) +; + +/** + Provides software reset for the USB host controller. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param Attributes A bit mask of the reset operation to perform. + + @retval EFI_SUCCESS The reset operation succeeded. + @retval EFI_INVALID_PARAMETER Attributes is not valid. + @retval EFI_UNSUPPORTED The type of reset specified by Attributes is not currently + supported by the host controller hardware. + @retval EFI_ACCESS_DENIED Reset operation is rejected due to the debug port being configured + and active; only EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG or + EFI_USB_HC_RESET_HOST_WITH_DEBUG reset Attributes can be used to + perform reset operation for this host controller. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to + retrieve the capabilities. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_RESET) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT16 Attributes + ) +; + +/** + Retrieves current state of the USB host controller. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param State A pointer to the EFI_USB_HC_STATE data structure that + indicates current state of the USB host controller. + + @retval EFI_SUCCESS The state information of the host controller was returned in State. + @retval EFI_INVALID_PARAMETER State is NULL. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the + host controller¡¯s current state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_GET_STATE) ( + IN EFI_USB2_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ) +; + +/** + Sets the USB host controller to a specific state. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param State Indicates the state of the host controller that will be set. + + @retval EFI_SUCCESS The USB host controller was successfully placed in the state + specified by State. + @retval EFI_INVALID_PARAMETER State is not valid. + @retval EFI_DEVICE_ERROR Failed to set the state specified by State due to device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_SET_STATE) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ) +; + +/** + Submits control transfer to a target USB device. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param DeviceSpeed Indicates device speed. + @param MaximumPacketLength Indicates the maximum packet size that the default control transfer + endpoint is capable of sending or receiving. + @param Request A pointer to the USB device request that will be sent to the USB device. + @param TransferDirection Specifies the data direction for the transfer. There are three values + available, EfiUsbDataIn, EfiUsbDataOut and EfiUsbNoData. + @param Data A pointer to the buffer of data that will be transmitted to USB device or + received from USB device. + @param DataLength On input, indicates the size, in bytes, of the data buffer specified by Data. + On output, indicates the amount of data actually transferred. + @param Translator A pointer to the transaction translator data. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer is + allowed to complete. + @param TransferResult A pointer to the detailed result information generated by this control + transfer. + + @retval EFI_SUCCESS The control transfer was completed successfully. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due to a lack of resources. + @retval EFI_TIMEOUT The control transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The control transfer failed due to host controller or device error. + Caller should check TransferResult for detailed error information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_CONTROL_TRANSFER) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data OPTIONAL, + IN OUT UINTN *DataLength OPTIONAL, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +; + +#define EFI_USB_MAX_BULK_BUFFER_NUM 10 + +/** + Submits bulk transfer to a bulk endpoint of a USB device. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param EndPointAddress The combination of an endpoint number and an endpoint direction of the + target USB device. + @param DeviceSpeed Indicates device speed. + @param MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of + sending or receiving. + @param DataBuffersNumber Number of data buffers prepared for the transfer. + @param Data Array of pointers to the buffers of data that will be transmitted to USB + device or received from USB device. + @param DataLength When input, indicates the size, in bytes, of the data buffers specified by + Data. When output, indicates the actually transferred data size. + @param DataToggle A pointer to the data toggle value. + @param Translator A pointer to the transaction translator data. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer is + allowed to complete. + @param TransferResult A pointer to the detailed result information of the bulk transfer. + + @retval EFI_SUCCESS The bulk transfer was completed successfully. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The bulk transfer could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The bulk transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error. + Caller should check TransferResult for detailed error information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_BULK_TRANSFER) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_BULK_BUFFER_NUM], + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +; + +/** + Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param EndPointAddress The combination of an endpoint number and an endpoint direction of the + target USB device. + @param DeviceSpeed Indicates device speed. + @param MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of + sending or receiving. + @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between the host and the + target interrupt endpoint. If FALSE, the specified asynchronous interrupt + pipe is canceled. If TRUE, and an interrupt transfer exists for the target + end point, then EFI_INVALID_PARAMETER is returned. + @param DataToggle A pointer to the data toggle value. + @param PollingInterval Indicates the interval, in milliseconds, that the asynchronous interrupt + transfer is polled. + @param DataLength Indicates the length of data to be received at the rate specified by + PollingInterval from the target asynchronous interrupt endpoint. + @param CallBackFunction The Callback function. This function is called at the rate specified by + PollingInterval. + @param Context The context that is passed to the CallBackFunction. This is an + optional parameter and may be NULL. + + @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully + submitted or canceled. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_ASYNC_INTERRUPT_TRANSFER) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaxiumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval OPTIONAL, + IN UINTN DataLength OPTIONAL, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL, + IN VOID *Context OPTIONAL + ) +; + +/** + Submits synchronous interrupt transfer to an interrupt endpoint of a USB device. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param EndPointAddress The combination of an endpoint number and an endpoint direction of the + target USB device. + @param DeviceSpeed Indicates device speed. + @param MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of + sending or receiving. + @param Data A pointer to the buffer of data that will be transmitted to USB device or + received from USB device. + @param DataLength On input, the size, in bytes, of the data buffer specified by Data. On + output, the number of bytes transferred. + @param DataToggle A pointer to the data toggle value. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer is + allowed to complete. + @param TransferResult A pointer to the detailed result information from the synchronous + interrupt transfer. + + @retval EFI_SUCCESS The synchronous interrupt transfer was completed successfully. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The synchronous interrupt transfer could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The synchronous interrupt transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The synchronous interrupt transfer failed due to host controller or device error. + Caller should check TransferResult for detailed error information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_SYNC_INTERRUPT_TRANSFER) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ) +; + +#define EFI_USB_MAX_ISO_BUFFER_NUM 7 +#define EFI_USB_MAX_ISO_BUFFER_NUM1 2 + +/** + Submits isochronous transfer to an isochronous endpoint of a USB device. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param EndPointAddress The combination of an endpoint number and an endpoint direction of the + target USB device. + @param DeviceSpeed Indicates device speed. + @param MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of + sending or receiving. + @param DataBuffersNumber Number of data buffers prepared for the transfer. + @param Data Array of pointers to the buffers of data that will be transmitted to USB + device or received from USB device. + @param DataLength Specifies the length, in bytes, of the data to be sent to or received from + the USB device. + @param Translator A pointer to the transaction translator data. + @param TransferResult A pointer to the detailed result information of the isochronous transfer. + + @retval EFI_SUCCESS The isochronous transfer was completed successfully. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The isochronous transfer could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The isochronous transfer cannot be completed within the one USB frame time. + @retval EFI_DEVICE_ERROR The isochronous transfer failed due to host controller or device error. + Caller should check TransferResult for detailed error information. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_ISOCHRONOUS_TRANSFER) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + OUT UINT32 *TransferResult + ) +; + +/** + Submits nonblocking isochronous transfer to an isochronous endpoint of a USB device. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB. + @param EndPointAddress The combination of an endpoint number and an endpoint direction of the + target USB device. + @param DeviceSpeed Indicates device speed. + @param MaximumPacketLength Indicates the maximum packet size the target endpoint is capable of + sending or receiving. + @param DataBuffersNumber Number of data buffers prepared for the transfer. + @param Data Array of pointers to the buffers of data that will be transmitted to USB + device or received from USB device. + @param DataLength Specifies the length, in bytes, of the data to be sent to or received from + the USB device. + @param Translator A pointer to the transaction translator data. + @param IsochronousCallback The Callback function. This function is called if the requested + isochronous transfer is completed. + @param Context Data passed to the IsochronousCallback function. This is an + optional parameter and may be NULL. + + @retval EFI_SUCCESS The asynchronous isochronous transfer request has been successfully + submitted or canceled. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The asynchronous isochronous transfer could not be submitted due to + a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_ASYNC_ISOCHRONOUS_TRANSFER) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 DeviceSpeed, + IN UINTN MaximumPacketLength, + IN UINT8 DataBuffersNumber, + IN OUT VOID *Data[EFI_USB_MAX_ISO_BUFFER_NUM], + IN UINTN DataLength, + IN EFI_USB2_HC_TRANSACTION_TRANSLATOR *Translator, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ) +; + +/** + Retrieves the current status of a USB root hub port. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port from which the status is to be retrieved. + This value is zero based. + @param PortStatus A pointer to the current port status bits and port status change bits. + + @retval EFI_SUCCESS The status of the USB root hub port specified by PortNumber + was returned in PortStatus. + @retval EFI_INVALID_PARAMETER PortNumber is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_GET_ROOTHUB_PORT_STATUS) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ) +; + +/** + Sets a feature for the specified root hub port. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port whose feature is requested to be set. This + value is zero based. + @param PortFeature Indicates the feature selector associated with the feature set request. + + @retval EFI_SUCCESS The feature specified by PortFeature was set for the USB + root hub port specified by PortNumber. + @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid for this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_SET_ROOTHUB_PORT_FEATURE) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +; + +/** + Clears a feature for the specified root hub port. + + @param This A pointer to the EFI_USB2_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port whose feature is requested to be cleared. This + value is zero based. + @param PortFeature Indicates the feature selector associated with the feature clear request. + + @retval EFI_SUCCESS The feature specified by PortFeature was cleared for the USB + root hub port specified by PortNumber. + @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid for this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB2_HC_PROTOCOL_CLEAR_ROOTHUB_PORT_FEATURE) ( + IN EFI_USB2_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ) +; + +struct _EFI_USB2_HC_PROTOCOL { + EFI_USB2_HC_PROTOCOL_GET_CAPABILITY GetCapability; + EFI_USB2_HC_PROTOCOL_RESET Reset; + EFI_USB2_HC_PROTOCOL_GET_STATE GetState; + EFI_USB2_HC_PROTOCOL_SET_STATE SetState; + EFI_USB2_HC_PROTOCOL_CONTROL_TRANSFER ControlTransfer; + EFI_USB2_HC_PROTOCOL_BULK_TRANSFER BulkTransfer; + EFI_USB2_HC_PROTOCOL_ASYNC_INTERRUPT_TRANSFER AsyncInterruptTransfer; + EFI_USB2_HC_PROTOCOL_SYNC_INTERRUPT_TRANSFER SyncInterruptTransfer; + EFI_USB2_HC_PROTOCOL_ISOCHRONOUS_TRANSFER IsochronousTransfer; + EFI_USB2_HC_PROTOCOL_ASYNC_ISOCHRONOUS_TRANSFER AsyncIsochronousTransfer; + EFI_USB2_HC_PROTOCOL_GET_ROOTHUB_PORT_STATUS GetRootHubPortStatus; + EFI_USB2_HC_PROTOCOL_SET_ROOTHUB_PORT_FEATURE SetRootHubPortFeature; + EFI_USB2_HC_PROTOCOL_CLEAR_ROOTHUB_PORT_FEATURE ClearRootHubPortFeature; + UINT16 MajorRevision; + UINT16 MinorRevision; +}; + +extern EFI_GUID gEfiUsb2HcProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/UsbHostController.h b/MdePkg/Include/Protocol/UsbHostController.h new file mode 100644 index 0000000000..f816d73002 --- /dev/null +++ b/MdePkg/Include/Protocol/UsbHostController.h @@ -0,0 +1,446 @@ +/** @file + EFI_USB_HC_PROTOCOL as defined in EFI 1.10. + + Copyright (c) 2006, 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. + + Module Name: UsbHostController.h + +**/ + +#ifndef _USB_HOSTCONTROLLER_H_ +#define _USB_HOSTCONTROLLER_H_ + +#define EFI_USB_HC_PROTOCOL_GUID \ + { \ + 0xf5089266, 0x1aa0, 0x4953, {0x97, 0xd8, 0x56, 0x2f, 0x8a, 0x73, 0xb5, 0x19 } \ + } + +// +// Forward reference for pure ANSI compatability +// +typedef struct _EFI_USB_HC_PROTOCOL EFI_USB_HC_PROTOCOL; + +// +// Protocol definitions +// + +/** + Provides software reset for the USB host controller. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param Attributes A bit mask of the reset operation to perform. + + @retval EFI_SUCCESS The reset operation succeeded. + @retval EFI_UNSUPPORTED The type of reset specified by Attributes is not currently supported + by the host controller hardware. + @retval EFI_INVALID_PARAMETER Attributes is not valid. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to perform the reset operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_RESET) ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT16 Attributes + ); + +/** + Retrieves current state of the USB host controller. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param State A pointer to the EFI_USB_HC_STATE data structure that + indicates current state of the USB host controller. + + @retval EFI_SUCCESS The state information of the host controller was returned in State. + @retval EFI_INVALID_PARAMETER State is NULL. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the host controller¡¯s + current state. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_GET_STATE) ( + IN EFI_USB_HC_PROTOCOL *This, + OUT EFI_USB_HC_STATE *State + ); + +/** + Sets the USB host controller to a specific state. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param State Indicates the state of the host controller that will be set. + + @retval EFI_SUCCESS The USB host controller was successfully placed in the state specified by + State. + @retval EFI_INVALID_PARAMETER State is NULL. + @retval EFI_DEVICE_ERROR Failed to set the state specified by State due to device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_SET_STATE) ( + IN EFI_USB_HC_PROTOCOL *This, + IN EFI_USB_HC_STATE State + ); + +/** + Submits control transfer to a target USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param IsSlowDevice Indicates whether the target device is slow device or full-speed + device. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param Request A pointer to the USB device request that will be sent to the USB + device. + @param TransferDirection Specifies the data direction for the transfer. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength On input, indicates the size, in bytes, of the data buffer specified + by Data. On output, indicates the amount of data actually + transferred. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer + is allowed to complete. + @param TransferResult A pointer to the detailed result information generated by this + control transfer. + + @retval EFI_SUCCESS The control transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The control transfer could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The control transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The control transfer failed due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_CONTROL_TRANSFER) ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaximumPacketLength, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION TransferDirection, + IN OUT VOID *Data OPTIONAL, + IN OUT UINTN *DataLength OPTIONAL, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); + +/** + Submits bulk transfer to a bulk endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength On input, indicates the size, in bytes, of the data buffer specified + by Data. On output, indicates the amount of data actually + transferred. + @param DataToggle A pointer to the data toggle value. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer + is allowed to complete. + @param TransferResult A pointer to the detailed result information of the bulk transfer. + + @retval EFI_SUCCESS The bulk transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The bulk transfer could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The bulk transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_BULK_TRANSFER) ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); + +/** + Submits an asynchronous interrupt transfer to an interrupt endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. + @param IsSlowDevice Indicates whether the target device is slow device or full-speed + device. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param IsNewTransfer If TRUE, an asynchronous interrupt pipe is built between the host + and the target interrupt endpoint. If FALSE, the specified + + @param DataToggle A pointer to the data toggle value. + @param PollingInterval Indicates the interval, in milliseconds, that the asynchronous + interrupt transfer is polled. asynchronous interrupt pipe is canceled. + @param DataLength Indicates the length of data to be received at the rate specified by + PollingInterval from the target asynchronous interrupt + endpoint. + @param CallBackFunction The Callback function. + @param Context The context that is passed to the CallBackFunction. + + @retval EFI_SUCCESS The asynchronous interrupt transfer request has been successfully + submitted or canceled. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The bulk transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The bulk transfer failed due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_ASYNC_INTERRUPT_TRANSFER) ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaxiumPacketLength, + IN BOOLEAN IsNewTransfer, + IN OUT UINT8 *DataToggle, + IN UINTN PollingInterval OPTIONAL, + IN UINTN DataLength OPTIONAL, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK CallBackFunction OPTIONAL, + IN VOID *Context OPTIONAL + ); + +/** + Submits synchronous interrupt transfer to an interrupt endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. + @param IsSlowDevice Indicates whether the target device is slow device or full-speed + device. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. asynchronous interrupt pipe is canceled. + @param DataLength On input, the size, in bytes, of the data buffer specified by Data. + On output, the number of bytes transferred. + @param DataToggle A pointer to the data toggle value. + @param TimeOut Indicates the maximum time, in milliseconds, which the transfer + is allowed to complete. + @param TransferResult A pointer to the detailed result information from the synchronous + interrupt transfer. + + @retval EFI_SUCCESS The synchronous interrupt transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The synchronous interrupt transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The synchronous interrupt transfer failed due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_SYNC_INTERRUPT_TRANSFER) ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN BOOLEAN IsSlowDevice, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN OUT UINT8 *DataToggle, + IN UINTN TimeOut, + OUT UINT32 *TransferResult + ); + +/** + Submits isochronous transfer to an isochronous endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. asynchronous interrupt pipe is canceled. + @param DataLength Specifies the length, in bytes, of the data to be sent to or received + from the USB device. + @param TransferResult A pointer to the detailed result information from the isochronous + transfer. + + @retval EFI_SUCCESS The isochronous transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The isochronous could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + @retval EFI_TIMEOUT The isochronous transfer failed due to timeout. + @retval EFI_DEVICE_ERROR The isochronous transfer failed due to host controller or device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_ISOCHRONOUS_TRANSFER) ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN UINTN DataLength, + OUT UINT32 *TransferResult + ); + +/** + Submits nonblocking isochronous transfer to an isochronous endpoint of a USB device. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param DeviceAddress Represents the address of the target device on the USB, which is + assigned during USB enumeration. + @param EndPointAddress The combination of an endpoint number and an endpoint + direction of the target USB device. + @param MaximumPacketLength Indicates the maximum packet size that the default control + transfer endpoint is capable of sending or receiving. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. asynchronous interrupt pipe is canceled. + @param DataLength Specifies the length, in bytes, of the data to be sent to or received + from the USB device. + @param IsochronousCallback The Callback function. + @param Context Data passed to the IsochronousCallback function. This is + an optional parameter and may be NULL. + + @retval EFI_SUCCESS The asynchronous isochronous transfer was completed successfully. + @retval EFI_OUT_OF_RESOURCES The asynchronous isochronous could not be completed due to a lack of resources. + @retval EFI_INVALID_PARAMETER Some parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_ASYNC_ISOCHRONOUS_TRANSFER) ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 DeviceAddress, + IN UINT8 EndPointAddress, + IN UINT8 MaximumPacketLength, + IN OUT VOID *Data, + IN UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ); + +/** + Retrieves the number of root hub ports. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param PortNumber A pointer to the number of the root hub ports. + + @retval EFI_SUCCESS The port number was retrieved successfully. + @retval EFI_DEVICE_ERROR An error was encountered while attempting to retrieve the port number. + @retval EFI_INVALID_PARAMETER PortNumber is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_GET_ROOTHUB_PORT_NUMBER) ( + IN EFI_USB_HC_PROTOCOL *This, + OUT UINT8 *PortNumber + ); + +/** + Retrieves the current status of a USB root hub port. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port from which the status is to be retrieved. + This value is zero based. + @param PortStatus A pointer to the current port status bits and port status change bits. + + @retval EFI_SUCCESS The status of the USB root hub port specified by PortNumber + was returned in PortStatus. + @retval EFI_INVALID_PARAMETER PortNumber is invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_GET_ROOTHUB_PORT_STATUS) ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + OUT EFI_USB_PORT_STATUS *PortStatus + ); + +/** + Sets a feature for the specified root hub port. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port from which the status is to be retrieved. + This value is zero based. + @param PortFeature Indicates the feature selector associated with the feature set + request. + + @retval EFI_SUCCESS The feature specified by PortFeature was set for the USB + root hub port specified by PortNumber. + @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid for this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_SET_ROOTHUB_PORT_FEATURE) ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + +/** + Clears a feature for the specified root hub port. + + @param This A pointer to the EFI_USB_HC_PROTOCOL instance. + @param PortNumber Specifies the root hub port from which the status is to be cleared. + This value is zero based. + @param PortFeature Indicates the feature selector associated with the feature clear + request. + + @retval EFI_SUCCESS The feature specified by PortFeature was cleared for the USB + root hub port specified by PortNumber. + @retval EFI_INVALID_PARAMETER PortNumber is invalid or PortFeature is invalid for this function. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_HC_PROTOCOL_CLEAR_ROOTHUB_PORT_FEATURE) ( + IN EFI_USB_HC_PROTOCOL *This, + IN UINT8 PortNumber, + IN EFI_USB_PORT_FEATURE PortFeature + ); + +struct _EFI_USB_HC_PROTOCOL { + EFI_USB_HC_PROTOCOL_RESET Reset; + EFI_USB_HC_PROTOCOL_GET_STATE GetState; + EFI_USB_HC_PROTOCOL_SET_STATE SetState; + EFI_USB_HC_PROTOCOL_CONTROL_TRANSFER ControlTransfer; + EFI_USB_HC_PROTOCOL_BULK_TRANSFER BulkTransfer; + EFI_USB_HC_PROTOCOL_ASYNC_INTERRUPT_TRANSFER AsyncInterruptTransfer; + EFI_USB_HC_PROTOCOL_SYNC_INTERRUPT_TRANSFER SyncInterruptTransfer; + EFI_USB_HC_PROTOCOL_ISOCHRONOUS_TRANSFER IsochronousTransfer; + EFI_USB_HC_PROTOCOL_ASYNC_ISOCHRONOUS_TRANSFER AsyncIsochronousTransfer; + EFI_USB_HC_PROTOCOL_GET_ROOTHUB_PORT_NUMBER GetRootHubPortNumber; + EFI_USB_HC_PROTOCOL_GET_ROOTHUB_PORT_STATUS GetRootHubPortStatus; + EFI_USB_HC_PROTOCOL_SET_ROOTHUB_PORT_FEATURE SetRootHubPortFeature; + EFI_USB_HC_PROTOCOL_CLEAR_ROOTHUB_PORT_FEATURE ClearRootHubPortFeature; + UINT16 MajorRevision; + UINT16 MinorRevision; +}; + +extern EFI_GUID gEfiUsbHcProtocolGuid; + +#endif diff --git a/MdePkg/Include/Protocol/UsbIo.h b/MdePkg/Include/Protocol/UsbIo.h new file mode 100644 index 0000000000..30309e3035 --- /dev/null +++ b/MdePkg/Include/Protocol/UsbIo.h @@ -0,0 +1,418 @@ +/** @file + EFI Usb I/O Protocol + + Copyright (c) 2006, 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. + + Module Name: UsbIo.h + +**/ + +#ifndef __USB_IO_H__ +#define __USB_IO_H__ + +// +// Global ID for the USB I/O Protocol +// +#define EFI_USB_IO_PROTOCOL_GUID \ + { \ + 0x2B2F68D6, 0x0CD2, 0x44cf, {0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 } \ + } + +typedef struct _EFI_USB_IO_PROTOCOL EFI_USB_IO_PROTOCOL; + +/** + Async USB transfer callback routine. + + @param Data Data received or sent via the USB Asynchronous Transfer, if the + transfer completed successfully. + @param DataLength The length of Data received or sent via the Asynchronous + Transfer, if transfer successfully completes. + @param Context Data passed from UsbAsyncInterruptTransfer() request. + @param Status Indicates the result of the asynchronous transfer. + + @retval EFI_SUCCESS The asynchronous USB transfer request has been successfully executed. + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request failed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ASYNC_USB_TRANSFER_CALLBACK) ( + IN VOID *Data, + IN UINTN DataLength, + IN VOID *Context, + IN UINT32 Status + ); + +// +// Prototype for EFI USB I/O protocol +// + + +/** + This function is used to manage a USB device with a control transfer pipe. A control transfer is + typically used to perform device initialization and configuration. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param Request A pointer to the USB device request that will be sent to the USB + device. + @param Direction Indicates the data direction. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param Timeout Indicating the transfer should be completed within this time frame. + The units are in milliseconds. + @param DataLength The size, in bytes, of the data buffer specified by Data. + @param Status A pointer to the result of the USB transfer. + + @retval EFI_SUCCESS The control transfer has been successfully executed. + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status is returned in Status. + @retval EFI_INVALID_PARAMETE 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_TIMEOUT The control transfer fails due to timeout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_CONTROL_TRANSFER) ( + IN EFI_USB_IO_PROTOCOL *This, + IN EFI_USB_DEVICE_REQUEST *Request, + IN EFI_USB_DATA_DIRECTION Direction, + IN UINT32 Timeout, + IN OUT VOID *Data OPTIONAL, + IN UINTN DataLength OPTIONAL, + OUT UINT32 *Status + ); + +/** + This function is used to manage a USB device with the bulk transfer pipe. Bulk Transfers are + typically used to transfer large amounts of data to/from USB devices. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceEndpoint A pointer to the USB device request that will be sent to the USB + device. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength The size, in bytes, of the data buffer specified by Data. + @param Timeout Indicating the transfer should be completed within this time frame. + The units are in milliseconds. + @param Status This parameter indicates the USB transfer status. + + @retval EFI_SUCCESS The bulk transfer has been successfully executed. + @retval EFI_DEVICE_ERROR The transfer failed. The transfer status is returned in Status. + @retval EFI_INVALID_PARAMETE One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The control transfer fails due to timeout. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_BULK_TRANSFER) ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout, + OUT UINT32 *Status + ); + +/** + This function is used to manage a USB device with an interrupt transfer pipe. An Asynchronous + Interrupt Transfer is typically used to query a device¡¯s status at a fixed rate. For example, + keyboard, mouse, and hub devices use this type of transfer to query their interrupt endpoints at + a fixed rate. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceEndpoint A pointer to the USB device request that will be sent to the USB + device. + @param IsNewTransfer If TRUE, a new transfer will be submitted to USB controller. If + FALSE, the interrupt transfer is deleted from the device¡¯s interrupt + transfer queue. + @param PollingInterval Indicates the periodic rate, in milliseconds, that the transfer is to be + executed. + @param DataLength Specifies the length, in bytes, of the data to be received from the + USB device. + @param Context Data passed to the InterruptCallback function. + @param InterruptCallback The Callback function. This function is called if the asynchronous + interrupt transfer is completed. + + @retval EFI_SUCCESS The asynchronous USB transfer request transfer has been successfully executed. + @retval EFI_DEVICE_ERROR The asynchronous USB transfer request failed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_ASYNC_INTERRUPT_TRANSFER) ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN BOOLEAN IsNewTransfer, + IN UINTN PollingInterval OPTIONAL, + IN UINTN DataLength OPTIONAL, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK InterruptCallBack OPTIONAL, + IN VOID *Context OPTIONAL + ); + +/** + This function is used to manage a USB device with an interrupt transfer pipe. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceEndpoint A pointer to the USB device request that will be sent to the USB + device. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength On input, then size, in bytes, of the buffer Data. On output, the + amount of data actually transferred. + @param Timeout The time out, in seconds, for this transfer. + @param Status This parameter indicates the USB transfer status. + + @retval EFI_SUCCESS The sync interrupt transfer has been successfully executed. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The sync interrupt transfer request failed. + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The transfer fails due to timeout. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_SYNC_INTERRUPT_TRANSFER) ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN OUT UINTN *DataLength, + IN UINTN Timeout, + OUT UINT32 *Status + ); + +/** + This function is used to manage a USB device with an isochronous transfer pipe. An Isochronous + transfer is typically used to transfer streaming data. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceEndpoint A pointer to the USB device request that will be sent to the USB + device. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength The size, in bytes, of the data buffer specified by Data. + @param Status This parameter indicates the USB transfer status. + + @retval EFI_SUCCESS The isochronous transfer has been successfully executed. + @retval EFI_INVALID_PARAMETER The parameter DeviceEndpoint is not valid. + @retval EFI_DEVICE_ERROR The transfer failed due to the reason other than timeout, The error status + is returned in Status. + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to a lack of resources. + @retval EFI_TIMEOUT The transfer fails due to timeout. +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_ISOCHRONOUS_TRANSFER) ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN UINTN DataLength, + OUT UINT32 *Status + ); + +/** + This function is used to manage a USB device with an isochronous transfer pipe. An Isochronous + transfer is typically used to transfer streaming data. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceEndpoint A pointer to the USB device request that will be sent to the USB + device. + @param Data A pointer to the buffer of data that will be transmitted to USB + device or received from USB device. + @param DataLength The size, in bytes, of the data buffer specified by Data. + @param Context Data passed to the IsochronousCallback() function. + @param IsochronousCallback The IsochronousCallback() function. + + @retval EFI_SUCCESS The asynchronous isochronous transfer has been successfully submitted + to the system. + @retval EFI_INVALID_PARAMETER The parameter DeviceEndpoint is not valid. + @retval EFI_OUT_OF_RESOURCES The request could not be submitted due to a lack of resources. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_ASYNC_ISOCHRONOUS_TRANSFER) ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 DeviceEndpoint, + IN OUT VOID *Data, + IN UINTN DataLength, + IN EFI_ASYNC_USB_TRANSFER_CALLBACK IsochronousCallBack, + IN VOID *Context OPTIONAL + ); + +/** + Resets and reconfigures the USB controller. This function will work for all USB devices except + USB Hub Controllers. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + + @retval EFI_SUCCESS The USB controller was reset. + @retval EFI_INVALID_PARAMETER If the controller specified by This is a USB hub. + @retval EFI_DEVICE_ERROR An error occurred during the reconfiguration process. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_PORT_RESET) ( + IN EFI_USB_IO_PROTOCOL *This + ); + +/** + Retrieves the USB Device Descriptor. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param DeviceDescriptor A pointer to the caller allocated USB Device Descriptor. + + @retval EFI_SUCCESS The device descriptor was retrieved successfully. + @retval EFI_INVALID_PARAMETER DeviceDescriptor is NULL. + @retval EFI_NOT_FOUND The device descriptor was not found. The device may not be configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_DEVICE_DESCRIPTOR) ( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_DEVICE_DESCRIPTOR *DeviceDescriptor + ); + +/** + Retrieves the USB Device Descriptor. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param ConfigurationDescriptor A pointer to the caller allocated USB Active Configuration + Descriptor. + @retval EFI_SUCCESS The active configuration descriptor was retrieved successfully. + @retval EFI_INVALID_PARAMETER ConfigurationDescriptor is NULL. + @retval EFI_NOT_FOUND An active configuration descriptor cannot be found. The device may not + be configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_CONFIG_DESCRIPTOR) ( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_CONFIG_DESCRIPTOR *ConfigurationDescriptor + ); + +/** + Retrieves the Interface Descriptor for a USB Device Controller. As stated earlier, an interface + within a USB device is equivalently to a USB Controller within the current configuration. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param InterfaceDescriptor A pointer to the caller allocated USB Interface Descriptor within + the configuration setting. + @retval EFI_SUCCESS The interface descriptor retrieved successfully. + @retval EFI_INVALID_PARAMETER InterfaceDescriptor is NULL. + @retval EFI_NOT_FOUND The interface descriptor cannot be found. The device may not be + correctly configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_INTERFACE_DESCRIPTOR) ( + IN EFI_USB_IO_PROTOCOL *This, + OUT EFI_USB_INTERFACE_DESCRIPTOR *InterfaceDescriptor + ); + +/** + Retrieves an Endpoint Descriptor within a USB Controller. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param EndpointIndex Indicates which endpoint descriptor to retrieve. + @param EndpointDescriptor A pointer to the caller allocated USB Endpoint Descriptor of + a USB controller. + + @retval EFI_SUCCESS The endpoint descriptor was retrieved successfully. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_NOT_FOUND The endpoint descriptor cannot be found. The device may not be + correctly configured. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_ENDPOINT_DESCRIPTOR) ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT8 EndpointIndex, + OUT EFI_USB_ENDPOINT_DESCRIPTOR *EndpointDescriptor + ); + +/** + Retrieves a Unicode string stored in a USB Device. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param LangID The Language ID for the string being retrieved. + @param StringID The ID of the string being retrieved. + @param String A pointer to a buffer allocated by this function with + AllocatePool() to store the string. + + @retval EFI_SUCCESS The string was retrieved successfully. + @retval EFI_NOT_FOUND The string specified by LangID and StringID was not found. + @retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate the return buffer String. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_STRING_DESCRIPTOR) ( + IN EFI_USB_IO_PROTOCOL *This, + IN UINT16 LangID, + IN UINT8 StringID, + OUT CHAR16 **String + ); + +/** + Retrieves all the language ID codes that the USB device supports. + + @param This A pointer to the EFI_USB_IO_PROTOCOL instance. + @param LangIDTable Language ID for the string the caller wants to get. + @param TableSize The size, in bytes, of the table LangIDTable. + + @retval EFI_SUCCESS The support languages were retrieved successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_USB_IO_GET_SUPPORTED_LANGUAGE) ( + IN EFI_USB_IO_PROTOCOL *This, + OUT UINT16 **LangIDTable, + OUT UINT16 *TableSize + ); + +// +// Protocol Interface Structure +// +struct _EFI_USB_IO_PROTOCOL { + // + // IO transfer + // + EFI_USB_IO_CONTROL_TRANSFER UsbControlTransfer; + EFI_USB_IO_BULK_TRANSFER UsbBulkTransfer; + EFI_USB_IO_ASYNC_INTERRUPT_TRANSFER UsbAsyncInterruptTransfer; + EFI_USB_IO_SYNC_INTERRUPT_TRANSFER UsbSyncInterruptTransfer; + EFI_USB_IO_ISOCHRONOUS_TRANSFER UsbIsochronousTransfer; + EFI_USB_IO_ASYNC_ISOCHRONOUS_TRANSFER UsbAsyncIsochronousTransfer; + + // + // Common device request + // + EFI_USB_IO_GET_DEVICE_DESCRIPTOR UsbGetDeviceDescriptor; + EFI_USB_IO_GET_CONFIG_DESCRIPTOR UsbGetConfigDescriptor; + EFI_USB_IO_GET_INTERFACE_DESCRIPTOR UsbGetInterfaceDescriptor; + EFI_USB_IO_GET_ENDPOINT_DESCRIPTOR UsbGetEndpointDescriptor; + EFI_USB_IO_GET_STRING_DESCRIPTOR UsbGetStringDescriptor; + EFI_USB_IO_GET_SUPPORTED_LANGUAGE UsbGetSupportedLanguages; + + // + // Reset controller's parent port + // + EFI_USB_IO_PORT_RESET UsbPortReset; +}; + +extern EFI_GUID gEfiUsbIoProtocolGuid; + +#endif diff --git a/MdePkg/Include/ToBeRemoved/Variable.h b/MdePkg/Include/ToBeRemoved/Variable.h new file mode 100644 index 0000000000..bc0d6408d7 --- /dev/null +++ b/MdePkg/Include/ToBeRemoved/Variable.h @@ -0,0 +1,78 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EfiVariable.h + +Abstract: + + Header file for EFI Variable Services + +--*/ + +#ifndef _EFI_VARIABLE_H_ +#define _EFI_VARIABLE_H_ + +#define VARIABLE_STORE_SIGNATURE EFI_SIGNATURE_32 ('$', 'V', 'S', 'S') + +#define MAX_VARIABLE_SIZE 1024 + +#define VARIABLE_DATA 0x55AA + +// +// Variable Store Header flags +// +#define VARIABLE_STORE_FORMATTED 0x5a +#define VARIABLE_STORE_HEALTHY 0xfe + +// +// Variable Store Status +// +typedef enum { + EfiRaw, + EfiValid, + EfiInvalid, + EfiUnknown +} VARIABLE_STORE_STATUS; + +// +// Variable State flags +// +#define VAR_IN_DELETED_TRANSITION 0xfe // Variable is in obsolete transistion +#define VAR_DELETED 0xfd // Variable is obsolete +#define VAR_ADDED 0x7f // Variable has been completely added +#define IS_VARIABLE_STATE(_c, _Mask) (BOOLEAN) (((~_c) & (~_Mask)) != 0) + +#pragma pack(1) + +typedef struct { + UINT32 Signature; + UINT32 Size; + UINT8 Format; + UINT8 State; + UINT16 Reserved; + UINT32 Reserved1; +} VARIABLE_STORE_HEADER; + +typedef struct { + UINT16 StartId; + UINT8 State; + UINT8 Reserved; + UINT32 Attributes; + UINTN NameSize; + UINTN DataSize; + EFI_GUID VendorGuid; +} VARIABLE_HEADER; + +#pragma pack() + +#endif // _EFI_VARIABLE_H_ diff --git a/MdePkg/Include/ToBeRemoved/WorkingBlockHeader.h b/MdePkg/Include/ToBeRemoved/WorkingBlockHeader.h new file mode 100644 index 0000000000..235b740e83 --- /dev/null +++ b/MdePkg/Include/ToBeRemoved/WorkingBlockHeader.h @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2006, 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. + +Module Name: + + EfiWorkingBlockHeader.h + +Abstract: + + Defines data structure that is the headers found at the runtime + updatable firmware volumes, such as the FileSystemGuid of the + working block, the header structure of the variable block, FTW + working block, or event log block. + +--*/ + +#ifndef _EFI_WORKING_BLOCK_HEADER_H_ +#define _EFI_WORKING_BLOCK_HEADER_H_ + +// +// EFI Fault tolerant working block header +// The header is immediately followed by the write queue. +// +typedef struct { + EFI_GUID Signature; + UINT32 Crc; + UINT32 WorkingBlockValid : 1; + UINT32 WorkingBlockInvalid : 1; +#define WORKING_BLOCK_VALID 0x1 +#define WORKING_BLOCK_INVALID 0x2 + UINT32 Reserved : 6; + UINT8 Reserved3[3]; + UINTN WriteQueueSize; + // + // UINT8 WriteQueue[WriteQueueSize]; + // +} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER; + +#endif diff --git a/MdePkg/Include/Uefi.h b/MdePkg/Include/Uefi.h new file mode 100644 index 0000000000..fcaaeb262c --- /dev/null +++ b/MdePkg/Include/Uefi.h @@ -0,0 +1,66 @@ +/** @file + + Root include file for Mde Package UEFI modules. + + UEFI modules follow the public EFI 1.10 or UEFI 2.0 specifications and + also contains the infrastructure required to build modules. The build + infrastructure must set EFI_SPECIFICATION_VERSION before including this + file. To support R9/UEFI2.0 set EFI_SPECIFIATION_VERSION to 0x00020000. To + support R8.5/EFI 1.10 set EFI_SPECIFIATION_VERSION to 0x00010010. + Seting EDK_RELEASE_VERSION to zero implies no Tiano extensions and a + non zero value implies Tiano extensions are availible. + EFI_SPECIFIATION_VERSION and EDK_RELEASE_VERSION are set automatically + by the build infrastructure for every module. + +Copyright (c) 2006, 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 __UEFI_H__ +#define __UEFI_H__ + + +// +// Check to make sure EFI_SPECIFICATION_VERSION and EDK_RELEASE_VERSION are defined. +// also check for legal combinations +// +#if !defined(EFI_SPECIFICATION_VERSION) + #error EFI_SPECIFICATION_VERSION not defined +#elif !defined(EDK_RELEASE_VERSION) + #error EDK_RELEASE_VERSION not defined +#elif EDK_RELEASE_VERSION == 0x00000000 +// +// UEFI mode with no Tiano extensions is legal +// +#elif (EDK_RELEASE_VERSION <= 0x00080005) && (EFI_SPECIFICATION_VERSION >= 0x00020000) + #error Illegal combination of EFI_SPECIFICATION_VERSION and EDK_RELEASE_VERSION versions +#endif + + + +#include +#include + +// +// Need due to R8.5 Tiano contamination of UEFI enumes. +// There is a UEFI library that does things the new way and the old way +// This is why these definitions are need in Uefi.h +// +#include +#include + + +// +// All module types types have access to PCD for build support +// +#include + +#endif diff --git a/MdePkg/Include/Uefi/EfiPxe.h b/MdePkg/Include/Uefi/EfiPxe.h new file mode 100644 index 0000000000..eadac3c850 --- /dev/null +++ b/MdePkg/Include/Uefi/EfiPxe.h @@ -0,0 +1,1780 @@ +/** @file + This header file contains all of the PXE type definitions, + structure prototypes, global variables and constants that + are needed for porting PXE to EFI. + + Copyright (c) 2006, 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. + + Module name: EfiPxe.h + + @par Revision Reference: + 32/64-bit PXE specification: + alpha-4, 99-Dec-17 + +**/ + +#ifndef __EFI_PXE_H__ +#define __EFI_PXE_H__ + +#pragma pack(1) + + + +#define PXE_BUSTYPE(a, b, c, d) \ + ( \ + (((PXE_UINT32) (d) & 0xFF) << 24) | (((PXE_UINT32) (c) & 0xFF) << 16) | (((PXE_UINT32) (b) & 0xFF) << 8) | \ + ((PXE_UINT32) (a) & 0xFF) \ + ) + +// +// UNDI ROM ID and devive ID signature +// +#define PXE_BUSTYPE_PXE PXE_BUSTYPE ('!', 'P', 'X', 'E') + +// +// BUS ROM ID signatures +// +#define PXE_BUSTYPE_PCI PXE_BUSTYPE ('P', 'C', 'I', 'R') +#define PXE_BUSTYPE_PC_CARD PXE_BUSTYPE ('P', 'C', 'C', 'R') +#define PXE_BUSTYPE_USB PXE_BUSTYPE ('U', 'S', 'B', 'R') +#define PXE_BUSTYPE_1394 PXE_BUSTYPE ('1', '3', '9', '4') + +#define PXE_SWAP_UINT16(n) ((((PXE_UINT16) (n) & 0x00FF) << 8) | (((PXE_UINT16) (n) & 0xFF00) >> 8)) + +#define PXE_SWAP_UINT32(n) \ + ((((PXE_UINT32)(n) & 0x000000FF) << 24) | \ + (((PXE_UINT32)(n) & 0x0000FF00) << 8) | \ + (((PXE_UINT32)(n) & 0x00FF0000) >> 8) | \ + (((PXE_UINT32)(n) & 0xFF000000) >> 24)) + +#define PXE_SWAP_UINT64(n) \ + ((((PXE_UINT64)(n) & 0x00000000000000FFULL) << 56) | \ + (((PXE_UINT64)(n) & 0x000000000000FF00ULL) << 40) | \ + (((PXE_UINT64)(n) & 0x0000000000FF0000ULL) << 24) | \ + (((PXE_UINT64)(n) & 0x00000000FF000000ULL) << 8) | \ + (((PXE_UINT64)(n) & 0x000000FF00000000ULL) >> 8) | \ + (((PXE_UINT64)(n) & 0x0000FF0000000000ULL) >> 24) | \ + (((PXE_UINT64)(n) & 0x00FF000000000000ULL) >> 40) | \ + (((PXE_UINT64)(n) & 0xFF00000000000000ULL) >> 56)) + + +#define PXE_CPBSIZE_NOT_USED 0 // zero +#define PXE_DBSIZE_NOT_USED 0 // zero +#define PXE_CPBADDR_NOT_USED (PXE_UINT64) 0 // zero +#define PXE_DBADDR_NOT_USED (PXE_UINT64) 0 // zero +#define PXE_CONST const + +#define PXE_VOLATILE volatile + +typedef VOID PXE_VOID; +typedef UINT8 PXE_UINT8; +typedef UINT16 PXE_UINT16; +typedef UINT32 PXE_UINT32; +typedef UINTN PXE_UINTN; + +// +// typedef unsigned long PXE_UINT64; +// +typedef UINT64 PXE_UINT64; + +typedef PXE_UINT8 PXE_BOOL; +#define PXE_FALSE 0 // zero +#define PXE_TRUE (!PXE_FALSE) + +typedef PXE_UINT16 PXE_OPCODE; + +// +// Return UNDI operational state. +// +#define PXE_OPCODE_GET_STATE 0x0000 + +// +// Change UNDI operational state from Stopped to Started. +// +#define PXE_OPCODE_START 0x0001 + +// +// Change UNDI operational state from Started to Stopped. +// +#define PXE_OPCODE_STOP 0x0002 + +// +// Get UNDI initialization information. +// +#define PXE_OPCODE_GET_INIT_INFO 0x0003 + +// +// Get NIC configuration information. +// +#define PXE_OPCODE_GET_CONFIG_INFO 0x0004 + +// +// Changed UNDI operational state from Started to Initialized. +// +#define PXE_OPCODE_INITIALIZE 0x0005 + +// +// Re-initialize the NIC H/W. +// +#define PXE_OPCODE_RESET 0x0006 + +// +// Change the UNDI operational state from Initialized to Started. +// +#define PXE_OPCODE_SHUTDOWN 0x0007 + +// +// Read & change state of external interrupt enables. +// +#define PXE_OPCODE_INTERRUPT_ENABLES 0x0008 + +// +// Read & change state of packet receive filters. +// +#define PXE_OPCODE_RECEIVE_FILTERS 0x0009 + +// +// Read & change station MAC address. +// +#define PXE_OPCODE_STATION_ADDRESS 0x000A + +// +// Read traffic statistics. +// +#define PXE_OPCODE_STATISTICS 0x000B + +// +// Convert multicast IP address to multicast MAC address. +// +#define PXE_OPCODE_MCAST_IP_TO_MAC 0x000C + +// +// Read or change non-volatile storage on the NIC. +// +#define PXE_OPCODE_NVDATA 0x000D + +// +// Get & clear interrupt status. +// +#define PXE_OPCODE_GET_STATUS 0x000E + +// +// Fill media header in packet for transmit. +// +#define PXE_OPCODE_FILL_HEADER 0x000F + +// +// Transmit packet(s). +// +#define PXE_OPCODE_TRANSMIT 0x0010 + +// +// Receive packet. +// +#define PXE_OPCODE_RECEIVE 0x0011 + +// +// Last valid PXE UNDI OpCode number. +// +#define PXE_OPCODE_LAST_VALID 0x0011 + +typedef PXE_UINT16 PXE_OPFLAGS; + +#define PXE_OPFLAGS_NOT_USED 0x0000 + +// +// ////////////////////////////////////// +// UNDI Get State +// +// No OpFlags + +//////////////////////////////////////// +// UNDI Start +// +// No OpFlags + +//////////////////////////////////////// +// UNDI Stop +// +// No OpFlags + +//////////////////////////////////////// +// UNDI Get Init Info +// +// No Opflags + +//////////////////////////////////////// +// UNDI Get Config Info +// +// No Opflags + +//////////////////////////////////////// +// UNDI Initialize +// +#define PXE_OPFLAGS_INITIALIZE_CABLE_DETECT_MASK 0x0001 +#define PXE_OPFLAGS_INITIALIZE_DETECT_CABLE 0x0000 +#define PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE 0x0001 + +// +// ////////////////////////////////////// +// UNDI Reset +// +#define PXE_OPFLAGS_RESET_DISABLE_INTERRUPTS 0x0001 +#define PXE_OPFLAGS_RESET_DISABLE_FILTERS 0x0002 + +// +// ////////////////////////////////////// +// UNDI Shutdown +// +// No OpFlags + +//////////////////////////////////////// +// UNDI Interrupt Enables +// +// +// Select whether to enable or disable external interrupt signals. +// Setting both enable and disable will return PXE_STATCODE_INVALID_OPFLAGS. +// +#define PXE_OPFLAGS_INTERRUPT_OPMASK 0xC000 +#define PXE_OPFLAGS_INTERRUPT_ENABLE 0x8000 +#define PXE_OPFLAGS_INTERRUPT_DISABLE 0x4000 +#define PXE_OPFLAGS_INTERRUPT_READ 0x0000 + +// +// Enable receive interrupts. An external interrupt will be generated +// after a complete non-error packet has been received. +// +#define PXE_OPFLAGS_INTERRUPT_RECEIVE 0x0001 + +// +// Enable transmit interrupts. An external interrupt will be generated +// after a complete non-error packet has been transmitted. +// +#define PXE_OPFLAGS_INTERRUPT_TRANSMIT 0x0002 + +// +// Enable command interrupts. An external interrupt will be generated +// when command execution stops. +// +#define PXE_OPFLAGS_INTERRUPT_COMMAND 0x0004 + +// +// Generate software interrupt. Setting this bit generates an external +// interrupt, if it is supported by the hardware. +// +#define PXE_OPFLAGS_INTERRUPT_SOFTWARE 0x0008 + +// +// ////////////////////////////////////// +// UNDI Receive Filters +// +// +// Select whether to enable or disable receive filters. +// Setting both enable and disable will return PXE_STATCODE_INVALID_OPCODE. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_OPMASK 0xC000 +#define PXE_OPFLAGS_RECEIVE_FILTER_ENABLE 0x8000 +#define PXE_OPFLAGS_RECEIVE_FILTER_DISABLE 0x4000 +#define PXE_OPFLAGS_RECEIVE_FILTER_READ 0x0000 + +// +// To reset the contents of the multicast MAC address filter list, +// set this OpFlag: +// +#define PXE_OPFLAGS_RECEIVE_FILTER_RESET_MCAST_LIST 0x2000 + +// +// Enable unicast packet receiving. Packets sent to the current station +// MAC address will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_UNICAST 0x0001 + +// +// Enable broadcast packet receiving. Packets sent to the broadcast +// MAC address will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_BROADCAST 0x0002 + +// +// Enable filtered multicast packet receiving. Packets sent to any +// of the multicast MAC addresses in the multicast MAC address filter +// list will be received. If the filter list is empty, no multicast +// +#define PXE_OPFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004 + +// +// Enable promiscuous packet receiving. All packets will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008 + +// +// Enable promiscuous multicast packet receiving. All multicast +// packets will be received. +// +#define PXE_OPFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010 + +// +// ////////////////////////////////////// +// UNDI Station Address +// +#define PXE_OPFLAGS_STATION_ADDRESS_READ 0x0000 +#define PXE_OPFLAGS_STATION_ADDRESS_WRITE 0x0000 +#define PXE_OPFLAGS_STATION_ADDRESS_RESET 0x0001 + +// +// ////////////////////////////////////// +// UNDI Statistics +// +#define PXE_OPFLAGS_STATISTICS_READ 0x0000 +#define PXE_OPFLAGS_STATISTICS_RESET 0x0001 + +// +// ////////////////////////////////////// +// UNDI MCast IP to MAC +// +// +// Identify the type of IP address in the CPB. +// +#define PXE_OPFLAGS_MCAST_IP_TO_MAC_OPMASK 0x0003 +#define PXE_OPFLAGS_MCAST_IPV4_TO_MAC 0x0000 +#define PXE_OPFLAGS_MCAST_IPV6_TO_MAC 0x0001 + +// +// ////////////////////////////////////// +// UNDI NvData +// +// +// Select the type of non-volatile data operation. +// +#define PXE_OPFLAGS_NVDATA_OPMASK 0x0001 +#define PXE_OPFLAGS_NVDATA_READ 0x0000 +#define PXE_OPFLAGS_NVDATA_WRITE 0x0001 + +// +// ////////////////////////////////////// +// UNDI Get Status +// +// +// Return current interrupt status. This will also clear any interrupts +// that are currently set. This can be used in a polling routine. The +// interrupt flags are still set and cleared even when the interrupts +// are disabled. +// +#define PXE_OPFLAGS_GET_INTERRUPT_STATUS 0x0001 + +// +// Return list of transmitted buffers for recycling. Transmit buffers +// must not be changed or unallocated until they have recycled. After +// issuing a transmit command, wait for a transmit complete interrupt. +// When a transmit complete interrupt is received, read the transmitted +// buffers. Do not plan on getting one buffer per interrupt. Some +// NICs and UNDIs may transmit multiple buffers per interrupt. +// +#define PXE_OPFLAGS_GET_TRANSMITTED_BUFFERS 0x0002 + +// +// ////////////////////////////////////// +// UNDI Fill Header +// +#define PXE_OPFLAGS_FILL_HEADER_OPMASK 0x0001 +#define PXE_OPFLAGS_FILL_HEADER_FRAGMENTED 0x0001 +#define PXE_OPFLAGS_FILL_HEADER_WHOLE 0x0000 + +// +// ////////////////////////////////////// +// UNDI Transmit +// +// +// S/W UNDI only. Return after the packet has been transmitted. A +// transmit complete interrupt will still be generated and the transmit +// buffer will have to be recycled. +// +#define PXE_OPFLAGS_SWUNDI_TRANSMIT_OPMASK 0x0001 +#define PXE_OPFLAGS_TRANSMIT_BLOCK 0x0001 +#define PXE_OPFLAGS_TRANSMIT_DONT_BLOCK 0x0000 + +// +// +// +#define PXE_OPFLAGS_TRANSMIT_OPMASK 0x0002 +#define PXE_OPFLAGS_TRANSMIT_FRAGMENTED 0x0002 +#define PXE_OPFLAGS_TRANSMIT_WHOLE 0x0000 + +// +// ////////////////////////////////////// +// UNDI Receive +// +// No OpFlags +// +typedef PXE_UINT16 PXE_STATFLAGS; + +#define PXE_STATFLAGS_INITIALIZE 0x0000 + +// +// ////////////////////////////////////// +// Common StatFlags that can be returned by all commands. +// +// +// The COMMAND_COMPLETE and COMMAND_FAILED status flags must be +// implemented by all UNDIs. COMMAND_QUEUED is only needed by UNDIs +// that support command queuing. +// +#define PXE_STATFLAGS_STATUS_MASK 0xC000 +#define PXE_STATFLAGS_COMMAND_COMPLETE 0xC000 +#define PXE_STATFLAGS_COMMAND_FAILED 0x8000 +#define PXE_STATFLAGS_COMMAND_QUEUED 0x4000 + +// +// ////////////////////////////////////// +// UNDI Get State +// +#define PXE_STATFLAGS_GET_STATE_MASK 0x0003 +#define PXE_STATFLAGS_GET_STATE_INITIALIZED 0x0002 +#define PXE_STATFLAGS_GET_STATE_STARTED 0x0001 +#define PXE_STATFLAGS_GET_STATE_STOPPED 0x0000 + +// +// ////////////////////////////////////// +// UNDI Start +// +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Get Init Info +// +#define PXE_STATFLAGS_CABLE_DETECT_MASK 0x0001 +#define PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED 0x0000 +#define PXE_STATFLAGS_CABLE_DETECT_SUPPORTED 0x0001 + +// +// ////////////////////////////////////// +// UNDI Initialize +// +#define PXE_STATFLAGS_INITIALIZED_NO_MEDIA 0x0001 + +// +// ////////////////////////////////////// +// UNDI Reset +// +#define PXE_STATFLAGS_RESET_NO_MEDIA 0x0001 + +// +// ////////////////////////////////////// +// UNDI Shutdown +// +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Interrupt Enables +// +// +// If set, receive interrupts are enabled. +// +#define PXE_STATFLAGS_INTERRUPT_RECEIVE 0x0001 + +// +// If set, transmit interrupts are enabled. +// +#define PXE_STATFLAGS_INTERRUPT_TRANSMIT 0x0002 + +// +// If set, command interrupts are enabled. +// +#define PXE_STATFLAGS_INTERRUPT_COMMAND 0x0004 + +// +// ////////////////////////////////////// +// UNDI Receive Filters +// +// +// If set, unicast packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_UNICAST 0x0001 + +// +// If set, broadcast packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_BROADCAST 0x0002 + +// +// If set, multicast packets that match up with the multicast address +// filter list will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_FILTERED_MULTICAST 0x0004 + +// +// If set, all packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_PROMISCUOUS 0x0008 + +// +// If set, all multicast packets will be received. +// +#define PXE_STATFLAGS_RECEIVE_FILTER_ALL_MULTICAST 0x0010 + +// +// ////////////////////////////////////// +// UNDI Station Address +// +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Statistics +// +// No additional StatFlags + +//////////////////////////////////////// +// UNDI MCast IP to MAC +// +// No additional StatFlags + +//////////////////////////////////////// +// UNDI NvData +// +// No additional StatFlags + + +//////////////////////////////////////// +// UNDI Get Status +// +// +// Use to determine if an interrupt has occurred. +// +#define PXE_STATFLAGS_GET_STATUS_INTERRUPT_MASK 0x000F +#define PXE_STATFLAGS_GET_STATUS_NO_INTERRUPTS 0x0000 + +// +// If set, at least one receive interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_RECEIVE 0x0001 + +// +// If set, at least one transmit interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_TRANSMIT 0x0002 + +// +// If set, at least one command interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_COMMAND 0x0004 + +// +// If set, at least one software interrupt occurred. +// +#define PXE_STATFLAGS_GET_STATUS_SOFTWARE 0x0008 + +// +// This flag is set if the transmitted buffer queue is empty. This flag +// will be set if all transmitted buffer addresses get written into the DB. +// +#define PXE_STATFLAGS_GET_STATUS_TXBUF_QUEUE_EMPTY 0x0010 + +// +// This flag is set if no transmitted buffer addresses were written +// into the DB. (This could be because DBsize was too small.) +// +#define PXE_STATFLAGS_GET_STATUS_NO_TXBUFS_WRITTEN 0x0020 + +// +// ////////////////////////////////////// +// UNDI Fill Header +// +// No additional StatFlags + +//////////////////////////////////////// +// UNDI Transmit +// +// No additional StatFlags. + +//////////////////////////////////////// +// UNDI Receive +// +// No additional StatFlags. +// +typedef PXE_UINT16 PXE_STATCODE; + +#define PXE_STATCODE_INITIALIZE 0x0000 + +// +// ////////////////////////////////////// +// Common StatCodes returned by all UNDI commands, UNDI protocol functions +// and BC protocol functions. +// +#define PXE_STATCODE_SUCCESS 0x0000 + +#define PXE_STATCODE_INVALID_CDB 0x0001 +#define PXE_STATCODE_INVALID_CPB 0x0002 +#define PXE_STATCODE_BUSY 0x0003 +#define PXE_STATCODE_QUEUE_FULL 0x0004 +#define PXE_STATCODE_ALREADY_STARTED 0x0005 +#define PXE_STATCODE_NOT_STARTED 0x0006 +#define PXE_STATCODE_NOT_SHUTDOWN 0x0007 +#define PXE_STATCODE_ALREADY_INITIALIZED 0x0008 +#define PXE_STATCODE_NOT_INITIALIZED 0x0009 +#define PXE_STATCODE_DEVICE_FAILURE 0x000A +#define PXE_STATCODE_NVDATA_FAILURE 0x000B +#define PXE_STATCODE_UNSUPPORTED 0x000C +#define PXE_STATCODE_BUFFER_FULL 0x000D +#define PXE_STATCODE_INVALID_PARAMETER 0x000E +#define PXE_STATCODE_INVALID_UNDI 0x000F +#define PXE_STATCODE_IPV4_NOT_SUPPORTED 0x0010 +#define PXE_STATCODE_IPV6_NOT_SUPPORTED 0x0011 +#define PXE_STATCODE_NOT_ENOUGH_MEMORY 0x0012 +#define PXE_STATCODE_NO_DATA 0x0013 + +typedef PXE_UINT16 PXE_IFNUM; + +// +// This interface number must be passed to the S/W UNDI Start command. +// +#define PXE_IFNUM_START 0x0000 + +// +// This interface number is returned by the S/W UNDI Get State and +// Start commands if information in the CDB, CPB or DB is invalid. +// +#define PXE_IFNUM_INVALID 0x0000 + +typedef PXE_UINT16 PXE_CONTROL; + +// +// Setting this flag directs the UNDI to queue this command for later +// execution if the UNDI is busy and it supports command queuing. +// If queuing is not supported, a PXE_STATCODE_INVALID_CONTROL error +// is returned. If the queue is full, a PXE_STATCODE_CDB_QUEUE_FULL +// error is returned. +// +#define PXE_CONTROL_QUEUE_IF_BUSY 0x0002 + +// +// These two bit values are used to determine if there are more UNDI +// CDB structures following this one. If the link bit is set, there +// must be a CDB structure following this one. Execution will start +// on the next CDB structure as soon as this one completes successfully. +// If an error is generated by this command, execution will stop. +// +#define PXE_CONTROL_LINK 0x0001 +#define PXE_CONTROL_LAST_CDB_IN_LIST 0x0000 + +typedef PXE_UINT8 PXE_FRAME_TYPE; + +#define PXE_FRAME_TYPE_NONE 0x00 +#define PXE_FRAME_TYPE_UNICAST 0x01 +#define PXE_FRAME_TYPE_BROADCAST 0x02 +#define PXE_FRAME_TYPE_FILTERED_MULTICAST 0x03 +#define PXE_FRAME_TYPE_PROMISCUOUS 0x04 +#define PXE_FRAME_TYPE_PROMISCUOUS_MULTICAST 0x05 + +#define PXE_FRAME_TYPE_MULTICAST PXE_FRAME_TYPE_FILTERED_MULTICAST + +typedef PXE_UINT32 PXE_IPV4; + +typedef PXE_UINT32 PXE_IPV6[4]; +#define PXE_MAC_LENGTH 32 + +typedef PXE_UINT8 PXE_MAC_ADDR[PXE_MAC_LENGTH]; + +typedef PXE_UINT8 PXE_IFTYPE; +typedef UINT16 PXE_MEDIA_PROTOCOL; + +// +// This information is from the ARP section of RFC 1700. +// +// 1 Ethernet (10Mb) [JBP] +// 2 Experimental Ethernet (3Mb) [JBP] +// 3 Amateur Radio AX.25 [PXK] +// 4 Proteon ProNET Token Ring [JBP] +// 5 Chaos [GXP] +// 6 IEEE 802 Networks [JBP] +// 7 ARCNET [JBP] +// 8 Hyperchannel [JBP] +// 9 Lanstar [TU] +// 10 Autonet Short Address [MXB1] +// 11 LocalTalk [JKR1] +// 12 LocalNet (IBM* PCNet or SYTEK* LocalNET) [JXM] +// 13 Ultra link [RXD2] +// 14 SMDS [GXC1] +// 15 Frame Relay [AGM] +// 16 Asynchronous Transmission Mode (ATM) [JXB2] +// 17 HDLC [JBP] +// 18 Fibre Channel [Yakov Rekhter] +// 19 Asynchronous Transmission Mode (ATM) [Mark Laubach] +// 20 Serial Line [JBP] +// 21 Asynchronous Transmission Mode (ATM) [MXB1] +// +// * Other names and brands may be claimed as the property of others. +// +#define PXE_IFTYPE_ETHERNET 0x01 +#define PXE_IFTYPE_TOKENRING 0x04 +#define PXE_IFTYPE_FIBRE_CHANNEL 0x12 + +typedef struct s_pxe_hw_undi { + PXE_UINT32 Signature; // PXE_ROMID_SIGNATURE + PXE_UINT8 Len; // sizeof(PXE_HW_UNDI) + PXE_UINT8 Fudge; // makes 8-bit cksum equal zero + PXE_UINT8 Rev; // PXE_ROMID_REV + PXE_UINT8 IFcnt; // physical connector count + PXE_UINT8 MajorVer; // PXE_ROMID_MAJORVER + PXE_UINT8 MinorVer; // PXE_ROMID_MINORVER + PXE_UINT16 reserved; // zero, not used + PXE_UINT32 Implementation; // implementation flags + // reserved // vendor use + // UINT32 Status; // status port + // UINT32 Command; // command port + // UINT64 CDBaddr; // CDB address port + // +} PXE_HW_UNDI; + +// +// Status port bit definitions +// +// +// UNDI operation state +// +#define PXE_HWSTAT_STATE_MASK 0xC0000000 +#define PXE_HWSTAT_BUSY 0xC0000000 +#define PXE_HWSTAT_INITIALIZED 0x80000000 +#define PXE_HWSTAT_STARTED 0x40000000 +#define PXE_HWSTAT_STOPPED 0x00000000 + +// +// If set, last command failed +// +#define PXE_HWSTAT_COMMAND_FAILED 0x20000000 + +// +// If set, identifies enabled receive filters +// +#define PXE_HWSTAT_PROMISCUOUS_MULTICAST_RX_ENABLED 0x00001000 +#define PXE_HWSTAT_PROMISCUOUS_RX_ENABLED 0x00000800 +#define PXE_HWSTAT_BROADCAST_RX_ENABLED 0x00000400 +#define PXE_HWSTAT_MULTICAST_RX_ENABLED 0x00000200 +#define PXE_HWSTAT_UNICAST_RX_ENABLED 0x00000100 + +// +// If set, identifies enabled external interrupts +// +#define PXE_HWSTAT_SOFTWARE_INT_ENABLED 0x00000080 +#define PXE_HWSTAT_TX_COMPLETE_INT_ENABLED 0x00000040 +#define PXE_HWSTAT_PACKET_RX_INT_ENABLED 0x00000020 +#define PXE_HWSTAT_CMD_COMPLETE_INT_ENABLED 0x00000010 + +// +// If set, identifies pending interrupts +// +#define PXE_HWSTAT_SOFTWARE_INT_PENDING 0x00000008 +#define PXE_HWSTAT_TX_COMPLETE_INT_PENDING 0x00000004 +#define PXE_HWSTAT_PACKET_RX_INT_PENDING 0x00000002 +#define PXE_HWSTAT_CMD_COMPLETE_INT_PENDING 0x00000001 + +// +// Command port definitions +// +// +// If set, CDB identified in CDBaddr port is given to UNDI. +// If not set, other bits in this word will be processed. +// +#define PXE_HWCMD_ISSUE_COMMAND 0x80000000 +#define PXE_HWCMD_INTS_AND_FILTS 0x00000000 + +// +// Use these to enable/disable receive filters. +// +#define PXE_HWCMD_PROMISCUOUS_MULTICAST_RX_ENABLE 0x00001000 +#define PXE_HWCMD_PROMISCUOUS_RX_ENABLE 0x00000800 +#define PXE_HWCMD_BROADCAST_RX_ENABLE 0x00000400 +#define PXE_HWCMD_MULTICAST_RX_ENABLE 0x00000200 +#define PXE_HWCMD_UNICAST_RX_ENABLE 0x00000100 + +// +// Use these to enable/disable external interrupts +// +#define PXE_HWCMD_SOFTWARE_INT_ENABLE 0x00000080 +#define PXE_HWCMD_TX_COMPLETE_INT_ENABLE 0x00000040 +#define PXE_HWCMD_PACKET_RX_INT_ENABLE 0x00000020 +#define PXE_HWCMD_CMD_COMPLETE_INT_ENABLE 0x00000010 + +// +// Use these to clear pending external interrupts +// +#define PXE_HWCMD_CLEAR_SOFTWARE_INT 0x00000008 +#define PXE_HWCMD_CLEAR_TX_COMPLETE_INT 0x00000004 +#define PXE_HWCMD_CLEAR_PACKET_RX_INT 0x00000002 +#define PXE_HWCMD_CLEAR_CMD_COMPLETE_INT 0x00000001 + +typedef struct s_pxe_sw_undi { + PXE_UINT32 Signature; // PXE_ROMID_SIGNATURE + PXE_UINT8 Len; // sizeof(PXE_SW_UNDI) + PXE_UINT8 Fudge; // makes 8-bit cksum zero + PXE_UINT8 Rev; // PXE_ROMID_REV + PXE_UINT8 IFcnt; // physical connector count + PXE_UINT8 MajorVer; // PXE_ROMID_MAJORVER + PXE_UINT8 MinorVer; // PXE_ROMID_MINORVER + PXE_UINT16 reserved1; // zero, not used + PXE_UINT32 Implementation; // Implementation flags + PXE_UINT64 EntryPoint; // API entry point + PXE_UINT8 reserved2[3]; // zero, not used + PXE_UINT8 BusCnt; // number of bustypes supported + PXE_UINT32 BusType[1]; // list of supported bustypes +} PXE_SW_UNDI; + +typedef union u_pxe_undi { + PXE_HW_UNDI hw; + PXE_SW_UNDI sw; +} PXE_UNDI; + +// +// Signature of !PXE structure +// +#define PXE_ROMID_SIGNATURE PXE_BUSTYPE ('!', 'P', 'X', 'E') + +// +// !PXE structure format revision +// +#define PXE_ROMID_REV 0x02 + +// +// UNDI command interface revision. These are the values that get sent +// in option 94 (Client Network Interface Identifier) in the DHCP Discover +// and PXE Boot Server Request packets. +// +#define PXE_ROMID_MAJORVER 0x03 +#define PXE_ROMID_MINORVER 0x01 + +// +// Implementation flags +// +#define PXE_ROMID_IMP_HW_UNDI 0x80000000 +#define PXE_ROMID_IMP_SW_VIRT_ADDR 0x40000000 +#define PXE_ROMID_IMP_64BIT_DEVICE 0x00010000 +#define PXE_ROMID_IMP_FRAG_SUPPORTED 0x00008000 +#define PXE_ROMID_IMP_CMD_LINK_SUPPORTED 0x00004000 +#define PXE_ROMID_IMP_CMD_QUEUE_SUPPORTED 0x00002000 +#define PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED 0x00001000 +#define PXE_ROMID_IMP_NVDATA_SUPPORT_MASK 0x00000C00 +#define PXE_ROMID_IMP_NVDATA_BULK_WRITABLE 0x00000C00 +#define PXE_ROMID_IMP_NVDATA_SPARSE_WRITABLE 0x00000800 +#define PXE_ROMID_IMP_NVDATA_READ_ONLY 0x00000400 +#define PXE_ROMID_IMP_NVDATA_NOT_AVAILABLE 0x00000000 +#define PXE_ROMID_IMP_STATISTICS_SUPPORTED 0x00000200 +#define PXE_ROMID_IMP_STATION_ADDR_SETTABLE 0x00000100 +#define PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED 0x00000080 +#define PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED 0x00000040 +#define PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED 0x00000020 +#define PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED 0x00000010 +#define PXE_ROMID_IMP_SOFTWARE_INT_SUPPORTED 0x00000008 +#define PXE_ROMID_IMP_TX_COMPLETE_INT_SUPPORTED 0x00000004 +#define PXE_ROMID_IMP_PACKET_RX_INT_SUPPORTED 0x00000002 +#define PXE_ROMID_IMP_CMD_COMPLETE_INT_SUPPORTED 0x00000001 + +typedef struct s_pxe_cdb { + PXE_OPCODE OpCode; + PXE_OPFLAGS OpFlags; + PXE_UINT16 CPBsize; + PXE_UINT16 DBsize; + PXE_UINT64 CPBaddr; + PXE_UINT64 DBaddr; + PXE_STATCODE StatCode; + PXE_STATFLAGS StatFlags; + PXE_UINT16 IFnum; + PXE_CONTROL Control; +} PXE_CDB; + +typedef union u_pxe_ip_addr { + PXE_IPV6 IPv6; + PXE_IPV4 IPv4; +} PXE_IP_ADDR; + +typedef union pxe_device { + // + // PCI and PC Card NICs are both identified using bus, device + // and function numbers. For PC Card, this may require PC + // Card services to be loaded in the BIOS or preboot + // environment. + // + struct { + // + // See S/W UNDI ROMID structure definition for PCI and + // PCC BusType definitions. + // + PXE_UINT32 BusType; + + // + // Bus, device & function numbers that locate this device. + // + PXE_UINT16 Bus; + PXE_UINT8 Device; + PXE_UINT8 Function; + } + PCI, PCC; + + // + // %%TBD - More information is needed about enumerating + // USB and 1394 devices. + // + struct { + PXE_UINT32 BusType; + PXE_UINT32 tdb; + } + USB, _1394; +} PXE_DEVICE; + +// +// cpb and db definitions +// +#define MAX_PCI_CONFIG_LEN 64 // # of dwords +#define MAX_EEPROM_LEN 128 // #of dwords +#define MAX_XMIT_BUFFERS 32 // recycling Q length for xmit_done +#define MAX_MCAST_ADDRESS_CNT 8 + +typedef struct s_pxe_cpb_start_30 { + // + // PXE_VOID Delay(UINTN microseconds); + // + // UNDI will never request a delay smaller than 10 microseconds + // and will always request delays in increments of 10 microseconds. + // The Delay() CallBack routine must delay between n and n + 10 + // microseconds before returning control to the UNDI. + // + // This field cannot be set to zero. + // + UINT64 Delay; + + // + // PXE_VOID Block(UINT32 enable); + // + // UNDI may need to block multi-threaded/multi-processor access to + // critical code sections when programming or accessing the network + // device. To this end, a blocking service is needed by the UNDI. + // When UNDI needs a block, it will call Block() passing a non-zero + // value. When UNDI no longer needs a block, it will call Block() + // with a zero value. When called, if the Block() is already enabled, + // do not return control to the UNDI until the previous Block() is + // disabled. + // + // This field cannot be set to zero. + // + UINT64 Block; + + // + // PXE_VOID Virt2Phys(UINT64 virtual, UINT64 physical_ptr); + // + // UNDI will pass the virtual address of a buffer and the virtual + // address of a 64-bit physical buffer. Convert the virtual address + // to a physical address and write the result to the physical address + // buffer. If virtual and physical addresses are the same, just + // copy the virtual address to the physical address buffer. + // + // This field can be set to zero if virtual and physical addresses + // are equal. + // + UINT64 Virt2Phys; + // + // PXE_VOID Mem_IO(UINT8 read_write, UINT8 len, UINT64 port, + // UINT64 buf_addr); + // + // UNDI will read or write the device io space using this call back + // function. It passes the number of bytes as the len parameter and it + // will be either 1,2,4 or 8. + // + // This field can not be set to zero. + // + UINT64 Mem_IO; +} PXE_CPB_START_30; + +typedef struct s_pxe_cpb_start_31 { + // + // PXE_VOID Delay(UINT64 UnqId, UINTN microseconds); + // + // UNDI will never request a delay smaller than 10 microseconds + // and will always request delays in increments of 10 microseconds. + // The Delay() CallBack routine must delay between n and n + 10 + // microseconds before returning control to the UNDI. + // + // This field cannot be set to zero. + // + UINT64 Delay; + + // + // PXE_VOID Block(UINT64 unq_id, UINT32 enable); + // + // UNDI may need to block multi-threaded/multi-processor access to + // critical code sections when programming or accessing the network + // device. To this end, a blocking service is needed by the UNDI. + // When UNDI needs a block, it will call Block() passing a non-zero + // value. When UNDI no longer needs a block, it will call Block() + // with a zero value. When called, if the Block() is already enabled, + // do not return control to the UNDI until the previous Block() is + // disabled. + // + // This field cannot be set to zero. + // + UINT64 Block; + + // + // PXE_VOID Virt2Phys(UINT64 UnqId, UINT64 virtual, UINT64 physical_ptr); + // + // UNDI will pass the virtual address of a buffer and the virtual + // address of a 64-bit physical buffer. Convert the virtual address + // to a physical address and write the result to the physical address + // buffer. If virtual and physical addresses are the same, just + // copy the virtual address to the physical address buffer. + // + // This field can be set to zero if virtual and physical addresses + // are equal. + // + UINT64 Virt2Phys; + // + // PXE_VOID Mem_IO(UINT64 UnqId, UINT8 read_write, UINT8 len, UINT64 port, + // UINT64 buf_addr); + // + // UNDI will read or write the device io space using this call back + // function. It passes the number of bytes as the len parameter and it + // will be either 1,2,4 or 8. + // + // This field can not be set to zero. + // + UINT64 Mem_IO; + // + // PXE_VOID Map_Mem(UINT64 unq_id, UINT64 virtual_addr, UINT32 size, + // UINT32 Direction, UINT64 mapped_addr); + // + // UNDI will pass the virtual address of a buffer, direction of the data + // flow from/to the mapped buffer (the constants are defined below) + // and a place holder (pointer) for the mapped address. + // This call will Map the given address to a physical DMA address and write + // the result to the mapped_addr pointer. If there is no need to + // map the given address to a lower address (i.e. the given address is + // associated with a physical address that is already compatible to be + // used with the DMA, it converts the given virtual address to it's + // physical address and write that in the mapped address pointer. + // + // This field can be set to zero if there is no mapping service available + // + UINT64 Map_Mem; + + // + // PXE_VOID UnMap_Mem(UINT64 unq_id, UINT64 virtual_addr, UINT32 size, + // UINT32 Direction, UINT64 mapped_addr); + // + // UNDI will pass the virtual and mapped addresses of a buffer + // This call will un map the given address + // + // This field can be set to zero if there is no unmapping service available + // + UINT64 UnMap_Mem; + + // + // PXE_VOID Sync_Mem(UINT64 unq_id, UINT64 virtual, + // UINT32 size, UINT32 Direction, UINT64 mapped_addr); + // + // UNDI will pass the virtual and mapped addresses of a buffer + // This call will synchronize the contents of both the virtual and mapped + // buffers for the given Direction. + // + // This field can be set to zero if there is no service available + // + UINT64 Sync_Mem; + + // + // protocol driver can provide anything for this Unique_ID, UNDI remembers + // that as just a 64bit value assocaited to the interface specified by + // the ifnum and gives it back as a parameter to all the call-back routines + // when calling for that interface! + // + UINT64 Unique_ID; + // +} PXE_CPB_START_31; + +#define TO_AND_FROM_DEVICE 0 +#define FROM_DEVICE 1 +#define TO_DEVICE 2 + +#define PXE_DELAY_MILLISECOND 1000 +#define PXE_DELAY_SECOND 1000000 +#define PXE_IO_READ 0 +#define PXE_IO_WRITE 1 +#define PXE_MEM_READ 2 +#define PXE_MEM_WRITE 4 + +typedef struct s_pxe_db_get_init_info { + // + // Minimum length of locked memory buffer that must be given to + // the Initialize command. Giving UNDI more memory will generally + // give better performance. + // + // If MemoryRequired is zero, the UNDI does not need and will not + // use system memory to receive and transmit packets. + // + PXE_UINT32 MemoryRequired; + + // + // Maximum frame data length for Tx/Rx excluding the media header. + // + PXE_UINT32 FrameDataLen; + + // + // Supported link speeds are in units of mega bits. Common ethernet + // values are 10, 100 and 1000. Unused LinkSpeeds[] entries are zero + // filled. + // + PXE_UINT32 LinkSpeeds[4]; + + // + // Number of non-volatile storage items. + // + PXE_UINT32 NvCount; + + // + // Width of non-volatile storage item in bytes. 0, 1, 2 or 4 + // + PXE_UINT16 NvWidth; + + // + // Media header length. This is the typical media header length for + // this UNDI. This information is needed when allocating receive + // and transmit buffers. + // + PXE_UINT16 MediaHeaderLen; + + // + // Number of bytes in the NIC hardware (MAC) address. + // + PXE_UINT16 HWaddrLen; + + // + // Maximum number of multicast MAC addresses in the multicast + // MAC address filter list. + // + PXE_UINT16 MCastFilterCnt; + + // + // Default number and size of transmit and receive buffers that will + // be allocated by the UNDI. If MemoryRequired is non-zero, this + // allocation will come out of the memory buffer given to the Initialize + // command. If MemoryRequired is zero, this allocation will come out of + // memory on the NIC. + // + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; + + // + // Hardware interface types defined in the Assigned Numbers RFC + // and used in DHCP and ARP packets. + // See the PXE_IFTYPE typedef and PXE_IFTYPE_xxx macros. + // + PXE_UINT8 IFtype; + + // + // Supported duplex. See PXE_DUPLEX_xxxxx #defines below. + // + PXE_UINT8 SupportedDuplexModes; + + // + // Supported loopback options. See PXE_LOOPBACK_xxxxx #defines below. + // + PXE_UINT8 SupportedLoopBackModes; +} PXE_DB_GET_INIT_INFO; + +#define PXE_MAX_TXRX_UNIT_ETHER 1500 + +#define PXE_HWADDR_LEN_ETHER 0x0006 +#define PXE_MAC_HEADER_LEN_ETHER 0x000E + +#define PXE_DUPLEX_ENABLE_FULL_SUPPORTED 1 +#define PXE_DUPLEX_FORCE_FULL_SUPPORTED 2 + +#define PXE_LOOPBACK_INTERNAL_SUPPORTED 1 +#define PXE_LOOPBACK_EXTERNAL_SUPPORTED 2 + +typedef struct s_pxe_pci_config_info { + // + // This is the flag field for the PXE_DB_GET_CONFIG_INFO union. + // For PCI bus devices, this field is set to PXE_BUSTYPE_PCI. + // + UINT32 BusType; + + // + // This identifies the PCI network device that this UNDI interface + // is bound to. + // + UINT16 Bus; + UINT8 Device; + UINT8 Function; + + // + // This is a copy of the PCI configuration space for this + // network device. + // + union { + UINT8 Byte[256]; + UINT16 Word[128]; + UINT32 Dword[64]; + } Config; +} PXE_PCI_CONFIG_INFO; + +typedef struct s_pxe_pcc_config_info { + // + // This is the flag field for the PXE_DB_GET_CONFIG_INFO union. + // For PCC bus devices, this field is set to PXE_BUSTYPE_PCC. + // + PXE_UINT32 BusType; + + // + // This identifies the PCC network device that this UNDI interface + // is bound to. + // + PXE_UINT16 Bus; + PXE_UINT8 Device; + PXE_UINT8 Function; + + // + // This is a copy of the PCC configuration space for this + // network device. + // + union { + PXE_UINT8 Byte[256]; + PXE_UINT16 Word[128]; + PXE_UINT32 Dword[64]; + } Config; +} PXE_PCC_CONFIG_INFO; + +typedef union u_pxe_db_get_config_info { + PXE_PCI_CONFIG_INFO pci; + PXE_PCC_CONFIG_INFO pcc; +} PXE_DB_GET_CONFIG_INFO; + +typedef struct s_pxe_cpb_initialize { + // + // Address of first (lowest) byte of the memory buffer. This buffer must + // be in contiguous physical memory and cannot be swapped out. The UNDI + // will be using this for transmit and receive buffering. + // + PXE_UINT64 MemoryAddr; + + // + // MemoryLength must be greater than or equal to MemoryRequired + // returned by the Get Init Info command. + // + PXE_UINT32 MemoryLength; + + // + // Desired link speed in Mbit/sec. Common ethernet values are 10, 100 + // and 1000. Setting a value of zero will auto-detect and/or use the + // default link speed (operation depends on UNDI/NIC functionality). + // + PXE_UINT32 LinkSpeed; + + // + // Suggested number and size of receive and transmit buffers to + // allocate. If MemoryAddr and MemoryLength are non-zero, this + // allocation comes out of the supplied memory buffer. If MemoryAddr + // and MemoryLength are zero, this allocation comes out of memory + // on the NIC. + // + // If these fields are set to zero, the UNDI will allocate buffer + // counts and sizes as it sees fit. + // + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; + + // + // The following configuration parameters are optional and must be zero + // to use the default values. + // + PXE_UINT8 DuplexMode; + + PXE_UINT8 LoopBackMode; +} PXE_CPB_INITIALIZE; + +#define PXE_DUPLEX_DEFAULT 0x00 +#define PXE_FORCE_FULL_DUPLEX 0x01 +#define PXE_ENABLE_FULL_DUPLEX 0x02 +#define PXE_FORCE_HALF_DUPLEX 0x04 +#define PXE_DISABLE_FULL_DUPLEX 0x08 + +#define LOOPBACK_NORMAL 0 +#define LOOPBACK_INTERNAL 1 +#define LOOPBACK_EXTERNAL 2 + +typedef struct s_pxe_db_initialize { + // + // Actual amount of memory used from the supplied memory buffer. This + // may be less that the amount of memory suppllied and may be zero if + // the UNDI and network device do not use external memory buffers. + // + // Memory used by the UNDI and network device is allocated from the + // lowest memory buffer address. + // + PXE_UINT32 MemoryUsed; + + // + // Actual number and size of receive and transmit buffers that were + // allocated. + // + PXE_UINT16 TxBufCnt; + PXE_UINT16 TxBufSize; + PXE_UINT16 RxBufCnt; + PXE_UINT16 RxBufSize; +} PXE_DB_INITIALIZE; + +typedef struct s_pxe_cpb_receive_filters { + // + // List of multicast MAC addresses. This list, if present, will + // replace the existing multicast MAC address filter list. + // + PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT]; +} PXE_CPB_RECEIVE_FILTERS; + +typedef struct s_pxe_db_receive_filters { + // + // Filtered multicast MAC address list. + // + PXE_MAC_ADDR MCastList[MAX_MCAST_ADDRESS_CNT]; +} PXE_DB_RECEIVE_FILTERS; + +typedef struct s_pxe_cpb_station_address { + // + // If supplied and supported, the current station MAC address + // will be changed. + // + PXE_MAC_ADDR StationAddr; +} PXE_CPB_STATION_ADDRESS; + +typedef struct s_pxe_dpb_station_address { + // + // Current station MAC address. + // + PXE_MAC_ADDR StationAddr; + + // + // Station broadcast MAC address. + // + PXE_MAC_ADDR BroadcastAddr; + + // + // Permanent station MAC address. + // + PXE_MAC_ADDR PermanentAddr; +} PXE_DB_STATION_ADDRESS; + +typedef struct s_pxe_db_statistics { + // + // Bit field identifying what statistic data is collected by the + // UNDI/NIC. + // If bit 0x00 is set, Data[0x00] is collected. + // If bit 0x01 is set, Data[0x01] is collected. + // If bit 0x20 is set, Data[0x20] is collected. + // If bit 0x21 is set, Data[0x21] is collected. + // Etc. + // + PXE_UINT64 Supported; + + // + // Statistic data. + // + PXE_UINT64 Data[64]; +} PXE_DB_STATISTICS; + +// +// Total number of frames received. Includes frames with errors and +// dropped frames. +// +#define PXE_STATISTICS_RX_TOTAL_FRAMES 0x00 + +// +// Number of valid frames received and copied into receive buffers. +// +#define PXE_STATISTICS_RX_GOOD_FRAMES 0x01 + +// +// Number of frames below the minimum length for the media. +// This would be <64 for ethernet. +// +#define PXE_STATISTICS_RX_UNDERSIZE_FRAMES 0x02 + +// +// Number of frames longer than the maxminum length for the +// media. This would be >1500 for ethernet. +// +#define PXE_STATISTICS_RX_OVERSIZE_FRAMES 0x03 + +// +// Valid frames that were dropped because receive buffers were full. +// +#define PXE_STATISTICS_RX_DROPPED_FRAMES 0x04 + +// +// Number of valid unicast frames received and not dropped. +// +#define PXE_STATISTICS_RX_UNICAST_FRAMES 0x05 + +// +// Number of valid broadcast frames received and not dropped. +// +#define PXE_STATISTICS_RX_BROADCAST_FRAMES 0x06 + +// +// Number of valid mutlicast frames received and not dropped. +// +#define PXE_STATISTICS_RX_MULTICAST_FRAMES 0x07 + +// +// Number of frames w/ CRC or alignment errors. +// +#define PXE_STATISTICS_RX_CRC_ERROR_FRAMES 0x08 + +// +// Total number of bytes received. Includes frames with errors +// and dropped frames. +// +#define PXE_STATISTICS_RX_TOTAL_BYTES 0x09 + +// +// Transmit statistics. +// +#define PXE_STATISTICS_TX_TOTAL_FRAMES 0x0A +#define PXE_STATISTICS_TX_GOOD_FRAMES 0x0B +#define PXE_STATISTICS_TX_UNDERSIZE_FRAMES 0x0C +#define PXE_STATISTICS_TX_OVERSIZE_FRAMES 0x0D +#define PXE_STATISTICS_TX_DROPPED_FRAMES 0x0E +#define PXE_STATISTICS_TX_UNICAST_FRAMES 0x0F +#define PXE_STATISTICS_TX_BROADCAST_FRAMES 0x10 +#define PXE_STATISTICS_TX_MULTICAST_FRAMES 0x11 +#define PXE_STATISTICS_TX_CRC_ERROR_FRAMES 0x12 +#define PXE_STATISTICS_TX_TOTAL_BYTES 0x13 + +// +// Number of collisions detection on this subnet. +// +#define PXE_STATISTICS_COLLISIONS 0x14 + +// +// Number of frames destined for unsupported protocol. +// +#define PXE_STATISTICS_UNSUPPORTED_PROTOCOL 0x15 + +typedef struct s_pxe_cpb_mcast_ip_to_mac { + // + // Multicast IP address to be converted to multicast MAC address. + // + PXE_IP_ADDR IP; +} PXE_CPB_MCAST_IP_TO_MAC; + +typedef struct s_pxe_db_mcast_ip_to_mac { + // + // Multicast MAC address. + // + PXE_MAC_ADDR MAC; +} PXE_DB_MCAST_IP_TO_MAC; + +typedef struct s_pxe_cpb_nvdata_sparse { + // + // NvData item list. Only items in this list will be updated. + // + struct { + // + // Non-volatile storage address to be changed. + // + PXE_UINT32 Addr; + + // + // Data item to write into above storage address. + // + union { + PXE_UINT8 Byte; + PXE_UINT16 Word; + PXE_UINT32 Dword; + } Data; + } Item[MAX_EEPROM_LEN]; +} +PXE_CPB_NVDATA_SPARSE; + +// +// When using bulk update, the size of the CPB structure must be +// the same size as the non-volatile NIC storage. +// +typedef union u_pxe_cpb_nvdata_bulk { + // + // Array of byte-wide data items. + // + PXE_UINT8 Byte[MAX_EEPROM_LEN << 2]; + + // + // Array of word-wide data items. + // + PXE_UINT16 Word[MAX_EEPROM_LEN << 1]; + + // + // Array of dword-wide data items. + // + PXE_UINT32 Dword[MAX_EEPROM_LEN]; +} PXE_CPB_NVDATA_BULK; + +typedef struct s_pxe_db_nvdata { + // + // Arrays of data items from non-volatile storage. + // + union { + // + // Array of byte-wide data items. + // + PXE_UINT8 Byte[MAX_EEPROM_LEN << 2]; + + // + // Array of word-wide data items. + // + PXE_UINT16 Word[MAX_EEPROM_LEN << 1]; + + // + // Array of dword-wide data items. + // + PXE_UINT32 Dword[MAX_EEPROM_LEN]; + } Data; +} PXE_DB_NVDATA; + +typedef struct s_pxe_db_get_status { + // + // Length of next receive frame (header + data). If this is zero, + // there is no next receive frame available. + // + PXE_UINT32 RxFrameLen; + + // + // Reserved, set to zero. + // + PXE_UINT32 reserved; + + // + // Addresses of transmitted buffers that need to be recycled. + // + PXE_UINT64 TxBuffer[MAX_XMIT_BUFFERS]; +} PXE_DB_GET_STATUS; + +typedef struct s_pxe_cpb_fill_header { + // + // Source and destination MAC addresses. These will be copied into + // the media header without doing byte swapping. + // + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + // + // Address of first byte of media header. The first byte of packet data + // follows the last byte of the media header. + // + PXE_UINT64 MediaHeader; + + // + // Length of packet data in bytes (not including the media header). + // + PXE_UINT32 PacketLen; + + // + // Protocol type. This will be copied into the media header without + // doing byte swapping. Protocol type numbers can be obtained from + // the Assigned Numbers RFC 1700. + // + PXE_UINT16 Protocol; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaHeaderLen; +} PXE_CPB_FILL_HEADER; + +#define PXE_PROTOCOL_ETHERNET_IP 0x0800 +#define PXE_PROTOCOL_ETHERNET_ARP 0x0806 +#define MAX_XMIT_FRAGMENTS 16 + +typedef struct s_pxe_cpb_fill_header_fragmented { + // + // Source and destination MAC addresses. These will be copied into + // the media header without doing byte swapping. + // + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + // + // Length of packet data in bytes (not including the media header). + // + PXE_UINT32 PacketLen; + + // + // Protocol type. This will be copied into the media header without + // doing byte swapping. Protocol type numbers can be obtained from + // the Assigned Numbers RFC 1700. + // + PXE_MEDIA_PROTOCOL Protocol; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaHeaderLen; + + // + // Number of packet fragment descriptors. + // + PXE_UINT16 FragCnt; + + // + // Reserved, must be set to zero. + // + PXE_UINT16 reserved; + + // + // Array of packet fragment descriptors. The first byte of the media + // header is the first byte of the first fragment. + // + struct { + // + // Address of this packet fragment. + // + PXE_UINT64 FragAddr; + + // + // Length of this packet fragment. + // + PXE_UINT32 FragLen; + + // + // Reserved, must be set to zero. + // + PXE_UINT32 reserved; + } FragDesc[MAX_XMIT_FRAGMENTS]; +} +PXE_CPB_FILL_HEADER_FRAGMENTED; + +typedef struct s_pxe_cpb_transmit { + // + // Address of first byte of frame buffer. This is also the first byte + // of the media header. + // + PXE_UINT64 FrameAddr; + + // + // Length of the data portion of the frame buffer in bytes. Do not + // include the length of the media header. + // + PXE_UINT32 DataLen; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaheaderLen; + + // + // Reserved, must be zero. + // + PXE_UINT16 reserved; +} PXE_CPB_TRANSMIT; + +typedef struct s_pxe_cpb_transmit_fragments { + // + // Length of packet data in bytes (not including the media header). + // + PXE_UINT32 FrameLen; + + // + // Length of the media header in bytes. + // + PXE_UINT16 MediaheaderLen; + + // + // Number of packet fragment descriptors. + // + PXE_UINT16 FragCnt; + + // + // Array of frame fragment descriptors. The first byte of the first + // fragment is also the first byte of the media header. + // + struct { + // + // Address of this frame fragment. + // + PXE_UINT64 FragAddr; + + // + // Length of this frame fragment. + // + PXE_UINT32 FragLen; + + // + // Reserved, must be set to zero. + // + PXE_UINT32 reserved; + } FragDesc[MAX_XMIT_FRAGMENTS]; +} +PXE_CPB_TRANSMIT_FRAGMENTS; + +typedef struct s_pxe_cpb_receive { + // + // Address of first byte of receive buffer. This is also the first byte + // of the frame header. + // + PXE_UINT64 BufferAddr; + + // + // Length of receive buffer. This must be large enough to hold the + // received frame (media header + data). If the length of smaller than + // the received frame, data will be lost. + // + PXE_UINT32 BufferLen; + + // + // Reserved, must be set to zero. + // + PXE_UINT32 reserved; +} PXE_CPB_RECEIVE; + +typedef struct s_pxe_db_receive { + // + // Source and destination MAC addresses from media header. + // + PXE_MAC_ADDR SrcAddr; + PXE_MAC_ADDR DestAddr; + + // + // Length of received frame. May be larger than receive buffer size. + // The receive buffer will not be overwritten. This is how to tell + // if data was lost because the receive buffer was too small. + // + PXE_UINT32 FrameLen; + + // + // Protocol type from media header. + // + PXE_MEDIA_PROTOCOL Protocol; + + // + // Length of media header in received frame. + // + PXE_UINT16 MediaHeaderLen; + + // + // Type of receive frame. + // + PXE_FRAME_TYPE Type; + + // + // Reserved, must be zero. + // + PXE_UINT8 reserved[7]; + +} PXE_DB_RECEIVE; + +#pragma pack() + +#endif diff --git a/MdePkg/Include/Uefi/Errors.h b/MdePkg/Include/Uefi/Errors.h new file mode 100644 index 0000000000..fd1dc02c81 --- /dev/null +++ b/MdePkg/Include/Uefi/Errors.h @@ -0,0 +1,24 @@ +/** @file + Include file that supportes UEFI Error Codes. + + This include file must only contain things defined in the UEFI 2.0 specification. + + Copyright (c) 2006, 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. + + Module Name: UefiErrors.h + +**/ + +#ifndef __UEFI_ERRORS_H__ +#define __UEFI_ERRORS_H__ + + + +#endif diff --git a/MdePkg/Include/Uefi/UefiSpec.h b/MdePkg/Include/Uefi/UefiSpec.h new file mode 100644 index 0000000000..d648b1b9f1 --- /dev/null +++ b/MdePkg/Include/Uefi/UefiSpec.h @@ -0,0 +1,2460 @@ +/** @file + Include file that supportes UEFI. + + This include file must only contain things defined in the UEFI 2.0 specification. + If a code construct is defined in the UEFI 2.0 specification it must be included + by this include file. + + Copyright (c) 2006, 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. + + Module Name: UefiSpec.h + +**/ + +#ifndef __UEFI_SPEC_H__ +#define __UEFI_SPEC_H__ + +#include + +// +// EFI Data Types based on ANSI C integer types in EfiBind.h +// + + +// +// EFI Data Types derived from other EFI data types. +// + +#define NULL_HANDLE ((VOID *) 0) + +typedef VOID *EFI_EVENT; +typedef UINTN EFI_TPL; + +// +// EFI Time Abstraction: +// Year: 2000 - 20XX +// Month: 1 - 12 +// Day: 1 - 31 +// Hour: 0 - 23 +// Minute: 0 - 59 +// Second: 0 - 59 +// Nanosecond: 0 - 999,999,999 +// TimeZone: -1440 to 1440 or 2047 +// +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + UINT8 Pad1; + UINT32 Nanosecond; + INT16 TimeZone; + UINT8 Daylight; + UINT8 Pad2; +} EFI_TIME; + +// +// Bit definitions for EFI_TIME.Daylight +// +#define EFI_TIME_ADJUST_DAYLIGHT 0x01 +#define EFI_TIME_IN_DAYLIGHT 0x02 + +// +// Value definition for EFI_TIME.TimeZone +// +#define EFI_UNSPECIFIED_TIMEZONE 0x07FF + +// +// Networking +// +typedef struct { + UINT8 Addr[4]; +} EFI_IPv4_ADDRESS; + +typedef struct { + UINT8 Addr[16]; +} EFI_IPv6_ADDRESS; + +typedef struct { + UINT8 Addr[32]; +} EFI_MAC_ADDRESS; + +typedef union { + UINT32 Addr[4]; + EFI_IPv4_ADDRESS v4; + EFI_IPv6_ADDRESS v6; +} EFI_IP_ADDRESS; + + +typedef enum { + AllocateAnyPages, + AllocateMaxAddress, + AllocateAddress, + MaxAllocateType +} EFI_ALLOCATE_TYPE; + + +// +// possible caching types for the memory range +// +#define EFI_MEMORY_UC 0x0000000000000001ULL +#define EFI_MEMORY_WC 0x0000000000000002ULL +#define EFI_MEMORY_WT 0x0000000000000004ULL +#define EFI_MEMORY_WB 0x0000000000000008ULL +#define EFI_MEMORY_UCE 0x0000000000000010ULL + +// +// physical memory protection on range +// +#define EFI_MEMORY_WP 0x0000000000001000ULL +#define EFI_MEMORY_RP 0x0000000000002000ULL +#define EFI_MEMORY_XP 0x0000000000004000ULL + +// +// range requires a runtime mapping +// +#define EFI_MEMORY_RUNTIME 0x8000000000000000ULL + +typedef UINT64 EFI_VIRTUAL_ADDRESS; + +#define EFI_MEMORY_DESCRIPTOR_VERSION 1 +typedef struct { + UINT32 Type; + UINT32 Pad; + EFI_PHYSICAL_ADDRESS PhysicalStart; + EFI_VIRTUAL_ADDRESS VirtualStart; + UINT64 NumberOfPages; + UINT64 Attribute; +} EFI_MEMORY_DESCRIPTOR; + +// +// EFI_FIELD_OFFSET - returns the byte offset to a field within a structure +// +#define EFI_FIELD_OFFSET(TYPE,Field) ((UINTN)(&(((TYPE *) 0)->Field))) + +#include +#include +#include + +// +// Declare forward referenced data structures +// +typedef struct _EFI_SYSTEM_TABLE EFI_SYSTEM_TABLE; + +/** + Allocates memory pages from the system. + + @param Type The type of allocation to perform. + @param MemoryType The type of memory to allocate. + @param Pages The number of contiguous 4 KB pages to allocate. + @param Memory Pointer to a physical address. On input, the way in which the address is + used depends on the value of Type. + + @retval EFI_SUCCESS The requested pages were allocated. + @retval EFI_INVALID_PARAMETER 1) Type is not AllocateAnyPages or + AllocateMaxAddress or AllocateAddress. + 2) MemoryType is in the range + EfiMaxMemoryType..0x7FFFFFFF. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + @retval EFI_NOT_FOUND The requested pages could not be found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_PAGES) ( + IN EFI_ALLOCATE_TYPE Type, + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ); + +/** + Frees memory pages. + + @param Memory The base physical address of the pages to be freed. + @param Pages The number of contiguous 4 KB pages to free. + + @retval EFI_SUCCESS The requested pages were freed. + @retval EFI_INVALID_PARAMETER Memory is not a page-aligned address or Pages is invalid. + @retval EFI_NOT_FOUND The requested memory pages were not allocated with + AllocatePages(). + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_PAGES) ( + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN Pages + ); + +/** + Returns the current memory map. + + @param MemoryMapSize A pointer to the size, in bytes, of the MemoryMap buffer. + @param MemoryMap A pointer to the buffer in which firmware places the current memory + map. + @param MapKey A pointer to the location in which firmware returns the key for the + current memory map. + @param DescriptorSize A pointer to the location in which firmware returns the size, in bytes, of + an individual EFI_MEMORY_DESCRIPTOR. + @param DescriptorVersion A pointer to the location in which firmware returns the version number + associated with the EFI_MEMORY_DESCRIPTOR. + + @retval EFI_SUCCESS The memory map was returned in the MemoryMap buffer. + @retval EFI_BUFFER_TOO_SMALL The MemoryMap buffer was too small. The current buffer size + needed to hold the memory map is returned in MemoryMapSize. + @retval EFI_INVALID_PARAMETER 1) MemoryMapSize is NULL. + 2) The MemoryMap buffer is not too small and MemoryMap is + NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_MEMORY_MAP) ( + IN OUT UINTN *MemoryMapSize, + IN OUT EFI_MEMORY_DESCRIPTOR *MemoryMap, + OUT UINTN *MapKey, + OUT UINTN *DescriptorSize, + OUT UINT32 *DescriptorVersion + ); + +#define NextMemoryDescriptor(_Ptr, _Size) ((EFI_MEMORY_DESCRIPTOR *) (((UINT8 *) (_Ptr)) + (_Size))) +#define NEXT_MEMORY_DESCRIPTOR(_Ptr, _Size) NextMemoryDescriptor (_Ptr, _Size) + +/** + Allocates pool memory. + + @param PoolType The type of pool to allocate. + @param Size The number of bytes to allocate from the pool. + @param Buffer A pointer to a pointer to the allocated buffer if the call succeeds; + undefined otherwise. + + @retval EFI_SUCCESS The requested number of bytes was allocated. + @retval EFI_OUT_OF_RESOURCES The pool requested could not be allocated. + @retval EFI_INVALID_PARAMETER PoolType was invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_ALLOCATE_POOL) ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN Size, + OUT VOID **Buffer + ); + +/** + Returns pool memory to the system. + + @param Buffer Pointer to the buffer to free. + + @retval EFI_SUCCESS The memory was returned to the system. + @retval EFI_INVALID_PARAMETER Buffer was invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_FREE_POOL) ( + IN VOID *Buffer + ); + +/** + Changes the runtime addressing mode of EFI firmware from physical to virtual. + + @param MemoryMapSize The size in bytes of VirtualMap. + @param DescriptorSize The size in bytes of an entry in the VirtualMap. + @param DescriptorVersion The version of the structure entries in VirtualMap. + @param VirtualMap An array of memory descriptors which contain new virtual + address mapping information for all runtime ranges. + + @retval EFI_SUCCESS The virtual address map has been applied. + @retval EFI_UNSUPPORTED EFI firmware is not at runtime, or the EFI firmware is already in + virtual address mapped mode. + @retval EFI_INVALID_PARAMETER DescriptorSize or DescriptorVersion is invalid. + @retval EFI_NO_MAPPING A virtual address was not supplied for a range in the memory + map that requires a mapping. + @retval EFI_NOT_FOUND A virtual address was supplied for an address that is not found + in the memory map. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_VIRTUAL_ADDRESS_MAP) ( + IN UINTN MemoryMapSize, + IN UINTN DescriptorSize, + IN UINT32 DescriptorVersion, + IN EFI_MEMORY_DESCRIPTOR *VirtualMap + ); + +/** + Connects one or more drivers to a controller. + + @param ControllerHandle The handle of the controller to which driver(s) are to be connected. + @param DriverImageHandle A pointer to an ordered list handles that support the + EFI_DRIVER_BINDING_PROTOCOL. + @param RemainingDevicePath A pointer to the device path that specifies a child of the + controller specified by ControllerHandle. + @param Recursive If TRUE, then ConnectController() is called recursively + until the entire tree of controllers below the controller specified + by ControllerHandle have been created. If FALSE, then + the tree of controllers is only expanded one level. + + @retval EFI_SUCCESS 1) One or more drivers were connected to ControllerHandle. + 2) No drivers were connected to ControllerHandle, but + RemainingDevicePath is not NULL, and it is an End Device + Path Node. + @retval EFI_INVALID_PARAMETER ControllerHandle is not a valid EFI_HANDLE. + @retval EFI_NOT_FOUND 1) There are no EFI_DRIVER_BINDING_PROTOCOL instances + present in the system. + 2) No drivers were connected to ControllerHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CONNECT_CONTROLLER) ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE *DriverImageHandle, OPTIONAL + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath, OPTIONAL + IN BOOLEAN Recursive + ); + +/** + Disconnects one or more drivers from a controller. + + @param ControllerHandle The handle of the controller from which driver(s) are to be disconnected. + @param DriverImageHandle The driver to disconnect from ControllerHandle. + @param ChildHandle The handle of the child to destroy. + + @retval EFI_SUCCESS 1) One or more drivers were disconnected from the controller. + 2) On entry, no drivers are managing ControllerHandle. + 3) DriverImageHandle is not NULL, and on entry + DriverImageHandle is not managing ControllerHandle. + + @retval EFI_INVALID_PARAMETER One ore more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to disconnect any drivers from + ControllerHandle. + @retval EFI_DEVICE_ERROR The controller could not be disconnected because of a device error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_DISCONNECT_CONTROLLER) ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE DriverImageHandle, OPTIONAL + IN EFI_HANDLE ChildHandle OPTIONAL + ); + +// +// ConvertPointer DebugDisposition type. +// +#define EFI_OPTIONAL_PTR 0x00000001 +#define EFI_OPTIONAL_POINTER EFI_OPTIONAL_PTR + +/** + Determines the new virtual address that is to be used on subsequent memory accesses. + + @param DebugDisposition Supplies type information for the pointer being converted. + @param Address A pointer to a pointer that is to be fixed to be the value needed + for the new virtual address mappings being applied. + + @retval EFI_SUCCESS The pointer pointed to by Address was modified. + @retval EFI_INVALID_PARAMETER 1) Address is NULL. + 2) *Address is NULL and DebugDisposition does + not have the EFI_OPTIONAL_PTR bit set. + @retval EFI_NOT_FOUND The pointer pointed to by Address was not found to be part + of the current memory map. This is normally fatal. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CONVERT_POINTER) ( + IN UINTN DebugDisposition, + IN OUT VOID **Address + ); + +// +// EFI Event Types (name defined in spec) +// +#define EVENT_TIMER 0x80000000 +#define EVENT_RUNTIME 0x40000000 +#define EVENT_RUNTIME_CONTEXT 0x20000000 + +#define EVENT_NOTIFY_WAIT 0x00000100 +#define EVENT_NOTIFY_SIGNAL 0x00000200 + +#define EVENT_SIGNAL_EXIT_BOOT_SERVICES 0x00000201 +#define EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE 0x60000202 + +#if ((EDK_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000)) +// +// Prior to UEFI 2.0 Tiano extended these enums. This was replaced by +// CreateEventEx() Event Groups in UEFI 2.0 +// +#define EFI_EVENT_NOTIFY_SIGNAL_ALL 0x00000400 + +#define EFI_EVENT_SIGNAL_READY_TO_BOOT 0x00000203 +#define EFI_EVENT_SIGNAL_LEGACY_BOOT 0x00000204 + +#endif + +// +// EFI Event Types (name following coding style) +// +#define EFI_EVENT_TIMER EVENT_TIMER +#define EFI_EVENT_RUNTIME EVENT_RUNTIME +#define EFI_EVENT_RUNTIME_CONTEXT EVENT_RUNTIME_CONTEXT + +#define EFI_EVENT_NOTIFY_WAIT EVENT_NOTIFY_WAIT +#define EFI_EVENT_NOTIFY_SIGNAL EVENT_NOTIFY_SIGNAL + +#define EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES EVENT_SIGNAL_EXIT_BOOT_SERVICES +#define EFI_EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE EVENT_SIGNAL_VIRTUAL_ADDRESS_CHANGE + + +/** + Invoke a notification event + + @param Event Event whose notification function is being invoked. + @param Context Pointer to the notification function¡¯s context, + which is implementation-dependent. + +**/ +typedef +VOID +(EFIAPI *EFI_EVENT_NOTIFY) ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +/** + Creates an event. + + @param Type The type of event to create and its mode and attributes. + @param NotifyTpl Pointer to the notification function¡¯s context. + @param NotifyFunction Pointer to the event¡¯s notification function, if any. + @param NotifyContext Pointer to the notification function¡¯s context; corresponds to parameter + Context in the notification function. + @param Event Pointer to the newly created event if the call succeeds; undefined + otherwise. + + @retval EFI_SUCCESS The event structure was created. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The event could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREATE_EVENT) ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, + OUT EFI_EVENT *Event + ); + +/** + Creates an event in a group. + + @param Type The type of event to create and its mode and attributes. + @param NotifyTpl Pointer to the notification function¡¯s context. + @param NotifyFunction Pointer to the event¡¯s notification function, if any. + @param NotifyContext Pointer to the notification function¡¯s context; corresponds to parameter + Context in the notification function. + @param EventGroup Pointer to the unique identifier of the group to which this event belongs. + @param Event Pointer to the newly created event if the call succeeds; undefined + otherwise. + + @retval EFI_SUCCESS The event structure was created. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_OUT_OF_RESOURCES The event could not be allocated. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CREATE_EVENT_EX) ( + IN UINT32 Type, + IN EFI_TPL NotifyTpl OPTIONAL, + IN EFI_EVENT_NOTIFY NotifyFunction OPTIONAL, + IN CONST VOID *NotifyContext OPTIONAL, + IN CONST EFI_GUID *EventGroup OPTIONAL, + OUT EFI_EVENT *Event + ); + +typedef enum { + TimerCancel, + TimerPeriodic, + TimerRelative +} EFI_TIMER_DELAY; + +/** + Sets the type of timer and the trigger time for a timer event. + + @param Event The timer event that is to be signaled at the specified time. + @param Type The type of time that is specified in TriggerTime. + @param TriggerTime The number of 100ns units until the timer expires. + + @retval EFI_SUCCESS The event has been set to be signaled at the requested time. + @retval EFI_INVALID_PARAMETER Event or Type is not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_TIMER) ( + IN EFI_EVENT Event, + IN EFI_TIMER_DELAY Type, + IN UINT64 TriggerTime + ); + +/** + Signals an event. + + @param Event The event to signal. + + @retval EFI_SUCCESS The event has been signaled. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SIGNAL_EVENT) ( + IN EFI_EVENT Event + ); + +/** + Stops execution until an event is signaled. + + @param NumberOfEvents The number of events in the Event array. + @param Event An array of EFI_EVENT. + @param Index Pointer to the index of the event which satisfied the wait condition. + + @retval EFI_SUCCESS The event indicated by Index was signaled. + @retval EFI_INVALID_PARAMETER 1) NumberOfEvents is 0. + 2) The event indicated by Index is of type + EVT_NOTIFY_SIGNAL. + @retval EFI_UNSUPPORTED The current TPL is not TPL_APPLICATION. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_WAIT_FOR_EVENT) ( + IN UINTN NumberOfEvents, + IN EFI_EVENT *Event, + OUT UINTN *Index + ); + +/** + Closes an event. + + @param Event The event to close. + + @retval EFI_SUCCESS The event has been closed. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CLOSE_EVENT) ( + IN EFI_EVENT Event + ); + +/** + Checks whether an event is in the signaled state. + + @param Event The event to check. + + @retval EFI_SUCCESS The event is in the signaled state. + @retval EFI_NOT_READY The event is not in the signaled state. + @retval EFI_INVALID_PARAMETER Event is of type EVT_NOTIFY_SIGNAL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CHECK_EVENT) ( + IN EFI_EVENT Event + ); + +// +// Task priority level (name defined in spec). +// +#define TPL_APPLICATION 4 +#define TPL_CALLBACK 8 +#define TPL_NOTIFY 16 +#define TPL_HIGH_LEVEL 31 + +// +// Task priority level (name following coding style). +// +#define EFI_TPL_APPLICATION TPL_APPLICATION +#define EFI_TPL_CALLBACK TPL_CALLBACK +#define EFI_TPL_NOTIFY TPL_NOTIFY +#define EFI_TPL_HIGH_LEVEL TPL_HIGH_LEVEL + +/** + Raises a task¡¯s priority level and returns its previous level. + + @param NewTpl The new task priority level. + + @retval Previous task priority level + +**/ +typedef +EFI_TPL +(EFIAPI *EFI_RAISE_TPL) ( + IN EFI_TPL NewTpl + ); + +/** + Restores a task¡¯s priority level to its previous value. + + @param OldTpl The previous task priority level to restore + +**/ +typedef +VOID +(EFIAPI *EFI_RESTORE_TPL) ( + IN EFI_TPL OldTpl + ); + +// +// Variable attributes +// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 + +/** + Returns the value of a variable. + + @param VariableName A Null-terminated Unicode string that is the name of the + vendor¡¯s variable. + @param VendorGuid A unique identifier for the vendor. + @param Attributes If not NULL, a pointer to the memory location to return the + attributes bitmask for the variable. + @param DataSize On input, the size in bytes of the return Data buffer. + On output the size of data returned in Data. + @param Data The buffer to return the contents of the variable. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The variable was not found. + @retval EFI_BUFFER_TOO_SMALL The DataSize is too small for the result. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_VARIABLE) ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT UINT32 *Attributes, OPTIONAL + IN OUT UINTN *DataSize, + OUT VOID *Data + ); + +/** + Enumerates the current variable names. + + @param VariableNameSize The size of the VariableName buffer. + @param VariableName On input, supplies the last VariableName that was returned + by GetNextVariableName(). On output, returns the Nullterminated + Unicode string of the current variable. + @param VendorGuid On input, supplies the last VendorGuid that was returned by + GetNextVariableName(). On output, returns the + VendorGuid of the current variable. + + @retval EFI_SUCCESS The function completed successfully. + @retval EFI_NOT_FOUND The next variable was not found. + @retval EFI_BUFFER_TOO_SMALL The VariableNameSize is too small for the result. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_VARIABLE_NAME) ( + IN OUT UINTN *VariableNameSize, + IN OUT CHAR16 *VariableName, + IN OUT EFI_GUID *VendorGuid + ); + +/** + Sets the value of a variable. + + @param VariableName A Null-terminated Unicode string that is the name of the + vendor¡¯s variable. + @param VendorGuid A unique identifier for the vendor. + @param Attributes Attributes bitmask to set for the variable. + @param DataSize The size in bytes of the Data buffer. + @param Data The contents for the variable. + + @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as + defined by the Attributes. + @retval EFI_WRITE_PROTECTED The variable in question is read-only. + @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the variable and its data. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_DEVICE_ERROR The variable could not be retrieved due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_VARIABLE) ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT32 Attributes, + IN UINTN DataSize, + IN VOID *Data + ); + +// +// EFI Time +// +typedef struct { + UINT32 Resolution; + UINT32 Accuracy; + BOOLEAN SetsToZero; +} EFI_TIME_CAPABILITIES; + +/** + Returns the current time and date information, and the time-keeping capabilities + of the hardware platform. + + @param Time A pointer to storage to receive a snapshot of the current time. + @param Capabilities An optional pointer to a buffer to receive the real time clock + device¡¯s capabilities. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER Time is NULL. + @retval EFI_DEVICE_ERROR The time could not be retrieved due to hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_TIME) ( + OUT EFI_TIME *Time, + OUT EFI_TIME_CAPABILITIES *Capabilities OPTIONAL + ); + +/** + Sets the current local time and date information. + + @param Time A pointer to the current time. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The time could not be set due due to hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_TIME) ( + IN EFI_TIME *Time + ); + +/** + Returns the current wakeup alarm clock setting. + + @param Enabled Indicates if the alarm is currently enabled or disabled. + @param Pending Indicates if the alarm signal is pending and requires acknowledgement. + @param Time The current alarm setting. + + @retval EFI_SUCCESS The alarm settings were returned. + @retval EFI_INVALID_PARAMETER Any parameter is NULL. + @retval EFI_DEVICE_ERROR The wakeup time could not be retrieved due to a hardware error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_WAKEUP_TIME) ( + OUT BOOLEAN *Enabled, + OUT BOOLEAN *Pending, + OUT EFI_TIME *Time + ); + +/** + Sets the system wakeup alarm clock time. + + @param Enabled Enable or disable the wakeup alarm. + @param Time If Enable is TRUE, the time to set the wakeup alarm for. + + @retval EFI_SUCCESS If Enable is TRUE, then the wakeup alarm was enabled. If + Enable is FALSE, then the wakeup alarm was disabled. + @retval EFI_INVALID_PARAMETER A time field is out of range. + @retval EFI_DEVICE_ERROR The wakeup time could not be set due to a hardware error. + @retval EFI_UNSUPPORTED A wakeup timer is not supported on this platform. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_WAKEUP_TIME) ( + IN BOOLEAN Enable, + IN EFI_TIME *Time OPTIONAL + ); + +/** + This is the declaration of an EFI image entry point. This can be the entry point to an application + written to this specification, an EFI boot service driver, or an EFI runtime driver. + + @param ImageHandle Handle that identifies the loaded image. + @param SystemTable System Table for this image. + + @retval EFI_SUCCESS The operation completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_ENTRY_POINT) ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Loads an EFI image into memory. + + @param BootPolicy If TRUE, indicates that the request originates from the boot + manager, and that the boot manager is attempting to load + FilePath as a boot selection. Ignored if SourceBuffer is + not NULL. + @param ParentImageHandle The caller¡¯s image handle. + @param FilePath The DeviceHandle specific file path from which the image is + loaded. + @param SourceBuffer If not NULL, a pointer to the memory location containing a copy + of the image to be loaded. + @param SourceSize The size in bytes of SourceBuffer. + @param ImageHandle Pointer to the returned image handle that is created when the + image is successfully loaded. + + @retval EFI_SUCCESS Image was loaded into memory correctly. + @retval EFI_NOT_FOUND Both SourceBuffer and FilePath are NULL. + @retval EFI_INVALID_PARAMETER One or more parametes are invalid. + @retval EFI_UNSUPPORTED The image type is not supported. + @retval EFI_OUT_OF_RESOURCES Image was not loaded due to insufficient resources. + @retval EFI_LOAD_ERROR Image was not loaded because the image format was corrupt or not + understood. + @retval EFI_DEVICE_ERROR Image was not loaded because the device returned a read error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_LOAD) ( + IN BOOLEAN BootPolicy, + IN EFI_HANDLE ParentImageHandle, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN VOID *SourceBuffer OPTIONAL, + IN UINTN SourceSize, + OUT EFI_HANDLE *ImageHandle + ); + +/** + Transfers control to a loaded image¡¯s entry point. + + @param ImageHandle Handle of image to be started. + @param ExitDataSize Pointer to the size, in bytes, of ExitData. + @param ExitData Pointer to a pointer to a data buffer that includes a Null-terminated + Unicode string, optionally followed by additional binary data. + + @retval EFI_INVALID_PARAMETER ImageHandle is either an invalid image handle or the image + has already been initialized with StartImage + @retval Exit code from image Exit code from image + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_START) ( + IN EFI_HANDLE ImageHandle, + OUT UINTN *ExitDataSize, + OUT CHAR16 **ExitData OPTIONAL + ); + +/** + Terminates a loaded EFI image and returns control to boot services. + + @param ImageHandle Handle that identifies the image. + @param ExitStatus The image¡¯s exit code. + @param ExitDataSize The size, in bytes, of ExitData. + @param ExitData Pointer to a data buffer that includes a Null-terminated Unicode string, + optionally followed by additional binary data. + + @retval EFI_SUCCESS The image specified by ImageHandle was unloaded. + @retval EFI_INVALID_PARAMETER The image specified by ImageHandle has been loaded and + started with LoadImage() and StartImage(), but the + image is not the currently executing image. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXIT) ( + IN EFI_HANDLE ImageHandle, + IN EFI_STATUS ExitStatus, + IN UINTN ExitDataSize, + IN CHAR16 *ExitData OPTIONAL + ); + +/** + Unloads an image. + + @param ImageHandle Handle that identifies the image to be unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. + @retval EFI_UNSUPPORTED The image has been started, and does not support unload. + @retval Exit code from the image's unload handler + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_IMAGE_UNLOAD) ( + IN EFI_HANDLE ImageHandle + ); + +/** + Terminates all boot services. + + @param ImageHandle Handle that identifies the exiting image. + @param MapKey Key to the latest memory map. + + @retval EFI_SUCCESS Boot services have been terminated. + @retval EFI_INVALID_PARAMETER MapKey is incorrect. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXIT_BOOT_SERVICES) ( + IN EFI_HANDLE ImageHandle, + IN UINTN MapKey + ); + +/** + Induces a fine-grained stall. + + @param Microseconds The number of microseconds to stall execution. + + @retval EFI_SUCCESS Execution was stalled at least the requested number of + Microseconds. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_STALL) ( + IN UINTN Microseconds + ); + +/** + Sets the system¡¯s watchdog timer. + + @param Timeout The number of seconds to set the watchdog timer to. + @param WatchdogCode The numeric code to log on a watchdog timer timeout event. + @param DataSize The size, in bytes, of WatchdogData. + @param WatchdogData A data buffer that includes a Null-terminated Unicode string, optionally + followed by additional binary data. + + @retval EFI_SUCCESS The timeout has been set. + @retval EFI_INVALID_PARAMETER The supplied WatchdogCode is invalid. + @retval EFI_UNSUPPORTED The system does not have a watchdog timer. + @retval EFI_DEVICE_ERROR The watch dog timer could not be programmed due to a hardware + error. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_SET_WATCHDOG_TIMER) ( + IN UINTN Timeout, + IN UINT64 WatchdogCode, + IN UINTN DataSize, + IN CHAR16 *WatchdogData OPTIONAL + ); + +typedef enum { + EfiResetCold, + EfiResetWarm, + EfiResetShutdown, +#if ((EDK_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000)) + // + // Tiano extension for capsules that was removed after UEFI 2.0 came out + // + EfiResetUpdate +#endif +} EFI_RESET_TYPE; + +/** + Resets the entire platform. + + @param ResetType The type of reset to perform. + @param ResetStatus The status code for the reset. + @param DataSize The size, in bytes, of WatchdogData. + @param ResetData For a ResetType of EfiResetCold, EfiResetWarm, or + EfiResetShutdown the data buffer starts with a Null-terminated + Unicode string, optionally followed by additional binary data. + +**/ +typedef +VOID +(EFIAPI *EFI_RESET_SYSTEM) ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN CHAR16 *ResetData OPTIONAL + ); + +/** + Returns a monotonically increasing count for the platform. + + @param Count Pointer to returned value. + + @retval EFI_SUCCESS The next monotonic count was returned. + @retval EFI_INVALID_PARAMETER Count is NULL. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_MONOTONIC_COUNT) ( + OUT UINT64 *Count + ); + +/** + Returns the next high 32 bits of the platform¡¯s monotonic counter. + + @param HighCount Pointer to returned value. + + @retval EFI_SUCCESS The next high monotonic count was returned. + @retval EFI_INVALID_PARAMETER HighCount is NULL. + @retval EFI_DEVICE_ERROR The device is not functioning properly. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GET_NEXT_HIGH_MONO_COUNT) ( + OUT UINT32 *HighCount + ); + +/** + Computes and returns a 32-bit CRC for a data buffer. + + @param Data A pointer to the buffer on which the 32-bit CRC is to be computed. + @param DataSize The number of bytes in the buffer Data. + @param Crc32 The 32-bit CRC that was computed for the data buffer specified by Data + and DataSize. + + @retval EFI_SUCCESS The 32-bit CRC was computed for the data buffer and returned in + Crc32. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CALCULATE_CRC32) ( + IN VOID *Data, + IN UINTN DataSize, + OUT UINT32 *Crc32 + ); + +/** + Copies the contents of one buffer to another buffer. + + @param Destination Pointer to the destination buffer of the memory copy. + @param Source Pointer to the source buffer of the memory copy. + @param Length Number of bytes to copy from Source to Destination. + +**/ +typedef +VOID +(EFIAPI *EFI_COPY_MEM) ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +/** + The SetMem() function fills a buffer with a specified value. + + @param Buffer Pointer to the buffer to fill. + @param Size Number of bytes in Buffer to fill. + @param Value Value to fill Buffer with. + +**/ +typedef +VOID +(EFIAPI *EFI_SET_MEM) ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ); + +// +// Protocol handler functions +// +typedef enum { + EFI_NATIVE_INTERFACE +} EFI_INTERFACE_TYPE; + +/** + Installs a protocol interface on a device handle. If the handle does not exist, it is created and added + to the list of handles in the system. InstallMultipleProtocolInterfaces() performs + more error checking than InstallProtocolInterface(), so it is recommended that + InstallMultipleProtocolInterfaces() be used in place of + InstallProtocolInterface() + + @param Handle A pointer to the EFI_HANDLE on which the interface is to be installed. + @param Protocol The numeric ID of the protocol interface. + @param InterfaceType Indicates whether Interface is supplied in native form. + @param Interface A pointer to the protocol interface. + + @retval EFI_SUCCESS The protocol interface was installed. + @retval EFI_OUT_OF_RESOURCES Space for a new handle could not be allocated. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_PROTOCOL_INTERFACE) ( + IN OUT EFI_HANDLE *Handle, + IN EFI_GUID *Protocol, + IN EFI_INTERFACE_TYPE InterfaceType, + IN VOID *Interface + ); + +/** + Installs one or more protocol interfaces into the boot services environment. + + @param Handle The handle to install the new protocol interfaces on, or NULL if a new + handle is to be allocated. + @param ... A variable argument list containing pairs of protocol GUIDs and protocol + interfaces. + + @retval EFI_SUCCESS All the protocol interface was installed. + @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols. + @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in + the handle database. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES) ( + IN OUT EFI_HANDLE *Handle, + ... + ); + +/** + Reinstalls a protocol interface on a device handle. + + @param Handle Handle on which the interface is to be reinstalled. + @param Protocol The numeric ID of the interface. + @param OldInterface A pointer to the old interface. NULL can be used if a structure is not + associated with Protocol. + @param NewInterface A pointer to the new interface. + + @retval EFI_SUCCESS The protocol interface was reinstalled. + @retval EFI_NOT_FOUND The OldInterface on the handle was not found. + @retval EFI_ACCESS_DENIED The protocol interface could not be reinstalled, + because OldInterface is still being used by a + driver that will not release it. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REINSTALL_PROTOCOL_INTERFACE) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN VOID *OldInterface, + IN VOID *NewInterface + ); + +/** + Removes a protocol interface from a device handle. It is recommended that + UninstallMultipleProtocolInterfaces() be used in place of + UninstallProtocolInterface(). + + @param Handle The handle on which the interface was installed. + @param Protocol The numeric ID of the interface. + @param Interface A pointer to the interface. + + @retval EFI_SUCCESS The interface was removed. + @retval EFI_NOT_FOUND The interface was not found. + @retval EFI_ACCESS_DENIED The interface was not removed because the interface + is still being used by a driver. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UNINSTALL_PROTOCOL_INTERFACE) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN VOID *Interface + ); + +/** + Removes one or more protocol interfaces into the boot services environment. + + @param Handle The handle to remove the protocol interfaces from. + @param ... A variable argument list containing pairs of protocol GUIDs and + protocol interfaces. + + @retval EFI_SUCCESS All the protocol interfaces were removed. + @retval EFI_INVALID_PARAMETER One of the protocol interfaces was not previously installed on Handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES) ( + IN EFI_HANDLE Handle, + ... + ); + +/** + Queries a handle to determine if it supports a specified protocol. + + @param Handle The handle being queried. + @param Protocol The published unique identifier of the protocol. + @param Interface Supplies the address where a pointer to the corresponding Protocol + Interface is returned. + @retval EFI_SUCCESS The interface information for the specified protocol was returned. + @retval EFI_UNSUPPORTED The device does not support the specified protocol. + @retval EFI_INVALID_PARAMETER One of the protocol interfaces was not previously installed on Handle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HANDLE_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT VOID **Interface + ); + +#define EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 +#define EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 +#define EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 +#define EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 +#define EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 +#define EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 + +/** + Queries a handle to determine if it supports a specified protocol. If the protocol is supported by the + handle, it opens the protocol on behalf of the calling agent. + + @param Handle The handle for the protocol interface that is being opened. + @param Protocol The published unique identifier of the protocol. + @param Interface Supplies the address where a pointer to the corresponding Protocol + Interface is returned. + @param AgentHandle The handle of the agent that is opening the protocol interface + specified by Protocol and Interface. + @param ControllerHandle If the agent that is opening a protocol is a driver that follows the + UEFI Driver Model, then this parameter is the controller handle + that requires the protocol interface. If the agent does not follow + the UEFI Driver Model, then this parameter is optional and may + be NULL. + @param Attributes The open mode of the protocol interface specified by Handle + and Protocol. + + @retval EFI_SUCCESS An item was added to the open list for the protocol interface, and the + protocol interface was returned in Interface. + @retval EFI_UNSUPPORTED Handle does not support Protocol. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_ACCESS_DENIED Required attributes can't be supported in current environment. + @retval EFI_ALREADY_STARTED Item on the open list already has requierd attributes whose agent + handle is the same as AgentHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + OUT VOID **Interface, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle, OPTIONAL + IN UINT32 Attributes + ); + + +/** + Closes a protocol on a handle that was opened using OpenProtocol(). + + @param Handle The handle for the protocol interface that was previously opened + with OpenProtocol(), and is now being closed. + @param Protocol The published unique identifier of the protocol. + @param Interface Supplies the address where a pointer to the corresponding Protocol + Interface is returned. + @param AgentHandle The handle of the agent that is closing the protocol interface. + @param ControllerHandle If the agent that opened a protocol is a driver that follows the + UEFI Driver Model, then this parameter is the controller handle + that required the protocol interface. + + @retval EFI_SUCCESS The protocol instance was closed. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + @retval EFI_NOT_FOUND 1) Handle does not support the protocol specified by Protocol. + 2) The protocol interface specified by Handle and Protocol is not + currently open by AgentHandle and ControllerHandle. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_CLOSE_PROTOCOL) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN EFI_HANDLE AgentHandle, + IN EFI_HANDLE ControllerHandle + ); + +typedef struct { + EFI_HANDLE AgentHandle; + EFI_HANDLE ControllerHandle; + UINT32 Attributes; + UINT32 OpenCount; +} EFI_OPEN_PROTOCOL_INFORMATION_ENTRY; + +/** + Retrieves the list of agents that currently have a protocol interface opened. + + @param Handle The handle for the protocol interface that is being queried. + @param Protocol The published unique identifier of the protocol. + @param EntryBuffer A pointer to a buffer of open protocol information in the form of + EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures. + @param EntryCount A pointer to the number of entries in EntryBuffer. + + @retval EFI_SUCCESS The open protocol information was returned in EntryBuffer, and the + number of entries was returned EntryCount. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to allocate EntryBuffer. + @retval EFI_NOT_FOUND Handle does not support the protocol specified by Protocol. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_OPEN_PROTOCOL_INFORMATION) ( + IN EFI_HANDLE Handle, + IN EFI_GUID *Protocol, + IN EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + OUT UINTN *EntryCount + ); + +/** + Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated + from pool. + + @param Handle The handle from which to retrieve the list of protocol interface + GUIDs. + @param ProtocolBuffer A pointer to the list of protocol interface GUID pointers that are + installed on Handle. + @param ProtocolBufferCount A pointer to the number of GUID pointers present in + ProtocolBuffer. + + @retval EFI_SUCCESS The list of protocol interface GUIDs installed on Handle was returned in + ProtocolBuffer. The number of protocol interface GUIDs was + returned in ProtocolBufferCount. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the results. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_PROTOCOLS_PER_HANDLE) ( + IN EFI_HANDLE Handle, + OUT EFI_GUID ***ProtocolBuffer, + OUT UINTN *ProtocolBufferCount + ); + +/** + Creates an event that is to be signaled whenever an interface is installed for a specified protocol. + + @param Protocol The numeric ID of the protocol for which the event is to be registered. + @param Event Event that is to be signaled whenever a protocol interface is registered + for Protocol. + @param Registration A pointer to a memory location to receive the registration value. + + @retval EFI_SUCCESS The notification event has been registered. + @retval EFI_OUT_OF_RESOURCES Space for the notification event could not be allocated. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_REGISTER_PROTOCOL_NOTIFY) ( + IN EFI_GUID *Protocol, + IN EFI_EVENT Event, + OUT VOID **Registration + ); + +typedef enum { + AllHandles, + ByRegisterNotify, + ByProtocol +} EFI_LOCATE_SEARCH_TYPE; + +/** + Returns an array of handles that support a specified protocol. + + @param SearchType Specifies which handle(s) are to be returned. + @param Protocol Specifies the protocol to search by. + @param SearchKey Specifies the search key. + @param BufferSize On input, the size in bytes of Buffer. On output, the size in bytes of + the array returned in Buffer (if the buffer was large enough) or the + size, in bytes, of the buffer needed to obtain the array (if the buffer was + not large enough). + @param Buffer The buffer in which the array is returned. + + @retval EFI_SUCCESS The array of handles was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_HANDLE) ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + IN OUT UINTN *BufferSize, + OUT EFI_HANDLE *Buffer + ); + +/** + Locates the handle to a device on the device path that supports the specified protocol. + + @param Protocol Specifies the protocol to search for. + @param DevicePath On input, a pointer to a pointer to the device path. On output, the device + path pointer is modified to point to the remaining part of the device + path. + @param Device A pointer to the returned device handle. + + @retval EFI_SUCCESS The resulting handle was returned. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_DEVICE_PATH) ( + IN EFI_GUID *Protocol, + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT EFI_HANDLE *Device + ); + +/** + Adds, updates, or removes a configuration table entry from the EFI System Table. + + @param Guid A pointer to the GUID for the entry to add, update, or remove. + @param Table A pointer to the configuration table for the entry to add, update, or + remove. May be NULL. + + @retval EFI_SUCCESS The (Guid, Table) pair was added, updated, or removed. + @retval EFI_NOT_FOUND An attempt was made to delete a nonexistent entry. + @retval EFI_INVALID_PARAMETER Guid is not valid. + @retval EFI_OUT_OF_RESOURCES There is not enough memory available to complete the operation. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_INSTALL_CONFIGURATION_TABLE) ( + IN EFI_GUID *Guid, + IN VOID *Table + ); + +/** + Reserved service. + + @retval EFI_SUCCESS The operation has been completed successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_RESERVED_SERVICE) ( + VOID + ); + +/** + Returns an array of handles that support the requested protocol in a buffer allocated from pool. + + @param SearchType Specifies which handle(s) are to be returned. + @param Protocol Specifies the protocol to search by. + @param SearchKey Supplies the search key depending on the SearchType. + @param NoHandles The number of handles returned in Buffer. + @param Buffer A pointer to the buffer to return the requested array of handles that + support Protocol. + + @retval EFI_SUCCESS The array of handles was returned in Buffer, and the number of + handles in Buffer was returned in NoHandles. + @retval EFI_NOT_FOUND No handles match the search. + @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the matching results. + @retval EFI_INVALID_PARAMETER One or more parameters are invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_HANDLE_BUFFER) ( + IN EFI_LOCATE_SEARCH_TYPE SearchType, + IN EFI_GUID *Protocol, OPTIONAL + IN VOID *SearchKey, OPTIONAL + IN OUT UINTN *NoHandles, + OUT EFI_HANDLE **Buffer + ); + +/** + Returns the first protocol instance that matches the given protocol. + + @param Protocol Provides the protocol to search for. + @param Registration Optional registration key returned from + RegisterProtocolNotify(). + @param Interface On return, a pointer to the first interface that matches Protocol and + Registration. + + @retval EFI_SUCCESS A protocol instance matching Protocol was found and returned in + Interface. + @retval EFI_NOT_FOUND No protocol instances were found that match Protocol and + Registration. + @retval EFI_INVALID_PARAMETER Interface is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_LOCATE_PROTOCOL) ( + IN EFI_GUID *Protocol, + IN VOID *Registration, OPTIONAL + OUT VOID **Interface + ); + + +typedef struct { + UINT64 Length; + union { + EFI_PHYSICAL_ADDRESS DataBlock; + EFI_PHYSICAL_ADDRESS ContinuationPointer; + } Union; +} UEFI_CAPSULE_BLOCK_DESCRIPTOR; + +typedef struct { + EFI_GUID CapsuleGuid; + UINT32 HeaderSize; + UINT32 Flags; + UINT32 CapsuleImageSize; +} UEFI_CAPSULE_HEADER; + +#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000 +#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 + +/** + Passes capsules to the firmware with both virtual and physical mapping. Depending on the intended + consumption, the firmware may process the capsule immediately. If the payload should persist + across a system reset, the reset value returned from EFI_QueryCapsuleCapabilities must + be passed into ResetSystem() and will cause the capsule to be processed by the firmware as + part of the reset process. + + @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules + being passed into update capsule. + @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in + CaspuleHeaderArray. + @param ScatterGatherList Physical pointer to a set of + EFI_CAPSULE_BLOCK_DESCRIPTOR that describes the + location in physical memory of a set of capsules. + + @retval EFI_SUCCESS Valid capsule was passed. If + CAPSULE_FLAGS_PERSIT_ACROSS_RESET is not set, the + capsule has been successfully processed by the firmware. + @retval EFI_DEVICE_ERROR The capsule update was started, but failed due to a device error. + @retval EFI_INVALID_PARAMETER CapsuleSize is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UPDATE_CAPSULE) ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + IN EFI_PHYSICAL_ADDRESS ScatterGatherList OPTIONAL + ); + +/** + Returns if the capsule can be supported via UpdateCapsule(). + + @param CapsuleHeaderArray Virtual pointer to an array of virtual pointers to the capsules + being passed into update capsule. + @param CapsuleCount Number of pointers to EFI_CAPSULE_HEADER in + CaspuleHeaderArray. + @param MaxiumCapsuleSize On output the maximum size that UpdateCapsule() can + support as an argument to UpdateCapsule() via + CapsuleHeaderArray and ScatterGatherList. + @param ResetType Returns the type of reset required for the capsule update. + + @retval EFI_SUCCESS Valid answer returned. + @retval EFI_UNSUPPORTED The capsule type is not supported on this platform, and + MaximumCapsuleSize and ResetType are undefined. + @retval EFI_INVALID_PARAMETER MaximumCapsuleSize is NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_QUERY_CAPSULE_CAPABILITIES) ( + IN UEFI_CAPSULE_HEADER **CapsuleHeaderArray, + IN UINTN CapsuleCount, + OUT UINT64 *MaximumCapsuleSize, + OUT EFI_RESET_TYPE *ResetType + ); + +/** + Returns information about the EFI variables. + + @param Attributes Attributes bitmask to specify the type of variables on + which to return information. + @param MaximumVariableStorageSize On output the maximum size of the storage space + available for the EFI variables associated with the + attributes specified. + @param RemainingVariableStorageSize Returns the remaining size of the storage space + available for the EFI variables associated with the + attributes specified. + @param MaximumVariableSize Returns the maximum size of the individual EFI + variables associated with the attributes specified. + + @retval EFI_SUCCESS Valid answer returned. + @retval EFI_INVALID_PARAMETER An invalid combination of attribute bits was supplied + @retval EFI_UNSUPPORTED The attribute is not supported on this platform, and the + MaximumVariableStorageSize, + RemainingVariableStorageSize, MaximumVariableSize + are undefined. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_QUERY_VARIABLE_INFO) ( + IN UINT32 Attributes, + OUT UINT64 *MaximumVariableStorageSize, + OUT UINT64 *RemainingVariableStorageSize, + OUT UINT64 *MaximumVariableSize + ); + + +// +// EFI Runtime Services Table +// +#define EFI_1_02_SYSTEM_TABLE_REVISION ((1 << 16) | 02) +#define EFI_1_10_SYSTEM_TABLE_REVISION ((1 << 16) | 10) +#define EFI_2_00_SYSTEM_TABLE_REVISION ((2 << 16) | 0) + +#define EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552ULL +#define EFI_RUNTIME_SERVICES_REVISION (EFI_2_00_SYSTEM_TABLE_REVISION) + +#if (EDK_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000) +// +// Include the definition for TIANO_REPORT_STATUS_CODE if this is the version +// of Tiano that extended the EFI specification. If Tiano mode is diabled +// don't include it. +// +#include +#endif + + +typedef struct { + EFI_TABLE_HEADER Hdr; + + // + // Time services + // + EFI_GET_TIME GetTime; + EFI_SET_TIME SetTime; + EFI_GET_WAKEUP_TIME GetWakeupTime; + EFI_SET_WAKEUP_TIME SetWakeupTime; + + // + // Virtual memory services + // + EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap; + EFI_CONVERT_POINTER ConvertPointer; + + // + // Variable services + // + EFI_GET_VARIABLE GetVariable; + EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName; + EFI_SET_VARIABLE SetVariable; + + // + // Misc + // + EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount; + EFI_RESET_SYSTEM ResetSystem; + +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + // + // New Boot Services added by UEFI 2.0 + // + EFI_UPDATE_CAPSULE UpdateCapsule; + EFI_QUERY_CAPSULE_CAPABILITIES QueryCapsuleCapabilities; + EFI_QUERY_VARIABLE_INFO QueryVariableInfo; +#elif (EDK_RELEASE_VERSION != 0) + // + // Tiano extension to EFI 1.10 runtime table + // It was moved to a protocol to not conflict with UEFI 2.0 + // If Tiano is disabled this item is not enabled for EFI 1.10 + // + TIANO_REPORT_STATUS_CODE ReportStatusCode; +#endif +} EFI_RUNTIME_SERVICES; + +// +// EFI Boot Services Table +// +#define EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42ULL +#define EFI_BOOT_SERVICES_REVISION (EFI_2_00_SYSTEM_TABLE_REVISION) + +typedef struct { + EFI_TABLE_HEADER Hdr; + + // + // Task priority functions + // + EFI_RAISE_TPL RaiseTPL; + EFI_RESTORE_TPL RestoreTPL; + + // + // Memory functions + // + EFI_ALLOCATE_PAGES AllocatePages; + EFI_FREE_PAGES FreePages; + EFI_GET_MEMORY_MAP GetMemoryMap; + EFI_ALLOCATE_POOL AllocatePool; + EFI_FREE_POOL FreePool; + + // + // Event & timer functions + // + EFI_CREATE_EVENT CreateEvent; + EFI_SET_TIMER SetTimer; + EFI_WAIT_FOR_EVENT WaitForEvent; + EFI_SIGNAL_EVENT SignalEvent; + EFI_CLOSE_EVENT CloseEvent; + EFI_CHECK_EVENT CheckEvent; + + // + // Protocol handler functions + // + EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; + EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; + EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; + EFI_HANDLE_PROTOCOL HandleProtocol; + VOID *Reserved; + EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; + EFI_LOCATE_HANDLE LocateHandle; + EFI_LOCATE_DEVICE_PATH LocateDevicePath; + EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; + + // + // Image functions + // + EFI_IMAGE_LOAD LoadImage; + EFI_IMAGE_START StartImage; + EFI_EXIT Exit; + EFI_IMAGE_UNLOAD UnloadImage; + EFI_EXIT_BOOT_SERVICES ExitBootServices; + + // + // Misc functions + // + EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; + EFI_STALL Stall; + EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; + + // + // //////////////////////////////////////////////////// + // EFI 1.1 Services + ////////////////////////////////////////////////////// + // + // DriverSupport Services + // + EFI_CONNECT_CONTROLLER ConnectController; + EFI_DISCONNECT_CONTROLLER DisconnectController; + + // + // Added Open and Close protocol for the new driver model + // + EFI_OPEN_PROTOCOL OpenProtocol; + EFI_CLOSE_PROTOCOL CloseProtocol; + EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation; + + // + // Added new services to EFI 1.1 as Lib to reduce code size. + // + EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle; + EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer; + EFI_LOCATE_PROTOCOL LocateProtocol; + + EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces; + EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces; + + // + // CRC32 services + // + EFI_CALCULATE_CRC32 CalculateCrc32; + + // + // Memory Utility Services + // + EFI_COPY_MEM CopyMem; + EFI_SET_MEM SetMem; + +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) + // + // UEFI 2.0 Extension to the table + // + EFI_CREATE_EVENT_EX CreateEventEx; +#endif +} EFI_BOOT_SERVICES; + +// +// EFI Configuration Table +// +typedef struct { + EFI_GUID VendorGuid; + VOID *VendorTable; +} EFI_CONFIGURATION_TABLE; + +// +// EFI System Table +// +#define EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249ULL +#define EFI_SYSTEM_TABLE_REVISION (EFI_2_00_SYSTEM_TABLE_REVISION) + +struct _EFI_SYSTEM_TABLE { + EFI_TABLE_HEADER Hdr; + + CHAR16 *FirmwareVendor; + UINT32 FirmwareRevision; + + EFI_HANDLE ConsoleInHandle; + EFI_SIMPLE_TEXT_IN_PROTOCOL *ConIn; + + EFI_HANDLE ConsoleOutHandle; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *ConOut; + + EFI_HANDLE StandardErrorHandle; + EFI_SIMPLE_TEXT_OUT_PROTOCOL *StdErr; + + EFI_RUNTIME_SERVICES *RuntimeServices; + EFI_BOOT_SERVICES *BootServices; + + UINTN NumberOfTableEntries; + EFI_CONFIGURATION_TABLE *ConfigurationTable; + +}; + +// +// Device Path information +// + +#pragma pack(1) + +// +// Hardware Device Paths +// +#define HARDWARE_DEVICE_PATH 0x01 + +#define HW_PCI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 Function; + UINT8 Device; +} PCI_DEVICE_PATH; + +#define HW_PCCARD_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 FunctionNumber; +} PCCARD_DEVICE_PATH; + +#define HW_MEMMAP_DP 0x03 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 MemoryType; + EFI_PHYSICAL_ADDRESS StartingAddress; + EFI_PHYSICAL_ADDRESS EndingAddress; +} MEMMAP_DEVICE_PATH; + +#define HW_VENDOR_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; +} VENDOR_DEVICE_PATH; + +#define HW_CONTROLLER_DP 0x05 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; +#if EDK_RELEASE_VERSION >= 0x00020000 + UINT32 ControllerNumber; +#else + UINT32 Controller; +#endif +} CONTROLLER_DEVICE_PATH; + +// +// ACPI Device Paths +// +#define ACPI_DEVICE_PATH 0x02 + +#define ACPI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 HID; + UINT32 UID; +} ACPI_HID_DEVICE_PATH; + +#define ACPI_EXTENDED_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 HID; + UINT32 UID; + UINT32 CID; + // + // Optional variable length _HIDSTR + // Optional variable length _UIDSTR + // +} ACPI_EXTENDED_HID_DEVICE_PATH; + +// +// EISA ID Macro +// EISA ID Definition 32-bits +// bits[15:0] - three character compressed ASCII EISA ID. +// bits[31:16] - binary number +// Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z' +// +#define PNP_EISA_ID_CONST 0x41d0 +#define EISA_ID(_Name, _Num) ((UINT32) ((_Name) | (_Num) << 16)) +#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) +#define EFI_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) + +#define PNP_EISA_ID_MASK 0xffff +#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16) + + +#define ACPI_ADR_DP 0x03 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 ADR; +} ACPI_ADR_DEVICE_PATH; + + +// +// Messaging Device Paths +// +#define MESSAGING_DEVICE_PATH 0x03 + +#define MSG_ATAPI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 PrimarySecondary; + UINT8 SlaveMaster; + UINT16 Lun; +} ATAPI_DEVICE_PATH; + +#define MSG_SCSI_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 Pun; + UINT16 Lun; +} SCSI_DEVICE_PATH; + +#define MSG_FIBRECHANNEL_DP 0x03 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 WWN; + UINT64 Lun; +} FIBRECHANNEL_DEVICE_PATH; + +#define MSG_1394_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 Guid; +} F1394_DEVICE_PATH; + +#define MSG_USB_DP 0x05 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 ParentPortNumber; + UINT8 InterfaceNumber; +} USB_DEVICE_PATH; + +#define MSG_USB_CLASS_DP 0x0f +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 VendorId; + UINT16 ProductId; + UINT8 DeviceClass; + UINT8 DeviceSubClass; + UINT8 DeviceProtocol; +} USB_CLASS_DEVICE_PATH; + +#define MSG_USB_WWID_DP 0x10 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 InterfaceNumber; + UINT16 VendorId; + UINT16 ProductId; + // CHAR16 SerialNumber[]; +} USB_WWID_DEVICE_PATH; + +#define MSG_DEVICE_LOGICAL_UNIT_DP 0x11 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 LUN; +} DEVICE_LOGICAL_UNIT_DEVICE_PATH; + +#define MSG_I2O_DP 0x06 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Tid; +} I2O_DEVICE_PATH; + +#define MSG_MAC_ADDR_DP 0x0b +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_MAC_ADDRESS MacAddress; + UINT8 IfType; +} MAC_ADDR_DEVICE_PATH; + +#define MSG_IPv4_DP 0x0c +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_IPv4_ADDRESS LocalIpAddress; + EFI_IPv4_ADDRESS RemoteIpAddress; + UINT16 LocalPort; + UINT16 RemotePort; + UINT16 Protocol; + BOOLEAN StaticIpAddress; +} IPv4_DEVICE_PATH; + +#define MSG_IPv6_DP 0x0d +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_IPv6_ADDRESS LocalIpAddress; + EFI_IPv6_ADDRESS RemoteIpAddress; + UINT16 LocalPort; + UINT16 RemotePort; + UINT16 Protocol; + BOOLEAN StaticIpAddress; +} IPv6_DEVICE_PATH; + +#define MSG_INFINIBAND_DP 0x09 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 ResourceFlags; + UINT8 PortGid[16]; + UINT64 ServiceId; + UINT64 TargetPortId; + UINT64 DeviceId; +} INFINIBAND_DEVICE_PATH; + +#define INFINIBAND_RESOURCE_FLAG_IOC_SERVICE 0x01 +#define INFINIBAND_RESOURCE_FLAG_EXTENDED_BOOT_ENVIRONMENT 0x02 +#define INFINIBAND_RESOURCE_FLAG_CONSOLE_PROTOCOL 0x04 +#define INFINIBAND_RESOURCE_FLAG_STORAGE_PROTOCOL 0x08 +#define INFINIBAND_RESOURCE_FLAG_NETWORK_PROTOCOL 0x10 + +#define MSG_UART_DP 0x0e +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 BaudRate; + UINT8 DataBits; + UINT8 Parity; + UINT8 StopBits; +} UART_DEVICE_PATH; + +// +// Use VENDOR_DEVICE_PATH struct +// +#define MSG_VENDOR_DP 0x0a + +#define DEVICE_PATH_MESSAGING_PC_ANSI EFI_PC_ANSI_GUID +#define DEVICE_PATH_MESSAGING_VT_100 EFI_VT_100_GUID +#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID +#define DEVICE_PATH_MESSAGING_VT_UTF8 EFI_VT_UTF8_GUID +#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID + + +#define MSG_ISCSI_DP 0x13 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 NetworkProtocol; + UINT16 LoginOption; + UINT16 Reserved; + UINT16 TargetPortalGroupTag; + UINT64 LUN; + // CHAR8 iSCSI Target Name +} ISCSI_DEVICE_PATH; + +#define ISCSI_LOGIN_OPTION_NO_HEADER_DIGEST 0x0000 +#define ISCSI_LOGIN_OPTION_HEADER_DIGEST_USING_CRC32C 0x0002 +#define ISCSI_LOGIN_OPTION_NO_DATA_DIGEST 0x0000 +#define ISCSI_LOGIN_OPTION_DATA_DIGEST_USING_CRC32C 0x0008 +#define ISCSI_LOGIN_OPTION_AUTHMETHOD_CHAP 0x0000 +#define ISCSI_LOGIN_OPTION_AUTHMETHOD_NON 0x1000 +#define ISCSI_LOGIN_OPTION_CHAP_BI 0x0000 +#define ISCSI_LOGIN_OPTION_CHAP_UNI 0x2000 + + +// +// Media Device Path +// +#define MEDIA_DEVICE_PATH 0x04 + +#define MEDIA_HARDDRIVE_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 PartitionNumber; + UINT64 PartitionStart; + UINT64 PartitionSize; + UINT8 Signature[16]; + UINT8 MBRType; + UINT8 SignatureType; +} HARDDRIVE_DEVICE_PATH; + +#define MBR_TYPE_PCAT 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +#define SIGNATURE_TYPE_MBR 0x01 +#define SIGNATURE_TYPE_GUID 0x02 + +#define MEDIA_CDROM_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 BootEntry; + UINT64 PartitionStart; + UINT64 PartitionSize; +} CDROM_DEVICE_PATH; + +// +// Use VENDOR_DEVICE_PATH struct +// +#define MEDIA_VENDOR_DP 0x03 + +#define MEDIA_FILEPATH_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + CHAR16 PathName[1]; +} FILEPATH_DEVICE_PATH; + +#define SIZE_OF_FILEPATH_DEVICE_PATH EFI_FIELD_OFFSET(FILEPATH_DEVICE_PATH,PathName) + +#define MEDIA_PROTOCOL_DP 0x05 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Protocol; +} MEDIA_PROTOCOL_DEVICE_PATH; + +#if ((EDK_RELEASE_VERSION != 0) && (EFI_SPECIFICATION_VERSION < 0x00020000)) +// +// Prior to UEFI 2.0 Tiano extended this enum. UEFI owns device path values +// and we moved to a new GUID'ed device path for Tiano +// + +#define MEDIA_FV_FILEPATH_DP 0x06 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID NameGuid; +} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH; + +#else + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID PiwgSpecificDevicePath; + UINT32 Type; +} PIWG_DEVICE_PATH; + +#define PIWG_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH_TYPE 0x01 +typedef struct { + PIWG_DEVICE_PATH Piwg; + EFI_GUID NameGuid; +} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH; + +// +// Place holder for a future extension +// +#define PIWG_MEDIAFW_VOL_DEVICE_PATH_TYPE 0x02 +typedef struct { + PIWG_DEVICE_PATH Piwg; + EFI_GUID VolumeGuid; +} MEDIA_FW_VOL_DEVICE_PATH; + +#endif + + +// +// BBS Device Path +// +#define BBS_DEVICE_PATH 0x05 +#define BBS_BBS_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 DeviceType; + UINT16 StatusFlag; + CHAR8 String[1]; +} BBS_BBS_DEVICE_PATH; + +// +// DeviceType definitions - from BBS specification +// +#define BBS_TYPE_FLOPPY 0x01 +#define BBS_TYPE_HARDDRIVE 0x02 +#define BBS_TYPE_CDROM 0x03 +#define BBS_TYPE_PCMCIA 0x04 +#define BBS_TYPE_USB 0x05 +#define BBS_TYPE_EMBEDDED_NETWORK 0x06 +#define BBS_TYPE_BEV 0x80 +#define BBS_TYPE_UNKNOWN 0xFF + + +// +// Union of all possible Device Paths and pointers to Device Paths +// + +typedef union { + EFI_DEVICE_PATH_PROTOCOL DevPath; + PCI_DEVICE_PATH Pci; + PCCARD_DEVICE_PATH PcCard; + MEMMAP_DEVICE_PATH MemMap; + VENDOR_DEVICE_PATH Vendor; + + CONTROLLER_DEVICE_PATH Controller; + ACPI_HID_DEVICE_PATH Acpi; + + ATAPI_DEVICE_PATH Atapi; + SCSI_DEVICE_PATH Scsi; + FIBRECHANNEL_DEVICE_PATH FibreChannel; + + F1394_DEVICE_PATH F1394; + USB_DEVICE_PATH Usb; + USB_CLASS_DEVICE_PATH UsbClass; + I2O_DEVICE_PATH I2O; + MAC_ADDR_DEVICE_PATH MacAddr; + IPv4_DEVICE_PATH Ipv4; + IPv6_DEVICE_PATH Ipv6; + INFINIBAND_DEVICE_PATH InfiniBand; + UART_DEVICE_PATH Uart; + + HARDDRIVE_DEVICE_PATH HardDrive; + CDROM_DEVICE_PATH CD; + + FILEPATH_DEVICE_PATH FilePath; + MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; + + BBS_BBS_DEVICE_PATH Bbs; +} EFI_DEV_PATH; + + + +typedef union { + EFI_DEVICE_PATH_PROTOCOL *DevPath; + PCI_DEVICE_PATH *Pci; + PCCARD_DEVICE_PATH *PcCard; + MEMMAP_DEVICE_PATH *MemMap; + VENDOR_DEVICE_PATH *Vendor; + + CONTROLLER_DEVICE_PATH *Controller; + ACPI_HID_DEVICE_PATH *Acpi; + ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi; + + ATAPI_DEVICE_PATH *Atapi; + SCSI_DEVICE_PATH *Scsi; + FIBRECHANNEL_DEVICE_PATH *FibreChannel; + + F1394_DEVICE_PATH *F1394; + USB_DEVICE_PATH *Usb; + USB_CLASS_DEVICE_PATH *UsbClass; + I2O_DEVICE_PATH *I2O; + MAC_ADDR_DEVICE_PATH *MacAddr; + IPv4_DEVICE_PATH *Ipv4; + IPv6_DEVICE_PATH *Ipv6; + INFINIBAND_DEVICE_PATH *InfiniBand; + UART_DEVICE_PATH *Uart; + + HARDDRIVE_DEVICE_PATH *HardDrive; + CDROM_DEVICE_PATH *CD; + + FILEPATH_DEVICE_PATH *FilePath; + MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol; + + BBS_BBS_DEVICE_PATH *Bbs; + UINT8 *Raw; +} EFI_DEV_PATH_PTR; + +#pragma pack() + + +// +// PXE Informations +// + +// +// Packet definitions +// +typedef struct { + UINT8 BootpOpcode; + UINT8 BootpHwType; + UINT8 BootpHwAddrLen; + UINT8 BootpGateHops; + UINT32 BootpIdent; + UINT16 BootpSeconds; + UINT16 BootpFlags; + UINT8 BootpCiAddr[4]; + UINT8 BootpYiAddr[4]; + UINT8 BootpSiAddr[4]; + UINT8 BootpGiAddr[4]; + UINT8 BootpHwAddr[16]; + UINT8 BootpSrvName[64]; + UINT8 BootpBootFile[128]; + UINT32 DhcpMagik; + UINT8 DhcpOptions[56]; +} EFI_PXE_BASE_CODE_DHCPV4_PACKET; + +typedef union { + UINT8 Raw[1472]; + EFI_PXE_BASE_CODE_DHCPV4_PACKET Dhcpv4; + + // + // EFI_PXE_BASE_CODE_DHCPV6_PACKET Dhcpv6; + // +} EFI_PXE_BASE_CODE_PACKET; + +#include + +// +// EFI Revision information +// +#define EFI_FIRMWARE_REVISION (EFI_2_00_SYSTEM_TABLE_REVISION) + +#include +#include + + +#define EFI_USB_HC_RESET_GLOBAL 0x0001 +#define EFI_USB_HC_RESET_HOST_CONTROLLER 0x0002 +#define EFI_USB_HC_RESET_GLOBAL_WITH_DEBUG 0x0004 +#define EFI_USB_HC_RESET_HOST_WITH_DEBUG 0x0008 + +// +// USB Host Controller state +// +typedef enum { + EfiUsbHcStateHalt, + EfiUsbHcStateOperational, + EfiUsbHcStateSuspend, + EfiUsbHcStateMaximum +} EFI_USB_HC_STATE; + + +// +// EFI File location to boot from on removable media devices +// +#define EFI_REMOVABLE_MEDIA_FILE_NAME_IA32 L"\\EFI\\BOOT\\BOOTIA32.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_IA64 L"\\EFI\\BOOT\\BOOTIA64.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_X64 L"\\EFI\\BOOT\\BOOTX64.EFI" +#define EFI_REMOVABLE_MEDIA_FILE_NAME_EBC L"\\EFI\\BOOT\\BOOTEBC.EFI" + +#if defined (MDE_CPU_IA32) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_IA32 +#elif defined (MDE_CPU_IPF) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_IA64 +#elif defined (MDE_CPU_X64) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_X64 +#elif defined (MDE_CPU_EBC) + #define EFI_REMOVABLE_MEDIA_FILE_NAME EFI_REMOVABLE_MEDIA_FILE_NAME_EBC +#else + #error Unknown Processor Type +#endif + + +// +// Protocols from EFI 1.10 that got thier names fixed in UEFI 2.0 +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// EFI 1.10 Protocols +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// EFI 1.10 GUIDs +// +#include +#include +#include +#include +#include +#include +#include + + +#if (EFI_SPECIFICATION_VERSION >= 0x00020000) +// +// Turn on UEFI 2.0 Protocols and GUIDs +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +//#include +#endif + + +#endif diff --git a/MdePkg/Include/x64/ProcessorBind.h b/MdePkg/Include/x64/ProcessorBind.h new file mode 100644 index 0000000000..c61966e154 --- /dev/null +++ b/MdePkg/Include/x64/ProcessorBind.h @@ -0,0 +1,193 @@ +/** @file + Processor or Compiler specific defines and types x64 (Intel(r) EM64T, AMD64). + + Copyright (c) 2006, 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. + + Module Name: ProcessorBind.h + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +// +// Define the processor type so other code can make processor based choices +// +#define MDE_CPU_X64 + + +// +// Make sure we are useing the correct packing rules per EFI specification +// +#pragma pack() + + +#if _MSC_EXTENSIONS + +// +// Disable warning that make it impossible to compile at /W4 +// This only works for Microsoft* tools +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning +// +#pragma warning ( disable : 4127 ) + + +#endif + + +#if (__STDC_VERSION__ < 199901L) + // + // No ANSI C 2000 stdint.h integer width declarations, so define equivalents + // + + #if _MSC_EXTENSIONS + + + // + // use Microsoft C complier dependent interger width types + // + typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int32 UINT32; + typedef __int32 INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #else + #ifdef _EFI_P64 + // + // P64 - is Intel Itanium(TM) speak for pointers being 64-bit and longs and ints + // are 32-bits + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short CHAR16; + typedef unsigned short UINT16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #else + // + // Assume LP64 - longs and pointers are 64-bit. Ints are 32-bit. + // + typedef unsigned long UINT64; + typedef long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #endif + #endif + + #define UINT8_MAX 0xff + +#else + // + // Use ANSI C 2000 stdint.h integer width declarations + // + #include + typedef uint8_t BOOLEAN; + typedef int8_t INT8; + typedef uint8_t UINT8; + typedef int16_t INT16; + typedef uint16_t UINT16; + typedef int32_t INT32; + typedef uint32_t UINT32; + typedef int64_t INT64; + typedef uint64_t UINT64; + typedef char CHAR8; + typedef uint16_t CHAR16; + +#endif + +typedef UINT64 UINTN; +typedef INT64 INTN; + + +// +// Processor specific defines +// +#define MAX_BIT 0x8000000000000000 +#define MAX_2_BITS 0xC000000000000000 + +// +// Maximum legal Itanium-based address +// +#define MAX_ADDRESS 0xFFFFFFFFFFFFFFFF + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify thier member functions with EFIAPI. +// +#if _MSC_EXTENSIONS + /// + /// Define the standard calling convention reguardless of optimization level. + /// __cdecl is Microsoft* specific C extension. + /// + #define EFIAPI __cdecl +#elif __GNUC__ + /// + /// Define the standard calling convention reguardless of optimization level. + /// efidecl is an extension to GCC that supports the differnece between x64 + /// GCC ABI and x64 Microsoft* ABI. EFI is closer to the Microsoft* ABI and + /// EFIAPI makes sure the right ABI is used for public interfaces. + /// eficecl is a work in progress and we do not yet have the compiler + /// + #define EFIAPI __attribute__((efidecl)) +#else + #define EFIAPI +#endif + +// +// The Microsoft* C compiler can removed references to unreferenced data items +// if the /OPT:REF linker option is used. We defined a macro as this is a +// a non standard extension +// +#if _MSC_EXTENSIONS + #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany) +#else + #define GLOBAL_REMOVE_IF_UNREFERENCED +#endif + +#endif + diff --git a/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.mbd b/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.mbd new file mode 100644 index 0000000000..a0be253d11 --- /dev/null +++ b/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.mbd @@ -0,0 +1,30 @@ + + + + + BaseCacheMaintenanceLib + 123dd843-57c9-4158-8418-ce68b3944ce7 + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.msa b/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.msa new file mode 100644 index 0000000000..4fd80ab9bd --- /dev/null +++ b/MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.msa @@ -0,0 +1,57 @@ + + + + + BaseCacheMaintenanceLib + BASE + LIBRARY + 123dd843-57c9-4158-8418-ce68b3944ce7 + 0 + Library Dependencies:BaseLib + FIX ME! + Copyright (c) 2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + CacheMaintenanceLib + BaseLib + + + + x86Cache.c + + + x86Cache.c + + + EbcCache.c + + + IpfCache.c + Ipf/Cpu.s + Ipf/CallPalProc.s + + + + MdePkg + + diff --git a/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c b/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c new file mode 100644 index 0000000000..a7e36236c5 --- /dev/null +++ b/MdePkg/Library/BaseCacheMaintenanceLib/EbcCache.c @@ -0,0 +1,85 @@ +/** @file + Cache Maintenance Functions. + + Copyright (c) 2006, 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. + +**/ + +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ +} + +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return Address; +} + +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ +} + +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return Address; +} + +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ +} + +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return Address; +} + +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ +} + +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return Address; +} diff --git a/MdePkg/Library/BaseCacheMaintenanceLib/Ipf/CallPalProc.s b/MdePkg/Library/BaseCacheMaintenanceLib/Ipf/CallPalProc.s new file mode 100644 index 0000000000..18b0f5815a --- /dev/null +++ b/MdePkg/Library/BaseCacheMaintenanceLib/Ipf/CallPalProc.s @@ -0,0 +1,38 @@ +/// @file +/// Contains an implementation of CallPalProcStatic on Itanium-based +/// architecture. +/// +/// Copyright (c) 2006, 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. +/// +/// Module Name: CallPalProc.s +/// +/// + +.auto +.text + +.proc CallPalProcStatic +.type CallPalProcStatic, @function +CallPalProcStatic:: + mov r9 = ar.k5 + mov r8 = ip + add r8 = (PalProcReturn - CallPalProcStatic), r8 + mov r28 = r32 + mov b7 = r9 + mov r29 = r33 + mov r30 = r34 + mov r31 = r35 + mov r32 = b0 + mov b0 = r8 + br.sptk b7 +PalProcReturn: + mov b0 = r32 + br.ret.sptk.many b0 +.endp CallPalProcStatic diff --git a/MdePkg/Library/BaseCacheMaintenanceLib/Ipf/Cpu.s b/MdePkg/Library/BaseCacheMaintenanceLib/Ipf/Cpu.s new file mode 100644 index 0000000000..4f144c683e --- /dev/null +++ b/MdePkg/Library/BaseCacheMaintenanceLib/Ipf/Cpu.s @@ -0,0 +1,106 @@ +//++ +// Copyright (c) 2006, 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. +// +// Module Name: +// +// Cpu.s +// +// Abstract: +// +// +// Revision History: +// +//-- + + .file "Cpu.s" + .radix D + .section .text, "ax", "progbits" + .align 32 + .section .pdata, "a", "progbits" + .align 4 + .section .xdata, "a", "progbits" + .align 8 + .section .data, "wa", "progbits" + .align 16 + .section .rdata, "a", "progbits" + .align 16 + .section .bss, "wa", "nobits" + .align 16 + .section .tls$, "was", "progbits" + .align 16 + .section .sdata, "was", "progbits" + .align 16 + .section .sbss, "was", "nobits" + .align 16 + .section .srdata, "as", "progbits" + .align 16 + .section .rdata, "a", "progbits" + .align 16 + .section .rtcode, "ax", "progbits" + .align 32 + .type InvalidateInstructionCacheRange# ,@function + .global InvalidateInstructionCacheRange# +// Function compile flags: /Ogsy + .section .rtcode + +// Begin code for function: InvalidateInstructionCacheRange: + .proc InvalidateInstructionCacheRange# + .align 32 +InvalidateInstructionCacheRange: +// File e:\tmp\pioflush.c + { .mii //R-Addr: 0X00 + alloc r3=2, 0, 0, 0 //11, 00000002H + cmp4.leu p0,p6=32, r33;; //15, 00000020H + (p6) mov r33=32;; //16, 00000020H + } + { .mii //R-Addr: 0X010 + nop.m 0 + zxt4 r29=r33;; //21 + dep.z r30=r29, 0, 5;; //21, 00000005H + } + { .mii //R-Addr: 0X020 + cmp4.eq p0,p7=r0, r30 //21 + shr.u r28=r29, 5;; //19, 00000005H + (p7) adds r28=1, r28;; //22, 00000001H + } + { .mii //R-Addr: 0X030 + nop.m 0 + shl r27=r28, 5;; //25, 00000005H + zxt4 r26=r27;; //25 + } + { .mfb //R-Addr: 0X040 + add r31=r26, r32 //25 + nop.f 0 + nop.b 0 + } +$L143: + { .mii //R-Addr: 0X050 + fc r32 //27 + adds r32=32, r32;; //28, 00000020H + cmp.ltu p14,p15=r32, r31 //29 + } + { .mfb //R-Addr: 0X060 + nop.m 0 + nop.f 0 + (p14) br.cond.dptk.few $L143#;; //29, 880000/120000 + } + { .mmi + sync.i;; + srlz.i + nop.i 0;; + } + { .mfb //R-Addr: 0X070 + nop.m 0 + nop.f 0 + br.ret.sptk.few b0;; //31 + } +// End code for function: + .endp InvalidateInstructionCacheRange# +// END diff --git a/MdePkg/Library/BaseCacheMaintenanceLib/IpfCache.c b/MdePkg/Library/BaseCacheMaintenanceLib/IpfCache.c new file mode 100644 index 0000000000..b0d017bd7a --- /dev/null +++ b/MdePkg/Library/BaseCacheMaintenanceLib/IpfCache.c @@ -0,0 +1,95 @@ +/** @file + Cache Maintenance Functions. + + Copyright (c) 2006, 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. + +**/ + +typedef struct { + UINT64 Status; + UINT64 r9; + UINT64 r10; + UINT64 r11; +} PAL_PROC_RETURN; + +PAL_PROC_RETURN +CallPalProcStatic ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4 + ); + +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ + CallPalProcStatic (1, 1, 1, 0); +} + +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ + CallPalProcStatic (1, 2, 1, 0); +} + +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + WriteBackInvalidateDataCache (); + return Address; +} + +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ + CallPalProcStatic (1, 2, 0, 0); +} + +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + WriteBackDataCache (); + return Address; +} + +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ +} + +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return Address; +} diff --git a/MdePkg/Library/BaseCacheMaintenanceLib/build.xml b/MdePkg/Library/BaseCacheMaintenanceLib/build.xml new file mode 100644 index 0000000000..0df03c4356 --- /dev/null +++ b/MdePkg/Library/BaseCacheMaintenanceLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseCacheMaintenanceLib/x86Cache.c b/MdePkg/Library/BaseCacheMaintenanceLib/x86Cache.c new file mode 100644 index 0000000000..f86d9d6221 --- /dev/null +++ b/MdePkg/Library/BaseCacheMaintenanceLib/x86Cache.c @@ -0,0 +1,95 @@ +/** @file + Cache Maintenance Functions. + + Copyright (c) 2006, 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. + + Module Name: x86Cache.c + +**/ + +VOID +EFIAPI +InvalidateInstructionCache ( + VOID + ) +{ + return; +} + +VOID * +EFIAPI +InvalidateInstructionCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return Address; +} + +VOID +EFIAPI +WriteBackInvalidateDataCache ( + VOID + ) +{ + AsmWbinvd (); +} + +VOID * +EFIAPI +WriteBackInvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + if (Length != 0) { + AsmWbinvd (); + } + return Address; +} + +VOID +EFIAPI +WriteBackDataCache ( + VOID + ) +{ + AsmWbinvd (); +} + +VOID * +EFIAPI +WriteBackDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + AsmWbinvd (); + return Address; +} + +VOID +EFIAPI +InvalidateDataCache ( + VOID + ) +{ + AsmInvd (); +} + +VOID * +EFIAPI +InvalidateDataCacheRange ( + IN VOID *Address, + IN UINTN Length + ) +{ + return Address; +} diff --git a/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.mbd b/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.mbd new file mode 100644 index 0000000000..6463e09b5c --- /dev/null +++ b/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.mbd @@ -0,0 +1,30 @@ + + + + + BaseDebugLibNull + 9ba1d976-0624-41a3-8650-28165e8d9ae8 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.msa b/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.msa new file mode 100644 index 0000000000..9eae8f2334 --- /dev/null +++ b/MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.msa @@ -0,0 +1,64 @@ + + + + + BaseDebugLibNull + BASE + LIBRARY + 9ba1d976-0624-41a3-8650-28165e8d9ae8 + 0 + NULL Debug Library for UEFI drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + DebugLib + PcdLib + BaseLib + BaseMemoryLib + PrintLib + + + DebugLib.c + + + MdePkg + + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + + + diff --git a/MdePkg/Library/BaseDebugLibNull/DebugLib.c b/MdePkg/Library/BaseDebugLibNull/DebugLib.c new file mode 100644 index 0000000000..1440f8f127 --- /dev/null +++ b/MdePkg/Library/BaseDebugLibNull/DebugLib.c @@ -0,0 +1,225 @@ +/** @file + Base Debug Library that uses PrintLib to print messages to a memory buffer. + + Copyright (c) 2006, 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. + +**/ + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + +/** + + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print + the message specified by Format and the associated variable argument list to + the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Print the assert message to a buffer + // + VA_START (Marker, Format); + AsciiVSPrint (Buffer, sizeof (Buffer), Format, Marker); + VA_END (Marker); +} + + +/** + + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form “ASSERT (): \n” + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recusrsion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a string of “(NULL) Filename” is printed. + + If Description is NULL, then a string of “(NULL) Description” is printed. + + @param FileName Pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description Pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) +{ + CHAR8 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + // + // Print the assert message to a buffer + // + AsciiSPrint (Buffer, sizeof (Buffer), "ASSERT %s(%d): %s\n", FileName, LineNumber, Description); + + // + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings + // + if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { + CpuBreakpoint (); + } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { + CpuDeadLoop (); + } +} + + +/** + + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + + If Length is greater than (MAX_ADDRESS – Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue)); +} + + +/** + + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CODE()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CLEAR_MEMORY()macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} diff --git a/MdePkg/Library/BaseDebugLibNull/build.xml b/MdePkg/Library/BaseDebugLibNull/build.xml new file mode 100644 index 0000000000..fec569082a --- /dev/null +++ b/MdePkg/Library/BaseDebugLibNull/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseDebugLibReportStatusCode/BaseDebugLibReportStatusCode.mbd b/MdePkg/Library/BaseDebugLibReportStatusCode/BaseDebugLibReportStatusCode.mbd new file mode 100644 index 0000000000..0fc959a5c8 --- /dev/null +++ b/MdePkg/Library/BaseDebugLibReportStatusCode/BaseDebugLibReportStatusCode.mbd @@ -0,0 +1,30 @@ + + + + + BaseDebugLibReportStatusCode + bda39d3a-451b-4350-8266-81ab10fa0523 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BaseDebugLibReportStatusCode/BaseDebugLibReportStatusCode.msa b/MdePkg/Library/BaseDebugLibReportStatusCode/BaseDebugLibReportStatusCode.msa new file mode 100644 index 0000000000..cd781d23d5 --- /dev/null +++ b/MdePkg/Library/BaseDebugLibReportStatusCode/BaseDebugLibReportStatusCode.msa @@ -0,0 +1,64 @@ + + + + + BaseDebugLibReportStatusCode + PEIM + LIBRARY + bda39d3a-451b-4350-8266-81ab10fa0523 + 0 + Debug Library for PEIMs that send debug messages to ReportStatusCode + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + DebugLib + BaseLib + BaseMemoryLib + ReportStatusCodeLib + PcdLib + + + DebugLib.c + + + MdePkg + + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + + + diff --git a/MdePkg/Library/BaseDebugLibReportStatusCode/DebugLib.c b/MdePkg/Library/BaseDebugLibReportStatusCode/DebugLib.c new file mode 100644 index 0000000000..8a4c6a2c1c --- /dev/null +++ b/MdePkg/Library/BaseDebugLibReportStatusCode/DebugLib.c @@ -0,0 +1,283 @@ +/** @file + Debug Library that fowards all messages to ReportStatusCode() + + Copyright (c) 2006, 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. + +**/ + + +/** + + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print + the message specified by Format and the associated variable argument list to + the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ) +{ + UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof (UINT64)]; + EFI_DEBUG_INFO *DebugInfo; + UINTN TotalSize; + UINTN Index; + VA_LIST Marker; + UINT64 *ArgumentPointer; + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver Debug Level value and global debug level + // + if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) { + return; + } + + TotalSize = sizeof (EFI_DEBUG_INFO) + 12 * sizeof (UINT64) + AsciiStrLen (Format) + 1; + if (TotalSize > EFI_STATUS_CODE_DATA_MAX_SIZE) { + return; + } + + // + // Then EFI_DEBUG_INFO + // + DebugInfo = (EFI_DEBUG_INFO *)Buffer; + DebugInfo->ErrorLevel = (UINT32)ErrorLevel; + + // + // 256 byte mini Var Arg stack. That is followed by the format string. + // + VA_START (Marker, Format); + for (Index = 0, ArgumentPointer = (UINT64 *)(DebugInfo + 1); Index < 12; Index++, ArgumentPointer++) { + *ArgumentPointer = VA_ARG (Marker, UINT64); + } + VA_END (Marker); + AsciiStrCpy ((CHAR8 *)ArgumentPointer, Format); + + // + // + // + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + EFI_DEBUG_CODE, + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_DC_UNSPECIFIED), + DebugInfo, + TotalSize + ); +} + + +/** + + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form “ASSERT (): \n” + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recusrsion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a string of “(NULL) Filename” is printed. + + If Description is NULL, then a string of “(NULL) Description” is printed. + + @param FileName Pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description Pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) +{ + UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE / sizeof(UINT64)]; + EFI_DEBUG_ASSERT_DATA *AssertData; + UINTN TotalSize; + CHAR8 *Temp; + + // + // Make sure it will all fit in the passed in buffer + // + TotalSize = sizeof (EFI_DEBUG_ASSERT_DATA) + AsciiStrLen (FileName) + 1 + AsciiStrLen (Description) + 1; + if (TotalSize <= EFI_STATUS_CODE_DATA_MAX_SIZE) { + // + // Fill in EFI_DEBUG_ASSERT_DATA + // + AssertData = (EFI_DEBUG_ASSERT_DATA *)Buffer; + AssertData->LineNumber = (UINT32)LineNumber; + + // + // Copy Ascii FileName including NULL. + // + Temp = AsciiStrCpy ((CHAR8 *)(AssertData + 1), FileName); + + // + // Copy Ascii Description + // + AsciiStrCpy (Temp + AsciiStrLen(FileName) + 1, Description); + + REPORT_STATUS_CODE_WITH_EXTENDED_DATA ( + (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), + (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE), + AssertData, + TotalSize + ); + } + + // + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings + // + if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { + CpuBreakpoint (); + } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { + CpuDeadLoop (); + } +} + + +/** + + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + + If Length is greater than (MAX_ADDRESS – Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue)); +} + + +/** + + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CODE()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CLEAR_MEMORY()macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} diff --git a/MdePkg/Library/BaseDebugLibReportStatusCode/build.xml b/MdePkg/Library/BaseDebugLibReportStatusCode/build.xml new file mode 100644 index 0000000000..edfc5fcd8d --- /dev/null +++ b/MdePkg/Library/BaseDebugLibReportStatusCode/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.mbd b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.mbd new file mode 100644 index 0000000000..8f0c6909e2 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.mbd @@ -0,0 +1,33 @@ + + + + + BaseIoLibIntrinsic + 926c9cd0-4bb8-479b-9ac4-8a2a23f85307 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + + + + diff --git a/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.msa b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.msa new file mode 100644 index 0000000000..91acec75b1 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.msa @@ -0,0 +1,56 @@ + + + + + BaseIoLibIntrinsic + BASE + LIBRARY + 926c9cd0-4bb8-479b-9ac4-8a2a23f85307 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + IoLib + BaseLib + DebugLib + + + + IoLib.c + IoLibMsc.c + IoLibGcc.c + IoHighLevel.c + + + IoLib.c + IoLibMsc.c + IoLibGcc.c + IoHighLevel.c + + + + MdePkg + + diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c b/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c new file mode 100644 index 0000000000..48a7477d81 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoHighLevel.c @@ -0,0 +1,2272 @@ +/** @file + High-level Io/Mmio functions. + + All assertions for bit field operations are handled bit field functions in the + Base Library. + + Copyright (c) 2006, 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. + + Module Name: IoHighLevel.c + + The following IoLib instances share the same version of this file: + + BaseIoLibIntrinsic + DxeIoLibCpuIo + PeiIoLibCpuIo + +**/ + +/** + Reads an 8-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoOr8 ( + IN UINTN Port, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, IoRead8 (Port) | OrData); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND, and writes the result back + to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAnd8 ( + IN UINTN Port, + IN UINT8 AndData + ) +{ + return IoWrite8 (Port, IoRead8 (Port) & AndData); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAndThenOr8 ( + IN UINTN Port, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (IoRead8 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in an 8-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoBitFieldRead8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (IoRead8 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldWrite8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return IoWrite8 ( + Port, + BitFieldWrite8 (IoRead8 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldOr8 (IoRead8 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAnd8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return IoWrite8 ( + Port, + BitFieldAnd8 (IoRead8 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 8-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAndThenOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldAndThenOr8 (IoRead8 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoOr16 ( + IN UINTN Port, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, IoRead16 (Port) | OrData); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND, and writes the result back + to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAnd16 ( + IN UINTN Port, + IN UINT16 AndData + ) +{ + return IoWrite16 (Port, IoRead16 (Port) & AndData); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAndThenOr16 ( + IN UINTN Port, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (IoRead16 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 16-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoBitFieldRead16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (IoRead16 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldWrite16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return IoWrite16 ( + Port, + BitFieldWrite16 (IoRead16 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldOr16 (IoRead16 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAnd16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return IoWrite16 ( + Port, + BitFieldAnd16 (IoRead16 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 16-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAndThenOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldAndThenOr16 (IoRead16 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoOr32 ( + IN UINTN Port, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) | OrData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND, and writes the result back + to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAnd32 ( + IN UINTN Port, + IN UINT32 AndData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) & AndData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAndThenOr32 ( + IN UINTN Port, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, (IoRead32 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 32-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoBitFieldRead32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (IoRead32 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldWrite32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return IoWrite32 ( + Port, + BitFieldWrite32 (IoRead32 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldOr32 (IoRead32 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAnd32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return IoWrite32 ( + Port, + BitFieldAnd32 (IoRead32 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 32-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAndThenOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldAndThenOr32 (IoRead32 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoOr64 ( + IN UINTN Port, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) | OrData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND, and writes the result back + to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAnd64 ( + IN UINTN Port, + IN UINT64 AndData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) & AndData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAndThenOr64 ( + IN UINTN Port, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, (IoRead64 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 64-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoBitFieldRead64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (IoRead64 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldWrite64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return IoWrite64 ( + Port, + BitFieldWrite64 (IoRead64 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldOr64 (IoRead64 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAnd64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return IoWrite64 ( + Port, + BitFieldAnd64 (IoRead64 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 64-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAndThenOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldAndThenOr64 (IoRead64 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, MmioRead8 (Address) | OrData); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND, and writes the result + back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return MmioWrite8 (Address, MmioRead8 (Address) & AndData); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 8-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (MmioRead8 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in an 8-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (MmioRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 8-bit register is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return MmioWrite8 ( + Address, + BitFieldWrite8 (MmioRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldOr8 (MmioRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAnd8 (MmioRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 8-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAndThenOr8 (MmioRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, MmioRead16 (Address) | OrData); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result + back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return MmioWrite16 (Address, MmioRead16 (Address) & AndData); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 16-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (MmioRead16 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 16-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (MmioRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 16-bit register is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return MmioWrite16 ( + Address, + BitFieldWrite16 (MmioRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldOr16 (MmioRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAnd16 (MmioRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 16-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAndThenOr16 (MmioRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) | OrData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result + back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) & AndData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 32-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, (MmioRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 32-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (MmioRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 32-bit register is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return MmioWrite32 ( + Address, + BitFieldWrite32 (MmioRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldOr32 (MmioRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAnd32 (MmioRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 32-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAndThenOr32 (MmioRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioOr64 ( + IN UINTN Address, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) | OrData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result + back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAnd64 ( + IN UINTN Address, + IN UINT64 AndData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) & AndData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 64-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAndThenOr64 ( + IN UINTN Address, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, (MmioRead64 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 64-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioBitFieldRead64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (MmioRead64 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 64-bit register is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldWrite64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return MmioWrite64 ( + Address, + BitFieldWrite64 (MmioRead64 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldOr64 (MmioRead64 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAnd64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAnd64 (MmioRead64 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 64-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAndThenOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAndThenOr64 (MmioRead64 (Address), StartBit, EndBit, AndData, OrData) + ); +} diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c b/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c new file mode 100644 index 0000000000..126457a7e5 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLib.c @@ -0,0 +1,255 @@ +/** @file + Common I/O Library routines. + + Copyright (c) 2006, 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. + + Module Name: IoLib.c + +**/ + +/** + Reads a 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoRead64 ( + IN UINTN Port + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Writes a 64-bit I/O port. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT64 +EFIAPI +IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ) +{ + ASSERT (FALSE); + return 0; +} + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8 ( + IN UINTN Address + ) +{ + return *(volatile UINT8*)Address; +} + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return *(volatile UINT8*)Address = Value; +} + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16 ( + IN UINTN Address + ) +{ + ASSERT ((Address & 1) == 0); + return *(volatile UINT16*)Address; +} + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + ASSERT ((Address & 1) == 0); + return *(volatile UINT16*)Address = Value; +} + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32 ( + IN UINTN Address + ) +{ + ASSERT ((Address & 3) == 0); + return *(volatile UINT32*)Address; +} + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + ASSERT ((Address & 3) == 0); + return *(volatile UINT32*)Address = Value; +} + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64 ( + IN UINTN Address + ) +{ + ASSERT ((Address & 7) == 0); + return *(volatile UINT64*)Address; +} + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + ASSERT ((Address & 7) == 0); + return *(volatile UINT64*)Address = Value; +} diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c b/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c new file mode 100644 index 0000000000..a065c14299 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c @@ -0,0 +1,194 @@ +/** @file + I/O Library. This file has compiler specifics for GCC as there is no + ANSI C standard for doing IO. + + GCC - uses EFIAPI assembler. __asm__ calls GAS. __volatile__ makes sure the + compiler puts the assembler in this exact location. The complex GNUC + operations are not optimzed. It would be possible to also write these + with EFIAPI assembler. + + We don't advocate putting compiler specifics in libraries or drivers but there + is no other way to make this work. + + Copyright (c) 2006, 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. + + Module Name: IoLibGcc.c + +**/ + +#ifdef __GNUC__ + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +__inline__ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + UINT8 Data; + + __asm__ __volatile__ ("inb %w1,%b0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +__inline__ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + __asm__ __volatile__ ("outb %b0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value;; +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +__inline__ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + UINT16 Data; + + ASSERT ((Port & 1) == 0); + __asm__ __volatile__ ("inw %w1,%w0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +__inline__ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + ASSERT ((Port & 1) == 0); + __asm__ __volatile__ ("outw %w0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value;; +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +__inline__ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + UINT32 Data; + + ASSERT ((Port & 3) == 0); + __asm__ __volatile__ ("inl %w1,%0" : "=a" (Data) : "d" ((UINT16)Port)); + return Data; +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +__inline__ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + ASSERT ((Port & 3) == 0); + __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Port)); + return Value; +} + +#endif diff --git a/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c b/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c new file mode 100644 index 0000000000..8bce7a5eb9 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/IoLibMsc.c @@ -0,0 +1,193 @@ +/** @file + I/O Library. This file has compiler specifics for Microsft C as there is no + ANSI C standard for doing IO. + + MSC - uses intrinsic functions and the optimize will remove the function call + overhead. + + We don't advocate putting compiler specifics in libraries or drivers but there + is no other way to make this work. + + Copyright (c) 2006, 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. + + Module Name: IoLibMsc.c + +**/ + + +#if _MSC_EXTENSIONS + +// +// Microsoft Visual Studio 7.1 Function Prototypes for I/O Intrinsics +// +int _inp (unsigned short port); +unsigned short _inpw (unsigned short port); +unsigned long _inpd (unsigned short port); +int _outp (unsigned short port, int databyte ); +unsigned short _outpw(unsigned short port, unsigned short dataword ); +unsigned long _outpd(unsigned short port, unsigned long dataword ); + +#pragma intrinsic(_inp) +#pragma intrinsic(_inpw) +#pragma intrinsic(_inpd) +#pragma intrinsic(_outp) +#pragma intrinsic(_outpw) +#pragma intrinsic(_outpd) + + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + return (UINT8)_inp ((UINT16)Port); +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + return (UINT8)_outp ((UINT16)Port, Value); +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + ASSERT ((Port & 1) == 0); + return _inpw((UINT16)Port); +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + ASSERT ((Port & 1) == 0); + return _outpw ((UINT16)Port, Value); +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + ASSERT ((Port & 3) == 0); + return _inpd((UINT16)Port); +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + ASSERT ((Port & 3) == 0); + return _outpd ((UINT16)Port, Value); +} + +#endif diff --git a/MdePkg/Library/BaseIoLibIntrinsic/build.xml b/MdePkg/Library/BaseIoLibIntrinsic/build.xml new file mode 100644 index 0000000000..9ef6c0ccb7 --- /dev/null +++ b/MdePkg/Library/BaseIoLibIntrinsic/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseLib/ARShiftU64.c b/MdePkg/Library/BaseLib/ARShiftU64.c new file mode 100644 index 0000000000..feb5430311 --- /dev/null +++ b/MdePkg/Library/BaseLib/ARShiftU64.c @@ -0,0 +1,41 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Shifts a 64-bit integer right between 0 and 63 bits. The high bits are filled + with original integer's bit 63. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to bit 63 of Operand. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand arithmetically shifted right by Count + +**/ +UINT64 +EFIAPI +ARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < sizeof (Operand) * 8); + return InternalMathARShiftU64 (Operand, Count); +} diff --git a/MdePkg/Library/BaseLib/BaseLib.mbd b/MdePkg/Library/BaseLib/BaseLib.mbd new file mode 100644 index 0000000000..971777a6d1 --- /dev/null +++ b/MdePkg/Library/BaseLib/BaseLib.mbd @@ -0,0 +1,30 @@ + + + + + BaseLib + 27d67720-ea68-48ae-93da-a3a074c90e30 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-22 18:15 + + diff --git a/MdePkg/Library/BaseLib/BaseLib.msa b/MdePkg/Library/BaseLib/BaseLib.msa new file mode 100644 index 0000000000..efc9eadda7 --- /dev/null +++ b/MdePkg/Library/BaseLib/BaseLib.msa @@ -0,0 +1,309 @@ + + + + + BaseLib + BASE + LIBRARY + 27d67720-ea68-48ae-93da-a3a074c90e30 + 0 + Memory-only library functions with no library constructordestructor + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-22 18:15 + + + BaseLib + BaseMemoryLib + DebugLib + TimerLib + + + String.c + LinkedList.c + Synchronization.c + Cpu.c + CpuDeadLoop.c + BitField.c + ARShiftU64.c + DivS64x64Remainder.c + DivU64x32.c + DivU64x32Remainder.c + DivU64x64Remainder.c + GetPowerOfTwo32.c + GetPowerOfTwo64.c + HighBitSet32.c + HighBitSet64.c + LowBitSet32.c + LowBitSet64.c + LRotU32.c + LRotU64.c + LShiftU64.c + ModU64x32.c + MultS64x64.c + MultU64x32.c + MultU64x64.c + RRotU32.c + RRotU64.c + RShiftU64.c + SwapBytes16.c + SwapBytes32.c + SwapBytes64.c + + x86LowLevel.c + x86Thunk.c + Unaligned.c + Ia32\Non-existing.c + Ia32\LShiftU64.asm + Ia32\RShiftU64.asm + Ia32\ARShiftU64.asm + Ia32\LRotU64.asm + Ia32\RRotU64.asm + Ia32\MultU64x32.asm + Ia32\MultU64x64.asm + Ia32\DivU64x32.asm + Ia32\ModU64x32.asm + Ia32\DivU64x32Remainder.asm + Ia32\DivU64x64Remainder.asm + Ia32\DivS64x64Remainder.c + Ia32\SwapBytes64.asm + Ia32\SetJump.asm + Ia32\LongJump.asm + Ia32\SwitchStack.c + Ia32\CpuId.asm + Ia32\ReadEflags.asm + Ia32\ReadMsr64.asm + Ia32\WriteMsr32.asm + Ia32\WriteMsr64.asm + Ia32\ReadCr0.asm + Ia32\ReadCr2.asm + Ia32\ReadCr3.asm + Ia32\ReadCr4.asm + Ia32\WriteCr0.asm + Ia32\WriteCr2.asm + Ia32\WriteCr3.asm + Ia32\WriteCr4.asm + Ia32\ReadDr0.asm + Ia32\ReadDr1.asm + Ia32\ReadDr2.asm + Ia32\ReadDr3.asm + Ia32\ReadDr4.asm + Ia32\ReadDr5.asm + Ia32\ReadDr6.asm + Ia32\ReadDr7.asm + Ia32\WriteDr0.asm + Ia32\WriteDr1.asm + Ia32\WriteDr2.asm + Ia32\WriteDr3.asm + Ia32\WriteDr4.asm + Ia32\WriteDr5.asm + Ia32\WriteDr6.asm + Ia32\WriteDr7.asm + Ia32\ReadCs.asm + Ia32\ReadDs.asm + Ia32\ReadEs.asm + Ia32\ReadFs.asm + Ia32\ReadGs.asm + Ia32\ReadSs.asm + Ia32\ReadTr.asm + Ia32\ReadGdtr.asm + Ia32\WriteGdtr.asm + Ia32\ReadIdtr.asm + Ia32\WriteIdtr.asm + Ia32\ReadLdtr.asm + Ia32\WriteLdtr.asm + Ia32\FxSave.asm + Ia32\FxRestore.asm + Ia32\ReadMm0.asm + Ia32\ReadMm1.asm + Ia32\ReadMm2.asm + Ia32\ReadMm3.asm + Ia32\ReadMm4.asm + Ia32\ReadMm5.asm + Ia32\ReadMm6.asm + Ia32\ReadMm7.asm + Ia32\WriteMm0.asm + Ia32\WriteMm1.asm + Ia32\WriteMm2.asm + Ia32\WriteMm3.asm + Ia32\WriteMm4.asm + Ia32\WriteMm5.asm + Ia32\WriteMm6.asm + Ia32\WriteMm7.asm + Ia32\ReadTsc.asm + Ia32\ReadPmc.asm + Ia32\Monitor.asm + Ia32\Mwait.asm + Ia32\EnablePaging32.asm + Ia32\DisablePaging32.asm + Ia32\EnablePaging64.asm + Ia32\Wbinvd.asm + Ia32\Invd.asm + Ia32\FlushCacheLine.asm + Ia32\InterlockedIncrement.asm + Ia32\InterlockedDecrement.asm + Ia32\InterlockedCompareExchange32.asm + Ia32\InterlockedCompareExchange64.asm + Ia32\EnableInterrupts.asm + Ia32\DisableInterrupts.asm + Ia32\EnableDisableInterrupts.asm + Ia32\CpuSleep.asm + Ia32\CpuPause.asm + Ia32\CpuBreakpoint.asm + Ia32\CpuFlushTlb.asm + Ia32\Thunk16.asm + + + x86LowLevel.c + x86Thunk.c + Unaligned.c + Math64.c + x64\Non-existing.c + x64\SwitchStack.asm + x64\SetJump.asm + x64\LongJump.asm + x64\CpuId.asm + x64\ReadEflags.asm + x64\ReadMsr32.asm + x64\ReadMsr64.asm + x64\WriteMsr32.asm + x64\WriteMsr64.asm + x64\ReadCr0.asm + x64\ReadCr2.asm + x64\ReadCr3.asm + x64\ReadCr4.asm + x64\WriteCr0.asm + x64\WriteCr2.asm + x64\WriteCr3.asm + x64\WriteCr4.asm + x64\ReadDr0.asm + x64\ReadDr1.asm + x64\ReadDr2.asm + x64\ReadDr3.asm + x64\ReadDr4.asm + x64\ReadDr5.asm + x64\ReadDr6.asm + x64\ReadDr7.asm + x64\WriteDr0.asm + x64\WriteDr1.asm + x64\WriteDr2.asm + x64\WriteDr3.asm + x64\WriteDr4.asm + x64\WriteDr5.asm + x64\WriteDr6.asm + x64\WriteDr7.asm + x64\ReadCs.asm + x64\ReadDs.asm + x64\ReadEs.asm + x64\ReadFs.asm + x64\ReadGs.asm + x64\ReadSs.asm + x64\ReadTr.asm + x64\ReadGdtr.asm + x64\WriteGdtr.asm + x64\ReadIdtr.asm + x64\WriteIdtr.asm + x64\ReadLdtr.asm + x64\WriteLdtr.asm + x64\FxSave.asm + x64\FxRestore.asm + x64\ReadMm0.asm + x64\ReadMm1.asm + x64\ReadMm2.asm + x64\ReadMm3.asm + x64\ReadMm4.asm + x64\ReadMm5.asm + x64\ReadMm6.asm + x64\ReadMm7.asm + x64\WriteMm0.asm + x64\WriteMm1.asm + x64\WriteMm2.asm + x64\WriteMm3.asm + x64\WriteMm4.asm + x64\WriteMm5.asm + x64\WriteMm6.asm + x64\WriteMm7.asm + x64\ReadTsc.asm + x64\ReadPmc.asm + x64\Monitor.asm + x64\Mwait.asm + x64\DisablePaging64.asm + x64\Wbinvd.asm + x64\Invd.asm + x64\FlushCacheLine.asm + x64\InterlockedIncrement.asm + x64\InterlockedDecrement.asm + x64\InterlockedCompareExchange32.asm + x64\InterlockedCompareExchange64.asm + x64\EnableInterrupts.asm + x64\DisableInterrupts.asm + x64\EnableDisableInterrupts.asm + x64\CpuSleep.asm + x64\CpuPause.asm + x64\CpuBreakpoint.asm + x64\CpuFlushTlb.asm + x64\Thunk16.asm + + + Math64.c + Ipf\setjmp.s + Ipf\SwitchStack.s + Ipf\Unaligned.c + Ipf\CpuBreakpoint.c + Ipf\InterlockedCompareExchange32.s + Ipf\InterlockedCompareExchange64.s + Ipf\Synchronization.c + + + Math64.c + SwitchStack.c + SetJumpLongJump.c + Unaligned.c + Ebc\CpuBreakpoint.c + + + + MdePkg + + + + PcdMaximumUnicodeStringLength + 0x00000001 + UINT32 + + + PcdMaximumAsciiStringLength + 0x00000002 + UINT32 + + + PcdMaximumLinkedListLength + 0x00000003 + UINT32 + + + PcdSpinLockTimeout + 0x00000004 + UINT32 + + + diff --git a/MdePkg/Library/BaseLib/BaseLibInternals.h b/MdePkg/Library/BaseLib/BaseLibInternals.h new file mode 100644 index 0000000000..4cccdae528 --- /dev/null +++ b/MdePkg/Library/BaseLib/BaseLibInternals.h @@ -0,0 +1,195 @@ +/** @file + Declaration of internal functions in BaseLib. + + Copyright (c) 2006, 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. + + Module Name: BaseLibInternals.h + +**/ + +#ifndef __BASE_LIB_INTERNALS__ +#define __BASE_LIB_INTERNALS__ + +// +// Math functions +// + +UINT64 +EFIAPI +InternalMathLShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +UINT64 +EFIAPI +InternalMathRShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +UINT64 +EFIAPI +InternalMathARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +UINT64 +EFIAPI +InternalMathLRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +UINT64 +EFIAPI +InternalMathRRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ); + +UINT64 +EFIAPI +InternalMathSwapBytes64 ( + IN UINT64 Operand + ); + +UINT64 +EFIAPI +InternalMathMultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ); + +UINT64 +EFIAPI +InternalMathMultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ); + +UINT64 +EFIAPI +InternalMathDivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + +UINT32 +EFIAPI +InternalMathModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ); + +UINT64 +EFIAPI +InternalMathDivRemU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder + ); + +UINT64 +EFIAPI +InternalMathDivRemU64x64 ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder + ); + +INT64 +EFIAPI +InternalMathDivRemS64x64 ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder + ); + +// +// Ia32 and x64 specific functions +// + +VOID +EFIAPI +InternalX86ReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ); + +VOID +EFIAPI +InternalX86WriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ); + +VOID +EFIAPI +InternalX86ReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ); + +VOID +EFIAPI +InternalX86WriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ); + +VOID +EFIAPI +InternalX86FxSave ( + OUT IA32_FX_BUFFER *Buffer + ); + +VOID +EFIAPI +InternalX86FxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ); + +VOID +EFIAPI +InternalX86EnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + +VOID +EFIAPI +InternalX86DisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ); + +VOID +EFIAPI +InternalX86EnablePaging64 ( + IN UINT16 Cs, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ); + +VOID +EFIAPI +InternalX86DisablePaging64 ( + IN UINT16 Cs, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ); + +#endif diff --git a/MdePkg/Library/BaseLib/BitField.c b/MdePkg/Library/BaseLib/BitField.c new file mode 100644 index 0000000000..ad953396ac --- /dev/null +++ b/MdePkg/Library/BaseLib/BitField.c @@ -0,0 +1,812 @@ +/** @file + Bit field functions of BaseLib. + + Copyright (c) 2006, 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. + + Module Name: BitField.c + +**/ + +unsigned int +EFIAPI +BitFieldReadUint ( + IN unsigned int Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + // + // ~((unsigned int)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] + // are 1's while bit[EndBit + 1] thru the most significant bit are 0's. + // + return (Operand & ~((unsigned int)-2 << EndBit)) >> StartBit; +} + +unsigned int +EFIAPI +BitFieldOrUint ( + IN unsigned int Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN unsigned int OrData + ) +{ + // + // ~((unsigned int)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] + // are 1's while bit[EndBit + 1] thru the most significant bit are 0's. + // + return Operand | ((OrData << StartBit) & ~((unsigned int)-2 << EndBit)); +} + +unsigned int +EFIAPI +BitFieldAndUint ( + IN unsigned int Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN unsigned int AndData + ) +{ + // + // ~((unsigned int)-2 << EndBit) is a mask in which bit[0] thru bit[EndBit] + // are 1's while bit[EndBit + 1] thru the most significant bit are 0's. + // + return Operand & ~((~AndData << StartBit) & ~((unsigned int)-2 << EndBit)); +} + +/** + Returns a bit field from an 8-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The bit field read. + +**/ +UINT8 +EFIAPI +BitFieldRead8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return (UINT8)BitFieldReadUint (Operand, StartBit, EndBit); +} + +/** + Writes a bit field to an 8-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 8-bit value is + returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldWrite8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr8 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from an 8-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise inclusive OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the value + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return (UINT8)BitFieldOrUint (Operand, StartBit, EndBit, OrData); +} + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAnd8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return (UINT8)BitFieldAndUint (Operand, StartBit, EndBit, AndData); +} + +/** + Reads a bit field from an 8-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + inclusive OR with value specified by OrData. All other bits in Operand are + preserved. The new 8-bit value is returned. + + If 8-bit operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 8-bit value. + +**/ +UINT8 +EFIAPI +BitFieldAndThenOr8 ( + IN UINT8 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return BitFieldOr8 ( + BitFieldAnd8 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Returns a bit field from a 16-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The bit field read. + +**/ +UINT16 +EFIAPI +BitFieldRead16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return (UINT16)BitFieldReadUint (Operand, StartBit, EndBit); +} + +/** + Writes a bit field to a 16-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 16-bit value is + returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldWrite16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr16 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from a 16-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise inclusive OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the value + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return (UINT16)BitFieldOrUint (Operand, StartBit, EndBit, OrData); +} + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAnd16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return (UINT16)BitFieldAndUint (Operand, StartBit, EndBit, AndData); +} + +/** + Reads a bit field from a 16-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + inclusive OR with value specified by OrData. All other bits in Operand are + preserved. The new 16-bit value is returned. + + If 16-bit operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 16-bit value. + +**/ +UINT16 +EFIAPI +BitFieldAndThenOr16 ( + IN UINT16 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return BitFieldOr16 ( + BitFieldAnd16 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Returns a bit field from a 32-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read. + +**/ +UINT32 +EFIAPI +BitFieldRead32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)BitFieldReadUint (Operand, StartBit, EndBit); +} + +/** + Writes a bit field to a 32-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 32-bit value is + returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldWrite32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr32 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from a 32-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise inclusive OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the value + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)BitFieldOrUint (Operand, StartBit, EndBit, OrData); +} + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAnd32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)BitFieldAndUint (Operand, StartBit, EndBit, AndData); +} + +/** + Reads a bit field from a 32-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + inclusive OR with value specified by OrData. All other bits in Operand are + preserved. The new 32-bit value is returned. + + If 32-bit operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 32-bit value. + +**/ +UINT32 +EFIAPI +BitFieldAndThenOr32 ( + IN UINT32 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return BitFieldOr32 ( + BitFieldAnd32 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} + +/** + Returns a bit field from a 64-bit value. + + Returns the bitfield specified by the StartBit and the EndBit from Operand. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The bit field read. + +**/ +UINT64 +EFIAPI +BitFieldRead64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return RShiftU64 (Operand & ~LShiftU64 ((UINT64)-2, EndBit), StartBit); +} + +/** + Writes a bit field to a 64-bit value, and returns the result. + + Writes Value to the bit field specified by the StartBit and the EndBit in + Operand. All other bits in Operand are preserved. The new 64-bit value is + returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldWrite64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return BitFieldAndThenOr64 (Operand, StartBit, EndBit, 0, Value); +} + +/** + Reads a bit field from a 64-bit value, performs a bitwise OR, and returns the + result. + + Performs a bitwise inclusive OR between the bit field specified by StartBit + and EndBit in Operand and the value specified by OrData. All other bits in + Operand are preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the value + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return Operand | + (LShiftU64 (OrData, StartBit) & ~LShiftU64 ((UINT64)-2, EndBit)); +} + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND, and returns + the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAnd64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return Operand & + ~(LShiftU64 (~AndData, StartBit) & ~LShiftU64 ((UINT64)-2, EndBit)); +} + +/** + Reads a bit field from a 64-bit value, performs a bitwise AND followed by a + bitwise OR, and returns the result. + + Performs a bitwise AND between the bit field specified by StartBit and EndBit + in Operand and the value specified by AndData, followed by a bitwise + inclusive OR with value specified by OrData. All other bits in Operand are + preserved. The new 64-bit value is returned. + + If 64-bit operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Operand Operand on which to perform the bitfield operation. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the value. + @param OrData The value to OR with the result of the AND operation. + + @return The new 64-bit value. + +**/ +UINT64 +EFIAPI +BitFieldAndThenOr64 ( + IN UINT64 Operand, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + ASSERT (EndBit < sizeof (Operand) * 8); + ASSERT (StartBit <= EndBit); + return BitFieldOr64 ( + BitFieldAnd64 (Operand, StartBit, EndBit, AndData), + StartBit, + EndBit, + OrData + ); +} diff --git a/MdePkg/Library/BaseLib/Cpu.c b/MdePkg/Library/BaseLib/Cpu.c new file mode 100644 index 0000000000..cc7a608f83 --- /dev/null +++ b/MdePkg/Library/BaseLib/Cpu.c @@ -0,0 +1,67 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006, 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. + + Module Name: Cpu.c + +**/ + +/** + Disables CPU interrupts and returns the interrupt state prior to the disable + operation. + + Disables CPU interrupts and returns the interrupt state prior to the disable + operation. + + @retval TRUE CPU interrupts were enabled on entry to this call. + @retval FALSE CPU interrupts were disabled on entry to this call. + +**/ +BOOLEAN +EFIAPI +SaveAndDisableInterrupts ( + VOID + ) +{ + BOOLEAN InterruptState; + + InterruptState = GetInterruptState (); + DisableInterrupts (); + return InterruptState; +} + +/** + Set the current CPU interrupt state. + + Sets the current CPU interrupt state to the state specified by + InterruptState. If InterruptState is TRUE, then interrupts are enabled. If + InterruptState is FALSE, then interrupts are disabled. InterruptState is + returned. + + @param InterruptState TRUE if interrupts should enabled. FALSE if + interrupts should be disabled. + + @return InterruptState + +**/ +BOOLEAN +EFIAPI +SetInterruptState ( + IN BOOLEAN InterruptState + ) +{ + if (InterruptState) { + EnableInterrupts (); + } else { + DisableInterrupts (); + } + return InterruptState; +} diff --git a/MdePkg/Library/BaseLib/CpuDeadLoop.c b/MdePkg/Library/BaseLib/CpuDeadLoop.c new file mode 100644 index 0000000000..f8f530207a --- /dev/null +++ b/MdePkg/Library/BaseLib/CpuDeadLoop.c @@ -0,0 +1,33 @@ +/** @file + Base Library CPU Functions for all architectures. + + Copyright (c) 2006, 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. + +**/ + +/** + Executes an infinite loop. + + Forces the CPU to execute an infinite loop. A debugger may be used to skip + past the loop and the code that follows the loop must execute properly. This + implies that the infinite loop must not cause the code that follow it to be + optimized away. + +**/ +VOID +EFIAPI +CpuDeadLoop ( + VOID + ) +{ + volatile UINTN Index; + + for (Index = 0; Index == 0;); +} diff --git a/MdePkg/Library/BaseLib/DivS64x64Remainder.c b/MdePkg/Library/BaseLib/DivS64x64Remainder.c new file mode 100644 index 0000000000..aa28fc8ccb --- /dev/null +++ b/MdePkg/Library/BaseLib/DivS64x64Remainder.c @@ -0,0 +1,46 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Divides a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result and a optional 64-bit signed remainder. + + This function divides the 64-bit signed value Dividend by the 64-bit signed + value Divisor and generates a 64-bit signed quotient. If Remainder is not + NULL, then the 64-bit signed remainder is returned in Remainder. This + function returns the 64-bit signed quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit signed value. + @param Divisor A 64-bit signed value. + @param Remainder A pointer to a 64-bit signed value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +INT64 +EFIAPI +DivS64x64Remainder ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivRemS64x64 (Dividend, Divisor, Remainder); +} diff --git a/MdePkg/Library/BaseLib/DivU64x32.c b/MdePkg/Library/BaseLib/DivU64x32.c new file mode 100644 index 0000000000..b223c6c87b --- /dev/null +++ b/MdePkg/Library/BaseLib/DivU64x32.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. This + function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivU64x32 (Dividend, Divisor); +} diff --git a/MdePkg/Library/BaseLib/DivU64x32Remainder.c b/MdePkg/Library/BaseLib/DivU64x32Remainder.c new file mode 100644 index 0000000000..aa34b31e46 --- /dev/null +++ b/MdePkg/Library/BaseLib/DivU64x32Remainder.c @@ -0,0 +1,46 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 64-bit unsigned result and an optional 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 32-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + @param Remainder A pointer to a 32-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x32Remainder ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivRemU64x32 (Dividend, Divisor, Remainder); +} diff --git a/MdePkg/Library/BaseLib/DivU64x64Remainder.c b/MdePkg/Library/BaseLib/DivU64x64Remainder.c new file mode 100644 index 0000000000..0caa5295aa --- /dev/null +++ b/MdePkg/Library/BaseLib/DivU64x64Remainder.c @@ -0,0 +1,46 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Divides a 64-bit unsigned integer by a 64-bit unsigned integer and generates + a 64-bit unsigned result and an optional 64-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 64-bit + unsigned value Divisor and generates a 64-bit unsigned quotient. If Remainder + is not NULL, then the 64-bit unsigned remainder is returned in Remainder. + This function returns the 64-bit unsigned quotient. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 64-bit unsigned value. + @param Remainder A pointer to a 64-bit unsigned value. This parameter is + optional and may be NULL. + + @return Dividend / Divisor + +**/ +UINT64 +EFIAPI +DivU64x64Remainder ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder + ) +{ + ASSERT (Divisor != 0); + return InternalMathDivRemU64x64 (Dividend, Divisor, Remainder); +} diff --git a/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c b/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c new file mode 100644 index 0000000000..b0b262f367 --- /dev/null +++ b/MdePkg/Library/BaseLib/Ebc/CpuBreakpoint.c @@ -0,0 +1,100 @@ +/** @file + Base Library CPU Functions for EBC + + Copyright (c) 2006, 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. + +**/ + +extern +UINT64 +_break ( + CHAR8 BreakCode + ); + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + _break (3); +} + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ +} + +/** + Disables CPU interrupts. + + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + ASSERT (FALSE); +} + +/** + Enables CPU interrupts. + + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + ASSERT (FALSE); +} + +/** + Retrieves the current CPU interrupt state. + + Retrieves the current CPU interrupt state. Returns TRUE is interrupts are + currently enabled. Otherwise returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + VOID + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/MdePkg/Library/BaseLib/GetPowerOfTwo32.c b/MdePkg/Library/BaseLib/GetPowerOfTwo32.c new file mode 100644 index 0000000000..6dfe8056b4 --- /dev/null +++ b/MdePkg/Library/BaseLib/GetPowerOfTwo32.c @@ -0,0 +1,39 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Returns the value of the highest bit set in a 32-bit value. Equivalent to + 1 << HighBitSet32(x). + + This function computes the value of the highest bit set in the 32-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 32-bit operand to evaluate. + + @return 1 << HighBitSet32(Operand) + @retval 0 Operand is zero. + +**/ +UINT32 +EFIAPI +GetPowerOfTwo32 ( + IN UINT32 Operand + ) +{ + INTN BitPos; + + return (BitPos = HighBitSet32 (Operand)) > 0 ? 1ul << BitPos : 0; +} diff --git a/MdePkg/Library/BaseLib/GetPowerOfTwo64.c b/MdePkg/Library/BaseLib/GetPowerOfTwo64.c new file mode 100644 index 0000000000..9994fb8f12 --- /dev/null +++ b/MdePkg/Library/BaseLib/GetPowerOfTwo64.c @@ -0,0 +1,39 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Returns the value of the highest bit set in a 64-bit value. Equivalent to + 1 << HighBitSet64(x). + + This function computes the value of the highest bit set in the 64-bit value + specified by Operand. If Operand is zero, then zero is returned. + + @param Operand The 64-bit operand to evaluate. + + @return 1 << HighBitSet64(Operand) + @retval 0 Operand is zero. + +**/ +UINT64 +EFIAPI +GetPowerOfTwo64 ( + IN UINT64 Operand + ) +{ + INTN BitPos; + + return (BitPos = HighBitSet64 (Operand)) > 0 ? LShiftU64 (1, BitPos) : 0; +} diff --git a/MdePkg/Library/BaseLib/HighBitSet32.c b/MdePkg/Library/BaseLib/HighBitSet32.c new file mode 100644 index 0000000000..65f067ac1a --- /dev/null +++ b/MdePkg/Library/BaseLib/HighBitSet32.c @@ -0,0 +1,41 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Returns the bit position of the highest bit set in a 32-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @return Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet32 ( + IN UINT32 Operand + ) +{ + INTN BitIndex; + + for (BitIndex = -1; Operand != 0; BitIndex++, Operand >>= 1); + return BitIndex; +} diff --git a/MdePkg/Library/BaseLib/HighBitSet64.c b/MdePkg/Library/BaseLib/HighBitSet64.c new file mode 100644 index 0000000000..50889777b5 --- /dev/null +++ b/MdePkg/Library/BaseLib/HighBitSet64.c @@ -0,0 +1,43 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Returns the bit position of the highest bit set in a 64-bit value. Equivalent + to log2(x). + + This function computes the bit position of the highest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @return Position of the highest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +HighBitSet64 ( + IN UINT64 Operand + ) +{ + INTN BitIndex; + + for (BitIndex = -1; + Operand != 0; + BitIndex++, Operand = RShiftU64 (Operand, 1)); + return BitIndex; +} diff --git a/MdePkg/Library/BaseLib/Ipf/CpuBreakpoint.c b/MdePkg/Library/BaseLib/Ipf/CpuBreakpoint.c new file mode 100644 index 0000000000..987fc9c846 --- /dev/null +++ b/MdePkg/Library/BaseLib/Ipf/CpuBreakpoint.c @@ -0,0 +1,101 @@ +/** @file + Base Library CPU functions for Itanium + + Copyright (c) 2006, 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. + +**/ + +//void __mfa (void); + +#pragma intrinsic (_enable) +#pragma intrinsic (_disable) +#pragma intrinsic (__break) +#pragma intrinsic (__mfa) + +/** + Generates a breakpoint on the CPU. + + Generates a breakpoint on the CPU. The breakpoint must be implemented such + that code can resume normal execution after the breakpoint. + +**/ +VOID +EFIAPI +CpuBreakpoint ( + VOID + ) +{ + __break (0); +} + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ + __mfa (); +} + +/** + Disables CPU interrupts. + + Disables CPU interrupts. + +**/ +VOID +EFIAPI +DisableInterrupts ( + VOID + ) +{ + _disable (); +} + +/** + Enables CPU interrupts. + + Enables CPU interrupts. + +**/ +VOID +EFIAPI +EnableInterrupts ( + VOID + ) +{ + _enable (); +} + +/** + Retrieves the current CPU interrupt state. + + Retrieves the current CPU interrupt state. Returns TRUE is interrupts are + currently enabled. Otherwise returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + VOID + ) +{ + return FALSE; +} diff --git a/MdePkg/Library/BaseLib/Ipf/InterlockedCompareExchange32.s b/MdePkg/Library/BaseLib/Ipf/InterlockedCompareExchange32.s new file mode 100644 index 0000000000..3a278d7268 --- /dev/null +++ b/MdePkg/Library/BaseLib/Ipf/InterlockedCompareExchange32.s @@ -0,0 +1,29 @@ +/// @file +/// Contains an implementation of InterlockedCompareExchange32 on Itanium- +/// based architecture. +/// +/// Copyright (c) 2006, 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. +/// +/// Module Name: InterlockedCompareExchange32.s +/// +/// + +.auto +.text + +.proc InternalSyncCompareExchange32 +.type InternalSyncCompareExchange32, @function +InternalSyncCompareExchange32:: + zxt4 r33 = r33 + mov ar.ccv = r33 + cmpxchg4.rel r8 = [r32], r34 + mf + br.ret.sptk.many b0 +.endp InternalSyncCompareExchange32 \ No newline at end of file diff --git a/MdePkg/Library/BaseLib/Ipf/InterlockedCompareExchange64.s b/MdePkg/Library/BaseLib/Ipf/InterlockedCompareExchange64.s new file mode 100644 index 0000000000..200e30e09e --- /dev/null +++ b/MdePkg/Library/BaseLib/Ipf/InterlockedCompareExchange64.s @@ -0,0 +1,28 @@ +/// @file +/// Contains an implementation of InterlockedCompareExchange64 on Itanium- +/// based architecture. +/// +/// Copyright (c) 2006, 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. +/// +/// Module Name: InterlockedCompareExchange64.s +/// +/// + +.auto +.text + +.proc InternalSyncCompareExchange64 +.type InternalSyncCompareExchange64, @function +InternalSyncCompareExchange64:: + mov ar.ccv = r33 + cmpxchg8.rel r8 = [r64], r34 + mf + br.ret.sptk.many b0 +.endp InternalSyncCompareExchange64 \ No newline at end of file diff --git a/MdePkg/Library/BaseLib/Ipf/SwitchStack.s b/MdePkg/Library/BaseLib/Ipf/SwitchStack.s new file mode 100644 index 0000000000..4dd17f533e --- /dev/null +++ b/MdePkg/Library/BaseLib/Ipf/SwitchStack.s @@ -0,0 +1,122 @@ +//++ +// Copyright (c) 2006, 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. +// +// Module Name: +// +// SwitchStack.s +// +// Abstract: +// +// Contains an implementation of a stack switch for the Itanium-based architecture. +// +// +// +// Revision History: +// +//-- + + .file "SwitchStack.s" + +#include "asm.h" +#include "ia_64gen.h" + +// Define hardware RSE Configuration Register +// +// RS Configuration (RSC) bit field positions + +#define RSC_MODE 0 +#define RSC_PL 2 +#define RSC_BE 4 +// RSC bits 5-15 reserved +#define RSC_MBZ0 5 +#define RSC_MBZ0_V 0x3ff +#define RSC_LOADRS 16 +#define RSC_LOADRS_LEN 14 +// RSC bits 30-63 reserved +#define RSC_MBZ1 30 +#define RSC_MBZ1_V 0x3ffffffffULL + +// RSC modes +// Lazy +#define RSC_MODE_LY (0x0) +// Store intensive +#define RSC_MODE_SI (0x1) +// Load intensive +#define RSC_MODE_LI (0x2) +// Eager +#define RSC_MODE_EA (0x3) + +// RSC Endian bit values +#define RSC_BE_LITTLE 0 +#define RSC_BE_BIG 1 + +// RSC while in kernel: enabled, little endian, pl = 0, eager mode +#define RSC_KERNEL ((RSC_MODE_EA< + 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. + + Module Name: Synchronization.c + +**/ + +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ); + +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ) +{ + UINT32 OriginalValue; + + do { + OriginalValue = *Value; + } while (OriginalValue == InternalSyncCompareExchange32 ( + Value, + OriginalValue, + OriginalValue + 1 + )); + return OriginalValue + 1; +} + +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ) +{ + UINT32 OriginalValue; + + do { + OriginalValue = *Value; + } while (OriginalValue == InternalSyncCompareExchange32 ( + Value, + OriginalValue, + OriginalValue - 1 + )); + return OriginalValue - 1; +} diff --git a/MdePkg/Library/BaseLib/Ipf/Unaligned.c b/MdePkg/Library/BaseLib/Ipf/Unaligned.c new file mode 100644 index 0000000000..eeeb0f85bb --- /dev/null +++ b/MdePkg/Library/BaseLib/Ipf/Unaligned.c @@ -0,0 +1,220 @@ +/** @file + Unaligned access functions of BaseLib for IPF. + + Copyright (c) 2006, 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. + + Module Name: Unaligned.c + +**/ + +/** + Reads a 16-bit value from memory that may be unaligned. + + This function returns the 16-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 16-bit value that may be unaligned. + + @return *Uint16 + +**/ +UINT16 +EFIAPI +ReadUnaligned16 ( + IN CONST UINT16 *Buffer + ) +{ + return (UINT16)(((UINT8*)Buffer)[0] | (((UINT8*)Buffer)[1] << 8)); +} + +/** + Writes a 16-bit value to memory that may be unaligned. + + This function writes the 16-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 16-bit value that may be unaligned. + @param Value 16-bit value to write to Buffer. + + @return Value + +**/ +UINT16 +EFIAPI +WriteUnaligned16 ( + OUT UINT16 *Buffer, + IN UINT16 Value + ) +{ + ((UINT8*)Buffer)[0] = (UINT8)Value; + ((UINT8*)Buffer)[1] = (UINT8)(Value >> 8); + return Value; +} + +/** + Reads a 24-bit value from memory that may be unaligned. + + This function returns the 24-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 24-bit value that may be unaligned. + + @return The value read. + +**/ +UINT32 +EFIAPI +ReadUnaligned24 ( + IN CONST UINT32 *Buffer + ) +{ + return (UINT32)( + ReadUnaligned16 ((UINT16*)Buffer) | + (((UINT8*)Buffer)[2] << 16) + ); +} + +/** + Writes a 24-bit value to memory that may be unaligned. + + This function writes the 24-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 24-bit value that may be unaligned. + @param Value 24-bit value to write to Buffer. + + @return The value written. + +**/ +UINT32 +EFIAPI +WriteUnaligned24 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ) +{ + WriteUnaligned16 ((UINT16*)Buffer, (UINT16)Value); + *(UINT8*)((UINT16*)Buffer + 1) = (UINT8)(Value >> 16); + return Value; +} + +/** + Reads a 32-bit value from memory that may be unaligned. + + This function returns the 32-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 32-bit value that may be unaligned. + + @return *Uint32 + +**/ +UINT32 +EFIAPI +ReadUnaligned32 ( + IN CONST UINT32 *Buffer + ) +{ + return (UINT32)( + ReadUnaligned16 ((UINT16*)Buffer) | + (ReadUnaligned16 ((UINT16*)Buffer + 1) << 16) + ); +} + +/** + Writes a 32-bit value to memory that may be unaligned. + + This function writes the 32-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 32-bit value that may be unaligned. + @param Value 32-bit value to write to Buffer. + + @return Value + +**/ +UINT32 +EFIAPI +WriteUnaligned32 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ) +{ + WriteUnaligned16 ((UINT16*)Buffer, (UINT16)Value); + WriteUnaligned16 ((UINT16*)Buffer + 1, (UINT16)(Value >> 16)); + return Value; +} + +/** + Reads a 64-bit value from memory that may be unaligned. + + This function returns the 64-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 64-bit value that may be unaligned. + + @return *Uint64 + +**/ +UINT64 +EFIAPI +ReadUnaligned64 ( + IN CONST UINT64 *Buffer + ) +{ + return (UINT64)( + ReadUnaligned32 ((UINT32*)Buffer) | + LShiftU64 (ReadUnaligned32 ((UINT32*)Buffer + 1), 32) + ); +} + +/** + Writes a 64-bit value to memory that may be unaligned. + + This function writes the 64-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 64-bit value that may be unaligned. + @param Value 64-bit value to write to Buffer. + + @return Value + +**/ +UINT64 +EFIAPI +WriteUnaligned64 ( + OUT UINT64 *Buffer, + IN UINT64 Value + ) +{ + WriteUnaligned32 ((UINT32*)Buffer, (UINT32)Value); + WriteUnaligned32 ((UINT32*)Buffer + 1, (UINT32)RShiftU64 (Value, 32)); + return Value; +} diff --git a/MdePkg/Library/BaseLib/Ipf/asm.h b/MdePkg/Library/BaseLib/Ipf/asm.h new file mode 100644 index 0000000000..8ef0b30626 --- /dev/null +++ b/MdePkg/Library/BaseLib/Ipf/asm.h @@ -0,0 +1,27 @@ +/// @file +/// This module contains generic macros for an assembly writer. +/// +/// Copyright (c) 2006, 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. +/// +/// Module Name: asm.h +/// +#ifndef _ASM_H +#define _ASM_H + +#define TRUE 1 +#define FALSE 0 +#define PROCEDURE_ENTRY(name) .##text; \ + .##type name, @function; \ + .##proc name; \ + name:: + +#define PROCEDURE_EXIT(name) .##endp name + +#endif // _ASM_H diff --git a/MdePkg/Library/BaseLib/Ipf/ia_64gen.h b/MdePkg/Library/BaseLib/Ipf/ia_64gen.h new file mode 100644 index 0000000000..081cc4a8f6 --- /dev/null +++ b/MdePkg/Library/BaseLib/Ipf/ia_64gen.h @@ -0,0 +1,205 @@ +/// @file +/// +/// +/// Copyright (c) 2006, 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. +/// +/// Module Name: ia_64gen.h +/// +#ifndef _IA64GEN_H +#define _IA64GEN_H + +#define TT_UNAT 0 +#define C_PSR 0 +#define J_UNAT 0 +#define T_TYPE 0 +#define T_IPSR 0x8 +#define T_ISR 0x10 +#define T_IIP 0x18 +#define T_IFA 0x20 +#define T_IIPA 0x28 +#define T_IFS 0x30 +#define T_IIM 0x38 +#define T_RSC 0x40 +#define T_BSP 0x48 +#define T_BSPSTORE 0x50 +#define T_RNAT 0x58 +#define T_PFS 0x60 +#define T_KBSPSTORE 0x68 +#define T_UNAT 0x70 +#define T_CCV 0x78 +#define T_DCR 0x80 +#define T_PREDS 0x88 +#define T_NATS 0x90 +#define T_R1 0x98 +#define T_GP 0x98 +#define T_R2 0xa0 +#define T_R3 0xa8 +#define T_R4 0xb0 +#define T_R5 0xb8 +#define T_R6 0xc0 +#define T_R7 0xc8 +#define T_R8 0xd0 +#define T_R9 0xd8 +#define T_R10 0xe0 +#define T_R11 0xe8 +#define T_R12 0xf0 +#define T_SP 0xf0 +#define T_R13 0xf8 +#define T_R14 0x100 +#define T_R15 0x108 +#define T_R16 0x110 +#define T_R17 0x118 +#define T_R18 0x120 +#define T_R19 0x128 +#define T_R20 0x130 +#define T_R21 0x138 +#define T_R22 0x140 +#define T_R23 0x148 +#define T_R24 0x150 +#define T_R25 0x158 +#define T_R26 0x160 +#define T_R27 0x168 +#define T_R28 0x170 +#define T_R29 0x178 +#define T_R30 0x180 +#define T_R31 0x188 +#define T_F2 0x1f0 +#define T_F3 0x200 +#define T_F4 0x210 +#define T_F5 0x220 +#define T_F6 0x230 +#define T_F7 0x240 +#define T_F8 0x250 +#define T_F9 0x260 +#define T_F10 0x270 +#define T_F11 0x280 +#define T_F12 0x290 +#define T_F13 0x2a0 +#define T_F14 0x2b0 +#define T_F15 0x2c0 +#define T_F16 0x2d0 +#define T_F17 0x2e0 +#define T_F18 0x2f0 +#define T_F19 0x300 +#define T_F20 0x310 +#define T_F21 0x320 +#define T_F22 0x330 +#define T_F23 0x340 +#define T_F24 0x350 +#define T_F25 0x360 +#define T_F26 0x370 +#define T_F27 0x380 +#define T_F28 0x390 +#define T_F29 0x3a0 +#define T_F30 0x3b0 +#define T_F31 0x3c0 +#define T_FPSR 0x1e0 +#define T_B0 0x190 +#define T_B1 0x198 +#define T_B2 0x1a0 +#define T_B3 0x1a8 +#define T_B4 0x1b0 +#define T_B5 0x1b8 +#define T_B6 0x1c0 +#define T_B7 0x1c8 +#define T_EC 0x1d0 +#define T_LC 0x1d8 +#define J_NATS 0x8 +#define J_PFS 0x10 +#define J_BSP 0x18 +#define J_RNAT 0x20 +#define J_PREDS 0x28 +#define J_LC 0x30 +#define J_R4 0x38 +#define J_R5 0x40 +#define J_R6 0x48 +#define J_R7 0x50 +#define J_SP 0x58 +#define J_F2 0x60 +#define J_F3 0x70 +#define J_F4 0x80 +#define J_F5 0x90 +#define J_F16 0xa0 +#define J_F17 0xb0 +#define J_F18 0xc0 +#define J_F19 0xd0 +#define J_F20 0xe0 +#define J_F21 0xf0 +#define J_F22 0x100 +#define J_F23 0x110 +#define J_F24 0x120 +#define J_F25 0x130 +#define J_F26 0x140 +#define J_F27 0x150 +#define J_F28 0x160 +#define J_F29 0x170 +#define J_F30 0x180 +#define J_F31 0x190 +#define J_FPSR 0x1a0 +#define J_B0 0x1a8 +#define J_B1 0x1b0 +#define J_B2 0x1b8 +#define J_B3 0x1c0 +#define J_B4 0x1c8 +#define J_B5 0x1d0 +#define TRAP_FRAME_LENGTH 0x3d0 +#define C_UNAT 0x28 +#define C_NATS 0x30 +#define C_PFS 0x8 +#define C_BSPSTORE 0x10 +#define C_RNAT 0x18 +#define C_RSC 0x20 +#define C_PREDS 0x38 +#define C_LC 0x40 +#define C_DCR 0x48 +#define C_R1 0x50 +#define C_GP 0x50 +#define C_R4 0x58 +#define C_R5 0x60 +#define C_R6 0x68 +#define C_R7 0x70 +#define C_SP 0x78 +#define C_R13 0x80 +#define C_F2 0x90 +#define C_F3 0xa0 +#define C_F4 0xb0 +#define C_F5 0xc0 +#define C_F16 0xd0 +#define C_F17 0xe0 +#define C_F18 0xf0 +#define C_F19 0x100 +#define C_F20 0x110 +#define C_F21 0x120 +#define C_F22 0x130 +#define C_F23 0x140 +#define C_F24 0x150 +#define C_F25 0x160 +#define C_F26 0x170 +#define C_F27 0x180 +#define C_F28 0x190 +#define C_F29 0x1a0 +#define C_F30 0x1b0 +#define C_F31 0x1c0 +#define C_FPSR 0x1d0 +#define C_B0 0x1d8 +#define C_B1 0x1e0 +#define C_B2 0x1e8 +#define C_B3 0x1f0 +#define C_B4 0x1f8 +#define C_B5 0x200 +#define TT_R2 0x8 +#define TT_R3 0x10 +#define TT_R8 0x18 +#define TT_R9 0x20 +#define TT_R10 0x28 +#define TT_R11 0x30 +#define TT_R14 0x38 + +#endif _IA64GEN_H diff --git a/MdePkg/Library/BaseLib/Ipf/setjmp.s b/MdePkg/Library/BaseLib/Ipf/setjmp.s new file mode 100644 index 0000000000..6569db6af4 --- /dev/null +++ b/MdePkg/Library/BaseLib/Ipf/setjmp.s @@ -0,0 +1,317 @@ +/// @file +/// Contains an implementation of setjmp and longjmp for the +/// Itanium-based architecture. +/// +/// Copyright (c) 2006, 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. +/// +/// Module Name: setjmp.s +/// +/// + + .file "setjmp.s" + +#include "asm.h" +#include "ia_64gen.h" + +/// int SetJump(struct jmp_buffer save) +/// +/// Setup a non-local goto. +/// +/// Description: +/// +/// SetJump stores the current register set in the area pointed to +/// by "save". It returns zero. Subsequent calls to "LongJump" will +/// restore the registers and return non-zero to the same location. +/// +/// On entry, r32 contains the pointer to the jmp_buffer +/// + +PROCEDURE_ENTRY(SetJump) + // + // Make sure buffer is aligned at 16byte boundary + // + mov r32 = r33 + + add r10 = -0x10,r0 ;; // mask the lower 4 bits + and r32 = r32, r10;; + add r32 = 0x10, r32;; // move to next 16 byte boundary + + add r10 = J_PREDS, r32 // skip Unats & pfs save area + add r11 = J_BSP, r32 + // + // save immediate context + // + mov r2 = ar.bsp // save backing store pointer + mov r3 = pr // save predicates + ;; + // + // save user Unat register + // + mov r16 = ar.lc // save loop count register + mov r14 = ar.unat // save user Unat register + + st8 [r10] = r3, J_LC-J_PREDS + st8 [r11] = r2, J_R4-J_BSP + ;; + st8 [r10] = r16, J_R5-J_LC + st8 [r32] = r14, J_NATS // Note: Unat at the + // beginning of the save area + mov r15 = ar.pfs + ;; + // + // save preserved general registers & NaT's + // + st8.spill [r11] = r4, J_R6-J_R4 + ;; + st8.spill [r10] = r5, J_R7-J_R5 + ;; + st8.spill [r11] = r6, J_SP-J_R6 + ;; + st8.spill [r10] = r7, J_F3-J_R7 + ;; + st8.spill [r11] = sp, J_F2-J_SP + ;; + // + // save spilled Unat and pfs registers + // + mov r2 = ar.unat // save Unat register after spill + ;; + st8 [r32] = r2, J_PFS-J_NATS // save unat for spilled regs + ;; + st8 [r32] = r15 // save pfs + // + // save floating registers + // + stf.spill [r11] = f2, J_F4-J_F2 + stf.spill [r10] = f3, J_F5-J_F3 + ;; + stf.spill [r11] = f4, J_F16-J_F4 + stf.spill [r10] = f5, J_F17-J_F5 + ;; + stf.spill [r11] = f16, J_F18-J_F16 + stf.spill [r10] = f17, J_F19-J_F17 + ;; + stf.spill [r11] = f18, J_F20-J_F18 + stf.spill [r10] = f19, J_F21-J_F19 + ;; + stf.spill [r11] = f20, J_F22-J_F20 + stf.spill [r10] = f21, J_F23-J_F21 + ;; + stf.spill [r11] = f22, J_F24-J_F22 + stf.spill [r10] = f23, J_F25-J_F23 + ;; + stf.spill [r11] = f24, J_F26-J_F24 + stf.spill [r10] = f25, J_F27-J_F25 + ;; + stf.spill [r11] = f26, J_F28-J_F26 + stf.spill [r10] = f27, J_F29-J_F27 + ;; + stf.spill [r11] = f28, J_F30-J_F28 + stf.spill [r10] = f29, J_F31-J_F29 + ;; + stf.spill [r11] = f30, J_FPSR-J_F30 + stf.spill [r10] = f31, J_B0-J_F31 // size of f31 + fpsr + // + // save FPSR register & branch registers + // + mov r2 = ar.fpsr // save fpsr register + mov r3 = b0 + ;; + st8 [r11] = r2, J_B1-J_FPSR + st8 [r10] = r3, J_B2-J_B0 + mov r2 = b1 + mov r3 = b2 + ;; + st8 [r11] = r2, J_B3-J_B1 + st8 [r10] = r3, J_B4-J_B2 + mov r2 = b3 + mov r3 = b4 + ;; + st8 [r11] = r2, J_B5-J_B3 + st8 [r10] = r3 + mov r2 = b5 + ;; + st8 [r11] = r2 + ;; + // + // return + // + mov r8 = r0 // return 0 from setjmp + mov ar.unat = r14 // restore unat + br.ret.sptk b0 + +PROCEDURE_EXIT(SetJump) + + +// +// void LongJump(struct jmp_buffer *) +// +// Perform a non-local goto. +// +// Description: +// +// LongJump initializes the register set to the values saved by a +// previous 'SetJump' and jumps to the return location saved by that +// 'SetJump'. This has the effect of unwinding the stack and returning +// for a second time to the 'SetJump'. +// + +PROCEDURE_ENTRY(LongJump) + // + // Make sure buffer is aligned at 16byte boundary + // + mov r32 = r33 + + add r10 = -0x10,r0 ;; // mask the lower 4 bits + and r32 = r32, r10;; + add r32 = 0x10, r32;; // move to next 16 byte boundary + + // + // caching the return value as we do invala in the end + // +/// mov r8 = r33 // return value + mov r8 = 1 // For now return hard coded 1 + + // + // get immediate context + // + mov r14 = ar.rsc // get user RSC conf + add r10 = J_PFS, r32 // get address of pfs + add r11 = J_NATS, r32 + ;; + ld8 r15 = [r10], J_BSP-J_PFS // get pfs + ld8 r2 = [r11], J_LC-J_NATS // get unat for spilled regs + ;; + mov ar.unat = r2 + ;; + ld8 r16 = [r10], J_PREDS-J_BSP // get backing store pointer + mov ar.rsc = r0 // put RSE in enforced lazy + mov ar.pfs = r15 + ;; + + // + // while returning from longjmp the BSPSTORE and BSP needs to be + // same and discard all the registers allocated after we did + // setjmp. Also, we need to generate the RNAT register since we + // did not flushed the RSE on setjmp. + // + mov r17 = ar.bspstore // get current BSPSTORE + ;; + cmp.ltu p6,p7 = r17, r16 // is it less than BSP of +(p6) br.spnt.few .flush_rse + mov r19 = ar.rnat // get current RNAT + ;; + loadrs // invalidate dirty regs + br.sptk.many .restore_rnat // restore RNAT + +.flush_rse: + flushrs + ;; + mov r19 = ar.rnat // get current RNAT + mov r17 = r16 // current BSPSTORE + ;; +.restore_rnat: + // + // check if RNAT is saved between saved BSP and curr BSPSTORE + // + dep r18 = 1,r16,3,6 // get RNAT address + ;; + cmp.ltu p8,p9 = r18, r17 // RNAT saved on RSE + ;; +(p8) ld8 r19 = [r18] // get RNAT from RSE + ;; + mov ar.bspstore = r16 // set new BSPSTORE + ;; + mov ar.rnat = r19 // restore RNAT + mov ar.rsc = r14 // restore RSC conf + + + ld8 r3 = [r11], J_R4-J_LC // get lc register + ld8 r2 = [r10], J_R5-J_PREDS // get predicates + ;; + mov pr = r2, -1 + mov ar.lc = r3 + // + // restore preserved general registers & NaT's + // + ld8.fill r4 = [r11], J_R6-J_R4 + ;; + ld8.fill r5 = [r10], J_R7-J_R5 + ld8.fill r6 = [r11], J_SP-J_R6 + ;; + ld8.fill r7 = [r10], J_F2-J_R7 + ld8.fill sp = [r11], J_F3-J_SP + ;; + // + // restore floating registers + // + ldf.fill f2 = [r10], J_F4-J_F2 + ldf.fill f3 = [r11], J_F5-J_F3 + ;; + ldf.fill f4 = [r10], J_F16-J_F4 + ldf.fill f5 = [r11], J_F17-J_F5 + ;; + ldf.fill f16 = [r10], J_F18-J_F16 + ldf.fill f17 = [r11], J_F19-J_F17 + ;; + ldf.fill f18 = [r10], J_F20-J_F18 + ldf.fill f19 = [r11], J_F21-J_F19 + ;; + ldf.fill f20 = [r10], J_F22-J_F20 + ldf.fill f21 = [r11], J_F23-J_F21 + ;; + ldf.fill f22 = [r10], J_F24-J_F22 + ldf.fill f23 = [r11], J_F25-J_F23 + ;; + ldf.fill f24 = [r10], J_F26-J_F24 + ldf.fill f25 = [r11], J_F27-J_F25 + ;; + ldf.fill f26 = [r10], J_F28-J_F26 + ldf.fill f27 = [r11], J_F29-J_F27 + ;; + ldf.fill f28 = [r10], J_F30-J_F28 + ldf.fill f29 = [r11], J_F31-J_F29 + ;; + ldf.fill f30 = [r10], J_FPSR-J_F30 + ldf.fill f31 = [r11], J_B0-J_F31 ;; + + // + // restore branch registers and fpsr + // + ld8 r16 = [r10], J_B1-J_FPSR // get fpsr + ld8 r17 = [r11], J_B2-J_B0 // get return pointer + ;; + mov ar.fpsr = r16 + mov b0 = r17 + ld8 r2 = [r10], J_B3-J_B1 + ld8 r3 = [r11], J_B4-J_B2 + ;; + mov b1 = r2 + mov b2 = r3 + ld8 r2 = [r10], J_B5-J_B3 + ld8 r3 = [r11] + ;; + mov b3 = r2 + mov b4 = r3 + ld8 r2 = [r10] + ld8 r21 = [r32] // get user unat + ;; + mov b5 = r2 + mov ar.unat = r21 + + // + // invalidate ALAT + // + invala ;; + + br.ret.sptk b0 +PROCEDURE_EXIT(LongJump) + + diff --git a/MdePkg/Library/BaseLib/LRotU32.c b/MdePkg/Library/BaseLib/LRotU32.c new file mode 100644 index 0000000000..ea782463d0 --- /dev/null +++ b/MdePkg/Library/BaseLib/LRotU32.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Rotates a 32-bit integer left between 0 and 31 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 32-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand <<< Count + +**/ +UINT32 +EFIAPI +LRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < sizeof (Operand) * 8); + return (Operand << Count) | (Operand >> (32 - Count)); +} diff --git a/MdePkg/Library/BaseLib/LRotU64.c b/MdePkg/Library/BaseLib/LRotU64.c new file mode 100644 index 0000000000..cf751f98f5 --- /dev/null +++ b/MdePkg/Library/BaseLib/LRotU64.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Rotates a 64-bit integer left between 0 and 63 bits, filling the low bits + with the high bits that were rotated. + + This function rotates the 64-bit value Operand to the left by Count bits. The + low Count bits are fill with the high Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate left. + @param Count The number of bits to rotate left. + + @return Operand <<< Count + +**/ +UINT64 +EFIAPI +LRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < sizeof (Operand) * 8); + return InternalMathLRotU64 (Operand, Count); +} diff --git a/MdePkg/Library/BaseLib/LShiftU64.c b/MdePkg/Library/BaseLib/LShiftU64.c new file mode 100644 index 0000000000..50449eb9e3 --- /dev/null +++ b/MdePkg/Library/BaseLib/LShiftU64.c @@ -0,0 +1,41 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Shifts a 64-bit integer left between 0 and 63 bits. The low bits are filled + with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the left by Count bits. The + low Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift left. + @param Count The number of bits to shift left. + + @return Operand << Count + +**/ +UINT64 +EFIAPI +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < sizeof (Operand) * 8); + return InternalMathLShiftU64 (Operand, Count); +} diff --git a/MdePkg/Library/BaseLib/LinkedList.c b/MdePkg/Library/BaseLib/LinkedList.c new file mode 100644 index 0000000000..0f42749775 --- /dev/null +++ b/MdePkg/Library/BaseLib/LinkedList.c @@ -0,0 +1,433 @@ +/** @file + Linked List Library Functions. + + Copyright (c) 2006, 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. + + Module Name: LinkedList.c + +**/ + +BOOLEAN +EFIAPI +IsNodeInList ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + UINTN Count; + CONST LIST_ENTRY *Ptr; + BOOLEAN Found; + + // + // Test the validity of List and Node + // + ASSERT (List != NULL); + ASSERT (List->ForwardLink != NULL); + ASSERT (List->BackLink != NULL); + ASSERT (Node != NULL); + + Count = FixedPcdGet32 (PcdMaximumLinkedListLength); + Ptr = List; + do { + Ptr = Ptr->ForwardLink; + Count--; + } while ((Ptr != List) && (Ptr != Node) && (Count > 0)); + Found = (BOOLEAN)(Ptr == Node); + + if (FixedPcdGet32 (PcdMaximumLinkedListLength) > 0) { + while ((Count > 0) && (Ptr != List)) { + Ptr = Ptr->ForwardLink; + } + ASSERT (Count > 0); + } + + return Found; +} + +/** + Initializes the head node of a doubly linked list, and returns the pointer to + the head node of the doubly linked list. + + Initializes the forward and backward links of a new linked list. After + initializing a linked list with this function, the other linked list + functions may be used to add and remove nodes from the linked list. It is up + to the caller of this function to allocate the memory for ListHead. + + If ListHead is NULL, then ASSERT(). + + @param ListHead A pointer to the head node of a new doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InitializeListHead ( + IN OUT LIST_ENTRY *List + ) + +{ + ASSERT (List != NULL); + + List->ForwardLink = List; + List->BackLink = List; + return List; +} + +/** + Adds a node to the beginning of a doubly linked list, and returns the pointer + to the head node of the doubly linked list. + + Adds the node Entry at the beginning of the doubly linked list denoted by + ListHead, and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and ListHead contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + @param Entry A pointer to a node that is to be inserted at the beginning + of a doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertHeadList ( + IN OUT LIST_ENTRY *List, + IN OUT LIST_ENTRY *Entry + ) +{ + // + // ASSERT List not too long and Entry is not one of the nodes of List + // + ASSERT (!IsNodeInList (List, Entry)); + + Entry->ForwardLink = List->ForwardLink; + Entry->BackLink = List; + Entry->ForwardLink->BackLink = Entry; + List->ForwardLink = Entry; + return List; +} + +/** + Adds a node to the end of a doubly linked list, and returns the pointer to + the head node of the doubly linked list. + + Adds the node Entry to the end of the doubly linked list denoted by ListHead, + and returns ListHead. + + If ListHead is NULL, then ASSERT(). + If Entry is NULL, then ASSERT(). + If ListHead was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and ListHead contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + @param Entry A pointer to a node that is to be added at the end of the + doubly linked list. + + @return ListHead + +**/ +LIST_ENTRY * +EFIAPI +InsertTailList ( + IN OUT LIST_ENTRY *List, + IN OUT LIST_ENTRY *Entry + ) +{ + // + // ASSERT List not too long and Entry is not one of the nodes of List + // + ASSERT (!IsNodeInList (List, Entry)); + + Entry->ForwardLink = List; + Entry->BackLink = List->BackLink; + Entry->BackLink->ForwardLink = Entry; + List->BackLink = Entry; + return List; +} + +/** + Retrieves the first node of a doubly linked list. + + Returns the first node of a doubly linked list. List must have been + initialized with InitializeListHead(). If List is empty, then NULL is + returned. + + If List is NULL, then ASSERT(). + If List was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + + @return The first node of a doubly linked list. + @retval NULL The list is empty. + +**/ +LIST_ENTRY * +EFIAPI +GetFirstNode ( + IN CONST LIST_ENTRY *List + ) +{ + // + // ASSERT List not too long + // + ASSERT (IsNodeInList (List, List)); + + return List->ForwardLink; +} + +/** + Retrieves the next node of a doubly linked list. + + Returns the node of a doubly linked list that follows Node. List must have + been initialized with InitializeListHead(). If List is empty, then List is + returned. + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + If Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @return Pointer to the next node if one exists. Otherwise a null value which + is actually List is returned. + +**/ +LIST_ENTRY * +EFIAPI +GetNextNode ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT (IsNodeInList (List, Node)); + + return Node->ForwardLink; +} + +/** + Checks to see if a doubly linked list is empty or not. + + Checks to see if the doubly linked list is empty. If the linked list contains + zero nodes, this function returns TRUE. Otherwise, it returns FALSE. + + If ListHead is NULL, then ASSERT(). + If ListHead was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + + @param ListHead A pointer to the head node of a doubly linked list. + + @retval TRUE The linked list is empty. + @retval FALSE The linked list is not empty. + +**/ +BOOLEAN +EFIAPI +IsListEmpty ( + IN CONST LIST_ENTRY *List + ) +{ + // + // ASSERT List not too long + // + ASSERT (IsNodeInList (List, List)); + + return (BOOLEAN)(List->ForwardLink == List); +} + +/** + Determines if a node in a doubly linked list is null. + + Returns FALSE if Node is one of the nodes in the doubly linked list specified + by List. Otherwise, TRUE is returned. List must have been initialized with + InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + If Node is not a node in List and Node is not equal to List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @retval TRUE Node is one of the nodes in the doubly linked list. + @retval FALSE Node is not one of the nodes in the doubly linked list. + +**/ +BOOLEAN +EFIAPI +IsNull ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT (IsNodeInList (List, Node)); + + return (BOOLEAN)(Node == List); +} + +/** + Determines if a node the last node in a doubly linked list. + + Returns TRUE if Node is the last node in the doubly linked list specified by + List. Otherwise, FALSE is returned. List must have been initialized with + InitializeListHead(). + + If List is NULL, then ASSERT(). + If Node is NULL, then ASSERT(). + If List was not initialized with InitializeListHead(), then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and List contains more than + PcdMaximumLinkedListLenth nodes, then ASSERT(). + If Node is not a node in List, then ASSERT(). + + @param List A pointer to the head node of a doubly linked list. + @param Node A pointer to a node in the doubly linked list. + + @retval TRUE Node is the last node in the linked list. + @retval FALSE Node is not the last node in the linked list. + +**/ +BOOLEAN +EFIAPI +IsNodeAtEnd ( + IN CONST LIST_ENTRY *List, + IN CONST LIST_ENTRY *Node + ) +{ + // + // ASSERT List not too long and Node is one of the nodes of List + // + ASSERT (IsNodeInList (List, Node)); + + return (BOOLEAN)(!IsNull (List, Node) && List->BackLink == Node); +} + +/** + Swaps the location of two nodes in a doubly linked list, and returns the + first node after the swap. + + If FirstEntry is identical to SecondEntry, then SecondEntry is returned. + Otherwise, the location of the FirstEntry node is swapped with the location + of the SecondEntry node in a doubly linked list. SecondEntry must be in the + same double linked list as FirstEntry and that double linked list must have + been initialized with InitializeListHead(). SecondEntry is returned after the + nodes are swapped. + + If FirstEntry is NULL, then ASSERT(). + If SecondEntry is NULL, then ASSERT(). + If SecondEntry and FirstEntry are not in the same linked list, then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the linked list containing + FirstEntry and SecondEntry contains more than PcdMaximumLinkedListLenth + nodes, then ASSERT(). + + @param FirstEntry A pointer to a node in a linked list. + @param SecondEntry A pointer to another node in the same linked list. + +**/ +LIST_ENTRY * +EFIAPI +SwapListEntries ( + IN OUT LIST_ENTRY *FirstEntry, + IN OUT LIST_ENTRY *SecondEntry + ) +{ + LIST_ENTRY *Ptr; + + if (FirstEntry == SecondEntry) { + return SecondEntry; + } + + // + // ASSERT Entry1 and Entry2 are in the same linked list + // + ASSERT (IsNodeInList (FirstEntry, SecondEntry)); + + // + // Ptr is the node pointed to by FirstEntry->ForwardLink + // + Ptr = RemoveEntryList (FirstEntry); + + // + // If FirstEntry immediately follows SecondEntry, FirstEntry willl be placed + // immediately in front of SecondEntry + // + if (Ptr->BackLink == SecondEntry) { + return InsertTailList (SecondEntry, FirstEntry); + } + + // + // Ptr == SecondEntry means SecondEntry immediately follows FirstEntry, + // then there are no further steps necessary + // + if (Ptr == InsertHeadList (SecondEntry, FirstEntry)) { + return Ptr; + } + + // + // Move SecondEntry to the front of Ptr + // + RemoveEntryList (SecondEntry); + InsertTailList (Ptr, SecondEntry); + return SecondEntry; +} + +/** + Removes a node from a doubly linked list, and returns the node that follows + the removed node. + + Removes the node Entry from a doubly linked list. It is up to the caller of + this function to release the memory used by this node if that is required. On + exit, the node following Entry in the doubly linked list is returned. If + Entry is the only node in the linked list, then the head node of the linked + list is returned. + + If Entry is NULL, then ASSERT(). + If Entry is the head node of an empty list, then ASSERT(). + If PcdMaximumLinkedListLenth is not zero, and the linked list containing + Entry contains more than PcdMaximumLinkedListLenth nodes, then ASSERT(). + + @param Entry A pointer to a node in a linked list + + @return Entry + +**/ +LIST_ENTRY * +EFIAPI +RemoveEntryList ( + IN CONST LIST_ENTRY *Entry + ) +{ + ASSERT (!IsListEmpty (Entry)); + + Entry->ForwardLink->BackLink = Entry->BackLink; + Entry->BackLink->ForwardLink = Entry->ForwardLink; + return Entry->ForwardLink; +} diff --git a/MdePkg/Library/BaseLib/LowBitSet32.c b/MdePkg/Library/BaseLib/LowBitSet32.c new file mode 100644 index 0000000000..5a21245264 --- /dev/null +++ b/MdePkg/Library/BaseLib/LowBitSet32.c @@ -0,0 +1,44 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Returns the bit position of the lowest bit set in a 32-bit value. + + This function computes the bit position of the lowest bit set in the 32-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 31 is returned. + + @param Operand The 32-bit operand to evaluate. + + @return Position of the lowest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +LowBitSet32 ( + IN UINT32 Operand + ) +{ + INTN BitIndex; + + if (Operand == 0) { + return -1; + } + + for (BitIndex = 0; (Operand & 1) == 0; BitIndex++, Operand >>= 1); + return BitIndex; +} diff --git a/MdePkg/Library/BaseLib/LowBitSet64.c b/MdePkg/Library/BaseLib/LowBitSet64.c new file mode 100644 index 0000000000..a3e5ba0842 --- /dev/null +++ b/MdePkg/Library/BaseLib/LowBitSet64.c @@ -0,0 +1,46 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Returns the bit position of the lowest bit set in a 64-bit value. + + This function computes the bit position of the lowest bit set in the 64-bit + value specified by Operand. If Operand is zero, then -1 is returned. + Otherwise, a value between 0 and 63 is returned. + + @param Operand The 64-bit operand to evaluate. + + @return Position of the lowest bit set in Operand if found. + @retval -1 Operand is zero. + +**/ +INTN +EFIAPI +LowBitSet64 ( + IN UINT64 Operand + ) +{ + INTN BitIndex; + + if (Operand == 0) { + return -1; + } + + for (BitIndex = 0; + (Operand & 1) == 0; + BitIndex++, Operand = RShiftU64 (Operand, 1)); + return BitIndex; +} diff --git a/MdePkg/Library/BaseLib/Math64.c b/MdePkg/Library/BaseLib/Math64.c new file mode 100644 index 0000000000..27d75232c5 --- /dev/null +++ b/MdePkg/Library/BaseLib/Math64.c @@ -0,0 +1,174 @@ +/** @file + Leaf math worker functions that require 64-bit arithmetic support from the + compiler. + + Copyright (c) 2006, 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. + + Module Name: Math64.c + +**/ + +UINT64 +EFIAPI +InternalMathLShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return Operand << Count; +} + +UINT64 +EFIAPI +InternalMathRShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return Operand >> Count; +} + +UINT64 +EFIAPI +InternalMathARShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + // + // Test if this compiler supports arithmetic shift + // + if ((((-1) << (sizeof (-1) * 8 - 1)) >> (sizeof (-1) * 8 - 1)) == -1) { + // + // Arithmetic shift is supported + // + return (UINT64)((INT64)Operand >> Count); + } + + // + // Arithmetic is not supported + // + return (Operand >> Count) | + ((INTN)Operand < 0 ? ~((UINTN)-1 >> Count) : 0); +} + +UINT64 +EFIAPI +InternalMathLRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return (Operand << Count) | (Operand >> (64 - Count)); +} + +UINT64 +EFIAPI +InternalMathRRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + return (Operand >> Count) | (Operand << (64 - Count)); +} + +UINT64 +EFIAPI +InternalMathSwapBytes64 ( + IN UINT64 Operand + ) +{ + return (UINT64)( + ((UINT64)SwapBytes32 ((UINT32)Operand) << 32) | + ((UINT64)SwapBytes32 ((UINT32)(Operand >> 32))) + ); +} + +UINT64 +EFIAPI +InternalMathMultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ) +{ + return Multiplicand * Multiplier; +} + +UINT64 +EFIAPI +InternalMathMultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ) +{ + return Multiplicand * Multiplier; +} + +UINT64 +EFIAPI +InternalMathDivU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + return Dividend / Divisor; +} + +UINT64 +EFIAPI +InternalMathModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + return Dividend % Divisor; +} + +UINT64 +EFIAPI +InternalMathDivRemU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor, + OUT UINT32 *Remainder + ) +{ + if (Remainder != NULL) { + *Remainder = (UINT32)(Dividend % Divisor); + } + return Dividend / Divisor; +} + +UINT64 +EFIAPI +InternalMathDivRemU64x64 ( + IN UINT64 Dividend, + IN UINT64 Divisor, + OUT UINT64 *Remainder + ) +{ + if (Remainder != NULL) { + *Remainder = Dividend % Divisor; + } + return Dividend / Divisor; +} + +INT64 +EFIAPI +InternalMathDivRemS64x64 ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder + ) +{ + if (Remainder != NULL) { + *Remainder = Dividend % Divisor; + } + return Dividend / Divisor; +} diff --git a/MdePkg/Library/BaseLib/ModU64x32.c b/MdePkg/Library/BaseLib/ModU64x32.c new file mode 100644 index 0000000000..a8737f43f6 --- /dev/null +++ b/MdePkg/Library/BaseLib/ModU64x32.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Divides a 64-bit unsigned integer by a 32-bit unsigned integer and generates + a 32-bit unsigned remainder. + + This function divides the 64-bit unsigned value Dividend by the 32-bit + unsigned value Divisor and generates a 32-bit remainder. This function + returns the 32-bit unsigned remainder. + + If Divisor is 0, then ASSERT(). + + @param Dividend A 64-bit unsigned value. + @param Divisor A 32-bit unsigned value. + + @return Dividend % Divisor + +**/ +UINT32 +EFIAPI +ModU64x32 ( + IN UINT64 Dividend, + IN UINT32 Divisor + ) +{ + ASSERT (Divisor != 0); + return InternalMathModU64x32 (Dividend, Divisor); +} diff --git a/MdePkg/Library/BaseLib/MultS64x64.c b/MdePkg/Library/BaseLib/MultS64x64.c new file mode 100644 index 0000000000..7e8d3184f5 --- /dev/null +++ b/MdePkg/Library/BaseLib/MultS64x64.c @@ -0,0 +1,41 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Multiples a 64-bit signed integer by a 64-bit signed integer and generates a + 64-bit signed result. + + This function multiples the 64-bit signed value Multiplicand by the 64-bit + signed value Multiplier and generates a 64-bit signed result. This 64-bit + signed result is returned. + + If the result overflows, then ASSERT(). + + @param Multiplicand A 64-bit signed value. + @param Multiplier A 64-bit signed value. + + @return Multiplicand * Multiplier + +**/ +INT64 +EFIAPI +MultS64x64 ( + IN INT64 Multiplicand, + IN INT64 Multiplier + ) +{ + return (INT64)MultU64x64 (Multiplicand, Multiplier); +} diff --git a/MdePkg/Library/BaseLib/MultU64x32.c b/MdePkg/Library/BaseLib/MultU64x32.c new file mode 100644 index 0000000000..4c30472bfa --- /dev/null +++ b/MdePkg/Library/BaseLib/MultU64x32.c @@ -0,0 +1,45 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Multiples a 64-bit unsigned integer by a 32-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiples the 64-bit unsigned value Multiplicand by the 32-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + If the result overflows, then ASSERT(). + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 32-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINT32 Multiplier + ) +{ + UINT64 Result; + + Result = InternalMathMultU64x32 (Multiplicand, Multiplier); + // TODO: ASSERT (Result not overflow); + return Result; +} diff --git a/MdePkg/Library/BaseLib/MultU64x64.c b/MdePkg/Library/BaseLib/MultU64x64.c new file mode 100644 index 0000000000..6324c3e335 --- /dev/null +++ b/MdePkg/Library/BaseLib/MultU64x64.c @@ -0,0 +1,45 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Multiples a 64-bit unsigned integer by a 64-bit unsigned integer and + generates a 64-bit unsigned result. + + This function multiples the 64-bit unsigned value Multiplicand by the 64-bit + unsigned value Multiplier and generates a 64-bit unsigned result. This 64- + bit unsigned result is returned. + + If the result overflows, then ASSERT(). + + @param Multiplicand A 64-bit unsigned value. + @param Multiplier A 64-bit unsigned value. + + @return Multiplicand * Multiplier + +**/ +UINT64 +EFIAPI +MultU64x64 ( + IN UINT64 Multiplicand, + IN UINT64 Multiplier + ) +{ + UINT64 Result; + + Result = InternalMathMultU64x64 (Multiplicand, Multiplier); + // TODO: ASSERT (Result not overflow); + return Result; +} diff --git a/MdePkg/Library/BaseLib/RRotU32.c b/MdePkg/Library/BaseLib/RRotU32.c new file mode 100644 index 0000000000..93dda94b9f --- /dev/null +++ b/MdePkg/Library/BaseLib/RRotU32.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Rotates a 32-bit integer right between 0 and 31 bits, filling the high bits + with the low bits that were rotated. + + This function rotates the 32-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 31, then ASSERT(). + + @param Operand The 32-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >>> Count + +**/ +UINT32 +EFIAPI +RRotU32 ( + IN UINT32 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < sizeof (Operand) * 8); + return (Operand >> Count) | (Operand << (32 - Count)); +} diff --git a/MdePkg/Library/BaseLib/RRotU64.c b/MdePkg/Library/BaseLib/RRotU64.c new file mode 100644 index 0000000000..d55bbfc79f --- /dev/null +++ b/MdePkg/Library/BaseLib/RRotU64.c @@ -0,0 +1,42 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Rotates a 64-bit integer right between 0 and 63 bits, filling the high bits + with the high low bits that were rotated. + + This function rotates the 64-bit value Operand to the right by Count bits. + The high Count bits are fill with the low Count bits of Operand. The rotated + value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to rotate right. + @param Count The number of bits to rotate right. + + @return Operand >>> Count + +**/ +UINT64 +EFIAPI +RRotU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < sizeof (Operand) * 8); + return InternalMathRRotU64 (Operand, Count); +} diff --git a/MdePkg/Library/BaseLib/RShiftU64.c b/MdePkg/Library/BaseLib/RShiftU64.c new file mode 100644 index 0000000000..f9ae4f6efa --- /dev/null +++ b/MdePkg/Library/BaseLib/RShiftU64.c @@ -0,0 +1,41 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Shifts a 64-bit integer right between 0 and 63 bits. This high bits are + filled with zeros. The shifted value is returned. + + This function shifts the 64-bit value Operand to the right by Count bits. The + high Count bits are set to zero. The shifted value is returned. + + If Count is greater than 63, then ASSERT(). + + @param Operand The 64-bit operand to shift right. + @param Count The number of bits to shift right. + + @return Operand >> Count + +**/ +UINT64 +EFIAPI +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +{ + ASSERT (Count < sizeof (Operand) * 8); + return InternalMathRShiftU64 (Operand, Count); +} diff --git a/MdePkg/Library/BaseLib/SetJumpLongJump.c b/MdePkg/Library/BaseLib/SetJumpLongJump.c new file mode 100644 index 0000000000..a2381251f3 --- /dev/null +++ b/MdePkg/Library/BaseLib/SetJumpLongJump.c @@ -0,0 +1,40 @@ +/** @file + Switch Stack functions. + + Copyright (c) 2006, 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. + + Module Name: SetJumpLongJump.c + +**/ + + + +UINTN +EFIAPI +SetJump ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer + ) +{ + ASSERT (JumpBuffer != NULL); + ASSERT (FALSE); + return 0; +} + +VOID +EFIAPI +LongJump ( + IN BASE_LIBRARY_JUMP_BUFFER *JumpBuffer, + IN UINTN Value + ) +{ + ASSERT (JumpBuffer != NULL); + ASSERT (Value != 0); + ASSERT (FALSE); +} diff --git a/MdePkg/Library/BaseLib/String.c b/MdePkg/Library/BaseLib/String.c new file mode 100644 index 0000000000..fb39a22a42 --- /dev/null +++ b/MdePkg/Library/BaseLib/String.c @@ -0,0 +1,798 @@ +/** @file + Unicode string primatives. + + Copyright (c) 2006, 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. + + Module Name: String.c + +**/ + +/** + Copies one Null-terminated Unicode string to another Null-terminated Unicode + string and returns the new Unicode string. + + This function copies the contents of the Unicode string Source to the Unicode + string Destination, and returns Destination. If Source and Destination + overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated Unicode string. + @param Source Pointer to a Null-terminated Unicode string. + + @return Destiantion + +**/ +CHAR16 * +EFIAPI +StrCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ) +{ + CHAR16 *ReturnValue; + + // + // Destination cannot be NULL + // + ASSERT (Destination != NULL); + + // + // Destination and source cannot overlap + // + ASSERT ((UINTN)(Destination - Source) > StrLen (Source)); + ASSERT ((UINTN)(Source - Destination) > StrLen (Source)); + + ReturnValue = Destination; + while (*Source) { + *(Destination++) = *(Source++); + } + *Destination = 0; + return ReturnValue; +} + +/** + Copies one Null-terminated Unicode string with a maximum length to another + Null-terminated Unicode string with a maximum length and returns the new + Unicode string. + + This function copies the contents of the Unicode string Source to the Unicode + string Destination, and returns Destination. At most, Length Unicode + characters are copied from Source to Destination. If Length is 0, then + Destination is returned unmodified. If Length is greater that the number of + Unicode characters in Source, then Destination is padded with Null Unicode + characters. If Source and Destination overlap, then the results are + undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated Unicode string. + @param Source Pointer to a Null-terminated Unicode string. + @param Length Maximum number of Unicode characters to copy. + + @return Destination + +**/ +CHAR16 * +EFIAPI +StrnCpy ( + OUT CHAR16 *Destination, + IN CONST CHAR16 *Source, + IN UINTN Length + ) +{ + CHAR16 *ReturnValue; + + if (Length == 0) { + return Destination; + } + + // + // Destination cannot be NULL if Length is not zero + // + ASSERT (Destination != NULL); + + // + // Destination and source cannot overlap + // Q: Does Source have to be NULL-terminated? + // + ASSERT ((UINTN)(Destination - Source) > StrLen (Source)); + ASSERT ((UINTN)(Source - Destination) >= Length); + + ReturnValue = Destination; + + while ((*Source != L'\0') && (Length > 1)) { + *(Destination++) = *(Source++); + Length--; + } + + ZeroMem (Destination, Length * sizeof (*Destination)); + return ReturnValue; +} + +/** + Returns the length of a Null-terminated Unicode string. + + This function returns the number of Unicode characters in the Null-terminated + Unicode string specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + + @return The length of String. + +**/ +UINTN +EFIAPI +StrLen ( + IN CONST CHAR16 *String + ) +{ + UINTN Length; + + ASSERT (String != NULL); + + for (Length = 0; *String != L'\0'; String++, Length++) { + // + // If PcdMaximumUnicodeStringLength is not zero, + // length should not more than PcdMaximumUnicodeStringLength + // + if (FixedPcdGet32 (PcdMaximumUnicodeStringLength) != 0) { + ASSERT (Length < FixedPcdGet32 (PcdMaximumUnicodeStringLength)); + } + } + return Length; +} + +/** + Returns the size of a Null-terminated Unicode string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated Unicode + string specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + + @return The size of String. + +**/ +UINTN +EFIAPI +StrSize ( + IN CONST CHAR16 *String + ) +{ + return (StrLen (String) + 1) * sizeof (*String); +} + +/** + Compares two Null-terminated Unicode strings, and returns the difference + between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched Unicode character in SecondString subtracted from the first + mismatched Unicode character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param FirstString Pointer to a Null-terminated Unicode string. + @param SecondString Pointer to a Null-terminated Unicode string. + + @retval 0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString + ) +{ + // + // ASSERT both strings are less long than PcdMaximumUnicodeStringLength + // + ASSERT (StrSize (FirstString) != 0); + ASSERT (StrSize (SecondString) != 0); + + while ((*FirstString != L'\0') && (*FirstString == *SecondString)) { + FirstString++; + SecondString++; + } + return *FirstString - *SecondString; +} + +/** + Compares two Null-terminated Unicode strings with maximum lengths, and + returns the difference between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. At most, Length Unicode + characters will be compared. If Length is 0, then 0 is returned. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched Unicode character in SecondString + subtracted from the first mismatched Unicode character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param FirstString Pointer to a Null-terminated Unicode string. + @param SecondString Pointer to a Null-terminated Unicode string. + @param Length Maximum number of Unicode characters to compare. + + @retval 0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +StrnCmp ( + IN CONST CHAR16 *FirstString, + IN CONST CHAR16 *SecondString, + IN UINTN Length + ) +{ + if (Length == 0) { + return 0; + } + + // + // ASSERT both strings are less long than PcdMaximumUnicodeStringLength. + // Length tests are performed inside StrLen(). + // + ASSERT (StrSize (FirstString) != 0); + ASSERT (StrSize (SecondString) != 0); + + while ((*FirstString != L'\0') && + (*FirstString != *SecondString) && + (Length > 1)) { + FirstString++; + SecondString++; + Length--; + } + + return *FirstString - *SecondString; +} + +/** + Concatenates one Null-terminated Unicode string to another Null-terminated + Unicode string, and returns the concatenated Unicode string. + + This function concatenates two Null-terminated Unicode strings. The contents + of Null-terminated Unicode string Source are concatenated to the end of + Null-terminated Unicode string Destination. The Null-terminated concatenated + Unicode String is returned. If Source and Destination overlap, then the + results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Destination contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination + and Source results in a Unicode string with more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated Unicode string. + @param Source Pointer to a Null-terminated Unicode string. + + @return Destination + +**/ +CHAR16 * +EFIAPI +StrCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source + ) +{ + StrCpy (Destination + StrLen (Destination), Source); + + // + // Size of the resulting string should never be zero. + // PcdMaximumUnicodeStringLength is tested inside StrLen(). + // + ASSERT (StrSize (Destination) != 0); + return Destination; +} + +/** + Concatenates one Null-terminated Unicode string with a maximum length to the + end of another Null-terminated Unicode string, and returns the concatenated + Unicode string. + + This function concatenates two Null-terminated Unicode strings. The contents + of Null-terminated Unicode string Source are concatenated to the end of + Null-terminated Unicode string Destination, and Destination is returned. At + most, Length Unicode characters are concatenated from Source to the end of + Destination, and Destination is always Null-terminated. If Length is 0, then + Destination is returned unmodified. If Source and Destination overlap, then + the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Destination contains more + than PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Source contains more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and concatenating Destination + and Source results in a Unicode string with more than + PcdMaximumUnicodeStringLength Unicode characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated Unicode string. + @param Source Pointer to a Null-terminated Unicode string. + @param Length Maximum number of Unicode characters to concatenate from + Source. + + @return Destination + +**/ +CHAR16 * +EFIAPI +StrnCat ( + IN OUT CHAR16 *Destination, + IN CONST CHAR16 *Source, + IN UINTN Length + ) +{ + StrnCpy (Destination + StrLen (Destination), Source, Length); + + // + // Size of the resulting string should never be zero. + // PcdMaximumUnicodeStringLength is tested inside StrLen(). + // + ASSERT (StrSize (Destination) != 0); + return Destination; +} + +/** + Copies one Null-terminated ASCII string to another Null-terminated ASCII + string and returns the new ASCII string. + + This function copies the contents of the ASCII string Source to the ASCII + string Destination, and returns Destination. If Source and Destination + overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated ASCII string. + @param Source Pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ) +{ + CHAR8 *ReturnValue; + + // + // Destination cannot be NULL + // + ASSERT (Destination != NULL); + + // + // Destination and source cannot overlap + // + ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source)); + ASSERT ((UINTN)(Source - Destination) > AsciiStrLen (Source)); + + ReturnValue = Destination; + while (*Source) { + *(Destination++) = *(Source++); + } + *Destination = 0; + return ReturnValue; +} + +/** + Copies one Null-terminated ASCII string with a maximum length to another + Null-terminated ASCII string with a maximum length and returns the new ASCII + string. + + This function copies the contents of the ASCII string Source to the ASCII + string Destination, and returns Destination. At most, Length ASCII characters + are copied from Source to Destination. If Length is 0, then Destination is + returned unmodified. If Length is greater that the number of ASCII characters + in Source, then Destination is padded with Null ASCII characters. If Source + and Destination overlap, then the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated ASCII string. + @param Source Pointer to a Null-terminated ASCII string. + @param Length Maximum number of ASCII characters to copy. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrnCpy ( + OUT CHAR8 *Destination, + IN CONST CHAR8 *Source, + IN UINTN Length + ) +{ + CHAR8 *ReturnValue; + + if (Length == 0) { + return Destination; + } + + // + // Destination cannot be NULL + // + ASSERT (Destination != NULL); + + // + // Destination and source cannot overlap + // + ASSERT ((UINTN)(Destination - Source) > AsciiStrLen (Source)); + ASSERT ((UINTN)(Source - Destination) >= Length); + + ReturnValue = Destination; + + while (*Source && Length > 1) { + *(Destination++) = *(Source++); + Length--; + } + + ZeroMem (Destination, Length * sizeof (*Destination)); + return ReturnValue; +} + +/** + Returns the length of a Null-terminated ASCII string. + + This function returns the number of ASCII characters in the Null-terminated + ASCII string specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param String Pointer to a Null-terminated ASCII string. + + @return The length of String. + +**/ +UINTN +EFIAPI +AsciiStrLen ( + IN CONST CHAR8 *String + ) +{ + UINTN Length; + + ASSERT (String != NULL); + + for (Length = 0; *String != '\0'; String++, Length++) { + // + // If PcdMaximumUnicodeStringLength is not zero, + // length should not more than PcdMaximumUnicodeStringLength + // + if (FixedPcdGet32 (PcdMaximumAsciiStringLength) != 0) { + ASSERT (Length < FixedPcdGet32 (PcdMaximumAsciiStringLength)); + } + } + return Length; +} + +/** + Returns the size of a Null-terminated ASCII string in bytes, including the + Null terminator. + + This function returns the size, in bytes, of the Null-terminated ASCII string + specified by String. + + If String is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and String contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param String Pointer to a Null-terminated ASCII string. + + @return The size of String. + +**/ +UINTN +EFIAPI +AsciiStrSize ( + IN CONST CHAR8 *String + ) +{ + return (AsciiStrLen (String) + 1) * sizeof (*String); +} + +/** + Compares two Null-terminated ASCII strings, and returns the difference + between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. If FirstString is identical to + SecondString, then 0 is returned. Otherwise, the value returned is the first + mismatched ASCII character in SecondString subtracted from the first + mismatched ASCII character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param FirstString Pointer to a Null-terminated ASCII string. + @param SecondString Pointer to a Null-terminated ASCII string. + + @retval 0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ) +{ + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (FirstString)); + ASSERT (AsciiStrSize (SecondString)); + + while ((*FirstString != '\0') && (*FirstString == *SecondString)) { + FirstString++; + SecondString++; + } + + return *FirstString - *SecondString; +} + +STATIC +CHAR8 +EFIAPI +AsciiToUpper ( + IN CHAR8 Chr + ) +{ + return (Chr >= 'a' && Chr <= 'z') ? Chr - ('a' - 'A') : Chr; +} + +/** + Performs a case insensitive comparison of two Null-terminated ASCII strings, + and returns the difference between the first mismatched ASCII characters. + + This function performs a case insensitive comparison of the Null-terminated + ASCII string FirstString to the Null-terminated ASCII string SecondString. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched lower case ASCII character in + SecondString subtracted from the first mismatched lower case ASCII character + in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param FirstString Pointer to a Null-terminated ASCII string. + @param SecondString Pointer to a Null-terminated ASCII string. + + @retval 0 FirstString is identical to SecondString using case insensitive + comparisons. + @retval !=0 FirstString is not identical to SecondString using case + insensitive comparisons. + +**/ +INTN +EFIAPI +AsciiStriCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString + ) +{ + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (FirstString)); + ASSERT (AsciiStrSize (SecondString)); + + while ((*FirstString != '\0') && + (AsciiToUpper (*FirstString) == AsciiToUpper (*SecondString))) { + FirstString++; + SecondString++; + } + + return AsciiToUpper (*FirstString) - AsciiToUpper (*SecondString); +} + +/** + Compares two Null-terminated ASCII strings with maximum lengths, and returns + the difference between the first mismatched ASCII characters. + + This function compares the Null-terminated ASCII string FirstString to the + Null-terminated ASCII string SecondString. At most, Length ASCII characters + will be compared. If Length is 0, then 0 is returned. If FirstString is + identical to SecondString, then 0 is returned. Otherwise, the value returned + is the first mismatched ASCII character in SecondString subtracted from the + first mismatched ASCII character in FirstString. + + If FirstString is NULL, then ASSERT(). + If SecondString is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and FirstString contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and SecondString contains more + than PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + + @param FirstString Pointer to a Null-terminated ASCII string. + @param SecondString Pointer to a Null-terminated ASCII string. + + @retval 0 FirstString is identical to SecondString. + @retval !=0 FirstString is not identical to SecondString. + +**/ +INTN +EFIAPI +AsciiStrnCmp ( + IN CONST CHAR8 *FirstString, + IN CONST CHAR8 *SecondString, + IN UINTN Length + ) +{ + // + // ASSERT both strings are less long than PcdMaximumAsciiStringLength + // + ASSERT (AsciiStrSize (FirstString)); + ASSERT (AsciiStrSize (SecondString)); + + while ((*FirstString != '\0') && + (*FirstString != *SecondString) && + (Length > 1)) { + FirstString++; + SecondString++; + Length--; + } + return *FirstString - *SecondString; +} + +/** + Concatenates one Null-terminated ASCII string to another Null-terminated + ASCII string, and returns the concatenated ASCII string. + + This function concatenates two Null-terminated ASCII strings. The contents of + Null-terminated ASCII string Source are concatenated to the end of Null- + terminated ASCII string Destination. The Null-terminated concatenated ASCII + String is returned. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Destination contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero and concatenating Destination and + Source results in a ASCII string with more than PcdMaximumAsciiStringLength + ASCII characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated ASCII string. + @param Source Pointer to a Null-terminated ASCII string. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source + ) +{ + AsciiStrCpy (Destination + AsciiStrLen (Destination), Source); + + // + // Size of the resulting string should never be zero. + // PcdMaximumUnicodeStringLength is tested inside StrLen(). + // + ASSERT (AsciiStrSize (Destination) != 0); + return Destination; +} + +/** + Concatenates one Null-terminated ASCII string with a maximum length to the + end of another Null-terminated ASCII string, and returns the concatenated + ASCII string. + + This function concatenates two Null-terminated ASCII strings. The contents + of Null-terminated ASCII string Source are concatenated to the end of Null- + terminated ASCII string Destination, and Destination is returned. At most, + Length ASCII characters are concatenated from Source to the end of + Destination, and Destination is always Null-terminated. If Length is 0, then + Destination is returned unmodified. If Source and Destination overlap, then + the results are undefined. + + If Destination is NULL, then ASSERT(). + If Source is NULL, then ASSERT(). + If Source and Destination overlap, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Destination contains more + than PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and Source contains more than + PcdMaximumAsciiStringLength ASCII characters, then ASSERT(). + If PcdMaximumAsciiStringLength is not zero, and concatenating Destination and + Source results in a ASCII string with more than PcdMaximumAsciiStringLength + ASCII characters, then ASSERT(). + + @param Destination Pointer to a Null-terminated ASCII string. + @param Source Pointer to a Null-terminated ASCII string. + @param Length Maximum number of ASCII characters to concatenate from + Source. + + @return Destination + +**/ +CHAR8 * +EFIAPI +AsciiStrnCat ( + IN OUT CHAR8 *Destination, + IN CONST CHAR8 *Source, + IN UINTN Length + ) +{ + AsciiStrnCpy (Destination + AsciiStrLen (Destination), Source, Length); + + // + // Size of the resulting string should never be zero. + // PcdMaximumUnicodeStringLength is tested inside StrLen(). + // + ASSERT (AsciiStrSize (Destination) != 0); + return Destination; +} diff --git a/MdePkg/Library/BaseLib/SwapBytes16.c b/MdePkg/Library/BaseLib/SwapBytes16.c new file mode 100644 index 0000000000..c8460a28f7 --- /dev/null +++ b/MdePkg/Library/BaseLib/SwapBytes16.c @@ -0,0 +1,36 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Switches the endianess of a 16-bit integer. + + This function swaps the bytes in a 16-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Operand A 16-bit unsigned value. + + @return The byte swaped Operand. + +**/ +UINT16 +EFIAPI +SwapBytes16 ( + IN UINT16 Operand + ) +{ + return (Operand << 8) | (Operand >> 8); +} diff --git a/MdePkg/Library/BaseLib/SwapBytes32.c b/MdePkg/Library/BaseLib/SwapBytes32.c new file mode 100644 index 0000000000..4e683b09d1 --- /dev/null +++ b/MdePkg/Library/BaseLib/SwapBytes32.c @@ -0,0 +1,39 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Switches the endianess of a 32-bit integer. + + This function swaps the bytes in a 32-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Operand A 32-bit unsigned value. + + @return The byte swaped Operand. + +**/ +UINT32 +EFIAPI +SwapBytes32 ( + IN UINT32 Operand + ) +{ + return (UINT32)( + ((UINT32)SwapBytes16 ((UINT16)Operand) << 16) | + ((UINT32)SwapBytes16 ((UINT16)(Operand >> 16))) + ); +} diff --git a/MdePkg/Library/BaseLib/SwapBytes64.c b/MdePkg/Library/BaseLib/SwapBytes64.c new file mode 100644 index 0000000000..1b0882fc9a --- /dev/null +++ b/MdePkg/Library/BaseLib/SwapBytes64.c @@ -0,0 +1,36 @@ +/** @file + Math worker functions. + + Copyright (c) 2006, 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. + +**/ + +#include "BaseLibInternals.h" + +/** + Switches the endianess of a 64-bit integer. + + This function swaps the bytes in a 64-bit unsigned value to switch the value + from little endian to big endian or vice versa. The byte swapped value is + returned. + + @param Operand A 64-bit unsigned value. + + @return The byte swaped Operand. + +**/ +UINT64 +EFIAPI +SwapBytes64 ( + IN UINT64 Operand + ) +{ + return InternalMathSwapBytes64 (Operand); +} diff --git a/MdePkg/Library/BaseLib/SwitchStack.c b/MdePkg/Library/BaseLib/SwitchStack.c new file mode 100644 index 0000000000..73b8edb1af --- /dev/null +++ b/MdePkg/Library/BaseLib/SwitchStack.c @@ -0,0 +1,52 @@ +/** @file + Switch Stack functions. + + Copyright (c) 2006, 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. + + Module Name: SwitchStack.c + +**/ + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + +**/ +VOID +EFIAPI +SwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + // + // This version of this function does not actually change the stack pointer + // This is to support compilation of CPU types that do not support assemblers + // such as EBC + // + EntryPoint (Context1, Context2); +} diff --git a/MdePkg/Library/BaseLib/Synchronization.c b/MdePkg/Library/BaseLib/Synchronization.c new file mode 100644 index 0000000000..df395869a2 --- /dev/null +++ b/MdePkg/Library/BaseLib/Synchronization.c @@ -0,0 +1,353 @@ +/** @file + Implementation of synchronization functions. + + Copyright (c) 2006, 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. + + Module Name: Synchronization.c + +**/ + +#define SPIN_LOCK_RELEASED ((SPIN_LOCK)0) +#define SPIN_LOCK_ACQUIRED ((SPIN_LOCK)-1) + +UINT32 +EFIAPI +InternalSyncIncrement ( + IN volatile UINT32 *Value + ); + +UINT32 +EFIAPI +InternalSyncDecrement ( + IN volatile UINT32 *Value + ); + +UINT32 +EFIAPI +InternalSyncCompareExchange32 ( + IN volatile UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ); + +UINT64 +EFIAPI +InternalSyncCompareExchange64 ( + IN volatile UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ); + +/** + Retrieves the architecture specific spin lock alignment requirements for + optimal spin lock performance. + + This function retrieves the spin lock alignment requirements for optimal + performance on a given CPU architecture. The spin lock alignment must be a + power of two and is returned by this function. If there are no alignment + requirements, then 1 must be returned. The spin lock synchronization + functions must function correctly if the spin lock size and alignment values + returned by this function are not used at all. These values are hints to the + consumers of the spin lock synchronization functions to obtain optimal spin + lock performance. + + @return The architecture specific spin lock alignment. + +**/ +UINTN +EFIAPI +GetSpinLockProperties ( + VOID + ) +{ + // @bug May use a PCD entry to determine this alignment. + return 32; +} + +/** + Initializes a spin lock to the released state and returns the spin lock. + + This function initializes the spin lock specified by SpinLock to the released + state, and returns SpinLock. Optimal performance can be achieved by calling + GetSpinLockProperties() to determine the size and alignment requirements for + SpinLock. + + If SpinLock is NULL, then ASSERT(). + + @param SpinLock A pointer to the spin lock to initialize to the released + state. + + @return SpinLock + +**/ +SPIN_LOCK * +EFIAPI +InitializeSpinLock ( + OUT SPIN_LOCK *SpinLock + ) +{ + ASSERT (SpinLock != NULL); + *SpinLock = 0; + return SpinLock; +} + +/** + Waits until a spin lock can be placed in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns SpinLock. Otherwise, this function waits + indefinitely for the spin lock to be released, and then places it in the + acquired state and returns SpinLock. All state transitions of SpinLock must + be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + If PcdSpinLockTimeout is not zero, and SpinLock is can not be acquired in + PcdSpinLockTimeout microseconds, then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @return SpinLock + +**/ +SPIN_LOCK * +EFIAPI +AcquireSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + UINT64 Tick; + UINT64 Start, End; + UINT64 Timeout; + + Tick = 0; + Start = 0; + End = 0; + if (FixedPcdGet32 (PcdSpinLockTimeout) > 0) { + Tick = GetPerformanceCounter (); + Timeout = DivU64x32 ( + MultU64x32 ( + GetPerformanceCounterProperties (&Start, &End), + FixedPcdGet32 (PcdSpinLockTimeout) + ), + 1000000 + ); + if (Start < End) { + Tick += Timeout; + } else { + Tick -= Timeout; + } + } + + while (!AcquireSpinLockOrFail (SpinLock)) { + CpuPause (); + ASSERT ((Start < End) ^ (Tick <= GetPerformanceCounter ())); + } + return SpinLock; +} + +/** + Attempts to place a spin lock in the acquired state. + + This function checks the state of the spin lock specified by SpinLock. If + SpinLock is in the released state, then this function places SpinLock in the + acquired state and returns TRUE. Otherwise, FALSE is returned. All state + transitions of SpinLock must be performed using MP safe mechanisms. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to place in the acquired state. + + @retval TRUE SpinLock was placed in the acquired state. + @retval FALSE SpinLock could not be acquired. + +**/ +BOOLEAN +EFIAPI +AcquireSpinLockOrFail ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + ASSERT (SpinLock != NULL); + return (BOOLEAN)( + InterlockedCompareExchangePointer ( + (VOID**)SpinLock, + (VOID*)SPIN_LOCK_RELEASED, + (VOID*)SPIN_LOCK_ACQUIRED + ) == (VOID*)SPIN_LOCK_RELEASED + ); +} + +/** + Releases a spin lock. + + This function places the spin lock specified by SpinLock in the release state + and returns SpinLock. + + If SpinLock is NULL, then ASSERT(). + If SpinLock was not initialized with InitializeSpinLock(), then ASSERT(). + + @param SpinLock A pointer to the spin lock to release. + + @return SpinLock + +**/ +SPIN_LOCK * +EFIAPI +ReleaseSpinLock ( + IN OUT SPIN_LOCK *SpinLock + ) +{ + ASSERT (SpinLock != NULL); + *SpinLock = 0; + return SpinLock; +} + +/** + Performs an atomic increment of an 32-bit unsigned integer. + + Performs an atomic increment of the 32-bit unsigned integer specified by + Value and returns the incremented value. The increment operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to increment. + + @return The incremented value. + +**/ +UINT32 +EFIAPI +InterlockedIncrement ( + IN UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncIncrement (Value); +} + +/** + Performs an atomic decrement of an 32-bit unsigned integer. + + Performs an atomic decrement of the 32-bit unsigned integer specified by + Value and returns the decremented value. The decrement operation must be + performed using MP safe mechanisms. The state of the return value is not + guaranteed to be MP safe. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the 32-bit value to decrement. + + @return The decremented value. + +**/ +UINT32 +EFIAPI +InterlockedDecrement ( + IN UINT32 *Value + ) +{ + ASSERT (Value != NULL); + return InternalSyncDecrement (Value); +} + +/** + Performs an atomic compare exchange operation on a 32-bit unsigned integer. + + @param Value A pointer to the 32-bit value for the compare exchange + operation. + @param CompareValue 32-bit value used in compare operation. + @param ExchangeValue 32-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT32 +EFIAPI +InterlockedCompareExchange32 ( + IN UINT32 *Value, + IN UINT32 CompareValue, + IN UINT32 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange32 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a 64-bit unsigned integer. + + @param Value A pointer to the 64-bit value for the compare exchange + operation. + @param CompareValue 64-bit value used in compare operation. + @param ExchangeValue 64-bit value used in exchange operation. + + @return The original *Value before exchange. + +**/ +UINT64 +EFIAPI +InterlockedCompareExchange64 ( + IN UINT64 *Value, + IN UINT64 CompareValue, + IN UINT64 ExchangeValue + ) +{ + ASSERT (Value != NULL); + return InternalSyncCompareExchange64 (Value, CompareValue, ExchangeValue); +} + +/** + Performs an atomic compare exchange operation on a pointer value. + + Performs an atomic compare exchange operation on the pointer value specified + by Value. If Value is equal to CompareValue, then Value is set to + ExchangeValue and CompareValue is returned. If Value is not equal to + CompareValue, then Value is returned. The compare exchange operation must be + performed using MP safe mechanisms. + + If Value is NULL, then ASSERT(). + + @param Value A pointer to the pointer value for the compare exchange + operation. + @param CompareValue Pointer value used in compare operation. + @param ExchangeValue Pointer value used in exchange operation. + +**/ +VOID * +EFIAPI +InterlockedCompareExchangePointer ( + IN VOID **Value, + IN VOID *CompareValue, + IN VOID *ExchangeValue + ) +{ + switch (sizeof (*Value)) { + case sizeof (UINT32): + return (VOID*)(UINTN)InterlockedCompareExchange32 ( + (UINT32*)Value, + (UINT32)(UINTN)CompareValue, + (UINT32)(UINTN)ExchangeValue + ); + case sizeof (UINT64): + return (VOID*)(UINTN)InterlockedCompareExchange64 ( + (UINT64*)Value, + (UINT64)(UINTN)CompareValue, + (UINT64)(UINTN)ExchangeValue + ); + default: + ASSERT (FALSE); + return NULL; + } +} diff --git a/MdePkg/Library/BaseLib/Unaligned.c b/MdePkg/Library/BaseLib/Unaligned.c new file mode 100644 index 0000000000..9d0521e595 --- /dev/null +++ b/MdePkg/Library/BaseLib/Unaligned.c @@ -0,0 +1,203 @@ +/** @file + Unaligned access functions of BaseLib. + + Copyright (c) 2006, 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. + + Module Name: Unaligned.c + +**/ + +/** + Reads a 16-bit value from memory that may be unaligned. + + This function returns the 16-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 16-bit value that may be unaligned. + + @return *Uint16 + +**/ +UINT16 +EFIAPI +ReadUnaligned16 ( + IN CONST UINT16 *Buffer + ) +{ + return *Buffer; +} + +/** + Writes a 16-bit value to memory that may be unaligned. + + This function writes the 16-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 16-bit value that may be unaligned. + @param Value 16-bit value to write to Buffer. + + @return Value + +**/ +UINT16 +EFIAPI +WriteUnaligned16 ( + OUT UINT16 *Buffer, + IN UINT16 Value + ) +{ + return *Buffer = Value; +} + +/** + Reads a 24-bit value from memory that may be unaligned. + + This function returns the 24-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 24-bit value that may be unaligned. + + @return The value read. + +**/ +UINT32 +EFIAPI +ReadUnaligned24 ( + IN CONST UINT32 *Buffer + ) +{ + return *Buffer & 0xffffff; +} + +/** + Writes a 24-bit value to memory that may be unaligned. + + This function writes the 24-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 24-bit value that may be unaligned. + @param Value 24-bit value to write to Buffer. + + @return The value written. + +**/ +UINT32 +EFIAPI +WriteUnaligned24 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ) +{ + return *Buffer = BitFieldWrite32 (*Buffer, 0, 23, Value); +} + +/** + Reads a 32-bit value from memory that may be unaligned. + + This function returns the 32-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 32-bit value that may be unaligned. + + @return *Uint32 + +**/ +UINT32 +EFIAPI +ReadUnaligned32 ( + IN CONST UINT32 *Buffer + ) +{ + return *Buffer; +} + +/** + Writes a 32-bit value to memory that may be unaligned. + + This function writes the 32-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 32-bit value that may be unaligned. + @param Value 32-bit value to write to Buffer. + + @return Value + +**/ +UINT32 +EFIAPI +WriteUnaligned32 ( + OUT UINT32 *Buffer, + IN UINT32 Value + ) +{ + return *Buffer = Value; +} + +/** + Reads a 64-bit value from memory that may be unaligned. + + This function returns the 64-bit value pointed to by Buffer. The function + guarantees that the read operation does not produce an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 64-bit value that may be unaligned. + + @return *Uint64 + +**/ +UINT64 +EFIAPI +ReadUnaligned64 ( + IN CONST UINT64 *Buffer + ) +{ + return *Buffer; +} + +/** + Writes a 64-bit value to memory that may be unaligned. + + This function writes the 64-bit value specified by Value to Buffer. Value is + returned. The function guarantees that the write operation does not produce + an alignment fault. + + If the Buffer is NULL, then ASSERT(). + + @param Buffer Pointer to a 64-bit value that may be unaligned. + @param Value 64-bit value to write to Buffer. + + @return Value + +**/ +UINT64 +EFIAPI +WriteUnaligned64 ( + OUT UINT64 *Buffer, + IN UINT64 Value + ) +{ + return *Buffer = Value; +} diff --git a/MdePkg/Library/BaseLib/build.xml b/MdePkg/Library/BaseLib/build.xml new file mode 100644 index 0000000000..7533da8ddc --- /dev/null +++ b/MdePkg/Library/BaseLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseLib/ia32/ARShiftU64.asm b/MdePkg/Library/BaseLib/ia32/ARShiftU64.asm new file mode 100644 index 0000000000..6b9cfa18a8 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ARShiftU64.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ARShiftU64.asm +; +; Abstract: +; +; 64-bit arithmetic right shift function for IA-32 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMathARShiftU64 PROC + mov cl, [esp + 12] + mov eax, [esp + 8] + cdq + test cl, 32 + cmovz edx, eax + cmovz eax, [esp + 4] + shrd eax, edx, cl + sar edx, cl + ret +InternalMathARShiftU64 ENDP + + END \ No newline at end of file diff --git a/MdePkg/Library/BaseLib/ia32/ARShiftU64.s b/MdePkg/Library/BaseLib/ia32/ARShiftU64.s new file mode 100644 index 0000000000..d6af974d0f --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ARShiftU64.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ARShiftU64.asm +# +# Abstract: +# +# 64-bit arithmetic right shift function for IA-32 +# +#------------------------------------------------------------------------------ + + + + + +.global _ARShiftU64 +_ARShiftU64: + movb 12(%esp),%cl + movl 8(%esp),%eax + cltd + testb $32,%cl +# MISMATCH: " cmovz edx, eax" + cmovz %eax, %edx +# MISMATCH: " cmovz eax, [esp + 4]" + cmovz 4(%esp), %eax + shrdl %cl,%edx,%eax + sar %cl,%edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/CpuBreakpoint.asm b/MdePkg/Library/BaseLib/ia32/CpuBreakpoint.asm new file mode 100644 index 0000000000..a4d397874d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/CpuBreakpoint.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuBreakpoint.Asm +; +; Abstract: +; +; CpuBreakpoint function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuBreakpoint ( +; VOID +; ); +;------------------------------------------------------------------------------ +_CpuBreakpoint PROC + int 3 + ret +_CpuBreakpoint ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/CpuBreakpoint.s b/MdePkg/Library/BaseLib/ia32/CpuBreakpoint.s new file mode 100644 index 0000000000..e5d18c35b3 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/CpuBreakpoint.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ ; +# Copyright (c) 2006, 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. +# +# Module Name: +# +# CpuBreakpoint.s +# +# Abstract: +# +# CpuBreakpoint function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# CpuBreakpoint ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _CpuBreakpoint +_CpuBreakpoint: + int 3 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/CpuFlushTlb.asm b/MdePkg/Library/BaseLib/ia32/CpuFlushTlb.asm new file mode 100644 index 0000000000..de87ad75e9 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/CpuFlushTlb.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuFlushTlb.Asm +; +; Abstract: +; +; CpuFlushTlb function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuFlushTlb ( +; VOID +; ); +;------------------------------------------------------------------------------ +_CpuFlushTlb PROC + mov eax, cr3 + mov cr3, eax + ret +_CpuFlushTlb ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/CpuFlushTlb.s b/MdePkg/Library/BaseLib/ia32/CpuFlushTlb.s new file mode 100644 index 0000000000..1d85fa77da --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/CpuFlushTlb.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ ; +# Copyright (c) 2006, 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. +# +# Module Name: +# +# CpuFlushTlb.Asm +# +# Abstract: +# +# CpuFlushTlb function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# CpuFlushTlb ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _CpuFlushTlb +_CpuFlushTlb: + movl %cr3, %eax + movl %eax, %cr3 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/CpuId.asm b/MdePkg/Library/BaseLib/ia32/CpuId.asm new file mode 100644 index 0000000000..2c94e3a1ae --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/CpuId.asm @@ -0,0 +1,66 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuId.Asm +; +; Abstract: +; +; AsmCpuid function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat,C + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmCpuid ( +; IN UINT32 RegisterInEax, +; OUT UINT32 *RegisterOutEax OPTIONAL, +; OUT UINT32 *RegisterOutEbx OPTIONAL, +; OUT UINT32 *RegisterOutEcx OPTIONAL, +; OUT UINT32 *RegisterOutEdx OPTIONAL +; ) +;------------------------------------------------------------------------------ +AsmCpuid PROC USES ebx + push ebp + mov ebp, esp + mov eax, [ebp + 12] + cpuid + push ecx + mov ecx, [ebp + 16] + jecxz @F + mov [ecx], eax +@@: + mov ecx, [ebp + 20] + jecxz @F + mov [ecx], ebx +@@: + mov ecx, [ebp + 24] + jecxz @F + pop [ecx] +@@: + mov ecx, [ebp + 28] + jecxz @F + mov [ecx], edx +@@: + mov eax, [ebp + 12] + leave + ret +AsmCpuid ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/CpuId.s b/MdePkg/Library/BaseLib/ia32/CpuId.s new file mode 100644 index 0000000000..989daba127 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/CpuId.s @@ -0,0 +1,63 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# CpuId.Asm +# +# Abstract: +# +# AsmCpuid function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmCpuid ( +# IN UINT32 RegisterInEax, +# OUT UINT32 *RegisterOutEax OPTIONAL, +# OUT UINT32 *RegisterOutEbx OPTIONAL, +# OUT UINT32 *RegisterOutEcx OPTIONAL, +# OUT UINT32 *RegisterOutEdx OPTIONAL +# ) +#------------------------------------------------------------------------------ +.globl _AsmCpuid +_AsmCpuid: + push %ebx + push %edi + movl 12(%esp),%eax + cpuid + movl %ecx,%edi + movl 16(%esp),%ecx + jecxz L1 + movl %eax,(%ecx) +L1: + movl 20(%esp),%ecx + jecxz L2 + movl %ebx,(%ecx) +L2: + movl 24(%esp),%ecx + jecxz L3 + movl %edi,(%ecx) +L3: + movl 28(%esp),%ecx + jecxz L4 + movl %edx,(%ecx) +L4: + pop %edi + pop %ebx + ret diff --git a/MdePkg/Library/BaseLib/ia32/CpuPause.asm b/MdePkg/Library/BaseLib/ia32/CpuPause.asm new file mode 100644 index 0000000000..79a4f2f67b --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/CpuPause.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuPause.Asm +; +; Abstract: +; +; CpuPause function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuPause ( +; VOID +; ); +;------------------------------------------------------------------------------ +_CpuPause PROC + pause + ret +_CpuPause ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/CpuPause.s b/MdePkg/Library/BaseLib/ia32/CpuPause.s new file mode 100644 index 0000000000..ace2c6764a --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/CpuPause.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ ; +# Copyright (c) 2006, 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. +# +# Module Name: +# +# CpuPause.Asm +# +# Abstract: +# +# CpuPause function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# CpuPause ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _CpuPause +_CpuPause: + pause + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/CpuSleep.asm b/MdePkg/Library/BaseLib/ia32/CpuSleep.asm new file mode 100644 index 0000000000..66fb90e903 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/CpuSleep.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuSleep.Asm +; +; Abstract: +; +; CpuSleep function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuSleep ( +; VOID +; ); +;------------------------------------------------------------------------------ +_CpuSleep PROC + hlt + ret +_CpuSleep ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/CpuSleep.s b/MdePkg/Library/BaseLib/ia32/CpuSleep.s new file mode 100644 index 0000000000..9b7713128f --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/CpuSleep.s @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------------ ; +# Copyright (c) 2006, 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. +# +# Module Name: +# +# CpuSleep.Asm +# +# Abstract: +# +# CpuSleep function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# CpuSleep ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _CpuSleep +_CpuSleep: + hlt + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/DisableInterrupts.asm b/MdePkg/Library/BaseLib/ia32/DisableInterrupts.asm new file mode 100644 index 0000000000..74bdd0bd98 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DisableInterrupts.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; DisableInterrupts.Asm +; +; Abstract: +; +; DisableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; DisableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +_DisableInterrupts PROC + cli + ret +_DisableInterrupts ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/DisableInterrupts.s b/MdePkg/Library/BaseLib/ia32/DisableInterrupts.s new file mode 100644 index 0000000000..cc9c95c30f --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DisableInterrupts.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# DisableInterrupts.Asm +# +# Abstract: +# +# DisableInterrupts function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# DisableInterrupts ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _DisableInterrupts +_DisableInterrupts: + cli + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/DisablePaging32.asm b/MdePkg/Library/BaseLib/ia32/DisablePaging32.asm new file mode 100644 index 0000000000..04ae8cf514 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DisablePaging32.asm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; DisablePaging32.Asm +; +; Abstract: +; +; AsmDisablePaging32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86DisablePaging32 ( +; IN SWITCH_STACK_ENTRY_POINT EntryPoint, +; IN VOID *Context1, OPTIONAL +; IN VOID *Context2, OPTIONAL +; IN VOID *NewStack +; ); +;------------------------------------------------------------------------------ +InternalX86DisablePaging32 PROC + mov ebx, [esp + 4] + mov ecx, [esp + 8] + mov edx, [esp + 12] + pushfd + pop edi + cli + mov eax, cr0 + btr eax, 31 + mov esp, [esp + 16] + mov cr0, eax + push edi + popfd + push edx + push ecx + call ebx + jmp $ +InternalX86DisablePaging32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/DisablePaging32.s b/MdePkg/Library/BaseLib/ia32/DisablePaging32.s new file mode 100644 index 0000000000..21e8a82c0e --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DisablePaging32.s @@ -0,0 +1,58 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# DisablePaging32.Asm +# +# Abstract: +# +# AsmDisablePaging32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmDisablePaging32 ( +# IN SWITCH_STACK_ENTRY_POINT EntryPoint, +# IN VOID *Context1, OPTIONAL +# IN VOID *Context2, OPTIONAL +# IN VOID *NewStack +# ); +#------------------------------------------------------------------------------ +.global _AsmDisablePaging32 +_AsmDisablePaging32: + movl 4(%esp),%ebx + movl 8(%esp),%ecx + movl 12(%esp),%edx + pushfl + popl %edi + cli + movl %cr0, %eax + btrl $31,%eax + movl 16(%esp),%esp + movl %eax, %cr0 + pushl %edi + popfl + pushl %edx + pushl %ecx + call *%ebx + jmp . + + + diff --git a/MdePkg/Library/BaseLib/ia32/DivS64x64Remainder.c b/MdePkg/Library/BaseLib/ia32/DivS64x64Remainder.c new file mode 100644 index 0000000000..219f48f321 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DivS64x64Remainder.c @@ -0,0 +1,38 @@ +/** @file + Integer division worker functions for Ia32. + + Copyright (c) 2006, 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. + + Module Name: DivS64x64Remainder.c + +**/ + +#include "../BaseLibInternals.h" + +INT64 +EFIAPI +InternalMathDivRemS64x64 ( + IN INT64 Dividend, + IN INT64 Divisor, + OUT INT64 *Remainder + ) +{ + INT64 Quot; + + Quot = InternalMathDivRemU64x64 ( + Dividend >= 0 ? Dividend : -Dividend, + Divisor >= 0 ? Divisor : -Divisor, + (UINT64 *) Remainder + ); + if (Remainder != NULL && Dividend < 0) { + *Remainder = -*Remainder; + } + return (Dividend ^ Divisor) >= 0 ? Quot : -Quot; +} diff --git a/MdePkg/Library/BaseLib/ia32/DivU64x32.asm b/MdePkg/Library/BaseLib/ia32/DivU64x32.asm new file mode 100644 index 0000000000..1ad5474586 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DivU64x32.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; DivU64x32.asm +; +; Abstract: +; +; Calculate the quotient of a 64-bit integer by a 32-bit integer +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMathDivU64x32 PROC + mov eax, [esp + 8] + mov ecx, [esp + 12] + xor edx, edx + div ecx + push eax + mov eax, [esp + 8] + div ecx + pop edx + ret +InternalMathDivU64x32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/DivU64x32.s b/MdePkg/Library/BaseLib/ia32/DivU64x32.s new file mode 100644 index 0000000000..689c7092c0 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DivU64x32.s @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# DivU64x32.asm +# +# Abstract: +# +# Calculate the quotient of a 64-bit integer by a 32-bit integer +# +#------------------------------------------------------------------------------ + + + + + +.global _DivU64x32 +_DivU64x32: + movl 8(%esp),%eax + movl 12(%esp),%ecx + xorl %edx,%edx + divl %ecx + pushl %eax + movl 8(%esp),%eax + divl %ecx + popl %edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/DivU64x32Remainder.asm b/MdePkg/Library/BaseLib/ia32/DivU64x32Remainder.asm new file mode 100644 index 0000000000..f1c6c1f4ac --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DivU64x32Remainder.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; DivError.asm +; +; Abstract: +; +; Set error flag for all division functions +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMathDivRemU64x32 PROC + mov ecx, [esp + 12] + mov eax, [esp + 8] + xor edx, edx + div ecx + push eax + mov eax, [esp + 8] + div ecx + mov ecx, [esp + 20] + jecxz @F + mov [ecx], edx +@@: + pop edx + ret +InternalMathDivRemU64x32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/DivU64x32Remainder.s b/MdePkg/Library/BaseLib/ia32/DivU64x32Remainder.s new file mode 100644 index 0000000000..1f34f18255 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DivU64x32Remainder.s @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# DivError.asm +# +# Abstract: +# +# Set error flag for all division functions +# +#------------------------------------------------------------------------------ + + + + + +.global _InternalMathDivRemU64x32 +_InternalMathDivRemU64x32: + movl 12(%esp),%ecx + movl 8(%esp),%eax + xorl %edx,%edx + divl %ecx + pushl %eax + movl 8(%esp),%eax + divl %ecx + movl 20(%esp),%ecx + jecxz L1 + movl %edx,(%ecx) +L1: + popl %edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/DivU64x64Remainder.asm b/MdePkg/Library/BaseLib/ia32/DivU64x64Remainder.asm new file mode 100644 index 0000000000..261211b946 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DivU64x64Remainder.asm @@ -0,0 +1,83 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; DivU64x64Remainder.asm +; +; Abstract: +; +; Calculate the quotient of a 64-bit integer by a 64-bit integer and returns +; both the quotient and the remainder +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +EXTERN InternalMathDivRemU64x32:PROC + +InternalMathDivRemU64x64 PROC + mov ecx, [esp + 16] + test ecx, ecx + jnz _@DivRemU64x64 + mov ecx, [esp + 20] + jecxz @F + and dword ptr [ecx + 4], 0 + mov [esp + 16], ecx +@@: + jmp InternalMathDivRemU64x32 +InternalMathDivRemU64x64 ENDP + +_@DivRemU64x64 PROC USES ebx esi edi + mov edx, dword ptr [esp + 20] + mov eax, dword ptr [esp + 16] + mov edi, edx + mov esi, eax + mov ebx, dword ptr [esp + 24] +@@: + shr edx, 1 + rcr eax, 1 + shrd ebx, ecx, 1 + shr ecx, 1 + jnz @B + div ebx + mov ebx, eax + mov ecx, [esp + 28] + mul dword ptr [esp + 24] + imul ecx, ebx + add edx, ecx + mov ecx, dword ptr [esp + 32] + jc @TooLarge + cmp edi, edx + ja @Correct + jb @TooLarge + cmp esi, eax + jae @Correct +@TooLarge: + dec ebx + jecxz @Return + sub eax, dword ptr [esp + 24] + sbb edx, dword ptr [esp + 28] +@Correct: + jecxz @Return + sub esi, eax + sbb edi, edx + mov [ecx], esi + mov [ecx + 4], edi +@Return: + mov eax, ebx + xor edx, edx + ret +_@DivRemU64x64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/DivU64x64Remainder.s b/MdePkg/Library/BaseLib/ia32/DivU64x64Remainder.s new file mode 100644 index 0000000000..f604f7c72e --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/DivU64x64Remainder.s @@ -0,0 +1,89 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# DivU64x64Remainder.asm +# +# Abstract: +# +# Calculate the quotient of a 64-bit integer by a 64-bit integer and returns +# both the quotient and the remainder +# +#------------------------------------------------------------------------------ + + + + + +.extern _InternalMathDivRemU64x32 + +.global _InternalMathDivRemU64x64 +_InternalMathDivRemU64x64: + movl 16(%esp),%ecx + testl %ecx,%ecx + jnz _DivRemU64x64 + movl 20(%esp),%ecx + jecxz L1 + and $0,4(%ecx) + movl %ecx,16(%esp) +L1: + jmp _InternalMathDivRemU64x32 + + +.global DivRemU64x64 +DivRemU64x64: +# MISMATCH: "DivRemU64x64: USES ebx esi edi" + push %ebx + push %esi + push %edi + mov 20(%esp), %edx + mov 16(%esp), %eax + movl %edx,%edi + movl %eax,%esi + mov 24(%esp), %ebx +L2: + shrl %edx + rcrl $1,%eax + shrdl $1,%ecx,%ebx + shrl %ecx + jnz L2 + divl %ebx + movl %eax,%ebx + movl 28(%esp),%ecx + mull 24(%esp) + imull %ebx,%ecx + addl %ecx,%edx + mov 32(%esp), %ecx + jc TooLarge + cmpl %edx,%edi + ja Correct + jb TooLarge + cmpl %eax,%esi + jae Correct +TooLarge: + decl %ebx + jecxz Return + sub 24(%esp), %eax + sbb 28(%esp), %edx +Correct: + jecxz Return + subl %eax,%esi + sbbl %edx,%edi + movl %esi,(%ecx) + movl %edi,4(%ecx) +Return: + movl %ebx,%eax + xorl %edx,%edx + push %edi + push %esi + push %ebx + ret diff --git a/MdePkg/Library/BaseLib/ia32/EnableDisableInterrupts.asm b/MdePkg/Library/BaseLib/ia32/EnableDisableInterrupts.asm new file mode 100644 index 0000000000..fe2016da87 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/EnableDisableInterrupts.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; EnableDisableInterrupts.Asm +; +; Abstract: +; +; EnableDisableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; EnableDisableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +_EnableDisableInterrupts PROC + sti + cli + ret +_EnableDisableInterrupts ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/EnableDisableInterrupts.s b/MdePkg/Library/BaseLib/ia32/EnableDisableInterrupts.s new file mode 100644 index 0000000000..80362a95b2 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/EnableDisableInterrupts.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# EnableDisableInterrupts.Asm +# +# Abstract: +# +# EnableDisableInterrupts function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# EnableDisableInterrupts ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _EnableDisableInterrupts +_EnableDisableInterrupts: + sti + cli + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/EnableInterrupts.asm b/MdePkg/Library/BaseLib/ia32/EnableInterrupts.asm new file mode 100644 index 0000000000..194dd8f935 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/EnableInterrupts.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; EnableInterrupts.Asm +; +; Abstract: +; +; EnableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; EnableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +_EnableInterrupts PROC + sti + ret +_EnableInterrupts ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/EnableInterrupts.s b/MdePkg/Library/BaseLib/ia32/EnableInterrupts.s new file mode 100644 index 0000000000..74413d83b6 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/EnableInterrupts.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# EnableInterrupts.Asm +# +# Abstract: +# +# EnableInterrupts function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# EnableInterrupts ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _EnableInterrupts +_EnableInterrupts: + sti + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/EnablePaging32.asm b/MdePkg/Library/BaseLib/ia32/EnablePaging32.asm new file mode 100644 index 0000000000..cf6f2fe458 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/EnablePaging32.asm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; EnablePaging32.Asm +; +; Abstract: +; +; AsmEnablePaging32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86EnablePaging32 ( +; IN SWITCH_STACK_ENTRY_POINT EntryPoint, +; IN VOID *Context1, OPTIONAL +; IN VOID *Context2, OPTIONAL +; IN VOID *NewStack +; ); +;------------------------------------------------------------------------------ +InternalX86EnablePaging32 PROC + mov ebx, [esp + 4] + mov ecx, [esp + 8] + mov edx, [esp + 12] + pushfd + pop edi + cli + mov eax, cr0 + bts eax, 31 + mov esp, [esp + 16] + mov cr0, eax + push edi + popfd + push edx + push ecx + call ebx + jmp $ +InternalX86EnablePaging32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/EnablePaging32.s b/MdePkg/Library/BaseLib/ia32/EnablePaging32.s new file mode 100644 index 0000000000..6f9befcb4a --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/EnablePaging32.s @@ -0,0 +1,58 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# EnablePaging32.Asm +# +# Abstract: +# +# AsmEnablePaging32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmEnablePaging32 ( +# IN SWITCH_STACK_ENTRY_POINT EntryPoint, +# IN VOID *Context1, OPTIONAL +# IN VOID *Context2, OPTIONAL +# IN VOID *NewStack +# ); +#------------------------------------------------------------------------------ +.global _AsmEnablePaging32 +_AsmEnablePaging32: + movl 4(%esp),%ebx + movl 8(%esp),%ecx + movl 12(%esp),%edx + pushfl + popl %edi + cli + movl %cr0, %eax + btsl $31,%eax + movl 16(%esp),%esp + movl %eax, %cr0 + pushl %edi + popfl + pushl %edx + pushl %ecx + call *%ebx + jmp . + + + diff --git a/MdePkg/Library/BaseLib/ia32/EnablePaging64.asm b/MdePkg/Library/BaseLib/ia32/EnablePaging64.asm new file mode 100644 index 0000000000..6c9b0ea76b --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/EnablePaging64.asm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; EnablePaging64.Asm +; +; Abstract: +; +; AsmEnablePaging64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686p + .model flat,C + .code + +InternalX86EnablePaging64 PROC + cli + mov [esp], @F ; offset for far retf + mov eax, cr4 + or al, (1 SHL 5) + mov cr4, eax ; enable PAE + mov ecx, 0c0000080h + rdmsr + or ah, 1 ; set LME + wrmsr + mov eax, cr0 + bts eax, 31 + mov cr0, eax ; enable paging + retf +@@: ; long mode starts here + DB 67h, 48h + mov ebx, [esp] ; mov rbx, [esp] + DB 67h, 48h + mov ecx, [esp + 8] ; mov rcx, [esp + 8] + DB 67h, 48h + mov edx, [esp + 10h] ; mov rdx, [esp + 10h] + DB 67h, 48h + mov esp, [esp + 18h] ; mov rsp, [esp + 18h] + DB 48h + add esp, -20h ; add rsp, -20h + call ebx ; call rbx + jmp $ +InternalX86EnablePaging64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/EnablePaging64.s b/MdePkg/Library/BaseLib/ia32/EnablePaging64.s new file mode 100644 index 0000000000..b365ea762a --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/EnablePaging64.s @@ -0,0 +1,66 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# EnablePaging64.Asm +# +# Abstract: +# +# AsmEnablePaging64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + #.MODEL flat + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmEnablePaging64 ( +# IN UINT16 CodeSelector, +# IN UINT64 EntryPoint, +# IN UINT64 Context1, OPTIONAL +# IN UINT64 Context2, OPTIONAL +# IN UINT64 NewStack +# ); +#------------------------------------------------------------------------------ +.global _AsmEnablePaging64 +_AsmEnablePaging64: + cli + movl $$LongStart, (%esp) + movl %cr4, %eax + orb $0x20, %al + movl %eax, %cr4 # enable PAE + movl $0xc0000080, %ecx + rdmsr + orb $1, %ah # set LME + wrmsr + movl %cr0, %eax + btsl $31, %eax + movl %eax, %cr0 # enable paging + lret +LongStart: # long mode starts here + .byte 0x67,0x48 + movl (%esp), %ebx # mov rbx, [esp] + .byte 0x67,0x48 + movl 8(%esp), %ecx # mov rcx, [esp + 8] + .byte 0x67,0x48 + movl 0x10(%esp), %edx # mov rdx, [esp + 10h] + .byte 0x67,0x48 + movl 0x18(%esp), %esp # mov rsp, [esp + 18h] + .byte 0x48 + addl $0x-20, %esp # add rsp, -20h + call *%ebx # call rbx + jmp . diff --git a/MdePkg/Library/BaseLib/ia32/FlushCacheLine.asm b/MdePkg/Library/BaseLib/ia32/FlushCacheLine.asm new file mode 100644 index 0000000000..d79f217610 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/FlushCacheLine.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; FlushCacheLine.Asm +; +; Abstract: +; +; AsmFlushCacheLine function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmFlushCacheLine ( +; IN VOID *LinearAddress +; ); +;------------------------------------------------------------------------------ +_AsmFlushCacheLine PROC + mov eax, [esp + 4] + clflush [eax] + ret +_AsmFlushCacheLine ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/FlushCacheLine.s b/MdePkg/Library/BaseLib/ia32/FlushCacheLine.s new file mode 100644 index 0000000000..c14bd11d68 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/FlushCacheLine.s @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# FlushCacheLine.Asm +# +# Abstract: +# +# AsmFlushCacheLine function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmFlushCacheLine ( +# IN VOID *LinearAddress +# ); +#------------------------------------------------------------------------------ +.global _AsmFlushCacheLine +_AsmFlushCacheLine: + movl 4(%esp),%eax + clflush (%eax) + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/FxRestore.asm b/MdePkg/Library/BaseLib/ia32/FxRestore.asm new file mode 100644 index 0000000000..e9e37d1384 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/FxRestore.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; FxRestore.Asm +; +; Abstract: +; +; AsmFxRestore function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86FxRestore ( +; IN CONST IA32_FX_BUFFER *Buffer +; ); +;------------------------------------------------------------------------------ +InternalX86FxRestore PROC + mov eax, [esp + 4] + fxrstor [eax] + ret +InternalX86FxRestore ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/FxRestore.s b/MdePkg/Library/BaseLib/ia32/FxRestore.s new file mode 100644 index 0000000000..631a3ef68a --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/FxRestore.s @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# FxRestore.Asm +# +# Abstract: +# +# AsmFxRestore function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmFxRestore ( +# IN CONST IA32_FX_BUFFER *Buffer +# ); +#------------------------------------------------------------------------------ +.global _AsmFxRestore +_AsmFxRestore: + movl 4(%esp),%eax + fxrstor (%eax) + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/FxSave.asm b/MdePkg/Library/BaseLib/ia32/FxSave.asm new file mode 100644 index 0000000000..22496c5e57 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/FxSave.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; FxSave.Asm +; +; Abstract: +; +; AsmFxSave function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86FxSave ( +; OUT IA32_FX_BUFFER *Buffer +; ); +;------------------------------------------------------------------------------ +InternalX86FxSave PROC + mov eax, [esp + 4] + fxsave [eax] + ret +InternalX86FxSave ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/FxSave.s b/MdePkg/Library/BaseLib/ia32/FxSave.s new file mode 100644 index 0000000000..44a55126a9 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/FxSave.s @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# FxSave.Asm +# +# Abstract: +# +# AsmFxSave function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmFxSave ( +# OUT IA32_FX_BUFFER *Buffer +# ); +#------------------------------------------------------------------------------ +.global _AsmFxSave +_AsmFxSave: + movl 4(%esp),%eax + fxsave (%eax) + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange32.asm b/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange32.asm new file mode 100644 index 0000000000..c8c20fbc92 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange32.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; InterlockedCompareExchange32.Asm +; +; Abstract: +; +; InterlockedCompareExchange32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .486 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InterlockedCompareExchange32 ( +; IN UINT32 *Value, +; IN UINT32 CompareValue, +; IN UINT32 ExchangeValue +; ); +;------------------------------------------------------------------------------ +InternalSyncCompareExchange32 PROC + mov ecx, [esp + 4] + mov eax, [esp + 8] + mov edx, [esp + 12] + lock cmpxchg [ecx], edx + ret +InternalSyncCompareExchange32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange32.s b/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange32.s new file mode 100644 index 0000000000..43bb92526e --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange32.s @@ -0,0 +1,64 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# InterlockedCompareExchange32.Asm +# +# Abstract: +# +# InterlockedCompareExchange32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID * +# EFIAPI +# InterlockedCompareExchangePointer ( +# IN VOID **Value, +# IN VOID *CompareValue, +# IN VOID *ExchangeValue +# ); +#------------------------------------------------------------------------------ +.global _InterlockedCompareExchangePointer +_InterlockedCompareExchangePointer: + # + # InterlockedCompareExchangePointer() shares the same code as + # InterlockedCompareExchange32() on IA32 and thus no code inside this + # function + # + + +#------------------------------------------------------------------------------ +# UINT32 +# EFIAPI +# InterlockedCompareExchange32 ( +# IN UINT32 *Value, +# IN UINT32 CompareValue, +# IN UINT32 ExchangeValue +# ); +#------------------------------------------------------------------------------ +.global _InterlockedCompareExchange32 +_InterlockedCompareExchange32: + movl 4(%esp),%ecx + movl 8(%esp),%eax + movl 12(%esp),%edx + lock cmpxchgl %edx,(%ecx) + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange64.asm b/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange64.asm new file mode 100644 index 0000000000..cded9206b8 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange64.asm @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; InterlockedCompareExchange64.Asm +; +; Abstract: +; +; InterlockedCompareExchange64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat,C + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InterlockedCompareExchange64 ( +; IN UINT64 *Value, +; IN UINT64 CompareValue, +; IN UINT64 ExchangeValue +; ); +;------------------------------------------------------------------------------ +InternalSyncCompareExchange64 PROC USES esi ebx + mov esi, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov ebx, [esp + 24] + mov ecx, [esp + 28] + lock cmpxchg8b qword ptr [esi] + ret +InternalSyncCompareExchange64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange64.s b/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange64.s new file mode 100644 index 0000000000..abc51e905b --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/InterlockedCompareExchange64.s @@ -0,0 +1,52 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# InterlockedCompareExchange64.Asm +# +# Abstract: +# +# InterlockedCompareExchange64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# InterlockedCompareExchange64 ( +# IN UINT64 *Value, +# IN UINT64 CompareValue, +# IN UINT64 ExchangeValue +# ); +#------------------------------------------------------------------------------ +.global _InterlockedCompareExchange64 + push %esi + push %ebx + movl 12(%esp),%esi + movl 16(%esp),%eax + movl 20(%esp),%edx + movl 24(%esp),%ebx + movl 28(%esp),%ecx + lock + cmpxchg8b (%esi) + pop %ebx + pop %esi + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/InterlockedDecrement.asm b/MdePkg/Library/BaseLib/ia32/InterlockedDecrement.asm new file mode 100644 index 0000000000..d8495405c0 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/InterlockedDecrement.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; InterlockedDecrement.Asm +; +; Abstract: +; +; InterlockedDecrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InterlockedDecrement ( +; IN UINT32 *Value +; ); +;------------------------------------------------------------------------------ +InternalSyncDecrement PROC + mov eax, [esp + 4] + lock dec dword ptr [eax] + mov eax, [eax] + ret +InternalSyncDecrement ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/InterlockedDecrement.s b/MdePkg/Library/BaseLib/ia32/InterlockedDecrement.s new file mode 100644 index 0000000000..a7b653ac20 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/InterlockedDecrement.s @@ -0,0 +1,44 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# InterlockedDecrement.Asm +# +# Abstract: +# +# InterlockedDecrement function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT32 +# EFIAPI +# InterlockedDecrement ( +# IN UINT32 *Value +# ); +#------------------------------------------------------------------------------ +.global _InterlockedDecrement +_InterlockedDecrement: + movl 4(%esp),%eax + lock + decl (%eax) + movl (%eax),%eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/InterlockedIncrement.asm b/MdePkg/Library/BaseLib/ia32/InterlockedIncrement.asm new file mode 100644 index 0000000000..a7bfb6fccd --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/InterlockedIncrement.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; InterlockedIncrement.Asm +; +; Abstract: +; +; InterlockedIncrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InterlockedIncrement ( +; IN UINT32 *Value +; ); +;------------------------------------------------------------------------------ +InternalSyncIncrement PROC + mov eax, [esp + 4] + lock inc dword ptr [eax] + mov eax, [eax] + ret +InternalSyncIncrement ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/InterlockedIncrement.s b/MdePkg/Library/BaseLib/ia32/InterlockedIncrement.s new file mode 100644 index 0000000000..3f9beec211 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/InterlockedIncrement.s @@ -0,0 +1,44 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# InterlockedIncrement.Asm +# +# Abstract: +# +# InterlockedIncrement function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT32 +# EFIAPI +# InterlockedIncrement ( +# IN UINT32 *Value +# ); +#------------------------------------------------------------------------------ +.global _InterlockedIncrement +_InterlockedIncrement: + movl 4(%esp),%eax + lock + incl (%eax) + movl (%eax),%eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/Invd.asm b/MdePkg/Library/BaseLib/ia32/Invd.asm new file mode 100644 index 0000000000..5767f54848 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Invd.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Invd.Asm +; +; Abstract: +; +; AsmInvd function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .486p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmInvd ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmInvd PROC + invd + ret +_AsmInvd ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/Invd.s b/MdePkg/Library/BaseLib/ia32/Invd.s new file mode 100644 index 0000000000..6d6c8d46cd --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Invd.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# Invd.Asm +# +# Abstract: +# +# AsmInvd function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmInvd ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmInvd +_AsmInvd: + invd + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/LRotU64.asm b/MdePkg/Library/BaseLib/ia32/LRotU64.asm new file mode 100644 index 0000000000..1d5562a799 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/LRotU64.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; LRotU64.asm +; +; Abstract: +; +; 64-bit left rotation for Ia32 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMathLRotU64 PROC USES ebx + mov cl, [esp + 16] + mov edx, [esp + 12] + mov eax, [esp + 8] + shld ebx, edx, cl + shld edx, eax, cl + ror ebx, cl + shld eax, ebx, cl + test cl, 32 + cmovnz ecx, eax + cmovnz eax, edx + cmovnz edx, ecx + ret +InternalMathLRotU64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/LRotU64.s b/MdePkg/Library/BaseLib/ia32/LRotU64.s new file mode 100644 index 0000000000..9c961ce378 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/LRotU64.s @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# LRotU64.asm +# +# Abstract: +# +# 64-bit left rotation for Ia32 +# +#------------------------------------------------------------------------------ + + + + + +.global _LRotU64 + push %ebx + movb 16(%esp),%cl + movl 12(%esp),%edx + movl 8(%esp),%eax + shldl %cl,%edx,%ebx + shldl %cl,%eax,%edx + rorl %cl,%ebx + shldl %cl,%ebx,%eax + testb $32,%cl + cmovnz %eax, %ecx + cmovnz %edx, %eax + cmovnz %ecx, %edx + pop %ebx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/LShiftU64.asm b/MdePkg/Library/BaseLib/ia32/LShiftU64.asm new file mode 100644 index 0000000000..9ce946ddd1 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/LShiftU64.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; LShiftU64.asm +; +; Abstract: +; +; 64-bit left shift function for IA-32 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMathLShiftU64 PROC + mov cl, [esp + 12] + xor eax, eax + mov edx, [esp + 4] + test cl, 32 + cmovz eax, edx + cmovz edx, [esp + 8] + shld edx, eax, cl + shl eax, cl + ret +InternalMathLShiftU64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/LShiftU64.s b/MdePkg/Library/BaseLib/ia32/LShiftU64.s new file mode 100644 index 0000000000..94cbc12265 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/LShiftU64.s @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# LShiftU64.asm +# +# Abstract: +# +# 64-bit left shift function for IA-32 +# +#------------------------------------------------------------------------------ + + + + + +.global _LShiftU64 +_LShiftU64: + movb 12(%esp),%cl + xorl %eax,%eax + movl 4(%esp),%edx + testb $32,%cl + cmovz %edx, %eax + cmovz 8(%esp), %edx + shldl %cl,%eax,%edx + shll %cl,%eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/LongJump.asm b/MdePkg/Library/BaseLib/ia32/LongJump.asm new file mode 100644 index 0000000000..ff0cef2273 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/LongJump.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; LongJump.Asm +; +; Abstract: +; +; Implementation of LongJump() on IA-32. +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +_LongJump PROC + pop eax + pop edx + pop eax + mov ebx, [edx] + mov esi, [edx + 4] + mov edi, [edx + 8] + mov ebp, [edx + 12] + mov esp, [edx + 16] + jmp dword ptr [edx + 20] +_LongJump ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/LongJump.s b/MdePkg/Library/BaseLib/ia32/LongJump.s new file mode 100644 index 0000000000..3da09142fc --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/LongJump.s @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# LongJump.Asm +# +# Abstract: +# +# Implementation of LongJump() on IA-32. +# +#------------------------------------------------------------------------------ + + + + + +.global _LongJump +_LongJump: + popl %eax + popl %edx + popl %eax + movl (%edx),%ebx + movl 4(%edx),%esi + movl 8(%edx),%edi + movl 12(%edx),%ebp + movl 16(%edx),%esp + jmpl *20(%edx) + + + diff --git a/MdePkg/Library/BaseLib/ia32/ModU64x32.asm b/MdePkg/Library/BaseLib/ia32/ModU64x32.asm new file mode 100644 index 0000000000..62481ce98a --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ModU64x32.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; DivU64x32.asm +; +; Abstract: +; +; Calculate the remainder of a 64-bit integer by a 32-bit integer +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMathModU64x32 PROC + mov eax, [esp + 8] + mov ecx, [esp + 12] + xor edx, edx + div ecx + mov eax, [esp + 4] + div ecx + mov eax, edx + ret +InternalMathModU64x32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ModU64x32.s b/MdePkg/Library/BaseLib/ia32/ModU64x32.s new file mode 100644 index 0000000000..ed9c2fee25 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ModU64x32.s @@ -0,0 +1,38 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# DivU64x32.asm +# +# Abstract: +# +# Calculate the remainder of a 64-bit integer by a 32-bit integer +# +#------------------------------------------------------------------------------ + + + + + +.global _ModU64x32 +_ModU64x32: + movl 8(%esp),%eax + movl 12(%esp),%ecx + xorl %edx,%edx + divl %ecx + movl 4(%esp),%eax + divl %ecx + movl %edx,%eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/Monitor.asm b/MdePkg/Library/BaseLib/ia32/Monitor.asm new file mode 100644 index 0000000000..5d92d26673 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Monitor.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Monitor.Asm +; +; Abstract: +; +; AsmMonitor function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmMonitor ( +; IN UINTN Eax, +; IN UINTN Ecx, +; IN UINTN Edx +; ); +;------------------------------------------------------------------------------ +_AsmMonitor PROC + mov eax, [esp + 4] + mov ecx, [esp + 8] + mov edx, [esp + 12] + DB 0fh, 1, 0c8h + ret +_AsmMonitor ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/Monitor.s b/MdePkg/Library/BaseLib/ia32/Monitor.s new file mode 100644 index 0000000000..8da0e341ed --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Monitor.s @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# Monitor.Asm +# +# Abstract: +# +# AsmMonitor function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmMonitor ( +# IN UINTN Eax, +# IN UINTN Ecx, +# IN UINTN Edx +# ); +#------------------------------------------------------------------------------ +.global _AsmMonitor +_AsmMonitor: + movl 4(%esp),%eax + movl 8(%esp),%ecx + movl 12(%esp),%edx + monitor %eax,%ecx,%edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/MultU64x32.asm b/MdePkg/Library/BaseLib/ia32/MultU64x32.asm new file mode 100644 index 0000000000..e2806e3082 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/MultU64x32.asm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; MultU64x32.asm +; +; Abstract: +; +; Calculate the product of a 64-bit integer and a 32-bit integer +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMathMultU64x32 PROC + mov ecx, [esp + 12] + mov eax, ecx + imul ecx, [esp + 8] + mul dword ptr [esp + 4] + add edx, ecx + ret +InternalMathMultU64x32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/MultU64x32.s b/MdePkg/Library/BaseLib/ia32/MultU64x32.s new file mode 100644 index 0000000000..03c520bcf7 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/MultU64x32.s @@ -0,0 +1,36 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# MultU64x32.asm +# +# Abstract: +# +# Calculate the product of a 64-bit integer and a 32-bit integer +# +#------------------------------------------------------------------------------ + + + + + +.global _MultU64x32 +_MultU64x32: + movl 12(%esp),%ecx + movl %ecx,%eax + imull 8(%esp),%ecx + mull 4(%esp) + addl %ecx,%edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/MultU64x64.asm b/MdePkg/Library/BaseLib/ia32/MultU64x64.asm new file mode 100644 index 0000000000..24c6a7daa3 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/MultU64x64.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; MultU64x64.asm +; +; Abstract: +; +; Calculate the product of a 64-bit integer and another 64-bit integer +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMathMultU64x64 PROC USES ebx + mov ebx, [esp + 8] + mov edx, [esp + 16] + mov ecx, ebx + mov eax, edx + imul ebx, [esp + 20] + imul edx, [esp + 12] + add ebx, edx + mul ecx + add edx, ebx + ret +InternalMathMultU64x64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/MultU64x64.s b/MdePkg/Library/BaseLib/ia32/MultU64x64.s new file mode 100644 index 0000000000..8841fc44dc --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/MultU64x64.s @@ -0,0 +1,49 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# MultU64x64.asm +# +# Abstract: +# +# Calculate the product of a 64-bit integer and another 64-bit integer +# +#------------------------------------------------------------------------------ + + + + + +.global _MultS64x64 +_MultS64x64: + # + # MultS64x32 shares the same implementation with _MultU64x32, and thus no + # code inside this function. + # + + +.global _MultU64x64 + push %ebx + movl 8(%esp),%ebx + movl 16(%esp),%edx + movl %ebx,%ecx + movl %edx,%eax + imull 20(%esp),%ebx + imull 12(%esp),%edx + addl %edx,%ebx + mull %ecx + addl %ebx,%edx + pop %ebx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/Mwait.asm b/MdePkg/Library/BaseLib/ia32/Mwait.asm new file mode 100644 index 0000000000..91d505b4e2 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Mwait.asm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Mwait.Asm +; +; Abstract: +; +; AsmMwait function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmMwait ( +; IN UINTN Eax, +; IN UINTN Ecx +; ); +;------------------------------------------------------------------------------ +_AsmMwait PROC + mov eax, [esp + 4] + mov ecx, [esp + 8] + DB 0fh, 1, 0c9h + ret +_AsmMwait ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/Mwait.s b/MdePkg/Library/BaseLib/ia32/Mwait.s new file mode 100644 index 0000000000..7e04453352 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Mwait.s @@ -0,0 +1,44 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# Mwait.Asm +# +# Abstract: +# +# AsmMwait function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmMwait ( +# IN UINTN Eax, +# IN UINTN Ecx +# ); +#------------------------------------------------------------------------------ +.global _AsmMwait +_AsmMwait: + movl 4(%esp),%eax + movl 8(%esp),%ecx + mwait %eax,%ecx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/Non-existing.c b/MdePkg/Library/BaseLib/ia32/Non-existing.c new file mode 100644 index 0000000000..4132d30c31 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Non-existing.c @@ -0,0 +1,30 @@ +/** @file + Non-existing BaseLib functions on Ia32 + + Copyright (c) 2006, 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. + + Module Name: Non-existing.c + +**/ + +#include "../BaseLibInternals.h" + +VOID +EFIAPI +InternalX86DisablePaging64 ( + IN UINT16 CodeSelector, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ) +{ + ASSERT (FALSE); +} diff --git a/MdePkg/Library/BaseLib/ia32/RRotU64.asm b/MdePkg/Library/BaseLib/ia32/RRotU64.asm new file mode 100644 index 0000000000..062e201e8d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/RRotU64.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; RRotU64.asm +; +; Abstract: +; +; 64-bit right rotation for Ia32 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMathRRotU64 PROC USES ebx + mov cl, [esp + 16] + mov eax, [esp + 8] + mov edx, [esp + 12] + shrd ebx, eax, cl + shrd eax, edx, cl + rol ebx, cl + shrd edx, ebx, cl + test cl, 32 + cmovnz ecx, eax + cmovnz eax, edx + cmovnz edx, ecx + ret +InternalMathRRotU64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/RRotU64.s b/MdePkg/Library/BaseLib/ia32/RRotU64.s new file mode 100644 index 0000000000..541e420a3c --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/RRotU64.s @@ -0,0 +1,43 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# RRotU64.asm +# +# Abstract: +# +# 64-bit right rotation for Ia32 +# +#------------------------------------------------------------------------------ + + + + + +.global _RRotU64 + push %ebx + movb 16(%esp),%cl + movl 8(%esp),%eax + movl 12(%esp),%edx + shrdl %cl,%eax,%ebx + shrdl %cl,%edx,%eax + roll %cl,%ebx + shrdl %cl,%ebx,%edx + testb $32,%cl + cmovnz %eax, %ecx + cmovnz %edx, %eax + cmovnz %ecx, %edx + pop %ebx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/RShiftU64.asm b/MdePkg/Library/BaseLib/ia32/RShiftU64.asm new file mode 100644 index 0000000000..effbc55e1c --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/RShiftU64.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; RShiftU64.asm +; +; Abstract: +; +; 64-bit logical right shift function for IA-32 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMathRShiftU64 PROC + mov cl, [esp + 12] + xor edx, edx + mov eax, [esp + 8] + test cl, 32 + cmovz edx, eax + cmovz eax, [esp + 4] + shrd eax, edx, cl + shr edx, cl + ret +InternalMathRShiftU64 ENDP + + END \ No newline at end of file diff --git a/MdePkg/Library/BaseLib/ia32/RShiftU64.s b/MdePkg/Library/BaseLib/ia32/RShiftU64.s new file mode 100644 index 0000000000..5b681e391b --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/RShiftU64.s @@ -0,0 +1,39 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# RShiftU64.asm +# +# Abstract: +# +# 64-bit logical right shift function for IA-32 +# +#------------------------------------------------------------------------------ + + + + + +.global _RShiftU64 +_RShiftU64: + movb 12(%esp),%cl + xorl %edx,%edx + movl 8(%esp),%eax + testb $32,%cl + cmovz %eax, %edx + cmovz 4(%esp), %eax + shrdl %cl,%edx,%eax + shrl %cl,%edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadCr0.asm b/MdePkg/Library/BaseLib/ia32/ReadCr0.asm new file mode 100644 index 0000000000..579cee2377 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadCr0.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadCr0.Asm +; +; Abstract: +; +; AsmReadCr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadCr0 PROC + mov eax, cr0 + ret +_AsmReadCr0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadCr0.s b/MdePkg/Library/BaseLib/ia32/ReadCr0.s new file mode 100644 index 0000000000..3108b71eeb --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadCr0.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadCr0.Asm +# +# Abstract: +# +# AsmReadCr0 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadCr0 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadCr0 +_AsmReadCr0: + movl %cr0, %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadCr2.asm b/MdePkg/Library/BaseLib/ia32/ReadCr2.asm new file mode 100644 index 0000000000..3e4a926abd --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadCr2.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadCr2.Asm +; +; Abstract: +; +; AsmReadCr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadCr2 PROC + mov eax, cr2 + ret +_AsmReadCr2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadCr2.s b/MdePkg/Library/BaseLib/ia32/ReadCr2.s new file mode 100644 index 0000000000..3ce287a252 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadCr2.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadCr2.Asm +# +# Abstract: +# +# AsmReadCr2 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadCr2 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadCr2 +_AsmReadCr2: + movl %cr2, %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadCr3.asm b/MdePkg/Library/BaseLib/ia32/ReadCr3.asm new file mode 100644 index 0000000000..c24ded8051 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadCr3.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadCr3.Asm +; +; Abstract: +; +; AsmReadCr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadCr3 PROC + mov eax, cr3 + ret +_AsmReadCr3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadCr3.s b/MdePkg/Library/BaseLib/ia32/ReadCr3.s new file mode 100644 index 0000000000..2bd63c725a --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadCr3.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadCr3.Asm +# +# Abstract: +# +# AsmReadCr3 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadCr3 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadCr3 +_AsmReadCr3: + movl %cr3, %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadCr4.asm b/MdePkg/Library/BaseLib/ia32/ReadCr4.asm new file mode 100644 index 0000000000..258f37a97f --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadCr4.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadCr4.Asm +; +; Abstract: +; +; AsmReadCr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadCr4 PROC + mov eax, cr4 + ret +_AsmReadCr4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadCr4.s b/MdePkg/Library/BaseLib/ia32/ReadCr4.s new file mode 100644 index 0000000000..4d746d807b --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadCr4.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadCr4.Asm +# +# Abstract: +# +# AsmReadCr4 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadCr4 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadCr4 +_AsmReadCr4: + movl %cr4, %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadCs.asm b/MdePkg/Library/BaseLib/ia32/ReadCs.asm new file mode 100644 index 0000000000..5972d66754 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadCs.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadCs.Asm +; +; Abstract: +; +; AsmReadCs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadCs ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadCs PROC + mov ax, cs + ret +_AsmReadCs ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadCs.s b/MdePkg/Library/BaseLib/ia32/ReadCs.s new file mode 100644 index 0000000000..66bf4b9eeb --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadCs.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadCs.Asm +# +# Abstract: +# +# AsmReadCs function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT16 +# EFIAPI +# AsmReadCs ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadCs +_AsmReadCs: + movw %cs,%ax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr0.asm b/MdePkg/Library/BaseLib/ia32/ReadDr0.asm new file mode 100644 index 0000000000..4da1dd8d0d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr0.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr0.Asm +; +; Abstract: +; +; AsmReadDr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadDr0 PROC + mov eax, dr0 + ret +_AsmReadDr0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr0.s b/MdePkg/Library/BaseLib/ia32/ReadDr0.s new file mode 100644 index 0000000000..00c521b51d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr0.s @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadDr0.Asm +# +# Abstract: +# +# AsmReadDr0 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadDr0 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadDr0 +_AsmReadDr0: + movl %dr0, %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr1.asm b/MdePkg/Library/BaseLib/ia32/ReadDr1.asm new file mode 100644 index 0000000000..8724dd228b --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr1.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr1.Asm +; +; Abstract: +; +; AsmReadDr1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr1 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadDr1 PROC + mov eax, dr1 + ret +_AsmReadDr1 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr1.s b/MdePkg/Library/BaseLib/ia32/ReadDr1.s new file mode 100644 index 0000000000..81d0e54919 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr1.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadDr1.Asm +# +# Abstract: +# +# AsmReadDr1 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadDr1 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadDr1 +_AsmReadDr1: + movl %dr1, %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr2.asm b/MdePkg/Library/BaseLib/ia32/ReadDr2.asm new file mode 100644 index 0000000000..9122d42545 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr2.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr2.Asm +; +; Abstract: +; +; AsmReadDr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadDr2 PROC + mov eax, dr2 + ret +_AsmReadDr2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr2.s b/MdePkg/Library/BaseLib/ia32/ReadDr2.s new file mode 100644 index 0000000000..296fff699e --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr2.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadDr2.Asm +# +# Abstract: +# +# AsmReadDr2 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadDr2 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadDr2 +_AsmReadDr2: + movl %dr2, %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr3.asm b/MdePkg/Library/BaseLib/ia32/ReadDr3.asm new file mode 100644 index 0000000000..7c1ee9826d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr3.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr3.Asm +; +; Abstract: +; +; AsmReadDr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadDr3 PROC + mov eax, dr3 + ret +_AsmReadDr3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr3.s b/MdePkg/Library/BaseLib/ia32/ReadDr3.s new file mode 100644 index 0000000000..e99391de81 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr3.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadDr3.Asm +# +# Abstract: +# +# AsmReadDr3 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadDr3 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadDr3 +_AsmReadDr3: + movl %dr3, %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr4.asm b/MdePkg/Library/BaseLib/ia32/ReadDr4.asm new file mode 100644 index 0000000000..01724555d2 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr4.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr4.Asm +; +; Abstract: +; +; AsmReadDr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadDr4 PROC + DB 0fh, 21h, 0e0h + ret +_AsmReadDr4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr5.asm b/MdePkg/Library/BaseLib/ia32/ReadDr5.asm new file mode 100644 index 0000000000..a95527e44c --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr5.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr5.Asm +; +; Abstract: +; +; AsmReadDr5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr5 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadDr5 PROC + DB 0fh, 21h, 0e8h + ret +_AsmReadDr5 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr6.asm b/MdePkg/Library/BaseLib/ia32/ReadDr6.asm new file mode 100644 index 0000000000..b2d9a3d252 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr6.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr6.Asm +; +; Abstract: +; +; AsmReadDr6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr6 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadDr6 PROC + mov eax, dr6 + ret +_AsmReadDr6 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr6.s b/MdePkg/Library/BaseLib/ia32/ReadDr6.s new file mode 100644 index 0000000000..bdadd80672 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr6.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadDr6.Asm +# +# Abstract: +# +# AsmReadDr6 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadDr6 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadDr6 +_AsmReadDr6: + movl %dr6, %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr7.asm b/MdePkg/Library/BaseLib/ia32/ReadDr7.asm new file mode 100644 index 0000000000..23924b1184 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr7.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr7.Asm +; +; Abstract: +; +; AsmReadDr7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr7 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadDr7 PROC + mov eax, dr7 + ret +_AsmReadDr7 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadDr7.s b/MdePkg/Library/BaseLib/ia32/ReadDr7.s new file mode 100644 index 0000000000..cf213caac9 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDr7.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadDr7.Asm +# +# Abstract: +# +# AsmReadDr7 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadDr7 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadDr7 +_AsmReadDr7: + movl %dr7, %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadDs.asm b/MdePkg/Library/BaseLib/ia32/ReadDs.asm new file mode 100644 index 0000000000..6992766e58 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDs.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDs.Asm +; +; Abstract: +; +; AsmReadDs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadDs ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadDs PROC + mov ax, ds + ret +_AsmReadDs ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadDs.s b/MdePkg/Library/BaseLib/ia32/ReadDs.s new file mode 100644 index 0000000000..ca1e37937a --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadDs.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadDs.Asm +# +# Abstract: +# +# AsmReadDs function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT16 +# EFIAPI +# AsmReadDs ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadDs +_AsmReadDs: + movw %ds,%ax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadEflags.asm b/MdePkg/Library/BaseLib/ia32/ReadEflags.asm new file mode 100644 index 0000000000..365b1dee87 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadEflags.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadEflags.Asm +; +; Abstract: +; +; AsmReadEflags function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadEflags ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadEflags PROC + pushfd + pop eax + ret +_AsmReadEflags ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadEflags.s b/MdePkg/Library/BaseLib/ia32/ReadEflags.s new file mode 100644 index 0000000000..a70a209ffb --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadEflags.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadEflags.Asm +# +# Abstract: +# +# AsmReadEflags function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadEflags ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadEflags +_AsmReadEflags: + pushfl + popl %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadEs.asm b/MdePkg/Library/BaseLib/ia32/ReadEs.asm new file mode 100644 index 0000000000..0ced46aa62 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadEs.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadEs.Asm +; +; Abstract: +; +; AsmReadEs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadEs ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadEs PROC + mov ax, es + ret +_AsmReadEs ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadEs.s b/MdePkg/Library/BaseLib/ia32/ReadEs.s new file mode 100644 index 0000000000..69727b5afc --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadEs.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadEs.Asm +# +# Abstract: +# +# AsmReadEs function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT16 +# EFIAPI +# AsmReadEs ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadEs +_AsmReadEs: + movw %es,%ax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadFs.asm b/MdePkg/Library/BaseLib/ia32/ReadFs.asm new file mode 100644 index 0000000000..f1790c6e9e --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadFs.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadFs.Asm +; +; Abstract: +; +; AsmReadFs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadFs ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadFs PROC + mov ax, fs + ret +_AsmReadFs ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadFs.s b/MdePkg/Library/BaseLib/ia32/ReadFs.s new file mode 100644 index 0000000000..7f4fdfa77c --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadFs.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadFs.Asm +# +# Abstract: +# +# AsmReadFs function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT16 +# EFIAPI +# AsmReadFs ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadFs +_AsmReadFs: + movw %fs,%ax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadGdtr.asm b/MdePkg/Library/BaseLib/ia32/ReadGdtr.asm new file mode 100644 index 0000000000..beacb62b0d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadGdtr.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadGdtr.Asm +; +; Abstract: +; +; AsmReadGdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; InternalX86ReadGdtr ( +; OUT IA32_DESCRIPTOR *Gdtr +; ); +;------------------------------------------------------------------------------ +InternalX86ReadGdtr PROC + mov eax, [esp + 4] + sgdt fword ptr [eax] + ret +InternalX86ReadGdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadGdtr.s b/MdePkg/Library/BaseLib/ia32/ReadGdtr.s new file mode 100644 index 0000000000..f03a05696d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadGdtr.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadGdtr.Asm +# +# Abstract: +# +# AsmReadGdtr function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmReadGdtr ( +# OUT IA32_DESCRIPTOR *Gdtr +# ); +#------------------------------------------------------------------------------ +.global _AsmReadGdtr +_AsmReadGdtr: + movl 4(%esp),%eax + sgdt (%eax) + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadGs.asm b/MdePkg/Library/BaseLib/ia32/ReadGs.asm new file mode 100644 index 0000000000..1de0ebfc88 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadGs.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadGs.Asm +; +; Abstract: +; +; AsmReadGs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadGs ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadGs PROC + mov ax, gs + ret +_AsmReadGs ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadGs.s b/MdePkg/Library/BaseLib/ia32/ReadGs.s new file mode 100644 index 0000000000..0d88a60a52 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadGs.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadGs.Asm +# +# Abstract: +# +# AsmReadGs function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT16 +# EFIAPI +# AsmReadGs ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadGs +_AsmReadGs: + movw %gs,%ax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadIdtr.asm b/MdePkg/Library/BaseLib/ia32/ReadIdtr.asm new file mode 100644 index 0000000000..95158be903 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadIdtr.asm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadIdtr.Asm +; +; Abstract: +; +; AsmReadIdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalX86ReadIdtr PROC + mov eax, [esp + 4] + sidt fword ptr [eax] + ret +InternalX86ReadIdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadIdtr.s b/MdePkg/Library/BaseLib/ia32/ReadIdtr.s new file mode 100644 index 0000000000..fa72d3ba7d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadIdtr.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadIdtr.Asm +# +# Abstract: +# +# AsmReadIdtr function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmReadIdtr ( +# OUT IA32_DESCRIPTOR *Idtr +# ); +#------------------------------------------------------------------------------ +.global _AsmReadIdtr +_AsmReadIdtr: + movl 4(%esp),%eax + sidt (%eax) + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadLdtr.asm b/MdePkg/Library/BaseLib/ia32/ReadLdtr.asm new file mode 100644 index 0000000000..a859a0e553 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadLdtr.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadLdtr.Asm +; +; Abstract: +; +; AsmReadLdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadLdtr ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadLdtr PROC + sldt ax + ret +_AsmReadLdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadLdtr.s b/MdePkg/Library/BaseLib/ia32/ReadLdtr.s new file mode 100644 index 0000000000..aea1d9265c --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadLdtr.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadLdtr.Asm +# +# Abstract: +# +# AsmReadLdtr function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT16 +# EFIAPI +# AsmReadLdtr ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadLdtr +_AsmReadLdtr: + sldt %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm0.asm b/MdePkg/Library/BaseLib/ia32/ReadMm0.asm new file mode 100644 index 0000000000..c45895b2a8 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm0.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm0.Asm +; +; Abstract: +; +; AsmReadMm0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadMm0 PROC + push eax + push eax + movq [esp], mm0 + pop eax + pop edx + ret +_AsmReadMm0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm0.s b/MdePkg/Library/BaseLib/ia32/ReadMm0.s new file mode 100644 index 0000000000..dd6b846836 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm0.s @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadMm0.Asm +# +# Abstract: +# +# AsmReadMm0 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadMm0 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadMm0 +_AsmReadMm0: + pushl %eax + pushl %eax + movq %mm0,(%esp) + popl %eax + popl %edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm1.asm b/MdePkg/Library/BaseLib/ia32/ReadMm1.asm new file mode 100644 index 0000000000..ea748cbd7e --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm1.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm1.Asm +; +; Abstract: +; +; AsmReadMm1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm1 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadMm1 PROC + push eax + push eax + movq [esp], mm1 + pop eax + pop edx + ret +_AsmReadMm1 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm1.s b/MdePkg/Library/BaseLib/ia32/ReadMm1.s new file mode 100644 index 0000000000..cbaafff0f3 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm1.s @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadMm1.Asm +# +# Abstract: +# +# AsmReadMm1 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadMm1 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadMm1 +_AsmReadMm1: + pushl %eax + pushl %eax + movq %mm1,(%esp) + popl %eax + popl %edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm2.asm b/MdePkg/Library/BaseLib/ia32/ReadMm2.asm new file mode 100644 index 0000000000..ab16c513f3 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm2.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm2.Asm +; +; Abstract: +; +; AsmReadMm2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadMm2 PROC + push eax + push eax + movq [esp], mm2 + pop eax + pop edx + ret +_AsmReadMm2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm2.s b/MdePkg/Library/BaseLib/ia32/ReadMm2.s new file mode 100644 index 0000000000..22a5d71ebc --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm2.s @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadMm2.Asm +# +# Abstract: +# +# AsmReadMm2 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadMm2 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadMm2 +_AsmReadMm2: + pushl %eax + pushl %eax + movq %mm2,(%esp) + popl %eax + popl %edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm3.asm b/MdePkg/Library/BaseLib/ia32/ReadMm3.asm new file mode 100644 index 0000000000..3c4bf34492 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm3.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm3.Asm +; +; Abstract: +; +; AsmReadMm3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadMm3 PROC + push eax + push eax + movq [esp], mm3 + pop eax + pop edx + ret +_AsmReadMm3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm3.s b/MdePkg/Library/BaseLib/ia32/ReadMm3.s new file mode 100644 index 0000000000..dae267af7a --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm3.s @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadMm3.Asm +# +# Abstract: +# +# AsmReadMm3 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadMm3 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadMm3 +_AsmReadMm3: + pushl %eax + pushl %eax + movq %mm3,(%esp) + popl %eax + popl %edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm4.asm b/MdePkg/Library/BaseLib/ia32/ReadMm4.asm new file mode 100644 index 0000000000..4c2beb885b --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm4.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm4.Asm +; +; Abstract: +; +; AsmReadMm4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadMm4 PROC + push eax + push eax + movq [esp], mm4 + pop eax + pop edx + ret +_AsmReadMm4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm4.s b/MdePkg/Library/BaseLib/ia32/ReadMm4.s new file mode 100644 index 0000000000..0ae1afcedd --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm4.s @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadMm4.Asm +# +# Abstract: +# +# AsmReadMm4 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadMm4 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadMm4 +_AsmReadMm4: + pushl %eax + pushl %eax + movq %mm4,(%esp) + popl %eax + popl %edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm5.asm b/MdePkg/Library/BaseLib/ia32/ReadMm5.asm new file mode 100644 index 0000000000..66e38265c6 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm5.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm5.Asm +; +; Abstract: +; +; AsmReadMm5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm5 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadMm5 PROC + push eax + push eax + movq [esp], mm5 + pop eax + pop edx + ret +_AsmReadMm5 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm5.s b/MdePkg/Library/BaseLib/ia32/ReadMm5.s new file mode 100644 index 0000000000..2fad14a7e0 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm5.s @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadMm5.Asm +# +# Abstract: +# +# AsmReadMm5 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadMm5 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadMm5 +_AsmReadMm5: + pushl %eax + pushl %eax + movq %mm5,(%esp) + popl %eax + popl %edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm6.asm b/MdePkg/Library/BaseLib/ia32/ReadMm6.asm new file mode 100644 index 0000000000..69d9e13f6b --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm6.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm6.Asm +; +; Abstract: +; +; AsmReadMm6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm6 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadMm6 PROC + push eax + push eax + movq [esp], mm6 + pop eax + pop edx + ret +_AsmReadMm6 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm6.s b/MdePkg/Library/BaseLib/ia32/ReadMm6.s new file mode 100644 index 0000000000..22cddfa486 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm6.s @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadMm6.Asm +# +# Abstract: +# +# AsmReadMm6 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadMm6 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadMm6 +_AsmReadMm6: + pushl %eax + pushl %eax + movq %mm6,(%esp) + popl %eax + popl %edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm7.asm b/MdePkg/Library/BaseLib/ia32/ReadMm7.asm new file mode 100644 index 0000000000..a8788cbf7a --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm7.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm7.Asm +; +; Abstract: +; +; AsmReadMm7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm7 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadMm7 PROC + push eax + push eax + movq [esp], mm7 + pop eax + pop edx + ret +_AsmReadMm7 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadMm7.s b/MdePkg/Library/BaseLib/ia32/ReadMm7.s new file mode 100644 index 0000000000..fb485a00c9 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMm7.s @@ -0,0 +1,46 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadMm7.Asm +# +# Abstract: +# +# AsmReadMm7 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmReadMm7 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadMm7 +_AsmReadMm7: + pushl %eax + pushl %eax + movq %mm7,(%esp) + popl %eax + popl %edx + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadMsr64.asm b/MdePkg/Library/BaseLib/ia32/ReadMsr64.asm new file mode 100644 index 0000000000..6c9fe00033 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMsr64.asm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMsr64.Asm +; +; Abstract: +; +; AsmReadMsr64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; AsmReadMsr32 ( +; IN UINT32 Index +; ); +;------------------------------------------------------------------------------ +_AsmReadMsr32 PROC + ; + ; AsmReadMsr32 shares the same implementation with AsmReadMsr64 and thus no + ; code inside this function + ; +_AsmReadMsr32 ENDP + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMsr64 ( +; IN UINT64 Index +; ); +;------------------------------------------------------------------------------ +_AsmReadMsr64 PROC + mov ecx, [esp + 4] + rdmsr + ret +_AsmReadMsr64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadMsr64.s b/MdePkg/Library/BaseLib/ia32/ReadMsr64.s new file mode 100644 index 0000000000..6a2c9c6688 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadMsr64.s @@ -0,0 +1,57 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadMsr64.Asm +# +# Abstract: +# +# AsmReadMsr64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT32 +# EFIAPI +# AsmReadMsr32 ( +# IN UINT32 Index +# ); +#------------------------------------------------------------------------------ +.global _AsmReadMsr32 +_AsmReadMsr32: + # + # AsmReadMsr32 shares the same implementation with AsmReadMsr64 and thus no + # code inside this function + # + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmReadMsr64 ( +# IN UINT64 Index +# ); +#------------------------------------------------------------------------------ +.global _AsmReadMsr64 +_AsmReadMsr64: + movl 4(%esp),%ecx + rdmsr + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadPmc.asm b/MdePkg/Library/BaseLib/ia32/ReadPmc.asm new file mode 100644 index 0000000000..1fe598158d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadPmc.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadPmc.Asm +; +; Abstract: +; +; AsmReadPmc function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadPmc ( +; IN UINT32 PmcIndex +; ); +;------------------------------------------------------------------------------ +_AsmReadPmc PROC + mov ecx, [esp + 4] + rdpmc + ret +_AsmReadPmc ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadPmc.s b/MdePkg/Library/BaseLib/ia32/ReadPmc.s new file mode 100644 index 0000000000..868e85c23d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadPmc.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadPmc.Asm +# +# Abstract: +# +# AsmReadPmc function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmReadPmc ( +# IN UINT32 PmcIndex +# ); +#------------------------------------------------------------------------------ +.global _AsmReadPmc +_AsmReadPmc: + movl 4(%esp),%ecx + rdpmc + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadSs.asm b/MdePkg/Library/BaseLib/ia32/ReadSs.asm new file mode 100644 index 0000000000..6d0cd9f2a0 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadSs.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadSs.Asm +; +; Abstract: +; +; AsmReadSs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadSs ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadSs PROC + mov ax, ss + ret +_AsmReadSs ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadSs.s b/MdePkg/Library/BaseLib/ia32/ReadSs.s new file mode 100644 index 0000000000..7db65c1490 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadSs.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadSs.Asm +# +# Abstract: +# +# AsmReadSs function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT16 +# EFIAPI +# AsmReadSs ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadSs +_AsmReadSs: + movw %ss,%ax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadTr.asm b/MdePkg/Library/BaseLib/ia32/ReadTr.asm new file mode 100644 index 0000000000..d77ee89123 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadTr.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadTr.Asm +; +; Abstract: +; +; AsmReadTr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadTr ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadTr PROC + str ax + ret +_AsmReadTr ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadTr.s b/MdePkg/Library/BaseLib/ia32/ReadTr.s new file mode 100644 index 0000000000..8c31e9d9fa --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadTr.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadTr.Asm +# +# Abstract: +# +# AsmReadTr function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT16 +# EFIAPI +# AsmReadTr ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadTr +_AsmReadTr: + str %eax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/ReadTsc.asm b/MdePkg/Library/BaseLib/ia32/ReadTsc.asm new file mode 100644 index 0000000000..ea3c164ecd --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadTsc.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadTsc.Asm +; +; Abstract: +; +; AsmReadTsc function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadTsc ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmReadTsc PROC + rdtsc + ret +_AsmReadTsc ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/ReadTsc.s b/MdePkg/Library/BaseLib/ia32/ReadTsc.s new file mode 100644 index 0000000000..e7981c05b0 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/ReadTsc.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# ReadTsc.Asm +# +# Abstract: +# +# AsmReadTsc function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmReadTsc ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmReadTsc +_AsmReadTsc: + rdtsc + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/SetJump.asm b/MdePkg/Library/BaseLib/ia32/SetJump.asm new file mode 100644 index 0000000000..41277cd20f --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/SetJump.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetJump.Asm +; +; Abstract: +; +; Implementation of SetJump() on IA-32. +; +;------------------------------------------------------------------------------ + + .386 + .model flat + .code + +_SetJump PROC + pop ecx + mov edx, [esp] + mov [edx], ebx + mov [edx + 4], esi + mov [edx + 8], edi + mov [edx + 12], ebp + mov [edx + 16], esp + mov [edx + 20], ecx + xor eax, eax + jmp ecx +_SetJump ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/SetJump.s b/MdePkg/Library/BaseLib/ia32/SetJump.s new file mode 100644 index 0000000000..b1b6a84f63 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/SetJump.s @@ -0,0 +1,40 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# SetJump.Asm +# +# Abstract: +# +# Implementation of SetJump() on IA-32. +# +#------------------------------------------------------------------------------ + + + + + +.global _SetJump +_SetJump: + popl %ecx + movl (%esp),%edx + movl %ebx,(%edx) + movl %esi,4(%edx) + movl %edi,8(%edx) + movl %ebp,12(%edx) + movl %esp,16(%edx) + movl %ecx,20(%edx) + xorl %eax,%eax + jmp *%ecx + + + diff --git a/MdePkg/Library/BaseLib/ia32/SwapBytes64.asm b/MdePkg/Library/BaseLib/ia32/SwapBytes64.asm new file mode 100644 index 0000000000..72e366bd4d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/SwapBytes64.asm @@ -0,0 +1,36 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuId.Asm +; +; Abstract: +; +; AsmCpuid function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat,C + .code + +InternalMathSwapBytes64 PROC + mov eax, [esp + 8] + mov edx, [esp + 4] + bswap eax + bswap edx + ret +InternalMathSwapBytes64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/SwitchStack.c b/MdePkg/Library/BaseLib/ia32/SwitchStack.c new file mode 100644 index 0000000000..77800e35dd --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/SwitchStack.c @@ -0,0 +1,57 @@ +/** @file + SwitchStack() function for IA-32. + + Copyright (c) 2006, 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. + + Module Name: SwitchStack.c + +**/ + +/** + Transfers control to a function starting with a new stack. + + Transfers control to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + @param EntryPoint A pointer to function to call with the new stack. + @param Context1 A pointer to the context to pass into the EntryPoint + function. + @param Context2 A pointer to the context to pass into the EntryPoint + function. + @param NewStack A pointer to the new stack to use for the EntryPoint + function. + +**/ +VOID +EFIAPI +SwitchStack ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, + IN VOID *Context2, + IN VOID *NewStack + ) +{ + BASE_LIBRARY_JUMP_BUFFER JumpBuffer; + + ASSERT (EntryPoint != NULL && NewStack != NULL); + + JumpBuffer.Eip = (UINTN)EntryPoint; + JumpBuffer.Esp = (UINTN)NewStack - sizeof (VOID*); + JumpBuffer.Esp -= sizeof (Context1) + sizeof (Context2); + ((VOID**)JumpBuffer.Esp)[1] = Context1; + ((VOID**)JumpBuffer.Esp)[2] = Context2; + + LongJump (&JumpBuffer, (UINTN)-1); +} diff --git a/MdePkg/Library/BaseLib/ia32/Thunk16.asm b/MdePkg/Library/BaseLib/ia32/Thunk16.asm new file mode 100644 index 0000000000..2d62d72aef --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Thunk16.asm @@ -0,0 +1,163 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Thunk.asm +; +; Abstract: +; +; Real mode thunk +; +;------------------------------------------------------------------------------ + + .686p + .model flat,C + + .data + +NullSegSel DQ 0 +_16BitCsSel LABEL QWORD + DW -1 + DW 0 + DB 0 + DB 9bh + DB 8fh ; 16-bit segment + DB 0 +_16BitDsSel LABEL QWORD + DW -1 + DW 0 + DB 0 + DB 93h + DB 8fh ; 16-bit segment + DB 0 +GdtEnd LABEL QWORD + + .const + +_16Gdtr LABEL FWORD + DW offset GdtEnd - offset NullSegSel - 1 + DD offset NullSegSel + +_16Idtr FWORD (1 SHL 10) - 1 + + .code + +IA32_REGS STRUC 4t +_EDI DD ? +_ESI DD ? +_EBP DD ? +_ESP DD ? +_EBX DD ? +_EDX DD ? +_ECX DD ? +_EAX DD ? +_DS DW ? +_ES DW ? +_FS DW ? +_GS DW ? +_EFLAGS DD ? +_EIP DD ? +_CS DW ? +_SS DW ? +IA32_REGS ENDS + +InternalAsmThunk16 PROC USES ebp ebx esi edi ds es fs gs + mov esi, [esp + 36] ; esi <- RegSet + push sizeof (IA32_REGS) + pop ecx + movzx edx, (IA32_REGS ptr [esi])._SS + mov edi, (IA32_REGS ptr [esi])._ESP + sub edi, ecx ; reserve space on realmode stack + push edi ; save stack offset + imul eax, edx, 16 ; eax <- edx * 16 + add edi, eax ; edi <- linear address of 16-bit stack + rep movsb ; copy RegSet + mov esi, edx ; esi <- 16-bit stack segment + pop ebx ; ebx <- 16-bit stack offset + mov edi, [esp + 40] ; edi <- realmode patch + push cs ; save CS segment selector + push offset @BackToThunk ; offset to back from real mode + mov eax, offset @16Return + stosd + xor eax, eax + stosw ; set CS base to 0 + mov eax, esp + stosd + mov eax, ss + stosd + mov eax, cr0 + mov ecx, eax ; ecx <- CR0 + and ecx, 7ffffffeh ; clear PE, PG bits + stosd + mov eax, cr4 + mov ebp, eax + and ebp, 300h ; clear all but PCE and OSFXSR bits + stosd + sidt fword ptr [esp + 44] ; use parameter space to save IDTR + sgdt fword ptr [edi] + lidt _16Idtr + push 10h + pop eax + push 8 + push offset @16Start + lgdt _16Gdtr + retf +@16Start: ; 16-bit starts here + mov ss, eax ; set SS to be a 16-bit segment + mov cr0, ecx + mov cr4, ebp + mov ss, esi ; set up 16-bit stack + mov sp, bx ; mov esp, ebx actually + popaw ; popad actually + pop ds + pop es + pop fs + pop gs + add sp, 4 ; skip _EFLAGS + DB 66h + retf ; transfer control to 16-bit code +@16Return: + pushf ; pushfd actually + push gs + push fs + push es + push ds + pushaw ; pushad actually + DB 67h, 66h + lds esi, fword ptr (IA32_REGS ptr [esp])._EIP + DB 67h, 66h + mov eax, [esi + 12] + mov cr4, eax ; restore CR4 + DB 67h, 66h + lgdt fword ptr [esi + 16] + DB 67h, 66h + mov eax, [esi + 8] + mov cr0, eax ; restore CR0 + xor ax, ax ; xor eax, eax actually + mov eax, ss + DB 67h + mov dword ptr (IA32_REGS ptr [esp])._SS, eax + shl ax, 4 ; shl eax, 4 actually + add ax, sp ; add eax, esp actually + add sp, sizeof (IA32_REGS) ; add esp, sizeof (IA32_REGS) + DB 67h, 66h + mov dword ptr (IA32_REGS ptr [esp - sizeof (IA32_REGS)])._ESP, esp + DB 67h, 66h + lss esp, fword ptr [esi] ; restore protected mode stack + DB 66h + retf ; go back to protected mode +@BackToThunk: + lidt fword ptr [esp + 36] ; restore protected mode IDTR + ret +InternalAsmThunk16 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/Thunk16.s b/MdePkg/Library/BaseLib/ia32/Thunk16.s new file mode 100644 index 0000000000..4236996226 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Thunk16.s @@ -0,0 +1,191 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# Thunk.asm +# +# Abstract: +# +# Real mode thunk +# +#------------------------------------------------------------------------------ + + + +MISMATCH: "EXTERNDEF C mCode16Size:DWORD" + +MISMATCH: "CONST SEGMENT FLAT "DATA" READONLY" + +MISMATCH: "mCode16Size DD _TEXT16SIZE" + +MISMATCH: "CONSTS" + +MISMATCH: "_DATA SEGMENT FLAT "DATA"" + +MISMATCH: "NullSegSel DQ 0" +MISMATCH: "_16BitCsSel LABEL QWORD" + .word -1 + .word 0 + .byte 0 + .byte 0x9b + .byte 0x8f # 16-bit segment + .byte 0 + +MISMATCH: "_16Gdtr LABEL FWORD" +MISMATCH: " DW $ - offset NullSegSel - 1" +MISMATCH: " DD offset NullSegSel" + +MISMATCH: "_DATAS" + +MISMATCH: "_TEXT SEGMENT FLAT "CODE" PARA" + +MISMATCH: "IA32_REGS STRUC 4t" +MISMATCH: "_EDI DD ?" +MISMATCH: "_ESI DD ?" +MISMATCH: "_EBP DD ?" +MISMATCH: "_ESP DD ?" +MISMATCH: "_EBX DD ?" +MISMATCH: "_EDX DD ?" +MISMATCH: "_ECX DD ?" +MISMATCH: "_EAX DD ?" +MISMATCH: "_DS DW ?" +MISMATCH: "_ES DW ?" +MISMATCH: "_FS DW ?" +MISMATCH: "_GS DW ?" +MISMATCH: "_EFLAGS DD ?" +MISMATCH: "_EIP DD ?" +MISMATCH: "_CS DW ?" +MISMATCH: "_SS DW ?" +MISMATCH: "IA32_REGSS" + +MISMATCH: "_STK16 STRUC 1t" +MISMATCH: "RetEip DD ?" +MISMATCH: "RetCs DW ?" +MISMATCH: "ThunkFlags DW ?" +MISMATCH: "SavedEsp DD ?" +MISMATCH: "SavedSs DW ?" +MISMATCH: "SavedGdtr FWORD ?" +MISMATCH: "SavedCr0 DD ?" +MISMATCH: "SavedCr4 DD ?" +MISMATCH: "_STK16S" + +.global _InternalAsmThunk16 +MISMATCH: "_InternalAsmThunk16: USES ebp ebx esi edi ds es fs gs" +MISMATCH: " ASSUME esi:PTR IA32_REGS" + movl 36(%esp),%esi +MISMATCH: " movzx edx, [esi]._SS" + movl $[esi]._ESP, %edi +MISMATCH: " add edi, - sizeof (_STK16) - sizeof (IA32_REGS)" + pushl %edi # save stack offset + imull $16,%edx,%eax # eax <- edx*16 + addl %eax,%edi # edi <- linear address of 16-bit stack +MISMATCH: " push sizeof (IA32_REGS) / 4" + popl %ecx + rep + movsl # copy context to 16-bit stack + popl %ebx # ebx <- 16-bit stack offset +MISMATCH: " mov eax, offset @F " + stosl + movl %cs,%eax # return segment + stosw + movl 40(%esp),%eax # THUNK flags + stosw + movl %esp,%eax + stosl # save esp + movl %ss,%eax # save ss + stosw +MISMATCH: " sgdt fword ptr [edi] " +MISMATCH: " sidt fword ptr [esp + 36] " + movl %cr0, %esi + movl %esi,6(%edi) # save CR0 +MISMATCH: " and esi, NOT 80000001h " + movl %cr4, %eax + movl %eax,10(%edi) # save CR4 +MISMATCH: " and al, NOT 30h " + movl %edx,%edi # edi <- 16-bit stack segment + movl 44(%esp),%edx + shll $16,%edx + pushl %edx +MISMATCH: " lgdt _16Gdtr " + .byte 0xea +MISMATCH: " DD offset @16Bit" + .word 8 # jmp far 8:@16Bit +@16Bit: + movl %esi, %cr0 # disable protected mode + movl %eax, %cr4 # disable PAE & PSE + lret +@@: + movl %ss,%eax + shll $4,%eax + addl %esp,%eax # eax <- address of 16-bit stack +MISMATCH: " lss esp, fword ptr (_STK16 ptr [esp + sizeof (IA32_REGS)]).SavedEsp" +MISMATCH: " lidt fword ptr [esp + 36] " + ret + + +MISMATCH: "_TEXTS" + +MISMATCH: "_TEXT16 SEGMENT USE16 "CODE" PARA" + +.global _Code16Addr +MISMATCH: "_Code16Addr: C" + + +.global RealMode +RealMode: +MISMATCH: " ASSUME bp:PTR _STK16" + movw %di,%ss # set up stack + movl %ebx,%esp +MISMATCH: " lidt fword ptr cs:[_16Idtr - _Code16Addr]" + popal + popl %ds + popl %es + popl %fs + popl %gs + addw $4,%sp # skip EFlags +MISMATCH: " test (_STK16 ptr [esp + 8]).ThunkFlags, 1" + jz @F + pushf +@@: + pushw %cs +MISMATCH: " push @FarCallRet - _Code16Addr" + jz @F +MISMATCH: " jmp fword ptr [esp + 6]" +@@: +MISMATCH: " jmp fword ptr [esp + 4]" +@FarCallRet: + pushfl + pushw %gs + pushw %fs + pushw %es + pushw %ds + pushal + cli +MISMATCH: " lea bp, [esp + sizeof (IA32_REGS)]" + .byte 0x66 +MISMATCH: " lgdt [bp].SavedGdtr" + movl $[bp].SavedCr4, %eax + movl %eax, %cr4 + movl $[bp].SavedCr0, %eax + movl %eax, %cr0 # restore CR0 +MISMATCH: " jmp fword ptr [bp].RetEip" + + +MISMATCH: "_16Idtr FWORD (1 SHL 10) - 1" + +_TEXT16: + +MISMATCH: "_TEXT16SIZE = _TEXT16- _Code16Addr" + +MISMATCH: "_TEXT16S" + + diff --git a/MdePkg/Library/BaseLib/ia32/Wbinvd.asm b/MdePkg/Library/BaseLib/ia32/Wbinvd.asm new file mode 100644 index 0000000000..07258fb9e9 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Wbinvd.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Wbinvd.Asm +; +; Abstract: +; +; AsmWbinvd function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .486p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWbinvd ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmWbinvd PROC + wbinvd + ret +_AsmWbinvd ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/Wbinvd.s b/MdePkg/Library/BaseLib/ia32/Wbinvd.s new file mode 100644 index 0000000000..e9f6c0ce6b --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/Wbinvd.s @@ -0,0 +1,41 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# Wbinvd.Asm +# +# Abstract: +# +# AsmWbinvd function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmWbinvd ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmWbinvd +_AsmWbinvd: + wbinvd + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteCr0.asm b/MdePkg/Library/BaseLib/ia32/WriteCr0.asm new file mode 100644 index 0000000000..d64d621cd5 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteCr0.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteCr0.Asm +; +; Abstract: +; +; AsmWriteCr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmWriteCr0 PROC + mov eax, [esp + 4] + mov cr0, eax + ret +_AsmWriteCr0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteCr0.s b/MdePkg/Library/BaseLib/ia32/WriteCr0.s new file mode 100644 index 0000000000..6e3ad50765 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteCr0.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteCr0.Asm +# +# Abstract: +# +# AsmWriteCr0 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmWriteCr0 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteCr0 +_AsmWriteCr0: + movl 4(%esp),%eax + movl %eax, %cr0 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteCr2.asm b/MdePkg/Library/BaseLib/ia32/WriteCr2.asm new file mode 100644 index 0000000000..7ab5b0f64f --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteCr2.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteCr2.Asm +; +; Abstract: +; +; AsmWriteCr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmWriteCr2 PROC + mov eax, [esp + 4] + mov cr2, eax + ret +_AsmWriteCr2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteCr2.s b/MdePkg/Library/BaseLib/ia32/WriteCr2.s new file mode 100644 index 0000000000..cf45e01a24 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteCr2.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteCr2.Asm +# +# Abstract: +# +# AsmWriteCr2 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmWriteCr2 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteCr2 +_AsmWriteCr2: + movl 4(%esp),%eax + movl %eax, %cr2 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteCr3.asm b/MdePkg/Library/BaseLib/ia32/WriteCr3.asm new file mode 100644 index 0000000000..9753de1abe --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteCr3.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteCr3.Asm +; +; Abstract: +; +; AsmWriteCr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmWriteCr3 PROC + mov eax, [esp + 4] + mov cr3, eax + ret +_AsmWriteCr3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteCr3.s b/MdePkg/Library/BaseLib/ia32/WriteCr3.s new file mode 100644 index 0000000000..1c55581905 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteCr3.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteCr3.Asm +# +# Abstract: +# +# AsmWriteCr3 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmWriteCr3 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteCr3 +_AsmWriteCr3: + movl 4(%esp),%eax + movl %eax, %cr3 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteCr4.asm b/MdePkg/Library/BaseLib/ia32/WriteCr4.asm new file mode 100644 index 0000000000..60bfe78cb6 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteCr4.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteCr4.Asm +; +; Abstract: +; +; AsmWriteCr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +_AsmWriteCr4 PROC + mov eax, [esp + 4] + mov cr4, eax + ret +_AsmWriteCr4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteCr4.s b/MdePkg/Library/BaseLib/ia32/WriteCr4.s new file mode 100644 index 0000000000..fbe48c1cd0 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteCr4.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteCr4.Asm +# +# Abstract: +# +# AsmWriteCr4 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINTN +# EFIAPI +# AsmWriteCr4 ( +# VOID +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteCr4 +_AsmWriteCr4: + movl 4(%esp),%eax + movl %eax, %cr4 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr0.asm b/MdePkg/Library/BaseLib/ia32/WriteDr0.asm new file mode 100644 index 0000000000..3dab544c49 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr0.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr0.Asm +; +; Abstract: +; +; AsmWriteDr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteDr0 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteDr0 PROC + mov eax, [esp + 4] + mov dr0, eax + ret +_AsmWriteDr0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr0.s b/MdePkg/Library/BaseLib/ia32/WriteDr0.s new file mode 100644 index 0000000000..a5a84de6b4 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr0.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteDr0.Asm +# +# Abstract: +# +# AsmWriteDr0 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmWriteDr0 ( +# IN UINTN Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteDr0 +_AsmWriteDr0: + movl 4(%esp),%eax + movl %eax, %dr0 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr1.asm b/MdePkg/Library/BaseLib/ia32/WriteDr1.asm new file mode 100644 index 0000000000..5898206c53 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr1.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr1.Asm +; +; Abstract: +; +; AsmWriteDr1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteDr1 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteDr1 PROC + mov eax, [esp + 4] + mov dr1, eax + ret +_AsmWriteDr1 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr1.s b/MdePkg/Library/BaseLib/ia32/WriteDr1.s new file mode 100644 index 0000000000..66fc2c7cf3 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr1.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteDr1.Asm +# +# Abstract: +# +# AsmWriteDr1 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmWriteDr1 ( +# IN UINTN Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteDr1 +_AsmWriteDr1: + movl 4(%esp),%eax + movl %eax, %dr1 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr2.asm b/MdePkg/Library/BaseLib/ia32/WriteDr2.asm new file mode 100644 index 0000000000..3ed25fc8ef --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr2.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr2.Asm +; +; Abstract: +; +; AsmWriteDr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteDr2 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteDr2 PROC + mov eax, [esp + 4] + mov dr2, eax + ret +_AsmWriteDr2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr2.s b/MdePkg/Library/BaseLib/ia32/WriteDr2.s new file mode 100644 index 0000000000..7b3f780510 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr2.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteDr2.Asm +# +# Abstract: +# +# AsmWriteDr2 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmWriteDr2 ( +# IN UINTN Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteDr2 +_AsmWriteDr2: + movl 4(%esp),%eax + movl %eax, %dr2 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr3.asm b/MdePkg/Library/BaseLib/ia32/WriteDr3.asm new file mode 100644 index 0000000000..c1dbc826b3 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr3.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr3.Asm +; +; Abstract: +; +; AsmWriteDr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteDr3 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteDr3 PROC + mov eax, [esp + 4] + mov dr3, eax + ret +_AsmWriteDr3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr3.s b/MdePkg/Library/BaseLib/ia32/WriteDr3.s new file mode 100644 index 0000000000..34d3e4f0cb --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr3.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteDr3.Asm +# +# Abstract: +# +# AsmWriteDr3 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmWriteDr3 ( +# IN UINTN Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteDr3 +_AsmWriteDr3: + movl 4(%esp),%eax + movl %eax, %dr3 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr4.asm b/MdePkg/Library/BaseLib/ia32/WriteDr4.asm new file mode 100644 index 0000000000..2c82512acc --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr4.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr4.Asm +; +; Abstract: +; +; AsmWriteDr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteDr4 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteDr4 PROC + mov eax, [esp + 4] + DB 0fh, 23h, 0e0h + ret +_AsmWriteDr4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr5.asm b/MdePkg/Library/BaseLib/ia32/WriteDr5.asm new file mode 100644 index 0000000000..dc074244a1 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr5.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr5.Asm +; +; Abstract: +; +; AsmWriteDr5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteDr5 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteDr5 PROC + mov eax, [esp + 4] + DB 0fh, 23h, 0e8h + ret +_AsmWriteDr5 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr6.asm b/MdePkg/Library/BaseLib/ia32/WriteDr6.asm new file mode 100644 index 0000000000..e307e827dd --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr6.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr6.Asm +; +; Abstract: +; +; AsmWriteDr6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteDr6 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteDr6 PROC + mov eax, [esp + 4] + mov dr6, eax + ret +_AsmWriteDr6 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr6.s b/MdePkg/Library/BaseLib/ia32/WriteDr6.s new file mode 100644 index 0000000000..7d7726be64 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr6.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteDr6.Asm +# +# Abstract: +# +# AsmWriteDr6 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmWriteDr6 ( +# IN UINTN Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteDr6 +_AsmWriteDr6: + movl 4(%esp),%eax + movl %eax, %dr6 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr7.asm b/MdePkg/Library/BaseLib/ia32/WriteDr7.asm new file mode 100644 index 0000000000..55dbdc9c52 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr7.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr7.Asm +; +; Abstract: +; +; AsmWriteDr7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteDr7 ( +; IN UINTN Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteDr7 PROC + mov eax, [esp + 4] + mov dr7, eax + ret +_AsmWriteDr7 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteDr7.s b/MdePkg/Library/BaseLib/ia32/WriteDr7.s new file mode 100644 index 0000000000..a96f445632 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteDr7.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteDr7.Asm +# +# Abstract: +# +# AsmWriteDr7 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmWriteDr7 ( +# IN UINTN Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteDr7 +_AsmWriteDr7: + movl 4(%esp),%eax + movl %eax, %dr7 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteGdtr.asm b/MdePkg/Library/BaseLib/ia32/WriteGdtr.asm new file mode 100644 index 0000000000..a317e75388 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteGdtr.asm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteGdtr.Asm +; +; Abstract: +; +; AsmWriteGdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686P + .model flat,C + .code + +InternalX86WriteGdtr PROC + mov eax, [esp + 4] + lgdt fword ptr [eax] + ret +InternalX86WriteGdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteGdtr.s b/MdePkg/Library/BaseLib/ia32/WriteGdtr.s new file mode 100644 index 0000000000..c3eb63d9e4 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteGdtr.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteGdtr.Asm +# +# Abstract: +# +# AsmWriteGdtr function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmWriteGdtr ( +# OUT IA32_DESCRIPTOR *Gdtr +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteGdtr +_AsmWriteGdtr: + movl 4(%esp),%eax + lgdt (%eax) + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteIdtr.asm b/MdePkg/Library/BaseLib/ia32/WriteIdtr.asm new file mode 100644 index 0000000000..d4b3b51a04 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteIdtr.asm @@ -0,0 +1,34 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteIdtr.Asm +; +; Abstract: +; +; AsmWriteIdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686P + .model flat,C + .code + +InternalX86WriteIdtr PROC + mov eax, [esp + 4] + lidt fword ptr [eax] + ret +InternalX86WriteIdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteIdtr.s b/MdePkg/Library/BaseLib/ia32/WriteIdtr.s new file mode 100644 index 0000000000..f71b696d97 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteIdtr.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteIdtr.Asm +# +# Abstract: +# +# AsmWriteIdtr function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmWriteIdtr ( +# OUT IA32_DESCRIPTOR *Idtr +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteIdtr +_AsmWriteIdtr: + movl 4(%esp),%eax + lidt (%eax) + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteLdtr.asm b/MdePkg/Library/BaseLib/ia32/WriteLdtr.asm new file mode 100644 index 0000000000..39f8b2ed5e --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteLdtr.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteLdtr.Asm +; +; Abstract: +; +; AsmWriteLdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386p + .model flat + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteLdtr ( +; IN UINT16 Ldtr +; ); +;------------------------------------------------------------------------------ +_AsmWriteLdtr PROC + mov eax, [esp + 4] + lldt ax + ret +_AsmWriteLdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteLdtr.s b/MdePkg/Library/BaseLib/ia32/WriteLdtr.s new file mode 100644 index 0000000000..3797bd547d --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteLdtr.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteLdtr.Asm +# +# Abstract: +# +# AsmWriteLdtr function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# VOID +# EFIAPI +# AsmWriteLdtr ( +# IN UINT16 Ldtr +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteLdtr +_AsmWriteLdtr: + movl 4(%esp),%eax + lldtw %ax + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm0.asm b/MdePkg/Library/BaseLib/ia32/WriteMm0.asm new file mode 100644 index 0000000000..e924dbdb61 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm0.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm0.Asm +; +; Abstract: +; +; AsmWriteMm0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMm0 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteMm0 PROC + movq mm0, [esp + 4] + ret +_AsmWriteMm0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm0.s b/MdePkg/Library/BaseLib/ia32/WriteMm0.s new file mode 100644 index 0000000000..c4444219a9 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm0.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteMm0.Asm +# +# Abstract: +# +# AsmWriteMm0 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmWriteMm0 ( +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteMm0 +_AsmWriteMm0: + movq 4(%esp),%mm0 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm1.asm b/MdePkg/Library/BaseLib/ia32/WriteMm1.asm new file mode 100644 index 0000000000..1f1d8ce8dc --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm1.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm1.Asm +; +; Abstract: +; +; AsmWriteMm1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMm1 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteMm1 PROC + movq mm1, [esp + 4] + ret +_AsmWriteMm1 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm1.s b/MdePkg/Library/BaseLib/ia32/WriteMm1.s new file mode 100644 index 0000000000..e3a492f9ec --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm1.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteMm1.Asm +# +# Abstract: +# +# AsmWriteMm1 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmWriteMm1 ( +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteMm1 +_AsmWriteMm1: + movq 4(%esp),%mm1 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm2.asm b/MdePkg/Library/BaseLib/ia32/WriteMm2.asm new file mode 100644 index 0000000000..a18417a0d1 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm2.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm2.Asm +; +; Abstract: +; +; AsmWriteMm2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMm2 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteMm2 PROC + movq mm2, [esp + 4] + ret +_AsmWriteMm2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm2.s b/MdePkg/Library/BaseLib/ia32/WriteMm2.s new file mode 100644 index 0000000000..eaebb37636 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm2.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteMm2.Asm +# +# Abstract: +# +# AsmWriteMm2 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmWriteMm2 ( +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteMm2 +_AsmWriteMm2: + movq 4(%esp),%mm2 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm3.asm b/MdePkg/Library/BaseLib/ia32/WriteMm3.asm new file mode 100644 index 0000000000..7aad49f77f --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm3.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm3.Asm +; +; Abstract: +; +; AsmWriteMm3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMm3 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteMm3 PROC + movq mm3, [esp + 4] + ret +_AsmWriteMm3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm3.s b/MdePkg/Library/BaseLib/ia32/WriteMm3.s new file mode 100644 index 0000000000..a514091732 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm3.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteMm3.Asm +# +# Abstract: +# +# AsmWriteMm3 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmWriteMm3 ( +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteMm3 +_AsmWriteMm3: + movq 4(%esp),%mm3 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm4.asm b/MdePkg/Library/BaseLib/ia32/WriteMm4.asm new file mode 100644 index 0000000000..8be9c4beb8 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm4.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm4.Asm +; +; Abstract: +; +; AsmWriteMm4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMm4 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteMm4 PROC + movq mm4, [esp + 4] + ret +_AsmWriteMm4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm4.s b/MdePkg/Library/BaseLib/ia32/WriteMm4.s new file mode 100644 index 0000000000..6d4a6cdce1 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm4.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteMm4.Asm +# +# Abstract: +# +# AsmWriteMm4 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmWriteMm4 ( +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteMm4 +_AsmWriteMm4: + movq 4(%esp),%mm4 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm5.asm b/MdePkg/Library/BaseLib/ia32/WriteMm5.asm new file mode 100644 index 0000000000..bc501b397c --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm5.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm5.Asm +; +; Abstract: +; +; AsmWriteMm5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMm5 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteMm5 PROC + movq mm5, [esp + 4] + ret +_AsmWriteMm5 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm5.s b/MdePkg/Library/BaseLib/ia32/WriteMm5.s new file mode 100644 index 0000000000..15d433271f --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm5.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteMm5.Asm +# +# Abstract: +# +# AsmWriteMm5 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmWriteMm5 ( +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteMm5 +_AsmWriteMm5: + movq 4(%esp),%mm5 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm6.asm b/MdePkg/Library/BaseLib/ia32/WriteMm6.asm new file mode 100644 index 0000000000..4a6445cb63 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm6.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm6.Asm +; +; Abstract: +; +; AsmWriteMm6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMm6 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteMm6 PROC + movq mm6, [esp + 4] + ret +_AsmWriteMm6 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm6.s b/MdePkg/Library/BaseLib/ia32/WriteMm6.s new file mode 100644 index 0000000000..6b1361e7a3 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm6.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteMm6.Asm +# +# Abstract: +# +# AsmWriteMm6 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmWriteMm6 ( +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteMm6 +_AsmWriteMm6: + movq 4(%esp),%mm6 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm7.asm b/MdePkg/Library/BaseLib/ia32/WriteMm7.asm new file mode 100644 index 0000000000..3bc73fed27 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm7.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm7.Asm +; +; Abstract: +; +; AsmWriteMm7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .xmm + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMm7 ( +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteMm7 PROC + movq mm7, [esp + 4] + ret +_AsmWriteMm7 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteMm7.s b/MdePkg/Library/BaseLib/ia32/WriteMm7.s new file mode 100644 index 0000000000..d702fbb242 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMm7.s @@ -0,0 +1,42 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteMm7.Asm +# +# Abstract: +# +# AsmWriteMm7 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmWriteMm7 ( +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteMm7 +_AsmWriteMm7: + movq 4(%esp),%mm7 + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteMsr32.asm b/MdePkg/Library/BaseLib/ia32/WriteMsr32.asm new file mode 100644 index 0000000000..ba14514c93 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMsr32.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMsr32.Asm +; +; Abstract: +; +; AsmWriteMsr32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; AsmWriteMsr32 ( +; IN UINT32 Index, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteMsr32 PROC + mov eax, [esp + 8] + xor edx, edx + mov ecx, [esp + 4] + wrmsr + ret +_AsmWriteMsr32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteMsr32.s b/MdePkg/Library/BaseLib/ia32/WriteMsr32.s new file mode 100644 index 0000000000..450b3b7b9f --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMsr32.s @@ -0,0 +1,45 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteMsr32.Asm +# +# Abstract: +# +# AsmWriteMsr32 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT32 +# EFIAPI +# AsmWriteMsr32 ( +# IN UINT32 Index, +# IN UINT32 Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteMsr32 +_AsmWriteMsr32: + movl 8(%esp),%eax + xorl %edx,%edx + movl 4(%esp),%ecx + wrmsr + ret + + + diff --git a/MdePkg/Library/BaseLib/ia32/WriteMsr64.asm b/MdePkg/Library/BaseLib/ia32/WriteMsr64.asm new file mode 100644 index 0000000000..5afc074291 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMsr64.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMsr64.Asm +; +; Abstract: +; +; AsmWriteMsr64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .586P + .model flat + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMsr64 ( +; IN UINT32 Index, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +_AsmWriteMsr64 PROC + mov edx, [esp + 12] + mov eax, [esp + 8] + mov ecx, [esp + 4] + wrmsr + ret +_AsmWriteMsr64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/ia32/WriteMsr64.s b/MdePkg/Library/BaseLib/ia32/WriteMsr64.s new file mode 100644 index 0000000000..802aad7803 --- /dev/null +++ b/MdePkg/Library/BaseLib/ia32/WriteMsr64.s @@ -0,0 +1,45 @@ +#------------------------------------------------------------------------------ +# +# Copyright (c) 2006, 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. +# +# Module Name: +# +# WriteMsr64.Asm +# +# Abstract: +# +# AsmWriteMsr64 function +# +# Notes: +# +#------------------------------------------------------------------------------ + + + + + +#------------------------------------------------------------------------------ +# UINT64 +# EFIAPI +# AsmWriteMsr64 ( +# IN UINT32 Index, +# IN UINT64 Value +# ); +#------------------------------------------------------------------------------ +.global _AsmWriteMsr64 +_AsmWriteMsr64: + movl 12(%esp),%edx + movl 8(%esp),%eax + movl 4(%esp),%ecx + wrmsr + ret + + + diff --git a/MdePkg/Library/BaseLib/x64/CpuBreakpoint.asm b/MdePkg/Library/BaseLib/x64/CpuBreakpoint.asm new file mode 100644 index 0000000000..f1ebe47b21 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/CpuBreakpoint.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuBreakpoint.Asm +; +; Abstract: +; +; CpuBreakpoint function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuBreakpoint ( +; VOID +; ); +;------------------------------------------------------------------------------ +CpuBreakpoint PROC + int 3 + ret +CpuBreakpoint ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/CpuFlushTlb.asm b/MdePkg/Library/BaseLib/x64/CpuFlushTlb.asm new file mode 100644 index 0000000000..c2c4490e9d --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/CpuFlushTlb.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuFlushTlb.Asm +; +; Abstract: +; +; CpuFlushTlb function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuFlushTlb ( +; VOID +; ); +;------------------------------------------------------------------------------ +CpuFlushTlb PROC + mov rax, cr3 + mov cr3, rax + ret +CpuFlushTlb ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/CpuId.asm b/MdePkg/Library/BaseLib/x64/CpuId.asm new file mode 100644 index 0000000000..867e92a677 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/CpuId.asm @@ -0,0 +1,62 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuId.Asm +; +; Abstract: +; +; AsmCpuid function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmCpuid ( +; IN UINT32 RegisterInEax, +; OUT UINT32 *RegisterOutEax OPTIONAL, +; OUT UINT32 *RegisterOutEbx OPTIONAL, +; OUT UINT32 *RegisterOutEcx OPTIONAL, +; OUT UINT32 *RegisterOutEdx OPTIONAL +; ) +;------------------------------------------------------------------------------ +AsmCpuid PROC USES rbx + mov eax, ecx + push rdx + push rax ; save Index on stack + cpuid + test r9, r9 + jz @F + mov [r9], ecx +@@: + pop rcx + jrcxz @F + mov [rcx], eax +@@: + mov rcx, r8 + jrcxz @F + mov [rcx], ebx +@@: + mov rcx, [rsp + 30h] + jrcxz @F + mov [rcx], edx +@@: + pop rax ; restore Index to rax as return value + ret +AsmCpuid ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/CpuPause.asm b/MdePkg/Library/BaseLib/x64/CpuPause.asm new file mode 100644 index 0000000000..d16da37712 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/CpuPause.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuPause.Asm +; +; Abstract: +; +; CpuPause function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuPause ( +; VOID +; ); +;------------------------------------------------------------------------------ +CpuPause PROC + pause + ret +CpuPause ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/CpuSleep.asm b/MdePkg/Library/BaseLib/x64/CpuSleep.asm new file mode 100644 index 0000000000..b2c4907032 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/CpuSleep.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ ; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CpuSleep.Asm +; +; Abstract: +; +; CpuSleep function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; CpuSleep ( +; VOID +; ); +;------------------------------------------------------------------------------ +CpuSleep PROC + hlt + ret +CpuSleep ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/DisableInterrupts.asm b/MdePkg/Library/BaseLib/x64/DisableInterrupts.asm new file mode 100644 index 0000000000..586832c1a2 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/DisableInterrupts.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; DisableInterrupts.Asm +; +; Abstract: +; +; DisableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; DisableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +DisableInterrupts PROC + cli + ret +DisableInterrupts ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/DisablePaging64.asm b/MdePkg/Library/BaseLib/x64/DisablePaging64.asm new file mode 100644 index 0000000000..3134e42571 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/DisablePaging64.asm @@ -0,0 +1,54 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; DisablePaging64.Asm +; +; Abstract: +; +; AsmDisablePaging64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalX86DisablePaging64 PROC + cli + shl rcx, 32 + lea ecx, @F + push rcx + mov ebx, edx + mov esi, r8d + mov edi, r9d + mov eax, [rsp + 28h] + retf +@@: + mov esp, eax ; set up new stack + mov rax, cr0 + btr eax, 31 + mov cr0, rax ; disable paging + mov ecx, 0c0000080h + rdmsr + and ah, NOT 1 ; clear LME + wrmsr + mov rax, cr4 + and al, NOT (1 SHL 5) ; clear PAE + mov cr4, rax + push rdi + push rsi + call rbx + jmp $ +InternalX86DisablePaging64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/EnableDisableInterrupts.asm b/MdePkg/Library/BaseLib/x64/EnableDisableInterrupts.asm new file mode 100644 index 0000000000..0d0400f007 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/EnableDisableInterrupts.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; EnableDisableInterrupts.Asm +; +; Abstract: +; +; EnableDisableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; EnableDisableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +EnableDisableInterrupts PROC + sti + cli + ret +EnableDisableInterrupts ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/EnableInterrupts.asm b/MdePkg/Library/BaseLib/x64/EnableInterrupts.asm new file mode 100644 index 0000000000..8fb4adfe37 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/EnableInterrupts.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; EnableInterrupts.Asm +; +; Abstract: +; +; EnableInterrupts function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; EnableInterrupts ( +; VOID +; ); +;------------------------------------------------------------------------------ +EnableInterrupts PROC + sti + ret +EnableInterrupts ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/FlushCacheLine.asm b/MdePkg/Library/BaseLib/x64/FlushCacheLine.asm new file mode 100644 index 0000000000..1d470e8753 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/FlushCacheLine.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; FlushCacheLine.Asm +; +; Abstract: +; +; AsmFlushCacheLine function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmFlushCacheLine ( +; IN VOID *LinearAddress +; ); +;------------------------------------------------------------------------------ +AsmFlushCacheLine PROC + clflush [rcx] + ret +AsmFlushCacheLine ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/FxRestore.asm b/MdePkg/Library/BaseLib/x64/FxRestore.asm new file mode 100644 index 0000000000..8acfc2f00f --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/FxRestore.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; FxRestore.Asm +; +; Abstract: +; +; AsmFxRestore function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalX86FxRestore PROC + fxrstor [rcx] + ret +InternalX86FxRestore ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/FxSave.asm b/MdePkg/Library/BaseLib/x64/FxSave.asm new file mode 100644 index 0000000000..cacb1f5283 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/FxSave.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; FxSave.Asm +; +; Abstract: +; +; AsmFxSave function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalX86FxSave PROC + fxsave [rcx] + ret +InternalX86FxSave ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/InterlockedCompareExchange32.asm b/MdePkg/Library/BaseLib/x64/InterlockedCompareExchange32.asm new file mode 100644 index 0000000000..55b055453f --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/InterlockedCompareExchange32.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; InterlockedCompareExchange32.Asm +; +; Abstract: +; +; InterlockedCompareExchange32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InterlockedCompareExchange32 ( +; IN UINT32 *Value, +; IN UINT32 CompareValue, +; IN UINT32 ExchangeValue +; ); +;------------------------------------------------------------------------------ +InternalSyncCompareExchange32 PROC + mov eax, edx + lock cmpxchg [rcx], r8d + ret +InternalSyncCompareExchange32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/InterlockedCompareExchange64.asm b/MdePkg/Library/BaseLib/x64/InterlockedCompareExchange64.asm new file mode 100644 index 0000000000..88c25a56de --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/InterlockedCompareExchange64.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; InterlockedCompareExchange64.Asm +; +; Abstract: +; +; InterlockedCompareExchange64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; InterlockedCompareExchange64 ( +; IN UINT64 *Value, +; IN UINT64 CompareValue, +; IN UINT64 ExchangeValue +; ); +;------------------------------------------------------------------------------ +InternalSyncCompareExchange64 PROC + mov rax, rdx + lock cmpxchg [rcx], r8 + ret +InternalSyncCompareExchange64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/InterlockedDecrement.asm b/MdePkg/Library/BaseLib/x64/InterlockedDecrement.asm new file mode 100644 index 0000000000..f907fed4a8 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/InterlockedDecrement.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; InterlockedDecrement.Asm +; +; Abstract: +; +; InterlockedDecrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InterlockedDecrement ( +; IN UINT32 *Value +; ); +;------------------------------------------------------------------------------ +InternalSyncDecrement PROC + lock dec dword ptr [rcx] + mov eax, [rcx] + ret +InternalSyncDecrement ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/InterlockedIncrement.asm b/MdePkg/Library/BaseLib/x64/InterlockedIncrement.asm new file mode 100644 index 0000000000..f5a4130bf1 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/InterlockedIncrement.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; InterlockedIncrement.Asm +; +; Abstract: +; +; InterlockedIncrement function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; InterlockedIncrement ( +; IN UINT32 *Value +; ); +;------------------------------------------------------------------------------ +InternalSyncIncrement PROC + lock inc dword ptr [rcx] + mov eax, [rcx] + ret +InternalSyncIncrement ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/Invd.asm b/MdePkg/Library/BaseLib/x64/Invd.asm new file mode 100644 index 0000000000..446587923b --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/Invd.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Invd.Asm +; +; Abstract: +; +; AsmInvd function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmInvd ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmInvd PROC + invd + ret +AsmInvd ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/LongJump.asm b/MdePkg/Library/BaseLib/x64/LongJump.asm new file mode 100644 index 0000000000..6634778592 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/LongJump.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; LongJump.Asm +; +; Abstract: +; +; Implementation of LongJump() on x64. +; +;------------------------------------------------------------------------------ + + .code + +LongJump PROC + mov rbx, [rcx] + mov rsp, [rcx + 8] + mov rbp, [rcx + 10h] + mov rdi, [rcx + 18h] + mov rsi, [rcx + 20h] + mov r12, [rcx + 28h] + mov r13, [rcx + 30h] + mov r14, [rcx + 38h] + mov r15, [rcx + 40h] + mov rax, rdx + jmp qword ptr [rcx + 48h] +LongJump ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/Monitor.asm b/MdePkg/Library/BaseLib/x64/Monitor.asm new file mode 100644 index 0000000000..0140494d30 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/Monitor.asm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Monitor.Asm +; +; Abstract: +; +; AsmMonitor function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmMonitor ( +; IN UINTN Eax, +; IN UINTN Ecx, +; IN UINTN Edx +; ); +;------------------------------------------------------------------------------ +AsmMonitor PROC + mov eax, ecx + mov ecx, edx + mov edx, r8d + DB 0fh, 1, 0c8h + ret +AsmMonitor ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/Mwait.asm b/MdePkg/Library/BaseLib/x64/Mwait.asm new file mode 100644 index 0000000000..8f76d944f1 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/Mwait.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Mwait.Asm +; +; Abstract: +; +; AsmMwait function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmMwait ( +; IN UINTN Eax, +; IN UINTN Ecx +; ); +;------------------------------------------------------------------------------ +AsmMwait PROC + mov eax, ecx + mov ecx, edx + DB 0fh, 1, 0c9h + ret +AsmMwait ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/Non-existing.c b/MdePkg/Library/BaseLib/x64/Non-existing.c new file mode 100644 index 0000000000..b2c737857d --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/Non-existing.c @@ -0,0 +1,54 @@ +/** @file + Non-existing BaseLib functions on x64 + + Copyright (c) 2006, 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. + + Module Name: Non-existing.c + +**/ + +#include "../BaseLibInternals.h" + +VOID +EFIAPI +InternalX86EnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + ASSERT (FALSE); +} + +VOID +EFIAPI +InternalX86DisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + ASSERT (FALSE); +} + +VOID +EFIAPI +InternalX86EnablePaging64 ( + IN UINT16 Cs, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ) +{ + ASSERT (FALSE); +} diff --git a/MdePkg/Library/BaseLib/x64/ReadCr0.asm b/MdePkg/Library/BaseLib/x64/ReadCr0.asm new file mode 100644 index 0000000000..3e369c3a81 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadCr0.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadCr0.Asm +; +; Abstract: +; +; AsmReadCr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadCr0 PROC + mov rax, cr0 + ret +AsmReadCr0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadCr2.asm b/MdePkg/Library/BaseLib/x64/ReadCr2.asm new file mode 100644 index 0000000000..8476f5af18 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadCr2.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadCr2.Asm +; +; Abstract: +; +; AsmReadCr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadCr2 PROC + mov rax, cr2 + ret +AsmReadCr2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadCr3.asm b/MdePkg/Library/BaseLib/x64/ReadCr3.asm new file mode 100644 index 0000000000..af54d46373 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadCr3.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadCr3.Asm +; +; Abstract: +; +; AsmReadCr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadCr3 PROC + mov rax, cr3 + ret +AsmReadCr3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadCr4.asm b/MdePkg/Library/BaseLib/x64/ReadCr4.asm new file mode 100644 index 0000000000..c8a881db9e --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadCr4.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadCr4.Asm +; +; Abstract: +; +; AsmReadCr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadCr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadCr4 PROC + mov rax, cr4 + ret +AsmReadCr4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadCs.asm b/MdePkg/Library/BaseLib/x64/ReadCs.asm new file mode 100644 index 0000000000..126149a47c --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadCs.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadCs.Asm +; +; Abstract: +; +; AsmReadCs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadCs ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadCs PROC + mov ax, cs + ret +AsmReadCs ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadDr0.asm b/MdePkg/Library/BaseLib/x64/ReadDr0.asm new file mode 100644 index 0000000000..7e0d6b714a --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadDr0.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr0.Asm +; +; Abstract: +; +; AsmReadDr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadDr0 PROC + mov rax, dr0 + ret +AsmReadDr0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadDr1.asm b/MdePkg/Library/BaseLib/x64/ReadDr1.asm new file mode 100644 index 0000000000..22f11c4e0f --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadDr1.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr1.Asm +; +; Abstract: +; +; AsmReadDr1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr1 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadDr1 PROC + mov rax, dr1 + ret +AsmReadDr1 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadDr2.asm b/MdePkg/Library/BaseLib/x64/ReadDr2.asm new file mode 100644 index 0000000000..3b81605861 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadDr2.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr2.Asm +; +; Abstract: +; +; AsmReadDr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadDr2 PROC + mov rax, dr2 + ret +AsmReadDr2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadDr3.asm b/MdePkg/Library/BaseLib/x64/ReadDr3.asm new file mode 100644 index 0000000000..1968fd0d67 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadDr3.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr3.Asm +; +; Abstract: +; +; AsmReadDr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadDr3 PROC + mov rax, dr3 + ret +AsmReadDr3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadDr4.asm b/MdePkg/Library/BaseLib/x64/ReadDr4.asm new file mode 100644 index 0000000000..97740016b3 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadDr4.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr4.Asm +; +; Abstract: +; +; AsmReadDr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadDr4 PROC + DB 0fh, 21h, 0e0h + ret +AsmReadDr4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadDr5.asm b/MdePkg/Library/BaseLib/x64/ReadDr5.asm new file mode 100644 index 0000000000..0582502220 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadDr5.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr5.Asm +; +; Abstract: +; +; AsmReadDr5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr5 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadDr5 PROC + DB 0fh, 21h, 0e8h + ret +AsmReadDr5 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadDr6.asm b/MdePkg/Library/BaseLib/x64/ReadDr6.asm new file mode 100644 index 0000000000..a3dafb9b9f --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadDr6.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr6.Asm +; +; Abstract: +; +; AsmReadDr6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr6 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadDr6 PROC + mov rax, dr6 + ret +AsmReadDr6 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadDr7.asm b/MdePkg/Library/BaseLib/x64/ReadDr7.asm new file mode 100644 index 0000000000..0cff14b5c4 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadDr7.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDr7.Asm +; +; Abstract: +; +; AsmReadDr7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadDr7 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadDr7 PROC + mov rax, dr7 + ret +AsmReadDr7 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadDs.asm b/MdePkg/Library/BaseLib/x64/ReadDs.asm new file mode 100644 index 0000000000..bdcddb65d8 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadDs.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadDs.Asm +; +; Abstract: +; +; AsmReadDs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadDs ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadDs PROC + mov ax, ds + ret +AsmReadDs ENDP + + END + diff --git a/MdePkg/Library/BaseLib/x64/ReadEflags.asm b/MdePkg/Library/BaseLib/x64/ReadEflags.asm new file mode 100644 index 0000000000..174ae95887 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadEflags.asm @@ -0,0 +1,39 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadEflags.Asm +; +; Abstract: +; +; AsmReadEflags function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadEflags ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadEflags PROC + pushfq + pop rax + ret +AsmReadEflags ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadEs.asm b/MdePkg/Library/BaseLib/x64/ReadEs.asm new file mode 100644 index 0000000000..40384bcd71 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadEs.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadEs.Asm +; +; Abstract: +; +; AsmReadEs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadEs ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadEs PROC + mov ax, es + ret +AsmReadEs ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadFs.asm b/MdePkg/Library/BaseLib/x64/ReadFs.asm new file mode 100644 index 0000000000..b63e474023 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadFs.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadFs.Asm +; +; Abstract: +; +; AsmReadFs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadFs ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadFs PROC + mov ax, fs + ret +AsmReadFs ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadGdtr.asm b/MdePkg/Library/BaseLib/x64/ReadGdtr.asm new file mode 100644 index 0000000000..2d40599a8b --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadGdtr.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadGdtr.Asm +; +; Abstract: +; +; AsmReadGdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalX86ReadGdtr PROC + sgdt fword ptr [rcx] + ret +InternalX86ReadGdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadGs.asm b/MdePkg/Library/BaseLib/x64/ReadGs.asm new file mode 100644 index 0000000000..02d140e670 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadGs.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadGs.Asm +; +; Abstract: +; +; AsmReadGs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadGs ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadGs PROC + mov ax, gs + ret +AsmReadGs ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadIdtr.asm b/MdePkg/Library/BaseLib/x64/ReadIdtr.asm new file mode 100644 index 0000000000..260f697178 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadIdtr.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadIdtr.Asm +; +; Abstract: +; +; AsmReadIdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalX86ReadIdtr PROC + sidt fword ptr [rcx] + ret +InternalX86ReadIdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadLdtr.asm b/MdePkg/Library/BaseLib/x64/ReadLdtr.asm new file mode 100644 index 0000000000..3d6a2f8843 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadLdtr.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadLdtr.Asm +; +; Abstract: +; +; AsmReadLdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadLdtr ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadLdtr PROC + sldt eax + ret +AsmReadLdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadMm0.asm b/MdePkg/Library/BaseLib/x64/ReadMm0.asm new file mode 100644 index 0000000000..1239bcacd6 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadMm0.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm0.Asm +; +; Abstract: +; +; AsmReadMm0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadMm0 PROC + DB 48h, 0fh, 7eh, 0c0h + ret +AsmReadMm0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadMm1.asm b/MdePkg/Library/BaseLib/x64/ReadMm1.asm new file mode 100644 index 0000000000..b42bd7f63f --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadMm1.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm1.Asm +; +; Abstract: +; +; AsmReadMm1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm1 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadMm1 PROC + DB 48h, 0fh, 7eh, 0c8h + ret +AsmReadMm1 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadMm2.asm b/MdePkg/Library/BaseLib/x64/ReadMm2.asm new file mode 100644 index 0000000000..b10782e403 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadMm2.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm2.Asm +; +; Abstract: +; +; AsmReadMm2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadMm2 PROC + DB 48h, 0fh, 7eh, 0d0h + ret +AsmReadMm2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadMm3.asm b/MdePkg/Library/BaseLib/x64/ReadMm3.asm new file mode 100644 index 0000000000..15a96475bd --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadMm3.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm3.Asm +; +; Abstract: +; +; AsmReadMm3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadMm3 PROC + DB 48h, 0fh, 7eh, 0d8h + ret +AsmReadMm3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadMm4.asm b/MdePkg/Library/BaseLib/x64/ReadMm4.asm new file mode 100644 index 0000000000..73f528342e --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadMm4.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm4.Asm +; +; Abstract: +; +; AsmReadMm4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadMm4 PROC + DB 48h, 0fh, 7eh, 0e0h + ret +AsmReadMm4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadMm5.asm b/MdePkg/Library/BaseLib/x64/ReadMm5.asm new file mode 100644 index 0000000000..a487889480 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadMm5.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm5.Asm +; +; Abstract: +; +; AsmReadMm5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm5 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadMm5 PROC + DB 48h, 0fh, 7eh, 0e8h + ret +AsmReadMm5 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadMm6.asm b/MdePkg/Library/BaseLib/x64/ReadMm6.asm new file mode 100644 index 0000000000..56f81bf7b1 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadMm6.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm6.Asm +; +; Abstract: +; +; AsmReadMm6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm6 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadMm6 PROC + DB 48h, 0fh, 7eh, 0f0h + ret +AsmReadMm6 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadMm7.asm b/MdePkg/Library/BaseLib/x64/ReadMm7.asm new file mode 100644 index 0000000000..e3ad6bb658 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadMm7.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMm7.Asm +; +; Abstract: +; +; AsmReadMm7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmReadMm7 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadMm7 PROC + DB 48h, 0fh, 7eh, 0f8h + ret +AsmReadMm7 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadMsr32.asm b/MdePkg/Library/BaseLib/x64/ReadMsr32.asm new file mode 100644 index 0000000000..271eabbeae --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadMsr32.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMsr32.Asm +; +; Abstract: +; +; AsmReadMsr32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; AsmReadMsr32 ( +; IN UINT32 Index +; ); +;------------------------------------------------------------------------------ +AsmReadMsr32 PROC + rdmsr + ret +AsmReadMsr32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadMsr64.asm b/MdePkg/Library/BaseLib/x64/ReadMsr64.asm new file mode 100644 index 0000000000..4444c18676 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadMsr64.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadMsr64.Asm +; +; Abstract: +; +; AsmReadMsr64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadMsr64 ( +; IN UINT32 Index +; ); +;------------------------------------------------------------------------------ +AsmReadMsr64 PROC + rdmsr + shl rax, 20h + shrd rax, rdx, 20h + ret +AsmReadMsr64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadPmc.asm b/MdePkg/Library/BaseLib/x64/ReadPmc.asm new file mode 100644 index 0000000000..b5004d6f34 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadPmc.asm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadPmc.Asm +; +; Abstract: +; +; AsmReadPmc function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadPmc ( +; IN UINT32 PmcIndex +; ); +;------------------------------------------------------------------------------ +AsmReadPmc PROC + rdpmc + shl ecx, 1 + jnc @F + shl rax, 20h + shrd rax, rdx, 20h +@@: + ret +AsmReadPmc ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadSs.asm b/MdePkg/Library/BaseLib/x64/ReadSs.asm new file mode 100644 index 0000000000..4aa480d71b --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadSs.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadSs.Asm +; +; Abstract: +; +; AsmReadSs function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadSs ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadSs PROC + mov ax, ss + ret +AsmReadSs ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadTr.asm b/MdePkg/Library/BaseLib/x64/ReadTr.asm new file mode 100644 index 0000000000..7cf8cdfd43 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadTr.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadTr.Asm +; +; Abstract: +; +; AsmReadTr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT16 +; EFIAPI +; AsmReadTr ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadTr PROC + str eax + ret +AsmReadTr ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/ReadTsc.asm b/MdePkg/Library/BaseLib/x64/ReadTsc.asm new file mode 100644 index 0000000000..25fa2cc5d8 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/ReadTsc.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ReadTsc.Asm +; +; Abstract: +; +; AsmReadTsc function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmReadTsc ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmReadTsc PROC + rdtsc + shl rax, 20h + shrd rax, rdx, 20h + ret +AsmReadTsc ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/SetJump.asm b/MdePkg/Library/BaseLib/x64/SetJump.asm new file mode 100644 index 0000000000..305e721b8b --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/SetJump.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetJump.Asm +; +; Abstract: +; +; Implementation of SetJump() on x64. +; +;------------------------------------------------------------------------------ + + .code + +SetJump PROC + pop rdx + mov [rcx], rbx + mov [rcx + 8], rsp + mov [rcx + 10h], rbp + mov [rcx + 18h], rdi + mov [rcx + 20h], rsi + mov [rcx + 28h], r12 + mov [rcx + 30h], r13 + mov [rcx + 38h], r14 + mov [rcx + 40h], r15 + mov [rcx + 48h], rdx + xor rax, rax + jmp rdx +SetJump ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/SwitchStack.asm b/MdePkg/Library/BaseLib/x64/SwitchStack.asm new file mode 100644 index 0000000000..0dfddc011b --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/SwitchStack.asm @@ -0,0 +1,47 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SwitchStack.Asm +; +; Abstract: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; Routine Description: +; +; Routine for switching stacks with 1 parameter +; +; Arguments: +; +; (rcx) EntryPoint - Entry point with new stack. +; (rdx) Context - Parameter for entry point. +; (r8) Context2 - Parameter2 for entry point. +; (r9) NewStack - Pointer to new stack. +; +; Returns: +; +; None +; +;------------------------------------------------------------------------------ +SwitchStack PROC + mov rax, rcx + mov rcx, rdx + mov rdx, r8 + lea rsp, [r9 - 20h] + call rax +SwitchStack ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/Thunk16.asm b/MdePkg/Library/BaseLib/x64/Thunk16.asm new file mode 100644 index 0000000000..f3e80840b3 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/Thunk16.asm @@ -0,0 +1,189 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Thunk.asm +; +; Abstract: +; +; Real mode thunk +; +;------------------------------------------------------------------------------ + + .data + +NullSegSel DQ 0 +_16CsSegSel LABEL QWORD + DW -1 + DW 0 + DB 0 + DB 9bh + DB 8fh ; 16-bit segment + DB 0 +_16BitDsSel LABEL QWORD + DW -1 + DW 0 + DB 0 + DB 93h + DB 8fh ; 16-bit segment + DB 0 +GdtEnd LABEL QWORD + + .const + +_16Gdtr LABEL FWORD + DW offset GdtEnd - offset NullSegSel - 1 + DQ offset NullSegSel + +_16Idtr FWORD (1 SHL 10) - 1 + + .code + +IA32_REGS STRUC 4t +_EDI DD ? +_ESI DD ? +_EBP DD ? +_ESP DD ? +_EBX DD ? +_EDX DD ? +_ECX DD ? +_EAX DD ? +_DS DW ? +_ES DW ? +_FS DW ? +_GS DW ? +_RFLAGS DQ ? +_EIP DD ? +_CS DW ? +_SS DW ? +IA32_REGS ENDS + +InternalAsmThunk16 PROC USES rbp rbx rsi rdi r12 r13 r14 r15 + mov eax, ds + push rax + mov eax, es + push rax + push fs + push gs + mov rsi, rcx ; rsi <- RegSet + push sizeof (IA32_REGS) + pop rcx + movzx r8, (IA32_REGS ptr [rsi])._SS + xor rdi, rdi + mov edi, (IA32_REGS ptr [rsi])._ESP + sub rdi, rcx ; reserve space on realmode stack + push rdi ; save stack offset + imul rax, r8, 16 + add rdi, rax ; rdi <- linear address of 16-bit stack + rep movsb ; copy RegSet + mov rsi, r8 ; si <- 16-bit stack segment + pop rbx ; rbx <- 16-bit stack offset + mov rdi, rdx ; rdi <- realmode patch + lea eax, @BackToThunk ; rax <- address to back from real mode + push rax ; use in a far return + mov eax, cs + mov [rsp + 4], eax ; save CS + lea eax, @16Return ; thus @Return must < 4GB + stosd ; set ret address offset + xor eax, eax + stosw ; set ret CS base to 0 + mov eax, esp + stosd ; rsp must < 4GB + mov eax, ss + stosd + mov rax, cr0 + mov ecx, eax ; ecx <- CR0 + and ecx, 7ffffffeh ; clear PE, PG bits + stosd + mov rax, cr4 + mov ebp, eax + and ebp, 300h ; clear all but PCE and OSFXSR bits + stosd + sidt fword ptr [rsp + 70h] ; use parameter space to save IDTR + sgdt fword ptr [rdi] + lea edi, _16Idtr + lea eax, @16Start ; rax <- seg:offset of @16Start + push rax + mov dword ptr [rsp + 4], 8 + push 10h + pop rax ; rax <- 10h as dataseg selector + lgdt _16Gdtr + retf +@16Start: ; 16-bit starts here + mov ss, eax ; set SS to be a 16-bit segment + mov cr0, rcx ; disable protected mode + mov cr4, rbp + DB 66h + mov ecx, 0c0000080h + rdmsr + and ah, NOT 1 ; clear LME + wrmsr + mov ss, esi ; set up 16-bit stack + mov sp, bx ; mov esp, ebx actually + lidt fword ptr [edi] + DB 66h, 61h ; popad + DB 1fh ; pop ds + DB 7 ; pop es + pop fs + pop gs + add sp, 8 ; skip _RFLAGS + DB 66h + retf ; transfer control to 16-bit code +@16Return: + DB 66h + push 0 ; high order 32 bits of rflags + pushf ; pushfd actually + push gs + push fs + DB 6 ; push es + DB 1eh ; push ds + DB 66h, 60h ; pushad + DB 67h, 66h, 0c5h, 74h, 24h, 30h ; lds esi, [esp + 12*4] + DB 66h + mov eax, [esi + 12] + mov cr4, rax ; restore CR4 + DB 66h + lgdt fword ptr [esi + 16] + DB 66h + mov ecx, 0c0000080h + rdmsr + or ah, 1 ; set LME + wrmsr + DB 66h + mov eax, [esi + 8] + mov cr0, rax ; restore CR0 + xor ax, ax ; xor eax, eax actually + mov eax, ss + mov dword ptr (IA32_REGS ptr [esp])._SS, eax + shl ax, 4 ; shl eax, 4 actually + add ax, sp ; add eax, esp actually + add sp, sizeof (IA32_REGS) ; add esp, sizeof (IA32_REGS) + DB 66h + mov dword ptr (IA32_REGS ptr [esp - sizeof (IA32_REGS)])._ESP, esp + DB 66h + lss esp, fword ptr [esi] ; restore protected mode stack + DB 66h + retf ; go back to protected mode +@BackToThunk: + lidt fword ptr [rsp + 68h] ; restore protected mode IDTR + shl rax, 32 + shr rax, 32 ; clear high order 32 bits of RAX + pop gs + pop fs + pop rcx + mov es, ecx + pop rcx + mov ds, ecx + ret +InternalAsmThunk16 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/Wbinvd.asm b/MdePkg/Library/BaseLib/x64/Wbinvd.asm new file mode 100644 index 0000000000..ca0cb252b3 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/Wbinvd.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; Wbinvd.Asm +; +; Abstract: +; +; AsmWbinvd function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWbinvd ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWbinvd PROC + wbinvd + ret +AsmWbinvd ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteCr0.asm b/MdePkg/Library/BaseLib/x64/WriteCr0.asm new file mode 100644 index 0000000000..defc7e7c96 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteCr0.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteCr0.Asm +; +; Abstract: +; +; AsmWriteCr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteCr0 PROC + mov cr0, rcx + ret +AsmWriteCr0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteCr2.asm b/MdePkg/Library/BaseLib/x64/WriteCr2.asm new file mode 100644 index 0000000000..ebe6f89d62 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteCr2.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteCr2.Asm +; +; Abstract: +; +; AsmWriteCr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteCr2 PROC + mov cr2, rcx + ret +AsmWriteCr2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteCr3.asm b/MdePkg/Library/BaseLib/x64/WriteCr3.asm new file mode 100644 index 0000000000..5715dea9b7 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteCr3.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteCr3.Asm +; +; Abstract: +; +; AsmWriteCr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteCr3 PROC + mov cr3, rcx + ret +AsmWriteCr3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteCr4.asm b/MdePkg/Library/BaseLib/x64/WriteCr4.asm new file mode 100644 index 0000000000..210744e16f --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteCr4.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteCr4.Asm +; +; Abstract: +; +; AsmWriteCr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteCr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteCr4 PROC + mov cr4, rcx + ret +AsmWriteCr4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteDr0.asm b/MdePkg/Library/BaseLib/x64/WriteDr0.asm new file mode 100644 index 0000000000..2515a20404 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteDr0.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr0.Asm +; +; Abstract: +; +; AsmWriteDr0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteDr0 PROC + mov dr0, rcx + ret +AsmWriteDr0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteDr1.asm b/MdePkg/Library/BaseLib/x64/WriteDr1.asm new file mode 100644 index 0000000000..89f36ac3f9 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteDr1.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr1.Asm +; +; Abstract: +; +; AsmWriteDr1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr1 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteDr1 PROC + mov dr1, rcx + ret +AsmWriteDr1 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteDr2.asm b/MdePkg/Library/BaseLib/x64/WriteDr2.asm new file mode 100644 index 0000000000..820977c2e4 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteDr2.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr2.Asm +; +; Abstract: +; +; AsmWriteDr2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteDr2 PROC + mov dr2, rcx + ret +AsmWriteDr2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteDr3.asm b/MdePkg/Library/BaseLib/x64/WriteDr3.asm new file mode 100644 index 0000000000..51c1407277 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteDr3.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr3.Asm +; +; Abstract: +; +; AsmWriteDr3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteDr3 PROC + mov dr3, rcx + ret +AsmWriteDr3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteDr4.asm b/MdePkg/Library/BaseLib/x64/WriteDr4.asm new file mode 100644 index 0000000000..12b643825b --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteDr4.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr4.Asm +; +; Abstract: +; +; AsmWriteDr4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteDr4 PROC + DB 0fh, 23h, 0e1h + ret +AsmWriteDr4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteDr5.asm b/MdePkg/Library/BaseLib/x64/WriteDr5.asm new file mode 100644 index 0000000000..6d454d5267 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteDr5.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr5.Asm +; +; Abstract: +; +; AsmWriteDr5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr5 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteDr5 PROC + DB 0fh, 23h, 0e9h + ret +AsmWriteDr5 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteDr6.asm b/MdePkg/Library/BaseLib/x64/WriteDr6.asm new file mode 100644 index 0000000000..b7b9f2509d --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteDr6.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr6.Asm +; +; Abstract: +; +; AsmWriteDr6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr6 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteDr6 PROC + mov dr6, rcx + ret +AsmWriteDr6 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteDr7.asm b/MdePkg/Library/BaseLib/x64/WriteDr7.asm new file mode 100644 index 0000000000..de2237b6e4 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteDr7.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteDr7.Asm +; +; Abstract: +; +; AsmWriteDr7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteDr7 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteDr7 PROC + mov dr7, rcx + ret +AsmWriteDr7 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteGdtr.asm b/MdePkg/Library/BaseLib/x64/WriteGdtr.asm new file mode 100644 index 0000000000..1757e3dea4 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteGdtr.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteGdtr.Asm +; +; Abstract: +; +; AsmWriteGdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalX86WriteGdtr PROC + lgdt fword ptr [rcx] + ret +InternalX86WriteGdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteIdtr.asm b/MdePkg/Library/BaseLib/x64/WriteIdtr.asm new file mode 100644 index 0000000000..09fcb9e457 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteIdtr.asm @@ -0,0 +1,31 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteIdtr.Asm +; +; Abstract: +; +; AsmWriteIdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalX86WriteIdtr PROC + lidt fword ptr [rcx] + ret +InternalX86WriteIdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteLdtr.asm b/MdePkg/Library/BaseLib/x64/WriteLdtr.asm new file mode 100644 index 0000000000..d85ae38f29 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteLdtr.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteLdtr.Asm +; +; Abstract: +; +; AsmWriteLdtr function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID +; EFIAPI +; AsmWriteLdtr ( +; IN UINT16 Ldtr +; ); +;------------------------------------------------------------------------------ +AsmWriteLdtr PROC + lldt cx + ret +AsmWriteLdtr ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteMm0.asm b/MdePkg/Library/BaseLib/x64/WriteMm0.asm new file mode 100644 index 0000000000..bb9a576125 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteMm0.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm0.Asm +; +; Abstract: +; +; AsmWriteMm0 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteMm0 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteMm0 PROC + DB 48h, 0fh, 6eh, 0c1h + ret +AsmWriteMm0 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteMm1.asm b/MdePkg/Library/BaseLib/x64/WriteMm1.asm new file mode 100644 index 0000000000..1bab3bcd8e --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteMm1.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm1.Asm +; +; Abstract: +; +; AsmWriteMm1 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteMm1 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteMm1 PROC + DB 48h, 0fh, 6eh, 0c9h + ret +AsmWriteMm1 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteMm2.asm b/MdePkg/Library/BaseLib/x64/WriteMm2.asm new file mode 100644 index 0000000000..97e8a6a676 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteMm2.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm2.Asm +; +; Abstract: +; +; AsmWriteMm2 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteMm2 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteMm2 PROC + DB 48h, 0fh, 6eh, 0d1h + ret +AsmWriteMm2 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteMm3.asm b/MdePkg/Library/BaseLib/x64/WriteMm3.asm new file mode 100644 index 0000000000..d55e19a406 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteMm3.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm3.Asm +; +; Abstract: +; +; AsmWriteMm3 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteMm3 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteMm3 PROC + DB 48h, 0fh, 6eh, 0d9h + ret +AsmWriteMm3 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteMm4.asm b/MdePkg/Library/BaseLib/x64/WriteMm4.asm new file mode 100644 index 0000000000..2a69b93bcc --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteMm4.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm4.Asm +; +; Abstract: +; +; AsmWriteMm4 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteMm4 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteMm4 PROC + DB 48h, 0fh, 6eh, 0e1h + ret +AsmWriteMm4 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteMm5.asm b/MdePkg/Library/BaseLib/x64/WriteMm5.asm new file mode 100644 index 0000000000..c4d798bcbd --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteMm5.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm5.Asm +; +; Abstract: +; +; AsmWriteMm5 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteMm5 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteMm5 PROC + DB 48h, 0fh, 6eh, 0e9h + ret +AsmWriteMm5 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteMm6.asm b/MdePkg/Library/BaseLib/x64/WriteMm6.asm new file mode 100644 index 0000000000..c0164f66da --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteMm6.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm6.Asm +; +; Abstract: +; +; AsmWriteMm6 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteMm6 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteMm6 PROC + DB 48h, 0fh, 6eh, 0f1h + ret +AsmWriteMm6 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteMm7.asm b/MdePkg/Library/BaseLib/x64/WriteMm7.asm new file mode 100644 index 0000000000..20768e2b78 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteMm7.asm @@ -0,0 +1,38 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMm7.Asm +; +; Abstract: +; +; AsmWriteMm7 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINTN +; EFIAPI +; AsmWriteMm7 ( +; VOID +; ); +;------------------------------------------------------------------------------ +AsmWriteMm7 PROC + DB 48h, 0fh, 6eh, 0f9h + ret +AsmWriteMm7 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteMsr32.asm b/MdePkg/Library/BaseLib/x64/WriteMsr32.asm new file mode 100644 index 0000000000..0a74403624 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteMsr32.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMsr32.Asm +; +; Abstract: +; +; AsmWriteMsr32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT32 +; EFIAPI +; AsmWriteMsr32 ( +; IN UINT32 Index, +; IN UINT32 Value +; ); +;------------------------------------------------------------------------------ +AsmWriteMsr32 PROC + mov eax, edx + xor edx, edx + wrmsr + ret +AsmWriteMsr32 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x64/WriteMsr64.asm b/MdePkg/Library/BaseLib/x64/WriteMsr64.asm new file mode 100644 index 0000000000..3337f45891 --- /dev/null +++ b/MdePkg/Library/BaseLib/x64/WriteMsr64.asm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; WriteMsr64.Asm +; +; Abstract: +; +; AsmWriteMsr64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; UINT64 +; EFIAPI +; AsmWriteMsr64 ( +; IN UINT32 Index, +; IN UINT64 Value +; ); +;------------------------------------------------------------------------------ +AsmWriteMsr64 PROC + push rdx + mov eax, edx + shr rdx, 20h + wrmsr + pop rax + ret +AsmWriteMsr64 ENDP + + END diff --git a/MdePkg/Library/BaseLib/x86LowLevel.c b/MdePkg/Library/BaseLib/x86LowLevel.c new file mode 100644 index 0000000000..c222c6ccb6 --- /dev/null +++ b/MdePkg/Library/BaseLib/x86LowLevel.c @@ -0,0 +1,979 @@ +/** @file + IA-32/x64 specific functions. + + Copyright (c) 2006, 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. + + Module Name: x86LowLevel.c + +**/ + +#include "BaseLibInternals.h" + +// +// Bit-wise MSR operations +// + +/** + Reads a 64-bit MSR, performs a bitwise inclusive OR on the lower 32-bits, and + writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise inclusive OR + between the lower 32-bits of the read result and the value specified by + OrData, and writes the result to the 64-bit MSR specified by Index. The lower + 32-bits of the value written to the MSR is returned. No parameter checking is + performed on Index or OrData, and some of these may cause CPU exceptions. The + caller must either guarantee that Index and OrData are valid, or the caller + must establish proper exception handlers. This function is only available on + IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param OrData The value to OR with the read value from the MSR. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrOr32 ( + IN UINT32 Index, + IN UINT32 OrData + ) +{ + return (UINT32)AsmMsrOr64 (Index, OrData); +} + +/** + Reads a 64-bit MSR, performs a bitwise AND on the lower 32-bits, and writes + the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + lower 32-bits of the read result and the value specified by AndData, and + writes the result to the 64-bit MSR specified by Index. The lower 32-bits of + the value written to the MSR is returned. No parameter checking is performed + on Index or AndData, and some of these may cause CPU exceptions. The caller + must either guarantee that Index and AndData are valid, or the caller must + establish proper exception handlers. This function is only available on IA-32 + and X64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrAnd32 ( + IN UINT32 Index, + IN UINT32 AndData + ) +{ + return (UINT32)AsmMsrAnd64 (Index, AndData); +} + +/** + Reads a 64-bit MSR, performs a bitwise AND followed by a bitwise inclusive OR + on the lower 32-bits, and writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + lower 32-bits of the read result and the value specified by AndData + preserving the upper 32-bits, performs a bitwise inclusive OR between the + result of the AND operation and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Address. The lower 32-bits of the value + written to the MSR is returned. No parameter checking is performed on Index, + AndData, or OrData, and some of these may cause CPU exceptions. The caller + must either guarantee that Index, AndData, and OrData are valid, or the + caller must establish proper exception handlers. This function is only + available on IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The lower 32-bit value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrAndThenOr32 ( + IN UINT32 Index, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return (UINT32)AsmMsrAndThenOr64 (Index, AndData, OrData); +} + +/** + Reads a bit field of an MSR. + + Reads the bit field in the lower 32-bits of a 64-bit MSR. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. The caller must either guarantee that Index is valid, or the caller + must set up exception handlers to catch the exceptions. This function is only + available on IA-32 and X64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The bit field read from the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldRead32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (AsmReadMsr32 (Index), StartBit, EndBit); +} + +/** + Writes a bit field to an MSR. + + Writes Value to a bit field in the lower 32-bits of a 64-bit MSR. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination MSR are preserved. The lower 32-bits of the MSR written is + returned. Extra left bits in Value are stripped. The caller must either + guarantee that Index and the data written is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and X64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldWrite32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + ASSERT (EndBit < sizeof (Value) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)AsmMsrBitFieldWrite64 (Index, StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The lower 32-bits of the value + written to the MSR are returned. Extra left bits in OrData are stripped. The + caller must either guarantee that Index and the data written is valid, or + the caller must set up exception handlers to catch the exceptions. This + function is only available on IA-32 and X64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the MSR. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldOr32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + ASSERT (EndBit < sizeof (OrData) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)AsmMsrBitFieldOr64 (Index, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by AndData, and writes the result to the + 64-bit MSR specified by Index. The lower 32-bits of the value written to the + MSR are returned. Extra left bits in AndData are stripped. The caller must + either guarantee that Index and the data written is valid, or the caller must + set up exception handlers to catch the exceptions. This function is only + available on IA-32 and X64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MSR. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldAnd32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + ASSERT (EndBit < sizeof (AndData) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)AsmMsrBitFieldAnd64 (Index, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND followed by a + bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 64-bit MSR specified by Index. The + lower 32-bits of the value written to the MSR are returned. Extra left bits + in both AndData and OrData are stripped. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 + and X64. + + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The lower 32-bit of the value written to the MSR. + +**/ +UINT32 +EFIAPI +AsmMsrBitFieldAndThenOr32 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT (EndBit < sizeof (AndData) * 8); + ASSERT (StartBit <= EndBit); + return (UINT32)AsmMsrBitFieldAndThenOr64 ( + Index, + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 64-bit MSR, performs a bitwise inclusive OR, and writes the result + back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The value written to the MSR is + returned. No parameter checking is performed on Index or OrData, and some of + these may cause CPU exceptions. The caller must either guarantee that Index + and OrData are valid, or the caller must establish proper exception handlers. + This function is only available on IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param OrData The value to OR with the read value from the MSR. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrOr64 ( + IN UINT32 Index, + IN UINT64 OrData + ) +{ + return AsmWriteMsr64 (Index, AsmReadMsr64 (Index) | OrData); +} + +/** + Reads a 64-bit MSR, performs a bitwise AND, and writes the result back to the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by OrData, and writes the result to the + 64-bit MSR specified by Index. The value written to the MSR is returned. No + parameter checking is performed on Index or OrData, and some of these may + cause CPU exceptions. The caller must either guarantee that Index and OrData + are valid, or the caller must establish proper exception handlers. This + function is only available on IA-32 and X64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrAnd64 ( + IN UINT32 Index, + IN UINT64 AndData + ) +{ + return AsmWriteMsr64 (Index, AsmReadMsr64 (Index) & AndData); +} + +/** + Reads a 64-bit MSR, performs a bitwise AND followed by a bitwise inclusive + OR, and writes the result back to the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between read + result and the value specified by AndData, performs a bitwise inclusive OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit MSR specified by Index. The value written + to the MSR is returned. No parameter checking is performed on Index, AndData, + or OrData, and some of these may cause CPU exceptions. The caller must either + guarantee that Index, AndData, and OrData are valid, or the caller must + establish proper exception handlers. This function is only available on IA-32 + and X64. + + @param Index The 32-bit MSR index to write. + @param AndData The value to AND with the read value from the MSR. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrAndThenOr64 ( + IN UINT32 Index, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return AsmWriteMsr64 (Index, (AsmReadMsr64 (Index) & AndData) | OrData); +} + +/** + Reads a bit field of an MSR. + + Reads the bit field in the 64-bit MSR. The bit field is specified by the + StartBit and the EndBit. The value of the bit field is returned. The caller + must either guarantee that Index is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and X64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldRead64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (AsmReadMsr64 (Index), StartBit, EndBit); +} + +/** + Writes a bit field to an MSR. + + Writes Value to a bit field in a 64-bit MSR. The bit field is specified by + the StartBit and the EndBit. All other bits in the destination MSR are + preserved. The MSR written is returned. Extra left bits in Value are + stripped. The caller must either guarantee that Index and the data written is + valid, or the caller must set up exception handlers to catch the exceptions. + This function is only available on IA-32 and X64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldWrite64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return AsmWriteMsr64 ( + Index, + BitFieldWrite64 (AsmReadMsr64 (Index), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise inclusive OR, and + writes the result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit MSR specified by Index. The value written to the MSR is + returned. Extra left bits in OrData are stripped. The caller must either + guarantee that Index and the data written is valid, or the caller must set up + exception handlers to catch the exceptions. This function is only available + on IA-32 and X64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldOr64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return AsmWriteMsr64 ( + Index, + BitFieldOr64 (AsmReadMsr64 (Index), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND between the + read result and the value specified by AndData, and writes the result to the + 64-bit MSR specified by Index. The value written to the MSR is returned. + Extra left bits in AndData are stripped. The caller must either guarantee + that Index and the data written is valid, or the caller must set up exception + handlers to catch the exceptions. This function is only available on IA-32 + and X64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the bit field. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldAnd64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return AsmWriteMsr64 ( + Index, + BitFieldAnd64 (AsmReadMsr64 (Index), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit MSR, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit MSR. + + Reads the 64-bit MSR specified by Index, performs a bitwise AND followed by + a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 64-bit MSR specified by Index. The + value written to the MSR is returned. Extra left bits in both AndData and + OrData are stripped. The caller must either guarantee that Index and the data + written is valid, or the caller must set up exception handlers to catch the + exceptions. This function is only available on IA-32 and X64. + + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Index The 32-bit MSR index to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the bit field. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MSR. + +**/ +UINT64 +EFIAPI +AsmMsrBitFieldAndThenOr64 ( + IN UINT32 Index, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return AsmWriteMsr64 ( + Index, + BitFieldAndThenOr64 ( + AsmReadMsr64 (Index), + StartBit, + EndBit, + AndData, + OrData + ) + ); +} + +// +// Base Library CPU Functions +// + +/** + Retrieves the current CPU interrupt state. + + Retrieves the current CPU interrupt state. Returns TRUE is interrupts are + currently enabled. Otherwise returns FALSE. + + @retval TRUE CPU interrupts are enabled. + @retval FALSE CPU interrupts are disabled. + +**/ +BOOLEAN +EFIAPI +GetInterruptState ( + VOID + ) +{ + IA32_EFLAGS32 EFlags; + + EFlags.UintN = AsmReadEflags (); + return (BOOLEAN)(EFlags.Bits.IF == 1); +} + +// +// Ia32 and x64 specific functions +// + +/** + Reads the current Global Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current GDTR descriptor and returns it in Gdtr. This + function is only available on IA-32 and X64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr Pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadGdtr ( + OUT IA32_DESCRIPTOR *Gdtr + ) +{ + ASSERT (Gdtr != NULL); + InternalX86ReadGdtr (Gdtr); +} + +/** + Writes the current Global Descriptor Table Register (GDTR) descriptor. + + Writes and the current GDTR descriptor specified by Gdtr. This function is + only available on IA-32 and X64. + + If Gdtr is NULL, then ASSERT(). + + @param Gdtr Pointer to a GDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteGdtr ( + IN CONST IA32_DESCRIPTOR *Gdtr + ) +{ + ASSERT (Gdtr != NULL); + InternalX86WriteGdtr (Gdtr); +} + +/** + Reads the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Reads and returns the current IDTR descriptor and returns it in Idtr. This + function is only available on IA-32 and X64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr Pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmReadIdtr ( + OUT IA32_DESCRIPTOR *Idtr + ) +{ + ASSERT (Idtr != NULL); + InternalX86ReadIdtr (Idtr); +} + +/** + Writes the current Interrupt Descriptor Table Register(GDTR) descriptor. + + Writes the current IDTR descriptor and returns it in Idtr. This function is + only available on IA-32 and X64. + + If Idtr is NULL, then ASSERT(). + + @param Idtr Pointer to a IDTR descriptor. + +**/ +VOID +EFIAPI +AsmWriteIdtr ( + IN CONST IA32_DESCRIPTOR *Idtr + ) +{ + ASSERT (Idtr != NULL); + InternalX86WriteIdtr (Idtr); +} + +/** + Save the current floating point/SSE/SSE2 context to a buffer. + + Saves the current floating point/SSE/SSE2 state to the buffer specified by + Buffer. Buffer must be aligned on a 16-byte boundary. This function is only + available on IA-32 and X64. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-byte boundary, then ASSERT(). + + @param Buffer Pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxSave ( + OUT IA32_FX_BUFFER *Buffer + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & 0xf) == 0); + InternalX86FxSave (Buffer); +} + +/** + Restores the current floating point/SSE/SSE2 context from a buffer. + + Restores the current floating point/SSE/SSE2 state from the buffer specified + by Buffer. Buffer must be aligned on a 16-byte boundary. This function is + only available on IA-32 and X64. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-byte boundary, then ASSERT(). + If Buffer was not saved with AsmFxSave(), then ASSERT(). + + @param Buffer Pointer to a buffer to save the floating point/SSE/SSE2 context. + +**/ +VOID +EFIAPI +AsmFxRestore ( + IN CONST IA32_FX_BUFFER *Buffer + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & 0xf) == 0); + InternalX86FxRestore (Buffer); +} + +/** + Enables the 32-bit paging mode on the CPU. + + Enables the 32-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode. This function is + only available on IA-32. After the 32-bit paging mode is enabled, control is + transferred to the function specified by EntryPoint using the new stack + specified by NewStack and passing in the parameters specified by Context1 and + Context2. Context1 and Context2 are optional and may be NULL. The function + EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit protected mode with flat descriptors. This + means all descriptors must have a base of 0 and a limit of 4GB. + 3) CR0 and CR4 must be compatible with 32-bit protected mode with flat + descriptors. + 4) CR3 must point to valid page tables that will be used once the transition + is complete, and those page tables must guarantee that the pages for this + function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is enabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is enabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is enabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + ASSERT (EntryPoint != NULL); + ASSERT (NewStack != NULL); + InternalX86EnablePaging32 (EntryPoint, Context1, Context2, NewStack); +} + +/** + Disables the 32-bit paging mode on the CPU. + + Disables the 32-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 32-paged protected + mode. This function is only available on IA-32. After the 32-bit paging mode + is disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be NULL. The function EntryPoint must never return. + + If the current execution mode is not 32-bit paged mode, then ASSERT(). + If EntryPoint is NULL, then ASSERT(). + If NewStack is NULL, then ASSERT(). + + There are a number of constraints that must be followed before calling this + function: + 1) Interrupts must be disabled. + 2) The caller must be in 32-bit paged mode. + 3) CR0, CR3, and CR4 must be compatible with 32-bit paged mode. + 4) CR3 must point to valid page tables that guarantee that the pages for + this function and the stack are identity mapped. + + @param EntryPoint A pointer to function to call with the new stack after + paging is disabled. + @param Context1 A pointer to the context to pass into the EntryPoint + function as the first parameter after paging is disabled. + @param Context2 A pointer to the context to pass into the EntryPoint + function as the second parameter after paging is + disabled. + @param NewStack A pointer to the new stack to use for the EntryPoint + function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging32 ( + IN SWITCH_STACK_ENTRY_POINT EntryPoint, + IN VOID *Context1, OPTIONAL + IN VOID *Context2, OPTIONAL + IN VOID *NewStack + ) +{ + ASSERT (EntryPoint != NULL); + ASSERT (NewStack != NULL); + InternalX86DisablePaging32 (EntryPoint, Context1, Context2, NewStack); +} + +/** + Enables the 64-bit paging mode on the CPU. + + Enables the 64-bit paging mode on the CPU. CR0, CR3, CR4, and the page tables + must be properly initialized prior to calling this service. This function + assumes the current execution mode is 32-bit protected mode with flat + descriptors. This function is only available on IA-32. After the 64-bit + paging mode is enabled, control is transferred to the function specified by + EntryPoint using the new stack specified by NewStack and passing in the + parameters specified by Context1 and Context2. Context1 and Context2 are + optional and may be 0. The function EntryPoint must never return. + + If the current execution mode is not 32-bit protected mode with flat + descriptors, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for long mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is enabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is enabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is enabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is enabled. + +**/ +VOID +EFIAPI +AsmEnablePaging64 ( + IN UINT16 Cs, + IN UINT64 EntryPoint, + IN UINT64 Context1, OPTIONAL + IN UINT64 Context2, OPTIONAL + IN UINT64 NewStack + ) +{ + ASSERT (EntryPoint != 0); + ASSERT (NewStack != 0); + InternalX86EnablePaging64 (Cs, EntryPoint, Context1, Context2, NewStack); +} + +/** + Disables the 64-bit paging mode on the CPU. + + Disables the 64-bit paging mode on the CPU and returns to 32-bit protected + mode. This function assumes the current execution mode is 64-paging mode. + This function is only available on X64. After the 64-bit paging mode is + disabled, control is transferred to the function specified by EntryPoint + using the new stack specified by NewStack and passing in the parameters + specified by Context1 and Context2. Context1 and Context2 are optional and + may be 0. The function EntryPoint must never return. + + If the current execution mode is not 64-bit paged mode, then ASSERT(). + If EntryPoint is 0, then ASSERT(). + If NewStack is 0, then ASSERT(). + + @param Cs The 16-bit selector to load in the CS before EntryPoint + is called. The descriptor in the GDT that this selector + references must be setup for 32-bit protected mode. + @param EntryPoint The 64-bit virtual address of the function to call with + the new stack after paging is disabled. + @param Context1 The 64-bit virtual address of the context to pass into + the EntryPoint function as the first parameter after + paging is disabled. + @param Context2 The 64-bit virtual address of the context to pass into + the EntryPoint function as the second parameter after + paging is disabled. + @param NewStack The 64-bit virtual address of the new stack to use for + the EntryPoint function after paging is disabled. + +**/ +VOID +EFIAPI +AsmDisablePaging64 ( + IN UINT16 Cs, + IN UINT32 EntryPoint, + IN UINT32 Context1, OPTIONAL + IN UINT32 Context2, OPTIONAL + IN UINT32 NewStack + ) +{ + ASSERT (EntryPoint != 0); + ASSERT (NewStack != 0); + InternalX86DisablePaging64 (Cs, EntryPoint, Context1, Context2, NewStack); +} + +// +// x86 version of MemoryFence() +// + +/** + Used to serialize load and store operations. + + All loads and stores that proceed calls to this function are guaranteed to be + globally visible when this function returns. + +**/ +VOID +EFIAPI +MemoryFence ( + VOID + ) +{ +} diff --git a/MdePkg/Library/BaseLib/x86Thunk.c b/MdePkg/Library/BaseLib/x86Thunk.c new file mode 100644 index 0000000000..8cb5f4f8bd --- /dev/null +++ b/MdePkg/Library/BaseLib/x86Thunk.c @@ -0,0 +1,127 @@ +/** @file + Real Mode Thunk Functions for IA32 and X64. + + Copyright (c) 2006, 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. + + Module Name: x86Thunk.c + +**/ + +/** + Invokes 16-bit code in big real mode and returns the updated register set. + + This function transfers control to the 16-bit code specified by CS:EIP using + the stack specified by SS:ESP in RegisterSet. The updated registers are saved + on the real mode stack and the starting address of the save area is returned. + + @param RegisterSet Values of registers before invocation of 16-bit code. + @param Patch Pointer to the area following the 16-bit code. + + @return The pointer to a IA32_REGISTER_SET structure containing the updated + register values. + +**/ +IA32_REGISTER_SET * +InternalAsmThunk16 ( + IN IA32_REGISTER_SET *RegisterSet, + IN OUT VOID *Patch + ); + +/** + Prepares all structures a code required to use AsmThunk16(). + + Prepares all structures and code required to use AsmThunk16(). + + If ThunkContext is NULL, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareThunk16 ( + OUT THUNK_CONTEXT *ThunkContext + ) +{ + ASSERT (ThunkContext != NULL); +} + +/** + Transfers control to a 16-bit real mode entry point and returns the results. + + Transfers control to a 16-bit real mode entry point and returns the results. + AsmPrepareThunk16() must be called with ThunkContext before this function is + used. This function must be called with interrupts disabled. + + If ThunkContext is NULL, then ASSERT(). + If AsmPrepareThunk16() was not previously called with ThunkContext, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ + UINT16 *Patch; + + ASSERT (ThunkContext != NULL); + + Patch = (UINT16*)( + (UINTN)ThunkContext->RealModeCode + + ThunkContext->RealModeCodeSize + ); + + // + // 0x9a66 is the OpCode of far call with an operand size override. + // + *Patch = 0x9a66; + + // + // CopyMem() here copies the updated register values back to RealModeState + // + CopyMem ( + &ThunkContext->RealModeState, + InternalAsmThunk16 (&ThunkContext->RealModeState, Patch + 1), + sizeof (ThunkContext->RealModeState) + ); +} + +/** + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. + + Prepares all structures and code for a 16-bit real mode thunk, transfers + control to a 16-bit real mode entry point, and returns the results. If the + caller only need to perform a single 16-bit real mode thunk, then this + service should be used. If the caller intends to make more than one 16-bit + real mode thunk, then it is more efficient if AsmPrepareThunk16() is called + once and AsmThunk16() can be called for each 16-bit real mode thunk. This + function must be called with interrupts disabled. + + If ThunkContext is NULL, then ASSERT(). + + @param ThunkContext A pointer to the context structure that describes the + 16-bit real mode code to call. + +**/ +VOID +EFIAPI +AsmPrepareAndThunk16 ( + IN OUT THUNK_CONTEXT *ThunkContext + ) +{ + AsmPrepareThunk16 (ThunkContext); + AsmThunk16 (ThunkContext); +} diff --git a/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.mbd b/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.mbd new file mode 100644 index 0000000000..767de2f139 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.mbd @@ -0,0 +1,29 @@ + + + + + BaseMemoryLib + fd44e603-002a-4b29-9f5f-529e815b6165 + EDK_RELEASE_VERSION 0x00090000 + FIX ME! + Copyright (c) 2006, 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. + + 2006-04-12 13:55 + + diff --git a/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.msa b/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.msa new file mode 100644 index 0000000000..ebd241bc71 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLib/BaseMemoryLib.msa @@ -0,0 +1,48 @@ + + + + + BaseMemoryLib + BASE + LIBRARY + fd44e603-002a-4b29-9f5f-529e815b6165 + EDK_RELEASE_VERSION 0x00090000 + Memory-only library functions with no library constructor/destructor + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-12 13:55 + + + BaseMemoryLib + BaseLib + DebugLib + + + CopyMem.c + MemLibGuid.c + MemLibGeneric.c + MemLibWrapper.c + SetMem.c + + + MdePkg + + diff --git a/MdePkg/Library/BaseMemoryLib/CopyMem.c b/MdePkg/Library/BaseMemoryLib/CopyMem.c new file mode 100644 index 0000000000..f2106acb18 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLib/CopyMem.c @@ -0,0 +1,60 @@ +/** @file + Implementation of the EfiCopyMem routine. This function is broken + out into its own source file so that it can be excluded from a + build for a particular platform easily if an optimized version + is desired. + + Copyright (c) 2006, 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. + + Module Name: EfiCopyMem.c + +**/ + +/** + Copy Length bytes from Source to Destination. + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + // + // Declare the local variables that actually move the data elements as + // volatile to prevent the optimizer from replacing this function with + // the intrinsic memcpy() + // + volatile UINT8 *Destination8; + CONST UINT8 *Source8; + + if (Source > Destination) { + Destination8 = (UINT8*)Destination; + Source8 = (CONST UINT8*)Source; + while (Length-- != 0) { + *(Destination8++) = *(Source8++); + } + } else if (Source < Destination) { + Destination8 = (UINT8*)Destination + Length; + Source8 = (CONST UINT8*)Source + Length; + while (Length-- != 0) { + *(--Destination8) = *(--Source8); + } + } + return Destination; +} diff --git a/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c b/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c new file mode 100644 index 0000000000..ef9f358a79 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLib/MemLibGeneric.c @@ -0,0 +1,282 @@ +/** @file + Architecture Independent Base Memory Library Implementation. + + Copyright (c) 2006, 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. + + Module Name: MemLibGeneric.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + do { + ((UINT16*)Buffer)[--Length] = Value; + } while (Length != 0); + return Buffer; +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + do { + ((UINT32*)Buffer)[--Length] = Value; + } while (Length != 0); + return Buffer; +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + do { + ((UINT64*)Buffer)[--Length] = Value; + } while (Length != 0); + return Buffer; +} + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + return InternalMemSetMem (Buffer, Length, 0); +} + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @retval 0 if MemOne == MemTwo + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + ASSERT (Length > 0); + while ((--Length != 0) && + (*(INT8*)DestinationBuffer == *(INT8*)SourceBuffer)) { + DestinationBuffer = (INT8*)DestinationBuffer + 1; + SourceBuffer = (INT8*)SourceBuffer + 1; + } + return (INTN)*(UINT8*)DestinationBuffer - (INTN)*(UINT8*)SourceBuffer; +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + CONST UINT8 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT8*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + CONST UINT16 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT16*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + CONST UINT32 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT32*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + CONST UINT64 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT64*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} diff --git a/MdePkg/Library/BaseMemoryLib/MemLibGuid.c b/MdePkg/Library/BaseMemoryLib/MemLibGuid.c new file mode 100644 index 0000000000..06b2721c64 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLib/MemLibGuid.c @@ -0,0 +1,131 @@ +/** @file + Implementation of GUID functions. + + Copyright (c) 2006, 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. + + Module Name: MemLibGuid.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + This function copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid + to DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid Pointer to the destination GUID. + @param SourceGuid Pointer to the source GUID. + + @return DestinationGuid + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE + is returned. If there are any bit differences in the two GUIDs, then FALSE is + returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 guid to compare + @param Guid2 guid to compare + + @retval TRUE if Guid1 == Guid2 + @retval FALSE if Guid1 != Guid2 + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + return (BOOLEAN)( + ReadUnaligned64 ((CONST UINT64*)Guid1) + == ReadUnaligned64 ((CONST UINT64*)Guid2) && + ReadUnaligned64 ((CONST UINT64*)Guid1 + 1) + == ReadUnaligned64 ((CONST UINT64*)Guid2 + 1) + ); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the + 128-bit GUID value that matches Guid. If a match is found, then a pointer to + the matching GUID in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Guid Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Guid was not found. +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} diff --git a/MdePkg/Library/BaseMemoryLib/MemLibWrapper.c b/MdePkg/Library/BaseMemoryLib/MemLibWrapper.c new file mode 100644 index 0000000000..2ef0766242 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLib/MemLibWrapper.c @@ -0,0 +1,620 @@ +/** @file + Wrapper functions for Base Memory Library. + + Copyright (c) 2006, 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. + + Module Name: MemLibWrapper.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + Copy Length bytes from Source to Destination. + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @retval 0 if MemOne == MemTwo + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Copy Length bytes from Source to Destination. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and + returns DestinationBuffer. The implementation must be reentrant, and it must + handle the case where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Destination + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Source + 1); + return InternalMemCopyMem (Destination, Source, Length); +} + +/** + Set Buffer to Value for Size bytes. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + ASSERT (Size <= MAX_ADDRESS - (UINTN)Buffer + 1); + return InternalMemSetMem (Buffer, Size, Value); +} + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem16 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem32 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem64 (Buffer, Length, Value); +} + +/** + Set Buffer to 0 for Size bytes. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + ASSERT (Buffer != NULL); + return InternalMemSetMem (Buffer, Size, 0); +} + +/** + Compares two memory buffers of a given length. + + This function compares Length bytes of SourceBuffer to Length bytes of + DestinationBuffer. If all Length bytes of the two buffers are identical, then + 0 is returned. Otherwise, the value returned is the first mismatched byte in + SourceBuffer subtracted from the first mismatched byte in DestinationBuffer. + + If DestinationBuffer is NULL and Length > 0, then ASSERT(). + If SourceBuffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare + + @retval 0 if DestinationBuffer == SourceBuffer + @retval Non-zero if DestinationBuffer != SourceBuffer + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)DestinationBuffer + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)SourceBuffer + 1); + if (Length == 0) { + return 0; + } + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address for an 8-bit value that matches + Value. If a match is found, then a pointer to the matching byte in the target + buffer is returned. If no match is found, then NULL is returned. If Length is + 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 16-bit increments for a 16-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem16 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 32-bit increments for a 32-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem32 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 64-bit increments for a 64-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem64 (Buffer, Length, Value); +} diff --git a/MdePkg/Library/BaseMemoryLib/SetMem.c b/MdePkg/Library/BaseMemoryLib/SetMem.c new file mode 100644 index 0000000000..bd7fee014d --- /dev/null +++ b/MdePkg/Library/BaseMemoryLib/SetMem.c @@ -0,0 +1,51 @@ +/** @file + Implementation of the EfiSetMem routine. This function is broken + out into its own source file so that it can be excluded from a + build for a particular platform easily if an optimized version + is desired. + + Copyright (c) 2006, 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. + + Module Name: EfiSetMem.c + +**/ + + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + // + // Declare the local variables that actually move the data elements as + // volatile to prevent the optimizer from replacing this function with + // the intrinsic memset() + // + volatile UINT8 *Pointer; + + Pointer = (UINT8*)Buffer; + while (Size-- != 0) { + *(Pointer++) = Value; + } + return Buffer; +} diff --git a/MdePkg/Library/BaseMemoryLib/build.xml b/MdePkg/Library/BaseMemoryLib/build.xml new file mode 100644 index 0000000000..fd1b805b43 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.mbd b/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.mbd new file mode 100644 index 0000000000..adea3a035c --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.mbd @@ -0,0 +1,29 @@ + + + + + BaseMemoryLibMmx + d458a654-f64c-49db-b8d1-3821306bf1f6 + EDK_RELEASE_VERSION 0x00090000 + FIX ME! + Copyright (c) 2006, 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. + + 2006-04-12 19:53 + + diff --git a/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.msa b/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.msa new file mode 100644 index 0000000000..37abf06853 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/BaseMemoryLibMmx.msa @@ -0,0 +1,58 @@ + + + + + BaseMemoryLibMmx + BASE + LIBRARY + d458a654-f64c-49db-b8d1-3821306bf1f6 + EDK_RELEASE_VERSION 0x00090000 + Memory-only library functions with no library constructor/destructor + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-12 19:53 + + + BaseMemoryLib + BaseLib + DebugLib + + + + MemLibGuid.c + MemLibWrapper.c + Ia32\CopyMem.asm + Ia32\SetMem.asm + Ia32\ZeroMem.asm + Ia32\SetMem16.asm + Ia32\SetMem32.asm + Ia32\SetMem64.asm + Ia32\CompareMem.asm + Ia32\ScanMem8.asm + Ia32\ScanMem16.asm + Ia32\ScanMem32.asm + Ia32\ScanMem64.asm + + + + MdePkg + + diff --git a/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c b/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c new file mode 100644 index 0000000000..06b2721c64 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/MemLibGuid.c @@ -0,0 +1,131 @@ +/** @file + Implementation of GUID functions. + + Copyright (c) 2006, 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. + + Module Name: MemLibGuid.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + This function copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid + to DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid Pointer to the destination GUID. + @param SourceGuid Pointer to the source GUID. + + @return DestinationGuid + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE + is returned. If there are any bit differences in the two GUIDs, then FALSE is + returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 guid to compare + @param Guid2 guid to compare + + @retval TRUE if Guid1 == Guid2 + @retval FALSE if Guid1 != Guid2 + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + return (BOOLEAN)( + ReadUnaligned64 ((CONST UINT64*)Guid1) + == ReadUnaligned64 ((CONST UINT64*)Guid2) && + ReadUnaligned64 ((CONST UINT64*)Guid1 + 1) + == ReadUnaligned64 ((CONST UINT64*)Guid2 + 1) + ); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the + 128-bit GUID value that matches Guid. If a match is found, then a pointer to + the matching GUID in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Guid Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Guid was not found. +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} diff --git a/MdePkg/Library/BaseMemoryLibMmx/MemLibWrapper.c b/MdePkg/Library/BaseMemoryLibMmx/MemLibWrapper.c new file mode 100644 index 0000000000..2ef0766242 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/MemLibWrapper.c @@ -0,0 +1,620 @@ +/** @file + Wrapper functions for Base Memory Library. + + Copyright (c) 2006, 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. + + Module Name: MemLibWrapper.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + Copy Length bytes from Source to Destination. + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @retval 0 if MemOne == MemTwo + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Copy Length bytes from Source to Destination. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and + returns DestinationBuffer. The implementation must be reentrant, and it must + handle the case where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Destination + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Source + 1); + return InternalMemCopyMem (Destination, Source, Length); +} + +/** + Set Buffer to Value for Size bytes. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + ASSERT (Size <= MAX_ADDRESS - (UINTN)Buffer + 1); + return InternalMemSetMem (Buffer, Size, Value); +} + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem16 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem32 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem64 (Buffer, Length, Value); +} + +/** + Set Buffer to 0 for Size bytes. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + ASSERT (Buffer != NULL); + return InternalMemSetMem (Buffer, Size, 0); +} + +/** + Compares two memory buffers of a given length. + + This function compares Length bytes of SourceBuffer to Length bytes of + DestinationBuffer. If all Length bytes of the two buffers are identical, then + 0 is returned. Otherwise, the value returned is the first mismatched byte in + SourceBuffer subtracted from the first mismatched byte in DestinationBuffer. + + If DestinationBuffer is NULL and Length > 0, then ASSERT(). + If SourceBuffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare + + @retval 0 if DestinationBuffer == SourceBuffer + @retval Non-zero if DestinationBuffer != SourceBuffer + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)DestinationBuffer + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)SourceBuffer + 1); + if (Length == 0) { + return 0; + } + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address for an 8-bit value that matches + Value. If a match is found, then a pointer to the matching byte in the target + buffer is returned. If no match is found, then NULL is returned. If Length is + 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 16-bit increments for a 16-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem16 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 32-bit increments for a 32-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem32 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 64-bit increments for a 64-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem64 (Buffer, Length, Value); +} diff --git a/MdePkg/Library/BaseMemoryLibMmx/build.xml b/MdePkg/Library/BaseMemoryLibMmx/build.xml new file mode 100644 index 0000000000..13a9a993ea --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/CompareMem.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/CompareMem.asm new file mode 100644 index 0000000000..4e35d1c858 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/CompareMem.asm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemCompareMem PROC USES esi edi + mov esi, [esp + 12] + mov edi, [esp + 16] + mov ecx, [esp + 20] + repe cmpsb + movzx eax, byte ptr [esi - 1] + movzx edx, byte ptr [edi - 1] + sub eax, edx + sub eax, edx + ret +InternalMemCompareMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/CopyMem.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/CopyMem.asm new file mode 100644 index 0000000000..b709a809d5 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/CopyMem.asm @@ -0,0 +1,86 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CopyMem.asm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_CopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +InternalMemCopyMem PROC USES esi edi + mov esi, [esp + 16] ; esi <- Source + mov edi, [esp + 12] ; edi <- Destination + mov edx, [esp + 20] ; edx <- Count + lea eax, [edi + edx - 1] ; eax <- End of Destination + cmp esi, edi + jae @F + cmp eax, esi ; Overlapped? + jae @CopyBackward ; Copy backward if overlapped +@@: + xor ecx, ecx + sub ecx, esi + and ecx, 7 ; ecx + esi aligns on 8-byte boundary + jz @F + cmp ecx, edx + cmova ecx, edx + sub edx, ecx ; edx <- remaining bytes to copy + rep movsb +@@: + mov ecx, edx + and edx, 7 + shr ecx, 3 ; ecx <- # of Qwords to copy + jz @CopyBytes + push eax + push eax + movq [esp], mm0 ; save mm0 +@@: + movq mm0, [esi] + movntq [edi], mm0 + add esi, 8 + add edi, 8 + loop @B + mfence + movq mm0, [esp] ; restore mm0 + pop ecx ; stack cleanup + pop ecx ; stack cleanup + jmp @CopyBytes +@CopyBackward: + mov edi, eax ; edi <- Last byte in Destination + lea esi, [esi + edx - 1] ; esi <- Last byte in Source + std +@CopyBytes: + mov ecx, edx + rep movsb + cld + mov eax, [esp + 12] + ret +InternalMemCopyMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem16.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem16.asm new file mode 100644 index 0000000000..7071942ede --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem16.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem16 PROC USES edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasw + lea eax, [edi - 2] + cmovnz eax, ecx + ret +InternalMemScanMem16 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem32.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem32.asm new file mode 100644 index 0000000000..e6aaf02bc3 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem32.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem32 PROC USES edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasd + lea eax, [edi - 4] + cmovnz eax, ecx + ret +InternalMemScanMem32 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem64.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem64.asm new file mode 100644 index 0000000000..f9725a4a5d --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem64.asm @@ -0,0 +1,53 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem64 PROC USES edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +@@: + cmp eax, [edi] + lea edi, [edi + 8] + loopne @B + jne @F + cmp edx, [edi - 4] + jecxz @F + jne @B +@@: + lea eax, [edi - 8] + cmovne eax, ecx + ret +InternalMemScanMem64 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem8.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem8.asm new file mode 100644 index 0000000000..6ae1900189 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/ScanMem8.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem8 PROC USES edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov al, [esp + 16] + repne scasb + lea eax, [edi - 1] + cmovnz eax, ecx + ret +InternalMemScanMem8 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem.asm new file mode 100644 index 0000000000..f2c55f1296 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem.asm @@ -0,0 +1,66 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem.asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem PROC USES edi + mov ecx, [esp + 12] ; ecx <- Count + mov edi, [esp + 8] ; edi <- Buffer + mov edx, ecx + shr ecx, 3 ; # of Qwords to set + mov al, [esp + 16] ; al <- Value + jz @SetBytes + mov ah, al ; ax <- Value | (Value << 8) + push ecx + push ecx + movq [esp], mm0 ; save mm0 + movd mm0, eax + pshufw mm0, mm0, 0 ; fill mm0 with 8 Value's +@@: + movntq [edi], mm0 + add edi, 8 + loop @B + mfence + movq mm0, [esp] ; restore mm0 + pop ecx ; stack cleanup + pop ecx +@SetBytes: + and edx, 7 + mov ecx, edx + rep stosb + mov eax, [esp + 8] ; eax <- Buffer as return value + ret +InternalMemSetMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem16.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem16.asm new file mode 100644 index 0000000000..f9dc533fd8 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem16.asm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem16.asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem16 PROC USES edi + mov edx, [esp + 12] + mov edi, [esp + 8] + mov ecx, edx + and edx, 3 + shr ecx, 2 + mov eax, [esp + 16] + jz @SetWords + movd mm0, eax + pshufw mm0, mm0, 0 +@@: + movntq [edi], mm0 + add edi, 8 + loop @B + mfence +@SetWords: + mov ecx, edx + rep stosw + mov eax, [esp + 8] + ret +InternalMemSetMem16 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem32.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem32.asm new file mode 100644 index 0000000000..7f24fcd744 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem32.asm @@ -0,0 +1,59 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem32.asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem32 PROC USES edi + mov edx, [esp + 12] + mov edi, [esp + 8] + mov ecx, edx + shr ecx, 1 + movd mm0, [esp + 16] + mov eax, edi + jz @SetDwords + pshufw mm0, mm0, 44h +@@: + movntq [edi], mm0 + add edi, 8 + loop @B + mfence +@SetDwords: + test dl, 1 + jz @F + movd [edi], mm0 +@@: + ret +InternalMemSetMem32 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem64.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem64.asm new file mode 100644 index 0000000000..b607608505 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/SetMem64.asm @@ -0,0 +1,50 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem64.asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem64 PROC USES edi + movq mm0, [esp + 16] + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, edi +@@: + movntq [edi], mm0 + add edi, 8 + loop @B + mfence + ret +InternalMemSetMem64 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibMmx/ia32/ZeroMem.asm b/MdePkg/Library/BaseMemoryLibMmx/ia32/ZeroMem.asm new file mode 100644 index 0000000000..31ef120525 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibMmx/ia32/ZeroMem.asm @@ -0,0 +1,57 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ZeroMem.asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_ZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +InternalMemZeroMem PROC USES edi + mov edi, [esp + 8] + mov ecx, [esp + 12] + mov edx, ecx + shr ecx, 3 + jz @ZeroBytes + pxor mm0, mm0 +@@: + movntq [edi], mm0 + add edi, 8 + loop @B + mfence +@ZeroBytes: + and edx, 7 + xor eax, eax + mov ecx, edx + rep stosb + mov eax, [esp + 8] + ret +InternalMemZeroMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.mbd b/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.mbd new file mode 100644 index 0000000000..400ca94b35 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.mbd @@ -0,0 +1,29 @@ + + + + + BaseMemoryLibRepStr + e7884bf4-51a1-485b-982a-ff89129983bc + EDK_RELEASE_VERSION 0x00090000 + FIX ME! + Copyright (c) 2006, 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. + + 2006-04-12 13:39 + + diff --git a/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.msa b/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.msa new file mode 100644 index 0000000000..24c67a044e --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.msa @@ -0,0 +1,73 @@ + + + + + BaseMemoryLibRepStr + BASE + LIBRARY + e7884bf4-51a1-485b-982a-ff89129983bc + EDK_RELEASE_VERSION 0x00090000 + Memory-only library functions with no library constructor/destructor + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-12 13:39 + + + BaseMemoryLib + BaseLib + DebugLib + + + + MemLibGuid.c + MemLibWrapper.c + Ia32\CopyMem.asm + Ia32\SetMem.asm + Ia32\SetMem16.asm + Ia32\SetMem32.asm + Ia32\SetMem64.asm + Ia32\ZeroMem.asm + Ia32\CompareMem.asm + Ia32\ScanMem8.asm + Ia32\ScanMem16.asm + Ia32\ScanMem32.asm + Ia32\ScanMem64.asm + + + MemLibGuid.c + MemLibWrapper.c + x64\CopyMem.asm + x64\SetMem.asm + x64\SetMem16.asm + x64\SetMem32.asm + x64\SetMem64.asm + x64\ZeroMem.asm + x64\CompareMem.asm + x64\ScanMem8.asm + x64\ScanMem16.asm + x64\ScanMem32.asm + x64\ScanMem64.asm + + + + MdePkg + + diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.asm new file mode 100644 index 0000000000..3cf6fe7f73 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CompareMem.asm @@ -0,0 +1,45 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemCompareMem PROC USES esi edi + mov esi, [esp + 12] + mov edi, [esp + 16] + mov ecx, [esp + 20] + repe cmpsb + movzx eax, byte ptr [esi - 1] + movzx edx, byte ptr [edi - 1] + sub eax, edx + ret +InternalMemCompareMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.asm new file mode 100644 index 0000000000..7b3e5eafee --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/CopyMem.asm @@ -0,0 +1,55 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CopyMem.Asm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMemCopyMem PROC USES esi edi + mov esi, [esp + 16] ; esi <- Source + mov edi, [esp + 12] ; edi <- Destination + mov edx, [esp + 20] ; edx <- Count + lea eax, [edi + edx - 1] ; eax <- End of Destination + cmp esi, edi + jae @F + cmp eax, esi + jae @CopyBackward ; Copy backward if overlapped +@@: + mov ecx, edx + and edx, 3 + shr ecx, 2 + rep movsd ; Copy as many Dwords as possible + jmp @CopyBytes +@CopyBackward: + mov edi, eax ; edi <- End of Destination + lea esi, [esi + edx - 1] ; esi <- End of Source + std +@CopyBytes: + mov ecx, edx + rep movsb ; Copy bytes backward + cld + mov eax, [esp + 12] ; eax <- Destination as return value + ret +InternalMemCopyMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.asm new file mode 100644 index 0000000000..7071942ede --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem16.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem16 PROC USES edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasw + lea eax, [edi - 2] + cmovnz eax, ecx + ret +InternalMemScanMem16 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.asm new file mode 100644 index 0000000000..e6aaf02bc3 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem32.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem32 PROC USES edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasd + lea eax, [edi - 4] + cmovnz eax, ecx + ret +InternalMemScanMem32 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.asm new file mode 100644 index 0000000000..f9725a4a5d --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem64.asm @@ -0,0 +1,53 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem64 PROC USES edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +@@: + cmp eax, [edi] + lea edi, [edi + 8] + loopne @B + jne @F + cmp edx, [edi - 4] + jecxz @F + jne @B +@@: + lea eax, [edi - 8] + cmovne eax, ecx + ret +InternalMemScanMem64 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.asm new file mode 100644 index 0000000000..6ae1900189 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ScanMem8.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem8 PROC USES edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov al, [esp + 16] + repne scasb + lea eax, [edi - 1] + cmovnz eax, ecx + ret +InternalMemScanMem8 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.asm new file mode 100644 index 0000000000..495dd3f4ba --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem.Asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMemSetMem PROC USES edi + mov eax, [esp + 16] + mov edi, [esp + 8] + mov ecx, [esp + 12] + rep stosb + mov eax, [esp + 8] + ret +InternalMemSetMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.asm new file mode 100644 index 0000000000..483e26e2b6 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem16.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem16.Asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMemSetMem16 PROC USES edi + mov eax, [esp + 16] + mov edi, [esp + 8] + mov ecx, [esp + 12] + rep stosw + mov eax, [esp + 8] + ret +InternalMemSetMem16 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.asm new file mode 100644 index 0000000000..18b77ce183 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem32.asm @@ -0,0 +1,37 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem32.Asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMemSetMem32 PROC USES edi + mov eax, [esp + 16] + mov edi, [esp + 8] + mov ecx, [esp + 12] + rep stosd + mov eax, [esp + 8] + ret +InternalMemSetMem32 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.asm new file mode 100644 index 0000000000..3f6f3ecf9d --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/SetMem64.asm @@ -0,0 +1,41 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem64.Asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMemSetMem64 PROC USES edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +@@: + mov [edi + ecx*4 - 8], eax + mov [edi + ecx*4 - 4], edx + loop @B + mov eax, edi + ret +InternalMemSetMem64 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.asm b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.asm new file mode 100644 index 0000000000..f892250d16 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/Ia32/ZeroMem.asm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ZeroMem.Asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .386 + .model flat,C + .code + +InternalMemZeroMem PROC USES edi + xor eax, eax + mov edi, [esp + 8] + mov ecx, [esp + 12] + mov edx, ecx + shr ecx, 2 + and edx, 3 + push edi + rep stosd + mov ecx, edx + rep stosb + pop eax + ret +InternalMemZeroMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c b/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c new file mode 100644 index 0000000000..06b2721c64 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/MemLibGuid.c @@ -0,0 +1,131 @@ +/** @file + Implementation of GUID functions. + + Copyright (c) 2006, 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. + + Module Name: MemLibGuid.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + This function copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid + to DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid Pointer to the destination GUID. + @param SourceGuid Pointer to the source GUID. + + @return DestinationGuid + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE + is returned. If there are any bit differences in the two GUIDs, then FALSE is + returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 guid to compare + @param Guid2 guid to compare + + @retval TRUE if Guid1 == Guid2 + @retval FALSE if Guid1 != Guid2 + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + return (BOOLEAN)( + ReadUnaligned64 ((CONST UINT64*)Guid1) + == ReadUnaligned64 ((CONST UINT64*)Guid2) && + ReadUnaligned64 ((CONST UINT64*)Guid1 + 1) + == ReadUnaligned64 ((CONST UINT64*)Guid2 + 1) + ); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the + 128-bit GUID value that matches Guid. If a match is found, then a pointer to + the matching GUID in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Guid Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Guid was not found. +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} diff --git a/MdePkg/Library/BaseMemoryLibRepStr/MemLibWrapper.c b/MdePkg/Library/BaseMemoryLibRepStr/MemLibWrapper.c new file mode 100644 index 0000000000..2ef0766242 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/MemLibWrapper.c @@ -0,0 +1,620 @@ +/** @file + Wrapper functions for Base Memory Library. + + Copyright (c) 2006, 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. + + Module Name: MemLibWrapper.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + Copy Length bytes from Source to Destination. + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @retval 0 if MemOne == MemTwo + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Copy Length bytes from Source to Destination. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and + returns DestinationBuffer. The implementation must be reentrant, and it must + handle the case where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Destination + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Source + 1); + return InternalMemCopyMem (Destination, Source, Length); +} + +/** + Set Buffer to Value for Size bytes. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + ASSERT (Size <= MAX_ADDRESS - (UINTN)Buffer + 1); + return InternalMemSetMem (Buffer, Size, Value); +} + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem16 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem32 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem64 (Buffer, Length, Value); +} + +/** + Set Buffer to 0 for Size bytes. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + ASSERT (Buffer != NULL); + return InternalMemSetMem (Buffer, Size, 0); +} + +/** + Compares two memory buffers of a given length. + + This function compares Length bytes of SourceBuffer to Length bytes of + DestinationBuffer. If all Length bytes of the two buffers are identical, then + 0 is returned. Otherwise, the value returned is the first mismatched byte in + SourceBuffer subtracted from the first mismatched byte in DestinationBuffer. + + If DestinationBuffer is NULL and Length > 0, then ASSERT(). + If SourceBuffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare + + @retval 0 if DestinationBuffer == SourceBuffer + @retval Non-zero if DestinationBuffer != SourceBuffer + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)DestinationBuffer + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)SourceBuffer + 1); + if (Length == 0) { + return 0; + } + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address for an 8-bit value that matches + Value. If a match is found, then a pointer to the matching byte in the target + buffer is returned. If no match is found, then NULL is returned. If Length is + 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 16-bit increments for a 16-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem16 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 32-bit increments for a 32-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem32 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 64-bit increments for a 64-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem64 (Buffer, Length, Value); +} diff --git a/MdePkg/Library/BaseMemoryLibRepStr/build.xml b/MdePkg/Library/BaseMemoryLibRepStr/build.xml new file mode 100644 index 0000000000..cc6423b839 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/CompareMem.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/CompareMem.asm new file mode 100644 index 0000000000..b8e289bb27 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/CompareMem.asm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .code + +InternalMemCompareMem PROC USES rsi rdi + mov rsi, rcx + mov rdi, rdx + mov rcx, r8 + repe cmpsb + movzx rax, byte ptr [rsi - 1] + movzx rdx, byte ptr [rdi - 1] + sub rax, rdx + ret +InternalMemCompareMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/CopyMem.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/CopyMem.asm new file mode 100644 index 0000000000..43630715cb --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/CopyMem.asm @@ -0,0 +1,52 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CopyMem.Asm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalMemCopyMem PROC USES rsi rdi + mov rsi, rdx ; rsi <- Source + mov rdi, rcx ; rdi <- Destination + lea r9, [rdi + r8 - 1] ; r9 <- End of Destination + cmp rsi, rdi + mov rax, rdi ; rax <- Destination as return value + jae @F + cmp r9, rsi + jae @CopyBackward ; Copy backward if overlapped +@@: + mov rcx, r8 + and r8, 7 + shr rcx, 3 + rep movsq ; Copy as many Qwords as possible + jmp @CopyBytes +@CopyBackward: + mov rdi, r9 ; rdi <- End of Destination + lea rsi, [rsi + r8 - 1] ; esi <- End of Source + std ; set direction flag +@CopyBytes: + mov rcx, r8 + rep movsb ; Copy bytes backward + cld + ret +InternalMemCopyMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem16.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem16.asm new file mode 100644 index 0000000000..6af88fae5b --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem16.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .code + +InternalMemScanMem16 PROC USES rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasw + lea rax, [rdi - 2] + cmovnz rax, rcx + ret +InternalMemScanMem16 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem32.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem32.asm new file mode 100644 index 0000000000..f9c9feb00e --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem32.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .code + +InternalMemScanMem32 PROC USES rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasd + lea rax, [rdi - 4] + cmovnz rax, rcx + ret +InternalMemScanMem32 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem64.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem64.asm new file mode 100644 index 0000000000..2f286c9e2f --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem64.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .code + +InternalMemScanMem64 PROC USES rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasq + lea rax, [rdi - 8] + cmovnz rax, rcx + ret +InternalMemScanMem64 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem8.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem8.asm new file mode 100644 index 0000000000..4027ece768 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/ScanMem8.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .code + +InternalMemScanMem8 PROC USES rdi + mov rdi, rcx + mov rcx, rdx + mov rax, r8 + repne scasb + lea rax, [rdi - 1] + cmovnz rax, rcx ; set rax to 0 if not found + ret +InternalMemScanMem8 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem.asm new file mode 100644 index 0000000000..b9108c750e --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem.asm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem.Asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalMemSetMem PROC USES rdi + mov rax, r8 + mov rdi, rcx + xchg rcx, rdx + rep stosb + mov rax, rdx + ret +InternalMemSetMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem16.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem16.asm new file mode 100644 index 0000000000..3a9fd47fc3 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem16.asm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem16.Asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalMemSetMem16 PROC USES rdi + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosw + mov rax, rdx + ret +InternalMemSetMem16 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem32.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem32.asm new file mode 100644 index 0000000000..2020d19065 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem32.asm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem32.Asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalMemSetMem32 PROC USES rdi + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosd + mov rax, rdx + ret +InternalMemSetMem32 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem64.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem64.asm new file mode 100644 index 0000000000..70ca4fb75a --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/SetMem64.asm @@ -0,0 +1,35 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem64.Asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalMemSetMem64 PROC USES rdi + mov rdi, rcx + mov rax, r8 + xchg rcx, rdx + rep stosq + mov rax, rdx + ret +InternalMemSetMem64 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibRepStr/x64/ZeroMem.asm b/MdePkg/Library/BaseMemoryLibRepStr/x64/ZeroMem.asm new file mode 100644 index 0000000000..c18a2e27c1 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibRepStr/x64/ZeroMem.asm @@ -0,0 +1,40 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ZeroMem.Asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +InternalMemZeroMem PROC USES rdi + push rcx + xor rax, rax + mov rdi, rcx + mov rcx, rdx + shr rcx, 3 + and rdx, 7 + rep stosq + mov ecx, edx + rep stosb + pop rax + ret +InternalMemZeroMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.mbd b/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.mbd new file mode 100644 index 0000000000..346968572a --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.mbd @@ -0,0 +1,29 @@ + + + + + BaseMemoryLibSse2 + 65a18235-5096-4032-8c63-214f0249ce8d + EDK_RELEASE_VERSION 0x00090000 + FIX ME! + Copyright (c) 2006, 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. + + 2006-04-12 13:46 + + diff --git a/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.msa b/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.msa new file mode 100644 index 0000000000..6336f58b85 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/BaseMemoryLibSse2.msa @@ -0,0 +1,73 @@ + + + + + BaseMemoryLibSse2 + BASE + LIBRARY + 65a18235-5096-4032-8c63-214f0249ce8d + EDK_RELEASE_VERSION 0x00090000 + Memory-only library functions with no library constructor/destructor + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-12 13:46 + + + BaseMemoryLib + BaseLib + DebugLib + + + + MemLibGuid.c + MemLibWrapper.c + Ia32\CopyMem.asm + Ia32\SetMem.asm + Ia32\SetMem16.asm + Ia32\SetMem32.asm + Ia32\SetMem64.asm + Ia32\ZeroMem.asm + Ia32\CompareMem.asm + Ia32\ScanMem8.asm + Ia32\ScanMem16.asm + Ia32\ScanMem32.asm + Ia32\ScanMem64.asm + + + MemLibGuid.c + MemLibWrapper.c + x64\CopyMem.asm + x64\SetMem.asm + x64\SetMem16.asm + x64\SetMem32.asm + x64\SetMem64.asm + x64\ZeroMem.asm + x64\CompareMem.asm + x64\ScanMem8.asm + x64\ScanMem16.asm + x64\ScanMem32.asm + x64\ScanMem64.asm + + + + MdePkg + + diff --git a/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c b/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c new file mode 100644 index 0000000000..06b2721c64 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/MemLibGuid.c @@ -0,0 +1,131 @@ +/** @file + Implementation of GUID functions. + + Copyright (c) 2006, 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. + + Module Name: MemLibGuid.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + This function copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid + to DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid Pointer to the destination GUID. + @param SourceGuid Pointer to the source GUID. + + @return DestinationGuid + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE + is returned. If there are any bit differences in the two GUIDs, then FALSE is + returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 guid to compare + @param Guid2 guid to compare + + @retval TRUE if Guid1 == Guid2 + @retval FALSE if Guid1 != Guid2 + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + return (BOOLEAN)( + ReadUnaligned64 ((CONST UINT64*)Guid1) + == ReadUnaligned64 ((CONST UINT64*)Guid2) && + ReadUnaligned64 ((CONST UINT64*)Guid1 + 1) + == ReadUnaligned64 ((CONST UINT64*)Guid2 + 1) + ); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the + 128-bit GUID value that matches Guid. If a match is found, then a pointer to + the matching GUID in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Guid Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Guid was not found. +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} diff --git a/MdePkg/Library/BaseMemoryLibSse2/MemLibWrapper.c b/MdePkg/Library/BaseMemoryLibSse2/MemLibWrapper.c new file mode 100644 index 0000000000..2ef0766242 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/MemLibWrapper.c @@ -0,0 +1,620 @@ +/** @file + Wrapper functions for Base Memory Library. + + Copyright (c) 2006, 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. + + Module Name: MemLibWrapper.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + Copy Length bytes from Source to Destination. + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @retval 0 if MemOne == MemTwo + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Copy Length bytes from Source to Destination. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and + returns DestinationBuffer. The implementation must be reentrant, and it must + handle the case where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Destination + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Source + 1); + return InternalMemCopyMem (Destination, Source, Length); +} + +/** + Set Buffer to Value for Size bytes. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + ASSERT (Size <= MAX_ADDRESS - (UINTN)Buffer + 1); + return InternalMemSetMem (Buffer, Size, Value); +} + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem16 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem32 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem64 (Buffer, Length, Value); +} + +/** + Set Buffer to 0 for Size bytes. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + ASSERT (Buffer != NULL); + return InternalMemSetMem (Buffer, Size, 0); +} + +/** + Compares two memory buffers of a given length. + + This function compares Length bytes of SourceBuffer to Length bytes of + DestinationBuffer. If all Length bytes of the two buffers are identical, then + 0 is returned. Otherwise, the value returned is the first mismatched byte in + SourceBuffer subtracted from the first mismatched byte in DestinationBuffer. + + If DestinationBuffer is NULL and Length > 0, then ASSERT(). + If SourceBuffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare + + @retval 0 if DestinationBuffer == SourceBuffer + @retval Non-zero if DestinationBuffer != SourceBuffer + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)DestinationBuffer + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)SourceBuffer + 1); + if (Length == 0) { + return 0; + } + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address for an 8-bit value that matches + Value. If a match is found, then a pointer to the matching byte in the target + buffer is returned. If no match is found, then NULL is returned. If Length is + 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 16-bit increments for a 16-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem16 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 32-bit increments for a 32-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem32 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 64-bit increments for a 64-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem64 (Buffer, Length, Value); +} diff --git a/MdePkg/Library/BaseMemoryLibSse2/build.xml b/MdePkg/Library/BaseMemoryLibSse2/build.xml new file mode 100644 index 0000000000..39482b0bfa --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/CompareMem.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/CompareMem.asm new file mode 100644 index 0000000000..4e35d1c858 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/CompareMem.asm @@ -0,0 +1,46 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemCompareMem PROC USES esi edi + mov esi, [esp + 12] + mov edi, [esp + 16] + mov ecx, [esp + 20] + repe cmpsb + movzx eax, byte ptr [esi - 1] + movzx edx, byte ptr [edi - 1] + sub eax, edx + sub eax, edx + ret +InternalMemCompareMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/CopyMem.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/CopyMem.asm new file mode 100644 index 0000000000..6127cc2188 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/CopyMem.asm @@ -0,0 +1,84 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CopyMem.asm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_CopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +InternalMemCopyMem PROC USES esi edi + mov esi, [esp + 16] ; esi <- Source + mov edi, [esp + 12] ; edi <- Destination + mov edx, [esp + 20] ; edx <- Count + lea eax, [edi + edx - 1] ; eax <- End of Destination + cmp esi, edi + jae @F + cmp eax, esi ; Overlapped? + jae @CopyBackward ; Copy backward if overlapped +@@: + xor ecx, ecx + sub ecx, edi + and ecx, 15 ; ecx + edi aligns on 16-byte boundary + jz @F + cmp ecx, edx + cmova ecx, edx + sub edx, ecx ; edx <- remaining bytes to copy + rep movsb +@@: + mov ecx, edx + and edx, 15 + shr ecx, 4 ; ecx <- # of DQwords to copy + jz @CopyBytes + add esp, -16 + movdqu [esp], xmm0 ; save xmm0 +@@: + movdqu xmm0, [esi] ; esi may not be 16-bytes aligned + movntdq [edi], xmm0 ; edi should be 16-bytes aligned + add esi, 16 + add edi, 16 + loop @B + mfence + movdqu xmm0, [esp] ; restore xmm0 + add esp, 16 ; stack cleanup + jmp @CopyBytes +@CopyBackward: + mov edi, eax ; edi <- Last byte in Destination + lea esi, [esi + edx - 1] ; esi <- Last byte in Source + std +@CopyBytes: + mov ecx, edx + rep movsb + cld + mov eax, [esp + 12] ; eax <- Destination as return value + ret +InternalMemCopyMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem16.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem16.asm new file mode 100644 index 0000000000..7071942ede --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem16.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem16 PROC USES edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasw + lea eax, [edi - 2] + cmovnz eax, ecx + ret +InternalMemScanMem16 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem32.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem32.asm new file mode 100644 index 0000000000..e6aaf02bc3 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem32.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem32 PROC USES edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov eax, [esp + 16] + repne scasd + lea eax, [edi - 4] + cmovnz eax, ecx + ret +InternalMemScanMem32 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem64.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem64.asm new file mode 100644 index 0000000000..f9725a4a5d --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem64.asm @@ -0,0 +1,53 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem64 PROC USES edi + mov ecx, [esp + 12] + mov eax, [esp + 16] + mov edx, [esp + 20] + mov edi, [esp + 8] +@@: + cmp eax, [edi] + lea edi, [edi + 8] + loopne @B + jne @F + cmp edx, [edi - 4] + jecxz @F + jne @B +@@: + lea eax, [edi - 8] + cmovne eax, ecx + ret +InternalMemScanMem64 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem8.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem8.asm new file mode 100644 index 0000000000..6ae1900189 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/ScanMem8.asm @@ -0,0 +1,44 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .code + +InternalMemScanMem8 PROC USES edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + mov al, [esp + 16] + repne scasb + lea eax, [edi - 1] + cmovnz eax, ecx + ret +InternalMemScanMem8 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem.asm new file mode 100644 index 0000000000..62b10cff0a --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem.asm @@ -0,0 +1,74 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem.asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem PROC USES edi + mov edx, [esp + 12] ; edx <- Count + mov edi, [esp + 8] ; edi <- Buffer + mov al, [esp + 16] ; al <- Value + xor ecx, ecx + sub ecx, edi + and ecx, 15 ; ecx + edi aligns on 16-byte boundary + jz @F + cmp ecx, edx + cmova ecx, edx + sub edx, ecx + rep stosb +@@: + mov ecx, edx + and edx, 15 + shr ecx, 4 ; ecx <- # of DQwords to set + jz @SetBytes + mov ah, al ; ax <- Value | (Value << 8) + add esp, -16 + movdqu [esp], xmm0 ; save xmm0 + movd xmm0, eax + pshuflw xmm0, xmm0, 0 ; xmm0[0..63] <- Value repeats 8 times + movlhps xmm0, xmm0 ; xmm0 <- Value repeats 16 times +@@: + movntdq [edi], xmm0 ; edi should be 16-byte aligned + add edi, 16 + loop @B + mfence + movdqu xmm0, [esp] ; restore xmm0 + add esp, 16 ; stack cleanup +@SetBytes: + mov ecx, edx + rep stosb + mov eax, [esp + 8] ; eax <- Buffer as return value + ret +InternalMemSetMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem16.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem16.asm new file mode 100644 index 0000000000..3fabb00d31 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem16.asm @@ -0,0 +1,70 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem16.asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem16 PROC USES edi + mov edx, [esp + 12] + mov edi, [esp + 8] + xor ecx, ecx + sub ecx, edi + and ecx, 15 ; ecx + edi aligns on 16-byte boundary + mov eax, [esp + 16] + jz @F + shr ecx, 1 + cmp ecx, edx + cmova ecx, edx + sub edx, ecx + rep stosw +@@: + mov ecx, edx + and edx, 7 + shr ecx, 3 + jz @SetWords + movd xmm0, eax + pshuflw xmm0, xmm0, 0 + movlhps xmm0, xmm0 +@@: + movntdq [edi], xmm0 ; edi should be 16-byte aligned + add edi, 16 + loop @B + mfence +@SetWords: + mov ecx, edx + rep stosw + mov eax, [esp + 8] + ret +InternalMemSetMem16 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem32.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem32.asm new file mode 100644 index 0000000000..a7f1f0e127 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem32.asm @@ -0,0 +1,69 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem32.asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT32 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem32 PROC USES edi + mov edx, [esp + 12] + mov edi, [esp + 8] + xor ecx, ecx + sub ecx, edi + and ecx, 15 ; ecx + edi aligns on 16-byte boundary + mov eax, [esp + 16] + jz @F + shr ecx, 2 + cmp ecx, edx + cmova ecx, edx + sub edx, ecx + rep stosd +@@: + mov ecx, edx + and edx, 3 + shr ecx, 2 + jz @SetDwords + movd xmm0, eax + pshufd xmm0, xmm0, 0 +@@: + movntdq [edi], xmm0 + add edi, 16 + loop @B + mfence +@SetDwords: + mov ecx, edx + rep stosd + mov eax, [esp + 8] + ret +InternalMemSetMem32 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem64.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem64.asm new file mode 100644 index 0000000000..1ddc7ea191 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/SetMem64.asm @@ -0,0 +1,63 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem64.asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT64 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem64 PROC USES edi + mov ecx, [esp + 12] + mov edi, [esp + 8] + test edi, 8 + DB 0f2h, 0fh, 12h, 44h, 24h, 16 ; movddup xmm0, [esp + 16] + jz @F + movq [edi], xmm0 + add edi, 8 + dec ecx +@@: + mov edx, ecx + shr ecx, 1 + jz @SetQwords +@@: + movntdq [edi], xmm0 + add edi, 16 + loop @B + mfence +@SetQwords: + test dl, 1 + jz @F + movq [edi], xmm0 +@@: + ret +InternalMemSetMem64 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/ia32/ZeroMem.asm b/MdePkg/Library/BaseMemoryLibSse2/ia32/ZeroMem.asm new file mode 100644 index 0000000000..b532382e2e --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/ia32/ZeroMem.asm @@ -0,0 +1,66 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ZeroMem.asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .686 + .model flat,C + .xmm + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_ZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +InternalMemZeroMem PROC USES edi + mov edi, [esp + 8] + mov edx, [esp + 12] + xor ecx, ecx + sub ecx, edi + xor eax, eax + and ecx, 15 + jz @F + cmp ecx, edx + cmova ecx, edx + sub edx, ecx + rep stosb +@@: + mov ecx, edx + and edx, 15 + shr ecx, 4 + jz @ZeroBytes + pxor xmm0, xmm0 +@@: + movntdq [edi], xmm0 + add edi, 16 + loop @B + mfence +@ZeroBytes: + mov ecx, edx + rep stosb + mov eax, [esp + 8] + ret +InternalMemZeroMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/CompareMem.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/CompareMem.asm new file mode 100644 index 0000000000..b8e289bb27 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/CompareMem.asm @@ -0,0 +1,43 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CompareMem.Asm +; +; Abstract: +; +; CompareMem function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .code + +InternalMemCompareMem PROC USES rsi rdi + mov rsi, rcx + mov rdi, rdx + mov rcx, r8 + repe cmpsb + movzx rax, byte ptr [rsi - 1] + movzx rdx, byte ptr [rdi - 1] + sub rax, rdx + ret +InternalMemCompareMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/CopyMem.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/CopyMem.asm new file mode 100644 index 0000000000..955cd25f36 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/CopyMem.asm @@ -0,0 +1,78 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; CopyMem.asm +; +; Abstract: +; +; CopyMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_CopyMem ( +; IN VOID *Destination, +; IN VOID *Source, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +InternalMemCopyMem PROC USES rsi rdi + mov rsi, rdx ; rsi <- Source + mov rdi, rcx ; rdi <- Destination + lea r9, [rdi + r8 - 1] ; r9 <- Last byte of Destination + cmp rsi, rdi + mov rax, rdi ; rax <- Destination as return value + jae @F ; Copy forward if Source > Destination + cmp r9, rsi ; Overlapped? + jae @CopyBackward ; Copy backward if overlapped +@@: + xor rcx, rcx + sub rcx, rdi ; rcx <- -rdi + and rcx, 15 ; rcx + rsi should be 16 bytes aligned + jz @F ; skip if rcx == 0 + cmp rcx, r8 + cmova rcx, r8 + sub r8, rcx + rep movsb +@@: + mov rcx, r8 + and r8, 15 + shr rcx, 4 ; rcx <- # of DQwords to copy + jz @CopyBytes + movdqa [rsp + 18h], xmm0 ; save xmm0 on stack +@@: + movdqu xmm0, [rsi] ; rsi may not be 16-byte aligned + movntdq [rdi], xmm0 ; rdi should be 16-byte aligned + add rsi, 16 + add rdi, 16 + loop @B + mfence + movdqa xmm0, [rsp + 18h] ; restore xmm0 + jmp @CopyBytes ; copy remaining bytes +@CopyBackward: + mov rdi, r9 ; rdi <- Last byte of Destination + lea rsi, [rsi + r8 - 1] ; rsi <- Last byte of Source + std +@CopyBytes: + mov rcx, r8 + rep movsb + cld + ret +InternalMemCopyMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem16.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem16.asm new file mode 100644 index 0000000000..6af88fae5b --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem16.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem16.Asm +; +; Abstract: +; +; ScanMem16 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .code + +InternalMemScanMem16 PROC USES rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasw + lea rax, [rdi - 2] + cmovnz rax, rcx + ret +InternalMemScanMem16 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem32.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem32.asm new file mode 100644 index 0000000000..f9c9feb00e --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem32.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem32.Asm +; +; Abstract: +; +; ScanMem32 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .code + +InternalMemScanMem32 PROC USES rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasd + lea rax, [rdi - 4] + cmovnz rax, rcx + ret +InternalMemScanMem32 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem64.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem64.asm new file mode 100644 index 0000000000..2f286c9e2f --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem64.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem64.Asm +; +; Abstract: +; +; ScanMem64 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .code + +InternalMemScanMem64 PROC USES rdi + mov rdi, rcx + mov rax, r8 + mov rcx, rdx + repne scasq + lea rax, [rdi - 8] + cmovnz rax, rcx + ret +InternalMemScanMem64 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem8.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem8.asm new file mode 100644 index 0000000000..4027ece768 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/ScanMem8.asm @@ -0,0 +1,42 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ScanMem8.Asm +; +; Abstract: +; +; ScanMem8 function +; +; Notes: +; +; The following BaseMemoryLib instances share the same version of this file: +; +; BaseMemoryLibRepStr +; BaseMemoryLibMmx +; BaseMemoryLibSse2 +; +;------------------------------------------------------------------------------ + + .code + +InternalMemScanMem8 PROC USES rdi + mov rdi, rcx + mov rcx, rdx + mov rax, r8 + repne scasb + lea rax, [rdi - 1] + cmovnz rax, rcx ; set rax to 0 if not found + ret +InternalMemScanMem8 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem.asm new file mode 100644 index 0000000000..2aba207ab9 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem.asm @@ -0,0 +1,69 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem.asm +; +; Abstract: +; +; SetMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem PROC USES rdi + mov rdi, rcx ; rdi <- Buffer + mov al, r8b ; al <- Value + mov r9, rdi ; r9 <- Buffer as return value + xor rcx, rcx + sub rcx, rdi + and rcx, 15 ; rcx + rdi aligns on 16-byte boundary + jz @F + cmp rcx, rdx + cmova rcx, rdx + sub rdx, rcx + rep stosb +@@: + mov rcx, rdx + and rdx, 15 + shr rcx, 4 + jz @SetBytes + mov ah, al ; ax <- Value repeats twice + movdqa [rsp + 10h], xmm0 ; save xmm0 + movd xmm0, eax ; xmm0[0..16] <- Value repeats twice + pshuflw xmm0, xmm0, 0 ; xmm0[0..63] <- Value repeats 8 times + movlhps xmm0, xmm0 ; xmm0 <- Value repeats 16 times +@@: + movntdq [rdi], xmm0 ; rdi should be 16-byte aligned + add rdi, 16 + loop @B + mfence + movdqa xmm0, [rsp + 10h] ; restore xmm0 +@SetBytes: + mov ecx, edx ; high 32 bits of rcx are always zero + rep stosb + mov rax, r9 ; rax <- Return value + ret +InternalMemSetMem ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem16.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem16.asm new file mode 100644 index 0000000000..a2f4d0e538 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem16.asm @@ -0,0 +1,67 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem16.asm +; +; Abstract: +; +; SetMem16 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem16 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT16 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem16 PROC USES rdi + mov rdi, rcx + mov r9, rdi + xor rcx, rcx + sub rcx, rdi + and rcx, 15 + mov rax, r8 + jz @F + shr rcx, 1 + cmp rcx, rdx + cmova rcx, rdx + sub rdx, rcx + rep stosw +@@: + mov rcx, rdx + and edx, 7 + shr rcx, 3 + jz @SetWords + movd xmm0, eax + pshuflw xmm0, xmm0, 0 + movlhps xmm0, xmm0 +@@: + movntdq [rdi], xmm0 + add rdi, 16 + loop @B + mfence +@SetWords: + mov ecx, edx + rep stosw + mov rax, r9 + ret +InternalMemSetMem16 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem32.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem32.asm new file mode 100644 index 0000000000..24207ec699 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem32.asm @@ -0,0 +1,66 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem32.asm +; +; Abstract: +; +; SetMem32 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem32 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem32 PROC USES rdi + mov rdi, rcx + mov r9, rdi + xor rcx, rcx + sub rcx, rdi + and rcx, 15 + mov rax, r8 + jz @F + shr rcx, 2 + cmp rcx, rdx + cmova rcx, rdx + sub rdx, rcx + rep stosd +@@: + mov rcx, rdx + and edx, 3 + shr rcx, 2 + jz @SetDwords + movd xmm0, eax + pshufd xmm0, xmm0, 0 +@@: + movntdq [rdi], xmm0 + add rdi, 16 + loop @B + mfence +@SetDwords: + mov ecx, edx + rep stosd + mov rax, r9 + ret +InternalMemSetMem32 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem64.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem64.asm new file mode 100644 index 0000000000..8b33386ad0 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/SetMem64.asm @@ -0,0 +1,61 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; SetMem64.asm +; +; Abstract: +; +; SetMem64 function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_SetMem64 ( +; IN VOID *Buffer, +; IN UINTN Count, +; IN UINT8 Value +; ) +;------------------------------------------------------------------------------ +InternalMemSetMem64 PROC USES rdi + mov rdi, rcx + mov r9, rcx + test cl, 8 + jz @F + mov [rdi], r8 + add rdi, 8 + dec rdx +@@: + mov rcx, rdx + shr rcx, 1 + jz @SetQwords + movd xmm0, r8 + movlhps xmm0, xmm0 +@@: + movntdq [rdi], xmm0 + add rdi, 16 + loop @B + mfence +@SetQwords: + test dl, 1 + jz @F + mov [rdi], r8 +@@: + ret +InternalMemSetMem64 ENDP + + END diff --git a/MdePkg/Library/BaseMemoryLibSse2/x64/ZeroMem.asm b/MdePkg/Library/BaseMemoryLibSse2/x64/ZeroMem.asm new file mode 100644 index 0000000000..6d0f99ba94 --- /dev/null +++ b/MdePkg/Library/BaseMemoryLibSse2/x64/ZeroMem.asm @@ -0,0 +1,63 @@ +;------------------------------------------------------------------------------ +; +; Copyright (c) 2006, 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. +; +; Module Name: +; +; ZeroMem.asm +; +; Abstract: +; +; ZeroMem function +; +; Notes: +; +;------------------------------------------------------------------------------ + + .code + +;------------------------------------------------------------------------------ +; VOID * +; _mem_ZeroMem ( +; IN VOID *Buffer, +; IN UINTN Count +; ) +;------------------------------------------------------------------------------ +InternalMemZeroMem PROC USES rdi + mov rdi, rcx + xor rcx, rcx + xor eax, eax + sub rcx, rdi + and rcx, 15 + mov r8, rdi + jz @F + cmp rcx, rdx + cmova rcx, rdx + sub rdx, rcx + rep stosb +@@: + mov rcx, rdx + and edx, 15 + shr rcx, 4 + jz @ZeroBytes + pxor xmm0, xmm0 +@@: + movntdq [rdi], xmm0 ; rdi should be 16-byte aligned + add rdi, 16 + loop @B + mfence +@ZeroBytes: + mov ecx, edx + rep stosb + mov rax, r8 + ret +InternalMemZeroMem ENDP + + END diff --git a/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.mbd b/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.mbd new file mode 100644 index 0000000000..695b32e958 --- /dev/null +++ b/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.mbd @@ -0,0 +1,29 @@ + + + + + BasePcdLibNull + 40096a3a-5c2a-4fbc-aef7-5475dd7ab334 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-31 10:50 + + diff --git a/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.msa b/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.msa new file mode 100644 index 0000000000..5768d45a49 --- /dev/null +++ b/MdePkg/Library/BasePcdLibNull/BasePcdLibNull.msa @@ -0,0 +1,43 @@ + + + + + BasePcdLibNull + BASE + LIBRARY + 40096a3a-5c2a-4fbc-aef7-5475dd7ab334 + EDK_RELEASE_VERSION 0x00020000 + NULL PCD Library + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-31 10:50 + + + PcdLib + DebugLib + + + PcdLib.c + + + MdePkg + + diff --git a/MdePkg/Library/BasePcdLibNull/PcdLib.c b/MdePkg/Library/BasePcdLibNull/PcdLib.c new file mode 100644 index 0000000000..6c01017024 --- /dev/null +++ b/MdePkg/Library/BasePcdLibNull/PcdLib.c @@ -0,0 +1,734 @@ +/** @file + A emptry template implementation of PCD Library. + + Copyright (c) 2006, 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. + + Module Name: PcdLib.c + +**/ + + + +/** + Sets the current SKU in the PCD database to the value specified by SkuId. SkuId is returned. + + @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and + set values associated with a PCD token. + + @retval UINTN Return the SKU ID that just be set. + +**/ +UINTN +EFIAPI +LibPcdSetSku ( + IN UINTN SkuId + ) +{ + return SkuId; +} + + + +/** + Returns the 8-bit value for the token specified by TokenNumber. + + @param[in] The PCD token number to retrieve a current value for. + + @retval UINT8 Returns the 8-bit value for the token specified by TokenNumber. + +**/ +UINT8 +EFIAPI +LibPcdGet8 ( + IN UINTN TokenNumber + ) +{ + return 0; +} + + + +/** + Returns the 16-bit value for the token specified by TokenNumber. + + @param[in] The PCD token number to retrieve a current value for. + + @retval UINT16 Returns the 16-bit value for the token specified by TokenNumber. + +**/ +UINT16 +EFIAPI +LibPcdGet16 ( + IN UINTN TokenNumber + ) +{ + return 0; +} + + + +/** + Returns the 32-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT32 Returns the 32-bit value for the token specified by TokenNumber. + +**/ +UINT32 +EFIAPI +LibPcdGet32 ( + IN UINTN TokenNumber + ) +{ + return 0; +} + + + +/** + Returns the 64-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT64 Returns the 64-bit value for the token specified by TokenNumber. + +**/ +UINT64 +EFIAPI +LibPcdGet64 ( + IN UINTN TokenNumber + ) +{ + return 0; +} + + + +/** + Returns the pointer to the buffer of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval VOID* Returns the pointer to the token specified by TokenNumber. + +**/ +VOID * +EFIAPI +LibPcdGetPtr ( + IN UINTN TokenNumber + ) +{ + return 0; +} + + + +/** + Returns the Boolean value of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval BOOLEAN Returns the Boolean value of the token specified by TokenNumber. + +**/ +BOOLEAN +EFIAPI +LibPcdGetBool ( + IN UINTN TokenNumber + ) +{ + return 0; +} + + + +/** + Returns the size of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINTN Returns the size of the token specified by TokenNumber. + +**/ +UINTN +EFIAPI +LibPcdGetSize ( + IN UINTN TokenNumber + ) +{ + return 0; +} + + + +/** + Returns the 8-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT8 Return the UINT8. + +**/ +UINT8 +EFIAPI +LibPcdGetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return 0; +} + + + +/** + Returns the 16-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT16 Return the UINT16. + +**/ +UINT16 +EFIAPI +LibPcdGetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return 0; +} + + + +/** + Returns the 32-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT32 Return the UINT32. + +**/ +UINT32 +EFIAPI +LibPcdGetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return 0; +} + + + +/** + Returns the 64-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT64 Return the UINT64. + +**/ +UINT64 +EFIAPI +LibPcdGetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return 0; +} + + + +/** + Returns the pointer to the buffer of the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval VOID* Return the VOID* pointer. + +**/ +VOID * +EFIAPI +LibPcdGetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return 0; +} + + + +/** + Returns the Boolean value of the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval BOOLEAN Return the BOOLEAN. + +**/ +BOOLEAN +EFIAPI +LibPcdGetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return 0; +} + + + +/** + Returns the size of the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINTN Return the size. + +**/ +UINTN +EFIAPI +LibPcdGetExSize ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return 0; +} + + + +/** + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT8 +EFIAPI +LibPcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + return Value; +} + + + +/** + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @retval UINT16 Return the value been set. + +**/ +UINT16 +EFIAPI +LibPcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + return Value; +} + + + +/** + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @retval UINT32 Return the value been set. + +**/ +UINT32 +EFIAPI +LibPcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + return Value; +} + + + +/** + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @retval UINT64 Return the value been set. + +**/ +UINT64 +EFIAPI +LibPcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + return Value; +} + + + +/** + Sets a buffer for the token specified by TokenNumber to + the value specified by Value. Value is returned. + If Value is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value A pointer to the buffer to set. + + @retval VOID* Return the pointer for the buffer been set. + +**/ +VOID * +EFIAPI +LibPcdSetPtr ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + ASSERT (Value != NULL); + // + // Remove the CONST + // + return (VOID *)Value; +} + + + +/** + Sets the Boolean value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @retval BOOLEAN Return the value been set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + return Value; +} + + + +/** + Sets the 8-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT8 +EFIAPI +LibPcdSetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + ASSERT (Guid != NULL); + + return Value; +} + + + +/** + Sets the 16-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT16 +EFIAPI +LibPcdSetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + ASSERT (Guid != NULL); + + return Value; +} + + + +/** + Sets the 32-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @retval UINT32 Return the value been set. + +**/ +UINT32 +EFIAPI +LibPcdSetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + ASSERT (Guid != NULL); + + return Value; +} + + + +/** + Sets the 64-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @retval UINT64 Return the value been set. + +**/ +UINT64 +EFIAPI +LibPcdSetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + ASSERT (Guid != NULL); + + return Value; +} + + + +/** + Sets a buffer for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + If Value is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval VOID * Return the value been set. + +**/ +VOID * +EFIAPI +LibPcdSetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + // + // Remove the CONST + // + ASSERT (Guid != NULL); + ASSERT (Value != NULL); + + return (VOID *)Value; +} + + + +/** + Sets the Boolean value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The Boolean value to set. + + @retval Boolean Return the value been set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + ASSERT (Guid != NULL); + + return Value; +} + + + +/** + When the token specified by TokenNumber and Guid is set, + then notification function specified by NotificationFunction is called. + If Guid is NULL, then the default token space is used. + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates which + namespace to set a value from. If NULL, then the default + token space is used. + @param[in] TokenNumber The PCD token number to monitor. + @param[in] NotificationFunction The function to call when the token + specified by Guid and TokenNumber is set. + + @retval VOID + +**/ +VOID +EFIAPI +LibPcdCallbackOnSet ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + ASSERT (NotificationFunction != NULL); +} + + + +/** + Disable a notification function that was established with LibPcdCallbackonSet(). + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid Specify the GUID token space. + @param[in] TokenNumber Specify the token number. + @param[in] NotificationFunction The callback function to be unregistered. + + @retval VOID + +**/ +VOID +EFIAPI +LibPcdCancelCallback ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + ASSERT (NotificationFunction != NULL); +} + + + +/** + Retrieves the next PCD token number from the token space specified by Guid. + If Guid is NULL, then the default token space is used. If TokenNumber is 0, + then the first token number is returned. Otherwise, the token number that + follows TokenNumber in the token space is returned. If TokenNumber is the last + token number in the token space, then 0 is returned. If TokenNumber is not 0 and + is not in the token space specified by Guid, then ASSERT(). + + @param[in] Pointer to a 128-bit unique value that designates which namespace + to set a value from. If NULL, then the default token space is used. + @param[in] The previous PCD token number. If 0, then retrieves the first PCD + token number. + + @retval UINTN The next valid token number. + +**/ +UINTN +EFIAPI +LibPcdGetNextToken ( + IN CONST GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ) +{ + return 0; +} diff --git a/MdePkg/Library/BasePcdLibNull/build.xml b/MdePkg/Library/BasePcdLibNull/build.xml new file mode 100644 index 0000000000..2e4e22b070 --- /dev/null +++ b/MdePkg/Library/BasePcdLibNull/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.mbd b/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.mbd new file mode 100644 index 0000000000..f05ef61e26 --- /dev/null +++ b/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.mbd @@ -0,0 +1,30 @@ + + + + + BasePciCf8Lib + 472ab06d-9810-4c00-bb7f-dad1828fc1ab + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.msa b/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.msa new file mode 100644 index 0000000000..6ffbf8a0b1 --- /dev/null +++ b/MdePkg/Library/BasePciCf8Lib/BasePciCf8Lib.msa @@ -0,0 +1,45 @@ + + + + + BasePciCf8Lib + BASE + LIBRARY + 472ab06d-9810-4c00-bb7f-dad1828fc1ab + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + PciCf8Lib + IoLib + DebugLib + + + PciLib.c + + + MdePkg + + diff --git a/MdePkg/Library/BasePciCf8Lib/PciLib.c b/MdePkg/Library/BasePciCf8Lib/PciLib.c new file mode 100644 index 0000000000..c5880bdeee --- /dev/null +++ b/MdePkg/Library/BasePciCf8Lib/PciLib.c @@ -0,0 +1,1431 @@ +/** @file + PCI Library. + + Copyright (c) 2006, 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. + + Module Name: PciLib.c + +**/ + +// +// Declare I/O Ports used to perform PCI Confguration Cycles +// +#define PCI_CONFIGURATION_ADDRESS_PORT 0xCF8 +#define PCI_CONFIGURATION_DATA_PORT 0xCFC + +// +// Declare macro to convert PCI Library formatted address to CF8 formatted address +// +// PCI Library formatted address CF8 Formatted Address +// ============================= ====================== +// Bits 00..11 Register Bits 00..07 Register +// Bits 12..14 Function Bits 08..10 Function +// Bits 15..19 Device Bits 11..15 Device +// Bits 20..27 Bus Bits 16..23 Bus +// Bits 28..31 Reserved(MBZ) Bits 24..30 Reserved(MBZ) +// Bits 31..31 Must be 1 +// + +/** + Assert the validity of a PCI address. A valid PCI address should contain 1's + only in the low 28 bits. + + @param A The address to validate. + @param M Additional bits to assert to be zero. + +**/ +#define ASSERT_INVALID_PCI_ADDRESS(A,M) \ + ASSERT (((A) & (~0xffff0ff | (M))) == 0) + +/** + Convert a PCI Express address to PCI CF8 address. + + @param A The address to convert. + + @retval The coverted address. + +**/ +#define PCI_TO_CF8_ADDRESS(A) \ + ((UINT32)(((A) >> 4) | ((A) & 0xfc) | 0x80000000)) + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8Read8 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoRead8 (PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3)); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8Write8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoWrite8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + Value + ); +} + +/** + Performs a bitwise inclusive OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8Or8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoOr8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + OrData + ); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8And8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoAnd8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + AndData + ); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise inclusive OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8AndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoAndThenOr8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldRead8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldWrite8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldOr8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldAnd8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciCf8BitFieldAndThenOr8( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 0); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldAndThenOr8 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 3), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8Read16 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoRead16 (PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2)); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8Write16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoWrite16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + Value + ); +} + +/** + Performs a bitwise inclusive OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8Or16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoOr16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + OrData + ); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8And16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoAnd16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + AndData + ); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise inclusive OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8AndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoAndThenOr16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldRead16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldWrite16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldOr16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldAnd16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciCf8BitFieldAndThenOr16( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 1); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldAndThenOr16 ( + PCI_CONFIGURATION_DATA_PORT + (UINT16)(Address & 2), + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8Read32 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoRead32 (PCI_CONFIGURATION_DATA_PORT); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8Write32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoWrite32 ( + PCI_CONFIGURATION_DATA_PORT, + Value + ); +} + +/** + Performs a bitwise inclusive OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8Or32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoOr32 ( + PCI_CONFIGURATION_DATA_PORT, + OrData + ); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8And32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoAnd32 ( + PCI_CONFIGURATION_DATA_PORT, + AndData + ); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise inclusive OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8AndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoAndThenOr32 ( + PCI_CONFIGURATION_DATA_PORT, + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldRead32 ( + PCI_CONFIGURATION_DATA_PORT, + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldWrite32 ( + PCI_CONFIGURATION_DATA_PORT, + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldOr32 ( + PCI_CONFIGURATION_DATA_PORT, + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldAnd32 ( + PCI_CONFIGURATION_DATA_PORT, + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If the register specified by Address >= 0x100, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciCf8BitFieldAndThenOr32( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address, 3); + IoWrite32 (PCI_CONFIGURATION_ADDRESS_PORT, PCI_TO_CF8_ADDRESS (Address)); + return IoBitFieldAndThenOr32 ( + PCI_CONFIGURATION_DATA_PORT, + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If the register specified by StartAddress >= 0x100, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x100, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciCf8ReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN EndAddress; + + EndAddress = StartAddress + Size; + + if (StartAddress < EndAddress && (StartAddress & 1)) { + // + // Read a byte if StartAddress is byte aligned + // + *(UINT8*)Buffer = PciCf8Read8 (StartAddress); + StartAddress += sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (StartAddress < EndAddress && (StartAddress & 2)) { + // + // Read a word if StartAddress is word aligned + // + *(UINT16*)Buffer = PciCf8Read16 (StartAddress); + StartAddress += sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (EndAddress - StartAddress >= 4) { + // + // Read as many double words as possible + // + *(UINT32*)Buffer = PciCf8Read32 (StartAddress); + StartAddress += sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if ((EndAddress & 2) != 0) { + // + // Read the last remaining word if exist + // + *(UINT16*)Buffer = PciCf8Read16 (StartAddress); + StartAddress += sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (EndAddress & 1) { + // + // Read the last remaining byte if exist + // + *(UINT8*)Buffer = PciCf8Read8 (StartAddress); + } + + return Size; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If the register specified by StartAddress >= 0x100, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x100, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return Size + +**/ +UINTN +EFIAPI +PciCf8WriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN EndAddress; + + EndAddress = StartAddress + Size; + + if ((StartAddress < EndAddress) && ((StartAddress & 1)!= 0)) { + // + // Write a byte if StartAddress is byte aligned + // + PciCf8Write8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (StartAddress < EndAddress && (StartAddress & 2)) { + // + // Write a word if StartAddress is word aligned + // + PciCf8Write16 (StartAddress, *(UINT16*)Buffer); + StartAddress += sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (EndAddress - StartAddress >= 4) { + // + // Write as many double words as possible + // + PciCf8Write32 (StartAddress, *(UINT32*)Buffer); + StartAddress += sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (EndAddress & 2) { + // + // Write the last remaining word if exist + // + PciCf8Write16 (StartAddress, *(UINT16*)Buffer); + StartAddress += sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (EndAddress & 1) { + // + // Write the last remaining byte if exist + // + PciCf8Write8 (StartAddress, *(UINT8*)Buffer); + } + + return Size; +} diff --git a/MdePkg/Library/BasePciCf8Lib/build.xml b/MdePkg/Library/BasePciCf8Lib/build.xml new file mode 100644 index 0000000000..fdf000bbbd --- /dev/null +++ b/MdePkg/Library/BasePciCf8Lib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.mbd b/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.mbd new file mode 100644 index 0000000000..a7051c285a --- /dev/null +++ b/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.mbd @@ -0,0 +1,30 @@ + + + + + BasePciExpressLib + 287e50f4-a188-4699-b907-3e4080ca5688 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.msa b/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.msa new file mode 100644 index 0000000000..dd071189dc --- /dev/null +++ b/MdePkg/Library/BasePciExpressLib/BasePciExpressLib.msa @@ -0,0 +1,45 @@ + + + + + BasePciExpressLib + BASE + LIBRARY + 287e50f4-a188-4699-b907-3e4080ca5688 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + PciExpressLib + IoLib + DebugLib + + + PciLib.c + + + MdePkg + + diff --git a/MdePkg/Library/BasePciExpressLib/PciLib.c b/MdePkg/Library/BasePciExpressLib/PciLib.c new file mode 100644 index 0000000000..a3dab38ec3 --- /dev/null +++ b/MdePkg/Library/BasePciExpressLib/PciLib.c @@ -0,0 +1,1328 @@ +/** @file + PCI Library. + + Functions in this library instance make use of MMIO functions in IoLib to + access memory mapped PCI configuration space. + + All assertions for I/O operations are handled in MMIO functions in the IoLib + Library. + + Copyright (c) 2006, 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. + + Module Name: PciLib.c + +**/ + +/** + Assert the validity of a PCI address. A valid PCI address should contain 1's + only in the low 28 bits. + + @param A The address to validate. + +**/ +#define ASSERT_INVALID_PCI_ADDRESS(A) \ + ASSERT (((A) & ~0xfffffff) == 0) + + +UINTN +EFIAPI +GetPciExpressBaseAddress ( + VOID + ) +{ + /// @bug Change this to a PCD Get call to retrieve the PCI-E Base Address + return 0xc0000000; +} + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressRead8 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioRead8 (GetPciExpressBaseAddress () + Address); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioWrite8 (GetPciExpressBaseAddress () + Address, Value); +} + +/** + Performs a bitwise inclusive OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioOr8 (GetPciExpressBaseAddress () + Address, OrData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAnd8 (GetPciExpressBaseAddress () + Address, AndData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise inclusive OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAndThenOr8 ( + GetPciExpressBaseAddress () + Address, + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldRead8 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldWrite8 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldOr8 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAnd8 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciExpressBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAndThenOr8 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressRead16 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioRead16 (GetPciExpressBaseAddress () + Address); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioWrite16 (GetPciExpressBaseAddress () + Address, Value); +} + +/** + Performs a bitwise inclusive OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioOr16 (GetPciExpressBaseAddress () + Address, OrData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAnd16 (GetPciExpressBaseAddress () + Address, AndData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise inclusive OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAndThenOr16 ( + GetPciExpressBaseAddress () + Address, + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldRead16 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldWrite16 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldOr16 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAnd16 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 16-bit boundary, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciExpressBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAndThenOr16 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressRead32 ( + IN UINTN Address + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioRead32 (GetPciExpressBaseAddress () + Address); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioWrite32 (GetPciExpressBaseAddress () + Address, Value); +} + +/** + Performs a bitwise inclusive OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioOr32 (GetPciExpressBaseAddress () + Address, OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAnd32 (GetPciExpressBaseAddress () + Address, AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise inclusive OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioAndThenOr32 ( + GetPciExpressBaseAddress () + Address, + AndData, + OrData + ); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldRead32 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit + ); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldWrite32 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + Value + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldOr32 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + OrData + ); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAnd32 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If Address is not aligned on a 32-bit boundary, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciExpressBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + ASSERT_INVALID_PCI_ADDRESS (Address); + return MmioBitFieldAndThenOr32 ( + GetPciExpressBaseAddress () + Address, + StartBit, + EndBit, + AndData, + OrData + ); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciExpressReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + UINTN EndAddress; + + EndAddress = StartAddress + Size; + + if (StartAddress < EndAddress && (StartAddress & 1)) { + // + // Read a byte if StartAddress is byte aligned + // + *(UINT8*)Buffer = PciExpressRead8 (StartAddress); + StartAddress += sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (StartAddress < EndAddress && (StartAddress & 2)) { + // + // Read a word if StartAddress is word aligned + // + *(UINT16*)Buffer = PciExpressRead16 (StartAddress); + StartAddress += sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (EndAddress - StartAddress >= 4) { + // + // Read as many double words as possible + // + *(UINT32*)Buffer = PciExpressRead32 (StartAddress); + StartAddress += sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if ((EndAddress & 2) != 0) { + // + // Read the last remaining word if exist + // + *(UINT16*)Buffer = PciExpressRead16 (StartAddress); + StartAddress += sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (EndAddress & 1) { + // + // Read the last remaining byte if exist + // + *(UINT8*)Buffer = PciExpressRead8 (StartAddress); + } + + return Size; +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return Size + +**/ +UINTN +EFIAPI +PciExpressWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + UINTN EndAddress; + + EndAddress = StartAddress + Size; + + if ((StartAddress < EndAddress) && ((StartAddress & 1)!= 0)) { + // + // Write a byte if StartAddress is byte aligned + // + PciExpressWrite8 (StartAddress, *(UINT8*)Buffer); + StartAddress += sizeof (UINT8); + Buffer = (UINT8*)Buffer + 1; + } + + if (StartAddress < EndAddress && (StartAddress & 2)) { + // + // Write a word if StartAddress is word aligned + // + PciExpressWrite16 (StartAddress, *(UINT16*)Buffer); + StartAddress += sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + while (EndAddress - StartAddress >= 4) { + // + // Write as many double words as possible + // + PciExpressWrite32 (StartAddress, *(UINT32*)Buffer); + StartAddress += sizeof (UINT32); + Buffer = (UINT32*)Buffer + 1; + } + + if (EndAddress & 2) { + // + // Write the last remaining word if exist + // + PciExpressWrite16 (StartAddress, *(UINT16*)Buffer); + StartAddress += sizeof (UINT16); + Buffer = (UINT16*)Buffer + 1; + } + + if (EndAddress & 1) { + // + // Write the last remaining byte if exist + // + PciExpressWrite8 (StartAddress, *(UINT8*)Buffer); + } + + return Size; +} diff --git a/MdePkg/Library/BasePciExpressLib/build.xml b/MdePkg/Library/BasePciExpressLib/build.xml new file mode 100644 index 0000000000..576b73207a --- /dev/null +++ b/MdePkg/Library/BasePciExpressLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.mbd b/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.mbd new file mode 100644 index 0000000000..b908388955 --- /dev/null +++ b/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.mbd @@ -0,0 +1,30 @@ + + + + + BasePciLibCf8 + 28bde99c-e8a7-4e3e-9a8a-e66cd64f31c6 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.msa b/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.msa new file mode 100644 index 0000000000..808a82bd76 --- /dev/null +++ b/MdePkg/Library/BasePciLibCf8/BasePciLibCf8.msa @@ -0,0 +1,45 @@ + + + + + BasePciLibCf8 + BASE + LIBRARY + 28bde99c-e8a7-4e3e-9a8a-e66cd64f31c6 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + PciLib + PciCf8Lib + DebugLib + + + PciLib.c + + + MdePkg + + diff --git a/MdePkg/Library/BasePciLibCf8/PciLib.c b/MdePkg/Library/BasePciLibCf8/PciLib.c new file mode 100644 index 0000000000..3a41809dbd --- /dev/null +++ b/MdePkg/Library/BasePciLibCf8/PciLib.c @@ -0,0 +1,1070 @@ +/** @file + PCI Library using Port CF8/CFC access. + + Copyright (c) 2006, 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. + + Module Name: PciLib.c + +**/ + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciRead8 ( + IN UINTN Address + ) +{ + return PciCf8Read8 (Address); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciWrite8 ( + IN UINTN Address, + IN UINT8 Data + ) +{ + return PciCf8Write8 (Address, Data); +} + +/** + Performs a bitwise inclusive OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return PciCf8Or8 (Address, OrData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return PciCf8And8 (Address, AndData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise inclusive OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciCf8AndThenOr8 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciCf8BitFieldRead8 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciCf8BitFieldWrite8 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciCf8BitFieldOr8 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciCf8BitFieldAnd8 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciCf8BitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciRead16 ( + IN UINTN Address + ) +{ + return PciCf8Read16 (Address); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciWrite16 ( + IN UINTN Address, + IN UINT16 Data + ) +{ + return PciCf8Write16 (Address, Data); +} + +/** + Performs a bitwise inclusive OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return PciCf8Or16 (Address, OrData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return PciCf8And16 (Address, AndData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise inclusive OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciCf8AndThenOr16 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciCf8BitFieldRead16 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciCf8BitFieldWrite16 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciCf8BitFieldOr16 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciCf8BitFieldAnd16 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciCf8BitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciRead32 ( + IN UINTN Address + ) +{ + return PciCf8Read32 (Address); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciWrite32 ( + IN UINTN Address, + IN UINT32 Data + ) +{ + return PciCf8Write32 (Address, Data); +} + +/** + Performs a bitwise inclusive OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return PciCf8Or32 (Address, OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return PciCf8And32 (Address, AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise inclusive OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciCf8AndThenOr32 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciCf8BitFieldRead32 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciCf8BitFieldWrite32 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciCf8BitFieldOr32 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciCf8BitFieldAnd32 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciCf8BitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + return PciCf8ReadBuffer (StartAddress, Size, Buffer); +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return Size + +**/ +UINTN +EFIAPI +PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + return PciCf8WriteBuffer (StartAddress, Size, Buffer); +} diff --git a/MdePkg/Library/BasePciLibCf8/build.xml b/MdePkg/Library/BasePciLibCf8/build.xml new file mode 100644 index 0000000000..3e59bd0642 --- /dev/null +++ b/MdePkg/Library/BasePciLibCf8/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.mbd b/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.mbd new file mode 100644 index 0000000000..c2caa74b26 --- /dev/null +++ b/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.mbd @@ -0,0 +1,30 @@ + + + + + BasePciLibPciExpress + 8987081e-daeb-44a9-8bef-a195b22d9417 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.msa b/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.msa new file mode 100644 index 0000000000..f98049cb38 --- /dev/null +++ b/MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.msa @@ -0,0 +1,45 @@ + + + + + BasePciLibPciExpress + BASE + LIBRARY + 8987081e-daeb-44a9-8bef-a195b22d9417 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + PciLib + PciExpressLib + DebugLib + + + PciLib.c + + + MdePkg + + diff --git a/MdePkg/Library/BasePciLibPciExpress/PciLib.c b/MdePkg/Library/BasePciLibPciExpress/PciLib.c new file mode 100644 index 0000000000..59bcd2dc0e --- /dev/null +++ b/MdePkg/Library/BasePciLibPciExpress/PciLib.c @@ -0,0 +1,1070 @@ +/** @file + PCI Library using PC Express access. + + Copyright (c) 2006, 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. + + Module Name: PciLib.c + +**/ + +/** + Reads an 8-bit PCI configuration register. + + Reads and returns the 8-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciRead8 ( + IN UINTN Address + ) +{ + return PciExpressRead8 (Address); +} + +/** + Writes an 8-bit PCI configuration register. + + Writes the 8-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciWrite8 ( + IN UINTN Address, + IN UINT8 Data + ) +{ + return PciExpressWrite8 (Address, Data); +} + +/** + Performs a bitwise inclusive OR of an 8-bit PCI configuration register with + an 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return PciExpressOr8 (Address, OrData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return PciExpressAnd8 (Address, AndData); +} + +/** + Performs a bitwise AND of an 8-bit PCI configuration register with an 8-bit + value, followed a bitwise inclusive OR with another 8-bit value. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciExpressAndThenOr8 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in an 8-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciExpressBitFieldRead8 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 8-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return PciExpressBitFieldWrite8 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in an 8-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 8-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return PciExpressBitFieldOr8 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in an 8-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 8-bit register. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 8-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return PciExpressBitFieldAnd8 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 8-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT8 +EFIAPI +PciBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return PciExpressBitFieldAndThenOr8 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 16-bit PCI configuration register. + + Reads and returns the 16-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciRead16 ( + IN UINTN Address + ) +{ + return PciExpressRead16 (Address); +} + +/** + Writes a 16-bit PCI configuration register. + + Writes the 16-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciWrite16 ( + IN UINTN Address, + IN UINT16 Data + ) +{ + return PciExpressWrite16 (Address, Data); +} + +/** + Performs a bitwise inclusive OR of a 16-bit PCI configuration register with + a 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return PciExpressOr16 (Address, OrData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return PciExpressAnd16 (Address, AndData); +} + +/** + Performs a bitwise AND of a 16-bit PCI configuration register with a 16-bit + value, followed a bitwise inclusive OR with another 16-bit value. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciExpressAndThenOr16 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 16-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciExpressBitFieldRead16 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 16-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return PciExpressBitFieldWrite16 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 16-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 16-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return PciExpressBitFieldOr16 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 16-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 16-bit register. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 16-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return PciExpressBitFieldAnd16 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 16-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT16 +EFIAPI +PciBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return PciExpressBitFieldAndThenOr16 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a 32-bit PCI configuration register. + + Reads and returns the 32-bit PCI configuration register specified by Address. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + + @return The read value from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciRead32 ( + IN UINTN Address + ) +{ + return PciExpressRead32 (Address); +} + +/** + Writes a 32-bit PCI configuration register. + + Writes the 32-bit PCI configuration register specified by Address with the + value specified by Value. Value is returned. This function must guarantee + that all PCI read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param Value The value to write. + + @return The value written to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciWrite32 ( + IN UINTN Address, + IN UINT32 Data + ) +{ + return PciExpressWrite32 (Address, Data); +} + +/** + Performs a bitwise inclusive OR of a 32-bit PCI configuration register with + a 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return PciExpressOr32 (Address, OrData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return PciExpressAnd32 (Address, AndData); +} + +/** + Performs a bitwise AND of a 32-bit PCI configuration register with a 32-bit + value, followed a bitwise inclusive OR with another 32-bit value. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, + performs a bitwise inclusive OR between the result of the AND operation and + the value specified by OrData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. + + If Address > 0x0FFFFFFF, then ASSERT(). + + @param Address Address that encodes the PCI Bus, Device, Function and + Register. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciExpressAndThenOr32 (Address, AndData, OrData); +} + +/** + Reads a bit field of a PCI configuration register. + + Reads the bit field in a 32-bit PCI configuration register. The bit field is + specified by the StartBit and the EndBit. The value of the bit field is + returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value of the bit field read from the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return PciExpressBitFieldRead32 (Address, StartBit, EndBit); +} + +/** + Writes a bit field to a PCI configuration register. + + Writes Value to the bit field of the PCI configuration register. The bit + field is specified by the StartBit and the EndBit. All other bits in the + destination PCI configuration register are preserved. The new value of the + 32-bit register is returned. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return PciExpressBitFieldWrite32 (Address, StartBit, EndBit, Value); +} + +/** + Reads a bit field in a 32-bit PCI configuration, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise inclusive OR between the read result and the value specified by + OrData, and writes the result to the 32-bit PCI configuration register + specified by Address. The value written to the PCI configuration register is + returned. This function must guarantee that all PCI read and write operations + are serialized. Extra left bits in OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return PciExpressBitFieldOr32 (Address, StartBit, EndBit, OrData); +} + +/** + Reads a bit field in a 32-bit PCI configuration register, performs a bitwise + AND, and writes the result back to the bit field in the 32-bit register. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND between the read result and the value specified by AndData, and + writes the result to the 32-bit PCI configuration register specified by + Address. The value written to the PCI configuration register is returned. + This function must guarantee that all PCI read and write operations are + serialized. Extra left bits in AndData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return PciExpressBitFieldAnd32 (Address, StartBit, EndBit, AndData); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit PCI configuration register specified by Address, performs a + bitwise AND followed by a bitwise inclusive OR between the read result and + the value specified by AndData, and writes the result to the 32-bit PCI + configuration register specified by Address. The value written to the PCI + configuration register is returned. This function must guarantee that all PCI + read and write operations are serialized. Extra left bits in both AndData and + OrData are stripped. + + If Address > 0x0FFFFFFF, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address PCI configuration register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the PCI configuration register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the PCI configuration register. + +**/ +UINT32 +EFIAPI +PciBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return PciExpressBitFieldAndThenOr32 (Address, StartBit, EndBit, AndData, OrData); +} + +/** + Reads a range of PCI configuration registers into a caller supplied buffer. + + Reads the range of PCI configuration registers specified by StartAddress and + Size into the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be read. Size is + returned. When possible 32-bit PCI configuration read cycles are used to read + from StartAdress to StartAddress + Size. Due to alignment restrictions, 8-bit + and 16-bit PCI configuration read cycles may be used at the beginning and the + end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer receiving the data read. + + @return Size + +**/ +UINTN +EFIAPI +PciReadBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + OUT VOID *Buffer + ) +{ + return PciExpressReadBuffer (StartAddress, Size, Buffer); +} + +/** + Copies the data in a caller supplied buffer to a specified range of PCI + configuration space. + + Writes the range of PCI configuration registers specified by StartAddress and + Size from the buffer specified by Buffer. This function only allows the PCI + configuration registers from a single PCI function to be written. Size is + returned. When possible 32-bit PCI configuration write cycles are used to + write from StartAdress to StartAddress + Size. Due to alignment restrictions, + 8-bit and 16-bit PCI configuration write cycles may be used at the beginning + and the end of the range. + + If StartAddress > 0x0FFFFFFF, then ASSERT(). + If ((StartAddress & 0xFFF) + Size) > 0x1000, then ASSERT(). + If (StartAddress + Size - 1) > 0x0FFFFFFF, then ASSERT(). + If Buffer is NULL, then ASSERT(). + + @param StartAddress Starting address that encodes the PCI Bus, Device, + Function and Register. + @param Size Size in bytes of the transfer. + @param Buffer Pointer to a buffer containing the data to write. + + @return Size + +**/ +UINTN +EFIAPI +PciWriteBuffer ( + IN UINTN StartAddress, + IN UINTN Size, + IN VOID *Buffer + ) +{ + return PciExpressWriteBuffer (StartAddress, Size, Buffer); +} diff --git a/MdePkg/Library/BasePciLibPciExpress/build.xml b/MdePkg/Library/BasePciLibPciExpress/build.xml new file mode 100644 index 0000000000..162f29e06e --- /dev/null +++ b/MdePkg/Library/BasePciLibPciExpress/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.mbd b/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.mbd new file mode 100644 index 0000000000..8bb2641d77 --- /dev/null +++ b/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.mbd @@ -0,0 +1,30 @@ + + + + + BasePeCoffGetEntryPointLib + be490364-73d2-420d-950e-f6450ca75dfb + 0 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.msa b/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.msa new file mode 100644 index 0000000000..7a619df39b --- /dev/null +++ b/MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.msa @@ -0,0 +1,43 @@ + + + + + BasePeCoffGetEntryPointLib + BASE + LIBRARY + be490364-73d2-420d-950e-f6450ca75dfb + 0 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + PeCoffGetEntryPointLib + + + PeCoffGetEntryPoint.c + + + MdePkg + + diff --git a/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c b/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c new file mode 100644 index 0000000000..d5ff7db009 --- /dev/null +++ b/MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c @@ -0,0 +1,54 @@ +/** @file + Tiano PE/COFF loader. + + Copyright (c) 2006, 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. + + Module Name: PeCoffGetEntryPoint.c + +**/ + + + +/** + Loads a PE/COFF image into memory. + + @param Pe32Data Pointer to a PE/COFF Image + + @param EntryPoint Pointer to the entry point of the PE/COFF image + + @retval EFI_SUCCESS if the EntryPoint was returned + @retval EFI_INVALID_PARAMETER if the EntryPoint could not be found from Pe32Data + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + IN OUT VOID **EntryPoint + ) +{ + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_NT_HEADERS *PeHeader; + + DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + PeHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base + // + PeHeader = (EFI_IMAGE_NT_HEADERS *) Pe32Data; + } + *EntryPoint = (VOID *) ((UINTN) Pe32Data + (UINTN) (PeHeader->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff)); + return RETURN_SUCCESS; +} diff --git a/MdePkg/Library/BasePeCoffGetEntryPointLib/build.xml b/MdePkg/Library/BasePeCoffGetEntryPointLib/build.xml new file mode 100644 index 0000000000..4d74c32630 --- /dev/null +++ b/MdePkg/Library/BasePeCoffGetEntryPointLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c new file mode 100644 index 0000000000..c7f3354637 --- /dev/null +++ b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c @@ -0,0 +1,1019 @@ +/** @file + Tiano PE/COFF loader. + + Copyright (c) 2006, 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. + + Module Name: PeCoffLoader.c + +**/ + + + + +STATIC +RETURN_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_NT_HEADERS *PeHdr, + OUT EFI_TE_IMAGE_HEADER *TeHdr + ); + +STATIC +RETURN_STATUS +PeCoffLoaderCheckImageType ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_NT_HEADERS *PeHdr, + IN EFI_TE_IMAGE_HEADER *TeHdr + ); + +STATIC +VOID * +PeCoffLoaderImageAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ); + +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ); + + + +/** + Retrieves the PE or TE Header from a PE/COFF or TE image. + + @param ImageContext The context of the image being loaded. + + @param PeHdr The buffer in which to return the PE header. + + @param TeHdr The buffer in which to return the TE header. + + @return + RETURN_SUCCESS if the PE or TE Header is read, + Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function. + +**/ +STATIC +RETURN_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_NT_HEADERS *PeHdr, + OUT EFI_TE_IMAGE_HEADER *TeHdr + ) +{ + RETURN_STATUS Status; + EFI_IMAGE_DOS_HEADER DosHdr; + UINTN Size; + + ImageContext->IsTeImage = FALSE; + // + // Read the DOS image headers + // + Size = sizeof (EFI_IMAGE_DOS_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &Size, + &DosHdr + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + ImageContext->PeCoffHeaderOffset = 0; + if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew; + } + // + // Read the PE/COFF Header + // + Size = sizeof (EFI_IMAGE_NT_HEADERS); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + ImageContext->PeCoffHeaderOffset, + &Size, + PeHdr + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + // + // Check the PE/COFF Header Signature. If not, then try to read a TE header + // + if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) { + Size = sizeof (EFI_TE_IMAGE_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &Size, + TeHdr + ); + if (TeHdr->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) { + return RETURN_UNSUPPORTED; + } + + ImageContext->IsTeImage = TRUE; + } + + return RETURN_SUCCESS; +} + +/** + Checks the PE or TE header of a PE/COFF or TE image to determine if it supported. + + @param ImageContext The context of the image being loaded. + + @param PeHdr The buffer in which to return the PE header. + + @param TeHdr The buffer in which to return the TE header. + + @retval RETURN_SUCCESS if the PE/COFF or TE image is supported + @retval RETURN_UNSUPPORTED of the PE/COFF or TE image is not supported. + +**/ +STATIC +RETURN_STATUS +PeCoffLoaderCheckImageType ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_NT_HEADERS *PeHdr, + IN EFI_TE_IMAGE_HEADER *TeHdr + ) +{ + // + // See if the machine type is supported. We support a native machine type (IA-32/Itanium-based) + // and the machine type for the Virtual Machine. + // + if (ImageContext->IsTeImage == FALSE) { + ImageContext->Machine = PeHdr->FileHeader.Machine; + } else { + ImageContext->Machine = TeHdr->Machine; + } + + if (!(EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageContext->Machine))) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE; + return RETURN_UNSUPPORTED; + } + + // + // See if the image type is supported. We support EFI Applications, + // EFI Boot Service Drivers, and EFI Runtime Drivers. + // + if (ImageContext->IsTeImage == FALSE) { + ImageContext->ImageType = PeHdr->OptionalHeader.Subsystem; + } else { + ImageContext->ImageType = (UINT16) (TeHdr->Subsystem); + } + + + return RETURN_SUCCESS; +} + +/** + Retrieves information on a PE/COFF image. + + @param This Calling context + @param ImageContext The context of the image being loaded + + @retval RETURN_SUCCESS The information on the PE/COFF image was collected. + @retval RETURN_INVALID_PARAMETER ImageContext is NULL. + @retval RETURN_UNSUPPORTED The PE/COFF image is not supported. + @retval Otherwise The error status from reading the PE/COFF image using the + ImageContext->ImageRead() function + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderGetImageInfo ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + RETURN_STATUS Status; + EFI_IMAGE_NT_HEADERS PeHdr; + EFI_TE_IMAGE_HEADER TeHdr; + EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry; + UINTN Size; + UINTN Index; + UINTN DebugDirectoryEntryRva; + UINTN DebugDirectoryEntryFileOffset; + UINTN SectionHeaderOffset; + EFI_IMAGE_SECTION_HEADER SectionHeader; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry; + + if (NULL == ImageContext) { + return RETURN_INVALID_PARAMETER; + } + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + Status = PeCoffLoaderGetPeHeader (ImageContext, &PeHdr, &TeHdr); + if (RETURN_ERROR (Status)) { + return Status; + } + // + // Verify machine type + // + Status = PeCoffLoaderCheckImageType (ImageContext, &PeHdr, &TeHdr); + if (RETURN_ERROR (Status)) { + return Status; + } + // + // Retrieve the base address of the image + // + if (!(ImageContext->IsTeImage)) { + ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase; + } else { + ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr.ImageBase); + } + // + // Initialize the alternate destination address to 0 indicating that it + // should not be used. + // + ImageContext->DestinationAddress = 0; + + // + // Initialize the codeview pointer. + // + ImageContext->CodeView = NULL; + ImageContext->PdbPointer = NULL; + + // + // Three cases with regards to relocations: + // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable + // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable + // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but + // has no base relocs to apply + // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid. + // + // Look at the file header to determine if relocations have been stripped, and + // save this info in the image context for later use. + // + if ((!(ImageContext->IsTeImage)) && ((PeHdr.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) { + ImageContext->RelocationsStripped = TRUE; + } else { + ImageContext->RelocationsStripped = FALSE; + } + + if (!(ImageContext->IsTeImage)) { + ImageContext->ImageSize = (UINT64) PeHdr.OptionalHeader.SizeOfImage; + ImageContext->SectionAlignment = PeHdr.OptionalHeader.SectionAlignment; + ImageContext->SizeOfHeaders = PeHdr.OptionalHeader.SizeOfHeaders; + + // + // Modify ImageSize to contain .PDB file name if required and initialize + // PdbRVA field... + // + if (PeHdr.OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + + // + // Determine the file offset of the debug directory... This means we walk + // the sections to find which section contains the RVA of the debug + // directory + // + DebugDirectoryEntryFileOffset = 0; + + SectionHeaderOffset = (UINTN)( + ImageContext->PeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + PeHdr.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < PeHdr.FileHeader.NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = + DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData; + break; + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset, + &Size, + &DebugEntry + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) { + ImageContext->ImageSize += DebugEntry.SizeOfData; + } + + return RETURN_SUCCESS; + } + } + } + } + } else { + ImageContext->ImageSize = 0; + ImageContext->SectionAlignment = 4096; + ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) TeHdr.BaseOfCode - (UINTN) TeHdr.StrippedSize; + + DebugDirectoryEntry = &TeHdr.DataDirectory[1]; + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + SectionHeaderOffset = (UINTN) (sizeof (EFI_TE_IMAGE_HEADER)); + + DebugDirectoryEntryFileOffset = 0; + + for (Index = 0; Index < TeHdr.NumberOfSections;) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - + SectionHeader.VirtualAddress + + SectionHeader.PointerToRawData + + sizeof (EFI_TE_IMAGE_HEADER) - + TeHdr.StrippedSize; + + // + // File offset of the debug directory was found, if this is not the last + // section, then skip to the last section for calculating the image size. + // + if (Index < (UINTN) TeHdr.NumberOfSections - 1) { + SectionHeaderOffset += (TeHdr.NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER); + Index = TeHdr.NumberOfSections - 1; + continue; + } + } + + // + // In Te image header there is not a field to describe the ImageSize. + // Actually, the ImageSize equals the RVA plus the VirtualSize of + // the last section mapped into memory (Must be rounded up to + // a mulitple of Section Alignment). Per the PE/COFF specification, the + // section headers in the Section Table must appear in order of the RVA + // values for the corresponding sections. So the ImageSize can be determined + // by the RVA and the VirtualSize of the last section header in the + // Section Table. + // + if ((++Index) == (UINTN) TeHdr.NumberOfSections) { + ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize + + ImageContext->SectionAlignment - 1) & ~(ImageContext->SectionAlignment - 1); + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset, + &Size, + &DebugEntry + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + return RETURN_SUCCESS; + } + } + } + } + + return RETURN_SUCCESS; +} + +/** + Converts an image address to the loaded address. + + @param ImageContext The context of the image being loaded. + + @param Address The address to be converted to the loaded address. + + @return NULL if the address can not be converted, otherwise, the converted address + +**/ +STATIC +VOID * +PeCoffLoaderImageAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ) +{ + if (Address >= ImageContext->ImageSize) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return NULL; + } + + return (CHAR8 *) ((UINTN) ImageContext->ImageAddress + Address); +} + +/** + Relocates a PE/COFF image in memory. + + @param This Calling context. + + @param ImageContext Contains information on the loaded image to relocate. + + @retval RETURN_SUCCESS if the PE/COFF image was relocated. + @retval RETURN_LOAD_ERROR if the image is not a valid PE/COFF image. + @retval RETURN_UNSUPPORTED not support. + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderRelocateImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + RETURN_STATUS Status; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + EFI_IMAGE_DATA_DIRECTORY *RelocDir; + UINT64 Adjust; + EFI_IMAGE_BASE_RELOCATION *RelocBase; + EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; + UINT16 *Reloc; + UINT16 *RelocEnd; + CHAR8 *Fixup; + CHAR8 *FixupBase; + UINT16 *F16; + UINT32 *F32; + CHAR8 *FixupData; + PHYSICAL_ADDRESS BaseAddress; + + PeHdr = NULL; + TeHdr = NULL; + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + // + // If there are no relocation entries, then we are done + // + if (ImageContext->RelocationsStripped) { + return RETURN_SUCCESS; + } + + // + // If the destination address is not 0, use that rather than the + // image address as the relocation target. + // + if (ImageContext->DestinationAddress) { + BaseAddress = ImageContext->DestinationAddress; + } else { + BaseAddress = ImageContext->ImageAddress; + } + + if (!(ImageContext->IsTeImage)) { + PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset); + Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase; + PeHdr->OptionalHeader.ImageBase = (UINTN)BaseAddress; + + // + // Find the relocation block + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + RelocDir = &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress); + RelocBaseEnd = PeCoffLoaderImageAddress ( + ImageContext, + RelocDir->VirtualAddress + RelocDir->Size - 1 + ); + } else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = 0; + } + } else { + TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress); + Adjust = (UINT64) (BaseAddress - TeHdr->ImageBase); + TeHdr->ImageBase = (UINT64) (BaseAddress); + + // + // Find the relocation block + // + RelocDir = &TeHdr->DataDirectory[0]; + RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)( + ImageContext->ImageAddress + + RelocDir->VirtualAddress + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1); + } + + // + // Run the relocation information and apply the fixups + // + FixupData = ImageContext->FixupData; + while (RelocBase < RelocBaseEnd) { + + Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); + RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock); + if (!(ImageContext->IsTeImage)) { + FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress); + } else { + FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress + + RelocBase->VirtualAddress + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + } + + if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) || + (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + + (UINTN)ImageContext->ImageSize)) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + + // + // Run this relocation record + // + while (Reloc < RelocEnd) { + + Fixup = FixupBase + (*Reloc & 0xFFF); + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + + case EFI_IMAGE_REL_BASED_HIGH: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) ((*F16 << 16) + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_LOW: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) (*F16 + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHLOW: + F32 = (UINT32 *) Fixup; + *F32 = *F32 + (UINT32) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32)); + *(UINT32 *) FixupData = *F32; + FixupData = FixupData + sizeof (UINT32); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHADJ: + // + // Return the same EFI_UNSUPPORTED return code as + // PeCoffLoaderRelocateImageEx() returns if it does not recognize + // the relocation type. + // + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_UNSUPPORTED; + + default: + Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return Status; + } + } + + // + // Next relocation record + // + Reloc += 1; + } + + // + // Next reloc block + // + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; + } + + return RETURN_SUCCESS; +} + +/** + Loads a PE/COFF image into memory. + + @param This Calling context. + + @param ImageContext Contains information on image to load into memory. + + @retval RETURN_SUCCESS if the PE/COFF image was loaded. + @retval RETURN_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer. + @retval RETURN_LOAD_ERROR if the image is a runtime driver with no relocations. + @retval RETURN_INVALID_PARAMETER if the image address is invalid. + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderLoadImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +{ + RETURN_STATUS Status; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + PE_COFF_LOADER_IMAGE_CONTEXT CheckContext; + EFI_IMAGE_SECTION_HEADER *FirstSection; + EFI_IMAGE_SECTION_HEADER *Section; + UINTN NumberOfSections; + UINTN Index; + CHAR8 *Base; + CHAR8 *End; + CHAR8 *MaxEnd; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN Size; + UINT32 TempDebugEntryRva; + + PeHdr = NULL; + TeHdr = NULL; + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + // + // Copy the provided context info into our local version, get what we + // can from the original image, and then use that to make sure everything + // is legit. + // + CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + + Status = PeCoffLoaderGetImageInfo (&CheckContext); + if (RETURN_ERROR (Status)) { + return Status; + } + + // + // Make sure there is enough allocated space for the image being loaded + // + if (ImageContext->ImageSize < CheckContext.ImageSize) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE; + return RETURN_BUFFER_TOO_SMALL; + } + + // + // If there's no relocations, then make sure it's not a runtime driver, + // and that it's being loaded at the linked address. + // + if (CheckContext.RelocationsStripped) { + // + // If the image does not contain relocations and it is a runtime driver + // then return an error. + // + if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM; + return RETURN_LOAD_ERROR; + } + // + // If the image does not contain relocations, and the requested load address + // is not the linked address, then return an error. + // + if (CheckContext.ImageAddress != ImageContext->ImageAddress) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return RETURN_INVALID_PARAMETER; + } + } + // + // Make sure the allocated space has the proper section alignment + // + if (!(ImageContext->IsTeImage)) { + if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT; + return RETURN_INVALID_PARAMETER; + } + } + // + // Read the entire PE/COFF or TE header into memory + // + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (VOID *) (UINTN) ImageContext->ImageAddress + ); + + PeHdr = (EFI_IMAGE_NT_HEADERS *) + ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + PeHdr->FileHeader.SizeOfOptionalHeader + ); + NumberOfSections = (UINTN) (PeHdr->FileHeader.NumberOfSections); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (void *) (UINTN) ImageContext->ImageAddress + ); + + TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + sizeof(EFI_TE_IMAGE_HEADER) + ); + NumberOfSections = (UINTN) (TeHdr->NumberOfSections); + + } + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + // + // Load each section of the image + // + Section = FirstSection; + for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) { + + // + // Compute sections address + // + Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress); + End = PeCoffLoaderImageAddress ( + ImageContext, + Section->VirtualAddress + Section->Misc.VirtualSize - 1 + ); + if (ImageContext->IsTeImage) { + Base = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize); + End = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize); + } + + if (End > MaxEnd) { + MaxEnd = End; + } + // + // If the base start or end address resolved to 0, then fail. + // + if ((Base == NULL) || (End == NULL)) { + ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED; + return RETURN_LOAD_ERROR; + } + + // + // Read the section + // + Size = (UINTN) Section->Misc.VirtualSize; + if ((Size == 0) || (Size > Section->SizeOfRawData)) { + Size = (UINTN) Section->SizeOfRawData; + } + + if (Section->SizeOfRawData) { + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData, + &Size, + Base + ); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize, + &Size, + Base + ); + } + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + } + + // + // If raw size is less then virt size, zero fill the remaining + // + + if (Size < Section->Misc.VirtualSize) { + ZeroMem (Base + Size, Section->Misc.VirtualSize - Size); + } + + // + // Next Section + // + Section += 1; + } + + // + // Get image's entry point + // + if (!(ImageContext->IsTeImage)) { + ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress ( + ImageContext, + PeHdr->OptionalHeader.AddressOfEntryPoint + ); + } else { + ImageContext->EntryPoint = (PHYSICAL_ADDRESS) ( + (UINTN)ImageContext->ImageAddress + + (UINTN)TeHdr->AddressOfEntryPoint + + (UINTN)sizeof(EFI_TE_IMAGE_HEADER) - + (UINTN) TeHdr->StrippedSize + ); + } + + // + // Determine the size of the fixup data + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (!(ImageContext->IsTeImage)) { + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) + &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } else { + ImageContext->FixupDataSize = 0; + } + } else { + DirectoryEntry = &TeHdr->DataDirectory[0]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } + // + // Consumer must allocate a buffer for the relocation fixup log. + // Only used for runtime drivers. + // + ImageContext->FixupData = NULL; + + // + // Load the Codeview info if present + // + if (ImageContext->DebugDirectoryEntryRva != 0) { + if (!(ImageContext->IsTeImage)) { + DebugEntry = PeCoffLoaderImageAddress ( + ImageContext, + ImageContext->DebugDirectoryEntryRva + ); + } else { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)( + ImageContext->ImageAddress + + ImageContext->DebugDirectoryEntryRva + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + } + + if (DebugEntry != NULL) { + TempDebugEntryRva = DebugEntry->RVA; + if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) { + Section--; + if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) { + TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize; + } else { + TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData; + } + } + + if (TempDebugEntryRva != 0) { + if (!(ImageContext->IsTeImage)) { + ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva); + } else { + ImageContext->CodeView = (VOID *)( + (UINTN)ImageContext->ImageAddress + + (UINTN)TempDebugEntryRva + + (UINTN)sizeof(EFI_TE_IMAGE_HEADER) - + (UINTN) TeHdr->StrippedSize + ); + } + + if (ImageContext->CodeView == NULL) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + if (DebugEntry->RVA == 0) { + Size = DebugEntry->SizeOfData; + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset, + &Size, + ImageContext->CodeView + ); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr->StrippedSize, + &Size, + ImageContext->CodeView + ); + // + // Should we apply fix up to this field according to the size difference between PE and TE? + // Because now we maintain TE header fields unfixed, this field will also remain as they are + // in original PE image. + // + } + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + DebugEntry->RVA = TempDebugEntryRva; + } + + switch (*(UINT32 *) ImageContext->CodeView) { + case CODEVIEW_SIGNATURE_NB10: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + break; + } + } + } + } + + return Status; +} diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.mbd b/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.mbd new file mode 100644 index 0000000000..7e8def950d --- /dev/null +++ b/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.mbd @@ -0,0 +1,30 @@ + + + + + BasePeCoffLib + 556f5d10-7309-4af4-b80a-8196bd60946f + 0 + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.msa b/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.msa new file mode 100644 index 0000000000..534558c7fa --- /dev/null +++ b/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.msa @@ -0,0 +1,56 @@ + + + + + BasePeCoffLib + BASE + LIBRARY + 556f5d10-7309-4af4-b80a-8196bd60946f + 0 + Component description file for the PEI library. + FIX ME! + Copyright (c) 2004 - 2005, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + PeCoffLib + BaseMemoryLib + + + BasePeCoff.c + + ia32\PeCoffLoaderEx.c + + + x64\PeCoffLoaderEx.c + + + ipf\PeCoffLoaderEx.c + + + ebc\PeCoffLoaderEx.c + + + + MdePkg + + diff --git a/MdePkg/Library/BasePeCoffLib/Ebc/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/Ebc/PeCoffLoaderEx.c new file mode 100644 index 0000000000..6cfc566bd4 --- /dev/null +++ b/MdePkg/Library/BasePeCoffLib/Ebc/PeCoffLoaderEx.c @@ -0,0 +1,43 @@ +/** @file + EBC Specific relocation fixups. + + Copyright (c) 2006, 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. + + Module Name: PeCoffLoaderEx.c + +**/ + + + + +/** + Performs an IA-32 specific relocation fixup. + + @param Reloc Pointer to the relocation record. + + @param Fixup Pointer to the address to fix up. + + @param FixupData Pointer to a buffer to log the fixups. + + @param Adjust The offset to adjust the fixup. + + @retval EFI_UNSUPPORTED Unsupported now. + +**/ +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + return RETURN_UNSUPPORTED; +} diff --git a/MdePkg/Library/BasePeCoffLib/Ia32/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/Ia32/PeCoffLoaderEx.c new file mode 100644 index 0000000000..4ee64c2b36 --- /dev/null +++ b/MdePkg/Library/BasePeCoffLib/Ia32/PeCoffLoaderEx.c @@ -0,0 +1,44 @@ +/** @file + IA-32 Specific relocation fixups. + + Copyright (c) 2006, 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. + + Module Name: PeCoffLoaderEx.c + +**/ + + + + + +/** + Performs an IA-32 specific relocation fixup. + + @param Reloc Pointer to the relocation record. + + @param Fixup Pointer to the address to fix up. + + @param FixupData Pointer to a buffer to log the fixups. + + @param Adjust The offset to adjust the fixup. + + @retval EFI_UNSUPPORTED Unsupported now. + +**/ +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + return RETURN_UNSUPPORTED; +} diff --git a/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c new file mode 100644 index 0000000000..d35231e9cd --- /dev/null +++ b/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c @@ -0,0 +1,230 @@ +/** @file + Fixes Intel Itanium(TM) specific relocation types. + + Copyright (c) 2006, 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. + + Module Name: PeCoffLoaderEx.c + +**/ + + + + + +#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \ + Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos) + +#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \ + *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \ + ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos) + +#define IMM64_IMM7B_INST_WORD_X 3 +#define IMM64_IMM7B_SIZE_X 7 +#define IMM64_IMM7B_INST_WORD_POS_X 4 +#define IMM64_IMM7B_VAL_POS_X 0 + +#define IMM64_IMM9D_INST_WORD_X 3 +#define IMM64_IMM9D_SIZE_X 9 +#define IMM64_IMM9D_INST_WORD_POS_X 18 +#define IMM64_IMM9D_VAL_POS_X 7 + +#define IMM64_IMM5C_INST_WORD_X 3 +#define IMM64_IMM5C_SIZE_X 5 +#define IMM64_IMM5C_INST_WORD_POS_X 13 +#define IMM64_IMM5C_VAL_POS_X 16 + +#define IMM64_IC_INST_WORD_X 3 +#define IMM64_IC_SIZE_X 1 +#define IMM64_IC_INST_WORD_POS_X 12 +#define IMM64_IC_VAL_POS_X 21 + +#define IMM64_IMM41a_INST_WORD_X 1 +#define IMM64_IMM41a_SIZE_X 10 +#define IMM64_IMM41a_INST_WORD_POS_X 14 +#define IMM64_IMM41a_VAL_POS_X 22 + +#define IMM64_IMM41b_INST_WORD_X 1 +#define IMM64_IMM41b_SIZE_X 8 +#define IMM64_IMM41b_INST_WORD_POS_X 24 +#define IMM64_IMM41b_VAL_POS_X 32 + +#define IMM64_IMM41c_INST_WORD_X 2 +#define IMM64_IMM41c_SIZE_X 23 +#define IMM64_IMM41c_INST_WORD_POS_X 0 +#define IMM64_IMM41c_VAL_POS_X 40 + +#define IMM64_SIGN_INST_WORD_X 3 +#define IMM64_SIGN_SIZE_X 1 +#define IMM64_SIGN_INST_WORD_POS_X 27 +#define IMM64_SIGN_VAL_POS_X 63 + +/** + Performs an Itanium-based specific relocation fixup. + + @param Reloc Pointer to the relocation record. + + @param Fixup Pointer to the address to fix up. + + @param FixupData Pointer to a buffer to log the fixups. + + @param Adjust The offset to adjust the fixup. + + @return Status code. + +**/ +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + UINT64 *F64; + UINT64 FixupVal; + + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_DIR64: + F64 = (UINT64 *) Fixup; + *F64 = *F64 + (UINT64) Adjust; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + case EFI_IMAGE_REL_BASED_IA64_IMM64: + + // + // Align it to bundle address before fixing up the + // 64-bit immediate value of the movl instruction. + // + + Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15)); + FixupVal = (UINT64)0; + + // + // Extract the lower 32 bits of IMM64 from bundle + // + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X, + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X, + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X, + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IC_INST_WORD_X, + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X, + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + // + // Update 64-bit address + // + FixupVal += Adjust; + + // + // Insert IMM64 into bundle + // + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X), + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X), + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X), + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X), + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X), + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X), + IMM64_IMM41b_SIZE_X, + IMM64_IMM41b_INST_WORD_POS_X, + IMM64_IMM41b_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X), + IMM64_IMM41c_SIZE_X, + IMM64_IMM41c_INST_WORD_POS_X, + IMM64_IMM41c_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X), + IMM64_SIGN_SIZE_X, + IMM64_SIGN_INST_WORD_POS_X, + IMM64_SIGN_VAL_POS_X + ); + + F64 = (UINT64 *) Fixup; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + default: + return RETURN_UNSUPPORTED; + } + + return RETURN_SUCCESS; +} diff --git a/MdePkg/Library/BasePeCoffLib/build.xml b/MdePkg/Library/BasePeCoffLib/build.xml new file mode 100644 index 0000000000..0aff39d00b --- /dev/null +++ b/MdePkg/Library/BasePeCoffLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BasePeCoffLib/x64/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/x64/PeCoffLoaderEx.c new file mode 100644 index 0000000000..7648447f71 --- /dev/null +++ b/MdePkg/Library/BasePeCoffLib/x64/PeCoffLoaderEx.c @@ -0,0 +1,56 @@ +/** @file + x64 Specific relocation fixups. + + Copyright (c) 2006, 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. + + Module Name: PeCoffLoaderEx.c + +**/ + + + + +/** + Performs an x64 specific relocation fixup. + + @param Reloc Pointer to the relocation record + @param Fixup Pointer to the address to fix up + @param FixupData Pointer to a buffer to log the fixups + @param Adjust The offset to adjust the fixup + +**/ +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + UINT64 *F64; + + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_DIR64: + F64 = (UINT64 *) Fixup; + *F64 = *F64 + (UINT64) Adjust; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + default: + return RETURN_UNSUPPORTED; + } + + return RETURN_SUCCESS; +} diff --git a/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.mbd b/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.mbd new file mode 100644 index 0000000000..ac9c3ac33f --- /dev/null +++ b/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.mbd @@ -0,0 +1,30 @@ + + + + + BasePerformanceLibNull + FC120ED3-40E1-46dc-8C9C-AAE3CA139ACF + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-04-04 11:05 + 2006-04-04 11:05 + + diff --git a/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.msa b/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.msa new file mode 100644 index 0000000000..3147d641ef --- /dev/null +++ b/MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.msa @@ -0,0 +1,52 @@ + + + + + BasePerformanceLibNull + BASE + LIBRARY + FC120ED3-40E1-46dc-8C9C-AAE3CA139ACF + EDK_RELEASE_VERSION 0x00020000 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-04 11:05 + 2006-04-04 11:05 + + + PerformanceLib + DebugLib + PcdLib + + + PerformanceLib.c + + + MdePkg + + + + PcdPerformanceLibraryPropertyMask + 0x00000001 + UINT8 + + + diff --git a/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c b/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c new file mode 100644 index 0000000000..01226cbb02 --- /dev/null +++ b/MdePkg/Library/BasePerformanceLibNull/PerformanceLib.c @@ -0,0 +1,148 @@ +/** @file + Base Performance Library which provides no service. + + Copyright (c) 2006, 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. + + Module Name: PerformanceLib.c + +**/ + +/** + Creates a record for the beginning of a performance measurement. + + Creates a record that contains the Handle, Token, and Module. + If TimeStamp is not zero, then TimeStamp is added to the record as the start time. + If TimeStamp is zero, then this function reads the current time stamp + and adds that time stamp value to the record as the start time. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The start of the measurement was recorded. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources to record the measurement. + +**/ +RETURN_STATUS +EFIAPI +StartPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, + IN CONST CHAR8 *Module, + IN UINT64 TimeStamp + ) +{ + return RETURN_SUCCESS; +} + +/** + Fills in the end time of a performance measurement. + + Looks up the record that matches Handle, Token, and Module. + If the record can not be found then return RETURN_NOT_FOUND. + If the record is found and TimeStamp is not zero, + then TimeStamp is added to the record as the end time. + If the record is found and TimeStamp is zero, then this function reads + the current time stamp and adds that time stamp value to the record as the end time. + If this function is called multiple times for the same record, then the end time is overwritten. + + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param TimeStamp 64-bit time stamp. + + @retval RETURN_SUCCESS The end of the measurement was recorded. + @retval RETURN_NOT_FOUND The specified measurement record could not be found. + +**/ +RETURN_STATUS +EFIAPI +EndPerformanceMeasurement ( + IN CONST VOID *Handle, OPTIONAL + IN CONST CHAR8 *Token, + IN CONST CHAR8 *Module, + IN UINT64 TimeStamp + ) +{ + return RETURN_SUCCESS; +} + +/** + Retrieves a previously logged performance measurement. + + Retrieves the performance log entry from the performance log + that immediately follows the log entry specified by LogEntryKey. + If LogEntryKey is zero, then the first entry from the performance log is returned. + If the log entry specified by LogEntryKey is the last entry in the performance log, + then 0 is returned. Otherwise, the performance log entry is returned in Handle, + Token, Module, StartTimeStamp, and EndTimeStamp. + The key for the current performance log entry is returned. + + @param LogEntryKey The key for the previous performance measurement log entry. + If 0, then the first performance measurement log entry is retrieved. + @param Handle Pointer to environment specific context used + to identify the component being measured. + @param Token Pointer to a Null-terminated ASCII string + that identifies the component being measured. + @param Module Pointer to a Null-terminated ASCII string + that identifies the module being measured. + @param StartTimeStamp The 64-bit time stamp that was recorded when the measurement was started. + @param EndTimeStamp The 64-bit time stamp that was recorded when the measurement was ended. + + @return The key for the current performance log entry. + +**/ +UINTN +EFIAPI +GetPerformanceMeasurement ( + UINTN LogEntryKey, + OUT CONST VOID **Handle, + OUT CONST CHAR8 **Token, + OUT CONST CHAR8 **Module, + OUT UINT64 *StartTimeStamp, + OUT UINT64 *EndTimeStamp + ) +{ + ASSERT (Handle != NULL); + ASSERT (Token != NULL); + ASSERT (Module != NULL); + ASSERT (StartTimeStamp != NULL); + ASSERT (EndTimeStamp != NULL); + + return 0; +} + +/** + Returns TRUE if the performance measurement macros are enabled. + + This function returns TRUE if the PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. Otherwise FALSE is returned. + + @retval TRUE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is set. + @retval FALSE The PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED bit of + PcdPerformanceLibraryPropertyMask is clear. + +**/ +BOOLEAN +EFIAPI +PerformanceMeasurementEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdPerformanceLibraryPropertyMask) & PERFORMANCE_LIBRARY_PROPERTY_MEASUREMENT_ENABLED) != 0); +} diff --git a/MdePkg/Library/BasePerformanceLibNull/build.xml b/MdePkg/Library/BasePerformanceLibNull/build.xml new file mode 100644 index 0000000000..aec9654740 --- /dev/null +++ b/MdePkg/Library/BasePerformanceLibNull/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BasePrintLib/BasePrintLib.mbd b/MdePkg/Library/BasePrintLib/BasePrintLib.mbd new file mode 100644 index 0000000000..8ac041b255 --- /dev/null +++ b/MdePkg/Library/BasePrintLib/BasePrintLib.mbd @@ -0,0 +1,30 @@ + + + + + BasePrintLib + a86fbfca-0183-4eeb-aa8a-762e3b7da1f3 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BasePrintLib/BasePrintLib.msa b/MdePkg/Library/BasePrintLib/BasePrintLib.msa new file mode 100644 index 0000000000..90f47a71ca --- /dev/null +++ b/MdePkg/Library/BasePrintLib/BasePrintLib.msa @@ -0,0 +1,46 @@ + + + + + BasePrintLib + BASE + LIBRARY + a86fbfca-0183-4eeb-aa8a-762e3b7da1f3 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + PrintLib + BaseLib + + + PrintLib.c + PrintLibInternal.c + PrintLibInternal.h + + + MdePkg + + diff --git a/MdePkg/Library/BasePrintLib/PrintLib.c b/MdePkg/Library/BasePrintLib/PrintLib.c new file mode 100644 index 0000000000..9b8285f714 --- /dev/null +++ b/MdePkg/Library/BasePrintLib/PrintLib.c @@ -0,0 +1,639 @@ +/** @file + Print Library. + + Copyright (c) 2006, 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. + + Module Name: PrintLib.c + +**/ + +#include "PrintLibInternal.h" + +typedef struct { + RETURN_STATUS Status; + CHAR8 *String; +} STATUS_LOOKUP_TABLE_ENTRY; + +static CONST STATUS_LOOKUP_TABLE_ENTRY StatusString[] = { + { RETURN_SUCCESS, "Success" }, + { RETURN_LOAD_ERROR, "Load Error" }, + { RETURN_INVALID_PARAMETER, "Invalid Parameter" }, + { RETURN_UNSUPPORTED, "Unsupported" }, + { RETURN_BAD_BUFFER_SIZE, "Bad Buffer Size" }, + { RETURN_BUFFER_TOO_SMALL, "Buffer Too Small" }, + { RETURN_NOT_READY, "Not Ready" }, + { RETURN_DEVICE_ERROR, "Device Error" }, + { RETURN_WRITE_PROTECTED, "Write Protected" }, + { RETURN_OUT_OF_RESOURCES, "Out of Resources" }, + { RETURN_VOLUME_CORRUPTED, "Volume Corrupt" }, + { RETURN_VOLUME_FULL, "Volume Full" }, + { RETURN_NO_MEDIA, "No Media" }, + { RETURN_MEDIA_CHANGED, "Media changed" }, + { RETURN_NOT_FOUND, "Not Found" }, + { RETURN_ACCESS_DENIED, "Access Denied" }, + { RETURN_NO_RESPONSE, "No Response" }, + { RETURN_NO_MAPPING, "No mapping" }, + { RETURN_TIMEOUT, "Time out" }, + { RETURN_NOT_STARTED, "Not started" }, + { RETURN_ALREADY_STARTED, "Already started" }, + { RETURN_ABORTED, "Aborted" }, + { RETURN_ICMP_ERROR, "ICMP Error" }, + { RETURN_TFTP_ERROR, "TFTP Error" }, + { RETURN_PROTOCOL_ERROR, "Protocol Error" }, + { RETURN_WARN_UNKNOWN_GLYPH, "Warning Unknown Glyph" }, + { RETURN_WARN_DELETE_FAILURE, "Warning Delete Failure" }, + { RETURN_WARN_WRITE_FAILURE, "Warning Write Failure" }, + { RETURN_WARN_BUFFER_TOO_SMALL, "Warning Buffer Too Small" }, + { 0, NULL } +}; + + +/** + VSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this rountine allows the nesting of Vararg routines. Thus + this is the main print working routine + + @param StartOfBuffer Unicode buffer to print the results of the parsing of Format into. + + @param BufferSize Maximum number of characters to put into buffer. Zero means + no limit. + + @param Flags Intial flags value. Can only have FORMAT_UNICODE and OUTPUT_UNICODE set + + @param FormatString Unicode format string see file header for more details. + + @param Marker Vararg list consumed by processing Format. + + @return Number of characters printed. + +**/ +UINTN +BasePrintLibVSPrint ( + OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN CONST CHAR8 *Format, + IN VA_LIST Marker + ) +{ + CHAR8 *OriginalBuffer; + CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS]; + UINTN BytesPerOutputCharacter; + UINTN BytesPerFormatCharacter; + UINTN FormatMask; + UINTN FormatCharacter; + UINTN Width; + UINTN Precision; + INT64 Value; + CHAR8 *ArgumentString; + UINTN Character; + GUID *TmpGuid; + TIME *TmpTime; + UINTN Count; + UINTN ArgumentMask; + INTN BytesPerArgumentCharacter; + UINTN ArgumentCharacter; + BOOLEAN Done; + UINTN Index; + CHAR8 Prefix; + BOOLEAN ZeroPad; + BOOLEAN Comma; + UINTN Digits; + UINTN Radix; + RETURN_STATUS Status; + + OriginalBuffer = Buffer; + + if ((Flags & OUTPUT_UNICODE) != 0) { + BytesPerOutputCharacter = 2; + } else { + BytesPerOutputCharacter = 1; + } + if ((Flags & FORMAT_UNICODE) != 0) { + BytesPerFormatCharacter = 2; + FormatMask = 0xffff; + } else { + BytesPerFormatCharacter = 1; + FormatMask = 0xff; + } + + // + // Reserve space for the Null terminator. + // If BufferSize is 0, this will set BufferSize to the max unsigned value + // + BufferSize--; + + // + // Get the first character from the format string + // + FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask; + + // + // Loop until the end of the format string is reached or the output buffer is full + // + while (FormatCharacter != 0 && BufferSize > 0) { + // + // Clear all the flag bits except those that may have been passed in + // + Flags &= (OUTPUT_UNICODE | FORMAT_UNICODE); + + // + // Set the default width to zero, and the default precision to 1 + // + Width = 0; + Precision = 1; + Prefix = 0; + Comma = FALSE; + ZeroPad = FALSE; + Count = 0; + Digits = 0; + + switch (FormatCharacter) { + case '%': + // + // Parse Flags and Width + // + for (Done = FALSE; !Done; ) { + Format += BytesPerFormatCharacter; + FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask; + switch (FormatCharacter) { + case '.': + Flags |= PRECISION; + break; + case '-': + Flags |= LEFT_JUSTIFY; + break; + case '+': + Flags |= PREFIX_SIGN; + break; + case ' ': + Flags |= PREFIX_BLANK; + break; + case ',': + Flags |= COMMA_TYPE; + break; + case 'L': + case 'l': + Flags |= LONG_TYPE; + break; + case '*': + if ((Flags & PRECISION) == 0) { + Flags |= PAD_TO_WIDTH; + Width = VA_ARG (Marker, UINTN); + } else { + Precision = VA_ARG (Marker, UINTN); + } + break; + case '0': + if ((Flags & PRECISION) == 0) { + Flags |= PREFIX_ZERO; + } + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + for (Count = 0; ((FormatCharacter >= '0') && (FormatCharacter <= '9')); ){ + Count = (Count * 10) + FormatCharacter - '0'; + Format += BytesPerFormatCharacter; + FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask; + } + Format -= BytesPerFormatCharacter; + if ((Flags & PRECISION) == 0) { + Flags |= PAD_TO_WIDTH; + Width = Count; + } else { + Precision = Count; + } + break; + default: + Done = TRUE; + break; + } + } + + // + // Limit the maximum field width to the remaining characters in the output buffer + // + if (Width > BufferSize) { + Width = BufferSize; + } + + // + // Handle each argument type + // + switch (FormatCharacter) { + case 'X': + Flags |= PREFIX_ZERO; + // + // break skiped on purpose + // + case 'x': + Flags |= RADIX_HEX; + // + // break skiped on purpose + // + case 'd': + if ((Flags & LONG_TYPE) == 0) { + Value = (VA_ARG (Marker, INTN)); + } else { + Value = VA_ARG (Marker, INT64); + } + if ((Flags & PREFIX_BLANK) != 0) { + Prefix = ' '; + } + if ((Flags & PREFIX_SIGN) != 0) { + Prefix = '+'; + } + if ((Flags & COMMA_TYPE) != 0) { + Comma = TRUE; + } + if ((Flags & RADIX_HEX) == 0) { + Radix = 10; + if (Comma) { + Flags &= (~PREFIX_ZERO); + Precision = 1; + } + if (Value < 0) { + Flags |= PREFIX_SIGN; + Prefix = '-'; + Value = -Value; + } + } else { + Radix = 16; + Comma = FALSE; + if ((Flags & LONG_TYPE) == 0 && Value < 0) { + Value = (UINTN)Value; + } + } + // + // Convert Value to a reversed string + // + Count = BasePrintLibValueToString (ValueBuffer, Value, Radix); + if (Value == 0 && Precision == 0) { + Count = 0; + } + ArgumentString = (CHAR8 *)ValueBuffer + Count; + Digits = 3 - (Count % 3); + if (Comma && Count != 0) { + Count += ((Count - 1) / 3); + } + if (Prefix != 0) { + Count++; + } + Flags |= ARGUMENT_REVERSED; + ZeroPad = TRUE; + if ((Flags & PREFIX_ZERO) != 0) { + if ((Flags & PAD_TO_WIDTH) != 0) { + if ((Flags & PRECISION) == 0) { + Precision = Width; + } + } + } + break; + + case 's': + case 'S': + Flags |= ARGUMENT_UNICODE; + // + // break skipped on purpose + // + case 'a': + ArgumentString = (CHAR8 *)VA_ARG (Marker, CHAR8 *); + if (ArgumentString == NULL) { + Flags &= (~ARGUMENT_UNICODE); + ArgumentString = ""; + } + break; + + case 'c': + Character = VA_ARG (Marker, UINTN) & 0xffff; + ArgumentString = (CHAR8 *)&Character; + Flags |= ARGUMENT_UNICODE; + break; + + case 'g': + TmpGuid = VA_ARG (Marker, GUID *); + if (TmpGuid == NULL) { + ArgumentString = ""; + } else { + BasePrintLibSPrint ( + ValueBuffer, + 0, + 0, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + TmpGuid->Data1, + TmpGuid->Data2, + TmpGuid->Data3, + TmpGuid->Data4[0], + TmpGuid->Data4[1], + TmpGuid->Data4[2], + TmpGuid->Data4[3], + TmpGuid->Data4[4], + TmpGuid->Data4[5], + TmpGuid->Data4[6], + TmpGuid->Data4[7] + ); + ArgumentString = ValueBuffer; + } + break; + + case 't': + TmpTime = VA_ARG (Marker, TIME *); + if (TmpTime == NULL) { + ArgumentString = ""; + } else { + BasePrintLibSPrint ( + ValueBuffer, + 0, + 0, + "%02d/%02d/%04d %02d:%02d", + TmpTime->Month, + TmpTime->Day, + TmpTime->Year, + TmpTime->Hour, + TmpTime->Minute + ); + ArgumentString = ValueBuffer; + } + break; + + case 'r': + Status = VA_ARG (Marker, RETURN_STATUS); + ArgumentString = ValueBuffer; + for (Index = 0; StatusString[Index].String != NULL; Index++) { + if (Status == StatusString[Index].Status) { + ArgumentString = StatusString[Index].String; + } + } + if (ArgumentString == ValueBuffer) { + BasePrintLibSPrint ((CHAR8 *) ValueBuffer, 0, 0, "%08X", Status); + } + break; + + case '%': + default: + // + // if the type is '%' or unknown, then print it to the screen + // + ArgumentString = (CHAR8 *)&FormatCharacter; + Flags |= ARGUMENT_UNICODE; + break; + } + break; + case '\n': + ArgumentString = "\r\n"; + break; + default: + ArgumentString = (CHAR8 *)&FormatCharacter; + Flags |= ARGUMENT_UNICODE; + break; + } + + // + // Retrieve the ArgumentString attriubutes + // + if ((Flags & ARGUMENT_UNICODE) != 0) { + ArgumentMask = 0xffff; + BytesPerArgumentCharacter = 2; + } else { + ArgumentMask = 0xff; + BytesPerArgumentCharacter = 1; + } + if ((Flags & ARGUMENT_REVERSED) != 0) { + BytesPerArgumentCharacter = -BytesPerArgumentCharacter; + } else { + // + // Compute the number of characters in ArgumentString and store it in Count + // ArgumentString is either null-terminated, or it contains Precision characters + // + for (Count = 0; Count < Precision || ((Flags & PRECISION) == 0); Count++) { + ArgumentCharacter = ((ArgumentString[Count * BytesPerArgumentCharacter] & 0xff) | ((ArgumentString[Count * BytesPerArgumentCharacter + 1]) << 8)) & ArgumentMask; + if (ArgumentCharacter == 0) { + break; + } + } + } + + // + // Limit the length of the string to append to the remaining characters in the output buffer + // + if (Count > BufferSize) { + Count = BufferSize; + } + if (Precision < Count) { + Precision = Count; + } + + // + // Pad before the string + // + if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH)) { + Buffer = BasePrintLibFillBuffer (Buffer, Width - Precision, ' ', BytesPerOutputCharacter); + } + + if (ZeroPad) { + if (Prefix != 0) { + Buffer = BasePrintLibFillBuffer (Buffer, 1, Prefix, BytesPerOutputCharacter); + } + Buffer = BasePrintLibFillBuffer (Buffer, Precision - Count, '0', BytesPerOutputCharacter); + } else { + Buffer = BasePrintLibFillBuffer (Buffer, Precision - Count, ' ', BytesPerOutputCharacter); + if (Prefix != 0) { + Buffer = BasePrintLibFillBuffer (Buffer, 1, Prefix, BytesPerOutputCharacter); + } + } + + // + // Output the Prefix character if it is present + // + Index = 0; + if (Prefix) { + Index++; + } + + // + // Copy the string into the output buffer performing the required type conversions + // + while (Index < Count) { + ArgumentCharacter = ((*ArgumentString & 0xff) | (*(ArgumentString + 1) << 8)) & ArgumentMask; + + Buffer = BasePrintLibFillBuffer (Buffer, 1, ArgumentCharacter, BytesPerOutputCharacter); + ArgumentString += BytesPerArgumentCharacter; + Index++; + if (Comma) { + Digits++; + if (Digits == 3) { + Digits = 0; + Index++; + if (Index < Count) { + Buffer = BasePrintLibFillBuffer (Buffer, 1, ',', BytesPerOutputCharacter); + } + } + } + } + + // + // Pad after the string + // + if ((Flags & (PAD_TO_WIDTH | LEFT_JUSTIFY)) == (PAD_TO_WIDTH | LEFT_JUSTIFY)) { + Buffer = BasePrintLibFillBuffer (Buffer, Width - Precision, ' ', BytesPerOutputCharacter); + } + + // + // Reduce the number of characters + // + BufferSize -= Count; + + // + // Get the next character from the format string + // + Format += BytesPerFormatCharacter; + + // + // Get the next character from the format string + // + FormatCharacter = (*Format | (*(Format + 1) << 8)) & FormatMask; + } + + // + // Null terminate the Unicode or ASCII string + // + Buffer = BasePrintLibFillBuffer (Buffer, 1, 0, BytesPerOutputCharacter); + + return ((Buffer - OriginalBuffer) / BytesPerOutputCharacter); +} + +UINTN +BasePrintLibSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN CONST CHAR8 *FormatString, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, FormatString); + return BasePrintLibVSPrint (StartOfBuffer, BufferSize, Flags, FormatString, Marker); +} + +UINTN +EFIAPI +UnicodeVSPrint ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + IN VA_LIST Marker + ) +{ + return BasePrintLibVSPrint ((CHAR8 *)StartOfBuffer, BufferSize >> 1, FORMAT_UNICODE | OUTPUT_UNICODE, (CHAR8 *)FormatString, Marker); +} + +UINTN +EFIAPI +UnicodeSPrint ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, FormatString); + return UnicodeVSPrint (StartOfBuffer, BufferSize, FormatString, Marker); +} + +UINTN +EFIAPI +UnicodeVSPrintAsciiFormat ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + IN VA_LIST Marker + ) +{ + return BasePrintLibVSPrint ((CHAR8 *)StartOfBuffer, BufferSize >> 1, OUTPUT_UNICODE,FormatString, Marker); +} + +UINTN +EFIAPI +UnicodeSPrintAsciiFormat ( + OUT CHAR16 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, FormatString); + return UnicodeVSPrintAsciiFormat (StartOfBuffer, BufferSize >> 1, FormatString, Marker); +} + +UINTN +EFIAPI +AsciiVSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + IN VA_LIST Marker + ) +{ + return BasePrintLibVSPrint (StartOfBuffer, BufferSize, 0, FormatString, Marker); +} + +UINTN +EFIAPI +AsciiSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, FormatString); + return AsciiVSPrint (StartOfBuffer, BufferSize, FormatString, Marker); +} + +UINTN +EFIAPI +AsciiVSPrintUnicodeFormat ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + IN VA_LIST Marker + ) +{ + return BasePrintLibVSPrint (StartOfBuffer, BufferSize, FORMAT_UNICODE, (CHAR8 *)FormatString, Marker); +} + +UINTN +EFIAPI +AsciiSPrintUnicodeFormat ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR16 *FormatString, + ... + ) +{ + VA_LIST Marker; + + VA_START (Marker, FormatString); + return AsciiVSPrintUnicodeFormat (StartOfBuffer, BufferSize, FormatString, Marker); +} diff --git a/MdePkg/Library/BasePrintLib/PrintLibInternal.c b/MdePkg/Library/BasePrintLib/PrintLibInternal.c new file mode 100644 index 0000000000..24d8b56598 --- /dev/null +++ b/MdePkg/Library/BasePrintLib/PrintLibInternal.c @@ -0,0 +1,153 @@ +/** @file + Print Library worker functions. + + Copyright (c) 2006, 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. + + Module Name: PrintLibInternal.c + +**/ + +#include "PrintLibInternal.h" + +static CONST CHAR8 mHexStr[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + +CHAR8 * +BasePrintLibFillBuffer ( + CHAR8 *Buffer, + INTN Length, + UINTN Character, + INTN Increment + ) +{ + INTN Index; + + for (Index = 0; Index < Length; Index++) { + *Buffer = (CHAR8) Character; + *(Buffer + 1) = (CHAR8) (Character >> 8); + Buffer += Increment; + } + return Buffer; +} + +/** + Print worker function that prints a Value as a decimal number in Buffer. + + @param Buffer Location to place the Unicode or ASCII string of Value. + + @param Value Value to convert to a Decimal or Hexidecimal string in Buffer. + + @param Flags Flags to use in printing string, see file header for details. + + @param Precision Minimum number of digits to return in the ASCII string + + @return Number of characters printed. + +**/ +UINTN +EFIAPI +BasePrintLibValueToString ( + IN OUT CHAR8 *Buffer, + IN INT64 Value, + IN UINTN Radix + ) +{ + UINTN Digits; + UINT32 Remainder; + + // + // Loop to convert one digit at a time in reverse order + // + *(Buffer++) = 0; + Digits = 0; + do { + Value = (INT64)DivU64x32Remainder ((UINT64)Value, (UINT32)Radix, &Remainder); + *(Buffer++) = mHexStr[Remainder]; + Digits++; + } while (Value != 0); + return Digits; +} + +UINTN +BasePrintLibConvertValueToString ( + IN OUT CHAR8 *Buffer, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width, + IN UINTN Increment + ) +{ + CHAR8 *OriginalBuffer; + CHAR8 ValueBuffer[MAXIMUM_VALUE_CHARACTERS]; + UINTN Count; + UINTN Digits; + UINTN Index; + + OriginalBuffer = Buffer; + + if (Width == 0 || (Flags & COMMA_TYPE) != 0) { + Flags &= (~PREFIX_ZERO); + } + + if (Width == 0 || Width > (MAXIMUM_VALUE_CHARACTERS - 1)) { + Width = MAXIMUM_VALUE_CHARACTERS - 1; + } + + if (Value < 0) { + Value = -Value; + Buffer = BasePrintLibFillBuffer (Buffer, 1, '-', Increment); + } + + Count = BasePrintLibValueToString (ValueBuffer, Value, 10); + + if ((Flags & PREFIX_ZERO) != 0) { + Buffer = BasePrintLibFillBuffer (Buffer, Width - Count, '0', Increment); + } + + Digits = 3 - (Count % 3); + for (Index = 0; Index < Count; Index++) { + Buffer = BasePrintLibFillBuffer (Buffer, 1, ValueBuffer[Count - Index], Increment); + if ((Flags & COMMA_TYPE) != 0) { + Digits++; + if (Digits == 3) { + Digits = 0; + if ((Index + 1) < Count) { + Buffer = BasePrintLibFillBuffer (Buffer, 1, ',', Increment); + } + } + } + } + + Buffer = BasePrintLibFillBuffer (Buffer, 1, 0, Increment); + + return ((Buffer - OriginalBuffer) / Increment); +} + + +UINTN +UnicodeValueToString ( + IN OUT CHAR16 *Buffer, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width + ) +{ + return BasePrintLibConvertValueToString ((CHAR8 *)Buffer, Flags, Value, Width, 2); +} + +UINTN +AsciiValueToString ( + IN OUT CHAR8 *Buffer, + IN UINTN Flags, + IN INT64 Value, + IN UINTN Width + ) +{ + return BasePrintLibConvertValueToString ((CHAR8 *)Buffer, Flags, Value, Width, 1); +} diff --git a/MdePkg/Library/BasePrintLib/PrintLibInternal.h b/MdePkg/Library/BasePrintLib/PrintLibInternal.h new file mode 100644 index 0000000000..de08f0edfc --- /dev/null +++ b/MdePkg/Library/BasePrintLib/PrintLibInternal.h @@ -0,0 +1,87 @@ +/** @file + Print Library. + + Copyright (c) 2006, 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. + + Module Name: PrintLibInternal.h + +**/ + + + +// +// Print primitives +// +//#define LEFT_JUSTIFY 0x01 +#define PREFIX_SIGN 0x02 +#define PREFIX_BLANK 0x04 +//#define COMMA_TYPE 0x08 +#define LONG_TYPE 0x10 +//#define PREFIX_ZERO 0x20 +#define OUTPUT_UNICODE 0x40 +#define RADIX_HEX 0x80 +#define FORMAT_UNICODE 0x100 +#define PAD_TO_WIDTH 0x200 +#define ARGUMENT_UNICODE 0x400 +#define PRECISION 0x800 +#define ARGUMENT_REVERSED 0x1000 + +/// +/// Define the maximum number of characters that are required to encode +/// a decimal, hexidecimal, GUID, or TIME value with a Nll terminator. +/// Maximum Length Decimal String = 28 "-9,223,372,036,854,775,808" +/// Maximum Length Hexidecimal String = 17 "FFFFFFFFFFFFFFFF" +/// Maximum Length GUID = 37 "00000000-0000-0000-0000-000000000000" +/// Maximum Length TIME = 17 "12/12/2006 12:12" +/// +#define MAXIMUM_VALUE_CHARACTERS 38 + +// +// +// +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + UINT8 Pad1; + UINT32 Nanosecond; + INT16 TimeZone; + UINT8 Daylight; + UINT8 Pad2; +} TIME; + +UINTN +BasePrintLibSPrint ( + OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN UINTN Flags, + IN CONST CHAR8 *FormatString, + ... + ); + +CHAR8 * +BasePrintLibFillBuffer ( + CHAR8 *Buffer, + INTN Length, + UINTN Character, + INTN Increment + ); + +UINTN +EFIAPI +BasePrintLibValueToString ( + IN OUT CHAR8 *Buffer, + IN INT64 Value, + IN UINTN Radix + ); + diff --git a/MdePkg/Library/BasePrintLib/build.xml b/MdePkg/Library/BasePrintLib/build.xml new file mode 100644 index 0000000000..66f9c88641 --- /dev/null +++ b/MdePkg/Library/BasePrintLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.mbd b/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.mbd new file mode 100644 index 0000000000..abc965c519 --- /dev/null +++ b/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.mbd @@ -0,0 +1,30 @@ + + + + + BaseReportStatusCodeLibNull + 55c61087-7367-4546-bc32-4937c5e6aff3 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.msa b/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.msa new file mode 100644 index 0000000000..dae4508335 --- /dev/null +++ b/MdePkg/Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.msa @@ -0,0 +1,61 @@ + + + + + BaseReportStatusCodeLibNull + DXE_DRIVER + LIBRARY + 55c61087-7367-4546-bc32-4937c5e6aff3 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + ReportStatusCodeLib + BaseLib + BaseMemoryLib + DebugLib + PcdLib + IoLib + + + ReportStatusCodeLib.c + PostCode.c + + + MdePkg + + + + StatusCodeDataTypeDebug + + + + + PcdReportStatusCodePropertyMask + 0x00000007 + UINT8 + + + diff --git a/MdePkg/Library/BaseReportStatusCodeLibNull/PostCode.c b/MdePkg/Library/BaseReportStatusCodeLibNull/PostCode.c new file mode 100644 index 0000000000..3d0ce7cb8f --- /dev/null +++ b/MdePkg/Library/BaseReportStatusCodeLibNull/PostCode.c @@ -0,0 +1,125 @@ +/** @file + Report Status Code Library Post Code functions for DXE Phase. + + Copyright (c) 2006, 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. + +**/ + + +/** + Sends an 32-bit value to a POST card. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + Some implementations of this library function may perform I/O operations + directly to a POST card device. Other implementations may send Value to + ReportStatusCode(), and the status code reporting mechanism will eventually + display the 32-bit value on the status reporting device. + + PostCode() must actively prevent recursion. If PostCode() is called while + processing another any other Report Status Code Library function, then + PostCode() must return Value immediately. + + @param Value The 32-bit value to write to the POST card. + + @return Value + +**/ +UINT32 +EFIAPI +PostCode ( + IN UINT32 Value + ) +{ + DEBUG((EFI_D_INFO, "POST %08x\n", Value)); + IoWrite8 (0x80, (UINT8)(Value)); + return Value; +} + + +/** + Sends an 32-bit value to a POST and associated ASCII string. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + If Description is not NULL, then the ASCII string specified by Description is + also passed to the handler that displays the POST card value. Some + implementations of this library function may perform I/O operations directly + to a POST card device. Other implementations may send Value to ReportStatusCode(), + and the status code reporting mechanism will eventually display the 32-bit + value on the status reporting device. + + PostCodeWithDescription()must actively prevent recursion. If + PostCodeWithDescription() is called while processing another any other Report + Status Code Library function, then PostCodeWithDescription() must return Value + immediately. + + @param Value The 32-bit value to write to the POST card. + @param Description Pointer to an ASCII string that is a description of the + POST code value. This is an optional parameter that may + be NULL. + + @return Value + +**/ +UINT32 +EFIAPI +PostCodeWithDescription ( + IN UINT32 Value, + IN CONST CHAR8 *Description OPTIONAL + ) +{ + DEBUG((EFI_D_INFO, "POST %08x - %s\n", Value, Description)); + IoWrite8 (0x80, (UINT8)(Value)); + return Value; +} + + +/** + Returns TRUE if POST Codes are enabled. + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportPostCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if POST code descriptions are enabled. + + This function returns TRUE if the + REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED bit of + PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED + bit of PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED + bit of PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportPostCodeDescriptionEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED) != 0); +} diff --git a/MdePkg/Library/BaseReportStatusCodeLibNull/ReportStatusCodeLib.c b/MdePkg/Library/BaseReportStatusCodeLibNull/ReportStatusCodeLib.c new file mode 100644 index 0000000000..752dc72c79 --- /dev/null +++ b/MdePkg/Library/BaseReportStatusCodeLibNull/ReportStatusCodeLib.c @@ -0,0 +1,439 @@ +/** @file + Report Status Code Library template for Base modules. + + Copyright (c) 2006, 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. + +**/ + +/** + Converts a status code to an 8-bit POST code value. + + Converts the status code specified by CodeType and Value to an 8-bit POST code + and returns the 8-bit POST code in PostCode. If CodeType is an + EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode + are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits + 24..26 of Value., and TRUE is returned. Otherwise, FALSE is returned. + + If PostCode is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param PostCode A pointer to the 8-bit POST code value to return. + + @retval TRUE The status code specified by CodeType and Value was converted + to an 8-bit POST code and returned in PostCode. + @retval FALSE The status code specified by CodeType and Value could not be + converted to an 8-bit POST code value. + +**/ +BOOLEAN +EFIAPI +CodeTypeToPostCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + OUT UINT8 *PostCode + ) +{ + // + // If PostCode is NULL, then ASSERT() + // + ASSERT (PostCode != NULL); + + // + // Convert Value to an 8 bit post code + // + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || + ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ) { + *PostCode = (UINT8) (((Value & EFI_STATUS_CODE_CLASS_MASK) >> 24) << 5); + *PostCode |= (UINT8) (((Value & EFI_STATUS_CODE_SUBCLASS_MASK) >> 16) & 0x1f); + return TRUE; + } + return FALSE; +} + + +/** + Extracts ASSERT() information from a status code structure. + + Converts the status code specified by CodeType, Value, and Data to the ASSERT() + arguments specified by Filename, Description, and LineNumber. If CodeType is + an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and + Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract + Filename, Description, and LineNumber from the optional data area of the + status code buffer specified by Data. The optional data area of Data contains + a Null-terminated ASCII string for the FileName, followed by a Null-terminated + ASCII string for the Description, followed by a 32-bit LineNumber. If the + ASSERT() information could be extracted from Data, then return TRUE. + Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If Filename is NULL, then ASSERT(). + If Description is NULL, then ASSERT(). + If LineNumber is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param Data Pointer to status code data buffer. + @param Filename Pointer to the source file name that generated the ASSERT(). + @param Description Pointer to the description of the ASSERT(). + @param LineNumber Pointer to source line number that generated the ASSERT(). + + @retval TRUE The status code specified by CodeType, Value, and Data was + converted ASSERT() arguments specified by Filename, Description, + and LineNumber. + @retval FALSE The status code specified by CodeType, Value, and Data could + not be converted to ASSERT() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractAssertInfo ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_STATUS_CODE_DATA *Data, + OUT CHAR8 **Filename, + OUT CHAR8 **Description, + OUT UINT32 *LineNumber + ) +{ + EFI_DEBUG_ASSERT_DATA *AssertData; + + ASSERT (Data != NULL); + ASSERT (Filename != NULL); + ASSERT (Description != NULL); + ASSERT (LineNumber != NULL); + + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) && + ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) && + ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) { + AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1); + *Filename = (CHAR8 *)(AssertData + 1); + *Description = *Filename + AsciiStrLen (*Filename) + 1; + *LineNumber = AssertData->LineNumber; + return TRUE; + } + return FALSE; +} + + +/** + Extracts DEBUG() information from a status code structure. + + Converts the status code specified by Data to the DEBUG() arguments specified + by ErrorLevel, Marker, and Format. If type GUID in Data is + EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and + Format from the optional data area of the status code buffer specified by Data. + The optional data area of Data contains a 32-bit ErrorLevel followed by Marker + which is 12 UINTN parameters, followed by a Null-terminated ASCII string for + the Format. If the DEBUG() information could be extracted from Data, then + return TRUE. Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If ErrorLevel is NULL, then ASSERT(). + If Marker is NULL, then ASSERT(). + If Format is NULL, then ASSERT(). + + @param Data Pointer to status code data buffer. + @param ErrorLevel Pointer to error level mask for a debug message. + @param Marker Pointer to the variable argument list associated with Format. + @param Format Pointer to a Null-terminated ASCII format string of a + debug message. + + @retval TRUE The status code specified by Data was converted DEBUG() arguments + specified by ErrorLevel, Marker, and Format. + @retval FALSE The status code specified by Data could not be converted to + DEBUG() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractDebugInfo ( + IN EFI_STATUS_CODE_DATA *Data, + OUT UINT32 *ErrorLevel, + OUT VA_LIST *Marker, + OUT CHAR8 **Format + ) +{ + EFI_DEBUG_INFO *DebugInfo; + + ASSERT (Data != NULL); + ASSERT (ErrorLevel != NULL); + ASSERT (Marker != NULL); + ASSERT (Format != NULL); + + // + // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE + // + if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) { + return FALSE; + } + + // + // Retrieve the debug information from the status code record + // + DebugInfo = (EFI_DEBUG_INFO *)(Data + 1); + + *ErrorLevel = DebugInfo->ErrorLevel; + + // + // The first 12 * UINTN bytes of the string are really an + // argument stack to support varargs on the Format string. + // + *Marker = (VA_LIST) (DebugInfo + 1); + *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12); + + return TRUE; +} + + +/** + Reports a status code. + + Reports the status code specified by the parameters Type and Value. Status + code also require an instance, caller ID, and extended data. This function + passed in a zero instance, NULL extended data, and a caller ID of + gEfiCallerIdGuid, which is the GUID for the module. + + ReportStatusCode()must actively prevent recusrsion. If ReportStatusCode() + is called while processing another any other Report Status Code Library function, + then ReportStatusCode() must return immediately. + + @param Type Status code type. + @param Value Status code value. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_DEVICE_ERROR There status code could not be reported due to a + device error. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value + ) +{ + return EFI_UNSUPPORTED; +} + + +/** + Reports a status code with a Device Path Protocol as the extended data. + + Allocates and fills in the extended data section of a status code with the + Device Path Protocol specified by DevicePath. This function is responsible + for allocating a buffer large enough for the standard header and the device + path. The standard header is filled in with a GUID of + gEfiStatusCodeSpecificDataGuid. The status code is reported with a zero + instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithDevicePath()must actively prevent recursion. If + ReportStatusCodeWithDevicePath() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithDevicePath() + must return EFI_DEVICE_ERROR immediately. + + If DevicePath is NULL, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param DevicePath Pointer to the Device Path Protocol to be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by DevicePath. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithDevicePath ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ASSERT (DevicePath != NULL); + return EFI_UNSUPPORTED; +} + + +/** + Reports a status code with an extended data buffer. + + Allocates and fills in the extended data section of a status code with the + extended data specified by ExtendedData and ExtendedDataSize. ExtendedData + is assumed to be one of the data structures specified in Related Definitions. + These data structure do not have the standard header, so this function is + responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled + in with a GUID of gEfiStatusCodeSpecificDataGuid. The status code is reported + with a zero instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithExtendedData()must actively prevent recursion. If + ReportStatusCodeWithExtendedData() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithExtendedData() + must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL, then ASSERT(). + If ExtendedDataSize is 0, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param ExtendedData Pointer to the extended data buffer to be reported. + @param ExtendedDataSize The size, in bytes, of the extended data buffer to + be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by ExtendedData and ExtendedDataSize. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithExtendedData ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN VOID *ExtendedData, + IN UINTN ExtendedDataSize + ) +{ + ASSERT (ExtendedData != NULL); + ASSERT (ExtendedDataSize != 0); + return EFI_UNSUPPORTED; +} + + +/** + Reports a status code with full parameters. + + The function reports a status code. If ExtendedData is NULL and ExtendedDataSize + is 0, then an extended data buffer is not reported. If ExtendedData is not + NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. + ExtendedData is assumed not have the standard status code header, so this function + is responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled in + with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a + GUID of gEfiStatusCodeSpecificDatauid is used. The status code is reported with + an instance specified by Instance and a caller ID specified by CallerId. If + CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. + + ReportStatusCodeEx()must actively prevent recursion. If ReportStatusCodeEx() + is called while processing another any other Report Status Code Library function, + then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). + If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. If this parameter is NULL, then a caller + ID of gEfiCallerIdGuid is used. + @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. + If this parameter is NULL, then a the status code + standard header is filled in with + gEfiStatusCodeSpecificDataGuid. + @param ExtendedData Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + @param ExtendedDataSize The size, in bytes, of the extended data buffer. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate + the extended data section if it was specified. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeEx ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_GUID *ExtendedDataGuid OPTIONAL, + IN VOID *ExtendedData OPTIONAL, + IN UINTN ExtendedDataSize + ) +{ + ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0))); + ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0))); + return EFI_UNSUPPORTED; +} + + +/** + Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportProgressCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if status codes of type EFI_ERROR_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportErrorCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportDebugCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} diff --git a/MdePkg/Library/BaseReportStatusCodeLibNull/build.xml b/MdePkg/Library/BaseReportStatusCodeLibNull/build.xml new file mode 100644 index 0000000000..1ef3f9766f --- /dev/null +++ b/MdePkg/Library/BaseReportStatusCodeLibNull/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseSmbusLib/BaseSmbusLib.mbd b/MdePkg/Library/BaseSmbusLib/BaseSmbusLib.mbd new file mode 100644 index 0000000000..e548f14355 --- /dev/null +++ b/MdePkg/Library/BaseSmbusLib/BaseSmbusLib.mbd @@ -0,0 +1,33 @@ + + + + + BaseSmbusLib + 4c38a173-b317-4f29-a7bf-1cc7e10ccb10 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-17 09:00 + 2006-03-19 15:17 + + + + + diff --git a/MdePkg/Library/BaseSmbusLib/BaseSmbusLib.msa b/MdePkg/Library/BaseSmbusLib/BaseSmbusLib.msa new file mode 100644 index 0000000000..00c2aa4a03 --- /dev/null +++ b/MdePkg/Library/BaseSmbusLib/BaseSmbusLib.msa @@ -0,0 +1,47 @@ + + + + + BaseSmbusLib + BASE + LIBRARY + 4c38a173-b317-4f29-a7bf-1cc7e10ccb10 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-17 09:00 + 2006-03-19 15:17 + + + SmBusLib + BaseLib + IoLib + PciLib + DebugLib + + + SmbusLib.c + + + MdePkg + + diff --git a/MdePkg/Library/BaseSmbusLib/SmbusLib.c b/MdePkg/Library/BaseSmbusLib/SmbusLib.c new file mode 100644 index 0000000000..5aad978836 --- /dev/null +++ b/MdePkg/Library/BaseSmbusLib/SmbusLib.c @@ -0,0 +1,557 @@ +/** @file + Base SMBUS library implementation built upon I/O library. + + Copyright (c) 2006, 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. + + Module Name: SmbusLib.h + +**/ + +RETURN_STATUS +EFIAPI +BaseSmBusLibConstructor ( + IN VOID *Param1, + IN VOID *Param2 + ) +{ + return RETURN_SUCCESS; +} + +// +// BUGBUG: use PCD to retrieve BUS, DEV, FUNC & OFFSET for SMBUS host BAR +// +#define SMBUS_HOST_BUS 0 +#define SMBUS_HOST_DEV 31 +#define SMBUS_HOST_FUNC 3 +#define SMBUS_HOST_SMB_BASE 0x20 + +// +// Offsets of registers for SMBUS controller +// +#define R_HST_STS 0 +#define R_HST_CNT 2 +#define R_HST_CMD 3 +#define R_XMIT_SLVA 4 +#define R_HST_D0 5 +#define R_HST_D1 6 +#define R_HOST_BLOCK_DB 7 +#define R_PEC 8 +#define R_RCV_SLVA 9 +#define R_SLV_DATA 0x0a +#define R_AUX_STS 0x0c +#define R_AUX_CTL 0x0d +#define R_SMLINK_PIN_CTL 0x0e +#define R_SMBUS_PIN_CTL 0x0f +#define R_SLV_STS 0x10 +#define R_SLV_CMD 0x11 +#define R_NOTIFY_DADDR 0x14 +#define R_NOTIFY_DLOW 0x16 +#define R_NOTIFY_DHIGH 0x17 + +// +// Bits in HST_STS +// +#define B_HST_STS_DS 0x80 +#define B_HST_STS_INUSE 0x40 +#define B_HST_STS_SMBALERT 0x20 +#define B_HST_STS_FAILED 0x10 +#define B_HST_STS_BUS_ERR 0x08 +#define B_HST_STS_DEV_ERR 0x04 +#define B_HST_STS_INTR 0x02 +#define B_HST_STS_BUSY 0x01 +#define B_HST_STS_ERR ( B_HST_STS_BUS_ERR | \ + B_HST_STS_DEV_ERR | \ + B_HST_STS_FAILED ) +#define B_HST_STS_ALL ( B_HST_STS_DS | \ + B_HST_STS_INUSE | \ + B_HST_STS_SMBALERT | \ + B_HST_STS_ERR | \ + B_HST_STS_INTR ) + +// +// Bits in HST_CNT +// +#define B_HST_CNT_PEC 0x80 +#define B_HST_CNT_START 0x40 +#define B_HST_CNT_LAST_BYTE 0x20 +#define B_HST_CNT_SMB_CMD 0x1c +#define B_HST_CNT_KILL 0x02 +#define B_HST_CNT_INTREN 0x01 + +// +// SMBUS Protocols +// +#define B_SMB_CMD_QUICK 0 +#define B_SMB_CMD_BYTE 1 +#define B_SMB_CMD_BYTE_DATA 2 +#define B_SMB_CMD_WORD_DATA 3 +#define B_SMB_CMD_PROCESS_CALL 4 +#define B_SMB_CMD_BLOCK 5 +#define B_SMB_CMD_I2C 6 +#define B_SMB_CMD_BLOCK_PROCESS 7 + +// +// Bits in AUX_CTL +// +#define B_AUX_CTL_E32B 0x02 +#define B_AUX_CTL_AAC 0x01 + +// +// SMBUS Rd/Wr control +// +#define B_SMBUS_READ 1 +#define B_SMBUS_WRITE 0 + +static +UINT16 +EFIAPI +GetSmBusIOBaseAddress ( + VOID + ) +{ + UINT32 SmbusBar; + + SmbusBar = PciRead32 ( + PCI_LIB_ADDRESS ( + SMBUS_HOST_BUS, + SMBUS_HOST_DEV, + SMBUS_HOST_FUNC, + SMBUS_HOST_SMB_BASE + ) + ); + ASSERT ((SmbusBar & 0xffff001f) == 1); + return (UINT16)(SmbusBar & ~1); +} + +static +BOOLEAN +EFIAPI +SmBusAcquire ( + IN UINT16 SmBusBase + ) +{ + UINT8 HstSts; + + HstSts = IoRead8 (SmBusBase + R_HST_STS); + if (HstSts & B_HST_STS_INUSE) { + return FALSE; + } + + // + // BUGBUG: Dead loop may occur here + // + while (HstSts & B_HST_STS_BUSY) { + ASSERT (HstSts & B_HST_STS_INUSE); + HstSts = IoRead8 (SmBusBase + R_HST_STS); + } + return TRUE; +} + +static +VOID +EFIAPI +SmBusStart ( + IN UINT16 SmBusBase, + IN UINT8 SmBusProtocol, + IN UINT8 SlaveAddress + ) +{ + IoWrite8 (SmBusBase + R_XMIT_SLVA, SlaveAddress); + IoWrite8 ( + SmBusBase + R_HST_CNT, + IoBitFieldWrite8 (SmBusBase + R_HST_CNT, 2, 4, SmBusProtocol) | + B_HST_CNT_START + ); +} + +static +UINT8 +EFIAPI +SmBusWait ( + IN UINT16 SmBusBase + ) +{ + UINT8 HstSts; + + while (((HstSts = IoRead8 (SmBusBase + R_HST_STS)) & B_HST_STS_INTR) == 0); + return HstSts; +} + +static +VOID +EFIAPI +SmBusCleanup ( + IN UINT16 SmBusBase + ) +{ + IoWrite8 (SmBusBase + R_HST_STS, B_HST_STS_ALL); +} + +static +RETURN_STATUS +EFIAPI +SmBusQuick ( + IN UINT8 SmBusAddress + ) +{ + RETURN_STATUS Status; + UINT16 SmBusBase; + + SmBusBase = GetSmBusIOBaseAddress (); + if (!SmBusAcquire (SmBusBase)) { + return RETURN_TIMEOUT; + } + + SmBusStart (SmBusAddress, B_SMB_CMD_QUICK, SmBusAddress); + if (SmBusWait (SmBusAddress) & B_HST_STS_ERR) { + Status = RETURN_DEVICE_ERROR; + } else { + Status = RETURN_SUCCESS; + } + + SmBusCleanup (SmBusAddress); + return Status; +} + +VOID +EFIAPI +SmBusQuickRead ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status + ) +{ + RETURN_STATUS RetStatus; + + ASSERT ((SmBusAddress & ~0xfe) == 0); + RetStatus = SmBusQuick ((UINT8)SmBusAddress | B_SMBUS_READ); + if (Status) { + *Status = RetStatus; + } +} + +BOOLEAN +EFIAPI +SmBusQuickWrite ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status + ) +{ + RETURN_STATUS RetStatus; + + ASSERT ((SmBusAddress & ~0xfe) == 0); + RetStatus = SmBusQuick ((UINT8)SmBusAddress | B_SMBUS_WRITE); + if (Status) { + *Status = RetStatus; + } + return (BOOLEAN)!RETURN_ERROR (RetStatus); +} + +static +UINT16 +EFIAPI +SmBusByteWord ( + IN UINTN SmBusAddress, + IN UINT16 Value, + IN UINT8 SmBusProtocol, + OUT RETURN_STATUS *Status + ) +{ + RETURN_STATUS RetStatus; + UINT16 SmBusBase; + + if (Status == NULL) { + Status = &RetStatus; + } + + SmBusBase = GetSmBusIOBaseAddress (); + if (!SmBusAcquire (SmBusBase)) { + *Status = RETURN_TIMEOUT; + return Value; + } + + IoWrite8 (SmBusBase + R_HST_CMD, (UINT8)(SmBusAddress >> 8)); + IoWrite8 (SmBusBase + R_HST_D0, (UINT8)Value); + IoWrite8 (SmBusBase + R_HST_D1, (UINT8)(Value >> 8)); + if ((INTN)SmBusAddress < 0) { + IoOr8 (SmBusBase + R_HST_CNT, B_HST_CNT_PEC); + IoOr8 (SmBusBase + R_AUX_CTL, B_AUX_CTL_AAC); + } else { + IoAnd8 (SmBusBase + R_HST_CNT, (UINT8)~B_HST_CNT_PEC); + IoAnd8 (SmBusBase + R_AUX_CTL, (UINT8)~B_AUX_CTL_AAC); + } + + SmBusStart (SmBusBase, SmBusProtocol, (UINT8)SmBusAddress); + + if (SmBusWait (SmBusBase) & B_HST_STS_ERR) { + *Status = RETURN_DEVICE_ERROR; + } else { + *Status = RETURN_SUCCESS; + Value = IoRead8 (SmBusBase + R_HST_D0); + Value |= (UINT16)IoRead8 (SmBusBase + R_HST_D1) << 8; + } + + SmBusCleanup (SmBusBase); + return Value; +} + +UINT8 +EFIAPI +SmBusReceiveByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status + ) +{ + ASSERT ((SmBusAddress & ~(0xfe | MAX_BIT)) == 0); + return (UINT8)SmBusByteWord ( + SmBusAddress | B_SMBUS_READ, + 0, + B_SMB_CMD_BYTE, + Status + ); +} + +UINT8 +EFIAPI +SmBusSendByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status + ) +{ + ASSERT ((SmBusAddress & ~(0xfe | MAX_BIT)) == 0); + return (UINT8)SmBusByteWord ( + SmBusAddress | B_SMBUS_WRITE, + Value, + B_SMB_CMD_BYTE, + Status + ); +} + +UINT8 +EFIAPI +SmBusReadDataByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status + ) +{ + ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0); + return (UINT8)SmBusByteWord ( + SmBusAddress | B_SMBUS_READ, + 0, + B_SMB_CMD_BYTE_DATA, + Status + ); +} + +UINT8 +EFIAPI +SmBusWriteDataByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status + ) +{ + ASSERT (((UINT32)SmBusAddress & ~(0xfffe | MAX_BIT)) == 0); + return (UINT8)SmBusByteWord ( + SmBusAddress | B_SMBUS_WRITE, + Value, + B_SMB_CMD_BYTE_DATA, + Status + ); +} + +UINT16 +EFIAPI +SmBusReadDataWord ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status + ) +{ + ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0); + return SmBusByteWord ( + SmBusAddress | B_SMBUS_READ, + 0, + B_SMB_CMD_WORD_DATA, + Status + ); +} + +UINT16 +EFIAPI +SmBusWriteDataWord ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status + ) +{ + ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0); + return SmBusByteWord ( + SmBusAddress | B_SMBUS_WRITE, + Value, + B_SMB_CMD_WORD_DATA, + Status + ); +} + +UINT16 +EFIAPI +SmBusProcessCall ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status + ) +{ + ASSERT ((SmBusAddress & ~(0xfffe | MAX_BIT)) == 0); + return SmBusByteWord ( + SmBusAddress | B_SMBUS_WRITE, + Value, + B_SMB_CMD_PROCESS_CALL, + Status + ); +} + +static +UINTN +EFIAPI +SmBusBlock ( + IN UINTN SmBusAddress, + IN UINT8 SmBusProtocol, + IN VOID *InBuffer, + OUT VOID *OutBuffer, + OUT RETURN_STATUS *Status + ) +{ + RETURN_STATUS RetStatus; + UINT16 SmBusBase; + UINTN Index; + UINTN BytesCount; + + BytesCount = (UINT8)(SmBusAddress >> 16); + ASSERT (BytesCount <= 32); + + if (Status == NULL) { + Status = &RetStatus; + } + + SmBusBase = GetSmBusIOBaseAddress (); + if (!SmBusAcquire (SmBusBase)) { + *Status = RETURN_TIMEOUT; + return 0; + } + + IoWrite8 (SmBusBase + R_HST_CMD, (UINT8)(SmBusAddress >> 8)); + IoWrite8 (SmBusBase + R_HST_D0, (UINT8)BytesCount); + if ((INTN)SmBusAddress < 0) { + IoOr8 (SmBusBase + R_HST_CNT, B_HST_CNT_PEC); + IoOr8 (SmBusBase + R_AUX_CTL, B_AUX_CTL_AAC); + } else { + IoAnd8 (SmBusBase + R_HST_CNT, (UINT8)~B_HST_CNT_PEC); + IoAnd8 (SmBusBase + R_AUX_CTL, (UINT8)~B_AUX_CTL_AAC); + } + + // + // BUGBUG: E32B bit does not exist in ICH3 or earlier + // + IoOr8 (SmBusBase + R_AUX_CTL, B_AUX_CTL_E32B); + ASSERT (IoRead8 (SmBusBase + R_AUX_CTL) & B_AUX_CTL_E32B); + for (Index = 0; InBuffer != NULL && Index < BytesCount; Index++) { + IoWrite8 (SmBusBase + R_HOST_BLOCK_DB, ((UINT8*)InBuffer)[Index]); + } + + SmBusStart (SmBusBase, SmBusProtocol, (UINT8)SmBusAddress); + + if (SmBusWait (SmBusBase) & B_HST_STS_ERR) { + *Status = RETURN_DEVICE_ERROR; + } else { + *Status = RETURN_SUCCESS; + BytesCount = IoRead8 (SmBusBase + R_HST_D0); + for (Index = 0; OutBuffer != NULL && Index < BytesCount; Index++) { + ((UINT8*)OutBuffer)[Index] = IoRead8 (SmBusBase + R_HOST_BLOCK_DB); + } + } + + SmBusCleanup (SmBusBase); + return BytesCount; +} + +UINTN +EFIAPI +SmBusReadBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status + ) +{ + ASSERT ((SmBusAddress & ~(0xfffffe | MAX_BIT)) == 0); + return SmBusBlock ( + SmBusAddress | B_SMBUS_READ, + B_SMB_CMD_BLOCK, + NULL, + Buffer, + Status + ); +} + +UINTN +EFIAPI +SmBusWriteBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status + ) +{ + ASSERT ((SmBusAddress & ~(0xfffffe | MAX_BIT)) == 0); + return SmBusBlock ( + SmBusAddress | B_SMBUS_WRITE, + B_SMB_CMD_BLOCK, + Buffer, + NULL, + Status + ); +} + +UINTN +EFIAPI +SmBusBlockProcessCall ( + IN UINTN SmBusAddress, + IN VOID *OutBuffer, + OUT VOID *InBuffer, + OUT RETURN_STATUS *Status + ) +{ + ASSERT ((SmBusAddress & ~(0xfffffe | MAX_BIT)) == 0); + return SmBusBlock ( + SmBusAddress | B_SMBUS_WRITE, + B_SMB_CMD_BLOCK_PROCESS, + OutBuffer, + InBuffer, + Status + ); +} + +RETURN_STATUS +EFIAPI +SmBusArpAll ( + IN UINTN SmBusAddress + ); + +RETURN_STATUS +EFIAPI +SmBusArpDevice ( + IN UINTN SmBusAddress, + IN CONST GUID *Uuid + ); + +RETURN_STATUS +EFIAPI +SmBusGetUuid ( + IN UINTN SmBusAddress, + OUT GUID *Uuid + ); diff --git a/MdePkg/Library/BaseSmbusLib/build.xml b/MdePkg/Library/BaseSmbusLib/build.xml new file mode 100644 index 0000000000..95dfe52bd3 --- /dev/null +++ b/MdePkg/Library/BaseSmbusLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseTimerLibLocalApic/BaseTimerLibLocalApic.mbd b/MdePkg/Library/BaseTimerLibLocalApic/BaseTimerLibLocalApic.mbd new file mode 100644 index 0000000000..d597fe0b13 --- /dev/null +++ b/MdePkg/Library/BaseTimerLibLocalApic/BaseTimerLibLocalApic.mbd @@ -0,0 +1,30 @@ + + + + + BaseTimerLibLocalApic + b5a05743-9b71-489b-a0ed-a0eb3950d23b + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-13 16:57 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BaseTimerLibLocalApic/BaseTimerLibLocalApic.msa b/MdePkg/Library/BaseTimerLibLocalApic/BaseTimerLibLocalApic.msa new file mode 100644 index 0000000000..7d83751219 --- /dev/null +++ b/MdePkg/Library/BaseTimerLibLocalApic/BaseTimerLibLocalApic.msa @@ -0,0 +1,56 @@ + + + + + BaseTimerLibLocalApic + BASE + LIBRARY + b5a05743-9b71-489b-a0ed-a0eb3950d23b + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-13 16:57 + 2006-03-19 15:17 + + + TimerLib + BaseLib + IoLib + DebugLib + + + + x86TimerLib.c + + + x86TimerLib.c + + + Ipf\CallPalProc.s + Ipf\ReadItc.s + Ipf\IpfTimerLib.c + + + + MdePkg + + diff --git a/MdePkg/Library/BaseTimerLibLocalApic/Ipf/CallPalProc.s b/MdePkg/Library/BaseTimerLibLocalApic/Ipf/CallPalProc.s new file mode 100644 index 0000000000..18b0f5815a --- /dev/null +++ b/MdePkg/Library/BaseTimerLibLocalApic/Ipf/CallPalProc.s @@ -0,0 +1,38 @@ +/// @file +/// Contains an implementation of CallPalProcStatic on Itanium-based +/// architecture. +/// +/// Copyright (c) 2006, 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. +/// +/// Module Name: CallPalProc.s +/// +/// + +.auto +.text + +.proc CallPalProcStatic +.type CallPalProcStatic, @function +CallPalProcStatic:: + mov r9 = ar.k5 + mov r8 = ip + add r8 = (PalProcReturn - CallPalProcStatic), r8 + mov r28 = r32 + mov b7 = r9 + mov r29 = r33 + mov r30 = r34 + mov r31 = r35 + mov r32 = b0 + mov b0 = r8 + br.sptk b7 +PalProcReturn: + mov b0 = r32 + br.ret.sptk.many b0 +.endp CallPalProcStatic diff --git a/MdePkg/Library/BaseTimerLibLocalApic/Ipf/IpfTimerLib.c b/MdePkg/Library/BaseTimerLibLocalApic/Ipf/IpfTimerLib.c new file mode 100644 index 0000000000..652cc7e6e4 --- /dev/null +++ b/MdePkg/Library/BaseTimerLibLocalApic/Ipf/IpfTimerLib.c @@ -0,0 +1,155 @@ +/** @file + Timer Library functions built upon local APIC on IA32/x64. + + @bug Should use PCD to retrieve all the constants including index of + the IA32_APIC_BASE MSR, the offsets of InitialCount, CorrentCount + and DivideConfiguration. + + Copyright (c) 2006, 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. + + Module Name: IpfTimerLib.c + +**/ + +UINT64 +ReadItc ( + VOID + ); + +typedef struct { + UINT64 Status; + UINT64 r9; + UINT64 r10; + UINT64 r11; +} PAL_PROC_RETURN; + +PAL_PROC_RETURN +CallPalProcStatic ( + IN UINT64 Arg1, + IN UINT64 Arg2, + IN UINT64 Arg3, + IN UINT64 Arg4 + ); + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return The ticks delayed actually. + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + UINT64 Ticks; + UINT64 Delay; + + Ticks = GetPerformanceCounter (); + Delay = GetPerformanceCounterProperties (NULL, NULL) * MicroSeconds / 1000000; + while (Ticks + Delay < GetPerformanceCounter ()); + return (UINTN)Delay; +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return The ticks delayed actually. + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + UINT64 Ticks; + UINT64 Delay; + + Ticks = GetPerformanceCounter (); + Delay = GetPerformanceCounterProperties (NULL, NULL) * NanoSeconds / 1000000000; + while (Ticks + Delay < GetPerformanceCounter ()); + return (UINTN)Delay; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + Retrieves the current value of a 64-bit free running performance counter. The + counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return ReadItc (); +} + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + IN UINT64 *StartValue, + IN UINT64 *EndValue + ) +{ + PAL_PROC_RETURN PalRet; + UINT64 BaseFrequence; + + PalRet = CallPalProcStatic (13, 0, 0, 0); + ASSERT (PalRet.Status == 0); + BaseFrequence = PalRet.r9; + + PalRet = CallPalProcStatic (14, 0, 0, 0); + ASSERT (PalRet.Status == 0); + + *StartValue = 0; + *EndValue = (UINT64)(-1); + return BaseFrequence * (PalRet.r11 >> 32) / (UINT32)PalRet.r11; +} diff --git a/MdePkg/Library/BaseTimerLibLocalApic/Ipf/ReadItc.s b/MdePkg/Library/BaseTimerLibLocalApic/Ipf/ReadItc.s new file mode 100644 index 0000000000..383bb242ba --- /dev/null +++ b/MdePkg/Library/BaseTimerLibLocalApic/Ipf/ReadItc.s @@ -0,0 +1,25 @@ +/// @file +/// Contains an implementation of ReadItc on Itanium-based architecture. +/// +/// Copyright (c) 2006, 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. +/// +/// Module Name: ReadItc.s +/// +/// + +.auto +.text + +.proc ReadItc +.type ReadItc, @function +ReadItc:: + mov r8 = ar.itc + br.ret.sptk.many b0 +.endp ReadItc \ No newline at end of file diff --git a/MdePkg/Library/BaseTimerLibLocalApic/build.xml b/MdePkg/Library/BaseTimerLibLocalApic/build.xml new file mode 100644 index 0000000000..2d3be90bed --- /dev/null +++ b/MdePkg/Library/BaseTimerLibLocalApic/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/BaseTimerLibLocalApic/x86TimerLib.c b/MdePkg/Library/BaseTimerLibLocalApic/x86TimerLib.c new file mode 100644 index 0000000000..6f78e4e4fd --- /dev/null +++ b/MdePkg/Library/BaseTimerLibLocalApic/x86TimerLib.c @@ -0,0 +1,168 @@ +/** @file + Timer Library functions built upon local APIC on IA32/x64. + + @bug Should use PCD to retrieve all the constants including index of + the IA32_APIC_BASE MSR, the offsets of InitialCount, CorrentCount + and DivideConfiguration. + + Copyright (c) 2006, 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. + + Module Name: x86TimerLib.c + +**/ + +static +UINTN +EFIAPI +DelayWorker ( + IN UINT64 NDelay + ) +{ + UINTN Ticks; + + Ticks = (UINTN)GetPerformanceCounter (); + Ticks -= (UINTN)DivU64x32 ( + MultU64x64 ( + GetPerformanceCounterProperties (NULL, NULL), + NDelay + ), + 1000000000u + ); + while (Ticks >= GetPerformanceCounter ()); + return Ticks; +} + +/** + Stalls the CPU for at least the given number of microseconds. + + Stalls the CPU for the number of microseconds specified by MicroSeconds. + + @param MicroSeconds The minimum number of microseconds to delay. + + @return Return value depends on implementation. + +**/ +UINTN +EFIAPI +MicroSecondDelay ( + IN UINTN MicroSeconds + ) +{ + return DelayWorker (MicroSeconds * 1000ull); +} + +/** + Stalls the CPU for at least the given number of nanoseconds. + + Stalls the CPU for the number of nanoseconds specified by NanoSeconds. + + @param NanoSeconds The minimum number of nanoseconds to delay. + + @return Return value depends on implementation. + +**/ +UINTN +EFIAPI +NanoSecondDelay ( + IN UINTN NanoSeconds + ) +{ + return DelayWorker (NanoSeconds); +} + +static +UINTN +EFIAPI +GetApicBase ( + VOID + ) +{ + return (UINTN)AsmMsrBitFieldRead64 (27, 12, 35) << 12; +} + +/** + Retrieves the current value of a 64-bit free running performance counter. + + Retrieves the current value of a 64-bit free running performance counter. The + counter can either count up by 1 or count down by 1. If the physical + performance counter counts by a larger increment, then the counter values + must be translated. The properties of the counter can be retrieved from + GetPerformanceCounterProperties(). + + @return The current value of the free running performance counter. + +**/ +UINT64 +EFIAPI +GetPerformanceCounter ( + VOID + ) +{ + return MmioRead32 (GetApicBase () + 0x390); +} + +/** + Retrieves the 64-bit frequency in Hz and the range of performance counter + values. + + If StartValue is not NULL, then the value that the performance counter starts + with immediately after is it rolls over is returned in StartValue. If + EndValue is not NULL, then the value that the performance counter end with + immediately before it rolls over is returned in EndValue. The 64-bit + frequency of the performance counter in Hz is always returned. If StartValue + is less than EndValue, then the performance counter counts up. If StartValue + is greater than EndValue, then the performance counter counts down. For + example, a 64-bit free running counter that counts up would have a StartValue + of 0 and an EndValue of 0xFFFFFFFFFFFFFFFF. A 24-bit free running counter + that counts down would have a StartValue of 0xFFFFFF and an EndValue of 0. + + @param StartValue The value the performance counter starts with when it + rolls over. + @param EndValue The value that the performance counter ends with before + it rolls over. + + @return The frequency in Hz. + +**/ +UINT64 +EFIAPI +GetPerformanceCounterProperties ( + IN UINT64 *StartValue, + IN UINT64 *EndValue + ) +{ + static const UINT32 mFrequencies[] = { + 100000000, + 133000000, + 200000000, + 166000000 + }; + static const UINT8 mDivisor[] = { + 0x02, 0x04, 0x08, 0x10, + 0x02, 0x04, 0x08, 0x10, + 0x20, 0x40, 0x80, 0x01, + 0x20, 0x40, 0x80, 0x01 + }; + + UINTN ApicBase; + + ApicBase = GetApicBase (); + + if (StartValue != NULL) { + *StartValue = MmioRead32 (ApicBase + 0x380); + } + + if (EndValue != NULL) { + *EndValue = 0; + } + + return mFrequencies[AsmMsrBitFieldRead32 (44, 16, 18)] / + mDivisor[MmioBitFieldRead32 (ApicBase + 0x3e0, 0, 3)]; +} diff --git a/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c b/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c new file mode 100644 index 0000000000..ee832f0b2f --- /dev/null +++ b/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.c @@ -0,0 +1,712 @@ +/** @file + UEFI Decompress Library. + + Copyright (c) 2006, 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. + + Module Name: UefiDecompressLib.c + +**/ + +// +// Decompression algorithm begins here +// +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define BAD_TABLE - 1 + +// +// C: Char&Len Set; P: Position Set; T: exTra Set +// +#define NC (0xff + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define MAXPBIT 5 +#define TBIT 5 +#define MAXNP ((1U << MAXPBIT) - 1) +#define NT (CODE_BIT + 3) +#if NT > MAXNP +#define NPT NT +#else +#define NPT MAXNP +#endif + +typedef struct { + UINT8 *mSrcBase; ///< Starting address of compressed data + UINT8 *mDstBase; ///< Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; + + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; + + UINT16 mBadTableFlag; + + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; + + /// + /// The length of the field 'Position Set Code Length Array Size' in Block Header. + /// For EFI 1.1 de/compression algorithm, mPBit = 4 + /// For Tiano de/compression algorithm, mPBit = 5 + /// + UINT8 mPBit; +} SCRATCH_DATA; + +/** + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + + @param Sd The global scratch data + @param NumOfBits The number of bits to shift and read. + +**/ +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +{ + Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); + + while (NumOfBits > Sd->mBitCount) { + + Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); + + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; + Sd->mBitCount = 8; + + } else { + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + + } + } + + Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; +} + +/** + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + + @param Sd The global scratch data. + @param NumOfBits The number of bits to pop and read. + + @return The bits that are popped out. + +**/ +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +{ + UINT32 OutBits; + + OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + + FillBuf (Sd, NumOfBits); + + return OutBits; +} + +/** + Creates Huffman Code mapping table according to code length array. + + @param Sd The global scratch data + @param NumOfChar Number of symbols in the symbol set + @param BitLen Code length array + @param TableBits The width of the mapping table + @param Table The table + + @retval 0 OK. + @retval BAD_TABLE The table is corrupted. + +**/ +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ) +{ + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *Pointer; + UINT16 Index3; + volatile UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; + + for (Index = 1; Index <= 16; Index++) { + Count[Index] = 0; + } + + for (Index = 0; Index < NumOfChar; Index++) { + Count[BitLen[Index]]++; + } + + Start[1] = 0; + + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index))); + } + + if (Start[17] != 0) { + /*(1U << 16)*/ + return (UINT16) BAD_TABLE; + } + + JuBits = (UINT16) (16 - TableBits); + + for (Index = 1; Index <= TableBits; Index++) { + Start[Index] >>= JuBits; + Weight[Index] = (UINT16) (1U << (TableBits - Index)); + } + + while (Index <= 16) { + Weight[Index] = (UINT16) (1U << (16 - Index)); + Index++; + } + + Index = (UINT16) (Start[TableBits + 1] >> JuBits); + + if (Index != 0) { + Index3 = (UINT16) (1U << TableBits); + while (Index != Index3) { + Table[Index++] = 0; + } + } + + Avail = NumOfChar; + Mask = (UINT16) (1U << (15 - TableBits)); + + for (Char = 0; Char < NumOfChar; Char++) { + + Len = BitLen[Char]; + if (Len == 0) { + continue; + } + + NextCode = (UINT16) (Start[Len] + Weight[Len]); + + if (Len <= TableBits) { + + for (Index = Start[Len]; Index < NextCode; Index++) { + Table[Index] = Char; + } + + } else { + + Index3 = Start[Len]; + Pointer = &Table[Index3 >> JuBits]; + Index = (UINT16) (Len - TableBits); + + while (Index != 0) { + if (*Pointer == 0) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *Pointer = Avail++; + } + + if (Index3 & Mask) { + Pointer = &Sd->mRight[*Pointer]; + } else { + Pointer = &Sd->mLeft[*Pointer]; + } + + Index3 <<= 1; + Index--; + } + + *Pointer = Char; + + } + + Start[Len] = NextCode; + } + // + // Succeeds + // + return 0; +} + +/** + Decodes a position value. + + @param Sd the global scratch data + + @return The position value decoded. + +**/ +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ) +{ + UINT16 Val; + UINT32 Mask; + UINT32 Pos; + + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Sd->mBitBuf & Mask) { + Val = Sd->mRight[Val]; + } else { + Val = Sd->mLeft[Val]; + } + + Mask >>= 1; + } while (Val >= MAXNP); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[Val]); + + Pos = Val; + if (Val > 1) { + Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); + } + + return Pos; +} + +/** + Reads code lengths for the Extra Set or the Position Set. + + @param Sd The global scratch data. + @param nn Number of symbols. + @param nbit Number of bits needed to represent nn. + @param Special The special symbol that needs to be taken care of. + + @retval 0 OK. + @retval BAD_TABLE Table is corrupted. + +**/ +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ) +{ + UINT16 Number; + UINT16 CharC; + volatile UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, nbit); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, nbit); + + for (Index = 0; Index < 256; Index++) { + Sd->mPTTable[Index] = CharC; + } + + for (Index = 0; Index < nn; Index++) { + Sd->mPTLen[Index] = 0; + } + + return 0; + } + + Index = 0; + + while (Index < Number) { + + CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); + + if (CharC == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + CharC += 1; + } + } + + FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); + + Sd->mPTLen[Index++] = (UINT8) CharC; + + if (Index == Special) { + CharC = (UINT16) GetBits (Sd, 2); + while ((INT16) (--CharC) >= 0) { + Sd->mPTLen[Index++] = 0; + } + } + } + + while (Index < nn) { + Sd->mPTLen[Index++] = 0; + } + + return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); +} + +/** + Reads code lengths for Char&Len Set. + + @param Sd the global scratch data + +**/ +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ) +{ + UINT16 Number; + UINT16 CharC; + volatile UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, CBIT); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, CBIT); + + for (Index = 0; Index < NC; Index++) { + Sd->mCLen[Index] = 0; + } + + for (Index = 0; Index < 4096; Index++) { + Sd->mCTable[Index] = CharC; + } + + return ; + } + + Index = 0; + while (Index < Number) { + + CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (CharC >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Mask & Sd->mBitBuf) { + CharC = Sd->mRight[CharC]; + } else { + CharC = Sd->mLeft[CharC]; + } + + Mask >>= 1; + + } while (CharC >= NT); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[CharC]); + + if (CharC <= 2) { + + if (CharC == 0) { + CharC = 1; + } else if (CharC == 1) { + CharC = (UINT16) (GetBits (Sd, 4) + 3); + } else if (CharC == 2) { + CharC = (UINT16) (GetBits (Sd, CBIT) + 20); + } + + while ((INT16) (--CharC) >= 0) { + Sd->mCLen[Index++] = 0; + } + + } else { + + Sd->mCLen[Index++] = (UINT8) (CharC - 2); + + } + } + + while (Index < NC) { + Sd->mCLen[Index++] = 0; + } + + MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); + + return ; +} + +/** + Decode a character/length value. + + @param Sd The global scratch data. + + @return The value decoded. + +**/ +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ) +{ + UINT16 Index2; + UINT32 Mask; + + if (Sd->mBlockSize == 0) { + // + // Starting a new block + // + Sd->mBlockSize = (UINT16) GetBits (Sd, 16); + Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } + + ReadCLen (Sd); + + Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } + + Sd->mBlockSize--; + Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + + if (Index2 >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); + + do { + if (Sd->mBitBuf & Mask) { + Index2 = Sd->mRight[Index2]; + } else { + Index2 = Sd->mLeft[Index2]; + } + + Mask >>= 1; + } while (Index2 >= NC); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mCLen[Index2]); + + return Index2; +} + +/** + Decode the source data and put the resulting data into the destination buffer. + + @param Sd The global scratch data + +**/ +VOID +Decode ( + SCRATCH_DATA *Sd + ) +{ + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 CharC; + + BytesRemain = (UINT16) (-1); + + DataIdx = 0; + + for (;;) { + CharC = DecodeC (Sd); + if (Sd->mBadTableFlag != 0) { + return ; + } + + if (CharC < 256) { + // + // Process an Original character + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } else { + Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; + } + + } else { + // + // Process a Pointer + // + CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD)); + + BytesRemain = CharC; + + DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; + + BytesRemain--; + while ((INT16) (BytesRemain) >= 0) { + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } + + BytesRemain--; + } + } + } + + return ; +} + +/** + The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). + + @param Source The source buffer containing the compressed data. + @param SourceSize The size of source buffer + @param DestinationSize The size of destination buffer. + @param ScratchSize The size of scratch buffer. + + @retval RETURN_SUCCESS The size of destination buffer and the size of scratch buffer are successull retrieved. + @retval RETURN_INVALID_PARAMETER The source data is corrupted + +**/ +RETURN_STATUS +EFIAPI +UefiDecompressGetInfo ( + IN CONST VOID *Source, + IN UINT32 SourceSize, + OUT UINT32 *DestinationSize, + OUT UINT32 *ScratchSize + ) +{ + UINT32 CompressedSize; + + ASSERT (Source != NULL); + ASSERT (DestinationSize != NULL); + ASSERT (ScratchSize != NULL); + + *ScratchSize = sizeof (SCRATCH_DATA); + + if (SourceSize < 8) { + return RETURN_INVALID_PARAMETER; + } + + CopyMem (&CompressedSize, Source, sizeof (UINT32)); + CopyMem (DestinationSize, (VOID *)((UINT8 *)Source + 4), sizeof (UINT32)); + + if (SourceSize < (CompressedSize + 8)) { + return RETURN_INVALID_PARAMETER; + } + + return RETURN_SUCCESS; +} + +/** + The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). + + @param Source The source buffer containing the compressed data. + @param Destination The destination buffer to store the decompressed data + @param Scratch The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + + @retval RETURN_SUCCESS Decompression is successfull + @retval RETURN_INVALID_PARAMETER The source data is corrupted + +**/ +RETURN_STATUS +EFIAPI +UefiDecompress ( + IN CONST VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch + ) +{ + volatile UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + SCRATCH_DATA *Sd; + CONST UINT8 *Src; + UINT8 *Dst; + + ASSERT (Source != NULL); + ASSERT (Destination != NULL); + ASSERT (Scratch != NULL); + + Src = Source; + Dst = Destination; + + Sd = (SCRATCH_DATA *) Scratch; + + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + // + // If compressed file size is 0, return + // + if (OrigSize == 0) { + return RETURN_SUCCESS; + } + + Src = Src + 8; + + for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { + ((UINT8 *) Sd)[Index] = 0; + } + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 + // For Tiano de/compression algorithm(Version 2), mPBit = 5 + // + Sd->mPBit = 4; + Sd->mSrcBase = (UINT8 *)Src; + Sd->mDstBase = Dst; + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; + + // + // Fill the first BITBUFSIZ bits + // + FillBuf (Sd, BITBUFSIZ); + + // + // Decompress it + // + Decode (Sd); + + if (Sd->mBadTableFlag != 0) { + // + // Something wrong with the source + // + return RETURN_INVALID_PARAMETER; + } + + return RETURN_SUCCESS; +} diff --git a/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.mbd b/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.mbd new file mode 100644 index 0000000000..7ed513e9ba --- /dev/null +++ b/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.mbd @@ -0,0 +1,30 @@ + + + + + BaseUefiDecompressLib + 9ae5147d-b240-467f-a484-b024fdc42ee0 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.msa b/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.msa new file mode 100644 index 0000000000..f7f3f4f0d4 --- /dev/null +++ b/MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.msa @@ -0,0 +1,45 @@ + + + + + BaseUefiDecompressLib + DXE_DRIVER + LIBRARY + 9ae5147d-b240-467f-a484-b024fdc42ee0 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + UefiDecompressLib + DebugLib + BaseMemoryLib + + + BaseUefiDecompressLib.c + + + MdePkg + + diff --git a/MdePkg/Library/BaseUefiDecompressLib/build.xml b/MdePkg/Library/BaseUefiDecompressLib/build.xml new file mode 100644 index 0000000000..e41fcf9114 --- /dev/null +++ b/MdePkg/Library/BaseUefiDecompressLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c new file mode 100644 index 0000000000..a6f04dfe2f --- /dev/null +++ b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.c @@ -0,0 +1,63 @@ +/** @file + Entry point to the DXE Core. + +Copyright (c) 2006, 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. + +**/ + +// +// Cache copy of HobList pointer. +// +VOID *gHobList = NULL; + +/** + Enrty point to DXE core. + + @param HobStart Pointer of HobList. + +**/ +VOID +EFIAPI +_ModuleEntryPoint ( + IN VOID *HobStart + ) +{ + // + // Cache a pointer to the HobList + // + gHobList = HobStart; + + // + // Call the DXE Core entry point + // + ProcessModuleEntryPointList (HobStart); + + // + // Should never return + // + ASSERT(FALSE); + CpuDeadLoop (); +} + + +/** + Wrapper of enrty point to DXE CORE. + + @param HobStart Pointer of HobList. + +**/ +VOID +EFIAPI +EfiMain ( + IN VOID *HobStart + ) +{ + _ModuleEntryPoint (HobStart); +} diff --git a/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.mbd b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.mbd new file mode 100644 index 0000000000..57a7d25ddd --- /dev/null +++ b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.mbd @@ -0,0 +1,30 @@ + + + + + DxeCoreEntryPoint + d258d6af-2fc0-4019-9c1f-1101c3dd19b5 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.msa b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.msa new file mode 100644 index 0000000000..5d0e73faf0 --- /dev/null +++ b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.msa @@ -0,0 +1,45 @@ + + + + + DxeCoreEntryPoint + DXE_CORE + LIBRARY + d258d6af-2fc0-4019-9c1f-1101c3dd19b5 + 0 + Component description file for the entry point to the DXE Core + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + DxeCoreEntryPoint + DebugLib + BaseLib + + + DxeCoreEntryPoint.c + + + MdePkg + + diff --git a/MdePkg/Library/DxeCoreEntryPoint/build.xml b/MdePkg/Library/DxeCoreEntryPoint/build.xml new file mode 100644 index 0000000000..9980656298 --- /dev/null +++ b/MdePkg/Library/DxeCoreEntryPoint/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.mbd b/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.mbd new file mode 100644 index 0000000000..6173b1c4e7 --- /dev/null +++ b/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.mbd @@ -0,0 +1,30 @@ + + + + + DxeCoreHobLib + 882ee1a3-35b2-412c-b8a2-7a8d34a7c390 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.msa b/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.msa new file mode 100644 index 0000000000..22f0968980 --- /dev/null +++ b/MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.msa @@ -0,0 +1,46 @@ + + + + + DxeCoreHobLib + DXE_CORE + LIBRARY + 882ee1a3-35b2-412c-b8a2-7a8d34a7c390 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + HobLib + DebugLib + DxeCoreEntryPoint + BaseMemoryLib + + + HobLib.c + + + MdePkg + + diff --git a/MdePkg/Library/DxeCoreHobLib/HobLib.c b/MdePkg/Library/DxeCoreHobLib/HobLib.c new file mode 100644 index 0000000000..febd1e45b9 --- /dev/null +++ b/MdePkg/Library/DxeCoreHobLib/HobLib.c @@ -0,0 +1,365 @@ +/** @file + HOB Library. + + Copyright (c) 2006, 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. + + Module Name: HobLib.c + +**/ + + + +extern VOID *gHobList; + +/** + Returns the pointer to the HOB list. + + @return The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ) +{ + return gHobList; +} + +/** + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + ASSERT (HobStart != NULL); + + Hob.Raw = (UINT8 *) HobStart; + // + // Parse the HOB list, stop if end of list or matching type found. + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == Type) { + return Hob.Raw; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return NULL; +} + +/** + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextHob (Type, HobList); +} + +/** + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = (UINT8 *) HobStart; + while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) { + if (CompareGuid (Guid, &GuidHob.Guid->Name)) { + break; + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + return GuidHob.Raw; +} + +/** + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextGuidHob (Guid, HobList); +} + +/** + This function builds a HOB for a loaded PE32 module. + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the moduleÂ’s entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB that describes a chunk of system memory. + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); + return NULL; +} + +/** + This function builds a customized HOB tagged with a GUID for identification, + copies the input data to the HOB data field, and returns the start address of GUID HOB data. + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); + return NULL; +} + +/** + Builds a Firmware Volume HOB. + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a Capsule Volume HOB. + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the CPU. + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the Stack. + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the BSP store. + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the memory allocation. + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} diff --git a/MdePkg/Library/DxeCoreHobLib/build.xml b/MdePkg/Library/DxeCoreHobLib/build.xml new file mode 100644 index 0000000000..9ef95dc421 --- /dev/null +++ b/MdePkg/Library/DxeCoreHobLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/DxeHobLib/DxeHobLib.mbd b/MdePkg/Library/DxeHobLib/DxeHobLib.mbd new file mode 100644 index 0000000000..9a314afdc0 --- /dev/null +++ b/MdePkg/Library/DxeHobLib/DxeHobLib.mbd @@ -0,0 +1,30 @@ + + + + + DxeHobLib + f12b59c9-76d0-4661-ad7c-f04d1bef0558 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/DxeHobLib/DxeHobLib.msa b/MdePkg/Library/DxeHobLib/DxeHobLib.msa new file mode 100644 index 0000000000..a0ffa5e979 --- /dev/null +++ b/MdePkg/Library/DxeHobLib/DxeHobLib.msa @@ -0,0 +1,56 @@ + + + + + DxeHobLib + DXE_DRIVER + LIBRARY + f12b59c9-76d0-4661-ad7c-f04d1bef0558 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + HobLib + UefiLib + DebugLib + BaseMemoryLib + + + HobLib.c + + + MdePkg + + + + HobList + + + + + HobLibConstructor + + + diff --git a/MdePkg/Library/DxeHobLib/HobLib.c b/MdePkg/Library/DxeHobLib/HobLib.c new file mode 100644 index 0000000000..a914dd7ba2 --- /dev/null +++ b/MdePkg/Library/DxeHobLib/HobLib.c @@ -0,0 +1,394 @@ +/** @file + HOB Library. + + Copyright (c) 2006, 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. + + Module Name: HobLib.c + +**/ + + + +STATIC VOID *mHobList = NULL; + +/** + The constructor function caches the pointer to HOB list. + + The constructor function gets the start address of HOB list from system configuration table. + It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +HobLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = EfiGetSystemConfigurationTable (&gEfiHobListGuid, &mHobList); + ASSERT_EFI_ERROR (Status); + ASSERT (mHobList != NULL); + return Status; +} + +/** + Returns the pointer to the HOB list. + + None. + + The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ) +{ + return mHobList; +} + +/** + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + ASSERT (HobStart != NULL); + + Hob.Raw = (UINT8 *) HobStart; + // + // Parse the HOB list, stop if end of list or matching type found. + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == Type) { + return Hob.Raw; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return NULL; +} + +/** + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextHob (Type, HobList); +} + +/** + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = (UINT8 *) HobStart; + while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) { + if (CompareGuid (Guid, &GuidHob.Guid->Name)) { + break; + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + return GuidHob.Raw; +} + +/** + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextGuidHob (Guid, HobList); +} + +/** + This function builds a HOB for a loaded PE32 module. + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the module’s entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB that describes a chunk of system memory. + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); + return NULL; +} + +/** + This function builds a customized HOB tagged with a GUID for identification, + copies the input data to the HOB data field, and returns the start address of GUID HOB data. + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); + return NULL; +} + +/** + Builds a Firmware Volume HOB. + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a Capsule Volume HOB. + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the CPU. + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the Stack. + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the BSP store. + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} + +/** + Builds a HOB for the memory allocation. + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + // + // PEI HOB is read only for DXE phase + // + ASSERT (FALSE); +} diff --git a/MdePkg/Library/DxeHobLib/build.xml b/MdePkg/Library/DxeHobLib/build.xml new file mode 100644 index 0000000000..1def5e77b7 --- /dev/null +++ b/MdePkg/Library/DxeHobLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.mbd b/MdePkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.mbd new file mode 100644 index 0000000000..1db8290353 --- /dev/null +++ b/MdePkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.mbd @@ -0,0 +1,29 @@ + + + + + DxeIoLibCpuIo + e94cd42a-3aad-4ea0-9b09-945891c60ccd + EDK_RELEASE_VERSION 0x00090000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-04-14 12:44 + + diff --git a/MdePkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.msa b/MdePkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.msa new file mode 100644 index 0000000000..93a0e6cb1f --- /dev/null +++ b/MdePkg/Library/DxeIoLibCpuIo/DxeIoLibCpuIo.msa @@ -0,0 +1,53 @@ + + + + + DxeIoLibCpuIo + DXE_DRIVER + LIBRARY + e94cd42a-3aad-4ea0-9b09-945891c60ccd + EDK_RELEASE_VERSION 0x00090000 + I/O Library implemented with Framework CPU I/O Protocol + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-14 12:44 + + + IoLib + DebugLib + BaseLib + + + IoLib.c + IoHighLevel.c + + + MdePkg + + + CpuIo + + + + IoLibConstructor + + + diff --git a/MdePkg/Library/DxeIoLibCpuIo/IoHighLevel.c b/MdePkg/Library/DxeIoLibCpuIo/IoHighLevel.c new file mode 100644 index 0000000000..48a7477d81 --- /dev/null +++ b/MdePkg/Library/DxeIoLibCpuIo/IoHighLevel.c @@ -0,0 +1,2272 @@ +/** @file + High-level Io/Mmio functions. + + All assertions for bit field operations are handled bit field functions in the + Base Library. + + Copyright (c) 2006, 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. + + Module Name: IoHighLevel.c + + The following IoLib instances share the same version of this file: + + BaseIoLibIntrinsic + DxeIoLibCpuIo + PeiIoLibCpuIo + +**/ + +/** + Reads an 8-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoOr8 ( + IN UINTN Port, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, IoRead8 (Port) | OrData); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND, and writes the result back + to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAnd8 ( + IN UINTN Port, + IN UINT8 AndData + ) +{ + return IoWrite8 (Port, IoRead8 (Port) & AndData); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAndThenOr8 ( + IN UINTN Port, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (IoRead8 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in an 8-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoBitFieldRead8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (IoRead8 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldWrite8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return IoWrite8 ( + Port, + BitFieldWrite8 (IoRead8 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldOr8 (IoRead8 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAnd8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return IoWrite8 ( + Port, + BitFieldAnd8 (IoRead8 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 8-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAndThenOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldAndThenOr8 (IoRead8 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoOr16 ( + IN UINTN Port, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, IoRead16 (Port) | OrData); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND, and writes the result back + to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAnd16 ( + IN UINTN Port, + IN UINT16 AndData + ) +{ + return IoWrite16 (Port, IoRead16 (Port) & AndData); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAndThenOr16 ( + IN UINTN Port, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (IoRead16 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 16-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoBitFieldRead16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (IoRead16 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldWrite16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return IoWrite16 ( + Port, + BitFieldWrite16 (IoRead16 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldOr16 (IoRead16 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAnd16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return IoWrite16 ( + Port, + BitFieldAnd16 (IoRead16 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 16-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAndThenOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldAndThenOr16 (IoRead16 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoOr32 ( + IN UINTN Port, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) | OrData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND, and writes the result back + to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAnd32 ( + IN UINTN Port, + IN UINT32 AndData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) & AndData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAndThenOr32 ( + IN UINTN Port, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, (IoRead32 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 32-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoBitFieldRead32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (IoRead32 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldWrite32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return IoWrite32 ( + Port, + BitFieldWrite32 (IoRead32 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldOr32 (IoRead32 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAnd32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return IoWrite32 ( + Port, + BitFieldAnd32 (IoRead32 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 32-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAndThenOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldAndThenOr32 (IoRead32 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoOr64 ( + IN UINTN Port, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) | OrData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND, and writes the result back + to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAnd64 ( + IN UINTN Port, + IN UINT64 AndData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) & AndData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAndThenOr64 ( + IN UINTN Port, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, (IoRead64 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 64-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoBitFieldRead64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (IoRead64 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldWrite64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return IoWrite64 ( + Port, + BitFieldWrite64 (IoRead64 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldOr64 (IoRead64 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAnd64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return IoWrite64 ( + Port, + BitFieldAnd64 (IoRead64 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 64-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAndThenOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldAndThenOr64 (IoRead64 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, MmioRead8 (Address) | OrData); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND, and writes the result + back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return MmioWrite8 (Address, MmioRead8 (Address) & AndData); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 8-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (MmioRead8 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in an 8-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (MmioRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 8-bit register is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return MmioWrite8 ( + Address, + BitFieldWrite8 (MmioRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldOr8 (MmioRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAnd8 (MmioRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 8-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAndThenOr8 (MmioRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, MmioRead16 (Address) | OrData); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result + back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return MmioWrite16 (Address, MmioRead16 (Address) & AndData); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 16-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (MmioRead16 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 16-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (MmioRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 16-bit register is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return MmioWrite16 ( + Address, + BitFieldWrite16 (MmioRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldOr16 (MmioRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAnd16 (MmioRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 16-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAndThenOr16 (MmioRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) | OrData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result + back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) & AndData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 32-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, (MmioRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 32-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (MmioRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 32-bit register is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return MmioWrite32 ( + Address, + BitFieldWrite32 (MmioRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldOr32 (MmioRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAnd32 (MmioRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 32-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAndThenOr32 (MmioRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioOr64 ( + IN UINTN Address, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) | OrData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result + back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAnd64 ( + IN UINTN Address, + IN UINT64 AndData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) & AndData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 64-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAndThenOr64 ( + IN UINTN Address, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, (MmioRead64 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 64-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioBitFieldRead64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (MmioRead64 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 64-bit register is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldWrite64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return MmioWrite64 ( + Address, + BitFieldWrite64 (MmioRead64 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldOr64 (MmioRead64 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAnd64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAnd64 (MmioRead64 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 64-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAndThenOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAndThenOr64 (MmioRead64 (Address), StartBit, EndBit, AndData, OrData) + ); +} diff --git a/MdePkg/Library/DxeIoLibCpuIo/IoLib.c b/MdePkg/Library/DxeIoLibCpuIo/IoLib.c new file mode 100644 index 0000000000..21b23dfe3b --- /dev/null +++ b/MdePkg/Library/DxeIoLibCpuIo/IoLib.c @@ -0,0 +1,460 @@ +/** @file + I/O Library. + + Copyright (c) 2006, 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. + + Module Name: IoLib.c + +**/ + +static EFI_CPU_IO_PROTOCOL *gCpuIo; + +EFI_STATUS +IoLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = SystemTable->BootServices->LocateProtocol ( + &gEfiCpuIoProtocolGuid, + NULL, + (VOID**)&gCpuIo + ); + ASSERT_EFI_ERROR (Status); + return Status; +} + +UINT64 +EFIAPI +IoReadWorker ( + IN UINTN Port, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width + ) +{ + UINT64 Data; + + gCpuIo->Io.Read (gCpuIo, Width, Port, 1, &Data); + return Data; +} + +UINT64 +EFIAPI +IoWriteWorker ( + IN UINTN Port, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Data + ) +{ + gCpuIo->Io.Write (gCpuIo, Width, Port, 1, &Data); + return Data; +} + +UINT64 +EFIAPI +MmioReadWorker ( + IN UINTN Address, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width + ) +{ + UINT64 Data; + + gCpuIo->Mem.Read (gCpuIo, Width, Address, 1, &Data); + return Data; +} + +UINT64 +EFIAPI +MmioWriteWorker ( + IN UINTN Address, + IN EFI_CPU_IO_PROTOCOL_WIDTH Width, + IN UINT64 Data + ) +{ + gCpuIo->Mem.Write (gCpuIo, Width, Address, 1, &Data); + return Data; +} + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + return (UINT8)IoReadWorker (Port, EfiCpuIoWidthUint8); +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + return (UINT8)IoWriteWorker (Port, EfiCpuIoWidthUint8, Value); +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + return (UINT16)IoReadWorker (Port, EfiCpuIoWidthUint16); +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + return (UINT16)IoWriteWorker (Port, EfiCpuIoWidthUint16, Value); +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + return (UINT32)IoReadWorker (Port, EfiCpuIoWidthUint32); +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + return (UINT32)IoWriteWorker (Port, EfiCpuIoWidthUint32, Value); +} + +/** + Reads a 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoRead64 ( + IN UINTN Port + ) +{ + return IoReadWorker (Port, EfiCpuIoWidthUint64); +} + +/** + Writes a 64-bit I/O port. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT64 +EFIAPI +IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ) +{ + return IoWriteWorker (Port, EfiCpuIoWidthUint64, Value); +} + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8 ( + IN UINTN Address + ) +{ + return (UINT8)MmioReadWorker (Address, EfiCpuIoWidthUint8); +} + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + return (UINT8)MmioWriteWorker (Address, EfiCpuIoWidthUint8, Value); +} + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16 ( + IN UINTN Address + ) +{ + return (UINT16)MmioReadWorker (Address, EfiCpuIoWidthUint16); +} + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + return (UINT16)MmioWriteWorker (Address, EfiCpuIoWidthUint16, Value); +} + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32 ( + IN UINTN Address + ) +{ + return (UINT32)MmioReadWorker (Address, EfiCpuIoWidthUint32); +} + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + return (UINT32)MmioWriteWorker (Address, EfiCpuIoWidthUint32, Value); +} + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64 ( + IN UINTN Address + ) +{ + return (UINT64)MmioReadWorker (Address, EfiCpuIoWidthUint64); +} + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + return (UINT64)MmioWriteWorker (Address, EfiCpuIoWidthUint64, Value); +} diff --git a/MdePkg/Library/DxeIoLibCpuIo/build.xml b/MdePkg/Library/DxeIoLibCpuIo/build.xml new file mode 100644 index 0000000000..94dbb4a139 --- /dev/null +++ b/MdePkg/Library/DxeIoLibCpuIo/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.mbd b/MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.mbd new file mode 100644 index 0000000000..d1f11c90aa --- /dev/null +++ b/MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.mbd @@ -0,0 +1,30 @@ + + + + + DxeMemoryAllocationLib + 4674739d-3195-4fb2-8094-ac1d22d00194 + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.msa b/MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.msa new file mode 100644 index 0000000000..4bcf029b64 --- /dev/null +++ b/MdePkg/Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.msa @@ -0,0 +1,46 @@ + + + + + DxeMemoryAllocationLib + DXE_DRIVER + LIBRARY + 4674739d-3195-4fb2-8094-ac1d22d00194 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + MemoryAllocationLib + UefiBootServicesTableLib + BaseMemoryLib + DebugLib + + + MemoryAllocationLib.c + + + MdePkg + + diff --git a/MdePkg/Library/DxeMemoryAllocationLib/MemoryAllocationLib.c b/MdePkg/Library/DxeMemoryAllocationLib/MemoryAllocationLib.c new file mode 100644 index 0000000000..a9bdf60aa1 --- /dev/null +++ b/MdePkg/Library/DxeMemoryAllocationLib/MemoryAllocationLib.c @@ -0,0 +1,886 @@ +/** @file + Support routines for memory allocation routines for use with drivers. + + Copyright (c) 2006, 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. + + Module Name: MemoryAllocationLib.c + +**/ + + + +/** + Allocates the number of 4KB pages specified by Pages of a certain memory type. + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary.
+ If Pages is 0, then NULL is returned.
+ If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + + if (Pages == 0) { + return NULL; + } + + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + Memory = 0; + } + return (VOID *) (UINTN) Memory; +} + +/** + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary.
+ If Pages is 0, then NULL is returned.
+ If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiBootServicesData, Pages); +} + +/** + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary.
+ If Pages is 0, then NULL is returned.
+ If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiRuntimeServicesData, Pages); +} + +/** + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary.
+ If Pages is 0, then NULL is returned.
+ If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedPages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiReservedMemoryType, Pages); +} + +/** + Frees one or more 4KB pages that were previously allocated with + one of the page allocation functions in the Memory Allocation Library. + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates the number of 4KB pages specified by Pages of a certian memory type + with an alignment specified by Alignment. + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return The allocated buffer is returned.
+ If Pages is 0, then NULL is returned.
+ If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + UINTN AlignedMemory; + UINTN AlignmentMask; + UINTN UnalignedPages; + UINTN RealPages; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + if (Alignment > EFI_PAGE_SIZE) { + // + // Caculate the total number of pages since alignment is larger than page size. + // + AlignmentMask = Alignment - 1; + RealPages = Pages + EFI_SIZE_TO_PAGES (Alignment); + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, RealPages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask; + UnalignedPages = EFI_SIZE_TO_PAGES ((UINTN) Memory - AlignedMemory); + if (UnalignedPages > 0) { + // + // Free first unaligned page(s). + // + Status = gBS->FreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + Memory = (EFI_PHYSICAL_ADDRESS) (AlignedMemory + EFI_PAGES_TO_SIZE (Pages)); + UnalignedPages = RealPages - Pages - UnalignedPages; + if (UnalignedPages > 0) { + // + // Free last unaligned page(s). + // + Status = gBS->FreePages (Memory, UnalignedPages); + ASSERT_EFI_ERROR (Status); + } + } else { + // + // Do not over-allocate pages in this case. + // + Status = gBS->AllocatePages (AllocateAnyPages, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedMemory = (UINTN) Memory; + } + return (VOID *) AlignedMemory; +} + +/** + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData + with an alignment specified by Alignment. + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return The allocated buffer is returned.
+ If Pages is 0, then NULL is returned.
+ If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment); +} + +/** + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData + with an alignment specified by Alignment. + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment); +} + +/** + Frees one or more 4KB pages that were previously allocated with + one of the aligned page allocation functions in the Memory Allocation Library. + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + + ASSERT (Pages != 0); + Status = gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) Buffer, Pages); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates a buffer of a certain memory type. + + @param MemoryType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocatePool ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN AllocationSize + ) +{ + EFI_STATUS Status; + VOID *Memory; + + Status = gBS->AllocatePool (MemoryType, AllocationSize, &Memory); + if (EFI_ERROR (Status)) { + Memory = NULL; + } + return Memory; +} + +/** + Allocates a buffer of type EfiBootServicesData. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiBootServicesData, AllocationSize); +} + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates a buffer of type EfiReservedMemoryType. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiReservedMemoryType, AllocationSize); +} + +/** + Allocates and zeros a buffer of a certian pool type. + + @param PoolType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize + ) +{ + VOID *Memory; + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiBootServicesData, AllocationSize); +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize); +} + +/** + Copies a buffer to an allocated buffer of a certian memory type. + + @param MemoryType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiBootServicesData, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType at a specified alignment. + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + EFI_STATUS Status; + + Status = gBS->FreePool (Buffer); + ASSERT_EFI_ERROR (Status); +} + +/** + Allocates a buffer of a certain pool type at a specified alignment. + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateAlignedPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + VOID *RawAddress; + UINTN AlignedAddress; + UINTN AlignmentMask; + UINTN OverAllocationSize; + VOID **FreePointer; + EFI_STATUS Status; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Alignment == 0) { + AlignmentMask = Alignment; + } else { + AlignmentMask = Alignment - 1; + } + // + // Calculate the extra memory size, over-allocate memory pool and get the aligned memory address. + // + OverAllocationSize = sizeof (RawAddress) + AlignmentMask; + Status = gBS->AllocatePool (PoolType, AllocationSize + OverAllocationSize, &RawAddress); + if (EFI_ERROR (Status)) { + return NULL; + } + AlignedAddress = ((UINTN) RawAddress + OverAllocationSize) & ~AlignmentMask; + // + // Save the original memory address just before the aligned address. + // + FreePointer = (VOID **)(AlignedAddress - sizeof (RawAddress)); + *FreePointer = RawAddress; + + return (VOID *) AlignedAddress; +} + +/** + Allocates a buffer of type EfiBootServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPool (EfiBootServicesData, AllocationSize, Alignment); +} + +/** + Allocates a buffer of type EfiRuntimeServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPool (EfiRuntimeServicesData, AllocationSize, Alignment); +} + +/** + Allocates a buffer of type EfiReservedMemoryType at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPool (EfiReservedMemoryType, AllocationSize, Alignment); +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment. + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateAlignedZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + VOID *Memory; + Memory = InternalAllocateAlignedPool (PoolType, AllocationSize, Alignment); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedZeroPool (EfiBootServicesData, AllocationSize, Alignment); +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimeZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedZeroPool (EfiRuntimeServicesData, AllocationSize, Alignment); +} + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedZeroPool (EfiReservedMemoryType, AllocationSize, Alignment); +} + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData at a specified alignment. + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateAlignedCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + VOID *Memory; + + Memory = InternalAllocateAlignedPool (PoolType, AllocationSize, Alignment); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedCopyPool (EfiBootServicesData, AllocationSize, Buffer, Alignment); +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer, Alignment); +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedCopyPool (EfiReservedMemoryType, AllocationSize, Buffer, Alignment); +} + +/** + Frees a buffer that was previously allocated with one of the aligned pool allocation functions + in the Memory Allocation Library. + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreeAlignedPool ( + IN VOID *Buffer + ) +{ + VOID *RawAddress; + VOID **FreePointer; + EFI_STATUS Status; + + // + // Get the pre-saved original address in the over-allocate pool. + // + FreePointer = (VOID **)((UINTN) Buffer - sizeof (RawAddress)); + RawAddress = *FreePointer; + + Status = gBS->FreePool (RawAddress); + ASSERT_EFI_ERROR (Status); +} diff --git a/MdePkg/Library/DxeMemoryAllocationLib/build.xml b/MdePkg/Library/DxeMemoryAllocationLib/build.xml new file mode 100644 index 0000000000..cabeb3b28b --- /dev/null +++ b/MdePkg/Library/DxeMemoryAllocationLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/DxePcdLib/DxePcdLib.c b/MdePkg/Library/DxePcdLib/DxePcdLib.c new file mode 100644 index 0000000000..4773bf6c0c --- /dev/null +++ b/MdePkg/Library/DxePcdLib/DxePcdLib.c @@ -0,0 +1,852 @@ +/** @file +Implementation of PcdLib class library for DXE phase. + +Copyright (c) 2006, 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. + + +Module Name: DxePcdLib.c + +**/ + +static PCD_PROTOCOL *mPcd; + +/** + The constructor function caches the PCD_PROTOCOL pointer. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always return EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +PcdLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol (&gPcdProtocolGuid, NULL, (VOID **)&mPcd); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + +/** + Sets the current SKU in the PCD database to the value specified by SkuId. SkuId is returned. + + @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and + set values associated with a PCD token. + + @retval UINTN Return the SKU ID that just be set. + +**/ +UINTN +EFIAPI +LibPcdSetSku ( + IN UINTN SkuId + ) +{ + EFI_STATUS Status; + + Status = mPcd->SetSku (SkuId); + ASSERT_EFI_ERROR (Status); + + return SkuId; +} + + + +/** + Returns the 8-bit value for the token specified by TokenNumber. + + @param[in] The PCD token number to retrieve a current value for. + + @retval UINT8 Returns the 8-bit value for the token specified by TokenNumber. + +**/ +UINT8 +EFIAPI +LibPcdGet8 ( + IN UINTN TokenNumber + ) +{ + return mPcd->Get8 (TokenNumber); +} + + + +/** + Returns the 16-bit value for the token specified by TokenNumber. + + @param[in] The PCD token number to retrieve a current value for. + + @retval UINT16 Returns the 16-bit value for the token specified by TokenNumber. + +**/ +UINT16 +EFIAPI +LibPcdGet16 ( + IN UINTN TokenNumber + ) +{ + return mPcd->Get16 (TokenNumber); +} + + + +/** + Returns the 32-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT32 Returns the 32-bit value for the token specified by TokenNumber. + +**/ +UINT32 +EFIAPI +LibPcdGet32 ( + IN UINTN TokenNumber + ) +{ + return mPcd->Get32 (TokenNumber); +} + + + +/** + Returns the 64-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT64 Returns the 64-bit value for the token specified by TokenNumber. + +**/ +UINT64 +EFIAPI +LibPcdGet64 ( + IN UINTN TokenNumber + ) +{ + return mPcd->Get64 (TokenNumber); +} + + + +/** + Returns the pointer to the buffer of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval VOID* Returns the pointer to the token specified by TokenNumber. + +**/ +VOID * +EFIAPI +LibPcdGetPtr ( + IN UINTN TokenNumber + ) +{ + return mPcd->GetPtr (TokenNumber); +} + + + +/** + Returns the Boolean value of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval BOOLEAN Returns the Boolean value of the token specified by TokenNumber. + +**/ +BOOLEAN +EFIAPI +LibPcdGetBool ( + IN UINTN TokenNumber + ) +{ + return mPcd->GetBool (TokenNumber); +} + + + +/** + Returns the size of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINTN Returns the size of the token specified by TokenNumber. + +**/ +UINTN +EFIAPI +LibPcdGetSize ( + IN UINTN TokenNumber + ) +{ + return mPcd->GetSize (TokenNumber); +} + + + +/** + Returns the 8-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT8 Return the UINT8. + +**/ +UINT8 +EFIAPI +LibPcdGetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return mPcd->Get8Ex (Guid, TokenNumber); +} + + +/** + Returns the 16-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT16 Return the UINT16. + +**/ +UINT16 +EFIAPI +LibPcdGetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return mPcd->Get16Ex (Guid, TokenNumber); +} + + +/** + Returns the 32-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT32 Return the UINT32. + +**/ +UINT32 +EFIAPI +LibPcdGetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return mPcd->Get32Ex (Guid, TokenNumber); +} + + + +/** + Returns the 64-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT64 Return the UINT64. + +**/ +UINT64 +EFIAPI +LibPcdGetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return mPcd->Get64Ex (Guid, TokenNumber); +} + + + +/** + Returns the pointer to the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval VOID* Return the VOID* pointer. + +**/ +VOID * +EFIAPI +LibPcdGetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return mPcd->GetPtrEx (Guid, TokenNumber); +} + + + +/** + Returns the Boolean value of the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval BOOLEAN Return the BOOLEAN. + +**/ +BOOLEAN +EFIAPI +LibPcdGetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return mPcd->GetBoolEx (Guid, TokenNumber); +} + + + +/** + Returns the size of the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINTN Return the size. + +**/ +UINTN +EFIAPI +LibPcdGetExSize ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + ASSERT (Guid != NULL); + + return mPcd->GetSizeEx (Guid, TokenNumber); +} + + + +/** + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT8 +EFIAPI +LibPcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + EFI_STATUS Status; + + Status = mPcd->Set8 (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @retval UINT16 Return the value been set. + +**/ +UINT16 +EFIAPI +LibPcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + EFI_STATUS Status; + + Status = mPcd->Set16 (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @retval UINT32 Return the value been set. + +**/ +UINT32 +EFIAPI +LibPcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + EFI_STATUS Status; + Status = mPcd->Set32 (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @retval UINT64 Return the value been set. + +**/ +UINT64 +EFIAPI +LibPcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + EFI_STATUS Status; + + Status = mPcd->Set64 (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets a buffer for the token specified by TokenNumber to + the value specified by Value. Value is returned. + If Value is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value A pointer to the buffer to set. + + @retval VOID* Return the pointer for the buffer been set. + +**/ +VOID * +EFIAPI +LibPcdSetPtr ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + EFI_STATUS Status; + + ASSERT (Value != NULL); + + Status = mPcd->SetPtr (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return (VOID *)Value; +} + + + +/** + Sets the Boolean value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @retval BOOLEAN Return the value been set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + EFI_STATUS Status; + + Status = mPcd->SetBool (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 8-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT8 +EFIAPI +LibPcdSetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + EFI_STATUS Status; + + ASSERT (Guid != NULL); + + Status = mPcd->Set8Ex (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 16-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT16 +EFIAPI +LibPcdSetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + EFI_STATUS Status; + + ASSERT (Guid != NULL); + + Status = mPcd->Set16Ex (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 32-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @retval UINT32 Return the value been set. + +**/ +UINT32 +EFIAPI +LibPcdSetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + EFI_STATUS Status; + + ASSERT (Guid != NULL); + + Status = mPcd->Set32Ex (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 64-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @retval UINT64 Return the value been set. + +**/ +UINT64 +EFIAPI +LibPcdSetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + EFI_STATUS Status; + + ASSERT (Guid != NULL); + + Status = mPcd->Set64Ex (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets a buffer for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + If Value is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval VOID * Return the value been set. + +**/ +VOID * +EFIAPI +LibPcdSetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + EFI_STATUS Status; + + ASSERT (Guid != NULL); + ASSERT (Value != NULL); + + Status = mPcd->SetPtrEx (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return (VOID *)Value; +} + + + +/** + Sets the Boolean value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The Boolean value to set. + + @retval Boolean Return the value been set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + EFI_STATUS Status; + + ASSERT (Guid != NULL); + + Status = mPcd->SetBoolEx (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + When the token specified by TokenNumber and Guid is set, + then notification function specified by NotificationFunction is called. + If Guid is NULL, then the default token space is used. + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates which + namespace to set a value from. If NULL, then the default + token space is used. + @param[in] TokenNumber The PCD token number to monitor. + @param[in] NotificationFunction The function to call when the token + specified by Guid and TokenNumber is set. + + @retval VOID + +**/ +VOID +EFIAPI +LibPcdCallbackOnSet ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + EFI_STATUS Status; + + ASSERT (NotificationFunction != NULL); + + Status = mPcd->CallbackOnSet (TokenNumber, Guid, NotificationFunction); + + ASSERT_EFI_ERROR (Status); + + return; +} + + + +/** + Disable a notification function that was established with LibPcdCallbackonSet(). + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid Specify the GUID token space. + @param[in] TokenNumber Specify the token number. + @param[in] NotificationFunction The callback function to be unregistered. + + @retval VOID + +**/ +VOID +EFIAPI +LibPcdCancelCallback ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + EFI_STATUS Status; + + ASSERT (NotificationFunction != NULL); + + Status = mPcd->CancelCallback (TokenNumber, Guid, NotificationFunction); + + ASSERT_EFI_ERROR (Status); + + return; +} + + + +/** + Retrieves the next PCD token number from the token space specified by Guid. + If Guid is NULL, then the default token space is used. If TokenNumber is 0, + then the first token number is returned. Otherwise, the token number that + follows TokenNumber in the token space is returned. If TokenNumber is the last + token number in the token space, then 0 is returned. If TokenNumber is not 0 and + is not in the token space specified by Guid, then ASSERT(). + + @param[in] Pointer to a 128-bit unique value that designates which namespace + to set a value from. If NULL, then the default token space is used. + @param[in] The previous PCD token number. If 0, then retrieves the first PCD + token number. + + @retval UINTN The next valid token number. + +**/ +UINTN +EFIAPI +LibPcdGetNextToken ( + IN CONST GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ) +{ + EFI_STATUS Status; + + Status = mPcd->GetNextToken (Guid, TokenNumber); + + ASSERT_EFI_ERROR (Status); + + return (*TokenNumber); +} + diff --git a/MdePkg/Library/DxePcdLib/DxePcdLib.mbd b/MdePkg/Library/DxePcdLib/DxePcdLib.mbd new file mode 100644 index 0000000000..52fc7e3e72 --- /dev/null +++ b/MdePkg/Library/DxePcdLib/DxePcdLib.mbd @@ -0,0 +1,30 @@ + + + + + DxePcdLib + af97eb89-4cc6-45f8-a514-ca025b346480 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/DxePcdLib/DxePcdLib.msa b/MdePkg/Library/DxePcdLib/DxePcdLib.msa new file mode 100644 index 0000000000..dd7cbcee09 --- /dev/null +++ b/MdePkg/Library/DxePcdLib/DxePcdLib.msa @@ -0,0 +1,50 @@ + + + + + DxePcdLib + DXE_DRIVER + LIBRARY + af97eb89-4cc6-45f8-a514-ca025b346480 + 0 + IO Library implemented with Framework CPU IO Protocol + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + PcdLib + DebugLib + UefiBootServicesTableLib + + + DxePcdLib.c + + + MdePkg + + + + PcdLibConstructor + + + diff --git a/MdePkg/Library/DxePcdLib/build.xml b/MdePkg/Library/DxePcdLib/build.xml new file mode 100644 index 0000000000..1c5b401d63 --- /dev/null +++ b/MdePkg/Library/DxePcdLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.mbd b/MdePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.mbd new file mode 100644 index 0000000000..5569ae901e --- /dev/null +++ b/MdePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.mbd @@ -0,0 +1,30 @@ + + + + + DxeReportStatusCodeLib + 3ddc3b12-99ea-4364-b315-6310a2050be5 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:16 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.msa b/MdePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.msa new file mode 100644 index 0000000000..34b14497d8 --- /dev/null +++ b/MdePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.msa @@ -0,0 +1,71 @@ + + + + + DxeReportStatusCodeLib + DXE_DRIVER + LIBRARY + 3ddc3b12-99ea-4364-b315-6310a2050be5 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:16 + 2006-03-19 15:17 + + + ReportStatusCodeLib + DebugLib + UefiBootServicesTableLib + BaseLib + BaseMemoryLib + PcdLib + IoLib + + + ReportStatusCodeLib.c + PostCode.c + + + MdePkg + + + StatusCode + + + + StatusCodeDataTypeAssert + + + StatusCodeDataTypeDebug + + + StatusCodeSpecificData + + + + + PcdReportStatusCodePropertyMask + 0x00000007 + UINT8 + + + diff --git a/MdePkg/Library/DxeReportStatusCodeLib/PostCode.c b/MdePkg/Library/DxeReportStatusCodeLib/PostCode.c new file mode 100644 index 0000000000..3d0ce7cb8f --- /dev/null +++ b/MdePkg/Library/DxeReportStatusCodeLib/PostCode.c @@ -0,0 +1,125 @@ +/** @file + Report Status Code Library Post Code functions for DXE Phase. + + Copyright (c) 2006, 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. + +**/ + + +/** + Sends an 32-bit value to a POST card. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + Some implementations of this library function may perform I/O operations + directly to a POST card device. Other implementations may send Value to + ReportStatusCode(), and the status code reporting mechanism will eventually + display the 32-bit value on the status reporting device. + + PostCode() must actively prevent recursion. If PostCode() is called while + processing another any other Report Status Code Library function, then + PostCode() must return Value immediately. + + @param Value The 32-bit value to write to the POST card. + + @return Value + +**/ +UINT32 +EFIAPI +PostCode ( + IN UINT32 Value + ) +{ + DEBUG((EFI_D_INFO, "POST %08x\n", Value)); + IoWrite8 (0x80, (UINT8)(Value)); + return Value; +} + + +/** + Sends an 32-bit value to a POST and associated ASCII string. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + If Description is not NULL, then the ASCII string specified by Description is + also passed to the handler that displays the POST card value. Some + implementations of this library function may perform I/O operations directly + to a POST card device. Other implementations may send Value to ReportStatusCode(), + and the status code reporting mechanism will eventually display the 32-bit + value on the status reporting device. + + PostCodeWithDescription()must actively prevent recursion. If + PostCodeWithDescription() is called while processing another any other Report + Status Code Library function, then PostCodeWithDescription() must return Value + immediately. + + @param Value The 32-bit value to write to the POST card. + @param Description Pointer to an ASCII string that is a description of the + POST code value. This is an optional parameter that may + be NULL. + + @return Value + +**/ +UINT32 +EFIAPI +PostCodeWithDescription ( + IN UINT32 Value, + IN CONST CHAR8 *Description OPTIONAL + ) +{ + DEBUG((EFI_D_INFO, "POST %08x - %s\n", Value, Description)); + IoWrite8 (0x80, (UINT8)(Value)); + return Value; +} + + +/** + Returns TRUE if POST Codes are enabled. + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportPostCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if POST code descriptions are enabled. + + This function returns TRUE if the + REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED bit of + PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED + bit of PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED + bit of PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportPostCodeDescriptionEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED) != 0); +} diff --git a/MdePkg/Library/DxeReportStatusCodeLib/ReportStatusCodeLib.c b/MdePkg/Library/DxeReportStatusCodeLib/ReportStatusCodeLib.c new file mode 100644 index 0000000000..9edb753137 --- /dev/null +++ b/MdePkg/Library/DxeReportStatusCodeLib/ReportStatusCodeLib.c @@ -0,0 +1,585 @@ +/** @file + Report Status Code Library for DXE Phase. + + Copyright (c) 2006, 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. + +**/ + +// +// Global pointer to the Status Code Protocol +// +static EFI_STATUS_CODE_PROTOCOL *gStatusCode = NULL; + +/** + Internal worker function that reports a status code through the Status Code Protocol + + This function checks to see if a Status Code Protocol is present in the handle + database. If a Status Code Protocol is not present, then EFI_UNSUPPORTED is + returned. If a Status Code Protocol is present, then it is cached in gStatusCode, + and the ReportStatusCode() service of the Status Code Protocol is called passing in + Type, Value, Instance, CallerId, and Data. The result of this call is returned. + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. This is an optional parameter that may be + NULL. + @param Data Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to report the status code. + @retval EFI_UNSUPPORTED Status Code Protocol is not available. + +**/ +EFI_STATUS +InternalReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + EFI_STATUS Status; + + // + // If gStatusCode is NULL, then see if a Status Code Protocol instance is present + // in the handle database. + // + if (gStatusCode == NULL) { + Status = gBS->LocateProtocol (&gEfiStatusCodeRuntimeProtocolGuid, NULL, (VOID **)&gStatusCode); + if (EFI_ERROR (Status) || gStatusCode == NULL) { + return EFI_UNSUPPORTED; + } + } + + // + // A Status Code Protocol is present in the handle database, so pass in all the + // parameters to the ReportStatusCode() service of the Status Code Protocol + // + return gStatusCode->ReportStatusCode (Type, Value, Instance, CallerId, Data); +} + + +/** + Computes and returns the size, in bytes, of a device path. + + @param DevicePath A pointer to a device path. + + @return The size, in bytes, of DevicePath. + +**/ +UINTN +InternalReportStatusCodeDevicePathSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = DevicePath; + while (!EfiIsDevicePathEnd (DevicePath)) { + DevicePath = EfiNextDevicePathNode (DevicePath); + } + + // + // Subtract the start node from the end node and add in the size of the end node + // + return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath); +} + + +/** + Converts a status code to an 8-bit POST code value. + + Converts the status code specified by CodeType and Value to an 8-bit POST code + and returns the 8-bit POST code in PostCode. If CodeType is an + EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode + are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits + 24..26 of Value., and TRUE is returned. Otherwise, FALSE is returned. + + If PostCode is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param PostCode A pointer to the 8-bit POST code value to return. + + @retval TRUE The status code specified by CodeType and Value was converted + to an 8-bit POST code and returned in PostCode. + @retval FALSE The status code specified by CodeType and Value could not be + converted to an 8-bit POST code value. + +**/ +BOOLEAN +EFIAPI +CodeTypeToPostCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + OUT UINT8 *PostCode + ) +{ + // + // If PostCode is NULL, then ASSERT() + // + ASSERT (PostCode != NULL); + + // + // Convert Value to an 8 bit post code + // + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || + ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ) { + *PostCode = (UINT8) (((Value & EFI_STATUS_CODE_CLASS_MASK) >> 24) << 5); + *PostCode |= (UINT8) (((Value & EFI_STATUS_CODE_SUBCLASS_MASK) >> 16) & 0x1f); + return TRUE; + } + return FALSE; +} + + +/** + Extracts ASSERT() information from a status code structure. + + Converts the status code specified by CodeType, Value, and Data to the ASSERT() + arguments specified by Filename, Description, and LineNumber. If CodeType is + an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and + Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract + Filename, Description, and LineNumber from the optional data area of the + status code buffer specified by Data. The optional data area of Data contains + a Null-terminated ASCII string for the FileName, followed by a Null-terminated + ASCII string for the Description, followed by a 32-bit LineNumber. If the + ASSERT() information could be extracted from Data, then return TRUE. + Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If Filename is NULL, then ASSERT(). + If Description is NULL, then ASSERT(). + If LineNumber is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param Data Pointer to status code data buffer. + @param Filename Pointer to the source file name that generated the ASSERT(). + @param Description Pointer to the description of the ASSERT(). + @param LineNumber Pointer to source line number that generated the ASSERT(). + + @retval TRUE The status code specified by CodeType, Value, and Data was + converted ASSERT() arguments specified by Filename, Description, + and LineNumber. + @retval FALSE The status code specified by CodeType, Value, and Data could + not be converted to ASSERT() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractAssertInfo ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_STATUS_CODE_DATA *Data, + OUT CHAR8 **Filename, + OUT CHAR8 **Description, + OUT UINT32 *LineNumber + ) +{ + EFI_DEBUG_ASSERT_DATA *AssertData; + + ASSERT (Data != NULL); + ASSERT (Filename != NULL); + ASSERT (Description != NULL); + ASSERT (LineNumber != NULL); + + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) && + ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) && + ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) { + AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1); + *Filename = (CHAR8 *)(AssertData + 1); + *Description = *Filename + AsciiStrLen (*Filename) + 1; + *LineNumber = AssertData->LineNumber; + return TRUE; + } + return FALSE; +} + + +/** + Extracts DEBUG() information from a status code structure. + + Converts the status code specified by Data to the DEBUG() arguments specified + by ErrorLevel, Marker, and Format. If type GUID in Data is + EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and + Format from the optional data area of the status code buffer specified by Data. + The optional data area of Data contains a 32-bit ErrorLevel followed by Marker + which is 12 UINTN parameters, followed by a Null-terminated ASCII string for + the Format. If the DEBUG() information could be extracted from Data, then + return TRUE. Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If ErrorLevel is NULL, then ASSERT(). + If Marker is NULL, then ASSERT(). + If Format is NULL, then ASSERT(). + + @param Data Pointer to status code data buffer. + @param ErrorLevel Pointer to error level mask for a debug message. + @param Marker Pointer to the variable argument list associated with Format. + @param Format Pointer to a Null-terminated ASCII format string of a + debug message. + + @retval TRUE The status code specified by Data was converted DEBUG() arguments + specified by ErrorLevel, Marker, and Format. + @retval FALSE The status code specified by Data could not be converted to + DEBUG() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractDebugInfo ( + IN EFI_STATUS_CODE_DATA *Data, + OUT UINT32 *ErrorLevel, + OUT VA_LIST *Marker, + OUT CHAR8 **Format + ) +{ + EFI_DEBUG_INFO *DebugInfo; + + ASSERT (Data != NULL); + ASSERT (ErrorLevel != NULL); + ASSERT (Marker != NULL); + ASSERT (Format != NULL); + + // + // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE + // + if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) { + return FALSE; + } + + // + // Retrieve the debug information from the status code record + // + DebugInfo = (EFI_DEBUG_INFO *)(Data + 1); + + *ErrorLevel = DebugInfo->ErrorLevel; + + // + // The first 12 * UINTN bytes of the string are really an + // argument stack to support varargs on the Format string. + // + *Marker = (VA_LIST) (DebugInfo + 1); + *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12); + + return TRUE; +} + + +/** + Reports a status code. + + Reports the status code specified by the parameters Type and Value. Status + code also require an instance, caller ID, and extended data. This function + passed in a zero instance, NULL extended data, and a caller ID of + gEfiCallerIdGuid, which is the GUID for the module. + + ReportStatusCode()must actively prevent recusrsion. If ReportStatusCode() + is called while processing another any other Report Status Code Library function, + then ReportStatusCode() must return immediately. + + @param Type Status code type. + @param Value Status code value. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_DEVICE_ERROR There status code could not be reported due to a + device error. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value + ) +{ + return InternalReportStatusCode (Type, Value, 0, &gEfiCallerIdGuid, NULL); +} + + +/** + Reports a status code with a Device Path Protocol as the extended data. + + Allocates and fills in the extended data section of a status code with the + Device Path Protocol specified by DevicePath. This function is responsible + for allocating a buffer large enough for the standard header and the device + path. The standard header is filled in with a GUID of + gEfiStatusCodeSpecificDataGuid. The status code is reported with a zero + instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithDevicePath()must actively prevent recursion. If + ReportStatusCodeWithDevicePath() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithDevicePath() + must return EFI_DEVICE_ERROR immediately. + + If DevicePath is NULL, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param DevicePath Pointer to the Device Path Protocol to be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by DevicePath. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithDevicePath ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ASSERT (DevicePath != NULL); + return ReportStatusCodeWithExtendedData ( + Type, + Value, + (VOID *)DevicePath, + InternalReportStatusCodeDevicePathSize (DevicePath) + ); +} + + +/** + Reports a status code with an extended data buffer. + + Allocates and fills in the extended data section of a status code with the + extended data specified by ExtendedData and ExtendedDataSize. ExtendedData + is assumed to be one of the data structures specified in Related Definitions. + These data structure do not have the standard header, so this function is + responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled + in with a GUID of gEfiStatusCodeSpecificDataGuid. The status code is reported + with a zero instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithExtendedData()must actively prevent recursion. If + ReportStatusCodeWithExtendedData() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithExtendedData() + must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL, then ASSERT(). + If ExtendedDataSize is 0, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param ExtendedData Pointer to the extended data buffer to be reported. + @param ExtendedDataSize The size, in bytes, of the extended data buffer to + be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by ExtendedData and ExtendedDataSize. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithExtendedData ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN VOID *ExtendedData, + IN UINTN ExtendedDataSize + ) +{ + ASSERT (ExtendedData != NULL); + ASSERT (ExtendedDataSize != 0); + return ReportStatusCodeEx ( + Type, + Value, + 0, + NULL, + NULL, + ExtendedData, + ExtendedDataSize + ); +} + + +/** + Reports a status code with full parameters. + + The function reports a status code. If ExtendedData is NULL and ExtendedDataSize + is 0, then an extended data buffer is not reported. If ExtendedData is not + NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. + ExtendedData is assumed not have the standard status code header, so this function + is responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled in + with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a + GUID of gEfiStatusCodeSpecificDatauid is used. The status code is reported with + an instance specified by Instance and a caller ID specified by CallerId. If + CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. + + ReportStatusCodeEx()must actively prevent recursion. If ReportStatusCodeEx() + is called while processing another any other Report Status Code Library function, + then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). + If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. If this parameter is NULL, then a caller + ID of gEfiCallerIdGuid is used. + @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. + If this parameter is NULL, then a the status code + standard header is filled in with + gEfiStatusCodeSpecificDataGuid. + @param ExtendedData Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + @param ExtendedDataSize The size, in bytes, of the extended data buffer. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate + the extended data section if it was specified. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeEx ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_GUID *ExtendedDataGuid OPTIONAL, + IN VOID *ExtendedData OPTIONAL, + IN UINTN ExtendedDataSize + ) +{ + EFI_STATUS Status; + EFI_STATUS_CODE_DATA *StatusCodeData; + + ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0))); + ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0))); + + // + // Allocate space for the Status Code Header and its buffer + // + StatusCodeData = NULL; + gBS->AllocatePool (EfiBootServicesData, sizeof (EFI_STATUS_CODE_DATA) + ExtendedDataSize, (VOID **)&StatusCodeData); + if (StatusCodeData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Fill in the extended data header + // + StatusCodeData->HeaderSize = sizeof (EFI_STATUS_CODE_DATA); + StatusCodeData->Size = (UINT16)ExtendedDataSize; + if (ExtendedDataGuid == NULL) { + ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid; + } + CopyGuid (&StatusCodeData->Type, ExtendedDataGuid); + + // + // Fill in the extended data buffer + // + CopyMem (StatusCodeData + 1, ExtendedData, ExtendedDataSize); + + // + // Report the status code + // + if (CallerId == NULL) { + CallerId = &gEfiCallerIdGuid; + } + Status = InternalReportStatusCode (Type, Value, Instance, CallerId, StatusCodeData); + + // + // Free the allocated buffer + // + gBS->FreePool (StatusCodeData); + + return Status; +} + + +/** + Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportProgressCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if status codes of type EFI_ERROR_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportErrorCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportDebugCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} diff --git a/MdePkg/Library/DxeReportStatusCodeLib/build.xml b/MdePkg/Library/DxeReportStatusCodeLib/build.xml new file mode 100644 index 0000000000..bc4f59fc1d --- /dev/null +++ b/MdePkg/Library/DxeReportStatusCodeLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c b/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c new file mode 100644 index 0000000000..f130b207e5 --- /dev/null +++ b/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.c @@ -0,0 +1,36 @@ +/** @file + DXE Library. + + Copyright (c) 2006, 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. + + Module Name: DxeServicesTableLib.c + +**/ + + + +EFI_DXE_SERVICES *gDS = NULL; + +/** +**/ +EFI_STATUS +DxeServicesTableLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = EfiGetSystemConfigurationTable (&gEfiDxeServicesTableGuid, (VOID **) &gDS); + ASSERT_EFI_ERROR (Status); + ASSERT (gDS != NULL); + + return Status; +} diff --git a/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.mbd b/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.mbd new file mode 100644 index 0000000000..6f818e0e33 --- /dev/null +++ b/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.mbd @@ -0,0 +1,30 @@ + + + + + DxeServicesTableLib + baa1baa3-0a8d-402c-8042-985115fae953 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-31 13:35 + + diff --git a/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.msa b/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.msa new file mode 100644 index 0000000000..9912255c7b --- /dev/null +++ b/MdePkg/Library/DxeServicesTableLib/DxeServicesTableLib.msa @@ -0,0 +1,55 @@ + + + + + DxeServicesTableLib + DXE_DRIVER + LIBRARY + baa1baa3-0a8d-402c-8042-985115fae953 + EDK_RELEASE_VERSION 0x00020000 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-09 23:12 + 2006-03-31 13:35 + + + DxeServicesTableLib + DebugLib + UefiLib + + + DxeServicesTableLib.c + + + MdePkg + + + + DxeServicesTable + + + + + DxeServicesTableLibConstructor + + + diff --git a/MdePkg/Library/DxeServicesTableLib/build.xml b/MdePkg/Library/DxeServicesTableLib/build.xml new file mode 100644 index 0000000000..bf830f631e --- /dev/null +++ b/MdePkg/Library/DxeServicesTableLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c b/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c new file mode 100644 index 0000000000..4c888370eb --- /dev/null +++ b/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.c @@ -0,0 +1,168 @@ +/** @file +Implementation of SmBusLib class library for PEI phase. + +Copyright (c) 2006, 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. + + +Module Name: DxeSmbusLib.c + +**/ + +#include "InternalSmbusLib.h" + +// +// Globle varible to cache pointer to Smbus protocol. +// +STATIC EFI_SMBUS_HC_PROTOCOL *mSmbus = NULL; + +/** + The constructor function caches the pointer to Smbus protocol. + + The constructor function locates Smbus protocol from protocol database. + It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +SmbusLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEfiCpuIoProtocolGuid, + NULL, + (VOID**) &mSmbus + ); + ASSERT_EFI_ERROR (Status); + ASSERT (mSmbus != NULL); + + return Status; +} + +/** + Executes an SMBus operation to an SMBus controller. + + This function provides a standard way to execute Smbus script + as defined in the SmBus Specification. The data can either be of + the Length byte, word, or a block of data. + + @param SmbusOperation Signifies which particular SMBus hardware protocol instance that it will use to + execute the SMBus transactions. + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Length Signifies the number of bytes that this operation will do. The maximum number of + bytes can be revision specific and operation specific. + @param Buffer Contains the value of data to execute to the SMBus slave device. Not all operations + require this argument. The length of this buffer is identified by Length. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The actual number of bytes that are executed for this operation.. + +**/ +UINTN +InternalSmBusExec ( + IN EFI_SMBUS_OPERATION SmbusOperation, + IN UINTN SmBusAddress, + IN UINTN Length, + IN VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + RETURN_STATUS ReturnStatus; + EFI_SMBUS_DEVICE_ADDRESS SmbusDeviceAddress; + + SmbusDeviceAddress.SmbusDeviceAddress = SMBUS_LIB_SLAVE_ADDRESS (SmBusAddress); + + ReturnStatus = mSmbus->Execute ( + mSmbus, + SmbusDeviceAddress, + SMBUS_LIB_COMMAND (SmBusAddress), + SmbusOperation, + SMBUS_LIB_PEC (SmBusAddress), + &Length, + Buffer + ); + if (Status != NULL) { + *Status = ReturnStatus; + } + + return Length; +} + +/** + Assigns an SMBUS slave addresses. + + Assigns the SMBUS device specified by Uuid the slave address specified by SmBusAddress. + The status of the executed command is returned. + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Uuid Pointer to the UUID of the device to assign a slave address. + It will assign to all SMBUS slave devices if it is NULL. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +InternalSmBusArpDevice ( + IN UINTN SmBusAddress, + IN CONST GUID *Uuid OPTIONAL + ) +{ + EFI_SMBUS_DEVICE_ADDRESS SmbusDeviceAddress; + + SmbusDeviceAddress.SmbusDeviceAddress = SMBUS_LIB_SLAVE_ADDRESS (SmBusAddress); + return (RETURN_STATUS) mSmbus->ArpDevice ( + mSmbus, + (BOOLEAN) (Uuid == NULL), + (EFI_SMBUS_UDID *) Uuid, + &SmbusDeviceAddress + ); +} + +/** + Retrieves the mapping of all the SMBus devices. + + The GetArpMap() function returns the mapping of all the SMBus devices + that are enumerated by the SMBus host driver. + + @param Length Size of the buffer that contains the SMBus device map. + @param SmbusDeviceMap The pointer to the device map as enumerated by the SMBus controller driver. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +InternalGetArpMap ( + OUT UINTN *Length, + OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap + ) +{ + return (RETURN_STATUS) mSmbus->GetArpMap (mSmbus, Length, SmbusDeviceMap); +} diff --git a/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.mbd b/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.mbd new file mode 100644 index 0000000000..6522eacc1a --- /dev/null +++ b/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.mbd @@ -0,0 +1,30 @@ + + + + + DxeSmbusLib + 91B68627-0B5D-4d32-8F1C-16CD242A8C2A + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-04-17 22:31 + 2006-04-17 23:17 + + diff --git a/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.msa b/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.msa new file mode 100644 index 0000000000..9507c070a2 --- /dev/null +++ b/MdePkg/Library/DxeSmbusLib/DxeSmbusLib.msa @@ -0,0 +1,54 @@ + + + + + DxeSmbusLib + DXE_DRIVER + LIBRARY + 07720769-A7D0-4a8d-BE41-71CC18EB3338 + 0 + SmBus Library Instance implemented with SmBus Protocol. + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-17 22:31 + + + SmbusLib + DebugLib + UefiBootServicesTableLib + BaseMemoryLib + + + DxeSmbusLib.c + SmbusLib.c + + + MdePkg + + + Smbus + + + + SmbusLibConstructor + + + diff --git a/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h b/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h new file mode 100644 index 0000000000..3c0b597fc5 --- /dev/null +++ b/MdePkg/Library/DxeSmbusLib/InternalSmbusLib.h @@ -0,0 +1,112 @@ +/** @file +Internal header file for Smbus library. + +Copyright (c) 2006, 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. + + +Module Name: SmbusLib.c + +**/ + +#ifndef __INTERNAL_SMBUS_LIB_H +#define __INTERNAL_SMBUS_LIB_H + +#define SMBUS_LIB_PEC(SmBusAddress) ((BOOLEAN) ((SmBusAddress) & 0x01)) +#define SMBUS_LIB_SLAVE_ADDRESS(SmBusAddress) (((SmBusAddress) >> 1) & 0x7f) +#define SMBUS_LIB_COMMAND(SmBusAddress) (((SmBusAddress) >> 8) & 0xff) +#define SMBUS_LIB_LENGTH(SmBusAddress) (((SmBusAddress) >> 16) & 0x1f) +#define SMBUS_LIB_RESEARVED(SmBusAddress) (((SmBusAddress) >> 21)) + +// +// Declaration for internal functions +// +/** + Executes an SMBus operation to an SMBus controller. + + This function provides a standard way to execute Smbus script + as defined in the SmBus Specification. The data can either be of + the Length byte, word, or a block of data. + + @param SmbusOperation Signifies which particular SMBus hardware protocol instance that it will use to + execute the SMBus transactions. + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Length Signifies the number of bytes that this operation will do. The maximum number of + bytes can be revision specific and operation specific. + @param Buffer Contains the value of data to execute to the SMBus slave device. Not all operations + require this argument. The length of this buffer is identified by Length. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The actual number of bytes that are executed for this operation.. + +**/ +UINTN +InternalSmBusExec ( + IN EFI_SMBUS_OPERATION SmbusOperation, + IN UINTN SmBusAddress, + IN UINTN Length, + IN VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + Assigns an SMBUS slave addresses. + + Assigns the SMBUS device specified by Uuid the slave address specified by SmBusAddress. + The status of the executed command is returned. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Uuid Pointer to the UUID of the device to assign a slave address. + It will assign to all SMBUS slave devices if it is NULL. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +InternalSmBusArpDevice ( + IN UINTN SmBusAddress, + IN CONST GUID *Uuid OPTIONAL + ); + +/** + Retrieves the mapping of all the SMBus devices. + + The GetArpMap() function returns the mapping of all the SMBus devices + that are enumerated by the SMBus host driver. + + @param Length Size of the buffer that contains the SMBus device map. + @param SmbusDeviceMap The pointer to the device map as enumerated by the SMBus controller driver. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +InternalGetArpMap ( + OUT UINTN *Length, + OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap + ); + +#endif diff --git a/MdePkg/Library/DxeSmbusLib/SmbusLib.c b/MdePkg/Library/DxeSmbusLib/SmbusLib.c new file mode 100644 index 0000000000..da29fab5a3 --- /dev/null +++ b/MdePkg/Library/DxeSmbusLib/SmbusLib.c @@ -0,0 +1,597 @@ +/** @file +Implementation of SmBusLib class library for PEI phase. + +Copyright (c) 2006, 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. + + +Module Name: SmbusLib.c + +**/ + +#include "InternalSmbusLib.h" + +/** + Executes an SMBUS quick read command. + + Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + +**/ +VOID +EFIAPI +SmBusQuickRead ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusQuickRead, SmBusAddress, 0, NULL, Status); +} + +/** + Executes an SMBUS quick write command. + + Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + +**/ +BOOLEAN +EFIAPI +SmBusQuickWrite ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusQuickWrite, SmBusAddress, 0, NULL, Status); + // + // Bugbug: Undefined return value in spec + // + return TRUE; +} + +/** + Executes an SMBUS receive byte command. + + Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + The byte received from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte received from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReceiveByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReceiveByte, SmBusAddress, 1, &Byte, Status); + + return Byte; +} + +/** + Executes an SMBUS send byte command. + + Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress. + The byte specified by Value is sent. + Only the SMBUS slave address field of SmBusAddress is required. Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to send. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusSendByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + Byte = Value; + InternalSmBusExec (EfiSmbusSendByte, SmBusAddress, 1, &Byte, Status); + + return Value; +} + +/** + Executes an SMBUS read data byte command. + + Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 8-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte read from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReadDataByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReadByte, SmBusAddress, 1, &Byte, Status); + + return Byte; +} + +/** + Executes an SMBUS write data byte command. + + Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress. + The 8-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusWriteDataByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + Byte = Value; + InternalSmBusExec (EfiSmbusWriteByte, SmBusAddress, 1, &Byte, Status); + + return Value; +} + +/** + Executes an SMBUS read data word command. + + Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte read from the SMBUS. + +**/ +UINT16 +EFIAPI +SmBusReadDataWord ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReadWord, SmBusAddress, 2, &Word, Status); + + return Word; +} + +/** + Executes an SMBUS write data word command. + + Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +SmBusWriteDataWord ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + Word = Value; + InternalSmBusExec (EfiSmbusWriteWord, SmBusAddress, 2, &Word, Status); + + return Value; +} + +/** + Executes an SMBUS process call command. + + Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value returned by the process call command is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The 16-bit value returned by the process call command. + +**/ +UINT16 +EFIAPI +SmBusProcessCall ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusProcessCall, SmBusAddress, 2, &Value, Status); + + return Value; +} + +/** + Executes an SMBUS read block command. + + Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Bytes are read from the SMBUS and stored in Buffer. + The number of bytes read is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller¡¯s responsibility to make sure Buffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is not zero, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes read. + +**/ +UINTN +EFIAPI +SmBusReadBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return InternalSmBusExec (EfiSmbusReadBlock, SmBusAddress, 0x1f, Buffer, Status); +} + +/** + Executes an SMBUS write block command. + + Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from Buffer. + The number of bytes written is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusWriteBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return InternalSmBusExec (EfiSmbusWriteBlock, SmBusAddress, SMBUS_LIB_LENGTH (SmBusAddress), Buffer, Status); +} + +/** + Executes an SMBUS block process call command. + + Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from OutBuffer. Bytes are then read from the SMBUS into InBuffer. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller¡¯s responsibility to make sure InBuffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If OutBuffer is NULL, then ASSERT(). + If InBuffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param OutBuffer Pointer to the buffer of bytes to write to the SMBUS. + @param InBuffer Pointer to the buffer of bytes to read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusBlockProcessCall ( + IN UINTN SmBusAddress, + OUT VOID *OutBuffer, + OUT VOID *InBuffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (InBuffer != NULL); + ASSERT (OutBuffer != NULL); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + // + // BugBug: Not sure whether it's all right. + // + InternalSmBusExec (EfiSmbusWriteBlock, SmBusAddress, SMBUS_LIB_LENGTH (SmBusAddress), OutBuffer, Status); + + return InternalSmBusExec (EfiSmbusReadBlock, SmBusAddress, 1, InBuffer, Status); +} + +/** + Enumerates the SMBUS and assigns slave addresses. + + Executes the SMBUS enumeration algorithm and assigns a valid address to all SMBUS slave devices. + The total number of SMBUS slave devices detected is returned. + The status of the executed command is returned. + If Slave Address in SmBusAddress is not zero, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +EFIAPI +SmBusArpAll ( + IN UINTN SmBusAddress + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_SLAVE_ADDRESS (SmBusAddress) == 0); + + return InternalSmBusArpDevice (SmBusAddress, NULL); +} + +/** + Assigns an SMBUS slave addresses. + + Assigns the SMBUS device specified by Uuid the slave address specified by SmBusAddress. + The status of the executed command is returned. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Uuid Pointer to the UUID of the device to assign a slave address. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +EFIAPI +SmBusArpDevice ( + IN UINTN SmBusAddress, + IN CONST GUID *Uuid + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + + return InternalSmBusArpDevice (SmBusAddress, Uuid); +} + +/** + Retrieves the UUID associated with an SMBUS slave device. + + Retrieves the UUID associated with the slave address specified + by SmBusAddress and returns the UUID in Uuid. + The status of the executed command is returned. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If Uuid is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Uuid Pointer to the UUID retrieved from the SMBUS slave device. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +EFIAPI +SmBusGetUuid ( + IN UINTN SmBusAddress, + OUT GUID *Uuid + ) +{ + UINTN Length; + EFI_SMBUS_DEVICE_MAP *SmBusDeviceMap; + RETURN_STATUS ReturnStatus; + UINTN SmbusDeviceAddress; + UINTN Index; + + ASSERT (Uuid != NULL); + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + + ReturnStatus = InternalGetArpMap (&Length, &SmBusDeviceMap); + if (!RETURN_ERROR (ReturnStatus)) { + SmbusDeviceAddress = SMBUS_LIB_SLAVE_ADDRESS (SmBusAddress); + for (Index = 0; Index < Length; Index++) { + if (SmBusDeviceMap[Index].SmbusDeviceAddress.SmbusDeviceAddress == SmbusDeviceAddress) { + CopyMem (Uuid, &SmBusDeviceMap[Index].SmbusDeviceUdid, sizeof (EFI_SMBUS_UDID)); + break; + } + } + } + + return ReturnStatus; +} diff --git a/MdePkg/Library/DxeSmbusLib/build.xml b/MdePkg/Library/DxeSmbusLib/build.xml new file mode 100644 index 0000000000..2d01f3c300 --- /dev/null +++ b/MdePkg/Library/DxeSmbusLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/DxeSmmDriverEntryPoint/DriverEntryPoint.c b/MdePkg/Library/DxeSmmDriverEntryPoint/DriverEntryPoint.c new file mode 100644 index 0000000000..3439d6da35 --- /dev/null +++ b/MdePkg/Library/DxeSmmDriverEntryPoint/DriverEntryPoint.c @@ -0,0 +1,274 @@ +/** @file + Entry point to a EFI/DXE driver. + +Copyright (c) 2006, 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. + +**/ + +EFI_BOOT_SERVICES *mBS; + +/** + This function returns the size, in bytes, + of the device path data structure specified by DevicePath. + If DevicePath is NULL, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @return The size of a device path in bytes. + +**/ +STATIC +UINTN +EFIAPI +SmmGetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = DevicePath; + while (!EfiIsDevicePathEnd (DevicePath)) { + DevicePath = EfiNextDevicePathNode (DevicePath); + } + + // + // Compute the size and add back in the size of the end device path structure + // + return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL); +} + +/** + This function appends the device path SecondDevicePath + to every device path instance in FirstDevicePath. + + @param FirstDevicePath A pointer to a device path data structure. + + @param SecondDevicePath A pointer to a device path data structure. + + @return A pointer to the new device path is returned. + NULL is returned if space for the new device path could not be allocated from pool. + It is up to the caller to free the memory used by FirstDevicePath and SecondDevicePath + if they are no longer needed. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +SmmAppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath + ) +{ + EFI_STATUS Status; + UINTN Size; + UINTN Size1; + UINTN Size2; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath2; + + ASSERT (FirstDevicePath != NULL && SecondDevicePath != NULL); + + // + // Allocate space for the combined device path. It only has one end node of + // length EFI_DEVICE_PATH_PROTOCOL + // + Size1 = SmmGetDevicePathSize (FirstDevicePath); + Size2 = SmmGetDevicePathSize (SecondDevicePath); + Size = Size1 + Size2 - sizeof (EFI_DEVICE_PATH_PROTOCOL); + + Status = mBS->AllocatePool (EfiBootServicesData, Size, (VOID **) &NewDevicePath); + + if (EFI_SUCCESS == Status) { + mBS->CopyMem ((VOID *) NewDevicePath, (VOID *) FirstDevicePath, Size1); + // + // Over write Src1 EndNode and do the copy + // + DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + (Size1 - sizeof (EFI_DEVICE_PATH_PROTOCOL))); + mBS->CopyMem ((VOID *) DevicePath2, (VOID *) SecondDevicePath, Size2); + } + + return NewDevicePath; +} + +/** + Unload function that is registered in the LoadImage protocol. It un-installs + protocols produced and deallocates pool used by the driver. Called by the core + when unloading the driver. + + @param ImageHandle ImageHandle of the unloaded driver + + @return Status of the ProcessModuleUnloadList. + +**/ +EFI_STATUS +EFIAPI +_DriverUnloadHandler ( + EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + // + // Call the unload handlers for all the modules + // + Status = ProcessModuleUnloadList (ImageHandle); + + // + // If the driver specific unload handler does not return an error, then call all of the + // library destructors. If the unload handler returned an error, then the driver can not be + // unloaded, and the library destructors should not be called + // + if (!EFI_ERROR (Status)) { + ProcessLibraryDestructorList (ImageHandle, gST); + } + + // + // Return the status from the driver specific unload handler + // + return Status; +} + +/** + Enrty point to DXE SMM Driver. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @retval EFI_SUCCESS One or more of the drivers returned a success code. + @retval !EFI_SUCESS The return status from the last driver entry point in the list. + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + EFI_SMM_BASE_PROTOCOL *SmmBase; + BOOLEAN InSmm; + EFI_DEVICE_PATH_PROTOCOL *CompleteFilePath; + EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath; + EFI_HANDLE Handle; + + // + // Cache a pointer to the Boot Services Table + // + mBS = SystemTable->BootServices; + + // + // Retrieve the Loaded Image Protocol + // + Status = mBS->HandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID*)&LoadedImage + ); + ASSERT_EFI_ERROR (Status); + + // + // Retrieve SMM Base Protocol + // + Status = mBS->LocateProtocol ( + &gEfiSmmBaseProtocolGuid, + NULL, + (VOID **) &SmmBase + ); + ASSERT_EFI_ERROR (Status); + + // + // Check to see if we are already in SMM + // + SmmBase->InSmm (SmmBase, &InSmm); + + // + // + // + if (!InSmm) { + // + // Retrieve the Device Path Protocol from the DeviceHandle tha this driver was loaded from + // + Status = mBS->HandleProtocol ( + LoadedImage->DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID*)&ImageDevicePath + ); + ASSERT_EFI_ERROR (Status); + + // + // Build the full device path to the currently execuing image + // + CompleteFilePath = SmmAppendDevicePath (ImageDevicePath, LoadedImage->FilePath); + + // + // Load the image in memory to SMRAM; it will automatically generate the + // SMI. + // + Status = SmmBase->Register (SmmBase, CompleteFilePath, NULL, 0, &Handle, FALSE); + ASSERT_EFI_ERROR (Status); + return Status; + } + + // + // Call constructor for all libraries + // + ProcessLibraryConstructorList (ImageHandle, SystemTable); + + // + // Optionally install the unload handler + // + if (_gDriverUnloadImageCount > 0) { + Status = mBS->HandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + ASSERT_EFI_ERROR (Status); + LoadedImage->Unload = _DriverUnloadHandler; + } + + // + // Call the list of driver entry points + // + Status = ProcessModuleEntryPointList (ImageHandle, SystemTable); + if (EFI_ERROR (Status)) { + ProcessLibraryDestructorList (ImageHandle, SystemTable); + } + + return Status; +} + +/** + Enrty point wrapper of DXE SMM Driver. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @retval EFI_SUCCESS One or more of the drivers returned a success code. + @retval !EFI_SUCESS The return status from the last driver entry point in the list. + +**/ +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return _ModuleEntryPoint (ImageHandle, SystemTable); +} diff --git a/MdePkg/Library/DxeSmmDriverEntryPoint/DxeSmmDriverEntryPoint.mbd b/MdePkg/Library/DxeSmmDriverEntryPoint/DxeSmmDriverEntryPoint.mbd new file mode 100644 index 0000000000..b9d9ed2e39 --- /dev/null +++ b/MdePkg/Library/DxeSmmDriverEntryPoint/DxeSmmDriverEntryPoint.mbd @@ -0,0 +1,29 @@ + + + + + DxeSmmDriverEntryPoint + 79C5C7B7-1083-42a6-AD15-2A4E7C4274D7 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-27 17:32 + + diff --git a/MdePkg/Library/DxeSmmDriverEntryPoint/DxeSmmDriverEntryPoint.msa b/MdePkg/Library/DxeSmmDriverEntryPoint/DxeSmmDriverEntryPoint.msa new file mode 100644 index 0000000000..ed4a9bed36 --- /dev/null +++ b/MdePkg/Library/DxeSmmDriverEntryPoint/DxeSmmDriverEntryPoint.msa @@ -0,0 +1,50 @@ + + + + + DxeSmmDriverEntryPoint + DXE_SMM_DRIVER + LIBRARY + 79C5C7B7-1083-42a6-AD15-2A4E7C4274D7 + EDK_RELEASE_VERSION 0x00020000 + Component description file for the entry point to a EFI/DXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-27 17:32 + + + DxeSmmDriverEntryPoint + UefiBootServicesTableLib + DebugLib + BaseLib + + + DriverEntryPoint.c + + + MdePkg + + + DevicePath + SmmBase + LoadedImage + + diff --git a/MdePkg/Library/DxeSmmDriverEntryPoint/build.xml b/MdePkg/Library/DxeSmmDriverEntryPoint/build.xml new file mode 100644 index 0000000000..6105184eca --- /dev/null +++ b/MdePkg/Library/DxeSmmDriverEntryPoint/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/HiiLib/HiiLib.c b/MdePkg/Library/HiiLib/HiiLib.c new file mode 100644 index 0000000000..d7fad9fd45 --- /dev/null +++ b/MdePkg/Library/HiiLib/HiiLib.c @@ -0,0 +1,62 @@ +/** @file + HII Library implementation that uses DXE protocols and services. + + Copyright (c) 2006, 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. + + Module Name: HiiLib.c + +**/ + +/** + This function allocates pool for an EFI_HII_PACKAGES structure + with enough space for the variable argument list of package pointers. + The allocated structure is initialized using NumberOfPackages, Guid, + and the variable length argument list of package pointers. + + @param NumberOfPackages The number of HII packages to prepare. + @param Guid Package GUID. + + @return The allocated and initialized packages. + +**/ +EFI_HII_PACKAGES * +EFIAPI +PreparePackages ( + IN UINTN NumberOfPackages, + IN CONST EFI_GUID *Guid OPTIONAL, + ... + ) +{ + VA_LIST Args; + EFI_HII_PACKAGES *HiiPackages; + VOID **Package; + UINTN Index; + + ASSERT (NumberOfPackages > 0); + + HiiPackages = AllocateZeroPool (sizeof (EFI_HII_PACKAGES) + NumberOfPackages * sizeof (VOID *)); + ASSERT (HiiPackages != NULL); + + HiiPackages->GuidId = (EFI_GUID *) Guid; + HiiPackages->NumberOfPackages = NumberOfPackages; + Package = (VOID **) (((UINT8 *) HiiPackages) + sizeof (EFI_HII_PACKAGES)); + + VA_START (Args, Guid); + + for (Index = 0; Index < NumberOfPackages; Index++) { + *Package = VA_ARG (Args, VOID *); + Package++; + } + + VA_END (Args); + + return HiiPackages; + +} diff --git a/MdePkg/Library/HiiLib/HiiLib.mbd b/MdePkg/Library/HiiLib/HiiLib.mbd new file mode 100644 index 0000000000..4a681fbb7e --- /dev/null +++ b/MdePkg/Library/HiiLib/HiiLib.mbd @@ -0,0 +1,30 @@ + + + + + HiiLib + 1e2c4c2e-67e6-4e57-b3ae-cf5a5af72c2c + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-17 09:00 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/HiiLib/HiiLib.msa b/MdePkg/Library/HiiLib/HiiLib.msa new file mode 100644 index 0000000000..bcd76aab36 --- /dev/null +++ b/MdePkg/Library/HiiLib/HiiLib.msa @@ -0,0 +1,45 @@ + + + + + HiiLib + DXE_DRIVER + LIBRARY + 1e2c4c2e-67e6-4e57-b3ae-cf5a5af72c2c + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2006, 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. + + 0 + 2006-03-17 09:00 + 2006-03-19 15:17 + + + HiiLib + DebugLib + MemoryAllocationLib + + + HiiLib.c + + + MdePkg + + diff --git a/MdePkg/Library/HiiLib/build.xml b/MdePkg/Library/HiiLib/build.xml new file mode 100644 index 0000000000..d48a5576d8 --- /dev/null +++ b/MdePkg/Library/HiiLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c new file mode 100644 index 0000000000..d44725a728 --- /dev/null +++ b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.c @@ -0,0 +1,51 @@ +/** @file + Entry point to a the PEI Core. + +Copyright (c) 2006, 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. + +**/ + +/** + Enrty point to PEI core. + + @param PeiStartupDescriptor Pointer of start up information. + + @return Status returned by entry points of core and drivers. + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +{ + // + // Call the PEI Core entry point + // + return ProcessModuleEntryPointList (PeiStartupDescriptor, NULL); +} + + +/** + Wrapper of enrty point to PEI core. + + @param PeiStartupDescriptor Pointer of start up information. + + @return Status returned by entry points of core and drivers. + +**/ +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor + ) +{ + return _ModuleEntryPoint (PeiStartupDescriptor); +} diff --git a/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.mbd b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.mbd new file mode 100644 index 0000000000..8739972296 --- /dev/null +++ b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.mbd @@ -0,0 +1,30 @@ + + + + + PeiCoreEntryPoint + b3b0654a-969d-4096-86cb-27e262a02083 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.msa b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.msa new file mode 100644 index 0000000000..83d6a18399 --- /dev/null +++ b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.msa @@ -0,0 +1,43 @@ + + + + + PeiCoreEntryPoint + PEI_CORE + LIBRARY + b3b0654a-969d-4096-86cb-27e262a02083 + 0 + Component description file for the entry point to the PEI Core + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + PeiCoreEntryPoint + + + PeiCoreEntryPoint.c + + + MdePkg + + diff --git a/MdePkg/Library/PeiCoreEntryPoint/build.xml b/MdePkg/Library/PeiCoreEntryPoint/build.xml new file mode 100644 index 0000000000..da71288b5b --- /dev/null +++ b/MdePkg/Library/PeiCoreEntryPoint/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiCoreLib/PeiCoreLib.c b/MdePkg/Library/PeiCoreLib/PeiCoreLib.c new file mode 100644 index 0000000000..70c4d64eb3 --- /dev/null +++ b/MdePkg/Library/PeiCoreLib/PeiCoreLib.c @@ -0,0 +1,376 @@ +/** @file + PEI Library. + + Copyright (c) 2006, 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. + + Module Name: PeiCoreLib.c + +**/ + +/** + This service enables a given PEIM to register an interface into the PEI Foundation. + + @param PpiList A pointer to the list of interfaces that the caller shall install. + + @retval EFI_SUCCESS The interface was successfully installed. + @retval EFI_INVALID_PARAMETER The PpiList pointer is NULL. + @retval EFI_INVALID_PARAMETER Any of the PEI PPI descriptors in the list do not have + the EFI_PEI_PPI_DESCRIPTOR_PPI bit set in the Flags field. + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + +**/ +EFI_STATUS +EFIAPI +PeiCoreInstallPpi ( + IN EFI_PEI_PPI_DESCRIPTOR *PpiList + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->InstallPpi (PeiServices, PpiList); +} + +/** + This service enables PEIMs to replace an entry in the PPI database with an alternate entry. + + @param OldPpi Pointer to the old PEI PPI Descriptors. + @param NewPpi Pointer to the new PEI PPI Descriptors. + + @retval EFI_SUCCESS The interface was successfully installed. + @retval EFI_INVALID_PARAMETER The OldPpi or NewPpi is NULL. + @retval EFI_INVALID_PARAMETER Any of the PEI PPI descriptors in the list do not have + the EFI_PEI_PPI_DESCRIPTOR_PPI bit set in the Flags field. + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + @retval EFI_NOT_FOUND The PPI for which the reinstallation was requested has not been installed. + +**/ +EFI_STATUS +EFIAPI +PeiCoreReinstallPpi ( + IN EFI_PEI_PPI_DESCRIPTOR *OldPpi, + IN EFI_PEI_PPI_DESCRIPTOR *NewPpi + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->ReInstallPpi (PeiServices, OldPpi, NewPpi); +} + +/** + This service enables PEIMs to discover a given instance of an interface. + + @param Guid A pointer to the GUID whose corresponding interface needs to be found. + @param Instance The N-th instance of the interface that is required. + @param PpiDescriptor A pointer to instance of the EFI_PEI_PPI_DESCRIPTOR. + @param Ppi A pointer to the instance of the interface. + + @retval EFI_SUCCESS The interface was successfully returned. + @retval EFI_NOT_FOUND The PPI descriptor is not found in the database. + +**/ +EFI_STATUS +EFIAPI +PeiCoreLocatePpi ( + IN EFI_GUID *Guid, + IN UINTN Instance, + IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, + IN OUT VOID **Ppi + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->LocatePpi (PeiServices, Guid, Instance, PpiDescriptor, Ppi); +} + +/** + This service enables PEIMs to register a given service to be invoked + when another service is installed or reinstalled. + + @param NotifyList A pointer to the list of notification interfaces that the caller shall install. + + @retval EFI_SUCCESS The interface was successfully installed. + @retval EFI_INVALID_PARAMETER The NotifyList pointer is NULL. + @retval EFI_INVALID_PARAMETER Any of the PEI notify descriptors in the list do not have + the EFI_PEI_PPI_DESCRIPTOR_NOTIFY_TYPES bit set in the Flags field. + @retval EFI_OUT_OF_RESOURCES There is no additional space in the PPI database. + +**/ +EFI_STATUS +EFIAPI +PeiCoreNotifyPpi ( + IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyList + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->NotifyPpi (PeiServices, NotifyList); +} + +/** + This service enables PEIMs to ascertain the present value of the boot mode. + + @param BootMode A pointer to contain the value of the boot mode. + + @retval EFI_SUCCESS The boot mode was returned successfully. + @retval EFI_INVALID_PARAMETER BootMode is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiCoreGetBootMode ( + IN OUT EFI_BOOT_MODE *BootMode + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->GetBootMode (PeiServices, BootMode); +} + +/** + This service enables PEIMs to update the boot mode variable. + + @param BootMode The value of the boot mode to set. + + @retval EFI_SUCCESS The value was successfully updated + +**/ +EFI_STATUS +EFIAPI +PeiCoreSetBootMode ( + IN EFI_BOOT_MODE BootMode + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->SetBootMode (PeiServices, BootMode); +} + +/** + This service enables a PEIM to ascertain the address of the list of HOBs in memory. + + @param HobList A pointer to the list of HOBs that the PEI Foundation will initialize. + + @retval EFI_SUCCESS The list was successfully returned. + @retval EFI_NOT_AVAILABLE_YET The HOB list is not yet published. + +**/ +EFI_STATUS +EFIAPI +PeiCoreGetHobList ( + IN OUT VOID **HobList + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->GetHobList (PeiServices, HobList); +} + +/** + This service enables PEIMs to create various types of HOBs. + + @param Type The type of HOB to be installed. + @param Length The length of the HOB to be added. + @param Hob The address of a pointer that will contain the HOB header. + + @retval EFI_SUCCESS The HOB was successfully created. + @retval EFI_OUT_OF_RESOURCES There is no additional space for HOB creation. + +**/ +EFI_STATUS +EFIAPI +PeiCoreCreateHob ( + IN UINT16 Type, + IN UINT16 Length, + IN OUT VOID **Hob + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->CreateHob (PeiServices, Type, Length, Hob); +} + +/** + This service enables PEIMs to discover additional firmware volumes. + + @param Instance This instance of the firmware volume to find. + The value 0 is the Boot Firmware Volume (BFV). + @param FwVolHeader Pointer to the firmware volume header of the volume to return. + + @retval EFI_SUCCESS The volume was found. + @retval EFI_NOT_FOUND The volume was not found. + @retval EFI_INVALID_PARAMETER FwVolHeader is NULL. + +**/ +EFI_STATUS +EFIAPI +PeiCoreFfsFindNextVolume ( + IN UINTN Instance, + IN OUT EFI_FIRMWARE_VOLUME_HEADER **FwVolHeader + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->FfsFindNextVolume (PeiServices, Instance, FwVolHeader); +} + +/** + This service enables PEIMs to discover additional firmware files. + + @param SearchType A filter to find files only of this type. + @param FwVolHeader Pointer to the firmware volume header of the volume to search. + This parameter must point to a valid FFS volume. + @param FileHeader Pointer to the current file from which to begin searching. + + @retval EFI_SUCCESS The file was found. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_NOT_FOUND The header checksum was not zero. + +**/ +EFI_STATUS +EFIAPI +PeiCoreFfsFindNextFile ( + IN EFI_FV_FILETYPE SearchType, + IN EFI_FIRMWARE_VOLUME_HEADER *FwVolHeader, + IN OUT EFI_FFS_FILE_HEADER **FileHeader + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->FfsFindNextFile (PeiServices, SearchType, FwVolHeader, FileHeader); +} + +/** + This service enables PEIMs to discover sections of a given type within a valid FFS file. + + @param SearchType The value of the section type to find. + @param FfsFileHeader A pointer to the file header that contains the set of sections to be searched. + @param SectionData A pointer to the discovered section, if successful. + + @retval EFI_SUCCESS The section was found. + @retval EFI_NOT_FOUND The section was not found. + +**/ +EFI_STATUS +EFIAPI +PeiCoreFfsFindSectionData ( + IN EFI_SECTION_TYPE SectionType, + IN EFI_FFS_FILE_HEADER *FfsFileHeader, + IN OUT VOID **SectionData + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->FfsFindSectionData (PeiServices, SectionType, FfsFileHeader, SectionData); +} + +/** + This service enables PEIMs to register the permanent memory configuration + that has been initialized with the PEI Foundation. + + @param MemoryBegin The value of a region of installed memory. + @param MemoryLength The corresponding length of a region of installed memory. + + @retval EFI_SUCCESS The region was successfully installed in a HOB. + @retval EFI_INVALID_PARAMETER MemoryBegin and MemoryLength are illegal for this system. + @retval EFI_OUT_OF_RESOURCES There is no additional space for HOB creation. + +**/ +EFI_STATUS +EFIAPI +PeiCoreInstallPeiMemory ( + IN EFI_PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->InstallPeiMemory (PeiServices, MemoryBegin, MemoryLength); +} + +/** + This service enables PEIMs to allocate memory after the permanent memory has been installed by a PEIM. + + @param MemoryType Type of memory to allocate. + @param Pages Number of pages to allocate. + @param Memory Pointer of memory allocated. + + @retval EFI_SUCCESS The memory range was successfully allocated. + @retval EFI_INVALID_PARAMETER Type is not equal to AllocateAnyPages. + @retval EFI_NOT_AVAILABLE_YET Called with permanent memory not available. + @retval EFI_OUT_OF_RESOURCES The pages could not be allocated. + +**/ +EFI_STATUS +EFIAPI +PeiCoreAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN OUT EFI_PHYSICAL_ADDRESS *Memory + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->AllocatePages (PeiServices, MemoryType, Pages, Memory); +} + +/** + This service allocates memory from the Hand-Off Block (HOB) heap. + + @param Size The number of bytes to allocate from the pool. + @param Buffer If the call succeeds, a pointer to a pointer to the allocated buffer; + undefined otherwise. + + @retval EFI_SUCCESS The allocation was successful + @retval EFI_OUT_OF_RESOURCES There is not enough heap to allocate the requested size. + +**/ +EFI_STATUS +EFIAPI +PeiCoreAllocatePool ( + IN UINTN Size, + OUT VOID **Buffer + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->AllocatePool (PeiServices, Size, Buffer); +} + +/** + This service resets the entire platform, including all processors and devices, and reboots the system. + + @retval EFI_NOT_AVAILABLE_YET The service has not been installed yet. + +**/ +EFI_STATUS +EFIAPI +PeiCoreResetSystem ( + VOID + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->PeiResetSystem (PeiServices); +} diff --git a/MdePkg/Library/PeiCoreLib/PeiCoreLib.mbd b/MdePkg/Library/PeiCoreLib/PeiCoreLib.mbd new file mode 100644 index 0000000000..441a418709 --- /dev/null +++ b/MdePkg/Library/PeiCoreLib/PeiCoreLib.mbd @@ -0,0 +1,30 @@ + + + + + PeiCoreLib + a804239b-4155-446f-acc8-f0825d74908c + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/PeiCoreLib/PeiCoreLib.msa b/MdePkg/Library/PeiCoreLib/PeiCoreLib.msa new file mode 100644 index 0000000000..93a0876cf4 --- /dev/null +++ b/MdePkg/Library/PeiCoreLib/PeiCoreLib.msa @@ -0,0 +1,44 @@ + + + + + PeiCoreLib + PEIM + LIBRARY + a804239b-4155-446f-acc8-f0825d74908c + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + PeiCoreLib + PeiServicesTablePointerLib + + + PeiCoreLib.c + + + MdePkg + + diff --git a/MdePkg/Library/PeiCoreLib/build.xml b/MdePkg/Library/PeiCoreLib/build.xml new file mode 100644 index 0000000000..8f5e86ee84 --- /dev/null +++ b/MdePkg/Library/PeiCoreLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiHobLib/HobLib.c b/MdePkg/Library/PeiHobLib/HobLib.c new file mode 100644 index 0000000000..a06f1690bf --- /dev/null +++ b/MdePkg/Library/PeiHobLib/HobLib.c @@ -0,0 +1,432 @@ +/** @file + HOB Library. + + Copyright (c) 2006, 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. + + Module Name: HobLib.c + +**/ + + + +/** + Returns the pointer to the HOB list. + + None. + + The pointer to the HOB list. + +**/ +VOID * +EFIAPI +GetHobList ( + VOID + ) +{ + EFI_STATUS Status; + VOID *HobList; + + Status = PeiCoreGetHobList (&HobList); + ASSERT_EFI_ERROR (Status); + ASSERT (HobList != NULL); + + return HobList; +} + +/** + This function searches the first instance of a HOB type from the starting HOB pointer. + If there does not exist such HOB type from the starting HOB pointer, it will return NULL. + + @param Type The HOB type to return. + @param HobStart The starting HOB pointer to search from. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextHob ( + IN UINT16 Type, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS Hob; + + ASSERT (HobStart != NULL); + + Hob.Raw = (UINT8 *) HobStart; + // + // Parse the HOB list, stop if end of list or matching type found. + // + while (!END_OF_HOB_LIST (Hob)) { + if (Hob.Header->HobType == Type) { + return Hob.Raw; + } + Hob.Raw = GET_NEXT_HOB (Hob); + } + return NULL; +} + +/** + This function searches the first instance of a HOB type among the whole HOB list. + If there does not exist such HOB type in the HOB list, it will return NULL. + + @param Type The HOB type to return. + + @return The next instance of a HOB type from the starting HOB. + +**/ +VOID * +EFIAPI +GetFirstHob ( + IN UINT16 Type + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextHob (Type, HobList); +} + +/** + This function searches the first instance of a HOB from the starting HOB pointer. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + + @param Guid The GUID to match with in the HOB list. + @param HobStart A pointer to a Guid. + + @return The next instance of the matched GUID HOB from the starting HOB. + +**/ +VOID * +EFIAPI +GetNextGuidHob ( + IN CONST EFI_GUID *Guid, + IN CONST VOID *HobStart + ) +{ + EFI_PEI_HOB_POINTERS GuidHob; + + GuidHob.Raw = (UINT8 *) HobStart; + while ((GuidHob.Raw = GetNextHob (EFI_HOB_TYPE_GUID_EXTENSION, GuidHob.Raw)) != NULL) { + if (CompareGuid (Guid, &GuidHob.Guid->Name)) { + break; + } + GuidHob.Raw = GET_NEXT_HOB (GuidHob); + } + return GuidHob.Raw; +} + +/** + This function searches the first instance of a HOB among the whole HOB list. + Such HOB should satisfy two conditions: + its HOB type is EFI_HOB_TYPE_GUID_EXTENSION and its GUID Name equals to the input Guid. + If there does not exist such HOB from the starting HOB pointer, it will return NULL. + + @param Guid The GUID to match with in the HOB list. + + @return The first instance of the matched GUID HOB among the whole HOB list. + +**/ +VOID * +EFIAPI +GetFirstGuidHob ( + IN CONST EFI_GUID *Guid + ) +{ + VOID *HobList; + + HobList = GetHobList (); + return GetNextGuidHob (Guid, HobList); +} + +/** + Add a new HOB to the HOB List. + + @param Type Type of the new HOB. + @param Length Length of the new HOB to allocate. + + @return The address of new HOB. + +**/ +VOID * +InternalPeiCreateHob ( + IN UINT16 Type, + IN UINT16 Length + ) +{ + EFI_STATUS Status; + VOID *Hob; + + Status = PeiCoreCreateHob (Type, Length, &Hob); + // + // Assume the process of HOB building is always successful. + // + ASSERT_EFI_ERROR (Status); + return Hob; +} + +/** + This function builds a HOB for a loaded PE32 module. + + @param ModuleName The GUID File Name of the module. + @param MemoryAllocationModule The 64 bit physical address of the module. + @param ModuleLength The length of the module in bytes. + @param EntryPoint The 64 bit physical address of the moduleÂ’s entry point. + +**/ +VOID +EFIAPI +BuildModuleHob ( + IN CONST EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +{ + EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE)); + + CopyGuid (&(Hob->MemoryAllocationHeader.Name), &gEfiHobMemoryAllocModuleGuid); + Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; + Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; + Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; + + CopyGuid (&Hob->ModuleName, ModuleName); + Hob->EntryPoint = EntryPoint; +} + +/** + Builds a HOB that describes a chunk of system memory. + + @param ResourceType The type of resource described by this HOB. + @param ResourceAttribute The resource attributes of the memory described by this HOB. + @param PhysicalStart The 64 bit physical address of memory described by this HOB. + @param NumberOfBytes The length of the memory described by this HOB in bytes. + +**/ +VOID +EFIAPI +BuildResourceDescriptorHob ( + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +{ + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, sizeof (EFI_HOB_RESOURCE_DESCRIPTOR)); + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; + Hob->PhysicalStart = PhysicalStart; + Hob->ResourceLength = NumberOfBytes; +} + +/** + This function builds a customized HOB tagged with a GUID for identification + and returns the start address of GUID HOB data so that caller can fill the customized data. + + @param Guid The GUID to tag the customized HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidHob ( + IN CONST EFI_GUID *Guid, + IN UINTN DataLength + ) +{ + EFI_HOB_GUID_TYPE *Hob; + + // + // Make sure that data length is not too long. + // + ASSERT (DataLength <= (0xffff - sizeof (EFI_HOB_GUID_TYPE))); + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_GUID_EXTENSION, (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength)); + CopyGuid (&Hob->Name, Guid); + return Hob + 1; +} + +/** + This function builds a customized HOB tagged with a GUID for identification, + copies the input data to the HOB data field, and returns the start address of GUID HOB data. + + @param Guid The GUID to tag the customized HOB. + @param Data The data to be copied into the data field of the GUID HOB. + @param DataLength The size of the data payload for the GUID HOB. + + @return The start address of GUID HOB data. + +**/ +VOID * +EFIAPI +BuildGuidDataHob ( + IN CONST EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +{ + VOID *HobData; + + HobData = BuildGuidHob (Guid, DataLength); + + return CopyMem (HobData, Data, DataLength); +} + +/** + Builds a Firmware Volume HOB. + + @param BaseAddress The base address of the Firmware Volume. + @param Length The size of the Firmware Volume in bytes. + +**/ +VOID +EFIAPI +BuildFvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_FIRMWARE_VOLUME *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_FV, sizeof (EFI_HOB_FIRMWARE_VOLUME)); + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +} + +/** + Builds a Capsule Volume HOB. + + @param BaseAddress The base address of the Capsule Volume. + @param Length The size of the Capsule Volume in bytes. + +**/ +VOID +EFIAPI +BuildCvHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_CAPSULE_VOLUME *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_CV, sizeof (EFI_HOB_CAPSULE_VOLUME)); + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; +} + +/** + Builds a HOB for the CPU. + + @param SizeOfMemorySpace The maximum physical memory addressability of the processor. + @param SizeOfIoSpace The maximum physical I/O addressability of the processor. + +**/ +VOID +EFIAPI +BuildCpuHob ( + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +{ + EFI_HOB_CPU *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_CPU, sizeof (EFI_HOB_CPU)); + + Hob->SizeOfMemorySpace = SizeOfMemorySpace; + Hob->SizeOfIoSpace = SizeOfIoSpace; +} + +/** + Builds a HOB for the Stack. + + @param BaseAddress The 64 bit physical address of the Stack. + @param Length The length of the stack in bytes. + +**/ +VOID +EFIAPI +BuildStackHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +{ + EFI_HOB_MEMORY_ALLOCATION_STACK *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK)); + + CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocStackGuid); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = EfiConventionalMemory; +} + +/** + Builds a HOB for the BSP store. + + @param BaseAddress The 64 bit physical address of the BSP. + @param Length The length of the BSP store in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildBspStoreHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION_BSP_STORE)); + + CopyGuid (&(Hob->AllocDescriptor.Name), &gEfiHobMemoryAllocBspStoreGuid); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; +} + +/** + Builds a HOB for the memory allocation. + + @param BaseAddress The 64 bit physical address of the memory. + @param Length The length of the memory allocation in bytes. + @param MemoryType Type of memory allocated by this HOB. + +**/ +VOID +EFIAPI +BuildMemoryAllocationHob ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +{ + EFI_HOB_MEMORY_ALLOCATION *Hob; + + Hob = InternalPeiCreateHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, sizeof (EFI_HOB_MEMORY_ALLOCATION)); + + ZeroMem (&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID)); + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; +} diff --git a/MdePkg/Library/PeiHobLib/PeiHobLib.mbd b/MdePkg/Library/PeiHobLib/PeiHobLib.mbd new file mode 100644 index 0000000000..2d2f34a4ce --- /dev/null +++ b/MdePkg/Library/PeiHobLib/PeiHobLib.mbd @@ -0,0 +1,30 @@ + + + + + PeiHobLib + 9643128f-ac24-4b3e-b6be-d8849a306153 + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/PeiHobLib/PeiHobLib.msa b/MdePkg/Library/PeiHobLib/PeiHobLib.msa new file mode 100644 index 0000000000..f3385c5f77 --- /dev/null +++ b/MdePkg/Library/PeiHobLib/PeiHobLib.msa @@ -0,0 +1,57 @@ + + + + + PeiHobLib + PEIM + LIBRARY + 9643128f-ac24-4b3e-b6be-d8849a306153 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + HobLib + DebugLib + PeiCoreLib + BaseMemoryLib + + + HobLib.c + + + MdePkg + + + + HobMemoryAllocModule + + + HobMemoryAllocBspStore + + + HobMemoryAllocStack + + + diff --git a/MdePkg/Library/PeiHobLib/build.xml b/MdePkg/Library/PeiHobLib/build.xml new file mode 100644 index 0000000000..b230593d28 --- /dev/null +++ b/MdePkg/Library/PeiHobLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c b/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c new file mode 100644 index 0000000000..48a7477d81 --- /dev/null +++ b/MdePkg/Library/PeiIoLibCpuIo/IoHighLevel.c @@ -0,0 +1,2272 @@ +/** @file + High-level Io/Mmio functions. + + All assertions for bit field operations are handled bit field functions in the + Base Library. + + Copyright (c) 2006, 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. + + Module Name: IoHighLevel.c + + The following IoLib instances share the same version of this file: + + BaseIoLibIntrinsic + DxeIoLibCpuIo + PeiIoLibCpuIo + +**/ + +/** + Reads an 8-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoOr8 ( + IN UINTN Port, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, IoRead8 (Port) | OrData); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND, and writes the result back + to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAnd8 ( + IN UINTN Port, + IN UINT8 AndData + ) +{ + return IoWrite8 (Port, IoRead8 (Port) & AndData); +} + +/** + Reads an 8-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 8-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoAndThenOr8 ( + IN UINTN Port, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 (Port, (IoRead8 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in an 8-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoBitFieldRead8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (IoRead8 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldWrite8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return IoWrite8 ( + Port, + BitFieldWrite8 (IoRead8 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 8-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldOr8 (IoRead8 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 8-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAnd8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return IoWrite8 ( + Port, + BitFieldAnd8 (IoRead8 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit port. + + Reads the 8-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 8-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 8-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT8 +EFIAPI +IoBitFieldAndThenOr8 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return IoWrite8 ( + Port, + BitFieldAndThenOr8 (IoRead8 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoOr16 ( + IN UINTN Port, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, IoRead16 (Port) | OrData); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND, and writes the result back + to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAnd16 ( + IN UINTN Port, + IN UINT16 AndData + ) +{ + return IoWrite16 (Port, IoRead16 (Port) & AndData); +} + +/** + Reads a 16-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 16-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoAndThenOr16 ( + IN UINTN Port, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 (Port, (IoRead16 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 16-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoBitFieldRead16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (IoRead16 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldWrite16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return IoWrite16 ( + Port, + BitFieldWrite16 (IoRead16 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 16-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldOr16 (IoRead16 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 16-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAnd16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return IoWrite16 ( + Port, + BitFieldAnd16 (IoRead16 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit port. + + Reads the 16-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 16-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 16-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT16 +EFIAPI +IoBitFieldAndThenOr16 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return IoWrite16 ( + Port, + BitFieldAndThenOr16 (IoRead16 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoOr32 ( + IN UINTN Port, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) | OrData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND, and writes the result back + to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAnd32 ( + IN UINTN Port, + IN UINT32 AndData + ) +{ + return IoWrite32 (Port, IoRead32 (Port) & AndData); +} + +/** + Reads a 32-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 32-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoAndThenOr32 ( + IN UINTN Port, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 (Port, (IoRead32 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 32-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoBitFieldRead32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (IoRead32 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldWrite32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return IoWrite32 ( + Port, + BitFieldWrite32 (IoRead32 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 32-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldOr32 (IoRead32 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 32-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAnd32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return IoWrite32 ( + Port, + BitFieldAnd32 (IoRead32 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit port. + + Reads the 32-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 32-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 32-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT32 +EFIAPI +IoBitFieldAndThenOr32 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return IoWrite32 ( + Port, + BitFieldAndThenOr32 (IoRead32 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit I/O port, performs a bitwise inclusive OR, and writes the + result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoOr64 ( + IN UINTN Port, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) | OrData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND, and writes the result back + to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAnd64 ( + IN UINTN Port, + IN UINT64 AndData + ) +{ + return IoWrite64 (Port, IoRead64 (Port) & AndData); +} + +/** + Reads a 64-bit I/O port, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, performs a bitwise OR + between the result of the AND operation and the value specified by OrData, + and writes the result to the 64-bit I/O port specified by Port. The value + written to the I/O port is returned. This function must guarantee that all + I/O read and write operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoAndThenOr64 ( + IN UINTN Port, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 (Port, (IoRead64 (Port) & AndData) | OrData); +} + +/** + Reads a bit field of an I/O register. + + Reads the bit field in a 64-bit I/O register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoBitFieldRead64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (IoRead64 (Port), StartBit, EndBit); +} + +/** + Writes a bit field to an I/O register. + + Writes Value to the bit field of the I/O register. The bit field is specified + by the StartBit and the EndBit. All other bits in the destination I/O + register are preserved. The value written to the I/O port is returned. Extra + left bits in Value are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldWrite64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return IoWrite64 ( + Port, + BitFieldWrite64 (IoRead64 (Port), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise OR, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise inclusive OR + between the read result and the value specified by OrData, and writes the + result to the 64-bit I/O port specified by Port. The value written to the I/O + port is returned. This function must guarantee that all I/O read and write + operations are serialized. Extra left bits in OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldOr64 (IoRead64 (Port), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND, and writes the + result back to the bit field in the 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND between + the read result and the value specified by AndData, and writes the result to + the 64-bit I/O port specified by Port. The value written to the I/O port is + returned. This function must guarantee that all I/O read and write operations + are serialized. Extra left bits in AndData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAnd64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return IoWrite64 ( + Port, + BitFieldAnd64 (IoRead64 (Port), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit port, performs a bitwise AND followed by a + bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit port. + + Reads the 64-bit I/O port specified by Port, performs a bitwise AND followed + by a bitwise inclusive OR between the read result and the value specified by + AndData, and writes the result to the 64-bit I/O port specified by Port. The + value written to the I/O port is returned. This function must guarantee that + all I/O read and write operations are serialized. Extra left bits in both + AndData and OrData are stripped. + + If 64-bit I/O port operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Port The I/O port to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with the read value from the I/O port. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the I/O port. + +**/ +UINT64 +EFIAPI +IoBitFieldAndThenOr64 ( + IN UINTN Port, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return IoWrite64 ( + Port, + BitFieldAndThenOr64 (IoRead64 (Port), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioOr8 ( + IN UINTN Address, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, MmioRead8 (Address) | OrData); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND, and writes the result + back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAnd8 ( + IN UINTN Address, + IN UINT8 AndData + ) +{ + return MmioWrite8 (Address, MmioRead8 (Address) & AndData); +} + +/** + Reads an 8-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 8-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioAndThenOr8 ( + IN UINTN Address, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 (Address, (MmioRead8 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in an 8-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioBitFieldRead8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead8 (MmioRead8 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 8-bit register is returned. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldWrite8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 Value + ) +{ + return MmioWrite8 ( + Address, + BitFieldWrite8 (MmioRead8 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 8-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldOr8 (MmioRead8 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 8-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAnd8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAnd8 (MmioRead8 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in an 8-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 8-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 7, then ASSERT(). + If EndBit is greater than 7, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..7. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..7. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioBitFieldAndThenOr8 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT8 AndData, + IN UINT8 OrData + ) +{ + return MmioWrite8 ( + Address, + BitFieldAndThenOr8 (MmioRead8 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioOr16 ( + IN UINTN Address, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, MmioRead16 (Address) | OrData); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND, and writes the result + back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAnd16 ( + IN UINTN Address, + IN UINT16 AndData + ) +{ + return MmioWrite16 (Address, MmioRead16 (Address) & AndData); +} + +/** + Reads a 16-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 16-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioAndThenOr16 ( + IN UINTN Address, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 (Address, (MmioRead16 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 16-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioBitFieldRead16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead16 (MmioRead16 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 16-bit register is returned. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldWrite16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 Value + ) +{ + return MmioWrite16 ( + Address, + BitFieldWrite16 (MmioRead16 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 16-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldOr16 (MmioRead16 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 16-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAnd16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAnd16 (MmioRead16 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 16-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 16-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 15, then ASSERT(). + If EndBit is greater than 15, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..15. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..15. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioBitFieldAndThenOr16 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT16 AndData, + IN UINT16 OrData + ) +{ + return MmioWrite16 ( + Address, + BitFieldAndThenOr16 (MmioRead16 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioOr32 ( + IN UINTN Address, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) | OrData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND, and writes the result + back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAnd32 ( + IN UINTN Address, + IN UINT32 AndData + ) +{ + return MmioWrite32 (Address, MmioRead32 (Address) & AndData); +} + +/** + Reads a 32-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 32-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioAndThenOr32 ( + IN UINTN Address, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 (Address, (MmioRead32 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 32-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioBitFieldRead32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead32 (MmioRead32 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 32-bit register is returned. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldWrite32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 Value + ) +{ + return MmioWrite32 ( + Address, + BitFieldWrite32 (MmioRead32 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 32-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldOr32 (MmioRead32 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 32-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAnd32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAnd32 (MmioRead32 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 32-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 32-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 31, then ASSERT(). + If EndBit is greater than 31, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..31. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..31. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioBitFieldAndThenOr32 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT32 AndData, + IN UINT32 OrData + ) +{ + return MmioWrite32 ( + Address, + BitFieldAndThenOr32 (MmioRead32 (Address), StartBit, EndBit, AndData, OrData) + ); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise inclusive OR, and writes the + result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param OrData The value to OR with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioOr64 ( + IN UINTN Address, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) | OrData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND, and writes the result + back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAnd64 ( + IN UINTN Address, + IN UINT64 AndData + ) +{ + return MmioWrite64 (Address, MmioRead64 (Address) & AndData); +} + +/** + Reads a 64-bit MMIO register, performs a bitwise AND followed by a bitwise + inclusive OR, and writes the result back to the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, performs a + bitwise OR between the result of the AND operation and the value specified by + OrData, and writes the result to the 64-bit MMIO register specified by + Address. The value written to the MMIO register is returned. This function + must guarantee that all MMIO read and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + + @param Address The MMIO register to write. + @param AndData The value to AND with the read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioAndThenOr64 ( + IN UINTN Address, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 (Address, (MmioRead64 (Address) & AndData) | OrData); +} + +/** + Reads a bit field of a MMIO register. + + Reads the bit field in a 64-bit MMIO register. The bit field is specified by + the StartBit and the EndBit. The value of the bit field is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to read. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioBitFieldRead64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit + ) +{ + return BitFieldRead64 (MmioRead64 (Address), StartBit, EndBit); +} + +/** + Writes a bit field to a MMIO register. + + Writes Value to the bit field of the MMIO register. The bit field is + specified by the StartBit and the EndBit. All other bits in the destination + MMIO register are preserved. The new value of the 64-bit register is returned. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param Value New value of the bit field. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldWrite64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 Value + ) +{ + return MmioWrite64 ( + Address, + BitFieldWrite64 (MmioRead64 (Address), StartBit, EndBit, Value) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise OR, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise + inclusive OR between the read result and the value specified by OrData, and + writes the result to the 64-bit MMIO register specified by Address. The value + written to the MMIO register is returned. This function must guarantee that + all MMIO read and write operations are serialized. Extra left bits in OrData + are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param OrData The value to OR with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldOr64 (MmioRead64 (Address), StartBit, EndBit, OrData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND, and + writes the result back to the bit field in the 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + between the read result and the value specified by AndData, and writes the + result to the 64-bit MMIO register specified by Address. The value written to + the MMIO register is returned. This function must guarantee that all MMIO + read and write operations are serialized. Extra left bits in AndData are + stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAnd64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAnd64 (MmioRead64 (Address), StartBit, EndBit, AndData) + ); +} + +/** + Reads a bit field in a 64-bit MMIO register, performs a bitwise AND followed + by a bitwise inclusive OR, and writes the result back to the bit field in the + 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address, performs a bitwise AND + followed by a bitwise inclusive OR between the read result and the value + specified by AndData, and writes the result to the 64-bit MMIO register + specified by Address. The value written to the MMIO register is returned. + This function must guarantee that all MMIO read and write operations are + serialized. Extra left bits in both AndData and OrData are stripped. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + If StartBit is greater than 63, then ASSERT(). + If EndBit is greater than 63, then ASSERT(). + If EndBit is less than or equal to StartBit, then ASSERT(). + + @param Address MMIO register to write. + @param StartBit The ordinal of the least significant bit in the bit field. + Range 0..63. + @param EndBit The ordinal of the most significant bit in the bit field. + Range 0..63. + @param AndData The value to AND with read value from the MMIO register. + @param OrData The value to OR with the result of the AND operation. + + @return The value written back to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioBitFieldAndThenOr64 ( + IN UINTN Address, + IN UINTN StartBit, + IN UINTN EndBit, + IN UINT64 AndData, + IN UINT64 OrData + ) +{ + return MmioWrite64 ( + Address, + BitFieldAndThenOr64 (MmioRead64 (Address), StartBit, EndBit, AndData, OrData) + ); +} diff --git a/MdePkg/Library/PeiIoLibCpuIo/IoLib.c b/MdePkg/Library/PeiIoLibCpuIo/IoLib.c new file mode 100644 index 0000000000..2156f6b480 --- /dev/null +++ b/MdePkg/Library/PeiIoLibCpuIo/IoLib.c @@ -0,0 +1,530 @@ +/** @file + I/O Library. + + Copyright (c) 2006, 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. + + Module Name: IoLib.c + +**/ + +/** + Reads an 8-bit I/O port. + + Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +IoRead8 ( + IN UINTN Port + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + return CpuIo->IoRead8 (PeiServices, CpuIo, (UINT64) Port); +} + +/** + Writes an 8-bit I/O port. + + Writes the 8-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 8-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT8 +EFIAPI +IoWrite8 ( + IN UINTN Port, + IN UINT8 Value + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + CpuIo->IoWrite8 (PeiServices, CpuIo, (UINT64) Port, Value); + return Value; +} + +/** + Reads a 16-bit I/O port. + + Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +IoRead16 ( + IN UINTN Port + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + return CpuIo->IoRead16 (PeiServices, CpuIo, (UINT64) Port); +} + +/** + Writes a 16-bit I/O port. + + Writes the 16-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 16-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT16 +EFIAPI +IoWrite16 ( + IN UINTN Port, + IN UINT16 Value + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + CpuIo->IoWrite16 (PeiServices, CpuIo, (UINT64) Port, Value); + return Value; +} + +/** + Reads a 32-bit I/O port. + + Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +IoRead32 ( + IN UINTN Port + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + return CpuIo->IoRead32 (PeiServices, CpuIo, (UINT64) Port); +} + +/** + Writes a 32-bit I/O port. + + Writes the 32-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 32-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT32 +EFIAPI +IoWrite32 ( + IN UINTN Port, + IN UINT32 Value + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + CpuIo->IoWrite32 (PeiServices, CpuIo, (UINT64) Port, Value); + return Value; +} + +/** + Reads a 64-bit I/O port. + + Reads the 64-bit I/O port specified by Port. The 64-bit read value is returned. + This function must guarantee that all I/O read and write operations are + serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +IoRead64 ( + IN UINTN Port + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + return CpuIo->IoRead64 (PeiServices, CpuIo, (UINT64) Port); +} + +/** + Writes a 64-bit I/O port. + + Writes the 64-bit I/O port specified by Port with the value specified by Value + and returns Value. This function must guarantee that all I/O read and write + operations are serialized. + + If 64-bit I/O port operations are not supported, then ASSERT(). + + @param Port The I/O port to write. + @param Value The value to write to the I/O port. + + @return The value written the I/O port. + +**/ +UINT64 +EFIAPI +IoWrite64 ( + IN UINTN Port, + IN UINT64 Value + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + CpuIo->IoWrite64 (PeiServices, CpuIo, (UINT64) Port, Value); + return Value;; +} + +/** + Reads an 8-bit MMIO register. + + Reads the 8-bit MMIO register specified by Address. The 8-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT8 +EFIAPI +MmioRead8 ( + IN UINTN Address + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + return CpuIo->MemRead8 (PeiServices, CpuIo, (UINT64) Address); +} + +/** + Writes an 8-bit MMIO register. + + Writes the 8-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 8-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT8 +EFIAPI +MmioWrite8 ( + IN UINTN Address, + IN UINT8 Value + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + CpuIo->MemWrite8 (PeiServices, CpuIo, (UINT64) Address, Value); + return Value; +} + +/** + Reads a 16-bit MMIO register. + + Reads the 16-bit MMIO register specified by Address. The 16-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT16 +EFIAPI +MmioRead16 ( + IN UINTN Address + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + return CpuIo->MemRead16 (PeiServices, CpuIo, (UINT64) Address); + +} + +/** + Writes a 16-bit MMIO register. + + Writes the 16-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 16-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT16 +EFIAPI +MmioWrite16 ( + IN UINTN Address, + IN UINT16 Value + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + CpuIo->MemWrite16 (PeiServices, CpuIo, (UINT64) Address, Value); + return Value; +} + +/** + Reads a 32-bit MMIO register. + + Reads the 32-bit MMIO register specified by Address. The 32-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT32 +EFIAPI +MmioRead32 ( + IN UINTN Address + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + return CpuIo->MemRead32 (PeiServices, CpuIo, (UINT64) Address); + +} + +/** + Writes a 32-bit MMIO register. + + Writes the 32-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 32-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT32 +EFIAPI +MmioWrite32 ( + IN UINTN Address, + IN UINT32 Value + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + CpuIo->MemWrite32 (PeiServices, CpuIo, (UINT64) Address, Value); + return Value; +} + +/** + Reads a 64-bit MMIO register. + + Reads the 64-bit MMIO register specified by Address. The 64-bit read value is + returned. This function must guarantee that all MMIO read and write + operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to read. + + @return The value read. + +**/ +UINT64 +EFIAPI +MmioRead64 ( + IN UINTN Address + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + return CpuIo->MemRead64 (PeiServices, CpuIo, (UINT64) Address); + +} + +/** + Writes a 64-bit MMIO register. + + Writes the 64-bit MMIO register specified by Address with the value specified + by Value and returns Value. This function must guarantee that all MMIO read + and write operations are serialized. + + If 64-bit MMIO register operations are not supported, then ASSERT(). + + @param Address The MMIO register to write. + @param Value The value to write to the MMIO register. + +**/ +UINT64 +EFIAPI +MmioWrite64 ( + IN UINTN Address, + IN UINT64 Value + ) +{ + EFI_PEI_SERVICES **PeiServices; + EFI_PEI_CPU_IO_PPI *CpuIo; + + PeiServices = GetPeiServicesTablePointer (); + CpuIo = (*PeiServices)->CpuIo; + + ASSERT (CpuIo != NULL); + + CpuIo->MemWrite64 (PeiServices, CpuIo, (UINT64) Address, Value); + return Value; +} diff --git a/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.mbd b/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.mbd new file mode 100644 index 0000000000..a615d24b97 --- /dev/null +++ b/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.mbd @@ -0,0 +1,29 @@ + + + + + PeiIoLibCpuIo + b2585b69-fb63-4220-844a-8fbea8bf01af + EDK_RELEASE_VERSION 0x00090000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-04-14 12:42 + + diff --git a/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.msa b/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.msa new file mode 100644 index 0000000000..fb214ce932 --- /dev/null +++ b/MdePkg/Library/PeiIoLibCpuIo/PeiIoLibCpuIo.msa @@ -0,0 +1,46 @@ + + + + + PeiIoLibCpuIo + PEIM + LIBRARY + b2585b69-fb63-4220-844a-8fbea8bf01af + EDK_RELEASE_VERSION 0x00090000 + I/O Library implemented with Framework CPU I/O Protocol + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-14 12:42 + + + IoLib + DebugLib + BaseLib + PeiServicesTablePointerLib + + + IoLib.c + IoHighLevel.c + + + MdePkg + + diff --git a/MdePkg/Library/PeiIoLibCpuIo/build.xml b/MdePkg/Library/PeiIoLibCpuIo/build.xml new file mode 100644 index 0000000000..3a650ed6d4 --- /dev/null +++ b/MdePkg/Library/PeiIoLibCpuIo/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c b/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c new file mode 100644 index 0000000000..63641569ff --- /dev/null +++ b/MdePkg/Library/PeiMemoryAllocationLib/MemoryAllocationLib.c @@ -0,0 +1,879 @@ +/** @file + Support routines for memory allocation routines for use with drivers. + + Copyright (c) 2006, 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. + + Module Name: MemoryAllocationLib.c + +**/ + + + +/** + Allocates the number of 4KB pages specified by Pages of a certain memory type. + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocatePages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages + ) +{ + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS Memory; + EFI_PEI_SERVICES **PeiServices; + + if (Pages == 0) { + return NULL; + } + + PeiServices = GetPeiServicesTablePointer (); + Status = (*PeiServices)->AllocatePages (PeiServices, MemoryType, Pages, &Memory); + if (EFI_ERROR (Status)) { + Memory = 0; + } + return (VOID *) (UINTN) Memory; +} + +/** + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocatePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiBootServicesData, Pages); +} + +/** + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimePages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiRuntimeServicesData, Pages); +} + +/** + Allocates the number of 4KB pages specified by Pages of type EfiReservedMemoryType. + + @param Pages The number of 4 KB pages to allocate. + + @return A pointer to the allocated buffer. The buffer returned is aligned on a 4KB boundary. + If Pages is 0, then NULL is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedPages ( + IN UINTN Pages + ) +{ + return InternalAllocatePages (EfiReservedMemoryType, Pages); +} + +/** + Frees one or more 4KB pages that were previously allocated with + one of the page allocation functions in the Memory Allocation Library. + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreePages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + // + // PEI phase does not support to free pages, so leave it as NOP. + // +} + +/** + Allocates the number of 4KB pages specified by Pages of a certian memory type + with an alignment specified by Alignment. + + @param MemoryType The type of memory to allocate. + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateAlignedPages ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN Pages, + IN UINTN Alignment + ) +{ + VOID *Memory; + UINTN AlignmentMask; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Pages == 0) { + return NULL; + } + // + // We would rather waste some memory to save PEI code size. + // + Memory = InternalAllocatePages (MemoryType, Pages + EFI_SIZE_TO_PAGES (Alignment)); + if (Alignment == 0) { + AlignmentMask = Alignment; + } else { + AlignmentMask = Alignment - 1; + } + return (VOID *) (UINTN) (((UINTN) Memory + AlignmentMask) & ~AlignmentMask); +} + +/** + Allocates the number of 4KB pages specified by Pages of type EfiBootServicesData + with an alignment specified by Alignment. + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiBootServicesData, Pages, Alignment); +} + +/** + Allocates the number of 4KB pages specified by Pages of type EfiRuntimeServicesData + with an alignment specified by Alignment. + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiRuntimeServicesData, Pages, Alignment); +} + +/** + Allocates one or more 4KB pages of type EfiReservedMemoryType at a specified alignment. + + @param Pages The number of 4 KB pages to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return The allocated buffer is returned. If Pages is 0, then NULL is returned. + If there is not enough memory at the specified alignment remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPages ( + IN UINTN Pages, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPages (EfiReservedMemoryType, Pages, Alignment); +} + +/** + Frees one or more 4KB pages that were previously allocated with + one of the aligned page allocation functions in the Memory Allocation Library. + + @param Buffer Pointer to the buffer of pages to free. + @param Pages The number of 4 KB pages to free. + +**/ +VOID +EFIAPI +FreeAlignedPages ( + IN VOID *Buffer, + IN UINTN Pages + ) +{ + // + // PEI phase does not support to free pages, so leave it as NOP. + // +} + +/** + Allocates a buffer of a certain memory type. + + @param MemoryType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocatePool ( + IN EFI_MEMORY_TYPE MemoryType, + IN UINTN AllocationSize + ) +{ + // + // If we need lots of small runtime/reserved memory type from PEI in the future, + // we can consider providing a more complex algorithm that allocates runtime pages and + // provide pool allocations from those pages. + // + return InternalAllocatePages (MemoryType, EFI_SIZE_TO_PAGES (AllocationSize)); +} + +/** + Allocates a buffer of type EfiBootServicesData. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocatePool ( + IN UINTN AllocationSize + ) +{ + EFI_STATUS Status; + EFI_PEI_SERVICES **PeiServices; + VOID *Buffer; + + PeiServices = GetPeiServicesTablePointer (); + + Status = (*PeiServices)->AllocatePool (PeiServices, AllocationSize, &Buffer); + if (EFI_ERROR (Status)) { + Buffer = NULL; + } + return Buffer; +} + +/** + Allocates a buffer of type EfiRuntimeServicesData. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimePool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates a buffer of type EfiReservedMemoryType. + + @param AllocationSize The number of bytes to allocate. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocatePool (EfiReservedMemoryType, AllocationSize); +} + +/** + Allocates and zeros a buffer of a certian pool type. + + @param PoolType The type of memory to allocate. + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateZeroPool ( + IN UINTN AllocationSize + ) +{ + VOID *Memory; + + Memory = AllocatePool (AllocationSize); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimeZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiRuntimeServicesData, AllocationSize); +} + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType. + + @param AllocationSize The number of bytes to allocate and zero. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedZeroPool ( + IN UINTN AllocationSize + ) +{ + return InternalAllocateZeroPool (EfiReservedMemoryType, AllocationSize); +} + +/** + Copies a buffer to an allocated buffer of a certian memory type. + + @param MemoryType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate and zero. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + Memory = InternalAllocatePool (PoolType, AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + VOID *Memory; + + Memory = AllocatePool (AllocationSize); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (EfiReservedMemoryType, AllocationSize, Buffer); +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType at a specified alignment. + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreePool ( + IN VOID *Buffer + ) +{ + // + // PEI phase does not support to free pool, so leave it as NOP. + // +} + +/** + Allocates a buffer of a certain pool type at a specified alignment. + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateAlignedPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + VOID *RawAddress; + UINTN AlignedAddress; + UINTN AlignmentMask; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Alignment == 0) { + AlignmentMask = Alignment; + } else { + AlignmentMask = Alignment - 1; + } + + RawAddress = InternalAllocatePool (PoolType, AllocationSize + AlignmentMask); + + AlignedAddress = ((UINTN) RawAddress + AlignmentMask) & ~AlignmentMask; + + return (VOID *) AlignedAddress; +} + +/** + Allocates a buffer of type EfiBootServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + VOID *RawAddress; + UINTN AlignedAddress; + UINTN AlignmentMask; + + // + // Alignment must be a power of two or zero. + // + ASSERT ((Alignment & (Alignment - 1)) == 0); + + if (Alignment == 0) { + AlignmentMask = Alignment; + } else { + AlignmentMask = Alignment - 1; + } + + RawAddress = AllocatePool (AllocationSize + AlignmentMask); + + AlignedAddress = ((UINTN) RawAddress + AlignmentMask) & ~AlignmentMask; + + return (VOID *) AlignedAddress; +} + +/** + Allocates a buffer of type EfiRuntimeServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimePool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPool (EfiRuntimeServicesData, AllocationSize, Alignment); +} + +/** + Allocates a buffer of type EfiReservedMemoryType at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedPool (EfiReservedMemoryType, AllocationSize, Alignment); +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment. + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateAlignedZeroPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + VOID *Memory; + + Memory = InternalAllocateAlignedPool (PoolType, AllocationSize, Alignment); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiBootServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + VOID *Memory; + + Memory = AllocateAlignedPool (AllocationSize, Alignment); + if (Memory != NULL) { + Memory = ZeroMem (Memory, AllocationSize); + } + return Memory; +} + +/** + Allocates and zeros a buffer of type EfiRuntimeServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimeZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedZeroPool (EfiRuntimeServicesData, AllocationSize, Alignment); +} + +/** + Allocates and zeros a buffer of type EfiReservedMemoryType at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedZeroPool ( + IN UINTN AllocationSize, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedZeroPool (EfiReservedMemoryType, AllocationSize, Alignment); +} + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData at a specified alignment. + + @param PoolType The type of pool to allocate. + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +InternalAllocateAlignedCopyPool ( + IN EFI_MEMORY_TYPE PoolType, + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + VOID *Memory; + + Memory = InternalAllocateAlignedPool (PoolType, AllocationSize, Alignment); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiBootServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + VOID *Memory; + + Memory = AllocateAlignedPool (AllocationSize, Alignment); + if (Memory != NULL) { + Memory = CopyMem (Memory, Buffer, AllocationSize); + } + return Memory; +} + +/** + Copies a buffer to an allocated buffer of type EfiRuntimeServicesData at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedRuntimeCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedCopyPool (EfiRuntimeServicesData, AllocationSize, Buffer, Alignment); +} + +/** + Copies a buffer to an allocated buffer of type EfiReservedMemoryType at a specified alignment. + + @param AllocationSize The number of bytes to allocate. + @param Buffer The buffer to copy to the allocated buffer. + @param Alignment The requested alignment of the allocation. Must be a power of two. + If Alignment is zero, then byte alignment is used. + + @return A pointer to the allocated buffer. If AllocationSize is 0, then a valid buffer of 0 size is returned. + If there is not enough memory remaining to satisfy the request, then NULL is returned. + +**/ +VOID * +EFIAPI +AllocateAlignedReservedCopyPool ( + IN UINTN AllocationSize, + IN CONST VOID *Buffer, + IN UINTN Alignment + ) +{ + return InternalAllocateAlignedCopyPool (EfiReservedMemoryType, AllocationSize, Buffer, Alignment); +} + +/** + Frees a buffer that was previously allocated with one of the aligned pool allocation functions + in the Memory Allocation Library. + + @param Buffer Pointer to the buffer to free. + +**/ +VOID +EFIAPI +FreeAlignedPool ( + IN VOID *Buffer + ) +{ + // + // PEI phase does not support to free pool, so leave it as NOP. + // +} diff --git a/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.mbd b/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.mbd new file mode 100644 index 0000000000..94991603ac --- /dev/null +++ b/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.mbd @@ -0,0 +1,30 @@ + + + + + PeiMemoryAllocationLib + b694e0dc-cd4e-4b30-885b-9c164ed3e74a + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.msa b/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.msa new file mode 100644 index 0000000000..4555d7cfe8 --- /dev/null +++ b/MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.msa @@ -0,0 +1,46 @@ + + + + + PeiMemoryAllocationLib + PEIM + LIBRARY + b694e0dc-cd4e-4b30-885b-9c164ed3e74a + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + MemoryAllocationLib + PeiServicesTablePointerLib + BaseMemoryLib + DebugLib + + + MemoryAllocationLib.c + + + MdePkg + + diff --git a/MdePkg/Library/PeiMemoryAllocationLib/build.xml b/MdePkg/Library/PeiMemoryAllocationLib/build.xml new file mode 100644 index 0000000000..47eff363e2 --- /dev/null +++ b/MdePkg/Library/PeiMemoryAllocationLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiMemoryLib/MemLib.c b/MdePkg/Library/PeiMemoryLib/MemLib.c new file mode 100644 index 0000000000..3a27ab2e83 --- /dev/null +++ b/MdePkg/Library/PeiMemoryLib/MemLib.c @@ -0,0 +1,47 @@ +/** @file + Base Memory Library. + + Copyright (c) 2006, 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. + + Module Name: MemLib.c + +**/ + +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + (*GetPeiServicesTablePointer ())->CopyMem ( + Destination, + (VOID*)Source, + Length + ); + return Destination; +} + +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + (*GetPeiServicesTablePointer ())->SetMem ( + Buffer, + Size, + Value + ); + return Buffer; +} diff --git a/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c b/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c new file mode 100644 index 0000000000..ef9f358a79 --- /dev/null +++ b/MdePkg/Library/PeiMemoryLib/MemLibGeneric.c @@ -0,0 +1,282 @@ +/** @file + Architecture Independent Base Memory Library Implementation. + + Copyright (c) 2006, 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. + + Module Name: MemLibGeneric.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + do { + ((UINT16*)Buffer)[--Length] = Value; + } while (Length != 0); + return Buffer; +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + do { + ((UINT32*)Buffer)[--Length] = Value; + } while (Length != 0); + return Buffer; +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + do { + ((UINT64*)Buffer)[--Length] = Value; + } while (Length != 0); + return Buffer; +} + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + return InternalMemSetMem (Buffer, Length, 0); +} + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @retval 0 if MemOne == MemTwo + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + ASSERT (Length > 0); + while ((--Length != 0) && + (*(INT8*)DestinationBuffer == *(INT8*)SourceBuffer)) { + DestinationBuffer = (INT8*)DestinationBuffer + 1; + SourceBuffer = (INT8*)SourceBuffer + 1; + } + return (INTN)*(UINT8*)DestinationBuffer - (INTN)*(UINT8*)SourceBuffer; +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + CONST UINT8 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT8*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + CONST UINT16 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT16*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + CONST UINT32 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT32*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + CONST UINT64 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT64*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} diff --git a/MdePkg/Library/PeiMemoryLib/MemLibGuid.c b/MdePkg/Library/PeiMemoryLib/MemLibGuid.c new file mode 100644 index 0000000000..06b2721c64 --- /dev/null +++ b/MdePkg/Library/PeiMemoryLib/MemLibGuid.c @@ -0,0 +1,131 @@ +/** @file + Implementation of GUID functions. + + Copyright (c) 2006, 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. + + Module Name: MemLibGuid.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + This function copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid + to DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid Pointer to the destination GUID. + @param SourceGuid Pointer to the source GUID. + + @return DestinationGuid + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE + is returned. If there are any bit differences in the two GUIDs, then FALSE is + returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 guid to compare + @param Guid2 guid to compare + + @retval TRUE if Guid1 == Guid2 + @retval FALSE if Guid1 != Guid2 + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + return (BOOLEAN)( + ReadUnaligned64 ((CONST UINT64*)Guid1) + == ReadUnaligned64 ((CONST UINT64*)Guid2) && + ReadUnaligned64 ((CONST UINT64*)Guid1 + 1) + == ReadUnaligned64 ((CONST UINT64*)Guid2 + 1) + ); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the + 128-bit GUID value that matches Guid. If a match is found, then a pointer to + the matching GUID in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Guid Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Guid was not found. +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} diff --git a/MdePkg/Library/PeiMemoryLib/MemLibWrapper.c b/MdePkg/Library/PeiMemoryLib/MemLibWrapper.c new file mode 100644 index 0000000000..2ef0766242 --- /dev/null +++ b/MdePkg/Library/PeiMemoryLib/MemLibWrapper.c @@ -0,0 +1,620 @@ +/** @file + Wrapper functions for Base Memory Library. + + Copyright (c) 2006, 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. + + Module Name: MemLibWrapper.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + Copy Length bytes from Source to Destination. + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @retval 0 if MemOne == MemTwo + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Copy Length bytes from Source to Destination. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and + returns DestinationBuffer. The implementation must be reentrant, and it must + handle the case where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Destination + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Source + 1); + return InternalMemCopyMem (Destination, Source, Length); +} + +/** + Set Buffer to Value for Size bytes. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + ASSERT (Size <= MAX_ADDRESS - (UINTN)Buffer + 1); + return InternalMemSetMem (Buffer, Size, Value); +} + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem16 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem32 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem64 (Buffer, Length, Value); +} + +/** + Set Buffer to 0 for Size bytes. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + ASSERT (Buffer != NULL); + return InternalMemSetMem (Buffer, Size, 0); +} + +/** + Compares two memory buffers of a given length. + + This function compares Length bytes of SourceBuffer to Length bytes of + DestinationBuffer. If all Length bytes of the two buffers are identical, then + 0 is returned. Otherwise, the value returned is the first mismatched byte in + SourceBuffer subtracted from the first mismatched byte in DestinationBuffer. + + If DestinationBuffer is NULL and Length > 0, then ASSERT(). + If SourceBuffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare + + @retval 0 if DestinationBuffer == SourceBuffer + @retval Non-zero if DestinationBuffer != SourceBuffer + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)DestinationBuffer + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)SourceBuffer + 1); + if (Length == 0) { + return 0; + } + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address for an 8-bit value that matches + Value. If a match is found, then a pointer to the matching byte in the target + buffer is returned. If no match is found, then NULL is returned. If Length is + 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 16-bit increments for a 16-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem16 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 32-bit increments for a 32-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem32 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 64-bit increments for a 64-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem64 (Buffer, Length, Value); +} diff --git a/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.mbd b/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.mbd new file mode 100644 index 0000000000..d78b59c500 --- /dev/null +++ b/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.mbd @@ -0,0 +1,29 @@ + + + + + PeiMemoryLib + 3a9759d2-53bc-4eb2-abcd-c93099419063 + EDK_RELEASE_VERSION 0x00090000 + FIX ME! + Copyright (c) 2006, 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. + + 2006-04-12 13:39 + + diff --git a/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.msa b/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.msa new file mode 100644 index 0000000000..38a05fe7af --- /dev/null +++ b/MdePkg/Library/PeiMemoryLib/PeiMemoryLib.msa @@ -0,0 +1,48 @@ + + + + + PeiMemoryLib + PEIM + LIBRARY + 3a9759d2-53bc-4eb2-abcd-c93099419063 + EDK_RELEASE_VERSION 0x00090000 + Memory-only library functions with no library constructor/destructor + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-12 13:39 + + + BaseMemoryLib + PeiServicesTablePointerLib + DebugLib + BaseLib + + + MemLib.c + MemLibGuid.c + MemLibGeneric.c + MemLibWrapper.c + + + MdePkg + + diff --git a/MdePkg/Library/PeiMemoryLib/build.xml b/MdePkg/Library/PeiMemoryLib/build.xml new file mode 100644 index 0000000000..f8d7bd35a4 --- /dev/null +++ b/MdePkg/Library/PeiMemoryLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiPcdLib/PeiPcdLib.c b/MdePkg/Library/PeiPcdLib/PeiPcdLib.c new file mode 100644 index 0000000000..29fdeb0ee4 --- /dev/null +++ b/MdePkg/Library/PeiPcdLib/PeiPcdLib.c @@ -0,0 +1,951 @@ +/** @file +Implementation of PcdLib class library for PEI phase. + +Copyright (c) 2006, 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. + + +Module Name: PeiPcdLib.c + +**/ + + + +/** + The constructor function retrieve the PCD_PPI pointer. + + @param[in] VOID + + @retval PCD_PPI * The pointer to the PCD_PPI. + +**/ +PCD_PPI * +GetPcdPpiPtr ( + VOID + ) +{ + EFI_STATUS Status; + PCD_PPI *PcdPpi; + EFI_PEI_SERVICES **PeiServices; + + + PeiServices = GetPeiServicesTablePointer (); + + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gPcdPpiGuid, + 0, + NULL, + (VOID **)&PcdPpi + ); + + ASSERT_EFI_ERROR (Status); + + return PcdPpi; +} + + + +/** + Sets the current SKU in the PCD database to the value specified by SkuId. SkuId is returned. + + @param[in] SkuId The SKU value that will be used when the PCD service will retrieve and + set values associated with a PCD token. + + @retval UINTN Return the SKU ID that just be set. + +**/ +UINTN +EFIAPI +LibPcdSetSku ( + IN UINTN SkuId + ) +{ + EFI_STATUS Status; + PCD_PPI *PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->SetSku (SkuId); + ASSERT_EFI_ERROR (Status); + + return SkuId; +} + + + +/** + Returns the 8-bit value for the token specified by TokenNumber. + + @param[in] The PCD token number to retrieve a current value for. + + @retval UINT8 Returns the 8-bit value for the token specified by TokenNumber. + +**/ +UINT8 +EFIAPI +LibPcdGet8 ( + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->Get8 (TokenNumber); +} + + + +/** + Returns the 16-bit value for the token specified by TokenNumber. + + @param[in] The PCD token number to retrieve a current value for. + + @retval UINT16 Returns the 16-bit value for the token specified by TokenNumber. + +**/ +UINT16 +EFIAPI +LibPcdGet16 ( + IN UINTN TokenNumber + ) +{ + PCD_PPI *PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->Get16 (TokenNumber); +} + + + +/** + Returns the 32-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT32 Returns the 32-bit value for the token specified by TokenNumber. + +**/ +UINT32 +EFIAPI +LibPcdGet32 ( + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->Get32 (TokenNumber); +} + + + +/** + Returns the 64-bit value for the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT64 Returns the 64-bit value for the token specified by TokenNumber. + +**/ +UINT64 +EFIAPI +LibPcdGet64 ( + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->Get64 (TokenNumber); +} + + + +/** + Returns the pointer to the buffer of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval VOID* Returns the pointer to the token specified by TokenNumber. + +**/ +VOID * +EFIAPI +LibPcdGetPtr ( + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->GetPtr (TokenNumber); +} + + + +/** + Returns the Boolean value of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval BOOLEAN Returns the Boolean value of the token specified by TokenNumber. + +**/ +BOOLEAN +EFIAPI +LibPcdGetBool ( + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->GetBool (TokenNumber); +} + + + +/** + Returns the size of the token specified by TokenNumber. + + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINTN Returns the size of the token specified by TokenNumber. + +**/ +UINTN +EFIAPI +LibPcdGetSize ( + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->GetSize (TokenNumber); +} + + + +/** + Returns the 8-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT8 Return the UINT8. + +**/ +UINT8 +EFIAPI +LibPcdGetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->Get8Ex (Guid, TokenNumber); +} + + + +/** + Returns the 16-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT16 Return the UINT16. + +**/ +UINT16 +EFIAPI +LibPcdGetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->Get16Ex (Guid, TokenNumber); +} + + + +/** + Returns the 32-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT32 Return the UINT32. + +**/ +UINT32 +EFIAPI +LibPcdGetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->Get32Ex (Guid, TokenNumber); +} + + + + +/** + Returns the 64-bit value for the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINT64 Return the UINT64. + +**/ +UINT64 +EFIAPI +LibPcdGetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->Get64Ex (Guid, TokenNumber); +} + + + +/** + Returns the pointer to the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval VOID* Return the VOID* pointer. + +**/ +VOID * +EFIAPI +LibPcdGetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->GetPtrEx (Guid, TokenNumber); +} + + + +/** + Returns the Boolean value of the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval BOOLEAN Return the BOOLEAN. + +**/ +BOOLEAN +EFIAPI +LibPcdGetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->GetBoolEx (Guid, TokenNumber); +} + + + +/** + Returns the size of the token specified by TokenNumber and Guid. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates + which namespace to retrieve a value from. + @param[in] TokenNumber The PCD token number to retrieve a current value for. + + @retval UINTN Return the size. + +**/ +UINTN +EFIAPI +LibPcdGetExSize ( + IN CONST GUID *Guid, + IN UINTN TokenNumber + ) +{ + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + return PcdPpi->GetSizeEx (Guid, TokenNumber); +} + + + +/** + Sets the 8-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT8 +EFIAPI +LibPcdSet8 ( + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->Set8 (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 16-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @retval UINT16 Return the value been set. + +**/ +UINT16 +EFIAPI +LibPcdSet16 ( + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->Set16 (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 32-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @retval UINT32 Return the value been set. + +**/ +UINT32 +EFIAPI +LibPcdSet32 ( + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + Status = PcdPpi->Set32 (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 64-bit value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @retval UINT64 Return the value been set. + +**/ +UINT64 +EFIAPI +LibPcdSet64 ( + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->Set64 (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets a buffer for the token specified by TokenNumber to + the value specified by Value. Value is returned. + If Value is NULL, then ASSERT(). + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value A pointer to the buffer to set. + + @retval VOID* Return the pointer for the buffer been set. + +**/ +VOID * +EFIAPI +LibPcdSetPtr ( + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->SetPtr (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return (VOID *)Value; +} + + + +/** + Sets the Boolean value for the token specified by TokenNumber + to the value specified by Value. Value is returned. + + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The boolean value to set. + + @retval BOOLEAN Return the value been set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetBool ( + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->SetBool (TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 8-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT8 +EFIAPI +LibPcdSetEx8 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT8 Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->Set8Ex (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 16-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 16-bit value to set. + + @retval UINT8 Return the value been set. + +**/ +UINT16 +EFIAPI +LibPcdSetEx16 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT16 Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->Set16Ex (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 32-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 32-bit value to set. + + @retval UINT32 Return the value been set. + +**/ +UINT32 +EFIAPI +LibPcdSetEx32 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT32 Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->Set32Ex (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets the 64-bit value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 64-bit value to set. + + @retval UINT64 Return the value been set. + +**/ +UINT64 +EFIAPI +LibPcdSetEx64 ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN UINT64 Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->Set64Ex (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + Sets a buffer for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + If Value is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The 8-bit value to set. + + @retval VOID * Return the value been set. + +**/ +VOID * +EFIAPI +LibPcdSetExPtr ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN CONST VOID *Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->SetPtrEx (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return (VOID *)Value; +} + + + +/** + Sets the Boolean value for the token specified by TokenNumber and + Guid to the value specified by Value. Value is returned. + If Guid is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that + designates which namespace to set a value from. + @param[in] TokenNumber The PCD token number to set a current value for. + @param[in] Value The Boolean value to set. + + @retval Boolean Return the value been set. + +**/ +BOOLEAN +EFIAPI +LibPcdSetExBool ( + IN CONST GUID *Guid, + IN UINTN TokenNumber, + IN BOOLEAN Value + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->SetBoolEx (Guid, TokenNumber, Value); + + ASSERT_EFI_ERROR (Status); + + return Value; +} + + + +/** + When the token specified by TokenNumber and Guid is set, + then notification function specified by NotificationFunction is called. + If Guid is NULL, then the default token space is used. + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid Pointer to a 128-bit unique value that designates which + namespace to set a value from. If NULL, then the default + token space is used. + @param[in] TokenNumber The PCD token number to monitor. + @param[in] NotificationFunction The function to call when the token + specified by Guid and TokenNumber is set. + + @retval VOID + +**/ +VOID +EFIAPI +LibPcdCallbackOnSet ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->CallbackOnSet (TokenNumber, Guid, NotificationFunction); + + ASSERT_EFI_ERROR (Status); + + return; +} + + + +/** + Disable a notification function that was established with LibPcdCallbackonSet(). + If NotificationFunction is NULL, then ASSERT(). + + @param[in] Guid Specify the GUID token space. + @param[in] TokenNumber Specify the token number. + @param[in] NotificationFunction The callback function to be unregistered. + + @retval VOID + +**/ +VOID +EFIAPI +LibPcdCancelCallback ( + IN CONST GUID *Guid, OPTIONAL + IN UINTN TokenNumber, + IN PCD_CALLBACK NotificationFunction + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->CancelCallback (TokenNumber, Guid, NotificationFunction); + + ASSERT_EFI_ERROR (Status); + + return; +} + + + +/** + Retrieves the next PCD token number from the token space specified by Guid. + If Guid is NULL, then the default token space is used. If TokenNumber is 0, + then the first token number is returned. Otherwise, the token number that + follows TokenNumber in the token space is returned. If TokenNumber is the last + token number in the token space, then 0 is returned. If TokenNumber is not 0 and + is not in the token space specified by Guid, then ASSERT(). + + @param[in] Pointer to a 128-bit unique value that designates which namespace + to set a value from. If NULL, then the default token space is used. + @param[in] The previous PCD token number. If 0, then retrieves the first PCD + token number. + + @retval UINTN The next valid token number. + +**/ +UINTN +EFIAPI +LibPcdGetNextToken ( + IN CONST GUID *Guid, OPTIONAL + IN OUT UINTN *TokenNumber + ) +{ + EFI_STATUS Status; + PCD_PPI * PcdPpi; + + PcdPpi = GetPcdPpiPtr (); + + + Status = PcdPpi->GetNextToken (Guid, TokenNumber); + + ASSERT_EFI_ERROR (Status); + + return (*TokenNumber); +} diff --git a/MdePkg/Library/PeiPcdLib/PeiPcdLib.mbd b/MdePkg/Library/PeiPcdLib/PeiPcdLib.mbd new file mode 100644 index 0000000000..bb90381ca0 --- /dev/null +++ b/MdePkg/Library/PeiPcdLib/PeiPcdLib.mbd @@ -0,0 +1,30 @@ + + + + + PeiPcdLib + 9dbf6f25-0da2-4a1d-8e12-e78de6ab4d0e + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/PeiPcdLib/PeiPcdLib.msa b/MdePkg/Library/PeiPcdLib/PeiPcdLib.msa new file mode 100644 index 0000000000..cc07e01f49 --- /dev/null +++ b/MdePkg/Library/PeiPcdLib/PeiPcdLib.msa @@ -0,0 +1,46 @@ + + + + + PeiPcdLib + PEIM + LIBRARY + 9dbf6f25-0da2-4a1d-8e12-e78de6ab4d0e + 0 + PCD Library Instance implemented with PCD PPI. + FIX ME! + Copyright (c) 2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + PcdLib + PeimEntryPoint + DebugLib + PeiServicesTablePointerLib + + + PeiPcdLib.c + + + MdePkg + + diff --git a/MdePkg/Library/PeiPcdLib/build.xml b/MdePkg/Library/PeiPcdLib/build.xml new file mode 100644 index 0000000000..5e79dde43e --- /dev/null +++ b/MdePkg/Library/PeiPcdLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.mbd b/MdePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.mbd new file mode 100644 index 0000000000..54cb661400 --- /dev/null +++ b/MdePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.mbd @@ -0,0 +1,30 @@ + + + + + PeiReportStatusCodeLib + 8c690838-7a22-45c4-aa58-a33e3e515cd4 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.msa b/MdePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.msa new file mode 100644 index 0000000000..c8f457a3ed --- /dev/null +++ b/MdePkg/Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.msa @@ -0,0 +1,68 @@ + + + + + PeiReportStatusCodeLib + PEIM + LIBRARY + 8c690838-7a22-45c4-aa58-a33e3e515cd4 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + ReportStatusCodeLib + DebugLib + BaseLib + BaseMemoryLib + PeiServicesTablePointerLib + PcdLib + IoLib + + + ReportStatusCodeLib.c + PostCode.c + + + MdePkg + + + + StatusCodeDataTypeDebug + + + StatusCodeDataTypeAssert + + + StatusCodeSpecificData + + + + + PcdReportStatusCodePropertyMask + 0x00000007 + UINT8 + + + diff --git a/MdePkg/Library/PeiReportStatusCodeLib/PostCode.c b/MdePkg/Library/PeiReportStatusCodeLib/PostCode.c new file mode 100644 index 0000000000..c5d32e77fb --- /dev/null +++ b/MdePkg/Library/PeiReportStatusCodeLib/PostCode.c @@ -0,0 +1,125 @@ +/** @file + Report Status Code Library Post Code functions for PEI Phase. + + Copyright (c) 2006, 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. + +**/ + + +/** + Sends an 32-bit value to a POST card. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + Some implementations of this library function may perform I/O operations + directly to a POST card device. Other implementations may send Value to + ReportStatusCode(), and the status code reporting mechanism will eventually + display the 32-bit value on the status reporting device. + + PostCode() must actively prevent recursion. If PostCode() is called while + processing another any other Report Status Code Library function, then + PostCode() must return Value immediately. + + @param Value The 32-bit value to write to the POST card. + + @return Value + +**/ +UINT32 +EFIAPI +PostCode ( + IN UINT32 Value + ) +{ + DEBUG((EFI_D_INFO, "POST %08x\n", Value)); + IoWrite8 (0x80, (UINT8)(Value)); + return Value; +} + + +/** + Sends an 32-bit value to a POST and associated ASCII string. + + Sends the 32-bit value specified by Value to a POST card, and returns Value. + If Description is not NULL, then the ASCII string specified by Description is + also passed to the handler that displays the POST card value. Some + implementations of this library function may perform I/O operations directly + to a POST card device. Other implementations may send Value to ReportStatusCode(), + and the status code reporting mechanism will eventually display the 32-bit + value on the status reporting device. + + PostCodeWithDescription()must actively prevent recursion. If + PostCodeWithDescription() is called while processing another any other Report + Status Code Library function, then PostCodeWithDescription() must return Value + immediately. + + @param Value The 32-bit value to write to the POST card. + @param Description Pointer to an ASCII string that is a description of the + POST code value. This is an optional parameter that may + be NULL. + + @return Value + +**/ +UINT32 +EFIAPI +PostCodeWithDescription ( + IN UINT32 Value, + IN CONST CHAR8 *Description OPTIONAL + ) +{ + DEBUG((EFI_D_INFO, "POST %08x - %s\n", Value, Description)); + IoWrite8 (0x80, (UINT8)(Value)); + return Value; +} + + +/** + Returns TRUE if POST Codes are enabled. + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportPostCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_POST_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if POST code descriptions are enabled. + + This function returns TRUE if the + REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED bit of + PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED + bit of PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTIONS_ENABLED + bit of PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportPostCodeDescriptionEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_POST_CODE_DESCRIPTION_ENABLED) != 0); +} diff --git a/MdePkg/Library/PeiReportStatusCodeLib/ReportStatusCodeLib.c b/MdePkg/Library/PeiReportStatusCodeLib/ReportStatusCodeLib.c new file mode 100644 index 0000000000..5c022d6adc --- /dev/null +++ b/MdePkg/Library/PeiReportStatusCodeLib/ReportStatusCodeLib.c @@ -0,0 +1,548 @@ +/** @file + Report Status Code Library for DXE Phase. + + Copyright (c) 2006, 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. + +**/ + +// +// Define the maximum extended data size that is supported in the PEI phase +// +#define MAX_EXTENDED_DATA_SIZE 0x200 + +/** + Internal worker function that reports a status code through the Status Code Protocol + + This function checks to see if a Status Code Protocol is present in the handle + database. If a Status Code Protocol is not present, then EFI_UNSUPPORTED is + returned. If a Status Code Protocol is present, then it is cached in gStatusCode, + and the ReportStatusCode() service of the Status Code Protocol is called passing in + Type, Value, Instance, CallerId, and Data. The result of this call is returned. + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. This is an optional parameter that may be + NULL. + @param Data Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to report the status code. + @retval EFI_UNSUPPORTED Status Code Protocol is not available. + +**/ +EFI_STATUS +InternalReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_STATUS_CODE_DATA *Data OPTIONAL + ) +{ + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + return (*PeiServices)->PeiReportStatusCode (PeiServices, Type, Value, Instance, CallerId, Data); +} + + +/** + Computes and returns the size, in bytes, of a device path. + + @param DevicePath A pointer to a device path. + + @return The size, in bytes, of DevicePath. + +**/ +UINTN +InternalReportStatusCodeDevicePathSize ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = DevicePath; + while (!EfiIsDevicePathEnd (DevicePath)) { + DevicePath = EfiNextDevicePathNode (DevicePath); + } + + // + // Subtract the start node from the end node and add in the size of the end node + // + return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath); +} + + +/** + Converts a status code to an 8-bit POST code value. + + Converts the status code specified by CodeType and Value to an 8-bit POST code + and returns the 8-bit POST code in PostCode. If CodeType is an + EFI_PROGRESS_CODE or CodeType is an EFI_ERROR_CODE, then bits 0..4 of PostCode + are set to bits 16..20 of Value, and bits 5..7 of PostCode are set to bits + 24..26 of Value., and TRUE is returned. Otherwise, FALSE is returned. + + If PostCode is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param PostCode A pointer to the 8-bit POST code value to return. + + @retval TRUE The status code specified by CodeType and Value was converted + to an 8-bit POST code and returned in PostCode. + @retval FALSE The status code specified by CodeType and Value could not be + converted to an 8-bit POST code value. + +**/ +BOOLEAN +EFIAPI +CodeTypeToPostCode ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + OUT UINT8 *PostCode + ) +{ + // + // If PostCode is NULL, then ASSERT() + // + ASSERT (PostCode != NULL); + + // + // Convert Value to an 8 bit post code + // + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_PROGRESS_CODE) || + ((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) ) { + *PostCode = (UINT8) (((Value & EFI_STATUS_CODE_CLASS_MASK) >> 24) << 5); + *PostCode |= (UINT8) (((Value & EFI_STATUS_CODE_SUBCLASS_MASK) >> 16) & 0x1f); + return TRUE; + } + return FALSE; +} + + +/** + Extracts ASSERT() information from a status code structure. + + Converts the status code specified by CodeType, Value, and Data to the ASSERT() + arguments specified by Filename, Description, and LineNumber. If CodeType is + an EFI_ERROR_CODE, and CodeType has a severity of EFI_ERROR_UNRECOVERED, and + Value has an operation mask of EFI_SW_EC_ILLEGAL_SOFTWARE_STATE, extract + Filename, Description, and LineNumber from the optional data area of the + status code buffer specified by Data. The optional data area of Data contains + a Null-terminated ASCII string for the FileName, followed by a Null-terminated + ASCII string for the Description, followed by a 32-bit LineNumber. If the + ASSERT() information could be extracted from Data, then return TRUE. + Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If Filename is NULL, then ASSERT(). + If Description is NULL, then ASSERT(). + If LineNumber is NULL, then ASSERT(). + + @param CodeType The type of status code being converted. + @param Value The status code value being converted. + @param Data Pointer to status code data buffer. + @param Filename Pointer to the source file name that generated the ASSERT(). + @param Description Pointer to the description of the ASSERT(). + @param LineNumber Pointer to source line number that generated the ASSERT(). + + @retval TRUE The status code specified by CodeType, Value, and Data was + converted ASSERT() arguments specified by Filename, Description, + and LineNumber. + @retval FALSE The status code specified by CodeType, Value, and Data could + not be converted to ASSERT() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractAssertInfo ( + IN EFI_STATUS_CODE_TYPE CodeType, + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_STATUS_CODE_DATA *Data, + OUT CHAR8 **Filename, + OUT CHAR8 **Description, + OUT UINT32 *LineNumber + ) +{ + EFI_DEBUG_ASSERT_DATA *AssertData; + + ASSERT (Data != NULL); + ASSERT (Filename != NULL); + ASSERT (Description != NULL); + ASSERT (LineNumber != NULL); + + if (((CodeType & EFI_STATUS_CODE_TYPE_MASK) == EFI_ERROR_CODE) && + ((CodeType & EFI_STATUS_CODE_SEVERITY_MASK) == EFI_ERROR_UNRECOVERED) && + ((Value & EFI_STATUS_CODE_OPERATION_MASK) == EFI_SW_EC_ILLEGAL_SOFTWARE_STATE)) { + AssertData = (EFI_DEBUG_ASSERT_DATA *)(Data + 1); + *Filename = (CHAR8 *)(AssertData + 1); + *Description = *Filename + AsciiStrLen (*Filename) + 1; + *LineNumber = AssertData->LineNumber; + return TRUE; + } + return FALSE; +} + + +/** + Extracts DEBUG() information from a status code structure. + + Converts the status code specified by Data to the DEBUG() arguments specified + by ErrorLevel, Marker, and Format. If type GUID in Data is + EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID, then extract ErrorLevel, Marker, and + Format from the optional data area of the status code buffer specified by Data. + The optional data area of Data contains a 32-bit ErrorLevel followed by Marker + which is 12 UINTN parameters, followed by a Null-terminated ASCII string for + the Format. If the DEBUG() information could be extracted from Data, then + return TRUE. Otherwise, FALSE is returned. + + If Data is NULL, then ASSERT(). + If ErrorLevel is NULL, then ASSERT(). + If Marker is NULL, then ASSERT(). + If Format is NULL, then ASSERT(). + + @param Data Pointer to status code data buffer. + @param ErrorLevel Pointer to error level mask for a debug message. + @param Marker Pointer to the variable argument list associated with Format. + @param Format Pointer to a Null-terminated ASCII format string of a + debug message. + + @retval TRUE The status code specified by Data was converted DEBUG() arguments + specified by ErrorLevel, Marker, and Format. + @retval FALSE The status code specified by Data could not be converted to + DEBUG() arguments. + +**/ +BOOLEAN +EFIAPI +ReportStatusCodeExtractDebugInfo ( + IN EFI_STATUS_CODE_DATA *Data, + OUT UINT32 *ErrorLevel, + OUT VA_LIST *Marker, + OUT CHAR8 **Format + ) +{ + EFI_DEBUG_INFO *DebugInfo; + + ASSERT (Data != NULL); + ASSERT (ErrorLevel != NULL); + ASSERT (Marker != NULL); + ASSERT (Format != NULL); + + // + // If the GUID type is not EFI_STATUS_CODE_DATA_TYPE_DEBUG_GUID then return FALSE + // + if (!CompareGuid (&Data->Type, &gEfiStatusCodeDataTypeDebugGuid)) { + return FALSE; + } + + // + // Retrieve the debug information from the status code record + // + DebugInfo = (EFI_DEBUG_INFO *)(Data + 1); + + *ErrorLevel = DebugInfo->ErrorLevel; + + // + // The first 12 * UINTN bytes of the string are really an + // argument stack to support varargs on the Format string. + // + *Marker = (VA_LIST) (DebugInfo + 1); + *Format = (CHAR8 *)(((UINT64 *)*Marker) + 12); + + return TRUE; +} + + +/** + Reports a status code. + + Reports the status code specified by the parameters Type and Value. Status + code also require an instance, caller ID, and extended data. This function + passed in a zero instance, NULL extended data, and a caller ID of + gEfiCallerIdGuid, which is the GUID for the module. + + ReportStatusCode()must actively prevent recusrsion. If ReportStatusCode() + is called while processing another any other Report Status Code Library function, + then ReportStatusCode() must return immediately. + + @param Type Status code type. + @param Value Status code value. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_DEVICE_ERROR There status code could not be reported due to a + device error. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCode ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value + ) +{ + return InternalReportStatusCode (Type, Value, 0, &gEfiCallerIdGuid, NULL); +} + + +/** + Reports a status code with a Device Path Protocol as the extended data. + + Allocates and fills in the extended data section of a status code with the + Device Path Protocol specified by DevicePath. This function is responsible + for allocating a buffer large enough for the standard header and the device + path. The standard header is filled in with a GUID of + gEfiStatusCodeSpecificDataGuid. The status code is reported with a zero + instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithDevicePath()must actively prevent recursion. If + ReportStatusCodeWithDevicePath() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithDevicePath() + must return EFI_DEVICE_ERROR immediately. + + If DevicePath is NULL, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param DevicePath Pointer to the Device Path Protocol to be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by DevicePath. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithDevicePath ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + ASSERT (DevicePath != NULL); + return ReportStatusCodeWithExtendedData ( + Type, + Value, + (VOID *)DevicePath, + InternalReportStatusCodeDevicePathSize (DevicePath) + ); +} + + +/** + Reports a status code with an extended data buffer. + + Allocates and fills in the extended data section of a status code with the + extended data specified by ExtendedData and ExtendedDataSize. ExtendedData + is assumed to be one of the data structures specified in Related Definitions. + These data structure do not have the standard header, so this function is + responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled + in with a GUID of gEfiStatusCodeSpecificDataGuid. The status code is reported + with a zero instance and a caller ID of gEfiCallerIdGuid. + + ReportStatusCodeWithExtendedData()must actively prevent recursion. If + ReportStatusCodeWithExtendedData() is called while processing another any other + Report Status Code Library function, then ReportStatusCodeWithExtendedData() + must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL, then ASSERT(). + If ExtendedDataSize is 0, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param ExtendedData Pointer to the extended data buffer to be reported. + @param ExtendedDataSize The size, in bytes, of the extended data buffer to + be reported. + + @retval EFI_SUCCESS The status code was reported with the extended + data specified by ExtendedData and ExtendedDataSize. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate the + extended data section. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeWithExtendedData ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN VOID *ExtendedData, + IN UINTN ExtendedDataSize + ) +{ + ASSERT (ExtendedData != NULL); + ASSERT (ExtendedDataSize != 0); + return ReportStatusCodeEx ( + Type, + Value, + 0, + NULL, + NULL, + ExtendedData, + ExtendedDataSize + ); +} + + +/** + Reports a status code with full parameters. + + The function reports a status code. If ExtendedData is NULL and ExtendedDataSize + is 0, then an extended data buffer is not reported. If ExtendedData is not + NULL and ExtendedDataSize is not 0, then an extended data buffer is allocated. + ExtendedData is assumed not have the standard status code header, so this function + is responsible for allocating a buffer large enough for the standard header and + the extended data passed into this function. The standard header is filled in + with a GUID specified by ExtendedDataGuid. If ExtendedDataGuid is NULL, then a + GUID of gEfiStatusCodeSpecificDatauid is used. The status code is reported with + an instance specified by Instance and a caller ID specified by CallerId. If + CallerId is NULL, then a caller ID of gEfiCallerIdGuid is used. + + ReportStatusCodeEx()must actively prevent recursion. If ReportStatusCodeEx() + is called while processing another any other Report Status Code Library function, + then ReportStatusCodeEx() must return EFI_DEVICE_ERROR immediately. + + If ExtendedData is NULL and ExtendedDataSize is not zero, then ASSERT(). + If ExtendedData is not NULL and ExtendedDataSize is zero, then ASSERT(). + + @param Type Status code type. + @param Value Status code value. + @param Instance Status code instance number. + @param CallerId Pointer to a GUID that identifies the caller of this + function. If this parameter is NULL, then a caller + ID of gEfiCallerIdGuid is used. + @param ExtendedDataGuid Pointer to the GUID for the extended data buffer. + If this parameter is NULL, then a the status code + standard header is filled in with + gEfiStatusCodeSpecificDataGuid. + @param ExtendedData Pointer to the extended data buffer. This is an + optional parameter that may be NULL. + @param ExtendedDataSize The size, in bytes, of the extended data buffer. + + @retval EFI_SUCCESS The status code was reported. + @retval EFI_OUT_OF_RESOURCES There were not enough resources to allocate + the extended data section if it was specified. + @retval EFI_UNSUPPORTED Report status code is not supported + +**/ +EFI_STATUS +EFIAPI +ReportStatusCodeEx ( + IN EFI_STATUS_CODE_TYPE Type, + IN EFI_STATUS_CODE_VALUE Value, + IN UINT32 Instance, + IN EFI_GUID *CallerId OPTIONAL, + IN EFI_GUID *ExtendedDataGuid OPTIONAL, + IN VOID *ExtendedData OPTIONAL, + IN UINTN ExtendedDataSize + ) +{ + EFI_STATUS_CODE_DATA *StatusCodeData; + UINT64 Buffer[MAX_EXTENDED_DATA_SIZE / sizeof (UINT64)]; + + ASSERT (!((ExtendedData == NULL) && (ExtendedDataSize != 0))); + ASSERT (!((ExtendedData != NULL) && (ExtendedDataSize == 0))); + + if (ExtendedDataSize > (MAX_EXTENDED_DATA_SIZE - sizeof (EFI_STATUS_CODE_DATA))) { + return EFI_OUT_OF_RESOURCES; + } + StatusCodeData = (EFI_STATUS_CODE_DATA *)Buffer; + StatusCodeData->HeaderSize = sizeof (EFI_STATUS_CODE_DATA); + StatusCodeData->Size = (UINT16)ExtendedDataSize; + if (ExtendedDataGuid == NULL) { + ExtendedDataGuid = &gEfiStatusCodeSpecificDataGuid; + } + CopyGuid (&StatusCodeData->Type, ExtendedDataGuid); + CopyMem (StatusCodeData + 1, ExtendedData, ExtendedDataSize); + if (CallerId == NULL) { + CallerId = &gEfiCallerIdGuid; + } + return InternalReportStatusCode (Type, Value, Instance, CallerId, StatusCodeData); +} + + +/** + Returns TRUE if status codes of type EFI_PROGRESS_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportProgressCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_PROGRESS_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if status codes of type EFI_ERROR_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportErrorCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_ERROR_CODE_ENABLED) != 0); +} + + +/** + Returns TRUE if status codes of type EFI_DEBUG_CODE are enabled + + This function returns TRUE if the REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED + bit of PcdReportStatusCodeProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is set. + @retval FALSE The REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdReportStatusCodeProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +ReportDebugCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdReportStatusCodePropertyMask) & REPORT_STATUS_CODE_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} diff --git a/MdePkg/Library/PeiReportStatusCodeLib/build.xml b/MdePkg/Library/PeiReportStatusCodeLib/build.xml new file mode 100644 index 0000000000..53f59b1e93 --- /dev/null +++ b/MdePkg/Library/PeiReportStatusCodeLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c b/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c new file mode 100644 index 0000000000..2726c53fc5 --- /dev/null +++ b/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.c @@ -0,0 +1,50 @@ +/** @file + Resource Publication Library that uses PEI Core Services to publish system memory. + + Copyright (c) 2006, 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. + + Module Name: PeiResourcePublicationLib.c + +**/ + + +/** + + Declares the presence of permanent system memory in the platform. + + Declares that the system memory buffer specified by MemoryBegin and MemoryLength + as permanent memory that may be used for general purpose use by software. + The amount of memory available to software may be less than MemoryLength + if published memory has alignment restrictions. + + @param MemoryBegin The start address of the memory being declared. + @param MemoryLength The number of bytes of memory being declared. + + @retval RETURN_SUCCESS The memory buffer was published. + @retval RETURN_OUT_OF_RESOURCES There are not enough resources to publish the memory buffer + +**/ +RETURN_STATUS +EFIAPI +PublishSystemMemory ( + IN PHYSICAL_ADDRESS MemoryBegin, + IN UINT64 MemoryLength + ) +{ + EFI_STATUS Status; + + ASSERT (MemoryLength > 0); + ASSERT (MemoryLength <= (MAX_ADDRESS - MemoryBegin + 1)); + + Status = PeiCoreInstallPeiMemory (MemoryBegin, MemoryLength); + + return (RETURN_STATUS) Status; +} + diff --git a/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.mbd b/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.mbd new file mode 100644 index 0000000000..4271c550ef --- /dev/null +++ b/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.mbd @@ -0,0 +1,30 @@ + + + + + PeiResourcePublicationLib + e8d6390d-e190-4957-9ab6-d47d51b01336 + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-17 09:00 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.msa b/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.msa new file mode 100644 index 0000000000..c4c6109680 --- /dev/null +++ b/MdePkg/Library/PeiResourcePublicationLib/PeiResourcePublicationLib.msa @@ -0,0 +1,45 @@ + + + + + PeiResourcePublicationLib + PEIM + LIBRARY + e8d6390d-e190-4957-9ab6-d47d51b01336 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2006, 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. + + 0 + 2006-03-17 09:00 + 2006-03-19 15:17 + + + ResourcePublicationLib + PeiCoreLib + DebugLib + + + PeiResourcePublicationLib.c + + + MdePkg + + diff --git a/MdePkg/Library/PeiResourcePublicationLib/build.xml b/MdePkg/Library/PeiResourcePublicationLib/build.xml new file mode 100644 index 0000000000..b5ad8581e9 --- /dev/null +++ b/MdePkg/Library/PeiResourcePublicationLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c b/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c new file mode 100644 index 0000000000..0240c38dbc --- /dev/null +++ b/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointer.c @@ -0,0 +1,39 @@ +/** @file + PEI Services Table Pointer Library. + + Copyright (c) 2006, 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. + + Module Name: PeiServicesTablePointer.c + +**/ + + + +static EFI_PEI_SERVICES **gPeiServices; + +EFI_PEI_SERVICES ** +GetPeiServicesTablePointer ( + VOID + ) +{ + return gPeiServices; +} + +/** +**/ +EFI_STATUS +PeiServicesTablePointerLibConstructor ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + gPeiServices = PeiServices; + return EFI_SUCCESS; +} diff --git a/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.mbd b/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.mbd new file mode 100644 index 0000000000..c45d77e39c --- /dev/null +++ b/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.mbd @@ -0,0 +1,30 @@ + + + + + PeiServicesTablePointerLib + 1c747f6b-0a58-49ae-8ea3-0327a4fa10e3 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.msa b/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.msa new file mode 100644 index 0000000000..b1451eae1c --- /dev/null +++ b/MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.msa @@ -0,0 +1,48 @@ + + + + + PeiServicesTablePointerLib + PEIM + LIBRARY + 1c747f6b-0a58-49ae-8ea3-0327a4fa10e3 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + PeiServicesTablePointerLib + + + PeiServicesTablePointer.c + + + MdePkg + + + + PeiServicesTablePointerLibConstructor + + + diff --git a/MdePkg/Library/PeiServicesTablePointerLib/build.xml b/MdePkg/Library/PeiServicesTablePointerLib/build.xml new file mode 100644 index 0000000000..b3c94a87b2 --- /dev/null +++ b/MdePkg/Library/PeiServicesTablePointerLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointer.c b/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointer.c new file mode 100644 index 0000000000..285a5a05ad --- /dev/null +++ b/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointer.c @@ -0,0 +1,37 @@ +/** @file + PEI Services Table Pointer Library. + + Copyright (c) 2006, 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. + + Module Name: PeiServicesTablePointer.c + +**/ + + + +EFI_PEI_SERVICES ** +GetPeiServicesTablePointer ( + VOID + ) +{ + return (EFI_PEI_SERVICES **)(UINTN)AsmReadMm7 (); +} + +/** +**/ +EFI_STATUS +PeiServicesTablePointerLibConstructor ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + AsmWriteMm7 ((UINT64)(UINTN)PeiServices); + return EFI_SUCCESS; +} diff --git a/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointerLibMm7.mbd b/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointerLibMm7.mbd new file mode 100644 index 0000000000..5023d92701 --- /dev/null +++ b/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointerLibMm7.mbd @@ -0,0 +1,30 @@ + + + + + PeiServicesTablePointerLibMm7 + e6e9c1f8-2c8a-4f4b-a27c-c382e4bb8e67 + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointerLibMm7.msa b/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointerLibMm7.msa new file mode 100644 index 0000000000..2afb2ed831 --- /dev/null +++ b/MdePkg/Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointerLibMm7.msa @@ -0,0 +1,49 @@ + + + + + PeiServicesTablePointerLibMm7 + PEIM + LIBRARY + e6e9c1f8-2c8a-4f4b-a27c-c382e4bb8e67 + 0 + Component description file for the entry point to a EFIDXE Drivers + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + PeiServicesTablePointerLib + BaseLib + + + PeiServicesTablePointer.c + + + MdePkg + + + + PeiServicesTablePointerLibConstructor + + + diff --git a/MdePkg/Library/PeiServicesTablePointerLibMm7/build.xml b/MdePkg/Library/PeiServicesTablePointerLibMm7/build.xml new file mode 100644 index 0000000000..af443df77c --- /dev/null +++ b/MdePkg/Library/PeiServicesTablePointerLibMm7/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeiSmbusLib/InternalSmbusLib.h b/MdePkg/Library/PeiSmbusLib/InternalSmbusLib.h new file mode 100644 index 0000000000..3c0b597fc5 --- /dev/null +++ b/MdePkg/Library/PeiSmbusLib/InternalSmbusLib.h @@ -0,0 +1,112 @@ +/** @file +Internal header file for Smbus library. + +Copyright (c) 2006, 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. + + +Module Name: SmbusLib.c + +**/ + +#ifndef __INTERNAL_SMBUS_LIB_H +#define __INTERNAL_SMBUS_LIB_H + +#define SMBUS_LIB_PEC(SmBusAddress) ((BOOLEAN) ((SmBusAddress) & 0x01)) +#define SMBUS_LIB_SLAVE_ADDRESS(SmBusAddress) (((SmBusAddress) >> 1) & 0x7f) +#define SMBUS_LIB_COMMAND(SmBusAddress) (((SmBusAddress) >> 8) & 0xff) +#define SMBUS_LIB_LENGTH(SmBusAddress) (((SmBusAddress) >> 16) & 0x1f) +#define SMBUS_LIB_RESEARVED(SmBusAddress) (((SmBusAddress) >> 21)) + +// +// Declaration for internal functions +// +/** + Executes an SMBus operation to an SMBus controller. + + This function provides a standard way to execute Smbus script + as defined in the SmBus Specification. The data can either be of + the Length byte, word, or a block of data. + + @param SmbusOperation Signifies which particular SMBus hardware protocol instance that it will use to + execute the SMBus transactions. + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Length Signifies the number of bytes that this operation will do. The maximum number of + bytes can be revision specific and operation specific. + @param Buffer Contains the value of data to execute to the SMBus slave device. Not all operations + require this argument. The length of this buffer is identified by Length. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The actual number of bytes that are executed for this operation.. + +**/ +UINTN +InternalSmBusExec ( + IN EFI_SMBUS_OPERATION SmbusOperation, + IN UINTN SmBusAddress, + IN UINTN Length, + IN VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ); + +/** + Assigns an SMBUS slave addresses. + + Assigns the SMBUS device specified by Uuid the slave address specified by SmBusAddress. + The status of the executed command is returned. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Uuid Pointer to the UUID of the device to assign a slave address. + It will assign to all SMBUS slave devices if it is NULL. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +InternalSmBusArpDevice ( + IN UINTN SmBusAddress, + IN CONST GUID *Uuid OPTIONAL + ); + +/** + Retrieves the mapping of all the SMBus devices. + + The GetArpMap() function returns the mapping of all the SMBus devices + that are enumerated by the SMBus host driver. + + @param Length Size of the buffer that contains the SMBus device map. + @param SmbusDeviceMap The pointer to the device map as enumerated by the SMBus controller driver. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +InternalGetArpMap ( + OUT UINTN *Length, + OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap + ); + +#endif diff --git a/MdePkg/Library/PeiSmbusLib/PeiSmbusLib.c b/MdePkg/Library/PeiSmbusLib/PeiSmbusLib.c new file mode 100644 index 0000000000..3ada624f68 --- /dev/null +++ b/MdePkg/Library/PeiSmbusLib/PeiSmbusLib.c @@ -0,0 +1,177 @@ +/** @file +Implementation of SmBusLib class library for PEI phase. + +Copyright (c) 2006, 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. + + +Module Name: PeiSmbusLib.c + +**/ + +#include "InternalSmbusLib.h" + +/** + Gets Smbus PPIs. + + This internal function retrieves Smbus PPI from PPI database. + + @param PeiServices An indirect pointer to the EFI_PEI_SERVICES published by the PEI Foundation. + + @return The pointer to Smbus PPI. + +**/ +EFI_PEI_SMBUS_PPI * +InternalGetSmbusPpi ( + EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + EFI_PEI_SMBUS_PPI *SmbusPpi; + + Status = (*PeiServices)->LocatePpi (PeiServices, &gEfiPeiSmbusPpiGuid, 0, NULL, (VOID **) &SmbusPpi); + ASSERT_EFI_ERROR (Status); + ASSERT (SmbusPpi != NULL); + + return SmbusPpi; +} + +/** + Executes an SMBus operation to an SMBus controller. + + This function provides a standard way to execute Smbus script + as defined in the SmBus Specification. The data can either be of + the Length byte, word, or a block of data. + + @param SmbusOperation Signifies which particular SMBus hardware protocol instance that it will use to + execute the SMBus transactions. + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Length Signifies the number of bytes that this operation will do. The maximum number of + bytes can be revision specific and operation specific. + @param Buffer Contains the value of data to execute to the SMBus slave device. Not all operations + require this argument. The length of this buffer is identified by Length. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The actual number of bytes that are executed for this operation.. + +**/ +UINTN +InternalSmBusExec ( + IN EFI_SMBUS_OPERATION SmbusOperation, + IN UINTN SmBusAddress, + IN UINTN Length, + IN VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + EFI_PEI_SMBUS_PPI *SmbusPpi; + EFI_PEI_SERVICES **PeiServices; + RETURN_STATUS ReturnStatus; + EFI_SMBUS_DEVICE_ADDRESS SmbusDeviceAddress; + + PeiServices = GetPeiServicesTablePointer (); + SmbusPpi = InternalGetSmbusPpi (PeiServices); + SmbusDeviceAddress.SmbusDeviceAddress = SMBUS_LIB_SLAVE_ADDRESS (SmBusAddress); + + ReturnStatus = SmbusPpi->Execute ( + PeiServices, + SmbusPpi, + SmbusDeviceAddress, + SMBUS_LIB_COMMAND (SmBusAddress), + SmbusOperation, + SMBUS_LIB_PEC (SmBusAddress), + &Length, + Buffer + ); + if (Status != NULL) { + *Status = ReturnStatus; + } + + return Length; +} + +/** + Assigns an SMBUS slave addresses. + + Assigns the SMBUS device specified by Uuid the slave address specified by SmBusAddress. + The status of the executed command is returned. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Uuid Pointer to the UUID of the device to assign a slave address. + It will assign to all SMBUS slave devices if it is NULL. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +InternalSmBusArpDevice ( + IN UINTN SmBusAddress, + IN CONST GUID *Uuid OPTIONAL + ) +{ + EFI_PEI_SMBUS_PPI *SmbusPpi; + EFI_PEI_SERVICES **PeiServices; + EFI_SMBUS_DEVICE_ADDRESS SmbusDeviceAddress; + + PeiServices = GetPeiServicesTablePointer (); + SmbusPpi = InternalGetSmbusPpi (PeiServices); + + SmbusDeviceAddress.SmbusDeviceAddress = SMBUS_LIB_SLAVE_ADDRESS (SmBusAddress); + return (RETURN_STATUS) SmbusPpi->ArpDevice ( + PeiServices, + SmbusPpi, + (BOOLEAN) (Uuid == NULL), + (EFI_SMBUS_UDID *) Uuid, + &SmbusDeviceAddress + ); +} + +/** + Retrieves the mapping of all the SMBus devices. + + The GetArpMap() function returns the mapping of all the SMBus devices + that are enumerated by the SMBus host driver. + + @param Length Size of the buffer that contains the SMBus device map. + @param SmbusDeviceMap The pointer to the device map as enumerated by the SMBus controller driver. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +InternalGetArpMap ( + OUT UINTN *Length, + OUT EFI_SMBUS_DEVICE_MAP **SmbusDeviceMap + ) +{ + EFI_PEI_SMBUS_PPI *SmbusPpi; + EFI_PEI_SERVICES **PeiServices; + + PeiServices = GetPeiServicesTablePointer (); + SmbusPpi = InternalGetSmbusPpi (PeiServices); + + return (RETURN_STATUS) SmbusPpi->GetArpMap (PeiServices, SmbusPpi, Length, SmbusDeviceMap); +} diff --git a/MdePkg/Library/PeiSmbusLib/PeiSmbusLib.mbd b/MdePkg/Library/PeiSmbusLib/PeiSmbusLib.mbd new file mode 100644 index 0000000000..5b5bfdf8d7 --- /dev/null +++ b/MdePkg/Library/PeiSmbusLib/PeiSmbusLib.mbd @@ -0,0 +1,30 @@ + + + + + PeiSmbusLib + 56E800D9-7603-4e01-9581-1FFB9E98F5BE + 0 + FIX ME! + Copyright (c) 2006, 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. + + 2006-04-17 22:30 + 2006-04-17 22:30 + + diff --git a/MdePkg/Library/PeiSmbusLib/PeiSmbusLib.msa b/MdePkg/Library/PeiSmbusLib/PeiSmbusLib.msa new file mode 100644 index 0000000000..f96ba746c7 --- /dev/null +++ b/MdePkg/Library/PeiSmbusLib/PeiSmbusLib.msa @@ -0,0 +1,51 @@ + + + + + PeiSmbusLib + PEIM + LIBRARY + 51C4C059-67F0-4e3c-9A55-FF42A8291C8C + 0 + SmBus Library Instance implemented with SmBus PPI. + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-17 22:30 + 2006-04-17 22:30 + + + SmbusLib + PeimEntryPoint + DebugLib + PeiServicesTablePointerLib + BaseMemoryLib + + + PeiSmbusLib.c + SmbusLib.c + + + MdePkg + + + Smbus + + diff --git a/MdePkg/Library/PeiSmbusLib/SmbusLib.c b/MdePkg/Library/PeiSmbusLib/SmbusLib.c new file mode 100644 index 0000000000..da29fab5a3 --- /dev/null +++ b/MdePkg/Library/PeiSmbusLib/SmbusLib.c @@ -0,0 +1,597 @@ +/** @file +Implementation of SmBusLib class library for PEI phase. + +Copyright (c) 2006, 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. + + +Module Name: SmbusLib.c + +**/ + +#include "InternalSmbusLib.h" + +/** + Executes an SMBUS quick read command. + + Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + +**/ +VOID +EFIAPI +SmBusQuickRead ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusQuickRead, SmBusAddress, 0, NULL, Status); +} + +/** + Executes an SMBUS quick write command. + + Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + If Status is not NULL, then the status of the executed command is returned in Status. + If PEC is set in SmBusAddress, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + +**/ +BOOLEAN +EFIAPI +SmBusQuickWrite ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusQuickWrite, SmBusAddress, 0, NULL, Status); + // + // Bugbug: Undefined return value in spec + // + return TRUE; +} + +/** + Executes an SMBUS receive byte command. + + Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address field of SmBusAddress is required. + The byte received from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte received from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReceiveByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReceiveByte, SmBusAddress, 1, &Byte, Status); + + return Byte; +} + +/** + Executes an SMBUS send byte command. + + Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress. + The byte specified by Value is sent. + Only the SMBUS slave address field of SmBusAddress is required. Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to send. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusSendByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + Byte = Value; + InternalSmBusExec (EfiSmbusSendByte, SmBusAddress, 1, &Byte, Status); + + return Value; +} + +/** + Executes an SMBUS read data byte command. + + Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 8-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte read from the SMBUS. + +**/ +UINT8 +EFIAPI +SmBusReadDataByte ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReadByte, SmBusAddress, 1, &Byte, Status); + + return Byte; +} + +/** + Executes an SMBUS write data byte command. + + Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress. + The 8-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 8-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT8 +EFIAPI +SmBusWriteDataByte ( + IN UINTN SmBusAddress, + IN UINT8 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT8 Byte; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + Byte = Value; + InternalSmBusExec (EfiSmbusWriteByte, SmBusAddress, 1, &Byte, Status); + + return Value; +} + +/** + Executes an SMBUS read data word command. + + Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value read from the SMBUS is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The byte read from the SMBUS. + +**/ +UINT16 +EFIAPI +SmBusReadDataWord ( + IN UINTN SmBusAddress, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusReadWord, SmBusAddress, 2, &Word, Status); + + return Word; +} + +/** + Executes an SMBUS write data word command. + + Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Value is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The parameter of Value. + +**/ +UINT16 +EFIAPI +SmBusWriteDataWord ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + UINT16 Word; + + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + Word = Value; + InternalSmBusExec (EfiSmbusWriteWord, SmBusAddress, 2, &Word, Status); + + return Value; +} + +/** + Executes an SMBUS process call command. + + Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress. + The 16-bit value specified by Value is written. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + The 16-bit value returned by the process call command is returned. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is not zero, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Value The 16-bit value to write. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The 16-bit value returned by the process call command. + +**/ +UINT16 +EFIAPI +SmBusProcessCall ( + IN UINTN SmBusAddress, + IN UINT16 Value, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + InternalSmBusExec (EfiSmbusProcessCall, SmBusAddress, 2, &Value, Status); + + return Value; +} + +/** + Executes an SMBUS read block command. + + Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress. + Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required. + Bytes are read from the SMBUS and stored in Buffer. + The number of bytes read is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller¡¯s responsibility to make sure Buffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If Length in SmBusAddress is not zero, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes read. + +**/ +UINTN +EFIAPI +SmBusReadBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return InternalSmBusExec (EfiSmbusReadBlock, SmBusAddress, 0x1f, Buffer, Status); +} + +/** + Executes an SMBUS write block command. + + Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from Buffer. + The number of bytes written is returned, and will never return a value larger than 32-bytes. + If Status is not NULL, then the status of the executed command is returned in Status. + If Length in SmBusAddress is zero or greater than 32, then ASSERT(). + If Buffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Buffer Pointer to the buffer to store the bytes read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusWriteBlock ( + IN UINTN SmBusAddress, + OUT VOID *Buffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (Buffer != NULL); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + return InternalSmBusExec (EfiSmbusWriteBlock, SmBusAddress, SMBUS_LIB_LENGTH (SmBusAddress), Buffer, Status); +} + +/** + Executes an SMBUS block process call command. + + Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress. + The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required. + Bytes are written to the SMBUS from OutBuffer. Bytes are then read from the SMBUS into InBuffer. + If Status is not NULL, then the status of the executed command is returned in Status. + It is the caller¡¯s responsibility to make sure InBuffer is large enough for the total number of bytes read. + SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes. + If OutBuffer is NULL, then ASSERT(). + If InBuffer is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param OutBuffer Pointer to the buffer of bytes to write to the SMBUS. + @param InBuffer Pointer to the buffer of bytes to read from the SMBUS. + @param Status Return status for the executed command. + This is an optional parameter and may be NULL. + + @return The number of bytes written. + +**/ +UINTN +EFIAPI +SmBusBlockProcessCall ( + IN UINTN SmBusAddress, + OUT VOID *OutBuffer, + OUT VOID *InBuffer, + OUT RETURN_STATUS *Status OPTIONAL + ) +{ + ASSERT (InBuffer != NULL); + ASSERT (OutBuffer != NULL); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + + // + // BugBug: Not sure whether it's all right. + // + InternalSmBusExec (EfiSmbusWriteBlock, SmBusAddress, SMBUS_LIB_LENGTH (SmBusAddress), OutBuffer, Status); + + return InternalSmBusExec (EfiSmbusReadBlock, SmBusAddress, 1, InBuffer, Status); +} + +/** + Enumerates the SMBUS and assigns slave addresses. + + Executes the SMBUS enumeration algorithm and assigns a valid address to all SMBUS slave devices. + The total number of SMBUS slave devices detected is returned. + The status of the executed command is returned. + If Slave Address in SmBusAddress is not zero, then ASSERT(). + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +EFIAPI +SmBusArpAll ( + IN UINTN SmBusAddress + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_SLAVE_ADDRESS (SmBusAddress) == 0); + + return InternalSmBusArpDevice (SmBusAddress, NULL); +} + +/** + Assigns an SMBUS slave addresses. + + Assigns the SMBUS device specified by Uuid the slave address specified by SmBusAddress. + The status of the executed command is returned. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Uuid Pointer to the UUID of the device to assign a slave address. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +EFIAPI +SmBusArpDevice ( + IN UINTN SmBusAddress, + IN CONST GUID *Uuid + ) +{ + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + + return InternalSmBusArpDevice (SmBusAddress, Uuid); +} + +/** + Retrieves the UUID associated with an SMBUS slave device. + + Retrieves the UUID associated with the slave address specified + by SmBusAddress and returns the UUID in Uuid. + The status of the executed command is returned. + If Command in SmBusAddress is not zero, then ASSERT(). + If Length in SmBusAddress is not zero, then ASSERT(). + If PEC in SmBusAddress is set, then ASSERT(). + If Uuid is NULL, then ASSERT(). + If any reserved bits of SmBusAddress are set, then ASSERT(). + + @param SmBusAddress Address that encodes the SMBUS Slave Address, + SMBUS Command, SMBUS Data Length, and PEC. + @param Uuid Pointer to the UUID retrieved from the SMBUS slave device. + + @retval RETURN_SUCCESS The SMBUS command was executed. + @retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command. + @retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected + in the Host Status Register bit. + Device errors are a result of a transaction collision, illegal command field, + unclaimed cycle (host initiated), or bus errors (collisions). + +**/ +RETURN_STATUS +EFIAPI +SmBusGetUuid ( + IN UINTN SmBusAddress, + OUT GUID *Uuid + ) +{ + UINTN Length; + EFI_SMBUS_DEVICE_MAP *SmBusDeviceMap; + RETURN_STATUS ReturnStatus; + UINTN SmbusDeviceAddress; + UINTN Index; + + ASSERT (Uuid != NULL); + ASSERT (!SMBUS_LIB_PEC (SmBusAddress)); + ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_RESEARVED (SmBusAddress) == 0); + ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0); + + ReturnStatus = InternalGetArpMap (&Length, &SmBusDeviceMap); + if (!RETURN_ERROR (ReturnStatus)) { + SmbusDeviceAddress = SMBUS_LIB_SLAVE_ADDRESS (SmBusAddress); + for (Index = 0; Index < Length; Index++) { + if (SmBusDeviceMap[Index].SmbusDeviceAddress.SmbusDeviceAddress == SmbusDeviceAddress) { + CopyMem (Uuid, &SmBusDeviceMap[Index].SmbusDeviceUdid, sizeof (EFI_SMBUS_UDID)); + break; + } + } + } + + return ReturnStatus; +} diff --git a/MdePkg/Library/PeiSmbusLib/build.xml b/MdePkg/Library/PeiSmbusLib/build.xml new file mode 100644 index 0000000000..9f1b89302d --- /dev/null +++ b/MdePkg/Library/PeiSmbusLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c new file mode 100644 index 0000000000..b661646083 --- /dev/null +++ b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.c @@ -0,0 +1,68 @@ + +/** @file + Entry point to a PEIM. + +Copyright (c) 2006, 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. + +**/ + +/** + Image entry point of Peim. + + @param FfsHeader Pointer to FFS header the loaded driver. + @param PeiServices Pointer to the PEI services. + + @return Status returned by entry points of Peims. + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + if (_gPeimRevision != 0) { + // + // Make sure that the PEI spec revision of the platform is >= PEI spec revision of the driver + // + ASSERT ((*PeiServices)->Hdr.Revision >= _gPeimRevision); + } + + // + // Call constructor for all libraries + // + ProcessLibraryConstructorList (FfsHeader, PeiServices); + + // + // Call the driver entry point + // + return ProcessModuleEntryPointList (FfsHeader, PeiServices); +} + + +/** + Wrapper of Peim image entry point. + + @param FfsHeader Pointer to FFS header the loaded driver. + @param PeiServices Pointer to the PEI services. + + @return Status returned by entry points of Peims. + +**/ +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_FFS_FILE_HEADER *FfsHeader, + IN EFI_PEI_SERVICES **PeiServices + ) +{ + return _ModuleEntryPoint (FfsHeader, PeiServices); +} diff --git a/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.mbd b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.mbd new file mode 100644 index 0000000000..1a41f73e69 --- /dev/null +++ b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.mbd @@ -0,0 +1,30 @@ + + + + + PeimEntryPoint + fa177ff7-1fc7-458d-a358-d9d62ae61cec + 0 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.msa b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.msa new file mode 100644 index 0000000000..73d4e60d2f --- /dev/null +++ b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.msa @@ -0,0 +1,44 @@ + + + + + PeimEntryPoint + PEIM + LIBRARY + fa177ff7-1fc7-458d-a358-d9d62ae61cec + 0 + Component description file for the entry point to the PEI Core + FIX ME! + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + PeimEntryPoint + DebugLib + + + PeimEntryPoint.c + + + MdePkg + + diff --git a/MdePkg/Library/PeimEntryPoint/build.xml b/MdePkg/Library/PeimEntryPoint/build.xml new file mode 100644 index 0000000000..93a821692e --- /dev/null +++ b/MdePkg/Library/PeimEntryPoint/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c b/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c new file mode 100644 index 0000000000..aa990f7fdf --- /dev/null +++ b/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.c @@ -0,0 +1,47 @@ +/** @file + UEFI Boot Services Table Library. + + Copyright (c) 2006, 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. + + Module Name: UefiBootServicesTableLib.c + +**/ + +EFI_HANDLE gImageHandle; +EFI_SYSTEM_TABLE *gST; +EFI_BOOT_SERVICES *gBS; + +/** +**/ +EFI_STATUS +UefiBootServicesTableLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // Cache the Image Handle + // + gImageHandle = ImageHandle; + + // + // Cache pointer to the EFI System Table + // + gST = SystemTable; + ASSERT (gST != NULL); + + // + // Cache pointer to the EFI Boot Services Table + // + gBS = SystemTable->BootServices; + ASSERT (gBS != NULL); + + return EFI_SUCCESS; +} diff --git a/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.mbd b/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.mbd new file mode 100644 index 0000000000..dc6fda9ad3 --- /dev/null +++ b/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.mbd @@ -0,0 +1,30 @@ + + + + + UefiBootServicesTableLib + baa1baa3-0a8d-402c-8042-985115fae953 + 0 + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 2006-03-17 15:49 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.msa b/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.msa new file mode 100644 index 0000000000..90585bf722 --- /dev/null +++ b/MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.msa @@ -0,0 +1,49 @@ + + + + + UefiBootServicesTableLib + DXE_DRIVER + LIBRARY + baa1baa3-0a8d-402c-8042-985115fae953 + 0 + UEFI Boot Services Table Library + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-17 15:49 + 2006-03-19 15:17 + + + UefiBootServicesTableLib + DebugLib + + + UefiBootServicesTableLib.c + + + MdePkg + + + + UefiBootServicesTableLibConstructor + + + diff --git a/MdePkg/Library/UefiBootServicesTableLib/build.xml b/MdePkg/Library/UefiBootServicesTableLib/build.xml new file mode 100644 index 0000000000..c9f9fc980d --- /dev/null +++ b/MdePkg/Library/UefiBootServicesTableLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/UefiDebugLibConOut/DebugLib.c b/MdePkg/Library/UefiDebugLibConOut/DebugLib.c new file mode 100644 index 0000000000..4c068087be --- /dev/null +++ b/MdePkg/Library/UefiDebugLibConOut/DebugLib.c @@ -0,0 +1,247 @@ +/** @file + UEFI Debug Library that uses PrintLib to send messages to CONOUT. + + Copyright (c) 2006, 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. + +**/ + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + + +/** + + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print + the message specified by Format and the associated variable argument list to + the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ) +{ + CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) { + return; + } + + // + // Convert the DEBUG() message to a Unicode String + // + VA_START (Marker, Format); + UnicodeVSPrintAsciiFormat (Buffer, sizeof (Buffer), Format, Marker); + VA_END (Marker); + + // + // Send the print string to the Console Output device + // + if (gST->ConOut != NULL) { + gST->ConOut->OutputString (gST->ConOut, Buffer); + } +} + + +/** + + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form “ASSERT (): \n” + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recusrsion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a string of “(NULL) Filename” is printed. + + If Description is NULL, then a string of “(NULL) Description” is printed. + + @param FileName Pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description Pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) +{ + CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + // + // Generate the ASSERT() message in Unicode format + // + UnicodeSPrintAsciiFormat (Buffer, sizeof (Buffer), "ASSERT %s(%d): %s\n", FileName, LineNumber, Description); + + // + // Send the print string to the Console Output device + // + if (gST->ConOut != NULL) { + gST->ConOut->OutputString (gST->ConOut, Buffer); + } + + // + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings + // + if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { + CpuBreakpoint (); + } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { + CpuDeadLoop (); + } +} + + +/** + + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + + If Length is greater than (MAX_ADDRESS – Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue)); +} + + +/** + + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CODE()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CLEAR_MEMORY()macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} diff --git a/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.mbd b/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.mbd new file mode 100644 index 0000000000..12032d4094 --- /dev/null +++ b/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.mbd @@ -0,0 +1,30 @@ + + + + + UefiDebugLibConOut + 5cddfaf3-e9a7-4d16-bdce-1e002df475bb + 0 + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.msa b/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.msa new file mode 100644 index 0000000000..6d41033d8d --- /dev/null +++ b/MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.msa @@ -0,0 +1,65 @@ + + + + + UefiDebugLibConOut + UEFI_DRIVER + LIBRARY + 5cddfaf3-e9a7-4d16-bdce-1e002df475bb + 0 + Debug Library for UEFI drivers + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + DebugLib + UefiBootServicesTableLib + PrintLib + PcdLib + BaseLib + BaseMemoryLib + + + DebugLib.c + + + MdePkg + + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + + + diff --git a/MdePkg/Library/UefiDebugLibConOut/build.xml b/MdePkg/Library/UefiDebugLibConOut/build.xml new file mode 100644 index 0000000000..b314b5fffe --- /dev/null +++ b/MdePkg/Library/UefiDebugLibConOut/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c b/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c new file mode 100644 index 0000000000..7acbee5900 --- /dev/null +++ b/MdePkg/Library/UefiDebugLibStdErr/DebugLib.c @@ -0,0 +1,247 @@ +/** @file + UEFI Debug Library that uses PrintLib to send messages to STDERR. + + Copyright (c) 2006, 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. + +**/ + +// +// Define the maximum debug and assert message length that this library supports +// +#define MAX_DEBUG_MESSAGE_LENGTH 0x100 + + +/** + + Prints a debug message to the debug output device if the specified error level is enabled. + + If any bit in ErrorLevel is also set in PcdDebugPrintErrorLevel, then print + the message specified by Format and the associated variable argument list to + the debug output device. + + If Format is NULL, then ASSERT(). + + @param ErrorLevel The error level of the debug message. + @param Format Format string for the debug message to print. + +**/ +VOID +EFIAPI +DebugPrint ( + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ) +{ + CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + VA_LIST Marker; + + // + // If Format is NULL, then ASSERT(). + // + ASSERT (Format != NULL); + + // + // Check driver debug mask value and global mask + // + if ((ErrorLevel & PcdGet32(PcdDebugPrintErrorLevel)) == 0) { + return; + } + + // + // Convert the DEBUG() message to a Unicode String + // + VA_START (Marker, Format); + UnicodeVSPrintAsciiFormat (Buffer, sizeof (Buffer), Format, Marker); + VA_END (Marker); + + // + // Send the print string to the Standard Error device + // + if (gST->StdErr != NULL) { + gST->StdErr->OutputString (gST->StdErr, Buffer); + } +} + + +/** + + Prints an assert message containing a filename, line number, and description. + This may be followed by a breakpoint or a dead loop. + + Print a message of the form “ASSERT (): \n” + to the debug output device. If DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED bit of + PcdDebugProperyMask is set then CpuBreakpoint() is called. Otherwise, if + DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED bit of PcdDebugProperyMask is set then + CpuDeadLoop() is called. If neither of these bits are set, then this function + returns immediately after the message is printed to the debug output device. + DebugAssert() must actively prevent recusrsion. If DebugAssert() is called while + processing another DebugAssert(), then DebugAssert() must return immediately. + + If FileName is NULL, then a string of “(NULL) Filename” is printed. + + If Description is NULL, then a string of “(NULL) Description” is printed. + + @param FileName Pointer to the name of the source file that generated the assert condition. + @param LineNumber The line number in the source file that generated the assert condition + @param Description Pointer to the description of the assert condition. + +**/ +VOID +EFIAPI +DebugAssert ( + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) +{ + CHAR16 Buffer[MAX_DEBUG_MESSAGE_LENGTH]; + + // + // Generate the ASSERT() message in Unicode format + // + UnicodeSPrintAsciiFormat (Buffer, sizeof (Buffer), "ASSERT %s(%d): %s\n", FileName, LineNumber, Description); + + // + // Send the print string to the Standard Error device + // + if (gST->StdErr != NULL) { + gST->StdErr->OutputString (gST->StdErr, Buffer); + } + + // + // Generate a Breakpoint, DeadLoop, or NOP based on PCD settings + // + if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_BREAKPOINT_ENABLED) != 0) { + CpuBreakpoint (); + } else if ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_ASSERT_DEADLOOP_ENABLED) != 0) { + CpuDeadLoop (); + } +} + + +/** + + Fills a target buffer with PcdDebugClearMemoryValue, and returns the target buffer. + + This function fills Length bytes of Buffer with the value specified by + PcdDebugClearMemoryValue, and returns Buffer. + + If Buffer is NULL, then ASSERT(). + + If Length is greater than (MAX_ADDRESS – Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to fill with PcdDebugClearMemoryValue. + @param Length Number of bytes in Buffer to fill with zeros PcdDebugClearMemoryValue. + + @return Buffer + +**/ +VOID * +EFIAPI +DebugClearMemory ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + // + // If Buffer is NULL, then ASSERT(). + // + ASSERT (Buffer != NULL); + + // + // SetMem() checks for the the ASSERT() condition on Length and returns Buffer + // + return SetMem (Buffer, Length, PcdGet8(PcdDebugClearMemoryValue)); +} + + +/** + + Returns TRUE if ASSERT() macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugAssertEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_PRINT_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugPrintEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_PRINT_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CODE()macros are enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CODE_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugCodeEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_DEBUG_CODE_ENABLED) != 0); +} + + +/** + + Returns TRUE if DEBUG_CLEAR_MEMORY()macro is enabled. + + This function returns TRUE if the DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of + PcdDebugProperyMask is set. Otherwise FALSE is returned. + + @retval TRUE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is set. + @retval FALSE The DEBUG_PROPERTY_DEBUG_CLEAR_MEMORY_ENABLED bit of PcdDebugProperyMask is clear. + +**/ +BOOLEAN +EFIAPI +DebugClearMemoryEnabled ( + VOID + ) +{ + return ((PcdGet8(PcdDebugPropertyMask) & DEBUG_PROPERTY_CLEAR_MEMORY_ENABLED) != 0); +} diff --git a/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.mbd b/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.mbd new file mode 100644 index 0000000000..ecec5af1cf --- /dev/null +++ b/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.mbd @@ -0,0 +1,30 @@ + + + + + UefiDebugLibStdErr + b57a1df6-ffdb-4247-a3df-3a562176751a + 0 + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.msa b/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.msa new file mode 100644 index 0000000000..e8943dad5b --- /dev/null +++ b/MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.msa @@ -0,0 +1,65 @@ + + + + + UefiDebugLibStdErr + UEFI_DRIVER + LIBRARY + b57a1df6-ffdb-4247-a3df-3a562176751a + 0 + Debug Library for UEFI drivers + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + DebugLib + UefiBootServicesTableLib + PrintLib + PcdLib + BaseLib + BaseMemoryLib + + + DebugLib.c + + + MdePkg + + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + + + diff --git a/MdePkg/Library/UefiDebugLibStdErr/build.xml b/MdePkg/Library/UefiDebugLibStdErr/build.xml new file mode 100644 index 0000000000..c7449e3d75 --- /dev/null +++ b/MdePkg/Library/UefiDebugLibStdErr/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c b/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c new file mode 100644 index 0000000000..8dc84f48b7 --- /dev/null +++ b/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.c @@ -0,0 +1,434 @@ +/** @file + Device Path services. The thing to remember is device paths are built out of + nodes. The device path is terminated by an end node that is length + sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL) + all over this file. + + The only place where multi-instance device paths are supported is in + environment varibles. Multi-instance device paths should never be placed + on a Handle. + + Copyright (c) 2006, 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. + + Module Name: UefiDevicePathLib.c + +**/ + +/** + This function returns the size, in bytes, + of the device path data structure specified by DevicePath. + If DevicePath is NULL, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @return The size of a device path in bytes. + +**/ +UINTN +EFIAPI +GetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = DevicePath; + while (!EfiIsDevicePathEnd (DevicePath)) { + DevicePath = EfiNextDevicePathNode (DevicePath); + } + + // + // Compute the size and add back in the size of the end device path structure + // + return ((UINTN) DevicePath - (UINTN) Start) + sizeof (EFI_DEVICE_PATH_PROTOCOL); +} + +/** + This function allocates space for a new copy of the device path + specified by DevicePath. + + @param DevicePath A pointer to a device path data structure. + + @return The duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + UINTN Size; + + // + // Compute the size + // + Size = GetDevicePathSize (DevicePath); + if (Size == 0) { + return NULL; + } + + // + // Allocate space for duplicate device path + // + NewDevicePath = AllocateCopyPool (Size, DevicePath); + + return NewDevicePath; +} + +/** + This function appends the device path SecondDevicePath + to every device path instance in FirstDevicePath. + + @param FirstDevicePath A pointer to a device path data structure. + + @param SecondDevicePath A pointer to a device path data structure. + + @return A pointer to the new device path is returned. + NULL is returned if space for the new device path could not be allocated from pool. + It is up to the caller to free the memory used by FirstDevicePath and SecondDevicePath + if they are no longer needed. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath + ) +{ + UINTN Size; + UINTN Size1; + UINTN Size2; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath2; + + // + // If there's only 1 path, just duplicate it + // + if (FirstDevicePath == NULL) { + return DuplicateDevicePath (SecondDevicePath); + } + + if (SecondDevicePath == NULL) { + return DuplicateDevicePath (FirstDevicePath); + } + + // + // Allocate space for the combined device path. It only has one end node of + // length EFI_DEVICE_PATH_PROTOCOL + // + Size1 = GetDevicePathSize (FirstDevicePath); + Size2 = GetDevicePathSize (SecondDevicePath); + Size = Size1 + Size2 - sizeof (EFI_DEVICE_PATH_PROTOCOL); + + NewDevicePath = AllocatePool (Size); + + if (NewDevicePath != NULL) { + NewDevicePath = CopyMem (NewDevicePath, FirstDevicePath, Size1); + // + // Over write Src1 EndNode and do the copy + // + DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + (Size1 - sizeof (EFI_DEVICE_PATH_PROTOCOL))); + CopyMem (DevicePath2, SecondDevicePath, Size2); + } + + return NewDevicePath; +} + +/** + This function appends the device path node SecondDevicePath + to every device path instance in FirstDevicePath. + + @param FirstDevicePath A pointer to a device path data structure. + + @param SecondDevicePath A pointer to a single device path node. + + @return A pointer to the new device path. + If there is not enough temporary pool memory available to complete this function, + then NULL is returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *NextNode; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + UINTN NodeLength; + UINTN Size1; + + // + // Build a Node that has a terminator on it + // + NodeLength = DevicePathNodeLength (SecondDevicePath); + Size1 = GetDevicePathSize (FirstDevicePath); + + NewDevicePath = AllocatePool (NodeLength + Size1); + if (NewDevicePath != NULL) { + // + // Copy the first device path to the new device path + // + NewDevicePath = CopyMem (NewDevicePath, FirstDevicePath, Size1); + + // + // Copy the device path node to the new device path + // + NextNode = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + (Size1 - sizeof (EFI_DEVICE_PATH_PROTOCOL))); + NextNode = CopyMem (NextNode, SecondDevicePath, NodeLength); + + // + // Terminate the whole device path + // + NextNode = NextDevicePathNode (NextNode); + SetDevicePathEndNode (NextNode); + } + return NewDevicePath; +} + +/** + This function appends the device path instance Instance to the device path Source. + If Source is NULL, then a new device path with one instance is created. + + @param Source A pointer to a device path data structure. + @param Instance A pointer to a device path instance. + + @return A pointer to the new device path. + If there is not enough temporary pool memory available to complete this function, + then NULL is returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Source, + IN CONST EFI_DEVICE_PATH_PROTOCOL *Instance + ) +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + UINTN SrcSize; + UINTN InstanceSize; + + if (Source == NULL) { + return DuplicateDevicePath (Instance); + } + + SrcSize = GetDevicePathSize (Source); + InstanceSize = GetDevicePathSize (Instance); + + NewDevicePath = AllocatePool (SrcSize + InstanceSize); + if (NewDevicePath != NULL) { + + DevicePath = CopyMem (NewDevicePath, Source, SrcSize);; + + while (!IsDevicePathEnd (DevicePath)) { + DevicePath = NextDevicePathNode (DevicePath); + } + + DevicePath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; + + DevicePath = NextDevicePathNode (DevicePath); + CopyMem (DevicePath, Instance, InstanceSize); + } + + return NewDevicePath; +} + +/** + Function retrieves the next device path instance from a device path data structure. + + @param DevicePath A pointer to a device path data structure. + + @param Size A pointer to the size of a device path instance in bytes. + + @return This function returns a pointer to the current device path instance. + In addition, it returns the size in bytes of the current device path instance in Size, + and a pointer to the next device path instance in DevicePath. + If there are no more device path instances in DevicePath, then DevicePath will be set to NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +GetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *ReturnValue; + UINT8 Temp; + + ASSERT (DevicePath != NULL); + ASSERT (Size != NULL); + if (*DevicePath == NULL) { + *Size = 0; + return NULL; + } + + // + // Find the end of the device path instance + // + DevPath = *DevicePath; + while (!IsDevicePathEndType (DevPath)) { + DevPath = NextDevicePathNode (DevPath); + } + + // + // Compute the size of the device path instance + // + *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL); + + // + // Make a copy and return the device path instance + // + Temp = DevPath->SubType; + DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; + ReturnValue = DuplicateDevicePath (*DevicePath); + DevPath->SubType = Temp; + + // + // If DevPath is the end of an entire device path, then another instance + // does not follow, so *DevicePath is set to NULL. + // + if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) { + *DevicePath = NULL; + } else { + *DevicePath = NextDevicePathNode (DevPath); + } + + return ReturnValue; +} + +/** + Return TRUE is this is a multi instance device path. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE If DevicePath is multi-instance. + @retval FALSE If DevicePath is not multi-instance or DevicePath is NULL. + +**/ +BOOLEAN +EFIAPI +IsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Node; + + if (DevicePath == NULL) { + return FALSE; + } + + Node = DevicePath; + while (!EfiIsDevicePathEnd (Node)) { + if (EfiIsDevicePathEndInstance (Node)) { + return TRUE; + } + + Node = EfiNextDevicePathNode (Node); + } + + return FALSE; +} + +/** + This function retrieves the device path protocol from a handle. + + @param Handle The handle from which to retrieve the device path protocol. + + @return This function returns the device path protocol from the handle specified by Handle. + If Handle is NULL or Handle does not contain a device path protocol, then NULL is returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DevicePathFromHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_STATUS Status; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID *) &DevicePath + ); + if (EFI_ERROR (Status)) { + DevicePath = NULL; + } + return DevicePath; +} + +/** + This function allocates a device path for a file and appends it to an existing device path. + + @param Device A pointer to a device handle. This parameter is optional and may be NULL. + @param FileName A pointer to a Null-terminated Unicode string. + + @return If Device is a valid device handle that contains a device path protocol, + then a device path for the file specified by FileName is allocated + and appended to the device path associated with the handle Device. The allocated device path is returned. + If Device is NULL or Device is a handle that does not support the device path protocol, + then a device path containing a single device path node for the file specified by FileName + is allocated and returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +FileDevicePath ( + IN EFI_HANDLE Device, OPTIONAL + IN CONST CHAR16 *FileName + ) +{ + UINTN FileNameSize; + UINTN FilePathNodeSize; + FILEPATH_DEVICE_PATH *FilePathNode; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = NULL; + + FileNameSize = StrSize (FileName); + FilePathNodeSize = FileNameSize + SIZE_OF_FILEPATH_DEVICE_PATH; + FilePathNode = AllocatePool (FilePathNodeSize); + if (FilePathNode != NULL) { + // + // Build a file path node + // + FilePathNode->Header.Type = MEDIA_DEVICE_PATH; + FilePathNode->Header.SubType = MEDIA_FILEPATH_DP; + SetDevicePathNodeLength (&FilePathNode->Header, FilePathNodeSize); + CopyMem (FilePathNode->PathName, FileName, FileNameSize); + + // + // Append file path node to device's device path + // + if (Device != NULL) { + DevicePath = DevicePathFromHandle (Device); + } + DevicePath = AppendDevicePathNode (DevicePath, (EFI_DEVICE_PATH_PROTOCOL *) FilePathNode); + FreePool (FilePathNode); + } + return DevicePath; +} + diff --git a/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.mbd b/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.mbd new file mode 100644 index 0000000000..dc69382880 --- /dev/null +++ b/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.mbd @@ -0,0 +1,30 @@ + + + + + UefiDevicePathLib + 91c1677a-e57f-4191-8b8e-eb7711a716e0 + 0 + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2006, 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. + + 2006-03-13 16:52 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.msa b/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.msa new file mode 100644 index 0000000000..c5225d89c9 --- /dev/null +++ b/MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.msa @@ -0,0 +1,51 @@ + + + + + UefiDevicePathLib + UEFI_DRIVER + LIBRARY + 91c1677a-e57f-4191-8b8e-eb7711a716e0 + 0 + Component description file for the entry point to a EFIDXE Drivers + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2006, 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. + + 0 + 2006-03-13 16:52 + 2006-03-19 15:17 + + + DevicePathLib + BaseMemoryLib + DebugLib + MemoryAllocationLib + UefiBootServicesTableLib + BaseLib + + + UefiDevicePathLib.c + + + MdePkg + + + DevicePath + + diff --git a/MdePkg/Library/UefiDevicePathLib/build.xml b/MdePkg/Library/UefiDevicePathLib/build.xml new file mode 100644 index 0000000000..2234ca485f --- /dev/null +++ b/MdePkg/Library/UefiDevicePathLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c b/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c new file mode 100644 index 0000000000..aea75aa496 --- /dev/null +++ b/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLib.c @@ -0,0 +1,274 @@ +/** @file + UEFI Device Path Library. + + Copyright (c) 2006, 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. + + Module Name: UefiDevicePathLib.c + +**/ + +STATIC EFI_DEVICE_PATH_UTILITIES_PROTOCOL *mDevicePathUtilities = NULL; + +/** + The constructor function caches the pointer to DevicePathUtilites protocol. + + The constructor function locates DevicePathUtilities protocol from protocol database. + It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. + + @param ImageHandle The firmware allocated handle for the EFI image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The constructor always returns EFI_SUCCESS. + +**/ +EFI_STATUS +EFIAPI +DevicePathLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + Status = gBS->LocateProtocol ( + &gEfiDevicePathUtilitiesProtocolGuid, + NULL, + (VOID**) &mDevicePathUtilities + ); + ASSERT_EFI_ERROR (Status); + ASSERT (mDevicePathUtilities != NULL); + + return Status; +} + +/** + This function returns the size, in bytes, + of the device path data structure specified by DevicePath. + If DevicePath is NULL, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @return The size of a device path in bytes. + +**/ +UINTN +EFIAPI +GetDevicePathSize ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return mDevicePathUtilities->GetDevicePathSize (DevicePath); +} + +/** + This function allocates space for a new copy of the device path + specified by DevicePath. + + @param DevicePath A pointer to a device path data structure. + + @return The duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DuplicateDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return mDevicePathUtilities->DuplicateDevicePath (DevicePath); +} + +/** + This function appends the device path SecondDevicePath + to every device path instance in FirstDevicePath. + + @param FirstDevicePath A pointer to a device path data structure. + + @param SecondDevicePath A pointer to a device path data structure. + + @return A pointer to the new device path is returned. + NULL is returned if space for the new device path could not be allocated from pool. + It is up to the caller to free the memory used by FirstDevicePath and SecondDevicePath + if they are no longer needed. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePath ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath + ) +{ + return mDevicePathUtilities->AppendDevicePath (FirstDevicePath, SecondDevicePath); +} + +/** + This function appends the device path node SecondDevicePath + to every device path instance in FirstDevicePath. + + @param FirstDevicePath A pointer to a device path data structure. + + @param SecondDevicePath A pointer to a single device path node. + + @return A pointer to the new device path. + If there is not enough temporary pool memory available to complete this function, + then NULL is returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathNode ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, + IN CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath + ) +{ + return mDevicePathUtilities->AppendDeviceNode (FirstDevicePath, SecondDevicePath); +} + +/** + This function appends the device path instance Instance to the device path Source. + If Source is NULL, then a new device path with one instance is created. + + @param Source A pointer to a device path data structure. + @param Instance A pointer to a device path instance. + + @return A pointer to the new device path. + If there is not enough temporary pool memory available to complete this function, + then NULL is returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +AppendDevicePathInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *Source, + IN CONST EFI_DEVICE_PATH_PROTOCOL *Instance + ) +{ + return mDevicePathUtilities->AppendDevicePathInstance (Source, Instance); +} + +/** + Function retrieves the next device path instance from a device path data structure. + + @param DevicePath A pointer to a device path data structure. + + @param Size A pointer to the size of a device path instance in bytes. + + @return This function returns a pointer to the current device path instance. + In addition, it returns the size in bytes of the current device path instance in Size, + and a pointer to the next device path instance in DevicePath. + If there are no more device path instances in DevicePath, then DevicePath will be set to NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +GetNextDevicePathInstance ( + IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath, + OUT UINTN *Size + ) +{ + ASSERT (DevicePath != NULL); + ASSERT (Size != NULL); + return mDevicePathUtilities->GetNextDevicePathInstance (DevicePath, Size); +} + +/** + Return TRUE is this is a multi instance device path. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE If DevicePath is multi-instance. + @retval FALSE If DevicePath is not multi-instance or DevicePath is NULL. + +**/ +BOOLEAN +EFIAPI +IsDevicePathMultiInstance ( + IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return mDevicePathUtilities->IsDevicePathMultiInstance (DevicePath); +} + +/** + This function retrieves the device path protocol from a handle. + + @param Handle The handle from which to retrieve the device path protocol. + + @return This function returns the device path protocol from the handle specified by Handle. + If Handle is NULL or Handle does not contain a device path protocol, then NULL is returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +DevicePathFromHandle ( + IN EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_STATUS Status; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID *) &DevicePath + ); + if (EFI_ERROR (Status)) { + DevicePath = NULL; + } + return DevicePath; +} + +/** + This function allocates a device path for a file and appends it to an existing device path. + + @param Device A pointer to a device handle. This parameter is optional and may be NULL. + @param FileName A pointer to a Null-terminated Unicode string. + + @return If Device is a valid device handle that contains a device path protocol, + then a device path for the file specified by FileName is allocated + and appended to the device path associated with the handle Device. The allocated device path is returned. + If Device is NULL or Device is a handle that does not support the device path protocol, + then a device path containing a single device path node for the file specified by FileName + is allocated and returned. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +FileDevicePath ( + IN EFI_HANDLE Device, OPTIONAL + IN CONST CHAR16 *FileName + ) +{ + UINTN Size; + FILEPATH_DEVICE_PATH *FilePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *FileDevicePathNode; + + DevicePath = NULL; + + Size = StrSize (FileName); + FileDevicePathNode = mDevicePathUtilities->CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_FILEPATH_DP, + (UINT16) (Size + SIZE_OF_FILEPATH_DEVICE_PATH) + ); + if (FileDevicePathNode != NULL) { + FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePathNode; + CopyMem (&FilePath->PathName, FileName, Size); + if (Device != NULL) { + DevicePath = DevicePathFromHandle (Device); + } + DevicePath = AppendDevicePathNode (DevicePath, FileDevicePathNode); + FreePool (FileDevicePathNode); + } + return DevicePath; +} + diff --git a/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.mbd b/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.mbd new file mode 100644 index 0000000000..f975a6c8fb --- /dev/null +++ b/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.mbd @@ -0,0 +1,29 @@ + + + + + UefiDevicePathLibDevicePathProtocol + 050EB8C6-C12E-4b86-892B-40985E8B3137 + EDK_RELEASE_VERSION 0x00020000 + FIX ME! + Copyright (c) 2006, 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. + + 2006-03-30 10:05 + + diff --git a/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.msa b/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.msa new file mode 100644 index 0000000000..ac2106209d --- /dev/null +++ b/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.msa @@ -0,0 +1,55 @@ + + + + + UefiDevicePathLibDevicePathProtocol + UEFI_DRIVER + LIBRARY + 050EB8C6-C12E-4b86-892B-40985E8B3137 + EDK_RELEASE_VERSION 0x00020000 + Device Path Library + FIX ME! + Copyright (c) 2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-03-30 10:05 + + + DevicePathLib + DebugLib + BaseLib + MemoryAllocationLib + BaseMemoryLib + UefiBootServicesTableLib + + + UefiDevicePathLib.c + + + MdePkg + + + DevicePathUtilities + + + + DevicePathLibConstructor + + + diff --git a/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/build.xml b/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/build.xml new file mode 100644 index 0000000000..c7d82d624a --- /dev/null +++ b/MdePkg/Library/UefiDevicePathLibDevicePathProtocol/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c b/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c new file mode 100644 index 0000000000..60177bc9c5 --- /dev/null +++ b/MdePkg/Library/UefiDriverEntryPoint/DriverEntryPoint.c @@ -0,0 +1,137 @@ +/** @file + Entry point to a EFI/DXE driver. + +Copyright (c) 2006, 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. + +**/ + +/** + Unload function that is registered in the LoadImage protocol. It un-installs + protocols produced and deallocates pool used by the driver. Called by the core + when unloading the driver. + + @param ImageHandle + + @retval EFI_SUCCESS + +**/ +EFI_STATUS +EFIAPI +_DriverUnloadHandler ( + EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + + // + // If an UnloadImage() handler is specified, then call it + // + Status = ProcessModuleUnloadList (ImageHandle); + + // + // If the driver specific unload handler does not return an error, then call all of the + // library destructors. If the unload handler returned an error, then the driver can not be + // unloaded, and the library destructors should not be called + // + if (!EFI_ERROR (Status)) { + ProcessLibraryDestructorList (ImageHandle, gST); + } + + // + // Return the status from the driver specific unload handler + // + return Status; +} + +/** + Enrty point to DXE Driver. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @retval EFI_SUCCESS One or more of the drivers returned a success code. + @retval !EFI_SUCESS The return status from the last driver entry point in the list. + +**/ +EFI_STATUS +EFIAPI +_ModuleEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; + + if (_gUefiDriverRevision != 0) { + // + // Make sure that the EFI/UEFI spec revision of the platform is >= EFI/UEFI spec revision of the driver + // + if (SystemTable->Hdr.Revision < _gUefiDriverRevision) { + return EFI_INCOMPATIBLE_VERSION; + } + } + + // + // Call constructor for all libraries + // + ProcessLibraryConstructorList (ImageHandle, SystemTable); + + // + // Install unload handler... + // + if (_gDriverUnloadImageCount != 0) { + Status = gBS->HandleProtocol ( + ImageHandle, + &gEfiLoadedImageProtocolGuid, + (VOID **)&LoadedImage + ); + ASSERT_EFI_ERROR (Status); + LoadedImage->Unload = _DriverUnloadHandler; + } + + // + // Call the driver entry point + // + Status = ProcessModuleEntryPointList (ImageHandle, SystemTable); + + // + // If all of the drivers returned errors, then invoke all of the library destructors + // + if (EFI_ERROR (Status)) { + ProcessLibraryDestructorList (ImageHandle, SystemTable); + } + + // + // Return the cummalative return status code from all of the driver entry points + // + return Status; +} + + +/** + Enrty point wrapper of DXE Driver. + + @param ImageHandle ImageHandle of the loaded driver. + @param SystemTable Pointer to the EFI System Table. + + @retval EFI_SUCCESS One or more of the drivers returned a success code. + @retval !EFI_SUCESS The return status from the last driver entry point in the list. + +**/ +EFI_STATUS +EFIAPI +EfiMain ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + return _ModuleEntryPoint (ImageHandle, SystemTable); +} diff --git a/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.mbd b/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.mbd new file mode 100644 index 0000000000..d41abe2f6b --- /dev/null +++ b/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.mbd @@ -0,0 +1,30 @@ + + + + + UefiDriverEntryPoint + 331deb15-454b-48d8-9b74-70d01f3f3556 + 0 + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.msa b/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.msa new file mode 100644 index 0000000000..d4029e6c1b --- /dev/null +++ b/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.msa @@ -0,0 +1,50 @@ + + + + + UefiDriverEntryPoint + UEFI_DRIVER + LIBRARY + 331deb15-454b-48d8-9b74-70d01f3f3556 + 0 + Component description file for the entry point to a EFIDXE Drivers + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + UefiDriverEntryPoint + DebugLib + BaseLib + UefiBootServicesTableLib + UefiRuntimeServicesTableLib + + + DriverEntryPoint.c + + + MdePkg + + + LoadedImage + + diff --git a/MdePkg/Library/UefiDriverEntryPoint/build.xml b/MdePkg/Library/UefiDriverEntryPoint/build.xml new file mode 100644 index 0000000000..8fae304134 --- /dev/null +++ b/MdePkg/Library/UefiDriverEntryPoint/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/UefiDriverModelLib/UefiDriverModelLib.c b/MdePkg/Library/UefiDriverModelLib/UefiDriverModelLib.c new file mode 100644 index 0000000000..9b96f28fb1 --- /dev/null +++ b/MdePkg/Library/UefiDriverModelLib/UefiDriverModelLib.c @@ -0,0 +1,405 @@ +/** @file + EFI Driver Model Library. + + Copyright (c) 2006, 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. + + Module Name: EfiDriverModelLib.c + +**/ + + + +/** +**/ +EFI_STATUS +UefiDriverModelLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE DriverBindingHandle; + EFI_DRIVER_BINDING_PROTOCOL *DriverBinding; + + // + // If no Driver Binding Protocols are advertised by the driver then simply return + // + if (_gDriverModelProtocolListEntries == 0) { + return EFI_SUCCESS; + } + + // + // Install the first Driver Bindng Protocol onto ImageHandle + // + DriverBindingHandle = ImageHandle; + + // + // See if onle one Driver Binding Protocol is advertised by the driver + // + if (_gDriverModelProtocolListEntries == 1) { + // + // The Driver Binding Protocol must never be NULL + // + ASSERT(_gDriverModelProtocolList[0].DriverBinding != NULL); + + // + // Check for all 8 possible combinations of the ComponentName, DriverConfiguration, and DriverDiagnostics Protocol + // These are all checks against const pointers, so the optimizing compiler will only select one of the + // calls to InstallMultipleProtocolInterfaces() + // + if (_gDriverModelProtocolList[0].DriverDiagnostics == NULL) { + if (_gDriverModelProtocolList[0].DriverConfiguration == NULL) { + if (_gDriverModelProtocolList[0].ComponentName == NULL) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiComponentNameProtocolGuid, (EFI_COMPONENT_NAME_PROTOCOL *)_gDriverModelProtocolList[0].ComponentName, + NULL + ); + } + } else { + if (_gDriverModelProtocolList[0].ComponentName == NULL) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiDriverConfigurationProtocolGuid, (EFI_DRIVER_CONFIGURATION_PROTOCOL *)_gDriverModelProtocolList[0].DriverConfiguration, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiComponentNameProtocolGuid, (EFI_COMPONENT_NAME_PROTOCOL *)_gDriverModelProtocolList[0].ComponentName, + &gEfiDriverConfigurationProtocolGuid, (EFI_DRIVER_CONFIGURATION_PROTOCOL *)_gDriverModelProtocolList[0].DriverConfiguration, + NULL + ); + } + } + } else { + if (_gDriverModelProtocolList[0].DriverConfiguration == NULL) { + if (_gDriverModelProtocolList[0].ComponentName == NULL) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiDriverDiagnosticsProtocolGuid, (EFI_DRIVER_DIAGNOSTICS_PROTOCOL *)_gDriverModelProtocolList[0].DriverDiagnostics, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiComponentNameProtocolGuid, (EFI_COMPONENT_NAME_PROTOCOL *)_gDriverModelProtocolList[0].ComponentName, + &gEfiDriverDiagnosticsProtocolGuid, (EFI_DRIVER_DIAGNOSTICS_PROTOCOL *)_gDriverModelProtocolList[0].DriverDiagnostics, + NULL + ); + } + } else { + if (_gDriverModelProtocolList[0].ComponentName == NULL) { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiDriverConfigurationProtocolGuid, (EFI_DRIVER_CONFIGURATION_PROTOCOL *)_gDriverModelProtocolList[0].DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, (EFI_DRIVER_DIAGNOSTICS_PROTOCOL *)_gDriverModelProtocolList[0].DriverDiagnostics, + NULL + ); + } else { + Status = gBS->InstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiComponentNameProtocolGuid, (EFI_COMPONENT_NAME_PROTOCOL *)_gDriverModelProtocolList[0].ComponentName, + &gEfiDriverConfigurationProtocolGuid, (EFI_DRIVER_CONFIGURATION_PROTOCOL *)_gDriverModelProtocolList[0].DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, (EFI_DRIVER_DIAGNOSTICS_PROTOCOL *)_gDriverModelProtocolList[0].DriverDiagnostics, + NULL + ); + } + } + } + + // + // ASSERT if the call to InstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + + // + // Update the ImageHandle and DriverBindingHandle fields of the Driver Binding Protocol + // + DriverBinding = (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding; + DriverBinding->ImageHandle = ImageHandle; + DriverBinding->DriverBindingHandle = DriverBindingHandle; + + } else { + for (Index = 0; Index < _gDriverModelProtocolListEntries; Index++) { + // + // The Driver Binding Protocol must never be NULL + // + ASSERT(_gDriverModelProtocolList[Index].DriverBinding != NULL); + + // + // Install the Driver Binding Protocol and ASSERT() if the installation fails + // + Status = gBS->InstallProtocolInterface ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, + EFI_NATIVE_INTERFACE, + (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[Index].DriverBinding + ); + ASSERT_EFI_ERROR (Status); + + // + // Update the ImageHandle and DriverBindingHandle fields of the Driver Binding Protocol + // + DriverBinding = (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[Index].DriverBinding; + DriverBinding->ImageHandle = ImageHandle; + DriverBinding->DriverBindingHandle = DriverBindingHandle; + + // + // If Component Name Protocol is specified then install it and ASSERT() if the installation fails + // + if ((_gDriverModelProtocolBitmask & UEFI_DRIVER_MODEL_LIBRARY_COMPONENT_NAME_PROTOCOL_ENABLED) != 0) { + if (_gDriverModelProtocolList[Index].ComponentName != NULL) { + Status = gBS->InstallProtocolInterface ( + &DriverBindingHandle, + &gEfiComponentNameProtocolGuid, + EFI_NATIVE_INTERFACE, + (EFI_COMPONENT_NAME_PROTOCOL *)_gDriverModelProtocolList[Index].ComponentName + ); + ASSERT_EFI_ERROR (Status); + } + } + + // + // If Driver Configuration Protocol is specified then install it and ASSERT() if the installation fails + // + if ((_gDriverModelProtocolBitmask & UEFI_DRIVER_MODEL_LIBRARY_DRIVER_CONFIGURATION_PROTOCOL_ENABLED) != 0) { + if (_gDriverModelProtocolList[Index].DriverConfiguration != NULL) { + Status = gBS->InstallProtocolInterface ( + &DriverBindingHandle, + &gEfiDriverConfigurationProtocolGuid, + EFI_NATIVE_INTERFACE, + (EFI_DRIVER_CONFIGURATION_PROTOCOL *)_gDriverModelProtocolList[Index].DriverConfiguration + ); + ASSERT_EFI_ERROR (Status); + } + } + + // + // If Driver Diagnostics Protocol is specified then install it and ASSERT() if the installation fails + // + if ((_gDriverModelProtocolBitmask & UEFI_DRIVER_MODEL_LIBRARY_DRIVER_DIAGNOSTICS_PROTOCOL_ENABLED) != 0) { + if (_gDriverModelProtocolList[Index].DriverDiagnostics != NULL) { + Status = gBS->InstallProtocolInterface ( + &DriverBindingHandle, + &gEfiDriverDiagnosticsProtocolGuid, + EFI_NATIVE_INTERFACE, + (EFI_DRIVER_DIAGNOSTICS_PROTOCOL *)_gDriverModelProtocolList[Index].DriverDiagnostics + ); + ASSERT_EFI_ERROR (Status); + } + } + + // + // Install subsequent Driver Bindng Protocols onto new handles + // + DriverBindingHandle = NULL; + } + } + return EFI_SUCCESS; +} + +/** +**/ +EFI_STATUS +UefiDriverModelLibDestructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UINTN Index; + EFI_HANDLE DriverBindingHandle; + + // + // If no Driver Binding Protocols are advertised by the driver then simply return + // + if (_gDriverModelProtocolListEntries == 0) { + return EFI_SUCCESS; + } + + // + // See if onle one Driver Binding Protocol is advertised by the driver + // + if (_gDriverModelProtocolListEntries == 1) { + // + // The Driver Binding Protocol must never be NULL + // + ASSERT(_gDriverModelProtocolList[0].DriverBinding != NULL); + + // + // Retrieve the DriverBindingHandle from the Driver Binding Protocol + // + DriverBindingHandle = _gDriverModelProtocolList[0].DriverBinding->DriverBindingHandle; + + // + // Check for all 8 possible combinations of the ComponentName, DriverConfiguration, and DriverDiagnostics Protocol + // These are all checks against const pointers, so the optimizing compiler will only select one of the + // calls to InstallMultipleProtocolInterfaces() + // + if (_gDriverModelProtocolList[0].DriverDiagnostics == NULL) { + if (_gDriverModelProtocolList[0].DriverConfiguration == NULL) { + if (_gDriverModelProtocolList[0].ComponentName == NULL) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiComponentNameProtocolGuid, (EFI_COMPONENT_NAME_PROTOCOL *)_gDriverModelProtocolList[0].ComponentName, + NULL + ); + } + } else { + if (_gDriverModelProtocolList[0].ComponentName == NULL) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiDriverConfigurationProtocolGuid, (EFI_DRIVER_CONFIGURATION_PROTOCOL *)_gDriverModelProtocolList[0].DriverConfiguration, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiComponentNameProtocolGuid, (EFI_COMPONENT_NAME_PROTOCOL *)_gDriverModelProtocolList[0].ComponentName, + &gEfiDriverConfigurationProtocolGuid, (EFI_DRIVER_CONFIGURATION_PROTOCOL *)_gDriverModelProtocolList[0].DriverConfiguration, + NULL + ); + } + } + } else { + if (_gDriverModelProtocolList[0].DriverConfiguration == NULL) { + if (_gDriverModelProtocolList[0].ComponentName == NULL) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiDriverDiagnosticsProtocolGuid, (EFI_DRIVER_DIAGNOSTICS_PROTOCOL *)_gDriverModelProtocolList[0].DriverDiagnostics, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiComponentNameProtocolGuid, (EFI_COMPONENT_NAME_PROTOCOL *)_gDriverModelProtocolList[0].ComponentName, + &gEfiDriverDiagnosticsProtocolGuid, (EFI_DRIVER_DIAGNOSTICS_PROTOCOL *)_gDriverModelProtocolList[0].DriverDiagnostics, + NULL + ); + } + } else { + if (_gDriverModelProtocolList[0].ComponentName == NULL) { + Status = gBS->UninstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiDriverConfigurationProtocolGuid, (EFI_DRIVER_CONFIGURATION_PROTOCOL *)_gDriverModelProtocolList[0].DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, (EFI_DRIVER_DIAGNOSTICS_PROTOCOL *)_gDriverModelProtocolList[0].DriverDiagnostics, + NULL + ); + } else { + Status = gBS->UninstallMultipleProtocolInterfaces ( + &DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[0].DriverBinding, + &gEfiComponentNameProtocolGuid, (EFI_COMPONENT_NAME_PROTOCOL *)_gDriverModelProtocolList[0].ComponentName, + &gEfiDriverConfigurationProtocolGuid, (EFI_DRIVER_CONFIGURATION_PROTOCOL *)_gDriverModelProtocolList[0].DriverConfiguration, + &gEfiDriverDiagnosticsProtocolGuid, (EFI_DRIVER_DIAGNOSTICS_PROTOCOL *)_gDriverModelProtocolList[0].DriverDiagnostics, + NULL + ); + } + } + } + + // + // ASSERT if the call to UninstallMultipleProtocolInterfaces() failed + // + ASSERT_EFI_ERROR (Status); + } else { + for (Index = 0; Index < _gDriverModelProtocolListEntries; Index++) { + // + // The Driver Binding Protocol must never be NULL + // + ASSERT(_gDriverModelProtocolList[Index].DriverBinding != NULL); + + // + // Retrieve the DriverBindingHandle from the Driver Binding Protocol + // + DriverBindingHandle = _gDriverModelProtocolList[0].DriverBinding->DriverBindingHandle; + + // + // Uninstall the Driver Binding Protocol and ASSERT() if the installation fails + // + Status = gBS->UninstallProtocolInterface ( + DriverBindingHandle, + &gEfiDriverBindingProtocolGuid, + (EFI_DRIVER_BINDING_PROTOCOL *)_gDriverModelProtocolList[Index].DriverBinding + ); + ASSERT_EFI_ERROR (Status); + + // + // If Component Name Protocol is specified then uninstall it and ASSERT() if the uninstallation fails + // + if ((_gDriverModelProtocolBitmask & UEFI_DRIVER_MODEL_LIBRARY_COMPONENT_NAME_PROTOCOL_ENABLED) != 0) { + if (_gDriverModelProtocolList[Index].ComponentName != NULL) { + Status = gBS->UninstallProtocolInterface ( + DriverBindingHandle, + &gEfiComponentNameProtocolGuid, + (EFI_COMPONENT_NAME_PROTOCOL *)_gDriverModelProtocolList[Index].ComponentName + ); + ASSERT_EFI_ERROR (Status); + } + } + + // + // If Driver Configuration Protocol is specified then uninstall it and ASSERT() if the uninstallation fails + // + if ((_gDriverModelProtocolBitmask & UEFI_DRIVER_MODEL_LIBRARY_DRIVER_CONFIGURATION_PROTOCOL_ENABLED) != 0) { + if (_gDriverModelProtocolList[Index].DriverConfiguration != NULL) { + Status = gBS->UninstallProtocolInterface ( + DriverBindingHandle, + &gEfiDriverConfigurationProtocolGuid, + (EFI_DRIVER_CONFIGURATION_PROTOCOL *)_gDriverModelProtocolList[Index].DriverConfiguration + ); + ASSERT_EFI_ERROR (Status); + } + } + + // + // If Driver Diagnostics Protocol is specified then uninstall it and ASSERT() if the uninstallation fails + // + if ((_gDriverModelProtocolBitmask & UEFI_DRIVER_MODEL_LIBRARY_DRIVER_DIAGNOSTICS_PROTOCOL_ENABLED) != 0) { + if (_gDriverModelProtocolList[Index].DriverDiagnostics != NULL) { + Status = gBS->UninstallProtocolInterface ( + DriverBindingHandle, + &gEfiDriverDiagnosticsProtocolGuid, + (EFI_DRIVER_DIAGNOSTICS_PROTOCOL *)_gDriverModelProtocolList[Index].DriverDiagnostics + ); + ASSERT_EFI_ERROR (Status); + } + } + } + } + return EFI_SUCCESS; +} diff --git a/MdePkg/Library/UefiDriverModelLib/UefiDriverModelLib.mbd b/MdePkg/Library/UefiDriverModelLib/UefiDriverModelLib.mbd new file mode 100644 index 0000000000..6de82c157c --- /dev/null +++ b/MdePkg/Library/UefiDriverModelLib/UefiDriverModelLib.mbd @@ -0,0 +1,30 @@ + + + + + UefiDriverModelLib + 52af22ae-9901-4484-8cdc-622dd5838b09 + 0 + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/UefiDriverModelLib/UefiDriverModelLib.msa b/MdePkg/Library/UefiDriverModelLib/UefiDriverModelLib.msa new file mode 100644 index 0000000000..935c4cca40 --- /dev/null +++ b/MdePkg/Library/UefiDriverModelLib/UefiDriverModelLib.msa @@ -0,0 +1,57 @@ + + + + + UefiDriverModelLib + UEFI_DRIVER + LIBRARY + 52af22ae-9901-4484-8cdc-622dd5838b09 + 0 + Component description file for the entry point to a EFIDXE Drivers + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + UefiDriverModelLib + DebugLib + UefiBootServicesTableLib + + + UefiDriverModelLib.c + + + MdePkg + + + DriverBinding + ComponentName + DriverConfiguration + DriverDiagnostics + + + + UefiDriverModelLibConstructor + UefiDriverModelLibDestructor + + + diff --git a/MdePkg/Library/UefiDriverModelLib/build.xml b/MdePkg/Library/UefiDriverModelLib/build.xml new file mode 100644 index 0000000000..cb6b40c1a1 --- /dev/null +++ b/MdePkg/Library/UefiDriverModelLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/UefiLib/Console.c b/MdePkg/Library/UefiLib/Console.c new file mode 100644 index 0000000000..d06b0a932d --- /dev/null +++ b/MdePkg/Library/UefiLib/Console.c @@ -0,0 +1,278 @@ +/** @file + Mde UEFI library functions. + + Copyright (c) 2006, 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. + + Module Name: Console.c + +**/ + + + +typedef struct { + CHAR16 WChar; + UINT32 Width; +} UNICODE_WIDTH_ENTRY; + +UNICODE_WIDTH_ENTRY mUnicodeWidthTable[] = { + // + // General script area + // + {(CHAR16)0x1FFF, 1}, + /* + * Merge the blocks and replace them with the above entry as they fall to + * the same category and they are all narrow glyph. This will reduce search + * time and table size. The merge will omit the reserved code. + * + * Remove the above item if below is un-commented. + * + {(CHAR16)0x007F, 1}, // C0 controls and basic Latin. 0x0000-0x007F + {(CHAR16)0x00FF, 1}, // C1 controls and Latin-1 support. 0x0080-0x00FF + {(CHAR16)0x017F, 1}, // Latin extended-A. 0x0100-0x017F + {(CHAR16)0x024F, 1}, // Latin extended-B. 0x0180-0x024F + {(CHAR16)0x02AF, 1}, // IPA extensions. 0x0250-0x02AF + {(CHAR16)0x02FF, 1}, // Spacing modifier letters. 0x02B0-0x02FF + {(CHAR16)0x036F, 1}, // Combining diacritical marks. 0x0300-0x036F + {(CHAR16)0x03FF, 1}, // Greek. 0x0370-0x03FF + {(CHAR16)0x04FF, 1}, // Cyrillic. 0x0400-0x04FF + {(CHAR16)0x052F, 0}, // Unassigned. As Armenian in ver3.0. 0x0500-0x052F + {(CHAR16)0x058F, 1}, // Armenian. 0x0530-0x058F + {(CHAR16)0x05FF, 1}, // Hebrew. 0x0590-0x05FF + {(CHAR16)0x06FF, 1}, // Arabic. 0x0600-0x06FF + {(CHAR16)0x08FF, 0}, // Unassigned. 0x0700-0x08FF + {(CHAR16)0x097F, 1}, // Devanagari. 0x0900-0x097F + {(CHAR16)0x09FF, 1}, // Bengali. 0x0980-0x09FF + {(CHAR16)0x0A7F, 1}, // Gurmukhi. 0x0A00-0x0A7F + {(CHAR16)0x0AFF, 1}, // Gujarati. 0x0A80-0x0AFF + {(CHAR16)0x0B7F, 1}, // Oriya. 0x0B00-0x0B7F + {(CHAR16)0x0BFF, 1}, // Tamil. (See page 7-92). 0x0B80-0x0BFF + {(CHAR16)0x0C7F, 1}, // Telugu. 0x0C00-0x0C7F + {(CHAR16)0x0CFF, 1}, // Kannada. (See page 7-100). 0x0C80-0x0CFF + {(CHAR16)0x0D7F, 1}, // Malayalam (See page 7-104). 0x0D00-0x0D7F + {(CHAR16)0x0DFF, 0}, // Unassigned. 0x0D80-0x0DFF + {(CHAR16)0x0E7F, 1}, // Thai. 0x0E00-0x0E7F + {(CHAR16)0x0EFF, 1}, // Lao. 0x0E80-0x0EFF + {(CHAR16)0x0FBF, 1}, // Tibetan. 0x0F00-0x0FBF + {(CHAR16)0x109F, 0}, // Unassigned. 0x0FC0-0x109F + {(CHAR16)0x10FF, 1}, // Georgian. 0x10A0-0x10FF + {(CHAR16)0x11FF, 1}, // Hangul Jamo. 0x1100-0x11FF + {(CHAR16)0x1DFF, 0}, // Unassigned. 0x1200-0x1DFF + {(CHAR16)0x1EFF, 1}, // Latin extended additional. 0x1E00-0x1EFF + {(CHAR16)0x1FFF, 1}, // Greek extended. 0x1F00-0x1FFF + * + */ + + // + // Symbol area + // + {(CHAR16)0x2FFF, 1}, + /* + * Merge the blocks and replace them with the above entry as they fall to + * the same category and they are all narrow glyph. This will reduce search + * time and table size. The merge will omit the reserved code. + * + * Remove the above item if below is un-commented. + * + {(CHAR16)0x206F, 1}, // General punctuation. (See page7-154). 0x200-0x206F + {(CHAR16)0x209F, 1}, // Superscripts and subscripts. 0x2070-0x209F + {(CHAR16)0x20CF, 1}, // Currency symbols. 0x20A0-0x20CF + {(CHAR16)0x20FF, 1}, // Combining diacritical marks for symbols. 0x20D0-0x20FF + {(CHAR16)0x214F, 1}, // Letterlike sympbols. 0x2100-0x214F + {(CHAR16)0x218F, 1}, // Number forms. 0x2150-0x218F + {(CHAR16)0x21FF, 1}, // Arrows. 0x2190-0x21FF + {(CHAR16)0x22FF, 1}, // Mathematical operators. 0x2200-0x22FF + {(CHAR16)0x23FF, 1}, // Miscellaneous technical. 0x2300-0x23FF + {(CHAR16)0x243F, 1}, // Control pictures. 0x2400-0x243F + {(CHAR16)0x245F, 1}, // Optical character recognition. 0x2440-0x245F + {(CHAR16)0x24FF, 1}, // Enclosed alphanumerics. 0x2460-0x24FF + {(CHAR16)0x257F, 1}, // Box drawing. 0x2500-0x257F + {(CHAR16)0x259F, 1}, // Block elements. 0x2580-0x259F + {(CHAR16)0x25FF, 1}, // Geometric shapes. 0x25A0-0x25FF + {(CHAR16)0x26FF, 1}, // Miscellaneous symbols. 0x2600-0x26FF + {(CHAR16)0x27BF, 1}, // Dingbats. 0x2700-0x27BF + {(CHAR16)0x2FFF, 0}, // Reserved. 0x27C0-0x2FFF + * + */ + + // + // CJK phonetics and symbol area + // + {(CHAR16)0x33FF, 2}, + /* + * Merge the blocks and replace them with the above entry as they fall to + * the same category and they are all wide glyph. This will reduce search + * time and table size. The merge will omit the reserved code. + * + * Remove the above item if below is un-commented. + * + {(CHAR16)0x303F, 2}, // CJK symbols and punctuation. 0x3000-0x303F + {(CHAR16)0x309F, 2}, // Hiragana. 0x3040-0x309F + {(CHAR16)0x30FF, 2}, // Katakana. 0x30A0-0x30FF + {(CHAR16)0x312F, 2}, // Bopomofo. 0x3100-0x312F + {(CHAR16)0x318F, 2}, // Hangul compatibility jamo. 0x3130-0x318F + {(CHAR16)0x319F, 2}, // Kanbun. 0x3190-0x319F + {(CHAR16)0x31FF, 0}, // Reserved. As Bopomofo extended in ver3.0. 0x31A0-0x31FF + {(CHAR16)0x32FF, 2}, // Enclosed CJK letters and months. 0x3200-0x32FF + {(CHAR16)0x33FF, 2}, // CJK compatibility. 0x3300-0x33FF + * + */ + + // + // CJK ideograph area + // + {(CHAR16)0x9FFF, 2}, + /* + * Merge the blocks and replace them with the above entry as they fall to + * the same category and they are all wide glyph. This will reduce search + * time and table size. The merge will omit the reserved code. + * + * Remove the above item if below is un-commented. + * + {(CHAR16)0x4DFF, 0}, // Reserved. 0x3400-0x4DBF as CJK unified ideographs + // extension A in ver3.0. 0x3400-0x4DFF + {(CHAR16)0x9FFF, 2}, // CJK unified ideographs. 0x4E00-0x9FFF + * + */ + + // + // Reserved + // + {(CHAR16)0xABFF, 0}, // Reserved. 0xA000-0xA490 as Yi syllables. 0xA490-0xA4D0 + // as Yi radicals in ver3.0. 0xA000-0xABFF + // + // Hangul syllables + // + {(CHAR16)0xD7FF, 2}, + /* + * Merge the blocks and replace them with the above entry as they fall to + * the same category and they are all wide glyph. This will reduce search + * time and table size. The merge will omit the reserved code. + * + * Remove the above item if below is un-commented. + * + {(CHAR16)0xD7A3, 2}, // Hangul syllables. 0xAC00-0xD7A3 + {(CHAR16)0xD7FF, 0}, // Reserved. 0xD7A3-0xD7FF + * + */ + + // + // Surrogates area + // + {(CHAR16)0xDFFF, 0}, // Surrogates, not used now. 0xD800-0xDFFF + + // + // Private use area + // + {(CHAR16)0xF8FF, 0}, // Private use area. 0xE000-0xF8FF + + // + // Compatibility area and specials + // + {(CHAR16)0xFAFF, 2}, // CJK compatibility ideographs. 0xF900-0xFAFF + {(CHAR16)0xFB4F, 1}, // Alphabetic presentation forms. 0xFB00-0xFB4F + {(CHAR16)0xFDFF, 1}, // Arabic presentation forms-A. 0xFB50-0xFDFF + {(CHAR16)0xFE1F, 0}, // Reserved. As variation selectors in ver3.0. 0xFE00-0xFE1F + {(CHAR16)0xFE2F, 1}, // Combining half marks. 0xFE20-0xFE2F + {(CHAR16)0xFE4F, 2}, // CJK compatibility forms. 0xFE30-0xFE4F + {(CHAR16)0xFE6F, 1}, // Small Form Variants. 0xFE50-0xFE6F + {(CHAR16)0xFEFF, 1}, // Arabic presentation forms-B. 0xFE70-0xFEFF + {(CHAR16)0xFFEF, 1}, // Half width and full width forms. 0xFF00-0xFFEF + {(CHAR16)0xFFFF, 0}, // Speicials. 0xFFF0-0xFFFF +}; + +/** + This function computes and returns the width of the Unicode character + specified by UnicodeChar. + + @param UnicodeChar A Unicode character. + + @retval 0 The width if UnicodeChar could not be determined. + @retval 1 UnicodeChar is a narrow glyph. + @retval 2 UnicodeChar is a wide glyph. + +**/ +UINTN +EFIAPI +GetGlyphWidth ( + IN CHAR16 UnicodeChar + ) +{ + UINTN Index; + UINTN Low; + UINTN High; + UNICODE_WIDTH_ENTRY *Item; + + Item = NULL; + Low = 0; + High = (sizeof (mUnicodeWidthTable)) / (sizeof (UNICODE_WIDTH_ENTRY)) - 1; + while (Low <= High) { + Index = (Low + High) >> 1; + Item = &(mUnicodeWidthTable[Index]); + if (Index == 0) { + if (UnicodeChar <= Item->WChar) { + break; + } + + return 0; + } + + if (UnicodeChar > Item->WChar) { + Low = Index + 1; + } else if (UnicodeChar <= mUnicodeWidthTable[Index - 1].WChar) { + High = Index - 1; + } else { + // + // Index - 1 < UnicodeChar <= Index. Found + // + break; + } + } + + if (Low <= High) { + return Item->Width; + } + + return 0; +} + +/** + This function computes and returns the display length of + the Null-terminated Unicode string specified by String. + If String is NULL, then 0 is returned. + If any of the widths of the Unicode characters in String + can not be determined, then 0 is returned. + + @param String A pointer to a Null-terminated Unicode string. + + @return The display length of the Null-terminated Unicode string specified by String. + +**/ +UINTN +EFIAPI +UnicodeStringDisplayLength ( + IN CONST CHAR16 *String + ) +{ + UINTN Length; + UINTN Width; + + Length = 0; + while (*String != 0) { + Width = GetGlyphWidth (*String); + if (Width == 0) { + return 0; + } + + Length += Width; + String++; + } + + return Length; +} diff --git a/MdePkg/Library/UefiLib/UefiLib.c b/MdePkg/Library/UefiLib/UefiLib.c new file mode 100644 index 0000000000..5280d659ac --- /dev/null +++ b/MdePkg/Library/UefiLib/UefiLib.c @@ -0,0 +1,650 @@ +/** @file + Mde UEFI library functions. + + Copyright (c) 2006, 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. + + Module Name: UefiLib.c + +**/ + +/** + Compare whether two names of languages are identical. + + @param Language1 Name of language 1. + @param Language2 Name of language 2. + + @retval TRUE Language 1 and language 2 are the same. + @retval FALSE Language 1 and language 2 are not the same. + +**/ +BOOLEAN +CompareIso639LanguageCode ( + IN CONST CHAR8 *Language1, + IN CONST CHAR8 *Language2 + ) +{ + return (BOOLEAN) (ReadUnaligned24 ((CONST UINT32 *) Language1) == ReadUnaligned24 ((CONST UINT32 *) Language2)); +} + +/** + This function searches the list of configuration tables stored in the EFI System + Table for a table with a GUID that matches TableGuid. If a match is found, + then a pointer to the configuration table is returned in Table, and EFI_SUCCESS + is returned. If a matching GUID is not found, then EFI_NOT_FOUND is returned. + + @param TableGuid Pointer to table's GUID type.. + @param Table Pointer to the table associated with TableGuid in the EFI System Table. + + @retval EFI_SUCCESS A configuration table matching TableGuid was found. + @retval EFI_NOT_FOUND A configuration table matching TableGuid could not be found. + +**/ +EFI_STATUS +EFIAPI +EfiGetSystemConfigurationTable ( + IN EFI_GUID *TableGuid, + OUT VOID **Table + ) +{ + EFI_SYSTEM_TABLE *SystemTable; + UINTN Index; + + ASSERT (TableGuid != NULL); + ASSERT (Table != NULL); + + SystemTable = gST; + *Table = NULL; + for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) { + if (CompareGuid (TableGuid, &(SystemTable->ConfigurationTable[Index].VendorGuid))) { + *Table = SystemTable->ConfigurationTable[Index].VendorTable; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +/** + This function causes the notification function to be executed for every protocol + of type ProtocolGuid instance that exists in the system when this function is + invoked. In addition, every time a protocol of type ProtocolGuid instance is + installed or reinstalled, the notification function is also executed. + + @param ProtocolGuid Supplies GUID of the protocol upon whose installation the event is fired. + @param NotifyTpl Supplies the task priority level of the event notifications. + @param NotifyFunction Supplies the function to notify when the event is signaled. + @param NotifyContext The context parameter to pass to NotifyFunction. + @param Registration A pointer to a memory location to receive the registration value. + + @return The notification event that was created. + +**/ +EFI_EVENT +EFIAPI +EfiCreateProtocolNotifyEvent( + IN EFI_GUID *ProtocolGuid, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN VOID *NotifyContext, OPTIONAL + OUT VOID *Registration + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + + // + // Create the event + // + + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + NotifyTpl, + NotifyFunction, + NotifyContext, + &Event + ); + ASSERT_EFI_ERROR (Status); + + // + // Register for protocol notifactions on this event + // + + Status = gBS->RegisterProtocolNotify ( + ProtocolGuid, + Event, + Registration + ); + + ASSERT_EFI_ERROR (Status); + + // + // Kick the event so we will perform an initial pass of + // current installed drivers + // + + gBS->SignalEvent (Event); + return Event; +} + +/** + This function creates an event using NotifyTpl, NoifyFunction, and NotifyContext. + This event is signaled with EfiNamedEventSignal(). This provide the ability for + one or more listeners on the same event named by the GUID specified by Name. + + @param Name Supplies GUID name of the event. + @param NotifyTpl Supplies the task priority level of the event notifications. + @param NotifyFunction Supplies the function to notify when the event is signaled. + @param NotifyContext The context parameter to pass to NotifyFunction. + @param Registration A pointer to a memory location to receive the registration value. + + @retval EFI_SUCCESS A named event was created. + @retval EFI_OUT_OF_RESOURCES There are not enough resource to create the named event. + +**/ +EFI_STATUS +EFIAPI +EfiNamedEventListen ( + IN CONST EFI_GUID *Name, + IN EFI_TPL NotifyTpl, + IN EFI_EVENT_NOTIFY NotifyFunction, + IN CONST VOID *NotifyContext, OPTIONAL + OUT VOID *Registration OPTIONAL + ) +{ + EFI_STATUS Status; + EFI_EVENT Event; + VOID *RegistrationLocal; + + // + // Create event + // + Status = gBS->CreateEvent ( + EFI_EVENT_NOTIFY_SIGNAL, + NotifyTpl, + NotifyFunction, + (VOID *) NotifyContext, + &Event + ); + ASSERT_EFI_ERROR (Status); + + // + // The Registration is not optional to RegisterProtocolNotify(). + // To make it optional to EfiNamedEventListen(), may need to substitute with a local. + // + if (Registration != NULL) { + RegistrationLocal = Registration; + } else { + RegistrationLocal = &RegistrationLocal; + } + + // + // Register for an installation of protocol interface + // + + Status = gBS->RegisterProtocolNotify ( + (EFI_GUID *) Name, + Event, + RegistrationLocal + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + +/** + This function signals the named event specified by Name. The named event must + have been created with EfiNamedEventListen(). + + @param Name Supplies GUID name of the event. + + @retval EFI_SUCCESS A named event was signaled. + @retval EFI_OUT_OF_RESOURCES There are not enough resource to signal the named event. + +**/ +EFI_STATUS +EFIAPI +EfiNamedEventSignal ( + IN CONST EFI_GUID *Name + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + + Handle = NULL; + Status = gBS->InstallProtocolInterface ( + &Handle, + (EFI_GUID *) Name, + EFI_NATIVE_INTERFACE, + NULL + ); + ASSERT_EFI_ERROR (Status); + + Status = gBS->UninstallProtocolInterface ( + Handle, + (EFI_GUID *) Name, + NULL + ); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} + + +/** + This function initializes a basic mutual exclusion lock to the released state + and returns the lock. Each lock provides mutual exclusion access at its task + priority level. Since there is no preemption or multiprocessor support in EFI, + acquiring the lock only consists of raising to the locks TPL. + + @param Lock A pointer to the lock data structure to initialize. + @param Priority EFI TPL associated with the lock. + + @return The lock. + +**/ +EFI_LOCK * +EFIAPI +EfiInitializeLock ( + IN OUT EFI_LOCK *Lock, + IN EFI_TPL Priority + ) +{ + ASSERT (Lock != NULL); + ASSERT (Priority <= EFI_TPL_HIGH_LEVEL); + + Lock->Tpl = Priority; + Lock->OwnerTpl = EFI_TPL_APPLICATION; + Lock->Lock = EfiLockReleased ; + return Lock; +} + +/** + This function raises the system¡¯s current task priority level to the task + priority level of the mutual exclusion lock. Then, it places the lock in the + acquired state. + + @param Priority The task priority level of the lock. + +**/ +VOID +EFIAPI +EfiAcquireLock ( + IN EFI_LOCK *Lock + ) +{ + ASSERT (Lock != NULL); + ASSERT (Lock->Lock == EfiLockReleased); + + Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl); + Lock->Lock = EfiLockAcquired; +} + +/** + This function raises the system¡¯s current task priority level to the task + priority level of the mutual exclusion lock. Then, it attempts to place the + lock in the acquired state. + + @param Lock A pointer to the lock to acquire. + + @retval EFI_SUCCESS The lock was acquired. + @retval EFI_ACCESS_DENIED The lock could not be acquired because it is already owned. + +**/ +EFI_STATUS +EFIAPI +EfiAcquireLockOrFail ( + IN EFI_LOCK *Lock + ) +{ + + ASSERT (Lock != NULL); + ASSERT (Lock->Lock != EfiLockUninitialized); + + if (Lock->Lock == EfiLockAcquired) { + // + // Lock is already owned, so bail out + // + return EFI_ACCESS_DENIED; + } + + Lock->OwnerTpl = gBS->RaiseTPL (Lock->Tpl); + + Lock->Lock = EfiLockAcquired; + + return EFI_SUCCESS; +} + +/** + This function transitions a mutual exclusion lock from the acquired state to + the released state, and restores the system¡¯s task priority level to its + previous level. + + @param Lock A pointer to the lock to release. + +**/ +VOID +EFIAPI +EfiReleaseLock ( + IN EFI_LOCK *Lock + ) +{ + EFI_TPL Tpl; + + ASSERT (Lock != NULL); + ASSERT (Lock->Lock == EfiLockAcquired); + + Tpl = Lock->OwnerTpl; + + Lock->Lock = EfiLockReleased; + + gBS->RestoreTPL (Tpl); +} + +/** + This function looks up a Unicode string in UnicodeStringTable. If Language is + a member of SupportedLanguages and a Unicode string is found in UnicodeStringTable + that matches the language code specified by Language, then it is returned in + UnicodeString. + + @param Language A pointer to the ISO 639-2 language code for the + Unicode string to look up and return. + @param SupportedLanguages A pointer to the set of ISO 639-2 language codes + that the Unicode string table supports. Language + must be a member of this set. + @param UnicodeStringTable A pointer to the table of Unicode strings. + @param UnicodeString A pointer to the Unicode string from UnicodeStringTable + that matches the language specified by Language. + + @retval EFI_SUCCESS The Unicode string that matches the language + specified by Language was found + in the table of Unicoide strings UnicodeStringTable, + and it was returned in UnicodeString. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is NULL. + @retval EFI_UNSUPPORTED SupportedLanguages is NULL. + @retval EFI_UNSUPPORTED UnicodeStringTable is NULL. + @retval EFI_UNSUPPORTED The language specified by Language is not a + member of SupportedLanguages. + @retval EFI_UNSUPPORTED The language specified by Language is not + supported by UnicodeStringTable. + +**/ +EFI_STATUS +EFIAPI +LookupUnicodeString ( + IN CONST CHAR8 *Language, + IN CONST CHAR8 *SupportedLanguages, + IN CONST EFI_UNICODE_STRING_TABLE *UnicodeStringTable, + OUT CHAR16 **UnicodeString + ) +{ + // + // Make sure the parameters are valid + // + if (Language == NULL || UnicodeString == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // If there are no supported languages, or the Unicode String Table is empty, then the + // Unicode String specified by Language is not supported by this Unicode String Table + // + if (SupportedLanguages == NULL || UnicodeStringTable == NULL) { + return EFI_UNSUPPORTED; + } + + // + // Make sure Language is in the set of Supported Languages + // + while (*SupportedLanguages != 0) { + if (CompareIso639LanguageCode (Language, SupportedLanguages)) { + + // + // Search the Unicode String Table for the matching Language specifier + // + while (UnicodeStringTable->Language != NULL) { + if (CompareIso639LanguageCode (Language, UnicodeStringTable->Language)) { + + // + // A matching string was found, so return it + // + *UnicodeString = UnicodeStringTable->UnicodeString; + return EFI_SUCCESS; + } + + UnicodeStringTable++; + } + + return EFI_UNSUPPORTED; + } + + SupportedLanguages += 3; + } + + return EFI_UNSUPPORTED; +} + +/** + This function adds a Unicode string to UnicodeStringTable. + If Language is a member of SupportedLanguages then UnicodeString is added to + UnicodeStringTable. New buffers are allocated for both Language and + UnicodeString. The contents of Language and UnicodeString are copied into + these new buffers. These buffers are automatically freed when + FreeUnicodeStringTable() is called. + + @param Language A pointer to the ISO 639-2 language code for the Unicode + string to add. + @param SupportedLanguages A pointer to the set of ISO 639-2 language codes + that the Unicode string table supports. + Language must be a member of this set. + @param UnicodeStringTable A pointer to the table of Unicode strings. + @param UnicodeString A pointer to the Unicode string to add. + + @retval EFI_SUCCESS The Unicode string that matches the language + specified by Language was found in the table of + Unicode strings UnicodeStringTable, and it was + returned in UnicodeString. + @retval EFI_INVALID_PARAMETER Language is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is NULL. + @retval EFI_INVALID_PARAMETER UnicodeString is an empty string. + @retval EFI_UNSUPPORTED SupportedLanguages is NULL. + @retval EFI_ALREADY_STARTED A Unicode string with language Language is + already present in UnicodeStringTable. + @retval EFI_OUT_OF_RESOURCES There is not enough memory to add another + Unicode string to UnicodeStringTable. + @retval EFI_UNSUPPORTED The language specified by Language is not a + member of SupportedLanguages. + +**/ +EFI_STATUS +EFIAPI +AddUnicodeString ( + IN CONST CHAR8 *Language, + IN CONST CHAR8 *SupportedLanguages, + IN EFI_UNICODE_STRING_TABLE **UnicodeStringTable, + IN CONST CHAR16 *UnicodeString + ) +{ + UINTN NumberOfEntries; + EFI_UNICODE_STRING_TABLE *OldUnicodeStringTable; + EFI_UNICODE_STRING_TABLE *NewUnicodeStringTable; + UINTN UnicodeStringLength; + + // + // Make sure the parameter are valid + // + if (Language == NULL || UnicodeString == NULL || UnicodeStringTable == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // If there are no supported languages, then a Unicode String can not be added + // + if (SupportedLanguages == NULL) { + return EFI_UNSUPPORTED; + } + + // + // If the Unicode String is empty, then a Unicode String can not be added + // + if (UnicodeString[0] == 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Make sure Language is a member of SupportedLanguages + // + while (*SupportedLanguages != 0) { + if (CompareIso639LanguageCode (Language, SupportedLanguages)) { + + // + // Determine the size of the Unicode String Table by looking for a NULL Language entry + // + NumberOfEntries = 0; + if (*UnicodeStringTable != NULL) { + OldUnicodeStringTable = *UnicodeStringTable; + while (OldUnicodeStringTable->Language != NULL) { + if (CompareIso639LanguageCode (Language, OldUnicodeStringTable->Language)) { + return EFI_ALREADY_STARTED; + } + + OldUnicodeStringTable++; + NumberOfEntries++; + } + } + + // + // Allocate space for a new Unicode String Table. It must hold the current number of + // entries, plus 1 entry for the new Unicode String, plus 1 entry for the end of table + // marker + // + NewUnicodeStringTable = AllocatePool ((NumberOfEntries + 2) * sizeof (EFI_UNICODE_STRING_TABLE)); + if (NewUnicodeStringTable == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // If the current Unicode String Table contains any entries, then copy them to the + // newly allocated Unicode String Table. + // + if (*UnicodeStringTable != NULL) { + CopyMem ( + NewUnicodeStringTable, + *UnicodeStringTable, + NumberOfEntries * sizeof (EFI_UNICODE_STRING_TABLE) + ); + } + + // + // Allocate space for a copy of the Language specifier + // + NewUnicodeStringTable[NumberOfEntries].Language = AllocateCopyPool (3, Language); + if (NewUnicodeStringTable[NumberOfEntries].Language == NULL) { + gBS->FreePool (NewUnicodeStringTable); + return EFI_OUT_OF_RESOURCES; + } + + // + // Compute the length of the Unicode String + // + for (UnicodeStringLength = 0; UnicodeString[UnicodeStringLength] != 0; UnicodeStringLength++) + ; + + // + // Allocate space for a copy of the Unicode String + // + NewUnicodeStringTable[NumberOfEntries].UnicodeString = AllocateCopyPool ( + (UnicodeStringLength + 1) * sizeof (CHAR16), + UnicodeString + ); + if (NewUnicodeStringTable[NumberOfEntries].UnicodeString == NULL) { + gBS->FreePool (NewUnicodeStringTable[NumberOfEntries].Language); + gBS->FreePool (NewUnicodeStringTable); + return EFI_OUT_OF_RESOURCES; + } + + // + // Mark the end of the Unicode String Table + // + NewUnicodeStringTable[NumberOfEntries + 1].Language = NULL; + NewUnicodeStringTable[NumberOfEntries + 1].UnicodeString = NULL; + + // + // Free the old Unicode String Table + // + if (*UnicodeStringTable != NULL) { + gBS->FreePool (*UnicodeStringTable); + } + + // + // Point UnicodeStringTable at the newly allocated Unicode String Table + // + *UnicodeStringTable = NewUnicodeStringTable; + + return EFI_SUCCESS; + } + + SupportedLanguages += 3; + } + + return EFI_UNSUPPORTED; +} + +/** + This function frees the table of Unicode strings in UnicodeStringTable. + If UnicodeStringTable is NULL, then EFI_SUCCESS is returned. + Otherwise, each language code, and each Unicode string in the Unicode string + table are freed, and EFI_SUCCESS is returned. + + @param UnicodeStringTable A pointer to the table of Unicode strings. + + @retval EFI_SUCCESS The Unicode string table was freed. + +**/ +EFI_STATUS +EFIAPI +FreeUnicodeStringTable ( + IN EFI_UNICODE_STRING_TABLE *UnicodeStringTable + ) +{ + UINTN Index; + + // + // If the Unicode String Table is NULL, then it is already freed + // + if (UnicodeStringTable == NULL) { + return EFI_SUCCESS; + } + + // + // Loop through the Unicode String Table until we reach the end of table marker + // + for (Index = 0; UnicodeStringTable[Index].Language != NULL; Index++) { + + // + // Free the Language string from the Unicode String Table + // + gBS->FreePool (UnicodeStringTable[Index].Language); + + // + // Free the Unicode String from the Unicode String Table + // + if (UnicodeStringTable[Index].UnicodeString != NULL) { + gBS->FreePool (UnicodeStringTable[Index].UnicodeString); + } + } + + // + // Free the Unicode String Table itself + // + gBS->FreePool (UnicodeStringTable); + + return EFI_SUCCESS; +} diff --git a/MdePkg/Library/UefiLib/UefiLib.mbd b/MdePkg/Library/UefiLib/UefiLib.mbd new file mode 100644 index 0000000000..252e3b1e83 --- /dev/null +++ b/MdePkg/Library/UefiLib/UefiLib.mbd @@ -0,0 +1,30 @@ + + + + + UefiLib + 3a004ba5-efe0-4a61-9f1a-267a46ae5ba9 + 0 + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 2006-03-09 23:12 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/UefiLib/UefiLib.msa b/MdePkg/Library/UefiLib/UefiLib.msa new file mode 100644 index 0000000000..6b3ea17ef5 --- /dev/null +++ b/MdePkg/Library/UefiLib/UefiLib.msa @@ -0,0 +1,61 @@ + + + + + UefiLib + UEFI_DRIVER + LIBRARY + 3a004ba5-efe0-4a61-9f1a-267a46ae5ba9 + 0 + Component description file for the entry point to a EFIDXE Drivers + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-09 23:12 + 2006-03-19 15:17 + + + UefiLib + UefiBootServicesTableLib + BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib + + + UefiLib.c + Console.c + UefiNotTiano.c + + + MdePkg + + + + EventLegacyBoot + + + EventReadyToBoot + + + FrameworkDevicePath + + + diff --git a/MdePkg/Library/UefiLib/UefiNotTiano.c b/MdePkg/Library/UefiLib/UefiNotTiano.c new file mode 100644 index 0000000000..2ac12f1b3a --- /dev/null +++ b/MdePkg/Library/UefiLib/UefiNotTiano.c @@ -0,0 +1,285 @@ +/** @file + Library functions that abstract areas of conflict between Tiano an UEFI 2.0. + + Help Port Framework/Tinao code that has conflicts with UEFI 2.0 by hiding the + oldconflicts with library functions and supporting implementations of the old + (R8.5/EFI 1.10) and new (R9/UEFI 2.0) way. + +Copyright (c) 2006, 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. + +**/ + + + +/** + Create a Legacy Boot Event. + + Tiano extended the CreateEvent Type enum to add a legacy boot event type. + This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was + added and now it's possible to not voilate the UEFI specification by + declaring a GUID for the legacy boot event class. This library supports + the R8.5/EFI 1.10 form and R9/UEFI 2.0 form and allows common code to + work both ways. + + @param LegacyBootEvent Returns the EFI event returned from gBS->CreateEvent(Ex). + + @retval EFI_SUCCESS Event was created. + @retval Other Event was not created. + +**/ +EFI_STATUS +EFIAPI +EfiCreateEventLegacyBoot ( + OUT EFI_EVENT *LegacyBootEvent + ) +{ + EFI_STATUS Status; + + ASSERT (LegacyBootEvent != NULL); + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) + // + // prior to UEFI 2.0 use Tiano extension to EFI + // + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_LEGACY_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL, + EFI_TPL_CALLBACK, + NULL, + NULL, + LegacyBootEvent + ); +#else + // + // For UEFI 2.0 and the future use an Event Group + // + Status = gBS->CreateEventEx ( + EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + NULL, + NULL, + &gEfiEventLegacyBootGuid, + LegacyBootEvent + ); +#endif + return Status; +} + + + +/** + Create a Read to Boot Event. + + Tiano extended the CreateEvent Type enum to add a ready to boot event type. + This was bad as Tiano did not own the enum. In UEFI 2.0 CreateEventEx was + added and now it's possible to not voilate the UEFI specification and use + the ready to boot event class defined in UEFI 2.0. This library supports + the R8.5/EFI 1.10 form and R9/UEFI 2.0 form and allows common code to + work both ways. + + @param LegacyBootEvent Returns the EFI event returned from gBS->CreateEvent(Ex). + + @retval EFI_SUCCESS Event was created. + @retval Other Event was not created. + +**/ +EFI_STATUS +EFIAPI +EfiCreateEventReadyToBoot ( + IN EFI_EVENT *ReadyToBootEvent + ) +{ + EFI_STATUS Status; + + ASSERT (ReadyToBootEvent != NULL); + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) + // + // prior to UEFI 2.0 use Tiano extension to EFI + // + Status = gBS->CreateEvent ( + EFI_EVENT_SIGNAL_READY_TO_BOOT | EFI_EVENT_NOTIFY_SIGNAL_ALL, + EFI_TPL_CALLBACK, + NULL, + NULL, + ReadyToBootEvent + ); +#else + // + // For UEFI 2.0 and the future use an Event Group + // + Status = gBS->CreateEventEx ( + EVENT_NOTIFY_SIGNAL, + EFI_TPL_CALLBACK, + NULL, + NULL, + &gEfiEventReadyToBootGuid, + ReadyToBootEvent + ); +#endif + + return Status; +} + + +/** + Signal a Ready to Boot Event. + + Create a Ready to Boot Event. Signal it and close it. This causes other + events of the same event group to be signaled in other modules. + +**/ +VOID +EFIAPI +EfiSignalEventReadyToBoot ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT ReadyToBootEvent; + + Status = EfiCreateEventReadyToBoot (&ReadyToBootEvent); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (ReadyToBootEvent); + gBS->CloseEvent (ReadyToBootEvent); + } +} + +/** + Signal a Legacy Boot Event. + + Create a legacy Boot Event. Signal it and close it. This causes other + events of the same event group to be signaled in other modules. + +**/ +VOID +EFIAPI +EfiSignalEventLegacyBoot ( + VOID + ) +{ + EFI_STATUS Status; + EFI_EVENT LegacyBootEvent; + + Status = EfiCreateEventLegacyBoot (&LegacyBootEvent); + if (!EFI_ERROR (Status)) { + gBS->SignalEvent (LegacyBootEvent); + gBS->CloseEvent (LegacyBootEvent); + } +} + + +/** + Check to see if the Firmware Volume (FV) Media Device Path is valid + + Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum + so as we move to UEFI 2.0 support we must use a mechanism that conforms with + the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed + device path is defined for PIWG extensions of device path. If the code + is compiled to conform with the UEFI 2.0 specification use the new device path + else use the old form for backwards compatability. The return value to this + function points to a location in FvDevicePathNode and it does not allocate + new memory for the GUID pointer that is returned. + + @param FvDevicePathNode Pointer to FV device path to check. + + @retval NULL FvDevicePathNode is not valid. + @retval Other FvDevicePathNode is valid and pointer to NameGuid was returned. + +**/ +EFI_GUID * +EFIAPI +EfiGetNameGuidFromFwVolDevicePathNode ( + IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode + ) +{ + ASSERT (FvDevicePathNode != NULL); + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) + // + // Use old Device Path that conflicts with UEFI + // + if (DevicePathType (&FvDevicePathNode->Header) == MEDIA_DEVICE_PATH || + DevicePathSubType (&FvDevicePathNode->Header) == MEDIA_FV_FILEPATH_DP) { + return &FvDevicePathNode->NameGuid; + } + +#else + // + // Use the new Device path that does not conflict with the UEFI + // + if (FvDevicePathNode->Piwg.Header.Type == MEDIA_DEVICE_PATH || + FvDevicePathNode->Piwg.Header.SubType == MEDIA_VENDOR_DP) { + if (CompareGuid (&gEfiFrameworkDevicePathGuid, &FvDevicePathNode->Piwg.PiwgSpecificDevicePath)) { + if (FvDevicePathNode->Piwg.Type == PIWG_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH_TYPE) { + return &FvDevicePathNode->NameGuid; + } + } + } +#endif + return NULL; +} + + +/** + Initialize a Firmware Volume (FV) Media Device Path node. + + Tiano extended the EFI 1.10 device path nodes. Tiano does not own this enum + so as we move to UEFI 2.0 support we must use a mechanism that conforms with + the UEFI 2.0 specification to define the FV device path. An UEFI GUIDed + device path is defined for PIWG extensions of device path. If the code + is compiled to conform with the UEFI 2.0 specification use the new device path + else use the old form for backwards compatability. + + @param FvDevicePathNode Pointer to a FV device path node to initialize + @param NameGuid FV file name to use in FvDevicePathNode + +**/ +VOID +EFIAPI +EfiInitializeFwVolDevicepathNode ( + IN MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvDevicePathNode, + IN EFI_GUID *NameGuid + ) +{ + ASSERT (FvDevicePathNode != NULL); + ASSERT (NameGuid != NULL); + +#if (EFI_SPECIFICATION_VERSION < 0x00020000) + // + // Use old Device Path that conflicts with UEFI + // + FvDevicePathNode->Header.Type = MEDIA_DEVICE_PATH; + FvDevicePathNode->Header.SubType = MEDIA_FV_FILEPATH_DP; + SetDevicePathNodeLength (&FvDevicePathNode->Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH)); + +#else + // + // Use the new Device path that does not conflict with the UEFI + // + FvDevicePathNode->Piwg.Header.Type = MEDIA_DEVICE_PATH; + FvDevicePathNode->Piwg.Header.SubType = MEDIA_VENDOR_DP; + SetDevicePathNodeLength (&FvDevicePathNode->Piwg.Header, sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH)); + + // + // Add the GUID for generic PIWG device paths + // + CopyGuid (&FvDevicePathNode->Piwg.PiwgSpecificDevicePath, &gEfiFrameworkDevicePathGuid); + + // + // Add in the FW Vol File Path PIWG defined inforation + // + FvDevicePathNode->Piwg.Type = PIWG_MEDIA_FW_VOL_FILEPATH_DEVICE_PATH_TYPE; + +#endif + + CopyGuid (&FvDevicePathNode->NameGuid, NameGuid); + +} + diff --git a/MdePkg/Library/UefiLib/build.xml b/MdePkg/Library/UefiLib/build.xml new file mode 100644 index 0000000000..27def12f4f --- /dev/null +++ b/MdePkg/Library/UefiLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/UefiMemoryLib/MemLib.c b/MdePkg/Library/UefiMemoryLib/MemLib.c new file mode 100644 index 0000000000..f8f8e30d0a --- /dev/null +++ b/MdePkg/Library/UefiMemoryLib/MemLib.c @@ -0,0 +1,39 @@ +/** @file + Base Memory Library. + + Copyright (c) 2006, 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. + + Module Name: MemLib.c + +**/ + +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + gBS->CopyMem (Destination, (VOID*)Source, Length); + return Destination; +} + +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + gBS->SetMem (Buffer, Size, Value); + return Buffer; +} diff --git a/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c b/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c new file mode 100644 index 0000000000..ef9f358a79 --- /dev/null +++ b/MdePkg/Library/UefiMemoryLib/MemLibGeneric.c @@ -0,0 +1,282 @@ +/** @file + Architecture Independent Base Memory Library Implementation. + + Copyright (c) 2006, 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. + + Module Name: MemLibGeneric.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + do { + ((UINT16*)Buffer)[--Length] = Value; + } while (Length != 0); + return Buffer; +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + do { + ((UINT32*)Buffer)[--Length] = Value; + } while (Length != 0); + return Buffer; +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + do { + ((UINT64*)Buffer)[--Length] = Value; + } while (Length != 0); + return Buffer; +} + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ) +{ + return InternalMemSetMem (Buffer, Length, 0); +} + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @retval 0 if MemOne == MemTwo + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + ASSERT (Length > 0); + while ((--Length != 0) && + (*(INT8*)DestinationBuffer == *(INT8*)SourceBuffer)) { + DestinationBuffer = (INT8*)DestinationBuffer + 1; + SourceBuffer = (INT8*)SourceBuffer + 1; + } + return (INTN)*(UINT8*)DestinationBuffer - (INTN)*(UINT8*)SourceBuffer; +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + CONST UINT8 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT8*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + CONST UINT16 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT16*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + CONST UINT32 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT32*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + CONST UINT64 *Pointer; + + ASSERT (Length > 0); + Pointer = (CONST UINT64*)Buffer; + do { + if (*(Pointer++) == Value) { + return Pointer; + } + } while (--Length != 0); + return NULL; +} diff --git a/MdePkg/Library/UefiMemoryLib/MemLibGuid.c b/MdePkg/Library/UefiMemoryLib/MemLibGuid.c new file mode 100644 index 0000000000..06b2721c64 --- /dev/null +++ b/MdePkg/Library/UefiMemoryLib/MemLibGuid.c @@ -0,0 +1,131 @@ +/** @file + Implementation of GUID functions. + + Copyright (c) 2006, 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. + + Module Name: MemLibGuid.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + This function copies a source GUID to a destination GUID. + + This function copies the contents of the 128-bit GUID specified by SourceGuid + to DestinationGuid, and returns DestinationGuid. + + If DestinationGuid is NULL, then ASSERT(). + If SourceGuid is NULL, then ASSERT(). + + @param DestinationGuid Pointer to the destination GUID. + @param SourceGuid Pointer to the source GUID. + + @return DestinationGuid + +**/ +GUID * +EFIAPI +CopyGuid ( + OUT GUID *DestinationGuid, + IN CONST GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +/** + Compares two GUIDs + + This function compares Guid1 to Guid2. If the GUIDs are identical then TRUE + is returned. If there are any bit differences in the two GUIDs, then FALSE is + returned. + + If Guid1 is NULL, then ASSERT(). + If Guid2 is NULL, then ASSERT(). + + @param Guid1 guid to compare + @param Guid2 guid to compare + + @retval TRUE if Guid1 == Guid2 + @retval FALSE if Guid1 != Guid2 + +**/ +BOOLEAN +EFIAPI +CompareGuid ( + IN CONST GUID *Guid1, + IN CONST GUID *Guid2 + ) +{ + return (BOOLEAN)( + ReadUnaligned64 ((CONST UINT64*)Guid1) + == ReadUnaligned64 ((CONST UINT64*)Guid2) && + ReadUnaligned64 ((CONST UINT64*)Guid1 + 1) + == ReadUnaligned64 ((CONST UINT64*)Guid2 + 1) + ); +} + +/** + Scans a target buffer for a GUID, and returns a pointer to the matching GUID + in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 128-bit increments for the + 128-bit GUID value that matches Guid. If a match is found, then a pointer to + the matching GUID in the target buffer is returned. If no match is found, + then NULL is returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Guid Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Guid was not found. +**/ +VOID * +EFIAPI +ScanGuid ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN CONST GUID *Guid + ) +{ + CONST GUID *GuidPtr; + + GuidPtr = (GUID*)Buffer; + Buffer = GuidPtr + Length / sizeof (*GuidPtr); + while (GuidPtr < (CONST GUID*)Buffer) { + if (CompareGuid (GuidPtr, Guid)) { + return (VOID*)GuidPtr; + } + GuidPtr++; + } + return NULL; +} diff --git a/MdePkg/Library/UefiMemoryLib/MemLibWrapper.c b/MdePkg/Library/UefiMemoryLib/MemLibWrapper.c new file mode 100644 index 0000000000..2ef0766242 --- /dev/null +++ b/MdePkg/Library/UefiMemoryLib/MemLibWrapper.c @@ -0,0 +1,620 @@ +/** @file + Wrapper functions for Base Memory Library. + + Copyright (c) 2006, 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. + + Module Name: MemLibWrapper.c + + The following BaseMemoryLib instances share the same version of this file: + + BaseMemoryLib + BaseMemoryLibMmx + BaseMemoryLibSse2 + BaseMemoryLibRepStr + PeiMemoryLib + UefiMemoryLib + +**/ + +/** + Copy Length bytes from Source to Destination. + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +InternalMemCopyMem ( + OUT VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Set Buffer to Value for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemSetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Set Buffer to 0 for Size bytes. + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +InternalMemZeroMem ( + OUT VOID *Buffer, + IN UINTN Length + ); + +/** + Compares two memory buffers of a given length. + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare. Must be non-zero. + + @retval 0 if MemOne == MemTwo + +**/ +INTN +EFIAPI +InternalMemCompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ); + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ); + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ); + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ); + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. Must be non-zero. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + +**/ +CONST VOID * +EFIAPI +InternalMemScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ); + +/** + Copy Length bytes from Source to Destination. + + This function copies Length bytes from SourceBuffer to DestinationBuffer, and + returns DestinationBuffer. The implementation must be reentrant, and it must + handle the case where SourceBuffer overlaps DestinationBuffer. + + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param Destination Target of copy + @param Source Place to copy from + @param Length Number of bytes to copy + + @return Destination + +**/ +VOID * +EFIAPI +CopyMem ( + OUT VOID *Destination, + IN CONST VOID *Source, + IN UINTN Length + ) +{ + ASSERT (Length <= MAX_ADDRESS - (UINTN)Destination + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Source + 1); + return InternalMemCopyMem (Destination, Source, Length); +} + +/** + Set Buffer to Value for Size bytes. + + This function fills Length bytes of Buffer with Value, and returns Buffer. + + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + @param Value Value of the set operation. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem ( + IN VOID *Buffer, + IN UINTN Size, + IN UINT8 Value + ) +{ + ASSERT (Size <= MAX_ADDRESS - (UINTN)Buffer + 1); + return InternalMemSetMem (Buffer, Size, Value); +} + +/** + Fills a target buffer with a 16-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 16-bit value specified by + Value, and returns Buffer. Value is repeated every 16-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is not aligned on a 16-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem16 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem16 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 32-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 32-bit value specified by + Value, and returns Buffer. Value is repeated every 32-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is not aligned on a 32-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem32 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem32 (Buffer, Length, Value); +} + +/** + Fills a target buffer with a 64-bit value, and returns the target buffer. + + This function fills Length bytes of Buffer with the 64-bit value specified by + Value, and returns Buffer. Value is repeated every 64-bits in for Length + bytes of Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is not aligned on a 64-bit boundary, then ASSERT(). + + @param Buffer Pointer to the target buffer to fill. + @param Length Number of bytes in Buffer to fill. + @param Value Value with which to fill Length bytes of Buffer. + + @return Buffer + +**/ +VOID * +EFIAPI +SetMem64 ( + OUT VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)Buffer + 1); + ASSERT ((((UINTN)Buffer) & 1) != 0); + ASSERT ((Length & 1) != 0); + + if ((Length /= sizeof (Value)) == 0) { + return Buffer; + } + return InternalMemSetMem64 (Buffer, Length, Value); +} + +/** + Set Buffer to 0 for Size bytes. + + This function fills Length bytes of Buffer with zeros, and returns Buffer. + + If Buffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Memory to set. + @param Size Number of bytes to set + + @return Buffer + +**/ +VOID * +EFIAPI +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + ASSERT (Buffer != NULL); + return InternalMemSetMem (Buffer, Size, 0); +} + +/** + Compares two memory buffers of a given length. + + This function compares Length bytes of SourceBuffer to Length bytes of + DestinationBuffer. If all Length bytes of the two buffers are identical, then + 0 is returned. Otherwise, the value returned is the first mismatched byte in + SourceBuffer subtracted from the first mismatched byte in DestinationBuffer. + + If DestinationBuffer is NULL and Length > 0, then ASSERT(). + If SourceBuffer is NULL and Length > 0, then ASSERT(). + If Length is greater than (MAX_ADDRESS - DestinationBuffer + 1), then + ASSERT(). + If Length is greater than (MAX_ADDRESS - SourceBuffer + 1), then ASSERT(). + + @param DestinationBuffer First memory buffer + @param SourceBuffer Second memory buffer + @param Length Length of DestinationBuffer and SourceBuffer memory + regions to compare + + @retval 0 if DestinationBuffer == SourceBuffer + @retval Non-zero if DestinationBuffer != SourceBuffer + +**/ +INTN +EFIAPI +CompareMem ( + IN CONST VOID *DestinationBuffer, + IN CONST VOID *SourceBuffer, + IN UINTN Length + ) +{ + ASSERT (DestinationBuffer != NULL); + ASSERT (SourceBuffer != NULL); + ASSERT (Length <= MAX_ADDRESS - (UINTN)DestinationBuffer + 1); + ASSERT (Length <= MAX_ADDRESS - (UINTN)SourceBuffer + 1); + if (Length == 0) { + return 0; + } + return InternalMemCompareMem (DestinationBuffer, SourceBuffer, Length); +} + +/** + Scans a target buffer for an 8-bit value, and returns a pointer to the + matching 8-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address for an 8-bit value that matches + Value. If a match is found, then a pointer to the matching byte in the target + buffer is returned. If no match is found, then NULL is returned. If Length is + 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem8 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT8 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem8 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 16-bit value, and returns a pointer to the + matching 16-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 16-bit increments for a 16-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 16-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem16 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem16 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 32-bit value, and returns a pointer to the + matching 32-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 32-bit increments for a 32-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 32-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem32 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT32 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem32 (Buffer, Length, Value); +} + +/** + Scans a target buffer for a 64-bit value, and returns a pointer to the + matching 64-bit value in the target buffer. + + This function searches target the buffer specified by Buffer and Length from + the lowest address to the highest address at 64-bit increments for a 64-bit + value that matches Value. If a match is found, then a pointer to the matching + value in the target buffer is returned. If no match is found, then NULL is + returned. If Length is 0, then NULL is returned. + + If Buffer is NULL, then ASSERT(). + If Buffer is not aligned on a 64-bit boundary, then ASSERT(). + If Length is greater than (MAX_ADDRESS - Buffer + 1), then ASSERT(). + + @param Buffer Pointer to the target buffer to scan. + @param Length Number of bytes in Buffer to scan. + @param Value Value to search for in the target buffer. + + @return Pointer to the first occurrence or NULL if not found. + @retval NULL if Length == 0 or Value was not found. + +**/ +VOID * +EFIAPI +ScanMem64 ( + IN CONST VOID *Buffer, + IN UINTN Length, + IN UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + ASSERT (((UINTN)Buffer & (sizeof (Value) - 1)) == 0); + ASSERT (Length <= MAX_ADDRESS + (UINTN)Buffer + 1); + + if ((Length /= sizeof (Value)) == 0) { + return NULL; + } + return (VOID*)InternalMemScanMem64 (Buffer, Length, Value); +} diff --git a/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.mbd b/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.mbd new file mode 100644 index 0000000000..70fd110e1e --- /dev/null +++ b/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.mbd @@ -0,0 +1,29 @@ + + + + + UefiMemoryLib + f1bbe03d-2f28-4dee-bec7-d98d7a30c36a + EDK_RELEASE_VERSION 0x00090000 + FIX ME! + Copyright (c) 2004-2006, 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. + + 2006-04-12 13:39 + + diff --git a/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.msa b/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.msa new file mode 100644 index 0000000000..7ef511cb16 --- /dev/null +++ b/MdePkg/Library/UefiMemoryLib/UefiMemoryLib.msa @@ -0,0 +1,48 @@ + + + + + UefiMemoryLib + UEFI_DRIVER + LIBRARY + f1bbe03d-2f28-4dee-bec7-d98d7a30c36a + EDK_RELEASE_VERSION 0x00090000 + Memory-only library functions with no library constructor/destructor + FIX ME! + Copyright (c) 2004-2006, 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. + + EFI_SPECIFICATION_VERSION 0x00000000 + 2006-04-12 13:39 + + + BaseMemoryLib + DebugLib + UefiBootServicesTableLib + BaseLib + + + MemLib.c + MemLibGuid.c + MemLibGeneric.c + MemLibWrapper.c + + + MdePkg + + diff --git a/MdePkg/Library/UefiMemoryLib/build.xml b/MdePkg/Library/UefiMemoryLib/build.xml new file mode 100644 index 0000000000..02f67e706b --- /dev/null +++ b/MdePkg/Library/UefiMemoryLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c b/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c new file mode 100644 index 0000000000..ac4b3ebfbf --- /dev/null +++ b/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.c @@ -0,0 +1,36 @@ +/** @file + UEFI Runtime Services Table Library. + + Copyright (c) 2006, 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. + + Module Name: UefiRuntimeServicesTableLib.c + +**/ + +// +// Cached copy of the EFI Runtime Services Table +// +EFI_RUNTIME_SERVICES *gRT = NULL; + +/** +**/ +EFI_STATUS +UefiRuntimeServicesTableLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + // + // Cache pointer to the EFI Runtime Services Table + // + gRT = SystemTable->RuntimeServices; + ASSERT (gRT != NULL); + return EFI_SUCCESS; +} diff --git a/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.mbd b/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.mbd new file mode 100644 index 0000000000..df9238a717 --- /dev/null +++ b/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.mbd @@ -0,0 +1,30 @@ + + + + + UefiRuntimeServicesTableLib + baa1baa3-0a8d-402c-8042-985115fae953 + 0 + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 2006-03-17 15:49 + 2006-03-19 15:17 + + diff --git a/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.msa b/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.msa new file mode 100644 index 0000000000..e78c9cb9d0 --- /dev/null +++ b/MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.msa @@ -0,0 +1,49 @@ + + + + + UefiRuntimeServicesTableLib + DXE_DRIVER + LIBRARY + baa1baa3-0a8d-402c-8042-985115fae953 + 0 + UEFI Runtime Services Table Library + Library to abstract Framework extensions that conflict with UEFI 2.0 Specification + Copyright (c) 2004-2006, 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. + + 0 + 2006-03-17 15:49 + 2006-03-19 15:17 + + + UefiRuntimeServicesTableLib + DebugLib + + + UefiRuntimeServicesTableLib.c + + + MdePkg + + + + UefiRuntimeServicesTableLibConstructor + + + diff --git a/MdePkg/Library/UefiRuntimeServicesTableLib/build.xml b/MdePkg/Library/UefiRuntimeServicesTableLib/build.xml new file mode 100644 index 0000000000..37c0cacd25 --- /dev/null +++ b/MdePkg/Library/UefiRuntimeServicesTableLib/build.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MdePkg/MdePkg.fpd b/MdePkg/MdePkg.fpd new file mode 100644 index 0000000000..3e30358384 --- /dev/null +++ b/MdePkg/MdePkg.fpd @@ -0,0 +1,482 @@ + + + + + MdePkg + EFI/Tiano MdePkg Package + This FPD file is used for Package Level build. + 2006-04-03 13:40 + lhauch + + + dummy.fdf + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + PcdMaximumUnicodeStringLength + 0x00000001 + UINT32 + false + false + false + false + false + 0 + 0 + 4 + 0 + L"" + 0 + 0 + 1000000 + + + PcdMaximumAsciiStringLength + 0x00000002 + UINT32 + false + false + false + false + false + 0 + 0 + 4 + 0 + L"" + 0 + 0 + 1000000 + + + PcdMaximumLinkedListLength + 0x00000003 + UINT32 + false + false + false + false + false + 0 + 0 + 4 + 0 + L"" + 0 + 0 + 1000000 + + + PcdSpinLockTimeout + 0x00000004 + UINT32 + false + false + false + false + false + 0 + 0 + 4 + 0 + L"" + 0 + 0 + 10000000 + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + false + false + false + false + false + 0 + 0 + 1 + 0 + L"" + 0 + 0 + 0 + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + false + false + false + false + false + 0 + 0 + 4 + 0 + L"" + 0 + 0 + 0x80000000 + + + PcdReportStatusCodePropertyMask + 0x00000007 + UINT8 + false + false + false + false + false + 0 + 0 + 1 + 0 + L"" + 0 + 0 + 0 + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + false + false + false + false + false + 0 + 0 + 1 + 0 + L"" + 0 + 0 + 0xAF + + + PcdPerformanceLibraryPropertyMask + 0x00000009 + UINT8 + false + false + false + false + false + 0 + 0 + 1 + 0 + L"" + 0 + 0 + 0x0 + + + + + + diff --git a/MdePkg/MdePkg.spd b/MdePkg/MdePkg.spd new file mode 100644 index 0000000000..4b2983274f --- /dev/null +++ b/MdePkg/MdePkg.spd @@ -0,0 +1,1231 @@ + + + + + MdePkg + 5e0e9358-46b6-4ae2-8218-4ab8b9bbdcec + 0 + FIX ME! + FIX ME! + Copyright (c) 2006, 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. + 2006-03-18 19:02 + 2006-03-19 15:18 + http://www.TianoCore.org + SOURCE + true + false + + + + BaseLib + Include/Library/BaseLib.h + + + BaseMemoryLib + Include/Library/BaseMemoryLib.h + + + CacheMaintenanceLib + Include/Library/CacheMaintenanceLib.h + + + CpuLib + Include/Library/CpuLib.h + + + DebugLib + Include/Library/DebugLib.h + + + DevicePathLib + Include/Library/DevicePathLib.h + + + DxeCoreEntryPoint + Include/Library/DxeCoreEntryPoint.h + + + DxeRuntimeDriverLib + Include/Library/DxeRuntimeDriverLib.h + + + DxeServicesTableLib + Include/Library/DxeServicesTableLib.h + + + DxeSmmDriverEntryPoint + Include/Library/DxeSmmDriverEntryPoint.h + + + HiiLib + Include/Library/HiiLib.h + + + HobLib + Include/Library/HobLib.h + + + IoLib + Include/Library/IoLib.h + + + MemoryAllocationLib + Include/Library/MemoryAllocationLib.h + + + PcdLib + Include/Library/PcdLib.h + + + PciCf8Lib + Include/Library/PciCf8Lib.h + + + PciExpressLib + Include/Library/PciExpressLib.h + + + PciLib + Include/Library/PciLib.h + + + PciSegmentLib + Include/Library/PciSegmentLib.h + + + PeCoffGetEntryPointLib + Include/Library/PeCoffGetEntryPointLib.h + + + PeCoffLib + Include/Library/PeCoffLib.h + + + PeiCoreEntryPoint + Include/Library/PeiCoreEntryPoint.h + + + PeiCoreLib + Include/Library/PeiCoreLib.h + + + PeimEntryPoint + Include/Library/PeimEntryPoint.h + + + PeiServicesTablePointerLib + Include/Library/PeiServicesTablePointerLib.h + + + PerformanceLib + Include/Library/PerformanceLib.h + + + PrintLib + Include/Library/PrintLib.h + + + ReportStatusCodeLib + Include/Library/ReportStatusCodeLib.h + + + ResourcePublicationLib + Include/Library/ResourcePublicationLib.h + + + SmbusLib + Include/Library/SmbusLib.h + + + TimerLib + Include/Library/TimerLib.h + + + Uefi2PortLib + Include/Library/Uefi2PortLib.h + + + UefiBootServicesTableLib + Include/Library/UefiBootServicesTableLib.h + + + UefiDecompressLib + Include/Library/UefiDecompressLib.h + + + UefiDriverEntryPoint + Include/Library/UefiDriverEntryPoint.h + + + UefiDriverModelLib + Include/Library/UefiDriverModelLib.h + + + UefiLib + Include/Library/UefiLib.h + + + UefiRuntimeServicesTableLib + Include/Library/UefiRuntimeServicesTableLib.h + + + + + Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.msa + + + Library/BaseDebugLibNull/BaseDebugLibNull.msa + + + Library/BaseDebugLibReportStatusCode/BaseDebugLibReportStatusCode.msa + + + Library/BasePerformanceLibNull/BasePerformanceLibNull.msa + + + Library/BasePcdLibNull/BasePcdLibNull.msa + + + Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.msa + + + Library/BaseLib/BaseLib.msa + + + Library/BaseMemoryLib/BaseMemoryLib.msa + + + Library/BaseMemoryLibRepStr/BaseMemoryLibRepStr.msa + + + Library/BaseMemoryLibMmx/BaseMemoryLibMmx.msa + + + Library/BaseMemoryLibSse2/BaseMemoryLibSse2.msa + + + Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.msa + + + Library/BasePeCoffLib/BasePeCoffLib.msa + + + Library/BasePrintLib/BasePrintLib.msa + + + Library/BaseReportStatusCodeLibNull/BaseReportStatusCodeLibNull.msa + + + Library/BaseSmbusLib/BaseSmbusLib.msa + + + Library/PeiSmbusLib/PeiSmbusLib.msa + + + Library/DxeSmbusLib/DxeSmbusLib.msa + + + Library/BaseUefiDecompressLib/BaseUefiDecompressLib.msa + + + Library/BasePciCf8Lib/BasePciCf8Lib.msa + + + Library/BasePciExpressLib/BasePciExpressLib.msa + + + Library/BasePciLibCf8/BasePciLibCf8.msa + + + Library/BasePciLibPciExpress/BasePciLibPciExpress.msa + + + Library/BaseTimerLibLocalApic/BaseTimerLibLocalApic.msa + + + Library/DxeCoreEntryPoint/DxeCoreEntryPoint.msa + + + Library/DxeCoreHobLib/DxeCoreHobLib.msa + + + Library/DxeHobLib/DxeHobLib.msa + + + Library/DxeIoLibCpuIo/DxeIoLibCpuIo.msa + + + Library/PeiIoLibCpuIo/PeiIoLibCpuIo.msa + + + Library/DxeMemoryAllocationLib/DxeMemoryAllocationLib.msa + + + Library/DxePcdLib/DxePcdLib.msa + + + Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.msa + + + Library/DxeServicesTableLib/DxeServicesTableLib.msa + + + Library/DxeSmmDriverEntryPoint/DxeSmmDriverEntryPoint.msa + + + Library/HiiLib/HiiLib.msa + + + Library/PeiCoreEntryPoint/PeiCoreEntryPoint.msa + + + Library/PeiCoreLib/PeiCoreLib.msa + + + Library/PeiHobLib/PeiHobLib.msa + + + Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.msa + + + Library/PeiMemoryLib/PeiMemoryLib.msa + + + Library/PeimEntryPoint/PeimEntryPoint.msa + + + Library/PeiPcdLib/PeiPcdLib.msa + + + Library/PeiReportStatusCodeLib/PeiReportStatusCodeLib.msa + + + Library/PeiResourcePublicationLib/PeiResourcePublicationLib.msa + + + Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.msa + + + Library/PeiServicesTablePointerLibMm7/PeiServicesTablePointerLibMm7.msa + + + Library/UefiBootServicesTableLib/UefiBootServicesTableLib.msa + + + Library/UefiDebugLibConOut/UefiDebugLibConOut.msa + + + Library/UefiDebugLibStdErr/UefiDebugLibStdErr.msa + + + Library/UefiDevicePathLib/UefiDevicePathLib.msa + + + Library/UefiDevicePathLibDevicePathProtocol/UefiDevicePathLibDevicePathProtocol.msa + + + Library/UefiDriverEntryPoint/UefiDriverEntryPoint.msa + + + Library/UefiDriverModelLib/UefiDriverModelLib.msa + + + Library/UefiLib/UefiLib.msa + + + Library/UefiMemoryLib/UefiMemoryLib.msa + + + Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.msa + + + + Include/Base.h + Include/Peim.h + Include/PeiCore.h + Include/Peim.h + Include/DxeCore.h + Include/Dxe.h + Include/Dxe.h + Include/Dxe.h + Include/Dxe.h + Include/Uefi.h + Include/Uefi.h + + + + gEfiAcpi10TableGuid + 0xeb9d2d30, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiAcpi20TableGuid + 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiAcpi30TableGuid + 0x8868e871, 0xe4f1, 0x11d3, 0xbc, 0x22, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiDebugImageInfoTableGuid + 0x49152e77, 0x1ada, 0x4764, 0xb7, 0xa2, 0x7a, 0xfe, 0xfe, 0xd9, 0x5e, 0x8b + + + gEfiGlobalVariableGuid + 0x8BE4DF61, 0x93CA, 0x11d2, 0xAA, 0x0D, 0x00, 0xE0, 0x98, 0x03, 0x2B, 0x8C + + + gEfiPartTypeUnusedGuid + 0x00000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + + + gEfiPartTypeSystemPartGuid + 0xc12a7328, 0xf81f, 0x11d2, 0xba, 0x4b, 0x00, 0xa0, 0xc9, 0x3e, 0xc9, 0x3b + + + gEfiPartTypeLegacyMbrGuid + 0x024dee41, 0x33e7, 0x11d3, 0x9d, 0x69, 0x00, 0x08, 0xc7, 0x81, 0xf3, 0x9f + + + gEfiMpsTableGuid + 0xeb9d2d2f, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiPcAnsiGuid + 0xe0c14753, 0xf9be, 0x11d2, 0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiVT100Guid + 0xdfa66065, 0xb419, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiVT100PlusGuid + 0x7baec70b, 0x57e0, 0x4c76, 0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43 + + + gEfiVTUTF8Guid + 0xad15a0d6, 0x8bec, 0x4acf, 0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88 + + + gEfiSalSystemTableGuid + 0xeb9d2d32, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiSmbiosTableGuid + 0xeb9d2d31, 0x2d88, 0x11d3, 0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gAprioriGuid + 0xfc510ee7, 0xffdc, 0x11d4, 0xbd, 0x41, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiDxeServicesTableGuid + 0x5ad34ba, 0x6f02, 0x4214, 0x95, 0x2e, 0x4d, 0xa0, 0x39, 0x8e, 0x2b, 0xb9 + + + gEfiFirmwareFileSystemGuid + 0x7A9354D9, 0x0468, 0x444a, 0x81, 0xCE, 0x0B, 0xF6, 0x17, 0xD8, 0x90, 0xDF + + + gEfiFirmwareVolumeTopFileGuid + 0x1BA0062E, 0xC779, 0x4582, 0x85, 0x66, 0x33, 0x6A, 0xE8, 0xF7, 0x8F, 0x09 + + + gEfiHobListGuid + 0x7739f24c, 0x93d7, 0x11d4, 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiHobMemoryAllocBspStoreGuid + 0x564b33cd, 0xc92a, 0x4593, 0x90, 0xbf, 0x24, 0x73, 0xe4, 0x3c, 0x63, 0x22 + + + gEfiHobMemoryAllocStackGuid + 0x4ed4bf27, 0x4092, 0x42e9, 0x80, 0x7d, 0x52, 0x7b, 0x1d, 0x00, 0xc9, 0xbd + + + gEfiHobMemoryAllocModuleGuid + 0xf8e21975, 0x0899, 0x4f58, 0xa4, 0xbe, 0x55, 0x25, 0xa9, 0xc6, 0xd7, 0x7a + + + gEfiFileInfoGuid + 0x9576e92, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + gEfiFileSystemInfoGuid + 0x9576e93, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + gEfiFileSystemVolumeLabelInfoIdGuid + 0xDB47D7D3, 0xFE81, 0x11d3, 0x9A, 0x35, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D + + + gEfiProcessorProducerGuid + 0x1bf06aea, 0x5bec, 0x4a8d, 0x95, 0x76, 0x74, 0x9b, 0x09, 0x56, 0x2d, 0x30 + + + gEfiProcessorSubClassGuid + 0x26fdeb7e, 0xb8af, 0x4ccf, 0xaa, 0x97, 0x02, 0x63, 0x3c, 0xe4, 0x8c, 0xa7 + + + gEfiCacheSubClassGuid + 0x7f0013a7, 0xdc79, 0x4b22, 0x80, 0x99, 0x11, 0xf7, 0x5f, 0xdc, 0x82, 0x9d + + + gEfiMemoryProducerGuid + 0x772484B2, 0x7482, 0x4b91, 0x9F, 0x9A, 0xAD, 0x43, 0xF8, 0x1C, 0x58, 0x81 + + + gEfiMemorySubClassGuid + 0x4E8F4EBB, 0x64B9, 0x4e05, 0x9B, 0x18, 0x4C, 0xFE, 0x49, 0x23, 0x50, 0x97 + + + gEfiMiscProducerGuid + 0x62512c92, 0x63c4, 0x4d80, 0x82, 0xb1, 0xc1, 0xa4, 0xdc, 0x44, 0x80, 0xe5 + + + gEfiMiscSubClassGuid + 0x772484B2, 0x7482, 0x4b91, 0x9F, 0x9A, 0xAD, 0x43, 0xF8, 0x1C, 0x58, 0x81 + + + gEfiStatusCodeDataTypeStringGuid + 0x92D11080, 0x496F, 0x4D95, 0xBE, 0x7E, 0x03, 0x74, 0x88, 0x38, 0x2B, 0x0A + + + gEfiStatusCodeSpecificDataGuid + 0x335984bd, 0xe805, 0x409a, 0xb8, 0xf8, 0xd2, 0x7e, 0xce, 0x5f, 0xf7, 0xa6 + + + gEfiStatusCodeDataTypeAssertGuid + 0xDA571595, 0x4D99, 0x487C, 0x82, 0x7C, 0x26, 0x22, 0x67, 0x7D, 0x33, 0x07 + + + gEfiStatusCodeDataTypeExceptionHandlerGuid + 0x3BC2BD12, 0xAD2E, 0x11D5, 0x87, 0xDD, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xB9 + + + gEfiStatusCodeDataTypeDebugGuid + 0x9A4E9246, 0xD553, 0x11D5, 0x87, 0xE2, 0x00, 0x06, 0x29, 0x45, 0xC3, 0xb9 + + + gEfiStatusCodeDataTypeErrorGuid + 0xAB359CE3, 0x99B3, 0xAE18, 0xC8, 0x9D, 0x95, 0xD3, 0xB0, 0x72, 0xE1, 0x9B + + + gEfiStatusCodeDataTypeProgressCodeGuid + 0xA356AB39, 0x35C4, 0x35DA, 0xB3, 0x7A, 0xF8, 0xEA, 0x9E, 0x8B, 0x36, 0xA3 + + + gEfiAuthenticationChapRadiusGuid + 0xd6062b50, 0x15ca, 0x11da, 0x92, 0x19, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d + + + gEfiAuthenticationChapLocalGuid + 0xc280c73e, 0x15ca, 0x11da, 0xb0, 0xca, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d + + + gEfiHashAlgorithmSha1Guid + 0x2ae9d80f, 0x3fb2, 0x4095, 0xb7, 0xb1, 0xe9, 0x31, 0x57, 0xb9, 0x46, 0xb6 + + + gEfiHashAlgorithmSha224Guid + 0x8df01a06, 0x9bd5, 0x4bf7, 0xb0, 0x21, 0xdb, 0x4f, 0xd9, 0xcc, 0xf4, 0x5b + + + gEfiHashAlgorithmSha256Guid + 0x51aa59de, 0xfdf2, 0x4ea3, 0xbc, 0x63, 0x87, 0x5f, 0xb7, 0x84, 0x2e, 0xe9 + + + gEfiHashAlgorithmSha384Guid + 0xefa96432, 0xde33, 0x4dd2, 0xae, 0xe6, 0x32, 0x8c, 0x33, 0xdf, 0x77, 0x7a + + + gEfiHashAlgorithmSha512Guid + 0xcaa4381e, 0x750c, 0x4770, 0xb8, 0x70, 0x7a, 0x23, 0xb4, 0xe4, 0x21, 0x30 + + + gEfiHashAlgorithmMD5Guid + 0xaf7c79c, 0x65b5, 0x4319, 0xb0, 0xae, 0x44, 0xec, 0x48, 0x4e, 0x4a, 0xd7 + + + gBootObjectAuthorizationParmsetGuid + 0xedd35e31, 0x7b9, 0x11d2, 0x83, 0xa3, 0x00, 0xa0, 0xc9, 0x1f, 0xad, 0xcf + + + gEfiAcpiTableStorageGuid + 0x7e374e25, 0x8e01, 0x4fee, 0x87, 0xf2, 0x39, 0x0c, 0x23, 0xc6, 0x06, 0xcd + + + gEfiSmmPeiSmramMemoryReserve + 0x6dadf1d1, 0xd4cc, 0x4910, 0xbb, 0x6e, 0x82, 0xb1, 0xfd, 0x80, 0xff, 0x3d + + + gEfiSmmCpuIoGuid + 0x5f439a0b, 0x45d8, 0x4682, 0xa4, 0xf4, 0xf0, 0x57, 0x6b, 0x51, 0x34, 0x41 + + + gSmmCommunicateHeaderGuid + 0xf328e36c, 0x23b6, 0x4a95, 0x85, 0x4b, 0x32, 0xe1, 0x95, 0x34, 0xcd, 0x75 + + + gEfiCapsuleGuid + 0x3B6686BD, 0x0D76, 0x4030, 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 + + + gEfiConfigFileNameGuid + 0x98B8D59B, 0xE8BA, 0x48EE, 0x98, 0xDD, 0xC2, 0x95, 0x39, 0x2F, 0x1E, 0xDB + + + gEfiEventLegacyBootGuid + 0x2a571201, 0x4966, 0x47f6, 0x8b, 0x86, 0xf3, 0x1e, 0x41, 0xf3, 0x2f, 0x10 + + + gEfiEventExitBootServicesGuid + 0x27abf055, 0xb1b8, 0x4c26, 0x80, 0x48, 0x74, 0x8f, 0x37, 0xba, 0xa2, 0xdf + + + gEfiEventVirtualAddressChangeGuid + 0x13fa7698, 0xc831, 0x49c7, 0x87, 0xea, 0x8f, 0x43, 0xfc, 0xc2, 0x51, 0x96 + + + gEfiEventMemoryMapChangeGuid + 0x78bee926, 0x692f, 0x48fd, 0x9e, 0xdb, 0x01, 0x42, 0x2e, 0xf0, 0xd7, 0xab + + + gEfiEventReadyToBootGuid + 0x7ce88fb3, 0x4bd7, 0x4679, 0x87, 0xa8, 0xa8, 0xd8, 0xde, 0xe5, 0x0d, 0x2b + + + gEfiFrameworkDevicePathGuid + 0xb7084e63, 0x46b7, 0x4d1a, 0x86, 0x77, 0xe3, 0x0b, 0x53, 0xdb, 0xf0, 0x50 + + + + + gEfiBdsArchProtocolGuid + 0x665E3FF6, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D + + + gEfiCpuArchProtocolGuid + 0x26baccb1, 0x6f42, 0x11d4, 0xbc, 0xe7, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiMetronomeArchProtocolGuid + 0x26baccb2, 0x6f42, 0x11d4, 0xbc, 0xe7, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiMonotonicCounterArchProtocolGuid + 0x1da97072, 0xbddc, 0x4b30, 0x99, 0xf1, 0x72, 0xa0, 0xb5, 0x6f, 0xff, 0x2a + + + gEfiRealTimeClockArchProtocolGuid + 0x27CFAC87, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D + + + gEfiResetArchProtocolGuid + 0x27CFAC88, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D + + + gEfiRuntimeArchProtocolGuid + 0x96d08253, 0x8483, 0x11d4, 0xbc, 0xf1, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiSecurityArchProtocolGuid + 0xA46423E3, 0x4617, 0x49f1, 0xB9, 0xFF, 0xD1, 0xBF, 0xA9, 0x11, 0x58, 0x39 + + + gEfiStatusCodeRuntimeProtocolGuid + 0xd2b2b828, 0x826, 0x48a7, 0xb3, 0xdf, 0x98, 0x3c, 0x0, 0x60, 0x24, 0xf0 + + + gEfiTimerArchProtocolGuid + 0x26baccb3, 0x6f42, 0x11d4, 0xbc, 0xe7, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiVariableArchProtocolGuid + 0x1e5668e2, 0x8481, 0x11d4, 0xbc, 0xf1, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiVariableWriteArchProtocolGuid + 0x6441f818, 0x6362, 0x4e44, 0xb5, 0x70, 0x7d, 0xba, 0x31, 0xdd, 0x24, 0x53 + + + gEfiWatchdogTimerArchProtocolGuid + 0x665E3FF5, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D + + + gEfiCpuIoProtocolGuid + 0xB0732526, 0x38C8, 0x4b40, 0x88, 0x77, 0x61, 0xC7, 0xB0, 0x6A, 0xAC, 0x45 + + + gEfiDataHubProtocolGuid + 0xae80d021, 0x618e, 0x11d4, 0xbc, 0xd7, 0x00, 0x80, 0xc7, 0x3c, 0x88, 0x81 + + + gEfiFirmwareVolumeProtocolGuid + 0x389F751F, 0x1838, 0x4388, 0x83, 0x90, 0xCD, 0x81, 0x54, 0xBD, 0x27, 0xF8 + + + gEfiFirmwareVolumeBlockProtocolGuid + 0xDE28BC59, 0x6228, 0x41BD, 0xBD, 0xF6, 0xA3, 0xB9, 0xAD, 0xB5, 0x8D, 0xA1 + + + gEfiFirmwareVolumeDispatchProtocolGuid + 0x7aa35a69, 0x506c, 0x444f, 0xa7, 0xaf, 0x69, 0x4b, 0xf5, 0x6f, 0x71, 0xc8 + + + gEfiFormBrowserProtocolGuid + 0xe5a1333e, 0xe1b4, 0x4d55, 0xce, 0xeb, 0x35, 0xc3, 0xef, 0x13, 0x34, 0x43 + + + gEfiFormCallbackProtocolGuid + 0xf3e4543d, 0xcf35, 0x6cef, 0x35, 0xc4, 0x4f, 0xe6, 0x34, 0x4d, 0xfc, 0x54 + + + gEfiCrc32GuidedSectionExtractionProtocolGuid + 0xFC1BCDB0, 0x7D31, 0x49aa, 0x93, 0x6A, 0xA4, 0x60, 0x0D, 0x9D, 0xD0, 0x83 + + + gEfiHiiProtocolGuid + 0xea816d2c, 0xcee5, 0x4f02, 0x99, 0xb5, 0xd3, 0x90, 0x5c, 0xbb, 0xd0, 0x77 + + + gPcdProtocolGuid + 0x11b34006, 0xd85b, 0x4d0a, 0xa2, 0x90, 0xd5, 0xa5, 0x71, 0x31, 0x0e, 0xf7 + + + gEfiSectionExtractionProtocolGuid + 0x448F5DA4, 0x6DD7, 0x4FE1, 0x93, 0x07, 0x69, 0x22, 0x41, 0x92, 0x21, 0x5D + + + gEfiBisProtocolGuid + 0x0b64aab0, 0x5429, 0x11d4, 0x98, 0x16, 0x00, 0xa0, 0xc9, 0x1f, 0xad, 0xcf + + + gEfiBlockIoProtocolGuid + 0x964e5b21, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + gEfiBusSpecificDriverOverrideProtocolGuid + 0x3bc1b285, 0x8a15, 0x4a82, 0xaa, 0xbf, 0x4d, 0x7d, 0x13, 0xfb, 0x32, 0x65 + + + gEfiComponentNameProtocolGuid + 0x107a772c, 0xd5e1, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiDebugPortProtocolGuid + 0xEBA4E8D2, 0x3858, 0x41EC, 0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 + + + gEfiDebugSupportProtocolGuid + 0x2755590C, 0x6F3C, 0x42FA, 0x9E, 0xA4, 0xA3, 0xBA, 0x54, 0x3C, 0xDA, 0x25 + + + gEfiDecompressProtocolGuid + 0xd8117cfe, 0x94a6, 0x11d4, 0x9a, 0x3a, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiDevicePathProtocolGuid + 0x9576e91, 0x6d3f, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + gEfiDiskIoProtocolGuid + 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + gEfiDriverBindingProtocolGuid + 0x18a031ab, 0xb443, 0x4d1a, 0xa5, 0xc0, 0x0c, 0x09, 0x26, 0x1e, 0x9f, 0x71 + + + gEfiDriverConfigurationProtocolGuid + 0x107a772b, 0xd5e1, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gUefiDriverConfigurationProtocolGuid + 0xbfd7dc1d, 0x24f1, 0x40d9, 0x82, 0xe7, 0x2e, 0x09, 0xbb, 0x6b, 0x4e, 0xbe + + + gEfiDriverDiagnosticsProtocolGuid + 0x0784924f, 0xe296, 0x11d4, 0x9a, 0x49, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gUefiDriverDiagnosticsProtocolGuid + 0x4d330321, 0x025f, 0x4aac, 0x90, 0xd8, 0x5e, 0xd9, 0x00, 0x17, 0x3b, 0x63 + + + gEfiEbcProtocolGuid + 0x13AC6DD1, 0x73D0, 0x11D4, 0xB0, 0x6B, 0x00, 0xAA, 0x00, 0xBD, 0x6D, 0xE7 + + + gEfiNetworkInterfaceIdentifierProtocolGuid + 0xE18541CD, 0xF755, 0x4f73, 0x92, 0x8D, 0x64, 0x3C, 0x8A, 0x79, 0xB2, 0x29 + + + gEfiNetworkInterfaceIdentifierProtocolGuid_31 + 0x1ACED566, 0x76ED, 0x4218, 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 + + + gEfiNetworkInterfaceIdentifierProtocolGuid_31 + 0x1ACED566, 0x76ED, 0x4218, 0xBC, 0x81, 0x76, 0x7F, 0x1F, 0x97, 0x7A, 0x89 + + + gEfiLoadedImageProtocolGuid + 0x5B1B31A1, 0x9562, 0x11d2, 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B + + + gEfiLoadFileProtocolGuid + 0x56EC3091, 0x954C, 0x11d2, 0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B + + + gEfiPciIoProtocolGuid + 0x4cf5b200, 0x68b8, 0x4ca5, 0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x02, 0x9a + + + gEfiPciRootBridgeIoProtocolGuid + 0x2f707ebb, 0x4a1a, 0x11d4, 0x9a, 0x38, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiPlatformDriverOverrideProtocolGuid + 0x6b30c738, 0xa391, 0x11d4, 0x9a, 0x3b, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiPxeBaseCodeProtocolGuid + 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiPxeBaseCodeCallbackProtocolGuid + 0x245dca21, 0xfb7b, 0x11d3, 0x8f, 0x01, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + gEfiScsiPassThruProtocolGuid + 0xa59e8fcf, 0xbda0, 0x43bb, 0x90, 0xb1, 0xd3, 0x73, 0x2e, 0xca, 0xa8, 0x77 + + + gEfiSerialIoProtocolGuid + 0xBB25CF6F, 0xF1D4, 0x11D2, 0x9A, 0x0C, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0xFD + + + gEfiSimpleFileSystemProtocolGuid + 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + gEfiSimpleNetworkProtocolGuid + 0xA19832B9, 0xAC25, 0x11D3, 0x9A, 0x2D, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D + + + gEfiSimplePointerProtocolGuid + 0x31878c87, 0x0b75, 0x11d5, 0x9a, 0x4f, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiSimpleTextInProtocolGuid + 0x387477c1, 0x69c7, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + gEfiSimpleTextOutProtocolGuid + 0x387477c2, 0x69c7, 0x11d2, 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + gEfiUgaDrawProtocolGuid + 0x982c298b, 0xf4fa, 0x41cb, 0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 + + + gEfiUnicodeCollationProtocolGuid + 0x1d85cd7f, 0xf43d, 0x11d2, 0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d + + + gEfiUsbHcProtocolGuid + 0xf5089266, 0x1aa0, 0x4953, 0x97, 0xd8, 0x56, 0x2f, 0x8a, 0x73, 0xb5, 0x19 + + + gEfiPciPlatformProtocolGuid + 0x7d75280, 0x27d4, 0x4d69, 0x90, 0xd0, 0x56, 0x43, 0xe2, 0x38, 0xb3, 0x41 + + + gEfiIncompatiblePciDeviceSupportProtocolGuid + 0xeb23f55a, 0x7863, 0x4ac2, 0x8d, 0x3d, 0x95, 0x65, 0x35, 0xde, 0x03, 0x75 + + + gEfiPciHotPlugInitProtocolGuid + 0xaa0e8bc1, 0xdabc, 0x46b0, 0xa8, 0x44, 0x37, 0xb8, 0x16, 0x9b, 0x2b, 0xea + + + gEfiPciHostBridgeResourceAllocationProtocolGuid + 0xCF8034BE, 0x6768, 0x4d8b, 0xb7, 0x39, 0x7c, 0xce, 0x68, 0x3a, 0x9f, 0xbe + + + gEfiIdeControllerInitProtocolGuid + 0xa1e37052, 0x80d9, 0x4e65, 0xa3, 0x17, 0x3e, 0x9a, 0x55, 0xc4, 0x3e, 0xc9 + + + gEfiUsbIoProtocolGuid + 0x2B2F68D6, 0x0CD2, 0x44cf, 0x8E, 0x8B, 0xBB, 0xA2, 0x0B, 0x1B, 0x5B, 0x75 + + + gEfiArpProtocolGuid + 0xf4b427bb, 0xba21, 0x4f16, 0xbc, 0x4e, 0x43, 0xe4, 0x16, 0xab, 0x61, 0x9c + + + gEfiArpServiceBindingProtocolGuid + 0xf44c00ee, 0x1f2c, 0x4a00, 0xaa, 0x09, 0x1c, 0x9f, 0x3e, 0x08, 0x00, 0xa3 + + + gEfiDhcp4ProtocolGuid + 0x8a219718, 0x4ef5, 0x4761, 0x91, 0xc8, 0xc0, 0xf0, 0x4b, 0xda, 0x9e, 0x56 + + + gEfiDhcp4ServiceBindingProtocolGuid + 0x9d9a39d8, 0xbd42, 0x4a73, 0xa4, 0xd5, 0x8e, 0xe9, 0x4b, 0xe1, 0x13, 0x80 + + + gEfiIp4ProtocolGuid + 0x41d94cd2, 0x35b6, 0x455a, 0x82, 0x58, 0xd4, 0xe5, 0x13, 0x34, 0xaa, 0xdd + + + gEfiIp4ServiceBindingProtocolGuid + 0xc51711e7, 0xb4bf, 0x404a, 0xbf, 0xb8, 0x0a, 0x04, 0x8e, 0xf1, 0xff, 0xe4 + + + gEfiIp4ConfigProtocolGuid + 0x3b95aa31, 0x3793, 0x434b, 0x86, 0x67, 0xc8, 0x07, 0x08, 0x92, 0xe0, 0x5e + + + gEfiManagedNetworkProtocolGuid + 0x3b95aa31, 0x3793, 0x434b, 0x86, 0x67, 0xc8, 0x07, 0x08, 0x92, 0xe0, 0x5e + + + gEfiManagedNetworkServiceBindingProtocolGuid + 0xf36ff770, 0xa7e1, 0x42cf, 0x9e, 0xd2, 0x56, 0xf0, 0xf2, 0x71, 0xf4, 0x4c + + + gEfiMtftp4ProtocolGuid + 0x3ad9df29, 0x4501, 0x478d, 0xb1, 0xf8, 0x7f, 0x7f, 0xe7, 0x0e, 0x50, 0xf3 + + + gEfiMtftp4ServiceBindingProtocolGuid + 0x2FE800BE, 0x8F01, 0x4aa6, 0x94, 0x6B, 0xD7, 0x13, 0x88, 0xE1, 0x83, 0x3F + + + gEfiTcp4ProtocolGuid + 0x65530BC7, 0xA359, 0x410f, 0xB0, 0x10, 0x5A, 0xAD, 0xC7, 0xEC, 0x2B, 0x62 + + + gEfiTcp4ServiceBindingProtocolGuid + 0x00720665, 0x67EB, 0x4a99, 0xBA, 0xF7, 0xD3, 0xC3, 0x3A, 0x1C, 0x7C, 0xC9 + + + gEfiUdp4ProtocolGuid + 0x3ad9df29, 0x4501, 0x478d, 0xb1, 0xf8, 0x7f, 0x7f, 0xe7, 0x0e, 0x50, 0xf3 + + + gEfiUdp4ServiceBindingProtocolGuid + 0x83f01464, 0x99bd, 0x45e5, 0xb3, 0x83, 0xaf, 0x63, 0x05, 0xd8, 0xe9, 0xe6 + + + gEfiAuthenticationInfoProtocolGuid + 0x7671d9d0, 0x53db, 0x4173, 0xaa, 0x69, 0x23, 0x27, 0xf2, 0x1f, 0x0b, 0xc7 + + + gEfiDevicePathFromTextProtocolGuid + 0x5c99a21, 0xc70f, 0x4ad2, 0x8a, 0x5f, 0x35, 0xdf, 0x33, 0x43, 0xf5, 0x1e + + + gEfiDevicePathToTextProtocolGuid + 0x8b843e20, 0x8132, 0x4852, 0x90, 0xcc, 0x55, 0x1a, 0x4e, 0x4a, 0x7f, 0x1c + + + gEfiDevicePathUtilitiesProtocolGuid + 0x379be4e, 0xd706, 0x437d, 0xb0, 0x37, 0xed, 0xb8, 0x2f, 0xb7, 0x72, 0xa4 + + + gEfiEdidActiveProtocolGuid + 0xbd8c1056, 0x9f36, 0x44ec, 0x92, 0xa8, 0xa6, 0x33, 0x7f, 0x81, 0x79, 0x86 + + + gEfiEdidDiscoveredProtocolGuid + 0x1c0c34f6, 0xd380, 0x41fa, 0xa0, 0x49, 0x8a, 0xd0, 0x6c, 0x1a, 0x66, 0xaa + + + gEfiEdidOverrideProtocolGuid + 0x48ecb431, 0xfb72, 0x45c0, 0xa9, 0x22, 0xf4, 0x58, 0xfe, 0x04, 0x0b, 0xd5 + + + gEfiGraphicsOutputProtocolGuid + 0x9042a9de, 0x23dc, 0x4a38, 0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a + + + gEfiHashProtocolGuid + 0xc5184932, 0xdba5, 0x46db, 0xa5, 0xba, 0xcc, 0x0b, 0xda, 0x9c, 0x14, 0x35 + + + gEfiHashServiceBindingProtocolGuid + 0x42881c98, 0xa4f3, 0x44b0, 0xa3, 0x9d, 0xdf, 0xa1, 0x86, 0x67, 0xd8, 0xcd + + + gEfiIScsiInitiatorNameProtocolGuid + 0xa6a72875, 0x2962, 0x4c18, 0x9f, 0x46, 0x8d, 0xa6, 0x44, 0xcc, 0xfe, 0x00 + + + gEfiScsiIoProtocolGuid + 0x932f4736, 0x2362, 0x4002, 0x80, 0x3e, 0x3c, 0xd5, 0x4b, 0x13, 0x8f, 0x85 + + + gEfiExtScsiPassThruProtocolGuid + 0x1d3de7f0, 0x0807, 0x424f, 0xaa, 0x69, 0x11, 0xa5, 0x4e, 0x19, 0xa4, 0x6f + + + gEfiTapeIoProtocolGuid + 0x1e93e633, 0xd65a, 0x459e, 0xab, 0x84, 0x93, 0xd9, 0xec, 0x26, 0x6d, 0x18 + + + gEfiUsb2HcProtocolGuid + 0x3e745226, 0x9818, 0x45b6, 0xa2, 0xac, 0xd7, 0xcd, 0x0e, 0x8b, 0xa2, 0xbc + + + gEfiSecurityPolicyProtocolGuid + 0x78E4D245, 0xCD4D, 0x4a05, 0xA2, 0xBA, 0x47, 0x43, 0xE8, 0x6C, 0xFC, 0xAB + + + gEfiAcpiSupportGuid + 0xdbff9d55, 0x89b7, 0x46da, 0xbd, 0xdf, 0x67, 0x7d, 0x3d, 0xc0, 0x24, 0x1d + + + gEfiBootScriptSaveGuid + 0x470e1529, 0xb79e, 0x4e32, 0xa0, 0xfe, 0x6a, 0x15, 0x6d, 0x29, 0xf9, 0xb2 + + + gEfiSmbusProtocolGuid + 0xe49d33ed, 0x513d, 0x4634, 0xb6, 0x98, 0x6f, 0x55, 0xaa, 0x75, 0x1c, 0x1b + + + gEfiLegacyBiosProtocolGuid + 0xdb9a1e3d, 0x45cb, 0x4abb, 0x85, 0x3b, 0xe5, 0x38, 0x7f, 0xdb, 0x2e, 0x2d + + + gEfiLegacy8259ProtocolGuid + 0x38321dba, 0x4fe0, 0x4e17, 0x8a, 0xec, 0x41, 0x30, 0x55, 0xea, 0xed, 0xc1 + + + gEfiLegacyBiosPlatformProtocolGuid + 0x783658a3, 0x4172, 0x4421, 0xa2, 0x99, 0xe0, 0x09, 0x07, 0x9c, 0x0c, 0xb4 + + + gEfiLegacyInterruptProtocolGuid + 0x31ce593d, 0x108a, 0x485d, 0xad, 0xb2, 0x78, 0xf2, 0x1f, 0x29, 0x66, 0xbe + + + gEfiLegacyRegionProtocolGuid + 0xfc9013a, 0x0568, 0x4ba9, 0x9b, 0x7e, 0xc9, 0xc3, 0x90, 0xa6, 0x60, 0x9b + + + gEfiSmmAccessProtocolGuid + 0x3792095a, 0xe309, 0x4c1e, 0xaa, 0x01, 0x85, 0xf5, 0x65, 0x5a, 0x17, 0xf1 + + + gEfiSmmBaseProtocolGuid + 0x1390954D, 0xda95, 0x4227, 0x93, 0x28, 0x72, 0x82, 0xc2, 0x17, 0xda, 0xa8 + + + gEfiSmmControlProtocolGuid + 0x8d12e231, 0xc667, 0x4fd1, 0x98, 0xf2, 0x24, 0x49, 0xa7, 0xe7, 0xb2, 0xe5 + + + gEfiSmmGpiDispatchProtocolGuid + 0xe0744b81, 0x9513, 0x49cd, 0x8c, 0xea, 0xe9, 0x24, 0x5e, 0x70, 0x39, 0xda + + + gEfiSmmIchnDispatchProtocolGuid + 0xc50b323e, 0x9075, 0x4f2a, 0xac, 0x8e, 0xd2, 0x59, 0x6a, 0x10, 0x85, 0xcc + + + gEfiSmmPeriodicTimerDispatchProtocolGuid + 0x9cca03fc, 0x4c9e, 0x4a19, 0x9b, 0x06, 0xed, 0x7b, 0x47, 0x9b, 0xde, 0x55 + + + gEfiSmmPowerButtonDispatchProtocolGuid + 0xb709efa0, 0x47a6, 0x4b41, 0xb9, 0x31, 0x12, 0xec, 0xe7, 0xa8, 0xee, 0x56 + + + gEfiSmmStandbyButtonDispatchProtocolGuid + 0x78965b98, 0xb0bf, 0x449e, 0x8b, 0x22, 0xd2, 0x91, 0x4e, 0x49, 0x8a, 0x98 + + + gEfiSmmStatusCodeProtocolGuid + 0x6afd2b77, 0x98c1, 0x4acd, 0xa6, 0xf9, 0x8a, 0x94, 0x39, 0xde, 0x0f, 0xb1 + + + gEfiSmmSwDispatchProtocolGuid + 0xe541b773, 0xdd11, 0x420c, 0xb0, 0x26, 0xdf, 0x99, 0x36, 0x53, 0xf8, 0xbf + + + gEfiSmmSxDispatchProtocolGuid + 0x14fc52be, 0x01dc, 0x426c, 0x91, 0xae, 0xa2, 0x3c, 0x3e, 0x22, 0x0a, 0xe8 + + + gEfiSmmUsbDispatchProtocolGuid + 0xa05b6ffd, 0x87af, 0x4e42, 0x95, 0xc9, 0x62, 0x28, 0xb6, 0x3c, 0xf3, 0xf3 + + + gEfiDeviceIoProtocolGuid + 0xaf6ac311, 0x84c3, 0x11d2, 0x8e, 0x3c, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b + + + + + gEfiPeiBootInRecoveryModePpiGuid + 0x17ee496a, 0xd8e4, 0x4b9a, 0x94, 0xd1, 0xce, 0x82, 0x72, 0x30, 0x08, 0x50 + + + gEfiPeiCpuIoPpiInServiceTableGuid + 0xe6af1f7b, 0xfc3f, 0x46da, 0xa8, 0x28, 0xa3, 0xb4, 0x57, 0xa4, 0x42, 0x82 + + + gEfiDxeIplPpiGuid + 0xae8ce5d, 0xe448, 0x4437, 0xa8, 0xd7, 0xeb, 0xf5, 0xf1, 0x94, 0xf7, 0x31 + + + gEfiEndOfPeiSignalPpiGuid + 0x605EA650, 0xC65C, 0x42e1, 0xBA, 0x80, 0x91, 0xA5, 0x2A, 0xB6, 0x18, 0xC6 + + + gEfiFindFvPpiGuid + 0x36164812, 0xa023, 0x44e5, 0xbd, 0x85, 0x05, 0xbf, 0x3c, 0x77, 0x00, 0xaa + + + gEfiPeiFvFileLoaderPpiGuid + 0x7e1f0d85, 0x04ff, 0x4bb2, 0x86, 0x6a, 0x31, 0xa2, 0x99, 0x6a, 0x48, 0xa8 + + + gEfiPeiMasterBootModePpiGuid + 0x7408d748, 0xfc8c, 0x4ee6, 0x92, 0x88, 0xc4, 0xbe, 0xc0, 0x92, 0xa4, 0x10 + + + gEfiPeiMemoryDiscoveredPpiGuid + 0xf894643d, 0xc449, 0x42d1, 0x8e, 0xa8, 0x85, 0xbd, 0xd8, 0xc6, 0x5b, 0xde + + + gEfiPciCfgPpiInServiceTableGuid + 0xe1f2eba0, 0xf7b9, 0x4a26, 0x86, 0x20, 0x13, 0x12, 0x21, 0x64, 0x2a, 0x90 + + + gEfiPeiReadOnlyVariablePpiGuid + 0x3cdc90c6, 0x13fb, 0x4a75, 0x9e, 0x79, 0x59, 0xe9, 0xdd, 0x78, 0xb9, 0xfa + + + gEfiPeiRecoveryModulePpiGuid + 0xFB6D9542, 0x612D, 0x4f45, 0x87, 0x2F, 0x5C, 0xFF, 0x52, 0xE9, 0x3D, 0xCF + + + gEfiPeiResetPpiGuid + 0xef398d58, 0x9dfd, 0x4103, 0xbf, 0x94, 0x78, 0xc6, 0xf4, 0xfe, 0x71, 0x2f + + + gEfiPeiS3ResumePpiGuid + 0x4426CCB2, 0xE684, 0x4a8a, 0xAE, 0x40, 0x20, 0xD4, 0xB0, 0x25, 0xB7, 0x10 + + + gEfiSecPlatformInformationPpiGuid + 0x6f8c2b35, 0xfef4, 0x448d, 0x82, 0x56, 0xe1, 0x1b, 0x19, 0xd6, 0x10, 0x77 + + + gEfiPeiSectionExtractionPpiGuid + 0x4F89E208, 0xE144, 0x4804, 0x9E, 0xC8, 0x0F, 0x89, 0x4F, 0x7E, 0x36, 0xD7 + + + gEfiPeiSecurityPpiGuid + 0x1388066e, 0x3a57, 0x4efa, 0x98, 0xf3, 0xc1, 0x2f, 0x3a, 0x95, 0x8a, 0x29 + + + gEfiPeiStatusCodePpiGuid + 0x229832d3, 0x7a30, 0x4b36, 0xb8, 0x27, 0xf4, 0x0c, 0xb7, 0xd4, 0x54, 0x36 + + + gPcdPpiGuid + 0x5d5c0e21, 0x749c, 0x4063, 0x81, 0xaf, 0xbc, 0x74, 0xfc, 0x79, 0xab, 0x5c + + + gEfiPeiBootScriptExecuterPpiGuid + 0xabd42895, 0x78cf, 0x4872, 0x84, 0x44, 0x1b, 0x5c, 0x18, 0x0b, 0xfb, 0xff + + + gEfiPeiSmbusPpiGuid + 0xabd42895, 0x78cf, 0x4872, 0x84, 0x44, 0x1b, 0x5c, 0x18, 0x0b, 0xfb, 0xda + + + gEfiPeiBlockIoPpiGuid + 0x695d8aa1, 0x42ee, 0x4c46, 0x80, 0x5c, 0x6e, 0xa6, 0xbc, 0xe7, 0x99, 0xe3 + + + gEfiPeiDeviceRecoveryModulePpiGuid + 0x0DE2CE25, 0x446A, 0x45a7, 0xBF, 0xC9, 0x37, 0xDA, 0x26, 0x34, 0x4B, 0x37 + + + gEfiPeiStallPpiGuid + 0x1f4c6f90, 0xb06b, 0x48d8, 0xa2, 0x01, 0xba, 0xe5, 0xf1, 0xcd, 0x7d, 0x56 + + + + + PcdMaximumUnicodeStringLength + 0x00000001 + UINT32 + 1000000 + + + PcdMaximumAsciiStringLength + 0x00000002 + UINT32 + 1000000 + + + PcdMaximumLinkedListLength + 0x00000003 + UINT32 + 1000000 + + + PcdSpinLockTimeout + 0x00000004 + UINT32 + 10000000 + + + PcdDebugPropertyMask + 0x00000005 + UINT8 + 0 + + + PcdDebugPrintErrorLevel + 0x00000006 + UINT32 + 0x80000000 + + + PcdReportStatusCodePropertyMask + 0x00000007 + UINT8 + 0 + + + PcdDebugClearMemoryValue + 0x00000008 + UINT8 + 0xAF + + + PcdPerformanceLibraryPropertyMask + 0x00000009 + UINT8 + 0x0 + + + diff --git a/MdePkg/build.xml b/MdePkg/build.xml new file mode 100644 index 0000000000..7d78671589 --- /dev/null +++ b/MdePkg/build.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MdePkg/genbuildfile.xml b/MdePkg/genbuildfile.xml new file mode 100644 index 0000000000..77702ef12d --- /dev/null +++ b/MdePkg/genbuildfile.xml @@ -0,0 +1,19 @@ + + + + + + + + + + diff --git a/Start Create Setup Package.bat b/Start Create Setup Package.bat new file mode 100644 index 0000000000..3ab70df6bf --- /dev/null +++ b/Start Create Setup Package.bat @@ -0,0 +1,40 @@ +@REM set following environment in this file or in command shell +@REM set JAVA_HOME="C:\Program Files\Java\jdk1.5.0_04" +@REM set WORKSPACE=C:\MyWorkspace + + +@REM ############################################################## +@REM # You should not have to modify anything below this line +@REM # + +@echo off + +:check_java +if "%JAVA_HOME%"=="" goto no_jdk +:check_wks +if "%WORKSPACE%"=="" goto no_wks + +set ANT_HOME=%WORKSPACE%\Tools\bin\apache-ant +set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%WORKSPACE%\Tools\bin;%XMLBEANS_HOME%\bin;%PATH% + +call "ant" -f %WORKSPACE%\Tools\Source\Setup\build.xml + +echo DONE + +goto end + +:no_jdk +echo. +echo !!! Please set JAVA_HOME !!! +echo. +goto check_wks + +:no_wks +echo. +echo !!! Please set WORKSPACE !!! +echo. +goto end + +:end +@echo on + diff --git a/Tools/Conf/BuildMacro.xml b/Tools/Conf/BuildMacro.xml new file mode 100644 index 0000000000..782b2714d3 --- /dev/null +++ b/Tools/Conf/BuildMacro.xml @@ -0,0 +1,1115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Conf/Common.xml b/Tools/Conf/Common.xml new file mode 100644 index 0000000000..9bf62ca756 --- /dev/null +++ b/Tools/Conf/Common.xml @@ -0,0 +1,133 @@ + + + + + + + + +
+
+
+ + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + +
+ +
+
+
+ + + + + + + + +
+
+
+ + + + + + + +
+
+ + + + + + + +
+
+
+ + + + + + + + + + +
+
+
+
+ + + + + + + + +
+
+
+
+ + + + + + + +
+
+
+
+ + + + + + + + +
+ + + + + diff --git a/Tools/Conf/FrameworkDatabase.db b/Tools/Conf/FrameworkDatabase.db new file mode 100644 index 0000000000..2c95111493 --- /dev/null +++ b/Tools/Conf/FrameworkDatabase.db @@ -0,0 +1,65 @@ + + + + FrameworkDatabase + 5ce32c23-6448-43ab-b509-a9deae3aae65 + 0.3 + 2006-03-04 22:14 + 2006-03-06 16:56 + The Framework Module Development Packaging System Database + This Database tracks the Basename, Version, Guid and Path for all packages installed in this workspace. + Copyright (c) 2006, 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. + + + + + EdkFatBinPkg + 0fd7197b-9bde-44fe-a7e4-d2177a9922e5 + 0.3 + EdkFatBinPkg/ + 2006-03-05 09:49 + + + EdkModulePkg + 0xb6ec423c, 0x21d2, 0x490d, 0x85, 0xc6, 0xdd, 0x58, 0x64, 0xea, 0xa6, 0x74 + 0.3 + EdkModulePkg/ + 2006-02-21 17:43 + + + EdkNt32Pkg + 146fab65-922d-4bc3-b34b-cf1b0fe16eed + 0.01-test1 + EdkNt32Pkg/ + 2006-02-22 13:25 + + + EdkShellBinPkg + d4266a1b-1d38-4116-93ae-60dc3e2012a6 + 0.3 + EdkShellBinPkg/ + 2006-03-05 10:13 + + + MdePkg + 18413569-8b0d-43b1-920f-c110aa37265d + 0.3 + MdePkg/ + 2006-03-05 09:01 + + + Tools + 53f84ca0-53fe-4412-b4e7-dcec602e1d49 + 0.1 + Tools/ + 2006-02-24 14:49 + + + diff --git a/Tools/Conf/debug_efi_flags.txt b/Tools/Conf/debug_efi_flags.txt new file mode 100644 index 0000000000..0a5e6373e9 --- /dev/null +++ b/Tools/Conf/debug_efi_flags.txt @@ -0,0 +1,4 @@ +WORKSPACE_TARGET = DEBUG +EFI_LOCK_STATUS = FALSE +EFI_S3_RESUME = YES +EFI_LOG_LEVEL = 3 diff --git a/Tools/Conf/efi_flags_table.txt b/Tools/Conf/efi_flags_table.txt new file mode 100644 index 0000000000..6dfc4fa75f --- /dev/null +++ b/Tools/Conf/efi_flags_table.txt @@ -0,0 +1,26 @@ +# +# TABLE COLUMES: FLAGS_NAME, FLAGS_SETTING, VENDOR_ARCH_COMMANDTYPE ADD and SUB +# Here, Vendor is defined in tools_def.txt, for example: MSFT, WINDDK, INTEL, GCC, CYGWIN +# ARCH is IA32, IPF, x64, EBC and so on +# COMMANDTYPE is one of CC, LIB, LINK, ASM, ASMLINK, PP, ASL +# + +# EFI_DEBUG +EFI_DEBUG YES MSFT_IA32_ASM ADD.["/Zi", "/DEBUG"] +EFI_DEBUG YES MSFT_IA32_CC ADD.["/Zi", "/Gm", "/D EFI_DEBUG"] SUB.["/nologo", "/WX"] +EFI_DEBUG YES MSFT_IA32_LINK ADD.["/DEBUG"] +EFI_DEBUG YES MSFT_NT32_CC ADD.["/DEBUG"] + +EFI_DEBUG YES INTEL_EBC_CC ADD.["/Zd", "/Zi"] +EFI_DEBUG YES INTEL_EBC_LINK ADD.["/DEBUG"] + +EFI_DEBUG YES WINDDK_X64_ASM ADD.["/Zi", "/DDEBUG"] +EFI_DEBUG YES WINDDK_X64_CC ADD.["/Zi", "/Gm", "/D EFI_DEBUG"] +EFI_DEBUG YES WINDDK_X64_LINK ADD.["/DEBUG"] + +EFI_DEBUG YES WINDDK_IPF_ASM ADD.["-d debug"] +EFI_DEBUG YES WINDDK_IPF_CC ADD.["/Zi", "/Gm"] +EFI_DEBUG YES WINDDK_IPF_LINK ADD.["/DEBUG"] + + +# EFI_DEBUG_CLEAR_MEMORY diff --git a/Tools/Conf/gcc_tools.txt b/Tools/Conf/gcc_tools.txt new file mode 100644 index 0000000000..04dab63500 --- /dev/null +++ b/Tools/Conf/gcc_tools.txt @@ -0,0 +1,7 @@ +IA32_CC = "-Os","-fno-strict-aliasing","-Wall", "-Werror", "-c", "-x c" +IA32_LIB = +IA32_LINK = "-nostdlib", "-O2", "--gc-sections", "--dll", "--export-all-symbols" +IA32_ASM = "/nologo", "/W3", "/WX", "/c", "/coff", "/DEFI32" +IA32_ASMLINK = +IA32_PP = "-E" + diff --git a/Tools/Conf/gcc_tools_def.txt b/Tools/Conf/gcc_tools_def.txt new file mode 100644 index 0000000000..0cd372f8eb --- /dev/null +++ b/Tools/Conf/gcc_tools_def.txt @@ -0,0 +1,55 @@ +#Host definitions +HOST_VENDOR = INTEL +PATH_TO_HOST_CC = c:\cygwin\bin + +#Default values +CC_NAME = gcc.exe +LIB_NAME = ar.exe +LINK_NAME = ld.exe +ASM_NAME = ml.exe +ASMLINK_NAME = link.exe +ASL_NAME = iasl.exe +PP_NAME=gcc.exe + +#define for IA32 +IA32_VENDOR = GCC +IA32_CC_VENDOR = GCC +IA32_ASL_VENDOR = GCC +IA32_ASM_VENDOR = MSFT +IA32_PATH = C:\cygwin\opt\tiano\i386-tiano-pe\i386-tiano-pe\bin +IA32_ASM_PATH = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin +#IA32_ASMLINK_PATH = C:\MASM611\BINR +IA32_ASL_PATH = C:\TianoTools\Bin + +#define for x64 +x64_VENDOR = WINDDK +x64_CC_VENDOR = WINDDK +x64_ASM_VENDOR = WINDDK +x64_CC_NAME = cl.exe +x64_LIB_NAME = lib.exe +x64_LINK_NAME = link.exe +x64_PP_NAME = cl.exe +x64_ASL_VENDOR = INTEL +x64_PATH = c:\WINDDK\3790.1830\bin\win64\x86\amd64 +x64_ASL_PATH = C:\TianoTools\Bin +X64_ASM_NAME = ml64.exe + +#define for IPF +IPF_CC_NAME = cl.exe +IPF_LIB_NAME = lib.exe +IPF_LINK_NAME = link.exe +IPF_PP_NAME = cl.exe +IPF_VENDOR = WINDDK +IPF_ASL_VENDOR = INTEL +IPF_PATH = c:\WINDDK\3790.1830\bin\win64\x86 +IPF_ASL_PATH = C:\TianoTools\Bin +IPF_ASM_NAME = ias.exe + +#define for EBC +EBC_VENDOR = INTEL +EBC_ASL_VENDOR = INTEL +EBC_PATH = C:\Program Files\Intel\EBC\Bin +EBC_ASL_PATH = C:\TianoTools\Bin +EBC_CC_NAME = iec.exe +EBC_LIB_NAME = link.exe +EBC_LINK_NAME = link.exe diff --git a/Tools/Conf/global_efi_flags.txt b/Tools/Conf/global_efi_flags.txt new file mode 100644 index 0000000000..1c1df04f50 --- /dev/null +++ b/Tools/Conf/global_efi_flags.txt @@ -0,0 +1,35 @@ +EFI_GENERATE_SYM_FILE = NO +EFI_DEBUG = NO +EFI_DEBUG_CLEAR_MEMORY = NO +EFI_PEI_PERFORMANCE = YES +EFI_DXE_PERFORMANCE = YES +EFI_SYMBOLIC_DEBUG = NO +EFI_USE_NEW_SHELL_BIN = NO +EFI_GENERATE_INTERMEDIATE_FILE = NO + +EFI_READ_DISABLED_CAP = TRUE +EFI_READ_ENABLED_CAP = TRUE +EFI_READ_STATUS = TRUE +EFI_WRITE_DISABLED_CAP = TRUE +EFI_WRITE_ENABLED_CAP = TRUE +EFI_WRITE_STATUS = TRUE +EFI_LOCK_CAP = TRUE +EFI_STICKY_WRITE = TRUE +EFI_MEMORY_MAPPED = TRUE +EFI_ALIGNMENT_CAP = TRUE +EFI_ALIGNMENT_2 = TRUE +EFI_ALIGNMENT_4 = TRUE +EFI_ALIGNMENT_8 = TRUE +EFI_ALIGNMENT_16 = TRUE +EFI_ALIGNMENT_32 = TRUE +EFI_ALIGNMENT_64 = TRUE +EFI_ALIGNMENT_128 = TRUE +EFI_ALIGNMENT_256 = TRUE +EFI_ALIGNMENT_512 = TRUE +EFI_ALIGNMENT_1K = TRUE +EFI_ALIGNMENT_2K = TRUE +EFI_ALIGNMENT_4K = TRUE +EFI_ALIGNMENT_8K = TRUE +EFI_ALIGNMENT_16K = TRUE +EFI_ALIGNMENT_32K = TRUE +EFI_ALIGNMENT_64K = TRUE \ No newline at end of file diff --git a/Tools/Conf/intel_tools.txt b/Tools/Conf/intel_tools.txt new file mode 100644 index 0000000000..d4482468fa --- /dev/null +++ b/Tools/Conf/intel_tools.txt @@ -0,0 +1,19 @@ +ASL = -vo + +IA32_CC = +IA32_LIB = +IA32_LINK = + +X64_CC = +X64_LIB = +X64_LINK = + +IPF_CC = +IPF_LIB = +IPF_LINK = +IPF_ASM = "-N us", "-X explicit", "-M ilp64", "-N so", "-W4" + +EBC_CC = "-nologo", "-FAcs", "-c", "-W3", "-WX" +EBC_LIB = "/lib", "/NOLOGO", "/MACHINE:EBC" +EBC_LINK = "/NOLOGO", "/MACHINE:EBC", "/SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER", "/OPT:REF", "/NODEFAULTLIB" +EBC_PP = "/P" \ No newline at end of file diff --git a/Tools/Conf/msft_tools.txt b/Tools/Conf/msft_tools.txt new file mode 100644 index 0000000000..cc0cf081b0 --- /dev/null +++ b/Tools/Conf/msft_tools.txt @@ -0,0 +1,8 @@ +ASL = "/nologo" + +IA32_CC = "/nologo", "/W3", "/WX", "/GX", "/Gy", "/Gs-", "/c", "/D EFI32", "/D UNICODE" +IA32_LIB = "/NOLOGO" +IA32_LINK = "/NOLOGO", "/SUBSYSTEM:CONSOLE", "/NODEFAULTLIB", "/IGNORE:4086", "/MAP", "/OPT:REF", "/MACHINE:I386", "/ALIGN:32", "/DLL", "/LTCG" +IA32_ASM = "/nologo", "/W3", "/WX", "/c", "/coff", "/DEFI32" +IA32_ASMLINK = +IA32_PP = "/P" diff --git a/Tools/Conf/msft_tools_def.txt b/Tools/Conf/msft_tools_def.txt new file mode 100644 index 0000000000..71c7da17e4 --- /dev/null +++ b/Tools/Conf/msft_tools_def.txt @@ -0,0 +1,43 @@ +#WORKSPACE = C:\MyWork\Edk2.0 +#Host definitions +HOST_VENDOR = INTEL +PATH_TO_HOST_CC = C:\Program Files\Intel\Compiler\c++\9.0\IA32\Bin + +#Default values +CC_NAME = cl.exe +LIB_NAME = lib.exe +LINK_NAME = link.exe +ASM_NAME = ml.exe +ASMLINK_NAME = link.exe +ASL_NAME = iasl.exe +PP_NAME=cl.exe + +#define for IA32 +IA32_VENDOR = MSFT +IA32_ASL_VENDOR = INTEL +IA32_PATH = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin +#IA32_ASM_PATH = C:\MASM611\BIN +IA32_ASMLINK_PATH = C:\MASM611\BINR +IA32_ASL_PATH = C:\TianoTools\Bin + +#define for x64 +x64_VENDOR = WINDDK +x64_ASL_VENDOR = INTEL +x64_PATH = c:\WINDDK\3790.1830\bin\win64\x86\amd64 +x64_ASL_PATH = C:\TianoTools\Bin +X64_ASM_NAME = ml64.exe + +#define for IPF +IPF_VENDOR = WINDDK +IPF_ASL_VENDOR = INTEL +IPF_PATH = c:\WINDDK\3790.1830\bin\win64\x86 +IPF_ASL_PATH = C:\TianoTools\Bin +IPF_ASM_NAME = ias.exe + +#define for EBC +EBC_VENDOR = INTEL +EBC_ASL_VENDOR = INTEL +EBC_PATH = C:\Program Files\Intel\EBC\Bin +EBC_ASL_PATH = C:\TianoTools\Bin +EBC_CC_NAME = iec.exe +EBC_LIB_NAME = link.exe diff --git a/Tools/Conf/my_efi_flags.txt b/Tools/Conf/my_efi_flags.txt new file mode 100644 index 0000000000..f033429f4b --- /dev/null +++ b/Tools/Conf/my_efi_flags.txt @@ -0,0 +1,2 @@ +EFI_DEBUG = NO +EFI_DEBUG_CLEAR_MEMORY = NO \ No newline at end of file diff --git a/Tools/Conf/release_efi_flags.txt b/Tools/Conf/release_efi_flags.txt new file mode 100644 index 0000000000..0a5e6373e9 --- /dev/null +++ b/Tools/Conf/release_efi_flags.txt @@ -0,0 +1,4 @@ +WORKSPACE_TARGET = DEBUG +EFI_LOCK_STATUS = FALSE +EFI_S3_RESUME = YES +EFI_LOG_LEVEL = 3 diff --git a/Tools/Conf/target.txt b/Tools/Conf/target.txt new file mode 100644 index 0000000000..571d517e82 --- /dev/null +++ b/Tools/Conf/target.txt @@ -0,0 +1,2 @@ +WORKSPACE_TARGET = DEBUG +TARGET_ARCH = IA32, x64, IPF, EBC diff --git a/Tools/Conf/tools_def.txt b/Tools/Conf/tools_def.txt new file mode 100644 index 0000000000..89c76e8380 --- /dev/null +++ b/Tools/Conf/tools_def.txt @@ -0,0 +1,44 @@ +WORKSPACE = C:\MDE +#Host definitions +HOST_VENDOR = INTEL +PATH_TO_HOST_CC = C:\Program Files\Intel\Compiler\c++\9.0\IA32\Bin + +#Default values +CC_NAME = cl.exe +LIB_NAME = lib.exe +LINK_NAME = link.exe +ASM_NAME = ml.exe +ASMLINK_NAME = link.exe +ASL_NAME = iasl.exe +PP_NAME=cl.exe + +#define for IA32 +IA32_VENDOR = MSFT +IA32_ASL_VENDOR = INTEL +#IA32_PATH = C:\Program Files\Microsoft Visual Studio .NET 2003\Vc7\bin +#IA32_ASM_PATH = C:\MASM611\BIN +IA32_ASMLINK_PATH = C:\MASM611\BINR +IA32_ASL_PATH = C:\TianoTools\Bin + +#define for x64 +x64_VENDOR = WINDDK +x64_ASL_VENDOR = INTEL +x64_PATH = C:\WINDDK\3790.1830\bin\win64\x86\amd64 +x64_ASL_PATH = C:\TianoTools\Bin +X64_ASM_NAME = ml64.exe + +#define for IPF +IPF_VENDOR = WINDDK +IPF_ASL_VENDOR = INTEL +IPF_PATH = C:\WINDDK\3790.1830\bin\win64\x86 +IPF_ASL_PATH = C:\TianoTools\Bin +IPF_ASM_NAME = ias.exe + +#define for EBC +EBC_VENDOR = INTEL +EBC_ASL_VENDOR = INTEL +EBC_PATH = C:\Program Files\Intel\Ebc\Bin +EBC_ASL_PATH = C:\TianoTools\Bin +EBC_CC_NAME = iec.exe +#EBC_LIB_PATH = +EBC_LIB_NAME = link.exe diff --git a/Tools/Conf/winddk_tools.txt b/Tools/Conf/winddk_tools.txt new file mode 100644 index 0000000000..062d974eaa --- /dev/null +++ b/Tools/Conf/winddk_tools.txt @@ -0,0 +1,19 @@ +IA32_CC = "/nologo", "/X", "/W4", "/WX", "/GX", "/Gy", "/GS-", "/c", "/D EFI32" +IA32_LIB = "/NOLOGO" +IA32_LINK = "/NOLOGO", "/SUBSYSTEM:CONSOLE", "/NODEFAULTLIB", "/IGNORE:4086", "/MAP", "/OPT:REF", "/MACHINE:I386", "/ALIGN:32", "/DLL" +IA32_ASM = "/nologo", "/W3", "/WX", "/c", "/coff", "/DEFI32" +IA32_PP = "/P" + +x64_CC = "/nologo", "/X", "/W4", "/WX", "/Gy", "/c", "/Gs8192", "/GS-", "/D EFIx64" +x64_LIB = "/NOLOGO" +x64_LINK = "/NOLOGO", "/Machine:AMD64", "/ALIGN:32", "/DLL", "/NODEFAULTLIB", "/OPT:REF" +x64_ASM = "/nologo", "/W3", "/WX", "/c", "/DEFI32" +x64_ASMLINK = +x64_PP = "/P" + +IPF_CC = "/nologo", "/W4", "/WX", "/EHsc", "/Gy", "/c", "/GS-", "/D EFI64" +IPF_PP = "/nologo", "/W4", "/WX", "/EHsc", "/Gy", "/c", "/GS-", "-P", "-C", "/D EFI_MONOSHELL", "/D EFI64" +IPF_LIB = "/NOLOGO" +IPF_LINK = "/NOLOGO", "/SUBSYSTEM:CONSOLE", "/NODEFAULTLIB", "/IGNORE:4086", "/MAP", "/OPT:REF", "/MACHINE:IA64" +IPF_ASM = "-N us", "-X explicit", "-M ilp64", "-N so", "-W4" +IPF_PP = "/P" diff --git a/Tools/JavaResources.msa b/Tools/JavaResources.msa new file mode 100644 index 0000000000..283dc96cfd --- /dev/null +++ b/Tools/JavaResources.msa @@ -0,0 +1,71 @@ + + + + + JavaResources + BASE + CUSTOM_BUILD + faf22a0f-10fc-428e-b311-fe506a9c0b2d + 2.0 + This is the EFI/Tiano Tool Resources Module + + This Module provides the EFI/Tiano Tools and resources that are used to create EFI/Tiano + Modules and Platform Binary Files (PBF) + These resources and tools do not require compilation. (The three JAR files are provided, + Pre-compiled, and do not require additional compilation, the sources are provided, but + will not be built under normal procedures. + + Copyright 2005-2006, 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. + + 2006-03-23 12:00 + + + Java + Perl + + + inf2msa.pl + mkspd.pl + mkdb.pl + FrameworkDatabase.db + cygwin_tools.txt + desktop_efi_flags.txt + embedded_efi_flags.txt + gcc_tools.txt + global_efi_flags.txt + intel_tools.txt + mobile_efi_flags.txt + msft_tools.txt + my_efi_flags.txt + node.txt + server_efi_flags.txt + target.txt + tools_def.txt + winddk_tools.txt + cpptasks.jar + frameworktasks.jar + GenBuild.jar + + + Base + + + + + diff --git a/Tools/Source/Cpptasks/build.xml b/Tools/Source/Cpptasks/build.xml new file mode 100644 index 0000000000..cfed13b7b3 --- /dev/null +++ b/Tools/Source/Cpptasks/build.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/Cpptasks/cpptasks.mf b/Tools/Source/Cpptasks/cpptasks.mf new file mode 100644 index 0000000000..a2bf638932 --- /dev/null +++ b/Tools/Source/Cpptasks/cpptasks.mf @@ -0,0 +1,7 @@ +Manifest-Version: 2.0 +Main-Class: net.sf.antcontrib.cpptasks.AboutCCTask + +Name: CCTask +Implementation-Vendor: Ant-Contrib project +Implementation-Version: 1.0 +Implementation-Title: Compile and link tasks for Apache Ant diff --git a/Tools/Source/Cpptasks/cpptasks.tasks b/Tools/Source/Cpptasks/cpptasks.tasks new file mode 100644 index 0000000000..f34458374f --- /dev/null +++ b/Tools/Source/Cpptasks/cpptasks.tasks @@ -0,0 +1 @@ +cc=net.sf.antcontrib.cpptasks.CCTask diff --git a/Tools/Source/Cpptasks/cpptasks.types b/Tools/Source/Cpptasks/cpptasks.types new file mode 100644 index 0000000000..65af6e66c6 --- /dev/null +++ b/Tools/Source/Cpptasks/cpptasks.types @@ -0,0 +1,9 @@ +defineset=net.sf.antcontrib.cpptasks.types.DefineSet +compiler=net.sf.antcontrib.cpptasks.CompilerDef +linker=net.sf.antcontrib.cpptasks.LinkerDef +assembler=net.sf.antcontrib.cpptasks.AssemblerDef +aslcompiler=net.sf.antcontrib.cpptasks.AslcompilerDef +targetplatform=net.sf.antcontrib.cpptasks.TargetDef +versioninfo=net.sf.antcontrib.cpptasks.VersionInfo +distributer=net.sf.antcontrib.cpptasks.DistributerDef +command=net.sf.antcontrib.cpptasks.userdefine.UserDefineDef \ No newline at end of file diff --git a/Tools/Source/Cpptasks/javadoc.xml b/Tools/Source/Cpptasks/javadoc.xml new file mode 100644 index 0000000000..f0ca9648e9 --- /dev/null +++ b/Tools/Source/Cpptasks/javadoc.xml @@ -0,0 +1,30 @@ + + + + + + + + + Copyright @2001-2005 Ant-Contrib project. All Rights Reserved. + + + diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AboutCCTask.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AboutCCTask.java new file mode 100644 index 0000000000..67757bbf87 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AboutCCTask.java @@ -0,0 +1,49 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +/** + * The equivalent of a Help About + * run "java -jar cpptasks.jar" to read + * + * @author Curt Arnold + */ +public class AboutCCTask { + /** + * display identification message and exit + * + * @param args ignored + */ + public static void main(String args[]) { + System.out.println("CCTask: Compile and link task for Apache Ant 1.5 or later\n"); + System.out.println("Copyright (c) 2002-2004, The Ant-Contrib project.\n"); + System.out.println("http://sf.net/projects/ant-contrib\n"); + System.out.println("Licensed under the Apache Software License 2.0"); + System.out.println("available at http://www.apache.org/licenses/LICENSE-2.0\n"); + System.out.println("This software is not a product of the"); + System.out.println("of the Apache Software Foundation and no"); + System.out.println("endorsement or promotion is implied.\n"); + System.out.println("THIS SOFTWARE IS PROVIDED 'AS-IS', See"); + System.out.println("http://www.apache.org/LICENSE for additional"); + System.out.println("disclaimers.\n"); + System.out.println("To use:"); + System.out.println("\tPlace cpptasks.jar into lib directory of Ant 1.5 or later."); + System.out.println("\tAdd and"); + System.out.println("\t\t to build.xml"); + System.out.println("Add , , , and elements."); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ArchEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ArchEnum.java new file mode 100644 index 0000000000..e219ad6871 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ArchEnum.java @@ -0,0 +1,72 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import org.apache.tools.ant.types.EnumeratedAttribute; + +/** + * Enumeration of cpu architecture types. + * + * @author Curt Arnold + * + */ +public final class ArchEnum + extends EnumeratedAttribute { + /** + * Constructor. + * + * Set by default to "pentium3" + * + * @see java.lang.Object#Object() + */ + public ArchEnum() { + setValue("pentium3"); + } + + /** + * Gets list of acceptable values. + * + * @see org.apache.tools.ant.types.EnumeratedAttribute#getValues() + */ + public String[] getValues() { + /** + * Class initializer. + */ + return new String[] { + "i386", + "i486", + "i586", + "i686", + "pentium", + "pentium-mmx", + "pentiumpro", + "pentium2", + "pentium3", + "pentium4", + "k6", + "k6-2", + "k6-3", + "athlon", + "athlon-tbird", + "athlon-4", + "athlon-xp", + "athlon-mp", + "winchip-c6", + "winchip2", + "c3"}; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AslcompilerDef.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AslcompilerDef.java new file mode 100644 index 0000000000..f69d3fde63 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AslcompilerDef.java @@ -0,0 +1,118 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import net.sf.antcontrib.cpptasks.compiler.Aslcompiler; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.intel.IntelWin32Aslcompiler; +import net.sf.antcontrib.cpptasks.types.AslcompilerArgument; + +import org.apache.tools.ant.BuildException; + +/** + * A asl compiler definition. asl compiler elements may be placed either as + * children of a cc element or the project element. A asl compiler element with + * an id attribute may be referenced from asl compiler elements with refid or + * extends attributes. + * + */ +public final class AslcompilerDef extends ProcessorDef { + + private Boolean defaultflag = new Boolean(true); + + public AslcompilerDef () { + } + + /** + * Adds a asl compiler command-line arg. + */ + public void addConfiguredAslcompilerArg(AslcompilerArgument arg) { + if (isReference()) { + throw noChildrenAllowed(); + } + addConfiguredProcessorArg(arg); + } + + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + + public final Boolean getDefaultflag(AslcompilerDef[] defaultProviders, + int index) { + if (isReference()) { + return ((AslcompilerDef) getCheckedRef(AslcompilerDef.class, + "AslcompilerDef")).getDefaultflag(defaultProviders, + index); + } + return defaultflag; + } + + public Processor getProcessor() { + Processor processor = super.getProcessor(); + if (processor == null) { + processor = IntelWin32Aslcompiler.getInstance(); + } + return processor; + } + + /** + * Sets r type. + * + * Supported ASL Compilers + * + * + * + * + * + * + * + * + *
iasl (default)Intel ACPI Source Language
aslMicrosoft ACPI Source Language
+ * + */ + public void setName(AslcompilerEnum name) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + Aslcompiler aslcompiler = name.getAslcompiler(); + setProcessor(aslcompiler); + } + + protected void setProcessor(Processor proc) throws BuildException { + try { + super.setProcessor((Aslcompiler) proc); + } catch (ClassCastException ex) { + throw new BuildException(ex); + } + } + + /** + * Enables or disables default flags. + * + * @param defaultflag + * if true, default flags will add to command line. + * + */ + public void setDefaultflag(boolean defaultflag) { + if (isReference()) { + throw tooManyAttributes(); + } + this.defaultflag = booleanValueOf(defaultflag); + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AslcompilerEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AslcompilerEnum.java new file mode 100644 index 0000000000..fa9806916f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AslcompilerEnum.java @@ -0,0 +1,54 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import net.sf.antcontrib.cpptasks.compiler.Aslcompiler; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioAslcompiler; +import net.sf.antcontrib.cpptasks.intel.IntelWin32Aslcompiler; + +import org.apache.tools.ant.types.EnumeratedAttribute; + +/** + * Enumeration of supported ASL Compilers + * + * Supported ASL Compilers + * + * + * + * + * + * + * + * + *
iasl (default)Intel ACPI Source Language
aslMicrosoft ACPI Source Language
+ * + */ +public class AslcompilerEnum extends EnumeratedAttribute { + private final static ProcessorEnumValue[] aslcompiler = new ProcessorEnumValue[] { + new ProcessorEnumValue("iasl", IntelWin32Aslcompiler + .getInstance()), + new ProcessorEnumValue("asl", DevStudioAslcompiler + .getInstance()), }; + + public Aslcompiler getAslcompiler() { + return (Aslcompiler) aslcompiler[getIndex()].getProcessor(); + } + + public String[] getValues() { + return ProcessorEnumValue.getValues(aslcompiler); + } +} \ No newline at end of file diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AssemblerDef.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AssemblerDef.java new file mode 100644 index 0000000000..aeae215780 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AssemblerDef.java @@ -0,0 +1,237 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.Assembler; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.gcc.GccAssembler; +import net.sf.antcontrib.cpptasks.types.AssemblerArgument; +import net.sf.antcontrib.cpptasks.types.ConditionalPath; +import net.sf.antcontrib.cpptasks.types.IncludePath; +import net.sf.antcontrib.cpptasks.types.SystemIncludePath; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; + +/** + * A assembler definition. Assembler elements may be placed either as children + * of a cc element or the project element. A assembler element with an id + * attribute may be referenced from assembler elements with refid or extends + * attributes. + * + */ +public final class AssemblerDef extends ProcessorDef { + + private final Vector includePaths = new Vector(); + + private final Vector sysIncludePaths = new Vector(); + + private Boolean defaultflag = new Boolean(true); + + public AssemblerDef () { + } + + /** + * Adds a assembler command-line arg. + */ + public void addConfiguredAssemblerArg(AssemblerArgument arg) { + if (isReference()) { + throw noChildrenAllowed(); + } + addConfiguredProcessorArg(arg); + } + + /** + * Creates an include path. + */ + public IncludePath createIncludePath() { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project must be set"); + } + if (isReference()) { + throw noChildrenAllowed(); + } + IncludePath path = new IncludePath(p); + includePaths.addElement(path); + return path; + } + + /** + * Creates an include path. + */ + public SystemIncludePath createSysIncludePath() { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project must be set"); + } + if (isReference()) { + throw noChildrenAllowed(); + } + SystemIncludePath path = new SystemIncludePath(p); + sysIncludePaths.addElement(path); + return path; + } + + /** + * Add a or if specify the file attribute + * + * @throws BuildException + * if the specify file not exist + */ + protected void loadFile(Vector activePath, File file) throws BuildException { + FileReader fileReader; + BufferedReader in; + String str; + if (!file.exists()) { + throw new BuildException("The file " + file + " is not existed"); + } + try { + fileReader = new FileReader(file); + in = new BufferedReader(fileReader); + while ((str = in.readLine()) != null) { + if (str.trim() == "") { + continue; + } + str = getProject().replaceProperties(str); + activePath.addElement(str.trim()); + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } + + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + + /** + * Returns the assembler-specific include path. + */ + public String[] getActiveIncludePaths() { + if (isReference()) { + return ((AssemblerDef) getCheckedRef(AssemblerDef.class, + "AssemblerDef")).getActiveIncludePaths(); + } + return getActivePaths(includePaths); + } + + /** + * Returns the assembler-specific sysinclude path. + */ + public String[] getActiveSysIncludePaths() { + if (isReference()) { + return ((AssemblerDef) getCheckedRef(AssemblerDef.class, + "AssemblerDef")).getActiveSysIncludePaths(); + } + return getActivePaths(sysIncludePaths); + } + + private String[] getActivePaths(Vector paths) { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project not set"); + } + Vector activePaths = new Vector(paths.size()); + for (int i = 0; i < paths.size(); i++) { + ConditionalPath path = (ConditionalPath) paths.elementAt(i); + if (path.isActive(p)) { + if (path.getFile() == null) { + String[] pathEntries = path.list(); + for (int j = 0; j < pathEntries.length; j++) { + activePaths.addElement(pathEntries[j]); + } + } else { + loadFile(activePaths, path.getFile()); + } + } + } + String[] pathNames = new String[activePaths.size()]; + activePaths.copyInto(pathNames); + return pathNames; + } + + public final Boolean getDefaultflag(AssemblerDef[] defaultProviders, + int index) { + if (isReference()) { + return ((AssemblerDef) getCheckedRef(AssemblerDef.class, + "AssemblerDef")).getDefaultflag(defaultProviders, + index); + } + return defaultflag; + } + + public Processor getProcessor() { + Processor processor = super.getProcessor(); + if (processor == null) { + processor = GccAssembler.getInstance(); + } + return processor; + } + + /** + * Sets r type. + * + * Supported assemblers + * + * + * + * + * + * + * + * + *
gcc (default)GAS assembler
masmMASM assembler
+ * + */ + public void setName(AssemblerEnum name) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + Assembler assembler = name.getAssembler(); + setProcessor(assembler); + } + + protected void setProcessor(Processor proc) throws BuildException { + try { + super.setProcessor((Assembler) proc); + } catch (ClassCastException ex) { + throw new BuildException(ex); + } + } + + /** + * Enables or disables default flags. + * + * @param defaultflag + * if true, default flags will add to command line. + * + */ + public void setDefaultflag(boolean defaultflag) { + if (isReference()) { + throw tooManyAttributes(); + } + this.defaultflag = booleanValueOf(defaultflag); + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AssemblerEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AssemblerEnum.java new file mode 100644 index 0000000000..9abf9f496d --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/AssemblerEnum.java @@ -0,0 +1,53 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import net.sf.antcontrib.cpptasks.compiler.Assembler; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioAssembler; +import net.sf.antcontrib.cpptasks.gcc.GccAssembler; + +import org.apache.tools.ant.types.EnumeratedAttribute; + +/** + * Enumeration of supported assemblers + * + * Supported assemblers + * + * + * + * + * + * + * + * + *
gas (default)GAS assembler
masmMASM assembler
+ * + */ +public class AssemblerEnum extends EnumeratedAttribute { + private final static ProcessorEnumValue[] assemblers = new ProcessorEnumValue[] { + new ProcessorEnumValue("gas", GccAssembler.getInstance()), + new ProcessorEnumValue("masm", DevStudioAssembler + .getInstance()), }; + + public Assembler getAssembler() { + return (Assembler) assemblers[getIndex()].getProcessor(); + } + + public String[] getValues() { + return ProcessorEnumValue.getValues(assemblers); + } +} \ No newline at end of file diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CCTask.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CCTask.java new file mode 100644 index 0000000000..d044df1288 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CCTask.java @@ -0,0 +1,1749 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.AslcompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.AssemblerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.CompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.LinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; +import net.sf.antcontrib.cpptasks.types.AslcompilerArgument; +import net.sf.antcontrib.cpptasks.types.AssemblerArgument; +import net.sf.antcontrib.cpptasks.types.CompilerArgument; +import net.sf.antcontrib.cpptasks.types.ConditionalFileSet; +import net.sf.antcontrib.cpptasks.types.DefineSet; +import net.sf.antcontrib.cpptasks.types.IncludePath; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +import net.sf.antcontrib.cpptasks.types.LinkerArgument; +import net.sf.antcontrib.cpptasks.types.SystemIncludePath; +import net.sf.antcontrib.cpptasks.types.SystemLibrarySet; +import net.sf.antcontrib.cpptasks.userdefine.UserDefineCompiler; +import net.sf.antcontrib.cpptasks.userdefine.UserDefineDef; +import net.sf.antcontrib.cpptasks.VersionInfo; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.types.Environment; + +/** + * Compile, link, assembler and asl compile task. + * + *

+ * This task can compile various source languages and produce executables, + * shared libraries (aka DLL's) and static libraries. Compiler adaptors are + * currently available for several C/C++ compilers, FORTRAN, MIDL and Windows + * Resource files. Assembler adaptors are currently available for MASM and GAS. + * And aslcompiler support to ASL and IASL command. + *

+ * + * + *

+ * Copyright (c) 2001-2005, The Ant-Contrib project. + *

+ * + *

+ * Licensed under the Apache Software License 2.0, + * http://www.apache.org/licenses/LICENSE-2.0. + *

+ * + *

+ * For use with Apache Ant 1.5 or later. This software is not a product of the + * of the Apache Software Foundation and no endorsement is implied. + *

+ * + *

+ * THIS SOFTWARE IS PROVIDED 'AS-IS', See + * http://www.apache.org/licenses/LICENSE-2.0 for additional disclaimers. + *

+ * + * To use: + *
    + *
  1. Place cpptasks.jar into the lib directory of Ant 1.5 or later.
  2. + *
  3. Add <taskdef resource="cpptasks.tasks"/> and <typedef + * resource="cpptasks.types"/> to build.xml.
  4. + *
  5. Add <cc/>, <compiler/> <linker/> <assembler/> + * and <aslcompiler/> elements to project.
  6. + *
  7. Set path and environment variables to be able to run compiler from + * command line.
  8. + *
  9. Build project.
  10. + *
+ * + * @author Adam Murdoch + * @author Curt Arnold + */ +public class CCTask extends Task { + private class SystemLibraryCollector implements FileVisitor { + private Hashtable libraries; + + private Linker linker; + + public SystemLibraryCollector (Linker linker, Hashtable libraries) { + this.linker = linker; + this.libraries = libraries; + } + + public void visit(File basedir, String filename) { + if (linker.bid(filename) > 0) { + File libfile = new File(basedir, filename); + String key = linker.getLibraryKey(libfile); + libraries.put(key, libfile); + } + } + } + + private static final ProcessorConfiguration[] EMPTY_CONFIG_ARRAY = new ProcessorConfiguration[0]; + + /** + * Builds a Hashtable to targets needing to be rebuilt keyed by compiler + * configuration + */ + public static Hashtable getTargetsToBuildByConfiguration(Hashtable targets) { + Hashtable targetsByConfig = new Hashtable(); + Enumeration targetEnum = targets.elements(); + while (targetEnum.hasMoreElements()) { + TargetInfo target = (TargetInfo) targetEnum.nextElement(); + if (target.getRebuild()) { + Vector targetsForSameConfig = (Vector) targetsByConfig + .get(target.getConfiguration()); + if (targetsForSameConfig != null) { + targetsForSameConfig.addElement(target); + } else { + targetsForSameConfig = new Vector(); + targetsForSameConfig.addElement(target); + targetsByConfig.put(target.getConfiguration(), + targetsForSameConfig); + } + } + } + return targetsByConfig; + } + + /** The userdefine definitions. */ + private Vector _userdefines = new Vector(); + + /** The compiler definitions. */ + private Vector _compilers = new Vector(); + + /** The output file type. */ + // private LinkType _linkType = LinkType.EXECUTABLE; + /** The library sets. */ + private Vector _libsets = new Vector(); + + /** The aslcompiler definitions. */ + private Vector _aslcompiler = new Vector(); + + /** The assembler definitions. */ + private Vector _assemblers = new Vector(); + + /** The linker definitions. */ + private Vector _linkers = new Vector(); + + /** The object directory. */ + private File _objDir; + + /** The output file. */ + private File _outfile; + + private boolean userdefine = false; + private String arch; + private String os; + private String vendor; + + /** the flag for assembler */ + private boolean assembler = true; + + /** the flag for aslcompiler */ + private boolean aslcompiler = true; + + /** The linker definitions. */ + private final Vector targetPlatforms = new Vector(); + + /** The distributer definitions. */ + private Vector distributers = new Vector(); + + /** + * If true, stop build on compile failure. + */ + protected boolean failOnError = true; + + /** + * Content that appears in and also in are maintained by a + * captive CompilerDef instance + */ + private final CompilerDef compilerDef = new CompilerDef(); + + /** + * Content that appears in and also in are maintained by a + * captive AslcompilerDef instance + */ + private final AslcompilerDef aslcompilerDef = new AslcompilerDef(); + + /** The OS390 dataset to build to object to */ + private String dataset; + + /** + * + * Depth of dependency checking + * + * Values < 0 indicate full dependency checking Values >= 0 indicate partial + * dependency checking and for superficial compilation checks. Will throw + * BuildException before attempting link + */ + private int dependencyDepth = -1; + + /** + * Content that appears in and also in are maintained by a + * captive AssemblerDef instance + */ + private final AssemblerDef assemblerDef = new AssemblerDef(); + + /** + * Content that appears in and also in are maintained by a + * captive CompilerDef instance + */ + private final LinkerDef linkerDef = new LinkerDef(); + + /** + * contains the subsystem, output type and + * + */ + private final LinkType linkType = new LinkType(); + + /** + * The property name which will be set with the physical filename of the + * file that is generated by the linker + */ + private String outputFileProperty; + + /** + * if relentless = true, compilations should attempt to compile as many + * files as possible before throwing a BuildException + */ + private boolean relentless; + + public CCTask () { + } + + + public void addConfiguredCommand(UserDefineDef userdefineDef) { + if (userdefineDef == null) { + throw new NullPointerException("UserDefineDef"); + } + userdefineDef.setProject(getProject()); + _userdefines.addElement(userdefineDef); + } + /** + * Adds a asl compiler definition or reference. + * + * @param Aslcompiler + * aslcompiler + * @throws NullPointerException + * if aslcompiler is null + */ + public void addConfiguredAslcompiler(AslcompilerDef aslcompier) { + if (aslcompier == null) { + throw new NullPointerException("aslcompier"); + } + aslcompier.setProject(getProject()); + _aslcompiler.addElement(aslcompier); + } + + /** + * Adds a asl command-line arg. Argument will be inherited by all nested + * aslcompiler elements that do not have inherit="false". + * + */ + public void addConfiguredAslcompilerArg(AslcompilerArgument arg) { + aslcompilerDef.addConfiguredAslcompilerArg(arg); + } + + /** + * Adds a assembler definition or reference. + * + * @param assembler + * assemblera + * @throws NullPointerException + * if assembler is null + */ + public void addConfiguredAssembler(AssemblerDef assembler) { + if (assembler == null) { + throw new NullPointerException("assembler"); + } + assembler.setProject(getProject()); + _assemblers.addElement(assembler); + } + + /** + * Adds a assembler command-line arg. Argument will be inherited by all + * nested assembler elements that do not have inherit="false". + * + */ + public void addConfiguredAssemblerArg(AssemblerArgument arg) { + assemblerDef.addConfiguredAssemblerArg(arg); + } + + /** + * Adds a compiler definition or reference. + * + * @param compiler + * compiler + * @throws NullPointerException + * if compiler is null + */ + public void addConfiguredCompiler(CompilerDef compiler) { + if (compiler == null) { + throw new NullPointerException("compiler"); + } + compiler.setProject(getProject()); + _compilers.addElement(compiler); + } + + /** + * Adds a compiler command-line arg. Argument will be inherited by all + * nested compiler elements that do not have inherit="false". + * + */ + public void addConfiguredCompilerArg(CompilerArgument arg) { + compilerDef.addConfiguredCompilerArg(arg); + } + + /** + * Adds a defineset. Will be inherited by all compiler elements that do not + * have inherit="false". + * + * @param defs + * Define set + */ + public void addConfiguredDefineset(DefineSet defs) { + compilerDef.addConfiguredDefineset(defs); + } + + /** + * Adds a linker definition. The first linker that is not disqualified by + * its "if" and "unless" attributes will perform the link. If no child + * linker element is active, the linker implied by the cc elements name or + * classname attribute will be used. + * + * @param linker + * linker + * @throws NullPointerException + * if linker is null + */ + public void addConfiguredLinker(LinkerDef linker) { + if (linker == null) { + throw new NullPointerException("linker"); + } + linker.setProject(getProject()); + _linkers.addElement(linker); + } + + /** + * Adds a linker command-line arg. Argument will be inherited by all nested + * linker elements that do not have inherit="false". + */ + public void addConfiguredLinkerArg(LinkerArgument arg) { + linkerDef.addConfiguredLinkerArg(arg); + } + + /** + * Add an environment variable to the launched process. + */ + public void addEnv(Environment.Variable var) { + compilerDef.addEnv(var); + linkerDef.addEnv(var); + assemblerDef.addEnv(var); + aslcompilerDef.addEnv(var); + } + + /** + * Adds a source file set. + * + * Files in these filesets will be auctioned to the available compiler + * configurations, with the default compiler implied by the cc element + * bidding last. If no compiler is interested in the file, it will be passed + * to the linker. + * + * To have a file be processed by a particular compiler configuration, add a + * fileset to the corresponding compiler element. + */ + public void addFileset(ConditionalFileSet srcSet) { + compilerDef.addFileset(srcSet); + } + + /** + * Adds a library set. + * + * Library sets will be inherited by all linker elements that do not have + * inherit="false". + * + * @param libset + * library set + * @throws NullPointerException + * if libset is null. + */ + public void addLibset(LibrarySet libset) { + if (libset == null) { + throw new NullPointerException("libset"); + } + linkerDef.addLibset(libset); + } + + /** + * Adds a system library set. Timestamps and locations of system library + * sets are not used in dependency analysis. + * + * Essential libraries (such as C Runtime libraries) should not be specified + * since the task will attempt to identify the correct libraries based on + * the multithread, debug and runtime attributes. + * + * System library sets will be inherited by all linker elements that do not + * have inherit="false". + * + * @param libset + * library set + * @throws NullPointerException + * if libset is null. + */ + public void addSyslibset(SystemLibrarySet libset) { + if (libset == null) { + throw new NullPointerException("libset"); + } + linkerDef.addSyslibset(libset); + } + + /** + * Checks all targets that are not forced to be rebuilt or are missing + * object files to be checked for modified include files + * + * @returns total number of targets to be rebuilt + * + */ + protected int checkForChangedIncludeFiles(Hashtable targets) { + int potentialTargets = 0; + int definiteTargets = 0; + Enumeration targetEnum = targets.elements(); + while (targetEnum.hasMoreElements()) { + TargetInfo target = (TargetInfo) targetEnum.nextElement(); + if (!target.getRebuild()) { + potentialTargets++; + } else { + definiteTargets++; + } + } + // + // If there were remaining targets that + // might be out of date + // + if (potentialTargets > 0) { + log("Starting dependency analysis for " + + Integer.toString(potentialTargets) + " files."); + DependencyTable dependencyTable = new DependencyTable(_objDir); + try { + dependencyTable.load(); + } catch (Exception ex) { + log("Problem reading dependencies.xml: " + ex.toString()); + } + targetEnum = targets.elements(); + while (targetEnum.hasMoreElements()) { + TargetInfo target = (TargetInfo) targetEnum.nextElement(); + if (!target.getRebuild()) { + if (dependencyTable.needsRebuild(this, target, + dependencyDepth)) { + target.mustRebuild(); + } + } + } + dependencyTable.commit(this); + } + // + // count files being rebuilt now + // + int currentTargets = 0; + targetEnum = targets.elements(); + while (targetEnum.hasMoreElements()) { + TargetInfo target = (TargetInfo) targetEnum.nextElement(); + if (target.getRebuild()) { + currentTargets++; + } + } + if (potentialTargets > 0) { + log(Integer.toString(potentialTargets - currentTargets + + definiteTargets) + + " files are up to date."); + log(Integer.toString(currentTargets - definiteTargets) + + " files to be recompiled from dependency analysis."); + } + log(Integer.toString(currentTargets) + " total files to be compiled."); + return currentTargets; + } + + protected LinkerConfiguration collectExplicitObjectFiles( + Vector objectFiles, Vector sysObjectFiles) { + // + // find the first eligible linker + // + // + ProcessorConfiguration linkerConfig = null; + LinkerDef selectedLinkerDef = null; + Linker selectedLinker = null; + Hashtable sysLibraries = new Hashtable(); + TargetDef targetPlatform = getTargetPlatform(); + FileVisitor objCollector = null; + FileVisitor sysLibraryCollector = null; + for (int i = 0; i < _linkers.size(); i++) { + LinkerDef currentLinkerDef = (LinkerDef) _linkers.elementAt(i); + if (currentLinkerDef.isActive()) { + selectedLinkerDef = currentLinkerDef; + selectedLinker = currentLinkerDef.getProcessor().getLinker( + linkType); + // + // skip the linker if it doesn't know how to + // produce the specified link type + if (selectedLinker != null) { + linkerConfig = currentLinkerDef.createConfiguration(this, + linkType, linkerDef, targetPlatform); + if (linkerConfig != null) { + // + // create collectors for object files + // and system libraries + objCollector = new ObjectFileCollector(selectedLinker, + objectFiles); + sysLibraryCollector = new SystemLibraryCollector( + selectedLinker, sysLibraries); + // + // if the has embedded 's + // (such as linker specific libraries) + // add them as object files. + // + if (currentLinkerDef.hasFileSets()) { + currentLinkerDef.visitFiles(objCollector); + } + // + // user libraries are just a specialized form + // of an object fileset + selectedLinkerDef.visitUserLibraries(selectedLinker, + objCollector); + } + break; + } + } + } + if (linkerConfig == null) { + linkerConfig = linkerDef.createConfiguration(this, linkType, null, + targetPlatform); + selectedLinker = (Linker) linkerDef.getProcessor().getLinker( + linkType); + objCollector = new ObjectFileCollector(selectedLinker, objectFiles); + sysLibraryCollector = new SystemLibraryCollector(selectedLinker, + sysLibraries); + } + // + // unless there was a element that + // explicitly did not inherit files from + // containing element + if (selectedLinkerDef == null || selectedLinkerDef.getInherit()) { + linkerDef.visitUserLibraries(selectedLinker, objCollector); + linkerDef.visitSystemLibraries(selectedLinker, sysLibraryCollector); + } + // + // if there was a in a nested + // evaluate it last so it takes priority over + // identically named libs from element + // + if (selectedLinkerDef != null) { + // + // add any system libraries to the hashtable + // done in reverse order so the earliest + // on the classpath takes priority + selectedLinkerDef.visitSystemLibraries(selectedLinker, + sysLibraryCollector); + } + // + // copy over any system libraries to the + // object files vector + // + Enumeration sysLibEnum = sysLibraries.elements(); + while (sysLibEnum.hasMoreElements()) { + sysObjectFiles.addElement(sysLibEnum.nextElement()); + } + return (LinkerConfiguration) linkerConfig; + } + + /** + * Adds an include path. + * + * Include paths will be inherited by nested compiler elements that do not + * have inherit="false". + */ + public IncludePath createIncludePath() { + return compilerDef.createIncludePath(); + } + + /** + * Specifies precompilation prototype file and exclusions. Inherited by all + * compilers that do not have inherit="false". + * + */ + public PrecompileDef createPrecompile() throws BuildException { + return compilerDef.createPrecompile(); + } + + /** + * Adds a system include path. Locations and timestamps of files located + * using the system include paths are not used in dependency analysis. + * + * + * Standard include locations should not be specified. The compiler adapters + * should recognized the settings from the appropriate environment variables + * or configuration files. + * + * System include paths will be inherited by nested compiler elements that + * do not have inherit="false". + */ + public SystemIncludePath createSysIncludePath() { + return compilerDef.createSysIncludePath(); + } + + /** + * Executes the task. Compiles the given files. + * + * @throws BuildException + * if someting goes wrong with the build + */ + public void execute() throws BuildException { + // + // if link type allowed objdir to be defaulted + // provide it from outfile + if (_objDir == null) { + if (_outfile != null) { + _objDir = new File(_outfile.getParent()); + } else { + _objDir = new File("."); + } + } + + // + // if the object directory does not exist + // + if (!_objDir.exists()) { + throw new BuildException("Object directory does not exist"); + } + + // + // if userdefine is true, then run all user defined command + // + if (userdefine) { + Iterator iter = _userdefines.iterator(); + while( iter.hasNext()) { + UserDefineDef userdefineDef = (UserDefineDef)iter.next(); + UserDefineCompiler userdefineCompiler = new UserDefineCompiler(this, userdefineDef); + userdefineCompiler.command(this, userdefineDef); + } + return ; + } + + TargetHistoryTable objHistory = new TargetHistoryTable(this, _objDir); + // + // determine the eventual linker configuration + // (may be null) and collect any explicit + // object files or libraries + Vector objectFiles = new Vector(); + Vector sysObjectFiles = new Vector(); + LinkerConfiguration linkerConfig = collectExplicitObjectFiles( + objectFiles, sysObjectFiles); + // + // Assembler hashtable of all files + // that we know how to compile (keyed by output file name) + // + Hashtable targets = getTargets(linkerConfig, objectFiles); + Hashtable acpiTarget = new Hashtable(); + if (aslcompiler) { + acpiTarget = getAcpiTargets(linkerConfig, new Vector()); + } + Hashtable assemblerTarget = new Hashtable(); + if (assembler) { + assemblerTarget = getAssemblerTargets(linkerConfig, objectFiles); + } + TargetInfo linkTarget = null; + // + // if output file is not specified, + // then skip link step + // + if (_outfile != null) { + linkTarget = getLinkTarget(linkerConfig, objectFiles, + sysObjectFiles, targets, assemblerTarget); + } + // + // If specify the aslcompiler, then call asl compiler + // + if (aslcompiler) { + BuildException acpiException = null; + Hashtable targetsByConfig = getTargetsToBuildByConfiguration(acpiTarget); + Enumeration acpiTargetEnum = targetsByConfig.elements(); + Vector[] targetVectors = new Vector[targetsByConfig.size()]; + int index = 0; + while (acpiTargetEnum.hasMoreElements()) { + Vector targetsForConfig = (Vector) acpiTargetEnum.nextElement(); + targetVectors[index++] = targetsForConfig; + } + for (int i = 0; i < targetVectors.length; i++) { + // + // get the targets for this configuration + // + Vector targetsForConfig = targetVectors[i]; + // + // get the configuration from the first entry + // + AslcompilerConfiguration config = (AslcompilerConfiguration) ((TargetInfo) targetsForConfig + .elementAt(0)).getConfiguration(); + // + // prepare the list of source files + // + String[] sourceFiles = new String[targetsForConfig.size()]; + Enumeration targetsEnum = targetsForConfig.elements(); + index = 0; + while (targetsEnum.hasMoreElements()) { + TargetInfo targetInfo = ((TargetInfo) targetsEnum + .nextElement()); + sourceFiles[index++] = targetInfo.getSources()[0] + .toString(); + } + try { + config.aslcompiler(this, _objDir, sourceFiles); + log(sourceFiles.length + + " total ACPI source files to be compiled."); + } catch (BuildException ex) { + if (acpiException == null) { + acpiException = ex; + } + if (!relentless) + break; + } + } + } + // + // If specify the assembler, then call assembler + // + if (assembler) { + BuildException assemblerException = null; + Hashtable targetsByConfig = getTargetsToBuildByConfiguration(assemblerTarget); + Enumeration assembleTargetEnum = targetsByConfig.elements(); + Vector[] targetVectors = new Vector[targetsByConfig.size()]; + int index = 0; + while (assembleTargetEnum.hasMoreElements()) { + Vector targetsForConfig = (Vector) assembleTargetEnum + .nextElement(); + targetVectors[index++] = targetsForConfig; + } + for (int i = 0; i < targetVectors.length; i++) { + // + // get the targets for this configuration + // + Vector targetsForConfig = targetVectors[i]; + // + // get the configuration from the first entry + // + AssemblerConfiguration config = (AssemblerConfiguration) ((TargetInfo) targetsForConfig + .elementAt(0)).getConfiguration(); + // + // prepare the list of source files + // + String[] sourceFiles = new String[targetsForConfig.size()]; + Enumeration targetsEnum = targetsForConfig.elements(); + index = 0; + while (targetsEnum.hasMoreElements()) { + TargetInfo targetInfo = ((TargetInfo) targetsEnum + .nextElement()); + sourceFiles[index++] = targetInfo.getSources()[0] + .toString(); + } + try { + config.assembler(this, _objDir, sourceFiles); + log(sourceFiles.length + " total files to be assembled."); + } catch (BuildException ex) { + if (assemblerException == null) { + assemblerException = ex; + } + if (!relentless) + break; + } + } + // + // if we threw a assembler exception and + // didn't throw it at the time because + // we were relentless then + // save the history and + // throw the exception + // + if (assemblerException != null) { + if (failOnError) { + throw assemblerException; + } else { + log(assemblerException.getMessage(), Project.MSG_ERR); + return; + } + } + } + + // + // mark targets that don't have a history record or + // whose source last modification time is not + // the same as the history to be rebuilt + // + objHistory.markForRebuild(targets); + CCTaskProgressMonitor monitor = new CCTaskProgressMonitor(objHistory); + // + // check for changed include files + // + int rebuildCount = checkForChangedIncludeFiles(targets); + if (rebuildCount > 0) { + BuildException compileException = null; + // + // compile all targets with getRebuild() == true + // + Hashtable targetsByConfig = getTargetsToBuildByConfiguration(targets); + // + // build array containing Vectors with precompiled generation + // steps going first + // + Vector[] targetVectors = new Vector[targetsByConfig.size()]; + int index = 0; + Enumeration targetVectorEnum = targetsByConfig.elements(); + while (targetVectorEnum.hasMoreElements()) { + Vector targetsForConfig = (Vector) targetVectorEnum + .nextElement(); + // + // get the configuration from the first entry + // + CompilerConfiguration config = (CompilerConfiguration) ((TargetInfo) targetsForConfig + .elementAt(0)).getConfiguration(); + if (config.isPrecompileGeneration()) { + targetVectors[index++] = targetsForConfig; + } + } + targetVectorEnum = targetsByConfig.elements(); + while (targetVectorEnum.hasMoreElements()) { + Vector targetsForConfig = (Vector) targetVectorEnum + .nextElement(); + for (int i = 0; i < targetVectors.length; i++) { + if (targetVectors[i] == targetsForConfig) { + break; + } + if (targetVectors[i] == null) { + targetVectors[i] = targetsForConfig; + break; + } + } + } + for (int i = 0; i < targetVectors.length; i++) { + // + // get the targets for this configuration + // + Vector targetsForConfig = targetVectors[i]; + // + // get the configuration from the first entry + // + CompilerConfiguration config = (CompilerConfiguration) ((TargetInfo) targetsForConfig + .elementAt(0)).getConfiguration(); + // + // prepare the list of source files + // + String[] sourceFiles = new String[targetsForConfig.size()]; + Enumeration targetsEnum = targetsForConfig.elements(); + index = 0; + while (targetsEnum.hasMoreElements()) { + TargetInfo targetInfo = ((TargetInfo) targetsEnum + .nextElement()); + sourceFiles[index++] = targetInfo.getSources()[0] + .toString(); + } + try { + config.compile(this, _objDir, sourceFiles, relentless, + monitor); + } catch (BuildException ex) { + if (compileException == null) { + compileException = ex; + } + if (!relentless) + break; + } + } + // + // save the details of the object file compilation + // settings to disk for dependency analysis + // + try { + objHistory.commit(); + } catch (IOException ex) { + this.log("Error writing history.xml: " + ex.toString()); + } + // + // if we threw a compile exception and + // didn't throw it at the time because + // we were relentless then + // save the history and + // throw the exception + // + if (compileException != null) { + if (failOnError) { + throw compileException; + } else { + log(compileException.getMessage(), Project.MSG_ERR); + return; + } + } + } + // + // if the dependency tree was not fully + // evaluated, then throw an exception + // since we really didn't do what we + // should have done + // + // + if (dependencyDepth >= 0) { + throw new BuildException( + "All files at depth " + + Integer.toString(dependencyDepth) + + " from changes successfully compiled.\n" + + "Remove or change dependencyDepth to -1 to perform full compilation."); + } + // + // if no link target then + // commit the history for the object files + // and leave the task + if (linkTarget != null) { + // + // get the history for the link target (may be the same + // as the object history) + TargetHistoryTable linkHistory = getLinkHistory(objHistory); + // + // see if it needs to be rebuilt + // + linkHistory.markForRebuild(linkTarget); + // + // if it needs to be rebuilt, rebuild it + // + File output = linkTarget.getOutput(); + if (linkTarget.getRebuild()) { + log("Starting link"); + LinkerConfiguration linkConfig = (LinkerConfiguration) linkTarget + .getConfiguration(); + if (failOnError) { + linkConfig.link(this, linkTarget); + } else { + try { + linkConfig.link(this, linkTarget); + } catch (BuildException ex) { + log(ex.getMessage(), Project.MSG_ERR); + return; + } + } + if (outputFileProperty != null) + getProject().setProperty(outputFileProperty, + output.getAbsolutePath()); + linkHistory.update(linkTarget); + try { + linkHistory.commit(); + } catch (IOException ex) { + log("Error writing link history.xml: " + ex.toString()); + } + } else { + if (outputFileProperty != null) + getProject().setProperty(outputFileProperty, + output.getAbsolutePath()); + } + } + } + + /** + * Gets the dataset. + * + * @return Returns a String + */ + public String getDataset() { + return dataset; + } + + protected TargetHistoryTable getLinkHistory(TargetHistoryTable objHistory) { + File outputFileDir = new File(_outfile.getParent()); + // + // if the output file is being produced in the link + // directory, then we can use the same history file + // + if (_objDir.equals(outputFileDir)) { + return objHistory; + } + return new TargetHistoryTable(this, outputFileDir); + } + + protected TargetInfo getLinkTarget(LinkerConfiguration linkerConfig, + Vector objectFiles, Vector sysObjectFiles, + Hashtable compileTargets, Hashtable assemblerTargets) { + // + // walk the compile phase targets and + // add those sources that have already been + // assigned to the linker or + // our output files the linker knows how to consume + // files the linker knows how to consume + // + Enumeration compileTargetsEnum = compileTargets.elements(); + while (compileTargetsEnum.hasMoreElements()) { + TargetInfo compileTarget = (TargetInfo) compileTargetsEnum + .nextElement(); + // + // output of compile tasks + // + int bid = linkerConfig.bid(compileTarget.getOutput().toString()); + if (bid > 0) { + objectFiles.addElement(compileTarget.getOutput()); + } + } + // + // walk the assembler phase targets and + // add those sources that have already been + // assigned to the linker or + // our output files the linker knows how to consume + // files the linker knows how to consume + // + Enumeration assembleTargetsEnum = assemblerTargets.elements(); + while (assembleTargetsEnum.hasMoreElements()) { + TargetInfo assemblerTarget = (TargetInfo) assembleTargetsEnum + .nextElement(); + // + // output of assemble tasks + // + int bid = linkerConfig.bid(assemblerTarget.getOutput().toString()); + if (bid > 0) { + objectFiles.addElement(assemblerTarget.getOutput()); + } + } + File[] objectFileArray = new File[objectFiles.size()]; + objectFiles.copyInto(objectFileArray); + File[] sysObjectFileArray = new File[sysObjectFiles.size()]; + sysObjectFiles.copyInto(sysObjectFileArray); + String baseName = _outfile.getName(); + String fullName = linkerConfig.getOutputFileName(baseName); + File outputFile = new File(_outfile.getParent(), fullName); + return new TargetInfo(linkerConfig, objectFileArray, + sysObjectFileArray, outputFile, linkerConfig + .getRebuild()); + } + + public File getObjdir() { + return _objDir; + } + + public File getOutfile() { + return _outfile; + } + + public TargetDef getTargetPlatform() { + return null; + } + + /** + * This method collects a Hashtable, keyed by output file name, of + * TargetInfo's for every source file that is specified in the filesets of + * the elements. The TargetInfo's contain the appropriate ACPI + * configurations for their possible acpi + * + */ + private Hashtable getAcpiTargets(LinkerConfiguration linkerConfig, + Vector objectFiles) { + Hashtable targets = new Hashtable(1000); + TargetDef targetPlatform = getTargetPlatform(); + Vector biddingProcessors = new Vector(_aslcompiler.size()); + for (int i = 0; i < _aslcompiler.size(); i++) { + AslcompilerDef currentAslDef = (AslcompilerDef) _aslcompiler + .elementAt(i); + if (currentAslDef.isActive()) { + ProcessorConfiguration config = currentAslDef + .createConfiguration(this, linkType, + aslcompilerDef, targetPlatform); + // + // if the aslcompiler has a fileset + // then allow it to add its files to + // the set of potential targets + // + ProcessorConfiguration[] localConfigs = new ProcessorConfiguration[] { config }; + if (currentAslDef.hasFileSets()) { + TargetMatcher matcher = new TargetMatcher(this, _objDir, + localConfigs, linkerConfig, objectFiles, + targets); + currentAslDef.visitFiles(matcher); + } + biddingProcessors.addElement(config); + } + } + // + // add fallback compiler at the end + // + ProcessorConfiguration config = aslcompilerDef.createConfiguration( + this, linkType, null, targetPlatform); + biddingProcessors.addElement(config); + ProcessorConfiguration[] bidders = new ProcessorConfiguration[biddingProcessors + .size()]; + biddingProcessors.copyInto(bidders); + TargetMatcher matcher = new TargetMatcher(this, _objDir, bidders, + linkerConfig, objectFiles, targets); + aslcompilerDef.visitFiles(matcher); + return targets; + } + + /** + * This method collects a Hashtable, keyed by output file name, of + * TargetInfo's for every source file that is specified in the filesets of + * the elements. The TargetInfo's contain the appropriate + * assembler configurations for their possible assembly + * + */ + private Hashtable getAssemblerTargets(LinkerConfiguration linkerConfig, + Vector objectFiles) { + Hashtable targets = new Hashtable(1000); + TargetDef targetPlatform = getTargetPlatform(); + Vector biddingProcessors = new Vector(_assemblers.size()); + for (int i = 0; i < _assemblers.size(); i++) { + AssemblerDef currentAssemblerDef = (AssemblerDef) _assemblers + .elementAt(i); + if (currentAssemblerDef.isActive()) { + ProcessorConfiguration config = currentAssemblerDef + .createConfiguration(this, linkType, + assemblerDef, targetPlatform); + // + // if the assembler has a fileset + // then allow it to add its files to + // the set of potential targets + // + ProcessorConfiguration[] localConfigs = new ProcessorConfiguration[] { config }; + if (currentAssemblerDef.hasFileSets()) { + TargetMatcher matcher = new TargetMatcher(this, _objDir, + localConfigs, linkerConfig, objectFiles, + targets); + currentAssemblerDef.visitFiles(matcher); + } + biddingProcessors.addElement(config); + } + } + // + // add fallback assembler at the end + // + ProcessorConfiguration config = assemblerDef.createConfiguration(this, + linkType, null, targetPlatform); + biddingProcessors.addElement(config); + ProcessorConfiguration[] bidders = new ProcessorConfiguration[biddingProcessors + .size()]; + biddingProcessors.copyInto(bidders); + TargetMatcher matcher = new TargetMatcher(this, _objDir, bidders, + linkerConfig, objectFiles, targets); + assemblerDef.visitFiles(matcher); + return targets; + } + + /** + * This method collects a Hashtable, keyed by output file name, of + * TargetInfo's for every source file that is specified in the filesets of + * the and nested elements. The TargetInfo's contain the + * appropriate compiler configurations for their possible compilation + * + */ + private Hashtable getTargets(LinkerConfiguration linkerConfig, + Vector objectFiles) { + Hashtable targets = new Hashtable(1000); + TargetDef targetPlatform = getTargetPlatform(); + // + // find active (specialized) compilers + // + Vector biddingProcessors = new Vector(_compilers.size()); + for (int i = 0; i < _compilers.size(); i++) { + CompilerDef currentCompilerDef = (CompilerDef) _compilers + .elementAt(i); + if (currentCompilerDef.isActive()) { + ProcessorConfiguration config = currentCompilerDef + .createConfiguration(this, linkType, + compilerDef, targetPlatform); + // + // see if this processor had a precompile child element + // + PrecompileDef precompileDef = currentCompilerDef + .getActivePrecompile(compilerDef); + ProcessorConfiguration[] localConfigs = new ProcessorConfiguration[] { config }; + // + // if it does then + // + if (precompileDef != null) { + File prototype = precompileDef.getPrototype(); + // + // will throw exceptions if prototype doesn't exist, etc + // + if (!prototype.exists()) { + throw new BuildException("prototype (" + + prototype.toString() + + ") does not exist."); + } + if (prototype.isDirectory()) { + throw new BuildException("prototype (" + + prototype.toString() + + ") is a directory."); + } + String[] exceptFiles = precompileDef.getExceptFiles(); + // + // create a precompile building and precompile using + // variants of the configuration + // or return null if compiler doesn't support + // precompilation + CompilerConfiguration[] configs = ((CompilerConfiguration) config) + .createPrecompileConfigurations(prototype, + exceptFiles); + if (configs != null && configs.length == 2) { + // + // visit the precompiled file to add it into the + // targets list (just like any other file if + // compiler doesn't support precompilation) + TargetMatcher matcher = new TargetMatcher( + this, + _objDir, + new ProcessorConfiguration[] { configs[0] }, + linkerConfig, objectFiles, targets); + matcher.visit(new File(prototype.getParent()), + prototype.getName()); + // + // only the configuration that uses the + // precompiled header gets added to the bidding list + biddingProcessors.addElement(configs[1]); + localConfigs = new ProcessorConfiguration[2]; + localConfigs[0] = configs[1]; + localConfigs[1] = config; + } + } + // + // if the compiler has a fileset + // then allow it to add its files + // to the set of potential targets + if (currentCompilerDef.hasFileSets()) { + TargetMatcher matcher = new TargetMatcher(this, _objDir, + localConfigs, linkerConfig, objectFiles, + targets); + currentCompilerDef.visitFiles(matcher); + } + biddingProcessors.addElement(config); + } + } + // + // add fallback compiler at the end + // + ProcessorConfiguration config = compilerDef.createConfiguration(this, + linkType, null, targetPlatform); + biddingProcessors.addElement(config); + ProcessorConfiguration[] bidders = new ProcessorConfiguration[biddingProcessors + .size()]; + biddingProcessors.copyInto(bidders); + // + // bid out the 's in the cctask + // + TargetMatcher matcher = new TargetMatcher(this, _objDir, bidders, + linkerConfig, objectFiles, targets); + compilerDef.visitFiles(matcher); + return targets; + } + + /** + * Sets the default compiler adapter. Use the "name" attribute when the + * compiler is a supported compiler. + * + * @param classname + * fully qualified classname which implements CompilerAdapter + */ + public void setClassname(String classname) { + compilerDef.setClassname(classname); + linkerDef.setClassname(classname); + assemblerDef.setClassname(classname); + aslcompilerDef.setClassname(classname); + } + + /** + * Sets the dataset for OS/390 builds. + * + * @param dataset + * The dataset to set + */ + public void setDataset(String dataset) { + this.dataset = dataset; + } + + /** + * Enables or disables generation of debug info. + */ + public void setDebug(boolean debug) { + compilerDef.setDebug(debug); + linkerDef.setDebug(debug); + assemblerDef.setDebug(debug); + aslcompilerDef.setDebug(debug); + } + + /** + * Deprecated. + * + * Controls the depth of the dependency evaluation. Used to do a quick check + * of changes before a full build. + * + * Any negative value which will perform full dependency checking. Positive + * values will truncate dependency checking. A value of 0 will cause only + * those files that changed to be recompiled, a value of 1 which cause files + * that changed or that explicitly include a file that changed to be + * recompiled. + * + * Any non-negative value will cause a BuildException to be thrown before + * attempting a link or completing the task. + * + */ + public void setDependencyDepth(int depth) { + dependencyDepth = depth; + } + + /** + * Enables generation of exception handling code + */ + public void setExceptions(boolean exceptions) { + compilerDef.setExceptions(exceptions); + } + + /** + * Enables run-time type information. + */ + public void setRtti(boolean rtti) { + compilerDef.setRtti(rtti); + } + + // public LinkType getLinkType() { + // return linkType; + // } + /** + * Enables or disables incremental linking. + * + * @param incremental + * new state + */ + public void setIncremental(boolean incremental) { + linkerDef.setIncremental(incremental); + } + + /** + * Set use of libtool. + * + * If set to true, the "libtool " will be prepended to the command line for + * compatible processors + * + * @param libtool + * If true, use libtool. + */ + public void setLibtool(boolean libtool) { + compilerDef.setLibtool(libtool); + linkerDef.setLibtool(libtool); + assemblerDef.setLibtool(libtool); + aslcompilerDef.setLibtool(libtool); + } + + /** + * Sets the output file type. Supported values "executable", "shared", and + * "static". Deprecated, specify outtype instead. + * + * @deprecated + */ + public void setLink(OutputTypeEnum outputType) { + linkType.setOutputType(outputType); + } + + /** + * Enables or disables generation of multithreaded code + * + * @param multi + * If true, generated code may be multithreaded. + */ + public void setMultithreaded(boolean multi) { + compilerDef.setMultithreaded(multi); + } + + // + // keep near duplicate comment at CompilerDef.setName in sync + // + /** + * Sets type of the default compiler and linker. + * + * Supported compilers + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
gcc (default)GCC C++ compiler
g++GCC C++ compiler
c++GCC C++ compiler
g77GNU FORTRAN compiler
msvcMicrosoft Visual C++
bccBorland C++ Compiler
msrcMicrosoft Resource Compiler
brcBorland Resource Compiler
dfCompaq Visual Fortran Compiler
midlMicrosoft MIDL Compiler
iclIntel C++ compiler for Windows (IA-32)
eclIntel C++ compiler for Windows (IA-64)
iccIntel C++ compiler for Linux (IA-32)
eccIntel C++ compiler for Linux (IA-64)
CCSun ONE C++ compiler
aCCHP aC++ C++ Compiler
os390OS390 C Compiler
os400Icc Compiler
sunc89Sun C89 C Compiler
xlCVisualAge C Compiler
+ * + */ + public void setName(CompilerEnum name) { + compilerDef.setName(name); + Processor compiler = compilerDef.getProcessor(); + Linker linker = compiler.getLinker(linkType); + linkerDef.setProcessor(linker); + } + + /** + * Do not propagate old environment when new environment variables are + * specified. + */ + public void setNewenvironment(boolean newenv) { + compilerDef.setNewenvironment(newenv); + linkerDef.setNewenvironment(newenv); + assemblerDef.setNewenvironment(newenv); + aslcompilerDef.setNewenvironment(newenv); + } + + /** + * Sets the destination directory for object files. + * + * Generally this should be a property expression that evaluates to distinct + * debug and release object file directories. + * + * @param dir + * object directory + */ + public void setObjdir(File dir) { + if (dir == null) { + throw new NullPointerException("dir"); + } + _objDir = dir; + } + + /** + * Sets the output file name. If not specified, the task will only compile + * files and not attempt to link. If an extension is not specified, the task + * may use a system appropriate extension and prefix, for example, + * outfile="example" may result in "libexample.so" being created. + * + * @param outfile + * output file name + */ + public void setOutfile(File outfile) { + // + // if file name was empty, skip link step + // + if (outfile == null || outfile.toString().length() > 0) { + _outfile = outfile; + } + } + + /** + * Specifies the name of a property to set with the physical filename that + * is produced by the linker + */ + public void setOutputFileProperty(String outputFileProperty) { + this.outputFileProperty = outputFileProperty; + } + + /** + * Sets the output file type. Supported values "executable", "shared", and + * "static". + */ + public void setOuttype(OutputTypeEnum outputType) { + linkType.setOutputType(outputType); + } + + /** + * Sets the project. + */ + public void setProject(Project project) { + super.setProject(project); + compilerDef.setProject(project); + linkerDef.setProject(project); + assemblerDef.setProject(project); + aslcompilerDef.setProject(project); + } + + /** + * If set to true, all files will be rebuilt. + * + * @paran rebuildAll If true, all files will be rebuilt. If false, up to + * date files will not be rebuilt. + */ + public void setRebuild(boolean rebuildAll) { + compilerDef.setRebuild(rebuildAll); + linkerDef.setRebuild(rebuildAll); + assemblerDef.setRebuild(rebuildAll); + aslcompilerDef.setRebuild(rebuildAll); + } + + /** + * If set to true, compilation errors will not stop the task until all files + * have been attempted. + * + * @param relentless + * If true, don't stop on the first compilation error + * + */ + public void setRelentless(boolean relentless) { + this.relentless = relentless; + } + + /** + * Sets the type of runtime library, possible values "dynamic", "static". + */ + public void setRuntime(RuntimeType rtlType) { + linkType.setStaticRuntime((rtlType.getIndex() == 1)); + } + + /** + * Sets the nature of the subsystem under which that the program will + * execute. + * + * Supported subsystems + * + * + * + * + * + * + * + * + * + * + * + * + *
guiGraphical User Interface
consoleCommand Line Console
otherOther
+ * + * @param subsystem + * subsystem + * @throws NullPointerException + * if subsystem is null + */ + public void setSubsystem(SubsystemEnum subsystem) { + if (subsystem == null) { + throw new NullPointerException("subsystem"); + } + linkType.setSubsystem(subsystem); + } + + /** + * Enumerated attribute with the values "none", "severe", "default", + * "production", "diagnostic", and "failtask". + */ + public void setWarnings(CompilerDef.WarningLevel level) { + compilerDef.setWarnings(level); + } + + /** + * Indicates whether the build will continue even if there are compilation + * errors; defaults to true. + * + * @param fail + * if true halt the build on failure + */ + public void setFailonerror(boolean fail) { + failOnError = fail; + } + + /** + * Gets the failonerror flag. + * + * @return the failonerror flag + */ + public boolean getFailonerror() { + return failOnError; + } + + /** + * Adds descriptive version information to be included in the generated + * file. The first active version info block will be used. (Non-functional + * prototype) + */ + public void addConfiguredVersioninfo(VersionInfo info) { + linkerDef.addConfiguredVersioninfo(info); + } + + /** + * Adds a target definition or reference (Non-functional prototype). + * + * @param target + * target + * @throws NullPointerException + * if compiler is null + */ + public void addConfiguredTarget(TargetDef target) { + if (target == null) { + throw new NullPointerException("target"); + } + target.setProject(getProject()); + targetPlatforms.addElement(target); + } + + /** + * Adds a distributer definition or reference (Non-functional prototype). + * + * @param distributer + * distributer + * @throws NullPointerException + * if compiler is null + */ + public void addConfiguredDistributer(DistributerDef distributer) { + if (distributer == null) { + throw new NullPointerException("distributer"); + } + distributer.setProject(getProject()); + distributers.addElement(distributer); + } + + /** + * Sets optimization. + * @param optimization + */ + public void setOptimize(OptimizationEnum optimization) { + compilerDef.setOptimize(optimization); + } + + public boolean isAssembler() { + return assembler; + } + + public void setAssembler(boolean assembler) { + this.assembler = assembler; + } + + public boolean isAslcompiler() { + return aslcompiler; + } + + public void setAslcompiler(boolean aslcompiler) { + this.aslcompiler = aslcompiler; + } + + public boolean isUserdefine() { + return userdefine; + } + + public void setUserdefine(boolean userdefine) { + this.userdefine = userdefine; + } + + public String getArch() { + return arch; + } + + public void setArch(String arch) { + this.arch = arch; + } + + public String getOs() { + return os; + } + + public void setOs(String os) { + this.os = os; + } + + public String getVendor() { + return vendor; + } + + public void setVendor(String vendor) { + this.vendor = vendor; + } + + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CCTaskProgressMonitor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CCTaskProgressMonitor.java new file mode 100644 index 0000000000..78192a5ba7 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CCTaskProgressMonitor.java @@ -0,0 +1,56 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.IOException; + +import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; +import net.sf.antcontrib.cpptasks.compiler.ProgressMonitor; +public class CCTaskProgressMonitor implements ProgressMonitor { + private ProcessorConfiguration config; + private TargetHistoryTable history; + private long lastCommit = -1; + public CCTaskProgressMonitor(TargetHistoryTable history) { + this.history = history; + } + public void finish(ProcessorConfiguration config, boolean normal) { + long current = System.currentTimeMillis(); + if ((current - lastCommit) > 120000) { + try { + history.commit(); + lastCommit = System.currentTimeMillis(); + } catch (IOException ex) { + } + } + } + public void progress(String[] sources) { + history.update(config, sources); + long current = System.currentTimeMillis(); + if ((current - lastCommit) > 120000) { + try { + history.commit(); + lastCommit = current; + } catch (IOException ex) { + } + } + } + public void start(ProcessorConfiguration config) { + if (lastCommit < 0) { + lastCommit = System.currentTimeMillis(); + } + this.config = config; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CPUEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CPUEnum.java new file mode 100644 index 0000000000..ba73902361 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CPUEnum.java @@ -0,0 +1,71 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import org.apache.tools.ant.types.EnumeratedAttribute; + +/** + * Enumeration of cpu types. + * + * @author Curt Arnold + * + */ +public final class CPUEnum + extends EnumeratedAttribute { + + /** + * Constructor. + * + * Set by default to "pentium3" + * + * @see java.lang.Object#Object() + */ + public CPUEnum() { + setValue("pentium3"); + } + + /** + * Gets list of acceptable values. + * + * @see org.apache.tools.ant.types.EnumeratedAttribute#getValues() + */ + public String[] getValues() { + return new String[] { + "i386", + "i486", + "i586", + "i686", + "pentium", + "pentium-mmx", + "pentiumpro", + "pentium2", + "pentium3", + "pentium4", + "k6", + "k6-2", + "k6-3", + "athlon", + "athlon-tbird", + "athlon-4", + "athlon-xp", + "athlon-mp", + "winchip-c6", + "winchip2", + "c3" }; + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CUtil.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CUtil.java new file mode 100644 index 0000000000..074e8b42f8 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CUtil.java @@ -0,0 +1,461 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.StringTokenizer; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.types.Environment; +/** + * Some utilities used by the CC and Link tasks. + * + * @author Adam Murdoch + */ +public class CUtil { + /** + * A class that splits a white-space, comma-separated list into a String + * array. Used for task attributes. + */ + public static final class StringArrayBuilder { + private String[] _value; + public StringArrayBuilder(String value) { + // Split the defines up + StringTokenizer tokens = new StringTokenizer(value, ", "); + Vector vallist = new Vector(); + while (tokens.hasMoreTokens()) { + String val = tokens.nextToken().trim(); + if (val.length() == 0) { + continue; + } + vallist.addElement(val); + } + _value = new String[vallist.size()]; + vallist.copyInto(_value); + } + public String[] getValue() { + return _value; + } + } + /** + * Adds the elements of the array to the given vector + */ + public static void addAll(Vector dest, Object[] src) { + if (src == null) { + return; + } + for (int i = 0; i < src.length; i++) { + dest.addElement(src[i]); + } + } + /** + * Checks a array of names for non existent or non directory entries and + * nulls them out. + * + * @return Count of non-null elements + */ + public static int checkDirectoryArray(String[] names) { + int count = 0; + for (int i = 0; i < names.length; i++) { + if (names[i] != null) { + File dir = new File(names[i]); + if (dir.exists() && dir.isDirectory()) { + count++; + } else { + names[i] = null; + } + } + } + return count; + } + /** + * Extracts the basename of a file, removing the extension, if present + */ + public static String getBasename(File file) { + String path = file.getPath(); + // Remove the extension + String basename = file.getName(); + int pos = basename.lastIndexOf('.'); + if (pos != -1) { + basename = basename.substring(0, pos); + } + return basename; + } + /** + * Gets the parent directory for the executable file name using the current + * directory and system executable path + * + * @param exeName + * Name of executable such as "cl.exe" + * @return parent directory or null if not located + */ + public static File getExecutableLocation(String exeName) { + // + // must add current working directory to the + // from of the path from the "path" environment variable + File currentDir = new File(System.getProperty("user.dir")); + if (new File(currentDir, exeName).exists()) { + return currentDir; + } + File[] envPath = CUtil.getPathFromEnvironment("PATH", + File.pathSeparator); + for (int i = 0; i < envPath.length; i++) { + if (new File(envPath[i], exeName).exists()) { + return envPath[i]; + } + } + return null; + } + /** + * Extracts the parent of a file + */ + public static String getParentPath(String path) { + int pos = path.lastIndexOf(File.separator); + if (pos <= 0) { + return null; + } + return path.substring(0, pos); + } + /** + * Returns an array of File for each existing directory in the specified + * environment variable + * + * @param envVariable + * environment variable name such as "LIB" or "INCLUDE" + * @param delim + * delimitor used to separate parts of the path, typically ";" + * or ":" + * @return array of File's for each part that is an existing directory + */ + public static File[] getPathFromEnvironment(String envVariable, String delim) { + // OS/4000 does not support the env command. + if (System.getProperty("os.name").equals("OS/400")) + return new File[]{}; + Vector osEnv = Execute.getProcEnvironment(); + String match = envVariable.concat("="); + for (Enumeration e = osEnv.elements(); e.hasMoreElements();) { + String entry = ((String) e.nextElement()).trim(); + if (entry.length() > match.length()) { + String entryFrag = entry.substring(0, match.length()); + if (entryFrag.equalsIgnoreCase(match)) { + String path = entry.substring(match.length()); + return parsePath(path, delim); + } + } + } + File[] noPath = new File[0]; + return noPath; + } + /** + * Returns a relative path for the targetFile relative to the base + * directory. + * + * @param canonicalBase + * base directory as returned by File.getCanonicalPath() + * @param targetFile + * target file + * @return relative path of target file. Returns targetFile if there were + * no commonalities between the base and the target + * + * @author Curt Arnold + */ + public static String getRelativePath(String base, File targetFile) { + try { + // + // remove trailing file separator + // + String canonicalBase = base; + if (base.charAt(base.length() - 1) == File.separatorChar) { + canonicalBase = base.substring(0, base.length() - 1); + } + // + // get canonical name of target and remove trailing separator + // + String canonicalTarget; + if (System.getProperty("os.name").equals("OS/400")) + canonicalTarget = targetFile.getPath(); + else + canonicalTarget = targetFile.getCanonicalPath(); + if (canonicalTarget.charAt(canonicalTarget.length() - 1) == File.separatorChar) { + canonicalTarget = canonicalTarget.substring(0, canonicalTarget + .length() - 1); + } + if (canonicalTarget.equals(canonicalBase)) { + return "."; + } + // + // see if the prefixes are the same + // + if (canonicalBase.substring(0, 2).equals("\\\\")) { + // + // UNC file name, if target file doesn't also start with same + // server name, don't go there + int endPrefix = canonicalBase.indexOf('\\', 2); + String prefix1 = canonicalBase.substring(0, endPrefix); + String prefix2 = canonicalTarget.substring(0, endPrefix); + if (!prefix1.equals(prefix2)) { + return canonicalTarget; + } + } else { + if (canonicalBase.substring(1, 3).equals(":\\")) { + int endPrefix = 2; + String prefix1 = canonicalBase.substring(0, endPrefix); + String prefix2 = canonicalTarget.substring(0, endPrefix); + if (!prefix1.equals(prefix2)) { + return canonicalTarget; + } + } else { + if (canonicalBase.charAt(0) == '/') { + if (canonicalTarget.charAt(0) != '/') { + return canonicalTarget; + } + } + } + } + char separator = File.separatorChar; + int lastSeparator = -1; + int minLength = canonicalBase.length(); + if (canonicalTarget.length() < minLength) { + minLength = canonicalTarget.length(); + } + int firstDifference = minLength + 1; + // + // walk to the shorter of the two paths + // finding the last separator they have in common + for (int i = 0; i < minLength; i++) { + if (canonicalTarget.charAt(i) == canonicalBase.charAt(i)) { + if (canonicalTarget.charAt(i) == separator) { + lastSeparator = i; + } + } else { + firstDifference = lastSeparator + 1; + break; + } + } + StringBuffer relativePath = new StringBuffer(50); + // + // walk from the first difference to the end of the base + // adding "../" for each separator encountered + // + if (canonicalBase.length() > firstDifference) { + relativePath.append(".."); + for (int i = firstDifference; i < canonicalBase.length(); i++) { + if (canonicalBase.charAt(i) == separator) { + relativePath.append(separator); + relativePath.append(".."); + } + } + } + if (canonicalTarget.length() > firstDifference) { + // + // append the rest of the target + // + // + if (relativePath.length() > 0) { + relativePath.append(separator); + } + relativePath.append(canonicalTarget.substring(firstDifference)); + } + return relativePath.toString(); + } catch (IOException ex) { + } + return targetFile.toString(); + } + public static boolean isActive(Project p, String ifCond, String unlessCond) + throws BuildException { + if (ifCond != null) { + String ifValue = p.getProperty(ifCond); + if (ifValue == null) { + return false; + } else { + if (ifValue.equals("false") || ifValue.equals("no")) { + throw new BuildException("if condition \"" + ifCond + + "\" has suspicious value \"" + ifValue); + } + } + } + if (unlessCond != null) { + String unlessValue = p.getProperty(unlessCond); + if (unlessValue != null) { + if (unlessValue.equals("false") || unlessValue.equals("no")) { + throw new BuildException("unless condition \"" + unlessCond + + "\" has suspicious value \"" + unlessValue); + } + return false; + } + } + return true; + } + /** + * Parse a string containing directories into an File[] + * + * @param path + * path string, for example ".;c:\something\include" + * @param delim + * delimiter, typically ; or : + */ + public static File[] parsePath(String path, String delim) { + Vector libpaths = new Vector(); + int delimPos = 0; + for (int startPos = 0; startPos < path.length(); startPos = delimPos + + delim.length()) { + delimPos = path.indexOf(delim, startPos); + if (delimPos < 0) { + delimPos = path.length(); + } + // + // don't add an entry for zero-length paths + // + if (delimPos > startPos) { + String dirName = path.substring(startPos, delimPos); + File dir = new File(dirName); + if (dir.exists() && dir.isDirectory()) { + libpaths.addElement(dir); + } + } + } + File[] paths = new File[libpaths.size()]; + libpaths.copyInto(paths); + return paths; + } + /** + * This method is exposed so test classes can overload and test the + * arguments without actually spawning the compiler + */ + public static int runCommand(CCTask task, File workingDir, + String[] cmdline, boolean newEnvironment, Environment env) + throws BuildException { + try { + task.log(Commandline.toString(cmdline), Project.MSG_VERBOSE); + Execute exe = new Execute(new LogStreamHandler(task, + Project.MSG_INFO, Project.MSG_ERR)); + if (System.getProperty("os.name").equals("OS/390")) + exe.setVMLauncher(false); + exe.setAntRun(task.getProject()); + exe.setCommandline(cmdline); + exe.setWorkingDirectory(workingDir); + if (env != null) { + String[] environment = env.getVariables(); + if (environment != null) { + for (int i = 0; i < environment.length; i++) { + task.log("Setting environment variable: " + + environment[i], Project.MSG_VERBOSE); + } + } + exe.setEnvironment(environment); + } + exe.setNewenvironment(newEnvironment); + return exe.execute(); + } catch (java.io.IOException exc) { + throw new BuildException("Could not launch " + cmdline[0] + ": " + + exc, task.getLocation()); + } + } + /** + * Compares the contents of 2 arrays for equaliy. + */ + public static boolean sameList(Object[] a, Object[] b) { + if (a == null || b == null || a.length != b.length) { + return false; + } + for (int i = 0; i < a.length; i++) { + if (!a[i].equals(b[i])) { + return false; + } + } + return true; + } + /** + * Compares the contents of an array and a Vector for equality. + */ + public static boolean sameList(Vector v, Object[] a) { + if (v == null || a == null || v.size() != a.length) { + return false; + } + for (int i = 0; i < a.length; i++) { + Object o = a[i]; + if (!o.equals(v.elementAt(i))) { + return false; + } + } + return true; + } + /** + * Compares the contents of an array and a Vector for set equality. Assumes + * input array and vector are sets (i.e. no duplicate entries) + */ + public static boolean sameSet(Object[] a, Vector b) { + if (a == null || b == null || a.length != b.size()) { + return false; + } + if (a.length == 0) { + return true; + } + // Convert the array into a set + Hashtable t = new Hashtable(); + for (int i = 0; i < a.length; i++) { + t.put(a[i], a[i]); + } + for (int i = 0; i < b.size(); i++) { + Object o = b.elementAt(i); + if (t.remove(o) == null) { + return false; + } + } + return (t.size() == 0); + } + /** + * Converts a vector to a string array. + */ + public static String[] toArray(Vector src) { + String[] retval = new String[src.size()]; + src.copyInto(retval); + return retval; + } + /** + * Replaces any embedded quotes in the string so that the value can be + * placed in an attribute in an XML file + * + * @param attrValue + * value to be expressed + * @return equivalent attribute literal + * + */ + public static String xmlAttribEncode(String attrValue) { + int quotePos = attrValue.indexOf('\"'); + if (quotePos < 0) { + return attrValue; + } + int startPos = 0; + StringBuffer buf = new StringBuffer(attrValue.length() + 20); + while (quotePos >= 0) { + buf.append(attrValue.substring(startPos, quotePos)); + buf.append("""); + startPos = quotePos + 1; + quotePos = attrValue.indexOf('\"', startPos); + } + buf.append(attrValue.substring(startPos)); + return buf.toString(); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CompilerDef.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CompilerDef.java new file mode 100644 index 0000000000..0a92a51512 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CompilerDef.java @@ -0,0 +1,556 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.Enumeration; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler; +import net.sf.antcontrib.cpptasks.compiler.Compiler; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.gcc.GccCCompiler; +import net.sf.antcontrib.cpptasks.types.CompilerArgument; +import net.sf.antcontrib.cpptasks.types.ConditionalPath; +import net.sf.antcontrib.cpptasks.types.DefineSet; +import net.sf.antcontrib.cpptasks.types.IncludePath; +import net.sf.antcontrib.cpptasks.types.SystemIncludePath; +import net.sf.antcontrib.cpptasks.types.UndefineArgument; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.*; +/** + * A compiler definition. compiler elements may be placed either as children of + * a cc element or the project element. A compiler element with an id attribute + * may be referenced from compiler elements with refid or extends attributes. + * + * @author Adam Murdoch + */ +public final class CompilerDef extends ProcessorDef { + /** + * Enumerated attribute with the values "none", "severe", "default", + * "production", "diagnostic", and "failtask". + */ + public static class WarningLevel extends EnumeratedAttribute { + public String[] getValues() { + return new String[]{"none", "severe", "default", "production", + "diagnostic", "aserror"}; + } + } + /** The source file sets. */ + private final Vector defineSets = new Vector(); + private Boolean exceptions; + private Boolean rtti; + private final Vector includePaths = new Vector(); + private Boolean multithreaded; + private final Vector precompileDefs = new Vector(); + private final Vector sysIncludePaths = new Vector(); + private OptimizationEnum optimization; + private int warnings = -1; + private Boolean defaultflag = new Boolean(true); + public CompilerDef() { + } + /** + * Adds a compiler command-line arg. + */ + public void addConfiguredCompilerArg(CompilerArgument arg) { + if (isReference()) { + throw noChildrenAllowed(); + } + addConfiguredProcessorArg(arg); + } + /** + * Adds a compiler command-line arg. + */ + public void addConfiguredCompilerParam(CompilerParam param) { + if (isReference()) { + throw noChildrenAllowed(); + } + addConfiguredProcessorParam(param); + } + /** + * Adds a defineset. + */ + public void addConfiguredDefineset(DefineSet defs) { + if (defs == null) { + throw new NullPointerException("defs"); + } + if (isReference()) { + throw noChildrenAllowed(); + } + defineSets.addElement(defs); + } + /** + * Creates an include path. + */ + public IncludePath createIncludePath() { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project must be set"); + } + if (isReference()) { + throw noChildrenAllowed(); + } + IncludePath path = new IncludePath(p); + includePaths.addElement(path); + return path; + } + /** + * Add a or if specify the file + * attribute + * + * @throws BuildException + * if the specify file not exist + */ + protected void loadFile(Vector activePath,File file) throws BuildException { + FileReader fileReader; + BufferedReader in; + String str; + if (! file.exists()){ + throw new BuildException("The file " + file + " is not existed"); + } + try { + fileReader = new FileReader(file); + in = new BufferedReader(fileReader); + while ( (str = in.readLine()) != null ){ + if(str.trim() == ""){ + continue ; + } + str = getProject().replaceProperties(str); + activePath.addElement(str.trim()); + } + } + catch(Exception e){ + throw new BuildException(e.getMessage()); + } + } + + /** + * Specifies precompilation prototype file and exclusions. + * + */ + public PrecompileDef createPrecompile() throws BuildException { + Project p = getProject(); + if (isReference()) { + throw noChildrenAllowed(); + } + PrecompileDef precomp = new PrecompileDef(); + precomp.setProject(p); + precompileDefs.addElement(precomp); + return precomp; + } + /** + * Creates a system include path. Locations and timestamps of files located + * using the system include paths are not used in dependency analysis. + * + * + * Standard include locations should not be specified. The compiler + * adapters should recognized the settings from the appropriate environment + * variables or configuration files. + */ + public SystemIncludePath createSysIncludePath() { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project must be set"); + } + if (isReference()) { + throw noChildrenAllowed(); + } + SystemIncludePath path = new SystemIncludePath(p); + sysIncludePaths.addElement(path); + return path; + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + public UndefineArgument[] getActiveDefines() { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException( + "project must be set before this call"); + } + if (isReference()) { + return ((CompilerDef) getCheckedRef(CompilerDef.class, + "CompilerDef")).getActiveDefines(); + } + Vector actives = new Vector(); + for (int i = 0; i < defineSets.size(); i++) { + DefineSet currentSet = (DefineSet) defineSets.elementAt(i); + UndefineArgument[] defines = currentSet.getDefines(); + for (int j = 0; j < defines.length; j++) { + if (defines[j].isActive(p)) { + actives.addElement(defines[j]); + } + } + } + UndefineArgument[] retval = new UndefineArgument[actives.size()]; + actives.copyInto(retval); + return retval; + } + /** + * Returns the compiler-specific include path. + */ + public String[] getActiveIncludePaths() { + if (isReference()) { + return ((CompilerDef) getCheckedRef(CompilerDef.class, + "CompilerDef")).getActiveIncludePaths(); + } + return getActivePaths(includePaths); + } + private String[] getActivePaths(Vector paths) { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project not set"); + } + Vector activePaths = new Vector(paths.size()); + for (int i = 0; i < paths.size(); i++) { + ConditionalPath path = (ConditionalPath) paths.elementAt(i); + if (path.isActive(p)) { + if (path.getFile() == null) { + String[] pathEntries = path.list(); + for (int j = 0; j < pathEntries.length; j++) { + activePaths.addElement(pathEntries[j]); + } + } + else { + loadFile(activePaths, path.getFile()); + } + } + } + String[] pathNames = new String[activePaths.size()]; + activePaths.copyInto(pathNames); + return pathNames; + } + public PrecompileDef getActivePrecompile(CompilerDef ccElement) { + if (isReference()) { + return ((CompilerDef) getCheckedRef(CompilerDef.class, + "CompilerDef")).getActivePrecompile(ccElement); + } + PrecompileDef current = null; + Enumeration enumPrecompilerDef = precompileDefs.elements(); + while (enumPrecompilerDef.hasMoreElements()) { + current = (PrecompileDef) enumPrecompilerDef.nextElement(); + if (current.isActive()) { + return current; + } + } + CompilerDef extendedDef = (CompilerDef) getExtends(); + if (extendedDef != null) { + current = extendedDef.getActivePrecompile(null); + if (current != null) { + return current; + } + } + if (ccElement != null && getInherit()) { + return ccElement.getActivePrecompile(null); + } + return null; + } + public String[] getActiveSysIncludePaths() { + if (isReference()) { + return ((CompilerDef) getCheckedRef(CompilerDef.class, + "CompilerDef")).getActiveSysIncludePaths(); + } + return getActivePaths(sysIncludePaths); + } + public final boolean getExceptions(CompilerDef[] defaultProviders, int index) { + if (isReference()) { + return ((CompilerDef) getCheckedRef(CompilerDef.class, + "CompilerDef")).getExceptions(defaultProviders, index); + } + if (exceptions != null) { + return exceptions.booleanValue(); + } else { + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getExceptions(defaultProviders, + index + 1); + } + } + return false; + } + public final Boolean getRtti(CompilerDef[] defaultProviders, int index) { + if (isReference()) { + return ((CompilerDef) getCheckedRef(CompilerDef.class, + "CompilerDef")).getRtti(defaultProviders, index); + } + if (rtti != null) { + return rtti; + } else { + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getRtti(defaultProviders, + index + 1); + } + } + return null; + } + public final Boolean getDefaultflag(CompilerDef[] defaultProviders, int index) { + if (isReference()) { + return ((CompilerDef) getCheckedRef(CompilerDef.class, + "CompilerDef")).getDefaultflag(defaultProviders, index); + } + return defaultflag; + } + public final OptimizationEnum getOptimization(CompilerDef[] defaultProviders, int index) { + if (isReference()) { + return ((CompilerDef) getCheckedRef(CompilerDef.class, + "CompilerDef")).getOptimization(defaultProviders, index); + } + if (optimization != null) { + return optimization; + } else { + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getOptimization(defaultProviders, + index + 1); + } + } + return null; + } + + public boolean getMultithreaded(CompilerDef[] defaultProviders, int index) { + if (isReference()) { + return ((CompilerDef) getCheckedRef(CompilerDef.class, + "CompilerDef")).getMultithreaded(defaultProviders, index); + } + if (multithreaded != null) { + return multithreaded.booleanValue(); + } else { + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getMultithreaded( + defaultProviders, index + 1); + } + } + return true; + } + public Processor getProcessor() { + Processor processor = super.getProcessor(); + if (processor == null) { + processor = GccCCompiler.getInstance(); + } + if (getLibtool() && processor instanceof CommandLineCompiler) { + CommandLineCompiler compiler = (CommandLineCompiler) processor; + processor = compiler.getLibtoolCompiler(); + } + return processor; + } + public int getWarnings(CompilerDef[] defaultProviders, int index) { + if (isReference()) { + return ((CompilerDef) getCheckedRef(CompilerDef.class, + "CompilerDef")).getWarnings(defaultProviders, index); + } + if (warnings == -1) { + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getWarnings(defaultProviders, + index + 1); + } + } + return warnings; + } + /** + * Sets the default compiler adapter. Use the "name" attribute when the + * compiler is a supported compiler. + * + * @param classname + * fully qualified classname which implements CompilerAdapter + */ + public void setClassname(String classname) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + super.setClassname(classname); + Processor proc = getProcessor(); + if (!(proc instanceof Compiler)) { + throw new BuildException(classname + " does not implement Compiler"); + } + } + /** + * Enables or disables exception support. + * + * @param exceptions + * if true, exceptions are supported. + * + */ + public void setExceptions(boolean exceptions) { + if (isReference()) { + throw tooManyAttributes(); + } + this.exceptions = booleanValueOf(exceptions); + } + + /** + * Enables or disables run-time type information. + * + * @param rtti + * if true, run-time type information is supported. + * + */ + public void setRtti(boolean rtti) { + if (isReference()) { + throw tooManyAttributes(); + } + this.rtti = booleanValueOf(rtti); + } + + /** + * Enables or disables generation of multithreaded code. Unless specified, + * multithreaded code generation is enabled. + * + * @param multi + * If true, generated code may be multithreaded. + */ + public void setMultithreaded(boolean multithreaded) { + if (isReference()) { + throw tooManyAttributes(); + } + this.multithreaded = booleanValueOf(multithreaded); + } + /** + * Sets compiler type. + * + * + * Supported compilers + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
gcc (default)GCC C++ compiler
g++GCC C++ compiler
c++GCC C++ compiler
g77GNU Fortran compiler
msvcMicrosoft Visual C++
bccBorland C++ Compiler
msrcMicrosoft Resource Compiler
brcBorland Resource Compiler
dfCompaq Visual Fortran Compiler
midlMicrosoft MIDL Compiler
iclIntel C++ compiler for Windows (IA-32)
eclIntel C++ compiler for Windows (IA-64)
iccIntel C++ compiler for Linux (IA-32)
eccIntel C++ compiler for Linux (IA-64)
CCSun ONE C++ compiler
aCCHP aC++ C++ Compiler
os390OS390 C Compiler
os400Icc Compiler
sunc89Sun C89 C Compiler
xlCVisualAge C Compiler
+ * + */ + public void setName(CompilerEnum name) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + Compiler compiler = name.getCompiler(); + setProcessor(compiler); + } + protected void setProcessor(Processor proc) throws BuildException { + try { + super.setProcessor((Compiler) proc); + } catch (ClassCastException ex) { + throw new BuildException(ex); + } + } + /** + * Enumerated attribute with the values "none", "severe", "default", + * "production", "diagnostic", and "failtask". + */ + public void setWarnings(CompilerDef.WarningLevel level) { + warnings = level.getIndex(); + } + /** + * Sets optimization level. + * + * @param value optimization level + */ + public void setOptimize(OptimizationEnum value) { + if (isReference()) { + throw tooManyAttributes(); + } + this.optimization = value; + } + /** + * Enables or disables default flags. + * + * @param defaultflag + * if true, default flags will add to command line. + * + */ + public void setDefaultflag(boolean defaultflag) { + if (isReference()) { + throw tooManyAttributes(); + } + this.defaultflag = booleanValueOf(defaultflag); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CompilerEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CompilerEnum.java new file mode 100644 index 0000000000..a017243522 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CompilerEnum.java @@ -0,0 +1,221 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import net.sf.antcontrib.cpptasks.arm.ADSCCompiler; +import net.sf.antcontrib.cpptasks.borland.BorlandCCompiler; +import net.sf.antcontrib.cpptasks.borland.BorlandResourceCompiler; +import net.sf.antcontrib.cpptasks.compaq.CompaqVisualFortranCompiler; +import net.sf.antcontrib.cpptasks.compiler.Compiler; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioCCompiler; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioMIDLCompiler; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioResourceCompiler; +import net.sf.antcontrib.cpptasks.gcc.GccCCompiler; +import net.sf.antcontrib.cpptasks.hp.aCCCompiler; +import net.sf.antcontrib.cpptasks.ibm.VisualAgeCCompiler; +import net.sf.antcontrib.cpptasks.intel.IntelLinux32CCompiler; +import net.sf.antcontrib.cpptasks.intel.IntelLinux64CCompiler; +import net.sf.antcontrib.cpptasks.intel.IntelWin32CCompiler; +import net.sf.antcontrib.cpptasks.intel.IntelWin64CCompiler; +import net.sf.antcontrib.cpptasks.os390.OS390CCompiler; +import net.sf.antcontrib.cpptasks.os400.IccCompiler; +import net.sf.antcontrib.cpptasks.sun.C89CCompiler; +import net.sf.antcontrib.cpptasks.sun.ForteCCCompiler; +import net.sf.antcontrib.cpptasks.ti.ClxxCCompiler; + +import org.apache.tools.ant.types.EnumeratedAttribute; +/** + * Enumeration of supported compilers + * + * Supported compilers + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
gcc (default)GCC C++ compiler
g++GCC C++ compiler
c++GCC C++ compiler
g77GNU FORTRAN compiler
msvcMicrosoft Visual C++
bccBorland C++ Compiler
msrcMicrosoft Resource Compiler
brcBorland Resource Compiler
dfCompaq Visual Fortran Compiler
midlMicrosoft MIDL Compiler
iclIntel C++ compiler for Windows (IA-32)
eclIntel C++ compiler for Windows (IA-64)
iccIntel C++ compiler for Linux (IA-32)
eccIntel C++ compiler for Linux (IA-64)
CCSun ONE C++ compiler
aCCHP aC++ C++ Compiler
os390OS390 C Compiler
os400Icc Compiler
sunc89Sun C89 C Compiler
xlCVisualAge C Compiler
cl6xTI TMS320C6000 Optimizing Compiler
cl55TI TMS320C55x Optimizing C/C++ Compiler
armcppARM 32-bit C++ compiler
armccARM 32-bit C compiler
tcppARM 16-bit C++ compiler
tccARM 16-bit C compiler
+ * + * @author Curt Arnold + * + */ +public class CompilerEnum extends EnumeratedAttribute { + private final static ProcessorEnumValue[] compilers = new ProcessorEnumValue[]{ + new ProcessorEnumValue("gcc", GccCCompiler.getInstance()), + new ProcessorEnumValue("g++", GccCCompiler.getGppInstance()), + new ProcessorEnumValue("c++", GccCCompiler.getCppInstance()), + new ProcessorEnumValue("g77", GccCCompiler.getG77Instance()), + new ProcessorEnumValue("msvc", DevStudioCCompiler.getInstance()), + new ProcessorEnumValue("bcc", BorlandCCompiler.getInstance()), + new ProcessorEnumValue("msrc", DevStudioResourceCompiler + .getInstance()), + new ProcessorEnumValue("brc", BorlandResourceCompiler.getInstance()), + new ProcessorEnumValue("df", CompaqVisualFortranCompiler + .getInstance()), + new ProcessorEnumValue("midl", DevStudioMIDLCompiler.getInstance()), + new ProcessorEnumValue("icl", IntelWin32CCompiler.getInstance()), + new ProcessorEnumValue("ecl", IntelWin64CCompiler.getInstance()), + new ProcessorEnumValue("icc", IntelLinux32CCompiler.getInstance()), + new ProcessorEnumValue("ecc", IntelLinux64CCompiler.getInstance()), + new ProcessorEnumValue("CC", ForteCCCompiler.getInstance()), + new ProcessorEnumValue("aCC", aCCCompiler.getInstance()), + new ProcessorEnumValue("os390", OS390CCompiler.getInstance()), + new ProcessorEnumValue("os400", IccCompiler.getInstance()), + new ProcessorEnumValue("sunc89", C89CCompiler.getInstance()), + new ProcessorEnumValue("xlC", VisualAgeCCompiler.getInstance()), + new ProcessorEnumValue("cl6x", ClxxCCompiler.getCl6xInstance()), + new ProcessorEnumValue("cl55", ClxxCCompiler.getCl55Instance()), + new ProcessorEnumValue("armcc", ADSCCompiler.getArmCC()), + new ProcessorEnumValue("armcpp", ADSCCompiler.getArmCpp()), + new ProcessorEnumValue("tcc", ADSCCompiler.getThumbCC()), + new ProcessorEnumValue("tcpp", ADSCCompiler.getThumbCpp()), + // userdefined + //new ProcessorEnumValue("userdefine", UserdefineCompiler.getInstance()), + // GCC Cross Compilers + new ProcessorEnumValue( + "sparc-sun-solaris2-gcc", + net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2.GccCCompiler + .getInstance()), + new ProcessorEnumValue( + "sparc-sun-solaris2-g++", + net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2.GccCCompiler + .getGppInstance()), + new ProcessorEnumValue( + "sparc-sun-solaris2-c++", + net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2.GccCCompiler + .getCppInstance()), + new ProcessorEnumValue( + "sparc-sun-solaris2-g77", + net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2.GccCCompiler + .getG77Instance()), + // GCC Cross Compilers + new ProcessorEnumValue("gcc-cross", + net.sf.antcontrib.cpptasks.gcc.cross.GccCCompiler + .getInstance()), + new ProcessorEnumValue("g++-cross", + net.sf.antcontrib.cpptasks.gcc.cross.GccCCompiler + .getGppInstance()), + new ProcessorEnumValue("c++-cross", + net.sf.antcontrib.cpptasks.gcc.cross.GccCCompiler + .getCppInstance()), + new ProcessorEnumValue("g77-cross", + net.sf.antcontrib.cpptasks.gcc.cross.GccCCompiler + .getG77Instance()),}; + public Compiler getCompiler() { + return (Compiler) compilers[getIndex()].getProcessor(); + } + public String[] getValues() { + return ProcessorEnumValue.getValues(compilers); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CompilerParam.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CompilerParam.java new file mode 100644 index 0000000000..82eb6ee425 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/CompilerParam.java @@ -0,0 +1,33 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +/******************************************************************************* + * Place class description here. + * + * @author inger + * @author + * + * @since + ******************************************************************************/ +public class CompilerParam extends ProcessorParam { + public CompilerParam() { + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DependencyInfo.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DependencyInfo.java new file mode 100644 index 0000000000..429d2b0107 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DependencyInfo.java @@ -0,0 +1,86 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.util.Vector; +/** + * @author Curt Arnold + */ +public final class DependencyInfo { + /** + * Last modified time of this file or anything that it depends on. + * + * Not persisted since almost any change could invalidate it. Initialized + * to long.MIN_VALUE on construction. + */ + private long compositeLastModified; + private/* final */String includePathIdentifier; + private/* final */String[] includes; + private/* final */String source; + private/* final */long sourceLastModified; + private/* final */String[] sysIncludes; + public DependencyInfo(String includePathIdentifier, String source, + long sourceLastModified, Vector includes, Vector sysIncludes) { + if (source == null) { + throw new NullPointerException("source"); + } + if (includePathIdentifier == null) { + throw new NullPointerException("includePathIdentifier"); + } + this.source = source; + this.sourceLastModified = sourceLastModified; + this.includePathIdentifier = includePathIdentifier; + this.includes = new String[includes.size()]; + if (includes.size() == 0) { + compositeLastModified = sourceLastModified; + } else { + includes.copyInto(this.includes); + compositeLastModified = Long.MIN_VALUE; + } + this.sysIncludes = new String[sysIncludes.size()]; + sysIncludes.copyInto(this.sysIncludes); + } + /** + * Returns the latest modification date of the source or anything that it + * depends on. + * + * @returns the composite lastModified time, returns Long.MIN_VALUE if not + * set + */ + public long getCompositeLastModified() { + return compositeLastModified; + } + public String getIncludePathIdentifier() { + return includePathIdentifier; + } + public String[] getIncludes() { + String[] includesClone = (String[]) includes.clone(); + return includesClone; + } + public String getSource() { + return source; + } + public long getSourceLastModified() { + return sourceLastModified; + } + public String[] getSysIncludes() { + String[] sysIncludesClone = (String[]) sysIncludes.clone(); + return sysIncludesClone; + } + public void setCompositeLastModified(long lastMod) { + compositeLastModified = lastMod; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DependencyTable.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DependencyTable.java new file mode 100644 index 0000000000..3cbee7a625 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DependencyTable.java @@ -0,0 +1,609 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; +import net.sf.antcontrib.cpptasks.compiler.CompilerConfiguration; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; +/** + * @author Curt Arnold + */ +public final class DependencyTable { + /** + * This class handles populates the TargetHistory hashtable in response to + * SAX parse events + */ + private class DependencyTableHandler extends DefaultHandler { + private File baseDir; + private final DependencyTable dependencyTable; + private String includePath; + private Vector includes; + private String source; + private long sourceLastModified; + private Vector sysIncludes; + /** + * Constructor + * + * @param history + * hashtable of TargetHistory keyed by output name + * @param outputFiles + * existing files in output directory + */ + private DependencyTableHandler(DependencyTable dependencyTable, + File baseDir) { + this.dependencyTable = dependencyTable; + this.baseDir = baseDir; + includes = new Vector(); + sysIncludes = new Vector(); + source = null; + } + public void endElement(String namespaceURI, String localName, + String qName) throws SAXException { + // + // if then + // create Dependency object and add to hashtable + // if corresponding source file exists and + // has the same timestamp + // + if (qName.equals("source")) { + if (source != null && includePath != null) { + File existingFile = new File(baseDir, source); + // + // if the file exists and the time stamp is right + // preserve the dependency info + if (existingFile.exists()) { + // + // would have expected exact matches + // but was seeing some unexpected difference by + // a few tens of milliseconds, as long + // as the times are within a second + long existingLastModified = existingFile.lastModified(); + long diff = existingLastModified - sourceLastModified; + if (diff >= -500 && diff <= 500) { + DependencyInfo dependInfo = new DependencyInfo( + includePath, source, sourceLastModified, + includes, sysIncludes); + dependencyTable.putDependencyInfo(source, + dependInfo); + } + } + source = null; + includes.setSize(0); + } + } else { + // + // this causes any elements outside the + // scope of an to be discarded + // + if (qName.equals("includePath")) { + includePath = null; + } + } + } + /** + * startElement handler + */ + public void startElement(String namespaceURI, String localName, + String qName, Attributes atts) throws SAXException { + // + // if includes, then add relative file name to vector + // + if (qName.equals("include")) { + includes.addElement(atts.getValue("file")); + } else { + if (qName.equals("sysinclude")) { + sysIncludes.addElement(atts.getValue("file")); + } else { + // + // if source then + // capture source file name, + // modification time and reset includes vector + // + if (qName.equals("source")) { + source = atts.getValue("file"); + sourceLastModified = Long.parseLong(atts + .getValue("lastModified"), 16); + includes.setSize(0); + sysIncludes.setSize(0); + } else { + if (qName.equals("includePath")) { + includePath = atts.getValue("signature"); + } + } + } + } + } + } + public abstract class DependencyVisitor { + /** + * Previews all the children of this source file. + * + * May be called multiple times as DependencyInfo's for children are + * filled in. + * + * @return true to continue towards recursion into included files + */ + public abstract boolean preview(DependencyInfo parent, + DependencyInfo[] children); + /** + * Called if the dependency depth exhausted the stack. + */ + public abstract void stackExhausted(); + /** + * Visits the dependency info. + * + * @returns true to continue towards recursion into included files + */ + public abstract boolean visit(DependencyInfo dependInfo); + } + public class TimestampChecker extends DependencyVisitor { + private boolean noNeedToRebuild; + private long outputLastModified; + private boolean rebuildOnStackExhaustion; + public TimestampChecker(final long outputLastModified, + boolean rebuildOnStackExhaustion) { + this.outputLastModified = outputLastModified; + noNeedToRebuild = true; + this.rebuildOnStackExhaustion = rebuildOnStackExhaustion; + } + public boolean getMustRebuild() { + return !noNeedToRebuild; + } + public boolean preview(DependencyInfo parent, DependencyInfo[] children) { + int withCompositeTimes = 0; + long parentCompositeLastModified = parent.getSourceLastModified(); + for (int i = 0; i < children.length; i++) { + if (children[i] != null) { + // + // expedient way to determine if a child forces us to + // rebuild + // + visit(children[i]); + long childCompositeLastModified = children[i] + .getCompositeLastModified(); + if (childCompositeLastModified != Long.MIN_VALUE) { + withCompositeTimes++; + if (childCompositeLastModified > parentCompositeLastModified) { + parentCompositeLastModified = childCompositeLastModified; + } + } + } + } + if (withCompositeTimes == children.length) { + parent.setCompositeLastModified(parentCompositeLastModified); + } + // + // may have been changed by an earlier call to visit() + // + return noNeedToRebuild; + } + public void stackExhausted() { + if (rebuildOnStackExhaustion) { + noNeedToRebuild = false; + } + } + public boolean visit(DependencyInfo dependInfo) { + if (noNeedToRebuild) { + if (dependInfo.getSourceLastModified() > outputLastModified + || dependInfo.getCompositeLastModified() > outputLastModified) { + noNeedToRebuild = false; + } + } + // + // only need to process the children if + // it has not yet been determined whether + // we need to rebuild and the composite modified time + // has not been determined for this file + return noNeedToRebuild + && dependInfo.getCompositeLastModified() == Long.MIN_VALUE; + } + } + private/* final */File baseDir; + private String baseDirPath; + /** + * a hashtable of DependencyInfo[] keyed by output file name + */ + private final Hashtable dependencies = new Hashtable(); + /** The file the cache was loaded from. */ + private/* final */File dependenciesFile; + /** Flag indicating whether the cache should be written back to file. */ + private boolean dirty; + /** + * Creates a target history table from dependencies.xml in the prject + * directory, if it exists. Otherwise, initializes the dependencies empty. + * + * @param task + * task used for logging history load errors + * @param baseDir + * output directory for task + */ + public DependencyTable(File baseDir) { + if (baseDir == null) { + throw new NullPointerException("baseDir"); + } + this.baseDir = baseDir; + try { + baseDirPath = baseDir.getCanonicalPath(); + } catch (IOException ex) { + baseDirPath = baseDir.toString(); + } + dirty = false; + // + // load any existing dependencies from file + dependenciesFile = new File(baseDir, "dependencies.xml"); + } + public void commit(CCTask task) { + // + // if not dirty, no need to update file + // + if (dirty) { + // + // walk through dependencies to get vector of include paths + // identifiers + // + Vector includePaths = getIncludePaths(); + // + // + // write dependency file + // + try { + FileOutputStream outStream = new FileOutputStream( + dependenciesFile); + OutputStreamWriter streamWriter; + // + // Early VM's may not have UTF-8 support + // fallback to default code page which + // "should" be okay unless there are + // non ASCII file names + String encodingName = "UTF-8"; + try { + streamWriter = new OutputStreamWriter(outStream, "UTF-8"); + } catch (UnsupportedEncodingException ex) { + streamWriter = new OutputStreamWriter(outStream); + encodingName = streamWriter.getEncoding(); + } + BufferedWriter writer = new BufferedWriter(streamWriter); + writer.write("\n"); + writer.write("\n"); + StringBuffer buf = new StringBuffer(); + Enumeration includePathEnum = includePaths.elements(); + while (includePathEnum.hasMoreElements()) { + writeIncludePathDependencies((String) includePathEnum + .nextElement(), writer, buf); + } + writer.write("\n"); + writer.close(); + dirty = false; + } catch (IOException ex) { + task.log("Error writing " + dependenciesFile.toString() + ":" + + ex.toString()); + } + } + } + /** + * Returns an enumerator of DependencyInfo's + */ + public Enumeration elements() { + return dependencies.elements(); + } + /** + * This method returns a DependencyInfo for the specific source file and + * include path identifier + * + */ + public DependencyInfo getDependencyInfo(String sourceRelativeName, + String includePathIdentifier) { + DependencyInfo dependInfo = null; + DependencyInfo[] dependInfos = (DependencyInfo[]) dependencies + .get(sourceRelativeName); + if (dependInfos != null) { + for (int i = 0; i < dependInfos.length; i++) { + dependInfo = dependInfos[i]; + if (dependInfo.getIncludePathIdentifier().equals( + includePathIdentifier)) { + return dependInfo; + } + } + } + return null; + } + private Vector getIncludePaths() { + Vector includePaths = new Vector(); + DependencyInfo[] dependInfos; + Enumeration dependenciesEnum = dependencies.elements(); + while (dependenciesEnum.hasMoreElements()) { + dependInfos = (DependencyInfo[]) dependenciesEnum.nextElement(); + for (int i = 0; i < dependInfos.length; i++) { + DependencyInfo dependInfo = dependInfos[i]; + boolean matchesExisting = false; + final String dependIncludePath = dependInfo + .getIncludePathIdentifier(); + Enumeration includePathEnum = includePaths.elements(); + while (includePathEnum.hasMoreElements()) { + if (dependIncludePath.equals(includePathEnum.nextElement())) { + matchesExisting = true; + break; + } + } + if (!matchesExisting) { + includePaths.addElement(dependIncludePath); + } + } + } + return includePaths; + } + public void load() throws IOException, ParserConfigurationException, + SAXException { + dependencies.clear(); + if (dependenciesFile.exists()) { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(false); + SAXParser parser = factory.newSAXParser(); + parser.parse(dependenciesFile, new DependencyTableHandler(this, + baseDir)); + dirty = false; + } + } + /** + * Determines if the specified target needs to be rebuilt. + * + * This task may result in substantial IO as files are parsed to determine + * their dependencies + */ + public boolean needsRebuild(CCTask task, TargetInfo target, + int dependencyDepth) { + // look at any files where the compositeLastModified + // is not known, but the includes are known + // + boolean mustRebuild = false; + CompilerConfiguration compiler = (CompilerConfiguration) target + .getConfiguration(); + String includePathIdentifier = compiler.getIncludePathIdentifier(); + File[] sources = target.getSources(); + DependencyInfo[] dependInfos = new DependencyInfo[sources.length]; + long outputLastModified = target.getOutput().lastModified(); + // + // try to solve problem using existing dependency info + // (not parsing any new files) + // + DependencyInfo[] stack = new DependencyInfo[50]; + boolean rebuildOnStackExhaustion = true; + if (dependencyDepth >= 0) { + if (dependencyDepth < 50) { + stack = new DependencyInfo[dependencyDepth]; + } + rebuildOnStackExhaustion = false; + } + TimestampChecker checker = new TimestampChecker(outputLastModified, + rebuildOnStackExhaustion); + for (int i = 0; i < sources.length && !mustRebuild; i++) { + File source = sources[i]; + String relative = CUtil.getRelativePath(baseDirPath, source); + DependencyInfo dependInfo = getDependencyInfo(relative, + includePathIdentifier); + if (dependInfo == null) { + task.log("Parsing " + relative, Project.MSG_VERBOSE); + dependInfo = parseIncludes(task, compiler, source); + } + walkDependencies(task, dependInfo, compiler, stack, checker); + mustRebuild = checker.getMustRebuild(); + } + return mustRebuild; + } + public DependencyInfo parseIncludes(CCTask task, + CompilerConfiguration compiler, File source) { + DependencyInfo dependInfo = compiler.parseIncludes(task, baseDir, + source); + String relativeSource = CUtil.getRelativePath(baseDirPath, source); + putDependencyInfo(relativeSource, dependInfo); + return dependInfo; + } + private void putDependencyInfo(String key, DependencyInfo dependInfo) { + // + // optimistic, add new value + // + DependencyInfo[] old = (DependencyInfo[]) dependencies.put(key, + new DependencyInfo[]{dependInfo}); + dirty = true; + // + // something was already there + // + if (old != null) { + // + // see if the include path matches a previous entry + // if so replace it + String includePathIdentifier = dependInfo + .getIncludePathIdentifier(); + for (int i = 0; i < old.length; i++) { + DependencyInfo oldDepend = old[i]; + if (oldDepend.getIncludePathIdentifier().equals( + includePathIdentifier)) { + old[i] = dependInfo; + dependencies.put(key, old); + return; + } + } + // + // no match prepend the new entry to the array + // of dependencies for the file + DependencyInfo[] combined = new DependencyInfo[old.length + 1]; + combined[0] = dependInfo; + for (int i = 0; i < old.length; i++) { + combined[i + 1] = old[i]; + } + dependencies.put(key, combined); + } + return; + } + public void walkDependencies(CCTask task, DependencyInfo dependInfo, + CompilerConfiguration compiler, DependencyInfo[] stack, + DependencyVisitor visitor) throws BuildException { + // + // visit this node + // if visit returns true then + // visit the referenced include and sysInclude dependencies + // + if (visitor.visit(dependInfo)) { + // + // find first null entry on stack + // + int stackPosition = -1; + for (int i = 0; i < stack.length; i++) { + if (stack[i] == null) { + stackPosition = i; + stack[i] = dependInfo; + break; + } else { + // + // if we have appeared early in the calling history + // then we didn't exceed the criteria + if (stack[i] == dependInfo) { + return; + } + } + } + if (stackPosition == -1) { + visitor.stackExhausted(); + return; + } + // + // locate dependency infos + // + String[] includes = dependInfo.getIncludes(); + String includePathIdentifier = compiler.getIncludePathIdentifier(); + DependencyInfo[] includeInfos = new DependencyInfo[includes.length]; + for (int i = 0; i < includes.length; i++) { + DependencyInfo includeInfo = getDependencyInfo(includes[i], + includePathIdentifier); + includeInfos[i] = includeInfo; + } + // + // preview with only the already available dependency infos + // + if (visitor.preview(dependInfo, includeInfos)) { + // + // now need to fill in the missing DependencyInfos + // + int missingCount = 0; + for (int i = 0; i < includes.length; i++) { + if (includeInfos[i] == null) { + missingCount++; + task.log("Parsing " + includes[i], Project.MSG_VERBOSE); + // If the include is part of a UNC don't go building a + // relative file name. + File src = includes[i].startsWith("\\\\") ? new File( + includes[i]) : new File(baseDir, includes[i]); + DependencyInfo includeInfo = parseIncludes(task, + compiler, src); + includeInfos[i] = includeInfo; + } + } + // + // if it passes a review the second time + // then recurse into all the children + if (missingCount == 0 + || visitor.preview(dependInfo, includeInfos)) { + // + // recurse into + // + for (int i = 0; i < includeInfos.length; i++) { + DependencyInfo includeInfo = includeInfos[i]; + walkDependencies(task, includeInfo, compiler, stack, + visitor); + } + } + } + stack[stackPosition] = null; + } + } + private void writeDependencyInfo(BufferedWriter writer, StringBuffer buf, + DependencyInfo dependInfo) throws IOException { + String[] includes = dependInfo.getIncludes(); + String[] sysIncludes = dependInfo.getSysIncludes(); + // + // if the includes have not been evaluted then + // it is not worth our time saving it + // and trying to distiguish between files with + // no dependencies and those with undetermined dependencies + buf.setLength(0); + buf.append(" \n"); + writer.write(buf.toString()); + for (int i = 0; i < includes.length; i++) { + buf.setLength(0); + buf.append(" \n"); + writer.write(buf.toString()); + } + for (int i = 0; i < sysIncludes.length; i++) { + buf.setLength(0); + buf.append(" \n"); + writer.write(buf.toString()); + } + writer.write(" \n"); + return; + } + private void writeIncludePathDependencies(String includePathIdentifier, + BufferedWriter writer, StringBuffer buf) throws IOException { + // + // include path element + // + buf.setLength(0); + buf.append(" \n"); + writer.write(buf.toString()); + Enumeration dependenciesEnum = dependencies.elements(); + while (dependenciesEnum.hasMoreElements()) { + DependencyInfo[] dependInfos = (DependencyInfo[]) dependenciesEnum + .nextElement(); + for (int i = 0; i < dependInfos.length; i++) { + DependencyInfo dependInfo = dependInfos[i]; + // + // if this is for the same include path + // then output the info + if (dependInfo.getIncludePathIdentifier().equals( + includePathIdentifier)) { + writeDependencyInfo(writer, buf, dependInfo); + } + } + } + writer.write(" \n"); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DistributerDef.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DistributerDef.java new file mode 100644 index 0000000000..ee4f656ccc --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DistributerDef.java @@ -0,0 +1,243 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + + +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Reference; +import java.util.Vector; + +/** + * Distributed build information (Non-functional prototype). + * + */ +public final class DistributerDef + extends DataType { + /** + * if property. + */ + private String ifCond; + + /** + * unless property. + */ + private String unlessCond; + + /** + * hosts. + * + */ + private String hosts; + + /** + * Protocol. + * + */ + private DistributerProtocolEnum protocol; + + /** + * Not sure what this is. + */ + private int tcpCork; + + /** + * user name. + */ + private String user; + + /** + * local to remote file name maps. + */ + private final Vector maps = new Vector(); + + /** + * Constructor. + * + */ + public DistributerDef() { + } + + /** + * Required by documentation generator. + */ + public void execute() { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + + /** + * Returns true if the if and unless conditions (if any) are + * satisfied. + * @return true if definition is active. + */ + public boolean isActive() { + return CUtil.isActive(getProject(), ifCond, unlessCond); + } + + /** + * Sets an id that can be used to reference this element. + * + * @param id + * id + */ + public void setId(final String id) { + // + // this is actually accomplished by a different + // mechanism, but we can document it + // + } + + /** + * Sets the property name for the 'if' condition. + * + * The define will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + * + * @param propName + * property name + */ + public void setIf(final String propName) { + ifCond = propName; + } + + /** + * Specifies that this element should behave as if the content of the + * element with the matching id attribute was inserted at this location. If + * specified, no other attributes should be specified. + * @param r reference name + */ + public void setRefid(final Reference r) { + super.setRefid(r); + } + + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the define will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public void setUnless(final String propName) { + unlessCond = propName; + } + + /** + * Gets hosts. + * @return hosts, may be null. + * + */ + public String getHosts() { + if (isReference()) { + DistributerDef refDistributer = (DistributerDef) + getCheckedRef(DistributerDef.class, + "DistributerDef"); + return refDistributer.getHosts(); + } + return hosts; + } + + /** + * Gets tcp cork. + * @return TCP_CORK value. + * + */ + public int getTcpcork() { + if (isReference()) { + DistributerDef refDistributer = (DistributerDef) + getCheckedRef(DistributerDef.class, + "DistributerDef"); + return refDistributer.getTcpcork(); + } + return tcpCork; + } + + /** + * Gets protocol. + * @return protocol, may be null. + * + */ + public DistributerProtocolEnum getProtocol() { + if (isReference()) { + DistributerDef refDistributer = (DistributerDef) + getCheckedRef(DistributerDef.class, + "DistributerDef"); + return refDistributer.getProtocol(); + } + return protocol; + } + + /** + * Sets hosts. + * @param value new value + */ + public void setHosts(final String value) { + if (isReference()) { + throw tooManyAttributes(); + } + hosts = value; + } + + /** + * Sets TCP_CORK value. + * @param value new value + */ + public void setTcpcork(final int value) { + if (isReference()) { + throw tooManyAttributes(); + } + tcpCork = value; + } + + /** + * Sets protocol. + * @param value new value + */ + public void setProtocol(final DistributerProtocolEnum value) { + if (isReference()) { + throw tooManyAttributes(); + } + protocol = value; + } + + /** + * Local to remote filename maps. + * @return new map + */ + public DistributerMap createMap() { + DistributerMap map = new DistributerMap(); + map.setProject(getProject()); + maps.addElement(map); + return map; + } + + /** + * Sets remote user name. + * @param value user name + */ + public void setUser(final String value) { + user = value; + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DistributerMap.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DistributerMap.java new file mode 100644 index 0000000000..aeacf551fa --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DistributerMap.java @@ -0,0 +1,218 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import java.io.File; +import java.io.IOException; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.DataType; + +/** + * Local to remote filename mapping (Experimental). + * + */ +public final class DistributerMap + extends DataType { + /** + * if property. + */ + private String ifCond; + + /** + * unless property. + */ + private String unlessCond; + + /** + * local directory name. + * + */ + private File localName; + + /** + * Canonical local file name. + */ + private String canonicalPath; + + /** + * remote name. + * + */ + private String remoteName; + + /** + * Separator (/ or \) character on remote system. + */ + private char remoteSeparator = File.separatorChar; + + /** + * hosts that for which this map is valid. + * + */ + private String hosts; + + /** + * Constructor. + * + */ + public DistributerMap() { + } + + /** + * Required by documentation generator. + */ + public void execute() { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + + /** + * Returns true if the if and unless conditions (if any) are + * satisfied. + * + * @return true if this object is active. + */ + public boolean isActive() { + return CUtil.isActive(getProject(), ifCond, unlessCond); + } + + /** + * Sets the property name for the 'if' condition. + * + * This object will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + * + * @param propName + * property name + */ + public void setIf(final String propName) { + ifCond = propName; + } + + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the define will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public void setUnless(final String propName) { + unlessCond = propName; + } + + /** + * Gets local directory. + * @return local directory, may be null. + * + */ + public File getLocal() { + return localName; + } + + /** + * Gets remote name for directory. + * @return remote name, may be null. + * + */ + public String getRemote() { + return remoteName; + } + + /** + * Converts the local file name to the remote name for the same file. + * + * @param host host + * @param localFile local file + * @return remote name for local file, null if unknown. + */ + public String toRemote(final String host, final File localFile) { + if (remoteName != null + && (hosts == null || hosts.indexOf(host) >= 0)) { + try { + String canonical = localFile.getCanonicalPath(); + if (canonical.startsWith(canonicalPath)) { + if (isActive()) { + return remoteName + + canonical.substring(canonicalPath.length()).replace(File. + separatorChar, remoteSeparator); + } + } + } catch (IOException ex) { + return null; + } + } + return null; + } + + /** + * Sets local directory for base of mapping. + * + * @param value value + */ + public void setLocal(final File value) { + if (value == null) { + throw new NullPointerException("value"); + } + if (value.exists() && !value.isDirectory()) { + throw new BuildException("local should be a directory"); + } + localName = value; + try { + canonicalPath = localName.getCanonicalPath(); + } catch (IOException ex) { + throw new BuildException(ex); + } + } + + /** + * Sets remote name for directory. + * @param value remote name for directory + */ + public void setRemote(final String value) { + remoteName = value; + } + + /** + * Sets the separator character (/ or \) for the remote system. + * @param value separator character + */ + public void setRemoteSeparator(final String value) { + if (value != null && value.length() != 1) { + throw new BuildException("remote separator must be a single character"); + } + remoteSeparator = value.charAt(0); + } + + /** + * Sets hosts for which this mapping is valid. + * + * @param value hosts + */ + public void setHosts(final String value) { + hosts = value; + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DistributerProtocolEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DistributerProtocolEnum.java new file mode 100644 index 0000000000..5606d47a08 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/DistributerProtocolEnum.java @@ -0,0 +1,50 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import org.apache.tools.ant.types.EnumeratedAttribute; + +/** + * Distributer prococol names (experimental). + * + * @author Curt Arnold + * + */ +public final class DistributerProtocolEnum + extends EnumeratedAttribute { + /** + * Constructor. + * + * Set by default to "distcc" + * + * @see java.lang.Object#Object() + */ + public DistributerProtocolEnum() { + setValue("distcc"); + } + + /** + * Gets list of acceptable values. + * + * @see org.apache.tools.ant.types.EnumeratedAttribute#getValues() + */ + public String[] getValues() { + return new String[] { + "distcc", + "ssh"}; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/FileVisitor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/FileVisitor.java new file mode 100644 index 0000000000..24aef25fb6 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/FileVisitor.java @@ -0,0 +1,27 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.File; + +import org.apache.tools.ant.BuildException; +/** + * An abstract class implemented to walk over the fileset members of a + * ProcessorDef + */ +public interface FileVisitor { + abstract void visit(File parentDir, String filename) throws BuildException; +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/LinkerDef.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/LinkerDef.java new file mode 100644 index 0000000000..d997b2f992 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/LinkerDef.java @@ -0,0 +1,549 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.File; +import java.util.Enumeration; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; +import net.sf.antcontrib.cpptasks.gcc.GccLinker; +import net.sf.antcontrib.cpptasks.types.FlexLong; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +import net.sf.antcontrib.cpptasks.types.LinkerArgument; +import net.sf.antcontrib.cpptasks.types.SystemLibrarySet; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.FlexInteger; +/** + * A linker definition. linker elements may be placed either as children of a + * cc element or the project element. A linker element with an id attribute may + * be referenced by linker elements with refid or extends attributes. + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public class LinkerDef extends ProcessorDef { + private long base; + private String entry; + private Boolean fixed; + private Boolean incremental; + private final Vector librarySets = new Vector(); + private Boolean map; + private int stack; + private final Vector sysLibrarySets = new Vector(); + private final Vector versionInfos = new Vector(); + private Boolean defaultflag = new Boolean(true); + /** + * Default constructor + * + * @see java.lang.Object#Object() + */ + public LinkerDef() { + base = -1; + stack = -1; + } + private void addActiveLibrarySet(Project project, Vector libsets, + Vector srcSets) { + Enumeration srcenum = srcSets.elements(); + while (srcenum.hasMoreElements()) { + LibrarySet set = (LibrarySet) srcenum.nextElement(); + if (set.isActive(project)) { + libsets.addElement(set); + } + } + } + private void addActiveSystemLibrarySets(Project project, Vector libsets) { + addActiveLibrarySet(project, libsets, sysLibrarySets); + } + private void addActiveUserLibrarySets(Project project, Vector libsets) { + addActiveLibrarySet(project, libsets, librarySets); + } + /** + * Adds a linker command-line arg. + */ + public void addConfiguredLinkerArg(LinkerArgument arg) { + addConfiguredProcessorArg(arg); + } + /** + * Adds a compiler command-line arg. + */ + public void addConfiguredLinkerParam(LinkerParam param) { + if (isReference()) { + throw noChildrenAllowed(); + } + addConfiguredProcessorParam(param); + } + /** + * Adds a system library set. + */ + public void addLibset(LibrarySet libset) { + if (isReference()) { + throw super.noChildrenAllowed(); + } + if (libset == null) { + throw new NullPointerException("libset"); + } + librarySets.addElement(libset); + } + /** + * Adds a system library set. + */ + public void addSyslibset(SystemLibrarySet libset) { + if (isReference()) { + throw super.noChildrenAllowed(); + } + if (libset == null) { + throw new NullPointerException("libset"); + } + sysLibrarySets.addElement(libset); + } + + /** + * Adds desriptive version information to be included in the + * generated file. The first active version info block will + * be used. + */ + public void addConfiguredVersioninfo(VersionInfo newVersionInfo) { + if (isReference()) { + throw noChildrenAllowed(); + } + newVersionInfo.setProject(this.getProject()); + versionInfos.addElement(newVersionInfo); + } + + public ProcessorConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef baseDef, TargetDef targetPlatform) { + // + // must combine some local context (the linkType) + // with the referenced element + // + // get a pointer to the definition (either local or referenced) + ProcessorDef thisDef = this; + if (isReference()) { + thisDef = ((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")); + } + // + // find the appropriate processor (combines local linkType + // with possibly remote linker name) + Processor proc = getProcessor(); + proc = proc.getLinker(linkType); + ProcessorDef[] defaultProviders = getDefaultProviders(baseDef); + return proc.createConfiguration(task, linkType, defaultProviders, + thisDef, targetPlatform); + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + /** + * Returns an array of active library sets for this linker definition. + */ + public LibrarySet[] getActiveLibrarySets(LinkerDef[] defaultProviders, + int index) { + if (isReference()) { + return ((LinkerDef) getCheckedRef(LinkerDef.class, "LinkerDef")) + .getActiveUserLibrarySets(defaultProviders, index); + } + Project p = getProject(); + Vector libsets = new Vector(); + for (int i = index; i < defaultProviders.length; i++) { + defaultProviders[i].addActiveUserLibrarySets(p, libsets); + defaultProviders[i].addActiveSystemLibrarySets(p, libsets); + } + addActiveUserLibrarySets(p, libsets); + addActiveSystemLibrarySets(p, libsets); + LibrarySet[] sets = new LibrarySet[libsets.size()]; + libsets.copyInto(sets); + return sets; + } + /** + * Returns an array of active library sets for this linker definition. + */ + public LibrarySet[] getActiveSystemLibrarySets( + LinkerDef[] defaultProviders, int index) { + if (isReference()) { + return ((LinkerDef) getCheckedRef(LinkerDef.class, "LinkerDef")) + .getActiveUserLibrarySets(defaultProviders, index); + } + Project p = getProject(); + Vector libsets = new Vector(); + for (int i = index; i < defaultProviders.length; i++) { + defaultProviders[i].addActiveSystemLibrarySets(p, libsets); + } + addActiveSystemLibrarySets(p, libsets); + LibrarySet[] sets = new LibrarySet[libsets.size()]; + libsets.copyInto(sets); + return sets; + } + /** + * Returns an array of active library sets for this linker definition. + */ + public LibrarySet[] getActiveUserLibrarySets(LinkerDef[] defaultProviders, + int index) { + if (isReference()) { + return ((LinkerDef) getCheckedRef(LinkerDef.class, "LinkerDef")) + .getActiveUserLibrarySets(defaultProviders, index); + } + Project p = getProject(); + Vector libsets = new Vector(); + for (int i = index; i < defaultProviders.length; i++) { + defaultProviders[i].addActiveUserLibrarySets(p, libsets); + } + addActiveUserLibrarySets(p, libsets); + LibrarySet[] sets = new LibrarySet[libsets.size()]; + libsets.copyInto(sets); + return sets; + } + public long getBase(LinkerDef[] defaultProviders, int index) { + if (isReference()) { + return ((LinkerDef) getCheckedRef(LinkerDef.class, "LinkerDef")) + .getBase(defaultProviders, index); + } + if (base <= 0) { + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getBase(defaultProviders, + index + 1); + } + } + return base; + } + public Boolean getFixed(LinkerDef[] defaultProviders, int index) { + if (isReference()) { + return ((LinkerDef) getCheckedRef(LinkerDef.class, "LinkerDef")) + .getFixed(defaultProviders, index); + } + if (fixed == null) { + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getFixed(defaultProviders, + index + 1); + } + } + return fixed; + } + public boolean getIncremental(LinkerDef[] defaultProviders, int index) { + if (isReference()) { + return ((LinkerDef) getCheckedRef(LinkerDef.class, "LinkerDef")) + .getIncremental(defaultProviders, index); + } + if (incremental != null) { + return incremental.booleanValue(); + } + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getIncremental(defaultProviders, index + 1); + } + return false; + } + public boolean getMap(LinkerDef[] defaultProviders, int index) { + if (isReference()) { + return ((LinkerDef) getCheckedRef(LinkerDef.class, "LinkerDef")) + .getMap(defaultProviders, index); + } + if (map != null) { + return map.booleanValue(); + } + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getMap(defaultProviders, index + 1); + } + return false; + } + public final Boolean getDefaultflag(LinkerDef[] defaultProviders, int index) { + if (isReference()) { + return ((LinkerDef) getCheckedRef(LinkerDef.class, + "LinkerDef")).getDefaultflag(defaultProviders, index); + } + return defaultflag; + } + public String getEntry(LinkerDef[] defaultProviders, int index) { + if (isReference()) { + return ((LinkerDef) getCheckedRef(LinkerDef.class, "LinkerDef")) + .getEntry(defaultProviders, index); + } + if (entry != null) { + return entry; + } + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getEntry(defaultProviders, index + 1); + } + return null; + } + + public Processor getProcessor() { + Linker linker = (Linker) super.getProcessor(); + if (linker == null) { + linker = GccLinker.getInstance(); + } + if (getLibtool() && linker instanceof CommandLineLinker) { + CommandLineLinker cmdLineLinker = (CommandLineLinker) linker; + linker = cmdLineLinker.getLibtoolLinker(); + } + return linker; + } + public int getStack(LinkerDef[] defaultProviders, int index) { + if (isReference()) { + return ((LinkerDef) getCheckedRef(LinkerDef.class, "LinkerDef")) + .getStack(defaultProviders, index); + } + if (stack < 0) { + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getStack(defaultProviders, + index + 1); + } + } + return stack; + } + /** + * Sets the base address. May be specified in either decimal or hex. + * + * @param base + * base address + * + */ + public void setBase(FlexLong base) { + if (isReference()) { + throw tooManyAttributes(); + } + this.base = base.longValue(); + } + /** + * Sets the starting address. + * + * @param name + * function name + */ + public void setEntry(String entry) { + if (isReference()) { + throw tooManyAttributes(); + } + this.entry = entry; + } + /** + * If true, marks the file to be loaded only at its preferred address. + */ + public void setFixed(boolean fixed) { + if (isReference()) { + throw tooManyAttributes(); + } + this.fixed = booleanValueOf(fixed); + } + /** + * If true, allows incremental linking. + * + */ + public void setIncremental(boolean incremental) { + if (isReference()) { + throw tooManyAttributes(); + } + this.incremental = booleanValueOf(incremental); + } + /** + * If set to true, a map file will be produced. + */ + public void setMap(boolean map) { + if (isReference()) { + throw tooManyAttributes(); + } + this.map = booleanValueOf(map); + } + /** + * Sets linker type. + * + * + * Supported linkers + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
gccGcc Linker
g++G++ Linker
ldLd Linker
arGcc Librarian
msvcMicrosoft Linker
bccBorland Linker
dfCompaq Visual Fortran Linker
iclIntel Linker for Windows (IA-32)
eclIntel Linker for Windows (IA-64)
iccIntel Linker for Linux (IA-32)
eccIntel Linker for Linux (IA-64)
CCSun ONE Linker
aCCHP aC++ Linker
os390OS390 Linker
os390batchOS390 Linker
os400IccLinker
sunc89C89 Linker
xlCVisualAge Linker
+ * + */ + public void setName(LinkerEnum name) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + Linker linker = name.getLinker(); + super.setProcessor(linker); + } + protected void setProcessor(Processor proc) throws BuildException { + Linker linker = null; + if (proc instanceof Linker) { + linker = (Linker) proc; + } else { + LinkType linkType = new LinkType(); + linker = proc.getLinker(linkType); + } + super.setProcessor(linker); + } + /** + * Sets stack size in bytes. + */ + public void setStack(FlexInteger stack) { + if (isReference()) { + throw tooManyAttributes(); + } + this.stack = stack.intValue(); + } + public void visitSystemLibraries(Linker linker, FileVisitor libraryVisitor) { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project must be set"); + } + if (isReference()) { + LinkerDef master = ((LinkerDef) getCheckedRef(LinkerDef.class, + "Linker")); + master.visitSystemLibraries(linker, libraryVisitor); + } else { + // + // if this linker extends another, + // visit its libraries first + // + LinkerDef extendsDef = (LinkerDef) getExtends(); + if (extendsDef != null) { + extendsDef.visitSystemLibraries(linker, libraryVisitor); + } + if (sysLibrarySets.size() > 0) { + File[] libpath = linker.getLibraryPath(); + for (int i = 0; i < sysLibrarySets.size(); i++) { + LibrarySet set = (LibrarySet) sysLibrarySets.elementAt(i); + if (set.isActive(p)) { + set.visitLibraries(p, linker, libpath, + libraryVisitor); + } + } + } + } + } + public void visitUserLibraries(Linker linker, FileVisitor libraryVisitor) { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project must be set"); + } + if (isReference()) { + LinkerDef master = ((LinkerDef) getCheckedRef(LinkerDef.class, + "Linker")); + master.visitUserLibraries(linker, libraryVisitor); + } else { + // + // if this linker extends another, + // visit its libraries first + // + LinkerDef extendsDef = (LinkerDef) getExtends(); + if (extendsDef != null) { + extendsDef.visitUserLibraries(linker, libraryVisitor); + } + // + // visit the user libraries + // + if (librarySets.size() > 0) { + File[] libpath = linker.getLibraryPath(); + for (int i = 0; i < librarySets.size(); i++) { + LibrarySet set = (LibrarySet) librarySets.elementAt(i); + if (set.isActive(p)) { + set.visitLibraries(p, linker, libpath, + libraryVisitor); + } + } + } + } + } + /** + * Enables or disables default flags. + * + * @param defaultflag + * if true, default flags will add to command line. + * + */ + public void setDefaultflag(boolean defaultflag) { + if (isReference()) { + throw tooManyAttributes(); + } + this.defaultflag = booleanValueOf(defaultflag); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/LinkerEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/LinkerEnum.java new file mode 100644 index 0000000000..cfe8984c23 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/LinkerEnum.java @@ -0,0 +1,106 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import net.sf.antcontrib.cpptasks.arm.ADSLinker; +import net.sf.antcontrib.cpptasks.borland.BorlandLinker; +import net.sf.antcontrib.cpptasks.compaq.CompaqVisualFortranLinker; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioLinker; +import net.sf.antcontrib.cpptasks.gcc.GccLibrarian; +import net.sf.antcontrib.cpptasks.gcc.GccLinker; +import net.sf.antcontrib.cpptasks.gcc.GppLinker; +import net.sf.antcontrib.cpptasks.gcc.LdLinker; +import net.sf.antcontrib.cpptasks.hp.aCCLinker; +import net.sf.antcontrib.cpptasks.ibm.VisualAgeLinker; +import net.sf.antcontrib.cpptasks.intel.IntelLinux32Linker; +import net.sf.antcontrib.cpptasks.intel.IntelLinux64Linker; +import net.sf.antcontrib.cpptasks.intel.IntelWin32Linker; +import net.sf.antcontrib.cpptasks.os390.OS390Linker; +import net.sf.antcontrib.cpptasks.os400.IccLinker; +import net.sf.antcontrib.cpptasks.sun.C89Linker; +import net.sf.antcontrib.cpptasks.sun.ForteCCLinker; +import net.sf.antcontrib.cpptasks.ti.ClxxLinker; +import org.apache.tools.ant.types.EnumeratedAttribute; +/** + * Enumeration of supported linkers + * + * @author Curt Arnold + * + */ +public class LinkerEnum extends EnumeratedAttribute { + private final static ProcessorEnumValue[] linkers = new ProcessorEnumValue[]{ + new ProcessorEnumValue("gcc", GccLinker.getInstance()), + new ProcessorEnumValue("g++", GppLinker.getInstance()), + new ProcessorEnumValue("ld", LdLinker.getInstance()), + new ProcessorEnumValue("ar", GccLibrarian.getInstance()), + new ProcessorEnumValue("msvc", DevStudioLinker.getInstance()), + new ProcessorEnumValue("bcc", BorlandLinker.getInstance()), + new ProcessorEnumValue("df", CompaqVisualFortranLinker + .getInstance()), + new ProcessorEnumValue("icl", IntelWin32Linker.getInstance()), + new ProcessorEnumValue("ecl", IntelWin32Linker.getInstance()), + new ProcessorEnumValue("icc", IntelLinux32Linker.getInstance()), + new ProcessorEnumValue("ecc", IntelLinux64Linker.getInstance()), + new ProcessorEnumValue("CC", ForteCCLinker.getInstance()), + new ProcessorEnumValue("aCC", aCCLinker.getInstance()), + new ProcessorEnumValue("os390", OS390Linker.getInstance()), + new ProcessorEnumValue("os390batch", OS390Linker + .getDataSetInstance()), + new ProcessorEnumValue("os400", IccLinker.getInstance()), + new ProcessorEnumValue("sunc89", C89Linker.getInstance()), + new ProcessorEnumValue("xlC", VisualAgeLinker.getInstance()), + new ProcessorEnumValue("cl6x", ClxxLinker.getCl6xInstance()), + new ProcessorEnumValue("cl55", ClxxLinker.getCl55Instance()), + new ProcessorEnumValue("armcc", ADSLinker.getInstance()), + new ProcessorEnumValue("armcpp", ADSLinker.getInstance()), + new ProcessorEnumValue("tcc", ADSLinker.getInstance()), + new ProcessorEnumValue("tcpp", ADSLinker.getInstance()), + // gcc cross compilers + new ProcessorEnumValue( + "sparc-sun-solaris2-gcc", + net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2.GccLinker + .getInstance()), + new ProcessorEnumValue( + "sparc-sun-solaris2-g++", + net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2.GppLinker + .getInstance()), + new ProcessorEnumValue( + "sparc-sun-solaris2-ld", + net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2.LdLinker + .getInstance()), + new ProcessorEnumValue( + "sparc-sun-solaris2-ar", + net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2.GccLibrarian + .getInstance()), + new ProcessorEnumValue("gcc-cross", + net.sf.antcontrib.cpptasks.gcc.cross.GccLinker + .getInstance()), + new ProcessorEnumValue("g++-cross", + net.sf.antcontrib.cpptasks.gcc.cross.GppLinker + .getInstance()), + new ProcessorEnumValue("ld-cross", + net.sf.antcontrib.cpptasks.gcc.cross.LdLinker.getInstance()), + new ProcessorEnumValue("ar-cross", + net.sf.antcontrib.cpptasks.gcc.cross.GccLibrarian + .getInstance()),}; + public Linker getLinker() { + return (Linker) linkers[getIndex()].getProcessor(); + } + public String[] getValues() { + return ProcessorEnumValue.getValues(linkers); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/LinkerParam.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/LinkerParam.java new file mode 100644 index 0000000000..383bae55c9 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/LinkerParam.java @@ -0,0 +1,33 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +/******************************************************************************* + * Place class description here. + * + * @author inger + * @author + * + * @since + ******************************************************************************/ +public class LinkerParam extends ProcessorParam { + public LinkerParam() { + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/OSFamilyEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/OSFamilyEnum.java new file mode 100644 index 0000000000..536d9922d3 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/OSFamilyEnum.java @@ -0,0 +1,59 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import org.apache.tools.ant.types.EnumeratedAttribute; + +/** + * Enumeration of cpu types. + * + * @author Curt Arnold + * + */ +public final class OSFamilyEnum + extends EnumeratedAttribute { + /** + * Constructor. + * + * Set by default to "pentium3" + * + * @see java.lang.Object#Object() + */ + public OSFamilyEnum() { + setValue("windows"); + } + + /** + * Gets list of acceptable values. + * + * @see org.apache.tools.ant.types.EnumeratedAttribute#getValues() + */ + public String[] getValues() { + return new String[] { + "windows", + "dos", + "mac", + "unix", + "netware", + "os/2", + "tandem", + "win9x", + "z/os", + "os/400", + "openvms"}; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ObjectFileCollector.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ObjectFileCollector.java new file mode 100644 index 0000000000..3e97fa40af --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ObjectFileCollector.java @@ -0,0 +1,42 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.Linker; + +import org.apache.tools.ant.BuildException; +/** + * Collects object files for the link step. + * + * + */ +public final class ObjectFileCollector implements FileVisitor { + private final Vector files; + private final Linker linker; + public ObjectFileCollector(Linker linker, Vector files) { + this.linker = linker; + this.files = files; + } + public void visit(File parentDir, String filename) throws BuildException { + int bid = linker.bid(filename); + if (bid >= 1) { + files.addElement(new File(parentDir, filename)); + } + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/OptimizationEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/OptimizationEnum.java new file mode 100644 index 0000000000..4a0d17953e --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/OptimizationEnum.java @@ -0,0 +1,82 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import org.apache.tools.ant.types.EnumeratedAttribute; + +/** + * Enumeration of optimization levels (experimental). + * + * @author Curt Arnold + * + */ +public final class OptimizationEnum + extends EnumeratedAttribute { + /** + * Constructor. + * + * Set by default to "speed" + * + * @see java.lang.Object#Object() + */ + public OptimizationEnum() { + setValue("speed"); + } + + /** + * Gets list of acceptable values. + * + * @see org.apache.tools.ant.types.EnumeratedAttribute#getValues() + */ + public String[] getValues() { + return new String[] { + "none", + "size", + "minimal", + "speed", + "full", + "aggressive", + "extreme", + "unsafe" + }; + } + + /** + * Is size optimized. + * @return boolean true if size is optimized. + */ + public boolean isSize() { + return "speed".equals(getValue()); + } + + /** + * Is speed optimized. + * @return boolean true if speed is optimized. + */ + public boolean isSpeed() { + return !isSize() && !isNoOptimization(); + } + + /** + * Is no optimization performed. + * @return boolean true if no optimization is performed. + */ + public boolean isNoOptimization() { + return "none".equals(getValue()); + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/OutputTypeEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/OutputTypeEnum.java new file mode 100644 index 0000000000..fb37843fbc --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/OutputTypeEnum.java @@ -0,0 +1,48 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import org.apache.tools.ant.types.EnumeratedAttribute; +/** + * Enumeration of supported subsystems + * + * @author Curt Arnold + * + */ +public class OutputTypeEnum extends EnumeratedAttribute { + /** + * Constructor + * + * Set by default to "executable" + * + * @see java.lang.Object#Object() + */ + public OutputTypeEnum() { + setValue("executable"); + } + /** + * Gets list of acceptable values + * + * @see org.apache.tools.ant.types.EnumeratedAttribute#getValues() + */ + public String[] getValues() { + return new String[]{"executable", // executable program + "plugin", // plugin module + "shared", // dynamically linkable module + "static" // convenience library + }; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/PrecompileDef.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/PrecompileDef.java new file mode 100644 index 0000000000..828e2c2f48 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/PrecompileDef.java @@ -0,0 +1,215 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.File; +import java.util.Enumeration; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.types.ConditionalFileSet; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.types.DataType; +/** + * An element that specifies a prototype file and rules for source files that + * should not use precompiled headers + * + * @author Curt Arnold + */ +public final class PrecompileDef extends DataType { + private final Vector exceptSets = new Vector(); + private String ifCond; + /** + * Directory of prototype file + */ + private File prototype = new File("stdafx.cpp"); + private String unlessCond; + /** + * Constructor + * + */ + public PrecompileDef() { + } + /** + * Method used by PrecompileExceptDef to add exception set to + * PrecompileDef. + */ + public void appendExceptFileSet(ConditionalFileSet exceptSet) { + exceptSet.setProject(getProject()); + exceptSets.addElement(exceptSet); + } + /** + * Adds filesets that specify files that should not be processed with + * precompiled headers enabled. + * + * @param exceptSet + * FileSet specify files that should not be processed with + * precompiled headers enabled. + */ + public PrecompileExceptDef createExcept() { + return new PrecompileExceptDef(this); + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + public String[] getExceptFiles() { + PrecompileDef ref = getRef(); + if (ref != null) { + return ref.getExceptFiles(); + } + if (exceptSets.size() == 0) { + return new String[0]; + } + Project p = getProject(); + String[] exceptFiles = null; + Enumeration setEnum = exceptSets.elements(); + while (setEnum.hasMoreElements()) { + ConditionalFileSet exceptSet = (ConditionalFileSet) setEnum + .nextElement(); + if (exceptSet.isActive()) { + DirectoryScanner scanner = exceptSet + .getDirectoryScanner(p); + String[] scannerFiles = scanner.getIncludedFiles(); + if (exceptFiles == null) { + exceptFiles = scannerFiles; + } else { + if (scannerFiles.length > 0) { + String[] newFiles = new String[exceptFiles.length + + scannerFiles.length]; + for (int i = 0; i < exceptFiles.length; i++) { + newFiles[i] = exceptFiles[i]; + } + int index = exceptFiles.length; + for (int i = 0; i < scannerFiles.length; i++) { + newFiles[index++] = scannerFiles[i]; + } + exceptFiles = newFiles; + } + } + } + } + if (exceptFiles == null) { + exceptFiles = new String[0]; + } + return exceptFiles; + } + /** + * Gets prototype source file + * + */ + public File getPrototype() { + PrecompileDef ref = getRef(); + if (ref != null) { + return ref.getPrototype(); + } + return prototype; + } + private PrecompileDef getRef() { + if (isReference()) { + return ((PrecompileDef) getCheckedRef(PrecompileDef.class, + "PrecompileDef")); + } + return null; + } + public boolean isActive() { + boolean isActive = CUtil.isActive(getProject(), ifCond, unlessCond); + if (!isActive) { + PrecompileDef ref = getRef(); + if (ref != null) { + return ref.isActive(); + } + } + return isActive; + } + /** + * Sets a description of the current data type. + */ + public void setDescription(String desc) { + super.setDescription(desc); + } + /** + * Sets an id that can be used to reference this element. + * + * @param id + * id + */ + public void setId(String id) { + // + // this is actually accomplished by a different + // mechanism, but we can document it + // + } + /** + * Set the 'if' condition. + * + * The processor will be ignored unless the property is defined. + * + * The value of property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * isActive() is evaluated. + * + * @param propName + * name of property + */ + public void setIf(String propName) { + ifCond = propName; + } + /** + * Sets file to precompile. + * + * Should be a source file that includes only one unguarded header file. + * Default value is "stdafx.cpp". + * + * @param prototype + * file path for prototype source file + */ + public void setPrototype(File prototype) { + if (isReference()) { + throw tooManyAttributes(); + } + if (prototype == null) { + throw new NullPointerException("prototype"); + } + this.prototype = prototype; + } + /** + * Specifies that this element should behave as if the content of the + * element with the matching id attribute was inserted at this location. + * + * @param ref + * Reference to other element + * + */ + public void setRefid(org.apache.tools.ant.types.Reference ref) { + super.setRefid(ref); + } + /** + * Set the 'unless' condition. If named property exists at execution time, + * the processor will be ignored. + * + * Value of property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when isActive is called. + * + * @param propName + * name of property + */ + public void setUnless(String propName) { + unlessCond = propName; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/PrecompileExceptDef.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/PrecompileExceptDef.java new file mode 100644 index 0000000000..d6cdd6025f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/PrecompileExceptDef.java @@ -0,0 +1,80 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.File; + +import net.sf.antcontrib.cpptasks.types.ConditionalFileSet; + +import org.apache.tools.ant.BuildException; +/** + * Specifies files that should not be compiled using precompiled headers. + * + * @author Curt Arnold + */ +public final class PrecompileExceptDef { + private ConditionalFileSet localSet = null; + /** + * Collection of contained by definition + */ + private PrecompileDef owner; + /** + * Constructor + * + */ + public PrecompileExceptDef(PrecompileDef owner) { + this.owner = owner; + } + /** + * Adds filesets that specify files that should not be processed using + * precompiled headers. + * + * @param exceptSet + * FileSet specify files that should not be processed with + * precompiled headers enabled. + */ + public void addFileset(ConditionalFileSet exceptSet) { + owner.appendExceptFileSet(exceptSet); + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + /** + * Sets the base-directory + */ + public void setDir(File dir) throws BuildException { + if (localSet == null) { + localSet = new ConditionalFileSet(); + owner.appendExceptFileSet(localSet); + } + localSet.setDir(dir); + } + /** + * Comma or space separated list of file patterns that should not be + * compiled using precompiled headers. + * + * @param includes + * the string containing the include patterns + */ + public void setIncludes(String includes) { + if (localSet == null) { + localSet = new ConditionalFileSet(); + owner.appendExceptFileSet(localSet); + } + localSet.setIncludes(includes); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ProcessorDef.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ProcessorDef.java new file mode 100644 index 0000000000..38faf427e7 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ProcessorDef.java @@ -0,0 +1,714 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; +import net.sf.antcontrib.cpptasks.types.CommandLineArgument; +import net.sf.antcontrib.cpptasks.types.ConditionalFileSet; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Environment; +import org.apache.tools.ant.types.Reference; +/** + * An abstract compiler/linker definition. + * + * @author Curt Arnold + */ +public abstract class ProcessorDef extends DataType { + /** + * Returns the equivalent Boolean object for the specified value + * + * Equivalent to Boolean.valueOf in JDK 1.4 + * + * @param val + * boolean value + * @return Boolean.TRUE or Boolean.FALSE + */ + protected static Boolean booleanValueOf(boolean val) { + if (val) { + return Boolean.TRUE; + } + return Boolean.FALSE; + } + /** + * if true, targets will be built for debugging + */ + private Boolean debug; + private Environment env = null; + /** + * Reference for "extends" processor definition + */ + private Reference extendsRef = null; + /** + * Name of property that must be present or definition will be ignored. May + * be null. + */ + private String ifProp; + /** + * if true, processor definition inherits values from containing + * element + */ + private boolean inherit; + private Boolean libtool = null; + protected boolean newEnvironment = false; + /** + * Processor. + */ + private Processor processor; + /** + * Collection of or contained by definition + */ + private final Vector processorArgs = new Vector(); + /** + * Collection of or contained by definition + */ + private final Vector processorParams = new Vector(); + /** + * if true, all targets will be unconditionally rebuilt + */ + private Boolean rebuild; + /** + * Collection of contained by definition + */ + private final Vector srcSets = new Vector(); + /** + * Name of property that if present will cause definition to be ignored. + * May be null. + */ + private String unlessProp; + /** + * Constructor + * + */ + protected ProcessorDef() throws NullPointerException { + inherit = true; + } + /** + * Adds a or + * + * @param arg + * command line argument, must not be null + * @throws NullPointerException + * if arg is null + * @throws BuildException + * if this definition is a reference + */ + protected void addConfiguredProcessorArg(CommandLineArgument arg) + throws NullPointerException, BuildException { + if (arg == null) { + throw new NullPointerException("arg"); + } + if (isReference()) { + throw noChildrenAllowed(); + } + if(arg.getFile() == null ) { + processorArgs.addElement(arg); + } + else { + loadFile(arg.getFile()); + } + } + /** + * Add a or if specify the file attribute + * + * @param arg + * command line argument, must not be null + * @throws BuildException + * if the specify file not exist + */ + protected void loadFile(File file) + throws BuildException { + FileReader fileReader; + BufferedReader in; + String str; + if (! file.exists()){ + throw new BuildException("The file " + file + " is not existed"); + } + try { + fileReader = new FileReader(file); + in = new BufferedReader(fileReader); + while ( (str = in.readLine()) != null ){ + if(str.trim() == ""){ + continue ; + } + str = getProject().replaceProperties(str); + CommandLineArgument newarg = new CommandLineArgument(); + newarg.setValue(str.trim()); + processorArgs.addElement(newarg); + } + } + catch(Exception e){ + throw new BuildException(e.getMessage()); + } + } + /** + * Adds a or + * + * @param arg + * command line argument, must not be null + * @throws NullPointerException + * if arg is null + * @throws BuildException + * if this definition is a reference + */ + protected void addConfiguredProcessorParam(ProcessorParam param) + throws NullPointerException, BuildException { + if (param == null) { + throw new NullPointerException("param"); + } + if (isReference()) { + throw noChildrenAllowed(); + } + processorParams.addElement(param); + } + /** + * Add an environment variable to the launched process. + */ + public void addEnv(Environment.Variable var) { + if (env == null) { + env = new Environment(); + } + env.addVariable(var); + } + /** + * Adds a source file set. + * + * Files in these set will be processed by this configuration and will not + * participate in the auction. + * + * @param srcSet + * Fileset identifying files that should be processed by this + * processor + * @throws BuildException + * if processor definition is a reference + */ + public void addFileset(ConditionalFileSet srcSet) throws BuildException { + if (isReference()) { + throw noChildrenAllowed(); + } + srcSet.setProject(getProject()); + srcSets.addElement(srcSet); + } + /** + * Creates a configuration + * + * @param baseDef + * reference to def from containing element, may be null + * @return configuration + * + */ + public ProcessorConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef baseDef, TargetDef targetPlatform) { + if (isReference()) { + return ((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")).createConfiguration(task, linkType, + baseDef, targetPlatform); + } + ProcessorDef[] defaultProviders = getDefaultProviders(baseDef); + Processor proc = getProcessor(); + return proc.createConfiguration(task, linkType, defaultProviders, this, targetPlatform); + } + /** + * Prepares list of processor arguments ( , ) that + * are active for the current project settings. + * + * @return active compiler arguments + */ + public CommandLineArgument[] getActiveProcessorArgs() { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project must be set"); + } + if (isReference()) { + return ((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")).getActiveProcessorArgs(); + } + Vector activeArgs = new Vector(processorArgs.size()); + for (int i = 0; i < processorArgs.size(); i++) { + CommandLineArgument arg = (CommandLineArgument) processorArgs + .elementAt(i); + if (arg.isActive(p)) { + activeArgs.addElement(arg); + } + } + CommandLineArgument[] array = new CommandLineArgument[activeArgs.size()]; + activeArgs.copyInto(array); + return array; + } + /** + * Prepares list of processor arguments ( , ) that + * are active for the current project settings. + * + * @return active compiler arguments + */ + public ProcessorParam[] getActiveProcessorParams() { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project must be set"); + } + if (isReference()) { + return ((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")).getActiveProcessorParams(); + } + Vector activeParams = new Vector(processorParams.size()); + for (int i = 0; i < processorParams.size(); i++) { + ProcessorParam param = (ProcessorParam) processorParams + .elementAt(i); + if (param.isActive(p)) { + activeParams.addElement(param); + } + } + ProcessorParam[] array = new ProcessorParam[activeParams.size()]; + activeParams.copyInto(array); + return array; + } + /** + * Gets boolean indicating debug build + * + * @param defaultProviders + * array of ProcessorDef's in descending priority + * @param index + * index to first element in array that should be considered + * @return if true, built targets for debugging + */ + public boolean getDebug(ProcessorDef[] defaultProviders, int index) { + if (isReference()) { + return ((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")).getDebug(defaultProviders, index); + } + if (debug != null) { + return debug.booleanValue(); + } else { + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getDebug(defaultProviders, + index + 1); + } + } + return false; + } + /** + * Creates an chain of objects which provide default values in descending + * order of significance. + * + * @param baseDef + * corresponding ProcessorDef from CCTask, will be last element + * in array unless inherit = false + * @return default provider array + * + */ + protected final ProcessorDef[] getDefaultProviders(ProcessorDef baseDef) { + ProcessorDef extendsDef = getExtends(); + Vector chain = new Vector(); + while (extendsDef != null && !chain.contains(extendsDef)) { + chain.addElement(extendsDef); + extendsDef = extendsDef.getExtends(); + } + if (baseDef != null && getInherit()) { + chain.addElement(baseDef); + } + ProcessorDef[] defaultProviders = new ProcessorDef[chain.size()]; + chain.copyInto(defaultProviders); + return defaultProviders; + } + /** + * Gets the ProcessorDef specified by the extends attribute + * + * @return Base ProcessorDef, null if extends is not specified + * @throws BuildException + * if reference is not same type object + */ + public ProcessorDef getExtends() throws BuildException { + if (extendsRef != null) { + Object obj = extendsRef.getReferencedObject(getProject()); + if (!getClass().isInstance(obj)) { + throw new BuildException("Referenced object " + + extendsRef.getRefId() + " not correct type, is " + + obj.getClass().getName() + " should be " + + getClass().getName()); + } + return (ProcessorDef) obj; + } + return null; + } + /** + * Gets the inherit attribute. If the inherit value is true, this processor + * definition will inherit default values from the containing element. + * + * @return if true then properties from the containing element are + * used. + */ + public final boolean getInherit() { + return inherit; + } + public boolean getLibtool() { + if (libtool != null) { + return libtool.booleanValue(); + } + if (isReference()) { + return ((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")).getLibtool(); + } + ProcessorDef extendsDef = getExtends(); + if (extendsDef != null) { + return extendsDef.getLibtool(); + } + return false; + } + /** + * Obtains the appropriate processor (compiler, linker) + * + * @return processor + */ + protected Processor getProcessor() { + if (isReference()) { + return ((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")).getProcessor(); + } + // + // if a processor has not been explicitly set + // then may be set by an extended definition + if (processor == null) { + ProcessorDef extendsDef = getExtends(); + if (extendsDef != null) { + return extendsDef.getProcessor(); + } + } + return processor; + } + /** + * Gets a boolean value indicating whether all targets must be rebuilt + * regardless of dependency analysis. + * + * @param defaultProviders + * array of ProcessorDef's in descending priority + * @param index + * index to first element in array that should be considered + * @return true if all targets should be rebuilt. + */ + public boolean getRebuild(ProcessorDef[] defaultProviders, int index) { + if (isReference()) { + return ((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")).getRebuild(defaultProviders, index); + } + if (rebuild != null) { + return rebuild.booleanValue(); + } else { + if (defaultProviders != null && index < defaultProviders.length) { + return defaultProviders[index].getRebuild(defaultProviders, + index + 1); + } + } + return false; + } + /** + * Returns true if the processor definition contains embedded file set + * definitions + * + * @return true if processor definition contains embedded filesets + */ + public boolean hasFileSets() { + if (isReference()) { + return ((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")).hasFileSets(); + } + return srcSets.size() > 0; + } + /** + * Determine if this def should be used. + * + * Definition will be active if the "if" variable (if specified) is set and + * the "unless" variable (if specified) is not set and that all reference + * or extended definitions are active + * + * @return true if processor is active + * @throws IllegalStateException + * if not properly initialized + * @throws BuildException + * if "if" or "unless" variable contains suspicious values + * "false" or "no" which indicates possible confusion + */ + public boolean isActive() throws BuildException, IllegalStateException { + Project project = getProject(); + if (!CUtil.isActive(project, ifProp, unlessProp)) { + return false; + } + if (isReference()) { + if (!((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")).isActive()) { + return false; + } + } + // + // walk through any extended definitions + // + ProcessorDef[] defaultProviders = getDefaultProviders(null); + for (int i = 0; i < defaultProviders.length; i++) { + if (!defaultProviders[i].isActive()) { + return false; + } + } + return true; + } + /** + * Sets the class name for the adapter. Use the "name" attribute when the + * tool is supported. + * + * @param className + * full class name + * + */ + public void setClassname(String className) throws BuildException { + Object proc = null; + try { + Class implClass = ProcessorDef.class.getClassLoader().loadClass( + className); + try { + Method getInstance = implClass.getMethod("getInstance", + new Class[0]); + proc = getInstance.invoke(null, new Object[0]); + } catch (Exception ex) { + proc = implClass.newInstance(); + } + } catch (Exception ex) { + throw new BuildException(ex); + } + setProcessor((Processor) proc); + } + /** + * If set true, all targets will be built for debugging. + * + * @param debug + * true if targets should be built for debugging + * @throws BuildException + * if processor definition is a reference + */ + public void setDebug(boolean debug) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + this.debug = booleanValueOf(debug); + } + /** + * Sets a description of the current data type. + */ + public void setDescription(String desc) { + super.setDescription(desc); + } + /** + * Specifies that this element extends the element with id attribute with a + * matching value. The configuration will be constructed from the settings + * of this element, element referenced by extends, and the containing cc + * element. + * + * @param extendsRef + * Reference to the extended processor definition. + * @throws BuildException + * if this processor definition is a reference + */ + public void setExtends(Reference extendsRef) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + this.extendsRef = extendsRef; + } + /** + * Sets an id that can be used to reference this element. + * + * @param id + * id + */ + public void setId(String id) { + // + // this is actually accomplished by a different + // mechanism, but we can document it + // + } + /** + * Sets the property name for the 'if' condition. + * + * The configuration will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + * + * @param propName + * name of property + */ + public void setIf(String propName) { + ifProp = propName; + } + /** + * If inherit has the default value of true, defines, includes and other + * settings from the containing element will be inherited. + * + * @param inherit + * new value + * @throws BuildException + * if processor definition is a reference + */ + public void setInherit(boolean inherit) throws BuildException { + if (isReference()) { + throw super.tooManyAttributes(); + } + this.inherit = inherit; + } + /** + * Set use of libtool. + * + * If set to true, the "libtool " will be prepended to the command line + * + * @param libtool + * If true, use libtool. + */ + public void setLibtool(boolean libtool) { + if (isReference()) { + throw tooManyAttributes(); + } + this.libtool = booleanValueOf(libtool); + } + /** + * Do not propagate old environment when new environment variables are + * specified. + */ + public void setNewenvironment(boolean newenv) { + newEnvironment = newenv; + } + /** + * Sets the processor + * + * @param processor + * processor, may not be null. + * @throws BuildException + * if ProcessorDef is a reference + * @throws NullPointerException + * if processor is null + */ + protected void setProcessor(Processor processor) throws BuildException, + NullPointerException { + if (processor == null) { + throw new NullPointerException("processor"); + } + if (isReference()) { + throw super.tooManyAttributes(); + } + if (env == null && !newEnvironment) { + this.processor = processor; + } else { + this.processor = processor.changeEnvironment(newEnvironment, env); + } + } + /** + * If set true, all targets will be unconditionally rebuilt. + * + * @param rebuild + * if true, rebuild all targets. + * @throws BuildException + * if processor definition is a reference + */ + public void setRebuild(boolean rebuild) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + this.rebuild = booleanValueOf(rebuild); + } + /** + * Specifies that this element should behave as if the content of the + * element with the matching id attribute was inserted at this location. If + * specified, no other attributes or child content should be specified, + * other than "if", "unless" and "description". + * + * @param ref + * Reference to other element + * + */ + public void setRefid(org.apache.tools.ant.types.Reference ref) { + super.setRefid(ref); + } + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the configuration will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public void setUnless(String propName) { + unlessProp = propName; + } + /** + * This method calls the FileVistor's visit function for every file in the + * processors definition + * + * @param visitor + * object whose visit method is called for every file + */ + public void visitFiles(FileVisitor visitor) { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException( + "project must be set before this call"); + } + if (isReference()) { + ((ProcessorDef) getCheckedRef(ProcessorDef.class, "ProcessorDef")) + .visitFiles(visitor); + } + // + // if this processor extends another, + // visit its files first + // + ProcessorDef extendsDef = getExtends(); + if (extendsDef != null) { + extendsDef.visitFiles(visitor); + } + for (int i = 0; i < srcSets.size(); i++) { + ConditionalFileSet srcSet = (ConditionalFileSet) srcSets + .elementAt(i); + if (srcSet.isActive()) { + // Find matching source files + DirectoryScanner scanner = srcSet.getDirectoryScanner(p); + // Check each source file - see if it needs compilation + String[] fileNames = scanner.getIncludedFiles(); + File parentDir = scanner.getBasedir(); + for (int j = 0; j < fileNames.length; j++) { + String currentFile = fileNames[j]; + visitor.visit(parentDir, currentFile); + } + } + } + } + public Vector getSrcSets() { + if (isReference()) { + return ((ProcessorDef) getCheckedRef(ProcessorDef.class, + "ProcessorDef")).getSrcSets(); + } + return srcSets; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ProcessorEnumValue.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ProcessorEnumValue.java new file mode 100644 index 0000000000..d028052232 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ProcessorEnumValue.java @@ -0,0 +1,47 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import net.sf.antcontrib.cpptasks.compiler.Processor; +/** + * One entry in the arrays used by the CompilerEnum and LinkerEnum classes. + * + * @author Curt Arnold + * @see CompilerEnum + * @see LinkerEnum + * + */ +public class ProcessorEnumValue { + public static String[] getValues(ProcessorEnumValue[] processors) { + String[] values = new String[processors.length]; + for (int i = 0; i < processors.length; i++) { + values[i] = processors[i].getName(); + } + return values; + } + private String name; + private Processor processor; + public ProcessorEnumValue(String name, Processor processor) { + this.name = name; + this.processor = processor; + } + public String getName() { + return name; + } + public Processor getProcessor() { + return processor; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ProcessorParam.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ProcessorParam.java new file mode 100644 index 0000000000..b2d47962ed --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ProcessorParam.java @@ -0,0 +1,100 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +/******************************************************************************* + * Place class description here. + * + * @author inger + * @author + * + * @since + ******************************************************************************/ +public class ProcessorParam { + private String ifCond; + private String name; + private String unlessCond; + private String value; + public ProcessorParam() { + } + public String getName() { + return name; + } + public String getValue() { + return value; + } + /** + * Returns true if the define's if and unless conditions (if any) are + * satisfied. + */ + public boolean isActive(org.apache.tools.ant.Project p) { + if (value == null) { + return false; + } + if (ifCond != null && p.getProperty(ifCond) == null) { + return false; + } else if (unlessCond != null && p.getProperty(unlessCond) != null) { + return false; + } + return true; + } + /** + * Sets the property name for the 'if' condition. + * + * The argument will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + */ + public void setIf(String propName) { + ifCond = propName; + } + /** + * Specifies relative location of argument on command line. "start" will + * place argument at start of command line, "mid" will place argument after + * all "start" arguments but before filenames, "end" will place argument + * after filenames. + * + */ + public void setName(String name) { + this.name = name; + } + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the argument will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public void setUnless(String propName) { + unlessCond = propName; + } + /** + * Specifies the string that should appear on the command line. The + * argument will be quoted if it contains embedded blanks. Use multiple + * arguments to avoid quoting. + * + */ + public void setValue(String value) { + this.value = value; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/RuntimeType.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/RuntimeType.java new file mode 100644 index 0000000000..02da661917 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/RuntimeType.java @@ -0,0 +1,26 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import org.apache.tools.ant.types.EnumeratedAttribute; +/** + * Enumerated attribute with the values "dynamic" and "static", + */ +public class RuntimeType extends EnumeratedAttribute { + public String[] getValues() { + return new String[]{"dynamic", "static"}; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/SourceHistory.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/SourceHistory.java new file mode 100644 index 0000000000..0c608b4d87 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/SourceHistory.java @@ -0,0 +1,51 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.File; +import java.io.IOException; +/** + * The history of a source file used to build a target + * + * @author Curt Arnold + */ +public final class SourceHistory { + private/* final */long lastModified; + private/* final */String relativePath; + /** + * Constructor + */ + public SourceHistory(String relativePath, long lastModified) { + if (relativePath == null) { + throw new NullPointerException("relativePath"); + } + this.relativePath = relativePath; + this.lastModified = lastModified; + } + public String getAbsolutePath(File baseDir) { + try { + return new File(baseDir, relativePath).getCanonicalPath(); + } catch (IOException ex) { + } + return relativePath; + } + public long getLastModified() { + return lastModified; + } + public String getRelativePath() { + return relativePath; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/SubsystemEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/SubsystemEnum.java new file mode 100644 index 0000000000..3dc342a38a --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/SubsystemEnum.java @@ -0,0 +1,34 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import org.apache.tools.ant.types.EnumeratedAttribute; +/** + * Enumeration of supported subsystems + * + * @author Curt Arnold + * + */ +public final class SubsystemEnum extends EnumeratedAttribute { + private final static String[] values = new String[]{"gui", "console", + "other"}; + public SubsystemEnum() { + setValue("gui"); + } + public String[] getValues() { + return (String[]) values.clone(); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetDef.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetDef.java new file mode 100644 index 0000000000..8e46cb7c6c --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetDef.java @@ -0,0 +1,228 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Reference; + +/** + * Information on the execution platforms for the generated code. + * (Non-functional prototype) + * + */ +public final class TargetDef + extends DataType { + /** + * if property. + */ + private String ifCond; + + /** + * unless property. + */ + private String unlessCond; + + /** + * cpu. + * + */ + private CPUEnum cpu; + + /** + * architecture. + * + */ + private ArchEnum arch; + + /** + * OS Family. + * + */ + private OSFamilyEnum osFamily; + + /** + * Constructor. + * + */ + public TargetDef() { + } + + /** + * Bogus method required for documentation generation. + */ + public void execute() { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + + /** + * Returns true if the define's if and unless conditions (if any) are + * satisfied. + * @return true if active + */ + public boolean isActive() { + return CUtil.isActive(getProject(), ifCond, unlessCond); + } + + /** + * Sets a description of the current data type. + * @param desc description + */ + public void setDescription(final String desc) { + super.setDescription(desc); + } + + /** + * Sets an id that can be used to reference this element. + * + * @param id + * id + */ + public void setId(final String id) { + // + // this is actually accomplished by a different + // mechanism, but we can document it + // + } + + /** + * Sets the property name for the 'if' condition. + * + * The define will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + * + * @param propName + * property name + */ + public void setIf(final String propName) { + ifCond = propName; + } + + /** + * Specifies that this element should behave as if the content of the + * element with the matching id attribute was inserted at this location. If + * specified, no other attributes should be specified. + * @param r id of referenced target + */ + public void setRefid(final Reference r) { + super.setRefid(r); + } + + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the define will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public void setUnless(final String propName) { + unlessCond = propName; + } + + /** + * Gets cpu. + * @return cpu, may be null. + * + */ + public CPUEnum getCpu() { + if (isReference()) { + TargetDef refPlatform = (TargetDef) + getCheckedRef(TargetDef.class, + "TargetDef"); + return refPlatform.getCpu(); + } + return cpu; + } + + /** + * Gets arch. + * @return arch, may be null. + * + */ + public ArchEnum getArch() { + if (isReference()) { + TargetDef refPlatform = (TargetDef) + getCheckedRef(TargetDef.class, + "TargetDef"); + return refPlatform.getArch(); + } + return arch; + } + + /** + * Gets operating system family. + * @return os family, may be null. + * + */ + public OSFamilyEnum getOsfamily() { + if (isReference()) { + TargetDef refPlatform = (TargetDef) + getCheckedRef(TargetDef.class, + "TargetDef"); + return refPlatform.getOsfamily(); + } + return osFamily; + } + + /** + * Sets preferred cpu, but does not use cpu specific instructions. + * @param value new value + */ + public void setCpu(final CPUEnum value) { + if (isReference()) { + throw tooManyAttributes(); + } + cpu = value; + } + + /** + * Sets cpu architecture, compiler may use cpu specific instructions. + * @param value new value + */ + public void setArch(final ArchEnum value) { + if (isReference()) { + throw tooManyAttributes(); + } + if (cpu != null) { + throw tooManyAttributes(); + } + arch = value; + } + + /** + * Sets operating system family. + * @param value new value + */ + public void setOsfamily(final OSFamilyEnum value) { + if (isReference()) { + throw tooManyAttributes(); + } + if (cpu != null) { + throw tooManyAttributes(); + } + osFamily = value; + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetHistory.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetHistory.java new file mode 100644 index 0000000000..0094c8ecec --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetHistory.java @@ -0,0 +1,58 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +/** + * A description of a file built or to be built + */ +public final class TargetHistory { + private/* final */String config; + private/* final */String output; + private/* final */long outputLastModified; + private/* final */SourceHistory[] sources; + /** + * Constructor from build step + */ + public TargetHistory(String config, String output, long outputLastModified, + SourceHistory[] sources) { + if (config == null) { + throw new NullPointerException("config"); + } + if (sources == null) { + throw new NullPointerException("source"); + } + if (output == null) { + throw new NullPointerException("output"); + } + this.config = config; + this.output = output; + this.outputLastModified = outputLastModified; + this.sources = (SourceHistory[]) sources.clone(); + } + public String getOutput() { + return output; + } + public long getOutputLastModified() { + return outputLastModified; + } + public String getProcessorConfiguration() { + return config; + } + public SourceHistory[] getSources() { + SourceHistory[] clone = (SourceHistory[]) sources.clone(); + return clone; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetHistoryTable.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetHistoryTable.java new file mode 100644 index 0000000000..9fb0a7b642 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetHistoryTable.java @@ -0,0 +1,426 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.UnsupportedEncodingException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; + +import javax.xml.parsers.SAXParser; +import javax.xml.parsers.SAXParserFactory; + +import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; + +import org.apache.tools.ant.BuildException; +import org.xml.sax.Attributes; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.DefaultHandler; +/** + * A history of the compiler and linker settings used to build the files in the + * same directory as the history. + * + * @author Curt Arnold + */ +public final class TargetHistoryTable { + /** + * This class handles populates the TargetHistory hashtable in response to + * SAX parse events + */ + private class TargetHistoryTableHandler extends DefaultHandler { + private final File baseDir; + private String config; + private final Hashtable history; + private String output; + private long outputLastModified; + private final Vector sources = new Vector(); + /** + * Constructor + * + * @param history + * hashtable of TargetHistory keyed by output name + * @param outputFiles + * existing files in output directory + */ + private TargetHistoryTableHandler(Hashtable history, File baseDir) { + this.history = history; + config = null; + output = null; + this.baseDir = baseDir; + } + public void endElement(String namespaceURI, String localName, + String qName) throws SAXException { + // + // if then + // create TargetHistory object and add to hashtable + // if corresponding output file exists and + // has the same timestamp + // + if (qName.equals("target")) { + if (config != null && output != null) { + File existingFile = new File(baseDir, output); + // + // if the corresponding files doesn't exist or has a + // different + // modification time, then discard this record + if (existingFile.exists()) { + long existingLastModified = existingFile.lastModified(); + // + // would have expected exact time stamps + // but have observed slight differences + // in return value for multiple evaluations of + // lastModified(). Check if times are within + // a second + long diff = outputLastModified - existingLastModified; + if (diff >= -500 && diff <= 500) { + SourceHistory[] sourcesArray = new SourceHistory[sources + .size()]; + sources.copyInto(sourcesArray); + TargetHistory targetHistory = new TargetHistory( + config, output, outputLastModified, + sourcesArray); + history.put(output, targetHistory); + } + } + } + output = null; + sources.setSize(0); + } else { + // + // reset config so targets not within a processor element + // don't pick up a previous processors signature + // + if (qName.equals("processor")) { + config = null; + } + } + } + /** + * startElement handler + */ + public void startElement(String namespaceURI, String localName, + String qName, Attributes atts) throws SAXException { + // + // if sourceElement + // + if (qName.equals("source")) { + String sourceFile = atts.getValue("file"); + long sourceLastModified = Long.parseLong(atts + .getValue("lastModified"), 16); + sources.addElement(new SourceHistory(sourceFile, + sourceLastModified)); + } else { + // + // if element, + // grab file name and lastModified values + // TargetHistory object will be created in endElement + // + if (qName.equals("target")) { + sources.setSize(0); + output = atts.getValue("file"); + outputLastModified = Long.parseLong(atts + .getValue("lastModified"), 16); + } else { + // + // if element, + // grab signature attribute + // + if (qName.equals("processor")) { + config = atts.getValue("signature"); + } + } + } + } + } + /** Flag indicating whether the cache should be written back to file. */ + private boolean dirty; + /** + * a hashtable of TargetHistory's keyed by output file name + */ + private final Hashtable history = new Hashtable(); + /** The file the cache was loaded from. */ + private/* final */File historyFile; + private/* final */File outputDir; + private String outputDirPath; + /** + * Creates a target history table from history.xml in the output directory, + * if it exists. Otherwise, initializes the history table empty. + * + * @param task + * task used for logging history load errors + * @param outputDir + * output directory for task + */ + public TargetHistoryTable(CCTask task, File outputDir) + throws BuildException { + if (outputDir == null) { + throw new NullPointerException("outputDir"); + } + if (!outputDir.isDirectory()) { + throw new BuildException("Output directory is not a directory"); + } + if (!outputDir.exists()) { + throw new BuildException("Output directory does not exist"); + } + this.outputDir = outputDir; + try { + outputDirPath = outputDir.getCanonicalPath(); + } catch (IOException ex) { + outputDirPath = outputDir.toString(); + } + // + // load any existing history from file + // suppressing any records whose corresponding + // file does not exist, is zero-length or + // last modified dates differ + historyFile = new File(outputDir, "history.xml"); + if (historyFile.exists()) { + SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setValidating(false); + try { + SAXParser parser = factory.newSAXParser(); + parser.parse(historyFile, new TargetHistoryTableHandler( + history, outputDir)); + } catch (Exception ex) { + // + // a failure on loading this history is not critical + // but should be logged + task.log("Error reading history.xml: " + ex.toString()); + } + } else { + // + // create empty history file for identifying new files by last + // modified + // timestamp comperation (to compare with + // System.currentTimeMillis() don't work on Unix, because it + // maesure timestamps only in seconds). + // + try { + FileOutputStream outputStream = new FileOutputStream( + historyFile); + byte[] historyElement = new byte[]{0x3C, 0x68, 0x69, 0x73, + 0x74, 0x6F, 0x72, 0x79, 0x2F, 0x3E}; + outputStream.write(historyElement); + outputStream.close(); + } catch (IOException ex) { + throw new BuildException("Can't create history file", ex); + } + } + } + public void commit() throws IOException { + // + // if not dirty, no need to update file + // + if (dirty) { + // + // build (small) hashtable of config id's in history + // + Hashtable configs = new Hashtable(20); + Enumeration elements = history.elements(); + while (elements.hasMoreElements()) { + TargetHistory targetHistory = (TargetHistory) elements + .nextElement(); + String configId = targetHistory.getProcessorConfiguration(); + if (configs.get(configId) == null) { + configs.put(configId, configId); + } + } + FileOutputStream outStream = new FileOutputStream(historyFile); + OutputStreamWriter outWriter; + // + // early VM's don't support UTF-8 encoding + // try and fallback to the default encoding + // otherwise + String encodingName = "UTF-8"; + try { + outWriter = new OutputStreamWriter(outStream, "UTF-8"); + } catch (UnsupportedEncodingException ex) { + outWriter = new OutputStreamWriter(outStream); + encodingName = outWriter.getEncoding(); + } + BufferedWriter writer = new BufferedWriter(outWriter); + writer.write("\n"); + writer.write("\n"); + StringBuffer buf = new StringBuffer(200); + Enumeration configEnum = configs.elements(); + while (configEnum.hasMoreElements()) { + String configId = (String) configEnum.nextElement(); + buf.setLength(0); + buf.append(" \n"); + writer.write(buf.toString()); + elements = history.elements(); + while (elements.hasMoreElements()) { + TargetHistory targetHistory = (TargetHistory) elements + .nextElement(); + if (targetHistory.getProcessorConfiguration().equals( + configId)) { + buf.setLength(0); + buf.append(" \n"); + writer.write(buf.toString()); + SourceHistory[] sourceHistories = targetHistory + .getSources(); + for (int i = 0; i < sourceHistories.length; i++) { + buf.setLength(0); + buf.append(" \n"); + writer.write(buf.toString()); + } + writer.write(" \n"); + } + } + writer.write(" \n"); + } + writer.write("\n"); + writer.close(); + dirty = false; + } + } + public TargetHistory get(String configId, String outputName) { + TargetHistory targetHistory = (TargetHistory) history.get(outputName); + if (targetHistory != null) { + if (!targetHistory.getProcessorConfiguration().equals(configId)) { + targetHistory = null; + } + } + return targetHistory; + } + public void markForRebuild(Hashtable targetInfos) { + Enumeration targetInfoEnum = targetInfos.elements(); + while (targetInfoEnum.hasMoreElements()) { + markForRebuild((TargetInfo) targetInfoEnum.nextElement()); + } + } + public void markForRebuild(TargetInfo targetInfo) { + // + // if it must already be rebuilt, no need to check further + // + if (!targetInfo.getRebuild()) { + TargetHistory history = get(targetInfo.getConfiguration() + .toString(), targetInfo.getOutput().getName()); + if (history == null) { + targetInfo.mustRebuild(); + } else { + SourceHistory[] sourceHistories = history.getSources(); + File[] sources = targetInfo.getSources(); + if (sourceHistories.length != sources.length) { + targetInfo.mustRebuild(); + } else { + for (int i = 0; i < sourceHistories.length + && !targetInfo.getRebuild(); i++) { + // + // relative file name, must absolutize it on output + // directory + // + boolean foundMatch = false; + String historySourcePath = sourceHistories[i] + .getAbsolutePath(outputDir); + for (int j = 0; j < sources.length; j++) { + File targetSource = sources[j]; + String targetSourcePath = targetSource + .getAbsolutePath(); + if (targetSourcePath.equals(historySourcePath)) { + foundMatch = true; + if (targetSource.lastModified() != sourceHistories[i] + .getLastModified()) { + targetInfo.mustRebuild(); + break; + } + } + } + if (!foundMatch) { + targetInfo.mustRebuild(); + } + } + } + } + } + } + public void update(ProcessorConfiguration config, String[] sources) { + String configId = config.getIdentifier(); + String[] onesource = new String[1]; + String outputName; + for (int i = 0; i < sources.length; i++) { + onesource[0] = sources[i]; + outputName = config.getOutputFileName(sources[i]); + update(configId, outputName, onesource); + } + } + private void update(String configId, String outputName, String[] sources) { + File outputFile = new File(outputDir, outputName); + // + // if output file doesn't exist or predates the start of the + // compile step (most likely a compilation error) then + // do not write add a history entry + // + if (outputFile.exists() + && outputFile.lastModified() >= historyFile.lastModified()) { + dirty = true; + history.remove(outputName); + SourceHistory[] sourceHistories = new SourceHistory[sources.length]; + for (int i = 0; i < sources.length; i++) { + File sourceFile = new File(sources[i]); + long lastModified = sourceFile.lastModified(); + String relativePath = CUtil.getRelativePath(outputDirPath, + sourceFile); + sourceHistories[i] = new SourceHistory(relativePath, + lastModified); + } + TargetHistory newHistory = new TargetHistory(configId, outputName, + outputFile.lastModified(), sourceHistories); + history.put(outputName, newHistory); + } + } + public void update(TargetInfo linkTarget) { + File outputFile = linkTarget.getOutput(); + String outputName = outputFile.getName(); + // + // if output file doesn't exist or predates the start of the + // compile or link step (most likely a compilation error) then + // do not write add a history entry + // + if (outputFile.exists() + && outputFile.lastModified() >= historyFile.lastModified()) { + dirty = true; + history.remove(outputName); + SourceHistory[] sourceHistories = linkTarget + .getSourceHistories(outputDirPath); + TargetHistory newHistory = new TargetHistory(linkTarget + .getConfiguration().getIdentifier(), outputName, outputFile + .lastModified(), sourceHistories); + history.put(outputName, newHistory); + } + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetInfo.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetInfo.java new file mode 100644 index 0000000000..3a9dd14b16 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetInfo.java @@ -0,0 +1,127 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.File; + +import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; +/** + * A description of a file built or to be built + */ +public final class TargetInfo { + private static final File[] emptyFileArray = new File[0]; + private/* final */ProcessorConfiguration config; + private/* final */File output; + private boolean rebuild; + private/* final */File[] sources; + private File[] sysSources; + public TargetInfo(ProcessorConfiguration config, File[] sources, + File[] sysSources, File output, boolean rebuild) { + if (config == null) { + throw new NullPointerException("config"); + } + if (sources == null) { + throw new NullPointerException("sources"); + } + if (output == null) { + throw new NullPointerException("output"); + } + this.config = config; + this.sources = (File[]) sources.clone(); + if (sysSources == null) { + this.sysSources = emptyFileArray; + } else { + this.sysSources = (File[]) sysSources.clone(); + } + this.output = output; + this.rebuild = rebuild; + // + // if the output doesn't exist, must rebuild it + // + if (!output.exists()) { + rebuild = true; + } + } + public String[] getAllSourcePaths() { + String[] paths = new String[sysSources.length + sources.length]; + for (int i = 0; i < sysSources.length; i++) { + paths[i] = sysSources[i].toString(); + } + int offset = sysSources.length; + for (int i = 0; i < sources.length; i++) { + paths[offset + i] = sources[i].toString(); + } + return paths; + } + public File[] getAllSources() { + File[] allSources = new File[sources.length + sysSources.length]; + for (int i = 0; i < sysSources.length; i++) { + allSources[i] = sysSources[i]; + } + int offset = sysSources.length; + for (int i = 0; i < sources.length; i++) { + allSources[i + offset] = sources[i]; + } + return allSources; + } + public ProcessorConfiguration getConfiguration() { + return config; + } + public File getOutput() { + return output; + } + public boolean getRebuild() { + return rebuild; + } + /** + * Returns an array of SourceHistory objects (contains relative path and + * last modified time) for the source[s] of this target + */ + public SourceHistory[] getSourceHistories(String basePath) { + SourceHistory[] histories = new SourceHistory[sources.length]; + for (int i = 0; i < sources.length; i++) { + String relativeName = CUtil.getRelativePath(basePath, sources[i]); + long lastModified = sources[i].lastModified(); + histories[i] = new SourceHistory(relativeName, lastModified); + } + return histories; + } + public String[] getSourcePaths() { + String[] paths = new String[sources.length]; + for (int i = 0; i < sources.length; i++) { + paths[i] = sources[i].toString(); + } + return paths; + } + public File[] getSources() { + File[] clone = (File[]) sources.clone(); + return clone; + } + public String[] getSysSourcePaths() { + String[] paths = new String[sysSources.length]; + for (int i = 0; i < sysSources.length; i++) { + paths[i] = sysSources[i].toString(); + } + return paths; + } + public File[] getSysSources() { + File[] clone = (File[]) sysSources.clone(); + return clone; + } + public void mustRebuild() { + this.rebuild = true; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetMatcher.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetMatcher.java new file mode 100644 index 0000000000..2574e1561f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/TargetMatcher.java @@ -0,0 +1,117 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; +import java.io.File; +import java.util.Hashtable; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.LinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.ProcessorConfiguration; + +import org.apache.tools.ant.BuildException; +/** + * This class matches each visited file with an appropriate compiler + * + * @author Curt Arnold + */ +public final class TargetMatcher implements FileVisitor { + private LinkerConfiguration linker; + private Vector objectFiles; + private File outputDir; + private ProcessorConfiguration[] processors; + private final File sourceFiles[] = new File[1]; + private Hashtable targets; + private CCTask task; + public TargetMatcher(CCTask task, File outputDir, + ProcessorConfiguration[] processors, LinkerConfiguration linker, + Vector objectFiles, Hashtable targets) { + this.task = task; + this.outputDir = outputDir; + this.processors = processors; + this.targets = targets; + this.linker = linker; + this.objectFiles = objectFiles; + } + public void visit(File parentDir, String filename) throws BuildException { + // + // see if any processor wants to bid + // on this one + ProcessorConfiguration selectedCompiler = null; + int bid = 0; + if (processors != null) { + for (int k = 0; k < processors.length; k++) { + int newBid = processors[k].bid(filename); + if (newBid > bid) { + bid = newBid; + selectedCompiler = processors[k]; + } + } + } + // + // no processor interested in file + // log diagnostic message + if (bid <= 0) { + if (linker != null) { + int linkerbid = linker.bid(filename); + if (linkerbid > 0) { + File objFile = new File(parentDir, filename); + objectFiles.addElement(objFile); + if (linkerbid == 1) { + task.log("Unrecognized file type " + objFile.toString() + + " will be passed to linker"); + } + } + } + } else { + // + // get output file name + // + String outputFileName = selectedCompiler + .getOutputFileName(filename); + // + // if there is some output for this task + // (that is a source file and not an header file) + // + if (outputFileName != null) { + sourceFiles[0] = new File(parentDir, filename); + // + // see if the same output file has already been registered + // + TargetInfo previousTarget = (TargetInfo) targets + .get(outputFileName); + if (previousTarget == null) { + targets.put(outputFileName, new TargetInfo( + selectedCompiler, sourceFiles, null, new File( + outputDir, outputFileName), + selectedCompiler.getRebuild())); + } else { + if (!previousTarget.getSources()[0].equals(sourceFiles[0])) { + StringBuffer builder = new StringBuffer( + "Output filename conflict: "); + builder.append(outputFileName); + builder.append(" would be produced from "); + builder.append(previousTarget.getSources()[0] + .toString()); + builder.append(" and "); + builder.append(filename); + throw new BuildException(builder.toString()); + } + } + } + } + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/VersionInfo.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/VersionInfo.java new file mode 100644 index 0000000000..f55b976fef --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/VersionInfo.java @@ -0,0 +1,550 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks; + +import java.io.IOException; +import java.io.Writer; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Reference; + +/** + * Version Information. (Non-functional prototype) + * + */ +public class VersionInfo extends DataType { + /** + * if property. + */ + private String ifCond; + /** + * unless property. + */ + private String unlessCond; + + /** + * extends property. + */ + private String extendsId; + + /** + * file version. + * + */ + private String fileVersion; + /** + * Product version. + * + */ + private String productVersion; + /** + * file language. + * + */ + private String language; + + /** + * comments. + * + */ + private String fileComments; + /** + * Company name. + * + */ + private String companyName; + /** + * Description. + * + */ + private String description; + /** + * internal name. + */ + private String internalName; + /** + * legal copyright. + * + */ + private String legalCopyright; + /** + * legal trademark. + * + */ + private String legalTrademark; + /** + * original filename. + * + */ + private String originalFilename; + /** + * private build. + * + */ + private String privateBuild; + /** + * product name. + * + */ + private String productName; + /** + * Special build + */ + private String specialBuild; + /** + * compatibility version + * + */ + private String compatibilityVersion; + + + /** + * Constructor. + * + */ + public VersionInfo() { + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + /** + * Returns true if the define's if and unless conditions (if any) are + * satisfied. + * + * @exception BuildException + * throws build exception if name is not set + */ + public final boolean isActive() throws BuildException { + return CUtil.isActive(getProject(), ifCond, unlessCond); + } + /** + * Sets an id that can be used to reference this element. + * + * @param id + * id + */ + public void setId(String id) { + // + // this is actually accomplished by a different + // mechanism, but we can document it + // + } + /** + * Sets the name of a version info that this info extends. + * + * @param id + * id + */ + public void setExtends(String id) { + extendsId = id; + } + + + /** + * Sets the property name for the 'if' condition. + * + * The define will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + * + * @param propName + * property name + */ + public final void setIf(String propName) { + ifCond = propName; + } + /** + * Specifies that this element should behave as if the content of the + * element with the matching id attribute was inserted at this location. If + * specified, no other attributes should be specified. + * + */ + public void setRefid(Reference r) throws BuildException { + super.setRefid(r); + } + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the define will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public final void setUnless(String propName) { + unlessCond = propName; + } + /** + * Gets file version. + * @return file version, may be null. + * + */ + public String getFileversion() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getFileversion(); + } + return fileVersion; + } + /** + * Gets Product version. + * @return product version, may be null + */ + public String getProductversion() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getProductversion(); + } + return productVersion; + } + /** + * Gets compatibility version. + * @return compatibility version, may be null + */ + public String getCompatibilityversion() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getCompatibilityversion(); + } + return compatibilityVersion; + } + /** + * Gets file language, should be an IETF RFC 3066 identifier, for example, en-US. + * @return language, may be null. + */ + public String getLanguage() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getLanguage(); + } + return language; + } + + /** + * Gets comments. + * @return comments, may be null. + */ + public String getFilecomments() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getFilecomments(); + } + return fileComments; + } + /** + * Gets Company name. + * @return company name, may be null. + */ + public String getCompanyname() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getCompanyname(); + } + return companyName; + } + /** + * Gets Description. + * @return description, may be null. + */ + public String getDescription() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getDescription(); + } + return description; + } + /** + * Gets internal name. + * @return internal name, may be null. + */ + public String getInternalname() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getInternalname(); + } + return internalName; + } + /** + * Gets legal copyright. + * @return legal copyright, may be null. + */ + public String getLegalcopyright() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getLegalcopyright(); + } + return legalCopyright; + } + /** + * Gets legal trademark. + * @return legal trademark, may be null; + */ + public String getLegaltrademark() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getLegaltrademark(); + } + return legalTrademark; + } + /** + * Gets original filename. + * @return original filename, may be null. + */ + public String getOriginalfilename() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getOriginalfilename(); + } + return originalFilename; + } + /** + * Gets private build. + * @return private build, may be null. + */ + public String getPrivatebuild() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getPrivatebuild(); + } + return privateBuild; + } + /** + * Gets product name. + * @return product name, may be null. + */ + public String getProductname() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getProductname(); + } + return productName; + } + /** + * Special build + * @return special build, may be null. + */ + public String getSpecialbuild() { + if (isReference()) { + VersionInfo refVersion = (VersionInfo) + getCheckedRef(VersionInfo.class, + "VersionInfo"); + return refVersion.getSpecialbuild(); + } + return specialBuild; + } + + /** + * Sets file version. + * @param value new value + * @throws BuildException if specified with refid + */ + public void setFileversion(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + fileVersion = value; + } + /** + * Sets product version. + * @param value new value + * @throws BuildException if specified with refid + */ + public void setProductversion(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + productVersion = value; + } + /** + * Sets compatibility version. + * @param value new value + * @throws BuildException if specified with refid + */ + public void setCompatibilityversion(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + compatibilityVersion = value; + } + /** + * Sets language. + * @param value new value, should be an IETF RFC 3066 language identifier. + * @throws BuildException if specified with refid + */ + public void setLanguage(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + language = value; + } + /** + * Sets comments. + * @param value new value + * @throws BuildException if specified with refid + */ + public void setFilecomments(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + fileComments = value; + } + + /** + * Sets company name. + * @param value new value + * @throws BuildException if specified with refid + */ + public void setCompanyname(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + companyName = value; + } + + + /** + * Sets internal name. Internal name will automatically be + * specified from build step, only set this value if + * intentionally overriding that value. + * + * @param value new value + * @throws BuildException if specified with refid + */ + public void setInternalname(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + internalName = value; + } + + /** + * Sets legal copyright. + * @param value new value + * @throws BuildException if specified with refid + */ + public void setLegalcopyright(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + legalCopyright = value; + } + /** + * Sets legal trademark. + * @param value new value + * @throws BuildException if specified with refid + */ + public void setLegaltrademark(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + legalTrademark = value; + } + /** + * Sets original name. Only set this value if + * intentionally overriding the value from the build set. + * + * @param value new value + * @throws BuildException if specified with refid + */ + public void setOriginalfilename(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + originalFilename = value; + } + /** + * Sets private build. + * @param value new value + * @throws BuildException if specified with refid + */ + public void setPrivatebuild(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + privateBuild = value; + } + /** + * Sets product name. + * @param value new value + * @throws BuildException if specified with refid + */ + public void setProductname(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + productName= value; + } + /** + * Sets private build. + * @param value new value + * @throws BuildException if specified with refid + */ + public void setSpecialbuild(String value) throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + specialBuild = value; + } + + /** + * Writes windows resource + * @param writer writer, may not be null. + * @param project project, may not be null + * @param executableName name of executable + */ + public void writeResource(final Writer writer, + final Project p, + final String executableName) throws IOException { + // TODO: + + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/arm/ADSCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/arm/ADSCCompiler.java new file mode 100644 index 0000000000..78489b8c31 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/arm/ADSCCompiler.java @@ -0,0 +1,215 @@ +/* + * + * Copyright 2003-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.arm; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.OptimizationEnum; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the ARM C Compilers + * + * See Doc No: ARM DUI 0151A, Issued: Nov 2001 at + * http://www.arm.com/arm/User_Guides?OpenDocument + * + * @author Curt Arnold + * + */ +public class ADSCCompiler extends CommandLineCCompiler { + /** + * Header file extensions + */ + private static final String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + /** + * Source file extensions + */ + private static final String[] sourceExtensions = new String[]{".c", ".cc", + ".cpp", ".cxx", ".c++"}; + /** + * Singleton for ARM 32-bit C compiler + */ + private static final ADSCCompiler armcc = new ADSCCompiler("armcc", false, + null); + /** + * Singleton for ARM 32-bit C++ compiler + */ + private static final ADSCCompiler armcpp = new ADSCCompiler("armcpp", + false, null); + /** + * Singleton for ARM 16-bit C compiler + */ + private static final ADSCCompiler tcc = new ADSCCompiler("tcc", false, null); + /** + * Singleton for ARM 16-bit C++ compiler + */ + private static final ADSCCompiler tcpp = new ADSCCompiler("tcpp", false, + null); + /** + * Singleton for ARM 32-bit C compiler + */ + public static ADSCCompiler getArmCC() { + return armcc; + } + /** + * Singleton for ARM 32-bit C++ compiler + */ + public static ADSCCompiler getArmCpp() { + return armcpp; + } + /** + * Singleton for ARM 16-bit C compiler + */ + public static ADSCCompiler getThumbCC() { + return tcpp; + } + /** + * Singleton for ARM 16-bit C++ compiler + */ + public static ADSCCompiler getThumbCpp() { + return tcpp; + } + private static void quoteFile(StringBuffer buf, String outPath) { + if (outPath.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(outPath); + buf.append('\"'); + } else { + buf.append(outPath); + } + } + /** + * Private constructor + * + * @param command + * executable name + * @param newEnvironment + * Change environment + * @param env + * New environment + */ + private ADSCCompiler(String command, boolean newEnvironment, Environment env) { + super(command, "-vsn", sourceExtensions, headerExtensions, ".o", false, + null, newEnvironment, env); + } + /** + * Adds command switches for generic configuration options + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#addImpliedArgs(java.util.Vector, + * boolean, boolean, boolean, + * net.sf.antcontrib.cpptasks.compiler.LinkType) + */ + protected void addImpliedArgs(Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + if (debug) { + args.addElement("-g"); + } + // + // didn't see anything about producing + // anything other than executables in the docs + if (linkType.isExecutable()) { + } else if (linkType.isSharedLibrary()) { + } + } + /** + * Adds flags that customize the warnings reported + * + * Compiler does not appear to have warning levels but ability to turn off + * specific errors by explicit switches, could fabricate levels by + * prioritizing errors. + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#addWarningSwitch(java.util.Vector, + * int) + */ + protected void addWarningSwitch(Vector args, int warnings) { + } + /** + * Add command line options for preprocessor macro + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#getDefineSwitch(java.lang.StringBuffer, + * java.lang.String, java.lang.String) + */ + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + buffer.append("-D"); + buffer.append(define); + if (value != null) { + buffer.append('='); + buffer.append(value); + } + } + /** + * ARMINC environment variable contains the default include path + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#getEnvironmentIncludePath() + */ + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("ARMINC", ";"); + } + /** + * Returns command line option to specify include directory + * + */ + protected String getIncludeDirSwitch(String source) { + StringBuffer buf = new StringBuffer("-I"); + quoteFile(buf, source); + return buf.toString(); + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Processor#getLinker(net.sf.antcontrib.cpptasks.compiler.LinkType) + */ + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return ADSLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return ADSLinker.getDllInstance(); + } + return ADSLinker.getInstance(); + } + /** + * Maximum command line length + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#getMaximumCommandLength() + */ + public int getMaximumCommandLength() { + return 1000; + } + /* + * Adds command to undefine preprocessor macro + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#getUndefineSwitch(java.lang.StringBuffer, + * java.lang.String) + */ + protected void getUndefineSwitch(StringBuffer buffer, String define) { + buffer.append("-U"); + buffer.append(define); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/arm/ADSLibrarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/arm/ADSLibrarian.java new file mode 100644 index 0000000000..0ff53d309f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/arm/ADSLibrarian.java @@ -0,0 +1,160 @@ +/* + * + * Copyright 2003-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.arm; + +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * Adapter for ARM Librarian + * + * @author Curt Arnold + */ +public class ADSLibrarian extends CommandLineLinker { + + private static final ADSLibrarian instance = new ADSLibrarian(); + + public static ADSLibrarian getInstance() { + return instance; + } + + private ADSLibrarian() + { + super("armar",null, + new String[] { ".o" }, new String[0], ".lib", false, null); + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addBase(long, java.util.Vector) + */ + protected void addBase(long base, Vector args) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addFixed(java.lang.Boolean, java.util.Vector) + */ + protected void addFixed(Boolean fixed, Vector args) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addImpliedArgs(boolean, net.sf.antcontrib.cpptasks.compiler.LinkType, java.util.Vector) + */ + protected void addImpliedArgs( + boolean debug, + LinkType linkType, + Vector args, + Boolean defaultflag) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addIncremental(boolean, java.util.Vector) + */ + protected void addIncremental(boolean incremental, Vector args) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addMap(boolean, java.util.Vector) + */ + protected void addMap(boolean map, Vector args) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addStack(int, java.util.Vector) + */ + protected void addStack(int stack, Vector args) { + // TODO Auto-generated method stub + + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getCommandFileSwitch(java.lang.String) + */ + protected String getCommandFileSwitch(String commandFile) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.Linker#getLibraryPath() + */ + public File[] getLibraryPath() { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.Linker#getLibraryPatterns(java.lang.String[]) + */ + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + return new String[0]; + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.Processor#getLinker(net.sf.antcontrib.cpptasks.compiler.LinkType) + */ + public Linker getLinker(LinkType linkType) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getMaximumCommandLength() + */ + protected int getMaximumCommandLength() { + // TODO Auto-generated method stub + return 0; + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getOutputFileSwitch(java.lang.String) + */ + protected String[] getOutputFileSwitch(String outputFile) { + // TODO Auto-generated method stub + return null; + } + + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.Linker#isCaseSensitive() + */ + public boolean isCaseSensitive() { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/arm/ADSLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/arm/ADSLinker.java new file mode 100644 index 0000000000..042eb217ec --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/arm/ADSLinker.java @@ -0,0 +1,166 @@ +/* + * + * Copyright 2003-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.arm; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * Adapter for the ARM Linker + * + * @author CurtA + */ +public class ADSLinker extends CommandLineLinker { + private static final ADSLinker dllInstance = new ADSLinker(".o"); + private static final ADSLinker instance = new ADSLinker(".axf"); + public static ADSLinker getDllInstance() { + return dllInstance; + } + public static ADSLinker getInstance() { + return instance; + } + private ADSLinker(String outputSuffix) { + super("armlink", "-vsn", new String[]{".o", ".lib", ".res"}, + new String[]{".map", ".pdb", ".lnk"}, outputSuffix, false, null); + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addBase(long, + * java.util.Vector) + */ + protected void addBase(long base, Vector args) { + // TODO Auto-generated method stub + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addFixed(java.lang.Boolean, + * java.util.Vector) + */ + protected void addFixed(Boolean fixed, Vector args) { + // TODO Auto-generated method stub + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addImpliedArgs(boolean, + * net.sf.antcontrib.cpptasks.compiler.LinkType, java.util.Vector) + */ + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + if (debug) { + args.addElement("-debug"); + } + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addIncremental(boolean, + * java.util.Vector) + */ + protected void addIncremental(boolean incremental, Vector args) { + // TODO Auto-generated method stub + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addMap(boolean, + * java.util.Vector) + */ + protected void addMap(boolean map, Vector args) { + // TODO Auto-generated method stub + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addStack(int, + * java.util.Vector) + */ + protected void addStack(int stack, Vector args) { + // TODO Auto-generated method stub + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + // TODO Auto-generated method stub + + } + + /** + * May have to make this String array return + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getCommandFileSwitch(java.lang.String) + */ + protected String getCommandFileSwitch(String commandFile) { + return "-via" + commandFile; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Linker#getLibraryPath() + */ + public File[] getLibraryPath() { + return CUtil.getPathFromEnvironment("ARMLIB", ";"); + } + /* + * @see net.sf.antcontrib.cpptasks.compiler.Linker#getLibraryPatterns(java.lang.String[]) + */ + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + // + // TODO: looks like bad extension + // + return new String[]{".o"}; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Processor#getLinker(net.sf.antcontrib.cpptasks.compiler.LinkType) + */ + public Linker getLinker(LinkType linkType) { + return this; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getMaximumCommandLength() + */ + protected int getMaximumCommandLength() { + return 1024; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getOutputFileSwitch(java.lang.String) + */ + protected String[] getOutputFileSwitch(String outputFile) { + return new String[]{"-output", outputFile}; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Linker#isCaseSensitive() + */ + public boolean isCaseSensitive() { + return false; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandCCompiler.java new file mode 100644 index 0000000000..3304c9a860 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandCCompiler.java @@ -0,0 +1,135 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.borland; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.CompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.PrecompilingCommandLineCCompiler; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the Borland(r) C/C++ compiler. + * + * @author Curt Arnold + */ +public class BorlandCCompiler extends PrecompilingCommandLineCCompiler { + private static final String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + private static final String[] sourceExtensions = new String[]{".c", ".cc", + ".cpp", ".cxx", ".c++"}; + private static final BorlandCCompiler instance = new BorlandCCompiler( + false, null); + public static BorlandCCompiler getInstance() { + return instance; + } + private BorlandCCompiler(boolean newEnvironment, Environment env) { + super("bcc32", "--version", sourceExtensions, headerExtensions, ".obj", false, + null, newEnvironment, env); + } + protected void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + args.addElement("-c"); + // + // turn off compiler autodependency since + // we do it ourselves + args.addElement("-X"); + if (exceptions) { + args.addElement("-x"); + } else { + args.addElement("-x-"); + } + if (multithreaded) { + args.addElement("-tWM"); + } + if (debug) { + args.addElement("-Od"); + args.addElement("-v"); + } else { + if (optimization != null) { + if (optimization.isSpeed()) { + args.addElement("-O1"); + } else { + if (optimization.isSpeed()) { + args.addElement("-O2"); + } else { + if (optimization.isNoOptimization()) { + args.addElement("-Od"); + } + } + } + } + } + if (rtti != null && !rtti.booleanValue()) { + args.addElement("-RT-"); + } + } + protected void addWarningSwitch(Vector args, int level) { + BorlandProcessor.addWarningSwitch(args, level); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new BorlandCCompiler(newEnvironment, env); + } + return this; + } + protected CompilerConfiguration createPrecompileGeneratingConfig( + CommandLineCompilerConfiguration baseConfig, File prototype, + String lastInclude) { + String[] additionalArgs = new String[]{"-H=" + lastInclude, "-Hc"}; + return new CommandLineCompilerConfiguration(baseConfig, additionalArgs, + null, true); + } + protected CompilerConfiguration createPrecompileUsingConfig( + CommandLineCompilerConfiguration baseConfig, File prototype, + String lastInclude, String[] exceptFiles) { + String[] additionalArgs = new String[]{"-Hu"}; + return new CommandLineCompilerConfiguration(baseConfig, additionalArgs, + exceptFiles, false); + } + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + BorlandProcessor.getDefineSwitch(buffer, define, value); + } + protected File[] getEnvironmentIncludePath() { + return BorlandProcessor.getEnvironmentPath("bcc32", 'I', + new String[]{"..\\include"}); + } + protected String getIncludeDirSwitch(String includeDir) { + return BorlandProcessor.getIncludeDirSwitch("-I", includeDir); + } + public Linker getLinker(LinkType type) { + return BorlandLinker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 1024; + } + protected void getUndefineSwitch(StringBuffer buffer, String define) { + BorlandProcessor.getUndefineSwitch(buffer, define); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandCfgParser.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandCfgParser.java new file mode 100644 index 0000000000..19daedd203 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandCfgParser.java @@ -0,0 +1,70 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.borland; +import java.io.IOException; +import java.io.Reader; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.parser.AbstractParser; +import net.sf.antcontrib.cpptasks.parser.AbstractParserState; +import net.sf.antcontrib.cpptasks.parser.LetterState; +import net.sf.antcontrib.cpptasks.parser.WhitespaceOrLetterState; +/** + * A parser that paths from a borland cfg file + * + * @author Curt Arnold + */ +public final class BorlandCfgParser extends AbstractParser { + private AbstractParserState newLineState; + private final Vector path = new Vector(); + /** + * + * + */ + public BorlandCfgParser(char switchChar) { + // + // a quoted path (-I"some path") + // doesn't end till a close quote and will be abandoned + // if a new line is encountered first + // + AbstractParserState quote = new CfgFilenameState(this, new char[]{'"'}); + // + // an unquoted path (-Ic:\borland\include) + // ends at the first space or new line + AbstractParserState unquote = new CfgFilenameState(this, new char[]{ + ' ', '\n', '\r'}); + AbstractParserState quoteBranch = new QuoteBranchState(this, quote, + unquote); + AbstractParserState toNextSwitch = new ConsumeToSpaceOrNewLine(this); + AbstractParserState switchState = new LetterState(this, switchChar, + quoteBranch, toNextSwitch); + newLineState = new WhitespaceOrLetterState(this, '-', switchState); + } + public void addFilename(String include) { + path.addElement(include); + } + public AbstractParserState getNewLineState() { + return newLineState; + } + public String[] parsePath(Reader reader) throws IOException { + path.setSize(0); + super.parse(reader); + String[] retval = new String[path.size()]; + path.copyInto(retval); + return retval; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandLibrarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandLibrarian.java new file mode 100644 index 0000000000..5fb3eb0827 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandLibrarian.java @@ -0,0 +1,200 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.borland; +import java.io.File; +import java.io.IOException; +import java.util.Vector; +import org.apache.tools.ant.BuildException; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * Adapter for the Borland(r) tlib Librarian + * + * @author Curt Arnold + */ +public class BorlandLibrarian extends CommandLineLinker { + private static final BorlandLibrarian instance = new BorlandLibrarian(); + public static BorlandLibrarian getInstance() { + return instance; + } + private BorlandLibrarian() { + super("tlib", "--version", new String[]{".obj"}, new String[0], ".lib", false, + null); + } + protected void addBase(long base, Vector args) { + } + protected void addFixed(Boolean fixed, Vector args) { + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + } + protected void addIncremental(boolean incremental, Vector args) { + } + protected void addMap(boolean map, Vector args) { + } + protected void addStack(int stack, Vector args) { + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + protected String getCommandFileSwitch(String cmdFile) { + return BorlandProcessor.getCommandFileSwitch(cmdFile); + } + public File[] getLibraryPath() { + return CUtil.getPathFromEnvironment("LIB", ";"); + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + return BorlandProcessor.getLibraryPatterns(libnames, libType); + } + public Linker getLinker(LinkType type) { + return BorlandLinker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 1024; + } + public String[] getOutputFileSwitch(String outFile) { + return BorlandProcessor.getOutputFileSwitch(outFile); + } + public boolean isCaseSensitive() { + return BorlandProcessor.isCaseSensitive(); + } + /** + * Gets identifier for the linker. + * + * TLIB will lockup when attempting to get version + * information. Since the Librarian version isn't critical + * just return a stock response. + */ + public String getIdentifier() { + return "TLIB 4.5 Copyright (c) 1987, 1999 Inprise Corporation"; + } + + /** + * Prepares argument list for exec command. + * + * @param outputFile + * linker output file + * @param sourceFiles + * linker input files (.obj, .o, .res) + * @param args + * linker arguments + * @return arguments for runTask + */ + protected String[] prepareArguments( + CCTask task, + String outputDir, + String outputName, + String[] sourceFiles, + CommandLineLinkerConfiguration config) { + String[] preargs = config.getPreArguments(); + String[] endargs = config.getEndArguments(); + StringBuffer buf = new StringBuffer(); + Vector execArgs = new Vector(preargs.length + endargs.length + 10 + + sourceFiles.length); + + execArgs.addElement(this.getCommand()); + String outputFileName = new File(outputDir, outputName).toString(); + execArgs.addElement(quoteFilename(buf, outputFileName)); + + for (int i = 0; i < preargs.length; i++) { + execArgs.addElement(preargs[i]); + } + + // + // add a place-holder for page size + // + int pageSizeIndex = execArgs.size(); + execArgs.addElement(null); + + int objBytes = 0; + + for (int i = 0; i < sourceFiles.length; i++) { + String last4 = sourceFiles[i] + .substring(sourceFiles[i].length() - 4).toLowerCase(); + if (last4.equals(".def")) { + } else { + if (last4.equals(".res")) { + } else { + if (last4.equals(".lib")) { + } else { + execArgs.addElement("+" + quoteFilename(buf, sourceFiles[i])); + objBytes += new File(sourceFiles[i]).length(); + } + } + } + } + + for (int i = 0; i < endargs.length; i++) { + execArgs.addElement(endargs[i]); + } + + String[] execArguments = new String[execArgs.size()]; + execArgs.copyInto(execArguments); + + int minPageSize = objBytes >> 16; + int pageSize = 0; + for(int i = 4; i <= 15; i++) { + pageSize = 1 << i; + if (pageSize > minPageSize) break; + } + execArguments[pageSizeIndex] = "/P" + Integer.toString(pageSize); + + return execArguments; + } + + /** + * Prepares argument list to execute the linker using a response file. + * + * @param outputFile + * linker output file + * @param args + * output of prepareArguments + * @return arguments for runTask + */ + protected String[] prepareResponseFile(File outputFile, String[] args) + throws IOException { + return BorlandProcessor.prepareResponseFile(outputFile, args, " & \n"); + } + + /** + * Builds a library + * + */ + public void link(CCTask task, + File outputFile, + String[] sourceFiles, + CommandLineLinkerConfiguration config) + throws BuildException + { + // + // delete any existing library + outputFile.delete(); + // + // build a new library + super.link(task, outputFile, sourceFiles, config); + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandLinker.java new file mode 100644 index 0000000000..f425c528bd --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandLinker.java @@ -0,0 +1,264 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.borland; +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * Adapter for the Borland(r) ilink32 linker + * + * @author Curt Arnold + */ +public final class BorlandLinker extends CommandLineLinker { + private static final BorlandLinker dllLinker = new BorlandLinker(".dll"); + private static final BorlandLinker instance = new BorlandLinker(".exe"); + public static BorlandLinker getInstance() { + return instance; + } + private BorlandLinker(String outputSuffix) { + super("ilink32", "-r", new String[]{".obj", ".lib", ".res"}, + new String[]{".map", ".pdb", ".lnk"}, outputSuffix, false, null); + } + protected void addBase(long base, Vector args) { + if (base >= 0) { + String baseAddr = Long.toHexString(base); + args.addElement("-b:" + baseAddr); + } + } + protected void addFixed(Boolean fixed, Vector args) { + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + if (linkType.isExecutable()) { + if (linkType.isSubsystemConsole()) { + args.addElement("/ap"); + } else { + if (linkType.isSubsystemGUI()) { + args.addElement("/Tpe"); + } + } + } + if (linkType.isSharedLibrary()) { + args.addElement("/Tpd"); + args.addElement("/Gi"); + } + } + protected void addIncremental(boolean incremental, Vector args) { + } + protected void addMap(boolean map, Vector args) { + if (!map) { + args.addElement("-x"); + } + } + protected void addStack(int stack, Vector args) { + if (stack >= 0) { + String stackStr = Integer.toHexString(stack); + args.addElement("-S:" + stackStr); + } + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + public String getCommandFileSwitch(String commandFile) { + return "@" + commandFile; + } + public String getIdentifier() { + return "Borland Linker"; + } + public File[] getLibraryPath() { + return BorlandProcessor.getEnvironmentPath("ilink32", 'L', + new String[]{"..\\lib"}); + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + return BorlandProcessor.getLibraryPatterns(libnames, libType); + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return BorlandLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } + public int getMaximumCommandLength() { + return 1024; + } + public String[] getOutputFileSwitch(String outFile) { + return BorlandProcessor.getOutputFileSwitch(outFile); + } + protected String getStartupObject(LinkType linkType) { + if (linkType.isSharedLibrary()) { + return "c0d32.obj"; + } + if (linkType.isSubsystemGUI()) { + return "c0w32.obj"; + } + if (linkType.isSubsystemConsole()) { + return "c0x32.obj"; + } + return null; + } + public boolean isCaseSensitive() { + return BorlandProcessor.isCaseSensitive(); + } + /** + * Prepares argument list for exec command. + * + * @param outputFile + * linker output file + * @param sourceFiles + * linker input files (.obj, .o, .res) + * @param args + * linker arguments + * @return arguments for runTask + */ + protected String[] prepareArguments( + CCTask task, + String outputDir, + String outputName, + String[] sourceFiles, + CommandLineLinkerConfiguration config) { + String[] preargs = config.getPreArguments(); + String[] endargs = config.getEndArguments(); + Vector execArgs = new Vector(preargs.length + endargs.length + 10 + + sourceFiles.length); + execArgs.addElement(this.getCommand()); + for (int i = 0; i < preargs.length; i++) { + execArgs.addElement(preargs[i]); + } + for (int i = 0; i < endargs.length; i++) { + execArgs.addElement(endargs[i]); + } + // + // see if the input files have any known startup obj files + // + String startup = null; + for (int i = 0; i < sourceFiles.length; i++) { + String filename = new File(sourceFiles[i]).getName().toLowerCase(); + if (startup != null && filename.substring(0, 2).equals("c0") + && filename.substring(3, 5).equals("32") + && filename.substring(filename.length() - 4).equals(".obj")) { + startup = sourceFiles[i]; + } + } + // + // c0w32.obj, c0x32.obj or c0d32.obj depending on + // link type + if (startup == null) { + startup = config.getStartupObject(); + } + execArgs.addElement(startup); + Vector resFiles = new Vector(); + Vector libFiles = new Vector(); + String defFile = null; + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < sourceFiles.length; i++) { + String last4 = sourceFiles[i] + .substring(sourceFiles[i].length() - 4).toLowerCase(); + if (last4.equals(".def")) { + defFile = quoteFilename(buf, sourceFiles[i]); + } else { + if (last4.equals(".res")) { + resFiles.addElement(quoteFilename(buf, sourceFiles[i])); + } else { + if (last4.equals(".lib")) { + libFiles.addElement(quoteFilename(buf, sourceFiles[i])); + } else { + execArgs.addElement(quoteFilename(buf, sourceFiles[i])); + } + } + } + } + // + // output file name + // + String outputFileName = new File(outputDir, outputName).toString(); + execArgs.addElement("," + quoteFilename(buf, outputFileName)); + if (config.getMap()) { + int lastPeriod = outputFileName.lastIndexOf('.'); + String mapName; + if (lastPeriod < outputFileName.length() - 4) { + mapName = outputFileName + ".map"; + } else { + mapName = outputFileName.substring(0, lastPeriod) + ".map"; + } + execArgs.addElement("," + quoteFilename(buf, mapName) + ","); + } else { + execArgs.addElement(",,"); + } + // + // add all the libraries + // + Enumeration libEnum = libFiles.elements(); + boolean hasImport32 = false; + boolean hasCw32 = false; + while (libEnum.hasMoreElements()) { + String libName = (String) libEnum.nextElement(); + if (libName.equalsIgnoreCase("import32.lib")) { + hasImport32 = true; + } + if (libName.equalsIgnoreCase("cw32.lib")) { + hasImport32 = true; + } + execArgs.addElement(quoteFilename(buf, libName)); + } + if (!hasCw32) { + execArgs.addElement(quoteFilename(buf, "cw32.lib")); + } + if (!hasImport32) { + execArgs.addElement(quoteFilename(buf, "import32.lib")); + } + if (defFile == null) { + execArgs.addElement(",,"); + } else { + execArgs.addElement("," + quoteFilename(buf, defFile) + ","); + } + Enumeration resEnum = resFiles.elements(); + while (resEnum.hasMoreElements()) { + String resName = (String) resEnum.nextElement(); + execArgs.addElement(quoteFilename(buf, resName)); + } + String[] execArguments = new String[execArgs.size()]; + execArgs.copyInto(execArguments); + return execArguments; + } + /** + * Prepares argument list to execute the linker using a response file. + * + * @param outputFile + * linker output file + * @param args + * output of prepareArguments + * @return arguments for runTask + */ + protected String[] prepareResponseFile(File outputFile, String[] args) + throws IOException { + return BorlandProcessor.prepareResponseFile(outputFile, args, " + \n"); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandProcessor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandProcessor.java new file mode 100644 index 0000000000..d53f00cc12 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandProcessor.java @@ -0,0 +1,219 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.borland; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.Vector; +import java.io.FileWriter; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; +/** + * A add-in class for Borland(r) processor adapters + * + * + */ +public final class BorlandProcessor { + public static void addWarningSwitch(Vector args, int level) { + switch (level) { + case 0 : + args.addElement("-w-"); + break; + case 5 : + args.addElement("-w!"); + break; + default : + args.addElement("-w"); + break; + } + } + public static String getCommandFileSwitch(String cmdFile) { + StringBuffer buf = new StringBuffer("@"); + quoteFile(buf, cmdFile); + return buf.toString(); + } + public static void getDefineSwitch(StringBuffer buffer, String define, + String value) { + buffer.append("-D"); + buffer.append(define); + if (value != null && value.length() > 0) { + buffer.append('='); + buffer.append(value); + } + } + /** + * This method extracts path information from the appropriate .cfg file in + * the install directory. + * + * @param toolName + * Tool name, for example, "bcc32", "brc32", "ilink32" + * @param switchChar + * Command line switch character, for example "L" for libraries + * @param defaultRelativePaths + * default paths relative to executable directory + * @return path + */ + public static File[] getEnvironmentPath(String toolName, char switchChar, + String[] defaultRelativePath) { + if (toolName == null) { + throw new NullPointerException("toolName"); + } + if (defaultRelativePath == null) { + throw new NullPointerException("defaultRelativePath"); + } + String[] path = defaultRelativePath; + File exeDir = CUtil.getExecutableLocation(toolName + ".exe"); + if (exeDir != null) { + File cfgFile = new File(exeDir, toolName + ".cfg"); + if (cfgFile.exists()) { + try { + Reader reader = new BufferedReader(new FileReader(cfgFile)); + BorlandCfgParser cfgParser = new BorlandCfgParser( + switchChar); + path = cfgParser.parsePath(reader); + reader.close(); + } catch (IOException ex) { + // + // could be logged + // + } + } + } else { + // + // if can't find the executable, + // assume current directory to resolve relative paths + // + exeDir = new File(System.getProperty("user.dir")); + } + int nonExistant = 0; + File[] resourcePath = new File[path.length]; + for (int i = 0; i < path.length; i++) { + resourcePath[i] = new File(path[i]); + if (!resourcePath[i].isAbsolute()) { + resourcePath[i] = new File(exeDir, path[i]); + } + // + // if any of the entries do not exist or are + // not directories, null them out + if (!(resourcePath[i].exists() && resourcePath[i].isDirectory())) { + resourcePath[i] = null; + nonExistant++; + } + } + // + // if there were some non-existant or non-directory + // entries in the configuration file then + // create a shorter array + if (nonExistant > 0) { + File[] culled = new File[resourcePath.length - nonExistant]; + int index = 0; + for (int i = 0; i < resourcePath.length; i++) { + if (resourcePath[i] != null) { + culled[index++] = resourcePath[i]; + } + } + resourcePath = culled; + } + return resourcePath; + } + public static String getIncludeDirSwitch(String includeOption, + String includeDir) { + StringBuffer buf = new StringBuffer(includeOption); + quoteFile(buf, includeDir); + return buf.toString(); + } + public static String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + StringBuffer buf = new StringBuffer(); + String[] patterns = new String[libnames.length]; + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(libnames[i]); + buf.append(".lib"); + patterns[i] = buf.toString(); + } + return patterns; + } + public static String[] getOutputFileSwitch(String outFile) { + return new String[0]; + } + public static void getUndefineSwitch(StringBuffer buffer, String define) { + buffer.append("-U"); + buffer.append(define); + } + public static boolean isCaseSensitive() { + return false; + } + private static void quoteFile(StringBuffer buf, String outPath) { + if (outPath.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(outPath); + buf.append('\"'); + } else { + buf.append(outPath); + } + } + + /** + * Prepares argument list to execute the linker using a response file. + * + * @param outputFile + * linker output file + * @param args + * output of prepareArguments + * @return arguments for runTask + */ + public static String[] prepareResponseFile(File outputFile, + String[] args, + String continuation) + throws IOException { + String baseName = outputFile.getName(); + File commandFile = new File(outputFile.getParent(), baseName + ".lnk"); + FileWriter writer = new FileWriter(commandFile); + for (int i = 1; i < args.length - 1; i++) { + writer.write(args[i]); + // + // if either the current argument ends with + // or next argument starts with a comma then + // don't split the line + if (args[i].endsWith(",") || args[i + 1].startsWith(",")) { + writer.write(' '); + } else { + // + // split the line to make it more readable + // + writer.write(continuation); + } + } + // + // write the last argument + // + if (args.length > 1) { + writer.write(args[args.length - 1]); + } + writer.close(); + String[] execArgs = new String[2]; + execArgs[0] = args[0]; + execArgs[1] = getCommandFileSwitch(commandFile.toString()); + return execArgs; + } + + private BorlandProcessor() { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandResourceCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandResourceCompiler.java new file mode 100644 index 0000000000..5e8609797e --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/BorlandResourceCompiler.java @@ -0,0 +1,130 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.borland; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.compiler.ProgressMonitor; +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.Parser; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the Borland(r) brc32 Resource compiler. + * + * @author Curt Arnold + */ +public class BorlandResourceCompiler extends CommandLineCompiler { + private static final BorlandResourceCompiler instance = new BorlandResourceCompiler( + false, null); + public static BorlandResourceCompiler getInstance() { + return instance; + } + private BorlandResourceCompiler(boolean newEnvironment, Environment env) { + super("brc32", "c:\\__bogus\\__bogus.rc", new String[]{".rc"}, + new String[]{".h", ".hpp", ".inl"}, ".res", false, null, + newEnvironment, env); + } + protected void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + // + // compile only + // + args.addElement("-r"); + } + protected void addWarningSwitch(Vector args, int level) { + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new BorlandResourceCompiler(newEnvironment, env); + } + return this; + } + public void compile(CCTask task, File outputDir, String[] sourceFiles, + String[] args, String[] endArgs, boolean relentless, + CommandLineCompilerConfiguration config, ProgressMonitor monitor) + throws BuildException { + super.compile(task, outputDir, sourceFiles, args, endArgs, relentless, + config, monitor); + } + /** + * The include parser for C will work just fine, but we didn't want to + * inherit from CommandLineCCompiler + */ + protected Parser createParser(File source) { + return new CParser(); + } + protected int getArgumentCountPerInputFile() { + return 2; + } + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + buffer.append("-d"); + buffer.append(define); + if (value != null && value.length() > 0) { + buffer.append('='); + buffer.append(value); + } + } + protected File[] getEnvironmentIncludePath() { + return BorlandProcessor.getEnvironmentPath("brc32", 'i', + new String[]{"..\\include"}); + } + protected String getIncludeDirSwitch(String includeDir) { + return BorlandProcessor.getIncludeDirSwitch("-i", includeDir); + } + protected String getInputFileArgument(File outputDir, String filename, + int index) { + if (index == 0) { + String outputFileName = getOutputFileName(filename); + String fullOutputName = new File(outputDir, outputFileName) + .toString(); + return "-fo" + fullOutputName; + } + return filename; + } + public Linker getLinker(LinkType type) { + return BorlandLinker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 1024; + } + protected int getMaximumInputFilesPerCommand() { + return 1; + } + protected int getTotalArgumentLengthForInputFile(File outputDir, + String inputFile) { + String arg1 = getInputFileArgument(outputDir, inputFile, 0); + String arg2 = getInputFileArgument(outputDir, inputFile, 1); + return arg1.length() + arg2.length() + 2; + } + protected void getUndefineSwitch(StringBuffer buffer, String define) { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/CfgFilenameState.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/CfgFilenameState.java new file mode 100644 index 0000000000..a3651d3b25 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/CfgFilenameState.java @@ -0,0 +1,46 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.borland; +import net.sf.antcontrib.cpptasks.parser.AbstractParser; +import net.sf.antcontrib.cpptasks.parser.AbstractParserState; +import net.sf.antcontrib.cpptasks.parser.FilenameState; +public class CfgFilenameState extends FilenameState { + private char terminator; + public CfgFilenameState(AbstractParser parser, char[] terminators) { + super(parser, terminators); + terminator = terminators[0]; + } + public AbstractParserState consume(char ch) { + // + // if a ';' is encountered then + // close the previous filename by sending a + // recognized terminator to our super class + // and stay in this state for more filenamese + if (ch == ';') { + super.consume(terminator); + return this; + } + AbstractParserState newState = super.consume(ch); + // + // change null (consume to end of line) + // to look for next switch character + if (newState == null) { + newState = getParser().getNewLineState(); + } + return newState; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/ConsumeToSpaceOrNewLine.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/ConsumeToSpaceOrNewLine.java new file mode 100644 index 0000000000..d1dd072cce --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/ConsumeToSpaceOrNewLine.java @@ -0,0 +1,30 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.borland; +import net.sf.antcontrib.cpptasks.parser.AbstractParser; +import net.sf.antcontrib.cpptasks.parser.AbstractParserState; +public class ConsumeToSpaceOrNewLine extends AbstractParserState { + public ConsumeToSpaceOrNewLine(AbstractParser parser) { + super(parser); + } + public AbstractParserState consume(char ch) { + if (ch == ' ' || ch == '\t' || ch == '\n') { + return getParser().getNewLineState(); + } + return this; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/QuoteBranchState.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/QuoteBranchState.java new file mode 100644 index 0000000000..89724b26e5 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/borland/QuoteBranchState.java @@ -0,0 +1,35 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.borland; +import net.sf.antcontrib.cpptasks.parser.AbstractParser; +import net.sf.antcontrib.cpptasks.parser.AbstractParserState; +public class QuoteBranchState extends AbstractParserState { + private AbstractParserState quote; + private AbstractParserState unquote; + public QuoteBranchState(AbstractParser parser, AbstractParserState quote, + AbstractParserState unquote) { + super(parser); + this.quote = quote; + this.unquote = unquote; + } + public AbstractParserState consume(char ch) { + if (ch == '"') { + return quote; + } + return unquote.consume(ch); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compaq/CompaqVisualFortranCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compaq/CompaqVisualFortranCompiler.java new file mode 100644 index 0000000000..e1d3deb8b6 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compaq/CompaqVisualFortranCompiler.java @@ -0,0 +1,138 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compaq; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineFortranCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the Compaq(r) Visual Fortran compiler. + * + * @author Curt Arnold + */ +public class CompaqVisualFortranCompiler extends CommandLineFortranCompiler { + private static final CompaqVisualFortranCompiler[] instance = new CompaqVisualFortranCompiler[]{new CompaqVisualFortranCompiler( + false, null)}; + public static CompaqVisualFortranCompiler getInstance() { + return instance[0]; + } + private CompaqVisualFortranCompiler(boolean newEnvironment, Environment env) { + super("DF", null, new String[]{".f90", ".for", ".f"}, new String[]{ + ".i", ".i90", ".fpp", ".inc", ".bak", ".exe"}, ".obj", false, + null, newEnvironment, env); + } + protected void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + args.addElement("/nologo"); + args.addElement("/compile_only"); + if (debug) { + args.addElement("/debug:full"); + args.addElement("/define:_DEBUG"); + } else { + args.addElement("/debug:none"); + args.addElement("/define:NDEBUG"); + } + if (multithreaded) { + args.addElement("/threads"); + args.addElement("/define:_MT"); + } else { + args.addElement("/nothreads"); + } + boolean staticRuntime = linkType.isStaticRuntime(); + if (staticRuntime) { + args.addElement("/libs:static"); + } else { + args.addElement("/libs:dll"); + } + if (linkType.isSharedLibrary()) { + args.addElement("/dll"); + args.addElement("/define:_DLL"); + } + } + public void addWarningSwitch(Vector args, int level) { + switch (level) { + case 0 : + args.addElement("/nowarn"); + break; + case 1 : + break; + case 2 : + break; + case 3 : + args.addElement("/warn:usage"); + break; + case 4 : + args.addElement("/warn:all"); + break; + case 5 : + args.addElement("/warn:errors"); + break; + } + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new CompaqVisualFortranCompiler(newEnvironment, env); + } + return this; + } + protected void getDefineSwitch(StringBuffer buf, String define, String value) { + buf.append("/define:"); + buf.append(define); + if (value != null && value.length() > 0) { + buf.append('='); + buf.append(value); + } + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ";"); + } + protected String getIncludeDirSwitch(String includeDir) { + StringBuffer buf = new StringBuffer("/include:"); + if (includeDir.indexOf(' ') >= 0) { + buf.append('"'); + buf.append(includeDir); + buf.append('"'); + } else { + buf.append(includeDir); + } + return buf.toString(); + } + public Linker getLinker(LinkType type) { + return CompaqVisualFortranLinker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 1024; + } + protected void getUndefineSwitch(StringBuffer buf, String define) { + buf.append("/undefine:"); + buf.append(define); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compaq/CompaqVisualFortranLibrarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compaq/CompaqVisualFortranLibrarian.java new file mode 100644 index 0000000000..eb4a40769e --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compaq/CompaqVisualFortranLibrarian.java @@ -0,0 +1,82 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compaq; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioLibrarian; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioProcessor; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * Adapter for the Compaq(r) Visual Fortran Librarian + * + * @author Curt Arnold + */ +public class CompaqVisualFortranLibrarian extends CommandLineLinker { + private static final CompaqVisualFortranLibrarian instance = new CompaqVisualFortranLibrarian(); + public static CompaqVisualFortranLibrarian getInstance() { + return instance; + } + private CompaqVisualFortranLibrarian() { + super("lib", "/bogus", new String[]{".obj"}, new String[0], ".lib", + false, null); + } + protected void addBase(long base, Vector args) { + } + protected void addFixed(Boolean fixed, Vector args) { + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + args.addElement("/nologo"); + } + protected void addIncremental(boolean incremental, Vector args) { + } + protected void addMap(boolean map, Vector args) { + } + protected void addStack(int stack, Vector args) { + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + protected String getCommandFileSwitch(String commandFile) { + return DevStudioProcessor.getCommandFileSwitch(commandFile); + } + public File[] getLibraryPath() { + return new File[0]; + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + return new String[0]; + } + public Linker getLinker(LinkType type) { + return CompaqVisualFortranLinker.getInstance().getLinker(type); + } + protected int getMaximumCommandLength() { + return DevStudioLibrarian.getInstance().getMaximumCommandLength(); + } + protected String[] getOutputFileSwitch(String outputFile) { + return DevStudioLibrarian.getInstance().getOutputFileSwitch(outputFile); + } + public boolean isCaseSensitive() { + return false; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compaq/CompaqVisualFortranLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compaq/CompaqVisualFortranLinker.java new file mode 100644 index 0000000000..d83e3b213d --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compaq/CompaqVisualFortranLinker.java @@ -0,0 +1,77 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compaq; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioCompatibleLinker; +/** + * Adapter for the Compaq(r) Visual Fortran linker. + * + * @author Curt Arnold + */ +public final class CompaqVisualFortranLinker extends DevStudioCompatibleLinker { + private static final CompaqVisualFortranLinker dllLinker = new CompaqVisualFortranLinker( + ".dll"); + private static final CompaqVisualFortranLinker instance = new CompaqVisualFortranLinker( + ".exe"); + public static CompaqVisualFortranLinker getInstance() { + return instance; + } + private CompaqVisualFortranLinker(String outputSuffix) { + super("DF", "__bogus__.xxx", outputSuffix); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + args.addElement("/NOLOGO"); + boolean staticRuntime = linkType.isStaticRuntime(); + if (staticRuntime) { + args.addElement("/libs:static"); + } else { + args.addElement("/libs:dll"); + } + if (debug) { + args.addElement("/debug"); + } else { + } + if (linkType.isSharedLibrary()) { + args.addElement("/dll"); + } else { + args.addElement("/exe"); + } + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return CompaqVisualFortranLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } + public String[] getOutputFileSwitch(String outputFile) { + StringBuffer buf = new StringBuffer("/OUT:"); + if (outputFile.indexOf(' ') >= 0) { + buf.append('"'); + buf.append(outputFile); + buf.append('"'); + } else { + buf.append(outputFile); + } + return new String[]{buf.toString()}; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractAslcompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractAslcompiler.java new file mode 100644 index 0000000000..90c539c965 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractAslcompiler.java @@ -0,0 +1,75 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.File; + +import net.sf.antcontrib.cpptasks.AslcompilerDef; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.TargetDef; + +/** + * An abstract asl compiler implementation. + * + */ +public abstract class AbstractAslcompiler extends AbstractProcessor +implements Aslcompiler { + private String outputSuffix; + protected AbstractAslcompiler(String[] sourceExtensions, + String[] headerExtensions, String outputSuffix) { + super(sourceExtensions, headerExtensions); + this.outputSuffix = outputSuffix; + } + abstract protected AslcompilerConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + AslcompilerDef specificConfig, TargetDef targetPlatform); + + public ProcessorConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + ProcessorDef specificConfig, TargetDef targetPlatform) { + if (specificConfig == null) { + throw new NullPointerException("specificConfig"); + } + return createConfiguration(task, linkType, baseConfigs, + (AslcompilerDef) specificConfig, targetPlatform); + } + + public String getOutputFileName(String inputFile) { + if (bid(inputFile) > 1) { + String baseName = getBaseOutputName(inputFile); + return baseName + outputSuffix; + } + return null; + } + protected String getBaseOutputName(String inputFile) { + int lastSlash = inputFile.lastIndexOf('/'); + int lastReverse = inputFile.lastIndexOf('\\'); + int lastSep = inputFile.lastIndexOf(File.separatorChar); + if (lastReverse > lastSlash) { + lastSlash = lastReverse; + } + if (lastSep > lastSlash) { + lastSlash = lastSep; + } + int lastPeriod = inputFile.lastIndexOf('.'); + if (lastPeriod < 0) { + lastPeriod = inputFile.length(); + } + return inputFile.substring(lastSlash + 1, lastPeriod); + } +} \ No newline at end of file diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractAssembler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractAssembler.java new file mode 100644 index 0000000000..1d49232a05 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractAssembler.java @@ -0,0 +1,72 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.File; + +import net.sf.antcontrib.cpptasks.AssemblerDef; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.TargetDef; +/** + * An abstract assembler implementation. + * + */ +public abstract class AbstractAssembler extends AbstractProcessor +implements Assembler { + private String outputSuffix; + protected AbstractAssembler(String[] sourceExtensions, + String[] headerExtensions, String outputSuffix) { + super(sourceExtensions, headerExtensions); + this.outputSuffix = outputSuffix; + } + abstract protected AssemblerConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + AssemblerDef specificConfig, TargetDef targetPlatform); + public ProcessorConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + ProcessorDef specificConfig, TargetDef targetPlatform) { + if (specificConfig == null) { + throw new NullPointerException("specificConfig"); + } + return createConfiguration(task, linkType, baseConfigs, + (AssemblerDef) specificConfig, targetPlatform); + } + public String getOutputFileName(String inputFile) { + if (bid(inputFile) > 1) { + String baseName = getBaseOutputName(inputFile); + return baseName + outputSuffix; + } + return null; + } + protected String getBaseOutputName(String inputFile) { + int lastSlash = inputFile.lastIndexOf('/'); + int lastReverse = inputFile.lastIndexOf('\\'); + int lastSep = inputFile.lastIndexOf(File.separatorChar); + if (lastReverse > lastSlash) { + lastSlash = lastReverse; + } + if (lastSep > lastSlash) { + lastSlash = lastSep; + } + int lastPeriod = inputFile.lastIndexOf('.'); + if (lastPeriod < 0) { + lastPeriod = inputFile.length(); + } + return inputFile.substring(lastSlash + 1, lastPeriod); + } +} \ No newline at end of file diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java new file mode 100644 index 0000000000..f16ec6caf3 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractCompiler.java @@ -0,0 +1,205 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.CompilerDef; +import net.sf.antcontrib.cpptasks.DependencyInfo; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.parser.Parser; +import net.sf.antcontrib.cpptasks.TargetDef; + +/** + * An abstract compiler implementation. + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public abstract class AbstractCompiler extends AbstractProcessor + implements + Compiler { + private static final String[] emptyIncludeArray = new String[0]; + private String outputSuffix; + protected AbstractCompiler(String[] sourceExtensions, + String[] headerExtensions, String outputSuffix) { + super(sourceExtensions, headerExtensions); + this.outputSuffix = outputSuffix; + } + /** + * Checks file name to see if parse should be attempted + * + * Default implementation returns false for files with extensions '.dll', + * 'tlb', '.res' + * + */ + protected boolean canParse(File sourceFile) { + String sourceName = sourceFile.toString(); + int lastPeriod = sourceName.lastIndexOf('.'); + if (lastPeriod >= 0 && lastPeriod == sourceName.length() - 4) { + String ext = sourceName.substring(lastPeriod).toUpperCase(); + if (ext.equals(".DLL") || ext.equals(".TLB") || ext.equals(".RES")) { + return false; + } + } + return true; + } + abstract protected CompilerConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + CompilerDef specificConfig, TargetDef targetPlatform); + public ProcessorConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + ProcessorDef specificConfig, TargetDef targetPlatform) { + if (specificConfig == null) { + throw new NullPointerException("specificConfig"); + } + return createConfiguration(task, linkType, baseConfigs, + (CompilerDef) specificConfig, targetPlatform); + } + abstract protected Parser createParser(File sourceFile); + protected String getBaseOutputName(String inputFile) { + int lastSlash = inputFile.lastIndexOf('/'); + int lastReverse = inputFile.lastIndexOf('\\'); + int lastSep = inputFile.lastIndexOf(File.separatorChar); + if (lastReverse > lastSlash) { + lastSlash = lastReverse; + } + if (lastSep > lastSlash) { + lastSlash = lastSep; + } + int lastPeriod = inputFile.lastIndexOf('.'); + if (lastPeriod < 0) { + lastPeriod = inputFile.length(); + } + return inputFile.substring(lastSlash + 1, lastPeriod); + } + public String getOutputFileName(String inputFile) { + // + // if a recognized input file + // + if (bid(inputFile) > 1) { + String baseName = getBaseOutputName(inputFile); + return baseName + outputSuffix; + } + return null; + } + /** + * Returns dependency info for the specified source file + * + * @param task + * task for any diagnostic output + * @param source + * file to be parsed + * @param includePath + * include path to be used to resolve included files + * + * @param sysIncludePath + * sysinclude path from build file, files resolved using + * sysInclude path will not participate in dependency analysis + * + * @param envIncludePath + * include path from environment variable, files resolved with + * envIncludePath will not participate in dependency analysis + * + * @param baseDir + * used to produce relative paths in DependencyInfo + * @param includePathIdentifier + * used to distinguish DependencyInfo's from different include + * path settings + * + * @author Curt Arnold + */ + public final DependencyInfo parseIncludes(CCTask task, File source, + File[] includePath, File[] sysIncludePath, File[] envIncludePath, + File baseDir, String includePathIdentifier) { + // + // if any of the include files can not be identified + // change the sourceLastModified to Long.MAX_VALUE to + // force recompilation of anything that depends on it + long sourceLastModified = source.lastModified(); + File[] sourcePath = new File[1]; + sourcePath[0] = new File(source.getParent()); + Vector onIncludePath = new Vector(); + Vector onSysIncludePath = new Vector(); + String baseDirPath; + try { + baseDirPath = baseDir.getCanonicalPath(); + } catch (IOException ex) { + baseDirPath = baseDir.toString(); + } + String relativeSource = CUtil.getRelativePath(baseDirPath, source); + String[] includes = emptyIncludeArray; + if (canParse(source)) { + Parser parser = createParser(source); + try { + Reader reader = new BufferedReader(new FileReader(source)); + parser.parse(reader); + includes = parser.getIncludes(); + } catch (IOException ex) { + task.log("Error parsing " + source.toString() + ":" + + ex.toString()); + includes = new String[0]; + } + } + for (int i = 0; i < includes.length; i++) { + String includeName = includes[i]; + if (!resolveInclude(includeName, sourcePath, onIncludePath)) { + if (!resolveInclude(includeName, includePath, onIncludePath)) { + if (!resolveInclude(includeName, sysIncludePath, + onSysIncludePath)) { + if (!resolveInclude(includeName, envIncludePath, + onSysIncludePath)) { + // + // this should be enough to require us to reparse + // the file with the missing include for dependency + // information without forcing a rebuild + sourceLastModified++; + } + } + } + } + } + for (int i = 0; i < onIncludePath.size(); i++) { + String relativeInclude = CUtil.getRelativePath(baseDirPath, + (File) onIncludePath.elementAt(i)); + onIncludePath.setElementAt(relativeInclude, i); + } + for (int i = 0; i < onSysIncludePath.size(); i++) { + String relativeInclude = CUtil.getRelativePath(baseDirPath, + (File) onSysIncludePath.elementAt(i)); + onSysIncludePath.setElementAt(relativeInclude, i); + } + return new DependencyInfo(includePathIdentifier, relativeSource, + sourceLastModified, onIncludePath, onSysIncludePath); + } + protected boolean resolveInclude(String includeName, File[] includePath, + Vector onThisPath) { + for (int i = 0; i < includePath.length; i++) { + File includeFile = new File(includePath[i], includeName); + if (includeFile.exists()) { + onThisPath.addElement(includeFile); + return true; + } + } + return false; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractLinker.java new file mode 100644 index 0000000000..20580e5d33 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractLinker.java @@ -0,0 +1,85 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.LinkerDef; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.TargetDef; + + +import org.apache.tools.ant.types.Environment; +/** + * An abstract Linker implementation. + * + * @author Adam Murdoch + */ +public abstract class AbstractLinker extends AbstractProcessor + implements + Linker { + public AbstractLinker(String[] objExtensions, String[] ignoredExtensions) { + super(objExtensions, ignoredExtensions); + } + /** + * Returns the bid of the processor for the file. + * + * A linker will bid 1 on any unrecognized file type. + * + * @param inputFile + * filename of input file + * @return bid for the file, 0 indicates no interest, 1 indicates that the + * processor recognizes the file but doesn't process it (header + * files, for example), 100 indicates strong interest + */ + public int bid(String inputFile) { + int bid = super.bid(inputFile); + switch (bid) { + // + // unrecognized extension, take the file + // + case 0 : + return 1; + // + // discard the ignored extensions + // + case 1 : + return 0; + } + return bid; + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + return this; + } + abstract protected LinkerConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + LinkerDef specificConfig, TargetDef targetPlatform); + public ProcessorConfiguration createConfiguration(CCTask task, + LinkType linkType, ProcessorDef[] baseConfigs, + ProcessorDef specificConfig, + TargetDef targetPlatform) { + if (specificConfig == null) { + throw new NullPointerException("specificConfig"); + } + return createConfiguration(task, linkType, baseConfigs, + (LinkerDef) specificConfig, targetPlatform); + } + public String getLibraryKey(File libfile) { + return libfile.getName(); + } + public abstract String getOutputFileName(String fileName); +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractProcessor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractProcessor.java new file mode 100644 index 0000000000..b6456d5e3e --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AbstractProcessor.java @@ -0,0 +1,129 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import org.apache.tools.ant.types.Environment; +/** + * An abstract processor (compiler/linker) implementation. + * + * @author Curt Arnold + */ +public abstract class AbstractProcessor implements Processor, Cloneable { + /** + * default bid for a file name that the processor recognizes but does not + * process and does not want to fall through to the linker + */ + public final static int DEFAULT_DISCARD_BID = 1; + /** + * default bid for a file name that the processor desires to process + */ + public final static int DEFAULT_PROCESS_BID = 100; + /** + * Determines the identification of a command line processor by capture the + * first line of its output for a specific command. + * + * @param command + * array of command line arguments starting with executable + * name. For example, { "cl" } + * @param fallback + * start of identifier if there is an error in executing the + * command + * @return identifier for the processor + */ + protected static String getIdentifier(String[] command, String fallback) { + String identifier = fallback; + try { + String[] cmdout = CaptureStreamHandler.run(command); + if (cmdout.length > 0) { + identifier = cmdout[0]; + } + } catch (Throwable ex) { + identifier = fallback + ":" + ex.toString(); + } + return identifier; + } + private final String[] headerExtensions; + private final String[] sourceExtensions; + protected AbstractProcessor(String[] sourceExtensions, + String[] headerExtensions) { + this.sourceExtensions = (String[]) sourceExtensions.clone(); + this.headerExtensions = (String[]) headerExtensions.clone(); + } + /** + * Returns the bid of the processor for the file. + * + * @param inputFile + * filename of input file + * @return bid for the file, 0 indicates no interest, 1 indicates that the + * processor recognizes the file but doesn't process it (header + * files, for example), 100 indicates strong interest + */ + public int bid(String inputFile) { + String lower = inputFile.toLowerCase(); + for (int i = 0; i < sourceExtensions.length; i++) { + if (lower.endsWith(sourceExtensions[i])) { + return DEFAULT_PROCESS_BID; + } + } + for (int i = 0; i < headerExtensions.length; i++) { + if (lower.endsWith(headerExtensions[i])) { + return DEFAULT_DISCARD_BID; + } + } + return 0; + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + return this; + } + protected Object clone() throws CloneNotSupportedException { + return super.clone(); + } + public String[] getHeaderExtensions() { + return (String[]) this.headerExtensions.clone(); + } + abstract public String getIdentifier(); + /** + * Gets the target operating system architecture + * + * @return String target operating system architecture + */ + protected String getOSArch() { + return System.getProperty("os.arch"); + } + /** + * Gets the target operating system name + * + * @return String target operating system name + */ + protected String getOSName() { + return System.getProperty("os.name"); + } + public String[] getSourceExtensions() { + return (String[]) this.sourceExtensions.clone(); + } + /** + * Returns true if the target operating system is Mac OS X or Darwin. + * + * @return boolean + */ + protected boolean isDarwin() { + String osName = getOSName(); + return "Mac OS X".equals(osName); + } + public final String toString() { + return getIdentifier(); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Aslcompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Aslcompiler.java new file mode 100644 index 0000000000..a210e1c684 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Aslcompiler.java @@ -0,0 +1,23 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +/** + * A asl compiler. + * + */ +public interface Aslcompiler extends Processor { +} \ No newline at end of file diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AslcompilerConfiguration.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AslcompilerConfiguration.java new file mode 100644 index 0000000000..62ac2760c6 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AslcompilerConfiguration.java @@ -0,0 +1,29 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import org.apache.tools.ant.BuildException; +/** + * A configuration for an ASL compiler + * + */ +public interface AslcompilerConfiguration extends ProcessorConfiguration { + void aslcompiler(CCTask task, File outputDir, String[] sourceFiles) throws BuildException; +} \ No newline at end of file diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Assembler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Assembler.java new file mode 100644 index 0000000000..1b6d7b5d11 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Assembler.java @@ -0,0 +1,23 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +/** + * A assembler. + * + */ +public interface Assembler extends Processor { +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AssemblerConfiguration.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AssemblerConfiguration.java new file mode 100644 index 0000000000..9411551b47 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/AssemblerConfiguration.java @@ -0,0 +1,29 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import org.apache.tools.ant.BuildException; +/** + * A configuration for an assembler + * + */ +public interface AssemblerConfiguration extends ProcessorConfiguration { + void assembler(CCTask task, File outputDir, String[] sourceFiles) throws BuildException; +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java new file mode 100644 index 0000000000..1b89a70a58 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CaptureStreamHandler.java @@ -0,0 +1,122 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.util.Vector; + +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.ExecuteStreamHandler; +/** + * Implements ExecuteStreamHandler to capture the output of a Execute to an + * array of strings + * + * @author Curt Arnold + */ +public class CaptureStreamHandler implements ExecuteStreamHandler { + /** + * Runs an executable and captures the output in a String array + * + * @param cmdline + * command line arguments + * @return output of process + */ + public static String[] run(String[] cmdline) { + CaptureStreamHandler handler = new CaptureStreamHandler(); + Execute exec = new Execute(handler); + exec.setCommandline(cmdline); + try { + int status = exec.execute(); + } catch (IOException ex) { + } + return handler.getOutput(); + } + private InputStream errorStream; + private InputStream fromProcess; + public CaptureStreamHandler() { + } + public String[] getOutput() { + String[] output; + if (fromProcess != null) { + Vector lines = new Vector(10); + try { + BufferedReader reader = new BufferedReader( + new InputStreamReader(errorStream)); + for (int i = 0; i < 2; i++) { + for (int j = 0; j < 100; j++) { + String line = reader.readLine(); + if (line == null) { + reader = new BufferedReader(new InputStreamReader( + fromProcess)); + break; + } + lines.addElement(line); + } + } + } catch (IOException ex) { + } + output = new String[lines.size()]; + lines.copyInto(output); + return output; + } + output = new String[0]; + return output; + } + /** + * Install a handler for the error stream of the subprocess. + * + * @param is + * input stream to read from the error stream from the + * subprocess + */ + public void setProcessErrorStream(InputStream is) throws IOException { + errorStream = is; + } + /** + * Install a handler for the input stream of the subprocess. + * + * @param os + * output stream to write to the standard input stream of the + * subprocess + */ + public void setProcessInputStream(OutputStream os) throws IOException { + os.close(); + } + /** + * Install a handler for the output stream of the subprocess. + * + * @param is + * input stream to read from the error stream from the + * subprocess + */ + public void setProcessOutputStream(InputStream is) throws IOException { + fromProcess = is; + } + /** + * Start handling of the streams. + */ + public void start() throws IOException { + } + /** + * Stop handling of the streams - will not be restarted. + */ + public void stop() { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAslcompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAslcompiler.java new file mode 100644 index 0000000000..88dda5796f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAslcompiler.java @@ -0,0 +1,226 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.File; +import java.util.Enumeration; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.AslcompilerDef; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.TargetDef; +import net.sf.antcontrib.cpptasks.types.CommandLineArgument; + +import org.apache.tools.ant.BuildException; +/** + * An abstract ASL Compiler implementation which uses an external program to + * perform the ASL compile. + * + */ +public abstract class CommandLineAslcompiler extends AbstractAslcompiler{ + + private String command; + private String identifier; + private String identifierArg; + + protected CommandLineAslcompiler(String command, String identifierArg, + String[] sourceExtensions, String[] headerExtensions, + String outputSuffix) { + super(sourceExtensions, headerExtensions, outputSuffix); + this.command = command; + this.identifierArg = identifierArg; + } + + abstract protected void addImpliedArgs(Vector args, boolean debug, + Boolean defaultflag); + + /** + * Compile a ACPI source file + * + */ + public void aslcompiler(CCTask task, File outputDir, String[] sourceFiles, + String[] args, String[] endArgs) throws BuildException{ + String command = getCommand(); + int baseLength = command.length() + args.length + endArgs.length; + for (int i = 0; i < args.length; i++) { + baseLength += args[i].length(); + } + for (int i = 0; i < endArgs.length; i++) { + baseLength += endArgs[i].length(); + } + if (baseLength > getMaximumCommandLength()) { + throw new BuildException( + "Command line is over maximum length without sepcifying source file"); + } + int maxInputFilesPerCommand = getMaximumInputFilesPerCommand(); + int argumentCountPerInputFile = getArgumentCountPerInputFIle(); + for (int sourceIndex = 0; sourceIndex < sourceFiles.length;) { + int cmdLength = baseLength; + int firstFileNextExec; + for (firstFileNextExec = sourceIndex; firstFileNextExec < sourceFiles.length + && (firstFileNextExec - sourceIndex) < maxInputFilesPerCommand; firstFileNextExec++) { + cmdLength += getTotalArgumentLengthForInputFile(outputDir, + sourceFiles[firstFileNextExec]); + if (cmdLength >= getMaximumCommandLength()) + break; + } + if (firstFileNextExec == sourceIndex) { + throw new BuildException( + "Extremely long file name, can't fit on command line"); + } + int argCount = args.length + 1 + endArgs.length + + (firstFileNextExec - sourceIndex) + * argumentCountPerInputFile; + String[] commandline = new String[argCount]; + int index = 0; + commandline[index++] = command; + for (int j = 0; j < args.length; j++) { + commandline[index++] = args[j]; + } + for (int j = sourceIndex; j < firstFileNextExec; j++) { + for (int k = 0; k < argumentCountPerInputFile; k++) { + commandline[index++] = getInputFileArgument(outputDir, + sourceFiles[j], k); + } + } + for (int j = 0; j < endArgs.length; j++) { + commandline[index++] = endArgs[j]; + } + int retval = runCommand(task, outputDir, commandline); + // if with monitor, add more code + if (retval != 0) { + throw new BuildException(this.getCommand() + + " failed with return code " + retval, + task.getLocation()); + } + sourceIndex = firstFileNextExec; + } + } + + protected AslcompilerConfiguration createConfiguration(final CCTask task, + final LinkType linkType, + final ProcessorDef[] baseDefs, + final AslcompilerDef specificDef, + final TargetDef targetPlatform) { + Vector args = new Vector(); + AslcompilerDef[] defaultProviders = new AslcompilerDef[baseDefs.length +1]; + for (int i = 0; i < baseDefs.length; i++) { + defaultProviders[i + 1] = (AslcompilerDef) baseDefs[i]; + } + defaultProviders[0] = specificDef; + Vector cmdArgs = new Vector(); + // + // add command line arguments inherited from element + // any "extends" and finally and specific AslcompilerDef + // + CommandLineArgument[] commandArgs; + for (int i = defaultProviders.length - 1; i >=0; i--){ + commandArgs = defaultProviders[i].getActiveProcessorArgs(); + for (int j = 0; j < commandArgs.length; j++) { + if (commandArgs[j].getLocation() == 0) { + args.addElement(commandArgs[j].getValue()); + } + else { + cmdArgs.addElement(commandArgs[j]); + } + } + } + // omit param + boolean debug = specificDef.getDebug(baseDefs, 0); + Boolean defaultflag = specificDef.getDefaultflag(defaultProviders, 1); + this.addImpliedArgs(args, debug, defaultflag); + Enumeration argEnum = cmdArgs.elements(); + int endCount = 0; + while( argEnum.hasMoreElements()) { + CommandLineArgument arg = (CommandLineArgument) argEnum.nextElement(); + switch (arg.getLocation()) { + case 1 : + args.addElement(arg.getValue()); + break; + case 2 : + endCount++; + break; + } + } + String[] endArgs = new String[endCount]; + argEnum = cmdArgs.elements(); + int index = 0; + while (argEnum.hasMoreElements()) { + CommandLineArgument arg = (CommandLineArgument) argEnum.nextElement(); + if (arg.getLocation() == 2) { + endArgs[index++] = arg.getValue(); + } + } + String[] argArray = new String[args.size()]; + args.copyInto(argArray); + return new CommandLineAslcompilerConfiguration(this, argArray, true, endArgs); + } + + protected int getArgumentCountPerInputFile() { + return 1; + } + + public String getIdentifier() { + if (identifier == null) { + if (identifierArg == null) { + identifier = getIdentifier(new String[]{command}, command); + } + else { + identifier = getIdentifier( + new String[]{command, identifierArg}, command); + } + } + return identifier; + } + + public final String getCommand() { + return command; + } + abstract public int getMaximumCommandLength(); + public void setCommand(String command) { + this.command = command; + } + protected int getTotalArgumentLengthForInputFile(File outputDir, + String inputFile) { + return inputFile.length() + 1; + } + protected int runCommand(CCTask task, File workingDir, String[] cmdline) + throws BuildException { + return CUtil.runCommand(task, workingDir, cmdline, false, null); + + } + protected int getMaximumInputFilesPerCommand(){ + return 1; + } + protected int getArgumentCountPerInputFIle(){ + return 1; + } + protected String getInputFileArgument(File outputDir, String filename, int index) { + // + // if there is an embedded space, + // must enclose in quotes + if (filename.indexOf(' ') >= 0) { + StringBuffer buf = new StringBuffer("\""); + buf.append(filename); + buf.append("\""); + return buf.toString(); + } + return filename; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAslcompilerConfiguration.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAslcompilerConfiguration.java new file mode 100644 index 0000000000..9a3457dafb --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAslcompilerConfiguration.java @@ -0,0 +1,93 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.File; + +import org.apache.tools.ant.BuildException; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.ProcessorParam; + +/** + * A configuration for an ASL compiler + * + */ +public final class CommandLineAslcompilerConfiguration implements + AslcompilerConfiguration { + + private String[] args; + + private CommandLineAslcompiler acpi; + + private String[] endArgs; + + private boolean rebuild; + + public CommandLineAslcompilerConfiguration (CommandLineAslcompiler acpi, + String[] args, boolean rebuild, String[] endArgs) { + if (acpi == null) { + throw new NullPointerException("acpi"); + } + if (args == null) { + this.args = new String[0]; + } else { + this.args = (String[]) args.clone(); + } + this.acpi = acpi; + this.rebuild = rebuild; + this.endArgs = (String[]) endArgs.clone(); + } + + public int bid (String inputFile) { + int acpiBid = acpi.bid(inputFile); + return acpiBid; + } + + public void aslcompiler (CCTask task, File outputDir, String[] sourceFiles) + throws BuildException { + try { + acpi.aslcompiler(task, outputDir, sourceFiles, args, endArgs); + } catch (BuildException ex) { + throw ex; + } + } + + public String getIdentifier () { + return acpi.getCommand(); + } + + public ProcessorParam[] getParams () { + return new ProcessorParam[0]; + } + + public boolean getRebuild () { + return rebuild; + } + + public String[] getPreArguments () { + return (String[]) args.clone(); + } + + public String[] getEndArguments () { + return (String[]) endArgs.clone(); + } + + public String getOutputFileName (String inputFile) { + return acpi.getOutputFileName(inputFile); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAssembler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAssembler.java new file mode 100644 index 0000000000..f01fc5ee61 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAssembler.java @@ -0,0 +1,326 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.AssemblerDef; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.TargetDef; +import net.sf.antcontrib.cpptasks.types.CommandLineArgument; + +import org.apache.tools.ant.BuildException; + +/** + * An abstract Assembler implementation which uses an external program to + * perform the assemble. + * + */ +public abstract class CommandLineAssembler extends AbstractAssembler { + + private String command; + + private String identifier; + + private String identifierArg; + + protected CommandLineAssembler (String command, String identifierArg, + String[] sourceExtensions, String[] headerExtensions, + String outputSuffix) { + super(sourceExtensions, headerExtensions, outputSuffix); + this.command = command; + this.identifierArg = identifierArg; + } + + abstract protected void addImpliedArgs(Vector args, boolean debug, + Boolean defaultflag); + + /** + * Adds command-line arguments for include directories. + * + * If relativeArgs is not null will add corresponding relative paths include + * switches to that vector (for use in building a configuration identifier + * that is consistent between machines). + * + * @param baseDirPaths + * A vector containing the parts of the working directory, + * produced by CUtil.DecomposeFile. + * @param includeDirs + * Array of include directory paths + * @param args + * Vector of command line arguments used to execute the task + * @param relativeArgs + * Vector of command line arguments used to build the + * configuration identifier + */ + protected void addIncludes(String baseDirPath, File[] includeDirs, + Vector args, Vector relativeArgs, StringBuffer includePathId) { + for (int i = 0; i < includeDirs.length; i++) { + args.addElement(getIncludeDirSwitch(includeDirs[i] + .getAbsolutePath())); + if (relativeArgs != null) { + String relative = CUtil.getRelativePath(baseDirPath, + includeDirs[i]); + relativeArgs.addElement(getIncludeDirSwitch(relative)); + if (includePathId != null) { + if (includePathId.length() == 0) { + includePathId.append("/I"); + } else { + includePathId.append(" /I"); + } + includePathId.append(relative); + } + } + } + } + + abstract protected String getIncludeDirSwitch(String source); + + /** + * Assembles a source file + * + */ + public void assembler(CCTask task, File outputDir, String[] sourceFiles, + String[] args, String[] endArgs) throws BuildException { + String command = getCommand(); + int baseLength = command.length() + args.length + endArgs.length; + for (int i = 0; i < args.length; i++) { + baseLength += args[i].length(); + } + for (int i = 0; i < endArgs.length; i++) { + baseLength += endArgs[i].length(); + } + if (baseLength > getMaximumCommandLength()) { + throw new BuildException( + "Command line is over maximum length without sepcifying source file"); + } + int maxInputFilesPerCommand = getMaximumInputFilesPerCommand(); + int argumentCountPerInputFile = getArgumentCountPerInputFIle(); + for (int sourceIndex = 0; sourceIndex < sourceFiles.length;) { + int cmdLength = baseLength; + int firstFileNextExec; + for (firstFileNextExec = sourceIndex; firstFileNextExec < sourceFiles.length + && (firstFileNextExec - sourceIndex) < maxInputFilesPerCommand; firstFileNextExec++) { + cmdLength += getTotalArgumentLengthForInputFile(outputDir, + sourceFiles[firstFileNextExec]); + if (cmdLength >= getMaximumCommandLength()) + break; + } + if (firstFileNextExec == sourceIndex) { + throw new BuildException( + "Extremely long file name, can't fit on command line"); + } + int argCount = args.length + 1 + endArgs.length + + (firstFileNextExec - sourceIndex) + * argumentCountPerInputFile; + String[] commandline = new String[argCount]; + int index = 0; + commandline[index++] = command; + for (int j = 0; j < args.length; j++) { + commandline[index++] = args[j]; + } + for (int j = sourceIndex; j < firstFileNextExec; j++) { + for (int k = 0; k < argumentCountPerInputFile; k++) { + commandline[index++] = getInputFileArgument(outputDir, + sourceFiles[j], k); + } + } + for (int j = 0; j < endArgs.length; j++) { + commandline[index++] = endArgs[j]; + } + int retval = runCommand(task, outputDir, commandline); + // if with monitor, add more code + if (retval != 0) { + throw new BuildException(this.getCommand() + + " failed with return code " + retval, task + .getLocation()); + } + sourceIndex = firstFileNextExec; + } + } + + protected AssemblerConfiguration createConfiguration(final CCTask task, + final LinkType linkType, final ProcessorDef[] baseDefs, + final AssemblerDef specificDef, + final TargetDef targetPlatform) { + Vector args = new Vector(); + AssemblerDef[] defaultProviders = new AssemblerDef[baseDefs.length + 1]; + for (int i = 0; i < baseDefs.length; i++) { + defaultProviders[i + 1] = (AssemblerDef) baseDefs[i]; + } + defaultProviders[0] = specificDef; + Vector cmdArgs = new Vector(); + // + // add command line arguments inherited from element + // any "extends" and finally and specific AssemblerDef + // + CommandLineArgument[] commandArgs; + for (int i = defaultProviders.length - 1; i >= 0; i--) { + commandArgs = defaultProviders[i].getActiveProcessorArgs(); + for (int j = 0; j < commandArgs.length; j++) { + if (commandArgs[j].getLocation() == 0) { + args.addElement(commandArgs[j].getValue()); + } else { + cmdArgs.addElement(commandArgs[j]); + } + } + } + // omit param + boolean debug = specificDef.getDebug(baseDefs, 0); + Boolean defaultflag = specificDef.getDefaultflag(defaultProviders, 1); + this.addImpliedArgs(args, debug, defaultflag); + // + // Want to have distinct set of arguments with relative + // path names for includes that are used to build + // the configuration identifier + // + Vector relativeArgs = (Vector) args.clone(); + // + // add all active include an + // + StringBuffer includePathIdentifier = new StringBuffer(); + File baseDir = specificDef.getProject().getBaseDir(); + String baseDirPath; + try { + baseDirPath = baseDir.getCanonicalPath(); + } catch (IOException ex) { + baseDirPath = baseDir.toString(); + } + Vector includePath = new Vector(); + Vector sysIncludePath = new Vector(); + for (int i = defaultProviders.length - 1; i >= 0; i--) { + String[] incPath = defaultProviders[i].getActiveIncludePaths(); + for (int j = 0; j < incPath.length; j++) { + includePath.addElement(incPath[j]); + } + incPath = defaultProviders[i].getActiveSysIncludePaths(); + for (int j = 0; j < incPath.length; j++) { + sysIncludePath.addElement(incPath[j]); + } + } + File[] incPath = new File[includePath.size()]; + for (int i = 0; i < includePath.size(); i++) { + incPath[i] = new File((String) includePath.elementAt(i)); + } + File[] sysIncPath = new File[sysIncludePath.size()]; + for (int i = 0; i < sysIncludePath.size(); i++) { + sysIncPath[i] = new File((String) sysIncludePath.elementAt(i)); + } + addIncludes(baseDirPath, incPath, args, relativeArgs, + includePathIdentifier); + addIncludes(baseDirPath, sysIncPath, args, null, null); + StringBuffer buf = new StringBuffer(getIdentifier()); + for (int i = 0; i < relativeArgs.size(); i++) { + buf.append(relativeArgs.elementAt(i)); + buf.append(' '); + } + buf.setLength(buf.length() - 1); + Enumeration argEnum = cmdArgs.elements(); + int endCount = 0; + while (argEnum.hasMoreElements()) { + CommandLineArgument arg = (CommandLineArgument) argEnum + .nextElement(); + switch (arg.getLocation()) { + case 1: + args.addElement(arg.getValue()); + break; + case 2: + endCount++; + break; + } + } + String[] endArgs = new String[endCount]; + argEnum = cmdArgs.elements(); + int index = 0; + while (argEnum.hasMoreElements()) { + CommandLineArgument arg = (CommandLineArgument) argEnum + .nextElement(); + if (arg.getLocation() == 2) { + endArgs[index++] = arg.getValue(); + } + } + String[] argArray = new String[args.size()]; + args.copyInto(argArray); + return new CommandLineAssemblerConfiguration(this, incPath, sysIncPath, + new File[0], argArray, true, endArgs, new String[0]); + } + + protected int getArgumentCountPerInputFile() { + return 1; + } + + protected abstract File[] getEnvironmentIncludePath(); + + public String getIdentifier() { + if (identifier == null) { + if (identifierArg == null) { + identifier = getIdentifier(new String[] { command }, command); + } else { + identifier = getIdentifier(new String[] { command, + identifierArg }, command); + } + } + return identifier; + } + + public final String getCommand() { + return command; + } + + abstract public int getMaximumCommandLength(); + + public void setCommand(String command) { + this.command = command; + } + + protected int getTotalArgumentLengthForInputFile(File outputDir, + String inputFile) { + return inputFile.length() + 1; + } + + protected int runCommand(CCTask task, File workingDir, String[] cmdline) + throws BuildException { + return CUtil.runCommand(task, workingDir, cmdline, false, null); + } + + protected int getMaximumInputFilesPerCommand() { + return Integer.MAX_VALUE; + } + + protected int getArgumentCountPerInputFIle() { + return 1; + } + + protected String getInputFileArgument(File outputDir, String filename, + int index) { + // + // if there is an embedded space, + // must enclose in quotes + if (filename.indexOf(' ') >= 0) { + StringBuffer buf = new StringBuffer("\""); + buf.append(filename); + buf.append("\""); + return buf.toString(); + } + return filename; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAssemblerConfiguration.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAssemblerConfiguration.java new file mode 100644 index 0000000000..542d441559 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineAssemblerConfiguration.java @@ -0,0 +1,123 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.File; + +import org.apache.tools.ant.BuildException; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.ProcessorParam; + +/** + * A configuration for an assember + * + */ +public final class CommandLineAssemblerConfiguration implements + AssemblerConfiguration { + + private String[] args; + + private CommandLineAssembler assembler; + + private String[] endArgs; + + // + // include path from environment variable + // not explicitly stated in Ant script + // + private File[] envIncludePath; + + private String[] exceptFiles; + + private File[] includePath; + + private boolean rebuild; + + private File[] sysIncludePath; + + public CommandLineAssemblerConfiguration (CommandLineAssembler assembler, + File[] includePath, File[] sysIncludePath, + File[] envIncludePath, String[] args, boolean rebuild, + String[] endArgs, String[] exceptFiles) { + if (assembler == null) { + throw new NullPointerException("assembler"); + } + if (args == null) { + this.args = new String[0]; + } else { + this.args = (String[]) args.clone(); + } + if (includePath == null) { + this.includePath = new File[0]; + } else { + this.includePath = (File[]) includePath.clone(); + } + if (sysIncludePath == null) { + this.sysIncludePath = new File[0]; + } else { + this.sysIncludePath = (File[]) sysIncludePath.clone(); + } + if (envIncludePath == null) { + this.envIncludePath = new File[0]; + } else { + this.envIncludePath = (File[]) envIncludePath.clone(); + } + this.assembler = assembler; + this.rebuild = rebuild; + this.endArgs = (String[]) endArgs.clone(); + this.exceptFiles = (String[]) exceptFiles.clone(); + } + + public int bid(String inputFile) { + int assembleBid = assembler.bid(inputFile); + return assembleBid; + } + + public void assembler(CCTask task, File outputDir, String[] sourceFiles) + throws BuildException { + try { + assembler.assembler(task, outputDir, sourceFiles, args, endArgs); + } catch (BuildException ex) { + throw ex; + } + } + + public String getOutputFileName(String inputFile) { + return assembler.getOutputFileName(inputFile); + } + + public String getIdentifier() { + return assembler.getCommand(); + } + + public ProcessorParam[] getParams() { + return new ProcessorParam[0]; + } + + public boolean getRebuild() { + return rebuild; + } + + public String[] getPreArguments() { + return (String[]) args.clone(); + } + + public String[] getEndArguments() { + return (String[]) endArgs.clone(); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineCCompiler.java new file mode 100644 index 0000000000..442d6b8187 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineCCompiler.java @@ -0,0 +1,42 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.types.Environment; +/** + * An abstract Compiler implementation which uses an external program to + * perform the compile. + * + * @author Adam Murdoch + */ +public abstract class CommandLineCCompiler extends CommandLineCompiler { + protected CommandLineCCompiler(String command, String identifierArg, + String[] sourceExtensions, String[] headerExtensions, + String outputSuffix, boolean libtool, + CommandLineCCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + outputSuffix, libtool, libtoolCompiler, newEnvironment, env); + } + protected Parser createParser(File source) { + return new CParser(); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineCompiler.java new file mode 100644 index 0000000000..3f45ce539d --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineCompiler.java @@ -0,0 +1,435 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.CompilerDef; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.ProcessorParam; +import net.sf.antcontrib.cpptasks.types.CommandLineArgument; +import net.sf.antcontrib.cpptasks.types.UndefineArgument; +import net.sf.antcontrib.cpptasks.TargetDef; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum;; +/** + * An abstract Compiler implementation which uses an external program to + * perform the compile. + * + * @author Adam Murdoch + */ +public abstract class CommandLineCompiler extends AbstractCompiler { + private String command; + private final Environment env; + private String identifier; + private String identifierArg; + private boolean libtool; + private CommandLineCompiler libtoolCompiler; + private final boolean newEnvironment; + protected CommandLineCompiler(String command, String identifierArg, + String[] sourceExtensions, String[] headerExtensions, + String outputSuffix, boolean libtool, + CommandLineCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(sourceExtensions, headerExtensions, outputSuffix); + this.command = command; + if (libtool && libtoolCompiler != null) { + throw new java.lang.IllegalArgumentException( + "libtoolCompiler should be null when libtool is true"); + } + this.libtool = libtool; + this.libtoolCompiler = libtoolCompiler; + this.identifierArg = identifierArg; + this.newEnvironment = newEnvironment; + this.env = env; + } + abstract protected void addImpliedArgs(Vector args, boolean debug, + boolean multithreaded, boolean exceptions, LinkType linkType, + Boolean rtti, OptimizationEnum optimization, Boolean defaultflag); + /** + * Adds command-line arguments for include directories. + * + * If relativeArgs is not null will add corresponding relative paths + * include switches to that vector (for use in building a configuration + * identifier that is consistent between machines). + * + * @param baseDirPaths + * A vector containing the parts of the working directory, + * produced by CUtil.DecomposeFile. + * @param includeDirs + * Array of include directory paths + * @param args + * Vector of command line arguments used to execute the task + * @param relativeArgs + * Vector of command line arguments used to build the + * configuration identifier + */ + protected void addIncludes(String baseDirPath, File[] includeDirs, + Vector args, Vector relativeArgs, StringBuffer includePathId) { + for (int i = 0; i < includeDirs.length; i++) { + args.addElement(getIncludeDirSwitch(includeDirs[i] + .getAbsolutePath())); + if (relativeArgs != null) { + String relative = CUtil.getRelativePath(baseDirPath, + includeDirs[i]); + relativeArgs.addElement(getIncludeDirSwitch(relative)); + if (includePathId != null) { + if (includePathId.length() == 0) { + includePathId.append("/I"); + } else { + includePathId.append(" /I"); + } + includePathId.append(relative); + } + } + } + } + abstract protected void addWarningSwitch(Vector args, int warnings); + protected void buildDefineArguments(CompilerDef[] defs, Vector args) { + // + // assume that we aren't inheriting defines from containing + // + UndefineArgument[] merged = defs[0].getActiveDefines(); + for (int i = 1; i < defs.length; i++) { + // + // if we are inheriting, merge the specific defines with the + // containing defines + merged = UndefineArgument.merge(defs[i].getActiveDefines(), merged); + } + StringBuffer buf = new StringBuffer(30); + for (int i = 0; i < merged.length; i++) { + buf.setLength(0); + UndefineArgument current = merged[i]; + if (current.isDefine()) { + getDefineSwitch(buf, current.getName(), current.getValue()); + } else { + getUndefineSwitch(buf, current.getName()); + } + args.addElement(buf.toString()); + } + } + /** + * Compiles a source file. + * + * @author Curt Arnold + */ + public void compile(CCTask task, File outputDir, String[] sourceFiles, + String[] args, String[] endArgs, boolean relentless, + CommandLineCompilerConfiguration config, ProgressMonitor monitor) + throws BuildException { + BuildException exc = null; + // + // determine length of executable name and args + // + String command = getCommand(); + int baseLength = command.length() + args.length + endArgs.length; + if (libtool) { + baseLength += 8; + } + for (int i = 0; i < args.length; i++) { + baseLength += args[i].length(); + } + for (int i = 0; i < endArgs.length; i++) { + baseLength += endArgs[i].length(); + } + if (baseLength > getMaximumCommandLength()) { + throw new BuildException( + "Command line is over maximum length without specifying source file"); + } + // + // typically either 1 or Integer.MAX_VALUE + // + int maxInputFilesPerCommand = getMaximumInputFilesPerCommand(); + int argumentCountPerInputFile = getArgumentCountPerInputFile(); + for (int sourceIndex = 0; sourceIndex < sourceFiles.length;) { + int cmdLength = baseLength; + int firstFileNextExec; + for (firstFileNextExec = sourceIndex; firstFileNextExec < sourceFiles.length + && (firstFileNextExec - sourceIndex) < maxInputFilesPerCommand; firstFileNextExec++) { + cmdLength += getTotalArgumentLengthForInputFile(outputDir, + sourceFiles[firstFileNextExec]); + if (cmdLength >= getMaximumCommandLength()) + break; + } + if (firstFileNextExec == sourceIndex) { + throw new BuildException( + "Extremely long file name, can't fit on command line"); + } + int argCount = args.length + 1 + endArgs.length + + (firstFileNextExec - sourceIndex) + * argumentCountPerInputFile; + if (libtool) { + argCount++; + } + String[] commandline = new String[argCount]; + int index = 0; + if (libtool) { + commandline[index++] = "libtool"; + } + commandline[index++] = command; + for (int j = 0; j < args.length; j++) { + commandline[index++] = args[j]; + } + for (int j = sourceIndex; j < firstFileNextExec; j++) { + for (int k = 0; k < argumentCountPerInputFile; k++) { + commandline[index++] = getInputFileArgument(outputDir, + sourceFiles[j], k); + } + } + for (int j = 0; j < endArgs.length; j++) { + commandline[index++] = endArgs[j]; + } + int retval = runCommand(task, outputDir, commandline); + if (monitor != null) { + String[] fileNames = new String[firstFileNextExec - sourceIndex]; + for (int j = 0; j < fileNames.length; j++) { + fileNames[j] = sourceFiles[sourceIndex + j]; + } + monitor.progress(fileNames); + } + // + // if the process returned a failure code and + // we aren't holding an exception from an earlier + // interation + if (retval != 0 && exc == null) { + // + // construct the exception + // + exc = new BuildException(this.getCommand() + + " failed with return code " + retval, task + .getLocation()); + // + // and throw it now unless we are relentless + // + if (!relentless) { + throw exc; + } + } + sourceIndex = firstFileNextExec; + } + // + // if the compiler returned a failure value earlier + // then throw an exception + if (exc != null) { + throw exc; + } + } + protected CompilerConfiguration createConfiguration(final CCTask task, + final LinkType linkType, + final ProcessorDef[] baseDefs, + final CompilerDef specificDef, + final TargetDef targetPlatform) { + Vector args = new Vector(); + CompilerDef[] defaultProviders = new CompilerDef[baseDefs.length + 1]; + for (int i = 0; i < baseDefs.length; i++) { + defaultProviders[i + 1] = (CompilerDef) baseDefs[i]; + } + defaultProviders[0] = specificDef; + Vector cmdArgs = new Vector(); + // + // add command line arguments inherited from element + // any "extends" and finally the specific CompilerDef + CommandLineArgument[] commandArgs; + for (int i = defaultProviders.length - 1; i >= 0; i--) { + commandArgs = defaultProviders[i].getActiveProcessorArgs(); + for (int j = 0; j < commandArgs.length; j++) { + if (commandArgs[j].getLocation() == 0) { + args.addElement(commandArgs[j].getValue()); + } else { + cmdArgs.addElement(commandArgs[j]); + } + } + } + Vector params = new Vector(); + // + // add command line arguments inherited from element + // any "extends" and finally the specific CompilerDef + ProcessorParam[] paramArray; + for (int i = defaultProviders.length - 1; i >= 0; i--) { + paramArray = defaultProviders[i].getActiveProcessorParams(); + for (int j = 0; j < paramArray.length; j++) { + params.add(paramArray[j]); + } + } + paramArray = (ProcessorParam[]) (params + .toArray(new ProcessorParam[params.size()])); + boolean multithreaded = specificDef.getMultithreaded(defaultProviders, + 1); + boolean debug = specificDef.getDebug(baseDefs, 0); + boolean exceptions = specificDef.getExceptions(defaultProviders, 1); + Boolean rtti = specificDef.getRtti(defaultProviders, 1); + Boolean defaultflag = specificDef.getDefaultflag(defaultProviders, 1); + OptimizationEnum optimization = specificDef.getOptimization(defaultProviders, 1); + this.addImpliedArgs(args, debug, multithreaded, exceptions, linkType, rtti, optimization, defaultflag); + // + // add all appropriate defines and undefines + // + buildDefineArguments(defaultProviders, args); + // + // Want to have distinct set of arguments with relative + // path names for includes that are used to build + // the configuration identifier + // + Vector relativeArgs = (Vector) args.clone(); + // + // add all active include and sysincludes + // + StringBuffer includePathIdentifier = new StringBuffer(); + File baseDir = specificDef.getProject().getBaseDir(); + String baseDirPath; + try { + baseDirPath = baseDir.getCanonicalPath(); + } catch (IOException ex) { + baseDirPath = baseDir.toString(); + } + Vector includePath = new Vector(); + Vector sysIncludePath = new Vector(); + for (int i = defaultProviders.length - 1; i >= 0; i--) { + String[] incPath = defaultProviders[i].getActiveIncludePaths(); + for (int j = 0; j < incPath.length; j++) { + includePath.addElement(incPath[j]); + } + incPath = defaultProviders[i].getActiveSysIncludePaths(); + for (int j = 0; j < incPath.length; j++) { + sysIncludePath.addElement(incPath[j]); + } + } + File[] incPath = new File[includePath.size()]; + for (int i = 0; i < includePath.size(); i++) { + incPath[i] = new File((String) includePath.elementAt(i)); + } + File[] sysIncPath = new File[sysIncludePath.size()]; + for (int i = 0; i < sysIncludePath.size(); i++) { + sysIncPath[i] = new File((String) sysIncludePath.elementAt(i)); + } + addIncludes(baseDirPath, incPath, args, relativeArgs, + includePathIdentifier); + addIncludes(baseDirPath, sysIncPath, args, null, null); + StringBuffer buf = new StringBuffer(getIdentifier()); + for (int i = 0; i < relativeArgs.size(); i++) { + buf.append(relativeArgs.elementAt(i)); + buf.append(' '); + } + buf.setLength(buf.length() - 1); + String configId = buf.toString(); + int warnings = specificDef.getWarnings(defaultProviders, 0); + addWarningSwitch(args, warnings); + Enumeration argEnum = cmdArgs.elements(); + int endCount = 0; + while (argEnum.hasMoreElements()) { + CommandLineArgument arg = (CommandLineArgument) argEnum + .nextElement(); + switch (arg.getLocation()) { + case 1 : + args.addElement(arg.getValue()); + break; + case 2 : + endCount++; + break; + } + } + String[] endArgs = new String[endCount]; + argEnum = cmdArgs.elements(); + int index = 0; + while (argEnum.hasMoreElements()) { + CommandLineArgument arg = (CommandLineArgument) argEnum + .nextElement(); + if (arg.getLocation() == 2) { + endArgs[index++] = arg.getValue(); + } + } + String[] argArray = new String[args.size()]; + args.copyInto(argArray); + boolean rebuild = specificDef.getRebuild(baseDefs, 0); + File[] envIncludePath = getEnvironmentIncludePath(); + return new CommandLineCompilerConfiguration(this, configId, incPath, + sysIncPath, envIncludePath, includePathIdentifier.toString(), + argArray, paramArray, rebuild, endArgs); + } + protected int getArgumentCountPerInputFile() { + return 1; + } + protected final String getCommand() { + return command; + } + abstract protected void getDefineSwitch(StringBuffer buffer, String define, + String value); + protected abstract File[] getEnvironmentIncludePath(); + public String getIdentifier() { + if (identifier == null) { + if (identifierArg == null) { + identifier = getIdentifier(new String[]{command}, command); + } else { + identifier = getIdentifier( + new String[]{command, identifierArg}, command); + } + } + return identifier; + } + abstract protected String getIncludeDirSwitch(String source); + protected String getInputFileArgument(File outputDir, String filename, + int index) { + // + // if there is an embedded space, + // must enclose in quotes + if (filename.indexOf(' ') >= 0) { + StringBuffer buf = new StringBuffer("\""); + buf.append(filename); + buf.append("\""); + return buf.toString(); + } + return filename; + } + protected final boolean getLibtool() { + return libtool; + } + /** + * Obtains the same compiler, but with libtool set + * + * Default behavior is to ignore libtool + */ + public final CommandLineCompiler getLibtoolCompiler() { + if (libtoolCompiler != null) { + return libtoolCompiler; + } + return this; + } + abstract public int getMaximumCommandLength(); + protected int getMaximumInputFilesPerCommand() { + return Integer.MAX_VALUE; + } + protected int getTotalArgumentLengthForInputFile(File outputDir, + String inputFile) { + return inputFile.length() + 1; + } + abstract protected void getUndefineSwitch(StringBuffer buffer, String define); + /** + * This method is exposed so test classes can overload and test the + * arguments without actually spawning the compiler + */ + protected int runCommand(CCTask task, File workingDir, String[] cmdline) + throws BuildException { + return CUtil.runCommand(task, workingDir, cmdline, newEnvironment, env); + } + protected final void setCommand(String command) { + this.command = command; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineCompilerConfiguration.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineCompilerConfiguration.java new file mode 100644 index 0000000000..4c53df105b --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineCompilerConfiguration.java @@ -0,0 +1,216 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CompilerParam; +import net.sf.antcontrib.cpptasks.DependencyInfo; +import net.sf.antcontrib.cpptasks.ProcessorParam; + +import org.apache.tools.ant.BuildException; +/** + * A configuration for a C++ compiler + * + * @author Curt Arnold + */ +public final class CommandLineCompilerConfiguration + implements + CompilerConfiguration { + private/* final */String[] args; + private/* final */CommandLineCompiler compiler; + private String[] endArgs; + // + // include path from environment variable not + // explicitly stated in Ant script + private/* final */File[] envIncludePath; + private String[] exceptFiles; + private/* final */String identifier; + private/* final */File[] includePath; + private/* final */String includePathIdentifier; + private boolean isPrecompiledHeaderGeneration; + private/* final */ProcessorParam[] params; + private/* final */boolean rebuild; + private/* final */File[] sysIncludePath; + public CommandLineCompilerConfiguration(CommandLineCompiler compiler, + String identifier, File[] includePath, File[] sysIncludePath, + File[] envIncludePath, String includePathIdentifier, String[] args, + ProcessorParam[] params, boolean rebuild, String[] endArgs) { + if (compiler == null) { + throw new NullPointerException("compiler"); + } + if (identifier == null) { + throw new NullPointerException("identifier"); + } + if (includePathIdentifier == null) { + throw new NullPointerException("includePathIdentifier"); + } + if (args == null) { + this.args = new String[0]; + } else { + this.args = (String[]) args.clone(); + } + if (includePath == null) { + this.includePath = new File[0]; + } else { + this.includePath = (File[]) includePath.clone(); + } + if (sysIncludePath == null) { + this.sysIncludePath = new File[0]; + } else { + this.sysIncludePath = (File[]) sysIncludePath.clone(); + } + if (envIncludePath == null) { + this.envIncludePath = new File[0]; + } else { + this.envIncludePath = (File[]) envIncludePath.clone(); + } + this.compiler = compiler; + this.params = (ProcessorParam[]) params.clone(); + this.rebuild = rebuild; + this.identifier = identifier; + this.includePathIdentifier = includePathIdentifier; + this.endArgs = (String[]) endArgs.clone(); + exceptFiles = null; + isPrecompiledHeaderGeneration = false; + } + public CommandLineCompilerConfiguration( + CommandLineCompilerConfiguration base, String[] additionalArgs, + String[] exceptFiles, boolean isPrecompileHeaderGeneration) { + compiler = base.compiler; + identifier = base.identifier; + rebuild = base.rebuild; + includePath = (File[]) base.includePath.clone(); + sysIncludePath = (File[]) base.sysIncludePath.clone(); + endArgs = (String[]) base.endArgs.clone(); + envIncludePath = (File[]) base.envIncludePath.clone(); + includePathIdentifier = base.includePathIdentifier; + if (exceptFiles != null) { + this.exceptFiles = (String[]) exceptFiles.clone(); + } + this.isPrecompiledHeaderGeneration = isPrecompileHeaderGeneration; + args = new String[base.args.length + additionalArgs.length]; + for (int i = 0; i < base.args.length; i++) { + args[i] = base.args[i]; + } + int index = base.args.length; + for (int i = 0; i < additionalArgs.length; i++) { + args[index++] = additionalArgs[i]; + } + } + public int bid(String inputFile) { + int compilerBid = compiler.bid(inputFile); + if (compilerBid > 0 && exceptFiles != null) { + for (int i = 0; i < exceptFiles.length; i++) { + if (inputFile.equals(exceptFiles[i])) { + return 0; + } + } + } + return compilerBid; + } + public void compile(CCTask task, File outputDir, String[] sourceFiles, + boolean relentless, ProgressMonitor monitor) throws BuildException { + if (monitor != null) { + monitor.start(this); + } + try { + compiler.compile(task, outputDir, sourceFiles, args, endArgs, + relentless, this, monitor); + if (monitor != null) { + monitor.finish(this, true); + } + } catch (BuildException ex) { + if (monitor != null) { + monitor.finish(this, false); + } + throw ex; + } + } + /** + * + * This method may be used to get two distinct compiler configurations, one + * for compiling the specified file and producing a precompiled header + * file, and a second for compiling other files using the precompiled + * header file. + * + * The last (preferrably only) include directive in the prototype file will + * be used to mark the boundary between pre-compiled and normally compiled + * headers. + * + * @param prototype + * A source file (for example, stdafx.cpp) that is used to build + * the precompiled header file. @returns null if precompiled + * headers are not supported or a two element array containing + * the precompiled header generation configuration and the + * consuming configuration + * + */ + public CompilerConfiguration[] createPrecompileConfigurations( + File prototype, String[] nonPrecompiledFiles) { + if (compiler instanceof PrecompilingCompiler) { + return ((PrecompilingCompiler) compiler) + .createPrecompileConfigurations(this, prototype, + nonPrecompiledFiles); + } + return null; + } + /** + * Returns a string representation of this configuration. Should be + * canonical so that equivalent configurations will have equivalent string + * representations + */ + public String getIdentifier() { + return identifier; + } + public String getIncludePathIdentifier() { + return includePathIdentifier; + } + public String getOutputFileName(String inputFile) { + return compiler.getOutputFileName(inputFile); + } + public CompilerParam getParam(String name) { + for (int i = 0; i < params.length; i++) { + if (name.equals(params[i].getName())) + return (CompilerParam) params[i]; + } + return null; + } + public ProcessorParam[] getParams() { + return params; + } + public boolean getRebuild() { + return rebuild; + } + public boolean isPrecompileGeneration() { + return isPrecompiledHeaderGeneration; + } + public DependencyInfo parseIncludes(CCTask task, File baseDir, File source) { + return compiler.parseIncludes(task, source, includePath, + sysIncludePath, envIncludePath, baseDir, + getIncludePathIdentifier()); + } + public String toString() { + return identifier; + } + public String[] getPreArguments() { + return (String[]) args.clone(); + } + public String[] getEndArguments() { + return (String[]) endArgs.clone(); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineFortranCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineFortranCompiler.java new file mode 100644 index 0000000000..d01cb9e356 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineFortranCompiler.java @@ -0,0 +1,42 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.parser.FortranParser; +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.types.Environment; +/** + * An abstract Compiler implementation which uses an external program to + * perform the compile. + * + * @author Curt Arnold + */ +public abstract class CommandLineFortranCompiler extends CommandLineCompiler { + protected CommandLineFortranCompiler(String command, String identifierArg, + String[] sourceExtensions, String[] headerExtensions, + String outputSuffix, boolean libtool, + CommandLineFortranCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + outputSuffix, libtool, libtoolCompiler, newEnvironment, env); + } + protected Parser createParser(File source) { + return new FortranParser(); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java new file mode 100644 index 0000000000..4161469a8f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineLinker.java @@ -0,0 +1,404 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.LinkerDef; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.ProcessorParam; +import net.sf.antcontrib.cpptasks.types.CommandLineArgument; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +import net.sf.antcontrib.cpptasks.TargetDef; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; + + +/** + * An abstract Linker implementation that performs the link via an external + * command. + * + * @author Adam Murdoch + */ +public abstract class CommandLineLinker extends AbstractLinker +{ + private String command; + private Environment env = null; + private String identifier; + private String identifierArg; + private boolean isLibtool; + private String[] librarySets; + private CommandLineLinker libtoolLinker; + private boolean newEnvironment = false; + private String outputSuffix; + + + /** Creates a comand line linker invocation */ + public CommandLineLinker(String command, + String identifierArg, + String[] extensions, + String[] ignoredExtensions, String outputSuffix, + boolean isLibtool, CommandLineLinker libtoolLinker) + { + super(extensions, ignoredExtensions); + this.command = command; + this.identifierArg = identifierArg; + this.outputSuffix = outputSuffix; + this.isLibtool = isLibtool; + this.libtoolLinker = libtoolLinker; + } + protected abstract void addBase(long base, Vector args); + + protected abstract void addFixed(Boolean fixed, Vector args); + + abstract protected void addImpliedArgs(boolean debug, + LinkType linkType, Vector args, Boolean defaultflag); + protected abstract void addIncremental(boolean incremental, Vector args); + + // + // Windows processors handle these through file list + // + protected String[] addLibrarySets(CCTask task, LibrarySet[] libsets, Vector preargs, + Vector midargs, Vector endargs) { + return null; + } + protected abstract void addMap(boolean map, Vector args); + protected abstract void addStack(int stack, Vector args); + protected abstract void addEntry(String entry, Vector args); + + protected LinkerConfiguration createConfiguration( + CCTask task, + LinkType linkType, + ProcessorDef[] baseDefs, LinkerDef specificDef, TargetDef targetPlatform) { + + Vector preargs = new Vector(); + Vector midargs = new Vector(); + Vector endargs = new Vector(); + Vector[] args = new Vector[] { preargs, midargs, endargs }; + + LinkerDef[] defaultProviders = new LinkerDef[baseDefs.length+1]; + defaultProviders[0] = specificDef; + for(int i = 0; i < baseDefs.length; i++) { + defaultProviders[i+1] = (LinkerDef) baseDefs[i]; + } + // + // add command line arguments inherited from element + // any "extends" and finally the specific CompilerDef + CommandLineArgument[] commandArgs; + for(int i = defaultProviders.length-1; i >= 0; i--) { + commandArgs = defaultProviders[i].getActiveProcessorArgs(); + for(int j = 0; j < commandArgs.length; j++) { + args[commandArgs[j].getLocation()]. + addElement(commandArgs[j].getValue()); + } + } + + Vector params = new Vector(); + // + // add command line arguments inherited from element + // any "extends" and finally the specific CompilerDef + ProcessorParam[] paramArray; + for (int i = defaultProviders.length - 1; i >= 0; i--) { + paramArray = defaultProviders[i].getActiveProcessorParams(); + for (int j = 0; j < paramArray.length; j++) { + params.add(paramArray[j]); + } + } + + paramArray = (ProcessorParam[])(params.toArray(new ProcessorParam[params.size()])); + + boolean debug = specificDef.getDebug(baseDefs,0); + + + String startupObject = getStartupObject(linkType); + Boolean defaultflag = specificDef.getDefaultflag(defaultProviders, 1); + addImpliedArgs(debug, linkType, preargs, defaultflag); + addIncremental(specificDef.getIncremental(defaultProviders,1), preargs); + addFixed(specificDef.getFixed(defaultProviders,1), preargs); + addMap(specificDef.getMap(defaultProviders,1), preargs); + addBase(specificDef.getBase(defaultProviders,1), preargs); + addStack(specificDef.getStack(defaultProviders,1), preargs); + addEntry(specificDef.getEntry(defaultProviders, 1), preargs); + + String[] libnames = null; + LibrarySet[] libsets = specificDef.getActiveLibrarySets(defaultProviders,1); + if (libsets.length > 0) { + libnames = addLibrarySets(task, libsets, preargs, midargs, endargs); + } + + StringBuffer buf = new StringBuffer(getIdentifier()); + for (int i = 0; i < 3; i++) { + Enumeration argenum = args[i].elements(); + while (argenum.hasMoreElements()) { + buf.append(' '); + buf.append(argenum.nextElement().toString()); + } + } + String configId = buf.toString(); + + String[][] options = new String[][] { + new String[args[0].size() + args[1].size()], + new String[args[2].size()] }; + args[0].copyInto(options[0]); + int offset = args[0].size(); + for (int i = 0; i < args[1].size(); i++) { + options[0][i+offset] = (String) args[1].elementAt(i); + } + args[2].copyInto(options[1]); + + + boolean rebuild = specificDef.getRebuild(baseDefs,0); + boolean map = specificDef.getMap(defaultProviders,1); + + //task.log("libnames:"+libnames.length, Project.MSG_VERBOSE); + return new CommandLineLinkerConfiguration(this,configId,options, + paramArray, + rebuild,map,libnames, startupObject); + } + + /** + * Allows drived linker to decorate linker option. + * Override by GccLinker to prepend a "-Wl," to + * pass option to through gcc to linker. + * + * @param buf buffer that may be used and abused in the decoration process, + * must not be null. + * @param arg linker argument + */ + protected String decorateLinkerOption(StringBuffer buf, String arg) { + return arg; + } + + protected final String getCommand() { + return command; + } + protected abstract String getCommandFileSwitch(String commandFile); + + + public String getIdentifier() { + if(identifier == null) { + if (identifierArg == null) { + identifier = getIdentifier(new String[] { command }, command); + } else { + identifier = getIdentifier(new String[] { command, identifierArg }, + command); + } + } + return identifier; + } + public final CommandLineLinker getLibtoolLinker() { + if (libtoolLinker != null) { + return libtoolLinker; + } + return this; + } + protected abstract int getMaximumCommandLength(); + + public String getOutputFileName(String baseName) { + return baseName + outputSuffix; + } + + protected String[] getOutputFileSwitch(CCTask task, String outputFile) { + return getOutputFileSwitch(outputFile); + } + protected abstract String[] getOutputFileSwitch(String outputFile); + protected String getStartupObject(LinkType linkType) { + return null; + } + + /** + * Performs a link using a command line linker + * + */ + public void link(CCTask task, + File outputFile, + String[] sourceFiles, + CommandLineLinkerConfiguration config) + throws BuildException + { + File parentDir = new File(outputFile.getParent()); + String parentPath; + try { + parentPath = parentDir.getCanonicalPath(); + } catch(IOException ex) { + parentPath = parentDir.getAbsolutePath(); + } + String[] execArgs = prepareArguments(task, parentPath,outputFile.getName(), + sourceFiles, config); + int commandLength = 0; + for(int i = 0; i < execArgs.length; i++) { + commandLength += execArgs[i].length() + 1; + } + + // + // if command length exceeds maximum + // (1024 for Windows) then create a temporary + // file containing everything but the command name + if(commandLength >= this.getMaximumCommandLength()) { + try { + execArgs = prepareResponseFile(outputFile,execArgs); + } + catch(IOException ex) { + throw new BuildException(ex); + } + } + + int retval = runCommand(task,parentDir,execArgs); + // + // if the process returned a failure code then + // throw an BuildException + // + if(retval != 0) { + // + // construct the exception + // + throw new BuildException(this.getCommand() + " failed with return code " + retval, task.getLocation()); + } + + } + + + /** + * Prepares argument list for exec command. Will return null + * if command line would exceed allowable command line buffer. + * + * @param outputFile linker output file + * @param sourceFiles linker input files (.obj, .o, .res) + * @param args linker arguments + * @return arguments for runTask + */ + protected String[] prepareArguments( + CCTask task, + String outputDir, + String outputFile, + String[] sourceFiles, + CommandLineLinkerConfiguration config) { + + String[] preargs = config.getPreArguments(); + String[] endargs = config.getEndArguments(); + String outputSwitch[] = getOutputFileSwitch(task, outputFile); + int allArgsCount = preargs.length + 1 + outputSwitch.length + + sourceFiles.length + endargs.length; + if (isLibtool) { + allArgsCount++; + } + String[] allArgs = new String[allArgsCount]; + int index = 0; + if (isLibtool) { + allArgs[index++] = "libtool"; + } + allArgs[index++] = this.getCommand(); + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < preargs.length; i++) { + allArgs[index++] = decorateLinkerOption(buf, preargs[i]); + } + for (int i = 0; i < outputSwitch.length; i++) { + allArgs[index++] = outputSwitch[i]; + } + for (int i = 0; i < sourceFiles.length; i++) { + allArgs[index++] = prepareFilename(buf,outputDir,sourceFiles[i]); + } + for (int i = 0; i < endargs.length; i++) { + allArgs[index++] = decorateLinkerOption(buf, endargs[i]); + } + return allArgs; + } + + /** + * Processes filename into argument form + * + */ + protected String prepareFilename(StringBuffer buf, + String outputDir, String sourceFile) { + String relativePath = CUtil.getRelativePath(outputDir, + new File(sourceFile)); + return quoteFilename(buf,relativePath); + } + + /** + * Prepares argument list to execute the linker using a + * response file. + * + * @param outputFile linker output file + * @param args output of prepareArguments + * @return arguments for runTask + */ + protected String[] prepareResponseFile(File outputFile,String[] args) throws IOException + { + String baseName = outputFile.getName(); + File commandFile = new File(outputFile.getParent(),baseName + ".rsp"); + FileWriter writer = new FileWriter(commandFile); + int execArgCount = 1; + if (isLibtool) { + execArgCount++; + } + String[] execArgs = new String[execArgCount+1]; + for (int i = 0; i < execArgCount; i++) { + execArgs[i] = args[i]; + } + execArgs[execArgCount] = getCommandFileSwitch(commandFile.toString()); + for(int i = execArgCount; i < args.length; i++) { + // + // if embedded space and not quoted then + // quote argument + if (args[i].indexOf(" ") >= 0 && args[i].charAt(0) != '\"') { + writer.write('\"'); + writer.write(args[i]); + writer.write("\"\n"); + } else { + writer.write(args[i]); + writer.write('\n'); + } + } + writer.close(); + return execArgs; + } + + + protected String quoteFilename(StringBuffer buf,String filename) { + if(filename.indexOf(' ') >= 0) { + buf.setLength(0); + buf.append('\"'); + buf.append(filename); + buf.append('\"'); + return buf.toString(); + } + return filename; + } + + /** + * This method is exposed so test classes can overload + * and test the arguments without actually spawning the + * compiler + */ + protected int runCommand(CCTask task, File workingDir,String[] cmdline) + throws BuildException { + return CUtil.runCommand(task,workingDir,cmdline, newEnvironment, env); + } + + protected final void setCommand(String command) { + this.command = command; + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineLinkerConfiguration.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineLinkerConfiguration.java new file mode 100644 index 0000000000..b3a7290b00 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CommandLineLinkerConfiguration.java @@ -0,0 +1,119 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.ProcessorParam; +import net.sf.antcontrib.cpptasks.TargetInfo; + +import org.apache.tools.ant.BuildException; +/** + * A configuration for a command line linker + * + * @author Curt Arnold + */ +public final class CommandLineLinkerConfiguration + implements + LinkerConfiguration { + private/* final */String[][] args; + private/* final */String identifier; + private String[] libraryNames; + private/* final */CommandLineLinker linker; + private/* final */boolean map; + private/* final */ProcessorParam[] params; + private/* final */boolean rebuild; + private String startupObject; + public CommandLineLinkerConfiguration(CommandLineLinker linker, + String identifier, String[][] args, ProcessorParam[] params, + boolean rebuild, boolean map, String[] libraryNames, + String startupObject) { + if (linker == null) { + throw new NullPointerException("linker"); + } + if (args == null) { + throw new NullPointerException("args"); + } else { + this.args = (String[][]) args.clone(); + } + this.linker = linker; + this.params = (ProcessorParam[]) params.clone(); + this.rebuild = rebuild; + this.identifier = identifier; + this.map = map; + if (libraryNames == null) { + this.libraryNames = new String[0]; + } else { + this.libraryNames = (String[]) libraryNames.clone(); + } + this.startupObject = startupObject; + } + public int bid(String filename) { + return linker.bid(filename); + } + public String[] getEndArguments() { + String[] clone = (String[]) args[1].clone(); + return clone; + } + /** + * Returns a string representation of this configuration. Should be + * canonical so that equivalent configurations will have equivalent string + * representations + */ + public String getIdentifier() { + return identifier; + } + public String[] getLibraryNames() { + String[] clone = (String[]) libraryNames.clone(); + return clone; + } + public boolean getMap() { + return map; + } + public String getOutputFileName(String inputFile) { + return linker.getOutputFileName(inputFile); + } + public LinkerParam getParam(String name) { + for (int i = 0; i < params.length; i++) { + if (name.equals(params[i].getName())) + return (LinkerParam) params[i]; + } + return null; + } + public ProcessorParam[] getParams() { + return params; + } + public String[] getPreArguments() { + String[] clone = (String[]) args[0].clone(); + return clone; + } + public boolean getRebuild() { + return rebuild; + } + public String getStartupObject() { + return startupObject; + } + public void link(CCTask task, TargetInfo linkTarget) throws BuildException { + // + // AllSourcePath's include any syslibsets + // + String[] sourcePaths = linkTarget.getAllSourcePaths(); + linker.link(task, linkTarget.getOutput(), sourcePaths, this); + } + public String toString() { + return identifier; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Compiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Compiler.java new file mode 100644 index 0000000000..bbb6c99c5d --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Compiler.java @@ -0,0 +1,24 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +/** + * A compiler. + * + * @author Adam Murdoch + */ +public interface Compiler extends Processor { +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CompilerConfiguration.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CompilerConfiguration.java new file mode 100644 index 0000000000..72abb8b5f4 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/CompilerConfiguration.java @@ -0,0 +1,64 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CompilerParam; +import net.sf.antcontrib.cpptasks.DependencyInfo; + +import org.apache.tools.ant.BuildException; +/** + * A configuration for a compiler + * + * @author Curt Arnold + */ +public interface CompilerConfiguration extends ProcessorConfiguration { + void compile(CCTask task, File outputDir, String[] sourceFiles, + boolean relentless, ProgressMonitor monitor) throws BuildException; + /** + * + * This method may be used to get two distinct compiler configurations, one + * for compiling the specified file and producing a precompiled header + * file, and a second for compiling other files using the precompiled + * header file. + * + * The last (preferrably only) include directive in the prototype file will + * be used to mark the boundary between pre-compiled and normally compiled + * headers. + * + * @param prototype + * A source file (for example, stdafx.cpp) that is used to build + * the precompiled header file. @returns null if precompiled + * headers are not supported or a two element array containing + * the precompiled header generation configuration and the + * consuming configuration + * + */ + CompilerConfiguration[] createPrecompileConfigurations(File prototype, + String[] nonPrecompiledFiles); + /** + * Returns an digest for the include path for the configuration. + * + * This is used to determine if cached dependency information is invalid + * because the include paths have changed + */ + String getIncludePathIdentifier(); + public CompilerParam getParam(String name); + boolean isPrecompileGeneration(); + DependencyInfo parseIncludes(CCTask task, File baseDir, File source); +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/LinkType.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/LinkType.java new file mode 100644 index 0000000000..7d6041ff93 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/LinkType.java @@ -0,0 +1,134 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import net.sf.antcontrib.cpptasks.OutputTypeEnum; +import net.sf.antcontrib.cpptasks.SubsystemEnum; +/** + * This class represents the target platform for the compile and link step. The + * name is an anachronism and should be changed. + * + * @author Curt Arnold + */ +public class LinkType { + private OutputTypeEnum outputType = new OutputTypeEnum(); + private boolean staticRuntime = false; + private SubsystemEnum subsystem = new SubsystemEnum(); + /** + * Constructor + * + * By default, an gui executable with a dynamically linked runtime + * + */ + public LinkType() { + } + /** + * Gets whether the link should produce an executable + * + * @return boolean + */ + public boolean isExecutable() { + String value = outputType.getValue(); + return value.equals("executable"); + } + /** + * Gets whether the link should produce a plugin module. + * + * @return boolean + */ + public boolean isPluginModule() { + String value = outputType.getValue(); + return value.equals("plugin"); + } + /** + * Gets whether the link should produce a shared library. + * + * @return boolean + */ + public boolean isSharedLibrary() { + String value = outputType.getValue(); + return value.equals("shared") || value.equals("plugin"); + } + /** + * Gets whether the link should produce a static library. + * + * @return boolean + */ + public boolean isStaticLibrary() { + String value = outputType.getValue(); + return value.equals("static"); + } + /** + * Gets whether the module should use a statically linked runtime library. + * + * @return boolean + */ + public boolean isStaticRuntime() { + return staticRuntime; + } + /** + * Gets whether the link should produce a module for a console subsystem. + * + * @return boolean + */ + public boolean isSubsystemConsole() { + String value = subsystem.getValue(); + return value.equals("console"); + } + /** + * Gets whether the link should produce a module for a graphical user + * interface subsystem. + * + * @return boolean + */ + public boolean isSubsystemGUI() { + String value = subsystem.getValue(); + return value.equals("gui"); + } + /** + * Sets the output type (execuable, shared, etc). + * + * @param outputType, + * may not be null + */ + public void setOutputType(OutputTypeEnum outputType) { + if (outputType == null) { + throw new IllegalArgumentException("outputType"); + } + this.outputType = outputType; + } + /** + * Requests use of a static runtime library. + * + * @param staticRuntime + * if true, use static runtime library if possible. + */ + public void setStaticRuntime(boolean staticRuntime) { + this.staticRuntime = staticRuntime; + } + /** + * Sets the subsystem (gui, console, etc). + * + * @param subsystem + * subsystem, may not be null + */ + public void setSubsystem(SubsystemEnum subsystem) { + if (subsystem == null) { + throw new IllegalArgumentException("subsystem"); + } + this.subsystem = subsystem; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Linker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Linker.java new file mode 100644 index 0000000000..776a808ac7 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Linker.java @@ -0,0 +1,57 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; +/** + * A linker for executables, and static and dynamic libraries. + * + * @author Adam Murdoch + */ +public interface Linker extends Processor { + /** + * Extracts the significant part of a library name to ensure there aren't + * collisions + */ + String getLibraryKey(File libname); + /** + * returns the library path for the linker + */ + File[] getLibraryPath(); + /** + * Returns a set of filename patterns corresponding to library names. + * + * For example, "advapi32" would be expanded to "advapi32.dll" by + * DevStudioLinker and to "libadvapi32.a" and "libadvapi32.so" by + * GccLinker. + * + * @param libnames + * array of library names + */ + String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libraryType); + /** + * Gets the linker for the specified link type. + * + * @return appropriate linker or null, will return this if this linker can + * handle the specified link type + */ + Linker getLinker(LinkType linkType); + /** + * Returns true if the linker is case-sensitive + */ + boolean isCaseSensitive(); +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/LinkerConfiguration.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/LinkerConfiguration.java new file mode 100644 index 0000000000..c2d62c4137 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/LinkerConfiguration.java @@ -0,0 +1,31 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.TargetInfo; + +import org.apache.tools.ant.BuildException; +/** + * A configuration for a linker + * + * @author Curt Arnold + */ +public interface LinkerConfiguration extends ProcessorConfiguration { + public LinkerParam getParam(String name); + void link(CCTask task, TargetInfo linkTarget) throws BuildException; +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCCompiler.java new file mode 100644 index 0000000000..eb64119299 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCCompiler.java @@ -0,0 +1,43 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; + +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.types.Environment; +/** + * A command line C compiler that can utilize precompilation of header files + * + * @author Curt Arnold + */ +public abstract class PrecompilingCommandLineCCompiler + extends + PrecompilingCommandLineCompiler { + protected PrecompilingCommandLineCCompiler(String command, + String identifierArg, String[] sourceExtensions, + String[] headerExtensions, String outputSuffix, boolean libtool, + PrecompilingCommandLineCCompiler libtoolCompiler, + boolean newEnvironment, Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + outputSuffix, libtool, libtoolCompiler, newEnvironment, env); + } + protected Parser createParser(File source) { + return new CParser(); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCompiler.java new file mode 100644 index 0000000000..6e3c145675 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/PrecompilingCommandLineCompiler.java @@ -0,0 +1,104 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; + +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +/** + * A command line C compiler that can utilize precompilation of header files + * + * @author Curt Arnold + */ +public abstract class PrecompilingCommandLineCompiler + extends + CommandLineCompiler implements PrecompilingCompiler { + protected PrecompilingCommandLineCompiler(String command, + String identifierArg, String[] sourceExtensions, + String[] headerExtensions, String outputSuffix, boolean libtool, + PrecompilingCommandLineCompiler libtoolCompiler, + boolean newEnvironment, Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + outputSuffix, libtool, libtoolCompiler, newEnvironment, env); + } + /** + * + * This method may be used to get two distinct compiler configurations, one + * for compiling the specified file and producing a precompiled header + * file, and a second for compiling other files using the precompiled + * header file. + * + * The last (preferrably only) include directive in the prototype file will + * be used to mark the boundary between pre-compiled and normally compiled + * headers. + * + * @param config + * base configuration + * @param prototype + * A source file (for example, stdafx.cpp) that is used to build + * the precompiled header file. @returns null if precompiled + * headers are not supported or a two element array containing + * the precompiled header generation configuration and the + * consuming configuration + * + */ + public CompilerConfiguration[] createPrecompileConfigurations( + CompilerConfiguration config, File prototype, String[] exceptFiles) { + // + // cast should success or someone is passing us a configuration + // that was prepared by another processor + // + CommandLineCompilerConfiguration cmdLineConfig = (CommandLineCompilerConfiguration) config; + // + // parse prototype file to determine last header + // + Parser parser = createParser(prototype); + String[] includes; + try { + Reader reader = new BufferedReader(new FileReader(prototype)); + parser.parse(reader); + includes = parser.getIncludes(); + } catch (IOException ex) { + throw new BuildException( + "Error parsing precompiled header protoype: " + + prototype.toString() + ":" + ex.toString()); + } + if (includes.length == 0) { + throw new BuildException("Precompiled header prototype: " + + prototype.toString() + + " does not contain any include directives."); + } + CompilerConfiguration[] configs = new CompilerConfiguration[2]; + configs[0] = createPrecompileGeneratingConfig(cmdLineConfig, prototype, + includes[0]); + configs[1] = createPrecompileUsingConfig(cmdLineConfig, prototype, + includes[0], exceptFiles); + return configs; + } + abstract protected CompilerConfiguration createPrecompileGeneratingConfig( + CommandLineCompilerConfiguration baseConfig, File prototype, + String lastInclude); + abstract protected CompilerConfiguration createPrecompileUsingConfig( + CommandLineCompilerConfiguration baseConfig, File prototype, + String lastInclude, String[] exceptFiles); +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/PrecompilingCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/PrecompilingCompiler.java new file mode 100644 index 0000000000..e60b1da8e6 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/PrecompilingCompiler.java @@ -0,0 +1,49 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import java.io.File; +/** + * A compiler that can utilize precompilation of header files + * + * @author Curt Arnold + */ +public interface PrecompilingCompiler { + /** + * + * This method may be used to get two distinct compiler configurations, one + * for compiling the specified file and producing a precompiled header + * file, and a second for compiling other files using the precompiled + * header file. + * + * The last (preferrably only) include directive in the prototype file will + * be used to mark the boundary between pre-compiled and normally compiled + * headers. + * + * @param config + * base configuration + * @param prototype + * A source file (for example, stdafx.cpp) that is used to build + * the precompiled header file. @returns null if precompiled + * headers are not supported or a two element array containing + * the precompiled header generation configuration and the + * consuming configuration + * + */ + CompilerConfiguration[] createPrecompileConfigurations( + CompilerConfiguration config, File prototype, + String[] nonPrecompiledFiles); +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Processor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Processor.java new file mode 100644 index 0000000000..6fb74e9ea3 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/Processor.java @@ -0,0 +1,73 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.TargetDef; +import org.apache.tools.ant.types.Environment; +/** + * A processor. Base interface for Compiler and Linker + * + * @author Curt Arnold + */ +public interface Processor { + /** + * Returns a bid indicating the desire of this compiler to process the + * file. + * + * @param inputFile + * input file + * @return 0 = no interest, 100 = high interest + */ + int bid(String inputFile); + Processor changeEnvironment(boolean newEnvironment, Environment env); + /** + * Returns the compiler configuration for or element. + * + * @param defaultProviders + * When specificConfig corresponds to a or linker + * element, defaultProvider will be a zero to two element array. + * If there is an extends attribute, the first element will be + * the referenced ProcessorDef, unless inherit = false, the last + * element will be the containing element + * @param specificConfig + * A or element. + * @return resulting configuration + */ + ProcessorConfiguration createConfiguration(CCTask task, LinkType linkType, + ProcessorDef[] defaultProviders, ProcessorDef specificConfig, + TargetDef targetPlatform); + /** + * Retrieve an identifier that identifies the specific version of the + * compiler. Compilers with the same identifier should produce the same + * output files for the same input files and command line switches. + */ + String getIdentifier(); + /** + * Gets the linker that is associated with this processors + */ + Linker getLinker(LinkType type); + /** + * Output file name (no path components) corresponding to source file + * + * @param inputFile + * input file + * @return output file name or null if no output file or name not + * determined by input file + */ + String getOutputFileName(String inputFile); +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/ProcessorConfiguration.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/ProcessorConfiguration.java new file mode 100644 index 0000000000..dd75483d6d --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/ProcessorConfiguration.java @@ -0,0 +1,52 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +import net.sf.antcontrib.cpptasks.ProcessorParam; +/** + * A configuration for a C++ compiler, linker or other processor + * + * @author Curt Arnold + */ +public interface ProcessorConfiguration { + /** + * An indication of how much this compiler would like to process this file + * + * @return 0 is no interest to process, 100 is strong interest to process + */ + int bid(String filename); + /** + * Returns a string representation of this configuration. Should be + * canonical so that equivalent configurations will have equivalent string + * representations + */ + String getIdentifier(); + /** + * Output file name (no path components) corresponding to source file + * + * @param inputFile + * input file + * @return output file name or null if no output file or name not + * determined by input file + */ + String getOutputFileName(String inputFile); + ProcessorParam[] getParams(); + /** + * If true, all files using this configuration should be rebuilt and any + * existing output files should be ignored + */ + boolean getRebuild(); +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/ProgressMonitor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/ProgressMonitor.java new file mode 100644 index 0000000000..2206ed874e --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/compiler/ProgressMonitor.java @@ -0,0 +1,31 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.compiler; +/** + * Interface to receive notification of compile progress + * + * @author Curt Arnold + */ +public interface ProgressMonitor { + public void finish(ProcessorConfiguration config, boolean normal); + /** + * Called to notify monitor of progress + * + */ + void progress(String[] sources); + public void start(ProcessorConfiguration config); +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioAslcompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioAslcompiler.java new file mode 100644 index 0000000000..f0be5945a3 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioAslcompiler.java @@ -0,0 +1,70 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; + +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineAslcompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; + +/** + * Adaptor for Microsoft ASL compiler. + * + */ +public final class DevStudioAslcompiler extends CommandLineAslcompiler { + private final static String[] sourceExtensions = new String[] { ".asl" }; + + private final static String[] headerExtensions = new String[] {}; + + private final static String[] defaultflags = new String[] {}; + + private static final DevStudioAslcompiler instance = new DevStudioAslcompiler( + "asl", sourceExtensions, headerExtensions, false); + + /** + * Gets asl adapter + */ + public static DevStudioAslcompiler getInstance() { + return instance; + } + + /** + * Private constructor. Use DevStudioAslcompiler.getInstance() to get + * singleton instance of this class. + */ + private DevStudioAslcompiler (String command, String[] sourceExtensions, + String[] headerExtensions, boolean isLibtool) { + super(command, null, sourceExtensions, headerExtensions, ".aml"); + } + + public void addImpliedArgs(Vector args, boolean debug, Boolean defaultflag) { + if (defaultflag != null && defaultflag.booleanValue()) { + for (int i = 0; i < defaultflags.length; i++) { + args.addElement(defaultflags[i]); + } + } + } + + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + + public Linker getLinker(LinkType linkType) { + return DevStudioLinker.getInstance().getLinker(linkType); + } +} \ No newline at end of file diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioAssembler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioAssembler.java new file mode 100644 index 0000000000..23d319ecd9 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioAssembler.java @@ -0,0 +1,84 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; + +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineAssembler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; + +/** + * Adaptor for Microsoft MASM + * + */ +public final class DevStudioAssembler extends CommandLineAssembler { + private final static String[] sourceExtensions = new String[] { ".asm" }; + + private final static String[] headerExtensions = new String[] { ".h", + ".inc" }; + + private final static String[] defaultflags = new String[] { "/nologo", "/c" }; + + private static final DevStudioAssembler instance = new DevStudioAssembler( + "ml", sourceExtensions, headerExtensions, false); + + /** + * Gets masm adapter + */ + public static DevStudioAssembler getInstance() { + return instance; + } + + /** + * Private constructor. Use DevStudioAssembler.getInstance() to get + * singleton instance of this class. + */ + private DevStudioAssembler (String command, String[] sourceExtensions, + String[] headerExtensions, boolean isLibtool) { + super(command, null, sourceExtensions, headerExtensions, ".obj"); + } + + public void addImpliedArgs(Vector args, boolean debug, Boolean defaultflag) { + if (defaultflag != null && defaultflag.booleanValue()) { + for (int i = 0; i < defaultflags.length; i++) { + args.addElement(defaultflags[i]); + } + } + if (debug) { + args.addElement("Zi"); + } + } + + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + + public Linker getLinker(LinkType linkType) { + return DevStudioLinker.getInstance().getLinker(linkType); + } + + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ";"); + } + + protected String getIncludeDirSwitch(String includeDir) { + return "/I" + includeDir.replace('/', '\\'); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCCompiler.java new file mode 100644 index 0000000000..3bb5181250 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCCompiler.java @@ -0,0 +1,50 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the Microsoft(r) C/C++ Optimizing Compiler + * + * @author Adam Murdoch + */ +public final class DevStudioCCompiler extends DevStudioCompatibleCCompiler { + private static final DevStudioCCompiler instance = new DevStudioCCompiler( + "cl", false, null); + public static DevStudioCCompiler getInstance() { + return instance; + } + private DevStudioCCompiler(String command, boolean newEnvironment, + Environment env) { + super(command, "/bogus", newEnvironment, env); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new DevStudioCCompiler(getCommand(), newEnvironment, env); + } + return this; + } + public Linker getLinker(LinkType type) { + return DevStudioLinker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 4096; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java new file mode 100644 index 0000000000..5e29a323c7 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleCCompiler.java @@ -0,0 +1,136 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.CompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.PrecompilingCommandLineCCompiler; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * An abstract base class for compilers that are basically command line + * compatible with Microsoft(r) C/C++ Optimizing Compiler + * + * @author Curt Arnold + */ +public abstract class DevStudioCompatibleCCompiler + extends + PrecompilingCommandLineCCompiler { + private static String[] mflags = new String[]{ + // + // first four are single-threaded + // (runtime=static,debug=false), (..,debug=true), + // (runtime=dynamic,debug=true), (..,debug=false), (not supported) + // next four are multi-threaded, same sequence + "/ML", "/MLd", null, null, "/MT", "/MTd", "/MD", "/MDd"}; + private static String[] defaultflags = new String[]{"/nologo", "/c"}; + protected DevStudioCompatibleCCompiler(String command, + String identifierArg, boolean newEnvironment, Environment env) { + super(command, identifierArg, new String[]{".c", ".cc", ".cpp", ".cxx", + ".c++"}, new String[]{".h", ".hpp", ".inl"}, ".obj", false, + null, newEnvironment, env); + } + protected void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + if (defaultflag != null && defaultflag.booleanValue()) { + for (int i = 0; i < defaultflags.length; i++) { + args.addElement(defaultflags[i]); + } + } + if (exceptions) { + args.addElement("/GX"); + } + int mindex = 0; + if (multithreaded) { + mindex += 4; + } + boolean staticRuntime = linkType.isStaticRuntime(); + if (!staticRuntime) { + mindex += 2; + } + if (debug) { + mindex += 1; + args.addElement("/Zi"); + args.addElement("/Od"); + args.addElement("/GZ"); + args.addElement("/D_DEBUG"); + } else { + if (optimization != null) { + if (optimization.isSize()) { + args.addElement("/O1"); + } + if (optimization.isSpeed()) { + args.addElement("/O2"); + } + } + args.addElement("/DNDEBUG"); + } + String mflag = mflags[mindex]; + if (mflag == null) { + throw new BuildException( + "multithread='false' and runtime='dynamic' not supported"); + } + args.addElement(mflag); + if (rtti != null && rtti.booleanValue()) { + args.addElement("/GR"); + } + } + protected void addWarningSwitch(Vector args, int level) { + DevStudioProcessor.addWarningSwitch(args, level); + } + protected CompilerConfiguration createPrecompileGeneratingConfig( + CommandLineCompilerConfiguration baseConfig, File prototype, + String lastInclude) { + String[] additionalArgs = new String[]{ + "/Fp" + CUtil.getBasename(prototype) + ".pch", "/Yc"}; + return new CommandLineCompilerConfiguration(baseConfig, additionalArgs, + null, true); + } + protected CompilerConfiguration createPrecompileUsingConfig( + CommandLineCompilerConfiguration baseConfig, File prototype, + String lastInclude, String[] exceptFiles) { + String[] additionalArgs = new String[]{ + "/Fp" + CUtil.getBasename(prototype) + ".pch", + "/Yu" + lastInclude}; + return new CommandLineCompilerConfiguration(baseConfig, additionalArgs, + exceptFiles, false); + } + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + DevStudioProcessor.getDefineSwitch(buffer, define, value); + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ";"); + } + protected String getIncludeDirSwitch(String includeDir) { + return DevStudioProcessor.getIncludeDirSwitch(includeDir); + } + protected void getUndefineSwitch(StringBuffer buffer, String define) { + DevStudioProcessor.getUndefineSwitch(buffer, define); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLibrarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLibrarian.java new file mode 100644 index 0000000000..40bef6e239 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLibrarian.java @@ -0,0 +1,86 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; +/** + * Abstract base adapter for librarians with command line options compatible + * with the Microsoft(r) Library Manager + * + * @author Curt Arnold + */ +public abstract class DevStudioCompatibleLibrarian extends CommandLineLinker { + private static String[] defaultflags = new String[]{"/nologo"}; + public DevStudioCompatibleLibrarian(String command, String identifierArg) { + super(command, identifierArg, new String[]{".obj"}, new String[0], + ".lib", false, null); + } + protected void addBase(long base, Vector args) { + } + protected void addFixed(Boolean fixed, Vector args) { + } + protected void addImpliedArgs(boolean debug, LinkType linkType, + Vector args, Boolean defaultflag) { + if(defaultflag != null && defaultflag.booleanValue()){ + for (int i = 0; i < defaultflags.length; i++) { + args.addElement(defaultflags[i]); + } + } + } + protected void addIncremental(boolean incremental, Vector args) { + } + protected void addMap(boolean map, Vector args) { + } + protected void addStack(int stack, Vector args) { + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + protected String getCommandFileSwitch(String cmdFile) { + return "@" + cmdFile; + } + public File[] getLibraryPath() { + return new File[0]; + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + return new String[0]; + } + public int getMaximumCommandLength() { + return 4096; + } + public String[] getOutputFileSwitch(String outFile) { + StringBuffer buf = new StringBuffer("/OUT:"); + if (outFile.indexOf(' ') >= 0) { + buf.append('"'); + buf.append(outFile); + buf.append('"'); + } else { + buf.append(outFile); + } + return new String[]{buf.toString()}; + } + public boolean isCaseSensitive() { + return false; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java new file mode 100644 index 0000000000..9e156b0426 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioCompatibleLinker.java @@ -0,0 +1,127 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; +/** + * Abstract base class for linkers that try to mimic the command line arguments + * for the Microsoft (r) Incremental Linker + * + * @author Curt Arnold + */ +public abstract class DevStudioCompatibleLinker extends CommandLineLinker { + private static String[] defaultflags = new String[]{"/NOLOGO"}; + public DevStudioCompatibleLinker(String command, String identifierArg, + String outputSuffix) { + super(command, identifierArg, new String[]{".obj", ".lib", ".res"}, + new String[]{".map", ".pdb", ".lnk", ".dll"}, outputSuffix, + false, null); + } + protected void addBase(long base, Vector args) { + if (base >= 0) { + String baseAddr = Long.toHexString(base); + args.addElement("/BASE:0x" + baseAddr); + } + } + protected void addFixed(Boolean fixed, Vector args) { + if (fixed != null) { + if (fixed.booleanValue()) { + args.addElement("/FIXED"); + } else { + args.addElement("/FIXED:NO"); + } + } + } + protected void addImpliedArgs(boolean debug, LinkType linkType, + Vector args, Boolean defaultflag) { + if(defaultflag != null && defaultflag.booleanValue()){ + for (int i = 0; i < defaultflags.length; i++) { + args.addElement(defaultflags[i]); + } + } + if (debug) { + args.addElement("/DEBUG"); + } + if (linkType.isSharedLibrary()) { + args.addElement("/DLL"); + } + /* + * if(linkType.isSubsystemGUI()) { + * args.addElement("/SUBSYSTEM:WINDOWS"); } else { + * if(linkType.isSubsystemConsole()) { + * args.addElement("/SUBSYSTEM:CONSOLE"); } } + */ + } + protected void addIncremental(boolean incremental, Vector args) { + if (incremental) { + args.addElement("/INCREMENTAL:YES"); + } else { + args.addElement("/INCREMENTAL:NO"); + } + } + protected void addMap(boolean map, Vector args) { + if (map) { + args.addElement("/MAP"); + } + } + protected void addStack(int stack, Vector args) { + if (stack >= 0) { + String stackStr = Integer.toHexString(stack); + args.addElement("/STACK:0x" + stackStr); + } + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + if (entry != null) { + args.addElement("/ENTRY:" + entry); + } + } + + public String getCommandFileSwitch(String commandFile) { + return "@" + commandFile; + } + public File[] getLibraryPath() { + return CUtil.getPathFromEnvironment("LIB", ";"); + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + StringBuffer buf = new StringBuffer(); + String[] patterns = new String[libnames.length]; + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(libnames[i]); + buf.append(".lib"); + patterns[i] = buf.toString(); + } + return patterns; + } + public int getMaximumCommandLength() { + return 4096; + } + public String[] getOutputFileSwitch(String outputFile) { + return new String[]{"/OUT:" + outputFile}; + } + public boolean isCaseSensitive() { + return false; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioLibrarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioLibrarian.java new file mode 100644 index 0000000000..06eac71e19 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioLibrarian.java @@ -0,0 +1,36 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +/** + * Adapter for the Microsoft (r) Library Manager + * + * @author Curt Arnold + */ +public final class DevStudioLibrarian extends DevStudioCompatibleLibrarian { + private static final DevStudioLibrarian instance = new DevStudioLibrarian(); + public static DevStudioLibrarian getInstance() { + return instance; + } + private DevStudioLibrarian() { + super("lib", "/bogus"); + } + public Linker getLinker(LinkType type) { + return DevStudioLinker.getInstance().getLinker(type); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioLinker.java new file mode 100644 index 0000000000..7ae0178a8b --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioLinker.java @@ -0,0 +1,44 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +/** + * Adapter for the Microsoft (r) Incremental Linker + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public final class DevStudioLinker extends DevStudioCompatibleLinker { + private static final DevStudioLinker dllLinker = new DevStudioLinker(".dll"); + private static final DevStudioLinker instance = new DevStudioLinker(".exe"); + public static DevStudioLinker getInstance() { + return instance; + } + private DevStudioLinker(String outputSuffix) { + super("link", "/DLL", outputSuffix); + } + public Linker getLinker(LinkType type) { + if (type.isSharedLibrary()) { + return dllLinker; + } + if (type.isStaticLibrary()) { + return DevStudioLibrarian.getInstance(); + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioMIDLCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioMIDLCompiler.java new file mode 100644 index 0000000000..7df898b92f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioMIDLCompiler.java @@ -0,0 +1,113 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.Parser; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * Adapter for the Microsoft (r) MIDL Compiler + * + * @author Curt Arnold + */ +public final class DevStudioMIDLCompiler extends CommandLineCompiler { + private static final DevStudioMIDLCompiler instance = new DevStudioMIDLCompiler( + false, null); + public static DevStudioMIDLCompiler getInstance() { + return instance; + } + private DevStudioMIDLCompiler(boolean newEnvironment, Environment env) { + super("midl", null, new String[]{".idl", ".odl"}, new String[]{}, + ".tlb", false, null, newEnvironment, env); + } + protected void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + } + protected void addWarningSwitch(Vector args, int level) { + DevStudioProcessor.addWarningSwitch(args, level); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new DevStudioMIDLCompiler(newEnvironment, env); + } + return this; + } + /** + * The include parser for C will work just fine, but we didn't want to + * inherit from CommandLineCCompiler + */ + protected Parser createParser(File source) { + return new CParser(); + } + protected int getArgumentCountPerInputFile() { + return 3; + } + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + DevStudioProcessor.getDefineSwitch(buffer, define, value); + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ";"); + } + protected String getIncludeDirSwitch(String includeDir) { + return DevStudioProcessor.getIncludeDirSwitch(includeDir); + } + protected String getInputFileArgument(File outputDir, String filename, + int index) { + switch (index) { + case 0 : + return "/tlb"; + case 1 : + return new File(outputDir, getOutputFileName(filename)) + .getAbsolutePath(); + } + return filename; + } + public Linker getLinker(LinkType type) { + return DevStudioLinker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 1024; + } + protected int getMaximumInputFilesPerCommand() { + return 1; + } + protected int getTotalArgumentLengthForInputFile(File outputDir, + String inputFile) { + String arg1 = getInputFileArgument(outputDir, inputFile, 0); + String arg2 = getInputFileArgument(outputDir, inputFile, 1); + String arg3 = getInputFileArgument(outputDir, inputFile, 2); + return arg1.length() + arg2.length() + arg3.length() + 3; + } + protected void getUndefineSwitch(StringBuffer buffer, String define) { + DevStudioProcessor.getUndefineSwitch(buffer, define); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioProcessor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioProcessor.java new file mode 100644 index 0000000000..6b2af7ed54 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioProcessor.java @@ -0,0 +1,90 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.util.Vector; +/** + * A add-in class for Microsoft Developer Studio processors + * + * + */ +public class DevStudioProcessor { + public static void addWarningSwitch(Vector args, int level) { + switch (level) { + case 0 : + args.addElement("/W0"); + break; + case 1 : + args.addElement("/W1"); + break; + case 2 : + break; + case 3 : + args.addElement("/W3"); + break; + case 4 : + args.addElement("/W4"); + break; + case 5 : + args.addElement("/WX"); + break; + } + } + public static String getCommandFileSwitch(String cmdFile) { + StringBuffer buf = new StringBuffer("@"); + if (cmdFile.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(cmdFile.replace('/', '\\')); + buf.append('\"'); + } else { + buf.append(cmdFile); + } + return buf.toString(); + } + public static void getDefineSwitch(StringBuffer buffer, String define, + String value) { + buffer.append("/D"); + buffer.append(define); + if (value != null && value.length() > 0) { + buffer.append('='); + buffer.append(value); + } + } + public static String getIncludeDirSwitch(String includeDir) { + return "/I" + includeDir.replace('/', '\\'); + } + public static String[] getOutputFileSwitch(String outPath) { + StringBuffer buf = new StringBuffer("/Fo"); + if (outPath.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(outPath); + buf.append('\"'); + } else { + buf.append(outPath); + } + String[] retval = new String[]{buf.toString()}; + return retval; + } + public static void getUndefineSwitch(StringBuffer buffer, String define) { + buffer.append("/U"); + buffer.append(define); + } + public static boolean isCaseSensitive() { + return false; + } + private DevStudioProcessor() { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioResourceCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioResourceCompiler.java new file mode 100644 index 0000000000..d6e2fd4442 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/devstudio/DevStudioResourceCompiler.java @@ -0,0 +1,117 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.devstudio; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.Parser; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the Microsoft (r) Windows 32 Resource Compiler + * + * @author Curt Arnold + */ +public final class DevStudioResourceCompiler extends CommandLineCompiler { + private static final DevStudioResourceCompiler instance = new DevStudioResourceCompiler( + false, null); + public static DevStudioResourceCompiler getInstance() { + return instance; + } + private String identifier; + private DevStudioResourceCompiler(boolean newEnvironment, Environment env) { + super("rc", null, new String[]{".rc"}, new String[]{".h", ".hpp", + ".inl"}, ".res", false, null, newEnvironment, env); + } + protected void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + if (debug) { + args.addElement("/D_DEBUG"); + } else { + args.addElement("/DNDEBUG"); + } + } + protected void addWarningSwitch(Vector args, int level) { + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new DevStudioResourceCompiler(newEnvironment, env); + } + return this; + } + /** + * The include parser for C will work just fine, but we didn't want to + * inherit from CommandLineCCompiler + */ + protected Parser createParser(File source) { + return new CParser(); + } + protected int getArgumentCountPerInputFile() { + return 2; + } + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + DevStudioProcessor.getDefineSwitch(buffer, define, value); + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ";"); + } + protected String getIncludeDirSwitch(String includeDir) { + return DevStudioProcessor.getIncludeDirSwitch(includeDir); + } + protected String getInputFileArgument(File outputDir, String filename, + int index) { + if (index == 0) { + String outputFileName = getOutputFileName(filename); + String fullOutputName = new File(outputDir, outputFileName) + .toString(); + return "/fo" + fullOutputName; + } + return filename; + } + public Linker getLinker(LinkType type) { + return DevStudioLinker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 1024; + } + protected int getMaximumInputFilesPerCommand() { + return 1; + } + protected int getTotalArgumentLengthForInputFile(File outputDir, + String inputFile) { + String arg1 = getInputFileArgument(outputDir, inputFile, 0); + String arg2 = getInputFileArgument(outputDir, inputFile, 1); + return arg1.length() + arg2.length() + 2; + } + protected void getUndefineSwitch(StringBuffer buffer, String define) { + DevStudioProcessor.getUndefineSwitch(buffer, define); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/AbstractArLibrarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/AbstractArLibrarian.java new file mode 100644 index 0000000000..f7bb2eab95 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/AbstractArLibrarian.java @@ -0,0 +1,106 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +import org.apache.tools.ant.BuildException; +/** + * Adapter for the "ar" tool + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public abstract class AbstractArLibrarian extends CommandLineLinker { + private/* final */ + String outputPrefix; + private static String[] defaultflags = new String[]{}; + protected AbstractArLibrarian(String command, String identificationArg, + String[] inputExtensions, String[] ignoredExtensions, + String outputPrefix, String outputExtension, boolean isLibtool, + AbstractArLibrarian libtoolLibrarian) { + super(command, identificationArg, inputExtensions, ignoredExtensions, + outputExtension, isLibtool, libtoolLibrarian); + this.outputPrefix = outputPrefix; + } + public void addBase(long base, Vector args) { + } + public void addFixed(Boolean fixed, Vector args) { + } + public void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + if(defaultflag != null && defaultflag.booleanValue()){ + for (int i = 0; i < defaultflags.length; i++) { + args.addElement(defaultflags[i]); + } + } + } + public void addIncremental(boolean incremental, Vector args) { + } + public void addMap(boolean map, Vector args) { + } + public void addStack(int stack, Vector args) { + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + public String getCommandFileSwitch(String commandFile) { + return null; + } + public File[] getLibraryPath() { + return new File[0]; + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + return new String[0]; + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + public String getOutputFileName(String baseName) { + return outputPrefix + super.getOutputFileName(baseName); + } + public String[] getOutputFileSwitch(String outputFile) { + return GccProcessor.getOutputFileSwitch("rvs", outputFile); + } + public boolean isCaseSensitive() { + return true; + } + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + // + // if there is an existing library then + // we must delete it before executing "ar" + if (outputFile.exists()) { + if (!outputFile.delete()) { + throw new BuildException("Unable to delete " + + outputFile.getAbsolutePath()); + } + } + // + // delegate to CommandLineLinker + // + super.link(task, outputFile, sourceFiles, config); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/AbstractLdLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/AbstractLdLinker.java new file mode 100644 index 0000000000..f6e376643f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/AbstractLdLinker.java @@ -0,0 +1,323 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * Abstract adapter for ld-like linkers + * + * @author Curt Arnold + */ +public abstract class AbstractLdLinker extends CommandLineLinker { + private String outputPrefix; + private static String[] defaultflags = new String[]{}; + protected AbstractLdLinker(String command, String identifierArg, + String[] extensions, String[] ignoredExtensions, + String outputPrefix, String outputSuffix, boolean isLibtool, + AbstractLdLinker libtoolLinker) { + super(command, identifierArg, extensions, ignoredExtensions, + outputSuffix, isLibtool, libtoolLinker); + this.outputPrefix = outputPrefix; + } + public void addBase(long base, Vector args) { + if (base >= 0) { + args.addElement("--image-base"); + args.addElement(Long.toHexString(base)); + } + } + public void addFixed(Boolean fixed, Vector args) { + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + if(defaultflag != null && defaultflag.booleanValue()){ + for (int i = 0; i < defaultflags.length; i++) { + args.addElement(defaultflags[i]); + } + } + if (debug) { + args.addElement("-g"); + } + if (isDarwin()) { + if (linkType.isPluginModule()) { + args.addElement("-bundle"); + } else { + if (linkType.isSharedLibrary()) { + args.addElement("-prebind"); + args.addElement("-dynamiclib"); + } + } + } else { + if (linkType.isStaticRuntime()) { + args.addElement("-static"); + } + if (linkType.isPluginModule()) { + args.addElement("-shared"); + } else { + if (linkType.isSharedLibrary()) { + args.addElement("-shared"); + } + } + } + } + public void addIncremental(boolean incremental, Vector args) { + if (incremental) { + args.addElement("-i"); + } + } + protected int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + Vector libnames = new Vector(); + super.addLibrarySets(task, libsets, preargs, midargs, endargs); + LibraryTypeEnum previousLibraryType = null; + for (int i = 0; i < libsets.length; i++) { + LibrarySet set = libsets[i]; + File libdir = set.getDir(null); + String[] libs = set.getLibs(); + if (libdir != null) { + if (set.getType() != null && + "framework".equals(set.getType().getValue()) && + isDarwin()) { + endargs.addElement("-F" + libdir.getAbsolutePath()); + } else { + endargs.addElement("-L" + libdir.getAbsolutePath()); + } + } + // + // if there has been a change of library type + // + if (set.getType() != previousLibraryType) { + if (set.getType() != null && "static".equals(set.getType().getValue())) { + endargs.addElement("-Bstatic"); + previousLibraryType = set.getType(); + } else { + if (set.getType() == null || + !"framework".equals(set.getType().getValue()) || + !isDarwin()) { + endargs.addElement("-Bdynamic"); + previousLibraryType = set.getType(); + } + } + } + StringBuffer buf = new StringBuffer("-l"); + if (set.getType() != null && + "framework".equals(set.getType().getValue()) && + isDarwin()) { + buf.setLength(0); + buf.append("-framework "); + } + int initialLength = buf.length(); + for (int j = 0; j < libs.length; j++) { + // + // reset the buffer to just "-l" + // + buf.setLength(initialLength); + // + // add the library name + buf.append(libs[j]); + libnames.addElement(libs[j]); + // + // add the argument to the list + endargs.addElement(buf.toString()); + } + } + String rc[] = new String[libnames.size()]; + for (int i = 0; i < libnames.size(); i++) { + rc[i] = (String) libnames.elementAt(i); + } + return rc; + } + public void addMap(boolean map, Vector args) { + if (map) { + args.addElement("-M"); + } + } + public void addStack(int stack, Vector args) { + if (stack > 0) { + args.addElement("--stack"); + args.addElement(Integer.toString(stack)); + } + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + if (entry != null) { + args.addElement("-e"); + args.addElement(entry); + } + } + + public String getCommandFileSwitch(String commandFile) { + throw new IllegalStateException("ld does not support command files"); + } + /** + * Returns library path. + * + */ + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("LIB", ":"); + } + public String getLibraryKey(File libfile) { + String libname = libfile.getName(); + int lastDot = libname.lastIndexOf('.'); + if (lastDot >= 0) { + return libname.substring(0, lastDot); + } + return libname; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + return new File[0]; + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + StringBuffer buf = new StringBuffer(); + int patternCount = libnames.length; + if (libType == null) { + patternCount *= 2; + } + String[] patterns = new String[patternCount]; + int offset = 0; + if (libType == null || "static".equals(libType.getValue())) { + offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0); + } + if (libType != null && "framework".equals(libType.getValue()) && isDarwin()) { + for(int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(libnames[i]); + buf.append(".framework/"); + buf.append(libnames[i]); + patterns[offset++] = buf.toString(); + } + } else { + if (libType == null || !"static".equals(libType.getValue())) { + if (isHPUX()) { + offset = addLibraryPatterns(libnames, buf, "lib", ".sl", patterns, + offset); + } else { + offset = addLibraryPatterns(libnames, buf, "lib", ".so", patterns, + offset); + } + } + } + return patterns; + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + public String getOutputFileName(String baseName) { + return outputPrefix + super.getOutputFileName(baseName); + } + public String[] getOutputFileSwitch(String outputFile) { + return GccProcessor.getOutputFileSwitch("-o", outputFile); + } + public boolean isCaseSensitive() { + return true; + } + protected boolean isHPUX() { + String osname = System.getProperty("os.name").toLowerCase(); + if (osname.indexOf("hp") >= 0 && osname.indexOf("ux") >= 0) { + return true; + } + return false; + } + /** + * Prepares argument list for exec command. Will return null if command + * line would exceed allowable command line buffer. + * + * @param outputFile + * linker output file + * @param sourceFiles + * linker input files (.obj, .o, .res) + * @param args + * linker arguments + * @return arguments for runTask + */ + public String[] prepareArguments(CCTask task, String outputDir, + String outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) { + // + // need to suppress sources that correspond to + // library set entries since they are already + // in the argument list + String[] libnames = config.getLibraryNames(); + if (libnames == null || libnames.length == 0) { + return super.prepareArguments(task, outputDir, outputFile, + sourceFiles, config); + } + // + // + // null out any sources that correspond to library names + // + String[] localSources = (String[]) sourceFiles.clone(); + int extra = 0; + for (int i = 0; i < libnames.length; i++) { + String libname = libnames[i]; + for (int j = 0; j < localSources.length; j++) { + if (localSources[j] != null + && localSources[j].indexOf(libname) > 0 + && localSources[j].indexOf("lib") > 0) { + String filename = new File(localSources[j]).getName(); + if (filename.startsWith("lib") + && filename.substring(3).startsWith(libname)) { + String extension = filename + .substring(libname.length() + 3); + if (extension.equals(".a") || extension.equals(".so") + || extension.equals(".sl")) { + localSources[j] = null; + extra++; + } + } + } + } + } + if (extra == 0) { + return super.prepareArguments(task, outputDir, outputFile, + sourceFiles, config); + } + String[] finalSources = new String[localSources.length - extra]; + int index = 0; + for (int i = 0; i < localSources.length; i++) { + if (localSources[i] != null) { + finalSources[index++] = localSources[i]; + } + } + return super.prepareArguments(task, outputDir, outputFile, + finalSources, config); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccAssembler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccAssembler.java new file mode 100644 index 0000000000..412bffa847 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccAssembler.java @@ -0,0 +1,76 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; + +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineAssembler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; + +/** + * Adapter for gcc assemble + * + */ +public final class GccAssembler extends CommandLineAssembler { + private final static String[] sourceExtensions = new String[] { ".asm" }; + + private final static String[] headerExtensions = new String[] { ".h", + ".inc" }; + + private static final GccAssembler instance = new GccAssembler("gas", + sourceExtensions, headerExtensions, false); + + /** + * Gets gcc adapter + */ + public static GccAssembler getInstance() { + return instance; + } + + /** + * Private constructor. Use GccAssembler.getInstance() to get singleton + * instance of this class. + */ + private GccAssembler (String command, String[] sourceExtensions, + String[] headerExtensions, boolean isLibtool) { + super(command, null, sourceExtensions, headerExtensions, + isLibtool ? ".fo" : ".o"); + } + + public void addImpliedArgs(Vector args, boolean debug, Boolean defaultflag) { + + } + + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + + public Linker getLinker(LinkType linkType) { + return GccLinker.getInstance().getLinker(linkType); + } + + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ":"); + } + + protected String getIncludeDirSwitch(String includeDir) { + return "-I" + includeDir; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccCCompiler.java new file mode 100644 index 0000000000..af3b26b134 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccCCompiler.java @@ -0,0 +1,243 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.FortranParser; +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * Adapter for the GCC C/C++ compiler + * + * @author Adam Murdoch + */ +public final class GccCCompiler extends GccCompatibleCCompiler { + private final static String[] sourceExtensions = new String[]{".c", /* C */ + ".cc", /* C++ */ + ".cpp", /* C++ */ + ".cxx", /* C++ */ + ".c++", /* C++ */ + ".i", /* preprocessed C */ + ".ii", /* preprocessed C++ */ + ".f", /* FORTRAN */ + ".for", /* FORTRAN */ + ".m", /* Objective-C */ + ".mm", /* Objected-C++ */ + ".s" /* Assembly */ + }; + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + private static final GccCCompiler cppInstance = new GccCCompiler("c++", + sourceExtensions, headerExtensions, false, + new GccCCompiler("c++", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler g77Instance = new GccCCompiler("g77", + sourceExtensions, headerExtensions, false, + new GccCCompiler("g77", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler gppInstance = new GccCCompiler("g++", + sourceExtensions, headerExtensions, false, + new GccCCompiler("g++", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler instance = new GccCCompiler("gcc", + sourceExtensions, headerExtensions, false, + new GccCCompiler("gcc", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + /** + * Gets c++ adapter + */ + public static GccCCompiler getCppInstance() { + return cppInstance; + } + /** + * Gets g77 adapter + */ + public static GccCCompiler getG77Instance() { + return g77Instance; + } + /** + * Gets gpp adapter + */ + public static GccCCompiler getGppInstance() { + return gppInstance; + } + /** + * Gets gcc adapter + */ + public static GccCCompiler getInstance() { + return instance; + } + private String identifier; + private File[] includePath; + private boolean isPICMeaningful = true; + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + private GccCCompiler(String command, String[] sourceExtensions, + String[] headerExtensions, boolean isLibtool, + GccCCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(command, null, sourceExtensions, headerExtensions, isLibtool, + libtoolCompiler, newEnvironment, env); + isPICMeaningful = System.getProperty("os.name").indexOf("Windows") < 0; + } + public void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + super.addImpliedArgs(args, debug, multithreaded, + exceptions, linkType, rtti, optimization, defaultflag); + if (isPICMeaningful && linkType.isSharedLibrary()) { + args.addElement("-fPIC"); + } + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new GccCCompiler(getCommand(), this.getSourceExtensions(), + this.getHeaderExtensions(), this.getLibtool(), + (GccCCompiler) this.getLibtoolCompiler(), newEnvironment, + env); + } + return this; + } + /** + * Create parser to determine dependencies. + * + * Will create appropriate parser (C++, FORTRAN) based on file extension. + * + */ + protected Parser createParser(File source) { + if (source != null) { + String sourceName = source.getName(); + int lastDot = sourceName.lastIndexOf('.'); + if (lastDot >= 0 && lastDot + 1 < sourceName.length()) { + char afterDot = sourceName.charAt(lastDot + 1); + if (afterDot == 'f' || afterDot == 'F') { + return new FortranParser(); + } + } + } + return new CParser(); + } + public File[] getEnvironmentIncludePath() { + if (includePath == null) { + // + // construct default include path from machine id and version id + // + String[] defaultInclude = new String[1]; + StringBuffer buf = new StringBuffer("/lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + buf.append("/include"); + defaultInclude[0] = buf.toString(); + // + // read specs file and look for -istart and -idirafter + // + String[] specs = GccProcessor.getSpecs(); + String[][] optionValues = GccProcessor.parseSpecs(specs, "*cpp:", + new String[]{"-isystem ", "-idirafter "}); + // + // if no entries were found, then use a default path + // + if (optionValues[0].length == 0 && optionValues[1].length == 0) { + optionValues[0] = new String[]{"/usr/local/include", + "/usr/include", "/usr/include/win32api"}; + } + // + // remove mingw entries. + // For MinGW compiles this will mean the + // location of the sys includes will be + // wrong in dependencies.xml + // but that should have no significant effect + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j].indexOf("mingw") > 0) { + optionValues[i][j] = null; + } + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(optionValues[0]); + GccProcessor.convertCygwinFilenames(optionValues[1]); + GccProcessor.convertCygwinFilenames(defaultInclude); + } + int count = CUtil.checkDirectoryArray(optionValues[0]); + count += CUtil.checkDirectoryArray(optionValues[1]); + count += CUtil.checkDirectoryArray(defaultInclude); + includePath = new File[count]; + int index = 0; + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j] != null) { + includePath[index++] = new File(optionValues[i][j]); + } + } + } + for (int i = 0; i < defaultInclude.length; i++) { + if (defaultInclude[i] != null) { + includePath[index++] = new File(defaultInclude[i]); + } + } + } + return (File[]) includePath.clone(); + } + public String getIdentifier() throws BuildException { + if (identifier == null) { + StringBuffer buf; + if (getLibtool()) { + buf = new StringBuffer("libtool "); + } else { + buf = new StringBuffer(' '); + } + buf.append(getCommand()); + buf.append(' '); + buf.append(GccProcessor.getVersion()); + buf.append(' '); + buf.append(GccProcessor.getMachine()); + identifier = buf.toString(); + } + return identifier; + } + public Linker getLinker(LinkType linkType) { + return GccLinker.getInstance().getLinker(linkType); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccCompatibleCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccCompatibleCCompiler.java new file mode 100644 index 0000000000..98f086ed61 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccCompatibleCCompiler.java @@ -0,0 +1,152 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * Abstract base class for compilers that attempt to be command line compatible + * with GCC + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public abstract class GccCompatibleCCompiler extends CommandLineCCompiler { + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + private final static String[] sourceExtensions = new String[]{".c", ".cc", + ".cpp", ".cxx", ".c++", ".i", ".f", ".for"}; + private final static String[] defaultflags = new String[]{"-c"}; + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + protected GccCompatibleCCompiler(String command, String identifierArg, + boolean libtool, GccCompatibleCCompiler libtoolCompiler, + boolean newEnvironment, Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + libtool ? ".fo" : ".o", libtool, libtoolCompiler, + newEnvironment, env); + } + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + protected GccCompatibleCCompiler(String command, String identifierArg, + String[] sourceExtensions, String[] headerExtensions, + boolean libtool, GccCompatibleCCompiler libtoolCompiler, + boolean newEnvironment, Environment env) { + super(command, identifierArg, sourceExtensions, headerExtensions, + libtool ? ".fo" : ".o", libtool, libtoolCompiler, + newEnvironment, env); + } + public void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + // + // -fPIC is too much trouble + // users have to manually add it for + // operating systems that make sense + // + if (defaultflag != null && defaultflag.booleanValue()) { + for (int i = 0; i < defaultflags.length; i++) { + args.addElement(defaultflags[i]); + } + } + if (debug) { + args.addElement("-g"); + } else { + if (optimization != null) { + if (optimization.isSize()) { + args.addElement("-Os"); + } else if (optimization.isSpeed()) { + if ("full".equals(optimization.getValue())) { + args.addElement("-O2"); + } else { + if ("speed".equals(optimization.getValue())) { + args.addElement("-O1"); + } else { + args.addElement("-O3"); + } + } + } + } + } + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + if (rtti != null && !rtti.booleanValue()) { + args.addElement("-fno-rtti"); + } + + } + /** + * Adds an include path to the command. + */ + public void addIncludePath(String path, Vector cmd) { + cmd.addElement("-I" + path); + } + public void addWarningSwitch(Vector args, int level) { + switch (level) { + case 0 : + args.addElement("-w"); + break; + case 5 : + args.addElement("-Werror"); + /* nobreak */ + case 4 : + args.addElement("-W"); + /* nobreak */ + case 3 : + args.addElement("-Wall"); + break; + } + } + public void getDefineSwitch(StringBuffer buffer, String define, String value) { + buffer.append("-D"); + buffer.append(define); + if (value != null && value.length() > 0) { + buffer.append('='); + buffer.append(value); + } + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ":"); + } + public String getIncludeDirSwitch(String includeDir) { + return "-I" + includeDir; + } + public void getUndefineSwitch(StringBuffer buffer, String define) { + buffer.append("-U"); + buffer.append(define); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccLibrarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccLibrarian.java new file mode 100644 index 0000000000..62500021cf --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccLibrarian.java @@ -0,0 +1,41 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +/** + * Adapter for the 'ar' archiver + * + * @author Adam Murdoch + */ +public final class GccLibrarian extends AbstractArLibrarian { + private static String[] objFileExtensions = new String[]{".o"}; + private static GccLibrarian instance = new GccLibrarian("ar", + objFileExtensions, false, new GccLibrarian("ar", objFileExtensions, + true, null)); + public static GccLibrarian getInstance() { + return instance; + } + private GccLibrarian(String command, String[] inputExtensions, + boolean isLibtool, GccLibrarian libtoolLibrarian) { + super(command, "V", inputExtensions, new String[0], "lib", ".a", + isLibtool, libtoolLibrarian); + } + public Linker getLinker(LinkType type) { + return GccLinker.getInstance().getLinker(type); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccLinker.java new file mode 100644 index 0000000000..f37f55092a --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccLinker.java @@ -0,0 +1,210 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +/** + * Adapter for the GCC linker + * + * @author Adam Murdoch + */ +public class GccLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", + "-dynamiclib", "-nostartfiles", "-nostdlib", "-prebind", "-s", + "-static", "-shared", "-symbolic", "-Xlinker", + "--export-all-symbols", "-static-libgcc",}; + private static final GccLinker dllLinker = new GccLinker("gcc", objFiles, + discardFiles, "lib", ".so", false, new GccLinker("gcc", objFiles, + discardFiles, "lib", ".so", true, null)); + private static final GccLinker instance = new GccLinker("gcc", objFiles, + discardFiles, "", "", false, null); + private static final GccLinker machBundleLinker = new GccLinker("gcc", + objFiles, discardFiles, "lib", ".bundle", false, null); + private static final GccLinker machDllLinker = new GccLinker("gcc", + objFiles, discardFiles, "lib", ".dylib", false, null); + public static GccLinker getInstance() { + return instance; + } + private File[] libDirs; + protected GccLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GccLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + super.addImpliedArgs(debug, linkType, args, defaultflag); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + } + /** + * Allows drived linker to decorate linker option. Override by GccLinker to + * prepend a "-Wl," to pass option to through gcc to linker. + * + * @param buf + * buffer that may be used and abused in the decoration process, + * must not be null. + * @param arg + * linker argument + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + case 'v' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + // + // construct gcc lib path from machine and version + // + StringBuffer buf = new StringBuffer("/lib/gcc-lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + // + // build default path from gcc and system /lib and /lib/w32api + // + String[] impliedLibPath = new String[]{buf.toString(), + "/lib/w32api", "/lib"}; + // + // read gcc specs file for other library paths + // + String[] specs = GccProcessor.getSpecs(); + String[][] libpaths = GccProcessor.parseSpecs(specs, "*link:", + new String[]{"%q"}); + String[] libpath; + if (libpaths[0].length > 0) { + libpath = new String[libpaths[0].length + 3]; + int i = 0; + for (; i < libpaths[0].length; i++) { + libpath[i] = libpaths[0][i]; + } + libpath[i++] = buf.toString(); + libpath[i++] = "/lib/w32api"; + libpath[i++] = "/lib"; + } else { + // + // if a failure to find any matches then + // use some default values for lib path entries + libpath = new String[]{"/usr/local/lib/mingw", + "/usr/local/lib", "/usr/lib/w32api", "/usr/lib/mingw", + "/usr/lib", buf.toString(), "/lib/w32api", "/lib"}; + } + for (int i = 0; i < libpath.length; i++) { + if (libpath[i].indexOf("mingw") >= 0) { + libpath[i] = null; + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(libpath); + } + // + // check that remaining entries are actual directories + // + int count = CUtil.checkDirectoryArray(libpath); + // + // populate return array with remaining entries + // + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; i++) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (isDarwin()) { + return machBundleLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (isDarwin()) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java new file mode 100644 index 0000000000..236969f5e7 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GccProcessor.java @@ -0,0 +1,299 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; +/** + * A add-in class for Gcc processors + * + * + */ +public class GccProcessor { + // the results from gcc -dumpmachine + private static String machine; + private static String[] specs; + // the results from gcc -dumpversion + private static String version; + private static int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + /** + * Converts absolute Cygwin file or directory names to the corresponding + * Win32 name. + * + * @param names + * array of names, some elements may be null, will be changed in + * place. + */ + public static void convertCygwinFilenames(String[] names) { + if (names == null) { + throw new NullPointerException("names"); + } + File gccDir = CUtil.getExecutableLocation("gcc.exe"); + if (gccDir != null) { + String prefix = gccDir.getAbsolutePath() + "/.."; + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + if (name != null && name.length() > 1 && name.charAt(0) == '/') { + buf.setLength(0); + buf.append(prefix); + buf.append(name); + names[i] = buf.toString(); + } + } + } + } + public static String[] getLibraryPatterns(String[] libnames) { + StringBuffer buf = new StringBuffer(); + String[] patterns = new String[libnames.length * 2]; + int offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0); + if (isHPUX()) { + offset = addLibraryPatterns(libnames, buf, "lib", ".sl", patterns, + offset); + } else { + offset = addLibraryPatterns(libnames, buf, "lib", ".so", patterns, + offset); + } + return patterns; + } + public static String getMachine() { + if (machine == null) { + String[] args = new String[]{"gcc", "-dumpmachine"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + machine = "nomachine"; + } else { + machine = cmdout[0]; + } + } + return machine; + } + public static String[] getOutputFileSwitch(String letter, String outputFile) { + StringBuffer buf = new StringBuffer(); + if (outputFile.indexOf(' ') >= 0) { + buf.append('"'); + buf.append(outputFile.replace('\\', '/')); + buf.append('"'); + } else { + buf.append(outputFile.replace('\\', '/')); + } + String[] retval = new String[]{letter, buf.toString()}; + return retval; + } + /** + * Returns the contents of the gcc specs file. + * + * The implementation locates gcc.exe in the executable path and then + * builds a relative path name from the results of -dumpmachine and + * -dumpversion. Attempts to use gcc -dumpspecs to provide this information + * resulted in stalling on the Execute.run + * + * @returns contents of the specs file + */ + public static String[] getSpecs() { + if (specs == null) { + File gccParent = CUtil.getExecutableLocation("gcc.exe"); + if (gccParent != null) { + // + // build a relative path like + // ../lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs + // + StringBuffer buf = new StringBuffer("../lib/gcc-lib/"); + buf.append(getMachine()); + buf.append('/'); + buf.append(getVersion()); + buf.append("/specs"); + // + // resolve it relative to the location of gcc.exe + // + String relativePath = buf.toString(); + File specsFile = new File(gccParent, relativePath); + // + // found the specs file + // + try { + // + // read the lines in the file + // + BufferedReader reader = new BufferedReader(new FileReader( + specsFile)); + Vector lines = new Vector(100); + String line = reader.readLine(); + while (line != null) { + lines.addElement(line); + line = reader.readLine(); + } + specs = new String[lines.size()]; + lines.copyInto(specs); + } catch (IOException ex) { + } + } + } + if (specs == null) { + specs = new String[0]; + } + return specs; + } + public static String getVersion() { + if (version == null) { + String[] args = new String[]{"gcc", "-dumpversion"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + version = "noversion"; + } else { + version = cmdout[0]; + } + } + return version; + } + public static boolean isCaseSensitive() { + return true; + } + /** + * Determines if task is running with cygwin + * + * @return true if cygwin was detected + */ + public static boolean isCygwin() { + return getMachine().indexOf("cygwin") > 0; + } + private static boolean isHPUX() { + String osname = System.getProperty("os.name").toLowerCase(); + if (osname.indexOf("hp") >= 0 && osname.indexOf("ux") >= 0) { + return true; + } + return false; + } + /** + * + * Parses the results of the specs file for a specific processor and + * options + * + * @param specsContent + * Contents of specs file as returned from getSpecs + * @param specSectionStart + * start of spec section, for example "*cpp:" + * @param options + * command line switches such as "-istart" + */ + public static String[][] parseSpecs(String[] specsContent, + String specSectionStart, String[] options) { + if (specsContent == null) { + throw new NullPointerException("specsContent"); + } + if (specSectionStart == null) { + throw new NullPointerException("specSectionStart"); + } + if (options == null) { + throw new NullPointerException("option"); + } + String[][] optionValues = new String[options.length][]; + StringBuffer optionValue = new StringBuffer(40); + for (int i = 0; i < specsContent.length; i++) { + String specLine = specsContent[i]; + // + // if start of section then start paying attention + // + if (specLine.startsWith(specSectionStart)) { + Vector[] optionVectors = new Vector[options.length]; + for (int j = 0; j < options.length; j++) { + optionVectors[j] = new Vector(10); + } + // + // go to next line and examine contents + // and repeat until end of file + // + for (i++; i < specsContent.length; i++) { + specLine = specsContent[i]; + for (int j = 0; j < options.length; j++) { + int optionStart = specLine.indexOf(options[j]); + while (optionStart >= 0) { + optionValue.setLength(0); + // + // walk rest of line looking for first non + // whitespace + // and then next space + boolean hasNonBlank = false; + int k = optionStart + options[j].length(); + for (; k < specLine.length(); k++) { + // + // either a blank or a "}" (close of + // conditional) + // section will end the path + // + if (specLine.charAt(k) == ' ' + || specLine.charAt(k) == '}') { + if (hasNonBlank) { + break; + } + } else { + hasNonBlank = true; + optionValue.append(specLine.charAt(k)); + } + } + // + // transition back to whitespace + // value is over, add it to vector + if (hasNonBlank) { + optionVectors[j].addElement(optionValue + .toString()); + } + // + // find next occurance on line + // + optionStart = specLine.indexOf(options[j], k); + } + } + } + // + // copy vectors over to option arrays + // + for (int j = 0; j < options.length; j++) { + optionValues[j] = new String[optionVectors[j].size()]; + optionVectors[j].copyInto(optionValues[j]); + } + } + } + // + // fill in any missing option values with + // a zero-length string array + for (int i = 0; i < optionValues.length; i++) { + String[] zeroLenArray = new String[0]; + if (optionValues[i] == null) { + optionValues[i] = zeroLenArray; + } + } + return optionValues; + } + private GccProcessor() { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GppLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GppLinker.java new file mode 100644 index 0000000000..e7036abe16 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/GppLinker.java @@ -0,0 +1,203 @@ +/* + * + * Copyright 2003-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +/** + * Adapter for the g++ variant of the GCC linker + * + * @author Stephen M. Webb + */ +public class GppLinker extends AbstractLdLinker { + protected static final String[] discardFiles = new String[0]; + protected static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final GppLinker dllLinker = new GppLinker("gcc", objFiles, + discardFiles, "lib", ".so", false, new GppLinker("gcc", objFiles, + discardFiles, "lib", ".so", true, null)); + private final static String libPrefix = "libraries: ="; + protected static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", "-dylib", + "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib", + "-prebind", "-s", "-static", "-shared", "-symbolic", "-Xlinker"}; + private static final GppLinker instance = new GppLinker("gcc", objFiles, + discardFiles, "", "", false, null); + private static final GppLinker machDllLinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".dylib", false, null); + private static final GppLinker machPluginLinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".bundle", false, null); + public static GppLinker getInstance() { + return instance; + } + private File[] libDirs; + private String runtimeLibrary; + protected GppLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GppLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + super.addImpliedArgs(debug, linkType, args, defaultflag); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + if (linkType.isStaticRuntime()) { + String[] cmdin = new String[]{"g++", "-print-file-name=libstdc++.a"}; + String[] cmdout = CaptureStreamHandler.run(cmdin); + if (cmdout.length > 0) { + runtimeLibrary = cmdout[0]; + } else { + runtimeLibrary = null; + } + } else { + runtimeLibrary = "-lstdc++"; + } + } + public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + String[] rs = super.addLibrarySets(task, libsets, preargs, midargs, + endargs); + if (runtimeLibrary != null) { + endargs.addElement(runtimeLibrary); + } + return rs; + } + /** + * Allows drived linker to decorate linker option. Override by GppLinker to + * prepend a "-Wl," to pass option to through gcc to linker. + * + * @param buf + * buffer that may be used and abused in the decoration process, + * must not be null. + * @param arg + * linker argument + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + Vector dirs = new Vector(); + // Ask GCC where it will look for its libraries. + String[] args = new String[]{"g++", "-print-search-dirs"}; + String[] cmdout = CaptureStreamHandler.run(args); + for (int i = 0; i < cmdout.length; ++i) { + int prefixIndex = cmdout[i].indexOf(libPrefix); + if (prefixIndex >= 0) { + // Special case DOS-type GCCs like MinGW or Cygwin + int s = prefixIndex + libPrefix.length(); + int t = cmdout[i].indexOf(';', s); + while (t > 0) { + dirs.addElement(cmdout[i].substring(s, t)); + s = t + 1; + t = cmdout[i].indexOf(';', s); + } + dirs.addElement(cmdout[i].substring(s)); + ++i; + for (; i < cmdout.length; ++i) { + dirs.addElement(cmdout[i]); + } + } + } + // Eliminate all but actual directories. + String[] libpath = new String[dirs.size()]; + dirs.copyInto(libpath); + int count = CUtil.checkDirectoryArray(libpath); + // Build return array. + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; ++i) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machPluginLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/LdLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/LdLinker.java new file mode 100644 index 0000000000..e05fa5b2db --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/LdLinker.java @@ -0,0 +1,57 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc; +import java.io.File; + +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +/** + * Adapter for the 'ld' linker + * + * @author Curt Arnold + */ +public final class LdLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final LdLinker dllLinker = new LdLinker("ld", objFiles, + discardFiles, "lib", ".so", false, new LdLinker("ld", objFiles, + discardFiles, "lib", ".so", true, null)); + private static final LdLinker instance = new LdLinker("ld", objFiles, + discardFiles, "", "", false, null); + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + public static LdLinker getInstance() { + return instance; + } + private File[] libDirs; + private LdLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, LdLinker libtoolLinker) { + super(command, "-version", extensions, ignoredExtensions, outputPrefix, + outputSuffix, isLibtool, libtoolLinker); + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccCCompiler.java new file mode 100644 index 0000000000..6a5697eb80 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccCCompiler.java @@ -0,0 +1,273 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.CompilerParam; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCompilerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.compiler.ProgressMonitor; +import net.sf.antcontrib.cpptasks.gcc.GccCompatibleCCompiler; +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.FortranParser; +import net.sf.antcontrib.cpptasks.parser.Parser; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * Adapter for the GCC C/C++ compiler + * + * @author Adam Murdoch + */ +public final class GccCCompiler extends GccCompatibleCCompiler { + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + private final static String[] sourceExtensions = new String[]{".c", /* C */ + ".cc", /* C++ */ + ".cpp", /* C++ */ + ".cxx", /* C++ */ + ".c++", /* C++ */ + ".i", /* preprocessed C */ + ".ii", /* preprocessed C++ */ + ".f", /* FORTRAN */ + ".for", /* FORTRAN */ + ".m", /* Objective-C */ + ".mm", /* Objected-C++ */ + ".s" /* Assembly */ + }; + private static final GccCCompiler cppInstance = new GccCCompiler("c++", + sourceExtensions, headerExtensions, false, + new GccCCompiler("c++", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler g77Instance = new GccCCompiler("g77", + sourceExtensions, headerExtensions, false, + new GccCCompiler("g77", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler gppInstance = new GccCCompiler("g++", + sourceExtensions, headerExtensions, false, + new GccCCompiler("g++", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + private static final GccCCompiler instance = new GccCCompiler("gcc", + sourceExtensions, headerExtensions, false, + new GccCCompiler("gcc", sourceExtensions, headerExtensions, true, + null, false, null), false, null); + /** + * Gets c++ adapter + */ + public static GccCCompiler getCppInstance() { + return cppInstance; + } + /** + * Gets g77 adapter + */ + public static GccCCompiler getG77Instance() { + return g77Instance; + } + /** + * Gets gpp adapter + */ + public static GccCCompiler getGppInstance() { + return gppInstance; + } + /** + * Gets gcc adapter + */ + public static GccCCompiler getInstance() { + return instance; + } + private String identifier; + private File[] includePath; + private boolean isPICMeaningful = true; + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + private GccCCompiler(String command, String[] sourceExtensions, + String[] headerExtensions, boolean isLibtool, + GccCCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(command, null, sourceExtensions, headerExtensions, isLibtool, + libtoolCompiler, newEnvironment, env); + isPICMeaningful = System.getProperty("os.name").indexOf("Windows") < 0; + } + public void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + super.addImpliedArgs(args, debug, multithreaded, + exceptions, linkType, rtti, optimization, defaultflag); + if (isPICMeaningful && linkType.isSharedLibrary()) { + args.addElement("-fPIC"); + } + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new GccCCompiler(getCommand(), this.getSourceExtensions(), + this.getHeaderExtensions(), this.getLibtool(), + (GccCCompiler) this.getLibtoolCompiler(), newEnvironment, + env); + } + return this; + } + protected Object clone() throws CloneNotSupportedException { + GccCCompiler clone = (GccCCompiler) super.clone(); + return clone; + } + public void compile(CCTask task, File outputDir, String[] sourceFiles, + String[] args, String[] endArgs, boolean relentless, + CommandLineCompilerConfiguration config, ProgressMonitor monitor) + throws BuildException { + try { + GccCCompiler clone = (GccCCompiler) this.clone(); + CompilerParam param = config.getParam("target"); + if (param != null) + clone.setCommand(param.getValue() + "-" + this.getCommand()); + clone.supercompile(task, outputDir, sourceFiles, args, endArgs, + relentless, config, monitor); + } catch (CloneNotSupportedException e) { + supercompile(task, outputDir, sourceFiles, args, endArgs, + relentless, config, monitor); + } + } + /** + * Create parser to determine dependencies. + * + * Will create appropriate parser (C++, FORTRAN) based on file extension. + * + */ + protected Parser createParser(File source) { + if (source != null) { + String sourceName = source.getName(); + int lastDot = sourceName.lastIndexOf('.'); + if (lastDot >= 0 && lastDot + 1 < sourceName.length()) { + char afterDot = sourceName.charAt(lastDot + 1); + if (afterDot == 'f' || afterDot == 'F') { + return new FortranParser(); + } + } + } + return new CParser(); + } + public File[] getEnvironmentIncludePath() { + if (includePath == null) { + // + // construct default include path from machine id and version id + // + String[] defaultInclude = new String[1]; + StringBuffer buf = new StringBuffer("/lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + buf.append("/include"); + defaultInclude[0] = buf.toString(); + // + // read specs file and look for -istart and -idirafter + // + String[] specs = GccProcessor.getSpecs(); + String[][] optionValues = GccProcessor.parseSpecs(specs, "*cpp:", + new String[]{"-isystem ", "-idirafter "}); + // + // if no entries were found, then use a default path + // + if (optionValues[0].length == 0 && optionValues[1].length == 0) { + optionValues[0] = new String[]{"/usr/local/include", + "/usr/include", "/usr/include/win32api"}; + } + // + // remove mingw entries. + // For MinGW compiles this will mean the + // location of the sys includes will be + // wrong in dependencies.xml + // but that should have no significant effect + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j].indexOf("mingw") > 0) { + optionValues[i][j] = null; + } + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(optionValues[0]); + GccProcessor.convertCygwinFilenames(optionValues[1]); + GccProcessor.convertCygwinFilenames(defaultInclude); + } + int count = CUtil.checkDirectoryArray(optionValues[0]); + count += CUtil.checkDirectoryArray(optionValues[1]); + count += CUtil.checkDirectoryArray(defaultInclude); + includePath = new File[count]; + int index = 0; + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j] != null) { + includePath[index++] = new File(optionValues[i][j]); + } + } + } + for (int i = 0; i < defaultInclude.length; i++) { + if (defaultInclude[i] != null) { + includePath[index++] = new File(defaultInclude[i]); + } + } + } + return (File[]) includePath.clone(); + } + public String getIdentifier() throws BuildException { + if (identifier == null) { + StringBuffer buf; + if (getLibtool()) { + buf = new StringBuffer("libtool "); + } else { + buf = new StringBuffer(' '); + } + buf.append(getCommand()); + buf.append(' '); + buf.append(GccProcessor.getVersion()); + buf.append(' '); + buf.append(GccProcessor.getMachine()); + identifier = buf.toString(); + } + return identifier; + } + public Linker getLinker(LinkType linkType) { + return GccLinker.getInstance().getLinker(linkType); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + private void supercompile(CCTask task, File outputDir, + String[] sourceFiles, String[] args, String[] endArgs, + boolean relentless, CommandLineCompilerConfiguration config, + ProgressMonitor monitor) throws BuildException { + super.compile(task, outputDir, sourceFiles, args, endArgs, relentless, + config, monitor); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccLibrarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccLibrarian.java new file mode 100644 index 0000000000..ea2278a6e7 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccLibrarian.java @@ -0,0 +1,69 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractArLibrarian; + +import org.apache.tools.ant.BuildException; +/** + * Adapter for the 'ar' archiver + * + * @author Adam Murdoch + */ +public final class GccLibrarian extends AbstractArLibrarian { + private static String[] objFileExtensions = new String[]{".o"}; + private static GccLibrarian instance = new GccLibrarian("ar", + objFileExtensions, false, new GccLibrarian("ar", objFileExtensions, + true, null)); + public static GccLibrarian getInstance() { + return instance; + } + private GccLibrarian(String command, String[] inputExtensions, + boolean isLibtool, GccLibrarian libtoolLibrarian) { + super(command, "V", inputExtensions, new String[0], "lib", ".a", + isLibtool, libtoolLibrarian); + } + protected Object clone() throws CloneNotSupportedException { + GccLibrarian clone = (GccLibrarian) super.clone(); + return clone; + } + public Linker getLinker(LinkType type) { + return GccLinker.getInstance().getLinker(type); + } + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + try { + GccLibrarian clone = (GccLibrarian) this.clone(); + LinkerParam param = config.getParam("target"); + if (param != null) + clone.setCommand(param.getValue() + "-" + this.getCommand()); + clone.superlink(task, outputFile, sourceFiles, config); + } catch (CloneNotSupportedException e) { + superlink(task, outputFile, sourceFiles, config); + } + } + private void superlink(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + super.link(task, outputFile, sourceFiles, config); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccLinker.java new file mode 100644 index 0000000000..3293829d13 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccLinker.java @@ -0,0 +1,234 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross; +import java.io.File; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +import org.apache.tools.ant.BuildException; +/** + * Adapter for the GCC linker + * + * @author Adam Murdoch + */ +public class GccLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final GccLinker dllLinker = new GccLinker("gcc", objFiles, + discardFiles, "lib", ".so", false, new GccLinker("gcc", objFiles, + discardFiles, "lib", ".so", true, null)); + private static final GccLinker instance = new GccLinker("gcc", objFiles, + discardFiles, "", "", false, null); + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", + "-dynamiclib", "-nostartfiles", "-nostdlib", "-prebind", "-s", + "-static", "-shared", "-symbolic", "-Xlinker", + "--export-all-symbols", "-static-libgcc",}; + private static final GccLinker machBundleLinker = new GccLinker("gcc", + objFiles, discardFiles, "lib", ".bundle", false, null); + private static final GccLinker machDllLinker = new GccLinker("gcc", + objFiles, discardFiles, "lib", ".dylib", false, null); + public static GccLinker getInstance() { + return instance; + } + private File[] libDirs; + protected GccLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GccLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + super.addImpliedArgs(debug, linkType, args, defaultflag); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + } + protected Object clone() throws CloneNotSupportedException { + GccLinker clone = (GccLinker) super.clone(); + return clone; + } + /** + * Allows drived linker to decorate linker option. Override by GccLinker to + * prepend a "-Wl," to pass option to through gcc to linker. + * + * @param buf + * buffer that may be used and abused in the decoration process, + * must not be null. + * @param arg + * linker argument + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + case 'v' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + // + // construct gcc lib path from machine and version + // + StringBuffer buf = new StringBuffer("/lib/gcc-lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + // + // build default path from gcc and system /lib and /lib/w32api + // + String[] impliedLibPath = new String[]{buf.toString(), + "/lib/w32api", "/lib"}; + // + // read gcc specs file for other library paths + // + String[] specs = GccProcessor.getSpecs(); + String[][] libpaths = GccProcessor.parseSpecs(specs, "*link:", + new String[]{"%q"}); + String[] libpath; + if (libpaths[0].length > 0) { + libpath = new String[libpaths[0].length + 3]; + int i = 0; + for (; i < libpaths[0].length; i++) { + libpath[i] = libpaths[0][i]; + } + libpath[i++] = buf.toString(); + libpath[i++] = "/lib/w32api"; + libpath[i++] = "/lib"; + } else { + // + // if a failure to find any matches then + // use some default values for lib path entries + libpath = new String[]{"/usr/local/lib/mingw", + "/usr/local/lib", "/usr/lib/w32api", "/usr/lib/mingw", + "/usr/lib", buf.toString(), "/lib/w32api", "/lib"}; + } + for (int i = 0; i < libpath.length; i++) { + if (libpath[i].indexOf("mingw") >= 0) { + libpath[i] = null; + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(libpath); + } + // + // check that remaining entries are actual directories + // + int count = CUtil.checkDirectoryArray(libpath); + // + // populate return array with remaining entries + // + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; i++) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (isDarwin()) { + return machBundleLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (isDarwin()) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + try { + GccLinker clone = (GccLinker) this.clone(); + LinkerParam param = config.getParam("target"); + if (param != null) + clone.setCommand(param.getValue() + "-" + this.getCommand()); + clone.superlink(task, outputFile, sourceFiles, config); + } catch (CloneNotSupportedException e) { + superlink(task, outputFile, sourceFiles, config); + } + } + private void superlink(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + super.link(task, outputFile, sourceFiles, config); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccProcessor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccProcessor.java new file mode 100644 index 0000000000..283df63314 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GccProcessor.java @@ -0,0 +1,288 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; + +/** + * A add-in class for Gcc processors + * + * + */ +public class GccProcessor { + // the results from gcc -dumpmachine + private static String machine; + private static String[] specs; + // the results from gcc -dumpversion + private static String version; + private static int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + /** + * Converts absolute Cygwin file or directory names to the corresponding + * Win32 name. + * + * @param names + * array of names, some elements may be null, will be changed in + * place. + */ + public static void convertCygwinFilenames(String[] names) { + if (names == null) { + throw new NullPointerException("names"); + } + File gccDir = CUtil.getExecutableLocation("gcc.exe"); + if (gccDir != null) { + String prefix = gccDir.getAbsolutePath() + "/.."; + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + if (name != null && name.length() > 1 && name.charAt(0) == '/') { + buf.setLength(0); + buf.append(prefix); + buf.append(name); + names[i] = buf.toString(); + } + } + } + } + + public static String getMachine() { + if (machine == null) { + String[] args = new String[]{"gcc", "-dumpmachine"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + machine = "nomachine"; + } else { + machine = cmdout[0]; + } + } + return machine; + } + public static String[] getOutputFileSwitch(String letter, String outputFile) { + StringBuffer buf = new StringBuffer(); + if (outputFile.indexOf(' ') >= 0) { + buf.append('"'); + buf.append(outputFile.replace('\\', '/')); + buf.append('"'); + } else { + buf.append(outputFile.replace('\\', '/')); + } + String[] retval = new String[]{letter, buf.toString()}; + return retval; + } + /** + * Returns the contents of the gcc specs file. + * + * The implementation locates gcc.exe in the executable path and then + * builds a relative path name from the results of -dumpmachine and + * -dumpversion. Attempts to use gcc -dumpspecs to provide this information + * resulted in stalling on the Execute.run + * + * @returns contents of the specs file + */ + public static String[] getSpecs() { + if (specs == null) { + File gccParent = CUtil.getExecutableLocation("gcc.exe"); + if (gccParent != null) { + // + // build a relative path like + // ../lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs + // + StringBuffer buf = new StringBuffer("../lib/gcc-lib/"); + buf.append(getMachine()); + buf.append('/'); + buf.append(getVersion()); + buf.append("/specs"); + // + // resolve it relative to the location of gcc.exe + // + String relativePath = buf.toString(); + File specsFile = new File(gccParent, relativePath); + // + // found the specs file + // + try { + // + // read the lines in the file + // + BufferedReader reader = new BufferedReader(new FileReader( + specsFile)); + Vector lines = new Vector(100); + String line = reader.readLine(); + while (line != null) { + lines.addElement(line); + line = reader.readLine(); + } + specs = new String[lines.size()]; + lines.copyInto(specs); + } catch (IOException ex) { + } + } + } + if (specs == null) { + specs = new String[0]; + } + return specs; + } + public static String getVersion() { + if (version == null) { + String[] args = new String[]{"gcc", "-dumpversion"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + version = "noversion"; + } else { + version = cmdout[0]; + } + } + return version; + } + public static boolean isCaseSensitive() { + return true; + } + /** + * Determines if task is running with cygwin + * + * @return true if cygwin was detected + */ + public static boolean isCygwin() { + return getMachine().indexOf("cygwin") > 0; + } + private static boolean isHPUX() { + String osname = System.getProperty("os.name").toLowerCase(); + if (osname.indexOf("hp") >= 0 && osname.indexOf("ux") >= 0) { + return true; + } + return false; + } + /** + * + * Parses the results of the specs file for a specific processor and + * options + * + * @param specsContent + * Contents of specs file as returned from getSpecs + * @param specSectionStart + * start of spec section, for example "*cpp:" + * @param options + * command line switches such as "-istart" + */ + public static String[][] parseSpecs(String[] specsContent, + String specSectionStart, String[] options) { + if (specsContent == null) { + throw new NullPointerException("specsContent"); + } + if (specSectionStart == null) { + throw new NullPointerException("specSectionStart"); + } + if (options == null) { + throw new NullPointerException("option"); + } + String[][] optionValues = new String[options.length][]; + StringBuffer optionValue = new StringBuffer(40); + for (int i = 0; i < specsContent.length; i++) { + String specLine = specsContent[i]; + // + // if start of section then start paying attention + // + if (specLine.startsWith(specSectionStart)) { + Vector[] optionVectors = new Vector[options.length]; + for (int j = 0; j < options.length; j++) { + optionVectors[j] = new Vector(10); + } + // + // go to next line and examine contents + // and repeat until end of file + // + for (i++; i < specsContent.length; i++) { + specLine = specsContent[i]; + for (int j = 0; j < options.length; j++) { + int optionStart = specLine.indexOf(options[j]); + while (optionStart >= 0) { + optionValue.setLength(0); + // + // walk rest of line looking for first non + // whitespace + // and then next space + boolean hasNonBlank = false; + int k = optionStart + options[j].length(); + for (; k < specLine.length(); k++) { + // + // either a blank or a "}" (close of + // conditional) + // section will end the path + // + if (specLine.charAt(k) == ' ' + || specLine.charAt(k) == '}') { + if (hasNonBlank) { + break; + } + } else { + hasNonBlank = true; + optionValue.append(specLine.charAt(k)); + } + } + // + // transition back to whitespace + // value is over, add it to vector + if (hasNonBlank) { + optionVectors[j].addElement(optionValue + .toString()); + } + // + // find next occurance on line + // + optionStart = specLine.indexOf(options[j], k); + } + } + } + // + // copy vectors over to option arrays + // + for (int j = 0; j < options.length; j++) { + optionValues[j] = new String[optionVectors[j].size()]; + optionVectors[j].copyInto(optionValues[j]); + } + } + } + // + // fill in any missing option values with + // a zero-length string array + for (int i = 0; i < optionValues.length; i++) { + String[] zeroLenArray = new String[0]; + if (optionValues[i] == null) { + optionValues[i] = zeroLenArray; + } + } + return optionValues; + } + private GccProcessor() { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GppLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GppLinker.java new file mode 100644 index 0000000000..3ba8f06bf8 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/GppLinker.java @@ -0,0 +1,228 @@ +/* + * + * Copyright 2003-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +import net.sf.antcontrib.cpptasks.types.LibrarySet; + +import org.apache.tools.ant.BuildException; +/** + * Adapter for the g++ variant of the GCC linker + * + * @author Stephen M. Webb + */ +public class GppLinker extends AbstractLdLinker { + protected static final String[] discardFiles = new String[0]; + protected static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final GppLinker dllLinker = new GppLinker("gcc", objFiles, + discardFiles, "lib", ".so", false, new GppLinker("gcc", objFiles, + discardFiles, "lib", ".so", true, null)); + private final static String libPrefix = "libraries: ="; + protected static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", "-dylib", + "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib", + "-prebind", "-s", "-static", "-shared", "-symbolic", "-Xlinker"}; + private static final GppLinker instance = new GppLinker("gcc", objFiles, + discardFiles, "", "", false, null); + private static final GppLinker machDllLinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".dylib", false, null); + private static final GppLinker machPluginLinker = new GppLinker("gcc", + objFiles, discardFiles, "lib", ".bundle", false, null); + public static GppLinker getInstance() { + return instance; + } + private File[] libDirs; + private String runtimeLibrary; + protected GppLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GppLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + super.addImpliedArgs(debug, linkType, args, defaultflag); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + if (linkType.isStaticRuntime()) { + String[] cmdin = new String[]{"g++", "-print-file-name=libstdc++.a"}; + String[] cmdout = CaptureStreamHandler.run(cmdin); + if (cmdout.length > 0) { + runtimeLibrary = cmdout[0]; + } else { + runtimeLibrary = null; + } + } else { + runtimeLibrary = "-lstdc++"; + } + } + public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + String[] rs = super.addLibrarySets(task, libsets, preargs, midargs, + endargs); + if (runtimeLibrary != null) { + endargs.addElement(runtimeLibrary); + } + return rs; + } + protected Object clone() throws CloneNotSupportedException { + GppLinker clone = (GppLinker) super.clone(); + return clone; + } + /** + * Allows drived linker to decorate linker option. Override by GppLinker to + * prepend a "-Wl," to pass option to through gcc to linker. + * + * @param buf + * buffer that may be used and abused in the decoration process, + * must not be null. + * @param arg + * linker argument + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + Vector dirs = new Vector(); + // Ask GCC where it will look for its libraries. + String[] args = new String[]{"g++", "-print-search-dirs"}; + String[] cmdout = CaptureStreamHandler.run(args); + for (int i = 0; i < cmdout.length; ++i) { + int prefixIndex = cmdout[i].indexOf(libPrefix); + if (prefixIndex >= 0) { + // Special case DOS-type GCCs like MinGW or Cygwin + int s = prefixIndex + libPrefix.length(); + int t = cmdout[i].indexOf(';', s); + while (t > 0) { + dirs.addElement(cmdout[i].substring(s, t)); + s = t + 1; + t = cmdout[i].indexOf(';', s); + } + dirs.addElement(cmdout[i].substring(s)); + ++i; + for (; i < cmdout.length; ++i) { + dirs.addElement(cmdout[i]); + } + } + } + // Eliminate all but actual directories. + String[] libpath = new String[dirs.size()]; + dirs.copyInto(libpath); + int count = CUtil.checkDirectoryArray(libpath); + // Build return array. + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; ++i) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machPluginLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + try { + GppLinker clone = (GppLinker) this.clone(); + LinkerParam param = config.getParam("target"); + if (param != null) + clone.setCommand(param.getValue() + "-" + this.getCommand()); + clone.superlink(task, outputFile, sourceFiles, config); + } catch (CloneNotSupportedException e) { + superlink(task, outputFile, sourceFiles, config); + } + } + private void superlink(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + super.link(task, outputFile, sourceFiles, config); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/LdLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/LdLinker.java new file mode 100644 index 0000000000..8ac0cf82a7 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/LdLinker.java @@ -0,0 +1,83 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.LinkerParam; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; + +import org.apache.tools.ant.BuildException; +/** + * Adapter for the 'ld' linker + * + * @author Curt Arnold + */ +public final class LdLinker extends AbstractLdLinker { + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final String[] discardFiles = new String[0]; + private static final LdLinker dllLinker = new LdLinker("ld", objFiles, + discardFiles, "lib", ".so", false, new LdLinker("ld", objFiles, + discardFiles, "lib", ".so", true, null)); + private static final LdLinker instance = new LdLinker("ld", objFiles, + discardFiles, "", "", false, null); + public static LdLinker getInstance() { + return instance; + } + private File[] libDirs; + private LdLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, LdLinker libtoolLinker) { + super(command, "-version", extensions, ignoredExtensions, outputPrefix, + outputSuffix, isLibtool, libtoolLinker); + } + protected Object clone() throws CloneNotSupportedException { + LdLinker clone = (LdLinker) super.clone(); + return clone; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + try { + LdLinker clone = (LdLinker) this.clone(); + LinkerParam param = config.getParam("target"); + if (param != null) + clone.setCommand(param.getValue() + "-" + this.getCommand()); + clone.superlink(task, outputFile, sourceFiles, config); + } catch (CloneNotSupportedException e) { + superlink(task, outputFile, sourceFiles, config); + } + } + private void superlink(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + super.link(task, outputFile, sourceFiles, config); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccCCompiler.java new file mode 100644 index 0000000000..62d65b910c --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccCCompiler.java @@ -0,0 +1,245 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.gcc.GccCompatibleCCompiler; +import net.sf.antcontrib.cpptasks.parser.CParser; +import net.sf.antcontrib.cpptasks.parser.FortranParser; +import net.sf.antcontrib.cpptasks.parser.Parser; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.Environment; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +/** + * Adapter for the GCC C/C++ compiler + * + * @author Adam Murdoch + */ +public final class GccCCompiler extends GccCompatibleCCompiler { + private final static String[] sourceExtensions = new String[]{".c", /* C */ + ".cc", /* C++ */ + ".cpp", /* C++ */ + ".cxx", /* C++ */ + ".c++", /* C++ */ + ".i", /* preprocessed C */ + ".ii", /* preprocessed C++ */ + ".f", /* FORTRAN */ + ".for", /* FORTRAN */ + ".m", /* Objective-C */ + ".mm", /* Objected-C++ */ + ".s" /* Assembly */ + }; + private final static String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + public static final String CMD_PREFIX = "sparc-sun-solaris2-"; + private static final GccCCompiler cppInstance = new GccCCompiler(CMD_PREFIX + + "c++", sourceExtensions, headerExtensions, false, + new GccCCompiler(CMD_PREFIX + "c++", sourceExtensions, + headerExtensions, true, null, false, null), false, null); + private static final GccCCompiler g77Instance = new GccCCompiler(CMD_PREFIX + + "g77", sourceExtensions, headerExtensions, false, + new GccCCompiler(CMD_PREFIX + "g77", sourceExtensions, + headerExtensions, true, null, false, null), false, null); + private static final GccCCompiler gppInstance = new GccCCompiler(CMD_PREFIX + + "g++", sourceExtensions, headerExtensions, false, + new GccCCompiler(CMD_PREFIX + "g++", sourceExtensions, + headerExtensions, true, null, false, null), false, null); + private static final GccCCompiler instance = new GccCCompiler(CMD_PREFIX + + "gcc", sourceExtensions, headerExtensions, false, + new GccCCompiler(CMD_PREFIX + "gcc", sourceExtensions, + headerExtensions, true, null, false, null), false, null); + /** + * Gets c++ adapter + */ + public static GccCCompiler getCppInstance() { + return cppInstance; + } + /** + * Gets g77 adapter + */ + public static GccCCompiler getG77Instance() { + return g77Instance; + } + /** + * Gets gpp adapter + */ + public static GccCCompiler getGppInstance() { + return gppInstance; + } + /** + * Gets gcc adapter + */ + public static GccCCompiler getInstance() { + return instance; + } + private String identifier; + private File[] includePath; + private boolean isPICMeaningful = true; + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + private GccCCompiler(String command, String[] sourceExtensions, + String[] headerExtensions, boolean isLibtool, + GccCCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super(command, null, sourceExtensions, headerExtensions, isLibtool, + libtoolCompiler, newEnvironment, env); + isPICMeaningful = System.getProperty("os.name").indexOf("Windows") < 0; + } + public void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + super.addImpliedArgs(args, debug, multithreaded, + exceptions, linkType, rtti, optimization, defaultflag); + if (isPICMeaningful && linkType.isSharedLibrary()) { + args.addElement("-fPIC"); + } + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new GccCCompiler(getCommand(), this.getSourceExtensions(), + this.getHeaderExtensions(), this.getLibtool(), + (GccCCompiler) this.getLibtoolCompiler(), newEnvironment, + env); + } + return this; + } + /** + * Create parser to determine dependencies. + * + * Will create appropriate parser (C++, FORTRAN) based on file extension. + * + */ + protected Parser createParser(File source) { + if (source != null) { + String sourceName = source.getName(); + int lastDot = sourceName.lastIndexOf('.'); + if (lastDot >= 0 && lastDot + 1 < sourceName.length()) { + char afterDot = sourceName.charAt(lastDot + 1); + if (afterDot == 'f' || afterDot == 'F') { + return new FortranParser(); + } + } + } + return new CParser(); + } + public File[] getEnvironmentIncludePath() { + if (includePath == null) { + // + // construct default include path from machine id and version id + // + String[] defaultInclude = new String[1]; + StringBuffer buf = new StringBuffer("/lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + buf.append("/include"); + defaultInclude[0] = buf.toString(); + // + // read specs file and look for -istart and -idirafter + // + String[] specs = GccProcessor.getSpecs(); + String[][] optionValues = GccProcessor.parseSpecs(specs, "*cpp:", + new String[]{"-isystem ", "-idirafter "}); + // + // if no entries were found, then use a default path + // + if (optionValues[0].length == 0 && optionValues[1].length == 0) { + optionValues[0] = new String[]{"/usr/local/include", + "/usr/include", "/usr/include/win32api"}; + } + // + // remove mingw entries. + // For MinGW compiles this will mean the + // location of the sys includes will be + // wrong in dependencies.xml + // but that should have no significant effect + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j].indexOf("mingw") > 0) { + optionValues[i][j] = null; + } + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(optionValues[0]); + GccProcessor.convertCygwinFilenames(optionValues[1]); + GccProcessor.convertCygwinFilenames(defaultInclude); + } + int count = CUtil.checkDirectoryArray(optionValues[0]); + count += CUtil.checkDirectoryArray(optionValues[1]); + count += CUtil.checkDirectoryArray(defaultInclude); + includePath = new File[count]; + int index = 0; + for (int i = 0; i < optionValues.length; i++) { + for (int j = 0; j < optionValues[i].length; j++) { + if (optionValues[i][j] != null) { + includePath[index++] = new File(optionValues[i][j]); + } + } + } + for (int i = 0; i < defaultInclude.length; i++) { + if (defaultInclude[i] != null) { + includePath[index++] = new File(defaultInclude[i]); + } + } + } + return (File[]) includePath.clone(); + } + public String getIdentifier() throws BuildException { + if (identifier == null) { + StringBuffer buf; + if (getLibtool()) { + buf = new StringBuffer("libtool "); + } else { + buf = new StringBuffer(' '); + } + buf.append(getCommand()); + buf.append(' '); + buf.append(GccProcessor.getVersion()); + buf.append(' '); + buf.append(GccProcessor.getMachine()); + identifier = buf.toString(); + } + return identifier; + } + public Linker getLinker(LinkType linkType) { + return GccLinker.getInstance().getLinker(linkType); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLibrarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLibrarian.java new file mode 100644 index 0000000000..bb243879af --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLibrarian.java @@ -0,0 +1,43 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractArLibrarian; +/** + * Adapter for the 'ar' archiver + * + * @author Adam Murdoch + */ +public final class GccLibrarian extends AbstractArLibrarian { + private static String[] objFileExtensions = new String[]{".o"}; + private static GccLibrarian instance = new GccLibrarian( + GccCCompiler.CMD_PREFIX + "ar", objFileExtensions, false, + new GccLibrarian(GccCCompiler.CMD_PREFIX + "ar", objFileExtensions, + true, null)); + public static GccLibrarian getInstance() { + return instance; + } + private GccLibrarian(String command, String[] inputExtensions, + boolean isLibtool, GccLibrarian libtoolLibrarian) { + super(command, "V", inputExtensions, new String[0], "lib", ".a", + isLibtool, libtoolLibrarian); + } + public Linker getLinker(LinkType type) { + return GccLinker.getInstance().getLinker(type); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLinker.java new file mode 100644 index 0000000000..914da34439 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccLinker.java @@ -0,0 +1,215 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +/** + * Adapter for the GCC linker + * + * @author Adam Murdoch + */ +public class GccLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", + "-dynamiclib", "-nostartfiles", "-nostdlib", "-prebind", "-s", + "-static", "-shared", "-symbolic", "-Xlinker", + "--export-all-symbols", "-static-libgcc",}; + private static final GccLinker dllLinker = new GccLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".so", false, new GccLinker(GccCCompiler.CMD_PREFIX + "gcc", + objFiles, discardFiles, "lib", ".so", true, null)); + private static final GccLinker instance = new GccLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "", "", + false, null); + private static final GccLinker machBundleLinker = new GccLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".bundle", false, null); + private static final GccLinker machDllLinker = new GccLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".dylib", false, null); + public static GccLinker getInstance() { + return instance; + } + private File[] libDirs; + protected GccLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GccLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + super.addImpliedArgs(debug, linkType, args, defaultflag); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + } + /** + * Allows drived linker to decorate linker option. Override by GccLinker to + * prepend a "-Wl," to pass option to through gcc to linker. + * + * @param buf + * buffer that may be used and abused in the decoration process, + * must not be null. + * @param arg + * linker argument + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + case 'v' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + // + // construct gcc lib path from machine and version + // + StringBuffer buf = new StringBuffer("/lib/gcc-lib/"); + buf.append(GccProcessor.getMachine()); + buf.append('/'); + buf.append(GccProcessor.getVersion()); + // + // build default path from gcc and system /lib and /lib/w32api + // + String[] impliedLibPath = new String[]{buf.toString(), + "/lib/w32api", "/lib"}; + // + // read gcc specs file for other library paths + // + String[] specs = GccProcessor.getSpecs(); + String[][] libpaths = GccProcessor.parseSpecs(specs, "*link:", + new String[]{"%q"}); + String[] libpath; + if (libpaths[0].length > 0) { + libpath = new String[libpaths[0].length + 3]; + int i = 0; + for (; i < libpaths[0].length; i++) { + libpath[i] = libpaths[0][i]; + } + libpath[i++] = buf.toString(); + libpath[i++] = "/lib/w32api"; + libpath[i++] = "/lib"; + } else { + // + // if a failure to find any matches then + // use some default values for lib path entries + libpath = new String[]{"/usr/local/lib/mingw", + "/usr/local/lib", "/usr/lib/w32api", "/usr/lib/mingw", + "/usr/lib", buf.toString(), "/lib/w32api", "/lib"}; + } + for (int i = 0; i < libpath.length; i++) { + if (libpath[i].indexOf("mingw") >= 0) { + libpath[i] = null; + } + } + // + // if cygwin then + // we have to prepend location of gcc32 + // and .. to start of absolute filenames to + // have something that will exist in the + // windows filesystem + if (GccProcessor.isCygwin()) { + GccProcessor.convertCygwinFilenames(libpath); + } + // + // check that remaining entries are actual directories + // + int count = CUtil.checkDirectoryArray(libpath); + // + // populate return array with remaining entries + // + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; i++) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (isDarwin()) { + return machBundleLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (isDarwin()) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccProcessor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccProcessor.java new file mode 100644 index 0000000000..599d6a8013 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GccProcessor.java @@ -0,0 +1,305 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * A add-in class for Gcc processors + * + * + */ +public class GccProcessor { + // the results from gcc -dumpmachine + private static String machine; + private static String[] specs; + // the results from gcc -dumpversion + private static String version; + private static int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + /** + * Converts absolute Cygwin file or directory names to the corresponding + * Win32 name. + * + * @param names + * array of names, some elements may be null, will be changed in + * place. + */ + public static void convertCygwinFilenames(String[] names) { + if (names == null) { + throw new NullPointerException("names"); + } + File gccDir = CUtil.getExecutableLocation(GccCCompiler.CMD_PREFIX + + "gcc.exe"); + if (gccDir != null) { + String prefix = gccDir.getAbsolutePath() + "/.."; + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < names.length; i++) { + String name = names[i]; + if (name != null && name.length() > 1 && name.charAt(0) == '/') { + buf.setLength(0); + buf.append(prefix); + buf.append(name); + names[i] = buf.toString(); + } + } + } + } + public static String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + StringBuffer buf = new StringBuffer(); + String[] patterns = new String[libnames.length * 2]; + int offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0); + if (isHPUX()) { + offset = addLibraryPatterns(libnames, buf, "lib", ".sl", patterns, + offset); + } else { + offset = addLibraryPatterns(libnames, buf, "lib", ".so", patterns, + offset); + } + return patterns; + } + public static String getMachine() { + if (machine == null) { + String[] args = new String[]{GccCCompiler.CMD_PREFIX + "gcc", + "-dumpmachine"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + machine = "nomachine"; + } else { + machine = cmdout[0]; + } + } + return machine; + } + public static String[] getOutputFileSwitch(String letter, String outputFile) { + StringBuffer buf = new StringBuffer(); + if (outputFile.indexOf(' ') >= 0) { + buf.append('"'); + buf.append(outputFile.replace('\\', '/')); + buf.append('"'); + } else { + buf.append(outputFile.replace('\\', '/')); + } + String[] retval = new String[]{letter, buf.toString()}; + return retval; + } + /** + * Returns the contents of the gcc specs file. + * + * The implementation locates gcc.exe in the executable path and then + * builds a relative path name from the results of -dumpmachine and + * -dumpversion. Attempts to use gcc -dumpspecs to provide this information + * resulted in stalling on the Execute.run + * + * @returns contents of the specs file + */ + public static String[] getSpecs() { + if (specs == null) { + File gccParent = CUtil + .getExecutableLocation(GccCCompiler.CMD_PREFIX + "gcc.exe"); + if (gccParent != null) { + // + // build a relative path like + // ../lib/gcc-lib/i686-pc-cygwin/2.95.3-5/specs + // + StringBuffer buf = new StringBuffer("../lib/gcc-lib/"); + buf.append(getMachine()); + buf.append('/'); + buf.append(getVersion()); + buf.append("/specs"); + // + // resolve it relative to the location of gcc.exe + // + String relativePath = buf.toString(); + File specsFile = new File(gccParent, relativePath); + // + // found the specs file + // + try { + // + // read the lines in the file + // + BufferedReader reader = new BufferedReader(new FileReader( + specsFile)); + Vector lines = new Vector(100); + String line = reader.readLine(); + while (line != null) { + lines.addElement(line); + line = reader.readLine(); + } + specs = new String[lines.size()]; + lines.copyInto(specs); + } catch (IOException ex) { + } + } + } + if (specs == null) { + specs = new String[0]; + } + return specs; + } + public static String getVersion() { + if (version == null) { + String[] args = new String[]{GccCCompiler.CMD_PREFIX + "gcc", + "-dumpversion"}; + String[] cmdout = CaptureStreamHandler.run(args); + if (cmdout.length == 0) { + version = "noversion"; + } else { + version = cmdout[0]; + } + } + return version; + } + public static boolean isCaseSensitive() { + return true; + } + /** + * Determines if task is running with cygwin + * + * @return true if cygwin was detected + */ + public static boolean isCygwin() { + return getMachine().indexOf("cygwin") > 0; + } + private static boolean isHPUX() { + String osname = System.getProperty("os.name").toLowerCase(); + if (osname.indexOf("hp") >= 0 && osname.indexOf("ux") >= 0) { + return true; + } + return false; + } + /** + * + * Parses the results of the specs file for a specific processor and + * options + * + * @param specsContent + * Contents of specs file as returned from getSpecs + * @param specSectionStart + * start of spec section, for example "*cpp:" + * @param options + * command line switches such as "-istart" + */ + public static String[][] parseSpecs(String[] specsContent, + String specSectionStart, String[] options) { + if (specsContent == null) { + throw new NullPointerException("specsContent"); + } + if (specSectionStart == null) { + throw new NullPointerException("specSectionStart"); + } + if (options == null) { + throw new NullPointerException("option"); + } + String[][] optionValues = new String[options.length][]; + StringBuffer optionValue = new StringBuffer(40); + for (int i = 0; i < specsContent.length; i++) { + String specLine = specsContent[i]; + // + // if start of section then start paying attention + // + if (specLine.startsWith(specSectionStart)) { + Vector[] optionVectors = new Vector[options.length]; + for (int j = 0; j < options.length; j++) { + optionVectors[j] = new Vector(10); + } + // + // go to next line and examine contents + // and repeat until end of file + // + for (i++; i < specsContent.length; i++) { + specLine = specsContent[i]; + for (int j = 0; j < options.length; j++) { + int optionStart = specLine.indexOf(options[j]); + while (optionStart >= 0) { + optionValue.setLength(0); + // + // walk rest of line looking for first non + // whitespace + // and then next space + boolean hasNonBlank = false; + int k = optionStart + options[j].length(); + for (; k < specLine.length(); k++) { + // + // either a blank or a "}" (close of + // conditional) + // section will end the path + // + if (specLine.charAt(k) == ' ' + || specLine.charAt(k) == '}') { + if (hasNonBlank) { + break; + } + } else { + hasNonBlank = true; + optionValue.append(specLine.charAt(k)); + } + } + // + // transition back to whitespace + // value is over, add it to vector + if (hasNonBlank) { + optionVectors[j].addElement(optionValue + .toString()); + } + // + // find next occurance on line + // + optionStart = specLine.indexOf(options[j], k); + } + } + } + // + // copy vectors over to option arrays + // + for (int j = 0; j < options.length; j++) { + optionValues[j] = new String[optionVectors[j].size()]; + optionVectors[j].copyInto(optionValues[j]); + } + } + } + // + // fill in any missing option values with + // a zero-length string array + for (int i = 0; i < optionValues.length; i++) { + String[] zeroLenArray = new String[0]; + if (optionValues[i] == null) { + optionValues[i] = zeroLenArray; + } + } + return optionValues; + } + private GccProcessor() { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GppLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GppLinker.java new file mode 100644 index 0000000000..6a4c0ab14b --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/GppLinker.java @@ -0,0 +1,210 @@ +/* + * + * Copyright 2003-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CaptureStreamHandler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +/** + * Adapter for the g++ variant of the GCC linker + * + * @author Stephen M. Webb + */ +public class GppLinker extends AbstractLdLinker { + protected static final String[] discardFiles = new String[0]; + protected static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private final static String libPrefix = "libraries: ="; + protected static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static String[] linkerOptions = new String[]{"-bundle", "-dylib", + "-dynamic", "-dynamiclib", "-nostartfiles", "-nostdlib", + "-prebind", "-s", "-static", "-shared", "-symbolic", "-Xlinker"}; + private static final GppLinker dllLinker = new GppLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".so", false, new GppLinker(GccCCompiler.CMD_PREFIX + "gcc", + objFiles, discardFiles, "lib", ".so", true, null)); + private static final GppLinker instance = new GppLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "", "", + false, null); + private static final GppLinker machDllLinker = new GppLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".dylib", false, null); + private static final GppLinker machPluginLinker = new GppLinker( + GccCCompiler.CMD_PREFIX + "gcc", objFiles, discardFiles, "lib", + ".bundle", false, null); + public static GppLinker getInstance() { + return instance; + } + private File[] libDirs; + private String runtimeLibrary; + protected GppLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, GppLinker libtoolLinker) { + super(command, "-dumpversion", extensions, ignoredExtensions, + outputPrefix, outputSuffix, isLibtool, libtoolLinker); + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + super.addImpliedArgs(debug, linkType, args, defaultflag); + if (getIdentifier().indexOf("mingw") >= 0) { + if (linkType.isSubsystemConsole()) { + args.addElement("-mconsole"); + } + if (linkType.isSubsystemGUI()) { + args.addElement("-mwindows"); + } + } + if (linkType.isStaticRuntime()) { + String[] cmdin = new String[]{GccCCompiler.CMD_PREFIX + "g++", + "-print-file-name=libstdc++.a"}; + String[] cmdout = CaptureStreamHandler.run(cmdin); + if (cmdout.length > 0) { + runtimeLibrary = cmdout[0]; + } else { + runtimeLibrary = null; + } + } else { + runtimeLibrary = "-lstdc++"; + } + } + public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + String[] rs = super.addLibrarySets(task, libsets, preargs, midargs, + endargs); + if (runtimeLibrary != null) { + endargs.addElement(runtimeLibrary); + } + return rs; + } + /** + * Allows drived linker to decorate linker option. Override by GppLinker to + * prepend a "-Wl," to pass option to through gcc to linker. + * + * @param buf + * buffer that may be used and abused in the decoration process, + * must not be null. + * @param arg + * linker argument + */ + public String decorateLinkerOption(StringBuffer buf, String arg) { + String decoratedArg = arg; + if (arg.length() > 1 && arg.charAt(0) == '-') { + switch (arg.charAt(1)) { + // + // passed automatically by GCC + // + case 'g' : + case 'f' : + case 'F' : + /* Darwin */ + case 'm' : + case 'O' : + case 'W' : + case 'l' : + case 'L' : + case 'u' : + break; + default : + boolean known = false; + for (int i = 0; i < linkerOptions.length; i++) { + if (linkerOptions[i].equals(arg)) { + known = true; + break; + } + } + if (!known) { + buf.setLength(0); + buf.append("-Wl,"); + buf.append(arg); + decoratedArg = buf.toString(); + } + break; + } + } + return decoratedArg; + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + Vector dirs = new Vector(); + // Ask GCC where it will look for its libraries. + String[] args = new String[]{GccCCompiler.CMD_PREFIX + "g++", + "-print-search-dirs"}; + String[] cmdout = CaptureStreamHandler.run(args); + for (int i = 0; i < cmdout.length; ++i) { + int prefixIndex = cmdout[i].indexOf(libPrefix); + if (prefixIndex >= 0) { + // Special case DOS-type GCCs like MinGW or Cygwin + int s = prefixIndex + libPrefix.length(); + int t = cmdout[i].indexOf(';', s); + while (t > 0) { + dirs.addElement(cmdout[i].substring(s, t)); + s = t + 1; + t = cmdout[i].indexOf(';', s); + } + dirs.addElement(cmdout[i].substring(s)); + ++i; + for (; i < cmdout.length; ++i) { + dirs.addElement(cmdout[i]); + } + } + } + // Eliminate all but actual directories. + String[] libpath = new String[dirs.size()]; + dirs.copyInto(libpath); + int count = CUtil.checkDirectoryArray(libpath); + // Build return array. + libDirs = new File[count]; + int index = 0; + for (int i = 0; i < libpath.length; ++i) { + if (libpath[i] != null) { + libDirs[index++] = new File(libpath[i]); + } + } + } + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isPluginModule()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machPluginLinker; + } else { + return dllLinker; + } + } + if (type.isSharedLibrary()) { + if (GccProcessor.getMachine().indexOf("darwin") >= 0) { + return machDllLinker; + } else { + return dllLinker; + } + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/LdLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/LdLinker.java new file mode 100644 index 0000000000..fc7761e87c --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/gcc/cross/sparc_sun_solaris2/LdLinker.java @@ -0,0 +1,60 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.gcc.cross.sparc_sun_solaris2; +import java.io.File; + +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +/** + * Adapter for the 'ld' linker + * + * @author Curt Arnold + */ +public final class LdLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final LdLinker dllLinker = new LdLinker( + GccCCompiler.CMD_PREFIX + "ld", objFiles, discardFiles, "lib", + ".so", false, new LdLinker(GccCCompiler.CMD_PREFIX + "ld", + objFiles, discardFiles, "lib", ".so", true, null)); + private static final LdLinker instance = new LdLinker( + GccCCompiler.CMD_PREFIX + "ld", objFiles, discardFiles, "", "", + false, null); + public static LdLinker getInstance() { + return instance; + } + private File[] libDirs; + private LdLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, + String outputSuffix, boolean isLibtool, LdLinker libtoolLinker) { + super(command, "-version", extensions, ignoredExtensions, outputPrefix, + outputSuffix, isLibtool, libtoolLinker); + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/hp/aCCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/hp/aCCCompiler.java new file mode 100644 index 0000000000..951bfc1a75 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/hp/aCCCompiler.java @@ -0,0 +1,104 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.hp; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.GccCompatibleCCompiler; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the HP aC++ C++ compiler + * + * @author Curt Arnold + */ +public final class aCCCompiler extends GccCompatibleCCompiler { + private static final aCCCompiler instance = new aCCCompiler("aCC", false, + null); + /** + * Gets singleton instance of this class + */ + public static aCCCompiler getInstance() { + return instance; + } + private String identifier; + private File[] includePath; + /** + * Private constructor. Use GccCCompiler.getInstance() to get singleton + * instance of this class. + */ + private aCCCompiler(String command, boolean newEnvironment, Environment env) { + super(command, "-help", false, null, newEnvironment, env); + } + public void addImpliedArgs(Vector args, boolean debug, + boolean multithreaded, boolean exceptions, LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization) { + args.addElement("-c"); + if (debug) { + args.addElement("-g"); + } + /* + * if (multithreaded) { args.addElement("-mt"); } + */ + if (linkType.isSharedLibrary()) { + args.addElement("+z"); + } + } + public void addWarningSwitch(Vector args, int level) { + switch (level) { + case 0 : + args.addElement("-w"); + break; + case 1 : + case 2 : + args.addElement("+w"); + break; + /* + * case 3: case 4: case 5: args.addElement("+w2"); break; + */ + } + } + public File[] getEnvironmentIncludePath() { + if (includePath == null) { + File ccLoc = CUtil.getExecutableLocation("aCC"); + if (ccLoc != null) { + File compilerIncludeDir = new File( + new File(ccLoc, "../include").getAbsolutePath()); + if (compilerIncludeDir.exists()) { + includePath = new File[2]; + includePath[0] = compilerIncludeDir; + } + } + if (includePath == null) { + includePath = new File[1]; + } + includePath[includePath.length - 1] = new File("/usr/include"); + } + return includePath; + } + public Linker getLinker(LinkType linkType) { + return aCCLinker.getInstance().getLinker(linkType); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/hp/aCCLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/hp/aCCLinker.java new file mode 100644 index 0000000000..86b22e0522 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/hp/aCCLinker.java @@ -0,0 +1,100 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.hp; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +/** + * Adapter for Sun (r) Forte(tm) C++ Linker + * + * @author Curt Arnold + */ +public final class aCCLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final aCCLinker arLinker = new aCCLinker("aCC", objFiles, + discardFiles, "", ".a"); + private static final aCCLinker dllLinker = new aCCLinker("aCC", objFiles, + discardFiles, "lib", ".sl"); + private static final aCCLinker instance = new aCCLinker("aCC", objFiles, + discardFiles, "", ""); + public static aCCLinker getInstance() { + return instance; + } + private File[] libDirs; + private aCCLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, String outputSuffix) { + super(command, "-help", extensions, ignoredExtensions, outputPrefix, + outputSuffix, false, null); + } + public void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + if (debug) { + args.addElement("-g"); + } + /* + * if(linkType.isStaticRuntime()) { args.addElement("-static"); } + */ + if (linkType.isSharedLibrary()) { + args.addElement("-b"); + } + /* + * if (linkType.isStaticLibrary()) { args.addElement("-Wl,-noshared"); } + */ + } + public void addIncremental(boolean incremental, Vector args) { + /* + * if (incremental) { args.addElement("-xidlon"); } else { + * args.addElement("-xidloff"); } + */ + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + File CCloc = CUtil.getExecutableLocation("aCC"); + if (CCloc != null) { + File compilerLib = new File(new File(CCloc, "../lib") + .getAbsolutePath()); + if (compilerLib.exists()) { + libDirs = new File[2]; + libDirs[0] = compilerLib; + } + } + if (libDirs == null) { + libDirs = new File[1]; + } + } + libDirs[libDirs.length - 1] = new File("/usr/lib"); + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return arLinker; + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ibm/VisualAgeCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ibm/VisualAgeCCompiler.java new file mode 100644 index 0000000000..f181c0e3af --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ibm/VisualAgeCCompiler.java @@ -0,0 +1,111 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.ibm; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.GccCompatibleCCompiler; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the IBM(r) Visual Age(tm) C++ compiler for AIX(tm) + * + * @author Curt Arnold + */ +public final class VisualAgeCCompiler extends GccCompatibleCCompiler { + private static final VisualAgeCCompiler instance = new VisualAgeCCompiler( + "xlC", false, null); + /** + * Gets singleton instance of this class + */ + public static VisualAgeCCompiler getInstance() { + return instance; + } + private String identifier; + private File[] includePath; + /** + * Private constructor. Use getInstance() to get singleton instance of this + * class. + */ + private VisualAgeCCompiler(String command, boolean newEnvironment, + Environment env) { + super(command, "-help", false, null, newEnvironment, env); + } + public void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization) { + args.addElement("-c"); + if (debug) { + args.addElement("-g"); + } + if (linkType.isSharedLibrary()) { + args.addElement("-fpic"); + } + if (rtti != null) { + if (rtti.booleanValue()) { + args.addElement("-qrtti=all"); + } else { + args.addElement("-qnortti"); + } + } + } + public void addWarningSwitch(Vector args, int level) { + switch (level) { + case 0 : + args.addElement("-w"); + break; + case 1 : + args.addElement("-qflag=s:s"); + break; + case 2 : + args.addElement("-qflag=e:e"); + break; + case 3 : + args.addElement("-qflag=w:w"); + break; + case 4 : + args.addElement("-qflag=i:i"); + break; + case 5 : + args.addElement("-qhalt=w:w"); + break; + } + } + public Linker getLinker(LinkType linkType) { + return VisualAgeLinker.getInstance().getLinker(linkType); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + /** + * Gets identifier for the compiler. + * + * Initial attempt at extracting version information + * would lock up. Using a stock response. + */ + public String getIdentifier() { + return "VisualAge compiler - unidentified version"; + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ibm/VisualAgeLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ibm/VisualAgeLinker.java new file mode 100644 index 0000000000..f0a811b4ea --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ibm/VisualAgeLinker.java @@ -0,0 +1,75 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.ibm; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +import net.sf.antcontrib.cpptasks.gcc.GccLibrarian; +/** + * Adapter for IBM(r) Visual Age(tm) Linker for AIX(tm) + * + * @author Curt Arnold + */ +public final class VisualAgeLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[]{}; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final VisualAgeLinker dllLinker = new VisualAgeLinker( + "makeC++SharedLib", objFiles, discardFiles, "lib", ".so"); + private static final VisualAgeLinker instance = new VisualAgeLinker("xlC", + objFiles, discardFiles, "", ""); + public static VisualAgeLinker getInstance() { + return instance; + } + private VisualAgeLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, String outputSuffix) { + // + // just guessing that -? might display something useful + // + super(command, "-?", extensions, ignoredExtensions, outputPrefix, + outputSuffix, false, null); + } + public void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + if (debug) { + //args.addElement("-g"); + } + if (linkType.isSharedLibrary()) { + //args.addElement("-G"); + } + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } + /** + * Gets identifier for the compiler. + * + * Initial attempt at extracting version information + * would lock up. Using a stock response. + */ + public String getIdentifier() { + return "VisualAge linker - unidentified version"; + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux32CCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux32CCompiler.java new file mode 100644 index 0000000000..65402f41fb --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux32CCompiler.java @@ -0,0 +1,58 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.intel; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.gcc.GccCompatibleCCompiler; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the Intel (r) C/C++ compiler for IA-32 Linux (r) + * + * The Intel (r) C/C++ compiler for IA32 Linux mimics the command options for + * gcc compiler. + * + * @author Curt Arnold + */ +public final class IntelLinux32CCompiler extends GccCompatibleCCompiler { + private static final IntelLinux32CCompiler instance = new IntelLinux32CCompiler( + false, new IntelLinux32CCompiler(true, null, false, null), false, + null); + public static IntelLinux32CCompiler getInstance() { + return instance; + } + private IntelLinux32CCompiler(boolean isLibtool, + IntelLinux32CCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super("icc", "-V", isLibtool, libtoolCompiler, newEnvironment, env); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new IntelLinux32CCompiler(getLibtool(), + (IntelLinux32CCompiler) getLibtoolCompiler(), + newEnvironment, env); + } + return this; + } + public Linker getLinker(LinkType type) { + return IntelLinux32Linker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux32Linker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux32Linker.java new file mode 100644 index 0000000000..268f490ff3 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux32Linker.java @@ -0,0 +1,55 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.intel; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +import net.sf.antcontrib.cpptasks.gcc.GccLibrarian; +/** + * Adapter for the Intel (r) Linker for Linux (r) for IA-32 + * + * @author Curt Arnold + */ +public final class IntelLinux32Linker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final IntelLinux32Linker dllLinker = new IntelLinux32Linker( + "lib", ".so", false, new IntelLinux32Linker("lib", ".so", true, + null)); + private static final IntelLinux32Linker instance = new IntelLinux32Linker( + "", "", false, null); + public static IntelLinux32Linker getInstance() { + return instance; + } + private IntelLinux32Linker(String outputPrefix, String outputSuffix, + boolean isLibtool, IntelLinux32Linker libtoolLinker) { + super("icc", "-V", objFiles, discardFiles, outputPrefix, outputSuffix, + isLibtool, libtoolLinker); + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux64CCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux64CCompiler.java new file mode 100644 index 0000000000..5a506e0d85 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux64CCompiler.java @@ -0,0 +1,58 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.intel; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.gcc.GccCompatibleCCompiler; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the Intel (r) C/C++ compiler for IA-64 Linux (r) + * + * The Intel C/C++ compiler for IA-64 Linux mimics the command options for gcc + * compiler. + * + * @author Curt Arnold + */ +public final class IntelLinux64CCompiler extends GccCompatibleCCompiler { + private static final IntelLinux64CCompiler instance = new IntelLinux64CCompiler( + false, new IntelLinux64CCompiler(true, null, false, null), false, + null); + public static IntelLinux64CCompiler getInstance() { + return instance; + } + private IntelLinux64CCompiler(boolean isLibtool, + IntelLinux64CCompiler libtoolCompiler, boolean newEnvironment, + Environment env) { + super("ecc", "-V", isLibtool, libtoolCompiler, newEnvironment, env); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new IntelLinux64CCompiler(getLibtool(), + (IntelLinux64CCompiler) this.getLibtoolCompiler(), + newEnvironment, env); + } + return this; + } + public Linker getLinker(LinkType type) { + return IntelLinux64Linker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux64Linker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux64Linker.java new file mode 100644 index 0000000000..f381403510 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelLinux64Linker.java @@ -0,0 +1,55 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.intel; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +import net.sf.antcontrib.cpptasks.gcc.GccLibrarian; +/** + * Adapter for the Intel (r) linker for Linux for IA-64 + * + * @author Curt Arnold + */ +public final class IntelLinux64Linker extends AbstractLdLinker { + private static final String[] discardFiles = new String[0]; + private static final String[] libtoolObjFiles = new String[]{".fo", ".a", + ".lib", ".dll", ".so", ".sl"}; + private static final String[] objFiles = new String[]{".o", ".a", ".lib", + ".dll", ".so", ".sl"}; + private static final IntelLinux64Linker dllLinker = new IntelLinux64Linker( + "lib", ".so", false, new IntelLinux64Linker("lib", ".so", true, + null)); + private static final IntelLinux64Linker instance = new IntelLinux64Linker( + "", "", false, null); + public static IntelLinux64Linker getInstance() { + return instance; + } + private IntelLinux64Linker(String outputPrefix, String outputSuffix, + boolean isLibtool, IntelLinux64Linker libtoolLinker) { + super("ecc", "-V", objFiles, discardFiles, outputPrefix, outputSuffix, + isLibtool, libtoolLinker); + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return GccLibrarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelProcessor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelProcessor.java new file mode 100644 index 0000000000..d1b4eafec5 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelProcessor.java @@ -0,0 +1,51 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.intel; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.devstudio.DevStudioProcessor; +/** + * A add-in class for Intel (r) compilers and linkers + * + * + */ +public class IntelProcessor { + public static void addWarningSwitch(Vector args, int level) { + DevStudioProcessor.addWarningSwitch(args, level); + } + public static String getCommandFileSwitch(String cmdFile) { + return DevStudioProcessor.getCommandFileSwitch(cmdFile); + } + public static void getDefineSwitch(StringBuffer buffer, String define, + String value) { + DevStudioProcessor.getDefineSwitch(buffer, define, value); + } + public static String getIncludeDirSwitch(String includeDir) { + return DevStudioProcessor.getIncludeDirSwitch(includeDir); + } + public static String[] getOutputFileSwitch(String outPath) { + return DevStudioProcessor.getOutputFileSwitch(outPath); + } + public static void getUndefineSwitch(StringBuffer buffer, String define) { + DevStudioProcessor.getUndefineSwitch(buffer, define); + } + public static boolean isCaseSensitive() { + return false; + } + private IntelProcessor() { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32Aslcompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32Aslcompiler.java new file mode 100644 index 0000000000..5255cb90ce --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32Aslcompiler.java @@ -0,0 +1,66 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.intel; + +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineAslcompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioLinker; +/** + * Adapter for Intel ASL compiler + * + */ +public final class IntelWin32Aslcompiler extends CommandLineAslcompiler{ + private final static String[] sourceExtensions = new String[]{".asl"}; + private final static String[] headerExtensions = new String[]{}; + private final static String[] defaultflags = new String[]{}; + private static final IntelWin32Aslcompiler instance = new IntelWin32Aslcompiler("iasl", + sourceExtensions, headerExtensions, false); + + /** + * Gets gcc adapter + */ + public static IntelWin32Aslcompiler getInstance() { + return instance; + } + + /** + * Private constructor. Use GccAssembler.getInstance() to get singleton + * instance of this class. + */ + private IntelWin32Aslcompiler(String command, String[] sourceExtensions, + String[] headerExtensions, boolean isLibtool){ + super(command, null, sourceExtensions, headerExtensions, + ".aml"); + } + public void addImpliedArgs(Vector args, boolean debug, + Boolean defaultflag){ + if (defaultflag != null && defaultflag.booleanValue()) { + for (int i = 0; i < defaultflags.length; i++) { + args.addElement(defaultflags[i]); + } + } + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + public Linker getLinker(LinkType linkType) { + return DevStudioLinker.getInstance().getLinker(linkType); + } +} \ No newline at end of file diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32CCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32CCompiler.java new file mode 100644 index 0000000000..7aef79999f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32CCompiler.java @@ -0,0 +1,53 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.intel; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioCompatibleCCompiler; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the Intel (r) C++ compiler for 32-bit applications + * + * The Intel (r) C++ compiler for IA32 Windows mimics the command options for + * the Microsoft (r) C++ compiler. + * + * @author Curt Arnold + */ +public final class IntelWin32CCompiler extends DevStudioCompatibleCCompiler { + private static final IntelWin32CCompiler instance = new IntelWin32CCompiler( + false, null); + public static IntelWin32CCompiler getInstance() { + return instance; + } + private IntelWin32CCompiler(boolean newEnvironment, Environment env) { + super("icl", null, newEnvironment, env); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new IntelWin32CCompiler(newEnvironment, env); + } + return this; + } + public Linker getLinker(LinkType type) { + return IntelWin32Linker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 1024; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32Librarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32Librarian.java new file mode 100644 index 0000000000..e83da1ce0b --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32Librarian.java @@ -0,0 +1,38 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.intel; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioCompatibleLibrarian; +/** + * Adapter for the xilib from the Intel(r) C++ Compiler for IA-32 or IA-64 + * systems running Microsoft (r) operating systems + * + * @author Curt Arnold + */ +public class IntelWin32Librarian extends DevStudioCompatibleLibrarian { + private static final IntelWin32Librarian instance = new IntelWin32Librarian(); + public static IntelWin32Librarian getInstance() { + return instance; + } + protected IntelWin32Librarian() { + super("xilib", "/bogus"); + } + public Linker getLinker(LinkType type) { + return IntelWin32Linker.getInstance().getLinker(type); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32Linker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32Linker.java new file mode 100644 index 0000000000..51258e23ca --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin32Linker.java @@ -0,0 +1,46 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.intel; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioCompatibleLinker; +/** + * Adapter for the Intel (r) linker for 32-bit applications + * + * @author Curt Arnold + */ +public final class IntelWin32Linker extends DevStudioCompatibleLinker { + private static final IntelWin32Linker dllLinker = new IntelWin32Linker( + ".dll"); + private static final IntelWin32Linker instance = new IntelWin32Linker( + ".exe"); + public static IntelWin32Linker getInstance() { + return instance; + } + private IntelWin32Linker(String outputSuffix) { + super("xilink", "/bogus", outputSuffix); + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return IntelWin32Librarian.getInstance(); + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin64CCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin64CCompiler.java new file mode 100644 index 0000000000..9b8d2c9db4 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/intel/IntelWin64CCompiler.java @@ -0,0 +1,53 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.intel; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.devstudio.DevStudioCompatibleCCompiler; + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the Intel C++ compiler for Itanium(TM) Applications + * + * @author Curt Arnold + */ +public final class IntelWin64CCompiler extends DevStudioCompatibleCCompiler { + private static final IntelWin64CCompiler instance = new IntelWin64CCompiler( + false, null); + public static IntelWin64CCompiler getInstance() { + return instance; + } + private IntelWin64CCompiler(boolean newEnvironment, Environment env) { + super("ecl", null, newEnvironment, env); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new IntelWin64CCompiler(newEnvironment, env); + } + return this; + } + public Linker getLinker(LinkType type) { + // + // currently the Intel Win32 and Win64 linkers + // are command line equivalent + return IntelWin32Linker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return 1024; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os390/OS390CCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os390/OS390CCompiler.java new file mode 100644 index 0000000000..633b55ec0c --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os390/OS390CCompiler.java @@ -0,0 +1,157 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.os390; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.CompilerDef; +import net.sf.antcontrib.cpptasks.compiler.AbstractCompiler; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.types.DefineArgument; +import net.sf.antcontrib.cpptasks.types.UndefineArgument; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the IBM (R) OS/390 (tm) C++ Compiler + * + * @author Hiram Chirino (cojonudo14@hotmail.com) + */ +public class OS390CCompiler extends CommandLineCCompiler { + private static final AbstractCompiler instance = new OS390CCompiler(false, + null); + public static AbstractCompiler getInstance() { + return instance; + } + private OS390CCompiler(boolean newEnvironment, Environment env) { + super("cxx", null, new String[]{".c", ".cc", ".cpp", ".cxx", ".c++", + ".s"}, new String[]{".h", ".hpp"}, ".o", false, null, + newEnvironment, env); + } + protected void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + // Specifies that only compilations and assemblies be done. + // Link-edit is not done + args.addElement("-c"); + args.addElement("-W"); + args.addElement("c,NOEXPMAC,NOSHOWINC"); + /* + * if (exceptions) { args.addElement("/GX"); } + */ + if (debug) { + args.addElement("-g"); + args.addElement("-D"); + args.addElement("_DEBUG"); + /* + * if (multithreaded) { args.addElement("/D_MT"); if (staticLink) { + * args.addElement("/MTd"); } else { args.addElement("/MDd"); + * args.addElement("/D_DLL"); } } else { args.addElement("/MLd"); } + */ + } else { + args.addElement("-D"); + args.addElement("NEBUG"); + /* + * if (multithreaded) { args.addElement("/D_MT"); if (staticLink) { + * args.addElement("/MT"); } else { args.addElement("/MD"); + * args.addElement("/D_DLL"); } } else { args.addElement("/ML"); } + */ + } + } + protected void addWarningSwitch(Vector args, int level) { + OS390Processor.addWarningSwitch(args, level); + } + /** + * The buildDefineArguments implementation CommandLineCCompiler is not good + * for us because os390 defines are give by -D definex instead of + * /Ddefinex, 2 args not 1! since we implement this ourslefs, we do not + * have to implement the getDefineSwitch() and the getUndefineSwitch(). + */ + protected void buildDefineArguments(CompilerDef[] defs, Vector args) { + // + // assume that we aren't inheriting defines from containing + // + UndefineArgument[] merged = defs[0].getActiveDefines(); + for (int i = 1; i < defs.length; i++) { + // + // if we are inheriting, merge the specific defines with the + // containing defines + merged = DefineArgument.merge(defs[i].getActiveDefines(), merged); + } + StringBuffer buf = new StringBuffer(30); + for (int i = 0; i < merged.length; i++) { + buf.setLength(0); + UndefineArgument current = merged[i]; + if (current.isDefine()) { + args.addElement("-D"); + buf.append(current.getName()); + if (current.getValue() != null + && current.getValue().length() > 0) { + buf.append('='); + buf.append(current.getValue()); + } + args.addElement(buf.toString()); + } else { + args.addElement("-U"); + args.addElement(current.getName()); + } + } + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new OS390CCompiler(newEnvironment, env); + } + return this; + } + /* + * @see CommandLineCompiler#getDefineSwitch(StringBuffer, String, String) + */ + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ":"); + } + protected String getIncludeDirSwitch(String includeDir) { + return OS390Processor.getIncludeDirSwitch(includeDir); + } + public Linker getLinker(LinkType type) { + return OS390Linker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + /* Only compile one file at time for now */ + protected int getMaximumInputFilesPerCommand() { + return Integer.MAX_VALUE; + } + /* + * @see CommandLineCompiler#getUndefineSwitch(StringBuffer, String) + */ + protected void getUndefineSwitch(StringBuffer buffer, String define) { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os390/OS390Linker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os390/OS390Linker.java new file mode 100644 index 0000000000..f6653b7be4 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os390/OS390Linker.java @@ -0,0 +1,201 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.os390; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +import org.apache.tools.ant.BuildException; +/** + * Adapter for the IBM (R) OS/390 (tm) Linker + * + * @author Hiram Chirino (cojonudo14@hotmail.com) + */ +public final class OS390Linker extends CommandLineLinker { + private static final OS390Linker datasetLinker = new OS390Linker(); + private static final OS390Linker dllLinker = new OS390Linker("", ".dll"); + private static final OS390Linker instance = new OS390Linker("", ""); + public static OS390Linker getDataSetInstance() { + return datasetLinker; + } + public static OS390Linker getInstance() { + return instance; + } + private boolean isADatasetLinker; + File outputFile; + private String outputPrefix; + CCTask task; + private OS390Linker() { + super("cxx", "/bogus", new String[]{".o", ".a", ".lib", ".xds"}, + new String[]{".dll", ".x"}, ".xds", false, null); + this.outputPrefix = ""; + this.isADatasetLinker = true; + } + private OS390Linker(String outputPrefix, String outputSuffix) { + super("cxx", "/bogus", new String[]{".o", ".a", ".lib", ".x"}, + new String[]{".dll"}, outputSuffix, false, null); + this.outputPrefix = outputPrefix; + this.isADatasetLinker = false; + } + protected void addBase(long base, Vector args) { + } + protected void addFixed(Boolean fixed, Vector args) { + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + if (linkType.isSharedLibrary()) { + args.addElement("-W"); + args.addElement("l,DLL"); + } + } + protected void addIncremental(boolean incremental, Vector args) { + } + /* + * @see CommandLineLinker#addLibrarySets(LibrarySet[], Vector, Vector, + * Vector) + */ + protected String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + // If yo want to link against a library sitting in a dataset and + // not in the HFS, you can just use the //'dataset' notation + // to specify it. e.g: + // + // + // We have to have special handling here because the file is not + // on the normal filesystem so the task will not noramly include it + // as part of the link command. + if (libsets != null) { + for (int i = 0; i < libsets.length; i++) { + String libs[] = libsets[i].getLibs(); + for (int j = 0; j < libs.length; j++) { + if (libs[j].startsWith("//")) { + endargs.addElement("-l"); + endargs.addElement(libs[j]); + } else if (libsets[i].getDataset() != null) { + String ds = libsets[i].getDataset(); + endargs.addElement("//'" + ds + "(" + libs[j] + ")'"); + } + } + } + } + return super.addLibrarySets(task, libsets, preargs, midargs, endargs); + } + protected void addMap(boolean map, Vector args) { + } + protected void addStack(int stack, Vector args) { + } + protected void addEntry(String entry, Vector args) { + } + + public String getCommandFileSwitch(String commandFile) { + return "@" + commandFile; + } + public File[] getLibraryPath() { + return CUtil.getPathFromEnvironment("LIB", ";"); + } + + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + StringBuffer buf = new StringBuffer(); + String[] patterns = new String[libnames.length * 3]; + int offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0); + offset = addLibraryPatterns(libnames, buf, "", ".x", patterns, offset); + offset = addLibraryPatterns(libnames, buf, "", ".o", patterns, offset); + return patterns; + } + + private static int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + + public Linker getLinker(LinkType linkType) { + if (this == datasetLinker) + return datasetLinker; + if (linkType.isSharedLibrary()) + return dllLinker; + return instance; + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + public String getOutputFileName(String baseName) { + return outputPrefix + super.getOutputFileName(baseName); + } + protected String[] getOutputFileSwitch(CCTask task, String outputFile) { + if (isADatasetLinker && task.getDataset() != null) { + String ds = task.getDataset(); + outputFile = "//'" + ds + "(" + outputFile + ")'"; + } + return getOutputFileSwitch(outputFile); + } + public String[] getOutputFileSwitch(String outputFile) { + return new String[]{"-o", outputFile}; + } + public boolean isCaseSensitive() { + return OS390Processor.isCaseSensitive(); + } + /* + * @see CommandLineLinker#link(Task, File, String[], + * CommandLineLinkerConfiguration) + */ + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + this.task = task; + this.outputFile = outputFile; + if (isADatasetLinker) { + int p = outputFile.getName().indexOf("."); + if (p >= 0) { + String newname = outputFile.getName().substring(0, p); + outputFile = new File(outputFile.getParent(), newname); + } + } + super.link(task, outputFile, sourceFiles, config); + } + /* + * @see CommandLineLinker#runCommand(Task, File, String[]) + */ + protected int runCommand(CCTask task, File workingDir, String[] cmdline) + throws BuildException { + int rc = super.runCommand(task, workingDir, cmdline); + // create the .xds file if everything was ok. + if (rc == 0) { + try { + outputFile.delete(); + new FileOutputStream(outputFile).close(); + } catch (IOException e) { + throw new BuildException(e.getMessage()); + } + } + return rc; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os390/OS390Processor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os390/OS390Processor.java new file mode 100644 index 0000000000..2c209dd6bb --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os390/OS390Processor.java @@ -0,0 +1,71 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.os390; +import java.util.Vector; +/** + * A add-in class for IBM (r) OS/390 compilers and linkers + * + * @author Hiram Chirino (cojonudo14@hotmail.com) + */ +public class OS390Processor { + public static void addWarningSwitch(Vector args, int level) { + switch (level) { + /* + * case 0: args.addElement("/W0"); break; + * + * case 1: args.addElement("/W1"); break; + * + * case 2: break; + * + * case 3: args.addElement("/W3"); break; + * + * case 4: args.addElement("/W4"); break; + */ + } + } + public static String getCommandFileSwitch(String cmdFile) { + StringBuffer buf = new StringBuffer("@"); + if (cmdFile.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(cmdFile); + buf.append('\"'); + } else { + buf.append(cmdFile); + } + return buf.toString(); + } + public static String getIncludeDirSwitch(String includeDir) { + return "-I" + includeDir; + } + public static String[] getOutputFileSwitch(String outPath) { + StringBuffer buf = new StringBuffer("-o "); + if (outPath.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(outPath); + buf.append('\"'); + } else { + buf.append(outPath); + } + String[] retval = new String[]{buf.toString()}; + return retval; + } + public static boolean isCaseSensitive() { + return true; + } + private OS390Processor() { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os400/IccCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os400/IccCompiler.java new file mode 100644 index 0000000000..f40858f71b --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os400/IccCompiler.java @@ -0,0 +1,124 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.os400; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.AbstractCompiler; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the IBM (R) OS/390 (tm) C++ Compiler + * + * @author Hiram Chirino (cojonudo14@hotmail.com) + */ +public class IccCompiler extends CommandLineCCompiler { + private static final AbstractCompiler instance = new IccCompiler(false, + null); + public static AbstractCompiler getInstance() { + return instance; + } + private IccCompiler(boolean newEnvironment, Environment env) { + super("icc", null, new String[]{".c", ".cc", ".cpp", ".cxx", ".c++", + ".s"}, new String[]{".h", ".hpp"}, ".o", false, null, + newEnvironment, env); + } + protected void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + // Specifies that only compilations and assemblies be done. + // Link-edit is not done + args.addElement("-c"); + /* + * if (exceptions) { args.addElement("/GX"); } + */ + if (debug) { + args.addElement("-g"); + /* + * args.addElement("-D"); args.addElement("_DEBUG"); if + * (multithreaded) { args.addElement("/D_MT"); if (staticLink) { + * args.addElement("/MTd"); } else { args.addElement("/MDd"); + * args.addElement("/D_DLL"); } } else { args.addElement("/MLd"); } + */ + } else { + /* + * args.addElement("-D"); args.addElement("NEBUG"); if + * (multithreaded) { args.addElement("/D_MT"); if (staticLink) { + * args.addElement("/MT"); } else { args.addElement("/MD"); + * args.addElement("/D_DLL"); } } else { args.addElement("/ML"); } + */ + } + } + protected void addWarningSwitch(Vector args, int level) { + IccProcessor.addWarningSwitch(args, level); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new IccCompiler(newEnvironment, env); + } + return this; + } + /* + * @see CommandLineCompiler#getDefineSwitch(StringBuffer, String, String) + */ + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + buffer.append("-q"); + buffer.append(define); + if (value != null && value.length() > 0) { + buffer.append('='); + buffer.append(value); + } + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ":"); + } + protected String getIncludeDirSwitch(String includeDir) { + return IccProcessor.getIncludeDirSwitch(includeDir); + } + public Linker getLinker(LinkType type) { + return IccLinker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + /* Only compile one file at time for now */ + protected int getMaximumInputFilesPerCommand() { + return 1; + //return Integer.MAX_VALUE; + } + /* + * @see CommandLineCompiler#getUndefineSwitch(StringBuffer, String) + */ + protected void getUndefineSwitch(StringBuffer buffer, String define) { + /* + * buffer.addElement("-q"); buf.append(define); + */ + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os400/IccLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os400/IccLinker.java new file mode 100644 index 0000000000..5e4e2f229a --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os400/IccLinker.java @@ -0,0 +1,202 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.os400; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinkerConfiguration; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; +import org.apache.tools.ant.BuildException; +/** + * Adapter for the IBM (R) OS/390 (tm) Linker + * + * @author Hiram Chirino (cojonudo14@hotmail.com) + */ +public final class IccLinker extends CommandLineLinker { + private static final IccLinker datasetLinker = new IccLinker(); + private static final IccLinker dllLinker = new IccLinker("", ".dll"); + private static final IccLinker instance = new IccLinker("", ""); + public static IccLinker getDataSetInstance() { + return datasetLinker; + } + public static IccLinker getInstance() { + return instance; + } + private boolean isADatasetLinker; + File outputFile; + private String outputPrefix; + CCTask task; + private IccLinker() { + super("icc", "/bogus", new String[]{".o", ".a", ".lib", ".xds"}, + new String[]{".dll", ".x"}, ".xds", false, null); + this.outputPrefix = ""; + this.isADatasetLinker = true; + } + private IccLinker(String outputPrefix, String outputSuffix) { + super("icc", "/bogus", new String[]{".o", ".a", ".lib", ".x"}, + new String[]{".dll"}, outputSuffix, false, null); + this.outputPrefix = outputPrefix; + this.isADatasetLinker = false; + } + protected void addBase(long base, Vector args) { + } + protected void addFixed(Boolean fixed, Vector args) { + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + if (linkType.isSharedLibrary()) { + args.addElement("-W"); + args.addElement("l,DLL"); + } + } + protected void addIncremental(boolean incremental, Vector args) { + } + /* + * @see CommandLineLinker#addLibrarySets(LibrarySet[], Vector, Vector, + * Vector) + */ + protected String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + // If yo want to link against a library sitting in a dataset and + // not in the HFS, you can just use the //'dataset' notation + // to specify it. e.g: + // + // + // We have to have special handling here because the file is not + // on the normal filesystem so the task will not noramly include it + // as part of the link command. + if (libsets != null) { + for (int i = 0; i < libsets.length; i++) { + String libs[] = libsets[i].getLibs(); + for (int j = 0; j < libs.length; j++) { + if (libs[j].startsWith("//")) { + endargs.addElement("-l"); + endargs.addElement(libs[j]); + } else if (libsets[i].getDataset() != null) { + String ds = libsets[i].getDataset(); + endargs.addElement("//'" + ds + "(" + libs[j] + ")'"); + } + } + } + } + return super.addLibrarySets(task, libsets, preargs, midargs, endargs); + } + protected void addMap(boolean map, Vector args) { + } + protected void addStack(int stack, Vector args) { + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + public String getCommandFileSwitch(String commandFile) { + return "@" + commandFile; + } + public File[] getLibraryPath() { + return CUtil.getPathFromEnvironment("LIB", ";"); + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + StringBuffer buf = new StringBuffer(); + String[] patterns = new String[libnames.length * 3]; + int offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0); + offset = addLibraryPatterns(libnames, buf, "", ".x", patterns, offset); + offset = addLibraryPatterns(libnames, buf, "", ".o", patterns, offset); + return patterns; + } + + private static int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + + + public Linker getLinker(LinkType linkType) { + if (this == datasetLinker) + return datasetLinker; + if (linkType.isSharedLibrary()) + return dllLinker; + return instance; + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + protected String[] getOutputFileSwitch(CCTask task, String outputFile) { + if (isADatasetLinker && task.getDataset() != null) { + String ds = task.getDataset(); + outputFile = "//'" + ds + "(" + outputFile + ")'"; + } + return getOutputFileSwitch(outputFile); + } + public String[] getOutputFileSwitch(String outputFile) { + return new String[]{"-o", outputFile}; + } + public boolean isCaseSensitive() { + return IccProcessor.isCaseSensitive(); + } + /* + * @see CommandLineLinker#link(Task, File, String[], + * CommandLineLinkerConfiguration) + */ + public void link(CCTask task, File outputFile, String[] sourceFiles, + CommandLineLinkerConfiguration config) throws BuildException { + this.task = task; + this.outputFile = outputFile; + if (isADatasetLinker) { + int p = outputFile.getName().indexOf("."); + if (p >= 0) { + String newname = outputFile.getName().substring(0, p); + outputFile = new File(outputFile.getParent(), newname); + } + } + super.link(task, outputFile, sourceFiles, config); + } + /* + * @see CommandLineLinker#runCommand(Task, File, String[]) + */ + protected int runCommand(CCTask task, File workingDir, String[] cmdline) + throws BuildException { + int rc = super.runCommand(task, workingDir, cmdline); + // create the .xds file if everything was ok. + if (rc == 0) { + try { + outputFile.delete(); + new FileOutputStream(outputFile).close(); + } catch (IOException e) { + throw new BuildException(e.getMessage()); + } + } + return rc; + } + public String xgetOutputFileName(String baseName) { + return outputPrefix + super.getOutputFileName(baseName); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os400/IccProcessor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os400/IccProcessor.java new file mode 100644 index 0000000000..4cc7b36ab3 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/os400/IccProcessor.java @@ -0,0 +1,71 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.os400; +import java.util.Vector; +/** + * A add-in class for IBM (r) OS/390 compilers and linkers + * + * @author Hiram Chirino (cojonudo14@hotmail.com) + */ +public class IccProcessor { + public static void addWarningSwitch(Vector args, int level) { + switch (level) { + /* + * case 0: args.addElement("/W0"); break; + * + * case 1: args.addElement("/W1"); break; + * + * case 2: break; + * + * case 3: args.addElement("/W3"); break; + * + * case 4: args.addElement("/W4"); break; + */ + } + } + public static String getCommandFileSwitch(String cmdFile) { + StringBuffer buf = new StringBuffer("@"); + if (cmdFile.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(cmdFile); + buf.append('\"'); + } else { + buf.append(cmdFile); + } + return buf.toString(); + } + public static String getIncludeDirSwitch(String includeDir) { + return "-I" + includeDir; + } + public static String[] getOutputFileSwitch(String outPath) { + StringBuffer buf = new StringBuffer("-o "); + if (outPath.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(outPath); + buf.append('\"'); + } else { + buf.append(outPath); + } + String[] retval = new String[]{buf.toString()}; + return retval; + } + public static boolean isCaseSensitive() { + return true; + } + private IccProcessor() { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/AbstractParser.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/AbstractParser.java new file mode 100644 index 0000000000..6f0b79c072 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/AbstractParser.java @@ -0,0 +1,67 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; +import java.io.IOException; +import java.io.Reader; +/** + * An abstract base class for simple parsers + * + * @author Curt Arnold + */ +public abstract class AbstractParser { + /** + * + * + */ + protected AbstractParser() { + } + protected abstract void addFilename(String filename); + public abstract AbstractParserState getNewLineState(); + protected void parse(Reader reader) throws IOException { + char[] buf = new char[4096]; + AbstractParserState newLineState = getNewLineState(); + AbstractParserState state = newLineState; + int charsRead = -1; + do { + charsRead = reader.read(buf, 0, buf.length); + if (state == null) { + for (int i = 0; i < charsRead; i++) { + if (buf[i] == '\n') { + state = newLineState; + break; + } + } + } + if (state != null) { + for (int i = 0; i < charsRead; i++) { + state = state.consume(buf[i]); + // + // didn't match a production, skip to a new line + // + if (state == null) { + for (; i < charsRead; i++) { + if (buf[i] == '\n') { + state = newLineState; + break; + } + } + } + } + } + } while (charsRead >= 0); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/AbstractParserState.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/AbstractParserState.java new file mode 100644 index 0000000000..fe66dbbef0 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/AbstractParserState.java @@ -0,0 +1,41 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; +/** + * An base class for objects that represent the state of an AbstractParser. + * + * @author CurtArnold + * @see AbstractParser + */ +public abstract class AbstractParserState { + private AbstractParser parser; + protected AbstractParserState(AbstractParser parser) { + if (parser == null) { + throw new NullPointerException("parser"); + } + this.parser = parser; + } + /** + * Consume a character + * + * @return new state, may be null to ignore the rest of the line + */ + public abstract AbstractParserState consume(char ch); + protected AbstractParser getParser() { + return parser; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/BranchState.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/BranchState.java new file mode 100644 index 0000000000..370c7d5836 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/BranchState.java @@ -0,0 +1,46 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; +public class BranchState extends AbstractParserState { + private char[] branchChars; + private AbstractParserState[] branchStates; + private AbstractParserState noMatchState; + public BranchState(AbstractParser parser, char[] branchChars, + AbstractParserState[] branchStates, AbstractParserState noMatchState) { + super(parser); + this.branchChars = (char[]) branchChars.clone(); + this.branchStates = (AbstractParserState[]) branchStates.clone(); + this.noMatchState = noMatchState; + } + public AbstractParserState consume(char ch) { + AbstractParserState state; + for (int i = 0; i < branchChars.length; i++) { + if (ch == branchChars[i]) { + state = branchStates[i]; + return state.consume(ch); + } + } + state = getNoMatchState(); + if (state != null) { + return state.consume(ch); + } + return state; + } + protected AbstractParserState getNoMatchState() { + return noMatchState; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/CParser.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/CParser.java new file mode 100644 index 0000000000..07f8eba4e2 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/CParser.java @@ -0,0 +1,78 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; +import java.io.IOException; +import java.io.Reader; +import java.util.Vector; +/** + * A parser that extracts #include statements from a Reader. + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public final class CParser extends AbstractParser implements Parser { + private final Vector includes = new Vector(); + private AbstractParserState newLineState; + /** + * + * + */ + public CParser() { + AbstractParserState quote = new FilenameState(this, new char[]{'"'}); + AbstractParserState bracket = new FilenameState(this, new char[]{'>'}); + AbstractParserState postE = new PostE(this, bracket, quote); + // + // nclude + // + AbstractParserState e = new LetterState(this, 'e', postE, null); + AbstractParserState d = new LetterState(this, 'd', e, null); + AbstractParserState u = new LetterState(this, 'u', d, null); + AbstractParserState l = new LetterState(this, 'l', u, null); + AbstractParserState c = new LetterState(this, 'c', l, null); + AbstractParserState n = new LetterState(this, 'n', c, null); + // + // mport is equivalent to nclude + // + AbstractParserState t = new LetterState(this, 't', postE, null); + AbstractParserState r = new LetterState(this, 'r', t, null); + AbstractParserState o = new LetterState(this, 'o', r, null); + AbstractParserState p = new LetterState(this, 'p', o, null); + AbstractParserState m = new LetterState(this, 'm', p, null); + // + // switch between + // + AbstractParserState n_m = new BranchState(this, new char[]{'n', 'm'}, + new AbstractParserState[]{n, m}, null); + AbstractParserState i = new WhitespaceOrLetterState(this, 'i', n_m); + newLineState = new LetterState(this, '#', i, null); + } + public void addFilename(String include) { + includes.addElement(include); + } + public String[] getIncludes() { + String[] retval = new String[includes.size()]; + includes.copyInto(retval); + return retval; + } + public AbstractParserState getNewLineState() { + return newLineState; + } + public void parse(Reader reader) throws IOException { + includes.setSize(0); + super.parse(reader); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/CaseInsensitiveLetterState.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/CaseInsensitiveLetterState.java new file mode 100644 index 0000000000..a86700f166 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/CaseInsensitiveLetterState.java @@ -0,0 +1,87 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; + +/** + * This parser state checks consumed characters against a specific character + * (case insensitive). + * + * @author Curt Arnold + */ +public final class CaseInsensitiveLetterState + extends AbstractParserState { + /** + * Next state if a match is found. + */ + private final AbstractParserState nextState; + + /** + * Next state if not match is found. + */ + private final AbstractParserState noMatchState; + + /** + * Lower case version of character to match. + */ + private final char lowerLetter; + + /** + * Lower case version of character to match. + */ + private final char upperLetter; + + /** + * Constructor. + * + * @param parser + * parser + * @param matchLetter + * letter to match + * @param nextStateArg + * next state if a match on the letter + * @param noMatchStateArg + * state if no match on letter + */ + public CaseInsensitiveLetterState(final AbstractParser parser, + final char matchLetter, + final AbstractParserState nextStateArg, + final AbstractParserState noMatchStateArg) { + super(parser); + this.lowerLetter = Character.toLowerCase(matchLetter); + this.upperLetter = Character.toUpperCase(matchLetter); + this.nextState = nextStateArg; + this.noMatchState = noMatchStateArg; + } + + /** + * Consumes a character and returns the next state for the parser. + * + * @param ch + * next character + * @return the configured nextState if ch is the expected character or the + * configure noMatchState otherwise. + */ + public AbstractParserState consume(final char ch) { + if (ch == lowerLetter || ch == upperLetter) { + return nextState; + } + if (ch == '\n') { + getParser().getNewLineState(); + } + return noMatchState; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/FilenameState.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/FilenameState.java new file mode 100644 index 0000000000..f33940b0a7 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/FilenameState.java @@ -0,0 +1,41 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; +public class FilenameState extends AbstractParserState { + private final StringBuffer buf = new StringBuffer(); + private final char[] terminators; + public FilenameState(AbstractParser parser, char[] terminators) { + super(parser); + this.terminators = (char[]) terminators.clone(); + } + public AbstractParserState consume(char ch) { + for (int i = 0; i < terminators.length; i++) { + if (ch == terminators[i]) { + getParser().addFilename(buf.toString()); + buf.setLength(0); + return null; + } + } + if (ch == '\n') { + buf.setLength(0); + return getParser().getNewLineState(); + } else { + buf.append(ch); + } + return this; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/FortranParser.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/FortranParser.java new file mode 100644 index 0000000000..261e95ad81 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/FortranParser.java @@ -0,0 +1,106 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; + +import java.io.IOException; +import java.io.Reader; +import java.util.Vector; + +/** + * A parser that extracts INCLUDE statements from a Reader. + * + * @author Curt Arnold + */ +public final class FortranParser + extends AbstractParser + implements Parser { + /** + * List of included filenames. + */ + private final Vector includes = new Vector(); + + /** + * State that starts consuming content at the beginning of a line. + */ + private final AbstractParserState newLineState; + + /** + * Default constructor. + * + */ + public FortranParser() { + AbstractParserState filename = new FilenameState(this, new char[] {'\'', + '/'}); + AbstractParserState apos = new WhitespaceOrLetterState(this, '\'', + filename); + AbstractParserState blank = new LetterState(this, ' ', apos, null); + AbstractParserState e = new CaseInsensitiveLetterState(this, 'E', + blank, null); + AbstractParserState d = new CaseInsensitiveLetterState(this, 'D', e, + null); + AbstractParserState u = new CaseInsensitiveLetterState(this, 'U', d, + null); + AbstractParserState l = new CaseInsensitiveLetterState(this, 'L', u, + null); + AbstractParserState c = new CaseInsensitiveLetterState(this, 'C', l, + null); + AbstractParserState n = new CaseInsensitiveLetterState(this, 'N', c, + null); + newLineState = new WhitespaceOrCaseInsensitiveLetterState(this, 'I', n); + } + + /** + * Called by FilenameState at completion of file name production. + * + * @param include + * include file name + */ + public void addFilename(final String include) { + includes.addElement(include); + } + + /** + * Gets collection of include file names encountered in parse. + * @return include file names + */ + public String[] getIncludes() { + String[] retval = new String[includes.size()]; + includes.copyInto(retval); + return retval; + } + + /** + * Get the state for the beginning of a new line. + * @return start of line state + */ + public AbstractParserState getNewLineState() { + return newLineState; + } + + /** + * Collects all included files from the content of the reader. + * + * @param reader + * character reader containing a FORTRAN source module + * @throws IOException + * throw if I/O error during parse + */ + public void parse(final Reader reader) throws IOException { + includes.setSize(0); + super.parse(reader); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/LetterState.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/LetterState.java new file mode 100644 index 0000000000..945ae91233 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/LetterState.java @@ -0,0 +1,80 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; + +/** + * This parser state checks consumed characters against a specific character. + * + * @author Curt Arnold + */ +public final class LetterState + extends AbstractParserState { + /** + * Next state if a match is found. + */ + private final AbstractParserState nextState; + + /** + * Next state if not match is found. + */ + private final AbstractParserState noMatchState; + + /** + * Character to match. + */ + private final char thisLetter; + + /** + * Constructor. + * + * @param parser + * parser + * @param matchLetter + * letter to match + * @param nextStateArg + * next state if a match on the letter + * @param noMatchStateArg + * state if no match on letter + */ + public LetterState(final AbstractParser parser, + final char matchLetter, + final AbstractParserState nextStateArg, + final AbstractParserState noMatchStateArg) { + super(parser); + this.thisLetter = matchLetter; + this.nextState = nextStateArg; + this.noMatchState = noMatchStateArg; + } + + /** + * Consumes a character and returns the next state for the parser. + * + * @param ch + * next character + * @return the configured nextState if ch is the expected character or the + * configure noMatchState otherwise. + */ + public AbstractParserState consume(final char ch) { + if (ch == thisLetter) { + return nextState; + } + if (ch == '\n') { + getParser().getNewLineState(); + } + return noMatchState; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/Parser.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/Parser.java new file mode 100644 index 0000000000..cf759fc7d5 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/Parser.java @@ -0,0 +1,28 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; +import java.io.IOException; +import java.io.Reader; +/** + * A parser that extracts #include statements from a Reader. + * + * @author Curt Arnold + */ +public interface Parser { + String[] getIncludes(); + void parse(Reader reader) throws IOException; +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/PostE.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/PostE.java new file mode 100644 index 0000000000..fe225fb35a --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/PostE.java @@ -0,0 +1,41 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; +public class PostE extends AbstractParserState { + private AbstractParserState bracket; + private AbstractParserState quote; + public PostE(CParser parser, AbstractParserState bracket, + AbstractParserState quote) { + super(parser); + this.bracket = bracket; + this.quote = quote; + } + public AbstractParserState consume(char ch) { + switch (ch) { + case ' ' : + case '\t' : + return this; + case '<' : + return bracket; + case '"' : + return quote; + case '\n' : + return getParser().getNewLineState(); + } + return null; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/WhitespaceOrCaseInsensitiveLetterState.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/WhitespaceOrCaseInsensitiveLetterState.java new file mode 100644 index 0000000000..9d42feeaad --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/WhitespaceOrCaseInsensitiveLetterState.java @@ -0,0 +1,83 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; + +/** + * This parser state checks consumed characters against a specific character + * (case insensitive) or whitespace. + * + * @author Curt Arnold + */ +public final class WhitespaceOrCaseInsensitiveLetterState + extends + AbstractParserState { + /** + * Next state if the character is found. + */ + private final AbstractParserState nextState; + + /** + * Character to match (lower case). + */ + private final char lowerLetter; + + /** + * Character to match (upper case). + */ + private final char upperLetter; + + /** + * Constructor. + * + * @param parser + * parser + * @param matchLetter + * letter to match + * @param nextStateArg + * next state if a match on the letter + */ + public WhitespaceOrCaseInsensitiveLetterState(final AbstractParser parser, + final char matchLetter, + final AbstractParserState + nextStateArg) { + super(parser); + this.lowerLetter = Character.toLowerCase(matchLetter); + this.upperLetter = Character.toUpperCase(matchLetter); + this.nextState = nextStateArg; + } + + /** + * Consumes a character and returns the next state for the parser. + * + * @param ch + * next character + * @return the configured nextState if ch is the expected character or the + * configure noMatchState otherwise. + */ + public AbstractParserState consume(final char ch) { + if (ch == lowerLetter || ch == upperLetter) { + return nextState; + } + if (ch == ' ' || ch == '\t') { + return this; + } + if (ch == '\n') { + getParser().getNewLineState(); + } + return null; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/WhitespaceOrLetterState.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/WhitespaceOrLetterState.java new file mode 100644 index 0000000000..824abe6b68 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/parser/WhitespaceOrLetterState.java @@ -0,0 +1,75 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.parser; + +/** + * This parser state checks consumed characters against a specific character or + * whitespace. + * + * @author Curt Arnold + */ +public final class WhitespaceOrLetterState + extends AbstractParserState { + /** + * Next state if the character is found. + */ + private final AbstractParserState nextState; + + /** + * Character to match. + */ + private final char thisLetter; + + /** + * Constructor. + * + * @param parser + * parser + * @param matchLetter + * letter to match + * @param nextStateArg + * next state if a match on the letter + */ + public WhitespaceOrLetterState(final AbstractParser parser, + final char matchLetter, + final AbstractParserState nextStateArg) { + super(parser); + this.thisLetter = matchLetter; + this.nextState = nextStateArg; + } + + /** + * Consumes a character and returns the next state for the parser. + * + * @param ch + * next character @returns the configured nextState if ch is the + * expected character or the configure noMatchState otherwise. + * @return next state + */ + public AbstractParserState consume(final char ch) { + if (ch == thisLetter) { + return nextState; + } + if (ch == ' ' || ch == '\t') { + return this; + } + if (ch == '\n') { + getParser().getNewLineState(); + } + return null; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/C89CCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/C89CCompiler.java new file mode 100644 index 0000000000..6679c239dd --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/C89CCompiler.java @@ -0,0 +1,109 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.sun; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.AbstractCompiler; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.compiler.Processor; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for the Sun C89 C++ Compiler + * + * @author Hiram Chirino (cojonudo14@hotmail.com) + */ +public class C89CCompiler extends CommandLineCCompiler { + private static final AbstractCompiler instance = new C89CCompiler(false, + null); + public static AbstractCompiler getInstance() { + return instance; + } + private C89CCompiler(boolean newEnvironment, Environment env) { + super("c89", null, new String[]{".c", ".cc", ".cpp", ".cxx", ".c++"}, + new String[]{".h", ".hpp"}, ".o", false, null, newEnvironment, + env); + } + protected void addImpliedArgs( + final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + // Specifies that only compilations and assemblies be done. + args.addElement("-c"); + /* + * if (exceptions) { args.addElement("/GX"); } + */ + if (debug) { + args.addElement("-g"); + args.addElement("-D_DEBUG"); + /* + * if (multithreaded) { args.addElement("/D_MT"); if (staticLink) { + * args.addElement("/MTd"); } else { args.addElement("/MDd"); + * args.addElement("/D_DLL"); } } else { args.addElement("/MLd"); } + */ + } else { + args.addElement("-DNDEBUG"); + /* + * if (multithreaded) { args.addElement("/D_MT"); if (staticLink) { + * args.addElement("/MT"); } else { args.addElement("/MD"); + * args.addElement("/D_DLL"); } } else { args.addElement("/ML"); } + */ + } + } + protected void addWarningSwitch(Vector args, int level) { + C89Processor.addWarningSwitch(args, level); + } + public Processor changeEnvironment(boolean newEnvironment, Environment env) { + if (newEnvironment || env != null) { + return new C89CCompiler(newEnvironment, env); + } + return this; + } + protected void getDefineSwitch(StringBuffer buf, String define, String value) { + C89Processor.getDefineSwitch(buf, define, value); + } + protected File[] getEnvironmentIncludePath() { + return CUtil.getPathFromEnvironment("INCLUDE", ":"); + } + protected String getIncludeDirSwitch(String includeDir) { + return C89Processor.getIncludeDirSwitch(includeDir); + } + public Linker getLinker(LinkType type) { + return C89Linker.getInstance().getLinker(type); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + /* Only compile one file at time for now */ + protected int getMaximumInputFilesPerCommand() { + return 1; + } + protected void getUndefineSwitch(StringBuffer buf, String define) { + C89Processor.getUndefineSwitch(buf, define); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/C89Linker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/C89Linker.java new file mode 100644 index 0000000000..37b3950bbe --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/C89Linker.java @@ -0,0 +1,125 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.sun; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.types.LibrarySet; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * Adapter for the Sun C89 Linker + * + * @author Hiram Chirino (cojonudo14@hotmail.com) + */ +public final class C89Linker extends CommandLineLinker { + private static final C89Linker dllLinker = new C89Linker("lib", ".so"); + private static final C89Linker instance = new C89Linker("", ""); + public static C89Linker getInstance() { + return instance; + } + private String outputPrefix; + private C89Linker(String outputPrefix, String outputSuffix) { + super("ld", "/bogus", new String[]{".o", ".a", ".lib", ".x"}, + new String[]{}, outputSuffix, false, null); + this.outputPrefix = outputPrefix; + } + protected void addBase(long base, Vector args) { + } + protected void addFixed(Boolean fixed, Vector args) { + } + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + if (linkType.isSharedLibrary()) { + args.addElement("-G"); + } + } + protected void addIncremental(boolean incremental, Vector args) { + } + public String[] addLibrarySets(CCTask task, LibrarySet[] libsets, + Vector preargs, Vector midargs, Vector endargs) { + super.addLibrarySets(task, libsets, preargs, midargs, endargs); + StringBuffer buf = new StringBuffer("-l"); + for (int i = 0; i < libsets.length; i++) { + LibrarySet set = libsets[i]; + File libdir = set.getDir(null); + String[] libs = set.getLibs(); + if (libdir != null) { + endargs.addElement("-L"); + endargs.addElement(libdir.getAbsolutePath()); + } + for (int j = 0; j < libs.length; j++) { + // + // reset the buffer to just "-l" + // + buf.setLength(2); + // + // add the library name + buf.append(libs[j]); + // + // add the argument to the list + endargs.addElement(buf.toString()); + } + } + return null; + } + protected void addMap(boolean map, Vector args) { + } + protected void addStack(int stack, Vector args) { + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + public String getCommandFileSwitch(String commandFile) { + return "@" + commandFile; + } + public File[] getLibraryPath() { + return CUtil.getPathFromEnvironment("LIB", ";"); + } + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + return C89Processor.getLibraryPatterns(libnames, libType); + } + public Linker getLinker(LinkType linkType) { + if (linkType.isSharedLibrary()) { + return dllLinker; + } + /* + * if(linkType.isStaticLibrary()) { return + * OS390Librarian.getInstance(); } + */ + return instance; + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } + public String getOutputFileName(String baseName) { + return outputPrefix + super.getOutputFileName(baseName); + } + public String[] getOutputFileSwitch(String outputFile) { + return new String[]{"-o", outputFile}; + } + public boolean isCaseSensitive() { + return C89Processor.isCaseSensitive(); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/C89Processor.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/C89Processor.java new file mode 100644 index 0000000000..c54c866966 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/C89Processor.java @@ -0,0 +1,116 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.sun; +import java.util.Vector; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * A add-in class for Sun C89 compilers and linkers + * + * @author Hiram Chirino (cojonudo14@hotmail.com) + */ +public class C89Processor { + private static int addLibraryPatterns(String[] libnames, StringBuffer buf, + String prefix, String extension, String[] patterns, int offset) { + for (int i = 0; i < libnames.length; i++) { + buf.setLength(0); + buf.append(prefix); + buf.append(libnames[i]); + buf.append(extension); + patterns[offset + i] = buf.toString(); + } + return offset + libnames.length; + } + public static void addWarningSwitch(Vector args, int level) { + switch (level) { + /* + * case 0: args.addElement("/W0"); break; + * + * case 1: args.addElement("/W1"); break; + * + * case 2: break; + * + * case 3: args.addElement("/W3"); break; + * + * case 4: args.addElement("/W4"); break; + */ + } + } + public static String getCommandFileSwitch(String cmdFile) { + StringBuffer buf = new StringBuffer("@"); + if (cmdFile.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(cmdFile); + buf.append('\"'); + } else { + buf.append(cmdFile); + } + return buf.toString(); + } + public static void getDefineSwitch(StringBuffer buf, String define, + String value) { + buf.setLength(0); + buf.append("-D"); + buf.append(define); + if (value != null && value.length() > 0) { + buf.append('='); + buf.append(value); + } + } + public static String getIncludeDirSwitch(String includeDir) { + return "-I" + includeDir; + } + public static String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + StringBuffer buf = new StringBuffer(); + int patternCount = libnames.length*2; + if (libType != null) { + patternCount = libnames.length; + } + String[] patterns = new String[patternCount]; + int offset = 0; + if (libType == null || "static".equals(libType.getValue())) { + offset = addLibraryPatterns(libnames, buf, "lib", ".a", patterns, 0); + } + if (libType == null || !"static".equals(libType.getValue())) { + offset = addLibraryPatterns(libnames, buf, "lib", ".so", patterns, + offset); + } + return patterns; + } + public static String[] getOutputFileSwitch(String outPath) { + StringBuffer buf = new StringBuffer("-o "); + if (outPath.indexOf(' ') >= 0) { + buf.append('\"'); + buf.append(outPath); + buf.append('\"'); + } else { + buf.append(outPath); + } + String[] retval = new String[]{buf.toString()}; + return retval; + } + public static void getUndefineSwitch(StringBuffer buf, String define) { + buf.setLength(0); + buf.append("-U"); + buf.append(define); + } + public static boolean isCaseSensitive() { + return true; + } + private C89Processor() { + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/ForteCCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/ForteCCCompiler.java new file mode 100644 index 0000000000..a35d01af49 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/ForteCCCompiler.java @@ -0,0 +1,119 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.sun; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.GccCompatibleCCompiler; +import net.sf.antcontrib.cpptasks.OptimizationEnum; +/** + * Adapter for the Sun (r) Forte (tm) C++ compiler + * + * @author Curt Arnold + */ +public final class ForteCCCompiler extends GccCompatibleCCompiler { + private static final ForteCCCompiler instance = new ForteCCCompiler("CC"); + /** + * Gets singleton instance of this class + */ + public static ForteCCCompiler getInstance() { + return instance; + } + private String identifier; + private File[] includePath; + /** + * Private constructor. Use ForteCCCompiler.getInstance() to get singleton + * instance of this class. + */ + private ForteCCCompiler(String command) { + super(command, "-V", false, null, false, null); + } + public void addImpliedArgs(final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization) { + args.addElement("-c"); + if (debug) { + args.addElement("-g"); + } + if (optimization != null) { + if (optimization.isSpeed()) { + args.addElement("-xO2"); + } + } + if (rtti != null) { + if (rtti.booleanValue()) { + args.addElement("-features=rtti"); + } else { + args.addElement("-features=no%rtti"); + } + } + if (multithreaded) { + args.addElement("-mt"); + } + if (linkType.isSharedLibrary()) { + args.addElement("-KPIC"); + } + + } + public void addWarningSwitch(Vector args, int level) { + switch (level) { + case 0 : + args.addElement("-w"); + break; + case 1 : + case 2 : + args.addElement("+w"); + break; + case 3 : + case 4 : + case 5 : + args.addElement("+w2"); + break; + } + } + public File[] getEnvironmentIncludePath() { + if (includePath == null) { + File ccLoc = CUtil.getExecutableLocation("CC"); + if (ccLoc != null) { + File compilerIncludeDir = new File( + new File(ccLoc, "../include").getAbsolutePath()); + if (compilerIncludeDir.exists()) { + includePath = new File[2]; + includePath[0] = compilerIncludeDir; + } + } + if (includePath == null) { + includePath = new File[1]; + } + includePath[includePath.length - 1] = new File("/usr/include"); + } + return includePath; + } + public Linker getLinker(LinkType linkType) { + return ForteCCLinker.getInstance().getLinker(linkType); + } + public int getMaximumCommandLength() { + return Integer.MAX_VALUE; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/ForteCCLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/ForteCCLinker.java new file mode 100644 index 0000000000..c39071af9f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/sun/ForteCCLinker.java @@ -0,0 +1,100 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.sun; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.gcc.AbstractLdLinker; +/** + * Adapter for Sun (r) Forte(tm) C++ Linker + * + * @author Curt Arnold + */ +public final class ForteCCLinker extends AbstractLdLinker { + private static final String[] discardFiles = new String[]{".dll", ".so", + ".sl"}; + private static final String[] objFiles = new String[]{".o", ".a", ".lib"}; + private static final ForteCCLinker arLinker = new ForteCCLinker("CC", + objFiles, discardFiles, "lib", ".a"); + private static final ForteCCLinker dllLinker = new ForteCCLinker("CC", + objFiles, discardFiles, "lib", ".so"); + private static final ForteCCLinker instance = new ForteCCLinker("CC", + objFiles, discardFiles, "", ""); + public static ForteCCLinker getInstance() { + return instance; + } + private File[] libDirs; + private ForteCCLinker(String command, String[] extensions, + String[] ignoredExtensions, String outputPrefix, String outputSuffix) { + super(command, "-V", extensions, ignoredExtensions, outputPrefix, + outputSuffix, false, null); + } + public void addImpliedArgs(boolean debug, LinkType linkType, Vector args) { + if (debug) { + args.addElement("-g"); + } + if (linkType.isStaticRuntime()) { + args.addElement("-static"); + } + if (linkType.isSharedLibrary()) { + args.addElement("-G"); + } + if (linkType.isStaticLibrary()) { + args.addElement("-xar"); + } + } + public void addIncremental(boolean incremental, Vector args) { + /* + * if (incremental) { args.addElement("-xidlon"); } else { + * args.addElement("-xidloff"); } + */ + } + /** + * Returns library path. + * + */ + public File[] getLibraryPath() { + if (libDirs == null) { + File CCloc = CUtil.getExecutableLocation("CC"); + if (CCloc != null) { + File compilerLib = new File(new File(CCloc, "../lib") + .getAbsolutePath()); + if (compilerLib.exists()) { + libDirs = new File[2]; + libDirs[0] = compilerLib; + } + } + if (libDirs == null) { + libDirs = new File[1]; + } + } + libDirs[libDirs.length - 1] = new File("/usr/lib"); + return libDirs; + } + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + return arLinker; + } + if (type.isSharedLibrary()) { + return dllLinker; + } + return instance; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ti/ClxxCCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ti/ClxxCCompiler.java new file mode 100644 index 0000000000..d08b9fbbf6 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ti/ClxxCCompiler.java @@ -0,0 +1,192 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.ti; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.compiler.CommandLineCCompiler; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.OptimizationEnum; + + +import org.apache.tools.ant.types.Environment; +/** + * Adapter for TI DSP compilers with cl** commands + * + * @author CurtA + */ +public class ClxxCCompiler extends CommandLineCCompiler { + /** + * Header file extensions + */ + private static final String[] headerExtensions = new String[]{".h", ".hpp", + ".inl"}; + /** + * Source file extensions + */ + private static final String[] sourceExtensions = new String[]{".c", ".cc", + ".cpp", ".cxx", ".c++"}; + /** + * Singleton for TMS320C55x + */ + private static final ClxxCCompiler cl55 = new ClxxCCompiler("cl55", false, + null); + /** + * Singleton for TMS320C6000 + */ + private static final ClxxCCompiler cl6x = new ClxxCCompiler("cl6x", false, + null); + public static ClxxCCompiler getCl55Instance() { + return cl55; + } + public static ClxxCCompiler getCl6xInstance() { + return cl6x; + } + /** + * Private constructor + * + * @param command + * executable name + * @param newEnvironment + * Change environment + * @param env + * New environment + */ + private ClxxCCompiler(String command, boolean newEnvironment, + Environment env) { + super(command, "-h", sourceExtensions, headerExtensions, ".o", false, + null, newEnvironment, env); + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#addImpliedArgs(java.util.Vector, + * boolean, boolean, boolean, + * net.sf.antcontrib.cpptasks.compiler.LinkType) + */ + protected void addImpliedArgs( + final Vector args, + final boolean debug, + final boolean multithreaded, + final boolean exceptions, + final LinkType linkType, + final Boolean rtti, + final OptimizationEnum optimization, + final Boolean defaultflag) { + if (debug) { + args.addElement("-gw"); + } + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#addWarningSwitch(java.util.Vector, + * int) + */ + protected void addWarningSwitch(Vector args, int warnings) { + // TODO Auto-generated method stub + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#getDefineSwitch(java.lang.StringBuffer, + * java.lang.String, java.lang.String) + */ + protected void getDefineSwitch(StringBuffer buffer, String define, + String value) { + buffer.append("-d"); + buffer.append(define); + if (value != null) { + buffer.append('='); + buffer.append(value); + } + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#getEnvironmentIncludePath() + */ + protected File[] getEnvironmentIncludePath() { + File[] c_dir = CUtil.getPathFromEnvironment("C_DIR", ";"); + File[] cx_dir = CUtil.getPathFromEnvironment("C6X_C_DIR", ";"); + if (c_dir.length == 0) { + return cx_dir; + } + if (cx_dir.length == 0) { + return c_dir; + } + File[] combo = new File[c_dir.length + cx_dir.length]; + for (int i = 0; i < cx_dir.length; i++) { + combo[i] = cx_dir[i]; + } + for (int i = 0; i < c_dir.length; i++) { + combo[i + cx_dir.length] = c_dir[i]; + } + return combo; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#getIncludeDirSwitch(java.lang.String) + */ + protected String getIncludeDirSwitch(String source) { + return "-I" + source; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Processor#getLinker(net.sf.antcontrib.cpptasks.compiler.LinkType) + */ + public Linker getLinker(LinkType type) { + if (type.isStaticLibrary()) { + if (this == cl6x) { + return ClxxLibrarian.getCl6xInstance(); + } + return ClxxLibrarian.getCl55Instance(); + } + if (type.isSharedLibrary()) { + if (this == cl6x) { + return ClxxLinker.getCl6xDllInstance(); + } + return ClxxLinker.getCl55DllInstance(); + } + if (this == cl6x) { + return ClxxLinker.getCl6xInstance(); + } + return ClxxLinker.getCl55Instance(); + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#getMaximumCommandLength() + */ + public int getMaximumCommandLength() { + return 1024; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineCompiler#getUndefineSwitch(java.lang.StringBuffer, + * java.lang.String) + */ + protected void getUndefineSwitch(StringBuffer buffer, String define) { + buffer.append("-u"); + buffer.append(define); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ti/ClxxLibrarian.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ti/ClxxLibrarian.java new file mode 100644 index 0000000000..082d1a477f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ti/ClxxLibrarian.java @@ -0,0 +1,162 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.ti; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * + * Adapter for TI DSP librarian + * * + * @author CurtA + */ +public class ClxxLibrarian extends CommandLineLinker { + private static final ClxxLibrarian cl55Instance = new ClxxLibrarian("ar55"); + private static final ClxxLibrarian cl6xInstance = new ClxxLibrarian("ar6x"); + public static final ClxxLibrarian getCl55Instance() { + return cl55Instance; + } + public static final ClxxLibrarian getCl6xInstance() { + return cl6xInstance; + } + private ClxxLibrarian(String command) { + super(command, null, new String[]{".o"}, new String[0], ".lib", false, + null); + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addBase(long, + * java.util.Vector) + */ + protected void addBase(long base, Vector args) { + // TODO Auto-generated method stub + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addFixed(java.lang.Boolean, + * java.util.Vector) + */ + protected void addFixed(Boolean fixed, Vector args) { + // TODO Auto-generated method stub + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addImpliedArgs(boolean, + * net.sf.antcontrib.cpptasks.compiler.LinkType, java.util.Vector) + */ + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + // TODO Auto-generated method stub + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addIncremental(boolean, + * java.util.Vector) + */ + protected void addIncremental(boolean incremental, Vector args) { + // TODO Auto-generated method stub + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addMap(boolean, + * java.util.Vector) + */ + protected void addMap(boolean map, Vector args) { + // TODO Auto-generated method stub + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addStack(int, + * java.util.Vector) + */ + protected void addStack(int stack, Vector args) { + // TODO Auto-generated method stub + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getCommandFileSwitch(java.lang.String) + */ + protected String getCommandFileSwitch(String commandFile) { + return "@" + commandFile; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Linker#getLibraryPath() + */ + public File[] getLibraryPath() { + return new File[0]; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Linker#getLibraryPatterns(java.lang.String[]) + */ + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + return new String[0]; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Processor#getLinker(net.sf.antcontrib.cpptasks.compiler.LinkType) + */ + public Linker getLinker(LinkType linkType) { + return null; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getMaximumCommandLength() + */ + protected int getMaximumCommandLength() { + return 1024; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getOutputFileSwitch(java.lang.String) + */ + protected String[] getOutputFileSwitch(String outputFile) { + return new String[]{"-o", outputFile}; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Linker#isCaseSensitive() + */ + public boolean isCaseSensitive() { + // TODO Auto-generated method stub + return false; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ti/ClxxLinker.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ti/ClxxLinker.java new file mode 100644 index 0000000000..43ee7c0662 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/ti/ClxxLinker.java @@ -0,0 +1,181 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.ti; +import java.io.File; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.compiler.CommandLineLinker; +import net.sf.antcontrib.cpptasks.compiler.LinkType; +import net.sf.antcontrib.cpptasks.compiler.Linker; +import net.sf.antcontrib.cpptasks.types.LibraryTypeEnum; + +/** + * Adapter for TI DSP linkers + * * + * @author CurtA + * + */ +public class ClxxLinker extends CommandLineLinker { + private static final ClxxLinker cl55DllInstance = new ClxxLinker("lnk55", + ".dll"); + private static final ClxxLinker cl55Instance = new ClxxLinker("lnk55", + ".exe"); + private static final ClxxLinker cl6xDllInstance = new ClxxLinker("lnk6x", + ".dll"); + private static final ClxxLinker cl6xInstance = new ClxxLinker("lnk6x", + ".exe"); + public static ClxxLinker getCl55DllInstance() { + return cl55DllInstance; + } + public static ClxxLinker getCl55Instance() { + return cl55Instance; + } + public static ClxxLinker getCl6xDllInstance() { + return cl6xDllInstance; + } + public static ClxxLinker getCl6xInstance() { + return cl6xInstance; + } + private ClxxLinker(String command, String outputSuffix) { + super(command, "-h", new String[]{".o", ".lib", ".res"}, new String[]{ + ".map", ".pdb", ".lnk"}, outputSuffix, false, null); + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addBase(long, + * java.util.Vector) + */ + protected void addBase(long base, Vector args) { + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addFixed(java.lang.Boolean, + * java.util.Vector) + */ + protected void addFixed(Boolean fixed, Vector args) { + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addImpliedArgs(boolean, + * net.sf.antcontrib.cpptasks.compiler.LinkType, java.util.Vector) + */ + protected void addImpliedArgs(boolean debug, LinkType linkType, Vector args, Boolean defaultflag) { + if (linkType.isSharedLibrary()) { + args.addElement("-abs"); + } + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addIncremental(boolean, + * java.util.Vector) + */ + protected void addIncremental(boolean incremental, Vector args) { + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addMap(boolean, + * java.util.Vector) + */ + protected void addMap(boolean map, Vector args) { + if (map) { + args.addElement("-m"); + } + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addStack(int, + * java.util.Vector) + */ + protected void addStack(int stack, Vector args) { + } + /* (non-Javadoc) + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#addEntry(int, java.util.Vector) + */ + protected void addEntry(String entry, Vector args) { + } + + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getCommandFileSwitch(java.lang.String) + */ + protected String getCommandFileSwitch(String commandFile) { + return "@" + commandFile; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Linker#getLibraryPath() + */ + public File[] getLibraryPath() { + return new File[0]; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Linker#getLibraryPatterns(java.lang.String[]) + */ + public String[] getLibraryPatterns(String[] libnames, LibraryTypeEnum libType) { + // + // TODO: Looks bogus, should be .a or .so's not .o's + // + String[] libpats = new String[libnames.length]; + for (int i = 0; i < libnames.length; i++) { + libpats[i] = libnames[i] + ".o"; + } + return libpats; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Processor#getLinker(net.sf.antcontrib.cpptasks.compiler.LinkType) + */ + public Linker getLinker(LinkType linkType) { + return this; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getMaximumCommandLength() + */ + protected int getMaximumCommandLength() { + return 1024; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.CommandLineLinker#getOutputFileSwitch(java.lang.String) + */ + protected String[] getOutputFileSwitch(String outputFile) { + return new String[]{"-o", outputFile}; + } + /* + * (non-Javadoc) + * + * @see net.sf.antcontrib.cpptasks.compiler.Linker#isCaseSensitive() + */ + public boolean isCaseSensitive() { + // TODO Auto-generated method stub + return false; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/AslcompilerArgument.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/AslcompilerArgument.java new file mode 100644 index 0000000000..87babcf740 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/AslcompilerArgument.java @@ -0,0 +1,30 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; + +/** + * A aslcompiler command line argument. + */ +public class AslcompilerArgument extends CommandLineArgument { + public AslcompilerArgument () { + } + + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } +} \ No newline at end of file diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/AssemblerArgument.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/AssemblerArgument.java new file mode 100644 index 0000000000..1b5f54d9a7 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/AssemblerArgument.java @@ -0,0 +1,30 @@ +/* + * + * Copyright 2001-2005 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; + +/** + * A assembler command line argument. + */ +public class AssemblerArgument extends CommandLineArgument { + public AssemblerArgument () { + } + + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/CommandLineArgument.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/CommandLineArgument.java new file mode 100644 index 0000000000..91ab2f6327 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/CommandLineArgument.java @@ -0,0 +1,122 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; + +import org.apache.tools.ant.types.EnumeratedAttribute; +import java.io.File; +/** + * An compiler/linker command line flag. + */ +public class CommandLineArgument { + /** + * Enumerated attribute with the values "start", "mid" and "end", + */ + public static class LocationEnum extends EnumeratedAttribute { + public String[] getValues() { + return new String[]{"start", "mid", "end"}; + } + } + private String ifCond; + private int location; + private String unlessCond; + private String value; + private File file; + public CommandLineArgument() { + } + public int getLocation() { + return location; + } + public String getValue() { + return value; + } + public File getFile() { + return file; + } + /** + * Returns true if the define's if and unless conditions (if any) are + * satisfied. + */ + public boolean isActive(org.apache.tools.ant.Project p) { + if (value == null) { + return false; + } + if (ifCond != null && p.getProperty(ifCond) == null) { + return false; + } else if (unlessCond != null && p.getProperty(unlessCond) != null) { + return false; + } + return true; + } + /** + * Sets the property name for the 'if' condition. + * + * The argument will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + */ + public void setIf(String propName) { + ifCond = propName; + } + /** + * Specifies relative location of argument on command line. "start" will + * place argument at start of command line, "mid" will place argument after + * all "start" arguments but before filenames, "end" will place argument + * after filenames. + * + */ + public void setLocation(LocationEnum location) { + this.location = location.getIndex(); + } + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the argument will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public void setUnless(String propName) { + unlessCond = propName; + } + /** + * Specifies the string that should appear on the command line. The + * argument will be quoted if it contains embedded blanks. Use multiple + * arguments to avoid quoting. + * + */ + public void setValue(String value) { + this.value = value; + } + /** + * Specifies the file which lists many strings that should appear on + * the command line. Each line is one argument. The argument will be + * quated if it contains embedded blanks. Use multiple arguments in + * file to avoid quating. + * + * @param file + * name of the file + */ + public void setFile(File file) { + this.file = file; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/CompilerArgument.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/CompilerArgument.java new file mode 100644 index 0000000000..ca9e90e732 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/CompilerArgument.java @@ -0,0 +1,28 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +/** + * A compiler command line argument. + */ +public class CompilerArgument extends CommandLineArgument { + public CompilerArgument() { + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/ConditionalFileSet.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/ConditionalFileSet.java new file mode 100644 index 0000000000..af2d141e99 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/ConditionalFileSet.java @@ -0,0 +1,84 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +import net.sf.antcontrib.cpptasks.CUtil; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.AbstractFileSet; +import org.apache.tools.ant.types.FileSet; +/** + * An Ant FileSet object augmented with if and unless conditions. + * + * @author Curt Arnold + */ +public class ConditionalFileSet extends FileSet { + private String ifCond; + private String unlessCond; + public ConditionalFileSet() { + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + /** + * overrides FileSet's implementation which would throw an exception since + * the referenced object isn't this type. + */ + protected AbstractFileSet getRef(Project p) { + return (AbstractFileSet) getRefid().getReferencedObject(p); + } + /** + * Returns true if the Path's if and unless conditions (if any) are + * satisfied. + */ + public boolean isActive() throws BuildException { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException( + "setProject() should have been called"); + } + return CUtil.isActive(p, ifCond, unlessCond); + } + /** + * Sets the property name for the 'if' condition. + * + * The fileset will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + */ + public void setIf(String propName) { + ifCond = propName; + } + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the fileset will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public void setUnless(String propName) { + unlessCond = propName; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/ConditionalPath.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/ConditionalPath.java new file mode 100644 index 0000000000..dc21189c15 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/ConditionalPath.java @@ -0,0 +1,92 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CUtil; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.Path; +/** + * An Ant Path object augmented with if and unless conditionals + * + * @author Curt Arnold + */ +public class ConditionalPath extends Path { + private String ifCond; + private String unlessCond; + private File file; + public ConditionalPath(Project project) { + super(project); + } + public ConditionalPath(Project p, String path) { + super(p, path); + } + public File getFile() { + return file; + } + /** + * Returns true if the Path's if and unless conditions (if any) are + * satisfied. + */ + public boolean isActive(org.apache.tools.ant.Project p) + throws BuildException { + return CUtil.isActive(p, ifCond, unlessCond); + } + /** + * Sets the property name for the 'if' condition. + * + * The path will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + * + * @param propName + * property name + */ + public void setIf(String propName) { + ifCond = propName; + } + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the path will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public void setUnless(String propName) { + unlessCond = propName; + } + /** + * Specifies the file which lists many include paths that should appear on + * the command line. Each line is an include path. The includepath will be + * quated if it contains embedded blanks. + * + * @param file + * name of the file + */ + public void setFile(File file) { + this.file = file; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/DefineArgument.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/DefineArgument.java new file mode 100644 index 0000000000..824e939481 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/DefineArgument.java @@ -0,0 +1,38 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +/** + * Preprocessor macro definition. + * + * @author Mark A Russell mark_russell@csg_systems.com + * + */ +public class DefineArgument extends UndefineArgument { + private String value; + public DefineArgument() { + super(true); + } + /** Returns the value of the define */ + public final String getValue() { + return value; + } + /** Set the value attribute */ + public final void setValue(String value) { + this.value = value; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/DefineSet.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/DefineSet.java new file mode 100644 index 0000000000..9d229fb0ff --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/DefineSet.java @@ -0,0 +1,199 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Reference; +/** + * Set of preprocessor macro defines and undefines. + * + * @author Mark A Russell mark_russell@csg_systems.com + * + * @author Adam Murdoch + */ +public class DefineSet extends DataType { + private Vector defineList = new Vector(); + private String ifCond = null; + private String unlessCond = null; + /** + * + * Adds a define element. + * + * @throws BuildException + * if reference + */ + public void addDefine(DefineArgument arg) throws BuildException { + if (isReference()) { + throw noChildrenAllowed(); + } + defineList.addElement(arg); + } + /** Adds defines/undefines. */ + private void addDefines(String[] defs, boolean isDefine) { + for (int i = 0; i < defs.length; i++) { + UndefineArgument def; + if (isDefine) { + def = new DefineArgument(); + } else { + def = new UndefineArgument(); + } + def.setName(defs[i]); + defineList.addElement(def); + } + } + /** + * + * Adds an undefine element. + * + * @throws BuildException + * if reference + */ + public void addUndefine(UndefineArgument arg) throws BuildException { + if (isReference()) { + throw noChildrenAllowed(); + } + defineList.addElement(arg); + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + /** Returns the defines and undefines in this set. */ + public UndefineArgument[] getDefines() throws BuildException { + if (isReference()) { + DefineSet defset = (DefineSet) getCheckedRef(DefineSet.class, + "DefineSet"); + return defset.getDefines(); + } else { + if (isActive()) { + UndefineArgument[] defs = new UndefineArgument[defineList + .size()]; + defineList.copyInto(defs); + return defs; + } else { + return new UndefineArgument[0]; + } + } + } + /** + * Returns true if the define's if and unless conditions (if any) are + * satisfied. + * + * @exception BuildException + * throws build exception if name is not set + */ + public final boolean isActive() throws BuildException { + return CUtil.isActive(getProject(), ifCond, unlessCond); + } + /** + * A comma-separated list of preprocessor macros to define. Use nested + * define elements to define macro values. + * + * @param defList + * comma-separated list of preprocessor macros + * @throws BuildException + * throw if defineset is a reference + */ + public void setDefine(CUtil.StringArrayBuilder defList) + throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + addDefines(defList.getValue(), true); + } + /** + * Sets a description of the current data type. + */ + public void setDescription(String desc) { + super.setDescription(desc); + } + /** + * Sets an id that can be used to reference this element. + * + * @param id + * id + */ + public void setId(String id) { + // + // this is actually accomplished by a different + // mechanism, but we can document it + // + } + /** + * Sets the property name for the 'if' condition. + * + * The define will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + * + * @param propName + * property name + */ + public final void setIf(String propName) { + ifCond = propName; + } + /** + * Specifies that this element should behave as if the content of the + * element with the matching id attribute was inserted at this location. If + * specified, no other attributes or child content should be specified, + * other than "description". + * + */ + public void setRefid(Reference r) throws BuildException { + if (!defineList.isEmpty()) { + throw tooManyAttributes(); + } + super.setRefid(r); + } + /** + * A comma-separated list of preprocessor macros to undefine. + * + * @param undefList + * comma-separated list of preprocessor macros + * @throws BuildException + * throw if defineset is a reference + */ + public void setUndefine(CUtil.StringArrayBuilder undefList) + throws BuildException { + if (isReference()) { + throw tooManyAttributes(); + } + addDefines(undefList.getValue(), false); + } + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the define will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public final void setUnless(String propName) { + unlessCond = propName; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/FlexLong.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/FlexLong.java new file mode 100644 index 0000000000..d95959f631 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/FlexLong.java @@ -0,0 +1,59 @@ +/* + * + * Copyright 2002-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +import java.lang.reflect.Method; + +/** + * Helper class which can be used for Ant task attribute setter methods to + * allow the build file to specify a long in either decimal, octal, or + * hexadecimal format. + * // FlexInteger author + * @author Erik Hatcher + * @see org.apache.tools.ant.types.FlexInteger + */ +public class FlexLong { + private Long value; + /** + * Constructor used by Ant's introspection mechanism for attribute + * population + */ + public FlexLong(String value) { + // Java 1.1 did not support Long.decode().. so we call it by + // reflection. + try { + Method m = Long.class + .getMethod("decode", new Class[]{String.class}); + Object rc = m.invoke(null, new Object[]{value}); + this.value = (Long) rc; + } catch (Exception e) { + // Try it the old fashioned way, we must be on a 1.1 jre + this.value = new Long(value); + } + } + /** + * Returns the decimal integer value + */ + public long longValue() { + return value.longValue(); + } + /** + * Overridden method to return the decimal value for display + */ + public String toString() { + return value.toString(); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/IncludePath.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/IncludePath.java new file mode 100644 index 0000000000..edcc42103c --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/IncludePath.java @@ -0,0 +1,38 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +import org.apache.tools.ant.Project; +/** + * An include path. + * + * Works like other paths in Ant with with the addition of "if" and "unless" + * conditions. + * + * @author Curt Arnold + */ +public class IncludePath extends ConditionalPath { + public IncludePath(Project project) { + super(project); + } + public IncludePath(Project p, String path) { + super(p, path); + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/LibrarySet.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/LibrarySet.java new file mode 100644 index 0000000000..d522ccc36f --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/LibrarySet.java @@ -0,0 +1,290 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +import java.io.File; + +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.FileVisitor; +import net.sf.antcontrib.cpptasks.compiler.Linker; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.ProjectComponent; +import org.apache.tools.ant.types.FileSet; +import org.apache.tools.ant.types.PatternSet; +/** + * A set of library names. Libraries can also be added to a link by specifying + * them in a fileset. + * + * For most Unix-like compilers, libset will result in a series of -l and -L + * linker arguments. For Windows compilers, the library names will be used to + * locate the appropriate library files which will be added to the linkers + * input file list as if they had been specified in a fileset. + * + * @author Mark A Russell mark_russell@csg_systems.com + * + * @author Adam Murdoch + * @author Curt Arnold + */ +public class LibrarySet extends ProjectComponent { + private String dataset; + private boolean explicitCaseSensitive; + private String ifCond; + private String[] libnames; + private final FileSet set = new FileSet(); + private String unlessCond; + private LibraryTypeEnum libraryType; + public LibrarySet() { + libnames = new String[0]; + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + /** + * Gets the dataset. Used on OS390 if the libs are in a dataset. + * + * @return Returns a String + */ + public String getDataset() { + return dataset; + } + public File getDir(Project project) { + return set.getDir(project); + } + protected FileSet getFileSet() { + return set; + } + public String[] getLibs() { + String[] retval = (String[]) libnames.clone(); + return retval; + } + + /** + * Gets preferred library type + * + * @return library type, may be null. + */ + public LibraryTypeEnum getType() { + return libraryType; + } + /** + * Returns true if the define's if and unless conditions (if any) are + * satisfied. + */ + public boolean isActive(org.apache.tools.ant.Project p) { + if (p == null) { + throw new NullPointerException("p"); + } + if (ifCond != null) { + String ifValue = p.getProperty(ifCond); + if (ifValue != null) { + if (ifValue.equals("no") || ifValue.equals("false")) { + throw new BuildException( + "property " + + ifCond + + " used as if condition has value " + + ifValue + + " which suggests a misunderstanding of if attributes"); + } + } else { + return false; + } + } + if (unlessCond != null) { + String unlessValue = p.getProperty(unlessCond); + if (unlessValue != null) { + if (unlessValue.equals("no") || unlessValue.equals("false")) { + throw new BuildException( + "property " + + unlessCond + + " used as unless condition has value " + + unlessValue + + " which suggests a misunderstanding of unless attributes"); + } + return false; + } + } + if (libnames.length == 0) { + p.log("libnames not specified or empty.", Project.MSG_WARN); + return false; + } + return true; + } + /** + * Sets case sensitivity of the file system. If not set, will default to + * the linker's case sensitivity. + * + * @param isCaseSensitive + * "true"|"on"|"yes" if file system is case sensitive, + * "false"|"off"|"no" when not. + */ + public void setCaseSensitive(boolean isCaseSensitive) { + explicitCaseSensitive = true; + set.setCaseSensitive(isCaseSensitive); + } + /** + * Sets the dataset. Used on OS390 if the libs are in a dataset. + * + * @param dataset + * The dataset to set + */ + public void setDataset(String dataset) { + this.dataset = dataset; + } + /** + * Library directory. + * + * @param dir + * library directory + * + */ + public void setDir(File dir) throws BuildException { + set.setDir(dir); + } + /** + * Sets the property name for the 'if' condition. + * + * The library set will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + * + * @param propName + * property name + */ + public void setIf(String propName) { + ifCond = propName; + } + /** + * Comma-separated list of library names without leading prefixes, such as + * "lib", or extensions, such as ".so" or ".a". + * + */ + public void setLibs(CUtil.StringArrayBuilder libs) throws BuildException { + libnames = libs.getValue(); + // If this is not active.. then it's ok if the lib names are invalid. + // so we can do a: + if (!isActive(getProject())) + return; + for (int i = 0; i < libnames.length; i++) { + int lastDot = libnames[i].lastIndexOf('.'); + if (lastDot >= 0) { + String extension = libnames[i].substring(lastDot); + if (extension.equalsIgnoreCase(".lib") + || extension.equalsIgnoreCase(".so") + || extension.equalsIgnoreCase(".a")) { + getProject().log( + "Suspicious library name ending with \"" + + extension + "\": " + libnames[i], Project.MSG_DEBUG ); + } + } + if (libnames[i].length() >= 3 + && libnames[i].substring(0, 3).equalsIgnoreCase("lib")) { + getProject().log( + "Suspicious library name starting with \"lib\": " + + libnames[i], Project.MSG_DEBUG); + } + } + } + public void setProject(Project project) { + set.setProject(project); + super.setProject(project); + } + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the library set will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public void setUnless(String propName) { + unlessCond = propName; + } + + /** + * Sets the preferred library type. Supported values "shared", "static", and + * "framework". "framework" is equivalent to "shared" on non-Darwin platforms. + */ + public void setType(LibraryTypeEnum type) { + this.libraryType = type; + } + + public void visitLibraries(Project project, Linker linker, File[] libpath, + FileVisitor visitor) throws BuildException { + FileSet localSet = (FileSet) set.clone(); + // + // unless explicitly set + // will default to the linker case sensitivity + // + if (!explicitCaseSensitive) { + boolean linkerCaseSensitive = linker.isCaseSensitive(); + localSet.setCaseSensitive(linkerCaseSensitive); + } + // + // if there was a libs attribute then + // add the corresponding patterns to the FileSet + // + if (libnames != null && libnames.length > 0) { + String[] patterns = linker.getLibraryPatterns(libnames, libraryType); + // + // if no patterns, then linker does not support libraries + // + if (patterns.length > 0) { + for (int i = 0; i < patterns.length; i++) { + PatternSet.NameEntry entry = localSet.createInclude(); + entry.setName(patterns[i]); + } + // + // if there was no specified directory then + // run through the libpath backwards + // + if (localSet.getDir(project) == null) { + // + // scan libpath in reverse order + // to give earlier entries priority + // + for (int j = libpath.length - 1; j >= 0; j--) { + FileSet clone = (FileSet) localSet.clone(); + clone.setDir(libpath[j]); + DirectoryScanner scanner = clone.getDirectoryScanner(project); + File basedir = scanner.getBasedir(); + String[] files = scanner.getIncludedFiles(); + for (int k = 0; k < files.length; k++) { + visitor.visit(basedir, files[k]); + } + } + } else { + DirectoryScanner scanner = localSet.getDirectoryScanner(project); + File basedir = scanner.getBasedir(); + String[] files = scanner.getIncludedFiles(); + for (int k = 0; k < files.length; k++) { + visitor.visit(basedir, files[k]); + } + } + } + } + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/LibraryTypeEnum.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/LibraryTypeEnum.java new file mode 100644 index 0000000000..82d7947bf2 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/LibraryTypeEnum.java @@ -0,0 +1,48 @@ +/* + * + * Copyright 2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +import org.apache.tools.ant.types.EnumeratedAttribute; +/** + * Enumeration of library types for LibrarySet + * + * @author Curt Arnold + * + */ +public class LibraryTypeEnum extends EnumeratedAttribute { + /** + * Constructor + * + * Set by default to "shared" + * + * @see java.lang.Object#Object() + */ + public LibraryTypeEnum() { + setValue("shared"); + } + /** + * Gets list of acceptable values + * + * @see org.apache.tools.ant.types.EnumeratedAttribute#getValues() + */ + public String[] getValues() { + return new String[]{"shared", // prefer shared libraries + "static", // prefer static libraries + "framework" // framework libraries (Mac OS/X) + // equiv to shared on other platforms + }; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/LinkerArgument.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/LinkerArgument.java new file mode 100644 index 0000000000..89bff1881b --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/LinkerArgument.java @@ -0,0 +1,28 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +/** + * A linker command line argument. + */ +public class LinkerArgument extends CommandLineArgument { + public LinkerArgument() { + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/SystemIncludePath.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/SystemIncludePath.java new file mode 100644 index 0000000000..be0dbd537a --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/SystemIncludePath.java @@ -0,0 +1,45 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +import org.apache.tools.ant.Project; +/** + * A system include path. + * + * Files located using a system include path will not participate in dependency + * analysis. + * + * Standard include paths for a compiler should not be specified since these + * should be determined from environment variables or configuration files by + * the compiler adapter. + * + * Works like other paths in Ant with with the addition of "if" and "unless" + * conditions. + * + * @author Curt Arnold + */ +public class SystemIncludePath extends ConditionalPath { + public SystemIncludePath(Project project) { + super(project); + } + public SystemIncludePath(Project p, String path) { + super(p, path); + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/SystemLibrarySet.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/SystemLibrarySet.java new file mode 100644 index 0000000000..02d08c8ac8 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/SystemLibrarySet.java @@ -0,0 +1,37 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +/** + * A set of system library names. Timestamp or location of system libraries are + * not considered in dependency analysis. + * + * Libraries can also be added to a link by specifying them in a fileset. + * + * For most Unix-like compilers, syslibset will result in a series of -l and -L + * linker arguments. For Windows compilers, the library names will be used to + * locate the appropriate library files which will be added to the linkers + * input file list as if they had been specified in a fileset. + */ +public class SystemLibrarySet extends LibrarySet { + public SystemLibrarySet() { + super(); + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/UndefineArgument.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/UndefineArgument.java new file mode 100644 index 0000000000..2a18fca6d1 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/types/UndefineArgument.java @@ -0,0 +1,153 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.types; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CUtil; + +import org.apache.tools.ant.BuildException; +/** + * Preprocessor macro undefinition. + * + * @author Mark A Russell mark_russell@csg_systems.com + * + */ +public class UndefineArgument { + /** + * This method returns an array of UndefineArgument and DefineArgument's by + * merging a base list with an override list. + * + * Any define in the base list with a name that appears in the override + * list is suppressed. All entries in the override list are preserved + * + */ + public static UndefineArgument[] merge(UndefineArgument[] base, + UndefineArgument[] override) { + if (base.length == 0) { + UndefineArgument[] overrideClone = (UndefineArgument[]) override + .clone(); + return overrideClone; + } + if (override.length == 0) { + UndefineArgument[] baseClone = (UndefineArgument[]) base.clone(); + return baseClone; + } + Vector unduplicated = new Vector(base.length); + for (int i = 0; i < base.length; i++) { + UndefineArgument current = base[i]; + String currentName = current.getName(); + boolean match = false; + if (currentName == null) { + match = true; + } else { + for (int j = 0; j < override.length; j++) { + UndefineArgument over = override[j]; + String overName = over.getName(); + if (overName != null && overName.equals(currentName)) { + match = true; + break; + } + } + } + if (!match) { + unduplicated.addElement(current); + } + } + UndefineArgument[] combined = new UndefineArgument[unduplicated.size() + + override.length]; + unduplicated.copyInto(combined); + int offset = unduplicated.size(); + for (int i = 0; i < override.length; i++) { + combined[offset + i] = override[i]; + } + return combined; + } + private boolean define = false; + private String ifCond; + private String name; + private String unlessCond; + public UndefineArgument() { + } + protected UndefineArgument(boolean isDefine) { + this.define = isDefine; + } + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + /** Returns the name of the define */ + public final String getName() { + return name; + } + /** Returns the value of the define */ + public String getValue() { + return null; + } + /** + * Returns true if the define's if and unless conditions (if any) are + * satisfied. + * + * @exception BuildException + * throws build exception if name is not set + */ + public final boolean isActive(org.apache.tools.ant.Project p) + throws BuildException { + if (name == null) { + throw new BuildException(" is missing name attribute"); + } + return CUtil.isActive(p, ifCond, unlessCond); + } + /** Returns true if this is a define, false if an undefine. */ + public final boolean isDefine() { + return define; + } + /** + * Sets the property name for the 'if' condition. + * + * The define will be ignored unless the property is defined. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") will throw an exception when + * evaluated. + * + * @param propName + * property name + */ + public final void setIf(String propName) { + ifCond = propName; + } + /** Set the name attribute */ + public final void setName(String name) { + this.name = name; + } + /** + * Set the property name for the 'unless' condition. + * + * If named property is set, the define will be ignored. + * + * The value of the property is insignificant, but values that would imply + * misinterpretation ("false", "no") of the behavior will throw an + * exception when evaluated. + * + * @param propName + * name of property + */ + public final void setUnless(String propName) { + unlessCond = propName; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/CommandLineUserDefine.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/CommandLineUserDefine.java new file mode 100644 index 0000000000..7c66eb1cbb --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/CommandLineUserDefine.java @@ -0,0 +1,389 @@ +package net.sf.antcontrib.cpptasks.userdefine; + +import java.io.File; +import java.util.Iterator; +import java.util.StringTokenizer; +import java.util.Vector; + +import net.sf.antcontrib.cpptasks.CCTask; +import net.sf.antcontrib.cpptasks.CUtil; +import net.sf.antcontrib.cpptasks.types.CommandLineArgument; +import net.sf.antcontrib.cpptasks.types.ConditionalFileSet; +import net.sf.antcontrib.cpptasks.types.LibrarySet; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +public class CommandLineUserDefine { + + String command; + + /* + * The follows variable set at child class. + */ + String includeFileFlag = null; + String entryPointFlag = null; + String subSystemFlag = null; + String mapFlag = null; + String pdbFlag = null; + String outputFileFlag = null; + String includePathDelimiter = null; + + /* + * get lib string if Vendor = "gcc", it should respectively aadd "-(" and ")-" + * at library set before and end. This value set at userDefineCompiler class. + */ + Vector libSetList = new Vector(); + Vector fileList = new Vector(); + public void command(CCTask cctask, UserDefineDef userdefine){ + File workdir; + File outdir; + Project project = cctask.getProject(); + if(userdefine.getWorkdir() == null) { + workdir = new File("."); + } + else { + workdir = userdefine.getWorkdir(); + } + + /* + * generate cmdline= command + args + includepath + endargs + outfile + */ + Vector args = new Vector(); + Vector argsWithoutSpace = new Vector(); + Vector endargs = new Vector(); + Vector endargsWithoutSpace = new Vector(); + Vector includePath = new Vector(); + + /* + * Generate cmdline = command + + * general args + + * outputflag + outputfile + * subsystemFlag + subsystemValue + + * includeFlag + includeFile + + * includeFileincludpath + + * entryPointFlag + entryPointValue + + * mapFlag + mapValue + + * pdbFlag + pdbValue + + * endargs + + * + * + */ + /* + * get Args. + */ + CommandLineArgument[] argument = userdefine.getActiveProcessorArgs(); + for (int j = 0; j < argument.length; j++) { + if (argument[j].getLocation() == 0) { + args.addElement(argument[j].getValue()); + } else { + endargs.addElement(argument[j].getValue()); + } + } + /* + * get include path. + */ + String[] incPath = userdefine.getActiveIncludePaths(); + for (int j = 0; j < incPath.length; j++) { + if(incPath[j].indexOf(' ') >= 0) { + includePath.addElement( includePathDelimiter + incPath[j]); + //includePath.addElement( includePathDelimiter + "\"" + incPath[j] + "\""); + } + else { + includePath.addElement( includePathDelimiter + incPath[j]); + } + } + /* + * Remove space in args and endargs. + */ + for ( int i=0; i < args.size(); i++) { + String str = (String)args.get(i); + StringTokenizer st = new StringTokenizer(str); + while(st.hasMoreTokens()) { + argsWithoutSpace.addElement(st.nextToken()); + } + } + for ( int i=0; i < endargs.size(); i++) { + String str = (String)endargs.get(i); + StringTokenizer st = new StringTokenizer(str); + while(st.hasMoreTokens()) { + endargsWithoutSpace.addElement(st.nextToken()); + } + } + + int cmdLen = 0; + if(userdefine.getOutdir() == null) { + outdir = new File("."); + /* + * command + args + endargs + includepath + sourcefile + */ + cmdLen = 1 + argsWithoutSpace.size() + endargsWithoutSpace.size() + includePath.size() + 1; + } + else { + outdir = userdefine.getOutdir(); + /* + * command + args + endargs + includepath + sourcefile + outfile + */ + cmdLen = 1 + argsWithoutSpace.size() + endargsWithoutSpace.size() + includePath.size() + 2; + } + if (includeFileFlag != null && includeFileFlag.trim().length() > 0){ + cmdLen++; + } + if (entryPointFlag != null && entryPointFlag.trim().length() > 0){ + cmdLen++; + } + if (subSystemFlag != null && subSystemFlag.trim().length() > 0){ + cmdLen++; + } + if (mapFlag != null && mapFlag.trim().length() > 0){ + cmdLen++; + } + if (pdbFlag != null && pdbFlag.trim().length() > 0){ + cmdLen++; + } + if (libSetList != null && libSetList.size() > 0){ + cmdLen = cmdLen + libSetList.size(); + } + if (fileList != null){ + cmdLen = cmdLen + fileList.size(); + } + /* + * In gcc the "cr" flag should follow space then add outputfile name, otherwise + * it will pop error. + */ + if (outputFileFlag != null && outputFileFlag.trim().length() > 0){ + if (outputFileFlag.trim().equalsIgnoreCase("-cr")){ + cmdLen = cmdLen + 2; + }else { + cmdLen++; + } + + } + /* + * for every source file + * if file is header file, just skip it (add later) + */ + Vector srcSets = userdefine.getSrcSets(); + if (srcSets.size() == 0) { + String[] cmd = new String[cmdLen - 1]; + int index = 0; + cmd[index++] = this.command; + + + + Iterator iter = argsWithoutSpace.iterator(); + while (iter.hasNext()) { + cmd[index++] = project.replaceProperties((String)iter.next()); + //cmd[index++] = (String)iter.next(); + } + + iter = endargsWithoutSpace.iterator(); + while (iter.hasNext()) { + cmd[index++] = (String)iter.next(); + } + + /* + * "OutputFlag + outputFile" as first option follow command.exe. + */ + if (outputFileFlag != null && outputFileFlag.trim().length() > 0){ + if (outputFileFlag.trim().equalsIgnoreCase("-cr")){ + cmd[index++] = outputFileFlag; + cmd[index++] = userdefine.getOutputFile(); + }else { + cmd[index++] = outputFileFlag + userdefine.getOutputFile(); + } + } + + /* + * Add fileList to cmd + */ + if (fileList != null && fileList.size()> 0){ + for (int i = 0; i < fileList.size(); i++){ + cmd[index++] = fileList.get(i); + } + } + + if (subSystemFlag != null && subSystemFlag.trim().length() > 0){ + cmd[index++] = subSystemFlag + userdefine.getSubSystemvalue(); + } + if (includeFileFlag != null && includeFileFlag.trim().length() > 0){ + cmd[index++] = includeFileFlag + userdefine.getIncludeFile(); + } + + iter = includePath.iterator(); + while (iter.hasNext()) { + cmd[index++] = (String)iter.next(); + } + + if (entryPointFlag != null && entryPointFlag.trim().length() > 0){ + // + // If GCC link use __ModuleEntrypoint instead of _ModuleEntryPoint; + // + if (entryPointFlag.equalsIgnoreCase("-e")){ + cmd[index++] = entryPointFlag + "_" + userdefine.getEntryPointvalue(); + } else { + cmd[index++] = entryPointFlag + userdefine.getEntryPointvalue(); + } + + } + if (mapFlag != null && mapFlag.trim().length() > 0){ + cmd[index++] = mapFlag + userdefine.getMapvalue(); + } + if (pdbFlag != null && pdbFlag.trim().length() > 0){ + cmd[index++] = pdbFlag + userdefine.getPdbvalue(); + } + + if (userdefine.getOutdir() != null){ + // will add code to generate outfile name and flag + cmd[index++] = "/nologo"; + } + + if (libSetList != null && libSetList.size() > 0){ + for (int i = 0; i < libSetList.size(); i++){ + cmd[index++] = libSetList.get(i); + } + } + + // execute the command + int retval = runCommand(cctask, workdir, cmd); + // if with monitor, add more code + if (retval != 0) { + throw new BuildException(this.command + + " failed with return code " + retval, + cctask.getLocation()); + } + } + + // + // if have source file append source file in command land. + // + for (int i = 0; i < srcSets.size(); i++) { + ConditionalFileSet srcSet = (ConditionalFileSet) srcSets + .elementAt(i); + if (srcSet.isActive()) { + // Find matching source files + DirectoryScanner scanner = srcSet.getDirectoryScanner(project); + // Check each source file - see if it needs compilation + String[] fileNames = scanner.getIncludedFiles(); + for (int j = 0; j < fileNames.length; j++){ + String[] cmd = new String[cmdLen]; + int index = 0; + cmd[index++] = this.command; + + + + Iterator iter = argsWithoutSpace.iterator(); + while (iter.hasNext()) { + cmd[index++] = (String)iter.next(); + } + + iter = endargsWithoutSpace.iterator(); + while (iter.hasNext()) { + cmd[index++] = (String)iter.next(); + } + + /* + * Add outputFileFlag and output file to cmd + */ + if (outputFileFlag != null && outputFileFlag.length()> 0){ + if (outputFileFlag.trim().equalsIgnoreCase("-cr")){ + cmd[index++] = outputFileFlag; + cmd[index++] = userdefine.getOutputFile(); + }else { + cmd[index++] = outputFileFlag + userdefine.getOutputFile(); + } + } + + /* + * Add fileList to cmd + */ + if (fileList != null && fileList.size()> 0){ + for (int s = 0; s < fileList.size(); s++){ + cmd[index++] = fileList.get(s); + } + } + if (subSystemFlag != null && subSystemFlag.length()> 0){ + cmd[index++] = subSystemFlag + userdefine.getSubSystemvalue(); + } + if (includeFileFlag != null && includeFileFlag.length()> 0){ + cmd[index++] = includeFileFlag + userdefine.getIncludeFile(); + } + + iter = includePath.iterator(); + while (iter.hasNext()) { + cmd[index++] = (String)iter.next(); + } + if (userdefine.getOutdir() != null){ + // will add code to generate outfile name and flag + cmd[index++] = "/nologo"; + } + + if (entryPointFlag != null && entryPointFlag.length()> 0){ + cmd[index++] = entryPointFlag + userdefine.getEntryPointvalue(); + } + if (mapFlag != null && mapFlag.length() > 0){ + cmd[index++] = mapFlag + userdefine.getMapvalue(); + } + if (pdbFlag != null && pdbFlag.length() > 0){ + cmd[index++] = pdbFlag + userdefine.getPdbvalue(); + } + + if (libSetList != null && libSetList.size() > 0){ + for (int k = 0; k < libSetList.size(); k++){ + cmd[index++] = libSetList.get(k); + } + } + + // execute the command + cmd[index++] = scanner.getBasedir() + "/" + fileNames[j]; + for (int k = 0; k < cmd.length; k++){ + } + int retval = runCommand(cctask, workdir, cmd); + // if with monitor, add more code + if (retval != 0) { + throw new BuildException(this.command + + " failed with return code " + retval, + cctask.getLocation()); + } + } + } + } + } + + protected int runCommand(CCTask task, File workingDir, String[] cmdline) + throws BuildException { + return CUtil.runCommand(task, workingDir, cmdline, false, null); + + } + + protected String getInputFileArgument(File outputDir, String filename, + int index) { + // + // if there is an embedded space, + // must enclose in quotes + if (filename.indexOf(' ') >= 0) { + StringBuffer buf = new StringBuffer("\""); + buf.append(filename); + buf.append("\""); + return buf.toString(); + } + return filename; + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineArgument.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineArgument.java new file mode 100644 index 0000000000..85d9a04e73 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineArgument.java @@ -0,0 +1,31 @@ +/* + * + * Copyright 2002-2006 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.userdefine; + +import net.sf.antcontrib.cpptasks.types.CommandLineArgument; + +public class UserDefineArgument extends CommandLineArgument { + + public UserDefineArgument() { + } + + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineCompiler.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineCompiler.java new file mode 100644 index 0000000000..382975abb0 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineCompiler.java @@ -0,0 +1,219 @@ +/* + * + * Copyright 2002-2006 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.userdefine; + +import org.apache.tools.ant.Project; + +import net.sf.antcontrib.cpptasks.CCTask; +import org.tianocore.build.toolchain.*; + +public class UserDefineCompiler extends CommandLineUserDefine { + + public UserDefineCompiler(CCTask cctask, UserDefineDef userdefineDef) { + String arch = null; + String os = null; + String vendor = null; + String commandType = null; + Project project = cctask.getProject(); + // get command string + if (cctask.getArch() == null) { + arch = project.getProperty("ARCH"); + if (arch == null) { + arch = System.getProperty("os.arch"); + } + } else { + arch = cctask.getArch(); + } + arch = arch.toUpperCase(); + if (cctask.getOs() == null) { + os = project.getProperty("OS"); + if (os == null) { + os = System.getProperty("os.name"); + } + } else { + os = cctask.getOs(); + } + + commandType = userdefineDef.getType(); + + if (commandType != null) { + if (ToolChainFactory.getValue(arch + "_" + commandType + "_VENDOR") != null + && ToolChainFactory.getValue( + arch + "_" + commandType + "_VENDOR").trim() + .length() > 0) { + vendor = ToolChainFactory.getValue(arch + "_" + commandType + + "_VENDOR"); + } else if (ToolChainFactory.getValue(arch + "_VENDOR") != null) { + vendor = ToolChainFactory.getValue(arch + "_VENDOR"); + } + } + + // look if ARCH_VENDOR_OS_COMMANDTYPE is existed + if (arch != null && vendor != null && os != null && commandType != null) { + command = project.getProperty(arch + "_" + vendor + "_" + os + "_" + + commandType); + } + // look if ARCH_VENDOR_COMMANDTYPE is existed + if (command == null) { + if (arch != null && vendor != null && commandType != null) { + command = project.getProperty(arch + "_" + vendor + "_" + + commandType); + } + } + // look if ARCH_COMMANDTYPE is existed + if (command == null) { + if (arch != null && commandType != null) { + command = project.getProperty(arch + "_" + commandType); + } + } + // look if COMMANDTYPE is existed + if (command == null) { + if (commandType != null) { + command = project.getProperty(commandType); + } + } + // using the default value from VENDOR_OS_COMMANDTYPE or + // VENDOR_COMMANDTYPE + if (command == null) { + if (vendor != null && os != null && commandType != null) { + String str = vendor + "_" + os + "_" + commandType; + command = UserDefineMapping.getDefaultCommand(str); + } + } + // VENDOR_COMMANDTYPE + if (command == null) { + if (vendor != null && commandType != null) { + String str = vendor + "_" + commandType; + command = UserDefineMapping.getDefaultCommand(str); + } + } + // just give the name whatever + if (command == null) { + command = "cl"; + } + + // initialize the includePathDelimiter + if (userdefineDef.getIncludepathDelimiter() != null) { + includePathDelimiter = userdefineDef.getIncludepathDelimiter(); + } + // else find VENDOR + else { + if (vendor != null) { + includePathDelimiter = UserDefineMapping + .getIncludePathDelimiter(vendor, commandType); + } + } + if (includePathDelimiter == null) { + includePathDelimiter = "-I"; + } + /* + * Set libSet. + */ + if (userdefineDef.getLibSet() != null + && userdefineDef.getLibSet().size() > 0) { + String[] libList; + if (vendor.equalsIgnoreCase("GCC")) { + libSetList.add("-("); + for (int i = 0; i < userdefineDef.getLibSet().size(); i++) { + libList = userdefineDef.getLibSet().get(i).getLibs(); + for (int j = 0; j < libList.length; j++) { + libSetList.add(libList[j]); + } + } + libSetList.add("-)"); + } else { + for (int i = 0; i < userdefineDef.getLibSet().size(); i++) { + libList = userdefineDef.getLibSet().get(i).getLibs(); + for (int j = 0; j < libList.length; j++) { + libSetList.add(libList[j]); + } + } + } + } + /* + * set includeFileFlag + */ + if (userdefineDef.getIncludeFile() != null) { + if (userdefineDef.getIncludeFileFlag() != null) { + includeFileFlag = userdefineDef.getIncludeFileFlag(); + } else { + includeFileFlag = UserDefineMapping.getCompellingIncFileFlag( + vendor, commandType); + } + } + /* + * set entryPointFlag + */ + if (userdefineDef.getEntryPointvalue() != null) { + if (userdefineDef.getEntryPointFlag() != null) { + entryPointFlag = userdefineDef.getEntryPointFlag(); + } else { + entryPointFlag = UserDefineMapping.getEntryPointFlag(vendor, + commandType); + } + } + /* + * set subSystemFlag + */ + if (userdefineDef.getSubSystemvalue() != null) { + if (userdefineDef.getSubSystemFlag() != null) { + subSystemFlag = userdefineDef.getSubSystemFlag(); + } else { + subSystemFlag = UserDefineMapping.getSubSystemFlag(vendor, + commandType); + } + } + /* + * set mapFlag + */ + if (userdefineDef.getMapvalue() != null) { + if (userdefineDef.getMapFlag() != null) { + mapFlag = userdefineDef.getMapFlag(); + } else { + mapFlag = UserDefineMapping.getMapFlag(vendor, commandType); + } + } + /* + * set pdbFlag + */ + if (userdefineDef.getPdbvalue() != null) { + if (userdefineDef.getPdbFlag() != null) { + pdbFlag = userdefineDef.getPdbFlag(); + } else { + pdbFlag = UserDefineMapping.getPdbFlag(vendor, commandType); + } + } + /* + * set outputFileFlag + */ + if (userdefineDef.getOutputFile() != null) { + if (userdefineDef.getOutPutFlag() != null) { + outputFileFlag = userdefineDef.getOutPutFlag(); + } else { + outputFileFlag = UserDefineMapping.getOutputFileFlag(vendor, + arch, commandType); + } + } + + /* + * set fileList + */ + if (userdefineDef.getFileList() != null) { + fileList = userdefineDef.getFileList(); + } + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineDef.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineDef.java new file mode 100644 index 0000000000..f17edcf4ae --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineDef.java @@ -0,0 +1,497 @@ +/* + * + * Copyright 2002-2006 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.userdefine; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.FileList; +import org.apache.tools.ant.types.FileSet; + +import sun.nio.cs.ext.TIS_620; + +import net.sf.antcontrib.cpptasks.ProcessorDef; +import net.sf.antcontrib.cpptasks.types.AslcompilerArgument; +import net.sf.antcontrib.cpptasks.types.ConditionalPath; +import net.sf.antcontrib.cpptasks.types.IncludePath; +import net.sf.antcontrib.cpptasks.types.LibrarySet; + +public class UserDefineDef extends ProcessorDef{ + + public UserDefineDef () {} + + private String type = "CC"; + private String includepathDelimiter; + + private File outdir; + private File workdir; + + private String inputSuffix; + private String outputSuffix; + + private Vector includePaths= new Vector(); + private Vector fileSetList = new Vector(); + + /** + * New adding for support GCC toolchain. + * Most of those only have one value for example : + * entryPoint, mapFile, pdbFile, define those as element because + * if attribut too much the command line is not good-lookinng. + */ + + private Vector includeFiles = new Vector(); + private Vector outPutFiles = new Vector(); + private Vector subSystem = new Vector(); + private Vector entryPoint = new Vector(); + private Vector map = new Vector(); + private Vector pdb = new Vector(); + private Vector libSet = new Vector(); + + public void execute() throws org.apache.tools.ant.BuildException { + throw new org.apache.tools.ant.BuildException( + "Not an actual task, but looks like one for documentation purposes"); + } + + + public void addConfiguredArgument(UserDefineArgument arg) { + if (isReference()) { + throw noChildrenAllowed(); + } + addConfiguredProcessorArg(arg); + } + + /** + * Creates an include path. + */ + public IncludePath createIncludePath() { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project must be set"); + } + if (isReference()) { + throw noChildrenAllowed(); + } + IncludePath path = new IncludePath(p); + includePaths.addElement(path); + return path; + } + + + /** + * Add a if specify the file attribute + * + * @throws BuildException + * if the specify file not exist + */ + protected void loadFile(Vector activePath, File file) throws BuildException { + FileReader fileReader; + BufferedReader in; + String str; + if (!file.exists()) { + throw new BuildException("The file " + file + " is not existed"); + } + try { + fileReader = new FileReader(file); + in = new BufferedReader(fileReader); + while ((str = in.readLine()) != null) { + if (str.trim() == "") { + continue; + } + str = getProject().replaceProperties(str); + activePath.addElement(str.trim()); + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } + + /** + * Returns the specific include path. + */ + public String[] getActiveIncludePaths() { + if (isReference()) { + return ((UserDefineDef) getCheckedRef(UserDefineDef.class, + "UserDefineDef")).getActiveIncludePaths(); + } + return getActivePaths(includePaths); + } + + private String[] getActivePaths(Vector paths) { + Project p = getProject(); + if (p == null) { + throw new java.lang.IllegalStateException("project not set"); + } + Vector activePaths = new Vector(paths.size()); + for (int i = 0; i < paths.size(); i++) { + ConditionalPath path = (ConditionalPath) paths.elementAt(i); + if (path.isActive(p)) { + if (path.getFile() == null) { + String[] pathEntries = path.list(); + for (int j = 0; j < pathEntries.length; j++) { + activePaths.addElement(pathEntries[j]); + } + } else { + loadFile(activePaths, path.getFile()); + } + } + } + String[] pathNames = new String[activePaths.size()]; + activePaths.copyInto(pathNames); + return pathNames; + } + + public String getIncludepathDelimiter() { + if (isReference()) { + return ((UserDefineDef) getCheckedRef(UserDefineDef.class, + "UserDefineDef")).getIncludepathDelimiter(); + } + return includepathDelimiter; + } + + public void setIncludepathDelimiter(String includepathDelimiter) { + if (isReference()) { + throw tooManyAttributes(); + } + this.includepathDelimiter = includepathDelimiter; + } + + public String getInputSuffix() { + if (isReference()) { + return ((UserDefineDef) getCheckedRef(UserDefineDef.class, + "UserDefineDef")).getInputSuffix(); + } + return inputSuffix; + } + + public void setInputSuffix(String inputSuffix) { + if (isReference()) { + throw tooManyAttributes(); + } + this.inputSuffix = inputSuffix; + } + + public File getOutdir() { + if (isReference()) { + return ((UserDefineDef) getCheckedRef(UserDefineDef.class, + "UserDefineDef")).getOutdir(); + } + return outdir; + } + + public void setOutdir(File outdir) { + if (isReference()) { + throw tooManyAttributes(); + } + this.outdir = outdir; + } + + public String getOutputSuffix() { + if (isReference()) { + return ((UserDefineDef) getCheckedRef(UserDefineDef.class, + "UserDefineDef")).getOutputSuffix(); + } + return outputSuffix; + } + + public void setOutputSuffix(String outputSuffix) { + if (isReference()) { + throw tooManyAttributes(); + } + this.outputSuffix = outputSuffix; + } + + public String getType() { + if (isReference()) { + return ((UserDefineDef) getCheckedRef(UserDefineDef.class, + "UserDefineDef")).getType(); + } + return type; + } + + public void setType(String type) { + if (isReference()) { + throw tooManyAttributes(); + } + this.type = type; + } + + public File getWorkdir() { + if (isReference()) { + return ((UserDefineDef) getCheckedRef(UserDefineDef.class, + "UserDefineDef")).getWorkdir(); + } + return workdir; + } + + public void setWorkdir(File workdir) { + if (isReference()) { + throw tooManyAttributes(); + } + this.workdir = workdir; + } + + /** + * Add an libSet. + */ + public LibrarySet createLibset() { + if (isReference()){ + throw noChildrenAllowed(); + } + LibrarySet lib = new LibrarySet(); + libSet.addElement(lib); + return lib; + } + + public String getLibSetString(){ + String libString = null; + for (int i = 0; i < libSet.size(); i++){ + String[] libList = libSet.get(i).getLibs(); + for (int j = 0; j < libList.length; j++){ + libString = libString + libList[j] + " "; + } + } + return libString; + } + + public Vector getLibSet(){ + return this.libSet; + } + + /** + * Add map element + */ + public void addMap(UserDefineElement mapElement){ + if (isReference()){ + throw noChildrenAllowed(); + }else{ + this.map.addElement(mapElement); + } + } + + public Vector getMap (){ + return this.map; + } + + public String getMapvalue (){ + if (this.map.size() > 0){ + /* + * If user set more than one map use the first one. + */ + return this.map.get(0).value; + } + return null; + + } + public String getMapFlag(){ + if (this.map.size() > 0){ + /* + * If user set more than one map use the first one. + */ + return this.map.get(0).flag; + } + return null; + } + /** + * Add pdb element + */ + public void addPdb(UserDefineElement pdbElement){ + if (isReference()){ + throw noChildrenAllowed(); + } + this.pdb.addElement(pdbElement); + } + + public Vector getPdb(){ + return this.pdb; + } + public String getPdbvalue (){ + if (this.pdb.size() > 0){ + /* + * If user set more than one pdb use the first one. + * + */ + return this.pdb.get(0).value; + } + return null; + + } + public String getPdbFlag(){ + if (this.pdb.size() > 0){ + /* + * If user set more than one pdb use the first one. + */ + return this.pdb.get(0).flag; + } + return null; + } + + /** + * add entryPoint element. + */ + public void addEntryPoint(UserDefineElement entryPointElement){ + if (isReference()){ + throw noChildrenAllowed(); + } + this.entryPoint.addElement(entryPointElement); + } + + public Vector getEntryPoint(){ + return this.entryPoint; + } + + public String getEntryPointvalue (){ + if (this.entryPoint.size() > 0){ + /* + * If user set more than one entryPoint use the first one. + */ + return this.entryPoint.get(0).value; + } + return null; + + } + public String getEntryPointFlag(){ + if (this.entryPoint.size() > 0){ + /* + * If user set more than one entry point use the first one. + */ + return this.entryPoint.get(0).flag; + } + return null; + } + + /** + * Add subSystem element. + */ + public void addSubSystem (UserDefineElement subSystem){ + if (isReference()){ + throw noChildrenAllowed(); + } + this.subSystem.addElement(subSystem); + } + public Vector getSubSystem (){ + return this.subSystem; + } + + public String getSubSystemvalue (){ + if (this.subSystem.size() > 0){ + /* + * If user set more than one subsystem use the first one. + */ + return this.subSystem.get(0).value; + } + return null; + + } + public String getSubSystemFlag(){ + if (this.subSystem.size() > 0){ + /* + * If user set more than one subsystem use the first one. + */ + return this.subSystem.get(0).flag; + } + return null; + } + /** + * Add includeFile element + */ + public void addIncludeFile (UserDefineElement includeFile){ + if (isReference()){ + throw noChildrenAllowed(); + } + this.includeFiles.addElement(includeFile); + } + public Vector getIncludeFiles(){ + return this.includeFiles; + } + + public String getIncludeFile (){ + if (this.includeFiles.size() > 0){ + /* + * If user set more than one map use the first one. + */ + return this.includeFiles.get(0).value; + } + return null; + + } + public String getIncludeFileFlag(){ + if (this.includeFiles.size() > 0){ + /* + * If user set more than one map use the first one. + */ + return this.includeFiles.get(0).flag; + } + return null; + } + + /** + * Add OutputFile element + */ + public void addOutputFile (UserDefineElement outPutFile){ + if (isReference()){ + throw noChildrenAllowed(); + } + this.outPutFiles.addElement(outPutFile); + } + + public Vector getOutputFiles(){ + return this.outPutFiles; + } + + public String getOutputFile (){ + if (this.outPutFiles.size() > 0){ + /* + * If user set more than one map use the first one. + */ + return this.outPutFiles.get(0).value; + } + return null; + + } + public String getOutPutFlag(){ + if (this.outPutFiles.size() > 0){ + /* + * If user set more than one map use the first one. + */ + return this.outPutFiles.get(0).flag; + } + return null; + } + + /** + * Add fileSet list + */ + public void addFileList(FileList fileSet){ + this.fileSetList.addElement(fileSet); + } + + public Vector getFileList(){ + Project p = getProject(); + Vector fileListVector = new Vector(); + for (int i = 0; i < this.fileSetList.size(); i++){ + String[] tempStrList = this.fileSetList.get(i).getFiles(p); + for (int j = 0; j < tempStrList.length; j++){ + fileListVector .addElement(tempStrList[j]); + } + } + return fileListVector; + } +} diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineElement.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineElement.java new file mode 100644 index 0000000000..b8c852c51a --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineElement.java @@ -0,0 +1,23 @@ +package net.sf.antcontrib.cpptasks.userdefine; + +public class UserDefineElement { + String flag = null; + String value = null; + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public String getFlag() { + return flag; + } + + public void setFlag(String flag) { + this.flag = flag; + } + +} \ No newline at end of file diff --git a/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineMapping.java b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineMapping.java new file mode 100644 index 0000000000..bb290efba2 --- /dev/null +++ b/Tools/Source/Cpptasks/net/sf/antcontrib/cpptasks/userdefine/UserDefineMapping.java @@ -0,0 +1,186 @@ +/* + * + * Copyright 2001-2004 The Ant-Contrib project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package net.sf.antcontrib.cpptasks.userdefine; +public class UserDefineMapping { + // list of Arch: EBC, ARM, IA32, X64, IPF, PPC, NT32 + public final static String[] arch = { "EBC", "ARM", "IA32", "X64", "IPF", + "PPC", "NT32" }; + + // list of OS: Linux, Windows + public final static String[] os = { "WINDOWS", "LINUX" }; + + // list of Vendor: Microsoft, Intel, Cygwin, Gcc + public final static String[] vendor = { "MSFT", "INTEL", "GCC", "CYGWIN" }; + + // list of Command Type: CC, LIB, LINK, ASL, ASM, ASMLINK + public final static String[] commandType = { "CC", "LIB", "LINK", "ASL", + "ASM", "ASMLINK", "PP" }; + + // + // flags mapping (Include compellingIncFileFlag,Path Delimiter, Output file + // flag, + // includepathfalge, + // ) + // Examples: '/I' for MSFT cl.exe while '-I' for GCC + // '/Fo' for MSFT cl.exe while '-o' for GCC + // + public final static String[][] compellingIncFileFlag = { + { "MSFT_CC", "/FI" }, { "GCC_CC", "-include" }, + { "INTEL_CC", "-FI" }, { "WINDDK_CC", "/FI" }, + { "MSFT_ASM", "/FI" }, { "GCC_ASM", "-include" }, + { "WINDDK_ASM", "/FI" } }; + + public final static String[][] includePathFlag = { { "MSFT_CC", "/I" }, + { "GCC_CC", "-I" }, { "INTEL_CC", "/I" }, { "WINDDK_CC", "/I" }, + { "MSFT_ASM", "/I" }, { "GCC_ASM", "-I" }, { "WINDDK_CC", "/I" }, + { "MSFT_PP", "/I" }, { "GCC_PP", "-I" }, { "WINDDK_PP", "/I" } }; + + public final static String[][] outputFileFlag = { { "MSFT_CC", "/Fo" }, + { "GCC_CC", "-o" }, { "INTEL_CC", "/Fo" }, { "WINDDK_CC", "/Fo" }, + { "MSFT_LIB", "/OUT:" }, { "GCC_LIB", "-cr" }, + { "INTEL_LIB", "/OUT:" }, { "WINDDK_LIB", "/OUT:" }, + { "MSFT_LINK", "/OUT:" }, { "GCC_LINK", "-o" }, + { "INTEL_LINK", "/OUT:" }, { "WINDDK_LINK", "/OUT:" }, + { "MSFT_ASM", "/Fo" }, { "GCC_ASM", "-o" }, + { "WINDDK_ASM", "/Fo" },{"WINDDK_IPF_ASM", "-o"} }; + + public final static String[][] subSystemFlag = { + { "MSFT_LIB", "/SUBSYSTEM:" }, { "GCC_LIB", "--subsystem=" }, + { "WINDDk_LIB", "/SUBSYSTEM:" }, { "INTEL_LIB", "/SUBSYSTEM:" }, + { "MSFT_LINK", "/SUBSYSTEM:" }, { "GCC_LINK", "--subsystem=" }, + { "INTEL_LINK", "/SUBSYSTEM:" }, { "WINDDK_LINK", "/SUBSYSTEM:" } }; + + public final static String[][] outputFileSuffix = { + { "WINDOWS_ASM", ".obj" }, { "WINDOWS_CC", ".obj" }, + { "LINUX_ASM", ".o" }, { "LINUX_CC", ".o" } }; + + public final static String[][] entryPointFlag = { + { "MSFT_LINK", "/ENTRY:" }, { "GCC_LINK", "-e" }, + { "INTEL_LINK", "/ENTRY:" }, + { "WINDDK_LINK", "/ENTRY:" } }; + + public final static String[][] mapFlag = { { "MSFT_LINK", "/MAP:" }, + { "GCC_LINK", "" }, { "INTEL_LINK", "/MAP:" }, + { "WINDDK_LINK", "/MAP:" } }; + + public final static String[][] pdbFlag = { { "MSFT_LINK", "/PDB:" }, + { "GCC_LINK", "" }, { "INTEL_LINK", "" }, { "WINDDK_LINK", "/PDB:"} }; + + public static String getIncludePathDelimiter(String vendor, + String commandType) { + String key = vendor + "_" + commandType; + for (int i = 0; i < includePathFlag.length; i++) { + if (includePathFlag[i][0].equalsIgnoreCase(key)) { + return includePathFlag[i][1]; + } + } + return null; + } + + public static String getOutputFileFlag(String vendor, String arch, String commandType) { + /* + * First find outputfileFlag by vendor_arch_commandType + */ + String key = vendor + "_" + arch + "_" + commandType; + for (int i = 0; i < outputFileFlag.length; i++) { + if (outputFileFlag[i][0].equalsIgnoreCase(key)) { + return outputFileFlag[i][1]; + } + } + key = vendor + "_" + commandType; + for (int i = 0; i < outputFileFlag.length; i++) { + if (outputFileFlag[i][0].equalsIgnoreCase(key)) { + return outputFileFlag[i][1]; + } + } + return null; + } + + public static String getCompellingIncFileFlag(String vendor, + String commandType) { + String key = vendor + "_" + commandType; + for (int i = 0; i < compellingIncFileFlag.length; i++) { + if (compellingIncFileFlag[i][0].equalsIgnoreCase(key)) { + return compellingIncFileFlag[i][1]; + } + } + return null; + } + + public static String getSubSystemFlag(String vendor, String commandType) { + String key = vendor + "_" + commandType; + for (int i = 0; i < subSystemFlag.length; i++) { + if (subSystemFlag[i][0].equalsIgnoreCase(key)) { + return subSystemFlag[i][1]; + } + } + return null; + } + + public static String getEntryPointFlag(String vendor, String commandType) { + String key = vendor + "_" + commandType; + for (int i = 0; i < entryPointFlag.length; i++) { + if (entryPointFlag[i][0].equalsIgnoreCase(key)) { + return entryPointFlag[i][1]; + } + } + return null; + } + + public static String getMapFlag(String vendor, String commandType) { + String key = vendor + "_" + commandType; + for (int i = 0; i < mapFlag.length; i++) { + if (mapFlag[i][0].equalsIgnoreCase(key)) { + return mapFlag[i][1]; + } + } + return null; + } + + public static String getPdbFlag(String vendor, String commandType) { + String key = vendor + "_" + commandType; + for (int i = 0; i < pdbFlag.length; i++) { + if (pdbFlag[i][0].equalsIgnoreCase(key)) { + return pdbFlag[i][1]; + } + } + return null; + } + + // + // Well-known source file suffix and output file suffix relationship + // sourceExtension(Multiple), + // headExtension(Multiple) and outputSuffix(Single) + // + + // + // Default command string such as 'cl' in MSFT while 'gcc' in GCC + // + public final static String[][] defaultCommand = { { "GCC", "gcc" }, + { "MSFT_CC", "cl" }, { "MSFT_LIB", "lib" }, + { "MSFT_LINK", "link" }, }; + + public static String getDefaultCommand(String toolchain) { + for (int i = 0; i < defaultCommand.length; i++) { + if (defaultCommand[i][0].equalsIgnoreCase(toolchain)) { + return defaultCommand[i][1]; + } + } + return null; + } + +} \ No newline at end of file diff --git a/Tools/Source/CreateMdkPkg/MANIFEST.MF b/Tools/Source/CreateMdkPkg/MANIFEST.MF new file mode 100644 index 0000000000..28f83c0ce2 --- /dev/null +++ b/Tools/Source/CreateMdkPkg/MANIFEST.MF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Main-Class: org.tianocore.packaging.workspace.ui.Welcome diff --git a/Tools/Source/CreateMdkPkg/build.xml b/Tools/Source/CreateMdkPkg/build.xml new file mode 100644 index 0000000000..1352d5d8d8 --- /dev/null +++ b/Tools/Source/CreateMdkPkg/build.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/common/Log.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/common/Log.java new file mode 100644 index 0000000000..383ffa719a --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/common/Log.java @@ -0,0 +1,188 @@ +/** @file + + The file is used to provides static interfaces to save log and error information + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.common; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.swing.JOptionPane; + +/** + The class is used to provides static interfaces to save log and error information + + @since CreateMdkPkg 1.0 + + **/ +public class Log { + + // + //Log file + // + private static File fleLogFile = null; + + // + //Err file + // + private static File fleErrFile = null; + + // + //Log file name + // + static String strLogFileName = "Log.log"; + + // + //Err file name + // + static String strErrFileName = "Err.log"; + + /** + Main class, used for test + + @param args + + **/ + public static void main(String[] args) { + try { + Log.log("Test", "test"); + Log.err("Test1", "test1"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + This is the default constructor + Do nothing + + **/ + public Log() { + } + + /** + Call writeToLogFile to save log item and log information to log file + + @param strItem The log item + @param strLog The log information + + **/ + public static void log(String strItem, String strLog) { + try { + writeToLogFile(strItem + ":" + strLog); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + Call writeToLogFile to save log information to log file + + @param strLog The log information + + **/ + public static void log(String strLog) { + try { + writeToLogFile(strLog); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + Call writeToErrFile to save err item and err information to err file + + @param strItem The err item + @param strLog The err information + + **/ + public static void err(String strItem, String strErr) { + try { + writeToErrFile("Error when " + strItem + ":" + strErr); + JOptionPane.showConfirmDialog(null, "Error when " + strItem + "::" + strErr, "Error", + JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); + + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + Call writeToErrFile to save err information to err file + + @param strLog The err information + + **/ + public static void err(String strErr) { + try { + writeToErrFile("Error::" + strErr); + JOptionPane.showConfirmDialog(null, "Error::" + strErr, "Error", JOptionPane.DEFAULT_OPTION, + JOptionPane.ERROR_MESSAGE); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + Open log file and write log information + + @param strLog The log information + @throws IOException + + **/ + private static void writeToLogFile(String strLog) throws IOException { + try { + if (fleLogFile == null) { + fleLogFile = new File(strLogFileName); + fleLogFile.createNewFile(); + } + FileOutputStream fos = new FileOutputStream(fleLogFile, true); + fos.write((Tools.getCurrentDateTime() + "\r\n").getBytes()); + fos.write((strLog + "\r\n").getBytes()); + fos.flush(); + fos.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + Open err file and write err information + + @param strLog The log information + @throws IOException + + **/ + private static void writeToErrFile(String strLog) throws IOException { + try { + if (fleErrFile == null) { + fleErrFile = new File(strErrFileName); + fleErrFile.createNewFile(); + } + FileOutputStream fos = new FileOutputStream(fleErrFile, true); + fos.write((Tools.getCurrentDateTime() + "\r\n").getBytes()); + fos.write((strLog + "\r\n").getBytes()); + fos.flush(); + fos.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/common/Tools.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/common/Tools.java new file mode 100644 index 0000000000..2494b03815 --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/common/Tools.java @@ -0,0 +1,120 @@ +/** @file + + The file is used to provides some useful interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.common; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +/** + The class is used to provides some useful interfaces + + @since CreateMdkPkg 1.0 + + **/ +public class Tools { + + /** + Used for test + + @param args + + **/ + public static void main(String[] args) { + System.out.println(getCurrentDateTime()); + } + + /** + Get current date and time and format it as "yyyy-MM-dd HH:mm" + + @return formatted current date and time + + **/ + public static String getCurrentDateTime() { + Date now = new Date(System.currentTimeMillis()); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + return sdf.format(now); + } + + /** + Delete a folder and all its files + + @param fleFolderName The name of the folder which need be deleted + + @retval true - Delete successfully + @retval false - Delete successfully + + **/ + public static boolean deleteFolder(File fleFolderName) { + boolean blnIsDeleted = true; + File[] aryAllFiles = fleFolderName.listFiles(); + + for (int indexI = 0; indexI < aryAllFiles.length; indexI++) { + if (blnIsDeleted) { + if (aryAllFiles[indexI].isDirectory()) { + // + //If is a directory, recursively call this function to delete sub folders + // + blnIsDeleted = deleteFolder(aryAllFiles[indexI]); + } else if (aryAllFiles[indexI].isFile()) { + // + //If is a file, delete it + // + if (!aryAllFiles[indexI].delete()) { + blnIsDeleted = false; + } + } + } + } + if (blnIsDeleted) { + fleFolderName.delete(); + } + return blnIsDeleted; + } + + /** + Generate a UUID + + @return the created UUID + + **/ + public static String generateUuidString() { + return UUID.randomUUID().toString(); + } + + /** + Get all system properties and output to the console + + **/ + public static void getSystemProperties() { + System.out.println(System.getProperty("java.class.version")); + System.out.println(System.getProperty("java.class.path")); + System.out.println(System.getProperty("java.ext.dirs")); + System.out.println(System.getProperty("os.name")); + System.out.println(System.getProperty("os.arch")); + System.out.println(System.getProperty("os.version")); + System.out.println(System.getProperty("file.separator")); + System.out.println(System.getProperty("path.separator")); + System.out.println(System.getProperty("line.separator")); + System.out.println(System.getProperty("user.name")); + System.out.println(System.getProperty("user.home")); + System.out.println(System.getProperty("user.dir")); + System.out.println(System.getProperty("PATH")); + + System.out.println(System.getenv("PROCESSOR_REVISION")); + } +} diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/FrameworkPkg.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/FrameworkPkg.java new file mode 100644 index 0000000000..e12b58438f --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/FrameworkPkg.java @@ -0,0 +1,238 @@ +/** @file + + The file is used to install .jar file + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import javax.swing.JFrame; + +/** + The class is used to install .jar file + + @since CreateMdkPkg 1.0 + + **/ +public class FrameworkPkg { + // + // Define class members + // + static JFrame frame; + + private String pkg = null; + + private JarFile jf = null; + + /** + Main clase, used to test + + @param args + + **/ + public static void main(String[] args) { + FrameworkPkg fp = new FrameworkPkg("C:\\Documents and Settings\\hchen30\\Desktop\\com.jar"); + try { + fp.install("C:\\MyWorkspace" + System.getProperty("file.separator")); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + This is the default constructor + + **/ + public FrameworkPkg() { + + } + + /** + This is the override constructor + + @param package_name + + **/ + public FrameworkPkg(String package_name) { + pkg = package_name; + } + + /** + Get package name + + @param package_name + + **/ + public void setPkg(String package_name) { + pkg = package_name; + } + + /** + Set Jarfile + + @throws IOException + + **/ + public void setJarFile() throws IOException { + jf = new JarFile(pkg); + } + + /** + Install the jar file to specific path + + @param dir The target path + @return 0 - success + @throws IOException + @throws BasePkgNotInstalled + @throws VerNotEqual + @throws GuidNotEqual + @throws SameAll + + **/ + public int install(final String dir) throws IOException, BasePkgNotInstalled, VerNotEqual, GuidNotEqual, SameAll { + pre_install(); + extract(dir); + post_install(); + return 0; + } + + /** + + @return + + **/ + public int uninstall() { + + return 0; + } + + /** + Check before install + + @throws IOException + @throws BasePkgNotInstalled + @throws VerNotEqual + @throws GuidNotEqual + @throws SameAll + + **/ + protected void pre_install() throws IOException, BasePkgNotInstalled, VerNotEqual, GuidNotEqual, SameAll { + jf = new JarFile(pkg); + if (false) { + throw new BasePkgNotInstalled(); + } + if (false) { + throw new VerNotEqual(); + } + if (false) { + throw new GuidNotEqual(); + } + if (false) { + throw new SameAll(); + } + } + + /** + End of install + + @throws IOException + + **/ + protected void post_install() throws IOException { + jf.close(); + + } + + /** + Extract the jar file to specific dir + + @param dir The target path + @throws IOException + + **/ + private synchronized void extract(String dir) throws IOException { + + int i = 0; + try { + for (Enumeration e = jf.entries(); e.hasMoreElements(); i++) { + JarEntry je = (JarEntry) e.nextElement(); + if (je.getName().contains("META-INF")) + continue; + if (je.isDirectory()) { + new File(dir + je.getName()).mkdirs(); + continue; + } + + if (je != null) { + // + // Get an input stream for the entry. + // + InputStream entryStream = jf.getInputStream(je); + + try { + // + // Create the output file (clobbering the file if it exists). + // + FileOutputStream file = new FileOutputStream(dir + je.getName()); + + try { + // + // Allocate a buffer for reading the entry data. + // + byte[] buffer = new byte[1024]; + int bytesRead; + + // + // Read the entry data and write it to the output file. + // + while ((bytesRead = entryStream.read(buffer)) != -1) { + file.write(buffer, 0, bytesRead); + } + + System.out.println(je.getName() + " extracted."); + } finally { + file.close(); + } + } finally { + entryStream.close(); + } + } + } + } finally { + jf.close(); + } + } +} + +class BasePkgNotInstalled extends Exception { + final static long serialVersionUID = 0; +} + +class VerNotEqual extends Exception { + final static long serialVersionUID = 0; +} + +class GuidNotEqual extends Exception { + final static long serialVersionUID = 0; +} + +class SameAll extends Exception { + final static long serialVersionUID = 0; +} diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/MdkPkg.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/MdkPkg.java new file mode 100644 index 0000000000..74250cc4a6 --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/MdkPkg.java @@ -0,0 +1,59 @@ +/** @file + + The file is used to override FrameworkPkg to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging; + +import java.io.IOException; + +/** + The class is used to override FrameworkPkg to provides customized interfaces + + @since CreateMdkPkg 1.0 + + **/ +public class MdkPkg extends FrameworkPkg { + + /** + Main class, reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + /** + This is the default constructor + + @param strJarFile The jar file need be installed + @throws IOException + + **/ + public MdkPkg(String strJarFile) throws IOException { + this.setPkg(strJarFile); + this.setJarFile(); + } + + /* (non-Javadoc) + * @see org.tianocore.packaging.FrameworkPkg#pre_install() + * + * Override pre_install to do nothing + * + */ + protected void pre_install() { + } +} diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/common/ui/ExitConfirm.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/common/ui/ExitConfirm.java new file mode 100644 index 0000000000..170ca6255d --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/common/ui/ExitConfirm.java @@ -0,0 +1,264 @@ +/** @file + + The file is used to popup a exit confirmation window when program exists + + Copyright (c) 2006, 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. + **/ +package org.tianocore.packaging.common.ui; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** + The class is used to popup a exit confirmation window when program exists + It extends JDialog and implements ActionListener and WindowListener + + @since CreateMdkPkg 1.0 + + **/ +public class ExitConfirm extends JDialog implements ActionListener, WindowListener { + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -5875921789385911029L; + + // + // Define class members + // + private JPanel jContentPane = null; + + private JLabel jLabelMessage = null; + + private JLabel jLabelResume = null; + + private JLabel jLabelExit = null; + + private JButton jButtonResume = null; + + private JButton jButtonExit = null; + + public boolean isCancel = false; + + /** + This method initializes jButtonResume + + @return javax.swing.JButton jButtonResume + + **/ + private JButton getJButtonResume() { + if (jButtonResume == null) { + jButtonResume = new JButton(); + jButtonResume.setText("Resume"); + jButtonResume.setSize(new java.awt.Dimension(90, 20)); + jButtonResume.setLocation(new java.awt.Point(150, 105)); + jButtonResume.setMnemonic('R'); + jButtonResume.addActionListener(this); + } + return jButtonResume; + } + + /** + This method initializes jButtonExit + + @return javax.swing.JButton jButtonExit + + **/ + private JButton getJButtonExit() { + if (jButtonExit == null) { + jButtonExit = new JButton(); + jButtonExit.setText("Exit"); + jButtonExit.setSize(new java.awt.Dimension(90, 20)); + jButtonExit.setLocation(new java.awt.Point(260, 105)); + jButtonExit.setMnemonic('x'); + jButtonExit.addActionListener(this); + } + return jButtonExit; + } + + /** + Main clasee, reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + /** + This is the default constructor + + **/ + public ExitConfirm(IFrame parentFrame, boolean modal) { + super(parentFrame, modal); + initialize(); + } + + /** + This method initializes this + + **/ + private void initialize() { + this.setSize(500, 170); + this.setTitle("Exit"); + this.setResizable(false); + this.setContentPane(getJContentPane()); + this.addWindowListener(this); + // + //Set DO_NOTHING_ON_CLOSE when click Close button on title bar + // + this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + centerWindow(); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelExit = new JLabel(); + jLabelExit.setSize(new java.awt.Dimension(450, 20)); + jLabelExit.setLocation(new java.awt.Point(25, 70)); + jLabelResume = new JLabel(); + jLabelResume.setSize(new java.awt.Dimension(450, 20)); + jLabelResume.setLocation(new java.awt.Point(25, 40)); + jLabelMessage = new JLabel(); + jLabelMessage.setSize(new java.awt.Dimension(450, 20)); + jLabelMessage.setLocation(new java.awt.Point(25, 10)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelMessage, null); + jContentPane.add(jLabelResume, null); + jContentPane.add(jLabelExit, null); + jContentPane.add(getJButtonResume(), null); + jContentPane.add(getJButtonExit(), null); + } + return jContentPane; + } + + /** + Call setWarningMessage to set messages of frame when it is used for Setup + + **/ + public void setSetupMessage() { + String strTitle = "Exit Setup"; + String strMessage = "Setup is not complete. If you quit now, the program will not be installed."; + //String strResume = "You may run the setup program at a later time to complete the installation."; + String strResume = ""; + String strExit = "To continue installing, click Resume. To quit the Setup program, click Exit."; + setWarningMessage(strTitle, strMessage, strResume, strExit); + } + + /** + Call setWarningMessage to set messages of frame when it is used for Module Main GUI + + **/ + public void setModuleMessage() { + String strTitle = "Exit"; + String strMessage = "Do you really want to quit now?"; + String strResume = "All unsaved module information will be lost."; + String strExit = "To continue editing module, click Resume. To quit the program, click Exit."; + setWarningMessage(strTitle, strMessage, strResume, strExit); + } + + /** + Set message information via input data + + @param strTitle The title value + @param strMessage The main message value + @param strResume The resume message value + @param strExit The exit message value + + **/ + private void setWarningMessage(String strTitle, String strMessage, String strResume, String strExit) { + this.setTitle(strTitle); + jLabelMessage.setText(strMessage); + jLabelResume.setText(strResume); + jLabelExit.setText(strExit); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listern all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + // + //Set isCancel true when click button "Exit" + // + Object obj = arg0.getSource(); + if (obj == jButtonResume) { + isCancel = false; + } + if (obj == jButtonExit) { + isCancel = true; + } + this.setVisible(false); + } + + /** + Make the window in the center of the screen + + **/ + private void centerWindow() { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - this.getSize().width) / 2, (d.height - this.getSize().height) / 2); + } + + public void windowActivated(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowClosed(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowClosing(WindowEvent arg0) { + isCancel = false; + this.setVisible(false); + } + + public void windowDeactivated(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowDeiconified(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowIconified(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowOpened(WindowEvent arg0) { + // TODO Auto-generated method stub + + } +} diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/common/ui/IFrame.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/common/ui/IFrame.java new file mode 100644 index 0000000000..211b9c3adb --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/common/ui/IFrame.java @@ -0,0 +1,203 @@ +/** @file + + The file is used to override Frame to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.common.ui; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +import javax.swing.JFrame; + +/** + The class is used to override Frame to provides customized interfaces + It extends JFrame implements ActionListener and WindowListener + + @since CreateMdkPkg 1.0 + + **/ +public class IFrame extends JFrame implements ActionListener, WindowListener { + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -3324138961029300427L; + + // + // Define class members + // + private ExitConfirm ec = null; + + // + // To indicate the status while quit + // 0 - When setup (Default) + // 1 - Whne editing module + // + private int intExitType = 0; + + /** + Main class, used for test + + @param args + + **/ + public static void main(String[] args) { + IFrame i = new IFrame(); + i.setVisible(true); + } + + /** + This is the default constructor + + **/ + public IFrame() { + super(); + initialize(); + } + + /** + This method initializes this + + **/ + public void initialize() { + this.setResizable(false); + this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + this.addWindowListener(this); + } + + /** + Start the dialog at the center of screen + + @param intWidth The width of the dialog + @param intHeight The height of the dialog + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the dialog at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + Set the exit window type + + @param ExitType The input data of ExitType + + **/ + protected void setExitType(int ExitType) { + this.intExitType = ExitType; + } + + /* (non-Javadoc) + * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent) + * + * Override windowClosing to call this.onDisvisible() + * + */ + public void windowClosing(WindowEvent arg0) { + this.onDisvisible(); + } + + public void windowOpened(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowClosed(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowIconified(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowDeiconified(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowActivated(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowDeactivated(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void actionPerformed(ActionEvent arg0) { + // TODO Auto-generated method stub + + } + + /** + Define the actions when exit + + **/ + public void onExit() { + ec = new ExitConfirm(this, true); + // + //Show different warning message via different ExitType + // + switch (intExitType) { + case 0: + ec.setSetupMessage(); + break; + case 1: + ec.setModuleMessage(); + break; + } + ec.setVisible(true); + if (ec.isCancel) { + this.dispose(); + System.exit(0); + } + } + + /** + Define the actions when disvisible + + **/ + public void onDisvisible() { + ec = new ExitConfirm(this, true); + // + //Show different warning message via different ExitType + // + switch (intExitType) { + case 0: + ec.setSetupMessage(); + break; + case 1: + ec.setModuleMessage(); + break; + } + ec.setVisible(true); + if (ec.isCancel) { + this.dispose(); + } + } +} diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/command/InstallWorkspace.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/command/InstallWorkspace.java new file mode 100644 index 0000000000..47bd36fe0a --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/command/InstallWorkspace.java @@ -0,0 +1,161 @@ +/** @file + + The file is used to override AbstractCellEditor to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.workspace.command; + +import java.io.File; +import java.io.IOException; + +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.MdkPkg; + +/** + The class is used to override AbstractCellEditor to provides customized interfaces + + @since CreateMdkPkg 1.0 + + **/ +public class InstallWorkspace { + /** + Main class, reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + /** + This is the default constructor + Reserved + + **/ + public InstallWorkspace() { + // TODO + } + + /** + Check if exist target dir + + @param strInstallDir The install target dir + @retval true - The target exists + @retval false - The target doesn't exist + + **/ + public static boolean isExistInstallDir(String strInstallDir) { + File id = new File(strInstallDir); + return id.exists(); + } + + /** + Create install target dir + + @param strInstallDir The install target dir + @retval true - Install success + @retval false - Install fail + + **/ + public static boolean createInstallDir(String strInstallDir) { + File id = new File(strInstallDir); + try { + return id.mkdir(); + } catch (Exception e) { + System.out.print(e.getMessage()); + return false; + } + } + + /** + Reserved + + @return boolean + + **/ + public static boolean setSystemEnvironment() { + return true; + } + + /** + Reserved + + @return boolean + **/ + public static boolean setToolChainPath() { + return true; + } + + /** + Reserved + + @return boolean + **/ + public static boolean setToolChain() { + return true; + } + + /** + Reserved + + @return boolean + **/ + public static boolean setFrameworkDatabase() { + return true; + } + + /** + Delete setup files and directory + + @param strPath The delete target dir + @retval true - Delete success + @retval false - Delete fail + + **/ + public static boolean delSetupPackage(String strPath) { + File f = new File(strPath); + try { + Tools.deleteFolder(f); + } catch (Exception e) { + e.printStackTrace(); + } + return true; + } + + /** + + @param strInstallDir The install target dir + @param strJarFile The install target file + @retval true - Install success + @retval false - Install fail + @throws IOException + + **/ + public static boolean installPackage(String strInstallDir, String strJarFile) throws IOException { + Log.log("Install Dir", strInstallDir); + Log.log("Jar File Path", strJarFile); + + MdkPkg mp = new MdkPkg(strJarFile); + try { + mp.install(strInstallDir + System.getProperty("file.separator")); + return true; + } catch (Exception e) { + e.printStackTrace(); + Log.log("Install Err", e.toString()); + } + return false; + } +} diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/Finish.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/Finish.java new file mode 100644 index 0000000000..aab046f570 --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/Finish.java @@ -0,0 +1,295 @@ +/** @file + + The file is used to show a Finish page in the last step of setup + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.workspace.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import org.tianocore.packaging.common.ui.IFrame; + +/** + The class is used to show a Finish page in the last step of setup + + @since CreateMdkPkg 1.0 + + **/ +public class Finish extends IFrame implements ActionListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = 9055339173915836187L; + + // + // Define class members + // + private JPanel jContentPane = null; + + private JTextArea jTextAreaTitle = null; + + private JTextArea jTextAreaContent = null; + + private JPanel jPanel = null; + + private JButton jButtonFinish = null; + + private JLabel jLabel = null; + + private JLabel jLabel1 = null; + + private JScrollPane jScrollPane = null; + + private JTextArea jTextAreaComment = null; + + private String strInstallDir = ""; + + /** + This method initializes jTextAreaTitle + + @return javax.swing.JTextArea jTextAreaTitle + + **/ + private JTextArea getJTextAreaTitle() { + if (jTextAreaTitle == null) { + jTextAreaTitle = new JTextArea(); + jTextAreaTitle.setLocation(new java.awt.Point(0, 0)); + jTextAreaTitle.setText(" Click button \"Install\" to start installation"); + jTextAreaTitle.setFont(new java.awt.Font("Dialog", java.awt.Font.BOLD, 14)); + jTextAreaTitle.setEditable(false); + jTextAreaTitle.setSize(new java.awt.Dimension(495, 20)); + } + return jTextAreaTitle; + } + + /** + This method initializes jTextAreaContent + + @return javax.swing.JTextArea jTextAreaContent + + **/ + private JTextArea getJTextAreaContent() { + if (jTextAreaContent == null) { + jTextAreaContent = new JTextArea(); + jTextAreaContent.setLocation(new java.awt.Point(0, 20)); + jTextAreaContent.setText(""); + jTextAreaContent.setEditable(false); + jTextAreaContent.setSize(new java.awt.Dimension(495, 35)); + } + return jTextAreaContent; + } + + /** + This method initializes jPanel + + @return javax.swing.JPanel jPanel + + **/ + private JPanel getJPanel() { + if (jPanel == null) { + jLabel1 = new JLabel(); + jLabel1.setText(""); + jLabel1.setLocation(new java.awt.Point(30, 40)); + jLabel1.setSize(new java.awt.Dimension(435, 20)); + jLabel = new JLabel(); + jLabel.setText(""); + jLabel.setLocation(new java.awt.Point(30, 15)); + jLabel.setSize(new java.awt.Dimension(435, 20)); + jPanel = new JPanel(); + jPanel.setLayout(null); + jPanel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED)); + jPanel.setSize(new java.awt.Dimension(494, 251)); + jPanel.setLocation(new java.awt.Point(0, 55)); + jPanel.add(jLabel, null); + jPanel.add(jLabel1, null); + jPanel.add(getJScrollPane(), null); + } + return jPanel; + } + + /** + This method initializes jButtonFinish + + @return javax.swing.JButton jButtonFinish + + **/ + private JButton getJButtonCancel() { + if (jButtonFinish == null) { + jButtonFinish = new JButton(); + jButtonFinish.setText("Finish"); + jButtonFinish.setBounds(new java.awt.Rectangle(360, 315, 90, 20)); + jButtonFinish.setEnabled(true); + jButtonFinish.setSelected(false); + jButtonFinish.setMnemonic('C'); + jButtonFinish.addActionListener(this); + } + return jButtonFinish; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane jScrollPane + + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setLocation(new java.awt.Point(30, 65)); + jScrollPane.setSize(new java.awt.Dimension(435, 180)); + jScrollPane.setViewportView(getJTextAreaComment()); + } + return jScrollPane; + } + + /** + This method initializes jTextAreaComment + + @return javax.swing.JTextArea jTextAreaComment + + **/ + private JTextArea getJTextAreaComment() { + if (jTextAreaComment == null) { + jTextAreaComment = new JTextArea(); + jTextAreaComment.setEditable(false); + jTextAreaComment.setLineWrap(true); + jTextAreaComment.setWrapStyleWord(false); + } + return jTextAreaComment; + } + + /** + Main class, used for test + + @param args + **/ + public static void main(String[] args) { + Finish f = new Finish(); + f.setVisible(true); + } + + /** + This is the override constructor + + @param InstallDir The install target dir + + **/ + public Finish(String InstallDir) { + super(); + this.strInstallDir = InstallDir; + init(); + } + + /** + This is the default constructor + + **/ + public Finish() { + super(); + init(); + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 390); + + this.setContentPane(getJContentPane()); + this.setTitle("Setup - Installing"); + this.centerWindow(); + this.getRootPane().setDefaultButton(jButtonFinish); + switchFinish(); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + jContentPane.add(getJTextAreaTitle(), null); + jContentPane.add(getJTextAreaContent(), null); + jContentPane.add(getJPanel(), null); + jContentPane.add(getJButtonCancel(), null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + Object obj = arg0.getSource(); + + if (obj == jButtonFinish) { + this.dispose(); + System.exit(0); + } + } + + /** + Change all message values to Finish contents. + + **/ + private void switchFinish() { + this.setTitle("Setup - Finish"); + jTextAreaTitle.setText(" Congratulations"); + jTextAreaContent.setText(" Your workspace was installed!"); + jLabel.setText("The MDK package was installed successfully"); + jLabel1.setText("Now you can start the trip with EFI"); + jTextAreaComment.setText("Please add \"WORKSPACE=" + this.strInstallDir + + "\" into your system environment variable"); + jButtonFinish.setEnabled(true); + this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + jButtonFinish.setText("Finish"); + } + + // private void switchInstall() { + // jTextAreaTitle.setText(" Installation is in process..."); + // jLabel.setText("The MDK package was being installed..."); + // jLabel1.setText("Just waiting for a second"); + // jButtonFinish.setEnabled(false); + // jButtonFinish.setText("Finish"); + // } + + /* (non-Javadoc) + * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent) + * + * Override windowClosing to exit directly + * + */ + public void windowClosing(WindowEvent arg0) { + this.dispose(); + System.exit(0); + } +} diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/LicenseAgreement.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/LicenseAgreement.java new file mode 100644 index 0000000000..4661743a57 --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/LicenseAgreement.java @@ -0,0 +1,403 @@ +/** @file + + The class is used to show a License Agreement page in + the process of setup + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.workspace.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +import org.tianocore.packaging.common.ui.IFrame; + +/** + The class is used to show a License Agreement page in + the process of setup + + @since CreateMdkPkg 1.0 + + **/ +public class LicenseAgreement extends IFrame implements ActionListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = 5507683268692334188L; + + // + // Define class members + // + private JPanel jContentPane = null; + + private JTextArea jTextArea = null; + + private JTextArea jTextArea1 = null; + + private JPanel jPanel = null; + + private JButton jButtonBack = null; + + private JButton jButtonNext = null; + + private JButton jButtonCancel = null; + + private JLabel jLabel = null; + + private JRadioButton jRadioButtonAgree = null; + + private JRadioButton jRadioButtonDisagree = null; + + private JScrollPane jScrollPane = null; + + private JTextArea jTextArea2 = null; + + private JLabel jLabel1 = null; + + private Welcome w = null; + + private SelectDestinationDirectory sdd = null; + + /** + This method initializes jTextArea + + @return javax.swing.JTextArea jTextArea + + **/ + private JTextArea getJTextArea() { + if (jTextArea == null) { + jTextArea = new JTextArea(); + jTextArea.setLocation(new java.awt.Point(0, 0)); + jTextArea.setText(" License Agreement"); + jTextArea.setFont(new java.awt.Font("Dialog", java.awt.Font.BOLD, 14)); + jTextArea.setEditable(false); + jTextArea.setSize(new java.awt.Dimension(495, 20)); + } + return jTextArea; + } + + /** + This method initializes jTextArea1 + + @return javax.swing.JTextArea jTextArea1 + + **/ + private JTextArea getJTextArea1() { + if (jTextArea1 == null) { + jTextArea1 = new JTextArea(); + jTextArea1.setLocation(new java.awt.Point(0, 20)); + jTextArea1.setText(" Please read the following important information before continuing."); + jTextArea1.setEditable(false); + jTextArea1.setSize(new java.awt.Dimension(495, 35)); + } + return jTextArea1; + } + + /** + This method initializes jPanel + + @return javax.swing.JPanel jPanel + + **/ + private JPanel getJPanel() { + if (jPanel == null) { + jLabel1 = new JLabel(); + jLabel1.setText(" this agreement before continuing with the installation."); + jLabel1.setLocation(new java.awt.Point(30, 35)); + jLabel1.setSize(new java.awt.Dimension(435, 20)); + jLabel = new JLabel(); + jLabel.setText("Please read the following License Agreement. You must accept the terms of"); + jLabel.setLocation(new java.awt.Point(30, 15)); + jLabel.setSize(new java.awt.Dimension(435, 20)); + jPanel = new JPanel(); + jPanel.setLayout(null); + jPanel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED)); + jPanel.setSize(new java.awt.Dimension(494, 251)); + jPanel.setLocation(new java.awt.Point(0, 55)); + jPanel.add(jLabel, null); + jPanel.add(getJRadioButtonAgree(), null); + jPanel.add(getJRadioButtonDisagree(), null); + jPanel.add(getJScrollPane(), null); + jPanel.add(jLabel1, null); + } + return jPanel; + } + + /** + This method initializes jButtonBack + + @return javax.swing.JButton jButtonBack + + **/ + private JButton getJButtonBack() { + if (jButtonBack == null) { + jButtonBack = new JButton(); + jButtonBack.setText("Back"); + jButtonBack.setSize(new java.awt.Dimension(90, 20)); + jButtonBack.setLocation(new java.awt.Point(200, 315)); + jButtonBack.setMnemonic('B'); + jButtonBack.addActionListener(this); + } + return jButtonBack; + } + + /** + This method initializes jButtonNext + + @return javax.swing.JButton jButtonNext + + **/ + private JButton getJButtonNext() { + if (jButtonNext == null) { + jButtonNext = new JButton(); + jButtonNext.setText("Next"); + jButtonNext.setBounds(new java.awt.Rectangle(292, 315, 90, 20)); + jButtonNext.setEnabled(false); + jButtonNext.setMnemonic('N'); + jButtonNext.addActionListener(this); + } + return jButtonNext; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 315, 90, 20)); + jButtonCancel.setMnemonic('C'); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jRadioButtonAgree + + @return javax.swing.JRadioButton jRadioButtonAgree + + **/ + private JRadioButton getJRadioButtonAgree() { + if (jRadioButtonAgree == null) { + jRadioButtonAgree = new JRadioButton(); + jRadioButtonAgree.setText("I accept the agreement"); + jRadioButtonAgree.setLocation(new java.awt.Point(30, 200)); + jRadioButtonAgree.setSize(new java.awt.Dimension(156, 19)); + jRadioButtonAgree.addActionListener(this); + } + return jRadioButtonAgree; + } + + /** + This method initializes jRadioButtonDisagree + + @return javax.swing.JRadioButton jRadioButtonDisagree + + **/ + private JRadioButton getJRadioButtonDisagree() { + if (jRadioButtonDisagree == null) { + jRadioButtonDisagree = new JRadioButton(); + jRadioButtonDisagree.setText("I do not accept the agreement"); + jRadioButtonDisagree.setLocation(new java.awt.Point(30, 220)); + jRadioButtonDisagree.setSize(new java.awt.Dimension(248, 19)); + jRadioButtonDisagree.addActionListener(this); + } + return jRadioButtonDisagree; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane jScrollPane + + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setSize(new java.awt.Dimension(435, 140)); + jScrollPane.setVerticalScrollBarPolicy(javax.swing.JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); + jScrollPane.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED)); + jScrollPane.setViewportView(getJTextArea2()); + jScrollPane.setLocation(new java.awt.Point(30, 55)); + } + return jScrollPane; + } + + /** + This method initializes jTextArea2 + + @return javax.swing.JTextArea jTextArea2 + + **/ + private JTextArea getJTextArea2() { + if (jTextArea2 == null) { + jTextArea2 = new JTextArea(); + jTextArea2.setEditable(false); + jTextArea2.setWrapStyleWord(false); + jTextArea2.setLineWrap(true); + jTextArea2.setText("Copyright (c) 2006, Intel Corp.\n" + + "All rights reserved. This program and the accompanying materials " + + "are licensed and made available under the terms and conditions of the BSD License " + + "which may be found at http://opensource.org/licenses/bsd-license.php\n\n\n" + + "THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN \"AS IS\" BASIS, " + + "WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED."); + } + return jTextArea2; + } + + /** + Main class, used for test + + @param args + + **/ + public static void main(String[] args) { + LicenseAgreement la = new LicenseAgreement(); + la.setVisible(true); + } + + /** + This is the default constructor + + **/ + public LicenseAgreement() { + super(); + init(); + } + + /** + This is the override constructor + + @param welcome The input data of Welcome + + **/ + public LicenseAgreement(Welcome welcome) { + super(); + init(); + w = welcome; + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 390); + this.setContentPane(getJContentPane()); + this.setTitle("Setup - License Agreement"); + this.centerWindow(); + this.getRootPane().setDefaultButton(jButtonNext); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + jContentPane.add(getJTextArea(), null); + jContentPane.add(getJTextArea1(), null); + jContentPane.add(getJPanel(), null); + jContentPane.add(getJButtonBack(), null); + jContentPane.add(getJButtonNext(), null); + jContentPane.add(getJButtonCancel(), null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + Object obj = arg0.getSource(); + // + // Disable button next when select jRadioButtonDisagree + // + if (obj == jRadioButtonDisagree) { + if (jRadioButtonDisagree.isSelected()) { + jRadioButtonAgree.setSelected(false); + jButtonNext.setEnabled(false); + jButtonNext.setFocusable(false); + } + if (!jRadioButtonAgree.isSelected() && !jRadioButtonDisagree.isSelected()) { + jRadioButtonDisagree.setSelected(true); + } + } + + // + // Enable button next when select jRadioButtonAgree + // + if (obj == jRadioButtonAgree) { + if (jRadioButtonAgree.isSelected()) { + jRadioButtonDisagree.setSelected(false); + jButtonNext.setEnabled(true); + jButtonNext.setFocusable(true); + } + if (!jRadioButtonAgree.isSelected() && !jRadioButtonDisagree.isSelected()) { + jRadioButtonAgree.setSelected(true); + } + } + + if (obj == jButtonBack) { + this.setVisible(false); + w.setVisible(true); + } + + // + // Show next page when click button Next + // + if (obj == jButtonNext) { + if (sdd == null) { + sdd = new SelectDestinationDirectory(this); + } + this.setVisible(false); + sdd.setVisible(true); + } + + if (obj == jButtonCancel) { + this.onExit(); + } + } + + /* (non-Javadoc) + * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent) + * + * Override windowClosing to show confirm quit dialog + * + */ + public void windowClosing(WindowEvent arg0) { + this.onExit(); + } +} diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/SelectDestinationDirectory.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/SelectDestinationDirectory.java new file mode 100644 index 0000000000..4f167dcfec --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/SelectDestinationDirectory.java @@ -0,0 +1,469 @@ +/** @file + + The file is used to show a Select Destination Directory page in + the process of setup + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.workspace.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; + +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +import org.tianocore.common.Log; +import org.tianocore.packaging.common.ui.IFrame; +import org.tianocore.packaging.workspace.command.InstallWorkspace; + +/** + The class is used to show a Select Destination Directory page in + the process of setup + + @since CreateMdkPkg 1.0 + + **/ +public class SelectDestinationDirectory extends IFrame implements ActionListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -2924500118774744205L; + + // + // Define class members + // + private JPanel jContentPane = null; + + private JTextArea jTextArea = null; + + private JTextArea jTextArea1 = null; + + private JPanel jPanel = null; + + private JButton jButtonBack = null; + + private JButton jButtonNext = null; + + private JButton jButtonCancel = null; + + private JLabel jLabel = null; + + private JLabel jLabel1 = null; + + private JTextField jTextFieldInstallDir = null; + + private JButton jButtonBrowse = null; + + private JLabel jLabel2 = null; + + private LicenseAgreement la = null; + + /** + This method initializes jTextArea + + @return javax.swing.JTextArea jTextArea + + **/ + private JTextArea getJTextArea() { + if (jTextArea == null) { + jTextArea = new JTextArea(); + jTextArea.setLocation(new java.awt.Point(0, 0)); + jTextArea.setText(" Select Destination Directory"); + jTextArea.setFont(new java.awt.Font("Dialog", java.awt.Font.BOLD, 14)); + jTextArea.setEditable(false); + jTextArea.setSize(new java.awt.Dimension(495, 20)); + } + return jTextArea; + } + + /** + This method initializes jTextArea1 + + @return javax.swing.JTextArea jTextArea1 + + **/ + private JTextArea getJTextArea1() { + if (jTextArea1 == null) { + jTextArea1 = new JTextArea(); + jTextArea1.setLocation(new java.awt.Point(0, 20)); + jTextArea1.setText(" Where should MDK package be installed?"); + jTextArea1.setEditable(false); + jTextArea1.setSize(new java.awt.Dimension(495, 35)); + } + return jTextArea1; + } + + /** + This method initializes jPanel + + @return javax.swing.JPanel jPanel + + **/ + private JPanel getJPanel() { + if (jPanel == null) { + jLabel2 = new JLabel(); + jLabel2.setText("At least 10 MB of free disk space is required"); + jLabel2.setLocation(new java.awt.Point(30, 225)); + jLabel2.setSize(new java.awt.Dimension(290, 20)); + jLabel1 = new JLabel(); + jLabel1.setText("To continue, click Next. If you wuold like to select different folder, click Browse."); + jLabel1.setLocation(new java.awt.Point(30, 55)); + jLabel1.setSize(new java.awt.Dimension(435, 20)); + jLabel = new JLabel(); + jLabel.setText("Setup will install MDK package into the following folders:"); + jLabel.setLocation(new java.awt.Point(30, 15)); + jLabel.setSize(new java.awt.Dimension(435, 20)); + jPanel = new JPanel(); + jPanel.setLayout(null); + jPanel.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.LOWERED)); + jPanel.setSize(new java.awt.Dimension(494, 251)); + jPanel.setLocation(new java.awt.Point(0, 55)); + jPanel.add(jLabel, null); + jPanel.add(jLabel1, null); + jPanel.add(getJTextField(), null); + jPanel.add(getJButtonBrowse(), null); + jPanel.add(jLabel2, null); + } + return jPanel; + } + + /** + This method initializes jButtonBack + + @return javax.swing.JButton jButtonBack + + **/ + private JButton getJButtonBack() { + if (jButtonBack == null) { + jButtonBack = new JButton(); + jButtonBack.setText("Back"); + jButtonBack.setSize(new java.awt.Dimension(90, 20)); + jButtonBack.setLocation(new java.awt.Point(200, 315)); + jButtonBack.setMnemonic('B'); + jButtonBack.addActionListener(this); + } + return jButtonBack; + } + + /** + This method initializes jButtonNext + + @return javax.swing.JButton jButtonNext + + **/ + private JButton getJButtonNext() { + if (jButtonNext == null) { + jButtonNext = new JButton(); + jButtonNext.setText("Next"); + jButtonNext.setBounds(new java.awt.Rectangle(292, 315, 90, 20)); + jButtonNext.setEnabled(true); + jButtonNext.setMnemonic('N'); + jButtonNext.addActionListener(this); + } + return jButtonNext; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 315, 90, 20)); + jButtonCancel.setMnemonic('C'); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jTextFieldInstallDir + + @return javax.swing.JTextField jTextFieldInstallDir + + **/ + private JTextField getJTextField() { + if (jTextFieldInstallDir == null) { + jTextFieldInstallDir = new JTextField(); + jTextFieldInstallDir.setLocation(new java.awt.Point(30, 90)); + jTextFieldInstallDir.setSize(new java.awt.Dimension(320, 20)); + jTextFieldInstallDir.setText("C:\\MyWorkspace"); + } + return jTextFieldInstallDir; + } + + /** + This method initializes jButtonBrowse + + @return javax.swing.JButton jButtonBrowse + + **/ + private JButton getJButtonBrowse() { + if (jButtonBrowse == null) { + jButtonBrowse = new JButton(); + jButtonBrowse.setText("Browse"); + jButtonBrowse.setSize(new java.awt.Dimension(90, 20)); + jButtonBrowse.setLocation(new java.awt.Point(370, 90)); + jButtonBrowse.addActionListener(this); + } + return jButtonBrowse; + } + + /** + Main class, used for test + + @param args + + **/ + public static void main(String[] args) { + SelectDestinationDirectory sdd = new SelectDestinationDirectory(); + sdd.setVisible(true); + } + + /** + This is the default constructor + + **/ + public SelectDestinationDirectory() { + super(); + init(); + } + + /** + This is the override constructor + + @param licenseagreement The input data of licenseagreement + + **/ + public SelectDestinationDirectory(LicenseAgreement licenseagreement) { + super(); + init(); + la = licenseagreement; + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 390); + this.setTitle("Setup - Select Destination Directory"); + this.setContentPane(getJContentPane()); + this.centerWindow(); + this.getRootPane().setDefaultButton(jButtonNext); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setBorder(javax.swing.BorderFactory.createBevelBorder(javax.swing.border.BevelBorder.RAISED)); + jContentPane.add(getJTextArea(), null); + jContentPane.add(getJTextArea1(), null); + jContentPane.add(getJPanel(), null); + jContentPane.add(getJButtonBack(), null); + jContentPane.add(getJButtonNext(), null); + jContentPane.add(getJButtonCancel(), null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + Object obj = arg0.getSource(); + + if (obj == jButtonBack) { + this.setVisible(false); + la.setVisible(true); + } + + // + // Show next page if click button Next + // + if (obj == jButtonNext) { + if (createWorkspace(jTextFieldInstallDir.getText())) { + if (initWorkspace(jTextFieldInstallDir.getText())) { + this.setVisible(false); + Finish f = new Finish(jTextFieldInstallDir.getText()); + f.setVisible(true); + } + } + } + + if (obj == jButtonCancel) { + this.onExit(); + } + + if (obj == jButtonBrowse) { + JFileChooser fc = new JFileChooser(); + fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + int result = fc.showOpenDialog(new JPanel()); + if (result == JFileChooser.APPROVE_OPTION) { + jTextFieldInstallDir.setText(fc.getCurrentDirectory().toString() + System.getProperty("file.separator") + + fc.getSelectedFile().getName()); + } + } + } + + /** + Create workspace to target dir + + @param strInstallDir The install target dir + @retval true - Create success + @retval false - Create fail + + **/ + private boolean createWorkspace(String strInstallDir) { + boolean bolCreateDirectory = true; + int intResult; + + // + //Check if the Install Dir exists + // + Log.log("is Exist Install Dir"); + if (InstallWorkspace.isExistInstallDir(strInstallDir)) { + intResult = JOptionPane.showConfirmDialog(null, strInstallDir + " already exists, continue anyway?", + "Override", JOptionPane.YES_NO_OPTION); + if (intResult != JOptionPane.YES_OPTION) { + return false; + } else { + bolCreateDirectory = false; + } + } + + // + //Create the directory + // + Log.log("Create Directory"); + if (bolCreateDirectory) { + if (!InstallWorkspace.createInstallDir(strInstallDir)) { + intResult = JOptionPane.showConfirmDialog(null, "Cannot create direcotry " + strInstallDir + + " in system. Click OK to exist.", "Error", + JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE); + return false; + } + } + return true; + } + + /** + Init created workspace + + @param strInstallDir The dir of workspace + @retval true - Init Success + @retval false - Init fail + + **/ + private boolean initWorkspace(String strInstallDir) { + String strJarFile = System.getProperty("user.dir") + System.getProperty("file.separator") + "CreateMdkPkg.jar"; + + // + //Install package + // + Log.log("Install Package"); + try { + if (!InstallWorkspace.installPackage(strInstallDir, strJarFile)) { + JOptionPane.showConfirmDialog(null, "Cannot intall package in system. Click OK to exist.", "Error", + JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE); + return false; + } + } catch (Exception e) { + e.printStackTrace(); + } + + // + //Update framework database + // + Log.log("Set Framework Database"); + if (!InstallWorkspace.setFrameworkDatabase()) { + JOptionPane.showConfirmDialog(null, "Cannot create workspace database in system. Click OK to exist.", + "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE); + return false; + } + + // + //Set System Environment + // + Log.log("Set System Environment"); + if (!InstallWorkspace.setSystemEnvironment()) { + JOptionPane.showConfirmDialog(null, "Cannot set WORKSPACE variable in system. Click OK to exist.", "Error", + JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE); + return false; + } + + // + //Set Tool Chain Path + // + Log.log("Set Tool Chain Path"); + if (!InstallWorkspace.setToolChainPath()) { + JOptionPane.showConfirmDialog(null, "Cannot set Tool Chain path variable in system. Click OK to exist.", + "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE); + return false; + } + + // + //Install tool chain + // + Log.log("Set Tool Chain"); + if (!InstallWorkspace.setToolChain()) { + JOptionPane.showConfirmDialog(null, "Cannot set Tool Chain in system. Click OK to exist.", "Error", + JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE); + return false; + } + + // + //Delete setup files + // + Log.log("Delete Setup Files"); + try { + InstallWorkspace.delSetupPackage(strInstallDir + System.getProperty("file.separator") + "org"); + } catch (Exception e) { + e.printStackTrace(); + Log.log(e.getMessage()); + } + + return true; + } + + /* (non-Javadoc) + * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent) + * + * Override windowClosing to show confirm quit dialog + * + */ + public void windowClosing(WindowEvent arg0) { + this.onExit(); + } +} diff --git a/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/Welcome.java b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/Welcome.java new file mode 100644 index 0000000000..aa2e5861be --- /dev/null +++ b/Tools/Source/CreateMdkPkg/src/org/tianocore/packaging/workspace/ui/Welcome.java @@ -0,0 +1,272 @@ +/** @file + + The file is used to show a welcome page in the process of setup + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.workspace.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; + +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.JTextArea; + +import org.tianocore.packaging.common.ui.IFrame; + +/** + The class is used to show a welcome page in the process of setup + + @since CreateMdkPkg 1.0 + + **/ +public class Welcome extends IFrame implements ActionListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = 8160041311175680637L; + + // + // Define class members + // + private JPanel jContentPane = null; + + private JPanel jPanel = null; + + private JTextArea jTextArea = null; + + private JTextArea jTextArea1 = null; + + private JTextArea jTextArea2 = null; + + private JTextArea jTextArea3 = null; + + private JButton jButtonNext = null; + + private JButton jButtonCancel = null; + + private LicenseAgreement la = null; + + /** + This method initializes jPanel + + @return javax.swing.JPanel jPanel + + **/ + private JPanel getJPanel() { + if (jPanel == null) { + jPanel = new JPanel(); + jPanel.setLayout(null); + jPanel.setSize(new java.awt.Dimension(495, 355)); + jPanel.setLocation(new java.awt.Point(0, 0)); + jPanel.add(getJTextArea(), null); + jPanel.add(getJTextArea1(), null); + jPanel.add(getJTextArea2(), null); + jPanel.add(getJTextArea3(), null); + jPanel.add(getJButtonNext(), null); + jPanel.add(getJButtonCancel(), null); + } + return jPanel; + } + + /** + This method initializes jTextArea + + @return javax.swing.JTextArea jTextArea + + **/ + private JTextArea getJTextArea() { + if (jTextArea == null) { + jTextArea = new JTextArea(); + jTextArea.setFont(new java.awt.Font("Times New Roman", java.awt.Font.BOLD, 24)); + jTextArea.setSize(new java.awt.Dimension(495, 70)); + jTextArea.setLocation(new java.awt.Point(0, 0)); + jTextArea.setEnabled(true); + jTextArea.setEditable(false); + jTextArea.setText("Welcome to the MDK Package Setup Wizard"); + } + return jTextArea; + } + + /** + This method initializes jTextArea1 + + @return javax.swing.JTextArea jTextArea1 + + **/ + private JTextArea getJTextArea1() { + if (jTextArea1 == null) { + jTextArea1 = new JTextArea(); + jTextArea1.setText("This will install MDK Package on your computer. "); + jTextArea1.setSize(new java.awt.Dimension(495, 40)); + jTextArea1.setEnabled(true); + jTextArea1.setEditable(false); + jTextArea1.setLocation(new java.awt.Point(0, 70)); + } + return jTextArea1; + } + + /** + This method initializes jTextArea2 + + @return javax.swing.JTextArea jTextArea2 + + **/ + private JTextArea getJTextArea2() { + if (jTextArea2 == null) { + jTextArea2 = new JTextArea(); + jTextArea2.setSize(new java.awt.Dimension(495, 50)); + jTextArea2 + .setText("It is strongly recommended that you exit all other programs before running this installation program."); + jTextArea2.setLineWrap(true); + jTextArea2.setEnabled(true); + jTextArea2.setEditable(false); + jTextArea2.setLocation(new java.awt.Point(0, 110)); + } + return jTextArea2; + } + + /** + This method initializes jTextArea3 + + @return javax.swing.JTextArea jTextArea3 + + **/ + private JTextArea getJTextArea3() { + if (jTextArea3 == null) { + jTextArea3 = new JTextArea(); + jTextArea3.setBounds(new java.awt.Rectangle(0, 160, 495, 150)); + jTextArea3.setEnabled(true); + jTextArea3.setEditable(false); + jTextArea3.setText("Click Nex to continue. Or click Cancel to exit Setup"); + } + return jTextArea3; + } + + /** + This method initializes jButtonNext + + @return javax.swing.JButton jButtonNext + + **/ + private JButton getJButtonNext() { + if (jButtonNext == null) { + jButtonNext = new JButton(); + jButtonNext.setText("Next"); + jButtonNext.setSize(new java.awt.Dimension(90, 20)); + jButtonNext.setLocation(new java.awt.Point(290, 320)); + jButtonNext.setMnemonic('N'); + jButtonNext.addActionListener(this); + } + return jButtonNext; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(90, 20)); + jButtonCancel.setLocation(new java.awt.Point(390, 320)); + jButtonCancel.setMnemonic('C'); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + Main class, used for test + + @param args + **/ + public static void main(String[] args) { + Welcome w = new Welcome(); + w.setVisible(true); + } + + /** + This is the default constructor + + **/ + public Welcome() { + super(); + init(); + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 390); + this.setContentPane(getJContentPane()); + this.setTitle("Welcome"); + this.centerWindow(); + this.getRootPane().setDefaultButton(jButtonNext); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJPanel(), null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + Object obj = arg0.getSource(); + // + // Show next page if click button Next + // + if (obj == jButtonNext) { + if (la == null) { + la = new LicenseAgreement(this); + } + this.setVisible(false); + la.setVisible(true); + } + if (obj == jButtonCancel) { + this.onExit(); + } + } + + /* (non-Javadoc) + * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent) + * + * Override windowClosing to show confirm quit dialog + * + */ + public void windowClosing(WindowEvent arg0) { + this.onExit(); + } +} diff --git a/Tools/Source/FrameworkTasks/build.xml b/Tools/Source/FrameworkTasks/build.xml new file mode 100644 index 0000000000..0a99a44b48 --- /dev/null +++ b/Tools/Source/FrameworkTasks/build.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/FrameworkTasks/frameworktasks.tasks b/Tools/Source/FrameworkTasks/frameworktasks.tasks new file mode 100644 index 0000000000..f8bafabb0b --- /dev/null +++ b/Tools/Source/FrameworkTasks/frameworktasks.tasks @@ -0,0 +1,11 @@ +fwimage=org.tianocore.framework.tasks.FwImageTask +setstamp=org.tianocore.framework.tasks.SetStampTask +gendepex=org.tianocore.framework.tasks.GenDepexTask +gensection=org.tianocore.framework.tasks.GenSectionTask +genffsfile=org.tianocore.framework.tasks.GenFfsFileTask +vfrcompile=org.tianocore.framework.tasks.VfrCompilerTask +strgather=org.tianocore.framework.tasks.StrGatherTask +genfvimage=org.tianocore.framework.tasks.GenFvImageTask +guidchk= org.tianocore.framework.tasks.GuidChkTask +gencrc32section=org.tianocore.framework.tasks.GenCRC32SectionTask +makedeps=org.tianocore.framework.tasks.MakeDeps diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Compress.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Compress.java new file mode 100644 index 0000000000..4410ecdda1 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Compress.java @@ -0,0 +1,78 @@ +/** @file + Compress class. + + This class is to call CompressDll.dll to compress section. + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.framework.tasks; + +import java.io.File; + +/** + + This class is to call CompressDll.dll to compress section. + +**/ +public class Compress { + byte[] inputBuffer; + byte[] outputBuffer; + int size; + + static { + String dllPath; + + dllPath = GenFfsFileTask.path; + dllPath = dllPath + + File.separator + + "CompressDll.dll"; + + System.load(dllPath); + } + + /** + CallCompress + + This function is to call the compressDll.dll to compress the contents in + buffer. + + @param inputBuffer The input buffer. + @param size The size of buffer in byte. + @param dllPath The compressDll.dll path. + @return The buffer contained the comrpessed input. + **/ + public native byte[] CallCompress (byte[] inputBuffer, int size, String dllPath); + + /** + Construct function + + This function is to initialize the class member and call the compress + function. + + @param inBuffer The input buffer. + @param size The size of buffer in byte. + **/ + public Compress (byte[] inBuffer, int size){ + this.inputBuffer = inBuffer; + this.size = size; + String path = GenFfsFileTask.path; + + // + // Call Compress function. + // + this.outputBuffer = CallCompress ( + this.inputBuffer, + this.size, + path + ); + } +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/CompressHeader.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/CompressHeader.java new file mode 100644 index 0000000000..5992b1d708 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/CompressHeader.java @@ -0,0 +1,78 @@ +/** @file + CompressHeader class. + + This class is to generate the compressed section header. + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.framework.tasks; + +import org.apache.tools.ant.BuildException; + +/** + + Internal class: This class is to generate the compressed section header. + +**/ +public class CompressHeader { + + /** + CommonSectionHeader + + This class define the compressed header structor. + + **/ + public class CommonSectionHeader { + byte[] Size = new byte[3]; + byte type; + } + + /// + /// Section header. + /// + public CommonSectionHeader SectionHeader = new CommonSectionHeader(); + + /// + /// Length of uncompress section in byte. + /// + public int UncompressLen; + /// + /// Compress type. + /// + public byte CompressType; + + /// + /// The size of compress header in byte. + /// + public int GetSize (){ + return 9; + } + + /// + /// Write class member to buffer. + /// + public void StructToBuffer (byte[] Buffer){ + if (Buffer.length != GetSize()) { + throw new BuildException ("CompressHeader Buffer size is not correct!"); + } + for (int i = 0; i < 3; i++){ + Buffer[i] = SectionHeader.Size[i]; + } + Buffer[3] = SectionHeader.type; + Buffer[4] = (byte)(UncompressLen & 0xff); + Buffer[5] = (byte)((UncompressLen & 0xff00)>>8); + Buffer[6] = (byte)((UncompressLen & 0xff0000)>>16); + Buffer[7] = (byte)((UncompressLen & 0xff000000)>>24); + Buffer[8] = CompressType; + } + +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/CompressSection.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/CompressSection.java new file mode 100644 index 0000000000..8def4ebc95 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/CompressSection.java @@ -0,0 +1,209 @@ +/** @file + CompressSection class. + + CompressSection indicate that all section which in it should be compressed. + + Copyright (c) 2006, 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. + + **/ + + +package org.tianocore.framework.tasks; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.tools.ant.BuildException; + + +/** + CompressSection + + CompressSection indicate that all section which in it should be compressed. + +**/ +public class CompressSection implements Section, FfsTypes{ + // + // The attribute of compressName. + // + String compressName = ""; + // + // The list contained the SectFile element. + // + List SectList = new ArrayList(); + + /** + toBuffer + + This function is to collect all sectFile and compress it , then output + the result to buffer. + + @param Buffer The point of output buffer + + **/ + public void toBuffer (DataOutputStream Buffer){ + + Section sect; + File compressOut; + + // + // Get section file in compress node. + // + try{ + compressOut = new File ("Compress.temp"); + FileOutputStream fo = new FileOutputStream (compressOut.getName()); + DataOutputStream Do = new DataOutputStream (fo); + + // + // Get each section which under the compress {}; + // And add it is contains to File; + // + Iterator SectionIter = SectList.iterator(); + while (SectionIter.hasNext()){ + sect = (Section)SectionIter.next(); + + // + // Call each section class's toBuffer function. + // + try { + sect.toBuffer(Do); + } + catch (BuildException e) { + System.out.print(e.getMessage()); + throw new BuildException ("Compress.toBuffer failed at section"); + } + + } + Do.close(); + + // + // Get contain to Buffer + // + FileInputStream fi = new FileInputStream (compressOut.getName()); + DataInputStream di = new DataInputStream (fi); + byte[] fileBuffer = new byte[(int)compressOut.length()]; + di.read(fileBuffer); + + // + // Call compress + // + Compress myCompress = new Compress(fileBuffer, fileBuffer.length); + + // + // Add Compress header + // + CompressHeader Ch = new CompressHeader(); + Ch.SectionHeader.Size[0] = (byte)((myCompress.outputBuffer.length + + Ch.GetSize()) & + 0xff + ); + Ch.SectionHeader.Size[1] = (byte)(((myCompress.outputBuffer.length + + Ch.GetSize())& + 0xff00) >> 8 + ); + Ch.SectionHeader.Size[2] = (byte)(((myCompress.outputBuffer.length + + Ch.GetSize()) & + 0xff0000) >> 16 + ); + Ch.SectionHeader.type = (byte) EFI_SECTION_COMPRESSION; + + // + // Note: The compressName was not effective now. Using the + // EFI_STANDARD_COMPRSSION for compressType . + // That is follow old Genffsfile tools. Some code will be added for + // the different compressName; + // + Ch.UncompressLen = fileBuffer.length; + Ch.CompressType = EFI_STANDARD_COMPRESSION; + + // + // Change header struct to byte buffer + // + byte [] headerBuffer = new byte[Ch.GetSize()]; + Ch.StructToBuffer(headerBuffer); + + // + // First add CompressHeader to Buffer, then add Compress data. + // + Buffer.write (headerBuffer); + Buffer.write(myCompress.outputBuffer); + + // + // 4 Byte aligment + // + int size = Ch.GetSize() + myCompress.outputBuffer.length; + + while ((size & 0x03) != 0){ + size ++; + Buffer.writeByte(0); + } + + // + // Delete temp file + // + di.close(); + compressOut.delete(); + + } + catch (Exception e){ + throw new BuildException("compress.toBuffer failed!\n"); + } + } + + /** + getCompressName + + This function is to get compressName. + + @return The compressName. + **/ + public String getCompressName() { + return compressName; + } + + /** + setCompressName + + This function is to set compressName. + + @param compressName The string of compressName + **/ + public void setCompressName(String compressName) { + this.compressName = compressName; + } + + /** + addSectFile + + This function is to add sectFile element to SectList. + + @param sectFile SectFile element which succeed from section class. + **/ + public void addSectFile (SectFile sectFile) { + SectList.add(sectFile); + + } + + /** + addTool + + This function is to add tool element to SectList. + @param tool Tool element which succeed from section class. + **/ + public void addTool (Tool tool) { + SectList.add(tool); + } +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Database.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Database.java new file mode 100644 index 0000000000..8c3f6be222 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Database.java @@ -0,0 +1,112 @@ +/** @file + Database class. + + Database represents an exceplicity name list of database file. + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.framework.tasks; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +/** + Database + + Database represents an exceplicity name list of database file. + +**/ +public class Database implements NestElement{ + /// + /// name of database file + /// + private String name = ""; + /// + /// name of file including database files + /// + private File file; + /// + /// the database file name list + /// + private List nameList = new ArrayList(); + + /** + getName + + This function is to get class member "name". + + @return class member "name". + **/ + public String getName() { + return this.name; + } + /** + setName + + This function is to set class member "name". + + @param name : name of database file. + **/ + public void setName(String name) { + this.name = " -db " + name; + } + + /** + toString + + This function is to call getName() function. + @return class member "name". + **/ + public String toString() { + return getName(); + } + + /** + getFile + + This function is to get file which include the database file list. + + @return class member "file" + + **/ + public File getFile() { + return this.file; + } + /** + setFile + + This function is to set class member "file". + + @param file The file which include the database file list. + **/ + public void setFile(File file) { + this.file = file; + } + + + public void setList(String fileNameList) { + if (fileNameList != null && fileNameList.length() > 0) { + StringTokenizer tokens = new StringTokenizer(fileNameList, " \t,;", false); + while (tokens.hasMoreTokens()) { + String fileName = tokens.nextToken().trim(); + if (fileName.length() > 0) { + this.nameList.add(fileName); + } + } + } + } + + public List getList() { + return nameList; + } +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/EfiDefine.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/EfiDefine.java new file mode 100644 index 0000000000..6f12f00f43 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/EfiDefine.java @@ -0,0 +1,56 @@ +/** @file + EfiDefine class. + + EfiDefine class records the UEFI return status value. + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.framework.tasks; + +/** + EfiDefine class. + + EfiDefine class records the UEFI return status value. +**/ +public interface EfiDefine { + // + // EFI define Interface for define constant related to UEFI. + // + static final int EFI_SUCCESS = 0; + static final int EFI_LOAD_ERROR = 0x80000001; + static final int EFI_INVALID_PARAMETER = 0x80000002; + static final int EFI_UNSUPPORTED = 0x80000003; + static final int EFI_BAD_BUFFER_SIZE = 0x80000004; + static final int EFI_BUFFER_TOO_SMALL = 0x80000005; + static final int EFI_NOT_READY = 0x80000006; + static final int EFI_DEVICE_ERROR = 0x80000007; + static final int EFI_WRITE_PROTECTED = 0x80000008; + static final int EFI_OUT_OF_RESOURCES = 0x80000009; + static final int EFI_VOLUME_CORRUPTED = 0x8000000a; + static final int EFI_VOLUME_FULL = 0x8000000b; + static final int EFI_NO_MEDIA = 0x8000000c; + static final int EFI_MEDIA_CHANGED = 0x8000000d; + static final int EFI_NOT_FOUND = 0x8000000e; + static final int EFI_ACCESS_DENIED = 0x8000000f; + static final int EFI_NO_RESPONSE = 0x80000010; + static final int EFI_NO_MAPPING = 0x80000011; + static final int EFI_TIMEOUT = 0x80000012; + static final int EFI_NOT_STARTED = 0x80000013; + static final int EFI_ALREADY_STARTED = 0x80000014; + static final int EFI_ABORTED = 0x80000015; + static final int EFI_ICMP_ERROR = 0x80000016; + static final int EFI_TFTP_ERROR = 0x80000017; + static final int EFI_PROTOCOL_ERROR = 0x80000018; + static final int EFI_INCOMPATIBLE_VERSION = 0x80000019; + static final int EFI_SECURITY_VIOLATION = 0x80000020; + static final int EFI_CRC_ERROR = 0x80000021; +} diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FfsHeader.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FfsHeader.java new file mode 100644 index 0000000000..452f65394e --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FfsHeader.java @@ -0,0 +1,185 @@ +/** @file + FfsHeader + + FfsHeader class describe the struct of Ffs file header. + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.framework.tasks; + +import org.apache.tools.ant.BuildException; + +/** + FfsHeader + + FfsHeader class describe the struct of Ffs file header. +**/ +public class FfsHeader { + + /** + FfsGuid + + FfsGuid is interal class of FfsHeader, it describe the struct of Guid. + **/ + public class FfsGuid { + + int data1 = 0; + short data2 = 0; + short data3 = 0; + byte[] data4 = new byte[8]; + byte[] dataBuffer = new byte[16]; + + /** + bufferToStruct + + This function is to convert GUID to ffsGuid class member. + + @param dataBuffer Buffer contained the GUID value in byte. + For example: if the input string as : "A6F691AC + 31C8 4444 854C E2C1A6950F92" + Then Data1: AC91F6A6 + Data2: C831 + Data3: 4444 + Data4: 4C85E2C1A6950F92 + **/ + public void bufferToStruct (byte[] dataBuffer){ + if (dataBuffer.length != 16) { + throw new BuildException ("Buffer is not fitting GUID type!"); + } + + data1 = (int)(dataBuffer[3]& 0xff); + data1 = data1 << 8; + data1 = (int)data1 | (dataBuffer[2]& 0xff); + data1 = ((data1 << 8) & 0xffff00) | (dataBuffer[1]& 0xff); + data1 = ((data1 << 8) & 0xffffff00) | (dataBuffer[0]& 0xff); + + + data2 = (short) (dataBuffer[5] & 0xff); + data2 = (short)((data2 << 8) | (dataBuffer[4]& 0xff)); + + data3 = (short)(dataBuffer[7] & 0xff); + data3 = (short)((data3 << 8) | (dataBuffer[6] & 0xff)); + + for (int i = 0; i < 8; i++) { + data4[i] = dataBuffer[i+8]; + } + + } + + /** + structToBuffer + + This function is to store ffsHeader class member to buffer. + + @return Byte buffer which contained the ffsHeader class member + **/ + public byte[] structToBuffer (){ + + byte[] buffer = new byte [16]; + + buffer[3] = (byte)(data1 & 0x000000ff); + buffer[2] = (byte)((data1 & 0x0000ff00)>> 8); + buffer[1] = (byte)((data1 & 0x00ff0000)>> 16); + buffer[0] = (byte)((data1 & 0xff000000)>> 24); + + buffer[5] = (byte)(data2 & 0x00ff); + buffer[4] = (byte)((data2 & 0xff00)>> 8); + + buffer[7] = (byte)(data3 & 0x00ff); + buffer[6] = (byte)((data3 & 0xff00)>> 8); + + for (int i = 8; i < 16; i++) { + buffer[i] = data4[i-8]; + } + return buffer; + } + + + } + + /** + integrityCheckSum + + This class is used to record the struct of checksum. + **/ + public class integrityCheckSum { + byte header; + byte file; + } + + /// + /// Guid + /// + FfsGuid name = new FfsGuid(); + + /// + /// CheckSum + /// + integrityCheckSum integrityCheck = new integrityCheckSum(); + + /// + /// File type + /// + byte fileType; + /// + /// Ffs attributes. + /// + byte ffsAttributes; + /// + /// Ffs file size + /// + byte[] ffsFileSize = new byte[3]; + /// + /// Ffs state. + /// + byte ffsState; + + /** + structToBuffer + + This function is to store FfsHeader class member to buffer. + + @return Byte buffer which contained the FfsHeader class member. + **/ + public byte[] structToBuffer () { + int i; + byte[] buffer1; + byte[] buffer = new byte[24]; + buffer1 = name.structToBuffer(); + + for (i = 0; i < 16; i++) { + buffer[i] = buffer1[i]; + } + + buffer[16] = integrityCheck.header; + buffer[17] = integrityCheck.file; + buffer[18] = fileType; + buffer[19] = ffsAttributes; + + for (i=20; i < 23; i++) { + buffer[i] = ffsFileSize[i-20]; + } + + buffer[23] = ffsState; + return buffer; + } + + /** + getSize + + This function is to get the size of FfsHeader in byte. + + @return The size of FfsHeader. + **/ + public int getSize(){ + return 24; + } +} diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FfsTypes.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FfsTypes.java new file mode 100644 index 0000000000..6afc3a90ad --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FfsTypes.java @@ -0,0 +1,115 @@ +/** @file + FfsTypes class. + + FfsType class record the costant value of Ffs File attribute, type, and + architecture. + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.framework.tasks; + +/** + FfsType + + FfsType class record the costant value of Ffs File attribute, type, and + architecture. + +**/ +public interface FfsTypes { + // + // Ffs file attributes + // + static final int FFS_ATTRIB_TAIL_PRESENT = 0x01; + + static final int FFS_ATTRIB_RECOVERY = 0x02; + + static final int FFS_ATTRIB_HEADER_EXTENSION = 0x04; + + static final int FFS_ATTRIB_DATA_ALIGNMENT = 0x38; + + static final int FFS_ATTRIB_CHECKSUM = 0x40; + + // + // Ffs states difinitions + // + static final int EFI_FILE_HEADER_CONSTRUCTION = 0x01; + + static final int EFI_FILE_HEADER_VALID = 0x02; + + static final int EFI_FILE_DATA_VALID = 0x04; + + static final int EFI_FILE_MARKED_FOR_UPDATE = 0x08; + + static final int EFI_FILE_DELETED = 0x10; + + static final int EFI_FILE_HEADER_INVALID = 0x20; + + // + // FFS_FIXED_CHECKSUM is the default checksum value used when the + // FFS_ATTRIB_CHECKSUM attribute bit is clear note this is NOT an + // architecturally defined value, but is in this file for implementation + // convenience + // + static final int FFS_FIXED_CHECKSUM = 0x5a; + + // + // Architectural file types + // + static final int EFI_FV_FILETYPE_ALL = 0x00; + + static final int EFI_FV_FILETYPE_RAW = 0x01; + + static final int EFI_FV_FILETYPE_FREEFORM = 0x02; + + static final int EFI_FV_FILETYPE_SECURITY_CORE = 0x03; + + static final int EFI_FV_FILETYPE_PEI_CORE = 0x04; + + static final int EFI_FV_FILETYPE_DXE_CORE = 0x05; + + static final int EFI_FV_FILETYPE_PEIM = 0x06; + + static final int EFI_FV_FILETYPE_DRIVER = 0x07; + + static final int EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER = 0x08; + + static final int EFI_FV_FILETYPE_APPLICATION = 0x09; + + static final int EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE = 0x0B; + + static final int EFI_FV_FILETYPE_FFS_PAD = 0xF0; + + // + // Ffs file type + // + static final String EFI_FV_FFS_FILETYPE_STR = ".FFS"; + static final String EFI_FV_DXE_FILETYPE_STR = ".DXE"; + static final String EFI_FV_PEI_FILETYPE_STR = ".PEI"; + static final String EFI_FV_APP_FILETYPE_STR = ".APP"; + static final String EFI_FV_FVI_FILETYPE_STR = ".FVI"; + static final String EFI_FV_SEC_FILETYPE_STR = ".SEC"; + + // + // Section Type copy from EfiImageFormat.h + // + static final int EFI_SECTION_COMPRESSION = 0x01; + static final int EFI_SECTION_GUID_DEFINED = 0x02; + + // + // CompressionType values, we currently don't support + // "EFI_CUSTOMIZED_COMPRESSION". + // + static final int EFI_NOT_COMPRESSED = 0x00; + static final int EFI_STANDARD_COMPRESSION = 0x01; + static final int EFI_CUSTOMIZED_COMPRESSION = 0x02; + + +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FileParser.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FileParser.java new file mode 100644 index 0000000000..982fd65096 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FileParser.java @@ -0,0 +1,72 @@ +/** @file + FileParser class. + + FileParser class is to parse file which contains the list of file name and + add those files to list. + + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.framework.tasks; +import java.io.*; +import java.util.List; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; + +/** + FileParser class. + + FileParser class is to parse file which contains the list of file name and + add those files to list. +**/ +public class FileParser { + /** + loadFile + + This function is to add files to array from input file which contains the + files list. + @param project The current project. + @param list File array. + @param file File which contains the file list. + @param tag Target of architecture. + @throws BuildException + **/ + public static synchronized void loadFile(Project project, List list, File file, String tag) throws BuildException{ + FileReader fileReader; + BufferedReader in; + String str; + + if (!file.exists()) { + throw new BuildException("The file" + file + "is not exist"); + } + try { + fileReader = new FileReader(file); + in = new BufferedReader(fileReader); + while((str=in.readLine())!= null){ + if (str.trim()==""){ + continue; + } + str = project.replaceProperties(str); + if (str.trim().substring(0,2).equalsIgnoreCase(tag)) { + list.add(str.trim()); + } else { + list.add(tag + " " + str.trim()); + } + + } + } catch (Exception e){ + System.out.println(e.getMessage()); + + } + } + +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FwImageTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FwImageTask.java new file mode 100644 index 0000000000..48262e543c --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/FwImageTask.java @@ -0,0 +1,199 @@ +/** @file + FwImageTask class. + + FwImageTask is used to call FwImage.ext to generate the FwImage. + + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.framework.tasks; + +import org.apache.tools.ant.Task; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; + +/** + FwImageTask class. + + FwImageTask is used to call FwImage.ext to generate the FwImage. +**/ +public class FwImageTask extends Task implements EfiDefine{ + /// + /// time&data + /// + private String time = ""; + /// + /// input PE image + /// + private String peImage = ""; + /// + /// output EFI image + /// + private String outImage = ""; + /// + /// component type + /// + private String componentType = ""; + + /** + * assemble tool command line & execute tool command line + * + * @throws BuildException + */ + /** + execute + + FwimageTask execute function is to assemble tool command line & execute + tool command line + + @throws BuidException + **/ + public void execute() throws BuildException { + + Project project = this.getOwningTarget().getProject(); + // + // absolute path of efi tools + // + String path = project.getProperty("env.Framework_Tools_Path"); + String command; + if (path == null) { + command = "fwimage"; + } else { + command = path + "/" + "fwimage"; + } + // + // argument of tools + // + String argument = time + componentType + peImage + outImage; + // + // return value of fwimage execution + // + int revl = -1; + + try { + Commandline cmdline = new Commandline(); + cmdline.setExecutable(command); + cmdline.createArgument().setLine(argument); + + LogStreamHandler streamHandler = new LogStreamHandler(this, + Project.MSG_INFO, Project.MSG_WARN); + Execute runner = new Execute(streamHandler, null); + + runner.setAntRun(project); + runner.setCommandline(cmdline.getCommandline()); + System.out.println(Commandline.toString(cmdline.getCommandline())); + + revl = runner.execute(); + if (EFI_SUCCESS == revl) { + // + // command execution success + // + System.out.println("fwimage successed!"); + } else { + // + // command execution fail + // + System.out.println("fwimage failed. (error=" + + Integer.toHexString(revl) + ")"); + throw new BuildException("fwimage failed. (error=" + + Integer.toHexString(revl) + ")"); + + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } + + /** + setTime + + This function is to set operation of class member "time". + + @param time string of time + **/ + public void setTime(String time) { + this.time = " -t " + time; + } + + /** + getTime + + This function is to get class member "time" + @return time string of time + **/ + public String getTime() { + return this.time; + } + + /** + getPeImage + + This function is to get class member "peImage". + @return name of PE image + **/ + public String getPeImage() { + return this.peImage; + } + + /** + setPeImage + + This function is to set class member "peImage" + @param peImage name of PE image + **/ + public void setPeImage(String peImage) { + this.peImage = " " + peImage; + } + + /** + getOutImage + + This function is to get class member "outImage". + @return name of output EFI image + **/ + public String getOutImage() { + return this.outImage; + } + + /** + setOutImage + + This function is to set class member "outImage". + @param outImage name of output EFI image + **/ + public void setOutImage(String outImage) { + this.outImage = " " + outImage; + } + + /** + getComponentType + + This function is to get class member "componentType". + + @return string of componentType + **/ + public String getComponentType() { + return this.componentType; + } + + /** + setComponentType + + This function is to set class member "componentType". + @param componentType string of component type + **/ + public void setComponentType(String componentType) { + this.componentType = " " + componentType; + } +} diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenCRC32SectionTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenCRC32SectionTask.java new file mode 100644 index 0000000000..ca426dfa69 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenCRC32SectionTask.java @@ -0,0 +1,183 @@ +/** @file + GenCRC32SectionTask class. + + GenCRC32SectionTask is to call GenCRC32Section.exe to generate crc32 section. + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.framework.tasks; + +import java.util.*; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; + +/** + GenCRC32SectionTask + + GenCRC32SectionTask is to call GenCRC32Section.exe to generate crc32 section. + +**/ +public class GenCRC32SectionTask extends Task implements EfiDefine{ + /// + /// output file + /// + private String outputFile; + /// + /// inputFile list + /// + private List inputFileList = new ArrayList(); + + /// + /// Project + /// + static private Project project; + + /** + execute + + GenCRC32SectionTask execute is to assemble tool command line & execute + tool command line + + @throws BuildException + **/ + public void execute() throws BuildException { + + project = this.getOwningTarget().getProject(); + /// + /// absolute path of efi tools + /// + String path = project.getProperty("env.Framework_Tools_Path"); + String command; + if (path == null) { + command = "gencrc32section"; + } else { + command = path + "/" + "gencrc32section" ; + } + // + // string line of input files + // + String inputFiles = list2Str(inputFileList, ""); + // + // assemble argument + // + String argument = inputFiles + outputFile; + // + // return value of fwimage execution + // + int revl = -1; + + try { + Commandline cmdline = new Commandline(); + cmdline.setExecutable(command); + cmdline.createArgument().setLine(argument); + + LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN); + Execute runner = new Execute(streamHandler, null); + + runner.setAntRun(project); + runner.setCommandline(cmdline.getCommandline()); + System.out.println(Commandline.toString(cmdline.getCommandline())); + + revl = runner.execute(); + if (EFI_SUCCESS == revl){ + // + // command execution success + // + System.out.println("gencrc32section succeeded!"); + } + else + { + // + // command execution fail + // + System.out.println("gencrc32section failed. (error=" + + Integer.toHexString(revl) + + ")" + ); + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + + } + + /** + addInputFile + + This function is to add a inputFile element into list + @param inputFile : inputFile element + **/ + public void addInputfile(InputFile inputFile) { + inputFileList.add(inputFile); + } + + /** + get class member "outputFile" + * @return name of output file + */ + public String getOutputFile() { + return this.outputFile; + } + /** + * set class member "outputFile" + * @param outputFile : outputFile parameter + */ + public void setOutputFile(String outputFile) { + this.outputFile = " -o " + outputFile; + }; + + /** + * transfer List to String + * @param list : nested element list + * @param tag : interval tag of parameter + * @return string line of parameters + */ + private String list2Str(List list, String tag) { + /* + * string line for return + */ + String paraStr = " -i"; + /* + * nested element in list + */ + NestElement element; + /* + * iterator of nested element list + */ + Iterator elementIter = list.iterator(); + /* + * string parameter list + */ + List strList = new ArrayList(); + + while (elementIter.hasNext()) { + element = (NestElement) elementIter.next(); + if (null != element.getFile()) { + FileParser.loadFile(project, strList, element.getFile(), tag); + } else { + paraStr = paraStr + element.getName(); + } + } + /* + * iterator of string parameter list + */ + Iterator strIter = strList.iterator(); + while (strIter.hasNext()) { + paraStr = paraStr + " " + strIter.next(); + } + return paraStr; + } +} diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenDepexTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenDepexTask.java new file mode 100644 index 0000000000..a13b74960c --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenDepexTask.java @@ -0,0 +1,166 @@ +/** @file + GenDepexTask class. + + GenDepexTask is to call GenDepex.exe to generate depex section. + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.framework.tasks; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; +/** + GenDepexTask + + GenDepexTask is to call GenDepex.exe to generate depex section. + +**/ +public class GenDepexTask extends Task implements EfiDefine { + /// + /// output binary dependency files name + /// + private String outputFile = ""; + /// + /// input pre-processed dependency text files name + /// + private String inputFile = ""; + /// + /// padding integer value + /// + private String padding = ""; + /** + execute + + GenDepexTask execute is to assemble tool command line & execute tool + command line. + */ + public void execute() throws BuildException { + + Project project = this.getOwningTarget().getProject(); + // + // absolute path of edk tools + // + String path = project.getProperty("env.Framework_Tools_Path"); + String command; + if (path == null) { + command = "gendepex"; + } else { + command = path + "/" + "gendepex"; + } + // + // argument of GenDepex tool + // + String argument = inputFile + outputFile + padding; + // + // reture value of GenDepex execution + // + int returnVal = -1; + + try { + Commandline commandLine = new Commandline(); + commandLine.setExecutable(command); + commandLine.createArgument().setLine(argument); + + LogStreamHandler streamHandler = new LogStreamHandler(this, + Project.MSG_INFO, Project.MSG_WARN); + + Execute runner = new Execute(streamHandler, null); + runner.setAntRun(project); + runner.setCommandline(commandLine.getCommandline()); + + System.out.println(Commandline.toString(commandLine + .getCommandline())); + + returnVal = runner.execute(); + if (EFI_SUCCESS == returnVal) { + // + // command execution success + // + System.out.println("GenDepex execute successed!"); + + } else { + // + // command execution fail + // + System.out.println("GenDepex failed. (error=" + + Integer.toHexString(returnVal) + ")"); + throw new BuildException("GenDepex failed. (error=" + + Integer.toHexString(returnVal) + ")"); + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } + + /** + setOutputFile + + This function is to set class member "outputFile" + @param outputFileName name of output file + **/ + public void setOutputFile(String outputFileName) { + this.outputFile = " -O " + outputFileName; + } + + /** + getOutputFile + + This function is to get class member "outputFile". + + @return name of ouput file + **/ + public String getOutputFile() { + return this.outputFile; + } + + /** + setInputFile + + This function is to set class member "inputFile". + @param inputFileName name of inputFile + **/ + public void setInputFile(String inputFileName) { + this.inputFile = " -I " + inputFileName; + } + + /** + getInputFile + + This function is to get class member "inputFile" + @return name of input file + **/ + public String getInputFile() { + return this.inputFile; + } + + /** + setPadding + + This function is to set class member "padding" + @param paddingNum padding value + **/ + public void setPadding(String paddingNum) { + this.padding = " -P " + paddingNum; + } + + /** + getPadding + + This function is to get class member "padding" + @return value of padding + **/ + public String getPadding() { + return this.padding; + } +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenFfsFileTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenFfsFileTask.java new file mode 100644 index 0000000000..00712d8bb6 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenFfsFileTask.java @@ -0,0 +1,878 @@ +/** @file + GenFfsFileTask class. + + GenFfsFileTaks is to generate ffs file. + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.framework.tasks; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; + +/** + GenFfsFileTask + + GenFfsFileTaks is to generate ffs file. + +**/ +public class GenFfsFileTask extends Task implements EfiDefine, FfsTypes { + /** + * GenFfsFile Task Class + * class member + * -baseName : module baseName + * -ffsFileGuid : module Guid. + * -ffsFileType : Ffs file type. + * -ffsAttributeRecovery : The file is required for recovery. + * -ffsAligment : The file data alignment (0 if none required). See FFS + * specification for supported alignments (0-7 are only possible + * values). * + * -ffsAttributeCheckSum : The file data is checksummed. If this is FALSE a + * value of 0x5A will be inserted in the file + * checksum field of the file header. * + * -sectFileDir : specifies the full path to the component build directory. + * Required. + * -ffsAttrib : Data recorde attribute added result. + * -sectionList : List recorded all section elemet in task. + */ + /// + /// module baseName + /// + String baseName = ""; + /// + /// module Guid + /// + String ffsFileGuid = ""; + /// + /// Ffs file type + /// + String ffsFileType = ""; + /// + /// ffsAttribHeaderExtension value is used to set the corresponding bit in + /// the output FFS file header + /// + boolean ffsAttribHeaderExtension = false; + /// + /// ffsAttribTailPresent value is used to set the corresponding bit in the + /// output FFS file header + /// + boolean ffsAttribTailPresent = false; + /// + /// ffsAttribRecovery value is used to set the corresponding bit in the + /// output FFS file header + /// + boolean ffsAttribRecovery = false; + /// + /// ffsAligenment value is used to set the corresponding bit in the output + /// FFS file header.The specified FFS alignment must be a value between 0 + /// and 7 inclusive + /// + int ffsAlignment = 0; + /// + /// ffsAttribChecksum value is used to set the corresponding bit in the + /// output FFS file header + /// + boolean FfsAttribChecksum = false; + /// + /// Attribute is used to record the sum of all bit in the output FFS file. + /// + byte attributes = 0; + /// + /// The output directory of ffs file. + /// + String outputDir = ""; + /// + /// List of section. + /// + List sectionList = new ArrayList(); + + /// + /// The path of Framewor_Tools_Paht. + /// + static String path = ""; + + /** + execute + + GenFfsFileTask execute is to generate ffs file according to input section + dscriptive information. + */ + public void execute() throws BuildException { + Section sect; + int fileSize; + int fileDataSize; + File ffsFile; + FfsHeader ffsHeader = new FfsHeader(); + String ffsSuffix = ""; + String outputPath = ""; + + // + // Get Fraemwork_Tools_Path + // + Project pj = this.getOwningTarget().getProject(); + path = pj.getProperty("env.Framework_Tools_Path"); + + // + // Check does the BaseName, Guid, FileType set value. + // + if (this.baseName.equals("")) { + throw new BuildException ("Must set BaseName!\n"); + } + + if (this.ffsFileGuid.equals("")) { + throw new BuildException ("Must set ffsFileGuid!\n"); + } + + if (this.ffsFileType.equals("")) { + throw new BuildException ("Must set ffsFileType!\n"); + } + + // + // Create ffs file. File name = FfsFileGuid + BaseName + ffsSuffix. + // If outputDir's value was set, file will output to the outputDir. + // + ffsSuffix = TypeToSuffix (this.ffsFileType); + if (!this.outputDir.equals("")) { + String temp; + outputPath = this.outputDir; + temp = outputPath.replace('\\', File.separatorChar); + outputPath = temp.replace('/', File.separatorChar); + if (outputPath.charAt(outputPath.length()-1) != File.separatorChar) { + outputPath = outputPath + File.separator; + } + + } + + ffsFile = new File (outputPath + this.ffsFileGuid + '-' + this.baseName + ffsSuffix); + System.out.print("General Ffs file: file name is:\n"); + System.out.print(outputPath + this.ffsFileGuid + '-' + this.baseName + ffsSuffix); + System.out.print("\n"); + + // + // Create file output stream -- dataBuffer. + // + try { + FileOutputStream dataFs = new FileOutputStream (ffsFile.getAbsolutePath()); + DataOutputStream dataBuffer = new DataOutputStream (dataFs); + + // + // Search SectionList find earch section and call it's + // ToBuffer function. + // + Iterator sectionIter = this.sectionList.iterator(); + while (sectionIter.hasNext()) { + sect = (Section)sectionIter.next(); + + try { + // + // The last section don't need 4 byte ffsAligment. + // + sect.toBuffer((DataOutputStream)dataBuffer); + } catch (Exception e) { + throw new BuildException (e.getMessage()); + } + } + dataBuffer.close(); + } catch (Exception e) { + throw new BuildException (e.getMessage()); + } + + // + // Creat Ffs file header + // + try { + + // + // create input stream to read file data + // + byte[] fileBuffer = new byte[(int)ffsFile.length()]; + FileInputStream fi = new FileInputStream (ffsFile.getAbsolutePath()); + DataInputStream di = new DataInputStream (fi); + di.read(fileBuffer); + di.close(); + + + // + // Add GUID to header struct + // + if (this.ffsFileGuid != null) { + stringToGuid (this.ffsFileGuid, ffsHeader.name); + } + + ffsHeader.ffsAttributes = this.attributes; + if ((ffsHeader.fileType = stringToType(this.ffsFileType))== -1) { + throw new BuildException ("FFS_FILE_TYPE unknow!\n"); + } + + + // + // Adjust file size. The function is used to tripe the last + // section padding of 4 binary boundary. + // + // + if (ffsHeader.fileType != EFI_FV_FILETYPE_RAW) { + + fileDataSize = adjustFileSize (fileBuffer); + + } else { + fileDataSize = fileBuffer.length; + } + + // + // 1. add header size to file size + // + fileSize = fileDataSize + ffsHeader.getSize(); + + if ((ffsHeader.ffsAttributes & FFS_ATTRIB_TAIL_PRESENT) != 0) { + if (ffsHeader.fileType == EFI_FV_FILETYPE_FFS_PAD) { + + throw new BuildException ( + "FFS_ATTRIB_TAIL_PRESENT=TRUE is " + + "invalid for PAD files" + ); + } + if (fileSize == ffsHeader.getSize()) { + throw new BuildException ( + "FFS_ATTRIB_TAIL_PRESENT=TRUE is " + + "invalid for 0-length files" + ); + } + fileSize = fileSize + 2; + } + + // + // 2. set file size to header struct + // + ffsHeader.ffsFileSize[0] = (byte)(fileSize & 0x00FF); + ffsHeader.ffsFileSize[1] = (byte)((fileSize & 0x00FF00)>>8); + ffsHeader.ffsFileSize[2] = (byte)(((int)fileSize & 0xFF0000)>>16); + + // + // Fill in checksums and state, these must be zero for checksumming + // + ffsHeader.integrityCheck.header = calculateChecksum8 ( + ffsHeader.structToBuffer(), + ffsHeader.getSize() + ); + + if ((this.attributes & FFS_ATTRIB_CHECKSUM) != 0) { + if ((this.attributes & FFS_ATTRIB_TAIL_PRESENT) != 0) { + ffsHeader.integrityCheck.file = calculateChecksum8 ( + fileBuffer, + fileDataSize + ); + } else { + ffsHeader.integrityCheck.file = calculateChecksum8 ( + fileBuffer, + fileDataSize + ); + } + } else { + ffsHeader.integrityCheck.file = FFS_FIXED_CHECKSUM; + } + + // + // Set the state now. Spec says the checksum assumes the state is 0. + // + ffsHeader.ffsState = EFI_FILE_HEADER_CONSTRUCTION | + EFI_FILE_HEADER_VALID | + EFI_FILE_DATA_VALID; + + + // + // create output stream to first write header data in file, then write sect data in file. + // + FileOutputStream headerFfs = new FileOutputStream (ffsFile.getAbsolutePath()); + DataOutputStream ffsBuffer = new DataOutputStream (headerFfs); + + // + // Add header struct and file data to FFS file + // + ffsBuffer.write(ffsHeader.structToBuffer()); + for (int i = 0; i< fileDataSize; i++) { + ffsBuffer.write(fileBuffer[i]); + } + + // + // If there is a tail, then set it + // + if ((this.attributes & FFS_ATTRIB_TAIL_PRESENT) != 0) { + short tailValue ; + byte [] tailByte = new byte[2]; + + // + // reverse tailvalue , integritycheck.file as hight byte, and + // integritycheck.header as low byte. + // + tailValue = (short)(ffsHeader.integrityCheck.header & 0xff); + tailValue = (short)((tailValue) | ((ffsHeader.integrityCheck.file << 8) & 0xff00)); + tailValue = (short)~tailValue; + + // + // Change short to byte[2] + // + tailByte[0] = (byte)(tailValue & 0xff); + tailByte[1] = (byte)((tailValue & 0xff00)>>8); + ffsBuffer.write(tailByte[0]); + ffsBuffer.write(tailByte[1]); + } + + // + // close output stream. Note if don't close output stream + // the buffer can't be rewritten to file. + // + ffsBuffer.close(); + System.out.print ("Successful create ffs file!\n"); + } catch (Exception e) { + throw new BuildException (e.getMessage()); + } + } + + /** + addCompress + + This function is to add compress section to section list. + @param compress Section of compress + **/ + public void addCompress(CompressSection compress) { + this.sectionList.add(compress); + } + + /** + addTool + + This function is to add tool section to section list. + @param tool Section of tool + **/ + public void addTool(Tool tool) { + this.sectionList.add(tool); + } + + /** + addSectionFile + + This function is to add sectFile section to section list. + @param sectFile Section of sectFile. + **/ + public void addSectFile (SectFile sectFile) { + this.sectionList.add(sectFile); + } + + /** + getBaseName + + This function is to get basename + + @return String of base name + **/ + public String getBaseName() { + return this.baseName; + } + + /** + setBaseName + + This function is to set base name. + @param baseName + **/ + public void setBaseName(String baseName) { + this.baseName = baseName.trim(); + } + + /** + getFfsAligment + + This function is to get the ffsAligment + @return The value of ffsAligment. + **/ + public int getFfsAligment() { + return this.ffsAlignment; + } + + /** + setFfsAligment + + This function is to set ffsAligment + @param ffsAligment The value of ffsAligment. + **/ + public void setFfsAligment(int ffsAligment) { + this.ffsAlignment = ffsAligment; + if (this.ffsAlignment > 7) { + throw new BuildException ("FFS_ALIGMENT Scope is 0-7"); + } else { + attributes |= (((byte)this.ffsAlignment) << 3); + } + } + + /** + getFfsAttribCheckSum + + This function is to get ffsAttribCheckSum + + @return Value of ffsAttribChecksum + **/ + public boolean getFfsAttribChecksum() { + return this.FfsAttribChecksum; + } + + /** + setFfsAttribChecksum + + This function is to set ffsAttribChecksum + @param ffsAttributeCheckSum Value of ffsAttribCheckSum + **/ + public void setFfsAttribChecksum(boolean ffsAttributeCheckSum) { + this.FfsAttribChecksum = ffsAttributeCheckSum; + if (ffsAttributeCheckSum) { + attributes |= FFS_ATTRIB_CHECKSUM; + } + } + + /** + getFfsAttribRecovery + + This function is to get ffsAttribRecovery + @return Value of ffsAttribRecovery + **/ + public boolean getFfsAttribRecovery() { + return this.ffsAttribRecovery; + } + + /** + setRecovery + + This function is to set ffsAttributeRecovery + + @param ffsAttributeRecovery Value of ffsAttributeRecovery + **/ + public void setRecovery(boolean ffsAttributeRecovery) { + this.ffsAttribRecovery = ffsAttributeRecovery; + if (ffsAttributeRecovery) { + attributes |= FFS_ATTRIB_RECOVERY; + } + } + + /** + getFileGuid + + This function is to get fileGuid + @return Guid + **/ + public String getFileGuid() { + return this.ffsFileGuid; + } + + /** + setFileGuid + + This function is to set fileGuid + @param ffsFileGuid String of GUID + **/ + public void setFileGuid(String ffsFileGuid) { + this.ffsFileGuid = ffsFileGuid.trim(); + } + + /** + getFfsFileType + + This function is to get ffsFileType. + + @return value of ffsFileType + **/ + public String getFfsFileType() { + return this.ffsFileType; + } + + /** + setFfsFileType + + This function is to set ffsFileType. + + @param ffsFileType + **/ + public void setFfsFileType(String ffsFileType) { + this.ffsFileType = ffsFileType.trim(); + } + + /** + ffsAttribHeaderExtension + + This function is to get ffsAttribHeaderExtension + + @return Value of ffsAttribHeaderExtension + **/ + public boolean isFfsAttribHeaderExtension() { + return this.ffsAttribHeaderExtension; + } + + /** + setHeaderExension + + This function is to set headerExtension + @param headerExtension Value of headerExension + **/ + public void setHeaderExtension(boolean headerExtension) { + this.ffsAttribHeaderExtension = headerExtension; + if (headerExtension) { + attributes |= FFS_ATTRIB_HEADER_EXTENSION; + } + } + + /** + isFfsAttribTailPresent + + This function is to get ffsAttribTailPresent value. + @return Value of ffsAttribTailPresent. + **/ + public boolean isFfsAttribTailPresent() { + return this.ffsAttribTailPresent; + } + + /** + setFfsAttribTailPresent + + This function is to set ffsAttribTailPresent. + @param tailPresent Value of ffsAttribTailPresent. + **/ + public void setFfsAttribTailPresent(boolean tailPresent) { + this.ffsAttribTailPresent = tailPresent; + if (tailPresent) { + attributes |= FFS_ATTRIB_TAIL_PRESENT; + } + } + + + /** + stringToGuid + + This function is to convert string to GUID. + * @param GuidStr String of GUID. + * @param Guid GUID form. + */ + private void stringToGuid (String GuidStr, FfsHeader.FfsGuid Guid){ + + int i = 0; + int j = 0; + int k = 0; + char [] charArry; + String [] SplitStr; + + byte[] buffer = new byte[16]; + if (GuidStr.length()!=36) { + throw new BuildException ("Guid length is not correct!"); + } + + + SplitStr = GuidStr.split("-"); + if (SplitStr.length != 5) { + throw new BuildException ("Guid type is not correct!"); + } + + + + for (i= 0; i < SplitStr.length; i++) { + String str = SplitStr[i]; + charArry = str.toCharArray(); + + for (j =0; j < (str.toCharArray().length)/2; j++) { + + buffer[k] = hexCharToByte (charArry[j*2]); + buffer[k] = (byte)( buffer[k]& 0x0f); + buffer[k] = (byte)((buffer[k]<< 4)); + buffer[k] = (byte)( buffer[k]& 0xf0); + buffer[k] = (byte)( buffer[k]|hexCharToByte(charArry[j*2+1])); + k++; + } + } + Guid.bufferToStruct(buffer); + } + + /** + typeToSuffix + + This function is to get suffix of ffs file according to ffsFileType. + + @param ffsFileType ffsFileType + @return The suffix of ffs file + **/ + private String TypeToSuffix (String ffsFileType){ + if (ffsFileType.equals("EFI_FV_FILETYPE_ALL")) { + return ""; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_RAW")) { + return EFI_FV_FFS_FILETYPE_STR; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_FREEFORM")) { + return EFI_FV_FFS_FILETYPE_STR; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_SECURITY_CORE")) { + return EFI_FV_SEC_FILETYPE_STR; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_PEI_CORE")) { + return EFI_FV_PEI_FILETYPE_STR; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_DXE_CORE")) { + return EFI_FV_DXE_FILETYPE_STR; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_PEIM")) { + return EFI_FV_PEI_FILETYPE_STR; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_DRIVER")) { + return EFI_FV_DXE_FILETYPE_STR; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER")) { + return EFI_FV_PEI_FILETYPE_STR; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_APPLICATION")) { + return EFI_FV_APP_FILETYPE_STR; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE")) { + return EFI_FV_FVI_FILETYPE_STR; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_FFS_PAD")) { + return EFI_FV_FFS_FILETYPE_STR; + } + return ""; + } + + + /** + stringToType + + This function is to get ffsFileType integer value according to ffsFileType. + @param ffsFileType String value of ffsFileType + @return Integer value of ffsFileType. + **/ + private byte stringToType (String ffsFileType){ + + if (ffsFileType.equals("EFI_FV_FILETYPE_ALL")) { + return(byte)EFI_FV_FILETYPE_ALL; + } + + if (ffsFileType.equals("EFI_FV_FILETYPE_RAW")) { + return(byte)EFI_FV_FILETYPE_RAW; + } + + if (ffsFileType.equals("EFI_FV_FILETYPE_FREEFORM")) { + return(byte)EFI_FV_FILETYPE_SECURITY_CORE; + } + + if (ffsFileType.equals("EFI_FV_FILETYPE_SECURITY_CORE")) { + return(byte)EFI_FV_FILETYPE_SECURITY_CORE; + } + + if (ffsFileType.equals("EFI_FV_FILETYPE_PEI_CORE")) { + return(byte) EFI_FV_FILETYPE_PEI_CORE; + } + + if (ffsFileType.equals("EFI_FV_FILETYPE_DXE_CORE")) { + return(byte)EFI_FV_FILETYPE_DXE_CORE; + } + + if (ffsFileType.equals("EFI_FV_FILETYPE_PEIM")) { + return(byte)EFI_FV_FILETYPE_PEIM; + } + + if (ffsFileType.equals("EFI_FV_FILETYPE_DRIVER")) { + return(byte) EFI_FV_FILETYPE_DRIVER; + } + + if (ffsFileType.equals("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER")) { + return(byte)EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER; + } + + if (ffsFileType.equals("EFI_FV_FILETYPE_APPLICATION")) { + return(byte)EFI_FV_FILETYPE_APPLICATION; + } + + if (ffsFileType.equals("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE")) { + return(byte)EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE; + } + if (ffsFileType.equals("EFI_FV_FILETYPE_FFS_PAD")) { + return(byte) EFI_FV_FILETYPE_FFS_PAD; + } + + return -1; + } + + + + /** + calculateCheckSum8 + + This function is to calculate the value needed for a valid UINT8 checksum + @param buffer Byte buffer containing byte data of component. + @param size Size of the buffer. + @return The 8 bit checksum value needed. + **/ + private byte calculateChecksum8 (byte[] buffer, int size){ + return(byte) (0x100 - calculateSum8 (buffer, size)); + } + + + /** + calculateSum8 + + This function is to calculate the UINT8 sum for the requested region. + @param buffer Byte buffer containing byte data of component + @param size Size of the buffer. + @return The 8 bit checksum value needed. + **/ + private short calculateSum8 (byte[] buffer, int size){ + int Index; + byte Sum; + Sum = 0; + + // + // Perform the word sum for buffer + // + for (Index = 0; Index < size; Index++) { + Sum = (byte) (Sum + buffer[Index]); + } + + return(byte) Sum; + } + + /** + hexCharToByte + + This function is to convert hex character to byte + + @param hexChar hex character + @return Byte which corresponding to the character. + **/ + private byte hexCharToByte (char hexChar){ + switch (hexChar) { + case '0': + return(byte)0x00; + case '1': + return(byte)0x01; + case '2': + return(byte)0x02; + case '3': + return(byte)0x03; + case '4': + return(byte)0x04; + case '5': + return(byte)0x05; + case '6': + return(byte)0x06; + case '7': + return(byte)0x07; + case '8': + return(byte)0x08; + case '9': + return(byte)0x09; + case 'a': + case 'A': + return(byte)0x0a; + case 'b': + case 'B': + return(byte)0x0b; + case 'c': + case 'C': + return(byte)0x0c; + + case 'd': + case 'D': + return(byte)0x0d; + + case 'e': + case 'E': + return(byte)0x0e; + case 'f': + case 'F': + return(byte)0x0f; + + default: + return(byte)0xff; + } + } + + /** + adjustFileSize + + This function is used to adjusts file size to insure sectioned file is exactly the right length such + that it ends on exactly the last byte of the last section. ProcessScript() + may have padded beyond the end of the last section out to a 4 byte boundary. + This padding is stripped. + + @param buffer Byte buffer contains a section stream + @return Corrected size of file. + **/ + private int adjustFileSize (byte[] buffer){ + + int orignalLen = buffer.length; + int adjustLen = 0; + int sectionPoint = 0; + int nextSectionPoint = 0; + int sectionLen = 0; + int totalLen = 0; + int firstSectionHeader = 0; + + + firstSectionHeader = buffer[0]& 0xff; + firstSectionHeader = ((buffer[1]&0xff)<<8) | firstSectionHeader; + firstSectionHeader = ((buffer[2]&0xff)<<16)| firstSectionHeader; + + + while (sectionPoint < buffer.length) { + sectionLen = buffer[0 + sectionPoint]& 0xff; + sectionLen = ((buffer[1 + sectionPoint]&0xff)<<8)| sectionLen; + sectionLen = ((buffer[2 + sectionPoint]&0xff)<<16)| sectionLen; + totalLen = totalLen + sectionLen; + + if (totalLen == orignalLen) { + return totalLen; + } + + sectionPoint = sectionPoint + sectionLen; + adjustLen = sectionPoint; + + nextSectionPoint = (sectionPoint + 0x03) & (~0x03); + totalLen = totalLen + nextSectionPoint - sectionLen; + sectionPoint = nextSectionPoint; + } + return adjustLen; + } + + /** + getOutputDir + + This function is to get output directory. + + @return Path of output directory. + **/ + public String getOutputDir() { + return outputDir; + } + + /** + setOutputDir + + This function is to set output directory. + + @param outputDir The output direcotry. + **/ + public void setOutputDir(String outputDir) { + this.outputDir = outputDir; + } +} diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenFvImageTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenFvImageTask.java new file mode 100644 index 0000000000..cd1e421263 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenFvImageTask.java @@ -0,0 +1,154 @@ +/** @file + GenFvImageTask class. + + GenFvImageTask is to call GenFvImage.exe to generate FvImage. + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.framework.tasks; +import java.io.File; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; + +/** + GenFvImageTask + + GenFvImageTask is to call GenFvImage.exe to generate the FvImage. + +**/ +public class GenFvImageTask extends Task implements EfiDefine{ + /// + /// The name of input inf file + /// + private String infFile=""; + /// + /// The target architecture. + /// + private String arch=""; + + /** + execute + + GenFvImageTask execute is to assemble tool command line & execute tool + command line. + **/ + public void execute() throws BuildException { + Project project = this.getOwningTarget().getProject(); + String path = project.getProperty("env.Framework_Tools_Path"); + String command = ""; + + if (path == null){ + path = ""; + }else { + path = path + File.separatorChar; + } + + if (arch.equalsIgnoreCase("")){ + command = path + "GenFvImage"; + } + if (arch.equalsIgnoreCase("ia32")){ + command = path + "GenFvImage_IA32"; + } + if (arch.equalsIgnoreCase("x64")){ + command = path + "GenFvImage_X64"; + } + if (arch.equalsIgnoreCase("ipf")){ + command = path + "GenFvImage_IPF"; + } + String argument = infFile; + + try { + + Commandline commandLine = new Commandline(); + commandLine.setExecutable(command); + commandLine.createArgument().setLine(argument); + + LogStreamHandler streamHandler = new LogStreamHandler(this, + Project.MSG_INFO, + Project.MSG_WARN); + // + // create a execute object and set it's commandline + // + Execute runner = new Execute(streamHandler,null); + runner.setAntRun(project); + runner.setCommandline(commandLine.getCommandline()); + System.out.println(Commandline.toString(commandLine.getCommandline())); + + int revl = -1; + // + // user execute class call external programs - GenFvImage + // + revl = runner.execute(); + // + // execute command line success! + // + if (EFI_SUCCESS == revl){ + System.out.println("GenFvImage succeeded!"); + } else { + + // + // execute command line failed! + // + throw new BuildException("GenFvImage failed !(error =" + + Integer.toHexString(revl) + ")"); + } + + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + /** + getInfFile + + This function is to get class member of infFile + @return String name of infFile + **/ + public String getInfFile() { + return infFile; + } + + /** + setInfFile + + This function is to set class member of infFile. + + @param infFile name of infFile + **/ + public void setInfFile(String infFile) { + this.infFile = "-I " + infFile; + } + + /** + getArch + + This function is to get class member of arch. + @return The target architecture. + **/ + public String getArch() { + return arch; + } + + /** + setArch + + This function is to set class member of arch. + + @param arch The target architecture. + **/ + public void setArch(String arch) { + this.arch = arch; + } +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenSectionTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenSectionTask.java new file mode 100644 index 0000000000..e432a2ce41 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GenSectionTask.java @@ -0,0 +1,215 @@ +/** @file + GenSectionTask class. + + GenSectionTask is to call GenSection.exe to generate Section. + + Copyright (c) 2006, 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. + +**/ + +package org.tianocore.framework.tasks; + +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; + +public class GenSectionTask extends Task implements EfiDefine { + /// + /// inputfile name + /// + private String inputFile = ""; + /// + /// outputfile name + /// + private String outputFile = ""; + /// + /// section type + /// + private String sectionType = ""; + /// + /// version number + /// + private String versionNum = ""; + /// + /// interface string + /// + private String interfaceString = ""; + + /** + execute + + GenSectionTaks execute is to assemble tool command line & execute tool + command line. + + @throws BuildException + **/ + public void execute() throws BuildException { + String command; + Project project = this.getOwningTarget().getProject(); + // + // absolute path of efi tools + // + String path = project.getProperty("env.Framework_Tools_Path"); + if (path == null) { + command = "gensection"; + } else { + command = path + "/" + "gensection"; + } + // + // argument of tools + // + String argument = inputFile + outputFile + sectionType + versionNum + + interfaceString; + // + // return value of gensection execution + // + int revl = -1; + + try { + Commandline cmdline = new Commandline(); + cmdline.setExecutable(command); + cmdline.createArgument().setLine(argument); + + LogStreamHandler streamHandler = new LogStreamHandler(this, + Project.MSG_INFO, Project.MSG_WARN); + Execute runner = new Execute(streamHandler, null); + + runner.setAntRun(project); + runner.setCommandline(cmdline.getCommandline()); + System.out.println(Commandline.toString(cmdline.getCommandline())); + + revl = runner.execute(); + if (EFI_SUCCESS == revl) { + // + // command execution success + // + System.out.println("gensection successed!"); + } else { + // + // command execution fail + // + System.out.println("gensection failed. (error=" + + Integer.toHexString(revl) + ")"); + throw new BuildException("gensection failed. (error=" + + Integer.toHexString(revl) + ")"); + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } + + /** + getInputFile + + This function is to get class member "inputFile". + + @return name of input file + **/ + public String getInputFile() { + return this.inputFile; + } + + /** + setInputFile + + This function is to set class member "inputFile". + + @param inputFile name of input file + **/ + public void setInputFile(String inputFile) { + this.inputFile = " -i " + inputFile; + } + + /** + getOutputFile + + This function is to get class member "outputFile". + + @return name of output file + **/ + public String getOutputFile() { + return this.outputFile; + } + + /** + setOutputfile + + This function is to set class member "outputFile". + @param outputFile name of output file + **/ + public void setOutputfile(String outputFile) { + this.outputFile = " -o " + outputFile; + } + + /** + getSectionType + + This function is to get class member "sectionType". + + @return sectoin type + **/ + public String getSectionType() { + return this.sectionType; + } + + /** + setSectionType + + This function is to set class member "sectionType". + + @param sectionType section type + **/ + public void setSectionType(String sectionType) { + this.sectionType = " -s " + sectionType; + } + + /** + getVersionNum + + This function is to get class member "versionNum". + @return version number + **/ + public String getVersionNum() { + return this.versionNum; + } + + /** + setVersionNume + + This function is to set class member "versionNum". + @param versionNum version number + **/ + public void setVersionNum(String versionNum) { + this.versionNum = " -v " + versionNum; + } + + /** + getInterfaceString + + This function is to get class member "interfaceString". + @return interface string + **/ + public String getInterfaceString() { + return this.interfaceString; + } + + /** + setInterfaceString + + This funcion is to set class member "interfaceString". + @param interfaceString interface string + **/ + public void setInterfaceString(String interfaceString) { + this.interfaceString = " -a " + "\"" + interfaceString + "\""; + } +} diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GuidChkTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GuidChkTask.java new file mode 100644 index 0000000000..69feb4e03d --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/GuidChkTask.java @@ -0,0 +1,367 @@ +/** @file + GuidChkTask class. + + GuidChkTask is to call GuidChk.exe to generate Section. + + Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.PrintWriter; +import java.io.File; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; + +/** + GuidChkTask + + GuidChkTask is to call GuidChk.exe to generate Section. + +**/ +public class GuidChkTask extends Task implements EfiDefine{ + /** + * GuidChk task class + * class member + * -exDir : directory name of exclusion searching + * -exFile : file name of exclusion searching + * -exExt : extension name of exclusion searching + * -exSubDir: extesnion name of sub dir which excluded searching + * -outFile : out put file wrote internal GUID+basename list + * -chkGui : check for duplicate guids + * -chkSign : check for duplicate signatures + * -printGuiDef : if set will print guid+defined symbol name + * -printAllGuid: if set will print all GUIDS found + * -outPut : redirection file name + * -fos : out put redirect to this file + * + */ + /// + /// Directory name of exclusion searching + /// + private String exDir = ""; + /// + /// File name of exclusion searching. + /// + private String exFile = ""; + /// + /// Extension name of exclusion searching. + /// + private String exExt = ""; + /// + /// Extesnion name of sub dir which excluded searching. + /// + private String exSubDir = ""; + /// + /// Out put file wrote internal GUID+basename list + /// + private String outFile = ""; + /// + /// Check for duplicate guids. + /// + private String chkGui = ""; + /// + /// Check for duplicate signatures + /// + private String chkSign = ""; + /// + /// If set will print guid+defined symbol name + /// + private String printGuiDef = ""; + /// + /// If set will print all GUIDS found + /// + private String printAllGuid = ""; + /// + /// redirection file name. + /// + private String outPut = ""; + /// + /// out put redirect to this file. + /// + protected PrintWriter fos = null; + + // + // overload class execute method + // + public void execute() throws BuildException { + Project project = this.getOwningTarget().getProject(); + String path = project.getProperty("env.Framework_Tools_Path"); + String command; + if (path == null) { + command = "GuidChk"; + } else { + command = path + File.separatorChar + "GuidChk"; + } + String argument = exDir + + exFile + + exExt + + exSubDir + + outFile + + chkGui + + chkSign + + printGuiDef + + printAllGuid; + try { + System.out.println(command + " " + argument); + // + // execute command line + // + Process proc = Runtime.getRuntime().exec(command + "" + argument); + // + // if set output, redirect out put to output file, else print output to screen + // + if ( !this.outPut.equals("")) { + fos = new PrintWriter(this.outPut); + BufferedReader bin = new BufferedReader(new InputStreamReader(proc.getInputStream())); + String line = bin.readLine(); + while (line != null ){ + fos.println(line); + line = bin.readLine(); + } + fos.close(); + } + else { + BufferedReader bin = new BufferedReader(new InputStreamReader(proc.getInputStream())); + String line = bin.readLine(); + System.out.println(line); + while (line != null ){ + System.out.print(line); + line = bin.readLine(); + } + } + System.out.println("GuidChkTask Success!"); + } catch (Exception e) { + System.out.println("GuidChkTask failed!"); + System.out.println(e.getMessage()); + + } + } + /** + getChkGui + + This function is to get the string of flag of ChkGui + + @return string of flag of ChkGui + **/ + public String getChkGui() { + return chkGui; + } + + /** + setChkGui + + This function is to set chkGui + + @param chkGui set class member of chkGui + **/ + public void setChkGui(String chkGui) { + if (chkGui.equals("on")||(chkGui.equals("ON"))){ + this.chkGui = " -g "; + } + + } + + /** + getChkSign + + This function is to get chkSign + + @return chkSign + **/ + public String getChkSign() { + return chkSign; + } + + /** + setChkSign + + This function is to set class member of chkSign + * @param chkSign + */ + public void setChkSign(String chkSign) { + if (chkSign.equals("on")|| chkSign.equals("ON")){ + this.chkSign = " -s "; + } + } + /** + getExDir + + This function is to get class member of exDir + + @return exDir + **/ + public String getExDir() { + return exDir; + } + + /** + setExDir + + This function is to set class member of exDir + + @param exDir + **/ + public void setExDir(String exDir) { + this.exDir = " -d " + exDir; + } + + /** + getExExt + + This function is to get class member of exExt + + @return exExt + **/ + public String getExExt() { + return exExt; + } + + /** + setExExt + + This function is to set class member of exExt + @param exExt + **/ + public void setExExt(String exExt) { + this.exExt = " -e " + exExt; + } + + /** + getExFile + + This function is to get class member of exFile + @return exFile + **/ + public String getExFile() { + return exFile; + } + + /** + setExFile + + This function is to set class member of exFile. + + @param exFile + **/ + public void setExFile(String exFile) { + this.exFile = " -f " + exFile; + } + + /** + getExSubDir + + This function is to get class member of exSubDir + + @return exSubDir + **/ + public String getExSubDir() { + return exSubDir; + } + + /** + setExSubDir + + This function is to set class member of exSubDir. + @param exSubDir + **/ + public void setExSubDir(String exSubDir) { + this.exSubDir = " -u " + exSubDir; + } + + /** + getOutFile + + This function is to get outFile + + @return outFile + **/ + public String getOutFile() { + return outFile; + } + /** + * set class member of outFile + * @param outFile + */ + public void setOutFile(String outFile) { + this.outFile = " -b " + outFile; + } + /** + getPrintGuidDef + + This function is to get printGuidDef + + @return flage of printing (guid+defined symbol name) + **/ + public String getPrintGuiDef() { + return printGuiDef; + } + + + /** + setPrintGuidDef + + This function is to set class member of printGuiDef. + @param printGuiDef + **/ + public void setPrintGuiDef(String printGuiDef) { + if (printGuiDef.equals("on")|| printGuiDef.equals("ON")){ + this.printGuiDef = " -x "; + } + + } + + /** + getOutput + + This function is to get output + + @return name of outPut file + **/ + public String getOutPut() { + return outPut; + } + + /** + setOutPut + + This function is to set class member of outPut. + @param outPut + **/ + public void setOutPut(String outPut) { + this.outPut = outPut; + } + + /** + getPrintAllGuid + + This function is to get printAllGuid + @return printAllGuid + **/ + public String getPrintAllGuid() { + return printAllGuid; + } + + /** + setPrintAllGuid + + This function is to set class member of printAllGuid. + @param printAllGuid + **/ + public void setPrintAllGuid(String printAllGuid) { + if (printAllGuid.equals("on")||printAllGuid.equals("ON")) { + this.printAllGuid = " -p "; + } + } +} + diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/IncludePath.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/IncludePath.java new file mode 100644 index 0000000000..3a30488cea --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/IncludePath.java @@ -0,0 +1,123 @@ +/** @file +This file is used to nest elements which is meant for include path name + +Copyright (c) 2006, 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. + +**/ + +package org.tianocore.framework.tasks; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +public class IncludePath implements NestElement { + /** + IncludePath nested element Class + class member + -name : name of include path + -file : name of file including include path + **/ + private String path = ""; + private File file; + private List nameList = new ArrayList(); + + /** + get class member "file" + + @returns The File object + **/ + public File getFile() { + return this.file; + } + + /** + set class member "file" + + @param file The name of include path + **/ + public void setFile(File file) { + this.file = file; + } + + /** + get class member "file" + + @returns The name of include path + **/ + public String getPath() { + return this.path; + } + + /** + get class member "name" + + @returns The name of include path + **/ + public String getName() { + return this.path; + } + + /** + set class member "name" + + @param name The name of include path + **/ + public void setName(String name){ + this.path = "-I " + name; + } + + /** + set class member "path" + + @param name name of file including include paths + **/ + public void setPath(String name) { + this.path = " -I " + name; + } + + /** + override Object.toString() + + @returns name of file including include paths + **/ + public String toString() { + return getPath(); + } + + /** + set class member "list" + + @param fileNameList name list of include paths, sperated by space, tab, + comma or semi-comma + **/ + public void setList(String fileNameList) { + if (fileNameList != null && fileNameList.length() > 0) { + StringTokenizer tokens = new StringTokenizer(fileNameList, " \t,;", false); + while (tokens.hasMoreTokens()) { + String fileName = tokens.nextToken().trim(); + if (fileName.length() > 0) { + this.nameList.add(fileName); + } + } + } + } + + /** + get class member "list" + + @returns The include paths list. + **/ + public List getList() { + return nameList; + } +} + diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Input.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Input.java new file mode 100644 index 0000000000..b940e8da4b --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Input.java @@ -0,0 +1,44 @@ +/** @file +This file is used to nest elements which is meant for file path + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +/** + Input class is defined to be as nested elements of other elements, to specify + the path of file(s) + **/ +public class Input { + private String filePath; + + public Input() { + + } + + /** + Standard set method of ANT task, for "file" attribute + + @param path The path of a file + **/ + public void setFile(String path) { + filePath = path; + } + + /** + Standard get method of ANT task, for "file" attribute + + @returns The path of current specified file. + **/ + public String getFile() { + return filePath; + } +} diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/InputFile.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/InputFile.java new file mode 100644 index 0000000000..b08a38007b --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/InputFile.java @@ -0,0 +1,95 @@ +/** @file +This file is used to nest elements which is meant for specifying files + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +public class InputFile implements NestElement { + /** + InputFile nested element Class + class member + -name : name of input file + -file : name of file including input files + **/ + private String name = ""; + private File file; + private List nameList = new ArrayList(); + + /** + get class member "name" + @returns name parameter + **/ + public String getName() { + return this.name; + } + + /** + set class member "name" + @param name name of input file + **/ + public void setName(String name) { + this.name = " " + name; + } + + public String toString() { + return getName(); + } + + /** + get class member "file" + @returns file parameter + **/ + public File getFile() { + return this.file; + } + + /** + set class member "file" + @param ext name of file including input files + **/ + public void setFile(File file) { + this.file = file; + } + + /** + set class member "list" + + @param fileNameList name list of include paths, sperated by space, tab, + comma or semi-comma + **/ + public void setList(String fileNameList) { + if (fileNameList != null && fileNameList.length() > 0) { + StringTokenizer tokens = new StringTokenizer(fileNameList, " \t,;", false); + while (tokens.hasMoreTokens()) { + String fileName = tokens.nextToken().trim(); + if (fileName.length() > 0) { + this.nameList.add(fileName); + } + } + } + } + + /** + get class member "list" + + @returns The include paths list. + **/ + public List getList() { + return nameList; + } +} + diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java new file mode 100644 index 0000000000..a90d36225d --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/MakeDeps.java @@ -0,0 +1,443 @@ +/** @file +This file is to wrap MakeDeps.exe tool as ANT task, which is used to generate +dependency files for source code. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.types.Path; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.LineNumberReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.StringTokenizer; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + Class MakeDeps is used to wrap MakeDeps.exe as an ANT task. + **/ +public class MakeDeps extends Task { + + // + // private members, use set/get to access them + // + private static final String cmdName = "MakeDeps"; + private static final String target = "dummy"; + private String includePath = null; + private String depsFile = null; + private String subDir = null; + private boolean quietMode = true; + private boolean ignoreError = true; + private String extraDeps = ""; + private List includePathList = new ArrayList(); + private List inputFileList = new ArrayList(); + + public MakeDeps() { + + } + + /** + The Standard execute method for ANT task. It will check if it's necessary + to generate the dependency list file. If no file is found or the dependency + is changed, it will compose the command line and call MakeDeps.exe to + generate the dependency list file. + + @throws BuildException + **/ + public void execute() throws BuildException { + /// + /// check if the dependency list file is uptodate or not + /// + if (isUptodate()) { + return; + } + + Project prj = this.getOwningTarget().getProject(); + String toolPath = prj.getProperty("env.Framework_Tools_Path"); + /// + /// compose full tool path + /// + if (toolPath == null || toolPath.length() == 0) { + toolPath = "./" + cmdName; + } else { + if (toolPath.endsWith("/") || toolPath.endsWith("\\")) { + toolPath = toolPath + cmdName; + } else { + toolPath = toolPath + "/" + cmdName; + } + } + + /// + /// compose tool arguments + /// + StringBuffer args = new StringBuffer(4096); + if (ignoreError) { + args.append(" -ignorenotfound"); + } + if (quietMode) { + args.append(" -q"); + } + if (subDir != null && subDir.length() > 0) { + args.append(" -s "); + args.append(subDir); + } + + /// + /// if there's no source files, we can do nothing about dependency + /// + if (inputFileList.size() == 0) { + throw new BuildException("No source files specified to scan"); + } + + /// + /// compose source file arguments + /// + Iterator iterator = inputFileList.iterator(); + while (iterator.hasNext()) { + Input inputFile = (Input)iterator.next(); + args.append(" -f "); + args.append(cleanupPathName(inputFile.getFile())); + } + + /// + /// compose search pathes argument + /// + StringBuffer includePathArg = new StringBuffer(4096); + if (includePath != null && includePath.length() > 0) { + StringTokenizer pathTokens = new StringTokenizer(includePath, ";"); + while (pathTokens.hasMoreTokens()) { + String tmpPath = pathTokens.nextToken().trim(); + if (tmpPath.length() == 0) { + continue; + } + + includePathArg.append(" -i "); + includePathArg.append(cleanupPathName(tmpPath)); + } + } + iterator = includePathList.iterator(); + while (iterator.hasNext()) { + IncludePath path = (IncludePath)iterator.next(); + includePathArg.append(cleanupPathName(path.getPath())); + } + args.append(includePathArg); + + /// + /// We don't need a real target. So just a "dummy" is given + /// + args.append(" -target dummy"); + args.append(" -o "); + args.append(cleanupPathName(depsFile)); + + /// + /// prepare to execute the tool + /// + Commandline cmd = new Commandline(); + cmd.setExecutable(toolPath); + cmd.createArgument().setLine(args.toString()); + + LogStreamHandler streamHandler = new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_WARN); + Execute runner = new Execute(streamHandler, null); + + runner.setAntRun(prj); + runner.setCommandline(cmd.getCommandline()); + + int result = 0; + try { + result = runner.execute(); + } catch (IOException e) { + throw new BuildException(e.getMessage()); + } + + if (result != 0) { + log ("MakeDeps failed"); + return; + } + + // change the old DEP file format (makefile compatible) to just file list + if (!cleanup()) { + throw new BuildException(depsFile + " was not generated"); + } + } + + /// + /// Remove any duplicated path separator or inconsistent path separator + /// + private String cleanupPathName(String path) { + String separator = "\\" + File.separator; + String duplicateSeparator = separator + "{2}"; + path = Path.translateFile(path); + path = path.replaceAll(duplicateSeparator, separator); + + return path; + } + + /** + Set method for "DepsFile" attribute + + @param name The name of dependency list file + **/ + public void setDepsFile(String name) { + depsFile = cleanupPathName(name); + } + + /** + Get method for "DepsFile" attribute + + @returns The name of dependency list file + **/ + public String getDepsFile() { + return depsFile; + } + + /** + Set method for "IgnoreError" attribute + + @param ignore flag to control error handling (true/false) + **/ + public void setIgnoreError(boolean ignore) { + ignoreError = ignore; + } + + /** + Get method for "IgnoreError" attribute + + @returns The value of current IgnoreError flag + **/ + public boolean getIgnoreError() { + return ignoreError; + } + + /** + Set method for "QuietMode" attribute + + @param quiet flag to control the output information (true/false) + **/ + public void setQuietMode(boolean quiet) { + quietMode = quiet; + } + + /** + Get method for "QuietMode" attribute + + @returns value of current QuietMode flag + **/ + public boolean getQuietMode() { + return quietMode; + } + + /** + Set method for "SubDir" attribute + + @param dir The name of sub-directory in which source files will be scanned + **/ + public void setSubDir(String dir) { + subDir = dir; + } + + /** + Get method for "SubDir" attribute + + @returns The name of sub-directory + **/ + public String getSubDir() { + return subDir; + } + + /** + Set method for "IncludePath" attribute + + @param path The name of include path + **/ + public void setIncludePath(String path) { + includePath = cleanupPathName(path); + } + + /** + Get method for "IncludePath" attribute + + @returns The name of include path + **/ + public String getIncludePath() { + return includePath; + } + + /** + Set method for "ExtraDeps" attribute + + @param deps The name of dependency file specified separately + **/ + public void setExtraDeps(String deps) { + extraDeps = deps; + } + + /** + Get method for "ExtraDeps" attribute + + @returns The name of dependency file specified separately + **/ + public String getExtraDeps () { + return extraDeps; + } + + /** + Add method for "IncludePath" nested element + + @param path The IncludePath object from nested IncludePath type of element + **/ + public void addIncludepath(IncludePath path) { + includePathList.add(path); + } + + /** + Add method for "Input" nested element + + @param input The Input object from nested Input type of element + **/ + public void addInput(Input inputFile) { + inputFileList.add(inputFile); + } + + /** + The original file generated by MakeDeps.exe is for makefile uses. The target + part (before :) is not useful for ANT. This method will do the removal. + + @returns true if cleaned files is saved successfully + @returns false if error occurs in file I/O system + **/ + private boolean cleanup() { + File df = new File(depsFile); + + if (!df.exists()) { + return false; + } + + LineNumberReader lineReader = null; + FileReader fileReader = null; + try { + fileReader = new FileReader(df); + lineReader = new LineNumberReader(fileReader); + + /// + /// clean-up each line in deps file + // + String line = null; + StringBuffer cleanedLines = new StringBuffer(4096); + while ((line = lineReader.readLine()) != null) { + Pattern pattern = Pattern.compile(target + "[ ]*:[ ]*(.+)"); + Matcher matcher = pattern.matcher(line); + + while (matcher.find()) { + /// + /// keep the file name after ":" + /// + String filePath = line.substring(matcher.start(1), matcher.end(1)); + filePath = cleanupPathName(filePath); + cleanedLines.append(filePath); + cleanedLines.append("\n"); + } + } + lineReader.close(); + fileReader.close(); + + /// + /// we may have explicitly specified dependency files + /// + StringTokenizer fileTokens = new StringTokenizer(extraDeps, ";"); + while (fileTokens.hasMoreTokens()) { + cleanedLines.append(cleanupPathName(fileTokens.nextToken())); + cleanedLines.append("\n"); + } + + /// + /// overwrite old dep file with new content + /// + FileWriter fileWriter = null; + fileWriter = new FileWriter(df); + fileWriter.write(cleanedLines.toString()); + fileWriter.close(); + } catch (IOException e) { + log (e.getMessage()); + } + + return true; + } + + /** + Check if the dependency list file should be (re-)generated or not. + + @returns true The dependency list file is uptodate. No re-generation is needed. + @returns false The dependency list file is outofdate. Re-generation is needed. + **/ + private boolean isUptodate() { + File df = new File(depsFile); + if (!df.exists()) { + return false; + } + + /// + /// If the source file(s) is newer than dependency list file, we need to + /// re-generate the dependency list file + /// + long depsFileTimeStamp = df.lastModified(); + Iterator iterator = inputFileList.iterator(); + while (iterator.hasNext()) { + Input inputFile = (Input)iterator.next(); + File sf = new File(inputFile.getFile()); + if (sf.lastModified() > depsFileTimeStamp) { + return false; + } + } + + /// + /// If the source files haven't been changed since last time the dependency + /// list file was generated, we need to check each file in the file list to + /// see if any of them is changed or not. If anyone of them is newer than + /// the dependency list file, MakeDeps.exe is needed to run again. + /// + LineNumberReader lineReader = null; + FileReader fileReader = null; + boolean ret = true; + try { + fileReader = new FileReader(df); + lineReader = new LineNumberReader(fileReader); + + String line = null; + while ((line = lineReader.readLine()) != null) { + File sourceFile = new File(line); + if (sourceFile.lastModified() > depsFileTimeStamp) { + ret = false; + break; + } + } + lineReader.close(); + fileReader.close(); + } catch (IOException e) { + log (e.getMessage()); + } + + return ret; + } +} + diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java new file mode 100644 index 0000000000..f64fa7cab9 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/NestElement.java @@ -0,0 +1,40 @@ +/** @file +This file is to define common interfaces for nested element of frameworktasks + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +import java.io.File; +import java.util.List; + +/** + Interface NestElement is just to define common interfaces for nested element + **/ +public interface NestElement { + /** + nested element Interface for up-casting + **/ + + public String getName(); + + public void setName(String name); + + public String toString(); + + public File getFile(); + + public void setFile(File file); + + public void setList(String fileNameList); + + public List getList(); +} diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/SectFile.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/SectFile.java new file mode 100644 index 0000000000..35576478d1 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/SectFile.java @@ -0,0 +1,108 @@ +/** @file +This file is to define nested element which is meant for specifying section file + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import org.apache.tools.ant.BuildException; + +/** + Class SectFile is to define a class corresponding to ANT nested element. It's + used to specify section file(s) when used with GenFfsFile task + **/ +public class SectFile implements Section { + private String fileName = ""; /// section file name + + /** + Get method of ANT task/datatype for "FileName" attribute + + @returns The name of section file + **/ + public String getFileName() { + return fileName; + } + + /** + Set method of ANT task/datatype for "FileName" attribute + + @param fileName The name of section file + **/ + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public SectFile (){ + } + + /** + Put the content of section file into specified buffer with extra bytes for + alignment requirement. + + @param Buffer buffer to contain the section file content with alignment + **/ + public void toBuffer (DataOutputStream Buffer){ + File sectFile; + byte data; + long fileLen; + + /// + /// open file + /// + sectFile = new File (this.fileName); + + /// + /// check if file exist. + /// + if (! sectFile.exists()) { + throw new BuildException("The file " + this.fileName + " is not exist!\n"); + } + + + /// + /// Read section file and add it's contains to buffer. + /// + try { + + FileInputStream fs = new FileInputStream (sectFile.getAbsoluteFile()); + DataInputStream In = new DataInputStream (fs); + fileLen = sectFile.length(); + + int i = 0; + while (i < fileLen) { + data = In.readByte(); + Buffer.writeByte(data); + i++; + } + + /// + /// 4 byte alignment + /// + while ((fileLen & 0x03)!= 0) { + fileLen ++; + Buffer.writeByte(0); + } + + /// + /// close inputStream + /// + In.close(); + + } catch (Exception e) { + System.out.print(e.getMessage()); + throw new BuildException("section file2Buffer failed!\n"); + } + } +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Section.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Section.java new file mode 100644 index 0000000000..3f56eaf0a5 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Section.java @@ -0,0 +1,23 @@ +/** @file +This file is to define interface for manipulating section file + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +import java.io.DataOutputStream; + +/** + Section interface is for geting the contain buffer form compress, tool, and sectFile + **/ +public interface Section { + public void toBuffer (DataOutputStream Buffer); +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/SetStampTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/SetStampTask.java new file mode 100644 index 0000000000..b3dbfb0b6a --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/SetStampTask.java @@ -0,0 +1,136 @@ +/** @file +This file is to define an ANT task to wrap setstamp.exe tool + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; + +/** + Class SetStampTask is a wrap class for setstamp.exe. + **/ +public class SetStampTask extends Task implements EfiDefine { + /** + SetStamp Task Class + class member + -peFile : file of PE + -timeFile: Txt file of time + **/ + + private String peFile = ""; + + private String timeFile = ""; + + /** + assemble tool command line & execute tool command line + + @throws BuildException + **/ + public void execute() throws BuildException { + + Project project = this.getOwningTarget().getProject(); + /// + /// absolute path of edk tools + /// + String path = project.getProperty("env.Framework_Tools_Path"); + String command; + if (path == null) { + command = "setstamp"; + } else { + command = path + "/" + "setstamp"; + } + /// + /// argument of SetStamp tool + /// + String argument = peFile + timeFile; + /// + /// reture value of SetStamp execution + /// + int returnVal = -1; + + try { + Commandline commandLine = new Commandline(); + commandLine.setExecutable(command); + commandLine.createArgument().setLine(argument); + + LogStreamHandler streamHandler = new LogStreamHandler(this, + Project.MSG_INFO, Project.MSG_WARN); + + Execute runner = new Execute(streamHandler, null); + runner.setAntRun(project); + runner.setCommandline(commandLine.getCommandline()); + + System.out.println(Commandline.toString(commandLine + .getCommandline())); + + returnVal = runner.execute(); + if (EFI_SUCCESS == returnVal) { + /// + /// command execution success + /// + System.out.println("SetStamp execute successed!"); + } else { + /// + /// command execution fail + /// + System.out.println("SetStamp failed. (error=" + + Integer.toHexString(returnVal) + ")"); + throw new BuildException("SetStamp failed. (error=" + + Integer.toHexString(returnVal) + ")"); + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } + + /** + set operation of class member "peFile" + + @param peFile name of PE File + **/ + public void setPeFile(String peFile) { + this.peFile = " " + peFile; + } + + /** + get operation of class member "peFile" + + @return peFile name of PE file + **/ + public String getPeFile() { + return this.peFile; + } + + /** + set operation of class member "timeFile" + + @param timeFile name of time file + **/ + public void setTimeFile(String timeFile) { + this.timeFile = " " + timeFile; + } + + /** + get class member "timeFile" + + @returns name of time file + **/ + public String getTimeFile() { + return this.timeFile; + } + +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/SkipExt.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/SkipExt.java new file mode 100644 index 0000000000..d766ed2c58 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/SkipExt.java @@ -0,0 +1,83 @@ +/** @file +This file is to define nested element which is meant for specifying skipped file list + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; +import java.util.StringTokenizer; + +/** + SkipExt nested element Class + class member + -name : extension name of skiped file + -file : name of file including ext + **/ +public class SkipExt implements NestElement { + private String name = ""; + private File file; + private List nameList = new ArrayList(); + + /** + get class member "name" + @returns name parameter + **/ + public String getName() { + return this.name; + } + /** + set class member "name" + @param name extension name of skiped file + **/ + public void setName(String name) { + this.name = " -skipext " + name; + } + + public String toString() { + return getName(); + } + + /** + get class member "file" + @returns file parameter + **/ + public File getFile() { + return this.file; + } + /** + set class member "file" + @param name of file including ext + **/ + public void setFile(File file) { + this.file = file; + } + + public void setList(String fileNameList) { + if (fileNameList != null && fileNameList.length() > 0) { + StringTokenizer tokens = new StringTokenizer(fileNameList, " \t,;", false); + while (tokens.hasMoreTokens()) { + String fileName = tokens.nextToken().trim(); + if (fileName.length() > 0) { + this.nameList.add(fileName); + } + } + } + } + + public List getList() { + return nameList; + } + +} + diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/StrGatherTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/StrGatherTask.java new file mode 100644 index 0000000000..670f6838f2 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/StrGatherTask.java @@ -0,0 +1,527 @@ +/** @file +This file is to define an ANT task which wraps StrGather.exe tool. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +import java.util.*; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; + +/** + StrGather Task Class + class memberg + -commandType : command type [parse/scan/dump] + -baseName : base name of component + -verbose : level of verbose [all/read/write] + -outputDatabase : file name of output database file + -databaseList : file name list of database files + -inputFileList : file name list of input files + -newDatabase : whether to need new database [ture/false] + -unquotedString : whether to unquoted strings are used [ture/false] + -includePathList: path list of include paths + -ignoreNotFound : whether to ignore a given STRING_TOKEN(STR) is not found in database [ture/false] + -skipExtList : skip scan of files with extension name + -outputString : write string data to filename + -outputDefines : write string defines to filename + -outputUnicode : dump database to unicode file filename + -lang : only dump for the language + -indirectionFile: specify an indirection file + -outputHpk : create an HII export pack of the strings + **/ +public class StrGatherTask extends Task implements EfiDefine { + /// + /// common options + /// + private String commandType = ""; + + private String baseName = ""; + + /// + /// "all/read/write" + /// + private String verbose = ""; + + private String outputDatabase = ""; + + private List databaseList = new ArrayList(); + + private List inputFileList = new ArrayList(); + + /// + /// parse options newDatabase -- "ture/false" unquoteString -- "ture/false" + /// + private String newDatabase = ""; + + private String unquotedString = ""; + + private List includePathList = new ArrayList(); + + /// + /// scan options ignoreNotFound -- "ture/false" + /// + private String ignoreNotFound = ""; + + private List skipExtList = new ArrayList(); + + /// + /// dump options + /// + private String outputString = ""; + + private String outputDefines = ""; + + private String outputUnicode = ""; + + private String lang = ""; + + private String indirectionFile = ""; + + private String outputHpk = ""; + + /// + /// global variable + /// + static private Project project; + + /** + assemble tool command line & execute tool command line + + @throws BuildException + **/ + public void execute() throws BuildException { + + project = this.getOwningTarget().getProject(); + /// + /// absolute path of efi tools + /// + String path = project.getProperty("env.Framework_Tools_Path"); + String command; + if (path == null) { + command = "strgather"; + } else { + command = path + "/" + "strgather"; + } + + /// + /// transfer nested elements into string + /// + String databases = list2Str(databaseList, "-db"); + String skipExts = list2Str(skipExtList, "-skipext"); + String includePaths = list2Str(includePathList, "-I"); + String inputFiles = list2Str(inputFileList, ""); + + /// + /// assemble argument + /// + String argument = commandType + verbose + databases + baseName + + outputDatabase + includePaths + newDatabase + unquotedString + + skipExts + ignoreNotFound + outputString + outputDefines + + outputUnicode + lang + indirectionFile + outputHpk + + inputFiles; + /// + /// return value of fwimage execution + /// + int revl = -1; + + try { + Commandline cmdline = new Commandline(); + cmdline.setExecutable(command); + cmdline.createArgument().setLine(argument); + + LogStreamHandler streamHandler = new LogStreamHandler(this, + Project.MSG_INFO, Project.MSG_WARN); + Execute runner = new Execute(streamHandler, null); + + runner.setAntRun(project); + runner.setCommandline(cmdline.getCommandline()); + System.out.println(Commandline.toString(cmdline.getCommandline())); + + revl = runner.execute(); + if (EFI_SUCCESS == revl) { + /// + /// command execution success + /// + System.out.println("strgather succeeded!"); + } else { + /// + /// command execution fail + /// + System.out.println("strgather failed. (error=" + + Integer.toHexString(revl) + ")"); + throw new BuildException("strgather failed. (error=" + + Integer.toHexString(revl) + ")"); + } + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } + + /** + get class member "commandType" + + @returns commandType parameter + **/ + public String getCommandType() { + return this.commandType; + } + + /** + set class member "" + + @param commandType type of strgather command [parse/scan/dump] + **/ + public void setCommandType(String commandType) { + this.commandType = " -" + commandType; + } + + /** + get class member "verbose" + + @returns verbose parameter + **/ + public String getVerbose() { + return this.verbose; + } + + /** + set class member "verbose" + + @param verbose verbose level [all/read/write] + **/ + public void setVerbose(String verbose) { + if (verbose.equals("all")) { + /// + /// for verbose output + /// + this.verbose = " -v "; + } else if (verbose.equals("read")) { + /// + /// for verbose output when reading database + /// + this.verbose = " -vdbr "; + } else if (verbose.equals("write")) { + /// + /// for verbose output when writing database + /// + this.verbose = " -vdbw "; + } + } + + /** + get class member baseName + + @returns baseName parameter + **/ + public String getBaseName() { + return this.baseName; + } + + /** + set class member baseName + + @param baseName name of the output files of .c and .h + **/ + public void setBaseName(String baseName) { + this.baseName = " -bn " + baseName; + } + + /** + get class member "outputDatabase" + + @returns outputDatabase parameter + **/ + public String getOutputDatabase() { + return this.outputDatabase; + } + + /** + set class member "outputDatabase" + + @param outputDatabase filename of output database file + **/ + public void setOutputDatabase(String outputDatabase) { + this.outputDatabase = " -od " + outputDatabase; + } + + /** + get class member "newDatabase" + + @returns newDatabase parameter + **/ + public String getNewDatabse() { + return this.newDatabase; + } + + /** + set class member "newDatabase" + + @param newDatabase whether to not read in existing database file + **/ + public void setNewDatabase(String newDatabase) { + if (newDatabase.equals("true")) { + this.newDatabase = " -newdb "; + } + } + + /** + get class member "unquotedString" + + @returns unquotedString parameter + **/ + public String getUnquotedString() { + return this.unquotedString; + } + + /** + set class member "unquotedString" + + @param unquotedString : + whether to indicate that unquoted strings are used + **/ + public void setUnquotedString(String unquotedString) { + if (unquotedString.equals("true")) { + this.unquotedString = " -uqs "; + } + } + + /** + get class member "ignoreNotFound" + + @returns ignoreNotFound parameter + **/ + public String getIgnoreNotFound() { + return this.ignoreNotFound; + } + + /** + set class member "ignoreNotFound" + + @param ignoreNotFound whether to ignore if a given STRING_TOKEN(STR) + is not found in the database + **/ + public void setIgnoreNotFound(String ignoreNotFound) { + if (ignoreNotFound.equals("true")) { + this.ignoreNotFound = " -ignorenotfound "; + } + } + + /** + get class member "outputString" + + @returns outputString parameter + **/ + public String getOutputString() { + return this.outputString; + } + + /** + set class member "outputString" + + @param outputString filename of string data file + **/ + public void setOutputString(String outputString) { + this.outputString = " -oc " + outputString; + } + + /** + get class member "outputDefines" + + @returns outputDefines parameter + **/ + public String getOutputDefines() { + return this.outputDefines; + } + + /** + set class member "outputDefines" + + @param outputDefines filename of string defines file + **/ + public void setOutputDefines(String outputDefines) { + this.outputDefines = " -oh " + outputDefines; + } + + /** + get class member "outputUnicode" + + @returns outputUnicode parameter + **/ + public String getOutputUnicode() { + return this.outputUnicode; + } + + /** + set class member "outputUnicode" + + @param outputUnicode filename of unicode file to be dumped database + **/ + public void setOutputUnicode(String outputUnicode) { + this.outputUnicode = " -ou " + outputUnicode; + } + + /** + get class member "lang" + + @returns lang parameter + **/ + public String getLang() { + return this.lang; + } + + /** + set class member "lang" + + @param lang language of dump + **/ + public void setLang(String lang) { + this.lang = " -lang " + lang; + } + + /** + get class member "indirectionFile" + + @returns indirectionFile parameter + **/ + public String getIndirectionFile() { + return this.indirectionFile; + } + + /** + set class member "indirectionFile" + + @param indirectionFile filename of indirection file + **/ + public void setIndirectionFile(String indirectionFile) { + this.indirectionFile = " -if " + indirectionFile; + } + + /** + get class member "outputHpk" + + @returns outputHpk parameter + **/ + public String getOutputHpk() { + return this.outputHpk; + } + + /** + set class member "outputHpk" + + @param outputHpk filename of output HII export pack of the strings + **/ + public void setOutputHpk(String outputHpk) { + this.outputHpk = " -hpk " + outputHpk; + } + + /** + add a skipExt element into list + + @param skipExt skipExt element + **/ + public void addSkipext(SkipExt skipExt) { + skipExtList.add(skipExt); + }; + + /** + add a includePath element into list + + @param includePath includePath element + **/ + public void addIncludepath(IncludePath includePath) { + includePathList.add(includePath); + }; + + /** + add a inputFile element into list + + @param inputFile inputFile element + **/ + public void addInputfile(InputFile inputFile) { + inputFileList.add(inputFile); + }; + + /** + add a database element into list + + @param database : + database element + **/ + public void addDatabase(Database database) { + databaseList.add(database); + } + + /** + transfer List to String + + @param list nested element list + @param tag interval tag of parameter + + @returns string line of parameters + **/ + private String list2Str(List list, String tag) { + /// + /// string line for return + /// + String paraStr = ""; + /// + /// nested element in list + /// + NestElement element; + /// + /// iterator of nested element list + /// + Iterator elementIter = list.iterator(); + /// + /// string parameter list + /// + List strList = new ArrayList(); + + while (elementIter.hasNext()) { + element = (NestElement) elementIter.next(); + if (null != element.getFile()) { + /// + /// nested element include file + /// + FileParser.loadFile(project, strList, element.getFile(), tag); + } + + if (element.getName().length() > 0) { + /// + /// nested element include name + /// + paraStr = paraStr + " " + element.getName(); + } + + List nameList = element.getList(); + if (nameList.size() > 0) { + Iterator nameIter = nameList.iterator(); + while (nameIter.hasNext()) { + paraStr = paraStr + " " + tag + " " + (String)nameIter.next(); + } + } + } + /// + /// iterator of string parameter list + /// + Iterator strIter = strList.iterator(); + while (strIter.hasNext()) { + paraStr = paraStr + " " + strIter.next(); + } + return paraStr; + } + +} diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Tool.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Tool.java new file mode 100644 index 0000000000..36b095a6e7 --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/Tool.java @@ -0,0 +1,194 @@ +/** @file +This file is to define nested element which is meant for specifying a tool + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.apache.tools.ant.BuildException; + +/** + Class Tool is to define an external tool to be used for genffsfile + **/ +public class Tool implements EfiDefine, Section { + + String toolName = ""; + List toolArgList = new ArrayList(); + String outputPath; + String outPutFileName ; + List inputFiles = new ArrayList(); + + /** + Call extern tool + + @param buffer The buffer to put the result with alignment + **/ + public void toBuffer (DataOutputStream buffer){ + File OutputFile; + byte data; + + /// + /// call extern tool + /// + try { + executeTool (); + } catch (Exception e) { + throw new BuildException("Call tools failed!\n"); + } + + /// + /// check if file exist + /// + OutputFile = new File (this.outPutFileName); + long fileLen = OutputFile.length(); + if (!OutputFile.exists()) { + throw new BuildException("The file " + outPutFileName + " is not exist!\n"); + } + + /// + /// Read output file and write it's cotains to buffer + /// + try { + FileInputStream fs = new FileInputStream (this.outPutFileName); + DataInputStream In = new DataInputStream (fs); + + int i = 0; + while (i < fileLen) { + data = In.readByte(); + buffer.writeByte(data); + i ++; + } + + /// + /// 4 byte alignment + /// + while ((fileLen & 0x03) != 0) { + fileLen++; + buffer.writeByte(0); + } + In.close(); + + } catch (Exception e) { + System.out.print(e.getMessage()); + throw new BuildException("Call tool2buffer failed!\n"); + } + } + + /// + /// execute external tool for genffsfile + /// + private void executeTool () { + String command = ""; + String argument = ""; + command = toolName; + Iterator argIter = toolArgList.iterator(); + Iterator inputIter = inputFiles.iterator(); + ToolArg toolArg; + Input file = null; + + /// + /// argument of tools + /// + while (argIter.hasNext()) { + toolArg = (ToolArg)argIter.next(); + argument = argument + toolArg.getLine() + " "; + + } + + /// + /// input files for tools + /// + argument = argument + "-i "; + while (inputIter.hasNext()) { + file = (Input)inputIter.next(); + argument = argument + file.getFile() + " "; + } + + outPutFileName = outputPath + File.separatorChar + (new File(file.getFile())).getName() + ".crc"; + argument = argument + " -o " + outPutFileName; + + try { + + /// + /// execute command line + /// + Process crcProcess = Runtime.getRuntime().exec(command + " " + argument); + crcProcess.waitFor(); + } catch (Exception e) { + System.out.print (e.getMessage()); + throw new BuildException("Execute tools fails!\n"); + } + } + + /** + Add method of ANT task/datatype for nested ToolArg type of element + + @param toolArg The ToolArg object containing arguments for the tool + **/ + public void addToolArg (ToolArg toolArg) { + toolArgList.add (toolArg); + } + + /** + Get method of ANT task/datatype for attribute "OutputPath" + + @returns The name of output path + **/ + public String getOutputPath() { + return outputPath; + } + + /** + Set method of ANT task/datatype for attribute "OutputPath" + + @param outputPath The name of output path + **/ + public void setOutputPath(String outPutPath) { + this.outputPath = outPutPath; + } + + /** + Get method of ANT task/datatype for attribute "ToolName" + + @returns The name of the tool. + **/ + public String getToolName() { + return toolName; + } + + /** + Set method of ANT task/datatype for attribute "ToolName" + + @param toolName The name of the tool + **/ + public void setToolName(String toolName) { + this.toolName = toolName; + } + + /** + Add method of ANT task/datatype for nested Input type of element + + @param file The Input objec which represents a file + **/ + public void addInput(Input file) { + inputFiles.add(file); + } +} + + diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/ToolArg.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/ToolArg.java new file mode 100644 index 0000000000..b5fbdfe81e --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/ToolArg.java @@ -0,0 +1,42 @@ +/** @file +This file is to define nested element which is meant for specifying tool arguments + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +/** + Class ToolArg is just used to specify arguments for genffsfile tool + **/ +public class ToolArg { + /// + /// keep the argument string + /// + private String line = ""; + + /** + Get method of ANT task/datatype for attribute "line" + + @returns The argument string + **/ + public String getLine() { + return line; + } + + /** + Set method of ANT task/datatype for attribute "line" + + @param line The argument string + **/ + public void setLine(String line) { + this.line = line; + } +} \ No newline at end of file diff --git a/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/VfrCompilerTask.java b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/VfrCompilerTask.java new file mode 100644 index 0000000000..dbd796e01e --- /dev/null +++ b/Tools/Source/FrameworkTasks/org/tianocore/framework/tasks/VfrCompilerTask.java @@ -0,0 +1,221 @@ +/** @file +This file is to define an ANT task which wraps VfrCompile.exe tool + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.framework.tasks; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogStreamHandler; +import org.apache.tools.ant.types.Commandline; + +/** + VfrcompilerTask Task Class + class member + -createListFile : create an output IFR listing file. + -outPutDir : deposit all output files to directory OutputDir (default=cwd) + -createIfrBinFile: create an IFR HII pack file + -vfrFile : name of the input VFR script file + -processArg : c processer argument + -includepathList : add IncPath to the search path for VFR included files + **/ +public class VfrCompilerTask extends Task implements EfiDefine { + private String createListFile = ""; + private String outPutDir = ""; + private String createIfrBinFile = ""; + private String processerArg =""; + private String vfrFile; + + private List includepathList = new ArrayList(); + + /** + get class member of createList file + + @returns file name of createList + **/ + public String getCreateListFile() { + return createListFile; + } + + /** + set class member of createList file + + @param createListFile if createList string equal "on" set '-l' flag + **/ + public void setCreateListFile(String createListFile) { + if (createListFile.equals("ON")||createListFile.equals("on")) + this.createListFile = " -l"; + } + + /** + get output dir + + @returns name of output dir + **/ + public String getOutPutDir() { + return outPutDir; + } + + /** + set class member of outPutDir + + @param outPutDir The directory name for ouput file + **/ + public void setOutPutDir(String outPutDir) { + this.outPutDir = " -od " + outPutDir; + } + + + /** + get class member of ifrBinFile + + @return file name of ifrBinFile + **/ + public String getCreateIfrBinFile() { + return createIfrBinFile; + } + + /** + set class member of ifrBinFile + + @param createIfrBinFile The flag to specify if the IFR binary file should + be generated or not + */ + public void setCreateIfrBinFile(String createIfrBinFile) { + if (createIfrBinFile.equals("ON") || createIfrBinFile.equals("on")); + this.createIfrBinFile = " -ibin"; + } + + /** + get class member of vfrFile + + @returns name of vfrFile + **/ + public String getVfrFile() { + return vfrFile; + } + + /** + set class member of vfrFile + + @param vfrFile The name of VFR file + **/ + public void setVfrFile(String vfrFile) { + this.vfrFile = " " + vfrFile; + } + + /** + add includePath in includepath List + + @param includepath The IncludePath object which represents include path + **/ + public void addIncludepath(IncludePath includepath){ + includepathList.add(includepath); + } + + + /** + get class member of processerArg + + @returns processer argument + **/ + public String getProcesserArg() { + return processerArg; + } + + + /** + set class member of processerArg + + @param processerArg The processor argument + */ + public void setProcesserArg(String processerArg) { + this.processerArg = " -ppflag " + processerArg; + } + + /** + The standard execute method of ANT task. + **/ + public void execute() throws BuildException { + Project project = this.getProject(); + String toolPath= project.getProperty("env.Framework_Tools_Path"); + String command; + if (toolPath == null) { + command = "VfrCompile"; + } else { + command = toolPath + "/" + "VfrCompile"; + } + List includePath = new ArrayList(); + String incPath = ""; + + int count = includepathList.size(); + IncludePath path; + for (int i = 0; i < count; i++) { + path = (IncludePath) includepathList.get(i); + if (path.getFile() != null) { + FileParser.loadFile( project,includePath,path.getFile(), "-I"); + } + } + for (int i = 0; i < count; i++) { + incPath = incPath + " " + includepathList.get(i); + } + count = includePath.size(); + for (int i = 0; i < count; i++) { + incPath = incPath + " " + includePath.get(i); + } + String argument = this.createIfrBinFile + + this.processerArg + + incPath + + this.outPutDir + + this.createListFile + + this.vfrFile ; + try { + /// + /// constructs the command-line + /// + Commandline commandLine = new Commandline(); + commandLine.setExecutable(command); + commandLine.createArgument().setLine(argument); + + /// + /// configures the Execute object + /// + LogStreamHandler streamHandler = new LogStreamHandler(this, + Project.MSG_INFO, + Project.MSG_WARN); + + Execute runner = new Execute(streamHandler,null); + runner.setAntRun(project); + runner.setCommandline(commandLine.getCommandline()); + + System.out.println(Commandline.toString(commandLine.getCommandline())); + int returnVal = runner.execute(); + if (EFI_SUCCESS == returnVal) { + System.out.println("VfrCompiler execution succeeded!"); + } else { + System.out.println("VfrCompiler failed. (error=" + + Integer.toHexString(returnVal) + ")"); + throw new BuildException("VfrCompiler failed. (error=" + + Integer.toHexString(returnVal) + ")"); + } + + } catch (IOException e) { + throw new BuildException(e.getMessage()); + } + } +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/GenBuild.tasks b/Tools/Source/GenBuild/GenBuild.tasks new file mode 100644 index 0000000000..c767cfb1dd --- /dev/null +++ b/Tools/Source/GenBuild/GenBuild.tasks @@ -0,0 +1,11 @@ +FPDParser = org.tianocore.build.fpd.FpdParserTask +bl = org.tianocore.build.global.VariableTask +bf = org.tianocore.build.global.LibBuildFileGenerator +GenBuild = org.tianocore.build.GenBuildTask +ToolChainSetup = org.tianocore.build.toolchain.ToolChainTask +Expand = org.tianocore.build.ExpandTask +OutputDirSetup = org.tianocore.build.OutputDirSetupTask +OnDependency = org.tianocore.build.global.OnDependency +sourcefiles = org.tianocore.build.global.DpFileList +targetfiles = org.tianocore.build.global.DpFileList +file = org.tianocore.build.global.DpFile diff --git a/Tools/Source/GenBuild/build.xml b/Tools/Source/GenBuild/build.xml new file mode 100644 index 0000000000..38801f1495 --- /dev/null +++ b/Tools/Source/GenBuild/build.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/GenBuild/org/tianocore/build/ExpandTask.java b/Tools/Source/GenBuild/org/tianocore/build/ExpandTask.java new file mode 100644 index 0000000000..d3df8cf7a6 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/ExpandTask.java @@ -0,0 +1,52 @@ +/** @file + This file is ANT task Expand. + + Expand task is used to prepare ANT properties for further build. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +import org.tianocore.build.global.GlobalData; + +/** + Expand task is used to prepare ANT properties for further build. +

Current, prepare the dependent Library instance list for LIBS

+ + @since GenBuild 1.0 +**/ +public class ExpandTask extends Task { + + /** + Public construct method. It is necessary for ANT task. + **/ + public ExpandTask () { + } + + /** + ANT task's entry point, will be called after init(). + + Set LIBS for further build usage. + **/ + public void execute() throws BuildException { + + String[] libraries = GlobalData.getModuleLibrary(getProject().getProperty("BASE_NAME")); + String str = ""; + for (int i = 0; i < libraries.length; i ++){ + str += " " + GlobalData.getLibrary(libraries[i]); + } + getProject().setProperty("LIBS", str); + + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java b/Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java new file mode 100644 index 0000000000..dbbddba3db --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/FfsProcess.java @@ -0,0 +1,390 @@ +/** @file + File is FfsProcess class which is used to get the corresponding FFS layout + information for driver module. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.build; + +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStream; +import java.util.Vector; + +import javax.xml.namespace.QName; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** +

FfsProcess is a class to find the corresponding FFS layout.

+ +

Property COMMON_FILE specified which file to search. The element + in COMMON_FILE is like following:

+ +
+    <Ffs type="APPLICATION">
+      <Attribute Name="FFS_FILETYPE" Value="EFI_FV_FILETYPE_APPLICATION" />
+      <Attribute Name="FFS_ATTRIB_CHECKSUM" Value="TRUE" />
+      <Sections EncapsulationType="Compress">
+        <Sections EncapsulationType="Guid-Defined">
+          <Section SectionType="EFI_SECTION_PE32" /> 
+          <Section SectionType="EFI_SECTION_USER_INTERFACE" />
+          <Section SectionType="EFI_SECTION_VERSION" /> 
+        </Sections>
+      </Sections>
+    </Ffs>
+  
+ + @since GenBuild 1.0 +**/ +public class FfsProcess { + + /// + /// Xml Document Node for corresponding FFS layout + /// + private Node ffs; + + /// + /// ANT script to call GenFfs + /// + private Element ffsNode = null; + + /// + /// Module base name + /// + private String basename; + + /// + /// Sections type: normal + /// + private static int MODE_NONE = 0; + + /// + /// Sections type: compress + /// + private static int MODE_COMPRESS = 1; + + /// + /// Sections type: guid-define + /// + private static int MODE_GUID_DEFINED = 2; + + /// + /// mapping from section type to section output file extension + /// + public static final String[][] sectionExt = { { "EFI_SECTION_FREEFORM_SUBTYPE_GUID", ".sec" }, + { "EFI_SECTION_VERSION", ".ver" }, + { "EFI_SECTION_USER_INTERFACE", ".ui" }, + { "EFI_SECTION_DXE_DEPEX", ".dpx" }, + { "EFI_SECTION_PEI_DEPEX", ".dpx" }, + { "EFI_SECTION_PE32", ".pe32" }, + { "EFI_SECTION_PIC", ".pic" }, + { "EFI_SECTION_TE", ".tes" }, + { "EFI_SECTION_RAW", ".sec" }, + { "EFI_SECTION_COMPRESSION", ".sec" }, + { "EFI_SECTION_GUID_DEFINED", ".sec" }, + { "EFI_SECTION_COMPATIBILITY16", ".sec" }, + { "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", ".sec" } }; + + /** + search in the type, if componentType is listed in type, return true; + otherwise return false. + + @param type a list supported component type separated by comma + @param componentType current module component type + @return whether componentType is one of type + **/ + private boolean isMatch(String type, String componentType) { + String[] items = type.split("[ \t]*,[ \t]*"); + for (int i = 0; i < items.length; i++) { + if (items[i].equalsIgnoreCase(componentType)) { + return true; + } + } + return false; + } + + /** + Find the corresponding FFS layout in COMMON_FILE if it + does not specify in module's surface area. + + @param buildType Current module's component type + @param project Ant project + @return whether find the corresponding FFS layout + @throws BuildException + If specified COMMON_FILE XML file is not valide. + **/ + public boolean initSections(String buildType, Project project) throws BuildException { + // + // first try to sections defined in PLATFORM level + // + + // + // if module specify sections itself, it's okay + // otherwise find sections from WORKSPACE default setting with + // ComponentType + // + if (ffs == null) { + File file = new File(project.getProperty("COMMON_FILE")); + // + // if common file is not existed, just return + // + if (!file.exists()) { + return false; + } + DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder dombuilder = domfac.newDocumentBuilder(); + InputStream is = new FileInputStream(file); + Document doc = dombuilder.parse(is); + Element root = doc.getDocumentElement(); + NodeList items = root.getChildNodes(); + for (int i = 0; i < items.getLength(); i++) { + Node node = items.item(i); + if (node.getNodeType() == Node.ELEMENT_NODE) { + String nodeName = node.getNodeName(); + if (nodeName.equalsIgnoreCase("Ffs")) { + NamedNodeMap attr = node.getAttributes(); + Node type = attr.getNamedItem("type"); + if (type != null) { + if (isMatch(type.getTextContent(), buildType)) { + ffs = node; + return true; + } + } + } + } + } + } catch (Exception e) { + throw new BuildException("Parse COMMON_FILE [" + file.getPath() + "] error!\n" + e.getMessage()); + } + } + if (ffs == null) { + return false; + } else { + return true; + } + } + + /** + Recursive parse the FFS layout. Find out all section type here used. + + @param document BaseName_build.xml Xml document + @param basename Module's base name + @param guid Module's GUID + @param targetFilename Module's final file name (GUID-BaseName.APP) + @return List of section type + **/ + public String[] getGenSectionElements(Document document, String basename, String guid, String targetFilename) { + this.basename = basename; + if (ffs == null) { + return new String[0]; + } + Vector sectionList = new Vector(); + XmlCursor cursor = null; + try { + cursor = XmlObject.Factory.parse(ffs).newCursor(); + } catch (Exception e) { + return null; + } + int mode = MODE_NONE; + Element root = document.createElement("genffsfile"); + root.setAttribute("outputDir", "${BIN_DIR}"); + root.setAttribute("BaseName", basename); + root.setAttribute("fileGuid", guid); + cursor.toFirstChild(); + if (cursor.toFirstChild()) { + do { + if (cursor.getName().getLocalPart().equalsIgnoreCase("Attribute")) { + String name = cursor.getAttributeText(new QName("Name")); + String value = cursor.getAttributeText(new QName("Value")); + root.setAttribute(changeAttributeName(name), value); + } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) { + cursor.push(); + dealSection(mode, document, root, cursor, sectionList); + cursor.pop(); + } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) { + cursor.push(); + dealSections(mode, document, root, cursor, sectionList); + cursor.pop(); + } + } while (cursor.toNextSibling()); + } + // + // Check dependency + // + Element outofdateEle = document.createElement("OnDependency"); + Element sourceEle = document.createElement("sourcefiles"); + String[] result = new String[sectionList.size()]; + for (int i = 0; i < sectionList.size(); i++) { + result[i] = (String) sectionList.get(i); + Element pathEle = document.createElement("file"); + pathEle.setAttribute("name", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + + getSectionExt(result[i])); + sourceEle.appendChild(pathEle); + } + outofdateEle.appendChild(sourceEle); + Element targetEle = document.createElement("targetfiles"); + Element fileEle = document.createElement("file"); + fileEle.setAttribute("name", "${BIN_DIR}\\" + targetFilename); + targetEle.appendChild(fileEle); + outofdateEle.appendChild(targetEle); + Element sequentialEle = document.createElement("sequential"); + sequentialEle.appendChild(root); + outofdateEle.appendChild(sequentialEle); + ffsNode = outofdateEle; + return result; + } + + /** + Change the attribute name. For example: + +
+          Before change: FFS_ATTRIB_CHECKSUM 
+          After  change: ffsATTRIBCHECKSUM
+      
+ + @param name Original attribute name + @return Changed attribute name + **/ + private String changeAttributeName(String name) { + String[] strs = name.split("_"); + String str = strs[0].toLowerCase(); + for (int j = 1; j < strs.length; j++) { + str += strs[j]; + } + return str; + } + + /** + Recursively deal with Sections. If sections does not specify a type, then omit it. + + @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED) + @param doc Xml Document + @param root Root Node + @param cursor Current FFS layout cursor + @param list List of section type here used + **/ + private void dealSections(int mode, Document doc, Element root, XmlCursor cursor, Vector list) { + String type = cursor.getAttributeText(new QName("EncapsulationType")); + if (type == null) { + if (cursor.toFirstChild()) { + do { + if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) { + cursor.push(); + dealSection(mode, doc, root, cursor, list); + cursor.pop(); + } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) { + cursor.push(); + dealSections(mode, doc, root, cursor, list); + cursor.pop(); + } + } while (cursor.toNextSibling()); + } + return; + } + Element ele; + if (type.equalsIgnoreCase("COMPRESS")) { + mode = MODE_COMPRESS; + // + // + // + ele = doc.createElement("compress"); + ele.setAttribute("compressName", "dummy"); + } else { + mode = MODE_GUID_DEFINED; + // + // + // + ele = doc.createElement("tool"); + ele.setAttribute("toolName", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "Bin" + + File.separatorChar + "GenCRC32Section"); + ele.setAttribute("outputPath", "${DEST_DIR_OUTPUT}"); + } + if (cursor.toFirstChild()) { + do { + if (cursor.getName().getLocalPart().equalsIgnoreCase("Section")) { + cursor.push(); + dealSection(mode, doc, ele, cursor, list); + cursor.pop(); + } else if (cursor.getName().getLocalPart().equalsIgnoreCase("Sections")) { + cursor.push(); + dealSections(mode, doc, ele, cursor, list); + cursor.pop(); + } + } while (cursor.toNextSibling()); + } + root.appendChild(ele); + } + + /** + Recursively deal with section. + + @param mode Current node mode (MODE_NONE | MODE_COMPREE | MODE_GUID_DEFINED) + @param doc Xml Document + @param root Root Node + @param cursor Current FFS layout cursor + @param list List of section type here used + **/ + private void dealSection(int mode, Document doc, Element root, XmlCursor cursor, Vector list) { + String type = cursor.getAttributeText(new QName("SectionType")); + list.addElement(type); + if (mode == MODE_GUID_DEFINED) { + // + // + // + Element ele = doc.createElement("input"); + ele.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type)); + root.appendChild(ele); + } else { + // + // + // + Element ele = doc.createElement("sectFile"); + ele.setAttribute("fileName", "${DEST_DIR_OUTPUT}" + File.separatorChar + basename + getSectionExt(type)); + root.appendChild(ele); + } + } + + /** + Get the corresponding section file suffix. + + @param type Section type + @return Corresponding section file extension + **/ + private String getSectionExt(String type) { + for (int i = 0; i < sectionExt.length; i++) { + if (sectionExt[i][0].equalsIgnoreCase(type)) { + return sectionExt[i][1]; + } + } + return ".sec"; + } + + /** + Return the ANT script to call GenFfs Tool. + + @return ANT script to call GenFfs Tool + **/ + public Element getFfsNode() { + return ffsNode; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/FileProcess.java b/Tools/Source/GenBuild/org/tianocore/build/FileProcess.java new file mode 100644 index 0000000000..87650af827 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/FileProcess.java @@ -0,0 +1,225 @@ +/** @file + File is FileProcess class which is used to generate ANT script to build + source files. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.build; + +import java.io.File; +import java.util.Set; + +import org.apache.tools.ant.Project; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +/** +

FileProcess is class to generate ANT script to build source + files.

+ +

If file does not specify file type, FileProcess will judge + by its extension. Following is the current supported extensions.

+ +
   
+          .c         |      C_Code
+          .asm       |      Assembly
+          .s         |      IPF_Assembly_Code
+          .h         |      Header
+          .lib       |      Static_Library
+          .i         |      IPF_PP_Code
+          .vfr       |      Vfr
+          .uni       |      Unicode
+          .dxs       |      Dependency_File
+          .bmp       |      Graphics
+          .efi       |      EFI
+  
+ + @since GenBuild 1.0 +**/ +public class FileProcess { + /// + /// The mapping information about source suffix, result suffix, file type. + /// + public final String[][] fileTypes = { { ".c", ".obj", "C_Code" }, { ".asm", ".obj", "Assembly" }, + { ".s", ".obj", "IPF_Assembly_Code" }, { ".h", "", "Header" }, + { ".lib", "", "Static_Library" }, { ".src", ".c", "" }, + { ".i", ".obj", "IPF_PP_Code" }, { ".vfr", ".obj", "Vfr" }, + { ".uni", "", "Unicode" }, { ".dxs", "", "Dependency_File" }, + { ".bmp", "", "Graphics" }, { ".efi", "", "EFI" } }; + + /// + /// Current ANT context. + /// + private Project project; + + /// + /// Current module's include pathes + /// + private Set includes; + + /// + /// Current source files. + /// + private Set sourceFiles; + + /// + /// Xml Document. + /// + private Document document; + + /// + /// The flag to ensure all unicode files build before others. + /// + private boolean unicodeFirst = true; + + /// + /// The flag present whether current module contains Unicode files or not. + /// + private boolean unicodeExist = false; + + /** + Initialize the project, includes, sourceFiles, document members. + + @param project ANT project + @param includes Module include pathes + @param sourceFiles Modules source files + @param document XML document + **/ + public void init(Project project, Set includes, Set sourceFiles, Document document) { + this.document = document; + this.includes = includes; + this.project = project; + this.sourceFiles = sourceFiles; + } + + /** + Parse file without file type. + + @param filename Source file name + @param root Root node + @param unicodeFirst whether build Unicode file firstly or not + **/ + public synchronized void parseFile(String filename, Node root, boolean unicodeFirst) { + this.unicodeFirst = unicodeFirst; + parseFile(filename, root); + } + + /** + Get whether current module contains Unicode files or not. + + @return Whether current module contains Unicode files or not + **/ + public boolean isUnicodeExist() { + return unicodeExist; + } + + /** + Parse file. + + @param filename Source file name + @param filetype Source file type + @param root Root node + @param unicodeFirst whether build Unicode file firstly or not + **/ + public synchronized void parseFile(String filename, String filetype, Node root, boolean unicodeFirst) { + this.unicodeFirst = unicodeFirst; + parseFile(filename, filetype, root); + } + + /** + Find out source file's type. + + @param filename Source file name + @param root Root node + **/ + public synchronized void parseFile(String filename, Node root) { + boolean flag = false; + for (int i = 0; i < fileTypes.length; i++) { + if (filename.toLowerCase().endsWith(fileTypes[i][0])) { + flag = true; + parseFile(filename, fileTypes[i][2], root); + } + } + if (!flag) { + System.out.println("Warning: File " + filename + " is not known from its suffix."); + } + } + + /** + Parse file. If flag unicodeFirst is true, then build all + unicode files firstly. + +

Note that AutoGen.c is processed specially. It's output path is always + ${DEST_DIR_OUTPUT}, others are ${DEST_DIR_OUTPUT} + and relative to module path.

+ + @param filename Source file name + @param filetype Source file type + @param root Root node + **/ + public synchronized void parseFile(String filename, String filetype, Node root) { + if (unicodeFirst) { + if ( ! filetype.equalsIgnoreCase("Unicode")){ + return ; + } + unicodeExist= true; + } else { + if (filetype.equalsIgnoreCase("Unicode")){ + return ; + } + } + sourceFiles.add(filename); + if (filetype.equalsIgnoreCase("Header")) { + return; + } + if (filetype.equalsIgnoreCase("IPF_PP_Code")) { + return; + } + String module_path = project.getProperty("MODULE_DIR"); + File moduleFile = new File(module_path); + File sourceFile = new File(filename); + // If source file is AutoGen.c, then Filepath is . + String sourceFilepath; + String sourceFilename; + if (sourceFile.getPath().endsWith("AutoGen.c")) { + sourceFilepath = "."; + sourceFilename = "AutoGen"; + filetype = "AUTOGEN"; + } else { + // sourceFile. + String str = sourceFile.getPath().substring(moduleFile.getPath().length() + 1); + int index = str.lastIndexOf(File.separatorChar); + sourceFilepath = "."; + if (index > 0) { + sourceFilepath = str.substring(0, index); + str = str.substring(index + 1); + } + sourceFilename = str; + index = str.lastIndexOf('.'); + if (index > 0) { + sourceFilename = str.substring(0, index); + } + } + // + Element ele = document.createElement("Build_" + filetype); + ele.setAttribute("FILEPATH", sourceFilepath); + ele.setAttribute("FILENAME", sourceFilename); + String[] includePaths = includes.toArray(new String[includes.size()]); + Element includesEle = document.createElement("EXTRA.INC"); + for (int i = 0; i < includePaths.length; i++) { + Element includeEle = document.createElement("includepath"); + includeEle.setAttribute("path", includePaths[i]); + includesEle.appendChild(includeEle); + } + ele.appendChild(includesEle); + root.appendChild(ele); + } +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/org/tianocore/build/GenBuildTask.java b/Tools/Source/GenBuild/org/tianocore/build/GenBuildTask.java new file mode 100644 index 0000000000..2d91991b8a --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/GenBuildTask.java @@ -0,0 +1,1170 @@ +/** @file + This file is ANT task GenBuild. + + The file is used to parse a specified Module, and generate its build time + ANT script build.xml, then call the the ANT script to build the module. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.build; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Vector; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Ant; +import org.apache.xmlbeans.XmlObject; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; + +import org.tianocore.build.autogen.AutoGen; +import org.tianocore.build.autogen.CommonDefinition; +import org.tianocore.build.fpd.FpdParserTask; +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.OutputManager; +import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.build.toolchain.ToolChainFactory; +import org.tianocore.FilenameDocument; +import org.tianocore.MsaHeaderDocument; +import org.tianocore.MsaLibHeaderDocument; + +/** +

+ GenBuildTask is an ANT task that can be used in ANT build + system. The main function of this task is to parse module's surface area, + then generate the corresponding BaseName_build.xml (the real ANT + build script) and call this to build the module. +

+ +

+ The usage is (take module HelloWorld for example): +

+ +
+   <GenBuild baseName="HelloWorld" 
+             mbdFilename="${MODULE_DIR}/HelloWorld.mbd" 
+             msaFilename="${MODULE_DIR}/HelloWorld.msa"/>
+  
+ +

+ This task calls AutoGen to generate AutoGen.c and + AutoGen.h. The task also parses the development environment + configuration files, such as collecting package information, setting compiler + flags and so on. +

+ + + @since GenBuild 1.0 +**/ +public class GenBuildTask extends Task { + + /// + /// Module surface area file. + /// + File msaFilename; + + /// + /// Module build description file. + /// + File mbdFilename; + + /// + /// Module surface area information after overrided. + /// + public Map map = new HashMap(); + + /// + /// Module's base name. + /// + private String baseName; + + /// + /// Current build Arch, such as IA32, X64, IPF and so on. + /// + private String arch; + + /// + /// Module's GUID (Globally Unique Identifier). + /// + private String guid; + + /// + /// Module's component type, such as SEC, LIBRARY, BS_DRIVER and so on. + /// + private String componentType; + + /// + /// This value is used in build time. Override module's component type. When + /// search FFS (Sections information) in common file, buildtype instead of + /// component type. + /// + private String buildType; + + /// + /// List all required includes for current build module. + /// + public Set includes = new LinkedHashSet(); + + /// + /// List all libraries for current build module. + /// + public Set libraries = new LinkedHashSet(); + + /// + /// List all source files for current build module. + /// + public Set sourceFiles = new LinkedHashSet(); + + /// + /// Flag to identify what surface area files are specified. Current value is + /// NO_SA, ONLY_MSA, ONLY_LIBMSA, + /// MSA_AND_MBD or LIBMSA_AND_LIBMBD. + /// + /// @see org.tianocore.build.global.GlobaData + /// + private int flag = GlobalData.NO_SA; + + /// + /// The information at the header of build.xml. + /// + private String info = "====================================================================\n" + + "DO NOT EDIT \n" + + "File auto-generated by build utility\n" + + "\n" + + "Abstract:\n" + + "Auto-generated ANT build file for building of EFI Modules/Platforms\n" + + "====================================================================="; + + /** + Public construct method. It is necessary for ANT task. + **/ + public GenBuildTask() { + } + + /** + ANT task's entry point, will be called after init(). The main steps is described + as following: +
    +
  • Judge current build mode (MODULE | PACKAGE | PLATFORM). This step will execute + only once in whole build process;
  • +
  • Initialize global information (Framework DB, SPD files and all MSA files + listed in SPD). This step will execute only once in whole build process;
  • +
  • Restore some important ANT property. If current build is single module + build, here will set many default values;
  • +
  • Get the current module's overridded surface area information from + global data;
  • +
  • Set up the output directories, including BIN_DIR, DEST_DIR_OUTPUT and + DEST_DIR_DEBUG;
  • +
  • Get module dependent library instances and include pathes;
  • +
  • Judge whether current module is built. If yes, skip it;
  • +
  • Call AutoGen and PCD to generate AutoGen.c & AutoGen.h
  • +
  • Set up the compile flags;
  • +
  • Generate BaseName_build.xml;
  • +
  • Call to BaseName_build.xml, and build the current module.
  • +
+ +

Build is dependent on BuildMacro.xml which define many macro.

+ + @throws BuildException + From module build, exception from module surface area invalid. + **/ + public void execute() throws BuildException { + System.out.println("Module [" + baseName + "] start."); + OutputManager.update(getProject()); + GlobalData.initInfo("Tools" + File.separatorChar + "Conf" + File.separatorChar + "FrameworkDatabase.db", + getProject().getProperty("WORKSPACE_DIR")); + recallFixedProperties(); + arch = getProject().getProperty("ARCH"); + arch = arch.toUpperCase(); + map = GlobalData.getDoc(baseName); + // + // Initialize SurfaceAreaQuery + // + SurfaceAreaQuery.setDoc(map); + // + // Setup Output Management + // + String[] outdir = SurfaceAreaQuery.getOutputDirectory(); + OutputManager.update(getProject(), outdir[1], outdir[0]); + + updateIncludesAndLibraries(); + + if (GlobalData.isModuleBuilt(baseName, arch)) { + return; + } else { + GlobalData.registerBuiltModule(baseName, arch); + } + // + // Call AutoGen + // + AutoGen autogen = new AutoGen(getProject().getProperty("DEST_DIR_DEBUG"), baseName, arch); + autogen.genAutogen(); + // + // Update parameters + // + updateParameters(); + // + // Update flags like CC_FLAGS, LIB_FLAGS etc. + // + flagsSetup(); + GlobalData.addLibrary(baseName, getProject().getProperty("BIN_DIR") + File.separatorChar + baseName + ".lib"); + GlobalData.addModuleLibrary(baseName, libraries); + // + // If ComponentType is USER_DEFINED, + // then call the exist BaseName_build.xml directly. + // + if (buildType.equalsIgnoreCase("CUSTOM_BUILD")) { + System.out.println("Call user-defined " + baseName + "_build.xml"); + Ant ant = new Ant(); + ant.setProject(getProject()); + ant.setAntfile(getProject().getProperty("MODULE_DIR") + File.separatorChar + baseName + "_build.xml"); + ant.setInheritAll(true); + ant.init(); + ant.execute(); + return; + } + // + // Generate ${BASE_NAME}_build.xml file + // + System.out.println("Generate " + baseName + "_build.xml"); + genBuildFile(); + System.out.println("Call the " + baseName + "_build.xml"); + Ant ant = new Ant(); + ant.setProject(getProject()); + ant.setAntfile(getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + baseName + "_build.xml"); + ant.setInheritAll(true); + ant.init(); + ant.execute(); + } + + /** + Get the dependent library instances and include package name from + surface area, and initialize module include pathes. + + **/ + private void updateIncludesAndLibraries() { + List rawIncludes = SurfaceAreaQuery.getIncludePackageName(arch); + if (rawIncludes != null) { + Iterator iter = rawIncludes.iterator(); + while (iter.hasNext()) { + String packageName = (String) iter.next(); + includes.add("${WORKSPACE_DIR}" + File.separatorChar + GlobalData.getPackagePath(packageName) + + File.separatorChar + "Include"); + includes.add("${WORKSPACE_DIR}" + File.separatorChar + GlobalData.getPackagePath(packageName) + + File.separatorChar + "Include" + File.separatorChar + "${ARCH}"); + } + } + includes.add("${DEST_DIR_DEBUG}"); + List rawLibraries = SurfaceAreaQuery.getLibraryInstance(this.arch, CommonDefinition.AlwaysConsumed); + if (rawLibraries != null) { + Iterator iter = rawLibraries.iterator(); + while (iter.hasNext()) { + libraries.add((String) iter.next()); + } + } + normalize(); + } + + /** + Normalize all dependent library instance and include pathes' format. + + **/ + private void normalize() { + String[] includesArray = includes.toArray(new String[includes.size()]); + includes.clear(); + for (int i = 0; i < includesArray.length; i++) { + includes.add((new File(includesArray[i])).getPath()); + } + String[] librariesArray = libraries.toArray(new String[libraries.size()]); + libraries.clear(); + for (int i = 0; i < librariesArray.length; i++) { + libraries.add((new File(librariesArray[i])).getPath()); + } + } + + /** + Restore some important ANT property. If current build is single module + build, here will set many default values. + +

If current build is single module build, then the default ARCH + is IA32. Also set up the properties PACKAGE, + PACKAGE_DIR, TARGET and MODULE_DIR

+ +

Note that for package build, package name is stored in PLATFORM + and package directory is stored in PLATFORM_DIR.

+ + @see org.tianocore.build.global.OutputManager + **/ + private void recallFixedProperties() { + // + // If build is for module build + // + if (getProject().getProperty("PACKAGE_DIR") == null) { + ToolChainFactory toolChainFactory = new ToolChainFactory(getProject()); + toolChainFactory.setupToolChain(); + // + // PACKAGE PACKAGE_DIR ARCH (Default) COMMON_FILE BUILD_MACRO + // + if (getProject().getProperty("ARCH") == null) { + getProject().setProperty("ARCH", "IA32"); + } + String packageName = GlobalData.getPackageNameForModule(baseName); + getProject().setProperty("PACKAGE", packageName); + + String packageDir = GlobalData.getPackagePath(packageName); + getProject().setProperty("PACKAGE_DIR", + getProject().getProperty("WORKSPACE_DIR") + File.separatorChar + packageDir); + + getProject().setProperty("TARGET", toolChainFactory.getCurrentTarget()); + + getProject().setProperty("MODULE_DIR", + getProject().replaceProperties(getProject().getProperty("MODULE_DIR"))); + } + if (OutputManager.PLATFORM != null) { + getProject().setProperty("PLATFORM", OutputManager.PLATFORM); + } + if (OutputManager.PLATFORM_DIR != null) { + getProject().setProperty("PLATFORM_DIR", OutputManager.PLATFORM_DIR); + } + } + + /** + The whole BaseName_build.xml is composed of seven part. +
    +
  • ANT properties;
  • +
  • Dependent module (dependent library instances in most case);
  • +
  • Source files;
  • +
  • Sections if module is not library;
  • +
  • Output (different for library module and driver module);
  • +
  • Clean;
  • +
  • Clean all.
  • +
+ + @throws BuildException + Error throws during BaseName_build.xml generating. + **/ + private void genBuildFile() throws BuildException { + FfsProcess fp = new FfsProcess(); + DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder dombuilder = domfac.newDocumentBuilder(); + Document document = dombuilder.newDocument(); + Comment rootComment = document.createComment(info); + // + // create root element and its attributes + // + Element root = document.createElement("project"); + // + // root.setAttribute("name", base_name); + // + root.setAttribute("default", "main"); + root.setAttribute("basedir", "."); + // + // element for External ANT tasks + // + root.appendChild(document.createComment("Apply external ANT tasks")); + Element ele = document.createElement("taskdef"); + ele.setAttribute("resource", "frameworktasks.tasks"); + root.appendChild(ele); + ele = document.createElement("taskdef"); + ele.setAttribute("resource", "cpptasks.tasks"); + root.appendChild(ele); + ele = document.createElement("typedef"); + ele.setAttribute("resource", "cpptasks.types"); + root.appendChild(ele); + ele = document.createElement("taskdef"); + ele.setAttribute("resource", "net/sf/antcontrib/antlib.xml"); + root.appendChild(ele); + // + // elements for Properties + // + root.appendChild(document.createComment("All Properties")); + ele = document.createElement("property"); + ele.setAttribute("name", "BASE_NAME"); + ele.setAttribute("value", baseName); + root.appendChild(ele); + // + // Generate the default target, + // which depends on init, sections and output target + // + root.appendChild(document.createComment("Default target")); + ele = document.createElement("target"); + ele.setAttribute("name", "main"); + ele.setAttribute("depends", "libraries, sourcefiles, sections, output"); + root.appendChild(ele); + // + // compile all source files + // + root.appendChild(document.createComment("Compile all dependency Library instances.")); + ele = document.createElement("target"); + ele.setAttribute("name", "libraries"); + // + // Parse all sourfiles but files specified in sections + // + applyLibraryInstance(document, ele); + root.appendChild(ele); + // + // compile all source files + // + root.appendChild(document.createComment("sourcefiles target")); + ele = document.createElement("target"); + ele.setAttribute("name", "sourcefiles"); + // + // Parse all sourfiles but files specified in sections + // + applyCompileElement(document, ele); + root.appendChild(ele); + // + // generate the init target + // main purpose is create all nessary pathes + // generate the sections target + // + root.appendChild(document.createComment("sections target")); + ele = document.createElement("target"); + ele.setAttribute("name", "sections"); + applySectionsElement(document, ele, fp); + root.appendChild(ele); + // + // generate the output target + // + root.appendChild(document.createComment("output target")); + ele = document.createElement("target"); + ele.setAttribute("name", "output"); + applyOutputElement(document, ele, fp); + root.appendChild(ele); + // + // generate the clean target + // + root.appendChild(document.createComment("clean target")); + ele = document.createElement("target"); + ele.setAttribute("name", "clean"); + applyCleanElement(document, ele); + root.appendChild(ele); + // + // generate the Clean All target + // + root.appendChild(document.createComment("Clean All target")); + ele = document.createElement("target"); + ele.setAttribute("name", "cleanall"); + applyDeepcleanElement(document, ele); + root.appendChild(ele); + // + // add the root element to the document + // + document.appendChild(rootComment); + document.appendChild(root); + // + // Prepare the DOM document for writing + // + Source source = new DOMSource(document); + // + // Prepare the output file + // + File file = new File(getProject().getProperty("DEST_DIR_OUTPUT") + File.separatorChar + baseName + + "_build.xml"); + // + // generate all directory path + // + (new File(file.getParent())).mkdirs(); + Result result = new StreamResult(file); + // + // Write the DOM document to the file + // + Transformer xformer = TransformerFactory.newInstance().newTransformer(); + xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + xformer.setOutputProperty(OutputKeys.INDENT, "yes"); + xformer.transform(source, result); + } catch (Exception ex) { + throw new BuildException("Module [" + baseName + "] generating build file failed.\n" + ex.getMessage()); + } + } + + /** + Generate the clean elements for BaseName_build.xml. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applyCleanElement(Document document, Node root) { + String[] libinstances = libraries.toArray(new String[libraries.size()]); + for (int i = 0; i < libinstances.length; i++) { + File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml"); + + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", file.getPath()); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element ele = document.createElement("ant"); + ele.setAttribute("antfile", file.getPath()); + ele.setAttribute("inheritAll", "false"); + ele.setAttribute("target", libinstances[i] + "_clean"); + // + // Workspace_DIR + // + Element property = document.createElement("property"); + property.setAttribute("name", "WORKSPACE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}"); + ele.appendChild(property); + // + // Package Dir + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(libinstances[i])); + ele.appendChild(property); + // + // ARCH + // + property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", "${ARCH}"); + ele.appendChild(property); + // + // TARGET + // + property = document.createElement("property"); + property.setAttribute("name", "TARGET"); + property.setAttribute("value", "${TARGET}"); + ele.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i])); + ele.appendChild(property); + + elseEle.appendChild(ele); + ifEle.appendChild(elseEle); + root.appendChild(ifEle); + } + } + + /** + Generate the cleanall elements for BaseName_build.xml. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applyDeepcleanElement(Document document, Node root) { + String[] libinstances = libraries.toArray(new String[libraries.size()]); + for (int i = 0; i < libinstances.length; i++) { + File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml"); + + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", file.getPath()); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element ele = document.createElement("ant"); + ele.setAttribute("antfile", file.getPath()); + ele.setAttribute("inheritAll", "false"); + ele.setAttribute("target", libinstances[i] + "_cleanall"); + // + // Workspace_DIR + // + Element property = document.createElement("property"); + property.setAttribute("name", "WORKSPACE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}"); + ele.appendChild(property); + // + // Package Dir + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(libinstances[i])); + ele.appendChild(property); + // + // ARCH + // + property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", "${ARCH}"); + ele.appendChild(property); + // + // TARGET + // + property = document.createElement("property"); + property.setAttribute("name", "TARGET"); + property.setAttribute("value", "${TARGET}"); + ele.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i])); + ele.appendChild(property); + + elseEle.appendChild(ele); + ifEle.appendChild(elseEle); + root.appendChild(ifEle); + } + } + + /** + Generate the dependent library instances elements for BaseName_build.xml. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applyLibraryInstance(Document document, Node root) { + String[] libinstances = libraries.toArray(new String[libraries.size()]); + for (int i = 0; i < libinstances.length; i++) { + Element ele = document.createElement("ant"); + File file = new File(GlobalData.getModulePath(libinstances[i]) + File.separatorChar + "build.xml"); + ele.setAttribute("antfile", file.getPath()); + ele.setAttribute("inheritAll", "false"); + ele.setAttribute("target", libinstances[i]); + // + // Workspace_DIR + // + Element property = document.createElement("property"); + property.setAttribute("name", "WORKSPACE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}"); + ele.appendChild(property); + // + // Package Dir + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(libinstances[i])); + ele.appendChild(property); + // + // ARCH + // + property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", "${ARCH}"); + ele.appendChild(property); + // + // TARGET + // + property = document.createElement("property"); + property.setAttribute("name", "TARGET"); + property.setAttribute("value", "${TARGET}"); + ele.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData.getPackageNameForModule(libinstances[i])); + ele.appendChild(property); + root.appendChild(ele); + } + Element expand = document.createElement("Expand"); + root.appendChild(expand); + } + + /** + Generate the build source files elements for BaseName_build.xml. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applyCompileElement(Document document, Node root) { + FileProcess fileProcess = new FileProcess(); + fileProcess.init(getProject(), includes, sourceFiles, document); + Node[] files = this.getSourceFiles(); + // + // Parse all unicode files + // + for (int i = 0; i < files.length; i++) { + String filetype = getFiletype(files[i]); + if (filetype != null) { + fileProcess.parseFile(getFilename(files[i]), filetype, root, true); + } else { + fileProcess.parseFile(getFilename(files[i]), root, true); + } + } + if (fileProcess.isUnicodeExist()) { + Element ele = document.createElement("Build_Unicode_Database"); + ele.setAttribute("FILEPATH", "."); + ele.setAttribute("FILENAME", "${BASE_NAME}"); + root.appendChild(ele); + } + + // + // Parse AutoGen.c & AutoGen.h + // + if (!baseName.equalsIgnoreCase("Shell")) { + fileProcess.parseFile(getProject().getProperty("DEST_DIR_DEBUG") + File.separatorChar + "AutoGen.c", root, + false); + } + // + // Parse all source files + // + for (int i = 0; i < files.length; i++) { + String filetype = getFiletype(files[i]); + if (filetype != null) { + fileProcess.parseFile(getFilename(files[i]), filetype, root, false); + } else { + fileProcess.parseFile(getFilename(files[i]), root, false); + } + } + // + // root.appendChild(parallelEle); + // + Iterator iter = sourceFiles.iterator(); + String str = ""; + while (iter.hasNext()) { + str += " " + (String) iter.next(); + } + getProject().setProperty("SOURCE_FILES", str); + } + + /** + Generate the section elements for BaseName_build.xml. Library module will + skip this process. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applySectionsElement(Document document, Node root, FfsProcess fp) { + if (fp.initSections(buildType, getProject())) { + String targetFilename = guid + "-" + baseName + FpdParserTask.getSuffix(componentType); + String[] list = fp.getGenSectionElements(document, baseName, guid, targetFilename); + + for (int i = 0; i < list.length; i++) { + Element ele = document.createElement(list[i]); + ele.setAttribute("FILEPATH", "."); + ele.setAttribute("FILENAME", "${BASE_NAME}"); + root.appendChild(ele); + } + } + } + + /** + Generate the output elements for BaseName_build.xml. If module is library, + call the LIB command, else call the GenFfs command. + + @param document current BaseName_build.xml XML document + @param root Root element for current + **/ + private void applyOutputElement(Document document, Node root, FfsProcess fp) { + if (flag == GlobalData.ONLY_LIBMSA || flag == GlobalData.LIBMSA_AND_LIBMBD) { + // + // call Lib command + // + Element cc = document.createElement("Build_Library"); + cc.setAttribute("FILENAME", baseName); + root.appendChild(cc); + } + // + // if it is a module but library + // + else { + if (fp.getFfsNode() != null) { + root.appendChild(fp.getFfsNode()); + } + } + } + + /** + Get file name from node. If some wrong, return string with zero length. + + @param node Filename node of MSA/MBD or specified in each Section + @return File name + **/ + private String getFilename(Node node) { + String path = null; + String filename = "${MODULE_DIR}" + File.separatorChar; + String str = ""; + try { + FilenameDocument file = (FilenameDocument) XmlObject.Factory.parse(node); + str = file.getFilename().getStringValue().trim(); + path = file.getFilename().getPath(); + } catch (Exception e) { + str = ""; + } + if (path != null) { + filename += path + File.separatorChar + str; + } else { + filename += str; + } + return getProject().replaceProperties(filename); + } + + /** + Get file type from node. If some wrong or not specified, return + null. + + @param node Filename node of MSA/MBD or specified in each Section + @return File type + **/ + private String getFiletype(Node node) { + String str = null; + try { + FilenameDocument file = (FilenameDocument) XmlObject.Factory.parse(node); + str = file.getFilename().getFileType(); + } catch (Exception e) { + str = null; + } + return str; + } + + /** + Return all source files but AutoGen.c. + + @return source files Node array + **/ + public Node[] getSourceFiles() { + XmlObject[] files = SurfaceAreaQuery.getSourceFiles(arch); + if (files == null) { + return new Node[0]; + } + Vector vector = new Vector(); + for (int i = 0; i < files.length; i++) { + vector.addElement(files[i].getDomNode()); + } + // + // To be consider sourcefiles from Sections + // + return vector.toArray(new Node[vector.size()]); + } + + /** + Get current module's base name. + + @return base name + **/ + public String getBaseName() { + return baseName; + } + + /** + Set MBD surface area file. For ANT use. + + @param mbdFilename Surface Area file + **/ + public void setMbdFilename(File mbdFilename) { + this.mbdFilename = mbdFilename; + } + + /** + Set MSA surface area file. For ANT use. + + @param msaFilename Surface Area file + **/ + public void setMsaFilename(File msaFilename) { + this.msaFilename = msaFilename; + } + + /** + Compile flags setup. + +

Take command CC and arch IA32 for example, + Those flags are from ToolChainFactory:

+
    +
  • IA32_CC
  • +
  • IA32_CC_STD_FLAGS
  • +
  • IA32_CC_GLOBAL_FLAGS
  • +
  • IA32_CC_GLOBAL_ADD_FLAGS
  • +
  • IA32_CC_GLOBAL_SUB_FLAGS
  • +
+ Those flags can user-define: +
    +
  • IA32_CC_PROJ_FLAGS
  • +
  • IA32_CC_PROJ_ADD_FLAGS
  • +
  • IA32_CC_PROJ_SUB_FLAGS
  • +
  • CC_PROJ_FLAGS
  • +
  • CC_PROJ_ADD_FLAGS
  • +
  • CC_PROJ_SUB_FLAGS
  • +
  • CC_FLAGS
  • +
  • IA32_CC_FLAGS
  • +
+ +

The final flags is composed of STD, GLOBAL and PROJ. If CC_FLAGS or + IA32_CC_FLAGS is specified, STD, GLOBAL and PROJ will not affect.

+ + Note that the ToolChainFactory executes only once + during whole build process. + **/ + private void flagsSetup() { + Project project = getProject(); + // + // If ToolChain has been set up before, do nothing. + // + ToolChainFactory toolChainFactory = new ToolChainFactory(project); + toolChainFactory.setupToolChain(); + + String[] cmd = ToolChainFactory.commandType; + Set addSet = new HashSet(40); + Set subSet = new HashSet(40); + for (int i = 0; i < cmd.length; i++) { + String str = ToolChainFactory.getValue(arch + "_" + cmd[i]); + // + // Command line path+command name + // + if (str != null) { + project.setProperty(cmd[i], str); + } + // + // ARCH_CMD_STD_FLAGS + // + str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_STD_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + project.setProperty(cmd[i] + "_STD_FLAGS", str); + } + // + // ARCH_CMD_GLOBAL_FLAGS + // + str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // ARCH_CMD_GLOBAL_ADD_FLAGS + // + str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_ADD_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // ARCH_CMD_GLOBAL_SUB_FLAGS + // + str = ToolChainFactory.getValue(arch + "_" + cmd[i] + "_GLOBAL_SUB_FLAGS"); + if (str != null) { + putFlagsToSet(subSet, str); + } + // + // ARCH_CMD_PROJ_FLAGS + // + str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // ARCH_CMD_PROG_FLAGS + // + str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_ADD_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // ARCH_CMD_PROG_FLAGS + // + str = project.getProperty(arch + "_" + cmd[i] + "_PROJ_SUB_FLAGS"); + if (str != null) { + putFlagsToSet(subSet, str); + } + // + // CMD_PROJ_FLAGS + // + str = project.getProperty(cmd[i] + "_PROJ_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // CMD_PROG_FLAGS + // + str = project.getProperty(cmd[i] + "_PROJ_ADD_FLAGS"); + if (str != null) { + putFlagsToSet(addSet, str); + } + // + // CMD_PROG_FLAGS + // + str = project.getProperty(cmd[i] + "_PROJ_SUB_FLAGS"); + if (str != null) { + putFlagsToSet(subSet, str); + } + // + // If IA32_CC_FLAGS or IA32_LIB_FLAGS .. has defined in BuildOptions + // + if ((str = project.getProperty(arch + "_" + cmd[i] + "_FLAGS")) != null) { + project.setProperty(cmd[i] + "_FLAGS", getRawFlags(addSet, subSet)); + addSet.clear(); + subSet.clear(); + putFlagsToSet(addSet, project.replaceProperties(str)); + project.setProperty(cmd[i] + "_FLAGS", project.replaceProperties(getFlags(addSet, subSet))); + addSet.clear(); + subSet.clear(); + } + // + // If CC_FLAGS or LIB_FLAGS .. has defined in BuildOptions + // + else if ((str = project.getProperty(cmd[i] + "_FLAGS")) != null) { + project.setProperty(cmd[i] + "_FLAGS", getRawFlags(addSet, subSet)); + addSet.clear(); + subSet.clear(); + putFlagsToSet(addSet, project.replaceProperties(str)); + project.setProperty(cmd[i] + "_FLAGS", project.replaceProperties(getFlags(addSet, subSet))); + addSet.clear(); + subSet.clear(); + } else { + project.setProperty(cmd[i] + "_FLAGS", getFlags(addSet, subSet)); + addSet.clear(); + subSet.clear(); + } + } + project.setProperty("C_FLAGS", project.getProperty("CC_FLAGS")); + } + + /** + Initialize some properties will be used in current module build, including + user-defined option from Option of BuildOptions in + surface area. + **/ + private void updateParameters() { + getProject().setProperty("OBJECTS", ""); + getProject().setProperty("SDB_FILES", ""); + getProject().setProperty("BASE_NAME", baseName); + if (map.get("MsaHeader") != null) { + flag = GlobalData.MSA_AND_MBD; + MsaHeaderDocument.MsaHeader header = ((MsaHeaderDocument) map.get("MsaHeader")).getMsaHeader(); + guid = header.getGuid().getStringValue(); + componentType = header.getComponentType().toString(); + } + + else if (map.get("MsaLibHeader") != null) { + flag = GlobalData.LIBMSA_AND_LIBMBD; + MsaLibHeaderDocument.MsaLibHeader header = ((MsaLibHeaderDocument) map.get("MsaLibHeader")) + .getMsaLibHeader(); + guid = header.getGuid().getStringValue(); + componentType = header.getComponentType().toString(); + } + + if (componentType != null) { + getProject().setProperty("COMPONENT_TYPE", componentType); + } + + if (guid != null) { + getProject().setProperty("FILE_GUID", guid); + } + // + // Get all options and set to properties + // + String[][] options = SurfaceAreaQuery.getOptions(arch); + for (int i = 0; i < options.length; i++) { + if (options[i][0] != null && options[i][1] != null) { + getProject().setProperty(options[i][0], getProject().replaceProperties(options[i][1])); + } + } + + buildType = getProject().getProperty("BUILD_TYPE"); + if (buildType == null) { + buildType = componentType; + } + + } + + /** + Separate the string and instore in set. + +

String is separated by Java Regulation Expression + "[^\\\\]?(\".*?[^\\\\]\")[ \t,]+".

+ +

For example:

+ +
+        "/nologo", "/W3", "/WX"
+        "/C", "/DSTRING_DEFINES_FILE=\"BdsStrDefs.h\""
+      
+ + @param set store the separated string + @param str string to separate + **/ + private void putFlagsToSet(Set set, String str) { + Pattern myPattern = Pattern.compile("[^\\\\]?(\".*?[^\\\\]\")[ \t,]+"); + Matcher matcher = myPattern.matcher(str + " "); + while (matcher.find()) { + String item = str.substring(matcher.start(1), matcher.end(1)); + if (!set.contains(item)) { + set.add(item); + } + } + } + + /** + Generate the final flags string will be used by compile command. + + @param add the add flags set + @param sub the sub flags set + @return final flags after add set substract sub set + **/ + private String getFlags(Set add, Set sub) { + String result = ""; + add.removeAll(sub); + Iterator iter = add.iterator(); + while (iter.hasNext()) { + String str = getProject().replaceProperties((String) iter.next()); + result += str.substring(1, str.length() - 1) + " "; + } + return result; + } + + /** + Generate the flags string with original format. The format is defined by + Java Regulation Expression "[^\\\\]?(\".*?[^\\\\]\")[ \t,]+".

+ +

For example:

+ +
+        "/nologo", "/W3", "/WX"
+        "/C", "/DSTRING_DEFINES_FILE=\"BdsStrDefs.h\""
+      
+ + @param add the add flags set + @param sub the sub flags set + @return flags with original format + **/ + private String getRawFlags(Set add, Set sub) { + String result = ""; + add.removeAll(sub); + Iterator iter = add.iterator(); + while (iter.hasNext()) { + String str = getProject().replaceProperties((String) iter.next()); + result += "\"" + str.substring(1, str.length() - 1) + "\", "; + } + return result; + } + + /** + Set base name. For ANT use. + + @param baseName Base name + **/ + public void setBaseName(String baseName) { + this.baseName = baseName; + } + +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/OutputDirSetupTask.java b/Tools/Source/GenBuild/org/tianocore/build/OutputDirSetupTask.java new file mode 100644 index 0000000000..c2b7cc997b --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/OutputDirSetupTask.java @@ -0,0 +1,190 @@ +/** @file + + This file is an ANT task OutputDirSetupTask. + + This task main purpose is to setup some necessary properties for Package, + Platform or Module clean. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.build; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.xmlbeans.XmlObject; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.OutputManager; +import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.build.toolchain.ToolChainFactory; + +/** + OutputDirSetupTask is an ANT task that can be used in ANT build + system. The main function of this task is to initialize some basic information + for Package|Platform|Module clean or cleanall usage. + +

Here is an example:

+
+     <OutputDirSetup baseName="HelloWorld" 
+                     mbdFilename="${MODULE_DIR}\HelloWorld.mbd" 
+                     msaFilename="${MODULE_DIR}\HelloWorld.msa" />
+  
+ +

Note that all this task doing is part of GenBuildTask.

+ + @since GenBuild 1.0 + @see org.tianocore.build.GenBuildTask +**/ +public class OutputDirSetupTask extends Task { + + /// + /// Module surface area file. + /// + File msaFilename; + + /// + /// Module build description file. + /// + File mbdFilename; + + /// + /// Module surface area information after overrided. + /// + public Map map = new HashMap(); + + /// + /// Module's base name. + /// + private String baseName; + + /** + Public construct method. It is necessary for ANT task. + **/ + public OutputDirSetupTask () { + } + + /** + ANT task's entry point, will be called after init(). The main steps is described + as following: +
    +
  • Judge current build mode (MODULE | PACKAGE | PLATFORM). This step will execute + only once in whole build process;
  • +
  • Initialize global information (Framework DB, SPD files and all MSA files + listed in SPD). This step will execute only once in whole build process;
  • +
  • Restore some important ANT property. If current build is single module + build, here will set many default values;
  • +
  • Get the current module's overridded surface area information from + global data;
  • +
  • Set up the output directories, including BIN_DIR, DEST_DIR_OUTPUT and + DEST_DIR_DEBUG;
  • +
+ + @throws BuildException + From module build, exception from module surface area invalid. + **/ + public void execute() throws BuildException { + System.out.println("Deleting module [" + baseName + "] start."); + OutputManager.update(getProject()); + GlobalData.initInfo("Tools" + File.separatorChar + "Conf" + File.separatorChar + "FrameworkDatabase.db", getProject() + .getProperty("WORKSPACE_DIR")); + recallFixedProperties(); + map = GlobalData.getDoc(baseName); + // + // Initialize SurfaceAreaQuery + // + SurfaceAreaQuery.setDoc(map); + // + // Setup Output Management + // + String[] outdir = SurfaceAreaQuery.getOutputDirectory(); + OutputManager.update(getProject(), outdir[1], outdir[0]); + } + + /** + Get current module's base name. + + @return base name + **/ + public String getBaseName() { + return baseName; + } + + /** + Set base name. For ANT use. + + @param baseName Base name + **/ + public void setBaseName(String baseName) { + this.baseName = baseName; + } + + /** + Set MBD surface area file. For ANT use. + + @param mbdFilename Surface Area file + **/ + public void setMbdFilename(File mbdFilename) { + this.mbdFilename = mbdFilename; + } + + /** + Set MSA surface area file. For ANT use. + + @param msaFilename Surface Area file + **/ + public void setMsaFilename(File msaFilename) { + this.msaFilename = msaFilename; + } + + /** + Restore some important ANT property. If current build is single module + build, here will set many default values. + +

If current build is single module build, then the default ARCH + is IA32. Also set up the properties PACKAGE, + PACKAGE_DIR, TARGET and MODULE_DIR

+ +

Note that for package build, package name is stored in PLATFORM + and package directory is stored in PLATFORM_DIR.

+ + @see org.tianocore.build.global.OutputManager + **/ + private void recallFixedProperties(){ + // + // If build is for module build + // + if (getProject().getProperty("PACKAGE_DIR") == null) { + ToolChainFactory toolChainFactory = new ToolChainFactory(getProject()); + toolChainFactory.setupToolChain(); + // + // PACKAGE PACKAGE_DIR ARCH (Default) COMMON_FILE BUILD_MACRO + // + if (getProject().getProperty("ARCH") == null){ + getProject().setProperty("ARCH", "IA32"); + } + String packageName = GlobalData.getPackageNameForModule(baseName); + getProject().setProperty("PACKAGE", packageName); + String packageDir = GlobalData.getPackagePath(packageName); + getProject().setProperty("PACKAGE_DIR", getProject().getProperty("WORKSPACE_DIR") + File.separatorChar + packageDir); + getProject().setProperty("TARGET", toolChainFactory.getCurrentTarget()); + getProject().setProperty("MODULE_DIR", getProject().replaceProperties(getProject().getProperty("MODULE_DIR"))); + } + if (OutputManager.PLATFORM != null) { + getProject().setProperty("PLATFORM", OutputManager.PLATFORM); + } + if (OutputManager.PLATFORM_DIR != null) { + getProject().setProperty("PLATFORM_DIR", OutputManager.PLATFORM_DIR); + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/autogen/AutoGen.java b/Tools/Source/GenBuild/org/tianocore/build/autogen/AutoGen.java new file mode 100644 index 0000000000..f1e9c5b4ec --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/autogen/AutoGen.java @@ -0,0 +1,2006 @@ +/** @file + AutoGen class. + + This class is to generate Autogen.h and Autogen.c according to module surface area + or library surface area. + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.build.autogen; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.Spd; +import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.GuidsDocument; +import org.tianocore.LibraryClassDocument.LibraryClass; +import org.tianocore.PPIsDocument; +import org.tianocore.ProtocolsDocument; +import org.tianocore.build.pcd.action.PCDAutoGenAction; + +import org.apache.tools.ant.BuildException; +import org.apache.xmlbeans.XmlObject; + +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + This class is to generate Autogen.h and Autogen.c according to module surface + area or library surface area. +**/ +public class AutoGen { + /// + /// The output path of Autogen.h and Autogen.c + /// + private String outputPath; + + /// + /// The base name of module or library. + /// + private String baseName; + + /// + /// The build architecture + /// + private String arch; + + /// + /// PcdAutogen instance which is used to manage how to generate the PCD + /// information. + /// + private PCDAutoGenAction myPcdAutogen; + + /// + /// The protocl list which records in module or library surface area and + /// it's dependence on library instance surface area. + /// + private List mProtocolList = new ArrayList(); + + /// + /// The Ppi list which recorded in module or library surface area and its + /// dependency on library instance surface area. + /// + private List mPpiList = new ArrayList(); + + /// + /// The Guid list which recoreded in module or library surface are and it's + /// dependence on library instance surface area. + /// + private List mGuidList = new ArrayList(); + + /** + Construct function + + This function mainly initialize some member variable. + + @param outputPath Output path of AutoGen file. + @param baseName Module base name. + @param arch Target architecture. + **/ + public AutoGen(String outputPath, String baseName, String arch) { + this.outputPath = outputPath; + this.baseName = baseName; + this.arch = arch; + + } + + /** + saveFile function + + This function save the content in stringBuffer to file. + + @param fileName The name of file. + @param fileBuffer The content of AutoGen file in buffer. + @return "true" successful, "false" failed. + **/ + private boolean saveFile(String fileName, StringBuffer fileBuffer) { + try { + File autoGenH = new File(fileName); + + // + // if the file exists, compare their content + // + if (autoGenH.exists()) { + FileReader fIn = new FileReader(autoGenH); + char[] oldFileBuffer = new char[(int) autoGenH.length()]; + fIn.read(oldFileBuffer, 0, (int) autoGenH.length()); + fIn.close(); + + // + // if we got the same file, don't re-generate it to prevent + // sources depending on it from re-building + // + if (fileBuffer.toString().compareTo(new String(oldFileBuffer)) == 0) { + return true; + } + } + FileWriter fOut = new FileWriter(autoGenH); + fOut.write(fileBuffer.toString()); + fOut.close(); + } catch (Exception e) { + return false; + } + return true; + } + + /** + genAutogen function + + This function call libGenAutoGen or moduleGenAutogen function, which + dependence on generate library autogen or module autogen. + + @throws BuildException Failed to creat AutoGen.c & AutoGen.h. + **/ + public void genAutogen() throws BuildException { + try { + // + // If outputPath do not exist, create it. + // + File path = new File(outputPath); + path.mkdirs(); + + // + // Check current is library or not, then call the corresponding + // function. + // + if (SurfaceAreaQuery.getComponentType().equalsIgnoreCase( + CommonDefinition.LibraryStr)) { + libGenAutogen(); + } else { + moduleGenAutogen(); + } + + } catch (Exception e) { + throw new BuildException( + "Failed to create AutoGen.c & AutoGen.h!\n" + + e.getMessage()); + } + } + + /** + moduleGenAutogen function + + This function generates AutoGen.c & AutoGen.h for module. + + @throws BuildException Faile to create module AutoGen.c & AutoGen.h. + **/ + void moduleGenAutogen() throws BuildException { + + try { + moduleGenAutogenC(); + moduleGenAutogenH(); + } catch (Exception e) { + throw new BuildException( + "Faile to create module AutoGen.c & AutoGen.h!\n" + + e.getMessage()); + } + } + + /** + libGenAutogen function + + This function generates AutoGen.c & AutoGen.h for library. + + @throws BuildException + Faile to create library AutoGen.c & AutoGen.h + **/ + void libGenAutogen() throws BuildException { + try { + libGenAutogenC(); + libGenAutogenH(); + } catch (Exception e) { + throw new BuildException( + "Faile to create library AutoGen.c & AutoGen.h!\n" + + e.getMessage()); + } + } + + /** + moduleGenAutogenH + + This function generates AutoGen.h for module. + + @throws BuildException + Failed to generate AutoGen.h. + **/ + void moduleGenAutogenH() throws BuildException { + + List libClassIncludeH; + String moduleType; + List headerFileList; + + StringBuffer fileBuffer = new StringBuffer(8192); + + // + // Write Autogen.h header notation + // + fileBuffer.append(CommonDefinition.autogenHNotation); + + // + // Add #ifndef ${BaseName}_AUTOGENH + // #def ${BseeName}_AUTOGENH + // + fileBuffer.append("#ifndef " + this.baseName.toUpperCase() + "_AUTOGENH\r\n"); + fileBuffer.append("#define " + this.baseName.toUpperCase() + "_AUTOGENH\r\n\r\n"); + + // + // Write the specification version and release version at the begine + // of autogen.h file. + // Note: the specification version and release version should + // be got from module surface area instead of hard code by it's moduleType. + // + moduleType = SurfaceAreaQuery.getModuleType(); + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append(CommonDefinition.autoGenHLine1); + break; + default: + fileBuffer.append(CommonDefinition.autoGenHVersionDefault); + break; + } + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append(CommonDefinition.autoGenHReleaseDefault); + break; + default: + fileBuffer.append(CommonDefinition.autoGenHLine2); + break; + } + + // + // Add "extern int __make_me_compile_correctly;" at begin of + // AutoGen.h. + // + fileBuffer.append(CommonDefinition.autoGenHbegin); + + // + // Write consumed package's mdouleInfo related .h file to autogen.h + // + List consumedPkgList = SurfaceAreaQuery + .getIncludePackageName(this.arch); + if (consumedPkgList != null) { + headerFileList = IncludesToAutogenH(consumedPkgList, moduleType); + for (int i = 0; i < headerFileList.size(); i++) { + fileBuffer.append(headerFileList.get(i)); + } + } + + // + // Write library class's related *.h file to autogen.h. + // + LibraryClass[] libClassList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysConsumed); + if (libClassList != null) { + libClassIncludeH = LibraryClassToAutogenH(libClassList); + for (int i = 0; i < libClassIncludeH.size(); i++) { + fileBuffer.append(libClassIncludeH.get(i)); + } + } + + libClassList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysProduced); + if (libClassList != null) { + libClassIncludeH = LibraryClassToAutogenH(libClassList); + for (int i = 0; i < libClassIncludeH.size(); i++) { + fileBuffer.append(libClassIncludeH.get(i)); + } + } + fileBuffer.append("\r\n"); + + // + // Write PCD autogen information to AutoGen.h. + // + if (this.myPcdAutogen != null) { + fileBuffer.append(this.myPcdAutogen.OutputH()); + } + + // + // Append the #endif at AutoGen.h + // + fileBuffer.append("#endif\r\n"); + + // + // Save string buffer content in AutoGen.h. + // + if (!saveFile(outputPath + File.separatorChar + "AutoGen.h", fileBuffer)) { + throw new BuildException("Failed to generate AutoGen.h !!!"); + } + } + + /** + moduleGenAutogenC + + This function generates AutoGen.c for module. + + @throws BuildException + Failed to generate AutoGen.c. + **/ + void moduleGenAutogenC() throws BuildException { + + StringBuffer fileBuffer = new StringBuffer(8192); + // + // Write Autogen.c header notation + // + fileBuffer.append(CommonDefinition.autogenCNotation); + + // + // Write #include at beginning of AutoGen.c + // + fileBuffer.append(CommonDefinition.includeAutogenH); + + // + // Write DriverBinding/ComponentName/DriverConfiguration/DriverDialog + // to AutoGen.c + // + ExternsDriverBindingToAutoGenC(fileBuffer); + + // + // Write DriverExitBootServicesEvent/DriverSetVirtualAddressMapEvent + // to Autogen.c + // + ExternCallBackToAutoGenC(fileBuffer); + + // + // Write EntryPoint to autgoGen.c + // + String[] entryPointList = SurfaceAreaQuery.getModuleEntryPointArray(); + if (entryPointList != null) { + EntryPointToAutoGen(entryPointList, fileBuffer); + } + + // + // Write Guid to autogen.c + // + String guid = SurfaceAreaQuery.getModuleGuid(); + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID gEfiCallerIdGuid = {"); + if (guid == null) { + throw new BuildException("Guid value must set!\n"); + } + + // + // Formate Guid as ANSI c form.Example: + // {0xd2b2b828, 0x826, 0x48a7,{0xb3, 0xdf, 0x98, 0x3c, 0x0, 0x60, 0x24, 0xf0}} + // + fileBuffer.append(Spd.formatGuidName(guid)); + fileBuffer.append("};\r\n"); + + // + // Generate library instance consumed protocol, guid, ppi, pcd list. + // Save those to this.protocolList, this.ppiList, this.pcdList, + // this.guidList. Write Consumed library constructor and desconstuct to + // autogen.c + // + LibInstanceToAutogenC(fileBuffer); + + // + // Write consumed ppi, guid, protocol to autogen.c + // + ProtocolGuidToAutogenC(fileBuffer); + PpiGuidToAutogenC(fileBuffer); + GuidGuidToAutogenC(fileBuffer); + + // + // Call pcd autogen. PCDAutoGenAction tool only need module name and + // isPcdEmulatedDriver as parameter. Library inherits PCD and module's + // PCD information has been collected in FPDParser task by + // CollectPCDAction. + // Note : when PCD image tool ready, + // isPCDEmulatedDriver parameter will be removed. + // + try { + this.myPcdAutogen = new PCDAutoGenAction(baseName, + baseName.equalsIgnoreCase("PcdEmulatorPeim")); + this.myPcdAutogen.execute(); + } catch (Exception e) { + throw new BuildException("PCD Autogen failed:" + e.getMessage()); + } + + if (this.myPcdAutogen != null) { + fileBuffer.append(this.myPcdAutogen.OutputC()); + } + + if (!saveFile(outputPath + File.separatorChar + "AutoGen.c", fileBuffer)) { + throw new BuildException("Failed to generate AutoGen.c !!!"); + } + + } + + /** + libGenAutogenH + + This function generates AutoGen.h for library. + + @throws BuildException + Failed to generate AutoGen.c. + **/ + void libGenAutogenH() throws BuildException { + + List libClassIncludeH; + String moduleType; + List headerFileList; + StringBuffer fileBuffer = new StringBuffer(10240); + + // + // Write Autogen.h header notation + // + fileBuffer.append(CommonDefinition.autogenHNotation); + + // + // Add #ifndef ${BaseName}_AUTOGENH + // #def ${BseeName}_AUTOGENH + // + fileBuffer.append("#ifndef " + this.baseName.toUpperCase() + "_AUTOGENH\r\n"); + fileBuffer.append("#define " + this.baseName.toUpperCase() + "_AUTOGENH\r\n\r\n"); + + // + // Write EFI_SPECIFICATION_VERSION and EDK_RELEASE_VERSION + // to autogen.h file. + // Note: the specification version and release version should + // be get from module surface area instead of hard code. + // + fileBuffer.append(CommonDefinition.autoGenHbegin); + fileBuffer.append(CommonDefinition.autoGenHLine1); + fileBuffer.append(CommonDefinition.autoGenHLine2); + + // + // Write consumed package's mdouleInfo related *.h file to autogen.h. + // + moduleType = SurfaceAreaQuery.getModuleType(); + List cosumedPkglist = SurfaceAreaQuery + .getIncludePackageName(this.arch); + headerFileList = IncludesToAutogenH(cosumedPkglist, moduleType); + for (int i = 0; i < headerFileList.size(); i++) { + fileBuffer.append(headerFileList.get(i)); + } + + // + // Write library class's related *.h file to autogen.h + // + LibraryClass[] libClassList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysConsumed); + if (libClassList != null) { + libClassIncludeH = LibraryClassToAutogenH(libClassList); + for (int i = 0; i < libClassIncludeH.size(); i++) { + fileBuffer.append(libClassIncludeH.get(i)); + } + } + + libClassList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysProduced); + if (libClassList != null) { + libClassIncludeH = LibraryClassToAutogenH(libClassList); + for (int i = 0; i < libClassIncludeH.size(); i++) { + fileBuffer.append(libClassIncludeH.get(i)); + } + } + fileBuffer.append("\r\n"); + + // + // Write PCD information to library AutoGen.h. + // + if (this.myPcdAutogen != null) { + fileBuffer.append(this.myPcdAutogen.OutputH()); + } + + // + // Append the #endif at AutoGen.h + // + fileBuffer.append("#endif\r\n"); + + // + // Save content of string buffer to AutoGen.h file. + // + if (!saveFile(outputPath + File.separatorChar + "AutoGen.h", fileBuffer)) { + throw new BuildException("Failed to generate AutoGen.h !!!"); + } + } + + /** + libGenAutogenC + + This function generates AutoGen.h for library. + + @throws BuildException + Failed to generate AutoGen.c. + **/ + void libGenAutogenC() throws BuildException { + StringBuffer fileBuffer = new StringBuffer(10240); + + // + // Write Autogen.c header notation + // + fileBuffer.append(CommonDefinition.autogenCNotation); + + fileBuffer.append(CommonDefinition.autoGenCLine1); + fileBuffer.append("\r\n"); + + // + // Call pcd autogen. PCDAutoGenAction tool only need module name and + // isPcdEmulatedDriver as parameter. Library inherit PCD and module's + // PCD information has been collected in FPDParser task by + // CollectPCDAction. + // Note : when PCD image tool ready, + // isPCDEmulatedDriver parameter will be removed. + // + try { + this.myPcdAutogen = new PCDAutoGenAction(baseName, baseName + .equalsIgnoreCase("PcdEmulatorPeim")); + this.myPcdAutogen.execute(); + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + + if (this.myPcdAutogen != null) { + fileBuffer.append(this.myPcdAutogen.OutputC()); + } + + if (!saveFile(outputPath + File.separatorChar + "AutoGen.c", fileBuffer)) { + throw new BuildException("Failed to generate AutoGen.c !!!"); + } + } + + /** + LibraryClassToAutogenH + + This function returns *.h files declared by library classes which are + consumed or produced by current build module or library. + + @param libClassList List of library class which consumed or produce + by current build module or library. + @return includeStrList List of *.h file. + **/ + List LibraryClassToAutogenH(LibraryClass[] libClassList) { + List includStrList = new ArrayList(); + String includerName; + String str = ""; + + // + // Get include file from GlobalData's SPDTable according to + // library class name. + // + for (int i = 0; i < libClassList.length; i++) { + includerName = GlobalData.getLibClassIncluder(libClassList[i] + .getStringValue()); + if (includerName != null) { + str = CommonDefinition.include + " " + "<"; + str = str + includerName + ">\r\n"; + includStrList.add(str); + includerName = null; + } + } + return includStrList; + } + + /** + IncludesToAutogenH + + This function add include file in AutoGen.h file. + @param packageNameList List of module depended package. + @param moduleType Module type. + @return + **/ + List IncludesToAutogenH(List packageNameList, + String moduleType) { + + List includeStrList = new ArrayList(); + String packageName = ""; + String includeStr = ""; + + // + // Get include file from moduleInfo file + // + for (int i = 0; i < packageNameList.size(); i++) { + packageName = packageNameList.get(i); + includeStr = GlobalData.getModuleInfoByPackageName(packageName, + moduleType); + includeStrList.add(includeStr); + } + return includeStrList; + } + + /** + EntryPointToAutoGen + + This function convert & information + in mas to AutoGen.c + + @param entryPointList List of entry point. + @param fileBuffer String buffer fo AutoGen.c. + @throws Exception + **/ + void EntryPointToAutoGen(String[] entryPointList, StringBuffer fileBuffer) + throws BuildException { + + String typeStr = SurfaceAreaQuery.getModuleType(); + + // + // The parameters and return value of entryPoint is difference + // for difference module type. + // + switch (CommonDefinition.getModuleType(typeStr)) { + + case CommonDefinition.ModuleTypePeiCore: + if (entryPointList.length != 1 || entryPointList[0].equals("")) { + throw new BuildException( + "Module type = 'PEI_CORE', only have one module entry point!"); + } else { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,\r\n"); + fileBuffer + .append(" IN VOID *OldCoreData\r\n"); + fileBuffer.append(" );\r\n\r\n"); + + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleEntryPointList (\r\n"); + fileBuffer + .append(" IN EFI_PEI_STARTUP_DESCRIPTOR *PeiStartupDescriptor,\r\n"); + fileBuffer + .append(" IN VOID *OldCoreData\r\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + fileBuffer.append(" return "); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (PeiStartupDescriptor, OldCoreData);\r\n"); + fileBuffer.append("}\r\n\r\n"); + } + break; + + case CommonDefinition.ModuleTypeDxeCore: + fileBuffer.append("const UINT32 _gUefiDriverRevision = 0;\r\n"); + if (entryPointList.length != 1 || entryPointList[0].equals("")) { + throw new BuildException( + "Module type = 'DXE_CORE', only have one module entry point!"); + } else { + + fileBuffer.append("VOID\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (\n"); + fileBuffer.append(" IN VOID *HobStart\r\n"); + fileBuffer.append(" );\r\n\r\n"); + + fileBuffer.append("VOID\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleEntryPointList (\r\n"); + fileBuffer.append(" IN VOID *HobStart\r\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + fileBuffer.append(" "); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (HobStart);\r\n"); + fileBuffer.append("}\r\n\r\n"); + } + break; + + case CommonDefinition.ModuleTypePeim: + int entryPointCount = 0; + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT32 _gPeimRevision = 0;\r\n"); + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" IN EFI_FFS_FILE_HEADER *FfsHeader,\r\n"); + fileBuffer + .append(" IN EFI_PEI_SERVICES **PeiServices\r\n"); + fileBuffer.append(" );\r\n"); + entryPointCount++; + } else { + break; + } + } + + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleEntryPointList (\r\n"); + fileBuffer.append(" IN EFI_FFS_FILE_HEADER *FfsHeader,\r\n"); + fileBuffer.append(" IN EFI_PEI_SERVICES **PeiServices\r\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + + if (entryPointCount == 0) { + fileBuffer.append(" return EFI_SUCCESS;\r\n"); + } else if (entryPointCount == 1) { + fileBuffer.append(" return "); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (FfsHeader, PeiServices);\r\n"); + } else { + fileBuffer.append(" EFI_STATUS Status;\r\n"); + fileBuffer.append(" EFI_STATUS CombinedStatus;\r\n\r\n"); + fileBuffer.append(" CombinedStatus = EFI_LOAD_ERROR;\r\n\r\n"); + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append(" Status = "); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (FfsHeader, PeiServices)\r\n"); + fileBuffer + .append(" if (!EFI_ERROR (Status) || EFI_ERROR (CombinedStatus)) {\r\n"); + fileBuffer.append(" CombinedStatus = Status;\r\n"); + fileBuffer.append(" }\r\n\r\n"); + } else { + break; + } + } + fileBuffer.append(" return CombinedStatus;\r\n"); + } + fileBuffer.append("}\r\n\r\n"); + break; + + case CommonDefinition.ModuleTypeDxeSmmDriver: + entryPointCount = 0; + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" );\r\n"); + entryPointCount++; + } else { + break; + } + } + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverEntryPointCount = "); + fileBuffer.append(Integer.toString(entryPointCount)); + fileBuffer.append(";\r\n"); + fileBuffer + .append("static BASE_LIBRARY_JUMP_BUFFER mJumpContext;\r\n"); + fileBuffer + .append("static EFI_STATUS mDriverEntryPointStatus = EFI_LOAD_ERROR;\r\n\r\n"); + + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleEntryPointList (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer + .append(" if (SetJump (&mJumpContext) == 0) {\r\n"); + fileBuffer.append(" ExitDriver ("); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (ImageHandle, SystemTable));\r\n"); + fileBuffer.append(" ASSERT (FALSE);\r\n"); + fileBuffer.append(" }\r\n"); + } else { + break; + } + } + fileBuffer.append(" return mDriverEntryPointStatus;\r\n"); + fileBuffer.append("}\r\n\r\n"); + + fileBuffer.append("VOID\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ExitDriver (\r\n"); + fileBuffer.append(" IN EFI_STATUS Status\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + fileBuffer + .append(" if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) {\r\n"); + fileBuffer.append(" mDriverEntryPointStatus = Status;\r\n"); + fileBuffer.append(" }\r\n"); + fileBuffer.append(" LongJump (&mJumpContext, (UINTN)-1);\r\n"); + fileBuffer.append(" ASSERT (FALSE);\r\n"); + fileBuffer.append("}\r\n\r\n"); + + // + // Add "ModuleUnloadImage" for DxeSmmDriver module type; + // + entryPointList = SurfaceAreaQuery.getModuleUnloadImageArray(); + entryPointCount = 0; + if (entryPointList != null) { + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" );\r\n"); + entryPointCount++; + } else { + break; + } + } + } + + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = "); + fileBuffer.append(Integer.toString(entryPointCount)); + fileBuffer.append(";\r\n\r\n"); + + if (entryPointList != null) { + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" );\r\n"); + } else { + break; + } + } + } + + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleUnloadList (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" )\r\n"); + fileBuffer.append("{\r\n"); + + if (entryPointCount == 0) { + fileBuffer.append(" return EFI_SUCCESS;\r\n"); + } else if (entryPointCount == 1) { + fileBuffer.append(" return "); + fileBuffer.append(entryPointList[0]); + fileBuffer.append("(ImageHandle);\r\n"); + } else { + fileBuffer.append(" EFI_STATUS Status;\r\n\r\n"); + fileBuffer.append(" Status = EFI_SUCCESS;\r\n\r\n"); + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append(" if (EFI_ERROR (Status)) {\r\n"); + fileBuffer.append(" "); + fileBuffer.append(entryPointList[i]); + fileBuffer.append("(ImageHandle);\r\n"); + fileBuffer.append(" } else {\r\n"); + fileBuffer.append(" Status = "); + fileBuffer.append(entryPointList[i]); + fileBuffer.append("(ImageHandle);\r\n"); + fileBuffer.append(" }\r\n"); + } else { + break; + } + } + fileBuffer.append(" return Status;\r\n"); + } + fileBuffer.append("}\r\n\r\n"); + break; + + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + entryPointCount = 0; + fileBuffer.append("const UINT32 _gUefiDriverRevision = 0;\r\n"); + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" );\r\n"); + entryPointCount++; + } else { + break; + } + } + + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverEntryPointCount = "); + fileBuffer.append(Integer.toString(entryPointCount)); + fileBuffer.append(";\r\n"); + if (entryPointCount > 1) { + fileBuffer + .append("static BASE_LIBRARY_JUMP_BUFFER mJumpContext;\r\n"); + fileBuffer + .append("static EFI_STATUS mDriverEntryPointStatus = EFI_LOAD_ERROR;\r\n"); + } + fileBuffer.append("\n"); + + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append("ProcessModuleEntryPointList (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + + if (entryPointCount == 0) { + fileBuffer.append(" return EFI_SUCCESS;\r\n"); + } else if (entryPointCount == 1) { + fileBuffer.append(" return ("); + fileBuffer.append(entryPointList[0]); + fileBuffer.append(" (ImageHandle, SystemTable));\r\n"); + } else { + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer + .append(" if (SetJump (&mJumpContext) == 0) {\r\n"); + fileBuffer.append(" ExitDriver ("); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (ImageHandle, SystemTable));\r\n"); + fileBuffer.append(" ASSERT (FALSE);\r\n"); + fileBuffer.append(" }\r\n"); + } else { + break; + } + } + fileBuffer.append(" return mDriverEntryPointStatus;\r\n"); + } + fileBuffer.append("}\r\n\r\n"); + + fileBuffer.append("VOID\n"); + fileBuffer.append("EFIAPI\n"); + fileBuffer.append("ExitDriver (\r\n"); + fileBuffer.append(" IN EFI_STATUS Status\n"); + fileBuffer.append(" )\r\n\r\n"); + fileBuffer.append("{\r\n"); + if (entryPointCount <= 1) { + fileBuffer.append(" if (EFI_ERROR (Status)) {\r\n"); + fileBuffer + .append(" ProcessLibraryDestructorList (gImageHandle, gST);\r\n"); + fileBuffer.append(" }\r\n"); + fileBuffer + .append(" gBS->Exit (gImageHandle, Status, 0, NULL);\r\n"); + } else { + fileBuffer + .append(" if (!EFI_ERROR (Status) || EFI_ERROR (mDriverEntryPointStatus)) {\r\n"); + fileBuffer.append(" mDriverEntryPointStatus = Status;\r\n"); + fileBuffer.append(" }\r\n"); + fileBuffer.append(" LongJump (&mJumpContext, (UINTN)-1);\r\n"); + fileBuffer.append(" ASSERT (FALSE);\r\n"); + } + fileBuffer.append("}\r\n\r\n"); + + // + // Add ModuleUnloadImage for DxeDriver and UefiDriver module type. + // + entryPointList = SurfaceAreaQuery.getModuleUnloadImageArray(); + entryPointCount = 0; + if (entryPointList != null) { + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" );\r\n"); + entryPointCount++; + } else { + break; + } + } + } + + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverUnloadImageCount = "); + fileBuffer.append(Integer.toString(entryPointCount)); + fileBuffer.append(";\r\n\r\n"); + + if (entryPointList != null) { + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append("EFIAPI\r\n"); + fileBuffer.append(entryPointList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" );\r\n"); + } else { + break; + } + } + } + + fileBuffer.append("EFI_STATUS\n"); + fileBuffer.append("EFIAPI\n"); + fileBuffer.append("ProcessModuleUnloadList (\r\n"); + fileBuffer.append(" EFI_HANDLE ImageHandle\r\n"); + fileBuffer.append(" )\r\n"); + fileBuffer.append("{\r\n"); + + if (entryPointCount == 0) { + fileBuffer.append(" return EFI_SUCCESS;\r\n"); + } else if (entryPointCount == 1) { + fileBuffer.append(" return "); + fileBuffer.append(entryPointList[0]); + fileBuffer.append("(ImageHandle);\r\n"); + } else { + fileBuffer.append(" EFI_STATUS Status;\r\n\r\n"); + fileBuffer.append(" Status = EFI_SUCCESS;\r\n\r\n"); + for (int i = 0; i < entryPointList.length; i++) { + if (!entryPointList[i].equals("")) { + fileBuffer.append(" if (EFI_ERROR (Status)) {\r\n"); + fileBuffer.append(" "); + fileBuffer.append(entryPointList[i]); + fileBuffer.append("(ImageHandle);\r\n"); + fileBuffer.append(" } else {\r\n"); + fileBuffer.append(" Status = "); + fileBuffer.append(entryPointList[i]); + fileBuffer.append("(ImageHandle);\r\n"); + fileBuffer.append(" }\r\n"); + } else { + break; + } + } + fileBuffer.append(" return Status;\r\n"); + } + fileBuffer.append("}\r\n\r\n"); + break; + } + } + + /** + PpiGuidToAutogenc + + This function gets GUIDs from SPD file accrodeing to information and + write those GUIDs to AutoGen.c. + + @param fileBuffer String Buffer for Autogen.c file. + @throws BuildException Guid must set value! + **/ + void PpiGuidToAutogenC(StringBuffer fileBuffer) throws BuildException { + String[] cNameGuid = null; + boolean isEqual = false; + + PPIsDocument.PPIs.Ppi[] ppiList = SurfaceAreaQuery.getPpiArray(null); + if (ppiList != null) { + for (int i = 0; i < ppiList.length; i++) { + isEqual = false; + for (int j = 0; j < this.mPpiList.size(); j++) { + if (this.mPpiList.get(j).equalsIgnoreCase( + ppiList[i].getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mPpiList.add(ppiList[i].getStringValue()); + } + } + } + + PPIsDocument.PPIs.PpiNotify[] ppiNotifyList = SurfaceAreaQuery + .getPpiNotifyArray(null); + if (ppiNotifyList != null) { + for (int i = 0; i < ppiNotifyList.length; i++) { + isEqual = false; + for (int j = 0; j < this.mPpiList.size(); j++) { + if (this.mPpiList.get(j).equalsIgnoreCase( + ppiNotifyList[i].getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mPpiList.add(ppiNotifyList[i].getStringValue()); + } + } + } + + for (int i = 0; i < this.mPpiList.size(); i++) { + if (this.mPpiList.get(i) != null) { + cNameGuid = GlobalData.getPpiInfoGuid(this.mPpiList.get(i)); + if (cNameGuid != null) { + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID "); + fileBuffer.append(cNameGuid[0]); + fileBuffer.append(" = { "); + fileBuffer.append(cNameGuid[1]); + fileBuffer.append(" } ;"); + } + } else { + throw new BuildException("Guid must set value!"); + } + } + } + + /** + ProtocolGuidToAutogenc + + This function gets GUIDs from SPD file accrodeing to + information and write those GUIDs to AutoGen.c. + + @param fileBuffer String Buffer for Autogen.c file. + @throws BuildException Protocol name must set. + **/ + void ProtocolGuidToAutogenC(StringBuffer fileBuffer) throws BuildException { + String[] cNameGuid = null; + boolean isEqual = false; + + ProtocolsDocument.Protocols.Protocol[] protocolList = SurfaceAreaQuery + .getProtocolArray(null); + if (protocolList != null) { + for (int i = 0; i < protocolList.length; i++) { + isEqual = false; + for (int j = 0; j < this.mProtocolList.size(); j++) { + if (this.mProtocolList.get(j).equalsIgnoreCase( + protocolList[i].getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mProtocolList.add(protocolList[i].getStringValue()); + + } + } + } + + ProtocolsDocument.Protocols.ProtocolNotify[] protocolNotifyList = SurfaceAreaQuery + .getProtocolNotifyArray(null); + if (protocolNotifyList != null) { + for (int i = 0; i < protocolNotifyList.length; i++) { + isEqual = false; + for (int j = 0; j < this.mProtocolList.size(); j++) { + if (this.mProtocolList.get(j).equalsIgnoreCase( + protocolNotifyList[i].getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mProtocolList.add(protocolNotifyList[i] + .getStringValue()); + + } + } + } + if (this.mProtocolList.size() > 0) { + for (int i = 0; i < this.mProtocolList.size(); i++) { + if (this.mProtocolList.get(i) != null) { + cNameGuid = GlobalData + .getProtocolInfoGuid(this.mProtocolList.get(i)); + if (cNameGuid != null) { + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID "); + fileBuffer.append(cNameGuid[0]); + fileBuffer.append(" = { "); + fileBuffer.append(cNameGuid[1]); + fileBuffer.append(" } ;"); + } + } else { + throw new BuildException("Protocol name must set!"); + } + } + } + } + + /** + GuidGuidToAutogenc + + This function gets GUIDs from SPD file accrodeing to information + and write those GUIDs to AutoGen.c. + + @param fileBuffer String Buffer for Autogen.c file. + + **/ + void GuidGuidToAutogenC(StringBuffer fileBuffer) { + String[] cNameGuid = null; + boolean isEqual = false; + GuidsDocument.Guids.GuidEntry[] guidList = SurfaceAreaQuery + .getGuidEntryArray(null); + + if (guidList != null) { + for (int i = 0; i < guidList.length; i++) { + for (int j = 0; j < this.mGuidList.size(); j++) { + isEqual = false; + if (this.mGuidList.get(j).getCName().equalsIgnoreCase( + guidList[i].getCName().toString())) { + isEqual = true; + break; + } + } + if (!isEqual) { + this.mGuidList.add(guidList[i]); + + } + + } + } + + for (int i = 0; i < this.mGuidList.size(); i++) { + if (this.mGuidList.get(i).getCName() != null) { + cNameGuid = GlobalData.getGuidInfoGuid(this.mGuidList.get(i) + .getCName()); + if (cNameGuid != null) { + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED EFI_GUID "); + fileBuffer.append(cNameGuid[0]); + fileBuffer.append(" = { "); + fileBuffer.append(cNameGuid[1]); + fileBuffer.append("} ;"); + } + } + } + } + + /** + LibInstanceToAutogenC + + This function adds dependent library instance to autogen.c,which includeing + library's constructor, destructor, and library dependent ppi, protocol, guid, + pcd information. + + @param fileBuffer String buffer for AutoGen.c + @throws BuildException + **/ + void LibInstanceToAutogenC(StringBuffer fileBuffer) throws BuildException { + int index; + boolean isEqual = false; + + String moduleType = SurfaceAreaQuery.getModuleType(); + List libConstructList = new ArrayList(); + List libDestructList = new ArrayList(); + + String libConstructName = null; + String libDestructName = null; + List libraryList = SurfaceAreaQuery.getLibraryInstance( + this.arch, CommonDefinition.AlwaysConsumed); + + try { + if (libraryList != null) { + // + // Reorder library instance sequence. + // + AutogenLibOrder libOrder = new AutogenLibOrder(libraryList); + List orderList = libOrder.orderLibInstance(); + + if (orderList != null) { + // + // Process library instance one by one. + // + for (int i = 0; i < orderList.size(); i++) { + + // + // Get library instance basename. + // + String libInstanceName = orderList.get(i).toString(); + + // + // Get override map + // + Map libDoc = GlobalData + .getDoc(libInstanceName); + SurfaceAreaQuery.push(libDoc); + + // + // Get , , list of this library + // instance. + // + PPIsDocument.PPIs.Ppi[] ppiList = SurfaceAreaQuery + .getPpiArray(null); + PPIsDocument.PPIs.PpiNotify[] ppiNotifyList = SurfaceAreaQuery + .getPpiNotifyArray(null); + ProtocolsDocument.Protocols.Protocol[] protocolList = SurfaceAreaQuery + .getProtocolArray(null); + ProtocolsDocument.Protocols.ProtocolNotify[] protocolNotifyList = SurfaceAreaQuery + .getProtocolNotifyArray(null); + GuidsDocument.Guids.GuidEntry[] guidList = SurfaceAreaQuery + .getGuidEntryArray(null); + + // + // Add those ppi, protocol, guid in global ppi, protocol, guid + // list. + // + if (ppiList != null) { + for (index = 0; index < ppiList.length; index++) { + isEqual = false; + for (int j = 0; j < this.mPpiList.size(); j++) { + if (this.mPpiList.get(j).equalsIgnoreCase( + ppiList[index].getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mPpiList.add(ppiList[index] + .getStringValue()); + } + } + } + if (ppiNotifyList != null) { + for (index = 0; index < ppiNotifyList.length; index++) { + isEqual = false; + for (int j = 0; j < this.mPpiList.size(); j++) { + if (this.mPpiList.get(j).equalsIgnoreCase( + ppiNotifyList[index] + .getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mPpiList.add(ppiNotifyList[index] + .getStringValue()); + } + } + } + if (protocolList != null) { + for (index = 0; index < protocolList.length; index++) { + isEqual = false; + for (int j = 0; j < this.mProtocolList.size(); j++) { + if (this.mProtocolList.get(j) + .equalsIgnoreCase( + protocolList[index] + .getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mProtocolList.add(protocolList[index] + .getStringValue()); + } + } + } + if (protocolNotifyList != null) { + for (index = 0; index < protocolNotifyList.length; index++) { + isEqual = false; + for (int j = 0; j < this.mProtocolList.size(); j++) { + if (this.mProtocolList.get(j) + .equalsIgnoreCase( + protocolNotifyList[index] + .getStringValue())) { + isEqual = true; + } + } + if (!isEqual) { + this.mProtocolList + .add(protocolNotifyList[index] + .getStringValue()); + } + } + } + if (guidList != null) { + for (index = 0; index < guidList.length; index++) { + isEqual = false; + for (int j = 0; j < this.mGuidList.size(); j++) { + if (this.mGuidList.get(j).getCName() + .equalsIgnoreCase( + guidList[index].getCName())) { + isEqual = true; + } + } + if (!isEqual) { + this.mGuidList.add(guidList[index]); + } + } + } + + // + // If not yet parse this library instance's constructor + // element,parse it. + // + if (!GlobalData.isHaveLibInstance(libInstanceName)) { + libConstructName = SurfaceAreaQuery + .getLibConstructorName(); + libDestructName = SurfaceAreaQuery + .getLibDestructorName(); + + GlobalData.setLibInstanceInfo(libInstanceName, + libConstructName, libDestructName); + } else { + libConstructName = GlobalData + .getLibInstanceConstructor(libInstanceName); + libDestructName = GlobalData + .getLibInstanceDestructor(libInstanceName); + } + SurfaceAreaQuery.pop(); + // + // Add dependent library instance constructor function. + // + if (libConstructName != null) { + libConstructList.add(libConstructName); + } + // + // Add dependent library instance destructor fuction. + // + if (libDestructName != null) { + libDestructList.add(libDestructName); + } + } + + } + + // + // Add library constructor to AutoGen.c + // + LibConstructorToAutogenC(libConstructList, moduleType, + fileBuffer/* autogenC */); + // + // Add library destructor to AutoGen.c + // + LibDestructorToAutogenC(libDestructList, moduleType, + fileBuffer/* autogenC */); + } + + } catch (Exception e) { + throw new BuildException(e.getMessage()); + } + } + + + /** + LibConstructorToAutogenc + + This function writes library constructor list to AutoGen.c. The library + constructor's parameter and return value depend on module type. + + @param libInstanceList List of library construct name. + @param moduleType Module type. + @param fileBuffer String buffer for AutoGen.c + @throws Exception + **/ + void LibConstructorToAutogenC(List libInstanceList, + String moduleType, StringBuffer fileBuffer) throws Exception { + boolean isFirst = true; + + // + // The library constructor's parameter and return value depend on + // module type. + // + for (int i = 0; i < libInstanceList.size(); i++) { + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeBase: + fileBuffer.append("RETURN_STATUS\r\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" VOID\r\n"); + fileBuffer.append(" );\r\n"); + break; + + case CommonDefinition.ModuleTypePeiCore: + case CommonDefinition.ModuleTypePeim: + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" IN EFI_FFS_FILE_HEADER *FfsHeader,\r\n"); + fileBuffer + .append(" IN EFI_PEI_SERVICES **PeiServices\r\n"); + fileBuffer.append(" );\r\n"); + break; + + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" IN EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" IN EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" );\r\n"); + break; + } + } + + // + // Add ProcessLibraryConstructorList in AutoGen.c + // + fileBuffer.append("VOID\r\n"); + fileBuffer.append("ProcessLibraryConstructorList (\r\n"); + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeBase: + fileBuffer.append(" VOID\r\n"); + break; + + case CommonDefinition.ModuleTypePeiCore: + case CommonDefinition.ModuleTypePeim: + fileBuffer.append(" IN EFI_FFS_FILE_HEADER *FfsHeader,\r\n"); + fileBuffer + .append(" IN EFI_PEI_SERVICES **PeiServices\r\n"); + break; + + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append(" IN EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" IN EFI_SYSTEM_TABLE *SystemTable\r\n"); + break; + } + + fileBuffer.append(" )\r\n"); + fileBuffer.append("{\r\n"); + + for (int i = 0; i < libInstanceList.size(); i++) { + if (isFirst) { + fileBuffer.append(" EFI_STATUS Status;\r\n"); + fileBuffer.append("\r\n"); + isFirst = false; + } + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeBase: + fileBuffer.append(" Status = "); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append("();\r\n"); + fileBuffer.append(" VOID\r\n"); + break; + case CommonDefinition.ModuleTypePeiCore: + case CommonDefinition.ModuleTypePeim: + fileBuffer.append(" Status = "); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (FfsHeader, PeiServices);\r\n"); + break; + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append(" Status = "); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (ImageHandle, SystemTable);\r\n"); + break; + } + fileBuffer.append(" ASSERT_EFI_ERROR (Status);\r\n"); + } + fileBuffer.append("}\r\n"); + } + + /** + LibDestructorToAutogenc + + This function writes library destructor list to AutoGen.c. The library + destructor's parameter and return value depend on module type. + + @param libInstanceList List of library destructor name. + @param moduleType Module type. + @param fileBuffer String buffer for AutoGen.c + @throws Exception + **/ + void LibDestructorToAutogenC(List libInstanceList, + String moduleType, StringBuffer fileBuffer) throws Exception { + boolean isFirst = true; + for (int i = 0; i < libInstanceList.size(); i++) { + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeBase: + fileBuffer.append("RETURN_STATUS\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" VOID\r\n"); + fileBuffer.append(" );\r\n"); + break; + case CommonDefinition.ModuleTypePeiCore: + case CommonDefinition.ModuleTypePeim: + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer + .append(" IN EFI_FFS_FILE_HEADER *FfsHeader,\r\n"); + fileBuffer + .append(" IN EFI_PEI_SERVICES **PeiServices\r\n"); + fileBuffer.append(" );\r\n"); + break; + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append("EFI_STATUS\r\n"); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" IN EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" IN EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" );\r\n"); + break; + } + } + + // + // Write ProcessLibraryDestructor list to autogen.c + // + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeBase: + case CommonDefinition.ModuleTypePeiCore: + case CommonDefinition.ModuleTypePeim: + break; + case CommonDefinition.ModuleTypeDxeCore: + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSmmDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + fileBuffer.append("VOID\r\n"); + fileBuffer.append("ProcessLibraryDestructorList (\r\n"); + fileBuffer.append(" IN EFI_HANDLE ImageHandle,\r\n"); + fileBuffer.append(" IN EFI_SYSTEM_TABLE *SystemTable\r\n"); + fileBuffer.append(" )\r\n"); + fileBuffer.append("{\r\n"); + + for (int i = 0; i < libInstanceList.size(); i++) { + if (isFirst) { + fileBuffer.append(" EFI_STATUS Status;\r\n"); + fileBuffer.append("\r\n"); + isFirst = false; + } + fileBuffer.append(" Status = "); + fileBuffer.append(libInstanceList.get(i)); + fileBuffer.append("(ImageHandle, SystemTable);\r\n"); + fileBuffer.append(" ASSERT_EFI_ERROR (Status);\r\n"); + } + fileBuffer.append("}\r\n"); + break; + } + } + + /** + ExternsDriverBindingToAutoGenC + + This function is to write DRIVER_BINDING, COMPONENT_NAME, + DRIVER_CONFIGURATION, DRIVER_DIAGNOSTIC in AutoGen.c. + + @param fileBuffer String buffer for AutoGen.c + */ + void ExternsDriverBindingToAutoGenC(StringBuffer fileBuffer) + throws BuildException { + + // + // Check what contains. And the number of following elements + // under should be same. 1. DRIVER_BINDING 2. COMPONENT_NAME + // 3.DRIVER_CONFIGURATION 4. DRIVER_DIAGNOSTIC + // + + String[] drvBindList = SurfaceAreaQuery.getDriverBindingArray(); + + // + // If component name protocol,component configuration protocol, + // component diagnostic protocol is not null or empty, check + // if every one have the same number of the driver binding protocol. + // + if (drvBindList == null || drvBindList.length == 0) { + return; + } + + String[] compNamList = SurfaceAreaQuery.getComponentNameArray(); + String[] compConfList = SurfaceAreaQuery.getDriverConfigArray(); + String[] compDiagList = SurfaceAreaQuery.getDriverDiagArray(); + + int BitMask = 0; + + // + // Write driver binding protocol extern to autogen.c + // + for (int i = 0; i < drvBindList.length; i++) { + fileBuffer.append("extern EFI_DRIVER_BINDING_PROTOCOL "); + fileBuffer.append(drvBindList[i]); + fileBuffer.append(";\r\n"); + } + + // + // Write component name protocol extern to autogen.c + // + if (compNamList != null && compNamList.length != 0) { + if (drvBindList.length != compNamList.length) { + throw new BuildException( + "Different number of Driver Binding and Component Name protocols!"); + } + + BitMask |= 0x01; + for (int i = 0; i < compNamList.length; i++) { + fileBuffer.append("extern EFI_COMPONENT_NAME_PROTOCOL "); + fileBuffer.append(compNamList[i]); + fileBuffer.append(";\r\n"); + } + } + + // + // Write driver configration protocol extern to autogen.c + // + if (compConfList != null && compConfList.length != 0) { + if (drvBindList.length != compConfList.length) { + throw new BuildException( + "Different number of Driver Binding and Driver Configuration protocols!"); + } + + BitMask |= 0x02; + for (int i = 0; i < compConfList.length; i++) { + fileBuffer.append("extern EFI_DRIVER_CONFIGURATION_PROTOCOL "); + fileBuffer.append(compConfList[i]); + fileBuffer.append(";\r\n"); + } + } + + // + // Write driver dignastic protocol extern to autogen.c + // + if (compDiagList != null && compDiagList.length != 0) { + if (drvBindList.length != compDiagList.length) { + throw new BuildException( + "Different number of Driver Binding and Driver Configuration protocols!"); + } + + BitMask |= 0x04; + for (int i = 0; i < compDiagList.length; i++) { + fileBuffer.append("extern EFI_DRIVER_DIAGNOSTICS_PROTOCOL "); + fileBuffer.append(compDiagList[i]); + fileBuffer.append(";\r\n"); + } + } + + // + // Write driver module protocol bitmask. + // + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINT8 _gDriverModelProtocolBitmask = "); + fileBuffer.append(Integer.toString(BitMask)); + fileBuffer.append(";\r\n"); + + // + // Write driver module protocol list entry + // + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gDriverModelProtocolListEntries = "); + + fileBuffer.append(Integer.toString(drvBindList.length)); + fileBuffer.append(";\r\n"); + + // + // Write drive module protocol list to autogen.c + // + fileBuffer + .append("GLOBAL_REMOVE_IF_UNREFERENCED const EFI_DRIVER_MODEL_PROTOCOL_LIST _gDriverModelProtocolList[] = {"); + for (int i = 0; i < drvBindList.length; i++) { + if (i != 0) { + fileBuffer.append(","); + } + fileBuffer.append("\r\n {\r\n"); + fileBuffer.append(" &"); + fileBuffer.append(drvBindList[i]); + fileBuffer.append(", \r\n"); + + if (compNamList != null) { + fileBuffer.append(" &"); + fileBuffer.append(compNamList[i]); + fileBuffer.append(", \r\n"); + } else { + fileBuffer.append(" NULL, \r\n"); + } + + if (compConfList != null) { + fileBuffer.append(" &"); + fileBuffer.append(compConfList[i]); + fileBuffer.append(", \r\n"); + } else { + fileBuffer.append(" NULL, \r\n"); + } + + if (compDiagList != null) { + fileBuffer.append(" &"); + fileBuffer.append(compDiagList[i]); + fileBuffer.append(", \r\n"); + } else { + fileBuffer.append(" NULL, \r\n"); + } + fileBuffer.append(" }"); + } + fileBuffer.append("\r\n};\r\n"); + } + + /** + ExternCallBackToAutoGenC + + This function adds and + infomation to AutoGen.c + + @param fileBuffer String buffer for AutoGen.c + @throws BuildException + **/ + void ExternCallBackToAutoGenC(StringBuffer fileBuffer) + throws BuildException { + String[] setVirtualList = SurfaceAreaQuery + .getSetVirtualAddressMapCallBackArray(); + String[] exitBootList = SurfaceAreaQuery + .getExitBootServicesCallBackArray(); + String moduleType = SurfaceAreaQuery.getModuleType(); + boolean UefiOrDxeModule = false; + int Count = 0; + int i; + + switch (CommonDefinition.getModuleType(moduleType)) { + case CommonDefinition.ModuleTypeDxeDriver: + case CommonDefinition.ModuleTypeDxeRuntimeDriver: + case CommonDefinition.ModuleTypeDxeSalDriver: + case CommonDefinition.ModuleTypeUefiDriver: + case CommonDefinition.ModuleTypeUefiApplication: + // + // Entry point lib for these module types needs to know the count + // of entryPoint. + // + UefiOrDxeModule = true; + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gDriverSetVirtualAddressMapEventCount = "); + + // + // If the list is not valid or has no entries set count to zero else + // set count to the number of valid entries + // + Count = 0; + if (setVirtualList != null) { + for (i = 0; i < setVirtualList.length; i++) { + if (setVirtualList[i].equalsIgnoreCase("")) { + break; + } + } + Count = i; + } + + fileBuffer.append(Integer.toString(Count)); + fileBuffer.append(";\r\n\r\n"); + break; + default: + break; + } + + if (setVirtualList == null) { + if (UefiOrDxeModule) { + // + // No data so make a NULL list + // + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const EFI_EVENT_NOTIFY _gDriverSetVirtualAddressMapEvent[] = {\r\n"); + fileBuffer.append(" NULL\r\n"); + fileBuffer.append("};\r\n\r\n"); + } + } else { + // + // Write SetVirtualAddressMap function definition. + // + for (i = 0; i < setVirtualList.length; i++) { + if (setVirtualList[i].equalsIgnoreCase("")) { + break; + } + fileBuffer.append("VOID\r\n"); + fileBuffer.append("EFIAPI\n"); + fileBuffer.append(setVirtualList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" IN EFI_EVENT Event,\r\n"); + fileBuffer.append(" IN VOID *Context\r\n"); + fileBuffer.append(" );\r\n\r\n"); + } + + // + // Write SetVirtualAddressMap entry point array. + // + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const EFI_EVENT_NOTIFY _gDriverSetVirtualAddressMapEvent[] = {"); + for (i = 0; i < setVirtualList.length; i++) { + if (setVirtualList[i].equalsIgnoreCase("")) { + break; + } + + if (i == 0) { + fileBuffer.append("\r\n "); + } else { + fileBuffer.append(",\r\n "); + } + + fileBuffer.append(setVirtualList[i]); + } + if (Count == 0) { + fileBuffer.append("\r\n NULL"); + } + fileBuffer.append("\r\n};\r\n\r\n"); + } + + if (UefiOrDxeModule) { + // + // Entry point lib for these module types needs to know the count. + // + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const UINTN _gDriverExitBootServicesEventCount = "); + + // + // If the list is not valid or has no entries set count to zero else + // set count to the number of valid entries. + // + Count = 0; + if (exitBootList != null) { + if (setVirtualList != null) { + for (i = 0; i < exitBootList.length; i++) { + if (exitBootList[i].equalsIgnoreCase("")) { + break; + } + } + Count = i; + } + } + fileBuffer.append(Integer.toString(Count)); + fileBuffer.append(";\r\n\r\n"); + } + + if (exitBootList == null) { + if (UefiOrDxeModule) { + // + // No data so make a NULL list. + // + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const EFI_EVENT_NOTIFY _gDriverExitBootServicesEvent[] = {\r\n"); + fileBuffer.append(" NULL\r\n"); + fileBuffer.append("};\r\n\r\n"); + } + } else { + // + // Write DriverExitBootServices function definition. + // + for (i = 0; i < exitBootList.length; i++) { + if (exitBootList[i].equalsIgnoreCase("")) { + break; + } + + fileBuffer.append("VOID\r\n"); + fileBuffer.append("EFIAPI\n"); + fileBuffer.append(exitBootList[i]); + fileBuffer.append(" (\r\n"); + fileBuffer.append(" IN EFI_EVENT Event,\r\n"); + fileBuffer.append(" IN VOID *Context\r\n"); + fileBuffer.append(" );\r\n\r\n"); + } + + // + // Write DriverExitBootServices entry point array. + // + fileBuffer + .append("\r\nGLOBAL_REMOVE_IF_UNREFERENCED const EFI_EVENT_NOTIFY _gDriverExitBootServicesEvent[] = {"); + for (i = 0; i < exitBootList.length; i++) { + if (exitBootList[i].equalsIgnoreCase("")) { + break; + } + + if (i == 0) { + fileBuffer.append("\r\n "); + } else { + fileBuffer.append(",\r\n "); + } + fileBuffer.append(exitBootList[i]); + } + if (Count == 0) { + fileBuffer.append("\r\n NULL"); + } + fileBuffer.append("\r\n};\r\n\r\n"); + } + + } + +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/org/tianocore/build/autogen/AutogenLibOrder.java b/Tools/Source/GenBuild/org/tianocore/build/autogen/AutogenLibOrder.java new file mode 100644 index 0000000000..77404d4007 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/autogen/AutogenLibOrder.java @@ -0,0 +1,306 @@ +/**@file + AutogenLibOrder class. + + This class is to reorder library instance sequence according to library + dependence. + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.build.autogen; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.xmlbeans.XmlObject; +import org.tianocore.LibraryClassDocument.LibraryClass; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.SurfaceAreaQuery; + +/** + This class This class is to reorder library instance sequence according to + library dependence. +**/ +public class AutogenLibOrder { + /// + /// The map of library class and its library instance. + /// + private Map libClassMap = new HashMap(); + + /// + /// The map of library instance and its implemet instance. + /// + private Map libInstanceMap = new HashMap(); + + /// + /// List of library instance. It is String[3] list, String[0] is libraryName, + /// String[1] is libraryConstructor name, String[2] is libDestructor name. + /// + private List libInstanceList = new ArrayList(); + + /** + Constructor function + + This function mainly initialize some member variable. + + @param libraryList List of the library instance. + @throws Exception + **/ + AutogenLibOrder(List libraryList) throws Exception { + String[] libInstance = new String[3]; + LibraryClass[] libClassDeclList = null; + LibraryClass[] libClassConsmList = null; + + for (int i = 0; i < libraryList.size(); i++) { + // + // Add libraryInstance in to libInstanceList. + // + libInstance[0] = libraryList.get(i); + Map libDoc = GlobalData.getDoc(libInstance[0]); + SurfaceAreaQuery.push(libDoc); + libInstance[1] = SurfaceAreaQuery.getLibConstructorName(); + libInstance[2] = SurfaceAreaQuery.getLibDestructorName(); + libInstanceList.add(libInstance.clone()); + + // + // Add library instance and consumed library class list to + // libInstanceMap. + // + libClassConsmList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysConsumed); + if (libClassConsmList != null) { + String[] classStr = new String[libClassConsmList.length]; + for (int k = 0; k < libClassConsmList.length; k++) { + classStr[k] = libClassConsmList[k].getStringValue(); + } + if (this.libInstanceMap.containsKey(libInstance[0])) { + throw new Exception( + libInstance[0] + + "this library instance is already exist, please check you library instance list!"); + } else { + this.libInstanceMap.put(libInstance[0], classStr); + } + } + + // + // Add library class and library instance map. + // + libClassDeclList = SurfaceAreaQuery + .getLibraryClassArray(CommonDefinition.AlwaysProduced); + if (libClassDeclList != null) { + for (int j = 0; j < libClassDeclList.length; j++) { + if (this.libClassMap.containsKey(libClassDeclList[j] + .getStringValue())) { + System.out.println(libClassDeclList[j].getStringValue() + + " class is already implement by " + + this.libClassMap.get(libClassDeclList[j] + .getStringValue())); + throw new Exception(libClassDeclList + + " is already have library instance!"); + } else { + this.libClassMap.put(libClassDeclList[j] + .getStringValue(), libInstance[0]); + } + } + } + SurfaceAreaQuery.pop(); + } + + // + // Check is the library instance list meet the require; + // + for (int s = 0; s < this.libInstanceList.size(); s++) { + String[] libClass = this.libInstanceMap.get(this.libInstanceList + .get(s)); + if (libClass != null) { + for (int t = 0; t < libClass.length; t++) { + if (this.libClassMap.get(libClass[t]) == null) { + // + // Note: There exist a kind of module which depend on + // library class with no instance or whose instance will + // never be linked into the module. + // For this satuation, the module has the description of + // library class in MSA file but no description of + // corresponding library instance in MBD file. There + // will be a warnig message given here after a standard + // log way has been decided. + // + } + } + } + } + } + + /** + orderLibInstance + + This function reorder the library instance according the library class + dependency. + + @return List which content the ordered library instance. + **/ + List orderLibInstance() { + List orderList = new ArrayList(); + // + // Stack of node which track the library instance name ant its visiting + // flag. + // + List stackList = new ArrayList(); + int stackSize = 0; + String libInstance = null; + if (libInstanceList.size() < 0) { + return null; + } + + // + // Reorder the library instance. + // + for (int i = 0; i < libInstanceList.size(); i++) { + // + // If library instance is already in the order list skip it. + // + if (isInLibInstance(orderList, libInstanceList.get(i)[0])) { + continue; + } + + Node node = new Node(libInstanceList.get(i)[0], false); + // + // Use stack to reorder library instance. + // Push node to stack. + // + stackList.add(node); + while (stackList.size() > 0) { + stackSize = stackList.size() - 1; + // + // Pop the first node in stack. If the node flag has been visited + // add this node to orderlist and remove it from stack. + // + if (stackList.get(stackSize).isVisit) { + if (!isInLibInstance(orderList, + stackList.get(stackSize).nodeName)) { + orderList.add(stackList.get(stackSize).nodeName); + stackList.remove(stackSize); + } + + } else { + // + // Get the node value and set visit flag as true. + // + stackList.get(stackList.size() - 1).isVisit = true; + String[] libClassList = this.libInstanceMap.get(stackList + .get(stackSize).nodeName); + // + // Push the node dependence library instance to the stack. + // + if (libClassList != null) { + for (int j = 0; j < libClassList.length; j++) { + libInstance = this.libClassMap.get(libClassList[j]); + if (libInstance != null + && !isInLibInstance(orderList, libInstance)) { + // + // If and only if the currently library instance + // is not in stack and it have constructor or + // destructor function, push this library + // instacne in stack. + // + if (!isInStackList(stackList, this.libClassMap + .get(libClassList[j])) && isHaveConsDestructor(libInstance)) { + stackList.add(new Node(this.libClassMap + .get(libClassList[j]), false)); + } + } + } + } + } + } + } + return orderList; + } + + /** + isInLibInstance + + This function check does the library instance already in the list. + + @param list List of the library instance. + @param instanceName Name of library instance. + @return "true" the library instance in list | + "false" the library instance is not in list. + **/ + private boolean isInLibInstance(List list, String instanceName) { + for (int i = 0; i < list.size(); i++) { + if (instanceName.equalsIgnoreCase(list.get(i).toString())) { + return true; + } + } + return false; + } + + /** + isInStackList + + This function check if the node already in the stack. + + @param list Stack. + @param nodeName Name of node. + @return "true" if node have in stack | + "false" if node don't in stack. + **/ + private boolean isInStackList(List list, String nodeName) { + for (int i = 0; i < list.size(); i++) { + if (nodeName.equalsIgnoreCase(list.get(i).nodeName)) { + return true; + } + } + return false; + } + + /** + isHaveConsDestructor + + This function check if the library have constructor or destructor + function. + + @param libName Name of library + @return "true" if library have constructor or desconstructor | + "false" if library don't have constructor + and desconstructor. + **/ + private boolean isHaveConsDestructor (String libName){ + for (int i = 0; i < libInstanceList.size(); i++){ + if (libInstanceList.get(i)[0].equalsIgnoreCase(libName)){ + if (libInstanceList.get(i)[1] != null || libInstanceList.get(i)[2] != null){ + return true; + } + } + } + return false; + } +} + +/** + Node + + This class is used as stack node. + + **/ +class Node { + String nodeName; + + boolean isVisit; + + Node(String name, boolean isVisit) { + this.nodeName = name; + this.isVisit = false; + } +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/org/tianocore/build/autogen/CommonDefinition.java b/Tools/Source/GenBuild/org/tianocore/build/autogen/CommonDefinition.java new file mode 100644 index 0000000000..2490d97467 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/autogen/CommonDefinition.java @@ -0,0 +1,257 @@ +/** @file + CommonDefinition class. + + This class is to define some common marcos and funcions, which used by AutoGen. + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.build.autogen; + +/** + CommonDefinition + + This class is to define some common marcos, which used by AutoGen. + +**/ +public class CommonDefinition { + public final static String spdSuffix = ".spd"; + public final static String mbdSuffix = ".mbd"; + public final static String msaSuffix = ".msa"; + public final static String LibraryStr = "LIBRARY"; + public final static String autoGenHbegin = "extern int __make_me_compile_correctly;\r\n"; + public final static String include = "#include"; + public final static String autoGenCLine1 = "\r\n"; + + public final static String autoGenCLine2 = "const UINT8 _gDebugPropertyMask " + + "= DEBUG_PROPERTY_DEBUG_ASSERT_ENABLED" + + " | DEBUG_PROPERTY_DEBUG_PRINT_ENABLED" + + " | DEBUG_PROPERTY_DEBUG_CODE_ENABLED;\r\n"; + + public final static String autoGenCLine3 = "const UINTN _gModuleDefaultErrorLevel" + + " = EFI_D_ERROR | EFI_D_LOAD;\r\n"; + + public final static String autoGenHLine1 = "#define EFI_SPECIFICATION_VERSION 0x00020000\r\n"; + public final static String autoGenHVersionDefault = "#define EFI_SPECIFICATION_VERSION 0x00000000\r\n"; + public final static String autoGenHLine2 = "#define EDK_RELEASE_VERSION 0x00090000\r\n"; + public final static String autoGenHReleaseDefault = "#define EDK_RELEASE_VERSION 0x00000000\r\n"; + + public final static String includeAutogenH = "#include \r\n" ; + + public final static String gEfi = "gEfi"; + public final static String protocolGuid = "ProtocolGuid"; + public final static String ppiGuid = "PpiGuid"; + public final static String guidGuid = "Guid"; + + // + // AutoGen.h and AutoGen.c file's header + // + public final static String autogenHNotation = + "/**\r\n" + + " DO NOT EDIT\r\n" + + " FILE auto-generated by GenBuild tasks\r\n" + + " Module name:\r\n" + + " AutoGen.h\r\n" + + " Abstract:" + + " Auto-generated AutoGen.h for building module or library.\r\n" + + "**/\r\n\r\n"; + + public final static String autogenCNotation = + "/**\r\n" + + " DO NOT EDIT\r\n" + + " FILE auto-generated by GenBuild tasks\r\n" + + " Module name:\r\n" + + " AutoGen.c\r\n" + + " Abstract:" + + " Auto-generated AutoGen.c for building module or library.\r\n" + + "**/\r\n\r\n"; + + // + // module type + // + public final static int ModuleTypeBase = 0; + public final static int ModuleTypeSec = 1; + public final static int ModuleTypePeiCore = 2; + public final static int ModuleTypePeim = 3; + public final static int ModuleTypeDxeCore = 4; + public final static int ModuleTypeDxeDriver = 5; + public final static int ModuleTypeDxeRuntimeDriver = 6; + public final static int ModuleTypeDxeSmmDriver = 7; + public final static int ModuleTypeDxeSalDriver = 8; + public final static int ModuleTypeUefiDriver = 9; + public final static int ModuleTypeUefiApplication = 10; + public final static int ModuleTypeUnknown = 11; + + + // + // component type + // + public final static int ComponentTypeNull = 0; + public final static int ComponentTypeApriori = 1; + public final static int ComponentTypeSec = 2; + public final static int ComponentTypeLibrary = 3; + public final static int ComponentTypeFvImageFile = 4; + public final static int ComponentTypeBsDriver = 5; + public final static int ComponentTypeRtDriver = 6; + public final static int ComponentTypeSalRtDriver =7; + public final static int ComponentTypePe32Peim = 8; + public final static int ComponentTypePicPeim =9; + public final static int ComponentTypeCombinedPeimDriver =10; + public final static int ComponentTypePeiCore = 11; + public final static int ComponentTypeDxeCore = 12; + public final static int ComponentTypeApplication = 13; + public final static int ComponentTypeBsDriverEfi = 14; + public final static int ComponentTypeShellApp = 15; + public final static int ComponentTypeBinary =16; + public final static int ComponentTypeLogo = 17; + public final static int ComponentTypeCustomBuild = 18; + public final static int ComponentTypeUnknown = 19; + + + // + // Usaged style + // + public final static String AlwaysConsumed = "ALWAYS_CONSUMED"; + public final static String AlwaysProduced = "ALWAYS_PRODUCED"; + + + public static class MyEnum { + String moduleTypeStr; + int type; + + MyEnum (String str, int type) { + this.type = type; + this.moduleTypeStr = str; + } + + int ForInt(String str) { + if (str.equals(this.moduleTypeStr)) { + return this.type; + } else + return -1; + } + } + + // + // Module type + // + public static final MyEnum[] moduleEnum = new MyEnum[] { + new MyEnum("BASE", ModuleTypeBase), + new MyEnum("SEC", ModuleTypeSec), + new MyEnum("PEI_CORE", ModuleTypePeiCore), + new MyEnum("PEIM", ModuleTypePeim), + new MyEnum("DXE_CORE", ModuleTypeDxeCore), + new MyEnum("DXE_DRIVER", ModuleTypeDxeRuntimeDriver), + new MyEnum("DXE_RUNTIME_DRIVER", ModuleTypeDxeRuntimeDriver), + new MyEnum("DXE_SAL_DRIVER", ModuleTypeDxeSmmDriver), + new MyEnum("DXE_SMM_DRIVER", ModuleTypeDxeSalDriver), + new MyEnum("UEFI_DRIVER", ModuleTypeUefiDriver), + new MyEnum("UEFI_APPLICATION", ModuleTypeUefiApplication) }; + + // + // Component type + // + public static final MyEnum[] componentEnum = new MyEnum[]{ + new MyEnum("APRIORI", ComponentTypeApriori), + new MyEnum("SEC", ComponentTypeSec), + new MyEnum("LIBRARY", ComponentTypeLibrary), + new MyEnum("FV_IMAGE_FILE", ComponentTypeFvImageFile), + new MyEnum("BS_DRIVER", ComponentTypeBsDriver), + new MyEnum("RT_DRIVER", ComponentTypeRtDriver), + new MyEnum("SAL_RT_DRIVER", ComponentTypeSalRtDriver), + new MyEnum("PE32_PEIM", ComponentTypePe32Peim), + new MyEnum("PIC_PEIM", ComponentTypePicPeim), + new MyEnum("COMBINED_PEIM_DRIVER", ComponentTypeCombinedPeimDriver), + new MyEnum("PEI_CORE", ComponentTypePeiCore), + new MyEnum("DXE_CORE", ComponentTypeDxeCore), + new MyEnum("APPLICATION", ComponentTypeApplication), + new MyEnum("BS_DRIVER_EFI", ComponentTypeBsDriverEfi), + new MyEnum("SHELLAPP", ComponentTypeShellApp), + new MyEnum("BINARY", ComponentTypeBinary), + new MyEnum("LOGO", ComponentTypeLogo), + new MyEnum("CUSTOM_BUILD", ComponentTypeCustomBuild) + }; + + /** + getModuleType + + This function get the module type value according module type string. + + @param moduleTypeStr String of modlue type. + @return + **/ + static public int getModuleType(String moduleTypeStr) { + int returnValue = -1; + for (int i = 0; i < CommonDefinition.moduleEnum.length; i++) { + returnValue = CommonDefinition.moduleEnum[i].ForInt(moduleTypeStr); + if (returnValue != -1) { + return returnValue; + } + } + return CommonDefinition.ModuleTypeUnknown; + } + + /** + getComponentType + + This function get the component type value according commponet type + string. + + @param componentTypeStr String of component type. + @return + **/ + static public int getComponentType (String componentTypeStr){ + int returnValue = -1; + for (int i = 0; i < CommonDefinition.componentEnum.length; i++) { + returnValue = CommonDefinition.componentEnum[i].ForInt(componentTypeStr); + if (returnValue != -1) { + return returnValue; + } + } + return CommonDefinition.ComponentTypeUnknown; + } + + /** + getComponentTypeString + + This function get the commponet type string according component type value. + + @param componentType Integer value of component type. + @return + **/ + static public String getComponentTypeString (int componentType) { + if ((componentType > CommonDefinition.ComponentTypeUnknown) || + (componentType < CommonDefinition.ComponentTypeNull)) { + return null; + } + for (int index = 0; index < CommonDefinition.componentEnum.length; index ++) { + if (componentType == CommonDefinition.componentEnum[index].type) { + return CommonDefinition.componentEnum[index].moduleTypeStr; + } + } + return null; + } + + /** + isLibraryComponent + + This function is to check does componet is library according to commponet + type value. + + @param componentType Integer value of component type. + @return + **/ + static public boolean isLibraryComponent (int componentType) { + if (ComponentTypeLibrary == componentType) { + return true; + } + return false; + } +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdModuleIdentification.java b/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdModuleIdentification.java new file mode 100644 index 0000000000..261cf58a35 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdModuleIdentification.java @@ -0,0 +1,131 @@ +/** @file + Java class FpdModuleIdentification is used to present a module identification + from BaseName, GUID, Version, PackageName, and ARCH. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.build.fpd; + +/** + This class is used to identify a module with BaseName, GUID, Version, PackageName + and ARCH. + + @since GenBuild 1.0 + **/ +public class FpdModuleIdentification { + + private String arch; + + private String fvBinding; + + private String baseName; + + private String packageName; + + private String guid; + + private String version; + + private String sequence; + + /** + + @param baseName the base name of the module + @param guid the GUID of the module + @param arch the ARCH of the module + **/ + public FpdModuleIdentification(String baseName, String guid, String arch){ + this.baseName = baseName; + this.guid = guid; + this.arch = arch; + } + + /** + Override java.lang.Object#equals. + +

Currently, use BaseName and ARCH to identify a module. It will enhance + in the next version.

+ + @see java.lang.Object#equals(java.lang.Object) + **/ + public boolean equals(Object obj) { + if (obj instanceof FpdModuleIdentification) { + FpdModuleIdentification moduleIdObj = (FpdModuleIdentification)obj; + if ( baseName.equalsIgnoreCase(moduleIdObj.baseName) && arch.equalsIgnoreCase(moduleIdObj.arch)) { + return true; + } + // TBD + return false; + } + else { + return super.equals(obj); + } + } + + public void setArch(String arch) { + this.arch = arch; + } + + public void setFvBinding(String fvBinding) { + this.fvBinding = fvBinding; + } + + public void setSequence(String sequence) { + this.sequence = sequence; + } + + public String toString(){ + return arch + ":" + guid + "_" + baseName; + } + + public void setBaseName(String baseName) { + this.baseName = baseName; + } + + public void setGuid(String guid) { + this.guid = guid; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getArch() { + return arch; + } + + public String getBaseName() { + return baseName; + } + + public String getFvBinding() { + return fvBinding; + } + + public String getGuid() { + return guid; + } + + public String getPackageName() { + return packageName; + } + + public String getSequence() { + return sequence; + } + + public String getVersion() { + return version; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java b/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java new file mode 100644 index 0000000000..99b7242ebc --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/fpd/FpdParserTask.java @@ -0,0 +1,808 @@ +/** @file + This file is ANT task FpdParserTask. + + FpdParserTask is used to parse FPD (Framework Platform Description) and generate + build.out.xml. It is for Package or Platform build use. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.build.fpd; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Property; +import org.apache.xmlbeans.XmlObject; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.OutputManager; +import org.tianocore.build.global.OverrideProcess; +import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.build.pcd.action.CollectPCDAction; +import org.tianocore.build.pcd.action.ActionMessage; +import org.tianocore.BuildOptionsDocument; +import org.tianocore.FrameworkPlatformDescriptionDocument; +import org.tianocore.ModuleSADocument; + + +/** + FpdParserTask is an ANT task. The main function is parsing FPD + XML file and generating its ANT build script for Platform or Package. + +

The usage is (take NT32 Platform for example):

+ +
+    <FPDParser fpdfilename="Build\Nt32.fpd" />
+  
+ +

The task will initialize all information through parsing Framework Database, + SPD, Tool chain configuration files.

+ + @since GenBuild 1.0 +**/ +public class FpdParserTask extends Task { + + /// + /// FV dir: ${PLATFORM_DIR}/Build/FV + /// + public static final String FV_OUTPUT_DIR = "${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "FV"; + + private File fpdFilename; + + private File guiddatabase; + + /// + /// Keep platform buildoption information + /// + public static XmlObject platformBuildOptions = null; + + /// + /// Mapping from modules identification to out put file name + /// + private Map outfiles = new LinkedHashMap(); + + /// + /// Mapping from FV name to its modules + /// + private Map > fvs = new HashMap >(); + + /// + /// Mapping from sequence number to its modules + /// + private Map > sequences = new HashMap >(); + + /// + /// FpdParserTask can specify some ANT properties. + /// + private Vector properties = new Vector(); + + private String info = "====================================================================\n" + + "DO NOT EDIT \n" + + "File auto-generated by build utility\n" + + "\n" + + "Abstract:\n" + + "Auto-generated ANT build file for building of EFI Modules/Platforms\n" + + "====================================================================="; + + /** + Public construct method. It is necessary for ANT task. + **/ + public FpdParserTask () { + } + + /** + ANT task's entry method. The main steps is described as following: + +
    +
  • Initialize global information (Framework DB, SPD files and all MSA files + listed in SPD). This step will execute only once in whole build process;
  • +
  • Parse specified FPD file;
  • +
  • Generate FV.inf files;
  • +
  • Generate build.out.xml file for Flatform or Package build;
  • +
  • Collect PCD information.
  • +
+ + @throws BuildException + Surface area is not valid. + **/ + public void execute() throws BuildException { + OutputManager.update(getProject()); + // + // Parse DB and SPDs files. Initialize Global Data + // + GlobalData.initInfo("Tools" + File.separatorChar + "Conf" + File.separatorChar + "FrameworkDatabase.db", getProject() + .getProperty("WORKSPACE_DIR")); + // + // Parse FPD file + // + parseFpdFile(); + // + // Gen Fv.inf files + // + genFvInfFiles(); + // + // Gen build.xml + // + genBuildFile(); + // + // Collect PCD information + // + collectPCDInformation (); + } + + /** + Generate Fv.inf files. The Fv.inf file is composed with four + parts: Options, Attributes, Components and Files. The Fv.inf files + will be under ${PLATFOMR_DIR}\Build\Fv. + + @throws BuildException + File write FV.inf files error. + **/ + private void genFvInfFiles() throws BuildException{ + String[] validFv = SurfaceAreaQuery.getFpdValidImageNames(); + for (int i = 0; i < validFv.length; i++) { + getProject().setProperty("FV_FILENAME", validFv[i].toUpperCase()); + // + // Get all global variables from FPD and set them to properties + // + String[][] globalVariables = SurfaceAreaQuery + .getFpdGlobalVariable(); + for (int j = 0; j < globalVariables.length; j++) { + getProject().setProperty(globalVariables[j][0], + globalVariables[j][1]); + } + + File fvFile = new File(getProject().replaceProperties( + FV_OUTPUT_DIR + File.separatorChar + validFv[i].toUpperCase() + + ".inf")); + fvFile.getParentFile().mkdirs(); + + try { + FileWriter fw = new FileWriter(fvFile); + BufferedWriter bw = new BufferedWriter(fw); + // + // Options + // + String[][] options = SurfaceAreaQuery.getFpdOptions(validFv[i]); + if (options.length > 0) { + bw.write("[options]"); + bw.newLine(); + for (int j = 0; j < options.length; j++) { + StringBuffer str = new StringBuffer(100); + str.append(options[j][0]); + while (str.length() < 40) { + str.append(' '); + } + str.append("= "); + str.append(options[j][1]); + bw.write(getProject().replaceProperties(str.toString())); + bw.newLine(); + } + bw.newLine(); + } + // + // Attributes; + // + String[][] attributes = SurfaceAreaQuery + .getFpdAttributes(validFv[i]); + if (attributes.length > 0) { + bw.write("[attributes]"); + bw.newLine(); + for (int j = 0; j < attributes.length; j++) { + StringBuffer str = new StringBuffer(100); + str.append(attributes[j][0]); + while (str.length() < 40) { + str.append(' '); + } + str.append("= "); + str.append(attributes[j][1]); + bw + .write(getProject().replaceProperties( + str.toString())); + bw.newLine(); + } + bw.newLine(); + } + // + // Components + // + String[][] components = SurfaceAreaQuery + .getFpdComponents(validFv[i]); + if (components.length > 0) { + bw.write("[components]"); + bw.newLine(); + for (int j = 0; j < components.length; j++) { + StringBuffer str = new StringBuffer(100); + str.append(components[j][0]); + while (str.length() < 40) { + str.append(' '); + } + str.append("= "); + str.append(components[j][1]); + bw + .write(getProject().replaceProperties( + str.toString())); + bw.newLine(); + } + bw.newLine(); + } + // + // Files + // + Set filesSet = fvs.get(validFv[i].toUpperCase()); + if (filesSet != null) { + FpdModuleIdentification[] files = filesSet.toArray(new FpdModuleIdentification[filesSet + .size()]); + bw.write("[files]"); + bw.newLine(); + for (int j = 0; j < files.length; j++) { + String str = outfiles.get(files[j]); + bw.write(getProject().replaceProperties( + "EFI_FILE_NAME = " + str)); + bw.newLine(); + } + } + bw.flush(); + bw.close(); + fw.close(); + } catch (Exception e) { + throw new BuildException("Generate Fv.inf file failed. \n" + e.getMessage()); + } + } + } + + /** + Parse FPD file. + + @throws BuildException + FPD file is not valid. + **/ + private void parseFpdFile() throws BuildException { + try { + FrameworkPlatformDescriptionDocument doc = (FrameworkPlatformDescriptionDocument) XmlObject.Factory + .parse(fpdFilename); + if ( ! doc.validate() ){ + throw new BuildException("FPD file is invalid."); + } + platformBuildOptions = doc.getFrameworkPlatformDescription() + .getBuildOptions(); + HashMap map = new HashMap(); + map.put("FrameworkPlatformDescription", doc); + SurfaceAreaQuery.setDoc(map); + // + // Parse all list modules SA + // + parseModuleSAFiles(); + SurfaceAreaQuery.setDoc(map); + } catch (Exception e) { + throw new BuildException("Load FPD file [" + fpdFilename.getPath() + + "] error. \n" + e.getMessage()); + } + } + + /** + Parse all modules listed in FPD file. + **/ + private void parseModuleSAFiles() { + ModuleSADocument.ModuleSA[] moduleSAs = SurfaceAreaQuery + .getFpdModules(); + // + // For every Module lists in FPD file. + // + for (int i = 0; i < moduleSAs.length; i++) { + String defaultFv = "NULL"; + String defaultArch = "IA32"; + String baseName = moduleSAs[i].getModuleName(); + if (baseName == null) { + System.out.println("Warning: Module Name is not specified."); + continue; + } + String fvBinding = moduleSAs[i].getFvBinding(); + // + // If the module do not specify any FvBinding, use the default value. + // Else update the default FvBinding value to this value. + // + if (fvBinding == null) { + fvBinding = defaultFv; + } + else { + defaultFv = fvBinding; + } + String arch; + // + // If the module do not specify any Arch, use the default value. + // Else update the default Arch value to this value. + // + if (moduleSAs[i].getArch() == null ){ + arch = defaultArch; + } + else { + arch = moduleSAs[i].getArch().toString(); + defaultArch = arch; + } + Map msaMap = GlobalData.getNativeMsa(baseName); + Map mbdMap = GlobalData.getNativeMbd(baseName); + Map map = new HashMap(); + // + // Whether the Module SA has parsed before or not + // + if (!GlobalData.isModuleParsed(baseName)) { + OverrideProcess op = new OverrideProcess(); + // + // using overriding rules + // Here we can also put platform Build override + // + map = op.override(mbdMap, msaMap); + Map overrideMap = op.override( + getPlatformOverrideInfo(moduleSAs[i]), + OverrideProcess.deal(map)); + GlobalData.registerModule(baseName, overrideMap); + } else { + map = GlobalData.getDoc(baseName); + } + SurfaceAreaQuery.setDoc(map); + String guid = SurfaceAreaQuery.getModuleGuid(); + String componentType = SurfaceAreaQuery.getComponentType(); + FpdModuleIdentification moduleId = new FpdModuleIdentification(baseName, guid, arch); + updateFvs(fvBinding, moduleId); + outfiles.put(moduleId, "${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + + "${TARGET}" + File.separatorChar + arch + + File.separatorChar + guid + "-" + baseName + + getSuffix(componentType)); + } + } + + /** + Add the current module to corresponding FV. + + @param fvName current FV name + @param moduleName current module identification + **/ + private void updateFvs(String fvName, FpdModuleIdentification moduleName) { + String upcaseFvName = fvName.toUpperCase(); + if (fvs.containsKey(upcaseFvName)) { + Set set = fvs.get(upcaseFvName); + set.add(moduleName); + } else { + Set set = new LinkedHashSet(); + set.add(moduleName); + fvs.put(upcaseFvName, set); + } + } + + /** + Get the suffix based on component type. Current relationship are listed: + +
+        ComponentType   Suffix
+           APPLICATION          .APP
+           SEC                  .SEC
+           PEI_CORE             .PEI
+           PE32_PEIM            .PEI
+           RELOCATABLE_PEIM     .PEI
+           PIC_PEIM             .PEI
+           COMBINED_PEIM_DRIVER .PEI
+           TE_PEIM              .PEI
+           LOGO                 .FFS
+           others               .DXE
+      
+ + @param componentType component type + @return + @throws BuildException + If component type is null + **/ + public static String getSuffix(String componentType) throws BuildException{ + if (componentType == null) { + throw new BuildException("Component type is not specified."); + } + String str = ".DXE"; + if (componentType.equalsIgnoreCase("APPLICATION")) { + str = ".APP"; + } else if (componentType.equalsIgnoreCase("SEC")) { + str = ".SEC"; + } else if (componentType.equalsIgnoreCase("PEI_CORE")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("PE32_PEIM")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("RELOCATABLE_PEIM")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("PIC_PEIM")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("COMBINED_PEIM_DRIVER")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("TE_PEIM")) { + str = ".PEI"; + } else if (componentType.equalsIgnoreCase("LOGO")) { + str = ".FFS"; + } + return str; + } + + /** + Parse module surface are info described in FPD file and put them into map. + + @param sa module surface area info descibed in FPD file + @return map list with top level elements + **/ + private Map getPlatformOverrideInfo( + ModuleSADocument.ModuleSA sa) { + Map map = new HashMap(); + map.put("SourceFiles", sa.getSourceFiles()); + map.put("Includes", sa.getIncludes()); + map.put("Libraries", sa.getLibraries()); + map.put("Protocols", sa.getProtocols()); + map.put("Events", sa.getEvents()); + map.put("Hobs", sa.getHobs()); + map.put("PPIs", sa.getPPIs()); + map.put("Variables", sa.getVariables()); + map.put("BootModes", sa.getBootModes()); + map.put("SystemTables", sa.getSystemTables()); + map.put("DataHubs", sa.getDataHubs()); + map.put("Formsets", sa.getFormsets()); + map.put("Guids", sa.getGuids()); + map.put("Externs", sa.getExterns()); + map.put("BuildOptions", platformBuildOptions); + return map; + } + + /** + Generate build.out.xml file. + + @throws BuildException + build.out.xml XML document create error + **/ + private void genBuildFile() throws BuildException { + DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder dombuilder = domfac.newDocumentBuilder(); + Document document = dombuilder.newDocument(); + Comment rootComment = document.createComment(info); + // + // create root element and its attributes + // + Element root = document.createElement("project"); + root.setAttribute("name", getProject().getProperty("PLATFORM")); + root.setAttribute("default", "main"); + root.setAttribute("basedir", "."); + // + // element for External ANT tasks + // + root.appendChild(document.createComment("Apply external ANT tasks")); + Element ele = document.createElement("taskdef"); + ele.setAttribute("resource", "GenBuild.tasks"); + root.appendChild(ele); + + ele = document.createElement("taskdef"); + ele.setAttribute("resource", "frameworktasks.tasks"); + root.appendChild(ele); + + ele = document.createElement("property"); + ele.setAttribute("environment", "env"); + root.appendChild(ele); + // + // Default Target + // + root.appendChild(document.createComment("Default target")); + ele = document.createElement("target"); + ele.setAttribute("name", "main"); + ele.setAttribute("depends", "modules, fvs"); + root.appendChild(ele); + // + // Modules Target + // + root.appendChild(document.createComment("Modules target")); + ele = document.createElement("target"); + ele.setAttribute("name", "modules"); + + Set set = outfiles.keySet(); + Iterator iter = set.iterator(); + while (iter.hasNext()) { + FpdModuleIdentification moduleId = (FpdModuleIdentification) iter.next(); + String baseName = moduleId.getBaseName(); + Element moduleEle = document.createElement("ant"); + moduleEle.setAttribute("antfile", GlobalData + .getModulePath(baseName) + + File.separatorChar + "build.xml"); + moduleEle.setAttribute("target", baseName); + // + // ARCH + // + Element property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", moduleId.getArch()); + moduleEle.appendChild(property); + // + // PACKAGE_DIR + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(baseName)); + moduleEle.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData + .getPackageNameForModule(baseName)); + moduleEle.appendChild(property); + ele.appendChild(moduleEle); + } + root.appendChild(ele); + // + // FVS Target + // + root.appendChild(document.createComment("FVs target")); + ele = document.createElement("target"); + ele.setAttribute("name", "fvs"); + + String[] validFv = SurfaceAreaQuery.getFpdValidImageNames(); + for (int i = 0; i < validFv.length; i++) { + String inputFile = FV_OUTPUT_DIR + "" + File.separatorChar + + validFv[i].toUpperCase() + ".inf"; + Element fvEle = document.createElement("genfvimage"); + fvEle.setAttribute("infFile", inputFile); + ele.appendChild(fvEle); + Element moveEle = document.createElement("move"); + moveEle.setAttribute("file", validFv[i].toUpperCase() + ".fv"); + moveEle.setAttribute("todir", FV_OUTPUT_DIR); + ele.appendChild(moveEle); + } + root.appendChild(ele); + + boolean isUnified = false; + BuildOptionsDocument.BuildOptions buildOptions = (BuildOptionsDocument.BuildOptions)platformBuildOptions; + if (buildOptions.getOutputDirectory() != null){ + if (buildOptions.getOutputDirectory().getIntermediateDirectories() != null){ + if (buildOptions.getOutputDirectory().getIntermediateDirectories().toString().equalsIgnoreCase("UNIFIED")){ + isUnified = true; + } + } + } + // + // Clean Target + // + root.appendChild(document.createComment("Clean target")); + ele = document.createElement("target"); + ele.setAttribute("name", "clean"); + + if (isUnified) { + Element cleanEle = document.createElement("delete"); + cleanEle.setAttribute("includeemptydirs", "true"); + Element filesetEle = document.createElement("fileset"); + filesetEle.setAttribute("dir", getProject().getProperty("PLATFORM_DIR") + File.separatorChar + "Build" + File.separatorChar + "${TARGET}"); + filesetEle.setAttribute("includes", "**/OUTPUT/**"); + cleanEle.appendChild(filesetEle); + ele.appendChild(cleanEle); + } + else { + set = outfiles.keySet(); + iter = set.iterator(); + while (iter.hasNext()) { + FpdModuleIdentification moduleId = (FpdModuleIdentification) iter.next(); + String baseName = moduleId.getBaseName(); + + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", GlobalData + .getModulePath(baseName) + + File.separatorChar + "build.xml"); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element moduleEle = document.createElement("ant"); + moduleEle.setAttribute("antfile", GlobalData + .getModulePath(baseName) + + File.separatorChar + "build.xml"); + moduleEle.setAttribute("target", baseName + "_clean"); + // + // ARCH + // + Element property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", moduleId.getArch()); + moduleEle.appendChild(property); + // + // PACKAGE_DIR + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(baseName)); + moduleEle.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData + .getPackageNameForModule(baseName)); + moduleEle.appendChild(property); + elseEle.appendChild(moduleEle); + ifEle.appendChild(elseEle); + ele.appendChild(ifEle); + } + } + root.appendChild(ele); + // + // Deep Clean Target + // + root.appendChild(document.createComment("Clean All target")); + ele = document.createElement("target"); + ele.setAttribute("name", "cleanall"); + + if (isUnified) { + Element cleanAllEle = document.createElement("delete"); + cleanAllEle.setAttribute("dir", getProject().getProperty("PLATFORM_DIR") + File.separatorChar + "Build" + File.separatorChar + "${TARGET}"); + ele.appendChild(cleanAllEle); + } + else { + set = outfiles.keySet(); + iter = set.iterator(); + while (iter.hasNext()) { + FpdModuleIdentification moduleId = (FpdModuleIdentification) iter.next(); + String baseName = moduleId.getBaseName(); + + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", GlobalData + .getModulePath(baseName) + + File.separatorChar + "build.xml"); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element moduleEle = document.createElement("ant"); + moduleEle.setAttribute("antfile", GlobalData + .getModulePath(baseName) + + File.separatorChar + "build.xml"); + moduleEle.setAttribute("target", baseName + "_cleanall"); + // + // ARCH + // + Element property = document.createElement("property"); + property.setAttribute("name", "ARCH"); + property.setAttribute("value", moduleId.getArch()); + moduleEle.appendChild(property); + // + // PACKAGE_DIR + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE_DIR"); + property.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + + GlobalData.getPackagePathForModule(baseName)); + moduleEle.appendChild(property); + // + // PACKAGE + // + property = document.createElement("property"); + property.setAttribute("name", "PACKAGE"); + property.setAttribute("value", GlobalData + .getPackageNameForModule(baseName)); + moduleEle.appendChild(property); + elseEle.appendChild(moduleEle); + ifEle.appendChild(elseEle); + ele.appendChild(ifEle); + } + } + root.appendChild(ele); + + document.appendChild(rootComment); + document.appendChild(root); + // + // Prepare the DOM document for writing + // + Source source = new DOMSource(document); + // + // Prepare the output file + // + File file = new File(getProject().getProperty("PLATFORM_DIR") + + File.separatorChar + "build.out.xml"); + // + // generate all directory path + // + (new File(file.getParent())).mkdirs(); + Result result = new StreamResult(file); + // + // Write the DOM document to the file + // + Transformer xformer = TransformerFactory.newInstance() + .newTransformer(); + xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + xformer.setOutputProperty(OutputKeys.INDENT, "yes"); + xformer.transform(source, result); + } catch (Exception ex) { + throw new BuildException("Generate build.out.xml failed. \n" + ex.getMessage()); + } + } + + /** + Add a property. + + @param p property + **/ + public void addProperty(Property p) { + properties.addElement(p); + } + + /** + Get FPD file name. + + @return FPD file name. + **/ + public File getFpdFilename() { + return fpdFilename; + } + + /** + Set FPD file name. + + @param fpdFilename FPD file name + **/ + public void setFpdFilename(File fpdFilename) { + this.fpdFilename = fpdFilename; + } + + public File getGuiddatabase() { + return guiddatabase; + } + + public void setGuiddatabase(File guiddatabase) { + this.guiddatabase = guiddatabase; + } + + public void collectPCDInformation() { + CollectPCDAction collectAction = new CollectPCDAction (); + // + // Set memory database log file path. It should be put into same directory with FPD file. + // + GlobalData.getPCDMemoryDBManager().setLogFileName( + fpdFilename.getPath() + ".PCDMemroyDatabaseLog.txt" + ); + // + // Collect all PCD information from FPD to MSA, and get help information from SPD. + // These all information will be stored into memory database for future usage such + // as autogen. + // + try { + collectAction.perform ( + getProject().getProperty("WORKSPACE_DIR"), + fpdFilename.getPath(), + ActionMessage.NULL_MESSAGE_LEVEL + ); + } catch (Exception exp) { + throw new BuildException (exp.getMessage()); + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/DpFile.java b/Tools/Source/GenBuild/org/tianocore/build/global/DpFile.java new file mode 100644 index 0000000000..78cde75604 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/DpFile.java @@ -0,0 +1,129 @@ +/** @file +This file is used to define class which represents dependency file in ANT task + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.global; + +import org.apache.tools.ant.types.DataType; +import org.apache.tools.ant.types.Path; + +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.LineNumberReader; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + DpFile is a ANT DataType which can be used to specify dependency files from + a file list file, from file list string separated by space, comma or semi-comma, + or from file name with absolute path + **/ +public class DpFile extends DataType { + /// + /// keep the list of files path + /// + private List nameList = new ArrayList(); + + /** + Empty constructor just in case + **/ + public DpFile() { + } + + /** + Empty execute method of ANT task, just in case + **/ + public void execute() { + } + + /** + Standard set method of ANT task/datatype, for ListFile attribute. It simply + fetch one file path a line from specified list file, and put them in nameList + + @param fileListFile file which contains a file list, one file a line, + with full path + **/ + public void setListFile(String fileListFile) { + File file = new File(fileListFile); + if (!file.exists()) { + return; + } + + try { + FileReader fileReader = new FileReader(file); + LineNumberReader lineReader = new LineNumberReader(fileReader); + + String filePath = null; + while ((filePath = lineReader.readLine()) != null) { + filePath = filePath.trim(); + if (filePath.length() == 0) { + continue; + } + this.nameList.add(filePath); + } + + lineReader.close(); + fileReader.close(); + } catch (IOException e) { + System.out.println (e.getMessage()); + } + } + + /** + Standard set method of ANT task/datatype, for List attribute. + + @param fileList string with file pathes separated by space, comma, + or semi-comma + **/ + public void setList(String fileList) { + // + // space, comma or semi-comma separated files list + // + Pattern pattern = Pattern.compile("([^ ,;\n\r]++)[ ,;\n\r]*+"); + Matcher matcher = pattern.matcher(fileList); + + while (matcher.find()) { + // + // keep each file name before " ,;\n\r" + // + String filePath = fileList.substring(matcher.start(1), matcher.end(1)).trim(); + if (filePath.length() == 0) { + continue; + } + nameList.add(Path.translateFile(filePath)); + } + + } + + /** + Standard set method of ANT task/datatype, for Name attribute. + + @param fileName string of a file full path + **/ + public void setName(String fileName) { + this.nameList.add(fileName); + } + + /** + Fetch the file name list. + + @returns A string list which contains file names specified to check dependnecy + **/ + public List getList() { + return this.nameList; + } +} + + diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/DpFileList.java b/Tools/Source/GenBuild/org/tianocore/build/global/DpFileList.java new file mode 100644 index 0000000000..8b4b4a0add --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/DpFileList.java @@ -0,0 +1,50 @@ +/** @file +This file is used to nest elements corresponding to DpFile + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.global; + +import java.util.ArrayList; +import java.util.List; + +/** + DpFileList is a container of Dpfile at the point of ANT task/datatype + **/ +public class DpFileList { + /// + /// Keep all the file names from all nested DpFile + /// + List nameList = new ArrayList(); + + /** + Empty constructor just in case + **/ + public DpFileList() { + } + + /** + Empty execute method of ANT task. ANT will call it even we don't need it. + **/ + public void execute() { + } + + /** + Standard add method of ANT task, for nested DpFile type of elements. It just + simply fetch the files list from DpFile and put them in its own nameList. + + @param f a DpFile object which will be instantiated by ANT + **/ + public void addConfiguredFile(DpFile f) { + this.nameList.addAll(f.getList()); + } +} + diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/GlobalData.java b/Tools/Source/GenBuild/org/tianocore/build/global/GlobalData.java new file mode 100644 index 0000000000..611758a4ef --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/GlobalData.java @@ -0,0 +1,637 @@ +/** @file + GlobalData class. + + GlobalData provide initializing, instoring, querying and update global data. + It is a bridge to intercommunicate between multiple component, such as AutoGen, + PCD and so on. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.build.global; + +import java.io.File; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.apache.tools.ant.BuildException; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.FrameworkDatabaseDocument; +import org.tianocore.MsaFilesDocument; +import org.tianocore.PackageListDocument; +import org.tianocore.PackageSurfaceAreaDocument; +import org.tianocore.MsaHeaderDocument.MsaHeader; +import org.tianocore.MsaLibHeaderDocument.MsaLibHeader; +import org.tianocore.build.pcd.entity.MemoryDatabaseManager; +import org.tianocore.build.autogen.CommonDefinition; +import org.tianocore.build.fpd.FpdParserTask; + +/** + GlobalData provide initializing, instoring, querying and update global data. + It is a bridge to intercommunicate between multiple component, such as AutoGen, + PCD and so on. + +

Note that all global information are initialized incrementally. All data will + parse and record only it is necessary during build time.

+ + @since GenBuild 1.0 +**/ +public class GlobalData { + + /// + /// means no surface area information for module + /// + public static final int NO_SA = 0; + + /// + /// means only MSA + /// + public static final int ONLY_MSA = 1; + + /// + /// means only Library MSA + /// + public static final int ONLY_LIBMSA = 2; + + /// + /// means both MSA and MBD + /// + public static final int MSA_AND_MBD = 3; + + /// + /// means both Library MSA and Library MBD + /// + public static final int LIBMSA_AND_LIBMBD = 4; + + /// + /// Be used to ensure Global data will be initialized only once. + /// + public static boolean globalFlag = false; + + /// + /// Record current WORKSPACE Directory + /// + private static String workspaceDir = ""; + + /// + /// Two columns: Package Name (Key), Package Path(ralative to WORKSPACE) + /// + private static final Map packageInfo = new HashMap(); + + /// + /// spdTable + /// Key: Package Name, Value: SPD detail info + /// + private static final Map spdTable = new HashMap(); + + /// + /// Three columns: + /// 1. Module Name | BaseName (Key) + /// 2. Module Path + Msa file name (relative to Package) + /// 3. Package Name (This module belong to which package) + /// + private static final Map moduleInfo = new HashMap(); + + /// + /// List all libraries for current build module + /// Key: Library BaseName, Value: output library path+name + /// + private static final Map libraries = new HashMap(); + + /// + /// Store every module's relative library instances BaseName + /// Key: Module BaseName, Value: All library instances module depends on. + /// + private static final Map > moduleLibraryMap = new HashMap >(); + + /// + /// Key: Module BaseName, Value: original MSA info + /// + private static final Map > nativeMsa = new HashMap >(); + + /// + /// Key: Module BaseName, Value: original MBD info + /// + private static final Map > nativeMbd = new HashMap >(); + + /// + /// Two columns: Module Name or Base Name as Key + /// Value is a HashMap with overridden data from MSA/MBD or/and Platform + /// + private static final Map > parsedModules = new HashMap >(); + + /// + /// List all built Module; Value is Module BaseName + Arch. TBD + /// + private static final Set builtModules = new HashSet(); + + /// + /// Library instance information table which recored the library and it's + /// constructor and distructor function + /// + private static final Map libInstanceInfo = new HashMap(); + + /// + /// PCD memory database stored all PCD information which collected from FPD,MSA and SPD. + /// + private static final MemoryDatabaseManager pcdDbManager = new MemoryDatabaseManager(); + + /** + Query the module's absolute path with module base name. + + @param moduleName the base name of the module + @return the absolute module path + **/ + public synchronized static String getModulePath(String moduleName) { + String[] info = moduleInfo.get(moduleName); + String packagePath = (String) packageInfo.get(info[1]); + File convertFile = new File(workspaceDir + File.separatorChar + packagePath + File.separatorChar + info[0]); + return convertFile.getParent(); + } + + /** + Query the module's absolute MSA file path with module base name. + + @param moduleName the base name of the module + @return the absolute MSA file name + @throws BuildException + Base name is not registered in any SPD files + **/ + private synchronized static String getMsaFilename(String moduleName) throws BuildException { + String[] info = moduleInfo.get(moduleName); + if (info == null) { + throw new BuildException("Module base name [" + moduleName + "] can't found in all SPD."); + } + String packagePath = (String) packageInfo.get(info[1]); + File convertFile = new File(workspaceDir + File.separatorChar + packagePath + File.separatorChar + info[0]); + return convertFile.getPath(); + } + + /** + Query the module's absolute MBD file path with module base name. + + @param moduleName the base name of the module + @return the absolute MBD file name + @throws BuildException + Base name is not registered in any SPD files + **/ + private synchronized static String getMbdFilename(String moduleName) throws BuildException { + String[] info = moduleInfo.get(moduleName); + if (info == null) { + throw new BuildException("Info: Module base name [" + moduleName + "] can't found in all SPD."); + } + String packagePath = (String) packageInfo.get(info[1]); + File convertFile = new File(workspaceDir + File.separatorChar + packagePath + File.separatorChar + info[0]); + return convertFile.getPath().substring(0, convertFile.getPath().length() - 4) + ".mbd"; + } + + /** + Get the current WORKSPACE Directory. + @return current workspace directory + **/ + public synchronized static String getWorkspacePath() { + return workspaceDir; + } + + /** + Query package relative path to WORKSPACE_DIR with package name. + + @param packageName the name of the package + @return the path relative to WORKSPACE_DIR + **/ + public synchronized static String getPackagePath(String packageName) { + return (String) packageInfo.get(packageName); + } + + /** + Query package (which the module belongs to) relative path to WORSPACE_DIR. + + @param moduleName the base name of the module + @return the relative path to WORKSPACE_DIR of the package which the module belongs to + **/ + public synchronized static String getPackagePathForModule(String moduleName) { + String[] info = moduleInfo.get(moduleName); + String packagePath = (String) packageInfo.get(info[1]); + return packagePath; + } + + /** + Query the package name which the module belongs to with the module's base name. + + @param moduleName the base name of the module + @return the package name which the module belongs to + **/ + public synchronized static String getPackageNameForModule(String moduleName) { + return moduleInfo.get(moduleName)[1]; + } + + /** + Parse framework database (DB) and all SPD files listed in DB to initialize + the environment for next build. This method will only be executed only once + in the whole build process. + + @param workspaceDatabaseFile the file name of framework database + @param workspaceDir current workspace directory path + @throws BuildException + Framework Dababase or SPD or MSA file is not valid + **/ + public synchronized static void initInfo(String workspaceDatabaseFile, String workspaceDir) throws BuildException { + if (globalFlag) { + return; + } + globalFlag = true; + GlobalData.workspaceDir = workspaceDir; + File dbFile = new File(workspaceDir + File.separatorChar + workspaceDatabaseFile); + try { + FrameworkDatabaseDocument db = (FrameworkDatabaseDocument) XmlObject.Factory.parse(dbFile); + List packages = db.getFrameworkDatabase().getPackageList() + .getPackageList(); + Iterator iter = packages.iterator(); + while (iter.hasNext()) { + PackageListDocument.PackageList.Package packageItem = (PackageListDocument.PackageList.Package) iter + .next(); + String name = packageItem.getPackageNameArray(0).getStringValue(); + String path = packageItem.getPathArray(0).getStringValue(); + packageInfo.put(name, path); + File spdFile = new File(workspaceDir + File.separatorChar + path + File.separatorChar + name + ".spd"); + initPackageInfo(spdFile.getPath(), name); + // + // SPD Parse. + // + PackageSurfaceAreaDocument spdDoc = (PackageSurfaceAreaDocument) XmlObject.Factory.parse(spdFile); + Spd spd = new Spd(spdDoc, path); + spdTable.put(name, spd); + + } + } catch (Exception e) { + throw new BuildException("Parse workspace Database [" + dbFile.getPath() + "] Error.\n" + e.getMessage()); + } + } + + /** + Parse every MSA files, get base name from MSA Header. And record those + values to ModuleInfo. + + @param packageFilename the file name of the package + @param packageName the name of the package + @throws BuildException + SPD or MSA file is not valid + **/ + private synchronized static void initPackageInfo(String packageFilename, String packageName) throws BuildException { + File packageFile = new File(packageFilename); + try { + PackageSurfaceAreaDocument spd = (PackageSurfaceAreaDocument) XmlObject.Factory.parse(packageFile); + List msasList = spd.getPackageSurfaceArea().getMsaFiles() + .getMsaFileList(); + Iterator msasIter = msasList.iterator(); + while (msasIter.hasNext()) { + MsaFilesDocument.MsaFiles.MsaFile msas = (MsaFilesDocument.MsaFiles.MsaFile) msasIter.next(); + String msaFilename = msas.getFilename().getStringValue(); + File msaFile = new File(workspaceDir + File.separatorChar + GlobalData.getPackagePath(packageName) + + File.separatorChar + msaFilename); + SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser(); + Map map = surfaceAreaParser.parseFile(msaFile); + String baseName = ""; + XmlObject header = null; + if ((header = map.get("MsaHeader")) != null) { + baseName = ((MsaHeader) header).getBaseName().getStringValue(); + } else if ((header = map.get("MsaLibHeader")) != null) { + baseName = ((MsaLibHeader) header).getBaseName().getStringValue(); + } else { + continue; + } + nativeMsa.put(baseName, map); + String[] info = { msaFilename, packageName }; + moduleInfo.put(baseName, info); + } + } catch (Exception e) { + throw new BuildException("Parse package description file [" + packageFile.getPath() + "] Error.\n" + + e.getMessage()); + } + } + + /** + Query the libraries which the module depends on. + + @param moduleName the base name of the module + @return the libraries which the module depends on + **/ + public synchronized static String[] getModuleLibrary(String moduleName) { + Set set = moduleLibraryMap.get(moduleName); + return set.toArray(new String[set.size()]); + } + + /** + Register module's library list which it depends on for later use. + + @param moduleName the base name of the module + @param libraryList the libraries which the module depends on + **/ + public synchronized static void addModuleLibrary(String moduleName, Set libraryList) { + moduleLibraryMap.put(moduleName, libraryList); + } + + /** + Query the library absolute file name with library name. + + @param library the base name of the library + @return the library absolute file name + **/ + public synchronized static String getLibrary(String library) { + return libraries.get(library); + } + + /** + Register library absolute file name for later use. + + @param library the base name of the library + @param resultPath the library absolute file name + **/ + public synchronized static void addLibrary(String library, String resultPath) { + libraries.put(library, resultPath); + } + + /** + Whether the module with ARCH has built in the previous build. + + @param moduleName the base name of the module + @param arch current build ARCH + @return true if the module has built in previous, otherwise return false + **/ + public synchronized static boolean isModuleBuilt(String moduleName, String arch) { + return builtModules.contains(moduleName + "-" + arch); + } + + /** + Register the module with ARCH has built. + + @param moduleName the base name of the module + @param arch current build ARCH + **/ + public synchronized static void registerBuiltModule(String moduleName, String arch) { + builtModules.add(moduleName + "-" + arch); + } + + /** + Whether the module's surface area has parsed in the previous build. + + @param moduleName the base name of the module + @return true if the module's surface area has parsed in previous, otherwise + return false + **/ + public synchronized static boolean isModuleParsed(String moduleName) { + return parsedModules.containsKey(moduleName); + } + + /** + Query overrided module surface area information. If current is Package + or Platform build, also include the information from FPD file. + +

Note that surface area parsing is incremental. That means the method will + only to parse the MSA and MBD files when never parsed before.

+ + @param moduleName the base name of the module + @return the overrided module surface area information + @throws BuildException + MSA or MBD is not valid + **/ + public synchronized static Map getDoc(String moduleName) throws BuildException { + if (parsedModules.containsKey(moduleName)) { + return parsedModules.get(moduleName); + } + Map msaMap = getNativeMsa(moduleName); + Map mbdMap = getNativeMbd(moduleName); + OverrideProcess op = new OverrideProcess(); + Map map = op.override(mbdMap, msaMap); + // + // IF IT IS A PALTFORM BUILD, OVERRIDE FROM PLATFORM + // + if (FpdParserTask.platformBuildOptions != null) { + Map platformMap = new HashMap(); + platformMap.put("BuildOptions", FpdParserTask.platformBuildOptions); + Map overrideMap = op.override(platformMap, OverrideProcess.deal(map)); + GlobalData.registerModule(moduleName, overrideMap); + return overrideMap; + } else { + parsedModules.put(moduleName, map); + return map; + } + } + + /** + Query the native MSA information with module base name. + +

Note that MSA parsing is incremental. That means the method will + only to parse the MSA files when never parsed before.

+ + @param moduleName the base name of the module + @return the native MSA information + @throws BuildException + MSA file is not valid + **/ + public synchronized static Map getNativeMsa(String moduleName) throws BuildException { + if (nativeMsa.containsKey(moduleName)) { + return nativeMsa.get(moduleName); + } + String msaFilename = getMsaFilename(moduleName); + File msaFile = new File(msaFilename); + if (!msaFile.exists()) { + throw new BuildException("Info: Surface Area file [" + msaFile.getPath() + "] can't found."); + } + SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser(); + Map map = surfaceAreaParser.parseFile(msaFile); + nativeMsa.put(moduleName, map); + return map; + } + + /** + Query the native MBD information with module base name. + +

Note that MBD parsing is incremental. That means the method will + only to parse the MBD files when never parsed before.

+ + @param moduleName the base name of the module + @return the native MBD information + @throws BuildException + MBD file is not valid + **/ + public synchronized static Map getNativeMbd(String moduleName) throws BuildException { + if (nativeMbd.containsKey(moduleName)) { + return nativeMbd.get(moduleName); + } + String mbdFilename = getMbdFilename(moduleName); + File mbdFile = new File(mbdFilename); + if (!mbdFile.exists()) { + throw new BuildException("Info: Surface Area file [" + mbdFile.getPath() + "] can't found."); + } + SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser(); + Map map = surfaceAreaParser.parseFile(mbdFile); + nativeMbd.put(moduleName, map); + return map; + } + + /** + Register module overrided surface area information. If has existed, then update. + + @param moduleName the base name of the module + @param map the overrided surface area information + **/ + public synchronized static void registerModule(String moduleName, Map map) { + parsedModules.put(moduleName, map); + } + + /** + * + * @param protocolName + * @return + */ + public synchronized static String[] getProtocolInfoGuid(String protocolName) { + Set set = spdTable.keySet(); + Iterator iter = set.iterator(); + String[] cNameGuid = null; + + while (iter.hasNext()) { + Spd spd = (Spd) spdTable.get(iter.next()); + cNameGuid = spd.getProtocolNameGuidArray(protocolName); + if (cNameGuid != null) { + break; + } + } + return cNameGuid; + } + + public synchronized static String[] getPpiInfoGuid(String ppiName) { + Set set = spdTable.keySet(); + Iterator iter = set.iterator(); + String[] cNameGuid = null; + + while (iter.hasNext()) { + Spd spd = (Spd) spdTable.get(iter.next()); + cNameGuid = spd.getPpiCnameGuidArray(ppiName); + + if (cNameGuid != null) { + break; + } + } + return cNameGuid; + } + + /** + * + * @param guidName + * @return + */ + public synchronized static String[] getGuidInfoGuid(String guidName) { + String[] cNameGuid = null; + Set set = spdTable.keySet(); + Iterator iter = set.iterator(); + + while (iter.hasNext()) { + Spd spd = (Spd) spdTable.get(iter.next()); + cNameGuid = spd.getGuidNameArray(guidName); + if (cNameGuid != null) { + break; + } + } + return cNameGuid; + } + + public synchronized static String getLibClassIncluder(String libName) { + String libIncluder = null; + Set set = spdTable.keySet(); + Iterator iter = set.iterator(); + + while (iter.hasNext()) { + String packageName = (String) iter.next(); + Spd spd = (Spd) spdTable.get(packageName); + libIncluder = spd.getLibClassIncluder(libName); + String packagePath = spd.packagePath; + if (packagePath != null) { + packagePath = packagePath.replace('\\', File.separatorChar); + packagePath = packagePath.replace('/', File.separatorChar); + } else { + packagePath = packageName; + } + if (libIncluder != null) { + libIncluder = libIncluder.replace('\\', File.separatorChar); + libIncluder = libIncluder.replace('/', File.separatorChar); + libIncluder = packageName + File.separatorChar + libIncluder; + break; + } + } + return libIncluder; + } + + public synchronized static String getModuleInfoByPackageName(String packageName, String moduleType) { + Spd spd; + String includeFile = null; + String includeStr = ""; + String cleanPath = ""; + + spd = (Spd) spdTable.get(packageName); + includeFile = spd.getModuleTypeIncluder(moduleType); + if (includeFile != null) { + includeFile = includeFile.replace('\\', File.separatorChar); + includeFile = includeFile.replace('/', File.separatorChar); + includeStr = CommonDefinition.include + " <" + includeStr; + cleanPath = spd.packagePath; + cleanPath = cleanPath.replace('\\', File.separatorChar); + cleanPath = cleanPath.replace('/', File.separatorChar); + + if (cleanPath.charAt(spd.packagePath.length() - 1) != File.separatorChar) { + cleanPath = cleanPath + File.separatorChar; + } + includeStr = includeStr + cleanPath; + includeStr = includeStr + includeFile; + includeStr = includeStr + ">\r\n"; + } + + return includeStr; + } + + public synchronized static void setLibInstanceInfo(String libName, String libConstructor, String libDesturctor) { + String[] libConsDes = new String[2]; + libConsDes[0] = libConstructor; + libConsDes[1] = libDesturctor; + + libInstanceInfo.put(libName, libConsDes); + } + + public synchronized static boolean isHaveLibInstance(String libName) { + return libInstanceInfo.containsKey(libName); + } + + public synchronized static String getLibInstanceConstructor(String libName) { + String[] libInstanceValue; + libInstanceValue = libInstanceInfo.get(libName); + if (libInstanceValue != null) { + return libInstanceValue[0]; + } else { + return null; + } + } + + public synchronized static String getLibInstanceDestructor(String libName) { + String[] libInstanceValue; + libInstanceValue = libInstanceInfo.get(libName); + if (libInstanceValue != null) { + return libInstanceValue[1]; + } else { + return null; + } + } + + public synchronized static MemoryDatabaseManager getPCDMemoryDBManager() { + return pcdDbManager; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/GlobalShare.java b/Tools/Source/GenBuild/org/tianocore/build/global/GlobalShare.java new file mode 100644 index 0000000000..5912127a10 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/GlobalShare.java @@ -0,0 +1,178 @@ +/*++ + + Copyright (c) 2006, 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. + + Module Name: + ShareObject.java + + Abstract: + + --*/ +package org.tianocore.build.global; + +import java.util.*; + +import org.apache.tools.ant.*; +import org.apache.tools.ant.types.DataType; + +public class GlobalShare extends DataType implements DynamicConfigurator { + private static final HashMap objStorage = new HashMap(); + + private DataObjectOp op; + + private String objName; + + private Object objInst; + + private String objClassPackage = "org.tianocore"; + + public GlobalShare () { + + } + + public GlobalShare (String objName) { + this.objName = objName; + this.objInst = objStorage.get(this.objName); + } + + public GlobalShare (String objName, Object obj) { + this.objName = objName; + this.objInst = obj; + objStorage.put(this.objName, this.objInst); + } + + public Object createDynamicElement(String name) throws BuildException { + String className = objClassPackage + "." + name; + log("GlobalShare.createDynamicElement(" + name + ")", + Project.MSG_VERBOSE); + try { + objInst = Class.forName(className).newInstance(); + } catch (ClassNotFoundException e) { + throw new BuildException("class name is not found"); + } catch (InstantiationException e) { + throw new BuildException("the class cannnot be instantiated"); + } catch (IllegalAccessException e) { + throw new BuildException("cannot access the class"); + } + + return objInst; + } + + public void setDynamicAttribute(String name, String value) + throws BuildException { + log("name = " + name + " value = " + value, Project.MSG_VERBOSE); + throw new BuildException(); + } + + public void setName(String name) { + this.objName = name; + if (this.op != null) { + issueOperation(); + } + } + + public String getName() { + return this.objName; + } + + public void setPackage(String name) { + log("ShareObject.setPackage(" + name + ")", Project.MSG_VERBOSE); + this.objClassPackage = name; + } + + public String getPackage() { + return this.objClassPackage; + } + + public void setOperation(String opName) { + log("ShareObject.setOperation(" + opName + ")", Project.MSG_VERBOSE); + this.op = DataObjectOp.formString(opName); + + if (this.objName != null) { + issueOperation(); + } + } + + public String getOperation() { + return this.op.toString(); + } + + public void issueOperation() { + if (this.op == DataObjectOp.ADD) { + + log("ShareObject: adding ... " + this.objName, Project.MSG_VERBOSE); + objStorage.put(this.objName, this.objInst); + + } else if (this.op == DataObjectOp.GET) { + + log("ShareObject: fetching ... " + this.objName, + Project.MSG_VERBOSE); + objInst = objStorage.get(objName); + + } else if (this.op == DataObjectOp.DEL) { + + log("ShareObject: removing ... " + this.objName, + Project.MSG_VERBOSE); + objInst = objStorage.remove(objName); + + } else { + throw new BuildException("not supported operation"); + } + } + + public Object get() { + return this.objInst; + } + + public static int getObjectNum() { + return objStorage.size(); + } + + public static Object add(String objName, Object obj) { + return objStorage.put(objName, obj); + } + + public static Object retrieve(String objName) { + return objStorage.get(objName); + } + + public static Object remove(String objName) { + return objStorage.remove(objName); + } + + public static void empty() { + objStorage.clear(); + } +} + +class DataObjectOp { + private static final HashMap opMap = new HashMap(); + + private final String opName; + + private DataObjectOp (String name) { + this.opName = name; + opMap.put(this.opName, this); + } + + public String toString() { + return opName; + } + + public static DataObjectOp formString(String opName) { + return opMap.get(opName); + } + + public static final DataObjectOp ADD = new DataObjectOp("ADD"); + + public static final DataObjectOp GET = new DataObjectOp("GET"); + + public static final DataObjectOp DEL = new DataObjectOp("DEL"); +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/LibBuildFileGenerator.java b/Tools/Source/GenBuild/org/tianocore/build/global/LibBuildFileGenerator.java new file mode 100644 index 0000000000..4d7e870587 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/LibBuildFileGenerator.java @@ -0,0 +1,412 @@ +/** @file + This file is an ANT task. + + LibBuildFileGenerator task is used to generate module's build.xml file. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.global; + +import java.io.File; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.MsaHeaderDocument.MsaHeader; +import org.tianocore.MsaLibHeaderDocument.MsaLibHeader; +import org.w3c.dom.Document; +import org.w3c.dom.Element; + +/** + This class LibBuildFileGenerator is an ANT task to generate + build.xml for each module. Here are two usages. + +
    +
  • + For one module (bf is LibBuildFileGenerator task name): +
    +        <bf buildFile="Application\HelloWorld\HelloWorld.msa" />
    +      
    +
  • +
  • + For one package: +
    +        <bf recursive="true" />
    +      
    +
  • +
+ + @since GenBuild 1.0 +**/ +public class LibBuildFileGenerator extends Task { + + private File buildFile; + + private boolean recursive = false; + + private String license = " Copyright (c) 2006, Intel Corporation \n" + + "All rights reserved. This program and the accompanying materials \n" + + "are licensed and made available under the terms and conditions of the BSD License \n" + + "which accompanies this distribution. The full text of the license may be found at \n" + + "http://opensource.org/licenses/bsd-license.php \n" + + "\n" + + "THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN \"AS IS\" BASIS, \n" + + "WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED."; + + private String base_name; + + private String module_relative_path; + + private File base_file = new File("."); + + /** + Public construct method. It is necessary for ANT task. + **/ + public LibBuildFileGenerator () { + } + + /** + ANT task's entry point, will be called after init(). + + @throws BuildException + buildFile do not specify while recursive set to false + **/ + public void execute() throws BuildException { + if(recursive){ + searchMsa(new File(".")); + } + else { + Map map = new HashMap(); + String basename = buildFile.getName(); + int k = basename.lastIndexOf('.'); + base_name = basename.substring(0, k); + map.put(base_name, buildFile); + genBuildFile(map); + } + } + + /** + Recursivly find all MSA files and record all modules. + + @param path Package path + **/ + private void searchMsa(File path){ + File[] files = path.listFiles(); + Vector vec = new Vector(); + for(int i=0; i < files.length; i ++){ + if (files[i].isFile()){ + if(files[i].getName().endsWith(".msa")){ + System.out.println("#" + files[i].getPath()); + vec.add(files[i]); + } + } + } + Map mapBasename = new HashMap(); + if (vec.size() > 0){ + base_name = null; + for ( int j = 0 ; j < vec.size(); j++){ + if ( vec.size() > 1){ + System.out.println("##" + vec.get(0)); + } + File f = (File)vec.get(j); + SurfaceAreaParser surfaceAreaParser = new SurfaceAreaParser(); + Map map = surfaceAreaParser.parseFile(f); + String baseName = ""; + XmlObject header = null; + if ( (header = map.get("MsaHeader")) != null ){ + baseName = ((MsaHeader)header).getBaseName().getStringValue(); + } + else if ( (header = map.get("MsaLibHeader")) != null){ + baseName = ((MsaLibHeader)header).getBaseName().getStringValue(); + } else { + continue ; + } + if ( base_name == null || base_name.length() > baseName.length()){ + base_name = baseName; + buildFile = f; + try { + module_relative_path = buildFile.getParent().substring(base_file.getPath().length() + 1); + } + catch(Exception e){ + module_relative_path = "."; + } + } + mapBasename.put(baseName, f); + } + genBuildFile(mapBasename); + } + + for(int i=0; i < files.length; i ++){ + if (files[i].isDirectory()){ + searchMsa(files[i]); + } + } + } + + /** + Generate build.xml. + + @param map All base name under one module directory + **/ + private void genBuildFile(Map map) { + DocumentBuilderFactory domfac = DocumentBuilderFactory.newInstance(); + try { + DocumentBuilder dombuilder = domfac.newDocumentBuilder(); + Document document = dombuilder.newDocument(); + // + // create root element and its attributes + // + document.appendChild(document.createComment(license)); + Element root = document.createElement("project"); + root.setAttribute("default", base_name); + root.setAttribute("basedir", "."); + // + // element for External ANT tasks + // + root.appendChild(document.createComment("Apply external ANT tasks")); + Element ele = document.createElement("taskdef"); + ele.setAttribute("resource", "GenBuild.tasks"); + root.appendChild(ele); + // + // + // + ele = document.createElement("taskdef"); + ele.setAttribute("resource", "net/sf/antcontrib/antlib.xml"); + root.appendChild(ele); + + ele = document.createElement("property"); + ele.setAttribute("environment", "env"); + root.appendChild(ele); + + ele = document.createElement("property"); + ele.setAttribute("name", "WORKSPACE_DIR"); + ele.setAttribute("value", "${env.WORKSPACE}"); + root.appendChild(ele); + + ele = document.createElement("import"); + ele.setAttribute("file", "${WORKSPACE_DIR}"+File.separatorChar+"Tools"+File.separatorChar+"Conf"+File.separatorChar+"BuildMacro.xml"); + root.appendChild(ele); + + root.appendChild(document.createComment("MODULE_RELATIVE PATH is relative to PACKAGE_DIR")); + ele = document.createElement("property"); + ele.setAttribute("name", "MODULE_RELATIVE_PATH"); + ele.setAttribute("value", module_relative_path); + root.appendChild(ele); + + ele = document.createElement("property"); + ele.setAttribute("name", "MODULE_DIR"); + ele.setAttribute("value", "${PACKAGE_DIR}" + File.separatorChar + "${MODULE_RELATIVE_PATH}"); + root.appendChild(ele); + + ele = document.createElement("property"); + ele.setAttribute("name", "COMMON_FILE"); + ele.setAttribute("value", "${WORKSPACE_DIR}" + File.separatorChar + "Tools" + + File.separatorChar + "Conf" + File.separatorChar + "Common.xml"); + root.appendChild(ele); + + // + // generate the buildfmd target + // + Set set = map.keySet(); + Iterator iter = set.iterator(); + while (iter.hasNext()){ + String bName = (String)iter.next(); + File msaFile = (File)map.get(bName); + String msaFilename = "${MODULE_DIR}" + File.separatorChar + msaFile.getName(); + String mbdFilename = msaFilename.substring(0 , msaFilename.length() - 4) + ".mbd"; + ele = document.createElement("target"); + ele.setAttribute("name", bName); + Element target = document.createElement("GenBuild"); + target.setAttribute("msaFilename", msaFilename); + target.setAttribute("mbdFilename", mbdFilename); + target.setAttribute("baseName", bName); + ele.appendChild(target); + root.appendChild(ele); + } + + root.appendChild(ele); + // + // Default clean + // + ele = document.createElement("target"); + ele.setAttribute("name", "clean"); + ele.setAttribute("depends", base_name + "_clean"); + root.appendChild(ele); + // + // Default Clean ALl + // + ele = document.createElement("target"); + ele.setAttribute("name", "cleanall"); + ele.setAttribute("depends", base_name + "_cleanall"); + root.appendChild(ele); + // + // Every clean target for each BaseName + // + set = map.keySet(); + iter = set.iterator(); + while (iter.hasNext()){ + String bName = (String)iter.next(); + File msaFile = (File)map.get(bName); + String msaFilename = "${MODULE_DIR}" + File.separatorChar + msaFile.getName(); + String mbdFilename = msaFilename.substring(0 , msaFilename.length() - 4) + ".mbd"; + + ele = document.createElement("target"); + ele.setAttribute("name", bName + "_clean"); + // + // Output Dir + // + Element target = document.createElement("OutputDirSetup"); + target.setAttribute("msaFilename", msaFilename); + target.setAttribute("mbdFilename", mbdFilename); + target.setAttribute("baseName", bName); + ele.appendChild(target); + // + // Call BaseName_build.xml clean + // + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + bName + "_build.xml"); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element moduleEle = document.createElement("ant"); + moduleEle.setAttribute("antfile", "${DEST_DIR_OUTPUT}" + File.separatorChar + bName + "_build.xml"); + moduleEle.setAttribute("target", "clean"); + + elseEle.appendChild(moduleEle); + ifEle.appendChild(elseEle); + ele.appendChild(ifEle); + // + // just delete + // + Element clean = document.createElement("delete"); + clean.setAttribute("dir", "${DEST_DIR_OUTPUT}"); + clean.setAttribute("excludes", "*.xml"); + ele.appendChild(clean); + + root.appendChild(ele); + } + // + // Every Clean ALl target for each BaseName + // + set = map.keySet(); + iter = set.iterator(); + while (iter.hasNext()){ + String bName = (String)iter.next(); + File msaFile = (File)map.get(bName); + String msaFilename = "${MODULE_DIR}" + File.separatorChar + msaFile.getName(); + String mbdFilename = msaFilename.substring(0 , msaFilename.length() - 4) + ".mbd"; + + ele = document.createElement("target"); + ele.setAttribute("name", bName + "_cleanall"); + // + // Output Dir + // + Element target = document.createElement("OutputDirSetup"); + target.setAttribute("msaFilename", msaFilename); + target.setAttribute("mbdFilename", mbdFilename); + target.setAttribute("baseName", bName); + ele.appendChild(target); + // + // Call BaseName_build.xml clean + // + Element ifEle = document.createElement("if"); + Element availableEle = document.createElement("available"); + availableEle.setAttribute("file", "${DEST_DIR_OUTPUT}" + File.separatorChar + bName + "_build.xml"); + ifEle.appendChild(availableEle); + Element elseEle = document.createElement("then"); + + Element moduleEle = document.createElement("ant"); + moduleEle.setAttribute("antfile", "${DEST_DIR_OUTPUT}" + File.separatorChar + bName + "_build.xml"); + moduleEle.setAttribute("target", "cleanall"); + + elseEle.appendChild(moduleEle); + ifEle.appendChild(elseEle); + ele.appendChild(ifEle); + // + // just delete + // + Element clean = document.createElement("delete"); + clean.setAttribute("dir", "${DEST_DIR_OUTPUT}"); + ele.appendChild(clean); + + clean = document.createElement("delete"); + clean.setAttribute("dir", "${DEST_DIR_DEBUG}"); + ele.appendChild(clean); + + clean = document.createElement("delete"); + Element fileset = document.createElement("fileset"); + fileset.setAttribute("dir", "${BIN_DIR}"); + fileset.setAttribute("includes", "**" + bName + "*"); + clean.appendChild(fileset); + ele.appendChild(clean); + + root.appendChild(ele); + } + document.appendChild(root); + // + // Prepare the DOM document for writing + // + Source source = new DOMSource(document); + // + // Prepare the output file + // + String filename = buildFile.getParent() + File.separatorChar + "build.xml"; + File file = new File(getProject().replaceProperties(filename)); + // + // generate all directory path + // + Result result = new StreamResult(file); + // + // Write the DOM document to the file + // + Transformer xformer = TransformerFactory.newInstance() + .newTransformer(); + xformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); + xformer.setOutputProperty(OutputKeys.INDENT, "yes"); + xformer.transform(source, result); + } catch (Exception ex) { + System.out.println("##" + ex); + } + } + + + public File getBuildFile() { + return buildFile; + } + + public void setBuildFile(File buildFile) { + this.buildFile = buildFile; + } + + public boolean isRecursive() { + return recursive; + } + + public void setRecursive(boolean recursive) { + this.recursive = recursive; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/ModuleIdentification.java b/Tools/Source/GenBuild/org/tianocore/build/global/ModuleIdentification.java new file mode 100644 index 0000000000..74311d4541 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/ModuleIdentification.java @@ -0,0 +1,55 @@ +package org.tianocore.build.global; + +public class ModuleIdentification { + + private String baseName; + + private String packageName; + + private String guid; + + private String version; + + public ModuleIdentification(String baseName, String packageName, String guid, String version){ + this.baseName = baseName; + this.packageName = packageName; + this.guid = guid; + this.version = version; + } + + public boolean equals(Object obj) { + if (obj instanceof ModuleIdentification) { + ModuleIdentification moduleIdObj = (ModuleIdentification)obj; + if ( baseName.equalsIgnoreCase(moduleIdObj.baseName)) { + return true; + } + // TBD + return false; + } + else { + return super.equals(obj); + } + } + + public String toString(){ + return packageName + ":" + guid + "_" + baseName + "_" + version; + } + + public void setBaseName(String baseName) { + this.baseName = baseName; + } + + public void setGuid(String guid) { + this.guid = guid; + } + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public void setVersion(String version) { + this.version = version; + } + + +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java b/Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java new file mode 100644 index 0000000000..936dac8ea3 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/OnDependency.java @@ -0,0 +1,121 @@ +/** @file +This file is to define OnDependency class. + +Copyright (c) 2006, 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. + +--*/ +package org.tianocore.build.global; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Sequential; + +import java.io.File; +import java.util.Iterator; + +/** + Class OnDepdendency is used to check the timestamp between source files and + target files, which can be used to determine if the target files are needed to + be re-generated from source files. + **/ +public class OnDependency extends Task { + /// + /// source files list + /// + private DpFileList sources = null; + /// + /// target files list + /// + private DpFileList targets = null; + /// + /// tasks to be performed to generate target files + /// + private Sequential task = null; + + /// + /// An empty constructor for an ANT task can avoid some potential issues + /// + public OnDependency(){ + } + + /** + Standard execute method of ANT task + **/ + public void execute() { + if (isOutOfDate() && task != null) { + task.perform(); + } + } + + /// + /// check if the target files are outofdate + /// + private boolean isOutOfDate() { + /// + /// if no source files specified, take it as a fresh start + /// + if (sources.nameList.size() == 0) { + return true; + } + + Iterator dstIt = targets.nameList.iterator(); + while (dstIt.hasNext()) { + String dstFileName = (String)dstIt.next(); + File dstFile = new File(dstFileName); + if (!dstFile.exists()) { + return true; + } + + long dstTimeStamp = dstFile.lastModified(); + Iterator srcIt = sources.nameList.iterator(); + while (srcIt.hasNext()) { + String srcFileName = (String)srcIt.next(); + File srcFile = new File(srcFileName); + if (!srcFile.exists()) { + throw new BuildException(srcFileName + " doesn't exist !!!"); + } + + if (dstTimeStamp < srcFile.lastModified()) { + return true; + } + } + } + + return false; + } + + /** + Add method of ANT task for nested element with Sequential type + + @param task Sequential object which contains tasks for generating target files + **/ + public void addSequential(Sequential task) { + this.task = task; + } + + /** + Add method of ANT task for nested element with DpFileList type + + @param sources DpFileList object which contains the list of source files + **/ + public void addSourcefiles(DpFileList sources) { + this.sources = sources; + } + + /** + Add method of ANT task for nested element with DpFileList type + + @param targets DpFileList object which contains the list of target files + **/ + public void addTargetfiles(DpFileList targets) { + this.targets = targets; + } +} + diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/OutputManager.java b/Tools/Source/GenBuild/org/tianocore/build/global/OutputManager.java new file mode 100644 index 0000000000..01e24e653f --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/OutputManager.java @@ -0,0 +1,176 @@ +/** @file + OutputManager class. + + OutputManager class set output directories for every module by BUILD_MODE. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.build.global; + +import org.apache.tools.ant.Project; +import java.io.File; + +/** + OutputManager class is used to setup output directories (BIN_DIR, DEST_DIR_OUTPUT, + DEST_DIR_DEBUG) according to BUILD_MODE. + + @since GenBuild 1.0 +**/ +public class OutputManager { + + /// + /// Single Module build + /// + public static final String MODULE_BUILD = "MODULE"; + + /// + /// Package build + /// + public static final String PACKAGE_BUILD = "PACKAGE"; + + /// + /// Platform build + /// + public static final String PLATFORM_BUILD = "PLATFORM"; + + public static String buildMode = MODULE_BUILD; + + /// + /// For Package build, PLATFORM represent PACKAGE + /// + public static String PLATFORM; + + /// + /// For Platform build, PLATFORM_DIR represent PACKAGE_DIR + /// + public static String PLATFORM_DIR; + + /// + /// means intermediate files will put under Module's dir + /// + public static final String MODULE = "MODULE"; + + /// + /// mean intermediate files will put under a unify dir + /// + public static final String UNIFIED = "UNIFIED"; + + /// + /// Flag to ensure the function update will be called only one in the whole build. + /// + private static boolean flag = true; + + /** + If BUILD_MODE is PLATFORM or PACKAGE, record PLATFORM and PLARFORM_DIR. + Reminder that for PACKAGE build, here set value PACKAGE to PLATFORM and + PACKAGE_DIR to PLARFORM_DIR, and also update the ant properties. + +

Note that this function will be called only once in the whole build.

+ + @param project current ANT build Project + **/ + public synchronized static void update(Project project) { + if (flag){ + flag = false; + String str = project.getProperty("BUILD_MODE"); + if (str != null){ + if (str.equals(PLATFORM_BUILD)) { + buildMode = PLATFORM_BUILD; + PLATFORM = project.getProperty("PLATFORM"); + PLATFORM_DIR = project.getProperty("PLATFORM_DIR"); + } + else if (str.equals(PACKAGE_BUILD)) { + buildMode = PACKAGE_BUILD; + PLATFORM = project.getProperty("PACKAGE"); + PLATFORM_DIR = project.getProperty("PACKAGE_DIR"); + project.setProperty("PLATFORM", PLATFORM); + project.setProperty("PLATFORM_DIR", PLATFORM_DIR); + } + } + } + } + + /** + Setup BIN_DIR, DEST_DIR_OUTPUT and DEST_DIR_OUTPUT, following are the rules: + +
+        Those three variables are defined as following
+        DEST_DIR_OUTPUT (intermediate files)
+        DEST_DIR_DEBUG (intermediate debug files)
+        BIN_DIR (final files)
+        
+        Output Dir (MODULE or UNIFIED):
+        For Module build: 
+        All intermediate files are at ${MODULE_DIR}/Build/${TARGET}/${ARCH}/DEBUG|OUTPUT
+        All final files are at ${MODULE_DIR}/Build/${TARGET}/${ARCH}
+        
+        For Platform build:
+        If specified with MODULE
+        Intermediate files->${MODULE_DIR}/Build/${PLATFORM}/${TARGET}/${ARCH}/DEBUG|OUTPUT
+        Final files -> ${PLARFORM_DIR}/Build/${TARGET}/${ARCH}
+        
+        Else if specified with UNIFIED
+        Intermediate files->${PLARFORM_DIR}/Build/${TARGET}/${ARCH}/${PACKAGE}/${SOURCE_RELATIVE_PATH}/DEBUG|OUTPUT
+        Final files -> ${PLARFORM_DIR}/Build/${TARGET}/${ARCH}
+        
+        For Package build:
+        If specified with MODULE
+        Intermediate files->${MODULE_DIR}/Build/${PACKAGE}/${TARGET}/${ARCH}/DEBUG|OUTPUT
+        Final files -> ${PACKAGE_DIR}/Build/${TARGET}/${ARCH}
+        
+        Else if specified with UNIFIED
+        Intermediate files->${PACKAGE_DIR}/Build/${TARGET}/${ARCH}/${PACKAGE}/${SOURCE_RELATIVE_PATH}/DEBUG|OUTPUT
+        Final files -> ${PACKAGE_DIR}/Build/${TARGET}/${ARCH}
+      
+ + @param project current ANT build Project + @param userdir user-defined directory + @param type the module build type (MODULE or UNIFIED) + **/ + public synchronized static void update(Project project, String userdir, String type) { + // + // userdir TBD + // + if( type == null || ! type.equals(MODULE)){ + type = UNIFIED; + } + if (buildMode.equals(MODULE_BUILD)){ + project.setProperty("DEST_DIR_OUTPUT", project.replaceProperties("${MODULE_DIR}" + + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + + File.separatorChar + "${ARCH}" + File.separatorChar + "OUTPUT")); + project.setProperty("DEST_DIR_DEBUG", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "DEBUG")); + project.setProperty("BIN_DIR", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}")); + } + else if (buildMode.equals(PLATFORM_BUILD)) { + if (type.equals(MODULE)) { + project.setProperty("DEST_DIR_OUTPUT", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${PLATFORM}" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "OUTPUT")); + project.setProperty("DEST_DIR_DEBUG", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${PLATFORM}" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "DEBUG")); + project.setProperty("BIN_DIR", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}")); + } + else if (type.equals(UNIFIED)){ + project.setProperty("DEST_DIR_OUTPUT", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "${PACKAGE}" + File.separatorChar + "${MODULE_RELATIVE_PATH}" + File.separatorChar + "OUTPUT")); + project.setProperty("DEST_DIR_DEBUG", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "${PACKAGE}" + File.separatorChar + "${MODULE_RELATIVE_PATH}" + File.separatorChar + "DEBUG")); + project.setProperty("BIN_DIR", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}")); + } + } + else if (buildMode.equals(PACKAGE_BUILD)) { + if (type.equals(MODULE)) { + project.setProperty("DEST_DIR_OUTPUT", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${PLATFORM}" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "OUTPUT")); + project.setProperty("DEST_DIR_DEBUG", project.replaceProperties("${MODULE_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${PLATFORM}" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "DEBUG")); + project.setProperty("BIN_DIR", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}")); + } + else if (type.equals(UNIFIED)){ + project.setProperty("DEST_DIR_OUTPUT", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "${PACKAGE}" + File.separatorChar + "${MODULE_RELATIVE_PATH}" + File.separatorChar + "OUTPUT")); + project.setProperty("DEST_DIR_DEBUG", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}" + File.separatorChar + "${PACKAGE}" + File.separatorChar + "${MODULE_RELATIVE_PATH}" + File.separatorChar + "DEBUG")); + project.setProperty("BIN_DIR", project.replaceProperties("${PLATFORM_DIR}" + File.separatorChar + "Build" + File.separatorChar + "${TARGET}" + File.separatorChar + "${ARCH}")); + } + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/OverrideProcess.java b/Tools/Source/GenBuild/org/tianocore/build/global/OverrideProcess.java new file mode 100644 index 0000000000..dae2ca29aa --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/OverrideProcess.java @@ -0,0 +1,354 @@ +/** @file + OverrideProcess class. + + OverrideProcess class is used to override surface area information. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.global; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tools.ant.BuildException; +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.BootModesDocument; +import org.tianocore.BuildOptionsDocument; +import org.tianocore.DataHubsDocument; +import org.tianocore.EventsDocument; +import org.tianocore.ExternsDocument; +import org.tianocore.FormsetsDocument; +import org.tianocore.GuidsDocument; +import org.tianocore.HobsDocument; +import org.tianocore.IncludesDocument; +import org.tianocore.LibrariesDocument; +import org.tianocore.LibraryClassDefinitionsDocument; +import org.tianocore.MsaHeaderDocument; +import org.tianocore.MsaLibHeaderDocument; +import org.tianocore.PCDsDocument; +import org.tianocore.PPIsDocument; +import org.tianocore.ProtocolsDocument; +import org.tianocore.SourceFilesDocument; +import org.tianocore.SystemTablesDocument; +import org.tianocore.VariablesDocument; + +/** + This class is used to override surface area information. For example, MBD can + overried MSA, Platform can override all information of the module. + +

Override will take effect if two element satisfy one of following two condition:

+
    +
  • Element name and its attribute OverrideID equal each other.
  • +
  • Element is defined as exclusive which mean such element can be + only appeared in the surface area.
  • +
+ +

For example, here OutputDirectory element is exclusive:

+ +
+  Low priority Xml Document fragment:
+     <Libraries>
+       <Arch ArchType="IA32">
+         <Library OverrideID="8888">EdkPeCoffLoaderLib</Library>
+         <Library OverrideID="8888">BasePeCoffLib</Library>
+       </Arch>
+     </Libraries> 
+     <BuildOptions>
+       <OutputDirectory IntermediateDirectories="MODULE"/>
+       <Option>CC_FLAGS = "/NOLOGO", "/C"</Option>
+     <BuildOptions>
+ 
+  High priority Xml Document fragment:
+     <Libraries>
+       <Arch ArchType="IA32">
+         <Library OverrideID="8888">Nt32PeCoffLoaderLib</Library>
+       </Arch>
+     </Libraries>
+     <BuildOptions>
+       <OutputDirectory IntermediateDirectories="UNIFIED"/>
+       <Option>LIB_FLAGS = "/NOLOGO"</Option>
+     <BuildOptions>
+     
+   The result is: 
+     <Libraries>
+       <Arch ArchType="IA32">
+         <Library OverrideID="8888">Nt32PeCoffLoaderLib</Library>
+       </Arch>
+     </Libraries>
+     <BuildOptions>
+       <OutputDirectory IntermediateDirectories="UNIFIED"/>
+       <Option>CC_FLAGS = "/NOLOGO", "/C"</Option>
+       <Option>LIB_FLAGS = "/NOLOGO"</Option>
+     <BuildOptions>
+   
+  
+ +

Note that using XmlBeans to walk through the whole XML document tree.

+ + @since GenBuild 1.0 + @see org.apache.xmlbeans.XmlBeans +**/ +public class OverrideProcess { + + /// + /// URI, the namespace of current XML schema + /// + public static String prefix = "http://www.TianoCore.org/2006/Edk2.0"; + + /// + /// list of top elements of surface area + /// + public static String[] topElements = { "LibraryClassDefinitions", + "SourceFiles", "Includes", "Libraries", "Protocols", + "Events", "Hobs", "PPIs", "Variables", "BootModes", + "SystemTables", "DataHubs", "Formsets", "Guids", "Externs", + "PCDs", "BuildOptions" }; + + /// + /// list of exclusive elements + /// + public static String[] exclusiveElements = {"OutputDirectory"}; + + /** + Recursively find out all elements specified with OverrideId attribute + and exclusive elements in current XML object. + + @param o curent parsing XML object + @param map Map to list elements specified OverrideID attribute + @param execlusiveMap Map to list exclusive elements appeared in current XMl object + @param level the depth in XML document tree + **/ + private void listOverrideID(XmlObject o, Map map, Map execlusiveMap, int level) { + XmlCursor cursor = o.newCursor(); + String name = cursor.getName().getLocalPart(); + for (int i = 0 ; i < exclusiveElements.length; i++){ + if (name.equalsIgnoreCase(exclusiveElements[i])){ + execlusiveMap.put(exclusiveElements[i], cursor.getObject()); + } + } + String overrideID = cursor.getAttributeText(new QName("OverrideID")); + if (overrideID != null) { + map.put(name + ":" + overrideID, cursor.getObject()); + } + if (cursor.toFirstChild()) { + do { + listOverrideID(cursor.getObject(), map, execlusiveMap, level + 1); + } while (cursor.toNextSibling()); + } + } + + /** + This function is used to prepare for overriding with changing data. + + @param map original surface area information + @return after normalize surface area information + **/ + public synchronized static Map deal(Map map) { + Map newMap = new HashMap(); + if (map.get("MsaHeader") != null) { + newMap.put("MsaHeader", ((MsaHeaderDocument) map.get("MsaHeader")) + .getMsaHeader()); + } + if (map.get("MsaLibHeader") != null) { + newMap.put("MsaLibHeader", ((MsaLibHeaderDocument) map + .get("MsaLibHeader")).getMsaLibHeader()); + } + if (map.get("LibraryClassDefinitions") != null) { + newMap.put("LibraryClassDefinitions", + ((LibraryClassDefinitionsDocument) map + .get("LibraryClassDefinitions")) + .getLibraryClassDefinitions()); + } + if (map.get("SourceFiles") != null) { + newMap.put("SourceFiles", ((SourceFilesDocument) map + .get("SourceFiles")).getSourceFiles()); + } + if (map.get("Includes") != null) { + newMap.put("Includes", ((IncludesDocument) map.get("Includes")) + .getIncludes()); + } + if (map.get("Libraries") != null) { + newMap.put("Libraries", ((LibrariesDocument) map.get("Libraries")) + .getLibraries()); + } + if (map.get("Protocols") != null) { + newMap.put("Protocols", ((ProtocolsDocument) map.get("Protocols")) + .getProtocols()); + } + if (map.get("Events") != null) { + newMap.put("Events", ((EventsDocument) map.get("Events")) + .getEvents()); + } + if (map.get("Hobs") != null) { + newMap.put("Hobs", ((HobsDocument) map.get("Hobs")).getHobs()); + } + if (map.get("PPIs") != null) { + newMap.put("PPIs", ((PPIsDocument) map.get("PPIs")).getPPIs()); + } + if (map.get("Variables") != null) { + newMap.put("Variables", ((VariablesDocument) map.get("Variables")) + .getVariables()); + } + if (map.get("BootModes") != null) { + newMap.put("BootModes", ((BootModesDocument) map.get("BootModes")) + .getBootModes()); + } + if (map.get("SystemTables") != null) { + newMap.put("SystemTables", ((SystemTablesDocument) map + .get("SystemTables")).getSystemTables()); + } + if (map.get("DataHubs") != null) { + newMap.put("DataHubs", ((DataHubsDocument) map.get("DataHubs")) + .getDataHubs()); + } + if (map.get("Formsets") != null) { + newMap.put("Formsets", ((FormsetsDocument) map.get("Formsets")) + .getFormsets()); + } + if (map.get("Guids") != null) { + newMap.put("Guids", ((GuidsDocument) map.get("Guids")).getGuids()); + } + if (map.get("Externs") != null) { + newMap.put("Externs", ((ExternsDocument) map.get("Externs")) + .getExterns()); + } + if (map.get("PCDs") != null) { + newMap.put("PCDs", ((PCDsDocument) map.get("PCDs")).getPCDs()); + } + if (map.get("BuildOptions") != null) { + newMap.put("BuildOptions", ((BuildOptionsDocument) map + .get("BuildOptions")).getBuildOptions()); + } + return newMap; + } + + /** + Recursively remove all subelement in Xml Object l (with low priority) + based on OverrideID or exclusive elements. + + @param l the XML object to process + @param map list of elements with OverrideID in high priority XML object + @param execusiveMap list of exclusive elements in high priority XML object + **/ + private void cut(XmlCursor l, Map map, Map execusiveMap) { + String name = l.getName().getLocalPart(); + if (execusiveMap.containsKey(name)){ + l.removeXml(); + return; + } + String overrideID = l.getAttributeText(new QName("OverrideID")); + if (overrideID != null) { + if (map.containsKey(name + ":" + overrideID)) { + l.removeXml(); + return; + } + } + if (l.toFirstChild()) { + do { + cut(l, map, execusiveMap); + } while (l.toNextSibling()); + } + } + + private XmlObject cloneXmlObject(XmlObject object, boolean deep) throws BuildException { + XmlObject result = null; + try { + result = XmlObject.Factory.parse(object.getDomNode() + .cloneNode(deep)); + } catch (Exception ex) { + throw new BuildException(ex.getMessage()); + } + return result; + } + + /** + Process every item list in h and l. + + @param h surface area info with high priority + @param l surface area info with low priority + @return surface area after override + **/ + public Map override(Map h, + Map l) { + Map result = new HashMap(); + result.put("MsaHeader", override(l.get("MsaHeader"), null)); + result.put("MsaLibHeader", override(l.get("MsaLibHeader"), null)); + for (int i = 0; i < topElements.length; i++) { + result.put(topElements[i], override(h.get(topElements[i]), l + .get(topElements[i]))); + } + return result; + } + + /** + Recursively override two Xml Objects. + + @param h Xml Object info with high priority + @param l Xml Object info with low priority + @return Xml Object after area + **/ + public XmlObject override(XmlObject h, XmlObject l) { + if (l == null && h == null) { + return null; + } + if (h == null) { + return cloneXmlObject(l, true); + } + if (l == null) { + return cloneXmlObject(h, true); + } + XmlCursor hc = h.newCursor(); + if (h.getClass() != l.getClass()) { + System.out + .println("Error: Two XmlObject does not with compliant format."); + return null; + } + if (!hc.toFirstChild()) { + return cloneXmlObject(l, true); + } + + XmlCursor result = cloneXmlObject(h, true).newCursor(); + XmlCursor lcursor = cloneXmlObject(l, true).newCursor(); + result.push(); + result.toNextToken(); + result.insertNamespace("", prefix); + result.toFirstChild(); + // + // found out all element specified a OverrideID + // + Map hmap = new HashMap(); + Map execlusiveMap = new HashMap(); + listOverrideID(h, hmap, execlusiveMap, 0); + lcursor.toNextToken(); + lcursor.push(); + // + // for every direct subelement of l, cut all element satisfied with + // override rule + // + if (lcursor.toFirstChild()) { + do { + cut(lcursor, hmap, execlusiveMap); + } while (lcursor.toNextSibling()); + } + lcursor.pop(); + if (lcursor.toFirstChild()) { + do { + lcursor.copyXml(result); + result.insertChars("\n"); + } while (lcursor.toNextSibling()); + } + result.pop(); + return result.getObject(); + } +} \ No newline at end of file diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/Spd.java b/Tools/Source/GenBuild/org/tianocore/build/global/Spd.java new file mode 100644 index 0000000000..54c1391094 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/Spd.java @@ -0,0 +1,414 @@ +/** @file + Spd class. + + This class is to generate a global table for the content of spd file. + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.build.global; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.tianocore.PackageSurfaceAreaDocument; +import org.tianocore.GuidDeclarationsDocument.GuidDeclarations; +import org.tianocore.IncludeHeaderDocument.IncludeHeader; +import org.tianocore.LibraryClassDeclarationDocument.LibraryClassDeclaration; +import org.tianocore.LibraryClassDeclarationsDocument.LibraryClassDeclarations; +import org.tianocore.PackageHeadersDocument.PackageHeaders; +import org.tianocore.PackageSurfaceAreaDocument.PackageSurfaceArea; +import org.tianocore.PpiDeclarationsDocument.PpiDeclarations; +import org.tianocore.ProtocolDeclarationsDocument.ProtocolDeclarations; + +/** + + This class is to generate a global table for the content of spd file. + +**/ +public class Spd { + /// + /// Map of module name and package it belongs to. + /// Key : Module BaseName + /// Value: Relative Path to Package + /// + Map msaInfo = new HashMap(); + + /// + /// Map of module info. + /// Key : moduletype + /// Value: moduletype related include file + /// + Map moduleInfo = new HashMap(); + + /// + /// Map of PPI info. + /// Key : PPI name + /// value: String[] a. PPI C_NAME; b. PPI GUID; + /// + Map ppiInfo = new HashMap(); + + /// + /// Map of Protocol info. + /// Key : Protocol name + /// value: String[] a. Protocol C_NAME; b. Protocol GUID; + /// + Map protocolInfo = new HashMap(); + + /// + /// Map of Guid info. + /// Key : Guid name + /// value: String[] a. Guid C_NAME; b. Guid's GUID; + /// + Map guidInfo = new HashMap(); + + + /// + /// Map of library class and its exposed header file. + /// Key : library class name + /// value : library class corresponding header file + /// + Map libClassHeaderList = new HashMap(); + + /// + /// Package path. + /// + String packagePath = null; + + /** + Constructor function + + This function mainly initialize some member variables. + + @param spdDoc Handle of spd document. + @param spdPath Path of spd file. + **/ + Spd (PackageSurfaceAreaDocument spdDoc, String spdPath) { + + PackageSurfaceArea spd = spdDoc.getPackageSurfaceArea(); + this.packagePath = spdPath; + + GuidDeclarations spdGuidInfo = spd.getGuidDeclarations(); + genGuidInfoList(spdGuidInfo); + + PpiDeclarations spdPpiInfo = spd.getPpiDeclarations(); + genPpiInfoList(spdPpiInfo); + + ProtocolDeclarations spdProtocolInfo = spd.getProtocolDeclarations(); + genProtocolInfoList(spdProtocolInfo); + + LibraryClassDeclarations spdLibClassDeclare = spd + .getLibraryClassDeclarations(); + genLibClassDeclare(spdLibClassDeclare); + + PackageHeaders spdPackageHeaderInfo = spd.getPackageHeaders(); + genModuleInfoList(spdPackageHeaderInfo); + + } + + /** + genModuleInfoList + + This function is to generate Module info map. + + @param packageHeader The information of packageHeader which descripted + in spd file. + **/ + public void genModuleInfoList(PackageHeaders packageHeader) { + + if (packageHeader != null) { + List headerList = packageHeader.getIncludeHeaderList(); + for (int i = 0; i < headerList.size(); i++) { + try { + this.moduleInfo + .put(headerList.get(i).getModuleType() + .toString(), headerList.get(i) + .getStringValue()); + } catch (Exception e) { + System.out + .print("can't find ModuleHeaders ModuleType & includeHeader!\n"); + } + } + } + } + + /** + genPpiInfoList + + This function is to generate Ppi info map. + + @param ppiInfo The information of PpiDeclarations which descripted + in spd file. + **/ + public void genPpiInfoList(PpiDeclarations ppiInfo) { + String[] cNameGuid = new String[2]; + + if (ppiInfo != null) { + List ppiEntryList = ppiInfo.getEntryList(); + for (int i = 0; i < ppiEntryList.size(); i++) { + try { + cNameGuid[0] = ppiEntryList.get(i).getCName(); + cNameGuid[1] = formatGuidName(ppiEntryList.get(i) + .getGuid().getStringValue()); + this.ppiInfo.put(ppiEntryList.get(i).getName(), new String[] { + cNameGuid[0], cNameGuid[1] }); + } catch (Exception e) { + System.out + .print("can't find GuidDeclarations C_Name & Guid!\n"); + } + } + } + } + + /** + genProtocolInfoList + + This function is to generate Protocol info map. + + @param proInfo The information of ProtocolDeclarations which + descripted in spd file. + **/ + public void genProtocolInfoList(ProtocolDeclarations proInfo) { + String[] cNameGuid = new String[2]; + if (proInfo != null) { + List protocolEntryList = proInfo.getEntryList(); + for (int i = 0; i < protocolEntryList.size(); i++) { + try { + cNameGuid[0] = protocolEntryList.get(i).getCName(); + cNameGuid[1] = formatGuidName(protocolEntryList.get(i) + .getGuid().getStringValue()); + + String temp = new String(protocolEntryList.get(i).getName()); + this.protocolInfo.put(temp, new String[] { cNameGuid[0], + cNameGuid[1] }); + } catch (Exception e) { + System.out + .print("can't find ProtocolDeclarations C_Name & Guid!\n"); + } + } + } + } + + /** + genGuidInfoList + + This function is to generate GUID inf map. + + @param guidInfo The information of GuidDeclarations which descripted + in spd file. + + **/ + public void genGuidInfoList(GuidDeclarations guidInfo) { + String[] cNameGuid = new String[2]; + if (guidInfo != null) { + + List guidEntryList = guidInfo.getEntryList(); + for (int i = 0; i < guidEntryList.size(); i++) { + cNameGuid[0] = guidEntryList.get(i).getCName(); + cNameGuid[1] = formatGuidName(guidEntryList.get(i) + .getGuid().getStringValue()); + this.guidInfo.put(guidEntryList.get(i).getName(), new String[] { + cNameGuid[0], cNameGuid[1] }); + } + } + } + + /** + genLibClassDeclare + + This function is to generate the libClassHeader list. + + @param libClassDeclares The information of LibraryClassDeclarations which + descripted in spd file. + **/ + public void genLibClassDeclare(LibraryClassDeclarations libClassDeclares) { + if (libClassDeclares != null && libClassDeclares.getLibraryClassDeclarationList() != null) { + if (libClassDeclares.getLibraryClassDeclarationList().size() > 0) { + List libDeclareList = libClassDeclares.getLibraryClassDeclarationList(); + for (int i = 0; i < libDeclareList.size(); i++) { + libClassHeaderList.put(libDeclareList.get(i).getLibraryClass() + .getStringValue(), libDeclareList.get(i) + .getIncludeHeader().getStringValue()); + } + } + } + } + + /** + getPpiGuid + + This function is to get ppi GUID according ppi name. + + @param ppiStr Name of ppi. + @return PPi's GUID. + **/ + public String getPpiGuid(String ppiStr) { + if (ppiInfo.get(ppiStr) != null) { + return ppiInfo.get(ppiStr)[1]; + } else { + return null; + } + + } + + /** + getPpiCnameGuidArray + + This function is to get the ppi CName and it's GUID according to ppi name. + + @param ppiName Name of ppi. + @return Ppi CName and it's GUID. + **/ + public String[] getPpiCnameGuidArray(String ppiName) { + return this.ppiInfo.get(ppiName); + } + + /** + getProtocolGuid + + This function is to get the protocol GUID according to protocol's name. + + @param protocolStr Name of protocol. + @return Protocol's GUID. + **/ + public String getProtocolGuid(String protocolStr) { + if (protocolInfo.get(protocolStr) != null) { + return this.protocolInfo.get(protocolStr)[0]; + } else { + return null; + } + } + + /** + getProtocolNameGuidArray + + This function is to get the protocol's CName ant it's GUID according to + protocol's namej. + + @param protocolName Name of protocl. + @return Protocol's CName and it's GUID. + **/ + public String[] getProtocolNameGuidArray(String protocolName) { + return this.protocolInfo.get(protocolName); + } + + /** + getGUIDGuid + + This function is to get the GUID according to GUID's name + + @param guidStr Name of GUID + @return GUID. + **/ + public String getGUIDGuid(String guidStr) { + if (guidInfo.get(guidStr) != null) { + return guidInfo.get(guidStr)[1]; + } else { + return null; + } + + } + + /** + getGuidNameArray + + This function is to get the GUID's CName and it's GUID according to + GUID's name + + @param guidName Name of GUID + @return CName and GUID. + **/ + public String[] getGuidNameArray(String guidName) { + return this.guidInfo.get(guidName); + } + + /** + getLibClassInclude + + This function is to get the library exposed header file name according + library class name. + + @param libName Name of library class + @return Name of header file + **/ + String getLibClassIncluder(String libName) { + return libClassHeaderList.get(libName); + } + + /** + getModuleTypeIncluder + + This function is to get the header file name from module info map + according to module type. + + @param moduleType Module type. + @return Name of header file. + **/ + String getModuleTypeIncluder(String moduleType) { + return moduleInfo.get(moduleType); + } + + /** + formateGuidName + + This function is to formate GUID to ANSI c form. + + @param guidNameCon String of GUID. + @return Formated GUID. + **/ + public static String formatGuidName (String guidNameConv) { + String[] strList; + String guid = ""; + int index = 0; + if (guidNameConv + .matches("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}")) { + strList = guidNameConv.split("-"); + guid = "0x" + strList[0] + ", "; + guid = guid + "0x" + strList[1] + ", "; + guid = guid + "0x" + strList[2] + ", "; + guid = guid + "{"; + guid = guid + "0x" + strList[3].substring(0, 2) + ", "; + guid = guid + "0x" + strList[3].substring(2, 4); + + while (index < strList[4].length()) { + guid = guid + ", "; + guid = guid + "0x" + strList[4].substring(index, index + 2); + index = index + 2; + } + guid = guid + "}"; + return guid; + } else if (guidNameConv + .matches("0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},( )*0x[a-fA-F0-9]{1,4}(,( )*\\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\\})?")) { + strList = guidNameConv.split(","); + + // + // chang Microsoft specific form to ANSI c form + // + for (int i = 0; i < 3; i++){ + guid = guid + strList[i] + ","; + } + guid = guid + "{"; + + for (int i = 3; i < strList.length; i++){ + if (i == strList.length - 1){ + guid = guid + strList[i]; + } else { + guid = guid + strList[i] + ","; + } + } + guid = guid + "}"; + return guid; + } else { + System.out.println("Check GUID Value, it don't conform to the schema!!!"); + return "0"; + + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaParser.java b/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaParser.java new file mode 100644 index 0000000000..96003c2e71 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaParser.java @@ -0,0 +1,218 @@ +/** @file + SurfaceAreaParser class. + + SurfaceAreaParser class is used to parse module surface area include both + driver and library. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.build.global; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import org.apache.tools.ant.BuildException; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.LibraryModuleBuildDescriptionDocument; +import org.tianocore.LibraryModuleSurfaceAreaDocument; +import org.tianocore.ModuleBuildDescriptionDocument; +import org.tianocore.ModuleSurfaceAreaDocument; + +/** + This class is used to parse module surface area (MSA & MBD) include both + driver and library. + + @since GenBuild 1.0 +**/ +public class SurfaceAreaParser { + + /** + Using XmlBeans to parse and valid surface area file. + + @param surfaceAreaFile the surface area file to parse + @return top level elements and its value mapping information + @throws BuildException + If surface area is not well-formed or invalid + **/ + public Map parseFile(File surfaceAreaFile) throws BuildException { + Map map = new HashMap(); + try { + XmlObject sadoc = XmlObject.Factory.parse(surfaceAreaFile); + // Validate File if they obey XML Schema + + if ( ! sadoc.validate()){ + throw new BuildException("Surface Area file [" + surfaceAreaFile.getPath() + "] is invalid."); + } + if (sadoc instanceof ModuleSurfaceAreaDocument){ + parseFile((ModuleSurfaceAreaDocument) sadoc, map); + } + else if(sadoc instanceof ModuleBuildDescriptionDocument){ + parseFile((ModuleBuildDescriptionDocument) sadoc, map); + } + else if(sadoc instanceof LibraryModuleSurfaceAreaDocument){ + parseFile((LibraryModuleSurfaceAreaDocument) sadoc, map); + } + else if(sadoc instanceof LibraryModuleBuildDescriptionDocument){ + parseFile((LibraryModuleBuildDescriptionDocument) sadoc, map); + } + } + catch (Exception ex){ + throw new BuildException(ex.getMessage()); + } + return map; + } + + + /** + Parse MSA. + + @param doc top level surface area XML document + @param msaMap the map to store the result + **/ + private void parseFile(ModuleSurfaceAreaDocument doc, Map msaMap) { + msaMap.put("MsaHeader", doc.getModuleSurfaceArea().getMsaHeader()); + msaMap.put("LibraryClassDefinitions", doc.getModuleSurfaceArea() + .getLibraryClassDefinitions()); + msaMap.put("SourceFiles", doc.getModuleSurfaceArea().getSourceFiles()); + msaMap.put("Includes", doc.getModuleSurfaceArea().getIncludes()); + msaMap.put("Protocols", doc.getModuleSurfaceArea().getProtocols()); + + msaMap.put("Events", doc.getModuleSurfaceArea().getEvents()); + msaMap.put("Hobs", doc.getModuleSurfaceArea().getHobs()); + msaMap.put("PPIs", doc.getModuleSurfaceArea().getPPIs()); + msaMap.put("Variables", doc.getModuleSurfaceArea().getVariables()); + msaMap.put("BootModes", doc.getModuleSurfaceArea().getBootModes()); + + msaMap + .put("SystemTables", doc.getModuleSurfaceArea() + .getSystemTables()); + msaMap.put("DataHubs", doc.getModuleSurfaceArea().getDataHubs()); + msaMap.put("Formsets", doc.getModuleSurfaceArea().getFormsets()); + msaMap.put("Guids", doc.getModuleSurfaceArea().getGuids()); + msaMap.put("Externs", doc.getModuleSurfaceArea().getExterns()); + + msaMap.put("PCDs", doc.getModuleSurfaceArea().getPCDs()); + msaMap + .put("BuildOptions", doc.getModuleSurfaceArea() + .getBuildOptions()); + } + + /** + Parse MBD. + + @param doc top level surface area XML document + @param msaMap the map to store the result + **/ + private void parseFile(ModuleBuildDescriptionDocument doc, Map mbdMap) { + mbdMap.put("MbdHeader", doc.getModuleBuildDescription().getMbdHeader()); + mbdMap.put("Libraries", doc.getModuleBuildDescription().getLibraries()); + mbdMap.put("SourceFiles", doc.getModuleBuildDescription() + .getSourceFiles()); + mbdMap.put("Includes", doc.getModuleBuildDescription().getIncludes()); + mbdMap.put("Protocols", doc.getModuleBuildDescription().getProtocols()); + + mbdMap.put("Events", doc.getModuleBuildDescription().getEvents()); + mbdMap.put("Hobs", doc.getModuleBuildDescription().getHobs()); + mbdMap.put("PPIs", doc.getModuleBuildDescription().getPPIs()); + mbdMap.put("Variables", doc.getModuleBuildDescription().getVariables()); + mbdMap.put("BootModes", doc.getModuleBuildDescription().getBootModes()); + + mbdMap.put("SystemTables", doc.getModuleBuildDescription() + .getSystemTables()); + mbdMap.put("DataHubs", doc.getModuleBuildDescription().getDataHubs()); + mbdMap.put("Formsets", doc.getModuleBuildDescription().getFormsets()); + mbdMap.put("Guids", doc.getModuleBuildDescription().getGuids()); + mbdMap.put("Externs", doc.getModuleBuildDescription().getExterns()); + + mbdMap.put("PCDs", doc.getModuleBuildDescription().getPCDs()); + mbdMap.put("BuildOptions", doc.getModuleBuildDescription() + .getBuildOptions()); + } + /** + Parse Library MSA. + + @param doc top level surface area XML document + @param msaMap the map to store the result + **/ + private void parseFile(LibraryModuleSurfaceAreaDocument doc, Map msaMap) { + msaMap.put("MsaLibHeader", doc.getLibraryModuleSurfaceArea() + .getMsaLibHeader()); + msaMap.put("LibraryClassDefinitions", doc.getLibraryModuleSurfaceArea() + .getLibraryClassDefinitions()); + msaMap.put("SourceFiles", doc.getLibraryModuleSurfaceArea() + .getSourceFiles()); + msaMap.put("Includes", doc.getLibraryModuleSurfaceArea().getIncludes()); + msaMap.put("Protocols", doc.getLibraryModuleSurfaceArea() + .getProtocols()); + + msaMap.put("Events", doc.getLibraryModuleSurfaceArea().getEvents()); + msaMap.put("Hobs", doc.getLibraryModuleSurfaceArea().getHobs()); + msaMap.put("PPIs", doc.getLibraryModuleSurfaceArea().getPPIs()); + msaMap.put("Variables", doc.getLibraryModuleSurfaceArea() + .getVariables()); + msaMap.put("BootModes", doc.getLibraryModuleSurfaceArea() + .getBootModes()); + + msaMap.put("SystemTables", doc.getLibraryModuleSurfaceArea() + .getSystemTables()); + msaMap.put("DataHubs", doc.getLibraryModuleSurfaceArea().getDataHubs()); + msaMap.put("Formsets", doc.getLibraryModuleSurfaceArea().getFormsets()); + msaMap.put("Guids", doc.getLibraryModuleSurfaceArea().getGuids()); + msaMap.put("Externs", doc.getLibraryModuleSurfaceArea().getExterns()); + + msaMap.put("PCDs", doc.getLibraryModuleSurfaceArea().getPCDs()); + msaMap.put("BuildOptions", doc.getLibraryModuleSurfaceArea() + .getBuildOptions()); + } + + /** + Parse Library MBD. + + @param doc top level surface area XML document + @param msaMap the map to store the result + **/ + private void parseFile(LibraryModuleBuildDescriptionDocument doc, Map mbdMap) { + mbdMap.put("MbdLibHeader", doc.getLibraryModuleBuildDescription() + .getMbdLibHeader()); + mbdMap.put("Libraries", doc.getLibraryModuleBuildDescription() + .getLibraries()); + mbdMap.put("SourceFiles", doc.getLibraryModuleBuildDescription() + .getSourceFiles()); + mbdMap.put("Includes", doc.getLibraryModuleBuildDescription() + .getIncludes()); + mbdMap.put("Protocols", doc.getLibraryModuleBuildDescription() + .getProtocols()); + + mbdMap + .put("Events", doc.getLibraryModuleBuildDescription() + .getEvents()); + mbdMap.put("Hobs", doc.getLibraryModuleBuildDescription().getHobs()); + mbdMap.put("PPIs", doc.getLibraryModuleBuildDescription().getPPIs()); + mbdMap.put("Variables", doc.getLibraryModuleBuildDescription() + .getVariables()); + mbdMap.put("BootModes", doc.getLibraryModuleBuildDescription() + .getBootModes()); + + mbdMap.put("SystemTables", doc.getLibraryModuleBuildDescription() + .getSystemTables()); + mbdMap.put("DataHubs", doc.getLibraryModuleBuildDescription() + .getDataHubs()); + mbdMap.put("Formsets", doc.getLibraryModuleBuildDescription() + .getFormsets()); + mbdMap.put("Guids", doc.getLibraryModuleBuildDescription().getGuids()); + mbdMap.put("Externs", doc.getLibraryModuleBuildDescription() + .getExterns()); + + mbdMap.put("PCDs", doc.getLibraryModuleBuildDescription().getPCDs()); + mbdMap.put("BuildOptions", doc.getLibraryModuleBuildDescription() + .getBuildOptions()); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaQuery.java b/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaQuery.java new file mode 100644 index 0000000000..03c8d4328d --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/SurfaceAreaQuery.java @@ -0,0 +1,1109 @@ +/** @file + This file is for surface area information retrieval. + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.build.global; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.xmlbeans.XmlNormalizedString; +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlString; +import org.tianocore.BuildOptionsDocument; +import org.tianocore.CName; +import org.tianocore.ExternsDocument; +import org.tianocore.FfsDocument; +import org.tianocore.FileNameConvention; +import org.tianocore.FrameworkComponentTypes; +import org.tianocore.FvImageOptionsDocument; +import org.tianocore.GuidDocument; +import org.tianocore.GuidsDocument; +import org.tianocore.LibrariesDocument; +import org.tianocore.LibraryClassDocument; +import org.tianocore.LibraryUsage; +import org.tianocore.ModuleSADocument; +import org.tianocore.ModuleTypeDef; +import org.tianocore.NameValueDocument; +import org.tianocore.OutputDirectoryDocument; +import org.tianocore.PPIsDocument; +import org.tianocore.PackageNameDocument; +import org.tianocore.ProtocolsDocument; +import org.tianocore.PCDsDocument.PCDs; + +/** + SurfaceAreaQuery class is used to query Surface Area information from msa, mbd, + spd and fpd files. + + This class should not instantiated. All the public interfaces is static. + + @since GenBuild 1.0 + **/ +public class SurfaceAreaQuery { + /// + /// Contains name/value pairs of Surface Area document object. The name is + /// always the top level element name. + /// + private static Map map = null; + + /// + /// mapStack is used to do nested query + /// + private static Stack< Map > mapStack = new Stack< Map >(); + + /// + /// prefix of name space + /// + private static String nsPrefix = "sans"; + + /// + /// xmlbeans needs a name space for each Xpath element + /// + private static String ns = null; + + /// + /// keep the namep declaration for xmlbeans Xpath query + /// + private static String queryDeclaration = null; + + /** + Set a Surface Area document for query later + + @param map A Surface Area document in TopLevelElementName/XmlObject format. + **/ + public static void setDoc(Map map) { + ns = OverrideProcess.prefix; + queryDeclaration = "declare namespace " + nsPrefix + "='" + ns + "'; "; + SurfaceAreaQuery.map = map; + } + + /** + Push current used Surface Area document into query stack. The given new + document will be used for any immediately followed getXXX() callings, + untill pop() is called. + + @param newMap The TopLevelElementName/XmlObject format of a Surface Area document. + **/ + public static void push(Map newMap) { + mapStack.push(SurfaceAreaQuery.map); + SurfaceAreaQuery.map = newMap; + } + + /** + Discard current used Surface Area document and use the top document in stack + instead. + **/ + public static void pop() { + SurfaceAreaQuery.map = mapStack.pop(); + } + + /// + /// Convert xPath to be namespace qualified, which is necessary for XmlBeans + /// selectPath(). For example, converting /MsaHeader/ModuleType to + /// /ns:MsaHeader/ns:ModuleType + /// + private static String normalizeQueryString(String[] exp, String from) { + StringBuffer normQueryString = new StringBuffer(4096); + + int i = 0; + while (i < exp.length) { + String newExp = from + exp[i]; + Pattern pattern = Pattern.compile("([^/]*)(/|//)([^/]+)"); + Matcher matcher = pattern.matcher(newExp); + + while (matcher.find()) { + String starter = newExp.substring(matcher.start(1), matcher.end(1)); + String seperator = newExp.substring(matcher.start(2), matcher.end(2)); + String token = newExp.substring(matcher.start(3), matcher.end(3)); + + normQueryString.append(starter); + normQueryString.append(seperator); + normQueryString.append(nsPrefix); + normQueryString.append(":"); + normQueryString.append(token); + } + + ++i; + if (i < exp.length) { + normQueryString.append(" | "); + } + } + + return normQueryString.toString(); + } + + /** + Search all XML documents stored in "map" for the specified xPath, using + relative path (starting with '$this') + + @param xPath xpath query string array + @returns An array of XmlObject if elements are found at the specified xpath + @returns NULL if nothing is at the specified xpath + **/ + public static XmlObject[] get(String[] xPath) { + if (map == null) { + return null; + } + + String[] keys = (String[]) map.keySet().toArray(new String[map.size()]); + List result = new ArrayList(); + for (int i = 0; i < keys.length; ++i) { + XmlObject rootNode = (XmlObject) map.get(keys[i]); + if (rootNode == null) { + continue; + } + + String query = queryDeclaration + normalizeQueryString(xPath, "$this/" + keys[i]); + XmlObject[] tmp = rootNode.selectPath(query); + for (int j = 0; j < tmp.length; ++j) { + result.add(tmp[j]); + } + } + + int size = result.size(); + if (size <= 0) { + return null; + } + + return (XmlObject[]) result.toArray(new XmlObject[size]); + } + + /** + Search XML documents named by "rootName" for the given xPath, using + relative path (starting with '$this') + + @param rootName The top level element name + @param xPath The xpath query string array + @returns An array of XmlObject if elements are found at the given xpath + @returns NULL if nothing is found at the given xpath + **/ + public static XmlObject[] get(String rootName, String[] xPath) { + if (map == null) { + return null; + } + + XmlObject root = (XmlObject) map.get(rootName); + if (root == null) { + return null; + } + + String query = queryDeclaration + normalizeQueryString(xPath, "$this/" + rootName); + XmlObject[] result = root.selectPath(query); + if (result.length > 0) { + return result; + } + + query = queryDeclaration + normalizeQueryString(xPath, "/" + rootName); + result = root.selectPath(query); + if (result.length > 0) { + return result; + } + + return null; + } + + /** + Retrieve SourceFiles/Filename for specified ARCH type + + @param arch architecture name + @returns An array of XmlObject if elements are found at the known xpath + @returns NULL if nothing is found at the known xpath + **/ + public static XmlObject[] getSourceFiles(String arch) { + String[] xPath; + + if (arch == null || arch.equals("")) { + xPath = new String[] { + "/Filename", + "/Arch/Filename" + }; + } else { + xPath = new String[] { + "/Filename[not(@ArchType) or @ArchType='ALL' or @ArchType='" + arch + "']", + "/Arch[@ArchType='ALL' or @ArchType='" + arch + "']/Filename" + }; + } + + return get("SourceFiles", xPath); + } + + /** + Retrieve BuildOptions/Ffs + + @returns FfsDocument.Ffs object if elements are found at the known xpath + @returns NULL if nothing is found at the known xpath + **/ + public static FfsDocument.Ffs getFfs() { + String[] xPath = new String[] { "/Ffs" }; + + XmlObject[] returns = get("BuildOptions", xPath); + if (returns != null && returns.length > 0) { + return (FfsDocument.Ffs) returns[0]; + } + + return null; + } + + /** + Retrieve BuildOptions/OutputDirectory + + @returns Directory names array if elements are found at the known xpath + @returns Empty if nothing is found at the known xpath + **/ + public static String[] getOutputDirectory() { + String[] xPath = new String[] { "/OutputDirectory" }; + + XmlObject[] returns = get("BuildOptions", xPath); + if (returns != null && returns.length > 0) { + String[] dirString = new String[2]; + + OutputDirectoryDocument.OutputDirectory[] dir = (OutputDirectoryDocument.OutputDirectory[]) returns; + dirString[0] = dir[0].getIntermediateDirectories().toString(); + dirString[1] = dir[0].getStringValue(); + + return dirString; + } + + return new String[] { "UNIFIED", null }; + } + + /** + Retrieve BuildOptions/Option or Arch/Option + + @param arch architecture name + + @returns name/value pairs of options if elements are found at the known xpath + @returns Empty array if nothing is there + **/ + public static String[][] getOptions(String arch){ + String[] xPath; + + if (arch == null || arch.equals("")) { + xPath = new String[] { + "/Option", + "/Arch/Option" + }; + } else { + xPath = new String[] { + "/Option", + "/Arch[@ArchType='ALL' or @ArchType='" + arch + "']/Option" + }; + } + + XmlObject[] returns = get("BuildOptions", xPath); + if (returns == null){ + return new String[0][2]; + } + + String[][] result = new String[returns.length][2]; + for (int i = 0; i < returns.length; i ++){ + String str; + String name = null; + String value = null; + + if (returns[i] instanceof BuildOptionsDocument.BuildOptions.Option) { + BuildOptionsDocument.BuildOptions.Option option = (BuildOptionsDocument.BuildOptions.Option)returns[i]; + str = option.getStringValue(); + } else if (returns[i] instanceof BuildOptionsDocument.BuildOptions.Arch.Option) { + BuildOptionsDocument.BuildOptions.Arch.Option archOption = (BuildOptionsDocument.BuildOptions.Arch.Option)returns[i]; + str = archOption.getStringValue(); + } else { + continue; + } + + int equalIndex = str.indexOf('='); + if ( equalIndex > 0) { + name = str.substring(0, equalIndex).trim(); + value = str.substring(equalIndex + 1).trim(); + // TBD remove some forbidden name: BASE_NAME, ARCH and so on + if (name.length() == 0){ + name = null; + } + } + result[i][0] = name; + result[i][1] = value; + } + + return result; + } + + /** + Retrieve /ModuleType + + @returns The module type name if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getModuleType() { + String[] xPath = new String[] { "/ModuleType" }; + + XmlObject[] returns = get(xPath); + if (returns != null && returns.length > 0) { + ModuleTypeDef type = (ModuleTypeDef) returns[0]; + return type.enumValue().toString(); + } + + return null; + } + + /** + Retrieve /ComponentType + + @returns The component type name if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getComponentType() { + String[] xPath = new String[] { "/ComponentType" }; + + XmlObject[] returns = get(xPath); + if (returns != null && returns.length > 0) { + FrameworkComponentTypes type = (FrameworkComponentTypes) returns[0]; + return type.enumValue().toString(); + } + + return null; + } + + /** + Retrieve Includes/PackageName + + @param arch Architecture name + + @returns package name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static List getIncludePackageName(String arch) { + String[] xPath; + + if (arch == null || arch.equals("")) { + xPath = new String[] { + "/PackageName", + "/Arch/PackageName" + }; + } else { + xPath = new String[] { + "/PackageName", + "/Arch[@ArchType='ALL' or @ArchType='" + arch + "']/PackageName" + }; + } + + XmlObject[] returns = get("Includes", xPath); + if (returns == null || returns.length == 0) { + return null; + } + + List packageNames = new ArrayList(); + PackageNameDocument.PackageName[] nameObj = (PackageNameDocument.PackageName[])returns; + for (int i = 0; i < returns.length; ++i) { + packageNames.add(nameObj[i].getStringValue()); + } + + return packageNames; + } + + /** + Retrieve LibraryClassDefinitions/LibraryClass for specified usage + + @param usage Library class usage + + @returns LibraryClass objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static LibraryClassDocument.LibraryClass[] getLibraryClassArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] {"/LibraryClass"}; + } else { + xPath = new String[] {"/LibraryClass[@Usage='" + usage + "']"}; + } + + XmlObject[] returns = get("LibraryClassDefinitions", xPath); + if (returns != null && returns.length > 0) { + return (LibraryClassDocument.LibraryClass[]) returns; + } + + return null; + } + + /** + Retrieve ModuleEntryPoint names + + @returns ModuleEntryPoint name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getModuleEntryPointArray() { + String[] xPath = new String[] { "/Extern/ModuleEntryPoint" }; + + XmlObject[] returns = get("Externs", xPath); + + if (returns != null && returns.length > 0) { + String[] entryPoints = new String[returns.length]; + + for (int i = 0; i < returns.length; ++i) { + entryPoints[i] = ((XmlNormalizedString) returns[i]) + .getStringValue(); + } + + return entryPoints; + } + + return null; + } + + /** + Retrieve module Guid string + + @returns GUILD string if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getModuleGuid() { + String[] xPath = new String[] { "/Guid" }; + + XmlObject[] returns = get(xPath); + if (returns != null && returns.length > 0) { + GuidDocument.Guid guid = (GuidDocument.Guid) returns[0]; + return guid.getStringValue(); + } + + return null; + } + + /** + retrieve Protocol for specified usage + + @param usage Protocol usage + + @returns Protocol objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static ProtocolsDocument.Protocols.Protocol[] getProtocolArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] {"/Protocol"}; + } else { + xPath = new String[] {"/Protocol[@Usage='" + usage + "']"}; + } + + XmlObject[] returns = get("Protocols", xPath); + if (returns != null && returns.length > 0) { + return (ProtocolsDocument.Protocols.Protocol[]) returns; + } + + return null; + } + + /** + Retrieve ProtocolNotify for specified usage + + @param usage ProtocolNotify usage + + @returns ProtocolNotify objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static ProtocolsDocument.Protocols.ProtocolNotify[] getProtocolNotifyArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] {"/ProtocolNotify"}; + } else { + xPath = new String[] {"/ProtocolNotify[@Usage='" + usage + "']"}; + } + + XmlObject[] returns = get("Protocols", xPath); + if (returns != null && returns.length > 0) { + return (ProtocolsDocument.Protocols.ProtocolNotify[]) returns; + } + + return null; + } + + /** + Retrieve ModuleUnloadImage names + + @returns ModuleUnloadImage name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getModuleUnloadImageArray() { + String[] xPath = new String[] { "/Extern/ModuleUnloadImage" }; + + XmlObject[] returns = get("Externs", xPath); + if (returns != null && returns.length > 0) { + String[] stringArray = new String[returns.length]; + XmlNormalizedString[] doc = (XmlNormalizedString[])returns; + + for (int i = 0; i < returns.length; ++i) { + stringArray[i] = doc[i].getStringValue(); + } + + return stringArray; + } + + return null; + } + + /** + Retrieve Extern + + @returns Extern objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static ExternsDocument.Externs.Extern[] getExternArray() { + String[] xPath = new String[] { "/Extern" }; + + XmlObject[] returns = get("Externs", xPath); + if (returns != null && returns.length > 0) { + return (ExternsDocument.Externs.Extern[]) returns; + } + + return null; + } + + /** + Retrieve Ppi information + + @param usage Ppi usage + + @returns Ppi objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static PPIsDocument.PPIs.Ppi[] getPpiArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] { "/Ppi" }; + } else { + xPath = new String[] { "/Ppi[@Usage='" + usage + "']" }; + } + + XmlObject[] returns = get("PPIs", xPath); + if (returns != null && returns.length > 0) { + return (PPIsDocument.PPIs.Ppi[])returns; + } + + return null; + } + + /** + Retrive PpiNotify information + + @param usage + + @returns PpiNotify objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static PPIsDocument.PPIs.PpiNotify[] getPpiNotifyArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] { "/PpiNotify" }; + } else { + xPath = new String[] { "/PpiNotify[@Usage='" + usage + "']" }; + } + + XmlObject[] returns = get("PPIs", xPath); + if (returns != null && returns.length > 0) { + return (PPIsDocument.PPIs.PpiNotify[])returns; + } + + return null; + } + + /** + Retrieve GuidEntry information for specified usage + + @param usage GuidEntry usage + + @returns GuidEntry objects list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static GuidsDocument.Guids.GuidEntry[] getGuidEntryArray(String usage) { + String[] xPath; + + if (usage == null || usage.equals("")) { + xPath = new String[] { "/GuidEntry" }; + } else { + xPath = new String[] { "/GuidEntry[@Usage='" + usage + "']" }; + } + + XmlObject[] returns = get("Guids", xPath); + if (returns != null && returns.length > 0) { + return (GuidsDocument.Guids.GuidEntry[])returns; + } + + return null; + } + + /** + Retrieve Library instance information + + @param arch Architecture name + @param usage Library instance usage + + @returns library instance name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static List getLibraryInstance(String arch, String usage) { + String[] xPath; + String archAttribute = ""; + String usageAttribute = ""; + + if ((arch != null) || (!arch.equals(""))) { + archAttribute = "[@ArchType='ALL' or @ArchType='" + arch + "']"; + } + + if ((usage != null) || (!usage.equals(""))) { + // if no Usage attribute specified, default to ALWAYS_CONSUMED + if (usage.equals(LibraryUsage.ALWAYS_CONSUMED.toString())) { + usageAttribute = "[not(@Usage) or @Usage='" + usage + "']"; + } else { + usageAttribute = "[@Usage='" + usage + "']"; + } + } + + xPath = new String[] { + "/Library" + usageAttribute, + "/Arch" + archAttribute + "/Library" + usageAttribute + }; + + XmlObject[] returns = get("Libraries", xPath); + if (returns == null || returns.length == 0) { + return null; + } + + List instances = new ArrayList(); + for (int i = 0; i < returns.length; ++i) { + if (returns[i] instanceof LibrariesDocument.Libraries.Library) { + LibrariesDocument.Libraries.Library lib = (LibrariesDocument.Libraries.Library)returns[i]; + instances.add(lib.getStringValue()); + } else if (returns[i] instanceof LibrariesDocument.Libraries.Arch.Library) { + LibrariesDocument.Libraries.Arch.Library lib = (LibrariesDocument.Libraries.Arch.Library)returns[i]; + instances.add(lib.getStringValue()); + } + } + + return instances; + } + + /// + /// This method is used for retrieving the elements information which has + /// CName sub-element + /// + private static String[] getCNames(String from, String xPath[]) { + XmlObject[] returns = get(from, xPath); + if (returns == null || returns.length == 0) { + return null; + } + + String[] strings = new String[returns.length]; + for (int i = 0; i < returns.length; ++i) { + strings[i] = ((CName)returns[i]).getStringValue(); + } + + return strings; + } + + /** + Retrive library's constructor name + + @returns constructor name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getLibConstructorName() { + String[] xPath = new String[] {"/Extern/Constructor"}; + + XmlObject[] returns = get("Externs", xPath); + if (returns != null && returns.length > 0) { + CName constructor = (CName)returns[0]; + return constructor.getStringValue(); + } + + return null; + } + + /** + Retrive library's destructor name + + @returns destructor name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getLibDestructorName() { + String[] xPath = new String[] {"/Extern/Destructor"}; + + XmlObject[] returns = get("Externs", xPath); + if (returns != null && returns.length > 0) { + CName destructor = (CName)returns[0]; + return destructor.getStringValue(); + } + + return null; + } + + /** + Retrive DriverBinding names + + @returns DriverBinding name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getDriverBindingArray() { + String[] xPath = new String[] {"/Extern/DriverBinding"}; + return getCNames("Externs", xPath); + } + + /** + Retrive ComponentName names + + @returns ComponentName name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getComponentNameArray() { + String[] xPath = new String[] {"/Extern/ComponentName"}; + return getCNames("Externs", xPath); + } + + /** + Retrive DriverConfig names + + @returns DriverConfig name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getDriverConfigArray() { + String[] xPath = new String[] {"/Extern/DriverConfig"}; + return getCNames("Externs", xPath); + } + + /** + Retrive DriverDiag names + + @returns DriverDiag name list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getDriverDiagArray() { + String[] xPath = new String[] {"/Extern/DriverDiag"}; + return getCNames("Externs", xPath); + } + + /** + Retrive SetVirtualAddressMapCallBack names + + @returns SetVirtualAddressMapCallBack name list + if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getSetVirtualAddressMapCallBackArray() { + String[] xPath = new String[] {"/Extern/SetVirtualAddressMapCallBack"}; + return getCNames("Externs", xPath); + } + + /** + Retrive ExitBootServicesCallBack names + + @returns ExitBootServicesCallBack name list + if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[] getExitBootServicesCallBackArray() { + String[] xPath = new String[] {"/Extern/ExitBootServicesCallBack"}; + return getCNames("Externs", xPath); + } + + /** + Retrieve module surface area file information + + @returns ModuleSA objects list if elements are found at the known xpath + @returns Empty ModuleSA list if nothing is there + **/ + public static ModuleSADocument.ModuleSA[] getFpdModules() { + String[] xPath = new String[] { "/TianoImage/*/ModuleSA" }; + + XmlObject[] result = get("FrameworkPlatformDescription", xPath); + if (result == null) { + return new ModuleSADocument.ModuleSA[0]; + } + + return (ModuleSADocument.ModuleSA[]) result; + } + + /** + Retrieve variables for FV images + + @returns name/value list if elements are found at the known xpath + @returns empty list if nothing is there + **/ + public static String[][] getFpdGlobalVariable() { + String[] xPath = new String[] { "/Flash/FvImages/NameValue" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null) { + return new String[0][]; + } + + String[][] result = new String[queryResult.length][2]; + for (int i = 0; i < queryResult.length; i++){ + result[i][0] = ((NameValueDocument.NameValue)queryResult[i]).getName(); + result[i][1] = ((NameValueDocument.NameValue)queryResult[i]).getValue(); + } + + return result; + } + + /** + Retrieve valid image names + + @returns valid iamges name list if elements are found at the known xpath + @returns empty list if nothing is there + **/ + public static String[] getFpdValidImageNames(){ + String[] xPath = new String[] { "/Flash/FvImages/FvImage[@Type='ValidImageNames']/FvImageNames" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null) { + return new String[0]; + } + + String[] result = new String[queryResult.length]; + for (int i = 0; i < queryResult.length; i++){ + result[i] = ((XmlString)queryResult[i]).getStringValue(); + } + + return result; + } + + /** + Retrieve FV image option information + + @param fvName FV image name + + @returns option name/value list if elements are found at the known xpath + @returns empty list if nothing is there + **/ + public static String[][] getFpdOptions(String fvName){ + String[] xPath = new String[] {"/Flash/FvImages/FvImageName[@Name='" + fvName.toUpperCase() + "']/FvImageOptions/NameValue" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null) { + return new String[0][]; + } + + String[][] result = new String[queryResult.length][2]; + for (int i = 0; i < queryResult.length; i++){ + result[i][0] = ((NameValueDocument.NameValue)queryResult[i]).getName(); + result[i][1] = ((NameValueDocument.NameValue)queryResult[i]).getValue(); + } + + return result; + } + + /** + Retrieve FV image attributes information + + @param fvName FV image name + + @returns attribute name/value list if elements are found at the known xpath + @returns empty list if nothing is there + **/ + public static String[][] getFpdAttributes(String fvName){ + String[] xPath = new String[] {"/Flash/FvImages/FvImage[@Type='Attributes' and ./FvImageNames='" + fvName.toUpperCase() + "']/FvImageOptions" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null) { + return new String[0][]; + } + + ArrayList list = new ArrayList(); + for (int i = 0 ; i < queryResult.length; i++){ + FvImageOptionsDocument.FvImageOptions item = (FvImageOptionsDocument.FvImageOptions)queryResult[i]; + + List namevalues = item.getNameValueList(); + Iterator iter = namevalues.iterator(); + while (iter.hasNext()) { + NameValueDocument.NameValue nvItem = (NameValueDocument.NameValue)iter.next(); + list.add(new String[]{nvItem.getName(), nvItem.getValue()}); + } + + List enables = item.getEnableList(); + iter = enables.iterator(); + while (iter.hasNext()) { + String enableItem = (String)iter.next(); + list.add(new String[]{enableItem, "TRUE"}); + } + + List disables = item.getDisableList(); + iter = disables.iterator(); + while (iter.hasNext()) { + String disableItem = (String)iter.next(); + list.add(new String[]{disableItem, "FALSE"}); + } + } + + String[][] result = new String[list.size()][2]; + for (int i = 0; i < list.size(); i++){ + result[i][0] = list.get(i)[0]; + result[i][1] = list.get(i)[1]; + } + + return result; + } + + /** + Retrieve flash definition file name + + @returns file name if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String getFlashDefinitionFile(){ + String[] xPath = new String[] {"/Flash/FlashDefinitionFile" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null || queryResult.length == 0) { + return null; + } + + FileNameConvention filename = (FileNameConvention)queryResult[queryResult.length - 1]; + return filename.getStringValue(); + } + + /** + Retrieve FV image component options + + @param fvName FV image name + + @returns name/value pairs list if elements are found at the known xpath + @returns empty list if nothing is there + **/ + public static String[][] getFpdComponents(String fvName){ + String[] xPath = new String[] {"/Flash/FvImages/FvImage[@Type='Components' and ./FvImageNames='" + fvName.toUpperCase() + "']/FvImageOptions" }; + + XmlObject[] queryResult = get("FrameworkPlatformDescription", xPath); + if (queryResult == null) { + return new String[0][]; + } + + ArrayList list = new ArrayList(); + for (int i = 0 ; i < queryResult.length; i++){ + FvImageOptionsDocument.FvImageOptions item = (FvImageOptionsDocument.FvImageOptions)queryResult[i]; + + List namevalues = item.getNameValueList(); + Iterator iter = namevalues.iterator(); + while (iter.hasNext()) { + NameValueDocument.NameValue nvItem = (NameValueDocument.NameValue)iter.next(); + list.add(new String[]{nvItem.getName(), nvItem.getValue()}); + } + + List enables = item.getEnableList(); + iter = enables.iterator(); + while (iter.hasNext()) { + String enableItem = (String)iter.next(); + list.add(new String[]{enableItem, "TRUE"}); + } + + List disables = item.getDisableList(); + iter = disables.iterator(); + while (iter.hasNext()) { + String disableItem = (String)iter.next(); + list.add(new String[]{disableItem, "FALSE"}); + } + } + + String[][] result = new String[list.size()][2]; + for (int i = 0; i < list.size(); i++){ + result[i][0] = list.get(i)[0]; + result[i][1] = list.get(i)[1]; + } + + return result; + } + + /** + Retrieve PCD tokens + + @returns CName/ItemType pairs list if elements are found at the known xpath + @returns null if nothing is there + **/ + public static String[][] getPcdTokenArray() { + String[] xPath = new String[] {"/PcdData"}; + + XmlObject[] returns = get("PCDs", xPath); + if (returns == null || returns.length == 0) { + return null; + } + + PCDs.PcdData[] pcds = (PCDs.PcdData[]) returns; + String[][] result = new String[pcds.length][2]; + for (int i = 0; i < returns.length; ++i) { + if (pcds[i].getItemType() != null) { + result[i][1] = pcds[i].getItemType().toString(); + } else { + result[i][1] = null; + } + result[i][0] = pcds[i].getCName(); + } + + return result; + } + + /** + Get the PcdToken array from module's surface area document. + The array should contains following data: +

-------------------------------------------------------------------

+

CName | ItemType | TokenspaceName | DefaultValue | Usage | HelpText

+

-------------------------------------------------------------------

+

Note: Until new schema applying, now we can only get CName, ItemType,

+ + @return 2-array table contains all information of PCD token retrieved from MSA. + **/ + public static Object[][] getModulePCDTokenArray () { + int index; + Object[][] result; + PCDs.PcdData[] pcds; + String[] xPath = new String[] {"/PcdData"}; + XmlObject[] returns = get ("PCDs", xPath); + + if ((returns == null) || (returns.length == 0)) { + return null; + } + + pcds = (PCDs.PcdData[]) returns; + result = new Object[pcds.length][6]; + for (index = 0; index < pcds.length; index ++) { + // + // Get CName + // + result [index][0] = pcds[index].getCName(); + // + // Get ItemType: FEATURE_FLAG, FIXED_AT_BUILD, PATCHABLE_IN_MODLE, DYNAMIC, DYNAMIC_EX + // + if (pcds[index].getItemType() != null) { + result [index][1] = pcds[index].getItemType().toString(); + } else { + result [index][1] = null; + } + + // + // BUGBUG: following field can *not* be got from current MSA until schema changed. + // + //result [index][2] = pcds[index].getTokenSpaceName(); + result [index][2] = null; + result [index][3] = pcds[index].getDefaultValue(); + //result [index][4] = pcds[index].getUsage (); + result [index][4] = null; + //result [index][5] = pcds[index].getHelpText (); + result [index][5] = null; + } + return result; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/global/VariableTask.java b/Tools/Source/GenBuild/org/tianocore/build/global/VariableTask.java new file mode 100644 index 0000000000..f830e0ac76 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/global/VariableTask.java @@ -0,0 +1,71 @@ +/** @file + * This file is ANT task VariableTask. + * + * VariableTask task implements part of ANT property task. The difference is + * this task will override variable with same name, but ANT property task do not. + * + * Copyright (c) 2006, 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. + */ +package org.tianocore.build.global; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +/** + * VariableTask task implements part of ANT property task. The difference is + * this task will override variable with same name, but ANT property task do not. + * + * @since GenBuild 1.0 + */ +public class VariableTask extends Task { + + /** + * property value + */ + private String value; + + /** + * property name + */ + private String name; + + /** + * Set property name. + * + * @param name property name + */ + public void setName( String name ) { + this.name = name; + } + + + /** + * Set property value. + * + * @param value property value + */ + public void setValue( String value ) { + this.value = value; + } + + /** + * ANT task's entry point, will be called after init(). + * + * @exception BuildException + * If name or value is null + */ + public void execute() throws BuildException { + if (name == null || value == null) { + throw new BuildException("Name or value must not null."); + } + getProject().setProperty(name, value); + } +} + diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ActionMessage.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ActionMessage.java new file mode 100644 index 0000000000..a67d2f9e4d --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ActionMessage.java @@ -0,0 +1,129 @@ +/** @file + ActionMessage class. + + ActionMessage class take over all message for loging and waning. This class should + dispatch message into different class according to instance class type. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.action; + +import org.apache.tools.ant.Task; +import org.tianocore.build.pcd.action.BuildAction; +import org.tianocore.build.pcd.action.UIAction; + +/** ActionMessage class take over all message for loging and waning. This class + should dispatch message into different Action class according to instance + class type. +**/ +public class ActionMessage { + /// + /// Macro definition for NULL messge level. + /// In this meessage level, all message will be hidden. + /// + public final static int NULL_MESSAGE_LEVEL = 0; + /// + /// Macro definition for Log messge level. + /// In this message level, Only log information will be shown. + /// + public final static int LOG_MESSAGE_LEVEL = 1; + /// + /// Macro definition for Warning message level. + /// In this message level, log and waning message will be shown. + /// + public final static int WARNING_MESSAGE_LEVEL = 2; + /// + /// Macro definition for Debug mesage level. + /// In this message level, log, warning, debug message will be shown. + /// + public final static int DEBUG_MESSAGE_LEVEL = 3; + /// + /// Macor definition for MAX message level. + /// In this message level, all message will be shown. + /// + public final static int MAX_MESSAGE_LEVEL = 4; + /// + /// Current message level. It will control all message output for PCD tool. + /// + public static int messageLevel = NULL_MESSAGE_LEVEL; + + /** + Log() function provide common log information functionality for all + PCD tool includes all function + + This function will dispatch message to special class such as BuildAction + Class, Entity Class etc. + + @param thisClass The class object who want log information. + @param logStr The string contains log information. + **/ + public static void log(Object thisClass, String logStr) { + if(messageLevel < LOG_MESSAGE_LEVEL) { + return; + } + + if(thisClass instanceof Task) { + BuildAction.logMsg(thisClass, "$$LOG$$:" + logStr); + } else if(thisClass instanceof UIAction) { + UIAction.logMsg(thisClass, "$$LOG$$:" + logStr); + } else { + System.out.println("$$LOG$$:" + logStr); + } + } + + /** + Warning() function provide common warning information functionality for all + PCD tool. + + This function will dispatch message to special class such as BuildAction + Class, Entity Class etc. + + @param thisClass The class object who want warn information. + @param warningStr The string contains warning information. + **/ + public static void warning(Object thisClass, String warningStr) { + if(messageLevel < WARNING_MESSAGE_LEVEL) { + return; + } + + if(thisClass instanceof Task) { + BuildAction.warningMsg(thisClass, "**WARNING**:" + warningStr); + } else if(thisClass instanceof UIAction) { + UIAction.warningMsg(thisClass, "**WARNING**:" + warningStr); + } else { + System.out.println("**WARNING**:" + warningStr); + } + } + + /** + Debug() function provide common Debug information functionality for all + PCD tool. + + This function will dispatch message to special class such as BuildAction + Class, Entity Class etc. + + @param thisClass The class object who want Debug information. + @param debugStr The string contains Debug information. + **/ + public static void debug(Object thisClass, String debugStr) { + if(messageLevel < DEBUG_MESSAGE_LEVEL) { + return; + } + + if(thisClass instanceof Task) { + BuildAction.logMsg(thisClass, "%%DEBUG%%:" + debugStr); + } else if(thisClass instanceof UIAction) { + UIAction.logMsg(thisClass, "%%DEBUG%%:" + debugStr); + } else { + System.out.println("%%DEBUG%%:" + debugStr); + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/BuildAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/BuildAction.java new file mode 100644 index 0000000000..c8b0d9dba1 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/BuildAction.java @@ -0,0 +1,114 @@ +/** @file + BuildAction class. + + BuildAction is the parent class for all action related to ant Task. This class will + define some common utility functionality, such as logMsg, warningMsg..etc. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.action; + +import org.apache.tools.ant.Task; +import org.tianocore.build.pcd.exception.BuildActionException; + +/** BuildAction is the parent class for all action related to ant Task. This class will + define some common utility functionality, such as logMsg, warningMsg..etc. +**/ +abstract class BuildAction extends Task { + /// + /// Original message level before this action. This value will + /// be restored when quit this action. + /// + private int originalMessageLevel; + + /** + checkParameter function check all parameter valid. + + This function will be overrided by child class. + **/ + abstract void checkParameter() throws BuildActionException; + + /** + performAction is to execute the detail action. + + This function will be overrided by child class. + **/ + abstract void performAction() throws BuildActionException; + + /** + setMessageLevel function set current message for task instance object. + + The message should be restored when this action exit. + + @param messageLevel The message level for this action. + **/ + public void setMessageLevel(int messageLevel) { + originalMessageLevel = ActionMessage.messageLevel; + ActionMessage.messageLevel = messageLevel; + } + + /** + logMsg function provide common log information functionality for all + PCD tool extends from ANT task class. + + This function will use the log function in Ant task class. + + @param action The class object who want log information. + @param logStr The string contains log information. + **/ + public static void logMsg(Object action, String logStr) { + // + // Comment following code because in console debug environment, we can't + // get Project instance. + //((Task) action).log(errorText, Project.MSG_INFO); + // + System.out.println(logStr); + } + + /** + warningMsg function provide common warning information functionality for all + PCD tool. + + This function will dispatch message to special class such as BuildAction + Class, Entity Class etc. + + @param action The class object who want warn information. + @param warningStr The string contains warning information. + **/ + public static void warningMsg(Object action, String warningStr) { + // + // Comment following code because in console debug environment, we can't + // get Project instance. + //((Task) action).log(warningText, Project.MSG_WARN); + // + System.out.println(warningStr); + } + + /** + execute function is the main flow for all build action class. + + This workflow will be: + 1) Check paramet of this action. + 2) Perform the child class action function. + 3) Restore the message level. + + @throws BuildActionException + **/ + public void execute() throws BuildActionException { + checkParameter(); + performAction(); + + // + // Restore orignal message level when exist the action. + // + ActionMessage.messageLevel = originalMessageLevel; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java new file mode 100644 index 0000000000..055563df1b --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/CollectPCDAction.java @@ -0,0 +1,669 @@ +/** @file + CollectPCDAction class. + + This action class is to collect PCD information from MSA, SPD, FPD xml file. + This class will be used for wizard and build tools, So it can *not* inherit + from buildAction or wizardAction. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.action; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.FrameworkPlatformDescriptionDocument; +import org.tianocore.ModuleSADocument; +import org.tianocore.PackageSurfaceAreaDocument; +import org.tianocore.PcdBuildDeclarationsDocument.PcdBuildDeclarations.PcdBuildData; +import org.tianocore.PcdDefinitionsDocument.PcdDefinitions; +import org.tianocore.build.autogen.CommonDefinition; +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.global.SurfaceAreaQuery; +import org.tianocore.build.pcd.action.ActionMessage; +import org.tianocore.build.pcd.entity.MemoryDatabaseManager; +import org.tianocore.build.pcd.entity.SkuInstance; +import org.tianocore.build.pcd.entity.Token; +import org.tianocore.build.pcd.entity.UsageInstance; +import org.tianocore.build.pcd.exception.EntityException; + +/** This action class is to collect PCD information from MSA, SPD, FPD xml file. + This class will be used for wizard and build tools, So it can *not* inherit + from buildAction or UIAction. +**/ +public class CollectPCDAction { + /// memoryDatabase hold all PCD information collected from SPD, MSA, FPD. + private MemoryDatabaseManager dbManager; + + /// Workspacepath hold the workspace information. + private String workspacePath; + + /// FPD file is the root file. + private String fpdFilePath; + + /// Message level for CollectPCDAction. + private int originalMessageLevel; + + /** + Set WorkspacePath parameter for this action class. + + @param workspacePath parameter for this action + **/ + public void setWorkspacePath(String workspacePath) { + this.workspacePath = workspacePath; + } + + /** + Set action message level for CollectPcdAction tool. + + The message should be restored when this action exit. + + @param actionMessageLevel parameter for this action + **/ + public void setActionMessageLevel(int actionMessageLevel) { + originalMessageLevel = ActionMessage.messageLevel; + ActionMessage.messageLevel = actionMessageLevel; + } + + /** + Set FPDFileName parameter for this action class. + + @param fpdFilePath fpd file path + **/ + public void setFPDFilePath(String fpdFilePath) { + this.fpdFilePath = fpdFilePath; + } + + /** + Common function interface for outer. + + @param workspacePath The path of workspace of current build or analysis. + @param fpdFilePath The fpd file path of current build or analysis. + @param messageLevel The message level for this Action. + + @throws Exception The exception of this function. Because it can *not* be predict + where the action class will be used. So only Exception can be throw. + + **/ + public void perform(String workspacePath, String fpdFilePath, + int messageLevel) throws Exception { + setWorkspacePath(workspacePath); + setFPDFilePath(fpdFilePath); + setActionMessageLevel(messageLevel); + checkParameter(); + execute(); + ActionMessage.messageLevel = originalMessageLevel; + } + + /** + Core execution function for this action class. + + This function work flows will be: + 1) Get all token's platform information from FPD, and create token object into memory database. + 2) Get all token's module information from MSA, and create usage instance for every module's PCD entry. + 3) Get all token's inherited information from MSA's library, and create usage instance + for module who consume this library and create usage instance for library for building. + 4) Collect token's package information from SPD, update these information for token in memory + database. + + @throws EntityException Exception indicate failed to execute this action. + + **/ + private void execute() throws EntityException { + FrameworkPlatformDescriptionDocument fpdDoc = null; + Object[][] modulePCDArray = null; + Map docMap = null; + ModuleSADocument.ModuleSA[] moduleSAs = null; + UsageInstance usageInstance = null; + String packageName = null; + String packageFullPath = null; + int index = 0; + int libraryIndex = 0; + int pcdArrayIndex = 0; + List listLibraryInstance = null; + String componentTypeStr = null; + + // + // Collect all PCD information defined in FPD file. + // Evenry token defind in FPD will be created as an token into + // memory database. + // + fpdDoc = createTokenInDBFromFPD(); + + // + // Searching MSA and SPD document. + // The information of MSA will be used to create usage instance into database. + // The information of SPD will be used to update the token information in database. + // + + HashMap map = new HashMap(); + map.put("FrameworkPlatformDescription", fpdDoc); + SurfaceAreaQuery.setDoc(map); + + moduleSAs = SurfaceAreaQuery.getFpdModules(); + for(index = 0; index < moduleSAs.length; index ++) { + // + // Get module document and use SurfaceAreaQuery to get PCD information + // + docMap = GlobalData.getDoc(moduleSAs[index].getModuleName()); + SurfaceAreaQuery.setDoc(docMap); + modulePCDArray = SurfaceAreaQuery.getModulePCDTokenArray(); + componentTypeStr = SurfaceAreaQuery.getComponentType(); + packageName = + GlobalData.getPackageNameForModule(moduleSAs[index].getModuleName()); + packageFullPath = this.workspacePath + File.separator + + GlobalData.getPackagePath(packageName) + + packageName + ".spd"; + + if(modulePCDArray != null) { + // + // If current MSA contains information, then create usage + // instance for PCD information from MSA + // + for(pcdArrayIndex = 0; pcdArrayIndex < modulePCDArray.length; + pcdArrayIndex ++) { + usageInstance = + createUsageInstanceFromMSA(moduleSAs[index].getModuleName(), + modulePCDArray[pcdArrayIndex]); + + if(usageInstance == null) { + continue; + } + // + // Get remaining PCD information from the package which this module belongs to + // + updateTokenBySPD(usageInstance, packageFullPath); + } + } + + // + // Get inherit PCD information which inherit from library instance of this module. + // + listLibraryInstance = + SurfaceAreaQuery.getLibraryInstance(moduleSAs[index].getArch().toString(), + CommonDefinition.AlwaysConsumed); + if(listLibraryInstance != null) { + for(libraryIndex = 0; libraryIndex < listLibraryInstance.size(); + libraryIndex ++) { + inheritPCDFromLibraryInstance(listLibraryInstance.get(libraryIndex), + moduleSAs[index].getModuleName(), + packageName, + componentTypeStr); + } + } + } + } + + /** + This function will collect inherit PCD information from library for a module. + + This function will create two usage instance for inherited PCD token, one is + for module and another is for library. + For module, if it inherited a PCD token from library, this PCD token's value + should be instanced in module level, and belongs to module. + For library, it also need a usage instance for build. + + @param libraryName The name of library instance. + @param moduleName The name of module. + @param packageName The name of package while module belongs to. + @param parentcomponentType The component type of module. + + @throws EntityException If the token does *not* exist in memory database. + + **/ + private void inheritPCDFromLibraryInstance(String libraryName, + String moduleName, + String packageName, + String parentcomponentType) + throws EntityException { + Map docMap = null; + String primaryKeyString = null; + Object[][] libPcdDataArray = null; + UUID nullUUID = new UUID(0,0); + UUID platformUUID = nullUUID; + UUID tokenSpaceGuid = null; + int tokenIndex = 0; + Token token = null; + Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN; + UsageInstance usageInstance = null; + String packageFullPath = null; + + // + // Query PCD information from library's document. + // + docMap = GlobalData.getDoc(libraryName); + SurfaceAreaQuery.setDoc(docMap); + libPcdDataArray = SurfaceAreaQuery.getModulePCDTokenArray(); + + if(libPcdDataArray == null) { + return; + } + + for(tokenIndex = 0; tokenIndex < libPcdDataArray.length; tokenIndex ++) { + tokenSpaceGuid =((UUID)libPcdDataArray[tokenIndex][2] == null) ? + nullUUID :(UUID)libPcdDataArray[tokenIndex][2]; + + // + // Get token from memory database. The token must be created from FPD already. + // + primaryKeyString = Token.getPrimaryKeyString((String)libPcdDataArray[tokenIndex][0], + tokenSpaceGuid, + platformUUID + ); + + if(dbManager.isTokenInDatabase(primaryKeyString)) { + token = dbManager.getTokenByKey(primaryKeyString); + } else { + throw new EntityException("The PCD token " + primaryKeyString + + " defined in module " + moduleName + + " does not exist in FPD file!"); + } + + // + // Create usage instance for module. + // + pcdType = Token.getpcdTypeFromString((String)libPcdDataArray[tokenIndex][1]); + usageInstance = new UsageInstance(token, + Token.PCD_USAGE.ALWAYS_CONSUMED, + pcdType, + CommonDefinition.getComponentType(parentcomponentType), + libPcdDataArray[tokenIndex][3], + null, + (String) libPcdDataArray[tokenIndex][5], + "", + moduleName, + packageName, + true); + if(Token.PCD_USAGE.UNKNOWN == token.isUsageInstanceExist(moduleName)) { + token.addUsageInstance(usageInstance); + + packageFullPath = this.workspacePath + File.separator + + GlobalData.getPackagePath(packageName) + + packageName + ".spd"; + updateTokenBySPD(usageInstance, packageFullPath); + } + + // + // We need create second usage instance for inherited case, which + // add library as an usage instance, because when build a module, and + // if module inherited from base library, then build process will build + // library at first. + // + if(Token.PCD_USAGE.UNKNOWN == token.isUsageInstanceExist(libraryName)) { + packageName = GlobalData.getPackageNameForModule(libraryName); + usageInstance = new UsageInstance(token, + Token.PCD_USAGE.ALWAYS_CONSUMED, + pcdType, + CommonDefinition.ComponentTypeLibrary, + libPcdDataArray[tokenIndex][3], + null, + (String)libPcdDataArray[tokenIndex][5], + "", + libraryName, + packageName, + false); + token.addUsageInstance(usageInstance); + } + } + } + + /** + Create usage instance for PCD token defined in MSA document + + A PCD token maybe used by many modules, and every module is one of usage + instance of this token. For ALWAY_CONSUMED, SOMETIMES_CONSUMED, it is + consumer type usage instance of this token, and for ALWAYS_PRODUCED, + SOMETIMES_PRODUCED, it is produce type usage instance. + + @param moduleName The name of module + @param tokenInfoInMsa The PCD token information array retrieved from MSA. + + @return UsageInstance The usage instance created in memroy database. + + @throws EntityException If token did not exist in database yet. + + **/ + private UsageInstance createUsageInstanceFromMSA(String moduleName, + Object[] tokenInfoInMsa) + throws EntityException { + String packageName = null; + UsageInstance usageInstance = null; + UUID tokenSpaceGuid = null; + UUID nullUUID = new UUID(0,0); + String primaryKeyString = null; + UUID platformTokenSpace = nullUUID; + Token token = null; + Token.PCD_TYPE pcdType = Token.PCD_TYPE.UNKNOWN; + Token.PCD_USAGE pcdUsage = Token.PCD_USAGE.UNKNOWN; + + tokenSpaceGuid =((UUID)tokenInfoInMsa[2] == null) ? nullUUID :(UUID)tokenInfoInMsa[2]; + + primaryKeyString = Token.getPrimaryKeyString((String)tokenInfoInMsa[0], + tokenSpaceGuid, + platformTokenSpace); + + // + // Get token object from memory database firstly. + // + if(dbManager.isTokenInDatabase(primaryKeyString)) { + token = dbManager.getTokenByKey(primaryKeyString); + } else { + throw new EntityException("The PCD token " + primaryKeyString + " defined in module " + + moduleName + " does not exist in FPD file!" ); + } + pcdType = Token.getpcdTypeFromString((String)tokenInfoInMsa[1]); + pcdUsage = Token.getUsageFromString((String)tokenInfoInMsa[4]); + + packageName = GlobalData.getPackageNameForModule(moduleName); + + if(Token.PCD_USAGE.UNKNOWN != token.isUsageInstanceExist(moduleName)) { + // + // BUGBUG: It should *not* throw exception here. Becaues in MdePkg.fpd, + // more than on BaseLib exist. But why? need confirmation. + // + //throw new EntityException( + // "In module " + moduleName + " exist more than one PCD token " + token.cName + // ); + ActionMessage.warning(this, + "In module " + moduleName + " exist more than one PCD token " + token.cName + ); + return null; + } + + // + // BUGBUG: following code could be enabled at current schema. Because + // current schema does not provide usage information. + // + // For FEATRURE_FLAG, FIXED_AT_BUILD, PATCH_IN_MODULE type PCD token, his + // usage is always ALWAYS_CONSUMED + // + //if((pcdType != Token.PCD_TYPE.DYNAMIC) && + // (pcdType != Token.PCD_TYPE.DYNAMIC_EX)) { + pcdUsage = Token.PCD_USAGE.ALWAYS_CONSUMED; + //} + + usageInstance = new UsageInstance(token, + pcdUsage, + pcdType, + CommonDefinition.getComponentType(SurfaceAreaQuery.getComponentType()), + tokenInfoInMsa[3], + null, + (String) tokenInfoInMsa[5], + "", + moduleName, + packageName, + false); + + // + // Use default value defined in MSA to update datum of token, + // if datum of token does not defined in FPD file. + // + if((token.datum == null) &&(tokenInfoInMsa[3] != null)) { + token.datum = tokenInfoInMsa[3]; + } + + token.addUsageInstance(usageInstance); + + return usageInstance; + } + + /** + Create token instance object into memory database, the token information + comes for FPD file. Normally, FPD file will contain all token platform + informations. + + This fucntion should be executed at firsly before others collection work + such as searching token information from MSA, SPD. + + @return FrameworkPlatformDescriptionDocument The FPD document instance for furture usage. + + @throws EntityException Failed to parse FPD xml file. + + **/ + private FrameworkPlatformDescriptionDocument createTokenInDBFromFPD() + throws EntityException { + XmlObject doc = null; + FrameworkPlatformDescriptionDocument fpdDoc = null; + int index = 0; + List pcdBuildDataArray = new ArrayList(); + PcdBuildData pcdBuildData = null; + Token token = null; + UUID nullUUID = new UUID(0,0); + UUID platformTokenSpace= nullUUID; + List skuDataArray = new ArrayList(); + SkuInstance skuInstance = null; + int skuIndex = 0; + + // + // Get all tokens from FPD file and create token into database. + // + + try { + doc = XmlObject.Factory.parse(new File(fpdFilePath)); + } catch(IOException ioE) { + throw new EntityException("Can't find the FPD xml fle:" + fpdFilePath); + } catch(XmlException xmlE) { + throw new EntityException("Can't parse the FPD xml fle:" + fpdFilePath); + } + + // + // Get memoryDatabaseManager instance from GlobalData. + // + if((dbManager = GlobalData.getPCDMemoryDBManager()) == null) { + throw new EntityException("The instance of PCD memory database manager is null"); + } + + dbManager = new MemoryDatabaseManager(); + + if(!(doc instanceof FrameworkPlatformDescriptionDocument)) { + throw new EntityException("File " + fpdFilePath + + " is not a FrameworkPlatformDescriptionDocument"); + } + + fpdDoc =(FrameworkPlatformDescriptionDocument)doc; + + // + // Add all tokens in FPD into Memory Database. + // + pcdBuildDataArray = + fpdDoc.getFrameworkPlatformDescription().getPcdBuildDeclarations().getPcdBuildDataList(); + for(index = 0; + index < fpdDoc.getFrameworkPlatformDescription().getPcdBuildDeclarations().sizeOfPcdBuildDataArray(); + index ++) { + pcdBuildData = pcdBuildDataArray.get(index); + token = new Token(pcdBuildData.getCName(), new UUID(0, 0), new UUID(0, 0)); + // + // BUGBUG: in FPD, should be defined as + // + token.datum = pcdBuildData.getDefaultValue(); + token.hiiEnabled = pcdBuildData.getHiiEnable(); + token.variableGuid = Token.getGUIDFromSchemaObject(pcdBuildData.getVariableGuid()); + token.variableName = pcdBuildData.getVariableName(); + token.variableOffset = Integer.decode(pcdBuildData.getDataOffset()); + token.skuEnabled = pcdBuildData.getSkuEnable(); + token.maxSkuCount = Integer.decode(pcdBuildData.getMaxSku()); + token.skuId = Integer.decode(pcdBuildData.getSkuId()); + token.skuDataArrayEnabled = pcdBuildData.getSkuDataArrayEnable(); + token.assignedtokenNumber = Integer.decode(pcdBuildData.getToken().getStringValue()); + skuDataArray = pcdBuildData.getSkuDataArray1(); + + if(skuDataArray != null) { + for(skuIndex = 0; skuIndex < skuDataArray.size(); skuIndex ++) { + // + // BUGBUG: Now in current schema, The value is defined as String type, + // it is not correct, the type should be same as the datumType + // + skuInstance = new SkuInstance(((PcdBuildData.SkuData)skuDataArray.get(skuIndex)).getId(), + ((PcdBuildData.SkuData)skuDataArray.get(skuIndex)).getValue()); + token.skuData.add(skuInstance); + } + } + + if(dbManager.isTokenInDatabase(Token.getPrimaryKeyString(token.cName, + token.tokenSpaceName, + platformTokenSpace))) { + // + // If found duplicate token, Should tool be hold? + // + ActionMessage.warning(this, + "Token " + token.cName + " exists in token database"); + continue; + } + token.pcdType = Token.getpcdTypeFromString(pcdBuildData.getItemType().toString()); + dbManager.addTokenToDatabase(Token.getPrimaryKeyString(token.cName, + token.tokenSpaceName, + platformTokenSpace), + token); + } + + return fpdDoc; + } + + /** + Update PCD token in memory database by help information in SPD. + + After create token from FPD and create usage instance from MSA, we should collect + PCD package level information from SPD and update token information in memory + database. + + @param usageInstance The usage instance defined in MSA and want to search in SPD. + @param packageFullPath The SPD file path. + + @throws EntityException Failed to parse SPD xml file. + + **/ + private void updateTokenBySPD(UsageInstance usageInstance, + String packageFullPath) + throws EntityException { + PackageSurfaceAreaDocument pkgDoc = null; + List pcdEntryArray = new ArrayList(); + int index; + boolean isFoundInSpd = false; + Token.DATUM_TYPE datumType = Token.DATUM_TYPE.UNKNOWN; + + try { + pkgDoc =(PackageSurfaceAreaDocument)XmlObject.Factory.parse(new File(packageFullPath)); + } catch(IOException ioE) { + throw new EntityException("Can't find the FPD xml fle:" + packageFullPath); + } catch(XmlException xmlE) { + throw new EntityException("Can't parse the FPD xml fle:" + packageFullPath); + } + + pcdEntryArray = pkgDoc.getPackageSurfaceArea().getPcdDefinitions().getPcdEntryList(); + for(index = 0; index < pcdEntryArray.size(); index ++) { + if(pcdEntryArray.get(index).getCName().equalsIgnoreCase( + usageInstance.parentToken.cName)) { + isFoundInSpd = true; + // + // From SPD file , we can get following information. + // Token: Token number defined in package level. + // PcdItemType: This item does not single one. It means all supported item type. + // datumType: UINT8, UNIT16, UNIT32, UINT64, VOID*, BOOLEAN + // datumSize: The size of default value or maxmine size. + // defaultValue: This value is defined in package level. + // HelpText: The help text is provided in package level. + // + + usageInstance.parentToken.tokenNumber = Integer.decode(pcdEntryArray.get(index).getToken()); + + if(pcdEntryArray.get(index).getDatumType() != null) { + datumType = Token.getdatumTypeFromString( + pcdEntryArray.get(index).getDatumType().toString()); + if(usageInstance.parentToken.datumType == Token.DATUM_TYPE.UNKNOWN) { + usageInstance.parentToken.datumType = datumType; + } else { + if(datumType != usageInstance.parentToken.datumType) { + throw new EntityException("Different datum types are defined for Token :" + + usageInstance.parentToken.cName); + } + } + + } else { + throw new EntityException("The datum type for token " + usageInstance.parentToken.cName + + " is not defind in SPD file " + packageFullPath); + } + + usageInstance.defaultValueInSPD = pcdEntryArray.get(index).getDefaultValue(); + usageInstance.helpTextInSPD = "Help Text in SPD"; + + // + // If token's datum is not valid, it indicate that datum is not provided + // in FPD and defaultValue is not provided in MSA, then use defaultValue + // in SPD as the datum of token. + // + if(usageInstance.parentToken.datum == null) { + if(pcdEntryArray.get(index).getDefaultValue() != null) { + usageInstance.parentToken.datum = pcdEntryArray.get(index).getDefaultValue(); + } else { + throw new EntityException("FPD does not provide datum for token " + usageInstance.parentToken.cName + + ", MSA and SPD also does not provide for this token!"); + } + } + } + } + + if(!isFoundInSpd ) { + ActionMessage.warning(this, + "Can *not* find the PCD token " + usageInstance.parentToken.cName + + " in SPD file!"); + } + } + + /** + check parameter for this action. + + @throws EntityException Bad parameter. + **/ + private void checkParameter() throws EntityException { + File file = null; + + if((fpdFilePath == null) ||(workspacePath == null)) { + throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!"); + } + + if(fpdFilePath.length() == 0 || workspacePath.length() == 0) { + throw new EntityException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!"); + } + + file = new File(workspacePath); + if(!file.exists()) { + throw new EntityException("WorkpacePath " + workspacePath + " does not exist!"); + } + + file = new File(fpdFilePath); + + if(!file.exists()) { + throw new EntityException("FPD File " + fpdFilePath + " does not exist!"); + } + } + + /** + Test case function + + @param argv parameter from command line + **/ + public static void main(String argv[]) throws EntityException { + CollectPCDAction ca = new CollectPCDAction(); + ca.setWorkspacePath("G:/mdk"); + ca.setFPDFilePath("G:/mdk/EdkNt32Pkg/build/Nt32.fpd"); + ca.setActionMessageLevel(ActionMessage.MAX_MESSAGE_LEVEL); + GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db", + "G:/mdk"); + ca.execute(); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/PCDAutoGenAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/PCDAutoGenAction.java new file mode 100644 index 0000000000..ca65c7546c --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/PCDAutoGenAction.java @@ -0,0 +1,452 @@ +/** @file + PCDAutoGenAction class. + + This class is to manage how to generate the PCD information into Autogen.c and + Autogen.h. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.action; + +import java.io.File; +import java.util.List; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.pcd.entity.MemoryDatabaseManager; +import org.tianocore.build.pcd.entity.Token; +import org.tianocore.build.pcd.entity.UsageInstance; +import org.tianocore.build.pcd.exception.BuildActionException; +import org.tianocore.build.pcd.exception.EntityException; + +/** This class is to manage how to generate the PCD information into Autogen.c and + Autogen.h. +**/ +public class PCDAutoGenAction extends BuildAction { + /// + /// The reference of DBManager in GlobalData class. + /// + private MemoryDatabaseManager dbManager; + /// + /// The name of module which is analysised currently. + /// + private String moduleName; + /// + /// Wheter current module is PCD emulated driver. It is only for + /// emulated PCD driver and will be kept until PCD IMAGE tool ready. + /// + private boolean isEmulatedPCDDriver; + /// + /// The generated string for header file. + /// + private String hAutoGenString; + /// + /// The generated string for C code file. + /// + private String cAutoGenString; + + /** + Set parameter ModuleName + + @param moduleName the module name parameter. + **/ + public void setModuleName(String moduleName) { + this.moduleName = moduleName; + } + + /** + Set parameter isEmulatedPCDDriver + + @param isEmulatedPCDDriver whether this module is PeiEmulatedPCD driver + **/ + public void setIsEmulatedPCDDriver(boolean isEmulatedPCDDriver) { + this.isEmulatedPCDDriver = isEmulatedPCDDriver; + } + + /** + Get the output of generated string for header file. + + @return the string of header file for PCD + **/ + public String OutputH() { + return hAutoGenString; + } + + /** + Get the output of generated string for C Code file. + + @return the string of C code file for PCD + **/ + public String OutputC() { + return cAutoGenString; + } + + /** + Construct function + + This function mainly initialize some member variable. + + @param moduleName Parameter of this action class. + @param isEmulatedPCDDriver Parameter of this action class. + **/ + public PCDAutoGenAction(String moduleName, boolean isEmulatedPCDDriver) { + dbManager = null; + setIsEmulatedPCDDriver(isEmulatedPCDDriver); + setModuleName(moduleName); + } + + /** + check the parameter for action class. + + @throws BuildActionException Bad parameter. + **/ + void checkParameter() throws BuildActionException { + if(!isEmulatedPCDDriver &&(moduleName == null)) { + throw new BuildActionException("Wrong module name parameter for PCDAutoGenAction tool!"); + } + + if(!isEmulatedPCDDriver && moduleName.length() == 0) { + throw new BuildActionException("Wrong module name parameter for PCDAutoGenAction tool!"); + } + + // + // Check the PCD memory database manager is valid. + // + if(GlobalData.getPCDMemoryDBManager() == null) { + throw new BuildActionException("Memory database has not been initlizated!"); + } + + dbManager = GlobalData.getPCDMemoryDBManager(); + + if(dbManager.getDBSize() == 0) { + throw new BuildActionException("Memory database does not contain any record!"); + } + + ActionMessage.debug(this, + "PCD memory database contains " + dbManager.getDBSize() + " PCD tokens"); + } + + /** + Core execution function for this action class. + + All PCD information of this module comes from memory dabase. The collection + work should be done before this action execution. + Currently, we should generated all PCD information(maybe all dynamic) as array + in Pei emulated driver for simulating PCD runtime database. + + @throws BuildActionException Failed to execute this aciton class. + **/ + void performAction() throws BuildActionException { + ActionMessage.debug(this, + "Starting PCDAutoGenAction to generate autogen.h and autogen.c!..."); + + hAutoGenString = ""; + cAutoGenString = ""; + + if(isEmulatedPCDDriver) { + generateAutogenForPCDEmulatedDriver(); + } else { + generateAutogenForModule(); + } + } + + /** + Generate the autogen string for a common module. + + All PCD information of this module comes from memory dabase. The collection + work should be done before this action execution. + **/ + private void generateAutogenForModule() + { + int index; + List usageInstanceArray; + + usageInstanceArray = dbManager.getUsageInstanceArrayByModuleName(moduleName); + + if(usageInstanceArray.size() != 0) { + // + // Add "#include 'PcdLib.h'" for Header file + // + hAutoGenString = "#include \r\n"; + } + + for(index = 0; index < usageInstanceArray.size(); index ++) { + ActionMessage.debug(this, + "Module " + moduleName + "'s PCD [" + Integer.toHexString(index) + + "]: " + usageInstanceArray.get(index).parentToken.cName); + try { + usageInstanceArray.get(index).generateAutoGen(); + hAutoGenString += usageInstanceArray.get(index).getHAutogenStr() + "\r\n"; + cAutoGenString += usageInstanceArray.get(index).getCAutogenStr() + "\r\n"; + } catch(EntityException exp) { + throw new BuildActionException(exp.getMessage()); + } + } + + ActionMessage.debug(this, + "Module " + moduleName + "'s PCD header file:\r\n" + hAutoGenString + "\r\n" + ); + ActionMessage.debug(this, + "Module " + moduleName + "'s PCD C file:\r\n" + cAutoGenString + "\r\n" + ); + } + + /** + Generate all PCD autogen string and the emulated PCD IMAGE array for emulated driver. + + Currently, we should generated all PCD information(maybe all dynamic) as array + in Pei emulated driver for simulating PCD runtime database. + + **/ + private void generateAutogenForPCDEmulatedDriver() { + int index; + Token[] tokenArray; + UsageInstance usageInstance; + + // + // Add "#include 'PcdLib.h'" for Header file + // + hAutoGenString = "#include \r\n"; + + tokenArray = dbManager.getRecordArray(); + for(index = 0; index < tokenArray.length; index ++) { + // + // Get one consumer instance and generate autogen for this token. + // + if(tokenArray[index].consumers != null ) { + if(tokenArray[index].consumers.size() == 0) { + continue; + } + + usageInstance = tokenArray[index].consumers.get(0); + try { + usageInstance.generateAutoGen(); + } catch(EntityException exp) { + throw new BuildActionException(exp.getMessage()); + } + + hAutoGenString += usageInstance.getHAutogenStr(); + cAutoGenString += usageInstance.getCAutogenStr(); + + hAutoGenString += "\r\n"; + cAutoGenString += "\r\n"; + } + } + + generatePCDEmulatedArray(tokenArray); + + ActionMessage.debug(this, + "PCD emulated driver's header: \r\n" + hAutoGenString + "\r\n" + ); + ActionMessage.debug(this, + "PCD emulated driver's C code: \r\n" + cAutoGenString + "\r\n" + ); + + } + + /** + Generate PCDEmulated array in PCDEmulated driver for emulated runtime database. + + @param tokenArray All PCD token in memory database. + + @throws BuildActionException Unknown PCD_TYPE + **/ + private void generatePCDEmulatedArray(Token[] tokenArray) + throws BuildActionException { + int index; + Token token; + String[] guidStrArray; + String value; + + // + // The value of String type of PCD entry maybe use byte array but not string direcly + // such as {0x1, 0x2, 0x3}, and define PCD1_STRING_Value as L"string define here" + // For this case, we should generate a string array to C output and use the address + // of generated string array. + // + for(index = 0; index < tokenArray.length; index ++) { + token = tokenArray[index]; + + if((token.producers.size() == 0) &&(token.consumers.size() == 0)) { + // + // If no one use this PCD token, it will not generated in emulated array. + // + continue; + } + value = token.datum.toString(); + if(token.datumType == Token.DATUM_TYPE.POINTER) { + if(!((value.charAt(0) == 'L' && value.charAt(1) == '"') ||(value.charAt(0) == '"'))) { + cAutoGenString += String.format("UINT8 _mPcdArray%08x[] = %s;\r\n", + index, + value + ); + } + } + } + + // + // Output emulated PCD entry array + // + cAutoGenString += "\r\nEMULATED_PCD_ENTRY gEmulatedPcdEntry[] = {\r\n"; + + for(index = 0; index < tokenArray.length; index ++) { + token = tokenArray[index]; + + if((token.producers.size() == 0) &&(token.consumers.size() == 0)) { + // + // If no one use this PCD token, it will not generated in emulated array. + // + continue; + } + + if(index != 0) { + cAutoGenString += ",\r\n"; + } + + // + // Print Start "{" for a Token item in array + // + cAutoGenString += " {\r\n"; + + // + // Print Token Name + // + cAutoGenString += String.format(" _PCD_TOKEN_%s,\r\n", token.cName); + + // + // Print Hii information + // + if(token.hiiEnabled) { + cAutoGenString += String.format(" TRUE,\r\n"); + } else { + cAutoGenString += String.format(" FALSE,\r\n"); + } + + // + // Print sku information + // + if(token.skuEnabled) { + cAutoGenString += String.format(" TRUE,\r\n"); + } else { + cAutoGenString += String.format(" FALSE,\r\n"); + } + + // + // Print maxSkuCount + // + cAutoGenString += String.format(" %d,\r\n", token.maxSkuCount); + + cAutoGenString += String.format(" %d,\r\n", token.skuId); + + if(token.variableGuid == null) { + cAutoGenString += " { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },\r\n"; + } else { + guidStrArray =(token.variableGuid.toString()).split("-"); + + cAutoGenString += String.format(" { 0x%s, 0x%s, 0x%s, { 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s, 0x%s } },\r\n", + guidStrArray[0], + guidStrArray[1], + guidStrArray[2], + (guidStrArray[3].substring(0, 2)), + (guidStrArray[3].substring(2, 4)), + (guidStrArray[4].substring(0, 2)), + (guidStrArray[4].substring(2, 4)), + (guidStrArray[4].substring(4, 6)), + (guidStrArray[4].substring(6, 8)), + (guidStrArray[4].substring(8, 10)), + (guidStrArray[4].substring(10, 12)) + ); + + } + + value = token.datum.toString(); + if(token.datumType == Token.DATUM_TYPE.POINTER) { + if((value.charAt(0) == 'L' && value.charAt(1) == '"') || value.charAt(0) == '"') { + cAutoGenString += String.format(" sizeof(_PCD_VALUE_%s),\r\n", token.cName); + cAutoGenString += String.format(" 0, %s, %s,\r\n", token.variableName, value); + } else { + cAutoGenString += String.format(" sizeof(_mPcdArray%08x),\r\n", index); + cAutoGenString += String.format(" 0, &_mPcdArray%08x, %s,\r\n", index, token.variableName); + } + } else { + switch(token.datumType) { + case UINT8: + cAutoGenString += " 1,\r\n"; + break; + case UINT16: + cAutoGenString += " 2,\r\n"; + break; + case UINT32: + cAutoGenString += " 4,\r\n"; + break; + case UINT64: + cAutoGenString += " 8,\r\n"; + break; + case BOOLEAN: + cAutoGenString += " 1,\r\n"; + break; + default: + throw new BuildActionException("Unknown datum size"); + } + cAutoGenString += String.format(" %s, %s, NULL,\r\n", value, token.variableName); + } + + // + // Print end "}" for a token item in array + // + cAutoGenString += " }"; + } + + cAutoGenString += "\r\n};\r\n"; + cAutoGenString += "\r\n"; + cAutoGenString += "UINTN\r\n"; + cAutoGenString += "GetPcdDataBaseSize(\r\n"; + cAutoGenString += " VOID\r\n"; + cAutoGenString += " )\r\n"; + cAutoGenString += "{\r\n"; + cAutoGenString += " return sizeof(gEmulatedPcdEntry);\r\n"; + cAutoGenString += "}\r\n"; + } + + /** + Test case function + + @param argv paramter from command line + **/ + public static void main(String argv[]) { + String logFilePath = "G:/mdk/EdkNt32Pkg/build/Nt32.fpd"; + + // + // At first, CollectPCDAction should be invoked to collect + // all PCD information from SPD, MSA, FPD. + // + CollectPCDAction collectionAction = new CollectPCDAction(); + GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db", + "G:/mdk"); + + GlobalData.getPCDMemoryDBManager().setLogFileName(logFilePath + ".PCDMemroyDatabaseLog.txt"); + + try { + collectionAction.perform("G:/mdk", + logFilePath, + ActionMessage.MAX_MESSAGE_LEVEL); + } catch(Exception e) { + e.printStackTrace(); + } + + // + // Then execute the PCDAuotoGenAction to get generated Autogen.h and Autogen.c + // + PCDAutoGenAction autogenAction = new PCDAutoGenAction("HelloWorld", + true + ); + autogenAction.execute(); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ShowPCDDatabaseAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ShowPCDDatabaseAction.java new file mode 100644 index 0000000000..cd67dd46c9 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/ShowPCDDatabaseAction.java @@ -0,0 +1,130 @@ +/** @file + ShowPCDDatabase class. + + This class is the action to diplay the PCD database. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.action; + +import java.io.File; + +import org.tianocore.build.global.GlobalData; +import org.tianocore.build.pcd.exception.UIException; +import org.tianocore.build.pcd.ui.PCDDatabaseFrame; + +/** This class is the action to show PCD database. +**/ +public class ShowPCDDatabaseAction extends UIAction { + /// + /// The workspace path parameter. + /// + private String workspacePath; + /// + /// The FpdfileName parameter. + /// + private String fpdFilePath; + + /** + set workspace path parameter for this action. + + @param workspacePath the string of workspace path. + **/ + public void setWorkspacePath(String workspacePath) { + this.workspacePath = workspacePath; + } + + /** + set fpd file path parameter for this action. + + @param fpdFilePath file path string + **/ + public void setFPDFilePath(String fpdFilePath) { + this.fpdFilePath = "./" + fpdFilePath; + } + + /** + check paramter for this action. + + @throw UIException wrong paramter. + **/ + void checkParamter() throws UIException { + File file = null; + + if((fpdFilePath == null) ||(workspacePath == null)) { + throw new UIException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!"); + } + + if(fpdFilePath.length() == 0 || workspacePath.length() == 0) { + throw new UIException("WorkspacePath and FPDFileName should be blank for CollectPCDAtion!"); + } + + file = new File(workspacePath); + if(!file.exists()) { + throw new UIException("WorkpacePath " + workspacePath + " does not exist!"); + } + + file = new File(fpdFilePath); + + if(!file.exists()) { + throw new UIException("FPD File " + fpdFilePath + " does not exist!"); + } + } + + /** + Core workflow function. + + @throw UIException Fail to show PCD database. + **/ + void performAction() throws UIException { + CollectPCDAction collectAction = null; + PCDDatabaseFrame dbFrame = null; + + // + // Initialize global data. + // + GlobalData.initInfo("Tools" + File.separator + "Conf" + File.separator + "FrameworkDatabase.db", + workspacePath); + GlobalData.getPCDMemoryDBManager().setLogFileName(fpdFilePath + ".PCDMemroyDatabaseLog.txt"); + + // + // Collect PCD information. + // + collectAction = new CollectPCDAction(); + + try { + collectAction.perform(workspacePath, + fpdFilePath, + ActionMessage.LOG_MESSAGE_LEVEL); + } catch(Exception exp) { + throw new UIException(exp.getMessage()); + } + + // + // Start tree windows. + // + dbFrame = new PCDDatabaseFrame(GlobalData.getPCDMemoryDBManager()); + } + + /** + Entry function. + + The action is run from command line. + + @param argv command line parameter. + **/ + public static void main(String[] argv) throws UIException { + ShowPCDDatabaseAction showAction = new ShowPCDDatabaseAction(); + showAction.setWorkspacePath(argv[0]); + showAction.setFPDFilePath(argv[1]); + showAction.execute(); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/action/UIAction.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/UIAction.java new file mode 100644 index 0000000000..2cde9b24ec --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/action/UIAction.java @@ -0,0 +1,83 @@ +/** @file + UIAction class. + + This class is the parent action class of UI wizard. + +Copyright (c) 2006, 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. + +**/ + +package org.tianocore.build.pcd.action; + +import org.tianocore.build.pcd.exception.UIException; + +/** This class is the parent class for all UI wizard action. +**/ +public abstract class UIAction { + /// + /// original message level. when finish this action, original + /// message level will be restored. + /// + private int originalMessageLevel; + + /** + Check the parameter for this aciton. + + This function will be overrided by child class. + **/ + abstract void checkParamter() throws UIException; + + /** + Perform action. + + This function will be overrided by child class. + **/ + abstract void performAction() throws UIException; + + /** + set the message level for this action. + + @param messageLevel message level wanted. + **/ + public void setMessageLevel(int messageLevel) { + originalMessageLevel = ActionMessage.messageLevel; + ActionMessage.messageLevel = messageLevel; + } + + /** + log message for UI wizard aciton. + + @param actionObj aciton instance object. + @param logStr log message string + **/ + public static void logMsg(Object actionObj, String logStr) { + System.out.println(logStr); + } + + /** + Warning message for UI wizard action. + + @param warningObj action instance object. + @param warningStr warning message string. + **/ + public static void warningMsg(Object warningObj, String warningStr) { + System.out.println(warningStr); + } + + /** + Entry function for all UI wizard actions. + **/ + public void execute() throws UIException { + checkParamter(); + performAction(); + + ActionMessage.messageLevel = originalMessageLevel; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/MemoryDatabaseManager.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/MemoryDatabaseManager.java new file mode 100644 index 0000000000..6f4f8949ef --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/MemoryDatabaseManager.java @@ -0,0 +1,306 @@ +/** @file + MemoryDatabaseManager class. + + Database hold all PCD information comes from SPD, MSA, FPD file in memory. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.entity; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.tianocore.build.autogen.CommonDefinition; +import org.tianocore.build.pcd.action.ActionMessage; + +/** Database hold all PCD information comes from SPD, MSA, FPD file in memory. +**/ +public class MemoryDatabaseManager { + /// + /// Memory database. The string "cName + SpaceNameGuid" is primary key. + /// memory database is in global scope, and it will be used for others PCD tools. + /// + private static Map memoryDatabase = null; + /// + /// The log file name for dumping memory database. + /// + private static String logFileName = null; + + /** + Constructure function + **/ + public MemoryDatabaseManager() { + // + // Allocate memory for new database in global scope. + // + if (memoryDatabase == null) { + memoryDatabase = new HashMap(); + } + } + + /** + Get the log file name. + **/ + public String getLogFileName() { + return logFileName; + } + + /** + Set parameter log file name. + + @param fileName log file name parameter. + **/ + public void setLogFileName(String fileName) { + logFileName = fileName; + } + + /** + Judege whether token exists in memory database + + @param primaryKey the primaryKey for searching token + + @retval TRUE - token already exist in database. + @retval FALSE - token does not exist in database. + **/ + public boolean isTokenInDatabase(String primaryKey) { + return (memoryDatabase.get(primaryKey) != null); + } + + /** + Add a pcd token into memory database. + + @param primaryKey the primary key for searching token + @param token token instance + **/ + public void addTokenToDatabase(String primaryKey, Token token) { + memoryDatabase.put(primaryKey, token); + } + + /** + Get a token instance from memory database with primary key. + + @param primaryKey the primary key for searching token + + @return token instance. + **/ + public Token getTokenByKey(String primaryKey) { + return memoryDatabase.get(primaryKey); + } + + /** + Get the number of PCD token record in memory database. + + @return the number of PCD token record in memory database. + **/ + public int getDBSize() { + return memoryDatabase.size(); + } + + /** + Get the token record array contained all PCD token in memory database. + + @return the token record array contained all PCD token in memory database. + **/ + public Token[] getRecordArray() { + Token[] tokenArray = null; + Object[] dataArray = null; + Map.Entry entry = null; + int index = 0; + + if (memoryDatabase == null) { + return null; + } + + dataArray = memoryDatabase.entrySet().toArray(); + tokenArray = new Token[memoryDatabase.size()]; + for (index = 0; index < memoryDatabase.size(); index ++) { + entry =(Map.Entry) dataArray [index]; + tokenArray[index] =(Token) entry.getValue(); + } + + return tokenArray; + } + + /** + Get all PCD record for a module according to module's name. + + @param moduleName the name of module. + + @return all usage instance for this module in memory database. + **/ + public List getUsageInstanceArrayByModuleName(String moduleName) { + Token[] tokenArray = null; + int recordIndex = 0; + int usageInstanceIndex = 0; + List usageInstanceArray = null; + UsageInstance usageInstance = null; + List returnArray = new ArrayList(); + + tokenArray = getRecordArray(); + + // + // Loop to find all PCD record related to current module + // + for (recordIndex = 0; recordIndex < getDBSize(); recordIndex ++) { + if (tokenArray[recordIndex].producers != null) { + usageInstanceArray = tokenArray[recordIndex].producers; + for (usageInstanceIndex = 0; usageInstanceIndex < usageInstanceArray.size(); usageInstanceIndex ++) { + usageInstance =(UsageInstance) usageInstanceArray.get(usageInstanceIndex); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + returnArray.add(usageInstance); + } + } + } + + if (tokenArray[recordIndex].consumers != null) { + usageInstanceArray = tokenArray[recordIndex].consumers; + for (usageInstanceIndex = 0; usageInstanceIndex < usageInstanceArray.size(); usageInstanceIndex ++) { + usageInstance =(UsageInstance) usageInstanceArray.get(usageInstanceIndex); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + returnArray.add(usageInstance); + } + } + } + } + + if (returnArray.size() == 0) { + ActionMessage.warning(this, "Can *not* find any usage instance for " + moduleName + " !"); + } + + return returnArray; + } + + /** + Get all modules name who contains PCD information + + @return Array for module name + **/ + public List getAllModuleArray() + { + int indexToken = 0; + int usageIndex = 0; + int moduleIndex = 0; + Token[] tokenArray = null; + List moduleNames = new ArrayList(); + UsageInstance usageInstance = null; + boolean bFound = false; + + tokenArray = this.getRecordArray(); + // + // Find all producer usage instance for retrieving module's name + // + for (indexToken = 0; indexToken < getDBSize(); indexToken ++) { + for (usageIndex = 0; usageIndex < tokenArray[indexToken].producers.size(); usageIndex ++) { + usageInstance = tokenArray[indexToken].producers.get(usageIndex); + bFound = false; + for (moduleIndex = 0; moduleIndex < moduleNames.size(); moduleIndex ++) { + if (moduleNames.get(moduleIndex).equalsIgnoreCase(usageInstance.moduleName)) { + bFound = true; + break; + } + } + if (!bFound) { + moduleNames.add(usageInstance.moduleName); + } + } + } + + // + // Find all consumer usage instance for retrieving module's name + // + for (indexToken = 0; indexToken < getDBSize(); indexToken ++) { + for (usageIndex = 0; usageIndex < tokenArray[indexToken].consumers.size(); usageIndex ++) { + usageInstance = tokenArray[indexToken].consumers.get(usageIndex); + bFound = false; + for (moduleIndex = 0; moduleIndex < moduleNames.size(); moduleIndex ++) { + if (moduleNames.get(moduleIndex).equalsIgnoreCase(usageInstance.moduleName)) { + bFound = true; + break; + } + } + if (!bFound) { + moduleNames.add(usageInstance.moduleName); + } + } + } + return moduleNames; + } + + /** + Dump all PCD record into file for reviewing. + **/ + public void DumpAllRecords() { + BufferedWriter bWriter = null; + Object[] tokenArray = null; + Map.Entry entry = null; + Token token = null; + int index = 0; + int usageIndex = 0; + UsageInstance usageInstance = null; + String inheritString = null; + String componentTypeName = null; + + try { + bWriter = new BufferedWriter(new FileWriter(new File(logFileName))); + tokenArray = memoryDatabase.entrySet().toArray(); + for (index = 0; index < memoryDatabase.size(); index ++) { + entry =(Map.Entry) tokenArray [index]; + token =(Token) entry.getValue(); + bWriter.write("****** token [" + Integer.toString(index) + "] ******\r\n"); + bWriter.write(" cName:" + token.cName + "\r\n"); + for (usageIndex = 0; usageIndex < token.producers.size(); usageIndex ++) { + usageInstance =(UsageInstance)token.producers.get(usageIndex); + componentTypeName = CommonDefinition.getComponentTypeString(usageInstance.componentType); + + if (usageInstance.isInherit) { + inheritString = "Inherit"; + } else { + inheritString = ""; + } + bWriter.write(String.format(" (Producer)#%d: %s:%s Package:%s %s\r\n", + usageIndex, + componentTypeName, + usageInstance.moduleName, + usageInstance.packageName, + inheritString + ) + ); + } + for (usageIndex = 0; usageIndex < token.consumers.size(); usageIndex ++) { + usageInstance =(UsageInstance)token.consumers.get(usageIndex); + componentTypeName = CommonDefinition.getComponentTypeString(usageInstance.componentType); + if (usageInstance.isInherit) { + inheritString = "Inherit"; + } else { + inheritString = ""; + } + bWriter.write(String.format(" (Consumer)#%d: %s:%s Package:%s %s\r\n", + usageIndex, + componentTypeName, + usageInstance.moduleName, + usageInstance.packageName, + inheritString + ) + ); + } + } + bWriter.close(); + } catch (IOException exp) { + ActionMessage.warning(this, "Failed to open database log file: " + logFileName); + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/SkuInstance.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/SkuInstance.java new file mode 100644 index 0000000000..2886506411 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/SkuInstance.java @@ -0,0 +1,40 @@ +/** @file + SkuInstance class. + + Sku instance contains ID and value, A pcd token maybe contains more than one Sku instance. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.entity; + +/** Sku instance contains ID and value, A pcd token maybe contains more than one Sku instance. +**/ +public class SkuInstance { + /// + /// The id number of this SKU instance + /// + public int id; + /// + /// The value of this SKU instance + /// + public Object value; + + /** + Constructure function + + @param id sku id + @param value sku value for this id. + **/ + public SkuInstance(int id, Object value) { + this.id = id; + this.value = value; + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/Token.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/Token.java new file mode 100644 index 0000000000..e4ecfc034c --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/Token.java @@ -0,0 +1,641 @@ +/** @file + Token class. + + This module contains all classes releted to PCD token. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.entity; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +import org.tianocore.build.pcd.action.ActionMessage; + +/** This class is to descript a PCD token object. The information of a token mainly + comes from MSA, SPD and setting produced by platform developer. +**/ +public class Token { + /// + /// Enumeration macro defintion for PCD type. + /// BUGBUG: Not use upcase charater is to facility for reading. It may be changed + /// in coding review. + public enum PCD_TYPE {FEATURE_FLAG, FIXED_AT_BUILD, PATCHABLE_IN_MODULE, DYNAMIC, + DYNAMIC_EX, UNKNOWN} + + /// + /// Enumeration macro definition for datum type. All type mainly comes from ProcessBind.h. + /// Wizard maybe expand this type as "int, unsigned int, short, unsigned short etc" in + /// prompt dialog. + /// + public enum DATUM_TYPE {UINT8, UINT16, UINT32, UINT64, BOOLEAN, POINTER, UNKNOWN} + + /// + /// Enumeration macor defintion for usage of PCD + /// + public enum PCD_USAGE {ALWAYS_PRODUCED, ALWAYS_CONSUMED, SOMETIMES_PRODUCED, + SOMETIMES_CONSUMED, UNKNOWN} + + /// + /// cName is to identify a PCD entry and will be used for generating autogen.h/autogen.c. + /// cName will be defined in MSA, SPD and FPD, can be regarded as primary key with token space guid. + /// + public String cName; + + /// + /// Token space name is the guid defined by token itself in package or module level. This + /// name mainly for DynamicEx type. For other PCD type token, his token space name is the + /// assignedtokenSpaceName as follows. + /// tokenSpaceName is defined in MSA, SPD, FPD, can be regarded as primary key with cName. + /// + public UUID tokenSpaceName; + + /// + /// tokenNumber is allocated by platform. tokenNumber indicate an index for this token in + /// platform token space. + /// tokenNumber is defined in SPD, FPD. + /// + public int tokenNumber; + + /// + /// The token space name assigned by platform. For Non-DynamicEx driver this value is same. + /// assignedtokenSpaceName is defined in FPD. + /// + public UUID assignedtokenSpaceName; + + /// + /// The token number assigned by platform. The number indiect the offset of this token in platform + /// token space. + /// AssgiendtokenNumber is defined in FPD. + /// + public int assignedtokenNumber; + + /// + /// pcdType is the PCD item type defined by platform developer. + /// + public PCD_TYPE pcdType; + + /// + /// PCDtype is set by platform developer. It is final PCD type of this token. + /// SupportedPcdType is defined in SPD. + /// + public PCD_TYPE[] supportedpcdType; + + /// + /// datumSize is to descript the fix size or max size for this token. + /// datumSize is defined in SPD. + /// + public int datumSize; + + /// + /// datum type is to descript what type can be expressed by a PCD token. + /// datumType is defined in SPD. + /// + public DATUM_TYPE datumType; + + /// + /// Isplatform is to descript whether this token is defined in platform level. + /// If token is belong to platform level. The value can be different for every + /// module. All are determined by platform developer. + /// + public boolean isPlatform; + + /// + /// hiiEnabled is to indicate whether the token support Hii functionality. + /// hiiEnabled is defined in FPD. + /// + public boolean hiiEnabled; + + /// + /// variableName is valid only when this token support Hii functionality. variableName + /// indicates the value of token is associated with what variable. + /// variableName is defined in FPD. + /// + public String variableName; + + /// + /// variableGuid is the GUID this token associated with. + /// variableGuid is defined in FPD. + /// + public UUID variableGuid; + + /// + /// Variable offset indicate the associated variable's offset in NV storage. + /// variableOffset is defined in FPD. + /// + public int variableOffset; + + /// + /// skuEnabled is to indicate whether the token support Sku functionality. + /// skuEnabled is defined in FPD. + /// + public boolean skuEnabled; + + /// + /// skuDataArrayEnabled is to indicate wheter use the skuData array or default value. + /// + public boolean skuDataArrayEnabled; + + /// + /// skuData contains all value for SkuNumber of token. + /// skuData is defined in FPD. + /// + public List skuData; + + /// + /// maxSkuCount indicate the max count of sku data. + /// maxSkuCount is defined in FPD. + /// + public int maxSkuCount; + + /// + /// SkuId is the id of current selected SKU. + /// SkuId is defined in FPD. + /// + public int skuId; + + /// + /// datum is the value set by platform developer. + /// datum is defined in FPD. + /// + public Object datum; + + /// + /// Default value of this token. + /// This default value is defined in SPD level. + /// + public Object defaultValue; + + /// + /// BUGBUG: fix comment + /// vpdEnabled is defined in FPD. + /// + public boolean vpdEnabled; + + /// + /// BUGBUG: fix comment + /// vpdOffset is defined in FPD. + /// + public long vpdOffset; + + /// + /// producers array record all module private information who produce this PCD token. + /// + public List producers; + + /// + /// consumers array record all module private information who consume this PCD token. + /// + public List consumers; + + /** + Constructure function. + + Initialize the value of token. + + @param cName The cName of this token + @param tokenSpaceName The tokenSpaceName of this token, it is a GUID. + @param assignedtokenSpaceName The assignedtokenSpaceName of this token, it is a GUID. + + **/ + public Token(String cName, UUID tokenSpaceName, UUID assignedtokenSpaceName) { + UUID nullUUID = new UUID(0, 0); + + this.cName = cName; + this.tokenSpaceName =(tokenSpaceName == null) ? nullUUID : tokenSpaceName; + this.assignedtokenSpaceName =(assignedtokenSpaceName == null) ? nullUUID : assignedtokenSpaceName; + this.tokenNumber = 0; + this.assignedtokenNumber = 0; + this.pcdType = PCD_TYPE.UNKNOWN; + this.supportedpcdType = null; + this.isPlatform = false; + this.datumType = DATUM_TYPE.UNKNOWN; + this.datumSize = -1; + this.defaultValue = null; + this.datum = null; + this.hiiEnabled = false; + this.variableGuid = null; + this.variableName = ""; + this.variableOffset = -1; + this.skuEnabled = false; + this.skuDataArrayEnabled = false; + this.skuId = -1; + this.maxSkuCount = -1; + this.skuData = new ArrayList(); + this.vpdEnabled = false; + this.vpdOffset = -1; + + this.producers = new ArrayList(); + this.consumers = new ArrayList(); + } + + /** + Use "TokencName + "-" + SpaceTokenName" as primary key when adding token into database + + @param cName Token name. + @param tokenSpaceName The token space guid defined in MSA or SPD + @param platformtokenSpaceName The token space guid for current platform token space, + + @return primary key for this token in token database. + **/ + public static String getPrimaryKeyString(String cName, UUID tokenSpaceName, + UUID platformtokenSpaceName) { + UUID nullUUID = new UUID(0, 0); + + if (platformtokenSpaceName == nullUUID) { + return cName + "-" + tokenSpaceName.toString(); + } else { + return cName + "-" + platformtokenSpaceName.toString(); + } + } + + /** + Judge datumType is valid + + @param type The datumType want to be judged. + + @retval TRUE - The type is valid. + @retval FALSE - The type is invalid. + **/ + public static boolean isValiddatumType(DATUM_TYPE type) { + if ((type.ordinal() < DATUM_TYPE.UINT8.ordinal() ) || + (type.ordinal() > DATUM_TYPE.POINTER.ordinal())) { + return false; + } + return true; + } + + /** + Judge pcdType is valid + + @param type The PCdType want to be judged. + + @retval TRUE - The type is valid. + @retval FALSE - The type is invalid. + **/ + public static boolean isValidpcdType(PCD_TYPE type) { + if ((type.ordinal() < PCD_TYPE.FEATURE_FLAG.ordinal() ) || + (type.ordinal() > PCD_TYPE.DYNAMIC_EX.ordinal())) { + return false; + } + return true; + } + + /** + Add an usage instance for token + + @param usageInstance The usage instance + + @retval TRUE - Success to add usage instance. + @retval FALSE - Fail to add usage instance + **/ + public boolean addUsageInstance(UsageInstance usageInstance) { + if (usageInstance.usage == PCD_USAGE.UNKNOWN) { + return false; + } + + if ((usageInstance.usage == PCD_USAGE.ALWAYS_PRODUCED) || + (usageInstance.usage == PCD_USAGE.SOMETIMES_PRODUCED)) { + producers.add(usageInstance); + } else { + consumers.add(usageInstance); + } + return true; + } + + /** + Judge whether exist an usage instance for this token + + @param moduleName Use xmlFilePath as keyword to search the usage instance + + @retval PCD_USAGE - if UsageInstance exists. + @retval UNKNOWN - if UsageInstance does not exist, return UNKONW. + **/ + public PCD_USAGE isUsageInstanceExist(String moduleName) { + int index; + UsageInstance usageInstance; + + if (moduleName == null) { + ActionMessage.warning(this, "Error parameter for isUsageInstanceExist() function!"); + return PCD_USAGE.UNKNOWN; + } + + if (moduleName.length() == 0) { + return PCD_USAGE.UNKNOWN; + } + + // + // Searching the usage instance in module's producer and consumer according to + // module's name. + // + for (index = 0; index < producers.size(); index ++) { + usageInstance =(UsageInstance)producers.get(index); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + return usageInstance.usage; + } + } + + for (index = 0; index < consumers.size(); index ++) { + usageInstance =(UsageInstance)consumers.get(index); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + return usageInstance.usage; + } + } + return PCD_USAGE.UNKNOWN; + } + + /** + Get usage instance according to a MSA file name + + @param moduleName The file path string of MSA file. + + @return usage instance object. + **/ + public UsageInstance getUsageInstance(String moduleName) { + int usageIndex; + UsageInstance usageInstance; + + if (moduleName == null) { + ActionMessage.warning(this, "Error parameter for isUsageInstanceExist() function!"); + return null; + } + + if (moduleName.length() == 0) { + return null; + } + + if (producers.size() != 0) { + for (usageIndex = 0; usageIndex < producers.size(); usageIndex ++) { + usageInstance =(UsageInstance)producers.get(usageIndex); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + return usageInstance; + } + } + } + + if (consumers.size() != 0) { + for (usageIndex = 0; usageIndex < consumers.size(); usageIndex ++) { + usageInstance =(UsageInstance)consumers.get(usageIndex); + if (usageInstance.moduleName.equalsIgnoreCase(moduleName)) { + return usageInstance; + } + } + } + return null; + } + + /** + Get the PCD_TYPE according to the string of PCD_TYPE + + @param pcdTypeStr The string of PCD_TYPE + + @return PCD_TYPE + **/ + public static PCD_TYPE getpcdTypeFromString(String pcdTypeStr) { + if (pcdTypeStr == null) { + return PCD_TYPE.UNKNOWN; + } + + if (pcdTypeStr.equalsIgnoreCase("FEATURE_FLAG")) { + return PCD_TYPE.FEATURE_FLAG; + } else if (pcdTypeStr.equalsIgnoreCase("FIXED_AT_BUILD")) { + return PCD_TYPE.FIXED_AT_BUILD; + } else if (pcdTypeStr.equalsIgnoreCase("PATCHABLE_IN_MODULE")) { + return PCD_TYPE.PATCHABLE_IN_MODULE; + } else if (pcdTypeStr.equalsIgnoreCase("DYNAMIC")) { + return PCD_TYPE.DYNAMIC; + } else if (pcdTypeStr.equalsIgnoreCase("DYNAMIC_EX")) { + return PCD_TYPE.DYNAMIC_EX; + } else { + return PCD_TYPE.UNKNOWN; + } + } + + /** + Get the string of given datumType. This string will be used for generating autogen files + + @param datumType Given datumType + + @return The string of datum type. + **/ + public static String getStringOfdatumType(DATUM_TYPE datumType) { + switch (datumType) { + case UINT8: + return "UINT8"; + case UINT16: + return "UINT16"; + case UINT32: + return "UINT32"; + case UINT64: + return "UINT64"; + case POINTER: + return "POINTER"; + case BOOLEAN: + return "BOOLEAN"; + } + return "UNKNOWN"; + } + + /** + Get the datumType according to a string. + + @param datumTypeStr The string of datumType + + @return DATUM_TYPE + **/ + public static DATUM_TYPE getdatumTypeFromString(String datumTypeStr) { + if (datumTypeStr.equalsIgnoreCase("UINT8")) { + return DATUM_TYPE.UINT8; + } else if (datumTypeStr.equalsIgnoreCase("UINT16")) { + return DATUM_TYPE.UINT16; + } else if (datumTypeStr.equalsIgnoreCase("UINT32")) { + return DATUM_TYPE.UINT32; + } else if (datumTypeStr.equalsIgnoreCase("UINT64")) { + return DATUM_TYPE.UINT64; + } else if (datumTypeStr.equalsIgnoreCase("VOID*")) { + return DATUM_TYPE.POINTER; + } else if (datumTypeStr.equalsIgnoreCase("BOOLEAN")) { + return DATUM_TYPE.BOOLEAN; + } + return DATUM_TYPE.UNKNOWN; + } + + /** + Get string of given pcdType + + @param pcdType The given PcdType + + @return The string of PCD_TYPE. + **/ + public static String getStringOfpcdType(PCD_TYPE pcdType) { + switch (pcdType) { + case FEATURE_FLAG: + return "FEATURE_FLAG"; + case FIXED_AT_BUILD: + return "FIXED_AT_BUILD"; + case PATCHABLE_IN_MODULE: + return "PATCHABLE_IN_MODULE"; + case DYNAMIC: + return "DYNAMIC"; + case DYNAMIC_EX: + return "DYNAMIC_EX"; + } + return "UNKNOWN"; + } + + /** + Get the PCD_USAGE according to a string + + @param usageStr The string of PCD_USAGE + + @return The PCD_USAGE + **/ + public static PCD_USAGE getUsageFromString(String usageStr) { + if (usageStr == null) { + return PCD_USAGE.UNKNOWN; + } + + if (usageStr.equalsIgnoreCase("ALWAYS_PRODUCED")) { + return PCD_USAGE.ALWAYS_PRODUCED; + } else if (usageStr.equalsIgnoreCase("SOMETIMES_PRODUCED")) { + return PCD_USAGE.SOMETIMES_PRODUCED; + } else if (usageStr.equalsIgnoreCase("ALWAYS_CONSUMED")) { + return PCD_USAGE.ALWAYS_CONSUMED; + } else if (usageStr.equalsIgnoreCase("SOMETIMES_CONSUMED")) { + return PCD_USAGE.SOMETIMES_CONSUMED; + } + + return PCD_USAGE.UNKNOWN; + } + + /** + Get the string of given PCD_USAGE + + @param usage The given PCD_USAGE + + @return The string of PDC_USAGE. + **/ + public static String getStringOfUsage(PCD_USAGE usage) { + switch (usage) { + case ALWAYS_PRODUCED: + return "ALWAYS_PRODUCED"; + case ALWAYS_CONSUMED: + return "ALWAYS_CONSUMED"; + case SOMETIMES_PRODUCED: + return "SOMETIMES_PRODUCED"; + case SOMETIMES_CONSUMED: + return "SOMETIMES_CONSUMED"; + } + return "UNKNOWN"; + } + + /** + Get the Defined datumType string for autogen. The string is for generating some MACROs in Autogen.h + + @param datumType The given datumType + + @return string of datum type for autogen. + **/ + public static String GetAutogenDefinedatumTypeString(DATUM_TYPE datumType) { + switch (datumType) { + + case UINT8: + return "8"; + case UINT16: + return "16"; + case BOOLEAN: + return "BOOL"; + case POINTER: + return "PTR"; + case UINT32: + return "32"; + case UINT64: + return "64"; + default: + return null; + } + } + + /** + Get the datumType String for Autogen. This string will be used for generating defintions of PCD token in autogen + + @param datumType The given datumType + + @return string of datum type. + **/ + public static String getAutogendatumTypeString(DATUM_TYPE datumType) { + switch (datumType) { + case UINT8: + return "UINT8"; + case UINT16: + return "UINT16"; + case UINT32: + return "UINT32"; + case UINT64: + return "UINT64"; + case POINTER: + return "VOID*"; + case BOOLEAN: + return "BOOLEAN"; + } + return null; + } + + /** + Get the datumType string for generating some MACROs in autogen file of Library + + @param datumType The given datumType + + @return String of datum for genrating bit charater. + **/ + public static String getAutogenLibrarydatumTypeString(DATUM_TYPE datumType) { + switch (datumType) { + case UINT8: + return "8"; + case UINT16: + return "16"; + case BOOLEAN: + return "Bool"; + case POINTER: + return "Ptr"; + case UINT32: + return "32"; + case UINT64: + return "64"; + default: + return null; + } + } + + /** + UUID defined in Schems is object, this function is to tranlate this object + to UUID data. + + @param uuidObj The object comes from schema. + + @return The traslated UUID instance. + **/ + public static UUID getGUIDFromSchemaObject(Object uuidObj) { + UUID uuid; + if (uuidObj.toString().equalsIgnoreCase("0")) { + uuid = new UUID(0,0); + } else { + uuid = UUID.fromString(uuidObj.toString()); + } + + return uuid; + } +} + + + + diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/UsageInstance.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/UsageInstance.java new file mode 100644 index 0000000000..a11633d91b --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/entity/UsageInstance.java @@ -0,0 +1,471 @@ +/** @file + UsageInstance class. + + This class indicate an usage instance for a PCD token. This instance maybe a module + or platform setting. When a module produce or cosume a PCD token, then this module + is an usage instance for this PCD token. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.entity; + + +import org.tianocore.build.pcd.exception.EntityException; +import org.tianocore.build.pcd.action.ActionMessage; + +import org.tianocore.build.autogen.CommonDefinition; + +/** + This class indicate an usage instance for a PCD token. This instance maybe a module + or platform setting. When a module produce or cosume a PCD token, then this module + is an usage instance for this PCD token. +**/ +public class UsageInstance { + /// + /// This parent that this usage instance belongs to. + /// + public Token parentToken; + /// + /// The usage of this token for platform or module. + /// + public Token.PCD_USAGE usage; + /// + /// Whether this usage instance inherit from library + /// + public boolean isInherit; + /// + /// The pcd type of this token for module. + /// + public Token.PCD_TYPE modulePcdType; + /// + /// The name of the module who contains this PCD. + /// + public String moduleName; + /// + /// The name of the package whose module contains this PCD. + /// + public String packageName; + /// + /// The component type for this usage instance. + /// + public int componentType; + /// + /// The default value defined in MSA has high prior than defined in SPD. + /// + public Object defaultValueInMSA; + /// + /// The default value defined in SPD. + /// + public Object defaultValueInSPD; + /// + /// Help text in MSA + /// + public String helpTextInMSA; + /// + /// Help text in SPD + /// + public String helpTextInSPD; + /// + /// Autogen string for header file. + /// + public String hAutogenStr; + /** + * Auotgen string for C code file. + */ + public String cAutogenStr; + + /** + Constructure function + + @param parentToken Member variable. + @param usage Member variable. + @param pcdType Member variable. + @param componentType Member variable. + @param defaultValueInMSA Member variable. + @param defaultValueInSPD Member variable. + @param helpTextInMSA Member variable. + @param helpTextInSPD Member variable. + @param moduleName Member variable. + @param packageName Member variable. + @param isInherit Member variable. + **/ + public UsageInstance( + Token parentToken, + Token.PCD_USAGE usage, + Token.PCD_TYPE pcdType, + int componentType, + Object defaultValueInMSA, + Object defaultValueInSPD, + String helpTextInMSA, + String helpTextInSPD, + String moduleName, + String packageName, + boolean isInherit + ) + { + this.parentToken = parentToken; + this.usage = usage; + this.modulePcdType = pcdType; + this.componentType = componentType; + this.defaultValueInMSA = defaultValueInMSA; + this.defaultValueInSPD = defaultValueInSPD; + this.helpTextInMSA = helpTextInMSA; + this.helpTextInSPD = helpTextInSPD; + this.moduleName = moduleName; + this.packageName = packageName; + this.isInherit = isInherit; + } + + /** + Generate autogen string for header file and C code file. + + @throws EntityException Fail to generate. + **/ + public void generateAutoGen() throws EntityException { + Object value = null; + int tokenNumber = 0; + + hAutogenStr = ""; + cAutogenStr = ""; + + value = this.parentToken.datum; + + // + // If this pcd token's PCD_TYPE is DYNAMIC_EX, use itself token space name + // otherwices use assgined token space name from tool automatically. + // + if(parentToken.pcdType == Token.PCD_TYPE.DYNAMIC_EX) { + tokenNumber = parentToken.tokenNumber; + } else { + tokenNumber = parentToken.assignedtokenNumber; + } + + hAutogenStr += String.format("#define _PCD_TOKEN_%s 0x%016x\r\n", + parentToken.cName, tokenNumber); + + switch(modulePcdType) { + case FEATURE_FLAG: + // + // BUGBUG: The judegement of module PCD type and platform PCD type should not be + // done here, but in wizard tools, But here is just following something + // PcdEmulation driver. + // + if(parentToken.pcdType.ordinal() > Token.PCD_TYPE.FEATURE_FLAG.ordinal()) { + throw new EntityException( + String.format( + "%s:Platform PCD Type %d is not compatible with Module PCD Type %d\r\n", + parentToken.cName, + parentToken.pcdType.name(), + modulePcdType.name() + ) + ); + } + + if(CommonDefinition.isLibraryComponent(componentType)) { + hAutogenStr += String.format( + "extern const BOOLEAN _gPcd_FixedAtBuild_%s;\r\n", + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_FixedAtBuild_%s\r\n", + parentToken.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } else { + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value.toString() + ); + hAutogenStr += String.format( + "extern const BOOLEAN _gPcd_FixedAtBuild_%s;\r\n", + parentToken.cName + ); + cAutogenStr += String.format( + "GLOBAL_REMOVE_IF_UNREFERENCED const BOOLEAN _gPcd_FixedAtBuild_%s = _PCD_VALUE_%s;\r\n", + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _PCD_VALUE_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } + break; + case FIXED_AT_BUILD: + // + // BUGBUG: The judegement of module PCD type and platform PCD type should not be + // done here, but in wizard tools, But here is just following something + // PcdEmulation driver. + // + if(parentToken.pcdType.ordinal() > Token.PCD_TYPE.FIXED_AT_BUILD.ordinal()) { + throw new EntityException( + String.format( + "%s:Platform PCD Type %d is not compatible with Module PCD Type %d\r\n", + parentToken.cName, + parentToken.pcdType.name(), + modulePcdType.name() + ) + ); + } + + if(CommonDefinition.isLibraryComponent(componentType)) { + hAutogenStr += String.format( + "extern const %s _gPcd_FixedAtBuild_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_FixedAtBuild_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } else { + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value.toString() + ); + hAutogenStr += String.format( + "extern const %s _gPcd_FixedAtBuild_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + cAutogenStr += String.format( + "GLOBAL_REMOVE_IF_UNREFERENCED const %s _gPcd_FixedAtBuild_%s = _PCD_VALUE_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _PCD_VALUE_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } + break; + case PATCHABLE_IN_MODULE: + // + // BUGBUG: The judegement of module PCD type and platform PCD type should not be + // done here, but in wizard tools, But here is just following something + // PcdEmulation driver. + // + if(parentToken.pcdType.ordinal() > Token.PCD_TYPE.PATCHABLE_IN_MODULE.ordinal()) { + throw new EntityException( + String.format( + "%s:Platform PCD Type %d is not compatible with Module PCD Type %d\r\n", + parentToken.cName, + parentToken.pcdType.name(), + modulePcdType.name() + ) + ); + } + + if(CommonDefinition.isLibraryComponent(componentType)) { + hAutogenStr += String.format( + "extern %s _gPcd_BinaryPatch_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_BinaryPatch_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } else { + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value + ); + hAutogenStr += String.format( + "extern %s _gPcd_BinaryPatch_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + cAutogenStr += String.format( + "GLOBAL_REMOVE_IF_UNREFERENCED %s _gPcd_BinaryPatch_%s = _PCD_VALUE_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_BinaryPatch_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } + + break; + case DYNAMIC: + // + // BUGBUG: The judegement of module PCD type and platform PCD type should not be + // done here, but in wizard tools, But here is just following something + // PcdEmulation driver. + // + if(parentToken.pcdType.ordinal() > Token.PCD_TYPE.DYNAMIC.ordinal()) { + throw new EntityException( + String.format( + "%s:Platform PCD Type %d is not compatible with Module PCD Type %d\r\n", + parentToken.cName, + parentToken.pcdType.name(), + modulePcdType.name() + ) + ); + } + + switch(parentToken.pcdType) { + case FEATURE_FLAG: + if(CommonDefinition.isLibraryComponent(componentType)) { + hAutogenStr += String.format( + "extern const BOOLEAN _gPcd_FixedAtBuild_%s;\r\n", + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_FixedAtBuild_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } else { + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value + ); + hAutogenStr += String.format( + "extern const BOOLEAN _gPcd_FixedAtBuild_%s;\r\n", + parentToken.cName + ); + cAutogenStr += String.format( + "const BOOLEAN _gPcd_FixedAtBuild_%s = _PCD_VALUE_%s;\r\n", + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _PCD_VALUE_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } + break; + case FIXED_AT_BUILD: + if(CommonDefinition.isLibraryComponent(componentType)) { + hAutogenStr += String.format( + "extern const %s _gPcd_FixedAtBuild_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_FixedAtBuild_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + + } else { + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value + ); + hAutogenStr += String.format( + "extern const %s _gPcd_FixedAtBuild_%s\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName + ); + cAutogenStr += String.format( + "const %s _gPcd_FixedAtBuild_%s = _PCD_VALUE_%s;\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _PCD_VALUE_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + } + break; + case PATCHABLE_IN_MODULE: + hAutogenStr += String.format( + "#define _PCD_VALUE_%s %s\r\n", + parentToken.cName, + value + ); + hAutogenStr += String.format( + "extern %s _gPcd_BinaryPatch_%s;\r\n", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + cAutogenStr += String.format( + "%s _gPcd_BinaryPatch_%s = _PCD_VALUE_%s;", + Token.getAutogendatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s _gPcd_BinaryPatch_%s\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + parentToken.cName + ); + break; + case DYNAMIC: + hAutogenStr += String.format( + "#define _PCD_MODE_%s_%s LibPcdGet%s(_PCD_TOKEN_%s)\r\n", + Token.GetAutogenDefinedatumTypeString(parentToken.datumType), + parentToken.cName, + Token.getAutogenLibrarydatumTypeString(parentToken.datumType), + parentToken.cName + ); + break; + default: + ActionMessage.log( + this, + "The PCD_TYPE setted by platform is unknown" + ); + } + break; + case DYNAMIC_EX: + break; + } + } + + /** + Get the autogen string for header file. + + @return The string of header file. + **/ + public String getHAutogenStr() { + return hAutogenStr; + } + + /** + Get the autogen string for C code file. + + @return The string of C Code file. + **/ + public String getCAutogenStr() { + return cAutogenStr; + } +} + diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/BuildActionException.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/BuildActionException.java new file mode 100644 index 0000000000..357ebf017a --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/BuildActionException.java @@ -0,0 +1,33 @@ +/** @file + BuildActionException class. + + BuildAction Exception deals with all build action exceptions. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.exception; + +import org.apache.tools.ant.BuildException; + +/** + BuildAction Exception deals with all build action exceptions. +**/ +public class BuildActionException extends BuildException { + static final long serialVersionUID = -7034897190740066939L; + /** + Constructure function + + @param reason exception message string. + **/ + public BuildActionException(String reason) { + super(reason); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/EntityException.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/EntityException.java new file mode 100644 index 0000000000..1e7ebfcbe1 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/EntityException.java @@ -0,0 +1,31 @@ +/** @file + EntityException class. + + The class handle the exception throwed by entity class. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.exception; + +/** + The class handle the exception throwed by entity class. +**/ +public class EntityException extends Exception { + static final long serialVersionUID = -8034897190740066939L; + /** + Constructure function + + @param expStr exception message string. + **/ + public EntityException(String expStr) { + super("[EntityException]:" + expStr); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/UIException.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/UIException.java new file mode 100644 index 0000000000..96575a1450 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/exception/UIException.java @@ -0,0 +1,31 @@ +/** @file + UIException class. + + The class handle the exception throwed by UI action class. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.exception; + +/** + The class handle the exception throwed by UI action class. +**/ +public class UIException extends Exception { + static final long serialVersionUID = -7034897190740066930L; + /** + Constructure function + + @param reason exception message string. + **/ + public UIException(String reason) { + super(reason); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/pcd/ui/PCDDatabaseFrame.java b/Tools/Source/GenBuild/org/tianocore/build/pcd/ui/PCDDatabaseFrame.java new file mode 100644 index 0000000000..81eb63025b --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/pcd/ui/PCDDatabaseFrame.java @@ -0,0 +1,184 @@ +/** @file + PCDDatabaseFrame class. + + The class is the frame class for displaying PCD database in tree method. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.pcd.ui; + +import java.awt.*; +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.tree.DefaultMutableTreeNode; + +import org.tianocore.build.pcd.action.ActionMessage; +import org.tianocore.build.pcd.entity.MemoryDatabaseManager; +import org.tianocore.build.pcd.entity.Token; +import org.tianocore.build.pcd.entity.UsageInstance; + +/** + The class is the frame class for displaying PCD database in tree method. +**/ +public class PCDDatabaseFrame extends JFrame { + static final long serialVersionUID = -7034897190740068939L; + /// + /// Database instance + /// + private MemoryDatabaseManager dbManager; + /// + /// The token and module tree + /// + private JTree databaseTree; + + /** + Constructure function. + + Create the UI component and display frame. + + @param dbManager databaase manager instance. + **/ + public PCDDatabaseFrame(MemoryDatabaseManager dbManager) { + if (dbManager != null) { + this.dbManager = dbManager; + } + // + // Put the frame into center of desktop. + // + setLocation(100, 100); + initializeComponent(); + + setTitle("PCD View Tool"); + pack(); + setVisible(true); + } + + /** + Initliaze the UI component in Display frame. + **/ + public void initializeComponent() { + JScrollPane scrollPane = new JScrollPane(); + Container contentPane = getContentPane(); + + contentPane.setLayout(new BorderLayout()); + scrollPane.setViewportView(initializeTree()); + contentPane.add(scrollPane); + + addWindowListener(new PCDDatabaseFrameAdapter()); + } + + /** + Initiliaze the TREE control. + **/ + public JTree initializeTree() { + Token[] tokenArray = null; + Token token = null; + DefaultMutableTreeNode root = new DefaultMutableTreeNode(dbManager.getLogFileName()); + DefaultMutableTreeNode rootByPCD = new DefaultMutableTreeNode("By PCD"); + DefaultMutableTreeNode rootByModule = new DefaultMutableTreeNode("By Module"); + DefaultMutableTreeNode tokenNode = null; + DefaultMutableTreeNode usageNode = null; + DefaultMutableTreeNode moduleNode = null; + java.util.List moduleNames = null; + int index = 0; + int usageIndex = 0; + int moduleIndex = 0; + java.util.List usageArray = null; + UsageInstance usageInstance = null; + + root.add(rootByPCD); + // + // By PCD Node + // + + tokenArray = dbManager.getRecordArray(); + for (index = 0; index < tokenArray.length; index ++) { + token = tokenArray[index]; + ActionMessage.debug(this, token.cName); + tokenNode = new DefaultMutableTreeNode(token.cName); + tokenNode.add(new DefaultMutableTreeNode(String.format("TOKEN NUMBER: 0x%08x", token.tokenNumber))); + tokenNode.add(new DefaultMutableTreeNode(String.format("ASSIGNED TOKEN NUMBER: 0x%08x", token.assignedtokenNumber))); + tokenNode.add(new DefaultMutableTreeNode("TOKEN SPACE NAME: " + token.tokenSpaceName.toString())); + tokenNode.add(new DefaultMutableTreeNode("ASSIGNED TOKEN SPACE NAME: " + token.assignedtokenSpaceName.toString())); + tokenNode.add(new DefaultMutableTreeNode("PCD TYPE: " + Token.getStringOfpcdType(token.pcdType))); + tokenNode.add(new DefaultMutableTreeNode("DATUM TYPE: " +Token.getStringOfdatumType(token.datumType))); + tokenNode.add(new DefaultMutableTreeNode("DATUM: " + token.datum.toString())); + tokenNode.add(new DefaultMutableTreeNode("HIIENABLE: " +(token.hiiEnabled?"true":"false"))); + tokenNode.add(new DefaultMutableTreeNode("VARIABLE NAME: " + token.variableName)); + tokenNode.add(new DefaultMutableTreeNode("VARIABLE GUID: " + token.variableGuid.toString())); + tokenNode.add(new DefaultMutableTreeNode("SKUENABLE: " +(token.skuEnabled?"true":"false"))); + tokenNode.add(new DefaultMutableTreeNode("SKUDATA ARRAY ENABLE: " +(token.skuDataArrayEnabled?"true":"false"))); + tokenNode.add(new DefaultMutableTreeNode(String.format("SKUID: %d", token.skuId))); + tokenNode.add(new DefaultMutableTreeNode(String.format("MAX SKU COUNT: %d", token.maxSkuCount))); + tokenNode.add(new DefaultMutableTreeNode("VPDENABLE: " +(token.vpdEnabled?"true":"false"))); + + usageNode = new DefaultMutableTreeNode("PRODUCER"); + tokenNode.add(usageNode); + + // + // Prepare producer's leaf node + // + + for (usageIndex = 0; usageIndex < token.producers.size(); usageIndex ++) { + usageNode.add(new DefaultMutableTreeNode(token.producers.get(usageIndex).moduleName)); + } + + // + // Prepare consumer's leaf node + // + usageNode = new DefaultMutableTreeNode("CONSUMER"); + tokenNode.add(usageNode); + + for (usageIndex = 0; usageIndex < token.consumers.size(); usageIndex ++) { + usageNode.add(new DefaultMutableTreeNode(token.consumers.get(usageIndex).moduleName)); + } + + rootByPCD.add(tokenNode); + } + + // + // BY MODULE Node + // + root.add(rootByModule); + moduleNames = dbManager.getAllModuleArray(); + for (moduleIndex = 0; moduleIndex < moduleNames.size(); moduleIndex ++) { + ActionMessage.debug(this, "ModuleName:" + moduleNames.get(moduleIndex)); + } + for (moduleIndex = 0; moduleIndex < moduleNames.size(); moduleIndex ++) { + moduleNode = new DefaultMutableTreeNode(moduleNames.get(moduleIndex)); + usageArray = dbManager.getUsageInstanceArrayByModuleName(moduleNames.get(moduleIndex)); + for (usageIndex = 0; usageIndex < usageArray.size(); usageIndex ++) { + usageInstance = usageArray.get(usageIndex); + usageNode = new DefaultMutableTreeNode(usageInstance.parentToken.cName); + usageNode.add(new DefaultMutableTreeNode("MODULE PCD TYPE: " + Token.getStringOfpcdType(usageInstance.modulePcdType))); + usageNode.add(new DefaultMutableTreeNode("HELP TEXT: " + usageInstance.helpTextInMSA)); + usageNode.add(new DefaultMutableTreeNode("IS INHERIT: " +(usageInstance.isInherit?"true":"false"))); + usageNode.add(new DefaultMutableTreeNode("USAGE: " + Token.getStringOfUsage(usageInstance.usage))); + moduleNode.add(usageNode); + } + rootByModule.add(moduleNode); + } + + databaseTree = new JTree(root); + return databaseTree; + } +} + +/** + The adatper class for PCDDatabaseFrame. This class instance many windows message + callback function. +**/ +class PCDDatabaseFrameAdapter extends WindowAdapter { + public void windowClosing(WindowEvent e) { + System.exit(0); + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/toolchain/ConfigReader.java b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ConfigReader.java new file mode 100644 index 0000000000..f48735966e --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ConfigReader.java @@ -0,0 +1,218 @@ +/** @file + ConfigReader class. + + ConfigReader is used to read tool chain config file with flat format. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.build.toolchain; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.Vector; + +import org.apache.tools.ant.BuildException; + +/** + + ConfigReader is used to read tool chain config file with flat format. Comments + is line starting with character '#'. + + @since GenBuild 1.0 +**/ +public class ConfigReader { + + private static String confPath = "."; + + /** + Public construct method. + **/ + public ConfigReader () { + } + + /** + Default filepath is ".". + + @param filename the config file name like "target.txt" + @return the variables defined in file + **/ + public static synchronized String[][] parse(String filename) { + return parse(confPath, filename); + } + + /** + Get all variables defined in config file. the config file format is flat + with "A=B". If line started with '#' looks as comments. + + @param confPath the path of config file + @param filename the file name of the config file + @return the variables defined in the config file + @throws BuildException + Config file's format is not valid + **/ + public static synchronized String[][] parse(String confPath, String filename) throws BuildException { + try { + Map map = new HashMap(20); + File file = new File(confPath + File.separatorChar + filename); + FileReader reader = new FileReader(file); + BufferedReader in = new BufferedReader(reader); + String str; + while ((str = in.readLine()) != null) { + str = str.trim(); + // + // if str is empty line or comments (start with '#') + // + if (str.equalsIgnoreCase("") || str.startsWith("#")) { + continue; + } + // + // if str without '=' or start with '=' + // + if (str.indexOf('=') <= 0) { + continue; + } + // + // look as line "A = B" + // + int index = str.indexOf('='); + String key = str.substring(0, index).trim(); + String value = str.substring(index + 1).trim(); + // + // if key is existed, then update + // + if (map.containsKey(key)) { + map.remove(key); + } + map.put(key, value); + } + Set keyset = map.keySet(); + Iterator iter = keyset.iterator(); + String[][] result = new String[map.size()][2]; + int i = 0; + while (iter.hasNext()) { + String key = (String) iter.next(); + result[i][0] = key; + result[i++][1] = (String) map.get(key); + } + return result; + } catch (Exception e) { + throw new BuildException("Processor file [" + filename + "] error. \n" + e.getMessage()); + } + } + + /** + Parse global flags table. The format is like such(global flag name, value, + vendor_arch_cmd, [add flags], [sub flags]): + +
+        # EFI_DEBUG
+        EFI_DEBUG YES MSFT_IA32_ASM    ADD.["/Zi", "/DEBUG"]
+        EFI_DEBUG YES MSFT_IA32_CC     ADD.["/Zi", "/Gm", "/D EFI_DEBUG"] SUB.["/nologo", "/WX"]
+        EFI_DEBUG YES MSFT_IA32_LINK   ADD.["/DEBUG"]
+        EFI_DEBUG YES MSFT_NT32_CC     ADD.["/DEBUG"]
+      
+ + @param confPath the file path of config file + @param filename the file name of config file + @return the value list + @throws BuildException + Config file is not valid + **/ + public static synchronized String[][] parseTable(String confPath, + String filename) throws BuildException { + try { + Vector vector = new Vector(20); + File file = new File(confPath + File.separatorChar + filename); + FileReader reader = new FileReader(file); + BufferedReader in = new BufferedReader(reader); + String str; + while ((str = in.readLine()) != null) { + str = str.trim(); + // + // if str is empty line or comments (start with '#') + // + if (str.equalsIgnoreCase("") || str.startsWith("#")) { + continue; + } + String[] item = new String[5]; + for(int i=0; i < item.length; i++){ + item[i] = ""; + } + // + // EFI_DEBUG YES MSFT_IA32_ASM ADD.["/Zi", "/DEBUG"] + // FLAGS: EFI_DEBUG + // + int index = str.indexOf(" "); + item[0] = str.substring(0, index); + str = str.substring(index + 1).trim(); + // + // Setting: YES + // + index = str.indexOf(" "); + item[1] = str.substring(0, index); + str = str.substring(index + 1).trim(); + // + // Vendor_Arch_Commandtype: MSFT_IA32_ASM + // + index = str.indexOf(" "); + item[2] = str.substring(0, index); + str = str.substring(index + 1).trim(); + // + // Add or/and Sub + // + if (str.startsWith("ADD.")) { + index = str.indexOf("]"); + if ( index > 0){ + item[3] = str.substring(5, index); + str = str.substring(index + 1).trim(); + } + } + else if(str.startsWith("SUB.")){ + index = str.indexOf("]"); + if ( index > 0){ + item[4] = str.substring(5, index); + str = str.substring(index + 1).trim(); + } + } + else { + throw new BuildException("File [" + filename + "] never conform to Global Flags Table format."); + } + + if (str.startsWith("ADD.")) { + index = str.indexOf("]"); + if ( index > 0){ + item[3] = str.substring(5, index); + str = str.substring(index + 1).trim(); + } + } + else if(str.startsWith("SUB.")){ + index = str.indexOf("]"); + if ( index > 0){ + item[4] = str.substring(5, index); + str = str.substring(index + 1).trim(); + } + } + vector.addElement(item); + } + String[][] result = new String[vector.size()][5]; + for(int i=0; i < vector.size(); i++){ + result[i] = (String[])vector.get(i); + } + return result; + } catch (Exception e) { + throw new BuildException("Processor file [" + filename + "] error. \n" + e.getMessage()); + } + } +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainFactory.java b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainFactory.java new file mode 100644 index 0000000000..e3010fccf4 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainFactory.java @@ -0,0 +1,529 @@ +/** @file + ToolChainFactory class. + + ToolChainFactory class parse all config files and get STD_FLAGS, GLOBAL_FLAGS, + and also command path + name. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.toolchain; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; +import java.util.StringTokenizer; +import java.io.File; + +import org.apache.tools.ant.Project; + + +/** + This class parse all config files and get STD_FLAGS, GLOBAL_FLAGS, and also + command path + name. + + @since GenBuild 1.0 +**/ +public class ToolChainFactory { + /// + /// list of Arch: EBC, ARM, IA32, X64, IPF, PPC + /// + public final static String[] arch = { "EBC", "ARM", "IA32", "X64", "IPF", + "PPC"}; + + /// + /// list of OS: Linux, Windows + /// + public final static String[] os = { "WINDOWS", "LINUX" }; + + /// + /// list of Command Type: CC, LIB, LINK, ASL, ASM, ASMLINK, PP + /// + public final static String[] commandType = { "CC", "LIB", "LINK", "ASL", + "ASM", "ASMLINK", "PP" }; + + /// + /// default command name for every command + /// + public final static String[][] defaultCmdName = { { "CC", "cl" }, + { "LIB", "lib" }, { "LINK", "link" }, { "ASL", "iasl" }, + { "ASM", "ml" }, { "ASMLINK", "link" }, { "PP", "cl" } }; + + private String confPath = "."; + + private String toolChainName = "MSFT"; + + private String sTargetFilename = "target.txt"; + + private String sToolsdefFilename = "tools_def.txt"; + + private String sWorkspaceTarget = "WORKSPACE_TARGET"; + + private String sTargetArch = "TARGET_ARCH"; + + private HashMap filesMap = new HashMap(); + + private HashMap globalFlagsMap = new HashMap(); + + private String[][] globalFlagTable; + + private String currentTarget = "RELEASE"; + + /// + /// toolchain array list all results by parsing config files + /// + public static String[][] toolchain = null; + + /** + Public construct method. + **/ + public ToolChainFactory () { + } + + /** + Public construct method. + + @param project current ANT Project. + **/ + public ToolChainFactory (Project project) { + this.confPath = project.replaceProperties("${WORKSPACE_DIR}" + File.separatorChar + "Tools" + File.separatorChar + "Conf"); + } + + /** + Public construct method. + + @param confPath the path of config files + @param toolChainName TOOL_CHAIN name + **/ + public ToolChainFactory (String confPath, String toolChainName) { + this.confPath = confPath; + // + // If set tool used the set one, otherwise use default one. + // toolChain used to define open tools define txt file. + // + if (toolChainName != null && toolChainName.length() > 0){ + this.toolChainName = toolChainName; + } + } + + /** + Parse all config files, following are the detail steps: + +
    +
  • Parse target.txt file. This file define the current build TARGET + and supported ARCH list.
  • +
  • Parse tools_def.txt file. This file define every command name, path + and vendor.
  • +
  • For every supported ARCH and Command Type, find out STD_FLAGS, + GLOBAL_ADD_FLAGS, GLOBAL_SUB_FLAGS.
  • +
+ +

Note that this method will be called only once during the whole build + process.

+ **/ + public void setupToolChain() { + if (toolchain != null) { + return ; + } + Map map = new HashMap(40); + // + // parse target.txt + // + String[][] target = ConfigReader.parse(confPath, sTargetFilename); + // + // get workspace_target and initialize global flags setting + // + currentTarget = getValue(sWorkspaceTarget, target); + parseGlobalSetting(currentTarget); + String[] archList = getArchs(getValue(sTargetArch, target)); + + // + // If user write the ${toolChain}_Tools_Def.txt use this one, + // otherwise used "tools_def.txt" file. + // + File tempFile = new File (confPath + File.separator + toolChainName.toLowerCase() + "_tools_def.txt"); + if (tempFile.exists()){ + sToolsdefFilename = toolChainName.toLowerCase() + "_tools_def.txt"; + } + + System.out.println("Tools definition file is: " + sToolsdefFilename); + // + // parse tools_def.txt + // + String[][] tools_def = ConfigReader.parse(confPath, sToolsdefFilename); + // + // for each arch find all command's path&name and flags + // + for (int i = 0; i < archList.length; i++) { + for (int j = 0; j < commandType.length; j++) { + // + // Path & Name + // + map.put(archList[i] + "_" + commandType[j], getAbsoluteCmdPath( + archList[i], commandType[j], tools_def)); + // + // Flags: CMD_STD_FLAGS + CMD_GLOBAL_FLAGS + CMD_PROJ_FLAGS + // ARCH_CMD_STD_FLAGS + // + map.put(archList[i] + "_" + commandType[j] + "_STD_FLAGS", + getStdFlags(archList[i], commandType[j], + tools_def)); + // + // Flags:ARCH_CMD_VENDOR or ARCH_VENDOR + // + map.put(archList[i]+ "_"+commandType[j]+"_VENDOR", getVendorFlag(archList[i], + commandType[j], tools_def)); + // + // ARCH_CMD_GLOBAL_FLAGS + // + String[] globalFlags = getGlobalFlags(archList[i], commandType[j], + tools_def); + map.put(archList[i] + "_" + commandType[j] + "_GLOBAL_ADD_FLAGS", + globalFlags[0]); + map.put(archList[i] + "_" + commandType[j] + "_GLOBAL_SUB_FLAGS", + globalFlags[1]); + // + // ARCH_CMD_GLOBAL_FLAGS, default is "". + // + map.put(archList[i] + "_" + commandType[j] + "_PROJ_FLAGS", ""); + } + map.put(archList[i]+"_VENDOR", getVendorFlag(archList[i], null, tools_def)); + } + Set keyset = map.keySet(); + Iterator iter = keyset.iterator(); + String[][] result = new String[map.size()][2]; + int i = 0; + while (iter.hasNext()) { + String key = (String) iter.next(); + result[i][0] = key; + result[i++][1] = (String) map.get(key); + } + toolchain = result; + } + + /** + Get the standard flags (STD_FLAGS) for specified arch and command type. + +
    +
  • Find out Vendor that cmd Command Type with arch ARCH used. The + search sequence is ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT". Here + we suppose default Vendor is MSFT.
  • +
  • Search ${Vendor}_tools.txt file, and get the corrsponding flags. +
  • +
+ + @param arch the ARCH + @param cmd the command type + @param map detail flags information of tools_def.txt + @return the standard flags of arch ARCH and cmd Command Type + **/ + private String getStdFlags(String arch, String cmd, String[][] map) { + // + // first is to find out its Vendor in map + // ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT" + // Here we suppose default Vendor is MSFT. + // + String vendor = "MSFT"; + String str; + if ((str = getValue(arch + "_" + cmd + "_VENDOR", map)) != null) { + vendor = str; + } else if ((str = getValue(arch + "_VENDOR", map)) != null) { + vendor = str; + } + // + // change to low letter + // + vendor = vendor.toLowerCase(); + // + // parse the corresponding file and get arch_cmd value + // + String filename = vendor + "_tools.txt"; + String[][] flagsMap; + if (filesMap.containsKey(filename)) { + flagsMap = (String[][]) filesMap.get(filename); + } else { + // + // read file and store in filesMap + // + flagsMap = ConfigReader.parse(confPath, vendor + "_tools.txt"); + filesMap.put(filename, flagsMap); + } + if ((str = getValue(arch + "_" + cmd, flagsMap)) != null) { + return str; + } + return ""; + } + + /** + Get the global flags (GLOBAL_ADD_FLAGS & GLOBAL_SUB_FLAGS) for specified + arch and command type. + +
    +
  • Find out Vendor that cmd Command Type with arch ARCH used. The + search sequence is ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT". Here + we suppose default Vendor is MSFT.
  • +
  • Search efi_flags_table.txt file, and get the corrsponding flags. +
  • +
+ + @param arch the ARCH + @param cmd the command type + @param map detail flags information of tools_def.txt + @return two values, first is GLOBAL_ADD_FLAGS and another value is + GLOBAL_SUB_FLAGS + **/ + private String[] getGlobalFlags(String arch, String cmd, String[][] map) { + String addStr = ""; + String subStr = ""; + // + // first is to find out its Vendor in map + // ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT" + // Here we suppose default Vendor is MSFT. + // + String vendor = "MSFT"; + String str; + if ((str = getValue(arch + "_" + cmd + "_VENDOR", map)) != null) { + vendor = str; + } else if ((str = getValue(arch + "_VENDOR", map)) != null) { + vendor = str; + } + // + // parse global flags table + // + if (globalFlagTable == null) { + globalFlagTable = ConfigReader.parseTable(confPath, "efi_flags_table.txt"); + } + for (int i=0; i < globalFlagTable.length; i++){ + String[] item = globalFlagTable[i]; + if (item[2].equalsIgnoreCase(vendor + "_" + arch + "_" + cmd)){ + // + // if item[0] == item[1] is existed in globalFlagsMap + // + if (globalFlagsMap.containsKey(item[0])){ + if( item[1].equalsIgnoreCase((String)globalFlagsMap.get(item[0]))){ + addStr += item[3] + " "; + subStr += item[4] + " "; + } + } + } + } + + return new String[]{addStr, subStr}; + } + + /** + Find out command path and command name. + +
+        Command path searching sequence in tools_def.txt file:
+        Path: ARCH_CMD_PATH -> ARCH_PATH -> Set to "".
+        
+        Command name searching sequence in tools_def.txt file:
+        Name: ARCH_CMD_NAME -> CMD_NAME -> Default Value.
+      
+ + @param arch the ARCH + @param cmd the Command Type + @param map detail flags information of tools_def.txt + @return the absolute command path and name + **/ + private String getAbsoluteCmdPath(String arch, String cmd, String[][] map) { + String path = ""; + String name = ""; + String str; + // + // find Path + // + if ((str = getValue(arch + "_" + cmd + "_PATH", map)) != null) { + path = str; + } else if ((str = getValue(arch + "_PATH", map)) != null) { + path = str; + } + // + // find Name + // + if ((str = getValue(arch + "_" + cmd + "_NAME", map)) != null) { + name = str; + } else if ((str = getValue(cmd + "_NAME", map)) != null) { + name = str; + } else { + name = getValue(cmd, defaultCmdName); + } + if (path.equalsIgnoreCase("")) { + return name; + } + return path + File.separatorChar + name; + } + + /** + Find out all global flags value, such as EFI_DEBUG equal YES or NO. Here + are three type files: global_efi_flags.txt, ${TARGET}_efi_flags.txt, + my_efi_flags.txt. global_efi_flags.txt with the highest priority while + my_efi_flags.txt with the lowest priority. + +

All global flags value will store in globalFlagsMap for + getGlobalFlags using.

+ + @param target current build TARGET value + **/ + private void parseGlobalSetting(String target){ + // + // parse global_efi_flags -> ${TARGET}_efi_flags -> my_efi_flags + // parse global_efi_flags + // + String[][] map = ConfigReader.parse(confPath, "global_efi_flags.txt"); + for (int i = 0; i < map.length; i++){ + if(globalFlagsMap.containsKey(map[i][0])){ + globalFlagsMap.remove(map[i][0]); + } + globalFlagsMap.put(map[i][0], map[i][1]); + } + // + // parse ${TARGET}_efi_flags + // + map = ConfigReader.parse(confPath, target + "_efi_flags.txt"); + for (int i = 0; i < map.length; i++){ + if(globalFlagsMap.containsKey(map[i][0])){ + globalFlagsMap.remove(map[i][0]); + } + globalFlagsMap.put(map[i][0], map[i][1]); + } + // + // parse my_efi_flags.txt + // + map = ConfigReader.parse(confPath, "my_efi_flags.txt"); + for (int i = 0; i < map.length; i++){ + if(globalFlagsMap.containsKey(map[i][0])){ + globalFlagsMap.remove(map[i][0]); + } + globalFlagsMap.put(map[i][0], map[i][1]); + } + } + + /** + Find value with key from map. If not found, return null. + +

Note that default is case-insensitive

+ + @param key key value + @param map mapping information + @return the related value of key + **/ + private String getValue(String key, String[][] map) { + return getValue(key, map, false); + } + + /** + Find value with key from map. If not found, return null. + + @param key key value + @param map mapping information + @param caseSensitive whether case sesitive or not + @return the related value of key + **/ + private String getValue(String key, String[][] map, boolean caseSensitive) { + for (int i = 0; i < map.length; i++) { + if (caseSensitive) { + if (key.compareTo(map[i][0]) == 0) { + return map[i][1]; + } + } else { + if (key.compareToIgnoreCase(map[i][0]) == 0) { + return map[i][1]; + } + } + } + return null; + } + + /** + Find value with key from toolchain. If not found, return null. + + @param key key value + @return the related value of key + **/ + public static String getValue(String key){ + for (int i = 0; i < toolchain.length; i++) { + if (key.compareToIgnoreCase(toolchain[i][0]) == 0) { + return toolchain[i][1]; + } + } + return null; + } + + /** + Get Arch list from a string separated with comma. + +
+        For example:
+          If the arch string is "IA32, X64, EBC".
+          Then the result is {"IA32", "X64", "EBC"}. 
+      
+ + @param arch string separated with comma + @return Arch list + **/ + public String[] getArchs(String arch) { + if (arch == null) { + return new String[0]; + } + StringTokenizer st = new StringTokenizer(arch, " \t,"); + String[] archs = new String[st.countTokens()]; + int i = 0; + while (st.hasMoreTokens()) { + archs[i++] = st.nextToken().toUpperCase(); + } + return archs; + } + + /** + Get current target value. + + @return current target value + **/ + public String getCurrentTarget() { + return currentTarget; + } + + /** + Find out Vendor that cmd Command Type with arch ARCH used. The + search sequence is ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT". Here + we suppose default Vendor is MSFT. + + @param arch the ARCH + @param cmd the Command Type + @param map detail flags information of tools_def.txt + @return the related vendor name + **/ + public String getVendorFlag (String arch, String cmdType, String[][] map){ + // + // ARCH_CMD_VENDOR -> ARCH_VENDOR -> "MSFT" + // Here we suppose default Vendor is MSFT. + // + String str; + String vendor = ""; + if (cmdType != null){ + if ((str = getValue(arch + "_" + cmdType + "_VENDOR", map)) != null) { + vendor = str; + }else { + vendor = ""; + } + }else if (arch != null){ + if ((str = getValue(arch + "_VENDOR", map)) != null) { + vendor = str; + }else { + vendor = ""; + } + } + return vendor; + } + +} diff --git a/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainTask.java b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainTask.java new file mode 100644 index 0000000000..04dab1c3e3 --- /dev/null +++ b/Tools/Source/GenBuild/org/tianocore/build/toolchain/ToolChainTask.java @@ -0,0 +1,60 @@ +/** @file + ToolChainTask class. + + ToolChainTask class's main fucntion is read all tool chain related config files. + +Copyright (c) 2006, 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. + +**/ +package org.tianocore.build.toolchain; + +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Task; + +/** + This class is an ANT task. The main function is to read all tool chain related + config files. + + @since GenBuild 1.0 +**/ +public class ToolChainTask extends Task{ + + private String confPath = "."; + + /** + Public construct method. It is necessary for ANT task. + **/ + public ToolChainTask(){ + } + + /** + ANT task's entry point, will be called after init(). Using + ToolChainFactory to parse all config files, and + set TARGET property. + + @throws BuildException + Config files are invalid. + **/ + public void execute() throws BuildException { + String toolChain = getProject().getProperty("env.TOOL_CHAIN"); + ToolChainFactory toolchain = new ToolChainFactory(confPath, toolChain); + toolchain.setupToolChain(); + getProject().setProperty("TARGET", toolchain.getCurrentTarget()); + } + + /** + Set the path of config files. + + @param confPath the path of config files + **/ + public void setConfPath(String confPath) { + this.confPath = confPath; + } +} diff --git a/Tools/Source/ModuleEditor/MANIFEST.MF b/Tools/Source/ModuleEditor/MANIFEST.MF new file mode 100644 index 0000000000..dffa2192fa --- /dev/null +++ b/Tools/Source/ModuleEditor/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: org.tianocore.packaging.module.ui.ModuleMain +Class-Path: ../Jars/SurfaceArea.jar ../bin/xmlbeans/lib/jsr173_1.0_api.jar ../bin/xmlbeans/lib/xbean.jar ../bin/xmlbeans/lib/xbean_xpath.jar ../bin/xmlbeans/lib/xmlpublic.jar ../bin/xmlbeans/lib/saxon8.jar ../bin/xmlbeans/lib/saxon8-jdom.jar ../bin/xmlbeans/lib/saxon8-sql.jar ../bin/xmlbeans/lib/resolver.jar diff --git a/Tools/Source/ModuleEditor/build.xml b/Tools/Source/ModuleEditor/build.xml new file mode 100644 index 0000000000..f78750e819 --- /dev/null +++ b/Tools/Source/ModuleEditor/build.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/common/DataType.java b/Tools/Source/ModuleEditor/src/org/tianocore/common/DataType.java new file mode 100644 index 0000000000..ea0731b70f --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/common/DataType.java @@ -0,0 +1,44 @@ +/** @file + + The file is used to define all used final variables + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.common; + +/** + The class is used to define all used final variables + + @since ModuleEditor 1.0 + +**/ +public class DataType { + + /** + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + // + // Define all used final variables + // + public static final String DOS_LINE_SEPARATOR = "\r\n"; + + public static final String UNXI_LINE_SEPARATOR = "\n"; + + public static final String EMPTY_SELECT_ITEM = "----"; + +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/common/DataValidation.java b/Tools/Source/ModuleEditor/src/org/tianocore/common/DataValidation.java new file mode 100644 index 0000000000..4747343725 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/common/DataValidation.java @@ -0,0 +1,905 @@ +/** @file + + The file is used to provides all kinds of Data Validation interface + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.common; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + The class is used to provides all kinds of data validation interface + +

All provided interfaces are in static mode

+ + @since ModuleEditor 1.0 + + **/ +public class DataValidation { + + /** + Reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + // + // The below is used to check common data types + // + + /** + Check if the imput data is int + + @param strInt The input string which needs validation + + @retval true - The input is Int + @retval false - The input is not Int + + **/ + public static boolean isInt(String strInt) { + return isMatch("^-?[0-9]\\d*$", strInt); + } + + /** + Check if the input data is int and it is in the valid scope + The scope is provided by String + + @param strNumber The input string which needs validation + @param BeginNumber The left boundary of the scope + @param EndNumber The right boundary of the scope + + @retval true - The input is Int and in the scope; + @retval false - The input is not Int or not in the scope + + **/ + public static boolean isInt(String strNumber, int BeginNumber, int EndNumber) { + // + //Check if the input data is int first + // + if (!isInt(strNumber)) { + return false; + } + // + //And then check if the data is between the scope + // + Integer intTemp = new Integer(strNumber); + if ((intTemp.intValue() < BeginNumber) || (intTemp.intValue() > EndNumber)) { + return false; + } + return true; + } + + /** + Check if the input data is int and it is in the valid scope + The scope is provided by String + + @param strNumber The input string which needs validation + @param strBeginNumber The left boundary of the scope + @param strEndNumber The right boundary of the scope + + @retval true - The input is Int and in the scope; + @retval false - The input is not Int or not in the scope + + **/ + public static boolean isInt(String strNumber, String strBeginNumber, String strEndNumber) { + // + //Check if all input data are int + // + if (!isInt(strNumber)) { + return false; + } + if (!isInt(strBeginNumber)) { + return false; + } + if (!isInt(strEndNumber)) { + return false; + } + // + //And then check if the data is between the scope + // + Integer intI = new Integer(strNumber); + Integer intJ = new Integer(strBeginNumber); + Integer intK = new Integer(strEndNumber); + if ((intI.intValue() < intJ.intValue()) || (intI.intValue() > intK.intValue())) { + return false; + } + return true; + } + + /** + Use regex to check if the input data is in valid format + + @param strPattern The input regex + @param strMatcher The input data need be checked + + @retval true - The data matches the regex + @retval false - The data doesn't match the regex + + **/ + public static boolean isMatch(String strPattern, String strMatcher) { + Pattern pattern = Pattern.compile(strPattern); + Matcher matcher = pattern.matcher(strMatcher); + + return matcher.find(); + } + + // + // The below is used to check common customized data types + // + + /** + Check if the input data is BaseNameConvention + + @param strBaseNameConvention The input string need be checked + + @retval true - The input is BaseNameConvention + @retval false - The input is not BaseNameConvention + + **/ + public static boolean isBaseNameConvention(String strBaseNameConvention) { + return isMatch("[A-Z]([a-zA-Z0-9])*(_)?([a-zA-Z0-9])*", strBaseNameConvention); + } + + /** + Check if the input data is GuidArrayType + + @param strGuidArrayType The input string need be checked + + @retval true - The input is GuidArrayType + @retval false - The input is not GuidArrayType + + **/ + public static boolean isGuidArrayType(String strGuidArrayType) { + return isMatch( + "0x[a-fA-F0-9]{1,8},( )*0x[a-fA-F0-9]{1,4},( )*0x[a-fA-F0-9]{1,4}(,( )*\\{)?(,?( )*0x[a-fA-F0-9]{1,2}){8}( )*(\\})?", + strGuidArrayType); + } + + /** + Check if the input data is GuidNamingConvention + + @param strGuidNamingConvention The input string need be checked + + @retval true - The input is GuidNamingConvention + @retval false - The input is not GuidNamingConvention + + **/ + public static boolean isGuidNamingConvention(String strGuidNamingConvention) { + return isMatch("[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}", + strGuidNamingConvention); + } + + /** + Check if the input data is GuidType + + @param strGuidType The input string need be checked + + @retval true - The input is GuidType + @reture false is not GuidType + + **/ + public static boolean isGuidType(String strGuidType) { + return (isGuidArrayType(strGuidType) || isGuidNamingConvention(strGuidType)); + } + + /** + Check if the input data is Guid + + @param strGuid The input string need be checked + + @retval true - The input is Guid + @retval false - The input is not Guid + + **/ + public static boolean isGuid(String strGuid) { + return isGuidType(strGuid); + } + + /** + Check if the input data is Sentence + + @param strSentence The input string need be checked + + @retval true - The input is Sentence + @retval false - The input is not Sentence + + **/ + public static boolean isSentence(String strSentence) { + return isMatch("(\\w+\\W*)+( )+(\\W*\\w*\\W*\\s*)*", strSentence); + } + + /** + Check if the input data is DateType + + @param strDateType The input string need be checked + + @retval true - The input is DateType + @retval false - The input is not DateType + + **/ + public static boolean isDateType(String strDateType) { + return isMatch("[1-9][0-9][0-9][0-9]-[0-1][0-9]-[0-3][0-9] [0-2][0-9]:[0-5][0-9]", strDateType); + } + + /** + Check if the input data is DosPath + + @param strDosPath The input string need be checked + + @retval true - The input is DosPath + @retval false - The input is not DosPath + + **/ + public static boolean isDosPath(String strDosPath) { + return isMatch("([a-zA-Z]:\\\\)?(((\\\\?_*-*.*[a-zA-Z0-9]*)*(_*-*.*[a-zA-Z0-9])*)+(\\\\)?)*", strDosPath); + } + + /** + Check if the input data is UnixPath + + @param strUnixPath The input string need be checked + + @retval true - The input is UnixPath + @retval false - The input is not UnixPath + + **/ + public static boolean isUnixPath(String strUnixPath) { + return isMatch("(\\/)?(((_*-*.*[a-zA-Z0-9]*)*(_*-*.*[a-zA-Z0-9])*)+(\\/)?)*", strUnixPath); + } + + /** + Check if the input data is DirectoryNamingConvention + + @param strDirectoryNamingConvention The input string need be checked + + @retval true - The input is DirectoryNamingConvention + @retval false - The input is not DirectoryNamingConvention + + **/ + public static boolean isDirectoryNamingConvention(String strDirectoryNamingConvention) { + return (isDosPath(strDirectoryNamingConvention) || isUnixPath(strDirectoryNamingConvention)); + } + + /** + Check if the input data is HexDoubleWordDataType + + @param strHexDoubleWordDataType The input string need be checked + + @retval true - The input is HexDoubleWordDataType + @retval false - The input is not HexDoubleWordDataType + + **/ + public static boolean isHexDoubleWordDataType(String strHexDoubleWordDataType) { + return isMatch("0x[a-fA-F0-9]{1,8}", strHexDoubleWordDataType); + } + + /** + Check if the input data is V1 + + @param strV1 The input string need be checked + + @retval true - The input is V1 + @retval false - The input is not V1 + + **/ + public static boolean isV1(String strV1) { + return isMatch("((%[A-Z](_*[A-Z0-9]*)*%)+((((\\\\)?_*-*.*[a-zA-Z0-9]*)*(_*-*.*[a-zA-Z0-9])*)+(\\\\)?)*)", strV1); + } + + /** + Check if the input data is V2 + + @param strV2 The input string need be checked + + @retval true - The input is V2 + @retval false - The input is not V2 + + **/ + public static boolean isV2(String strV2) { + return isMatch( + "(($[A-Z](_*[A-Z0-9]*)*)+||($\\([A-Z](_*[A-Z0-9]*)*\\))+||($\\{[A-Z](_*[A-Z0-9]*)*\\})+)+(\\/)?(((((_*-*.*[a-zA-Z0-9]*)*(_*-*.*[a-zA-Z0-9])*)+(\\/)?)*)*)", + strV2); + } + + /** + Check if the input data is VariableConvention + + @param strVariableConvention The input string need be checked + + @retval true - The input is VariableConvention + @retval false - The input is not VariableConvention + + **/ + public static boolean isVariableConvention(String strVariableConvention) { + return (isV1(strVariableConvention) || isV2(strVariableConvention)); + } + + /** + Check if the input data is UCName + + @param strUCName The input string need be checked + + @retval true - The input is UCName + @retval false - The input is not UCName + + **/ + public static boolean isUCName(String strUCName) { + return isMatch("[A-Z]+(_*[A-Z0-9]*( )*)*", strUCName); + } + + /** + Check if the input data is HexByteDataType + + @param strHex64BitDataType The input string need be checked + + @retval true - The input is HexByteDataType + @retval false - The input is not HexByteDataType + + **/ + public static boolean isHexByteDataType(String strHex64BitDataType) { + return isMatch("(0x)?[a-fA-F0-9]{1,2}", strHex64BitDataType); + } + + /** + Check if the input data is Hex64BitDataType + + @param strHex64BitDataType The input string need be checked + + @retval true - The input is Hex64BitDataType + @retval false - The input is not Hex64BitDataType + + **/ + public static boolean isHex64BitDataType(String strHex64BitDataType) { + return isMatch("(0x)?[a-fA-F0-9]{1,16}", strHex64BitDataType); + } + + /** + Check if the input data is HexWordDataType + + @param strHexWordDataType The input string need be checked + + @retval true - The input is HexWordDataType + @retval false - The input is not HexWordDataType + + **/ + public static boolean isHexWordDataType(String strHexWordDataType) { + return isMatch("0x[a-fA-F0-9]{1,4}", strHexWordDataType); + } + + /** + Check if the input data is CName + + @param strCName The input string need be checked + + @retval true - The input is CName + @retval false - The input is not CName + + **/ + public static boolean isCName(String strCName) { + return isMatch("((_)*([a-zA-Z])+((_)*[a-zA-Z0-9]*))*", strCName); + } + + /** + Check if the input data is OverrideID + + @param strOverrideID The input string need be checked + + @retval true - The input is OverrideID + @retval false - The input is not OverrideID + + **/ + public static boolean isOverrideID(String strOverrideID) { + return isInt(strOverrideID); + } + + // + //The below is used to check msaheader data type + // + + /** + Check if the input data is BaseName + + @param strBaseName The input string need be checked + + @retval true - The input is BaseName + @retval false - The input is not BaseName + + **/ + public static boolean isBaseName(String strBaseName) { + return isBaseNameConvention(strBaseName); + } + + /** + Check if the input data is Abstract + + @param strAbstract The input string need be checked + + @retval true - The input is Abstract + @retval false - The input is not Abstract + + **/ + public static boolean isAbstract(String strAbstract) { + return isSentence(strAbstract); + } + + /** + Check if the input data is Copyright + + @param strCopyright The input string need be checked + + @retval true - The input is Copyright + @retval false - The input is not Copyright + + **/ + public static boolean isCopyright(String strCopyright) { + return isSentence(strCopyright); + } + + /** + Check if the input data is Created + + @param strCreated The input string need be checked + + @retval true - The input is Created + @retval false - The input is not Created + + **/ + public static boolean isCreated(String strCreated) { + return isDateType(strCreated); + } + + /** + Check if the input data is Updated + + @param strUpdated The input string need be checked + + @retval true - The input is Updated + @retval false - The input is not Updated + + **/ + public static boolean isUpdated(String strUpdated) { + return isDateType(strUpdated); + } + + // + // The below is used to check LibraryClass data types + // + + /** + Check if the input data is LibraryClass + + @param strLibraryClass The input string need be checked + + @retval true - The input is LibraryClass + @retval false - The input is not LibraryClass + + **/ + public static boolean isLibraryClass(String strLibraryClass) { + return isBaseNameConvention(strLibraryClass); + } + + // + // The below is used to check sourcefiles data types + // + + /** + Check if the input data is Path + + @param strPath The input string need be checked + + @retval true - The input is Path + @retval false - The input is not Path + + **/ + public static boolean isPath(String strPath) { + return isDirectoryNamingConvention(strPath); + } + + /** + Check if the input data is FileName + + @param strFileName The input string need be checked + + @retval true - The input is FileName + @retval false - The input is not FileName + + **/ + public static boolean isFileName(String strFileName) { + return isVariableConvention(strFileName); + } + + // + // The below is used to check includes data types + // + + /** + Check if the input data is UpdatedDate + + @param strUpdatedDate The input string need be checked + + @retval true - The input is UpdatedDate + @retval false - The input is not UpdatedDate + + **/ + public static boolean isUpdatedDate(String strUpdatedDate) { + return isDateType(strUpdatedDate); + } + + /** + Check if the input data is PackageName + + @param strPackageName The input string need be checked + + @retval true - The input is PackageName + @retval false - The input is not PackageName + + **/ + public static boolean isPackageName(String strPackageName) { + return isBaseNameConvention(strPackageName); + } + + // + // The below is used to check protocols data types + // + + /** + Check if the input data is ProtocolName + + @param strProtocolName The input string need be checked + + @retval true - The input is ProtocolName + @retval false - The input is not ProtocolName + + **/ + public static boolean isProtocolName(String strProtocolName) { + return isCName(strProtocolName); + } + + /** + Check if the input data is ProtocolNotifyName + + @param strProtocolNotifyName The input string need be checked + + @retval true - The input is ProtocolNotifyName + @retval false - The input is not ProtocolNotifyName + + **/ + public static boolean isProtocolNotifyName(String strProtocolNotifyName) { + return isCName(strProtocolNotifyName); + } + + // + // The below is used to check ppis data types + // + + /** + Check if the input data is PpiName + + @param strPpiName The input string need be checked + + @retval true - The input is PpiName + @retval false - The input is not PpiName + + **/ + public static boolean isPpiName(String strPpiName) { + return isCName(strPpiName); + } + + /** + Check if the input data is PpiNotifyName + + @param strPpiNotifyName The input string need be checked + + @retval true - The input is PpiNotifyName + @retval false - The input is not PpiNotifyName + + **/ + public static boolean isPpiNotifyName(String strPpiNotifyName) { + return isCName(strPpiNotifyName); + } + + /** + Check if the input data is FeatureFlag + + @param strFeatureFlag The input string need be checked + + @retval true - The input is FeatureFlag + @retval false - The input is not FeatureFlag + + **/ + public static boolean isFeatureFlag(String strFeatureFlag) { + return isCName(strFeatureFlag); + } + + // + // The below is used to check variable data types + // + + /** + Check if the input data is ByteOffset + + @param strByteOffset The input string need be checked + + @retval true - The input is ByteOffset + @retval false - The input is not ByteOffset + + **/ + public static boolean isByteOffset(String strByteOffset) { + return isByteOffset(strByteOffset); + } + + /** + Check if the input data is BitOffset + + @param strBitOffset The input string need be checked + + @retval true - The input is BitOffset + @retval false - The input is not BitOffset + + **/ + public static boolean isBitOffset(String strBitOffset) { + return isInt(strBitOffset, 0, 8); + } + + /** + Check if the input data is OffsetBitSize + + @param strOffsetBitSize The input string need be checked + + @retval true - The input is OffsetBitSize + @retval false - The input is not OffsetBitSize + + **/ + public static boolean isOffsetBitSize(String strOffsetBitSize) { + return isInt(strOffsetBitSize, 0, 7); + } + + // + // The below is used to check formsets data types + // + + /** + Check if the input data is Formsets + + @param strFormsets The input string need be checked + + @retval true - The input is Formsets + @retval false - The input is not Formsets + + **/ + public static boolean isFormsets(String strFormsets) { + return isCName(strFormsets); + } + + // + // The below is used to check externs data types + // + + /** + Check if the input data is Constructor + + @param strConstructor The input string need be checked + + @retval true - The input is Constructor + @retval false - The input is not Constructor + + **/ + public static boolean isConstructor(String strConstructor) { + return isCName(strConstructor); + } + + /** + Check if the input data is Destructor + + @param strDestructor The input string need be checked + + @retval true - The input is Destructor + @retval false - The input is not Destructor + + **/ + public static boolean isDestructor(String strDestructor) { + return isCName(strDestructor); + } + + /** + Check if the input data is DriverBinding + + @param strDriverBinding The input string need be checked + + @retval true - The input is DriverBinding + @retval false - The input is not DriverBinding + + **/ + public static boolean isDriverBinding(String strDriverBinding) { + return isCName(strDriverBinding); + } + + /** + Check if the input data is ComponentName + + @param strComponentName The input string need be checked + + @retval true - The input is ComponentName + @retval false - The input is not ComponentName + + **/ + public static boolean isComponentName(String strComponentName) { + return isCName(strComponentName); + } + + /** + Check if the input data is DriverConfig + + @param strDriverConfig The input string need be checked + + @retval true - The input is DriverConfig + @retval false - The input is not DriverConfig + + **/ + public static boolean isDriverConfig(String strDriverConfig) { + return isCName(strDriverConfig); + } + + /** + Check if the input data is DriverDiag + + @param strDriverDiag The input string need be checked + + @retval true - The input is DriverDiag + @retval false - The input is not DriverDiag + + **/ + public static boolean isDriverDiag(String strDriverDiag) { + return isCName(strDriverDiag); + } + + /** + Check if the input data is SetVirtualAddressMapCallBack + + @param strSetVirtualAddressMapCallBack The input string need be checked + + @retval true - The input is SetVirtualAddressMapCallBack + @retval false - The input is not SetVirtualAddressMapCallBack + + **/ + public static boolean isSetVirtualAddressMapCallBack(String strSetVirtualAddressMapCallBack) { + return isCName(strSetVirtualAddressMapCallBack); + } + + /** + Check if the input data is ExitBootServicesCallBack + + @param strExitBootServicesCallBack The input string need be checked + + @retval true - The input is ExitBootServicesCallBack + @retval false - The input is not ExitBootServicesCallBack + + **/ + public static boolean isExitBootServicesCallBack(String strExitBootServicesCallBack) { + return isCName(strExitBootServicesCallBack); + } + + /** + Check if the input data is UserDefined + + @param strUserDefined The input string need be checked + + @retval true - The input is UserDefined + @retval false - The input is not UserDefined + + **/ + public static boolean isUserDefined(String strUserDefined) { + return isCName(strUserDefined); + } + + // + // The below is used to check PCDs data types + // + + /** + Check if the input data is Token + + @param strToken The input string need be checked + + @retval true - The input is Token + @retval false - The input is not Token + + **/ + public static boolean isToken(String strToken) { + return isHexDoubleWordDataType(strToken); + } + + /** + Check if the input data is MaxSku + + @param strMaxSku The input string need be checked + + @retval true - The input is MaxSku + @retval false - The input is not MaxSku + + **/ + public static boolean isMaxSku(String strMaxSku) { + return isHexByteDataType(strMaxSku); + } + + /** + Check if the input data is SkuId + + @param strSkuId The input string need be checked + + @retval true - The input is SkuId + @retval false - The input is not SkuId + + **/ + public static boolean isSkuId(String strSkuId) { + return isHexByteDataType(strSkuId); + } + + /** + Check if the input data is DatumSize + + @param strDatumSize The input string need be checked + + @retval true - The input is DatumSize + @retval false - The input is not DatumSize + + **/ + public static boolean isDatumSize(String strDatumSize) { + return isInt(strDatumSize, 1, 16777215); + } + + /** + Check if the input data is VariableGuid + + @param strVariableGuid The input string need be checked + + @retval true - The input is VariableGuid + @retval false - The input is not VariableGuid + + **/ + public static boolean isVariableGuid(String strVariableGuid) { + return (isGuid(strVariableGuid) || strVariableGuid.equals("0")); + } + + /** + Check if the input data is DataOffset + + @param strDataOffset The input string need be checked + + @retval true - The input is DataOffset + @retval false - The input is not DataOffset + + **/ + public static boolean isDataOffset(String strDataOffset) { + return isHex64BitDataType(strDataOffset); + } + + /** + Check if the input data is GuidOffset + + @param strGuidOffset The input string need be checked + + @retval true - The input is GuidOffset + @retval false - The input is not GuidOffset + + **/ + public static boolean isGuidOffset(String strGuidOffset) { + return isHex64BitDataType(strGuidOffset); + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/common/IFileFilter.java b/Tools/Source/ModuleEditor/src/org/tianocore/common/IFileFilter.java new file mode 100644 index 0000000000..1daf7fa867 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/common/IFileFilter.java @@ -0,0 +1,87 @@ +/** @file + + The file is used to override FileFilter to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.common; + +import java.io.File; + +import javax.swing.filechooser.FileFilter; + +/** + The class is used to override FileFilter to provides customized interfaces + + @since ModuleEditor 1.0 + + **/ +public class IFileFilter extends FileFilter { + + private String strExt; + + /** + Reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + /** + This is the default constructor + + @param ext + + **/ + public IFileFilter(String ext) { + this.strExt = ext; + } + + /* (non-Javadoc) + * @see javax.swing.filechooser.FileFilter#accept(java.io.File) + * + * Override method "accept" + * + */ + public boolean accept(File file) { + if (file.isDirectory()) { + return true; + } + String strFileName = file.getName(); + int intIndex = strFileName.lastIndexOf('.'); + if (intIndex > 0 && intIndex < strFileName.length() - 1) { + String strExtension = strFileName.substring(intIndex + 1).toLowerCase(); + if (strExtension.equals(strExt)) + return true; + } + return false; + } + + /* (non-Javadoc) + * @see javax.swing.filechooser.FileFilter#getDescription() + * + * Override method "getDescription" to config description via different file type + * + */ + public String getDescription() { + if (strExt.equals("msa")) + return "Module Surface Area File(*.msa)"; + if (strExt.equals("mbd")) + return "Module Build Description File(*.mbd)"; + return ""; + } + +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/common/Log.java b/Tools/Source/ModuleEditor/src/org/tianocore/common/Log.java new file mode 100644 index 0000000000..0759fc619c --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/common/Log.java @@ -0,0 +1,211 @@ +/** @file + + The file is used to provides static interfaces to save log and error information + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.common; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +import javax.swing.JOptionPane; + +/** + The class is used to provides static interfaces to save log and error information + + @since ModuleEditor 1.0 + + **/ +public class Log { + + // + //Log file + // + private static File fleLogFile = null; + + // + //Err file + // + private static File fleErrFile = null; + + // + //Log file name + // + static String strLogFileName = "Log.log"; + + // + //Err file name + // + static String strErrFileName = "Err.log"; + + /** + Main class, used for test + + @param args + + **/ + public static void main(String[] args) { + try { + Log.log("Test", "test"); + Log.err("Test1", "test1"); + Log.err("sdfsdfsd fsdfsdfsdfsdfj dsfksdjflsdjf sdkfjsdklfjsdkf dskfsjdkfjks dskfjsdklfjsdkf sdkfjsdlf sdkfjsdk kdfjskdf sdkfjsdkf ksdjfksdfjskdf sdkfsjdfksd fskdfjsdf", "dfsdf sdfksdf sd sdfksd fsdf"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + This is the default constructor + Do nothing + + **/ + public Log() { + } + + /** + Call writeToLogFile to save log item and log information to log file + + @param strItem The log item + @param strLog The log information + + **/ + public static void log(String strItem, String strLog) { + try { + writeToLogFile(strItem + ":" + strLog); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + Call writeToLogFile to save log information to log file + + @param strLog The log information + + **/ + public static void log(String strLog) { + try { + writeToLogFile(strLog); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + Call writeToErrFile to save err item and err information to err file + + @param strItem The err item + @param strLog The err information + + **/ + public static void err(String strItem, String strErr) { + try { + writeToErrFile("Error when " + strItem + "::" + strErr); + showErrMessage("Error when " + strItem + "::" + strErr); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + Call writeToErrFile to save err information to err file + + @param strLog The err information + + **/ + public static void err(String strErr) { + try { + writeToErrFile("Error::" + strErr); + showErrMessage("Error::" + strErr); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + Brings up a dialog to show err message + When the message's length > defined max length, wrap the text to the next line. + + @param strErr The input data of err message + + **/ + private static void showErrMessage(String strErr) { + int intMaxLength = 40; + String strReturn = ""; + String strTemp = ""; + while (strErr.length() > 0) { + if (strErr.length() > intMaxLength) { + strTemp = strErr.substring(0, intMaxLength); + strErr = strErr.substring(strTemp.length()); + strReturn = strReturn + strTemp + DataType.UNXI_LINE_SEPARATOR; + + } else if (strErr.length() <= intMaxLength) { + strReturn = strReturn + strErr; + strErr = ""; + } + } + JOptionPane.showConfirmDialog(null, strReturn, "Error", JOptionPane.DEFAULT_OPTION, JOptionPane.ERROR_MESSAGE); + } + + /** + Open log file and write log information + + @param strLog The log information + @throws IOException + + **/ + private static void writeToLogFile(String strLog) throws IOException { + try { + if (fleLogFile == null) { + fleLogFile = new File(strLogFileName); + fleLogFile.createNewFile(); + } + FileOutputStream fos = new FileOutputStream(fleLogFile, true); + fos.write((Tools.getCurrentDateTime() + DataType.DOS_LINE_SEPARATOR).getBytes()); + fos.write((strLog + DataType.DOS_LINE_SEPARATOR).getBytes()); + fos.flush(); + fos.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + Open err file and write err information + + @param strLog The log information + @throws IOException + + **/ + private static void writeToErrFile(String strLog) throws IOException { + try { + if (fleErrFile == null) { + fleErrFile = new File(strErrFileName); + fleErrFile.createNewFile(); + } + FileOutputStream fos = new FileOutputStream(fleErrFile, true); + fos.write((Tools.getCurrentDateTime() + DataType.DOS_LINE_SEPARATOR).getBytes()); + fos.write((strLog + DataType.DOS_LINE_SEPARATOR).getBytes()); + fos.flush(); + fos.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/common/Tools.java b/Tools/Source/ModuleEditor/src/org/tianocore/common/Tools.java new file mode 100644 index 0000000000..a11df00377 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/common/Tools.java @@ -0,0 +1,120 @@ +/** @file + + The file is used to provides some useful interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.common; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.UUID; + +/** + The class is used to provides some useful interfaces + + @since ModuleEditor 1.0 + + **/ +public class Tools { + + /** + Used for test + + @param args + + **/ + public static void main(String[] args) { + System.out.println(getCurrentDateTime()); + } + + /** + Get current date and time and format it as "yyyy-MM-dd HH:mm" + + @return formatted current date and time + + **/ + public static String getCurrentDateTime() { + Date now = new Date(System.currentTimeMillis()); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + return sdf.format(now); + } + + /** + Delete a folder and all its files + + @param fleFolderName The name of the folder which need be deleted + + @retval true - Delete successfully + @retval false - Delete successfully + + **/ + public static boolean deleteFolder(File fleFolderName) { + boolean blnIsDeleted = true; + File[] aryAllFiles = fleFolderName.listFiles(); + + for (int indexI = 0; indexI < aryAllFiles.length; indexI++) { + if (blnIsDeleted) { + if (aryAllFiles[indexI].isDirectory()) { + // + //If is a directory, recursively call this function to delete sub folders + // + blnIsDeleted = deleteFolder(aryAllFiles[indexI]); + } else if (aryAllFiles[indexI].isFile()) { + // + //If is a file, delete it + // + if (!aryAllFiles[indexI].delete()) { + blnIsDeleted = false; + } + } + } + } + if (blnIsDeleted) { + fleFolderName.delete(); + } + return blnIsDeleted; + } + + /** + Generate a UUID + + @return the created UUID + + **/ + public static String generateUuidString() { + return UUID.randomUUID().toString(); + } + + /** + Get all system properties and output to the console + + **/ + public static void getSystemProperties() { + System.out.println(System.getProperty("java.class.version")); + System.out.println(System.getProperty("java.class.path")); + System.out.println(System.getProperty("java.ext.dirs")); + System.out.println(System.getProperty("os.name")); + System.out.println(System.getProperty("os.arch")); + System.out.println(System.getProperty("os.version")); + System.out.println(System.getProperty("file.separator")); + System.out.println(System.getProperty("path.separator")); + System.out.println(System.getProperty("line.separator")); + System.out.println(System.getProperty("user.name")); + System.out.println(System.getProperty("user.home")); + System.out.println(System.getProperty("user.dir")); + System.out.println(System.getProperty("PATH")); + + System.out.println(System.getenv("PROCESSOR_REVISION")); + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/ExitConfirm.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/ExitConfirm.java new file mode 100644 index 0000000000..2ff84b669b --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/ExitConfirm.java @@ -0,0 +1,265 @@ +/** @file + + The file is used to popup a exit confirmation window when program exists + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.common.ui; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** + The class is used to popup a exit confirmation window when program exists + It extends JDialog and implements ActionListener and WindowListener + + @since ModuleEditor 1.0 + + **/ +public class ExitConfirm extends JDialog implements ActionListener, WindowListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -5875921789385911029L; + + private JPanel jContentPane = null; + + private JLabel jLabelMessage = null; + + private JLabel jLabelResume = null; + + private JLabel jLabelExit = null; + + private JButton jButtonResume = null; + + private JButton jButtonExit = null; + + public boolean isCancel = false; + + /** + This method initializes jButtonResume + + @return javax.swing.JButton jButtonResume + + **/ + private JButton getJButtonResume() { + if (jButtonResume == null) { + jButtonResume = new JButton(); + jButtonResume.setText("Resume"); + jButtonResume.setSize(new java.awt.Dimension(90, 20)); + jButtonResume.setLocation(new java.awt.Point(150, 105)); + jButtonResume.setMnemonic('R'); + jButtonResume.addActionListener(this); + } + return jButtonResume; + } + + /** + This method initializes jButtonExit + + @return javax.swing.JButton jButtonExit + + **/ + private JButton getJButtonExit() { + if (jButtonExit == null) { + jButtonExit = new JButton(); + jButtonExit.setText("Exit"); + jButtonExit.setSize(new java.awt.Dimension(90, 20)); + jButtonExit.setLocation(new java.awt.Point(260, 105)); + jButtonExit.setMnemonic('x'); + jButtonExit.addActionListener(this); + } + return jButtonExit; + } + + /** + Main clasee, reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + /** + This is the default constructor + + **/ + public ExitConfirm(IFrame parentFrame, boolean modal) { + super(parentFrame, modal); + initialize(); + } + + /** + This method initializes this + + @return void + + **/ + private void initialize() { + this.setSize(500, 170); + this.setTitle("Exit"); + this.setResizable(false); + this.setContentPane(getJContentPane()); + this.addWindowListener(this); + // + //Set DO_NOTHING_ON_CLOSE when click Close button on title bar + // + this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + centerWindow(); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelExit = new JLabel(); + jLabelExit.setSize(new java.awt.Dimension(450, 20)); + jLabelExit.setLocation(new java.awt.Point(25, 70)); + jLabelResume = new JLabel(); + jLabelResume.setSize(new java.awt.Dimension(450, 20)); + jLabelResume.setLocation(new java.awt.Point(25, 40)); + jLabelMessage = new JLabel(); + jLabelMessage.setSize(new java.awt.Dimension(450, 20)); + jLabelMessage.setLocation(new java.awt.Point(25, 10)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelMessage, null); + jContentPane.add(jLabelResume, null); + jContentPane.add(jLabelExit, null); + jContentPane.add(getJButtonResume(), null); + jContentPane.add(getJButtonExit(), null); + } + return jContentPane; + } + + /** + Call setWarningMessage to set messages of frame when it is used for Setup + + **/ + public void setSetupMessage() { + String strTitle = "Exit Setup"; + String strMessage = "Setup is not complete. If you quit now, the program will not be installed."; + String strResume = "You may run the setup program at a later time to complete the installation."; + String strExit = "To continue installing, click Resume. To quit the Setup program, click Exit."; + setWarningMessage(strTitle, strMessage, strResume, strExit); + } + + /** + Call setWarningMessage to set messages of frame when it is used for Module Main GUI + + **/ + public void setModuleMessage() { + String strTitle = "Exit"; + String strMessage = "Do you really want to quit now?"; + String strResume = "All unsaved module information will be lost."; + String strExit = "To continue editing module, click Resume. To quit the program, click Exit."; + setWarningMessage(strTitle, strMessage, strResume, strExit); + } + + /** + Set message information via input data + + @param strTitle The title value + @param strMessage The main message value + @param strResume The resume message value + @param strExit The exit message value + + **/ + private void setWarningMessage(String strTitle, String strMessage, String strResume, String strExit) { + this.setTitle(strTitle); + jLabelMessage.setText(strMessage); + jLabelResume.setText(strResume); + jLabelExit.setText(strExit); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listern all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + // + //Set isCancel true when click button "Exit" + // + Object obj = arg0.getSource(); + if (obj == jButtonResume) { + isCancel = false; + } + if (obj == jButtonExit) { + isCancel = true; + } + this.setVisible(false); + } + + /** + Make the window in the center of the screen + + **/ + private void centerWindow() { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - this.getSize().width) / 2, (d.height - this.getSize().height) / 2); + } + + public void windowActivated(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowClosed(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowClosing(WindowEvent arg0) { + isCancel = false; + this.setVisible(false); + } + + public void windowDeactivated(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowDeiconified(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowIconified(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowOpened(WindowEvent arg0) { + // TODO Auto-generated method stub + + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IComboBox.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IComboBox.java new file mode 100644 index 0000000000..f60ebcfe33 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IComboBox.java @@ -0,0 +1,196 @@ +/** @file + + The file is used to override JComboBox to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.common.ui; + +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; + +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JPanel; + +/** + The class is used to override JComboBox to provides customized interfaces + It extends JComboBox implements KeyListener, MouseListener and FocusListener + + @since ModuleEditor 1.0 + + **/ +public class IComboBox extends JComboBox implements KeyListener, MouseListener, FocusListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -1940262568168458911L; + + public void focusGained(FocusEvent arg0) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see java.awt.event.FocusListener#focusLost(java.awt.event.FocusEvent) + * + * Override focusLost to exit edit mode + * + */ + public void focusLost(FocusEvent arg0) { + this.closeEdit(); + } + + /** + Main class, used for test + + @param args + + **/ + public static void main(String[] args) { + JFrame jf = new JFrame(); + jf.setSize(500, 200); + JPanel jp = new JPanel(); + jp.setLayout(null); + IComboBox icb = new IComboBox(); + jp.add(icb, null); + jf.setContentPane(jp); + jf.setVisible(true); + } + + /** + This is the default constructor + + **/ + public IComboBox() { + super(); + init(); + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(320, 20); + this.setEditable(false); + this.editor.addActionListener(this); + this.addMouseListener(this); + this.addKeyListener(this); + this.getEditor().getEditorComponent().addKeyListener(this); + this.getEditor().getEditorComponent().addFocusListener(this); + } + + public void keyPressed(KeyEvent arg0) { + // TODO Auto-generated method stub + } + + /* (non-Javadoc) + * @see java.awt.event.KeyListener#keyReleased(java.awt.event.KeyEvent) + * + * Override keyReleased to listen key action + * + */ + public void keyReleased(KeyEvent arg0) { + // + //Add new item to list when press ENTER + // + if (arg0.getSource() == this.getEditor().getEditorComponent()) { + if (arg0.getKeyCode() == KeyEvent.VK_ENTER) { + String strCurrentText = this.getEditor().getItem().toString().trim(); + if (strCurrentText.length() == 0) { + if (this.getItemCount() > 0) { + this.setSelectedIndex(0); + } + } else { + this.addItem(strCurrentText); + this.setSelectedItem(strCurrentText); + } + this.setEditable(false); + } + if (arg0.getKeyCode() == KeyEvent.VK_ESCAPE) { + closeEdit(); + } + } + + if (arg0.getSource() == this) { + // + //Remove item from the list when press DEL + // + if (arg0.getKeyCode() == KeyEvent.VK_DELETE) { + int intSelected = this.getSelectedIndex(); + if (intSelected > -1) { + this.removeItemAt(this.getSelectedIndex()); + if (this.getItemCount() > 0) { + this.setSelectedIndex(0); + } else { + this.removeAllItems(); + } + } + } + } + } + + public void keyTyped(KeyEvent arg0) { + // TODO Auto-generated method stub + } + + /* (non-Javadoc) + * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) + * + * Override mouseClicked to enter edit mode when double click mouse + * + */ + public void mouseClicked(MouseEvent arg0) { + if (arg0.getClickCount() == 2) { + this.setEditable(true); + this.getEditor().setItem(""); + } + + } + + public void mouseEntered(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + public void mouseExited(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + public void mousePressed(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + public void mouseReleased(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + /** + Exit edit mode + + **/ + private void closeEdit() { + this.setEditable(false); + this.getEditor().setItem(""); + if (this.getItemCount() > 0) { + this.setSelectedIndex(0); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IDefaultMutableTreeNode.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IDefaultMutableTreeNode.java new file mode 100644 index 0000000000..ae51c5fa45 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IDefaultMutableTreeNode.java @@ -0,0 +1,307 @@ +/** @file + + + The file is used to override DefaultMutableTreeNode to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.common.ui; + +import javax.swing.tree.DefaultMutableTreeNode; + +/** + The class is used to override DefaultMutableTreeNode to provides customized interfaces + It extends DefaultMutableTreeNode + + @since ModuleEditor 1.0 + + **/ +public class IDefaultMutableTreeNode extends DefaultMutableTreeNode { + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -1947340717458069548L; + + // + //Static final definitions for all kinds of node + // + public static final int MSA_HEADER = 0; + + public static final int LIBRARYCLASSDEFINITIONS = 1; + + public static final int SOURCEFILES = 2; + + public static final int INCLUDES = 3; + + public static final int PROTOCOLS = 4; + + public static final int EVENTS = 5; + + public static final int HOBS = 6; + + public static final int PPIS = 7; + + public static final int VARIABLES = 8; + + public static final int BOOTMODES = 9; + + public static final int SYSTEMTABLES = 10; + + public static final int DATAHUBS = 11; + + public static final int FORMSETS = 12; + + public static final int GUIDS = 13; + + public static final int EXTERNS = 14; + + public static final int PCDS = 15; + + public static final int MBD_HEADER = 20; + + public static final int MLSA_HEADER = 21; + + public static final int MLBD_HEADER = 22; + + public static final int LIBRARIES = 23; + + public static final int LIBRARY_CLASS_DEFINITION = 101; + + public static final int SOURCEFILES_FILENAME = 210; + + public static final int SOURCEFILES_FILENAME_ITEM = 211; + + public static final int SOURCEFILES_ARCH = 220; + + public static final int SOURCEFILES_ARCH_ITEM = 221; + + public static final int INCLUDES_PACKAGENAME = 310; + + public static final int INCLUDES_PACKAGENAME_ITEM = 311; + + public static final int INCLUDES_ARCH = 320; + + public static final int INCLUDES_ARCH_ITEM = 321; + + public static final int PROTOCOLS_PROTOCOL = 410; + + public static final int PROTOCOLS_PROTOCOL_ITEM = 411; + + public static final int PROTOCOLS_PROTOCOLNOTIFY = 420; + + public static final int PROTOCOLS_PROTOCOLNOTIFY_ITEM = 421; + + public static final int EVENTS_CREATEEVENTS = 510; + + public static final int EVENTS_CREATEEVENTS_ITEM = 511; + + public static final int EVENTS_SIGNALEVENTS = 520; + + public static final int EVENTS_SIGNALEVENTS_ITEM = 521; + + public static final int HOBS_HOB_ITEM = 611; + + public static final int PPIS_PPI = 710; + + public static final int PPIS_PPI_ITEM = 711; + + public static final int PPIS_PPINOTIFY = 720; + + public static final int PPIS_PPINOTIFY_ITEM = 721; + + public static final int VARIABLES_VARIABLE_ITEM = 811; + + public static final int BOOTMODES_BOOTMODE_ITEM = 911; + + public static final int SYSTEMTABLES_SYSTEMTABLE_ITEM = 1011; + + public static final int DATAHUBS_DATAHUB_ITEM = 1111; + + public static final int FORMSETS_FORMSET_ITEM = 1211; + + public static final int GUIDS_GUIDENTRY_ITEM = 1311; + + public static final int EXTERNS_EXTERN_ITEM = 1411; + + public static final int PCDS_PCDDATA_ITEM = 1511; + + public static final int LIBRARIES_LIBRARY = 2310; + + public static final int LIBRARIES_LIBRARY_ITEM = 2311; + + public static final int LIBRARIES_ARCH = 2320; + + public static final int LIBRARIES_ARCH_ITEM = 2321; + + // + //Static final definitions for operation + // + public static final int OPERATION_NULL = 0; + + public static final int OPERATION_ADD = 1; + + public static final int OPERATION_UPDATE = 2; + + public static final int OPERATION_DELETE = 4; + + public static final int OPERATION_ADD_UPDATE = 3; + + public static final int OPERATION_ADD_DELETE = 5; + + public static final int OPERATION_UPDATE_DELETE = 6; + + public static final int OPERATION_ADD_UPDATE_DELETE = 7; + + // + //Define 4 node attributes + // + private int category = 0; + + private int operation = 0; + + private int location = 0; + + private String nodeName = ""; + + /** + Main class, reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + /** + This is the default constructor + + **/ + public IDefaultMutableTreeNode() { + super(); + } + + /** + This is the overrided constructor + Init clase members with input data + + @param strNodeName The name of node + @param intCategory The category of node + @param intOperation The operation of node + + **/ + public IDefaultMutableTreeNode(String strNodeName, int intCategory, int intOperation) { + super(strNodeName); + this.nodeName = strNodeName; + this.category = intCategory; + this.operation = intOperation; + } + + /** + This is the overrided constructor + Init clase members with input data + + @param strNodeName The name of node + @param intCategory The category of node + @param intOperation The operation of node + @param intLocation The location of node + + **/ + public IDefaultMutableTreeNode(String strNodeName, int intCategory, int intOperation, int intLocation) { + super(strNodeName); + this.nodeName = strNodeName; + this.category = intCategory; + this.operation = intOperation; + this.location = intLocation; + } + + /** + Get category of node + + @return The category of node + + **/ + public int getCategory() { + return category; + } + + /** + Set category of node + + @param category The input data of node category + + **/ + public void setCategory(int category) { + this.category = category; + } + + /** + Get name of node + + @return The name of node + + **/ + public String getNodeName() { + return nodeName; + } + + /** + Set name of node + + @param nodeName The input data of node name + + **/ + public void setNodeName(String nodeName) { + this.nodeName = nodeName; + } + + /** + Get operation of node + + @return The operation of node + + **/ + public int getOperation() { + return operation; + } + + /** + Set operation of node + + @param operation The input data of node operation + + **/ + public void setOperation(int operation) { + this.operation = operation; + } + + /** + Get location of node + + @return The location of node + + **/ + public int getLocation() { + return location; + } + + /** + Set location of node + + @param location The input data of node location + + **/ + public void setLocation(int location) { + this.location = location; + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IDesktopManager.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IDesktopManager.java new file mode 100644 index 0000000000..b86aa6b484 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IDesktopManager.java @@ -0,0 +1,76 @@ +/** @file + + The file is used to override DefaultDesktopManager to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.common.ui; + +import javax.swing.DefaultDesktopManager; +import javax.swing.JComponent; + +/** + The class is used to override DefaultDesktopManager to provides customized interfaces + It extends DefaultDesktopManager + + @since ModuleEditor 1.0 + + **/ +public class IDesktopManager extends DefaultDesktopManager { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -4596986878722011062L; + + /** + Main class, reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see javax.swing.DesktopManager#dragFrame(javax.swing.JComponent, int, int) + * + * Override dragFrame to do nothing to forbid internalframe to be draged + * + */ + public void dragFrame(JComponent f, int newX, int newY) { + + } + + /* (non-Javadoc) + * @see javax.swing.DesktopManager#endDraggingFrame(javax.swing.JComponent) + * + * Override endDraggingFrame to do nothing to forbid internalframe to be draged + * + */ + public void endDraggingFrame(JComponent f) { + + } + + /* (non-Javadoc) + * @see javax.swing.DesktopManager#beginResizingFrame(javax.swing.JComponent, int) + * + * Override beginResizingFrame to do nothing to forbid internalframe to be draged + * + */ + public void beginResizingFrame(JComponent f, int direction) { + + } + +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IDialog.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IDialog.java new file mode 100644 index 0000000000..622b54bcca --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IDialog.java @@ -0,0 +1,144 @@ +/** @file + + The file is used to override Dialog to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.common.ui; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JDialog; + +/** + The class is used to override Dialog to provides customized interfaces + It extends JDialog implements ActionListener + + @since ModuleEditor 1.0 + + **/ +public class IDialog extends JDialog implements ActionListener { + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -7692623863358631984L; + // + //Define class members + // + private boolean isEdited = false; + + public void actionPerformed(ActionEvent arg0) { + // TODO Auto-generated method stub + + } + + /** + Main class, used for test + + @param args + + **/ + public static void main(String[] args) { + IDialog id = new IDialog(); + id.setVisible(true); + } + + /** + This is the default constructor + **/ + public IDialog() { + super(); + initialize(); + } + + /** + * This is the override constructor + */ + /** + This is the override constructor + + @param parentFrame The parent frame which open the dialog + @param modal true means the dialog is modal dialog; false means the dialog is not modal dialog + **/ + public IDialog(IFrame parentFrame, boolean modal) { + super(parentFrame, modal); + initialize(); + } + + /** + This method initializes this + + **/ + private void initialize() { + this.setResizable(false); + } + + /** + Start the dialog at the center of screen + + @param intWidth The width of the dialog + @param intHeight The height of the dialog + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the dialog at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + Get if the dialog has been edited + + @retval true - The dialog has been edited + @retval false - The dialog hasn't been edited + + **/ + public boolean isEdited() { + return isEdited; + } + + /** + Set if the dialog has been edited + + @param isEdited The input data which identify if the dialog has been edited + + **/ + public void setEdited(boolean isEdited) { + this.isEdited = isEdited; + } + + /** + Check the input data is empty or not + + @param strValue The input data which need be checked + + @retval true - The input data is empty + @retval fals - The input data is not empty + + **/ + public boolean isEmpty(String strValue) { + if (strValue.length() > 0) { + return false; + } + return true; + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IFrame.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IFrame.java new file mode 100644 index 0000000000..4e36bd430a --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IFrame.java @@ -0,0 +1,204 @@ +/** @file + + The file is used to override Frame to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.common.ui; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowListener; + +import javax.swing.JFrame; + +/** + The class is used to override Frame to provides customized interfaces + It extends JFrame implements ActionListener and WindowListener + + @since ModuleEditor 1.0 + + **/ +public class IFrame extends JFrame implements ActionListener, WindowListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -3324138961029300427L; + + // + //Define class members + // + private ExitConfirm ec = null; + + // + // To indicate the status while quit + // 0 - When setup (Default) + // 1 - Whne editing module + // + private int intExitType = 0; + + /** + Main class, used for test + + @param args + + **/ + public static void main(String[] args) { + IFrame i = new IFrame(); + i.setVisible(true); + } + + /** + This is the default constructor + + **/ + public IFrame() { + super(); + initialize(); + } + + /** + This method initializes this + + **/ + public void initialize() { + this.setResizable(false); + this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + this.addWindowListener(this); + } + + /** + Start the dialog at the center of screen + + @param intWidth The width of the dialog + @param intHeight The height of the dialog + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the dialog at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + Set the exit window type + + @param ExitType The input data of ExitType + + **/ + protected void setExitType(int ExitType) { + this.intExitType = ExitType; + } + + /* (non-Javadoc) + * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent) + * + * Override windowClosing to call this.onDisvisible() + * + */ + public void windowClosing(WindowEvent arg0) { + this.onDisvisible(); + } + + public void windowOpened(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowClosed(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowIconified(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowDeiconified(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowActivated(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void windowDeactivated(WindowEvent arg0) { + // TODO Auto-generated method stub + + } + + public void actionPerformed(ActionEvent arg0) { + // TODO Auto-generated method stub + + } + + /** + Define the actions when exit + + **/ + public void onExit() { + ec = new ExitConfirm(this, true); + // + //Show different warning message via different ExitType + // + switch (intExitType) { + case 0: + ec.setSetupMessage(); + break; + case 1: + ec.setModuleMessage(); + break; + } + ec.setVisible(true); + if (ec.isCancel) { + this.dispose(); + System.exit(0); + } + } + + /** + Define the actions when disvisible + + **/ + public void onDisvisible() { + ec = new ExitConfirm(this, true); + // + //Show different warning message via different ExitType + // + switch (intExitType) { + case 0: + ec.setSetupMessage(); + break; + case 1: + ec.setModuleMessage(); + break; + } + ec.setVisible(true); + if (ec.isCancel) { + this.dispose(); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IInternalFrame.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IInternalFrame.java new file mode 100644 index 0000000000..8fc9d9b489 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/IInternalFrame.java @@ -0,0 +1,109 @@ +/** @file + + The file is used to override JInternalFrame to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.common.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JInternalFrame; + +/** + The class is used to override JInternalFrame to provides customized interfaces + It extends JInternalFrame implements ActionListener + + @since ModuleEditor 1.0 + + **/ +public class IInternalFrame extends JInternalFrame implements ActionListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -609841772384875886L; + // + //Define class members + // + private boolean isEdited = false; + + /** + Main class, reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + /** + This is the default constructor + + **/ + public IInternalFrame() { + super(); + initialize(); + } + + /** + This method initializes this + + **/ + private void initialize() { + this.setBounds(new java.awt.Rectangle(0, 0, 500, 500)); + } + + /** + Get if the InternalFrame has been edited + + @retval true - The InternalFrame has been edited + @retval false - The InternalFrame hasn't been edited + + **/ + public boolean isEdited() { + return isEdited; + } + + /** + Set if the InternalFrame has been edited + + @param isEdited The input data which identify if the InternalFrame has been edited + + **/ + public void setEdited(boolean isEdited) { + this.isEdited = isEdited; + } + + /** + Check the input data is empty or not + + @param strValue The input data which need be checked + + @retval true - The input data is empty + @retval fals - The input data is not empty + + **/ + public boolean isEmpty(String strValue) { + if (strValue.length() > 0) { + return false; + } + return true; + } + + public void actionPerformed(ActionEvent arg0) { + // TODO Auto-generated method stub + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/ITree.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/ITree.java new file mode 100644 index 0000000000..eeb51fce83 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/ITree.java @@ -0,0 +1,204 @@ +/** @file + + The file is used to override JTree to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.common.ui; + +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeNode; +import javax.swing.tree.TreePath; + +/** + The class is used to override JTree to provides customized interfaces + It extends JTree + + @since ModuleEditor 1.0 + + **/ +public class ITree extends JTree { + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -7907086164518295327L; + + // + // Define class members + // + DefaultTreeModel treeModel = null; + + /** + This is the default constructor + + **/ + public ITree() { + super(); + } + + /** + This is the overrided constructor + Init class members with input data + + @param iDmtRoot The root node of the tree + + **/ + public ITree(IDefaultMutableTreeNode iDmtRoot) { + super(iDmtRoot); + } + + /** + Get category of selected node + + @return The category of selected node + + **/ + public int getSelectCategory() { + int intCategory = 0; + TreePath path = this.getSelectionPath(); + IDefaultMutableTreeNode node = (IDefaultMutableTreeNode) path.getLastPathComponent(); + intCategory = node.getCategory(); + return intCategory; + } + + /** + Get operation of selected node + + @return The operation of selected node + + **/ + public int getSelectOperation() { + int intOperation = 0; + TreePath path = this.getSelectionPath(); + IDefaultMutableTreeNode node = (IDefaultMutableTreeNode) path.getLastPathComponent(); + intOperation = node.getOperation(); + return intOperation; + } + + /** + Get selectLoaction of selected node + + @return The selectLoaction of selected node + + **/ + public int getSelectLoaction() { + int intLocation = 0; + TreePath path = this.getSelectionPath(); + IDefaultMutableTreeNode node = (IDefaultMutableTreeNode) path.getLastPathComponent(); + intLocation = node.getLocation(); + return intLocation; + } + + /** + Main class, reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + } + + /** + Add input node as child node for current selected node + + @param strNewNode The name of the node which need be added + + **/ + public void addNode(String strNewNode) { + DefaultMutableTreeNode parentNode = null; + DefaultMutableTreeNode newNode = new DefaultMutableTreeNode(strNewNode); + newNode.setAllowsChildren(true); + TreePath parentPath = this.getSelectionPath(); + + /** + * Get parent node of new node + */ + parentNode = (DefaultMutableTreeNode) (parentPath.getLastPathComponent()); + + /** + * Insert new node + */ + treeModel.insertNodeInto(newNode, parentNode, parentNode.getChildCount()); + this.scrollPathToVisible(new TreePath(newNode.getPath())); + } + + /** + Add input node as child node for current selected node + + @param newNode The node need be added + + **/ + public void addNode(IDefaultMutableTreeNode newNode) { + IDefaultMutableTreeNode parentNode = null; + newNode.setAllowsChildren(true); + TreePath parentPath = this.getSelectionPath(); + parentNode = (IDefaultMutableTreeNode) (parentPath.getLastPathComponent()); + treeModel.insertNodeInto(newNode, parentNode, parentNode.getChildCount()); + this.scrollPathToVisible(new TreePath(newNode.getPath())); + } + + /** + Remove current selectd node + + **/ + public void removeNode() { + TreePath treepath = this.getSelectionPath(); + if (treepath != null) { + DefaultMutableTreeNode selectionNode = (DefaultMutableTreeNode) treepath.getLastPathComponent(); + TreeNode parent = (TreeNode) selectionNode.getParent(); + if (parent != null) { + treeModel.removeNodeFromParent(selectionNode); + } + } + } + + /** + Remove all node on a same level + + **/ + public void removeNodeOnSameLevel() { + TreePath treepath = this.getSelectionPath(); + IDefaultMutableTreeNode parentNode = (IDefaultMutableTreeNode) treepath.getLastPathComponent(); + parentNode.removeAllChildren(); + treeModel.reload(); + } + + /** + Remove the input node by name + + @param strRemovedNode + + **/ + public void removeNode(String strRemovedNode) { + TreePath treepath = this.getSelectionPath(); + if (treepath != null) { + DefaultMutableTreeNode selectionNode = (DefaultMutableTreeNode) treepath.getLastPathComponent(); + TreeNode parent = (TreeNode) selectionNode.getParent(); + if (parent != null) { + treeModel.removeNodeFromParent(selectionNode); + } + } + } + + /** + Remove all nodes of the tree + + **/ + public void removeAllNode() { + DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) treeModel.getRoot(); + rootNode.removeAllChildren(); + treeModel.reload(); + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/StarLabel.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/StarLabel.java new file mode 100644 index 0000000000..c451ac53b9 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/common/ui/StarLabel.java @@ -0,0 +1,64 @@ +/** @file + + The file is used to override JLabel to provides customized interfaces + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.common.ui; + +import javax.swing.JLabel; + +/** + The class is used to override JLabel to provides customized interfaces + + @since ModuleEditor 1.0 + + **/ +public class StarLabel extends JLabel { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -6702981027831543919L; + + /** + Main class, reserved for test + + @param args + + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + + } + + /** + This is the default constructor + + **/ + public StarLabel() { + super(); + init(); + } + + /** + To create a RED, BOLD and 14 size "*" + + **/ + private void init() { + this.setText("*"); + this.setSize(new java.awt.Dimension(10, 20)); + this.setForeground(java.awt.Color.red); + this.setFont(new java.awt.Font("DialogInput", java.awt.Font.BOLD, 14)); + this.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MbdHeader.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MbdHeader.java new file mode 100644 index 0000000000..9176407277 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MbdHeader.java @@ -0,0 +1,602 @@ +/** @file + + This file is used to create, update MbdHeader of a MBD file + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +import org.tianocore.BaseNameDocument; +import org.tianocore.GuidDocument; +import org.tianocore.LicenseDocument; +import org.tianocore.MbdHeaderDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + This class is used to create, update MbdHeader of a MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class MbdHeader extends IInternalFrame { + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -2015726615436197378L; + + // + // Define class members + // + private JPanel jContentPane = null; + + private JLabel jLabelBaseName = null; + + private JTextField jTextFieldBaseName = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelVersion = null; + + private JTextField jTextFieldVersion = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelLicense = null; + + private JTextArea jTextAreaLicense = null; + + private JLabel jLabelCopyright = null; + + private JTextArea jTextAreaCopyright = null; + + private JLabel jLabelDescription = null; + + private JTextArea jTextAreaDescription = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JScrollPane jScrollPaneLicense = null; + + private JScrollPane jScrollPaneCopyright = null; + + private JScrollPane jScrollPaneDescription = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + private StarLabel jStarLabel3 = null; + + private StarLabel jStarLabel4 = null; + + private StarLabel jStarLabel5 = null; + + private StarLabel jStarLabel6 = null; + + private MbdHeaderDocument.MbdHeader mbdHeader = null; + + /** + This method initializes jTextFieldBaseName + + @return javax.swing.JTextField jTextFieldBaseName + + **/ + private JTextField getJTextFieldBaseName() { + if (jTextFieldBaseName == null) { + jTextFieldBaseName = new JTextField(); + jTextFieldBaseName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldBaseName; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldVersion + + @return javax.swing.JTextField jTextFieldVersion + + **/ + private JTextField getJTextFieldVersion() { + if (jTextFieldVersion == null) { + jTextFieldVersion = new JTextField(); + jTextFieldVersion.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jTextFieldVersion; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextAreaLicense + + @return javax.swing.JTextArea jTextAreaLicense + + **/ + private JTextArea getJTextAreaLicense() { + if (jTextAreaLicense == null) { + jTextAreaLicense = new JTextArea(); + jTextAreaLicense.setText(""); + jTextAreaLicense.setLineWrap(true); + } + return jTextAreaLicense; + } + + /** + This method initializes jTextAreaCopyright + + @return javax.swing.JTextArea jTextAreaCopyright + + **/ + private JTextArea getJTextAreaCopyright() { + if (jTextAreaCopyright == null) { + jTextAreaCopyright = new JTextArea(); + jTextAreaCopyright.setLineWrap(true); + } + return jTextAreaCopyright; + } + + /** + This method initializes jTextAreaDescription + + @return javax.swing.JTextArea jTextAreaDescription + + **/ + private JTextArea getJTextAreaDescription() { + if (jTextAreaDescription == null) { + jTextAreaDescription = new JTextArea(); + jTextAreaDescription.setLineWrap(true); + } + return jTextAreaDescription; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 345, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 345, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jScrollPaneLicense + + @return javax.swing.JScrollPane jScrollPaneLicense + + **/ + private JScrollPane getJScrollPaneLicense() { + if (jScrollPaneLicense == null) { + jScrollPaneLicense = new JScrollPane(); + jScrollPaneLicense.setBounds(new java.awt.Rectangle(160, 85, 320, 80)); + jScrollPaneLicense.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneLicense.setViewportView(getJTextAreaLicense()); + } + return jScrollPaneLicense; + } + + /** + This method initializes jScrollPaneCopyright + + @return javax.swing.JScrollPane jScrollPaneCopyright + + **/ + private JScrollPane getJScrollPaneCopyright() { + if (jScrollPaneCopyright == null) { + jScrollPaneCopyright = new JScrollPane(); + jScrollPaneCopyright.setBounds(new java.awt.Rectangle(160, 170, 320, 80)); + jScrollPaneCopyright.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneCopyright.setViewportView(getJTextAreaCopyright()); + } + return jScrollPaneCopyright; + } + + /** + This method initializes jScrollPaneDescription + + @return javax.swing.JScrollPane jScrollPaneDescription + + **/ + private JScrollPane getJScrollPaneDescription() { + if (jScrollPaneDescription == null) { + jScrollPaneDescription = new JScrollPane(); + jScrollPaneDescription.setBounds(new java.awt.Rectangle(160, 255, 320, 80)); + jScrollPaneDescription.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneDescription.setViewportView(getJTextAreaDescription()); + } + return jScrollPaneDescription; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public MbdHeader() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + **/ + public MbdHeader(MbdHeaderDocument.MbdHeader inMbdHeader) { + super(); + init(inMbdHeader); + this.setVisible(true); + this.setViewMode(false); + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Module Build Description Header"); + initFrame(); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inMbdHeader The input MbdHeaderDocument.MbdHeader + + **/ + private void init(MbdHeaderDocument.MbdHeader inMbdHeader) { + init(); + setMbdHeader(inMbdHeader); + if (inMbdHeader != null) { + if (this.mbdHeader.getBaseName() != null) { + this.jTextFieldBaseName.setText(this.mbdHeader.getBaseName().getStringValue()); + } + if (this.mbdHeader.getGuid() != null) { + this.jTextFieldGuid.setText(this.mbdHeader.getGuid().getStringValue()); + } + if (this.mbdHeader.getVersion() != null) { + this.jTextFieldVersion.setText(this.mbdHeader.getVersion()); + } + if (this.mbdHeader.getLicense() != null) { + this.jTextAreaLicense.setText(this.mbdHeader.getLicense().getStringValue()); + } + if (this.mbdHeader.getCopyright() != null) { + this.jTextAreaCopyright.setText(this.mbdHeader.getCopyright()); + } + if (this.mbdHeader.getDescription() != null) { + this.jTextAreaDescription.setText(this.mbdHeader.getDescription()); + } + } + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldBaseName.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jTextFieldVersion.setEnabled(!isView); + this.jTextAreaLicense.setEnabled(!isView); + this.jTextAreaCopyright.setEnabled(!isView); + this.jTextAreaDescription.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelDescription = new JLabel(); + jLabelDescription.setText("Description"); + jLabelDescription.setBounds(new java.awt.Rectangle(15, 255, 140, 20)); + jLabelCopyright = new JLabel(); + jLabelCopyright.setText("Copyright"); + jLabelCopyright.setBounds(new java.awt.Rectangle(15, 170, 140, 20)); + jLabelLicense = new JLabel(); + jLabelLicense.setText("License"); + jLabelLicense.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelVersion = new JLabel(); + jLabelVersion.setText("Version"); + jLabelVersion.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setPreferredSize(new java.awt.Dimension(25, 15)); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelGuid.setText("Guid"); + jLabelBaseName = new JLabel(); + jLabelBaseName.setText("Base Name"); + jLabelBaseName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setLocation(new java.awt.Point(0, 0)); + jContentPane.setSize(new java.awt.Dimension(500, 524)); + jContentPane.add(jLabelBaseName, null); + jContentPane.add(getJTextFieldBaseName(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelVersion, null); + jContentPane.add(getJTextFieldVersion(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelLicense, null); + jContentPane.add(jLabelCopyright, null); + jContentPane.add(jLabelDescription, null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJScrollPaneLicense(), null); + jContentPane.add(getJScrollPaneCopyright(), null); + jContentPane.add(getJScrollPaneDescription(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setLocation(new java.awt.Point(0, 35)); + jStarLabel3 = new StarLabel(); + jStarLabel3.setLocation(new java.awt.Point(0, 60)); + jStarLabel4 = new StarLabel(); + jStarLabel4.setLocation(new java.awt.Point(0, 85)); + jStarLabel5 = new StarLabel(); + jStarLabel5.setLocation(new java.awt.Point(0, 170)); + jStarLabel6 = new StarLabel(); + jStarLabel6.setLocation(new java.awt.Point(0, 255)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + jContentPane.add(jStarLabel3, null); + jContentPane.add(jStarLabel4, null); + jContentPane.add(jStarLabel5, null); + jContentPane.add(jStarLabel6, null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.dispose(); + this.save(); + this.setEdited(true); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + this.setEdited(false); + } + // + // Generate GUID + // + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldBaseName.getText())) { + Log.err("Base Name couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldGuid.getText())) { + Log.err("Guid couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldVersion.getText())) { + Log.err("Version couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaLicense.getText())) { + Log.err("License couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaCopyright.getText())) { + Log.err("Copyright couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaDescription.getText())) { + Log.err("Description couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isBaseName(this.jTextFieldBaseName.getText())) { + Log.err("Incorrect data type for Base Name"); + return false; + } + if (!DataValidation.isGuid((this.jTextFieldGuid).getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!DataValidation.isCopyright(this.jTextAreaCopyright.getText())) { + Log.err("Incorrect data type for Copyright"); + return false; + } + return true; + } + + /** + Save all components of Mbd Header + if exists mbdHeader, set the value directly + if not exists mbdHeader, new an instance first + + **/ + public void save() { + try { + if (this.mbdHeader == null) { + mbdHeader = MbdHeaderDocument.MbdHeader.Factory.newInstance(); + } + if (this.mbdHeader.getBaseName() != null) { + this.mbdHeader.getBaseName().setStringValue(this.jTextFieldBaseName.getText()); + } else { + BaseNameDocument.BaseName mBaseName = BaseNameDocument.BaseName.Factory.newInstance(); + mBaseName.setStringValue(this.jTextFieldBaseName.getText()); + this.mbdHeader.setBaseName(mBaseName); + } + + if (this.mbdHeader.getGuid() != null) { + this.mbdHeader.getGuid().setStringValue(this.jTextFieldGuid.getText()); + } else { + GuidDocument.Guid mGuid = GuidDocument.Guid.Factory.newInstance(); + mGuid.setStringValue(this.jTextFieldGuid.getText()); + this.mbdHeader.setGuid(mGuid); + } + + this.mbdHeader.setVersion(this.jTextFieldVersion.getText()); + + if (this.mbdHeader.getLicense() != null) { + this.mbdHeader.getLicense().setStringValue(this.jTextAreaLicense.getText()); + } else { + LicenseDocument.License mLicense = LicenseDocument.License.Factory.newInstance(); + mLicense.setStringValue(this.jTextAreaLicense.getText()); + this.mbdHeader.setLicense(mLicense); + } + + this.mbdHeader.setCopyright(this.jTextAreaCopyright.getText()); + this.mbdHeader.setDescription(this.jTextAreaDescription.getText()); + + if (this.mbdHeader.getCreated() == null) { + this.mbdHeader.setCreated(Tools.getCurrentDateTime()); + } else { + this.mbdHeader.setModified(Tools.getCurrentDateTime()); + } + + } catch (Exception e) { + Log.err("Save Module Buid Description", e.getMessage()); + } + } + + /** + This method initializes module type and compontent type + + **/ + private void initFrame() { + + } + + /** + Get MbdHeaderDocument.MbdHeader + + @return MbdHeaderDocument.MbdHeader mbdHeader + + **/ + public MbdHeaderDocument.MbdHeader getMbdHeader() { + return mbdHeader; + } + + /** + Set MbdHeaderDocument.MbdHeader + + @param mbdHeader The input MbdHeaderDocument.MbdHeader + + **/ + public void setMbdHeader(MbdHeaderDocument.MbdHeader mbdHeader) { + this.mbdHeader = mbdHeader; + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MbdLibHeader.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MbdLibHeader.java new file mode 100644 index 0000000000..7f355c1e4d --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MbdLibHeader.java @@ -0,0 +1,599 @@ +/** @file + + The file is used to create, update MbdLibHeader of a MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +import org.tianocore.BaseNameDocument; +import org.tianocore.GuidDocument; +import org.tianocore.LicenseDocument; +import org.tianocore.MbdLibHeaderDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update MbdLibHeader of a MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class MbdLibHeader extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -4881447351274201866L; + + // + //Define class members + // + private JPanel jContentPane = null; + + private JLabel jLabelBaseName = null; + + private JTextField jTextFieldBaseName = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelVersion = null; + + private JTextField jTextFieldVersion = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelLicense = null; + + private JTextArea jTextAreaLicense = null; + + private JLabel jLabelCopyright = null; + + private JTextArea jTextAreaCopyright = null; + + private JLabel jLabelDescription = null; + + private JTextArea jTextAreaDescription = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JScrollPane jScrollPaneLicense = null; + + private JScrollPane jScrollPaneCopyright = null; + + private JScrollPane jScrollPaneDescription = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + private StarLabel jStarLabel3 = null; + + private StarLabel jStarLabel4 = null; + + private StarLabel jStarLabel5 = null; + + private StarLabel jStarLabel6 = null; + + private MbdLibHeaderDocument.MbdLibHeader mbdLibHeader = null; + + /** + This method initializes jTextFieldBaseName + + @return javax.swing.JTextField jTextFieldBaseName + + **/ + private JTextField getJTextFieldBaseName() { + if (jTextFieldBaseName == null) { + jTextFieldBaseName = new JTextField(); + jTextFieldBaseName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldBaseName; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldVersion + + @return javax.swing.JTextField jTextFieldVersion + + **/ + private JTextField getJTextFieldVersion() { + if (jTextFieldVersion == null) { + jTextFieldVersion = new JTextField(); + jTextFieldVersion.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jTextFieldVersion; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextAreaLicense + + @return javax.swing.JTextArea jTextAreaLicense + + **/ + private JTextArea getJTextAreaLicense() { + if (jTextAreaLicense == null) { + jTextAreaLicense = new JTextArea(); + jTextAreaLicense.setText(""); + jTextAreaLicense.setLineWrap(true); + } + return jTextAreaLicense; + } + + /** + This method initializes jTextAreaCopyright + + @return javax.swing.JTextArea jTextAreaCopyright + + **/ + private JTextArea getJTextAreaCopyright() { + if (jTextAreaCopyright == null) { + jTextAreaCopyright = new JTextArea(); + jTextAreaCopyright.setLineWrap(true); + } + return jTextAreaCopyright; + } + + /** + This method initializes jTextAreaDescription + + @return javax.swing.JTextArea jTextAreaDescription + + **/ + private JTextArea getJTextAreaDescription() { + if (jTextAreaDescription == null) { + jTextAreaDescription = new JTextArea(); + jTextAreaDescription.setLineWrap(true); + } + return jTextAreaDescription; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 345, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 345, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jScrollPaneLicense + + @return javax.swing.JScrollPane jScrollPaneLicense + + **/ + private JScrollPane getJScrollPaneLicense() { + if (jScrollPaneLicense == null) { + jScrollPaneLicense = new JScrollPane(); + jScrollPaneLicense.setBounds(new java.awt.Rectangle(160, 85, 320, 80)); + jScrollPaneLicense.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneLicense.setViewportView(getJTextAreaLicense()); + } + return jScrollPaneLicense; + } + + /** + This method initializes jScrollPaneCopyright + + @return javax.swing.JScrollPane jScrollPaneCopyright + + **/ + private JScrollPane getJScrollPaneCopyright() { + if (jScrollPaneCopyright == null) { + jScrollPaneCopyright = new JScrollPane(); + jScrollPaneCopyright.setBounds(new java.awt.Rectangle(160, 170, 320, 80)); + jScrollPaneCopyright.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneCopyright.setViewportView(getJTextAreaCopyright()); + } + return jScrollPaneCopyright; + } + + /** + This method initializes jScrollPaneDescription + + @return javax.swing.JScrollPane jScrollPaneDescription + + **/ + private JScrollPane getJScrollPaneDescription() { + if (jScrollPaneDescription == null) { + jScrollPaneDescription = new JScrollPane(); + jScrollPaneDescription.setBounds(new java.awt.Rectangle(160, 255, 320, 80)); + jScrollPaneDescription.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneDescription.setViewportView(getJTextAreaDescription()); + } + return jScrollPaneDescription; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public MbdLibHeader() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inMbdLibHeader The input MbdLibHeaderDocument.MbdLibHeader + + **/ + public MbdLibHeader(MbdLibHeaderDocument.MbdLibHeader inMbdLibHeader) { + super(); + init(inMbdLibHeader); + this.setVisible(true); + this.setViewMode(false); + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Library Module Build Description Header"); + initFrame(); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inMbdLibHeader The input MbdLibHeaderDocument.MbdLibHeader + + **/ + private void init(MbdLibHeaderDocument.MbdLibHeader inMbdLibHeader) { + init(); + setMbdLibHeader(inMbdLibHeader); + if (inMbdLibHeader != null) { + if (this.mbdLibHeader.getBaseName() != null) { + this.jTextFieldBaseName.setText(this.mbdLibHeader.getBaseName().getStringValue()); + } + if (this.mbdLibHeader.getGuid() != null) { + this.jTextFieldGuid.setText(this.mbdLibHeader.getGuid().getStringValue()); + } + if (this.mbdLibHeader.getVersion() != null) { + this.jTextFieldVersion.setText(this.mbdLibHeader.getVersion()); + } + if (this.mbdLibHeader.getLicense() != null) { + this.jTextAreaLicense.setText(this.mbdLibHeader.getLicense().getStringValue()); + } + if (this.mbdLibHeader.getCopyright() != null) { + this.jTextAreaCopyright.setText(this.mbdLibHeader.getCopyright()); + } + if (this.mbdLibHeader.getDescription() != null) { + this.jTextAreaDescription.setText(this.mbdLibHeader.getDescription()); + } + } + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldBaseName.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jTextFieldVersion.setEnabled(!isView); + this.jTextAreaLicense.setEnabled(!isView); + this.jTextAreaCopyright.setEnabled(!isView); + this.jTextAreaDescription.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelDescription = new JLabel(); + jLabelDescription.setText("Description"); + jLabelDescription.setBounds(new java.awt.Rectangle(15, 255, 140, 20)); + jLabelCopyright = new JLabel(); + jLabelCopyright.setText("Copyright"); + jLabelCopyright.setBounds(new java.awt.Rectangle(15, 170, 140, 20)); + jLabelLicense = new JLabel(); + jLabelLicense.setText("License"); + jLabelLicense.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelVersion = new JLabel(); + jLabelVersion.setText("Version"); + jLabelVersion.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setPreferredSize(new java.awt.Dimension(25, 15)); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelGuid.setText("Guid"); + jLabelBaseName = new JLabel(); + jLabelBaseName.setText("Base Name"); + jLabelBaseName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setLocation(new java.awt.Point(0, 0)); + jContentPane.setSize(new java.awt.Dimension(500, 524)); + jContentPane.add(jLabelBaseName, null); + jContentPane.add(getJTextFieldBaseName(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelVersion, null); + jContentPane.add(getJTextFieldVersion(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelLicense, null); + jContentPane.add(jLabelCopyright, null); + jContentPane.add(jLabelDescription, null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJScrollPaneLicense(), null); + jContentPane.add(getJScrollPaneCopyright(), null); + jContentPane.add(getJScrollPaneDescription(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setLocation(new java.awt.Point(0, 35)); + jStarLabel3 = new StarLabel(); + jStarLabel3.setLocation(new java.awt.Point(0, 60)); + jStarLabel4 = new StarLabel(); + jStarLabel4.setLocation(new java.awt.Point(0, 85)); + jStarLabel5 = new StarLabel(); + jStarLabel5.setLocation(new java.awt.Point(0, 170)); + jStarLabel6 = new StarLabel(); + jStarLabel6.setLocation(new java.awt.Point(0, 255)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + jContentPane.add(jStarLabel3, null); + jContentPane.add(jStarLabel4, null); + jContentPane.add(jStarLabel5, null); + jContentPane.add(jStarLabel6, null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.dispose(); + this.save(); + this.setEdited(true); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + this.setEdited(false); + } + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldBaseName.getText())) { + Log.err("Base Name couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldGuid.getText())) { + Log.err("Guid couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldVersion.getText())) { + Log.err("Version couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaLicense.getText())) { + Log.err("License couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaCopyright.getText())) { + Log.err("Copyright couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaDescription.getText())) { + Log.err("Description couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isBaseName(this.jTextFieldBaseName.getText())) { + Log.err("Incorrect data type for Base Name"); + return false; + } + if (!DataValidation.isGuid((this.jTextFieldGuid).getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!DataValidation.isCopyright(this.jTextAreaCopyright.getText())) { + Log.err("Incorrect data type for Copyright"); + return false; + } + return true; + } + + /** + Save all components of Mbd Lib Header + if exists mbdLibHeader, set the value directly + if not exists mbdLibHeader, new an instance first + + **/ + public void save() { + try { + if (this.mbdLibHeader == null) { + mbdLibHeader = MbdLibHeaderDocument.MbdLibHeader.Factory.newInstance(); + } + if (this.mbdLibHeader.getBaseName() != null) { + this.mbdLibHeader.getBaseName().setStringValue(this.jTextFieldBaseName.getText()); + } else { + BaseNameDocument.BaseName mBaseName = BaseNameDocument.BaseName.Factory.newInstance(); + mBaseName.setStringValue(this.jTextFieldBaseName.getText()); + this.mbdLibHeader.setBaseName(mBaseName); + } + + if (this.mbdLibHeader.getGuid() != null) { + this.mbdLibHeader.getGuid().setStringValue(this.jTextFieldGuid.getText()); + } else { + GuidDocument.Guid mGuid = GuidDocument.Guid.Factory.newInstance(); + mGuid.setStringValue(this.jTextFieldGuid.getText()); + this.mbdLibHeader.setGuid(mGuid); + } + + this.mbdLibHeader.setVersion(this.jTextFieldVersion.getText()); + + if (this.mbdLibHeader.getLicense() != null) { + this.mbdLibHeader.getLicense().setStringValue(this.jTextAreaLicense.getText()); + } else { + LicenseDocument.License mLicense = LicenseDocument.License.Factory.newInstance(); + mLicense.setStringValue(this.jTextAreaLicense.getText()); + this.mbdLibHeader.setLicense(mLicense); + } + + this.mbdLibHeader.setCopyright(this.jTextAreaCopyright.getText()); + this.mbdLibHeader.setDescription(this.jTextAreaDescription.getText()); + + if (this.mbdLibHeader.getCreated() == null) { + this.mbdLibHeader.setCreated(Tools.getCurrentDateTime()); + } else { + this.mbdLibHeader.setModified(Tools.getCurrentDateTime()); + } + } catch (Exception e) { + Log.err("Save Module Buid Description", e.getMessage()); + } + } + + /** + This method initializes module type and compontent type + + **/ + private void initFrame() { + } + + /** + Get MbdLibHeaderDocument.MbdLibHeader + + @return MbdLibHeaderDocument.MbdLibHeader + + **/ + public MbdLibHeaderDocument.MbdLibHeader getMbdLibHeader() { + return mbdLibHeader; + } + + /** + Set MbdLibHeaderDocument.MbdLibHeader + + @param mbdLibHeader The input MbdLibHeaderDocument.MbdLibHeader + + **/ + public void setMbdLibHeader(MbdLibHeaderDocument.MbdLibHeader mbdLibHeader) { + this.mbdLibHeader = mbdLibHeader; + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MbdLibraries.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MbdLibraries.java new file mode 100644 index 0000000000..ffbb3eb4ab --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MbdLibraries.java @@ -0,0 +1,1048 @@ +/** @file + + The file is used to create, update MbdLibraries of a MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Vector; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.tianocore.LibrariesDocument; +import org.tianocore.LibraryUsage; +import org.tianocore.SupportedArchitectures; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IDefaultMutableTreeNode; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update MbdLibraries of a MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class MbdLibraries extends IInternalFrame implements ItemListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = 8042998899875417568L; + + // + //Define class members + // + private LibrariesDocument.Libraries libraries = null; + + private int location = -1; + + private int intSelectedItemId = 0; + + // + //1 - Add; 2 - Update + // + private int operation = -1; + + private Vector vName = new Vector(); + + private Vector vGuid = new Vector(); + + private Vector vLibraryClass = new Vector(); + + private Vector vClassGuid = new Vector(); + + private Vector vVersion = new Vector(); + + private Vector vUsage = new Vector(); + + private Vector vOverrideID = new Vector(); + + private JPanel jContentPane = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelName = null; + + private JTextField jTextFieldFileName = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JButton jButtonGenerateGuid = null; + + private JComboBox jComboBoxArch = null; + + private JLabel jLabelLibraryClass = null; + + private JTextField jTextFieldLibraryClass = null; + + private JLabel jLabelUsage = null; + + private JLabel jLabelClassGuid = null; + + private JTextField jTextFieldClassGuid = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private JComboBox jComboBoxUsage = null; + + private StarLabel jStarLabel1 = null; + + private JComboBox jComboBoxFileList = null; + + private JButton jButtonAdd = null; + + private JButton jButtonRemove = null; + + private JButton jButtonUpdate = null; + + private JCheckBox jCheckBoxArch = null; + + private JButton jButtonGenerateGuid2 = null; + + private JLabel jLabelVersion = null; + + private JTextField jTextFieldVersion = null; + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButton() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 240, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + *This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 240, 90, 20)); + jButtonCancel.setPreferredSize(new java.awt.Dimension(90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jTextFieldFileName + + @return javax.swing.JTextField jTextFieldFileName + + **/ + private JTextField getJTextFieldSourceFilesDirectory() { + if (jTextFieldFileName == null) { + jTextFieldFileName = new JTextField(); + jTextFieldFileName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldFileName; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 35, 250, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(415, 35, 65, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jComboBoxArch + + @return javax.swing.JComboBox jComboBoxArch + + **/ + private JComboBox getJComboBoxArch() { + if (jComboBoxArch == null) { + jComboBoxArch = new JComboBox(); + jComboBoxArch.setBounds(new java.awt.Rectangle(140, 210, 340, 20)); + jComboBoxArch.setEnabled(false); + } + return jComboBoxArch; + } + + /** + This method initializes jTextFieldLibraryClass + + @return javax.swing.JTextField jTextFieldLibraryClass + + **/ + private JTextField getJTextFieldLibraryClass() { + if (jTextFieldLibraryClass == null) { + jTextFieldLibraryClass = new JTextField(); + jTextFieldLibraryClass.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jTextFieldLibraryClass; + } + + /** + This method initializes jTextFieldClassGuid + + @return javax.swing.JTextField jTextFieldClassGuid + + **/ + private JTextField getJTextFieldClassGuid() { + if (jTextFieldClassGuid == null) { + jTextFieldClassGuid = new JTextField(); + jTextFieldClassGuid.setBounds(new java.awt.Rectangle(160, 85, 250, 20)); + } + return jTextFieldClassGuid; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 160, 50, 20)); + } + return jTextFieldOverrideID; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 135, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jComboBoxFileList + + @return javax.swing.JComboBox jComboBoxFileList + + **/ + private JComboBox getJComboBoxFileList() { + if (jComboBoxFileList == null) { + jComboBoxFileList = new JComboBox(); + jComboBoxFileList.setBounds(new java.awt.Rectangle(15, 185, 210, 20)); + jComboBoxFileList.addItemListener(this); + jComboBoxFileList.addActionListener(this); + } + return jComboBoxFileList; + } + + /** + This method initializes jButtonAdd + + @return javax.swing.JButton jButtonAdd + + **/ + private JButton getJButtonAdd() { + if (jButtonAdd == null) { + jButtonAdd = new JButton(); + jButtonAdd.setBounds(new java.awt.Rectangle(230, 185, 80, 20)); + jButtonAdd.setText("Add"); + jButtonAdd.addActionListener(this); + } + return jButtonAdd; + } + + /** + This method initializes jButtonRemove + + @return javax.swing.JButton jButtonRemove + + **/ + private JButton getJButtonRemove() { + if (jButtonRemove == null) { + jButtonRemove = new JButton(); + jButtonRemove.setBounds(new java.awt.Rectangle(400, 185, 80, 20)); + jButtonRemove.setText("Remove"); + jButtonRemove.addActionListener(this); + } + return jButtonRemove; + } + + /** + This method initializes jButtonUpdate + + @return javax.swing.JButton jButtonUpdate + + **/ + private JButton getJButtonUpdate() { + if (jButtonUpdate == null) { + jButtonUpdate = new JButton(); + jButtonUpdate.setBounds(new java.awt.Rectangle(315, 185, 80, 20)); + jButtonUpdate.setText("Update"); + jButtonUpdate.addActionListener(this); + } + return jButtonUpdate; + } + + /** + This method initializes jCheckBoxArch + + @return javax.swing.JCheckBox jCheckBoxArch + + **/ + private JCheckBox getJCheckBoxArch() { + if (jCheckBoxArch == null) { + jCheckBoxArch = new JCheckBox(); + jCheckBoxArch.setBounds(new java.awt.Rectangle(10, 210, 119, 20)); + jCheckBoxArch.setText("Specific Arch"); + jCheckBoxArch.addActionListener(this); + } + return jCheckBoxArch; + } + + /** + This method initializes jButtonGenerateGuid2 + + @return javax.swing.JButton jButtonGenerateGuid2 + + **/ + private JButton getJButtonGenerateGuid2() { + if (jButtonGenerateGuid2 == null) { + jButtonGenerateGuid2 = new JButton(); + jButtonGenerateGuid2.setBounds(new java.awt.Rectangle(415, 85, 65, 20)); + jButtonGenerateGuid2.setText("GEN"); + jButtonGenerateGuid2.addActionListener(this); + } + return jButtonGenerateGuid2; + } + + /** + This method initializes jTextFieldVersion + + @return javax.swing.JTextField jTextFieldVersion + + **/ + private JTextField getJTextFieldVersion() { + if (jTextFieldVersion == null) { + jTextFieldVersion = new JTextField(); + jTextFieldVersion.setBounds(new java.awt.Rectangle(160, 110, 320, 20)); + } + return jTextFieldVersion; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public MbdLibraries() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inLibraries The input LibrariesDocument.Libraries + + **/ + public MbdLibraries(LibrariesDocument.Libraries inLibraries) { + super(); + init(inLibraries); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inLibraries The input LibrariesDocument.Libraries + @param type The input data of node type + @param index The input data of node index + + **/ + public MbdLibraries(LibrariesDocument.Libraries inLibraries, int type, int index) { + super(); + init(inLibraries); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inLibraries The input LibrariesDocument.Libraries + @param type The input data of node type + @param index The input data of node index + @param inOperation The input data of operation type + + **/ + public MbdLibraries(LibrariesDocument.Libraries inLibraries, int type, int index, int inOperation) { + super(); + init(inLibraries, type, index, inOperation); + this.operation = inOperation; + this.setVisible(true); + } + + /** + This method initializes this + + @param inLibraries LibrariesDocument.Libraries + + **/ + private void init(LibrariesDocument.Libraries inLibraries) { + init(); + this.setLibraries(inLibraries); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inLibraries LibrariesDocument.Libraries + @param type The input data of node type + @param index The input data of node index + @param inOperation The input data of operation type + + **/ + private void init(LibrariesDocument.Libraries inLibraries, int type, int index, int inOperation) { + init(inLibraries); + this.location = index; + this.operation = inOperation; + + if (operation == 2) { + this.jCheckBoxArch.setEnabled(false); + this.jComboBoxArch.setEnabled(false); + + if (type == IDefaultMutableTreeNode.LIBRARIES_LIBRARY) { + if (this.libraries.getLibraryList().size() > 0) { + for (int indexI = 0; indexI < this.libraries.getLibraryList().size(); indexI++) { + if (this.libraries.getLibraryArray(indexI).getStringValue() != null) { + vName.addElement(this.libraries.getLibraryArray(indexI).getStringValue()); + } else { + vName.addElement(""); + } + if (this.libraries.getLibraryArray(indexI).getGuid() != null) { + vGuid.addElement(this.libraries.getLibraryArray(indexI).getGuid()); + } else { + vGuid.addElement(""); + } + if (this.libraries.getLibraryArray(indexI).getLibraryClass() != null) { + vLibraryClass.addElement(this.libraries.getLibraryArray(indexI).getLibraryClass()); + } else { + vLibraryClass.addElement(""); + } + if (this.libraries.getLibraryArray(indexI).getClassGuid() != null) { + vClassGuid.addElement(this.libraries.getLibraryArray(indexI).getClassGuid()); + } else { + vClassGuid.addElement(""); + } + if (this.libraries.getLibraryArray(indexI).getVersion() != null) { + vVersion.addElement(this.libraries.getLibraryArray(indexI).getVersion()); + } else { + vVersion.addElement(""); + } + if (this.libraries.getLibraryArray(indexI).getUsage() != null) { + vUsage.addElement(this.libraries.getLibraryArray(indexI).getUsage().toString()); + } else { + vUsage.addElement("ALWAYS_CONSUMED"); + } + vOverrideID.addElement(String.valueOf(this.libraries.getLibraryArray(indexI).getOverrideID())); + jComboBoxFileList.addItem(this.libraries.getLibraryArray(indexI).getStringValue()); + } + } + } + if (type == IDefaultMutableTreeNode.LIBRARIES_ARCH_ITEM) { + this.jCheckBoxArch.setSelected(true); + this.jComboBoxArch.setSelectedItem(this.libraries.getArchArray(index).getArchType().toString()); + for (int indexI = 0; indexI < this.libraries.getArchArray(index).getLibraryList().size(); indexI++) { + if (this.libraries.getArchArray(index).getLibraryArray(indexI).getStringValue() != null) { + vName.addElement(this.libraries.getArchArray(index).getLibraryArray(indexI).getStringValue()); + } else { + vName.addElement(""); + } + if (this.libraries.getArchArray(index).getLibraryArray(indexI).getGuid() != null) { + vGuid.addElement(this.libraries.getArchArray(index).getLibraryArray(indexI).getGuid()); + } else { + vGuid.addElement(""); + } + if (this.libraries.getArchArray(index).getLibraryArray(indexI).getLibraryClass() != null) { + vLibraryClass.addElement(this.libraries.getArchArray(index).getLibraryArray(indexI) + .getLibraryClass()); + } else { + vLibraryClass.addElement(""); + } + if (this.libraries.getArchArray(index).getLibraryArray(indexI).getClassGuid() != null) { + vClassGuid + .addElement(this.libraries.getArchArray(index).getLibraryArray(indexI).getClassGuid()); + } else { + vClassGuid.addElement(""); + } + if (this.libraries.getArchArray(index).getLibraryArray(indexI).getVersion() != null) { + vVersion.addElement(this.libraries.getArchArray(index).getLibraryArray(indexI).getVersion()); + } else { + vVersion.addElement(""); + } + if (this.libraries.getArchArray(index).getLibraryArray(indexI).getUsage() != null) { + vUsage.addElement(this.libraries.getArchArray(index).getLibraryArray(indexI).getUsage() + .toString()); + } else { + vUsage.addElement(""); + } + vOverrideID.addElement(String.valueOf(this.libraries.getArchArray(index).getLibraryArray(indexI).getOverrideID())); + jComboBoxFileList.addItem(this.libraries.getArchArray(index).getLibraryArray(indexI) + .getStringValue()); + } + } + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setName("JFrame"); + this.setContentPane(getJContentPane()); + this.setTitle("Source Files"); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldFileName.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jComboBoxArch.setEnabled(!isView); + this.jTextFieldLibraryClass.setEnabled(!isView); + this.jTextFieldClassGuid.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jButtonAdd.setEnabled(!isView); + this.jButtonRemove.setEnabled(!isView); + this.jButtonUpdate.setEnabled(!isView); + this.jCheckBoxArch.setEnabled(!isView); + this.jTextFieldVersion.setEnabled(!isView); + + this.jButtonOk.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonGenerateGuid2.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelVersion = new JLabel(); + jLabelVersion.setBounds(new java.awt.Rectangle(15, 110, 140, 20)); + jLabelVersion.setText("Version"); + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 160, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelClassGuid = new JLabel(); + jLabelClassGuid.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelClassGuid.setText("Class Guid"); + jLabelUsage = new JLabel(); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 135, 140, 20)); + jLabelUsage.setText("Usage"); + jLabelLibraryClass = new JLabel(); + jLabelLibraryClass.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelLibraryClass.setText("Library Class"); + jLabelGuid = new JLabel(); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelGuid.setText("Guid"); + jLabelName = new JLabel(); + jLabelName.setText("Name"); + jLabelName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJButton(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(jLabelName, null); + jContentPane.add(getJTextFieldSourceFilesDirectory(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(getJComboBoxArch(), null); + jContentPane.add(jLabelLibraryClass, null); + jContentPane.add(getJTextFieldLibraryClass(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(jLabelClassGuid, null); + jContentPane.add(getJTextFieldClassGuid(), null); + jContentPane.add(getJButtonGenerateGuid2(), null); + jContentPane.add(jLabelVersion, null); + jContentPane.add(getJTextFieldVersion(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + jContentPane.add(getJComboBoxUsage(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(getJComboBoxFileList(), null); + jContentPane.add(getJButtonAdd(), null); + jContentPane.add(getJButtonRemove(), null); + jContentPane.add(getJButtonUpdate(), null); + jContentPane.add(getJCheckBoxArch(), null); + + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + if (arg0.getSource() == jButtonGenerateGuid2) { + jTextFieldClassGuid.setText(Tools.generateUuidString()); + } + if (arg0.getSource() == jButtonAdd) { + if (!checkAdd()) { + return; + } + addToList(); + } + if (arg0.getSource() == jButtonRemove) { + removeFromList(); + } + if (arg0.getSource() == jButtonUpdate) { + if (!checkAdd()) { + return; + } + updateForList(); + } + if (arg0.getSource() == jCheckBoxArch) { + if (this.jCheckBoxArch.isSelected()) { + this.jComboBoxArch.setEnabled(true); + } else { + this.jComboBoxArch.setEnabled(false); + } + } + } + + /** + Init the items of Usage and Arch + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("DEFAULT"); + jComboBoxUsage.addItem("PRIVATE"); + + jComboBoxArch.addItem("ALL"); + jComboBoxArch.addItem("EBC"); + jComboBoxArch.addItem("ARM"); + jComboBoxArch.addItem("IA32"); + jComboBoxArch.addItem("X64"); + jComboBoxArch.addItem("IPF"); + jComboBoxArch.addItem("PPC"); + } + + /** + Add current item to Vector + + **/ + private void addToList() { + intSelectedItemId = vName.size(); + vName.addElement(this.jTextFieldFileName.getText()); + vGuid.addElement(this.jTextFieldGuid.getText()); + vLibraryClass.addElement(this.jTextFieldLibraryClass.getText()); + vClassGuid.addElement(this.jTextFieldClassGuid.getText()); + vVersion.addElement(this.jTextFieldVersion.getText()); + vUsage.addElement(this.jComboBoxUsage.getSelectedItem().toString()); + vOverrideID.addElement(this.jTextFieldOverrideID.getText()); + jComboBoxFileList.addItem(this.jTextFieldFileName.getText()); + jComboBoxFileList.setSelectedItem(this.jTextFieldFileName.getText()); + + // + // Reset select item index + // + intSelectedItemId = vName.size(); + + // + // Reload all fields of selected item + // + reloadFromList(); + } + + /** + Remove current item from Vector + + **/ + private void removeFromList() { + int intTempIndex = intSelectedItemId; + if (vName.size() < 1) { + return; + } + + jComboBoxFileList.removeItemAt(intSelectedItemId); + + vName.removeElementAt(intTempIndex); + vGuid.removeElementAt(intTempIndex); + vLibraryClass.removeElementAt(intTempIndex); + vClassGuid.removeElementAt(intTempIndex); + vVersion.removeElementAt(intTempIndex); + vUsage.removeElementAt(intTempIndex); + vOverrideID.removeElementAt(intTempIndex); + + // + // Reload all fields of selected item + // + reloadFromList(); + } + + /** + Update current item of Vector + + **/ + private void updateForList() { + // + // Backup selected item index + // + int intTempIndex = intSelectedItemId; + vName.setElementAt(this.jTextFieldFileName.getText(), intSelectedItemId); + vGuid.setElementAt(this.jTextFieldGuid.getText(), intSelectedItemId); + vLibraryClass.setElementAt(this.jTextFieldLibraryClass.getText(), intSelectedItemId); + vClassGuid.setElementAt(this.jTextFieldClassGuid.getText(), intSelectedItemId); + vVersion.setElementAt(this.jTextFieldVersion.getText(), intSelectedItemId); + vUsage.setElementAt(this.jComboBoxUsage.getSelectedItem().toString(), intSelectedItemId); + vOverrideID.setElementAt(this.jTextFieldOverrideID.getText(), intSelectedItemId); + + jComboBoxFileList.removeAllItems(); + for (int index = 0; index < vName.size(); index++) { + jComboBoxFileList.addItem(vName.elementAt(index)); + } + + // + // Restore selected item index + // + intSelectedItemId = intTempIndex; + + // + // Reset select item index + // + jComboBoxFileList.setSelectedIndex(intSelectedItemId); + + // + // Reload all fields of selected item + // + reloadFromList(); + } + + /** + Refresh all fields' values of selected item of Vector + + **/ + private void reloadFromList() { + if (vName.size() > 0) { + // + // Get selected item index + // + intSelectedItemId = jComboBoxFileList.getSelectedIndex(); + + this.jTextFieldFileName.setText(vName.elementAt(intSelectedItemId).toString()); + this.jComboBoxUsage.setSelectedItem(vUsage.elementAt(intSelectedItemId).toString()); + this.jTextFieldGuid.setText(vGuid.elementAt(intSelectedItemId).toString()); + this.jTextFieldLibraryClass.setText(vLibraryClass.elementAt(intSelectedItemId).toString()); + this.jTextFieldClassGuid.setText(vClassGuid.elementAt(intSelectedItemId).toString()); + this.jTextFieldVersion.setText(vVersion.elementAt(intSelectedItemId).toString()); + this.jTextFieldOverrideID.setText(vOverrideID.elementAt(intSelectedItemId).toString()); + } else { + this.jTextFieldFileName.setText(""); + this.jComboBoxUsage.setSelectedIndex(0); + this.jTextFieldGuid.setText(""); + this.jTextFieldLibraryClass.setText(""); + this.jTextFieldClassGuid.setText(""); + this.jTextFieldVersion.setText(""); + this.jTextFieldOverrideID.setText(""); + } + } + + /* (non-Javadoc) + * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent) + * + * Reflesh the frame when selected item changed + */ + public void itemStateChanged(ItemEvent arg0) { + if (arg0.getStateChange() == ItemEvent.SELECTED) { + reloadFromList(); + } + } + + /** + Data validation for all fields before save + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + if (this.jComboBoxFileList.getItemCount() < 1) { + Log.err("Must have one Library at least!"); + return false; + } + return true; + } + + /** + Data validation for all fields before add current item to Vector + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean checkAdd() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldFileName.getText())) { + Log.err("File Name couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isBaseName(this.jTextFieldFileName.getText())) { + Log.err("Incorrect data type for Name"); + return false; + } + if (!isEmpty(this.jTextFieldGuid.getText()) && !DataValidation.isGuid(this.jTextFieldGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldLibraryClass.getText()) + && !DataValidation.isPath(this.jTextFieldLibraryClass.getText())) { + Log.err("Incorrect data type for Path"); + return false; + } + if (!isEmpty(this.jTextFieldClassGuid.getText()) && !DataValidation.isGuid(this.jTextFieldClassGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of Mbd Libraries + if exists libraries, set the value directly + if not exists libraries, new an instance first + + **/ + public void save() { + try { + if (this.libraries == null) { + libraries = LibrariesDocument.Libraries.Factory.newInstance(); + } + // + //Save as file name + // + if (!this.jCheckBoxArch.isSelected()) { + if (this.operation == 2) { //Add new filename + // + //First remove all existed filename + // + if (libraries.getLibraryList().size() > 0) { + for (int index = libraries.getLibraryList().size() - 1; index >= 0; index--) { + libraries.removeLibrary(index); + } + } + } + LibrariesDocument.Libraries.Library library = LibrariesDocument.Libraries.Library.Factory.newInstance(); + for (int index = 0; index < vName.size(); index++) { + if (!isEmpty(vName.elementAt(index).toString())) { + library.setStringValue(vName.elementAt(index).toString()); + } + if (!isEmpty(vGuid.elementAt(index).toString())) { + library.setGuid(vGuid.elementAt(index).toString()); + } + if (!isEmpty(vLibraryClass.elementAt(index).toString())) { + library.setLibraryClass(vLibraryClass.elementAt(index).toString()); + } + if (!isEmpty(vClassGuid.elementAt(index).toString())) { + library.setClassGuid(vClassGuid.elementAt(index).toString()); + } + if (!isEmpty(vVersion.elementAt(index).toString())) { + library.setVersion(vVersion.elementAt(index).toString()); + } + if (!isEmpty(vUsage.elementAt(index).toString())) { + library.setUsage(LibraryUsage.Enum.forString(vUsage.elementAt(index).toString())); + } + if (!isEmpty(vOverrideID.elementAt(index).toString())) { + library.setOverrideID(Integer.parseInt(vOverrideID.elementAt(index).toString())); + } + libraries.addNewLibrary(); + libraries.setLibraryArray(libraries.getLibraryList().size() - 1, library); + } + } + // + //Save as Arch + // + if (this.jCheckBoxArch.isSelected()) { + LibrariesDocument.Libraries.Arch arch = LibrariesDocument.Libraries.Arch.Factory.newInstance(); + if (this.operation == 2) { + //First remove all existed filename + for (int index = libraries.getArchArray(location).getLibraryList().size() - 1; index >= 0; index--) { + libraries.getArchArray(location).removeLibrary(index); + } + } + for (int index = 0; index < vName.size(); index++) { + LibrariesDocument.Libraries.Arch.Library library = LibrariesDocument.Libraries.Arch.Library.Factory.newInstance(); + if (!isEmpty(vName.elementAt(index).toString())) { + library.setStringValue(vName.elementAt(index).toString()); + } + if (!isEmpty(vGuid.elementAt(index).toString())) { + library.setGuid(vGuid.elementAt(index).toString()); + } + if (!isEmpty(vLibraryClass.elementAt(index).toString())) { + library.setLibraryClass(vLibraryClass.elementAt(index).toString()); + } + if (!isEmpty(vClassGuid.elementAt(index).toString())) { + library.setClassGuid(vClassGuid.elementAt(index).toString()); + } + if (!isEmpty(vVersion.elementAt(index).toString())) { + library.setVersion(vVersion.elementAt(index).toString()); + } + if (!isEmpty(vUsage.elementAt(index).toString())) { + library.setUsage(LibraryUsage.Enum.forString(vUsage.elementAt(index).toString())); + } + if (!isEmpty(vOverrideID.elementAt(index).toString())) { + library.setOverrideID(Integer.parseInt(vOverrideID.elementAt(index).toString())); + } + arch.addNewLibrary(); + arch.setLibraryArray(arch.getLibraryList().size() - 1, library); + } + arch + .setArchType(SupportedArchitectures.Enum.forString(this.jComboBoxArch.getSelectedItem().toString())); + if (location > -1) { + libraries.setArchArray(location, arch); + } else { + libraries.addNewArch(); + libraries.setArchArray(libraries.getArchList().size() - 1, arch); + } + } + } catch (Exception e) { + Log.err("Update Source Files", e.getMessage()); + } + } + + /** + Get LibrariesDocument.Libraries + + @return LibrariesDocument.Libraries + + **/ + public LibrariesDocument.Libraries getLibraries() { + return libraries; + } + + /** + Set LibrariesDocument.Libraries + + @param libraries The input LibrariesDocument.Libraries + + **/ + public void setLibraries(LibrariesDocument.Libraries libraries) { + this.libraries = libraries; + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleAbout.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleAbout.java new file mode 100644 index 0000000000..eb217f5f0a --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleAbout.java @@ -0,0 +1,146 @@ +/** @file + + To show a about window with copyright information + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.WindowEvent; + +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; + +import org.tianocore.packaging.common.ui.IDialog; + +/** + The class is used to show a about window with copyright information + It extends IDialog + + @since ModuleEditor 1.0 + + **/ +public class ModuleAbout extends IDialog { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = 2958136136667310962L; + + // + //Define class members + // + private JPanel jContentPane = null; + + private JLabel jLabel = null; + + private JLabel jLabel1 = null; + + private JLabel jLabel2 = null; + + private JButton jButtonOK = null; + + /** + This method initializes jButtonOK + + @return javax.swing.JButton jButtonOK + + **/ + private JButton getJButtonOK() { + if (jButtonOK == null) { + jButtonOK = new JButton(); + jButtonOK.setBounds(new java.awt.Rectangle(105, 120, 90, 20)); + jButtonOK.setText("OK"); + jButtonOK.addActionListener(this); + } + return jButtonOK; + } + + public static void main(String[] args) { + } + + /** + This is the default constructor + + **/ + public ModuleAbout() { + super(); + init(); + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(300, 200); + this.setContentPane(getJContentPane()); + this.setTitle("About..."); + this.getRootPane().setDefaultButton(jButtonOK); + this.centerWindow(); + this.setVisible(true); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabel2 = new JLabel(); + jLabel2.setBounds(new java.awt.Rectangle(15, 80, 270, 20)); + jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + jLabel2.setText("All rights reserved"); + jLabel1 = new JLabel(); + jLabel1.setBounds(new java.awt.Rectangle(15, 50, 270, 20)); + jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + jLabel1.setText("Copyright (c) 2006, Intel Corporation"); + jLabel = new JLabel(); + jLabel.setToolTipText(""); + jLabel.setBounds(new java.awt.Rectangle(15, 20, 270, 20)); + jLabel.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + jLabel.setText("Framework Development Package System 1.0"); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabel, null); + jContentPane.add(jLabel1, null); + jContentPane.add(jLabel2, null); + jContentPane.add(getJButtonOK(), null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOK) { + this.dispose(); + } + } + + /** + Dispose when windows is closing + + @param arg0 + + **/ + public void windowClosing(WindowEvent arg0) { + this.dispose(); + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleBootModes.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleBootModes.java new file mode 100644 index 0000000000..1acfa821e7 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleBootModes.java @@ -0,0 +1,456 @@ +/** @file + + The file is used to create, update BootModes of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.tianocore.BootModeNames; +import org.tianocore.BootModeUsage; +import org.tianocore.BootModesDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update BootModes of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleBootModes extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -3888558623432442561L; + + // + //Define class members + // + private BootModesDocument.BootModes bootModes = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelBootModeName = null; + + private JComboBox jComboBoxBootModeName = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private JButton jButtonGenerateGuid = null; + + private StarLabel jStarLabel1 = null; + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jComboBoxBootModeName + + @return javax.swing.JComboBox jComboBoxBootModeName + + **/ + private JComboBox getJComboBoxBootModeName() { + if (jComboBoxBootModeName == null) { + jComboBoxBootModeName = new JComboBox(); + jComboBoxBootModeName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jComboBoxBootModeName; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(280, 115, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 115, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 85, 320, 20)); + } + return jTextFieldOverrideID; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + public static void main(String[] args) { + } + + /** + This is the default constructor + + **/ + public ModuleBootModes() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inBootModes The input BootModesDocument.BootModes + + **/ + public ModuleBootModes(BootModesDocument.BootModes inBootModes) { + super(); + init(inBootModes); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inBootModes The input BootModesDocument.BootModes + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleBootModes(BootModesDocument.BootModes inBootModes, int type, int index) { + super(); + init(inBootModes, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inBootModes BootModesDocument.BootModes + + **/ + private void init(BootModesDocument.BootModes inBootModes) { + init(); + this.setBootModes(inBootModes); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inBootModes The input BootModesDocument.BootModes + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(BootModesDocument.BootModes inBootModes, int type, int index) { + init(inBootModes); + this.location = index; + if (this.bootModes.getBootModeList().size() > 0) { + if (this.bootModes.getBootModeArray(index).getBootModeName() != null) { + this.jComboBoxBootModeName.setSelectedItem(this.bootModes.getBootModeArray(index).getBootModeName() + .toString()); + } + if (this.bootModes.getBootModeArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.bootModes.getBootModeArray(index).getGuid()); + } + if (this.bootModes.getBootModeArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.bootModes.getBootModeArray(index).getUsage().toString()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.bootModes.getBootModeArray(index).getOverrideID())); + } + } + + /** + * This method initializes this + * + * @return void + */ + private void init() { + this.setContentPane(getJContentPane()); + this.setTitle("Boot Mode"); + this.setBounds(new java.awt.Rectangle(0, 0, 500, 515)); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jComboBoxBootModeName.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelBootModeName = new JLabel(); + jLabelBootModeName.setText("Boot Mode Name"); + jLabelBootModeName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setText("Guid"); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelBootModeName, null); + jContentPane.add(getJComboBoxBootModeName(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + + jContentPane.add(jStarLabel1, null); + } + return jContentPane; + } + + /** + This method initializes BootModeName groups and Usage type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + + jComboBoxBootModeName.addItem("FULL"); + jComboBoxBootModeName.addItem("MINIMAL"); + jComboBoxBootModeName.addItem("NO_CHANGE"); + jComboBoxBootModeName.addItem("DIAGNOSTICS"); + jComboBoxBootModeName.addItem("DEFAULT"); + jComboBoxBootModeName.addItem("S2_RESUME"); + jComboBoxBootModeName.addItem("S3_RESUME"); + jComboBoxBootModeName.addItem("S4_RESUME"); + jComboBoxBootModeName.addItem("S5_RESUME"); + jComboBoxBootModeName.addItem("FLASH_UPDATE"); + jComboBoxBootModeName.addItem("RECOVERY"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Get BootModesDocument.BootModes + + @return BootModesDocument.BootModes + + **/ + public BootModesDocument.BootModes getBootModes() { + return bootModes; + } + + /** + Set BootModesDocument.BootModes + + @param bootModes BootModesDocument.BootModes + + **/ + public void setBootModes(BootModesDocument.BootModes bootModes) { + this.bootModes = bootModes; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all fields have correct data types + // + if (!isEmpty(this.jTextFieldGuid.getText()) && !DataValidation.isGuid(this.jTextFieldGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of Mbd Header + if exists bootModes, set the value directly + if not exists bootModes, new an instance first + + **/ + public void save() { + try { + if (this.bootModes == null) { + bootModes = BootModesDocument.BootModes.Factory.newInstance(); + } + BootModesDocument.BootModes.BootMode bootMode = BootModesDocument.BootModes.BootMode.Factory.newInstance(); + bootMode.setBootModeName(BootModeNames.Enum.forString(jComboBoxBootModeName.getSelectedItem().toString())); + if (!isEmpty(this.jTextFieldGuid.getText())) { + bootMode.setGuid(this.jTextFieldGuid.getText()); + } + bootMode.setUsage(BootModeUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + bootMode.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + bootModes.setBootModeArray(location, bootMode); + } else { + bootModes.addNewBootMode(); + bootModes.setBootModeArray(bootModes.getBootModeList().size() - 1, bootMode); + } + } catch (Exception e) { + Log.err("Update Boot Modes", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleDataHubs.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleDataHubs.java new file mode 100644 index 0000000000..1d8e88c061 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleDataHubs.java @@ -0,0 +1,457 @@ +/** @file + + The file is used to create, update DataHub of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.tianocore.DataHubUsage; +import org.tianocore.DataHubsDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update DataHub of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleDataHubs extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -3667906991966638892L; + + // + //Define class members + // + private DataHubsDocument.DataHubs dataHubs = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelDataHubRecord = null; + + private JTextField jTextFieldDataHubRecord = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private StarLabel jStarLabel1 = null; + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(280, 115, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 115, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jTextFieldDataHubRecord + + @return javax.swing.JTextField jTextFieldDataHubRecord + + **/ + private JTextField getJTextFieldDataHubRecord() { + if (jTextFieldDataHubRecord == null) { + jTextFieldDataHubRecord = new JTextField(); + jTextFieldDataHubRecord.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldDataHubRecord; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 85, 320, 20)); + } + return jTextFieldOverrideID; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleDataHubs() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inDataHubs The input DataHubsDocument.DataHubs + + **/ + public ModuleDataHubs(DataHubsDocument.DataHubs inDataHubs) { + super(); + init(inDataHubs); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inDataHubs DataHubsDocument.DataHubs + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleDataHubs(DataHubsDocument.DataHubs inDataHubs, int type, int index) { + super(); + init(inDataHubs, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inDataHubs The input DataHubsDocument.DataHubs + + **/ + private void init(DataHubsDocument.DataHubs inDataHubs) { + init(); + this.setDataHubs(inDataHubs); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inDataHubs The input DataHubsDocument.DataHubs + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(DataHubsDocument.DataHubs inDataHubs, int type, int index) { + init(inDataHubs); + this.location = index; + if (this.dataHubs.getDataHubRecordList().size() > 0) { + if (this.dataHubs.getDataHubRecordArray(index).getStringValue() != null) { + this.jTextFieldDataHubRecord.setText(this.dataHubs.getDataHubRecordArray(index).getStringValue() + .toString()); + } + if (this.dataHubs.getDataHubRecordArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.dataHubs.getDataHubRecordArray(index).getGuid()); + } + if (this.dataHubs.getDataHubRecordArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.dataHubs.getDataHubRecordArray(index).getUsage().toString()); + } + this.jTextFieldOverrideID + .setText(String + .valueOf(this.dataHubs.getDataHubRecordArray(index).getOverrideID())); + } + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldDataHubRecord.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Data Hubs"); + initFrame(); + this.setViewMode(false); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelDataHubRecord = new JLabel(); + jLabelDataHubRecord.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jLabelDataHubRecord.setText("Data Hub Record"); + jLabelGuid = new JLabel(); + jLabelGuid.setText("Guid"); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(jLabelDataHubRecord, null); + jContentPane.add(getJTextFieldDataHubRecord(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + + jContentPane.add(jStarLabel1, null); + } + return jContentPane; + } + + /** + This method initializes Usage type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("PRIVATE"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Get DataHubsDocument.DataHubs + + @return DataHubsDocument.DataHubs + + **/ + public DataHubsDocument.DataHubs getDataHubs() { + return dataHubs; + } + + /** + Set DataHubsDocument.DataHubs + + @param dataHubs DataHubsDocument.DataHubs + + **/ + public void setDataHubs(DataHubsDocument.DataHubs dataHubs) { + this.dataHubs = dataHubs; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldDataHubRecord.getText())) { + Log.err("Data Hub Record couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!isEmpty(this.jTextFieldGuid.getText()) && !DataValidation.isGuid(this.jTextFieldGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of DataHubs + if exists dataHubs, set the value directly + if not exists dataHubs, new an instance first + + **/ + public void save() { + try { + if (this.dataHubs == null) { + dataHubs = DataHubsDocument.DataHubs.Factory.newInstance(); + } + DataHubsDocument.DataHubs.DataHubRecord dataHubRecord = DataHubsDocument.DataHubs.DataHubRecord.Factory + .newInstance(); + if (!isEmpty(this.jTextFieldDataHubRecord.getText())) { + dataHubRecord.setStringValue(this.jTextFieldDataHubRecord.getText()); + } + if (!isEmpty(this.jTextFieldGuid.getText())) { + dataHubRecord.setGuid(this.jTextFieldGuid.getText()); + } + dataHubRecord.setUsage(DataHubUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + dataHubRecord.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + dataHubs.setDataHubRecordArray(location, dataHubRecord); + } else { + dataHubs.addNewDataHubRecord(); + dataHubs.setDataHubRecordArray(dataHubs.getDataHubRecordList().size() - 1, dataHubRecord); + } + } catch (Exception e) { + Log.err("Update Data Hubs", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleEvents.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleEvents.java new file mode 100644 index 0000000000..abc3653d29 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleEvents.java @@ -0,0 +1,626 @@ +/** @file + + The file is used to create, update Event of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; + +import org.tianocore.EventTypes; +import org.tianocore.EventUsage; +import org.tianocore.EventsDocument; +import org.tianocore.GuidDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IDefaultMutableTreeNode; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update Event of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleEvents extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -4396143706422842331L; + + // + //Define class members + // + private EventsDocument.Events events = null; + + private EventsDocument.Events.CreateEvents createEvent = null; + + private EventsDocument.Events.SignalEvents signalEvent = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabelEventType = null; + + private JRadioButton jRadioButtonEventCreate = null; + + private JRadioButton jRadioButtonEventSignal = null; + + private JLabel jLabelC_Name = null; + + private JTextField jTextFieldC_Name = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelEventGroup = null; + + private JComboBox jComboBoxEventGroup = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + /** + This method initializes jRadioButtonEnentType + + @return javax.swing.JRadioButton jRadioButtonEventCreate + + **/ + private JRadioButton getJRadioButtonEventCreate() { + if (jRadioButtonEventCreate == null) { + jRadioButtonEventCreate = new JRadioButton(); + jRadioButtonEventCreate.setText("Create"); + jRadioButtonEventCreate.setBounds(new java.awt.Rectangle(160, 10, 90, 20)); + jRadioButtonEventCreate.addActionListener(this); + jRadioButtonEventCreate.setSelected(true); + } + return jRadioButtonEventCreate; + } + + /** + This method initializes jRadioButtonEventSignal + + @return javax.swing.JRadioButton jRadioButtonEventSignal + + **/ + private JRadioButton getJRadioButtonEventSignal() { + if (jRadioButtonEventSignal == null) { + jRadioButtonEventSignal = new JRadioButton(); + jRadioButtonEventSignal.setText("Signal"); + jRadioButtonEventSignal.setBounds(new java.awt.Rectangle(320, 10, 90, 20)); + jRadioButtonEventSignal.addActionListener(this); + } + return jRadioButtonEventSignal; + } + + /** + This method initializes jTextFieldC_Name + + @return javax.swing.JTextField jTextFieldC_Name + + **/ + private JTextField getJTextFieldC_Name() { + if (jTextFieldC_Name == null) { + jTextFieldC_Name = new JTextField(); + jTextFieldC_Name.setBounds(new java.awt.Rectangle(160, 35, 320, 20)); + } + return jTextFieldC_Name; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 60, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jComboBoxEventGroup + + @return javax.swing.JComboBox jComboBoxEventGroup + + **/ + private JComboBox getJComboBoxEventGroup() { + if (jComboBoxEventGroup == null) { + jComboBoxEventGroup = new JComboBox(); + jComboBoxEventGroup.setBounds(new java.awt.Rectangle(160, 85, 320, 20)); + } + return jComboBoxEventGroup; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 110, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButton() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 165, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 165, 90, 20)); + jButtonCancel.setPreferredSize(new Dimension(90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 60, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 135, 320, 20)); + } + return jTextFieldOverrideID; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleEvents() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inEvents The input EventsDocument.Events + + **/ + public ModuleEvents(EventsDocument.Events inEvents) { + super(); + init(inEvents); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inEvents The input EventsDocument.Events + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleEvents(EventsDocument.Events inEvents, int type, int index) { + super(); + init(inEvents, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inEvents The input EventsDocument.Events + + **/ + private void init(EventsDocument.Events inEvents) { + init(); + this.setEvents(inEvents); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inEvents EventsDocument.Events + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(EventsDocument.Events inEvents, int type, int index) { + init(inEvents); + this.location = index; + if (type == IDefaultMutableTreeNode.EVENTS_CREATEEVENTS_ITEM) { + this.jRadioButtonEventCreate.setSelected(true); + this.jRadioButtonEventSignal.setSelected(false); + if (this.events.getCreateEvents().getEventArray(index).getCName() != null) { + this.jTextFieldC_Name.setText(this.events.getCreateEvents().getEventArray(index).getCName()); + } + if (this.events.getCreateEvents().getEventArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.events.getCreateEvents().getEventArray(index).getGuid() + .getStringValue()); + } + if (this.events.getCreateEvents().getEventArray(index).getEventGroup() != null) { + this.jComboBoxEventGroup.setSelectedItem(this.events.getCreateEvents().getEventArray(index) + .getEventGroup().toString()); + } + if (this.events.getCreateEvents().getEventArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.events.getCreateEvents().getEventArray(index).getUsage() + .toString()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.events.getCreateEvents().getEventArray(index) + .getOverrideID())); + } else if (type == IDefaultMutableTreeNode.EVENTS_SIGNALEVENTS_ITEM) { + this.jRadioButtonEventCreate.setSelected(false); + this.jRadioButtonEventSignal.setSelected(true); + this.jComboBoxUsage.setEnabled(false); + if (this.events.getSignalEvents().getEventArray(index).getCName() != null) { + this.jTextFieldC_Name.setText(this.events.getSignalEvents().getEventArray(index).getCName()); + } + if (this.events.getSignalEvents().getEventArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.events.getSignalEvents().getEventArray(index).getGuid().toString()); + } + if (this.events.getSignalEvents().getEventArray(index).getEventGroup() != null) { + this.jComboBoxEventGroup.setSelectedItem(this.events.getSignalEvents().getEventArray(index) + .getEventGroup().toString()); + } + if (this.events.getSignalEvents().getEventArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.events.getSignalEvents().getEventArray(index).getUsage() + .toString()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.events.getSignalEvents().getEventArray(index) + .getOverrideID())); + } + this.jRadioButtonEventCreate.setEnabled(false); + this.jRadioButtonEventSignal.setEnabled(false); + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Events"); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jRadioButtonEventCreate.setEnabled(!isView); + this.jRadioButtonEventSignal.setEnabled(!isView); + this.jTextFieldC_Name.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jComboBoxEventGroup.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 135, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 110, 140, 20)); + jLabelEventGroup = new JLabel(); + jLabelEventGroup.setText("Event Group"); + jLabelEventGroup.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setText("Guid"); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelC_Name = new JLabel(); + jLabelC_Name.setText("C_Name"); + jLabelC_Name.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelEventType = new JLabel(); + jLabelEventType.setText("Event Type"); + jLabelEventType.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelEventType, null); + jContentPane.add(getJRadioButtonEventCreate(), null); + jContentPane.add(getJRadioButtonEventSignal(), null); + jContentPane.add(jLabelC_Name, null); + jContentPane.add(getJTextFieldC_Name(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelEventGroup, null); + jContentPane.add(getJComboBoxEventGroup(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJButton(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setBounds(new java.awt.Rectangle(0, 10, 10, 20)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setBounds(new java.awt.Rectangle(0, 35, 10, 20)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + } + return jContentPane; + } + + /** + This method initializes events groups and usage type + + **/ + private void initFrame() { + jComboBoxEventGroup.addItem("EVENT_GROUP_EXIT_BOOT_SERVICES"); + jComboBoxEventGroup.addItem("EVENT_GROUP_VIRTUAL_ADDRESS_CHANGE"); + jComboBoxEventGroup.addItem("EVENT_GROUP_MEMORY_MAP_CHANGE"); + jComboBoxEventGroup.addItem("EVENT_GROUP_READY_TO_BOOT"); + jComboBoxEventGroup.addItem("EVENT_GROUP_LEGACY_BOOT"); + + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("PRIVATE"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jRadioButtonEventCreate) { + if (jRadioButtonEventCreate.isSelected()) { + jRadioButtonEventSignal.setSelected(false); + } + if (!jRadioButtonEventSignal.isSelected() && !jRadioButtonEventCreate.isSelected()) { + jRadioButtonEventCreate.setSelected(true); + } + } + + if (arg0.getSource() == jRadioButtonEventSignal) { + if (jRadioButtonEventSignal.isSelected()) { + jRadioButtonEventCreate.setSelected(false); + } + if (!jRadioButtonEventSignal.isSelected() && !jRadioButtonEventCreate.isSelected()) { + jRadioButtonEventSignal.setSelected(true); + } + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + public EventsDocument.Events getEvents() { + return events; + } + + public void setEvents(EventsDocument.Events events) { + this.events = events; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldC_Name.getText())) { + Log.err("C_Name couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isCName(this.jTextFieldC_Name.getText())) { + Log.err("Incorrect data type for C_Name"); + return false; + } + if (!isEmpty(this.jTextFieldGuid.getText()) && !DataValidation.isGuid(this.jTextFieldGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of Events + if exists events, set the value directly + if not exists events, new an instance first + + **/ + public void save() { + try { + if (this.events == null) { + events = EventsDocument.Events.Factory.newInstance(); + createEvent = EventsDocument.Events.CreateEvents.Factory.newInstance(); + signalEvent = EventsDocument.Events.SignalEvents.Factory.newInstance(); + } else { + if (events.getCreateEvents() != null) { + createEvent = events.getCreateEvents(); + } else { + createEvent = EventsDocument.Events.CreateEvents.Factory.newInstance(); + } + if (events.getSignalEvents() != null) { + signalEvent = events.getSignalEvents(); + } else { + signalEvent = EventsDocument.Events.SignalEvents.Factory.newInstance(); + } + + } + if (this.jRadioButtonEventCreate.isSelected()) { + EventsDocument.Events.CreateEvents.Event event = EventsDocument.Events.CreateEvents.Event.Factory + .newInstance(); + event.setCName(this.jTextFieldC_Name.getText()); + if (!isEmpty(this.jTextFieldGuid.getText())) { + GuidDocument.Guid guid = GuidDocument.Guid.Factory.newInstance(); + guid.setStringValue(this.jTextFieldGuid.getText()); + event.setGuid(guid); + } + event.setEventGroup(EventTypes.Enum.forString(jComboBoxEventGroup.getSelectedItem().toString())); + event.setUsage(EventUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + event.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + createEvent.setEventArray(location, event); + } else { + createEvent.addNewEvent(); + createEvent.setEventArray(createEvent.getEventList().size() - 1, event); + } + events.setCreateEvents(createEvent); + } + if (this.jRadioButtonEventSignal.isSelected()) { + EventsDocument.Events.SignalEvents.Event event = EventsDocument.Events.SignalEvents.Event.Factory + .newInstance(); + event.setCName(this.jTextFieldC_Name.getText()); + if (!isEmpty(this.jTextFieldGuid.getText())) { + GuidDocument.Guid guid = GuidDocument.Guid.Factory.newInstance(); + guid.setStringValue(this.jTextFieldGuid.getText()); + event.setGuid(guid); + } + event.setEventGroup(EventTypes.Enum.forString(jComboBoxEventGroup.getSelectedItem().toString())); + event.setUsage(EventUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + event.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + signalEvent.setEventArray(location, event); + } else { + signalEvent.addNewEvent(); + signalEvent.setEventArray(signalEvent.getEventList().size() - 1, event); + } + events.setSignalEvents(signalEvent); + } + } catch (Exception e) { + Log.err("Update Events", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleExterns.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleExterns.java new file mode 100644 index 0000000000..ad466eb621 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleExterns.java @@ -0,0 +1,1030 @@ +/** @file + + The file is used to create, update DataHub of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.tianocore.ExternUsage; +import org.tianocore.ExternsDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.packaging.common.ui.IComboBox; +import org.tianocore.packaging.common.ui.IInternalFrame; + +/** + The class is used to create, update DataHub of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleExterns extends IInternalFrame implements ItemListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -7382008402932047191L; + + // + //Define class members + // + private ExternsDocument.Externs externs = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabelName = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private JPanel jPanelType1 = null; + + private JLabel jLabelModuleEntryPoint = null; + + private JLabel jLabelModuleUnloadImage = null; + + private IComboBox iComboBoxModuleEntryPoint = null; + + private IComboBox iComboBoxModuleUnloadImage = null; + + private JPanel jPanelType2 = null; + + private JLabel jLabelConstructor = null; + + private JTextField jTextFieldConstructor = null; + + private JLabel jLabelDestructor = null; + + private JTextField jTextFieldDestructor = null; + + private JComboBox jComboBoxType = null; + + private JPanel jPanelType3 = null; + + private JLabel jLabelDriverBinding = null; + + private JLabel jLabelComponentName = null; + + private IComboBox iComboBoxComponentName = null; + + private IComboBox iComboBoxDriverBinding = null; + + private JLabel jLabelDriverConfig = null; + + private JLabel jLabelDriverDiag = null; + + private IComboBox iComboBoxDriverDiag = null; + + private IComboBox iComboBoxDriverConfig = null; + + private JPanel jPanelType4 = null; + + private JLabel jLabelSetVirtualAddressMapCallBack = null; + + private IComboBox iComboBoxSetVirtualAddressMapCallBack = null; + + private JLabel jLabelExitBootServicesCallBack = null; + + private IComboBox iComboBoxExitBootServicesCallBack = null; + + private JPanel jPanelType5 = null; + + private JLabel jLabelUserDefined = null; + + private IComboBox iComboBoxUserDefined = null; + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 35, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setLocation(new java.awt.Point(290, 215)); + jButtonOk.setSize(new java.awt.Dimension(90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setLocation(new java.awt.Point(390, 215)); + jButtonCancel.setSize(new java.awt.Dimension(90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jTextFieldOverrideID; + } + + /** + This method initializes jPanelType1 + + @return javax.swing.JPanel jPanelType1 + + **/ + private JPanel getJPanelType1() { + if (jPanelType1 == null) { + jLabelModuleUnloadImage = new JLabel(); + jLabelModuleUnloadImage.setBounds(new java.awt.Rectangle(15, 30, 140, 20)); + jLabelModuleUnloadImage.setText("Module Unload Image"); + jLabelModuleEntryPoint = new JLabel(); + jLabelModuleEntryPoint.setBounds(new java.awt.Rectangle(15, 5, 140, 20)); + jLabelModuleEntryPoint.setText("Module Entry Point"); + jPanelType1 = new JPanel(); + jPanelType1.setLayout(null); + jPanelType1.setBounds(new java.awt.Rectangle(0, 105, 490, 55)); + jPanelType1.add(jLabelModuleEntryPoint, null); + jPanelType1.add(jLabelModuleUnloadImage, null); + jPanelType1.add(getIComboBoxModuleUnloadImage(), null); + jPanelType1.add(getIComboBoxModuleEntryPoint(), null); + } + return jPanelType1; + } + + /** + This method initializes jComboBoxModuleEntryPoint + + @return javax.swing.JComboBox iComboBoxModuleEntryPoint + + **/ + private IComboBox getIComboBoxModuleEntryPoint() { + if (iComboBoxModuleEntryPoint == null) { + iComboBoxModuleEntryPoint = new IComboBox(); + iComboBoxModuleEntryPoint.setBounds(new java.awt.Rectangle(160, 5, 320, 20)); + } + return iComboBoxModuleEntryPoint; + } + + /** + This method initializes jComboBoxModuleUnloadImage + + @return javax.swing.JComboBox iComboBoxModuleUnloadImage + + **/ + private IComboBox getIComboBoxModuleUnloadImage() { + if (iComboBoxModuleUnloadImage == null) { + iComboBoxModuleUnloadImage = new IComboBox(); + iComboBoxModuleUnloadImage.setBounds(new java.awt.Rectangle(160, 30, 320, 20)); + } + return iComboBoxModuleUnloadImage; + } + + /** + This method initializes jPanelType2 + + @return javax.swing.JPanel jPanelType2 + + **/ + private JPanel getJPanelType2() { + if (jPanelType2 == null) { + jLabelDestructor = new JLabel(); + jLabelDestructor.setBounds(new java.awt.Rectangle(15, 30, 140, 20)); + jLabelDestructor.setText("Destructor"); + jLabelConstructor = new JLabel(); + jLabelConstructor.setBounds(new java.awt.Rectangle(15, 5, 140, 20)); + jLabelConstructor.setText("Constructor"); + jPanelType2 = new JPanel(); + jPanelType2.setLayout(null); + jPanelType2.setBounds(new java.awt.Rectangle(0, 105, 490, 55)); + jPanelType2.add(jLabelConstructor, null); + jPanelType2.add(getJTextFieldConstructor(), null); + jPanelType2.add(jLabelDestructor, null); + jPanelType2.add(getJTextFieldDestructor(), null); + } + return jPanelType2; + } + + /** + This method initializes jTextFieldConstructor + + @return javax.swing.JTextField jTextFieldConstructor + + **/ + private JTextField getJTextFieldConstructor() { + if (jTextFieldConstructor == null) { + jTextFieldConstructor = new JTextField(); + jTextFieldConstructor.setBounds(new java.awt.Rectangle(160, 5, 320, 20)); + } + return jTextFieldConstructor; + } + + /** + This method initializes jTextFieldDestructor + + @return javax.swing.JTextField jTextFieldDestructor + + **/ + private JTextField getJTextFieldDestructor() { + if (jTextFieldDestructor == null) { + jTextFieldDestructor = new JTextField(); + jTextFieldDestructor.setBounds(new java.awt.Rectangle(160, 30, 320, 20)); + } + return jTextFieldDestructor; + } + + /** + This method initializes jComboBoxType + + @return javax.swing.JComboBox jComboBoxType + + **/ + private JComboBox getJComboBoxType() { + if (jComboBoxType == null) { + jComboBoxType = new JComboBox(); + jComboBoxType.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + jComboBoxType.addItemListener(this); + } + return jComboBoxType; + } + + /** + This method initializes jPanelType3 + + @return javax.swing.JPanel jPanelType3 + + **/ + private JPanel getJPanelType3() { + if (jPanelType3 == null) { + jLabelDriverDiag = new JLabel(); + jLabelDriverDiag.setBounds(new java.awt.Rectangle(15, 80, 140, 20)); + jLabelDriverDiag.setText("Driver Diag"); + jLabelDriverConfig = new JLabel(); + jLabelDriverConfig.setBounds(new java.awt.Rectangle(15, 55, 140, 20)); + jLabelDriverConfig.setText("Driver Config"); + jLabelComponentName = new JLabel(); + jLabelComponentName.setBounds(new java.awt.Rectangle(15, 30, 140, 20)); + jLabelComponentName.setText("Component Name"); + jLabelDriverBinding = new JLabel(); + jLabelDriverBinding.setBounds(new java.awt.Rectangle(15, 5, 140, 20)); + jLabelDriverBinding.setText("Driver Binding"); + jPanelType3 = new JPanel(); + jPanelType3.setLayout(null); + jPanelType3.setBounds(new java.awt.Rectangle(0, 105, 490, 105)); + jPanelType3.add(jLabelDriverBinding, null); + jPanelType3.add(jLabelComponentName, null); + jPanelType3.add(getIComboBoxComponentName(), null); + jPanelType3.add(getIComboBoxDriverBinding(), null); + jPanelType3.add(jLabelDriverConfig, null); + jPanelType3.add(jLabelDriverDiag, null); + jPanelType3.add(getIComboBoxDriverDiag(), null); + jPanelType3.add(getIComboBoxDriverConfig(), null); + } + return jPanelType3; + } + + /** + This method initializes jComboBoxComponentName + + @return javax.swing.JComboBox iComboBoxComponentName + + **/ + private IComboBox getIComboBoxComponentName() { + if (iComboBoxComponentName == null) { + iComboBoxComponentName = new IComboBox(); + iComboBoxComponentName.setBounds(new java.awt.Rectangle(160, 30, 320, 20)); + } + return iComboBoxComponentName; + } + + /** + This method initializes jComboBoxDriverBinding + + @return javax.swing.JComboBox iComboBoxDriverBinding + + **/ + private IComboBox getIComboBoxDriverBinding() { + if (iComboBoxDriverBinding == null) { + iComboBoxDriverBinding = new IComboBox(); + iComboBoxDriverBinding.setBounds(new java.awt.Rectangle(160, 5, 320, 20)); + } + return iComboBoxDriverBinding; + } + + /** + This method initializes jComboBoxDriverDiag + + @return javax.swing.JComboBox iComboBoxDriverDiag + + **/ + private IComboBox getIComboBoxDriverDiag() { + if (iComboBoxDriverDiag == null) { + iComboBoxDriverDiag = new IComboBox(); + iComboBoxDriverDiag.setBounds(new java.awt.Rectangle(160, 80, 320, 20)); + } + return iComboBoxDriverDiag; + } + + /** + This method initializes jComboBoxDriverConfig + + @return javax.swing.JComboBox iComboBoxDriverConfig + + */ + private IComboBox getIComboBoxDriverConfig() { + if (iComboBoxDriverConfig == null) { + iComboBoxDriverConfig = new IComboBox(); + iComboBoxDriverConfig.setBounds(new java.awt.Rectangle(160, 55, 320, 20)); + } + return iComboBoxDriverConfig; + } + + /** + This method initializes jPanelType4 + + @return javax.swing.JPanel jPanelType4 + + **/ + private JPanel getJPanelType4() { + if (jPanelType4 == null) { + jLabelExitBootServicesCallBack = new JLabel(); + jLabelExitBootServicesCallBack.setBounds(new java.awt.Rectangle(15, 30, 200, 20)); + jLabelExitBootServicesCallBack.setText("Exit Boot Services Call Back"); + jLabelSetVirtualAddressMapCallBack = new JLabel(); + jLabelSetVirtualAddressMapCallBack.setBounds(new java.awt.Rectangle(15, 5, 200, 20)); + jLabelSetVirtualAddressMapCallBack.setText("Set Virtual Address Map Call Back"); + jPanelType4 = new JPanel(); + jPanelType4.setLayout(null); + jPanelType4.setBounds(new java.awt.Rectangle(0, 105, 490, 55)); + jPanelType4.add(jLabelSetVirtualAddressMapCallBack, null); + jPanelType4.add(getIComboBoxSetVirtualAddressMapCallBack(), null); + jPanelType4.add(jLabelExitBootServicesCallBack, null); + jPanelType4.add(getIComboBoxExitBootServicesCallBack(), null); + } + return jPanelType4; + } + + /** + This method initializes jComboBoxSetVirtualAddressMapCallBack + + @return javax.swing.JComboBox iComboBoxSetVirtualAddressMapCallBack + + **/ + private IComboBox getIComboBoxSetVirtualAddressMapCallBack() { + if (iComboBoxSetVirtualAddressMapCallBack == null) { + iComboBoxSetVirtualAddressMapCallBack = new IComboBox(); + iComboBoxSetVirtualAddressMapCallBack.setBounds(new java.awt.Rectangle(220, 5, 260, 20)); + } + return iComboBoxSetVirtualAddressMapCallBack; + } + + /** + This method initializes jComboBoxExitBootServicesCallBack + + @return javax.swing.JComboBox iComboBoxExitBootServicesCallBack + + **/ + private IComboBox getIComboBoxExitBootServicesCallBack() { + if (iComboBoxExitBootServicesCallBack == null) { + iComboBoxExitBootServicesCallBack = new IComboBox(); + iComboBoxExitBootServicesCallBack.setBounds(new java.awt.Rectangle(220, 30, 260, 20)); + } + return iComboBoxExitBootServicesCallBack; + } + + /** + This method initializes jPanelType5 + + @return javax.swing.JPanel jPanelType5 + + **/ + private JPanel getJPanelType5() { + if (jPanelType5 == null) { + jLabelUserDefined = new JLabel(); + jLabelUserDefined.setBounds(new java.awt.Rectangle(15, 5, 140, 20)); + jLabelUserDefined.setText("User Defined"); + jPanelType5 = new JPanel(); + jPanelType5.setLayout(null); + jPanelType5.setBounds(new java.awt.Rectangle(0, 105, 490, 30)); + jPanelType5.add(jLabelUserDefined, null); + jPanelType5.add(getIComboBoxUserDefined(), null); + } + return jPanelType5; + } + + /** + This method initializes jComboBoxUserDefined + + @return javax.swing.JComboBox iComboBoxUserDefined + + **/ + private IComboBox getIComboBoxUserDefined() { + if (iComboBoxUserDefined == null) { + iComboBoxUserDefined = new IComboBox(); + iComboBoxUserDefined.setBounds(new java.awt.Rectangle(160, 5, 320, 20)); + } + return iComboBoxUserDefined; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleExterns() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inExterns The input data of ExternsDocument.Externs + + **/ + public ModuleExterns(ExternsDocument.Externs inExterns) { + super(); + init(inExterns); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inExterns The input data of ExternsDocument.Externs + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleExterns(ExternsDocument.Externs inExterns, int type, int index) { + super(); + init(inExterns, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inExterns The input data of ExternsDocument.Externs + + **/ + private void init(ExternsDocument.Externs inExterns) { + init(); + this.setExterns(inExterns); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inExterns The input data of ExternsDocument.Externs + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(ExternsDocument.Externs inExterns, int type, int index) { + init(inExterns); + this.location = index; + if (this.externs.getExternList().size() > 0) { + // + //Get common fields + // + if (this.externs.getExternArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.externs.getExternArray(index).getUsage().toString()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.externs.getExternArray(index).getOverrideID())); + // + //Type 1 + // + if (this.externs.getExternArray(index).getModuleEntryPointList().size() > 0) { + this.jComboBoxType.setSelectedIndex(0); + for (int indexI = 0; indexI < this.externs.getExternArray(index).getModuleEntryPointList().size(); indexI++) { + this.iComboBoxModuleEntryPoint.addItem(this.externs.getExternArray(index) + .getModuleEntryPointArray(indexI)); + } + } + if (this.externs.getExternArray(index).getModuleUnloadImageList().size() > 0) { + this.jComboBoxType.setSelectedIndex(0); + for (int indexI = 0; indexI < this.externs.getExternArray(index).getModuleUnloadImageList().size(); indexI++) { + this.iComboBoxModuleUnloadImage.addItem(this.externs.getExternArray(index) + .getModuleUnloadImageArray(indexI)); + } + } + + // + //Type 2 + // + if (this.externs.getExternArray(index).getConstructor() != null) { + this.jComboBoxType.setSelectedIndex(1); + this.jTextFieldConstructor.setText(this.externs.getExternArray(index).getConstructor()); + } + if (this.externs.getExternArray(index).getDestructor() != null) { + this.jComboBoxType.setSelectedIndex(1); + this.jTextFieldDestructor.setText(this.externs.getExternArray(index).getDestructor()); + } + + // + //Type 3 + // + if (this.externs.getExternArray(index).getDriverBindingList().size() > 0) { + this.jComboBoxType.setSelectedIndex(2); + for (int indexI = 0; indexI < this.externs.getExternArray(index).getDriverBindingList().size(); indexI++) { + this.iComboBoxDriverBinding.addItem(this.externs.getExternArray(index) + .getDriverBindingArray(indexI)); + } + } + if (this.externs.getExternArray(index).getComponentNameList().size() > 0) { + this.jComboBoxType.setSelectedIndex(2); + for (int indexI = 0; indexI < this.externs.getExternArray(index).getComponentNameList().size(); indexI++) { + this.iComboBoxComponentName.addItem(this.externs.getExternArray(index) + .getComponentNameArray(indexI)); + } + } + if (this.externs.getExternArray(index).getDriverConfigList().size() > 0) { + this.jComboBoxType.setSelectedIndex(2); + for (int indexI = 0; indexI < this.externs.getExternArray(index).getDriverConfigList().size(); indexI++) { + this.iComboBoxDriverConfig.addItem(this.externs.getExternArray(index).getDriverConfigArray(indexI)); + } + } + if (this.externs.getExternArray(index).getDriverDiagList().size() > 0) { + this.jComboBoxType.setSelectedIndex(2); + for (int indexI = 0; indexI < this.externs.getExternArray(index).getDriverDiagList().size(); indexI++) { + this.iComboBoxDriverDiag.addItem(this.externs.getExternArray(index).getDriverDiagArray(indexI)); + } + } + + // + //Type 4 + // + if (this.externs.getExternArray(index).getSetVirtualAddressMapCallBackList().size() > 0) { + this.jComboBoxType.setSelectedIndex(3); + for (int indexI = 0; indexI < this.externs.getExternArray(index).getSetVirtualAddressMapCallBackList() + .size(); indexI++) { + this.iComboBoxSetVirtualAddressMapCallBack + .addItem(this.externs + .getExternArray(index) + .getSetVirtualAddressMapCallBackArray( + indexI)); + } + } + if (this.externs.getExternArray(index).getExitBootServicesCallBackList().size() > 0) { + this.jComboBoxType.setSelectedIndex(3); + for (int indexI = 0; indexI < this.externs.getExternArray(index).getExitBootServicesCallBackList() + .size(); indexI++) { + this.iComboBoxExitBootServicesCallBack + .addItem(this.externs + .getExternArray(index) + .getExitBootServicesCallBackArray(indexI)); + } + } + + // + //Type 5 + // + if (this.externs.getExternArray(index).getUserDefinedList().size() > 0) { + this.jComboBoxType.setSelectedIndex(4); + for (int indexI = 0; indexI < this.externs.getExternArray(index).getUserDefinedList().size(); indexI++) { + this.iComboBoxUserDefined.addItem(this.externs.getExternArray(index).getUserDefinedArray(indexI)); + } + } + + this.jComboBoxType.setEnabled(false); + switchType(); + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Externs"); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jComboBoxUsage.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + // + //Type 1 + // + this.iComboBoxModuleEntryPoint.setEnabled(!isView); + this.iComboBoxModuleUnloadImage.setEnabled(!isView); + + // + //Type 2 + // + this.jTextFieldConstructor.setEnabled(!isView); + this.jTextFieldDestructor.setEnabled(!isView); + + // + //Type 3 + // + this.iComboBoxDriverBinding.setEnabled(!isView); + this.iComboBoxComponentName.setEnabled(!isView); + this.iComboBoxDriverConfig.setEnabled(!isView); + this.iComboBoxDriverDiag.setEnabled(!isView); + + // + //Type 4 + // + this.iComboBoxSetVirtualAddressMapCallBack.setEnabled(!isView); + this.iComboBoxExitBootServicesCallBack.setEnabled(!isView); + + // + //Type 5 + // + this.iComboBoxUserDefined.setEnabled(!isView); + + this.jComboBoxType.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelName = new JLabel(); + jLabelName.setText("Choose Type"); + jLabelName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setSize(new java.awt.Dimension(490, 244)); + jContentPane.add(getJPanelType2(), null); + jContentPane.add(jLabelName, null); + jContentPane.add(getJComboBoxType(), null); + jContentPane.add(getJPanelType3(), null); + jContentPane.add(getJPanelType4(), null); + jContentPane.add(getJPanelType5(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + + jContentPane.add(getJPanelType1(), null); + } + return jContentPane; + } + + /** + This method initializes Usage type and Externs type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + + jComboBoxType.addItem("Type 1"); + jComboBoxType.addItem("Type 2"); + jComboBoxType.addItem("Type 3"); + jComboBoxType.addItem("Type 4"); + jComboBoxType.addItem("Type 5"); + + jPanelType1.setVisible(true); + jPanelType2.setVisible(false); + jPanelType3.setVisible(false); + jPanelType4.setVisible(false); + jPanelType5.setVisible(false); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + } + + public void itemStateChanged(ItemEvent arg0) { + if (arg0.getSource() == jComboBoxType) { + if (arg0.getStateChange() == ItemEvent.SELECTED) { + switchType(); + } + } + } + + /** + Show/Hide relevant fields via select different types + + **/ + private void switchType() { + if (jComboBoxType.getSelectedIndex() == 0) { + jPanelType1.setVisible(true); + jPanelType2.setVisible(false); + jPanelType3.setVisible(false); + jPanelType4.setVisible(false); + jPanelType5.setVisible(false); + } + if (jComboBoxType.getSelectedIndex() == 1) { + jPanelType1.setVisible(false); + jPanelType2.setVisible(true); + jPanelType3.setVisible(false); + jPanelType4.setVisible(false); + jPanelType5.setVisible(false); + } + if (jComboBoxType.getSelectedIndex() == 2) { + jPanelType1.setVisible(false); + jPanelType2.setVisible(false); + jPanelType3.setVisible(true); + jPanelType4.setVisible(false); + jPanelType5.setVisible(false); + } + if (jComboBoxType.getSelectedIndex() == 3) { + jPanelType1.setVisible(false); + jPanelType2.setVisible(false); + jPanelType3.setVisible(false); + jPanelType4.setVisible(true); + jPanelType5.setVisible(false); + } + if (jComboBoxType.getSelectedIndex() == 4) { + jPanelType1.setVisible(false); + jPanelType2.setVisible(false); + jPanelType3.setVisible(false); + jPanelType4.setVisible(false); + jPanelType5.setVisible(true); + } + } + + /** + Set ExternsDocument.Externs + + @return ExternsDocument.Externs + + + **/ + public ExternsDocument.Externs getExterns() { + return externs; + } + + /** + Get ExternsDocument.Externs + + @param externs The input ExternsDocument.Externs + + **/ + public void setExterns(ExternsDocument.Externs externs) { + this.externs = externs; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all fields have correct data types + // + if (this.jComboBoxType.getSelectedIndex() == 1) { + if (!isEmpty(this.jTextFieldConstructor.getText()) + && !DataValidation.isConstructor(this.jTextFieldConstructor.getText())) { + Log.err("Incorrect data type for Constructor"); + return false; + } + if (!isEmpty(this.jTextFieldDestructor.getText()) + && !DataValidation.isDestructor(this.jTextFieldDestructor.getText())) { + Log.err("Incorrect data type for Destructor"); + return false; + } + } + + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of Externs + if exists externs, set the value directly + if not exists externs, new an instance first + + **/ + public void save() { + try { + if (this.externs == null) { + externs = ExternsDocument.Externs.Factory.newInstance(); + } + ExternsDocument.Externs.Extern extern = ExternsDocument.Externs.Extern.Factory.newInstance(); + // + //Save common fields + // + extern.setUsage(ExternUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + extern.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + + // + //Save type 1 + // + if (this.jComboBoxType.getSelectedIndex() == 0) { + if (this.iComboBoxModuleEntryPoint.getItemCount() > 0) { + for (int index = 0; index < this.iComboBoxModuleEntryPoint.getItemCount(); index++) { + extern.addNewModuleEntryPoint(); + extern.setModuleEntryPointArray(index, this.iComboBoxModuleEntryPoint.getItemAt(index) + .toString()); + } + } + if (this.iComboBoxModuleEntryPoint.getItemCount() > 0) { + for (int index = 0; index < this.iComboBoxModuleUnloadImage.getItemCount(); index++) { + extern.addNewModuleUnloadImage(); + extern.setModuleUnloadImageArray(index, this.iComboBoxModuleUnloadImage.getItemAt(index) + .toString()); + } + } + } + + // + //Save type 2 + // + if (this.jComboBoxType.getSelectedIndex() == 1) { + if (!isEmpty(this.jTextFieldConstructor.getText())) { + extern.setConstructor(this.jTextFieldConstructor.getText()); + } + if (!isEmpty(this.jTextFieldDestructor.getText())) { + extern.setDestructor(this.jTextFieldDestructor.getText()); + } + } + + // + //Save type 3 + // + if (this.jComboBoxType.getSelectedIndex() == 2) { + if (this.iComboBoxDriverBinding.getItemCount() > 0) { + for (int index = 0; index < this.iComboBoxDriverBinding.getItemCount(); index++) { + extern.addNewDriverBinding(); + extern.setDriverBindingArray(index, this.iComboBoxDriverBinding.getItemAt(index).toString()); + } + } + if (this.iComboBoxComponentName.getItemCount() > 0) { + for (int index = 0; index < this.iComboBoxComponentName.getItemCount(); index++) { + extern.addNewComponentName(); + extern.setComponentNameArray(index, this.iComboBoxComponentName.getItemAt(index).toString()); + } + } + if (this.iComboBoxDriverConfig.getItemCount() > 0) { + for (int index = 0; index < this.iComboBoxDriverConfig.getItemCount(); index++) { + extern.addNewDriverConfig(); + extern.setDriverConfigArray(index, this.iComboBoxDriverConfig.getItemAt(index).toString()); + } + } + if (this.iComboBoxDriverDiag.getItemCount() > 0) { + for (int index = 0; index < this.iComboBoxDriverDiag.getItemCount(); index++) { + extern.addNewDriverDiag(); + extern.setDriverDiagArray(index, this.iComboBoxDriverDiag.getItemAt(index).toString()); + } + } + } + + // + //Save type 4 + // + if (this.jComboBoxType.getSelectedIndex() == 3) { + if (this.iComboBoxSetVirtualAddressMapCallBack.getItemCount() > 0) { + for (int index = 0; index < this.iComboBoxSetVirtualAddressMapCallBack.getItemCount(); index++) { + extern.addNewSetVirtualAddressMapCallBack(); + extern + .setSetVirtualAddressMapCallBackArray( + index, + this.iComboBoxSetVirtualAddressMapCallBack + .getItemAt( + index) + .toString()); + } + } + if (this.iComboBoxExitBootServicesCallBack.getItemCount() > 0) { + for (int index = 0; index < this.iComboBoxExitBootServicesCallBack.getItemCount(); index++) { + extern.addNewExitBootServicesCallBack(); + extern.setExitBootServicesCallBackArray(index, + this.iComboBoxExitBootServicesCallBack.getItemAt(index) + .toString()); + } + } + } + // + //Save type 5 + // + if (this.jComboBoxType.getSelectedIndex() == 4) { + if (this.iComboBoxUserDefined.getItemCount() > 0) { + for (int index = 0; index < this.iComboBoxUserDefined.getItemCount(); index++) { + extern.addNewUserDefined(); + extern.setUserDefinedArray(index, this.iComboBoxUserDefined.getItemAt(index).toString()); + } + } + } + + if (location > -1) { + externs.setExternArray(location, extern); + } else { + externs.addNewExtern(); + externs.setExternArray(externs.getExternList().size() - 1, extern); + } + } catch (Exception e) { + Log.err("Update Externs", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleFormsets.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleFormsets.java new file mode 100644 index 0000000000..f725379ca8 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleFormsets.java @@ -0,0 +1,457 @@ +/** @file + + The file is used to create, update Formset of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.tianocore.FormSetUsage; +import org.tianocore.FormsetsDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update Formset of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleFormsets extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -6851574146786158116L; + + // + //Define class members + // + private FormsetsDocument.Formsets formsets = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabelName = null; + + private JTextField jTextFieldName = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelUsage = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JComboBox jComboBoxUsage = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private StarLabel jStarLabel1 = null; + + /** + This method initializes jTextFieldName + + @return javax.swing.JTextField jTextFieldName + + **/ + private JTextField getJTextFieldName() { + if (jTextFieldName == null) { + jTextFieldName = new JTextField(); + jTextFieldName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldName; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(280, 115, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 115, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 85, 320, 20)); + } + return jTextFieldOverrideID; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleFormsets() { + super(); + init(); + this.setVisible(true); + } + + /** + * + */ + /** + This is the override edit constructor + + @param inFormsets The input data of FormsetsDocument.Formsets + + **/ + public ModuleFormsets(FormsetsDocument.Formsets inFormsets) { + super(); + init(inFormsets); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inFormsets The input data of FormsetsDocument.Formsets + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleFormsets(FormsetsDocument.Formsets inFormsets, int type, int index) { + super(); + init(inFormsets, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inFormsets The input data of FormsetsDocument.Formsets + + **/ + private void init(FormsetsDocument.Formsets inFormsets) { + init(); + this.setFormsets(inFormsets); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inFormsets The input data of FormsetsDocument.Formsets + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(FormsetsDocument.Formsets inFormsets, int type, int index) { + init(inFormsets); + this.location = index; + if (this.formsets.getFormsetList().size() > 0) { + if (this.formsets.getFormsetArray(index).getStringValue() != null) { + this.jTextFieldName.setText(this.formsets.getFormsetArray(index).getStringValue().toString()); + } + if (this.formsets.getFormsetArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.formsets.getFormsetArray(index).getGuid()); + } + if (this.formsets.getFormsetArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.formsets.getFormsetArray(index).getUsage().toString()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.formsets.getFormsetArray(index).getOverrideID())); + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setContentPane(getJContentPane()); + this.setTitle("Form Sets"); + this.setBounds(new java.awt.Rectangle(0, 0, 500, 515)); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldName.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setText("Guid"); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelName = new JLabel(); + jLabelName.setText("Name"); + jLabelName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelName, null); + jContentPane.add(getJTextFieldName(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + + jContentPane.add(jStarLabel1, null); + } + return jContentPane; + } + + /** + This method initializes Usage type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("PRIVATE"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Set FormsetsDocument.Formsets + + @return FormsetsDocument.Formsets + + **/ + public FormsetsDocument.Formsets getFormsets() { + return formsets; + } + + /** + Get FormsetsDocument.Formsets + + @param formsets The input FormsetsDocument.Formsets + + **/ + public void setFormsets(FormsetsDocument.Formsets formsets) { + this.formsets = formsets; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldName.getText())) { + Log.err("Name couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isCName(this.jTextFieldName.getText())) { + Log.err("Incorrect data type for Name"); + return false; + } + if (!isEmpty(this.jTextFieldGuid.getText()) && !DataValidation.isGuid(this.jTextFieldGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of Formsets + if exists formset, set the value directly + if not exists formset, new an instance first + + **/ + public void save() { + try { + if (this.formsets == null) { + formsets = FormsetsDocument.Formsets.Factory.newInstance(); + } + FormsetsDocument.Formsets.Formset formset = FormsetsDocument.Formsets.Formset.Factory.newInstance(); + if (!isEmpty(this.jTextFieldName.getText())) { + formset.setStringValue(this.jTextFieldName.getText()); + } + if (!isEmpty(this.jTextFieldGuid.getText())) { + formset.setGuid(this.jTextFieldGuid.getText()); + } + formset.setUsage(FormSetUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + formset.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + formsets.setFormsetArray(location, formset); + } else { + formsets.addNewFormset(); + formsets.setFormsetArray(formsets.getFormsetList().size() - 1, formset); + } + } catch (Exception e) { + Log.err("Update Formsets", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleGuids.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleGuids.java new file mode 100644 index 0000000000..186709644f --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleGuids.java @@ -0,0 +1,675 @@ +/** @file + + The file is used to create, update Guids of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; + +import org.tianocore.ConditionalExpressionDocument; +import org.tianocore.DefaultValueDocument; +import org.tianocore.GuidUsage; +import org.tianocore.GuidsDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IComboBox; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update Guids of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleGuids extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = 6710858997766979803L; + + // + //Define class members + // + private GuidsDocument.Guids guids = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabelC_Name = null; + + private JTextField jTextFieldC_Name = null; + + private JLabel jLabelGuidValue = null; + + private JTextField jTextFieldGuidValue = null; + + private JLabel jLabelFeatureFlag = null; + + private IComboBox iComboBoxFeatureFlag = null; + + private JLabel jLabelConditionalExpression = null; + + private IComboBox iComboBoxConditionalExpression = null; + + private JLabel jLabelDefault = null; + + private JTextField jTextFieldDefaultValue = null; + + private JLabel jLabelHelpText = null; + + private JTextField jTextFieldHelpText = null; + + private JLabel jLabelEnableFeature = null; + + private JRadioButton jRadioButtonEnableFeature = null; + + private JRadioButton jRadioButtonDisableFeature = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + /** + This method initializes jTextFieldC_Name + + @return javax.swing.JTextField jTextFieldC_Name + + **/ + private JTextField getJTextFieldC_Name() { + if (jTextFieldC_Name == null) { + jTextFieldC_Name = new JTextField(); + jTextFieldC_Name.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldC_Name; + } + + /** + This method initializes jTextFieldGuidValsue + + @return javax.swing.JTextField jTextFieldGuidValue + + **/ + private JTextField getJTextFieldGuidValsue() { + if (jTextFieldGuidValue == null) { + jTextFieldGuidValue = new JTextField(); + jTextFieldGuidValue.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuidValue; + } + + /** + This method initializes jTextFieldFeatureFlag + + @return javax.swing.JTextField iComboBoxFeatureFlag + + **/ + private IComboBox getIComboBoxFeatureFlag() { + if (iComboBoxFeatureFlag == null) { + iComboBoxFeatureFlag = new IComboBox(); + iComboBoxFeatureFlag.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return iComboBoxFeatureFlag; + } + + /** + This method initializes jTextFieldConditionalExpression + + @return javax.swing.JTextField iComboBoxConditionalExpression + + **/ + private IComboBox getIComboBoxConditionalExpression() { + if (iComboBoxConditionalExpression == null) { + iComboBoxConditionalExpression = new IComboBox(); + iComboBoxConditionalExpression.setBounds(new java.awt.Rectangle(160, 85, 320, 20)); + } + return iComboBoxConditionalExpression; + } + + /** + This method initializes jTextFieldDefault + + @return javax.swing.JTextField jTextFieldDefaultValue + + **/ + private JTextField getJTextFieldDefaultValue() { + if (jTextFieldDefaultValue == null) { + jTextFieldDefaultValue = new JTextField(); + jTextFieldDefaultValue.setBounds(new java.awt.Rectangle(160, 110, 320, 20)); + } + return jTextFieldDefaultValue; + } + + /** + This method initializes jTextFieldHelpText + + @return javax.swing.JTextField jTextFieldHelpText + + **/ + private JTextField getJTextFieldHelpText() { + if (jTextFieldHelpText == null) { + jTextFieldHelpText = new JTextField(); + jTextFieldHelpText.setBounds(new java.awt.Rectangle(160, 135, 320, 20)); + } + return jTextFieldHelpText; + } + + /** + This method initializes jRadioButtonEnableFeature + + @return javax.swing.JRadioButton jRadioButtonEnableFeature + + **/ + private JRadioButton getJRadioButtonEnableFeature() { + if (jRadioButtonEnableFeature == null) { + jRadioButtonEnableFeature = new JRadioButton(); + jRadioButtonEnableFeature.setText("Enable"); + jRadioButtonEnableFeature.setBounds(new java.awt.Rectangle(160, 160, 90, 20)); + jRadioButtonEnableFeature.setSelected(true); + jRadioButtonEnableFeature.addActionListener(this); + } + return jRadioButtonEnableFeature; + } + + /** + This method initializes jRadioButtonDisableFeature + + @return javax.swing.JRadioButton jRadioButtonDisableFeature + + **/ + private JRadioButton getJRadioButtonDisableFeature() { + if (jRadioButtonDisableFeature == null) { + jRadioButtonDisableFeature = new JRadioButton(); + jRadioButtonDisableFeature.setText("Disable"); + jRadioButtonDisableFeature.setBounds(new java.awt.Rectangle(320, 160, 90, 20)); + jRadioButtonDisableFeature.addActionListener(this); + } + return jRadioButtonDisableFeature; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 185, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 240, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 240, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 210, 320, 20)); + } + return jTextFieldOverrideID; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleGuids() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inGuids The input data of GuidsDocument.Guids + + **/ + public ModuleGuids(GuidsDocument.Guids inGuids) { + super(); + init(inGuids); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inGuids The input data of GuidsDocument.Guids + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleGuids(GuidsDocument.Guids inGuids, int type, int index) { + super(); + init(inGuids, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inGuids The input data of GuidsDocument.Guids + + **/ + private void init(GuidsDocument.Guids inGuids) { + init(); + this.setGuids(inGuids); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inGuids The input data of GuidsDocument.Guids + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(GuidsDocument.Guids inGuids, int type, int index) { + init(inGuids); + this.location = index; + if (this.guids.getGuidEntryList().size() > 0) { + if (this.guids.getGuidEntryArray(index).getCName() != null) { + this.jTextFieldC_Name.setText(this.guids.getGuidEntryArray(index).getCName()); + } + if (this.guids.getGuidEntryArray(index).getGuidValue() != null) { + this.jTextFieldGuidValue.setText(this.guids.getGuidEntryArray(index).getGuidValue()); + } + if (this.guids.getGuidEntryArray(index).getFeatureFlagList().size() > 0) { + for (int indexI = 0; indexI < this.guids.getGuidEntryArray(index).getFeatureFlagList().size(); indexI++) { + this.iComboBoxFeatureFlag.addItem(this.guids.getGuidEntryArray(index).getFeatureFlagArray(indexI)); + } + } + if (this.guids.getGuidEntryArray(index).getConditionalExpressionList().size() > 0) { + for (int indexI = 0; indexI < this.guids.getGuidEntryArray(index).getConditionalExpressionArray(0) + .getConditionList().size(); indexI++) { + this.iComboBoxConditionalExpression.addItem(this.guids.getGuidEntryArray(index) + .getConditionalExpressionArray(0) + .getConditionArray(indexI)); + } + } + if (this.guids.getGuidEntryArray(index).getDefaultValue() != null) { + this.jTextFieldDefaultValue.setText(this.guids.getGuidEntryArray(index).getDefaultValue() + .getStringValue()); + } + if (this.guids.getGuidEntryArray(index).getHelpText() != null) { + this.jTextFieldHelpText.setText(this.guids.getGuidEntryArray(index).getHelpText()); + } + if (this.guids.getGuidEntryArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.guids.getGuidEntryArray(index).getUsage().toString()); + } + this.jRadioButtonEnableFeature.setSelected(this.guids.getGuidEntryArray(index).getEnableFeature()); + this.jRadioButtonDisableFeature.setSelected(!this.guids.getGuidEntryArray(index).getEnableFeature()); + this.jTextFieldOverrideID.setText(String.valueOf(this.guids.getGuidEntryArray(index).getOverrideID())); + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Guids"); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldC_Name.setEnabled(!isView); + this.jTextFieldGuidValue.setEnabled(!isView); + this.iComboBoxFeatureFlag.setEnabled(!isView); + this.iComboBoxConditionalExpression.setEnabled(!isView); + this.jTextFieldDefaultValue.setEnabled(!isView); + this.jTextFieldHelpText.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jRadioButtonEnableFeature.setEnabled(!isView); + this.jRadioButtonDisableFeature.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 210, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 185, 140, 20)); + jLabelEnableFeature = new JLabel(); + jLabelEnableFeature.setText("Enable Feature"); + jLabelEnableFeature.setBounds(new java.awt.Rectangle(15, 160, 140, 20)); + jLabelHelpText = new JLabel(); + jLabelHelpText.setText("Help Text"); + jLabelHelpText.setBounds(new java.awt.Rectangle(15, 135, 140, 20)); + jLabelDefault = new JLabel(); + jLabelDefault.setText("Default Value"); + jLabelDefault.setBounds(new java.awt.Rectangle(15, 110, 140, 20)); + jLabelConditionalExpression = new JLabel(); + jLabelConditionalExpression.setText("Conditional Expression"); + jLabelConditionalExpression.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelFeatureFlag = new JLabel(); + jLabelFeatureFlag.setText("Feature Flag"); + jLabelFeatureFlag.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelGuidValue = new JLabel(); + jLabelGuidValue.setText("Guid Value"); + jLabelGuidValue.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelC_Name = new JLabel(); + jLabelC_Name.setText("C_Name"); + jLabelC_Name.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelC_Name, null); + jContentPane.add(getJTextFieldC_Name(), null); + jContentPane.add(jLabelGuidValue, null); + jContentPane.add(getJTextFieldGuidValsue(), null); + jContentPane.add(jLabelFeatureFlag, null); + jContentPane.add(getIComboBoxFeatureFlag(), null); + jContentPane.add(jLabelConditionalExpression, null); + jContentPane.add(getIComboBoxConditionalExpression(), null); + jContentPane.add(jLabelDefault, null); + jContentPane.add(getJTextFieldDefaultValue(), null); + jContentPane.add(jLabelHelpText, null); + jContentPane.add(getJTextFieldHelpText(), null); + jContentPane.add(jLabelEnableFeature, null); + jContentPane.add(getJRadioButtonEnableFeature(), null); + jContentPane.add(getJRadioButtonDisableFeature(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + + StarLabel jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + + jContentPane.add(jStarLabel1, null); + + initFrame(); + + } + return jContentPane; + } + + /** + This method initializes Usage type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("DEFAULT"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuidValue.setText(Tools.generateUuidString()); + } + + // + //Contorl the selected status when click RadionButton + //Do not use Radio Button Group + // + if (arg0.getSource() == jRadioButtonEnableFeature) { + if (jRadioButtonEnableFeature.isSelected()) { + jRadioButtonDisableFeature.setSelected(false); + } + if (!jRadioButtonDisableFeature.isSelected() && !jRadioButtonEnableFeature.isSelected()) { + jRadioButtonEnableFeature.setSelected(true); + } + } + + if (arg0.getSource() == jRadioButtonDisableFeature) { + if (jRadioButtonDisableFeature.isSelected()) { + jRadioButtonEnableFeature.setSelected(false); + } + if (!jRadioButtonDisableFeature.isSelected() && !jRadioButtonEnableFeature.isSelected()) { + jRadioButtonDisableFeature.setSelected(true); + } + } + } + + /** + Get GuidsDocument.Guids + + @return GuidsDocument.Guids + + **/ + public GuidsDocument.Guids getGuids() { + return guids; + } + + /** + Set GuidsDocument.Guids + + @param guids The input GuidsDocument.Guids + + **/ + public void setGuids(GuidsDocument.Guids guids) { + this.guids = guids; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldC_Name.getText())) { + Log.err("C_Name couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isCName(this.jTextFieldC_Name.getText())) { + Log.err("Incorrect data type for C_Name"); + return false; + } + if (!isEmpty(this.jTextFieldGuidValue.getText()) && !DataValidation.isGuid(this.jTextFieldGuidValue.getText())) { + Log.err("Incorrect data type for Guid Value"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of Guids + if exists guids, set the value directly + if not exists guids, new an instance first + + **/ + public void save() { + try { + if (this.guids == null) { + guids = GuidsDocument.Guids.Factory.newInstance(); + } + GuidsDocument.Guids.GuidEntry guid = GuidsDocument.Guids.GuidEntry.Factory.newInstance(); + if (!isEmpty(this.jTextFieldC_Name.getText())) { + guid.setCName(this.jTextFieldC_Name.getText()); + } + if (!isEmpty(this.jTextFieldGuidValue.getText())) { + guid.setGuidValue(this.jTextFieldGuidValue.getText()); + } + if (this.iComboBoxFeatureFlag.getItemCount() > 0) { + for (int index = 0; index < this.iComboBoxFeatureFlag.getItemCount(); index++) { + guid.addNewFeatureFlag(); + guid.setFeatureFlagArray(index, this.iComboBoxFeatureFlag.getItemAt(index).toString()); + } + } + if (this.iComboBoxConditionalExpression.getItemCount() > 0) { + ConditionalExpressionDocument.ConditionalExpression ce = ConditionalExpressionDocument.ConditionalExpression.Factory + .newInstance(); + for (int index = 0; index < this.iComboBoxConditionalExpression.getItemCount(); index++) { + ce.addCondition(this.iComboBoxConditionalExpression.getItemAt(index).toString()); + } + if (guid.getConditionalExpressionList().size() < 1) { + guid.addNewConditionalExpression(); + } + guid.setConditionalExpressionArray(0, ce); + } + if (!isEmpty(this.jTextFieldDefaultValue.getText())) { + DefaultValueDocument.DefaultValue dv = DefaultValueDocument.DefaultValue.Factory.newInstance(); + dv.setStringValue(this.jTextFieldDefaultValue.getText()); + guid.setDefaultValue(dv); + } + if (!isEmpty(this.jTextFieldHelpText.getText())) { + guid.setHelpText(this.jTextFieldHelpText.getText()); + } + guid.setUsage(GuidUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + guid.setEnableFeature(this.jRadioButtonEnableFeature.isSelected()); + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + guid.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + + if (location > -1) { + guids.setGuidEntryArray(location, guid); + } else { + guids.addNewGuidEntry(); + guids.setGuidEntryArray(guids.getGuidEntryList().size() - 1, guid); + } + } catch (Exception e) { + Log.err("Update Guids", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleHobs.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleHobs.java new file mode 100644 index 0000000000..3d209e5634 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleHobs.java @@ -0,0 +1,596 @@ +/** @file + + The file is used to create, update Hob of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; + +import org.tianocore.GuidDocument; +import org.tianocore.HobTypes; +import org.tianocore.HobUsage; +import org.tianocore.HobsDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update Hob of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleHobs extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -553473437579358325L; + + // + //Define class members + // + private HobsDocument.Hobs hobs = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabel = null; + + private JTextField jTextFieldC_Name = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelName = null; + + private JTextField jTextFieldName = null; + + private JLabel jLabelUsage = null; + + private JLabel jLabelHobType = null; + + private JComboBox jComboBoxUsage = null; + + private JComboBox jComboBoxHobType = null; + + private JLabel jLabelHobEnabled = null; + + private JRadioButton jRadioButtonHobEnable = null; + + private JRadioButton jRadioButtonHobDisable = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private StarLabel jStarLabel1 = null; + + /** + This method initializes jTextField + + @return javax.swing.JTextField jTextFieldC_Name + + **/ + private JTextField getJTextFieldC_Name() { + if (jTextFieldC_Name == null) { + jTextFieldC_Name = new JTextField(); + jTextFieldC_Name.setBounds(new java.awt.Rectangle(160, 35, 320, 20)); + } + return jTextFieldC_Name; + } + + /** + This method initializes jTextField + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 60, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldName + + @return javax.swing.JTextField jTextFieldName + + **/ + private JTextField getJTextFieldName() { + if (jTextFieldName == null) { + jTextFieldName = new JTextField(); + jTextFieldName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldName; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 85, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jComboBoxHobType + + @return javax.swing.JComboBox jComboBoxHobType + + **/ + private JComboBox getJComboBoxHobType() { + if (jComboBoxHobType == null) { + jComboBoxHobType = new JComboBox(); + jComboBoxHobType.setBounds(new java.awt.Rectangle(160, 110, 320, 20)); + } + return jComboBoxHobType; + } + + /** + This method initializes jRadioButtonEnable + + @return javax.swing.JRadioButton jRadioButtonHobEnable + + **/ + private JRadioButton getJRadioButtonHobEnable() { + if (jRadioButtonHobEnable == null) { + jRadioButtonHobEnable = new JRadioButton(); + jRadioButtonHobEnable.setText("Enable"); + jRadioButtonHobEnable.setBounds(new java.awt.Rectangle(160, 135, 90, 20)); + jRadioButtonHobEnable.setSelected(true); + jRadioButtonHobEnable.addActionListener(this); + } + return jRadioButtonHobEnable; + } + + /** + This method initializes jRadioButtonDisable + + @return javax.swing.JRadioButton jRadioButtonHobDisable + + **/ + private JRadioButton getJRadioButtonHobDisable() { + if (jRadioButtonHobDisable == null) { + jRadioButtonHobDisable = new JRadioButton(); + jRadioButtonHobDisable.setText("Disable"); + jRadioButtonHobDisable.setBounds(new java.awt.Rectangle(320, 135, 90, 20)); + jRadioButtonHobDisable.addActionListener(this); + } + return jRadioButtonHobDisable; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 190, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 190, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 60, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 160, 320, 20)); + } + return jTextFieldOverrideID; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleHobs() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inHobs The input data of HobsDocument.Hobs + + **/ + public ModuleHobs(HobsDocument.Hobs inHobs) { + super(); + init(inHobs); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inHobs The input data of HobsDocument.Hobs + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleHobs(HobsDocument.Hobs inHobs, int type, int index) { + super(); + init(inHobs, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inHobs The input data of HobsDocument.Hobs + + **/ + private void init(HobsDocument.Hobs inHobs) { + init(); + this.setHobs(inHobs); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inHobs The input data of HobsDocument.Hobs + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(HobsDocument.Hobs inHobs, int type, int index) { + init(inHobs); + this.location = index; + if (this.hobs.getHobList().size() > 0) { + if (this.hobs.getHobArray(index).getName() != null) { + this.jTextFieldName.setText(this.hobs.getHobArray(index).getName()); + } + if (this.hobs.getHobArray(index).getCName() != null) { + this.jTextFieldC_Name.setText(this.hobs.getHobArray(index).getCName()); + } + if (this.hobs.getHobArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.hobs.getHobArray(index).getGuid().getStringValue()); + } + if (this.hobs.getHobArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.hobs.getHobArray(index).getUsage().toString()); + } + this.jRadioButtonHobEnable.setSelected(this.hobs.getHobArray(index).getHobEnabled()); + this.jRadioButtonHobDisable.setSelected(!this.hobs.getHobArray(index).getHobEnabled()); + this.jTextFieldOverrideID.setText(String.valueOf(this.hobs.getHobArray(index).getOverrideID())); + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Hobs"); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldName.setEnabled(!isView); + this.jTextFieldC_Name.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jComboBoxHobType.setEnabled(!isView); + this.jRadioButtonHobEnable.setEnabled(!isView); + this.jRadioButtonHobDisable.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + public JPanel getJContentPane() { + if (jContentPane == null) { + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 160, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelHobEnabled = new JLabel(); + jLabelHobEnabled.setText("Hob Enabled"); + jLabelHobEnabled.setBounds(new java.awt.Rectangle(15, 135, 140, 20)); + jLabelHobType = new JLabel(); + jLabelHobType.setText("Hob Type"); + jLabelHobType.setBounds(new java.awt.Rectangle(15, 110, 140, 20)); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelName = new JLabel(); + jLabelName.setText("Name"); + jLabelName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setText("Guid"); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabel = new JLabel(); + jLabel.setText("C_Name"); + jLabel.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabel, null); + jContentPane.add(getJTextFieldC_Name(), null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(jLabelName, null); + jContentPane.add(getJTextFieldName(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(jLabelHobType, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJComboBoxHobType(), null); + jContentPane.add(jLabelHobEnabled, null); + jContentPane.add(getJRadioButtonHobEnable(), null); + jContentPane.add(getJRadioButtonHobDisable(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + jContentPane.add(jStarLabel1, null); + } + return jContentPane; + } + + /** + This method initializes Usage type and Hob type + + **/ + private void initFrame() { + jComboBoxHobType.addItem("PHIT"); + jComboBoxHobType.addItem("MEMORY_ALLOCATION"); + jComboBoxHobType.addItem("RESOURCE_DESCRIPTOR"); + jComboBoxHobType.addItem("GUID_EXTENSION"); + jComboBoxHobType.addItem("FIRMWARE_VOLUME"); + jComboBoxHobType.addItem("CPU"); + jComboBoxHobType.addItem("POOL"); + jComboBoxHobType.addItem("CAPSULE_VOLUME"); + + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("PRIVATE"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + // + // Contorl the selected status when click RadionButton + // Do not use Radio Button Group + // + if (arg0.getSource() == jRadioButtonHobEnable) { + if (jRadioButtonHobEnable.isSelected()) { + jRadioButtonHobDisable.setSelected(false); + } + if (!jRadioButtonHobDisable.isSelected() && !jRadioButtonHobEnable.isSelected()) { + jRadioButtonHobEnable.setSelected(true); + } + } + + if (arg0.getSource() == jRadioButtonHobDisable) { + if (jRadioButtonHobDisable.isSelected()) { + jRadioButtonHobEnable.setSelected(false); + } + if (!jRadioButtonHobDisable.isSelected() && !jRadioButtonHobEnable.isSelected()) { + jRadioButtonHobDisable.setSelected(true); + } + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Get HobsDocument.Hobs + + @return HobsDocument.Hobs + + **/ + public HobsDocument.Hobs getHobs() { + return hobs; + } + + /** + Set HobsDocument.Hobs + + @param hobs The input data of HobsDocument.Hobs + + **/ + public void setHobs(HobsDocument.Hobs hobs) { + this.hobs = hobs; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldName.getText())) { + Log.err("Name couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isCName(this.jTextFieldC_Name.getText())) { + Log.err("Incorrect data type for C_Name"); + return false; + } + if (!isEmpty(this.jTextFieldGuid.getText()) && !DataValidation.isGuid(this.jTextFieldGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of Hobs + if exists hobs, set the value directly + if not exists hobs, new an instance first + + **/ + public void save() { + try { + if (this.hobs == null) { + hobs = HobsDocument.Hobs.Factory.newInstance(); + } + HobsDocument.Hobs.Hob hob = HobsDocument.Hobs.Hob.Factory.newInstance(); + if (!isEmpty(this.jTextFieldName.getText())) { + hob.setName(this.jTextFieldName.getText()); + } + if (!isEmpty(this.jTextFieldC_Name.getText())) { + hob.setCName(this.jTextFieldC_Name.getText()); + } + if (!isEmpty(this.jTextFieldGuid.getText())) { + GuidDocument.Guid guid = GuidDocument.Guid.Factory.newInstance(); + guid.setStringValue(this.jTextFieldGuid.getText()); + hob.setGuid(guid); + } + hob.setUsage(HobUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + hob.setHobType(HobTypes.Enum.forString(jComboBoxHobType.getSelectedItem().toString())); + hob.setHobEnabled(this.jRadioButtonHobEnable.isSelected()); + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + hob.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + hobs.setHobArray(location, hob); + } else { + hobs.addNewHob(); + hobs.setHobArray(hobs.getHobList().size() - 1, hob); + } + } catch (Exception e) { + Log.err("Update Hobs", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleIncludes.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleIncludes.java new file mode 100644 index 0000000000..dccee3148a --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleIncludes.java @@ -0,0 +1,867 @@ +/** @file + + The file is used to create, update Include of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Vector; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.tianocore.IncludesDocument; +import org.tianocore.PackageNameDocument; +import org.tianocore.PackageType; +import org.tianocore.PackageUsage; +import org.tianocore.SupportedArchitectures; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.packaging.common.ui.IDefaultMutableTreeNode; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update Include of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleIncludes extends IInternalFrame implements ItemListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = 3465193035145152131L; + + // + //Define class members + // + private IncludesDocument.Includes includes = null; + + private int location = -1; + + private int intSelectedItemId = 0; + + // + // 1 - Add; 2 - Update + // + private int operation = -1; + + private Vector vPackageName = new Vector(); + + private Vector vUsage = new Vector(); + + private Vector vPackageType = new Vector(); + + private Vector vUpdatedDate = new Vector(); + + private JPanel jContentPane = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelPackageName = null; + + private JLabel jLabelPackageType = null; + + private JComboBox jComboBoxPackageType = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private StarLabel jStarLabel1 = null; + + private JTextField jTextFieldPackageName = null; + + private JComboBox jComboBoxFileList = null; + + private JButton jButtonAdd = null; + + private JButton jButtonUpdate = null; + + private JButton jButtonRemove = null; + + private JLabel jLabelUpdatedDate = null; + + private JTextField jTextFieldUpdatedDate = null; + + private JCheckBox jCheckBoxArch = null; + + private JComboBox jComboBoxArch = null; + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButton() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 165, 90, 20)); + jButtonOk.addActionListener(this); + + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButton1() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 165, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jComboBoxPackageType + + @return javax.swing.JComboBox jComboBoxPackageType + + **/ + private JComboBox getJComboBoxPackageType() { + if (jComboBoxPackageType == null) { + jComboBoxPackageType = new JComboBox(); + jComboBoxPackageType.setBounds(new java.awt.Rectangle(160, 35, 320, 20)); + } + return jComboBoxPackageType; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jTextFieldPackageName + + @return javax.swing.JTextField jTextFieldPackageName + + **/ + private JTextField getJTextFieldPackageName() { + if (jTextFieldPackageName == null) { + jTextFieldPackageName = new JTextField(); + jTextFieldPackageName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldPackageName; + } + + /** + This method initializes jComboBoxFileList + + @return javax.swing.JComboBox jComboBoxFileList + + **/ + private JComboBox getJComboBoxFileList() { + if (jComboBoxFileList == null) { + jComboBoxFileList = new JComboBox(); + jComboBoxFileList.setBounds(new java.awt.Rectangle(15, 110, 210, 20)); + jComboBoxFileList.addActionListener(this); + jComboBoxFileList.addItemListener(this); + } + return jComboBoxFileList; + } + + /** + This method initializes jButtonAdd + + @return javax.swing.JButton jButtonAdd + + **/ + private JButton getJButtonAdd() { + if (jButtonAdd == null) { + jButtonAdd = new JButton(); + jButtonAdd.setBounds(new java.awt.Rectangle(230, 110, 80, 20)); + jButtonAdd.setText("Add"); + jButtonAdd.addActionListener(this); + } + return jButtonAdd; + } + + /** + This method initializes jButtonUpdate + + @return javax.swing.JButton jButtonUpdate + + **/ + private JButton getJButtonUpdate() { + if (jButtonUpdate == null) { + jButtonUpdate = new JButton(); + jButtonUpdate.setBounds(new java.awt.Rectangle(315, 110, 80, 20)); + jButtonUpdate.setText("Update"); + jButtonUpdate.addActionListener(this); + } + return jButtonUpdate; + } + + /** + This method initializes jButtonRemove + + @return javax.swing.JButton jButtonRemove + + **/ + private JButton getJButtonRemove() { + if (jButtonRemove == null) { + jButtonRemove = new JButton(); + jButtonRemove.setBounds(new java.awt.Rectangle(400, 110, 80, 20)); + jButtonRemove.setText("Remove"); + jButtonRemove.addActionListener(this); + } + return jButtonRemove; + } + + /** + This method initializes jTextFieldUpdatedDate + + @return javax.swing.JTextField jTextFieldUpdatedDate + + **/ + private JTextField getJTextFieldUpdatedDate() { + if (jTextFieldUpdatedDate == null) { + jTextFieldUpdatedDate = new JTextField(); + jTextFieldUpdatedDate.setBounds(new java.awt.Rectangle(160, 85, 320, 20)); + } + return jTextFieldUpdatedDate; + } + + /** + This method initializes jCheckBoxArch + + @return javax.swing.JCheckBox jCheckBoxArch + + **/ + private JCheckBox getJCheckBoxArch() { + if (jCheckBoxArch == null) { + jCheckBoxArch = new JCheckBox(); + jCheckBoxArch.setBounds(new java.awt.Rectangle(10, 135, 120, 20)); + jCheckBoxArch.setText("Specific Arch"); + jCheckBoxArch.addActionListener(this); + } + return jCheckBoxArch; + } + + /** + This method initializes jComboBoxArch + + @return javax.swing.JComboBox jComboBoxArch + + **/ + private JComboBox getJComboBoxArch() { + if (jComboBoxArch == null) { + jComboBoxArch = new JComboBox(); + jComboBoxArch.setBounds(new java.awt.Rectangle(140, 135, 340, 20)); + jComboBoxArch.setEnabled(false); + } + return jComboBoxArch; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleIncludes() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inIncludes The input data of IncludesDocument.Includes + + **/ + public ModuleIncludes(IncludesDocument.Includes inIncludes) { + super(); + init(inIncludes); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inIncludes The input data of IncludesDocument.Includes + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleIncludes(IncludesDocument.Includes inIncludes, int type, int index) { + super(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inIncludes The input data of IncludesDocument.Includes + @param type The input data of node type + @param index The input data of node index + @param inOperation The input data of current operation type + + **/ + public ModuleIncludes(IncludesDocument.Includes inIncludes, int type, int index, int inOperation) { + super(); + init(inIncludes, type, index, inOperation); + this.operation = inOperation; + this.setVisible(true); + } + + /** + This method initializes this + + @param inIncludes + + **/ + private void init(IncludesDocument.Includes inIncludes) { + init(); + this.setIncludes(inIncludes); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inIncludes The input data of IncludesDocument.Includes + @param type The input data of node type + @param index The input data of node index + @param inOperation The input data of current operation type + + **/ + private void init(IncludesDocument.Includes inIncludes, int type, int index, int inOperation) { + init(inIncludes); + this.location = index; + this.operation = inOperation; + + if (operation == 2) { + this.jCheckBoxArch.setEnabled(false); + this.jComboBoxArch.setEnabled(false); + + if (type == IDefaultMutableTreeNode.INCLUDES_PACKAGENAME) { + if (this.includes.getPackageNameList().size() > 0) { + for (int indexI = 0; indexI < this.includes.getPackageNameList().size(); indexI++) { + if (this.includes.getPackageNameArray(indexI).getStringValue() != null) { + vPackageName.addElement(this.includes.getPackageNameArray(indexI).getStringValue()); + } else { + vPackageName.addElement(""); + } + if (this.includes.getPackageNameArray(indexI).getUsage() != null) { + vUsage.addElement(this.includes.getPackageNameArray(indexI).getUsage().toString()); + } else { + vUsage.addElement("ALWAYS_CONSUMED"); + } + if (this.includes.getPackageNameArray(indexI).getPackageType() != null) { + vPackageType.addElement(this.includes.getPackageNameArray(indexI).getPackageType() + .toString()); + } else { + vPackageType.addElement("SOURCE"); + } + if (this.includes.getPackageNameArray(indexI).getUpdatedDate() != null) { + vUpdatedDate.addElement(this.includes.getPackageNameArray(indexI).getUpdatedDate()); + } else { + vUpdatedDate.addElement(""); + } + jComboBoxFileList.addItem(this.includes.getPackageNameArray(indexI).getStringValue()); + } + } + } + if (type == IDefaultMutableTreeNode.INCLUDES_ARCH_ITEM) { + this.jCheckBoxArch.setSelected(true); + this.jComboBoxArch.setSelectedItem(this.includes.getArchArray(index).getArchType().toString()); + for (int indexI = 0; indexI < this.includes.getArchArray(index).getPackageNameList().size(); indexI++) { + if (this.includes.getArchArray(index).getPackageNameArray(indexI).getStringValue() != null) { + vPackageName.addElement(this.includes.getArchArray(index).getPackageNameArray(indexI) + .getStringValue()); + } else { + vPackageName.addElement(""); + } + if (this.includes.getArchArray(index).getPackageNameArray(indexI).getUsage() != null) { + vUsage.addElement(this.includes.getArchArray(index).getPackageNameArray(indexI).getUsage() + .toString()); + } else { + vUsage.addElement(""); + } + if (this.includes.getArchArray(index).getPackageNameArray(indexI).getPackageType() != null) { + vPackageType.addElement(this.includes.getArchArray(index).getPackageNameArray(indexI) + .getPackageType().toString()); + } else { + vPackageType.addElement(""); + } + if (this.includes.getArchArray(index).getPackageNameArray(indexI).getUpdatedDate() != null) { + vUpdatedDate.addElement(this.includes.getArchArray(index).getPackageNameArray(indexI) + .getUpdatedDate()); + } else { + vUpdatedDate.addElement(""); + } + jComboBoxFileList.addItem(this.includes.getArchArray(index).getPackageNameArray(indexI) + .getStringValue()); + } + } + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Includes"); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jComboBoxPackageType.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jTextFieldPackageName.setEnabled(!isView); + this.jButtonAdd.setEnabled(!isView); + this.jButtonUpdate.setEnabled(!isView); + this.jButtonRemove.setEnabled(!isView); + this.jTextFieldUpdatedDate.setEnabled(!isView); + this.jCheckBoxArch.setEnabled(!isView); + this.jComboBoxArch.setEnabled(!isView); + + this.jButtonCancel.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelUpdatedDate = new JLabel(); + jLabelUpdatedDate.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelUpdatedDate.setText("Updated Date"); + jLabelUsage = new JLabel(); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelUsage.setText("Usage"); + jLabelPackageType = new JLabel(); + jLabelPackageType.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelPackageType.setText("Package Type"); + jLabelPackageName = new JLabel(); + jLabelPackageName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jLabelPackageName.setText("Package Name"); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJButton(), null); + jContentPane.add(getJButton1(), null); + jContentPane.add(jLabelPackageName, null); + jContentPane.add(jLabelPackageType, null); + jContentPane.add(getJComboBoxPackageType(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(getJTextFieldPackageName(), null); + jContentPane.add(getJComboBoxFileList(), null); + jContentPane.add(getJButtonAdd(), null); + jContentPane.add(getJButtonUpdate(), null); + jContentPane.add(getJButtonRemove(), null); + jContentPane.add(jLabelUpdatedDate, null); + jContentPane.add(getJTextFieldUpdatedDate(), null); + jContentPane.add(getJCheckBoxArch(), null); + jContentPane.add(getJComboBoxArch(), null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + if (arg0.getSource() == jButtonAdd) { + if (!checkAdd()) { + return; + } + addToList(); + } + if (arg0.getSource() == jButtonRemove) { + removeFromList(); + } + if (arg0.getSource() == jButtonUpdate) { + if (!checkAdd()) { + return; + } + updateForList(); + } + + // + //When and only when checked Arch box then can choose different arch types + // + if (arg0.getSource() == jCheckBoxArch) { + if (this.jCheckBoxArch.isSelected()) { + this.jComboBoxArch.setEnabled(true); + } else { + this.jComboBoxArch.setEnabled(false); + } + } + } + + /** + This method initializes Usage type, Package type and Arch type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("DEFAULT"); + + jComboBoxPackageType.addItem("SOURCE"); + jComboBoxPackageType.addItem("BINARY"); + jComboBoxPackageType.addItem("MIXED"); + + jComboBoxArch.addItem("ALL"); + jComboBoxArch.addItem("EBC"); + jComboBoxArch.addItem("ARM"); + jComboBoxArch.addItem("IA32"); + jComboBoxArch.addItem("X64"); + jComboBoxArch.addItem("IPF"); + jComboBoxArch.addItem("PPC"); + } + + /** + Add current item to Vector + + **/ + private void addToList() { + intSelectedItemId = vPackageName.size(); + vPackageName.addElement(this.jTextFieldPackageName.getText()); + vUsage.addElement(this.jComboBoxUsage.getSelectedItem().toString()); + vPackageType.addElement(this.jComboBoxPackageType.getSelectedItem().toString()); + vUpdatedDate.addElement(this.jTextFieldUpdatedDate.getText()); + jComboBoxFileList.addItem(this.jTextFieldPackageName.getText()); + jComboBoxFileList.setSelectedItem(this.jTextFieldPackageName.getText()); + + // + // Reset select item index + // + intSelectedItemId = vPackageName.size(); + + // + // Reload all fields of selected item + // + reloadFromList(); + } + + /** + Remove item from Vector + + **/ + private void removeFromList() { + int intTempIndex = intSelectedItemId; + if (vPackageName.size() < 1) { + return; + } + + jComboBoxFileList.removeItemAt(intSelectedItemId); + + vPackageName.removeElementAt(intTempIndex); + vUsage.removeElementAt(intTempIndex); + vPackageType.removeElementAt(intTempIndex); + vUpdatedDate.removeElementAt(intTempIndex); + + // + // Reload all fields of selected item + // + reloadFromList(); + } + + /** + Update current item of Vector + + **/ + private void updateForList() { + // + // Backup selected item index + // + int intTempIndex = intSelectedItemId; + + vPackageName.setElementAt(this.jTextFieldPackageName.getText(), intSelectedItemId); + vUsage.setElementAt(this.jComboBoxUsage.getSelectedItem().toString(), intSelectedItemId); + vPackageType.setElementAt(this.jComboBoxPackageType.getSelectedItem().toString(), intSelectedItemId); + vUpdatedDate.setElementAt(this.jTextFieldUpdatedDate.getText(), intSelectedItemId); + + jComboBoxFileList.removeAllItems(); + for (int index = 0; index < vPackageName.size(); index++) { + jComboBoxFileList.addItem(vPackageName.elementAt(index)); + } + + // + // Restore selected item index + // + intSelectedItemId = intTempIndex; + + // + // Reset select item index + // + jComboBoxFileList.setSelectedIndex(intSelectedItemId); + + // + // Reload all fields of selected item + // + reloadFromList(); + } + + /** + Refresh all fields' values of selected item of Vector + + **/ + private void reloadFromList() { + if (vPackageName.size() > 0) { + // + // Get selected item index + // + intSelectedItemId = jComboBoxFileList.getSelectedIndex(); + + this.jTextFieldPackageName.setText(vPackageName.elementAt(intSelectedItemId).toString()); + this.jComboBoxUsage.setSelectedItem(vUsage.elementAt(intSelectedItemId).toString()); + this.jComboBoxPackageType.setSelectedItem(vPackageType.elementAt(intSelectedItemId).toString()); + this.jTextFieldUpdatedDate.setText(vUpdatedDate.elementAt(intSelectedItemId).toString()); + } else { + this.jTextFieldPackageName.setText(""); + this.jComboBoxUsage.setSelectedItem(""); + this.jComboBoxPackageType.setSelectedItem(""); + this.jTextFieldUpdatedDate.setText(""); + } + } + + /** + Get IncludesDocument.Includes + + @return IncludesDocument.Includes + + **/ + public IncludesDocument.Includes getIncludes() { + return includes; + } + + /** + Set IncludesDocument.Includes + + @param includes IncludesDocument.Includes + + **/ + public void setIncludes(IncludesDocument.Includes includes) { + this.includes = includes; + } + + /* (non-Javadoc) + * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent) + * + * Reflesh the frame when selected item changed + * + */ + public void itemStateChanged(ItemEvent arg0) { + if (arg0.getStateChange() == ItemEvent.SELECTED) { + reloadFromList(); + } + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + if (this.jComboBoxFileList.getItemCount() < 1) { + Log.err("Must have one include at least!"); + return false; + } + return true; + } + + /** + Data validation for all fields before add current item to Vector + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean checkAdd() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldPackageName.getText())) { + Log.err("File Name couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isPackageName(this.jTextFieldPackageName.getText())) { + Log.err("Incorrect data type for Package Name"); + return false; + } + if (!isEmpty(this.jTextFieldUpdatedDate.getText()) + && !DataValidation.isDateType(this.jTextFieldUpdatedDate.getText())) { + Log.err("Incorrect data type for Update Date"); + return false; + } + + return true; + } + + /** + Save all components of Includes + if exists includes, set the value directly + if not exists includes, new an instance first + + **/ + public void save() { + try { + if (this.includes == null) { + includes = IncludesDocument.Includes.Factory.newInstance(); + } + // + //Save as file name + // + if (!this.jCheckBoxArch.isSelected()) { + if (this.operation == 2) { //Add new packageName + // + //First remove all existed packageName + // + if (includes.getPackageNameList().size() > 0) { + for (int index = includes.getPackageNameList().size() - 1; index >= 0; index--) { + includes.removePackageName(index); + } + } + } + for (int index = 0; index < vPackageName.size(); index++) { + PackageNameDocument.PackageName packageName = PackageNameDocument.PackageName.Factory.newInstance(); + if (!isEmpty(vPackageName.elementAt(index).toString())) { + packageName.setStringValue(vPackageName.elementAt(index).toString()); + } + if (!isEmpty(vUsage.elementAt(index).toString())) { + packageName.setUsage(PackageUsage.Enum.forString(vUsage.elementAt(index).toString())); + } + if (!isEmpty(vPackageType.elementAt(index).toString())) { + packageName + .setPackageType(PackageType.Enum.forString(vPackageType.elementAt(index).toString())); + } + if (!isEmpty(vUpdatedDate.elementAt(index).toString())) { + packageName.setUpdatedDate(vUpdatedDate.elementAt(index).toString()); + } + includes.addNewPackageName(); + includes.setPackageNameArray(includes.getPackageNameList().size() - 1, packageName); + } + } + // + //Save as Arch + // + if (this.jCheckBoxArch.isSelected()) { + IncludesDocument.Includes.Arch arch = IncludesDocument.Includes.Arch.Factory.newInstance(); + if (this.operation == 2) { + // + //First remove all existed filename + // + for (int index = includes.getArchArray(location).getPackageNameList().size() - 1; index >= 0; index--) { + includes.getArchArray(location).removePackageName(index); + } + } + + for (int index = 0; index < vPackageName.size(); index++) { + PackageNameDocument.PackageName packageName = PackageNameDocument.PackageName.Factory.newInstance(); + if (!isEmpty(vPackageName.elementAt(index).toString())) { + packageName.setStringValue(vPackageName.elementAt(index).toString()); + } + if (!isEmpty(vUsage.elementAt(index).toString())) { + packageName.setUsage(PackageUsage.Enum.forString(vUsage.elementAt(index).toString())); + } + if (!isEmpty(vPackageType.elementAt(index).toString())) { + packageName + .setPackageType(PackageType.Enum.forString(vPackageType.elementAt(index).toString())); + } + if (!isEmpty(vUpdatedDate.elementAt(index).toString())) { + packageName.setUpdatedDate(vUpdatedDate.elementAt(index).toString()); + } + arch.addNewPackageName(); + arch.setPackageNameArray(arch.getPackageNameList().size() - 1, packageName); + } + arch + .setArchType(SupportedArchitectures.Enum.forString(this.jComboBoxArch.getSelectedItem().toString())); + if (location > -1) { + includes.setArchArray(location, arch); + } else { + includes.addNewArch(); + includes.setArchArray(includes.getArchList().size() - 1, arch); + } + } + } catch (Exception e) { + Log.err("Update Source Files", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleLibraryClassDefinitions.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleLibraryClassDefinitions.java new file mode 100644 index 0000000000..dfd6893f18 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleLibraryClassDefinitions.java @@ -0,0 +1,625 @@ +/** @file + + The file is used to create, update Library Class Definition of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.DefaultListModel; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JScrollPane; +import javax.swing.JTextField; + +import org.tianocore.LibraryClassDefinitionsDocument; +import org.tianocore.LibraryClassDocument; +import org.tianocore.LibraryUsage; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.packaging.common.ui.IInternalFrame; + +/** + The class is used to create, update Library Class Definition of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleLibraryClassDefinitions extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -1743248695411382857L; + + // + //Define class members + // + private static String Separator = "::"; + + private DefaultListModel listItem = new DefaultListModel(); + + private LibraryClassDefinitionsDocument.LibraryClassDefinitions libraryClassDefinitions = null; + + private JPanel jContentPane = null; + + private JRadioButton jRadioButtonAdd = null; + + private JRadioButton jRadioButtonSelect = null; + + private JTextField jTextFieldAdd = null; + + private JComboBox jComboBoxSelect = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JScrollPane jScrollPane = null; + + private JList jListLibraryClassDefinitions = null; + + private JButton jButtonAdd = null; + + private JButton jButtonRemove = null; + + private JButton jButtonClearAll = null; + + private JButton jButtonCancel = null; + + private JButton jButtonOk = null; + + /** + This method initializes jRadioButtonAdd + + @return javax.swing.JRadioButton jRadioButtonAdd + + **/ + private JRadioButton getJRadioButtonAdd() { + if (jRadioButtonAdd == null) { + jRadioButtonAdd = new JRadioButton(); + jRadioButtonAdd.setBounds(new java.awt.Rectangle(15, 35, 205, 20)); + jRadioButtonAdd.setText("Add a new Library Class"); + jRadioButtonAdd.addActionListener(this); + jRadioButtonAdd.setSelected(false); + } + return jRadioButtonAdd; + } + + /** + This method initializes jRadioButtonSelect + + @return javax.swing.JRadioButton jRadioButtonSelect + + **/ + private JRadioButton getJRadioButtonSelect() { + if (jRadioButtonSelect == null) { + jRadioButtonSelect = new JRadioButton(); + jRadioButtonSelect.setBounds(new java.awt.Rectangle(15, 10, 205, 20)); + jRadioButtonSelect.setText("Select an existed Library Class"); + jRadioButtonSelect.addActionListener(this); + jRadioButtonSelect.setSelected(true); + } + return jRadioButtonSelect; + } + + /** + This method initializes jTextFieldAdd + + @return javax.swing.JTextField jTextFieldAdd + + **/ + private JTextField getJTextFieldAdd() { + if (jTextFieldAdd == null) { + jTextFieldAdd = new JTextField(); + jTextFieldAdd.setBounds(new java.awt.Rectangle(220, 35, 260, 20)); + jTextFieldAdd.setEnabled(false); + } + return jTextFieldAdd; + } + + /** + This method initializes jComboBoxSelect + + @return javax.swing.JComboBox jComboBoxSelect + + **/ + private JComboBox getJComboBoxSelect() { + if (jComboBoxSelect == null) { + jComboBoxSelect = new JComboBox(); + jComboBoxSelect.setBounds(new java.awt.Rectangle(220, 10, 260, 20)); + jComboBoxSelect.setEnabled(true); + } + return jComboBoxSelect; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(220, 60, 260, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane jScrollPane + + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(15, 95, 350, 200)); + jScrollPane.setViewportView(getJListLibraryClassDefinitions()); + } + return jScrollPane; + } + + /** + This method initializes jListLibraryClassDefinitions + + @return javax.swing.JList jListLibraryClassDefinitions + + **/ + private JList getJListLibraryClassDefinitions() { + if (jListLibraryClassDefinitions == null) { + jListLibraryClassDefinitions = new JList(listItem); + } + return jListLibraryClassDefinitions; + } + + /** + This method initializes jButtonAdd + + @return javax.swing.JButton jButtonAdd + + **/ + private JButton getJButtonAdd() { + if (jButtonAdd == null) { + jButtonAdd = new JButton(); + jButtonAdd.setBounds(new java.awt.Rectangle(380, 115, 90, 20)); + jButtonAdd.setText("Add"); + jButtonAdd.addActionListener(this); + } + return jButtonAdd; + } + + /** + This method initializes jButtonRemove + + @return javax.swing.JButton jButtonRemove + + **/ + private JButton getJButtonRemove() { + if (jButtonRemove == null) { + jButtonRemove = new JButton(); + jButtonRemove.setBounds(new java.awt.Rectangle(380, 230, 90, 20)); + jButtonRemove.setText("Remove"); + jButtonRemove.addActionListener(this); + } + return jButtonRemove; + } + + /** + This method initializes jButtonRemoveAll + + @return javax.swing.JButton jButtonClearAll + + **/ + private JButton getJButtonClearAll() { + if (jButtonClearAll == null) { + jButtonClearAll = new JButton(); + jButtonClearAll.setBounds(new java.awt.Rectangle(380, 260, 90, 20)); + jButtonClearAll.setText("Clear All"); + jButtonClearAll.addActionListener(this); + } + return jButtonClearAll; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setPreferredSize(new java.awt.Dimension(90, 20)); + jButtonCancel.setLocation(new java.awt.Point(390, 305)); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setSize(new java.awt.Dimension(90, 20)); + jButtonOk.setText("OK"); + jButtonOk.setLocation(new java.awt.Point(290, 305)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleLibraryClassDefinitions() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inLibraryClassDefinitions The input data of LibraryClassDefinitionsDocument.LibraryClassDefinitions + + **/ + public ModuleLibraryClassDefinitions( + LibraryClassDefinitionsDocument.LibraryClassDefinitions inLibraryClassDefinitions) { + super(); + init(inLibraryClassDefinitions); + this.setVisible(true); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inLibraryClassDefinitions The input data of LibraryClassDefinitionsDocument.LibraryClassDefinitions + + **/ + private void init(LibraryClassDefinitionsDocument.LibraryClassDefinitions inLibraryClassDefinitions) { + init(); + this.setLibraryClassDefinitions(inLibraryClassDefinitions); + if (this.libraryClassDefinitions != null) { + if (this.libraryClassDefinitions.getLibraryClassList().size() > 0) { + for (int index = 0; index < this.libraryClassDefinitions.getLibraryClassList().size(); index++) { + listItem.addElement(this.libraryClassDefinitions.getLibraryClassArray(index).getUsage().toString() + + ModuleLibraryClassDefinitions.Separator + + this.libraryClassDefinitions.getLibraryClassArray(index).getStringValue()); + this.libraryClassDefinitions.getLibraryClassList(); + } + } + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setContentPane(getJContentPane()); + this.setTitle("Library Class Definitions"); + this.setBounds(new java.awt.Rectangle(0, 0, 500, 515)); + //this.centerWindow(); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jRadioButtonAdd.setEnabled(!isView); + this.jRadioButtonSelect.setEnabled(!isView); + this.jTextFieldAdd.setEnabled(!isView); + this.jComboBoxSelect.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jButtonAdd.setEnabled(!isView); + this.jButtonRemove.setEnabled(!isView); + this.jButtonClearAll.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelUsage = new JLabel(); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 60, 205, 20)); + jLabelUsage.setText("Usage"); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJRadioButtonAdd(), null); + jContentPane.add(getJRadioButtonSelect(), null); + jContentPane.add(getJTextFieldAdd(), null); + jContentPane.add(getJComboBoxSelect(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButtonAdd(), null); + jContentPane.add(getJButtonRemove(), null); + jContentPane.add(getJButtonClearAll(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButtonOk(), null); + } + return jContentPane; + } + + /** + This method initializes all existing libraries and usage types + + **/ + private void initFrame() { + jComboBoxSelect.addItem("BaseCpuICacheFlush"); + jComboBoxSelect.addItem("BaseDebugLibNull"); + jComboBoxSelect.addItem("BaseDebugLibReportStatusCode"); + jComboBoxSelect.addItem("BaseIoLibIntrinsic"); + jComboBoxSelect.addItem("BaseLib"); + jComboBoxSelect.addItem("BaseMemoryLib"); + jComboBoxSelect.addItem("BaseMemoryLibMmx"); + jComboBoxSelect.addItem("BaseMemoryLibSse2"); + jComboBoxSelect.addItem("BasePeCoffGetEntryPointLib"); + jComboBoxSelect.addItem("BasePeCoffLib"); + jComboBoxSelect.addItem("BasePrintLib"); + jComboBoxSelect.addItem("BaseReportStatusCodeLibNull"); + jComboBoxSelect.addItem("CommonPciCf8Lib"); + jComboBoxSelect.addItem("CommonPciExpressLib"); + jComboBoxSelect.addItem("CommonPciLibCf8"); + jComboBoxSelect.addItem("CommonPciLibPciExpress"); + jComboBoxSelect.addItem("DxeCoreEntryPoint"); + jComboBoxSelect.addItem("DxeHobLib"); + jComboBoxSelect.addItem("DxeIoLibCpuIo"); + jComboBoxSelect.addItem("DxeLib"); + jComboBoxSelect.addItem("DxePcdLib"); + jComboBoxSelect.addItem("DxeReportStatusCodeLib"); + jComboBoxSelect.addItem("DxeServicesTableLib"); + jComboBoxSelect.addItem("PeiCoreEntryPoint"); + jComboBoxSelect.addItem("PeiMemoryLib"); + jComboBoxSelect.addItem("PeimEntryPoint"); + jComboBoxSelect.addItem("PeiReportStatusCodeLib"); + jComboBoxSelect.addItem("PeiServicesTablePointerLib"); + jComboBoxSelect.addItem("PeiServicesTablePointerLibMm7"); + jComboBoxSelect.addItem("UefiDebugLibConOut"); + jComboBoxSelect.addItem("UefiDebugLibStdErr"); + jComboBoxSelect.addItem("UefiDriverEntryPointMultiple"); + jComboBoxSelect.addItem("UefiDriverEntryPointSingle"); + jComboBoxSelect.addItem("UefiDriverEntryPointSingleUnload"); + jComboBoxSelect.addItem("UefiDriverModelLib"); + jComboBoxSelect.addItem("UefiDriverModelLibNoConfigNoDiag"); + jComboBoxSelect.addItem("UefiLib"); + jComboBoxSelect.addItem("UefiMemoryLib"); + + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("DEFAULT"); + jComboBoxUsage.addItem("PRIVATE"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.dispose(); + this.setEdited(true); + this.save(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + this.setEdited(false); + } + + // + // Add current Library and its usage to the list + // + if (arg0.getSource() == jButtonAdd) { + if (!checkAdd()) { + return; + } + String strLibClass = ""; + String strUsage = ""; + if (jRadioButtonAdd.isSelected()) { + strLibClass = jTextFieldAdd.getText(); + } + if (jRadioButtonSelect.isSelected()) { + strLibClass = jComboBoxSelect.getSelectedItem().toString(); + } + strUsage = jComboBoxUsage.getSelectedItem().toString(); + listItem.addElement(strUsage + ModuleLibraryClassDefinitions.Separator + strLibClass); + } + + // + // Remove current Library and its usage of the list + // + if (arg0.getSource() == jButtonRemove) { + int intSelected[] = jListLibraryClassDefinitions.getSelectedIndices(); + if (intSelected.length > 0) { + for (int index = intSelected.length - 1; index > -1; index--) { + listItem.removeElementAt(intSelected[index]); + } + } + jListLibraryClassDefinitions.getSelectionModel().clearSelection(); + } + + if (arg0.getSource() == jButtonClearAll) { + listItem.removeAllElements(); + } + + // + // Contorl the selected status when click RadionButton + // Do not use Radio Button Group + // + if (arg0.getSource() == jRadioButtonAdd) { + if (jRadioButtonAdd.isSelected()) { + jRadioButtonSelect.setSelected(false); + jTextFieldAdd.setEnabled(true); + jComboBoxSelect.setEnabled(false); + } + if (!jRadioButtonSelect.isSelected() && !jRadioButtonAdd.isSelected()) { + jRadioButtonAdd.setSelected(true); + jTextFieldAdd.setEnabled(true); + jComboBoxSelect.setEnabled(false); + } + } + + if (arg0.getSource() == jRadioButtonSelect) { + if (jRadioButtonSelect.isSelected()) { + jRadioButtonAdd.setSelected(false); + jTextFieldAdd.setEnabled(false); + jComboBoxSelect.setEnabled(true); + } + if (!jRadioButtonSelect.isSelected() && !jRadioButtonAdd.isSelected()) { + jRadioButtonSelect.setSelected(true); + jTextFieldAdd.setEnabled(false); + jComboBoxSelect.setEnabled(true); + } + } + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + if (listItem.getSize() < 1) { + Log.err("Must have one Library Class at least!"); + return false; + } + return true; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean checkAdd() { + // + // Check if all required fields are not empty + // + if (this.jRadioButtonAdd.isSelected() && isEmpty(this.jTextFieldAdd.getText())) { + Log.err("Library Class couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (this.jRadioButtonAdd.isSelected() && !DataValidation.isLibraryClass(this.jTextFieldAdd.getText())) { + Log.err("Incorrect data type for Library Class"); + return false; + } + return true; + } + + /** + Save all components of Mbd Header + if exists mbdHeader, set the value directly + if not exists mbdHeader, new an instance first + + **/ + public void save() { + try { + int intLibraryCount = listItem.getSize(); + + if (this.libraryClassDefinitions == null) { + libraryClassDefinitions = LibraryClassDefinitionsDocument.LibraryClassDefinitions.Factory.newInstance(); + } + + if (intLibraryCount > 0) { + LibraryClassDocument.LibraryClass mLibraryClass = LibraryClassDocument.LibraryClass.Factory + .newInstance(); + for (int index = this.libraryClassDefinitions.getLibraryClassList().size() - 1; index > -1; index--) { + this.libraryClassDefinitions.removeLibraryClass(index); + } + for (int index = 0; index < intLibraryCount; index++) { + String strAll = listItem.get(index).toString(); + String strUsage = strAll.substring(0, strAll.indexOf(ModuleLibraryClassDefinitions.Separator)); + String strLibraryClass = strAll.substring(strAll.indexOf(ModuleLibraryClassDefinitions.Separator) + + ModuleLibraryClassDefinitions.Separator.length()); + mLibraryClass.setStringValue(strLibraryClass); + mLibraryClass.setUsage(LibraryUsage.Enum.forString(strUsage)); + this.libraryClassDefinitions.addNewLibraryClass(); + this.libraryClassDefinitions.setLibraryClassArray(index, mLibraryClass); + } + } else { + this.libraryClassDefinitions.setNil(); + } + } catch (Exception e) { + Log.err("Update Library Class Definitions", e.getMessage()); + } + } + + /** + Get LibraryClassDefinitionsDocument.LibraryClassDefinitions + + @return + + **/ + public LibraryClassDefinitionsDocument.LibraryClassDefinitions getLibraryClassDefinitions() { + return libraryClassDefinitions; + } + + /** + Set LibraryClassDefinitionsDocument.LibraryClassDefinitions + + @param libraryClassDefinitions The input data of LibraryClassDefinitionsDocument.LibraryClassDefinitions + + **/ + public void setLibraryClassDefinitions( + LibraryClassDefinitionsDocument.LibraryClassDefinitions libraryClassDefinitions) { + this.libraryClassDefinitions = libraryClassDefinitions; + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleMain.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleMain.java new file mode 100644 index 0000000000..a9a0c21e5b --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleMain.java @@ -0,0 +1,4422 @@ +/** @file + + The main GUI for module editor. + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowEvent; +import java.io.File; +import java.io.IOException; + +import javax.swing.JButton; +import javax.swing.JDesktopPane; +import javax.swing.JFileChooser; +import javax.swing.JInternalFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.JScrollPane; +import javax.swing.border.BevelBorder; +import javax.swing.event.TreeSelectionEvent; +import javax.swing.event.TreeSelectionListener; + +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlOptions; +import org.tianocore.BootModesDocument; +import org.tianocore.BuildOptionsDocument; +import org.tianocore.DataHubsDocument; +import org.tianocore.EventsDocument; +import org.tianocore.ExternsDocument; +import org.tianocore.FormsetsDocument; +import org.tianocore.GuidsDocument; +import org.tianocore.HobsDocument; +import org.tianocore.IncludesDocument; +import org.tianocore.LibrariesDocument; +import org.tianocore.LibraryClassDefinitionsDocument; +import org.tianocore.LibraryModuleBuildDescriptionDocument; +import org.tianocore.LibraryModuleSurfaceAreaDocument; +import org.tianocore.MbdHeaderDocument; +import org.tianocore.MbdLibHeaderDocument; +import org.tianocore.ModuleBuildDescriptionDocument; +import org.tianocore.ModuleSurfaceAreaDocument; +import org.tianocore.MsaHeaderDocument; +import org.tianocore.MsaLibHeaderDocument; +import org.tianocore.PCDsDocument; +import org.tianocore.PPIsDocument; +import org.tianocore.ProtocolsDocument; +import org.tianocore.SourceFilesDocument; +import org.tianocore.SystemTablesDocument; +import org.tianocore.VariablesDocument; +import org.tianocore.common.IFileFilter; +import org.tianocore.common.Log; +import org.tianocore.packaging.common.ui.IDefaultMutableTreeNode; +import org.tianocore.packaging.common.ui.IDesktopManager; +import org.tianocore.packaging.common.ui.IFrame; +import org.tianocore.packaging.common.ui.ITree; +import org.tianocore.packaging.workspace.common.Workspace; + +/** + The class is used to show main GUI of ModuleEditor + It extends IFrame implements MouseListener, TreeSelectionListener + + @since ModuleEditor 1.0 + + **/ +public class ModuleMain extends IFrame implements MouseListener, TreeSelectionListener { + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -7103240960573031772L; + + // + //Define class members + // + private String currentModule = ""; + + private String saveFileName = ""; + + /// + /// 0 - reserved; 1 - msa; 2 - mbd; 3 - lmsa; 4 - lmbd; + /// + private int currentModuleType = 0; + + private int currentNodeType = -1; + + private String windowTitle = "ModuleEditor 1.0 "; + + private ModuleSurfaceAreaDocument xmlMsaDoc = null; + + private ModuleBuildDescriptionDocument xmlMbdDoc = null; + + private LibraryModuleSurfaceAreaDocument xmlMlsaDoc = null; + + private LibraryModuleBuildDescriptionDocument xmlMlbdDoc = null; + + private MsaHeaderDocument.MsaHeader xmlmh = null; + + private MbdHeaderDocument.MbdHeader xmlmbdh = null; + + private MsaLibHeaderDocument.MsaLibHeader xmlmlh = null; + + private MbdLibHeaderDocument.MbdLibHeader xmlmlbdh = null; + + private LibraryClassDefinitionsDocument.LibraryClassDefinitions xmllcd = null; + + private LibrariesDocument.Libraries xmllib = null; + + private SourceFilesDocument.SourceFiles xmlsf = null; + + private IncludesDocument.Includes xmlic = null; + + private ProtocolsDocument.Protocols xmlpl = null; + + private EventsDocument.Events xmlen = null; + + private HobsDocument.Hobs xmlhob = null; + + private PPIsDocument.PPIs xmlppi = null; + + private VariablesDocument.Variables xmlvb = null; + + private BootModesDocument.BootModes xmlbm = null; + + private SystemTablesDocument.SystemTables xmlst = null; + + private DataHubsDocument.DataHubs xmldh = null; + + private FormsetsDocument.Formsets xmlfs = null; + + private GuidsDocument.Guids xmlgu = null; + + private ExternsDocument.Externs xmlet = null; + + private PCDsDocument.PCDs xmlpcd = null; + + private BuildOptionsDocument.BuildOptions xmlbo = null; + + IDefaultMutableTreeNode dmtnRoot = null; + + private JPanel jContentPane = null; + + private JMenuBar jMenuBar = null; + + private JMenu jMenuModule = null; + + private JMenu jMenuModuleNew = null; + + private JMenuItem jMenuItemModuleNewModule = null; + + private JMenuItem jMenuItemModuleSaveAs = null; + + private JMenuItem jMenuItemModuleExit = null; + + private JMenu jMenuEdit = null; + + private JMenuItem jMenuItemEditAddLibraryClassDefinitions = null; + + private JMenuItem jMenuItemEditAddSourceFiles = null; + + private JMenuItem jMenuItemEditAddIncludes = null; + + private JMenuItem jMenuItemEditAddProtocols = null; + + private JMenuItem jMenuItemEditAddEvents = null; + + private JMenuItem jMenuItemEditAddHobs = null; + + private JMenuItem jMenuItemEditAddPPIs = null; + + private JMenuItem jMenuItemEditAddVariables = null; + + private JMenuItem jMenuItemEditAddBootModes = null; + + private JMenuItem jMenuItemEditAddSystemTables = null; + + private JMenuItem jMenuItemEditAddDataHubs = null; + + private JMenuItem jMenuItemEditAddFormsets = null; + + private JMenuItem jMenuItemEditAddGuids = null; + + private JMenuItem jMenuItemEditAddExterns = null; + + private JMenuItem jMenuItemEditAddPCDs = null; + + private JDesktopPane jDesktopPane = null; + + private IDesktopManager iDesktopManager = new IDesktopManager(); + + private JScrollPane jScrollPaneTree = null; + + private ITree iTree = null; + + private JMenu jMenuHelp = null; + + private JMenuItem jMenuItemHelpAbout = null; + + private JMenu jMenuEditAdd = null; + + private JMenuItem jMenuItemEditDelete = null; + + private JMenuItem jMenuItemEditUpdate = null; + + private JPopupMenu jPopupMenu = null; + + private JMenuItem jMenuItemPopupAdd = null; + + private JMenuItem jMenuItemPopupUpdate = null; + + private JMenuItem jMenuItemPopupDelete = null; + + private Workspace ws = new Workspace(); + + private static final int OPENED = 0; + + private static final int CLOSED = 1; + + private static final int NEW_WITHOUT_CHANGE = 2; + + private static final int NEW_WITH_CHANGE = 3; + + private static final int UPDATE_WITHOUT_CHANGE = 4; + + private static final int UPDATE_WITH_CHANGE = 5; + + private static final int SAVE_WITHOUT_CHANGE = 6; + + private static final int SAVE_WITH_CHANGE = 7; + + private static final int ADD = 1; + + private static final int UPDATE = 2; + + //private static final int DELETE = 3; + + private static final int VIEW = 4; + + private MsaHeader msa = null; + + private MbdHeader mbd = null; + + private MsaLibHeader mlsa = null; + + private MbdLibHeader mlbd = null; + + private ModuleLibraryClassDefinitions mlcd = null; + + private MbdLibraries mlib = null; + + private ModuleSourceFiles msf = null; + + private ModuleIncludes mic = null; + + private ModuleProtocols mp = null; + + private ModuleEvents mev = null; + + private ModuleHobs mh = null; + + private ModulePpis mpp = null; + + private ModuleVariables mv = null; + + private ModuleBootModes mbm = null; + + private ModuleSystemTables mst = null; + + private ModuleDataHubs mdh = null; + + private ModuleFormsets mf = null; + + private ModuleGuids mg = null; + + private ModuleExterns met = null; + + private ModulePCDs mpcd = null; + + private JMenuItem jMenuItemModuleOpenModule = null; + + private JMenuItem jMenuItemModuleNewModuleBuildDescription = null; + + private JMenuItem jMenuItemModuleNewLibraryModule = null; + + private JMenuItem jMenuItemModuleNewLibraryModuleBuildDescription = null; + + private JMenu jMenuModuleOpen = null; + + private JMenuItem jMenuItemModuleOpenModuleBuildDescription = null; + + private JMenuItem jMenuItemModuleOpenLibraryModule = null; + + private JMenuItem jMenuItemModuleOpenLibraryModuleBuildDescription = null; + + private JMenuItem jMenuItemModuleSave = null; + + private JMenuItem jMenuItemModuleClose = null; + + private JMenu jMenuTools = null; + + private JMenu jMenuWindow = null; + + private JMenuItem jMenuItemEditAddLibraries = null; + + private JPanel jPanelOperation = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + /** + This method initializes jMenuBar + + @return javax.swing.JMenuBar Main menu bar for the entire GUI + + **/ + private JMenuBar getjJMenuBar() { + if (jMenuBar == null) { + jMenuBar = new JMenuBar(); + jMenuBar.setPreferredSize(new java.awt.Dimension(0, 18)); + jMenuBar.add(getJMenuModule()); + jMenuBar.add(getJMenuEdit()); + jMenuBar.add(getJMenuTools()); + jMenuBar.add(getJMenuWindow()); + jMenuBar.add(getJMenuHelp()); + } + return jMenuBar; + } + + /** + This method initializes jMenuFile + + @return javax.swing.JMenu jMenuModule + + **/ + private JMenu getJMenuModule() { + if (jMenuModule == null) { + jMenuModule = new JMenu(); + jMenuModule.setText("Module"); + jMenuModule.add(getJMenuModuleNew()); + jMenuModule.addSeparator(); + jMenuModule.add(getJMenuModuleOpen()); + jMenuModule.addSeparator(); + jMenuModule.add(getJMenuItemModuleSave()); + jMenuModule.add(getJMenuItemModuleSaveAs()); + jMenuModule.addSeparator(); + jMenuModule.add(getJMenuItemModuleClose()); + jMenuModule.addSeparator(); + jMenuModule.add(getJMenuItemModuleExit()); + } + return jMenuModule; + } + + /** + This method initializes jMenuItemModuleNewModule + + @return javax.swing.JMenuItem jMenuItemModuleNewModule + + **/ + private JMenuItem getJMenuItemModuleNewModule() { + if (jMenuItemModuleNewModule == null) { + jMenuItemModuleNewModule = new JMenuItem(); + jMenuItemModuleNewModule.setText("Module (.msa)"); + jMenuItemModuleNewModule.addActionListener(this); + } + return jMenuItemModuleNewModule; + } + + /** + This method initializes jMenuItemModuleSaveAs + + @return javax.swing.JMenuItem jMenuItemModuleSaveAs + + **/ + private JMenuItem getJMenuItemModuleSaveAs() { + if (jMenuItemModuleSaveAs == null) { + jMenuItemModuleSaveAs = new JMenuItem(); + jMenuItemModuleSaveAs.setText("Save As..."); + jMenuItemModuleSaveAs.addActionListener(this); + jMenuItemModuleSaveAs.setEnabled(false); + } + return jMenuItemModuleSaveAs; + } + + /** + This method initializes jMenuItemModuleExit + + @return javax.swing.JMenuItem jMenuItemModuleExit + + **/ + private JMenuItem getJMenuItemModuleExit() { + if (jMenuItemModuleExit == null) { + jMenuItemModuleExit = new JMenuItem(); + jMenuItemModuleExit.setText("Exit"); + jMenuItemModuleExit.addActionListener(this); + } + return jMenuItemModuleExit; + } + + /** + This method initializes jMenuEdit + + @return javax.swing.JMenu jMenuEdit + + **/ + private JMenu getJMenuEdit() { + if (jMenuEdit == null) { + jMenuEdit = new JMenu(); + jMenuEdit.setText("Edit"); + jMenuEdit.add(getJMenu()); + jMenuEdit.add(getJMenuItemEditUpdate()); + jMenuEdit.add(getJMenuItemEditDelete()); + } + return jMenuEdit; + } + + /** + This method initializes jMenuItemEditAddLibraryClassDefinitions + + @return javax.swing.JMenuItem jMenuItemEditAddLibraryClassDefinitions + + **/ + private JMenuItem getJMenuItemEditAddLibraryClassDefinitions() { + if (jMenuItemEditAddLibraryClassDefinitions == null) { + jMenuItemEditAddLibraryClassDefinitions = new JMenuItem(); + jMenuItemEditAddLibraryClassDefinitions.setText("Library Class Definitions"); + jMenuItemEditAddLibraryClassDefinitions.addActionListener(this); + } + return jMenuItemEditAddLibraryClassDefinitions; + } + + /** + This method initializes jMenuItemEditAddSourceFiles + + @return javax.swing.JMenuItem jMenuItemEditAddSourceFiles + + **/ + private JMenuItem getJMenuItemEditAddSourceFiles() { + if (jMenuItemEditAddSourceFiles == null) { + jMenuItemEditAddSourceFiles = new JMenuItem(); + jMenuItemEditAddSourceFiles.setText("Source Files"); + jMenuItemEditAddSourceFiles.addActionListener(this); + } + return jMenuItemEditAddSourceFiles; + } + + /** + This method initializes jMenuItemEditAddIncludes + + @return javax.swing.JMenuItem jMenuItemEditAddIncludes + + **/ + private JMenuItem getJMenuItemEditAddIncludes() { + if (jMenuItemEditAddIncludes == null) { + jMenuItemEditAddIncludes = new JMenuItem(); + jMenuItemEditAddIncludes.setText("Includes"); + jMenuItemEditAddIncludes.addActionListener(this); + } + return jMenuItemEditAddIncludes; + } + + /** + This method initializes jMenuItemEditAddProtocols + + @return javax.swing.JMenuItem jMenuItemEditAddProtocols + + **/ + private JMenuItem getJMenuItemEditAddProtocols() { + if (jMenuItemEditAddProtocols == null) { + jMenuItemEditAddProtocols = new JMenuItem(); + jMenuItemEditAddProtocols.setText("Protocols"); + jMenuItemEditAddProtocols.addActionListener(this); + } + return jMenuItemEditAddProtocols; + } + + /** + This method initializes jMenuItemEditAddEvents + + @return javax.swing.JMenuItem jMenuItemEditAddEvents + + **/ + private JMenuItem getJMenuItemEditAddEvents() { + if (jMenuItemEditAddEvents == null) { + jMenuItemEditAddEvents = new JMenuItem(); + jMenuItemEditAddEvents.setText("Events"); + jMenuItemEditAddEvents.addActionListener(this); + } + return jMenuItemEditAddEvents; + } + + /** + This method initializes jMenuItemEditAddHobs + + @return javax.swing.JMenuItem jMenuItemEditAddHobs + + **/ + private JMenuItem getJMenuItemEditAddHobs() { + if (jMenuItemEditAddHobs == null) { + jMenuItemEditAddHobs = new JMenuItem(); + jMenuItemEditAddHobs.setText("Hobs"); + jMenuItemEditAddHobs.addActionListener(this); + } + return jMenuItemEditAddHobs; + } + + /** + This method initializes jMenuItemEditAddPPIs + + @return javax.swing.JMenuItem jMenuItemEditAddPPIs + + **/ + private JMenuItem getJMenuItemEditAddPPIs() { + if (jMenuItemEditAddPPIs == null) { + jMenuItemEditAddPPIs = new JMenuItem(); + jMenuItemEditAddPPIs.setText("PPIs"); + jMenuItemEditAddPPIs.addActionListener(this); + } + return jMenuItemEditAddPPIs; + } + + /** + This method initializes jMenuItemEditAddVariables + + @return javax.swing.JMenuItem jMenuItemEditAddVariables + + **/ + private JMenuItem getJMenuItemEditAddVariables() { + if (jMenuItemEditAddVariables == null) { + jMenuItemEditAddVariables = new JMenuItem(); + jMenuItemEditAddVariables.setText("Variables"); + jMenuItemEditAddVariables.addActionListener(this); + } + return jMenuItemEditAddVariables; + } + + /** + This method initializes jMenuItemEditAddBootModes + + @return javax.swing.JMenuItem jMenuItemEditAddBootModes + + **/ + private JMenuItem getJMenuItemAddBootModes() { + if (jMenuItemEditAddBootModes == null) { + jMenuItemEditAddBootModes = new JMenuItem(); + jMenuItemEditAddBootModes.setText("Boot Modes"); + jMenuItemEditAddBootModes.addActionListener(this); + } + return jMenuItemEditAddBootModes; + } + + /** + This method initializes jMenuItemEditAddSystemTables + + @return javax.swing.JMenuItem jMenuItemEditAddSystemTables + + **/ + private JMenuItem getJMenuItemAddSystemTables() { + if (jMenuItemEditAddSystemTables == null) { + jMenuItemEditAddSystemTables = new JMenuItem(); + jMenuItemEditAddSystemTables.setText("System Tables"); + jMenuItemEditAddSystemTables.addActionListener(this); + } + return jMenuItemEditAddSystemTables; + } + + /** + This method initializes jMenuItemEditAddDataHubs + + @return javax.swing.JMenuItem jMenuItemEditAddDataHubs + + **/ + private JMenuItem getJMenuItemEditAddDataHubs() { + if (jMenuItemEditAddDataHubs == null) { + jMenuItemEditAddDataHubs = new JMenuItem(); + jMenuItemEditAddDataHubs.setText("Data Hubs"); + jMenuItemEditAddDataHubs.addActionListener(this); + } + return jMenuItemEditAddDataHubs; + } + + /** + This method initializes jMenuItemEditAddFormsets + + @return javax.swing.JMenuItem jMenuItemEditAddFormsets + + **/ + private JMenuItem getJMenuItemEditAddFormsets() { + if (jMenuItemEditAddFormsets == null) { + jMenuItemEditAddFormsets = new JMenuItem(); + jMenuItemEditAddFormsets.setText("Formsets"); + jMenuItemEditAddFormsets.addActionListener(this); + } + return jMenuItemEditAddFormsets; + } + + /** + This method initializes jMenuItemEditAddGuids + + @return javax.swing.JMenuItem jMenuItemEditAddGuids + + **/ + private JMenuItem getJMenuItemEditAddGuids() { + if (jMenuItemEditAddGuids == null) { + jMenuItemEditAddGuids = new JMenuItem(); + jMenuItemEditAddGuids.setText("Guids"); + jMenuItemEditAddGuids.addActionListener(this); + } + return jMenuItemEditAddGuids; + } + + /** + This method initializes jMenuItemEditAddExterns + + @return javax.swing.JMenuItem jMenuItemEditAddExterns + + **/ + private JMenuItem getJMenuItemEditAddExterns() { + if (jMenuItemEditAddExterns == null) { + jMenuItemEditAddExterns = new JMenuItem(); + jMenuItemEditAddExterns.setText("Externs"); + jMenuItemEditAddExterns.addActionListener(this); + } + return jMenuItemEditAddExterns; + } + + /** + This method initializes jMenuItemEditAddPCDs + + @return javax.swing.JMenuItem jMenuItemEditAddPCDs + + **/ + private JMenuItem getJMenuItemEditAddPCDs() { + if (jMenuItemEditAddPCDs == null) { + jMenuItemEditAddPCDs = new JMenuItem(); + jMenuItemEditAddPCDs.setText("PCDs"); + jMenuItemEditAddPCDs.addActionListener(this); + } + return jMenuItemEditAddPCDs; + } + + /** + This method initializes jDesktopPane + + @return javax.swing.JDesktopPane jDesktopPane + + **/ + private JDesktopPane getJDesktopPane() { + if (jDesktopPane == null) { + jDesktopPane = new JDesktopPane(); + jDesktopPane.setBounds(new java.awt.Rectangle(295, 1, 500, 515)); + jDesktopPane.setDesktopManager(iDesktopManager); + } + return jDesktopPane; + } + + /** + This method initializes jScrollPaneTree + + @return javax.swing.JScrollPane jScrollPaneTree + + **/ + private JScrollPane getJScrollPaneTree() { + if (jScrollPaneTree == null) { + jScrollPaneTree = new JScrollPane(); + jScrollPaneTree.setBounds(new java.awt.Rectangle(0, 1, 290, 545)); + jScrollPaneTree.setViewportView(getITree()); + } + return jScrollPaneTree; + } + + /** + This method initializes iTree + + @return org.tianocore.packaging.common.ui.ITree iTree + + **/ + private ITree getITree() { + // + //Before open a real module, use an empty root node for the tree + // + IDefaultMutableTreeNode root = new IDefaultMutableTreeNode("No Msa/Mbd file opened", -1, -1); + iTree = new ITree(root); + return iTree; + } + + /** + This method initializes jMenuHelp + + @return javax.swing.JMenu jMenuHelp + + **/ + private JMenu getJMenuHelp() { + if (jMenuHelp == null) { + jMenuHelp = new JMenu(); + jMenuHelp.setText("Help"); + jMenuHelp.add(getJMenuItemHelpAbout()); + } + return jMenuHelp; + } + + /** + This method initializes jMenuItemHelpAbout + + @return javax.swing.JMenuItem jMenuItemHelpAbout + + **/ + private JMenuItem getJMenuItemHelpAbout() { + if (jMenuItemHelpAbout == null) { + jMenuItemHelpAbout = new JMenuItem(); + jMenuItemHelpAbout.setText("About..."); + jMenuItemHelpAbout.addActionListener(this); + } + return jMenuItemHelpAbout; + } + + /** + This method initializes jMenuEditAdd + + @return javax.swing.JMenu jMenuEditAdd + + **/ + private JMenu getJMenu() { + if (jMenuEditAdd == null) { + jMenuEditAdd = new JMenu(); + jMenuEditAdd.setText("Add"); + // + //Add all menu items of menu "Add" + // + jMenuEditAdd.add(getJMenuItemEditAddLibraries()); + jMenuEditAdd.add(getJMenuItemEditAddLibraryClassDefinitions()); + jMenuEditAdd.add(getJMenuItemEditAddSourceFiles()); + jMenuEditAdd.add(getJMenuItemEditAddIncludes()); + jMenuEditAdd.add(getJMenuItemEditAddProtocols()); + jMenuEditAdd.add(getJMenuItemEditAddEvents()); + jMenuEditAdd.add(getJMenuItemEditAddHobs()); + jMenuEditAdd.add(getJMenuItemEditAddPPIs()); + jMenuEditAdd.add(getJMenuItemEditAddVariables()); + jMenuEditAdd.add(getJMenuItemAddBootModes()); + jMenuEditAdd.add(getJMenuItemAddSystemTables()); + jMenuEditAdd.add(getJMenuItemEditAddDataHubs()); + jMenuEditAdd.add(getJMenuItemEditAddFormsets()); + jMenuEditAdd.add(getJMenuItemEditAddGuids()); + jMenuEditAdd.add(getJMenuItemEditAddExterns()); + jMenuEditAdd.add(getJMenuItemEditAddPCDs()); + jMenuEditAdd.setEnabled(false); + } + return jMenuEditAdd; + } + + /** + This method initializes jMenuItemEditDelete + + @return javax.swing.JMenuItem jMenuItemEditDelete + + **/ + private JMenuItem getJMenuItemEditDelete() { + if (jMenuItemEditDelete == null) { + jMenuItemEditDelete = new JMenuItem(); + jMenuItemEditDelete.setText("Delete"); + jMenuItemEditDelete.addActionListener(this); + // + //Disabled when no module is open + // + jMenuItemEditDelete.setEnabled(false); + } + return jMenuItemEditDelete; + } + + /** + This method initializes jMenuItemEditUpdate + + @return javax.swing.JMenuItem jMenuItemEditUpdate + + **/ + private JMenuItem getJMenuItemEditUpdate() { + if (jMenuItemEditUpdate == null) { + jMenuItemEditUpdate = new JMenuItem(); + jMenuItemEditUpdate.setText("Update"); + jMenuItemEditUpdate.addActionListener(this); + // + //Disabled when no module is open + // + jMenuItemEditUpdate.setEnabled(false); + } + return jMenuItemEditUpdate; + } + + /** + This method initializes jPopupMenu + + @return javax.swing.JPopupMenu jPopupMenu + + **/ + private JPopupMenu getJPopupMenu() { + if (jPopupMenu == null) { + jPopupMenu = new JPopupMenu(); + // + //Add menu items of popup menu + // + jPopupMenu.add(getJMenuItemPopupAdd()); + jPopupMenu.add(getJMenuItemPopupUpdate()); + jPopupMenu.add(getJMenuItemPopupDelete()); + jPopupMenu.setBorder(new BevelBorder(BevelBorder.RAISED)); + jPopupMenu.addMouseListener(this); + } + return jPopupMenu; + } + + /** + This method initializes jMenuItemPopupAdd + + @return javax.swing.JMenuItem jMenuItemPopupAdd + + **/ + private JMenuItem getJMenuItemPopupAdd() { + if (jMenuItemPopupAdd == null) { + jMenuItemPopupAdd = new JMenuItem(); + jMenuItemPopupAdd.setText("Add"); + jMenuItemPopupAdd.addActionListener(this); + jMenuItemPopupAdd.setEnabled(false); + } + return jMenuItemPopupAdd; + } + + /** + This method initializes jMenuItemPopupUpdate + + @return javax.swing.JMenuItem jMenuItemPopupUpdate + + **/ + private JMenuItem getJMenuItemPopupUpdate() { + if (jMenuItemPopupUpdate == null) { + jMenuItemPopupUpdate = new JMenuItem(); + jMenuItemPopupUpdate.setText("Update"); + jMenuItemPopupUpdate.addActionListener(this); + jMenuItemPopupUpdate.setEnabled(false); + } + return jMenuItemPopupUpdate; + } + + /** + This method initializes jMenuItemPopupDelete + + @return javax.swing.JMenuItem jMenuItemPopupDelete + + **/ + private JMenuItem getJMenuItemPopupDelete() { + if (jMenuItemPopupDelete == null) { + jMenuItemPopupDelete = new JMenuItem(); + jMenuItemPopupDelete.setText("Delete"); + jMenuItemPopupDelete.addActionListener(this); + jMenuItemPopupDelete.setEnabled(false); + } + return jMenuItemPopupDelete; + } + + /** + This method initializes jMenuModuleNew + + @return javax.swing.JMenu jMenuModuleNew + + **/ + private JMenu getJMenuModuleNew() { + if (jMenuModuleNew == null) { + jMenuModuleNew = new JMenu(); + jMenuModuleNew.setText("New"); + jMenuModuleNew.add(getJMenuItemModuleNewModule()); + jMenuModuleNew.add(getJMenuItemModuleNewModuleBuildDescription()); + jMenuModuleNew.add(getJMenuItemModuleNewLibraryModule()); + jMenuModuleNew.add(getJMenuItemModuleNewLibraryModuleBuildDescription()); + } + return jMenuModuleNew; + } + + /** + This method initializes jMenuItemModuleOpenModule + + @return javax.swing.JMenuItem jMenuItemModuleOpenModule + + **/ + private JMenuItem getJMenuItemModuleOpenModule() { + if (jMenuItemModuleOpenModule == null) { + jMenuItemModuleOpenModule = new JMenuItem(); + jMenuItemModuleOpenModule.setText("Module (.msa)"); + jMenuItemModuleOpenModule.addActionListener(this); + } + return jMenuItemModuleOpenModule; + } + + /** + This method initializes jMenuItemFileNewModuleBuildDescription + + @return javax.swing.JMenuItem jMenuItemModuleNewModuleBuildDescription + + **/ + private JMenuItem getJMenuItemModuleNewModuleBuildDescription() { + if (jMenuItemModuleNewModuleBuildDescription == null) { + jMenuItemModuleNewModuleBuildDescription = new JMenuItem(); + jMenuItemModuleNewModuleBuildDescription.setText("Module Build Description (.mbd)"); + jMenuItemModuleNewModuleBuildDescription.addActionListener(this); + } + return jMenuItemModuleNewModuleBuildDescription; + } + + /** + This method initializes jMenuItemFileNewLibraryModule + + @return javax.swing.JMenuItem jMenuItemModuleNewLibraryModule + + **/ + private JMenuItem getJMenuItemModuleNewLibraryModule() { + if (jMenuItemModuleNewLibraryModule == null) { + jMenuItemModuleNewLibraryModule = new JMenuItem(); + jMenuItemModuleNewLibraryModule.setText("Library Module (*.msa)"); + jMenuItemModuleNewLibraryModule.addActionListener(this); + } + return jMenuItemModuleNewLibraryModule; + } + + /** + This method initializes jMenuItemFileNewLibraryModuleBuildDescription + + @return javax.swing.JMenuItem jMenuItemModuleNewLibraryModuleBuildDescription + + **/ + private JMenuItem getJMenuItemModuleNewLibraryModuleBuildDescription() { + if (jMenuItemModuleNewLibraryModuleBuildDescription == null) { + jMenuItemModuleNewLibraryModuleBuildDescription = new JMenuItem(); + jMenuItemModuleNewLibraryModuleBuildDescription.setText("Library Module Build Description (.mbd)"); + jMenuItemModuleNewLibraryModuleBuildDescription.addActionListener(this); + } + return jMenuItemModuleNewLibraryModuleBuildDescription; + } + + /** + This method initializes jMenuOpen + + @return javax.swing.JMenu jMenuModuleOpen + + **/ + private JMenu getJMenuModuleOpen() { + if (jMenuModuleOpen == null) { + jMenuModuleOpen = new JMenu(); + jMenuModuleOpen.setText("Open"); + jMenuModuleOpen.add(getJMenuItemModuleOpenModule()); + jMenuModuleOpen.add(getJMenuItemModuleOpenModuleBuildDescription()); + jMenuModuleOpen.add(getJMenuItemModuleOpenLibraryModule()); + jMenuModuleOpen.add(getJMenuItemModuleOpenLibraryModuleBuildDescription()); + } + return jMenuModuleOpen; + } + + /** + This method initializes jMenuItemFileOpenModuleBuildDescription + + @return javax.swing.JMenuItem jMenuItemModuleOpenModuleBuildDescription + + **/ + private JMenuItem getJMenuItemModuleOpenModuleBuildDescription() { + if (jMenuItemModuleOpenModuleBuildDescription == null) { + jMenuItemModuleOpenModuleBuildDescription = new JMenuItem(); + jMenuItemModuleOpenModuleBuildDescription.setText("Module Build Description (.mbd)"); + jMenuItemModuleOpenModuleBuildDescription.addActionListener(this); + } + return jMenuItemModuleOpenModuleBuildDescription; + } + + /** + This method initializes jMenuItemFileOpenLibraryModule + + @return javax.swing.JMenuItem jMenuItemModuleOpenLibraryModule + + **/ + private JMenuItem getJMenuItemModuleOpenLibraryModule() { + if (jMenuItemModuleOpenLibraryModule == null) { + jMenuItemModuleOpenLibraryModule = new JMenuItem(); + jMenuItemModuleOpenLibraryModule.setText("Library Module (.msa)"); + jMenuItemModuleOpenLibraryModule.addActionListener(this); + } + return jMenuItemModuleOpenLibraryModule; + } + + /** + This method initializes jMenuItemFileOpenLibraryModuleBuildDescription + + @return javax.swing.JMenuItem jMenuItemModuleOpenLibraryModuleBuildDescription + + **/ + private JMenuItem getJMenuItemModuleOpenLibraryModuleBuildDescription() { + if (jMenuItemModuleOpenLibraryModuleBuildDescription == null) { + jMenuItemModuleOpenLibraryModuleBuildDescription = new JMenuItem(); + jMenuItemModuleOpenLibraryModuleBuildDescription.setText("Library Module Build Description (.mbd)"); + jMenuItemModuleOpenLibraryModuleBuildDescription.addActionListener(this); + } + return jMenuItemModuleOpenLibraryModuleBuildDescription; + } + + /** + This method initializes jMenuItemFileSave + + @return javax.swing.JMenuItem jMenuItemModuleSave + + **/ + private JMenuItem getJMenuItemModuleSave() { + if (jMenuItemModuleSave == null) { + jMenuItemModuleSave = new JMenuItem(); + jMenuItemModuleSave.setText("Save"); + jMenuItemModuleSave.addActionListener(this); + jMenuItemModuleSave.setEnabled(false); + } + return jMenuItemModuleSave; + } + + /** + This method initializes jMenuItemModuleClose + + @return javax.swing.JMenuItem jMenuItemModuleClose + + **/ + private JMenuItem getJMenuItemModuleClose() { + if (jMenuItemModuleClose == null) { + jMenuItemModuleClose = new JMenuItem(); + jMenuItemModuleClose.setText("Close"); + jMenuItemModuleClose.setEnabled(false); + jMenuItemModuleClose.addActionListener(this); + } + return jMenuItemModuleClose; + } + + /** + This method initializes jMenuTools + Reserved + + @return javax.swing.JMenu jMenuTools + + **/ + private JMenu getJMenuTools() { + if (jMenuTools == null) { + jMenuTools = new JMenu(); + jMenuTools.setText("Tools"); + jMenuTools.addActionListener(this); + jMenuTools.setEnabled(false); + } + return jMenuTools; + } + + /** + This method initializes jMenuWindow + Reserved + + @return javax.swing.JMenu jMenuWindow + + **/ + private JMenu getJMenuWindow() { + if (jMenuWindow == null) { + jMenuWindow = new JMenu(); + jMenuWindow.setText("Window"); + jMenuWindow.setEnabled(false); + jMenuWindow.addActionListener(this); + } + return jMenuWindow; + } + + /** + This method initializes jMenuItemEditAddLibraries + + @return javax.swing.JMenuItem jMenuItemEditAddLibraries + + **/ + private JMenuItem getJMenuItemEditAddLibraries() { + if (jMenuItemEditAddLibraries == null) { + jMenuItemEditAddLibraries = new JMenuItem(); + jMenuItemEditAddLibraries.setText("Libraries"); + jMenuItemEditAddLibraries.addActionListener(this); + } + return jMenuItemEditAddLibraries; + } + + /** + This method initializes jPanelOperation + + @return javax.swing.JPanel jPanelOperation + + **/ + private JPanel getJPanelOperation() { + if (jPanelOperation == null) { + jPanelOperation = new JPanel(); + jPanelOperation.setLayout(null); + jPanelOperation.setBounds(new java.awt.Rectangle(295, 520, 500, 25)); + jPanelOperation.add(getJButtonOk(), null); + jPanelOperation.add(getJButtonCancel(), null); + } + return jPanelOperation; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setBounds(new java.awt.Rectangle(395, 2, 90, 20)); + jButtonOk.setText("Ok"); + jButtonOk.setEnabled(false); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setBounds(new java.awt.Rectangle(395, 2, 90, 20)); + jButtonCancel.setText("Cancel"); + jButtonCancel.setEnabled(false); + jButtonCancel.addActionListener(this); + jButtonCancel.setVisible(false); + } + return jButtonCancel; + } + + /* (non-Javadoc) + * @see org.tianocore.packaging.common.ui.IFrame#main(java.lang.String[]) + * + * Main class, start the GUI + * + */ + public static void main(String[] args) { + ModuleMain module = new ModuleMain(); + module.setVisible(true); + } + + /** + This is the default constructor + + **/ + public ModuleMain() { + super(); + init(); + } + + /** + This method initializes this + + + **/ + private void init() { + // + // Check if exists WORKSPACE + // + // + if (!ws.checkCurrentWorkspace()) { + JOptionPane.showConfirmDialog(null, "You haven't a workspace yet. Please setup first.", "Warning", + JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE); + this.dispose(); + System.exit(0); + } + + this.setSize(800, 600); + this.setResizable(false); + this.setJMenuBar(getjJMenuBar()); + this.setContentPane(getJContentPane()); + this.setTitle(windowTitle + "- [" + ws.getCurrentWorkspace() + "]"); + this.setExitType(1); + this.centerWindow(); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJPanelOperation(), null); + jContentPane.add(getJDesktopPane(), null); + jContentPane.add(getJScrollPaneTree(), null); + jContentPane.add(getJPopupMenu(), null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + // + // Open relevant frame via clicking different menu items + // + if (arg0.getSource() == jMenuItemHelpAbout) { + ModuleAbout ma = new ModuleAbout(); + ma.setEdited(false); + } + + if (arg0.getSource() == jMenuItemEditAddLibraries) { + showLibraries(ModuleMain.ADD, IDefaultMutableTreeNode.LIBRARIES, -1); + } + + if (arg0.getSource() == jMenuItemEditAddLibraryClassDefinitions) { + showLibraryClassDefinitions(ModuleMain.ADD, IDefaultMutableTreeNode.LIBRARYCLASSDEFINITIONS); + } + + if (arg0.getSource() == jMenuItemEditAddSourceFiles) { + showSourceFiles(ModuleMain.ADD, IDefaultMutableTreeNode.SOURCEFILES, -1); + } + + if (arg0.getSource() == jMenuItemEditAddIncludes) { + showIncludes(ModuleMain.ADD, IDefaultMutableTreeNode.INCLUDES, -1); + } + + if (arg0.getSource() == jMenuItemEditAddProtocols) { + showProtocols(ModuleMain.ADD, IDefaultMutableTreeNode.PROTOCOLS, -1); + } + + if (arg0.getSource() == jMenuItemEditAddEvents) { + showEvents(ModuleMain.ADD, IDefaultMutableTreeNode.EVENTS, -1); + } + + if (arg0.getSource() == jMenuItemEditAddHobs) { + showHobs(ModuleMain.ADD, IDefaultMutableTreeNode.HOBS, -1); + } + + if (arg0.getSource() == jMenuItemEditAddPPIs) { + showPpis(ModuleMain.ADD, IDefaultMutableTreeNode.PPIS, -1); + } + + if (arg0.getSource() == jMenuItemEditAddVariables) { + showVariables(ModuleMain.ADD, IDefaultMutableTreeNode.VARIABLES, -1); + } + + if (arg0.getSource() == jMenuItemEditAddBootModes) { + showBootModes(ModuleMain.ADD, IDefaultMutableTreeNode.BOOTMODES, -1); + } + + if (arg0.getSource() == jMenuItemEditAddSystemTables) { + showSystemTables(ModuleMain.ADD, IDefaultMutableTreeNode.SYSTEMTABLES, -1); + } + + if (arg0.getSource() == jMenuItemEditAddDataHubs) { + showDataHubs(ModuleMain.ADD, IDefaultMutableTreeNode.DATAHUBS, -1); + } + + if (arg0.getSource() == jMenuItemEditAddFormsets) { + showFormsets(ModuleMain.ADD, IDefaultMutableTreeNode.FORMSETS, -1); + } + + if (arg0.getSource() == jMenuItemEditAddGuids) { + showGuids(ModuleMain.ADD, IDefaultMutableTreeNode.GUIDS, -1); + } + + if (arg0.getSource() == jMenuItemEditAddExterns) { + showExterns(ModuleMain.ADD, IDefaultMutableTreeNode.EXTERNS, -1); + } + + if (arg0.getSource() == jMenuItemEditAddPCDs) { + showPCDs(ModuleMain.ADD, IDefaultMutableTreeNode.PCDS, -1); + } + + if (arg0.getSource() == jMenuItemModuleNewModule) { + this.closeCurrentModule(); + showMsaHeader(ModuleMain.ADD); + } + + if (arg0.getSource() == jMenuItemModuleNewModuleBuildDescription) { + this.closeCurrentModule(); + showMbdHeader(ModuleMain.ADD); + } + + if (arg0.getSource() == jMenuItemModuleNewLibraryModule) { + this.closeCurrentModule(); + showMlsaHeader(ModuleMain.ADD); + } + + if (arg0.getSource() == jMenuItemModuleNewLibraryModuleBuildDescription) { + this.closeCurrentModule(); + showMlbdHeader(ModuleMain.ADD); + } + + // + // Open Msa, Mbd, Lmsa and Lmbd + // + if (arg0.getSource() == jMenuItemModuleOpenModule) { + openFile(1, 1); + } + + if (arg0.getSource() == jMenuItemModuleOpenModuleBuildDescription) { + openFile(1, 2); + } + + if (arg0.getSource() == jMenuItemModuleOpenLibraryModule) { + openFile(1, 3); + } + + if (arg0.getSource() == jMenuItemModuleOpenLibraryModuleBuildDescription) { + openFile(1, 4); + } + + // + // Listen popup menu items + // + if (arg0.getSource() == jMenuItemPopupAdd) { + int intCategory = iTree.getSelectCategory(); + int intLocation = iTree.getSelectLoaction(); + addCurrentModule(intCategory, intLocation); + } + + if (arg0.getSource() == jMenuItemPopupUpdate || arg0.getSource() == jMenuItemEditUpdate) { + int intCategory = iTree.getSelectCategory(); + int intLocation = iTree.getSelectLoaction(); + updateCurrentModule(intCategory, intLocation); + } + + if (arg0.getSource() == jMenuItemPopupDelete || arg0.getSource() == jMenuItemEditDelete) { + int intCategory = iTree.getSelectCategory(); + int intLocation = iTree.getSelectLoaction(); + deleteCurrentModule(intCategory, intLocation); + } + + if (arg0.getSource() == jMenuItemModuleExit) { + this.onExit(); + } + + if (arg0.getSource() == jMenuItemModuleClose) { + closeCurrentModule(); + } + + if (arg0.getSource() == jMenuItemModuleSaveAs) { + saveAsCurrentModule(); + } + + if (arg0.getSource() == jMenuItemModuleSave) { + saveCurrentModule(); + } + + if (arg0.getSource() == jButtonOk) { + save(); + } + + if (arg0.getSource() == jButtonCancel) { + + } + } + + /** + Open file + + @param intOperationType Open - 1 or Save - 2 + @param intFileType Msa - 1, Mbd - 2, Lmsa - 3, Lmbd - 4 + @return opened file path + + **/ + private void openFile(int intOperationType, int intFileType) { + String strCurrentPath = ""; + if (this.currentModule == "") { + strCurrentPath = ws.getCurrentWorkspace(); + } else { + strCurrentPath = this.currentModule + .substring( + 0, + this.currentModule + .lastIndexOf(System + .getProperty("file.separator"))); + } + + JFileChooser fc = new JFileChooser(strCurrentPath); + fc.setAcceptAllFileFilterUsed(false); + switch (intOperationType) { + case 1: + fc.setDialogTitle("Open"); + break; + case 2: + fc.setDialogTitle("Save As"); + break; + } + // + // Config File Filter via different file types + // + switch (intFileType) { + case 1: + fc.addChoosableFileFilter(new IFileFilter("msa")); + break; + case 2: + fc.addChoosableFileFilter(new IFileFilter("mbd")); + break; + case 3: + fc.addChoosableFileFilter(new IFileFilter("msa")); + break; + case 4: + fc.addChoosableFileFilter(new IFileFilter("mbd")); + break; + } + + int result = fc.showOpenDialog(new JPanel()); + // + // Open relevanf file after click "OK" + // + if (result == JFileChooser.APPROVE_OPTION) { + switch (intOperationType) { + case 1: + closeCurrentModule(); + switch (intFileType) { + case 1: + openMsaFile(fc.getSelectedFile().getPath()); + break; + case 2: + openMbdFile(fc.getSelectedFile().getPath()); + break; + case 3: + openMlsaFile(fc.getSelectedFile().getPath()); + break; + case 4: + openMlbdFile(fc.getSelectedFile().getPath()); + break; + } + break; + case 2: + switch (intFileType) { + case 1: + this.saveFileName = fc.getSelectedFile().getPath(); + break; + case 2: + this.saveFileName = fc.getSelectedFile().getPath(); + break; + case 3: + this.saveFileName = fc.getSelectedFile().getPath(); + break; + case 4: + this.saveFileName = fc.getSelectedFile().getPath(); + break; + } + break; + } + } else { + if (intOperationType == 2) { + this.saveFileName = ""; + } + } + } + + /** + Open specificed Msa file and read its content + + @param strMsaFilePath The input data of Msa File Path + + **/ + private void openMsaFile(String strMsaFilePath) { + Log.log("Open Msa", strMsaFilePath); + try { + File msaFile = new File(strMsaFilePath); + xmlMsaDoc = (ModuleSurfaceAreaDocument) XmlObject.Factory.parse(msaFile); + this.currentModule = strMsaFilePath; + this.saveFileName = strMsaFilePath; + this.currentModuleType = 1; + } catch (IOException e) { + Log.err("Open Msa " + strMsaFilePath, e.getMessage()); + return; + } catch (XmlException e) { + Log.err("Open Msa " + strMsaFilePath, e.getMessage()); + return; + } catch (Exception e) { + Log.err("Open Msa " + strMsaFilePath, e.getMessage()); + return; + } + + xmlmh = xmlMsaDoc.getModuleSurfaceArea().getMsaHeader(); + xmllcd = xmlMsaDoc.getModuleSurfaceArea().getLibraryClassDefinitions(); + xmlsf = xmlMsaDoc.getModuleSurfaceArea().getSourceFiles(); + xmlic = xmlMsaDoc.getModuleSurfaceArea().getIncludes(); + xmlpl = xmlMsaDoc.getModuleSurfaceArea().getProtocols(); + xmlen = xmlMsaDoc.getModuleSurfaceArea().getEvents(); + xmlhob = xmlMsaDoc.getModuleSurfaceArea().getHobs(); + xmlppi = xmlMsaDoc.getModuleSurfaceArea().getPPIs(); + xmlvb = xmlMsaDoc.getModuleSurfaceArea().getVariables(); + xmlbm = xmlMsaDoc.getModuleSurfaceArea().getBootModes(); + xmlst = xmlMsaDoc.getModuleSurfaceArea().getSystemTables(); + xmldh = xmlMsaDoc.getModuleSurfaceArea().getDataHubs(); + xmlfs = xmlMsaDoc.getModuleSurfaceArea().getFormsets(); + xmlgu = xmlMsaDoc.getModuleSurfaceArea().getGuids(); + xmlet = xmlMsaDoc.getModuleSurfaceArea().getExterns(); + xmlpcd = xmlMsaDoc.getModuleSurfaceArea().getPCDs(); + xmlbo = xmlMsaDoc.getModuleSurfaceArea().getBuildOptions(); + + this.showMsaHeader(ModuleMain.VIEW); + reloadTreeAndTable(ModuleMain.OPENED); + jMenuEditAdd.setEnabled(true); + } + + /** + Open specificed Mbd file and read its content + + @param strMbdFilePath The input data of Mbd File Path + + **/ + private void openMbdFile(String strMbdFilePath) { + Log.log("Open Mbd", strMbdFilePath); + try { + File mbdFile = new File(strMbdFilePath); + xmlMbdDoc = (ModuleBuildDescriptionDocument) XmlObject.Factory.parse(mbdFile); + this.currentModule = strMbdFilePath; + this.saveFileName = strMbdFilePath; + this.currentModuleType = 2; + } catch (IOException e) { + Log.err("Open Mbd " + strMbdFilePath, e.getMessage()); + return; + } catch (XmlException e) { + Log.err("Open Mbd " + strMbdFilePath, e.getMessage()); + return; + } catch (Exception e) { + Log.err("Open Mbd " + strMbdFilePath, e.getMessage()); + return; + } + + xmlmbdh = xmlMbdDoc.getModuleBuildDescription().getMbdHeader(); + xmllib = xmlMbdDoc.getModuleBuildDescription().getLibraries(); + xmlsf = xmlMbdDoc.getModuleBuildDescription().getSourceFiles(); + xmlic = xmlMbdDoc.getModuleBuildDescription().getIncludes(); + xmlpl = xmlMbdDoc.getModuleBuildDescription().getProtocols(); + xmlen = xmlMbdDoc.getModuleBuildDescription().getEvents(); + xmlhob = xmlMbdDoc.getModuleBuildDescription().getHobs(); + xmlppi = xmlMbdDoc.getModuleBuildDescription().getPPIs(); + xmlvb = xmlMbdDoc.getModuleBuildDescription().getVariables(); + xmlbm = xmlMbdDoc.getModuleBuildDescription().getBootModes(); + xmlst = xmlMbdDoc.getModuleBuildDescription().getSystemTables(); + xmldh = xmlMbdDoc.getModuleBuildDescription().getDataHubs(); + xmlfs = xmlMbdDoc.getModuleBuildDescription().getFormsets(); + xmlgu = xmlMbdDoc.getModuleBuildDescription().getGuids(); + xmlet = xmlMbdDoc.getModuleBuildDescription().getExterns(); + xmlpcd = xmlMbdDoc.getModuleBuildDescription().getPCDs(); + xmlbo = xmlMbdDoc.getModuleBuildDescription().getBuildOptions(); + + this.showMbdHeader(ModuleMain.VIEW); + reloadTreeAndTable(ModuleMain.OPENED); + jMenuEditAdd.setEnabled(true); + } + + /** + Open specificed Mlsa file and read its content + + @param strMlsaFilePath The input data of Mlsa File Path + + **/ + private void openMlsaFile(String strMlsaFilePath) { + Log.log("Open Mlsa", strMlsaFilePath); + try { + File mlsaFile = new File(strMlsaFilePath); + xmlMlsaDoc = (LibraryModuleSurfaceAreaDocument) XmlObject.Factory.parse(mlsaFile); + this.currentModule = strMlsaFilePath; + this.saveFileName = strMlsaFilePath; + this.currentModuleType = 3; + } catch (IOException e) { + Log.err("Open Mlsa " + strMlsaFilePath, e.getMessage()); + return; + } catch (XmlException e) { + Log.err("Open Mlsa " + strMlsaFilePath, e.getMessage()); + return; + } catch (Exception e) { + Log.err("Open Mlsa " + strMlsaFilePath, e.getMessage()); + return; + } + + xmlmlh = xmlMlsaDoc.getLibraryModuleSurfaceArea().getMsaLibHeader(); + xmllcd = xmlMlsaDoc.getLibraryModuleSurfaceArea().getLibraryClassDefinitions(); + xmlsf = xmlMlsaDoc.getLibraryModuleSurfaceArea().getSourceFiles(); + xmlic = xmlMlsaDoc.getLibraryModuleSurfaceArea().getIncludes(); + xmlpl = xmlMlsaDoc.getLibraryModuleSurfaceArea().getProtocols(); + xmlen = xmlMlsaDoc.getLibraryModuleSurfaceArea().getEvents(); + xmlhob = xmlMlsaDoc.getLibraryModuleSurfaceArea().getHobs(); + xmlppi = xmlMlsaDoc.getLibraryModuleSurfaceArea().getPPIs(); + xmlvb = xmlMlsaDoc.getLibraryModuleSurfaceArea().getVariables(); + xmlbm = xmlMlsaDoc.getLibraryModuleSurfaceArea().getBootModes(); + xmlst = xmlMlsaDoc.getLibraryModuleSurfaceArea().getSystemTables(); + xmldh = xmlMlsaDoc.getLibraryModuleSurfaceArea().getDataHubs(); + xmlfs = xmlMlsaDoc.getLibraryModuleSurfaceArea().getFormsets(); + xmlgu = xmlMlsaDoc.getLibraryModuleSurfaceArea().getGuids(); + xmlet = xmlMlsaDoc.getLibraryModuleSurfaceArea().getExterns(); + xmlpcd = xmlMlsaDoc.getLibraryModuleSurfaceArea().getPCDs(); + xmlbo = xmlMlsaDoc.getLibraryModuleSurfaceArea().getBuildOptions(); + + this.showMlsaHeader(ModuleMain.VIEW); + reloadTreeAndTable(ModuleMain.OPENED); + jMenuEditAdd.setEnabled(true); + } + + /** + Open specificed Mlbd file and read its content + + @param strMlbdFilePath The input data of Mlbd File Path + + **/ + private void openMlbdFile(String strMlbdFilePath) { + Log.log("Open Mlbd", strMlbdFilePath); + try { + File mlbdFile = new File(strMlbdFilePath); + xmlMlbdDoc = (LibraryModuleBuildDescriptionDocument) XmlObject.Factory.parse(mlbdFile); + this.currentModule = strMlbdFilePath; + this.saveFileName = strMlbdFilePath; + this.currentModuleType = 4; + } catch (IOException e) { + Log.err("Open Mlbd " + strMlbdFilePath, e.getMessage()); + return; + } catch (XmlException e) { + Log.err("Open Mlbd " + strMlbdFilePath, e.getMessage()); + return; + } catch (Exception e) { + Log.err("Open Mlbd " + strMlbdFilePath, e.getMessage()); + return; + } + + xmlmlbdh = xmlMlbdDoc.getLibraryModuleBuildDescription().getMbdLibHeader(); + xmllib = xmlMlbdDoc.getLibraryModuleBuildDescription().getLibraries(); + xmlsf = xmlMlbdDoc.getLibraryModuleBuildDescription().getSourceFiles(); + xmlic = xmlMlbdDoc.getLibraryModuleBuildDescription().getIncludes(); + xmlpl = xmlMlbdDoc.getLibraryModuleBuildDescription().getProtocols(); + xmlen = xmlMlbdDoc.getLibraryModuleBuildDescription().getEvents(); + xmlhob = xmlMlbdDoc.getLibraryModuleBuildDescription().getHobs(); + xmlppi = xmlMlbdDoc.getLibraryModuleBuildDescription().getPPIs(); + xmlvb = xmlMlbdDoc.getLibraryModuleBuildDescription().getVariables(); + xmlbm = xmlMlbdDoc.getLibraryModuleBuildDescription().getBootModes(); + xmlst = xmlMlbdDoc.getLibraryModuleBuildDescription().getSystemTables(); + xmldh = xmlMlbdDoc.getLibraryModuleBuildDescription().getDataHubs(); + xmlfs = xmlMlbdDoc.getLibraryModuleBuildDescription().getFormsets(); + xmlgu = xmlMlbdDoc.getLibraryModuleBuildDescription().getGuids(); + xmlet = xmlMlbdDoc.getLibraryModuleBuildDescription().getExterns(); + xmlpcd = xmlMlbdDoc.getLibraryModuleBuildDescription().getPCDs(); + xmlbo = xmlMlbdDoc.getLibraryModuleBuildDescription().getBuildOptions(); + + this.showMlbdHeader(ModuleMain.VIEW); + reloadTreeAndTable(ModuleMain.OPENED); + jMenuEditAdd.setEnabled(true); + } + + /** + Create an empty tree if no file is open + + **/ + private void makeEmptyTree() { + dmtnRoot = new IDefaultMutableTreeNode("No Msa/Mbd file opened", -1, -1); + iTree = new ITree(dmtnRoot); + jScrollPaneTree.setViewportView(iTree); + } + + /** + Create the tree to display all components of current open file. + First to check if the component is null or not + If not null, hangs it to the tree + If null, skip it + + **/ + private void makeTree() { + iTree.removeAll(); + + // + //Make an empty tree when closing + // + if (this.currentModuleType == 0) { + makeEmptyTree(); + return; + } + + // + //Msa File + // + if (this.currentModuleType == 1) { + // + //Add MsaHeader Node + // + if (xmlmh != null) { + dmtnRoot = new IDefaultMutableTreeNode(xmlmh.getBaseName().getStringValue(), + IDefaultMutableTreeNode.MSA_HEADER, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE); + } else { + makeEmptyTree(); + return; + } + + // + //Add LibraryClassDefinitions Node + // + if (xmllcd != null && xmllcd.getLibraryClassList().size() > 0) { + IDefaultMutableTreeNode libraryClassDefinitions = new IDefaultMutableTreeNode( + "Library Class Definitions", + IDefaultMutableTreeNode.LIBRARYCLASSDEFINITIONS, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE); + for (int indexI = 0; indexI < xmllcd.getLibraryClassList().size(); indexI++) { + libraryClassDefinitions + .add(new IDefaultMutableTreeNode( + xmllcd.getLibraryClassArray(indexI) + .getStringValue(), + IDefaultMutableTreeNode.LIBRARY_CLASS_DEFINITION, + IDefaultMutableTreeNode.OPERATION_NULL)); + } + dmtnRoot.add(libraryClassDefinitions); + } + } + + // + //Mbd File + // + if (this.currentModuleType == 2) { + // + //Add MsaHeader Node + // + if (xmlmbdh != null) { + dmtnRoot = new IDefaultMutableTreeNode(xmlmbdh.getBaseName().getStringValue(), + IDefaultMutableTreeNode.MBD_HEADER, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE); + } else { + makeEmptyTree(); + return; + } + + // + //Add Libraries Node + // + if (xmllib != null) { + IDefaultMutableTreeNode libraries = new IDefaultMutableTreeNode( + "Libraries", + IDefaultMutableTreeNode.LIBRARIES, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmllib.getArchList().size() > 0) { + IDefaultMutableTreeNode librariesArch = new IDefaultMutableTreeNode( + "Arch", + IDefaultMutableTreeNode.LIBRARIES_ARCH, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + for (int indexI = 0; indexI < xmllib.getArchList().size(); indexI++) { + librariesArch.add(new IDefaultMutableTreeNode(xmllib.getArchArray(indexI).getArchType() + .toString(), + IDefaultMutableTreeNode.LIBRARIES_ARCH_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + libraries.add(librariesArch); + } + if (xmllib.getLibraryList().size() > 0) { + IDefaultMutableTreeNode library = new IDefaultMutableTreeNode( + "Library", + IDefaultMutableTreeNode.LIBRARIES_LIBRARY, + IDefaultMutableTreeNode.OPERATION_ADD_UPDATE_DELETE); + for (int indexI = 0; indexI < xmllib.getLibraryList().size(); indexI++) { + library.add(new IDefaultMutableTreeNode(xmllib.getLibraryArray(indexI).getStringValue(), + IDefaultMutableTreeNode.LIBRARIES_LIBRARY_ITEM, + IDefaultMutableTreeNode.OPERATION_DELETE)); + } + libraries.add(library); + } + dmtnRoot.add(libraries); + } + } + + // + //MLsa File + // + if (this.currentModuleType == 3) { + // + //Add MsaHeader Node + // + if (xmlmlh != null) { + dmtnRoot = new IDefaultMutableTreeNode(xmlmlh.getBaseName().getStringValue(), + IDefaultMutableTreeNode.MLSA_HEADER, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE); + } else { + makeEmptyTree(); + return; + } + + // + //Add LibraryClassDefinitions Node + // + if (xmllcd != null && xmllcd.getLibraryClassList().size() > 0) { + IDefaultMutableTreeNode libraryClassDefinitions = new IDefaultMutableTreeNode( + "Library Class Definitions", + IDefaultMutableTreeNode.LIBRARYCLASSDEFINITIONS, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE); + for (int indexI = 0; indexI < xmllcd.getLibraryClassList().size(); indexI++) { + libraryClassDefinitions + .add(new IDefaultMutableTreeNode( + xmllcd.getLibraryClassArray(indexI) + .getStringValue(), + IDefaultMutableTreeNode.LIBRARY_CLASS_DEFINITION, + IDefaultMutableTreeNode.OPERATION_NULL)); + } + dmtnRoot.add(libraryClassDefinitions); + } + } + + // + //Mlbd File + // + if (this.currentModuleType == 4) { + // + //Add MsaHeader Node + // + if (xmlmlbdh != null) { + dmtnRoot = new IDefaultMutableTreeNode(xmlmlbdh.getBaseName().getStringValue(), + IDefaultMutableTreeNode.MLBD_HEADER, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE); + } else { + makeEmptyTree(); + return; + } + + // + //Add Libraries Node + // + if (xmllib != null) { + IDefaultMutableTreeNode libraries = new IDefaultMutableTreeNode( + "Libraries", + IDefaultMutableTreeNode.LIBRARIES, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmllib.getArchList().size() > 0) { + IDefaultMutableTreeNode librariesArch = new IDefaultMutableTreeNode( + "Arch", + IDefaultMutableTreeNode.LIBRARIES_ARCH, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + for (int indexI = 0; indexI < xmllib.getArchList().size(); indexI++) { + librariesArch.add(new IDefaultMutableTreeNode(xmllib.getArchArray(indexI).getArchType() + .toString(), + IDefaultMutableTreeNode.LIBRARIES_ARCH_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + libraries.add(librariesArch); + } + if (xmllib.getLibraryList().size() > 0) { + IDefaultMutableTreeNode library = new IDefaultMutableTreeNode( + "Library", + IDefaultMutableTreeNode.LIBRARIES_LIBRARY, + IDefaultMutableTreeNode.OPERATION_ADD_UPDATE_DELETE); + for (int indexI = 0; indexI < xmllib.getLibraryList().size(); indexI++) { + library.add(new IDefaultMutableTreeNode(xmllib.getLibraryArray(indexI).getStringValue(), + IDefaultMutableTreeNode.LIBRARIES_LIBRARY_ITEM, + IDefaultMutableTreeNode.OPERATION_DELETE)); + } + libraries.add(library); + } + dmtnRoot.add(libraries); + } + } + + // + //Add SourceFiles Node + // + if (xmlsf != null) { + IDefaultMutableTreeNode sourceFiles = new IDefaultMutableTreeNode( + "Source Files", + IDefaultMutableTreeNode.SOURCEFILES, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlsf.getArchList().size() > 0) { + IDefaultMutableTreeNode sourceFilesArch = new IDefaultMutableTreeNode( + "Arch", + IDefaultMutableTreeNode.SOURCEFILES_ARCH, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + for (int indexI = 0; indexI < xmlsf.getArchList().size(); indexI++) { + sourceFilesArch + .add(new IDefaultMutableTreeNode( + xmlsf.getArchArray(indexI).getArchType().toString(), + IDefaultMutableTreeNode.SOURCEFILES_ARCH_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + sourceFiles.add(sourceFilesArch); + } + if (xmlsf.getFilenameList().size() > 0) { + IDefaultMutableTreeNode sourceFilesFileName = new IDefaultMutableTreeNode( + "File Name", + IDefaultMutableTreeNode.SOURCEFILES_FILENAME, + IDefaultMutableTreeNode.OPERATION_ADD_UPDATE_DELETE); + for (int indexI = 0; indexI < xmlsf.getFilenameList().size(); indexI++) { + sourceFilesFileName + .add(new IDefaultMutableTreeNode( + xmlsf.getFilenameArray(indexI).getStringValue(), + IDefaultMutableTreeNode.SOURCEFILES_FILENAME_ITEM, + IDefaultMutableTreeNode.OPERATION_DELETE)); + } + sourceFiles.add(sourceFilesFileName); + } + dmtnRoot.add(sourceFiles); + } + + // + //Add includes + // + if (xmlic != null) { + IDefaultMutableTreeNode includes = new IDefaultMutableTreeNode("Includes", + IDefaultMutableTreeNode.INCLUDES, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlic.getArchList().size() > 0) { + IDefaultMutableTreeNode includesArch = new IDefaultMutableTreeNode( + "Arch", + IDefaultMutableTreeNode.INCLUDES_ARCH, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + for (int indexI = 0; indexI < xmlic.getArchList().size(); indexI++) { + includesArch.add(new IDefaultMutableTreeNode(xmlic.getArchArray(indexI).getArchType().toString(), + IDefaultMutableTreeNode.INCLUDES_ARCH_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + includes.add(includesArch); + } + if (xmlic.getPackageNameList().size() > 0) { + IDefaultMutableTreeNode includesPackageName = new IDefaultMutableTreeNode( + "Package Name", + IDefaultMutableTreeNode.INCLUDES_PACKAGENAME, + IDefaultMutableTreeNode.OPERATION_ADD_UPDATE_DELETE); + for (int indexI = 0; indexI < xmlic.getPackageNameList().size(); indexI++) { + includesPackageName + .add(new IDefaultMutableTreeNode( + xmlic.getPackageNameArray(indexI) + .getStringValue(), + IDefaultMutableTreeNode.INCLUDES_PACKAGENAME_ITEM, + IDefaultMutableTreeNode.OPERATION_DELETE)); + } + includes.add(includesPackageName); + } + dmtnRoot.add(includes); + } + + // + //Add protocols + // + if (xmlpl != null) { + IDefaultMutableTreeNode dmtnProtocols = new IDefaultMutableTreeNode( + "Protocols", + IDefaultMutableTreeNode.PROTOCOLS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + IDefaultMutableTreeNode dmtnProtocol = new IDefaultMutableTreeNode( + "Protocol", + IDefaultMutableTreeNode.PROTOCOLS_PROTOCOL, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + IDefaultMutableTreeNode dmtnProtocolNotify = new IDefaultMutableTreeNode( + "Protocol Notify", + IDefaultMutableTreeNode.PROTOCOLS_PROTOCOLNOTIFY, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlpl.getProtocolList().size() > 0) { + for (int indexI = 0; indexI < xmlpl.getProtocolList().size(); indexI++) { + dmtnProtocol.add(new IDefaultMutableTreeNode(xmlpl.getProtocolArray(indexI).getStringValue(), + IDefaultMutableTreeNode.PROTOCOLS_PROTOCOL_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + dmtnProtocols.add(dmtnProtocol); + } + if (xmlpl.getProtocolNotifyList().size() > 0) { + for (int indexI = 0; indexI < xmlpl.getProtocolNotifyList().size(); indexI++) { + dmtnProtocolNotify + .add(new IDefaultMutableTreeNode( + xmlpl.getProtocolNotifyArray(indexI) + .getStringValue(), + IDefaultMutableTreeNode.PROTOCOLS_PROTOCOLNOTIFY_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + dmtnProtocols.add(dmtnProtocolNotify); + } + dmtnRoot.add(dmtnProtocols); + } + + // + //Add events + // + if (xmlen != null) { + IDefaultMutableTreeNode dmtnEvents = new IDefaultMutableTreeNode( + "Events", + IDefaultMutableTreeNode.EVENTS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + IDefaultMutableTreeNode dmtnCreateEvents = new IDefaultMutableTreeNode( + "Create", + IDefaultMutableTreeNode.EVENTS_CREATEEVENTS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + IDefaultMutableTreeNode dmtnSignalEvents = new IDefaultMutableTreeNode( + "Signal", + IDefaultMutableTreeNode.EVENTS_SIGNALEVENTS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlen.getCreateEvents() != null && xmlen.getCreateEvents().getEventList().size() > 0) { + for (int indexI = 0; indexI < xmlen.getCreateEvents().getEventList().size(); indexI++) { + dmtnCreateEvents.add(new IDefaultMutableTreeNode(xmlen.getCreateEvents().getEventArray(indexI) + .getCName(), + IDefaultMutableTreeNode.EVENTS_CREATEEVENTS_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + dmtnEvents.add(dmtnCreateEvents); + } + if (xmlen.getSignalEvents() != null && xmlen.getSignalEvents().getEventList().size() > 0) { + for (int indexI = 0; indexI < xmlen.getSignalEvents().getEventList().size(); indexI++) { + dmtnSignalEvents.add(new IDefaultMutableTreeNode(xmlen.getSignalEvents().getEventArray(indexI) + .getCName(), + IDefaultMutableTreeNode.EVENTS_SIGNALEVENTS_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + dmtnEvents.add(dmtnSignalEvents); + } + dmtnRoot.add(dmtnEvents); + } + + // + //Add hobs + // + if (xmlhob != null) { + IDefaultMutableTreeNode dmtnHobs = new IDefaultMutableTreeNode("Hobs", IDefaultMutableTreeNode.HOBS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlhob.getHobList().size() > 0) { + for (int indexI = 0; indexI < xmlhob.getHobList().size(); indexI++) { + dmtnHobs.add(new IDefaultMutableTreeNode(xmlhob.getHobArray(indexI).getName(), + IDefaultMutableTreeNode.HOBS_HOB_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, indexI)); + } + } + dmtnRoot.add(dmtnHobs); + } + + // + //Add ppis + // + if (xmlppi != null) { + IDefaultMutableTreeNode dmtnPpis = new IDefaultMutableTreeNode("Ppis", IDefaultMutableTreeNode.PPIS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + IDefaultMutableTreeNode dmtnPpi = new IDefaultMutableTreeNode("Ppi", IDefaultMutableTreeNode.PPIS_PPI, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + IDefaultMutableTreeNode dmtnPpiNotify = new IDefaultMutableTreeNode( + "Ppi Notify", + IDefaultMutableTreeNode.PPIS_PPINOTIFY, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlppi.getPpiList().size() > 0) { + for (int indexI = 0; indexI < xmlppi.getPpiList().size(); indexI++) { + dmtnPpi.add(new IDefaultMutableTreeNode(xmlppi.getPpiArray(indexI).getStringValue(), + IDefaultMutableTreeNode.PPIS_PPI_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, indexI)); + } + dmtnPpis.add(dmtnPpi); + } + if (xmlppi.getPpiNotifyList().size() > 0) { + for (int indexI = 0; indexI < xmlppi.getPpiNotifyList().size(); indexI++) { + dmtnPpiNotify.add(new IDefaultMutableTreeNode(xmlppi.getPpiNotifyArray(indexI).getStringValue(), + IDefaultMutableTreeNode.PPIS_PPINOTIFY_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + dmtnPpis.add(dmtnPpiNotify); + } + dmtnRoot.add(dmtnPpis); + } + + // + //Add variables + // + if (xmlvb != null) { + IDefaultMutableTreeNode dmtnVariables = new IDefaultMutableTreeNode( + "Variables", + IDefaultMutableTreeNode.VARIABLES, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlvb.getVariableList().size() > 0) { + for (int indexI = 0; indexI < xmlvb.getVariableList().size(); indexI++) { + dmtnVariables.add(new IDefaultMutableTreeNode(xmlvb.getVariableArray(indexI).getString(), + IDefaultMutableTreeNode.VARIABLES_VARIABLE_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + } + dmtnRoot.add(dmtnVariables); + } + + // + //Add bootmodes + // + if (xmlbm != null) { + IDefaultMutableTreeNode dmtnBootModes = new IDefaultMutableTreeNode( + "BootModes", + IDefaultMutableTreeNode.BOOTMODES, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlbm.getBootModeList().size() > 0) { + for (int indexI = 0; indexI < xmlbm.getBootModeList().size(); indexI++) { + dmtnBootModes.add(new IDefaultMutableTreeNode(xmlbm.getBootModeArray(indexI).getBootModeName() + .toString(), + IDefaultMutableTreeNode.BOOTMODES_BOOTMODE_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + } + dmtnRoot.add(dmtnBootModes); + } + + // + //Add systemtables + // + if (xmlst != null) { + IDefaultMutableTreeNode dmtnSystemTables = new IDefaultMutableTreeNode( + "SystemTables", + IDefaultMutableTreeNode.SYSTEMTABLES, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlst.getSystemTableList().size() > 0) { + for (int indexI = 0; indexI < xmlst.getSystemTableList().size(); indexI++) { + dmtnSystemTables + .add(new IDefaultMutableTreeNode( + xmlst.getSystemTableArray(indexI).getEntry(), + IDefaultMutableTreeNode.SYSTEMTABLES_SYSTEMTABLE_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + } + dmtnRoot.add(dmtnSystemTables); + } + + // + //Add datahubs + // + if (xmldh != null) { + IDefaultMutableTreeNode dmtnDataHubs = new IDefaultMutableTreeNode( + "DataHubs", + IDefaultMutableTreeNode.DATAHUBS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmldh.getDataHubRecordList().size() > 0) { + for (int indexI = 0; indexI < xmldh.getDataHubRecordList().size(); indexI++) { + dmtnDataHubs.add(new IDefaultMutableTreeNode(xmldh.getDataHubRecordArray(indexI).getStringValue(), + IDefaultMutableTreeNode.DATAHUBS_DATAHUB_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + } + dmtnRoot.add(dmtnDataHubs); + } + + // + //Add formsets + // + if (xmlfs != null) { + IDefaultMutableTreeNode dmtnFormsets = new IDefaultMutableTreeNode( + "Formsets", + IDefaultMutableTreeNode.FORMSETS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlfs.getFormsetList().size() > 0) { + for (int indexI = 0; indexI < xmlfs.getFormsetList().size(); indexI++) { + dmtnFormsets.add(new IDefaultMutableTreeNode(xmlfs.getFormsetArray(indexI).getStringValue(), + IDefaultMutableTreeNode.FORMSETS_FORMSET_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, + indexI)); + } + } + dmtnRoot.add(dmtnFormsets); + } + + // + //Add guids + // + if (xmlgu != null) { + IDefaultMutableTreeNode dmtnGuids = new IDefaultMutableTreeNode( + "Guids", + IDefaultMutableTreeNode.GUIDS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlgu.getGuidEntryList().size() > 0) { + for (int indexI = 0; indexI < xmlgu.getGuidEntryList().size(); indexI++) { + dmtnGuids.add(new IDefaultMutableTreeNode(xmlgu.getGuidEntryArray(indexI).getCName(), + IDefaultMutableTreeNode.GUIDS_GUIDENTRY_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, indexI)); + } + } + dmtnRoot.add(dmtnGuids); + } + + // + //Add externs + // + if (xmlet != null) { + IDefaultMutableTreeNode dmtnExterns = new IDefaultMutableTreeNode( + "Externs", + IDefaultMutableTreeNode.EXTERNS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlet.getExternList().size() > 0) { + for (int indexI = 0; indexI < xmlet.getExternList().size(); indexI++) { + dmtnExterns + .add(new IDefaultMutableTreeNode("Extern " + Integer.valueOf(indexI + 1), + IDefaultMutableTreeNode.EXTERNS_EXTERN_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, indexI)); + } + } + dmtnRoot.add(dmtnExterns); + } + + // + //Add pcds + // + if (xmlpcd != null) { + IDefaultMutableTreeNode dmtnPCDs = new IDefaultMutableTreeNode("PCDs", IDefaultMutableTreeNode.PCDS, + IDefaultMutableTreeNode.OPERATION_ADD_DELETE); + if (xmlpcd.getPcdDataList().size() > 0) { + for (int indexI = 0; indexI < xmlpcd.getPcdDataList().size(); indexI++) { + dmtnPCDs.add(new IDefaultMutableTreeNode(xmlpcd.getPcdDataArray(indexI).getCName(), + IDefaultMutableTreeNode.PCDS_PCDDATA_ITEM, + IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE, indexI)); + } + } + dmtnRoot.add(dmtnPCDs); + } + + iTree = new ITree(dmtnRoot); + iTree.addMouseListener(this); + iTree.addTreeSelectionListener(this); + jScrollPaneTree.setViewportView(iTree); + } + + /* (non-Javadoc) + * @see java.awt.event.WindowListener#windowClosing(java.awt.event.WindowEvent) + * + * Override windowClosing to popup warning message to confirm quit + * + */ + public void windowClosing(WindowEvent arg0) { + this.onExit(); + } + + /* (non-Javadoc) + * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent) + * + * Override mouseClicked to check if need display popup menu + * + */ + public void mouseClicked(MouseEvent arg0) { + if (arg0.getButton() == MouseEvent.BUTTON1) { + + } + if (arg0.getButton() == MouseEvent.BUTTON3) { + jPopupMenu.show(arg0.getComponent(), arg0.getX(), arg0.getY()); + } + } + + public void mouseEntered(MouseEvent arg0) { + // TODO Auto-generated method stub + } + + public void mouseExited(MouseEvent arg0) { + // TODO Auto-generated method stub + } + + public void mousePressed(MouseEvent arg0) { + // TODO Auto-generated method stub + } + + public void mouseReleased(MouseEvent arg0) { + // TODO Auto-generated method stub + } + + /** + Init popup menu + + **/ + public void valueChanged(TreeSelectionEvent arg0) { + int intOperation = iTree.getSelectOperation(); + if (intOperation == IDefaultMutableTreeNode.OPERATION_NULL) { + setMenuItemAddEnabled(false); + setMenuItemUpdateEnabled(false); + setMenuItemDeleteEnabled(false); + } + if (intOperation == IDefaultMutableTreeNode.OPERATION_ADD) { + setMenuItemAddEnabled(true); + setMenuItemUpdateEnabled(false); + setMenuItemDeleteEnabled(false); + } + if (intOperation == IDefaultMutableTreeNode.OPERATION_UPDATE) { + setMenuItemAddEnabled(false); + setMenuItemUpdateEnabled(true); + setMenuItemDeleteEnabled(false); + } + if (intOperation == IDefaultMutableTreeNode.OPERATION_DELETE) { + setMenuItemAddEnabled(false); + setMenuItemUpdateEnabled(false); + setMenuItemDeleteEnabled(true); + } + if (intOperation == IDefaultMutableTreeNode.OPERATION_ADD_UPDATE) { + setMenuItemAddEnabled(true); + setMenuItemUpdateEnabled(true); + setMenuItemDeleteEnabled(false); + } + if (intOperation == IDefaultMutableTreeNode.OPERATION_ADD_DELETE) { + setMenuItemAddEnabled(true); + setMenuItemUpdateEnabled(false); + setMenuItemDeleteEnabled(true); + } + if (intOperation == IDefaultMutableTreeNode.OPERATION_UPDATE_DELETE) { + setMenuItemAddEnabled(false); + setMenuItemUpdateEnabled(true); + setMenuItemDeleteEnabled(true); + } + if (intOperation == IDefaultMutableTreeNode.OPERATION_ADD_UPDATE_DELETE) { + setMenuItemAddEnabled(true); + setMenuItemUpdateEnabled(true); + setMenuItemDeleteEnabled(true); + } + viewCurrentModule(); + } + + /** + Enable/Disable add menu item + + **/ + private void setMenuItemAddEnabled(boolean isEnable) { + jMenuItemPopupAdd.setEnabled(isEnable); + } + + /** + Enable/Disable update menu item + + **/ + private void setMenuItemUpdateEnabled(boolean isEnable) { + jMenuItemPopupUpdate.setEnabled(isEnable); + jMenuItemEditUpdate.setEnabled(isEnable); + } + + /** + Enable/Disable delete menu item + + **/ + private void setMenuItemDeleteEnabled(boolean isEnable) { + jMenuItemPopupDelete.setEnabled(isEnable); + jMenuItemEditDelete.setEnabled(isEnable); + } + + /** + Close current open module + + **/ + private void closeCurrentModule() { + cleanAllXml(); + + reloadTreeAndTable(ModuleMain.CLOSED); + setMenuItemAddEnabled(false); + setMenuItemUpdateEnabled(false); + setMenuItemDeleteEnabled(false); + cleanDesktopPane(); + } + + /** + Remove all Internal Frame of Desktop Pane + + **/ + private void cleanDesktopPane() { + JInternalFrame[] iif = this.jDesktopPane.getAllFrames(); + for (int index = 0; index < iif.length; index++) { + iif[index].dispose(); + } + } + + /** + Set all xml document null + + **/ + private void cleanAllXml() { + this.currentModule = ""; + this.saveFileName = ""; + this.currentModuleType = 0; + this.currentNodeType = 0; + + xmlMsaDoc = null; + xmlMbdDoc = null; + xmlMlsaDoc = null; + xmlMlbdDoc = null; + xmlmh = null; + xmllcd = null; + xmllib = null; + xmlsf = null; + xmlic = null; + xmlpl = null; + xmlen = null; + xmlhob = null; + xmlppi = null; + xmlvb = null; + xmlbm = null; + xmlst = null; + xmldh = null; + xmlfs = null; + xmlgu = null; + xmlet = null; + xmlpcd = null; + xmlbo = null; + } + + /** + Execute add operation for current node + + @param intCategory The category of current node + @param intLocation The location of current node + + **/ + private void addCurrentModule(int intCategory, int intLocation) { + // + //Add new libraries + // + if (intCategory == IDefaultMutableTreeNode.LIBRARIES + || intCategory == IDefaultMutableTreeNode.LIBRARIES_LIBRARY + || intCategory == IDefaultMutableTreeNode.LIBRARIES_ARCH) { + showLibraries(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new sourcefiles + // + if (intCategory == IDefaultMutableTreeNode.SOURCEFILES + || intCategory == IDefaultMutableTreeNode.SOURCEFILES_FILENAME + || intCategory == IDefaultMutableTreeNode.SOURCEFILES_ARCH) { + showSourceFiles(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new includes + // + if (intCategory == IDefaultMutableTreeNode.INCLUDES + || intCategory == IDefaultMutableTreeNode.INCLUDES_PACKAGENAME + || intCategory == IDefaultMutableTreeNode.INCLUDES_ARCH) { + showIncludes(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new protocols + // + if (intCategory == IDefaultMutableTreeNode.PROTOCOLS + || intCategory == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOL + || intCategory == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOLNOTIFY) { + showProtocols(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new events + // + if (intCategory == IDefaultMutableTreeNode.EVENTS || intCategory == IDefaultMutableTreeNode.EVENTS_CREATEEVENTS + || intCategory == IDefaultMutableTreeNode.EVENTS_SIGNALEVENTS) { + showEvents(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new hobs + // + if (intCategory == IDefaultMutableTreeNode.HOBS || intCategory == IDefaultMutableTreeNode.HOBS_HOB_ITEM) { + showHobs(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new ppis + // + if (intCategory == IDefaultMutableTreeNode.PPIS || intCategory == IDefaultMutableTreeNode.PPIS_PPI + || intCategory == IDefaultMutableTreeNode.PPIS_PPINOTIFY) { + showPpis(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new variables + // + if (intCategory == IDefaultMutableTreeNode.VARIABLES + || intCategory == IDefaultMutableTreeNode.VARIABLES_VARIABLE_ITEM) { + showVariables(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new BootModes + // + if (intCategory == IDefaultMutableTreeNode.BOOTMODES + || intCategory == IDefaultMutableTreeNode.BOOTMODES_BOOTMODE_ITEM) { + showBootModes(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new SystemTables + // + if (intCategory == IDefaultMutableTreeNode.SYSTEMTABLES + || intCategory == IDefaultMutableTreeNode.SYSTEMTABLES_SYSTEMTABLE_ITEM) { + showSystemTables(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new DataHubs + // + if (intCategory == IDefaultMutableTreeNode.DATAHUBS + || intCategory == IDefaultMutableTreeNode.DATAHUBS_DATAHUB_ITEM) { + showDataHubs(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new Formsets + // + if (intCategory == IDefaultMutableTreeNode.FORMSETS + || intCategory == IDefaultMutableTreeNode.FORMSETS_FORMSET_ITEM) { + showFormsets(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new Guids + // + if (intCategory == IDefaultMutableTreeNode.GUIDS || intCategory == IDefaultMutableTreeNode.GUIDS_GUIDENTRY_ITEM) { + showGuids(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new Externs + // + if (intCategory == IDefaultMutableTreeNode.EXTERNS + || intCategory == IDefaultMutableTreeNode.EXTERNS_EXTERN_ITEM) { + showExterns(ModuleMain.ADD, intCategory, -1); + } + + // + //Add new PCDs + // + if (intCategory == IDefaultMutableTreeNode.PCDS || intCategory == IDefaultMutableTreeNode.PCDS_PCDDATA_ITEM) { + showPCDs(ModuleMain.ADD, intCategory, -1); + } + } + + /** + Execute delete operation of current node + + @param intCategory The category of current node + @param intLocation The location of current node + + **/ + private void deleteCurrentModule(int intCategory, int intLocation) { + // + // Delete Msa Header + // + if (intCategory == IDefaultMutableTreeNode.MSA_HEADER || intCategory == IDefaultMutableTreeNode.MBD_HEADER + || intCategory == IDefaultMutableTreeNode.MLSA_HEADER || intCategory == IDefaultMutableTreeNode.MLBD_HEADER) { + if (JOptionPane.showConfirmDialog(null, "The module will be deleted permanently, do you want to continue?") == JOptionPane.YES_OPTION) { + try { + File f = new File(currentModule); + f.delete(); + closeCurrentModule(); + } catch (Exception e) { + Log.err("Delete " + currentModule, e.getMessage()); + } + } else { + return; + } + } + + // + //Delete LIBRARY CLASS DEFINITIONS + // + if (intCategory == IDefaultMutableTreeNode.LIBRARYCLASSDEFINITIONS) { + xmllcd = null; + } + + // + //Delete Libraries + // + if (intCategory == IDefaultMutableTreeNode.LIBRARIES) { + xmllib = null; + } + if (intCategory == IDefaultMutableTreeNode.LIBRARIES_LIBRARY) { + for (int indexI = xmllib.getLibraryList().size() - 1; indexI > -1; indexI--) { + xmllib.removeLibrary(indexI); + } + if (xmllib.getArchList().size() < 1 && xmllib.getLibraryList().size() < 1) { + xmllib = null; + } + } + if (intCategory == IDefaultMutableTreeNode.LIBRARIES_ARCH) { + for (int indexI = xmllib.getArchList().size() - 1; indexI > -1; indexI--) { + xmllib.removeArch(indexI); + } + if (xmllib.getArchList().size() < 1 && xmllib.getLibraryList().size() < 1) { + xmllib = null; + } + } + if (intCategory == IDefaultMutableTreeNode.LIBRARIES_ARCH_ITEM) { + xmllib.removeArch(intLocation); + } + if (intCategory == IDefaultMutableTreeNode.LIBRARIES_LIBRARY_ITEM) { + xmllib.removeLibrary(intLocation); + } + + // + //Delete SourceFiles + // + if (intCategory == IDefaultMutableTreeNode.SOURCEFILES) { + xmlsf = null; + } + if (intCategory == IDefaultMutableTreeNode.SOURCEFILES_FILENAME) { + for (int indexI = xmlsf.getFilenameList().size() - 1; indexI > -1; indexI--) { + xmlsf.removeFilename(indexI); + } + if (xmlsf.getArchList().size() < 1 && xmlsf.getFilenameList().size() < 1) { + xmlsf = null; + } + } + if (intCategory == IDefaultMutableTreeNode.SOURCEFILES_ARCH) { + for (int indexI = xmlsf.getArchList().size() - 1; indexI > -1; indexI--) { + xmlsf.removeArch(indexI); + } + if (xmlsf.getArchList().size() < 1 && xmlsf.getFilenameList().size() < 1) { + xmlsf = null; + } + } + if (intCategory == IDefaultMutableTreeNode.SOURCEFILES_ARCH_ITEM) { + xmlsf.removeArch(intLocation); + } + if (intCategory == IDefaultMutableTreeNode.SOURCEFILES_FILENAME_ITEM) { + xmlsf.removeFilename(intLocation); + } + + // + //Delete Includes + // + if (intCategory == IDefaultMutableTreeNode.INCLUDES) { + xmlic = null; + } + if (intCategory == IDefaultMutableTreeNode.INCLUDES_PACKAGENAME) { + for (int indexI = xmlic.getPackageNameList().size() - 1; indexI > -1; indexI--) { + xmlic.removePackageName(indexI); + } + if (xmlic.getArchList().size() < 1 && xmlic.getPackageNameList().size() < 1) { + xmlic = null; + } + } + if (intCategory == IDefaultMutableTreeNode.INCLUDES_ARCH) { + for (int indexI = xmlic.getArchList().size() - 1; indexI > -1; indexI--) { + xmlic.removeArch(indexI); + } + if (xmlic.getArchList().size() < 1 && xmlic.getPackageNameList().size() < 1) { + xmlic = null; + } + } + if (intCategory == IDefaultMutableTreeNode.INCLUDES_ARCH_ITEM) { + xmlic.removeArch(intLocation); + } + if (intCategory == IDefaultMutableTreeNode.INCLUDES_PACKAGENAME_ITEM) { + xmlic.removePackageName(intLocation); + } + + // + //Delete Protocols + // + if (intCategory == IDefaultMutableTreeNode.PROTOCOLS) { + xmlpl = null; + } + if (intCategory == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOL) { + for (int indexI = xmlpl.getProtocolList().size() - 1; indexI > -1; indexI--) { + xmlpl.removeProtocol(indexI); + } + if (xmlpl.getProtocolList().size() < 1 && xmlpl.getProtocolNotifyList().size() < 1) { + xmlpl = null; + } + } + if (intCategory == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOLNOTIFY) { + for (int indexI = xmlpl.getProtocolList().size() - 1; indexI > -1; indexI--) { + xmlpl.removeProtocolNotify(indexI); + } + if (xmlpl.getProtocolList().size() < 1 && xmlpl.getProtocolNotifyList().size() < 1) { + xmlpl = null; + } + } + if (intCategory == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOL_ITEM) { + xmlpl.removeProtocol(intLocation); + } + if (intCategory == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOLNOTIFY_ITEM) { + xmlpl.removeProtocolNotify(intLocation); + } + + // + //Delete Events + // + if (intCategory == IDefaultMutableTreeNode.EVENTS) { + xmlen = null; + } + if (intCategory == IDefaultMutableTreeNode.EVENTS_CREATEEVENTS) { + for (int indexI = xmlen.getCreateEvents().getEventList().size() - 1; indexI > -1; indexI--) { + xmlen.getCreateEvents().removeEvent(indexI); + } + if (xmlen.getCreateEvents().getEventList().size() < 1 && xmlen.getSignalEvents().getEventList().size() < 1) { + xmlen = null; + } + } + if (intCategory == IDefaultMutableTreeNode.EVENTS_SIGNALEVENTS) { + for (int indexI = xmlen.getSignalEvents().getEventList().size() - 1; indexI > -1; indexI--) { + xmlen.getSignalEvents().removeEvent(indexI); + } + if (xmlen.getCreateEvents().getEventList().size() < 1 && xmlen.getSignalEvents().getEventList().size() < 1) { + xmlen = null; + } + } + if (intCategory == IDefaultMutableTreeNode.EVENTS_CREATEEVENTS_ITEM) { + xmlen.getCreateEvents().removeEvent(intLocation); + } + if (intCategory == IDefaultMutableTreeNode.EVENTS_SIGNALEVENTS_ITEM) { + xmlen.getSignalEvents().removeEvent(intLocation); + } + + // + //Delete Hobs + // + if (intCategory == IDefaultMutableTreeNode.HOBS) { + xmlhob = null; + } + if (intCategory == IDefaultMutableTreeNode.HOBS_HOB_ITEM) { + xmlhob.removeHob(intLocation); + if (xmlhob.getHobList().size() < 1) { + xmlhob = null; + } + } + + // + //Delete Ppis + // + if (intCategory == IDefaultMutableTreeNode.PPIS) { + xmlppi = null; + } + if (intCategory == IDefaultMutableTreeNode.PPIS_PPI) { + for (int indexI = xmlppi.getPpiList().size() - 1; indexI > -1; indexI--) { + xmlppi.removePpi(indexI); + } + if (xmlppi.getPpiList().size() < 1 && xmlppi.getPpiNotifyList().size() < 1) { + xmlppi = null; + } + } + if (intCategory == IDefaultMutableTreeNode.PPIS_PPINOTIFY) { + for (int indexI = xmlppi.getPpiNotifyList().size() - 1; indexI > -1; indexI--) { + xmlppi.removePpiNotify(indexI); + } + if (xmlppi.getPpiList().size() < 1 && xmlppi.getPpiNotifyList().size() < 1) { + xmlppi = null; + } + } + if (intCategory == IDefaultMutableTreeNode.PPIS_PPI_ITEM) { + xmlppi.removePpi(intLocation); + } + if (intCategory == IDefaultMutableTreeNode.PPIS_PPINOTIFY_ITEM) { + xmlppi.removePpiNotify(intLocation); + } + + // + //Delete Variables + // + if (intCategory == IDefaultMutableTreeNode.VARIABLES) { + xmlvb = null; + } + if (intCategory == IDefaultMutableTreeNode.VARIABLES_VARIABLE_ITEM) { + xmlvb.removeVariable(intLocation); + if (xmlvb.getVariableList().size() < 1) { + xmlvb = null; + } + } + + // + //Delete BootModes + // + if (intCategory == IDefaultMutableTreeNode.BOOTMODES) { + xmlbm = null; + } + if (intCategory == IDefaultMutableTreeNode.BOOTMODES_BOOTMODE_ITEM) { + xmlbm.removeBootMode(intLocation); + if (xmlbm.getBootModeList().size() < 1) { + xmlbm = null; + } + } + + // + //Delete SystemTables + // + if (intCategory == IDefaultMutableTreeNode.SYSTEMTABLES) { + xmlst = null; + } + if (intCategory == IDefaultMutableTreeNode.SYSTEMTABLES_SYSTEMTABLE_ITEM) { + xmlst.removeSystemTable(intLocation); + if (xmlst.getSystemTableList().size() < 1) { + xmlst = null; + } + } + + // + //Delete DataHubs + // + if (intCategory == IDefaultMutableTreeNode.DATAHUBS) { + xmldh = null; + } + if (intCategory == IDefaultMutableTreeNode.DATAHUBS_DATAHUB_ITEM) { + xmldh.removeDataHubRecord(intLocation); + if (xmldh.getDataHubRecordList().size() < 1) { + xmldh = null; + } + } + + // + //Delete Formsets + // + if (intCategory == IDefaultMutableTreeNode.FORMSETS) { + xmlfs = null; + } + if (intCategory == IDefaultMutableTreeNode.FORMSETS_FORMSET_ITEM) { + xmlfs.removeFormset(intLocation); + if (xmlfs.getFormsetList().size() < 1) { + xmlfs = null; + } + } + + // + //Delete Guids + // + if (intCategory == IDefaultMutableTreeNode.GUIDS) { + xmlgu = null; + } + if (intCategory == IDefaultMutableTreeNode.GUIDS_GUIDENTRY_ITEM) { + xmlgu.removeGuidEntry(intLocation); + if (xmlgu.getGuidEntryList().size() < 1) { + xmlgu = null; + } + } + + // + //Delete Externs + // + if (intCategory == IDefaultMutableTreeNode.EXTERNS) { + xmlet = null; + } + if (intCategory == IDefaultMutableTreeNode.EXTERNS_EXTERN_ITEM) { + xmlet.removeExtern(intLocation); + if (xmlet.getExternList().size() < 1) { + xmlet = null; + } + } + + // + //Delete PCDs + // + if (intCategory == IDefaultMutableTreeNode.PCDS) { + xmlpcd = null; + } + if (intCategory == IDefaultMutableTreeNode.PCDS_PCDDATA_ITEM) { + xmlpcd.removePcdData(intLocation); + if (xmlpcd.getPcdDataList().size() < 1) { + xmlpcd = null; + } + } + this.cleanDesktopPane(); + reloadTreeAndTable(UPDATE_WITH_CHANGE); + } + + /** + View current Module + + **/ + private void viewCurrentModule() { + int intCategory = iTree.getSelectCategory(); + int intLocation = iTree.getSelectLoaction(); + // + //View Msa Header + // + if (intCategory == IDefaultMutableTreeNode.MSA_HEADER) { + showMsaHeader(ModuleMain.VIEW); + } + + // + //View Mbd Header + // + if (intCategory == IDefaultMutableTreeNode.MBD_HEADER) { + showMbdHeader(ModuleMain.VIEW); + } + + // + //View Msa Lib Header + // + if (intCategory == IDefaultMutableTreeNode.MLSA_HEADER) { + showMlsaHeader(ModuleMain.VIEW); + } + + // + //View Mbd Lib Header + // + if (intCategory == IDefaultMutableTreeNode.MLBD_HEADER) { + showMlbdHeader(ModuleMain.VIEW); + } + + // + //View Libraries + // + if (intCategory == IDefaultMutableTreeNode.LIBRARIES_LIBRARY + || intCategory == IDefaultMutableTreeNode.LIBRARIES_ARCH_ITEM) { + showLibraries(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View LIBRARY CLASS DEFINITIONS + // + if (intCategory == IDefaultMutableTreeNode.LIBRARYCLASSDEFINITIONS) { + showLibraryClassDefinitions(ModuleMain.VIEW, intCategory); + } + + // + //View Source Files + // + if (intCategory == IDefaultMutableTreeNode.SOURCEFILES_FILENAME + || intCategory == IDefaultMutableTreeNode.SOURCEFILES_ARCH_ITEM) { + showSourceFiles(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View Includes + // + if (intCategory == IDefaultMutableTreeNode.INCLUDES_PACKAGENAME + || intCategory == IDefaultMutableTreeNode.INCLUDES_ARCH_ITEM) { + showIncludes(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View Protocols + // + if (intCategory == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOL_ITEM + || intCategory == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOLNOTIFY_ITEM) { + showProtocols(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View Hobs + // + if (intCategory == IDefaultMutableTreeNode.HOBS_HOB_ITEM) { + showHobs(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View Events + // + if (intCategory == IDefaultMutableTreeNode.EVENTS_CREATEEVENTS_ITEM + || intCategory == IDefaultMutableTreeNode.EVENTS_SIGNALEVENTS_ITEM) { + showEvents(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View Ppis + // + if (intCategory == IDefaultMutableTreeNode.PPIS_PPI_ITEM + || intCategory == IDefaultMutableTreeNode.PPIS_PPINOTIFY_ITEM) { + showPpis(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View Variables + // + if (intCategory == IDefaultMutableTreeNode.VARIABLES_VARIABLE_ITEM) { + showVariables(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View BootModes + // + if (intCategory == IDefaultMutableTreeNode.BOOTMODES_BOOTMODE_ITEM) { + showBootModes(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View SystemTables + // + if (intCategory == IDefaultMutableTreeNode.SYSTEMTABLES_SYSTEMTABLE_ITEM) { + showSystemTables(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View DataHubs + // + if (intCategory == IDefaultMutableTreeNode.DATAHUBS_DATAHUB_ITEM) { + showDataHubs(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View Formsets + // + if (intCategory == IDefaultMutableTreeNode.FORMSETS_FORMSET_ITEM) { + showFormsets(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View Guids + // + if (intCategory == IDefaultMutableTreeNode.GUIDS_GUIDENTRY_ITEM) { + showGuids(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View Externs + // + if (intCategory == IDefaultMutableTreeNode.EXTERNS_EXTERN_ITEM) { + showExterns(ModuleMain.VIEW, intCategory, intLocation); + } + + // + //View PCDs + // + if (intCategory == IDefaultMutableTreeNode.PCDS_PCDDATA_ITEM) { + showPCDs(ModuleMain.VIEW, intCategory, intLocation); + } + } + + /** + Execute update operation of current module + + @param intCategory The category of current node + @param intLocation The location of current node + + **/ + private void updateCurrentModule(int intCategory, int intLocation) { + // + //Update Msa Header + // + if (intCategory == IDefaultMutableTreeNode.MSA_HEADER) { + showMsaHeader(ModuleMain.UPDATE); + } + + // + //Update Mbd Header + // + if (intCategory == IDefaultMutableTreeNode.MBD_HEADER) { + showMbdHeader(ModuleMain.UPDATE); + } + + // + //Update Msa Lib Header + // + if (intCategory == IDefaultMutableTreeNode.MLSA_HEADER) { + showMlsaHeader(ModuleMain.UPDATE); + } + + // + //Update Mbd Lib Header + // + if (intCategory == IDefaultMutableTreeNode.MLBD_HEADER) { + showMlbdHeader(ModuleMain.UPDATE); + } + + // + //Update Libraries + // + if (intCategory == IDefaultMutableTreeNode.LIBRARIES_LIBRARY + || intCategory == IDefaultMutableTreeNode.LIBRARIES_ARCH_ITEM) { + showLibraries(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update LIBRARY CLASS DEFINITIONS + // + if (intCategory == IDefaultMutableTreeNode.LIBRARYCLASSDEFINITIONS) { + showLibraryClassDefinitions(ModuleMain.UPDATE, intCategory); + } + + // + //Update Source Files + // + if (intCategory == IDefaultMutableTreeNode.SOURCEFILES_FILENAME + || intCategory == IDefaultMutableTreeNode.SOURCEFILES_ARCH_ITEM) { + showSourceFiles(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update Includes + // + if (intCategory == IDefaultMutableTreeNode.INCLUDES_PACKAGENAME + || intCategory == IDefaultMutableTreeNode.INCLUDES_ARCH_ITEM) { + showIncludes(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update Protocols + // + if (intCategory == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOL_ITEM + || intCategory == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOLNOTIFY_ITEM) { + showProtocols(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update Hobs + // + if (intCategory == IDefaultMutableTreeNode.HOBS_HOB_ITEM) { + showHobs(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update Events + // + if (intCategory == IDefaultMutableTreeNode.EVENTS_CREATEEVENTS_ITEM + || intCategory == IDefaultMutableTreeNode.EVENTS_SIGNALEVENTS_ITEM) { + showEvents(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update Ppis + // + if (intCategory == IDefaultMutableTreeNode.PPIS_PPI_ITEM + || intCategory == IDefaultMutableTreeNode.PPIS_PPINOTIFY_ITEM) { + showPpis(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update Variables + // + if (intCategory == IDefaultMutableTreeNode.VARIABLES_VARIABLE_ITEM) { + showVariables(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update BootModes + // + if (intCategory == IDefaultMutableTreeNode.BOOTMODES_BOOTMODE_ITEM) { + showBootModes(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update SystemTables + // + if (intCategory == IDefaultMutableTreeNode.SYSTEMTABLES_SYSTEMTABLE_ITEM) { + showSystemTables(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update DataHubs + // + if (intCategory == IDefaultMutableTreeNode.DATAHUBS_DATAHUB_ITEM) { + showDataHubs(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update Formsets + // + if (intCategory == IDefaultMutableTreeNode.FORMSETS_FORMSET_ITEM) { + showFormsets(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update Guids + // + if (intCategory == IDefaultMutableTreeNode.GUIDS_GUIDENTRY_ITEM) { + showGuids(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update Externs + // + if (intCategory == IDefaultMutableTreeNode.EXTERNS_EXTERN_ITEM) { + showExterns(ModuleMain.UPDATE, intCategory, intLocation); + } + + // + //Update PCDs + // + if (intCategory == IDefaultMutableTreeNode.PCDS_PCDDATA_ITEM) { + showPCDs(ModuleMain.UPDATE, intCategory, intLocation); + } + } + + /** + Save current module + Call relevant function via different file types + + **/ + private void saveCurrentModule() { + if (this.saveFileName == "") { + openFile(2, this.currentModuleType); + } + if (this.saveFileName == "") { + this.saveFileName = this.currentModule; + return; + } else { + switch (this.currentModuleType) { + case 1: + saveMsa(); + break; + case 2: + saveMbd(); + break; + case 3: + saveMlsa(); + break; + case 4: + saveMlbd(); + break; + } + + } + + reloadTreeAndTable(SAVE_WITH_CHANGE); + } + + /** + Save current module as + + **/ + private void saveAsCurrentModule() { + this.saveFileName = ""; + saveCurrentModule(); + } + + /** + Save file as msa + + **/ + private void saveMsa() { + File f = new File(this.saveFileName); + ModuleSurfaceAreaDocument msaDoc = ModuleSurfaceAreaDocument.Factory.newInstance(); + ModuleSurfaceAreaDocument.ModuleSurfaceArea msa = ModuleSurfaceAreaDocument.ModuleSurfaceArea.Factory + .newInstance(); + + // + //Add all components into xml doc file + // + if (xmlmh != null) { + msa.setMsaHeader(xmlmh); + } + if (xmllcd != null) { + msa.setLibraryClassDefinitions(xmllcd); + } + if (xmlsf != null) { + msa.setSourceFiles(xmlsf); + } + if (xmlic != null) { + msa.setIncludes(xmlic); + } + if (xmlpl != null) { + msa.setProtocols(xmlpl); + } + if (xmlen != null) { + msa.setEvents(xmlen); + } + if (xmlhob != null) { + msa.setHobs(xmlhob); + } + if (xmlppi != null) { + msa.setPPIs(xmlppi); + } + if (xmlvb != null) { + msa.setVariables(xmlvb); + } + if (xmlbm != null) { + msa.setBootModes(xmlbm); + } + if (xmlst != null) { + msa.setSystemTables(xmlst); + } + if (xmldh != null) { + msa.setDataHubs(xmldh); + } + if (xmlfs != null) { + msa.setFormsets(xmlfs); + } + if (xmlgu != null) { + msa.setGuids(xmlgu); + } + if (xmlet != null) { + msa.setExterns(xmlet); + } + if (xmlpcd != null) { + msa.setPCDs(xmlpcd); + } + if (xmlbo != null) { + msa.setBuildOptions(xmlbo); + } + // + //Init namespace + // + XmlCursor cursor = msa.newCursor(); + String uri = "http://www.TianoCore.org/2006/Edk2.0"; + cursor.push(); + cursor.toNextToken(); + cursor.insertNamespace("", uri); + cursor.insertNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + cursor.pop(); + + // + //Config file format + // + XmlOptions options = new XmlOptions(); + options.setCharacterEncoding("UTF-8"); + options.setSavePrettyPrint(); + options.setSavePrettyPrintIndent(2); + + // + //Create finial doc + // + msaDoc.addNewModuleSurfaceArea(); + msaDoc.setModuleSurfaceArea((ModuleSurfaceAreaDocument.ModuleSurfaceArea) cursor.getObject()); + try { + // + //Save the file + // + msaDoc.save(f, options); + this.currentModule = this.saveFileName; + } catch (Exception e) { + Log.err("Save Msa", e.getMessage()); + } + } + + /** + Save file as mbd + + **/ + private void saveMbd() { + File f = new File(this.saveFileName); + ModuleBuildDescriptionDocument mbdDoc = ModuleBuildDescriptionDocument.Factory.newInstance(); + ModuleBuildDescriptionDocument.ModuleBuildDescription mbd = ModuleBuildDescriptionDocument.ModuleBuildDescription.Factory + .newInstance(); + // + //Add all components into xml doc file + // + if (xmlmbdh != null) { + mbd.setMbdHeader(xmlmbdh); + } + if (xmllib != null) { + mbd.setLibraries(xmllib); + } + if (xmlsf != null) { + mbd.setSourceFiles(xmlsf); + } + if (xmlic != null) { + mbd.setIncludes(xmlic); + } + if (xmlpl != null) { + mbd.setProtocols(xmlpl); + } + if (xmlen != null) { + mbd.setEvents(xmlen); + } + if (xmlhob != null) { + mbd.setHobs(xmlhob); + } + if (xmlppi != null) { + mbd.setPPIs(xmlppi); + } + if (xmlvb != null) { + mbd.setVariables(xmlvb); + } + if (xmlbm != null) { + mbd.setBootModes(xmlbm); + } + if (xmlst != null) { + mbd.setSystemTables(xmlst); + } + if (xmldh != null) { + mbd.setDataHubs(xmldh); + } + if (xmlfs != null) { + mbd.setFormsets(xmlfs); + } + if (xmlgu != null) { + mbd.setGuids(xmlgu); + } + if (xmlet != null) { + mbd.setExterns(xmlet); + } + if (xmlpcd != null) { + mbd.setPCDs(xmlpcd); + } + if (xmlbo != null) { + mbd.setBuildOptions(xmlbo); + } + // + //Init namespace + // + XmlCursor cursor = mbd.newCursor(); + String uri = "http://www.TianoCore.org/2006/Edk2.0"; + cursor.push(); + cursor.toNextToken(); + cursor.insertNamespace("", uri); + cursor.insertNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + cursor.pop(); + + // + //Config file format + // + XmlOptions options = new XmlOptions(); + options.setCharacterEncoding("UTF-8"); + options.setSavePrettyPrint(); + options.setSavePrettyPrintIndent(2); + + // + //Create finial doc + // + mbdDoc.addNewModuleBuildDescription(); + mbdDoc.setModuleBuildDescription((ModuleBuildDescriptionDocument.ModuleBuildDescription) cursor.getObject()); + try { + // + //Save the file + // + mbdDoc.save(f, options); + this.currentModule = this.saveFileName; + } catch (Exception e) { + Log.err("Save Mbd", e.getMessage()); + } + } + + /** + Save file as mlsa + + **/ + private void saveMlsa() { + File f = new File(this.saveFileName); + LibraryModuleSurfaceAreaDocument mlsaDoc = LibraryModuleSurfaceAreaDocument.Factory.newInstance(); + LibraryModuleSurfaceAreaDocument.LibraryModuleSurfaceArea mlsa = LibraryModuleSurfaceAreaDocument.LibraryModuleSurfaceArea.Factory + .newInstance(); + // + //Add all components into xml doc file + // + if (xmlmlh != null) { + mlsa.setMsaLibHeader(xmlmlh); + } + if (xmllcd != null) { + mlsa.setLibraryClassDefinitions(xmllcd); + } + if (xmlsf != null) { + mlsa.setSourceFiles(xmlsf); + } + if (xmlic != null) { + mlsa.setIncludes(xmlic); + } + if (xmlpl != null) { + mlsa.setProtocols(xmlpl); + } + if (xmlen != null) { + mlsa.setEvents(xmlen); + } + if (xmlhob != null) { + mlsa.setHobs(xmlhob); + } + if (xmlppi != null) { + mlsa.setPPIs(xmlppi); + } + if (xmlvb != null) { + mlsa.setVariables(xmlvb); + } + if (xmlbm != null) { + mlsa.setBootModes(xmlbm); + } + if (xmlst != null) { + mlsa.setSystemTables(xmlst); + } + if (xmldh != null) { + mlsa.setDataHubs(xmldh); + } + if (xmlfs != null) { + mlsa.setFormsets(xmlfs); + } + if (xmlgu != null) { + mlsa.setGuids(xmlgu); + } + if (xmlet != null) { + mlsa.setExterns(xmlet); + } + if (xmlpcd != null) { + mlsa.setPCDs(xmlpcd); + } + if (xmlbo != null) { + mlsa.setBuildOptions(xmlbo); + } + // + //Init namespace + // + XmlCursor cursor = mlsa.newCursor(); + String uri = "http://www.TianoCore.org/2006/Edk2.0"; + cursor.push(); + cursor.toNextToken(); + cursor.insertNamespace("", uri); + cursor.insertNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + cursor.pop(); + + // + //Config file format + // + XmlOptions options = new XmlOptions(); + options.setCharacterEncoding("UTF-8"); + options.setSavePrettyPrint(); + options.setSavePrettyPrintIndent(2); + + // + //Create finial doc + // + mlsaDoc.addNewLibraryModuleSurfaceArea(); + mlsaDoc + .setLibraryModuleSurfaceArea((LibraryModuleSurfaceAreaDocument.LibraryModuleSurfaceArea) cursor + .getObject()); + try { + // + //Save the file + // + mlsaDoc.save(f, options); + this.currentModule = this.saveFileName; + } catch (Exception e) { + Log.err("Save Mlsa", e.getMessage()); + } + } + + /** + Save file as mbd + + **/ + private void saveMlbd() { + File f = new File(this.saveFileName); + LibraryModuleBuildDescriptionDocument mlbdDoc = LibraryModuleBuildDescriptionDocument.Factory.newInstance(); + LibraryModuleBuildDescriptionDocument.LibraryModuleBuildDescription mlbd = LibraryModuleBuildDescriptionDocument.LibraryModuleBuildDescription.Factory + .newInstance(); + // + //Add all components into xml doc file + // + if (xmlmlbdh != null) { + mlbd.setMbdLibHeader(xmlmlbdh); + } + if (xmllib != null) { + mlbd.setLibraries(xmllib); + } + if (xmlsf != null) { + mlbd.setSourceFiles(xmlsf); + } + if (xmlic != null) { + mlbd.setIncludes(xmlic); + } + if (xmlpl != null) { + mlbd.setProtocols(xmlpl); + } + if (xmlen != null) { + mlbd.setEvents(xmlen); + } + if (xmlhob != null) { + mlbd.setHobs(xmlhob); + } + if (xmlppi != null) { + mlbd.setPPIs(xmlppi); + } + if (xmlvb != null) { + mlbd.setVariables(xmlvb); + } + if (xmlbm != null) { + mlbd.setBootModes(xmlbm); + } + if (xmlst != null) { + mlbd.setSystemTables(xmlst); + } + if (xmldh != null) { + mlbd.setDataHubs(xmldh); + } + if (xmlfs != null) { + mlbd.setFormsets(xmlfs); + } + if (xmlgu != null) { + mlbd.setGuids(xmlgu); + } + if (xmlet != null) { + mlbd.setExterns(xmlet); + } + if (xmlpcd != null) { + mlbd.setPCDs(xmlpcd); + } + if (xmlbo != null) { + mlbd.setBuildOptions(xmlbo); + } + // + //Init namespace + // + XmlCursor cursor = mlbd.newCursor(); + String uri = "http://www.TianoCore.org/2006/Edk2.0"; + cursor.push(); + cursor.toNextToken(); + cursor.insertNamespace("", uri); + cursor.insertNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance"); + cursor.pop(); + + // + //Config file format + // + XmlOptions options = new XmlOptions(); + options.setCharacterEncoding("UTF-8"); + options.setSavePrettyPrint(); + options.setSavePrettyPrintIndent(2); + + // + //Create finial doc + // + mlbdDoc.addNewLibraryModuleBuildDescription(); + mlbdDoc + .setLibraryModuleBuildDescription((LibraryModuleBuildDescriptionDocument.LibraryModuleBuildDescription) cursor + .getObject()); + try { + // + //Save the file + // + mlbdDoc.save(f, options); + this.currentModule = this.saveFileName; + } catch (Exception e) { + Log.err("Save Mbd", e.getMessage()); + } + } + + /** + Reflash the tree via current value of xml documents. + + @param intMode The input data of current operation type + + **/ + private void reloadTreeAndTable(int intMode) { + makeTree(); + if (intMode == ModuleMain.OPENED) { + this.jMenuItemModuleClose.setEnabled(true); + this.jMenuItemModuleSaveAs.setEnabled(true); + this.jMenuEditAdd.setEnabled(true); + this.setTitle(windowTitle + "- [" + this.currentModule + "]"); + this.jButtonOk.setEnabled(false); + this.jButtonCancel.setEnabled(false); + } + if (intMode == ModuleMain.CLOSED) { + this.jMenuItemModuleClose.setEnabled(false); + this.jMenuItemModuleSave.setEnabled(false); + this.jMenuItemModuleSaveAs.setEnabled(false); + this.jMenuEditAdd.setEnabled(false); + this.setTitle(windowTitle + "- [" + ws.getCurrentWorkspace() + "]"); + this.setButtonEnable(false); + } + if (intMode == ModuleMain.NEW_WITHOUT_CHANGE) { + + } + + if (intMode == ModuleMain.NEW_WITH_CHANGE) { + this.jMenuItemModuleClose.setEnabled(true); + this.jMenuItemModuleSave.setEnabled(true); + this.jMenuItemModuleSaveAs.setEnabled(true); + this.jMenuEditAdd.setEnabled(true); + setButtonEnable(false); + } + if (intMode == ModuleMain.UPDATE_WITHOUT_CHANGE) { + + } + if (intMode == ModuleMain.UPDATE_WITH_CHANGE) { + this.jMenuItemModuleClose.setEnabled(true); + this.jMenuItemModuleSave.setEnabled(true); + this.jMenuItemModuleSaveAs.setEnabled(true); + } + if (intMode == ModuleMain.SAVE_WITHOUT_CHANGE) { + this.jMenuItemModuleClose.setEnabled(true); + this.jMenuItemModuleSave.setEnabled(true); + this.jMenuItemModuleSaveAs.setEnabled(true); + this.jButtonOk.setEnabled(false); + this.jButtonCancel.setEnabled(false); + } + if (intMode == ModuleMain.SAVE_WITH_CHANGE) { + this.jMenuItemModuleClose.setEnabled(true); + this.jMenuItemModuleSave.setEnabled(false); + this.jMenuItemModuleSaveAs.setEnabled(true); + this.jMenuItemEditUpdate.setEnabled(false); + this.jMenuItemEditDelete.setEnabled(false); + this.setTitle(windowTitle + "- [" + this.currentModule + "]"); + this.jButtonOk.setEnabled(false); + this.jButtonCancel.setEnabled(false); + } + + if (this.currentModuleType == 1 || this.currentModuleType == 3) { + this.jMenuItemEditAddLibraries.setEnabled(false); + this.jMenuItemEditAddLibraryClassDefinitions.setEnabled(true); + } + if (this.currentModuleType == 2 || this.currentModuleType == 4) { + this.jMenuItemEditAddLibraries.setEnabled(true); + this.jMenuItemEditAddLibraryClassDefinitions.setEnabled(false); + } + } + + /** + Enable/Disable button Ok and Cancel + + @param isEnabled The input data to indicate if button is enabled or not + + **/ + private void setButtonEnable(boolean isEnabled) { + this.jButtonCancel.setEnabled(isEnabled); + this.jButtonOk.setEnabled(isEnabled); + } + + /** + Show msa header + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showMsaHeader(int type) { + msa = null; + msa = new MsaHeader(this.xmlmh); + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(msa, 1); + this.currentNodeType = IDefaultMutableTreeNode.MSA_HEADER; + this.currentModuleType = 1; + if (type == ModuleMain.VIEW) { + setButtonEnable(false); + msa.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show MbdHeader + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showMbdHeader(int type) { + mbd = null; + mbd = new MbdHeader(this.xmlmbdh); + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mbd, 1); + this.currentNodeType = IDefaultMutableTreeNode.MBD_HEADER; + this.currentModuleType = 2; + if (type == ModuleMain.VIEW) { + setButtonEnable(false); + mbd.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show MlsaHeader + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showMlsaHeader(int type) { + mlsa = null; + mlsa = new MsaLibHeader(this.xmlmlh); + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mlsa, 1); + this.currentNodeType = IDefaultMutableTreeNode.MLSA_HEADER; + this.currentModuleType = 3; + if (type == ModuleMain.VIEW) { + setButtonEnable(false); + mlsa.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show MlbdHeader + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showMlbdHeader(int type) { + mlbd = null; + mlbd = new MbdLibHeader(this.xmlmlbdh); + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mlbd, 1); + this.currentNodeType = IDefaultMutableTreeNode.MLBD_HEADER; + this.currentModuleType = 4; + if (type == ModuleMain.VIEW) { + setButtonEnable(false); + mlbd.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show Libraries + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showLibraries(int operationType, int nodeType, int location) { + mlib = null; + if (operationType == ModuleMain.ADD) { + mlib = new MbdLibraries(this.xmllib, -1, -1, 1); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mlib = new MbdLibraries(this.xmllib, nodeType, location, 2); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mlib, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mlib.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show LibraryClassDefinitions + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showLibraryClassDefinitions(int operationType, int nodeType) { + mlcd = null; + if (operationType == ModuleMain.ADD) { + mlcd = new ModuleLibraryClassDefinitions(this.xmllcd); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mlcd = new ModuleLibraryClassDefinitions(this.xmllcd); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mlcd, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mlcd.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show SourceFiles + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showSourceFiles(int operationType, int nodeType, int location) { + msf = null; + if (operationType == ModuleMain.ADD) { + msf = new ModuleSourceFiles(this.xmlsf, -1, -1, 1); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + msf = new ModuleSourceFiles(this.xmlsf, nodeType, location, 2); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(msf, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + msf.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show Includes + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showIncludes(int operationType, int nodeType, int location) { + mic = null; + if (operationType == ModuleMain.ADD) { + mic = new ModuleIncludes(this.xmlic, -1, -1, 1); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mic = new ModuleIncludes(this.xmlic, nodeType, location, 2); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mic, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mic.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show Protocols + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showProtocols(int operationType, int nodeType, int location) { + mp = null; + if (operationType == ModuleMain.ADD) { + mp = new ModuleProtocols(this.xmlpl); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mp = new ModuleProtocols(this.xmlpl, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mp, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mp.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show Events + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showEvents(int operationType, int nodeType, int location) { + mev = null; + if (operationType == ModuleMain.ADD) { + mev = new ModuleEvents(this.xmlen); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mev = new ModuleEvents(this.xmlen, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mev, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mev.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show Hobs + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showHobs(int operationType, int nodeType, int location) { + mh = null; + if (operationType == ModuleMain.ADD) { + mh = new ModuleHobs(this.xmlhob); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mh = new ModuleHobs(this.xmlhob, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mh, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mh.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show Ppis + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showPpis(int operationType, int nodeType, int location) { + mpp = null; + if (operationType == ModuleMain.ADD) { + mpp = new ModulePpis(this.xmlppi); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mpp = new ModulePpis(this.xmlppi, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mpp, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mpp.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show Variables + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showVariables(int operationType, int nodeType, int location) { + mv = null; + if (operationType == ModuleMain.ADD) { + mv = new ModuleVariables(this.xmlvb); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mv = new ModuleVariables(this.xmlvb, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mv, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mv.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show BootModes + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showBootModes(int operationType, int nodeType, int location) { + mbm = null; + if (operationType == ModuleMain.ADD) { + mbm = new ModuleBootModes(this.xmlbm); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mbm = new ModuleBootModes(this.xmlbm, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mbm, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mbm.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show SystemTables + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showSystemTables(int operationType, int nodeType, int location) { + mst = null; + if (operationType == ModuleMain.ADD) { + mst = new ModuleSystemTables(this.xmlst); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mst = new ModuleSystemTables(this.xmlst, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mst, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mst.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show DataHubs + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showDataHubs(int operationType, int nodeType, int location) { + mdh = null; + if (operationType == ModuleMain.ADD) { + mdh = new ModuleDataHubs(this.xmldh); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mdh = new ModuleDataHubs(this.xmldh, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mdh, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mdh.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show Formsets + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showFormsets(int operationType, int nodeType, int location) { + mf = null; + if (operationType == ModuleMain.ADD) { + mf = new ModuleFormsets(this.xmlfs); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mf = new ModuleFormsets(this.xmlfs, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mf, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mf.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show Show Guids + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showGuids(int operationType, int nodeType, int location) { + mg = null; + if (operationType == ModuleMain.ADD || operationType == ModuleMain.VIEW) { + mg = new ModuleGuids(this.xmlgu); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mg = new ModuleGuids(this.xmlgu, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mg, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mg.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show Externs + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showExterns(int operationType, int nodeType, int location) { + met = null; + if (operationType == ModuleMain.ADD) { + met = new ModuleExterns(this.xmlet); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + met = new ModuleExterns(this.xmlet, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(met, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + met.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Show PCDs + When the operation is VIEW, disable all fields of internal frame + + @param type The input data of operation type + + **/ + private void showPCDs(int operationType, int nodeType, int location) { + mpcd = null; + if (operationType == ModuleMain.ADD) { + mpcd = new ModulePCDs(this.xmlpcd); + } + if (operationType == ModuleMain.UPDATE || operationType == ModuleMain.VIEW) { + mpcd = new ModulePCDs(this.xmlpcd, nodeType, location); + } + this.jDesktopPane.removeAll(); + this.jDesktopPane.add(mpcd, 1); + this.currentNodeType = nodeType; + if (operationType == ModuleMain.VIEW) { + setButtonEnable(false); + mpcd.setViewMode(true); + } else { + setButtonEnable(true); + } + } + + /** + Save currentModule when press button OK + + **/ + private void save() { + if (this.currentNodeType == IDefaultMutableTreeNode.MSA_HEADER) { + if (!msa.check()) { + return; + } + msa.save(); + msa.setViewMode(true); + this.xmlmh = msa.getMsaHeader(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.MBD_HEADER) { + if (!mbd.check()) { + return; + } + mbd.save(); + mbd.setViewMode(true); + this.xmlmbdh = mbd.getMbdHeader(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.MLSA_HEADER) { + if (!mlsa.check()) { + return; + } + mlsa.save(); + mlsa.setViewMode(true); + this.xmlmlh = mlsa.getMsaLibHeader(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.MLBD_HEADER) { + if (!mlbd.check()) { + return; + } + mlbd.save(); + mlbd.setViewMode(true); + this.xmlmlbdh = mlbd.getMbdLibHeader(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.LIBRARIES + || this.currentNodeType == IDefaultMutableTreeNode.LIBRARIES_ARCH + || this.currentNodeType == IDefaultMutableTreeNode.LIBRARIES_ARCH_ITEM + || this.currentNodeType == IDefaultMutableTreeNode.LIBRARIES_LIBRARY + || this.currentNodeType == IDefaultMutableTreeNode.LIBRARIES_LIBRARY_ITEM) { + if (!mlib.check()) { + return; + } + mlib.save(); + mlib.setViewMode(true); + this.xmllib = mlib.getLibraries(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.LIBRARYCLASSDEFINITIONS + || this.currentNodeType == IDefaultMutableTreeNode.LIBRARY_CLASS_DEFINITION) { + if (!mlcd.check()) { + return; + } + mlcd.save(); + mlcd.setViewMode(true); + this.xmllcd = mlcd.getLibraryClassDefinitions(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.SOURCEFILES + || this.currentNodeType == IDefaultMutableTreeNode.SOURCEFILES_ARCH + || this.currentNodeType == IDefaultMutableTreeNode.SOURCEFILES_ARCH_ITEM + || this.currentNodeType == IDefaultMutableTreeNode.SOURCEFILES_FILENAME + || this.currentNodeType == IDefaultMutableTreeNode.SOURCEFILES_FILENAME_ITEM) { + if (!msf.check()) { + return; + } + msf.save(); + msf.setViewMode(true); + this.xmlsf = msf.getSourceFiles(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.INCLUDES + || this.currentNodeType == IDefaultMutableTreeNode.INCLUDES_ARCH + || this.currentNodeType == IDefaultMutableTreeNode.INCLUDES_ARCH_ITEM + || this.currentNodeType == IDefaultMutableTreeNode.INCLUDES_PACKAGENAME + || this.currentNodeType == IDefaultMutableTreeNode.INCLUDES_PACKAGENAME_ITEM) { + if (!mic.check()) { + return; + } + mic.save(); + mic.setViewMode(true); + this.xmlic = mic.getIncludes(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.PROTOCOLS + || this.currentNodeType == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOL + || this.currentNodeType == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOL_ITEM + || this.currentNodeType == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOLNOTIFY + || this.currentNodeType == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOLNOTIFY_ITEM) { + if (!mp.check()) { + return; + } + mp.save(); + mp.setViewMode(true); + this.xmlpl = mp.getProtocols(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.EVENTS + || this.currentNodeType == IDefaultMutableTreeNode.EVENTS_CREATEEVENTS + || this.currentNodeType == IDefaultMutableTreeNode.EVENTS_CREATEEVENTS_ITEM + || this.currentNodeType == IDefaultMutableTreeNode.EVENTS_SIGNALEVENTS + || this.currentNodeType == IDefaultMutableTreeNode.EVENTS_SIGNALEVENTS_ITEM) { + if (!mev.check()) { + return; + } + mev.save(); + mev.setViewMode(true); + this.xmlen = mev.getEvents(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.HOBS + || this.currentNodeType == IDefaultMutableTreeNode.HOBS_HOB_ITEM) { + if (!mh.check()) { + return; + } + mh.save(); + mh.setViewMode(true); + this.xmlhob = mh.getHobs(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.PPIS + || this.currentNodeType == IDefaultMutableTreeNode.PPIS_PPI + || this.currentNodeType == IDefaultMutableTreeNode.PPIS_PPI_ITEM + || this.currentNodeType == IDefaultMutableTreeNode.PPIS_PPINOTIFY + || this.currentNodeType == IDefaultMutableTreeNode.PPIS_PPINOTIFY_ITEM) { + if (!mpp.check()) { + return; + } + mpp.save(); + mpp.setViewMode(true); + this.xmlppi = mpp.getPpis(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.VARIABLES + || this.currentNodeType == IDefaultMutableTreeNode.VARIABLES_VARIABLE_ITEM) { + if (!mv.check()) { + return; + } + mv.save(); + mv.setViewMode(true); + this.xmlvb = mv.getVariables(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.BOOTMODES + || this.currentNodeType == IDefaultMutableTreeNode.BOOTMODES_BOOTMODE_ITEM) { + if (!mbm.check()) { + return; + } + mbm.save(); + mbm.setViewMode(true); + this.xmlbm = mbm.getBootModes(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.SYSTEMTABLES + || this.currentNodeType == IDefaultMutableTreeNode.SYSTEMTABLES_SYSTEMTABLE_ITEM) { + if (!mst.check()) { + return; + } + mst.save(); + mst.setViewMode(true); + this.xmlst = mst.getSystemTables(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.DATAHUBS + || this.currentNodeType == IDefaultMutableTreeNode.DATAHUBS_DATAHUB_ITEM) { + if (!mdh.check()) { + return; + } + mdh.save(); + mdh.setViewMode(true); + this.xmldh = mdh.getDataHubs(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.FORMSETS + || this.currentNodeType == IDefaultMutableTreeNode.FORMSETS_FORMSET_ITEM) { + if (!mf.check()) { + return; + } + mf.save(); + mf.setViewMode(true); + this.xmlfs = mf.getFormsets(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.GUIDS + || this.currentNodeType == IDefaultMutableTreeNode.GUIDS_GUIDENTRY_ITEM) { + if (!mg.check()) { + return; + } + mg.save(); + mg.setViewMode(true); + this.xmlgu = mg.getGuids(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.EXTERNS + || this.currentNodeType == IDefaultMutableTreeNode.EXTERNS_EXTERN_ITEM) { + if (!met.check()) { + return; + } + met.save(); + met.setViewMode(true); + this.xmlet = met.getExterns(); + } + + if (this.currentNodeType == IDefaultMutableTreeNode.PCDS + || this.currentNodeType == IDefaultMutableTreeNode.PCDS_PCDDATA_ITEM) { + if (!mpcd.check()) { + return; + } + mpcd.save(); + mpcd.setViewMode(true); + this.xmlpcd = mpcd.getPcds(); + } + + reloadTreeAndTable(NEW_WITH_CHANGE); + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModulePCDs.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModulePCDs.java new file mode 100644 index 0000000000..827efe9f3f --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModulePCDs.java @@ -0,0 +1,519 @@ +/** @file + + The file is used to create, update PCD of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.tianocore.PCDsDocument; +import org.tianocore.PcdDataTypes; +import org.tianocore.PcdItemTypes; +import org.tianocore.PcdUsage; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update PCD of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModulePCDs extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = 2227717658188438696L; + + // + //Define class members + // + private PCDsDocument.PCDs pcds = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabelItemType = null; + + private JLabel jLabelC_Name = null; + + private JComboBox jComboBoxItemType = null; + + private JTextField jTextFieldC_Name = null; + + private JLabel jLabelToken = null; + + private JTextField jTextFieldToken = null; + + private JLabel jLabelDefaultValue = null; + + private JTextField jTextFieldDefaultValue = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelDatumType = null; + + private JComboBox jComboBoxDatumType = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + private StarLabel jStarLabel3 = null; + + private StarLabel jStarLabel4 = null; + + /** + This method initializes jComboBoxItemType + + @return javax.swing.JComboBox jComboBoxItemType + + **/ + private JComboBox getJComboBoxItemType() { + if (jComboBoxItemType == null) { + jComboBoxItemType = new JComboBox(); + jComboBoxItemType.setBounds(new java.awt.Rectangle(160, 110, 320, 20)); + } + return jComboBoxItemType; + } + + /** + This method initializes jTextFieldC_Name + + @return javax.swing.JTextField jTextFieldC_Name + + **/ + private JTextField getJTextFieldC_Name() { + if (jTextFieldC_Name == null) { + jTextFieldC_Name = new JTextField(); + jTextFieldC_Name.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldC_Name; + } + + /** + This method initializes jTextFieldToken + + @return javax.swing.JTextField jTextFieldToken + + **/ + private JTextField getJTextFieldToken() { + if (jTextFieldToken == null) { + jTextFieldToken = new JTextField(); + jTextFieldToken.setBounds(new java.awt.Rectangle(160, 35, 320, 20)); + } + return jTextFieldToken; + } + + /** + This method initializes jTextFieldDefaultValue + + @return javax.swing.JTextField jTextFieldDefaultValue + + **/ + private JTextField getJTextFieldDefaultValue() { + if (jTextFieldDefaultValue == null) { + jTextFieldDefaultValue = new JTextField(); + jTextFieldDefaultValue.setBounds(new java.awt.Rectangle(160, 85, 320, 20)); + } + return jTextFieldDefaultValue; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 135, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(280, 290, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 290, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jTextFieldDatumType + + @return javax.swing.JTextField jComboBoxDatumType + + **/ + private JComboBox getJComboBoxDatumType() { + if (jComboBoxDatumType == null) { + jComboBoxDatumType = new JComboBox(); + jComboBoxDatumType.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jComboBoxDatumType; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModulePCDs() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inPcds The input data of PCDsDocument.PCDs + + **/ + public ModulePCDs(PCDsDocument.PCDs inPcds) { + super(); + init(inPcds); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inPcds The input data of PCDsDocument.PCDs + @param type The input data of node type + @param index The input data of node index + + **/ + public ModulePCDs(PCDsDocument.PCDs inPcds, int type, int index) { + super(); + init(inPcds, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inPcds The input data of PCDsDocument.PCDs + + **/ + private void init(PCDsDocument.PCDs inPcds) { + init(); + this.setPcds(inPcds); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inPcds The input data of PCDsDocument.PCDs + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(PCDsDocument.PCDs inPcds, int type, int index) { + init(inPcds); + this.location = index; + if (this.pcds.getPcdDataList().size() > 0) { + if (this.pcds.getPcdDataArray(index).getCName() != null) { + this.jTextFieldC_Name.setText(this.pcds.getPcdDataArray(index).getCName()); + } + if (this.pcds.getPcdDataArray(index).getToken() != null) { + this.jTextFieldToken.setText(this.pcds.getPcdDataArray(index).getToken()); + } + if (this.pcds.getPcdDataArray(index).getDatumType() != null) { + this.jComboBoxDatumType.setSelectedItem(this.pcds.getPcdDataArray(index).getDatumType().toString()); + } + if (this.pcds.getPcdDataArray(index).getDefaultValue() != null) { + this.jTextFieldDefaultValue.setText(this.pcds.getPcdDataArray(index).getDefaultValue()); + } + if (this.pcds.getPcdDataArray(index).getPcdUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.pcds.getPcdDataArray(index).getPcdUsage().toString()); + } + if (this.pcds.getPcdDataArray(index).getItemType() != null) { + this.jComboBoxItemType.setSelectedItem(this.pcds.getPcdDataArray(index).getItemType().toString()); + } + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("PCDs"); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldC_Name.setEnabled(!isView); + this.jTextFieldToken.setEnabled(!isView); + this.jComboBoxDatumType.setEnabled(!isView); + this.jTextFieldDefaultValue.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jComboBoxItemType.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelDatumType = new JLabel(); + jLabelDatumType.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelDatumType.setText("Datum Type"); + jLabelC_Name = new JLabel(); + jLabelC_Name.setText("C_Name"); + jLabelC_Name.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 135, 140, 20)); + jLabelDefaultValue = new JLabel(); + jLabelDefaultValue.setText("Default Value"); + jLabelDefaultValue.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelToken = new JLabel(); + jLabelToken.setText("Token"); + jLabelToken.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelItemType = new JLabel(); + jLabelItemType.setText("Item Type"); + jLabelItemType.setBounds(new java.awt.Rectangle(15, 110, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setSize(new java.awt.Dimension(480,336)); + jContentPane.add(jLabelItemType, null); + jContentPane.add(jLabelC_Name, null); + jContentPane.add(getJTextFieldC_Name(), null); + jContentPane.add(jLabelToken, null); + jContentPane.add(getJTextFieldToken(), null); + jContentPane.add(jLabelDefaultValue, null); + jContentPane.add(getJTextFieldDefaultValue(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJComboBoxItemType(), null); + jContentPane.add(jLabelDatumType, null); + jContentPane.add(getJComboBoxDatumType(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setLocation(new java.awt.Point(0, 35)); + jStarLabel3 = new StarLabel(); + jStarLabel3.setLocation(new java.awt.Point(0, 60)); + jStarLabel4 = new StarLabel(); + jStarLabel4.setLocation(new java.awt.Point(0, 110)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + jContentPane.add(jStarLabel3, null); + jContentPane.add(jStarLabel4, null); + } + return jContentPane; + } + + /** + This method initializes Usage type, Item type and Datum type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("DEFAULT"); + + jComboBoxItemType.addItem("FEATURE_FLAG"); + jComboBoxItemType.addItem("FIXED_AT_BUILD"); + jComboBoxItemType.addItem("PATCHABLE_IN_MODULE"); + jComboBoxItemType.addItem("DYNAMIC"); + jComboBoxItemType.addItem("DYNAMIC_EX"); + + jComboBoxDatumType.addItem("UINT8"); + jComboBoxDatumType.addItem("UINT16"); + jComboBoxDatumType.addItem("UINT32"); + jComboBoxDatumType.addItem("UINT64"); + jComboBoxDatumType.addItem("VOID*"); + jComboBoxDatumType.addItem("BOOLEAN"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + } + + /** + Get PCDsDocument.PCDs + + @return PCDsDocument.PCDs + + **/ + public PCDsDocument.PCDs getPcds() { + return pcds; + } + + /** + Set PCDsDocument.PCDs + + @param pcds The input data of PCDsDocument.PCDs + + **/ + public void setPcds(PCDsDocument.PCDs pcds) { + this.pcds = pcds; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldC_Name.getText())) { + Log.err("C_Name couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldToken.getText())) { + Log.err("Token couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!isEmpty(this.jTextFieldC_Name.getText()) && !DataValidation.isCName(this.jTextFieldC_Name.getText())) { + Log.err("Incorrect data type for C_Name"); + return false; + } + if (!isEmpty(this.jTextFieldToken.getText()) && !DataValidation.isToken(this.jTextFieldToken.getText())) { + Log.err("Incorrect data type for Token"); + return false; + } + + return true; + } + + /** + Save all components of PCDs + if exists pcds, set the value directly + if not exists pcds, new an instance first + + **/ + public void save() { + try { + if (this.pcds == null) { + pcds = PCDsDocument.PCDs.Factory.newInstance(); + } + PCDsDocument.PCDs.PcdData pcdData = PCDsDocument.PCDs.PcdData.Factory.newInstance(); + if (!isEmpty(this.jTextFieldC_Name.getText())) { + pcdData.setCName(this.jTextFieldC_Name.getText()); + } + if (!isEmpty(this.jTextFieldToken.getText())) { + pcdData.setToken(this.jTextFieldToken.getText()); + } + pcdData.setDatumType(PcdDataTypes.Enum.forString(this.jComboBoxDatumType.getSelectedItem().toString())); + if (!isEmpty(this.jTextFieldDefaultValue.getText())) { + pcdData.setDefaultValue(this.jTextFieldDefaultValue.getText()); + } + pcdData.setItemType(PcdItemTypes.Enum.forString(this.jComboBoxItemType.getSelectedItem().toString())); + pcdData.setPcdUsage(PcdUsage.Enum.forString(this.jComboBoxUsage.getSelectedItem().toString())); + + + if (location > -1) { + pcds.setPcdDataArray(location, pcdData); + } else { + pcds.addNewPcdData(); + pcds.setPcdDataArray(pcds.getPcdDataList().size() - 1, pcdData); + } + } catch (Exception e) { + Log.err("Update Hobs", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModulePpis.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModulePpis.java new file mode 100644 index 0000000000..41435d1483 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModulePpis.java @@ -0,0 +1,711 @@ +/** @file + + The file is used to create, update Ppi of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; + +import org.tianocore.PPIsDocument; +import org.tianocore.PpiNotifyUsage; +import org.tianocore.PpiUsage; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IDefaultMutableTreeNode; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update Ppi of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModulePpis extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -4284901202357037724L; + + // + //Define class members + // + private PPIsDocument.PPIs ppis = null; + + private int location = -1; + + private static int PPI = 1; + + private static int PPI_NOTIFY = 2; + + private JPanel jContentPane = null; + + private JRadioButton jRadioButtonPpi = null; + + private JRadioButton jRadioButtonPpiNotify = null; + + private JLabel jLabelC_Name = null; + + private JTextField jTextFieldC_Name = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JTextField jTextFieldFeatureFlag = null; + + private JLabel jLabelFeatureFlag = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JLabel jLabelEnableFeature = null; + + private JRadioButton jRadioButtonEnableFeature = null; + + private JRadioButton jRadioButtonDisableFeature = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelPpiType = null; + + private JButton jButtonGenerateGuid = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + /** + This method initializes jRadioButtonPpi + + @return javax.swing.JRadioButton jRadioButtonPpi + + **/ + private JRadioButton getJRadioButtonPpiType() { + if (jRadioButtonPpi == null) { + jRadioButtonPpi = new JRadioButton(); + jRadioButtonPpi.setText("Ppi"); + jRadioButtonPpi.setBounds(new java.awt.Rectangle(160, 10, 100, 20)); + jRadioButtonPpi.addActionListener(this); + jRadioButtonPpi.setSelected(true); + } + return jRadioButtonPpi; + } + + /** + This method initializes jRadioButtonPpiNotify + + @return javax.swing.JRadioButton jRadioButtonPpiNotify + + **/ + private JRadioButton getJRadioButtonPpiNotify() { + if (jRadioButtonPpiNotify == null) { + jRadioButtonPpiNotify = new JRadioButton(); + jRadioButtonPpiNotify.setText("Ppi Notify"); + jRadioButtonPpiNotify.setBounds(new java.awt.Rectangle(320, 10, 100, 20)); + jRadioButtonPpiNotify.addActionListener(this); + } + return jRadioButtonPpiNotify; + } + + /** + This method initializes jTextFieldC_Name + + @return javax.swing.JTextField jTextFieldC_Name + + **/ + private JTextField getJTextFieldC_Name() { + if (jTextFieldC_Name == null) { + jTextFieldC_Name = new JTextField(); + jTextFieldC_Name.setBounds(new java.awt.Rectangle(160, 35, 320, 20)); + } + return jTextFieldC_Name; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 60, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldFeatureFlag + + @return javax.swing.JTextField jTextFieldFeatureFlag + + **/ + private JTextField getJTextFieldFeatureFlag() { + if (jTextFieldFeatureFlag == null) { + jTextFieldFeatureFlag = new JTextField(); + jTextFieldFeatureFlag.setBounds(new java.awt.Rectangle(160, 135, 320, 20)); + } + return jTextFieldFeatureFlag; + } + + /** + This method initializes jComboBox + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBox() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 85, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jRadioButtonEnableFeature + + @return javax.swing.JRadioButton jRadioButtonEnableFeature + + **/ + private JRadioButton getJRadioButtonEnableFeature() { + if (jRadioButtonEnableFeature == null) { + jRadioButtonEnableFeature = new JRadioButton(); + jRadioButtonEnableFeature.setText("Enable"); + jRadioButtonEnableFeature.setBounds(new java.awt.Rectangle(160, 110, 90, 20)); + jRadioButtonEnableFeature.addActionListener(this); + jRadioButtonEnableFeature.setSelected(true); + } + return jRadioButtonEnableFeature; + } + + /** + This method initializes jRadioButtonDisableFeature + + @return javax.swing.JRadioButton jRadioButtonDisableFeature + + **/ + private JRadioButton getJRadioButtonDisableFeature() { + if (jRadioButtonDisableFeature == null) { + jRadioButtonDisableFeature = new JRadioButton(); + jRadioButtonDisableFeature.setText("Disable"); + jRadioButtonDisableFeature.setBounds(new java.awt.Rectangle(320, 110, 90, 20)); + jRadioButtonDisableFeature.addActionListener(this); + } + return jRadioButtonDisableFeature; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 190, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 190, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 60, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 160, 320, 20)); + } + return jTextFieldOverrideID; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModulePpis() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inPpis The input data of PPIsDocument.PPIs + + **/ + public ModulePpis(PPIsDocument.PPIs inPpis) { + super(); + init(inPpis); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inPpis The input data of PPIsDocument.PPIs + @param type The input data of node type + @param index The input data of node index + + **/ + public ModulePpis(PPIsDocument.PPIs inPpis, int type, int index) { + super(); + init(inPpis, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inPpis The input data of PPIsDocument.PPIs + + **/ + private void init(PPIsDocument.PPIs inPpis) { + init(); + this.setPpis(inPpis); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inPpis The input data of PPIsDocument.PPIs + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(PPIsDocument.PPIs inPpis, int type, int index) { + init(inPpis); + this.location = index; + if (type == IDefaultMutableTreeNode.PPIS_PPI_ITEM) { + initUsage(ModulePpis.PPI); + this.jRadioButtonPpi.setSelected(true); + this.jRadioButtonPpiNotify.setSelected(false); + if (this.ppis.getPpiArray(index).getStringValue() != null) { + this.jTextFieldC_Name.setText(this.ppis.getPpiArray(index).getStringValue()); + } + if (this.ppis.getPpiArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.ppis.getPpiArray(index).getGuid()); + } + if (this.ppis.getPpiArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.ppis.getPpiArray(index).getUsage().toString()); + } + this.jRadioButtonEnableFeature.setSelected(this.ppis.getPpiArray(index).getEnableFeature()); + this.jRadioButtonDisableFeature.setSelected(!this.ppis.getPpiArray(index).getEnableFeature()); + if (this.ppis.getPpiArray(index).getFeatureFlag() != null) { + this.jTextFieldFeatureFlag.setText(this.ppis.getPpiArray(index).getFeatureFlag()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.ppis.getPpiArray(index).getOverrideID())); + } else if (type == IDefaultMutableTreeNode.PPIS_PPINOTIFY_ITEM) { + initUsage(ModulePpis.PPI_NOTIFY); + this.jRadioButtonPpi.setSelected(false); + this.jRadioButtonPpiNotify.setSelected(true); + if (this.ppis.getPpiNotifyArray(index).getStringValue() != null) { + this.jTextFieldC_Name.setText(this.ppis.getPpiNotifyArray(index).getStringValue()); + } + if (this.ppis.getPpiNotifyArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.ppis.getPpiNotifyArray(index).getGuid()); + } + if (this.ppis.getPpiNotifyArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.ppis.getPpiNotifyArray(index).getUsage().toString()); + } + this.jRadioButtonEnableFeature.setSelected(this.ppis.getPpiNotifyArray(index).getEnableFeature()); + this.jRadioButtonDisableFeature.setSelected(!this.ppis.getPpiNotifyArray(index).getEnableFeature()); + if (this.ppis.getPpiNotifyArray(index).getFeatureFlag() != null) { + this.jTextFieldFeatureFlag.setText(this.ppis.getPpiNotifyArray(index).getFeatureFlag()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.ppis.getPpiNotifyArray(index).getOverrideID())); + } + this.jRadioButtonPpi.setEnabled(false); + this.jRadioButtonPpiNotify.setEnabled(false); + } + + /** + This method initializes this + + **/ + private void init() { + this.setContentPane(getJContentPane()); + this.setTitle("Ppis"); + this.setBounds(new java.awt.Rectangle(0, 0, 500, 515)); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jRadioButtonPpi.setEnabled(!isView); + this.jRadioButtonPpiNotify.setEnabled(!isView); + this.jTextFieldC_Name.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jRadioButtonEnableFeature.setEnabled(!isView); + this.jRadioButtonDisableFeature.setEnabled(!isView); + this.jTextFieldFeatureFlag.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 160, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelPpiType = new JLabel(); + jLabelPpiType.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jLabelPpiType.setText("Ppi Type"); + jLabelEnableFeature = new JLabel(); + jLabelEnableFeature.setText("Enable Feature"); + jLabelEnableFeature.setBounds(new java.awt.Rectangle(15, 110, 140, 20)); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelFeatureFlag = new JLabel(); + jLabelFeatureFlag.setText("Feature Flag"); + jLabelFeatureFlag.setBounds(new java.awt.Rectangle(15, 135, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setText("Guid"); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelC_Name = new JLabel(); + jLabelC_Name.setText("C_Name"); + jLabelC_Name.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJRadioButtonPpiType(), null); + jContentPane.add(jLabelC_Name, null); + jContentPane.add(getJTextFieldC_Name(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(getJTextFieldFeatureFlag(), null); + jContentPane.add(jLabelFeatureFlag, null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBox(), null); + jContentPane.add(jLabelEnableFeature, null); + jContentPane.add(getJRadioButtonEnableFeature(), null); + jContentPane.add(getJRadioButtonDisableFeature(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJRadioButtonPpiNotify(), null); + jContentPane.add(jLabelPpiType, null); + jContentPane.add(getJButtonGenerateGuid(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setBounds(new java.awt.Rectangle(0, 10, 10, 20)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setBounds(new java.awt.Rectangle(0, 35, 10, 20)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + } + return jContentPane; + } + + /** + This method initializes Usage type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("PRIVATE"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + // + //Contorl the selected status when click RadionButton + //Do not use Radio Button Group + // + if (arg0.getSource() == jRadioButtonPpi) { + if (jRadioButtonPpi.isSelected()) { + jRadioButtonPpiNotify.setSelected(false); + initUsage(ModulePpis.PPI); + } + if (!jRadioButtonPpiNotify.isSelected() && !jRadioButtonPpi.isSelected()) { + jRadioButtonPpi.setSelected(true); + initUsage(ModulePpis.PPI); + } + } + + if (arg0.getSource() == jRadioButtonPpiNotify) { + if (jRadioButtonPpiNotify.isSelected()) { + jRadioButtonPpi.setSelected(false); + initUsage(ModulePpis.PPI_NOTIFY); + } + if (!jRadioButtonPpiNotify.isSelected() && !jRadioButtonPpi.isSelected()) { + jRadioButtonPpiNotify.setSelected(true); + initUsage(ModulePpis.PPI_NOTIFY); + } + } + + // + //Contorl the selected status when click RadionButton + //Do not use Radio Button Group + // + if (arg0.getSource() == jRadioButtonEnableFeature) { + if (jRadioButtonEnableFeature.isSelected()) { + jRadioButtonDisableFeature.setSelected(false); + } + if (!jRadioButtonDisableFeature.isSelected() && !jRadioButtonEnableFeature.isSelected()) { + jRadioButtonEnableFeature.setSelected(true); + } + } + + if (arg0.getSource() == jRadioButtonDisableFeature) { + if (jRadioButtonDisableFeature.isSelected()) { + jRadioButtonEnableFeature.setSelected(false); + } + if (!jRadioButtonDisableFeature.isSelected() && !jRadioButtonEnableFeature.isSelected()) { + jRadioButtonDisableFeature.setSelected(true); + } + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Get PPIsDocument.PPIs + + @return PPIsDocument.PPIs + + **/ + public PPIsDocument.PPIs getPpis() { + return ppis; + } + + /** + Set PPIsDocument.PPIs + + @param ppis The input data of PPIsDocument.PPIs + + **/ + public void setPpis(PPIsDocument.PPIs ppis) { + this.ppis = ppis; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldC_Name.getText())) { + Log.err("C_Name couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isCName(this.jTextFieldC_Name.getText())) { + Log.err("Incorrect data type for C_Name"); + return false; + } + if (!isEmpty(this.jTextFieldGuid.getText()) && !DataValidation.isGuid(this.jTextFieldGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldFeatureFlag.getText()) + && !DataValidation.isFeatureFlag(this.jTextFieldFeatureFlag.getText())) { + Log.err("Incorrect data type for Feature Flag"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of PPIs + if exists ppis, set the value directly + if not exists ppis, new an instance first + + **/ + public void save() { + try { + if (this.ppis == null) { + ppis = PPIsDocument.PPIs.Factory.newInstance(); + } + if (this.jRadioButtonPpi.isSelected()) { + PPIsDocument.PPIs.Ppi ppi = PPIsDocument.PPIs.Ppi.Factory.newInstance(); + ppi.setStringValue(this.jTextFieldC_Name.getText()); + if (!isEmpty(this.jTextFieldGuid.getText())) { + ppi.setGuid(this.jTextFieldGuid.getText()); + } + ppi.setUsage(PpiUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + ppi.setEnableFeature(this.jRadioButtonEnableFeature.isSelected()); + if (!isEmpty(this.jTextFieldFeatureFlag.getText())) { + ppi.setFeatureFlag(this.jTextFieldFeatureFlag.getText()); + } + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + ppi.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + ppis.setPpiArray(location, ppi); + } else { + ppis.addNewPpi(); + ppis.setPpiArray(ppis.getPpiList().size() - 1, ppi); + } + } + if (this.jRadioButtonPpiNotify.isSelected()) { + PPIsDocument.PPIs.PpiNotify ppiNotify = PPIsDocument.PPIs.PpiNotify.Factory.newInstance(); + ppiNotify.setStringValue(this.jTextFieldC_Name.getText()); + if (!isEmpty(this.jTextFieldGuid.getText())) { + ppiNotify.setGuid(this.jTextFieldGuid.getText()); + } + ppiNotify.setUsage(PpiNotifyUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + ppiNotify.setEnableFeature(this.jRadioButtonEnableFeature.isSelected()); + if (!isEmpty(this.jTextFieldFeatureFlag.getText())) { + ppiNotify.setFeatureFlag(this.jTextFieldFeatureFlag.getText()); + } + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + ppiNotify.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + ppis.setPpiNotifyArray(location, ppiNotify); + } else { + ppis.addNewPpiNotify(); + ppis.setPpiNotifyArray(ppis.getPpiNotifyList().size() - 1, ppiNotify); + } + } + } catch (Exception e) { + Log.err("Update Protocols", e.getMessage()); + } + } + + /** + Enable/Disable relevant fields via different PPI types + + @param intType The input data of PPI type + + **/ + private void initUsage(int intType) { + jComboBoxUsage.removeAllItems(); + if (intType == ModulePpis.PPI) { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("PRIVATE"); + } + if (intType == ModulePpis.PPI_NOTIFY) { + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleProtocols.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleProtocols.java new file mode 100644 index 0000000000..cd7a9b0324 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleProtocols.java @@ -0,0 +1,705 @@ +/** @file + + The file is used to create, update Protocol of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.module.ui; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; + +import org.tianocore.ProtocolNotifyUsage; +import org.tianocore.ProtocolUsage; +import org.tianocore.ProtocolsDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IDefaultMutableTreeNode; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update Protocol of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleProtocols extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -9084913640747858848L; + + // + //Define class members + // + private ProtocolsDocument.Protocols protocols = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabelC_Name = null; + + private JTextField jTextFieldC_Name = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelFeatureFlag = null; + + private JTextField jTextFieldFeatureFlag = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JLabel jLabelEnableFeature = null; + + private JRadioButton jRadioButtonEnableFeature = null; + + private JRadioButton jRadioButtonDisableFeature = null; + + private JRadioButton jRadioButtonProtocol = null; + + private JRadioButton jRadioButtonProtocolNotify = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + private JLabel jLabelProtocolType = null; + + /** + This method initializes jTextFieldC_Name + + @return javax.swing.JTextField jTextFieldC_Name + + **/ + private JTextField getJTextFieldProtocolName() { + if (jTextFieldC_Name == null) { + jTextFieldC_Name = new JTextField(); + jTextFieldC_Name.setBounds(new java.awt.Rectangle(160, 35, 320, 20)); + } + return jTextFieldC_Name; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 60, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldFeatureFlag + + @return javax.swing.JTextField jTextFieldFeatureFlag + + **/ + private JTextField getJTextFieldFeatureFlag() { + if (jTextFieldFeatureFlag == null) { + jTextFieldFeatureFlag = new JTextField(); + jTextFieldFeatureFlag.setBounds(new java.awt.Rectangle(160, 135, 320, 20)); + } + return jTextFieldFeatureFlag; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 190, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 190, 90, 20)); + jButtonCancel.setPreferredSize(new Dimension(90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxProtocolUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 85, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jRadioButtonEnableFeature + + @return javax.swing.JRadioButton jRadioButtonEnableFeature + + **/ + private JRadioButton getJRadioButtonEnableFeature() { + if (jRadioButtonEnableFeature == null) { + jRadioButtonEnableFeature = new JRadioButton(); + jRadioButtonEnableFeature.setText("Enable"); + jRadioButtonEnableFeature.setBounds(new java.awt.Rectangle(160, 110, 90, 20)); + jRadioButtonEnableFeature.addActionListener(this); + jRadioButtonEnableFeature.setSelected(true); + } + return jRadioButtonEnableFeature; + } + + /** + This method initializes jRadioButtonDisableFeature + + @return javax.swing.JRadioButton jRadioButtonDisableFeature + + **/ + private JRadioButton getJRadioButtonDisableFeature() { + if (jRadioButtonDisableFeature == null) { + jRadioButtonDisableFeature = new JRadioButton(); + jRadioButtonDisableFeature.setText("Disable"); + jRadioButtonDisableFeature.setBounds(new java.awt.Rectangle(320, 110, 90, 20)); + jRadioButtonDisableFeature.addActionListener(this); + } + return jRadioButtonDisableFeature; + } + + /** + This method initializes jRadioButtonProtocol + + @return javax.swing.JRadioButton jRadioButtonProtocol + + **/ + private JRadioButton getJRadioButtonProtocol() { + if (jRadioButtonProtocol == null) { + jRadioButtonProtocol = new JRadioButton(); + jRadioButtonProtocol.setText("Protocol"); + jRadioButtonProtocol.setBounds(new java.awt.Rectangle(160, 10, 90, 20)); + jRadioButtonProtocol.setSelected(true); + jRadioButtonProtocol.addActionListener(this); + } + return jRadioButtonProtocol; + } + + /** + This method initializes jRadioButtonProtocolNotify + + @return javax.swing.JRadioButton jRadioButtonProtocolNotify + + **/ + private JRadioButton getJRadioButtonProtocolNotify() { + if (jRadioButtonProtocolNotify == null) { + jRadioButtonProtocolNotify = new JRadioButton(); + jRadioButtonProtocolNotify.setText("Protocol Notify"); + jRadioButtonProtocolNotify.setBounds(new java.awt.Rectangle(320, 10, 120, 20)); + jRadioButtonProtocolNotify.addActionListener(this); + } + return jRadioButtonProtocolNotify; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 60, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 160, 320, 20)); + } + return jTextFieldOverrideID; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleProtocols() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inProtocol The input data of ProtocolsDocument.Protocols + + **/ + public ModuleProtocols(ProtocolsDocument.Protocols inProtocol) { + super(); + init(inProtocol); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inProtocol The input data of ProtocolsDocument.Protocols + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleProtocols(ProtocolsDocument.Protocols inProtocol, int type, int index) { + super(); + init(inProtocol, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inProtocol The input data of ProtocolsDocument.Protocols + + **/ + private void init(ProtocolsDocument.Protocols inProtocol) { + init(); + this.setProtocols(inProtocol); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inProtocol The input data of ProtocolsDocument.Protocols + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(ProtocolsDocument.Protocols inProtocol, int type, int index) { + init(inProtocol); + this.location = index; + if (type == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOL_ITEM) { + this.jRadioButtonProtocol.setSelected(true); + this.jRadioButtonProtocolNotify.setSelected(false); + if (this.protocols.getProtocolArray(index).getStringValue() != null) { + this.jTextFieldC_Name.setText(this.protocols.getProtocolArray(index).getStringValue()); + } + if (this.protocols.getProtocolArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.protocols.getProtocolArray(index).getGuid()); + } + if (this.protocols.getProtocolArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.protocols.getProtocolArray(index).getUsage().toString()); + } + this.jRadioButtonEnableFeature.setSelected(this.protocols.getProtocolArray(index).getEnableFeature()); + this.jRadioButtonDisableFeature.setSelected(!this.protocols.getProtocolArray(index).getEnableFeature()); + if (this.protocols.getProtocolArray(index).getFeatureFlag() != null) { + this.jTextFieldFeatureFlag.setText(this.protocols.getProtocolArray(index).getFeatureFlag()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.protocols.getProtocolArray(index).getOverrideID())); + } else if (type == IDefaultMutableTreeNode.PROTOCOLS_PROTOCOLNOTIFY_ITEM) { + this.jRadioButtonProtocol.setSelected(false); + this.jRadioButtonProtocolNotify.setSelected(true); + this.jTextFieldFeatureFlag.setEditable(false); + this.jRadioButtonDisableFeature.setEnabled(false); + this.jRadioButtonEnableFeature.setEnabled(false); + this.jComboBoxUsage.setEnabled(false); + if (this.protocols.getProtocolNotifyArray(index).getStringValue() != null) { + this.jTextFieldC_Name.setText(this.protocols.getProtocolNotifyArray(index).getStringValue()); + } + if (this.protocols.getProtocolNotifyArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.protocols.getProtocolNotifyArray(index).getGuid()); + } + if (this.protocols.getProtocolNotifyArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.protocols.getProtocolNotifyArray(index).getUsage().toString()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.protocols.getProtocolNotifyArray(index) + .getOverrideID())); + } + this.jRadioButtonProtocol.setEnabled(false); + this.jRadioButtonProtocolNotify.setEnabled(false); + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setName("JFrame"); + this.setContentPane(getJContentPane()); + this.setTitle("Protocols"); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jRadioButtonProtocol.setEnabled(!isView); + this.jRadioButtonProtocolNotify.setEnabled(!isView); + this.jTextFieldC_Name.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jRadioButtonEnableFeature.setEnabled(!isView); + this.jRadioButtonDisableFeature.setEnabled(!isView); + this.jTextFieldFeatureFlag.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelProtocolType = new JLabel(); + jLabelProtocolType.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jLabelProtocolType.setText("Protocol Type"); + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 160, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelEnableFeature = new JLabel(); + jLabelEnableFeature.setText("Enable Feature"); + jLabelEnableFeature.setBounds(new java.awt.Rectangle(15, 110, 140, 20)); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelFeatureFlag = new JLabel(); + jLabelFeatureFlag.setText("Feature Flag"); + jLabelFeatureFlag.setBounds(new java.awt.Rectangle(15, 135, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setText("Guid"); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelC_Name = new JLabel(); + jLabelC_Name.setText("C_Name"); + jLabelC_Name.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelC_Name, null); + jContentPane.add(getJTextFieldProtocolName(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelFeatureFlag, null); + jContentPane.add(getJTextFieldFeatureFlag(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxProtocolUsage(), null); + jContentPane.add(jLabelEnableFeature, null); + jContentPane.add(getJRadioButtonEnableFeature(), null); + jContentPane.add(getJRadioButtonDisableFeature(), null); + jContentPane.add(getJRadioButtonProtocol(), null); + jContentPane.add(getJRadioButtonProtocolNotify(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + jContentPane.add(jLabelProtocolType, null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setBounds(new java.awt.Rectangle(0, 10, 10, 20)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setBounds(new java.awt.Rectangle(0, 35, 10, 20)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + } + return jContentPane; + } + + /** + This method initializes Usage type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("TO_START"); + jComboBoxUsage.addItem("BY_START"); + jComboBoxUsage.addItem("PRIVATE"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + // + // Contorl the selected status when click RadionButton + // Do not use Radio Button Group + // + if (arg0.getSource() == jRadioButtonProtocol) { + if (jRadioButtonProtocol.isSelected()) { + jRadioButtonProtocolNotify.setSelected(false); + jRadioButtonEnableFeature.setEnabled(true); + jRadioButtonDisableFeature.setEnabled(true); + jTextFieldFeatureFlag.setEnabled(true); + jComboBoxUsage.setEnabled(true); + } + if (!jRadioButtonProtocolNotify.isSelected() && !jRadioButtonProtocol.isSelected()) { + jRadioButtonProtocol.setSelected(true); + jRadioButtonEnableFeature.setEnabled(true); + jRadioButtonDisableFeature.setEnabled(true); + jTextFieldFeatureFlag.setEnabled(true); + jComboBoxUsage.setEnabled(true); + } + } + + if (arg0.getSource() == jRadioButtonProtocolNotify) { + if (jRadioButtonProtocolNotify.isSelected()) { + jRadioButtonProtocol.setSelected(false); + jRadioButtonEnableFeature.setEnabled(false); + jRadioButtonDisableFeature.setEnabled(false); + jTextFieldFeatureFlag.setEnabled(false); + jComboBoxUsage.setSelectedIndex(1); + jComboBoxUsage.setEnabled(false); + } + if (!jRadioButtonProtocolNotify.isSelected() && !jRadioButtonProtocol.isSelected()) { + jRadioButtonProtocolNotify.setSelected(true); + jRadioButtonEnableFeature.setEnabled(false); + jRadioButtonDisableFeature.setEnabled(false); + jTextFieldFeatureFlag.setEnabled(false); + jComboBoxUsage.setSelectedIndex(1); + jComboBoxUsage.setEnabled(false); + } + } + + // + // Contorl the selected status when click RadionButton + // Do not use Radio Button Group + // + if (arg0.getSource() == jRadioButtonEnableFeature) { + if (jRadioButtonEnableFeature.isSelected()) { + jRadioButtonDisableFeature.setSelected(false); + } + if (!jRadioButtonDisableFeature.isSelected() && !jRadioButtonEnableFeature.isSelected()) { + jRadioButtonEnableFeature.setSelected(true); + } + } + + if (arg0.getSource() == jRadioButtonDisableFeature) { + if (jRadioButtonDisableFeature.isSelected()) { + jRadioButtonEnableFeature.setSelected(false); + } + if (!jRadioButtonDisableFeature.isSelected() && !jRadioButtonEnableFeature.isSelected()) { + jRadioButtonDisableFeature.setSelected(true); + } + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Get ProtocolsDocument.Protocols + + @return ProtocolsDocument.Protocols + + **/ + public ProtocolsDocument.Protocols getProtocols() { + return protocols; + } + + /** + Set ProtocolsDocument.Protocols + + @param protocols The input data of ProtocolsDocument.Protocols + + **/ + public void setProtocols(ProtocolsDocument.Protocols protocols) { + this.protocols = protocols; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldC_Name.getText())) { + Log.err("C_Name couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isCName(this.jTextFieldC_Name.getText())) { + Log.err("Incorrect data type for C_Name"); + return false; + } + if (!isEmpty(this.jTextFieldGuid.getText()) && !DataValidation.isGuid(this.jTextFieldGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldFeatureFlag.getText()) + && !DataValidation.isFeatureFlag(this.jTextFieldFeatureFlag.getText())) { + Log.err("Incorrect data type for Feature Flag"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of Protocols + if exists protocols, set the value directly + if not exists protocols, new an instance first + + **/ + public void save() { + try { + if (this.protocols == null) { + protocols = ProtocolsDocument.Protocols.Factory.newInstance(); + } + if (this.jRadioButtonProtocol.isSelected()) { + ProtocolsDocument.Protocols.Protocol protocol = ProtocolsDocument.Protocols.Protocol.Factory + .newInstance(); + protocol.setStringValue(this.jTextFieldC_Name.getText()); + if (!isEmpty(this.jTextFieldGuid.getText())) { + protocol.setGuid(this.jTextFieldGuid.getText()); + } + protocol.setUsage(ProtocolUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + protocol.setEnableFeature(this.jRadioButtonEnableFeature.isSelected()); + if (!isEmpty(this.jTextFieldFeatureFlag.getText())) { + protocol.setFeatureFlag(this.jTextFieldFeatureFlag.getText()); + } + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + protocol.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + protocols.setProtocolArray(location, protocol); + } else { + protocols.addNewProtocol(); + protocols.setProtocolArray(protocols.getProtocolList().size() - 1, protocol); + } + } + if (this.jRadioButtonProtocolNotify.isSelected()) { + ProtocolsDocument.Protocols.ProtocolNotify protocolNofity = ProtocolsDocument.Protocols.ProtocolNotify.Factory + .newInstance(); + protocolNofity.setStringValue(this.jTextFieldC_Name.getText()); + if (!isEmpty(this.jTextFieldGuid.getText())) { + protocolNofity.setGuid(this.jTextFieldGuid.getText()); + } + protocolNofity + .setUsage(ProtocolNotifyUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + protocolNofity.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + protocols.setProtocolNotifyArray(location, protocolNofity); + } else { + protocols.addNewProtocolNotify(); + protocols.setProtocolNotifyArray(protocols.getProtocolNotifyList().size() - 1, protocolNofity); + } + } + } catch (Exception e) { + Log.err("Update Protocols", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleSourceFiles.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleSourceFiles.java new file mode 100644 index 0000000000..036ca9a709 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleSourceFiles.java @@ -0,0 +1,1060 @@ +/** @file + + The file is used to create, update SourceFile of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.util.Vector; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JComboBox; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.tianocore.FilenameDocument; +import org.tianocore.SourceFilesDocument; +import org.tianocore.SupportedArchitectures; +import org.tianocore.ToolChains; +import org.tianocore.common.DataType; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IDefaultMutableTreeNode; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; +import org.tianocore.packaging.workspace.common.Workspace; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +/** + The class is used to create, update SourceFile of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleSourceFiles extends IInternalFrame implements ItemListener { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -6765742852142775378L; + + // + // Define class members + // + private SourceFilesDocument.SourceFiles sourceFiles = null; + + private int location = -1; + + private int intSelectedItemId = 0; + + // + // 1 - Add; 2 - Update + // + private int operation = -1; + + private Workspace ws = new Workspace(); + + private Vector vFileName = new Vector(); + + private Vector vGuid = new Vector(); + + private Vector vPath = new Vector(); + + private Vector vFileType = new Vector(); + + private Vector vToolChain = new Vector(); + + private Vector vOverrideID = new Vector(); + + private JPanel jContentPane = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelFileName = null; + + private JTextField jTextFieldFileName = null; + + private JButton jButtonOpenFile = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JButton jButtonGenerateGuid = null; + + private JComboBox jComboBoxArch = null; + + private JLabel jLabelPath = null; + + private JTextField jTextFieldPath = null; + + private JLabel jLabelFileType = null; + + private JTextField jTextFieldFileType = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private StarLabel jStarLabel1 = null; + + private JComboBox jComboBoxFileList = null; + + private JButton jButtonAdd = null; + + private JButton jButtonRemove = null; + + private JButton jButtonUpdate = null; + + private JCheckBox jCheckBoxArch = null; + + private JLabel jLabelToolChain = null; + + private JComboBox jComboBoxToolChain = null; + + private JScrollPane jScrollPaneFileList = null; + + private JTextArea jTextAreaFileList = null; + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButton() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 340, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButton1() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 340, 90, 20)); + jButtonCancel.setPreferredSize(new java.awt.Dimension(90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jTextFieldFileName + + @return javax.swing.JTextField jTextFieldFileName + + **/ + private JTextField getJTextFieldSourceFilesDirectory() { + if (jTextFieldFileName == null) { + jTextFieldFileName = new JTextField(); + jTextFieldFileName.setBounds(new java.awt.Rectangle(140,10,250,20)); + } + return jTextFieldFileName; + } + + /** + This method initializes jButtonOpenFile + + @return javax.swing.JButton jButtonOpenFile + + **/ + private JButton getJButtonOpenFile() { + if (jButtonOpenFile == null) { + jButtonOpenFile = new JButton(); + jButtonOpenFile.setText("Browse"); + jButtonOpenFile.setBounds(new java.awt.Rectangle(395,10,85,20)); + jButtonOpenFile.addActionListener(this); + } + return jButtonOpenFile; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(140,35,250,20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(395,35,85,20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jComboBoxArch + + @return javax.swing.JComboBox jComboBoxArch + + **/ + private JComboBox getJComboBoxArch() { + if (jComboBoxArch == null) { + jComboBoxArch = new JComboBox(); + jComboBoxArch.setBounds(new java.awt.Rectangle(140, 160, 340, 20)); + jComboBoxArch.setEnabled(false); + } + return jComboBoxArch; + } + + /** + This method initializes jTextFieldPath + + @return javax.swing.JTextField jTextFieldPath + + **/ + private JTextField getJTextFieldPath() { + if (jTextFieldPath == null) { + jTextFieldPath = new JTextField(); + jTextFieldPath.setBounds(new java.awt.Rectangle(140, 60, 340, 20)); + } + return jTextFieldPath; + } + + /** + This method initializes jTextFieldFileType + + @return javax.swing.JTextField jTextFieldFileType + + **/ + private JTextField getJTextFieldFileType() { + if (jTextFieldFileType == null) { + jTextFieldFileType = new JTextField(); + jTextFieldFileType.setBounds(new java.awt.Rectangle(140, 85, 340, 20)); + } + return jTextFieldFileType; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(140, 135, 50, 20)); + } + return jTextFieldOverrideID; + } + + /** + This method initializes jComboBoxFileList + + @return javax.swing.JComboBox jComboBoxFileList + + **/ + private JComboBox getJComboBoxFileList() { + if (jComboBoxFileList == null) { + jComboBoxFileList = new JComboBox(); + jComboBoxFileList.setBounds(new java.awt.Rectangle(15, 185, 210, 20)); + jComboBoxFileList.addItemListener(this); + jComboBoxFileList.addActionListener(this); + } + return jComboBoxFileList; + } + + /** + This method initializes jButtonAdd + + @return javax.swing.JButton jButtonAdd + + **/ + private JButton getJButtonAdd() { + if (jButtonAdd == null) { + jButtonAdd = new JButton(); + jButtonAdd.setBounds(new java.awt.Rectangle(230, 185, 80, 20)); + jButtonAdd.setText("Add"); + jButtonAdd.addActionListener(this); + } + return jButtonAdd; + } + + /** + This method initializes jButtonRemove + + @return javax.swing.JButton jButtonRemove + + **/ + private JButton getJButtonRemove() { + if (jButtonRemove == null) { + jButtonRemove = new JButton(); + jButtonRemove.setBounds(new java.awt.Rectangle(400, 185, 80, 20)); + jButtonRemove.setText("Remove"); + jButtonRemove.addActionListener(this); + } + return jButtonRemove; + } + + /** + This method initializes jButtonUpdate + + @return javax.swing.JButton jButtonUpdate + + **/ + private JButton getJButtonUpdate() { + if (jButtonUpdate == null) { + jButtonUpdate = new JButton(); + jButtonUpdate.setBounds(new java.awt.Rectangle(315, 185, 80, 20)); + jButtonUpdate.setText("Update"); + jButtonUpdate.addActionListener(this); + } + return jButtonUpdate; + } + + /** + This method initializes jCheckBoxArch + + @return javax.swing.JCheckBox jCheckBoxArch + + **/ + private JCheckBox getJCheckBoxArch() { + if (jCheckBoxArch == null) { + jCheckBoxArch = new JCheckBox(); + jCheckBoxArch.setBounds(new java.awt.Rectangle(15, 160, 120, 20)); + jCheckBoxArch.setText("Specific Arch"); + jCheckBoxArch.addActionListener(this); + } + return jCheckBoxArch; + } + + /** + This method initializes jComboBoxToolChain + + @return javax.swing.JComboBox jComboBoxToolChain + + **/ + private JComboBox getJComboBoxToolChain() { + if (jComboBoxToolChain == null) { + jComboBoxToolChain = new JComboBox(); + jComboBoxToolChain.setBounds(new java.awt.Rectangle(140, 110, 340, 20)); + } + return jComboBoxToolChain; + } + + /** + * This method initializes jScrollPaneFileList + * + * @return javax.swing.JScrollPane + */ + private JScrollPane getJScrollPaneFileList() { + if (jScrollPaneFileList == null) { + jScrollPaneFileList = new JScrollPane(); + jScrollPaneFileList.setBounds(new java.awt.Rectangle(15,210,465,240)); + jScrollPaneFileList.setViewportView(getJTextAreaFileList()); + } + return jScrollPaneFileList; + } + + /** + * This method initializes jTextAreaFileList + * + * @return javax.swing.JTextArea + */ + private JTextArea getJTextAreaFileList() { + if (jTextAreaFileList == null) { + jTextAreaFileList = new JTextArea(); + jTextAreaFileList.setEditable(false); + } + return jTextAreaFileList; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleSourceFiles() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inSourceFiles The input data of SourceFilesDocument.SourceFiles + + **/ + public ModuleSourceFiles(SourceFilesDocument.SourceFiles inSourceFiles) { + super(); + init(inSourceFiles); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inSourceFiles The input data of SourceFilesDocument.SourceFiles + @param type The input data of node type + @param index The input data of node index + @param inOperation The input data of current operation type + + **/ + public ModuleSourceFiles(SourceFilesDocument.SourceFiles inSourceFiles, int type, int index, int inOperation) { + super(); + init(inSourceFiles, type, index, inOperation); + this.operation = inOperation; + this.setVisible(true); + } + + /** + This method initializes this + + @param inSourceFiles The input data of SourceFilesDocument.SourceFiles + + **/ + private void init(SourceFilesDocument.SourceFiles inSourceFiles) { + init(); + this.setSourceFiles(inSourceFiles); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + + @param inSourceFiles The input data of SourceFilesDocument.SourceFiles + @param type The input data of node type + @param index The input data of node index + @param inOperation The input data of current operation type + + **/ + private void init(SourceFilesDocument.SourceFiles inSourceFiles, int type, int index, int inOperation) { + init(inSourceFiles); + this.location = index; + this.operation = inOperation; + + // + // When update + // + if (operation == 2) { + this.jCheckBoxArch.setEnabled(false); + this.jComboBoxArch.setEnabled(false); + + if (type == IDefaultMutableTreeNode.SOURCEFILES_FILENAME) { + if (this.sourceFiles.getFilenameList().size() > 0) { + for (int indexI = 0; indexI < this.sourceFiles.getFilenameList().size(); indexI++) { + if (this.sourceFiles.getFilenameArray(indexI).getStringValue() != null) { + vFileName.addElement(this.sourceFiles.getFilenameArray(indexI).getStringValue()); + } else { + vFileName.addElement(""); + } + if (this.sourceFiles.getFilenameArray(indexI).getGuid() != null) { + vGuid.addElement(this.sourceFiles.getFilenameArray(indexI).getGuid()); + } else { + vGuid.addElement(""); + } + if (this.sourceFiles.getFilenameArray(indexI).getPath() != null) { + vPath.addElement(this.sourceFiles.getFilenameArray(indexI).getPath()); + } else { + vPath.addElement(""); + } + if (this.sourceFiles.getFilenameArray(indexI).getFileType() != null) { + vFileType.addElement(this.sourceFiles.getFilenameArray(indexI).getFileType()); + } else { + vFileType.addElement(""); + } + if (this.sourceFiles.getFilenameArray(indexI).getToolChain() != null) { + vToolChain.addElement(this.sourceFiles.getFilenameArray(indexI).getToolChain().toString()); + } else { + vToolChain.addElement(DataType.EMPTY_SELECT_ITEM); + } + vOverrideID.addElement(String.valueOf(this.sourceFiles.getFilenameArray(indexI).getOverrideID())); + jComboBoxFileList.addItem(this.sourceFiles.getFilenameArray(indexI).getStringValue()); + } + } + } + if (type == IDefaultMutableTreeNode.SOURCEFILES_ARCH_ITEM) { + this.jCheckBoxArch.setSelected(true); + this.jComboBoxArch.setSelectedItem(this.sourceFiles.getArchArray(index).getArchType().toString()); + for (int indexI = 0; indexI < this.sourceFiles.getArchArray(index).getFilenameList().size(); indexI++) { + if (this.sourceFiles.getArchArray(index).getFilenameArray(indexI).getStringValue() != null) { + vFileName.addElement(this.sourceFiles.getArchArray(index).getFilenameArray(indexI) + .getStringValue()); + } else { + vFileName.addElement(""); + } + if (this.sourceFiles.getArchArray(index).getFilenameArray(indexI).getGuid() != null) { + vGuid.addElement(this.sourceFiles.getArchArray(index).getFilenameArray(indexI).getGuid()); + } else { + vGuid.addElement(""); + } + if (this.sourceFiles.getArchArray(index).getFilenameArray(indexI).getPath() != null) { + vPath.addElement(this.sourceFiles.getArchArray(index).getFilenameArray(indexI).getPath()); + } else { + vPath.addElement(""); + } + if (this.sourceFiles.getArchArray(index).getFilenameArray(indexI).getFileType() != null) { + vFileType.addElement(this.sourceFiles.getArchArray(index).getFilenameArray(indexI) + .getFileType()); + } else { + vFileType.addElement(""); + } + if (this.sourceFiles.getArchArray(index).getFilenameArray(indexI).getToolChain() != null) { + vToolChain.addElement(this.sourceFiles.getArchArray(index).getFilenameArray(indexI) + .getToolChain().toString()); + } else { + vToolChain.addElement(""); + } + vOverrideID.addElement(String.valueOf(this.sourceFiles.getArchArray(index).getFilenameArray(indexI) + .getOverrideID())); + jComboBoxFileList.addItem(this.sourceFiles.getArchArray(index).getFilenameArray(indexI) + .getStringValue()); + } + } + // + // Update the file list + // + reloadFileListArea(); + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Source Files"); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jButtonOk.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jTextFieldFileName.setEnabled(!isView); + this.jButtonOpenFile.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jTextFieldPath.setEnabled(!isView); + this.jTextFieldFileType.setEnabled(!isView); + this.jComboBoxToolChain.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + + this.jButtonAdd.setEnabled(!isView); + this.jButtonRemove.setEnabled(!isView); + this.jButtonUpdate.setEnabled(!isView); + this.jCheckBoxArch.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelToolChain = new JLabel(); + jLabelToolChain.setBounds(new java.awt.Rectangle(15, 110, 120, 20)); + jLabelToolChain.setText("Tool Chain"); + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 135, 120, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelFileType = new JLabel(); + jLabelFileType.setBounds(new java.awt.Rectangle(15, 85, 120, 20)); + jLabelFileType.setText("File Type"); + jLabelPath = new JLabel(); + jLabelPath.setBounds(new java.awt.Rectangle(15, 60, 120, 20)); + jLabelPath.setText("Path"); + jLabelGuid = new JLabel(); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 120, 20)); + jLabelGuid.setText("Guid"); + jLabelFileName = new JLabel(); + jLabelFileName.setText("File Name"); + jLabelFileName.setBounds(new java.awt.Rectangle(15, 10, 120, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setSize(new java.awt.Dimension(480,400)); + jContentPane.add(getJButton(), null); + jContentPane.add(getJButton1(), null); + jContentPane.add(jLabelFileName, null); + jContentPane.add(getJTextFieldSourceFilesDirectory(), null); + jContentPane.add(getJButtonOpenFile(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(getJComboBoxArch(), null); + jContentPane.add(jLabelPath, null); + jContentPane.add(getJTextFieldPath(), null); + jContentPane.add(jLabelFileType, null); + jContentPane.add(getJTextFieldFileType(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(getJComboBoxFileList(), null); + jContentPane.add(getJButtonAdd(), null); + jContentPane.add(getJButtonRemove(), null); + jContentPane.add(getJButtonUpdate(), null); + jContentPane.add(getJCheckBoxArch(), null); + jContentPane.add(jLabelToolChain, null); + jContentPane.add(getJComboBoxToolChain(), null); + + jContentPane.add(getJScrollPaneFileList(), null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + if (arg0.getSource() == jButtonOpenFile) { + selectFile(); + } + if (arg0.getSource() == jButtonAdd) { + if (!checkAdd()) { + return; + } + addToList(); + } + if (arg0.getSource() == jButtonRemove) { + removeFromList(); + } + if (arg0.getSource() == jButtonUpdate) { + if (!checkAdd()) { + return; + } + updateForList(); + } + + // + //When and only when checked Arch box then can choose different arch types + // + if (arg0.getSource() == jCheckBoxArch) { + if (this.jCheckBoxArch.isSelected()) { + this.jComboBoxArch.setEnabled(true); + } else { + this.jComboBoxArch.setEnabled(false); + } + } + } + + /** + This method initializes Usage type and Arch type + + **/ + private void initFrame() { + jComboBoxArch.addItem("ALL"); + jComboBoxArch.addItem("EBC"); + jComboBoxArch.addItem("ARM"); + jComboBoxArch.addItem("IA32"); + jComboBoxArch.addItem("X64"); + jComboBoxArch.addItem("IPF"); + jComboBoxArch.addItem("PPC"); + + jComboBoxToolChain.addItem(DataType.EMPTY_SELECT_ITEM); + jComboBoxToolChain.addItem("MSFT"); + jComboBoxToolChain.addItem("INTEL"); + jComboBoxToolChain.addItem("GCC"); + jComboBoxToolChain.addItem("CYGWIN"); + } + + /** + Add current item to Vector + + **/ + private void addToList() { + intSelectedItemId = vFileName.size(); + vFileName.addElement(this.jTextFieldFileName.getText()); + vGuid.addElement(this.jTextFieldGuid.getText()); + vPath.addElement(this.jTextFieldPath.getText()); + vFileType.addElement(this.jTextFieldFileType.getText()); + vToolChain.addElement(this.jComboBoxToolChain.getSelectedItem().toString()); + vOverrideID.addElement(this.jTextFieldOverrideID.getText()); + jComboBoxFileList.addItem(this.jTextFieldFileName.getText()); + jComboBoxFileList.setSelectedItem(this.jTextFieldFileName.getText()); + + // + // Reset select item index + // + intSelectedItemId = vFileName.size(); + + // + // Reload all fields of selected item + // + reloadFromList(); + } + + /** + Remove current item from Vector + + **/ + private void removeFromList() { + int intTempIndex = intSelectedItemId; + if (vFileName.size() < 1) { + return; + } + + jComboBoxFileList.removeItemAt(intSelectedItemId); + + vFileName.removeElementAt(intTempIndex); + vGuid.removeElementAt(intTempIndex); + vPath.removeElementAt(intTempIndex); + vFileType.removeElementAt(intTempIndex); + vToolChain.removeElementAt(intTempIndex); + vOverrideID.removeElementAt(intTempIndex); + + // + // Reload all fields of selected item + // + reloadFromList(); + } + + /** + Update current item of Vector + + **/ + private void updateForList() { + // + // Backup selected item index + // + int intTempIndex = intSelectedItemId; + vFileName.setElementAt(this.jTextFieldFileName.getText(), intSelectedItemId); + vGuid.setElementAt(this.jTextFieldGuid.getText(), intSelectedItemId); + vPath.setElementAt(this.jTextFieldPath.getText(), intSelectedItemId); + vFileType.setElementAt(this.jTextFieldFileType.getText(), intSelectedItemId); + vToolChain.setElementAt(this.jComboBoxToolChain.getSelectedItem().toString(), intSelectedItemId); + vOverrideID.setElementAt(this.jTextFieldOverrideID.getText(), intSelectedItemId); + jComboBoxFileList.removeAllItems(); + for (int index = 0; index < vFileName.size(); index++) { + jComboBoxFileList.addItem(vFileName.elementAt(index)); + } + + // + // Restore selected item index + // + intSelectedItemId = intTempIndex; + + // + // Reset select item index + // + jComboBoxFileList.setSelectedIndex(intSelectedItemId); + + // + // Reload all fields of selected item + // + reloadFromList(); + } + + /** + Refresh all fields' values of selected item of Vector + + **/ + private void reloadFromList() { + if (vFileName.size() > 0) { + // + // Get selected item index + // + intSelectedItemId = jComboBoxFileList.getSelectedIndex(); + + this.jTextFieldFileName.setText(vFileName.elementAt(intSelectedItemId).toString()); + this.jTextFieldGuid.setText(vGuid.elementAt(intSelectedItemId).toString()); + this.jTextFieldPath.setText(vPath.elementAt(intSelectedItemId).toString()); + this.jTextFieldFileType.setText(vFileType.elementAt(intSelectedItemId).toString()); + this.jComboBoxToolChain.setSelectedItem(vToolChain.elementAt(intSelectedItemId).toString()); + this.jTextFieldOverrideID.setText(vOverrideID.elementAt(intSelectedItemId).toString()); + } else { + this.jTextFieldFileName.setText(""); + this.jTextFieldGuid.setText(""); + this.jTextFieldPath.setText(""); + this.jTextFieldFileType.setText(""); + this.jComboBoxToolChain.setSelectedItem(DataType.EMPTY_SELECT_ITEM); + this.jTextFieldOverrideID.setText(""); + } + + reloadFileListArea(); + } + + /* (non-Javadoc) + * @see java.awt.event.ItemListener#itemStateChanged(java.awt.event.ItemEvent) + * + * Reflesh the frame when selected item changed + * + */ + public void itemStateChanged(ItemEvent arg0) { + if (arg0.getStateChange() == ItemEvent.SELECTED) { + reloadFromList(); + } + } + + /** + Get SourceFilesDocument.SourceFiles + + @return SourceFilesDocument.SourceFiles + + **/ + public SourceFilesDocument.SourceFiles getSourceFiles() { + return sourceFiles; + } + + /** + Set SourceFilesDocument.SourceFiles + + @param sourceFiles The input data of SourceFilesDocument.SourceFiles + + **/ + public void setSourceFiles(SourceFilesDocument.SourceFiles sourceFiles) { + this.sourceFiles = sourceFiles; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + if (this.jComboBoxFileList.getItemCount() < 1) { + Log.err("Must have one file at least!"); + return false; + } + return true; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean checkAdd() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldFileName.getText())) { + Log.err("File Name couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isFileName(this.jTextFieldFileName.getText())) { + Log.err("Incorrect data type for File Name"); + return false; + } + if (!isEmpty(this.jTextFieldGuid.getText()) && !DataValidation.isGuid(this.jTextFieldGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldPath.getText()) && !DataValidation.isPath(this.jTextFieldPath.getText())) { + Log.err("Incorrect data type for Path"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of SourceFiles + if exists sourceFiles, set the value directly + if not exists sourceFiles, new an instance first + + **/ + public void save() { + try { + if (this.sourceFiles == null) { + sourceFiles = SourceFilesDocument.SourceFiles.Factory.newInstance(); + } + // + //Save as file name + // + if (!this.jCheckBoxArch.isSelected()) { + if (this.operation == 2) { //Add new filename + // + //First remove all existed filename + // + if (sourceFiles.getFilenameList().size() > 0) { + for (int index = sourceFiles.getFilenameList().size() - 1; index >= 0; index--) { + sourceFiles.removeFilename(index); + } + } + } + for (int index = 0; index < vFileName.size(); index++) { + FilenameDocument.Filename filename = FilenameDocument.Filename.Factory.newInstance(); + if (!isEmpty(vFileName.elementAt(index).toString())) { + filename.setStringValue(vFileName.elementAt(index).toString()); + } + if (!isEmpty(vGuid.elementAt(index).toString())) { + filename.setGuid(vGuid.elementAt(index).toString()); + } + if (!isEmpty(vPath.elementAt(index).toString())) { + filename.setPath(vPath.elementAt(index).toString()); + } + if (!isEmpty(vFileType.elementAt(index).toString())) { + filename.setFileType(vFileType.elementAt(index).toString()); + } + if (!vToolChain.elementAt(index).toString().equals(DataType.EMPTY_SELECT_ITEM)) { + filename.setToolChain(ToolChains.Enum.forString(vToolChain.elementAt(index).toString())); + } + if (!isEmpty(vOverrideID.elementAt(index).toString())) { + filename.setOverrideID(Integer.parseInt(vOverrideID.elementAt(index).toString())); + } + sourceFiles.addNewFilename(); + sourceFiles.setFilenameArray(sourceFiles.getFilenameList().size() - 1, filename); + } + } + // + //Save as Arch + // + if (this.jCheckBoxArch.isSelected()) { + SourceFilesDocument.SourceFiles.Arch arch = SourceFilesDocument.SourceFiles.Arch.Factory.newInstance(); + if (this.operation == 2) { + // + //First remove all existed filename + // + for (int index = sourceFiles.getArchArray(location).getFilenameList().size() - 1; index >= 0; index--) { + sourceFiles.getArchArray(location).removeFilename(index); + } + } + for (int index = 0; index < vFileName.size(); index++) { + FilenameDocument.Filename filename = FilenameDocument.Filename.Factory.newInstance(); + if (!isEmpty(vFileName.elementAt(index).toString())) { + filename.setStringValue(vFileName.elementAt(index).toString()); + } + if (!isEmpty(vGuid.elementAt(index).toString())) { + filename.setGuid(vGuid.elementAt(index).toString()); + } + if (!isEmpty(vPath.elementAt(index).toString())) { + filename.setPath(vPath.elementAt(index).toString()); + } + if (!isEmpty(vFileType.elementAt(index).toString())) { + filename.setFileType(vFileType.elementAt(index).toString()); + } + if (!vToolChain.elementAt(index).toString().equals(DataType.EMPTY_SELECT_ITEM)) { + filename.setToolChain(ToolChains.Enum.forString(vToolChain.elementAt(index).toString())); + } + if (!isEmpty(vOverrideID.elementAt(index).toString())) { + filename.setOverrideID(Integer.parseInt(vOverrideID.elementAt(index).toString())); + } + arch.addNewFilename(); + arch.setFilenameArray(arch.getFilenameList().size() - 1, filename); + } + arch + .setArchType(SupportedArchitectures.Enum.forString(this.jComboBoxArch.getSelectedItem().toString())); + if (location > -1) { + sourceFiles.setArchArray(location, arch); + } else { + sourceFiles.addNewArch(); + sourceFiles.setArchArray(sourceFiles.getArchList().size() - 1, arch); + } + } + } catch (Exception e) { + Log.err("Update Source Files", e.getMessage()); + } + } + + /** + Display a file open browser to let user select file + + **/ + private void selectFile() { + JFileChooser fc = new JFileChooser(ws.getCurrentWorkspace()); + + int result = fc.showOpenDialog(new JPanel()); + if (result == JFileChooser.APPROVE_OPTION) { + this.jTextFieldFileName.setText(fc.getSelectedFile().getName()); + } + } + + /** + Update file list pane via the elements of Vector + + **/ + private void reloadFileListArea() { + String strFileList = ""; + for (int index = 0; index < vFileName.size(); index++) { + strFileList = strFileList + vFileName.elementAt(index).toString() + DataType.UNXI_LINE_SEPARATOR; + } + this.jTextAreaFileList.setText(strFileList); + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleSystemTables.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleSystemTables.java new file mode 100644 index 0000000000..aeaf88f9fd --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleSystemTables.java @@ -0,0 +1,393 @@ +/** @file + + The file is used to create, update SystemTable of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.tianocore.SystemTableUsage; +import org.tianocore.SystemTablesDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update SystemTable of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleSystemTables extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = 7488769180379442276L; + + // + //Define class members + // + private SystemTablesDocument.SystemTables systemTables = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabelEntry = null; + + private JTextField jTextFieldEntry = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private StarLabel jStarLabel1 = null; + + /** + This method initializes jTextFieldEntry + + @return javax.swing.JTextField jTextFieldEntry + + **/ + private JTextField getJTextFieldEntry() { + if (jTextFieldEntry == null) { + jTextFieldEntry = new JTextField(); + jTextFieldEntry.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldEntry; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 35, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(280, 90, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 90, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jTextFieldOverrideID; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleSystemTables() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inSystemTables The input data of SystemTablesDocument.SystemTables + + **/ + public ModuleSystemTables(SystemTablesDocument.SystemTables inSystemTables) { + super(); + init(inSystemTables); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inSystemTables The input data of SystemTablesDocument.SystemTables + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleSystemTables(SystemTablesDocument.SystemTables inSystemTables, int type, int index) { + super(); + init(inSystemTables, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inSystemTables The input data of SystemTablesDocument.SystemTables + + **/ + private void init(SystemTablesDocument.SystemTables inSystemTables) { + init(); + this.setSystemTables(inSystemTables); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inSystemTables The input data of SystemTablesDocument.SystemTables + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(SystemTablesDocument.SystemTables inSystemTables, int type, int index) { + init(inSystemTables); + this.location = index; + if (this.systemTables.getSystemTableList().size() > 0) { + if (this.systemTables.getSystemTableArray(index).getEntry() != null) { + this.jTextFieldEntry.setText(this.systemTables.getSystemTableArray(index).getEntry()); + } + if (this.systemTables.getSystemTableArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.systemTables.getSystemTableArray(index).getUsage().toString()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.systemTables.getSystemTableArray(index) + .getOverrideID())); + } + } + + /** + This method initializes this + + @return void + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("System Tables"); + initFrame(); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldEntry.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelOverrideID.setText("Override ID"); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelEntry = new JLabel(); + jLabelEntry.setText("Entry"); + jLabelEntry.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelEntry, null); + jContentPane.add(getJTextFieldEntry(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setBounds(new java.awt.Rectangle(0, 10, 10, 20)); + + jContentPane.add(jStarLabel1, null); + } + return jContentPane; + } + + /** + This method initializes Usage type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("PRIVATE"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + } + + /** + Get SystemTablesDocument.SystemTables + + @return SystemTablesDocument.SystemTables + + **/ + public SystemTablesDocument.SystemTables getSystemTables() { + return systemTables; + } + + /** + Set SystemTablesDocument.SystemTables + + @param systemTables The input data of SystemTablesDocument.SystemTables + + **/ + public void setSystemTables(SystemTablesDocument.SystemTables systemTables) { + this.systemTables = systemTables; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldEntry.getText())) { + Log.err("Entry couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of SystemTables + if exists systemTables, set the value directly + if not exists systemTables, new an instance first + + **/ + public void save() { + try { + if (this.systemTables == null) { + systemTables = SystemTablesDocument.SystemTables.Factory.newInstance(); + } + SystemTablesDocument.SystemTables.SystemTable systemTable = SystemTablesDocument.SystemTables.SystemTable.Factory + .newInstance(); + systemTable.setEntry(this.jTextFieldEntry.getText()); + + systemTable.setUsage(SystemTableUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + systemTable.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + systemTables.setSystemTableArray(location, systemTable); + } else { + systemTables.addNewSystemTable(); + systemTables.setSystemTableArray(systemTables.getSystemTableList().size() - 1, systemTable); + } + } catch (Exception e) { + Log.err("Update System Tables", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleVariables.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleVariables.java new file mode 100644 index 0000000000..90a28591f5 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/ModuleVariables.java @@ -0,0 +1,601 @@ +/** @file + + The file is used to create, update Variable of MSA/MBD file + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; + +import org.tianocore.GuidDocument; +import org.tianocore.VariableUsage; +import org.tianocore.VariablesDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update Variable of MSA/MBD file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class ModuleVariables extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -6998982978030439446L; + + // + //Define class members + // + private VariablesDocument.Variables variables = null; + + private int location = -1; + + private JPanel jContentPane = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelString = null; + + private JTextField jTextFieldString = null; + + private JLabel jLabelBitOffset = null; + + private JTextField jTextFieldBitOffset = null; + + private JLabel jLabelByteOffset = null; + + private JTextField jTextFieldByteOffset = null; + + private JLabel jLabelOffsetBitSize = null; + + private JTextField jTextFieldOffsetBitSize = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + private JLabel jLabelByteOffsetHint = null; + + private JLabel jLabelBitOffsetHint = null; + + private JLabel jLabelOffsetBitSizeHint = null; + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setSize(new java.awt.Dimension(250, 20)); + jTextFieldGuid.setLocation(new java.awt.Point(160, 35)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldString + + @return javax.swing.JTextField jTextFieldString + + **/ + private JTextField getJTextFieldString() { + if (jTextFieldString == null) { + jTextFieldString = new JTextField(); + jTextFieldString.setSize(new java.awt.Dimension(320, 20)); + jTextFieldString.setLocation(new java.awt.Point(160, 10)); + } + return jTextFieldString; + } + + /** + This method initializes jTextFieldBitOffset + + @return javax.swing.JTextField jTextFieldBitOffset + + **/ + private JTextField getJTextFieldBitOffset() { + if (jTextFieldBitOffset == null) { + jTextFieldBitOffset = new JTextField(); + jTextFieldBitOffset.setSize(new java.awt.Dimension(80, 20)); + jTextFieldBitOffset.setLocation(new java.awt.Point(160, 85)); + } + return jTextFieldBitOffset; + } + + /** + This method initializes jTextFieldByteOffset + + @return javax.swing.JTextField jTextFieldByteOffset + + **/ + private JTextField getJTextFieldByteOffset() { + if (jTextFieldByteOffset == null) { + jTextFieldByteOffset = new JTextField(); + jTextFieldByteOffset.setLocation(new java.awt.Point(160, 60)); + jTextFieldByteOffset.setSize(new java.awt.Dimension(80, 20)); + } + return jTextFieldByteOffset; + } + + /** + This method initializes jTextFieldBitSize + + @return javax.swing.JTextField jTextFieldOffsetBitSize + + **/ + private JTextField getJTextFieldOffsetBitSize() { + if (jTextFieldOffsetBitSize == null) { + jTextFieldOffsetBitSize = new JTextField(); + jTextFieldOffsetBitSize.setSize(new java.awt.Dimension(80, 20)); + jTextFieldOffsetBitSize.setLocation(new java.awt.Point(160, 110)); + } + return jTextFieldOffsetBitSize; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox jComboBoxUsage + + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(160, 135, 320, 20)); + } + return jComboBoxUsage; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("Ok"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 190, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 190, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(415, 35, 65, 20)); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField jTextFieldOverrideID + + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(160, 160, 50, 20)); + } + return jTextFieldOverrideID; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public ModuleVariables() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inVariables The input data of VariablesDocument.Variables + + **/ + public ModuleVariables(VariablesDocument.Variables inVariables) { + super(); + init(inVariables); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inVariables The input data of VariablesDocument.Variables + @param type The input data of node type + @param index The input data of node index + + **/ + public ModuleVariables(VariablesDocument.Variables inVariables, int type, int index) { + super(); + init(inVariables, type, index); + this.setVisible(true); + } + + /** + This method initializes this + + @param inVariables The input data of VariablesDocument.Variables + + **/ + private void init(VariablesDocument.Variables inVariables) { + init(); + this.setVariables(inVariables); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inVariables The input data of VariablesDocument.Variables + @param type The input data of node type + @param index The input data of node index + + **/ + private void init(VariablesDocument.Variables inVariables, int type, int index) { + init(inVariables); + this.location = index; + if (this.variables.getVariableList().size() > 0) { + if (this.variables.getVariableArray(index).getString() != null) { + this.jTextFieldString.setText(this.variables.getVariableArray(index).getString()); + } + if (this.variables.getVariableArray(index).getGuid() != null) { + this.jTextFieldGuid.setText(this.variables.getVariableArray(index).getGuid().getStringValue()); + } + if (this.variables.getVariableArray(index).getByteOffset() != null) { + this.jTextFieldByteOffset + .setText(String + .valueOf(this.variables.getVariableArray(index).getByteOffset())); + } + if (String.valueOf(this.variables.getVariableArray(index).getBitOffset()) != null) { + this.jTextFieldBitOffset.setText(String.valueOf(this.variables.getVariableArray(index).getBitOffset())); + } + if (String.valueOf(this.variables.getVariableArray(index).getOffsetBitSize()) != null) { + this.jTextFieldOffsetBitSize.setText(String.valueOf(this.variables.getVariableArray(index) + .getOffsetBitSize())); + } + if (this.variables.getVariableArray(index).getUsage() != null) { + this.jComboBoxUsage.setSelectedItem(this.variables.getVariableArray(index).getUsage().toString()); + } + this.jTextFieldOverrideID.setText(String.valueOf(this.variables.getVariableArray(index).getOverrideID())); + } + } + + /** + This method initializes this + + @return void + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Add Variables"); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldString.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jTextFieldByteOffset.setEnabled(!isView); + this.jTextFieldBitOffset.setEnabled(!isView); + this.jTextFieldOffsetBitSize.setEnabled(!isView); + this.jComboBoxUsage.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jTextFieldOverrideID.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelByteOffsetHint = new JLabel(); + jLabelByteOffsetHint.setBounds(new java.awt.Rectangle(245,60,235,20)); + jLabelByteOffsetHint.setText("0x00"); + jLabelOffsetBitSizeHint = new JLabel(); + jLabelOffsetBitSizeHint.setBounds(new java.awt.Rectangle(245,110,235,20)); + jLabelOffsetBitSizeHint.setText("1~7"); + jLabelBitOffsetHint = new JLabel(); + jLabelBitOffsetHint.setBounds(new java.awt.Rectangle(245,85,235,20)); + jLabelBitOffsetHint.setText("0~7"); + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setText("Override ID"); + jLabelOverrideID.setBounds(new java.awt.Rectangle(15, 160, 140, 20)); + jLabelUsage = new JLabel(); + jLabelUsage.setText("Usage"); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 135, 140, 20)); + jLabelOffsetBitSize = new JLabel(); + jLabelOffsetBitSize.setText("Offset Bit Size"); + jLabelOffsetBitSize.setLocation(new java.awt.Point(15, 110)); + jLabelOffsetBitSize.setSize(new java.awt.Dimension(140, 20)); + jLabelByteOffset = new JLabel(); + jLabelByteOffset.setText("Byte Offset"); + jLabelByteOffset.setLocation(new java.awt.Point(15, 60)); + jLabelByteOffset.setSize(new java.awt.Dimension(140, 20)); + jLabelBitOffset = new JLabel(); + jLabelBitOffset.setText("Bit Offset"); + jLabelBitOffset.setLocation(new java.awt.Point(15, 85)); + jLabelBitOffset.setSize(new java.awt.Dimension(140, 20)); + jLabelString = new JLabel(); + jLabelString.setText("String"); + jLabelString.setLocation(new java.awt.Point(15, 10)); + jLabelString.setSize(new java.awt.Dimension(140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setText("Guid"); + jLabelGuid.setLocation(new java.awt.Point(15, 35)); + jLabelGuid.setSize(new java.awt.Dimension(140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelString, null); + jContentPane.add(getJTextFieldString(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelByteOffset, null); + jContentPane.add(getJTextFieldByteOffset(), null); + jContentPane.add(jLabelBitOffset, null); + jContentPane.add(getJTextFieldBitOffset(), null); + jContentPane.add(jLabelOffsetBitSize, null); + jContentPane.add(getJTextFieldOffsetBitSize(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setLocation(new java.awt.Point(0, 35)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + + jContentPane.add(jLabelByteOffsetHint, null); + jContentPane.add(jLabelBitOffsetHint, null); + jContentPane.add(jLabelOffsetBitSizeHint, null); + initFrame(); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.setEdited(true); + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + This method initializes Usage type + + **/ + private void initFrame() { + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("PRIVATE"); + } + + /** + Get VariablesDocument.Variables + + @return VariablesDocument.Variables + + **/ + public VariablesDocument.Variables getVariables() { + return variables; + } + + /** + Set VariablesDocument.Variables + + @param variables The input data of VariablesDocument.Variables + + **/ + public void setVariables(VariablesDocument.Variables variables) { + this.variables = variables; + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldString.getText())) { + Log.err("String couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldGuid.getText())) { + Log.err("Guid couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!isEmpty(this.jTextFieldGuid.getText()) && !DataValidation.isGuid(this.jTextFieldGuid.getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!isEmpty(this.jTextFieldByteOffset.getText()) + && !DataValidation.isByteOffset(this.jTextFieldByteOffset.getText())) { + Log.err("Incorrect data type for Byte Offset"); + return false; + } + if (!isEmpty(this.jTextFieldBitOffset.getText()) + && !DataValidation.isBitOffset(this.jTextFieldBitOffset.getText())) { + Log.err("Incorrect data type for Bit Offset"); + return false; + } + if (!isEmpty(this.jTextFieldOffsetBitSize.getText()) + && !DataValidation.isOffsetBitSize(this.jTextFieldOffsetBitSize.getText())) { + Log.err("Incorrect data type for Bit Offset"); + return false; + } + if (!isEmpty(this.jTextFieldOverrideID.getText()) + && !DataValidation.isOverrideID(this.jTextFieldOverrideID.getText())) { + Log.err("Incorrect data type for Override ID"); + return false; + } + + return true; + } + + /** + Save all components of Variables + if exists variables, set the value directly + if not exists variables, new an instance first + + **/ + public void save() { + try { + if (this.variables == null) { + variables = VariablesDocument.Variables.Factory.newInstance(); + } + VariablesDocument.Variables.Variable variable = VariablesDocument.Variables.Variable.Factory.newInstance(); + if (!isEmpty(this.jTextFieldString.getText())) { + variable.setString(this.jTextFieldString.getText()); + } + if (!isEmpty(this.jTextFieldGuid.getText())) { + GuidDocument.Guid guid = GuidDocument.Guid.Factory.newInstance(); + guid.setStringValue(this.jTextFieldGuid.getText()); + variable.setGuid(guid); + } + if (!isEmpty(this.jTextFieldByteOffset.getText())) { + variable.setByteOffset(this.jTextFieldByteOffset.getText()); + } + if (!isEmpty(this.jTextFieldBitOffset.getText())) { + variable.setBitOffset(Integer.parseInt(this.jTextFieldBitOffset.getText())); + } + if (!isEmpty(this.jTextFieldBitOffset.getText())) { + variable.setOffsetBitSize(Integer.parseInt(this.jTextFieldBitOffset.getText())); + } + variable.setUsage(VariableUsage.Enum.forString(jComboBoxUsage.getSelectedItem().toString())); + if (!isEmpty(this.jTextFieldOverrideID.getText())) { + variable.setOverrideID(Integer.parseInt(this.jTextFieldOverrideID.getText())); + } + if (location > -1) { + variables.setVariableArray(location, variable); + } else { + variables.addNewVariable(); + variables.setVariableArray(variables.getVariableList().size() - 1, variable); + } + } catch (Exception e) { + Log.err("Update Variables", e.getMessage()); + } + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MsaHeader.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MsaHeader.java new file mode 100644 index 0000000000..f3e7011b3d --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MsaHeader.java @@ -0,0 +1,843 @@ +/** @file + + The file is used to create, update MsaHeader of MSA file + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +import org.tianocore.AbstractDocument; +import org.tianocore.BaseNameDocument; +import org.tianocore.FrameworkComponentTypes; +import org.tianocore.GuidDocument; +import org.tianocore.LicenseDocument; +import org.tianocore.ModuleTypeDef; +import org.tianocore.MsaHeaderDocument; +import org.tianocore.SpecificationDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update MsaHeader of MSA file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class MsaHeader extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = -8152099582923006900L; + + // + //Define class members + // + private JPanel jContentPane = null; + + private JLabel jLabelBaseName = null; + + private JTextField jTextFieldBaseName = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelVersion = null; + + private JTextField jTextFieldVersion = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelLicense = null; + + private JTextArea jTextAreaLicense = null; + + private JLabel jLabelCopyright = null; + + private JTextArea jTextAreaCopyright = null; + + private JLabel jLabelDescription = null; + + private JTextArea jTextAreaDescription = null; + + private JLabel jLabelSpecification = null; + + private JTextField jTextFieldSpecification = null; + + private JTextField jTextFieldSpecificationVersion = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JScrollPane jScrollPaneLicense = null; + + private JScrollPane jScrollPaneCopyright = null; + + private JScrollPane jScrollPaneDescription = null; + + private JLabel jLabelSpecVersion = null; + + private JLabel jLabelAbstract = null; + + private JTextField jTextFieldAbstract = null; + + private JLabel jLabelModuleType = null; + + private JLabel jLabelCompontentType = null; + + private JComboBox jComboBoxCompontentType = null; + + private JComboBox jComboBoxModuleType = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + private StarLabel jStarLabel3 = null; + + private StarLabel jStarLabel4 = null; + + private StarLabel jStarLabel5 = null; + + private StarLabel jStarLabel6 = null; + + private StarLabel jStarLabel7 = null; + + private StarLabel jStarLabel8 = null; + + private StarLabel jStarLabel9 = null; + + private MsaHeaderDocument.MsaHeader msaHeader = null; + + private JLabel jLabelURL = null; + + private JTextField jTextFieldAbstractURL = null; + + /** + This method initializes jTextFieldBaseName + + @return javax.swing.JTextField jTextFieldBaseName + + **/ + private JTextField getJTextFieldBaseName() { + if (jTextFieldBaseName == null) { + jTextFieldBaseName = new JTextField(); + jTextFieldBaseName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldBaseName; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldVersion + + @return javax.swing.JTextField jTextFieldVersion + + **/ + private JTextField getJTextFieldVersion() { + if (jTextFieldVersion == null) { + jTextFieldVersion = new JTextField(); + jTextFieldVersion.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jTextFieldVersion; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextAreaLicense + + @return javax.swing.JTextArea jTextAreaLicense + + **/ + private JTextArea getJTextAreaLicense() { + if (jTextAreaLicense == null) { + jTextAreaLicense = new JTextArea(); + jTextAreaLicense.setText(""); + jTextAreaLicense.setLineWrap(true); + } + return jTextAreaLicense; + } + + /** + This method initializes jTextAreaCopyright + + @return javax.swing.JTextArea jTextAreaCopyright + + **/ + private JTextArea getJTextAreaCopyright() { + if (jTextAreaCopyright == null) { + jTextAreaCopyright = new JTextArea(); + jTextAreaCopyright.setLineWrap(true); + } + return jTextAreaCopyright; + } + + /** + This method initializes jTextAreaDescription + + @return javax.swing.JTextArea jTextAreaDescription + + **/ + private JTextArea getJTextAreaDescription() { + if (jTextAreaDescription == null) { + jTextAreaDescription = new JTextArea(); + jTextAreaDescription.setLineWrap(true); + } + return jTextAreaDescription; + } + + /** + This method initializes jTextFieldSpecification + + @return javax.swing.JTextField jTextFieldSpecification + + **/ + private JTextField getJTextFieldSpecification() { + if (jTextFieldSpecification == null) { + jTextFieldSpecification = new JTextField(); + jTextFieldSpecification.setBounds(new java.awt.Rectangle(160, 340, 220, 20)); + } + return jTextFieldSpecification; + } + + /** + This method initializes jTextFieldSpecificationVersion + + @return javax.swing.JTextField jTextFieldSpecificationVersion + + **/ + private JTextField getJTextFieldSpecificationVersion() { + if (jTextFieldSpecificationVersion == null) { + jTextFieldSpecificationVersion = new JTextField(); + jTextFieldSpecificationVersion.setBounds(new java.awt.Rectangle(400, 340, 80, 20)); + } + return jTextFieldSpecificationVersion; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 445, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 445, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jScrollPaneLicense + + @return javax.swing.JScrollPane jScrollPaneLicense + + **/ + private JScrollPane getJScrollPaneLicense() { + if (jScrollPaneLicense == null) { + jScrollPaneLicense = new JScrollPane(); + jScrollPaneLicense.setBounds(new java.awt.Rectangle(160, 85, 320, 80)); + jScrollPaneLicense.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneLicense.setViewportView(getJTextAreaLicense()); + } + return jScrollPaneLicense; + } + + /** + This method initializes jScrollPaneCopyright + + @return javax.swing.JScrollPane jScrollPaneCopyright + + **/ + private JScrollPane getJScrollPaneCopyright() { + if (jScrollPaneCopyright == null) { + jScrollPaneCopyright = new JScrollPane(); + jScrollPaneCopyright.setBounds(new java.awt.Rectangle(160, 170, 320, 80)); + jScrollPaneCopyright.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneCopyright.setViewportView(getJTextAreaCopyright()); + } + return jScrollPaneCopyright; + } + + /** + This method initializes jScrollPaneDescription + + @return javax.swing.JScrollPane jScrollPaneDescription + + **/ + private JScrollPane getJScrollPaneDescription() { + if (jScrollPaneDescription == null) { + jScrollPaneDescription = new JScrollPane(); + jScrollPaneDescription.setBounds(new java.awt.Rectangle(160, 255, 320, 80)); + jScrollPaneDescription.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneDescription.setViewportView(getJTextAreaDescription()); + } + return jScrollPaneDescription; + } + + /** + This method initializes jTextFieldAbstract + + @return javax.swing.JTextField jTextFieldAbstract + + **/ + private JTextField getJTextFieldAbstract() { + if (jTextFieldAbstract == null) { + jTextFieldAbstract = new JTextField(); + jTextFieldAbstract.setBounds(new java.awt.Rectangle(160, 365, 200, 20)); + } + return jTextFieldAbstract; + } + + /** + This method initializes jComboBoxCompontentType + + @return javax.swing.JComboBox jComboBoxCompontentType + + **/ + private JComboBox getJComboBoxCompontentType() { + if (jComboBoxCompontentType == null) { + jComboBoxCompontentType = new JComboBox(); + jComboBoxCompontentType.setBounds(new java.awt.Rectangle(160, 415, 320, 20)); + } + return jComboBoxCompontentType; + } + + /** + This method initializes jComboBoxModuleType + + @return javax.swing.JComboBox jComboBoxModuleType + + **/ + private JComboBox getJComboBoxModuleType() { + if (jComboBoxModuleType == null) { + jComboBoxModuleType = new JComboBox(); + jComboBoxModuleType.setBounds(new java.awt.Rectangle(160, 390, 320, 20)); + } + return jComboBoxModuleType; + } + + /** + This method initializes jTextFieldAbstractURL + + @return javax.swing.JTextField jTextFieldAbstractURL + + **/ + private JTextField getJTextFieldAbstractURL() { + if (jTextFieldAbstractURL == null) { + jTextFieldAbstractURL = new JTextField(); + jTextFieldAbstractURL.setBounds(new java.awt.Rectangle(390, 365, 90, 20)); + } + return jTextFieldAbstractURL; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public MsaHeader() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inMsaHeader The input data of MsaHeaderDocument.MsaHeader + + **/ + public MsaHeader(MsaHeaderDocument.MsaHeader inMsaHeader) { + super(); + init(inMsaHeader); + this.setVisible(true); + this.setViewMode(false); + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldBaseName.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jTextFieldVersion.setEnabled(!isView); + this.jTextAreaLicense.setEnabled(!isView); + this.jTextAreaCopyright.setEnabled(!isView); + this.jTextAreaDescription.setEnabled(!isView); + this.jTextFieldSpecification.setEnabled(!isView); + this.jTextFieldSpecificationVersion.setEnabled(!isView); + this.jTextFieldAbstract.setEnabled(!isView); + this.jTextFieldAbstractURL.setEnabled(!isView); + this.jComboBoxModuleType.setEnabled(!isView); + this.jComboBoxCompontentType.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Module Surface Area Header"); + initFrame(); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inMsaHeader The input data of MsaHeaderDocument.MsaHeader + + **/ + private void init(MsaHeaderDocument.MsaHeader inMsaHeader) { + init(); + if (inMsaHeader != null) { + setMsaHeader(inMsaHeader); + if (this.msaHeader.getBaseName() != null) { + this.jTextFieldBaseName.setText(this.msaHeader.getBaseName().getStringValue()); + } + if (this.msaHeader.getGuid() != null) { + this.jTextFieldGuid.setText(this.msaHeader.getGuid().getStringValue()); + } + if (this.msaHeader.getVersion() != null) { + this.jTextFieldVersion.setText(this.msaHeader.getVersion()); + } + if (this.msaHeader.getLicense() != null) { + this.jTextAreaLicense.setText(this.msaHeader.getLicense().getStringValue()); + } + if (this.msaHeader.getCopyright() != null) { + this.jTextAreaCopyright.setText(this.msaHeader.getCopyright()); + } + if (this.msaHeader.getDescription() != null) { + this.jTextAreaDescription.setText(this.msaHeader.getDescription()); + } + if (this.msaHeader.getSpecification() != null) { + this.jTextFieldSpecification.setText(this.msaHeader.getSpecification().getStringValue()); + } + if (this.msaHeader.getSpecification() != null) { + this.jTextFieldSpecificationVersion.setText(this.msaHeader.getSpecification().getVersion()); + } + if (this.msaHeader.getAbstract() != null) { + this.jTextFieldAbstract.setText(this.msaHeader.getAbstract().getStringValue()); + this.jTextFieldAbstractURL.setText(this.msaHeader.getAbstract().getURL()); + } + if (this.msaHeader.getModuleType() != null) { + this.jComboBoxModuleType.setSelectedItem(this.msaHeader.getModuleType().toString()); + } + if (this.msaHeader.getComponentType() != null) { + this.jComboBoxCompontentType.setSelectedItem(this.msaHeader.getComponentType().toString()); + } + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelURL = new JLabel(); + jLabelURL.setBounds(new java.awt.Rectangle(365, 365, 25, 20)); + jLabelURL.setText("URL"); + jLabelCompontentType = new JLabel(); + jLabelCompontentType.setBounds(new java.awt.Rectangle(15, 415, 140, 20)); + jLabelCompontentType.setText("Compontent Type"); + jLabelModuleType = new JLabel(); + jLabelModuleType.setBounds(new java.awt.Rectangle(15, 390, 140, 20)); + jLabelModuleType.setText("Module Type"); + jLabelAbstract = new JLabel(); + jLabelAbstract.setBounds(new java.awt.Rectangle(15, 365, 140, 20)); + jLabelAbstract.setText("Abstract"); + jLabelSpecVersion = new JLabel(); + jLabelSpecVersion.setBounds(new java.awt.Rectangle(382, 340, 15, 20)); + jLabelSpecVersion.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + jLabelSpecVersion.setText("V"); + jLabelSpecification = new JLabel(); + jLabelSpecification.setText("Specification"); + jLabelSpecification.setBounds(new java.awt.Rectangle(15, 340, 140, 20)); + jLabelDescription = new JLabel(); + jLabelDescription.setText("Description"); + jLabelDescription.setBounds(new java.awt.Rectangle(15, 255, 140, 20)); + jLabelCopyright = new JLabel(); + jLabelCopyright.setText("Copyright"); + jLabelCopyright.setBounds(new java.awt.Rectangle(15, 170, 140, 20)); + jLabelLicense = new JLabel(); + jLabelLicense.setText("License"); + jLabelLicense.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelVersion = new JLabel(); + jLabelVersion.setText("Version"); + jLabelVersion.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setPreferredSize(new java.awt.Dimension(25, 15)); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelGuid.setText("Guid"); + jLabelBaseName = new JLabel(); + jLabelBaseName.setText("Base Name"); + jLabelBaseName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setLocation(new java.awt.Point(0, 0)); + jContentPane.setSize(new java.awt.Dimension(500, 524)); + jContentPane.add(jLabelBaseName, null); + jContentPane.add(getJTextFieldBaseName(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelVersion, null); + jContentPane.add(getJTextFieldVersion(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelLicense, null); + jContentPane.add(jLabelCopyright, null); + jContentPane.add(jLabelDescription, null); + jContentPane.add(jLabelSpecification, null); + jContentPane.add(getJTextFieldSpecification(), null); + jContentPane.add(getJTextFieldSpecificationVersion(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJScrollPaneLicense(), null); + jContentPane.add(getJScrollPaneCopyright(), null); + jContentPane.add(getJScrollPaneDescription(), null); + jContentPane.add(jLabelAbstract, null); + jContentPane.add(getJTextFieldAbstract(), null); + jContentPane.add(jLabelSpecVersion, null); + jContentPane.add(jLabelModuleType, null); + jContentPane.add(jLabelCompontentType, null); + jContentPane.add(getJComboBoxCompontentType(), null); + jContentPane.add(getJComboBoxModuleType(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setLocation(new java.awt.Point(0, 35)); + jStarLabel3 = new StarLabel(); + jStarLabel3.setLocation(new java.awt.Point(0, 60)); + jStarLabel4 = new StarLabel(); + jStarLabel4.setLocation(new java.awt.Point(0, 85)); + jStarLabel5 = new StarLabel(); + jStarLabel5.setLocation(new java.awt.Point(0, 170)); + jStarLabel6 = new StarLabel(); + jStarLabel6.setLocation(new java.awt.Point(0, 255)); + jStarLabel7 = new StarLabel(); + jStarLabel7.setLocation(new java.awt.Point(0, 365)); + jStarLabel8 = new StarLabel(); + jStarLabel8.setLocation(new java.awt.Point(0, 390)); + jStarLabel9 = new StarLabel(); + jStarLabel9.setLocation(new java.awt.Point(0, 415)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + jContentPane.add(jStarLabel3, null); + jContentPane.add(jStarLabel4, null); + jContentPane.add(jStarLabel5, null); + jContentPane.add(jStarLabel6, null); + jContentPane.add(jStarLabel7, null); + jContentPane.add(jStarLabel8, null); + jContentPane.add(jStarLabel9, null); + jContentPane.add(jLabelURL, null); + jContentPane.add(getJTextFieldAbstractURL(), null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.setEdited(true); + } + if (arg0.getSource() == jButtonCancel) { + this.setEdited(false); + } + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldBaseName.getText())) { + Log.err("Base Name couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldGuid.getText())) { + Log.err("Guid couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldVersion.getText())) { + Log.err("Version couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaLicense.getText())) { + Log.err("License couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaCopyright.getText())) { + Log.err("Copyright couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaDescription.getText())) { + Log.err("Description couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldAbstract.getText())) { + Log.err("Abstract couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isBaseName(this.jTextFieldBaseName.getText())) { + Log.err("Incorrect data type for Base Name"); + return false; + } + if (!DataValidation.isGuid((this.jTextFieldGuid).getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!DataValidation.isAbstract(this.jTextFieldAbstract.getText())) { + Log.err("Incorrect data type for Abstract"); + return false; + } + if (!DataValidation.isCopyright(this.jTextAreaCopyright.getText())) { + Log.err("Incorrect data type for Copyright"); + return false; + } + return true; + } + + /** + Save all components of Msa Header + if exists msaHeader, set the value directly + if not exists msaHeader, new an instance first + + **/ + public void save() { + try { + if (this.msaHeader == null) { + msaHeader = MsaHeaderDocument.MsaHeader.Factory.newInstance(); + } + if (this.msaHeader.getBaseName() != null) { + this.msaHeader.getBaseName().setStringValue(this.jTextFieldBaseName.getText()); + } else { + BaseNameDocument.BaseName mBaseName = BaseNameDocument.BaseName.Factory.newInstance(); + mBaseName.setStringValue(this.jTextFieldBaseName.getText()); + this.msaHeader.setBaseName(mBaseName); + } + + if (this.msaHeader.getGuid() != null) { + this.msaHeader.getGuid().setStringValue(this.jTextFieldGuid.getText()); + } else { + GuidDocument.Guid mGuid = GuidDocument.Guid.Factory.newInstance(); + mGuid.setStringValue(this.jTextFieldGuid.getText()); + this.msaHeader.setGuid(mGuid); + } + + this.msaHeader.setVersion(this.jTextFieldVersion.getText()); + + if (this.msaHeader.getLicense() != null) { + this.msaHeader.getLicense().setStringValue(this.jTextAreaLicense.getText()); + } else { + LicenseDocument.License mLicense = LicenseDocument.License.Factory.newInstance(); + mLicense.setStringValue(this.jTextAreaLicense.getText()); + this.msaHeader.setLicense(mLicense); + } + + this.msaHeader.setCopyright(this.jTextAreaCopyright.getText()); + this.msaHeader.setDescription(this.jTextAreaDescription.getText()); + + if (this.msaHeader.getSpecification() != null) { + this.msaHeader.getSpecification().setStringValue(this.jTextFieldSpecification.getText()); + this.msaHeader.getSpecification().setVersion(this.jTextFieldSpecificationVersion.getText()); + } else { + SpecificationDocument.Specification mSpecification = SpecificationDocument.Specification.Factory + .newInstance(); + mSpecification.setStringValue(this.jTextFieldSpecification.getText()); + mSpecification.setVersion(this.jTextFieldSpecificationVersion.getText()); + this.msaHeader.setSpecification(mSpecification); + } + + if (this.msaHeader.getAbstract() != null) { + this.msaHeader.getAbstract().setStringValue(this.jTextFieldAbstract.getText()); + this.msaHeader.getAbstract().setURL(this.jTextFieldAbstractURL.getText()); + } else { + AbstractDocument.Abstract mAbstract = AbstractDocument.Abstract.Factory.newInstance(); + mAbstract.setStringValue(this.jTextFieldAbstract.getText()); + mAbstract.setURL(this.jTextFieldAbstractURL.getText()); + this.msaHeader.setAbstract(mAbstract); + } + this.msaHeader.setModuleType(ModuleTypeDef.Enum.forString(this.jComboBoxModuleType.getSelectedItem() + .toString())); + this.msaHeader + .setComponentType(FrameworkComponentTypes.Enum + .forString(this.jComboBoxCompontentType + .getSelectedItem() + .toString())); + if (this.msaHeader.getCreated() == null) { + this.msaHeader.setCreated(Tools.getCurrentDateTime()); + } else { + this.msaHeader.setUpdated(Tools.getCurrentDateTime()); + } + + } catch (Exception e) { + Log.err("Save Module", e.getMessage()); + } + } + + /** + This method initializes Module type and Compontent type + + **/ + private void initFrame() { + jComboBoxModuleType.addItem("BASE"); + jComboBoxModuleType.addItem("SEC"); + jComboBoxModuleType.addItem("PEI_CORE"); + jComboBoxModuleType.addItem("PEIM"); + jComboBoxModuleType.addItem("DXE_CORE"); + jComboBoxModuleType.addItem("DXE_DRIVER"); + jComboBoxModuleType.addItem("DXE_RUNTIME_DRIVER"); + jComboBoxModuleType.addItem("DXE_SAL_DRIVER"); + jComboBoxModuleType.addItem("DXE_SMM_DRIVER"); + jComboBoxModuleType.addItem("TOOLS"); + jComboBoxModuleType.addItem("UEFI_DRIVER"); + jComboBoxModuleType.addItem("UEFI_APPLICATION"); + jComboBoxModuleType.addItem("USER_DEFINED"); + + jComboBoxCompontentType.addItem("APRIORI"); + jComboBoxCompontentType.addItem("LIBRARY"); + jComboBoxCompontentType.addItem("FV_IMAGE_FILE"); + jComboBoxCompontentType.addItem("BS_DRIVER"); + jComboBoxCompontentType.addItem("RT_DRIVER"); + jComboBoxCompontentType.addItem("SAL_RT_DRIVER"); + jComboBoxCompontentType.addItem("PE32_PEIM"); + jComboBoxCompontentType.addItem("PIC_PEIM"); + jComboBoxCompontentType.addItem("COMBINED_PEIM_DRIVER"); + jComboBoxCompontentType.addItem("PEI_CORE"); + jComboBoxCompontentType.addItem("DXE_CORE"); + jComboBoxCompontentType.addItem("APPLICATION"); + jComboBoxCompontentType.addItem("BS_DRIVER_EFI"); + jComboBoxCompontentType.addItem("SHELLAPP"); + } + + /** + Get MsaHeaderDocument.MsaHeader + + @return MsaHeaderDocument.MsaHeader + + **/ + public MsaHeaderDocument.MsaHeader getMsaHeader() { + return msaHeader; + } + + /** + Set MsaHeaderDocument.MsaHeader + + @param msaHeader The input data of MsaHeaderDocument.MsaHeader + + **/ + public void setMsaHeader(MsaHeaderDocument.MsaHeader msaHeader) { + this.msaHeader = msaHeader; + } +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MsaLibHeader.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MsaLibHeader.java new file mode 100644 index 0000000000..0760a76786 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/module/ui/MsaLibHeader.java @@ -0,0 +1,845 @@ +/** @file + + The file is used to create, update MsaLibHeader of a MSA file + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.module.ui; + +import java.awt.event.ActionEvent; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.JTextField; + +import org.tianocore.AbstractDocument; +import org.tianocore.BaseNameDocument; +import org.tianocore.FrameworkComponentTypes; +import org.tianocore.GuidDocument; +import org.tianocore.LicenseDocument; +import org.tianocore.ModuleTypeDef; +import org.tianocore.MsaLibHeaderDocument; +import org.tianocore.SpecificationDocument; +import org.tianocore.common.DataValidation; +import org.tianocore.common.Log; +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.IInternalFrame; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + The class is used to create, update MsaLibHeader of a MSA file + It extends IInternalFrame + + @since ModuleEditor 1.0 + + **/ +public class MsaLibHeader extends IInternalFrame { + + /// + /// Define class Serial Version UID + /// + private static final long serialVersionUID = 5526729363068526262L; + + // + //Define class members + // + private JPanel jContentPane = null; + + private JLabel jLabelBaseName = null; + + private JTextField jTextFieldBaseName = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelVersion = null; + + private JTextField jTextFieldVersion = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelLicense = null; + + private JTextArea jTextAreaLicense = null; + + private JLabel jLabelCopyright = null; + + private JTextArea jTextAreaCopyright = null; + + private JLabel jLabelDescription = null; + + private JTextArea jTextAreaDescription = null; + + private JLabel jLabelSpecification = null; + + private JTextField jTextFieldSpecification = null; + + private JTextField jTextFieldSpecificationVersion = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JScrollPane jScrollPaneLicense = null; + + private JScrollPane jScrollPaneCopyright = null; + + private JScrollPane jScrollPaneDescription = null; + + private JLabel jLabelSpecVersion = null; + + private JLabel jLabelAbstract = null; + + private JTextField jTextFieldAbstract = null; + + private JLabel jLabelModuleType = null; + + private JLabel jLabelCompontentType = null; + + private JComboBox jComboBoxCompontentType = null; + + private JComboBox jComboBoxModuleType = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + private StarLabel jStarLabel3 = null; + + private StarLabel jStarLabel4 = null; + + private StarLabel jStarLabel5 = null; + + private StarLabel jStarLabel6 = null; + + private StarLabel jStarLabel7 = null; + + private StarLabel jStarLabel8 = null; + + private StarLabel jStarLabel9 = null; + + private MsaLibHeaderDocument.MsaLibHeader msaLibHeader = null; + + private JLabel jLabelURL = null; + + private JTextField jTextFieldAbstractURL = null; + + /** + This method initializes jTextFieldBaseName + + @return javax.swing.JTextField jTextFieldBaseName + + **/ + private JTextField getJTextFieldBaseName() { + if (jTextFieldBaseName == null) { + jTextFieldBaseName = new JTextField(); + jTextFieldBaseName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldBaseName; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField jTextFieldGuid + + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldVersion + + @return javax.swing.JTextField jTextFieldVersion + + **/ + private JTextField getJTextFieldVersion() { + if (jTextFieldVersion == null) { + jTextFieldVersion = new JTextField(); + jTextFieldVersion.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jTextFieldVersion; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton jButtonGenerateGuid + + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextAreaLicense + + @return javax.swing.JTextArea jTextAreaLicense + + **/ + private JTextArea getJTextAreaLicense() { + if (jTextAreaLicense == null) { + jTextAreaLicense = new JTextArea(); + jTextAreaLicense.setText(""); + jTextAreaLicense.setLineWrap(true); + } + return jTextAreaLicense; + } + + /** + This method initializes jTextAreaCopyright + + @return javax.swing.JTextArea jTextAreaCopyright + + **/ + private JTextArea getJTextAreaCopyright() { + if (jTextAreaCopyright == null) { + jTextAreaCopyright = new JTextArea(); + jTextAreaCopyright.setLineWrap(true); + } + return jTextAreaCopyright; + } + + /** + This method initializes jTextAreaDescription + + @return javax.swing.JTextArea jTextAreaDescription + + **/ + private JTextArea getJTextAreaDescription() { + if (jTextAreaDescription == null) { + jTextAreaDescription = new JTextArea(); + jTextAreaDescription.setLineWrap(true); + } + return jTextAreaDescription; + } + + /** + This method initializes jTextFieldSpecification + + @return javax.swing.JTextField jTextFieldSpecification + + **/ + private JTextField getJTextFieldSpecification() { + if (jTextFieldSpecification == null) { + jTextFieldSpecification = new JTextField(); + jTextFieldSpecification.setBounds(new java.awt.Rectangle(160, 340, 220, 20)); + } + return jTextFieldSpecification; + } + + /** + This method initializes jTextFieldSpecificationVersion + + @return javax.swing.JTextField jTextFieldSpecificationVersion + + **/ + private JTextField getJTextFieldSpecificationVersion() { + if (jTextFieldSpecificationVersion == null) { + jTextFieldSpecificationVersion = new JTextField(); + jTextFieldSpecificationVersion.setBounds(new java.awt.Rectangle(400, 340, 80, 20)); + } + return jTextFieldSpecificationVersion; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton jButtonOk + + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 445, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton jButtonCancel + + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 445, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jScrollPaneLicense + + @return javax.swing.JScrollPane jScrollPaneLicense + + **/ + private JScrollPane getJScrollPaneLicense() { + if (jScrollPaneLicense == null) { + jScrollPaneLicense = new JScrollPane(); + jScrollPaneLicense.setBounds(new java.awt.Rectangle(160, 85, 320, 80)); + jScrollPaneLicense.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneLicense.setViewportView(getJTextAreaLicense()); + } + return jScrollPaneLicense; + } + + /** + This method initializes jScrollPaneCopyright + + @return javax.swing.JScrollPane jScrollPaneCopyright + + **/ + private JScrollPane getJScrollPaneCopyright() { + if (jScrollPaneCopyright == null) { + jScrollPaneCopyright = new JScrollPane(); + jScrollPaneCopyright.setBounds(new java.awt.Rectangle(160, 170, 320, 80)); + jScrollPaneCopyright.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneCopyright.setViewportView(getJTextAreaCopyright()); + } + return jScrollPaneCopyright; + } + + /** + This method initializes jScrollPaneDescription + + @return javax.swing.JScrollPane jScrollPaneDescription + + **/ + private JScrollPane getJScrollPaneDescription() { + if (jScrollPaneDescription == null) { + jScrollPaneDescription = new JScrollPane(); + jScrollPaneDescription.setBounds(new java.awt.Rectangle(160, 255, 320, 80)); + jScrollPaneDescription.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneDescription.setViewportView(getJTextAreaDescription()); + } + return jScrollPaneDescription; + } + + /** + This method initializes jTextFieldAbstract + + @return javax.swing.JTextField jTextFieldAbstract + + **/ + private JTextField getJTextFieldAbstract() { + if (jTextFieldAbstract == null) { + jTextFieldAbstract = new JTextField(); + jTextFieldAbstract.setBounds(new java.awt.Rectangle(160, 365, 200, 20)); + } + return jTextFieldAbstract; + } + + /** + This method initializes jComboBoxCompontentType + + @return javax.swing.JComboBox jComboBoxCompontentType + + **/ + private JComboBox getJComboBoxCompontentType() { + if (jComboBoxCompontentType == null) { + jComboBoxCompontentType = new JComboBox(); + jComboBoxCompontentType.setBounds(new java.awt.Rectangle(160, 415, 320, 20)); + } + return jComboBoxCompontentType; + } + + /** + This method initializes jComboBoxModuleType + + @return javax.swing.JComboBox jComboBoxModuleType + + **/ + private JComboBox getJComboBoxModuleType() { + if (jComboBoxModuleType == null) { + jComboBoxModuleType = new JComboBox(); + jComboBoxModuleType.setBounds(new java.awt.Rectangle(160, 390, 320, 20)); + } + return jComboBoxModuleType; + } + + /** + This method initializes jTextFieldAbstractURL + + @return javax.swing.JTextField jTextFieldAbstractURL + + **/ + private JTextField getJTextFieldAbstractURL() { + if (jTextFieldAbstractURL == null) { + jTextFieldAbstractURL = new JTextField(); + jTextFieldAbstractURL.setBounds(new java.awt.Rectangle(390, 365, 90, 20)); + } + return jTextFieldAbstractURL; + } + + public static void main(String[] args) { + + } + + /** + This is the default constructor + + **/ + public MsaLibHeader() { + super(); + init(); + this.setVisible(true); + } + + /** + This is the override edit constructor + + @param inMsaLibHeader The input data of MsaLibHeaderDocument.MsaLibHeader + + **/ + public MsaLibHeader(MsaLibHeaderDocument.MsaLibHeader inMsaLibHeader) { + super(); + init(inMsaLibHeader); + this.setVisible(true); + this.setViewMode(false); + } + + /** + This method initializes this + + **/ + private void init() { + this.setSize(500, 515); + this.setContentPane(getJContentPane()); + this.setTitle("Library Module"); + initFrame(); + } + + /** + This method initializes this + Fill values to all fields if these values are not empty + + @param inMsaLibHeader The input data of MsaLibHeaderDocument.MsaLibHeader + + **/ + private void init(MsaLibHeaderDocument.MsaLibHeader inMsaLibHeader) { + init(); + this.setMsaLibHeader(inMsaLibHeader); + if (inMsaLibHeader != null) { + if (this.msaLibHeader.getBaseName() != null) { + this.jTextFieldBaseName.setText(this.msaLibHeader.getBaseName().getStringValue()); + } + if (this.msaLibHeader.getGuid() != null) { + this.jTextFieldGuid.setText(this.msaLibHeader.getGuid().getStringValue()); + } + if (this.msaLibHeader.getVersion() != null) { + this.jTextFieldVersion.setText(this.msaLibHeader.getVersion()); + } + if (this.msaLibHeader.getLicense() != null) { + this.jTextAreaLicense.setText(this.msaLibHeader.getLicense().getStringValue()); + } + if (this.msaLibHeader.getCopyright() != null) { + this.jTextAreaCopyright.setText(this.msaLibHeader.getCopyright()); + } + if (this.msaLibHeader.getDescription() != null) { + this.jTextAreaDescription.setText(this.msaLibHeader.getDescription()); + } + if (this.msaLibHeader.getSpecification() != null) { + this.jTextFieldSpecification.setText(this.msaLibHeader.getSpecification().getStringValue()); + } + if (this.msaLibHeader.getSpecification() != null) { + this.jTextFieldSpecificationVersion.setText(this.msaLibHeader.getSpecification().getVersion()); + } + if (this.msaLibHeader.getAbstract() != null) { + this.jTextFieldAbstract.setText(this.msaLibHeader.getAbstract().getStringValue()); + this.jTextFieldAbstractURL.setText(this.msaLibHeader.getAbstract().getURL()); + } + if (this.msaLibHeader.getModuleType() != null) { + this.jComboBoxModuleType.setSelectedItem(this.msaLibHeader.getModuleType().toString()); + } + if (this.msaLibHeader.getComponentType() != null) { + this.jComboBoxCompontentType.setSelectedItem(this.msaLibHeader.getComponentType().toString()); + } + } + } + + /** + Disable all components when the mode is view + + @param isView true - The view mode; false - The non-view mode + + **/ + public void setViewMode(boolean isView) { + this.jButtonOk.setVisible(false); + this.jButtonCancel.setVisible(false); + if (isView) { + this.jTextFieldBaseName.setEnabled(!isView); + this.jTextFieldGuid.setEnabled(!isView); + this.jTextFieldVersion.setEnabled(!isView); + this.jTextAreaLicense.setEnabled(!isView); + this.jTextAreaCopyright.setEnabled(!isView); + this.jTextAreaDescription.setEnabled(!isView); + this.jTextFieldSpecification.setEnabled(!isView); + this.jTextFieldSpecificationVersion.setEnabled(!isView); + this.jTextFieldAbstract.setEnabled(!isView); + this.jTextFieldAbstractURL.setEnabled(!isView); + this.jComboBoxModuleType.setEnabled(!isView); + this.jComboBoxCompontentType.setEnabled(!isView); + this.jButtonCancel.setEnabled(!isView); + this.jButtonGenerateGuid.setEnabled(!isView); + this.jButtonOk.setEnabled(!isView); + } + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel jContentPane + + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelURL = new JLabel(); + jLabelURL.setBounds(new java.awt.Rectangle(365, 365, 25, 20)); + jLabelURL.setText("URL"); + jLabelCompontentType = new JLabel(); + jLabelCompontentType.setBounds(new java.awt.Rectangle(15, 415, 140, 20)); + jLabelCompontentType.setText("Compontent Type"); + jLabelModuleType = new JLabel(); + jLabelModuleType.setBounds(new java.awt.Rectangle(15, 390, 140, 20)); + jLabelModuleType.setText("Module Type"); + jLabelAbstract = new JLabel(); + jLabelAbstract.setBounds(new java.awt.Rectangle(15, 365, 140, 20)); + jLabelAbstract.setText("Abstract"); + jLabelSpecVersion = new JLabel(); + jLabelSpecVersion.setBounds(new java.awt.Rectangle(382, 340, 15, 20)); + jLabelSpecVersion.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + jLabelSpecVersion.setText("V"); + jLabelSpecification = new JLabel(); + jLabelSpecification.setText("Specification"); + jLabelSpecification.setBounds(new java.awt.Rectangle(15, 340, 140, 20)); + jLabelDescription = new JLabel(); + jLabelDescription.setText("Description"); + jLabelDescription.setBounds(new java.awt.Rectangle(15, 255, 140, 20)); + jLabelCopyright = new JLabel(); + jLabelCopyright.setText("Copyright"); + jLabelCopyright.setBounds(new java.awt.Rectangle(15, 170, 140, 20)); + jLabelLicense = new JLabel(); + jLabelLicense.setText("License"); + jLabelLicense.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelVersion = new JLabel(); + jLabelVersion.setText("Version"); + jLabelVersion.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setPreferredSize(new java.awt.Dimension(25, 15)); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelGuid.setText("Guid"); + jLabelBaseName = new JLabel(); + jLabelBaseName.setText("Base Name"); + jLabelBaseName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setLocation(new java.awt.Point(0, 0)); + jContentPane.setSize(new java.awt.Dimension(500, 524)); + jContentPane.add(jLabelBaseName, null); + jContentPane.add(getJTextFieldBaseName(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelVersion, null); + jContentPane.add(getJTextFieldVersion(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelLicense, null); + jContentPane.add(jLabelCopyright, null); + jContentPane.add(jLabelDescription, null); + jContentPane.add(jLabelSpecification, null); + jContentPane.add(getJTextFieldSpecification(), null); + jContentPane.add(getJTextFieldSpecificationVersion(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJScrollPaneLicense(), null); + jContentPane.add(getJScrollPaneCopyright(), null); + jContentPane.add(getJScrollPaneDescription(), null); + jContentPane.add(jLabelAbstract, null); + jContentPane.add(getJTextFieldAbstract(), null); + jContentPane.add(jLabelSpecVersion, null); + jContentPane.add(jLabelModuleType, null); + jContentPane.add(jLabelCompontentType, null); + jContentPane.add(getJComboBoxCompontentType(), null); + jContentPane.add(getJComboBoxModuleType(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setLocation(new java.awt.Point(0, 35)); + jStarLabel3 = new StarLabel(); + jStarLabel3.setLocation(new java.awt.Point(0, 60)); + jStarLabel4 = new StarLabel(); + jStarLabel4.setLocation(new java.awt.Point(0, 85)); + jStarLabel5 = new StarLabel(); + jStarLabel5.setLocation(new java.awt.Point(0, 170)); + jStarLabel6 = new StarLabel(); + jStarLabel6.setLocation(new java.awt.Point(0, 255)); + jStarLabel7 = new StarLabel(); + jStarLabel7.setLocation(new java.awt.Point(0, 365)); + jStarLabel8 = new StarLabel(); + jStarLabel8.setLocation(new java.awt.Point(0, 390)); + jStarLabel9 = new StarLabel(); + jStarLabel9.setLocation(new java.awt.Point(0, 415)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + jContentPane.add(jStarLabel3, null); + jContentPane.add(jStarLabel4, null); + jContentPane.add(jStarLabel5, null); + jContentPane.add(jStarLabel6, null); + jContentPane.add(jStarLabel7, null); + jContentPane.add(jStarLabel8, null); + jContentPane.add(jStarLabel9, null); + jContentPane.add(jLabelURL, null); + jContentPane.add(getJTextFieldAbstractURL(), null); + } + return jContentPane; + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + * + * Override actionPerformed to listen all actions + * + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.dispose(); + this.save(); + this.setEdited(true); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + this.setEdited(false); + } + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Data validation for all fields + + @retval true - All datas are valid + @retval false - At least one data is invalid + + **/ + public boolean check() { + // + // Check if all required fields are not empty + // + if (isEmpty(this.jTextFieldBaseName.getText())) { + Log.err("Base Name couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldGuid.getText())) { + Log.err("Guid couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldVersion.getText())) { + Log.err("Version couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaLicense.getText())) { + Log.err("License couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaCopyright.getText())) { + Log.err("Copyright couldn't be empty"); + return false; + } + if (isEmpty(this.jTextAreaDescription.getText())) { + Log.err("Description couldn't be empty"); + return false; + } + if (isEmpty(this.jTextFieldAbstract.getText())) { + Log.err("Abstract couldn't be empty"); + return false; + } + + // + // Check if all fields have correct data types + // + if (!DataValidation.isBaseName(this.jTextFieldBaseName.getText())) { + Log.err("Incorrect data type for Base Name"); + return false; + } + if (!DataValidation.isGuid((this.jTextFieldGuid).getText())) { + Log.err("Incorrect data type for Guid"); + return false; + } + if (!DataValidation.isAbstract(this.jTextFieldAbstract.getText())) { + Log.err("Incorrect data type for Abstract"); + return false; + } + if (!DataValidation.isCopyright(this.jTextAreaCopyright.getText())) { + Log.err("Incorrect data type for Copyright"); + return false; + } + return true; + } + + /** + Save all components of Msa Lib Header + if exists msaLibHeader, set the value directly + if not exists msaLibHeader, new an instance first + + **/ + public void save() { + try { + if (this.msaLibHeader == null) { + msaLibHeader = MsaLibHeaderDocument.MsaLibHeader.Factory.newInstance(); + } + if (this.msaLibHeader.getBaseName() != null) { + this.msaLibHeader.getBaseName().setStringValue(this.jTextFieldBaseName.getText()); + } else { + BaseNameDocument.BaseName mBaseName = BaseNameDocument.BaseName.Factory.newInstance(); + mBaseName.setStringValue(this.jTextFieldBaseName.getText()); + this.msaLibHeader.setBaseName(mBaseName); + } + + if (this.msaLibHeader.getGuid() != null) { + this.msaLibHeader.getGuid().setStringValue(this.jTextFieldGuid.getText()); + } else { + GuidDocument.Guid mGuid = GuidDocument.Guid.Factory.newInstance(); + mGuid.setStringValue(this.jTextFieldGuid.getText()); + this.msaLibHeader.setGuid(mGuid); + } + + this.msaLibHeader.setVersion(this.jTextFieldVersion.getText()); + + if (this.msaLibHeader.getLicense() != null) { + this.msaLibHeader.getLicense().setStringValue(this.jTextAreaLicense.getText()); + } else { + LicenseDocument.License mLicense = LicenseDocument.License.Factory.newInstance(); + mLicense.setStringValue(this.jTextAreaLicense.getText()); + this.msaLibHeader.setLicense(mLicense); + } + + this.msaLibHeader.setCopyright(this.jTextAreaCopyright.getText()); + this.msaLibHeader.setDescription(this.jTextAreaDescription.getText()); + + if (this.msaLibHeader.getSpecification() != null) { + this.msaLibHeader.getSpecification().setStringValue(this.jTextFieldSpecification.getText()); + this.msaLibHeader.getSpecification().setVersion(this.jTextFieldSpecificationVersion.getText()); + } else { + SpecificationDocument.Specification mSpecification = SpecificationDocument.Specification.Factory + .newInstance(); + mSpecification.setStringValue(this.jTextFieldSpecification.getText()); + mSpecification.setVersion(this.jTextFieldSpecificationVersion.getText()); + this.msaLibHeader.setSpecification(mSpecification); + } + + if (this.msaLibHeader.getAbstract() != null) { + this.msaLibHeader.getAbstract().setStringValue(this.jTextFieldAbstract.getText()); + this.msaLibHeader.getAbstract().setURL(this.jTextFieldAbstractURL.getText()); + } else { + AbstractDocument.Abstract mAbstract = AbstractDocument.Abstract.Factory.newInstance(); + mAbstract.setStringValue(this.jTextFieldAbstract.getText()); + mAbstract.setURL(this.jTextFieldAbstractURL.getText()); + this.msaLibHeader.setAbstract(mAbstract); + } + + this.msaLibHeader.setModuleType(ModuleTypeDef.Enum.forString(this.jComboBoxModuleType.getSelectedItem() + .toString())); + this.msaLibHeader + .setComponentType(FrameworkComponentTypes.Enum + .forString(this.jComboBoxCompontentType + .getSelectedItem() + .toString())); + + if (this.msaLibHeader.getCreated() == null) { + this.msaLibHeader.setCreated(Tools.getCurrentDateTime()); + } else { + this.msaLibHeader.setUpdated(Tools.getCurrentDateTime()); + } + } catch (Exception e) { + Log.err("Save Module", e.getMessage()); + } + } + + /** + This method initializes module type and compontent type + + **/ + private void initFrame() { + jComboBoxModuleType.addItem("BASE"); + jComboBoxModuleType.addItem("SEC"); + jComboBoxModuleType.addItem("PEI_CORE"); + jComboBoxModuleType.addItem("PEIM"); + jComboBoxModuleType.addItem("DXE_CORE"); + jComboBoxModuleType.addItem("DXE_DRIVER"); + jComboBoxModuleType.addItem("DXE_RUNTIME_DRIVER"); + jComboBoxModuleType.addItem("DXE_SMM_DRIVER"); + jComboBoxModuleType.addItem("DXE_SAL_DRIVER"); + jComboBoxModuleType.addItem("UEFI_DRIVER"); + jComboBoxModuleType.addItem("UEFI_APPLICATION"); + + jComboBoxCompontentType.addItem("APRIORI"); + jComboBoxCompontentType.addItem("LIBRARY"); + jComboBoxCompontentType.addItem("FV_IMAGE_FILE"); + jComboBoxCompontentType.addItem("BS_DRIVER"); + jComboBoxCompontentType.addItem("RT_DRIVER"); + jComboBoxCompontentType.addItem("SAL_RT_DRIVER"); + jComboBoxCompontentType.addItem("PE32_PEIM"); + jComboBoxCompontentType.addItem("PIC_PEIM"); + jComboBoxCompontentType.addItem("COMBINED_PEIM_DRIVER"); + jComboBoxCompontentType.addItem("PEI_CORE"); + jComboBoxCompontentType.addItem("DXE_CORE"); + jComboBoxCompontentType.addItem("APPLICATION"); + jComboBoxCompontentType.addItem("BS_DRIVER_EFI"); + jComboBoxCompontentType.addItem("SHELLAPP"); + } + + /** + Get MsaLibHeaderDocument.MsaLibHeader + + @return MsaLibHeaderDocument.MsaLibHeader + + **/ + public MsaLibHeaderDocument.MsaLibHeader getMsaLibHeader() { + return msaLibHeader; + } + + /** + Set MsaLibHeaderDocument.MsaLibHeader + + @param msaLibHeader The input data of MsaLibHeaderDocument.MsaLibHeader + + **/ + public void setMsaLibHeader(MsaLibHeaderDocument.MsaLibHeader msaLibHeader) { + this.msaLibHeader = msaLibHeader; + } + +} diff --git a/Tools/Source/ModuleEditor/src/org/tianocore/packaging/workspace/common/Workspace.java b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/workspace/common/Workspace.java new file mode 100644 index 0000000000..1d98909832 --- /dev/null +++ b/Tools/Source/ModuleEditor/src/org/tianocore/packaging/workspace/common/Workspace.java @@ -0,0 +1,147 @@ +/** @file + + The file is used to init workspace and get basic information of workspace + + Copyright (c) 2006, 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. + + **/ + +package org.tianocore.packaging.workspace.common; + +import java.io.File; + +import org.apache.xmlbeans.XmlException; +import org.apache.xmlbeans.XmlObject; +import org.tianocore.FrameworkDatabaseDocument; +import org.tianocore.common.Log; + +/** + The file is used to init workspace and get basic information of workspace + + @since ModuleEditor 1.0 + + **/ +public class Workspace { + + // + // Define class members + // + private String currentWorkspace = null; + + private FrameworkDatabaseDocument xmlFrameworkDbDoc = null; + + private String strWorkspaceDatabaseFile = System.getProperty("file.separator") + "Tools" + + System.getProperty("file.separator") + "Conf" + + System.getProperty("file.separator") + "FrameworkDatabase.db"; + + public static void main(String[] args) { + + } + + /** + This is the default constructor + Get current WORKSPACE from system environment variable + + **/ + public Workspace() { + this.currentWorkspace = System.getenv("WORKSPACE"); + } + + /** + Check if current workspace exists of not + + @retval true - The current WORKSPACE exists + @retval false - The current WORKSPACE doesn't exist + + **/ + public boolean checkCurrentWorkspace() { + return checkCurrentWorkspace(getCurrentWorkspace()); + } + + /** + Check if current workspace exists or not via input workspace path + + @param strWorkspace The input data of WORKSPACE path + @retval true - The current WORKSPACE exists + @retval false - The current WORKSPACE doesn't exist + + **/ + public boolean checkCurrentWorkspace(String strWorkspace) { + if (strWorkspace == null || strWorkspace == "") { + return false; + } + File f = new File(strWorkspace); + if (!f.isDirectory()) { + return false; + } + if (!f.exists()) { + return false; + } + return true; + } + + /** + Get Current Workspace + + @return currentWorkspace + + **/ + public String getCurrentWorkspace() { + return currentWorkspace; + } + + /** + Set Current Workspace + + @param currentWorkspace The input data of currentWorkspace + + **/ + public void setCurrentWorkspace(String currentWorkspace) { + this.currentWorkspace = currentWorkspace; + } + + /** + Open Framework Database file + + **/ + private void openFrameworkDb() { + String strFrameworkDbFilePath = this.getCurrentWorkspace() + strWorkspaceDatabaseFile; + try { + xmlFrameworkDbDoc = (FrameworkDatabaseDocument) XmlObject.Factory.parse(strFrameworkDbFilePath); + } catch (XmlException e) { + Log.err("Open Framework Database " + strFrameworkDbFilePath, e.getMessage()); + return; + } catch (Exception e) { + Log.err("Open Framework Database " + strFrameworkDbFilePath, "Invalid file type"); + return; + } + } + + /** + Get FrameworkDatabaseDocument + + @return FrameworkDatabaseDocument + + **/ + public FrameworkDatabaseDocument getXmlFrameworkDbDoc() { + openFrameworkDb(); + return xmlFrameworkDbDoc; + } + + /** + Set FrameworkDatabaseDocument + + @param xmlFrameworkDbDoc The input data of FrameworkDatabaseDocument + + **/ + public void setXmlFrameworkDbDoc(FrameworkDatabaseDocument xmlFrameworkDbDoc) { + this.xmlFrameworkDbDoc = xmlFrameworkDbDoc; + } +} diff --git a/Tools/Source/PackageEditor/MANIFEST.MF b/Tools/Source/PackageEditor/MANIFEST.MF new file mode 100644 index 0000000000..996b1f7159 --- /dev/null +++ b/Tools/Source/PackageEditor/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: org.tianocore.packaging.PackagingMain +Class-Path: ../Jars/SurfaceArea.jar ../Jars/FDPManifest.jar ./xmlbeans/lib/jsr173_1.0_api.jar ./xmlbeans/lib/xbean.jar ./xmlbeans/lib/xbean_xpath.jar ./xmlbeans/lib/xmlpublic.jar ./xmlbeans/lib/saxon8.jar ./xmlbeans/lib/saxon8-jdom.jar ./xmlbeans/lib/saxon8-sql.jar ./xmlbeans/lib/resolver.jar diff --git a/Tools/Source/PackageEditor/build.xml b/Tools/Source/PackageEditor/build.xml new file mode 100644 index 0000000000..2dd3dce273 --- /dev/null +++ b/Tools/Source/PackageEditor/build.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/PackageEditor/src/org/tianocore/common/Tools.java b/Tools/Source/PackageEditor/src/org/tianocore/common/Tools.java new file mode 100644 index 0000000000..e372812e1f --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/common/Tools.java @@ -0,0 +1,73 @@ +/** @file + Java class Tools contains common use procedures. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.common; + +import java.io.File; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Date; +import java.util.UUID; + +/** + This class contains static methods for some common operations + + @since PackageEditor 1.0 +**/ +public class Tools { + + /** + get current date and time, then return + @return String + **/ + public static String getCurrentDateTime() { + Date now = new Date(System.currentTimeMillis()); + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + return sdf.format(now); + } + + /** + Delete a folder and all its files + @param strFolderName + @return boolean + **/ + public static boolean deleteFolder(File fleFolderName) { + boolean blnIsDeleted = true; + File[] aryAllFiles = fleFolderName.listFiles(); + + for (int indexI = 0; indexI < aryAllFiles.length; indexI++) { + if (blnIsDeleted) { + if (aryAllFiles[indexI].isDirectory()) { + blnIsDeleted = deleteFolder(aryAllFiles[indexI]); + } else if (aryAllFiles[indexI].isFile()) { + if (!aryAllFiles[indexI].delete()) { + blnIsDeleted = false; + } + } + } + } + if (blnIsDeleted) { + fleFolderName.delete(); + } + return blnIsDeleted; + } + + /** + Get a new GUID + + @return String + **/ + public static String generateUuidString() { + return UUID.randomUUID().toString(); + } + +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/CreateFdp.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/CreateFdp.java new file mode 100644 index 0000000000..6988b5ae01 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/CreateFdp.java @@ -0,0 +1,93 @@ +/** @file + Java class CreateFdp is used to create a distributable package containing + FDPManifest.xml file in its root directory. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.io.*; +import java.util.jar.*; + +/** + This class contains static method create to generate *.fdp format package. + + @since PackageEditor 1.0 +**/ +public class CreateFdp { + + /** + recursively add contents under dir into output package. + + @param dir The directory with files that will be put into package + @param jos Stream used to create output package + @param wkDir The position of source directory + @throws Exception Any exception occurred during this process + **/ + public static void create(File dir, JarOutputStream jos, String wkDir) throws Exception { + + String[] list = dir.list(); + + try { + byte[] buffer = new byte[1024]; + int bytesRead; + + // + // Loop through the file names provided. + // + for (int i = 0; i < list.length; i++) { + + File f = new File(dir, list[i]); + if (f.getName().equals("..")) { + continue; + } + if (f.isDirectory()) { + // + // Call this method recursively for directory + // + CreateFdp.create(f, jos, wkDir); + continue; + } + + try { + // + // Open the file + // + FileInputStream fis = new FileInputStream(f); + + try { + // + // Create a Jar entry and add it, keep relative path only. + // + JarEntry entry = new JarEntry(f.getPath().substring(wkDir.length() + 1)); + jos.putNextEntry(entry); + + // + // Read the file and write it to the Jar. + // + while ((bytesRead = fis.read(buffer)) != -1) { + jos.write(buffer, 0, bytesRead); + } + + System.out.println(entry.getName() + " added."); + } catch (Exception ex) { + System.out.println(ex); + } finally { + fis.close(); + } + } catch (IOException ex) { + System.out.println(ex); + } + } + } finally { + System.out.println(dir.getPath() + " processed."); + } + } +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/DbFileContents.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/DbFileContents.java new file mode 100644 index 0000000000..44b8d27d2a --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/DbFileContents.java @@ -0,0 +1,315 @@ +/** @file + Java class DbFileContents is used to deal with FrameworkDatabase.db file cotents. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.io.File; +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.ListIterator; +import java.util.Date; +import java.text.SimpleDateFormat; + +import org.apache.xmlbeans.XmlCursor; +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlOptions; + +import org.tianocore.*; + +/** + This class provides methods for add, remove, query FrameworkDatabase.db file. + + @since PackageEditor 1.0 +**/ +public class DbFileContents { + + /// + /// return values for various conditions. + /// + static final int BASE_PACKAGE_NOT_INSTALLED = 1; + + static final int VERSION_NOT_EQUAL = 2; + + static final int GUID_NOT_EQUAL = 3; + + static final int SAME_ALL = 4; + + private File dbFile = null; + + private FrameworkDatabaseDocument fdd = null; + + private FrameworkDatabaseDocument.FrameworkDatabase fddRoot = null; + + private PackageListDocument.PackageList pkgList = null; + + public DbFileContents() { + super(); + // TODO Auto-generated constructor stub + } + + /** + Parse file f, store its xml data in fdd, store root xml element in fddRoot. + + @param f DB file to parse + **/ + public DbFileContents(File f) { + try { + dbFile = f; + if (fdd == null) { + fdd = ((FrameworkDatabaseDocument) XmlObject.Factory.parse(dbFile)); + } + fddRoot = fdd.getFrameworkDatabase(); + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + /** + Generate the Package element in FrameworkDatabase.db + + @param baseName Base name of package + @param ver Version of package + @param guid GUID of package + @param path Where the package installed + @param installDate When the package installed + **/ + public void genPackage (String baseName, String ver, String guid, String path, String installDate) { + if (getPkgList() == null) { + pkgList = fddRoot.addNewPackageList(); + } + PackageListDocument.PackageList.Package p = pkgList.addNewPackage(); + p.addNewPackageName().setStringValue(baseName); + p.addNewGuid().setStringValue(guid); + p.addVersion(ver); + p.addNewPath().setStringValue(path); + p.addNewInstalledDate().setStringValue(installDate); + } + + /** + Get PackageList + + @return PackageListDocument.PackageList + **/ + public PackageListDocument.PackageList getPkgList() { + if (pkgList == null) { + pkgList = fddRoot.getPackageList(); + } + return pkgList; + } + + /** + Remove PackageList and all elements under it. + **/ + public void removePackageList() { + XmlObject o = fddRoot.getPackageList(); + if (o == null) + return; + XmlCursor cursor = o.newCursor(); + cursor.removeXml(); + } + /** + Get the number of Package elements. + + @return int + **/ + public int getPackageCount () { + return fddRoot.getPackageList().getPackageList().size(); + } + + /** + Get all Package contents into String array + + @param pkg Two dimentional array to store Package info. + **/ + public void getPackageList(String[][] pkg) { + List l = fddRoot.getPackageList().getPackageList(); + int i = 0; + ListIterator li = l.listIterator(); + while (li.hasNext()) { + PackageListDocument.PackageList.Package p = (PackageListDocument.PackageList.Package) li + .next(); + if (p.getPackageNameArray(0)!= null) { + pkg[i][0] = p.getPackageNameArray(0).getStringValue(); + } + + pkg[i][1] = p.getVersionArray(0); + + if (p.getGuidArray(0) != null) { + pkg[i][2] = p.getGuidArray(0).getStringValue(); + } + if (p.getPathArray(0) != null) { + pkg[i][3] = p.getPathArray(0).getStringValue(); + } + if (p.getInstalledDateArray(0) != null) { + pkg[i][4] = p.getInstalledDateArray(0); + } + i++; + } + } + /** + Check whether destDir has been used by one Package + + @param destDir The directory to check. + @retval <1> destDir has been used + @retval <0> destDir has not been used + @return int + **/ + public int checkDir(String destDir) { + List lp = fddRoot.getPackageList().getPackageList(); + + ListIterator lpi = lp.listIterator(); + while (lpi.hasNext()) { + PackageListDocument.PackageList.Package p = (PackageListDocument.PackageList.Package) lpi.next(); + if (p.getPathArray(0).getStringValue().equals(destDir)) { + return 1; + } + } + return 0; + } + + /** + Find the package info. and store results into list of same base name or list + of same version. + + @param base The base name of package + @param version The version of package + @param guid the GUID of package + @param lpSameBase The list to store package info with the same base name with "base" + @param lpSameVersion The list to store package info from lpSameBase and same version + with "version" + @retval <0> No package installed has base name "base" + @retval At least one package installed with "base" but no "version" + @retval At least one package installed with "base" and "version" but no "guid" + @retval One installed package has the same base, version and guid + @return int + **/ + public int query(String base, String version, String guid, + List lpSameBase, + List lpSameVersion) { + + List lp = fddRoot.getPackageList().getPackageList(); + + ListIterator lpi = lp.listIterator(); + while (lpi.hasNext()) { + PackageListDocument.PackageList.Package p = (PackageListDocument.PackageList.Package) lpi.next(); + if (p.getPackageNameArray(0).getStringValue().equals(base)) { + lpSameBase.add(p); + } + } + + if (lpSameBase.size() == 0) { + return 0; + } + + for (ListIterator li = lpSameBase.listIterator(); li.hasNext();) { + PackageListDocument.PackageList.Package p = (PackageListDocument.PackageList.Package) li.next(); + if (p.getVersionArray(0).equals(version)) { + lpSameVersion.add(p); + } + } + + if (lpSameVersion.size() == 0) { + return VERSION_NOT_EQUAL; + } + + for (ListIterator li = lpSameVersion.listIterator(); li.hasNext();) { + PackageListDocument.PackageList.Package p = (PackageListDocument.PackageList.Package) li.next(); + if (!p.getGuidArray(0).getStringValue().equals(guid)) { + return GUID_NOT_EQUAL; + } + } + + return SAME_ALL; + + } + + /** + Update package info (name, version, guid) with installDir, newVer, newGuid. + And update install date with current date. if no package info available, add + a new entry. + + @param name Original base name + @param version Original version + @param guid Original GUID + @param installDir original path + @param newVer Version value of package to be installed + @param newGuid GUID value of package to be installed + @throws IOException Exception during file operation + **/ + public void updatePkgInfo(String name, String version, String guid, String installDir, String newVer, String newGuid) + throws IOException { + List lp = fddRoot.getPackageList().getPackageList(); + + ListIterator lpi = lp.listIterator(); + while (lpi.hasNext()) { + PackageListDocument.PackageList.Package p = (PackageListDocument.PackageList.Package) lpi.next(); + if (p.getPackageNameArray(0).getStringValue().equals(name)) { + if (p.getVersionArray(0).equals(version)) { + if (p.getGuidArray(0).getStringValue().equals(guid)) { + p.setVersionArray(0, newVer); + p.getGuidArray(0).setStringValue(newGuid); + p.getPathArray(0).setStringValue(installDir); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + Date date = new Date(); + p.setInstalledDateArray(0, format.format(date)); + saveAs(); + return; + + } + } + } + } + + addNewPkgInfo(name, newVer, newGuid, installDir); + } + + /** + Add one new package entry. + + @param name Package base name + @param version Package version + @param guid Package Guid + @param installDir Package path + @throws IOException Exception during file operation + **/ + public void addNewPkgInfo(String name, String version, String guid, String installDir) throws IOException { + + PackageListDocument.PackageList.Package p = fddRoot.getPackageList().addNewPackage(); + p.addNewPackageName().setStringValue(name); + p.addNewGuid().setStringValue(guid); + p.addNewVersion().setStringValue(version); + p.addNewPath().setStringValue(installDir); + + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + Date date = new Date(); + p.addNewInstalledDate().setStringValue(format.format(date)); + saveAs(); + } + + /** + Save the fdd into file with format options + **/ + public void saveAs() { + XmlOptions options = new XmlOptions(); + + options.setCharacterEncoding("UTF-8"); + options.setSavePrettyPrint(); + options.setSavePrettyPrintIndent(2); + try { + fdd.save(dbFile, options); + } catch (IOException e) { + e.printStackTrace(); + } + } + +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/ForceInstallPkg.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/ForceInstallPkg.java new file mode 100644 index 0000000000..4fe88b49fd --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/ForceInstallPkg.java @@ -0,0 +1,80 @@ +/** @file + Java class ForceInstallPkg is used to install a package without DB check. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.io.*; +import java.util.jar.*; +import org.apache.xmlbeans.XmlException; + +/** + Derived class from FrameworkPkg, installation skipping some checks. + + @since PackageEditor 1.0 +**/ +public class ForceInstallPkg extends FrameworkPkg { + + private String oldVer = null; + + private String oldGuid = null; + + /** + Constructor with parameters + + @param s Package path to be installed + @param d Destination directory + **/ + public ForceInstallPkg(String s, String d) { + super(s, d); + + } + + public void setOldVersion(String v) { + oldVer = v; + } + + public void setOldGuid(String guid) { + oldGuid = guid; + } + + /** + Set jar file to package name to be installed + **/ + protected void pre_install() throws DirSame, IOException { + setJf(new JarFile(getPkg())); + + } + + /** + Update database file contents after install + **/ + protected void post_install() throws IOException, XmlException { + // + // Get package info. from FDPManifest.xml file + // + setJf(new JarFile(getPkg())); + ManifestContents manFile = new ManifestContents(getManifestInputStream(getJf())); + setBName(manFile.getBaseName()); + setPVer(manFile.getVersion()); + setPGuid(manFile.getGuid()); + getJf().close(); + + // + // Add force installed package info. into database file + // + setDbFile(new File(getWkSpace() + System.getProperty("file.separator") + FrameworkPkg.dbConfigFile)); + setDfc(new DbFileContents(new File(getWkSpace() + System.getProperty("file.separator") + dbConfigFile))); + getDfc().updatePkgInfo(getBName(), oldVer, oldGuid, getWkDir().substring(getWkSpace().length() + 1), getPVer(), + getPGuid()); + } + +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/FrameworkPkg.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/FrameworkPkg.java new file mode 100644 index 0000000000..b184cf9364 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/FrameworkPkg.java @@ -0,0 +1,402 @@ +/** @file + Java class FrameworkPkg is used to do package related operations. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.io.*; +import java.util.Enumeration; +import java.util.LinkedList; +import java.util.List; +import java.util.jar.*; +import org.apache.xmlbeans.*; + +import org.tianocore.PackageListDocument; + +/** + This class deals with package related operations + + @since PackageEditor 1.0 +**/ +public class FrameworkPkg { + + private String pkg = null; + + private JarFile jf = null; + + /// + /// where the package will be extracted to + /// + private String wkDir = null; + + private String bName = null; + + private String pVer = null; + + private String pGuid = null; + + /// + /// current WORKSPACE location + /// + private String wkSpace = null; + + private File dbFile = null; + + private DbFileContents dfc = null; + + /// + /// relative path of FrameworkDatabase.db file + /// + final static String dbConfigFile = "Tools" + System.getProperty("file.separator") + "Conf" + + System.getProperty("file.separator") + "FrameworkDatabase.db"; + + + public FrameworkPkg() { + + } + + public FrameworkPkg(String package_name, String work_space) { + pkg = package_name; + wkSpace = work_space; + } + + /** + install package (*.fdp file) to dir + + @param dir Destination directory + @retval <0> Install successfully + @return int + @throws IOException + @throws XmlException Xml file exception + @throws DirSame One package already installed to dir + @throws BasePkgNotInstalled Some package must be installed first + @throws VerNotEqual At least one package info with same base name but version different + @throws GuidNotEqual At least one package info with same base name and version but guid different + @throws SameAll At least one package info with same base name, version and guid same + **/ + public int install(final String dir) throws IOException, XmlException, DirSame, BasePkgNotInstalled, VerNotEqual, + GuidNotEqual, SameAll { + wkDir = dir; + pre_install(); + extract(wkDir); + post_install(); + return 0; + } + + public int uninstall() { + + return 0; + } + + /** + Check package info. against Frameworkdatabase.db + + @throws IOException + @throws XmlException Xml file exception + @throws DirSame One package already installed to dir + @throws BasePkgNotInstalled Some package must be installed first + @throws VerNotEqual At least one package info with same base name but version different + @throws GuidNotEqual At least one package info with same base name and version but guid different + @throws SameAll At least one package info with same base name, version and guid same + **/ + protected void pre_install() throws IOException, XmlException, DirSame, BasePkgNotInstalled, VerNotEqual, + GuidNotEqual, SameAll { + + jf = new JarFile(pkg); + + ManifestContents manFile = new ManifestContents(getManifestInputStream(jf)); + + String baseName = manFile.getBaseName(); + String pkgVersion = manFile.getVersion(); + String pkgGuid = manFile.getGuid(); + bName = baseName; + pVer = pkgVersion; + pGuid = pkgGuid; + + if (dbFile == null) { + dbFile = new File(wkSpace + System.getProperty("file.separator") + dbConfigFile); + } + // + // the db file should exist if base packages have been installed + // + if (!dbFile.exists()) { + throw new BasePkgNotInstalled(); + } + + if (dfc == null) { + dfc = new DbFileContents(dbFile); + } + if (dfc.checkDir(wkDir) != 0) { + throw new DirSame(); + } + + // + // Get database info into lists + // + List lpSameBase = new LinkedList(); + List lpSameVersion = new LinkedList(); + int i = dfc.query(baseName, pkgVersion, pkgGuid, lpSameBase, lpSameVersion); + + // + // throw various kind of exceptions according to query return value. + // + if (i == DbFileContents.VERSION_NOT_EQUAL) { + + jf.close(); + throw new VerNotEqual(lpSameBase); + } + if (i == DbFileContents.GUID_NOT_EQUAL) { + + jf.close(); + throw new GuidNotEqual(lpSameVersion); + } + if (i == DbFileContents.SAME_ALL) { + jf.close(); + throw new SameAll(lpSameVersion); + } + + } + + /** + Add package info into db file. + + @throws IOException + @throws XmlException + **/ + protected void post_install() throws IOException, XmlException { + + dfc.addNewPkgInfo(bName, pVer, pGuid, wkDir.substring(wkSpace.length() + 1)); + + } + + /** + Extract package to dir + + @param dir Destination directory + @throws DirSame + @throws IOException + **/ + private void extract(String dir) throws DirSame, IOException { + + new File(dir).mkdirs(); + dir += System.getProperty("file.separator"); + try { + for (Enumeration e = jf.entries(); e.hasMoreElements();) { + JarEntry je = (JarEntry) e.nextElement(); + + // + // jar entry contains directory only, make these directories + // + if (je.isDirectory()) { + new File(dir + je.getName()).mkdirs(); + continue; + } + + // + // jar entry contains relative path and file name, make relative directories + // under destination dir + // + int index = je.getName().lastIndexOf(System.getProperty("file.separator")); + if (index != -1) { + String dirPath = je.getName().substring(0, index); + new File(dir + dirPath).mkdirs(); + } + + if (je != null) { + // + // Get an input stream for this entry. + // + InputStream entryStream = jf.getInputStream(je); + + try { + // + // Create the output file (clobbering the file if it exists). + // + FileOutputStream file = new FileOutputStream(dir + je.getName()); + + try { + + byte[] buffer = new byte[1024]; + int bytesRead; + // + // Read the entry data and write it to the output file. + // + while ((bytesRead = entryStream.read(buffer)) != -1) { + file.write(buffer, 0, bytesRead); + } + + System.out.println(je.getName() + " extracted."); + } finally { + file.close(); + } + } finally { + entryStream.close(); + } + } + + } + + } finally { + jf.close(); + + } + + } + + public String getBName() { + return bName; + } + + public void setBName(String name) { + bName = name; + } + + public File getDbFile() { + return dbFile; + } + + public void setDbFile(File dbFile) { + this.dbFile = dbFile; + } + + public DbFileContents getDfc() { + return dfc; + } + + public void setDfc(DbFileContents dfc) { + this.dfc = dfc; + } + + public String getPGuid() { + return pGuid; + } + + public void setPGuid(String guid) { + pGuid = guid; + } + + public String getPVer() { + return pVer; + } + + public void setPVer(String ver) { + pVer = ver; + } + + public String getWkDir() { + return wkDir; + } + + public void setWkDir(String wkDir) { + this.wkDir = wkDir; + } + + public String getWkSpace() { + return wkSpace; + } + + public void setWkSpace(String wkSpace) { + this.wkSpace = wkSpace; + } + + public JarFile getJf() { + return jf; + } + + public void setJf(JarFile jf) { + this.jf = jf; + } + + public String getPkg() { + return pkg; + } + + public void setPkg(String pkg) { + this.pkg = pkg; + } + + /** + Get the input stream of FDPManifest.xml file from jar entry + + @param jf The Jar file that contains FDPManifest.xml file + @return InputStream + @throws IOException + **/ + protected InputStream getManifestInputStream(JarFile jf) throws IOException { + JarEntry je = null; + for (Enumeration e = jf.entries(); e.hasMoreElements();) { + je = (JarEntry) e.nextElement(); + if (je.getName().contains("FDPManifest.xml")) + return jf.getInputStream(je); + } + + return null; + } + +} + + +/** + Various Exception classes for what happened when database info and package info + are compared. + + @since PackageEditor 1.0 +**/ +class DirSame extends Exception { + final static long serialVersionUID = 0; +} + +class BasePkgNotInstalled extends Exception { + final static long serialVersionUID = 0; +} + +class VerNotEqual extends Exception { + final static long serialVersionUID = 0; + + //private String version = null; + List lppSameBase = null; + + VerNotEqual(List ver) { + lppSameBase = ver; + } + + public List getVersion() { + return lppSameBase; + } +} + +class GuidNotEqual extends Exception { + final static long serialVersionUID = 0; + + private List lppSameVer = null; + + GuidNotEqual(List ver) { + lppSameVer = ver; + } + + public List getGuid() { + return lppSameVer; + } +} + +class SameAll extends Exception { + final static long serialVersionUID = 0; + + private List version = null; + + SameAll(List ver) { + version = ver; + } + + public List getVersion() { + return version; + } +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/GuiPkgInstall.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/GuiPkgInstall.java new file mode 100644 index 0000000000..3e757206f7 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/GuiPkgInstall.java @@ -0,0 +1,804 @@ +/** @file + Java class GuiPkgInstall is GUI for package installation. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + + +import javax.swing.JPanel; +import javax.swing.JFrame; +import javax.swing.JButton; +import javax.swing.JFileChooser; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JTextField; + +import java.awt.Dimension; +import java.awt.GridLayout; +import java.awt.Toolkit; + +import java.awt.FlowLayout; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import java.awt.ComponentOrientation; +import java.io.File; +import java.util.Hashtable; + +import javax.swing.SwingConstants; +import javax.swing.JProgressBar; +import javax.swing.filechooser.FileFilter; + +import org.apache.xmlbeans.XmlException; + + +/** + GUI for package installation. + + @since PackageEditor 1.0 +**/ +public class GuiPkgInstall extends JFrame implements MouseListener { + + final static long serialVersionUID = 0; + + static JFrame frame; + + /// + /// backup of "this". As we cannot use "this" to refer outer class inside inner class + /// + private JFrame pThis = null; + + private JFileChooser chooser = null; + + private JPanel jPanel = null; + + private JPanel jPanel1 = null; + + private JTextField jTextField = null; + + private JButton jButton = null; + + private JPanel jPanel2 = null; + + private JLabel jLabel1 = null; + + private JPanel jPanel4 = null; + + private JTextField jTextField1 = null; + + private JButton jButton1 = null; + + private JPanel jPanel5 = null; + + private JPanel jPanel6 = null; + + private JPanel jPanel7 = null; + + private JLabel jLabel2 = null; + + private JTextField jTextField2 = null; + + private JButton jButton2 = null; + + private JButton jButton3 = null; + + private JPanel jPanel3 = null; + + private JLabel jLabel = null; + + private JProgressBar jProgressBar = null; + + private JButton jButton4 = null; + + + public GuiPkgInstall() { + super(); + initialize(); + + } + + /** + GUI initialization + **/ + private void initialize() { + this.setSize(new java.awt.Dimension(454, 313)); + this.setContentPane(getJPanel()); + this.setTitle("Package Installation"); + this.addWindowListener(new GuiPkgInstallAdapter(this)); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE); + this.centerWindow(); + pThis = this; + } + + /** + make window appear center of screen + + @param intWidth + @param intHeight + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + This method initializes jPanel + @return javax.swing.JPanel + **/ + private JPanel getJPanel() { + if (jPanel == null) { + GridLayout gridLayout = new GridLayout(); + gridLayout.setRows(7); + gridLayout.setColumns(1); + jPanel = new JPanel(); + jPanel.setLayout(gridLayout); + jPanel.add(getJPanel3(), null); + jPanel.add(getJPanel1(), null); + jPanel.add(getJPanel2(), null); + jPanel.add(getJPanel4(), null); + jPanel.add(getJPanel5(), null); + jPanel.add(getJPanel6(), null); + jPanel.add(getJPanel7(), null); + } + return jPanel; + } + + /** + This method initializes jPanel1 + + @return javax.swing.JPanel + **/ + private JPanel getJPanel1() { + if (jPanel1 == null) { + FlowLayout flowLayout = new FlowLayout(); + flowLayout.setAlignment(java.awt.FlowLayout.LEFT); + jPanel1 = new JPanel(); + jPanel1.setLayout(flowLayout); + jPanel1.add(getJTextField(), null); + jPanel1.add(getJButton(), null); + } + return jPanel1; + } + + /** + This method initializes jTextField + + @return javax.swing.JTextField + **/ + private JTextField getJTextField() { + if (jTextField == null) { + jTextField = new JTextField(); + jTextField.setHorizontalAlignment(javax.swing.JTextField.LEFT); + jTextField.setPreferredSize(new java.awt.Dimension(350, 20)); + } + return jTextField; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setHorizontalAlignment(javax.swing.SwingConstants.LEFT); + jButton.setText("Browse"); + jButton.setComponentOrientation(java.awt.ComponentOrientation.LEFT_TO_RIGHT); + jButton.setHorizontalTextPosition(javax.swing.SwingConstants.CENTER); + jButton.setToolTipText("Where is the package?"); + jButton.setFont(new java.awt.Font("Dialog", java.awt.Font.BOLD, 12)); + + jButton.setPreferredSize(new java.awt.Dimension(80, 20)); + jButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + if (chooser == null) { + chooser = new JFileChooser(); + } + // + // disable multi-selection, you can only select one item each time. + // + chooser.setMultiSelectionEnabled(false); + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + chooser.setFileFilter(new PkgFileFilter("fdp")); + int retval = chooser.showOpenDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + + File theFile = chooser.getSelectedFile(); + jTextField.setText(theFile.getPath()); + // + // set a default directory for installation (WORKSPACE\PackageFileName) + // + if (jTextField1.getText().length() > 0) { + int indexbegin = jTextField.getText().lastIndexOf(System.getProperty("file.separator")); + int indexend = jTextField.getText().lastIndexOf('.'); + if (indexbegin >= 0 && indexend >= 0) { + jTextField2.setText(jTextField1.getText() + + jTextField.getText().substring(indexbegin, indexend)); + } else { + JOptionPane.showMessageDialog(frame, "Wrong Path:" + jTextField.getText()); + } + } + } + } + }); + } + return jButton; + } + + /** + This method initializes jPanel2 + + @return javax.swing.JPanel + **/ + private JPanel getJPanel2() { + if (jPanel2 == null) { + FlowLayout flowLayout1 = new FlowLayout(); + flowLayout1.setAlignment(java.awt.FlowLayout.LEFT); + flowLayout1.setVgap(20); + jLabel1 = new JLabel(); + jLabel1.setText("Enter Workspace Location"); + jLabel1.setComponentOrientation(java.awt.ComponentOrientation.UNKNOWN); + jLabel1.setHorizontalTextPosition(javax.swing.SwingConstants.TRAILING); + jLabel1.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jPanel2 = new JPanel(); + jPanel2.setLayout(flowLayout1); + jPanel2.add(jLabel1, null); + } + return jPanel2; + } + + /** + This method initializes jPanel4 + + @return javax.swing.JPanel + **/ + private JPanel getJPanel4() { + if (jPanel4 == null) { + FlowLayout flowLayout2 = new FlowLayout(); + flowLayout2.setAlignment(java.awt.FlowLayout.LEFT); + jPanel4 = new JPanel(); + jPanel4.setLayout(flowLayout2); + jPanel4.add(getJTextField1(), null); + jPanel4.add(getJButton1(), null); + } + return jPanel4; + } + + /** + This method initializes jTextField1 + + @return javax.swing.JTextField + **/ + private JTextField getJTextField1() { + if (jTextField1 == null) { + jTextField1 = new JTextField(); + jTextField1.setPreferredSize(new java.awt.Dimension(350, 20)); + + } + // + // default value is WORKSPACE environmental variable value + // + jTextField1.setText(System.getenv("WORKSPACE")); + return jTextField1; + } + + /** + This method initializes jButton1 + + @return javax.swing.JButton + **/ + private JButton getJButton1() { + if (jButton1 == null) { + jButton1 = new JButton(); + jButton1.setComponentOrientation(java.awt.ComponentOrientation.LEFT_TO_RIGHT); + + jButton1.setHorizontalAlignment(javax.swing.SwingConstants.LEADING); + jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.TRAILING); + jButton1.setText("Browse"); + jButton1.setPreferredSize(new java.awt.Dimension(80, 20)); + jButton1.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + if (chooser == null) { + chooser = new JFileChooser(); + } + // + // only directories can be selected for workspace location. + // + chooser.setMultiSelectionEnabled(false); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + int retval = chooser.showOpenDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + + File theFile = chooser.getSelectedFile(); + jTextField1.setText(theFile.getPath()); + // + // set a default directory for installation (WORKSPACE\PackageFileName) + // + if (jTextField.getText().length() > 0) { + int indexbegin = jTextField.getText().lastIndexOf(System.getProperty("file.separator")); + int indexend = jTextField.getText().lastIndexOf('.'); + if (indexbegin >= 0 && indexend >= 0) { + jTextField2.setText(jTextField1.getText() + + jTextField.getText().substring(indexbegin, indexend)); + } else { + JOptionPane.showMessageDialog(frame, "Wrong Path:" + jTextField.getText()); + } + } + } + + } + }); + } + return jButton1; + } + + /** + This method initializes jButton4 + + @return javax.swing.JButton + **/ + private JButton getJButton4() { + if (jButton4 == null) { + jButton4 = new JButton(); + jButton4.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + + jButton4.setHorizontalAlignment(SwingConstants.LEADING); + jButton4.setHorizontalTextPosition(SwingConstants.TRAILING); + jButton4.setText("Browse"); + jButton4.setPreferredSize(new Dimension(80, 20)); + jButton4.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + JFileChooser chooser = new JFileChooser(jTextField1.getText()); + + chooser.setMultiSelectionEnabled(false); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + int retval = chooser.showOpenDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + // + // specify installation directory from file chooser + // + File theFile = chooser.getSelectedFile(); + jTextField2.setText(theFile.getPath()); + + } + } + }); + + } + return jButton4; + } + /** + This method initializes jPanel5 + + @return javax.swing.JPanel + **/ + private JPanel getJPanel5() { + if (jPanel5 == null) { + FlowLayout flowLayout3 = new FlowLayout(); + flowLayout3.setAlignment(java.awt.FlowLayout.LEFT); + flowLayout3.setVgap(20); + jLabel2 = new JLabel(); + jLabel2.setComponentOrientation(java.awt.ComponentOrientation.UNKNOWN); + jLabel2.setHorizontalTextPosition(javax.swing.SwingConstants.TRAILING); + jLabel2.setText("Enter Installation Location Within Workspace"); + jLabel2.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING); + jPanel5 = new JPanel(); + jPanel5.setLayout(flowLayout3); + jPanel5.add(jLabel2, null); + } + return jPanel5; + } + + /** + This method initializes jPanel6 + + @return javax.swing.JPanel + **/ + private JPanel getJPanel6() { + if (jPanel6 == null) { + FlowLayout flowLayout4 = new FlowLayout(); + flowLayout4.setAlignment(java.awt.FlowLayout.LEFT); + jPanel6 = new JPanel(); + jPanel6.setLayout(flowLayout4); + jPanel6.add(getJTextField2(), null); + jPanel6.add(getJButton4(), null); + } + return jPanel6; + } + + /** + This method initializes jPanel7 + + @return javax.swing.JPanel + **/ + private JPanel getJPanel7() { + if (jPanel7 == null) { + FlowLayout flowLayout5 = new FlowLayout(); + flowLayout5.setAlignment(java.awt.FlowLayout.RIGHT); + jPanel7 = new JPanel(); + jPanel7.setLayout(flowLayout5); + jPanel7.add(getJProgressBar(), null); + jPanel7.add(getJButton2(), null); + jPanel7.add(getJButton3(), null); + } + return jPanel7; + } + + /** + This method initializes jTextField2 + + @return javax.swing.JTextField + **/ + private JTextField getJTextField2() { + if (jTextField2 == null) { + jTextField2 = new JTextField(); + jTextField2.setPreferredSize(new java.awt.Dimension(350, 20)); + } + return jTextField2; + } + + /** + This method initializes jButton2 + + @return javax.swing.JButton + **/ + private JButton getJButton2() { + if (jButton2 == null) { + jButton2 = new JButton(); + jButton2.setPreferredSize(new java.awt.Dimension(80, 20)); + jButton2.setText("Ok"); + jButton2.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + try { + // + // The installation directory must under workspace directory + // + locationcheck(jTextField.getText(), jTextField1.getText(), jTextField2.getText()); + } catch (Exception ee) { + JOptionPane.showMessageDialog(frame, "Package Location Error!"); + return; + } + + try { + // + // create a new FrameworkPkg object with user-selected package, current workspace location. + // install the package to dest dir from jTextField2 + // + int i = new FrameworkPkg(jTextField.getText(), jTextField1.getText()) + .install(jTextField2 + .getText()); + // + // the package is installed smoothly + // + if (i == 0) { + JOptionPane.showMessageDialog(frame, "Package" + jTextField.getText() + + " Installed Successfully!"); + } + } catch (BasePkgNotInstalled bpni) { + // + // exception no base package installed + // + JOptionPane + .showMessageDialog(frame, + "The Edk package needs to be installed before installing any other packages."); + } catch (VerNotEqual vne) { + // + // show modal GUI PkgInstallTypeChooser with user selected package name, + // current workspace location and the list of package info with same base name + // + ModalFrameUtil.showAsModal(new PkgInstallTypeChooser(jTextField.getText(), + jTextField1.getText(), vne.getVersion()), + pThis); + + } catch (GuidNotEqual gne) { + // + // show modal GUI PkgInstallTypeChooser with user selected package name, + // current workspace location and the list of package info with same base name and version + // + ModalFrameUtil.showAsModal(new PkgInstallTypeChooser(jTextField.getText(), + jTextField1.getText(), gne.getGuid()), + pThis); + + } catch (SameAll sa) { + // + // the package with same (base, version, guid) already exists. confirm user action. + // quit or replace the original info. (So only one package info entry in db file that may be triple same) + // + int retVal = JOptionPane + .showConfirmDialog( + frame, + "Package already exists. Would you like to replace it?", + "Package Installation", JOptionPane.YES_NO_OPTION); + if (retVal == JOptionPane.YES_OPTION) { + String installDir = sa.getVersion().listIterator().next().getPathArray(0).getStringValue(); + try { + ForceInstallPkg f = new ForceInstallPkg(jTextField.getText(), jTextField1.getText()); + // + // Get old packag info to meet the calling parameter layout of DbFileContents.updatePkgInfo + // ForceInstallPkg will call it after installation to update package info. + // + f.setOldVersion(sa.getVersion().listIterator().next().getVersionArray(0)); + f.setOldGuid(sa.getVersion().listIterator().next().getGuidArray(0).getStringValue()); + int i = f.install(jTextField1.getText() + System.getProperty("file.separator") + installDir); + if (i == 0) { + JOptionPane.showMessageDialog(frame, "Package" + jTextField.getText() + + " Installed Successfully!"); + } + } catch (Exception sae) { + System.out.println(sae.toString()); + JOptionPane.showMessageDialog(frame, "Extraction Error!"); + } + } + return; + } catch (XmlException xmle) { + System.out.println(xmle.toString()); + JOptionPane.showMessageDialog(frame, "Package Format Error!"); + } catch (DirSame ds) { + // + // You cannot install different packages into the same directory. + // + System.out.println(ds.toString()); + JOptionPane.showMessageDialog(frame, + "Another Package Exists There, Please Select Another Directory!"); + } catch (Exception ext) { + System.out.println(ext.toString()); + JOptionPane.showMessageDialog(frame, "Extraction Error!"); + } + } + }); + } + return jButton2; + } + + /** + * This method initializes jButton3 + * + * @return javax.swing.JButton + */ + private JButton getJButton3() { + if (jButton3 == null) { + jButton3 = new JButton(); + jButton3.setPreferredSize(new java.awt.Dimension(80, 20)); + jButton3.setText("Cancel"); + jButton3.addMouseListener(this); + } + return jButton3; + + } + + /** + This method initializes jPanel3 + + @return javax.swing.JPanel + */ + private JPanel getJPanel3() { + if (jPanel3 == null) { + jLabel = new JLabel(); + jLabel.setComponentOrientation(ComponentOrientation.UNKNOWN); + jLabel.setHorizontalTextPosition(SwingConstants.TRAILING); + jLabel.setText("Enter Package Location"); + jLabel.setHorizontalAlignment(SwingConstants.TRAILING); + FlowLayout flowLayout6 = new FlowLayout(); + flowLayout6.setVgap(20); + flowLayout6.setAlignment(FlowLayout.LEFT); + jPanel3 = new JPanel(); + jPanel3.setLayout(flowLayout6); + jPanel3.add(jLabel, null); + } + return jPanel3; + } + + /** + check user input validity + + @param s package path + @param s1 workspace path + @param s2 installation path + @throws Exception + **/ + private void locationcheck(String s, String s1, String s2) throws Exception { + if (new File(s).isFile() == false) + throw new Exception(); + if (new File(s1).isDirectory() == false) + throw new Exception(); + if (s2.startsWith(s1) == false) + throw new Exception(); + } + + + public void mouseClicked(MouseEvent arg0) { + // TODO Auto-generated method stub + int retVal = JOptionPane.showConfirmDialog(frame, "Are you sure to exit?", "Quit", JOptionPane.YES_NO_OPTION); + if (retVal == JOptionPane.YES_OPTION) { + this.dispose(); + } + return; + } + + public void mouseEntered(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + public void mouseExited(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + public void mousePressed(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + public void mouseReleased(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + /** + This method initializes jProgressBar + + @return javax.swing.JProgressBar + **/ + private JProgressBar getJProgressBar() { + if (jProgressBar == null) { + jProgressBar = new JProgressBar(); + jProgressBar.setComponentOrientation(java.awt.ComponentOrientation.LEFT_TO_RIGHT); + jProgressBar.setVisible(false); + } + return jProgressBar; + } + + + +} // @jve:decl-index=0:visual-constraint="24,82" + +/** +Derived from WindowAdapter, Event adapter for windowClosing event + +@since PackageEditor 1.0 +**/ +class GuiPkgInstallAdapter extends WindowAdapter { + + private JFrame frame = null; + + GuiPkgInstallAdapter(JFrame f) { + super(); + frame = f; + } + + /* (non-Javadoc) + * @see java.awt.event.WindowAdapter#windowClosing(java.awt.event.WindowEvent) + */ + @Override + public void windowClosing(WindowEvent arg0) { + // TODO Auto-generated method stub + super.windowClosing(arg0); + int retVal = JOptionPane.showConfirmDialog(frame, "Are you sure to exit?", "Quit", + JOptionPane.YES_NO_OPTION); + if (retVal == JOptionPane.YES_OPTION) { + frame.dispose(); + } + + } + +} + +/** + Filter out some specific type of file + + @since PackageEditor 1.0 +**/ +class PkgFileFilter extends FileFilter { + + /// + /// hash table used to store filter info. + /// + private Hashtable filters = null; + + + public PkgFileFilter() { + this.filters = new Hashtable(); + } + + /** + Create filter and add extension to hash table + + @param extension file extension string (e.g. "exe") + **/ + public PkgFileFilter(String extension) { + this(); + if(extension!=null) { + addExtension(extension); + } + + } + + public PkgFileFilter(String[] fileFilters) { + this(); + int i = 0; + while (i < fileFilters.length) { + // add filters one by one + addExtension(fileFilters[i]); + i++; + } + + } + + + /* (non-Javadoc) + * @see javax.swing.filechooser.FileFilter#accept(java.io.File) + */ + public boolean accept(File f) { + if (f != null) { + if (f.isDirectory()) { + return true; + } + + if (getExtension(f) != null && filters.get(getExtension(f)) != null) { + return true; + } + } + return false; + } + + + /** + Get the extension string of file + + @param f target file + @return String + **/ + public String getExtension(File f) { + if (f != null) { + int i = f.getName().lastIndexOf('.'); + if (i>0 && i(5); + } + filters.put(ext.toLowerCase(), "ext"); + + } + + /* (non-Javadoc) + * @see javax.swing.filechooser.FileFilter#getDescription() + */ + public String getDescription() { + return null; + } + +} + diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/GuiPkgUninstall.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/GuiPkgUninstall.java new file mode 100644 index 0000000000..667f65bf29 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/GuiPkgUninstall.java @@ -0,0 +1,370 @@ +/** @file + Java class GuiPkgUninstall is GUI for package installation. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import javax.swing.JPanel; +import javax.swing.JFrame; +import java.awt.FlowLayout; +//import java.awt.GridLayout; +import javax.swing.JLabel; +import javax.swing.JTextField; +import java.awt.Dimension; +import javax.swing.JButton; +import java.awt.ComponentOrientation; +import java.awt.Font; +import java.awt.Toolkit; +import java.io.File; + +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.SwingConstants; +import javax.swing.JList; +import javax.swing.JTextPane; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.DefaultTableModel; + +/** + GUI for package uninstallation. + + @since PackageEditor 1.0 +**/ +public class GuiPkgUninstall extends JFrame { + + final static long serialVersionUID = 0; + + static JFrame frame; + + private JPanel jPanel = null; + + private JLabel jLabel = null; + + private JTextField jTextField = null; + + private JButton jButton = null; + + private JLabel jLabel1 = null; + + private JPanel jPanel1 = null; + + private JButton jButton1 = null; + + private JButton jButton2 = null; + + private JScrollPane jScrollPane = null; + + private JTable jTable = null; + + private JButton jButton3 = null; + + private PkgRemoveTableModel model = null; + + private DbFileContents dfc = null; + + private JFrame pThis = null; + + + public GuiPkgUninstall() { + super(); + initialize(); + } + + + private void initialize() { + this.setSize(481, 404); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setContentPane(getJPanel()); + this.setTitle("Package Uninstallation"); + this.centerWindow(); + pThis = this; + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + initialize table contents from db file + + @param f FrameworkDatabase.db file under workspace + **/ + protected void loadDB(File f) { + if (!f.exists()) { + JOptionPane.showMessageDialog(frame, + "No FrameworkDatabase.db File!"); + return; + } + dfc = new DbFileContents(f); + if (dfc.getPackageCount() == 0) { + return; + } + // + // Get package list info. and add them one by one into table + // + String[][] saa = new String[dfc.getPackageCount()][5]; + dfc.getPackageList(saa); + int i = 0; + while (i < saa.length) { + model.addRow(saa[i]); + i++; + } + + } + /** + save package info. from table to db file + **/ + protected void save() { + dfc.removePackageList(); + int rowCount = jTable.getRowCount(); + int i = 0; + while (i < rowCount) { + + dfc.genPackage(jTable.getValueAt(i, 0).toString(), jTable.getValueAt(i, 1).toString(), + jTable.getValueAt(i, 2).toString(), jTable.getValueAt(i, 3).toString(), + jTable.getValueAt(i, 4).toString()); + i++; + } + dfc.saveAs(); + } + + private JPanel getJPanel() { + if (jPanel == null) { + jLabel1 = new JLabel(); + jLabel1.setBounds(new java.awt.Rectangle(20, 83, 141, 16)); + jLabel1.setText(" Packages Installed"); + jLabel = new JLabel(); + jLabel.setBounds(new java.awt.Rectangle(17, 16, 171, 16)); + jLabel.setText(" Enter Workspace Location"); + jPanel = new JPanel(); + jPanel.setLayout(null); + jPanel.add(jLabel, null); + jPanel.add(getJTextField(), null); + jPanel.add(getJButton(), null); + jPanel.add(jLabel1, null); + jPanel.add(getJPanel1(), null); + jPanel.add(getJScrollPane(), null); + } + return jPanel; + } + + /** + This method initializes jTextField + + @return javax.swing.JTextField + **/ + private JTextField getJTextField() { + if (jTextField == null) { + jTextField = new JTextField(); + jTextField.setBounds(new java.awt.Rectangle(16, 41, 350, 20)); + jTextField.setHorizontalAlignment(JTextField.LEFT); + jTextField.setEditable(false); + jTextField.setText(System.getenv("WORKSPACE")); + jTextField.setPreferredSize(new Dimension(350, 20)); + } + return jTextField; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setBounds(new java.awt.Rectangle(372,40,78,20)); + jButton.setFont(new Font("Dialog", Font.BOLD, 12)); + jButton.setPreferredSize(new Dimension(80, 20)); + jButton.setToolTipText("Where is the package?"); + jButton.setHorizontalAlignment(SwingConstants.LEFT); + jButton.setHorizontalTextPosition(SwingConstants.CENTER); + jButton.setText("Browse"); + jButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + // + // user can select another workspace directory + // + JFileChooser chooser = new JFileChooser(); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + chooser.setMultiSelectionEnabled(false); + int retval = chooser.showOpenDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + // + // update table when user selects a new workspace directory + // + jTextField.setText(chooser.getSelectedFile().getPath()); + File f = new File(chooser.getSelectedFile(), FrameworkPkg.dbConfigFile); + loadDB(f); + } + } + }); + } + return jButton; + } + + /** + This method initializes jPanel1 + + @return javax.swing.JPanel + **/ + private JPanel getJPanel1() { + if (jPanel1 == null) { + FlowLayout flowLayout = new FlowLayout(); + flowLayout.setAlignment(java.awt.FlowLayout.LEFT); + flowLayout.setHgap(20); + jPanel1 = new JPanel(); + jPanel1.setLayout(flowLayout); + jPanel1.setBounds(new java.awt.Rectangle(133,310,318,53)); + jPanel1.add(getJButton3(), null); + jPanel1.add(getJButton1(), null); + jPanel1.add(getJButton2(), null); + } + return jPanel1; + } + + /** + This method initializes jButton1 + + @return javax.swing.JButton + **/ + private JButton getJButton1() { + if (jButton1 == null) { + jButton1 = new JButton(); + jButton1.setPreferredSize(new java.awt.Dimension(85, 20)); + jButton1.setText("Ok"); + jButton1.setHorizontalTextPosition(javax.swing.SwingConstants.LEFT); + jButton1.setEnabled(true); + jButton1.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + if (dfc != null) { + // + // save package info. to file before exit + // + save(); + } + pThis.dispose(); + } + }); + } + return jButton1; + } + + /** + This method initializes jButton2 + + @return javax.swing.JButton + **/ + private JButton getJButton2() { + if (jButton2 == null) { + jButton2 = new JButton(); + jButton2.setPreferredSize(new java.awt.Dimension(85, 20)); + jButton2.setText("Cancel"); + jButton2.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + pThis.dispose(); + } + }); + } + return jButton2; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(20,108,431,194)); + jScrollPane.setViewportView(getJTable()); + } + return jScrollPane; + } + + /** + This method initializes jTable + + @return javax.swing.JTable + **/ + private JTable getJTable() { + if (jTable == null) { + model = new PkgRemoveTableModel(); + jTable = new JTable(model); + jTable.setRowHeight(20); + jTable.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION); + jTable.setRowSelectionAllowed(true); + model.addColumn("PackageName"); + model.addColumn("Version"); + model.addColumn("GUID"); + model.addColumn("Path"); + model.addColumn("InstallDate"); + File f = new File(jTextField.getText(), FrameworkPkg.dbConfigFile); + loadDB(f); + } + return jTable; + } + + /** + This method initializes jButton3 + + @return javax.swing.JButton + **/ + private JButton getJButton3() { + if (jButton3 == null) { + jButton3 = new JButton(); + jButton3.setText("Remove"); + jButton3.setPreferredSize(new java.awt.Dimension(85,20)); + jButton3.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + if (model != null){ + int index = jTable.getSelectedRow(); + if (index > -1) { + model.removeRow(index); + } + } + } + }); + } + return jButton3; + } + +} // @jve:decl-index=0:visual-constraint="10,10" + +/** + Derived table model which disables table edit + + @since PackageEditor 1.0 +**/ +class PkgRemoveTableModel extends DefaultTableModel { + PkgRemoveTableModel() { + super(); + } + + public boolean isCellEditable (int row, int col) { + return false; + } +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/ManifestContents.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/ManifestContents.java new file mode 100644 index 0000000000..7bebc627a2 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/ManifestContents.java @@ -0,0 +1,74 @@ +/** @file + Java class ManifestContents is used to deal with FDPManifest.xml file related + operations. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import org.apache.xmlbeans.XmlException; + +import org.tianocore.*; +import java.io.*; + +/** + This class operates on FDPManifest.xml file + + @since PackageEditor 1.0 +**/ +public class ManifestContents { + + /// + /// it is more convenient to get input stream from Jar entry of to-be-installed package file. + /// so i use InputStream instead of File + /// + private InputStream manIs = null; + + FrameworkDevPkgManifestDocument manDoc = null; + + HeaderDocument hdr = null; + + FrameworkDevPkgManifestDocument.FrameworkDevPkgManifest manRoot = null; + + public ManifestContents(InputStream fis) throws XmlException, IOException { + + manIs = fis; + manDoc = FrameworkDevPkgManifestDocument.Factory.parse(manIs); + manRoot = manDoc.getFrameworkDevPkgManifest(); + + } + + /** + Get package name from manifest file header. + + @return String + **/ + public String getBaseName() { + return manRoot.getHeader().getPackageName().getStringValue(); + } + + /** + Get package version from manifest file header. + + @return String + **/ + public String getVersion() { + return manRoot.getHeader().getVersion(); + } + + /** + Get package GUID from manifest file header. + + @return String + **/ + public String getGuid() { + return manRoot.getHeader().getGuid().getStringValue(); + } +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/ModalFrameUtil.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/ModalFrameUtil.java new file mode 100644 index 0000000000..a748a82f76 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/ModalFrameUtil.java @@ -0,0 +1,107 @@ +/** @file + Java class ModalFrameUtil is used to show modal frame. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; + +/** + This class is used to show modal frame. + + @since PackageEditor 1.0 +**/ +public class ModalFrameUtil { + /** + Invocation handler for event threads + + @since PackageEditor 1.0 + **/ + static class EventPump implements InvocationHandler { + Frame frame; + + public EventPump(Frame frame) { + this.frame = frame; + } + + /** + Invocation handler invoked by Method.invoke + **/ + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + // + // return frame showing status for Conditional.evaluate() + // + return frame.isShowing() ? Boolean.TRUE : Boolean.FALSE; + } + + public void start() throws Exception { + Class clazz = Class.forName("java.awt.Conditional"); + // + // Conditional proxy instance will invoke "this" InvocationHandler.invoke when calling its methods + // + Object conditional = Proxy.newProxyInstance(clazz.getClassLoader(), new Class[] { clazz }, this); + // + // EventDisaptchThread.pumpEvents will be called under Conditional "conditional" + // + Method pumpMethod = Class.forName("java.awt.EventDispatchThread").getDeclaredMethod("pumpEvents", + new Class[] { clazz }); + pumpMethod.setAccessible(true); + // + // pumpEvents when conditional.evaluate() == true (frame.isShowing() in EventPump.invoke) + // + pumpMethod.invoke(Thread.currentThread(), new Object[] { conditional }); + } + } + + /** + Show modal frame, return only when frame closed. + + @param frame Frame to be modal + @param owner Parent Frame + **/ + public static void showAsModal(final Frame frame, final Frame owner) { + frame.addWindowListener(new WindowAdapter() { + public void windowOpened(WindowEvent e) { + owner.setEnabled(false); + } + + public void windowClosed(WindowEvent e) { + owner.setEnabled(true); + owner.setVisible(true); + owner.removeWindowListener(this); + } + }); + + owner.addWindowListener(new WindowAdapter() { + public void windowActivated(WindowEvent e) { + if (frame.isShowing()) { + frame.setExtendedState(JFrame.NORMAL); + frame.toFront(); + } else { + owner.removeWindowListener(this); + } + } + }); + + frame.setVisible(true); + try { + new EventPump(frame).start(); + } catch (Throwable throwable) { + throw new RuntimeException(throwable); + } + } +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageAction.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageAction.java new file mode 100644 index 0000000000..71d291548d --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageAction.java @@ -0,0 +1,348 @@ +/** @file + Java class PackageAction is GUI for create spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Toolkit; + +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JFrame; +import java.awt.GridLayout; +import java.io.File; + +import javax.swing.JButton; + +/** + GUI for create spd file + + @since PackageEditor 1.0 +**/ +public class PackageAction extends JFrame { + + static JFrame frame; + + private JPanel jContentPane = null; + + private JButton jButton = null; + + private JButton jButton1 = null; + + private JButton jButton2 = null; + + private JButton jButton3 = null; + + private JButton jButton4 = null; + + private JButton jButton5 = null; + + private JButton jButton6 = null; + + private JButton jButton7 = null; + + /// + /// SpdFileContents object passed from main + /// + private SpdFileContents sfc = null; + + private JFrame pThis = null; // @jve:decl-index=0:visual-constraint="304,10" + + private JButton jButton8 = null; + + private JButton jButton9 = null; // @jve:decl-index=0:visual-constraint="116,388" + + /** + This is the default constructor + **/ + public PackageAction(SpdFileContents sfc) { + super(); + initialize(); + this.sfc = sfc; + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(305, 385); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setContentPane(getJContentPane()); + this.setTitle("Please Choose an Action"); + this.centerWindow(); + this.pThis = this; + + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + GridLayout gridLayout = new GridLayout(); + gridLayout.setRows(10); + gridLayout.setColumns(1); + jContentPane = new JPanel(); + jContentPane.setPreferredSize(new java.awt.Dimension(200,300)); + jContentPane.setLayout(gridLayout); + jContentPane.add(getJButton8(), null); + jContentPane.add(getJButton7(), null); + jContentPane.add(getJButton6(), null); + jContentPane.add(getJButton5(), null); + jContentPane.add(getJButton4(), null); + jContentPane.add(getJButton3(), null); + jContentPane.add(getJButton2(), null); + jContentPane.add(getJButton1(), null); + jContentPane.add(getJButton(), null); + jContentPane.add(getJButton9(), null); + } + return jContentPane; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setText("Save"); + jButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + // + // save sfc contents to file + // + JFileChooser chooser = new JFileChooser(System.getenv("WORKSPACE")); + chooser.setMultiSelectionEnabled(false); + + int retval = chooser.showSaveDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + try { + File theFile = chooser.getSelectedFile(); + if (theFile.exists()) { + int retVal = JOptionPane.showConfirmDialog(frame, "Are you sure to replace the exising one?", "File Exists", + JOptionPane.YES_NO_OPTION); + if (retVal == JOptionPane.NO_OPTION) { + return; + } + } + sfc.saveAs(theFile); + + } catch (Exception ee) { + System.out.println(ee.toString()); + } +// pThis.dispose(); + } + + } + }); + } + return jButton; + } + + /** + This method initializes jButton1 + + @return javax.swing.JButton + **/ + private JButton getJButton1() { + if (jButton1 == null) { + jButton1 = new JButton(); + jButton1.setText("Add PCD Information"); + jButton1.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + // + // Add PCD frame show modal + // + ModalFrameUtil.showAsModal(new PackagePCD(sfc), pThis); + } + }); + } + return jButton1; + } + + /** + This method initializes jButton2 + + @return javax.swing.JButton + **/ + private JButton getJButton2() { + if (jButton2 == null) { + jButton2 = new JButton(); + jButton2.setText("Add PPI Declarations"); + jButton2.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + // + // Add PPI frame show modal + // + ModalFrameUtil.showAsModal(new PackagePpi(sfc), pThis); + } + }); + } + return jButton2; + } + + /** + This method initializes jButton3 + + @return javax.swing.JButton + **/ + private JButton getJButton3() { + if (jButton3 == null) { + jButton3 = new JButton(); + jButton3.setText("Add Protocol Declarations"); + jButton3.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new PackageProtocols(sfc), pThis); + } + }); + } + return jButton3; + } + + /** + This method initializes jButton4 + + @return javax.swing.JButton + **/ + private JButton getJButton4() { + if (jButton4 == null) { + jButton4 = new JButton(); + jButton4.setText("Add GUID Declarations"); + jButton4.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new PackageGuids(sfc), pThis); + } + }); + } + return jButton4; + } + + /** + This method initializes jButton5 + + @return javax.swing.JButton + **/ + private JButton getJButton5() { + if (jButton5 == null) { + jButton5 = new JButton(); + jButton5.setText("Add Package Headers"); + jButton5.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new PackagePkgHeader(sfc), pThis); + } + }); + } + return jButton5; + } + + /** + This method initializes jButton6 + + @return javax.swing.JButton + **/ + private JButton getJButton6() { + if (jButton6 == null) { + jButton6 = new JButton(); + jButton6.setText("Add MSA Files"); + jButton6.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new PackageMsaFile(sfc), pThis); + } + }); + } + return jButton6; + } + + /** + This method initializes jButton7 + + @return javax.swing.JButton + **/ + private JButton getJButton7() { + if (jButton7 == null) { + jButton7 = new JButton(); + jButton7.setText("Add Library Classes"); + jButton7.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new PackageLibraryClass(sfc), pThis); + } + }); + } + return jButton7; + } + + /** + This method initializes jButton8 + + @return javax.swing.JButton + **/ + private JButton getJButton8() { + if (jButton8 == null) { + jButton8 = new JButton(); + jButton8.setText("Add SPD Header"); + jButton8.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new PackageNew(sfc), pThis); + } + }); + } + return jButton8; + } + + /** + This method initializes jButton9 + + @return javax.swing.JButton + **/ + private JButton getJButton9() { + if (jButton9 == null) { + jButton9 = new JButton(); + jButton9.setText("Done"); + jButton9.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + // + // quit current frame + // + pThis.dispose(); + + } + }); + } + return jButton9; + } + +} // @jve:decl-index=0:visual-constraint="104,41" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageGuids.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageGuids.java new file mode 100644 index 0000000000..6562a2772f --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageGuids.java @@ -0,0 +1,354 @@ +/** @file + Java class PackageGuids is GUI for create GUID elements of spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.DefaultListModel; +import javax.swing.JPanel; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JRadioButton; +import javax.swing.JComboBox; +import javax.swing.JButton; +import javax.swing.JFrame; + +import javax.swing.JScrollPane; +import javax.swing.JList; + +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + GUI for create GUID elements of spd file + + @since PackageEditor 1.0 +**/ +public class PackageGuids extends JFrame implements ActionListener { + + private SpdFileContents sfc = null; + + private static String separator = "::"; + + private JPanel jContentPane = null; + + private JLabel jLabelC_Name = null; + + private JTextField jTextFieldC_Name = null; + + private JLabel jLabelGuidValue = null; + + private JTextField jTextFieldGuidValue = null; + + private JLabel jLabelHelpText = null; + + private JTextField jTextFieldName = null; + + private JLabel jLabelEnableFeature = null; + + private JRadioButton jRadioButtonEnableFeature = null; + + private JRadioButton jRadioButtonDisableFeature = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JButton jButtonGenerateGuid = null; + + private StarLabel starLabel = null; + + private StarLabel starLabel1 = null; + + /** + This method initializes this + + **/ + private void initialize() { + this.setTitle("Guid Declarations"); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + } + + /** + This method initializes jTextFieldC_Name + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldC_Name() { + if (jTextFieldC_Name == null) { + jTextFieldC_Name = new JTextField(); + jTextFieldC_Name.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldC_Name; + } + + /** + This method initializes jTextFieldGuidValsue + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldGuidValsue() { + if (jTextFieldGuidValue == null) { + jTextFieldGuidValue = new JTextField(); + jTextFieldGuidValue.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuidValue; + } + + /** + This method initializes jTextFieldName + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldName() { + if (jTextFieldName == null) { + jTextFieldName = new JTextField(); + jTextFieldName.setBounds(new java.awt.Rectangle(160, 70, 320, 20)); + } + return jTextFieldName; + } + + /** + This method initializes jRadioButtonEnableFeature + + @return javax.swing.JRadioButton + **/ + private JRadioButton getJRadioButtonEnableFeature() { + if (jRadioButtonEnableFeature == null) { + jRadioButtonEnableFeature = new JRadioButton(); + jRadioButtonEnableFeature.setText("Enable"); + jRadioButtonEnableFeature.setBounds(new java.awt.Rectangle(160, 104, 90, 20)); + jRadioButtonEnableFeature.setEnabled(false); + jRadioButtonEnableFeature.setSelected(true); + } + return jRadioButtonEnableFeature; + } + + /** + This method initializes jRadioButtonDisableFeature + + @return javax.swing.JRadioButton + **/ + private JRadioButton getJRadioButtonDisableFeature() { + if (jRadioButtonDisableFeature == null) { + jRadioButtonDisableFeature = new JRadioButton(); + jRadioButtonDisableFeature.setText("Disable"); + jRadioButtonDisableFeature.setEnabled(false); + jRadioButtonDisableFeature.setBounds(new java.awt.Rectangle(250, 104, 90, 20)); + } + return jRadioButtonDisableFeature; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(300, 240, 75, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 240, 74, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This is the default constructor + **/ + public PackageGuids(SpdFileContents sfc) { + super(); + initialize(); + init(); + this.setVisible(true); + this.sfc = sfc; + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + This method initializes this + + @return void + **/ + private void init() { + this.setSize(500, 300); + this.setContentPane(getJContentPane()); + this.setTitle("Add Guids"); + this.centerWindow(); + initFrame(); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + starLabel1 = new StarLabel(); + starLabel1.setBounds(new java.awt.Rectangle(5, 34, 10, 20)); + starLabel = new StarLabel(); + starLabel.setBounds(new java.awt.Rectangle(6, 10, 10, 20)); + jLabelEnableFeature = new JLabel(); + jLabelEnableFeature.setText("Enable Feature"); + jLabelEnableFeature.setEnabled(false); + jLabelEnableFeature.setBounds(new java.awt.Rectangle(15, 104, 140, 20)); + jLabelHelpText = new JLabel(); + jLabelHelpText.setText("Name"); + jLabelHelpText.setBounds(new java.awt.Rectangle(15, 70, 140, 20)); + jLabelGuidValue = new JLabel(); + jLabelGuidValue.setText("Guid Value"); + jLabelGuidValue.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelC_Name = new JLabel(); + jLabelC_Name.setText("C_Name"); + jLabelC_Name.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelC_Name, null); + jContentPane.add(getJTextFieldC_Name(), null); + jContentPane.add(jLabelGuidValue, null); + jContentPane.add(getJTextFieldGuidValsue(), null); + + jContentPane.add(jLabelHelpText, null); + jContentPane.add(getJTextFieldName(), null); + jContentPane.add(jLabelEnableFeature, null); + jContentPane.add(getJRadioButtonEnableFeature(), null); + jContentPane.add(getJRadioButtonDisableFeature(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + + jContentPane.add(starLabel, null); + jContentPane.add(starLabel1, null); + + initFrame(); + + } + return jContentPane; + } + + /** + This method initializes events groups and usage type + + **/ + private void initFrame() { + + } + + public void actionPerformed(ActionEvent arg0) { + // + // save and exit + // + if (arg0.getSource() == jButtonOk) { + + this.save(); + this.dispose(); + } + // + // exit + // + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + // + // generate a new GUID + // + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuidValue.setText(Tools.generateUuidString()); + } + + if (arg0.getSource() == jRadioButtonEnableFeature) { + if (jRadioButtonEnableFeature.isSelected()) { + jRadioButtonDisableFeature.setSelected(false); + } + if (!jRadioButtonDisableFeature.isSelected() && !jRadioButtonEnableFeature.isSelected()) { + jRadioButtonEnableFeature.setSelected(true); + } + } + + if (arg0.getSource() == jRadioButtonDisableFeature) { + if (jRadioButtonDisableFeature.isSelected()) { + jRadioButtonEnableFeature.setSelected(false); + } + if (!jRadioButtonDisableFeature.isSelected() && !jRadioButtonEnableFeature.isSelected()) { + jRadioButtonDisableFeature.setSelected(true); + } + } + } + + /** + Add GUID entry to SpdFileContents object with element values from jTextFields* + **/ + protected void save() { + try { + String strName = jTextFieldName.getText(); + String strCName = jTextFieldC_Name.getText(); + String strGuid = jTextFieldGuidValue.getText(); + sfc.genSpdGuidDeclarations(strName, strCName, strGuid, null); + + } catch (Exception e) { + System.out.println(e.toString()); + } + } +} // @jve:decl-index=0:visual-constraint="10,10" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageLibraryClass.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageLibraryClass.java new file mode 100644 index 0000000000..efd6a767b4 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageLibraryClass.java @@ -0,0 +1,545 @@ +/** @file + Java class PackageLibraryClass is GUI for create library definition elements of spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.Vector; + +import javax.swing.DefaultListModel; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JScrollPane; +import javax.swing.JButton; +import javax.swing.JFrame; + +/** + GUI for create library definition elements of spd file. + + @since PackageEditor 1.0 +**/ +public class PackageLibraryClass extends JFrame implements ActionListener { + static JFrame frame; + + private static String Separator = "::"; + + private DefaultListModel listItem = new DefaultListModel(); + + private SpdFileContents sfc = null; + + private JPanel jContentPane = null; + + private JRadioButton jRadioButtonAdd = null; + + private JRadioButton jRadioButtonSelect = null; + + private JTextField jTextFieldAdd = null; + + private JComboBox jComboBoxSelect = null; + + private JLabel jLabelUsage = null; + + private JComboBox jComboBoxUsage = null; + + private JScrollPane jScrollPane = null; + + private JList jListLibraryClassDefinitions = null; + + private JButton jButtonAdd = null; + + private JButton jButtonRemove = null; + + private JButton jButtonClearAll = null; + + private JButton jButtonCancel = null; + + private JButton jButtonOk = null; + + private JLabel jLabel = null; + + private JTextField jTextField = null; + + private JButton jButtonBrowse = null; + + /** + This method initializes this + + **/ + private void initialize() { + this.setTitle("Library Declarations"); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + } + + /** + This method initializes jRadioButtonAdd + + @return javax.swing.JRadioButton + **/ + private JRadioButton getJRadioButtonAdd() { + if (jRadioButtonAdd == null) { + jRadioButtonAdd = new JRadioButton(); + jRadioButtonAdd.setBounds(new java.awt.Rectangle(10, 35, 205, 20)); + jRadioButtonAdd.setText("Add a new Library Class"); + jRadioButtonAdd.addActionListener(this); + jRadioButtonAdd.setSelected(false); + } + return jRadioButtonAdd; + } + + /** + This method initializes jRadioButtonSelect + + @return javax.swing.JRadioButton + **/ + private JRadioButton getJRadioButtonSelect() { + if (jRadioButtonSelect == null) { + jRadioButtonSelect = new JRadioButton(); + jRadioButtonSelect.setBounds(new java.awt.Rectangle(10, 10, 205, 20)); + jRadioButtonSelect.setText("Select Existing Library Class"); + jRadioButtonSelect.addActionListener(this); + jRadioButtonSelect.setSelected(true); + } + return jRadioButtonSelect; + } + + /** + This method initializes jTextFieldAdd + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldAdd() { + if (jTextFieldAdd == null) { + jTextFieldAdd = new JTextField(); + jTextFieldAdd.setBounds(new java.awt.Rectangle(220, 35, 260, 20)); + jTextFieldAdd.setEnabled(false); + } + return jTextFieldAdd; + } + + /** + This method initializes jComboBoxSelect + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBoxSelect() { + if (jComboBoxSelect == null) { + jComboBoxSelect = new JComboBox(); + jComboBoxSelect.setBounds(new java.awt.Rectangle(220, 10, 260, 20)); + jComboBoxSelect.setEnabled(true); + } + return jComboBoxSelect; + } + + /** + This method initializes jComboBoxUsage + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBoxUsage() { + if (jComboBoxUsage == null) { + jComboBoxUsage = new JComboBox(); + jComboBoxUsage.setBounds(new java.awt.Rectangle(220, 60, 260, 20)); + jComboBoxUsage.setEnabled(false); + } + return jComboBoxUsage; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(10,149,350,146)); + jScrollPane.setViewportView(getJListLibraryClassDefinitions()); + } + return jScrollPane; + } + + /** + This method initializes jListLibraryClassDefinitions + + @return javax.swing.JList + **/ + private JList getJListLibraryClassDefinitions() { + if (jListLibraryClassDefinitions == null) { + jListLibraryClassDefinitions = new JList(listItem); + } + return jListLibraryClassDefinitions; + } + + /** + This method initializes jButtonAdd + + @return javax.swing.JButton + **/ + private JButton getJButtonAdd() { + if (jButtonAdd == null) { + jButtonAdd = new JButton(); + jButtonAdd.setBounds(new java.awt.Rectangle(375,152,90,20)); + jButtonAdd.setText("Add"); + jButtonAdd.addActionListener(this); + } + return jButtonAdd; + } + + /** + This method initializes jButtonRemove + + @return javax.swing.JButton + **/ + private JButton getJButtonRemove() { + if (jButtonRemove == null) { + jButtonRemove = new JButton(); + jButtonRemove.setBounds(new java.awt.Rectangle(375, 230, 90, 20)); + jButtonRemove.setText("Remove"); + jButtonRemove.addActionListener(this); + } + return jButtonRemove; + } + + /** + This method initializes jButtonRemoveAll + + @return javax.swing.JButton + **/ + private JButton getJButtonClearAll() { + if (jButtonClearAll == null) { + jButtonClearAll = new JButton(); + jButtonClearAll.setBounds(new java.awt.Rectangle(375, 260, 90, 20)); + jButtonClearAll.setText("Clear All"); + jButtonClearAll.addActionListener(this); + } + return jButtonClearAll; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setPreferredSize(new java.awt.Dimension(90, 20)); + jButtonCancel.setLocation(new java.awt.Point(390, 305)); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setSize(new java.awt.Dimension(90, 20)); + jButtonOk.setText("OK"); + jButtonOk.setLocation(new java.awt.Point(290, 305)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This is the default constructor + **/ + public PackageLibraryClass(SpdFileContents sfc) { + super(); + initialize(); + init(); + this.sfc = sfc; + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + This method initializes this + + @return void + **/ + private void init() { + this.setContentPane(getJContentPane()); + this.setTitle("Library Class Declarations"); + this.setBounds(new java.awt.Rectangle(0, 0, 500, 370)); + this.centerWindow(); + initFrame(); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabel = new JLabel(); + jLabel.setBounds(new java.awt.Rectangle(14, 85, 201, 22)); + jLabel.setText("Include Header for Selected Class"); + jLabelUsage = new JLabel(); + jLabelUsage.setBounds(new java.awt.Rectangle(15, 60, 200, 20)); + jLabelUsage.setEnabled(false); + jLabelUsage.setText("Usage"); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJRadioButtonAdd(), null); + jContentPane.add(getJRadioButtonSelect(), null); + jContentPane.add(getJTextFieldAdd(), null); + jContentPane.add(getJComboBoxSelect(), null); + jContentPane.add(jLabelUsage, null); + jContentPane.add(getJComboBoxUsage(), null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButtonAdd(), null); + jContentPane.add(getJButtonRemove(), null); + jContentPane.add(getJButtonClearAll(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(jLabel, null); + jContentPane.add(getJTextField(), null); + jContentPane.add(getJButtonBrowse(), null); + } + return jContentPane; + } + + /** + fill ComboBoxes with pre-defined contents + **/ + private void initFrame() { + jComboBoxSelect.addItem("BaseCpuICacheFlush"); + jComboBoxSelect.addItem("BaseDebugLibNull"); + jComboBoxSelect.addItem("BaseDebugLibReportStatusCode"); + jComboBoxSelect.addItem("BaseIoLibIntrinsic"); + jComboBoxSelect.addItem("BaseLib"); + jComboBoxSelect.addItem("BaseMemoryLib"); + jComboBoxSelect.addItem("BaseMemoryLibMmx"); + jComboBoxSelect.addItem("BaseMemoryLibSse2"); + jComboBoxSelect.addItem("BasePeCoffGetEntryPointLib"); + jComboBoxSelect.addItem("BasePeCoffLib"); + jComboBoxSelect.addItem("BasePrintLib"); + jComboBoxSelect.addItem("BaseReportStatusCodeLibNull"); + jComboBoxSelect.addItem("CommonPciCf8Lib"); + jComboBoxSelect.addItem("CommonPciExpressLib"); + jComboBoxSelect.addItem("CommonPciLibCf8"); + jComboBoxSelect.addItem("CommonPciLibPciExpress"); + jComboBoxSelect.addItem("DxeCoreEntryPoint"); + jComboBoxSelect.addItem("DxeHobLib"); + jComboBoxSelect.addItem("DxeIoLibCpuIo"); + jComboBoxSelect.addItem("DxeLib"); + jComboBoxSelect.addItem("DxePcdLib"); + jComboBoxSelect.addItem("DxeReportStatusCodeLib"); + jComboBoxSelect.addItem("DxeServicesTableLib"); + jComboBoxSelect.addItem("PeiCoreEntryPoint"); + jComboBoxSelect.addItem("PeiMemoryLib"); + jComboBoxSelect.addItem("PeimEntryPoint"); + jComboBoxSelect.addItem("PeiReportStatusCodeLib"); + jComboBoxSelect.addItem("PeiServicesTablePointerLib"); + jComboBoxSelect.addItem("PeiServicesTablePointerLibMm7"); + jComboBoxSelect.addItem("UefiDebugLibConOut"); + jComboBoxSelect.addItem("UefiDebugLibStdErr"); + jComboBoxSelect.addItem("UefiDriverEntryPointMultiple"); + jComboBoxSelect.addItem("UefiDriverEntryPointSingle"); + jComboBoxSelect.addItem("UefiDriverEntryPointSingleUnload"); + jComboBoxSelect.addItem("UefiDriverModelLib"); + jComboBoxSelect.addItem("UefiDriverModelLibNoConfigNoDiag"); + jComboBoxSelect.addItem("UefiLib"); + jComboBoxSelect.addItem("UefiMemoryLib"); + + jComboBoxUsage.addItem("ALWAYS_CONSUMED"); + jComboBoxUsage.addItem("SOMETIMES_CONSUMED"); + jComboBoxUsage.addItem("ALWAYS_PRODUCED"); + jComboBoxUsage.addItem("SOMETIMES_PRODUCED"); + jComboBoxUsage.addItem("DEFAULT"); + jComboBoxUsage.addItem("PRIVATE"); + } + + /* (non-Javadoc) + * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) + */ + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jButtonAdd) { + String strLibClass = ""; + if (jRadioButtonAdd.isSelected()) { + strLibClass = jTextFieldAdd.getText(); + } + if (jRadioButtonSelect.isSelected()) { + strLibClass = jComboBoxSelect.getSelectedItem().toString(); + } + listItem.addElement(jTextField.getText() + this.Separator + strLibClass); + } + // + // remove selected line + // + if (arg0.getSource() == jButtonRemove) { + int intSelected[] = jListLibraryClassDefinitions.getSelectedIndices(); + if (intSelected.length > 0) { + for (int index = intSelected.length - 1; index > -1; index--) { + listItem.removeElementAt(intSelected[index]); + } + } + jListLibraryClassDefinitions.getSelectionModel().clearSelection(); + } + + if (arg0.getSource() == jButtonClearAll) { + listItem.removeAllElements(); + } + + if (arg0.getSource() == jRadioButtonAdd) { + if (jRadioButtonAdd.isSelected()) { + jRadioButtonSelect.setSelected(false); + jTextFieldAdd.setEnabled(true); + jComboBoxSelect.setEnabled(false); + } + if (!jRadioButtonSelect.isSelected() && !jRadioButtonAdd.isSelected()) { + jRadioButtonAdd.setSelected(true); + jTextFieldAdd.setEnabled(true); + jComboBoxSelect.setEnabled(false); + } + } + + if (arg0.getSource() == jRadioButtonSelect) { + if (jRadioButtonSelect.isSelected()) { + jRadioButtonAdd.setSelected(false); + jTextFieldAdd.setEnabled(false); + jComboBoxSelect.setEnabled(true); + } + if (!jRadioButtonSelect.isSelected() && !jRadioButtonAdd.isSelected()) { + jRadioButtonSelect.setSelected(true); + jTextFieldAdd.setEnabled(false); + jComboBoxSelect.setEnabled(true); + } + } + } + + /** + Add contents in list to sfc + **/ + protected void save() { + try { + int intLibraryCount = listItem.getSize(); + + if (intLibraryCount > 0) { + + for (int index = 0; index < intLibraryCount; index++) { + String strAll = listItem.get(index).toString(); + String strInclude = strAll.substring(0, strAll.indexOf(Separator)); + String strLibraryClass = strAll.substring(strAll.indexOf(Separator) + Separator.length()); + sfc.genSpdLibClassDeclarations(strLibraryClass, null, strInclude, null, null, null, null, null, + null, null); + } + } else { + + } + + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + /** + This method initializes jTextField + + @return javax.swing.JTextField + **/ + private JTextField getJTextField() { + if (jTextField == null) { + jTextField = new JTextField(); + jTextField.setBounds(new java.awt.Rectangle(12,112,346,21)); + } + return jTextField; + } + + /** + This method initializes jButtonBrowse + + @return javax.swing.JButton + **/ + private JButton getJButtonBrowse() { + if (jButtonBrowse == null) { + jButtonBrowse = new JButton(); + jButtonBrowse.setBounds(new java.awt.Rectangle(374,111,92,21)); + jButtonBrowse.setText("Browse"); + jButtonBrowse.setPreferredSize(new java.awt.Dimension(34,20)); + jButtonBrowse.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + // + // Select files from current workspace + // + JFileChooser chooser = new JFileChooser(System.getenv("WORKSPACE")); + + chooser.setMultiSelectionEnabled(false); + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + int retval = chooser.showOpenDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + + File theFile = chooser.getSelectedFile(); + String file = theFile.getPath(); + if (!file.startsWith(System.getenv("WORKSPACE"))) { + JOptionPane.showMessageDialog(frame, "You can only select files in current workspace!"); + return; + } + // + // record relative path of selected file. Assume top level package directory lies directly in workspace + // + int fileIndex = file.indexOf(System.getProperty("file.separator"), System.getenv("WORKSPACE").length() + 1); + jTextField.setText(file.substring(fileIndex + 1)); + + } + } + }); + } + return jButtonBrowse; + } + +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageMsaFile.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageMsaFile.java new file mode 100644 index 0000000000..b57a1b23d4 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageMsaFile.java @@ -0,0 +1,352 @@ +/** @file + Java class PackageMsaFile is GUI for create MsaFile elements of spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.File; +import java.util.Vector; + +import javax.swing.DefaultListModel; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JScrollPane; +import javax.swing.JButton; +import javax.swing.JFrame; + +/** + GUI for create MsaFile elements of spd file + + @since PackageEditor 1.0 +**/ +public class PackageMsaFile extends JFrame implements ActionListener { + static JFrame frame; + + private DefaultListModel listItem = new DefaultListModel(); + + private SpdFileContents sfc = null; + + private JPanel jContentPane = null; + + private JScrollPane jScrollPane = null; + + private JList jListLibraryClassDefinitions = null; + + private JButton jButtonAdd = null; + + private JButton jButtonRemove = null; + + private JButton jButtonClearAll = null; + + private JButton jButtonCancel = null; + + private JButton jButtonOk = null; + + private JLabel jLabel = null; + + private JTextField jTextField = null; + + private JButton jButton = null; + + /** + This method initializes this + + **/ + private void initialize() { + this.setTitle("MSA Files"); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(10, 85, 350, 210)); + jScrollPane.setViewportView(getJListLibraryClassDefinitions()); + } + return jScrollPane; + } + + /** + This method initializes jListLibraryClassDefinitions + + @return javax.swing.JList + **/ + private JList getJListLibraryClassDefinitions() { + if (jListLibraryClassDefinitions == null) { + jListLibraryClassDefinitions = new JList(listItem); + } + return jListLibraryClassDefinitions; + } + + /** + This method initializes jButtonAdd + + @return javax.swing.JButton + **/ + private JButton getJButtonAdd() { + if (jButtonAdd == null) { + jButtonAdd = new JButton(); + jButtonAdd.setBounds(new java.awt.Rectangle(375, 132, 90, 20)); + jButtonAdd.setText("Add"); + jButtonAdd.addActionListener(this); + } + return jButtonAdd; + } + + /** + This method initializes jButtonRemove + + @return javax.swing.JButton + **/ + private JButton getJButtonRemove() { + if (jButtonRemove == null) { + jButtonRemove = new JButton(); + jButtonRemove.setBounds(new java.awt.Rectangle(375, 230, 90, 20)); + jButtonRemove.setText("Remove"); + jButtonRemove.addActionListener(this); + } + return jButtonRemove; + } + + /** + This method initializes jButtonRemoveAll + + @return javax.swing.JButton + **/ + private JButton getJButtonClearAll() { + if (jButtonClearAll == null) { + jButtonClearAll = new JButton(); + jButtonClearAll.setBounds(new java.awt.Rectangle(375, 260, 90, 20)); + jButtonClearAll.setText("Clear All"); + jButtonClearAll.addActionListener(this); + } + return jButtonClearAll; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setPreferredSize(new java.awt.Dimension(90, 20)); + jButtonCancel.setLocation(new java.awt.Point(390, 305)); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setSize(new java.awt.Dimension(90, 20)); + jButtonOk.setText("OK"); + jButtonOk.setLocation(new java.awt.Point(290, 305)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This is the default constructor + **/ + public PackageMsaFile(SpdFileContents sfc) { + super(); + initialize(); + init(); + this.sfc = sfc; + } + + /** + Start the window at the center of screen + + */ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + This method initializes this + + @return void + **/ + private void init() { + this.setContentPane(getJContentPane()); + this.setTitle("Library Class Declarations"); + this.setBounds(new java.awt.Rectangle(0, 0, 500, 370)); + this.centerWindow(); + initFrame(); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabel = new JLabel(); + jLabel.setBounds(new java.awt.Rectangle(11,20,143,22)); + jLabel.setText("Msa File Path and Name"); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButtonAdd(), null); + jContentPane.add(getJButtonRemove(), null); + jContentPane.add(getJButtonClearAll(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(jLabel, null); + jContentPane.add(getJTextField(), null); + jContentPane.add(getJButton(), null); + } + return jContentPane; + } + + private void initFrame() { + + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.dispose(); + this.save(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jButtonAdd) { + + listItem.addElement(jTextField.getText()); + } + + if (arg0.getSource() == jButtonRemove) { + int intSelected[] = jListLibraryClassDefinitions.getSelectedIndices(); + if (intSelected.length > 0) { + for (int index = intSelected.length - 1; index > -1; index--) { + listItem.removeElementAt(intSelected[index]); + } + } + jListLibraryClassDefinitions.getSelectionModel().clearSelection(); + } + + if (arg0.getSource() == jButtonClearAll) { + listItem.removeAllElements(); + } + + } + + protected void save() { + try { + int intLibraryCount = listItem.getSize(); + + if (intLibraryCount > 0) { + + for (int index = 0; index < intLibraryCount; index++) { + String strAll = listItem.get(index).toString(); + sfc.genSpdMsaFiles(strAll, null); + } + } else { + + } + + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + /** + This method initializes jTextField + + @return javax.swing.JTextField + **/ + private JTextField getJTextField() { + if (jTextField == null) { + jTextField = new JTextField(); + jTextField.setBounds(new java.awt.Rectangle(11,44,349,21)); + } + return jTextField; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setBounds(new java.awt.Rectangle(377,46,89,20)); + jButton.setText("Browse"); + jButton.setPreferredSize(new java.awt.Dimension(34,20)); + jButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + JFileChooser chooser = new JFileChooser(System.getenv("WORKSPACE")); + + chooser.setMultiSelectionEnabled(false); + chooser.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); + chooser.setFileFilter(new PkgFileFilter("msa")); + int retval = chooser.showOpenDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + + File theFile = chooser.getSelectedFile(); + String file = theFile.getPath(); + if (!file.startsWith(System.getenv("WORKSPACE"))) { + JOptionPane.showMessageDialog(frame, "You can only select files in current workspace!"); + return; + } + int fileIndex = file.indexOf(System.getProperty("file.separator"), System.getenv("WORKSPACE").length() + 1); + jTextField.setText(file.substring(fileIndex + 1)); + + } + } + }); + } + return jButton; + } + +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageNew.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageNew.java new file mode 100644 index 0000000000..85676a4b84 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageNew.java @@ -0,0 +1,533 @@ +/** @file + Java class PackageNew is the top level GUI for create spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; +import javax.swing.JTextArea; +import javax.swing.JScrollPane; +import javax.swing.JComboBox; + +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + This class contains GUI components to show various GUIs for creating spd file elements + + @since PackageEditor 1.0 +**/ +public class PackageNew extends JFrame implements ActionListener { + + private JPanel jContentPane = null; // @jve:decl-index=0:visual-constraint="128,4" + + private JLabel jLabelBaseName = null; + + private JTextField jTextFieldBaseName = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelVersion = null; + + private JTextField jTextFieldVersion = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelLicense = null; + + private JTextArea jTextAreaLicense = null; + + private JLabel jLabelCopyright = null; + + private JTextArea jTextAreaCopyright = null; + + private JLabel jLabelDescription = null; + + private JTextArea jTextAreaDescription = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JScrollPane jScrollPaneLicense = null; + + private JScrollPane jScrollPaneDescription = null; + + private JLabel jLabelAbstract = null; + + private JTextField jTextFieldAbstract = null; + + private JLabel jLabelModuleType = null; + + private JLabel jLabelCompontentType = null; + + private JComboBox jComboBox1 = null; + + private JComboBox jComboBoxModuleType = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + private StarLabel jStarLabel3 = null; + + private StarLabel jStarLabel4 = null; + + private StarLabel jStarLabel5 = null; + + private StarLabel jStarLabel6 = null; + + private StarLabel jStarLabel7 = null; + + private StarLabel jStarLabel8 = null; + + private JLabel jLabelURL = null; + + private JTextField jTextFieldAbstractURL = null; + + private JLabel jLabel = null; + + private JComboBox jComboBox = null; + + private SpdFileContents sfc = null; + + /** + This method initializes this + + **/ + private void initialize() { + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + } + + /** + This method initializes jTextFieldBaseName + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldBaseName() { + if (jTextFieldBaseName == null) { + jTextFieldBaseName = new JTextField(); + jTextFieldBaseName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldBaseName; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldVersion + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldVersion() { + if (jTextFieldVersion == null) { + jTextFieldVersion = new JTextField(); + jTextFieldVersion.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jTextFieldVersion; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextAreaLicense + + @return javax.swing.JTextArea + **/ + private JTextArea getJTextAreaLicense() { + if (jTextAreaLicense == null) { + jTextAreaLicense = new JTextArea(); + jTextAreaLicense.setText(""); + jTextAreaLicense.setLineWrap(true); + } + return jTextAreaLicense; + } + + /** + This method initializes jTextAreaCopyright + + @return javax.swing.JTextArea + **/ + private JTextArea getJTextAreaCopyright() { + if (jTextAreaCopyright == null) { + jTextAreaCopyright = new JTextArea(); + jTextAreaCopyright.setLineWrap(true); + jTextAreaCopyright.setBounds(new java.awt.Rectangle(160,172,319,20)); + } + return jTextAreaCopyright; + } + + /** + This method initializes jTextAreaDescription + + @return javax.swing.JTextArea + **/ + private JTextArea getJTextAreaDescription() { + if (jTextAreaDescription == null) { + jTextAreaDescription = new JTextArea(); + jTextAreaDescription.setLineWrap(true); + } + return jTextAreaDescription; + } + + /** + This method initializes jButtonNext + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 481, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 481, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPaneLicense() { + if (jScrollPaneLicense == null) { + jScrollPaneLicense = new JScrollPane(); + jScrollPaneLicense.setBounds(new java.awt.Rectangle(160, 85, 320, 80)); + jScrollPaneLicense.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneLicense.setViewportView(getJTextAreaLicense()); + } + return jScrollPaneLicense; + } + + /** + This method initializes jScrollPane2 + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPaneDescription() { + if (jScrollPaneDescription == null) { + jScrollPaneDescription = new JScrollPane(); + jScrollPaneDescription.setBounds(new java.awt.Rectangle(160, 322, 320, 80)); + jScrollPaneDescription.setViewportView(getJTextAreaDescription()); + jScrollPaneDescription.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + } + return jScrollPaneDescription; + } + + /** + This method initializes jTextFieldAbstract + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldAbstract() { + if (jTextFieldAbstract == null) { + jTextFieldAbstract = new JTextField(); + jTextFieldAbstract.setBounds(new java.awt.Rectangle(159,218,318,70)); + } + return jTextFieldAbstract; + } + + /** + This method initializes jComboBoxCompontentType + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBox1() { + if (jComboBox1 == null) { + jComboBox1 = new JComboBox(); + jComboBox1.setBounds(new java.awt.Rectangle(160, 465, 91, 20)); + } + return jComboBox1; + } + + /** + This method initializes jComboBoxModuleType + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBoxModuleType() { + if (jComboBoxModuleType == null) { + jComboBoxModuleType = new JComboBox(); + jComboBoxModuleType.setBounds(new java.awt.Rectangle(160, 440, 91, 20)); + } + return jComboBoxModuleType; + } + + /** + This method initializes jTextFieldAbstractURL + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldAbstractURL() { + if (jTextFieldAbstractURL == null) { + jTextFieldAbstractURL = new JTextField(); + jTextFieldAbstractURL.setBounds(new java.awt.Rectangle(159, 414, 320, 20)); + } + return jTextFieldAbstractURL; + } + + public PackageNew(SpdFileContents sfc) { + super(); + initialize(); + init(); + this.setVisible(true); + this.sfc = sfc; + + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + This method initializes this + + @return void + **/ + private void init() { + this.setSize(500, 560); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setContentPane(getJContentPane()); + this.setTitle("SPD File Header"); + this.centerWindow(); + //this.getRootPane().setDefaultButton(jButtonOk); + initFrame(); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabel = new JLabel(); + jLabel.setBounds(new java.awt.Rectangle(15, 490, 140, 21)); + jLabel.setText("Re-Package"); + jLabelURL = new JLabel(); + jLabelURL.setBounds(new java.awt.Rectangle(16, 414, 25, 20)); + jLabelURL.setText("URL"); + jLabelCompontentType = new JLabel(); + jLabelCompontentType.setBounds(new java.awt.Rectangle(15, 465, 140, 20)); + jLabelCompontentType.setText("Read Only"); + jLabelModuleType = new JLabel(); + jLabelModuleType.setBounds(new java.awt.Rectangle(15, 440, 140, 20)); + jLabelModuleType.setText("Package Type"); + jLabelAbstract = new JLabel(); + jLabelAbstract.setBounds(new java.awt.Rectangle(15,218,140,20)); + jLabelAbstract.setText("Abstract"); + jLabelDescription = new JLabel(); + jLabelDescription.setText("Description"); + jLabelDescription.setBounds(new java.awt.Rectangle(16, 325, 140, 20)); + jLabelCopyright = new JLabel(); + jLabelCopyright.setText("Copyright"); + jLabelCopyright.setBounds(new java.awt.Rectangle(15, 171, 140, 20)); + jLabelLicense = new JLabel(); + jLabelLicense.setText("License"); + jLabelLicense.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelVersion = new JLabel(); + jLabelVersion.setText("Version"); + jLabelVersion.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setPreferredSize(new java.awt.Dimension(25, 15)); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelGuid.setText("Guid"); + jLabelBaseName = new JLabel(); + jLabelBaseName.setText("Package Name"); + jLabelBaseName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setLocation(new java.awt.Point(0, 0)); + jContentPane.setSize(new java.awt.Dimension(500, 524)); + jContentPane.add(jLabelBaseName, null); + jContentPane.add(getJTextFieldBaseName(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelVersion, null); + jContentPane.add(getJTextFieldVersion(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelLicense, null); + jContentPane.add(jLabelCopyright, null); + jContentPane.add(jLabelDescription, null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJScrollPaneLicense(), null); + jContentPane.add(getJScrollPaneDescription(), null); + jContentPane.add(jLabelAbstract, null); + jContentPane.add(getJTextFieldAbstract(), null); + jContentPane.add(jLabelModuleType, null); + jContentPane.add(jLabelCompontentType, null); + jContentPane.add(getJComboBox1(), null); + jContentPane.add(getJComboBoxModuleType(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setLocation(new java.awt.Point(0, 35)); + jStarLabel3 = new StarLabel(); + jStarLabel3.setLocation(new java.awt.Point(0, 60)); + jStarLabel4 = new StarLabel(); + jStarLabel4.setLocation(new java.awt.Point(0, 85)); + jStarLabel5 = new StarLabel(); + jStarLabel5.setLocation(new java.awt.Point(0, 171)); + jStarLabel6 = new StarLabel(); + jStarLabel6.setLocation(new java.awt.Point(1, 325)); + jStarLabel7 = new StarLabel(); + jStarLabel7.setLocation(new java.awt.Point(0,218)); + jStarLabel8 = new StarLabel(); + jStarLabel8.setLocation(new java.awt.Point(0, 440)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + jContentPane.add(jStarLabel3, null); + jContentPane.add(jStarLabel4, null); + jContentPane.add(jStarLabel5, null); + jContentPane.add(jStarLabel6, null); + jContentPane.add(jStarLabel7, null); + jContentPane.add(jStarLabel8, null); + jContentPane.add(jLabelURL, null); + jContentPane.add(getJTextFieldAbstractURL(), null); + jContentPane.add(jLabel, null); + jContentPane.add(getJComboBox(), null); + jContentPane.add(getJTextAreaCopyright(), null); + } + return jContentPane; + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + } + + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Save all components of Msa Header + if exist, set the value directly + if not exist, new instance first + + **/ + private void save() { + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + Date date = new Date(); + sfc.genSpdHeader(jTextFieldBaseName.getText(), jTextFieldGuid.getText(), jTextFieldVersion.getText(), + jTextFieldAbstract.getText(), jTextAreaDescription.getText(), jTextAreaCopyright.getText(), + jTextAreaLicense.getText(), format.format(date), format.format(date), + jTextFieldAbstractURL.getText(), jComboBoxModuleType.getSelectedItem().toString(), + jComboBox1.getSelectedItem().toString(), jComboBox.getSelectedItem().toString(), null, null); + } + + /** + This method initializes module type and compontent type + + **/ + private void initFrame() { + jComboBoxModuleType.addItem("SOURCE"); + jComboBoxModuleType.addItem("BINARY"); + jComboBoxModuleType.addItem("MIXED"); + + jComboBox1.addItem("true"); + jComboBox1.addItem("false"); + + jComboBox.addItem("false"); + jComboBox.addItem("true"); + + } + + /** + This method initializes jComboBox + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBox() { + if (jComboBox == null) { + jComboBox = new JComboBox(); + jComboBox.setBounds(new java.awt.Rectangle(160, 490, 90, 20)); + } + return jComboBox; + } + +} // @jve:decl-index=0:visual-constraint="38,-22" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagePCD.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagePCD.java new file mode 100644 index 0000000000..910540c4eb --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagePCD.java @@ -0,0 +1,321 @@ +/** @file + Java class PackagePCD is GUI for create PCD definition elements of spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.ButtonGroup; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JComboBox; +import javax.swing.JButton; +import javax.swing.JFrame; + +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + GUI for create PCD definition elements of spd file + + @since PackageEditor 1.0 +**/ +public class PackagePCD extends JFrame implements ActionListener { + + private JPanel jContentPane = null; + + private JLabel jLabelItemType = null; + + private JLabel jLabelC_Name = null; + + private JComboBox jComboBoxItemType = null; + + private JTextField jTextFieldC_Name = null; + + private JLabel jLabelToken = null; + + private JTextField jTextFieldToken = null; + + private JLabel jLabelDataType = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JComboBox jComboBoxDataType = null; + + private JLabel jLabelOverrideID = null; + + private JTextField jTextFieldOverrideID = null; + + private ButtonGroup bg1 = null; + + private ButtonGroup bg2 = null; + + private ButtonGroup bg3 = null; + + private StarLabel jStarLabel2 = null; + + private StarLabel jStarLabel3 = null; + + private SpdFileContents sfc = null; + + private StarLabel jStarLabel = null; + + private StarLabel jStarLabel1 = null; + + /** + This method initializes this + + **/ + private void initialize() { + this.setTitle("PCD Definition"); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + } + + /** + This method initializes jComboBoxItemType + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBoxItemType() { + if (jComboBoxItemType == null) { + jComboBoxItemType = new JComboBox(); + jComboBoxItemType.setBounds(new java.awt.Rectangle(160, 110, 320, 20)); + } + return jComboBoxItemType; + } + + /** + This method initializes jTextFieldC_Name + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldC_Name() { + if (jTextFieldC_Name == null) { + jTextFieldC_Name = new JTextField(); + jTextFieldC_Name.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jTextFieldC_Name; + } + + /** + This method initializes jTextFieldToken + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldToken() { + if (jTextFieldToken == null) { + jTextFieldToken = new JTextField(); + jTextFieldToken.setBounds(new java.awt.Rectangle(160, 135, 320, 20)); + } + return jTextFieldToken; + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(279,247,90,20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(389,247,90,20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jComboBoxDataType + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBoxDataType() { + if (jComboBoxDataType == null) { + jComboBoxDataType = new JComboBox(); + jComboBoxDataType.setBounds(new java.awt.Rectangle(160, 160, 320, 20)); + } + return jComboBoxDataType; + } + + /** + This method initializes jTextFieldOverrideID + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldOverrideID() { + if (jTextFieldOverrideID == null) { + jTextFieldOverrideID = new JTextField(); + jTextFieldOverrideID.setBounds(new java.awt.Rectangle(159,198,320,20)); + } + return jTextFieldOverrideID; + } + + /** + This is the default constructor + **/ + public PackagePCD(SpdFileContents sfc) { + super(); + init(); + initialize(); + this.sfc = sfc; + } + + /** + This method initializes this + + @return void + **/ + private void init() { + this.setSize(500, 450); + this.setContentPane(getJContentPane()); + this.setTitle("Add PCDs"); + this.centerWindow(); + this.getRootPane().setDefaultButton(jButtonOk); + initFrame(); + this.setVisible(true); + } + + /** + Start the window at the center of screen + * + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + * + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabelOverrideID = new JLabel(); + jLabelOverrideID.setBounds(new java.awt.Rectangle(14,197,140,20)); + jLabelOverrideID.setText("Default Value"); + jLabelC_Name = new JLabel(); + jLabelC_Name.setText("C_Name"); + jLabelC_Name.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelDataType = new JLabel(); + jLabelDataType.setText("Data Type"); + jLabelDataType.setBounds(new java.awt.Rectangle(15, 160, 140, 20)); + jLabelToken = new JLabel(); + jLabelToken.setText("Token"); + jLabelToken.setBounds(new java.awt.Rectangle(15, 135, 140, 20)); + jLabelItemType = new JLabel(); + jLabelItemType.setText("Item Type"); + jLabelItemType.setBounds(new java.awt.Rectangle(15, 110, 140, 20)); + bg1 = new ButtonGroup(); + bg2 = new ButtonGroup(); + bg3 = new ButtonGroup(); + //bg1.add(getJRadioButtonPCData()); + //bg2.add(getJRadioButtonPcdBuildData()); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + //jContentPane.add(bg1); + jContentPane.add(jLabelItemType, null); + jContentPane.add(jLabelC_Name, null); + jContentPane.add(getJTextFieldC_Name(), null); + jContentPane.add(jLabelToken, null); + jContentPane.add(getJTextFieldToken(), null); + jContentPane.add(jLabelDataType, null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJComboBoxItemType(), null); + jContentPane.add(getJComboBoxDataType(), null); + jContentPane.add(jLabelOverrideID, null); + jContentPane.add(getJTextFieldOverrideID(), null); + + jStarLabel = new StarLabel(); + jStarLabel1 = new StarLabel(); + jStarLabel1.setBounds(new java.awt.Rectangle(6, 59, 10, 20)); + jStarLabel2 = new StarLabel(); + jStarLabel3 = new StarLabel(); + jStarLabel.setLocation(new java.awt.Point(6, 110)); + jStarLabel.setLocation(new java.awt.Point(5, 85)); + jStarLabel2.setLocation(new java.awt.Point(5, 134)); + jStarLabel3.setLocation(new java.awt.Point(5, 159)); + jContentPane.add(jStarLabel2, null); + jContentPane.add(jStarLabel3, null); + jContentPane.add(jStarLabel, null); + jContentPane.add(jStarLabel1, null); + } + return jContentPane; + } + + /** + This method initializes comboboxes + + **/ + private void initFrame() { + + jComboBoxItemType.addItem("FEATURE_FLAG"); + jComboBoxItemType.addItem("FIXED_AT_BUILD"); + jComboBoxItemType.addItem("PATCHABLE_IN_MODULE"); + jComboBoxItemType.addItem("DYNAMIC"); + jComboBoxItemType.addItem("DYNAMIC_EX"); + + jComboBoxDataType.addItem("UINT8"); + jComboBoxDataType.addItem("UINT16"); + jComboBoxDataType.addItem("UINT32"); + jComboBoxDataType.addItem("UINT64"); + jComboBoxDataType.addItem("VOID*"); + jComboBoxDataType.addItem("BOOLEAN"); + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + + } + + protected void save() { + + sfc.genSpdPcdDefinitions(jComboBoxItemType.getSelectedItem().toString(), jTextFieldC_Name.getText(), + jTextFieldToken.getText(), jComboBoxDataType.getSelectedItem().toString(), null, + null, null, null, null, null, jTextFieldOverrideID.getText()); + } +} // @jve:decl-index=0:visual-constraint="22,11" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagePkgHeader.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagePkgHeader.java new file mode 100644 index 0000000000..982dbe224f --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagePkgHeader.java @@ -0,0 +1,454 @@ +/** @file + Java class PackagePkgHeader is GUI for create Package header elements of spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Vector; + +import javax.swing.DefaultListModel; +import javax.swing.JPanel; +import javax.swing.JRadioButton; +import javax.swing.JTextField; +import javax.swing.JComboBox; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JScrollPane; +import javax.swing.JButton; +import javax.swing.JFrame; + +import org.tianocore.packaging.common.ui.StarLabel; + +/** + GUI for create Package header elements of spd file + + @since PackageEditor 1.0 +**/ +public class PackagePkgHeader extends JFrame implements ActionListener { + private static String Separator = "::"; + + private DefaultListModel listItem = new DefaultListModel(); + + private SpdFileContents sfc = null; + + private JPanel jContentPane = null; + + private JRadioButton jRadioButtonAdd = null; + + private JRadioButton jRadioButtonSelect = null; + + private JTextField jTextFieldAdd = null; + + private JComboBox jComboBoxSelect = null; + + private JScrollPane jScrollPane = null; + + private JList jListLibraryClassDefinitions = null; + + private JButton jButtonAdd = null; + + private JButton jButtonRemove = null; + + private JButton jButtonClearAll = null; + + private JButton jButtonCancel = null; + + private JButton jButtonOk = null; + + private JLabel jLabel = null; + + private JTextField jTextField = null; + + private StarLabel starLabel = null; + + /** + This method initializes this + + **/ + private void initialize() { + this.setTitle("Package Headers"); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + } + + /** + This method initializes jRadioButtonAdd + + @return javax.swing.JRadioButton + **/ + private JRadioButton getJRadioButtonAdd() { + if (jRadioButtonAdd == null) { + jRadioButtonAdd = new JRadioButton(); + jRadioButtonAdd.setBounds(new java.awt.Rectangle(10, 35, 205, 20)); + jRadioButtonAdd.setText("Add a new Module Type"); + jRadioButtonAdd.setEnabled(false); + jRadioButtonAdd.addActionListener(this); + jRadioButtonAdd.setSelected(false); + } + return jRadioButtonAdd; + } + + /** + This method initializes jRadioButtonSelect + + @return javax.swing.JRadioButton + **/ + private JRadioButton getJRadioButtonSelect() { + if (jRadioButtonSelect == null) { + jRadioButtonSelect = new JRadioButton(); + jRadioButtonSelect.setBounds(new java.awt.Rectangle(10, 10, 205, 20)); + jRadioButtonSelect.setText("Select an existed Module Type"); + jRadioButtonSelect.setActionCommand("Select an existed Module Type"); + jRadioButtonSelect.addActionListener(this); + jRadioButtonSelect.setSelected(true); + } + return jRadioButtonSelect; + } + + /** + This method initializes jTextFieldAdd + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldAdd() { + if (jTextFieldAdd == null) { + jTextFieldAdd = new JTextField(); + jTextFieldAdd.setBounds(new java.awt.Rectangle(220, 35, 260, 20)); + jTextFieldAdd.setEditable(false); + jTextFieldAdd.setEnabled(false); + } + return jTextFieldAdd; + } + + /** + This method initializes jComboBoxSelect + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBoxSelect() { + if (jComboBoxSelect == null) { + jComboBoxSelect = new JComboBox(); + jComboBoxSelect.setBounds(new java.awt.Rectangle(220, 10, 260, 20)); + jComboBoxSelect.setEnabled(true); + } + return jComboBoxSelect; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(10, 121, 350, 174)); + jScrollPane.setViewportView(getJListLibraryClassDefinitions()); + } + return jScrollPane; + } + + /** + This method initializes jListLibraryClassDefinitions + + @return javax.swing.JList + **/ + private JList getJListLibraryClassDefinitions() { + if (jListLibraryClassDefinitions == null) { + jListLibraryClassDefinitions = new JList(listItem); + } + return jListLibraryClassDefinitions; + } + + /** + This method initializes jButtonAdd + + @return javax.swing.JButton + **/ + private JButton getJButtonAdd() { + if (jButtonAdd == null) { + jButtonAdd = new JButton(); + jButtonAdd.setBounds(new java.awt.Rectangle(375, 132, 90, 20)); + jButtonAdd.setText("Add"); + jButtonAdd.addActionListener(this); + } + return jButtonAdd; + } + + /** + This method initializes jButtonRemove + + @return javax.swing.JButton + **/ + private JButton getJButtonRemove() { + if (jButtonRemove == null) { + jButtonRemove = new JButton(); + jButtonRemove.setBounds(new java.awt.Rectangle(375, 230, 90, 20)); + jButtonRemove.setText("Remove"); + jButtonRemove.addActionListener(this); + } + return jButtonRemove; + } + + /** + This method initializes jButtonRemoveAll + + @return javax.swing.JButton + **/ + private JButton getJButtonClearAll() { + if (jButtonClearAll == null) { + jButtonClearAll = new JButton(); + jButtonClearAll.setBounds(new java.awt.Rectangle(375, 260, 90, 20)); + jButtonClearAll.setText("Clear All"); + jButtonClearAll.addActionListener(this); + } + return jButtonClearAll; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setPreferredSize(new java.awt.Dimension(90, 20)); + jButtonCancel.setLocation(new java.awt.Point(390, 305)); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setSize(new java.awt.Dimension(90, 20)); + jButtonOk.setText("OK"); + jButtonOk.setLocation(new java.awt.Point(290, 305)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This is the default constructor + **/ + public PackagePkgHeader(SpdFileContents sfc) { + super(); + initialize(); + init(); + this.sfc = sfc; + } + + /** + Start the window at the center of screen + * + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + * + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + // private void init(LibraryClassDefinitionsDocument.LibraryClassDefinitions inLibraryClassDefinitions) { + // init(); + // this.setLibraryClassDefinitions(inLibraryClassDefinitions); + // int intLibraryCount = this.libraryClassDefinitions.getLibraryClassArray().length; + // if (intLibraryCount > 0) { + // for (int index = 0; index < intLibraryCount; index++) { + // listItem.addElement(this.libraryClassDefinitions.getLibraryClassArray(index).getUsage().toString() + + // this.Separator + + // this.libraryClassDefinitions.getLibraryClassArray(index).getStringValue()); + // this.libraryClassDefinitions.getLibraryClassArray(); + // } + // } + // } + + /** + This method initializes this + + @return void + **/ + private void init() { + this.setContentPane(getJContentPane()); + this.setTitle("Library Class Declarations"); + this.setBounds(new java.awt.Rectangle(0, 0, 500, 370)); + this.centerWindow(); + initFrame(); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + starLabel = new StarLabel(); + starLabel.setBounds(new java.awt.Rectangle(5, 85, 10, 20)); + jLabel = new JLabel(); + jLabel.setBounds(new java.awt.Rectangle(14, 85, 201, 22)); + jLabel.setText("Include Header for Selected Type"); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJRadioButtonAdd(), null); + jContentPane.add(getJRadioButtonSelect(), null); + jContentPane.add(getJTextFieldAdd(), null); + jContentPane.add(getJComboBoxSelect(), null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButtonAdd(), null); + jContentPane.add(getJButtonRemove(), null); + jContentPane.add(getJButtonClearAll(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(jLabel, null); + jContentPane.add(getJTextField(), null); + jContentPane.add(starLabel, null); + } + return jContentPane; + } + + private void initFrame() { + jComboBoxSelect.addItem("BASE"); + jComboBoxSelect.addItem("SEC"); + jComboBoxSelect.addItem("PEI_CORE"); + jComboBoxSelect.addItem("PEIM"); + jComboBoxSelect.addItem("DXE_CORE"); + jComboBoxSelect.addItem("DXE_DRIVER"); + jComboBoxSelect.addItem("DXE_RUNTIME_DRIVER"); + jComboBoxSelect.addItem("DXE_SAL_DRIVER"); + jComboBoxSelect.addItem("DXE_SMM_DRIVER"); + jComboBoxSelect.addItem("TOOLS"); + jComboBoxSelect.addItem("UEFI_DRIVER"); + jComboBoxSelect.addItem("UEFI_APPLICATION"); + jComboBoxSelect.addItem("USER_DEFINED"); + + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jButtonAdd) { + String strLibClass = ""; + + if (jRadioButtonAdd.isSelected()) { + strLibClass = jTextFieldAdd.getText(); + } + if (jRadioButtonSelect.isSelected()) { + strLibClass = jComboBoxSelect.getSelectedItem().toString(); + } + + listItem.addElement(jTextField.getText() + Separator + strLibClass); + } + + if (arg0.getSource() == jButtonRemove) { + int intSelected[] = jListLibraryClassDefinitions.getSelectedIndices(); + if (intSelected.length > 0) { + for (int index = intSelected.length - 1; index > -1; index--) { + listItem.removeElementAt(intSelected[index]); + } + } + jListLibraryClassDefinitions.getSelectionModel().clearSelection(); + } + + if (arg0.getSource() == jButtonClearAll) { + listItem.removeAllElements(); + } + + if (arg0.getSource() == jRadioButtonAdd) { + if (jRadioButtonAdd.isSelected()) { + jRadioButtonSelect.setSelected(false); + jTextFieldAdd.setEnabled(true); + jComboBoxSelect.setEnabled(false); + } + if (!jRadioButtonSelect.isSelected() && !jRadioButtonAdd.isSelected()) { + jRadioButtonAdd.setSelected(true); + jTextFieldAdd.setEnabled(true); + jComboBoxSelect.setEnabled(false); + } + } + + if (arg0.getSource() == jRadioButtonSelect) { + if (jRadioButtonSelect.isSelected()) { + jRadioButtonAdd.setSelected(false); + jTextFieldAdd.setEnabled(false); + jComboBoxSelect.setEnabled(true); + } + if (!jRadioButtonSelect.isSelected() && !jRadioButtonAdd.isSelected()) { + jRadioButtonSelect.setSelected(true); + jTextFieldAdd.setEnabled(false); + jComboBoxSelect.setEnabled(true); + } + } + } + + private void save() { + try { + int intLibraryCount = listItem.getSize(); + + if (intLibraryCount > 0) { + + for (int index = 0; index < intLibraryCount; index++) { + String strAll = listItem.get(index).toString(); + String strInclude = strAll.substring(0, strAll.indexOf(Separator)); + String strType = strAll.substring(strAll.indexOf(Separator) + Separator.length()); + sfc.genSpdModuleHeaders(strType, strInclude, null, null, null, null, null, null); + } + } else { + + } + + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + /** + This method initializes jTextField + + @return javax.swing.JTextField + **/ + private JTextField getJTextField() { + if (jTextField == null) { + jTextField = new JTextField(); + jTextField.setBounds(new java.awt.Rectangle(221, 86, 257, 21)); + } + return jTextField; + } + +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagePpi.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagePpi.java new file mode 100644 index 0000000000..7b62d804e5 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagePpi.java @@ -0,0 +1,41 @@ +/** @file + Java class PackagePpi is GUI for create Ppi definition elements of spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +/** + GUI derived from PackageProtocols class, override save() method + + @since PackageEditor 1.0 +**/ +public class PackagePpi extends PackageProtocols { + + private SpdFileContents sfc = null; + + public PackagePpi(SpdFileContents sfc) { + super(sfc); + // TODO Auto-generated constructor stub + this.sfc = sfc; + } + + /** + add ppi definitions from GUI to SpdFileContents object passed in. + **/ + protected void save() { + try { + sfc.genSpdPpiDeclarations(getJTextField().getText(), getJTextFieldC_Name().getText(), + getJTextFieldGuid().getText(), null); + } catch (Exception e) { + System.out.println(e.toString()); + } + } +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageProtocols.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageProtocols.java new file mode 100644 index 0000000000..d99d18b4e6 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackageProtocols.java @@ -0,0 +1,377 @@ +/** @file + Java class PackageProtocols is GUI for create Protocol definition elements of spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import javax.swing.JPanel; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JComboBox; +import javax.swing.JRadioButton; +import javax.swing.JFrame; + +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + GUI for create Protocol definition elements of spd file. + + @since PackageEditor 1.0 +**/ +public class PackageProtocols extends JFrame implements ActionListener { + + private int location = -1; + + private SpdFileContents sfc = null; + + private JPanel jContentPane = null; + + private JLabel jLabelC_Name = null; + + private JTextField jTextFieldC_Name = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelFeatureFlag = null; + + private JTextField jTextFieldFeatureFlag = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JLabel jLabelEnableFeature = null; + + private JRadioButton jRadioButtonEnableFeature = null; + + private JRadioButton jRadioButtonDisableFeature = null; + + private JButton jButtonGenerateGuid = null; + + private StarLabel jStarLabel2 = null; + + private StarLabel starLabel = null; + + private JLabel jLabel = null; + + private JTextField jTextField = null; + + /** + This method initializes this + + **/ + private void initialize() { + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + } + + /** + This method initializes jTextFieldProtocolName + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldProtocolName() { + if (jTextFieldC_Name == null) { + jTextFieldC_Name = new JTextField(); + jTextFieldC_Name.setBounds(new java.awt.Rectangle(160, 35, 320, 20)); + } + return jTextFieldC_Name; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField + **/ + public JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 60, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldFeatureFlag + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldFeatureFlag() { + if (jTextFieldFeatureFlag == null) { + jTextFieldFeatureFlag = new JTextField(); + jTextFieldFeatureFlag.setBounds(new java.awt.Rectangle(160, 135, 320, 20)); + jTextFieldFeatureFlag.setEnabled(false); + } + return jTextFieldFeatureFlag; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 190, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButton1 + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 190, 90, 20)); + jButtonCancel.setPreferredSize(new Dimension(90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jRadioButtonEnableFeature + + @return javax.swing.JRadioButton + **/ + private JRadioButton getJRadioButtonEnableFeature() { + if (jRadioButtonEnableFeature == null) { + jRadioButtonEnableFeature = new JRadioButton(); + jRadioButtonEnableFeature.setText("Enable"); + jRadioButtonEnableFeature.setBounds(new java.awt.Rectangle(160, 110, 90, 20)); + jRadioButtonEnableFeature.setEnabled(false); + jRadioButtonEnableFeature.addActionListener(this); + jRadioButtonEnableFeature.setSelected(true); + } + return jRadioButtonEnableFeature; + } + + /** + This method initializes jRadioButtonDisableFeature + + @return javax.swing.JRadioButton + **/ + private JRadioButton getJRadioButtonDisableFeature() { + if (jRadioButtonDisableFeature == null) { + jRadioButtonDisableFeature = new JRadioButton(); + jRadioButtonDisableFeature.setText("Disable"); + jRadioButtonDisableFeature.setEnabled(false); + jRadioButtonDisableFeature.setBounds(new java.awt.Rectangle(320, 110, 90, 20)); + jRadioButtonDisableFeature.addActionListener(this); + } + return jRadioButtonDisableFeature; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 60, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This is the default constructor + **/ + public PackageProtocols(SpdFileContents sfc) { + super(); + initialize(); + init(); + this.setVisible(true); + this.sfc = sfc; + } + + /** + This method initializes this + + @return void + **/ + private void init() { + this.setSize(500, 250); + this.setName("JFrame"); + this.setContentPane(getJContentPane()); + this.setTitle("Add Protocols"); + this.centerWindow(); + //this.getRootPane().setDefaultButton(jButtonOk); + initFrame(); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabel = new JLabel(); + jLabel.setBounds(new java.awt.Rectangle(16, 10, 138, 16)); + jLabel.setText("Name"); + starLabel = new StarLabel(); + starLabel.setBounds(new java.awt.Rectangle(0, 9, 10, 20)); + jLabelEnableFeature = new JLabel(); + jLabelEnableFeature.setText("Enable Feature"); + jLabelEnableFeature.setEnabled(false); + jLabelEnableFeature.setBounds(new java.awt.Rectangle(15, 110, 140, 20)); + jLabelFeatureFlag = new JLabel(); + jLabelFeatureFlag.setText("Feature Flag"); + jLabelFeatureFlag.setEnabled(false); + jLabelFeatureFlag.setBounds(new java.awt.Rectangle(15, 135, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setText("Guid"); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelC_Name = new JLabel(); + jLabelC_Name.setText("C_Name"); + jLabelC_Name.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(jLabelC_Name, null); + jContentPane.add(getJTextFieldProtocolName(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelFeatureFlag, null); + jContentPane.add(getJTextFieldFeatureFlag(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(jLabelEnableFeature, null); + jContentPane.add(getJRadioButtonEnableFeature(), null); + jContentPane.add(getJRadioButtonDisableFeature(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + + jStarLabel2 = new StarLabel(); + jStarLabel2.setBounds(new java.awt.Rectangle(0, 35, 10, 20)); + + jContentPane.add(jStarLabel2, null); + jContentPane.add(starLabel, null); + jContentPane.add(jLabel, null); + jContentPane.add(getJTextField(), null); + } + return jContentPane; + } + + /** + This method initializes protocol usage type + + **/ + private void initFrame() { + + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + + this.save(); + this.dispose(); + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + } + + if (arg0.getSource() == jRadioButtonEnableFeature) { + if (jRadioButtonEnableFeature.isSelected()) { + jRadioButtonDisableFeature.setSelected(false); + } + if (!jRadioButtonDisableFeature.isSelected() && !jRadioButtonEnableFeature.isSelected()) { + jRadioButtonEnableFeature.setSelected(true); + } + } + + if (arg0.getSource() == jRadioButtonDisableFeature) { + if (jRadioButtonDisableFeature.isSelected()) { + jRadioButtonEnableFeature.setSelected(false); + } + if (!jRadioButtonDisableFeature.isSelected() && !jRadioButtonEnableFeature.isSelected()) { + jRadioButtonDisableFeature.setSelected(true); + } + } + + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + protected void save() { + try { + sfc.genSpdProtocolDeclarations(jTextField.getText(), jTextFieldC_Name.getText(), jTextFieldGuid.getText(), + null); + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + /** + This method initializes jTextField + + @return javax.swing.JTextField + **/ + public JTextField getJTextField() { + if (jTextField == null) { + jTextField = new JTextField(); + jTextField.setBounds(new java.awt.Rectangle(160, 8, 319, 23)); + } + return jTextField; + } + + public JTextField getJTextFieldC_Name() { + return jTextFieldC_Name; + } + + public void setJTextFieldC_Name(JTextField textFieldC_Name) { + jTextFieldC_Name = textFieldC_Name; + } + + public void setJTextField(JTextField textField) { + jTextField = textField; + } + + public void setJTextFieldGuid(JTextField textFieldGuid) { + jTextFieldGuid = textFieldGuid; + } +} // @jve:decl-index=0:visual-constraint="10,10" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagingMain.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagingMain.java new file mode 100644 index 0000000000..bca1108045 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PackagingMain.java @@ -0,0 +1,309 @@ +/** @file + Java class PackagingMain is top level GUI for PackageEditor. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Toolkit; + +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JFrame; +import java.awt.FlowLayout; +import javax.swing.JButton; +import java.awt.GridLayout; +import java.io.File; +import java.io.FileOutputStream; +import java.util.jar.JarOutputStream; + +/** + GUI for show various GUI wizards for create, update spd file; install, remove package; + create distributable package file. + + @since PackageEditor 1.0 +**/ +public class PackagingMain extends JFrame { + + static JFrame frame; + + private JPanel jContentPane = null; + + private JButton jButton = null; + + private JButton jButton1 = null; + + private JButton jButton2 = null; + + private JButton jButton3 = null; + + private JButton jButton4 = null; + + private JButton jButton5 = null; + + private JFrame pThis = null; + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setEnabled(true); + jButton.setText("Exit"); + jButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + pThis.dispose(); + } + }); + } + return jButton; + } + + /** + This method initializes jButton1 + + @return javax.swing.JButton + **/ + private JButton getJButton1() { + if (jButton1 == null) { + jButton1 = new JButton(); + jButton1.setText("Create an Installable Package"); + jButton1.setEnabled(true); + jButton1.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + File theFile = null; + JFileChooser chooser = new JFileChooser(); + // + // select the directory that contains files to be distribute + // + chooser.setMultiSelectionEnabled(false); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + int retval = chooser.showOpenDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + try { + theFile = chooser.getSelectedFile(); + // + // find the FDPManifest.xml file that should exist + // in the root directory of package + // + String[] list = theFile.list(); + boolean manifestExists = false; + for (int i = 0; i < list.length; i++) { + if (list[i].equals("FDPManifest.xml")) { + manifestExists = true; + break; + } + } + if (!manifestExists) { + JOptionPane.showMessageDialog(frame, + "Please Put the FDPManifest.xml File under the Directory You Selected!"); + return; + } + // + // create the distribute package .fdp file in the same directory with + // the package root directory selected above. + // + JarOutputStream jos = new JarOutputStream(new FileOutputStream(theFile.getPath() + ".fdp")); + CreateFdp.create(theFile, jos, theFile.getPath()); + jos.close(); + JOptionPane.showMessageDialog(frame, + "FDP File Created Successfully!"); + + + } catch (Exception ee) { + System.out.println(ee.toString()); + } + } else { + return; + } + } + }); + } + return jButton1; + } + + /** + This method initializes jButton2 + + @return javax.swing.JButton + **/ + private JButton getJButton2() { + if (jButton2 == null) { + jButton2 = new JButton(); + jButton2.setText("Remove Package"); + jButton2.setEnabled(true); + jButton2.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new GuiPkgUninstall(), pThis); + } + }); + } + return jButton2; + } + + /** + This method initializes jButton3 + + @return javax.swing.JButton + **/ + private JButton getJButton3() { + if (jButton3 == null) { + jButton3 = new JButton(); + jButton3.setText("Install Package"); + jButton3.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new GuiPkgInstall(), pThis); + } + }); + } + return jButton3; + } + + /** + This method initializes jButton4 + + @return javax.swing.JButton + **/ + private JButton getJButton4() { + if (jButton4 == null) { + jButton4 = new JButton(); + jButton4.setText("Update Package Description File"); + jButton4.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + File theFile = null; + JFileChooser chooser = new JFileChooser(); + // + // select the spd file to be updated first + // + chooser.setMultiSelectionEnabled(false); + chooser.setFileFilter(new PkgFileFilter("spd")); + int retval = chooser.showOpenDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + try { + theFile = chooser.getSelectedFile(); + if (!theFile.isFile()) { + JOptionPane.showMessageDialog(frame, "Please Select one Spd File!"); + return; + } + + } catch (Exception ee) { + System.out.println(ee.toString()); + } + } else { + return; + } + // + // create a SpdFileContents for this file and pass it to GUI + // + SpdFileContents sfc = new SpdFileContents(theFile); + ModalFrameUtil.showAsModal(new UpdateAction(sfc), pThis); + } + }); + } + return jButton4; + } + + /** + This method initializes jButton5 + + @return javax.swing.JButton + **/ + private JButton getJButton5() { + if (jButton5 == null) { + jButton5 = new JButton(); + jButton5.setText("Create Package Description File"); + jButton5.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + SpdFileContents sfc = new SpdFileContents(); + ModalFrameUtil.showAsModal(new PackageAction(sfc), pThis); + } + }); + } + return jButton5; + } + + /** + Main for all package editor + + @param args + **/ + public static void main(String[] args) { + // TODO Auto-generated method stub + new PackagingMain().setVisible(true); + } + + /** + This is the default constructor + **/ + public PackagingMain() { + super(); + initialize(); + pThis = this; + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(300, 357); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setTitle("Packaging"); + this.setContentPane(getJContentPane()); + this.centerWindow(); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + GridLayout gridLayout = new GridLayout(); + gridLayout.setRows(6); + gridLayout.setColumns(1); + jContentPane = new JPanel(); + jContentPane.setLayout(gridLayout); + jContentPane.add(getJButton5(), null); + jContentPane.add(getJButton4(), null); + jContentPane.add(getJButton3(), null); + jContentPane.add(getJButton2(), null); + jContentPane.add(getJButton1(), null); + jContentPane.add(getJButton(), null); + } + return jContentPane; + } + +} // @jve:decl-index=0:visual-constraint="125,31" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/PkgInstallTypeChooser.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PkgInstallTypeChooser.java new file mode 100644 index 0000000000..099c55ae40 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/PkgInstallTypeChooser.java @@ -0,0 +1,373 @@ +/** @file + Java class PkgInstallTypeChooser is GUI for upgrade package installation. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.io.File; +import java.util.List; +import java.util.ListIterator; +import java.util.Vector; + +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JDialog; +import javax.swing.JRadioButton; +import javax.swing.JButton; + +import org.tianocore.PackageListDocument; +import javax.swing.JList; +import javax.swing.JTextField; +import javax.swing.JScrollPane; + +/** + GUI for speicial circumstances of package installation. + + @since PackageEditor 1.0 +**/ +public class PkgInstallTypeChooser extends JFrame implements MouseListener { + + final static long serialVersionUID = 0; + + static JFrame frame; + + private JPanel jContentPane = null; + + private JRadioButton jRadioButton = null; + + private JRadioButton jRadioButton1 = null; + + private JButton jButton = null; + + private JButton jButton1 = null; + + private String pn = null; + + /// + /// list of package info from db file + /// + private List dd = null; + + private String wk = null; + + private JList jList = null; + + private JScrollPane jScrollPane = null; + + private JTextField jTextField = null; + + private JButton jButton2 = null; + + private JFileChooser chooser = null; + + /** + This is the default constructor + **/ + public PkgInstallTypeChooser(String pkgName, String wkSpace, List destDir) { + super(); + pn = pkgName; + dd = destDir; + wk = wkSpace; + initialize(); + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(359, 328); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setTitle("Chooser Installation Type"); + this.setContentPane(getJContentPane()); + this.centerWindow(); + this.insertList(); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + initialize jList with package info. from db file + **/ + private void insertList() { + + Vector v = new Vector(); + + ListIterator lpi = dd.listIterator(); + while (lpi.hasNext()) { + PackageListDocument.PackageList.Package p = (PackageListDocument.PackageList.Package) lpi.next(); + v.addElement(p.getPackageNameArray(0).getStringValue() + " " + p.getVersionArray(0) + " " + + p.getGuidArray(0).getStringValue()); + } + jList.setListData(v); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJRadioButton(), null); + jContentPane.add(getJRadioButton1(), null); + jContentPane.add(getJButton(), null); + jContentPane.add(getJButton1(), null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJTextField(), null); + jContentPane.add(getJButton2(), null); + } + return jContentPane; + } + + + private JRadioButton getJRadioButton() { + if (jRadioButton == null) { + jRadioButton = new JRadioButton(); + jRadioButton.setBounds(new java.awt.Rectangle(17, 39, 186, 21)); + jRadioButton.setSelected(true); + jRadioButton.setText("Reinstall Existing Package"); + jRadioButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + if (jRadioButton.isSelected()) { + jRadioButton1.setSelected(false); + jButton2.setEnabled(false); + jTextField.setEnabled(false); + jList.setEnabled(true); + return; + } + if (jRadioButton1.isSelected()) { + jRadioButton.setSelected(true); + jRadioButton1.setSelected(false); + jList.setEnabled(true); + return; + } + + } + }); + } + return jRadioButton; + } + + private JRadioButton getJRadioButton1() { + if (jRadioButton1 == null) { + jRadioButton1 = new JRadioButton(); + jRadioButton1.setBounds(new java.awt.Rectangle(17, 155, 176, 21)); + jRadioButton1.setText("Install to Directory"); + jRadioButton1.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + if (jRadioButton1.isSelected()) { + jRadioButton.setSelected(false); + jList.setEnabled(false); + jButton2.setEnabled(true); + jTextField.setEnabled(true); + return; + } + if (jRadioButton.isSelected()) { + jRadioButton1.setSelected(true); + jRadioButton.setSelected(false); + jButton2.setEnabled(true); + jTextField.setEnabled(true); + return; + } + } + }); + } + return jRadioButton1; + } + + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setPreferredSize(new java.awt.Dimension(34, 20)); + jButton.setSize(new java.awt.Dimension(76, 20)); + jButton.setText("Ok"); + jButton.setLocation(new java.awt.Point(141, 241)); + jButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + try { + int i = -1; + // + // user selects replace existing package + // + if (jRadioButton.isSelected()) { + int j = jList.getSelectedIndex(); + if (j == -1) { + JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), + "Please Select One Package to Replace!"); + return; + } + // + // the sequence of jList is the same with List + // + String destDir = dd.get(j).getPathArray(0).getStringValue(); + ForceInstallPkg f = new ForceInstallPkg(pn, wk); + // + // record the package info. to be replaced + // + f.setOldVersion(dd.get(j).getVersionArray(0)); + f.setOldGuid(dd.get(j).getGuidArray(0).getStringValue()); + i = f.install(wk + System.getProperty("file.separator") + destDir); + } else { + // + // user selects install to another directory + // + File f = new File(wk + System.getProperty("file.separator") + FrameworkPkg.dbConfigFile); + if (new DbFileContents(f).checkDir(jTextField.getText().substring(wk.length() + 1)) != 0) { + throw new DirSame(); + } + i = new ForceInstallPkg(pn, wk).install(jTextField.getText()); + } + if (i == 0) { + JOptionPane.showMessageDialog(JOptionPane.getRootFrame(), "Package " + pn + + " Installed Successfully!"); + } + } catch (DirSame ds) { + System.out.println(ds.toString()); + JOptionPane.showMessageDialog(frame, + "Another Package Exists There, Please Select Another Directory!"); + } catch (Exception ee) { + System.out.println(ee.toString()); + } + } + }); + } + return jButton; + } + + /** + * This method initializes jButton1 + * + * @return javax.swing.JButton + */ + private JButton getJButton1() { + if (jButton1 == null) { + jButton1 = new JButton(); + jButton1.setBounds(new java.awt.Rectangle(238, 241, 78, 20)); + jButton1.setText("Cancel"); + jButton1.setPreferredSize(new java.awt.Dimension(34, 20)); + jButton1.addMouseListener(this); + } + return jButton1; + } + + public void mouseClicked(MouseEvent arg0) { + // TODO Auto-generated method stub + this.dispose(); + } + + public void mouseEntered(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + public void mouseExited(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + public void mousePressed(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + public void mouseReleased(MouseEvent arg0) { + // TODO Auto-generated method stub + + } + + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(22, 68, 318, 58)); + jScrollPane.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPane.setViewportView(getJList()); + } + return jScrollPane; + } + + private JList getJList() { + if (jList == null) { + jList = new JList(); + + jList.setBounds(new java.awt.Rectangle(22, 68, 318, 58)); + + } + return jList; + } + + /** + * This method initializes jTextField + * + * @return javax.swing.JTextField + */ + private JTextField getJTextField() { + if (jTextField == null) { + jTextField = new JTextField(); + jTextField.setBounds(new java.awt.Rectangle(22, 184, 224, 20)); + jTextField.setEnabled(false); + jTextField.setText(wk); + } + return jTextField; + } + + private JButton getJButton2() { + if (jButton2 == null) { + jButton2 = new JButton(); + jButton2.setLocation(new java.awt.Point(259, 183)); + jButton2.setText("Browse"); + jButton2.setEnabled(false); + jButton2.setSize(new java.awt.Dimension(81, 20)); + jButton2.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + if (chooser == null) { + chooser = new JFileChooser(wk); + } + chooser.setMultiSelectionEnabled(false); + chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); + + int retval = chooser.showOpenDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + jTextField.setText(chooser.getSelectedFile().getPath()); + + } + + } + }); + } + return jButton2; + } + +} // @jve:decl-index=0:visual-constraint="134,45" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/SpdFileContents.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/SpdFileContents.java new file mode 100644 index 0000000000..b6e573a1fd --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/SpdFileContents.java @@ -0,0 +1,1282 @@ +/** @file + Java class SpdFileContents is used to parse spd xml file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.ListIterator; + +import org.apache.xmlbeans.XmlObject; +import org.apache.xmlbeans.XmlOptions; +import org.apache.xmlbeans.XmlCursor; + +import org.tianocore.AbstractDocument; +import org.tianocore.GuidDeclarationsDocument; +import org.tianocore.GuidDocument; +import org.tianocore.IncludeHeaderDocument; +import org.tianocore.LibraryClassDeclarationDocument; +import org.tianocore.LibraryClassDeclarationsDocument; +import org.tianocore.LibraryClassDocument; +import org.tianocore.LibraryUsage; +import org.tianocore.LicenseDocument; +import org.tianocore.ModuleTypeDef; +import org.tianocore.MsaFilesDocument; +import org.tianocore.OutputDirectoryDocument; +import org.tianocore.PackageDependenciesDocument; +import org.tianocore.PackageHeadersDocument; +import org.tianocore.PackageNameDocument; +import org.tianocore.PackageSurfaceAreaDocument; +import org.tianocore.PackageType; +import org.tianocore.PackageUsage; +import org.tianocore.PcdDataTypes; +import org.tianocore.PcdDefinitionsDocument; +import org.tianocore.PcdItemTypes; +import org.tianocore.PpiDeclarationsDocument; +import org.tianocore.ProtocolDeclarationsDocument; +import org.tianocore.SpdHeaderDocument; +import org.tianocore.SpecificationDocument; +import org.tianocore.GuidDeclarationsDocument.GuidDeclarations; + +/** + This class processes spd file contents such as add remove xml elements. + + @since PackageEditor 1.0 +**/ +public class SpdFileContents { + + private File file = null; + + private PackageSurfaceAreaDocument psad = null; + + private PackageSurfaceAreaDocument.PackageSurfaceArea psaRoot = null; + + private SpdHeaderDocument.SpdHeader spdHdr = null; + + private PackageNameDocument.PackageName spdHdrPkgName = null; + + private GuidDocument.Guid spdHdrGuid = null; + + private AbstractDocument.Abstract spdHdrAbs = null; + + private LicenseDocument.License spdHdrLicense = null; + + private SpecificationDocument.Specification spdHdrSpec = null; + + private OutputDirectoryDocument.OutputDirectory spdHdrOutDir = null; + + private LibraryClassDeclarationsDocument.LibraryClassDeclarations spdLibClassDeclarations = null; + + private PackageDependenciesDocument.PackageDependencies spdPkgDeps = null; + + private MsaFilesDocument.MsaFiles spdMsaFiles = null; + + private PackageHeadersDocument.PackageHeaders spdModHdrs = null; + + private GuidDeclarationsDocument.GuidDeclarations spdGuidDeclarations = null; + + private ProtocolDeclarationsDocument.ProtocolDeclarations spdProtocolDeclarations = null; + + private PpiDeclarationsDocument.PpiDeclarations spdPpiDeclarations = null; + + private PcdDefinitionsDocument.PcdDefinitions spdPcdDefinitions = null; + + /** + Constructor to create a new spd file + **/ + public SpdFileContents() { + + psad = PackageSurfaceAreaDocument.Factory.newInstance(); + psaRoot = psad.addNewPackageSurfaceArea(); + + } + + /** + Constructor based on an existing spd file + + @param f Existing spd file + **/ + public SpdFileContents(File f) { + try { + psad = PackageSurfaceAreaDocument.Factory.parse(f); + psaRoot = psad.getPackageSurfaceArea(); + file = f; + } catch (Exception e) { + System.out.println(e.toString()); + } + } + + /** + Remove existing pcd definitions elements using XmlCursor + **/ + public void removeSpdPcdDefinition() { + XmlObject o = psaRoot.getPcdDefinitions(); + if (o == null) + return; + XmlCursor cursor = o.newCursor(); + cursor.removeXml(); + } + + /** + Remove existing ppi declarations using XmlCursor + **/ + public void removeSpdPpiDeclaration() { + XmlObject o = psaRoot.getPpiDeclarations(); + if (o == null) + return; + XmlCursor cursor = o.newCursor(); + cursor.removeXml(); + } + + /** + Remove existing protocols declarations using XmlCursor + **/ + public void removeSpdProtocolDeclaration() { + XmlObject o = psaRoot.getProtocolDeclarations(); + if (o == null) + return; + XmlCursor cursor = o.newCursor(); + cursor.removeXml(); + } + + /** + Remove existing GUID declarations using XmlCursor + **/ + public void removeSpdGuidDeclaration() { + XmlObject o = psaRoot.getGuidDeclarations(); + if (o == null) + return; + XmlCursor cursor = o.newCursor(); + cursor.removeXml(); + } + + /** + Remove existing spd package header using XmlCursor + **/ + public void removeSpdPkgHeader() { + XmlObject o = psaRoot.getPackageHeaders(); + if (o == null) + return; + XmlCursor cursor = o.newCursor(); + cursor.removeXml(); + } + + /** + Remove existing msa files using XmlCursor + **/ + public void removeSpdMsaFile() { + XmlObject o = psaRoot.getMsaFiles(); + if (o == null) + return; + XmlCursor cursor = o.newCursor(); + cursor.removeXml(); + } + + /** + Remove existing library class declarations using XmlCursor + **/ + public void removeSpdLibClass() { + XmlObject o = psaRoot.getLibraryClassDeclarations(); + if (o == null) + return; + XmlCursor cursor = o.newCursor(); + cursor.removeXml(); + + } + + /** + Get spd file header contents into String array + + @param s Caller allocated String array + **/ + public void getSpdHdrDetails(String[] s) { + if (getSpdHdr() == null) { + spdHdr = psaRoot.addNewSpdHeader(); + } + s[0] = getSpdHdrPkgName().getStringValue(); + s[1] = getSpdHdrGuid().getStringValue(); + s[2] = getSpdHdrVer(); + s[3] = getSpdHdrAbs().getStringValue(); + s[4] = getSpdHdr().getDescription(); + s[5] = getSpdHdr().getCopyright(); + s[6] = getSpdHdrLicense().getStringValue(); + s[7] = getSpdHdr().getCreated(); + s[8] = getSpdHdr().getURL(); + if (getSpdHdr().getPackageType() != null) { + s[9] = getSpdHdr().getPackageType().toString(); + } + // + // convert boolean to String by adding empty String "" + // + s[10] = getSpdHdr().getReadOnly() + ""; + s[11] = getSpdHdr().getReadOnly() + ""; + } + + /** + Get the number of library class declarations from the size of List + + @return int + **/ + public int getSpdLibClassDeclarationCount() { + if (psaRoot.getLibraryClassDeclarations() == null + || psaRoot.getLibraryClassDeclarations().getLibraryClassDeclarationList() == null) { + return 0; + } + return psaRoot.getLibraryClassDeclarations().getLibraryClassDeclarationList().size(); + } + + /** + Get available library class declaration into String array + @param libClass Caller allocated two-dimentional String array + **/ + public void getSpdLibClassDeclarations(String[][] libClass) { + List l = psaRoot.getLibraryClassDeclarations() + .getLibraryClassDeclarationList(); + int i = 0; + ListIterator li = l.listIterator(); + while (li.hasNext()) { + LibraryClassDeclarationDocument.LibraryClassDeclaration lcd = (LibraryClassDeclarationDocument.LibraryClassDeclaration) li + .next(); + if (lcd.getLibraryClass() != null) { + libClass[i][0] = lcd.getLibraryClass().getStringValue(); + } + if (lcd.getIncludeHeader() != null) { + libClass[i][1] = lcd.getIncludeHeader().getStringValue(); + } + + i++; + } + + } + + /** + Get the number of Msa files from the size of List + + @return int + **/ + public int getSpdMsaFileCount() { + if (psaRoot.getMsaFiles() == null || psaRoot.getMsaFiles().getMsaFileList() == null) { + return 0; + } + return psaRoot.getMsaFiles().getMsaFileList().size(); + } + + /** + Get available Msa file into String array + + @param msaFile Caller allocated two-dimentional String array + **/ + public void getSpdMsaFiles(String[][] msaFile) { + List l = psaRoot.getMsaFiles().getMsaFileList(); + int i = 0; + ListIterator li = l.listIterator(); + while (li.hasNext()) { + MsaFilesDocument.MsaFiles.MsaFile m = (MsaFilesDocument.MsaFiles.MsaFile) li.next(); + if (m.getFilename() != null) { + msaFile[i][0] = m.getFilename().getStringValue(); + } + + i++; + } + } + + /** + Get the number of include header files in PackageHeaders from the size of List + + @return int + **/ + public int getSpdPackageHeaderCount() { + if (psaRoot.getPackageHeaders() == null || psaRoot.getPackageHeaders().getIncludeHeaderList() == null) { + return 0; + } + return psaRoot.getPackageHeaders().getIncludeHeaderList().size(); + } + + /** + Get available package header contents into String array + + @param pkgHeader Caller allocated two-dimentional String array + **/ + public void getSpdPackageHeaders(String[][] pkgHeader) { + List l = psaRoot.getPackageHeaders().getIncludeHeaderList(); + int i = 0; + ListIterator li = l.listIterator(); + while (li.hasNext()) { + IncludeHeaderDocument.IncludeHeader ih = (IncludeHeaderDocument.IncludeHeader) li.next(); + if (ih.getModuleType() != null) { + pkgHeader[i][0] = ih.getModuleType().toString(); + } + + pkgHeader[i][1] = ih.getStringValue(); + i++; + } + } + + /** + Get the number of GUID declarations from the size of List + + @return int + **/ + public int getSpdGuidDeclarationCount() { + if (psaRoot.getGuidDeclarations() == null || psaRoot.getGuidDeclarations().getEntryList() == null) { + return 0; + } + return psaRoot.getGuidDeclarations().getEntryList().size(); + } + + /** + Get available Guid declaration contents into String array + + @param guid Caller allocated two-dimentional String array + **/ + public void getSpdGuidDeclarations(String[][] guid) { + List l = psaRoot.getGuidDeclarations().getEntryList(); + int i = 0; + ListIterator li = l.listIterator(); + while (li.hasNext()) { + GuidDeclarationsDocument.GuidDeclarations.Entry e = (GuidDeclarationsDocument.GuidDeclarations.Entry) li + .next(); + guid[i][0] = e.getName(); + guid[i][1] = e.getCName(); + if (e.getGuid() != null) { + guid[i][2] = e.getGuid().getStringValue(); + } + i++; + } + } + + /** + Get the number of protocol declarations from the size of List + + @return int + **/ + public int getSpdProtocolDeclarationCount() { + if (psaRoot.getProtocolDeclarations() == null || psaRoot.getProtocolDeclarations().getEntryList() == null) { + return 0; + } + return psaRoot.getProtocolDeclarations().getEntryList().size(); + } + + /** + Get available protocol declaration contents into String array + + @param protocol Caller allocated two-dimentional String array + **/ + public void getSpdProtocolDeclarations(String[][] protocol) { + List l = psaRoot.getProtocolDeclarations() + .getEntryList(); + int i = 0; + ListIterator li = l.listIterator(); + while (li.hasNext()) { + ProtocolDeclarationsDocument.ProtocolDeclarations.Entry e = (ProtocolDeclarationsDocument.ProtocolDeclarations.Entry) li + .next(); + protocol[i][0] = e.getName(); + protocol[i][1] = e.getCName(); + if (e.getGuid() != null) { + protocol[i][2] = e.getGuid().getStringValue(); + } + i++; + } + } + + /** + Get the number of Ppi declarations from the size of List + + @return int + **/ + public int getSpdPpiDeclarationCount() { + if (psaRoot.getPpiDeclarations() == null || psaRoot.getPpiDeclarations().getEntryList() == null) { + return 0; + } + return psaRoot.getPpiDeclarations().getEntryList().size(); + } + + /** + Get available Ppi declaration contents into String array + + @param ppi Caller allocated two-dimentional String array + **/ + public void getSpdPpiDeclarations(String[][] ppi) { + List l = psaRoot.getPpiDeclarations().getEntryList(); + int i = 0; + ListIterator li = l.listIterator(); + while (li.hasNext()) { + PpiDeclarationsDocument.PpiDeclarations.Entry e = (PpiDeclarationsDocument.PpiDeclarations.Entry) li.next(); + ppi[i][0] = e.getName(); + ppi[i][1] = e.getCName(); + if (e.getGuid() != null) { + ppi[i][2] = e.getGuid().getStringValue(); + } + + i++; + } + } + + /** + Get the number of Pcd definitions from the size of List + + @return int + **/ + public int getSpdPcdDefinitionCount() { + if (psaRoot.getPcdDefinitions() == null || psaRoot.getPcdDefinitions().getPcdEntryList() == null) { + return 0; + } + return psaRoot.getPcdDefinitions().getPcdEntryList().size(); + } + + /** + Get available Pcd definition contents into String array + + @param pcd Caller allocated two-dimentional String array + **/ + public void getSpdPcdDefinitions(String[][] pcd) { + List l = psaRoot.getPcdDefinitions().getPcdEntryList(); + int i = 0; + ListIterator li = l.listIterator(); + while (li.hasNext()) { + PcdDefinitionsDocument.PcdDefinitions.PcdEntry e = (PcdDefinitionsDocument.PcdDefinitions.PcdEntry) li + .next(); + if (e.getItemType() != null) { + pcd[i][0] = e.getItemType().toString(); + } + + pcd[i][1] = e.getCName(); + pcd[i][2] = e.getToken(); + if (e.getDatumType() != null) { + pcd[i][3] = e.getDatumType().toString(); + } + + if (e.getDefaultValue() != null) { + pcd[i][4] = e.getDefaultValue().toString(); + } + + i++; + } + } + + /** + Save the processed xml contents to file + + @param spdFile The file to save xml contents + @throws IOException Exceptions during file operation + **/ + public void saveAs(File spdFile) throws IOException { + + XmlOptions options = new XmlOptions(); + + options.setCharacterEncoding("UTF-8"); + options.setSavePrettyPrint(); + options.setSavePrettyPrintIndent(2); + try { + psad.save(spdFile, options); + } catch (IOException e) { + e.printStackTrace(); + } + + } + + /** + Generate SpdHeader contents using parameters passed in. + + @param pkgName PackageName + @param pkgGuid Guid + @param pkgVer Version + @param pkgAbs Abstract + @param pkgDes Description + @param pkgCpRight Copyright + @param pkgLicense License + @param pkgCreateDate Created + @param pkgUpdateDate Updated + @param pkgURL URL + @param pkgType PackageType + @param pkgRdOnly ReadOnly + @param pkgRePkg RePackage + @param pkgSpec Reserved + @param pkgOutDir Reserved + **/ + public void genSpdHeader(String pkgName, String pkgGuid, String pkgVer, String pkgAbs, String pkgDes, + String pkgCpRight, String pkgLicense, String pkgCreateDate, String pkgUpdateDate, + String pkgURL, String pkgType, String pkgRdOnly, String pkgRePkg, String pkgSpec, + String pkgOutDir) { + if (getSpdHdr() == null) { + spdHdr = psaRoot.addNewSpdHeader(); + } + + setSpdHdrPkgName(pkgName); + setSpdHdrGuid(pkgGuid); + setSpdHdrVer(pkgVer); + setSpdHdrAbs(pkgAbs); + setSpdHdrDes(pkgDes); + setSpdHdrCpRit(pkgCpRight); + setSpdHdrLicense(pkgLicense); + setSpdHdrCreateDate(pkgCreateDate); + setSpdHdrUpdateDate(pkgUpdateDate); + setSpdHdrURL(pkgURL); + setSpdHdrPkgType(pkgType); + setSpdHdrRdOnly(pkgRdOnly); + setSpdHdrRePkg(pkgRePkg); + setSpdHdrSpec(pkgSpec); + setSpdHdrOutDir(pkgOutDir); + } + + /** + Generate library class declaration element using parameters passed in + + @param libClassBaseName LibraryClass element value + @param libClassUsage Reserved + @param incHdrFileName IncludeHeader element value + @param incHdrAttribGuid Reserved + @param incHdrAttribArch Reserved + @param incHdrAttribPath Reserved + @param incHdrAttribClass Reserved + @param incHdrAttribVer Reserved + @param incHdrAttribOverrideID Reserved + @param incHdrAttribModuleType Reserved + **/ + public void genSpdLibClassDeclarations(String libClassBaseName, String libClassUsage, String incHdrFileName, + String incHdrAttribGuid, String incHdrAttribArch, String incHdrAttribPath, + String incHdrAttribClass, String incHdrAttribVer, + String incHdrAttribOverrideID, String incHdrAttribModuleType) { + if (getSpdLibClassDeclarations() == null) { + spdLibClassDeclarations = psaRoot.addNewLibraryClassDeclarations(); + } + // + // add contents under LibraryClassDeclarations tag + // + setSpdLibClassDeclaration(libClassBaseName, libClassUsage, incHdrFileName, incHdrAttribGuid, incHdrAttribArch, + incHdrAttribPath, incHdrAttribClass, incHdrAttribVer, incHdrAttribOverrideID, + incHdrAttribModuleType, spdLibClassDeclarations); + } + + /** + Set library class declaration contents under parent tag + + @param clsName LibraryClass element value + @param clsUsage Reserved + @param hdrFile IncludeHeader element value + @param hdrAttribGuid Reserved + @param hdrAttribArch Reserved + @param hdrAttribPath Reserved + @param hdrAttribClass Reserved + @param hdrAttribVer Reserved + @param hdrAttribOverID Reserved + @param hdrAttribModType Reserved + @param parent The tag under which library class declaration goes to + **/ + public void setSpdLibClassDeclaration(String clsName, String clsUsage, String hdrFile, String hdrAttribGuid, + String hdrAttribArch, String hdrAttribPath, String hdrAttribClass, + String hdrAttribVer, String hdrAttribOverID, String hdrAttribModType, + XmlObject parent) { + + LibraryClassDeclarationDocument.LibraryClassDeclaration lcd = ((LibraryClassDeclarationsDocument.LibraryClassDeclarations) parent) + .addNewLibraryClassDeclaration(); + + setSpdLibraryClass(clsName, clsUsage, lcd); + + setSpdIncludeHeader(null, hdrFile, hdrAttribGuid, hdrAttribArch, hdrAttribPath, hdrAttribClass, hdrAttribVer, + hdrAttribOverID, lcd); + } + + /** + Set the contents of LibraryClass under parent element + + @param clsName LibraryClass element value + @param clsUsage Reserved + @param parent The tag under which library class declaration goes to + **/ + public void setSpdLibraryClass(String clsName, String clsUsage, XmlObject parent) { + LibraryClassDocument.LibraryClass lc = ((LibraryClassDeclarationDocument.LibraryClassDeclaration) parent) + .addNewLibraryClass(); + lc.setStringValue(clsName); + } + + /** + Set contents of IncludeHeader under parent element + + @param modType Reserved + @param hdrFile IncludeHeader element value + @param hdrAttribGuid Reserved + @param hdrAttribArch Reserved + @param hdrAttribPath Reserved + @param hdrAttribClass Reserved + @param hdrAttribVer Reserved + @param hdrAttribOverID Reserved + @param parent The tag under which library class declaration goes to + **/ + public void setSpdIncludeHeader(String modType, String hdrFile, String hdrAttribGuid, String hdrAttribArch, + String hdrAttribPath, String hdrAttribClass, String hdrAttribVer, + String hdrAttribOverID, XmlObject parent) { + IncludeHeaderDocument.IncludeHeader ih = null; + if (parent instanceof LibraryClassDeclarationDocument.LibraryClassDeclaration) { + ih = ((LibraryClassDeclarationDocument.LibraryClassDeclaration) parent).addNewIncludeHeader(); + } else if (parent instanceof PackageHeadersDocument.PackageHeaders) { + ih = ((PackageHeadersDocument.PackageHeaders) parent).addNewIncludeHeader(); + } else { + return; + } + + ih.setStringValue(hdrFile); + if (hdrAttribGuid != null) { + ih.setGuid(hdrAttribGuid); + } + if (hdrAttribPath != null) { + ih.setPath(hdrAttribPath); + } + if (hdrAttribClass != null) { + ih.setClass1(hdrAttribClass); + } + if (hdrAttribVer != null) { + ih.setVersion(hdrAttribVer); + } + if (hdrAttribOverID != null) { + ih.setOverrideID(Integer.parseInt(hdrAttribOverID)); + } + if (modType != null) { + ih.setModuleType(ModuleTypeDef.Enum.forString(modType)); + + } + + } + + /** + Reserved method + + @param pkgDepPkgName + @param pkgDepPkgAttribGuid + @param pkgDepPkgAttribVer + @param pkgDepPkgAttribType + @param pkgDepPkgAttribUsage + @param pkgDepPkgAttribInstallDate + @param pkgDepPkgAttribUpdateDate + @param pkgDepPkgAttribPath + **/ + public void genSpdPackageDependencies(String pkgDepPkgName, String pkgDepPkgAttribGuid, String pkgDepPkgAttribVer, + String pkgDepPkgAttribType, String pkgDepPkgAttribUsage, + String pkgDepPkgAttribInstallDate, String pkgDepPkgAttribUpdateDate, + String pkgDepPkgAttribPath) { + if (spdPkgDeps == null) { + spdPkgDeps = psaRoot.addNewPackageDependencies(); + } + + setSpdPackageName(pkgDepPkgName, pkgDepPkgAttribGuid, pkgDepPkgAttribVer, pkgDepPkgAttribType, + pkgDepPkgAttribUsage, pkgDepPkgAttribInstallDate, pkgDepPkgAttribUpdateDate, + pkgDepPkgAttribPath, spdPkgDeps); + } + + /** + Reserved method + + @param pkgName + @param pkgAttribGuid + @param pkgAttribVer + @param pkgAttribType + @param pkgAttribUsage + @param pkgAttribInstallDate + @param pkgAttribUpdateDate + @param pkgAttribPath + @param parent + **/ + public void setSpdPackageName(String pkgName, String pkgAttribGuid, String pkgAttribVer, String pkgAttribType, + String pkgAttribUsage, String pkgAttribInstallDate, String pkgAttribUpdateDate, + String pkgAttribPath, XmlObject parent) { + + PackageNameDocument.PackageName pn = ((PackageDependenciesDocument.PackageDependencies) parent) + .addNewPackageName(); + pn.setStringValue(pkgName); + pn.setPackageType(PackageType.Enum.forString(pkgAttribType)); + pn.setUsage(PackageUsage.Enum.forString(pkgAttribUsage)); + pn.setUpdatedDate(pkgAttribUpdateDate); + } + + /** + Generate MsaFile element. + + @param msaFileName MsaFile element value + @param archType Reserved + **/ + public void genSpdMsaFiles(String msaFileName, String archType) { + if (getSpdMsaFiles() == null) { + spdMsaFiles = psaRoot.addNewMsaFiles(); + } + setSpdMsaFile(msaFileName, spdMsaFiles); + + } + + /** + Set MsaFile contents under parent element. + + @param msaFileName MsaFile element value + @param parent Element under which MsaFile goes to + **/ + public void setSpdMsaFile(String msaFileName, XmlObject parent) { + + ((MsaFilesDocument.MsaFiles) parent).addNewMsaFile().addNewFilename().setStringValue(msaFileName); + } + + /** + Generate PackageHeader element using parameters passed in. + + @param ModHdrModType ModuleType attribute of IncludeHeader element + @param hdrFile IncludeHeader element value + @param hdrAttribGuid Reserved + @param hdrAttribArch Reserved + @param hdrAttribPath Reserved + @param hdrAttribClass Reserved + @param hdrAttribVer Reserved + @param hdrAttribOverID Reserved + **/ + public void genSpdModuleHeaders(String ModHdrModType, String hdrFile, String hdrAttribGuid, String hdrAttribArch, + String hdrAttribPath, String hdrAttribClass, String hdrAttribVer, + String hdrAttribOverID) { + if (getSpdModHdrs() == null) { + spdModHdrs = psaRoot.addNewPackageHeaders(); + } + + // + // add IncludeHeader under PackageHeaders element + // + setSpdIncludeHeader(ModHdrModType, hdrFile, hdrAttribGuid, hdrAttribArch, hdrAttribPath, hdrAttribClass, + hdrAttribVer, hdrAttribOverID, spdModHdrs); + } + + /** + Generate GUID declaration element using parameters passed in. + + @param guidDeclEntryName Name attribute of Entry element + @param guidDeclCName CName element value + @param guidDeclGuid Guid element value + @param guidDeclFeatureFlag Reserved + **/ + public void genSpdGuidDeclarations(String guidDeclEntryName, String guidDeclCName, String guidDeclGuid, + String guidDeclFeatureFlag) { + if (getSpdGuidDeclarations() == null) { + spdGuidDeclarations = psaRoot.addNewGuidDeclarations(); + } + + setSpdEntry(guidDeclEntryName, guidDeclCName, guidDeclGuid, guidDeclFeatureFlag, spdGuidDeclarations); + } + + /** + Generate protocol declaration element using parameters passed in. + + @param protocolDeclEntryName Name attribute of Entry element + @param protocolDeclCName CName element value + @param protocolDeclGuid Guid element value + @param protocolDeclFeatureFlag Reserved + **/ + public void genSpdProtocolDeclarations(String protocolDeclEntryName, String protocolDeclCName, + String protocolDeclGuid, String protocolDeclFeatureFlag) { + if (getSpdProtocolDeclarations() == null) { + spdProtocolDeclarations = psaRoot.addNewProtocolDeclarations(); + } + + setSpdEntry(protocolDeclEntryName, protocolDeclCName, protocolDeclGuid, protocolDeclFeatureFlag, + spdProtocolDeclarations); + } + + /** + Generate PPI declaration element using parameters passed in. + + @param ppiDeclEntryName Name attribute of Entry element + @param ppiDeclCName CName element value + @param ppiDeclGuid Guid element value + @param ppiDeclFeatureFlag Reserved + **/ + public void genSpdPpiDeclarations(String ppiDeclEntryName, String ppiDeclCName, String ppiDeclGuid, + String ppiDeclFeatureFlag) { + if (getSpdPpiDeclarations() == null) { + spdPpiDeclarations = psaRoot.addNewPpiDeclarations(); + } + + setSpdEntry(ppiDeclEntryName, ppiDeclCName, ppiDeclGuid, ppiDeclFeatureFlag, spdPpiDeclarations); + } + + /** + Set Entry contents using parameters passed in + + @param entryName Name attribute of Entry element + @param cName CName element value + @param guid Guid element value + @param featureFlag Reserved + @param parent The tag under which Entry element goes to + **/ + public void setSpdEntry(String entryName, String cName, String guid, String featureFlag, XmlObject parent) { + + if (parent instanceof GuidDeclarationsDocument.GuidDeclarations) { + GuidDeclarationsDocument.GuidDeclarations.Entry e = ((GuidDeclarations) parent).addNewEntry(); + e.setName(entryName); + e.setCName(cName); + e.addNewGuid().setStringValue(guid); + if (featureFlag != null) { + e.addNewFeatureFlag().setStringValue(featureFlag); + } + return; + } + if (parent instanceof ProtocolDeclarationsDocument.ProtocolDeclarations) { + ProtocolDeclarationsDocument.ProtocolDeclarations.Entry pe = ((ProtocolDeclarationsDocument.ProtocolDeclarations) parent) + .addNewEntry(); + pe.setName(entryName); + pe.setCName(cName); + pe.addNewGuid().setStringValue(guid); + if (featureFlag != null) { + pe.addNewFeatureFlag().setStringValue(featureFlag); + } + return; + } + if (parent instanceof PpiDeclarationsDocument.PpiDeclarations) { + PpiDeclarationsDocument.PpiDeclarations.Entry ppe = ((PpiDeclarationsDocument.PpiDeclarations) parent) + .addNewEntry(); + ppe.setName(entryName); + ppe.setCName(cName); + ppe.addNewGuid().setStringValue(guid); + if (featureFlag != null) { + ppe.addNewFeatureFlag().setStringValue(featureFlag); + } + return; + } + + return; + + } + + /** + Generate Pcd definition using parameters passed in + + @param pcdItemTypes ItemType attribute of PcdEntry element + @param cName C_Name element value + @param token Token element value + @param dataType DatumType element value + @param skuEnable Reserved + @param sku Reserved + @param maxSku Reserved + @param hiiEnable Reserved + @param varGuid Reserved + @param varName Reserved + @param defaultString DefaultString element value + **/ + public void genSpdPcdDefinitions(String pcdItemTypes, String cName, String token, String dataType, + String skuEnable, String sku, String maxSku, String hiiEnable, String varGuid, + String varName, String defaultString) { + if (getSpdPcdDefinitions() == null) { + spdPcdDefinitions = psaRoot.addNewPcdDefinitions(); + } + + setSpdPcdEntry(pcdItemTypes, cName, token, dataType, skuEnable, sku, maxSku, hiiEnable, varGuid, varName, + defaultString, spdPcdDefinitions); + } + + /** + Set Pcd entry contents under parent tag + + @param pcdItemTypes ItemType attribute of PcdEntry element + @param cName C_Name element value + @param token Token element value + @param dataType DatumType element value + @param skuEnable Reserved + @param sku Reserved + @param maxSku Reserved + @param hiiEnable Reserved + @param varGuid Reserved + @param varName Reserved + @param defaultString DefaultString element value + @param parent Tag under which PcdEntry goes to + **/ + public void setSpdPcdEntry(String pcdItemTypes, String cName, String token, String dataType, String skuEnable, + String sku, String maxSku, String hiiEnable, String varGuid, String varName, + String defaultString, XmlObject parent) { + + PcdDefinitionsDocument.PcdDefinitions.PcdEntry pe = ((PcdDefinitionsDocument.PcdDefinitions) parent) + .addNewPcdEntry(); + pe.setItemType(PcdItemTypes.Enum.forString(pcdItemTypes)); + pe.setCName(cName); + pe.setToken(token); + pe.setDatumType(PcdDataTypes.Enum.forString(dataType)); + pe.setDefaultValue(defaultString); + + } + + /** + Get PpiDeclarations element + + @return PpiDeclarationsDocument.PpiDeclarations + **/ + public PpiDeclarationsDocument.PpiDeclarations getSpdPpiDeclarations() { + if (spdPpiDeclarations == null) { + spdPpiDeclarations = psaRoot.getPpiDeclarations(); + } + return spdPpiDeclarations; + } + + /** + Get ProtocolDeclarations element + + @return ProtocolDeclarationsDocument.ProtocolDeclarations + **/ + public ProtocolDeclarationsDocument.ProtocolDeclarations getSpdProtocolDeclarations() { + if (spdProtocolDeclarations == null) { + spdProtocolDeclarations = psaRoot.getProtocolDeclarations(); + } + return spdProtocolDeclarations; + } + + /** + Get GuidDeclarations element + + @return GuidDeclarationsDocument.GuidDeclarations + **/ + public GuidDeclarationsDocument.GuidDeclarations getSpdGuidDeclarations() { + if (spdGuidDeclarations == null) { + spdGuidDeclarations = psaRoot.getGuidDeclarations(); + } + return spdGuidDeclarations; + } + + /** + Get PcdDefinitions element + + @return PcdDefinitionsDocument.PcdDefinitions + **/ + public PcdDefinitionsDocument.PcdDefinitions getSpdPcdDefinitions() { + if (spdPcdDefinitions == null) { + spdPcdDefinitions = psaRoot.getPcdDefinitions(); + } + return spdPcdDefinitions; + } + + /** + Get PackageHeaders element + + @return PackageHeadersDocument.PackageHeaders + **/ + public PackageHeadersDocument.PackageHeaders getSpdModHdrs() { + if (spdModHdrs == null) { + spdModHdrs = psaRoot.getPackageHeaders(); + } + return spdModHdrs; + } + + /** + Get MsaFiles element + + @return MsaFilesDocument.MsaFiles + **/ + public MsaFilesDocument.MsaFiles getSpdMsaFiles() { + if (spdMsaFiles == null) { + spdMsaFiles = psaRoot.getMsaFiles(); + } + return spdMsaFiles; + } + + /** + Get LibraryClassDeclarations element + + @return LibraryClassDeclarationsDocument.LibraryClassDeclarations + **/ + public LibraryClassDeclarationsDocument.LibraryClassDeclarations getSpdLibClassDeclarations() { + if (spdLibClassDeclarations == null) { + spdLibClassDeclarations = psaRoot.getLibraryClassDeclarations(); + } + return spdLibClassDeclarations; + } + + /** + Get SpdHeader element + + @return SpdHeaderDocument.SpdHeader + **/ + public SpdHeaderDocument.SpdHeader getSpdHdr() { + if (spdHdr == null) { + spdHdr = psaRoot.getSpdHeader(); + } + return spdHdr; + } + + /** + Get Abstract element under tag SpdHeader + + @return AbstractDocument.Abstract + **/ + public AbstractDocument.Abstract getSpdHdrAbs() { + if (spdHdrAbs == null) { + spdHdrAbs = getSpdHdr().getAbstract(); + } + return spdHdrAbs; + } + + /** + Set value to Abstract element + + @param abs The value set to Abstract element + **/ + public void setSpdHdrAbs(String abs) { + + if (getSpdHdrAbs() != null) { + getSpdHdrAbs().setStringValue(abs); + } else { + spdHdrAbs = getSpdHdr().addNewAbstract(); + spdHdrAbs.setStringValue(abs); + } + } + + /** + Set value to Copyright element + + @param cpRit The value set to Copyright element + **/ + public void setSpdHdrCpRit(String cpRit) { + + getSpdHdr().setCopyright(cpRit); + + } + + /** + Set value to Created element + + @param createDate The value set to Created element + **/ + public void setSpdHdrCreateDate(String createDate) { + + getSpdHdr().setCreated(createDate); + + } + + /** + Set value to Description element + + @param des The value set to Description element + **/ + public void setSpdHdrDes(String des) { + getSpdHdr().setDescription(des); + } + + /** + Get Guid element under SpdHdr + + @return GuidDocument.Guid + **/ + public GuidDocument.Guid getSpdHdrGuid() { + if (spdHdrGuid == null) { + spdHdrGuid = getSpdHdr().getGuid(); + } + return spdHdrGuid; + } + + /** + Set value to Guid element + + @param guid The value set to Guid element + **/ + public void setSpdHdrGuid(String guid) { + if (getSpdHdrGuid() != null) { + getSpdHdrGuid().setStringValue(guid); + } else { + spdHdrGuid = getSpdHdr().addNewGuid(); + spdHdrGuid.setStringValue(guid); + } + } + + /** + Get Version element under SpdHdr + + @return String + **/ + public String getSpdHdrVer() { + if (spdHdr != null) + return spdHdr.getVersion(); + else + return null; + } + + /** + Set value to Version element + + @param ver The value set to Version element + **/ + public void setSpdHdrVer(String ver) { + if (spdHdr != null) { + spdHdr.setVersion(ver); + } + + } + + /** + Get License element under SpdHdr + + @return LicenseDocument.License + **/ + public LicenseDocument.License getSpdHdrLicense() { + if (spdHdrLicense == null) { + spdHdrLicense = getSpdHdr().getLicense(); + } + return spdHdrLicense; + } + + /** + Set value to License element + + @param license The value set to License element + **/ + public void setSpdHdrLicense(String license) { + if (getSpdHdrLicense() != null) { + getSpdHdrLicense().setStringValue(license); + } else { + spdHdrLicense = getSpdHdr().addNewLicense(); + spdHdrLicense.setStringValue(license); + } + } + + /** + Reserved method + + @return + **/ + public OutputDirectoryDocument.OutputDirectory getSpdHdrOutDir() { + return spdHdrOutDir; + } + + /** + Reserved method + + @param outdir + **/ + public void setSpdHdrOutDir(String outdir) { + if (outdir == null) { + return; + } + if (getSpdHdrOutDir() != null) { + getSpdHdrOutDir().setStringValue(outdir); + } else { + spdHdrOutDir = getSpdHdr().addNewOutputDirectory(); + spdHdrOutDir.setStringValue(outdir); + } + } + + /** + Get PackageName element under SpdHdr + + @return PackageNameDocument.PackageName + **/ + public PackageNameDocument.PackageName getSpdHdrPkgName() { + if (spdHdrPkgName == null) { + spdHdrPkgName = getSpdHdr().getPackageName(); + } + return spdHdrPkgName; + } + + /** + Set value to PackageName element + + @param pkgName The value set to PackageName element + **/ + public void setSpdHdrPkgName(String pkgName) { + + if (getSpdHdrPkgName() != null) { + getSpdHdrPkgName().setStringValue(pkgName); + } else { + spdHdrPkgName = getSpdHdr().addNewPackageName(); + spdHdrPkgName.setStringValue(pkgName); + } + } + + /** + Reserved method + + @return SpecificationDocument.Specification + **/ + public SpecificationDocument.Specification getSpdHdrSpec() { + return spdHdrSpec; + } + + /** + Reserved method + + @param spec + **/ + public void setSpdHdrSpec(String spec) { + if (spec == null) { + return; + } + if (getSpdHdrSpec() != null) { + getSpdHdrSpec().setStringValue(spec); + } else { + spdHdrSpec = getSpdHdr().addNewSpecification(); + spdHdrSpec.setStringValue(spec); + } + } + + /** + Set value to PackageType element + + @param pkgType The value set to PackageType element + **/ + public void setSpdHdrPkgType(String pkgType) { + getSpdHdr().setPackageType(PackageType.Enum.forString(pkgType)); + } + + /** + Set value to ReadOnly element + + @param rdOnly The value set to ReadOnly element + **/ + public void setSpdHdrRdOnly(String rdOnly) { + + getSpdHdr().setReadOnly(new Boolean(rdOnly)); + } + + /** + Set value to RePackage element + + @param rePkg The value set to RePackage element + **/ + public void setSpdHdrRePkg(String rePkg) { + + getSpdHdr().setRePackage(new Boolean(rePkg)); + } + + /** + Set value to Updated element + + @param updateDate The value set to Updated element + **/ + public void setSpdHdrUpdateDate(String updateDate) { + getSpdHdr().setUpdated(updateDate); + } + + /** + Set value to URL element + + @param url The value set to URL element + **/ + public void setSpdHdrURL(String url) { + getSpdHdr().setURL(url); + } + + /** + Get xml file + + @return File + **/ + public File getFile() { + return file; + } + + /** + Set file + + @param file File with xml format + **/ + public void setFile(File file) { + this.file = file; + } + +} diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateAction.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateAction.java new file mode 100644 index 0000000000..a7ff0160e4 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateAction.java @@ -0,0 +1,328 @@ +/** @file + Java class UpdateAction is GUI for update spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Toolkit; + +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JFrame; +import java.awt.GridLayout; +import java.io.File; + +import javax.swing.JButton; + +/** +GUI for update spd file + +@since PackageEditor 1.0 +**/ +public class UpdateAction extends JFrame { + + static JFrame frame; + + private JPanel jContentPane = null; + + private JButton jButton = null; + + private JButton jButton1 = null; + + private JButton jButton2 = null; + + private JButton jButton3 = null; + + private JButton jButton4 = null; + + private JButton jButton5 = null; + + private JButton jButton6 = null; + + private JButton jButton7 = null; + + private SpdFileContents sfc = null; + + private JFrame pThis = null; // @jve:decl-index=0:visual-constraint="322,10" + + private JButton jButton8 = null; + + private JButton jButton9 = null; + + /** + This is the default constructor + **/ + public UpdateAction(SpdFileContents sfc) { + super(); + initialize(); + this.sfc = sfc; + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(300, 333); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setContentPane(getJContentPane()); + this.setTitle("Please Choose an Action"); + this.centerWindow(); + this.pThis = this; + pThis.setSize(new java.awt.Dimension(316,399)); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + GridLayout gridLayout = new GridLayout(); + gridLayout.setRows(10); + gridLayout.setColumns(1); + jContentPane = new JPanel(); + jContentPane.setLayout(gridLayout); + jContentPane.add(getJButton8(), null); + jContentPane.add(getJButton7(), null); + jContentPane.add(getJButton6(), null); + jContentPane.add(getJButton5(), null); + jContentPane.add(getJButton4(), null); + jContentPane.add(getJButton3(), null); + jContentPane.add(getJButton2(), null); + jContentPane.add(getJButton1(), null); + jContentPane.add(getJButton(), null); + jContentPane.add(getJButton9(), null); + } + return jContentPane; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setText("Save"); + jButton.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + JFileChooser chooser = new JFileChooser(sfc.getFile()); + chooser.setMultiSelectionEnabled(false); + + int retval = chooser.showSaveDialog(frame); + if (retval == JFileChooser.APPROVE_OPTION) { + try { + File theFile = chooser.getSelectedFile(); + if (theFile.exists()) { + int retVal = JOptionPane.showConfirmDialog(frame, "Are you sure to replace the exising one?", "File Exists", + JOptionPane.YES_NO_OPTION); + if (retVal == JOptionPane.NO_OPTION) { + return; + } + } + sfc.saveAs(theFile); + + } catch (Exception ee) { + System.out.println(ee.toString()); + } +// pThis.dispose(); + } + + } + }); + } + return jButton; + } + + /** + This method initializes jButton1 + + @return javax.swing.JButton + **/ + private JButton getJButton1() { + if (jButton1 == null) { + jButton1 = new JButton(); + jButton1.setText("Update PCD Information"); + jButton1.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new UpdatePCD(sfc), pThis); + } + }); + } + return jButton1; + } + + /** + This method initializes jButton2 + + @return javax.swing.JButton + **/ + private JButton getJButton2() { + if (jButton2 == null) { + jButton2 = new JButton(); + jButton2.setText("Update PPI Declarations"); + jButton2.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new UpdatePpi(sfc), pThis); + } + }); + } + return jButton2; + } + + /** + This method initializes jButton3 + + @return javax.swing.JButton + **/ + private JButton getJButton3() { + if (jButton3 == null) { + jButton3 = new JButton(); + jButton3.setText("Update Protocol Declarations"); + jButton3.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new UpdateProtocols(sfc), pThis); + } + }); + } + return jButton3; + } + + /** + This method initializes jButton4 + + @return javax.swing.JButton + **/ + private JButton getJButton4() { + if (jButton4 == null) { + jButton4 = new JButton(); + jButton4.setText("Update GUID Declarations"); + jButton4.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new UpdateGuids(sfc), pThis); + } + }); + } + return jButton4; + } + + /** + This method initializes jButton5 + + @return javax.swing.JButton + **/ + private JButton getJButton5() { + if (jButton5 == null) { + jButton5 = new JButton(); + jButton5.setText("Update Package Headers"); + jButton5.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new UpdatePkgHeader(sfc), pThis); + } + }); + } + return jButton5; + } + + /** + This method initializes jButton6 + + @return javax.swing.JButton + **/ + private JButton getJButton6() { + if (jButton6 == null) { + jButton6 = new JButton(); + jButton6.setText("Update MSA Files"); + jButton6.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new UpdateMsaFile(sfc), pThis); + } + }); + } + return jButton6; + } + + /** + This method initializes jButton7 + + @return javax.swing.JButton + **/ + private JButton getJButton7() { + if (jButton7 == null) { + jButton7 = new JButton(); + jButton7.setText("Update Library Classes"); + jButton7.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new UpdateLibraryClass(sfc), pThis); + } + }); + } + return jButton7; + } + + /** + This method initializes jButton8 + + @return javax.swing.JButton + **/ + private JButton getJButton8() { + if (jButton8 == null) { + jButton8 = new JButton(); + jButton8.setText("Update SPD Header"); + jButton8.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + ModalFrameUtil.showAsModal(new UpdateNew(sfc), pThis); + } + }); + } + return jButton8; + } + + private JButton getJButton9() { + if (jButton9 == null) { + jButton9 = new JButton(); + jButton9.setText("Done"); + jButton9.addMouseListener(new java.awt.event.MouseAdapter() { + public void mouseClicked(java.awt.event.MouseEvent e) { + + pThis.dispose(); + + } + }); + } + return jButton9; + } + +} // @jve:decl-index=0:visual-constraint="104,41" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateGuids.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateGuids.java new file mode 100644 index 0000000000..294549c9c1 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateGuids.java @@ -0,0 +1,226 @@ +/** @file + Java class UpdateGuids is GUI for update GUID declarations in spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import javax.swing.JPanel; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; + +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.*; + +import org.tianocore.common.Tools; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; + +/** + GUI for update GUID declarations in spd file + + @since PackageEditor 1.0 +**/ +public class UpdateGuids extends JFrame implements ActionListener { + + private JPanel jContentPane = null; + + private JScrollPane jScrollPane = null; + + private JTable jTable = null; + + private SpdFileContents sfc = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private DefaultTableModel model = null; + + private JButton jButton = null; + + /** + This is the default constructor + **/ + public UpdateGuids(SpdFileContents sfc) { + super(); + this.sfc = sfc; + initialize(); + + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + + } + if (arg0.getSource() == jButton) { + String[] o = { "", "", "" }; + model.addRow(o); + } + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(604, 553); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setTitle("Update GUID Declarations"); + this.setContentPane(getJContentPane()); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButton(), null); + } + return jContentPane; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(38, 45, 453, 419)); + jScrollPane.setViewportView(getJTable()); + } + return jScrollPane; + } + + /** + This method initializes jTable + + @return javax.swing.JTable + **/ + private JTable getJTable() { + if (jTable == null) { + model = new DefaultTableModel(); + jTable = new JTable(model); + jTable.setRowHeight(20); + model.addColumn("Name"); + model.addColumn("C_Name"); + model.addColumn("GUID"); + if (sfc.getSpdGuidDeclarationCount() == 0) { + return jTable; + } + // + // initialize table using SpdFileContents object + // + String[][] saa = new String[sfc.getSpdGuidDeclarationCount()][3]; + sfc.getSpdGuidDeclarations(saa); + int i = 0; + while (i < saa.length) { + model.addRow(saa[i]); + i++; + } + + } + return jTable; + } + + /** + Remove original GUID declarations before saving updated ones + **/ + protected void save() { + sfc.removeSpdGuidDeclaration(); + int rowCount = model.getRowCount(); + int i = 0; + + while (i < rowCount) { + String name = null; + if (model.getValueAt(i, 0) != null) { + name = model.getValueAt(i, 0).toString(); + } + String cName = null; + if (model.getValueAt(i, 1) != null) { + cName = model.getValueAt(i, 1).toString(); + } + String guid = null; + if (model.getValueAt(i, 2) != null) { + guid = model.getValueAt(i, 2).toString(); + } + sfc.genSpdGuidDeclarations(name, cName, guid, null); + i++; + } + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("Ok"); + jButtonOk.setSize(new java.awt.Dimension(84, 20)); + jButtonOk.setLocation(new java.awt.Point(316, 486)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(82, 20)); + jButtonCancel.setLocation(new java.awt.Point(411, 486)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setBounds(new java.awt.Rectangle(219, 487, 78, 18)); + jButton.setText("Insert"); + jButton.addActionListener(this); + } + return jButton; + } +} // @jve:decl-index=0:visual-constraint="11,7" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateLibraryClass.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateLibraryClass.java new file mode 100644 index 0000000000..8abca63b7f --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateLibraryClass.java @@ -0,0 +1,221 @@ +/** @file + Java class UpdateLibraryClass is GUI for update library class in spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import javax.swing.JPanel; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; + +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.*; + +import org.tianocore.common.Tools; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; + +/** + GUI for update library class in spd file + + @since PackageEditor 1.0 +**/ +public class UpdateLibraryClass extends JFrame implements ActionListener { + + private JPanel jContentPane = null; + + private JScrollPane jScrollPane = null; + + private JTable jTable = null; + + private SpdFileContents sfc = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private DefaultTableModel model = null; + + private JButton jButton = null; + + /** + This is the default constructor + **/ + public UpdateLibraryClass(SpdFileContents sfc) { + super(); + this.sfc = sfc; + initialize(); + + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + + } + + if (arg0.getSource() == jButton) { + String[] o = { "", "" }; + model.addRow(o); + } + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(604, 553); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setTitle("Update Library Class Declarations"); + this.setContentPane(getJContentPane()); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButton(), null); + } + return jContentPane; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(38, 45, 453, 419)); + jScrollPane.setViewportView(getJTable()); + } + return jScrollPane; + } + + /** + This method initializes jTable + + @return javax.swing.JTable + **/ + private JTable getJTable() { + if (jTable == null) { + model = new DefaultTableModel(); + jTable = new JTable(model); + jTable.setRowHeight(20); + model.addColumn("LibraryClass"); + model.addColumn("IncludeHeader"); + if (sfc.getSpdLibClassDeclarationCount() == 0) { + return jTable; + } + // + // initialize table using SpdFileContents object + // + String[][] saa = new String[sfc.getSpdLibClassDeclarationCount()][2]; + sfc.getSpdLibClassDeclarations(saa); + int i = 0; + while (i < saa.length) { + model.addRow(saa[i]); + i++; + } + + } + return jTable; + } + + /** + Remove original library classes before saving updated ones + **/ + protected void save() { + sfc.removeSpdLibClass(); + int rowCount = model.getRowCount(); + int i = 0; + while (i < rowCount) { + String libClass = null; + if (model.getValueAt(i, 0) != null) { + libClass = model.getValueAt(i, 0).toString(); + } + String headerFile = null; + if (model.getValueAt(i, 1) != null) { + headerFile = model.getValueAt(i, 1).toString(); + } + sfc.genSpdLibClassDeclarations(libClass, null, headerFile, null, null, null, null, null, null, null); + i++; + } + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("Ok"); + jButtonOk.setSize(new java.awt.Dimension(84, 20)); + jButtonOk.setLocation(new java.awt.Point(316, 486)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(82, 20)); + jButtonCancel.setLocation(new java.awt.Point(411, 486)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setBounds(new java.awt.Rectangle(221, 486, 79, 19)); + jButton.setText("Insert"); + jButton.addActionListener(this); + } + return jButton; + } +} // @jve:decl-index=0:visual-constraint="11,7" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateMsaFile.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateMsaFile.java new file mode 100644 index 0000000000..d06b24fdae --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateMsaFile.java @@ -0,0 +1,217 @@ +/** @file + Java class UpdateLibraryClass is GUI for msa files in spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import javax.swing.JPanel; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; + +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.*; + +import org.tianocore.common.Tools; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +/** + GUI for msa files in spd file + + @since PackageEditor 1.0 +**/ +public class UpdateMsaFile extends JFrame implements ActionListener { + + private JPanel jContentPane = null; + + private JScrollPane jScrollPane = null; + + private JTable jTable = null; + + private SpdFileContents sfc = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private DefaultTableModel model = null; + + private JButton jButton = null; + + /** + This is the default constructor + **/ + public UpdateMsaFile(SpdFileContents sfc) { + super(); + this.sfc = sfc; + initialize(); + + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + + } + if (arg0.getSource() == jButton) { + String[] o = { "" }; + model.addRow(o); + } + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(604, 553); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setTitle("Update MSA Files"); + this.setContentPane(getJContentPane()); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButton(), null); + } + return jContentPane; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(38, 45, 453, 419)); + jScrollPane.setViewportView(getJTable()); + } + return jScrollPane; + } + + /** + This method initializes jTable + + @return javax.swing.JTable + **/ + private JTable getJTable() { + if (jTable == null) { + model = new DefaultTableModel(); + jTable = new JTable(model); + jTable.setRowHeight(20); + model.addColumn("MSA File"); + + if (sfc.getSpdMsaFileCount() == 0) { + return jTable; + } + // + // initialize table using SpdFileContents object + // + String[][] saa = new String[sfc.getSpdMsaFileCount()][1]; + sfc.getSpdMsaFiles(saa); + int i = 0; + while (i < saa.length) { + model.addRow(saa[i]); + i++; + } + } + return jTable; + } + + /** + Remove original Msa files before saving updated ones + **/ + protected void save() { + + sfc.removeSpdMsaFile(); + int rowCount = jTable.getRowCount(); + int i = 0; + while (i < rowCount) { + String msaFile = null; + if (jTable.getValueAt(i, 0) != null) { + msaFile = jTable.getValueAt(i, 0).toString(); + } + sfc.genSpdMsaFiles(msaFile, null); + i++; + } + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("Ok"); + jButtonOk.setSize(new java.awt.Dimension(84, 20)); + jButtonOk.setLocation(new java.awt.Point(316, 486)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(82, 20)); + jButtonCancel.setLocation(new java.awt.Point(411, 486)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setBounds(new java.awt.Rectangle(219, 486, 79, 19)); + jButton.setText("Insert"); + jButton.addActionListener(this); + } + return jButton; + } + +} // @jve:decl-index=0:visual-constraint="11,7" + diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateNew.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateNew.java new file mode 100644 index 0000000000..46ba748784 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateNew.java @@ -0,0 +1,573 @@ +/** @file + Java class UpdateNew is GUI for SpdHeader in spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import java.awt.Dimension; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.text.SimpleDateFormat; +import java.util.Date; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; +import javax.swing.JTextArea; +import javax.swing.JScrollPane; + +import javax.swing.JComboBox; + +import org.tianocore.common.Tools; +import org.tianocore.packaging.common.ui.StarLabel; + +/** + GUI for update SpdHeader contents + + @since PackageEditor 1.0 +**/ +public class UpdateNew extends JFrame implements ActionListener { + + private JPanel jContentPane = null; // @jve:decl-index=0:visual-constraint="128,4" + + private JLabel jLabelBaseName = null; + + private JTextField jTextFieldBaseName = null; + + private JLabel jLabelGuid = null; + + private JTextField jTextFieldGuid = null; + + private JLabel jLabelVersion = null; + + private JTextField jTextFieldVersion = null; + + private JButton jButtonGenerateGuid = null; + + private JLabel jLabelLicense = null; + + private JTextArea jTextAreaLicense = null; + + private JLabel jLabelCopyright = null; + + private JTextArea jTextAreaCopyright = null; + + private JLabel jLabelDescription = null; + + private JTextArea jTextAreaDescription = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private JScrollPane jScrollPaneLicense = null; + + private JScrollPane jScrollPaneCopyright = null; + + private JScrollPane jScrollPaneDescription = null; + + private JLabel jLabelAbstract = null; + + private JTextField jTextFieldAbstract = null; + + private JLabel jLabelModuleType = null; + + private JLabel jLabelCompontentType = null; + + private JComboBox jComboBox1 = null; + + private JComboBox jComboBoxModuleType = null; + + private StarLabel jStarLabel1 = null; + + private StarLabel jStarLabel2 = null; + + private StarLabel jStarLabel3 = null; + + private StarLabel jStarLabel4 = null; + + private StarLabel jStarLabel5 = null; + + private StarLabel jStarLabel6 = null; + + private StarLabel jStarLabel7 = null; + + private StarLabel jStarLabel8 = null; + + private JLabel jLabelURL = null; + + private JTextField jTextFieldAbstractURL = null; + + private JLabel jLabel = null; + + private JComboBox jComboBox = null; + + private SpdFileContents sfc = null; + + private String createTime = null; + + /** + This method initializes this + + **/ + private void initialize() { + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + + } + + /** + This method initializes jTextFieldBaseName + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldBaseName() { + if (jTextFieldBaseName == null) { + jTextFieldBaseName = new JTextField(); + jTextFieldBaseName.setBounds(new java.awt.Rectangle(160, 10, 320, 20)); + } + return jTextFieldBaseName; + } + + /** + This method initializes jTextFieldGuid + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldGuid() { + if (jTextFieldGuid == null) { + jTextFieldGuid = new JTextField(); + jTextFieldGuid.setBounds(new java.awt.Rectangle(160, 35, 240, 20)); + } + return jTextFieldGuid; + } + + /** + This method initializes jTextFieldVersion + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldVersion() { + if (jTextFieldVersion == null) { + jTextFieldVersion = new JTextField(); + jTextFieldVersion.setBounds(new java.awt.Rectangle(160, 60, 320, 20)); + } + return jTextFieldVersion; + } + + /** + This method initializes jButtonGenerateGuid + + @return javax.swing.JButton + **/ + private JButton getJButtonGenerateGuid() { + if (jButtonGenerateGuid == null) { + jButtonGenerateGuid = new JButton(); + jButtonGenerateGuid.setBounds(new java.awt.Rectangle(405, 35, 75, 20)); + jButtonGenerateGuid.setText("GEN"); + jButtonGenerateGuid.addActionListener(this); + } + return jButtonGenerateGuid; + } + + /** + This method initializes jTextAreaLicense + + @return javax.swing.JTextArea + **/ + private JTextArea getJTextAreaLicense() { + if (jTextAreaLicense == null) { + jTextAreaLicense = new JTextArea(); + jTextAreaLicense.setText(""); + jTextAreaLicense.setLineWrap(true); + } + return jTextAreaLicense; + } + + /** + This method initializes jTextAreaCopyright + + @return javax.swing.JTextArea + **/ + private JTextArea getJTextAreaCopyright() { + if (jTextAreaCopyright == null) { + jTextAreaCopyright = new JTextArea(); + jTextAreaCopyright.setLineWrap(true); + } + return jTextAreaCopyright; + } + + /** + This method initializes jTextAreaDescription + + @return javax.swing.JTextArea + **/ + private JTextArea getJTextAreaDescription() { + if (jTextAreaDescription == null) { + jTextAreaDescription = new JTextArea(); + jTextAreaDescription.setLineWrap(true); + } + return jTextAreaDescription; + } + + /** + This method initializes jButtonNext + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("OK"); + jButtonOk.setBounds(new java.awt.Rectangle(290, 481, 90, 20)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setBounds(new java.awt.Rectangle(390, 481, 90, 20)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPaneLicense() { + if (jScrollPaneLicense == null) { + jScrollPaneLicense = new JScrollPane(); + jScrollPaneLicense.setBounds(new java.awt.Rectangle(160, 85, 320, 80)); + jScrollPaneLicense.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + jScrollPaneLicense.setViewportView(getJTextAreaLicense()); + } + return jScrollPaneLicense; + } + + /** + This method initializes jScrollPane1 + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPaneCopyright() { + if (jScrollPaneCopyright == null) { + jScrollPaneCopyright = new JScrollPane(); + jScrollPaneCopyright.setBounds(new java.awt.Rectangle(160,170,320,26)); + jScrollPaneCopyright.setViewportView(getJTextAreaCopyright()); + jScrollPaneCopyright.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + } + return jScrollPaneCopyright; + } + + /** + This method initializes jScrollPane2 + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPaneDescription() { + if (jScrollPaneDescription == null) { + jScrollPaneDescription = new JScrollPane(); + jScrollPaneDescription.setBounds(new java.awt.Rectangle(160, 322, 320, 80)); + jScrollPaneDescription.setViewportView(getJTextAreaDescription()); + jScrollPaneDescription.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + } + return jScrollPaneDescription; + } + + /** + This method initializes jTextFieldAbstract + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldAbstract() { + if (jTextFieldAbstract == null) { + jTextFieldAbstract = new JTextField(); + jTextFieldAbstract.setBounds(new java.awt.Rectangle(161,216,318,73)); + } + return jTextFieldAbstract; + } + + /** + This method initializes jComboBoxCompontentType + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBox1() { + if (jComboBox1 == null) { + jComboBox1 = new JComboBox(); + jComboBox1.setBounds(new java.awt.Rectangle(160, 465, 91, 20)); + } + return jComboBox1; + } + + /** + This method initializes jComboBoxModuleType + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBoxModuleType() { + if (jComboBoxModuleType == null) { + jComboBoxModuleType = new JComboBox(); + jComboBoxModuleType.setBounds(new java.awt.Rectangle(160, 440, 91, 20)); + } + return jComboBoxModuleType; + } + + /** + This method initializes jTextFieldAbstractURL + + @return javax.swing.JTextField + **/ + private JTextField getJTextFieldAbstractURL() { + if (jTextFieldAbstractURL == null) { + jTextFieldAbstractURL = new JTextField(); + jTextFieldAbstractURL.setBounds(new java.awt.Rectangle(159, 414, 320, 20)); + } + return jTextFieldAbstractURL; + } + + public UpdateNew(SpdFileContents sfc) { + super(); + initialize(); + init(); + this.setVisible(true); + this.sfc = sfc; + initShow(); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow(int intWidth, int intHeight) { + Dimension d = Toolkit.getDefaultToolkit().getScreenSize(); + this.setLocation((d.width - intWidth) / 2, (d.height - intHeight) / 2); + } + + /** + Start the window at the center of screen + + **/ + protected void centerWindow() { + centerWindow(this.getSize().width, this.getSize().height); + } + + /** + This method initializes this + + @return void + **/ + private void init() { + this.setSize(500, 560); + this.setContentPane(getJContentPane()); + this.setTitle("SPD File Header"); + this.centerWindow(); + //this.getRootPane().setDefaultButton(jButtonOk); + initFrame(); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jLabel = new JLabel(); + jLabel.setBounds(new java.awt.Rectangle(15, 490, 140, 21)); + jLabel.setText("Re-Package"); + jLabelURL = new JLabel(); + jLabelURL.setBounds(new java.awt.Rectangle(16, 414, 25, 20)); + jLabelURL.setText("URL"); + jLabelCompontentType = new JLabel(); + jLabelCompontentType.setBounds(new java.awt.Rectangle(15, 465, 140, 20)); + jLabelCompontentType.setText("Read Only"); + jLabelModuleType = new JLabel(); + jLabelModuleType.setBounds(new java.awt.Rectangle(15, 440, 140, 20)); + jLabelModuleType.setText("Package Type"); + jLabelAbstract = new JLabel(); + jLabelAbstract.setBounds(new java.awt.Rectangle(17,216,140,20)); + jLabelAbstract.setText("Abstract"); + jLabelDescription = new JLabel(); + jLabelDescription.setText("Description"); + jLabelDescription.setBounds(new java.awt.Rectangle(16, 325, 140, 20)); + jLabelCopyright = new JLabel(); + jLabelCopyright.setText("Copyright"); + jLabelCopyright.setBounds(new java.awt.Rectangle(15, 171, 140, 20)); + jLabelLicense = new JLabel(); + jLabelLicense.setText("License"); + jLabelLicense.setBounds(new java.awt.Rectangle(15, 85, 140, 20)); + jLabelVersion = new JLabel(); + jLabelVersion.setText("Version"); + jLabelVersion.setBounds(new java.awt.Rectangle(15, 60, 140, 20)); + jLabelGuid = new JLabel(); + jLabelGuid.setPreferredSize(new java.awt.Dimension(25, 15)); + jLabelGuid.setBounds(new java.awt.Rectangle(15, 35, 140, 20)); + jLabelGuid.setText("Guid"); + jLabelBaseName = new JLabel(); + jLabelBaseName.setText("Package Name"); + jLabelBaseName.setBounds(new java.awt.Rectangle(15, 10, 140, 20)); + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.setLocation(new java.awt.Point(0, 0)); + jContentPane.setSize(new java.awt.Dimension(500, 524)); + jContentPane.add(jLabelBaseName, null); + jContentPane.add(getJTextFieldBaseName(), null); + jContentPane.add(jLabelGuid, null); + jContentPane.add(getJTextFieldGuid(), null); + jContentPane.add(jLabelVersion, null); + jContentPane.add(getJTextFieldVersion(), null); + jContentPane.add(getJButtonGenerateGuid(), null); + jContentPane.add(jLabelLicense, null); + jContentPane.add(jLabelCopyright, null); + jContentPane.add(jLabelDescription, null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJScrollPaneLicense(), null); + jContentPane.add(getJScrollPaneCopyright(), null); + jContentPane.add(getJScrollPaneDescription(), null); + jContentPane.add(jLabelAbstract, null); + jContentPane.add(getJTextFieldAbstract(), null); + jContentPane.add(jLabelModuleType, null); + jContentPane.add(jLabelCompontentType, null); + jContentPane.add(getJComboBox1(), null); + jContentPane.add(getJComboBoxModuleType(), null); + + jStarLabel1 = new StarLabel(); + jStarLabel1.setLocation(new java.awt.Point(0, 10)); + jStarLabel2 = new StarLabel(); + jStarLabel2.setLocation(new java.awt.Point(0, 35)); + jStarLabel3 = new StarLabel(); + jStarLabel3.setLocation(new java.awt.Point(0, 60)); + jStarLabel4 = new StarLabel(); + jStarLabel4.setLocation(new java.awt.Point(0, 85)); + jStarLabel5 = new StarLabel(); + jStarLabel5.setLocation(new java.awt.Point(0, 171)); + jStarLabel6 = new StarLabel(); + jStarLabel6.setLocation(new java.awt.Point(1, 325)); + jStarLabel7 = new StarLabel(); + jStarLabel7.setLocation(new java.awt.Point(2,216)); + jStarLabel8 = new StarLabel(); + jStarLabel8.setLocation(new java.awt.Point(0, 440)); + + jContentPane.add(jStarLabel1, null); + jContentPane.add(jStarLabel2, null); + jContentPane.add(jStarLabel3, null); + jContentPane.add(jStarLabel4, null); + jContentPane.add(jStarLabel5, null); + jContentPane.add(jStarLabel6, null); + jContentPane.add(jStarLabel7, null); + jContentPane.add(jStarLabel8, null); + jContentPane.add(jLabelURL, null); + jContentPane.add(getJTextFieldAbstractURL(), null); + jContentPane.add(jLabel, null); + jContentPane.add(getJComboBox(), null); + } + return jContentPane; + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + + } + if (arg0.getSource() == jButtonGenerateGuid) { + jTextFieldGuid.setText(Tools.generateUuidString()); + } + } + + /** + Save all components of Msa Header, update time modified. + + **/ + private void save() { + // sfc.removeSpdHdr(); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm"); + Date date = new Date(); + sfc.genSpdHeader(jTextFieldBaseName.getText(), jTextFieldGuid.getText(), jTextFieldVersion.getText(), + jTextFieldAbstract.getText(), jTextAreaDescription.getText(), jTextAreaCopyright.getText(), + jTextAreaLicense.getText(), createTime, format.format(date), jTextFieldAbstractURL.getText(), + jComboBoxModuleType.getSelectedItem().toString(), jComboBox1.getSelectedItem().toString(), + jComboBox.getSelectedItem().toString(), null, null); + // ModalFrameUtil.showAsModal(new PackageAction(sfc), pThis); + } + + /** + This method initializes module type and compontent type + + **/ + private void initFrame() { + jComboBoxModuleType.addItem("SOURCE"); + jComboBoxModuleType.addItem("BINARY"); + jComboBoxModuleType.addItem("MIXED"); + + jComboBox1.addItem("true"); + jComboBox1.addItem("false"); + + jComboBox.addItem("false"); + jComboBox.addItem("true"); + + } + + /** + Display original SpdHeader contents during init + **/ + private void initShow() { + String[] s = new String[12]; + + sfc.getSpdHdrDetails(s); + jTextFieldBaseName.setText(s[0]); + jTextFieldGuid.setText(s[1]); + jTextFieldVersion.setText(s[2]); + jTextFieldAbstract.setText(s[3]); + jTextAreaDescription.setText(s[4]); + jTextAreaCopyright.setText(s[5]); + jTextAreaLicense.setText(s[6]); + createTime = s[7]; + jTextFieldAbstractURL.setText(s[8]); + jComboBoxModuleType.setSelectedItem(s[9]); + jComboBox1.setSelectedIndex(s[10].equals("true") ? 0 : 1); + jComboBox.setSelectedIndex(s[11].equals("true") ? 0 : 1); + + } + + /** + This method initializes jComboBox + + @return javax.swing.JComboBox + **/ + private JComboBox getJComboBox() { + if (jComboBox == null) { + jComboBox = new JComboBox(); + jComboBox.setBounds(new java.awt.Rectangle(160, 490, 90, 20)); + } + return jComboBox; + } + +} // @jve:decl-index=0:visual-constraint="38,-22" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdatePCD.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdatePCD.java new file mode 100644 index 0000000000..61b48d4aa5 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdatePCD.java @@ -0,0 +1,256 @@ +/** @file + Java class UpdatePCD is GUI for update PCD definitions in spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JPanel; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; + +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.*; + +import org.tianocore.common.Tools; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; + +/** + GUI for update PCD definitions in spd file + + @since PackageEditor 1.0 +**/ +public class UpdatePCD extends JFrame implements ActionListener { + + private JPanel jContentPane = null; + + private SpdFileContents sfc = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private DefaultTableModel model = null; + + private String[][] saa = null; + + private JScrollPane jScrollPane = null; + + private JTable jTable = null; + + private JButton jButton = null; + + /** + This is the default constructor + **/ + public UpdatePCD(SpdFileContents sfc) { + super(); + this.sfc = sfc; + initialize(); + + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + + } + if (arg0.getSource() == jButton) { + String[] o = { "FEATURE_FLAG", "", "", "UINT8", "0" }; + model.addRow(o); + } + + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(916, 486); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setTitle("Update PCD Definitions"); + this.setContentPane(getJContentPane()); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButton(), null); + } + return jContentPane; + } + + /** + Remove original Pcd definitions before saving updated ones + **/ + protected void save() { + sfc.removeSpdPcdDefinition(); + int rowCount = model.getRowCount(); + int i = 0; + while (i < rowCount) { + String cName = null; + if (model.getValueAt(i, 1) != null) { + cName = model.getValueAt(i, 1).toString(); + } + String token = null; + if (model.getValueAt(i, 2) != null) { + token = model.getValueAt(i, 2).toString(); + } + String defaultVal = null; + if (model.getValueAt(i, 4) != null) { + defaultVal = model.getValueAt(i, 4).toString(); + } + sfc.genSpdPcdDefinitions(model.getValueAt(i, 0).toString(), cName, token, + model.getValueAt(i, 3).toString(), null, null, null, null, null, null, defaultVal); + i++; + } + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("Ok"); + jButtonOk.setSize(new java.awt.Dimension(84, 20)); + jButtonOk.setLocation(new java.awt.Point(605, 404)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(82, 20)); + jButtonCancel.setLocation(new java.awt.Point(712, 404)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setHorizontalScrollBarPolicy(javax.swing.JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + jScrollPane.setBounds(new java.awt.Rectangle(51, 62, 782, 304)); + jScrollPane.setViewportView(getJTable2()); + } + return jScrollPane; + } + + /** + This method initializes jTable + + @return javax.swing.JTable + **/ + private JTable getJTable2() { + if (jTable == null) { + model = new DefaultTableModel(); + jTable = new JTable(model); + jTable.setRowHeight(20); + model.addColumn("ItemType"); + model.addColumn("C_Name"); + model.addColumn("Token"); + model.addColumn("DataType"); + model.addColumn("DefaultValue"); + // + // Using combobox to display ItemType in table + // + JComboBox jComboBoxItemType = new JComboBox(); + jComboBoxItemType.addItem("FEATURE_FLAG"); + jComboBoxItemType.addItem("FIXED_AT_BUILD"); + jComboBoxItemType.addItem("PATCHABLE_IN_MODULE"); + jComboBoxItemType.addItem("DYNAMIC"); + jComboBoxItemType.addItem("DYNAMIC_EX"); + TableColumn itemTypeColumn = jTable.getColumnModel().getColumn(0); + itemTypeColumn.setCellEditor(new DefaultCellEditor(jComboBoxItemType)); + // + // Using combobox to display data type in table + // + JComboBox jComboBoxDataType = new JComboBox(); + jComboBoxDataType.addItem("UINT8"); + jComboBoxDataType.addItem("UINT16"); + jComboBoxDataType.addItem("UINT32"); + jComboBoxDataType.addItem("UINT64"); + jComboBoxDataType.addItem("VOID*"); + jComboBoxDataType.addItem("BOOLEAN"); + TableColumn dataTypeColumn = jTable.getColumnModel().getColumn(3); + dataTypeColumn.setCellEditor(new DefaultCellEditor(jComboBoxDataType)); + + if (sfc.getSpdPcdDefinitionCount() == 0) { + + return jTable; + } + saa = new String[sfc.getSpdPcdDefinitionCount()][5]; + sfc.getSpdPcdDefinitions(saa); + int i = 0; + while (i < saa.length) { + model.addRow(saa[i]); + i++; + } + + } + return jTable; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setBounds(new java.awt.Rectangle(499, 404, 77, 20)); + jButton.setText("Insert"); + jButton.addActionListener(this); + } + return jButton; + } +} // @jve:decl-index=0:visual-constraint="11,7" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdatePkgHeader.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdatePkgHeader.java new file mode 100644 index 0000000000..cccc323ee8 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdatePkgHeader.java @@ -0,0 +1,236 @@ +/** @file + Java class UpdatePkgHeader is GUI for update Package Header in spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import javax.swing.DefaultCellEditor; +import javax.swing.JComboBox; +import javax.swing.JPanel; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; + +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.*; + +import org.tianocore.common.Tools; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; + +/** + GUI for update Package Header in spd file + + @since PackageEditor 1.0 +**/ +public class UpdatePkgHeader extends JFrame implements ActionListener { + + private JPanel jContentPane = null; + + private JScrollPane jScrollPane = null; + + private JTable jTable = null; + + private SpdFileContents sfc = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private DefaultTableModel model = null; + + private JButton jButton = null; + + /** + This is the default constructor + **/ + public UpdatePkgHeader(SpdFileContents sfc) { + super(); + this.sfc = sfc; + initialize(); + + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + + } + + if (arg0.getSource() == jButton) { + String[] o = { "BASE", "" }; + model.addRow(o); + } + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(604, 553); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setTitle("Update Package Headers"); + this.setContentPane(getJContentPane()); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButton(), null); + } + return jContentPane; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(38, 45, 453, 419)); + jScrollPane.setViewportView(getJTable()); + } + return jScrollPane; + } + + /** + This method initializes jTable + + @return javax.swing.JTable + **/ + private JTable getJTable() { + if (jTable == null) { + model = new DefaultTableModel(); + jTable = new JTable(model); + jTable.setRowHeight(20); + model.addColumn("ModuleType"); + model.addColumn("IncludeHeader"); + // + // Using combobox to display ModuleType in table + // + TableColumn typeColumn = jTable.getColumnModel().getColumn(0); + JComboBox jComboBoxSelect = new JComboBox(); + jComboBoxSelect.addItem("BASE"); + jComboBoxSelect.addItem("SEC"); + jComboBoxSelect.addItem("PEI_CORE"); + jComboBoxSelect.addItem("PEIM"); + jComboBoxSelect.addItem("DXE_CORE"); + jComboBoxSelect.addItem("DXE_DRIVER"); + jComboBoxSelect.addItem("DXE_RUNTIME_DRIVER"); + jComboBoxSelect.addItem("DXE_SAL_DRIVER"); + jComboBoxSelect.addItem("DXE_SMM_DRIVER"); + jComboBoxSelect.addItem("TOOLS"); + jComboBoxSelect.addItem("UEFI_DRIVER"); + jComboBoxSelect.addItem("UEFI_APPLICATION"); + jComboBoxSelect.addItem("USER_DEFINED"); + typeColumn.setCellEditor(new DefaultCellEditor(jComboBoxSelect)); + + if (sfc.getSpdPackageHeaderCount() == 0) { + return jTable; + } + String[][] saa = new String[sfc.getSpdPackageHeaderCount()][2]; + sfc.getSpdPackageHeaders(saa); + int i = 0; + while (i < saa.length) { + model.addRow(saa[i]); + i++; + } + + } + return jTable; + } + + /** + Remove original package headers before saving updated ones + **/ + protected void save() { + sfc.removeSpdPkgHeader(); + int rowCount = model.getRowCount(); + int i = 0; + while (i < rowCount) { + String headFile = null; + if (model.getValueAt(i, 1) != null) { + headFile = model.getValueAt(i, 1).toString(); + } + sfc.genSpdModuleHeaders(model.getValueAt(i, 0).toString(), headFile, null, null, null, null, null, null); + i++; + } + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("Ok"); + jButtonOk.setSize(new java.awt.Dimension(84, 20)); + jButtonOk.setLocation(new java.awt.Point(316, 486)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(82, 20)); + jButtonCancel.setLocation(new java.awt.Point(411, 486)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setBounds(new java.awt.Rectangle(220, 486, 85, 20)); + jButton.setText("Insert"); + jButton.addActionListener(this); + } + return jButton; + } +} // @jve:decl-index=0:visual-constraint="11,7" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdatePpi.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdatePpi.java new file mode 100644 index 0000000000..da1dc686fd --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdatePpi.java @@ -0,0 +1,226 @@ +/** @file + Java class UpdatePpi is GUI for update Ppi declarations in spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import javax.swing.JPanel; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; + +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.*; + +import org.tianocore.common.Tools; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; + +/** + GUI for update Ppi declarations in spd file. + + @since PackageEditor 1.0 +**/ +public class UpdatePpi extends JFrame implements ActionListener { + + private JPanel jContentPane = null; + + private JScrollPane jScrollPane = null; + + private JTable jTable = null; + + private SpdFileContents sfc = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private DefaultTableModel model = null; + + private JButton jButton = null; + + /** + This is the default constructor + **/ + public UpdatePpi(SpdFileContents sfc) { + super(); + this.sfc = sfc; + initialize(); + + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + + } + + if (arg0.getSource() == jButton) { + String[] o = { "", "", "" }; + model.addRow(o); + } + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(604, 553); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setTitle("Update PPI Declarations"); + this.setContentPane(getJContentPane()); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButton(), null); + } + return jContentPane; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(38, 45, 453, 419)); + jScrollPane.setViewportView(getJTable()); + } + return jScrollPane; + } + + /** + This method initializes jTable + + @return javax.swing.JTable + **/ + private JTable getJTable() { + if (jTable == null) { + model = new DefaultTableModel(); + jTable = new JTable(model); + jTable.setRowHeight(20); + model.addColumn("Name"); + model.addColumn("C_Name"); + model.addColumn("GUID"); + // + // initialize table using SpdFileContents object + // + if (sfc.getSpdPpiDeclarationCount() == 0) { + return jTable; + } + String[][] saa = new String[sfc.getSpdPpiDeclarationCount()][3]; + sfc.getSpdPpiDeclarations(saa); + int i = 0; + while (i < saa.length) { + model.addRow(saa[i]); + i++; + } + + } + return jTable; + } + + /** + Remove original ppi declarations before saving updated ones + **/ + protected void save() { + sfc.removeSpdPpiDeclaration(); + int rowCount = model.getRowCount(); + int i = 0; + while (i < rowCount) { + String name = null; + if (model.getValueAt(i, 0) != null) { + name = model.getValueAt(i, 0).toString(); + } + String cName = null; + if (model.getValueAt(i, 1) != null) { + cName = model.getValueAt(i, 1).toString(); + } + String guid = null; + if (model.getValueAt(i, 2) != null) { + guid = model.getValueAt(i, 2).toString(); + } + sfc.genSpdPpiDeclarations(name, cName, guid, null); + i++; + } + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("Ok"); + jButtonOk.setSize(new java.awt.Dimension(84, 20)); + jButtonOk.setLocation(new java.awt.Point(316, 486)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(82, 20)); + jButtonCancel.setLocation(new java.awt.Point(411, 486)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setBounds(new java.awt.Rectangle(224, 488, 72, 18)); + jButton.setText("Insert"); + jButton.addActionListener(this); + } + return jButton; + } +} // @jve:decl-index=0:visual-constraint="11,7" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateProtocols.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateProtocols.java new file mode 100644 index 0000000000..614cf82d60 --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/UpdateProtocols.java @@ -0,0 +1,226 @@ +/** @file + Java class UpdateProtocols is GUI for update protocol declarations in spd file. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging; + +import javax.swing.JPanel; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.JButton; + +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.table.*; + +import org.tianocore.common.Tools; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; + +/** + GUI for update protocol declarations in spd file + + @since PackageEditor 1.0 +**/ +public class UpdateProtocols extends JFrame implements ActionListener { + + private JPanel jContentPane = null; + + private JScrollPane jScrollPane = null; + + private JTable jTable = null; + + private SpdFileContents sfc = null; + + private JButton jButtonOk = null; + + private JButton jButtonCancel = null; + + private DefaultTableModel model = null; + + private JButton jButton = null; + + /** + This is the default constructor + **/ + public UpdateProtocols(SpdFileContents sfc) { + super(); + this.sfc = sfc; + initialize(); + + } + + public void actionPerformed(ActionEvent arg0) { + if (arg0.getSource() == jButtonOk) { + this.save(); + this.dispose(); + + } + if (arg0.getSource() == jButtonCancel) { + this.dispose(); + + } + + if (arg0.getSource() == jButton) { + String[] o = { "", "", "" }; + model.addRow(o); + } + } + + /** + This method initializes this + + @return void + **/ + private void initialize() { + this.setSize(604, 553); + this.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + this.setTitle("Update Protocol Declarations"); + this.setContentPane(getJContentPane()); + } + + /** + This method initializes jContentPane + + @return javax.swing.JPanel + **/ + private JPanel getJContentPane() { + if (jContentPane == null) { + jContentPane = new JPanel(); + jContentPane.setLayout(null); + jContentPane.add(getJScrollPane(), null); + jContentPane.add(getJButtonOk(), null); + jContentPane.add(getJButtonCancel(), null); + jContentPane.add(getJButton(), null); + } + return jContentPane; + } + + /** + This method initializes jScrollPane + + @return javax.swing.JScrollPane + **/ + private JScrollPane getJScrollPane() { + if (jScrollPane == null) { + jScrollPane = new JScrollPane(); + jScrollPane.setBounds(new java.awt.Rectangle(38, 45, 453, 419)); + jScrollPane.setViewportView(getJTable()); + } + return jScrollPane; + } + + /** + This method initializes jTable + + @return javax.swing.JTable + **/ + private JTable getJTable() { + if (jTable == null) { + model = new DefaultTableModel(); + jTable = new JTable(model); + jTable.setRowHeight(20); + model.addColumn("Name"); + model.addColumn("C_Name"); + model.addColumn("GUID"); + // + // initialize table using SpdFileContents object + // + if (sfc.getSpdProtocolDeclarationCount() == 0) { + return jTable; + } + String[][] saa = new String[sfc.getSpdProtocolDeclarationCount()][3]; + sfc.getSpdProtocolDeclarations(saa); + int i = 0; + while (i < saa.length) { + model.addRow(saa[i]); + i++; + } + + } + return jTable; + } + + /** + Remove original protocol declarations before saving updated ones + **/ + protected void save() { + sfc.removeSpdProtocolDeclaration(); + int rowCount = model.getRowCount(); + int i = 0; + while (i < rowCount) { + String name = null; + if (model.getValueAt(i, 0) != null) { + name = model.getValueAt(i, 0).toString(); + } + String cName = null; + if (model.getValueAt(i, 1) != null) { + cName = model.getValueAt(i, 1).toString(); + } + String guid = null; + if (model.getValueAt(i, 2) != null) { + guid = model.getValueAt(i, 2).toString(); + } + sfc.genSpdProtocolDeclarations(name, cName, guid, null); + i++; + } + } + + /** + This method initializes jButtonOk + + @return javax.swing.JButton + **/ + private JButton getJButtonOk() { + if (jButtonOk == null) { + jButtonOk = new JButton(); + jButtonOk.setText("Ok"); + jButtonOk.setSize(new java.awt.Dimension(84, 20)); + jButtonOk.setLocation(new java.awt.Point(316, 486)); + jButtonOk.addActionListener(this); + } + return jButtonOk; + } + + /** + This method initializes jButtonCancel + + @return javax.swing.JButton + **/ + private JButton getJButtonCancel() { + if (jButtonCancel == null) { + jButtonCancel = new JButton(); + jButtonCancel.setText("Cancel"); + jButtonCancel.setSize(new java.awt.Dimension(82, 20)); + jButtonCancel.setLocation(new java.awt.Point(411, 486)); + jButtonCancel.addActionListener(this); + } + return jButtonCancel; + } + + /** + This method initializes jButton + + @return javax.swing.JButton + **/ + private JButton getJButton() { + if (jButton == null) { + jButton = new JButton(); + jButton.setBounds(new java.awt.Rectangle(232, 486, 71, 19)); + jButton.setText("Insert"); + jButton.addActionListener(this); + } + return jButton; + } +} // @jve:decl-index=0:visual-constraint="11,7" diff --git a/Tools/Source/PackageEditor/src/org/tianocore/packaging/common/ui/StarLabel.java b/Tools/Source/PackageEditor/src/org/tianocore/packaging/common/ui/StarLabel.java new file mode 100644 index 0000000000..ad19472e5d --- /dev/null +++ b/Tools/Source/PackageEditor/src/org/tianocore/packaging/common/ui/StarLabel.java @@ -0,0 +1,41 @@ +/** @file + Java class StarLabel is used to create star label. + +Copyright (c) 2006, 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. +**/ +package org.tianocore.packaging.common.ui; + +import javax.swing.JLabel; + +/** + Derived from JLabel class to have a red star on it. + + @since PackageEditor 1.0 +**/ +public class StarLabel extends JLabel{ + /** + * This is the default constructor + */ + public StarLabel() { + super(); + init(); + } + + /** + Create a label with red star * appear on it + **/ + private void init() { + this.setText("*"); + this.setSize(new java.awt.Dimension(10,20)); + this.setForeground(java.awt.Color.red); + this.setFont(new java.awt.Font("DialogInput", java.awt.Font.BOLD, 14)); + this.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); + } +} diff --git a/Tools/Source/Prototype/Auto.java b/Tools/Source/Prototype/Auto.java new file mode 100644 index 0000000000..07d609406e --- /dev/null +++ b/Tools/Source/Prototype/Auto.java @@ -0,0 +1,8 @@ +import java.util.*; + +public class Auto +{ + public static void main(String args[]) + { + } +} diff --git a/Tools/Source/Prototype/Component.java b/Tools/Source/Prototype/Component.java new file mode 100644 index 0000000000..4e4e3a178c --- /dev/null +++ b/Tools/Source/Prototype/Component.java @@ -0,0 +1,43 @@ +import java.util.*; + +public class Component extends Module +{ + Component() + { + } + Component(String n) + { + name=n; + } + String name; + + // These are the libs we want to build with. + public Set buildLibs; + + public String name() { return name; } + + public boolean autoBuild() + { + // buildLibs must contain a list of libInstances. We need to check that + // These libs meet certain criterea. + if(!duplicateLibClasses(buildLibs).isEmpty()) + { + // Error: The lib instance implement the same lib twice. + return false; + } + if(! libClassesProduced(buildLibs).containsAll(consumesLibClasses)) + { + // We can not cover the libclasses consumed with these instances. + return false; + } + getConstructorOrder(buildLibs); + getDestructorOrder(buildLibs); + + // Get PPI, Protocol, GUID, PCDs from the lib instances. These are all simple unions of + // the corresponding sets in the modules. There is no ordering needed. + // TODO + + return true; + } + +} diff --git a/Tools/Source/Prototype/DAG.java b/Tools/Source/Prototype/DAG.java new file mode 100644 index 0000000000..1edad27887 --- /dev/null +++ b/Tools/Source/Prototype/DAG.java @@ -0,0 +1,176 @@ +import java.util.*; + +// A directed Acyclic Graph class. The main purpose is to provide a set of nodes +// and the dependency relations between them. Then ask for a topological sort of +// the nodes. + +public class DAG +{ + // Constructor. + DAG() + { + children = new HashMap>(); + } + + public Set nodes() { return children.keySet(); } + public Set children(Node parent) { return children.get(parent); } + + // Add the relations from a compatible DAG to this one. + public void add(DAG newDag) + { + for(Node parent : newDag.children.keySet()) + { + children.put(parent, newDag.children(parent)); + } + } + + // The central data structure is a one-to-many map. Each node is + // treated as a parent. It is mapped to a list of its children. Leaf + // nodes are also treated as parents and map to an empty list of + // children. + Map> children; + + public void remove(Collection nodes) + { + // Remove it as a parent + for(Node node : nodes) + { + children.remove(node); + } + + for(Set childlist : children.values()) + { + // Remove it as a child + childlist.removeAll(nodes); + } + } + + // Remove every occurrence of node from the DAG. + public void remove(Node node) + { + // Remove it as a parent + children.remove(node); + + for(Set childlist : children.values()) + { + // Remove it as a child + childlist.remove(node); + } + } + + // Return true iff parent is a direct parent of child. + public boolean directDepends(Node parent, Node child) + { + return children.containsKey(parent) ? + children(parent).contains(child) : + false; + } + + // Return true iff parent is a direct or indirect parent of child. + // This is the transitive closure of the dependency relation. + public boolean depends(Node parent, Node child) + { + if(!children.containsKey(parent)) + { + return false; + } + if( directDepends(parent, child) ) + { + return true; + } + else + { + for(Node descendent : children(parent) ) + { + // Recursively call depends() to compute the transitive closure of + // the relation. + if(depends(descendent, child)) + { + return true; + } + } + return false; + } + } + + // Add a parent child relation to the dag. Fail if there is already + // a dependency from the child to the parent. This implies a cycle. + // Our invariant is that the DAG must never contain a cycle. That + // way it lives up to its name. + public void add(Node parent, Node child) + { + if(depends(child, parent)) + { + System.out.format("Error: There is a cycle from %s to %s.\n", parent, child); + return; + } + if(children.containsKey(parent)) + { + children(parent).add(child); + } + else + { + Set cs = new HashSet(); + cs.add(child); + children.put(parent, cs); + } + if(!children.containsKey(child)) + { + children.put(child,new HashSet()); + } + } + + // Perform a topological sort on the DAG. + public List sort() + { + // Make an ordered list to hold the topo sort. + List sorted = new LinkedList(); + + // We add the leaves to the beginning of the list until + // the sorted list contains all the nodes in the DAG. + while(!sorted.containsAll(nodes())) + { + // Ignoring the ones we have found, what are the leaves of this + // DAG? + Set leaves = leaves(sorted); + // Put the new leaves at the beginning of the list. + sorted.addAll(0, leaves); + } + return sorted; + } + + // Return the set of nodes that have no children. Pretend + // the nodes in the exclude list are not present. + public Set leaves(Collection exclude) + { + Set leaves=new HashSet(); + for(Node parent : children.keySet()) + { + if(exclude.contains(parent)) + { + continue; + } + // If the children of parent are a subset of the exclude set, + // then parent is a leaf. + if(exclude.containsAll(children(parent))) + { + leaves.add(parent); + } + } + return leaves; + } + + // Return the set of nodes that have no children. + public Set leaves() + { + Set leaves=new HashSet(); + for(Node parent : children.keySet()) + { + if( children(parent).isEmpty()) + { + leaves.add(parent); + } + } + return leaves; + } +} diff --git a/Tools/Source/Prototype/Database.java b/Tools/Source/Prototype/Database.java new file mode 100644 index 0000000000..bc0a7b0c44 --- /dev/null +++ b/Tools/Source/Prototype/Database.java @@ -0,0 +1,14 @@ +import java.util.*; + +public class Database +{ + Database() + { + } + Database(String n) + { + name=n; + } + public String name; + Map> packages; +} diff --git a/Tools/Source/Prototype/GuidDecl.java b/Tools/Source/Prototype/GuidDecl.java new file mode 100644 index 0000000000..7aa928f9ed --- /dev/null +++ b/Tools/Source/Prototype/GuidDecl.java @@ -0,0 +1,16 @@ +import java.util.*; + +public class GuidDecl +{ + GuidDecl() + { + } + GuidDecl(String n) + { + name=n; + } + public String name; + public String cName; + public String guid; + public String name() { return name; } +} diff --git a/Tools/Source/Prototype/LibClass.java b/Tools/Source/Prototype/LibClass.java new file mode 100644 index 0000000000..c49f7ddb36 --- /dev/null +++ b/Tools/Source/Prototype/LibClass.java @@ -0,0 +1,14 @@ +import java.util.*; + +public class LibClass +{ + LibClass() + { + } + LibClass(String n) + { + name=n; + } + String name; + public String name() { return name; } +} diff --git a/Tools/Source/Prototype/LibInst.java b/Tools/Source/Prototype/LibInst.java new file mode 100644 index 0000000000..3e4dac32f3 --- /dev/null +++ b/Tools/Source/Prototype/LibInst.java @@ -0,0 +1,22 @@ +import java.util.*; + +public class LibInst extends Module +{ + LibInst() + { + } + LibInst(String n) + { + name=n; + } + + public Set producesLibClasses; + + public String constructorName, destructorName; + + public boolean autoBuild() + { + // A simple compile, without link. + return true; + } +} diff --git a/Tools/Source/Prototype/Module.java b/Tools/Source/Prototype/Module.java new file mode 100644 index 0000000000..79557f4de2 --- /dev/null +++ b/Tools/Source/Prototype/Module.java @@ -0,0 +1,178 @@ +import java.util.*; + +public class Module +{ + Module() + { + } + Module(String n) + { + name=n; + } + String name; + + public String name() { return name; } + + public Set consumesLibClasses; + + // The set of packages that this module depends upon. + Set packageDepends; + public Set packageDeps() { return packageDepends; } + + public boolean autoBuild() + { + // This should be implemented in the derived class. + return true; + } + + // Make sure that each class in this set of libclasses is declared in one + // of the packages that this module depends on. + public boolean validateLibClasses(Set classes) + { + for(LibClass lc : classes) + { + // Assume we will not find it. + boolean found = false; + + for(Package p : packageDepends) + { + if(p.libClassDecls.contains(lc)) + { + found=true; + break; + } + } + if(found == false) + { + // Error: This LibClass is not found in any of our Packages. + return false; + } + } + // Well, we never came up empty handed, so it looks good. + return true; + } + + public Set libClassesProduced(Collection instances) + { + // given a set of lib instances, what is the set of lib classes produced? + + Set classes = new HashSet(); + + for(LibInst li : instances) + { + classes.addAll(li.producesLibClasses); + } + return classes; + } + + // Search the given set of lib instance to see if, among them, they + // produce the same LibClass more than once. + public Set duplicateLibClasses(Set libs) + { + // Return true iff each class produced is produced only once. + + List classes = new LinkedList(); + Set dups = new HashSet(); + + for(LibInst li : libs) + { + classes.addAll(li.producesLibClasses); + } + + for(LibClass c : classes) + { + for(LibClass inner : classes) + { + if(c.equals(inner)) + { + dups.add(c); + } + } + } + return dups; + } + + public Set getProducers(LibClass lc, Set libs) + { + // Return the subset of the given libs that produce this LibClass. + + Set producers = new HashSet(); + + for(LibInst li : libs) + { + if(li.producesLibClasses.contains(lc)) + { + producers.add(li); + } + } + return producers; + } + + // + // The central dependency relationship between library instances is as follows. + // A LibInst "A" depends upon LibInst "B" if, and only if, there exists a LibClass + // "C" such that A consumes C and B produces C. This is the partial order over which + // we construct a Directed Acyclic Graph (DAG). The DAG can be used to detect + // cycles in the depends relation (which are illegal) and it can be used to implement a + // topological sort which is a total ordering over LibInstances. This total order on + // lib instances is what is needed in order to call the constructors and destructors + // in the proper sequence. + // + public DAG makeDAG(Set libs) + { + DAG dag = new DAG(); + + if(duplicateLibClasses(libs).size()>0) + { + System.out.format("Error: The library instances implement at least one " + + "library class more than once.\n"); + } + + for(LibInst consumer : libs) + { + // Find all the producers for each LC that li consumes. + for(LibClass lc : consumer.consumesLibClasses ) + { + Set producers = getProducers(lc, libs); + if(producers.isEmpty()) + { + System.out.format("Error: Unmet dependency libclass:%s .", lc.name() ); + return null; + } + + // There is exactly one lib inst that produces this class. + LibInst producer = producers.iterator().next(); + + // Now we are ready to add the dependency to the dag. It will flag + // circular dependencies for us. + dag.add(consumer, producer); + } + } + return dag; + } + + // As you evaluate each node in the graph (starting with the module node), you + // must call the constructors for all the child nodes before you call the + // constructor for the current node. + public List getConstructorOrder(Set libs) + { + List rev = new LinkedList(); + + for(LibInst li : getDestructorOrder(libs)) + rev.add(0, li); + + return rev; + } + + // The destructor order is exactly the reverese of the constructor order. + // As you evaluate each node in the graph (starting with the module node), you + // must call the destructor for the all the parent nodes before calling the + // destructors for the current node, and then call the destructors for all the + // child nodes. + public List getDestructorOrder(Set libs) + { + DAG dag = makeDAG(libs); + + return dag.sort(); + } +} diff --git a/Tools/Source/Prototype/Package.java b/Tools/Source/Prototype/Package.java new file mode 100644 index 0000000000..dac0802d6c --- /dev/null +++ b/Tools/Source/Prototype/Package.java @@ -0,0 +1,44 @@ +import java.util.*; + +public class Package +{ + Package() + { + } + Package(String n) + { + name=n; + } + public String name; + + public Set libClassDecls; + public Set guidDecls; + public Set ppiDecls; + public Set protocolDecls; + public Set modules; + public Set depends; + + public void genBuild() + { + for(Module m : modules) + { + m.autoBuild(); + } + } + + // Figure out what this package depends on based on what the modules + // depend on. + public void calculateDependencies() + { + depends = new HashSet(); + for(Module m : modules) + { + depends.addAll(m.packageDeps()); + } + } + + public void makeJar(String name) {}; + + public void addModule(Module m) {}; + public void removeModule(Module m) {}; +} diff --git a/Tools/Source/Prototype/PpiDecl.java b/Tools/Source/Prototype/PpiDecl.java new file mode 100644 index 0000000000..581fb13f76 --- /dev/null +++ b/Tools/Source/Prototype/PpiDecl.java @@ -0,0 +1,16 @@ +import java.util.*; + +public class PpiDecl +{ + PpiDecl() + { + } + PpiDecl(String n) + { + name=n; + } + public String name; + public String cName; + public String guid; + public String name() { return name; } +} diff --git a/Tools/Source/Prototype/ProtocolDecl.java b/Tools/Source/Prototype/ProtocolDecl.java new file mode 100644 index 0000000000..62a45e6fef --- /dev/null +++ b/Tools/Source/Prototype/ProtocolDecl.java @@ -0,0 +1,16 @@ +import java.util.*; + +public class ProtocolDecl +{ + ProtocolDecl() + { + } + ProtocolDecl(String n) + { + name=n; + } + public String name; + public String cName; + public String guid; + public String name() { return name; } +} diff --git a/Tools/Source/Prototype/TSort.java b/Tools/Source/Prototype/TSort.java new file mode 100644 index 0000000000..88765e17fc --- /dev/null +++ b/Tools/Source/Prototype/TSort.java @@ -0,0 +1,24 @@ +import java.util.*; + +public class TSort +{ + public static void main(String args[]) + { + DAG dag = new DAG(); + int i; + + if(args.length % 2==1) + { + System.out.println("Error: Odd number of elements"); + return; + } + for(i=0; i< args.length/2; i++) + { + dag.add(args[i*2], args[i*2+1]); + // System.out.println(pair.left); + // System.out.println(pair.right); + } + System.out.println(dag.sort().toString()); + System.out.println(dag.sort().toString()); + } +} diff --git a/Tools/Source/Prototype/build.xml b/Tools/Source/Prototype/build.xml new file mode 100644 index 0000000000..de4cde9248 --- /dev/null +++ b/Tools/Source/Prototype/build.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + diff --git a/Tools/Source/SurfaceArea/build.xml b/Tools/Source/SurfaceArea/build.xml new file mode 100644 index 0000000000..415958a4d7 --- /dev/null +++ b/Tools/Source/SurfaceArea/build.xml @@ -0,0 +1,203 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
]]> +
+ +
+ + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
diff --git a/Tools/Source/TianoTools/Common/CommonLib.c b/Tools/Source/TianoTools/Common/CommonLib.c new file mode 100644 index 0000000000..e2b12b4d27 --- /dev/null +++ b/Tools/Source/TianoTools/Common/CommonLib.c @@ -0,0 +1,495 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + CommonLib.c + +Abstract: + + Common Library Functions + +--*/ + +#include +#include +#include +#include "CommonLib.h" + +VOID +PeiZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + Set Buffer to zero for Size bytes. + +Arguments: + + Buffer - Memory to set. + + Size - Number of bytes to set + +Returns: + + None + +--*/ +{ + INT8 *Ptr; + + Ptr = Buffer; + while (Size--) { + *(Ptr++) = 0; + } +} + +VOID +PeiCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + + Destination8 = Destination; + Source8 = Source; + while (Length--) { + *(Destination8++) = *(Source8++); + } +} + +VOID +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + PeiZeroMem (Buffer, Size); +} + +VOID +CopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +{ + PeiCopyMem (Destination, Source, Length); +} + +INTN +CompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +/*++ + +Routine Description: + + Compares to GUIDs + +Arguments: + + Guid1 - guid to compare + Guid2 - guid to compare + +Returns: + = 0 if Guid1 == Guid2 + != 0 if Guid1 != Guid2 + +--*/ +{ + INT32 *g1; + INT32 *g2; + INT32 r; + + // + // Compare 32 bits at a time + // + g1 = (INT32 *) Guid1; + g2 = (INT32 *) Guid2; + + r = g1[0] - g2[0]; + r |= g1[1] - g2[1]; + r |= g1[2] - g2[2]; + r |= g1[3] - g2[3]; + + return r; +} + +EFI_STATUS +GetFileImage ( + IN CHAR8 *InputFileName, + OUT CHAR8 **InputFileImage, + OUT UINT32 *BytesRead + ) +/*++ + +Routine Description: + + This function opens a file and reads it into a memory buffer. The function + will allocate the memory buffer and returns the size of the buffer. + +Arguments: + + InputFileName The name of the file to read. + InputFileImage A pointer to the memory buffer. + BytesRead The size of the memory buffer. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + EFI_OUT_OF_RESOURCES No resource to complete operations. + +--*/ +{ + FILE *InputFile; + UINT32 FileSize; + + // + // Verify input parameters. + // + if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Open the file and copy contents into a memory buffer. + // + // + // Open the file + // + InputFile = fopen (InputFileName, "rb"); + if (InputFile == NULL) { + printf ("ERROR: Could not open input file \"%s\".\n", InputFileName); + return EFI_ABORTED; + } + // + // Go to the end so that we can determine the file size + // + if (fseek (InputFile, 0, SEEK_END)) { + printf ("ERROR: System error reading input file \"%s\".\n", InputFileName); + fclose (InputFile); + return EFI_ABORTED; + } + // + // Get the file size + // + FileSize = ftell (InputFile); + if (FileSize == -1) { + printf ("ERROR: System error parsing input file \"%s\".\n", InputFileName); + fclose (InputFile); + return EFI_ABORTED; + } + // + // Allocate a buffer + // + *InputFileImage = malloc (FileSize); + if (*InputFileImage == NULL) { + fclose (InputFile); + return EFI_OUT_OF_RESOURCES; + } + // + // Reset to the beginning of the file + // + if (fseek (InputFile, 0, SEEK_SET)) { + printf ("ERROR: System error reading input file \"%s\".\n", InputFileName); + fclose (InputFile); + free (*InputFileImage); + *InputFileImage = NULL; + return EFI_ABORTED; + } + // + // Read all of the file contents. + // + *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile); + if (*BytesRead != sizeof (UINT8) * FileSize) { + printf ("ERROR: Reading file \"%s\"%i.\n", InputFileName); + fclose (InputFile); + free (*InputFileImage); + *InputFileImage = NULL; + return EFI_ABORTED; + } + // + // Close the file + // + fclose (InputFile); + + return EFI_SUCCESS; +} + +UINT8 +CalculateChecksum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + This function calculates the value needed for a valid UINT8 checksum + +Arguments: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Returns: + + The 8 bit checksum value needed. + +--*/ +{ + return (UINT8) (0x100 - CalculateSum8 (Buffer, Size)); +} + +UINT8 +CalculateSum8 ( + IN UINT8 *Buffer, + IN UINT32 Size + ) +/*++ + +Routine Description:: + + This function calculates the UINT8 sum for the requested region. + +Arguments: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Returns: + + The 8 bit checksum value needed. + +--*/ +{ + UINTN Index; + UINT8 Sum; + + Sum = 0; + + // + // Perform the byte sum for buffer + // + for (Index = 0; Index < Size; Index++) { + Sum = (UINT8) (Sum + Buffer[Index]); + } + + return Sum; +} + +UINT16 +CalculateChecksum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description:: + + This function calculates the value needed for a valid UINT16 checksum + +Arguments: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Returns: + + The 16 bit checksum value needed. + +--*/ +{ + return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size)); +} + +UINT16 +CalculateSum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + This function calculates the UINT16 sum for the requested region. + +Arguments: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Returns: + + The 16 bit checksum + +--*/ +{ + UINTN Index; + UINT16 Sum; + + Sum = 0; + + // + // Perform the word sum for buffer + // + for (Index = 0; Index < Size; Index++) { + Sum = (UINT16) (Sum + Buffer[Index]); + } + + return (UINT16) Sum; +} + +EFI_STATUS +PrintGuid ( + IN EFI_GUID *Guid + ) +/*++ + +Routine Description: + + This function prints a GUID to STDOUT. + +Arguments: + + Guid Pointer to a GUID to print. + +Returns: + + EFI_SUCCESS The GUID was printed. + EFI_INVALID_PARAMETER The input was NULL. + +--*/ +{ + if (Guid == NULL) { + printf ("ERROR: PrintGuid called with a NULL value.\n"); + return EFI_INVALID_PARAMETER; + } + + printf ( + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7] + ); + return EFI_SUCCESS; +} + +EFI_STATUS +PrintGuidToBuffer ( + IN EFI_GUID *Guid, + IN OUT UINT8 *Buffer, + IN UINT32 BufferLen, + IN BOOLEAN Uppercase + ) +/*++ + +Routine Description: + + This function prints a GUID to a buffer + +Arguments: + + Guid - Pointer to a GUID to print. + Buffer - Pointer to a user-provided buffer to print to + BufferLen - Size of the Buffer + Uppercase - If use upper case. + +Returns: + + EFI_SUCCESS The GUID was printed. + EFI_INVALID_PARAMETER The input was NULL. + EFI_BUFFER_TOO_SMALL The input buffer was not big enough + +--*/ +{ + if (Guid == NULL) { + printf ("ERROR: PrintGuidToBuffer() called with a NULL value\n"); + return EFI_INVALID_PARAMETER; + } + + if (BufferLen < PRINTED_GUID_BUFFER_SIZE) { + printf ("ERORR: PrintGuidToBuffer() called with invalid buffer size\n"); + return EFI_BUFFER_TOO_SMALL; + } + + if (Uppercase) { + sprintf ( + Buffer, + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7] + ); + } else { + sprintf ( + Buffer, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7] + ); + } + + return EFI_SUCCESS; +} diff --git a/Tools/Source/TianoTools/Common/CommonLib.h b/Tools/Source/TianoTools/Common/CommonLib.h new file mode 100644 index 0000000000..7bc233134d --- /dev/null +++ b/Tools/Source/TianoTools/Common/CommonLib.h @@ -0,0 +1,131 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + CommonLib.h + +Abstract: + + Common library assistance routines. + +--*/ + +#ifndef _EFI_COMMON_LIB_H +#define _EFI_COMMON_LIB_H + +/* +#include "TianoCommon.h" +#include "TianoCommon.h" +#include "PeiHob.h" +*/ +#include +#include + +#ifndef _MAX_PATH +#define _MAX_PATH 500 +#endif + +#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination +// +// Function declarations +// +VOID +PeiZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +; + +VOID +PeiCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +; + +VOID +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +; + +VOID +CopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +; + +INTN +CompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +; + +EFI_STATUS +GetFileImage ( + IN CHAR8 *InputFileName, + OUT CHAR8 **InputFileImage, + OUT UINT32 *BytesRead + ) +; + +UINT8 +CalculateChecksum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +; + +UINT8 +CalculateSum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +; + +UINT16 +CalculateChecksum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ) +; + +UINT16 +CalculateSum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ) +; + +EFI_STATUS +PrintGuid ( + IN EFI_GUID *Guid + ) +; + +#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination +EFI_STATUS +PrintGuidToBuffer ( + IN EFI_GUID *Guid, + IN OUT UINT8 *Buffer, + IN UINT32 BufferLen, + IN BOOLEAN Uppercase + ) +; + + +#endif diff --git a/Tools/Source/TianoTools/Common/Crc32.c b/Tools/Source/TianoTools/Common/Crc32.c new file mode 100644 index 0000000000..4ae5eb486b --- /dev/null +++ b/Tools/Source/TianoTools/Common/Crc32.c @@ -0,0 +1,326 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + crc32.c + +Abstract: + + CalcuateCrc32 routine. + +--*/ + +#include +#include "Crc32.h" + +UINT32 mCrcTable[256] = { + 0x00000000, + 0x77073096, + 0xEE0E612C, + 0x990951BA, + 0x076DC419, + 0x706AF48F, + 0xE963A535, + 0x9E6495A3, + 0x0EDB8832, + 0x79DCB8A4, + 0xE0D5E91E, + 0x97D2D988, + 0x09B64C2B, + 0x7EB17CBD, + 0xE7B82D07, + 0x90BF1D91, + 0x1DB71064, + 0x6AB020F2, + 0xF3B97148, + 0x84BE41DE, + 0x1ADAD47D, + 0x6DDDE4EB, + 0xF4D4B551, + 0x83D385C7, + 0x136C9856, + 0x646BA8C0, + 0xFD62F97A, + 0x8A65C9EC, + 0x14015C4F, + 0x63066CD9, + 0xFA0F3D63, + 0x8D080DF5, + 0x3B6E20C8, + 0x4C69105E, + 0xD56041E4, + 0xA2677172, + 0x3C03E4D1, + 0x4B04D447, + 0xD20D85FD, + 0xA50AB56B, + 0x35B5A8FA, + 0x42B2986C, + 0xDBBBC9D6, + 0xACBCF940, + 0x32D86CE3, + 0x45DF5C75, + 0xDCD60DCF, + 0xABD13D59, + 0x26D930AC, + 0x51DE003A, + 0xC8D75180, + 0xBFD06116, + 0x21B4F4B5, + 0x56B3C423, + 0xCFBA9599, + 0xB8BDA50F, + 0x2802B89E, + 0x5F058808, + 0xC60CD9B2, + 0xB10BE924, + 0x2F6F7C87, + 0x58684C11, + 0xC1611DAB, + 0xB6662D3D, + 0x76DC4190, + 0x01DB7106, + 0x98D220BC, + 0xEFD5102A, + 0x71B18589, + 0x06B6B51F, + 0x9FBFE4A5, + 0xE8B8D433, + 0x7807C9A2, + 0x0F00F934, + 0x9609A88E, + 0xE10E9818, + 0x7F6A0DBB, + 0x086D3D2D, + 0x91646C97, + 0xE6635C01, + 0x6B6B51F4, + 0x1C6C6162, + 0x856530D8, + 0xF262004E, + 0x6C0695ED, + 0x1B01A57B, + 0x8208F4C1, + 0xF50FC457, + 0x65B0D9C6, + 0x12B7E950, + 0x8BBEB8EA, + 0xFCB9887C, + 0x62DD1DDF, + 0x15DA2D49, + 0x8CD37CF3, + 0xFBD44C65, + 0x4DB26158, + 0x3AB551CE, + 0xA3BC0074, + 0xD4BB30E2, + 0x4ADFA541, + 0x3DD895D7, + 0xA4D1C46D, + 0xD3D6F4FB, + 0x4369E96A, + 0x346ED9FC, + 0xAD678846, + 0xDA60B8D0, + 0x44042D73, + 0x33031DE5, + 0xAA0A4C5F, + 0xDD0D7CC9, + 0x5005713C, + 0x270241AA, + 0xBE0B1010, + 0xC90C2086, + 0x5768B525, + 0x206F85B3, + 0xB966D409, + 0xCE61E49F, + 0x5EDEF90E, + 0x29D9C998, + 0xB0D09822, + 0xC7D7A8B4, + 0x59B33D17, + 0x2EB40D81, + 0xB7BD5C3B, + 0xC0BA6CAD, + 0xEDB88320, + 0x9ABFB3B6, + 0x03B6E20C, + 0x74B1D29A, + 0xEAD54739, + 0x9DD277AF, + 0x04DB2615, + 0x73DC1683, + 0xE3630B12, + 0x94643B84, + 0x0D6D6A3E, + 0x7A6A5AA8, + 0xE40ECF0B, + 0x9309FF9D, + 0x0A00AE27, + 0x7D079EB1, + 0xF00F9344, + 0x8708A3D2, + 0x1E01F268, + 0x6906C2FE, + 0xF762575D, + 0x806567CB, + 0x196C3671, + 0x6E6B06E7, + 0xFED41B76, + 0x89D32BE0, + 0x10DA7A5A, + 0x67DD4ACC, + 0xF9B9DF6F, + 0x8EBEEFF9, + 0x17B7BE43, + 0x60B08ED5, + 0xD6D6A3E8, + 0xA1D1937E, + 0x38D8C2C4, + 0x4FDFF252, + 0xD1BB67F1, + 0xA6BC5767, + 0x3FB506DD, + 0x48B2364B, + 0xD80D2BDA, + 0xAF0A1B4C, + 0x36034AF6, + 0x41047A60, + 0xDF60EFC3, + 0xA867DF55, + 0x316E8EEF, + 0x4669BE79, + 0xCB61B38C, + 0xBC66831A, + 0x256FD2A0, + 0x5268E236, + 0xCC0C7795, + 0xBB0B4703, + 0x220216B9, + 0x5505262F, + 0xC5BA3BBE, + 0xB2BD0B28, + 0x2BB45A92, + 0x5CB36A04, + 0xC2D7FFA7, + 0xB5D0CF31, + 0x2CD99E8B, + 0x5BDEAE1D, + 0x9B64C2B0, + 0xEC63F226, + 0x756AA39C, + 0x026D930A, + 0x9C0906A9, + 0xEB0E363F, + 0x72076785, + 0x05005713, + 0x95BF4A82, + 0xE2B87A14, + 0x7BB12BAE, + 0x0CB61B38, + 0x92D28E9B, + 0xE5D5BE0D, + 0x7CDCEFB7, + 0x0BDBDF21, + 0x86D3D2D4, + 0xF1D4E242, + 0x68DDB3F8, + 0x1FDA836E, + 0x81BE16CD, + 0xF6B9265B, + 0x6FB077E1, + 0x18B74777, + 0x88085AE6, + 0xFF0F6A70, + 0x66063BCA, + 0x11010B5C, + 0x8F659EFF, + 0xF862AE69, + 0x616BFFD3, + 0x166CCF45, + 0xA00AE278, + 0xD70DD2EE, + 0x4E048354, + 0x3903B3C2, + 0xA7672661, + 0xD06016F7, + 0x4969474D, + 0x3E6E77DB, + 0xAED16A4A, + 0xD9D65ADC, + 0x40DF0B66, + 0x37D83BF0, + 0xA9BCAE53, + 0xDEBB9EC5, + 0x47B2CF7F, + 0x30B5FFE9, + 0xBDBDF21C, + 0xCABAC28A, + 0x53B39330, + 0x24B4A3A6, + 0xBAD03605, + 0xCDD70693, + 0x54DE5729, + 0x23D967BF, + 0xB3667A2E, + 0xC4614AB8, + 0x5D681B02, + 0x2A6F2B94, + 0xB40BBE37, + 0xC30C8EA1, + 0x5A05DF1B, + 0x2D02EF8D +}; + +EFI_STATUS +CalculateCrc32 ( + IN UINT8 *Data, + IN UINTN DataSize, + IN OUT UINT32 *CrcOut + ) +/*++ + +Routine Description: + + The CalculateCrc32 routine. + +Arguments: + + Data - The buffer contaning the data to be processed + DataSize - The size of data to be processed + CrcOut - A pointer to the caller allocated UINT32 that on + contains the CRC32 checksum of Data + +Returns: + + EFI_SUCCESS - Calculation is successful. + EFI_INVALID_PARAMETER - Data / CrcOut = NULL, or DataSize = 0 + +--*/ +{ + UINT32 Crc; + UINTN Index; + UINT8 *Ptr; + + if ((DataSize == 0) || (Data == NULL) || (CrcOut == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Crc = 0xffffffff; + for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) { + Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr]; + } + + *CrcOut = Crc ^ 0xffffffff; + + return EFI_SUCCESS; +} diff --git a/Tools/Source/TianoTools/Common/Crc32.h b/Tools/Source/TianoTools/Common/Crc32.h new file mode 100644 index 0000000000..0d24004fba --- /dev/null +++ b/Tools/Source/TianoTools/Common/Crc32.h @@ -0,0 +1,57 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + Crc32.h + +Abstract: + + Header file for CalcuateCrc32 routine + +--*/ + +/* +#include "TianoCommon.h" +*/ +#include +#include + +#ifndef _CRC32_H +#define _CRC32_H +EFI_STATUS +CalculateCrc32 ( + IN UINT8 *Data, + IN UINTN DataSize, + IN OUT UINT32 *CrcOut + ) +; + +/*++ + +Routine Description: + + The CalculateCrc32 routine. + +Arguments: + + Data - The buffer contaning the data to be processed + DataSize - The size of data to be processed + CrcOut - A pointer to the caller allocated UINT32 that on + contains the CRC32 checksum of Data + +Returns: + + EFI_SUCCESS - Calculation is successful. + EFI_INVALID_PARAMETER - Data / CrcOut = NULL, or DataSize = 0 + +--*/ +#endif diff --git a/Tools/Source/TianoTools/Common/EfiCompress.c b/Tools/Source/TianoTools/Common/EfiCompress.c new file mode 100644 index 0000000000..0a60a46d4b --- /dev/null +++ b/Tools/Source/TianoTools/Common/EfiCompress.c @@ -0,0 +1,1745 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + EfiCompress.c + +Abstract: + + Compression routine. The compression algorithm is a mixture of + LZ77 and Huffman coding. LZ77 transforms the source data into a + sequence of Original Characters and Pointers to repeated strings. + This sequence is further divided into Blocks and Huffman codings + are applied to each Block. + +--*/ + +/* +#include "TianoCommon.h" +*/ +#include "EfiCompress.h" + +// +// Macro Definitions +// +typedef INT32 NODE; +#define UINT8_BIT 8 +#define THRESHOLD 3 +#define INIT_CRC 0 +#define WNDBIT 19 +#define WNDSIZ (1U << WNDBIT) +#define MAXMATCH 256 +#define BLKSIZ (1U << 14) // 16 * 1024U +#define PERC_FLAG 0x80000000U +#define CODE_BIT 16 +#define NIL 0 +#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX) +#define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2) +#define CRCPOLY 0xA001 +#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT) + +// +// C: the Char&Len Set; P: the Position Set; T: the exTra Set +// +#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define NP (WNDBIT + 1) +#define PBIT 5 +#define NT (CODE_BIT + 3) +#define TBIT 5 +#if NT > NP +#define NPT NT +#else +#define NPT NP +#endif +// +// Function Prototypes +// +STATIC VOID PutDword(IN UINT32 Data); + +STATIC +EFI_STATUS +AllocateMemory ( + VOID + ); + +STATIC +VOID +FreeMemory ( + VOID + ); + +STATIC +VOID +InitSlide ( + VOID + ); + +STATIC +NODE +Child ( + IN NODE NodeQ, + IN UINT8 CharC + ); + +STATIC +VOID +MakeChild ( + IN NODE NodeQ, + IN UINT8 CharC, + IN NODE NodeR + ); + +STATIC +VOID +Split ( + IN NODE Old + ); + +STATIC +VOID +InsertNode ( + VOID + ); + +STATIC +VOID +DeleteNode ( + VOID + ); + +STATIC +VOID +GetNextMatch ( + VOID + ); + +STATIC +EFI_STATUS +Encode ( + VOID + ); + +STATIC +VOID +CountTFreq ( + VOID + ); + +STATIC +VOID +WritePTLen ( + IN INT32 Number, + IN INT32 nbit, + IN INT32 Special + ); + +STATIC +VOID +WriteCLen ( + VOID + ); + +STATIC +VOID +EncodeC ( + IN INT32 Value + ); + +STATIC +VOID +EncodeP ( + IN UINT32 Value + ); + +STATIC +VOID +SendBlock ( + VOID + ); + +STATIC +VOID +Output ( + IN UINT32 c, + IN UINT32 p + ); + +STATIC +VOID +HufEncodeStart ( + VOID + ); + +STATIC +VOID +HufEncodeEnd ( + VOID + ); + +STATIC +VOID +MakeCrcTable ( + VOID + ); + +STATIC +VOID +PutBits ( + IN INT32 Number, + IN UINT32 Value + ); + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *Pointer, + IN INT32 Number + ); + +STATIC +VOID +InitPutBits ( + VOID + ); + +STATIC +VOID +CountLen ( + IN INT32 Index + ); + +STATIC +VOID +MakeLen ( + IN INT32 Root + ); + +STATIC +VOID +DownHeap ( + IN INT32 Index + ); + +STATIC +VOID +MakeCode ( + IN INT32 Number, + IN UINT8 Len[ ], + OUT UINT16 Code[] + ); + +STATIC +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[ ], + OUT UINT16 CodeParm[] + ); + +// +// Global Variables +// +static UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit; + +static UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen; +static INT16 mHeap[NC + 1]; +static INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN; +static UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; +static UINT32 mCompSize, mOrigSize; + +static UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1], + mCFreq[2 * NC - 1], mCTable[4096], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; + +static NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; + +// +// functions +// +EFI_STATUS +Compress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +/*++ + +Routine Description: + + The main compression routine. + +Arguments: + + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. + +Returns: + + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + EFI_OUT_OF_RESOURCES - No resource to complete function. + +--*/ +{ + EFI_STATUS Status; + + // + // Initializations + // + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; + + mSrc = SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst +*DstSize; + + PutDword (0L); + PutDword (0L); + + MakeCrcTable (); + + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; + + // + // Compress it + // + Status = Encode (); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + // + // Fill in compressed size and original size + // + mDst = DstBuffer; + PutDword (mCompSize + 1); + PutDword (mOrigSize); + + // + // Return + // + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } + +} + +STATIC +VOID +PutDword ( + IN UINT32 Data + ) +/*++ + +Routine Description: + + Put a dword to output stream + +Arguments: + + Data - the dword to put + +Returns: (VOID) + +--*/ +{ + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff); + } +} + +STATIC +EFI_STATUS +AllocateMemory ( + VOID + ) +/*++ + +Routine Description: + + Allocate memory spaces for data structures used in compression process + +Argements: + VOID + +Returns: + + EFI_SUCCESS - Memory is allocated successfully + EFI_OUT_OF_RESOURCES - Allocation fails + +--*/ +{ + UINT32 Index; + + mText = malloc (WNDSIZ * 2 + MAXMATCH); + for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { + mText[Index] = 0; + } + + mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); + mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); + mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); + mParent = malloc (WNDSIZ * 2 * sizeof (*mParent)); + mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev)); + mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext)); + + mBufSiz = BLKSIZ; + mBuf = malloc (mBufSiz); + while (mBuf == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } + + mBuf = malloc (mBufSiz); + } + + mBuf[0] = 0; + + return EFI_SUCCESS; +} + +VOID +FreeMemory ( + VOID + ) +/*++ + +Routine Description: + + Called when compression is completed to free memory previously allocated. + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + if (mText != NULL) { + free (mText); + } + + if (mLevel != NULL) { + free (mLevel); + } + + if (mChildCount != NULL) { + free (mChildCount); + } + + if (mPosition != NULL) { + free (mPosition); + } + + if (mParent != NULL) { + free (mParent); + } + + if (mPrev != NULL) { + free (mPrev); + } + + if (mNext != NULL) { + free (mNext); + } + + if (mBuf != NULL) { + free (mBuf); + } + + return ; +} + +STATIC +VOID +InitSlide ( + VOID + ) +/*++ + +Routine Description: + + Initialize String Info Log data structures + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE Index; + + for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) { + mLevel[Index] = 1; + mPosition[Index] = NIL; /* sentinel */ + } + + for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) { + mParent[Index] = NIL; + } + + mAvail = 1; + for (Index = 1; Index < WNDSIZ - 1; Index++) { + mNext[Index] = (NODE) (Index + 1); + } + + mNext[WNDSIZ - 1] = NIL; + for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) { + mNext[Index] = NIL; + } +} + +STATIC +NODE +Child ( + IN NODE NodeQ, + IN UINT8 CharC + ) +/*++ + +Routine Description: + + Find child node given the parent node and the edge character + +Arguments: + + NodeQ - the parent node + CharC - the edge character + +Returns: + + The child node (NIL if not found) + +--*/ +{ + NODE NodeR; + + NodeR = mNext[HASH (NodeQ, CharC)]; + // + // sentinel + // + mParent[NIL] = NodeQ; + while (mParent[NodeR] != NodeQ) { + NodeR = mNext[NodeR]; + } + + return NodeR; +} + +STATIC +VOID +MakeChild ( + IN NODE Parent, + IN UINT8 CharC, + IN NODE Child + ) +/*++ + +Routine Description: + + Create a new child for a given parent node. + +Arguments: + + Parent - the parent node + CharC - the edge character + Child - the child node + +Returns: (VOID) + +--*/ +{ + NODE Node1; + NODE Node2; + + Node1 = (NODE) HASH (Parent, CharC); + Node2 = mNext[Node1]; + mNext[Node1] = Child; + mNext[Child] = Node2; + mPrev[Node2] = Child; + mPrev[Child] = Node1; + mParent[Child] = Parent; + mChildCount[Parent]++; +} + +STATIC +VOID +Split ( + NODE Old + ) +/*++ + +Routine Description: + + Split a node. + +Arguments: + + Old - the node to split + +Returns: (VOID) + +--*/ +{ + NODE New; + NODE TempNode; + + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + TempNode = mPrev[Old]; + mPrev[New] = TempNode; + mNext[TempNode] = New; + TempNode = mNext[Old]; + mNext[New] = TempNode; + mPrev[TempNode] = New; + mParent[New] = mParent[Old]; + mLevel[New] = (UINT8) mMatchLen; + mPosition[New] = mPos; + MakeChild (New, mText[mMatchPos + mMatchLen], Old); + MakeChild (New, mText[mPos + mMatchLen], mPos); +} + +STATIC +VOID +InsertNode ( + VOID + ) +/*++ + +Routine Description: + + Insert string info for current position into the String Info Log + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE NodeQ; + NODE NodeR; + NODE Index2; + NODE NodeT; + UINT8 CharC; + UINT8 *t1; + UINT8 *t2; + + if (mMatchLen >= 4) { + // + // We have just got a long match, the target tree + // can be located by MatchPos + 1. Travese the tree + // from bottom up to get to a proper starting point. + // The usage of PERC_FLAG ensures proper node deletion + // in DeleteNode() later. + // + mMatchLen--; + NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ); + NodeQ = mParent[NodeR]; + while (NodeQ == NIL) { + NodeR = mNext[NodeR]; + NodeQ = mParent[NodeR]; + } + + while (mLevel[NodeQ] >= mMatchLen) { + NodeR = NodeQ; + NodeQ = mParent[NodeQ]; + } + + NodeT = NodeQ; + while (mPosition[NodeT] < 0) { + mPosition[NodeT] = mPos; + NodeT = mParent[NodeT]; + } + + if (NodeT < WNDSIZ) { + mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG); + } + } else { + // + // Locate the target tree + // + NodeQ = (NODE) (mText[mPos] + WNDSIZ); + CharC = mText[mPos + 1]; + NodeR = Child (NodeQ, CharC); + if (NodeR == NIL) { + MakeChild (NodeQ, CharC, mPos); + mMatchLen = 1; + return ; + } + + mMatchLen = 2; + } + // + // Traverse down the tree to find a match. + // Update Position value along the route. + // Node split or creation is involved. + // + for (;;) { + if (NodeR >= WNDSIZ) { + Index2 = MAXMATCH; + mMatchPos = NodeR; + } else { + Index2 = mLevel[NodeR]; + mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); + } + + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } + + t1 = &mText[mPos + mMatchLen]; + t2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < Index2) { + if (*t1 != *t2) { + Split (NodeR); + return ; + } + + mMatchLen++; + t1++; + t2++; + } + + if (mMatchLen >= MAXMATCH) { + break; + } + + mPosition[NodeR] = mPos; + NodeQ = NodeR; + NodeR = Child (NodeQ, *t1); + if (NodeR == NIL) { + MakeChild (NodeQ, *t1, mPos); + return ; + } + + mMatchLen++; + } + + NodeT = mPrev[NodeR]; + mPrev[mPos] = NodeT; + mNext[NodeT] = mPos; + NodeT = mNext[NodeR]; + mNext[mPos] = NodeT; + mPrev[NodeT] = mPos; + mParent[mPos] = NodeQ; + mParent[NodeR] = NIL; + + // + // Special usage of 'next' + // + mNext[NodeR] = mPos; + +} + +STATIC +VOID +DeleteNode ( + VOID + ) +/*++ + +Routine Description: + + Delete outdated string info. (The Usage of PERC_FLAG + ensures a clean deletion) + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE NodeQ; + NODE NodeR; + NODE NodeS; + NODE NodeT; + NODE NodeU; + + if (mParent[mPos] == NIL) { + return ; + } + + NodeR = mPrev[mPos]; + NodeS = mNext[mPos]; + mNext[NodeR] = NodeS; + mPrev[NodeS] = NodeR; + NodeR = mParent[mPos]; + mParent[mPos] = NIL; + if (NodeR >= WNDSIZ) { + return ; + } + + mChildCount[NodeR]--; + if (mChildCount[NodeR] > 1) { + return ; + } + + NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); + if (NodeT >= mPos) { + NodeT -= WNDSIZ; + } + + NodeS = NodeT; + NodeQ = mParent[NodeR]; + NodeU = mPosition[NodeQ]; + while (NodeU & (UINT32) PERC_FLAG) { + NodeU &= (UINT32)~PERC_FLAG; + if (NodeU >= mPos) { + NodeU -= WNDSIZ; + } + + if (NodeU > NodeS) { + NodeS = NodeU; + } + + mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ); + NodeQ = mParent[NodeQ]; + NodeU = mPosition[NodeQ]; + } + + if (NodeQ < WNDSIZ) { + if (NodeU >= mPos) { + NodeU -= WNDSIZ; + } + + if (NodeU > NodeS) { + NodeS = NodeU; + } + + mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG); + } + + NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]); + NodeT = mPrev[NodeS]; + NodeU = mNext[NodeS]; + mNext[NodeT] = NodeU; + mPrev[NodeU] = NodeT; + NodeT = mPrev[NodeR]; + mNext[NodeT] = NodeS; + mPrev[NodeS] = NodeT; + NodeT = mNext[NodeR]; + mPrev[NodeT] = NodeS; + mNext[NodeS] = NodeT; + mParent[NodeS] = mParent[NodeR]; + mParent[NodeR] = NIL; + mNext[NodeR] = mAvail; + mAvail = NodeR; +} + +STATIC +VOID +GetNextMatch ( + VOID + ) +/*++ + +Routine Description: + + Advance the current position (read in new data if needed). + Delete outdated string info. Find a match string for current position. + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Number; + + mRemainder--; + mPos++; + if (mPos == WNDSIZ * 2) { + memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); + Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += Number; + mPos = WNDSIZ; + } + + DeleteNode (); + InsertNode (); +} + +STATIC +EFI_STATUS +Encode ( + VOID + ) +/*++ + +Routine Description: + + The main controlling routine for compression process. + +Arguments: (VOID) + +Returns: + + EFI_SUCCESS - The compression is successful + EFI_OUT_0F_RESOURCES - Not enough memory for compression process + +--*/ +{ + EFI_STATUS Status; + INT32 LastMatchLen; + NODE LastMatchPos; + + Status = AllocateMemory (); + if (EFI_ERROR (Status)) { + FreeMemory (); + return Status; + } + + InitSlide (); + + HufEncodeStart (); + + mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH); + + mMatchLen = 0; + mPos = WNDSIZ; + InsertNode (); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + while (mRemainder > 0) { + LastMatchLen = mMatchLen; + LastMatchPos = mMatchPos; + GetNextMatch (); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { + // + // Not enough benefits are gained by outputting a pointer, + // so just output the original character + // + Output (mText[mPos - 1], 0); + + } else { + + if (LastMatchLen == THRESHOLD) { + if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { + Output (mText[mPos - 1], 0); + continue; + } + } + // + // Outputting a pointer is beneficial enough, do it. + // + Output ( + LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1) + ); + LastMatchLen--; + while (LastMatchLen > 0) { + GetNextMatch (); + LastMatchLen--; + } + + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } + + HufEncodeEnd (); + FreeMemory (); + return EFI_SUCCESS; +} + +STATIC +VOID +CountTFreq ( + VOID + ) +/*++ + +Routine Description: + + Count the frequencies for the Extra Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + INT32 Number; + INT32 Count; + + for (Index = 0; Index < NT; Index++) { + mTFreq[Index] = 0; + } + + Number = NC; + while (Number > 0 && mCLen[Number - 1] == 0) { + Number--; + } + + Index = 0; + while (Index < Number) { + Index3 = mCLen[Index++]; + if (Index3 == 0) { + Count = 1; + while (Index < Number && mCLen[Index] == 0) { + Index++; + Count++; + } + + if (Count <= 2) { + mTFreq[0] = (UINT16) (mTFreq[0] + Count); + } else if (Count <= 18) { + mTFreq[1]++; + } else if (Count == 19) { + mTFreq[0]++; + mTFreq[1]++; + } else { + mTFreq[2]++; + } + } else { + mTFreq[Index3 + 2]++; + } + } +} + +STATIC +VOID +WritePTLen ( + IN INT32 Number, + IN INT32 nbit, + IN INT32 Special + ) +/*++ + +Routine Description: + + Outputs the code length array for the Extra Set or the Position Set. + +Arguments: + + Number - the number of symbols + nbit - the number of bits needed to represent 'n' + Special - the special symbol that needs to be take care of + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + + while (Number > 0 && mPTLen[Number - 1] == 0) { + Number--; + } + + PutBits (nbit, Number); + Index = 0; + while (Index < Number) { + Index3 = mPTLen[Index++]; + if (Index3 <= 6) { + PutBits (3, Index3); + } else { + PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2); + } + + if (Index == Special) { + while (Index < 6 && mPTLen[Index] == 0) { + Index++; + } + + PutBits (2, (Index - 3) & 3); + } + } +} + +STATIC +VOID +WriteCLen ( + VOID + ) +/*++ + +Routine Description: + + Outputs the code length array for Char&Length Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + INT32 Number; + INT32 Count; + + Number = NC; + while (Number > 0 && mCLen[Number - 1] == 0) { + Number--; + } + + PutBits (CBIT, Number); + Index = 0; + while (Index < Number) { + Index3 = mCLen[Index++]; + if (Index3 == 0) { + Count = 1; + while (Index < Number && mCLen[Index] == 0) { + Index++; + Count++; + } + + if (Count <= 2) { + for (Index3 = 0; Index3 < Count; Index3++) { + PutBits (mPTLen[0], mPTCode[0]); + } + } else if (Count <= 18) { + PutBits (mPTLen[1], mPTCode[1]); + PutBits (4, Count - 3); + } else if (Count == 19) { + PutBits (mPTLen[0], mPTCode[0]); + PutBits (mPTLen[1], mPTCode[1]); + PutBits (4, 15); + } else { + PutBits (mPTLen[2], mPTCode[2]); + PutBits (CBIT, Count - 20); + } + } else { + PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]); + } + } +} + +STATIC +VOID +EncodeC ( + IN INT32 Value + ) +{ + PutBits (mCLen[Value], mCCode[Value]); +} + +STATIC +VOID +EncodeP ( + IN UINT32 Value + ) +{ + UINT32 Index; + UINT32 NodeQ; + + Index = 0; + NodeQ = Value; + while (NodeQ) { + NodeQ >>= 1; + Index++; + } + + PutBits (mPTLen[Index], mPTCode[Index]); + if (Index > 1) { + PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); + } +} + +STATIC +VOID +SendBlock ( + VOID + ) +/*++ + +Routine Description: + + Huffman code the block and output it. + +Arguments: + (VOID) + +Returns: + (VOID) + +--*/ +{ + UINT32 Index; + UINT32 Index2; + UINT32 Index3; + UINT32 Flags; + UINT32 Root; + UINT32 Pos; + UINT32 Size; + Flags = 0; + + Root = MakeTree (NC, mCFreq, mCLen, mCCode); + Size = mCFreq[Root]; + PutBits (16, Size); + if (Root >= NC) { + CountTFreq (); + Root = MakeTree (NT, mTFreq, mPTLen, mPTCode); + if (Root >= NT) { + WritePTLen (NT, TBIT, 3); + } else { + PutBits (TBIT, 0); + PutBits (TBIT, Root); + } + + WriteCLen (); + } else { + PutBits (TBIT, 0); + PutBits (TBIT, 0); + PutBits (CBIT, 0); + PutBits (CBIT, Root); + } + + Root = MakeTree (NP, mPFreq, mPTLen, mPTCode); + if (Root >= NP) { + WritePTLen (NP, PBIT, -1); + } else { + PutBits (PBIT, 0); + PutBits (PBIT, Root); + } + + Pos = 0; + for (Index = 0; Index < Size; Index++) { + if (Index % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } else { + Flags <<= 1; + } + + if (Flags & (1U << (UINT8_BIT - 1))) { + EncodeC (mBuf[Pos++] + (1U << UINT8_BIT)); + Index3 = mBuf[Pos++]; + for (Index2 = 0; Index2 < 3; Index2++) { + Index3 <<= UINT8_BIT; + Index3 += mBuf[Pos++]; + } + + EncodeP (Index3); + } else { + EncodeC (mBuf[Pos++]); + } + } + + for (Index = 0; Index < NC; Index++) { + mCFreq[Index] = 0; + } + + for (Index = 0; Index < NP; Index++) { + mPFreq[Index] = 0; + } +} + +STATIC +VOID +Output ( + IN UINT32 CharC, + IN UINT32 Pos + ) +/*++ + +Routine Description: + + Outputs an Original Character or a Pointer + +Arguments: + + CharC - The original character or the 'String Length' element of a Pointer + Pos - The 'Position' field of a Pointer + +Returns: (VOID) + +--*/ +{ + static UINT32 CPos; + + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + // + // Check the buffer overflow per outputing UINT8_BIT symbols + // which is an Original Character or a Pointer. The biggest + // symbol is a Pointer which occupies 5 bytes. + // + if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { + SendBlock (); + mOutputPos = 0; + } + + CPos = mOutputPos++; + mBuf[CPos] = 0; + } + + mBuf[mOutputPos++] = (UINT8) CharC; + mCFreq[CharC]++; + if (CharC >= (1U << UINT8_BIT)) { + mBuf[CPos] |= mOutputMask; + mBuf[mOutputPos++] = (UINT8) (Pos >> 24); + mBuf[mOutputPos++] = (UINT8) (Pos >> 16); + mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT)); + mBuf[mOutputPos++] = (UINT8) Pos; + CharC = 0; + while (Pos) { + Pos >>= 1; + CharC++; + } + + mPFreq[CharC]++; + } +} + +STATIC +VOID +HufEncodeStart ( + VOID + ) +{ + INT32 Index; + + for (Index = 0; Index < NC; Index++) { + mCFreq[Index] = 0; + } + + for (Index = 0; Index < NP; Index++) { + mPFreq[Index] = 0; + } + + mOutputPos = mOutputMask = 0; + InitPutBits (); + return ; +} + +STATIC +VOID +HufEncodeEnd ( + VOID + ) +{ + SendBlock (); + + // + // Flush remaining bits + // + PutBits (UINT8_BIT - 1, 0); + + return ; +} + +STATIC +VOID +MakeCrcTable ( + VOID + ) +{ + UINT32 Index; + UINT32 Index2; + UINT32 Temp; + + for (Index = 0; Index <= UINT8_MAX; Index++) { + Temp = Index; + for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { + if (Temp & 1) { + Temp = (Temp >> 1) ^ CRCPOLY; + } else { + Temp >>= 1; + } + } + + mCrcTable[Index] = (UINT16) Temp; + } +} + +STATIC +VOID +PutBits ( + IN INT32 Number, + IN UINT32 Value + ) +/*++ + +Routine Description: + + Outputs rightmost n bits of x + +Arguments: + + Number - the rightmost n bits of the data is used + x - the data + +Returns: (VOID) + +--*/ +{ + UINT8 Temp; + + while (Number >= mBitCount) { + // + // Number -= mBitCount should never equal to 32 + // + Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount))); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + + mCompSize++; + mSubBitBuf = 0; + mBitCount = UINT8_BIT; + } + + mSubBitBuf |= Value << (mBitCount -= Number); +} + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *Pointer, + IN INT32 Number + ) +/*++ + +Routine Description: + + Read in source data + +Arguments: + + Pointer - the buffer to hold the data + Number - number of bytes to read + +Returns: + + number of bytes actually read + +--*/ +{ + INT32 Index; + + for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { + *Pointer++ = *mSrc++; + } + + Number = Index; + + Pointer -= Number; + mOrigSize += Number; + Index--; + while (Index >= 0) { + UPDATE_CRC (*Pointer++); + Index--; + } + + return Number; +} + +STATIC +VOID +InitPutBits ( + VOID + ) +{ + mBitCount = UINT8_BIT; + mSubBitBuf = 0; +} + +STATIC +VOID +CountLen ( + IN INT32 Index + ) +/*++ + +Routine Description: + + Count the number of each code length for a Huffman tree. + +Arguments: + + Index - the top node + +Returns: (VOID) + +--*/ +{ + static INT32 Depth = 0; + + if (Index < mN) { + mLenCnt[(Depth < 16) ? Depth : 16]++; + } else { + Depth++; + CountLen (mLeft[Index]); + CountLen (mRight[Index]); + Depth--; + } +} + +STATIC +VOID +MakeLen ( + IN INT32 Root + ) +/*++ + +Routine Description: + + Create code length array for a Huffman tree + +Arguments: + + Root - the root of the tree + +Returns: + + VOID + +--*/ +{ + INT32 Index; + INT32 Index3; + UINT32 Cum; + + for (Index = 0; Index <= 16; Index++) { + mLenCnt[Index] = 0; + } + + CountLen (Root); + + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + Cum = 0; + for (Index = 16; Index > 0; Index--) { + Cum += mLenCnt[Index] << (16 - Index); + } + + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (Index = 15; Index > 0; Index--) { + if (mLenCnt[Index] != 0) { + mLenCnt[Index]--; + mLenCnt[Index + 1] += 2; + break; + } + } + + Cum--; + } + + for (Index = 16; Index > 0; Index--) { + Index3 = mLenCnt[Index]; + Index3--; + while (Index3 >= 0) { + mLen[*mSortPtr++] = (UINT8) Index; + Index3--; + } + } +} + +STATIC +VOID +DownHeap ( + IN INT32 Index + ) +{ + INT32 Index2; + INT32 Index3; + + // + // priority queue: send Index-th entry down heap + // + Index3 = mHeap[Index]; + Index2 = 2 * Index; + while (Index2 <= mHeapSize) { + if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { + Index2++; + } + + if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { + break; + } + + mHeap[Index] = mHeap[Index2]; + Index = Index2; + Index2 = 2 * Index; + } + + mHeap[Index] = (INT16) Index3; +} + +STATIC +VOID +MakeCode ( + IN INT32 Number, + IN UINT8 Len[ ], + OUT UINT16 Code[] + ) +/*++ + +Routine Description: + + Assign code to each symbol based on the code length array + +Arguments: + + Number - number of symbols + Len - the code length array + Code - stores codes for each symbol + +Returns: (VOID) + +--*/ +{ + INT32 Index; + UINT16 Start[18]; + + Start[1] = 0; + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1); + } + + for (Index = 0; Index < Number; Index++) { + Code[Index] = Start[Len[Index]]++; + } +} + +STATIC +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[ ], + OUT UINT16 CodeParm[] + ) +/*++ + +Routine Description: + + Generates Huffman codes given a frequency distribution of symbols + +Arguments: + + NParm - number of symbols + FreqParm - frequency of each symbol + LenParm - code length for each symbol + CodeParm - code for each symbol + +Returns: + + Root of the Huffman tree. + +--*/ +{ + INT32 Index; + INT32 Index2; + INT32 Index3; + INT32 Avail; + + // + // make tree, calculate len[], return root + // + mN = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mN; + mHeapSize = 0; + mHeap[1] = 0; + for (Index = 0; Index < mN; Index++) { + mLen[Index] = 0; + if (mFreq[Index]) { + mHeapSize++; + mHeap[mHeapSize] = (INT16) Index; + } + } + + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } + + for (Index = mHeapSize / 2; Index >= 1; Index--) { + // + // make priority queue + // + DownHeap (Index); + } + + mSortPtr = CodeParm; + do { + Index = mHeap[1]; + if (Index < mN) { + *mSortPtr++ = (UINT16) Index; + } + + mHeap[1] = mHeap[mHeapSize--]; + DownHeap (1); + Index2 = mHeap[1]; + if (Index2 < mN) { + *mSortPtr++ = (UINT16) Index2; + } + + Index3 = Avail++; + mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]); + mHeap[1] = (INT16) Index3; + DownHeap (1); + mLeft[Index3] = (UINT16) Index; + mRight[Index3] = (UINT16) Index2; + } while (mHeapSize > 1); + + mSortPtr = CodeParm; + MakeLen (Index3); + MakeCode (NParm, LenParm, CodeParm); + + // + // return root + // + return Index3; +} diff --git a/Tools/Source/TianoTools/Common/EfiCompress.h b/Tools/Source/TianoTools/Common/EfiCompress.h new file mode 100644 index 0000000000..a129f2cc33 --- /dev/null +++ b/Tools/Source/TianoTools/Common/EfiCompress.h @@ -0,0 +1,68 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + EfiCompress.h + +Abstract: + + Header file for compression routine + +--*/ + +#include +#include +#include +#include + +#ifndef _EFICOMPRESS_H +#define _EFICOMPRESS_H +EFI_STATUS +Compress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +; + +/*++ + +Routine Description: + + The compression routine. + +Arguments: + + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. + +Returns: + + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + +--*/ +typedef +EFI_STATUS +(*COMPRESS_FUNCTION) ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ); + +#endif diff --git a/Tools/Source/TianoTools/Common/EfiCustomizedCompress.h b/Tools/Source/TianoTools/Common/EfiCustomizedCompress.h new file mode 100644 index 0000000000..4953e42b52 --- /dev/null +++ b/Tools/Source/TianoTools/Common/EfiCustomizedCompress.h @@ -0,0 +1,141 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + EfiCustomizedCompress.h + +Abstract: + + Header file for Customized compression routine + +--*/ + +#include +#include + +#ifndef _EFICUSTOMIZEDCOMPRESS_H +#define _EFICUSTOMIZEDCOMPRESS_H +EFI_STATUS +SetCustomizedCompressionType ( + IN CHAR8 *Type + ) +; + +/*++ + +Routine Description: + +The implementation of Customized SetCompressionType(). + +Arguments: + Type - The type if compression. + +Returns: + + EFI_SUCCESS - The type has been set. + EFI_UNSUPPORTED - This type is unsupported. + + +--*/ +EFI_STATUS +CustomizedGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +; + +/*++ + +Routine Description: + + The implementation of Customized GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +EFI_STATUS +CustomizedDecompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +; + +/*++ + +Routine Description: + + The implementation of Customized Decompress(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +EFI_STATUS +CustomizedCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +; + +/*++ + +Routine Description: + + The Customized compression routine. + +Arguments: + + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. + +Returns: + + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + +--*/ + +#endif diff --git a/Tools/Source/TianoTools/Common/EfiDecompress.c b/Tools/Source/TianoTools/Common/EfiDecompress.c new file mode 100644 index 0000000000..288c42579e --- /dev/null +++ b/Tools/Source/TianoTools/Common/EfiDecompress.c @@ -0,0 +1,790 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + EfiDecompress.c + +Abstract: + + Decompressor. Algorithm Ported from OPSD code (Decomp.asm) + +--*/ + +#include "EfiDecompress.h" + +// +// Decompression algorithm begins here +// +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define BAD_TABLE - 1 + +// +// C: Char&Len Set; P: Position Set; T: exTra Set +// +#define NC (0xff + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define PBIT 5 +#define TBIT 5 +#define MAXNP ((1U << PBIT) - 1) +#define NT (CODE_BIT + 3) +#if NT > MAXNP +#define NPT NT +#else +#define NPT MAXNP +#endif + +typedef struct { + UINT8 *mSrcBase; // Starting address of compressed data + UINT8 *mDstBase; // Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; + + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; + + UINT16 mBadTableFlag; + + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; +} SCRATCH_DATA; + +STATIC +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + +Arguments: + + Sd - The global scratch data + NumOfBit - The number of bits to shift and read. + +Returns: (VOID) + +--*/ +{ + Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); + + while (NumOfBits > Sd->mBitCount) { + + Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); + + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; + Sd->mBitCount = 8; + + } else { + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + + } + } + + Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; +} + +STATIC +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + +Arguments: + + Sd - The global scratch data. + NumOfBits - The number of bits to pop and read. + +Returns: + + The bits that are popped out. + +--*/ +{ + UINT32 OutBits; + + OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + + FillBuf (Sd, NumOfBits); + + return OutBits; +} + +STATIC +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ) +/*++ + +Routine Description: + + Creates Huffman Code mapping table according to code length array. + +Arguments: + + Sd - The global scratch data + NumOfChar - Number of symbols in the symbol set + BitLen - Code length array + TableBits - The width of the mapping table + Table - The table + +Returns: + + 0 - OK. + BAD_TABLE - The table is corrupted. + +--*/ +{ + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *Pointer; + UINT16 Index3; + UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; + + for (Index = 1; Index <= 16; Index++) { + Count[Index] = 0; + } + + for (Index = 0; Index < NumOfChar; Index++) { + Count[BitLen[Index]]++; + } + + Start[1] = 0; + + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index))); + } + + if (Start[17] != 0) { + /*(1U << 16)*/ + return (UINT16) BAD_TABLE; + } + + JuBits = (UINT16) (16 - TableBits); + + for (Index = 1; Index <= TableBits; Index++) { + Start[Index] >>= JuBits; + Weight[Index] = (UINT16) (1U << (TableBits - Index)); + } + + while (Index <= 16) { + Weight[Index++] = (UINT16) (1U << (16 - Index)); + } + + Index = (UINT16) (Start[TableBits + 1] >> JuBits); + + if (Index != 0) { + Index3 = (UINT16) (1U << TableBits); + while (Index != Index3) { + Table[Index++] = 0; + } + } + + Avail = NumOfChar; + Mask = (UINT16) (1U << (15 - TableBits)); + + for (Char = 0; Char < NumOfChar; Char++) { + + Len = BitLen[Char]; + if (Len == 0) { + continue; + } + + NextCode = (UINT16) (Start[Len] + Weight[Len]); + + if (Len <= TableBits) { + + for (Index = Start[Len]; Index < NextCode; Index++) { + Table[Index] = Char; + } + + } else { + + Index3 = Start[Len]; + Pointer = &Table[Index3 >> JuBits]; + Index = (UINT16) (Len - TableBits); + + while (Index != 0) { + if (*Pointer == 0) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *Pointer = Avail++; + } + + if (Index3 & Mask) { + Pointer = &Sd->mRight[*Pointer]; + } else { + Pointer = &Sd->mLeft[*Pointer]; + } + + Index3 <<= 1; + Index--; + } + + *Pointer = Char; + + } + + Start[Len] = NextCode; + } + // + // Succeeds + // + return 0; +} + +STATIC +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decodes a position value. + +Arguments: + + Sd - the global scratch data + +Returns: + + The position value decoded. + +--*/ +{ + UINT16 Val; + UINT32 Mask; + UINT32 Pos; + + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Sd->mBitBuf & Mask) { + Val = Sd->mRight[Val]; + } else { + Val = Sd->mLeft[Val]; + } + + Mask >>= 1; + } while (Val >= MAXNP); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[Val]); + + Pos = Val; + if (Val > 1) { + Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); + } + + return Pos; +} + +STATIC +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ) +/*++ + +Routine Description: + + Reads code lengths for the Extra Set or the Position Set + +Arguments: + + Sd - The global scratch data + nn - Number of symbols + nbit - Number of bits needed to represent nn + Special - The special symbol that needs to be taken care of + +Returns: + + 0 - OK. + BAD_TABLE - Table is corrupted. + +--*/ +{ + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, nbit); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, nbit); + + for (Index = 0; Index < 256; Index++) { + Sd->mPTTable[Index] = CharC; + } + + for (Index = 0; Index < nn; Index++) { + Sd->mPTLen[Index] = 0; + } + + return 0; + } + + Index = 0; + + while (Index < Number) { + + CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); + + if (CharC == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + CharC += 1; + } + } + + FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); + + Sd->mPTLen[Index++] = (UINT8) CharC; + + if (Index == Special) { + CharC = (UINT16) GetBits (Sd, 2); + CharC--; + while ((INT16) (CharC) >= 0) { + Sd->mPTLen[Index++] = 0; + CharC--; + } + } + } + + while (Index < nn) { + Sd->mPTLen[Index++] = 0; + } + + return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); +} + +STATIC +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Reads code lengths for Char&Len Set. + +Arguments: + + Sd - the global scratch data + +Returns: (VOID) + +--*/ +{ + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, CBIT); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, CBIT); + + for (Index = 0; Index < NC; Index++) { + Sd->mCLen[Index] = 0; + } + + for (Index = 0; Index < 4096; Index++) { + Sd->mCTable[Index] = CharC; + } + + return ; + } + + Index = 0; + while (Index < Number) { + + CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (CharC >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Mask & Sd->mBitBuf) { + CharC = Sd->mRight[CharC]; + } else { + CharC = Sd->mLeft[CharC]; + } + + Mask >>= 1; + + } while (CharC >= NT); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[CharC]); + + if (CharC <= 2) { + + if (CharC == 0) { + CharC = 1; + } else if (CharC == 1) { + CharC = (UINT16) (GetBits (Sd, 4) + 3); + } else if (CharC == 2) { + CharC = (UINT16) (GetBits (Sd, CBIT) + 20); + } + + CharC--; + while ((INT16) (CharC) >= 0) { + Sd->mCLen[Index++] = 0; + CharC--; + } + + } else { + + Sd->mCLen[Index++] = (UINT8) (CharC - 2); + + } + } + + while (Index < NC) { + Sd->mCLen[Index++] = 0; + } + + MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); + + return ; +} + +STATIC +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode a character/length value. + +Arguments: + + Sd - The global scratch data. + +Returns: + + The value decoded. + +--*/ +{ + UINT16 Index2; + UINT32 Mask; + + if (Sd->mBlockSize == 0) { + // + // Starting a new block + // + Sd->mBlockSize = (UINT16) GetBits (Sd, 16); + Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } + + ReadCLen (Sd); + + Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, PBIT, (UINT16) (-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } + + Sd->mBlockSize--; + Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + + if (Index2 >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); + + do { + if (Sd->mBitBuf & Mask) { + Index2 = Sd->mRight[Index2]; + } else { + Index2 = Sd->mLeft[Index2]; + } + + Mask >>= 1; + } while (Index2 >= NC); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mCLen[Index2]); + + return Index2; +} + +STATIC +VOID +Decode ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode the source data and put the resulting data into the destination buffer. + +Arguments: + + Sd - The global scratch data + +Returns: (VOID) + + --*/ +{ + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 CharC; + + BytesRemain = (UINT16) (-1); + + DataIdx = 0; + + for (;;) { + CharC = DecodeC (Sd); + if (Sd->mBadTableFlag != 0) { + return ; + } + + if (CharC < 256) { + // + // Process an Original character + // + Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } + + } else { + // + // Process a Pointer + // + CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD)); + + BytesRemain = CharC; + + DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; + + BytesRemain--; + while ((INT16) (BytesRemain) >= 0) { + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } + + BytesRemain--; + } + } + } + + return ; +} + +EFI_STATUS +GetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + UINT8 *Src; + + *ScratchSize = sizeof (SCRATCH_DATA); + + Src = Source; + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + return EFI_SUCCESS; +} + +EFI_STATUS +Decompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + EFI_STATUS Status; + SCRATCH_DATA *Sd; + UINT8 *Src; + UINT8 *Dst; + + Status = EFI_SUCCESS; + Src = Source; + Dst = Destination; + + if (ScratchSize < sizeof (SCRATCH_DATA)) { + return EFI_INVALID_PARAMETER; + } + + Sd = (SCRATCH_DATA *) Scratch; + + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + if (SrcSize < CompSize + 8) { + return EFI_INVALID_PARAMETER; + } + + if (DstSize != OrigSize) { + return EFI_INVALID_PARAMETER; + } + + Src = Src + 8; + + for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { + ((UINT8 *) Sd)[Index] = 0; + } + + Sd->mSrcBase = Src; + Sd->mDstBase = Dst; + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; + + // + // Fill the first BITBUFSIZ bits + // + FillBuf (Sd, BITBUFSIZ); + + // + // Decompress it + // + Decode (Sd); + + if (Sd->mBadTableFlag != 0) { + // + // Something wrong with the source + // + Status = EFI_INVALID_PARAMETER; + } + + return Status; +} diff --git a/Tools/Source/TianoTools/Common/EfiDecompress.h b/Tools/Source/TianoTools/Common/EfiDecompress.h new file mode 100644 index 0000000000..c5004a74a9 --- /dev/null +++ b/Tools/Source/TianoTools/Common/EfiDecompress.h @@ -0,0 +1,105 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + EfiDecompress.h + +Abstract: + + Header file for compression routine + +--*/ +#include +#include + +#ifndef _EFI_DECOMPRESS_H +#define _EFI_DECOMPRESS_H +EFI_STATUS +GetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); + +/*++ + +Routine Description: + + The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +EFI_STATUS +Decompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +; + +/*++ + +Routine Description: + + The implementation of EFI_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +typedef +EFI_STATUS +(*GETINFO_FUNCTION) ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); + +typedef +EFI_STATUS +(*DECOMPRESS_FUNCTION) ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); +#endif diff --git a/Tools/Source/TianoTools/Common/EfiUtilityMsgs.c b/Tools/Source/TianoTools/Common/EfiUtilityMsgs.c new file mode 100644 index 0000000000..6312c17250 --- /dev/null +++ b/Tools/Source/TianoTools/Common/EfiUtilityMsgs.c @@ -0,0 +1,758 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + EfiUtilityMsgs.c + +Abstract: + + EFI tools utility functions to display warning, error, and informational + messages. + +--*/ + +#include +#include +#include +#include + +/* +#include "Tiano.h" +*/ +#include "EfiUtilityMsgs.h" + +#define MAX_LINE_LEN 200 + +// +// Declare module globals for keeping track of the the utility's +// name and other settings. +// +static STATUS mStatus = STATUS_SUCCESS; +static CHAR8 mUtilityName[50] = { 0 }; +static UINT32 mDebugMsgMask = 0; +static CHAR8 *mSourceFileName = NULL; +static UINT32 mSourceFileLineNum = 0; +static UINT32 mErrorCount = 0; +static UINT32 mWarningCount = 0; +static UINT32 mMaxErrors = 0; +static UINT32 mMaxWarnings = 0; +static UINT32 mMaxWarningsPlusErrors = 0; +static INT8 mPrintLimitsSet = 0; + +static +void +PrintMessage ( + CHAR8 *Type, + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + CHAR8 *Text, + CHAR8 *MsgFmt, + va_list List + ); + +static +void +PrintLimitExceeded ( + VOID + ); + +void +Error ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + CHAR8 *Text, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Prints an error message. + +Arguments: + All arguments are optional, though the printed message may be useless if + at least something valid is not specified. + + FileName - name of the file or application. If not specified, then the + utilty name (as set by the utility calling SetUtilityName() + earlier) is used. Otherwise "Unknown utility" is used. + + LineNumber - the line number of error, typically used by parsers. If the + utility is not a parser, then 0 should be specified. Otherwise + the FileName and LineNumber info can be used to cause + MS Visual Studio to jump to the error. + + MessageCode - an application-specific error code that can be referenced in + other documentation. + + Text - the text in question, typically used by parsers. + + MsgFmt - the format string for the error message. Can contain formatting + controls for use with the varargs. + +Returns: + None. + +Notes: + We print the following (similar to the Warn() and Debug() + W + Typical error/warning message format: + + bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters + + BUGBUG -- these three utility functions are almost identical, and + should be modified to share code. + + Visual Studio does not find error messages with: + + " error :" + " error 1:" + " error c1:" + " error 1000:" + " error c100:" + + It does find: + " error c1000:" +--*/ +{ + va_list List; + // + // If limits have been set, then check that we have not exceeded them + // + if (mPrintLimitsSet) { + // + // See if we've exceeded our total count + // + if (mMaxWarningsPlusErrors != 0) { + if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) { + PrintLimitExceeded (); + return ; + } + } + // + // See if we've exceeded our error count + // + if (mMaxErrors != 0) { + if (mErrorCount > mMaxErrors) { + PrintLimitExceeded (); + return ; + } + } + } + + mErrorCount++; + va_start (List, MsgFmt); + PrintMessage ("error", FileName, LineNumber, MessageCode, Text, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_ERROR) { + mStatus = STATUS_ERROR; + } +} + +void +ParserError ( + UINT32 MessageCode, + CHAR8 *Text, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a parser error, using the source file name and line number + set by a previous call to SetParserPosition(). + +Arguments: + MessageCode - application-specific error code + Text - text to print in the error message + MsgFmt - format string to print at the end of the error message + +Returns: + NA + +--*/ +{ + va_list List; + // + // If limits have been set, then check them + // + if (mPrintLimitsSet) { + // + // See if we've exceeded our total count + // + if (mMaxWarningsPlusErrors != 0) { + if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) { + PrintLimitExceeded (); + return ; + } + } + // + // See if we've exceeded our error count + // + if (mMaxErrors != 0) { + if (mErrorCount > mMaxErrors) { + PrintLimitExceeded (); + return ; + } + } + } + + mErrorCount++; + va_start (List, MsgFmt); + PrintMessage ("error", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_ERROR) { + mStatus = STATUS_ERROR; + } +} + +void +ParserWarning ( + UINT32 ErrorCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a parser warning, using the source file name and line number + set by a previous call to SetParserPosition(). + +Arguments: + ErrorCode - application-specific error code + OffendingText - text to print in the warning message + MsgFmt - format string to print at the end of the warning message + +Returns: + NA + +--*/ +{ + va_list List; + // + // If limits have been set, then check them + // + if (mPrintLimitsSet) { + // + // See if we've exceeded our total count + // + if (mMaxWarningsPlusErrors != 0) { + if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) { + PrintLimitExceeded (); + return ; + } + } + // + // See if we've exceeded our warning count + // + if (mMaxWarnings != 0) { + if (mWarningCount > mMaxWarnings) { + PrintLimitExceeded (); + return ; + } + } + } + + mWarningCount++; + va_start (List, MsgFmt); + PrintMessage ("warning", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_WARNING) { + mStatus = STATUS_WARNING; + } +} + +void +Warning ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + CHAR8 *Text, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a warning message. + +Arguments: + FileName - name of the file where the warning was detected, or the name + of the application that detected the warning + + LineNumber - the line number where the warning was detected (parsers). + 0 should be specified if the utility is not a parser. + + MessageCode - an application-specific warning code that can be referenced in + other documentation. + + Text - the text in question (parsers) + + MsgFmt - the format string for the warning message. Can contain formatting + controls for use with varargs. + +Returns: + None. + +--*/ +{ + va_list List; + // + // If limits have been set, then check them + // + if (mPrintLimitsSet) { + // + // See if we've exceeded our total count + // + if (mMaxWarningsPlusErrors != 0) { + if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) { + PrintLimitExceeded (); + return ; + } + } + // + // See if we've exceeded our warning count + // + if (mMaxWarnings != 0) { + if (mWarningCount > mMaxWarnings) { + PrintLimitExceeded (); + return ; + } + } + } + + mWarningCount++; + va_start (List, MsgFmt); + PrintMessage ("warning", FileName, LineNumber, MessageCode, Text, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_WARNING) { + mStatus = STATUS_WARNING; + } +} + +void +DebugMsg ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MsgMask, + CHAR8 *Text, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a warning message. + +Arguments: + FileName - typically the name of the utility printing the debug message, but + can be the name of a file being parsed. + + LineNumber - the line number in FileName (parsers) + + MsgMask - an application-specific bitmask that, in combination with mDebugMsgMask, + determines if the debug message gets printed. + + Text - the text in question (parsers) + + MsgFmt - the format string for the debug message. Can contain formatting + controls for use with varargs. + +Returns: + None. + +--*/ +{ + va_list List; + // + // If the debug mask is not applicable, then do nothing. + // + if ((MsgMask != 0) && ((mDebugMsgMask & MsgMask) == 0)) { + return ; + } + + va_start (List, MsgFmt); + PrintMessage ("debug", FileName, LineNumber, 0, Text, MsgFmt, List); + va_end (List); +} + +static +void +PrintMessage ( + CHAR8 *Type, + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + CHAR8 *Text, + CHAR8 *MsgFmt, + va_list List + ) +/*++ + +Routine Description: + Worker routine for all the utility printing services. Prints the message in + a format that Visual Studio will find when scanning build outputs for + errors or warnings. + +Arguments: + Type - "warning" or "error" string to insert into the message to be + printed. The first character of this string (converted to uppercase) + is used to preceed the MessageCode value in the output string. + + FileName - name of the file where the warning was detected, or the name + of the application that detected the warning + + LineNumber - the line number where the warning was detected (parsers). + 0 should be specified if the utility is not a parser. + + MessageCode - an application-specific warning code that can be referenced in + other documentation. + + Text - part of the message to print + + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + List - the variable list. + +Returns: + None. + +Notes: + If FileName == NULL then this utility will use the string passed into SetUtilityName(). + + LineNumber is only used if the caller is a parser, in which case FileName refers to the + file being parsed. + + Text and MsgFmt are both optional, though it would be of little use calling this function with + them both NULL. + + Output will typically be of the form: + () : : : + + Parser (LineNumber != 0) + VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters + Generic utility (LineNumber == 0) + UtilityName : error E1234 : Text string : MsgFmt string and args + +--*/ +{ + CHAR8 Line[MAX_LINE_LEN]; + CHAR8 Line2[MAX_LINE_LEN]; + CHAR8 *Cptr; + // + // If given a filename, then add it (and the line number) to the string. + // If there's no filename, then use the program name if provided. + // + if (FileName != NULL) { + Cptr = FileName; + } else if (mUtilityName[0] != 0) { + Cptr = mUtilityName; + } else { + Cptr = "Unknown utility"; + } + + strcpy (Line, Cptr); + if (LineNumber != 0) { + sprintf (Line2, "(%d)", LineNumber); + strcat (Line, Line2); + } + // + // Have to print an error code or Visual Studio won't find the + // message for you. It has to be decimal digits too. + // + sprintf (Line2, " : %s %c%04d", Type, toupper (Type[0]), MessageCode); + strcat (Line, Line2); + fprintf (stdout, "%s", Line); + // + // If offending text was provided, then print it + // + if (Text != NULL) { + fprintf (stdout, ": %s ", Text); + } + // + // Print formatted message if provided + // + if (MsgFmt != NULL) { + vsprintf (Line2, MsgFmt, List); + fprintf (stdout, ": %s", Line2); + } + + fprintf (stdout, "\n"); +} + +void +ParserSetPosition ( + CHAR8 *SourceFileName, + UINT32 LineNum + ) +/*++ + +Routine Description: + Set the position in a file being parsed. This can be used to + print error messages deeper down in a parser. + +Arguments: + SourceFileName - name of the source file being parsed + LineNum - line number of the source file being parsed + +Returns: + NA + +--*/ +{ + mSourceFileName = SourceFileName; + mSourceFileLineNum = LineNum; +} + +void +SetUtilityName ( + CHAR8 *UtilityName + ) +/*++ + +Routine Description: + All printed error/warning/debug messages follow the same format, and + typically will print a filename or utility name followed by the error + text. However if a filename is not passed to the print routines, then + they'll print the utility name if you call this function early in your + app to set the utility name. + +Arguments: + UtilityName - name of the utility, which will be printed with all + error/warning/debug messags. + +Returns: + NA + +--*/ +{ + // + // Save the name of the utility in our local variable. Make sure its + // length does not exceed our buffer. + // + if (UtilityName != NULL) { + if (strlen (UtilityName) >= sizeof (mUtilityName)) { + Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size"); + strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1); + mUtilityName[sizeof (mUtilityName) - 1] = 0; + return ; + } else { + strcpy (mUtilityName, UtilityName); + } + } else { + Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name"); + } +} + +STATUS +GetUtilityStatus ( + VOID + ) +/*++ + +Routine Description: + When you call Error() or Warning(), this module keeps track of it and + sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility + exits, it can call this function to get the status and use it as a return + value. + +Arguments: + None. + +Returns: + Worst-case status reported, as defined by which print function was called. + +--*/ +{ + return mStatus; +} + +void +SetDebugMsgMask ( + UINT32 DebugMask + ) +/*++ + +Routine Description: + Set the debug printing mask. This is used by the DebugMsg() function + to determine when/if a debug message should be printed. + +Arguments: + DebugMask - bitmask, specific to the calling application + +Returns: + NA + +--*/ +{ + mDebugMsgMask = DebugMask; +} + +void +SetPrintLimits ( + UINT32 MaxErrors, + UINT32 MaxWarnings, + UINT32 MaxWarningsPlusErrors + ) +/*++ + +Routine Description: + Set the limits of how many errors, warnings, and errors+warnings + we will print. + +Arguments: + MaxErrors - maximum number of error messages to print + MaxWarnings - maximum number of warning messages to print + MaxWarningsPlusErrors + - maximum number of errors+warnings to print + +Returns: + NA + +--*/ +{ + mMaxErrors = MaxErrors; + mMaxWarnings = MaxWarnings; + mMaxWarningsPlusErrors = MaxWarningsPlusErrors; + mPrintLimitsSet = 1; +} + +static +void +PrintLimitExceeded ( + VOID + ) +{ + static INT8 mPrintLimitExceeded = 0; + // + // If we've already printed the message, do nothing. Otherwise + // temporarily increase our print limits so we can pass one + // more message through. + // + if (mPrintLimitExceeded == 0) { + mPrintLimitExceeded++; + mMaxErrors++; + mMaxWarnings++; + mMaxWarningsPlusErrors++; + Error (NULL, 0, 0, "error/warning print limit exceeded", NULL); + mMaxErrors--; + mMaxWarnings--; + mMaxWarningsPlusErrors--; + } +} + +#if 0 +void +TestUtilityMessages ( + VOID + ) +{ + char *ArgStr = "ArgString"; + int ArgInt; + + ArgInt = 0x12345678; + // + // Test without setting utility name + // + fprintf (stdout, "* Testing without setting utility name\n"); + fprintf (stdout, "** Test debug message not printed\n"); + DebugMsg (NULL, 0, 0x00000001, NULL, NULL); + fprintf (stdout, "** Test warning with two strings and two args\n"); + Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + fprintf (stdout, "** Test error with two strings and two args\n"); + Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + fprintf (stdout, "** Test parser warning with nothing\n"); + ParserWarning (0, NULL, NULL); + fprintf (stdout, "** Test parser error with nothing\n"); + ParserError (0, NULL, NULL); + // + // Test with utility name set now + // + fprintf (stdout, "** Testingin with utility name set\n"); + SetUtilityName ("MyUtilityName"); + // + // Test debug prints + // + SetDebugMsgMask (2); + fprintf (stdout, "** Test debug message with one string\n"); + DebugMsg (NULL, 0, 0x00000002, "Text1", NULL); + fprintf (stdout, "** Test debug message with one string\n"); + DebugMsg (NULL, 0, 0x00000002, NULL, "Text2"); + fprintf (stdout, "** Test debug message with two strings\n"); + DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2"); + fprintf (stdout, "** Test debug message with two strings and two args\n"); + DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + // + // Test warning prints + // + fprintf (stdout, "** Test warning with no strings\n"); + Warning (NULL, 0, 1234, NULL, NULL); + fprintf (stdout, "** Test warning with one string\n"); + Warning (NULL, 0, 1234, "Text1", NULL); + fprintf (stdout, "** Test warning with one string\n"); + Warning (NULL, 0, 1234, NULL, "Text2"); + fprintf (stdout, "** Test warning with two strings and two args\n"); + Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + // + // Test error prints + // + fprintf (stdout, "** Test error with no strings\n"); + Error (NULL, 0, 1234, NULL, NULL); + fprintf (stdout, "** Test error with one string\n"); + Error (NULL, 0, 1234, "Text1", NULL); + fprintf (stdout, "** Test error with one string\n"); + Error (NULL, 0, 1234, NULL, "Text2"); + fprintf (stdout, "** Test error with two strings and two args\n"); + Error (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + // + // Test parser prints + // + fprintf (stdout, "** Test parser errors\n"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserError (1234, NULL, NULL); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserError (1234, "Text1", NULL); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserError (1234, NULL, "Text2"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserError (1234, "Text1", "Text2"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + + fprintf (stdout, "** Test parser warnings\n"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserWarning (4321, NULL, NULL); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserWarning (4321, "Text1", NULL); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserWarning (4321, NULL, "Text2"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserWarning (4321, "Text1", "Text2"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); +} +#endif diff --git a/Tools/Source/TianoTools/Common/EfiUtilityMsgs.h b/Tools/Source/TianoTools/Common/EfiUtilityMsgs.h new file mode 100644 index 0000000000..777cacf771 --- /dev/null +++ b/Tools/Source/TianoTools/Common/EfiUtilityMsgs.h @@ -0,0 +1,138 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + EfiUtilityMsgs.h + +Abstract: + + Defines and prototypes for common EFI utility error and debug messages. + +--*/ + +#include +#include + +#ifndef _EFI_UTILITY_MSGS_H_ +#define _EFI_UTILITY_MSGS_H_ + +// +// Status codes returned by EFI utility programs and functions +// +#define STATUS_SUCCESS 0 +#define STATUS_WARNING 1 +#define STATUS_ERROR 2 +#define VOID void + +typedef int STATUS; + +#ifdef __cplusplus +extern "C" { +#endif +// +// When we call Error() or Warning(), the module keeps track of the worst +// case reported. GetUtilityStatus() will get the worst-case results, which +// can be used as the return value from the app. +// +STATUS +GetUtilityStatus ( + void + ); + +// +// If someone prints an error message and didn't specify a source file name, +// then we print the utility name instead. However they must tell us the +// utility name early on via this function. +// +void +SetUtilityName ( + CHAR8 *ProgramName + ) +; + +void +Error ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 ErrorCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +void +Warning ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 ErrorCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +void +DebugMsg ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MsgLevel, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +void +SetDebugMsgMask ( + UINT32 MsgMask + ) +; + +void +ParserSetPosition ( + CHAR8 *SourceFileName, + UINT32 LineNum + ) +; + +void +ParserError ( + UINT32 ErrorCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +void +ParserWarning ( + UINT32 ErrorCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +void +SetPrintLimits ( + UINT32 NumErrors, + UINT32 NumWarnings, + UINT32 NumWarningsPlusErrors + ) +; + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef _EFI_UTILITY_MSGS_H_ diff --git a/Tools/Source/TianoTools/Common/FvLib.c b/Tools/Source/TianoTools/Common/FvLib.c new file mode 100644 index 0000000000..9bfd84346d --- /dev/null +++ b/Tools/Source/TianoTools/Common/FvLib.c @@ -0,0 +1,788 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + FvLib.c + +Abstract: + + These functions assist in parsing and manipulating a Firmware Volume. + +--*/ + +// +// Include files +// +#include "FvLib.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +#include "MultiPhase.h" +/* +#include +*/ + +/* +#include EFI_GUID_DEFINITION (FirmwareFileSystem) +*/ + +// +// Module global variables +// +EFI_FIRMWARE_VOLUME_HEADER *mFvHeader = NULL; +UINT32 mFvLength = 0; + +// +// External function implementations +// +EFI_STATUS +InitializeFvLib ( + IN VOID *Fv, + IN UINT32 FvLength + ) +/*++ + +Routine Description: + + This initializes the FV lib with a pointer to the FV and length. It does not + verify the FV in any way. + +Arguments: + + Fv Buffer containing the FV. + FvLength Length of the FV + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +{ + // + // Verify input arguments + // + if (Fv == NULL) { + return EFI_INVALID_PARAMETER; + } + + mFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Fv; + mFvLength = FvLength; + + return EFI_SUCCESS; +} + +EFI_STATUS +GetFvHeader ( + OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader, + OUT UINT32 *FvLength + ) +/*++ + +Routine Description: + + This function returns a pointer to the current FV and the size. + +Arguments: + + FvHeader Pointer to the FV buffer. + FvLength Length of the FV + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_ABORTED The library needs to be initialized. + +--*/ +{ + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input arguments + // + if (FvHeader == NULL) { + return EFI_INVALID_PARAMETER; + } + + *FvHeader = mFvHeader; + return EFI_SUCCESS; +} + +EFI_STATUS +GetNextFile ( + IN EFI_FFS_FILE_HEADER *CurrentFile, + OUT EFI_FFS_FILE_HEADER **NextFile + ) +/*++ + +Routine Description: + + This function returns the next file. If the current file is NULL, it returns + the first file in the FV. If the function returns EFI_SUCCESS and the file + pointer is NULL, then there are no more files in the FV. + +Arguments: + + CurrentFile Pointer to the current file, must be within the current FV. + NextFile Pointer to the next file in the FV. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_INVALID_PARAMETER A required parameter was NULL or is out of range. + EFI_ABORTED The library needs to be initialized. + +--*/ +{ + EFI_STATUS Status; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input arguments + // + if (NextFile == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Get first file + // + if (CurrentFile == NULL) { + CurrentFile = (EFI_FFS_FILE_HEADER *) ((UINTN) mFvHeader + mFvHeader->HeaderLength); + + // + // Verify file is valid + // + Status = VerifyFfsFile (CurrentFile); + if (EFI_ERROR (Status)) { + // + // no files in this FV + // + *NextFile = NULL; + return EFI_SUCCESS; + } else { + // + // Verify file is in this FV. + // + if ((UINTN) CurrentFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FFS_FILE_HEADER)) { + *NextFile = NULL; + return EFI_SUCCESS; + } + + *NextFile = CurrentFile; + return EFI_SUCCESS; + } + } + // + // Verify current file is in range + // + if (((UINTN) CurrentFile < (UINTN) mFvHeader + sizeof (EFI_FIRMWARE_VOLUME_HEADER)) || + ((UINTN) CurrentFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FIRMWARE_VOLUME_HEADER)) + ) { + return EFI_INVALID_PARAMETER; + } + // + // Get next file, compensate for 8 byte alignment if necessary. + // + *NextFile = (EFI_FFS_FILE_HEADER *) (((UINTN) CurrentFile + GetLength (CurrentFile->Size) + 0x07) & (-1 << 3)); + + // + // Verify file is in this FV. + // + if ((UINTN) *NextFile >= (UINTN) mFvHeader + mFvLength - sizeof (EFI_FFS_FILE_HEADER)) { + *NextFile = NULL; + return EFI_SUCCESS; + } + // + // Verify file is valid + // + Status = VerifyFfsFile (*NextFile); + if (EFI_ERROR (Status)) { + // + // no more files in this FV + // + *NextFile = NULL; + return EFI_SUCCESS; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetFileByName ( + IN EFI_GUID *FileName, + OUT EFI_FFS_FILE_HEADER **File + ) +/*++ + +Routine Description: + + Find a file by name. The function will return NULL if the file is not found. + +Arguments: + + FileName The GUID file name of the file to search for. + File Return pointer. In the case of an error, contents are undefined. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_ABORTED An error was encountered. + EFI_INVALID_PARAMETER One of the parameters was NULL. + +--*/ +{ + EFI_FFS_FILE_HEADER *CurrentFile; + EFI_STATUS Status; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input parameters + // + if (FileName == NULL || File == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Get the first file + // + Status = GetNextFile (NULL, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "error parsing the FV", NULL); + return EFI_ABORTED; + } + // + // Loop as long as we have a valid file + // + while (CurrentFile) { + if (!CompareGuid (&CurrentFile->Name, FileName)) { + *File = CurrentFile; + return EFI_SUCCESS; + } + + Status = GetNextFile (CurrentFile, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "error parsing the FV", NULL); + return EFI_ABORTED; + } + } + // + // File not found in this FV. + // + *File = NULL; + return EFI_SUCCESS; +} + +EFI_STATUS +GetFileByType ( + IN EFI_FV_FILETYPE FileType, + IN UINTN Instance, + OUT EFI_FFS_FILE_HEADER **File + ) +/*++ + +Routine Description: + + Find a file by type and instance. An instance of 1 is the first instance. + The function will return NULL if a matching file cannot be found. + File type EFI_FV_FILETYPE_ALL means any file type is valid. + +Arguments: + + FileType Type of file to search for. + Instance Instace of the file type to return. + File Return pointer. In the case of an error, contents are undefined. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_ABORTED An error was encountered. + EFI_INVALID_PARAMETER One of the parameters was NULL. + +--*/ +{ + EFI_FFS_FILE_HEADER *CurrentFile; + EFI_STATUS Status; + UINTN FileCount; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input parameters + // + if (File == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Initialize the number of matching files found. + // + FileCount = 0; + + // + // Get the first file + // + Status = GetNextFile (NULL, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "error parsing FV", NULL); + return EFI_ABORTED; + } + // + // Loop as long as we have a valid file + // + while (CurrentFile) { + if (FileType == EFI_FV_FILETYPE_ALL || CurrentFile->Type == FileType) { + FileCount++; + } + + if (FileCount == Instance) { + *File = CurrentFile; + return EFI_SUCCESS; + } + + Status = GetNextFile (CurrentFile, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "error parsing the FV", NULL); + return EFI_ABORTED; + } + } + + *File = NULL; + return EFI_SUCCESS; +} + +EFI_STATUS +GetSectionByType ( + IN EFI_FFS_FILE_HEADER *File, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT EFI_FILE_SECTION_POINTER *Section + ) +/*++ + +Routine Description: + + Find a section in a file by type and instance. An instance of 1 is the first + instance. The function will return NULL if a matching section cannot be found. + The function will not handle encapsulating sections. + +Arguments: + + File The file to search. + SectionType Type of file to search for. + Instance Instace of the section to return. + Section Return pointer. In the case of an error, contents are undefined. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_ABORTED An error was encountered. + EFI_INVALID_PARAMETER One of the parameters was NULL. + EFI_NOT_FOUND No found. +--*/ +{ + EFI_FILE_SECTION_POINTER CurrentSection; + EFI_STATUS Status; + UINTN SectionCount; + + // + // Verify input parameters + // + if (File == NULL || Instance == 0) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FFS header + // + Status = VerifyFfsFile (File); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "invalid FFS file", NULL); + return EFI_ABORTED; + } + // + // Initialize the number of matching sections found. + // + SectionCount = 0; + + // + // Get the first section + // + CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + sizeof (EFI_FFS_FILE_HEADER)); + + // + // Loop as long as we have a valid file + // + while ((UINTN) CurrentSection.CommonHeader < (UINTN) File + GetLength (File->Size)) { + if (CurrentSection.CommonHeader->Type == SectionType) { + SectionCount++; + } + + if (SectionCount == Instance) { + *Section = CurrentSection; + return EFI_SUCCESS; + } + // + // Find next section (including compensating for alignment issues. + // + CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2)); + } + // + // Section not found + // + (*Section).Code16Section = NULL; + return EFI_NOT_FOUND; +} +// +// will not parse compressed sections +// +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +/*++ + +Routine Description: + + Verify the current pointer points to a valid FV header. + +Arguments: + + FvHeader Pointer to an alleged FV file. + +Returns: + + EFI_SUCCESS The FV header is valid. + EFI_VOLUME_CORRUPTED The FV header is not valid. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_ABORTED Operation aborted. + +--*/ +{ + UINT16 Checksum; + + // + // Verify input parameters + // + if (FvHeader == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (FvHeader->Signature != EFI_FVH_SIGNATURE) { + Error (NULL, 0, 0, "invalid FV header signature", NULL); + return EFI_VOLUME_CORRUPTED; + } + // + // Verify header checksum + // + Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + + if (Checksum != 0) { + Error (NULL, 0, 0, "invalid FV header checksum", NULL); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +VerifyFfsFile ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + Verify the current pointer points to a FFS file header. + +Arguments: + + FfsHeader Pointer to an alleged FFS file. + +Returns: + + EFI_SUCCESS The Ffs header is valid. + EFI_NOT_FOUND This "file" is the beginning of free space. + EFI_VOLUME_CORRUPTED The Ffs header is not valid. + EFI_ABORTED The erase polarity is not known. + +--*/ +{ + BOOLEAN ErasePolarity; + EFI_STATUS Status; + EFI_FFS_FILE_HEADER BlankHeader; + UINT8 Checksum; + UINT32 FileLength; + UINT32 OccupiedFileLength; + EFI_FFS_FILE_TAIL *Tail; + UINT8 SavedChecksum; + UINT8 SavedState; + UINT8 FileGuidString[80]; + UINT32 TailSize; + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Get the erase polarity. + // + Status = GetErasePolarity (&ErasePolarity); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Check if we have free space + // + if (ErasePolarity) { + memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER)); + } else { + memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); + } + + if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 0) { + return EFI_NOT_FOUND; + } + // + // Convert the GUID to a string so we can at least report which file + // if we find an error. + // + PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE); + if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailSize = sizeof (EFI_FFS_FILE_TAIL); + } else { + TailSize = 0; + } + // + // Verify file header checksum + // + SavedState = FfsHeader->State; + FfsHeader->State = 0; + SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File; + FfsHeader->IntegrityCheck.Checksum.File = 0; + Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER)); + FfsHeader->State = SavedState; + FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum; + if (Checksum != 0) { + Error (NULL, 0, 0, FileGuidString, "invalid FFS file header checksum"); + return EFI_ABORTED; + } + // + // Verify file checksum + // + if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Verify file data checksum + // + FileLength = GetLength (FfsHeader->Size); + OccupiedFileLength = (FileLength + 0x07) & (-1 << 3); + Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FileLength - TailSize); + Checksum = (UINT8) (Checksum - FfsHeader->State); + if (Checksum != 0) { + Error (NULL, 0, 0, FileGuidString, "invalid FFS file checksum"); + return EFI_ABORTED; + } + } else { + // + // File does not have a checksum + // Verify contents are 0x5A as spec'd + // + if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { + Error (NULL, 0, 0, FileGuidString, "invalid fixed FFS file header checksum"); + return EFI_ABORTED; + } + } + // + // Check if the tail is present and verify it if it is. + // + if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + // + // Verify tail is complement of integrity check field in the header. + // + Tail = (EFI_FFS_FILE_TAIL *) ((UINTN) FfsHeader + GetLength (FfsHeader->Size) - sizeof (EFI_FFS_FILE_TAIL)); + if (FfsHeader->IntegrityCheck.TailReference != (EFI_FFS_FILE_TAIL)~(*Tail)) { + Error (NULL, 0, 0, FileGuidString, "invalid FFS file tail"); + return EFI_ABORTED; + } + } + + return EFI_SUCCESS; +} + +UINT32 +GetLength ( + UINT8 *ThreeByteLength + ) +/*++ + +Routine Description: + + Converts a three byte length value into a UINT32. + +Arguments: + + ThreeByteLength Pointer to the first of the 3 byte length. + +Returns: + + UINT32 Size of the section + +--*/ +{ + UINT32 Length; + + if (ThreeByteLength == NULL) { + return 0; + } + + Length = *((UINT32 *) ThreeByteLength); + Length = Length & 0x00FFFFFF; + + return Length; +} + +EFI_STATUS +GetErasePolarity ( + OUT BOOLEAN *ErasePolarity + ) +/*++ + +Routine Description: + + This function returns with the FV erase polarity. If the erase polarity + for a bit is 1, the function return TRUE. + +Arguments: + + ErasePolarity A pointer to the erase polarity. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED Operation aborted. + +--*/ +{ + EFI_STATUS Status; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Verify input parameters. + // + if (ErasePolarity == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (mFvHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + *ErasePolarity = TRUE; + } else { + *ErasePolarity = FALSE; + } + + return EFI_SUCCESS; +} + +UINT8 +GetFileState ( + IN BOOLEAN ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + This function returns a the highest state bit in the FFS that is set. + It in no way validate the FFS file. + +Arguments: + + ErasePolarity The erase polarity for the file state bits. + FfsHeader Pointer to a FFS file. + +Returns: + + UINT8 The hightest set state of the file. + +--*/ +{ + UINT8 FileState; + UINT8 HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity) { + FileState = (UINT8)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} diff --git a/Tools/Source/TianoTools/Common/FvLib.h b/Tools/Source/TianoTools/Common/FvLib.h new file mode 100644 index 0000000000..4a10a3d364 --- /dev/null +++ b/Tools/Source/TianoTools/Common/FvLib.h @@ -0,0 +1,185 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + FvLib.h + +Abstract: + + These functions assist in parsing and manipulating a Firmware Volume. + +--*/ + +#ifndef _EFI_FV_LIB_H +#define _EFI_FV_LIB_H + +// +// Include files +// +#include +#include +#include +#include +#include +#include +/* +#include "TianoCommon.h" +#include "EfiFirmwareVolumeHeader.h" +#include "EfiFirmwareFileSystem.h" +*/ +#include + +EFI_STATUS +InitializeFvLib ( + IN VOID *Fv, + IN UINT32 FvLength + ) +; + +EFI_STATUS +GetFvHeader ( + OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader, + OUT UINT32 *FvLength + ) +; + +EFI_STATUS +GetNextFile ( + IN EFI_FFS_FILE_HEADER *CurrentFile, + OUT EFI_FFS_FILE_HEADER **NextFile + ) +; + +EFI_STATUS +GetFileByName ( + IN EFI_GUID *FileName, + OUT EFI_FFS_FILE_HEADER **File + ) +; + +EFI_STATUS +GetFileByType ( + IN EFI_FV_FILETYPE FileType, + IN UINTN Instance, + OUT EFI_FFS_FILE_HEADER **File + ) +; + +EFI_STATUS +GetSectionByType ( + IN EFI_FFS_FILE_HEADER *File, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT EFI_FILE_SECTION_POINTER *Section + ) +; +// +// will not parse compressed sections +// +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +; + +EFI_STATUS +VerifyFfsFile ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +; + +/*++ + +Routine Description: + + Verify the current pointer points to a FFS file header. + +Arguments: + + FfsHeader Pointer to an alleged FFS file. + +Returns: + + EFI_SUCCESS The Ffs header is valid. + EFI_NOT_FOUND This "file" is the beginning of free space. + EFI_VOLUME_CORRUPTED The Ffs header is not valid. + +--*/ +UINT32 +GetLength ( + UINT8 *ThreeByteLength + ) +; + +/*++ + +Routine Description: + + Converts a three byte length value into a UINT32. + +Arguments: + + ThreeByteLength Pointer to the first of the 3 byte length. + +Returns: + + UINT32 Size of the section + +--*/ +EFI_STATUS +GetErasePolarity ( + OUT BOOLEAN *ErasePolarity + ) +; + +/*++ + +Routine Description: + + This function returns with the FV erase polarity. If the erase polarity + for a bit is 1, the function return TRUE. + +Arguments: + + ErasePolarity A pointer to the erase polarity. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + +--*/ +UINT8 +GetFileState ( + IN BOOLEAN ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +; + +/*++ + +Routine Description: + + This function returns a the highest state bit in the FFS that is set. + It in no way validate the FFS file. + +Arguments: + + ErasePolarity The erase polarity for the file state bits. + FfsHeader Pointer to a FFS file. + +Returns: + + UINT8 The hightest set state of the file. + +--*/ +#endif diff --git a/Tools/Source/TianoTools/Common/MyAlloc.c b/Tools/Source/TianoTools/Common/MyAlloc.c new file mode 100644 index 0000000000..39fddf7428 --- /dev/null +++ b/Tools/Source/TianoTools/Common/MyAlloc.c @@ -0,0 +1,516 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + MyAlloc.c + +Abstract: + + File for memory allocation tracking functions. + +--*/ + +#include "MyAlloc.h" + +#if USE_MYALLOC +// +// Get back to original alloc/free calls. +// +#undef malloc +#undef calloc +#undef realloc +#undef free +// +// Start of allocation list. +// +static MY_ALLOC_STRUCT *MyAllocData = NULL; + +// +// +// +static UINT32 MyAllocHeadMagik = MYALLOC_HEAD_MAGIK; +static UINT32 MyAllocTailMagik = MYALLOC_TAIL_MAGIK; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// +VOID +MyCheck ( + BOOLEAN Final, + UINT8 File[], + UINTN Line + ) +// *++ +// Description: +// +// Check for corruptions in the allocated memory chain. If a corruption +// is detection program operation stops w/ an exit(1) call. +// +// Parameters: +// +// Final := When FALSE, MyCheck() returns if the allocated memory chain +// has not been corrupted. When TRUE, MyCheck() returns if there +// are no un-freed allocations. If there are un-freed allocations, +// they are displayed and exit(1) is called. +// +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// n/a +// +// --*/ +// +{ + MY_ALLOC_STRUCT *Tmp; + + // + // Check parameters. + // + if (File == NULL || Line == 0) { + printf ( + "\nMyCheck(Final=%u, File=%xh, Line=%u)" + "Invalid parameter(s).\n", + Final, + File, + Line + ); + + exit (1); + } + + if (strlen (File) == 0) { + printf ( + "\nMyCheck(Final=%u, File=%s, Line=%u)" + "Invalid parameter.\n", + Final, + File, + Line + ); + + exit (1); + } + // + // Check structure contents. + // + for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) { + if (memcmp(Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik) || + memcmp(&Tmp->Buffer[Tmp->Size + sizeof(UINT32)], &MyAllocTailMagik, sizeof MyAllocTailMagik)) { + break; + } + } + // + // If Tmp is not NULL, the structure is corrupt. + // + if (Tmp != NULL) { + printf ( + "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!" + "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n", + Final, + File, + Line, + Tmp->File, + Tmp->Line, + Tmp->Size, + *(UINT32 *) (Tmp->Buffer), + *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)]) + ); + + exit (1); + } + // + // If Final is TRUE, display the state of the structure chain. + // + if (Final) { + if (MyAllocData != NULL) { + printf ( + "\nMyCheck(Final=%u, File=%s, Line=%u)" + "\nSome allocated items have not been freed.\n", + Final, + File, + Line + ); + + for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) { + printf ( + "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n", + Tmp->File, + Tmp->Line, + Tmp->Size, + *(UINT32 *) (Tmp->Buffer), + *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)]) + ); + } + } + } +} +// +// //////////////////////////////////////////////////////////////////////////// +// +// +VOID * +MyAlloc ( + UINTN Size, + UINT8 File[], + UINTN Line + ) +// *++ +// Description: +// +// Allocate a new link in the allocation chain along with enough storage +// for the File[] string, requested Size and alignment overhead. If +// memory cannot be allocated or the allocation chain has been corrupted, +// exit(1) will be called. +// +// Parameters: +// +// Size := Number of bytes (UINT8) requested by the called. +// Size cannot be zero. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// Pointer to the caller's buffer. +// +// --*/ +// +{ + MY_ALLOC_STRUCT *Tmp; + UINTN Len; + + // + // Check for invalid parameters. + // + if (Size == 0 || File == NULL || Line == 0) { + printf ( + "\nMyAlloc(Size=%u, File=%xh, Line=%u)" + "\nInvalid parameter(s).\n", + Size, + File, + Line + ); + + exit (1); + } + + Len = strlen (File); + if (Len == 0) { + printf ( + "\nMyAlloc(Size=%u, File=%s, Line=%u)" + "\nInvalid parameter.\n", + Size, + File, + Line + ); + + exit (1); + } + // + // Check the allocation list for corruption. + // + MyCheck (0, __FILE__, __LINE__); + + // + // Allocate a new entry. + // + Tmp = calloc ( + 1, + sizeof (MY_ALLOC_STRUCT) + Len + 1 + sizeof (UINT64) + Size + (sizeof MyAllocHeadMagik) + (sizeof MyAllocTailMagik) + ); + + if (Tmp == NULL) { + printf ( + "\nMyAlloc(Size=%u, File=%s, Line=%u)" + "\nOut of memory.\n", + Size, + File, + Line + ); + + exit (1); + } + // + // Fill in the new entry. + // + Tmp->File = ((UINT8 *) Tmp) + sizeof (MY_ALLOC_STRUCT); + strcpy (Tmp->File, File); + Tmp->Line = Line; + Tmp->Size = Size; + Tmp->Buffer = (UINT8 *) (((UINTN) Tmp + Len + 9) &~7); + + memcpy (Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik); + + memcpy ( + &Tmp->Buffer[Size + sizeof (UINT32)], + &MyAllocTailMagik, + sizeof MyAllocTailMagik + ); + + Tmp->Next = MyAllocData; + Tmp->Cksum = (UINTN) Tmp + (UINTN) (Tmp->Next) + Tmp->Line + Tmp->Size + (UINTN) (Tmp->File) + (UINTN) (Tmp->Buffer); + + MyAllocData = Tmp; + + return Tmp->Buffer + sizeof (UINT32); +} +// +// //////////////////////////////////////////////////////////////////////////// +// +// +VOID * +MyRealloc ( + VOID *Ptr, + UINTN Size, + UINT8 File[], + UINTN Line + ) +// *++ +// Description: +// +// This does a MyAlloc(), memcpy() and MyFree(). There is no optimization +// for shrinking or expanding buffers. An invalid parameter will cause +// MyRealloc() to fail with a call to exit(1). +// +// Parameters: +// +// Ptr := Pointer to the caller's buffer to be re-allocated. +// +// Size := Size of new buffer. Size cannot be zero. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// Pointer to new caller's buffer. +// +// --*/ +// +{ + MY_ALLOC_STRUCT *Tmp; + VOID *Buffer; + + // + // Check for invalid parameter(s). + // + if (Size == 0 || File == NULL || Line == 0) { + printf ( + "\nMyRealloc(Ptr=%xh, Size=%u, File=%xh, Line=%u)" + "\nInvalid parameter(s).\n", + Ptr, + Size, + File, + Line + ); + + exit (1); + } + + if (strlen (File) == 0) { + printf ( + "\nMyRealloc(Ptr=%xh, Size=%u, File=%s, Line=%u)" + "\nInvalid parameter.\n", + Ptr, + Size, + File, + Line + ); + + exit (1); + } + // + // Find existing buffer in allocation list. + // + if (Ptr == NULL) { + Tmp = NULL; + } else if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) { + Tmp = MyAllocData; + } else { + for (Tmp = MyAllocData;; Tmp = Tmp->Next) { + if (Tmp->Next == NULL) { + printf ( + "\nMyRealloc(Ptr=%xh, Size=%u, File=%s, Line=%u)" + "\nCould not find buffer.\n", + Ptr, + Size, + File, + Line + ); + + exit (1); + } + + Tmp = Tmp->Next; + } + } + // + // Allocate new buffer, copy old data, free old buffer. + // + Buffer = MyAlloc (Size, File, Line); + + if (Buffer != NULL && Tmp != NULL) { + memcpy ( + Buffer, + &Tmp->Buffer[sizeof (UINT32)], + ((Size <= Tmp->Size) ? Size : Tmp->Size) + ); + + MyFree (Ptr, __FILE__, __LINE__); + } + + return Buffer; +} +// +// //////////////////////////////////////////////////////////////////////////// +// +// +VOID +MyFree ( + VOID *Ptr, + UINT8 File[], + UINTN Line + ) +// *++ +// Description: +// +// Release a previously allocated buffer. Invalid parameters will cause +// MyFree() to fail with an exit(1) call. +// +// Parameters: +// +// Ptr := Pointer to the caller's buffer to be freed. +// A NULL pointer will be ignored. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// n/a +// +// --*/ +// +{ + MY_ALLOC_STRUCT *Tmp; + MY_ALLOC_STRUCT *Tmp2; + + // + // Check for invalid parameter(s). + // + if (File == NULL || Line == 0) { + printf ( + "\nMyFree(Ptr=%xh, File=%xh, Line=%u)" + "\nInvalid parameter(s).\n", + Ptr, + File, + Line + ); + + exit (1); + } + + if (strlen (File) == 0) { + printf ( + "\nMyFree(Ptr=%xh, File=%s, Line=%u)" + "\nInvalid parameter.\n", + Ptr, + File, + Line + ); + + exit (1); + } + // + // Freeing NULL is always valid. + // + if (Ptr == NULL) { + return ; + } + // + // Fail if nothing is allocated. + // + if (MyAllocData == NULL) { + printf ( + "\nMyFree(Ptr=%xh, File=%s, Line=%u)" + "\nCalled before memory allocated.\n", + Ptr, + File, + Line + ); + + exit (1); + } + // + // Check for corrupted allocation list. + // + MyCheck (0, __FILE__, __LINE__); + + // + // Need special check for first item in list. + // + if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) { + // + // Unlink first item in list. + // + Tmp = MyAllocData; + MyAllocData = MyAllocData->Next; + } else { + // + // Walk list looking for matching item. + // + for (Tmp = MyAllocData;; Tmp = Tmp->Next) { + // + // Fail if end of list is reached. + // + if (Tmp->Next == NULL) { + printf ( + "\nMyFree(Ptr=%xh, File=%s, Line=%u)\n" + "\nNot found.\n", + Ptr, + File, + Line + ); + + exit (1); + } + // + // Leave loop when match is found. + // + if (&Tmp->Next->Buffer[sizeof (UINT32)] == Ptr) { + break; + } + } + // + // Unlink item from list. + // + Tmp2 = Tmp->Next; + Tmp->Next = Tmp->Next->Next; + Tmp = Tmp2; + } + // + // Release item. + // + free (Tmp); +} + +#endif /* USE_MYALLOC */ + +/* eof - MyAlloc.c */ diff --git a/Tools/Source/TianoTools/Common/MyAlloc.h b/Tools/Source/TianoTools/Common/MyAlloc.h new file mode 100644 index 0000000000..d766682ea1 --- /dev/null +++ b/Tools/Source/TianoTools/Common/MyAlloc.h @@ -0,0 +1,225 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + MyAlloc.h + +Abstract: + + Header file for memory allocation tracking functions. + +--*/ + +#ifndef _MYALLOC_H_ +#define _MYALLOC_H_ + +#include +#include +#include +#include + +/* +#include "Tiano.h" +*/ + +// +// Default operation is to use the memory allocation tracking functions. +// To over-ride add "#define USE_MYALLOC 0" to your program header and/or +// source files as needed. Or, just do not include this header file in +// your project. +// +#ifndef USE_MYALLOC +#define USE_MYALLOC 1 +#endif + +#if USE_MYALLOC +// +// Replace C library allocation routines with MyAlloc routines. +// +#define malloc(size) MyAlloc ((size), __FILE__, __LINE__) +#define calloc(count, size) MyAlloc ((count) * (size), __FILE__, __LINE__) +#define realloc(ptr, size) MyRealloc ((ptr), (size), __FILE__, __LINE__) +#define free(ptr) MyFree ((ptr), __FILE__, __LINE__) +#define alloc_check(final) MyCheck ((final), __FILE__, __LINE__) + +// +// Structure for checking/tracking memory allocations. +// +typedef struct MyAllocStruct { + UINTN Cksum; + struct MyAllocStruct *Next; + UINTN Line; + UINTN Size; + UINT8 *File; + UINT8 *Buffer; +} MY_ALLOC_STRUCT; +// +// Cksum := (UINTN)This + (UINTN)Next + Line + Size + (UINTN)File + +// (UINTN)Buffer; +// +// Next := Pointer to next allocation structure in the list. +// +// Line := __LINE__ +// +// Size := Size of allocation request. +// +// File := Pointer to __FILE__ string stored immediately following +// MY_ALLOC_STRUCT in memory. +// +// Buffer := Pointer to UINT32 aligned storage immediately following +// the NULL terminated __FILE__ string. This is UINT32 +// aligned because the underflow signature is 32-bits and +// this will place the first caller address on a 64-bit +// boundary. +// +// +// Signatures used to check for buffer overflow/underflow conditions. +// +#define MYALLOC_HEAD_MAGIK 0xBADFACED +#define MYALLOC_TAIL_MAGIK 0xDEADBEEF + +VOID +MyCheck ( + BOOLEAN Final, + UINT8 File[], + UINTN Line + ) +; +// +// *++ +// Description: +// +// Check for corruptions in the allocated memory chain. If a corruption +// is detection program operation stops w/ an exit(1) call. +// +// Parameters: +// +// Final := When FALSE, MyCheck() returns if the allocated memory chain +// has not been corrupted. When TRUE, MyCheck() returns if there +// are no un-freed allocations. If there are un-freed allocations, +// they are displayed and exit(1) is called. +// +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// n/a +// +// --*/ +// +VOID * +MyAlloc ( + UINTN Size, + UINT8 File[], + UINTN Line + ) +; +// +// *++ +// Description: +// +// Allocate a new link in the allocation chain along with enough storage +// for the File[] string, requested Size and alignment overhead. If +// memory cannot be allocated or the allocation chain has been corrupted, +// exit(1) will be called. +// +// Parameters: +// +// Size := Number of bytes (UINT8) requested by the called. +// Size cannot be zero. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// Pointer to the caller's buffer. +// +// --*/ +// +VOID * +MyRealloc ( + VOID *Ptr, + UINTN Size, + UINT8 File[], + UINTN Line + ) +; +// +// *++ +// Description: +// +// This does a MyAlloc(), memcpy() and MyFree(). There is no optimization +// for shrinking or expanding buffers. An invalid parameter will cause +// MyRealloc() to fail with a call to exit(1). +// +// Parameters: +// +// Ptr := Pointer to the caller's buffer to be re-allocated. +// Ptr cannot be NULL. +// +// Size := Size of new buffer. Size cannot be zero. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// Pointer to new caller's buffer. +// +// --*/ +// +VOID +MyFree ( + VOID *Ptr, + UINT8 File[], + UINTN Line + ) +; +// +// *++ +// Description: +// +// Release a previously allocated buffer. Invalid parameters will cause +// MyFree() to fail with an exit(1) call. +// +// Parameters: +// +// Ptr := Pointer to the caller's buffer to be freed. +// A NULL pointer will be ignored. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// n/a +// +// --*/ +// +#else /* USE_MYALLOC */ + +// +// Nothing to do when USE_MYALLOC is zero. +// +#define alloc_check(final) + +#endif /* USE_MYALLOC */ +#endif /* _MYALLOC_H_ */ + +/* eof - MyAlloc.h */ diff --git a/Tools/Source/TianoTools/Common/ParseInf.c b/Tools/Source/TianoTools/Common/ParseInf.c new file mode 100644 index 0000000000..989add7e9c --- /dev/null +++ b/Tools/Source/TianoTools/Common/ParseInf.c @@ -0,0 +1,630 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + ParseInf.c + +Abstract: + + This contains some useful functions for parsing INF files. + +--*/ + +#include "ParseInf.h" +#include +#include +#include +#include + +#ifndef _MAX_PATH +#define _MAX_PATH 500 +#endif + +CHAR8 * +ReadLine ( + IN MEMORY_FILE *InputFile, + IN OUT CHAR8 *InputBuffer, + IN UINTN MaxLength + ) +/*++ + +Routine Description: + + This function reads a line, stripping any comments. + The function reads a string from the input stream argument and stores it in + the input string. ReadLine reads characters from the current file position + to and including the first newline character, to the end of the stream, or + until the number of characters read is equal to MaxLength - 1, whichever + comes first. The newline character, if read, is replaced with a \0. + +Arguments: + + InputFile Memory file image. + InputBuffer Buffer to read into, must be _MAX_PATH size. + MaxLength The maximum size of the input buffer. + +Returns: + + NULL if error or EOF + InputBuffer otherwise + +--*/ +{ + CHAR8 *CharPtr; + CHAR8 *EndOfLine; + UINTN CharsToCopy; + + // + // Verify input parameters are not null + // + assert (InputBuffer); + assert (InputFile->FileImage); + assert (InputFile->Eof); + assert (InputFile->CurrentFilePointer); + + // + // Check for end of file condition + // + if (InputFile->CurrentFilePointer >= InputFile->Eof) { + return NULL; + } + // + // Find the next newline char + // + EndOfLine = strchr (InputFile->CurrentFilePointer, '\n'); + + // + // Determine the number of characters to copy. + // + if (EndOfLine == 0) { + // + // If no newline found, copy to the end of the file. + // + CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer; + } else if (EndOfLine >= InputFile->Eof) { + // + // If the newline found was beyond the end of file, copy to the eof. + // + CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer; + } else { + // + // Newline found in the file. + // + CharsToCopy = EndOfLine - InputFile->CurrentFilePointer; + } + // + // If the end of line is too big for the current buffer, set it to the max + // size of the buffer (leaving room for the \0. + // + if (CharsToCopy > MaxLength - 1) { + CharsToCopy = MaxLength - 1; + } + // + // Copy the line. + // + memcpy (InputBuffer, InputFile->CurrentFilePointer, CharsToCopy); + + // + // Add the null termination over the 0x0D + // + InputBuffer[CharsToCopy - 1] = '\0'; + + // + // Increment the current file pointer (include the 0x0A) + // + InputFile->CurrentFilePointer += CharsToCopy + 1; + + // + // Strip any comments + // + CharPtr = strstr (InputBuffer, "//"); + if (CharPtr != 0) { + CharPtr[0] = 0; + } + // + // Return the string + // + return InputBuffer; +} + +BOOLEAN +FindSection ( + IN MEMORY_FILE *InputFile, + IN CHAR8 *Section + ) +/*++ + +Routine Description: + + This function parses a file from the beginning to find a section. + The section string may be anywhere within a line. + +Arguments: + + InputFile Memory file image. + Section Section to search for + +Returns: + + FALSE if error or EOF + TRUE if section found + +--*/ +{ + CHAR8 InputBuffer[_MAX_PATH]; + CHAR8 *CurrentToken; + + // + // Verify input is not NULL + // + assert (InputFile->FileImage); + assert (InputFile->Eof); + assert (InputFile->CurrentFilePointer); + assert (Section); + + // + // Rewind to beginning of file + // + InputFile->CurrentFilePointer = InputFile->FileImage; + + // + // Read lines until the section is found + // + while (InputFile->CurrentFilePointer < InputFile->Eof) { + // + // Read a line + // + ReadLine (InputFile, InputBuffer, _MAX_PATH); + + // + // Check if the section is found + // + CurrentToken = strstr (InputBuffer, Section); + if (CurrentToken != NULL) { + return TRUE; + } + } + + return FALSE; +} + +EFI_STATUS +FindToken ( + IN MEMORY_FILE *InputFile, + IN CHAR8 *Section, + IN CHAR8 *Token, + IN UINTN Instance, + OUT CHAR8 *Value + ) +/*++ + +Routine Description: + + Finds a token value given the section and token to search for. + +Arguments: + + InputFile Memory file image. + Section The section to search for, a string within []. + Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file. + Instance The instance of the token to search for. Zero is the first instance. + Value The string that holds the value following the =. Must be _MAX_PATH in size. + +Returns: + + EFI_SUCCESS Value found. + EFI_ABORTED Format error detected in INF file. + EFI_INVALID_PARAMETER Input argument was null. + EFI_LOAD_ERROR Error reading from the file. + EFI_NOT_FOUND Section/Token/Value not found. + +--*/ +{ + CHAR8 InputBuffer[_MAX_PATH]; + CHAR8 *CurrentToken; + BOOLEAN ParseError; + BOOLEAN ReadError; + UINTN Occurrance; + + // + // Check input parameters + // + if (InputFile->FileImage == NULL || + InputFile->Eof == NULL || + InputFile->CurrentFilePointer == NULL || + Section == NULL || + strlen (Section) == 0 || + Token == NULL || + strlen (Token) == 0 || + Value == NULL + ) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize error codes + // + ParseError = FALSE; + ReadError = FALSE; + + // + // Initialize our instance counter for the search token + // + Occurrance = 0; + + if (FindSection (InputFile, Section)) { + // + // Found the desired section, find and read the desired token + // + do { + // + // Read a line from the file + // + if (ReadLine (InputFile, InputBuffer, _MAX_PATH) == NULL) { + // + // Error reading from input file + // + ReadError = TRUE; + break; + } + // + // Get the first non-whitespace string + // + CurrentToken = strtok (InputBuffer, " \t\n"); + if (CurrentToken == NULL) { + // + // Whitespace line found (or comment) so continue + // + CurrentToken = InputBuffer; + continue; + } + // + // Make sure we have not reached the end of the current section + // + if (CurrentToken[0] == '[') { + break; + } + // + // Compare the current token with the desired token + // + if (strcmp (CurrentToken, Token) == 0) { + // + // Found it + // + // + // Check if it is the correct instance + // + if (Instance == Occurrance) { + // + // Copy the contents following the = + // + CurrentToken = strtok (NULL, "= \t\n"); + if (CurrentToken == NULL) { + // + // Nothing found, parsing error + // + ParseError = TRUE; + } else { + // + // Copy the current token to the output value + // + strcpy (Value, CurrentToken); + return EFI_SUCCESS; + } + } else { + // + // Increment the occurrance found + // + Occurrance++; + } + } + } while ( + !ParseError && + !ReadError && + InputFile->CurrentFilePointer < InputFile->Eof && + CurrentToken[0] != '[' && + Occurrance <= Instance + ); + } + // + // Distinguish between read errors and INF file format errors. + // + if (ReadError) { + return EFI_LOAD_ERROR; + } + + if (ParseError) { + return EFI_ABORTED; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +StringToGuid ( + IN CHAR8 *AsciiGuidBuffer, + OUT EFI_GUID *GuidBuffer + ) +/*++ + +Routine Description: + + Converts a string to an EFI_GUID. The string must be in the + xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format. + +Arguments: + + AsciiGuidBuffer - pointer to ascii string + GuidBuffer - pointer to destination Guid + +Returns: + + EFI_ABORTED Could not convert the string + EFI_SUCCESS The string was successfully converted + EFI_INVALID_PARAMETER Input parameter is invalid. + +--*/ +{ + INT32 Index; + UINTN Data1; + UINTN Data2; + UINTN Data3; + UINTN Data4[8]; + + if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Scan the guid string into the buffer + // + Index = sscanf ( + AsciiGuidBuffer, + "%08x-%04x-%04x-%02x%02x-%02hx%02hx%02hx%02hx%02hx%02hx", + &Data1, + &Data2, + &Data3, + &Data4[0], + &Data4[1], + &Data4[2], + &Data4[3], + &Data4[4], + &Data4[5], + &Data4[6], + &Data4[7] + ); + + // + // Verify the correct number of items were scanned. + // + if (Index != 11) { + printf ("ERROR: Malformed GUID \"%s\".\n\n", AsciiGuidBuffer); + return EFI_ABORTED; + } + // + // Copy the data into our GUID. + // + GuidBuffer->Data1 = (UINT32) Data1; + GuidBuffer->Data2 = (UINT16) Data2; + GuidBuffer->Data3 = (UINT16) Data3; + GuidBuffer->Data4[0] = (UINT8) Data4[0]; + GuidBuffer->Data4[1] = (UINT8) Data4[1]; + GuidBuffer->Data4[2] = (UINT8) Data4[2]; + GuidBuffer->Data4[3] = (UINT8) Data4[3]; + GuidBuffer->Data4[4] = (UINT8) Data4[4]; + GuidBuffer->Data4[5] = (UINT8) Data4[5]; + GuidBuffer->Data4[6] = (UINT8) Data4[6]; + GuidBuffer->Data4[7] = (UINT8) Data4[7]; + + return EFI_SUCCESS; +} + +EFI_STATUS +AsciiStringToUint64 ( + IN CONST CHAR8 *AsciiString, + IN BOOLEAN IsHex, + OUT UINT64 *ReturnValue + ) +/*++ + +Routine Description: + + Converts a null terminated ascii string that represents a number into a + UINT64 value. A hex number may be preceeded by a 0x, but may not be + succeeded by an h. A number without 0x or 0X is considered to be base 10 + unless the IsHex input is true. + +Arguments: + + AsciiString The string to convert. + IsHex Force the string to be treated as a hex number. + ReturnValue The return value. + +Returns: + + EFI_SUCCESS Number successfully converted. + EFI_ABORTED Invalid character encountered. + +--*/ +{ + UINT8 Index; + UINT64 HexNumber; + CHAR8 CurrentChar; + + // + // Initialize the result + // + HexNumber = 0; + + // + // Add each character to the result + // + if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) { + // + // Verify string is a hex number + // + for (Index = 2; Index < strlen (AsciiString); Index++) { + if (isxdigit (AsciiString[Index]) == 0) { + return EFI_ABORTED; + } + } + // + // Convert the hex string. + // + for (Index = 2; AsciiString[Index] != '\0'; Index++) { + CurrentChar = AsciiString[Index]; + HexNumber *= 16; + if (CurrentChar >= '0' && CurrentChar <= '9') { + HexNumber += CurrentChar - '0'; + } else if (CurrentChar >= 'a' && CurrentChar <= 'f') { + HexNumber += CurrentChar - 'a' + 10; + } else if (CurrentChar >= 'A' && CurrentChar <= 'F') { + HexNumber += CurrentChar - 'A' + 10; + } else { + // + // Unrecognized character + // + return EFI_ABORTED; + } + } + + *ReturnValue = HexNumber; + } else { + // + // Verify string is a number + // + for (Index = 0; Index < strlen (AsciiString); Index++) { + if (isdigit (AsciiString[Index]) == 0) { + return EFI_ABORTED; + } + } + + *ReturnValue = atol (AsciiString); + } + + return EFI_SUCCESS; +}; + +CHAR8 * +ReadLineInStream ( + IN FILE *InputFile, + IN OUT CHAR8 *InputBuffer + ) +/*++ + +Routine Description: + + This function reads a line, stripping any comments. + // BUGBUG: This is obsolete once genmake goes away... + +Arguments: + + InputFile Stream pointer. + InputBuffer Buffer to read into, must be _MAX_PATH size. + +Returns: + + NULL if error or EOF + InputBuffer otherwise + +--*/ +{ + CHAR8 *CharPtr; + + // + // Verify input parameters are not null + // + assert (InputFile); + assert (InputBuffer); + + // + // Read a line + // + if (fgets (InputBuffer, _MAX_PATH, InputFile) == NULL) { + return NULL; + } + // + // Strip any comments + // + CharPtr = strstr (InputBuffer, "//"); + if (CharPtr != 0) { + CharPtr[0] = 0; + } + + CharPtr = strstr (InputBuffer, "#"); + if (CharPtr != 0) { + CharPtr[0] = 0; + } + // + // Return the string + // + return InputBuffer; +} + +BOOLEAN +FindSectionInStream ( + IN FILE *InputFile, + IN CHAR8 *Section + ) +/*++ + +Routine Description: + + This function parses a stream file from the beginning to find a section. + The section string may be anywhere within a line. + // BUGBUG: This is obsolete once genmake goes away... + +Arguments: + + InputFile Stream pointer. + Section Section to search for + +Returns: + + FALSE if error or EOF + TRUE if section found + +--*/ +{ + CHAR8 InputBuffer[_MAX_PATH]; + CHAR8 *CurrentToken; + + // + // Verify input is not NULL + // + assert (InputFile); + assert (Section); + + // + // Rewind to beginning of file + // + if (fseek (InputFile, 0, SEEK_SET) != 0) { + return FALSE; + } + // + // Read lines until the section is found + // + while (feof (InputFile) == 0) { + // + // Read a line + // + ReadLineInStream (InputFile, InputBuffer); + + // + // Check if the section is found + // + CurrentToken = strstr (InputBuffer, Section); + if (CurrentToken != NULL) { + return TRUE; + } + } + + return FALSE; +} diff --git a/Tools/Source/TianoTools/Common/ParseInf.h b/Tools/Source/TianoTools/Common/ParseInf.h new file mode 100644 index 0000000000..5691e53194 --- /dev/null +++ b/Tools/Source/TianoTools/Common/ParseInf.h @@ -0,0 +1,235 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + ParseInf.h + +Abstract: + + Header file for helper functions useful for parsing INF files. + +--*/ + +#ifndef _EFI_PARSE_INF_H +#define _EFI_PARSE_INF_H + +/* #include "TianoCommon.h" */ +#include +#include +#include +#include + +// +// Common data structures +// +typedef struct { + CHAR8 *FileImage; + CHAR8 *Eof; + CHAR8 *CurrentFilePointer; +} MEMORY_FILE; + +// +// Functions declarations +// +CHAR8 * +ReadLine ( + IN MEMORY_FILE *InputFile, + IN OUT CHAR8 *InputBuffer, + IN UINT32 MaxLength + ) +; + +/*++ + +Routine Description: + + This function reads a line, stripping any comments. + The function reads a string from the input stream argument and stores it in + the input string. ReadLine reads characters from the current file position + to and including the first newline character, to the end of the stream, or + until the number of characters read is equal to MaxLength - 1, whichever + comes first. The newline character, if read, is replaced with a \0. + +Arguments: + + InputFile Memory file image. + InputBuffer Buffer to read into, must be _MAX_PATH size. + MaxLength The maximum size of the input buffer. + +Returns: + + NULL if error or EOF + InputBuffer otherwise + +--*/ +BOOLEAN +FindSection ( + IN MEMORY_FILE *InputFile, + IN CHAR8 *Section + ) +; + +/*++ + +Routine Description: + + This function parses a file from the beginning to find a section. + The section string may be anywhere within a line. + +Arguments: + + InputFile Memory file image. + Section Section to search for + +Returns: + + FALSE if error or EOF + TRUE if section found + +--*/ +EFI_STATUS +FindToken ( + IN MEMORY_FILE *InputFile, + IN CHAR8 *Section, + IN CHAR8 *Token, + IN UINTN Instance, + OUT CHAR8 *Value + ) +; + +/*++ + +Routine Description: + + Finds a token value given the section and token to search for. + +Arguments: + + InputFile Memory file image. + Section The section to search for, a string within []. + Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file. + Instance The instance of the token to search for. Zero is the first instance. + Value The string that holds the value following the =. Must be _MAX_PATH in size. + +Returns: + + EFI_SUCCESS Value found. + EFI_ABORTED Format error detected in INF file. + EFI_INVALID_PARAMETER Input argument was null. + EFI_LOAD_ERROR Error reading from the file. + EFI_NOT_FOUND Section/Token/Value not found. + +--*/ +EFI_STATUS +StringToGuid ( + IN CHAR8 *AsciiGuidBuffer, + OUT EFI_GUID *GuidBuffer + ) +; + +/*++ + +Routine Description: + + Converts a string to an EFI_GUID. The string must be in the + xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format. + +Arguments: + + GuidBuffer - pointer to destination Guid + AsciiGuidBuffer - pointer to ascii string + +Returns: + + EFI_ABORTED Could not convert the string + EFI_SUCCESS The string was successfully converted + +--*/ +EFI_STATUS +AsciiStringToUint64 ( + IN CONST CHAR8 *AsciiString, + IN BOOLEAN IsHex, + OUT UINT64 *ReturnValue + ) +; + +/*++ + +Routine Description: + + Converts a null terminated ascii string that represents a number into a + UINT64 value. A hex number may be preceeded by a 0x, but may not be + succeeded by an h. A number without 0x or 0X is considered to be base 10 + unless the IsHex input is true. + +Arguments: + + AsciiString The string to convert. + IsHex Force the string to be treated as a hex number. + ReturnValue The return value. + +Returns: + + EFI_SUCCESS Number successfully converted. + EFI_ABORTED Invalid character encountered. + +--*/ +CHAR8 * +ReadLineInStream ( + IN FILE *InputFile, + IN OUT CHAR8 *InputBuffer + ) +; + +/*++ + +Routine Description: + + This function reads a line, stripping any comments. + +Arguments: + + InputFile Stream pointer. + InputBuffer Buffer to read into, must be _MAX_PATH size. + +Returns: + + NULL if error or EOF + InputBuffer otherwise + +--*/ +BOOLEAN +FindSectionInStream ( + IN FILE *InputFile, + IN CHAR8 *Section + ) +; + +/*++ + +Routine Description: + + This function parses a stream file from the beginning to find a section. + The section string may be anywhere within a line. + +Arguments: + + InputFile Stream pointer. + Section Section to search for + +Returns: + + FALSE if error or EOF + TRUE if section found + +--*/ +#endif diff --git a/Tools/Source/TianoTools/Common/PeiLib/Debug.c b/Tools/Source/TianoTools/Common/PeiLib/Debug.c new file mode 100644 index 0000000000..9094eb2802 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Debug.c @@ -0,0 +1,131 @@ +/*++ + +Copyright (c) 2004 - 2005, 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. + +Module Name: + + Debug.c + +Abstract: + + Support for Debug primatives. + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "EfiPrintLib.h" +#include "EfiStatusCode.h" +#include "EfiCommonLib.h" +#include EFI_GUID_DEFINITION (StatusCodeCallerId) +#include EFI_GUID_DEFINITION (StatusCodeDataTypeId) + +VOID +PeiDebugAssert ( + IN EFI_PEI_SERVICES **PeiServices, + IN CHAR8 *FileName, + IN INTN LineNumber, + IN CHAR8 *Description + ) +/*++ + +Routine Description: + + Worker function for ASSERT(). If Error Logging hub is loaded log ASSERT + information. If Error Logging hub is not loaded DEADLOOP (). + +Arguments: + + PeiServices - The PEI core services table. + + FileName - File name of failing routine. + + LineNumber - Line number of failing ASSERT(). + + Description - Description, usually the assertion, + +Returns: + + None + +--*/ +{ + UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE]; + + EfiDebugAssertWorker (FileName, LineNumber, Description, sizeof (Buffer), Buffer); + + // + // We choose NOT to use PEI_REPORT_STATUS_CODE here, because when debug is enable, + // we want get enough information if assert. + // + (**PeiServices).PeiReportStatusCode ( + PeiServices, + (EFI_ERROR_CODE | EFI_ERROR_UNRECOVERED), + (EFI_SOFTWARE_PEI_MODULE | EFI_SW_EC_ILLEGAL_SOFTWARE_STATE), + 0, + &gEfiCallerIdGuid, + (EFI_STATUS_CODE_DATA *) Buffer + ); + + EFI_DEADLOOP (); +} + + +VOID +PeiDebugPrint ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINTN ErrorLevel, + IN CHAR8 *Format, + ... + ) +/*++ + +Routine Description: + + Worker function for DEBUG(). If Error Logging hub is loaded log ASSERT + information. If Error Logging hub is not loaded do nothing. + +Arguments: + + PeiServices - The PEI core services table. + + ErrorLevel - If error level is set do the debug print. + + Format - String to use for the print, followed by Print arguments. + + ... - Print arguments + +Returns: + + None + +--*/ +{ + VA_LIST Marker; + UINT64 Buffer[EFI_STATUS_CODE_DATA_MAX_SIZE]; + + VA_START (Marker, Format); + EfiDebugVPrintWorker (ErrorLevel, Format, Marker, sizeof (Buffer), Buffer); + + // + // We choose NOT to use PEI_REPORT_STATUS_CODE here, because when debug is enable, + // we want get enough information if assert. + // + (**PeiServices).PeiReportStatusCode ( + PeiServices, + EFI_DEBUG_CODE, + (EFI_SOFTWARE_PEI_MODULE | EFI_DC_UNSPECIFIED), + 0, + &gEfiCallerIdGuid, + (EFI_STATUS_CODE_DATA *) Buffer + ); + + return ; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/Decompress.c b/Tools/Source/TianoTools/Common/PeiLib/Decompress.c new file mode 100644 index 0000000000..43446a37dd --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Decompress.c @@ -0,0 +1,1104 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + Decompress.c + +Abstract: + + Decompressor. Algorithm Ported from OPSD code (Decomp.asm) + +--*/ + +#include "TianoCommon.h" +#include EFI_PROTOCOL_DEFINITION (Decompress) +#include EFI_PROTOCOL_DEFINITION (TianoDecompress) + +EFI_STATUS +EFIAPI +EfiGetInfo ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); + +EFI_STATUS +EFIAPI +EfiDecompress ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +EFI_STATUS +EFIAPI +TianoGetInfo ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); + +EFI_STATUS +EFIAPI +TianoDecompress ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +// +// The protocol instance +// + +EFI_DECOMPRESS_PROTOCOL mEfiDecompress = { + EfiGetInfo, + EfiDecompress +}; + +EFI_TIANO_DECOMPRESS_PROTOCOL mTianoDecompress = { + TianoGetInfo, + TianoDecompress +}; + +EFI_STATUS +InstallEfiDecompress ( + IN OUT EFI_DECOMPRESS_PROTOCOL **This + ) +/*++ + +Routine Description: + + Install EFI decompress protocol. + +Arguments: + + This - Pointer to get decompress protocol as output + +Returns: + + EFI_SUCCESS - EFI decompress protocol successfully installed. + +--*/ +{ + *This = &mEfiDecompress; + return EFI_SUCCESS; +} + +EFI_STATUS +InstallTianoDecompress ( + EFI_TIANO_DECOMPRESS_PROTOCOL **This + ) +/*++ + +Routine Description: + + Install Tiano decompress protocol. + +Arguments: + + This - Pointer to get decompress protocol as output + +Returns: + + EFI_SUCCESS - Tiano decompress protocol successfully installed. + +--*/ +{ + *This = &mTianoDecompress; + return EFI_SUCCESS; +} +// +// Decompression algorithm begins here +// +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define UINT8_MAX 0xff +#define BAD_TABLE - 1 + +// +// C: Char&Len Set; P: Position Set; T: exTra Set +// +#define NC (0xff + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define MAXPBIT 5 +#define TBIT 5 +#define MAXNP ((1U << MAXPBIT) - 1) +#define NT (CODE_BIT + 3) +#if NT > MAXNP +#define NPT NT +#else +#define NPT MAXNP +#endif + +typedef struct { + UINT8 *mSrcBase; // Starting address of compressed data + UINT8 *mDstBase; // Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; + + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; + + UINT16 mBadTableFlag; + + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; + + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm, mPBit = 4 + // For Tiano de/compression algorithm, mPBit = 5 + // + UINT8 mPBit; +} SCRATCH_DATA; + +STATIC +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + +Arguments: + + Sd - The global scratch data + NumOfBits - The number of bits to shift and read. + +Returns: (VOID) + +--*/ +{ + Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); + + while (NumOfBits > Sd->mBitCount) { + + Sd->mBitBuf |= (UINT32) (Sd->mSubBitBuf << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); + + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; + Sd->mBitCount = 8; + + } else { + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + + } + } + + Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; +} + +STATIC +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + +Arguments: + + Sd - The global scratch data. + NumOfBits - The number of bits to pop and read. + +Returns: + + The bits that are popped out. + +--*/ +{ + UINT32 OutBits; + + OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + + FillBuf (Sd, NumOfBits); + + return OutBits; +} + +STATIC +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ) +/*++ + +Routine Description: + + Creates Huffman Code mapping table according to code length array. + +Arguments: + + Sd - The global scratch data + NumOfChar - Number of symbols in the symbol set + BitLen - Code length array + TableBits - The width of the mapping table + Table - The table + +Returns: + + 0 - OK. + BAD_TABLE - The table is corrupted. + +--*/ +{ + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *Pointer; + UINT16 Index3; + UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; + + for (Index = 1; Index <= 16; Index++) { + Count[Index] = 0; + } + + for (Index = 0; Index < NumOfChar; Index++) { + Count[BitLen[Index]]++; + } + + Start[1] = 0; + + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index))); + } + + if (Start[17] != 0) { + /*(1U << 16)*/ + return (UINT16) BAD_TABLE; + } + + JuBits = (UINT16) (16 - TableBits); + + for (Index = 1; Index <= TableBits; Index++) { + Start[Index] >>= JuBits; + Weight[Index] = (UINT16) (1U << (TableBits - Index)); + } + + while (Index <= 16) { + Weight[Index++] = (UINT16) (1U << (16 - Index)); + } + + Index = (UINT16) (Start[TableBits + 1] >> JuBits); + + if (Index != 0) { + Index3 = (UINT16) (1U << TableBits); + while (Index != Index3) { + Table[Index++] = 0; + } + } + + Avail = NumOfChar; + Mask = (UINT16) (1U << (15 - TableBits)); + + for (Char = 0; Char < NumOfChar; Char++) { + + Len = BitLen[Char]; + if (Len == 0) { + continue; + } + + NextCode = (UINT16) (Start[Len] + Weight[Len]); + + if (Len <= TableBits) { + + for (Index = Start[Len]; Index < NextCode; Index++) { + Table[Index] = Char; + } + + } else { + + Index3 = Start[Len]; + Pointer = &Table[Index3 >> JuBits]; + Index = (UINT16) (Len - TableBits); + + while (Index != 0) { + if (*Pointer == 0) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *Pointer = Avail++; + } + + if (Index3 & Mask) { + Pointer = &Sd->mRight[*Pointer]; + } else { + Pointer = &Sd->mLeft[*Pointer]; + } + + Index3 <<= 1; + Index--; + } + + *Pointer = Char; + + } + + Start[Len] = NextCode; + } + // + // Succeeds + // + return 0; +} + +STATIC +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decodes a position value. + +Arguments: + + Sd - the global scratch data + +Returns: + + The position value decoded. + +--*/ +{ + UINT16 Val; + UINT32 Mask; + UINT32 Pos; + + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Sd->mBitBuf & Mask) { + Val = Sd->mRight[Val]; + } else { + Val = Sd->mLeft[Val]; + } + + Mask >>= 1; + } while (Val >= MAXNP); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[Val]); + + Pos = Val; + if (Val > 1) { + Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); + } + + return Pos; +} + +STATIC +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ) +/*++ + +Routine Description: + + Reads code lengths for the Extra Set or the Position Set + +Arguments: + + Sd - The global scratch data + nn - Number of symbols + nbit - Number of bits needed to represent nn + Special - The special symbol that needs to be taken care of + +Returns: + + 0 - OK. + BAD_TABLE - Table is corrupted. + +--*/ +{ + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, nbit); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, nbit); + + for (Index = 0; Index < 256; Index++) { + Sd->mPTTable[Index] = CharC; + } + + for (Index = 0; Index < nn; Index++) { + Sd->mPTLen[Index] = 0; + } + + return 0; + } + + Index = 0; + + while (Index < Number) { + + CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); + + if (CharC == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + CharC += 1; + } + } + + FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); + + Sd->mPTLen[Index++] = (UINT8) CharC; + + if (Index == Special) { + CharC = (UINT16) GetBits (Sd, 2); + while ((INT16) (--CharC) >= 0) { + Sd->mPTLen[Index++] = 0; + } + } + } + + while (Index < nn) { + Sd->mPTLen[Index++] = 0; + } + + return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); +} + +STATIC +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Reads code lengths for Char&Len Set. + +Arguments: + + Sd - the global scratch data + +Returns: (VOID) + +--*/ +{ + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, CBIT); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, CBIT); + + for (Index = 0; Index < NC; Index++) { + Sd->mCLen[Index] = 0; + } + + for (Index = 0; Index < 4096; Index++) { + Sd->mCTable[Index] = CharC; + } + + return ; + } + + Index = 0; + while (Index < Number) { + + CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (CharC >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Mask & Sd->mBitBuf) { + CharC = Sd->mRight[CharC]; + } else { + CharC = Sd->mLeft[CharC]; + } + + Mask >>= 1; + + } while (CharC >= NT); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[CharC]); + + if (CharC <= 2) { + + if (CharC == 0) { + CharC = 1; + } else if (CharC == 1) { + CharC = (UINT16) (GetBits (Sd, 4) + 3); + } else if (CharC == 2) { + CharC = (UINT16) (GetBits (Sd, CBIT) + 20); + } + + while ((INT16) (--CharC) >= 0) { + Sd->mCLen[Index++] = 0; + } + + } else { + + Sd->mCLen[Index++] = (UINT8) (CharC - 2); + + } + } + + while (Index < NC) { + Sd->mCLen[Index++] = 0; + } + + MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); + + return ; +} + +STATIC +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode a character/length value. + +Arguments: + + Sd - The global scratch data. + +Returns: + + The value decoded. + +--*/ +{ + UINT16 Index2; + UINT32 Mask; + + if (Sd->mBlockSize == 0) { + // + // Starting a new block + // + Sd->mBlockSize = (UINT16) GetBits (Sd, 16); + Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } + + ReadCLen (Sd); + + Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } + + Sd->mBlockSize--; + Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + + if (Index2 >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); + + do { + if (Sd->mBitBuf & Mask) { + Index2 = Sd->mRight[Index2]; + } else { + Index2 = Sd->mLeft[Index2]; + } + + Mask >>= 1; + } while (Index2 >= NC); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mCLen[Index2]); + + return Index2; +} + +STATIC +VOID +Decode ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode the source data and put the resulting data into the destination buffer. + +Arguments: + + Sd - The global scratch data + +Returns: (VOID) + + --*/ +{ + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 CharC; + + BytesRemain = (UINT16) (-1); + + DataIdx = 0; + + for (;;) { + CharC = DecodeC (Sd); + if (Sd->mBadTableFlag != 0) { + return ; + } + + if (CharC < 256) { + // + // Process an Original character + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } else { + Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; + } + + } else { + // + // Process a Pointer + // + CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD)); + + BytesRemain = CharC; + + DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; + + BytesRemain--; + while ((INT16) (BytesRemain) >= 0) { + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } + + BytesRemain--; + } + } + } + + return ; +} + +EFI_STATUS +GetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + UINT8 *Src; + + *ScratchSize = sizeof (SCRATCH_DATA); + + Src = Source; + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + return EFI_SUCCESS; +} + +EFI_STATUS +Decompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize, + IN UINT8 Version + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + Version - The version of de/compression algorithm. + Version 1 for EFI 1.1 de/compression algorithm. + Version 2 for Tiano de/compression algorithm. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + EFI_STATUS Status; + SCRATCH_DATA *Sd; + UINT8 *Src; + UINT8 *Dst; + + Status = EFI_SUCCESS; + Src = Source; + Dst = Destination; + + if (ScratchSize < sizeof (SCRATCH_DATA)) { + return EFI_INVALID_PARAMETER; + } + + Sd = (SCRATCH_DATA *) Scratch; + + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + // + // If compressed file size is 0, return + // + if (OrigSize == 0) { + return Status; + } + + if (SrcSize < CompSize + 8) { + return EFI_INVALID_PARAMETER; + } + + if (DstSize != OrigSize) { + return EFI_INVALID_PARAMETER; + } + + Src = Src + 8; + + for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { + ((UINT8 *) Sd)[Index] = 0; + } + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 + // For Tiano de/compression algorithm(Version 2), mPBit = 5 + // + switch (Version) { + case 1: + Sd->mPBit = 4; + break; + + case 2: + Sd->mPBit = 5; + break; + + default: + // + // Currently, only have 2 versions + // + return EFI_INVALID_PARAMETER; + } + + Sd->mSrcBase = Src; + Sd->mDstBase = Dst; + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; + + // + // Fill the first BITBUFSIZ bits + // + FillBuf (Sd, BITBUFSIZ); + + // + // Decompress it + // + Decode (Sd); + + if (Sd->mBadTableFlag != 0) { + // + // Something wrong with the source + // + Status = EFI_INVALID_PARAMETER; + } + + return Status; +} + +EFI_STATUS +EFIAPI +EfiGetInfo ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return GetInfo ( + Source, + SrcSize, + DstSize, + ScratchSize + ); +} + +EFI_STATUS +EFIAPI +EfiDecompress ( + IN EFI_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + // + // For EFI 1.1 de/compression algorithm, the version is 1. + // + return Decompress ( + Source, + SrcSize, + Destination, + DstSize, + Scratch, + ScratchSize, + 1 + ); +} + +EFI_STATUS +EFIAPI +TianoGetInfo ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return GetInfo ( + Source, + SrcSize, + DstSize, + ScratchSize + ); +} + +EFI_STATUS +EFIAPI +TianoDecompress ( + IN EFI_TIANO_DECOMPRESS_PROTOCOL *This, + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + // + // For Tiano de/compression algorithm, the version is 2. + // + return Decompress ( + Source, + SrcSize, + Destination, + DstSize, + Scratch, + ScratchSize, + 2 + ); +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/Hob/Hob.c b/Tools/Source/TianoTools/Common/PeiLib/Hob/Hob.c new file mode 100644 index 0000000000..0f1ff5ffb8 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Hob/Hob.c @@ -0,0 +1,495 @@ + +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + hob.c + +Abstract: + + PEI Library Functions + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "peilib.h" +#include EFI_GUID_DEFINITION (MemoryAllocationHob) + + +EFI_STATUS +PeiBuildHobModule ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS MemoryAllocationModule, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +/*++ + +Routine Description: + + Builds a HOB for a loaded PE32 module + +Arguments: + + PeiServices - The PEI core services table. + ModuleName - The GUID File Name of the module + MemoryAllocationModule - The 64 bit physical address of the module + ModuleLength - The length of the module in bytes + EntryPoint - The 64 bit physical address of the entry point + to the module + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_ALLOCATION_MODULE *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + sizeof (EFI_HOB_MEMORY_ALLOCATION_MODULE), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->MemoryAllocationHeader.Name = gEfiHobMemeryAllocModuleGuid; + Hob->MemoryAllocationHeader.MemoryBaseAddress = MemoryAllocationModule; + Hob->MemoryAllocationHeader.MemoryLength = ModuleLength; + Hob->MemoryAllocationHeader.MemoryType = EfiBootServicesCode; + + Hob->ModuleName = *ModuleName; + Hob->EntryPoint = EntryPoint; + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiBuildHobResourceDescriptor ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +/*++ + +Routine Description: + + Builds a HOB that describes a chunck of system memory + +Arguments: + + PeiServices - The PEI core services table. + + ResourceType - The type of resource described by this HOB + + ResourceAttribute - The resource attributes of the memory described by this HOB + + PhysicalStart - The 64 bit physical address of memory described by this HOB + + NumberOfBytes - The length of the memoty described by this HOB in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_RESOURCE_DESCRIPTOR *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR, + sizeof (EFI_HOB_RESOURCE_DESCRIPTOR), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->ResourceType = ResourceType; + Hob->ResourceAttribute = ResourceAttribute; + Hob->PhysicalStart = PhysicalStart; + Hob->ResourceLength = NumberOfBytes; + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiBuildHobGuid ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN DataLength, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Builds a custom HOB that is tagged with a GUID for identification + +Arguments: + + PeiServices - The PEI core services table. + + Guid - The GUID of the custome HOB type + + DataLength - The size of the data payload for the GUIDed HOB + + Hob - Pointer to the Hob + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_GUID_EXTENSION, + (UINT16) (sizeof (EFI_HOB_GUID_TYPE) + DataLength), + Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + ((EFI_HOB_GUID_TYPE *)(*Hob))->Name = *Guid; + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiBuildHobGuidData ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +/*++ + +Routine Description: + + Builds a custom HOB that is tagged with a GUID for identification + +Arguments: + + PeiServices - The PEI core services table. + + Guid - The GUID of the custome HOB type + + Data - The data to be copied into the GUIDed HOB data field. + + DataLength - The data field length. + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + + EFI_HOB_GUID_TYPE *Hob; + + Status = PeiBuildHobGuid ( + PeiServices, + Guid, + DataLength, + &Hob + ); + + if (EFI_ERROR (Status)) { + return Status; + } + + Hob++; + (*PeiServices)->CopyMem (Hob, Data, DataLength); + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiBuildHobFv ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a Firmware Volume HOB + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The base address of the Firmware Volume + + Length - The size of the Firmware Volume in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_FIRMWARE_VOLUME *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_FV, + sizeof (EFI_HOB_FIRMWARE_VOLUME), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->BaseAddress = BaseAddress; + Hob->Length = Length; + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiBuildHobCpu ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +/*++ + +Routine Description: + + Builds a HOB for the CPU + +Arguments: + + PeiServices - The PEI core services table. + + SizeOfMemorySpace - Identifies the maximum + physical memory addressibility of the processor. + + SizeOfIoSpace - Identifies the maximum physical I/O addressibility + of the processor. + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_CPU *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_CPU, + sizeof (EFI_HOB_CPU), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->SizeOfMemorySpace = SizeOfMemorySpace; + Hob->SizeOfIoSpace = SizeOfIoSpace; + + return EFI_SUCCESS; +} + + + +EFI_STATUS +PeiBuildHobStack ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a HOB for the Stack + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The 64 bit physical address of the Stack + + Length - The length of the stack in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_ALLOCATION_STACK *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_MEMORY_ALLOCATION, + sizeof (EFI_HOB_MEMORY_ALLOCATION_STACK), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->AllocDescriptor.Name = gEfiHobMemeryAllocStackGuid; + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = EfiConventionalMemory; + + return EFI_SUCCESS; +} + + + +EFI_STATUS +PeiBuildHobBspStore ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for the bsp store + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The 64 bit physical address of the bsp + + Length - The length of the bsp store in bytes + + MemoryType - Memory type + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_ALLOCATION_BSP_STORE *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_MEMORY_ALLOCATION, + sizeof (EFI_HOB_MEMORY_ALLOCATION_BSP_STORE), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Hob->AllocDescriptor.Name = gEfiHobMemeryAllocBspStoreGuid; + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + + return EFI_SUCCESS; +} + + +EFI_STATUS +PeiBuildHobMemoryAllocation ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_GUID *Name, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for the memory allocation. + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The 64 bit physical address of the memory + + Length - The length of the memory allocation in bytes + + Name - Name for Hob + + MemoryType - Memory type + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_MEMORY_ALLOCATION *Hob; + + Status = (*PeiServices)->CreateHob ( + PeiServices, + EFI_HOB_TYPE_MEMORY_ALLOCATION, + sizeof (EFI_HOB_MEMORY_ALLOCATION), + &Hob + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Name != NULL) { + Hob->AllocDescriptor.Name = *Name; + } else { + (*PeiServices)->SetMem(&(Hob->AllocDescriptor.Name), sizeof (EFI_GUID), 0); + } + + Hob->AllocDescriptor.MemoryBaseAddress = BaseAddress; + Hob->AllocDescriptor.MemoryLength = Length; + Hob->AllocDescriptor.MemoryType = MemoryType; + + return EFI_SUCCESS; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/Ipf/PeCoffLoaderEx.c b/Tools/Source/TianoTools/Common/PeiLib/Ipf/PeCoffLoaderEx.c new file mode 100644 index 0000000000..09792818cc --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Ipf/PeCoffLoaderEx.c @@ -0,0 +1,244 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + PeCoffLoaderEx.c + +Abstract: + + Fixes Intel Itanium(TM) specific relocation types + + +Revision History + +--*/ + +#include "TianoCommon.h" +#include "EfiImage.h" + +#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \ + Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos) + +#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \ + *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \ + ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos) + +#define IMM64_IMM7B_INST_WORD_X 3 +#define IMM64_IMM7B_SIZE_X 7 +#define IMM64_IMM7B_INST_WORD_POS_X 4 +#define IMM64_IMM7B_VAL_POS_X 0 + +#define IMM64_IMM9D_INST_WORD_X 3 +#define IMM64_IMM9D_SIZE_X 9 +#define IMM64_IMM9D_INST_WORD_POS_X 18 +#define IMM64_IMM9D_VAL_POS_X 7 + +#define IMM64_IMM5C_INST_WORD_X 3 +#define IMM64_IMM5C_SIZE_X 5 +#define IMM64_IMM5C_INST_WORD_POS_X 13 +#define IMM64_IMM5C_VAL_POS_X 16 + +#define IMM64_IC_INST_WORD_X 3 +#define IMM64_IC_SIZE_X 1 +#define IMM64_IC_INST_WORD_POS_X 12 +#define IMM64_IC_VAL_POS_X 21 + +#define IMM64_IMM41a_INST_WORD_X 1 +#define IMM64_IMM41a_SIZE_X 10 +#define IMM64_IMM41a_INST_WORD_POS_X 14 +#define IMM64_IMM41a_VAL_POS_X 22 + +#define IMM64_IMM41b_INST_WORD_X 1 +#define IMM64_IMM41b_SIZE_X 8 +#define IMM64_IMM41b_INST_WORD_POS_X 24 +#define IMM64_IMM41b_VAL_POS_X 32 + +#define IMM64_IMM41c_INST_WORD_X 2 +#define IMM64_IMM41c_SIZE_X 23 +#define IMM64_IMM41c_INST_WORD_POS_X 0 +#define IMM64_IMM41c_VAL_POS_X 40 + +#define IMM64_SIGN_INST_WORD_X 3 +#define IMM64_SIGN_SIZE_X 1 +#define IMM64_SIGN_INST_WORD_POS_X 27 +#define IMM64_SIGN_VAL_POS_X 63 + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an Itanium-based specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + Status code + +--*/ +{ + UINT64 *F64; + UINT64 FixupVal; + + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_DIR64: + F64 = (UINT64 *) Fixup; + *F64 = *F64 + (UINT64) Adjust; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + case EFI_IMAGE_REL_BASED_IA64_IMM64: + + // + // Align it to bundle address before fixing up the + // 64-bit immediate value of the movl instruction. + // + + Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15)); + FixupVal = (UINT64)0; + + // + // Extract the lower 32 bits of IMM64 from bundle + // + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X, + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X, + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X, + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IC_INST_WORD_X, + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X, + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + // + // Update 64-bit address + // + FixupVal += Adjust; + + // + // Insert IMM64 into bundle + // + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X), + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X), + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X), + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X), + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X), + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X), + IMM64_IMM41b_SIZE_X, + IMM64_IMM41b_INST_WORD_POS_X, + IMM64_IMM41b_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X), + IMM64_IMM41c_SIZE_X, + IMM64_IMM41c_INST_WORD_POS_X, + IMM64_IMM41c_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X), + IMM64_SIGN_SIZE_X, + IMM64_SIGN_INST_WORD_POS_X, + IMM64_SIGN_VAL_POS_X + ); + + F64 = (UINT64 *) Fixup; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + default: + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/Ipf/PeCoffLoaderEx.h b/Tools/Source/TianoTools/Common/PeiLib/Ipf/PeCoffLoaderEx.h new file mode 100644 index 0000000000..b79ead654a --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Ipf/PeCoffLoaderEx.h @@ -0,0 +1,67 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + PeCoffLoaderEx.h + +Abstract: + + Fixes Intel Itanium(TM) specific relocation types + + +Revision History + +--*/ + +#ifndef _PE_COFF_LOADER_EX_H_ +#define _PE_COFF_LOADER_EX_H_ + +// +// Define macro to determine if the machine type is supported. +// Returns 0 if the machine is not supported, Not 0 otherwise. +// +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + ((Machine) == EFI_IMAGE_MACHINE_IA64 || \ + (Machine) == EFI_IMAGE_MACHINE_EBC) + + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an Itanium-based specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + Status code + +--*/ +; + +#endif diff --git a/Tools/Source/TianoTools/Common/PeiLib/Ipf/PerformancePrimitives.s b/Tools/Source/TianoTools/Common/PeiLib/Ipf/PerformancePrimitives.s new file mode 100644 index 0000000000..5814bb71b7 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Ipf/PerformancePrimitives.s @@ -0,0 +1,61 @@ +//++ +// Copyright (c) 2004, 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. +// +// Module Name: +// +// PerformancePrimitives.s +// +// Abstract: +// +// +// Revision History: +// +//-- + +.file "PerformancePrimitives.s" + +#include "IpfMacro.i" + +//----------------------------------------------------------------------------- +//++ +// GetTimerValue +// +// Implementation of CPU-based time service +// +// On Entry : +// EFI_STATUS +// GetTimerValue ( +// OUT UINT64 *TimerValue +// ) +// +// Return Value: +// r8 = Status +// r9 = 0 +// r10 = 0 +// r11 = 0 +// +// As per static calling conventions. +// +//-- +//--------------------------------------------------------------------------- +PROCEDURE_ENTRY (GetTimerValue) + + NESTED_SETUP (1,8,0,0) + mov r8 = ar.itc;; + st8 [r32]= r8 + mov r8 = r0 + mov r9 = r0 + mov r10 = r0 + mov r11 = r0 + NESTED_RETURN + +PROCEDURE_EXIT (GetTimerValue) +//--------------------------------------------------------------------------- + diff --git a/Tools/Source/TianoTools/Common/PeiLib/Ipf/SwitchStack.s b/Tools/Source/TianoTools/Common/PeiLib/Ipf/SwitchStack.s new file mode 100644 index 0000000000..08ff773b27 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Ipf/SwitchStack.s @@ -0,0 +1,122 @@ +//++ +// Copyright (c) 2004, 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. +// +// Module Name: +// +// SwitchStack.s +// +// Abstract: +// +// Contains an implementation of a stack switch for the Itanium-based architecture. +// +// +// +// Revision History: +// +//-- + + .file "SwitchStack.s" + +#include +#include + +// Define hardware RSE Configuration Register +// +// RS Configuration (RSC) bit field positions + +#define RSC_MODE 0 +#define RSC_PL 2 +#define RSC_BE 4 +// RSC bits 5-15 reserved +#define RSC_MBZ0 5 +#define RSC_MBZ0_V 0x3ff +#define RSC_LOADRS 16 +#define RSC_LOADRS_LEN 14 +// RSC bits 30-63 reserved +#define RSC_MBZ1 30 +#define RSC_MBZ1_V 0x3ffffffffULL + +// RSC modes +// Lazy +#define RSC_MODE_LY (0x0) +// Store intensive +#define RSC_MODE_SI (0x1) +// Load intensive +#define RSC_MODE_LI (0x2) +// Eager +#define RSC_MODE_EA (0x3) + +// RSC Endian bit values +#define RSC_BE_LITTLE 0 +#define RSC_BE_BIG 1 + +// RSC while in kernel: enabled, little endian, pl = 0, eager mode +#define RSC_KERNEL ((RSC_MODE_EA<> Count; +} + +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be multiplied with a 32 bit + value returns 64bit result. + No checking if the result is greater than 64bits + +Arguments: + + Multiplicand - multiplicand + Multiplier - multiplier + +Returns: + + Multiplicand * Multiplier + +--*/ +{ + return Multiplicand * Multiplier; +} + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be divided with a 32 bit value returns + 64bit result and the Remainder. + N.B. only works for 31bit divisors!! + +Arguments: + + Dividend - dividend + Divisor - divisor + Remainder - buffer for remainder + +Returns: + + Dividend / Divisor + Remainder = Dividend mod Divisor + +--*/ +{ + if (Remainder) { + *Remainder = Dividend % Divisor; + } + + return Dividend / Divisor; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/Ipf/pioflush.s b/Tools/Source/TianoTools/Common/PeiLib/Ipf/pioflush.s new file mode 100644 index 0000000000..e48a5e427d --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Ipf/pioflush.s @@ -0,0 +1,106 @@ +//++ +// Copyright (c) 2004, 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. +// +// Module Name: +// +// pioflush.s +// +// Abstract: +// +// +// Revision History: +// +//-- + + .file "pioflush.c" + .radix D + .section .text, "ax", "progbits" + .align 32 + .section .pdata, "a", "progbits" + .align 4 + .section .xdata, "a", "progbits" + .align 8 + .section .data, "wa", "progbits" + .align 16 + .section .rdata, "a", "progbits" + .align 16 + .section .bss, "wa", "nobits" + .align 16 + .section .tls$, "was", "progbits" + .align 16 + .section .sdata, "was", "progbits" + .align 16 + .section .sbss, "was", "nobits" + .align 16 + .section .srdata, "as", "progbits" + .align 16 + .section .rdata, "a", "progbits" + .align 16 + .section .rtcode, "ax", "progbits" + .align 32 + .type RtPioICacheFlush# ,@function + .global RtPioICacheFlush# +// Function compile flags: /Ogsy + .section .rtcode + +// Begin code for function: RtPioICacheFlush: + .proc RtPioICacheFlush# + .align 32 +RtPioICacheFlush: +// File e:\tmp\pioflush.c + { .mii //R-Addr: 0X00 + alloc r3=2, 0, 0, 0 //11, 00000002H + cmp4.leu p0,p6=32, r33;; //15, 00000020H + (p6) mov r33=32;; //16, 00000020H + } + { .mii //R-Addr: 0X010 + nop.m 0 + zxt4 r29=r33;; //21 + dep.z r30=r29, 0, 5;; //21, 00000005H + } + { .mii //R-Addr: 0X020 + cmp4.eq p0,p7=r0, r30 //21 + shr.u r28=r29, 5;; //19, 00000005H + (p7) adds r28=1, r28;; //22, 00000001H + } + { .mii //R-Addr: 0X030 + nop.m 0 + shl r27=r28, 5;; //25, 00000005H + zxt4 r26=r27;; //25 + } + { .mfb //R-Addr: 0X040 + add r31=r26, r32 //25 + nop.f 0 + nop.b 0 + } +$L143: + { .mii //R-Addr: 0X050 + fc r32 //27 + adds r32=32, r32;; //28, 00000020H + cmp.ltu p14,p15=r32, r31 //29 + } + { .mfb //R-Addr: 0X060 + nop.m 0 + nop.f 0 + (p14) br.cond.dptk.few $L143#;; //29, 880000/120000 + } + { .mmi + sync.i;; + srlz.i + nop.i 0;; + } + { .mfb //R-Addr: 0X070 + nop.m 0 + nop.f 0 + br.ret.sptk.few b0;; //31 + } +// End code for function: + .endp RtPioICacheFlush# +// END diff --git a/Tools/Source/TianoTools/Common/PeiLib/Ipf/processor.c b/Tools/Source/TianoTools/Common/PeiLib/Ipf/processor.c new file mode 100644 index 0000000000..e6d5c40435 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Ipf/processor.c @@ -0,0 +1,118 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + Processor.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "EfiJump.h" +#include "PeiHob.h" +#include EFI_GUID_DEFINITION (PeiFlushInstructionCache) +#include EFI_GUID_DEFINITION (PeiTransferControl) + +EFI_STATUS +WinNtFlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + +EFI_PEI_TRANSFER_CONTROL_PROTOCOL mTransferControl = { + SetJump, + LongJump, + sizeof (EFI_JUMP_BUFFER) +}; + +EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL mFlushInstructionCache = { + WinNtFlushInstructionCacheFlush +}; + +EFI_STATUS +InstallEfiPeiTransferControl ( + IN OUT EFI_PEI_TRANSFER_CONTROL_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the transfer control mechanism + +Arguments: + + This - Pointer to transfer control mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed. + +--*/ +{ + *This = &mTransferControl; + return EFI_SUCCESS; +} + +EFI_STATUS +InstallEfiPeiFlushInstructionCache ( + IN OUT EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the flush instruction cache mechanism + +Arguments: + + This - Pointer to flush instruction cache mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed + +--*/ +{ + *This = &mFlushInstructionCache; + return EFI_SUCCESS; +} + +EFI_STATUS +WinNtFlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + This routine would provide support for flushing the CPU instruction cache. + +Arguments: + + This - Pointer to CPU Architectural Protocol interface + Start - Start adddress in memory to flush + Length - Length of memory to flush + +Returns: + + Status + EFI_SUCCESS + +--*/ +{ + RtPioICacheFlush ((UINT8 *) Start, (UINTN) Length); + return EFI_SUCCESS; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/Ipf/setjmp.s b/Tools/Source/TianoTools/Common/PeiLib/Ipf/setjmp.s new file mode 100644 index 0000000000..4606437117 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Ipf/setjmp.s @@ -0,0 +1,325 @@ +//++ +// Copyright (c) 2004, 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. +// +// Module Name: +// +// setjmp.s +// +// Abstract: +// +// Contains an implementation of setjmp and longjmp for the +// Itanium-based architecture. +// +// +// +// Revision History: +// +//-- + + .file "setjmp.s" + +#include +#include + +// int SetJump(struct jmp_buffer save) +// +// Setup a non-local goto. +// +// Description: +// +// SetJump stores the current register set in the area pointed to +// by "save". It returns zero. Subsequent calls to "LongJump" will +// restore the registers and return non-zero to the same location. +// +// On entry, r32 contains the pointer to the jmp_buffer +// + +PROCEDURE_ENTRY(SetJump) + // + // Make sure buffer is aligned at 16byte boundary + // + mov r32 = r33 + + add r10 = -0x10,r0 ;; // mask the lower 4 bits + and r32 = r32, r10;; + add r32 = 0x10, r32;; // move to next 16 byte boundary + + add r10 = J_PREDS, r32 // skip Unats & pfs save area + add r11 = J_BSP, r32 + // + // save immediate context + // + mov r2 = ar.bsp // save backing store pointer + mov r3 = pr // save predicates + ;; + // + // save user Unat register + // + mov r16 = ar.lc // save loop count register + mov r14 = ar.unat // save user Unat register + + st8 [r10] = r3, J_LC-J_PREDS + st8 [r11] = r2, J_R4-J_BSP + ;; + st8 [r10] = r16, J_R5-J_LC + st8 [r32] = r14, J_NATS // Note: Unat at the + // beginning of the save area + mov r15 = ar.pfs + ;; + // + // save preserved general registers & NaT's + // + st8.spill [r11] = r4, J_R6-J_R4 + ;; + st8.spill [r10] = r5, J_R7-J_R5 + ;; + st8.spill [r11] = r6, J_SP-J_R6 + ;; + st8.spill [r10] = r7, J_F3-J_R7 + ;; + st8.spill [r11] = sp, J_F2-J_SP + ;; + // + // save spilled Unat and pfs registers + // + mov r2 = ar.unat // save Unat register after spill + ;; + st8 [r32] = r2, J_PFS-J_NATS // save unat for spilled regs + ;; + st8 [r32] = r15 // save pfs + // + // save floating registers + // + stf.spill [r11] = f2, J_F4-J_F2 + stf.spill [r10] = f3, J_F5-J_F3 + ;; + stf.spill [r11] = f4, J_F16-J_F4 + stf.spill [r10] = f5, J_F17-J_F5 + ;; + stf.spill [r11] = f16, J_F18-J_F16 + stf.spill [r10] = f17, J_F19-J_F17 + ;; + stf.spill [r11] = f18, J_F20-J_F18 + stf.spill [r10] = f19, J_F21-J_F19 + ;; + stf.spill [r11] = f20, J_F22-J_F20 + stf.spill [r10] = f21, J_F23-J_F21 + ;; + stf.spill [r11] = f22, J_F24-J_F22 + stf.spill [r10] = f23, J_F25-J_F23 + ;; + stf.spill [r11] = f24, J_F26-J_F24 + stf.spill [r10] = f25, J_F27-J_F25 + ;; + stf.spill [r11] = f26, J_F28-J_F26 + stf.spill [r10] = f27, J_F29-J_F27 + ;; + stf.spill [r11] = f28, J_F30-J_F28 + stf.spill [r10] = f29, J_F31-J_F29 + ;; + stf.spill [r11] = f30, J_FPSR-J_F30 + stf.spill [r10] = f31, J_B0-J_F31 // size of f31 + fpsr + // + // save FPSR register & branch registers + // + mov r2 = ar.fpsr // save fpsr register + mov r3 = b0 + ;; + st8 [r11] = r2, J_B1-J_FPSR + st8 [r10] = r3, J_B2-J_B0 + mov r2 = b1 + mov r3 = b2 + ;; + st8 [r11] = r2, J_B3-J_B1 + st8 [r10] = r3, J_B4-J_B2 + mov r2 = b3 + mov r3 = b4 + ;; + st8 [r11] = r2, J_B5-J_B3 + st8 [r10] = r3 + mov r2 = b5 + ;; + st8 [r11] = r2 + ;; + // + // return + // + mov r8 = r0 // return 0 from setjmp + mov ar.unat = r14 // restore unat + br.ret.sptk b0 + +PROCEDURE_EXIT(SetJump) + + +// +// void LongJump(struct jmp_buffer *) +// +// Perform a non-local goto. +// +// Description: +// +// LongJump initializes the register set to the values saved by a +// previous 'SetJump' and jumps to the return location saved by that +// 'SetJump'. This has the effect of unwinding the stack and returning +// for a second time to the 'SetJump'. +// + +PROCEDURE_ENTRY(LongJump) + // + // Make sure buffer is aligned at 16byte boundary + // + mov r32 = r33 + + add r10 = -0x10,r0 ;; // mask the lower 4 bits + and r32 = r32, r10;; + add r32 = 0x10, r32;; // move to next 16 byte boundary + + // + // caching the return value as we do invala in the end + // +/// mov r8 = r33 // return value + mov r8 = 1 // For now return hard coded 1 + + // + // get immediate context + // + mov r14 = ar.rsc // get user RSC conf + add r10 = J_PFS, r32 // get address of pfs + add r11 = J_NATS, r32 + ;; + ld8 r15 = [r10], J_BSP-J_PFS // get pfs + ld8 r2 = [r11], J_LC-J_NATS // get unat for spilled regs + ;; + mov ar.unat = r2 + ;; + ld8 r16 = [r10], J_PREDS-J_BSP // get backing store pointer + mov ar.rsc = r0 // put RSE in enforced lazy + mov ar.pfs = r15 + ;; + + // + // while returning from longjmp the BSPSTORE and BSP needs to be + // same and discard all the registers allocated after we did + // setjmp. Also, we need to generate the RNAT register since we + // did not flushed the RSE on setjmp. + // + mov r17 = ar.bspstore // get current BSPSTORE + ;; + cmp.ltu p6,p7 = r17, r16 // is it less than BSP of +(p6) br.spnt.few .flush_rse + mov r19 = ar.rnat // get current RNAT + ;; + loadrs // invalidate dirty regs + br.sptk.many .restore_rnat // restore RNAT + +.flush_rse: + flushrs + ;; + mov r19 = ar.rnat // get current RNAT + mov r17 = r16 // current BSPSTORE + ;; +.restore_rnat: + // + // check if RNAT is saved between saved BSP and curr BSPSTORE + // + dep r18 = 1,r16,3,6 // get RNAT address + ;; + cmp.ltu p8,p9 = r18, r17 // RNAT saved on RSE + ;; +(p8) ld8 r19 = [r18] // get RNAT from RSE + ;; + mov ar.bspstore = r16 // set new BSPSTORE + ;; + mov ar.rnat = r19 // restore RNAT + mov ar.rsc = r14 // restore RSC conf + + + ld8 r3 = [r11], J_R4-J_LC // get lc register + ld8 r2 = [r10], J_R5-J_PREDS // get predicates + ;; + mov pr = r2, -1 + mov ar.lc = r3 + // + // restore preserved general registers & NaT's + // + ld8.fill r4 = [r11], J_R6-J_R4 + ;; + ld8.fill r5 = [r10], J_R7-J_R5 + ld8.fill r6 = [r11], J_SP-J_R6 + ;; + ld8.fill r7 = [r10], J_F2-J_R7 + ld8.fill sp = [r11], J_F3-J_SP + ;; + // + // restore floating registers + // + ldf.fill f2 = [r10], J_F4-J_F2 + ldf.fill f3 = [r11], J_F5-J_F3 + ;; + ldf.fill f4 = [r10], J_F16-J_F4 + ldf.fill f5 = [r11], J_F17-J_F5 + ;; + ldf.fill f16 = [r10], J_F18-J_F16 + ldf.fill f17 = [r11], J_F19-J_F17 + ;; + ldf.fill f18 = [r10], J_F20-J_F18 + ldf.fill f19 = [r11], J_F21-J_F19 + ;; + ldf.fill f20 = [r10], J_F22-J_F20 + ldf.fill f21 = [r11], J_F23-J_F21 + ;; + ldf.fill f22 = [r10], J_F24-J_F22 + ldf.fill f23 = [r11], J_F25-J_F23 + ;; + ldf.fill f24 = [r10], J_F26-J_F24 + ldf.fill f25 = [r11], J_F27-J_F25 + ;; + ldf.fill f26 = [r10], J_F28-J_F26 + ldf.fill f27 = [r11], J_F29-J_F27 + ;; + ldf.fill f28 = [r10], J_F30-J_F28 + ldf.fill f29 = [r11], J_F31-J_F29 + ;; + ldf.fill f30 = [r10], J_FPSR-J_F30 + ldf.fill f31 = [r11], J_B0-J_F31 ;; + + // + // restore branch registers and fpsr + // + ld8 r16 = [r10], J_B1-J_FPSR // get fpsr + ld8 r17 = [r11], J_B2-J_B0 // get return pointer + ;; + mov ar.fpsr = r16 + mov b0 = r17 + ld8 r2 = [r10], J_B3-J_B1 + ld8 r3 = [r11], J_B4-J_B2 + ;; + mov b1 = r2 + mov b2 = r3 + ld8 r2 = [r10], J_B5-J_B3 + ld8 r3 = [r11] + ;; + mov b3 = r2 + mov b4 = r3 + ld8 r2 = [r10] + ld8 r21 = [r32] // get user unat + ;; + mov b5 = r2 + mov ar.unat = r21 + + // + // invalidate ALAT + // + invala ;; + + br.ret.sptk b0 +PROCEDURE_EXIT(LongJump) + + diff --git a/Tools/Source/TianoTools/Common/PeiLib/PeCoffLoader.c b/Tools/Source/TianoTools/Common/PeiLib/PeCoffLoader.c new file mode 100644 index 0000000000..0e84319f69 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/PeCoffLoader.c @@ -0,0 +1,1249 @@ +/*++ + +Copyright (c) 2004 - 2005, 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. + +Module Name: + + PeCoffLoader.c + +Abstract: + + Tiano PE/COFF loader + +Revision History + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "PeiLib.h" +#include "PeCoffLoaderEx.h" + +#ifdef EFI_NT_EMULATOR +#include "peilib.h" +#include "EfiHobLib.h" +#include EFI_PPI_DEFINITION (NtLoadAsDll) +#endif + +STATIC +EFI_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_NT_HEADERS *PeHdr, + OUT EFI_TE_IMAGE_HEADER *TeHdr + ); + +STATIC +EFI_STATUS +PeCoffLoaderCheckImageType ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_NT_HEADERS *PeHdr, + IN EFI_TE_IMAGE_HEADER *TeHdr + ); + +STATIC +VOID * +PeCoffLoaderImageAddress ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ); + +EFI_STATUS +EFIAPI +PeCoffLoaderGetImageInfo ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +PeCoffLoaderRelocateImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +PeCoffLoaderLoadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_STATUS +EFIAPI +PeCoffLoaderUnloadImage ( + IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ); + +EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader = { + PeCoffLoaderGetImageInfo, + PeCoffLoaderLoadImage, + PeCoffLoaderRelocateImage, + PeCoffLoaderUnloadImage +}; + +#ifdef EFI_NT_EMULATOR +EFI_NT_LOAD_AS_DLL_PPI *mPeCoffLoaderWinNtLoadAsDll = NULL; +#endif + +EFI_STATUS +InstallEfiPeiPeCoffLoader ( + IN EFI_PEI_SERVICES **PeiServices, + IN OUT EFI_PEI_PE_COFF_LOADER_PROTOCOL **This, + IN EFI_PEI_PPI_DESCRIPTOR *ThisPpi + ) +/*++ + +Routine Description: + + Install PE/COFF loader PPI + +Arguments: + + PeiServices - General purpose services available to every PEIM + + This - Pointer to get Pei PE coff loader protocol as output + + ThisPpi - Passed in as EFI_NT_LOAD_AS_DLL_PPI on NT_EMULATOR platform + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + Status = EFI_SUCCESS; + +#ifdef EFI_NT_EMULATOR + // + // For use by PEI Core and Modules + // + if (NULL != PeiServices) { + Status = (**PeiServices).LocatePpi ( + PeiServices, + &gEfiNtLoadAsDllPpiGuid, + 0, + NULL, + &mPeCoffLoaderWinNtLoadAsDll + ); + } else { + // + // Now in SecMain or ERM usage, bind appropriately + // + PEI_ASSERT (PeiServices, (NULL != ThisPpi)); + + mPeCoffLoaderWinNtLoadAsDll = (EFI_NT_LOAD_AS_DLL_PPI *) ThisPpi; + PEI_ASSERT (PeiServices, (NULL != mPeCoffLoaderWinNtLoadAsDll)); + } +#endif + + if (NULL != This) { + *This = &mPeCoffLoader; + } + + return Status; +} + +STATIC +EFI_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_NT_HEADERS *PeHdr, + OUT EFI_TE_IMAGE_HEADER *TeHdr + ) +/*++ + +Routine Description: + + Retrieves the PE or TE Header from a PE/COFF or TE image + +Arguments: + + ImageContext - The context of the image being loaded + + PeHdr - The buffer in which to return the PE header + + TeHdr - The buffer in which to return the TE header + +Returns: + + EFI_SUCCESS if the PE or TE Header is read, + Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function. + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_DOS_HEADER DosHdr; + UINTN Size; + + ImageContext->IsTeImage = FALSE; + // + // Read the DOS image headers + // + Size = sizeof (EFI_IMAGE_DOS_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &Size, + &DosHdr + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + ImageContext->PeCoffHeaderOffset = 0; + if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew; + } + // + // Read the PE/COFF Header + // + Size = sizeof (EFI_IMAGE_NT_HEADERS); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + ImageContext->PeCoffHeaderOffset, + &Size, + PeHdr + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + // + // Check the PE/COFF Header Signature. If not, then try to read a TE header + // + if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) { + Size = sizeof (EFI_TE_IMAGE_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &Size, + TeHdr + ); + if (TeHdr->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) { + return EFI_UNSUPPORTED; + } + + ImageContext->IsTeImage = TRUE; + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +PeCoffLoaderCheckImageType ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_NT_HEADERS *PeHdr, + IN EFI_TE_IMAGE_HEADER *TeHdr + ) +/*++ + +Routine Description: + + Checks the PE or TE header of a PE/COFF or TE image to determine if it supported + +Arguments: + + ImageContext - The context of the image being loaded + + PeHdr - The buffer in which to return the PE header + + TeHdr - The buffer in which to return the TE header + +Returns: + + EFI_SUCCESS if the PE/COFF or TE image is supported + EFI_UNSUPPORTED of the PE/COFF or TE image is not supported. + +--*/ +{ + // + // See if the machine type is supported. We support a native machine type (IA-32/Itanium-based) + // and the machine type for the Virtual Machine. + // + if (ImageContext->IsTeImage == FALSE) { + ImageContext->Machine = PeHdr->FileHeader.Machine; + } else { + ImageContext->Machine = TeHdr->Machine; + } + + if (!(EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageContext->Machine))) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_MACHINE_TYPE; + return EFI_UNSUPPORTED; + } + + // + // See if the image type is supported. We support EFI Applications, + // EFI Boot Service Drivers, and EFI Runtime Drivers. + // + if (ImageContext->IsTeImage == FALSE) { + ImageContext->ImageType = PeHdr->OptionalHeader.Subsystem; + } else { + ImageContext->ImageType = (UINT16) (TeHdr->Subsystem); + } + + switch (ImageContext->ImageType) { + + case EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION: + ImageContext->ImageCodeMemoryType = EfiLoaderCode; + ImageContext->ImageDataMemoryType = EfiLoaderData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER: + ImageContext->ImageCodeMemoryType = EfiBootServicesCode; + ImageContext->ImageDataMemoryType = EfiBootServicesData; + break; + + case EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER: + case EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER: + ImageContext->ImageCodeMemoryType = EfiRuntimeServicesCode; + ImageContext->ImageDataMemoryType = EfiRuntimeServicesData; + break; + + default: + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SUBSYSTEM; + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PeCoffLoaderGetImageInfo ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Retrieves information on a PE/COFF image + +Arguments: + + This - Calling context + ImageContext - The context of the image being loaded + +Returns: + + EFI_SUCCESS - The information on the PE/COFF image was collected. + EFI_INVALID_PARAMETER - ImageContext is NULL. + EFI_UNSUPPORTED - The PE/COFF image is not supported. + Otherwise - The error status from reading the PE/COFF image using the + ImageContext->ImageRead() function + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_NT_HEADERS PeHdr; + EFI_TE_IMAGE_HEADER TeHdr; + EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry; + UINTN Size; + UINTN Index; + UINTN DebugDirectoryEntryRva; + UINTN DebugDirectoryEntryFileOffset; + UINTN SectionHeaderOffset; + EFI_IMAGE_SECTION_HEADER SectionHeader; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry; + + if (NULL == ImageContext) { + return EFI_INVALID_PARAMETER; + } + // + // Assume success + // + ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS; + + Status = PeCoffLoaderGetPeHeader (ImageContext, &PeHdr, &TeHdr); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Verify machine type + // + Status = PeCoffLoaderCheckImageType (ImageContext, &PeHdr, &TeHdr); + if (EFI_ERROR (Status)) { + return Status; + } + // + // Retrieve the base address of the image + // + if (!(ImageContext->IsTeImage)) { + ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase; + } else { + ImageContext->ImageAddress = (EFI_PHYSICAL_ADDRESS) (TeHdr.ImageBase); + } + // + // Initialize the alternate destination address to 0 indicating that it + // should not be used. + // + ImageContext->DestinationAddress = 0; + + // + // Initialize the codeview pointer. + // + ImageContext->CodeView = NULL; + ImageContext->PdbPointer = NULL; + + // + // Three cases with regards to relocations: + // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable + // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable + // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but + // has no base relocs to apply + // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid. + // + // Look at the file header to determine if relocations have been stripped, and + // save this info in the image context for later use. + // + if ((!(ImageContext->IsTeImage)) && ((PeHdr.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) { + ImageContext->RelocationsStripped = TRUE; + } else { + ImageContext->RelocationsStripped = FALSE; + } + + if (!(ImageContext->IsTeImage)) { + ImageContext->ImageSize = (UINT64) PeHdr.OptionalHeader.SizeOfImage; + ImageContext->SectionAlignment = PeHdr.OptionalHeader.SectionAlignment; + ImageContext->SizeOfHeaders = PeHdr.OptionalHeader.SizeOfHeaders; + + // + // Modify ImageSize to contain .PDB file name if required and initialize + // PdbRVA field... + // + if (PeHdr.OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + + // + // Determine the file offset of the debug directory... This means we walk + // the sections to find which section contains the RVA of the debug + // directory + // + DebugDirectoryEntryFileOffset = 0; + + SectionHeaderOffset = (UINTN)( + ImageContext->PeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + PeHdr.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < PeHdr.FileHeader.NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = + DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData; + break; + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset, + &Size, + &DebugEntry + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) { + ImageContext->ImageSize += DebugEntry.SizeOfData; + } + + return EFI_SUCCESS; + } + } + } + } + } else { + ImageContext->ImageSize = 0; + ImageContext->SectionAlignment = 4096; + ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) TeHdr.BaseOfCode - (UINTN) TeHdr.StrippedSize; + + DebugDirectoryEntry = &TeHdr.DataDirectory[1]; + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + SectionHeaderOffset = (UINTN) (sizeof (EFI_TE_IMAGE_HEADER)); + + DebugDirectoryEntryFileOffset = 0; + + for (Index = 0; Index < TeHdr.NumberOfSections;) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - + SectionHeader.VirtualAddress + + SectionHeader.PointerToRawData + + sizeof (EFI_TE_IMAGE_HEADER) - + TeHdr.StrippedSize; + + // + // File offset of the debug directory was found, if this is not the last + // section, then skip to the last section for calculating the image size. + // + if (Index < (UINTN) TeHdr.NumberOfSections - 1) { + SectionHeaderOffset += (TeHdr.NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER); + Index = TeHdr.NumberOfSections - 1; + continue; + } + } + + // + // In Te image header there is not a field to describe the ImageSize. + // Actually, the ImageSize equals the RVA plus the VirtualSize of + // the last section mapped into memory (Must be rounded up to + // a mulitple of Section Alignment). Per the PE/COFF specification, the + // section headers in the Section Table must appear in order of the RVA + // values for the corresponding sections. So the ImageSize can be determined + // by the RVA and the VirtualSize of the last section header in the + // Section Table. + // + if ((++Index) == (UINTN) TeHdr.NumberOfSections) { + ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize + + ImageContext->SectionAlignment - 1) & ~(ImageContext->SectionAlignment - 1); + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset, + &Size, + &DebugEntry + ); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + return EFI_SUCCESS; + } + } + } + } + + return EFI_SUCCESS; +} + +STATIC +VOID * +PeCoffLoaderImageAddress ( + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ) +/*++ + +Routine Description: + + Converts an image address to the loaded address + +Arguments: + + ImageContext - The context of the image being loaded + + Address - The address to be converted to the loaded address + +Returns: + + NULL if the address can not be converted, otherwise, the converted address + +--*/ +{ + if (Address >= ImageContext->ImageSize) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return NULL; + } + + return (CHAR8 *) ((UINTN) ImageContext->ImageAddress + Address); +} + +EFI_STATUS +EFIAPI +PeCoffLoaderRelocateImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Relocates a PE/COFF image in memory + +Arguments: + + This - Calling context + + ImageContext - Contains information on the loaded image to relocate + +Returns: + + EFI_SUCCESS if the PE/COFF image was relocated + EFI_LOAD_ERROR if the image is not a valid PE/COFF image + EFI_UNSUPPORTED not support + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + EFI_IMAGE_DATA_DIRECTORY *RelocDir; + UINT64 Adjust; + EFI_IMAGE_BASE_RELOCATION *RelocBase; + EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; + UINT16 *Reloc; + UINT16 *RelocEnd; + CHAR8 *Fixup; + CHAR8 *FixupBase; + UINT16 *F16; + UINT32 *F32; + CHAR8 *FixupData; + EFI_PHYSICAL_ADDRESS BaseAddress; +#ifdef EFI_NT_EMULATOR + VOID *DllEntryPoint; + VOID *ModHandle; + ModHandle = NULL; +#endif + + PeHdr = NULL; + TeHdr = NULL; + // + // Assume success + // + ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS; + + // + // If there are no relocation entries, then we are done + // + if (ImageContext->RelocationsStripped) { + return EFI_SUCCESS; + } + + // + // If the destination address is not 0, use that rather than the + // image address as the relocation target. + // + if (ImageContext->DestinationAddress) { + BaseAddress = ImageContext->DestinationAddress; + } else { + BaseAddress = ImageContext->ImageAddress; + } + + if (!(ImageContext->IsTeImage)) { + PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset); + Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase; + PeHdr->OptionalHeader.ImageBase = (UINTN) BaseAddress; + + // + // Find the relocation block + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + RelocDir = &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress); + RelocBaseEnd = PeCoffLoaderImageAddress ( + ImageContext, + RelocDir->VirtualAddress + RelocDir->Size - 1 + ); + } else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = 0; + } + } else { + TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress); + Adjust = (UINT64) (BaseAddress - TeHdr->ImageBase); + TeHdr->ImageBase = (UINT64) (BaseAddress); + + // + // Find the relocation block + // + RelocDir = &TeHdr->DataDirectory[0]; + RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)( + ImageContext->ImageAddress + + RelocDir->VirtualAddress + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1); + } + + // + // Run the relocation information and apply the fixups + // + FixupData = ImageContext->FixupData; + while (RelocBase < RelocBaseEnd) { + + Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); + RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock); + if (!(ImageContext->IsTeImage)) { + FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress); + } else { + FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress + + RelocBase->VirtualAddress + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + } + + if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) || + (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + + (UINTN)ImageContext->ImageSize)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION; + return EFI_LOAD_ERROR; + } + + // + // Run this relocation record + // + while (Reloc < RelocEnd) { + + Fixup = FixupBase + (*Reloc & 0xFFF); + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + + case EFI_IMAGE_REL_BASED_HIGH: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) ((*F16 << 16) + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_LOW: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) (*F16 + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHLOW: + F32 = (UINT32 *) Fixup; + *F32 = *F32 + (UINT32) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32)); + *(UINT32 *) FixupData = *F32; + FixupData = FixupData + sizeof (UINT32); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHADJ: + // + // Return the same EFI_UNSUPPORTED return code as + // PeCoffLoaderRelocateImageEx() returns if it does not recognize + // the relocation type. + // + ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION; + return EFI_UNSUPPORTED; + + default: + Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust); + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_FAILED_RELOCATION; + return Status; + } + } + + // + // Next relocation record + // + Reloc += 1; + } + + // + // Next reloc block + // + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; + } + +#ifdef EFI_NT_EMULATOR + DllEntryPoint = NULL; + ImageContext->ModHandle = NULL; + // + // Load the DLL if it's not an EBC image. + // + if ((ImageContext->PdbPointer != NULL) && + (ImageContext->Machine != EFI_IMAGE_MACHINE_EBC)) { + Status = mPeCoffLoaderWinNtLoadAsDll->Entry ( + ImageContext->PdbPointer, + &DllEntryPoint, + &ModHandle + ); + + if (!EFI_ERROR (Status) && DllEntryPoint != NULL) { + ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) DllEntryPoint; + ImageContext->ModHandle = ModHandle; + } + } +#endif + + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +PeCoffLoaderLoadImage ( + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL *This, + IN OUT EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Loads a PE/COFF image into memory + +Arguments: + + This - Calling context + + ImageContext - Contains information on image to load into memory + +Returns: + + EFI_SUCCESS if the PE/COFF image was loaded + EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer + EFI_LOAD_ERROR if the image is a runtime driver with no relocations + EFI_INVALID_PARAMETER if the image address is invalid + +--*/ +{ + EFI_STATUS Status; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT CheckContext; + EFI_IMAGE_SECTION_HEADER *FirstSection; + EFI_IMAGE_SECTION_HEADER *Section; + UINTN NumberOfSections; + UINTN Index; + CHAR8 *Base; + CHAR8 *End; + CHAR8 *MaxEnd; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN Size; + UINT32 TempDebugEntryRva; + + PeHdr = NULL; + TeHdr = NULL; + // + // Assume success + // + ImageContext->ImageError = EFI_IMAGE_ERROR_SUCCESS; + + // + // Copy the provided context info into our local version, get what we + // can from the original image, and then use that to make sure everything + // is legit. + // + CopyMem (&CheckContext, ImageContext, sizeof (EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT)); + + Status = PeCoffLoaderGetImageInfo ( + This, + &CheckContext + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Make sure there is enough allocated space for the image being loaded + // + if (ImageContext->ImageSize < CheckContext.ImageSize) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_SIZE; + return EFI_BUFFER_TOO_SMALL; + } + + // + // If there's no relocations, then make sure it's not a runtime driver, + // and that it's being loaded at the linked address. + // + if (CheckContext.RelocationsStripped) { + // + // If the image does not contain relocations and it is a runtime driver + // then return an error. + // + if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SUBSYSTEM; + return EFI_LOAD_ERROR; + } + // + // If the image does not contain relocations, and the requested load address + // is not the linked address, then return an error. + // + if (CheckContext.ImageAddress != ImageContext->ImageAddress) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return EFI_INVALID_PARAMETER; + } + } + // + // Make sure the allocated space has the proper section alignment + // + if (!(ImageContext->IsTeImage)) { + if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) { + ImageContext->ImageError = EFI_IMAGE_ERROR_INVALID_SECTION_ALIGNMENT; + return EFI_INVALID_PARAMETER; + } + } + // + // Read the entire PE/COFF or TE header into memory + // + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (VOID *) (UINTN) ImageContext->ImageAddress + ); + + PeHdr = (EFI_IMAGE_NT_HEADERS *) + ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + PeHdr->FileHeader.SizeOfOptionalHeader + ); + NumberOfSections = (UINTN) (PeHdr->FileHeader.NumberOfSections); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (void *) (UINTN) ImageContext->ImageAddress + ); + + TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + sizeof(EFI_TE_IMAGE_HEADER) + ); + NumberOfSections = (UINTN) (TeHdr->NumberOfSections); + + } + + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return EFI_LOAD_ERROR; + } + + // + // Load each section of the image + // + Section = FirstSection; + for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) { + + // + // Compute sections address + // + Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress); + End = PeCoffLoaderImageAddress ( + ImageContext, + Section->VirtualAddress + Section->Misc.VirtualSize - 1 + ); + if (ImageContext->IsTeImage) { + Base = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize); + End = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize); + } + + if (End > MaxEnd) { + MaxEnd = End; + } + // + // If the base start or end address resolved to 0, then fail. + // + if ((Base == NULL) || (End == NULL)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_SECTION_NOT_LOADED; + return EFI_LOAD_ERROR; + } + + // + // Read the section + // + Size = (UINTN) Section->Misc.VirtualSize; + if ((Size == 0) || (Size > Section->SizeOfRawData)) { + Size = (UINTN) Section->SizeOfRawData; + } + + if (Section->SizeOfRawData) { + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData, + &Size, + Base + ); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize, + &Size, + Base + ); + } + + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return Status; + } + } + + // + // If raw size is less then virt size, zero fill the remaining + // + + if (Size < Section->Misc.VirtualSize) { + ZeroMem (Base + Size, Section->Misc.VirtualSize - Size); + } + + // + // Next Section + // + Section += 1; + } + + // + // Get image's entry point + // + if (!(ImageContext->IsTeImage)) { + ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress ( + ImageContext, + PeHdr->OptionalHeader.AddressOfEntryPoint + ); + } else { + ImageContext->EntryPoint = (EFI_PHYSICAL_ADDRESS) ( + (UINTN)ImageContext->ImageAddress + + (UINTN)TeHdr->AddressOfEntryPoint + + (UINTN)sizeof(EFI_TE_IMAGE_HEADER) - + (UINTN) TeHdr->StrippedSize + ); + } + + // + // Determine the size of the fixup data + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (!(ImageContext->IsTeImage)) { + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) + &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } else { + ImageContext->FixupDataSize = 0; + } + } else { + DirectoryEntry = &TeHdr->DataDirectory[0]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } + // + // Consumer must allocate a buffer for the relocation fixup log. + // Only used for runtime drivers. + // + ImageContext->FixupData = NULL; + + // + // Load the Codeview info if present + // + if (ImageContext->DebugDirectoryEntryRva != 0) { + if (!(ImageContext->IsTeImage)) { + DebugEntry = PeCoffLoaderImageAddress ( + ImageContext, + ImageContext->DebugDirectoryEntryRva + ); + } else { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)( + ImageContext->ImageAddress + + ImageContext->DebugDirectoryEntryRva + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + } + + if (DebugEntry != NULL) { + TempDebugEntryRva = DebugEntry->RVA; + if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) { + Section--; + if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) { + TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize; + } else { + TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData; + } + } + + if (TempDebugEntryRva != 0) { + if (!(ImageContext->IsTeImage)) { + ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva); + } else { + ImageContext->CodeView = (VOID *)( + (UINTN)ImageContext->ImageAddress + + (UINTN)TempDebugEntryRva + + (UINTN)sizeof(EFI_TE_IMAGE_HEADER) - + (UINTN) TeHdr->StrippedSize + ); + } + + if (ImageContext->CodeView == NULL) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return EFI_LOAD_ERROR; + } + + if (DebugEntry->RVA == 0) { + Size = DebugEntry->SizeOfData; + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset, + &Size, + ImageContext->CodeView + ); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr->StrippedSize, + &Size, + ImageContext->CodeView + ); + // + // Should we apply fix up to this field according to the size difference between PE and TE? + // Because now we maintain TE header fields unfixed, this field will also remain as they are + // in original PE image. + // + } + + if (EFI_ERROR (Status)) { + ImageContext->ImageError = EFI_IMAGE_ERROR_IMAGE_READ; + return EFI_LOAD_ERROR; + } + + DebugEntry->RVA = TempDebugEntryRva; + } + + switch (*(UINT32 *) ImageContext->CodeView) { + case CODEVIEW_SIGNATURE_NB10: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + break; + } + } + } + } + + return Status; +} + +EFI_STATUS +EFIAPI +PeCoffLoaderUnloadImage ( + IN EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Unload a PE/COFF image from memory + +Arguments: + + ImageContext - Contains information on image to load into memory + +Returns: + + EFI_SUCCESS + +--*/ +{ +#ifdef EFI_NT_EMULATOR + // + // Calling Win32 API free library + // + mPeCoffLoaderWinNtLoadAsDll->FreeLibrary (ImageContext->ModHandle); + +#endif + + return EFI_SUCCESS; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/PeiLib.c b/Tools/Source/TianoTools/Common/PeiLib/PeiLib.c new file mode 100644 index 0000000000..fec7182908 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/PeiLib.c @@ -0,0 +1,169 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + PeiLib.c + +Abstract: + + PEI Library Functions + +--*/ + +#include "TianoCommon.h" +#include "PeiHob.h" +#include "Pei.h" + +VOID +PeiCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +VOID +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + Set Buffer to zero for Size bytes. + +Arguments: + + Buffer - Memory to set. + + Size - Number of bytes to set + +Returns: + + None + +--*/ +{ + INT8 *Ptr; + + Ptr = Buffer; + while (Size--) { + *(Ptr++) = 0; + } +} + +VOID +PeiCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + + Destination8 = Destination; + Source8 = Source; + while (Length--) { + *(Destination8++) = *(Source8++); + } +} + +VOID +CopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + + Destination8 = Destination; + Source8 = Source; + while (Length--) { + *(Destination8++) = *(Source8++); + } +} + +BOOLEAN +CompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +/*++ + +Routine Description: + + Compares two GUIDs + +Arguments: + + Guid1 - guid to compare + Guid2 - guid to compare + +Returns: + = TRUE if Guid1 == Guid2 + = FALSE if Guid1 != Guid2 + +--*/ +{ + if ((((INT32 *) Guid1)[0] - ((INT32 *) Guid2)[0]) == 0) { + if ((((INT32 *) Guid1)[1] - ((INT32 *) Guid2)[1]) == 0) { + if ((((INT32 *) Guid1)[2] - ((INT32 *) Guid2)[2]) == 0) { + if ((((INT32 *) Guid1)[3] - ((INT32 *) Guid2)[3]) == 0) { + return TRUE; + } + } + } + } + + return FALSE; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/PeiLib.h b/Tools/Source/TianoTools/Common/PeiLib/PeiLib.h new file mode 100644 index 0000000000..ccb8d2f6a6 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/PeiLib.h @@ -0,0 +1,798 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + PeiLib.h + +Abstract: + + PEI Library Functions + +--*/ + +#ifndef _PEI_LIB_H_ +#define _PEI_LIB_H_ + +#include "Tiano.h" +#include "Pei.h" +#include "peiHobLib.h" +#include EFI_PROTOCOL_DEFINITION (Decompress) +#include EFI_PROTOCOL_DEFINITION (TianoDecompress) +#include EFI_GUID_DEFINITION (PeiPeCoffLoader) + +VOID +PeiCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +; + +VOID +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + Set Buffer to zero for Size bytes. + +Arguments: + + Buffer - Memory to set. + + Size - Number of bytes to set + +Returns: + + None + +--*/ +; + +VOID +CopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +; + +BOOLEAN +CompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +/*++ + +Routine Description: + + Compares two GUIDs + +Arguments: + + Guid1 - guid to compare + Guid2 - guid to compare + +Returns: + = TRUE if Guid1 == Guid2 + = FALSE if Guid1 != Guid2 + +--*/ +; + +EFI_STATUS +InstallEfiPeiPeCoffLoader ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PEI_PE_COFF_LOADER_PROTOCOL **This, + IN EFI_PEI_PPI_DESCRIPTOR *ThisPpi + ) +/*++ + +Routine Description: + + Install EFI Pei PE coff loader protocol. + +Arguments: + + PeiServices - The PEI core services table. + + This - Pointer to get Pei PE coff loader protocol as output + + ThisPpi - Passed in as EFI_NT_LOAD_AS_DLL_PPI on NT_EMULATOR platform + +Returns: + + EFI_SUCCESS + +--*/ +; + +EFI_STATUS +InstallEfiDecompress ( + EFI_DECOMPRESS_PROTOCOL **This + ) +/*++ + +Routine Description: + + Install EFI decompress protocol. + +Arguments: + + This - Pointer to get decompress protocol as output + +Returns: + + EFI_SUCCESS - EFI decompress protocol successfully installed. + +--*/ +; + +EFI_STATUS +InstallTianoDecompress ( + EFI_TIANO_DECOMPRESS_PROTOCOL **This + ) +/*++ + +Routine Description: + + Install Tiano decompress protocol. + +Arguments: + + This - Pointer to get decompress protocol as output + +Returns: + + EFI_SUCCESS - Tiano decompress protocol successfully installed. + +--*/ +; + +VOID +PeiPerfMeasure ( + EFI_PEI_SERVICES **PeiServices, + IN UINT16 *Token, + IN EFI_FFS_FILE_HEADER *FileHeader, + IN BOOLEAN EntryExit, + IN UINT64 Value + ) +/*++ + +Routine Description: + + Log a timestamp count. + +Arguments: + + PeiServices - Pointer to the PEI Core Services table + + Token - Pointer to Token Name + + FileHeader - Pointer to the file header + + EntryExit - Indicates start or stop measurement + + Value - The start time or the stop time + +Returns: + +--*/ +; + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ) +/*++ + +Routine Description: + + Get timer value. + +Arguments: + + TimerValue - Pointer to the returned timer value + +Returns: + + EFI_SUCCESS - Successfully got timer value + +--*/ +; + +#ifdef EFI_PEI_PERFORMANCE +#define PEI_PERF_START(Ps, Token, FileHeader, Value) PeiPerfMeasure (Ps, Token, FileHeader, FALSE, Value) +#define PEI_PERF_END(Ps, Token, FileHeader, Value) PeiPerfMeasure (Ps, Token, FileHeader, TRUE, Value) +#else +#define PEI_PERF_START(Ps, Token, FileHeader, Value) +#define PEI_PERF_END(Ps, Token, FileHeader, Value) +#endif + +#ifdef EFI_NT_EMULATOR +EFI_STATUS +PeCoffLoaderWinNtLoadAsDll ( + IN CHAR8 *PdbFileName, + IN VOID **ImageEntryPoint, + OUT VOID **ModHandle + ) +/*++ + +Routine Description: + + Loads the .DLL file is present when a PE/COFF file is loaded. This provides source level + debugging for drivers that have cooresponding .DLL files on the local system. + +Arguments: + + PdbFileName - The name of the .PDB file. This was found from the PE/COFF + file's debug directory entry. + + ImageEntryPoint - A pointer to the DLL entry point of the .DLL file was loaded. + + ModHandle - Pointer to loaded library. + +Returns: + + EFI_SUCCESS - The .DLL file was loaded, and the DLL entry point is returned in ImageEntryPoint + + EFI_NOT_FOUND - The .DLL file could not be found + + EFI_UNSUPPORTED - The .DLL file was loaded, but the entry point to the .DLL file could not + determined. + +--*/ +; + +#endif +// +// hob.c +// +EFI_STATUS +PeiBuildHobModule ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *ModuleName, + IN EFI_PHYSICAL_ADDRESS Module, + IN UINT64 ModuleLength, + IN EFI_PHYSICAL_ADDRESS EntryPoint + ) +/*++ + +Routine Description: + + Builds a HOB for a loaded PE32 module + +Arguments: + + PeiServices - The PEI core services table. + ModuleName - The GUID File Name of the module + Memory - The 64 bit physical address of the module + ModuleLength - The length of the module in bytes + EntryPoint - The 64 bit physical address of the entry point + to the module + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobResourceDescriptor ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_RESOURCE_TYPE ResourceType, + IN EFI_RESOURCE_ATTRIBUTE_TYPE ResourceAttribute, + IN EFI_PHYSICAL_ADDRESS PhysicalStart, + IN UINT64 NumberOfBytes + ) +/*++ + +Routine Description: + + Builds a HOB that describes a chunck of system memory + +Arguments: + + PeiServices - The PEI core services table. + + ResourceType - The type of resource described by this HOB + + ResourceAttribute - The resource attributes of the memory described by this HOB + + PhysicalStart - The 64 bit physical address of memory described by this HOB + + NumberOfBytes - The length of the memoty described by this HOB in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobGuid ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN UINTN DataLength, + IN OUT VOID **Hob + ) +/*++ + +Routine Description: + + Builds a custom HOB that is tagged with a GUID for identification + +Arguments: + + PeiServices - The PEI core services table. + + Guid - The GUID of the custome HOB type + + DataLength - The size of the data payload for the GUIDed HOB + + Hob - Pointer to the Hob + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobGuidData ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_GUID *Guid, + IN VOID *Data, + IN UINTN DataLength + ) +/*++ + +Routine Description: + + Builds a custom HOB that is tagged with a GUID for identification + +Arguments: + + PeiServices - The PEI core services table. + + Guid - The GUID of the custome HOB type + + Data - The data to be copied into the GUIDed HOB data field. + + DataLength - The data field length. + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobFv ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a Firmware Volume HOB + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The base address of the Firmware Volume + + Length - The size of the Firmware Volume in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobCpu ( + IN EFI_PEI_SERVICES **PeiServices, + IN UINT8 SizeOfMemorySpace, + IN UINT8 SizeOfIoSpace + ) +/*++ + +Routine Description: + + Builds a HOB for the CPU + +Arguments: + + PeiServices - The PEI core services table. + + SizeOfMemorySpace - Identifies the maximum + physical memory addressibility of the processor. + + SizeOfIoSpace - Identifies the maximum physical I/O addressibility + of the processor. + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobStack ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length + ) +/*++ + +Routine Description: + + Builds a HOB for the Stack + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The 64 bit physical address of the Stack + + Length - The length of the stack in bytes + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobBspStore ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for the bsp store + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The 64 bit physical address of the bsp store + + Length - The length of the bsp store in bytes + + MemoryType - Memory type + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +EFI_STATUS +PeiBuildHobMemoryAllocation ( + IN EFI_PEI_SERVICES **PeiServices, + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN EFI_GUID *Name, + IN EFI_MEMORY_TYPE MemoryType + ) +/*++ + +Routine Description: + + Builds a HOB for the memory allocation + +Arguments: + + PeiServices - The PEI core services table. + + BaseAddress - The 64 bit physical address of the memory + + Length - The length of the memory allocation in bytes + + Name - Name for Hob + + MemoryType - Memory type + +Returns: + + EFI_SUCCESS - Hob is successfully built. + Others - Errors occur while creating new Hob + +--*/ +; + +// +// print.c +// +UINTN +AvSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN StrSize, + IN CONST CHAR8 *Format, + IN VA_LIST Marker + ) +/*++ + +Routine Description: + + AvSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this rountine allows the nesting of Vararg routines. Thus + this is the main print working routine + +Arguments: + + StartOfBuffer - Ascii buffer to print the results of the parsing of Format into. + + StrSize - Maximum number of characters to put into buffer. Zero means + no limit. + + FormatString - Ascii format string see file header for more details. + + Marker - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +; + +UINTN +ASPrint ( + OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN CONST CHAR8 *Format, + ... + ) +/*++ + +Routine Description: + + ASPrint function to process format and place the results in Buffer. + +Arguments: + + Buffer - Ascii buffer to print the results of the parsing of Format into. + + BufferSize - Maximum number of characters to put into buffer. Zero means no + limit. + + Format - Ascii format string see file header for more details. + + ... - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +; + +// +// math.c +// +UINT64 +MultU64x32 ( + IN UINT64 Multiplicand, + IN UINTN Multiplier + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be multiplied with a 32 bit + value returns 64bit result. + No checking if the result is greater than 64bits + +Arguments: + + Multiplicand - multiplicand + Multiplier - multiplier + +Returns: + + Multiplicand * Multiplier + +--*/ +; + +UINT64 +DivU64x32 ( + IN UINT64 Dividend, + IN UINTN Divisor, + OUT UINTN *Remainder OPTIONAL + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be divided with a 32 bit value returns + 64bit result and the Remainder. + N.B. only works for 31bit divisors!! + +Arguments: + + Dividend - dividend + Divisor - divisor + Remainder - buffer for remainder + +Returns: + + Dividend / Divisor + Remainder = Dividend mod Divisor + +--*/ +; + +UINT64 +RShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be right shifted by 32 bits and returns the + shifted value. + Count is valid up 63. (Only Bits 0-5 is valid for Count) + +Arguments: + + Operand - Value to be shifted + Count - Number of times to shift right. + +Returns: + + Value shifted right identified by the Count. + +--*/ +; + +UINT64 +LShiftU64 ( + IN UINT64 Operand, + IN UINTN Count + ) +/*++ + +Routine Description: + + This routine allows a 64 bit value to be left shifted by 32 bits and + returns the shifted value. + Count is valid up 63. (Only Bits 0-5 is valid for Count) + +Arguments: + + Operand - Value to be shifted + Count - Number of times to shift left. + +Returns: + + Value shifted left identified by the Count. + +--*/ +; + +VOID +RegisterNativeCpuIo ( + IN EFI_PEI_SERVICES **PeiServices, + IN VOID *CpuIo + ) +/*++ + +Routine Description: + + Register a native Cpu IO + +Arguments: + + PeiServices - Calling context + CpuIo - CpuIo instance to register + +Returns: + + None + +--*/ +; + +VOID +GetNativeCpuIo ( + IN EFI_PEI_SERVICES **PeiServices, + OUT VOID **CpuIo + ) +/*++ + +Routine Description: + + Get registered Cpu IO. + +Arguments: + + PeiServices - Calling context + CpuIo - CpuIo instance registered before + +Returns: + + None + +--*/ +; + +#endif diff --git a/Tools/Source/TianoTools/Common/PeiLib/Perf.c b/Tools/Source/TianoTools/Common/PeiLib/Perf.c new file mode 100644 index 0000000000..cfc265ee66 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Perf.c @@ -0,0 +1,233 @@ +/*++ + +Copyright (c) 2004 - 2005, 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. + +Module Name: + + Perf.c + +Abstract: + + Support for performance primitives. + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "PeiLib.h" +#include "PeiHob.h" + +#include EFI_GUID_DEFINITION (PeiPerformanceHob) + +// +// Perfomance HOB data definitions +// + +#define MAX_PEI_PERF_LOG_ENTRIES 28 + +// +// Prototype functions +// +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ); + + +VOID +PeiPerfMeasure ( + EFI_PEI_SERVICES **PeiServices, + IN UINT16 *Token, + IN EFI_FFS_FILE_HEADER *FileHeader, + IN BOOLEAN EntryExit, + IN UINT64 Value + ) +/*++ + +Routine Description: + + Log a timestamp count. + +Arguments: + + PeiServices - Pointer to the PEI Core Services table + + Token - Pointer to Token Name + + FileHeader - Pointer to the file header + + EntryExit - Indicates start or stop measurement + + Value - The start time or the stop time + +Returns: + +--*/ +{ + EFI_STATUS Status; + EFI_HOB_GUID_TYPE *Hob; + EFI_HOB_GUID_DATA_PERFORMANCE_LOG *PerfHobData; + PEI_PERFORMANCE_MEASURE_LOG_ENTRY *Log; + EFI_PEI_PPI_DESCRIPTOR *PerfHobDescriptor; + UINT64 TimeCount; + INTN Index; + UINTN Index2; + EFI_GUID *Guid; + EFI_GUID *CheckGuid; + + TimeCount = 0; + // + // Get the END time as early as possible to make it more accurate. + // + if (EntryExit) { + GetTimerValue (&TimeCount); + } + + // + // Locate the Pei Performance Log Hob. + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiPerformanceHobGuid, + 0, + &PerfHobDescriptor, + NULL + ); + + // + // If the Performance Hob was not found, build and install one. + // + if (EFI_ERROR(Status)) { + Status = PeiBuildHobGuid ( + PeiServices, + &gEfiPeiPerformanceHobGuid, + (sizeof(EFI_HOB_GUID_DATA_PERFORMANCE_LOG) + + ((MAX_PEI_PERF_LOG_ENTRIES-1) * + sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY)) + + sizeof(EFI_PEI_PPI_DESCRIPTOR) + ), + &Hob + ); + ASSERT_PEI_ERROR(PeiServices, Status); + + PerfHobData = (EFI_HOB_GUID_DATA_PERFORMANCE_LOG *)(Hob+1); + PerfHobData->NumberOfEntries = 0; + + PerfHobDescriptor = (EFI_PEI_PPI_DESCRIPTOR *)((UINT8 *)(PerfHobData+1) + + (sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY) * + (MAX_PEI_PERF_LOG_ENTRIES-1) + ) + ); + PerfHobDescriptor->Flags = (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST); + PerfHobDescriptor->Guid = &gEfiPeiPerformanceHobGuid; + PerfHobDescriptor->Ppi = NULL; + + (*PeiServices)->InstallPpi ( + PeiServices, + PerfHobDescriptor + ); + } + + PerfHobData = (EFI_HOB_GUID_DATA_PERFORMANCE_LOG *)(((UINT8 *)(PerfHobDescriptor)) - + ((sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY) * + (MAX_PEI_PERF_LOG_ENTRIES-1) + ) + + sizeof(EFI_HOB_GUID_DATA_PERFORMANCE_LOG) + ) + ); + + if (PerfHobData->NumberOfEntries >= MAX_PEI_PERF_LOG_ENTRIES) { + return; + } + + if (!EntryExit) { + Log = &(PerfHobData->Log[PerfHobData->NumberOfEntries]); + (*PeiServices)->SetMem (Log, sizeof(PEI_PERFORMANCE_MEASURE_LOG_ENTRY), 0); + + // + // If not NULL pointer, copy the file name + // + if (FileHeader != NULL) { + Log->Name = FileHeader->Name; + } + + // + // Copy the description string + // + (*PeiServices)->CopyMem ( + &(Log->DescriptionString), + Token, + (PEI_PERF_MAX_DESC_STRING-1) * sizeof(UINT16) + ); + + // + // Get the start time as late as possible to make it more accurate. + // + GetTimerValue (&TimeCount); + + // + // Record the time stamp. + // + if (Value != 0) { + Log->StartTimeCount = Value; + } else { + Log->StartTimeCount = TimeCount; + } + Log->StopTimeCount = 0; + + // + // Increment the number of valid log entries. + // + PerfHobData->NumberOfEntries++; + + } else { + + for (Index = PerfHobData->NumberOfEntries-1; Index >= 0; Index--) { + Log = NULL; + for (Index2 = 0; Index2 < PEI_PERF_MAX_DESC_STRING; Index2++) { + if (PerfHobData->Log[Index].DescriptionString[Index2] == 0) { + Log = &(PerfHobData->Log[Index]); + break; + } + if (PerfHobData->Log[Index].DescriptionString[Index2] != + Token[Index2]) { + break; + } + } + if (Log != NULL) { + if (FileHeader != NULL) { + Guid = &(Log->Name); + CheckGuid = &(FileHeader->Name); + if ((((INT32 *)Guid)[0] == ((INT32 *)CheckGuid)[0]) && + (((INT32 *)Guid)[1] == ((INT32 *)CheckGuid)[1]) && + (((INT32 *)Guid)[2] == ((INT32 *)CheckGuid)[2]) && + (((INT32 *)Guid)[3] == ((INT32 *)CheckGuid)[3])) { + if (Value != 0) { + Log->StopTimeCount = Value; + } else { + Log->StopTimeCount = TimeCount; + } + break; + } + } else { + if (Value != 0) { + Log->StopTimeCount = Value; + } else { + Log->StopTimeCount = TimeCount; + } + break; + } + } + } + + } + + return; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/Print/Print.c b/Tools/Source/TianoTools/Common/PeiLib/Print/Print.c new file mode 100644 index 0000000000..13e7d33ae0 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Print/Print.c @@ -0,0 +1,736 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + Print.c + +Abstract: + + Basic Ascii AvSPrintf() function named AvSPrint(). AvSPrint() enables very + simple implemenation of debug prints. + + You can not Print more than PEI_LIB_MAX_PRINT_BUFFER characters at a + time. This makes the implementation very simple. + + AvSPrint format specification has the follwoing form + + %[flags][width]type + + flags: + '-' - Left justify + '+' - Prefix a sign + ' ' - Prefix a blank + ',' - Place commas in numberss + '0' - Prefix for width with zeros + 'l' - UINT64 + 'L' - UINT64 + + width: + '*' - Get width from a UINTN argumnet from the argument list + Decimal number that represents width of print + + type: + 'X' - argument is a UINTN hex number, prefix '0' + 'x' - argument is a hex number + 'd' - argument is a decimal number + 'a' - argument is an ascii string + 'S', 's' - argument is an Unicode string + 'g' - argument is a pointer to an EFI_GUID + 't' - argument is a pointer to an EFI_TIME structure + 'c' - argument is an ascii character + 'r' - argument is EFI_STATUS + '%' - Print a % + +--*/ + +#include "Tiano.h" +#include "Pei.h" +#include "PeiLib.h" +#include "Print.h" + + +STATIC +CHAR8 * +GetFlagsAndWidth ( + IN CHAR8 *Format, + OUT UINTN *Flags, + OUT UINTN *Width, + IN OUT VA_LIST *Marker + ); + +STATIC +UINTN +ValueToString ( + IN OUT CHAR8 *Buffer, + IN INT64 Value, + IN UINTN Flags, + IN UINTN Width + ); + +STATIC +UINTN +ValueTomHexStr ( + IN OUT CHAR8 *Buffer, + IN UINT64 Value, + IN UINTN Flags, + IN UINTN Width + ); + +STATIC +UINTN +GuidToString ( + IN EFI_GUID *Guid, + IN OUT CHAR8 *Buffer, + IN UINTN BufferSize + ); + +STATIC +UINTN +TimeToString ( + IN EFI_TIME *Time, + IN OUT CHAR8 *Buffer, + IN UINTN BufferSize + ); + +STATIC +UINTN +EfiStatusToString ( + IN EFI_STATUS Status, + OUT CHAR8 *Buffer, + IN UINTN BufferSize + ); + + +UINTN +ASPrint ( + OUT CHAR8 *Buffer, + IN UINTN BufferSize, + IN CONST CHAR8 *Format, + ... + ) +/*++ + +Routine Description: + + ASPrint function to process format and place the results in Buffer. + +Arguments: + + Buffer - Ascii buffer to print the results of the parsing of Format into. + + BufferSize - Maximum number of characters to put into buffer. Zero means no + limit. + + Format - Ascii format string see file header for more details. + + ... - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +{ + UINTN Return; + VA_LIST Marker; + + VA_START(Marker, Format); + Return = AvSPrint(Buffer, BufferSize, Format, Marker); + VA_END (Marker); + + return Return; +} + + +UINTN +AvSPrint ( + OUT CHAR8 *StartOfBuffer, + IN UINTN BufferSize, + IN CONST CHAR8 *FormatString, + IN VA_LIST Marker + ) +/*++ + +Routine Description: + + AvSPrint function to process format and place the results in Buffer. Since a + VA_LIST is used this rountine allows the nesting of Vararg routines. Thus + this is the main print working routine + +Arguments: + + StartOfBuffer - Ascii buffer to print the results of the parsing of Format into. + + BufferSize - Maximum number of characters to put into buffer. Zero means + no limit. + + FormatString - Ascii format string see file header for more details. + + Marker - Vararg list consumed by processing Format. + +Returns: + + Number of characters printed. + +--*/ +{ + CHAR8 *Buffer; + CHAR8 *AsciiStr; + CHAR16 *UnicodeStr; + CHAR8 *Format; + UINTN Index; + UINTN Flags; + UINTN Width; + UINT64 Value; + + // + // Process the format string. Stop if Buffer is over run. + // + + Buffer = StartOfBuffer; + Format = (CHAR8 *)FormatString; + for (Index = 0; (*Format != '\0') && (Index < BufferSize); Format++) { + if (*Format != '%') { + if (*Format == '\n') { + // + // If carage return add line feed + // + Buffer[Index++] = '\r'; + } + Buffer[Index++] = *Format; + } else { + + // + // Now it's time to parse what follows after % + // + Format = GetFlagsAndWidth (Format, &Flags, &Width, &Marker); + switch (*Format) { + case 'X': + Flags |= PREFIX_ZERO; + Width = sizeof (UINT64) * 2; + // + // break skiped on purpose + // + case 'x': + if ((Flags & LONG_TYPE) == LONG_TYPE) { + Value = VA_ARG (Marker, UINT64); + } else { + Value = VA_ARG (Marker, UINTN); + } + Index += ValueTomHexStr (&Buffer[Index], Value, Flags, Width); + break; + + case 'd': + if ((Flags & LONG_TYPE) == LONG_TYPE) { + Value = VA_ARG (Marker, UINT64); + } else { + Value = (UINTN)VA_ARG (Marker, UINTN); + } + Index += ValueToString (&Buffer[Index], Value, Flags, Width); + break; + + case 's': + case 'S': + UnicodeStr = (CHAR16 *)VA_ARG (Marker, CHAR16 *); + if (UnicodeStr == NULL) { + UnicodeStr = L""; + } + for ( ;*UnicodeStr != '\0'; UnicodeStr++) { + Buffer[Index++] = (CHAR8)*UnicodeStr; + } + break; + + case 'a': + AsciiStr = (CHAR8 *)VA_ARG (Marker, CHAR8 *); + if (AsciiStr == NULL) { + AsciiStr = ""; + } + while (*AsciiStr != '\0') { + Buffer[Index++] = *AsciiStr++; + } + break; + + case 'c': + Buffer[Index++] = (CHAR8)VA_ARG (Marker, UINTN); + break; + + case 'g': + Index += GuidToString ( + VA_ARG (Marker, EFI_GUID *), + &Buffer[Index], + BufferSize + ); + break; + + case 't': + Index += TimeToString ( + VA_ARG (Marker, EFI_TIME *), + &Buffer[Index], + BufferSize + ); + break; + + case 'r': + Index += EfiStatusToString ( + VA_ARG (Marker, EFI_STATUS), + &Buffer[Index], + BufferSize + ); + break; + + case '%': + Buffer[Index++] = *Format; + break; + + default: + // + // if the type is unknown print it to the screen + // + Buffer[Index++] = *Format; + } + + } + } + Buffer[Index++] = '\0'; + + return &Buffer[Index] - StartOfBuffer; +} + + + +STATIC +CHAR8 * +GetFlagsAndWidth ( + IN CHAR8 *Format, + OUT UINTN *Flags, + OUT UINTN *Width, + IN OUT VA_LIST *Marker + ) +/*++ + +Routine Description: + + AvSPrint worker function that parses flag and width information from the + Format string and returns the next index into the Format string that needs + to be parsed. See file headed for details of Flag and Width. + +Arguments: + + Format - Current location in the AvSPrint format string. + + Flags - Returns flags + + Width - Returns width of element + + Marker - Vararg list that may be paritally consumed and returned. + +Returns: + + Pointer indexed into the Format string for all the information parsed + by this routine. + +--*/ +{ + UINTN Count; + BOOLEAN Done; + + *Flags = 0; + *Width = 0; + for (Done = FALSE; !Done; ) { + Format++; + + switch (*Format) { + + case '-': *Flags |= LEFT_JUSTIFY; break; + case '+': *Flags |= PREFIX_SIGN; break; + case ' ': *Flags |= PREFIX_BLANK; break; + case ',': *Flags |= COMMA_TYPE; break; + case 'L': + case 'l': *Flags |= LONG_TYPE; break; + + case '*': + *Width = VA_ARG (*Marker, UINTN); + break; + + case '0': + *Flags |= PREFIX_ZERO; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + Count = 0; + do { + Count = (Count * 10) + *Format - '0'; + Format++; + } while ((*Format >= '0') && (*Format <= '9')); + Format--; + *Width = Count; + break; + + default: + Done = TRUE; + } + } + return Format; +} + +static CHAR8 mHexStr[] = { '0','1','2','3','4','5','6','7', + '8','9','A','B','C','D','E','F' }; + +STATIC +UINTN +ValueTomHexStr ( + IN OUT CHAR8 *Buffer, + IN UINT64 Value, + IN UINTN Flags, + IN UINTN Width + ) +/*++ + +Routine Description: + + AvSPrint worker function that prints a Value as a hex number in Buffer + +Arguments: + + Buffer - Location to place ascii hex string of Value. + + Value - Hex value to convert to a string in Buffer. + + Flags - Flags to use in printing Hex string, see file header for details. + + Width - Width of hex value. + +Returns: + + Number of characters printed. + +--*/ +{ + CHAR8 TempBuffer[30]; + CHAR8 *TempStr; + CHAR8 Prefix; + CHAR8 *BufferPtr; + UINTN Count; + UINTN Index; + + TempStr = TempBuffer; + BufferPtr = Buffer; + + // + // Count starts at one since we will null terminate. Each iteration of the + // loop picks off one nibble. Oh yea TempStr ends up backwards + // + Count = 0; + do { + *(TempStr++) = mHexStr[Value & 0x0f]; + Value = RShiftU64 (Value, 4); + Count++; + } while (Value != 0); + + if (Flags & PREFIX_ZERO) { + Prefix = '0'; + } else if (!(Flags & LEFT_JUSTIFY)) { + Prefix = ' '; + } else { + Prefix = 0x00; + } + for (Index = Count; Index < Width; Index++) { + *(TempStr++) = Prefix; + } + + // + // Reverse temp string into Buffer. + // + while (TempStr != TempBuffer) { + *(BufferPtr++) = *(--TempStr); + } + + *BufferPtr = 0; + return Index; +} + +STATIC +UINTN +ValueToString ( + IN OUT CHAR8 *Buffer, + IN INT64 Value, + IN UINTN Flags, + IN UINTN Width + ) +/*++ + +Routine Description: + + AvSPrint worker function that prints a Value as a decimal number in Buffer + +Arguments: + + Buffer - Location to place ascii decimal number string of Value. + + Value - Decimal value to convert to a string in Buffer. + + Flags - Flags to use in printing decimal string, see file header for details. + + Width - Width of hex value. + +Returns: + + Number of characters printed. + +--*/ +{ + CHAR8 TempBuffer[30]; + CHAR8 *TempStr; + CHAR8 *BufferPtr; + UINTN Count; + UINTN Remainder; + + TempStr = TempBuffer; + BufferPtr = Buffer; + Count = 0; + + if (Value < 0) { + *(BufferPtr++) = '-'; + Value = -Value; + Count++; + } + + do { + Value = (INT64)DivU64x32 ((UINT64)Value, 10, &Remainder); + *(TempStr++) = (CHAR8)(Remainder + '0'); + Count++; + if ((Flags & COMMA_TYPE) == COMMA_TYPE) { + if (Count % 3 == 0) { + *(TempStr++) = ','; + } + } + } while (Value != 0); + + // + // Reverse temp string into Buffer. + // + while (TempStr != TempBuffer) { + *(BufferPtr++) = *(--TempStr); + } + + *BufferPtr = 0; + return Count; +} + +STATIC +UINTN +GuidToString ( + IN EFI_GUID *Guid, + IN CHAR8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + AvSPrint worker function that prints an EFI_GUID. + +Arguments: + + Guid - Pointer to GUID to print. + + Buffer - Buffe to print Guid into. + + BufferSize - Size of Buffer. + +Returns: + + Number of characters printed. + +--*/ +{ + UINTN Size; + + Size = ASPrint ( + Buffer, + BufferSize, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7] + ); + + // + // ASPrint will null terminate the string. The -1 skips the null + // + return Size - 1; +} + + +STATIC +UINTN +TimeToString ( + IN EFI_TIME *Time, + OUT CHAR8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + AvSPrint worker function that prints EFI_TIME. + +Arguments: + + Time - Pointer to EFI_TIME sturcture to print. + + Buffer - Buffer to print Time into. + + BufferSize - Size of Buffer. + +Returns: + + Number of characters printed. + +--*/ +{ + UINTN Size; + + Size = ASPrint ( + Buffer, + BufferSize, + "%02d/%02d/%04d %02d:%02d", + Time->Month, + Time->Day, + Time->Year, + Time->Hour, + Time->Minute + ); + + // + // ASPrint will null terminate the string. The -1 skips the null + // + return Size - 1; +} + +STATIC +UINTN +EfiStatusToString ( + IN EFI_STATUS Status, + OUT CHAR8 *Buffer, + IN UINTN BufferSize + ) +/*++ + +Routine Description: + + AvSPrint worker function that prints EFI_STATUS as a string. If string is + not known a hex value will be printed. + +Arguments: + + Status - EFI_STATUS sturcture to print. + + Buffer - Buffer to print EFI_STATUS message string into. + + BufferSize - Size of Buffer. + +Returns: + + Number of characters printed. + +--*/ +{ + UINTN Size; + CHAR8 *Desc; + + if (Status == EFI_SUCCESS) { + Desc = "Success"; + } else if (Status == EFI_LOAD_ERROR) { + Desc = "Load Error"; + } else if (Status == EFI_INVALID_PARAMETER) { + Desc = "Invalid Parameter"; + } else if (Status == EFI_UNSUPPORTED) { + Desc = "Unsupported"; + } else if (Status == EFI_BAD_BUFFER_SIZE) { + Desc = "Bad Buffer Size"; + } else if (Status == EFI_BUFFER_TOO_SMALL) { + Desc = "Buffer Too Small"; + } else if (Status == EFI_NOT_READY) { + Desc = "Not Ready"; + } else if (Status == EFI_DEVICE_ERROR) { + Desc = "Device Error"; + } else if (Status == EFI_WRITE_PROTECTED) { + Desc = "Write Protected"; + } else if (Status == EFI_OUT_OF_RESOURCES) { + Desc = "Out of Resources"; + } else if (Status == EFI_VOLUME_CORRUPTED) { + Desc = "Volume Corrupt"; + } else if (Status == EFI_VOLUME_FULL) { + Desc = "Volume Full"; + } else if (Status == EFI_NO_MEDIA) { + Desc = "No Media"; + } else if (Status == EFI_MEDIA_CHANGED) { + Desc = "Media changed"; + } else if (Status == EFI_NOT_FOUND) { + Desc = "Not Found"; + } else if (Status == EFI_ACCESS_DENIED) { + Desc = "Access Denied"; + } else if (Status == EFI_NO_RESPONSE) { + Desc = "No Response"; + } else if (Status == EFI_NO_MAPPING) { + Desc = "No mapping"; + } else if (Status == EFI_TIMEOUT) { + Desc = "Time out"; + } else if (Status == EFI_NOT_STARTED) { + Desc = "Not started"; + } else if (Status == EFI_ALREADY_STARTED) { + Desc = "Already started"; + } else if (Status == EFI_ABORTED) { + Desc = "Aborted"; + } else if (Status == EFI_ICMP_ERROR) { + Desc = "ICMP Error"; + } else if (Status == EFI_TFTP_ERROR) { + Desc = "TFTP Error"; + } else if (Status == EFI_PROTOCOL_ERROR) { + Desc = "Protocol Error"; + } else if (Status == EFI_WARN_UNKNOWN_GLYPH) { + Desc = "Warning Unknown Glyph"; + } else if (Status == EFI_WARN_DELETE_FAILURE) { + Desc = "Warning Delete Failure"; + } else if (Status == EFI_WARN_WRITE_FAILURE) { + Desc = "Warning Write Failure"; + } else if (Status == EFI_WARN_BUFFER_TOO_SMALL) { + Desc = "Warning Buffer Too Small"; + } else { + Desc = NULL; + } + // + // If we found a match, copy the message to the user's buffer. Otherwise + // sprint the hex status code to their buffer. + // + if (Desc != NULL) { + Size = ASPrint (Buffer, BufferSize, "%a", Desc); + } else { + Size = ASPrint (Buffer, BufferSize, "%X", Status); + } + return Size - 1; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/Print/Print.h b/Tools/Source/TianoTools/Common/PeiLib/Print/Print.h new file mode 100644 index 0000000000..18c1834b81 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/Print/Print.h @@ -0,0 +1,37 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + Print.h + +Abstract: + + Private data for Print.c + +--*/ + +#ifndef _PRINT_H_ +#define _PRINT_H_ + +#define LEFT_JUSTIFY 0x01 +#define PREFIX_SIGN 0x02 +#define PREFIX_BLANK 0x04 +#define COMMA_TYPE 0x08 +#define LONG_TYPE 0x10 +#define PREFIX_ZERO 0x20 + +// +// Largest number of characters that can be printed out. +// +#define PEI_LIB_MAX_PRINT_BUFFER (80 * 4) + +#endif diff --git a/Tools/Source/TianoTools/Common/PeiLib/ia32/PeCoffLoaderEx.c b/Tools/Source/TianoTools/Common/PeiLib/ia32/PeCoffLoaderEx.c new file mode 100644 index 0000000000..6e40bf8ddf --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/ia32/PeCoffLoaderEx.c @@ -0,0 +1,56 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + PeCoffLoaderEx.c + +Abstract: + + IA-32 Specific relocation fixups + +Revision History + +--*/ + +#include "TianoCommon.h" + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IA-32 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - Unsupported now + +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/ia32/PeCoffLoaderEx.h b/Tools/Source/TianoTools/Common/PeiLib/ia32/PeCoffLoaderEx.h new file mode 100644 index 0000000000..e0f1e22598 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/ia32/PeCoffLoaderEx.h @@ -0,0 +1,65 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + PeCoffLoaderEx.h + +Abstract: + + IA-32 Specific relocation fixups + +Revision History + +--*/ + +#ifndef _PE_COFF_LOADER_EX_H_ +#define _PE_COFF_LOADER_EX_H_ + +// +// Define macro to determine if the machine type is supported. +// Returns 0 if the machine is not supported, Not 0 otherwise. +// +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + ((Machine) == EFI_IMAGE_MACHINE_IA32 || \ + (Machine) == EFI_IMAGE_MACHINE_EBC) + +EFI_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IA-32 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - Unsupported now + +--*/ +; + +#endif diff --git a/Tools/Source/TianoTools/Common/PeiLib/ia32/PerformancePrimitives.c b/Tools/Source/TianoTools/Common/PeiLib/ia32/PerformancePrimitives.c new file mode 100644 index 0000000000..4efec656ae --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/ia32/PerformancePrimitives.c @@ -0,0 +1,47 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + PerformancePrimitives.c + +Abstract: + + Support for Performance library + +--*/ + +#include "TianoCommon.h" +#include "CpuIA32.h" + +EFI_STATUS +GetTimerValue ( + OUT UINT64 *TimerValue + ) +/*++ + +Routine Description: + + Get timer value. + +Arguments: + + TimerValue - Pointer to the returned timer value + +Returns: + + EFI_SUCCESS - Successfully got timer value + +--*/ +{ + *TimerValue = EfiReadTsc (); + return EFI_SUCCESS; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/ia32/Processor.c b/Tools/Source/TianoTools/Common/PeiLib/ia32/Processor.c new file mode 100644 index 0000000000..4010db25a2 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/ia32/Processor.c @@ -0,0 +1,140 @@ +/*++ + +Copyright (c) 2004 - 2005, 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. + +Module Name: + + Processor.c + +Abstract: + +--*/ + +#include "Tiano.h" +#include "EfiJump.h" +#include EFI_GUID_DEFINITION (PeiFlushInstructionCache) +#include EFI_GUID_DEFINITION (PeiTransferControl) + +// +// Prototypes +// +EFI_STATUS +EFIAPI +TransferControlSetJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ); + +EFI_STATUS +EFIAPI +TransferControlLongJump ( + IN EFI_PEI_TRANSFER_CONTROL_PROTOCOL *This, + IN EFI_JUMP_BUFFER *Jump + ); + +EFI_STATUS +EFIAPI +FlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ); + +// +// Table declarations +// +EFI_PEI_TRANSFER_CONTROL_PROTOCOL mTransferControl = { + TransferControlSetJump, + TransferControlLongJump, + sizeof (EFI_JUMP_BUFFER) +}; + +EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL mFlushInstructionCache = { + FlushInstructionCacheFlush +}; + + +EFI_STATUS +InstallEfiPeiTransferControl ( + IN OUT EFI_PEI_TRANSFER_CONTROL_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the transfer control mechanism + +Arguments: + + This - Pointer to transfer control mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed. + +--*/ +{ + *This = &mTransferControl; + return EFI_SUCCESS; +} + +EFI_STATUS +InstallEfiPeiFlushInstructionCache ( + IN OUT EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL **This + ) +/*++ + +Routine Description: + + Installs the pointer to the flush instruction cache mechanism + +Arguments: + + This - Pointer to flush instruction cache mechanism. + +Returns: + + EFI_SUCCESS - Successfully installed + +--*/ +{ + *This = &mFlushInstructionCache; + return EFI_SUCCESS; +} + +EFI_STATUS +EFIAPI +FlushInstructionCacheFlush ( + IN EFI_PEI_FLUSH_INSTRUCTION_CACHE_PROTOCOL *This, + IN EFI_PHYSICAL_ADDRESS Start, + IN UINT64 Length + ) +/*++ + +Routine Description: + + This routine would provide support for flushing the CPU instruction cache. + In the case of IA32, this flushing is not necessary and is thus not implemented. + +Arguments: + + This - Pointer to CPU Architectural Protocol interface + Start - Start adddress in memory to flush + Length - Length of memory to flush + +Returns: + + Status + EFI_SUCCESS + +--*/ +{ + return EFI_SUCCESS; +} diff --git a/Tools/Source/TianoTools/Common/PeiLib/ia32/ProcessorAsms.Asm b/Tools/Source/TianoTools/Common/PeiLib/ia32/ProcessorAsms.Asm new file mode 100644 index 0000000000..bf0d5cbed7 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/ia32/ProcessorAsms.Asm @@ -0,0 +1,223 @@ +; +; Copyright (c) 2004, 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. +; +; Module Name: +; +; ProcessorAsms.Asm +; +; Abstract: +; This is separated from processor.c to allow this functions to be built with /O1 +; +; Notes: +; - Masm uses "This", "ebx", etc as a directive. +; - H2INC is still not embedded in our build process so I translated the struc manually. +; - Unreferenced variables/arguments (This, NewBsp, NewStack) were causing compile errors and +; did not know of "pragma" mechanism in MASM and I did not want to reduce the warning level. +; Instead, I did a dummy referenced. +; + + .686P + .MMX + .MODEL SMALL + .CODE + +EFI_SUCCESS equ 0 +EFI_WARN_RETURN_FROM_LONG_JUMP equ 5 + +; +; Generated by h2inc run manually +; +_EFI_JUMP_BUFFER STRUCT 2t +_ebx DWORD ? +_esi DWORD ? +_edi DWORD ? +_ebp DWORD ? +_esp DWORD ? +_eip DWORD ? +_EFI_JUMP_BUFFER ENDS + +EFI_JUMP_BUFFER TYPEDEF _EFI_JUMP_BUFFER + +TransferControlSetJump PROTO C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + +TransferControlLongJump PROTO C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + +SwitchStacks PROTO C \ + EntryPoint:PTR DWORD, \ + Parameter:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + +SwitchIplStacks PROTO C \ + EntryPoint:PTR DWORD, \ + Parameter1:DWORD, \ + Parameter2:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + +; +;Routine Description: +; +; This routine implements the IA32 variant of the SetJump call. Its +; responsibility is to store system state information for a possible +; subsequent LongJump. +; +;Arguments: +; +; Pointer to CPU context save buffer. +; +;Returns: +; +; EFI_SUCCESS +; +TransferControlSetJump PROC C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + + mov eax, _This + mov ecx, Jump + mov (EFI_JUMP_BUFFER PTR [ecx])._ebx, ebx + mov (EFI_JUMP_BUFFER PTR [ecx])._esi, esi + mov (EFI_JUMP_BUFFER PTR [ecx])._edi, edi + mov eax, [ebp] + mov (EFI_JUMP_BUFFER PTR [ecx])._ebp, eax + lea eax, [ebp+4] + mov (EFI_JUMP_BUFFER PTR [ecx])._esp, eax + mov eax, [ebp+4] + mov (EFI_JUMP_BUFFER PTR [ecx])._eip, eax + mov eax, EFI_SUCCESS + + ret + +TransferControlSetJump ENDP + +; +; Routine Description: +; +; This routine implements the IA32 variant of the LongJump call. Its +; responsibility is restore the system state to the Context Buffer and +; pass control back. +; +; Arguments: +; +; Pointer to CPU context save buffer. +; +; Returns: +; +; EFI_WARN_RETURN_FROM_LONG_JUMP +; + +TransferControlLongJump PROC C \ + _This:PTR EFI_PEI_TRANSFER_CONTROL_PROTOCOL, \ + Jump:PTR EFI_JUMP_BUFFER + + push ebx + push esi + push edi + + mov eax, _This + ; set return from SetJump to EFI_WARN_RETURN_FROM_LONG_JUMP + mov eax, EFI_WARN_RETURN_FROM_LONG_JUMP + mov ecx, Jump + mov ebx, (EFI_JUMP_BUFFER PTR [ecx])._ebx + mov esi, (EFI_JUMP_BUFFER PTR [ecx])._esi + mov edi, (EFI_JUMP_BUFFER PTR [ecx])._edi + mov ebp, (EFI_JUMP_BUFFER PTR [ecx])._ebp + mov esp, (EFI_JUMP_BUFFER PTR [ecx])._esp + add esp, 4 ;pop the eip + jmp DWORD PTR (EFI_JUMP_BUFFER PTR [ecx])._eip + mov eax, EFI_WARN_RETURN_FROM_LONG_JUMP + + pop edi + pop esi + pop ebx + ret + +TransferControlLongJump ENDP + +; +; Routine Description: +; This allows the caller to switch the stack and goes to the new entry point +; +; Arguments: +; EntryPoint - Pointer to the location to enter +; Parameter - Parameter to pass in +; NewStack - New Location of the stack +; NewBsp - New BSP +; +; Returns: +; +; Nothing. Goes to the Entry Point passing in the new parameters +; +SwitchStacks PROC C \ + EntryPoint:PTR DWORD, \ + Parameter:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + + push ebx + mov eax, NewBsp + mov ebx, Parameter + mov ecx, EntryPoint + mov eax, NewStack + mov esp, eax + push ebx + push 0 + jmp ecx + + pop ebx + ret + +SwitchStacks ENDP + +; +; Routine Description: +; This allows the caller to switch the stack and goes to the new entry point +; +; Arguments: +; EntryPoint - Pointer to the location to enter +; Parameter1/Parameter2 - Parameter to pass in +; NewStack - New Location of the stack +; NewBsp - New BSP +; +; Returns: +; +; Nothing. Goes to the Entry Point passing in the new parameters +; +SwitchIplStacks PROC C \ + EntryPoint:PTR DWORD, \ + Parameter1:DWORD, \ + Parameter2:DWORD, \ + NewStack:PTR DWORD, \ + NewBsp:PTR DWORD + + push ebx + mov eax, NewBsp + mov ebx, Parameter1 + mov edx, Parameter2 + mov ecx, EntryPoint + mov eax, NewStack + mov esp, eax + + push edx + push ebx + call ecx + + pop ebx + ret + +SwitchIplStacks ENDP + + END + diff --git a/Tools/Source/TianoTools/Common/PeiLib/ia32/efijump.h b/Tools/Source/TianoTools/Common/PeiLib/ia32/efijump.h new file mode 100644 index 0000000000..cdd7ca8c84 --- /dev/null +++ b/Tools/Source/TianoTools/Common/PeiLib/ia32/efijump.h @@ -0,0 +1,34 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + EfiJump.h + +Abstract: + + This is the Setjump/Longjump pair for an IA32 processor. + +--*/ + +#ifndef _EFI_JUMP_H_ +#define _EFI_JUMP_H_ + +typedef struct { + UINT32 ebx; + UINT32 esi; + UINT32 edi; + UINT32 ebp; + UINT32 esp; + UINT32 eip; +} EFI_JUMP_BUFFER; + +#endif diff --git a/Tools/Source/TianoTools/Common/SimpleFileParsing.c b/Tools/Source/TianoTools/Common/SimpleFileParsing.c new file mode 100644 index 0000000000..3ee3349d1a --- /dev/null +++ b/Tools/Source/TianoTools/Common/SimpleFileParsing.c @@ -0,0 +1,1460 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + SimpleFileParsing.c + +Abstract: + + Generic but simple file parsing routines. + +--*/ + +#include +#include +#include +#include + +/* +#include "Tiano.h" +*/ +#include "EfiUtilityMsgs.h" +#include "SimpleFileParsing.h" + +#ifndef MAX_PATH +#define MAX_PATH 255 +#endif +// +// just in case we get in an endless loop. +// +#define MAX_NEST_DEPTH 20 +// +// number of wchars +// +#define MAX_STRING_IDENTIFIER_NAME 100 + +#define MAX_LINE_LEN 400 + +#define T_CHAR_SPACE ' ' +#define T_CHAR_NULL 0 +#define T_CHAR_CR '\r' +#define T_CHAR_TAB '\t' +#define T_CHAR_LF '\n' +#define T_CHAR_SLASH '/' +#define T_CHAR_BACKSLASH '\\' +#define T_CHAR_DOUBLE_QUOTE '"' +#define T_CHAR_LC_X 'x' +#define T_CHAR_0 '0' +#define T_CHAR_STAR '*' + +// +// We keep a linked list of these for the source files we process +// +typedef struct _SOURCE_FILE { + FILE *Fptr; + T_CHAR *FileBuffer; + T_CHAR *FileBufferPtr; + unsigned int FileSize; + char FileName[MAX_PATH]; + unsigned int LineNum; + BOOLEAN EndOfFile; + BOOLEAN SkipToHash; + struct _SOURCE_FILE *Previous; + struct _SOURCE_FILE *Next; + T_CHAR ControlCharacter; +} SOURCE_FILE; + +typedef struct { + T_CHAR *FileBufferPtr; +} FILE_POSITION; + +// +// Keep all our module globals in this structure +// +static struct { + SOURCE_FILE SourceFile; + BOOLEAN VerboseFile; + BOOLEAN VerboseToken; +} mGlobals; + +static +unsigned int +t_strcmp ( + T_CHAR *Buffer, + T_CHAR *Str + ); + +static +unsigned int +t_strncmp ( + T_CHAR *Str1, + T_CHAR *Str2, + int Len + ); + +static +unsigned int +t_strlen ( + T_CHAR *Str + ); + +static +void +RewindFile ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +unsigned int +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ); + +static +void +PreprocessFile ( + SOURCE_FILE *SourceFile + ); + +static +T_CHAR * +t_strcpy ( + T_CHAR *Dest, + T_CHAR *Src + ); + +static +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ); + +static +STATUS +ParseFile ( + SOURCE_FILE *SourceFile + ); + +static +FILE * +FindFile ( + char *FileName, + char *FoundFileName, + unsigned int FoundFileNameLen + ); + +static +STATUS +ProcessFile ( + SOURCE_FILE *SourceFile + ); + +static +STATUS +GetFilePosition ( + FILE_POSITION *Fpos + ); + +static +STATUS +SetFilePosition ( + FILE_POSITION *Fpos + ); + +STATUS +SFPInit ( + VOID + ) +/*++ + +Routine Description: + +Arguments: + None. + +Returns: + STATUS_SUCCESS always + +--*/ +{ + memset ((void *) &mGlobals, 0, sizeof (mGlobals)); + return STATUS_SUCCESS; +} + +unsigned +int +SFPGetLineNumber ( + VOID + ) +/*++ + +Routine Description: + Return the line number of the file we're parsing. Used + for error reporting purposes. + +Arguments: + None. + +Returns: + The line number, or 0 if no file is being processed + +--*/ +{ + return mGlobals.SourceFile.LineNum; +} + +T_CHAR * +SFPGetFileName ( + VOID + ) +/*++ + +Routine Description: + Return the name of the file we're parsing. Used + for error reporting purposes. + +Arguments: + None. + +Returns: + A pointer to the file name. Null if no file is being + processed. + +--*/ +{ + if (mGlobals.SourceFile.FileName[0]) { + return mGlobals.SourceFile.FileName; + } + + return NULL; +} + +STATUS +SFPOpenFile ( + char *FileName + ) +/*++ + +Routine Description: + Open a file for parsing. + +Arguments: + FileName - name of the file to parse + +Returns: + + +--*/ +{ + STATUS Status; + t_strcpy (mGlobals.SourceFile.FileName, FileName); + Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL); + return Status; +} + +BOOLEAN +SFPIsToken ( + T_CHAR *Str + ) +/*++ + +Routine Description: + Check to see if the specified token is found at + the current position in the input file. + +Arguments: + Str - the token to look for + +Returns: + TRUE - the token is next + FALSE - the token is not next + +Notes: + We do a simple string comparison on this function. It is + the responsibility of the caller to ensure that the token + is not a subset of some other token. + + The file pointer is advanced past the token in the input file. + +--*/ +{ + unsigned int Len; + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) { + mGlobals.SourceFile.FileBufferPtr += Len; + if (mGlobals.VerboseToken) { + printf ("Token: '%s'\n", Str); + } + + return TRUE; + } + + return FALSE; +} + +BOOLEAN +SFPIsKeyword ( + T_CHAR *Str + ) +/*++ + +Routine Description: + Check to see if the specified keyword is found at + the current position in the input file. + +Arguments: + Str - keyword to look for + +Returns: + TRUE - the keyword is next + FALSE - the keyword is not next + +Notes: + A keyword is defined as a "special" string that has a non-alphanumeric + character following it. + +--*/ +{ + unsigned int Len; + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) { + if (isalnum (mGlobals.SourceFile.FileBufferPtr[Len])) { + return FALSE; + } + + mGlobals.SourceFile.FileBufferPtr += Len; + if (mGlobals.VerboseToken) { + printf ("Token: '%s'\n", Str); + } + + return TRUE; + } + + return FALSE; +} + +BOOLEAN +SFPGetNextToken ( + T_CHAR *Str, + unsigned int Len + ) +/*++ + +Routine Description: + Get the next token from the input stream. + +Arguments: + Str - pointer to a copy of the next token + Len - size of buffer pointed to by Str + +Returns: + TRUE - next token successfully returned + FALSE - otherwise + +Notes: + Preceeding white space is ignored. + The parser's buffer pointer is advanced past the end of the + token. + +--*/ +{ + unsigned int Index; + T_CHAR TempChar; + + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + // + // Have to have enough string for at least one char and a null-terminator + // + if (Len < 2) { + return FALSE; + } + // + // Look at the first character. If it's an identifier, then treat it + // as such + // + TempChar = mGlobals.SourceFile.FileBufferPtr[0]; + if (((TempChar >= 'a') && (TempChar <= 'z')) || ((TempChar >= 'A') && (TempChar <= 'Z')) || (TempChar == '_')) { + Str[0] = TempChar; + mGlobals.SourceFile.FileBufferPtr++; + Index = 1; + while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) { + TempChar = mGlobals.SourceFile.FileBufferPtr[0]; + if (((TempChar >= 'a') && (TempChar <= 'z')) || + ((TempChar >= 'A') && (TempChar <= 'Z')) || + ((TempChar >= '0') && (TempChar <= '9')) || + (TempChar == '_') + ) { + Str[Index] = mGlobals.SourceFile.FileBufferPtr[0]; + mGlobals.SourceFile.FileBufferPtr++; + Index++; + } else { + // + // Invalid character for symbol name, so break out + // + break; + } + } + // + // Null terminate and return success + // + Str[Index] = 0; + return TRUE; + } else if ((TempChar == ')') || (TempChar == '(') || (TempChar == '*')) { + Str[0] = mGlobals.SourceFile.FileBufferPtr[0]; + mGlobals.SourceFile.FileBufferPtr++; + Str[1] = 0; + return TRUE; + } else { + // + // Everything else is white-space (or EOF) separated + // + Index = 0; + while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) { + if (IsWhiteSpace (&mGlobals.SourceFile)) { + if (Index > 0) { + Str[Index] = 0; + return TRUE; + } + + return FALSE; + } else { + Str[Index] = mGlobals.SourceFile.FileBufferPtr[0]; + mGlobals.SourceFile.FileBufferPtr++; + Index++; + } + } + // + // See if we just ran out of file contents, but did find a token + // + if ((Index > 0) && EndOfFile (&mGlobals.SourceFile)) { + Str[Index] = 0; + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN +SFPGetGuidToken ( + T_CHAR *Str, + UINT32 Len + ) +/*++ + +Routine Description: + Parse a GUID from the input stream. Stop when you discover white space. + +Arguments: + Str - pointer to a copy of the next token + Len - size of buffer pointed to by Str + +Returns: + TRUE - GUID string returned successfully + FALSE - otherwise + +--*/ +{ + UINT32 Index; + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + Index = 0; + while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) { + if (IsWhiteSpace (&mGlobals.SourceFile)) { + if (Index > 0) { + Str[Index] = 0; + return TRUE; + } + + return FALSE; + } else { + Str[Index] = mGlobals.SourceFile.FileBufferPtr[0]; + mGlobals.SourceFile.FileBufferPtr++; + Index++; + } + } + + return FALSE; +} + +BOOLEAN +SFPSkipToToken ( + T_CHAR *Str + ) +{ + unsigned int Len; + T_CHAR *SavePos; + Len = t_strlen (Str); + SavePos = mGlobals.SourceFile.FileBufferPtr; + SkipWhiteSpace (&mGlobals.SourceFile); + while (!EndOfFile (&mGlobals.SourceFile)) { + if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) { + mGlobals.SourceFile.FileBufferPtr += Len; + return TRUE; + } + + mGlobals.SourceFile.FileBufferPtr++; + SkipWhiteSpace (&mGlobals.SourceFile); + } + + mGlobals.SourceFile.FileBufferPtr = SavePos; + return FALSE; +} + +BOOLEAN +SFPGetNumber ( + unsigned int *Value + ) +/*++ + +Routine Description: + Check the token at the current file position for a numeric value. + May be either decimal or hex. + +Arguments: + Value - pointer where to store the value + +Returns: + FALSE - current token is not a number + TRUE - current token is a number + +--*/ +{ + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) { + // + // Check for hex value + // + if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) { + if (!isxdigit (mGlobals.SourceFile.FileBufferPtr[2])) { + return FALSE; + } + + mGlobals.SourceFile.FileBufferPtr += 2; + sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value); + while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) { + mGlobals.SourceFile.FileBufferPtr++; + } + + return TRUE; + } else { + *Value = atoi (mGlobals.SourceFile.FileBufferPtr); + while (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) { + mGlobals.SourceFile.FileBufferPtr++; + } + + return TRUE; + } + } else { + return FALSE; + } +} + +STATUS +SFPCloseFile ( + VOID + ) +/*++ + +Routine Description: + Close the file being parsed. + +Arguments: + None. + +Returns: + STATUS_SUCCESS - the file was closed + STATUS_ERROR - no file is currently open + +--*/ +{ + if (mGlobals.SourceFile.FileBuffer != NULL) { + free (mGlobals.SourceFile.FileBuffer); + memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile)); + return STATUS_SUCCESS; + } + + return STATUS_ERROR; +} + +static +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ) +/*++ + +Routine Description: + + Given a source file, open the file and parse it + +Arguments: + + SourceFile - name of file to parse + ParentSourceFile - for error reporting purposes, the file that #included SourceFile. + +Returns: + + Standard status. + +--*/ +{ + static unsigned int NestDepth = 0; + char FoundFileName[MAX_PATH]; + STATUS Status; + + Status = STATUS_SUCCESS; + NestDepth++; + // + // Print the file being processed. Indent so you can tell the include nesting + // depth. + // + if (mGlobals.VerboseFile) { + fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName); + fprintf (stdout, "Parent source file = '%s'\n", ParentSourceFile); + } + + // + // Make sure we didn't exceed our maximum nesting depth + // + if (NestDepth > MAX_NEST_DEPTH) { + Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth); + Status = STATUS_ERROR; + goto Finish; + } + // + // Try to open the file locally, and if that fails try along our include paths. + // + strcpy (FoundFileName, SourceFile->FileName); + if ((SourceFile->Fptr = fopen (FoundFileName, "rb")) == NULL) { + return STATUS_ERROR; + } + // + // Process the file found + // + ProcessFile (SourceFile); +Finish: + // + // Close open files and return status + // + if (SourceFile->Fptr != NULL) { + fclose (SourceFile->Fptr); + SourceFile->Fptr = NULL; + } + + return Status; +} + +static +STATUS +ProcessFile ( + SOURCE_FILE *SourceFile + ) +/*++ + +Routine Description: + + Given a source file that's been opened, read the contents into an internal + buffer and pre-process it to remove comments. + +Arguments: + + SourceFile - structure containing info on the file to process + +Returns: + + Standard status. + +--*/ +{ + // + // Get the file size, and then read the entire thing into memory. + // Allocate extra space for a terminator character. + // + fseek (SourceFile->Fptr, 0, SEEK_END); + SourceFile->FileSize = ftell (SourceFile->Fptr); + if (mGlobals.VerboseFile) { + printf ("FileSize = %d (0x%X)\n", SourceFile->FileSize, SourceFile->FileSize); + } + + fseek (SourceFile->Fptr, 0, SEEK_SET); + SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR)); + if (SourceFile->FileBuffer == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + fread ((void *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr); + SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = T_CHAR_NULL; + // + // Pre-process the file to replace comments with spaces + // + PreprocessFile (SourceFile); + SourceFile->LineNum = 1; + return STATUS_SUCCESS; +} + +static +void +PreprocessFile ( + SOURCE_FILE *SourceFile + ) +/*++ + +Routine Description: + Preprocess a file to replace all carriage returns with NULLs so + we can print lines (as part of error messages) from the file to the screen. + +Arguments: + SourceFile - structure that we use to keep track of an input file. + +Returns: + Nothing. + +--*/ +{ + BOOLEAN InComment; + BOOLEAN SlashSlashComment; + int LineNum; + + RewindFile (SourceFile); + InComment = FALSE; + SlashSlashComment = FALSE; + while (!EndOfFile (SourceFile)) { + // + // If a line-feed, then no longer in a comment if we're in a // comment + // + if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) { + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + if (InComment && SlashSlashComment) { + InComment = FALSE; + SlashSlashComment = FALSE; + } + } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) { + // + // Replace all carriage returns with a NULL so we can print stuff + // + SourceFile->FileBufferPtr[0] = 0; + SourceFile->FileBufferPtr++; + // + // Check for */ comment end + // + } else if (InComment && + !SlashSlashComment && + (SourceFile->FileBufferPtr[0] == T_CHAR_STAR) && + (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH) + ) { + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + InComment = FALSE; + } else if (InComment) { + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + // + // Check for // comments + // + } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) { + InComment = TRUE; + SlashSlashComment = TRUE; + // + // Check for /* comment start + // + } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_STAR)) { + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + SlashSlashComment = FALSE; + InComment = TRUE; + } else { + SourceFile->FileBufferPtr++; + } + } + // + // Could check for end-of-file and still in a comment, but + // should not be necessary. So just restore the file pointers. + // + RewindFile (SourceFile); + // + // Dump the reformatted file if verbose mode + // + if (mGlobals.VerboseFile) { + LineNum = 1; + printf ("%04d: ", LineNum); + while (!EndOfFile (SourceFile)) { + if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) { + printf ("'\n%04d: '", ++LineNum); + } else { + printf ("%c", SourceFile->FileBufferPtr[0]); + } + + SourceFile->FileBufferPtr++; + } + + printf ("'\n"); + printf ("FileSize = %d (0x%X)\n", SourceFile->FileSize, SourceFile->FileSize); + RewindFile (SourceFile); + } +} + +BOOLEAN +SFPGetQuotedString ( + T_CHAR *Str, + int Length + ) +/*++ + +Routine Description: + Retrieve a quoted-string from the input file. + +Arguments: + Str - pointer to a copy of the quoted string parsed + Length - size of buffer pointed to by Str + +Returns: + TRUE - next token in input stream was a quoted string, and + the string value was returned in Str + FALSE - otherwise + +--*/ +{ + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) { + mGlobals.SourceFile.FileBufferPtr++; + while (Length > 0) { + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + // + // Check for closing quote + // + if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) { + mGlobals.SourceFile.FileBufferPtr++; + *Str = 0; + return TRUE; + } + + *Str = mGlobals.SourceFile.FileBufferPtr[0]; + Str++; + Length--; + mGlobals.SourceFile.FileBufferPtr++; + } + } + // + // First character was not a quote, or the input string length was + // insufficient to contain the quoted string, so return failure code. + // + return FALSE; +} + +BOOLEAN +SFPIsEOF ( + VOID + ) +/*++ + +Routine Description: + Return TRUE of FALSE to indicate whether or not we've reached the end of the + file we're parsing. + +Arguments: + NA + +Returns: + TRUE - EOF reached + FALSE - otherwise + +--*/ +{ + SkipWhiteSpace (&mGlobals.SourceFile); + return EndOfFile (&mGlobals.SourceFile); +} + +#if 0 +static +T_CHAR * +GetQuotedString ( + SOURCE_FILE *SourceFile, + BOOLEAN Optional + ) +{ + T_CHAR *String; + T_CHAR *Start; + T_CHAR *Ptr; + unsigned int Len; + BOOLEAN PreviousBackslash; + + if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) { + if (Optional == FALSE) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr); + } + + return NULL; + } + + Len = 0; + SourceFile->FileBufferPtr++; + Start = Ptr = SourceFile->FileBufferPtr; + PreviousBackslash = FALSE; + while (!EndOfFile (SourceFile)) { + if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (PreviousBackslash == FALSE)) { + break; + } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start); + PreviousBackslash = FALSE; + } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) { + PreviousBackslash = TRUE; + } else { + PreviousBackslash = FALSE; + } + + SourceFile->FileBufferPtr++; + Len++; + } + + if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start); + } else { + SourceFile->FileBufferPtr++; + } + // + // Now allocate memory for the string and save it off + // + String = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR)); + if (String == NULL) { + Error (NULL, 0, 0, "memory allocation failed", NULL); + return NULL; + } + // + // Copy the string from the file buffer to the local copy. + // We do no reformatting of it whatsoever at this point. + // + Ptr = String; + while (Len > 0) { + *Ptr = *Start; + Start++; + Ptr++; + Len--; + } + + *Ptr = 0; + return String; +} +#endif +static +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ) +{ + // + // The file buffer pointer will typically get updated before the End-of-file flag in the + // source file structure, so check it first. + // + if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (T_CHAR)) { + SourceFile->EndOfFile = TRUE; + return TRUE; + } + + if (SourceFile->EndOfFile) { + return TRUE; + } + + return FALSE; +} + +#if 0 +static +void +ProcessTokenInclude ( + SOURCE_FILE *SourceFile + ) +{ + char IncludeFileName[MAX_PATH]; + char *To; + unsigned int Len; + BOOLEAN ReportedError; + SOURCE_FILE IncludedSourceFile; + + ReportedError = FALSE; + if (SkipWhiteSpace (SourceFile) == 0) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL); + } + // + // Should be quoted file name + // + if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL); + goto FailDone; + } + + SourceFile->FileBufferPtr++; + // + // Copy the filename as ascii to our local string + // + To = IncludeFileName; + Len = 0; + while (!EndOfFile (SourceFile)) { + if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL); + goto FailDone; + } + + if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) { + SourceFile->FileBufferPtr++; + break; + } + // + // If too long, then report the error once and process until the closing quote + // + Len++; + if (!ReportedError && (Len >= sizeof (IncludeFileName))) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL); + ReportedError = TRUE; + } + + if (!ReportedError) { + *To = (T_CHAR) SourceFile->FileBufferPtr[0]; + To++; + } + + SourceFile->FileBufferPtr++; + } + + if (!ReportedError) { + *To = 0; + memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE)); + strcpy (IncludedSourceFile.FileName, IncludeFileName); + ProcessIncludeFile (&IncludedSourceFile, SourceFile); + } + + return ; +FailDone: + // + // Error recovery -- skip to next # + // + SourceFile->SkipToHash = TRUE; +} +#endif +static +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + switch (*SourceFile->FileBufferPtr) { + case T_CHAR_NULL: + case T_CHAR_CR: + case T_CHAR_SPACE: + case T_CHAR_TAB: + case T_CHAR_LF: + return TRUE; + + default: + return FALSE; + } +} + +unsigned int +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + unsigned int Count; + + Count = 0; + while (!EndOfFile (SourceFile)) { + Count++; + switch (*SourceFile->FileBufferPtr) { + case T_CHAR_NULL: + case T_CHAR_CR: + case T_CHAR_SPACE: + case T_CHAR_TAB: + SourceFile->FileBufferPtr++; + break; + + case T_CHAR_LF: + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + break; + + default: + return Count - 1; + } + } + // + // Some tokens require trailing whitespace. If we're at the end of the + // file, then we count that as well. + // + if ((Count == 0) && (EndOfFile (SourceFile))) { + Count++; + } + + return Count; +} + +static +unsigned int +t_strcmp ( + T_CHAR *Buffer, + T_CHAR *Str + ) +/*++ + +Routine Description: + Compare two strings for equality. The string pointed to by 'Buffer' may or may not be null-terminated, + so only compare up to the length of Str. + +Arguments: + Buffer - pointer to first (possibly not null-terminated) string + Str - pointer to null-terminated string to compare to Buffer + +Returns: + Number of bytes matched if exact match + 0 if Buffer does not start with Str + +--*/ +{ + unsigned int Len; + + Len = 0; + while (*Str && (*Str == *Buffer)) { + Buffer++; + Str++; + Len++; + } + + if (*Str) { + return 0; + } + + return Len; +} + +static +unsigned int +t_strlen ( + T_CHAR *Str + ) +{ + unsigned int Len; + Len = 0; + while (*Str) { + Len++; + Str++; + } + + return Len; +} + +static +unsigned int +t_strncmp ( + T_CHAR *Str1, + T_CHAR *Str2, + int Len + ) +{ + while (Len > 0) { + if (*Str1 != *Str2) { + return Len; + } + + Len--; + Str1++; + Str2++; + } + + return 0; +} + +static +T_CHAR * +t_strcpy ( + T_CHAR *Dest, + T_CHAR *Src + ) +{ + T_CHAR *SaveDest; + SaveDest = Dest; + while (*Src) { + *Dest = *Src; + Dest++; + Src++; + } + + *Dest = 0; + return SaveDest; +} + +static +void +RewindFile ( + SOURCE_FILE *SourceFile + ) +{ + SourceFile->LineNum = 1; + SourceFile->FileBufferPtr = SourceFile->FileBuffer; + SourceFile->EndOfFile = 0; +} + +static +UINT32 +GetHexChars ( + T_CHAR *Buffer, + UINT32 BufferLen + ) +{ + UINT32 Len; + Len = 0; + while (!EndOfFile (&mGlobals.SourceFile) && (BufferLen > 0)) { + if (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) { + *Buffer = mGlobals.SourceFile.FileBufferPtr[0]; + Buffer++; + Len++; + BufferLen--; + mGlobals.SourceFile.FileBufferPtr++; + } else { + break; + } + } + // + // Null terminate if we can + // + if ((Len > 0) && (BufferLen > 0)) { + *Buffer = 0; + } + + return Len; +} + +BOOLEAN +SFPGetGuid ( + int GuidStyle, + EFI_GUID *Value + ) +/*++ + +Routine Description: + Parse a GUID from the input stream. Stop when you discover white space. + +Arguments: + GuidStyle - Style of the following GUID token + Value - pointer to EFI_GUID struct for output + +Returns: + TRUE - GUID string parsed successfully + FALSE - otherwise + + GUID styles + Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD + +--*/ +{ + UINT32 Value32; + UINT32 Index; + FILE_POSITION FPos; + T_CHAR TempString[20]; + T_CHAR TempString2[3]; + T_CHAR *From; + T_CHAR *To; + UINT32 Len; + BOOLEAN Status; + + Status = FALSE; + // + // Skip white space, then start parsing + // + SkipWhiteSpace (&mGlobals.SourceFile); + GetFilePosition (&FPos); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if (GuidStyle == PARSE_GUID_STYLE_5_FIELDS) { + // + // Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD + // + Len = GetHexChars (TempString, sizeof (TempString)); + if ((Len == 0) || (Len > 8)) { + goto Done; + } + + sscanf (TempString, "%x", &Value32); + Value->Data1 = Value32; + // + // Next two UINT16 fields + // + if (mGlobals.SourceFile.FileBufferPtr[0] != '-') { + goto Done; + } + + mGlobals.SourceFile.FileBufferPtr++; + Len = GetHexChars (TempString, sizeof (TempString)); + if ((Len == 0) || (Len > 4)) { + goto Done; + } + + sscanf (TempString, "%x", &Value32); + Value->Data2 = (UINT16) Value32; + + if (mGlobals.SourceFile.FileBufferPtr[0] != '-') { + goto Done; + } + + mGlobals.SourceFile.FileBufferPtr++; + Len = GetHexChars (TempString, sizeof (TempString)); + if ((Len == 0) || (Len > 4)) { + goto Done; + } + + sscanf (TempString, "%x", &Value32); + Value->Data3 = (UINT16) Value32; + // + // Parse the "AAAA" as two bytes + // + if (mGlobals.SourceFile.FileBufferPtr[0] != '-') { + goto Done; + } + + mGlobals.SourceFile.FileBufferPtr++; + Len = GetHexChars (TempString, sizeof (TempString)); + if ((Len == 0) || (Len > 4)) { + goto Done; + } + + sscanf (TempString, "%x", &Value32); + Value->Data4[0] = (UINT8) (Value32 >> 8); + Value->Data4[1] = (UINT8) Value32; + if (mGlobals.SourceFile.FileBufferPtr[0] != '-') { + goto Done; + } + + mGlobals.SourceFile.FileBufferPtr++; + // + // Read the last 6 bytes of the GUID + // + // + Len = GetHexChars (TempString, sizeof (TempString)); + if ((Len == 0) || (Len > 12)) { + goto Done; + } + // + // Insert leading 0's to make life easier + // + if (Len != 12) { + From = TempString + Len - 1; + To = TempString + 11; + TempString[12] = 0; + while (From >= TempString) { + *To = *From; + To--; + From--; + } + + while (To >= TempString) { + *To = '0'; + To--; + } + } + // + // Now parse each byte + // + TempString2[2] = 0; + for (Index = 0; Index < 6; Index++) { + // + // Copy the two characters from the input string to something + // we can parse. + // + TempString2[0] = TempString[Index * 2]; + TempString2[1] = TempString[Index * 2 + 1]; + sscanf (TempString2, "%x", &Value32); + Value->Data4[Index + 2] = (UINT8) Value32; + } + + Status = TRUE; + } else { + // + // Unsupported GUID style + // + return FALSE; + } + +Done: + if (Status == FALSE) { + SetFilePosition (&FPos); + } + + return Status; +} + +static +STATUS +GetFilePosition ( + FILE_POSITION *Fpos + ) +{ + Fpos->FileBufferPtr = mGlobals.SourceFile.FileBufferPtr; + return STATUS_SUCCESS; +} + +static +STATUS +SetFilePosition ( + FILE_POSITION *Fpos + ) +{ + // + // Should check range of pointer + // + mGlobals.SourceFile.FileBufferPtr = Fpos->FileBufferPtr; + return STATUS_SUCCESS; +} diff --git a/Tools/Source/TianoTools/Common/SimpleFileParsing.h b/Tools/Source/TianoTools/Common/SimpleFileParsing.h new file mode 100644 index 0000000000..ea1f5a0adc --- /dev/null +++ b/Tools/Source/TianoTools/Common/SimpleFileParsing.h @@ -0,0 +1,121 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + SimpleFileParsing.h + +Abstract: + + Function prototypes and defines for the simple file parsing routines. + +--*/ + +#include +#include + +#ifndef _SIMPLE_FILE_PARSING_H_ +#define _SIMPLE_FILE_PARSING_H_ + +#define T_CHAR char + +STATUS +SFPInit ( + VOID + ) +; + +STATUS +SFPOpenFile ( + char *FileName + ) +; + +BOOLEAN +SFPIsKeyword ( + T_CHAR *Str + ) +; + +BOOLEAN +SFPIsToken ( + T_CHAR *Str + ) +; + +BOOLEAN +SFPGetNextToken ( + T_CHAR *Str, + unsigned int Len + ) +; + +BOOLEAN +SFPGetGuidToken ( + T_CHAR *Str, + UINT32 Len + ) +; + +#define PARSE_GUID_STYLE_5_FIELDS 0 + +BOOLEAN +SFPGetGuid ( + int GuidStyle, + EFI_GUID *Value + ) +; + +BOOLEAN +SFPSkipToToken ( + T_CHAR *Str + ) +; + +BOOLEAN +SFPGetNumber ( + unsigned int *Value + ) +; + +BOOLEAN +SFPGetQuotedString ( + T_CHAR *Str, + int Length + ) +; + +BOOLEAN +SFPIsEOF ( + VOID + ) +; + +STATUS +SFPCloseFile ( + VOID + ) +; + +unsigned +int +SFPGetLineNumber ( + VOID + ) +; + +T_CHAR * +SFPGetFileName ( + VOID + ) +; + +#endif // #ifndef _SIMPLE_FILE_PARSING_H_ diff --git a/Tools/Source/TianoTools/Common/WinNtInclude.h b/Tools/Source/TianoTools/Common/WinNtInclude.h new file mode 100644 index 0000000000..80e45b4ad6 --- /dev/null +++ b/Tools/Source/TianoTools/Common/WinNtInclude.h @@ -0,0 +1,73 @@ +/*-- + +Copyright (c) 2006, 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. + +Module Name: + WinNtInclude.h + +Abstract: + Include file for the WinNt Library + +--*/ + +#ifndef __WIN_NT_INCLUDE_H__ +#define __WIN_NT_INCLUDE_H__ + +// +// Win32 include files do not compile clean with /W4, so we use the warning +// pragma to suppress the warnings for Win32 only. This way our code can stil +// compile at /W4 (highest warning level) with /WX (warnings cause build +// errors). +// +#pragma warning(disable : 4115) +#pragma warning(disable : 4201) +#pragma warning(disable : 4214) +#pragma warning(disable : 4028) +#pragma warning(disable : 4133) + +#define GUID _WINNT_DUP_GUID_____ +#define _LIST_ENTRY _WINNT_DUP_LIST_ENTRY_FORWARD +#define LIST_ENTRY _WINNT_DUP_LIST_ENTRY +#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement +#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement +#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64 +#undef UNALIGNED +#undef CONST +#undef VOID + +#ifndef __GNUC__ +#include "windows.h" +#endif + +#undef GUID +#undef _LIST_ENTRY +#undef LIST_ENTRY +#undef InterlockedIncrement +#undef InterlockedDecrement +#undef InterlockedCompareExchange64 +#undef InterlockedCompareExchangePointer + +#define VOID void + +// +// Prevent collisions with Windows API name macros that deal with Unicode/Not issues +// +#undef LoadImage +#undef CreateEvent + +// +// Set the warnings back on as the EFI code must be /W4. +// +#pragma warning(default : 4115) +#pragma warning(default : 4201) +#pragma warning(default : 4214) + + +#endif diff --git a/Tools/Source/TianoTools/Common/build.gcc b/Tools/Source/TianoTools/Common/build.gcc new file mode 100644 index 0000000000..fb7ab10326 --- /dev/null +++ b/Tools/Source/TianoTools/Common/build.gcc @@ -0,0 +1,8 @@ +mkdir -p ../Library-mingw +mkdir -p ../Library-cygwin +rm *.o +gcc -c -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ *.c +ar cr ../Library-cygwin/libCommon.a *.o +rm *.o +gcc -mno-cygwin -c -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ *.c +ar cr ../Library-mingw/libCommon.a *.o diff --git a/Tools/Source/TianoTools/Common/build.xml b/Tools/Source/TianoTools/Common/build.xml new file mode 100644 index 0000000000..593db567b3 --- /dev/null +++ b/Tools/Source/TianoTools/Common/build.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/CompressDll/CompressDll.c b/Tools/Source/TianoTools/CompressDll/CompressDll.c new file mode 100644 index 0000000000..783587f654 --- /dev/null +++ b/Tools/Source/TianoTools/CompressDll/CompressDll.c @@ -0,0 +1,89 @@ +#include "CompressDll.h" +#include "EfiCompress.h" + +extern +EFI_STATUS +Compress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ); + +JNIEXPORT jbyteArray JNICALL Java_org_tianocore_framework_tasks_Compress_CallCompress +(JNIEnv *env, jobject obj, jbyteArray SourceBuffer, jint SourceSize, jstring path) +{ + char* DestBuffer; + int DestSize; + int Result; + char *InputBuffer; + jbyteArray OutputBuffer; + jbyte *TempByte; + + DestSize = 0; + DestBuffer = NULL; + + TempByte = (*env)->GetByteArrayElements(env, SourceBuffer, 0); + InputBuffer = (char*) TempByte; + + + // + // First call compress function and get need buffer size + // + + Result = Compress ( + (char*) InputBuffer, + SourceSize, + DestBuffer, + &DestSize + ); + + if (Result = EFI_BUFFER_TOO_SMALL) { + DestBuffer = malloc (DestSize); + } + + // + // Second call compress and get the DestBuffer value + // + Result = Compress( + (char*) InputBuffer, + SourceSize, + DestBuffer, + &DestSize + ); + + // + // new a MV array to store the return compressed buffer + // + OutputBuffer = (*env)->NewByteArray(env, DestSize); + (*env)->SetByteArrayRegion(env, OutputBuffer,0, DestSize, (jbyte*) DestBuffer); + + // + // Free Ouputbuffer. + // + free (DestBuffer); + + + if (Result != 0) { + return NULL; + } else { + return OutputBuffer; + } +} + +#ifdef _MSC_VER +BOOLEAN +__stdcall +DllMainCRTStartup( + unsigned int hDllHandle, + unsigned int nReason, + void* Reserved +) +{ + return TRUE; +} +#else +#ifdef __GNUC__ +#endif +#endif + diff --git a/Tools/Source/TianoTools/CompressDll/CompressDll.h b/Tools/Source/TianoTools/CompressDll/CompressDll.h new file mode 100644 index 0000000000..3b0fbb2cee --- /dev/null +++ b/Tools/Source/TianoTools/CompressDll/CompressDll.h @@ -0,0 +1,21 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class org_tianocore_frameworktasks_Compress */ + +#ifndef _Included_org_tianocore_framework_tasks_Compress +#define _Included_org_tianocore_framework_tasks_Compress +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: org_tianocore_frameworktasks_Compress + * Method: CallCompress + * Signature: ([BILjava/lang/String;)[B + */ +JNIEXPORT jbyteArray JNICALL Java_org_tianocore_framework_tasks_Compress_CallCompress + (JNIEnv *, jobject, jbyteArray, jint, jstring); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/Tools/Source/TianoTools/CompressDll/build.xml b/Tools/Source/TianoTools/CompressDll/build.xml new file mode 100644 index 0000000000..e742e21763 --- /dev/null +++ b/Tools/Source/TianoTools/CompressDll/build.xml @@ -0,0 +1,116 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/CustomizedCompress/CustomizedCompress.c b/Tools/Source/TianoTools/CustomizedCompress/CustomizedCompress.c new file mode 100644 index 0000000000..ca0ea17ce6 --- /dev/null +++ b/Tools/Source/TianoTools/CustomizedCompress/CustomizedCompress.c @@ -0,0 +1,147 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + CustomizedCompress.c + +Abstract: + + Header file for Customized compression routine + +--*/ + +#include +#include + +EFI_STATUS +SetCustomizedCompressionType ( + IN CHAR8 *Type + ) +/*++ + +Routine Description: + +The implementation of Customized SetCompressionType(). + +Arguments: + Type - The type if compression. + +Returns: + + EFI_SUCCESS - The type has been set. + EFI_UNSUPPORTED - This type is unsupported. + + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +CustomizedGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + +The implementation of Customized GetInfo(). + +Arguments: + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + EFI_UNSUPPORTED - The operation is unsupported. + + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +CustomizedDecompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation of Customized Decompress(). + +Arguments: + + This - The protocol instance pointer + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successfull + EFI_INVALID_PARAMETER - The source data is corrupted + EFI_UNSUPPORTED - The operation is unsupported. + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +CustomizedCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +/*++ + +Routine Description: + + The Customized compression routine. + +Arguments: + + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. + +Returns: + + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + + EFI_UNSUPPORTED - The operation is unsupported. +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/Tools/Source/TianoTools/CustomizedCompress/build.gcc b/Tools/Source/TianoTools/CustomizedCompress/build.gcc new file mode 100644 index 0000000000..09e29c47e2 --- /dev/null +++ b/Tools/Source/TianoTools/CustomizedCompress/build.gcc @@ -0,0 +1,8 @@ +mkdir -p ../Library-mingw +mkdir -p ../Library-cygwin +rm *.o +gcc -c -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ *.c +ar cr ../Library-cygwin/libCustomizedCompress.a *.o +rm *.o +gcc -mno-cygwin -c -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ *.c +ar cr ../Library-mingw/libCustomizedCompress.a *.o diff --git a/Tools/Source/TianoTools/CustomizedCompress/build.xml b/Tools/Source/TianoTools/CustomizedCompress/build.xml new file mode 100644 index 0000000000..ff41a011dd --- /dev/null +++ b/Tools/Source/TianoTools/CustomizedCompress/build.xml @@ -0,0 +1,121 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/FwImage/build.gcc b/Tools/Source/TianoTools/FwImage/build.gcc new file mode 100644 index 0000000000..0cc3bbb4f9 --- /dev/null +++ b/Tools/Source/TianoTools/FwImage/build.gcc @@ -0,0 +1 @@ +gcc -mno-cygwin -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ *.c -o FwImage -L../Library-mingw -lCommon diff --git a/Tools/Source/TianoTools/FwImage/build.xml b/Tools/Source/TianoTools/FwImage/build.xml new file mode 100644 index 0000000000..c51e27e873 --- /dev/null +++ b/Tools/Source/TianoTools/FwImage/build.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/FwImage/fwimage.c b/Tools/Source/TianoTools/FwImage/fwimage.c new file mode 100644 index 0000000000..e2e0d49b9f --- /dev/null +++ b/Tools/Source/TianoTools/FwImage/fwimage.c @@ -0,0 +1,332 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + fwimage.c + +Abstract: + + Converts a pe32+ image to an FW image type + +--*/ + +#include +#ifndef __GNUC__ +#include +#endif +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define UTILITY_NAME "FwImage" + +#ifdef __GNUC__ +typedef unsigned long ULONG; +typedef unsigned char UCHAR; +typedef unsigned char *PUCHAR; +typedef unsigned short USHORT; +#endif + +VOID +Usage ( + VOID + ) +{ + printf ("Usage: " UTILITY_NAME " {-t time-date} [APPLICATION|BS_DRIVER|RT_DRIVER|SAL_RT_DRIVER|COMBINED_PEIM_DRIVER|SECURITY_CORE|PEI_CORE|PE32_PEIM|RELOCATABLE_PEIM] peimage [outimage]"); +} + +static +STATUS +FCopyFile ( + FILE *in, + FILE *out + ) +{ + ULONG filesize; + ULONG offset; + ULONG length; + UCHAR Buffer[8 * 1024]; + + fseek (in, 0, SEEK_END); + filesize = ftell (in); + + fseek (in, 0, SEEK_SET); + fseek (out, 0, SEEK_SET); + + offset = 0; + while (offset < filesize) { + length = sizeof (Buffer); + if (filesize - offset < length) { + length = filesize - offset; + } + + fread (Buffer, length, 1, in); + fwrite (Buffer, length, 1, out); + offset += length; + } + + if ((ULONG) ftell (out) != filesize) { + Error (NULL, 0, 0, "write error", NULL); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + Main function. + +Arguments: + + argc - Number of command line parameters. + argv - Array of pointers to command line parameter strings. + +Returns: + STATUS_SUCCESS - Utility exits successfully. + STATUS_ERROR - Some error occurred during execution. + +--*/ +{ + ULONG Type; + PUCHAR Ext; + PUCHAR p; + PUCHAR pe; + PUCHAR OutImageName; + UCHAR outname[500]; + FILE *fpIn; + FILE *fpOut; + EFI_IMAGE_DOS_HEADER DosHdr; + EFI_IMAGE_NT_HEADERS PeHdr; + time_t TimeStamp; + struct tm TimeStruct; + EFI_IMAGE_DOS_HEADER BackupDosHdr; + ULONG Index; + BOOLEAN TimeStampPresent; + + SetUtilityName (UTILITY_NAME); + // + // Assign to fix compile warning + // + OutImageName = NULL; + Type = 0; + Ext = 0; + TimeStamp = 0; + TimeStampPresent = FALSE; + + // + // Look for -t time-date option first. If the time is "0", then + // skip it. + // + if ((argc > 2) && !strcmp (argv[1], "-t")) { + TimeStampPresent = TRUE; + if (strcmp (argv[2], "0") != 0) { + // + // Convert the string to a value + // + memset ((char *) &TimeStruct, 0, sizeof (TimeStruct)); + if (sscanf( + argv[2], "%d/%d/%d,%d:%d:%d", + &TimeStruct.tm_mon, /* months since January - [0,11] */ + &TimeStruct.tm_mday, /* day of the month - [1,31] */ + &TimeStruct.tm_year, /* years since 1900 */ + &TimeStruct.tm_hour, /* hours since midnight - [0,23] */ + &TimeStruct.tm_min, /* minutes after the hour - [0,59] */ + &TimeStruct.tm_sec /* seconds after the minute - [0,59] */ + ) != 6) { + Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format"); + return STATUS_ERROR; + } + // + // Now fixup some of the fields + // + TimeStruct.tm_mon--; + TimeStruct.tm_year -= 1900; + // + // Sanity-check values? + // Convert + // + TimeStamp = mktime (&TimeStruct); + if (TimeStamp == (time_t) - 1) { + Error (NULL, 0, 0, argv[2], "failed to convert time"); + return STATUS_ERROR; + } + } + // + // Skip over the args + // + argc -= 2; + argv += 2; + } + // + // Check for enough args + // + if (argc < 3) { + Usage (); + return STATUS_ERROR; + } + + if (argc == 4) { + OutImageName = argv[3]; + } + // + // Get new image type + // + p = argv[1]; + if (*p == '/' || *p == '\\') { + p += 1; + } + + if (stricmp (p, "app") == 0 || stricmp (p, "APPLICATION") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; + Ext = ".efi"; + + } else if (stricmp (p, "bsdrv") == 0 || stricmp (p, "BS_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + Ext = ".efi"; + + } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "RT_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; + Ext = ".efi"; + + } else if (stricmp (p, "rtdrv") == 0 || stricmp (p, "SAL_RT_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; + Ext = ".efi"; + } else if (stricmp (p, "SECURITY_CORE") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + Ext = ".sec"; + } else if (stricmp (p, "peim") == 0 || + stricmp (p, "PEI_CORE") == 0 || + stricmp (p, "PE32_PEIM") == 0 || + stricmp (p, "RELOCATABLE_PEIM") == 0 || + stricmp (p, "combined_peim_driver") == 0 + ) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + Ext = ".pei"; + } else { + Usage (); + return STATUS_ERROR; + } + // + // open source file + // + fpIn = fopen (argv[2], "rb"); + if (!fpIn) { + Error (NULL, 0, 0, argv[2], "failed to open input file for reading"); + return STATUS_ERROR; + } + // + // Read the dos & pe hdrs of the image + // + fseek (fpIn, 0, SEEK_SET); + fread (&DosHdr, sizeof (DosHdr), 1, fpIn); + if (DosHdr.e_magic != EFI_IMAGE_DOS_SIGNATURE) { + Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image"); + fclose (fpIn); + return STATUS_ERROR; + } + + fseek (fpIn, DosHdr.e_lfanew, SEEK_SET); + fread (&PeHdr, sizeof (PeHdr), 1, fpIn); + if (PeHdr.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 0, argv[2], "PE header signature not found in source image"); + fclose (fpIn); + return STATUS_ERROR; + } + // + // open output file + // + strcpy (outname, argv[2]); + pe = NULL; + for (p = outname; *p; p++) { + if (*p == '.') { + pe = p; + } + } + + if (!pe) { + pe = p; + } + + strcpy (pe, Ext); + + if (!OutImageName) { + OutImageName = outname; + } + + fpOut = fopen (OutImageName, "w+b"); + if (!fpOut) { + Error (NULL, 0, 0, OutImageName, "could not open output file for writing"); + fclose (fpIn); + return STATUS_ERROR; + } + // + // Copy the file + // + if (FCopyFile (fpIn, fpOut) != STATUS_SUCCESS) { + fclose (fpIn); + fclose (fpOut); + return STATUS_ERROR; + } + // + // Zero all unused fields of the DOS header + // + memcpy (&BackupDosHdr, &DosHdr, sizeof (DosHdr)); + memset (&DosHdr, 0, sizeof (DosHdr)); + DosHdr.e_magic = BackupDosHdr.e_magic; + DosHdr.e_lfanew = BackupDosHdr.e_lfanew; + fseek (fpOut, 0, SEEK_SET); + fwrite (&DosHdr, sizeof (DosHdr), 1, fpOut); + + fseek (fpOut, sizeof (DosHdr), SEEK_SET); + for (Index = sizeof (DosHdr); Index < (ULONG) DosHdr.e_lfanew; Index++) { + fwrite (&DosHdr.e_cp, 1, 1, fpOut); + } + // + // Path the PE header + // + PeHdr.OptionalHeader.Subsystem = (USHORT) Type; + if (TimeStampPresent) { + PeHdr.FileHeader.TimeDateStamp = (UINT32) TimeStamp; + } + + PeHdr.OptionalHeader.SizeOfStackReserve = 0; + PeHdr.OptionalHeader.SizeOfStackCommit = 0; + PeHdr.OptionalHeader.SizeOfHeapReserve = 0; + PeHdr.OptionalHeader.SizeOfHeapCommit = 0; + fseek (fpOut, DosHdr.e_lfanew, SEEK_SET); + fwrite (&PeHdr, sizeof (PeHdr), 1, fpOut); + + // + // Done + // + fclose (fpIn); + fclose (fpOut); + // + // printf ("Created %s\n", OutImageName); + // + return STATUS_SUCCESS; +} diff --git a/Tools/Source/TianoTools/GenCRC32Section/GenCRC32Section.c b/Tools/Source/TianoTools/GenCRC32Section/GenCRC32Section.c new file mode 100644 index 0000000000..b99cf2f816 --- /dev/null +++ b/Tools/Source/TianoTools/GenCRC32Section/GenCRC32Section.c @@ -0,0 +1,286 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenCRC32Section.c + +Abstract: + + This file contains functions required to generate a Firmware File System + file. The code is compliant with the Tiano C Coding standards. + +--*/ + +#include "GenCRC32Section.h" + +#define TOOLVERSION "0.2" + +#define UTILITY_NAME "GenCrc32Section" + +EFI_GUID gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; + +EFI_STATUS +SignSectionWithCrc32 ( + IN OUT UINT8 *FileBuffer, + IN OUT UINT32 *BufferSize, + IN UINT32 DataSize + ) +/*++ + +Routine Description: + + Signs the section with CRC32 and add GUIDed section header for the + signed data. data stays in same location (overwrites source data). + +Arguments: + + FileBuffer - Buffer containing data to sign + + BufferSize - On input, the size of FileBuffer. On output, the size of + actual section data (including added section header). + + DataSize - Length of data to Sign + + Key - Key to use when signing. Currently only CRC32 is supported. + +Returns: + + EFI_SUCCESS - Successful + EFI_OUT_OF_RESOURCES - Not enough resource to complete the operation. + +--*/ +{ + + UINT32 Crc32Checksum; + EFI_STATUS Status; + UINT32 TotalSize; + CRC32_SECTION_HEADER Crc32Header; + UINT8 *SwapBuffer; + + Crc32Checksum = 0; + SwapBuffer = NULL; + + if (DataSize == 0) { + *BufferSize = 0; + + return EFI_SUCCESS; + } + + Status = CalculateCrc32 (FileBuffer, DataSize, &Crc32Checksum); + if (EFI_ERROR (Status)) { + return Status; + } + + TotalSize = DataSize + CRC32_SECTION_HEADER_SIZE; + Crc32Header.GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED; + Crc32Header.GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff); + Crc32Header.GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8); + Crc32Header.GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16); + memcpy (&(Crc32Header.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID)); + Crc32Header.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + Crc32Header.GuidSectionHeader.DataOffset = CRC32_SECTION_HEADER_SIZE; + Crc32Header.CRC32Checksum = Crc32Checksum; + + SwapBuffer = (UINT8 *) malloc (DataSize); + if (SwapBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + memcpy (SwapBuffer, FileBuffer, DataSize); + memcpy (FileBuffer, &Crc32Header, CRC32_SECTION_HEADER_SIZE); + memcpy (FileBuffer + CRC32_SECTION_HEADER_SIZE, SwapBuffer, DataSize); + + // + // Make sure section ends on a DWORD boundary + // + while ((TotalSize & 0x03) != 0) { + FileBuffer[TotalSize] = 0; + TotalSize++; + } + + *BufferSize = TotalSize; + + if (SwapBuffer != NULL) { + free (SwapBuffer); + } + + return EFI_SUCCESS; +} + +VOID +PrintUsage ( + VOID + ) +{ + printf ("Usage:\n"); + printf (UTILITY_NAME " -i \"inputfile1\" \"inputfile2\" -o \"outputfile\" \n"); + printf (" -i \"inputfile\":\n "); + printf (" specifies the input files that would be signed to CRC32 Guided section.\n"); + printf (" -o \"outputfile\":\n"); + printf (" specifies the output file that is a CRC32 Guided section.\n"); +} + +INT32 +ReadFilesContentsIntoBuffer ( + IN CHAR8 *argv[], + IN INT32 Start, + IN OUT UINT8 **FileBuffer, + IN OUT UINT32 *BufferSize, + OUT UINT32 *ContentSize, + IN INT32 MaximumArguments + ) +{ + INT32 Index; + CHAR8 *FileName; + FILE *InputFile; + UINT8 Temp; + UINT32 Size; + + FileName = NULL; + InputFile = NULL; + Size = 0; + Index = 0; + + // + // read all input files into one file buffer + // + while (argv[Start + Index][0] != '-') { + + FileName = argv[Start + Index]; + InputFile = fopen (FileName, "rb"); + if (InputFile == NULL) { + Error (NULL, 0, 0, FileName, "failed to open input binary file"); + return -1; + } + + fread (&Temp, sizeof (UINT8), 1, InputFile); + while (!feof (InputFile)) { + (*FileBuffer)[Size++] = Temp; + fread (&Temp, sizeof (UINT8), 1, InputFile); + } + + fclose (InputFile); + InputFile = NULL; + + // + // Make sure section ends on a DWORD boundary + // + while ((Size & 0x03) != 0) { + (*FileBuffer)[Size] = 0; + Size++; + } + + Index++; + if (Index == MaximumArguments) { + break; + } + } + + *ContentSize = Size; + return Index; +} + +int +main ( + INT32 argc, + CHAR8 *argv[] + ) +{ + FILE *OutputFile; + UINT8 *FileBuffer; + UINT32 BufferSize; + EFI_STATUS Status; + UINT32 ContentSize; + CHAR8 *OutputFileName; + INT32 ReturnValue; + INT32 Index; + + OutputFile = NULL; + FileBuffer = NULL; + ContentSize = 0; + OutputFileName = NULL; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + PrintUsage (); + return -1; + } + + BufferSize = 1024 * 1024 * 16; + FileBuffer = (UINT8 *) malloc (BufferSize * sizeof (UINT8)); + if (FileBuffer == NULL) { + Error (NULL, 0, 0, "memory allocation failed", NULL); + return -1; + } + + ZeroMem (FileBuffer, BufferSize); + + for (Index = 0; Index < argc; Index++) { + if (strcmpi (argv[Index], "-i") == 0) { + ReturnValue = ReadFilesContentsIntoBuffer ( + argv, + (Index + 1), + &FileBuffer, + &BufferSize, + &ContentSize, + (argc - (Index + 1)) + ); + if (ReturnValue == -1) { + Error (NULL, 0, 0, "failed to read file contents", NULL); + return -1; + } + + Index += ReturnValue; + } + + if (strcmpi (argv[Index], "-o") == 0) { + OutputFileName = argv[Index + 1]; + } + } + + OutputFile = fopen (OutputFileName, "wb"); + if (OutputFile == NULL) { + Error (NULL, 0, 0, OutputFileName, "failed to open output binary file"); + free (FileBuffer); + return -1; + } + + /* + // + // make sure section ends on a DWORD boundary ?? + // + while ( (Size & 0x03) != 0 ) { + FileBuffer[Size] = 0; + Size ++; + } +*/ + Status = SignSectionWithCrc32 (FileBuffer, &BufferSize, ContentSize); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "failed to sign section", NULL); + free (FileBuffer); + fclose (OutputFile); + return -1; + } + + ContentSize = fwrite (FileBuffer, sizeof (UINT8), BufferSize, OutputFile); + if (ContentSize != BufferSize) { + Error (NULL, 0, 0, "failed to write output buffer", NULL); + ReturnValue = -1; + } else { + ReturnValue = 0; + } + + free (FileBuffer); + fclose (OutputFile); + return ReturnValue; +} diff --git a/Tools/Source/TianoTools/GenCRC32Section/GenCRC32Section.h b/Tools/Source/TianoTools/GenCRC32Section/GenCRC32Section.h new file mode 100644 index 0000000000..574231d093 --- /dev/null +++ b/Tools/Source/TianoTools/GenCRC32Section/GenCRC32Section.h @@ -0,0 +1,64 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenCRC32Section.h + +Abstract: + + Header file for GenFfsFile. Mainly defines the header of section + header for CRC32 GUID defined sections. Share with GenSection.c + +--*/ + +// +// External Files Referenced +// + +/* Standard Headers */ +#include +#include +#include +#include + +/* MDE Headers */ +#include +#include +#include +#include +#include +#include +#include + +/* Tool Headers */ +#include +#include +#include +#include +#include + +// +// Module Coded to Tiano Coding Conventions +// +#ifndef _EFI_GEN_CRC32_SECTION_H +#define _EFI_GEN_CRC32_SECTION_H + + +typedef struct { + EFI_GUID_DEFINED_SECTION GuidSectionHeader; + UINT32 CRC32Checksum; +} CRC32_SECTION_HEADER; + +#define EFI_SECTION_CRC32_GUID_DEFINED 0 +#define CRC32_SECTION_HEADER_SIZE (sizeof (CRC32_SECTION_HEADER)) + +#endif diff --git a/Tools/Source/TianoTools/GenCRC32Section/build.gcc b/Tools/Source/TianoTools/GenCRC32Section/build.gcc new file mode 100644 index 0000000000..8d239da2fb --- /dev/null +++ b/Tools/Source/TianoTools/GenCRC32Section/build.gcc @@ -0,0 +1 @@ +gcc -mno-cygwin -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ *.c -o GenCRC32Section -L../Library-mingw -lCommon diff --git a/Tools/Source/TianoTools/GenCRC32Section/build.xml b/Tools/Source/TianoTools/GenCRC32Section/build.xml new file mode 100644 index 0000000000..a239f983c0 --- /dev/null +++ b/Tools/Source/TianoTools/GenCRC32Section/build.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/GenDepex/DepexParser.c b/Tools/Source/TianoTools/GenDepex/DepexParser.c new file mode 100644 index 0000000000..9f0a0cbbab --- /dev/null +++ b/Tools/Source/TianoTools/GenDepex/DepexParser.c @@ -0,0 +1,903 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + DepexParser.c + +Abstract: + + Validate Dependency Expression syntax + recursive descent Algorithm + + The original BNF grammar(taken from "Pre EFI Initialization Core Interface Specification + draft review 0.9") is thus: + ::= BEFORE END + | AFTER END + | SOR END + | END + ::= AND + | OR + | + ::= NOT + | + ::= + | TRUE + | FALSE + | GUID + + ::= '{' ',' ',' ',' + ',' ',' ',' ',' + ',' ',' ',' '}' + ::= + ::= + ::= + ::= '0' 'x' + | '0' 'X' + ::= + | + ::= [0-9] + | [a-f] + | [A-F] + + After cleaning left recursive and parentheses supported, the BNF grammar used in this module is thus: + ::= BEFORE + | AFTER + | SOR + | + ::= + ::= AND + | OR + | '' + ::= NOT + | + ::= '('')' + | NOT + | TRUE + | FALSE + | END + | + ::=AND + | OR + | '' + ::= '{' ',' ',' ',' + ',' ',' ',' ',' + ',' ',' ',' '}' + ::= + ::= + ::= + ::= '0' 'x' + | '0' 'X' + ::= + | + ::= [0-9] + | [a-f] + | [A-F] + + Note: 1. There's no precedence in operators except parentheses; + 2. For hex32, less and equal than 8 bits is valid, more than 8 bits is invalid. + Same constraint for hex16 is 4, hex8 is 2. All hex should contains at least 1 bit. + 3. " ::= '('')'" is added to support parentheses; + 4. " ::= GUID" is changed to " ::= "; + 5. "DEPENDENCY_END" is the terminal of the expression. But it has been filtered by caller. + During parsing, "DEPENDENCY_END" will be treated as illegal factor; + + This code should build in any environment that supports a standard C-library w/ string + operations and File I/O services. + + As an example of usage, consider the following: + + The input string could be something like: + + NOT ({ 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, + 0x3b } AND { 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, + 0x72, 0x3b }) OR { 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27, + 0x3f, 0xc1, 0x4d } AND + + It's invalid for an extra "AND" in the end. + + Complies with Tiano C Coding Standards Document, version 0.33, 16 Aug 2001. + +--*/ + +#include "DepexParser.h" + +BOOLEAN +ParseBool ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ); + +BOOLEAN +ParseTerm ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ); + +BOOLEAN +ParseRightBool ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ); + +BOOLEAN +ParseFactor ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ); + +VOID +LeftTrim ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Left trim the space, '\n' and '\r' character in string. + The space at the end does not need trim. + + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + None + + +--*/ +{ + while + ( + ((*Pindex) < (Pbegin + length)) && + ((strncmp (*Pindex, " ", 1) == 0) || (strncmp (*Pindex, "\n", 1) == 0) || (strncmp (*Pindex, "\r", 1) == 0)) + ) { + (*Pindex)++; + } +} + +BOOLEAN +ParseHexdigit ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse Hex bit in dependency expression. + +Arguments: + + Pbegin The pointer to the string + length Length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If parses a valid hex bit, return TRUE, otherwise FALSE + + +--*/ +{ + // + // ::= [0-9] | [a-f] | [A-F] + // + if (((**Pindex) >= '0' && (**Pindex) <= '9') || + ((**Pindex) >= 'a' && (**Pindex) <= 'f') || + ((**Pindex) >= 'A' && (**Pindex) <= 'F') + ) { + (*Pindex)++; + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +ParseHex32 ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse Hex32 in dependency expression. + +Arguments: + + Pbegin The pointer to the string + length Length of the string + Pindex The pointer of point to the next parse character in the string + +Returns: + + BOOLEAN If parses a valid hex32, return TRUE, otherwise FALSE + + +--*/ +{ + INT32 Index; + INT8 *Pin; + + Index = 0; + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) { + return FALSE; + } + (*Pindex) += 2; + + while (ParseHexdigit (Pbegin, length, Pindex)) { + Index++; + } + + if (Index > 0 && Index <= 8) { + return TRUE; + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseHex16 ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse Hex16 in dependency expression. + +Arguments: + + Pbegin The pointer to the string + length Length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If parses a valid hex16, return TRUE, otherwise FALSE + + +--*/ +{ + int Index; + INT8 *Pin; + + Index = 0; + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) { + return FALSE; + } + (*Pindex) += 2; + + while (ParseHexdigit (Pbegin, length, Pindex)) { + Index++; + } + + if (Index > 0 && Index <= 4) { + return TRUE; + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseHex8 ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse Hex8 in dependency expression. + +Arguments: + + Pbegin The pointer to the string + length Length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If parses a valid hex8, return TRUE, otherwise FALSE + + +--*/ +{ + int Index; + INT8 *Pin; + + Index = 0; + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) { + return FALSE; + } + (*Pindex) += 2; + + while (ParseHexdigit (Pbegin, length, Pindex)) { + Index++; + } + + if (Index > 0 && Index <= 2) { + return TRUE; + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseGuid ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse guid in dependency expression. + There can be any number of spaces between '{' and hexword, ',' and hexword, + hexword and ',', hexword and '}'. The hexword include hex32, hex16 and hex8. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If parses a valid guid, return TRUE, otherwise FALSE + + +--*/ +{ + INT32 Index; + INT8 *Pin; + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, "{", 1) != 0) { + return FALSE; + } + (*Pindex)++; + + LeftTrim (Pbegin, length, Pindex); + if (!ParseHex32 (Pbegin, length, Pindex)) { + *Pindex = Pin; + return FALSE; + } + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, ",", 1) != 0) { + return FALSE; + } else { + (*Pindex)++; + } + + for (Index = 0; Index < 2; Index++) { + LeftTrim (Pbegin, length, Pindex); + if (!ParseHex16 (Pbegin, length, Pindex)) { + *Pindex = Pin; + return FALSE; + } + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, ",", 1) != 0) { + return FALSE; + } else { + (*Pindex)++; + } + } + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, "{", 1) != 0) { + return FALSE; + } + (*Pindex)++; + + for (Index = 0; Index < 7; Index++) { + LeftTrim (Pbegin, length, Pindex); + if (!ParseHex8 (Pbegin, length, Pindex)) { + *Pindex = Pin; + return FALSE; + } + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, ",", 1) != 0) { + return FALSE; + } else { + (*Pindex)++; + } + } + + LeftTrim (Pbegin, length, Pindex); + if (!ParseHex8 (Pbegin, length, Pindex)) { + *Pindex = Pin; + return FALSE; + } + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, "}", 1) != 0) { + return FALSE; + } else { + (*Pindex)++; + } + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, "}", 1) != 0) { + return FALSE; + } else { + (*Pindex)++; + } + + return TRUE; +} + +BOOLEAN +ParseRightFactor ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse rightfactor in bool expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If string is a valid rightfactor expression, return TRUE, otherwise FALSE + + +--*/ +{ + INT8 *Pin; + + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + // + // ::=AND + // + if (strncmp (*Pindex, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) { + *Pindex += strlen (OPERATOR_AND); + LeftTrim (Pbegin, length, Pindex); + + if (ParseTerm (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightBool (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } + // + // ::=OR + // + if (strncmp (*Pindex, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) { + *Pindex += strlen (OPERATOR_OR); + LeftTrim (Pbegin, length, Pindex); + + if (ParseTerm (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightBool (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } + // + // ::= '' + // + *Pindex = Pin; + return TRUE; +} + +BOOLEAN +ParseRightBool ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse rightbool in bool expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If string is a valid rightbool expression, return TRUE, otherwise FALSE + + +--*/ +{ + INT8 *Pin; + + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + // + // ::= AND + // + if (strncmp (*Pindex, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) { + *Pindex += strlen (OPERATOR_AND); + LeftTrim (Pbegin, length, Pindex); + + if (ParseTerm (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightBool (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } + // + // ::= OR + // + if (strncmp (*Pindex, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) { + *Pindex += strlen (OPERATOR_OR); + LeftTrim (Pbegin, length, Pindex); + + if (ParseTerm (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightBool (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } + // + // ::= '' + // + *Pindex = Pin; + return TRUE; +} + +BOOLEAN +ParseFactor ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse factor in bool expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If string is a valid factor, return TRUE, otherwise FALSE + + +--*/ +{ + INT8 *Pin; + + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + // + // ::= '('')' + // + if (strncmp (*Pindex, OPERATOR_LEFT_PARENTHESIS, strlen (OPERATOR_LEFT_PARENTHESIS)) == 0) { + *Pindex += strlen (OPERATOR_LEFT_PARENTHESIS); + LeftTrim (Pbegin, length, Pindex); + + if (!ParseBool (Pbegin, length, Pindex)) { + *Pindex = Pin; + } else { + LeftTrim (Pbegin, length, Pindex); + + if (strncmp (*Pindex, OPERATOR_RIGHT_PARENTHESIS, strlen (OPERATOR_RIGHT_PARENTHESIS)) == 0) { + *Pindex += strlen (OPERATOR_RIGHT_PARENTHESIS); + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } + } + } + // + // ::= NOT + // + if (strncmp (*Pindex, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) { + *Pindex += strlen (OPERATOR_NOT); + LeftTrim (Pbegin, length, Pindex); + + if (ParseFactor (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightBool (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } + // + // ::= TRUE + // + if (strncmp (*Pindex, OPERATOR_TRUE, strlen (OPERATOR_TRUE)) == 0) { + *Pindex += strlen (OPERATOR_TRUE); + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } + // + // ::= FALSE + // + if (strncmp (*Pindex, OPERATOR_FALSE, strlen (OPERATOR_FALSE)) == 0) { + *Pindex += strlen (OPERATOR_FALSE); + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } + // + // ::= + // + if (ParseGuid (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + return FALSE; + } + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseTerm ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse term in bool expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If string is a valid term, return TRUE, otherwise FALSE + + +--*/ +{ + INT8 *Pin; + + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + // + // ::= NOT + // + if (strncmp (*Pindex, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) { + *Pindex += strlen (OPERATOR_NOT); + LeftTrim (Pbegin, length, Pindex); + + if (!ParseFactor (Pbegin, length, Pindex)) { + *Pindex = Pin; + } else { + return TRUE; + } + } + // + // ::= + // + if (ParseFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseBool ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse bool expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If string is a valid bool expression, return TRUE, otherwise FALSE + + +--*/ +{ + INT8 *Pin; + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + if (ParseTerm (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (!ParseRightBool (Pbegin, length, Pindex)) { + *Pindex = Pin; + return FALSE; + } else { + return TRUE; + } + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseDepex ( + IN INT8 *Pbegin, + IN UINT32 length + ) +/*++ + +Routine Description: + + Parse whole dependency expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + +Returns: + + BOOLEAN If string is a valid dependency expression, return TRUE, otherwise FALSE + + +--*/ +{ + BOOLEAN Result; + INT8 **Pindex; + INT8 *temp; + + Result = FALSE; + temp = Pbegin; + Pindex = &temp; + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, OPERATOR_BEFORE, strlen (OPERATOR_BEFORE)) == 0) { + (*Pindex) += strlen (OPERATOR_BEFORE); + Result = ParseGuid (Pbegin, length, Pindex); + + } else if (strncmp (*Pindex, OPERATOR_AFTER, strlen (OPERATOR_AFTER)) == 0) { + (*Pindex) += strlen (OPERATOR_AFTER); + Result = ParseGuid (Pbegin, length, Pindex); + + } else if (strncmp (*Pindex, OPERATOR_SOR, strlen (OPERATOR_SOR)) == 0) { + (*Pindex) += strlen (OPERATOR_SOR); + Result = ParseBool (Pbegin, length, Pindex); + + } else { + Result = ParseBool (Pbegin, length, Pindex); + + } + + LeftTrim (Pbegin, length, Pindex); + return (BOOLEAN) (Result && (*Pindex) >= (Pbegin + length)); +} diff --git a/Tools/Source/TianoTools/GenDepex/DepexParser.h b/Tools/Source/TianoTools/GenDepex/DepexParser.h new file mode 100644 index 0000000000..29e0884a3e --- /dev/null +++ b/Tools/Source/TianoTools/GenDepex/DepexParser.h @@ -0,0 +1,26 @@ +/*++ +Copyright (c) 2004, 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. + + Module Name: + GenDepex.h + + Abstract: + This file contains the relevant declarations required + to generate a binary Dependency File + + Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000. + +--*/ + +// TODO: fix comment to set correct module name: DepexParser.h +#ifndef _EFI_DEPEX_PARSER_H_ +#define _EFI_DEPEX_PARSER_H_ +#include "GenDepex.h" +#endif diff --git a/Tools/Source/TianoTools/GenDepex/GenDepex.c b/Tools/Source/TianoTools/GenDepex/GenDepex.c new file mode 100644 index 0000000000..2a65e086fc --- /dev/null +++ b/Tools/Source/TianoTools/GenDepex/GenDepex.c @@ -0,0 +1,916 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenDepex.c + +Abstract: + + Generate Dependency Expression ("GenDepex") + + Infix to Postfix Algorithm + + This code has been scrubbed to be free of having any EFI core tree dependencies. + It should build in any environment that supports a standard C-library w/ string + operations and File I/O services. + + As an example of usage, consider the following: + + The input user file could be something like "Sample.DXS" whose contents are + + #include "Tiano.h" + + DEPENDENCY_START + NOT (DISK_IO_PROTOCOL AND SIMPLE_FILE_SYSTEM_PROTOCOL) + OR EFI_PXE_BASE_CODE_PROTOCOL + DEPENDENCY_END + + This file is then washed through the C-preprocessor, viz., + + cl /EP Sample.DXS > Sample.TMP1 + + This yields the following file "Sample.TMP1" whose contents are + + DEPENDENCY_START + NOT ({ 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, + 0x3b } AND { 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, + 0x72, 0x3b }) OR { 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27, + 0x3f, 0xc1, 0x4d } + DEPENDENCY_END + + This file, in turn, will be fed into the utility, viz., + + GenDepex Sample.TMP1 Sample.TMP2 + + With a file that is 55 bytes long: + + 55 bytes for the grammar binary + PUSH opcode - 1 byte + GUID Instance - 16 bytes + PUSH opcode - 1 byte + GUID Instance - 16 bytes + AND opcode - 1 byte + NOT opcode - 1 byte + PUSH opcode - 1 byte + GUID Instance - 16 bytes + OR opcode - 1 byte + END opcode - 1 byte + + The file "Sample.TMP2" could be fed via a Section-builder utility + (GenSection) that would be used for the creation of a dependency + section file (.DPX) which in turn would be used by a generate FFS + utility (GenFfsFile) to produce a DXE driver/core (.DXE) or + a DXE application (.APP) file. + + Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000. + +--*/ + +#include "GenDepex.h" + +#define TOOL_NAME "GenDepex" + +extern +ParseDepex ( + IN INT8 *Pbegin, + IN UINT32 length + ); + +VOID +PrintGenDepexUtilityInfo ( + VOID + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ( + "%s, Tiano Dependency Expression Generation Utility. Version %d.%d.\n", + UTILITY_NAME, + UTILITY_MAJOR_VERSION, + UTILITY_MINOR_VERSION + ); + printf ("Copyright (C) 1996-2002 Intel Corporation. All rights reserved.\n\n"); +} + +VOID +PrintGenDepexUsageInfo ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ( + "Usage: %s -I -O [-P ] \n", + UTILITY_NAME + ); + printf (" Where:\n"); + printf (" is the input pre-processed dependency text files name.\n"); + printf (" is the output binary dependency files name.\n"); + printf (" is the padding integer value.\n"); + printf (" This is the boundary to align the output file size to.\n"); +} + +DEPENDENCY_OPCODE +PopOpCode ( + IN OUT VOID **Stack + ) +/*++ + +Routine Description: + + Pop an element from the Opcode stack. + +Arguments: + + Stack Current top of the OpCode stack location + +Returns: + + DEPENDENCY_OPCODE OpCode at the top of the OpCode stack. + Stack New top of the OpCode stack location + + +--*/ +{ + DEPENDENCY_OPCODE *OpCodePtr; + + OpCodePtr = *Stack; + OpCodePtr--; + *Stack = OpCodePtr; + return *OpCodePtr; +} + +VOID +PushOpCode ( + IN OUT VOID **Stack, + IN DEPENDENCY_OPCODE OpCode + ) +/*++ + +Routine Description: + + Push an element onto the Opcode Stack + +Arguments: + + Stack Current top of the OpCode stack location + OpCode OpCode to push onto the stack + +Returns: + + Stack New top of the OpCode stack location + +--*/ +{ + DEPENDENCY_OPCODE *OpCodePtr; + + OpCodePtr = *Stack; + *OpCodePtr = OpCode; + OpCodePtr++; + *Stack = OpCodePtr; +} + +EFI_STATUS +GenerateDependencyExpression ( + IN FILE *InFile, + IN OUT FILE *OutFile, + IN UINT8 Padding OPTIONAL + ) +/*++ + +Routine Description: + + This takes the pre-compiled dependency text file and + converts it into a binary dependency file. + + The BNF for the dependency expression is as follows + (from the DXE 1.0 Draft specification). + + The inputted BNF grammar is thus: + ::= sor | + before GUID | + after GUID | + + + ::= | + + ::= and | + or | + + + ::= not | + + + ::= ( ) | + | + GUID | + + + ::= true | + false + + The outputed binary grammer is thus: + ::= sor | + before | + after | + + + ::= | + + ::= and | + or | + + ::= not | + + + ::= ( ) | + | + | + | + + + ::= true | + false + + ::= push GUID + + ::= end + + BugBug: A correct grammer is parsed correctly. A file that violates the + grammer may parse when it should generate an error. There is some + error checking and it covers most of the case when it's an include + of definition issue. An ill formed expresion may not be detected. + +Arguments: + + InFile - Input pre-compiled text file of the dependency expression. + This needs to be in ASCII. + The file pointer can not be NULL. + + OutFile - Binary dependency file. + The file pointer can not be NULL. + + Padding - OPTIONAL integer value to pad the output file to. + + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the parameters in the text file was invalid. + EFI_OUT_OF_RESOURCES Unable to allocate memory. + EFI_ABORTED An misc error occurred. + +--*/ +{ + INT8 *Ptrx; + INT8 *Pend; + INT8 *EvaluationStack; + INT8 *StackPtr; + INT8 *Buffer; + INT8 Line[LINESIZE]; + UINTN Index; + UINTN OutFileSize; + UINTN FileSize; + UINTN Results; + BOOLEAN NotDone; + BOOLEAN Before_Flag; + BOOLEAN After_Flag; + BOOLEAN Dep_Flag; + BOOLEAN SOR_Flag; + EFI_GUID Guid; + UINTN ArgCountParsed; + DEPENDENCY_OPCODE Opcode; + + Before_Flag = FALSE; + After_Flag = FALSE; + Dep_Flag = FALSE; + SOR_Flag = FALSE; + + memset (Line, 0, LINESIZE); + + OutFileSize = 0; + + EvaluationStack = (INT8 *) malloc (EVAL_STACK_SIZE); + + if (EvaluationStack != NULL) { + StackPtr = EvaluationStack; + } else { + printf ("Unable to allocate memory to EvaluationStack - Out of resources\n"); + return EFI_OUT_OF_RESOURCES; + } + + Results = (UINTN) fseek (InFile, 0, SEEK_END); + + if (Results != 0) { + printf ("FSEEK failed - Aborted\n"); + return EFI_ABORTED; + } + + FileSize = ftell (InFile); + + if (FileSize == -1L) { + printf ("FTELL failed - Aborted\n"); + return EFI_ABORTED; + } + + Buffer = (INT8 *) malloc (FileSize + BUFFER_SIZE); + + if (Buffer == NULL) { + printf ("Unable to allocate memory to Buffer - Out of resources\n"); + free (EvaluationStack); + + Results = (UINTN) fclose (InFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + Results = (UINTN) fclose (OutFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + return EFI_OUT_OF_RESOURCES; + } + + Results = (UINTN) fseek (InFile, 0, SEEK_SET); + + if (Results != 0) { + printf ("FSEEK failed - Aborted\n"); + return EFI_ABORTED; + } + + fread (Buffer, FileSize, 1, InFile); + + Ptrx = Buffer; + Pend = Ptrx + FileSize - strlen (DEPENDENCY_END); + Index = FileSize; + + NotDone = TRUE; + while ((Index--) && NotDone) { + + if (strncmp (Pend, DEPENDENCY_END, strlen (DEPENDENCY_END)) == 0) { + NotDone = FALSE; + } else { + Pend--; + } + } + + if (NotDone) { + printf ("Couldn't find end string %s\n", DEPENDENCY_END); + + Results = (UINTN) fclose (InFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + Results = (UINTN) fclose (OutFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + free (Buffer); + free (EvaluationStack); + + return EFI_INVALID_PARAMETER; + } + + Index = FileSize; + + NotDone = TRUE; + while ((Index--) && NotDone) { + + if (strncmp (Ptrx, DEPENDENCY_START, strlen (DEPENDENCY_START)) == 0) { + Ptrx += sizeof (DEPENDENCY_START); + NotDone = FALSE; + // + // BUGBUG -- should Index be decremented by sizeof(DEPENDENCY_START)? + // + } else { + Ptrx++; + } + } + + if (NotDone) { + printf ("Couldn't find start string %s\n", DEPENDENCY_START); + + Results = (UINTN) fclose (InFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + Results = (UINTN) fclose (OutFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + free (Buffer); + free (EvaluationStack); + + return EFI_INVALID_PARAMETER; + } + // + // validate the syntax of expression + // + if (!ParseDepex (Ptrx, Pend - Ptrx - 1)) { + printf ("The syntax of expression is wrong\n"); + + Results = (UINTN) fclose (InFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + Results = (UINTN) fclose (OutFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + free (Buffer); + free (EvaluationStack); + + return EFI_INVALID_PARAMETER; + } + + NotDone = TRUE; + + while ((Index--) && NotDone) { + + if (*Ptrx == ' ') { + Ptrx++; + } else if (*Ptrx == '\n' || *Ptrx == '\r') { + Ptrx++; + } else if (strncmp (Ptrx, OPERATOR_SOR, strlen (OPERATOR_SOR)) == 0) { + // + // Checks for some invalid dependencies + // + if (Before_Flag) { + + printf ("A BEFORE operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (After_Flag) { + + printf ("An AFTER operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (SOR_Flag) { + + printf ("Another SOR operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (Dep_Flag) { + + printf ("The Schedule On Request - SOR operator must be the first operator following DEPENDENCY_START\n"); + return EFI_INVALID_PARAMETER; + + } else { + // + // BUGBUG - This was not in the spec but is in the CORE code + // An OPERATOR_SOR has to be first - following the DEPENDENCY_START + // + fputc (EFI_DEP_SOR, OutFile); + OutFileSize++; + Ptrx += sizeof (OPERATOR_SOR); + SOR_Flag = TRUE; + + } + } else if (strncmp (Ptrx, OPERATOR_BEFORE, strlen (OPERATOR_BEFORE)) == 0) { + // + // Checks for some invalid dependencies + // + if (Before_Flag) { + + printf ("Another BEFORE operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (After_Flag) { + + printf ("An AFTER operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (SOR_Flag) { + + printf ("A SOR operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (Dep_Flag) { + + printf ("The BEFORE operator must be the first operator following DEPENDENCY_START\n"); + return EFI_INVALID_PARAMETER; + + } else { + fputc (EFI_DEP_BEFORE, OutFile); + OutFileSize++; + Ptrx += sizeof (OPERATOR_BEFORE); + Before_Flag = TRUE; + } + } else if (strncmp (Ptrx, OPERATOR_AFTER, strlen (OPERATOR_AFTER)) == 0) { + // + // Checks for some invalid dependencies + // + if (Before_Flag) { + + printf ("A BEFORE operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (After_Flag) { + + printf ("Another AFTER operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (SOR_Flag) { + + printf ("A SOR operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (Dep_Flag) { + + printf ("The AFTER operator must be the first operator following DEPENDENCY_START\n"); + return EFI_INVALID_PARAMETER; + + } else { + fputc (EFI_DEP_AFTER, OutFile); + OutFileSize++; + Ptrx += sizeof (OPERATOR_AFTER); + Dep_Flag = TRUE; + After_Flag = TRUE; + } + } else if (strncmp (Ptrx, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) { + while (StackPtr != EvaluationStack) { + Opcode = PopOpCode ((VOID **) &StackPtr); + if (Opcode != DXE_DEP_LEFT_PARENTHESIS) { + fputc (Opcode, OutFile); + OutFileSize++; + } else { + PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS); + break; + } + } + + PushOpCode ((VOID **) &StackPtr, EFI_DEP_AND); + Ptrx += sizeof (OPERATOR_AND); + Dep_Flag = TRUE; + + } else if (strncmp (Ptrx, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) { + while (StackPtr != EvaluationStack) { + Opcode = PopOpCode ((VOID **) &StackPtr); + if (Opcode != DXE_DEP_LEFT_PARENTHESIS) { + fputc (Opcode, OutFile); + OutFileSize++; + } else { + PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS); + break; + } + } + + PushOpCode ((VOID **) &StackPtr, EFI_DEP_OR); + Ptrx += sizeof (OPERATOR_OR); + Dep_Flag = TRUE; + + } else if (strncmp (Ptrx, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) { + while (StackPtr != EvaluationStack) { + Opcode = PopOpCode ((VOID **) &StackPtr); + if (Opcode != DXE_DEP_LEFT_PARENTHESIS) { + fputc (Opcode, OutFile); + OutFileSize++; + } else { + PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS); + break; + } + } + + PushOpCode ((VOID **) &StackPtr, EFI_DEP_NOT); + Ptrx += sizeof (OPERATOR_NOT); + Dep_Flag = TRUE; + + } else if (*Ptrx == '\t') { + + printf ("File contains tabs. This violates the coding standard\n"); + return EFI_INVALID_PARAMETER; + + } else if (*Ptrx == '\n') { + // + // Skip the newline character in the file + // + Ptrx++; + + } else if (strncmp (Ptrx, OPERATOR_LEFT_PARENTHESIS, strlen (OPERATOR_LEFT_PARENTHESIS)) == 0) { + PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS); + + Ptrx += strlen (OPERATOR_LEFT_PARENTHESIS); + Dep_Flag = TRUE; + + } else if (strncmp (Ptrx, OPERATOR_RIGHT_PARENTHESIS, strlen (OPERATOR_RIGHT_PARENTHESIS)) == 0) { + while (StackPtr != EvaluationStack) { + Opcode = PopOpCode ((VOID **) &StackPtr); + if (Opcode != DXE_DEP_LEFT_PARENTHESIS) { + fputc (Opcode, OutFile); + OutFileSize++; + } else { + break; + } + } + + Ptrx += strlen (OPERATOR_RIGHT_PARENTHESIS); + Dep_Flag = TRUE; + + } else if (strncmp (Ptrx, OPERATOR_TRUE, strlen (OPERATOR_TRUE)) == 0) { + + fputc (EFI_DEP_TRUE, OutFile); + + OutFileSize++; + + // + // OutFileSize += sizeof (EFI_DEP_TRUE); + // + Dep_Flag = TRUE; + + Ptrx += strlen (OPERATOR_TRUE); + + } else if (strncmp (Ptrx, OPERATOR_FALSE, strlen (OPERATOR_FALSE)) == 0) { + + fputc (EFI_DEP_FALSE, OutFile); + + OutFileSize++; + + // + // OutFileSize += sizeof (EFI_DEP_FALSE); + // + Dep_Flag = TRUE; + + Ptrx += strlen (OPERATOR_FALSE); + + } else if (*Ptrx == '{') { + Ptrx++; + + if (*Ptrx == ' ') { + Ptrx++; + } + + ArgCountParsed = sscanf ( + Ptrx, + "%x, %x, %x, { %x, %x, %x, %x, %x, %x, %x, %x }", + &Guid.Data1, + &Guid.Data2, + &Guid.Data3, + &Guid.Data4[0], + &Guid.Data4[1], + &Guid.Data4[2], + &Guid.Data4[3], + &Guid.Data4[4], + &Guid.Data4[5], + &Guid.Data4[6], + &Guid.Data4[7] + ); + + if (ArgCountParsed != 11) { + printf ("We have found an illegal GUID\n"); + printf ("Fix your depex\n"); + exit (-1); + } + + while (*Ptrx != '}') { + Ptrx++; + } + + Ptrx++; + while (*Ptrx != '}') { + Ptrx++; + } + // + // Absorb the closing } + // + Ptrx++; + + // + // Don't provide a PUSH Opcode for the Before and After case + // + if ((!Before_Flag) && (!After_Flag)) { + fputc (EFI_DEP_PUSH, OutFile); + OutFileSize++; + } + + fwrite (&Guid, sizeof (EFI_GUID), 1, OutFile); + + OutFileSize += sizeof (EFI_GUID); + Dep_Flag = TRUE; + + } else if (strncmp (Ptrx, DEPENDENCY_END, strlen (DEPENDENCY_END)) == 0) { + NotDone = FALSE; + } else { + // + // Not a valid construct. Null terminate somewhere out there and + // print an error message. + // + *(Ptrx + 20) = 0; + printf (TOOL_NAME " ERROR: Unrecognized input at: \"%s\"...\n", Ptrx); + return EFI_INVALID_PARAMETER; + } + } + // + // DRAIN(); + // + while (StackPtr != EvaluationStack) { + fputc (PopOpCode ((VOID **) &StackPtr), OutFile); + OutFileSize++; + } + + if (OutFileSize == 0) { + printf ("Grammer contains no operators or constants\n"); + return EFI_INVALID_PARAMETER; + } + + fputc (EFI_DEP_END, OutFile); + + OutFileSize++; + + // + // Checks for invalid padding values + // + if (Padding < 0) { + + printf ("The inputted padding value was %d\n", Padding); + printf ("The optional padding value can not be less than ZERO\n"); + return EFI_INVALID_PARAMETER; + + } else if (Padding > 0) { + + while ((OutFileSize % Padding) != 0) { + + fputc (' ', OutFile); + OutFileSize++; + } + } + + Results = (UINTN) fclose (InFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + Results = (UINTN) fclose (OutFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + free (Buffer); + free (EvaluationStack); + + return EFI_SUCCESS; +} // End GenerateDependencyExpression function + +int +main ( + IN UINTN argc, + IN CHAR8 *argv[] + ) +/*++ + +Routine Description: + + Parse user entries. Print some rudimentary help + +Arguments: + + argc The count of input arguments + argv The input arguments string array + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid or one of the parameters in the text file was invalid. + EFI_OUT_OF_RESOURCES Unable to allocate memory. + EFI_ABORTED Unable to open/create a file or a misc error. + +--*/ +// TODO: ] - add argument and description to function comment +{ + FILE *OutFile; + FILE *InFile; + UINT8 Padding; + UINTN Index; + BOOLEAN Input_Flag; + BOOLEAN Output_Flag; + BOOLEAN Pad_Flag; + + InFile = NULL; + OutFile = NULL; + Padding = 0; + Input_Flag = FALSE; + Output_Flag = FALSE; + Pad_Flag = FALSE; + + // + // Output the calling arguments + // + printf ("\n\n"); + for (Index = 0; Index < argc; Index++) { + printf ("%s ", argv[Index]); + } + + printf ("\n\n"); + + if (argc < 5) { + printf ("Not enough arguments\n"); + PrintGenDepexUsageInfo (); + return EFI_INVALID_PARAMETER; + } + + for (Index = 1; Index < argc - 1; Index++) { + + if ((strcmp (argv[Index], "-I") == 0) || (strcmp (argv[Index], "-i") == 0)) { + + if (!Input_Flag) { + + InFile = fopen (argv[Index + 1], "rb"); + Input_Flag = TRUE; + + } else { + printf ("GenDepex only allows one INPUT (-I) argument\n"); + return EFI_INVALID_PARAMETER; + } + + } else if ((strcmp (argv[Index], "-O") == 0) || (strcmp (argv[Index], "-o") == 0)) { + + if (!Output_Flag) { + + OutFile = fopen (argv[Index + 1], "wb"); + Output_Flag = TRUE; + + } else { + printf ("GenDepex only allows one OUTPUT (-O) argument\n"); + return EFI_INVALID_PARAMETER; + } + + } else if ((strcmp (argv[Index], "-P") == 0) || (strcmp (argv[Index], "-p") == 0)) { + + if (!Pad_Flag) { + + Padding = (UINT8) atoi (argv[Index + 1]); + Pad_Flag = TRUE; + + } else { + printf ("GenDepex only allows one PADDING (-P) argument\n"); + return EFI_INVALID_PARAMETER; + } + } + } + + PrintGenDepexUtilityInfo (); + + if (InFile == NULL) { + printf ("Can not open for reading.\n"); + PrintGenDepexUsageInfo (); + return EFI_ABORTED; + } + + if (OutFile == NULL) { + printf ("Can not open for writting.\n"); + PrintGenDepexUsageInfo (); + return EFI_ABORTED; + } + + return GenerateDependencyExpression (InFile, OutFile, Padding); +} diff --git a/Tools/Source/TianoTools/GenDepex/GenDepex.h b/Tools/Source/TianoTools/GenDepex/GenDepex.h new file mode 100644 index 0000000000..cfba0f2011 --- /dev/null +++ b/Tools/Source/TianoTools/GenDepex/GenDepex.h @@ -0,0 +1,71 @@ +/*++ +Copyright (c) 2004, 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. + + Module Name: + GenDepex.h + + Abstract: + This file contains the relevant declarations required + to generate a binary Dependency File + + Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000. + +--*/ + +#ifndef _EFI_GEN_DEPEX_H +#define _EFI_GEN_DEPEX_H + + +#include +#include +#include +#include +#ifndef __GNUC__ +#include +#endif +#include +#include +#include + +#define DEPENDENCY_START "DEPENDENCY_START" +#define OPERATOR_BEFORE "BEFORE" +#define OPERATOR_AFTER "AFTER" +#define OPERATOR_AND "AND" +#define OPERATOR_OR "OR" +#define OPERATOR_NOT "NOT" +#define OPERATOR_TRUE "TRUE" +#define OPERATOR_FALSE "FALSE" +#define OPERATOR_SOR "SOR" +#define OPERATOR_END "END" +#define OPERATOR_LEFT_PARENTHESIS "(" +#define OPERATOR_RIGHT_PARENTHESIS ")" +#define DEPENDENCY_END "DEPENDENCY_END" + +#define DXE_DEP_LEFT_PARENTHESIS 0x0a +#define DXE_DEP_RIGHT_PARENTHESIS 0x0b + +#define LINESIZE 320 +#define SIZE_A_SYMBOL 60 +#define DEPENDENCY_OPCODE UINT8 +#define EVAL_STACK_SIZE 0x1024 +#define BUFFER_SIZE 0x100 + +// +// Utility Name +// +#define UTILITY_NAME "GenDepex" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 5 + +#endif diff --git a/Tools/Source/TianoTools/GenDepex/build.gcc b/Tools/Source/TianoTools/GenDepex/build.gcc new file mode 100644 index 0000000000..71f5a9b731 --- /dev/null +++ b/Tools/Source/TianoTools/GenDepex/build.gcc @@ -0,0 +1 @@ +gcc -mno-cygwin -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ *.c -o GenDepex -L../Library-mingw -lCommon diff --git a/Tools/Source/TianoTools/GenDepex/build.xml b/Tools/Source/TianoTools/GenDepex/build.xml new file mode 100644 index 0000000000..9135694d2f --- /dev/null +++ b/Tools/Source/TianoTools/GenDepex/build.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/GenFfsFile/GenFfsFile.c b/Tools/Source/TianoTools/GenFfsFile/GenFfsFile.c new file mode 100644 index 0000000000..0e93a47cc9 --- /dev/null +++ b/Tools/Source/TianoTools/GenFfsFile/GenFfsFile.c @@ -0,0 +1,2645 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenFfsFile.c + +Abstract: + + This file contains functions required to generate a Firmware File System + file. + +--*/ + +#include "Base.h" +#include "UefiBaseTypes.h" +#include "FirmwareVolumeImageFormat.h" +#include "FirmwareFileSystem.h" +#include "FirmwareVolumeHeader.h" +#include "FirmwareVolumeImageFormat.h" +#include "ParseInf.h" +#include "EfiCompress.h" +#include "EfiCustomizedCompress.h" +#include "Crc32.h" +#include "GenFfsFile.h" +#include +#include // for isalpha() +// +// include file for _spawnv +// +#ifndef __GNUC__ +#include +#endif +#include +#include +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +#include "SimpleFileParsing.h" + +#define UTILITY_NAME "GenFfsFile" +#define TOOLVERSION "0.32" +#define MAX_ARRAY_SIZE 100 + +static +INT32 +GetNextLine ( + OUT CHAR8 *Destination, + IN FILE *Package, + IN OUT UINT32 *LineNumber + ); + +static +void +CheckSlash ( + IN OUT CHAR8 *String, + IN FILE *In, + IN OUT UINT32 *LineNumber + ); + +static +INT32 +FindSectionInPackage ( + IN CHAR8 *BuildDirectory, + IN FILE *OverridePackage, + IN OUT UINT32 *LineNumber + ); + +static +STATUS +ProcessCommandLineArgs ( + int Argc, + char *Argv[] + ); + +static +void +PrintUsage ( + void + ); + +// +// Keep globals in this structure +// +static struct { + UINT8 BuildDirectory[_MAX_PATH]; + UINT8 PrimaryPackagePath[_MAX_PATH]; + UINT8 OverridePackagePath[_MAX_PATH]; + BOOLEAN Verbose; +} mGlobals; + +static EFI_GUID mZeroGuid = { 0 }; + +static +void +StripQuotes ( + IN OUT CHAR8 *String + ) +/*++ + +Routine Description: + + Removes quotes and/or whitespace from around a string + +Arguments: + + String - String to remove quotes from + +Returns: + + None + +--*/ +{ + UINTN Index; + UINTN Index2; + UINTN StrLen; + + Index2 = strspn (String, "\" \t\n"); + StrLen = strlen (String); + + for (Index = Index2; String[Index] != '\"', Index < StrLen; Index++) { + String[Index - Index2] = String[Index]; + } + + String[Index - Index2] = 0; +} + +static +void +PrintUsage ( + void + ) +/*++ + +Routine Description: + + Print Error / Help message. + +Arguments: + + void + +Returns: + + None + +--*/ +{ + printf ("Usage:\n"); + printf (UTILITY_NAME " -b \"build directory\" -p1 \"package1.inf\" -p2 \"package2.inf\" -v\n"); + printf (" -b \"build directory\":\n "); + printf (" specifies the full path to the component build directory.\n"); + printf (" -p1 \"P1_path\":\n"); + printf (" specifies fully qualified file name to the primary package file.\n"); + printf (" This file will normally exist in the same directory as the makefile\n"); + printf (" for the component. Required.\n"); + printf (" -p2 \"P2_path\":\n"); + printf (" specifies fully qualified file name to the override package file.\n"); + printf (" This file will normally exist in the build tip. Optional.\n"); +} + +static +INT32 +TestComment ( + IN CHAR8 *String, + IN FILE *In + ) +/*++ + +Routine Description: + + Tests input string to see if it is a comment, and if so goes to the next line in the file that is not a comment + +Arguments: + + String - String to test + + In - Open file to move pointer within + +Returns: + + -1 - End of file reached + 0 - Not a comment + 1 - Comment bypassed + +--*/ +{ + CHAR8 CharBuffer; + + CharBuffer = 0; + if ((String[0] == '/') && (String[1] == '/')) { + while (CharBuffer != '\n') { + fscanf (In, "%c", &CharBuffer); + if (feof (In)) { + return -1; + } + } + } else { + return 0; + } + + return 1; +} + +static +void +BreakString ( + IN CONST CHAR8 *Source, + OUT CHAR8 *Destination, + IN INTN Direction + ) +/*++ + +Routine Description: + + Takes an input string and returns either the part before the =, or the part after the =, depending on direction + +Arguments: + + Source - String to break + + Destination - Buffer to place new string in + + Direction - 0 to return all of source string before = + 1 to return all of source string after = + +Returns: + + None + +--*/ +{ + UINTN Index; + UINTN Index2; + + Index = 0; + Index2 = 0; + + if (strchr (Source, '=') == NULL) { + strcpy (Destination, Source); + + return ; + } + + if (Direction == 0) { + // + // return part of string before = + // + while (Source[Index] != '=') { + Destination[Index] = Source[Index++]; + } + + Destination[Index] = 0; + } else { + // + // return part of string after = + // + strcpy (Destination, strchr (Source, '=') + 1); + } +} + +static +INT32 +GetNextLine ( + OUT CHAR8 *Destination, + IN FILE *Package, + IN OUT UINT32 *LineNumber + ) +/*++ + +Routine Description: + + Gets the next non-commented line from the file + +Arguments: + + Destination - Where to put string + + Package - Package to get string from + + LineNumber - The actual line number. + +Returns: + + -1 - End of file reached + 0 - Success + +--*/ +{ + CHAR8 String[_MAX_PATH]; + fscanf (Package, "%s", &String); + if (feof (Package)) { + return -1; + } + + while (TestComment (String, Package) == 1) { + fscanf (Package, "%s", &String); + if (feof (Package)) { + return -1; + } + } + + strcpy (Destination, String); + return 0; +} + +static +VOID +CheckSlash ( + IN OUT CHAR8 *String, + IN FILE *In, + IN OUT UINT32 *LineNumber + ) +/*++ + +Routine Description: + + Checks to see if string is line continuation character, if so goes to next valid line + +Arguments: + + String - String to test + + In - Open file to move pointer within + + LineNumber - The line number. + +Returns: + + None + +--*/ +{ + CHAR8 ByteBuffer; + ByteBuffer = 0; + + switch (String[0]) { + + case '\\': + while (String[0] == '\\') { + while (ByteBuffer != '\n') { + fscanf (In, "%c", &ByteBuffer); + } + (*LineNumber)++; + if (GetNextLine (String, In, LineNumber) == -1) { + return ; + } + } + break; + + case '\n': + (*LineNumber)++; + while (String[0] == '\n') { + if (GetNextLine (String, In, LineNumber) == -1) { + return ; + } + } + break; + + default: + break; + + } + +} + +static +INT32 +FindSectionInPackage ( + IN CHAR8 *BuildDirectory, + IN FILE *OverridePackage, + IN OUT UINT32 *LineNumber + ) +/*++ + +Routine Description: + + Finds the matching section within the package + +Arguments: + + BuildDirectory - name of section to find + + OverridePackage - Package file to search within + + LineNumber - The line number. + +Returns: + + -1 - End of file reached + 0 - Success + +--*/ +{ + CHAR8 String[_MAX_PATH]; + CHAR8 NewString[_MAX_PATH]; + String[0] = 0; + + while (strcmp (BuildDirectory, String) != 0) { + if (GetNextLine (NewString, OverridePackage, LineNumber) != 0) { + return -1; + } + + if (NewString[0] == '[') { + if (NewString[strlen (NewString) - 1] != ']') { + // + // have to construct string. + // + strcpy (String, NewString + 1); + + while (1) { + fscanf (OverridePackage, "%s", &NewString); + if (feof (OverridePackage)) { + return -1; + } + + if (NewString[0] != ']') { + if (strlen (String) != 0) { + strcat (String, " "); + } + + strcat (String, NewString); + if (String[strlen (String) - 1] == ']') { + String[strlen (String) - 1] = 0; + break; + } + } else { + break; + } + } + } else { + NewString[strlen (NewString) - 1] = 0; + strcpy (String, NewString + 1); + } + } + } + + return 0; +} + +static +EFI_STATUS +GenSimpleGuidSection ( + IN OUT UINT8 *FileBuffer, + IN OUT UINT32 *BufferSize, + IN UINT32 DataSize, + IN EFI_GUID SignGuid, + IN UINT16 GuidedSectionAttributes + ) +/*++ + +Routine Description: + + add GUIDed section header for the data buffer. + data stays in same location (overwrites source data). + +Arguments: + + FileBuffer - Buffer containing data to sign + + BufferSize - On input, the size of FileBuffer. On output, the size of + actual section data (including added section header). + + DataSize - Length of data to Sign + + SignGuid - Guid to be add. + + GuidedSectionAttributes - The section attribute. + +Returns: + + EFI_SUCCESS - Successful + EFI_OUT_OF_RESOURCES - Not enough resource. + +--*/ +{ + UINT32 TotalSize; + + EFI_GUID_DEFINED_SECTION GuidSectionHeader; + UINT8 *SwapBuffer; + + SwapBuffer = NULL; + + if (DataSize == 0) { + *BufferSize = 0; + + return EFI_SUCCESS; + } + + TotalSize = DataSize + sizeof (EFI_GUID_DEFINED_SECTION); + GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED; + GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff); + GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8); + GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16); + memcpy (&(GuidSectionHeader.SectionDefinitionGuid), &SignGuid, sizeof (EFI_GUID)); + GuidSectionHeader.Attributes = GuidedSectionAttributes; + GuidSectionHeader.DataOffset = sizeof (EFI_GUID_DEFINED_SECTION); + + SwapBuffer = (UINT8 *) malloc (DataSize); + if (SwapBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + memcpy (SwapBuffer, FileBuffer, DataSize); + memcpy (FileBuffer, &GuidSectionHeader, sizeof (EFI_GUID_DEFINED_SECTION)); + memcpy (FileBuffer + sizeof (EFI_GUID_DEFINED_SECTION), SwapBuffer, DataSize); + + // + // Make sure section ends on a DWORD boundary + // + while ((TotalSize & 0x03) != 0) { + FileBuffer[TotalSize] = 0; + TotalSize++; + } + + *BufferSize = TotalSize; + + if (SwapBuffer != NULL) { + free (SwapBuffer); + } + + return EFI_SUCCESS; +} + +static +EFI_STATUS +CompressSection ( + UINT8 *FileBuffer, + UINT32 *BufferSize, + UINT32 DataSize, + CHAR8 *Type + ) +/*++ + +Routine Description: + + Compress the data and add section header for the compressed data. + Compressed data (with section header) stays in same location as the source + (overwrites source data). + +Arguments: + + FileBuffer - Buffer containing data to Compress + + BufferSize - On input, the size of FileBuffer. On output, the size of + actual compressed data (including added section header). + When buffer is too small, this value indicates the size needed. + + DataSize - The size of data to compress + + Type - The compression type (not used currently). + Assume EFI_HEAVY_COMPRESSION. + +Returns: + + EFI_BUFFER_TOO_SMALL - Buffer size is too small. + EFI_UNSUPPORTED - Compress type can not be supported. + EFI_SUCCESS - Successful + EFI_OUT_OF_RESOURCES - Not enough resource. + +--*/ +{ + EFI_STATUS Status; + UINT8 *CompData; + UINT32 CompSize; + UINT32 TotalSize; + EFI_COMPRESSION_SECTION CompressionSet; + UINT8 CompressionType; + COMPRESS_FUNCTION CompressFunction; + + Status = EFI_SUCCESS; + CompData = NULL; + CompSize = 0; + TotalSize = 0; + CompressFunction = NULL; + + // + // Get the compress type + // + if (strcmpi (Type, "Dummy") == 0) { + // + // Added "Dummy" to keep backward compatibility. + // + CompressionType = EFI_STANDARD_COMPRESSION; + CompressFunction = (COMPRESS_FUNCTION) Compress; + + } else if (strcmpi (Type, "LZH") == 0) { + // + // EFI stardard compression (LZH) + // + CompressionType = EFI_STANDARD_COMPRESSION; + CompressFunction = (COMPRESS_FUNCTION) Compress; + + } else { + // + // Customized compression + // + Status = SetCustomizedCompressionType (Type); + if (EFI_ERROR (Status)) { + return Status; + } + + CompressionType = EFI_CUSTOMIZED_COMPRESSION; + CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress; + } + // + // Compress the raw data + // + Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize); + if (Status == EFI_BUFFER_TOO_SMALL) { + CompData = malloc (CompSize); + if (!CompData) { + return EFI_OUT_OF_RESOURCES; + } + + Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize); + } + + if (EFI_ERROR (Status)) { + if (CompData != NULL) { + free (CompData); + } + + return Status; + } + + TotalSize = CompSize + sizeof (EFI_COMPRESSION_SECTION); + + // + // Buffer too small? + // + if (TotalSize > *BufferSize) { + *BufferSize = TotalSize; + if (CompData != NULL) { + free (CompData); + } + + return EFI_BUFFER_TOO_SMALL; + } + // + // Add the section header for the compressed data + // + CompressionSet.CommonHeader.Type = EFI_SECTION_COMPRESSION; + CompressionSet.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff); + CompressionSet.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8); + CompressionSet.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16); + CompressionSet.CompressionType = CompressionType; + CompressionSet.UncompressedLength = DataSize; + + // + // Copy header and data to the buffer + // + memcpy (FileBuffer, &CompressionSet, sizeof (EFI_COMPRESSION_SECTION)); + memcpy (FileBuffer + sizeof (CompressionSet), CompData, CompSize); + + // + // Make sure section ends on a DWORD boundary + // + while ((TotalSize & 0x03) != 0) { + FileBuffer[TotalSize] = 0; + TotalSize++; + } + + *BufferSize = TotalSize; + + if (CompData != NULL) { + free (CompData); + } + + return EFI_SUCCESS; +} + +static +void +StripParens ( + IN OUT CHAR8 *String + ) +/*++ + +Routine Description: + + Removes Parenthesis from around a string + +Arguments: + + String - String to remove parens from + +Returns: + + None + +--*/ +{ + INT32 Index; + + if (String[0] != '(') { + return ; + } + + for (Index = 1; String[Index] != ')'; Index++) { + String[Index - 1] = String[Index]; + if (String[Index] == 0) { + return ; + } + } + + String[Index - 1] = 0; + + return ; +} + +static +void +StripEqualMark ( + IN OUT CHAR8 *String + ) +/*++ + +Routine Description: + + Removes Equal Mark from around a string + +Arguments: + + String - String to remove equal mark from + +Returns: + + None + +--*/ +{ + INT32 Index; + + if (String[0] != '=' && String[strlen (String) - 1] != '=') { + return ; + } + + if (String[0] == '=') { + + for (Index = 1; String[Index] != 0; Index++) { + String[Index - 1] = String[Index]; + } + + String[Index - 1] = 0; + } + + if (String[strlen (String) - 1] == '=') { + String[strlen (String) - 1] = 0; + } + + return ; +} + +static +INT32 +ProcessEnvironmentVariable ( + IN CHAR8 *Buffer, + OUT CHAR8 *NewBuffer + ) +/*++ + +Routine Description: + + Converts environment variables to values + +Arguments: + + Buffer - Buffer containing Environment Variable String + + NewBuffer - Buffer containing value of environment variable + + +Returns: + + Number of characters from Buffer used + +--*/ +{ + INT32 Index; + INT32 Index2; + CHAR8 VariableBuffer[_MAX_PATH]; + + Index = 2; + Index2 = 0; + + while (Buffer[Index] != ')') { + VariableBuffer[Index - 2] = Buffer[Index++]; + } + + VariableBuffer[Index - 2] = 0; + Index++; + + if (getenv (VariableBuffer) != NULL) { + strcpy (NewBuffer, getenv (VariableBuffer)); + } else { + printf ("Environment variable %s not found!\n", VariableBuffer); + } + + return Index; +} + +static +void +SplitAttributesField ( + IN CHAR8 *Buffer, + IN CHAR8 *AttributesArray[], + IN OUT UINT32 *NumberOfAttributes + ) +/* + NumberOfAttributes: on input, it specifies the current number of attributes + stored in AttributeArray. + on output, it is updated to the latest number of attributes + stored in AttributesArray. +*/ +{ + UINT32 Index; + UINT32 Index2; + UINT32 z; + CHAR8 *CharBuffer; + + CharBuffer = NULL; + CharBuffer = (CHAR8 *) malloc (_MAX_PATH); + ZeroMem (CharBuffer, _MAX_PATH); + + for (Index = 0, z = 0, Index2 = 0; Index < strlen (Buffer); Index++) { + + if (Buffer[Index] != '|') { + CharBuffer[z] = Buffer[Index]; + z++; + } else { + + CharBuffer[z] = 0; + AttributesArray[*NumberOfAttributes + Index2] = CharBuffer; + Index2++; + + // + // allocate new char buffer for the next attributes string + // + CharBuffer = (CHAR8 *) malloc (_MAX_PATH); + ZeroMem (CharBuffer, _MAX_PATH); + z = 0; + } + } + + CharBuffer[z] = 0; + // + // record the last attributes string in the Buffer + // + AttributesArray[*NumberOfAttributes + Index2] = CharBuffer; + Index2++; + + *NumberOfAttributes += Index2; + + return ; +} + +static +INT32 +GetToolArguments ( + CHAR8 *ToolArgumentsArray[], + FILE *Package, + CHAR8 **PtrInputFileName, + CHAR8 **PtrOutputFileName, + EFI_GUID *Guid, + UINT16 *GuidedSectionAttributes + ) +{ + CHAR8 Buffer[_MAX_PATH]; + BOOLEAN ArgumentsFlag; + BOOLEAN InputFlag; + BOOLEAN OutputFlag; + BOOLEAN GuidFlag; + BOOLEAN AttributesFlag; + UINT32 argc; + UINT32 Index2; + UINT32 z; + CHAR8 *CharBuffer; + INT32 Index; + INT32 ReturnValue; + EFI_STATUS Status; + + CHAR8 *AttributesArray[MAX_ARRAY_SIZE]; + UINT32 NumberOfAttributes; + CHAR8 *InputFileName; + CHAR8 *OutputFileName; + UINT32 LineNumber; + Buffer[_MAX_PATH]; + + ArgumentsFlag = FALSE; + InputFlag = FALSE; + OutputFlag = FALSE; + GuidFlag = FALSE; + AttributesFlag = FALSE; + // + // Start at 1, since ToolArgumentsArray[0] + // is the program name. + // + argc = 1; + Index2 = 0; + + z = 0; + ReturnValue = 0; + NumberOfAttributes = 0; + InputFileName = NULL; + OutputFileName = NULL; + + ZeroMem (Buffer, _MAX_PATH); + ZeroMem (AttributesArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE); + LineNumber = 0; + while (Buffer[0] != ')') { + + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + StripEqualMark (Buffer); + } else { + Error (NULL, 0, 0, "failed to get next line from package file", NULL); + return -1; + } + + if (Buffer[0] == ')') { + break; + } else if (strcmpi (Buffer, "ARGS") == 0) { + + ArgumentsFlag = TRUE; + AttributesFlag = FALSE; + continue; + + } else if (strcmpi (Buffer, "INPUT") == 0) { + + InputFlag = TRUE; + ArgumentsFlag = FALSE; + AttributesFlag = FALSE; + continue; + + } else if (strcmpi (Buffer, "OUTPUT") == 0) { + + OutputFlag = TRUE; + ArgumentsFlag = FALSE; + AttributesFlag = FALSE; + continue; + + } else if (strcmpi (Buffer, "GUID") == 0) { + + GuidFlag = TRUE; + ArgumentsFlag = FALSE; + AttributesFlag = FALSE; + // + // fetch the GUID for the section + // + continue; + + } else if (strcmpi (Buffer, "ATTRIBUTES") == 0) { + + AttributesFlag = TRUE; + ArgumentsFlag = FALSE; + // + // fetch the GUIDed Section's Attributes + // + continue; + + } else if (strcmpi (Buffer, "") == 0) { + continue; + } + // + // get all command arguments into ToolArgumentsArray + // + if (ArgumentsFlag) { + + StripEqualMark (Buffer); + + CharBuffer = (CHAR8 *) malloc (_MAX_PATH); + if (CharBuffer == NULL) { + goto ErrorExit; + } + + ZeroMem (CharBuffer, sizeof (_MAX_PATH)); + + ToolArgumentsArray[argc] = CharBuffer; + + if (Buffer[0] == '$') { + Index = ProcessEnvironmentVariable (&Buffer[0], ToolArgumentsArray[argc]); + // + // if there is string after the environment variable, cat it. + // + if ((UINT32) Index < strlen (Buffer)) { + strcat (ToolArgumentsArray[argc], &Buffer[Index]); + } + } else { + strcpy (ToolArgumentsArray[argc], Buffer); + } + + argc += 1; + ToolArgumentsArray[argc] = NULL; + continue; + } + + if (InputFlag) { + + StripEqualMark (Buffer); + + InputFileName = (CHAR8 *) malloc (_MAX_PATH); + if (InputFileName == NULL) { + goto ErrorExit; + } + + ZeroMem (InputFileName, sizeof (_MAX_PATH)); + + if (Buffer[0] == '$') { + Index = ProcessEnvironmentVariable (&Buffer[0], InputFileName); + // + // if there is string after the environment variable, cat it. + // + if ((UINT32) Index < strlen (Buffer)) { + strcat (InputFileName, &Buffer[Index]); + } + } else { + strcpy (InputFileName, Buffer); + } + + InputFlag = FALSE; + continue; + } + + if (OutputFlag) { + + StripEqualMark (Buffer); + + OutputFileName = (CHAR8 *) malloc (_MAX_PATH); + if (OutputFileName == NULL) { + goto ErrorExit; + } + + ZeroMem (OutputFileName, sizeof (_MAX_PATH)); + + if (Buffer[0] == '$') { + Index = ProcessEnvironmentVariable (&Buffer[0], OutputFileName); + // + // if there is string after the environment variable, cat it. + // + if ((UINT32) Index < strlen (Buffer)) { + strcat (OutputFileName, &Buffer[Index]); + } + } else { + strcpy (OutputFileName, Buffer); + } + + OutputFlag = FALSE; + continue; + } + + if (GuidFlag) { + + StripEqualMark (Buffer); + + Status = StringToGuid (Buffer, Guid); + if (EFI_ERROR (Status)) { + ReturnValue = -1; + goto ErrorExit; + } + + GuidFlag = FALSE; + } + + if (AttributesFlag) { + + StripEqualMark (Buffer); + + // + // there might be no space between each attribute in the statement, + // split them aside and return each attribute string + // in the AttributesArray + // + SplitAttributesField (Buffer, AttributesArray, &NumberOfAttributes); + } + } + // + // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j); + // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1); + // + for (z = 0; z < NumberOfAttributes; z++) { + if (strcmpi (AttributesArray[z], "PROCESSING_REQUIRED") == 0) { + *GuidedSectionAttributes |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED; + } else if (strcmpi (AttributesArray[z], "AUTH_STATUS_VALID") == 0) { + *GuidedSectionAttributes |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + } + } + +ErrorExit: + + for (Index2 = 0; Index2 < MAX_ARRAY_SIZE; Index2++) { + if (AttributesArray[Index2] == NULL) { + break; + } + + free (AttributesArray[Index2]); + } + + *PtrInputFileName = InputFileName; + *PtrOutputFileName = OutputFileName; + + return ReturnValue; +} + +static +INT32 +ProcessScript ( + IN OUT UINT8 *FileBuffer, + IN FILE *Package, + IN CHAR8 *BuildDirectory, + IN BOOLEAN ForceUncompress + ) +/*++ + +Routine Description: + + Signs the section, data stays in same location + +Arguments: + + FileBuffer - Data Buffer + + Package - Points to curly brace in Image Script + + BuildDirectory - Name of the source directory parameter + + ForceUncompress - Whether to force uncompress. + +Returns: + + Number of bytes added to file buffer + -1 on error + +--*/ +{ + EFI_STATUS Status; + UINT32 Size; + CHAR8 Buffer[_MAX_PATH]; + CHAR8 Type[_MAX_PATH]; + CHAR8 FileName[_MAX_PATH]; + CHAR8 NewBuffer[_MAX_PATH]; + INT32 Index3; + INT32 Index2; + UINT32 ReturnValue; + UINT8 ByteBuffer; + FILE *InFile; + UINT32 SourceDataSize; + CHAR8 *ToolArgumentsArray[MAX_ARRAY_SIZE]; + CHAR8 *OutputFileName; + CHAR8 *InputFileName; + CHAR8 ToolName[_MAX_PATH]; + FILE *OutputFile; + FILE *InputFile; + UINT8 Temp; + int returnint; + INT32 Index; + UINT32 LineNumber; + BOOLEAN IsError; + EFI_GUID SignGuid; + UINT16 GuidedSectionAttributes; + UINT8 *TargetFileBuffer; + + OutputFileName = NULL; + InputFileName = NULL; + OutputFile = NULL; + InputFile = NULL; + IsError = FALSE; + GuidedSectionAttributes = 0; + TargetFileBuffer = NULL; + + Size = 0; + LineNumber = 0; + Buffer[0] = 0; + for (Index3 = 0; Index3 < MAX_ARRAY_SIZE; ++Index3) { + ToolArgumentsArray[Index3] = NULL; + } + + while (Buffer[0] != '}') { + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + } else { + printf ("ERROR in IMAGE SCRIPT!\n"); + IsError = TRUE; + goto Done; + } + + if (strcmpi (Buffer, "Compress") == 0) { + // + // Handle compress + // + // + // read compression type + // + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + } + + StripParens (Buffer); + if (Buffer[0] == '$') { + ProcessEnvironmentVariable (&Buffer[0], Type); + } else { + strcpy (Type, Buffer); + } + // + // build buffer + // + while (Buffer[0] != '{') { + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + } + } + + ReturnValue = ProcessScript (&FileBuffer[Size], Package, BuildDirectory, ForceUncompress); + if (ReturnValue == -1) { + IsError = TRUE; + goto Done; + } + // + // Call compress routine on buffer. + // Occasionally, compressed data + section header would + // be largere than the source and EFI_BUFFER_TOO_SMALL is + // returned from CompressSection() + // + SourceDataSize = ReturnValue; + + if (!ForceUncompress) { + + Status = CompressSection ( + &FileBuffer[Size], + &ReturnValue, + SourceDataSize, + Type + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + Status = CompressSection ( + &FileBuffer[Size], + &ReturnValue, + SourceDataSize, + Type + ); + } + + if (EFI_ERROR (Status)) { + IsError = TRUE; + goto Done; + } + } + + Size += ReturnValue; + + } else if (strcmpi (Buffer, "Tool") == 0) { + + ZeroMem (ToolName, _MAX_PATH); + ZeroMem (ToolArgumentsArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE); + ZeroMem (&SignGuid, sizeof (EFI_GUID)); + + // + // handle signing Tool + // + while (Buffer[0] != '(') { + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + } + } + + if (strcmpi (Buffer, "(") == 0) { + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + } + } + + StripParens (Buffer); + + if (Buffer[0] == '$') { + Index = ProcessEnvironmentVariable (&Buffer[0], ToolName); + // + // if there is string after the environment variable, cat it. + // + if ((UINT32) Index < strlen (Buffer)) { + strcat (ToolName, &Buffer[Index]); + } + } else { + strcpy (ToolName, Buffer); + } + + ToolArgumentsArray[0] = ToolName; + + // + // read ARGS + // + if (GetToolArguments ( + ToolArgumentsArray, + Package, + &InputFileName, + &OutputFileName, + &SignGuid, + &GuidedSectionAttributes + ) == -1) { + IsError = TRUE; + goto Done; + } + // + // if the tool need input file, + // dump the file buffer to the specified input file. + // + if (InputFileName != NULL) { + InputFile = fopen (InputFileName, "wb"); + if (InputFile == NULL) { + Error (NULL, 0, 0, InputFileName, "failed to open output file for writing"); + IsError = TRUE; + goto Done; + } + + fwrite (FileBuffer, sizeof (UINT8), Size, InputFile); + fclose (InputFile); + InputFile = NULL; + free (InputFileName); + InputFileName = NULL; + } + // + // dispatch signing tool + // +#ifdef __GNUC__ + { + char CommandLine[1000]; + sprintf(CommandLine, "%s %s", ToolName, ToolArgumentsArray); + returnint = system(CommandLine); + } +#else + returnint = _spawnv (_P_WAIT, ToolName, ToolArgumentsArray); +#endif + if (returnint != 0) { + Error (NULL, 0, 0, ToolName, "external tool failed"); + IsError = TRUE; + goto Done; + } + // + // if the tool has output file, + // dump the output file to the file buffer + // + if (OutputFileName != NULL) { + + OutputFile = fopen (OutputFileName, "rb"); + if (OutputFile == NULL) { + Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing"); + IsError = TRUE; + goto Done; + } + + TargetFileBuffer = &FileBuffer[Size]; + SourceDataSize = Size; + + fread (&Temp, sizeof (UINT8), 1, OutputFile); + while (!feof (OutputFile)) { + FileBuffer[Size++] = Temp; + fread (&Temp, sizeof (UINT8), 1, OutputFile); + } + + while ((Size & 0x03) != 0) { + FileBuffer[Size] = 0; + Size++; + } + + SourceDataSize = Size - SourceDataSize; + + fclose (OutputFile); + OutputFile = NULL; + free (OutputFileName); + OutputFileName = NULL; + + if (CompareGuid (&SignGuid, &mZeroGuid) != 0) { + ReturnValue = SourceDataSize; + Status = GenSimpleGuidSection ( + TargetFileBuffer, + &ReturnValue, + SourceDataSize, + SignGuid, + GuidedSectionAttributes + ); + if (EFI_ERROR (Status)) { + IsError = TRUE; + goto Done; + } + + Size = ReturnValue; + } + } + + } else if (Buffer[0] != '}') { + // + // if we are here, we should see either a file name, + // or a }. + // + Index3 = 0; + FileName[0] = 0; + // + // Prepend the build directory to the file name if the + // file name does not already contain a full path. + // + if (!isalpha (Buffer[0]) || (Buffer[1] != ':')) { + sprintf (FileName, "%s\\", BuildDirectory); + } + + while (Buffer[Index3] != '\n') { + if (Buffer[Index3] == '$') { + Index3 += ProcessEnvironmentVariable (&Buffer[Index3], NewBuffer); + strcat (FileName, NewBuffer); + } + + if (Buffer[Index3] == 0) { + break; + } else { + Index2 = strlen (FileName); + FileName[Index2++] = Buffer[Index3++]; + FileName[Index2] = 0; + } + } + + InFile = fopen (FileName, "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0, FileName, "failed to open file for reading"); + IsError = TRUE; + goto Done; + } + + fread (&ByteBuffer, sizeof (UINT8), 1, InFile); + while (!feof (InFile)) { + FileBuffer[Size++] = ByteBuffer; + fread (&ByteBuffer, sizeof (UINT8), 1, InFile); + } + + fclose (InFile); + InFile = NULL; + + // + // Make sure section ends on a DWORD boundary + // + while ((Size & 0x03) != 0) { + FileBuffer[Size] = 0; + Size++; + } + + } + } + +Done: + for (Index3 = 1; Index3 < MAX_ARRAY_SIZE; Index3++) { + if (ToolArgumentsArray[Index3] == NULL) { + break; + } + + free (ToolArgumentsArray[Index3]); + } + + if (IsError) { + return -1; + } + + return Size; + +} + +static +UINT8 +StringToType ( + IN CHAR8 *String + ) +/*++ + +Routine Description: + + Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an + unrecognized file type was specified. + +Arguments: + + String - File type string + +Returns: + + File Type Value + +--*/ +{ + if (strcmpi (String, "EFI_FV_FILETYPE_RAW") == 0) { + return EFI_FV_FILETYPE_RAW; + } + + if (strcmpi (String, "EFI_FV_FILETYPE_FREEFORM") == 0) { + return EFI_FV_FILETYPE_FREEFORM; + } + + if (strcmpi (String, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) { + return EFI_FV_FILETYPE_SECURITY_CORE; + } + + if (strcmpi (String, "EFI_FV_FILETYPE_PEI_CORE") == 0) { + return EFI_FV_FILETYPE_PEI_CORE; + } + + if (strcmpi (String, "EFI_FV_FILETYPE_DXE_CORE") == 0) { + return EFI_FV_FILETYPE_DXE_CORE; + } + + if (strcmpi (String, "EFI_FV_FILETYPE_PEIM") == 0) { + return EFI_FV_FILETYPE_PEIM; + } + + if (strcmpi (String, "EFI_FV_FILETYPE_DRIVER") == 0) { + return EFI_FV_FILETYPE_DRIVER; + } + + if (strcmpi (String, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) { + return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER; + } + + if (strcmpi (String, "EFI_FV_FILETYPE_APPLICATION") == 0) { + return EFI_FV_FILETYPE_APPLICATION; + } + + if (strcmpi (String, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) { + return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE; + } + + return EFI_FV_FILETYPE_ALL; +} + +static +UINT32 +AdjustFileSize ( + IN UINT8 *FileBuffer, + IN UINT32 FileSize + ) +/*++ + +Routine Description: + Adjusts file size to insure sectioned file is exactly the right length such + that it ends on exactly the last byte of the last section. ProcessScript() + may have padded beyond the end of the last section out to a 4 byte boundary. + This padding is stripped. + +Arguments: + FileBuffer - Data Buffer - contains a section stream + FileSize - Size of FileBuffer as returned from ProcessScript() + +Returns: + Corrected size of file. + +--*/ +{ + UINT32 TotalLength; + UINT32 CurrentLength; + UINT32 SectionLength; + UINT32 SectionStreamLength; + EFI_COMMON_SECTION_HEADER *SectionHeader; + EFI_COMMON_SECTION_HEADER *NextSectionHeader; + + TotalLength = 0; + CurrentLength = 0; + SectionStreamLength = FileSize; + + SectionHeader = (EFI_COMMON_SECTION_HEADER *) FileBuffer; + + while (TotalLength < SectionStreamLength) { + SectionLength = *((UINT32 *) SectionHeader->Size) & 0x00ffffff; + TotalLength += SectionLength; + + if (TotalLength == SectionStreamLength) { + return TotalLength; + } + // + // Move to the next byte following the section... + // + SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength); + CurrentLength = (UINTN) SectionHeader - (UINTN) FileBuffer; + + // + // Figure out where the next section begins + // + NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + 3); + NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader &~ (UINTN) 3); + TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader; + SectionHeader = NextSectionHeader; + } + + return CurrentLength; +} + +static +INT32 +MainEntry ( + INT32 argc, + CHAR8 *argv[], + BOOLEAN ForceUncompress + ) +/*++ + +Routine Description: + + MainEntry function. + +Arguments: + + argc - Number of command line parameters. + argv - Array of pointers to command line parameter strings. + ForceUncompress - If TRUE, force to do not compress the sections even if compression + is specified in the script. Otherwise, FALSE. + +Returns: + STATUS_SUCCESS - Function exits successfully. + STATUS_ERROR - Some error occurred during execution. + +--*/ +{ + FILE *PrimaryPackage; + FILE *OverridePackage; + FILE *Out; + CHAR8 BaseName[_MAX_PATH]; + EFI_GUID FfsGuid; + CHAR8 GuidString[_MAX_PATH]; + EFI_FFS_FILE_HEADER FileHeader; + CHAR8 FileType[_MAX_PATH]; + EFI_FFS_FILE_ATTRIBUTES FfsAttrib; + EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined; + UINT64 FfsAlignment; + UINT32 FfsAlignment32; + CHAR8 InputString[_MAX_PATH]; + BOOLEAN ImageScriptInOveride; + UINT32 FileSize; + UINT8 *FileBuffer; + EFI_STATUS Status; + UINT32 LineNumber; + EFI_FFS_FILE_TAIL TailValue; + + BaseName[0] = 0; + FileType[0] = 0; + FfsAttrib = 0; + FfsAttribDefined = 0; + FfsAlignment = 0; + FfsAlignment32 = 0; + PrimaryPackage = NULL; + Out = NULL; + OverridePackage = NULL; + FileBuffer = NULL; + + strcpy (GuidString, "00000000-0000-0000-0000-000000000000"); + Status = StringToGuid (GuidString, &FfsGuid); + if (Status != 0) { + Error (NULL, 0, 0, GuidString, "error parsing GUID string"); + return STATUS_ERROR; + } + + GuidString[0] = 0; + ImageScriptInOveride = FALSE; + // + // Initialize the simple file parsing routines. Then open + // the primary package file for parsing. + // + SFPInit (); + if (SFPOpenFile (mGlobals.PrimaryPackagePath) != STATUS_SUCCESS) { + Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file"); + goto Done; + } + // + // First token in the file must be "PACKAGE.INF" + // + if (!SFPIsToken ("PACKAGE.INF")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL); + goto Done; + } + // + // Find the [.] section + // + if (!SFPSkipToToken ("[.]")) { + Error (mGlobals.PrimaryPackagePath, 1, 0, "could not locate [.] section in package file", NULL); + goto Done; + } + // + // Start parsing the data. The algorithm is essentially the same for each keyword: + // 1. Identify the keyword + // 2. Verify that the keyword/value pair has not already been defined + // 3. Set some flag indicating that the keyword/value pair has been defined + // 4. Skip over the "=" + // 5. Get the value, which may be a number, TRUE, FALSE, or a string. + // + while (1) { + if (SFPIsToken ("BASE_NAME")) { + // + // Found BASE_NAME, format: + // BASE_NAME = MyBaseName + // + if (BaseName[0] != 0) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL); + goto Done; + } + + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (!SFPGetNextToken (BaseName, sizeof (BaseName))) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid base name", NULL); + goto Done; + } + } else if (SFPIsToken ("IMAGE_SCRIPT")) { + // + // Found IMAGE_SCRIPT. Break out and process below. + // + break; + } else if (SFPIsToken ("FFS_FILEGUID")) { + // + // found FILEGUID, format: + // FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A + // + if (GuidString[0] != 0) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL); + goto Done; + } + + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPGetGuidToken (GuidString, sizeof (GuidString)) != TRUE) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected file GUID", NULL); + goto Done; + } + + Status = StringToGuid (GuidString, &FfsGuid); + if (Status != 0) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid file GUID", NULL); + goto Done; + } + } else if (SFPIsToken ("FFS_FILETYPE")) { + // + // *********************************************************************** + // + // Found FFS_FILETYPE, format: + // FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION + // + if (FileType[0] != 0) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL); + goto Done; + } + + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (!SFPGetNextToken (FileType, sizeof (FileType))) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL); + goto Done; + } + } else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) { + // + // *********************************************************************** + // + // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE + // Spec says the bit is for future expansion, and must be false. + // + if (FfsAttribDefined & FFS_ATTRIB_HEADER_EXTENSION) { + Error ( + mGlobals.PrimaryPackagePath, + SFPGetLineNumber (), + 0, + "FFS_ATTRIB_HEADER_EXTENSION previously defined", + NULL + ); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_HEADER_EXTENSION; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPIsToken ("TRUE")) { + Error ( + mGlobals.PrimaryPackagePath, + SFPGetLineNumber (), + 0, + "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported", + NULL + ); + goto Done; + } else if (SFPIsToken ("FALSE")) { + // + // Default is FALSE + // + } else { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL); + goto Done; + } + } else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) { + // + // *********************************************************************** + // + // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE + // + if (FfsAttribDefined & FFS_ATTRIB_TAIL_PRESENT) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_TAIL_PRESENT; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPIsToken ("TRUE")) { + FfsAttrib |= FFS_ATTRIB_TAIL_PRESENT; + } else if (SFPIsToken ("FALSE")) { + // + // Default is FALSE + // + } else { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL); + goto Done; + } + } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) { + // + // *********************************************************************** + // + // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE + // + if (FfsAttribDefined & FFS_ATTRIB_RECOVERY) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_RECOVERY; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPIsToken ("TRUE")) { + FfsAttrib |= FFS_ATTRIB_RECOVERY; + } else if (SFPIsToken ("FALSE")) { + // + // Default is FALSE + // + } else { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL); + goto Done; + } + } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) { + // + // *********************************************************************** + // + // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE + // + if (FfsAttribDefined & FFS_ATTRIB_CHECKSUM) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_CHECKSUM; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPIsToken ("TRUE")) { + FfsAttrib |= FFS_ATTRIB_CHECKSUM; + } else if (SFPIsToken ("FALSE")) { + // + // Default is FALSE + // + } else { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL); + goto Done; + } + } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) { + // + // *********************************************************************** + // + // Found FFS_ALIGNMENT, formats: + // FFS_ALIGNMENT = 0-7 + // FFS_ATTRIB_DATA_ALIGNMENT = 0-7 + // + if (FfsAttribDefined & FFS_ATTRIB_DATA_ALIGNMENT) { + Error ( + mGlobals.PrimaryPackagePath, + SFPGetLineNumber (), + 0, + "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined", + NULL + ); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_DATA_ALIGNMENT; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (!SFPGetNumber (&FfsAlignment32)) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL); + goto Done; + } + + if (FfsAlignment32 > 7) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL); + goto Done; + } + + FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment32) << 3); + } else { + SFPGetNextToken (InputString, sizeof (InputString)); + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, InputString, "unrecognized/unexpected token"); + goto Done; + } + } + // + // Close the primary package file + // + SFPCloseFile (); + // + // TODO: replace code below with basically a copy of the code above. Don't + // forget to reset the FfsAttribDefined variable first. Also, you'll need + // to somehow keep track of whether or not the basename is defined multiple + // times in the override package. Ditto on the file GUID. + // + if (mGlobals.OverridePackagePath[0] != 0) { + OverridePackage = fopen (mGlobals.OverridePackagePath, "r"); + // + // NOTE: For package override to work correctly, the code below must be modified to + // SET or CLEAR bits properly. For example, if the primary package set + // FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then + // we'd need to clear the bit below. Since this is not happening, I'm guessing that + // the override functionality is not being used, so should be made obsolete. If I'm + // wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is + // used, and we'll address it then. 4/10/2003 + // + Error (__FILE__, __LINE__, 0, "package override functionality is not implemented correctly", NULL); + goto Done; + } else { + OverridePackage = NULL; + } + +#ifdef OVERRIDE_SUPPORTED + if (OverridePackage != NULL) { + // + // Parse override package file + // + fscanf (OverridePackage, "%s", &InputString); + if (strcmpi (InputString, "PACKAGE.INF") != 0) { + Error (mGlobals.OverridePackagePath, 1, 0, "invalid package file", "expected 'PACKAGE.INF'"); + goto Done; + } + // + // Match [dir] to Build Directory + // + if (FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber) != 0) { + Error (mGlobals.OverridePackagePath, 1, 0, mGlobals.BuildDirectory, "section not found in package file"); + goto Done; + } + + InputString[0] = 0; + while ((InputString[0] != '[') && (!feof (OverridePackage))) { + if (GetNextLine (InputString, OverridePackage, &LineNumber) != -1) { + if (InputString[0] != '[') { +here: + if (strcmpi (InputString, "BASE_NAME") == 0) { + // + // found BASE_NAME, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + strcpy (BaseName, InputString); + } else { + BreakString (InputString, InputString, 1); + strcpy (BaseName, InputString); + } + } else if (strcmpi (InputString, "IMAGE_SCRIPT") == 0) { + // + // found IMAGE_SCRIPT, come back later to process it + // + ImageScriptInOveride = TRUE; + fscanf (OverridePackage, "%s", &InputString); + } else if (strcmpi (InputString, "FFS_FILEGUID") == 0) { + // + // found FILEGUID, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + Status = StringToGuid (InputString, &FfsGuid); + if (Status != 0) { + Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format"); + goto Done; + } + } else { + BreakString (InputString, InputString, 1); + Status = StringToGuid (InputString, &FfsGuid); + if (Status != 0) { + Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format"); + goto Done; + } + } + } else if (strcmpi (InputString, "FFS_FILETYPE") == 0) { + // + // found FILETYPE, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + strcpy (FileType, InputString); + } else { + BreakString (InputString, InputString, 1); + strcpy (FileType, InputString); + } + + } else if (strcmpi (InputString, "FFS_ATTRIB_RECOVERY") == 0) { + // + // found FFS_ATTRIB_RECOVERY, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strcmpi (InputString, "TRUE") == 0) { + FfsAttrib |= FFS_ATTRIB_RECOVERY; + } + } else { + BreakString (InputString, InputString, 1); + if (strcmpi (InputString, "TRUE") == 0) { + FfsAttrib |= FFS_ATTRIB_RECOVERY; + } + } + } else if (strcmpi (InputString, "FFS_ATTRIB_CHECKSUM") == 0) { + // + // found FFS_ATTRIB_CHECKSUM, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strcmpi (InputString, "TRUE") == 0) { + FfsAttrib |= FFS_ATTRIB_CHECKSUM; + } + } else { + BreakString (InputString, InputString, 1); + if (strcmpi (InputString, "TRUE") == 0) { + FfsAttrib |= FFS_ATTRIB_CHECKSUM; + } + } + } else if (strcmpi (InputString, "FFS_ALIGNMENT") == 0) { + // + // found FFS_ALIGNMENT, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + } else { + BreakString (InputString, InputString, 1); + } + + AsciiStringToUint64 (InputString, FALSE, &FfsAlignment); + if (FfsAlignment > 7) { + Error (mGlobals.OverridePackagePath, 1, 0, InputString, "invalid FFS_ALIGNMENT value"); + goto Done; + } + + FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment) << 3); + } else if (strchr (InputString, '=') != NULL) { + BreakString (InputString, String, 1); + fseek (OverridePackage, (-1 * (strlen (String) + 1)), SEEK_CUR); + BreakString (InputString, InputString, 0); + goto here; + } + } + } + } + } +#endif // #ifdef OVERRIDE_SUPPORTED + // + // Require that they specified a file GUID at least, since that's how we're + // naming the file. + // + if (GuidString[0] == 0) { + Error (mGlobals.PrimaryPackagePath, 1, 0, "FFS_FILEGUID must be specified", NULL); + return STATUS_ERROR; + } + // + // Build Header and process image script + // + FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 16) * sizeof (UINT8)); + if (FileBuffer == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL); + goto Done; + } + + FileSize = 0; + if (ImageScriptInOveride) { +#ifdef OVERRIDE_SUPORTED + rewind (OverridePackage); + LineNumber = 0; + FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber); + while (strcmpi (InputString, "IMAGE_SCRIPT") != 0) { + GetNextLine (InputString, OverridePackage, &LineNumber); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strchr (InputString, '=') != NULL) { + BreakString (InputString, InputString, 0); + } + } + + while (InputString[0] != '{') { + GetNextLine (InputString, OverridePackage, &LineNumber); + CheckSlash (InputString, OverridePackage, &LineNumber); + } + // + // Found start of image script, process it + // + FileSize += ProcessScript (FileBuffer, OverridePackage, mGlobals.BuildDirectory, ForceUncompress); + if (FileSize == -1) { + return -1; + } + + if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) { + FileSize = AdjustFileSize (FileBuffer, FileSize); + } + + if (BaseName[0] == '\"') { + StripQuotes (BaseName); + } + + if (BaseName[0] != 0) { + sprintf (InputString, "%s-%s", GuidString, BaseName); + } else { + strcpy (InputString, GuidString); + } + + switch (StringToType (FileType)) { + + case EFI_FV_FILETYPE_SECURITY_CORE: + strcat (InputString, ".SEC"); + break; + + case EFI_FV_FILETYPE_PEIM: + case EFI_FV_FILETYPE_PEI_CORE: + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + strcat (InputString, ".PEI"); + break; + + case EFI_FV_FILETYPE_DRIVER: + case EFI_FV_FILETYPE_DXE_CORE: + strcat (InputString, ".DXE"); + break; + + case EFI_FV_FILETYPE_APPLICATION: + strcat (InputString, ".APP"); + break; + + case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: + strcat (InputString, ".FVI"); + break; + + case EFI_FV_FILETYPE_ALL: + Error (mGlobals.OverridePackagePath, 1, 0, "invalid FFS file type for this utility", NULL); + goto Done; + + default: + strcat (InputString, ".FFS"); + break; + } + + if (ForceUncompress) { + strcat (InputString, ".ORG"); + } + + Out = fopen (InputString, "wb"); + if (Out == NULL) { + Error (NULL, 0, 0, InputString, "could not open output file for writing"); + goto Done; + } + // + // create ffs header + // + memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID)); + FileHeader.Type = StringToType (FileType); + FileHeader.Attributes = FfsAttrib; + // + // Now FileSize includes the EFI_FFS_FILE_HEADER + // + FileSize += sizeof (EFI_FFS_FILE_HEADER); + FileHeader.Size[0] = (UINT8) (FileSize & 0xFF); + FileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8); + FileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16); + // + // Fill in checksums and state, these must be zero for checksumming + // + // FileHeader.IntegrityCheck.Checksum.Header = 0; + // FileHeader.IntegrityCheck.Checksum.File = 0; + // FileHeader.State = 0; + // + FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 ( + (UINT8 *) &FileHeader, + sizeof (EFI_FFS_FILE_HEADER) + ); + if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) { + FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) &FileHeader, FileSize); + } else { + FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + // + // write header + // + if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) { + Error (NULL, 0, 0, "failed to write file header to output file", NULL); + goto Done; + } + // + // write data + // + if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) { + Error (NULL, 0, 0, "failed to write all bytes to output file", NULL); + goto Done; + } + + fclose (Out); + Out = NULL; +#endif // #ifdef OVERRIDE_SUPPORTED + } else { + // + // Open primary package file and process the IMAGE_SCRIPT section + // + PrimaryPackage = fopen (mGlobals.PrimaryPackagePath, "r"); + if (PrimaryPackage == NULL) { + Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file"); + goto Done; + } + + LineNumber = 1; + FindSectionInPackage (".", PrimaryPackage, &LineNumber); + while (strcmpi (InputString, "IMAGE_SCRIPT") != 0) { + GetNextLine (InputString, PrimaryPackage, &LineNumber); + CheckSlash (InputString, PrimaryPackage, &LineNumber); + if (strchr (InputString, '=') != NULL) { + BreakString (InputString, InputString, 0); + } + } + + while (InputString[0] != '{') { + GetNextLine (InputString, PrimaryPackage, &LineNumber); + CheckSlash (InputString, PrimaryPackage, &LineNumber); + } + // + // Found start of image script, process it + // + FileSize += ProcessScript (FileBuffer, PrimaryPackage, mGlobals.BuildDirectory, ForceUncompress); + if (FileSize == -1) { + goto Done; + } + + if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) { + FileSize = AdjustFileSize (FileBuffer, FileSize); + } + + if (BaseName[0] == '\"') { + StripQuotes (BaseName); + } + + if (BaseName[0] != 0) { + sprintf (InputString, "%s-%s", GuidString, BaseName); + } else { + strcpy (InputString, GuidString); + } + + switch (StringToType (FileType)) { + + case EFI_FV_FILETYPE_SECURITY_CORE: + strcat (InputString, ".SEC"); + break; + + case EFI_FV_FILETYPE_PEIM: + case EFI_FV_FILETYPE_PEI_CORE: + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + strcat (InputString, ".PEI"); + break; + + case EFI_FV_FILETYPE_DRIVER: + case EFI_FV_FILETYPE_DXE_CORE: + strcat (InputString, ".DXE"); + break; + + case EFI_FV_FILETYPE_APPLICATION: + strcat (InputString, ".APP"); + break; + + case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: + strcat (InputString, ".FVI"); + break; + + case EFI_FV_FILETYPE_ALL: + Error (mGlobals.PrimaryPackagePath, 1, 0, "invalid FFS file type for this utility", NULL); + goto Done; + + default: + strcat (InputString, ".FFS"); + break; + } + + if (ForceUncompress) { + strcat (InputString, ".ORG"); + } + + Out = fopen (InputString, "wb"); + if (Out == NULL) { + Error (NULL, 0, 0, InputString, "failed to open output file for writing"); + goto Done; + } + // + // Initialize the FFS file header + // + memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID)); + FileHeader.Type = StringToType (FileType); + FileHeader.Attributes = FfsAttrib; + // + // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER + // + FileSize += sizeof (EFI_FFS_FILE_HEADER); + // + // If using a tail, then it adds two bytes + // + if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) { + // + // Tail is not allowed for pad and 0-length files + // + if ((FileHeader.Type == EFI_FV_FILETYPE_FFS_PAD) || (FileSize == sizeof (EFI_FFS_FILE_HEADER))) { + Error ( + mGlobals.PrimaryPackagePath, + 1, + 0, + "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files", + NULL + ); + goto Done; + } + + FileSize += sizeof (EFI_FFS_FILE_TAIL); + } + + FileHeader.Size[0] = (UINT8) (FileSize & 0xFF); + FileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8); + FileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16); + // + // Fill in checksums and state, they must be 0 for checksumming. + // + // FileHeader.IntegrityCheck.Checksum.Header = 0; + // FileHeader.IntegrityCheck.Checksum.File = 0; + // FileHeader.State = 0; + // + FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 ( + (UINT8 *) &FileHeader, + sizeof (EFI_FFS_FILE_HEADER) + ); + if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Cheating here. Since the header checksums, just calculate the checksum of the body. + // Checksum does not include the tail + // + if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) { + FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ( + FileBuffer, + FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL) + ); + } else { + FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ( + FileBuffer, + FileSize - sizeof (EFI_FFS_FILE_HEADER) + ); + } + } else { + FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + // + // Set the state now. Spec says the checksum assumes the state is 0 + // + FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + // + // If there is a tail, then set it + // + if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailValue = FileHeader.IntegrityCheck.TailReference; + TailValue = (UINT16) (~TailValue); + memcpy ( + (UINT8 *) FileBuffer + FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL), + &TailValue, + sizeof (TailValue) + ); + } + // + // Write the FFS file header + // + if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) { + Error (NULL, 0, 0, "failed to write file header contents", NULL); + goto Done; + } + // + // Write data + // + if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) { + Error (NULL, 0, 0, "failed to write file contents", NULL); + goto Done; + } + } + +Done: + SFPCloseFile (); + if (Out != NULL) { + fclose (Out); + } + + if (PrimaryPackage != NULL) { + fclose (PrimaryPackage); + } + + if (FileBuffer != NULL) { + free (FileBuffer); + } + + if (OverridePackage != NULL) { + fclose (OverridePackage); + } + + return GetUtilityStatus (); +} + +int +main ( + INT32 argc, + CHAR8 *argv[] + ) +/*++ + +Routine Description: + + Main function. + +Arguments: + + argc - Number of command line parameters. + argv - Array of pointers to parameter strings. + +Returns: + STATUS_SUCCESS - Utility exits successfully. + STATUS_ERROR - Some error occurred during execution. + +--*/ +{ + STATUS Status; + // + // Set the name of our utility for error reporting purposes. + // + SetUtilityName (UTILITY_NAME); + Status = ProcessCommandLineArgs (argc, argv); + if (Status != STATUS_SUCCESS) { + return Status; + } + + Status = MainEntry (argc, argv, TRUE); + if (Status == STATUS_SUCCESS) { + MainEntry (argc, argv, FALSE); + } + // + // If any errors were reported via the standard error reporting + // routines, then the status has been saved. Get the value and + // return it to the caller. + // + return GetUtilityStatus (); +} + +static +STATUS +ProcessCommandLineArgs ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + Process the command line arguments. + +Arguments: + Argc - as passed in to main() + Argv - as passed in to main() + +Returns: + STATUS_SUCCESS - arguments all ok + STATUS_ERROR - problem with args, so caller should exit + +--*/ +{ + // + // If no args, then print usage instructions and return an error + // + if (Argc == 1) { + PrintUsage (); + return STATUS_ERROR; + } + + memset (&mGlobals, 0, sizeof (mGlobals)); + Argc--; + Argv++; + while (Argc > 0) { + if (strcmpi (Argv[0], "-b") == 0) { + // + // OPTION: -b BuildDirectory + // Make sure there is another argument, then save it to our globals. + // + if (Argc < 2) { + Error (NULL, 0, 0, "-b option requires the build directory name", NULL); + return STATUS_ERROR; + } + + if (mGlobals.BuildDirectory[0]) { + Error (NULL, 0, 0, Argv[0], "option can only be specified once"); + return STATUS_ERROR; + } + + strcpy (mGlobals.BuildDirectory, Argv[1]); + Argc--; + Argv++; + } else if (strcmpi (Argv[0], "-p1") == 0) { + // + // OPTION: -p1 PrimaryPackageFile + // Make sure there is another argument, then save it to our globals. + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "option requires the primary package file name"); + return STATUS_ERROR; + } + + if (mGlobals.PrimaryPackagePath[0]) { + Error (NULL, 0, 0, Argv[0], "option can only be specified once"); + return STATUS_ERROR; + } + + strcpy (mGlobals.PrimaryPackagePath, Argv[1]); + Argc--; + Argv++; + } else if (strcmpi (Argv[0], "-p2") == 0) { + // + // OPTION: -p2 OverridePackageFile + // Make sure there is another argument, then save it to our globals. + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "option requires the override package file name"); + return STATUS_ERROR; + } + + if (mGlobals.OverridePackagePath[0]) { + Error (NULL, 0, 0, Argv[0], "option can only be specified once"); + return STATUS_ERROR; + } + + strcpy (mGlobals.OverridePackagePath, Argv[1]); + Argc--; + Argv++; + } else if (strcmpi (Argv[0], "-v") == 0) { + // + // OPTION: -v verbose + // + mGlobals.Verbose = TRUE; + } else if (strcmpi (Argv[0], "-h") == 0) { + // + // OPTION: -h help + // + PrintUsage (); + return STATUS_ERROR; + } else if (strcmpi (Argv[0], "-?") == 0) { + // + // OPTION: -? help + // + PrintUsage (); + return STATUS_ERROR; + } else { + Error (NULL, 0, 0, Argv[0], "unrecognized option"); + PrintUsage (); + return STATUS_ERROR; + } + + Argv++; + Argc--; + } + // + // Must have at least specified the package file name + // + if (mGlobals.PrimaryPackagePath[0] == 0) { + Error (NULL, 0, 0, "must specify primary package file", NULL); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} diff --git a/Tools/Source/TianoTools/GenFfsFile/GenFfsFile.h b/Tools/Source/TianoTools/GenFfsFile/GenFfsFile.h new file mode 100644 index 0000000000..695809ce43 --- /dev/null +++ b/Tools/Source/TianoTools/GenFfsFile/GenFfsFile.h @@ -0,0 +1,36 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenFfsFile.h + +Abstract: + + Header file for GenFfsFile. + +--*/ + +// +// Module Coded to Tiano Coding Conventions +// +#ifndef _EFI_GEN_FFSFILE_H +#define _EFI_GEN_FFSFILE_H + +// +// External Files Referenced +// +#include "Base.h" +#include "UefiBaseTypes.h" +#include "FirmwareVolumeImageFormat.h" +#include "MyAlloc.h" + +#endif diff --git a/Tools/Source/TianoTools/GenFfsFile/SimpleFileParsing.c b/Tools/Source/TianoTools/GenFfsFile/SimpleFileParsing.c new file mode 100644 index 0000000000..d3933db420 --- /dev/null +++ b/Tools/Source/TianoTools/GenFfsFile/SimpleFileParsing.c @@ -0,0 +1,969 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + SimpleFileParsing.c + +Abstract: + + Generic but simple file parsing routines. + +--*/ + +#include +#include +#include +#include + +#include "Base.h" +#include "UefiBaseTypes.h" +#include "EfiUtilityMsgs.h" +#include "SimpleFileParsing.h" + +#define MAX_PATH 255 +#define MAX_NEST_DEPTH 20 // just in case we get in an endless loop. +#define MAX_STRING_IDENTIFIER_NAME 100 // number of wchars +#define MAX_LINE_LEN 400 + +#define T_CHAR_SPACE ' ' +#define T_CHAR_NULL 0 +#define T_CHAR_CR '\r' +#define T_CHAR_TAB '\t' +#define T_CHAR_LF '\n' +#define T_CHAR_SLASH '/' +#define T_CHAR_BACKSLASH '\\' +#define T_CHAR_DOUBLE_QUOTE '"' +#define T_CHAR_LC_X 'x' +#define T_CHAR_0 '0' + +// +// We keep a linked list of these for the source files we process +// +typedef struct _SOURCE_FILE { + FILE *Fptr; + T_CHAR *FileBuffer; + T_CHAR *FileBufferPtr; + UINT32 FileSize; + INT8 FileName[MAX_PATH]; + UINT32 LineNum; + BOOLEAN EndOfFile; + BOOLEAN SkipToHash; + struct _SOURCE_FILE *Previous; + struct _SOURCE_FILE *Next; + T_CHAR ControlCharacter; +} SOURCE_FILE; + +// +// Here's all our module globals. +// +static struct { + SOURCE_FILE SourceFile; + BOOLEAN Verbose; +} mGlobals; + +static +UINT32 +t_strcmp ( + T_CHAR *Buffer, + T_CHAR *Str + ); + +static +UINT32 +t_strncmp ( + T_CHAR *Str1, + T_CHAR *Str2, + UINT32 Len + ); + +static +UINT32 +t_strlen ( + T_CHAR *Str + ); + +static +void +RewindFile ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +SkipTo ( + SOURCE_FILE *SourceFile, + T_CHAR TChar, + BOOLEAN StopAfterNewline + ); + +static +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +UINT32 +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ); + +static +void +PreprocessFile ( + SOURCE_FILE *SourceFile + ); + +// +// static +// T_CHAR * +// GetQuotedString ( +// SOURCE_FILE *SourceFile, +// BOOLEAN Optional +// ); +// +static +T_CHAR * +t_strcpy ( + T_CHAR *Dest, + T_CHAR *Src + ); + +static +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ); + +static +STATUS +ParseFile ( + SOURCE_FILE *SourceFile + ); + +static +FILE * +FindFile ( + IN INT8 *FileName, + OUT INT8 *FoundFileName, + IN UINT32 FoundFileNameLen + ); + +static +STATUS +ProcessFile ( + SOURCE_FILE *SourceFile + ); + +STATUS +SFPInit ( + VOID + ) +{ + memset ((void *) &mGlobals, 0, sizeof (mGlobals)); + return STATUS_SUCCESS; +} + +UINT32 +SFPGetLineNumber ( + VOID + ) +{ + return mGlobals.SourceFile.LineNum; +} + +/*++ + +Routine Description: + Return the line number of the file we're parsing. Used + for error reporting purposes. + +Arguments: + None. + +Returns: + The line number, or 0 if no file is being processed + +--*/ +T_CHAR * +SFPGetFileName ( + VOID + ) +/*++ + +Routine Description: + Return the name of the file we're parsing. Used + for error reporting purposes. + +Arguments: + None. + +Returns: + A pointer to the file name. Null if no file is being + processed. + +--*/ +{ + if (mGlobals.SourceFile.FileName[0]) { + return mGlobals.SourceFile.FileName; + } + + return NULL; +} + +STATUS +SFPOpenFile ( + IN INT8 *FileName + ) +/*++ + +Routine Description: + Open a file for parsing. + +Arguments: + FileName - name of the file to parse + +Returns: + + +--*/ +{ + STATUS Status; + t_strcpy (mGlobals.SourceFile.FileName, FileName); + Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL); + return Status; +} + +BOOLEAN +SFPIsToken ( + T_CHAR *Str + ) +/*++ + +Routine Description: + Check to see if the specified token is found at + the current position in the input file. + +Arguments: + Str - the token to look for + +Returns: + TRUE - the token is next + FALSE - the token is not next + +Notes: + We do a simple string comparison on this function. It is + the responsibility of the caller to ensure that the token + is not a subset of some other token. + + The file pointer is advanced past the token in the input file. + +--*/ +{ + UINT32 Len; + SkipWhiteSpace (&mGlobals.SourceFile); + + if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) { + mGlobals.SourceFile.FileBufferPtr += Len; + return TRUE; + } + + return FALSE; + +} + +BOOLEAN +SFPGetNextToken ( + T_CHAR *Str, + UINT32 Len + ) +{ + UINT32 Index; + SkipWhiteSpace (&mGlobals.SourceFile); + Index = 0; + while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) { + if (IsWhiteSpace (&mGlobals.SourceFile)) { + if (Index > 0) { + Str[Index] = 0; + return TRUE; + } + + return FALSE; + } else { + Str[Index] = mGlobals.SourceFile.FileBufferPtr[0]; + mGlobals.SourceFile.FileBufferPtr++; + Index++; + } + } + + return FALSE; +} + +BOOLEAN +SFPSkipToToken ( + T_CHAR *Str + ) +{ + UINT32 Len; + T_CHAR *SavePos; + Len = t_strlen (Str); + SavePos = mGlobals.SourceFile.FileBufferPtr; + SkipWhiteSpace (&mGlobals.SourceFile); + while (!EndOfFile (&mGlobals.SourceFile)) { + if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) { + mGlobals.SourceFile.FileBufferPtr += Len; + return TRUE; + } + + mGlobals.SourceFile.FileBufferPtr++; + SkipWhiteSpace (&mGlobals.SourceFile); + } + + mGlobals.SourceFile.FileBufferPtr = SavePos; + return FALSE; +} + +BOOLEAN +SFPGetNumber ( + UINT32 *Value + ) +/*++ + +Routine Description: + Check the token at the current file position for a numeric value. + May be either decimal or hex. + +Arguments: + Value - pointer where to store the value + +Returns: + FALSE - current token is not a number + TRUE - current token is a number + +--*/ +{ + // + // UINT32 Len; + // + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) { + // + // Check for hex value + // + if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) { + if (!isxdigit (mGlobals.SourceFile.FileBufferPtr[2])) { + return FALSE; + } + + mGlobals.SourceFile.FileBufferPtr += 2; + sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value); + while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) { + mGlobals.SourceFile.FileBufferPtr++; + } + + return TRUE; + } else { + *Value = atoi (mGlobals.SourceFile.FileBufferPtr); + while (isdigit (mGlobals.SourceFile.FileBufferPtr[0])) { + mGlobals.SourceFile.FileBufferPtr++; + } + + return TRUE; + } + } else { + return FALSE; + } +} + +STATUS +SFPCloseFile ( + VOID + ) +/*++ + +Routine Description: + Close the file being parsed. + +Arguments: + None. + +Returns: + STATUS_SUCCESS - the file was closed + STATUS_ERROR - no file is currently open + +--*/ +{ + if (mGlobals.SourceFile.FileBuffer != NULL) { + free (mGlobals.SourceFile.FileBuffer); + memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile)); + return STATUS_SUCCESS; + } + + return STATUS_ERROR; +} + +static +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ) +/*++ + +Routine Description: + + Given a source file, open the file and parse it + +Arguments: + + SourceFile - name of file to parse + ParentSourceFile - for error reporting purposes, the file that #included SourceFile. + +Returns: + + Standard status. + +--*/ +{ + static UINT32 NestDepth = 0; + INT8 FoundFileName[MAX_PATH]; + STATUS Status; + + Status = STATUS_SUCCESS; + NestDepth++; + // + // Print the file being processed. Indent so you can tell the include nesting + // depth. + // + if (mGlobals.Verbose) { + fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName); + } + + // + // Make sure we didn't exceed our maximum nesting depth + // + if (NestDepth > MAX_NEST_DEPTH) { + Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth); + Status = STATUS_ERROR; + goto Finish; + } + // + // Try to open the file locally, and if that fails try along our include paths. + // + strcpy (FoundFileName, SourceFile->FileName); + if ((SourceFile->Fptr = fopen (FoundFileName, "r")) == NULL) { + // + // Try to find it among the paths if it has a parent (that is, it is included + // by someone else). + // + Error (NULL, 0, 0, SourceFile->FileName, "file not found"); + return STATUS_ERROR; + } + // + // Process the file found + // + ProcessFile (SourceFile); +Finish: + // + // Close open files and return status + // + if (SourceFile->Fptr != NULL) { + fclose (SourceFile->Fptr); + SourceFile->Fptr = NULL; + } + + return Status; +} + +static +STATUS +ProcessFile ( + SOURCE_FILE *SourceFile + ) +{ + // + // Get the file size, and then read the entire thing into memory. + // Allocate space for a terminator character. + // + fseek (SourceFile->Fptr, 0, SEEK_END); + SourceFile->FileSize = ftell (SourceFile->Fptr); + fseek (SourceFile->Fptr, 0, SEEK_SET); + SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR)); + if (SourceFile->FileBuffer == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr); + SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = T_CHAR_NULL; + // + // Pre-process the file to replace comments with spaces + // + PreprocessFile (SourceFile); + SourceFile->LineNum = 1; + return STATUS_SUCCESS; +} + +static +void +PreprocessFile ( + SOURCE_FILE *SourceFile + ) +/*++ + +Routine Description: + Preprocess a file to replace all carriage returns with NULLs so + we can print lines from the file to the screen. + +Arguments: + SourceFile - structure that we use to keep track of an input file. + +Returns: + Nothing. + +--*/ +{ + BOOLEAN InComment; + + RewindFile (SourceFile); + InComment = FALSE; + while (!EndOfFile (SourceFile)) { + // + // If a line-feed, then no longer in a comment + // + if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) { + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + InComment = 0; + } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) { + // + // Replace all carriage returns with a NULL so we can print stuff + // + SourceFile->FileBufferPtr[0] = 0; + SourceFile->FileBufferPtr++; + } else if (InComment) { + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) { + SourceFile->FileBufferPtr += 2; + InComment = TRUE; + } else { + SourceFile->FileBufferPtr++; + } + } + // + // Could check for end-of-file and still in a comment, but + // should not be necessary. So just restore the file pointers. + // + RewindFile (SourceFile); +} + +#if 0 +static +T_CHAR * +GetQuotedString ( + SOURCE_FILE *SourceFile, + BOOLEAN Optional + ) +{ + T_CHAR *String; + T_CHAR *Start; + T_CHAR *Ptr; + UINT32 Len; + BOOLEAN PreviousBackslash; + + if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) { + if (!Optional) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr); + } + + return NULL; + } + + Len = 0; + SourceFile->FileBufferPtr++; + Start = Ptr = SourceFile->FileBufferPtr; + PreviousBackslash = FALSE; + while (!EndOfFile (SourceFile)) { + if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (!PreviousBackslash)) { + break; + } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start); + PreviousBackslash = FALSE; + } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) { + PreviousBackslash = TRUE; + } else { + PreviousBackslash = FALSE; + } + + SourceFile->FileBufferPtr++; + Len++; + } + + if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start); + } else { + SourceFile->FileBufferPtr++; + } + // + // Now allocate memory for the string and save it off + // + String = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR)); + if (String == NULL) { + Error (NULL, 0, 0, "memory allocation failed", NULL); + return NULL; + } + // + // Copy the string from the file buffer to the local copy. + // We do no reformatting of it whatsoever at this point. + // + Ptr = String; + while (Len > 0) { + *Ptr = *Start; + Start++; + Ptr++; + Len--; + } + + *Ptr = 0; + return String; +} +#endif +static +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ) +{ + // + // The file buffer pointer will typically get updated before the End-of-file flag in the + // source file structure, so check it first. + // + if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (T_CHAR)) { + SourceFile->EndOfFile = TRUE; + return TRUE; + } + + if (SourceFile->EndOfFile) { + return TRUE; + } + + return FALSE; +} + +#if 0 +static +void +ProcessTokenInclude ( + SOURCE_FILE *SourceFile + ) +{ + INT8 IncludeFileName[MAX_PATH]; + INT8 *To; + UINT32 Len; + BOOLEAN ReportedError; + SOURCE_FILE IncludedSourceFile; + + ReportedError = FALSE; + if (SkipWhiteSpace (SourceFile) == 0) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL); + } + // + // Should be quoted file name + // + if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL); + goto FailDone; + } + + SourceFile->FileBufferPtr++; + // + // Copy the filename as ascii to our local string + // + To = IncludeFileName; + Len = 0; + while (!EndOfFile (SourceFile)) { + if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL); + goto FailDone; + } + + if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) { + SourceFile->FileBufferPtr++; + break; + } + // + // If too long, then report the error once and process until the closing quote + // + Len++; + if (!ReportedError && (Len >= sizeof (IncludeFileName))) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL); + ReportedError = TRUE; + } + + if (!ReportedError) { + // + // *To = UNICODE_TO_ASCII(SourceFile->FileBufferPtr[0]); + // + *To = (T_CHAR) SourceFile->FileBufferPtr[0]; + To++; + } + + SourceFile->FileBufferPtr++; + } + + if (!ReportedError) { + *To = 0; + memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE)); + strcpy (IncludedSourceFile.FileName, IncludeFileName); + // + // IncludedSourceFile.ControlCharacter = DEFAULT_CONTROL_CHARACTER; + // + ProcessIncludeFile (&IncludedSourceFile, SourceFile); + // + // printf ("including file '%s'\n", IncludeFileName); + // + } + + return ; +FailDone: + // + // Error recovery -- skip to next # + // + SourceFile->SkipToHash = TRUE; +} +#endif +static +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + switch (*SourceFile->FileBufferPtr) { + case T_CHAR_NULL: + case T_CHAR_CR: + case T_CHAR_SPACE: + case T_CHAR_TAB: + case T_CHAR_LF: + return TRUE; + + default: + return FALSE; + } +} + +UINT32 +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + UINT32 Count; + + Count = 0; + while (!EndOfFile (SourceFile)) { + Count++; + switch (*SourceFile->FileBufferPtr) { + case T_CHAR_NULL: + case T_CHAR_CR: + case T_CHAR_SPACE: + case T_CHAR_TAB: + SourceFile->FileBufferPtr++; + break; + + case T_CHAR_LF: + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + if (mGlobals.Verbose) { + printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr); + } + break; + + default: + return Count - 1; + } + } + // + // Some tokens require trailing whitespace. If we're at the end of the + // file, then we count that as well. + // + if ((Count == 0) && (EndOfFile (SourceFile))) { + Count++; + } + + return Count; +} + +static +UINT32 +t_strcmp ( + T_CHAR *Buffer, + T_CHAR *Str + ) +{ + UINT32 Len; + + Len = 0; + while (*Str == *Buffer) { + Buffer++; + Str++; + Len++; + } + + if (*Str) { + return 0; + } + + return Len; +} + +static +UINT32 +t_strlen ( + T_CHAR *Str + ) +{ + UINT32 Len; + Len = 0; + while (*Str) { + Len++; + Str++; + } + + return Len; +} + +static +UINT32 +t_strncmp ( + T_CHAR *Str1, + T_CHAR *Str2, + UINT32 Len + ) +{ + while (Len > 0) { + if (*Str1 != *Str2) { + return Len; + } + + Len--; + Str1++; + Str2++; + } + + return 0; +} + +static +T_CHAR * +t_strcpy ( + T_CHAR *Dest, + T_CHAR *Src + ) +{ + T_CHAR *SaveDest; + SaveDest = Dest; + while (*Src) { + *Dest = *Src; + Dest++; + Src++; + } + + *Dest = 0; + return SaveDest; +} + +#if 0 +static +BOOLEAN +IsValidIdentifierChar ( + INT8 Char, + BOOLEAN FirstChar + ) +{ + // + // If it's the first character of an identifier, then + // it must be one of [A-Za-z_]. + // + if (FirstChar) { + if (isalpha (Char) || (Char == '_')) { + return TRUE; + } + } else { + // + // If it's not the first character, then it can + // be one of [A-Za-z_0-9] + // + if (isalnum (Char) || (Char == '_')) { + return TRUE; + } + } + + return FALSE; +} +#endif +static +void +RewindFile ( + SOURCE_FILE *SourceFile + ) +{ + SourceFile->LineNum = 1; + SourceFile->FileBufferPtr = SourceFile->FileBuffer; + SourceFile->EndOfFile = 0; +} + +#if 0 +static +BOOLEAN +SkipTo ( + SOURCE_FILE *SourceFile, + T_CHAR TChar, + BOOLEAN StopAfterNewline + ) +{ + while (!EndOfFile (SourceFile)) { + // + // Check for the character of interest + // + if (SourceFile->FileBufferPtr[0] == TChar) { + return TRUE; + } else { + if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) { + SourceFile->LineNum++; + if (StopAfterNewline) { + SourceFile->FileBufferPtr++; + if (SourceFile->FileBufferPtr[0] == 0) { + SourceFile->FileBufferPtr++; + } + + return FALSE; + } + } + + SourceFile->FileBufferPtr++; + } + } + + return FALSE; +} +#endif diff --git a/Tools/Source/TianoTools/GenFfsFile/build.gcc b/Tools/Source/TianoTools/GenFfsFile/build.gcc new file mode 100644 index 0000000000..6b75815073 --- /dev/null +++ b/Tools/Source/TianoTools/GenFfsFile/build.gcc @@ -0,0 +1 @@ +gcc -mno-cygwin -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ -I../Common -I$WORKSPACE/MdePkg/Include/ -I$WORKSPACE/MdePkg/Include/Ia32 -I. GenFfsFile.c -L../Library-mingw -lCommon -lCustomizedCompress -o GenFfsFile diff --git a/Tools/Source/TianoTools/GenFfsFile/build.xml b/Tools/Source/TianoTools/GenFfsFile/build.xml new file mode 100644 index 0000000000..352ea0fca1 --- /dev/null +++ b/Tools/Source/TianoTools/GenFfsFile/build.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/GenFvImage/BasePeCoff.c b/Tools/Source/TianoTools/GenFvImage/BasePeCoff.c new file mode 100644 index 0000000000..b41a3a0e3b --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/BasePeCoff.c @@ -0,0 +1,1062 @@ +/*++ + +Copyright (c) 2004 - 2005, 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. + +Module Name: + + PeCoffLoader.c + +Abstract: + + Tiano PE/COFF loader + +Revision History + +--*/ + + +#define EFI_SPECIFICATION_VERSION 0x00000000 +#define EDK_RELEASE_VERSION 0x00020000 +#include +#include +#include + +STATIC +RETURN_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_NT_HEADERS *PeHdr, + OUT EFI_TE_IMAGE_HEADER *TeHdr + ); + +STATIC +RETURN_STATUS +PeCoffLoaderCheckImageType ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_NT_HEADERS *PeHdr, + IN EFI_TE_IMAGE_HEADER *TeHdr + ); + +STATIC +VOID * +PeCoffLoaderImageAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ); + + +STATIC +RETURN_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_NT_HEADERS *PeHdr, + OUT EFI_TE_IMAGE_HEADER *TeHdr + ) +/*++ + +Routine Description: + + Retrieves the PE or TE Header from a PE/COFF or TE image + +Arguments: + + ImageContext - The context of the image being loaded + + PeHdr - The buffer in which to return the PE header + + TeHdr - The buffer in which to return the TE header + +Returns: + + RETURN_SUCCESS if the PE or TE Header is read, + Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function. + +--*/ +{ + RETURN_STATUS Status; + EFI_IMAGE_DOS_HEADER DosHdr; + UINTN Size; + + ImageContext->IsTeImage = FALSE; + // + // Read the DOS image headers + // + Size = sizeof (EFI_IMAGE_DOS_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &Size, + &DosHdr + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + ImageContext->PeCoffHeaderOffset = 0; + if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew; + } + // + // Read the PE/COFF Header + // + Size = sizeof (EFI_IMAGE_NT_HEADERS); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + ImageContext->PeCoffHeaderOffset, + &Size, + PeHdr + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + // + // Check the PE/COFF Header Signature. If not, then try to read a TE header + // + if (PeHdr->Signature != EFI_IMAGE_NT_SIGNATURE) { + Size = sizeof (EFI_TE_IMAGE_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &Size, + TeHdr + ); + if (TeHdr->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) { + return RETURN_UNSUPPORTED; + } + + ImageContext->IsTeImage = TRUE; + } + + return RETURN_SUCCESS; +} + +STATIC +RETURN_STATUS +PeCoffLoaderCheckImageType ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_NT_HEADERS *PeHdr, + IN EFI_TE_IMAGE_HEADER *TeHdr + ) +/*++ + +Routine Description: + + Checks the PE or TE header of a PE/COFF or TE image to determine if it supported + +Arguments: + + ImageContext - The context of the image being loaded + + PeHdr - The buffer in which to return the PE header + + TeHdr - The buffer in which to return the TE header + +Returns: + + RETURN_SUCCESS if the PE/COFF or TE image is supported + RETURN_UNSUPPORTED of the PE/COFF or TE image is not supported. + +--*/ +{ + // + // See if the machine type is supported. We support a native machine type (IA-32/Itanium-based) + // and the machine type for the Virtual Machine. + // + if (ImageContext->IsTeImage == FALSE) { + ImageContext->Machine = PeHdr->FileHeader.Machine; + } else { + ImageContext->Machine = TeHdr->Machine; + } + + if (!(EFI_IMAGE_MACHINE_TYPE_SUPPORTED (ImageContext->Machine))) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_MACHINE_TYPE; + return RETURN_UNSUPPORTED; + } + + // + // See if the image type is supported. We support EFI Applications, + // EFI Boot Service Drivers, and EFI Runtime Drivers. + // + if (ImageContext->IsTeImage == FALSE) { + ImageContext->ImageType = PeHdr->OptionalHeader.Subsystem; + } else { + ImageContext->ImageType = (UINT16) (TeHdr->Subsystem); + } + + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EFIAPI +PeCoffLoaderGetImageInfo ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Retrieves information on a PE/COFF image + +Arguments: + + This - Calling context + ImageContext - The context of the image being loaded + +Returns: + + RETURN_SUCCESS - The information on the PE/COFF image was collected. + RETURN_INVALID_PARAMETER - ImageContext is NULL. + RETURN_UNSUPPORTED - The PE/COFF image is not supported. + Otherwise - The error status from reading the PE/COFF image using the + ImageContext->ImageRead() function + +--*/ +{ + RETURN_STATUS Status; + EFI_IMAGE_NT_HEADERS PeHdr; + EFI_TE_IMAGE_HEADER TeHdr; + EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry; + UINTN Size; + UINTN Index; + UINTN DebugDirectoryEntryRva; + UINTN DebugDirectoryEntryFileOffset; + UINTN SectionHeaderOffset; + EFI_IMAGE_SECTION_HEADER SectionHeader; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry; + + if (NULL == ImageContext) { + return RETURN_INVALID_PARAMETER; + } + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + Status = PeCoffLoaderGetPeHeader (ImageContext, &PeHdr, &TeHdr); + if (RETURN_ERROR (Status)) { + return Status; + } + // + // Verify machine type + // + Status = PeCoffLoaderCheckImageType (ImageContext, &PeHdr, &TeHdr); + if (RETURN_ERROR (Status)) { + return Status; + } + // + // Retrieve the base address of the image + // + if (!(ImageContext->IsTeImage)) { + ImageContext->ImageAddress = PeHdr.OptionalHeader.ImageBase; + } else { + ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr.ImageBase); + } + // + // Initialize the alternate destination address to 0 indicating that it + // should not be used. + // + ImageContext->DestinationAddress = 0; + + // + // Initialize the codeview pointer. + // + ImageContext->CodeView = NULL; + ImageContext->PdbPointer = NULL; + + // + // Three cases with regards to relocations: + // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable + // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable + // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but + // has no base relocs to apply + // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid. + // + // Look at the file header to determine if relocations have been stripped, and + // save this info in the image context for later use. + // + if ((!(ImageContext->IsTeImage)) && ((PeHdr.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) { + ImageContext->RelocationsStripped = TRUE; + } else { + ImageContext->RelocationsStripped = FALSE; + } + + if (!(ImageContext->IsTeImage)) { + ImageContext->ImageSize = (UINT64) PeHdr.OptionalHeader.SizeOfImage; + ImageContext->SectionAlignment = PeHdr.OptionalHeader.SectionAlignment; + ImageContext->SizeOfHeaders = PeHdr.OptionalHeader.SizeOfHeaders; + + // + // Modify ImageSize to contain .PDB file name if required and initialize + // PdbRVA field... + // + if (PeHdr.OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(PeHdr.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + + // + // Determine the file offset of the debug directory... This means we walk + // the sections to find which section contains the RVA of the debug + // directory + // + DebugDirectoryEntryFileOffset = 0; + + SectionHeaderOffset = (UINTN)( + ImageContext->PeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + PeHdr.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < PeHdr.FileHeader.NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = + DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData; + break; + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset, + &Size, + &DebugEntry + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) { + ImageContext->ImageSize += DebugEntry.SizeOfData; + } + + return RETURN_SUCCESS; + } + } + } + } + } else { + ImageContext->ImageSize = 0; + ImageContext->SectionAlignment = 4096; + ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) TeHdr.BaseOfCode - (UINTN) TeHdr.StrippedSize; + + DebugDirectoryEntry = &TeHdr.DataDirectory[1]; + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + SectionHeaderOffset = (UINTN) (sizeof (EFI_TE_IMAGE_HEADER)); + + DebugDirectoryEntryFileOffset = 0; + + for (Index = 0; Index < TeHdr.NumberOfSections;) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - + SectionHeader.VirtualAddress + + SectionHeader.PointerToRawData + + sizeof (EFI_TE_IMAGE_HEADER) - + TeHdr.StrippedSize; + + // + // File offset of the debug directory was found, if this is not the last + // section, then skip to the last section for calculating the image size. + // + if (Index < (UINTN) TeHdr.NumberOfSections - 1) { + SectionHeaderOffset += (TeHdr.NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER); + Index = TeHdr.NumberOfSections - 1; + continue; + } + } + + // + // In Te image header there is not a field to describe the ImageSize. + // Actually, the ImageSize equals the RVA plus the VirtualSize of + // the last section mapped into memory (Must be rounded up to + // a mulitple of Section Alignment). Per the PE/COFF specification, the + // section headers in the Section Table must appear in order of the RVA + // values for the corresponding sections. So the ImageSize can be determined + // by the RVA and the VirtualSize of the last section header in the + // Section Table. + // + if ((++Index) == (UINTN) TeHdr.NumberOfSections) { + ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize + + ImageContext->SectionAlignment - 1) & ~(ImageContext->SectionAlignment - 1); + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index++) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset, + &Size, + &DebugEntry + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index * sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + return RETURN_SUCCESS; + } + } + } + } + + return RETURN_SUCCESS; +} + +STATIC +VOID * +PeCoffLoaderImageAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ) +/*++ + +Routine Description: + + Converts an image address to the loaded address + +Arguments: + + ImageContext - The context of the image being loaded + + Address - The address to be converted to the loaded address + +Returns: + + NULL if the address can not be converted, otherwise, the converted address + +--*/ +{ + if (Address >= ImageContext->ImageSize) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return NULL; + } + + return (CHAR8 *) ((UINTN) ImageContext->ImageAddress + Address); +} + +RETURN_STATUS +EFIAPI +PeCoffLoaderRelocateImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Relocates a PE/COFF image in memory + +Arguments: + + This - Calling context + + ImageContext - Contains information on the loaded image to relocate + +Returns: + + RETURN_SUCCESS if the PE/COFF image was relocated + RETURN_LOAD_ERROR if the image is not a valid PE/COFF image + RETURN_UNSUPPORTED not support + +--*/ +{ + RETURN_STATUS Status; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + EFI_IMAGE_DATA_DIRECTORY *RelocDir; + UINT64 Adjust; + EFI_IMAGE_BASE_RELOCATION *RelocBase; + EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; + UINT16 *Reloc; + UINT16 *RelocEnd; + CHAR8 *Fixup; + CHAR8 *FixupBase; + UINT16 *F16; + UINT32 *F32; + CHAR8 *FixupData; + PHYSICAL_ADDRESS BaseAddress; + + PeHdr = NULL; + TeHdr = NULL; + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + // + // If there are no relocation entries, then we are done + // + if (ImageContext->RelocationsStripped) { + return RETURN_SUCCESS; + } + + // + // If the destination address is not 0, use that rather than the + // image address as the relocation target. + // + if (ImageContext->DestinationAddress) { + BaseAddress = ImageContext->DestinationAddress; + } else { + BaseAddress = ImageContext->ImageAddress; + } + + if (!(ImageContext->IsTeImage)) { + PeHdr = (EFI_IMAGE_NT_HEADERS *)((UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset); + Adjust = (UINT64) BaseAddress - PeHdr->OptionalHeader.ImageBase; + PeHdr->OptionalHeader.ImageBase = (UINTN) BaseAddress; + + // + // Find the relocation block + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + RelocDir = &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress); + RelocBaseEnd = PeCoffLoaderImageAddress ( + ImageContext, + RelocDir->VirtualAddress + RelocDir->Size - 1 + ); + } else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = 0; + } + } else { + TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress); + Adjust = (UINT64) (BaseAddress - TeHdr->ImageBase); + TeHdr->ImageBase = (UINT64) (BaseAddress); + + // + // Find the relocation block + // + RelocDir = &TeHdr->DataDirectory[0]; + RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)( + ImageContext->ImageAddress + + RelocDir->VirtualAddress + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1); + } + + // + // Run the relocation information and apply the fixups + // + FixupData = ImageContext->FixupData; + while (RelocBase < RelocBaseEnd) { + + Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); + RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock); + if (!(ImageContext->IsTeImage)) { + FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress); + } else { + FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress + + RelocBase->VirtualAddress + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + } + + if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) || + (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + + (UINTN)ImageContext->ImageSize)) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + + // + // Run this relocation record + // + while (Reloc < RelocEnd) { + + Fixup = FixupBase + (*Reloc & 0xFFF); + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + + case EFI_IMAGE_REL_BASED_HIGH: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) ((*F16 << 16) + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_LOW: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) (*F16 + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHLOW: + F32 = (UINT32 *) Fixup; + *F32 = *F32 + (UINT32) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32)); + *(UINT32 *) FixupData = *F32; + FixupData = FixupData + sizeof (UINT32); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHADJ: + // + // Return the same EFI_UNSUPPORTED return code as + // PeCoffLoaderRelocateImageEx() returns if it does not recognize + // the relocation type. + // + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_UNSUPPORTED; + + default: + Status = PeCoffLoaderRelocateImageEx (Reloc, Fixup, &FixupData, Adjust); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return Status; + } + } + + // + // Next relocation record + // + Reloc += 1; + } + + // + // Next reloc block + // + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; + } + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EFIAPI +PeCoffLoaderLoadImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Loads a PE/COFF image into memory + +Arguments: + + This - Calling context + + ImageContext - Contains information on image to load into memory + +Returns: + + RETURN_SUCCESS if the PE/COFF image was loaded + RETURN_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer + RETURN_LOAD_ERROR if the image is a runtime driver with no relocations + RETURN_INVALID_PARAMETER if the image address is invalid + +--*/ +{ + RETURN_STATUS Status; + EFI_IMAGE_NT_HEADERS *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + PE_COFF_LOADER_IMAGE_CONTEXT CheckContext; + EFI_IMAGE_SECTION_HEADER *FirstSection; + EFI_IMAGE_SECTION_HEADER *Section; + UINTN NumberOfSections; + UINTN Index; + CHAR8 *Base; + CHAR8 *End; + CHAR8 *MaxEnd; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN Size; + UINT32 TempDebugEntryRva; + + PeHdr = NULL; + TeHdr = NULL; + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + // + // Copy the provided context info into our local version, get what we + // can from the original image, and then use that to make sure everything + // is legit. + // + CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + + Status = PeCoffLoaderGetImageInfo (&CheckContext); + if (RETURN_ERROR (Status)) { + return Status; + } + + // + // Make sure there is enough allocated space for the image being loaded + // + if (ImageContext->ImageSize < CheckContext.ImageSize) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE; + return RETURN_BUFFER_TOO_SMALL; + } + + // + // If there's no relocations, then make sure it's not a runtime driver, + // and that it's being loaded at the linked address. + // + if (CheckContext.RelocationsStripped) { + // + // If the image does not contain relocations and it is a runtime driver + // then return an error. + // + if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM; + return RETURN_LOAD_ERROR; + } + // + // If the image does not contain relocations, and the requested load address + // is not the linked address, then return an error. + // + if (CheckContext.ImageAddress != ImageContext->ImageAddress) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return RETURN_INVALID_PARAMETER; + } + } + // + // Make sure the allocated space has the proper section alignment + // + if (!(ImageContext->IsTeImage)) { + if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT; + return RETURN_INVALID_PARAMETER; + } + } + // + // Read the entire PE/COFF or TE header into memory + // + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (VOID *) (UINTN) ImageContext->ImageAddress + ); + + PeHdr = (EFI_IMAGE_NT_HEADERS *) + ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + PeHdr->FileHeader.SizeOfOptionalHeader + ); + NumberOfSections = (UINTN) (PeHdr->FileHeader.NumberOfSections); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (void *) (UINTN) ImageContext->ImageAddress + ); + + TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + sizeof(EFI_TE_IMAGE_HEADER) + ); + NumberOfSections = (UINTN) (TeHdr->NumberOfSections); + + } + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + // + // Load each section of the image + // + Section = FirstSection; + for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) { + + // + // Compute sections address + // + Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress); + End = PeCoffLoaderImageAddress ( + ImageContext, + Section->VirtualAddress + Section->Misc.VirtualSize - 1 + ); + if (ImageContext->IsTeImage) { + Base = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize); + End = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize); + } + + if (End > MaxEnd) { + MaxEnd = End; + } + // + // If the base start or end address resolved to 0, then fail. + // + if ((Base == NULL) || (End == NULL)) { + ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED; + return RETURN_LOAD_ERROR; + } + + // + // Read the section + // + Size = (UINTN) Section->Misc.VirtualSize; + if ((Size == 0) || (Size > Section->SizeOfRawData)) { + Size = (UINTN) Section->SizeOfRawData; + } + + if (Section->SizeOfRawData) { + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData, + &Size, + Base + ); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize, + &Size, + Base + ); + } + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + } + + // + // If raw size is less then virt size, zero fill the remaining + // + + if (Size < Section->Misc.VirtualSize) { + ZeroMem (Base + Size, Section->Misc.VirtualSize - Size); + } + + // + // Next Section + // + Section += 1; + } + + // + // Get image's entry point + // + if (!(ImageContext->IsTeImage)) { + ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress ( + ImageContext, + PeHdr->OptionalHeader.AddressOfEntryPoint + ); + } else { + ImageContext->EntryPoint = (PHYSICAL_ADDRESS) ( + (UINTN)ImageContext->ImageAddress + + (UINTN)TeHdr->AddressOfEntryPoint + + (UINTN)sizeof(EFI_TE_IMAGE_HEADER) - + (UINTN) TeHdr->StrippedSize + ); + } + + // + // Determine the size of the fixup data + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (!(ImageContext->IsTeImage)) { + if (PeHdr->OptionalHeader.NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) + &PeHdr->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } else { + ImageContext->FixupDataSize = 0; + } + } else { + DirectoryEntry = &TeHdr->DataDirectory[0]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } + // + // Consumer must allocate a buffer for the relocation fixup log. + // Only used for runtime drivers. + // + ImageContext->FixupData = NULL; + + // + // Load the Codeview info if present + // + if (ImageContext->DebugDirectoryEntryRva != 0) { + if (!(ImageContext->IsTeImage)) { + DebugEntry = PeCoffLoaderImageAddress ( + ImageContext, + ImageContext->DebugDirectoryEntryRva + ); + } else { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)( + ImageContext->ImageAddress + + ImageContext->DebugDirectoryEntryRva + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + } + + if (DebugEntry != NULL) { + TempDebugEntryRva = DebugEntry->RVA; + if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) { + Section--; + if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) { + TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize; + } else { + TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData; + } + } + + if (TempDebugEntryRva != 0) { + if (!(ImageContext->IsTeImage)) { + ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva); + } else { + ImageContext->CodeView = (VOID *)( + (UINTN)ImageContext->ImageAddress + + (UINTN)TempDebugEntryRva + + (UINTN)sizeof(EFI_TE_IMAGE_HEADER) - + (UINTN) TeHdr->StrippedSize + ); + } + + if (ImageContext->CodeView == NULL) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + if (DebugEntry->RVA == 0) { + Size = DebugEntry->SizeOfData; + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset, + &Size, + ImageContext->CodeView + ); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr->StrippedSize, + &Size, + ImageContext->CodeView + ); + // + // Should we apply fix up to this field according to the size difference between PE and TE? + // Because now we maintain TE header fields unfixed, this field will also remain as they are + // in original PE image. + // + } + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + DebugEntry->RVA = TempDebugEntryRva; + } + + switch (*(UINT32 *) ImageContext->CodeView) { + case CODEVIEW_SIGNATURE_NB10: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + default: + break; + } + } + } + } + + return Status; +} diff --git a/Tools/Source/TianoTools/GenFvImage/Common/EfiImage.h b/Tools/Source/TianoTools/GenFvImage/Common/EfiImage.h new file mode 100644 index 0000000000..0ad71d34bd --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/Common/EfiImage.h @@ -0,0 +1,701 @@ +/** @file + EFI image format for PE32+. Please note some data structures are different + for IA-32 and Itanium-based images, look for UINTN and the #ifdef EFI_IA64 + + @bug Fix text - doc as defined in MSFT EFI specification. + + Copyright (c) 2006, 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. + + Module Name: EfiImage.h + +**/ + +#ifndef __EFI_IMAGE_H__ +#define __EFI_IMAGE_H__ + +// +// PE32+ Subsystem type for EFI images +// +#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 + +// +// BugBug: Need to get a real answer for this problem. This is not in the +// PE specification. +// +// A SAL runtime driver does not get fixed up when a transition to +// virtual mode is made. In all other cases it should be treated +// like a EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER image +// +#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 + +// +// PE32+ Machine type for EFI images +// +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_IA64 0x0200 +#define IMAGE_FILE_MACHINE_EBC 0x0EBC +#define IMAGE_FILE_MACHINE_X64 0x8664 +// +// Support old names for backward compatible +// +#define EFI_IMAGE_MACHINE_IA32 IMAGE_FILE_MACHINE_I386 +#define EFI_IMAGE_MACHINE_IA64 IMAGE_FILE_MACHINE_IA64 +#define EFI_IMAGE_MACHINE_IPF IMAGE_FILE_MACHINE_IA64 +#define EFI_IMAGE_MACHINE_EBC IMAGE_FILE_MACHINE_EBC +#define EFI_IMAGE_MACHINE_X64 IMAGE_FILE_MACHINE_X64 + +#define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define EFI_IMAGE_OS2_SIGNATURE 0x454E // NE +#define EFI_IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define EFI_IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define EFI_IMAGE_EDOS_SIGNATURE 0x44454550 // PEED + +/// +/// PE images can start with an optional DOS header, so if an image is run +/// under DOS it can print an error message. +/// +typedef struct { + UINT16 e_magic; // Magic number + UINT16 e_cblp; // Bytes on last page of file + UINT16 e_cp; // Pages in file + UINT16 e_crlc; // Relocations + UINT16 e_cparhdr; // Size of header in paragraphs + UINT16 e_minalloc; // Minimum extra paragraphs needed + UINT16 e_maxalloc; // Maximum extra paragraphs needed + UINT16 e_ss; // Initial (relative) SS value + UINT16 e_sp; // Initial SP value + UINT16 e_csum; // Checksum + UINT16 e_ip; // Initial IP value + UINT16 e_cs; // Initial (relative) CS value + UINT16 e_lfarlc; // File address of relocation table + UINT16 e_ovno; // Overlay number + UINT16 e_res[4]; // Reserved words + UINT16 e_oemid; // OEM identifier (for e_oeminfo) + UINT16 e_oeminfo; // OEM information; e_oemid specific + UINT16 e_res2[10]; // Reserved words + UINT32 e_lfanew; // File address of new exe header +} EFI_IMAGE_DOS_HEADER; + +/// +/// File header format. +/// +typedef struct { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} EFI_IMAGE_FILE_HEADER; + +#define EFI_IMAGE_SIZEOF_FILE_HEADER 20 + +#define EFI_IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define EFI_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define EFI_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define EFI_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define EFI_IMAGE_FILE_SYSTEM 0x1000 // System File. +#define EFI_IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define EFI_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. +#define EFI_IMAGE_FILE_MACHINE_UNKNOWN 0 +#define EFI_IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define EFI_IMAGE_FILE_MACHINE_R3000 0x162 // MIPS* little-endian, 0540 big-endian +#define EFI_IMAGE_FILE_MACHINE_R4000 0x166 // MIPS* little-endian +#define EFI_IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP* +#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM* PowerPC Little-Endian +#define EFI_IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine +// +// * Other names and brands may be claimed as the property of others. +// + +/// +/// Directory format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 Size; +} EFI_IMAGE_DATA_DIRECTORY; + +#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16 + +typedef struct { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + UINT32 BaseOfBss; + UINT32 GprMask; + UINT32 CprMask[4]; + UINT32 GpValue; +} EFI_IMAGE_ROM_OPTIONAL_HEADER; + +#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 +#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER) + +typedef struct { + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} EFI_IMAGE_ROM_HEADERS; + +/// +/// @attention +/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64 +/// are for use ONLY by tools. All proper EFI code MUST use +/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!! +/// +#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b + +typedef struct { + // + // Standard fields. + // + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + // + // NT additional fields. + // + UINT32 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Win32VersionValue; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT32 SizeOfStackReserve; + UINT32 SizeOfStackCommit; + UINT32 SizeOfHeapReserve; + UINT32 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; +} EFI_IMAGE_OPTIONAL_HEADER32; + +/// +/// @attention +/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64 +/// are for use ONLY by tools. All proper EFI code MUST use +/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!! +/// +#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b + +typedef struct { + // + // Standard fields. + // + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + // + // NT additional fields. + // + UINT64 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Win32VersionValue; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT64 SizeOfStackReserve; + UINT64 SizeOfStackCommit; + UINT64 SizeOfHeapReserve; + UINT64 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; +} EFI_IMAGE_OPTIONAL_HEADER64; + +/// +/// @attention +/// EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY +/// by tools. All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!! +/// +typedef struct { + UINT32 Signature; + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader; +} EFI_IMAGE_NT_HEADERS32; + +#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32) + +typedef struct { + UINT32 Signature; + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} EFI_IMAGE_NT_HEADERS64; + +#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64) + +// +// Processor specific definition of EFI_IMAGE_OPTIONAL_HEADER so the +// type name EFI_IMAGE_OPTIONAL_HEADER is appropriate to the build. Same for +// EFI_IMAGE_NT_HEADERS. These definitions MUST be used by ALL EFI code. +// +#if defined (MDE_CPU_IA32) && !defined (BUILDING_TOOLS) || \ + defined (BUILDING_TOOLS) && defined (TOOL_BUILD_IA32_TARGET) + +// typedef EFI_IMAGE_OPTIONAL_HEADER32 EFI_IMAGE_OPTIONAL_HEADER; +typedef EFI_IMAGE_NT_HEADERS32 EFI_IMAGE_NT_HEADERS; + +#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_IA32) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#elif defined (MDE_CPU_IPF) && !defined (BUILDING_TOOLS) || \ + defined (BUILDING_TOOLS) && defined (TOOL_BUILD_IPF_TARGET) + +typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER; +typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS; + +#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_IPF) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#elif defined (MDE_CPU_X64) && !defined (BUILDING_TOOLS) || \ + defined (BUILDING_TOOLS) && defined (TOOL_BUILD_X64_TARGET) + +typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER; +typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS; + +#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) \ + (((Machine) == EFI_IMAGE_MACHINE_X64) || ((Machine) == EFI_IMAGE_MACHINE_EBC)) + +#elif defined (MDE_CPU_EBC) + +// +// This is just to make sure you can cross compile with the EBC compiiler. +// It does not make sense to have a PE loader coded in EBC. You need to +// understand the basic +// +typedef EFI_IMAGE_OPTIONAL_HEADER64 EFI_IMAGE_OPTIONAL_HEADER; +typedef EFI_IMAGE_NT_HEADERS64 EFI_IMAGE_NT_HEADERS; + +#define EFI_IMAGE_NT_OPTIONAL_HDR_MAGIC EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC +#define EFI_IMAGE_MACHINE_TYPE_SUPPORTED(Machine) ((Machine) == EFI_IMAGE_MACHINE_EBC) + +#else +#error Unknown Processor Type +#endif + + +#define EFI_IMAGE_FIRST_SECTION(ntheader) \ + ( \ + (EFI_IMAGE_SECTION_HEADER *) \ + ( \ + (UINT32) ntheader + \ + FIELD_OFFSET (EFI_IMAGE_NT_HEADERS, OptionalHeader) + \ + ((EFI_IMAGE_NT_HEADERS *) (ntheader))->FileHeader.SizeOfOptionalHeader \ + ) \ + ) + +// +// Subsystem Values +// +#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0 +#define EFI_IMAGE_SUBSYSTEM_NATIVE 1 +#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3. +#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5 +#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7 + +// +// Directory Entries +// +#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0 +#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1 +#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 +#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4 +#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5 +#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6 +#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 +#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 +#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9 +#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 + +// +// Section header format. +// +#define EFI_IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct { + UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} EFI_IMAGE_SECTION_HEADER; + +#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40 + +#define EFI_IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. +#define EFI_IMAGE_SCN_CNT_CODE 0x00000020 +#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 + +#define EFI_IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define EFI_IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +#define EFI_IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define EFI_IMAGE_SCN_LNK_COMDAT 0x00001000 + +#define EFI_IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define EFI_IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define EFI_IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define EFI_IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define EFI_IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define EFI_IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define EFI_IMAGE_SCN_ALIGN_64BYTES 0x00700000 + +#define EFI_IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define EFI_IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define EFI_IMAGE_SCN_MEM_NOT_PAGED 0x08000000 +#define EFI_IMAGE_SCN_MEM_SHARED 0x10000000 +#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define EFI_IMAGE_SCN_MEM_READ 0x40000000 +#define EFI_IMAGE_SCN_MEM_WRITE 0x80000000 + +/// +/// Symbol format. +/// +#define EFI_IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// +#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 // Symbol is undefined or is common. +#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 // Symbol is an absolute value. +#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 // Symbol is a special debug item. +// +// Type (fundamental) values. +// +#define EFI_IMAGE_SYM_TYPE_NULL 0 // no type. +#define EFI_IMAGE_SYM_TYPE_VOID 1 // +#define EFI_IMAGE_SYM_TYPE_CHAR 2 // type character. +#define EFI_IMAGE_SYM_TYPE_SHORT 3 // type short integer. +#define EFI_IMAGE_SYM_TYPE_INT 4 +#define EFI_IMAGE_SYM_TYPE_LONG 5 +#define EFI_IMAGE_SYM_TYPE_FLOAT 6 +#define EFI_IMAGE_SYM_TYPE_DOUBLE 7 +#define EFI_IMAGE_SYM_TYPE_STRUCT 8 +#define EFI_IMAGE_SYM_TYPE_UNION 9 +#define EFI_IMAGE_SYM_TYPE_ENUM 10 // enumeration. +#define EFI_IMAGE_SYM_TYPE_MOE 11 // member of enumeration. +#define EFI_IMAGE_SYM_TYPE_BYTE 12 +#define EFI_IMAGE_SYM_TYPE_WORD 13 +#define EFI_IMAGE_SYM_TYPE_UINT 14 +#define EFI_IMAGE_SYM_TYPE_DWORD 15 + +// +// Type (derived) values. +// +#define EFI_IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define EFI_IMAGE_SYM_DTYPE_POINTER 1 +#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2 +#define EFI_IMAGE_SYM_DTYPE_ARRAY 3 + +// +// Storage classes. +// +#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION (UINT8) -1 +#define EFI_IMAGE_SYM_CLASS_NULL 0 +#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1 +#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2 +#define EFI_IMAGE_SYM_CLASS_STATIC 3 +#define EFI_IMAGE_SYM_CLASS_REGISTER 4 +#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define EFI_IMAGE_SYM_CLASS_LABEL 6 +#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9 +#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12 +#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18 +#define EFI_IMAGE_SYM_CLASS_BLOCK 100 +#define EFI_IMAGE_SYM_CLASS_FUNCTION 101 +#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define EFI_IMAGE_SYM_CLASS_FILE 103 +#define EFI_IMAGE_SYM_CLASS_SECTION 104 +#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// +// type packing constants +// +#define EFI_IMAGE_N_BTMASK 017 +#define EFI_IMAGE_N_TMASK 060 +#define EFI_IMAGE_N_TMASK1 0300 +#define EFI_IMAGE_N_TMASK2 0360 +#define EFI_IMAGE_N_BTSHFT 4 +#define EFI_IMAGE_N_TSHIFT 2 + +// +// Communal selection types. +// +#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define EFI_IMAGE_COMDAT_SELECT_ANY 2 +#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + +/// +/// Relocation format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} EFI_IMAGE_RELOCATION; + +#define EFI_IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// +#define EFI_IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define EFI_IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address +#define EFI_IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address +#define EFI_IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address +#define EFI_IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included +#define EFI_IMAGE_REL_I386_SEG12 011 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define EFI_IMAGE_REL_I386_SECTION 012 +#define EFI_IMAGE_REL_I386_SECREL 013 +#define EFI_IMAGE_REL_I386_REL32 024 // PC-relative 32-bit reference to the symbols virtual address + +/// +/// Based relocation format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +} EFI_IMAGE_BASE_RELOCATION; + +#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// +#define EFI_IMAGE_REL_BASED_ABSOLUTE 0 +#define EFI_IMAGE_REL_BASED_HIGH 1 +#define EFI_IMAGE_REL_BASED_LOW 2 +#define EFI_IMAGE_REL_BASED_HIGHLOW 3 +#define EFI_IMAGE_REL_BASED_HIGHADJ 4 +#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define EFI_IMAGE_REL_BASED_IA64_IMM64 9 +#define EFI_IMAGE_REL_BASED_DIR64 10 + +/// +/// Line number format. +/// +typedef struct { + union { + UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; // Virtual address of line number. + } Type; + UINT16 Linenumber; // Line number. +} EFI_IMAGE_LINENUMBER; + +#define EFI_IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// +#define EFI_IMAGE_ARCHIVE_START_SIZE 8 +#define EFI_IMAGE_ARCHIVE_START "!\n" +#define EFI_IMAGE_ARCHIVE_END "`\n" +#define EFI_IMAGE_ARCHIVE_PAD "\n" +#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct { + UINT8 Name[16]; // File member name - `/' terminated. + UINT8 Date[12]; // File member date - decimal. + UINT8 UserID[6]; // File member user id - decimal. + UINT8 GroupID[6]; // File member group id - decimal. + UINT8 Mode[8]; // File member mode - octal. + UINT8 Size[10]; // File member size - decimal. + UINT8 EndHeader[2]; // String to end header. +} EFI_IMAGE_ARCHIVE_MEMBER_HEADER; + +#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +/// +/// DLL Export Format +/// +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32 AddressOfFunctions; + UINT32 AddressOfNames; + UINT32 AddressOfNameOrdinals; +} EFI_IMAGE_EXPORT_DIRECTORY; + +/// +/// DLL support. +/// Import Format +/// +typedef struct { + UINT16 Hint; + UINT8 Name[1]; +} EFI_IMAGE_IMPORT_BY_NAME; + +typedef struct { + union { + UINT32 Function; + UINT32 Ordinal; + EFI_IMAGE_IMPORT_BY_NAME *AddressOfData; + } u1; +} EFI_IMAGE_THUNK_DATA; + +#define EFI_IMAGE_ORDINAL_FLAG 0x80000000 +#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0) +#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + EFI_IMAGE_THUNK_DATA *FirstThunk; +} EFI_IMAGE_IMPORT_DESCRIPTOR; + +/// +/// Debug Format +/// +#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 + +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Type; + UINT32 SizeOfData; + UINT32 RVA; + UINT32 FileOffset; +} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY; + +#define CODEVIEW_SIGNATURE_NB10 0x3031424E // "NB10" +typedef struct { + UINT32 Signature; // "NB10" + UINT32 Unknown; + UINT32 Unknown2; + UINT32 Unknown3; + // + // Filename of .PDB goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY; + +#define CODEVIEW_SIGNATURE_RSDS 0x53445352 // "RSDS" +typedef struct { + UINT32 Signature; // "RSDS" + UINT32 Unknown; + UINT32 Unknown2; + UINT32 Unknown3; + UINT32 Unknown4; + UINT32 Unknown5; + // + // Filename of .PDB goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY; + +/// +/// Header format for TE images +/// +typedef struct { + UINT16 Signature; // signature for TE format = "VZ" + UINT16 Machine; // from the original file header + UINT8 NumberOfSections; // from the original file header + UINT8 Subsystem; // from original optional header + UINT16 StrippedSize; // how many bytes we removed from the header + UINT32 AddressOfEntryPoint; // offset to entry point -- from original optional header + UINT32 BaseOfCode; // from original image -- required for ITP debug + UINT64 ImageBase; // from original file header + EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; // only base relocation and debug directory +} EFI_TE_IMAGE_HEADER; + +#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56 // "VZ" + +// +// Data directory indexes in our TE image header +// +#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0 +#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1 + +#endif diff --git a/Tools/Source/TianoTools/GenFvImage/Ebc/PeCoffLoaderEx.c b/Tools/Source/TianoTools/GenFvImage/Ebc/PeCoffLoaderEx.c new file mode 100644 index 0000000000..e8cf8b6457 --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/Ebc/PeCoffLoaderEx.c @@ -0,0 +1,57 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + PeCoffLoaderEx.c + +Abstract: + + EBC Specific relocation fixups + +Revision History + +--*/ + + + + +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IA-32 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - Unsupported now + +--*/ +{ + return RETURN_UNSUPPORTED; +} diff --git a/Tools/Source/TianoTools/GenFvImage/GenFvImageExe.c b/Tools/Source/TianoTools/GenFvImage/GenFvImageExe.c new file mode 100644 index 0000000000..d0117b8ae9 --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/GenFvImageExe.c @@ -0,0 +1,299 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenFvImageExe.c + +Abstract: + + This contains all code necessary to build the GenFvImage.exe utility. + This utility relies heavily on the GenFvImage Lib. Definitions for both + can be found in the Tiano Firmware Volume Generation Utility + Specification, review draft. + +--*/ + +// +// File included in build +// +#include "GenFvImageExe.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +VOID +PrintUtilityInfo ( + VOID + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ( + "%s - Tiano Firmware Volume Generation Utility."" Version %i.%i\n\n", + UTILITY_NAME, + UTILITY_MAJOR_VERSION, + UTILITY_MINOR_VERSION + ); +} + +VOID +PrintUsage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("Usage: %s -I FvInfFileName\n", UTILITY_NAME); + printf (" Where:\n"); + printf ("\tFvInfFileName is the name of the image description file.\n\n"); +} + +int +main ( + IN INTN argc, + IN CHAR8 **argv + ) +/*++ + +Routine Description: + + This utility uses GenFvImage.Lib to build a firmware volume image. + +Arguments: + + FvInfFileName The name of an FV image description file. + + Arguments come in pair in any order. + -I FvInfFileName + +Returns: + + EFI_SUCCESS No error conditions detected. + EFI_INVALID_PARAMETER One or more of the input parameters is invalid. + EFI_OUT_OF_RESOURCES A resource required by the utility was unavailable. + Most commonly this will be memory allocation + or file creation. + EFI_LOAD_ERROR GenFvImage.lib could not be loaded. + EFI_ABORTED Error executing the GenFvImage lib. + +--*/ +{ + EFI_STATUS Status; + CHAR8 InfFileName[_MAX_PATH]; + CHAR8 *InfFileImage; + UINTN InfFileSize; + UINT8 *FvImage; + UINTN FvImageSize; + UINT8 Index; + CHAR8 FvFileNameBuffer[_MAX_PATH]; + CHAR8 *FvFileName; + FILE *FvFile; + FILE *SymFile; + CHAR8 SymFileNameBuffer[_MAX_PATH]; + CHAR8 *SymFileName; + UINT8 *SymImage; + UINTN SymImageSize; + CHAR8 *CurrentSymString; + + FvFileName = FvFileNameBuffer; + SymFileName = SymFileNameBuffer; + + SetUtilityName (UTILITY_NAME); + // + // Display utility information + // + PrintUtilityInfo (); + + // + // Verify the correct number of arguments + // + if (argc != MAX_ARGS) { + Error (NULL, 0, 0, "invalid number of input parameters specified", NULL); + PrintUsage (); + return GetUtilityStatus (); + } + // + // Initialize variables + // + strcpy (InfFileName, ""); + + // + // Parse the command line arguments + // + for (Index = 1; Index < MAX_ARGS; Index += 2) { + // + // Make sure argument pair begin with - or / + // + if (argv[Index][0] != '-' && argv[Index][0] != '/') { + Error (NULL, 0, 0, argv[Index], "argument pair must begin with \"-\" or \"/\""); + PrintUsage (); + return GetUtilityStatus (); + } + // + // Make sure argument specifier is only one letter + // + if (argv[Index][2] != 0) { + Error (NULL, 0, 0, argv[Index], "unrecognized argument"); + PrintUsage (); + return GetUtilityStatus (); + } + // + // Determine argument to read + // + switch (argv[Index][1]) { + + case 'I': + case 'i': + if (strlen (InfFileName) == 0) { + strcpy (InfFileName, argv[Index + 1]); + } else { + Error (NULL, 0, 0, argv[Index + 1], "FvInfFileName may only be specified once"); + PrintUsage (); + return GetUtilityStatus (); + } + break; + + default: + Error (NULL, 0, 0, argv[Index], "unrecognized argument"); + PrintUsage (); + return GetUtilityStatus (); + break; + } + } + // + // Read the INF file image + // + Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize); + if (EFI_ERROR (Status)) { + return STATUS_ERROR; + } + // + // Call the GenFvImage lib + // + Status = GenerateFvImage ( + InfFileImage, + InfFileSize, + &FvImage, + &FvImageSize, + &FvFileName, + &SymImage, + &SymImageSize, + &SymFileName + ); + + if (EFI_ERROR (Status)) { + switch (Status) { + + case EFI_INVALID_PARAMETER: + Error (NULL, 0, 0, "invalid parameter passed to GenFvImage Lib", NULL); + return GetUtilityStatus (); + break; + + case EFI_ABORTED: + Error (NULL, 0, 0, "error detected while creating the file image", NULL); + return GetUtilityStatus (); + break; + + case EFI_OUT_OF_RESOURCES: + Error (NULL, 0, 0, "GenFvImage Lib could not allocate required resources", NULL); + return GetUtilityStatus (); + break; + + case EFI_VOLUME_CORRUPTED: + Error (NULL, 0, 0, "no base address was specified, but the FV.INF included a PEI or BSF file", NULL); + return GetUtilityStatus (); + break; + + case EFI_LOAD_ERROR: + Error (NULL, 0, 0, "could not load FV image generation library", NULL); + return GetUtilityStatus (); + break; + + default: + Error (NULL, 0, 0, "GenFvImage Lib returned unknown status", "status returned = 0x%X", Status); + return GetUtilityStatus (); + break; + } + } + // + // Write file + // + FvFile = fopen (FvFileName, "wb"); + if (FvFile == NULL) { + Error (NULL, 0, 0, FvFileName, "could not open output file"); + free (FvImage); + free (SymImage); + return GetUtilityStatus (); + } + + if (fwrite (FvImage, 1, FvImageSize, FvFile) != FvImageSize) { + Error (NULL, 0, 0, FvFileName, "failed to write to output file"); + free (FvImage); + free (SymImage); + fclose (FvFile); + return GetUtilityStatus (); + } + + fclose (FvFile); + free (FvImage); + + // + // Write symbol file + // + if (strcmp (SymFileName, "")) { + SymFile = fopen (SymFileName, "wt"); + if (SymFile == NULL) { + Error (NULL, 0, 0, SymFileName, "could not open output symbol file"); + free (SymImage); + return GetUtilityStatus (); + } + + fprintf (SymFile, "TEXTSYM format | V1.0\n"); + + CurrentSymString = SymImage; + while (((UINTN) CurrentSymString - (UINTN) SymImage) < SymImageSize) { + fprintf (SymFile, "%s", CurrentSymString); + CurrentSymString = (CHAR8 *) (((UINTN) CurrentSymString) + strlen (CurrentSymString) + 1); + } + + fclose (SymFile); + } + + free (SymImage); + + return GetUtilityStatus (); +} diff --git a/Tools/Source/TianoTools/GenFvImage/GenFvImageExe.h b/Tools/Source/TianoTools/GenFvImage/GenFvImageExe.h new file mode 100644 index 0000000000..9b97935656 --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/GenFvImageExe.h @@ -0,0 +1,98 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenFvImageExe.h + +Abstract: + + Definitions for the PeimFixup exe utility. + +--*/ + +// +// Coded to Tiano Coding Standards +// +#ifndef _EFI_GEN_FV_IMAGE_EXE_H +#define _EFI_GEN_FV_IMAGE_EXE_H + +#include +#include +#include +#include "GenFvImageLib.h" + +// +// Utility Name +// +#define UTILITY_NAME "GenFvImage" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 +#define UTILITY_DATE __DATE__ + +// +// The maximum number of arguments accepted from the command line. +// +#define MAX_ARGS 3 + +// +// The function that displays general utility information +// +VOID +PrintUtilityInfo ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +// +// The function that displays the utility usage message. +// +VOID +PrintUsage ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/Tools/Source/TianoTools/GenFvImage/GenFvImageLib.c b/Tools/Source/TianoTools/GenFvImage/GenFvImageLib.c new file mode 100644 index 0000000000..c4515001d8 --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/GenFvImageLib.c @@ -0,0 +1,2871 @@ +/*++ +i + +Copyright (c) 2004, 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. + +Module Name: + + GenFvImageLib.c + +Abstract: + + This file contains functions required to generate a Firmware Volume. + +--*/ + +// +// Include files +// +#define EFI_SPECIFICATION_VERSION 0x00020000 +#define EDK_RELEASE_VERSION 0x00020000 +#ifdef __GNUC__ +#include +#include +#endif +#include +#ifndef __GNUC__ +#include +#endif +#include +#include +#include +#include "GenFvImageLib.h" +#include "GenFvImageLibInternal.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +// +// Local function prototypes +// +EFI_STATUS +GetPe32Info ( + IN UINT8 *Pe32, + OUT UINT32 *EntryPoint, + OUT UINT32 *BaseOfCode, + OUT UINT16 *MachineType + ); + +// +// Local function implementations. +// +EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID; +EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f }; + +// +// This data array will be located at the base of the Firmware Volume Header (FVH) +// in the boot block. It must not exceed 14 bytes of code. The last 2 bytes +// will be used to keep the FVH checksum consistent. +// This code will be run in response to a starutp IPI for HT-enabled systems. +// +#define SIZEOF_STARTUP_DATA_ARRAY 0x10 + +UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = { + // + // EA D0 FF 00 F0 ; far jmp F000:FFD0 + // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes + // 0, 0 ; Checksum Padding + // + 0xEA, + 0xD0, + 0xFF, + 0x0, + 0xF0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = { + // + // EB CE ; jmp short ($-0x30) + // ; (from offset 0x0 to offset 0xFFD0) + // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes + // 0, 0 ; Checksum Padding + // + 0xEB, + 0xCE, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +EFI_STATUS +ParseFvInf ( + IN MEMORY_FILE *InfFile, + IN FV_INFO *FvInfo + ) +/*++ + +Routine Description: + + This function parses a FV.INF file and copies info into a FV_INFO structure. + +Arguments: + + InfFile Memory file image. + FvInfo Information read from INF file. + +Returns: + + EFI_SUCCESS INF file information successfully retrieved. + EFI_ABORTED INF file has an invalid format. + EFI_NOT_FOUND A required string was not found in the INF file. +--*/ +{ + CHAR8 Value[_MAX_PATH]; + UINT64 Value64; + UINTN Index; + EFI_STATUS Status; + + // + // Initialize FV info + // + memset (FvInfo, 0, sizeof (FV_INFO)); + + // + // Read the FV base address + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Get the base address + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value"); + return EFI_ABORTED; + } + + FvInfo->BaseAddress = Value64; + } else { + Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value"); + return EFI_ABORTED; + } + // + // Read the FV Guid + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Get the guid value + // + Status = StringToGuid (Value, &FvInfo->FvGuid); + if (EFI_ERROR (Status)) { + memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID)); + } + } else { + memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID)); + } + // + // Read the FV file name + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // copy the file name + // + strcpy (FvInfo->FvName, Value); + } else { + Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified"); + return EFI_ABORTED; + } + // + // Read the Sym file name + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // copy the file name + // + strcpy (FvInfo->SymName, Value); + } else { + // + // Symbols not required, so init to NULL. + // + strcpy (FvInfo->SymName, ""); + } + // + // Read the read disabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the read disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the read enabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the read disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the read status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the read disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_READ_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified"); + return Status; + } + // + // Read the write disabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the write disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the write enabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the write disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the write status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the write disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified"); + return Status; + } + // + // Read the lock capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the lock status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified"); + return Status; + } + // + // Read the sticky write attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified"); + return Status; + } + // + // Read the memory mapped attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified"); + return Status; + } + // + // Read the erase polarity attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, ONE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY; + } else if (strcmp (Value, ZERO_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified"); + return Status; + } + // + // Read the alignment capabilities attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the word alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified"); + return Status; + } + // + // Read the dword alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified"); + return Status; + } + // + // Read the word alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified"); + return Status; + } + // + // Read the qword alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified"); + return Status; + } + // + // Read the 32 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified"); + return Status; + } + // + // Read the 64 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified"); + return Status; + } + // + // Read the 128 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified"); + return Status; + } + // + // Read the 256 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified"); + return Status; + } + // + // Read the 512 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified"); + return Status; + } + // + // Read the 1K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified"); + return Status; + } + // + // Read the 2K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified"); + return Status; + } + // + // Read the 4K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified"); + return Status; + } + // + // Read the 8K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified"); + return Status; + } + // + // Read the 16K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified"); + return Status; + } + // + // Read the 32K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified"); + return Status; + } + // + // Read the 64K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified"); + return Status; + } + + if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) && + ( + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K) + ) + ) { + Error ( + NULL, + 0, + 0, + "illegal combination of alignment attributes", + "if %s is not %s, no individual alignments can be %s", + EFI_FVB_ALIGNMENT_CAP_STRING, + TRUE_STRING, + TRUE_STRING + ); + return EFI_ABORTED; + } + // + // Read block maps + // + for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) { + // + // Read the number of blocks + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the number of blocks + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING); + return EFI_ABORTED; + } + + FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64; + } else { + // + // If there is no number of blocks, but there is a size, then we have a mismatched pair + // and should return an error. + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value); + if (!EFI_ERROR (Status)) { + Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } else { + // + // We are done + // + break; + } + } + // + // Read the size of blocks + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the number of blocks + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } + + FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64; + } else { + // + // There is a number of blocks, but there is no size, so we have a mismatched pair + // and should return an error. + // + Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } + } + // + // Read files + // + for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) { + // + // Read the number of blocks + // + Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the file + // + strcpy (FvInfo->FvFiles[Index], Value); + } else { + break; + } + } + + if (FindSection (InfFile, COMPONENT_SECTION_STRING)) { + Index = 0; + // + // Read component FV_VARIABLE + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING); + } + + Index++; + // + // Read component FV_EVENT_LOG + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING); + } + + Index++; + // + // Read component FV_FTW_WORKING + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING); + } + + Index++; + // + // Read component FV_FTW_SPARE + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING); + } + } + // + // Compute size for easy access later + // + FvInfo->Size = 0; + for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) { + FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength; + } + + return EFI_SUCCESS; +} + +VOID +UpdateFfsFileState ( + IN EFI_FFS_FILE_HEADER *FfsFile, + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +/*++ + +Routine Description: + + This function changes the FFS file attributes based on the erase polarity + of the FV. + +Arguments: + + FfsFile File header. + FvHeader FV header. + +Returns: + + None + +--*/ +{ + if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + FfsFile->State = (UINT8)~(FfsFile->State); + } +} + +EFI_STATUS +ReadFfsAlignment ( + IN EFI_FFS_FILE_HEADER *FfsFile, + IN OUT UINT32 *Alignment + ) +/*++ + +Routine Description: + + This function determines the alignment of the FFS input file from the file + attributes. + +Arguments: + + FfsFile FFS file to parse + Alignment The minimum required alignment of the FFS file, in bytes + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + +--*/ +{ + // + // Verify input parameters. + // + if (FfsFile == NULL || Alignment == NULL) { + return EFI_INVALID_PARAMETER; + } + + switch ((FfsFile->Attributes >> 3) & 0x07) { + + case 0: + // + // 1 byte alignment + // + *Alignment = (1 << 0); + break; + + case 1: + // + // 16 byte alignment + // + *Alignment = (1 << 4); + break; + + case 2: + // + // 128 byte alignment + // + *Alignment = (1 << 7); + break; + + case 3: + // + // 512 byte alignment + // + *Alignment = (1 << 9); + break; + + case 4: + // + // 1K byte alignment + // + *Alignment = (1 << 10); + break; + + case 5: + // + // 4K byte alignment + // + *Alignment = (1 << 12); + break; + + case 6: + // + // 32K byte alignment + // + *Alignment = (1 << 15); + break; + + case 7: + // + // 64K byte alignment + // + *Alignment = (1 << 16); + break; + + default: + Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AddPadFile ( + IN OUT MEMORY_FILE *FvImage, + IN UINT32 DataAlignment + ) +/*++ + +Routine Description: + + This function adds a pad file to the FV image if it required to align the + data of the next file. + +Arguments: + + FvImage The memory image of the FV to add it to. The current offset + must be valid. + DataAlignment The data alignment of the next FFS file. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete + the pad file add. + +--*/ +{ + EFI_FFS_FILE_HEADER *PadFile; + EFI_GUID PadFileGuid; + UINTN PadFileSize; + + // + // Verify input parameters. + // + if (FvImage == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Basic assumption is we start from an 8 byte aligned address + // and our file header is a multiple of 8 bytes + // + assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0); + assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0); + + // + // Check if a pad file is necessary + // + if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) { + return EFI_SUCCESS; + } + // + // Write pad file header + // + PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; + + // + // Verify that we have enough space for the file header + // + if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) { + return EFI_OUT_OF_RESOURCES; + } + +#ifdef __GNUC__ + { + uuid_t tmp_id; + uuid_generate (tmp_id); + memcpy (&PadFileGuid, tmp_id, sizeof (EFI_GUID)); + } +#else + UuidCreate (&PadFileGuid); +#endif + memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID)); + PadFile->Type = EFI_FV_FILETYPE_FFS_PAD; + PadFile->Attributes = 0; + + // + // Calculate the pad file size + // + // + // This is the earliest possible valid offset (current plus pad file header + // plus the next file header) + // + PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2); + + // + // Add whatever it takes to get to the next aligned address + // + while ((PadFileSize % DataAlignment) != 0) { + PadFileSize++; + } + // + // Subtract the next file header size + // + PadFileSize -= sizeof (EFI_FFS_FILE_HEADER); + + // + // Subtract the starting offset to get size + // + PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage; + + // + // Write pad file size (calculated size minus next file header size) + // + PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF); + PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF); + PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF); + + // + // Fill in checksums and state, they must be 0 for checksumming. + // + PadFile->IntegrityCheck.Checksum.Header = 0; + PadFile->IntegrityCheck.Checksum.File = 0; + PadFile->State = 0; + PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER)); + if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) { + PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize); + } else { + PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) PadFile, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + + // + // Verify that we have enough space (including the padding + // + if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) { + return EFI_OUT_OF_RESOURCES; + } + // + // Update the current FV pointer + // + FvImage->CurrentFilePointer += PadFileSize; + + return EFI_SUCCESS; +} + +BOOLEAN +IsVtfFile ( + IN EFI_FFS_FILE_HEADER *FileBuffer + ) +/*++ + +Routine Description: + + This function checks the header to validate if it is a VTF file + +Arguments: + + FileBuffer Buffer in which content of a file has been read. + +Returns: + + TRUE If this is a VTF file + FALSE If this is not a VTF file + +--*/ +{ + EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID; + if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) { + return TRUE; + } else { + return FALSE; + } +} + +EFI_STATUS +FfsRebaseImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINT32 *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINT32 Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +RebaseFfsFile ( + IN OUT EFI_FFS_FILE_HEADER *FfsFile, + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +/*++ + +Routine Description: + + This function determines if a file is XIP and should be rebased. It will + rebase any PE32 sections found in the file using the base address. + +Arguments: + + FfsFile A pointer to Ffs file image. + BaseAddress The base address to use for rebasing the file image. + +Returns: + + EFI_SUCCESS The image was properly rebased. + EFI_INVALID_PARAMETER An input parameter is invalid. + EFI_ABORTED An error occurred while rebasing the input file image. + EFI_OUT_OF_RESOURCES Could not allocate a required resource. + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + UINTN MemoryImagePointer; + UINTN MemoryImagePointerAligned; + + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS EntryPoint; + + UINT32 Pe32FileSize; + UINT32 NewPe32BaseAddress; + + UINTN Index; + EFI_FILE_SECTION_POINTER CurrentPe32Section; + UINT8 FileGuidString[80]; + + // + // Verify input parameters + // + if (FfsFile == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Convert the GUID to a string so we can at least report which file + // if we find an error. + // + PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE); + + // + // Do some nominal checks on the file, then check for XIP. + // + Status = VerifyFfsFile (FfsFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "invalid FFS file", FileGuidString); + return EFI_INVALID_PARAMETER; + } + + if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE && + FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE && + FfsFile->Type != EFI_FV_FILETYPE_PEIM + ) { + // + // File is not XIP, so don't rebase + // + return EFI_SUCCESS; + } + // + // Rebase each PE32 section + // + for (Index = 1;; Index++) { + Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section); + if (EFI_ERROR (Status)) { + break; + } + // + // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section + // + NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile); + + // + // Initialize context + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION)); + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead; + + Status = PeCoffLoaderGetImageInfo (&ImageContext); + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString); + return Status; + } + // + // Allocate a buffer for the image to be loaded into. + // + Pe32FileSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size); + MemoryImagePointer = (UINTN) (malloc (Pe32FileSize + 0x1000)); + MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12); + if (MemoryImagePointerAligned == 0) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return EFI_OUT_OF_RESOURCES; + } + + // + // bugbug + // + ImageContext.ImageAddress = MemoryImagePointerAligned; + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "LoadImage() failure", FileGuidString); + free ((VOID *) MemoryImagePointer); + return Status; + } + + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString); + free ((VOID *) MemoryImagePointer); + return Status; + } + + ImageAddress = ImageContext.ImageAddress; + ImageSize = ImageContext.ImageSize; + EntryPoint = ImageContext.EntryPoint; + + if (ImageSize > Pe32FileSize) { + Error ( + NULL, + 0, + 0, + "rebased PE32 is larger than original PE32 image", + "0x%X > 0x%X on file %s", + ImageSize, + Pe32FileSize, + FileGuidString + ); + free ((VOID *) MemoryImagePointer); + return EFI_ABORTED; + } + + memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize); + + free ((VOID *) MemoryImagePointer); + } + // + // the above for loop will always exit with EFI_NOT_FOUND if it completes + // normally. If Index == 1 at exit, then no PE32 sections were found. If it + // exits with any other error code, then something broke... + // + if (Status != EFI_NOT_FOUND) { + Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString); + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AddSymFile ( + IN UINT64 BaseAddress, + IN EFI_FFS_FILE_HEADER *FfsFile, + IN OUT MEMORY_FILE *SymImage, + IN CHAR8 *SourceFileName + ) +/*++ + +Routine Description: + + This function adds the SYM tokens in the source file to the destination file. + The SYM tokens are updated to reflect the base address. + +Arguments: + + BaseAddress The base address for the new SYM tokens. + FfsFile Pointer to the beginning of the FFS file in question. + SymImage The memory file to update with symbol information. + SourceFileName The source file. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + +--*/ +{ + FILE *SourceFile; + + CHAR8 Buffer[_MAX_PATH]; + CHAR8 Type[_MAX_PATH]; + CHAR8 Address[_MAX_PATH]; + CHAR8 Section[_MAX_PATH]; + CHAR8 Token[_MAX_PATH]; + CHAR8 SymFileName[_MAX_PATH]; + CHAR8 CodeModuleName[_MAX_PATH]; + CHAR8 *Ptr; + + UINT64 TokenAddress; + + EFI_STATUS Status; + EFI_FILE_SECTION_POINTER Pe32Section; + UINT32 EntryPoint; + UINT32 BaseOfCode; + UINT16 MachineType; + EFI_TE_IMAGE_HEADER *TeHdr; + + TeHdr = NULL; + // + // Verify input parameters. + // + if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) { + Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL); + return EFI_INVALID_PARAMETER; + } + // + // Check if we want to add this file + // + // + // Get the file name + // + strcpy (Buffer, SourceFileName); + + // + // Copy the file name for the path of the sym file and truncate the name portion. + // + strcpy (SymFileName, Buffer); + Ptr = strrchr (SymFileName, '\\'); + assert (Ptr); + Ptr[0] = 0; + + // + // Find the file extension and make it lower case + // + Ptr = strrchr (SymFileName, '.'); + if (Ptr != NULL) { + strlwr (Ptr); + } + // + // Check if it is PEI file + // + if (strstr (Buffer, ".pei") != NULL) { + // + // Find the human readable portion + // + if (!strtok (Buffer, "-") || + !strtok (NULL, "-") || + !strtok (NULL, "-") || + !strtok (NULL, "-") || + !strtok (NULL, "-") || + !strcpy (Buffer, strtok (NULL, ".")) + ) { + Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL); + return EFI_ABORTED; + } + // + // Save code module name + // + strcpy (CodeModuleName, Buffer); + + // + // Add the symbol file name and extension to the file path. + // + strcat (Buffer, ".sym"); + strcat (SymFileName, "\\"); + strcat (SymFileName, Buffer); + } else { + // + // Only handle PEIM files. + // + return EFI_SUCCESS; + } + // + // Find PE32 section + // + Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section); + + // + // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address + // + if (Status == EFI_NOT_FOUND) { + Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section); + if (Status == EFI_NOT_FOUND) { + BaseOfCode = 0x60; + } else { + TeHdr = (EFI_TE_IMAGE_HEADER *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_COMMON_SECTION_HEADER)); + BaseOfCode = TeHdr->BaseOfCode - TeHdr->StrippedSize; + } + } else if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL); + return Status; + } else { + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL); + return Status; + } + } + // + // Open the source file + // + SourceFile = fopen (SymFileName, "r"); + if (SourceFile == NULL) { + // + // SYM files are not required. + // + return EFI_SUCCESS; + } + // + // Read the first line + // + if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) { + Buffer[0] = 0; + } + // + // Make sure it matches the expected sym format + // + if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) { + fclose (SourceFile); + Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL); + return EFI_ABORTED; + } + // + // Read in the file + // + while (feof (SourceFile) == 0) { + // + // Read a line + // + if (fscanf ( + SourceFile, + "%s | %s | %s | %s\n", + Type, + Address, + Section, + Token + ) == 4) { + // + // If the token starts with "??" ignore it + // + if (Token[0] == '?' && Token[1] == '?') { + continue; + } + // + // Get the token address + // + AsciiStringToUint64 (Address, TRUE, &TokenAddress); + + // + // Add the base address + // + TokenAddress += BaseAddress; + + // + // If PE32 then find the start of code. For PIC it is hardcoded. + // + if (TeHdr == NULL && Pe32Section.Pe32Section) { + // + // Add the offset of the PE32 section + // + TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile; + + // + // Add the size of the PE32 section header + // + TokenAddress += sizeof (EFI_PE32_SECTION); + } else if (TeHdr != NULL) { + // + // Add the Te section and FfsHeader + // + // + // BUGBUG: Don't know why this is 0x28 bytes. + // + TokenAddress += (UINTN) TeHdr - (UINTN) FfsFile + 0x28; + } else { + // + // BUGBUG: Don't know why this is 0x28 bytes. + // + TokenAddress += 0x28; + } + // + // Add the beginning of the code + // + TokenAddress += BaseOfCode; + + sprintf ( + Buffer, + "%s | %016I64X | %s | _%s%s\n", + Type, + TokenAddress, + Section, + CodeModuleName, + Token + ); + memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1); + SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1); + } + } + + fclose (SourceFile); + return EFI_SUCCESS; +} + +EFI_STATUS +AddFile ( + IN OUT MEMORY_FILE *FvImage, + IN FV_INFO *FvInfo, + IN UINTN Index, + IN OUT EFI_FFS_FILE_HEADER **VtfFileImage, + IN OUT MEMORY_FILE *SymImage + ) +/*++ + +Routine Description: + + This function adds a file to the FV image. The file will pad to the + appropriate alignment if required. + +Arguments: + + FvImage The memory image of the FV to add it to. The current offset + must be valid. + FvInfo Pointer to information about the FV. + Index The file in the FvInfo file list to add. + VtfFileImage A pointer to the VTF file within the FvImage. If this is equal + to the end of the FvImage then no VTF previously found. + SymImage The memory image of the Sym file to update if symbols are present. + The current offset must be valid. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add. + +--*/ +{ + FILE *NewFile; + UINTN FileSize; + UINT8 *FileBuffer; + UINTN NumBytesRead; + UINT32 CurrentFileAlignment; + EFI_STATUS Status; + EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress; + UINT8 VtfHeaderChecksum; + UINT8 VtfFileChecksum; + UINT8 FileState; + EFI_FFS_FILE_TAIL TailValue; + UINT32 TailSize; + // + // Verify input parameters. + // + if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Read the file to add + // + NewFile = fopen (FvInfo->FvFiles[Index], "rb"); + + if (NewFile == NULL) { + Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading"); + return EFI_ABORTED; + } + // + // Get the file size + // +#ifdef __GNUC__ + { + struct stat stat_buf; + fstat(fileno(NewFile), &stat_buf); + FileSize = stat_buf.st_size; + } +#else + FileSize = _filelength (fileno (NewFile)); +#endif + + // + // Read the file into a buffer + // + FileBuffer = malloc (FileSize); + if (FileBuffer == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return EFI_OUT_OF_RESOURCES; + } + + NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile); + + // + // Done with the file, from this point on we will just use the buffer read. + // + fclose (NewFile); + + // + // Verify read successful + // + if (NumBytesRead != sizeof (UINT8) * FileSize) { + free (FileBuffer); + Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to read input file contents"); + return EFI_ABORTED; + } + // + // Verify space exists to add the file + // + if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) { + Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file"); + return EFI_OUT_OF_RESOURCES; + } + // + // Update the file state based on polarity of the FV. + // + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) FileBuffer, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + + // + // If we have a VTF file, add it at the top. + // + if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) { + if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) { + // + // No previous VTF, add this one. + // + *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize); + // + // Sanity check. The file MUST align appropriately + // + if ((((UINTN) *VtfFileImage) & 0x07) != 0) { + Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL); + } + // + // copy VTF File Header + // + memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER)); + + // + // Copy VTF body + // + memcpy ( + (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER), + FileBuffer + sizeof (EFI_FFS_FILE_HEADER), + FileSize - sizeof (EFI_FFS_FILE_HEADER) + ); + + // + // re-calculate the VTF File Header + // + FileState = (*VtfFileImage)->State; + (*VtfFileImage)->State = 0; + *(UINT32 *) ((*VtfFileImage)->Size) = FileSize; + (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0; + (*VtfFileImage)->IntegrityCheck.Checksum.File = 0; + + VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER)); + (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum; + // + // Determine if it has a tail + // + if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailSize = sizeof (EFI_FFS_FILE_TAIL); + } else { + TailSize = 0; + } + + if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) { + VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize); + (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum; + } else { + (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + // + // If it has a file tail, update it + // + if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference)); + *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue; + } + (*VtfFileImage)->State = FileState; + free (FileBuffer); + return EFI_SUCCESS; + } else { + // + // Already found a VTF file. + // + Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL); + free (FileBuffer); + return EFI_ABORTED; + } + } + // + // Check if alignment is required + // + Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Add pad file if necessary + // + Status = AddPadFile (FvImage, CurrentFileAlignment); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not align the file data properly.\n"); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Add file + // + if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) { + // + // Copy the file + // + memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize); + + // + // If the file is XIP, rebase + // + CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage); + // + // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress); + // if (EFI_ERROR(Status)) { + // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]); + // return EFI_ABORTED; + // } + // + // Update Symbol file + // + Status = AddSymFile ( + CurrentFileBaseAddress, + (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer, + SymImage, + FvInfo->FvFiles[Index] + ); + assert (!EFI_ERROR (Status)); + + // + // Update the current pointer in the FV image + // + FvImage->CurrentFilePointer += FileSize; + } else { + printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]); + return EFI_ABORTED; + } + // + // Make next file start at QWord Boundry + // + while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) { + FvImage->CurrentFilePointer++; + } + // + // Free allocated memory. + // + free (FileBuffer); + + return EFI_SUCCESS; +} + +EFI_STATUS +AddVariableBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + VARIABLE_STORE_HEADER *VarStoreHeader; + // + // Variable block should exclude FvHeader. Since the length of + // FvHeader depends on the block map, which is variable length, + // we could only decide the actual variable block length here. + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage; + FvImage = FvImage + FvHeader->HeaderLength; + + VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage; + + VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE; + VarStoreHeader->Size = Size - FvHeader->HeaderLength; + VarStoreHeader->Format = VARIABLE_STORE_FORMATTED; + VarStoreHeader->State = VARIABLE_STORE_HEALTHY; + VarStoreHeader->Reserved = 0; + VarStoreHeader->Reserved1 = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +AddEventLogBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +AddFTWWorkingBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader; + UINT32 Crc32; + + Crc32 = 0; + FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage; + memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID)); + FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER); + CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32); + FTWHeader->Crc = Crc32; + if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) { + FTWHeader->WorkingBlockValid = 0; + FTWHeader->WorkingBlockInvalid = 1; + } else { + FTWHeader->WorkingBlockValid = 1; + FTWHeader->WorkingBlockInvalid = 0; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AddFTWSpareBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +GenNonFFSFv ( + IN UINT8 *FvImage, + IN FV_INFO *FvInfo + ) +/*++ + +Routine Description: + + This function generate the non FFS FV image, such as the working block + and spare block. How each component of the FV is built is component + specific. + +Arguments: + + FvImage The memory image of the FV to add it to. The current offset + must be valid. + FvInfo Pointer to information about the FV. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add. + +--*/ +{ + UINTN Index; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + UINT64 TotalSize; + + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage; + TotalSize = 0; + + for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) { + if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) { + AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) { + AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) { + AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else if (stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) { + AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else { + printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName); + return EFI_ABORTED; + } + + FvImage = FvImage + FvInfo->FvComponents[Index].Size; + TotalSize = TotalSize + FvInfo->FvComponents[Index].Size; + } + // + // Index and TotalSize is zero mean there's no component, so this is an empty fv + // + if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) { + printf ("Error. Component size does not sum up to FV size.\n"); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PadFvImage ( + IN MEMORY_FILE *FvImage, + IN EFI_FFS_FILE_HEADER *VtfFileImage + ) +/*++ + +Routine Description: + + This function places a pad file between the last file in the FV and the VTF + file if the VTF file exists. + +Arguments: + + FvImage Memory file for the FV memory image + VtfFileImage The address of the VTF file. If this is the end of the FV + image, no VTF exists and no pad file is needed. + +Returns: + + EFI_SUCCESS Completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was NULL. + +--*/ +{ + EFI_FFS_FILE_HEADER *PadFile; + UINTN FileSize; + + // + // If there is no VTF or the VTF naturally follows the previous file without a + // pad file, then there's nothing to do + // + if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) { + return EFI_SUCCESS; + } + // + // Pad file starts at beginning of free space + // + PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; + + // + // write header + // + memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID)); + PadFile->Type = EFI_FV_FILETYPE_FFS_PAD; + PadFile->Attributes = 0; + + // + // FileSize includes the EFI_FFS_FILE_HEADER + // + FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer; + PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF); + PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8); + PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16); + + // + // Fill in checksums and state, must be zero during checksum calculation. + // + PadFile->IntegrityCheck.Checksum.Header = 0; + PadFile->IntegrityCheck.Checksum.File = 0; + PadFile->State = 0; + PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, sizeof (EFI_FFS_FILE_HEADER)); + if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) { + PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize); + } else { + PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) PadFile, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + // + // Update the current FV pointer + // + FvImage->CurrentFilePointer = FvImage->Eof; + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdateResetVector ( + IN MEMORY_FILE *FvImage, + IN FV_INFO *FvInfo, + IN EFI_FFS_FILE_HEADER *VtfFile + ) +/*++ + +Routine Description: + + This parses the FV looking for the PEI core and then plugs the address into + the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to + complete an IA32 Bootstrap FV. + +Arguments: + + FvImage Memory file for the FV memory image + FvInfo Information read from INF file. + VtfFile Pointer to the VTF file in the FV image. + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_NOT_FOUND PEI Core file not found. + +--*/ +{ + EFI_FFS_FILE_HEADER *PeiCoreFile; + EFI_FFS_FILE_HEADER *SecCoreFile; + EFI_STATUS Status; + EFI_FILE_SECTION_POINTER Pe32Section; + UINT32 EntryPoint; + UINT32 BaseOfCode; + UINT16 MachineType; + EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress; + EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress; + EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr; + UINT32 *Ia32ResetAddressPtr; + UINT8 *BytePointer; + UINT8 *BytePointer2; + UINT16 *WordPointer; + UINT16 CheckSum; + UINTN Index; + EFI_FFS_FILE_STATE SavedState; + EFI_FFS_FILE_TAIL TailValue; + UINT32 TailSize; + UINT64 FitAddress; + FIT_TABLE *FitTablePtr; + + // + // Verify input parameters + // + if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize FV library + // + InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage); + + // + // Verify VTF file + // + Status = VerifyFfsFile (VtfFile); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + // + // Find the PEI Core + // + Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile); + if (EFI_ERROR (Status) || PeiCoreFile == NULL) { + Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL); + return EFI_ABORTED; + } + // + // PEI Core found, now find PE32 section + // + Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not find PE32 section in PEI core file", NULL); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL); + return EFI_ABORTED; + } + // + // Physical address is FV base + offset of PE32 + offset of the entry point + // + PeiCorePhysicalAddress = FvInfo->BaseAddress; + PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage; + PeiCorePhysicalAddress += EntryPoint; + + if (MachineType == EFI_IMAGE_MACHINE_IA64) { + // + // Update PEI_CORE address + // + // + // Set the uncached attribute bit in the physical address + // + PeiCorePhysicalAddress |= 0x8000000000000000ULL; + + // + // Check if address is aligned on a 16 byte boundary + // + if (PeiCorePhysicalAddress & 0xF) { + printf ( + "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n", + PeiCorePhysicalAddress + ); + return EFI_ABORTED; + } + // + // First Get the FIT table address + // + FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF; + + FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress)); + + Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress); + + if (!EFI_ERROR (Status)) { + UpdateFitCheckSum (FitTablePtr); + } + // + // Find the Sec Core + // + Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile); + if (EFI_ERROR (Status) || SecCoreFile == NULL) { + Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL); + return EFI_ABORTED; + } + // + // Sec Core found, now find PE32 section + // + Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL); + return EFI_ABORTED; + } + // + // Physical address is FV base + offset of PE32 + offset of the entry point + // + SecCorePhysicalAddress = FvInfo->BaseAddress; + SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage; + SecCorePhysicalAddress += EntryPoint; + + // + // Update SEC_CORE address + // + // + // Set the uncached attribute bit in the physical address + // + SecCorePhysicalAddress |= 0x8000000000000000ULL; + + // + // Update the address + // + SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET); + *SecCoreEntryAddressPtr = SecCorePhysicalAddress; + + // + // Check if address is aligned on a 16 byte boundary + // + if (SecCorePhysicalAddress & 0xF) { + printf ( + "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n", + SecCorePhysicalAddress + ); + return EFI_ABORTED; + } + } else if (MachineType == EFI_IMAGE_MACHINE_IA32) { + // + // Get the location to update + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET); + + // + // Write lower 32 bits of physical address + // + *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress; + + // + // Update the BFV base address + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4); + *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress); + + CheckSum = 0x0000; + + // + // Update the Startup AP in the FVH header block ZeroVector region. + // + BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage); + BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray; + for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) { + *BytePointer++ = *BytePointer2++; + } + // + // Calculate the checksum + // + WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage); + for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) { + CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer)); + WordPointer++; + } + // + // Update the checksum field + // + BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage); + BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2); + WordPointer = (UINT16 *) BytePointer; + *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum); + } else { + Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType); + return EFI_ABORTED; + } + // + // Determine if it has an FFS file tail. + // + if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailSize = sizeof (EFI_FFS_FILE_TAIL); + } else { + TailSize = 0; + } + // + // Now update file checksum + // + SavedState = VtfFile->State; + VtfFile->IntegrityCheck.Checksum.File = 0; + VtfFile->State = 0; + if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) { + VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ( + (UINT8 *) VtfFile, + GetLength (VtfFile->Size) - TailSize + ); + } else { + VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + VtfFile->State = SavedState; + + // + // Update tail if present + // + if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference)); + *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetPe32Info ( + IN UINT8 *Pe32, + OUT UINT32 *EntryPoint, + OUT UINT32 *BaseOfCode, + OUT UINT16 *MachineType + ) +/*++ + +Routine Description: + + Retrieves the PE32 entry point offset and machine type. See EfiImage.h for + machine types. The entry point offset is from the beginning of the PE32 + buffer passed in. + +Arguments: + + Pe32 Beginning of the PE32. + EntryPoint Offset from the beginning of the PE32 to the image entry point. + BaseOfCode Base address of code. + MachineType Magic number for the machine type. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_UNSUPPORTED The operation is unsupported. + +--*/ +{ + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_NT_HEADERS *NtHeader; + + // + // Verify input parameters + // + if (Pe32 == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // First is the DOS header + // + DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32; + + // + // Verify DOS header is expected + // + if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic); + return EFI_UNSUPPORTED; + } + // + // Immediately following is the NT header. + // + NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew); + + // + // Verify NT header is expected + // + if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) { + printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature); + return EFI_UNSUPPORTED; + } + // + // Get output + // + *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint; + *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode; + *MachineType = NtHeader->FileHeader.Machine; + + // + // Verify machine type is supported + // + if (*MachineType != EFI_IMAGE_MACHINE_IA32 && *MachineType != EFI_IMAGE_MACHINE_IA64 && *MachineType != EFI_IMAGE_MACHINE_X64 && *MachineType != EFI_IMAGE_MACHINE_EBC) { + printf ("ERROR: Unrecognized machine type in the PE32 file.\n"); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} +// +// Exposed function implementations (prototypes are defined in GenFvImageLib.h) +// +EFI_STATUS +GenerateFvImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + OUT UINT8 **FvImage, + OUT UINTN *FvImageSize, + OUT CHAR8 **FvFileName, + OUT UINT8 **SymImage, + OUT UINTN *SymImageSize, + OUT CHAR8 **SymFileName + ) +/*++ + +Routine Description: + + This is the main function which will be called from application. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + FvImage Pointer to the FV image created. + FvImageSize Size of the FV image created and pointed to by FvImage. + FvFileName Requested name for the FV file. + SymImage Pointer to the Sym image created. + SymImageSize Size of the Sym image created and pointed to by SymImage. + SymFileName Requested name for the Sym file. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_OUT_OF_RESOURCES Could not allocate required resources. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +{ + EFI_STATUS Status; + MEMORY_FILE InfMemoryFile; + MEMORY_FILE FvImageMemoryFile; + MEMORY_FILE SymImageMemoryFile; + FV_INFO FvInfo; + UINTN Index; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FFS_FILE_HEADER *VtfFileImage; + + // + // Check for invalid parameter + // + if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize file structures + // + InfMemoryFile.FileImage = InfFileImage; + InfMemoryFile.CurrentFilePointer = InfFileImage; + InfMemoryFile.Eof = InfFileImage + InfFileSize; + + // + // Parse the FV inf file for header information + // + Status = ParseFvInf (&InfMemoryFile, &FvInfo); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not parse the input INF file.\n"); + return EFI_ABORTED; + } + // + // Update the file name return values + // + strcpy (*FvFileName, FvInfo.FvName); + strcpy (*SymFileName, FvInfo.SymName); + + // + // Calculate the FV size + // + *FvImageSize = FvInfo.Size; + + // + // Allocate the FV + // + *FvImage = malloc (*FvImageSize); + if (*FvImage == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Allocate space for symbol file storage + // + *SymImage = malloc (SYMBOL_FILE_SIZE); + if (*SymImage == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize the FV to the erase polarity + // + if (FvInfo.FvAttributes & EFI_FVB_ERASE_POLARITY) { + memset (*FvImage, -1, *FvImageSize); + } else { + memset (*FvImage, 0, *FvImageSize); + } + // + // Initialize FV header + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) *FvImage; + + // + // Initialize the zero vector to all zeros. + // + memset (FvHeader->ZeroVector, 0, 16); + + // + // Copy the FFS GUID + // + memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID)); + + FvHeader->FvLength = *FvImageSize; + FvHeader->Signature = EFI_FVH_SIGNATURE; + FvHeader->Attributes = FvInfo.FvAttributes; + FvHeader->Revision = EFI_FVH_REVISION; + FvHeader->Reserved[0] = 0; + FvHeader->Reserved[1] = 0; + FvHeader->Reserved[2] = 0; + + // + // Copy firmware block map + // + for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) { + FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks; + FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength; + } + // + // Add block map terminator + // + FvHeader->FvBlockMap[Index].NumBlocks = 0; + FvHeader->FvBlockMap[Index].BlockLength = 0; + + // + // Complete the header + // + FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage); + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + + // + // If there is no FFS file, find and generate each components of the FV + // + if (FvInfo.FvFiles[0][0] == 0) { + Status = GenNonFFSFv (*FvImage, &FvInfo); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not generate NonFFS FV.\n"); + free (*FvImage); + return EFI_ABORTED; + } + + return EFI_SUCCESS; + } + // + // Initialize our "file" view of the buffer + // + FvImageMemoryFile.FileImage = *FvImage; + FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength; + FvImageMemoryFile.Eof = *FvImage +*FvImageSize; + + // + // Initialize our "file" view of the symbol file. + // + SymImageMemoryFile.FileImage = *SymImage; + SymImageMemoryFile.CurrentFilePointer = *SymImage; + SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE; + + // + // Initialize the FV library. + // + InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size); + + // + // Files start on 8 byte alignments, so move to the next 8 byte aligned + // address. For now, just assert if it isn't. Currently FV header is + // always a multiple of 8 bytes. + // BUGBUG: Handle this better + // + assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0); + + // + // Initialize the VTF file address. + // + VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof; + + // + // Add files to FV + // + for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) { + // + // Add the file + // + Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile); + + // + // Exit if error detected while adding the file + // + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]); + free (*FvImage); + return EFI_ABORTED; + } + } + // + // If there is a VTF file, some special actions need to occur. + // + if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) { + // + // Pad from the end of the last file to the beginning of the VTF file. + // + Status = PadFvImage (&FvImageMemoryFile, VtfFileImage); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n"); + free (*FvImage); + return EFI_ABORTED; + } + // + // Update reset vector (SALE_ENTRY for IPF) + // Now for IA32 and IA64 platform, the fv which has bsf file must have the + // EndAddress of 0xFFFFFFFF. Thus, only this type fv needs to update the + // reset vector. If the PEI Core is found, the VTF file will probably get + // corrupted by updating the entry point. + // + if ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) { + Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage); + if (EFI_ERROR(Status)) { + printf ("ERROR: Could not update the reset vector.\n"); + free (*FvImage); + return EFI_ABORTED; + } + } + } + // + // Determine final Sym file size + // + *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage; + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdatePeiCoreEntryInFit ( + IN FIT_TABLE *FitTablePtr, + IN UINT64 PeiCorePhysicalAddress + ) +/*++ + +Routine Description: + + This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from + Sec to Pei Core + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + PeiCorePhysicalAddress - The address of Pei Core entry. + +Returns: + + EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully. + EFI_NOT_FOUND - Not found the PEI_CORE FIT entry. + +--*/ +{ + FIT_TABLE *TmpFitPtr; + UINTN Index; + UINTN NumFitComponents; + + TmpFitPtr = FitTablePtr; + NumFitComponents = TmpFitPtr->CompSize; + + for (Index = 0; Index < NumFitComponents; Index++) { + if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) { + TmpFitPtr->CompAddress = PeiCorePhysicalAddress; + return EFI_SUCCESS; + } + + TmpFitPtr++; + } + + return EFI_NOT_FOUND; +} + +VOID +UpdateFitCheckSum ( + IN FIT_TABLE *FitTablePtr + ) +/*++ + +Routine Description: + + This function is used to update the checksum for FIT. + + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + +Returns: + + None. + +--*/ +{ + if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) { + FitTablePtr->CheckSum = 0; + FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16); + } +} diff --git a/Tools/Source/TianoTools/GenFvImage/GenFvImageLib.h b/Tools/Source/TianoTools/GenFvImage/GenFvImageLib.h new file mode 100644 index 0000000000..cc761b8e5a --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/GenFvImageLib.h @@ -0,0 +1,140 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenFvImageLib.h + +Abstract: + + This file contains describes the public interfaces to the GenFvImage Library. + The basic purpose of the library is to create Firmware Volume images. + +--*/ + +#ifndef _EFI_GEN_FV_IMAGE_LIB_H +#define _EFI_GEN_FV_IMAGE_LIB_H + +// +// Include files +// +// #include "Efi2WinNT.h" +#include "ParseInf.h" + +// +// Following definition is used for FIT in IPF +// +#define COMP_TYPE_FIT_PEICORE 0x10 +#define COMP_TYPE_FIT_UNUSED 0x7F + +#define FIT_TYPE_MASK 0x7F +#define CHECKSUM_BIT_MASK 0x80 + +#pragma pack(1) + +typedef struct { + UINT64 CompAddress; + UINT32 CompSize; + UINT16 CompVersion; + UINT8 CvAndType; + UINT8 CheckSum; +} FIT_TABLE; + +#pragma pack() +// +// Exported function prototypes +// +EFI_STATUS +GenerateFvImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + OUT UINT8 **FvImage, + OUT UINTN *FvImageSize, + OUT CHAR8 **FvFileName, + OUT UINT8 **SymImage, + OUT UINTN *SymImageSize, + OUT CHAR8 **SymFileName + ) +; + +/*++ + +Routine Description: + + This is the main function which will be called from application. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + FvImage Pointer to the FV image created. + FvImageSize Size of the FV image created and pointed to by FvImage. + FvFileName Requested name for the FV file. + SymImage Pointer to the Sym image created. + SymImageSize Size of the Sym image created and pointed to by SymImage. + SymFileName Requested name for the Sym file. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_OUT_OF_RESOURCES Could not allocate required resources. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +EFI_STATUS +UpdatePeiCoreEntryInFit ( + IN FIT_TABLE *FitTablePtr, + IN UINT64 PeiCorePhysicalAddress + ) +; + +/*++ + +Routine Description: + + This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from + Sec to Pei Core + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + PeiCorePhysicalAddress - The address of Pei Core entry. + +Returns: + + EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully. + EFI_NOT_FOUND - Not found the PEI_CORE FIT entry. + +--*/ +VOID +UpdateFitCheckSum ( + IN FIT_TABLE *FitTablePtr + ) +; + +/*++ + +Routine Description: + + This function is used to update the checksum for FIT. + + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + +Returns: + + None. + +--*/ +#endif diff --git a/Tools/Source/TianoTools/GenFvImage/GenFvImageLibInternal.h b/Tools/Source/TianoTools/GenFvImage/GenFvImageLibInternal.h new file mode 100644 index 0000000000..f38fe1151a --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/GenFvImageLibInternal.h @@ -0,0 +1,170 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenFvImageLibInternal.h + +Abstract: + + This file contains describes the private declarations for the GenFvImage Library. + The basic purpose of the library is to create Firmware Volume images. + +--*/ + +#ifndef _EFI_GEN_FV_IMAGE_LIB_INTERNAL_H +#define _EFI_GEN_FV_IMAGE_LIB_INTERNAL_H + +// +// Include files +// +#include "GenFvImageLib.h" +#include +#include +#include "FirmwareVolumeHeader.h" + +// +// Private data declarations +// +// +// The maximum number of block map entries supported by the library +// +#define MAX_NUMBER_OF_FV_BLOCKS 100 + +// +// The maximum number of files in the FV supported by the library +// +#define MAX_NUMBER_OF_FILES_IN_FV 1000 +#define MAX_NUMBER_OF_COMPONENTS_IN_FV 10 + +// +// INF file strings +// +#define OPTIONS_SECTION_STRING "[options]" +#define ATTRIBUTES_SECTION_STRING "[attributes]" +#define FILES_SECTION_STRING "[files]" +#define COMPONENT_SECTION_STRING "[components]" + +#define EFI_FV_BASE_ADDRESS_STRING "EFI_BASE_ADDRESS" +#define EFI_FV_FILE_NAME_STRING "EFI_FILE_NAME" +#define EFI_SYM_FILE_NAME_STRING "EFI_SYM_FILE_NAME" +#define EFI_NUM_BLOCKS_STRING "EFI_NUM_BLOCKS" +#define EFI_BLOCK_SIZE_STRING "EFI_BLOCK_SIZE" +#define EFI_FV_GUID_STRING "EFI_FV_GUID" + +#define EFI_FVB_READ_DISABLED_CAP_STRING "EFI_READ_DISABLED_CAP" +#define EFI_FVB_READ_ENABLED_CAP_STRING "EFI_READ_ENABLED_CAP" +#define EFI_FVB_READ_STATUS_STRING "EFI_READ_STATUS" + +#define EFI_FVB_WRITE_DISABLED_CAP_STRING "EFI_WRITE_DISABLED_CAP" +#define EFI_FVB_WRITE_ENABLED_CAP_STRING "EFI_WRITE_ENABLED_CAP" +#define EFI_FVB_WRITE_STATUS_STRING "EFI_WRITE_STATUS" + +#define EFI_FVB_LOCK_CAP_STRING "EFI_LOCK_CAP" +#define EFI_FVB_LOCK_STATUS_STRING "EFI_LOCK_STATUS" + +#define EFI_FVB_STICKY_WRITE_STRING "EFI_STICKY_WRITE" +#define EFI_FVB_MEMORY_MAPPED_STRING "EFI_MEMORY_MAPPED" +#define EFI_FVB_ERASE_POLARITY_STRING "EFI_ERASE_POLARITY" + +#define EFI_FVB_ALIGNMENT_CAP_STRING "EFI_ALIGNMENT_CAP" +#define EFI_FVB_ALIGNMENT_2_STRING "EFI_ALIGNMENT_2" +#define EFI_FVB_ALIGNMENT_4_STRING "EFI_ALIGNMENT_4" +#define EFI_FVB_ALIGNMENT_8_STRING "EFI_ALIGNMENT_8" +#define EFI_FVB_ALIGNMENT_16_STRING "EFI_ALIGNMENT_16" +#define EFI_FVB_ALIGNMENT_32_STRING "EFI_ALIGNMENT_32" +#define EFI_FVB_ALIGNMENT_64_STRING "EFI_ALIGNMENT_64" +#define EFI_FVB_ALIGNMENT_128_STRING "EFI_ALIGNMENT_128" +#define EFI_FVB_ALIGNMENT_256_STRING "EFI_ALIGNMENT_256" +#define EFI_FVB_ALIGNMENT_512_STRING "EFI_ALIGNMENT_512" +#define EFI_FVB_ALIGNMENT_1K_STRING "EFI_ALIGNMENT_1K" +#define EFI_FVB_ALIGNMENT_2K_STRING "EFI_ALIGNMENT_2K" +#define EFI_FVB_ALIGNMENT_4K_STRING "EFI_ALIGNMENT_4K" +#define EFI_FVB_ALIGNMENT_8K_STRING "EFI_ALIGNMENT_8K" +#define EFI_FVB_ALIGNMENT_16K_STRING "EFI_ALIGNMENT_16K" +#define EFI_FVB_ALIGNMENT_32K_STRING "EFI_ALIGNMENT_32K" +#define EFI_FVB_ALIGNMENT_64K_STRING "EFI_ALIGNMENT_64K" + +// +// Component sections +// +#define EFI_NV_VARIABLE_STRING "EFI_NV_VARIABLE" +#define EFI_NV_EVENT_LOG_STRING "EFI_NV_EVENT_LOG" +#define EFI_NV_FTW_WORKING_STRING "EFI_NV_FTW_WORKING" +#define EFI_NV_FTW_SPARE_STRING "EFI_NV_FTW_SPARE" + +#define EFI_FILE_NAME_STRING "EFI_FILE_NAME" + +#define ONE_STRING "1" +#define ZERO_STRING "0" +#define TRUE_STRING "TRUE" +#define FALSE_STRING "FALSE" +#define NULL_STRING "NULL" + +// +// Defines to calculate the offset for PEI CORE entry points +// +#define IA32_PEI_CORE_ENTRY_OFFSET 0x20 + +// +// Defines to calculate the FIT table +// +#define IPF_FIT_ADDRESS_OFFSET 0x20 + +// +// Defines to calculate the offset for SALE_ENTRY +// +#define IPF_SALE_ENTRY_ADDRESS_OFFSET 0x18 + +// +// Symbol file definitions, current max size if 512K +// +#define SYMBOL_FILE_SIZE 0x80000 + +#define FV_IMAGES_TOP_ADDRESS 0x100000000ULL + +// +// Private data types +// +// +// Component information +// +typedef struct { + UINTN Size; + CHAR8 ComponentName[_MAX_PATH]; +} COMPONENT_INFO; + +// +// FV information holder +// +typedef struct { + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_GUID FvGuid; + UINTN Size; + CHAR8 FvName[_MAX_PATH]; + CHAR8 SymName[_MAX_PATH]; + EFI_FV_BLOCK_MAP_ENTRY FvBlocks[MAX_NUMBER_OF_FV_BLOCKS]; + EFI_FVB_ATTRIBUTES FvAttributes; + CHAR8 FvFiles[MAX_NUMBER_OF_FILES_IN_FV][_MAX_PATH]; + COMPONENT_INFO FvComponents[MAX_NUMBER_OF_COMPONENTS_IN_FV]; +} FV_INFO; + +// +// Private function prototypes +// +EFI_STATUS +ParseFvInf ( + IN MEMORY_FILE *InfFile, + IN FV_INFO *FvInfo + ) +; + +#endif diff --git a/Tools/Source/TianoTools/GenFvImage/Ia32/PeCoffLoaderEx.c b/Tools/Source/TianoTools/GenFvImage/Ia32/PeCoffLoaderEx.c new file mode 100644 index 0000000000..0af4340fcb --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/Ia32/PeCoffLoaderEx.c @@ -0,0 +1,64 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + PeCoffLoaderEx.c + +Abstract: + + IA-32 Specific relocation fixups + +Revision History + +--*/ + + +#define EFI_SPECIFICATION_VERSION 0x00000000 +#define EDK_RELEASE_VERSION 0x00020000 +#include +#include +#include + + + + +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IA-32 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - Unsupported now + +--*/ +{ + return RETURN_UNSUPPORTED; +} diff --git a/Tools/Source/TianoTools/GenFvImage/Ipf/PeCoffLoaderEx.c b/Tools/Source/TianoTools/GenFvImage/Ipf/PeCoffLoaderEx.c new file mode 100644 index 0000000000..2a58a62f6d --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/Ipf/PeCoffLoaderEx.c @@ -0,0 +1,251 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + PeCoffLoaderEx.c + +Abstract: + + Fixes Intel Itanium(TM) specific relocation types + + +Revision History + +--*/ + +#define EFI_SPECIFICATION_VERSION 0x00000000 +#define EDK_RELEASE_VERSION 0x00020000 +#include +#include +#include + + + + + +#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \ + Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos) + +#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \ + *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \ + ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos) + +#define IMM64_IMM7B_INST_WORD_X 3 +#define IMM64_IMM7B_SIZE_X 7 +#define IMM64_IMM7B_INST_WORD_POS_X 4 +#define IMM64_IMM7B_VAL_POS_X 0 + +#define IMM64_IMM9D_INST_WORD_X 3 +#define IMM64_IMM9D_SIZE_X 9 +#define IMM64_IMM9D_INST_WORD_POS_X 18 +#define IMM64_IMM9D_VAL_POS_X 7 + +#define IMM64_IMM5C_INST_WORD_X 3 +#define IMM64_IMM5C_SIZE_X 5 +#define IMM64_IMM5C_INST_WORD_POS_X 13 +#define IMM64_IMM5C_VAL_POS_X 16 + +#define IMM64_IC_INST_WORD_X 3 +#define IMM64_IC_SIZE_X 1 +#define IMM64_IC_INST_WORD_POS_X 12 +#define IMM64_IC_VAL_POS_X 21 + +#define IMM64_IMM41a_INST_WORD_X 1 +#define IMM64_IMM41a_SIZE_X 10 +#define IMM64_IMM41a_INST_WORD_POS_X 14 +#define IMM64_IMM41a_VAL_POS_X 22 + +#define IMM64_IMM41b_INST_WORD_X 1 +#define IMM64_IMM41b_SIZE_X 8 +#define IMM64_IMM41b_INST_WORD_POS_X 24 +#define IMM64_IMM41b_VAL_POS_X 32 + +#define IMM64_IMM41c_INST_WORD_X 2 +#define IMM64_IMM41c_SIZE_X 23 +#define IMM64_IMM41c_INST_WORD_POS_X 0 +#define IMM64_IMM41c_VAL_POS_X 40 + +#define IMM64_SIGN_INST_WORD_X 3 +#define IMM64_SIGN_SIZE_X 1 +#define IMM64_SIGN_INST_WORD_POS_X 27 +#define IMM64_SIGN_VAL_POS_X 63 + +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an Itanium-based specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + Status code + +--*/ +{ + UINT64 *F64; + UINT64 FixupVal; + + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_DIR64: + F64 = (UINT64 *) Fixup; + *F64 = *F64 + (UINT64) Adjust; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + case EFI_IMAGE_REL_BASED_IA64_IMM64: + + // + // Align it to bundle address before fixing up the + // 64-bit immediate value of the movl instruction. + // + + Fixup = (CHAR8 *)((UINTN) Fixup & (UINTN) ~(15)); + FixupVal = (UINT64)0; + + // + // Extract the lower 32 bits of IMM64 from bundle + // + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X, + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X, + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X, + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IC_INST_WORD_X, + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + EXT_IMM64(FixupVal, + (UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X, + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + // + // Update 64-bit address + // + FixupVal += Adjust; + + // + // Insert IMM64 into bundle + // + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM7B_INST_WORD_X), + IMM64_IMM7B_SIZE_X, + IMM64_IMM7B_INST_WORD_POS_X, + IMM64_IMM7B_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM9D_INST_WORD_X), + IMM64_IMM9D_SIZE_X, + IMM64_IMM9D_INST_WORD_POS_X, + IMM64_IMM9D_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM5C_INST_WORD_X), + IMM64_IMM5C_SIZE_X, + IMM64_IMM5C_INST_WORD_POS_X, + IMM64_IMM5C_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IC_INST_WORD_X), + IMM64_IC_SIZE_X, + IMM64_IC_INST_WORD_POS_X, + IMM64_IC_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41a_INST_WORD_X), + IMM64_IMM41a_SIZE_X, + IMM64_IMM41a_INST_WORD_POS_X, + IMM64_IMM41a_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41b_INST_WORD_X), + IMM64_IMM41b_SIZE_X, + IMM64_IMM41b_INST_WORD_POS_X, + IMM64_IMM41b_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_IMM41c_INST_WORD_X), + IMM64_IMM41c_SIZE_X, + IMM64_IMM41c_INST_WORD_POS_X, + IMM64_IMM41c_VAL_POS_X + ); + + INS_IMM64(FixupVal, + ((UINT32 *)Fixup + IMM64_SIGN_INST_WORD_X), + IMM64_SIGN_SIZE_X, + IMM64_SIGN_INST_WORD_POS_X, + IMM64_SIGN_VAL_POS_X + ); + + F64 = (UINT64 *) Fixup; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + default: + return RETURN_UNSUPPORTED; + } + + return RETURN_SUCCESS; +} diff --git a/Tools/Source/TianoTools/GenFvImage/build.gcc b/Tools/Source/TianoTools/GenFvImage/build.gcc new file mode 100644 index 0000000000..6cc8a9959f --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/build.gcc @@ -0,0 +1,3 @@ +gcc -I $WORKSPACE/MdePkg/Include/ToBeRemoved -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ Ia32/*.c *.c -o GenFvImage_IA32 -L../Library-cygwin -lCommon -L/usr/lib/e2fsprogs -luuid +gcc -I $WORKSPACE/MdePkg/Include/ToBeRemoved -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ x64/*.c *.c -o GenFvImage_X64 -L../Library-cygwin -lCommon -L/usr/lib/e2fsprogs -luuid +gcc -I $WORKSPACE/MdePkg/Include/ToBeRemoved -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ Ipf/*.c *.c -o GenFvImage_IPF -L../Library-cygwin -lCommon -L/usr/lib/e2fsprogs -luuid diff --git a/Tools/Source/TianoTools/GenFvImage/build.xml b/Tools/Source/TianoTools/GenFvImage/build.xml new file mode 100644 index 0000000000..6c9970625e --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/build.xml @@ -0,0 +1,246 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/GenFvImage/x64/PeCoffLoaderEx.c b/Tools/Source/TianoTools/GenFvImage/x64/PeCoffLoaderEx.c new file mode 100644 index 0000000000..6bcae272e7 --- /dev/null +++ b/Tools/Source/TianoTools/GenFvImage/x64/PeCoffLoaderEx.c @@ -0,0 +1,76 @@ +/*++ + +Copyright 2005, 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. + + +Module Name: + + PeCoffLoaderEx.c + +Abstract: + + x64 Specific relocation fixups + +Revision History + +--*/ + +#define EFI_SPECIFICATION_VERSION 0x00000000 +#define EDK_RELEASE_VERSION 0x00020000 +#include +#include +#include + + + + +RETURN_STATUS +PeCoffLoaderRelocateImageEx ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + Performs an x64 specific relocation fixup + +Arguments: + Reloc - Pointer to the relocation record + Fixup - Pointer to the address to fix up + FixupData - Pointer to a buffer to log the fixups + Adjust - The offset to adjust the fixup + +Returns: + None + +--*/ +{ + UINT64 *F64; + + switch ((*Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_DIR64: + F64 = (UINT64 *) Fixup; + *F64 = *F64 + (UINT64) Adjust; + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + *(UINT64 *)(*FixupData) = *F64; + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + default: + return RETURN_UNSUPPORTED; + } + + return RETURN_SUCCESS; +} diff --git a/Tools/Source/TianoTools/GenSection/GenSection.c b/Tools/Source/TianoTools/GenSection/GenSection.c new file mode 100644 index 0000000000..8ae0a9c4ce --- /dev/null +++ b/Tools/Source/TianoTools/GenSection/GenSection.c @@ -0,0 +1,939 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenSection.c + +Abstract: + + Creates output file that is a properly formed section per the FV spec. + +--*/ + +#include +#include +#include "FirmwareVolumeImageFormat.h" +#include "CommonLib.h" +#include "EfiCompress.h" +#include "EfiCustomizedCompress.h" +#include "Crc32.h" +#include "EfiUtilityMsgs.h" + +#include +#include +#include + +#include "GenSection.h" + +#include + +#define UTILITY_NAME "GenSection" + +#define PARAMETER_NOT_SPECIFIED "Parameter not specified" +#define MAXIMUM_INPUT_FILE_NUM 10 + +char *SectionTypeName[] = { + NULL, // 0x00 - reserved + "EFI_SECTION_COMPRESSION", // 0x01 + "EFI_SECTION_GUID_DEFINED", // 0x02 + NULL, // 0x03 - reserved + NULL, // 0x04 - reserved + NULL, // 0x05 - reserved + NULL, // 0x06 - reserved + NULL, // 0x07 - reserved + NULL, // 0x08 - reserved + NULL, // 0x09 - reserved + NULL, // 0x0A - reserved + NULL, // 0x0B - reserved + NULL, // 0x0C - reserved + NULL, // 0x0D - reserved + NULL, // 0x0E - reserved + NULL, // 0x0F - reserved + "EFI_SECTION_PE32", // 0x10 + "EFI_SECTION_PIC", // 0x11 + "EFI_SECTION_TE", // 0x12 + "EFI_SECTION_DXE_DEPEX", // 0x13 + "EFI_SECTION_VERSION", // 0x14 + "EFI_SECTION_USER_INTERFACE", // 0x15 + "EFI_SECTION_COMPATIBILITY16", // 0x16 + "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17 + "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18 + "EFI_SECTION_RAW", // 0x19 + NULL, // 0x1A + "EFI_SECTION_PEI_DEPEX" // 0x1B +}; + +char *CompressionTypeName[] = { "NONE", "STANDARD" }; +char *GUIDedSectionTypeName[] = { "CRC32" }; +EFI_GUID gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; + +static +VOID +PrintUsageMessage ( + VOID + ) +{ + UINTN SectionType; + UINTN DisplayCount; + + printf ("Usage: "UTILITY_NAME " -i InputFile -o OutputFile -s SectionType [SectionType params]\n\n"); + printf (" Where SectionType is one of the following section types:\n\n"); + + DisplayCount = 0; + for (SectionType = 0; SectionType <= EFI_SECTION_LAST_SECTION_TYPE; SectionType++) { + if (SectionTypeName[SectionType] != NULL) { + printf (" %s\n", SectionTypeName[SectionType]); + } + } + + printf ("\n and SectionType dependent parameters are as follows:\n\n"); + printf ( + " %s: -t < %s | %s >\n", + SectionTypeName[EFI_SECTION_COMPRESSION], + CompressionTypeName[EFI_NOT_COMPRESSED], + CompressionTypeName[EFI_STANDARD_COMPRESSION] + ); + printf ( + " %s: -t < %s >\n"" // Currently only CRC32 is supported\n\n", + SectionTypeName[EFI_SECTION_GUID_DEFINED], + GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED] + ); + printf ( + " %s: -v VersionNumber\n"" [-a \"Version string\"]\n\n", + SectionTypeName[EFI_SECTION_VERSION] + ); + printf ( + " %s: -a \"Human readable name\"\n\n", + SectionTypeName[EFI_SECTION_USER_INTERFACE] + ); +} + +VOID +Ascii2UnicodeWriteString ( + char *String, + FILE *OutFile, + BOOLEAN WriteLangCode + ) +{ + UINTN Index; + UINT8 AsciiNull; + // + // BUGBUG need to get correct language code... + // + char *EnglishLangCode = "eng"; + AsciiNull = 0; + // + // first write the language code (english only) + // + if (WriteLangCode) { + fwrite (EnglishLangCode, 1, 4, OutFile); + } + // + // Next, write out the string... Convert ASCII to Unicode in the process. + // + Index = 0; + do { + fwrite (&String[Index], 1, 1, OutFile); + fwrite (&AsciiNull, 1, 1, OutFile); + } while (String[Index++] != 0); +} + +STATUS +GenSectionCommonLeafSection ( + char **InputFileName, + int InputFileNum, + UINTN SectionType, + FILE *OutFile + ) +/*++ + +Routine Description: + + Generate a leaf section of type other than EFI_SECTION_VERSION + and EFI_SECTION_USER_INTERFACE. Input file must be well formed. + The function won't validate the input file's contents. For + common leaf sections, the input file may be a binary file. + The utility will add section header to the file. + +Arguments: + + InputFileName - Name of the input file. + + InputFileNum - Number of input files. Should be 1 for leaf section. + + SectionType - A valid section type string + + OutFile - Output file handle + +Returns: + + STATUS_ERROR - can't continue + STATUS_SUCCESS - successful return + +--*/ +{ + UINT64 InputFileLength; + FILE *InFile; + UINT8 *Buffer; + INTN TotalLength; + EFI_COMMON_SECTION_HEADER CommonSect; + STATUS Status; + + if (InputFileNum > 1) { + Error (NULL, 0, 0, "invalid parameter", "more than one input file specified"); + return STATUS_ERROR; + } else if (InputFileNum < 1) { + Error (NULL, 0, 0, "no input file specified", NULL); + return STATUS_ERROR; + } + // + // Open the input file + // + InFile = fopen (InputFileName[0], "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0, InputFileName[0], "failed to open input file"); + return STATUS_ERROR; + } + + Status = STATUS_ERROR; + Buffer = NULL; + // + // Seek to the end of the input file so we can determine its size + // + fseek (InFile, 0, SEEK_END); + fgetpos (InFile, &InputFileLength); + fseek (InFile, 0, SEEK_SET); + // + // Fill in the fields in the local section header structure + // + CommonSect.Type = (EFI_SECTION_TYPE) SectionType; + TotalLength = sizeof (CommonSect) + (INTN) InputFileLength; + // + // Size must fit in 3 bytes + // + if (TotalLength >= 0x1000000) { + Error (NULL, 0, 0, InputFileName[0], "file size (0x%X) exceeds section size limit", TotalLength); + goto Done; + } + // + // Now copy the size into the section header and write out the section header + // + memcpy (&CommonSect.Size, &TotalLength, 3); + fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile); + // + // Allocate a buffer to read in the contents of the input file. Then + // read it in as one block and write it to the output file. + // + if (InputFileLength != 0) { + Buffer = (UINT8 *) malloc ((size_t) InputFileLength); + if (Buffer == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + goto Done; + } + + if (fread (Buffer, (size_t) InputFileLength, 1, InFile) != 1) { + Error (NULL, 0, 0, InputFileName[0], "failed to read contents of file"); + goto Done; + } + + if (fwrite (Buffer, (size_t) InputFileLength, 1, OutFile) != 1) { + Error (NULL, 0, 0, "failed to write to output file", NULL); + goto Done; + } + } + + Status = STATUS_SUCCESS; +Done: + fclose (InFile); + if (Buffer != NULL) { + free (Buffer); + } + + return Status; +} + +EFI_STATUS +GetSectionContents ( + char **InputFileName, + int InputFileNum, + UINT8 *FileBuffer, + UINTN *BufferLength + ) +/*++ + +Routine Description: + + Get the contents of all section files specified in InputFileName + into FileBuffer. + +Arguments: + + InputFileName - Name of the input file. + + InputFileNum - Number of input files. Should be at least 1. + + FileBuffer - Output buffer to contain data + + BufferLength - Actual length of the data + +Returns: + + EFI_SUCCESS on successful return + EFI_INVALID_PARAMETER if InputFileNum is less than 1 + EFI_ABORTED if unable to open input file. + +--*/ +{ + UINTN Size; + UINTN FileSize; + INTN Index; + FILE *InFile; + + if (InputFileNum < 1) { + Error (NULL, 0, 0, "must specify at least one input file", NULL); + return EFI_INVALID_PARAMETER; + } + + Size = 0; + // + // Go through our array of file names and copy their contents + // to the output buffer. + // + for (Index = 0; Index < InputFileNum; Index++) { + InFile = fopen (InputFileName[Index], "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0, InputFileName[Index], "failed to open input file"); + return EFI_ABORTED; + } + + fseek (InFile, 0, SEEK_END); + FileSize = ftell (InFile); + fseek (InFile, 0, SEEK_SET); + // + // Now read the contents of the file into the buffer + // + if (FileSize > 0) { + if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) { + Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file"); + fclose (InFile); + return EFI_ABORTED; + } + } + + fclose (InFile); + Size += (UINTN) FileSize; + // + // make sure section ends on a DWORD boundary + // + while ((Size & 0x03) != 0) { + FileBuffer[Size] = 0; + Size++; + } + } + + *BufferLength = Size; + return EFI_SUCCESS; +} + +EFI_STATUS +GenSectionCompressionSection ( + char **InputFileName, + int InputFileNum, + UINTN SectionType, + UINTN SectionSubType, + FILE *OutFile + ) +/*++ + +Routine Description: + + Generate an encapsulating section of type EFI_SECTION_COMPRESSION + Input file must be already sectioned. The function won't validate + the input files' contents. Caller should hand in files already + with section header. + +Arguments: + + InputFileName - Name of the input file. + + InputFileNum - Number of input files. Should be at least 1. + + SectionType - Section type to generate. Should be + EFI_SECTION_COMPRESSION + + SectionSubType - Specify the compression algorithm requested. + + OutFile - Output file handle + +Returns: + + EFI_SUCCESS on successful return + EFI_INVALID_PARAMETER if InputFileNum is less than 1 + EFI_ABORTED if unable to open input file. + EFI_OUT_OF_RESOURCES No resource to complete the operation. +--*/ +{ + UINTN TotalLength; + UINTN InputLength; + UINTN CompressedLength; + UINT8 *FileBuffer; + UINT8 *OutputBuffer; + EFI_STATUS Status; + EFI_COMPRESSION_SECTION CompressionSect; + COMPRESS_FUNCTION CompressFunction; + + if (SectionType != EFI_SECTION_COMPRESSION) { + Error (NULL, 0, 0, "parameter must be EFI_SECTION_COMPRESSION", NULL); + return EFI_INVALID_PARAMETER; + } + + InputLength = 0; + FileBuffer = NULL; + OutputBuffer = NULL; + CompressedLength = 0; + FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8)); + if (FileBuffer == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory"); + return EFI_OUT_OF_RESOURCES; + } + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + FileBuffer, + &InputLength + ); + if (EFI_ERROR (Status)) { + free (FileBuffer); + return Status; + } + + CompressFunction = NULL; + + // + // Now data is in FileBuffer, compress the data + // + switch (SectionSubType) { + case EFI_NOT_COMPRESSED: + CompressedLength = InputLength; + break; + + case EFI_STANDARD_COMPRESSION: + CompressFunction = (COMPRESS_FUNCTION) Compress; + break; + + case EFI_CUSTOMIZED_COMPRESSION: + CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress; + break; + + default: + Error (NULL, 0, 0, "unknown compression type", NULL); + free (FileBuffer); + return EFI_ABORTED; + } + + if (CompressFunction != NULL) { + + Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength); + if (Status == EFI_BUFFER_TOO_SMALL) { + OutputBuffer = malloc (CompressedLength); + if (!OutputBuffer) { + free (FileBuffer); + return EFI_OUT_OF_RESOURCES; + } + + Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength); + } + + free (FileBuffer); + FileBuffer = OutputBuffer; + + if (EFI_ERROR (Status)) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + + return Status; + } + } + + TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION); + // + // Add the section header for the compressed data + // + CompressionSect.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType; + CompressionSect.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff); + CompressionSect.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); + CompressionSect.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); + CompressionSect.CompressionType = (UINT8) SectionSubType; + CompressionSect.UncompressedLength = InputLength; + + fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile); + fwrite (FileBuffer, CompressedLength, 1, OutFile); + free (FileBuffer); + return EFI_SUCCESS; +} + +EFI_STATUS +GenSectionGuidDefinedSection ( + char **InputFileName, + int InputFileNum, + UINTN SectionType, + UINTN SectionSubType, + FILE *OutFile + ) +/*++ + +Routine Description: + + Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED + Input file must be already sectioned. The function won't validate + the input files' contents. Caller should hand in files already + with section header. + +Arguments: + + InputFileName - Name of the input file. + + InputFileNum - Number of input files. Should be at least 1. + + SectionType - Section type to generate. Should be + EFI_SECTION_GUID_DEFINED + + SectionSubType - Specify the authentication algorithm requested. + + OutFile - Output file handle + +Returns: + + EFI_SUCCESS on successful return + EFI_INVALID_PARAMETER if InputFileNum is less than 1 + EFI_ABORTED if unable to open input file. + EFI_OUT_OF_RESOURCES No resource to complete the operation. + +--*/ +{ + INTN TotalLength; + INTN InputLength; + UINT8 *FileBuffer; + UINT32 Crc32Checksum; + EFI_STATUS Status; + CRC32_SECTION_HEADER Crc32GuidSect; + + if (SectionType != EFI_SECTION_GUID_DEFINED) { + Error (NULL, 0, 0, "parameter must be EFI_SECTION_GUID_DEFINED", NULL); + return EFI_INVALID_PARAMETER; + } + + InputLength = 0; + FileBuffer = NULL; + FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 4) * sizeof (UINT8)); + if (FileBuffer == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory"); + return EFI_OUT_OF_RESOURCES; + } + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + FileBuffer, + &InputLength + ); + if (EFI_ERROR (Status)) { + free (FileBuffer); + return Status; + } + // + // Now data is in FileBuffer, compress the data + // + switch (SectionSubType) { + case EFI_SECTION_CRC32_GUID_DEFINED: + Crc32Checksum = 0; + CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum); + if (EFI_ERROR (Status)) { + free (FileBuffer); + return Status; + } + + TotalLength = InputLength + CRC32_SECTION_HEADER_SIZE; + Crc32GuidSect.GuidSectionHeader.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType; + Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff); + Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); + Crc32GuidSect.GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); + memcpy (&(Crc32GuidSect.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID)); + Crc32GuidSect.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + Crc32GuidSect.GuidSectionHeader.DataOffset = CRC32_SECTION_HEADER_SIZE; + Crc32GuidSect.CRC32Checksum = Crc32Checksum; + + break; + + default: + Error (NULL, 0, 0, "invalid parameter", "unknown GUID defined type"); + free (FileBuffer); + return EFI_ABORTED; + } + + fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile); + fwrite (FileBuffer, InputLength, 1, OutFile); + + free (FileBuffer); + + return EFI_SUCCESS; +} + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + Main + +Arguments: + + command line parameters + +Returns: + + EFI_SUCCESS Section header successfully generated and section concatenated. + EFI_ABORTED Could not generate the section + EFI_OUT_OF_RESOURCES No resource to complete the operation. + +--*/ +{ + INTN Index; + INTN VersionNumber; + UINTN SectionType; + UINTN SectionSubType; + BOOLEAN InputFileRequired; + BOOLEAN SubTypeRequired; + FILE *InFile; + FILE *OutFile; + INTN InputFileNum; + + char **InputFileName; + char *OutputFileName; + char AuxString[500] = { 0 }; + + char *ParamSectionType; + char *ParamSectionSubType; + char *ParamLength; + char *ParamVersion; + char *ParamDigitalSignature; + + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER CommonSect; + + InputFileName = NULL; + OutputFileName = PARAMETER_NOT_SPECIFIED; + ParamSectionType = PARAMETER_NOT_SPECIFIED; + ParamSectionSubType = PARAMETER_NOT_SPECIFIED; + ParamLength = PARAMETER_NOT_SPECIFIED; + ParamVersion = PARAMETER_NOT_SPECIFIED; + ParamDigitalSignature = PARAMETER_NOT_SPECIFIED; + Status = EFI_SUCCESS; + + VersionNumber = 0; + SectionType = 0; + SectionSubType = 0; + InputFileRequired = TRUE; + SubTypeRequired = FALSE; + InFile = NULL; + OutFile = NULL; + InputFileNum = 0; + Status = EFI_SUCCESS; + + SetUtilityName (UTILITY_NAME); + if (argc == 1) { + PrintUsageMessage (); + return STATUS_ERROR; + } + // + // Parse command line + // + Index = 1; + while (Index < argc) { + if (strcmpi (argv[Index], "-i") == 0) { + // + // Input File found + // + Index++; + InputFileName = (char **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)); + if (InputFileName == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory"); + return EFI_OUT_OF_RESOURCES; + } + + memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *))); + InputFileName[InputFileNum] = argv[Index]; + InputFileNum++; + Index++; + // + // Parse subsequent parameters until another switch is encountered + // + while ((Index < argc) && (argv[Index][0] != '-')) { + if ((InputFileNum % MAXIMUM_INPUT_FILE_NUM) == 0) { + // + // InputFileName buffer too small, need to realloc + // + InputFileName = (char **) realloc ( + InputFileName, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (char *) + ); + if (InputFileName == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory"); + return EFI_OUT_OF_RESOURCES; + } + + memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *))); + } + + InputFileName[InputFileNum] = argv[Index]; + InputFileNum++; + Index++; + } + + } + + if (strcmpi (argv[Index], "-o") == 0) { + // + // Output file found + // + Index++; + OutputFileName = argv[Index]; + } else if (strcmpi (argv[Index], "-s") == 0) { + // + // Section Type found + // + Index++; + ParamSectionType = argv[Index]; + } else if (strcmpi (argv[Index], "-t") == 0) { + // + // Compression or Authentication type + // + Index++; + ParamSectionSubType = argv[Index]; + } else if (strcmpi (argv[Index], "-l") == 0) { + // + // Length + // + Index++; + ParamLength = argv[Index]; + } else if (strcmpi (argv[Index], "-v") == 0) { + // + // VersionNumber + // + Index++; + ParamVersion = argv[Index]; + } else if (strcmpi (argv[Index], "-a") == 0) { + // + // Aux string + // + Index++; + // + // Note, the MSVC C-Start parses out and consolidates quoted strings from the command + // line. Quote characters are stripped. If this tool is ported to other environments + // this will need to be taken into account + // + strncpy (AuxString, argv[Index], 499); + } else if (strcmpi (argv[Index], "-d") == 0) { + // + // Digital signature for EFI_TEST_AUTHENTICAION (must be 0 or 1) + // + Index++; + ParamDigitalSignature = argv[Index]; + } else if (strcmpi (argv[Index], "-?") == 0) { + PrintUsageMessage (); + return STATUS_ERROR; + } else { + Error (NULL, 0, 0, argv[Index], "unknown option"); + return GetUtilityStatus (); + } + + Index++; + } + // + // At this point, all command line parameters are verified as not being totally + // bogus. Next verify the command line parameters are complete and make + // sense... + // + if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) { + SectionType = EFI_SECTION_COMPRESSION; + SubTypeRequired = TRUE; + if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) { + SectionSubType = EFI_NOT_COMPRESSED; + } else if (stricmp (ParamSectionSubType, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) { + SectionSubType = EFI_STANDARD_COMPRESSION; + } else { + Error (NULL, 0, 0, ParamSectionSubType, "unknown compression type"); + PrintUsageMessage (); + return GetUtilityStatus (); + } + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) { + SectionType = EFI_SECTION_GUID_DEFINED; + SubTypeRequired = TRUE; + if (stricmp (ParamSectionSubType, GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]) == 0) { + SectionSubType = EFI_SECTION_CRC32_GUID_DEFINED; + } else { + Error (NULL, 0, 0, ParamSectionSubType, "unknown GUID defined section type", ParamSectionSubType); + PrintUsageMessage (); + return GetUtilityStatus (); + } + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PE32]) == 0) { + SectionType = EFI_SECTION_PE32; + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PIC]) == 0) { + SectionType = EFI_SECTION_PIC; + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_TE]) == 0) { + SectionType = EFI_SECTION_TE; + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) { + SectionType = EFI_SECTION_DXE_DEPEX; + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_VERSION]) == 0) { + SectionType = EFI_SECTION_VERSION; + InputFileRequired = FALSE; + Index = sscanf (ParamVersion, "%d", &VersionNumber); + if (Index != 1 || VersionNumber < 0 || VersionNumber > 65565) { + Error (NULL, 0, 0, ParamVersion, "illegal version number"); + PrintUsageMessage (); + return GetUtilityStatus (); + } + + if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) { + AuxString[0] = 0; + } + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) { + SectionType = EFI_SECTION_USER_INTERFACE; + InputFileRequired = FALSE; + if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) { + Error (NULL, 0, 0, "user interface string not specified", NULL); + PrintUsageMessage (); + return GetUtilityStatus (); + } + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) { + SectionType = EFI_SECTION_COMPATIBILITY16; + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) { + SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) { + SectionType = EFI_SECTION_FREEFORM_SUBTYPE_GUID; + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_RAW]) == 0) { + SectionType = EFI_SECTION_RAW; + } else if (stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) { + SectionType = EFI_SECTION_PEI_DEPEX; + } else { + Error (NULL, 0, 0, ParamSectionType, "unknown section type"); + PrintUsageMessage (); + return GetUtilityStatus (); + } + // + // Open output file + // + OutFile = fopen (OutputFileName, "wb"); + if (OutFile == NULL) { + Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing"); + if (InFile != NULL) { + fclose (InFile); + } + + return GetUtilityStatus (); + } + // + // At this point, we've fully validated the command line, and opened appropriate + // files, so let's go and do what we've been asked to do... + // + // + // Within this switch, build and write out the section header including any + // section type specific pieces. If there's an input file, it's tacked on later + // + switch (SectionType) { + case EFI_SECTION_COMPRESSION: + Status = GenSectionCompressionSection ( + InputFileName, + InputFileNum, + SectionType, + SectionSubType, + OutFile + ); + break; + + case EFI_SECTION_GUID_DEFINED: + Status = GenSectionGuidDefinedSection ( + InputFileName, + InputFileNum, + SectionType, + SectionSubType, + OutFile + ); + break; + + case EFI_SECTION_VERSION: + CommonSect.Type = (EFI_SECTION_TYPE) SectionType; + + Index = sizeof (CommonSect); + // + // 2 characters for the build number + // + Index += 2; + // + // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null. + // + Index += (strlen (AuxString) * 2) + 2; + memcpy (&CommonSect.Size, &Index, 3); + fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile); + fwrite (&VersionNumber, 2, 1, OutFile); + Ascii2UnicodeWriteString (AuxString, OutFile, FALSE); + break; + + case EFI_SECTION_USER_INTERFACE: + CommonSect.Type = (EFI_SECTION_TYPE) SectionType; + Index = sizeof (CommonSect); + // + // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null. + // + Index += (strlen (AuxString) * 2) + 2; + memcpy (&CommonSect.Size, &Index, 3); + fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile); + Ascii2UnicodeWriteString (AuxString, OutFile, FALSE); + break; + + default: + // + // All other section types are caught by default (they're all the same) + // + Status = GenSectionCommonLeafSection ( + InputFileName, + InputFileNum, + SectionType, + OutFile + ); + break; + } + + if (InputFileName != NULL) { + free (InputFileName); + } + + fclose (OutFile); + // + // If we had errors, then delete the output file + // + if (GetUtilityStatus () == STATUS_ERROR) { + remove (OutputFileName); + } + + return GetUtilityStatus (); +} diff --git a/Tools/Source/TianoTools/GenSection/GenSection.h b/Tools/Source/TianoTools/GenSection/GenSection.h new file mode 100644 index 0000000000..847b3eba08 --- /dev/null +++ b/Tools/Source/TianoTools/GenSection/GenSection.h @@ -0,0 +1,43 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GenSection.h + +Abstract: + + Header file for GenSection. + +--*/ + +// +// Module Coded to Tiano Coding Conventions +// +#ifndef _EFI_GEN_SECTION_H +#define _EFI_GEN_SECTION_H + +// +// External Files Referenced +// +#include +#include +#include "FirmwareVolumeImageFormat.h" + +typedef struct { + EFI_GUID_DEFINED_SECTION GuidSectionHeader; + UINT32 CRC32Checksum; +} CRC32_SECTION_HEADER; + +#define EFI_SECTION_CRC32_GUID_DEFINED 0 +#define CRC32_SECTION_HEADER_SIZE (sizeof (CRC32_SECTION_HEADER)) + +#endif diff --git a/Tools/Source/TianoTools/GenSection/build.gcc b/Tools/Source/TianoTools/GenSection/build.gcc new file mode 100644 index 0000000000..5ad50a4b1a --- /dev/null +++ b/Tools/Source/TianoTools/GenSection/build.gcc @@ -0,0 +1 @@ +gcc -mno-cygwin -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ *.c -o GenSection -L../Library-mingw -lCommon -lCustomizedCompress diff --git a/Tools/Source/TianoTools/GenSection/build.xml b/Tools/Source/TianoTools/GenSection/build.xml new file mode 100644 index 0000000000..744bff8161 --- /dev/null +++ b/Tools/Source/TianoTools/GenSection/build.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/GuidChk/CommonUtils.h b/Tools/Source/TianoTools/GuidChk/CommonUtils.h new file mode 100644 index 0000000000..f7a331e5d7 --- /dev/null +++ b/Tools/Source/TianoTools/GuidChk/CommonUtils.h @@ -0,0 +1,57 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + CommonUtils.h + +Abstract: + + Common utility defines and structure definitions. + +--*/ + +#ifndef _COMMON_UTILS_H_ +#define _COMMON_UTILS_H_ + +// +// Basic types +// +typedef unsigned char UINT8; +typedef char INT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; + +typedef UINT8 BOOLEAN; +typedef UINT32 STATUS; + +#define TRUE 1 +#define FALSE 0 + +#define STATUS_SUCCESS 0 +#define STATUS_WARNING 1 +#define STATUS_ERROR 2 + +// +// Linked list of strings +// +typedef struct _STRING_LIST { + struct _STRING_LIST *Next; + char *Str; +} STRING_LIST; + +int +CreateGuidList ( + INT8 *OutFileName + ) +; + +#endif // #ifndef _COMMON_UTILS_H_ diff --git a/Tools/Source/TianoTools/GuidChk/FileSearch.c b/Tools/Source/TianoTools/GuidChk/FileSearch.c new file mode 100644 index 0000000000..8b5b58fddf --- /dev/null +++ b/Tools/Source/TianoTools/GuidChk/FileSearch.c @@ -0,0 +1,285 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + FileSearch.c + +Abstract: + + Module used to support file searches on the system. + +--*/ + +#include + +#include "CommonUtils.h" +#include "FileSearch.h" +#include "UtilsMsgs.h" + +// +// Internal file search flag for sanity checks +// +#define FILE_SEARCH_STARTED 0x8000 +#define FILE_SEARCH_INITED 0x4000 + +static +BOOLEAN +FileSearchMeetsCriteria ( + FILE_SEARCH_DATA *FSData + ); + +/*****************************************************************************/ +STATUS +FileSearchInit ( + FILE_SEARCH_DATA *FSData + ) +{ + memset ((char *) FSData, 0, sizeof (FILE_SEARCH_DATA)); + FSData->Handle = INVALID_HANDLE_VALUE; + FSData->FileSearchFlags = FILE_SEARCH_INITED; + FSData->FileName[0] = 0; + return STATUS_SUCCESS; +} + +STATUS +FileSearchStart ( + FILE_SEARCH_DATA *FSData, + char *FileMask, + UINT32 SearchFlags + ) +{ + BOOLEAN Done; + + // + // Save their flags, and set a flag to indicate that they called this + // start function so we can perform extended checking in the other + // routines we have in this module. + // + FSData->FileSearchFlags |= (SearchFlags | FILE_SEARCH_STARTED); + FSData->FileName[0] = 0; + + // + // Begin the search + // + FSData->Handle = FindFirstFile (FileMask, &(FSData->FindData)); + if (FSData->Handle == INVALID_HANDLE_VALUE) { + return STATUS_ERROR; + } + // + // Keep looping through until we find a file meeting the caller's + // criteria per the search flags + // + Done = FALSE; + while (!Done) { + // + // If we're done (we found a match) copy the file name found and return + // + Done = FileSearchMeetsCriteria (FSData); + if (Done) { + return STATUS_SUCCESS; + } + // + // Go on to next file + // + if (!FindNextFile (FSData->Handle, &(FSData->FindData))) { + return STATUS_NOT_FOUND; + } + } + // + // Not reached + // + return STATUS_NOT_FOUND; +} + +// +// Find the next file meeting their criteria and return it. +// +STATUS +FileSearchFindNext ( + FILE_SEARCH_DATA *FSData + ) +{ + BOOLEAN Done; + + Done = FALSE; + while (!Done) { + if (!FindNextFile (FSData->Handle, &(FSData->FindData))) { + return STATUS_NOT_FOUND; + } + // + // See if it matches their criteria + // + Done = FileSearchMeetsCriteria (FSData); + if (Done) { + return STATUS_SUCCESS; + } + } + // + // Not reached + // + return STATUS_NOT_FOUND; +} +// +// Perform any cleanup necessary to close down a search +// +STATUS +FileSearchDestroy ( + FILE_SEARCH_DATA *FSData + ) +{ + if (FSData->Handle != INVALID_HANDLE_VALUE) { + FindClose (FSData->Handle); + FSData->Handle = INVALID_HANDLE_VALUE; + } + + FSData->FileName[0] = 0; + FSData->FileSearchFlags = 0; + return STATUS_SUCCESS; +} + +static +BOOLEAN +FileSearchMeetsCriteria ( + FILE_SEARCH_DATA *FSData + ) +{ + BOOLEAN Status; + STRING_LIST *StrList; + UINT32 ExtLen; + UINT32 FileNameLen; + + Status = FALSE; + + // + // First clear the flag indicating this is neither a file or a + // directory. + // + FSData->FileFlags &= ~(FILE_SEARCH_DIR | FILE_SEARCH_FILE); + + // + // We found a file. See if it matches the user's search criteria. First + // check for this being a directory, and they want directories, and + // it's not "." and it's not ".." + // + if ((FSData->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + (FSData->FileSearchFlags & FILE_SEARCH_DIR) && + (strcmp (FSData->FindData.cFileName, ".")) && + (strcmp (FSData->FindData.cFileName, "..")) + ) { + // + // Assume we'll make it past this check + // + Status = TRUE; + // + // If they have a list of exclude directories, then check for those + // + StrList = FSData->ExcludeDirs; + while (StrList != NULL) { + if (stricmp (FSData->FindData.cFileName, StrList->Str) == 0) { + Status = FALSE; + break; + } + + StrList = StrList->Next; + } + // + // If we didn't fail due to excluded directories, then set the dir flag + // + if (Status) { + FSData->FileFlags |= FILE_SEARCH_DIR; + } + // + // Else check for a file, and they want files.... + // + } else if (((FSData->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) && + (FSData->FileSearchFlags & FILE_SEARCH_FILE) + ) { + // + // See if it's in our list of excluded files + // + Status = TRUE; + StrList = FSData->ExcludeFiles; + while (StrList != NULL) { + if (stricmp (FSData->FindData.cFileName, StrList->Str) == 0) { + Status = FALSE; + break; + } + + StrList = StrList->Next; + } + + if (Status) { + // + // See if it's in our list of excluded file extensions + // + FileNameLen = strlen (FSData->FindData.cFileName); + StrList = FSData->ExcludeExtensions; + while (StrList != NULL) { + ExtLen = strlen (StrList->Str); + if (stricmp ( + FSData->FindData.cFileName + FileNameLen - ExtLen, + StrList->Str + ) == 0) { + Status = FALSE; + break; + } + + StrList = StrList->Next; + } + } + + if (Status) { + FSData->FileFlags |= FILE_SEARCH_FILE; + } + } + // + // If it's a match, copy the filename into another field of the structure + // for portability. + // + if (Status) { + strcpy (FSData->FileName, FSData->FindData.cFileName); + } + + return Status; +} +// +// Exclude a list of subdirectories. +// +STATUS +FileSearchExcludeDirs ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +{ + FSData->ExcludeDirs = StrList; + return STATUS_SUCCESS; +} + +STATUS +FileSearchExcludeFiles ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +{ + FSData->ExcludeFiles = StrList; + return STATUS_SUCCESS; +} + +STATUS +FileSearchExcludeExtensions ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +{ + FSData->ExcludeExtensions = StrList; + return STATUS_SUCCESS; +} diff --git a/Tools/Source/TianoTools/GuidChk/FileSearch.h b/Tools/Source/TianoTools/GuidChk/FileSearch.h new file mode 100644 index 0000000000..bc40265366 --- /dev/null +++ b/Tools/Source/TianoTools/GuidChk/FileSearch.h @@ -0,0 +1,108 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + FileSearch.h + +Abstract: + + Header file to support file searching. + +--*/ + +#ifndef _FILE_SEARCH_H_ +#define _FILE_SEARCH_H_ + +// +// Since the file searching routines are OS dependent, put the +// necessary include paths in this header file so that the non-OS-dependent +// files don't need to include these windows-specific header files. +// +#include +#include +#include +#include +#include + +// +// Return codes of some of the file search routines +// +#define STATUS_NOT_FOUND 0x1000 + +// +// Flags for what to search for. Also used in the FileFlags return field. +// +#define FILE_SEARCH_DIR 0x0001 +#define FILE_SEARCH_FILE 0x0002 + +// +// Here's our class definition +// +typedef struct { + HANDLE Handle; + WIN32_FIND_DATA FindData; + UINT32 FileSearchFlags; // DIRS, FILES, etc + UINT32 FileFlags; + INT8 FileName[MAX_PATH]; // for portability + STRING_LIST *ExcludeDirs; + STRING_LIST *ExcludeFiles; + STRING_LIST *ExcludeExtensions; +} FILE_SEARCH_DATA; + +// +// Here's our member functions +// +STATUS +FileSearchInit ( + FILE_SEARCH_DATA *FSData + ) +; + +STATUS +FileSearchDestroy ( + FILE_SEARCH_DATA *FSData + ) +; + +STATUS +FileSearchStart ( + FILE_SEARCH_DATA *FSData, + char *FileMask, + UINT32 SearchFlags + ) +; + +STATUS +FileSearchFindNext ( + FILE_SEARCH_DATA *FSData + ) +; + +STATUS +FileSearchExcludeDirs ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +; +STATUS +FileSearchExcludeExtensions ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +; +STATUS +FileSearchExcludeFiles ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +; +#endif diff --git a/Tools/Source/TianoTools/GuidChk/GuidChk.c b/Tools/Source/TianoTools/GuidChk/GuidChk.c new file mode 100644 index 0000000000..de88405872 --- /dev/null +++ b/Tools/Source/TianoTools/GuidChk/GuidChk.c @@ -0,0 +1,2348 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GuidChk.c + +Abstract: + + Parse files in a directory and subdirectories to find all guid definitions. + Then check them against each other to make sure there are no duplicates. + +--*/ + +#include +#include +#include +#include + +#include "CommonUtils.h" +#include "FileSearch.h" +#include "UtilsMsgs.h" + +#define MAX_LINE_LEN 180 // we concatenate two lines sometimes +// Define a structure that correlates filename extensions to an enumerated +// type. +// +typedef struct { + INT8 *Extension; + INT8 ExtensionCode; +} FILE_TYPE_TABLE_ENTRY; + +#define FILE_EXTENSION_UNKNOWN 0 +#define FILE_EXTENSION_C 1 +#define FILE_EXTENSION_H 2 +#define FILE_EXTENSION_IA32_ASM 3 +#define FILE_EXTENSION_IA32_INC 4 +#define FILE_EXTENSION_IA64_ASM 5 +#define FILE_EXTENSION_IA64_INC 6 +#define FILE_EXTENSION_PKG 7 +#define FILE_EXTENSION_INF 8 + +FILE_TYPE_TABLE_ENTRY FileTypeTable[] = { + ".c", + FILE_EXTENSION_C, + ".h", + FILE_EXTENSION_H, + ".inc", + FILE_EXTENSION_IA32_INC, + ".asm", + FILE_EXTENSION_IA32_ASM, + ".s", + FILE_EXTENSION_IA64_ASM, + ".pkg", + FILE_EXTENSION_PKG, + ".inf", + FILE_EXTENSION_INF, + ".i", + FILE_EXTENSION_IA64_INC, + NULL, + 0 +}; + +typedef struct EFI_GUID { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} EFI_GUID; + +typedef struct { + INT8 Data[4]; + INT8 DataLen; +} EFI_SIGNATURE; + +typedef struct _GUID_RECORD { + struct _GUID_RECORD *Next; + BOOLEAN Reported; + INT8 *FileName; + INT8 *SymName; + EFI_GUID Guid; +} GUID_RECORD; + +typedef struct _SIGNATURE_RECORD { + struct _SIGNATURE_RECORD *Next; + BOOLEAN Reported; + INT8 *FileName; + EFI_SIGNATURE Signature; +} SIGNATURE_RECORD; + +// +// Utility options +// +typedef struct { + INT8 DatabaseOutputFileName[MAX_PATH]; // with -b option + STRING_LIST *ExcludeDirs; // list of directory names not to process + STRING_LIST *ExcludeSubDirs; // list of directory names to not process subdirectories (build) + STRING_LIST *ExcludeFiles; // list of files to exclude (make.inf) + STRING_LIST *ExcludeExtensions; // list of filename extensions to exclude (.inf, .pkg) + BOOLEAN Verbose; + BOOLEAN PrintFound; + BOOLEAN CheckGuids; + BOOLEAN CheckSignatures; + BOOLEAN GuidXReference; +} OPTIONS; + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ); + +static +VOID +Usage ( + VOID + ); + +static +STATUS +ProcessDirectory ( + INT8 *Path, + INT8 *DirectoryName + ); + +static +STATUS +ProcessFile ( + INT8 *DirectoryName, + INT8 *FileName + ); + +static +UINT32 +GetFileExtension ( + INT8 *FileName + ); + +static +UINT32 +SkipWhiteSpace ( + INT8 *Str + ); + +static +UINT32 +ValidSymbolName ( + INT8 *Name + ); + +static +STATUS +ProcessCFileGuids ( + INT8 *FileName + ); + +static +STATUS +AddSignature ( + INT8 *FileName, + INT8 *StrDef, + UINT32 SigSize + ); + +static +STATUS +ProcessCFileSigs ( + INT8 *FileName + ); + +static +STATUS +ProcessINFFileGuids ( + INT8 *FileName + ); + +static +STATUS +ProcessPkgFileGuids ( + INT8 *FileName + ); + +static +STATUS +ProcessIA32FileGuids ( + INT8 *FileName + ); + +static +STATUS +ProcessIA64FileGuids ( + INT8 *FileName + ); + +static +BOOLEAN +IsIA64GuidLine ( + INT8 *Line, + UINT32 *GuidHigh, + UINT32 *GuidLow, + BOOLEAN *Low, + INT8 *SymName + ); + +static +STATUS +AddGuid11 ( + INT8 *FileName, + UINT32 *Data, + INT8 *SymName + ); + +static +STATUS +AddPkgGuid ( + INT8 *FileName, + UINT32 *Data, + UINT64 *Data64 + ); + +static +STATUS +AddGuid16 ( + INT8 *FileName, + UINT32 *Data + ); + +static +STATUS +AddGuid64x2 ( + INT8 *FileName, + UINT32 DataHH, // Upper 32-bits of upper 64 bits of guid + UINT32 DataHL, // Lower 32-bits of upper 64 bits + UINT32 DataLH, + UINT32 DataLL + ); + +static +VOID +FreeGuids ( + VOID + ); + +static +VOID +FreeSigs ( + VOID + ); + +static +STATUS +CheckDuplicates ( + VOID + ); + +// +// static +// VOID +// ReportGuid ( +// INT8 *FileName, +// GUID_RECORD *FileRecord +// ); +// +static +VOID +FreeOptions ( + VOID + ); + +static +BOOLEAN +CheckGuidData ( + UINT32 *GuidData, + UINT32 DataCount + ); + +/**************************** GLOBALS ****************************************/ +static GUID_RECORD *gGuidList = NULL; +static SIGNATURE_RECORD *gSignatureList = NULL; +static OPTIONS gOptions; + +/*****************************************************************************/ +int +main ( + int Argc, + char *Argv[] + ) +{ + INT8 *Cwd; + STATUS Status; + + SetUtilityName ("GuidChk"); + // + // Get the current working directory and then process the command line + // arguments. + // + Cwd = _getcwd (NULL, 0); + Status = ProcessArgs (Argc, Argv); + if (Status != STATUS_SUCCESS) { + return Status; + } + + if (gOptions.CheckGuids || gOptions.CheckSignatures) { + Status = ProcessDirectory (Cwd, NULL); + if (Status == STATUS_SUCCESS) { + // + // Check for duplicates + // + Status = CheckDuplicates (); + } + } + + if (gOptions.DatabaseOutputFileName[0] != 0) { + CreateGuidList (gOptions.DatabaseOutputFileName); + } + // + // Free up the memory + // + free (Cwd); + FreeGuids (); + FreeSigs (); + FreeOptions (); + return GetUtilityStatus (); +} + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ) +{ + STRING_LIST *StrList; + + memset ((char *) &gOptions, 0, sizeof (gOptions)); + // + // skip over program name + // + Argc--; + Argv++; + + if (Argc == 0) { + Usage (); + return STATUS_ERROR; + } + + while (Argc > 0) { + // + // Look for options + // + if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) { + switch (Argv[0][1]) { + // + // Help option + // + case 'h': + case 'H': + case '?': + Usage (); + return STATUS_ERROR; + break; + + // + // Check guids option + // + case 'g': + case 'G': + gOptions.CheckGuids = TRUE; + break; + + // + // Check signatures option + // + case 's': + case 'S': + gOptions.CheckSignatures = TRUE; + break; + + // + // Print guids found option + // + case 'p': + case 'P': + gOptions.PrintFound = TRUE; + break; + + // + // Exclude files option + // + case 'f': + case 'F': + // + // Check for another arg + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "missing argument with option"); + Usage (); + return STATUS_ERROR; + } + + StrList = malloc (sizeof (STRING_LIST)); + if (StrList == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) StrList, 0, sizeof (STRING_LIST)); + StrList->Str = Argv[1]; + StrList->Next = gOptions.ExcludeFiles; + gOptions.ExcludeFiles = StrList; + Argc--; + Argv++; + break; + + // + // Exclude directories option + // + case 'd': + case 'D': + // + // Check for another arg + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "missing argument with option"); + Usage (); + return STATUS_ERROR; + } + + StrList = malloc (sizeof (STRING_LIST)); + if (StrList == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) StrList, 0, sizeof (STRING_LIST)); + StrList->Str = Argv[1]; + StrList->Next = gOptions.ExcludeDirs; + gOptions.ExcludeDirs = StrList; + Argc--; + Argv++; + break; + + // + // -u exclude all subdirectories of a given directory option + // + case 'u': + case 'U': + // + // Check for another arg + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "missing argument with option"); + Usage (); + return STATUS_ERROR; + } + + StrList = malloc (sizeof (STRING_LIST)); + if (StrList == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) StrList, 0, sizeof (STRING_LIST)); + StrList->Str = Argv[1]; + StrList->Next = gOptions.ExcludeSubDirs; + gOptions.ExcludeSubDirs = StrList; + Argc--; + Argv++; + break; + + // + // -e exclude by filename extension option + // + case 'e': + case 'E': + // + // Check for another arg + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "missing argument with option"); + Usage (); + return STATUS_ERROR; + } + + StrList = malloc (sizeof (STRING_LIST)); + if (StrList == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) StrList, 0, sizeof (STRING_LIST)); + // + // Let them put a * in front of the filename extension + // + StrList->Str = Argv[1]; + if (StrList->Str[0] == '*') { + StrList->Str++; + } + + StrList->Next = gOptions.ExcludeExtensions; + gOptions.ExcludeExtensions = StrList; + Argc--; + Argv++; + break; + + // + // Print guid with matching symbol name for guid definitions found + // + case 'x': + case 'X': + gOptions.GuidXReference = 1; + break; + + // + // -b Print the internal database list to a file + // + case 'b': + case 'B': + // + // Check for one more arg + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "must specify file name with option"); + Usage (); + return STATUS_ERROR; + } + + strcpy (gOptions.DatabaseOutputFileName, Argv[1]); + Argc--; + Argv++; + break; + + default: + Error (NULL, 0, 0, Argv[0], "invalid option"); + Usage (); + return STATUS_ERROR; + } + } else { + break; + } + // + // Next arg + // + Argc--; + Argv++; + } + + if (Argc > 0) { + Error (NULL, 0, 0, Argv[0], "invalid argument"); + Usage (); + return STATUS_ERROR; + } + // + // Have to check signatures, GUIDs, or dump the GUID database. + // + if ((!gOptions.CheckGuids) && (!gOptions.CheckSignatures) && (gOptions.DatabaseOutputFileName[0] == 0)) { + Error (NULL, 0, 0, "nothing to do", "must specify -g, -s, and/or -b"); + Usage (); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} +// +// Print usage instructions +// +static +VOID +Usage ( + VOID + ) +{ + int Index; + char *Str[] = { + "GuidChk - scan files for duplicate GUID or signature definitions", + "", + "Usage: GuidChk {options}\n", + " Options: ", + " -d dirname exclude searching of a directory", + " -f filename exclude searching of a file", + " -e extension exclude searching of files by extension", + " -p print all GUIDS found", + " -g check for duplicate guids", + " -s check for duplicate signatures", + " -x print guid+defined symbol name", + " -b outfile write internal GUID+basename list to outfile", + " -u dirname exclude searching all subdirectories of a directory", + " -h -? print this help text", + " ", + " Example: GuidChk -g -u build -d fv -f make.inf -e .pkg", + "", + NULL + }; + for (Index = 0; Str[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Str[Index]); + } +} +// +// Process an entire directory by name +// +static +STATUS +ProcessDirectory ( + INT8 *Path, + INT8 *DirectoryName + ) +{ + FILE_SEARCH_DATA FSData; + char *FileMask; + BOOLEAN Done; + UINT32 Len; + BOOLEAN NoSubdirs; + STRING_LIST *SLPtr; + + // + // Root directory may be null + // + if (DirectoryName != NULL) { + // + // printf ("Processing directory: %s\n", DirectoryName); + // + } + // + // Initialize our file searching + // + FileSearchInit (&FSData); + + // + // Exclude some directories, files, and extensions + // + FileSearchExcludeDirs (&FSData, gOptions.ExcludeDirs); + FileSearchExcludeExtensions (&FSData, gOptions.ExcludeExtensions); + FileSearchExcludeFiles (&FSData, gOptions.ExcludeFiles); + // + // See if this directory is in the list of directories that they + // don't want to process subdirectories of + // + NoSubdirs = FALSE; + if (DirectoryName != NULL) { + for (SLPtr = gOptions.ExcludeSubDirs; SLPtr != NULL; SLPtr = SLPtr->Next) { + if (stricmp (SLPtr->Str, DirectoryName) == 0) { + // + // printf ("not processing subdirectories of %s\n", DirectoryName); + // + NoSubdirs = TRUE; + break; + } + } + } + // + // Create a filemask of files to search for. We'll append "\*.*" on the + // end, so allocate some extra bytes. + // + Len = strlen (Path) + 10; + if (DirectoryName != NULL) { + Len += strlen (DirectoryName); + } + + FileMask = malloc (Len); + if (FileMask == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + // + // Now put it all together + // + strcpy (FileMask, Path); + if ((DirectoryName != NULL) && (strlen (DirectoryName) > 0)) { + strcat (FileMask, "\\"); + strcat (FileMask, DirectoryName); + } + + strcat (FileMask, "\\*.*"); + + // + // Start file searching for files and directories + // + FileSearchStart (&FSData, FileMask, FILE_SEARCH_FILE | FILE_SEARCH_DIR); + + // + // Now hack the "\*.*" off the end of the filemask so we can use it to pass + // the full directory path on recursive calls to process directories. + // + FileMask[strlen (FileMask) - 4] = 0; + + // + // Loop until no more files + // + Done = FALSE; + while (!Done) { + // + // printf ("Found %s...", FSData.FileName); + // + if (FSData.FileFlags & FILE_SEARCH_DIR) { + // + // printf ("directory\n"); + // + if (!NoSubdirs) { + ProcessDirectory (FileMask, FSData.FileName); + } + } else if (FSData.FileFlags & FILE_SEARCH_FILE) { + // + // printf ("file\n"); + // + ProcessFile (FileMask, FSData.FileName); + } else { + // + // printf ("unknown\n"); + // + } + + if (FileSearchFindNext (&FSData) != STATUS_SUCCESS) { + Done = TRUE; + } + } + // + // Free up allocated memory + // + free (FileMask); + + // + // Free up our file searching + // + FileSearchDestroy (&FSData); + + return STATUS_SUCCESS; +} +// +// Process a single file. +// +static +STATUS +ProcessFile ( + INT8 *DirectoryName, + INT8 *FileName + ) +{ + STATUS Status; + UINT32 FileExtension; + INT8 FullFileName[MAX_PATH]; + + Status = STATUS_SUCCESS; + + sprintf (FullFileName, "%s\\%s", DirectoryName, FileName); + // + // printf ("Found file: %s\n", FullFileName); + // + FileExtension = GetFileExtension (FileName); + + // + // Process these for GUID checks + // + if (gOptions.CheckGuids) { + switch (FileExtension) { + case FILE_EXTENSION_C: + case FILE_EXTENSION_H: + Status = ProcessCFileGuids (FullFileName); + break; + + case FILE_EXTENSION_PKG: + Status = ProcessPkgFileGuids (FullFileName); + break; + + case FILE_EXTENSION_IA32_INC: + case FILE_EXTENSION_IA32_ASM: + Status = ProcessIA32FileGuids (FullFileName); + break; + + case FILE_EXTENSION_INF: + Status = ProcessINFFileGuids (FullFileName); + break; + + case FILE_EXTENSION_IA64_INC: + case FILE_EXTENSION_IA64_ASM: + Status = ProcessIA64FileGuids (FullFileName); + break; + + default: + // + // No errors anyway + // + Status = STATUS_SUCCESS; + break; + } + } + + if (gOptions.CheckSignatures) { + switch (FileExtension) { + case FILE_EXTENSION_C: + case FILE_EXTENSION_H: + Status = ProcessCFileSigs (FullFileName); + break; + + default: + // + // No errors anyway + // + Status = STATUS_SUCCESS; + break; + } + } + + return Status; +} +// +// Return a code indicating the file name extension. +// +static +UINT32 +GetFileExtension ( + INT8 *FileName + ) +{ + INT8 *Extension; + int Index; + + // + // Look back for a filename extension + // + for (Extension = FileName + strlen (FileName) - 1; Extension >= FileName; Extension--) { + if (*Extension == '.') { + for (Index = 0; FileTypeTable[Index].Extension != NULL; Index++) { + if (stricmp (FileTypeTable[Index].Extension, Extension) == 0) { + return FileTypeTable[Index].ExtensionCode; + } + } + } + } + + return FILE_TYPE_UNKNOWN; +} +// +// Process a .pkg file. +// +// Look for FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7 +// +static +STATUS +ProcessPkgFileGuids ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN * 2]; + INT8 *Cptr; + INT8 *Cptr2; + UINT32 GuidScan[11]; + UINT64 Guid64; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + // + // Read lines from the file until done + // + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + Cptr = Line; + Cptr += SkipWhiteSpace (Line); + if (strncmp (Cptr, "FFS_FILEGUID", 12) == 0) { + Cptr += 12; + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr == '=') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr + 1); + // + // Blank out dashes on the line. + // + for (Cptr2 = Cptr; *Cptr2; Cptr2++) { + if (*Cptr2 == '-') { + *Cptr2 = ' '; + } + } + + if (sscanf ( + Cptr, + "%X %X %X %X %I64X", + &GuidScan[0], + &GuidScan[1], + &GuidScan[2], + &GuidScan[3], + &Guid64 + ) == 5) { + AddPkgGuid (FileName, GuidScan, &Guid64); + } else { + DebugMsg (NULL, 0, 0, FileName, "GUID scan failed"); + } + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// Process an IA32 assembly file. +// +// Look for: +// FIND_FD_GUID_VAL equ 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h +// PEI_GUID_FileNameGuid_Gmch815 equ 081818181h, 08181h, 08181h, 081h, 081h, 081h, 081h, 081h, 081h, 081h, 081h +// +static +STATUS +ProcessIA32FileGuids ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN]; + INT8 *Cptr; + INT8 CSave; + INT8 *CSavePtr; + UINT32 Len; + UINT32 GuidData[16]; + UINT32 Index; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + // + // Read lines from the file until done + // + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + Cptr = Line; + Cptr += SkipWhiteSpace (Line); + // + // Look for xxxGUIDyyy equ 01h, 02h, 03h, ... + // + Len = ValidSymbolName (Cptr); + if (Len) { + // + // Terminate the line after the symbol name, then look for "guid" in + // the name. + // + CSavePtr = Cptr + Len; + CSave = *CSavePtr; + *CSavePtr = 0; + while (*Cptr) { + if (strnicmp (Cptr, "guid", 4) == 0) { + break; + } + + Cptr++; + } + // + // If we found the string "guid", continue + // + if (*Cptr) { + // + // Restore the character on the line where we null-terminated the symbol + // + *CSavePtr = CSave; + Cptr = CSavePtr; + Len = SkipWhiteSpace (Cptr); + // + // Had to be some white space + // + if (Len) { + Cptr += Len; + // + // now look for "equ" + // + if (strnicmp (Cptr, "equ", 3) == 0) { + Cptr += 3; + Cptr += SkipWhiteSpace (Cptr); + // + // Now scan all the data + // + for (Index = 0; Index < 16; Index++) { + if (sscanf (Cptr, "%X", &GuidData[Index]) != 1) { + break; + } + // + // Skip to next + // + while (isxdigit (*Cptr)) { + Cptr++; + } + + if ((*Cptr != 'h') && (*Cptr != 'H')) { + break; + } else { + Cptr++; + while (*Cptr && (isspace (*Cptr) || (*Cptr == ','))) { + Cptr++; + } + } + } + // + // Now see which form we had + // + if (Index == 16) { + AddGuid16 (FileName, GuidData); + } else if (Index == 11) { + AddGuid11 (FileName, GuidData, NULL); + } + } + } + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// Found and parsed an IA32 assembly code guid. Save the 16 bytes off in the list +// of guids. +// +static +STATUS +AddGuid16 ( + INT8 *FileName, + UINT32 *Data + ) +{ + GUID_RECORD *NewRec; + int Index; + + // + // Sanity check the data + // + if (!CheckGuidData (Data, 16)) { + return STATUS_ERROR; + } + // + // Allocate memory for a new guid structure + // + NewRec = malloc (sizeof (GUID_RECORD)); + if (NewRec == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) NewRec, 0, sizeof (GUID_RECORD)); + NewRec->FileName = malloc (strlen (FileName) + 1); + if (NewRec->FileName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewRec->FileName, FileName); + NewRec->Guid.Data1 = (UINT32) (Data[0] | (Data[1] << 8) | (Data[2] << 16) | (Data[3] << 24)); + NewRec->Guid.Data2 = (UINT16) (Data[4] | (Data[5] << 8)); + NewRec->Guid.Data3 = (UINT16) (Data[6] | (Data[7] << 8)); + for (Index = 0; Index < 8; Index++) { + NewRec->Guid.Data4[Index] = (UINT8) Data[Index + 8]; + } + // + // Add it to the list + // + NewRec->Next = gGuidList; + gGuidList = NewRec; + + // + // Report it + // ReportGuid (FileName, NewRec); + // + return STATUS_SUCCESS; +} +// +// Add a GUID defined as GuidLow: 0x1122334455667788 +// GuidHi: 0x99AABBCCDDEEFF00 +// +// These are equivalent: +// { 0x11223344, 0x5566, 0x7788, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 } +// and: +// Low: 00FFEEDDCCBBAA99 +// Hi: 7788556611223344 +// +static +STATUS +AddGuid64x2 ( + INT8 *FileName, + UINT32 DataHH, // Upper 32-bits of upper 64 bits of guid + UINT32 DataHL, // Lower 32-bits of upper 64 bits + UINT32 DataLH, + UINT32 DataLL + ) +{ + GUID_RECORD *NewRec; + int Index; + + // + // Allocate memory for a new guid structure + // + NewRec = malloc (sizeof (GUID_RECORD)); + if (NewRec == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) NewRec, 0, sizeof (GUID_RECORD)); + NewRec->FileName = malloc (strlen (FileName) + 1); + if (NewRec->FileName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewRec->FileName, FileName); + NewRec->Guid.Data1 = DataHL; + NewRec->Guid.Data2 = (UINT16) DataHH; + NewRec->Guid.Data3 = (UINT16) (DataHH >> 16); + for (Index = 0; Index < 4; Index++) { + NewRec->Guid.Data4[Index] = (UINT8) DataLL; + DataLL >>= 8; + } + + for (Index = 0; Index < 4; Index++) { + NewRec->Guid.Data4[Index + 4] = (UINT8) DataLH; + DataLH >>= 8; + } + // + // Add it to the list + // + NewRec->Next = gGuidList; + gGuidList = NewRec; + + // + // Report it + // ReportGuid (FileName, NewRec); + // + return STATUS_SUCCESS; +} +// +// Process INF files. Look for: +// FILE_GUID = 240612B6-A063-11d4-9A3A-0090273FC14D +// +static +STATUS +ProcessINFFileGuids ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN * 2]; + INT8 *Cptr; + INT8 *Cptr2; + UINT32 GuidScan[11]; + UINT64 Guid64; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + // + // Read lines from the file until done + // + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + Cptr = Line; + Cptr += SkipWhiteSpace (Line); + if (strncmp (Cptr, "FILE_GUID", 9) == 0) { + Cptr += 9; + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr == '=') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr + 1); + // + // Blank out dashes on the line. + // + for (Cptr2 = Cptr; *Cptr2; Cptr2++) { + if (*Cptr2 == '-') { + *Cptr2 = ' '; + } + } + + if (sscanf ( + Cptr, + "%X %X %X %X %I64X", + &GuidScan[0], + &GuidScan[1], + &GuidScan[2], + &GuidScan[3], + &Guid64 + ) == 5) { + AddPkgGuid (FileName, GuidScan, &Guid64); + } else { + DebugMsg (NULL, 0, 0, FileName, "GUID scan failed"); + } + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// Parse ('g','m','a','p','a','b','c','d') +// +static +STATUS +AddSignature ( + INT8 *FileName, + INT8 *StrDef, + UINT32 SigSize + ) +{ + SIGNATURE_RECORD *NewRec; + INT8 *Cptr; + UINT32 Index; + BOOLEAN Fail; + + // + // Allocate memory for the new record + // + Fail = FALSE; + NewRec = malloc (sizeof (SIGNATURE_RECORD)); + if (NewRec == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + // + // Allocate memory to save the file name + // + NewRec->FileName = malloc (strlen (FileName) + 1); + if (NewRec->FileName == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + free (NewRec); + return STATUS_ERROR; + } + // + // Fill in the fields + // + strcpy (NewRec->FileName, FileName); + NewRec->Signature.DataLen = (UINT8) SigSize; + // + // Skip to open parenthesis + // + Cptr = StrDef; + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr != '(') { + Fail = TRUE; + goto Done; + } + + Cptr++; + // + // Skip to first ' and start processing + // + while (*Cptr && (*Cptr != '\'')) { + Cptr++; + } + + for (Index = 0; Index < SigSize; Index++) { + if (*Cptr == '\'') { + Cptr++; + NewRec->Signature.Data[Index] = (INT8) *Cptr; + // + // Skip to closing quote + // + Cptr++; + if (*Cptr != '\'') { + Fail = TRUE; + break; + } + // + // Skip over closing quote, go to next one + // + Cptr++; + while (*Cptr && (*Cptr != '\'')) { + Cptr++; + } + } else { + Fail = TRUE; + DebugMsg (NULL, 0, 0, StrDef, "failed to parse signature"); + break; + } + } + +Done: + if (Fail) { + free (NewRec->FileName); + free (NewRec); + return STATUS_ERROR; + } + + NewRec->Next = gSignatureList; + gSignatureList = NewRec; + return STATUS_SUCCESS; +} +// +// Look for: +// #define POOL_HEAD_SIGNATURE EFI_SIGNATURE_16('p','h') +// #define GCD_MEMORY_MAP_SIGNATURE EFI_SIGNATURE_32('g','m','a','p') +// #define GCD_MEMORY_MAP_SIGNATURE EFI_SIGNATURE_64('g','m','a','p','a','b','c','d') +// +static +STATUS +ProcessCFileSigs ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN * 2]; + INT8 *Cptr; + UINT32 Len; + UINT32 LineLen; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + // + // Read lines from the file until done + // + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + Cptr = Line; + Cptr += SkipWhiteSpace (Line); + // + // look for #define xxxGUIDxxx value + // + if (*Cptr == '#') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr); + // + // Look for "define" + // + if (!strncmp (Cptr, "define", 6)) { + Cptr += 6; + // + // Better be whitespace + // + Len = SkipWhiteSpace (Cptr); + if (Len) { + Cptr += Len; + // + // See if it's a valid symbol name + // + Len = ValidSymbolName (Cptr); + if (Len) { + // + // It is a valid symbol name. See if there's a line continuation, + // and if so, read one more line. + // Skip over the symbol name and look for the string "EFI_SIGNATURE_xx" + // + LineLen = strlen (Line); + if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) { + fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr); + } else if (Line[LineLen - 1] == '\\') { + fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr); + } + + Cptr += Len; + Cptr += SkipWhiteSpace (Cptr); + if (strncmp (Cptr, "EFI_SIGNATURE_16", 16) == 0) { + AddSignature (FileName, Cptr + 16, 2); + } else if (strncmp (Cptr, "EFI_SIGNATURE_32", 16) == 0) { + AddSignature (FileName, Cptr + 16, 4); + } else if (strncmp (Cptr, "EFI_SIGNATURE_64", 16) == 0) { + AddSignature (FileName, Cptr + 16, 8); + } + } + } + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// look for #define xxxGUIDyyy { 0x...} +// xxx EFI_GUID GuidName = { 0x... }; +// +static +STATUS +ProcessCFileGuids ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN * 2]; + INT8 *Cptr; + INT8 CSave; + INT8 *CSavePtr; + INT8 *TempCptr; + INT8 *SymName; + UINT32 Len; + UINT32 LineLen; + UINT32 GuidScan[11]; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + // + // Read lines from the file until done + // + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + Cptr = Line; + Cptr += SkipWhiteSpace (Line); + // + // look for #define xxxGUIDxxx value + // + if (*Cptr == '#') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr); + // + // Look for "define" + // + if (!strncmp (Cptr, "define", 6)) { + Cptr += 6; + // + // Better be whitespace + // + Len = SkipWhiteSpace (Cptr); + if (Len) { + Cptr += Len; + // + // See if it's a valid symbol name + // + Len = ValidSymbolName (Cptr); + if (Len) { + // + // It is a valid symbol name. See if there's a line continuation, + // and if so, read one more line. + // Then truncate after the symbol name, look for the string "GUID", + // and continue. + // + SymName = Cptr; + LineLen = strlen (Line); + if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) { + fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr); + } else if (Line[LineLen - 1] == '\\') { + fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr); + } + + CSavePtr = Cptr + Len; + CSave = *CSavePtr; + *CSavePtr = 0; + while (*Cptr) { + if (strncmp (Cptr, "GUID", 4) == 0) { + break; + } + + Cptr++; + } + // + // If we didn't run out of string, then we found the GUID string. + // Now look for { 0x....... } + // + if (*Cptr) { + Cptr = CSavePtr; + *CSavePtr = CSave; + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr == '{') { + *Cptr = 0; + Cptr++; + // + // 0x665E3FF6, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } + // If you have one suffixed with "L", then it doesn't work. So hack off 'L' characters + // in the string. + // + for (TempCptr = Cptr; *TempCptr; TempCptr++) { + if (*TempCptr == 'L') { + if (*(TempCptr + 1) == ',') { + *TempCptr = ','; + *(TempCptr + 1) = ' '; + } + } + } + + if (sscanf ( + Cptr, + "%X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X", + &GuidScan[0], + &GuidScan[1], + &GuidScan[2], + &GuidScan[3], + &GuidScan[4], + &GuidScan[5], + &GuidScan[6], + &GuidScan[7], + &GuidScan[8], + &GuidScan[9], + &GuidScan[10] + ) == 11) { + AddGuid11 (FileName, GuidScan, SymName); + } + } + } + } + } + } + // + // Else look for "static EFI_GUID xxxGUIDxxx = { 0x.... }; + // + } else if ((CSavePtr = strstr (Line, "EFI_GUID")) != NULL) { + // + // Read the next line if line continuation + // + LineLen = strlen (Line); + if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) { + fgets (Line + LineLen - 2, sizeof (Line) - LineLen, Fptr); + } else if (Line[LineLen - 1] == '\\') { + fgets (Line + LineLen - 1, sizeof (Line) - LineLen, Fptr); + } + + Cptr = CSavePtr + 8; + Cptr += SkipWhiteSpace (Cptr); + // + // Should be variable name next + // + Len = ValidSymbolName (Cptr); + SymName = Cptr; + Cptr += Len; + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr == '=') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr); + // + // Should be open-brace next to define guid + // + if (*Cptr == '{') { + Cptr++; + // + // 0x665E3FF6, 0x46CC, 0x11d4, 0x9A, 0x38, 0x00, 0x90, 0x27, 0x3F, 0xC1, 0x4D } + // + if (sscanf ( + Cptr, + "%X, %X, %X, %X, %X, %X, %X, %X, %X, %X, %X", + &GuidScan[0], + &GuidScan[1], + &GuidScan[2], + &GuidScan[3], + &GuidScan[4], + &GuidScan[5], + &GuidScan[6], + &GuidScan[7], + &GuidScan[8], + &GuidScan[9], + &GuidScan[10] + ) == 11) { + AddGuid11 (FileName, GuidScan, Cptr); + // + // printf ("Found guid: %s", Cptr); + // + } + } + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// Process Intel Itanium(TM) GUID definitions. Look for: +// #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA +// #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0 +// in either order. +// This function assumes no blank lines between definitions. +// +static +STATUS +ProcessIA64FileGuids ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN]; + UINT32 Guid1H; + UINT32 Guid1L; + UINT32 Guid2H; + UINT32 Guid2L; + INT8 SymName1[MAX_LINE_LEN]; + INT8 SymName2[MAX_LINE_LEN]; + BOOLEAN Done; + BOOLEAN LowFirst; + BOOLEAN FoundLow; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + + Done = FALSE; + if (fgets (Line, sizeof (Line), Fptr) == NULL) { + Done = 1; + } + // + // Read lines from the file until done. Since the guid definition takes + // two lines, we read lines in different places to recover gracefully + // from mismatches. For example, if you thought you found the first half, + // but the next line had a symbol mismatch, then you have to process the + // line again in case it's the start of a new definition. + // + while (!Done) { + // + // Check current line for GUID definition. Assume low define first. + // + if (IsIA64GuidLine (Line, &Guid1H, &Guid1L, &FoundLow, SymName1)) { + // + // Might have to swap guids later. Save off if we found the LOW first + // + if (FoundLow) { + LowFirst = TRUE; + } else { + LowFirst = FALSE; + } + // + // Read the next line and try for the rest of the guid definition + // + if (fgets (Line, sizeof (Line), Fptr) == NULL) { + Done = 1; + } else { + if (IsIA64GuidLine (Line, &Guid2H, &Guid2L, &FoundLow, SymName2)) { + // + // Found another. If the symbol names match, then save it off. + // + if (strcmp (SymName1, SymName2) == 0) { + // + // Yea, found one. Save it off. + // + if (LowFirst) { + AddGuid64x2 (FileName, Guid2H, Guid2L, Guid1H, Guid1L); + } else { + AddGuid64x2 (FileName, Guid1H, Guid1L, Guid2H, Guid2L); + } + // + // Read the next line for processing + // + if (fgets (Line, sizeof (Line), Fptr) == NULL) { + Done = 1; + } + } else { + // + // Don't get another line so that we reprocess this line in case it + // contains the start of a new definition. + // fprintf (stdout, "Symbol name mismatch: %s: %s != %s\n", + // FileName, SymName1, SymName2); + // + } + } else { + // + // Second line was not a guid definition. Get the next line from the + // file. + // + if (fgets (Line, sizeof (Line), Fptr) == NULL) { + Done = 1; + } + } + } + } else { + // + // Not a guid define line. Next. + // + if (fgets (Line, sizeof (Line), Fptr) == NULL) { + Done = 1; + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// Given a line from an Itanium-based assembly file, check the line for a guid +// defininition. One of either: +// #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA +// #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0 +// Return the defined value as two 32-bit values, and whether it's a high +// or low guid. +// +static +BOOLEAN +IsIA64GuidLine ( + INT8 *Line, + UINT32 *GuidHigh, + UINT32 *GuidLow, + BOOLEAN *FoundLow, + INT8 *SymName + ) +{ + INT8 *Cptr; + INT8 CSave; + INT8 *CSavePtr; + INT8 *SymStart; + UINT32 Len; + + Cptr = Line; + Cptr += SkipWhiteSpace (Cptr); + // + // look for #define xxxGUID[L|H] 0xHexValue + // + if (*Cptr == '#') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr); + // + // Look for "define" + // + if (!strncmp (Cptr, "define", 6)) { + Cptr += 6; + // + // Better be whitespace + // + Len = SkipWhiteSpace (Cptr); + if (Len) { + Cptr += Len; + // + // See if it's a valid symbol name + // + Len = ValidSymbolName (Cptr); + if (Len) { + // + // Save the start so we can copy it to their string if later checks are ok + // + SymStart = Cptr; + // + // It is a valid symbol name, look for the string GuidL or GuidH + // + CSavePtr = Cptr + Len; + CSave = *CSavePtr; + *CSavePtr = 0; + while (*Cptr) { + if (strncmp (Cptr, "GuidL", 5) == 0) { + *FoundLow = 1; + break; + } else if (strncmp (Cptr, "GuidH", 5) == 0) { + *FoundLow = 0; + break; + } + + Cptr++; + } + // + // If we didn't run out of string, then we found the GUID string. + // Restore the null character we inserted above and continue. + // Now look for 0x....... + // + if (*Cptr) { + // + // Return symbol name less the "L" or "H" + // + strcpy (SymName, SymStart); + SymName[strlen (SymName) - 1] = 0; + Cptr = CSavePtr; + *CSavePtr = CSave; + Cptr += SkipWhiteSpace (Cptr); + if ((*Cptr == '0') && (*(Cptr + 1) == 'x')) { + // + // skip over "0x" + // + Cptr += 2; + // + // 0x0123456789ABCDEF -- null terminate after 8 characters, + // scan, replace the character and scan at that point. + // + CSave = *(Cptr + 8); + *(Cptr + 8) = 0; + if (sscanf (Cptr, "%X", GuidHigh) == 1) { + *(Cptr + 8) = CSave; + if (sscanf (Cptr + 8, "%X", GuidLow) == 1) { + return TRUE; + } + } + } + } + } + } + } + } + + return FALSE; +} +// +// Look at the characters in the string and determine if it's a valid +// symbol name. Basically [a-zA-Z_][a-zA-Z_0-9]* +// +static +UINT32 +ValidSymbolName ( + INT8 *Name + ) +{ + int Len; + + Len = 0; + + // + // Test first character + // + if (((*Name >= 'a') && (*Name <= 'z')) || ((*Name >= 'A') && (*Name <= 'Z')) || (*Name == '_')) { + Name++; + Len = 1; + while (*Name) { + if (((*Name >= 'a') && (*Name <= 'z')) || + ((*Name >= 'A') && (*Name <= 'Z')) || + ((*Name >= '0') && (*Name <= '9')) || + (*Name == '_') + ) { + Name++; + Len++; + } else { + break; + } + } + } + + return Len; +} + +static +UINT32 +SkipWhiteSpace ( + INT8 *Str + ) +{ + UINT32 Len; + Len = 0; + while (isspace (*Str) && *Str) { + Len++; + Str++; + } + + return Len; +} +// +// found FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7 +// +static +STATUS +AddPkgGuid ( + INT8 *FileName, + UINT32 *Data, + UINT64 *Data64 + ) +{ + GUID_RECORD *NewRec; + int Index; + + // + // Sanity check the data + // + if ((Data[1] | Data[2] | Data[3]) & 0xFFFF0000) { + Error (NULL, 0, 0, "out of range value for GUID data word(s) [1] - [3]", NULL); + return STATUS_ERROR; + } + // + // More checks for Data64? + // Allocate memory for a new one guid structure + // + NewRec = malloc (sizeof (GUID_RECORD)); + if (NewRec == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) NewRec, 0, sizeof (GUID_RECORD)); + NewRec->FileName = malloc (strlen (FileName) + 1); + if (NewRec->FileName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewRec->FileName, FileName); + NewRec->Guid.Data1 = Data[0]; + NewRec->Guid.Data2 = (UINT16) Data[1]; + NewRec->Guid.Data3 = (UINT16) Data[2]; + NewRec->Guid.Data4[0] = (UINT8) Data[3]; + NewRec->Guid.Data4[1] = (UINT8) (Data[3] >> 8); + for (Index = 2; Index < 8; Index++) { + NewRec->Guid.Data4[Index] = (UINT8) *Data64; + *Data64 >>= 8; + } + // + // Add it to the list + // + NewRec->Next = gGuidList; + gGuidList = NewRec; + + // + // Report it + // ReportGuid (FileName, NewRec); + // + return STATUS_SUCCESS; +} +// +// Add a guid consisting of 11 fields to our list of guids +// +static +STATUS +AddGuid11 ( + INT8 *FileName, + UINT32 *Data, + INT8 *SymName + ) +{ + GUID_RECORD *NewRec; + int Index; + + // + // Sanity check the data + // + if (!CheckGuidData (Data, 11)) { + return STATUS_ERROR; + } + // + // Allocate memory for a new one guid structure + // + NewRec = malloc (sizeof (GUID_RECORD)); + if (NewRec == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) NewRec, 0, sizeof (GUID_RECORD)); + NewRec->FileName = malloc (strlen (FileName) + 1); + if (NewRec->FileName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewRec->FileName, FileName); + if (SymName != NULL) { + NewRec->SymName = malloc (strlen (SymName) + 1); + if (NewRec->SymName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + } + + strcpy (NewRec->SymName, SymName); + + NewRec->Guid.Data1 = Data[0]; + NewRec->Guid.Data2 = (UINT16) Data[1]; + NewRec->Guid.Data3 = (UINT16) Data[2]; + for (Index = 0; Index < 8; Index++) { + NewRec->Guid.Data4[Index] = (UINT8) Data[3 + Index]; + } + // + // Add it to the list + // + NewRec->Next = gGuidList; + gGuidList = NewRec; + + // + // Report it + // ReportGuid (FileName, NewRec); + // + return STATUS_SUCCESS; +} +// +// For debug purposes, print each guid found +// +// static +// VOID +// ReportGuid ( +// INT8 *FileName, +// GUID_RECORD *NewGuid +// ) +// { +// //fprintf (stdout, "%s: 0x%08X\n", FileName, NewGuid->Guid.Data1); +// } +// +// Free up memory we allocated to keep track of guids defined. +// +static +VOID +FreeGuids ( + VOID + ) +{ + GUID_RECORD *NextRec; + while (gGuidList != NULL) { + NextRec = gGuidList->Next; + if (gGuidList->FileName != NULL) { + free (gGuidList->FileName); + } + + if (gGuidList->SymName != NULL) { + free (gGuidList->SymName); + } + + free (gGuidList); + gGuidList = NextRec; + } +} + +static +VOID +FreeSigs ( + VOID + ) +{ + SIGNATURE_RECORD *NextRec; + while (gSignatureList != NULL) { + NextRec = gSignatureList->Next; + if (gSignatureList->FileName != NULL) { + free (gSignatureList->FileName); + } + + free (gSignatureList); + gSignatureList = NextRec; + } +} +// +// Scan through all guids defined and compare each for duplicates. +// +static +STATUS +CheckDuplicates ( + VOID + ) +{ + GUID_RECORD *CurrentFile; + + GUID_RECORD *TempFile; + SIGNATURE_RECORD *CurrentSig; + SIGNATURE_RECORD *TempSig; + STATUS Status; + int Index; + int DupCount; + int Len; + BOOLEAN Same; + UINT32 GuidSum; + INT8 *SymName; + + Status = STATUS_SUCCESS; + + // + // If we're checking guids..... + // + if (gOptions.CheckGuids) { + // + // If -p option, print all guids found + // + if (gOptions.PrintFound) { + CurrentFile = gGuidList; + while (CurrentFile != NULL) { + fprintf ( + stdout, + "GUID: 0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X %s\n", + (UINT32) CurrentFile->Guid.Data1, + (UINT32) CurrentFile->Guid.Data2, + (UINT32) CurrentFile->Guid.Data3, + (UINT32) CurrentFile->Guid.Data4[0], + (UINT32) CurrentFile->Guid.Data4[1], + (UINT32) CurrentFile->Guid.Data4[2], + (UINT32) CurrentFile->Guid.Data4[3], + (UINT32) CurrentFile->Guid.Data4[4], + (UINT32) CurrentFile->Guid.Data4[5], + (UINT32) CurrentFile->Guid.Data4[6], + (UINT32) CurrentFile->Guid.Data4[7], + CurrentFile->FileName + ); + CurrentFile = CurrentFile->Next; + } + } + + if (gOptions.GuidXReference) { + CurrentFile = gGuidList; + while (CurrentFile != NULL) { + // + // If no symbol name, print "unknown" + // + SymName = CurrentFile->SymName; + if (SymName == NULL) { + SymName = "unknown"; + } + + fprintf ( + stdout, + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s\n", + (UINT32) CurrentFile->Guid.Data1, + (UINT32) CurrentFile->Guid.Data2, + (UINT32) CurrentFile->Guid.Data3, + (UINT32) CurrentFile->Guid.Data4[0], + (UINT32) CurrentFile->Guid.Data4[1], + (UINT32) CurrentFile->Guid.Data4[2], + (UINT32) CurrentFile->Guid.Data4[3], + (UINT32) CurrentFile->Guid.Data4[4], + (UINT32) CurrentFile->Guid.Data4[5], + (UINT32) CurrentFile->Guid.Data4[6], + (UINT32) CurrentFile->Guid.Data4[7], + SymName + ); + CurrentFile = CurrentFile->Next; + } + } + // + // Now go through all guids and report duplicates. + // + CurrentFile = gGuidList; + while (CurrentFile != NULL) { + DupCount = 0; + TempFile = CurrentFile->Next; + while (TempFile) { + // + // Compare the guids + // + if ((CurrentFile->Guid.Data1 == TempFile->Guid.Data1) && + (CurrentFile->Guid.Data2 == TempFile->Guid.Data2) && + (CurrentFile->Guid.Data3 == TempFile->Guid.Data3) + ) { + // + // OR in all the guid bytes so we can ignore NULL-guid definitions. + // + GuidSum = CurrentFile->Guid.Data1 | CurrentFile->Guid.Data2 | CurrentFile->Guid.Data3; + Same = TRUE; + for (Index = 0; Index < 8; Index++) { + GuidSum |= CurrentFile->Guid.Data4[Index]; + if (CurrentFile->Guid.Data4[Index] != TempFile->Guid.Data4[Index]) { + Same = FALSE; + break; + } + } + // + // If they're the same, and the guid was non-zero, print a message. + // + if (Same && GuidSum) { + if (DupCount == 0) { + Error (NULL, 0, 0, "duplicate GUIDS found", NULL); + fprintf (stdout, " FILE1: %s\n", CurrentFile->FileName); + } + + DupCount++; + fprintf (stdout, " FILE%d: %s\n", DupCount + 1, TempFile->FileName); + // + // Flag it as reported so we don't report it again if there's three or more + // + TempFile->Reported = TRUE; + } + } + // + // Next one + // + TempFile = TempFile->Next; + } + // + // Print the guid if we found duplicates + // + if (DupCount) { + fprintf ( + stdout, + " GUID: 0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", + (UINT32) CurrentFile->Guid.Data1, + (UINT32) CurrentFile->Guid.Data2, + (UINT32) CurrentFile->Guid.Data3, + (UINT32) CurrentFile->Guid.Data4[0], + (UINT32) CurrentFile->Guid.Data4[1], + (UINT32) CurrentFile->Guid.Data4[2], + (UINT32) CurrentFile->Guid.Data4[3], + (UINT32) CurrentFile->Guid.Data4[4], + (UINT32) CurrentFile->Guid.Data4[5], + (UINT32) CurrentFile->Guid.Data4[6], + (UINT32) CurrentFile->Guid.Data4[7] + ); + // + // return STATUS_ERROR; + // + } + // + // Find the next one that hasn't been reported + // + do { + CurrentFile = CurrentFile->Next; + } while ((CurrentFile != NULL) && (CurrentFile->Reported)); + } + } + + if (gOptions.CheckSignatures) { + // + // Print ones found if specified + // + if (gOptions.PrintFound) { + CurrentSig = gSignatureList; + while (CurrentSig != NULL) { + Len = CurrentSig->Signature.DataLen; + for (Index = 0; Index < Len; Index++) { + fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]); + } + + fprintf (stdout, " %s\n", CurrentSig->FileName); + CurrentSig = CurrentSig->Next; + } + } + + CurrentSig = gSignatureList; + while (CurrentSig != NULL) { + DupCount = 0; + TempSig = CurrentSig->Next; + Len = CurrentSig->Signature.DataLen; + while (TempSig) { + // + // Check for same length, then do string compare + // + if (Len == TempSig->Signature.DataLen) { + if (strncmp (CurrentSig->Signature.Data, TempSig->Signature.Data, Len) == 0) { + // + // Print header message if first failure for this sig + // + if (DupCount == 0) { + Error (NULL, 0, 0, "duplicate signatures found", NULL); + fprintf (stdout, " FILE1: %s\n", CurrentSig->FileName); + } + + DupCount++; + fprintf (stdout, " FILE%d: %s\n", DupCount + 1, TempSig->FileName); + TempSig->Reported = TRUE; + } + } + + TempSig = TempSig->Next; + } + + if (DupCount) { + fprintf (stdout, " SIG: "); + for (Index = 0; Index < Len; Index++) { + fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]); + } + + fprintf (stdout, "\n"); + } + // + // On to the next one that hasn't been reported + // + do { + CurrentSig = CurrentSig->Next; + } while ((CurrentSig != NULL) && (CurrentSig->Reported)); + } + } + + return Status; +} + +static +VOID +FreeOptions ( + VOID + ) +/*++ + +Routine Description: + Free up any memory we allocated when processing command-line options. + +Arguments: + None. + +Returns: + NA + +Notes: + We don't free up the ->Str fields because we did not allocate them. + Instead, we just set the pointer to point to the actual parameter + from the command line. + +--*/ +{ + STRING_LIST *Ptr; + while (gOptions.ExcludeDirs != NULL) { + Ptr = gOptions.ExcludeDirs->Next; + // + // free (gOptions.ExcludeDirs->Str); + // + free (gOptions.ExcludeDirs); + gOptions.ExcludeDirs = Ptr; + } + + while (gOptions.ExcludeSubDirs != NULL) { + Ptr = gOptions.ExcludeSubDirs->Next; + // + // free (gOptions.ExcludeSubDirs->Str); + // + free (gOptions.ExcludeSubDirs); + gOptions.ExcludeSubDirs = Ptr; + } + + while (gOptions.ExcludeExtensions != NULL) { + Ptr = gOptions.ExcludeExtensions->Next; + // + // free (gOptions.ExcludeExtensions->Str); + // + free (gOptions.ExcludeExtensions); + gOptions.ExcludeExtensions = Ptr; + } + + while (gOptions.ExcludeFiles != NULL) { + Ptr = gOptions.ExcludeFiles->Next; + // + // free (gOptions.ExcludeFiles->Str); + // + free (gOptions.ExcludeFiles); + gOptions.ExcludeFiles = Ptr; + } +} +// +// Given an array of 32-bit data, validate the data for the given number of +// guid data. For example, it might have been scanned as 16 bytes of data, or +// 11 fields of data. +// +static +BOOLEAN +CheckGuidData ( + UINT32 *Data, + UINT32 DataCount + ) +{ + UINT32 Index; + + if (DataCount == 16) { + for (Index = 0; Index < 16; Index++) { + if (Data[Index] &~0xFF) { + return FALSE; + } + } + + return TRUE; + } else if (DataCount == 11) { + // + // Data[0] never out of range (32-bit) + // + if ((Data[1] | Data[2]) &~0xFFFF) { + // + // Error ("Out of range value for GUID data word(s) [1] and/or [2]"); + // + return FALSE; + } + + for (Index = 0; Index < 8; Index++) { + if (Data[Index + 3] &~0xFF) { + // + // Error ("Out of range value for GUID data byte(s) [4] - [11]"); + // + return FALSE; + } + } + + return TRUE; + } + + return FALSE; +} diff --git a/Tools/Source/TianoTools/GuidChk/GuidList.c b/Tools/Source/TianoTools/GuidChk/GuidList.c new file mode 100644 index 0000000000..0e8afde72c --- /dev/null +++ b/Tools/Source/TianoTools/GuidChk/GuidList.c @@ -0,0 +1,188 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + GuidList.c + +Abstract: + + Utility to create a GUID-to-name listing file that can + be used by other utilities. Basic operation is to take the + table of name+GUIDs that we have compiled into this utility, + and create a text file that can be parsed by other utilities + to do replacement of "name" with "GUID". + +Notes: + To add a new GUID to this database: + 1. Add a "#include EFI_GUID_DEFINITION(name)" statement below + 2. Modify the mGuidList[] array below to add the new GUID name + + The only issue that may come up is that, if the source GUID file + is not in the standard GUID directory, then this utility won't + compile because the #include fails. In this case you'd need + to define a new macro (if it's in a standard place) or modify + this utility's makefile to add the path to your new .h file. + +--*/ + +#include +#include +#include +#include + +#include +#include +#include +#include "EfiUtilityMsgs.h" + +#include +#include +// #include + +#define GUID_XREF(varname, guid) { \ + #varname, #guid, guid \ + } + +#define NULL_GUID \ + { \ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 \ + } + +typedef struct { + INT8 *VariableName; + INT8 *DefineName; + EFI_GUID Guid; +} GUID_LIST; + +// +// This is our table of all GUIDs we want to print out to create +// a GUID-to-name cross reference. +// Use the #defined name from the GUID definition's source .h file. +// +static GUID_LIST mGuidList[] = { + GUID_XREF(gAprioriGuid, EFI_APRIORI_GUID), + GUID_XREF(gEfiAcpiTableStorageGuid, EFI_ACPI_TABLE_STORAGE_GUID), + // FIXME The next line was removed in the port to R9. + // GUID_XREF(gEfiDefaultBmpLogoGuid, EFI_DEFAULT_BMP_LOGO_GUID), + GUID_XREF(gEfiAcpiTableStorageGuid, EFI_ACPI_TABLE_STORAGE_GUID), + // + // Terminator + // + { + NULL, + NULL, + NULL_GUID + } +}; + +void +PrintGuidText ( + FILE *OutFptr, + INT8 *VariableName, + INT8 *DefineName, + EFI_GUID *Guid + ); + +int +CreateGuidList ( + INT8 *OutFileName + ) +/*++ + +Routine Description: + Print our GUID/name list to the specified output file. + +Arguments: + OutFileName - name of the output file to write our results to. + +Returns: + 0 if successful + nonzero otherwise + +--*/ +{ + FILE *OutFptr; + int Index; + + // + // Open output file for writing. If the name is NULL, then write to stdout + // + if (OutFileName != NULL) { + OutFptr = fopen (OutFileName, "w"); + if (OutFptr == NULL) { + Error (NULL, 0, 0, OutFileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + } else { + OutFptr = stdout; + } + + for (Index = 0; mGuidList[Index].VariableName != NULL; Index++) { + PrintGuidText (OutFptr, mGuidList[Index].VariableName, mGuidList[Index].DefineName, &mGuidList[Index].Guid); + } + // + // Close the output file if they specified one. + // + if (OutFileName != NULL) { + fclose (OutFptr); + } + + return STATUS_SUCCESS; +} + +void +PrintGuidText ( + FILE *OutFptr, + INT8 *VariableName, + INT8 *DefineName, + EFI_GUID *Guid + ) +/*++ + +Routine Description: + Print a GUID/name combo in INF-style format + + guid-guid-guid-guid DEFINE_NAME gName + +Arguments: + OutFptr - file pointer to which to write the output + VariableName - the GUID variable's name + DefineName - the name used in the #define + Guid - pointer to the GUID value + +Returns: + NA + +--*/ +{ + if (OutFptr == NULL) { + OutFptr = stdout; + } + + fprintf ( + OutFptr, + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s %s\n", + Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7], + DefineName, + VariableName + ); +} diff --git a/Tools/Source/TianoTools/GuidChk/UtilsMsgs.c b/Tools/Source/TianoTools/GuidChk/UtilsMsgs.c new file mode 100644 index 0000000000..b9fcab0f72 --- /dev/null +++ b/Tools/Source/TianoTools/GuidChk/UtilsMsgs.c @@ -0,0 +1,490 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + UtilsMsgs.c + +Abstract: + + EFI tools utility functions to display warning, error, and informational + messages. + +--*/ + +#include +#include +#include +#include + +#include +#include +#include "EfiUtilityMsgs.h" + +#define MAX_LINE_LEN 200 + +// +// Declare module globals for keeping track of the the utility's +// name and other settings. +// +static STATUS mStatus = STATUS_SUCCESS; +static INT8 mUtilityName[50] = { 0 }; +static INT8 *mSourceFileName = NULL; +static UINT32 mSourceFileLineNum = 0; +static UINT32 mErrorCount = 0; +static UINT32 mWarningCount = 0; +static UINT32 mDebugMsgMask = 0; + +static +void +PrintMessage ( + INT8 *Type, + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *MsgFmt, + va_list List + ); + +void +Error ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Prints an error message. + +Arguments: + All arguments are optional, though the printed message may be useless if + at least something valid is not specified. + + FileName - name of the file or application. If not specified, then the + utilty name (as set by the utility calling SetUtilityName() + earlier) is used. Otherwise "Unknown utility" is used. + + LineNumber - the line number of error, typically used by parsers. If the + utility is not a parser, then 0 should be specified. Otherwise + the FileName and LineNumber info can be used to cause + MS Visual Studio to jump to the error. + + MessageCode - an application-specific error code that can be referenced in + other documentation. + + Text - the text in question, typically used by parsers. + + MsgFmt - the format string for the error message. Can contain formatting + controls for use with the varargs. + +Returns: + None. + +Notes: + We print the following (similar to the Warn() and Debug() + W + Typical error/warning message format: + + bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters + + BUGBUG -- these three utility functions are almost identical, and + should be modified to share code. + + Visual Studio does not find error messages with: + + " error :" + " error 1:" + " error c1:" + " error 1000:" + " error c100:" + + It does find: + " error c1000:" +--*/ +{ + va_list List; + mErrorCount++; + va_start (List, MsgFmt); + PrintMessage ("error", FileName, LineNumber, MessageCode, Text, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_ERROR) { + mStatus = STATUS_ERROR; + } +} + +void +ParserError ( + UINT32 MessageCode, + INT8 *Text, + INT8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a parser error, using the source file name and line number + set by a previous call to SetParserPosition(). + +Arguments: + MessageCode - application-specific error code + Text - text to print in the error message + MsgFmt - format string to print at the end of the error message + ... + +Returns: + NA + +--*/ +{ + va_list List; + mErrorCount++; + va_start (List, MsgFmt); + PrintMessage ("error", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_ERROR) { + mStatus = STATUS_ERROR; + } +} + +void +ParserWarning ( + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a parser warning, using the source file name and line number + set by a previous call to SetParserPosition(). + +Arguments: + ErrorCode - application-specific error code + OffendingText - text to print in the warning message + MsgFmt - format string to print at the end of the warning message + ... + +Returns: + NA + +--*/ +{ + va_list List; + mWarningCount++; + va_start (List, MsgFmt); + PrintMessage ("warning", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_WARNING) { + mStatus = STATUS_WARNING; + } +} + +void +Warning ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a warning message. + +Arguments: + FileName - name of the file where the warning was detected, or the name + of the application that detected the warning + + LineNumber - the line number where the warning was detected (parsers). + 0 should be specified if the utility is not a parser. + + MessageCode - an application-specific warning code that can be referenced in + other documentation. + + Text - the text in question (parsers) + + MsgFmt - the format string for the warning message. Can contain formatting + controls for use with varargs. + + ... + +Returns: + None. + +--*/ +{ + va_list List; + mWarningCount++; + va_start (List, MsgFmt); + PrintMessage ("warning", FileName, LineNumber, MessageCode, Text, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_WARNING) { + mStatus = STATUS_WARNING; + } +} + +void +DebugMsg ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MsgMask, + INT8 *Text, + INT8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a warning message. + +Arguments: + FileName - typically the name of the utility printing the debug message, but + can be the name of a file being parsed. + + LineNumber - the line number in FileName (parsers) + + MsgMask - an application-specific bitmask that, in combination with mDebugMsgMask, + determines if the debug message gets printed. + + Text - the text in question (parsers) + + MsgFmt - the format string for the debug message. Can contain formatting + controls for use with varargs. + + ... +Returns: + None. + +--*/ +{ + va_list List; + // + // If the debug mask is not applicable, then do nothing. + // + if ((MsgMask != 0) && ((mDebugMsgMask & MsgMask) == 0)) { + return ; + } + + va_start (List, MsgFmt); + PrintMessage ("debug", FileName, LineNumber, 0, Text, MsgFmt, List); + va_end (List); +} + +static +void +PrintMessage ( + INT8 *Type, + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *MsgFmt, + va_list List + ) +/*++ + +Routine Description: + Worker routine for all the utility printing services. Prints the message in + a format that Visual Studio will find when scanning build outputs for + errors or warnings. + +Arguments: + Type - "warning" or "error" string to insert into the message to be + printed. The first character of this string (converted to uppercase) + is used to preceed the MessageCode value in the output string. + + FileName - name of the file where the warning was detected, or the name + of the application that detected the warning + + LineNumber - the line number where the warning was detected (parsers). + 0 should be specified if the utility is not a parser. + + MessageCode - an application-specific warning code that can be referenced in + other documentation. + + Text - part of the message to print + + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + + List - Variable function parameter list. +Returns: + None. + +Notes: + If FileName == NULL then this utility will use the string passed into SetUtilityName(). + + LineNumber is only used if the caller is a parser, in which case FileName refers to the + file being parsed. + + Text and MsgFmt are both optional, though it would be of little use calling this function with + them both NULL. + + Output will typically be of the form: + () : : : + + Parser (LineNumber != 0) + VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters + Generic utility (LineNumber == 0) + UtilityName : error E1234 : Text string : MsgFmt string and args + +--*/ +{ + INT8 Line[MAX_LINE_LEN]; + INT8 Line2[MAX_LINE_LEN]; + INT8 *Cptr; + // + // If given a filename, then add it (and the line number) to the string. + // If there's no filename, then use the program name if provided. + // + if (FileName != NULL) { + Cptr = FileName; + } else if (mUtilityName[0] != 0) { + Cptr = mUtilityName; + } else { + Cptr = "Unknown utility"; + } + + strcpy (Line, Cptr); + if (LineNumber != 0) { + sprintf (Line2, "(%d)", LineNumber); + strcat (Line, Line2); + } + // + // Have to print an error code or Visual Studio won't find the + // message for you. It has to be decimal digits too. + // + sprintf (Line2, " : %s %c%04d", Type, toupper (Type[0]), MessageCode); + strcat (Line, Line2); + fprintf (stdout, "%s", Line); + // + // If offending text was provided, then print it + // + if (Text != NULL) { + fprintf (stdout, ": %s ", Text); + } + // + // Print formatted message if provided + // + if (MsgFmt != NULL) { + vsprintf (Line2, MsgFmt, List); + fprintf (stdout, ": %s", Line2); + } + + fprintf (stdout, "\n"); +} + +void +ParserSetPosition ( + INT8 *SourceFileName, + UINT32 LineNum + ) +/*++ + +Routine Description: + Set the position in a file being parsed. This can be used to + print error messages deeper down in a parser. + +Arguments: + SourceFileName - name of the source file being parsed + LineNum - line number of the source file being parsed + +Returns: + NA + +--*/ +{ + mSourceFileName = SourceFileName; + mSourceFileLineNum = LineNum; +} + +void +SetUtilityName ( + INT8 *UtilityName + ) +/*++ + +Routine Description: + All printed error/warning/debug messages follow the same format, and + typically will print a filename or utility name followed by the error + text. However if a filename is not passed to the print routines, then + they'll print the utility name if you call this function early in your + app to set the utility name. + +Arguments: + UtilityName - name of the utility, which will be printed with all + error/warning/debug messags. + +Returns: + NA + +--*/ +{ + // + // Save the name of the utility in our local variable. Make sure its + // length does not exceed our buffer. + // + if (UtilityName != NULL) { + if (strlen (UtilityName) >= sizeof (mUtilityName)) { + Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size"); + strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1); + mUtilityName[sizeof (mUtilityName) - 1] = 0; + return ; + } else { + strcpy (mUtilityName, UtilityName); + } + } else { + Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name"); + } +} + +STATUS +GetUtilityStatus ( + VOID + ) +/*++ + +Routine Description: + When you call Error() or Warning(), this module keeps track of it and + sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility + exits, it can call this function to get the status and use it as a return + value. + +Arguments: + None. + +Returns: + Worst-case status reported, as defined by which print function was called. + +--*/ +{ + return mStatus; +} diff --git a/Tools/Source/TianoTools/GuidChk/UtilsMsgs.h b/Tools/Source/TianoTools/GuidChk/UtilsMsgs.h new file mode 100644 index 0000000000..5f6c7010b4 --- /dev/null +++ b/Tools/Source/TianoTools/GuidChk/UtilsMsgs.h @@ -0,0 +1,106 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + UtilsMsgs.h + +Abstract: + + Prototypes for the EFI tools utility functions. + +--*/ + +#ifndef _UTILS_MESSAGES_H_ +#define _UTILS_MESSAGES_H_ + +STATUS +GetUtilityStatus ( + VOID + ) +; + +// +// If someone prints an error message and didn't specify a source file name, +// then we print the utility name instead. However they must tell us the +// utility name early on via this function. +// +VOID +SetUtilityName ( + INT8 *ProgramName + ) +; + +void +Error ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +Warning ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +DebugMsg ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MsgLevel, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +SetDebugMsgMask ( + UINT32 MsgMask + ) +; + +void +ParserSetPosition ( + INT8 *SourceFileName, + UINT32 LineNum + ) +; + +void +ParserError ( + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +ParserWarning ( + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +#endif diff --git a/Tools/Source/TianoTools/GuidChk/build.gcc b/Tools/Source/TianoTools/GuidChk/build.gcc new file mode 100644 index 0000000000..0d56b6bf2b --- /dev/null +++ b/Tools/Source/TianoTools/GuidChk/build.gcc @@ -0,0 +1 @@ +gcc -mno-cygwin -I../Common/ -I/workspace/mdk/MdePkg/Include/Guid -I/workspace/mdk/MdePkg/Include/Protocol/ -I/workspace/mdk/MdePkg/Include/Common/ -I/workspace/mdk/MdePkg/Include/ -I/workspace/mdk/MdePkg/Include/Ia32 -I. GuidChk.c GuidList.c UtilsMsgs.c -o GuidChk.exe diff --git a/Tools/Source/TianoTools/GuidChk/build.xml b/Tools/Source/TianoTools/GuidChk/build.xml new file mode 100644 index 0000000000..f131f79369 --- /dev/null +++ b/Tools/Source/TianoTools/GuidChk/build.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/Pccts/CHANGES_FROM_131.txt b/Tools/Source/TianoTools/Pccts/CHANGES_FROM_131.txt new file mode 100644 index 0000000000..500d84f2e8 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/CHANGES_FROM_131.txt @@ -0,0 +1,522 @@ +CHANGES FROM 1.31 + +This file contains the migration of PCCTS from 1.31 in the order that +changes were made. 1.32b7 is the last beta before full 1.32. +Terence Parr, Parr Research Corporation 1995. + + +====================================================================== +1.32b1 +Added Russell Quong to banner, changed banner for output slightly +Fixed it so that you have before / after actions for C++ in class def +Fixed bug in optimizer that made it sometimes forget to set internal + token pointers. Only showed up when a {...} was in the "wrong spot". + +====================================================================== +1.32b2 +Added fixes by Dave Seidel for PC compilers in 32 bit mode (config.h +and set.h). + +====================================================================== +1.32b3 +Fixed hideous bug in code generator for wildcard and for ~token op. + +from Dave Seidel + + Added pcnames.bat + 1. in antlr/main.c: change strcasecmp() to stricmp() + + 2. in dlg/output.c: use DLEXER_C instead on "DLexer.C" + + 3. in h/PBlackBox.h: use instead of + +====================================================================== +1.32b4 +When the -ft option was used, any path prefix screwed up +the gate on the .h files + +Fixed yet another bug due to the optimizer. + +The exception handling thing was a bit wacko: + +a : ( A B )? A B + | A C + ; + exception ... + +caused an exception if "A C" was the input. In other words, +it found that A C didn't match the (A B)? pred and caused +an exception rather than trying the next alt. All I did +was to change the zzmatch_wsig() macros. + +Fixed some problems in gen.c relating to the name of token +class bit sets in the output. + +Added the tremendously cool generalized predicate. For the +moment, I'll give this bried description. + +a : <>? blah + | foo + ; + +This implies that (assuming blah and foo are syntactically +ambiguous) "predicate" indicates the semantic validity of +applying "blah". If "predicate" is false, "foo" is attempted. + +Previously, you had to say: + +a : <>? ID + | ID + ; + +Now, you can simply use "predicate" without the ?: operator +if you turn on ANTLR command line option: "-prc on". This +tells ANTLR to compute that all by itself. It computes n +tokens of lookahead where LT(n) or LATEXT(n) is the farthest +ahead you look. + +If you give a predicate using "-prc on" that is followed +by a construct that can recognize more than one n-sequence, +you will get a warning from ANTLR. For example, + +a : <getText())>>? (ID|INT) + ; + +This is wrong because the predicate will be applied to INTs +as well as ID's. You should use this syntax to make +the predicate more specific: + +a : (ID)? => <getText())>>? (ID|INT) + ; + +which says "don't apply the predicate unless ID is the +current lookahead context". + +You cannot currently have anything in the "(context)? =>" +except sequences such as: + +( LPAREN ID | LPAREN SCOPE )? => <>? + +I haven't tested this THAT much, but it does work for the +C++ grammar. + +====================================================================== +1.32b5 + +Added getLine() to the ANTLRTokenBase and DLGBasedToken classes +left line() for backward compatibility. +---- +Removed SORCERER_TRANSFORM from the ast.h stuff. +------- +Fixed bug in code gen of ANTLR such that nested syn preds work more +efficiently now. The ANTLRTokenBuffer was getting very large +with nested predicates. +------ +Memory leak is now gone from ANTLRTokenBuf; all tokens are deleted. +For backward compatibility reasons, you have to say parser->deleteTokens() +or mytokenbuffer->deleteTokens() but later it will be the default mode. +Say this after the parser is constructed. E.g., + + ParserBlackBox p(stdin); + p.parser()->deleteTokens(); + p.parser()->start_symbol(); + + +============================== +1.32b6 + +Changed so that deleteTokens() will do a delete ((ANTLRTokenBase *)) +on the ptr. This gets the virtual destructor. + +Fixed some weird things in the C++ header files (a few return types). + +Made the AST routines correspond to the book and SORCERER stuff. + +New token stuff: See testcpp/14/test.g + +ANTLR accepts a #pragma gc_tokens which says +[1] Generate label = copy(LT(1)) instead of label=LT(1) for + all labeled token references. +[2] User now has to define ANTLRTokenPtr (as a class or a typedef + to just a pointer) as well as the ANTLRToken class itself. + See the example. + +To delete tokens in token buffer, use deleteTokens() message on parser. + + All tokens that fall off the ANTLRTokenBuffer get deleted + which is what currently happens when deleteTokens() message + has been sent to token buffer. + +We always generate ANTLRTokenPtr instead of 'ANTLRToken *' now. +Then if no pragma set, ANTLR generates a + + class ANTLRToken; + typedef ANTLRToken *ANTLRTokenPtr; + +in each file. + +Made a warning for x:rule_ref <<$x>>; still no warning for $i's, however. +class BB { + +a : x:b y:A <<$x +$y>> + ; + +b : B; + +} +generates +Antlr parser generator Version 1.32b6 1989-1995 +test.g, line 3: error: There are no token ptrs for rule references: '$x' + +=================== +1.32b7: + +[With respect to token object garbage collection (GC), 1.32b7 + backtracks from 1.32b6, but results in better and less intrusive GC. + This is the last beta version before full 1.32.] + +BIGGEST CHANGES: + +o The "#pragma gc_tokens" is no longer used. + +o .C files are now .cpp files (hence, makefiles will have to + be changed; or you can rerun genmk). This is a good move, + but causes some backward incompatibility problems. You can + avoid this by changing CPP_FILE_SUFFIX to ".C" in pccts/h/config.h. + +o The token object class hierarchy has been flattened to include + only three classes: ANTLRAbstractToken, ANTLRCommonToken, and + ANTLRCommonNoRefCountToken. The common token now does garbage + collection via ref counting. + +o "Smart" pointers are now used for garbage collection. That is, + ANTLRTokenPtr is used instead of "ANTLRToken *". + +o The antlr.1 man page has been cleaned up slightly. + +o The SUN C++ compiler now complains less about C++ support code. + +o Grammars which subclass ANTLRCommonToken must wrap all token + pointer references in mytoken(token_ptr). This is the only + serious backward incompatibility. See below. + + +MINOR CHANGES: + +-------------------------------------------------------- +1 deleteTokens() + +The deleteTokens() message to the parser or token buffer has been changed +to one of: + + void noGarbageCollectTokens() { inputTokens->noGarbageCollectTokens(); } + void garbageCollectTokens() { inputTokens->garbageCollectTokens(); } + +The token buffer deletes all non-referenced tokens by default now. + +-------------------------------------------------------- +2 makeToken() + +The makeToken() message returns a new type. The function should look +like: + + virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt, + ANTLRChar *txt, + int line) + { + ANTLRAbstractToken *t = new ANTLRCommonToken(tt,txt); + t->setLine(line); + return t; + } + +-------------------------------------------------------- +3 TokenType + +Changed TokenType-> ANTLRTokenType (often forces changes in AST defs due +to #[] constructor called to AST(tokentype, string)). + +-------------------------------------------------------- +4 AST() + +You must define AST(ANTLRTokenPtr t) now in your AST class definition. +You might also have to include ATokPtr.h above the definition; e.g., +if AST is defined in a separate file, such as AST.h, it's a good idea +to include ATOKPTR_H (ATokPtr.h). For example, + + #include ATOKPTR_H + class AST : public ASTBase { + protected: + ANTLRTokenPtr token; + public: + AST(ANTLRTokenPtr t) { token = t; } + void preorder_action() { + char *s = token->getText(); + printf(" %s", s); + } + }; + +Note the use of smart pointers rather than "ANTLRToken *". + +-------------------------------------------------------- +5 SUN C++ + +From robertb oakhill.sps.mot.com Bob Bailey. Changed ANTLR C++ output +to avoid an error in Sun C++ 3.0.1. Made "public" return value +structs created to hold multiple return values public. + +-------------------------------------------------------- +6 genmk + +Fixed genmk so that target List.* is not included anymore. It's +called SList.* anyway. + +-------------------------------------------------------- +7 \r vs \n + +Scott Vorthmann fixed antlr.g in ANTLR so that \r +is allowed as the return character as well as \n. + +-------------------------------------------------------- +8 Exceptions + +Bug in exceptions attached to labeled token/tokclass references. Didn't gen +code for exceptions. This didn't work: + +a : "help" x:ID + ; + exception[x] + catch MismatchedToken : <> + +Now ANTLR generates (which is kinda big, but necessary): + + if ( !_match_wsig(ID) ) { + if ( guessing ) goto fail; + _signal=MismatchedToken; + switch ( _signal ) { + case MismatchedToken : + printf("eh?\n"); + _signal = NoSignal; + break; + default : + goto _handler; + } + } + +which implies that you can recover and continue parsing after a missing/bad +token reference. + +-------------------------------------------------------- +9 genmk + +genmk now correctly uses config file for CPP_FILE_SUFFIX stuff. + +-------------------------------------------------------- +10 general cleanup / PURIFY + +Anthony Green suggested a bunch of good general +clean up things for the code; he also suggested a few things to +help out the "PURIFY" memory allocation checker. + +-------------------------------------------------------- +11 $-variable references. + +Manuel ORNATO indicated that a $-variable outside of a rule caused +ANTLR to crash. I fixed this. + +12 Tom Moog suggestion + +Fail action of semantic predicate needs "{}" envelope. FIXED. + +13 references to LT(1). + +I have enclosed all assignments such as: + + _t22 = (ANTLRTokenPtr)LT(1); + +in "if ( !guessing )" so that during backtracking the reference count +for token objects is not increased. + + +TOKEN OBJECT GARBAGE COLLECTION + +1 INTRODUCTION + +The class ANTLRCommonToken is now garbaged collected through a "smart" +pointer called ANTLRTokenPtr using reference counting. Any token +object not referenced by your grammar actions is destroyed by the +ANTLRTokenBuffer when it must make room for more token objects. +Referenced tokens are then destroyed in your parser when local +ANTLRTokenPtr objects are deleted. For example, + +a : label:ID ; + +would be converted to something like: + +void yourclass::a(void) +{ + zzRULE; + ANTLRTokenPtr label=NULL; // used to be ANTLRToken *label; + zzmatch(ID); + label = (ANTLRTokenPtr)LT(1); + consume(); + ... +} + +When the "label" object is destroyed (it's just a pointer to your +input token object LT(1)), it decrements the reference count on the +object created for the ID. If the count goes to zero, the object +pointed by label is deleted. + +To correctly manage the garbage collection, you should use +ANTLRTokenPtr instead of "ANTLRToken *". Most ANTLR support code +(visible to the user) has been modified to use the smart pointers. + +*************************************************************** +Remember that any local objects that you create are not deleted when a +lonjmp() is executed. Unfortunately, the syntactic predicates (...)? +use setjmp()/longjmp(). There are some situations when a few tokens +will "leak". +*************************************************************** + +2 DETAILS + +o The default is to perform token object garbage collection. + You may use parser->noGarbageCollectTokens() to turn off + garbage collection. + + +o The type ANTLRTokenPtr is always defined now (automatically). + If you do not wish to use smart pointers, you will have to + redefined ANTLRTokenPtr by subclassing, changing the header + file or changing ANTLR's code generation (easy enough to + do in gen.c). + +o If you don't use ParserBlackBox, the new initialization sequence is: + + ANTLRTokenPtr aToken = new ANTLRToken; + scan.setToken(mytoken(aToken)); + + where mytoken(aToken) gets an ANTLRToken * from the smart pointer. + +o Define C++ preprocessor symbol DBG_REFCOUNTTOKEN to see a bunch of + debugging stuff for reference counting if you suspect something. + + +3 WHY DO I HAVE TO TYPECAST ALL MY TOKEN POINTERS NOW?????? + +If you subclass ANTLRCommonToken and then attempt to refer to one of +your token members via a token pointer in your grammar actions, the +C++ compiler will complain that your token object does not have that +member. For example, if you used to do this + +<< +class ANTLRToken : public ANTLRCommonToken { + int muck; + ... +}; +>> + +class Foo { +a : t:ID << t->muck = ...; >> ; +} + +Now, you must do change the t->muck reference to: + +a : t:ID << mytoken(t)->muck = ...; >> ; + +in order to downcast 't' to be an "ANTLRToken *" not the +"ANTLRAbstractToken *" resulting from ANTLRTokenPtr::operator->(). +The macro is defined as: + +/* + * Since you cannot redefine operator->() to return one of the user's + * token object types, we must down cast. This is a drag. Here's + * a macro that helps. template: "mytoken(a-smart-ptr)->myfield". + */ +#define mytoken(tp) ((ANTLRToken *)(tp.operator->())) + +You have to use macro mytoken(grammar-label) now because smart +pointers are not specific to a parser's token objects. In other +words, the ANTLRTokenPtr class has a pointer to a generic +ANTLRAbstractToken not your ANTLRToken; the ANTLR support code must +use smart pointers too, but be able to work with any kind of +ANTLRToken. Sorry about this, but it's C++'s fault not mine. Some +nebulous future version of the C++ compilers should obviate the need +to downcast smart pointers with runtime type checking (and by allowing +different return type of overridden functions). + +A way to have backward compatible code is to shut off the token object +garbage collection; i.e., use parser->noGarbageCollectTokens() and +change the definition of ANTLRTokenPtr (that's why you get source code +). + + +PARSER EXCEPTION HANDLING + +I've noticed some weird stuff with the exception handling. I intend +to give this top priority for the "book release" of ANTLR. + +========== +1.32 Full Release + +o Changed Token class hierarchy to be (Thanks to Tom Moog): + + ANTLRAbstractToken + ANTLRRefCountToken + ANTLRCommonToken + ANTLRNoRefCountCommonToken + +o Added virtual panic() to ANTLRAbstractToken. Made ANTLRParser::panic() + virtual also. + +o Cleaned up the dup() stuff in AST hierarchy to use shallowCopy() to + make node copies. John Farr at Medtronic suggested this. I.e., + if you want to use dup() with either ANTLR or SORCERER or -transform + mode with SORCERER, you must defined shallowCopy() as: + + virtual PCCTS_AST *shallowCopy() + { + return new AST; + p->setDown(NULL); + p->setRight(NULL); + return p; + } + + or + + virtual PCCTS_AST *shallowCopy() + { + return new AST(*this); + } + + if you have defined a copy constructor such as + + AST(const AST &t) // shallow copy constructor + { + token = t.token; + iconst = t.iconst; + setDown(NULL); + setRight(NULL); + } + +o Added a warning with -CC and -gk are used together. This is broken, + hence a warning is appropriate. + +o Added warning when #-stuff is used w/o -gt option. + +o Updated MPW installation. + +o "Miller, Philip W." suggested + that genmk be use RENAME_OBJ_FLAG RENAME_EXE_FLAG instead of + hardcoding "-o" in genmk.c. + +o made all exit() calls use EXIT_SUCCESS or EXIT_FAILURE. + +=========================================================================== +1.33 + +EXIT_FAILURE and EXIT_SUCCESS were not always defined. I had to modify +a bunch of files to use PCCTS_EXIT_XXX, which forces a new version. Sorry +about that. + diff --git a/Tools/Source/TianoTools/Pccts/CHANGES_FROM_133.txt b/Tools/Source/TianoTools/Pccts/CHANGES_FROM_133.txt new file mode 100644 index 0000000000..2128c4ff25 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/CHANGES_FROM_133.txt @@ -0,0 +1,2448 @@ +======================================================================= +List of Implemented Fixes and Changes for Maintenance Releases of PCCTS +======================================================================= + + DISCLAIMER + + The software and these notes are provided "as is". They may include + typographical or technical errors and their authors disclaims all + liability of any kind or nature for damages due to error, fault, + defect, or deficiency regardless of cause. All warranties of any + kind, either express or implied, including, but not limited to, the + implied warranties of merchantability and fitness for a particular + purpose are disclaimed. + + + ------------------------------------------------------- + Note: Items #153 to #1 are now in a separate file named + CHANGES_FROM_133_BEFORE_MR13.txt + ------------------------------------------------------- + +#312. (Changed in MR33) Bug caused by change #299. + + In change #299 a warning message was suppressed when there was + no LT(1) in a semantic predicate and max(k,ck) was 1. The + changed caused the code which set a default predicate depth for + the semantic predicate to be left as 0 rather than set to 1. + + This manifested as an error at line #1559 of mrhost.c + + Reported by Peter Dulimov. + +#311. (Changed in MR33) Added sorcer/lib to Makefile. + + Reported by Dale Martin. + +#310. (Changed in MR32) In C mode zzastPush was spelled zzastpush in one case. + + Reported by Jean-Claude Durand + +#309. (Changed in MR32) Renamed baseName because of VMS name conflict + + Renamed baseName to pcctsBaseName to avoid library name conflict with + VMS library routine. Reported by Jean-François PIÉRONNE. + +#308. (Changed in MR32) Used "template" as name of formal in C routine + + In astlib.h routine ast_scan a formal was named "template". This caused + problems when the C code was compiled with a C++ compiler. Reported by + Sabyasachi Dey. + +#307. (Changed in MR31) Compiler dependent bug in function prototype generation + + The code which generated function prototypes contained a bug which + was compiler/optimization dependent. Under some circumstance an + extra character would be included in portions of a function prototype. + + Reported by David Cook. + +#306. (Changed in MR30) Validating predicate following a token + + A validating predicate which immediately followed a token match + consumed the token after the predicate rather than before. Prior + to this fix (in the following example) isValidTimeScaleValue() in + the predicate would test the text for TIMESCALE rather than for + NUMBER: + + time_scale : + TIMESCALE + <getText())>>? + ts:NUMBER + ( us:MICROSECOND << tVal = ...>> + | ns:NANOSECOND << tVal = ... >> + ) + + Reported by Adalbert Perbandt. + +#305. (Changed in MR30) Alternatives with guess blocks inside (...)* blocks. + + In MR14 change #175 fixed a bug in the prediction expressions for guess + blocks which were of the form (alpha)? beta. Unfortunately, this + resulted in a new bug as exemplified by the example below, which computed + the first set for r as {B} rather than {B C}: + + r : ( (A)? B + | C + )* + + This example doesn't make any sense as A is not a prefix of B, but it + illustrates the problem. This bug did not appear for: + + r : ( (A)? + | C + )* + + because it does not use the (alpha)? beta form. + + Item #175 fixed an asymmetry in ambiguity messages for the following + constructs which appear to have identical ambiguities (between repeating + the loop vs. exiting the loop). MR30 retains this fix, but the implementation + is slightly different. + + r_star : ( (A B)? )* A ; + r_plus : ( (A B)? )+ A ; + + Reported by Arpad Beszedes (beszedes inf.u-szeged.hu). + +#304. (Changed in MR30) Crash when mismatch between output value counts. + + For a rule such as: + + r1 : r2>[i,j]; + r2 >[int i, int j] : A; + + If there were extra actuals for the reference to rule r2 from rule r1 + there antlr would crash. This bug was introduced by change #276. + + Reported by Sinan Karasu. + +#303. (Changed in MR30) DLGLexerBase::replchar + + DLGLexerBase::replchar and the C mode routine zzreplchar did not work + properly when the new character was 0. + + Reported with fix by Philippe Laporte + +#302. (Changed in MR28) Fix significant problems in initial release of MR27. + +#301. (Changed in MR27) Default tab stops set to 2 spaces. + + To have antlr generate true tabs rather than spaces, use "antlr -tab 0". + To generate 4 spaces per tab stop use "antlr -tab 4" + +#300. (Changed in MR27) + + Consider the following methods of constructing an AST from ID: + + rule1! + : id:ID << #0 = #[id]; >> ; + + rule2! + : id:ID << #0 = #id; >> ; + + rule3 + : ID ; + + rule4 + : id:ID << #0 = #id; >> ; + + For rule_2, the AST corresponding to id would always be NULL. This + is because the user explicitly suppressed AST construction using the + "!" operator on the rule. In MR27 the use of an AST expression + such as #id overrides the "!" operator and forces construction of + the AST. + + This fix does not apply to C mode ASTs when the ASTs are referenced + using numbers rather than symbols. + + For C mode, this requires that the (optional) function/macro zzmk_ast + be defined. This functions copies information from an attribute into + a previously allocated AST. + + Reported by Jan Langer (jan langernetz.de) + +#299. (Changed in MR27) Don't warn if k=1 and semantic predicate missing LT(i) + + If a semantic does not have a reference to LT(i) or (C mode LATEXT(i)) + then pccts doesn't know how many lookahead tokens to use for context. + However, if max(k,ck) is 1 then there is really only one choice and + the warning is unnecessary. + +#298. (Changed in MR27) Removed "register" for lastpos in dlgauto.c zzgettok + +#297. (Changed in MR27) Incorrect prototypes when used with classic C + + There were a number of errors in function headers when antlr was + built with compilers that do not have __STDC__ or __cplusplus set. + + The functions which have variable length argument lists now use + PCCTS_USE_STDARG rather than __USE_PROTOTYPES__ to determine + whether to use stdargs or varargs. + +#296. (Changed in MR27) Complex return types in rules. + + The following return type was not properly handled when + unpacking a struct with containing multiple return values: + + rule > [int i, IIR_Bool (IIR_Decl::*constraint)()] : ... + + Instead of using "constraint", the program got lost and used + an empty string. + + Reported by P.A. Wilsey. + +#295. (Changed in MR27) Extra ";" following zzGUESS_DONE sometimes. + + Certain constructs with guess blocks in MR23 led to extra ";" + preceding the "else" clause of an "if". + + Reported by P.A. Wilsey. + +#294. (Changed in MR27) Infinite loop in antlr for nested blocks + + An oversight in detecting an empty alternative sometimes led + to an infinite loop in antlr when it encountered a rule with + nested blocks and guess blocks. + + Reported by P.A. Wilsey. + +#293. (Changed in MR27) Sorcerer optimization of _t->type() + + Sorcerer generated code may contain many calls to _t->type() in a + single statement. This change introduces a temporary variable + to eliminate unnnecesary function calls. + + Change implemented by Tom Molteno (tim videoscript.com). + +#292. (Changed in MR27) + + WARNING: Item #267 changes the signature of methods in the AST class. + + **** Be sure to revise your AST functions of the same name *** + +#291. (Changed in MR24) + + Fix to serious code generation error in MR23 for (...)+ block. + +#290. (Changed in MR23) + + Item #247 describes a change in the way {...} blocks handled + an error. Consider: + + r1 : {A} b ; + b : B; + + with input "C". + + Prior to change #247, the error would resemble "expected B - + found C". This is correct but incomplete, and therefore + misleading. In #247 it was changed to "expected A, B - found + C". This was fine, except for users of parser exception + handling because the exception was generated in the epilogue + for {...} block rather than in rule b. This made it difficult + for users of parser exception handling because B was not + expected in that context. Those not using parser exception + handling didn't notice the difference. + + The current change restores the behavior prior to #247 when + parser exceptions are present, but retains the revised behavior + otherwise. This change should be visible only when exceptions + are in use and only for {...} blocks and sub-blocks of the form + (something|something | something | epsilon) where epsilon represents + an empty production and it is the last alternative of a sub-block. + In contrast, (something | epsilon | something) should generate the + same code as before, even when exceptions are used. + + Reported by Philippe Laporte (philippe at transvirtual.com). + +#289. (Changed in MR23) Bug in matching complement of a #tokclass + + Prior to MR23 when a #tokclass was matched in both its complemented form + and uncomplemented form, the bit set generated for its first use was used + for both cases. However, the prediction expression was correctly computed + in both cases. This meant that the second case would never be matched + because, for the second appearance, the prediction expression and the + set to be matched would be complements of each other. + + Consider: + + #token A "a" + #token B "b" + #token C "c" + #tokclass AB {A B} + + r1 : AB /* alt 1x */ + | ~AB /* alt 1y */ + ; + + Prior to MR23, this resulted in alternative 1y being unreachable. Had it + been written: + + r2 : ~AB /* alt 2x */ + : AB /* alt 2y */ + + then alternative 2y would have become unreachable. + + This bug was only for the case of complemented #tokclass. For complemented + #token the proper code was generated. + +#288. (Changed in MR23) #errclass not restricted to choice points + + The #errclass directive is supposed to allow a programmer to define + print strings which should appear in syntax error messages as a replacement + for some combinations of tokens. For instance: + + #errclass Operator {PLUS MINUS TIMES DIVIDE} + + If a syntax message includes all four of these tokens, and there is no + "better" choice of error class, the word "Operator" will be used rather + than a list of the four token names. + + Prior to MR23 the #errclass definitions were used only at choice points + (which call the FAIL macro). In other cases where there was no choice + (e.g. where a single token or token class were matched) the #errclass + information was not used. + + With MR23 the #errclass declarations are used for syntax error messages + when matching a #tokclass, a wildcard (i.e. "*"), or the complement of a + #token or #tokclass (e.g. ~Operator). + + Please note that #errclass may now be defined using #tokclass names + (see Item #284). + + Reported by Philip A. Wilsey. + +#287. (Changed in MR23) Print name for #tokclass + + Item #148 describes how to give a print name to a #token so that,for + example, #token ID could have the expression "identifier" in syntax + error messages. This has been extended to #tokclass: + + #token ID("identifier") "[a-zA-Z]+" + #tokclass Primitive("primitive type") + {INT, FLOAT, CHAR, FLOAT, DOUBLE, BOOL} + + This is really a cosmetic change, since #tokclass names do not appear + in any error messages. + +#286. (Changed in MR23) Makefile change to use of cd + + In cases where a pccts subdirectory name matched a directory identified + in a $CDPATH environment variable the build would fail. All makefile + cd commands have been changed from "cd xyz" to "cd ./xyz" in order + to avoid this problem. + +#285. (Changed in MR23) Check for null pointers in some dlg structures + + An invalid regular expression can cause dlg to build an invalid + structure to represent the regular expression even while it issues + error messages. Additional pointer checks were added. + + Reported by Robert Sherry. + +#284. (Changed in MR23) Allow #tokclass in #errclass definitions + + Previously, a #tokclass reference in the definition of an + #errclass was not handled properly. Instead of being expanded + into the set of tokens represented by the #tokclass it was + treated somewhat like an #errclass. However, in a later phase + when all #errclass were expanded into the corresponding tokens + the #tokclass reference was not expanded (because it wasn't an + #errclass). In effect the reference was ignored. + + This has been fixed. + + Problem reported by Mike Dimmick (mike dimmick.demon.co.uk). + +#283. (Changed in MR23) Option -tmake invoke's parser's tmake + + When the string #(...) appears in an action antlr replaces it with + a call to ASTBase::tmake(...) to construct an AST. It is sometimes + useful to change the tmake routine so that it has access to information + in the parser - something which is not possible with a static method + in an application where they may be multiple parsers active. + + The antlr option -tmake replaces the call to ASTBase::tmake with a call + to a user supplied tmake routine. + +#282. (Changed in MR23) Initialization error for DBG_REFCOUNTTOKEN + + When the pre-processor symbol DBG_REFCOUNTTOKEN is defined + incorrect code is generated to initialize ANTLRRefCountToken::ctor and + dtor. + + Fix reported by Sven Kuehn (sven sevenkuehn.de). + +#281. (Changed in MR23) Addition of -noctor option for Sorcerer + + Added a -noctor option to suppress generation of the blank ctor + for users who wish to define their own ctor. + + Contributed by Jan Langer (jan langernetz.de). + +#280. (Changed in MR23) Syntax error message for EOF token + + The EOF token now receives special treatment in syntax error messages + because there is no text matched by the eof token. The token name + of the eof token is used unless it is "@" - in which case the string + "" is used. + + Problem reported by Erwin Achermann (erwin.achermann switzerland.org). + +#279. (Changed in MR23) Exception groups + + There was a bug in the way that exception groups were attached to + alternatives which caused problems when there was a block contained + in an alternative. For instance, in the following rule; + + statement : IF S { ELSE S } + exception .... + ; + + the exception would be attached to the {...} block instead of the + entire alternative because it was attached, in error, to the last + alternative instead of the last OPEN alternative. + + Reported by Ty Mordane (tymordane hotmail.com). + +#278. (Changed in MR23) makefile changes + + Contributed by Tomasz Babczynski (faster lab05-7.ict.pwr.wroc.pl). + + The -cfile option is not absolutely needed: when extension of + source file is one of the well-known C/C++ extensions it is + treated as C/C++ source + + The gnu make defines the CXX variable as the default C++ compiler + name, so I added a line to copy this (if defined) to the CCC var. + + Added a -sor option: after it any -class command defines the class + name for sorcerer, not for ANTLR. A file extended with .sor is + treated as sorcerer input. Because sorcerer can be called multiple + times, -sor option can be repeated. Any files and classes (one class + per group) after each -sor makes one tree parser. + + Not implemented: + + 1. Generate dependences for user c/c++ files. + 2. Support for -sor in c mode not. + + I have left the old genmk program in the directory as genmk_old.c. + +#277. (Changed in MR23) Change in macro for failed semantic predicates + + In the past, a semantic predicate that failed generated a call to + the macro zzfailed_pred: + + #ifndef zzfailed_pred + #define zzfailed_pred(_p) \ + if (guessing) { \ + zzGUESS_FAIL; \ + } else { \ + something(_p) + } + #endif + + If a user wished to use the failed action option for semantic predicates: + + rule : <>? [my_fail_action] A + | ... + + + the code for my_fail_action would have to contain logic for handling + the guess part of the zzfailed_pred macro. The user should not have + to be aware of the guess logic in writing the fail action. + + The zzfailed_pred has been rewritten to have three arguments: + + arg 1: the stringized predicate of the semantic predicate + arg 2: 0 => there is no user-defined fail action + 1 => there is a user-defined fail action + arg 3: the user-defined fail action (if defined) + otherwise a no-operation + + The zzfailed_pred macro is now defined as: + + #ifndef zzfailed_pred + #define zzfailed_pred(_p,_hasuseraction,_useraction) \ + if (guessing) { \ + zzGUESS_FAIL; \ + } else { \ + zzfailed_pred_action(_p,_hasuseraction,_useraction) \ + } + #endif + + + With zzfailed_pred_action defined as: + + #ifndef zzfailed_pred_action + #define zzfailed_pred_action(_p,_hasuseraction,_useraction) \ + if (_hasUserAction) { _useraction } else { failedSemanticPredicate(_p); } + #endif + + In C++ mode failedSemanticPredicate() is a virtual function. + In C mode the default action is a fprintf statement. + + Suggested by Erwin Achermann (erwin.achermann switzerland.org). + +#276. (Changed in MR23) Addition of return value initialization syntax + + In an attempt to reduce the problems caused by the PURIFY macro I have + added new syntax for initializing the return value of rules and the + antlr option "-nopurify". + + A rule with a single return argument: + + r1 > [Foo f = expr] : + + now generates code that resembles: + + Foo r1(void) { + Foo _retv = expr; + ... + } + + A rule with more than one return argument: + + r2 > [Foo f = expr1, Bar b = expr2 ] : + + generates code that resembles: + + struct _rv1 { + Foo f; + Bar b; + } + + _rv1 r2(void) { + struct _rv1 _retv; + _retv.f = expr1; + _retv.b = expr2; + ... + } + + C++ style comments appearing in the initialization list may cause problems. + +#275. (Changed in MR23) Addition of -nopurify option to antlr + + A long time ago the PURIFY macro was introduced to initialize + return value arguments and get rid of annying messages from program + that checked for unitialized variables. + + This has caused significant annoyance for C++ users that had + classes with virtual functions or non-trivial contructors because + it would zero the object, including the pointer to the virtual + function table. This could be defeated by redefining + the PURIFY macro to be empty, but it was a constant surprise to + new C++ users of pccts. + + I would like to remove it, but I fear that some existing programs + depend on it and would break. My temporary solution is to add + an antlr option -nopurify which disables generation of the PURIFY + macro call. + + The PURIFY macro should be avoided in favor of the new syntax + for initializing return arguments described in item #275. + + To avoid name clash, the PURIFY macro has been renamed PCCTS_PURIFY. + +#274. (Changed in MR23) DLexer.cpp renamed to DLexer.h + (Changed in MR23) ATokPtr.cpp renamed to ATokPtrImpl.h + + These two files had .cpp extensions but acted like .h files because + there were included in other files. This caused problems for many IDE. + I have renamed them. The ATokPtrImpl.h was necessary because there was + already an ATokPtr.h. + +#273. (Changed in MR23) Default win32 library changed to multi-threaded DLL + + The model used for building the Win32 debug and release libraries has changed + to multi-threaded DLL. + + To make this change in your MSVC 6 project: + + Project -> Settings + Select the C++ tab in the right pane of the dialog box + Select "Category: Code Generation" + Under "Use run-time library" select one of the following: + + Multi-threaded DLL + Debug Multi-threaded DLL + + Suggested by Bill Menees (bill.menees gogallagher.com) + +#272. (Changed in MR23) Failed semantic predicate reported via virtual function + + In the past, a failed semantic predicated reported the problem via a + macro which used fprintf(). The macro now expands into a call on + the virtual function ANTLRParser::failedSemanticPredicate(). + +#271. (Changed in MR23) Warning for LT(i), LATEXT(i) in token match actions + + An bug (or at least an oddity) is that a reference to LT(1), LA(1), + or LATEXT(1) in an action which immediately follows a token match + in a rule refers to the token matched, not the token which is in + the lookahead buffer. Consider: + + r : abc <> D <> E; + + In this case LT(1) in action alpha will refer to the next token in + the lookahead buffer ("D"), but LT(1) in action beta will refer to + the token matched by D - the preceding token. + + A warning has been added for users about this when an action + following a token match contains a reference to LT(1), LA(1), or LATEXT(1). + + This behavior should be changed, but it appears in too many programs + now. Another problem, perhaps more significant, is that the obvious + fix (moving the consume() call to before the action) could change the + order in which input is requested and output appears in existing programs. + + This problem was reported, along with a fix by Benjamin Mandel + (beny sd.co.il). However, I felt that changing the behavior was too + dangerous for existing code. + +#270. (Changed in MR23) Removed static objects from PCCTSAST.cpp + + There were some statically allocated objects in PCCTSAST.cpp + These were changed to non-static. + +#269. (Changed in MR23) dlg output for initializing static array + + The output from dlg contains a construct similar to the + following: + + struct XXX { + static const int size; + static int array1[5]; + }; + + const int XXX::size = 4; + int XXX::array1[size+1]; + + + The problem is that although the expression "size+1" used in + the definition of array1 is equal to 5 (the expression used to + declare array), it is not considered equivalent by some compilers. + + Reported with fix by Volker H. Simonis (simonis informatik.uni-tuebingen.de) + +#268. (Changed in MR23) syn() routine output when k > 1 + + The syn() routine is supposed to print out the text of the + token causing the syntax error. It appears that it always + used the text from the first lookahead token rather than the + appropriate one. The appropriate one is computed by comparing + the token codes of lookahead token i (for i = 1 to k) with + the FIRST(i) set. + + This has been corrected in ANTLRParser::syn(). + + Reported by Bill Menees (bill.menees gogallagher.com) + +#267. (Changed in MR23) AST traversal functions client data argument + + The AST traversal functions now take an extra (optional) parameter + which can point to client data: + + preorder_action(void* pData = NULL) + preorder_before_action(void* pData = NULL) + preorder_after_action(void* pData = NULL) + + **** Warning: this changes the AST signature. *** + **** Be sure to revise your AST functions of the same name *** + + Bill Menees (bill.menees gogallagher.com) + +#266. (Changed in MR23) virtual function printMessage() + + Bill Menees (bill.menees gogallagher.com) has completed the + tedious taks of replacing all calls to fprintf() with calls + to the virtual function printMessage(). For classes which + have a pointer to the parser it forwards the printMessage() + call to the parser's printMessage() routine. + + This should make it significanly easier to redirect pccts + error and warning messages. + +#265. (Changed in MR23) Remove "labase++" in C++ mode + + In C++ mode labase++ is called when a token is matched. + It appears that labase is not used in C++ mode at all, so + this code has been commented out. + +#264. (Changed in MR23) Complete rewrite of ParserBlackBox.h + + The parser black box (PBlackBox.h) was completely rewritten + by Chris Uzdavinis (chris atdesk.com) to improve its robustness. + +#263. (Changed in MR23) -preamble and -preamble_first rescinded + + Changes for item #253 have been rescinded. + +#262. (Changed in MR23) Crash with -alpha option during traceback + + Under some circumstances a -alpha traceback was started at the + "wrong" time. As a result, internal data structures were not + initialized. + + Reported by Arpad Beszedes (beszedes inf.u-szeged.hu). + +#261. (Changed in MR23) Defer token fetch for C++ mode + + Item #216 has been revised to indicate that use of the defer fetch + option (ZZDEFER_FETCH) requires dlg option -i. + +#260. (MR22) Raise default lex buffer size from 8,000 to 32,000 bytes. + + ZZLEXBUFSIZE is the size (in bytes) of the buffer used by dlg + generated lexers. The default value has been raised to 32,000 and + the value used by antlr, dlg, and sorcerer has also been raised to + 32,000. + +#259. (MR22) Default function arguments in C++ mode. + + If a rule is declared: + + rr [int i = 0] : .... + + then the declaration generated by pccts resembles: + + void rr(int i = 0); + + however, the definition must omit the default argument: + + void rr(int i) {...} + + In the past the default value was not omitted. In MR22 + the generated code resembles: + + void rr(int i /* = 0 */ ) {...} + + Implemented by Volker H. Simonis (simonis informatik.uni-tuebingen.de) + + + Note: In MR23 this was changed so that nested C style comments + ("/* ... */") would not cause problems. + +#258. (MR22) Using a base class for your parser + + In item #102 (MR10) the class statement was extended to allow one + to specify a base class other than ANTLRParser for the generated + parser. It turned out that this was less than useful because + the constructor still specified ANTLRParser as the base class. + + The class statement now uses the first identifier appearing after + the ":" as the name of the base class. For example: + + class MyParser : public FooParser { + + Generates in MyParser.h: + + class MyParser : public FooParser { + + Generates in MyParser.cpp something that resembles: + + MyParser::MyParser(ANTLRTokenBuffer *input) : + FooParser(input,1,0,0,4) + { + token_tbl = _token_tbl; + traceOptionValueDefault=1; // MR10 turn trace ON + } + + The base class constructor must have a signature similar to + that of ANTLRParser. + +#257. (MR21a) Removed dlg statement that -i has no effect in C++ mode. + + This was incorrect. + +#256. (MR21a) Malformed syntax graph causes crash after error message. + + In the past, certain kinds of errors in the very first grammar + element could cause the construction of a malformed graph + representing the grammar. This would eventually result in a + fatal internal error. The code has been changed to be more + resistant to this particular error. + +#255. (MR21a) ParserBlackBox(FILE* f) + + This constructor set openByBlackBox to the wrong value. + + Reported by Kees Bakker (kees_bakker tasking.nl). + +#254. (MR21a) Reporting syntax error at end-of-file + + When there was a syntax error at the end-of-file the syntax + error routine would substitute "" for the programmer's + end-of-file symbol. This substitution is now done only when + the programmer does not define his own end-of-file symbol + or the symbol begins with the character "@". + + Reported by Kees Bakker (kees_bakker tasking.nl). + +#253. (MR21) Generation of block preamble (-preamble and -preamble_first) + + *** This change was rescinded by item #263 *** + + The antlr option -preamble causes antlr to insert the code + BLOCK_PREAMBLE at the start of each rule and block. It does + not insert code before rules references, token references, or + actions. By properly defining the macro BLOCK_PREAMBLE the + user can generate code which is specific to the start of blocks. + + The antlr option -preamble_first is similar, but inserts the + code BLOCK_PREAMBLE_FIRST(PreambleFirst_123) where the symbol + PreambleFirst_123 is equivalent to the first set defined by + the #FirstSetSymbol described in Item #248. + + I have not investigated how these options interact with guess + mode (syntactic predicates). + +#252. (MR21) Check for null pointer in trace routine + + When some trace options are used when the parser is generated + without the trace enabled, the current rule name may be a + NULL pointer. A guard was added to check for this in + restoreState. + + Reported by Douglas E. Forester (dougf projtech.com). + +#251. (MR21) Changes to #define zzTRACE_RULES + + The macro zzTRACE_RULES was being use to pass information to + AParser.h. If this preprocessor symbol was not properly + set the first time AParser.h was #included, the declaration + of zzTRACEdata would be omitted (it is used by the -gd option). + Subsequent #includes of AParser.h would be skipped because of + the #ifdef guard, so the declaration of zzTracePrevRuleName would + never be made. The result was that proper compilation was very + order dependent. + + The declaration of zzTRACEdata was made unconditional and the + problem of removing unused declarations will be left to optimizers. + + Diagnosed by Douglas E. Forester (dougf projtech.com). + +#250. (MR21) Option for EXPERIMENTAL change to error sets for blocks + + The antlr option -mrblkerr turns on an experimental feature + which is supposed to provide more accurate syntax error messages + for k=1, ck=1 grammars. When used with k>1 or ck>1 grammars the + behavior should be no worse than the current behavior. + + There is no problem with the matching of elements or the computation + of prediction expressions in pccts. The task is only one of listing + the most appropriate tokens in the error message. The error sets used + in pccts error messages are approximations of the exact error set when + optional elements in (...)* or (...)+ are involved. While entirely + correct, the error messages are sometimes not 100% accurate. + + There is also a minor philosophical issue. For example, suppose the + grammar expects the token to be an optional A followed by Z, and it + is X. X, of course, is neither A nor Z, so an error message is appropriate. + Is it appropriate to say "Expected Z" ? It is correct, it is accurate, + but it is not complete. + + When k>1 or ck>1 the problem of providing the exactly correct + list of tokens for the syntax error messages ends up becoming + equivalent to evaluating the prediction expression for the + alternatives twice. However, for k=1 ck=1 grammars the prediction + expression can be computed easily and evaluated cheaply, so I + decided to try implementing it to satisfy a particular application. + This application uses the error set in an interactive command language + to provide prompts which list the alternatives available at that + point in the parser. The user can then enter additional tokens to + complete the command line. To do this required more accurate error + sets then previously provided by pccts. + + In some cases the default pccts behavior may lead to more robust error + recovery or clearer error messages then having the exact set of tokens. + This is because (a) features like -ge allow the use of symbolic names for + certain sets of tokens, so having extra tokens may simply obscure things + and (b) the error set is use to resynchronize the parser, so a good + choice is sometimes more important than having the exact set. + + Consider the following example: + + Note: All examples code has been abbreviated + to the absolute minimum in order to make the + examples concise. + + star1 : (A)* Z; + + The generated code resembles: + + old new (with -mrblkerr) + --//----------- -------------------- + for (;;) { for (;;) { + match(A); match(A); + } } + match(Z); if (! A and ! Z) then + FAIL(...{A,Z}...); + } + match(Z); + + + With input X + old message: Found X, expected Z + new message: Found X, expected A, Z + + For the example: + + star2 : (A|B)* Z; + + old new (with -mrblkerr) + ------------- -------------------- + for (;;) { for (;;) { + if (!A and !B) break; if (!A and !B) break; + if (...) { if (...) { + + } } + else { else { + FAIL(...{A,B,Z}...) FAIL(...{A,B}...); + } } + } } + match(B); if (! A and ! B and !Z) then + FAIL(...{A,B,Z}...); + } + match(B); + + With input X + old message: Found X, expected Z + new message: Found X, expected A, B, Z + With input A X + old message: Found X, expected Z + new message: Found X, expected A, B, Z + + This includes the choice of looping back to the + star block. + + The code for plus blocks: + + plus1 : (A)+ Z; + + The generated code resembles: + + old new (with -mrblkerr) + ------------- -------------------- + do { do { + match(A); match(A); + } while (A) } while (A) + match(Z); if (! A and ! Z) then + FAIL(...{A,Z}...); + } + match(Z); + + With input A X + old message: Found X, expected Z + new message: Found X, expected A, Z + + This includes the choice of looping back to the + plus block. + + For the example: + + plus2 : (A|B)+ Z; + + old new (with -mrblkerr) + ------------- -------------------- + do { do { + if (A) { + match(A); + } else if (B) { + match(B); + } else { + if (cnt > 1) break; + FAIL(...{A,B,Z}...) FAIL(...{A,B}...); + } } + cnt++; + } } + + match(Z); if (! A and ! B and !Z) then + FAIL(...{A,B,Z}...); + } + match(B); + + With input X + old message: Found X, expected A, B, Z + new message: Found X, expected A, B + With input A X + old message: Found X, expected Z + new message: Found X, expected A, B, Z + + This includes the choice of looping back to the + star block. + +#249. (MR21) Changes for DEC/VMS systems + + Jean-François Piéronne (jfp altavista.net) has updated some + VMS related command files and fixed some minor problems related + to building pccts under the DEC/VMS operating system. For DEC/VMS + users the most important differences are: + + a. Revised makefile.vms + b. Revised genMMS for genrating VMS style makefiles. + +#248. (MR21) Generate symbol for first set of an alternative + + pccts can generate a symbol which represents the tokens which may + appear at the start of a block: + + rr : #FirstSetSymbol(rr_FirstSet) ( Foo | Bar ) ; + + This will generate the symbol rr_FirstSet of type SetWordType with + elements Foo and Bar set. The bits can be tested using code similar + to the following: + + if (set_el(Foo, &rr_FirstSet)) { ... + + This can be combined with the C array zztokens[] or the C++ routine + tokenName() to get the print name of the token in the first set. + + The size of the set is given by the newly added enum SET_SIZE, a + protected member of the generated parser's class. The number of + elements in the generated set will not be exactly equal to the + value of SET_SIZE because of synthetic tokens created by #tokclass, + #errclass, the -ge option, and meta-tokens such as epsilon, and + end-of-file. + + The #FirstSetSymbol must appear immediately before a block + such as (...)+, (...)*, and {...}, and (...). It may not appear + immediately before a token, a rule reference, or action. However + a token or rule reference can be enclosed in a (...) in order to + make the use of #pragma FirstSetSymbol legal. + + rr_bad : #FirstSetSymbol(rr_bad_FirstSet) Foo; // Illegal + + rr_ok : #FirstSetSymbol(rr_ok_FirstSet) (Foo); // Legal + + Do not confuse FirstSetSymbol sets with the sets used for testing + lookahead. The sets used for FirstSetSymbol have one element per bit, + so the number of bytes is approximately the largest token number + divided by 8. The sets used for testing lookahead store 8 lookahead + sets per byte, so the length of the array is approximately the largest + token number. + + If there is demand, a similar routine for follow sets can be added. + +#247. (MR21) Misleading error message on syntax error for optional elements. + + =================================================== + The behavior has been revised when parser exception + handling is used. See Item #290 + =================================================== + + Prior to MR21, tokens which were optional did not appear in syntax + error messages if the block which immediately followed detected a + syntax error. + + Consider the following grammar which accepts Number, Word, and Other: + + rr : {Number} Word; + + For this rule the code resembles: + + if (LA(1) == Number) { + match(Number); + consume(); + } + match(Word); + + Prior to MR21, the error message for input "$ a" would be: + + line 1: syntax error at "$" missing Word + + With MR21 the message will be: + + line 1: syntax error at "$" expecting Word, Number. + + The generate code resembles: + + if ( (LA(1)==Number) ) { + zzmatch(Number); + consume(); + } + else { + if ( (LA(1)==Word) ) { + /* nothing */ + } + else { + FAIL(... message for both Number and Word ...); + } + } + match(Word); + + The code generated for optional blocks in MR21 is slightly longer + than the previous versions, but it should give better error messages. + + The code generated for: + + { a | b | c } + + should now be *identical* to: + + ( a | b | c | ) + + which was not the case prior to MR21. + + Reported by Sue Marvin (sue siara.com). + +#246. (Changed in MR21) Use of $(MAKE) for calls to make + + Calls to make from the makefiles were replaced with $(MAKE) + because of problems when using gmake. + + Reported with fix by Sunil K.Vallamkonda (sunil siara.com). + +#245. (Changed in MR21) Changes to genmk + + The following command line options have been added to genmk: + + -cfiles ... + + To add a user's C or C++ files into makefile automatically. + The list of files must be enclosed in apostrophes. This + option may be specified multiple times. + + -compiler ... + + The name of the compiler to use for $(CCC) or $(CC). The + default in C++ mode is "CC". The default in C mode is "cc". + + -pccts_path ... + + The value for $(PCCTS), the pccts directory. The default + is /usr/local/pccts. + + Contributed by Tomasz Babczynski (t.babczynski ict.pwr.wroc.pl). + +#244. (Changed in MR21) Rename variable "not" in antlr.g + + When antlr.g is compiled with a C++ compiler, a variable named + "not" causes problems. Reported by Sinan Karasu + (sinan.karasu boeing.com). + +#243 (Changed in MR21) Replace recursion with iteration in zzfree_ast + + Another refinement to zzfree_ast in ast.c to limit recursion. + + NAKAJIMA Mutsuki (muc isr.co.jp). + + +#242. (Changed in MR21) LineInfoFormatStr + + Added an #ifndef/#endif around LineInfoFormatStr in pcctscfg.h. + +#241. (Changed in MR21) Changed macro PURIFY to a no-op + + *********************** + *** NOT IMPLEMENTED *** + *********************** + + The PURIFY macro was changed to a no-op because it was causing + problems when passing C++ objects. + + The old definition: + + #define PURIFY(r,s) memset((char *) &(r),'\\0',(s)); + + The new definition: + + #define PURIFY(r,s) /* nothing */ +#endif + +#240. (Changed in MR21) sorcerer/h/sorcerer.h _MATCH and _MATCHRANGE + + Added test for NULL token pointer. + + Suggested by Peter Keller (keller ebi.ac.uk) + +#239. (Changed in MR21) C++ mode AParser::traceGuessFail + + If tracing is turned on when the code has been generated + without trace code, a failed guess generates a trace report + even though there are no other trace reports. This + make the behavior consistent with other parts of the + trace system. + + Reported by David Wigg (wiggjd sbu.ac.uk). + +#238. (Changed in MR21) Namespace version #include files + + Changed reference from CStdio to cstdio (and other + #include file names) in the namespace version of pccts. + Should have known better. + +#237. (Changed in MR21) ParserBlackBox(FILE*) + + In the past, ParserBlackBox would close the FILE in the dtor + even though it was not opened by ParserBlackBox. The problem + is that there were two constructors, one which accepted a file + name and did an fopen, the other which accepted a FILE and did + not do an fopen. There is now an extra member variable which + remembers whether ParserBlackBox did the open or not. + + Suggested by Mike Percy (mpercy scires.com). + +#236. (Changed in MR21) tmake now reports down pointer problem + + When ASTBase::tmake attempts to update the down pointer of + an AST it checks to see if the down pointer is NULL. If it + is not NULL it does not do the update and returns NULL. + An attempt to update the down pointer is almost always a + result of a user error. This can lead to difficult to find + problems during tree construction. + + With this change, the routine calls a virtual function + reportOverwriteOfDownPointer() which calls panic to + report the problem. Users who want the old behavior can + redefined the virtual function in their AST class. + + Suggested by Sinan Karasu (sinan.karasu boeing.com) + +#235. (Changed in MR21) Made ANTLRParser::resynch() virtual + + Suggested by Jerry Evans (jerry swsl.co.uk). + +#234. (Changed in MR21) Implicit int for function return value + + ATokenBuffer:bufferSize() did not specify a type for the + return value. + + Reported by Hai Vo-Ba (hai fc.hp.com). + +#233. (Changed in MR20) Converted to MSVC 6.0 + + Due to external circumstances I have had to convert to MSVC 6.0 + The MSVC 5.0 project files (.dsw and .dsp) have been retained as + xxx50.dsp and xxx50.dsw. The MSVC 6.0 files are named xxx60.dsp + and xxx60.dsw (where xxx is the related to the directory/project). + +#232. (Changed in MR20) Make setwd bit vectors protected in parser.h + + The access for the setwd array in the parser header was not + specified. As a result, it would depend on the code which + preceded it. In MR20 it will always have access "protected". + + Reported by Piotr Eljasiak (eljasiak zt.gdansk.tpsa.pl). + +#231. (Changed in MR20) Error in token buffer debug code. + + When token buffer debugging is selected via the pre-processor + symbol DEBUG_TOKENBUFFER there is an erroneous check in + AParser.cpp: + + #ifdef DEBUG_TOKENBUFFER + if (i >= inputTokens->bufferSize() || + inputTokens->minTokens() < LLk ) /* MR20 Was "<=" */ + ... + #endif + + Reported by David Wigg (wiggjd sbu.ac.uk). + +#230. (Changed in MR20) Fixed problem with #define for -gd option + + There was an error in setting zzTRACE_RULES for the -gd (trace) option. + + Reported by Gary Funck (gary intrepid.com). + +#229. (Changed in MR20) Additional "const" for literals + + "const" was added to the token name literal table. + "const" was added to some panic() and similar routine + +#228. (Changed in MR20) dlg crashes on "()" + + The following token defintion will cause DLG to crash. + + #token "()" + + When there is a syntax error in a regular expression + many of the dlg routines return a structure which has + null pointers. When this is accessed by callers it + generates the crash. + + I have attempted to fix the more common cases. + + Reported by Mengue Olivier (dolmen bigfoot.com). + +#227. (Changed in MR20) Array overwrite + + Steveh Hand (sassth unx.sas.com) reported a problem which + was traced to a temporary array which was not properly + resized for deeply nested blocks. This has been fixed. + +#226. (Changed in MR20) -pedantic conformance + + G. Hobbelt (i_a mbh.org) and THM made many, many minor + changes to create prototypes for all the functions and + bring antlr, dlg, and sorcerer into conformance with + the gcc -pedantic option. + + This may require uses to add pccts/h/pcctscfg.h to some + files or makefiles in order to have __USE_PROTOS defined. + +#225 (Changed in MR20) AST stack adjustment in C mode + + The fix in #214 for AST stack adjustment in C mode missed + some cases. + + Reported with fix by Ger Hobbelt (i_a mbh.org). + +#224 (Changed in MR20) LL(1) and LL(2) with #pragma approx + + This may take a record for the oldest, most trival, lexical + error in pccts. The regular expressions for LL(1) and LL(2) + lacked an escape for the left and right parenthesis. + + Reported by Ger Hobbelt (i_a mbh.org). + +#223 (Changed in MR20) Addition of IBM_VISUAL_AGE directory + + Build files for antlr, dlg, and sorcerer under IBM Visual Age + have been contributed by Anton Sergeev (ags mlc.ru). They have + been placed in the pccts/IBM_VISUAL_AGE directory. + +#222 (Changed in MR20) Replace __STDC__ with __USE_PROTOS + + Most occurrences of __STDC__ replaced with __USE_PROTOS due to + complaints from several users. + +#221 (Changed in MR20) Added #include for DLexerBase.h to PBlackBox. + + Added #include for DLexerBase.h to PBlackBox. + +#220 (Changed in MR19) strcat arguments reversed in #pred parse + + The arguments to strcat are reversed when creating a print + name for a hash table entry for use with #pred feature. + + Problem diagnosed and fix reported by Scott Harrington + (seh4 ix.netcom.com). + +#219. (Changed in MR19) C Mode routine zzfree_ast + + Changes to reduce use of recursion for AST trees with only right + links or only left links in the C mode routine zzfree_ast. + + Implemented by SAKAI Kiyotaka (ksakai isr.co.jp). + +#218. (Changed in MR19) Changes to support unsigned char in C mode + + Changes to antlr.h and err.h to fix omissions in use of zzchar_t + + Implemented by SAKAI Kiyotaka (ksakai isr.co.jp). + +#217. (Changed in MR19) Error message when dlg -i and -CC options selected + + *** This change was rescinded by item #257 *** + + The parsers generated by pccts in C++ mode are not able to support the + interactive lexer option (except, perhaps, when using the deferred fetch + parser option.(Item #216). + + DLG now warns when both -i and -CC are selected. + + This warning was suggested by David Venditti (07751870267-0001 t-online.de). + +#216. (Changed in MR19) Defer token fetch for C++ mode + + Implemented by Volker H. Simonis (simonis informatik.uni-tuebingen.de) + + Normally, pccts keeps the lookahead token buffer completely filled. + This requires max(k,ck) tokens of lookahead. For some applications + this can cause deadlock problems. For example, there may be cases + when the parser can't tell when the input has been completely consumed + until the parse is complete, but the parse can't be completed because + the input routines are waiting for additional tokens to fill the + lookahead buffer. + + When the ANTLRParser class is built with the pre-processor option + ZZDEFER_FETCH defined, the fetch of new tokens by consume() is deferred + until LA(i) or LT(i) is called. + + To test whether this option has been built into the ANTLRParser class + use "isDeferFetchEnabled()". + + Using the -gd trace option with the default tracein() and traceout() + routines will defeat the effort to defer the fetch because the + trace routines print out information about the lookahead token at + the start of the rule. + + Because the tracein and traceout routines are virtual it is + easy to redefine them in your parser: + + class MyParser { + << + virtual void tracein(ANTLRChar * ruleName) + { fprintf(stderr,"Entering: %s\n", ruleName); } + virtual void traceout(ANTLRChar * ruleName) + { fprintf(stderr,"Leaving: %s\n", ruleName); } + >> + + The originals for those routines are pccts/h/AParser.cpp + + This requires use of the dlg option -i (interactive lexer). + + This is implemented only for C++ mode. + + This is experimental. The interaction with guess mode (syntactic + predicates)is not known. + +#215. (Changed in MR19) Addition of reset() to DLGLexerBase + + There was no obvious way to reset the lexer for reuse. The + reset() method now does this. + + Suggested by David Venditti (07751870267-0001 t-online.de). + +#214. (Changed in MR19) C mode: Adjust AST stack pointer at exit + + In C mode the AST stack pointer needs to be reset if there will + be multiple calls to the ANTLRx macros. + + Reported with fix by Paul D. Smith (psmith baynetworks.com). + +#213. (Changed in MR18) Fatal error with -mrhoistk (k>1 hoisting) + + When rearranging code I forgot to un-comment a critical line of + code that handles hoisting of predicates with k>1 lookahead. This + is now fixed. + + Reported by Reinier van den Born (reinier vnet.ibm.com). + +#212. (Changed in MR17) Mac related changes by Kenji Tanaka + + Kenji Tanaka (kentar osa.att.ne.jp) has made a number of changes for + Macintosh users. + + a. The following Macintosh MPW files aid in installing pccts on Mac: + + pccts/MPW_Read_Me + + pccts/install68K.mpw + pccts/installPPC.mpw + + pccts/antlr/antlr.r + pccts/antlr/antlr68K.make + pccts/antlr/antlrPPC.make + + pccts/dlg/dlg.r + pccts/dlg/dlg68K.make + pccts/dlg/dlgPPC.make + + pccts/sorcerer/sor.r + pccts/sorcerer/sor68K.make + pccts/sorcerer/sorPPC.make + + They completely replace the previous Mac installation files. + + b. The most significant is a change in the MAC_FILE_CREATOR symbol + in pcctscfg.h: + + old: #define MAC_FILE_CREATOR 'MMCC' /* Metrowerks C/C++ Text files */ + new: #define MAC_FILE_CREATOR 'CWIE' /* Metrowerks C/C++ Text files */ + + c. Added calls to special_fopen_actions() where necessary. + +#211. (Changed in MR16a) C++ style comment in dlg + + This has been fixed. + +#210. (Changed in MR16a) Sor accepts \r\n, \r, or \n for end-of-line + + A user requested that Sorcerer be changed to accept other forms + of end-of-line. + +#209. (Changed in MR16) Name of files changed. + + Old: CHANGES_FROM_1.33 + New: CHANGES_FROM_133.txt + + Old: KNOWN_PROBLEMS + New: KNOWN_PROBLEMS.txt + +#208. (Changed in MR16) Change in use of pccts #include files + + There were problems with MS DevStudio when mixing Sorcerer and + PCCTS in the same source file. The problem is caused by the + redefinition of setjmp in the MS header file setjmp.h. In + setjmp.h the pre-processor symbol setjmp was redefined to be + _setjmp. A later effort to execute #include resulted + in an effort to #include <_setjmp.h>. I'm not sure whether this + is a bug or a feature. In any case, I decided to fix it by + avoiding the use of pre-processor symbols in #include statements + altogether. This has the added benefit of making pre-compiled + headers work again. + + I've replaced statements: + + old: #include PCCTS_SETJMP_H + new: #include "pccts_setjmp.h" + + Where pccts_setjmp.h contains: + + #ifndef __PCCTS_SETJMP_H__ + #define __PCCTS_SETJMP_H__ + + #ifdef PCCTS_USE_NAMESPACE_STD + #include + #else + #include + #endif + + #endif + + A similar change has been made for other standard header files + required by pccts and sorcerer: stdlib.h, stdarg.h, stdio.h, etc. + + Reported by Jeff Vincent (JVincent novell.com) and Dale Davis + (DalDavis spectrace.com). + +#207. (Changed in MR16) dlg reports an invalid range for: [\0x00-\0xff] + + ----------------------------------------------------------------- + Note from MR23: This fix does not work. I am investigating why. + ----------------------------------------------------------------- + + dlg will report that this is an invalid range. + + Diagnosed by Piotr Eljasiak (eljasiak no-spam.zt.gdansk.tpsa.pl): + + I think this problem is not specific to unsigned chars + because dlg reports no error for the range [\0x00-\0xfe]. + + I've found that information on range is kept in field + letter (unsigned char) of Attrib struct. Unfortunately + the letter value internally is for some reasons increased + by 1, so \0xff is represented here as 0. + + That's why dlg complains about the range [\0x00-\0xff] in + dlg_p.g: + + if ($$.letter > $2.letter) { + error("invalid range ", zzline); + } + + The fix is: + + if ($$.letter > $2.letter && 255 != $$2.letter) { + error("invalid range ", zzline); + } + +#206. (Changed in MR16) Free zzFAILtext in ANTLRParser destructor + + The ANTLRParser destructor now frees zzFAILtext. + + Problem and fix reported by Manfred Kogler (km cast.uni-linz.ac.at). + +#205. (Changed in MR16) DLGStringReset argument now const + + Changed: void DLGStringReset(DLGChar *s) {...} + To: void DLGStringReset(const DLGChar *s) {...} + + Suggested by Dale Davis (daldavis spectrace.com) + +#204. (Changed in MR15a) Change __WATCOM__ to __WATCOMC__ in pcctscfg.h + + Reported by Oleg Dashevskii (olegdash my-dejanews.com). + +#203. (Changed in MR15) Addition of sorcerer to distribution kit + + I have finally caved in to popular demand. The pccts 1.33mr15 + kit will include sorcerer. The separate sorcerer kit will be + discontinued. + +#202. (Changed) in MR15) Organization of MS Dev Studio Projects in Kit + + Previously there was one workspace that contained projects for + all three parts of pccts: antlr, dlg, and sorcerer. Now each + part (and directory) has its own workspace/project and there + is an additional workspace/project to build a library from the + .cpp files in the pccts/h directory. + + The library build will create pccts_debug.lib or pccts_release.lib + according to the configuration selected. + + If you don't want to build pccts 1.33MR15 you can download a + ready-to-run kit for win32 from http://www.polhode.com/win32.zip. + The ready-to-run for win32 includes executables, a pre-built static + library for the .cpp files in the pccts/h directory, and a sample + application + + You will need to define the environment variable PCCTS to point to + the root of the pccts directory hierarchy. + +#201. (Changed in MR15) Several fixes by K.J. Cummings (cummings peritus.com) + + Generation of SETJMP rather than SETJMP_H in gen.c. + + (Sor B19) Declaration of ref_vars_inits for ref_var_inits in + pccts/sorcerer/sorcerer.h. + +#200. (Changed in MR15) Remove operator=() in AToken.h + + User reported that WatCom couldn't handle use of + explicit operator =(). Replace with equivalent + using cast operator. + +#199. (Changed in MR15) Don't allow use of empty #tokclass + + Change antlr.g to disallow empty #tokclass sets. + + Reported by Manfred Kogler (km cast.uni-linz.ac.at). + +#198. Revised ANSI C grammar due to efforts by Manuel Kessler + + Manuel Kessler (mlkessler cip.physik.uni-wuerzburg.de) + + Allow trailing ... in function parameter lists. + Add bit fields. + Allow old-style function declarations. + Support cv-qualified pointers. + Better checking of combinations of type specifiers. + Release of memory for local symbols on scope exit. + Allow input file name on command line as well as by redirection. + + and other miscellaneous tweaks. + + This is not part of the pccts distribution kit. It must be + downloaded separately from: + + http://www.polhode.com/ansi_mr15.zip + +#197. (Changed in MR14) Resetting the lookahead buffer of the parser + + Explanation and fix by Sinan Karasu (sinan.karasu boeing.com) + + Consider the code used to prime the lookahead buffer LA(i) + of the parser when init() is called: + + void + ANTLRParser:: + prime_lookahead() + { + int i; + for(i=1;i<=LLk; i++) consume(); + dirty=0; + //lap = 0; // MR14 - Sinan Karasu (sinan.karusu boeing.com) + //labase = 0; // MR14 + labase=lap; // MR14 + } + + When the parser is instantiated, lap=0,labase=0 is set. + + The "for" loop runs LLk times. In consume(), lap = lap +1 (mod LLk) is + computed. Therefore, lap(before the loop) == lap (after the loop). + + Now the only problem comes in when one does an init() of the parser + after an Eof has been seen. At that time, lap could be non zero. + Assume it was lap==1. Now we do a prime_lookahead(). If LLk is 2, + then + + consume() + { + NLA = inputTokens->getToken()->getType(); + dirty--; + lap = (lap+1)&(LLk-1); + } + + or expanding NLA, + + token_type[lap&(LLk-1)]) = inputTokens->getToken()->getType(); + dirty--; + lap = (lap+1)&(LLk-1); + + so now we prime locations 1 and 2. In prime_lookahead it used to set + lap=0 and labase=0. Now, the next token will be read from location 0, + NOT 1 as it should have been. + + This was never caught before, because if a parser is just instantiated, + then lap and labase are 0, the offending assignment lines are + basically no-ops, since the for loop wraps around back to 0. + +#196. (Changed in MR14) Problems with "(alpha)? beta" guess + + Consider the following syntactic predicate in a grammar + with 2 tokens of lookahead (k=2 or ck=2): + + rule : ( alpha )? beta ; + alpha : S t ; + t : T U + | T + ; + beta : S t Z ; + + When antlr computes the prediction expression with one token + of lookahead for alts 1 and 2 of rule t it finds an ambiguity. + + Because the grammar has a lookahead of 2 it tries to compute + two tokens of lookahead for alts 1 and 2 of t. Alt 1 clearly + has a lookahead of (T U). Alt 2 is one token long so antlr + tries to compute the follow set of alt 2, which means finding + the things which can follow rule t in the context of (alpha)?. + This cannot be computed, because alpha is only part of a rule, + and antlr can't tell what part of beta is matched by alpha and + what part remains to be matched. Thus it impossible for antlr + to properly determine the follow set of rule t. + + Prior to 1.33MR14, the follow of (alpha)? was computed as + FIRST(beta) as a result of the internal representation of + guess blocks. + + With MR14 the follow set will be the empty set for that context. + + Normally, one expects a rule appearing in a guess block to also + appear elsewhere. When the follow context for this other use + is "ored" with the empty set, the context from the other use + results, and a reasonable follow context results. However if + there is *no* other use of the rule, or it is used in a different + manner then the follow context will be inaccurate - it was + inaccurate even before MR14, but it will be inaccurate in a + different way. + + For the example given earlier, a reasonable way to rewrite the + grammar: + + rule : ( alpha )? beta + alpha : S t ; + t : T U + | T + ; + beta : alpha Z ; + + If there are no other uses of the rule appearing in the guess + block it will generate a test for EOF - a workaround for + representing a null set in the lookahead tests. + + If you encounter such a problem you can use the -alpha option + to get additional information: + + line 2: error: not possible to compute follow set for alpha + in an "(alpha)? beta" block. + + With the antlr -alpha command line option the following information + is inserted into the generated file: + + #if 0 + + Trace of references leading to attempt to compute the follow set of + alpha in an "(alpha)? beta" block. It is not possible for antlr to + compute this follow set because it is not known what part of beta has + already been matched by alpha and what part remains to be matched. + + Rules which make use of the incorrect follow set will also be incorrect + + 1 #token T alpha/2 line 7 brief.g + 2 end alpha alpha/3 line 8 brief.g + 2 end (...)? block at start/1 line 2 brief.g + + #endif + + At the moment, with the -alpha option selected the program marks + any rules which appear in the trace back chain (above) as rules with + possible problems computing follow set. + + Reported by Greg Knapen (gregory.knapen bell.ca). + +#195. (Changed in MR14) #line directive not at column 1 + + Under certain circunstances a predicate test could generate + a #line directive which was not at column 1. + + Reported with fix by David Kågedal (davidk lysator.liu.se) + (http://www.lysator.liu.se/~davidk/). + +#194. (Changed in MR14) (C Mode only) Demand lookahead with #tokclass + + In C mode with the demand lookahead option there is a bug in the + code which handles matches for #tokclass (zzsetmatch and + zzsetmatch_wsig). + + The bug causes the lookahead pointer to get out of synchronization + with the current token pointer. + + The problem was reported with a fix by Ger Hobbelt (hobbelt axa.nl). + +#193. (Changed in MR14) Use of PCCTS_USE_NAMESPACE_STD + + The pcctscfg.h now contains the following definitions: + + #ifdef PCCTS_USE_NAMESPACE_STD + #define PCCTS_STDIO_H + #define PCCTS_STDLIB_H + #define PCCTS_STDARG_H + #define PCCTS_SETJMP_H + #define PCCTS_STRING_H + #define PCCTS_ASSERT_H + #define PCCTS_ISTREAM_H + #define PCCTS_IOSTREAM_H + #define PCCTS_NAMESPACE_STD namespace std {}; using namespace std; + #else + #define PCCTS_STDIO_H + #define PCCTS_STDLIB_H + #define PCCTS_STDARG_H + #define PCCTS_SETJMP_H + #define PCCTS_STRING_H + #define PCCTS_ASSERT_H + #define PCCTS_ISTREAM_H + #define PCCTS_IOSTREAM_H + #define PCCTS_NAMESPACE_STD + #endif + + The runtime support in pccts/h uses these pre-processor symbols + consistently. + + Also, antlr and dlg have been changed to generate code which uses + these pre-processor symbols rather than having the names of the + #include files hard-coded in the generated code. + + This required the addition of "#include pcctscfg.h" to a number of + files in pccts/h. + + It appears that this sometimes causes problems for MSVC 5 in + combination with the "automatic" option for pre-compiled headers. + In such cases disable the "automatic" pre-compiled headers option. + + Suggested by Hubert Holin (Hubert.Holin Bigfoot.com). + +#192. (Changed in MR14) Change setText() to accept "const ANTLRChar *" + + Changed ANTLRToken::setText(ANTLRChar *) to setText(const ANTLRChar *). + This allows literal strings to be used to initialize tokens. Since + the usual token implementation (ANTLRCommonToken) makes a copy of the + input string, this was an unnecessary limitation. + + Suggested by Bob McWhirter (bob netwrench.com). + +#191. (Changed in MR14) HP/UX aCC compiler compatibility problem + + Needed to explicitly declare zzINF_DEF_TOKEN_BUFFER_SIZE and + zzINF_BUFFER_TOKEN_CHUNK_SIZE as ints in pccts/h/AParser.cpp. + + Reported by David Cook (dcook bmc.com). + +#190. (Changed in MR14) IBM OS/2 CSet compiler compatibility problem + + Name conflict with "_cs" in pccts/h/ATokenBuffer.cpp + + Reported by David Cook (dcook bmc.com). + +#189. (Changed in MR14) -gxt switch in C mode + + The -gxt switch in C mode didn't work because of incorrect + initialization. + + Reported by Sinan Karasu (sinan boeing.com). + +#188. (Changed in MR14) Added pccts/h/DLG_stream_input.h + + This is a DLG stream class based on C++ istreams. + + Contributed by Hubert Holin (Hubert.Holin Bigfoot.com). + +#187. (Changed in MR14) Rename config.h to pcctscfg.h + + The PCCTS configuration file has been renamed from config.h to + pcctscfg.h. The problem with the original name is that it led + to name collisions when pccts parsers were combined with other + software. + + All of the runtime support routines in pccts/h/* have been + changed to use the new name. Existing software can continue + to use pccts/h/config.h. The contents of pccts/h/config.h is + now just "#include "pcctscfg.h". + + I don't have a record of the user who suggested this. + +#186. (Changed in MR14) Pre-processor symbol DllExportPCCTS class modifier + + Classes in the C++ runtime support routines are now declared: + + class DllExportPCCTS className .... + + By default, the pre-processor symbol is defined as the empty + string. This if for use by MSVC++ users to create DLL classes. + + Suggested by Manfred Kogler (km cast.uni-linz.ac.at). + +#185. (Changed in MR14) Option to not use PCCTS_AST base class for ASTBase + + Normally, the ASTBase class is derived from PCCTS_AST which contains + functions useful to Sorcerer. If these are not necessary then the + user can define the pre-processor symbol "PCCTS_NOT_USING_SOR" which + will cause the ASTBase class to replace references to PCCTS_AST with + references to ASTBase where necessary. + + The class ASTDoublyLinkedBase will contain a pure virtual function + shallowCopy() that was formerly defined in class PCCTS_AST. + + Suggested by Bob McWhirter (bob netwrench.com). + +#184. (Changed in MR14) Grammars with no tokens generate invalid tokens.h + + Reported by Hubert Holin (Hubert.Holin bigfoot.com). + +#183. (Changed in MR14) -f to specify file with names of grammar files + + In DEC/VMS it is difficult to specify very long command lines. + The -f option allows one to place the names of the grammar files + in a data file in order to bypass limitations of the DEC/VMS + command language interpreter. + + Addition supplied by Bernard Giroud (b_giroud decus.ch). + +#182. (Changed in MR14) Output directory option for DEC/VMS + + Fix some problems with the -o option under DEC/VMS. + + Fix supplied by Bernard Giroud (b_giroud decus.ch). + +#181. (Changed in MR14) Allow chars > 127 in DLGStringInput::nextChar() + + Changed DLGStringInput to cast the character using (unsigned char) + so that languages with character codes greater than 127 work + without changes. + + Suggested by Manfred Kogler (km cast.uni-linz.ac.at). + +#180. (Added in MR14) ANTLRParser::getEofToken() + + Added "ANTLRToken ANTLRParser::getEofToken() const" to match the + setEofToken routine. + + Requested by Manfred Kogler (km cast.uni-linz.ac.at). + +#179. (Fixed in MR14) Memory leak for BufFileInput subclass of DLGInputStream + + The BufFileInput class described in Item #142 neglected to release + the allocated buffer when an instance was destroyed. + + Reported by Manfred Kogler (km cast.uni-linz.ac.at). + +#178. (Fixed in MR14) Bug in "(alpha)? beta" guess blocks first sets + + In 1.33 vanilla, and all maintenance releases prior to MR14 + there is a bug in the handling of guess blocks which use the + "long" form: + + (alpha)? beta + + inside a (...)*, (...)+, or {...} block. + + This problem does *not* apply to the case where beta is omitted + or when the syntactic predicate is on the leading edge of an + alternative. + + The problem is that both alpha and beta are stored in the + syntax diagram, and that some analysis routines would fail + to skip the alpha portion when it was not on the leading edge. + Consider the following grammar with -ck 2: + + r : ( (A)? B )* C D + + | A B /* forces -ck 2 computation for old antlr */ + /* reports ambig for alts 1 & 2 */ + + | B C /* forces -ck 2 computation for new antlr */ + /* reports ambig for alts 1 & 3 */ + ; + + The prediction expression for the first alternative should be + LA(1)={B C} LA(2)={B C D}, but previous versions of antlr + would compute the prediction expression as LA(1)={A C} LA(2)={B D} + + Reported by Arpad Beszedes (beszedes inf.u-szeged.hu) who provided + a very clear example of the problem and identified the probable cause. + +#177. (Changed in MR14) #tokdefs and #token with regular expression + + In MR13 the change described by Item #162 caused an existing + feature of antlr to fail. Prior to the change it was possible + to give regular expression definitions and actions to tokens + which were defined via the #tokdefs directive. + + This now works again. + + Reported by Manfred Kogler (km cast.uni-linz.ac.at). + +#176. (Changed in MR14) Support for #line in antlr source code + + Note: this was implemented by Arpad Beszedes (beszedes inf.u-szeged.hu). + + In 1.33MR14 it is possible for a pre-processor to generate #line + directives in the antlr source and have those line numbers and file + names used in antlr error messages and in the #line directives + generated by antlr. + + The #line directive may appear in the following forms: + + #line ll "sss" xx xx ... + + where ll represents a line number, "sss" represents the name of a file + enclosed in quotation marks, and xxx are arbitrary integers. + + The following form (without "line") is not supported at the moment: + + # ll "sss" xx xx ... + + The result: + + zzline + + is replaced with ll from the # or #line directive + + FileStr[CurFile] + + is updated with the contents of the string (if any) + following the line number + + Note + ---- + The file-name string following the line number can be a complete + name with a directory-path. Antlr generates the output files from + the input file name (by replacing the extension from the file-name + with .c or .cpp). + + If the input file (or the file-name from the line-info) contains + a path: + + "../grammar.g" + + the generated source code will be placed in "../grammar.cpp" (i.e. + in the parent directory). This is inconvenient in some cases + (even the -o switch can not be used) so the path information is + removed from the #line directive. Thus, if the line-info was + + #line 2 "../grammar.g" + + then the current file-name will become "grammar.g" + + In this way, the generated source code according to the grammar file + will always be in the current directory, except when the -o switch + is used. + +#175. (Changed in MR14) Bug when guess block appears at start of (...)* + + In 1.33 vanilla and all maintenance releases prior to 1.33MR14 + there is a bug when a guess block appears at the start of a (...)+. + Consider the following k=1 (ck=1) grammar: + + rule : + ( (STAR)? ZIP )* ID ; + + Prior to 1.33MR14, the generated code resembled: + + ... + zzGUESS_BLOCK + while ( 1 ) { + if ( ! LA(1)==STAR) break; + zzGUESS + if ( !zzrv ) { + zzmatch(STAR); + zzCONSUME; + zzGUESS_DONE + zzmatch(ZIP); + zzCONSUME; + ... + + Note that the routine uses STAR for the prediction expression + rather than ZIP. With 1.33MR14 the generated code resembles: + + ... + while ( 1 ) { + if ( ! LA(1)==ZIP) break; + ... + + This problem existed only with (...)* blocks and was caused + by the slightly more complicated graph which represents (...)* + blocks. This caused the analysis routine to compute the first + set for the alpha part of the "(alpha)? beta" rather than the + beta part. + + Both (...)+ and {...} blocks handled the guess block correctly. + + Reported by Arpad Beszedes (beszedes inf.u-szeged.hu) who provided + a very clear example of the problem and identified the probable cause. + +#174. (Changed in MR14) Bug when action precedes syntactic predicate + + In 1.33 vanilla, and all maintenance releases prior to MR14, + there was a bug when a syntactic predicate was immediately + preceded by an action. Consider the following -ck 2 grammar: + + rule : + <> + (alpha)? beta C + | A B + ; + + alpha : A ; + beta : A B; + + Prior to MR14, the code generated for the first alternative + resembled: + + ... + zzGUESS + if ( !zzrv && LA(1)==A && LA(2)==A) { + alpha(); + zzGUESS_DONE + beta(); + zzmatch(C); + zzCONSUME; + } else { + ... + + The prediction expression (i.e. LA(1)==A && LA(2)==A) is clearly + wrong because LA(2) should be matched to B (first[2] of beta is {B}). + + With 1.33MR14 the prediction expression is: + + ... + if ( !zzrv && LA(1)==A && LA(2)==B) { + alpha(); + zzGUESS_DONE + beta(); + zzmatch(C); + zzCONSUME; + } else { + ... + + This will only affect users in which alpha is shorter than + than max(k,ck) and there is an action immediately preceding + the syntactic predicate. + + This problem was reported by reported by Arpad Beszedes + (beszedes inf.u-szeged.hu) who provided a very clear example + of the problem and identified the presence of the init-action + as the likely culprit. + +#173. (Changed in MR13a) -glms for Microsoft style filenames with -gl + + With the -gl option antlr generates #line directives using the + exact name of the input files specified on the command line. + An oddity of the Microsoft C and C++ compilers is that they + don't accept file names in #line directives containing "\" + even though these are names from the native file system. + + With -glms option, the "\" in file names appearing in #line + directives is replaced with a "/" in order to conform to + Microsoft compiler requirements. + + Reported by Erwin Achermann (erwin.achermann switzerland.org). + +#172. (Changed in MR13) \r\n in antlr source counted as one line + + Some MS software uses \r\n to indicate a new line. Antlr + now recognizes this in counting lines. + + Reported by Edward L. Hepler (elh ece.vill.edu). + +#171. (Changed in MR13) #tokclass L..U now allowed + + The following is now allowed: + + #tokclass ABC { A..B C } + + Reported by Dave Watola (dwatola amtsun.jpl.nasa.gov) + +#170. (Changed in MR13) Suppression for predicates with lookahead depth >1 + + In MR12 the capability for suppression of predicates with lookahead + depth=1 was introduced. With MR13 this had been extended to + predicates with lookahead depth > 1 and released for use by users + on an experimental basis. + + Consider the following grammar with -ck 2 and the predicate in rule + "a" with depth 2: + + r1 : (ab)* "@" + ; + + ab : a + | b + ; + + a : (A B)? => <>? A B C + ; + + b : A B C + ; + + Normally, the predicate would be hoisted into rule r1 in order to + determine whether to call rule "ab". However it should *not* be + hoisted because, even if p is false, there is a valid alternative + in rule b. With "-mrhoistk on" the predicate will be suppressed. + + If "-info p" command line option is present the following information + will appear in the generated code: + + while ( (LA(1)==A) + #if 0 + + Part (or all) of predicate with depth > 1 suppressed by alternative + without predicate + + pred << p(LATEXT(2))>>? + depth=k=2 ("=>" guard) rule a line 8 t1.g + tree context: + (root = A + B + ) + + The token sequence which is suppressed: ( A B ) + The sequence of references which generate that sequence of tokens: + + 1 to ab r1/1 line 1 t1.g + 2 ab ab/1 line 4 t1.g + 3 to b ab/2 line 5 t1.g + 4 b b/1 line 11 t1.g + 5 #token A b/1 line 11 t1.g + 6 #token B b/1 line 11 t1.g + + #endif + + A slightly more complicated example: + + r1 : (ab)* "@" + ; + + ab : a + | b + ; + + a : (A B)? => <>? (A B | D E) + ; + + b : <>? D E + ; + + + In this case, the sequence (D E) in rule "a" which lies behind + the guard is used to suppress the predicate with context (D E) + in rule b. + + while ( (LA(1)==A || LA(1)==D) + #if 0 + + Part (or all) of predicate with depth > 1 suppressed by alternative + without predicate + + pred << q(LATEXT(2))>>? + depth=k=2 rule b line 11 t2.g + tree context: + (root = D + E + ) + + The token sequence which is suppressed: ( D E ) + The sequence of references which generate that sequence of tokens: + + 1 to ab r1/1 line 1 t2.g + 2 ab ab/1 line 4 t2.g + 3 to a ab/1 line 4 t2.g + 4 a a/1 line 8 t2.g + 5 #token D a/1 line 8 t2.g + 6 #token E a/1 line 8 t2.g + + #endif + && + #if 0 + + pred << p(LATEXT(2))>>? + depth=k=2 ("=>" guard) rule a line 8 t2.g + tree context: + (root = A + B + ) + + #endif + + (! ( LA(1)==A && LA(2)==B ) || p(LATEXT(2)) ) { + ab(); + ... + +#169. (Changed in MR13) Predicate test optimization for depth=1 predicates + + When the MR12 generated a test of a predicate which had depth 1 + it would use the depth >1 routines, resulting in correct but + inefficient behavior. In MR13, a bit test is used. + +#168. (Changed in MR13) Token expressions in context guards + + The token expressions appearing in context guards such as: + + (A B)? => <>? someRule + + are computed during an early phase of antlr processing. As + a result, prior to MR13, complex expressions such as: + + ~B + L..U + ~L..U + TokClassName + ~TokClassName + + were not computed properly. This resulted in incorrect + context being computed for such expressions. + + In MR13 these context guards are verified for proper semantics + in the initial phase and then re-evaluated after complex token + expressions have been computed in order to produce the correct + behavior. + + Reported by Arpad Beszedes (beszedes inf.u-szeged.hu). + +#167. (Changed in MR13) ~L..U + + Prior to MR13, the complement of a token range was + not properly computed. + +#166. (Changed in MR13) token expression L..U + + The token U was represented as an unsigned char, restricting + the use of L..U to cases where U was assigned a token number + less than 256. This is corrected in MR13. + +#165. (Changed in MR13) option -newAST + + To create ASTs from an ANTLRTokenPtr antlr usually calls + "new AST(ANTLRTokenPtr)". This option generates a call + to "newAST(ANTLRTokenPtr)" instead. This allows a user + to define a parser member function to create an AST object. + + Similar changes for ASTBase::tmake and ASTBase::link were not + thought necessary since they do not create AST objects, only + use existing ones. + +#164. (Changed in MR13) Unused variable _astp + + For many compilations, we have lived with warnings about + the unused variable _astp. It turns out that this varible + can *never* be used because the code which references it was + commented out. + + This investigation was sparked by a note from Erwin Achermann + (erwin.achermann switzerland.org). + +#163. (Changed in MR13) Incorrect makefiles for testcpp examples + + All the examples in pccts/testcpp/* had incorrect definitions + in the makefiles for the symbol "CCC". Instead of CCC=CC they + had CC=$(CCC). + + There was an additional problem in testcpp/1/test.g due to the + change in ANTLRToken::getText() to a const member function + (Item #137). + + Reported by Maurice Mass (maas cuci.nl). + +#162. (Changed in MR13) Combining #token with #tokdefs + + When it became possible to change the print-name of a + #token (Item #148) it became useful to give a #token + statement whose only purpose was to giving a print name + to the #token. Prior to this change this could not be + combined with the #tokdefs feature. + +#161. (Changed in MR13) Switch -gxt inhibits generation of tokens.h + +#160. (Changed in MR13) Omissions in list of names for remap.h + + When a user selects the -gp option antlr creates a list + of macros in remap.h to rename some of the standard + antlr routines from zzXXX to userprefixXXX. + + There were number of omissions from the remap.h name + list related to the new trace facility. This was reported, + along with a fix, by Bernie Solomon (bernard ug.eds.com). + +#159. (Changed in MR13) Violations of classic C rules + + There were a number of violations of classic C style in + the distribution kit. This was reported, along with fixes, + by Bernie Solomon (bernard ug.eds.com). + +#158. (Changed in MR13) #header causes problem for pre-processors + + A user who runs the C pre-processor on antlr source suggested + that another syntax be allowed. With MR13 such directives + such as #header, #pragma, etc. may be written as "\#header", + "\#pragma", etc. For escaping pre-processor directives inside + a #header use something like the following: + + \#header + << + \#include + >> + +#157. (Fixed in MR13) empty error sets for rules with infinite recursion + + When the first set for a rule cannot be computed due to infinite + left recursion and it is the only alternative for a block then + the error set for the block would be empty. This would result + in a fatal error. + + Reported by Darin Creason (creason genedax.com) + +#156. (Changed in MR13) DLGLexerBase::getToken() now public + +#155. (Changed in MR13) Context behind predicates can suppress + + With -mrhoist enabled the context behind a guarded predicate can + be used to suppress other predicates. Consider the following grammar: + + r0 : (r1)+; + + r1 : rp + | rq + ; + rp : <

>? B ; + rq : (A)? => <>? (A|B); + + In earlier versions both predicates "p" and "q" would be hoisted into + rule r0. With MR12c predicate p is suppressed because the context which + follows predicate q includes "B" which can "cover" predicate "p". In + other words, in trying to decide in r0 whether to call r1, it doesn't + really matter whether p is false or true because, either way, there is + a valid choice within r1. + +#154. (Changed in MR13) Making hoist suppression explicit using <> + + A common error, even among experienced pccts users, is to code + an init-action to inhibit hoisting rather than a leading action. + An init-action does not inhibit hoisting. + + This was coded: + + rule1 : <<;>> rule2 + + This is what was meant: + + rule1 : <<;>> <<;>> rule2 + + With MR13, the user can code: + + rule1 : <<;>> <> rule2 + + The following will give an error message: + + rule1 : <> rule2 + + If the <> appears as an init-action rather than a leading + action an error message is issued. The meaning of an init-action + containing "nohoist" is unclear: does it apply to just one + alternative or to all alternatives ? + + + + + + + + + ------------------------------------------------------- + Note: Items #153 to #1 are now in a separate file named + CHANGES_FROM_133_BEFORE_MR13.txt + ------------------------------------------------------- diff --git a/Tools/Source/TianoTools/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt b/Tools/Source/TianoTools/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt new file mode 100644 index 0000000000..bba5ecdd64 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt @@ -0,0 +1,3666 @@ + + ------------------------------------------------------------ + This is the second part of a two part file. + This is a list of changes to pccts 1.33 prior to MR13 + For more recent information see CHANGES_FROM_133.txt + ------------------------------------------------------------ + + DISCLAIMER + + The software and these notes are provided "as is". They may include + typographical or technical errors and their authors disclaims all + liability of any kind or nature for damages due to error, fault, + defect, or deficiency regardless of cause. All warranties of any + kind, either express or implied, including, but not limited to, the + implied warranties of merchantability and fitness for a particular + purpose are disclaimed. + + +#153. (Changed in MR12b) Bug in computation of -mrhoist suppression set + + Consider the following grammar with k=1 and "-mrhoist on": + + r1 : (A)? => ((p>>? x /* l1 */ + | r2 /* l2 */ + ; + r2 : A /* l4 */ + | (B)? => <>? y /* l5 */ + ; + + In earlier versions the mrhoist routine would see that both l1 and + l2 contained predicates and would assume that this prevented either + from acting to suppress the other predicate. In the example above + it didn't realize the A at line l4 is capable of suppressing the + predicate at l1 even though alt l2 contains (indirectly) a predicate. + + This is fixed in MR12b. + + Reported by Reinier van den Born (reinier@vnet.ibm.com) + +#153. (Changed in MR12a) Bug in computation of -mrhoist suppression set + + An oversight similar to that described in Item #152 appeared in + the computation of the set that "covered" a predicate. If a + predicate expression included a term such as p=AND(q,r) the context + of p was taken to be context(q) & context(r), when it should have + been context(q) | context(r). This is fixed in MR12a. + +#152. (Changed in MR12) Bug in generation of predicate expressions + + The primary purpose for MR12 is to make quite clear that MR11 is + obsolete and to fix the bug related to predicate expressions. + + In MR10 code was added to optimize the code generated for + predicate expression tests. Unfortunately, there was a + significant oversight in the code which resulted in a bug in + the generation of code for predicate expression tests which + contained predicates combined using AND: + + r0 : (r1)* "@" ; + r1 : (AAA)? => <

>? r2 ; + r2 : (BBB)? => <>? Q + | (BBB)? => <>? Q + ; + + In MR11 (and MR10 when using "-mrhoist on") the code generated + for r0 to predict r1 would be equivalent to: + + if ( LA(1)==Q && + (LA(1)==AAA && LA(1)==BBB) && + ( p && ( q || r )) ) { + + This is incorrect because it expresses the idea that LA(1) + *must* be AAA in order to attempt r1, and *must* be BBB to + attempt r2. The result was that r1 became unreachable since + both condition can not be simultaneously true. + + The general philosophy of code generation for predicates + can be summarized as follows: + + a. If the context is true don't enter an alt + for which the corresponding predicate is false. + + If the context is false then it is okay to enter + the alt without evaluating the predicate at all. + + b. A predicate created by ORing of predicates has + context which is the OR of their individual contexts. + + c. A predicate created by ANDing of predicates has + (surprise) context which is the OR of their individual + contexts. + + d. Apply these rules recursively. + + e. Remember rule (a) + + The correct code should express the idea that *if* LA(1) is + AAA then p must be true to attempt r1, but if LA(1) is *not* + AAA then it is okay to attempt r1, provided that *if* LA(1) is + BBB then one of q or r must be true. + + if ( LA(1)==Q && + ( !(LA(1)==AAA || LA(1)==BBB) || + ( ! LA(1) == AAA || p) && + ( ! LA(1) == BBB || q || r ) ) ) { + + I believe this is fixed in MR12. + + Reported by Reinier van den Born (reinier@vnet.ibm.com) + +#151a. (Changed in MR12) ANTLRParser::getLexer() + + As a result of several requests, I have added public methods to + get a pointer to the lexer belonging to a parser. + + ANTLRTokenStream *ANTLRParser::getLexer() const + + Returns a pointer to the lexer being used by the + parser. ANTLRTokenStream is the base class of + DLGLexer + + ANTLRTokenStream *ANTLRTokenBuffer::getLexer() const + + Returns a pointer to the lexer being used by the + ANTLRTokenBuffer. ANTLRTokenStream is the base + class of DLGLexer + + You must manually cast the ANTLRTokenStream to your program's + lexer class. Because the name of the lexer's class is not fixed. + Thus it is impossible to incorporate it into the DLGLexerBase + class. + +#151b.(Changed in MR12) ParserBlackBox member getLexer() + + The template class ParserBlackBox now has a member getLexer() + which returns a pointer to the lexer. + +#150. (Changed in MR12) syntaxErrCount and lexErrCount now public + + See Item #127 for more information. + +#149. (Changed in MR12) antlr option -info o (letter o for orphan) + + If there is more than one rule which is not referenced by any + other rule then all such rules are listed. This is useful for + alerting one to rules which are not used, but which can still + contribute to ambiguity. For example: + + start : a Z ; + unused: a A ; + a : (A)+ ; + + will cause an ambiguity report for rule "a" which will be + difficult to understand if the user forgets about rule "unused" + simply because it is not used in the grammar. + +#148. (Changed in MR11) #token names appearing in zztokens,token_tbl + + In a #token statement like the following: + + #token Plus "\+" + + the string "Plus" appears in the zztokens array (C mode) and + token_tbl (C++ mode). This string is used in most error + messages. In MR11 one has the option of using some other string, + (e.g. "+") in those tables. + + In MR11 one can write: + + #token Plus ("+") "\+" + #token RP ("(") "\(" + #token COM ("comment begin") "/\*" + + A #token statement is allowed to appear in more than one #lexclass + with different regular expressions. However, the token name appears + only once in the zztokens/token_tbl array. This means that only + one substitute can be specified for a given #token name. The second + attempt to define a substitute name (different from the first) will + result in an error message. + +#147. (Changed in MR11) Bug in follow set computation + + There is a bug in 1.33 vanilla and all maintenance releases + prior to MR11 in the computation of the follow set. The bug is + different than that described in Item #82 and probably more + common. It was discovered in the ansi.g grammar while testing + the "ambiguity aid" (Item #119). The search for a bug started + when the ambiguity aid was unable to discover the actual source + of an ambiguity reported by antlr. + + The problem appears when an optimization of the follow set + computation is used inappropriately. The result is that the + follow set used is the "worst case". In other words, the error + can lead to false reports of ambiguity. The good news is that + if you have a grammar in which you have addressed all reported + ambiguities you are ok. The bad news is that you may have spent + time fixing ambiguities that were not real, or used k=2 when + ck=2 might have been sufficient, and so on. + + The following grammar demonstrates the problem: + + ------------------------------------------------------------ + expr : ID ; + + start : stmt SEMI ; + + stmt : CASE expr COLON + | expr SEMI + | plain_stmt + ; + + plain_stmt : ID COLON ; + ------------------------------------------------------------ + + When compiled with k=1 and ck=2 it will report: + + warning: alts 2 and 3 of the rule itself ambiguous upon + { IDENTIFIER }, { COLON } + + When antlr analyzes "stmt" it computes the first[1] set of all + alternatives. It finds an ambiguity between alts 2 and 3 for ID. + It then computes the first[2] set for alternatives 2 and 3 to resolve + the ambiguity. In computing the first[2] set of "expr" (which is + only one token long) it needs to determine what could follow "expr". + Under a certain combination of circumstances antlr forgets that it + is trying to analyze "stmt" which can only be followed by SEMI and + adds to the first[2] set of "expr" the "global" follow set (including + "COLON") which could follow "expr" (under other conditions) in the + phrase "CASE expr COLON". + +#146. (Changed in MR11) Option -treport for locating "difficult" alts + + It can be difficult to determine which alternatives are causing + pccts to work hard to resolve an ambiguity. In some cases the + ambiguity is successfully resolved after much CPU time so there + is no message at all. + + A rough measure of the amount of work being peformed which is + independent of the CPU speed and system load is the number of + tnodes created. Using "-info t" gives information about the + total number of tnodes created and the peak number of tnodes. + + Tree Nodes: peak 1300k created 1416k lost 0 + + It also puts in the generated C or C++ file the number of tnodes + created for a rule (at the end of the rule). However this + information is not sufficient to locate the alternatives within + a rule which are causing the creation of tnodes. + + Using: + + antlr -treport 100000 .... + + causes antlr to list on stdout any alternatives which require the + creation of more than 100,000 tnodes, along with the lookahead sets + for those alternatives. + + The following is a trivial case from the ansi.g grammar which shows + the format of the report. This report might be of more interest + in cases where 1,000,000 tuples were created to resolve the ambiguity. + + ------------------------------------------------------------------------- + There were 0 tuples whose ambiguity could not be resolved + by full lookahead + There were 157 tnodes created to resolve ambiguity between: + + Choice 1: statement/2 line 475 file ansi.g + Choice 2: statement/3 line 476 file ansi.g + + Intersection of lookahead[1] sets: + + IDENTIFIER + + Intersection of lookahead[2] sets: + + LPARENTHESIS COLON AMPERSAND MINUS + STAR PLUSPLUS MINUSMINUS ONESCOMPLEMENT + NOT SIZEOF OCTALINT DECIMALINT + HEXADECIMALINT FLOATONE FLOATTWO IDENTIFIER + STRING CHARACTER + ------------------------------------------------------------------------- + +#145. (Documentation) Generation of Expression Trees + + Item #99 was misleading because it implied that the optimization + for tree expressions was available only for trees created by + predicate expressions and neglected to mention that it required + the use of "-mrhoist on". The optimization applies to tree + expressions created for grammars with k>1 and for predicates with + lookahead depth >1. + + In MR11 the optimized version is always used so the -mrhoist on + option need not be specified. + +#144. (Changed in MR11) Incorrect test for exception group + + In testing for a rule's exception group the label a pointer + is compared against '\0'. The intention is "*pointer". + + Reported by Jeffrey C. Fried (Jeff@Fried.net). + +#143. (Changed in MR11) Optional ";" at end of #token statement + + Fixes problem of: + + #token X "x" + + << + parser action + >> + + Being confused with: + + #token X "x" <> + +#142. (Changed in MR11) class BufFileInput subclass of DLGInputStream + + Alexey Demakov (demakov@kazbek.ispras.ru) has supplied class + BufFileInput derived from DLGInputStream which provides a + function lookahead(char *string) to test characters in the + input stream more than one character ahead. + + The default amount of lookahead is specified by the constructor + and defaults to 8 characters. This does *not* include the one + character of lookahead maintained internally by DLG in member "ch" + and which is not available for testing via BufFileInput::lookahead(). + + This is a useful class for overcoming the one-character-lookahead + limitation of DLG without resorting to a lexer capable of + backtracking (like flex) which is not integrated with antlr as is + DLG. + + There are no restrictions on copying or using BufFileInput.* except + that the authorship and related information must be retained in the + source code. + + The class is located in pccts/h/BufFileInput.* of the kit. + +#141. (Changed in MR11) ZZDEBUG_CONSUME for ANTLRParser::consume() + + A debug aid has been added to file ANTLRParser::consume() in + file AParser.cpp: + + #ifdef ZZDEBUG_CONSUME_ACTION + zzdebug_consume_action(); + #endif + + Suggested by Sramji Ramanathan (ps@kumaran.com). + +#140. (Changed in MR11) #pred to define predicates + + +---------------------------------------------------+ + | Note: Assume "-prc on" for this entire discussion | + +---------------------------------------------------+ + + A problem with predicates is that each one is regarded as + unique and capable of disambiguating cases where two + alternatives have identical lookahead. For example: + + rule : <>? A + | <>? A + ; + + will not cause any error messages or warnings to be issued + by earlier versions of pccts. To compare the text of the + predicates is an incomplete solution. + + In 1.33MR11 I am introducing the #pred statement in order to + solve some problems with predicates. The #pred statement allows + one to give a symbolic name to a "predicate literal" or a + "predicate expression" in order to refer to it in other predicate + expressions or in the rules of the grammar. + + The predicate literal associated with a predicate symbol is C + or C++ code which can be used to test the condition. A + predicate expression defines a predicate symbol in terms of other + predicate symbols using "!", "&&", and "||". A predicate symbol + can be defined in terms of a predicate literal, a predicate + expression, or *both*. + + When a predicate symbol is defined with both a predicate literal + and a predicate expression, the predicate literal is used to generate + code, but the predicate expression is used to check for two + alternatives with identical predicates in both alternatives. + + Here are some examples of #pred statements: + + #pred IsLabel <>? + #pred IsLocalVar <>? + #pred IsGlobalVar <>? + #pred IsVar <>? IsLocalVar || IsGlobalVar + #pred IsScoped <>? IsLabel || IsLocalVar + + I hope that the use of EBNF notation to describe the syntax of the + #pred statement will not cause problems for my readers (joke). + + predStatement : "#pred" + CapitalizedName + ( + "<>?" + | "<>?" predOrExpr + | predOrExpr + ) + ; + + predOrExpr : predAndExpr ( "||" predAndExpr ) * ; + + predAndExpr : predPrimary ( "&&" predPrimary ) * ; + + predPrimary : CapitalizedName + | "!" predPrimary + | "(" predOrExpr ")" + ; + + What is the purpose of this nonsense ? + + To understand how predicate symbols help, you need to realize that + predicate symbols are used in two different ways with two different + goals. + + a. Allow simplification of predicates which have been combined + during predicate hoisting. + + b. Allow recognition of identical predicates which can't disambiguate + alternatives with common lookahead. + + First we will discuss goal (a). Consider the following rule: + + rule0: rule1 + | ID + | ... + ; + + rule1: rule2 + | rule3 + ; + + rule2: <>? ID ; + rule3: <>? ID ; + + When the predicates in rule2 and rule3 are combined by hoisting + to create a prediction expression for rule1 the result is: + + if ( LA(1)==ID + && ( isX(LATEXT(1) || !isX(LATEXT(1) ) ) { rule1(); ... + + This is inefficient, but more importantly, can lead to false + assumptions that the predicate expression distinguishes the rule1 + alternative with some other alternative with lookahead ID. In + MR11 one can write: + + #pred IsX <>? + + ... + + rule2: <>? ID ; + rule3: <>? ID ; + + During hoisting MR11 recognizes this as a special case and + eliminates the predicates. The result is a prediction + expression like the following: + + if ( LA(1)==ID ) { rule1(); ... + + Please note that the following cases which appear to be equivalent + *cannot* be simplified by MR11 during hoisting because the hoisting + logic only checks for a "!" in the predicate action, not in the + predicate expression for a predicate symbol. + + *Not* equivalent and is not simplified during hoisting: + + #pred IsX <>? + #pred NotX <>? + ... + rule2: <>? ID ; + rule3: <>? ID ; + + *Not* equivalent and is not simplified during hoisting: + + #pred IsX <>? + #pred NotX !IsX + ... + rule2: <>? ID ; + rule3: <>? ID ; + + Now we will discuss goal (b). + + When antlr discovers that there is a lookahead ambiguity between + two alternatives it attempts to resolve the ambiguity by searching + for predicates in both alternatives. In the past any predicate + would do, even if the same one appeared in both alternatives: + + rule: <>? X + | <>? X + ; + + The #pred statement is a start towards solving this problem. + During ambiguity resolution (*not* predicate hoisting) the + predicates for the two alternatives are expanded and compared. + Consider the following example: + + #pred Upper <>? + #pred Lower <>? + #pred Alpha <>? Upper || Lower + + rule0: rule1 + | <>? ID + ; + + rule1: + | rule2 + | rule3 + ... + ; + + rule2: <>? ID; + rule3: <>? ID; + + The definition of #pred Alpha expresses: + + a. to test the predicate use the C code "isAlpha(LATEXT(1))" + + b. to analyze the predicate use the information that + Alpha is equivalent to the union of Upper and Lower, + + During ambiguity resolution the definition of Alpha is expanded + into "Upper || Lower" and compared with the predicate in the other + alternative, which is also "Upper || Lower". Because they are + identical MR11 will report a problem. + + ------------------------------------------------------------------------- + t10.g, line 5: warning: the predicates used to disambiguate rule rule0 + (file t10.g alt 1 line 5 and alt 2 line 6) + are identical when compared without context and may have no + resolving power for some lookahead sequences. + ------------------------------------------------------------------------- + + If you use the "-info p" option the output file will contain: + + +----------------------------------------------------------------------+ + |#if 0 | + | | + |The following predicates are identical when compared without | + | lookahead context information. For some ambiguous lookahead | + | sequences they may not have any power to resolve the ambiguity. | + | | + |Choice 1: rule0/1 alt 1 line 5 file t10.g | + | | + | The original predicate for choice 1 with available context | + | information: | + | | + | OR expr | + | | + | pred << Upper>>? | + | depth=k=1 rule rule2 line 14 t10.g | + | set context: | + | ID | + | | + | pred << Lower>>? | + | depth=k=1 rule rule3 line 15 t10.g | + | set context: | + | ID | + | | + | The predicate for choice 1 after expansion (but without context | + | information): | + | | + | OR expr | + | | + | pred << isUpper(LATEXT(1))>>? | + | depth=k=1 rule line 1 t10.g | + | | + | pred << isLower(LATEXT(1))>>? | + | depth=k=1 rule line 2 t10.g | + | | + | | + |Choice 2: rule0/2 alt 2 line 6 file t10.g | + | | + | The original predicate for choice 2 with available context | + | information: | + | | + | pred << Alpha>>? | + | depth=k=1 rule rule0 line 6 t10.g | + | set context: | + | ID | + | | + | The predicate for choice 2 after expansion (but without context | + | information): | + | | + | OR expr | + | | + | pred << isUpper(LATEXT(1))>>? | + | depth=k=1 rule line 1 t10.g | + | | + | pred << isLower(LATEXT(1))>>? | + | depth=k=1 rule line 2 t10.g | + | | + | | + |#endif | + +----------------------------------------------------------------------+ + + The comparison of the predicates for the two alternatives takes + place without context information, which means that in some cases + the predicates will be considered identical even though they operate + on disjoint lookahead sets. Consider: + + #pred Alpha + + rule1: <>? ID + | <>? Label + ; + + Because the comparison of predicates takes place without context + these will be considered identical. The reason for comparing + without context is that otherwise it would be necessary to re-evaluate + the entire predicate expression for each possible lookahead sequence. + This would require more code to be written and more CPU time during + grammar analysis, and it is not yet clear whether anyone will even make + use of the new #pred facility. + + A temporary workaround might be to use different #pred statements + for predicates you know have different context. This would avoid + extraneous warnings. + + The above example might be termed a "false positive". Comparison + without context will also lead to "false negatives". Consider the + following example: + + #pred Alpha + #pred Beta + + rule1: <>? A + | rule2 + ; + + rule2: <>? A + | <>? B + ; + + The predicate used for alt 2 of rule1 is (Alpha || Beta). This + appears to be different than the predicate Alpha used for alt1. + However, the context of Beta is B. Thus when the lookahead is A + Beta will have no resolving power and Alpha will be used for both + alternatives. Using the same predicate for both alternatives isn't + very helpful, but this will not be detected with 1.33MR11. + + To properly handle this the predicate expression would have to be + evaluated for each distinct lookahead context. + + To determine whether two predicate expressions are identical is + difficult. The routine may fail to identify identical predicates. + + The #pred feature also compares predicates to see if a choice between + alternatives which is resolved by a predicate which makes the second + choice unreachable. Consider the following example: + + #pred A <>? + #pred B <>? + #pred A_or_B A || B + + r : s + | t + ; + s : <>? ID + ; + t : <>? ID + ; + + ---------------------------------------------------------------------------- + t11.g, line 5: warning: the predicate used to disambiguate the + first choice of rule r + (file t11.g alt 1 line 5 and alt 2 line 6) + appears to "cover" the second predicate when compared without context. + The second predicate may have no resolving power for some lookahead + sequences. + ---------------------------------------------------------------------------- + +#139. (Changed in MR11) Problem with -gp in C++ mode + + The -gp option to add a prefix to rule names did not work in + C++ mode. This has been fixed. + + Reported by Alexey Demakov (demakov@kazbek.ispras.ru). + +#138. (Changed in MR11) Additional makefiles for non-MSVC++ MS systems + + Sramji Ramanathan (ps@kumaran.com) has supplied makefiles for + building antlr and dlg with Win95/NT development tools that + are not based on MSVC5. They are pccts/antlr/AntlrMS.mak and + pccts/dlg/DlgMS.mak. + + The first line of the makefiles require a definition of PCCTS_HOME. + + These are in additiion to the AntlrMSVC50.* and DlgMSVC50.* + supplied by Jeff Vincent (JVincent@novell.com). + +#137. (Changed in MR11) Token getType(), getText(), getLine() const members + + -------------------------------------------------------------------- + If you use ANTLRCommonToken this change probably does not affect you. + -------------------------------------------------------------------- + + For a long time it has bothered me that these accessor functions + in ANTLRAbstractToken were not const member functions. I have + refrained from changing them because it require users to modify + existing token class definitions which are derived directly + from ANTLRAbstractToken. I think it is now time. + + For those who are not used to C++, a "const member function" is a + member function which does not modify its own object - the thing + to which "this" points. This is quite different from a function + which does not modify its arguments + + Most token definitions based on ANTLRAbstractToken have something like + the following in order to create concrete definitions of the pure + virtual methods in ANTLRAbstractToken: + + class MyToken : public ANTLRAbstractToken { + ... + ANTLRTokenType getType() {return _type; } + int getLine() {return _line; } + ANTLRChar * getText() {return _text; } + ... + } + + The required change is simply to put "const" following the function + prototype in the header (.h file) and the definition file (.cpp if + it is not inline): + + class MyToken : public ANTLRAbstractToken { + ... + ANTLRTokenType getType() const {return _type; } + int getLine() const {return _line; } + ANTLRChar * getText() const {return _text; } + ... + } + + This was originally proposed a long time ago by Bruce + Guenter (bruceg@qcc.sk.ca). + +#136. (Changed in MR11) Added getLength() to ANTLRCommonToken + + Classes ANTLRCommonToken and ANTLRCommonTokenNoRefCountToken + now have a member function: + + int getLength() const { return strlen(getText()) } + + Suggested by Sramji Ramanathan (ps@kumaran.com). + +#135. (Changed in MR11) Raised antlr's own default ZZLEXBUFSIZE to 8k + +#134a. (ansi_mr10.zip) T.J. Parr's ANSI C grammar made 1.33MR11 compatible + + There is a typographical error in the definition of BITWISEOREQ: + + #token BITWISEOREQ "!=" should be "\|=" + + When this change is combined with the bugfix to the follow set cache + problem (Item #147) and a minor rearrangement of the grammar + (Item #134b) it becomes a k=1 ck=2 grammar. + +#134b. (ansi_mr10.zip) T.J. Parr's ANSI C grammar made 1.33MR11 compatible + + The following changes were made in the ansi.g grammar (along with + using -mrhoist on): + + ansi.g + ====== + void tracein(char *) ====> void tracein(const char *) + void traceout(char *) ====> void traceout(const char *) + + getType()==IDENTIFIER ? isTypeName(LT(1)->getText()) : 1>>? + ====> <getText())>>? + + <<(LT(1)->getType()==LPARENTHESIS && LT(2)->getType()==IDENTIFIER) ? \ + isTypeName(LT(2)->getText()) : 1>>? + ====> (LPARENTHESIS IDENTIFIER)? => <getText())>>? + + <<(LT(1)->getType()==LPARENTHESIS && LT(2)->getType()==IDENTIFIER) ? \ + isTypeName(LT(2)->getText()) : 1>>? + ====> (LPARENTHESIS IDENTIFIER)? => <getText())>>? + + added to init(): traceOptionValueDefault=0; + added to init(): traceOption(-1); + + change rule "statement": + + statement + : plain_label_statement + | case_label_statement + | <<;>> expression SEMICOLON + | compound_statement + | selection_statement + | iteration_statement + | jump_statement + | SEMICOLON + ; + + plain_label_statement + : IDENTIFIER COLON statement + ; + + case_label_statement + : CASE constant_expression COLON statement + | DEFAULT COLON statement + ; + + support.cpp + =========== + void tracein(char *) ====> void tracein(const char *) + void traceout(char *) ====> void traceout(const char *) + + added to tracein(): ANTLRParser::tracein(r); // call superclass method + added to traceout(): ANTLRParser::traceout(r); // call superclass method + + Makefile + ======== + added to AFLAGS: -mrhoist on -prc on + +#133. (Changed in 1.33MR11) Make trace options public in ANTLRParser + + In checking T.J. Parr's ANSI C grammar for compatibility with + 1.33MR11 discovered that it was inconvenient to have the + trace facilities with protected access. + +#132. (Changed in 1.33MR11) Recognition of identical predicates in alts + + Prior to 1.33MR11, there would be no ambiguity warning when the + very same predicate was used to disambiguate both alternatives: + + test: ref B + | ref C + ; + + ref : <>? A + + In 1.33MR11 this will cause the warning: + + warning: the predicates used to disambiguate rule test + (file v98.g alt 1 line 1 and alt 2 line 2) + are identical and have no resolving power + + ----------------- Note ----------------- + + This is different than the following case + + test: <>? A B + | <>? A C + ; + + In this case there are two distinct predicates + which have exactly the same text. In the first + example there are two references to the same + predicate. The problem represented by this + grammar will be addressed later. + +#131. (Changed in 1.33MR11) Case insensitive command line options + + Command line switches like "-CC" and keywords like "on", "off", + and "stdin" are no longer case sensitive in antlr, dlg, and sorcerer. + +#130. (Changed in 1.33MR11) Changed ANTLR_VERSION to int from string + + The ANTLR_VERSION was not an integer, making it difficult to + perform conditional compilation based on the antlr version. + + Henceforth, ANTLR_VERSION will be: + + (base_version * 10000) + release number + + thus 1.33MR11 will be: 133*100+11 = 13311 + + Suggested by Rainer Janssen (Rainer.Janssen@Informatik.Uni-Oldenburg.DE). + +#129. (Changed in 1.33MR11) Addition of ANTLR_VERSION to .h + + The following code is now inserted into .h amd + stdpccts.h: + + #ifndef ANTLR_VERSION + #define ANTLR_VERSION 13311 + #endif + + Suggested by Rainer Janssen (Rainer.Janssen@Informatik.Uni-Oldenburg.DE) + +#128. (Changed in 1.33MR11) Redundant predicate code in (<>? ...)+ + + Prior to 1.33MR11, the following grammar would generate + redundant tests for the "while" condition. + + rule2 : (<>? X)+ X + | B + ; + + The code would resemble: + + if (LA(1)==X) { + if (pred) { + do { + if (!pred) {zzfailed_pred(" pred");} + zzmatch(X); zzCONSUME; + } while (LA(1)==X && pred && pred); + } else {... + + With 1.33MR11 the redundant predicate test is omitted. + +#127. (Changed in 1.33MR11) + + Count Syntax Errors Count DLG Errors + ------------------- ---------------- + + C++ mode ANTLRParser:: DLGLexerBase:: + syntaxErrCount lexErrCount + C mode zzSyntaxErrCount zzLexErrCount + + The C mode variables are global and initialized to 0. + They are *not* reset to 0 automatically when antlr is + restarted. + + The C++ mode variables are public. They are initialized + to 0 by the constructors. They are *not* reset to 0 by the + ANTLRParser::init() method. + + Suggested by Reinier van den Born (reinier@vnet.ibm.com). + +#126. (Changed in 1.33MR11) Addition of #first <<...>> + + The #first <<...>> inserts the specified text in the output + files before any other #include statements required by pccts. + The only things before the #first text are comments and + a #define ANTLR_VERSION. + + Requested by and Esa Pulkkinen (esap@cs.tut.fi) and Alexin + Zoltan (alexin@inf.u-szeged.hu). + +#125. (Changed in 1.33MR11) Lookahead for (guard)? && <

>? predicates + + When implementing the new style of guard predicate (Item #113) + in 1.33MR10 I decided to temporarily ignore the problem of + computing the "narrowest" lookahead context. + + Consider the following k=1 grammar: + + start : a + | b + ; + + a : (A)? && <>? ab ; + b : (B)? && <>? ab ; + + ab : A | B ; + + In MR10 the context for both "a" and "b" was {A B} because this is + the first set of rule "ab". Normally, this is not a problem because + the predicate which follows the guard inhibits any ambiguity report + by antlr. + + In MR11 the first set for rule "a" is {A} and for rule "b" it is {B}. + +#124. A Note on the New "&&" Style Guarded Predicates + + I've been asked several times, "What is the difference between + the old "=>" style guard predicates and the new style "&&" guard + predicates, and how do you choose one over the other" ? + + The main difference is that the "=>" does not apply the + predicate if the context guard doesn't match, whereas + the && form always does. What is the significance ? + + If you have a predicate which is not on the "leading edge" + it cannot be hoisted. Suppose you need a predicate that + looks at LA(2). You must introduce it manually. The + classic example is: + + castExpr : + LP typeName RP + | .... + ; + + typeName : <>? ID + | STRUCT ID + ; + + The problem is that typeName isn't on the leading edge + of castExpr, so the predicate isTypeName won't be hoisted into + castExpr to help make a decision on which production to choose. + + The *first* attempt to fix it is this: + + castExpr : + <>? + LP typeName RP + | .... + ; + + Unfortunately, this won't work because it ignores + the problem of STRUCT. The solution is to apply + isTypeName() in castExpr if LA(2) is an ID and + don't apply it when LA(2) is STRUCT: + + castExpr : + (LP ID)? => <>? + LP typeName RP + | .... + ; + + In conclusion, the "=>" style guarded predicate is + useful when: + + a. the tokens required for the predicate + are not on the leading edge + b. there are alternatives in the expression + selected by the predicate for which the + predicate is inappropriate + + If (b) were false, then one could use a simple + predicate (assuming "-prc on"): + + castExpr : + <>? + LP typeName RP + | .... + ; + + typeName : <>? ID + ; + + So, when do you use the "&&" style guarded predicate ? + + The new-style "&&" predicate should always be used with + predicate context. The context guard is in ADDITION to + the automatically computed context. Thus it useful for + predicates which depend on the token type for reasons + other than context. + + The following example is contributed by Reinier van den Born + (reinier@vnet.ibm.com). + + +-------------------------------------------------------------------------+ + | This grammar has two ways to call functions: | + | | + | - a "standard" call syntax with parens and comma separated args | + | - a shell command like syntax (no parens and spacing separated args) | + | | + | The former also allows a variable to hold the name of the function, | + | the latter can also be used to call external commands. | + | | + | The grammar (simplified) looks like this: | + | | + | fun_call : ID "(" { expr ("," expr)* } ")" | + | /* ID is function name */ | + | | "@" ID "(" { expr ("," expr)* } ")" | + | /* ID is var containing fun name */ | + | ; | + | | + | command : ID expr* /* ID is function name */ | + | | path expr* /* path is external command name */ | + | ; | + | | + | path : ID /* left out slashes and such */ | + | | "@" ID /* ID is environment var */ | + | ; | + | | + | expr : .... | + | | "(" expr ")"; | + | | + | call : fun_call | + | | command | + | ; | + | | + | Obviously the call is wildly ambiguous. This is more or less how this | + | is to be resolved: | + | | + | A call begins with an ID or an @ followed by an ID. | + | | + | If it is an ID and if it is an ext. command name -> command | + | if followed by a paren -> fun_call | + | otherwise -> command | + | | + | If it is an @ and if the ID is a var name -> fun_call | + | otherwise -> command | + | | + | One can implement these rules quite neatly using && predicates: | + | | + | call : ("@" ID)? && <>? fun_call | + | | (ID)? && <>? command | + | | (ID "(")? fun_call | + | | command | + | ; | + | | + | This can be done better, so it is not an ideal example, but it | + | conveys the principle. | + +-------------------------------------------------------------------------+ + +#123. (Changed in 1.33MR11) Correct definition of operators in ATokPtr.h + + The return value of operators in ANTLRTokenPtr: + + changed: unsigned ... operator !=(...) + to: int ... operator != (...) + changed: unsigned ... operator ==(...) + to: int ... operator == (...) + + Suggested by R.A. Nelson (cowboy@VNET.IBM.COM) + +#122. (Changed in 1.33MR11) Member functions to reset DLG in C++ mode + + void DLGFileReset(FILE *f) { input = f; found_eof = 0; } + void DLGStringReset(DLGChar *s) { input = s; p = &input[0]; } + + Supplied by R.A. Nelson (cowboy@VNET.IBM.COM) + +#121. (Changed in 1.33MR11) Another attempt to fix -o (output dir) option + + Another attempt is made to improve the -o option of antlr, dlg, + and sorcerer. This one by JVincent (JVincent@novell.com). + + The current rule: + + a. If -o is not specified than any explicit directory + names are retained. + + b. If -o is specified than the -o directory name overrides any + explicit directory names. + + c. The directory name of the grammar file is *not* stripped + to create the main output file. However it is stil subject + to override by the -o directory name. + +#120. (Changed in 1.33MR11) "-info f" output to stdout rather than stderr + + Added option 0 (e.g. "-info 0") which is a noop. + +#119. (Changed in 1.33MR11) Ambiguity aid for grammars + + The user can ask for additional information on ambiguities reported + by antlr to stdout. At the moment, only one ambiguity report can + be created in an antlr run. + + This feature is enabled using the "-aa" (Ambiguity Aid) option. + + The following options control the reporting of ambiguities: + + -aa ruleName Selects reporting by name of rule + -aa lineNumber Selects reporting by line number + (file name not compared) + + -aam Selects "multiple" reporting for a token + in the intersection set of the + alternatives. + + For instance, the token ID may appear dozens + of times in various paths as the program + explores the rules which are reachable from + the point of an ambiguity. With option -aam + every possible path the search program + encounters is reported. + + Without -aam only the first encounter is + reported. This may result in incomplete + information, but the information may be + sufficient and much shorter. + + -aad depth Selects the depth of the search. + The default value is 1. + + The number of paths to be searched, and the + size of the report can grow geometrically + with the -ck value if a full search for all + contributions to the source of the ambiguity + is explored. + + The depth represents the number of tokens + in the lookahead set which are matched against + the set of ambiguous tokens. A depth of 1 + means that the search stops when a lookahead + sequence of just one token is matched. + + A k=1 ck=6 grammar might generate 5,000 items + in a report if a full depth 6 search is made + with the Ambiguity Aid. The source of the + problem may be in the first token and obscured + by the volume of data - I hesitate to call + it information. + + When the user selects a depth > 1, the search + is first performed at depth=1 for both + alternatives, then depth=2 for both alternatives, + etc. + + Sample output for rule grammar in antlr.g itself: + + +---------------------------------------------------------------------+ + | Ambiguity Aid | + | | + | Choice 1: grammar/70 line 632 file a.g | + | Choice 2: grammar/82 line 644 file a.g | + | | + | Intersection of lookahead[1] sets: | + | | + | "\}" "class" "#errclass" "#tokclass" | + | | + | Choice:1 Depth:1 Group:1 ("#errclass") | + | 1 in (...)* block grammar/70 line 632 a.g | + | 2 to error grammar/73 line 635 a.g | + | 3 error error/1 line 894 a.g | + | 4 #token "#errclass" error/2 line 895 a.g | + | | + | Choice:1 Depth:1 Group:2 ("#tokclass") | + | 2 to tclass grammar/74 line 636 a.g | + | 3 tclass tclass/1 line 937 a.g | + | 4 #token "#tokclass" tclass/2 line 938 a.g | + | | + | Choice:1 Depth:1 Group:3 ("class") | + | 2 to class_def grammar/75 line 637 a.g | + | 3 class_def class_def/1 line 669 a.g | + | 4 #token "class" class_def/3 line 671 a.g | + | | + | Choice:1 Depth:1 Group:4 ("\}") | + | 2 #token "\}" grammar/76 line 638 a.g | + | | + | Choice:2 Depth:1 Group:5 ("#errclass") | + | 1 in (...)* block grammar/83 line 645 a.g | + | 2 to error grammar/93 line 655 a.g | + | 3 error error/1 line 894 a.g | + | 4 #token "#errclass" error/2 line 895 a.g | + | | + | Choice:2 Depth:1 Group:6 ("#tokclass") | + | 2 to tclass grammar/94 line 656 a.g | + | 3 tclass tclass/1 line 937 a.g | + | 4 #token "#tokclass" tclass/2 line 938 a.g | + | | + | Choice:2 Depth:1 Group:7 ("class") | + | 2 to class_def grammar/95 line 657 a.g | + | 3 class_def class_def/1 line 669 a.g | + | 4 #token "class" class_def/3 line 671 a.g | + | | + | Choice:2 Depth:1 Group:8 ("\}") | + | 2 #token "\}" grammar/96 line 658 a.g | + +---------------------------------------------------------------------+ + + For a linear lookahead set ambiguity (where k=1 or for k>1 but + when all lookahead sets [i] with i>? A ; + c : A ; + + Prior to 1.33MR10 the code generated for "start" would resemble: + + while { + if (LA(1)==A && + (!LA(1)==A || isUpper())) { + a(); + } + }; + + This code is wrong because it makes rule "c" unreachable from + "start". The essence of the problem is that antlr fails to + recognize that there can be a valid alternative within "a" even + when the predicate <>? is false. + + In 1.33MR10 with -mrhoist the hoisting of the predicate into + "start" is suppressed because it recognizes that "c" can + cover all the cases where the predicate is false: + + while { + if (LA(1)==A) { + a(); + } + }; + + With the antlr "-info p" switch the user will receive information + about the predicate suppression in the generated file: + + -------------------------------------------------------------- + #if 0 + + Hoisting of predicate suppressed by alternative without predicate. + The alt without the predicate includes all cases where + the predicate is false. + + WITH predicate: line 7 v1.g + WITHOUT predicate: line 7 v1.g + + The context set for the predicate: + + A + + The lookahead set for the alt WITHOUT the semantic predicate: + + A + + The predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 9 v1.g + set context: + A + tree context: null + + Chain of referenced rules: + + #0 in rule start (line 5 v1.g) to rule a + #1 in rule a (line 7 v1.g) + + #endif + -------------------------------------------------------------- + + A predicate can be suppressed by a combination of alternatives + which, taken together, cover a predicate: + + start : (a)* "@" ; + + a : b | ca | cb | cc ; + + b : <>? ( A | B | C ) ; + + ca : A ; + cb : B ; + cc : C ; + + Consider a more complex example in which "c" covers only part of + a predicate: + + start : (a)* "@" ; + + a : b + | c + ; + + b : <>? + ( A + | X + ); + + c : A + ; + + Prior to 1.33MR10 the code generated for "start" would resemble: + + while { + if ( (LA(1)==A || LA(1)==X) && + (! (LA(1)==A || LA(1)==X) || isUpper()) { + a(); + } + }; + + With 1.33MR10 and -mrhoist the predicate context is restricted to + the non-covered lookahead. The code resembles: + + while { + if ( (LA(1)==A || LA(1)==X) && + (! (LA(1)==X) || isUpper()) { + a(); + } + }; + + With the antlr "-info p" switch the user will receive information + about the predicate restriction in the generated file: + + -------------------------------------------------------------- + #if 0 + + Restricting the context of a predicate because of overlap + in the lookahead set between the alternative with the + semantic predicate and one without + Without this restriction the alternative without the predicate + could not be reached when input matched the context of the + predicate and the predicate was false. + + WITH predicate: line 11 v4.g + WITHOUT predicate: line 12 v4.g + + The original context set for the predicate: + + A X + + The lookahead set for the alt WITHOUT the semantic predicate: + + A + + The intersection of the two sets + + A + + The original predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 15 v4.g + set context: + A X + tree context: null + + The new (modified) form of the predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 15 v4.g + set context: + X + tree context: null + + #endif + -------------------------------------------------------------- + + The bad news about -mrhoist: + + (a) -mrhoist does not analyze predicates with lookahead + depth > 1. + + (b) -mrhoist does not look past a guarded predicate to + find context which might cover other predicates. + + For these cases you might want to use syntactic predicates. + When a semantic predicate fails during guess mode the guess + fails and the next alternative is tried. + + Limitation (a) is illustrated by the following example: + + start : (stmt)* EOF ; + + stmt : cast + | expr + ; + cast : <>? LP ID RP ; + + expr : LP ID RP ; + + This is not much different from the first example, except that + it requires two tokens of lookahead context to determine what + to do. This predicate is NOT suppressed because the current version + is unable to handle predicates with depth > 1. + + A predicate can be combined with other predicates during hoisting. + In those cases the depth=1 predicates are still handled. Thus, + in the following example the isUpper() predicate will be suppressed + by line #4 when hoisted from "bizarre" into "start", but will still + be present in "bizarre" in order to predict "stmt". + + start : (bizarre)* EOF ; // #1 + // #2 + bizarre : stmt // #3 + | A // #4 + ; + + stmt : cast + | expr + ; + + cast : <>? LP ID RP ; + + expr : LP ID RP ; + | <>? A + + Limitation (b) is illustrated by the following example of a + context guarded predicate: + + rule : (A)? <

>? // #1 + (A // #2 + |B // #3 + ) // #4 + | <> B // #5 + ; + + Recall that this means that when the lookahead is NOT A then + the predicate "p" is ignored and it attempts to match "A|B". + Ideally, the "B" at line #3 should suppress predicate "q". + However, the current version does not attempt to look past + the guard predicate to find context which might suppress other + predicates. + + In some cases -mrhoist will lead to the reporting of ambiguities + which were not visible before: + + start : (a)* "@"; + a : bc | d; + bc : b | c ; + + b : <>? A; + c : A ; + + d : A ; + + In this case there is a true ambiguity in "a" between "bc" and "d" + which can both match "A". Without -mrhoist the predicate in "b" + is hoisted into "a" and there is no ambiguity reported. However, + with -mrhoist, the predicate in "b" is suppressed by "c" (as it + should be) making the ambiguity in "a" apparent. + + The motivations for these changes were hoisting problems reported + by Reinier van den Born (reinier@vnet.ibm.com) and several others. + +#116. (Changed in 1.33MR10) C++ mode: tracein/traceout rule name is (const char *) + + The prototype for C++ mode routine tracein (and traceout) has changed from + "char *" to "const char *". + +#115. (Changed in 1.33MR10) Using guess mode with exception handlers in C mode + + The definition of the C mode macros zzmatch_wsig and zzsetmatch_wsig + neglected to consider guess mode. When control passed to the rule's + parse exception handler the routine would exit without ever closing the + guess block. This would lead to unpredictable behavior. + + In 1.33MR10 the behavior of exceptions in C mode and C++ mode should be + identical. + +#114. (Changed in 1.33MR10) difference in [zz]resynch() between C and C++ modes + + There was a slight difference in the way C and C++ mode resynchronized + following a parsing error. The C routine would sometimes skip an extra + token before attempting to resynchronize. + + The C routine was changed to match the C++ routine. + +#113. (Changed in 1.33MR10) new context guarded pred: (g)? && <

>? expr + + The existing context guarded predicate: + + rule : (guard)? => <

>? expr + | next_alternative + ; + + generates code which resembles: + + if (lookahead(expr) && (!guard || pred)) { + expr() + } else .... + + This is not suitable for some applications because it allows + expr() to be invoked when the predicate is false. This is + intentional because it is meant to mimic automatically computed + predicate context. + + The new context guarded predicate uses the guard information + differently because it has a different goal. Consider: + + rule : (guard)? && <

>? expr + | next_alternative + ; + + The new style of context guarded predicate is equivalent to: + + rule : <>? expr + | next_alternative + ; + + It generates code which resembles: + + if (lookahead(expr) && guard && pred) { + expr(); + } else ... + + Both forms of guarded predicates severely restrict the form of + the context guard: it can contain no rule references, no + (...)*, no (...)+, and no {...}. It may contain token and + token class references, and alternation ("|"). + + Addition for 1.33MR11: in the token expression all tokens must + be at the same height of the token tree: + + (A ( B | C))? && ... is ok (all height 2) + (A ( B | ))? && ... is not ok (some 1, some 2) + (A B C D | E F G H)? && ... is ok (all height 4) + (A B C D | E )? && ... is not ok (some 4, some 1) + + This restriction is required in order to properly compute the lookahead + set for expressions like: + + rule1 : (A B C)? && <>? rule2 ; + rule2 : (A|X) (B|Y) (C|Z); + + This addition was suggested by Rienier van den Born (reinier@vnet.ibm.com) + +#112. (Changed in 1.33MR10) failed validation predicate in C guess mode + + John Lilley (jlilley@empathy.com) suggested that failed validation + predicates abort a guess rather than reporting a failed error. + This was installed in C++ mode (Item #4). Only now was it noticed + that the fix was never installed for C mode. + +#111. (Changed in 1.33MR10) moved zzTRACEIN to before init action + + When the antlr -gd switch is present antlr generates calls to + zzTRACEIN at the start of a rule and zzTRACEOUT at the exit + from a rule. Prior to 1.33MR10 Tthe call to zzTRACEIN was + after the init-action, which could cause confusion because the + init-actions were reported with the name of the enclosing rule, + rather than the active rule. + +#110. (Changed in 1.33MR10) antlr command line copied to generated file + + The antlr command line is now copied to the generated file near + the start. + +#109. (Changed in 1.33MR10) improved trace information + + The quality of the trace information provided by the "-gd" + switch has been improved significantly. Here is an example + of the output from a test program. It shows the rule name, + the first token of lookahead, the call depth, and the guess + status: + + exit rule gusxx {"?"} depth 2 + enter rule gusxx {"?"} depth 2 + enter rule gus1 {"o"} depth 3 guessing + guess done - returning to rule gus1 {"o"} at depth 3 + (guess mode continues - an enclosing guess is still active) + guess done - returning to rule gus1 {"Z"} at depth 3 + (guess mode continues - an enclosing guess is still active) + exit rule gus1 {"Z"} depth 3 guessing + guess done - returning to rule gusxx {"o"} at depth 2 (guess mode ends) + enter rule gus1 {"o"} depth 3 + guess done - returning to rule gus1 {"o"} at depth 3 (guess mode ends) + guess done - returning to rule gus1 {"Z"} at depth 3 (guess mode ends) + exit rule gus1 {"Z"} depth 3 + line 1: syntax error at "Z" missing SC + ... + + Rule trace reporting is controlled by the value of the integer + [zz]traceOptionValue: when it is positive tracing is enabled, + otherwise it is disabled. Tracing during guess mode is controlled + by the value of the integer [zz]traceGuessOptionValue. When + it is positive AND [zz]traceOptionValue is positive rule trace + is reported in guess mode. + + The values of [zz]traceOptionValue and [zz]traceGuessOptionValue + can be adjusted by subroutine calls listed below. + + Depending on the presence or absence of the antlr -gd switch + the variable [zz]traceOptionValueDefault is set to 0 or 1. When + the parser is initialized or [zz]traceReset() is called the + value of [zz]traceOptionValueDefault is copied to [zz]traceOptionValue. + The value of [zz]traceGuessOptionValue is always initialzed to 1, + but, as noted earlier, nothing will be reported unless + [zz]traceOptionValue is also positive. + + When the parser state is saved/restored the value of the trace + variables are also saved/restored. If a restore causes a change in + reporting behavior from on to off or vice versa this will be reported. + + When the -gd option is selected, the macro "#define zzTRACE_RULES" + is added to appropriate output files. + + C++ mode + -------- + int traceOption(int delta) + int traceGuessOption(int delta) + void traceReset() + int traceOptionValueDefault + + C mode + -------- + int zzTraceOption(int delta) + int zzTraceGuessOption(int delta) + void zzTraceReset() + int zzTraceOptionValueDefault + + The argument "delta" is added to the traceOptionValue. To + turn on trace when inside a particular rule one: + + rule : <> + ( + rest-of-rule + ) + <> + ; /* fail clause */ <> + + One can use the same idea to turn *off* tracing within a + rule by using a delta of (-1). + + An improvement in the rule trace was suggested by Sramji + Ramanathan (ps@kumaran.com). + +#108. A Note on Deallocation of Variables Allocated in Guess Mode + + NOTE + ------------------------------------------------------ + This mechanism only works for heap allocated variables + ------------------------------------------------------ + + The rewrite of the trace provides the machinery necessary + to properly free variables or undo actions following a + failed guess. + + The macro zzUSER_GUESS_HOOK(guessSeq,zzrv) is expanded + as part of the zzGUESS macro. When a guess is opened + the value of zzrv is 0. When a longjmp() is executed to + undo the guess, the value of zzrv will be 1. + + The macro zzUSER_GUESS_DONE_HOOK(guessSeq) is expanded + as part of the zzGUESS_DONE macro. This is executed + whether the guess succeeds or fails as part of closing + the guess. + + The guessSeq is a sequence number which is assigned to each + guess and is incremented by 1 for each guess which becomes + active. It is needed by the user to associate the start of + a guess with the failure and/or completion (closing) of a + guess. + + Guesses are nested. They must be closed in the reverse + of the order that they are opened. + + In order to free memory used by a variable during a guess + a user must write a routine which can be called to + register the variable along with the current guess sequence + number provided by the zzUSER_GUESS_HOOK macro. If the guess + fails, all variables tagged with the corresponding guess + sequence number should be released. This is ugly, but + it would require a major rewrite of antlr 1.33 to use + some mechanism other than setjmp()/longjmp(). + + The order of calls for a *successful* guess would be: + + zzUSER_GUESS_HOOK(guessSeq,0); + zzUSER_GUESS_DONE_HOOK(guessSeq); + + The order of calls for a *failed* guess would be: + + zzUSER_GUESS_HOOK(guessSeq,0); + zzUSER_GUESS_HOOK(guessSeq,1); + zzUSER_GUESS_DONE_HOOK(guessSeq); + + The default definitions of these macros are empty strings. + + Here is an example in C++ mode. The zzUSER_GUESS_HOOK and + zzUSER_GUESS_DONE_HOOK macros and myGuessHook() routine + can be used without change in both C and C++ versions. + + ---------------------------------------------------------------------- + << + + #include "AToken.h" + + typedef ANTLRCommonToken ANTLRToken; + + #include "DLGLexer.h" + + int main() { + + { + DLGFileInput in(stdin); + DLGLexer lexer(&in,2000); + ANTLRTokenBuffer pipe(&lexer,1); + ANTLRCommonToken aToken; + P parser(&pipe); + + lexer.setToken(&aToken); + parser.init(); + parser.start(); + }; + + fclose(stdin); + fclose(stdout); + return 0; + } + + >> + + << + char *s=NULL; + + #undef zzUSER_GUESS_HOOK + #define zzUSER_GUESS_HOOK(guessSeq,zzrv) myGuessHook(guessSeq,zzrv); + #undef zzUSER_GUESS_DONE_HOOK + #define zzUSER_GUESS_DONE_HOOK(guessSeq) myGuessHook(guessSeq,2); + + void myGuessHook(int guessSeq,int zzrv) { + if (zzrv == 0) { + fprintf(stderr,"User hook: starting guess #%d\n",guessSeq); + } else if (zzrv == 1) { + free (s); + s=NULL; + fprintf(stderr,"User hook: failed guess #%d\n",guessSeq); + } else if (zzrv == 2) { + free (s); + s=NULL; + fprintf(stderr,"User hook: ending guess #%d\n",guessSeq); + }; + } + + >> + + #token A "a" + #token "[\t \ \n]" <> + + class P { + + start : (top)+ + ; + + top : (which) ? <> + | other <> + ; <> + + which : which2 + ; + + which2 : which3 + ; + which3 + : (label)? <> + | (global)? <> + | (exclamation)? <> + ; + + label : <getText());>> A ":" ; + + global : <getText());>> A "::" ; + + exclamation : <getText());>> A "!" ; + + other : <getText());>> "other" ; + + } + ---------------------------------------------------------------------- + + This is a silly example, but illustrates the idea. For the input + "a ::" with tracing enabled the output begins: + + ---------------------------------------------------------------------- + enter rule "start" depth 1 + enter rule "top" depth 2 + User hook: starting guess #1 + enter rule "which" depth 3 guessing + enter rule "which2" depth 4 guessing + enter rule "which3" depth 5 guessing + User hook: starting guess #2 + enter rule "label" depth 6 guessing + guess failed + User hook: failed guess #2 + guess done - returning to rule "which3" at depth 5 (guess mode continues + - an enclosing guess is still active) + User hook: ending guess #2 + User hook: starting guess #3 + enter rule "global" depth 6 guessing + exit rule "global" depth 6 guessing + guess done - returning to rule "which3" at depth 5 (guess mode continues + - an enclosing guess is still active) + User hook: ending guess #3 + enter rule "global" depth 6 guessing + exit rule "global" depth 6 guessing + exit rule "which3" depth 5 guessing + exit rule "which2" depth 4 guessing + exit rule "which" depth 3 guessing + guess done - returning to rule "top" at depth 2 (guess mode ends) + User hook: ending guess #1 + enter rule "which" depth 3 + ..... + ---------------------------------------------------------------------- + + Remember: + + (a) Only init-actions are executed during guess mode. + (b) A rule can be invoked multiple times during guess mode. + (c) If the guess succeeds the rule will be called once more + without guess mode so that normal actions will be executed. + This means that the init-action might need to distinguish + between guess mode and non-guess mode using the variable + [zz]guessing. + +#107. (Changed in 1.33MR10) construction of ASTs in guess mode + + Prior to 1.33MR10, when using automatic AST construction in C++ + mode for a rule, an AST would be constructed for elements of the + rule even while in guess mode. In MR10 this no longer occurs. + +#106. (Changed in 1.33MR10) guess variable confusion + + In C++ mode a guess which failed always restored the parser state + using zzGUESS_DONE as part of zzGUESS_FAIL. Prior to 1.33MR10, + C mode required an explicit call to zzGUESS_DONE after the + call to zzGUESS_FAIL. + + Consider: + + rule : (alpha)? beta + | ... + ; + + The generated code resembles: + + zzGUESS + if (!zzrv && LA(1)==ID) { <==== line #1 + alpha + zzGUESS_DONE + beta + } else { + if (! zzrv) zzGUESS_DONE <==== line #2a + .... + + However, in some cases line #2 was rendered: + + if (guessing) zzGUESS_DONE <==== line #2b + + This would work for simple test cases, but would fail in + some cases where there was a guess while another guess was active. + One kind of failure would be to match up the zzGUESS_DONE at line + #2b with the "outer" guess which was still active. The outer + guess would "succeed" when only the inner guess should have + succeeded. + + In 1.33MR10 the behavior of zzGUESS and zzGUESS_FAIL in C and + and C++ mode should be identical. + + The same problem appears in 1.33 vanilla in some places. For + example: + + start : { (sub)? } ; + + or: + + start : ( + B + | ( sub )? + | C + )+ + ; + + generates incorrect code. + + The general principle is: + + (a) use [zz]guessing only when deciding between a call to zzFAIL + or zzGUESS_FAIL + + (b) use zzrv in all other cases + + This problem was discovered while testing changes to item #105. + I believe this is now fixed. My apologies. + +#105. (Changed in 1.33MR10) guess block as single alt of (...)+ + + Prior to 1.33MR10 the following constructs: + + rule_plus : ( + (sub)? + )+ + ; + + rule_star : ( + (sub)? + )* + ; + + generated incorrect code for the guess block (which could result + in runtime errors) because of an incorrect optimization of a + block with only a single alternative. + + The fix caused some changes to the fix described in Item #49 + because there are now three code generation sequences for (...)+ + blocks containing a guess block: + + a. single alternative which is a guess block + b. multiple alternatives in which the last is a guess block + c. all other cases + + Forms like "rule_star" can have unexpected behavior when there + is a syntax error: if the subrule "sub" is not matched *exactly* + then "rule_star" will consume no tokens. + + Reported by Esa Pulkkinen (esap@cs.tut.fi). + +#104. (Changed in 1.33MR10) -o option for dlg + + There was problem with the code added by item #74 to handle the + -o option of dlg. This should fix it. + +#103. (Changed in 1.33MR10) ANDed semantic predicates + + Rescinded. + + The optimization was a mistake. + The resulting problem is described in Item #150. + +#102. (Changed in 1.33MR10) allow "class parser : .... {" + + The syntax of the class statement ("class parser-name {") + has been extended to allow for the specification of base + classes. An arbirtrary number of tokens may now appear + between the class name and the "{". They are output + again when the class declaration is generated. For + example: + + class Parser : public MyBaseClassANTLRparser { + + This was suggested by a user, but I don't have a record + of who it was. + +#101. (Changed in 1.33MR10) antlr -info command line switch + + -info + + p - extra predicate information in generated file + + t - information about tnode use: + at the end of each rule in generated file + summary on stderr at end of program + + m - monitor progress + prints name of each rule as it is started + flushes output at start of each rule + + f - first/follow set information to stdout + + 0 - no operation (added in 1.33MR11) + + The options may be combined and may appear in any order. + For example: + + antlr -info ptm -CC -gt -mrhoist on mygrammar.g + +#100a. (Changed in 1.33MR10) Predicate tree simplification + + When the same predicates can be referenced in more than one + alternative of a block large predicate trees can be formed. + + The difference that these optimizations make is so dramatic + that I have decided to use it even when -mrhoist is not selected. + + Consider the following grammar: + + start : ( all )* ; + + all : a + | d + | e + | f + ; + + a : c A B + | c A C + ; + + c : <>? + ; + + d : <>? B C + ; + + e : <>? B C + ; + + f : e X Y + ; + + In rule "a" there is a reference to rule "c" in both alternatives. + The length of the predicate AAA is k=2 and it can be followed in + alternative 1 only by (A B) while in alternative 2 it can be + followed only by (A C). Thus they do not have identical context. + + In rule "all" the alternatives which refer to rules "e" and "f" allow + elimination of the duplicate reference to predicate CCC. + + The table below summarized the kind of simplification performed by + 1.33MR10. In the table, X and Y stand for single predicates + (not trees). + + (OR X (OR Y (OR Z))) => (OR X Y Z) + (AND X (AND Y (AND Z))) => (AND X Y Z) + + (OR X (... (OR X Y) ... )) => (OR X (... Y ... )) + (AND X (... (AND X Y) ... )) => (AND X (... Y ... )) + (OR X (... (AND X Y) ... )) => (OR X (... ... )) + (AND X (... (OR X Y) ... )) => (AND X (... ... )) + + (AND X) => X + (OR X) => X + + In a test with a complex grammar for a real application, a predicate + tree with six OR nodes and 12 leaves was reduced to "(OR X Y Z)". + + In 1.33MR10 there is a greater effort to release memory used + by predicates once they are no longer in use. + +#100b. (Changed in 1.33MR10) Suppression of extra predicate tests + + The following optimizations require that -mrhoist be selected. + + It is relatively easy to optimize the code generated for predicate + gates when they are of the form: + + (AND X Y Z ...) + or (OR X Y Z ...) + + where X, Y, Z, and "..." represent individual predicates (leaves) not + predicate trees. + + If the predicate is an AND the contexts of the X, Y, Z, etc. are + ANDed together to create a single Tree context for the group and + context tests for the individual predicates are suppressed: + + -------------------------------------------------- + Note: This was incorrect. The contexts should be + ORed together. This has been fixed. A more + complete description is available in item #152. + --------------------------------------------------- + + Optimization 1: (AND X Y Z ...) + + Suppose the context for Xtest is LA(1)==LP and the context for + Ytest is LA(1)==LP && LA(2)==ID. + + Without the optimization the code would resemble: + + if (lookaheadContext && + !(LA(1)==LP && LA(1)==LP && LA(2)==ID) || + ( (! LA(1)==LP || Xtest) && + (! (LA(1)==LP || LA(2)==ID) || Xtest) + )) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==LP && LA(2)==ID) || (Xtest && Ytest) {... + + Optimization 2: (OR X Y Z ...) with identical contexts + + Suppose the context for Xtest is LA(1)==ID and for Ytest + the context is also LA(1)==ID. + + Without the optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==ID || LA(1)==ID) || + (LA(1)==ID && Xtest) || + (LA(1)==ID && Ytest) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + (! LA(1)==ID) || (Xtest || Ytest) {... + + Optimization 3: (OR X Y Z ...) with distinct contexts + + Suppose the context for Xtest is LA(1)==ID and for Ytest + the context is LA(1)==LP. + + Without the optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==ID || LA(1)==LP) || + (LA(1)==ID && Xtest) || + (LA(1)==LP && Ytest) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + (zzpf=0, + (LA(1)==ID && (zzpf=1) && Xtest) || + (LA(1)==LP && (zzpf=1) && Ytest) || + !zzpf) { + + These may appear to be of similar complexity at first, + but the non-optimized version contains two tests of each + context while the optimized version contains only one + such test, as well as eliminating some of the inverted + logic (" !(...) || "). + + Optimization 4: Computation of predicate gate trees + + When generating code for the gates of predicate expressions + antlr 1.33 vanilla uses a recursive procedure to generate + "&&" and "||" expressions for testing the lookahead. As each + layer of the predicate tree is exposed a new set of "&&" and + "||" expressions on the lookahead are generated. In many + cases the lookahead being tested has already been tested. + + With -mrhoist a lookahead tree is computed for the entire + lookahead expression. This means that predicates with identical + context or context which is a subset of another predicate's + context disappear. + + This is especially important for predicates formed by rules + like the following: + + uppperCaseVowel : <>? vowel; + vowel: : <>? LETTERS; + + These predicates are combined using AND since both must be + satisfied for rule upperCaseVowel. They have identical + context which makes this optimization very effective. + + The affect of Items #100a and #100b together can be dramatic. In + a very large (but real world) grammar one particular predicate + expression was reduced from an (unreadable) 50 predicate leaves, + 195 LA(1) terms, and 5500 characters to an (easily comprehensible) + 3 predicate leaves (all different) and a *single* LA(1) term. + +#99. (Changed in 1.33MR10) Code generation for expression trees + + Expression trees are used for k>1 grammars and predicates with + lookahead depth >1. This optimization must be enabled using + "-mrhoist on". (Clarification added for 1.33MR11). + + In the processing of expression trees, antlr can generate long chains + of token comparisons. Prior to 1.33MR10 there were many redundant + parenthesis which caused problems for compilers which could handle + expressions of only limited complexity. For example, to test an + expression tree (root R A B C D), antlr would generate something + resembling: + + (LA(1)==R && (LA(2)==A || (LA(2)==B || (LA(2)==C || LA(2)==D))))) + + If there were twenty tokens to test then there would be twenty + parenthesis at the end of the expression. + + In 1.33MR10 the generated code for tree expressions resembles: + + (LA(1)==R && (LA(2)==A || LA(2)==B || LA(2)==C || LA(2)==D)) + + For "complex" expressions the output is indented to reflect the LA + number being tested: + + (LA(1)==R + && (LA(2)==A || LA(2)==B || LA(2)==C || LA(2)==D + || LA(2)==E || LA(2)==F) + || LA(1)==S + && (LA(2)==G || LA(2)==H)) + + + Suggested by S. Bochnak (S.Bochnak@@microTool.com.pl), + +#98. (Changed in 1.33MR10) Option "-info p" + + When the user selects option "-info p" the program will generate + detailed information about predicates. If the user selects + "-mrhoist on" additional detail will be provided explaining + the promotion and suppression of predicates. The output is part + of the generated file and sandwiched between #if 0/#endif statements. + + Consider the following k=1 grammar: + + start : ( all ) * ; + + all : ( a + | b + ) + ; + + a : c B + ; + + c : <>? + | B + ; + + b : <>? X + ; + + Below is an excerpt of the output for rule "start" for the three + predicate options (off, on, and maintenance release style hoisting). + + For those who do not wish to use the "-mrhoist on" option for code + generation the option can be used in a "diagnostic" mode to provide + valuable information: + + a. where one should insert null actions to inhibit hoisting + b. a chain of rule references which shows where predicates are + being hoisted + + ====================================================================== + Example of "-info p" with "-mrhoist on" + ====================================================================== + #if 0 + + Hoisting of predicate suppressed by alternative without predicate. + The alt without the predicate includes all cases where the + predicate is false. + + WITH predicate: line 11 v36.g + WITHOUT predicate: line 12 v36.g + + The context set for the predicate: + + B + + The lookahead set for alt WITHOUT the semantic predicate: + + B + + The predicate: + + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + B + tree context: null + + Chain of referenced rules: + + #0 in rule start (line 1 v36.g) to rule all + #1 in rule all (line 3 v36.g) to rule a + #2 in rule a (line 8 v36.g) to rule c + #3 in rule c (line 11 v36.g) + + #endif + && + #if 0 + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + X + tree context: null + + #endif + ====================================================================== + Example of "-info p" with the default -prc setting ( "-prc off") + ====================================================================== + #if 0 + + OR + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + nil + tree context: null + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + nil + tree context: null + + #endif + ====================================================================== + Example of "-info p" with "-prc on" and "-mrhoist off" + ====================================================================== + #if 0 + + OR + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + B + tree context: null + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + X + tree context: null + + #endif + ====================================================================== + +#97. (Fixed in 1.33MR10) "Predicate applied for more than one ... " + + In 1.33 vanilla, the grammar listed below produced this message for + the first alternative (only) of rule "b": + + warning: predicate applied for >1 lookahead 1-sequences + [you may only want one lookahead 1-sequence to apply. + Try using a context guard '(...)? =>' + + In 1.33MR10 the message is issued for both alternatives. + + top : (a)*; + a : b | c ; + + b : <>? ( AAA | BBB ) + | <>? ( XXX | YYY ) + ; + + c : AAA | XXX; + +#96. (Fixed in 1.33MR10) Guard predicates ignored when -prc off + + Prior to 1.33MR10, guard predicate code was not generated unless + "-prc on" was selected. + + This was incorrect, since "-prc off" (the default) is supposed to + disable only AUTOMATIC computation of predicate context, not the + programmer specified context supplied by guard predicates. + +#95. (Fixed in 1.33MR10) Predicate guard context length was k, not max(k,ck) + + Prior to 1.33MR10, predicate guards were computed to k tokens rather + than max(k,ck). Consider the following grammar: + + a : ( A B C)? => <>? (A|X) (B|Y) (C|Z) ; + + The code generated by 1.33 vanilla with "-k 1 -ck 3 -prc on" + for the predicate in "a" resembles: + + if ( (! LA(1)==A) || AAA(LATEXT(1))) {... + + With 1.33MR10 and the same options the code resembles: + + if ( (! (LA(1)==A && LA(2)==B && LA(3)==C) || AAA(LATEXT(1))) {... + +#94. (Fixed in 1.33MR10) Predicates followed by rule references + + Prior to 1.33MR10, a semantic predicate which referenced a token + which was off the end of the rule caused an incomplete context + to be computed (with "-prc on") for the predicate under some circum- + stances. In some cases this manifested itself as illegal C code + (e.g. "LA(2)==[Ep](1)" in the k=2 examples below: + + all : ( a ) *; + + a : <>? ID X + | <>? Y + | Z + ; + + This might also occur when the semantic predicate was followed + by a rule reference which was shorter than the length of the + semantic predicate: + + all : ( a ) *; + + a : <>? ID X + | <>? y + | Z + ; + + y : Y ; + + Depending on circumstance, the resulting context might be too + generous because it was too short, or too restrictive because + of missing alternatives. + +#93. (Changed in 1.33MR10) Definition of Purify macro + + Ofer Ben-Ami (gremlin@cs.huji.ac.il) has supplied a definition + for the Purify macro: + + #define PURIFY(r, s) memset((char *) &(r), '\0', (s)); + + Note: This may not be the right thing to do for C++ objects that + have constructors. Reported by Bonny Rais (bonny@werple.net.au). + + For those cases one should #define PURIFY to an empty macro in the + #header or #first actions. + +#92. (Fixed in 1.33MR10) Guarded predicates and hoisting + + When a guarded predicate participates in hoisting it is linked into + a predicate expression tree. Prior to 1.33MR10 this link was never + cleared and the next time the guard was used to construct a new + tree the link could contain a spurious reference to another element + which had previosly been joined to it in the semantic predicate tree. + + For example: + + start : ( all ) *; + all : ( a | b ) ; + + start2 : ( all2 ) *; + all2 : ( a ) ; + + a : (A)? => <>? A ; + b : (B)? => <>? B ; + + Prior to 1.33MR10 the code for "start2" would include a spurious + reference to the BBB predicate which was left from constructing + the predicate tree for rule "start" (i.e. or(AAA,BBB) ). + + In 1.33MR10 this problem is avoided by cloning the original guard + each time it is linked into a predicate tree. + +#91. (Changed in 1.33MR10) Extensive changes to semantic pred hoisting + + ============================================ + This has been rendered obsolete by Item #117 + ============================================ + +#90. (Fixed in 1.33MR10) Semantic pred with LT(i) and i>max(k,ck) + + There is a bug in antlr 1.33 vanilla and all maintenance releases + prior to 1.33MR10 which allows semantic predicates to reference + an LT(i) or LATEXT(i) where i is larger than max(k,ck). When + this occurs antlr will attempt to mark the ith element of an array + in which there are only max(k,ck) elements. The result cannot + be predicted. + + Using LT(i) or LATEXT(i) for i>max(k,ck) is reported as an error + in 1.33MR10. + +#89. Rescinded + +#88. (Fixed in 1.33MR10) Tokens used in semantic predicates in guess mode + + Consider the behavior of a semantic predicate during guess mode: + + rule : a:A ( + <>? b:B + | c:C + ); + + Prior to MR10 the assignment of the token or attribute to + $a did not occur during guess mode, which would cause the + semantic predicate to misbehave because $a would be null. + + In 1.33MR10 a semantic predicate with a reference to an + element label (such as $a) forces the assignment to take + place even in guess mode. + + In order to work, this fix REQUIRES use of the $label format + for token pointers and attributes referenced in semantic + predicates. + + The fix does not apply to semantic predicates using the + numeric form to refer to attributes (e.g. <>?). + The user will receive a warning for this case. + + Reported by Rob Trout (trout@mcs.cs.kent.edu). + +#87. (Fixed in 1.33MR10) Malformed guard predicates + + Context guard predicates may contain only references to + tokens. They may not contain references to (...)+ and + (...)* blocks. This is now checked. This replaces the + fatal error message in item #78 with an appropriate + (non-fatal) error messge. + + In theory, context guards should be allowed to reference + rules. However, I have not had time to fix this. + Evaluation of the guard takes place before all rules have + been read, making it difficult to resolve a forward reference + to rule "zzz" - it hasn't been read yet ! To postpone evaluation + of the guard until all rules have been read is too much + for the moment. + +#86. (Fixed in 1.33MR10) Unequal set size in set_sub + + Routine set_sub() in pccts/support/set/set.h did not work + correctly when the sets were of unequal sizes. Rewrote + set_equ to make it simpler and remove unnecessary and + expensive calls to set_deg(). This routine was not used + in 1.33 vanila. + +#85. (Changed in 1.33MR10) Allow redefinition of MaxNumFiles + + Raised the maximum number of input files to 99 from 20. + Put a #ifndef/#endif around the "#define MaxNumFiles 99". + +#84. (Fixed in 1.33MR10) Initialize zzBadTok in macro zzRULE + + Initialize zzBadTok to NULL in zzRULE macro of AParser.h. + in order to get rid of warning messages. + +#83. (Fixed in 1.33MR10) False warnings with -w2 for #tokclass + + When -w2 is selected antlr gives inappropriate warnings about + #tokclass names not having any associated regular expressions. + Since a #tokclass is not a "real" token it will never have an + associated regular expression and there should be no warning. + + Reported by Derek Pappas (derek.pappas@eng.sun.com) + +#82. (Fixed in 1.33MR10) Computation of follow sets with multiple cycles + + Reinier van den Born (reinier@vnet.ibm.com) reported a problem + in the computation of follow sets by antlr. The problem (bug) + exists in 1.33 vanilla and all maintenance releases prior to 1.33MR10. + + The problem involves the computation of follow sets when there are + cycles - rules which have mutual references. I believe the problem + is restricted to cases where there is more than one cycle AND + elements of those cycles have rules in common. Even when this + occurs it may not affect the code generated - but it might. It + might also lead to undetected ambiguities. + + There were no changes in antlr or dlg output from the revised version. + + The following fragment demonstates the problem by giving different + follow sets (option -pa) for var_access when built with k=1 and ck=2 on + 1.33 vanilla and 1.33MR10: + + echo_statement : ECHO ( echo_expr )* + ; + + echo_expr : ( command )? + | expression + ; + + command : IDENTIFIER + { concat } + ; + + expression : operand ( OPERATOR operand )* + ; + + operand : value + | START command END + ; + + value : concat + | TYPE operand + ; + + concat : var_access { CONCAT value } + ; + + var_access : IDENTIFIER { INDEX } + + ; +#81. (Changed in 1.33MR10) C mode use of attributes and ASTs + + Reported by Isaac Clark (irclark@mindspring.com). + + C mode code ignores attributes returned by rules which are + referenced using element labels when ASTs are enabled (-gt option). + + 1. start : r:rule t:Token <<$start=$r;>> + + The $r refrence will not work when combined with + the -gt option. + + 2. start : t:Token <<$start=$t;>> + + The $t reference works in all cases. + + 3. start : rule <<$0=$1;>> + + Numeric labels work in all cases. + + With MR10 the user will receive an error message for case 1 when + the -gt option is used. + +#80. (Fixed in 1.33MR10) (...)? as last alternative of block + + A construct like the following: + + rule : a + | (b)? + ; + + does not make sense because there is no alternative when + the guess block fails. This is now reported as a warning + to the user. + + Previously, there was a code generation error for this case: + the guess block was not "closed" when the guess failed. + This could cause an infinite loop or other problems. This + is now fixed. + + Example problem: + + #header<< + #include + #include "charptr.h" + >> + + << + #include "charptr.c" + main () + { + ANTLR(start(),stdin); + } + >> + + #token "[\ \t]+" << zzskip(); >> + #token "[\n]" << zzline++; zzskip(); >> + + #token Word "[a-z]+" + #token Number "[0-9]+" + + + start : (test1)? + | (test2)? + ; + test1 : (Word Word Word Word)? + | (Word Word Word Number)? + ; + test2 : (Word Word Number Word)? + | (Word Word Number Number)? + ; + + Test data which caused infinite loop: + + a 1 a a + +#79. (Changed in 1.33MR10) Use of -fh with multiple parsers + + Previously, antlr always used the pre-processor symbol + STDPCCTS_H as a gate for the file stdpccts.h. This + caused problems when there were multiple parsers defined + because they used the same gate symbol. + + In 1.33MR10, the -fh filename is used to generate the + gate file for stdpccts.h. For instance: + + antlr -fh std_parser1.h + + generates the pre-processor symbol "STDPCCTS_std_parser1_H". + + Reported by Ramanathan Santhanam (ps@kumaran.com). + +#78. (Changed in 1.33MR9) Guard predicates that refer to rules + + ------------------------ + Please refer to Item #87 + ------------------------ + + Guard predicates are processed during an early phase + of antlr (during parsing) before all data structures + are completed. + + There is an apparent bug in earlier versions of 1.33 + which caused guard predicates which contained references + to rules (rather than tokens) to reference a structure + which hadn't yet been initialized. + + In some cases (perhaps all cases) references to rules + in guard predicates resulted in the use of "garbage". + +#79. (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com) + + Previously, the maximum length file name was set + arbitrarily to 300 characters in antlr, dlg, and sorcerer. + + The config.h file now attempts to define the maximum length + filename using _MAX_PATH from stdlib.h before falling back + to using the value 300. + +#78. (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com) + + Put #ifndef/#endif around definition of ZZLEXBUFSIZE in + antlr. + +#77. (Changed in 1.33MR9) Arithmetic overflow for very large grammars + + In routine HandleAmbiguities() antlr attempts to compute the + number of possible elements in a set that is order of + number-of-tokens raised to the number-of-lookahead-tokens power. + For large grammars or large lookahead (e.g. -ck 7) this can + cause arithmetic overflow. + + With 1.33MR9, arithmetic overflow in this computation is reported + the first time it happens. The program continues to run and + the program branches based on the assumption that the computed + value is larger than any number computed by counting actual cases + because 2**31 is larger than the number of bits in most computers. + + Before 1.33MR9 overflow was not reported. The behavior following + overflow is not predictable by anyone but the original author. + + NOTE + + In 1.33MR10 the warning message is suppressed. + The code which detects the overflow allows the + computation to continue without an error. The + error message itself made made users worry. + +#76. (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com) + + Jeff Vincent has convinced me to make ANTLRCommonToken and + ANTLRCommonNoRefCountToken use variable length strings + allocated from the heap rather than fixed length strings. + By suitable definition of setText(), the copy constructor, + and operator =() it is possible to maintain "copy" semantics. + By "copy" semantics I mean that when a token is copied from + an existing token it receives its own, distinct, copy of the + text allocated from the heap rather than simply a pointer + to the original token's text. + + ============================================================ + W * A * R * N * I * N * G + ============================================================ + + It is possible that this may cause problems for some users. + For those users I have included the old version of AToken.h as + pccts/h/AToken_traditional.h. + +#75. (Changed in 1.33MR9) Bruce Guenter (bruceg@qcc.sk.ca) + + Make DLGStringInput const correct. Since this is infrequently + subclassed, it should affect few users, I hope. + +#74. (Changed in 1.33MR9) -o (output directory) option + + Antlr does not properly handle the -o output directory option + when the filename of the grammar contains a directory part. For + example: + + antlr -o outdir pccts_src/myfile.g + + causes antlr create a file called "outdir/pccts_src/myfile.cpp. + It SHOULD create outdir/myfile.cpp + + The suggested code fix has been installed in antlr, dlg, and + Sorcerer. + +#73. (Changed in 1.33MR9) Hoisting of semantic predicates and -mrhoist + + ============================================ + This has been rendered obsolete by Item #117 + ============================================ + +#72. (Changed in 1.33MR9) virtual saveState()/restoreState()/guess_XXX + + The following methods in ANTLRParser were made virtual at + the request of S. Bochnak (S.Bochnak@microTool.com.pl): + + saveState() and restoreState() + guess(), guess_fail(), and guess_done() + +#71. (Changed in 1.33MR9) Access to omitted command line argument + + If a switch requiring arguments is the last thing on the + command line, and the argument is omitted, antlr would core. + + antlr test.g -prc + + instead of + + antlr test.g -prc off + +#70. (Changed in 1.33MR9) Addition of MSVC .dsp and .mak build files + + The following MSVC .dsp and .mak files for pccts and sorcerer + were contributed by Stanislaw Bochnak (S.Bochnak@microTool.com.pl) + and Jeff Vincent (JVincent@novell.com) + + PCCTS Distribution Kit + ---------------------- + pccts/PCCTSMSVC50.dsw + + pccts/antlr/AntlrMSVC50.dsp + pccts/antlr/AntlrMSVC50.mak + + pccts/dlg/DlgMSVC50.dsp + pccts/dlg/DlgMSVC50.mak + + pccts/support/msvc.dsp + + Sorcerer Distribution Kit + ------------------------- + pccts/sorcerer/SorcererMSVC50.dsp + pccts/sorcerer/SorcererMSVC50.mak + + pccts/sorcerer/lib/msvc.dsp + +#69. (Changed in 1.33MR9) Change "unsigned int" to plain "int" + + Declaration of max_token_num in misc.c as "unsigned int" + caused comparison between signed and unsigned ints giving + warning message without any special benefit. + +#68. (Changed in 1.33MR9) Add void return for dlg internal_error() + + Get rid of "no return value" message in internal_error() + in file dlg/support.c and dlg/dlg.h. + +#67. (Changed in Sor) sor.g: lisp() has no return value + + Added a "void" for the return type. + +#66. (Added to Sor) sor.g: ZZLEXBUFSIZE enclosed in #ifndef/#endif + + A user needed to be able to change the ZZLEXBUFSIZE for + sor. Put the definition of ZZLEXBUFSIZE inside #ifndef/#endif + +#65. (Changed in 1.33MR9) PCCTSAST::deepCopy() and ast_dup() bug + + Jeff Vincent (JVincent@novell.com) found that deepCopy() + made new copies of only the direct descendents. No new + copies were made of sibling nodes, Sibling pointers are + set to zero by shallowCopy(). + + PCCTS_AST::deepCopy() has been changed to make a + deep copy in the traditional sense. + + The deepCopy() routine depends on the behavior of + shallowCopy(). In all sor examples I've found, + shallowCopy() zeroes the right and down pointers. + + Original Tree Original deepCopy() Revised deepCopy + ------------- ------------------- ---------------- + a->b->c A A + | | | + d->e->f D D->E->F + | | | + g->h->i G G->H->I + | | + j->k J->K + + While comparing deepCopy() for C++ mode with ast_dup for + C mode I found a problem with ast_dup(). + + Routine ast_dup() has been changed to make a deep copy + in the traditional sense. + + Original Tree Original ast_dup() Revised ast_dup() + ------------- ------------------- ---------------- + a->b->c A->B->C A + | | | + d->e->f D->E->F D->E->F + | | | + g->h->i G->H->I G->H->I + | | | + j->k J->K J->K + + + I believe this affects transform mode sorcerer programs only. + +#64. (Changed in 1.33MR9) anltr/hash.h prototype for killHashTable() + +#63. (Changed in 1.33MR8) h/charptr.h does not zero pointer after free + + The charptr.h routine now zeroes the pointer after free(). + + Reported by Jens Tingleff (jensting@imaginet.fr) + +#62. (Changed in 1.33MR8) ANTLRParser::resynch had static variable + + The static variable "consumed" in ANTLRParser::resynch was + changed into an instance variable of the class with the + name "resynchConsumed". + + Reported by S.Bochnak@microTool.com.pl + +#61. (Changed in 1.33MR8) Using rule>[i,j] when rule has no return values + + Previously, the following code would cause antlr to core when + it tried to generate code for rule1 because rule2 had no return + values ("upward inheritance"): + + rule1 : <> + rule2 > [i,j] + ; + + rule2 : Anything ; + + Reported by S.Bochnak@microTool.com.pl + + Verified correct operation of antlr MR8 when missing or extra + inheritance arguments for all combinations. When there are + missing or extra arguments code will still be generated even + though this might cause the invocation of a subroutine with + the wrong number of arguments. + +#60. (Changed in 1.33MR7) Major changes to exception handling + + There were significant problems in the handling of exceptions + in 1.33 vanilla. The general problem is that it can only + process one level of exception handler. For example, a named + exception handler, an exception handler for an alternative, or + an exception for a subrule always went to the rule's exception + handler if there was no "catch" which matched the exception. + + In 1.33MR7 the exception handlers properly "nest". If an + exception handler does not have a matching "catch" then the + nextmost outer exception handler is checked for an appropriate + "catch" clause, and so on until an exception handler with an + appropriate "catch" is found. + + There are still undesirable features in the way exception + handlers are implemented, but I do not have time to fix them + at the moment: + + The exception handlers for alternatives are outside the + block containing the alternative. This makes it impossible + to access variables declared in a block or to resume the + parse by "falling through". The parse can still be easily + resumed in other ways, but not in the most natural fashion. + + This results in an inconsistentcy between named exception + handlers and exception handlers for alternatives. When + an exception handler for an alternative "falls through" + it goes to the nextmost outer handler - not the "normal + action". + + A major difference between 1.33MR7 and 1.33 vanilla is + the default action after an exception is caught: + + 1.33 Vanilla + ------------ + In 1.33 vanilla the signal value is set to zero ("NoSignal") + and the code drops through to the code following the exception. + For named exception handlers this is the "normal action". + For alternative exception handlers this is the rule's handler. + + 1.33MR7 + ------- + In 1.33MR7 the signal value is NOT automatically set to zero. + + There are two cases: + + For named exception handlers: if the signal value has been + set to zero the code drops through to the "normal action". + + For all other cases the code branches to the nextmost outer + exception handler until it reaches the handler for the rule. + + The following macros have been defined for convenience: + + C/C++ Mode Name + -------------------- + (zz)suppressSignal + set signal & return signal arg to 0 ("NoSignal") + (zz)setSignal(intValue) + set signal & return signal arg to some value + (zz)exportSignal + copy the signal value to the return signal arg + + I'm not sure why PCCTS make a distinction between the local + signal value and the return signal argument, but I'm loathe + to change the code. The burden of copying the local signal + value to the return signal argument can be given to the + default signal handler, I suppose. + +#59. (Changed in 1.33MR7) Prototypes for some functions + + Added prototypes for the following functions to antlr.h + + zzconsumeUntil() + zzconsumeUntilToken() + +#58. (Changed in 1.33MR7) Added defintion of zzbufsize to dlgauto.h + +#57. (Changed in 1.33MR7) Format of #line directive + + Previously, the -gl directive for line 1234 would + resemble: "# 1234 filename.g". This caused problems + for some compilers/pre-processors. In MR7 it generates + "#line 1234 filename.g". + +#56. (Added in 1.33MR7) Jan Mikkelsen + + Move PURIFY macro invocaton to after rule's init action. + +#55. (Fixed in 1.33MR7) Unitialized variables in ANTLRParser + + Member variables inf_labase and inf_last were not initialized. + (See item #50.) + +#54. (Fixed in 1.33MR6) Brad Schick (schick@interacess.com) + + Previously, the following constructs generated the same + code: + + rule1 : (A B C)? + | something-else + ; + + rule2 : (A B C)? () + | something-else + ; + + In all versions of pccts rule1 guesses (A B C) and then + consume all three tokens if the guess succeeds. In MR6 + rule2 guesses (A B C) but consumes NONE of the tokens + when the guess succeeds because "()" matches epsilon. + +#53. (Explanation for 1.33MR6) What happens after an exception is caught ? + + The Book is silent about what happens after an exception + is caught. + + The following code fragment prints "Error Action" followed + by "Normal Action". + + test : Word ex:Number <> + exception[ex] + catch NoViableAlt: + <> + ; + + The reason for "Normal Action" is that the normal flow of the + program after a user-written exception handler is to "drop through". + In the case of an exception handler for a rule this results in + the exection of a "return" statement. In the case of an + exception handler attached to an alternative, rule, or token + this is the code that would have executed had there been no + exception. + + The user can achieve the desired result by using a "return" + statement. + + test : Word ex:Number <> + exception[ex] + catch NoViableAlt: + <> + ; + + The most powerful mechanism for recovery from parse errors + in pccts is syntactic predicates because they provide + backtracking. Exceptions allow "return", "break", + "consumeUntil(...)", "goto _handler", "goto _fail", and + changing the _signal value. + +#52. (Fixed in 1.33MR6) Exceptions without syntactic predicates + + The following generates bad code in 1.33 if no syntactic + predicates are present in the grammar. + + test : Word ex:Number <> + exception[ex] + catch NoViableAlt: + <> + + There is a reference to a guess variable. In C mode + this causes a compiler error. In C++ mode it generates + an extraneous check on member "guessing". + + In MR6 correct code is generated for both C and C++ mode. + +#51. (Added to 1.33MR6) Exception operator "@" used without exceptions + + In MR6 added a warning when the exception operator "@" is + used and no exception group is defined. This is probably + a case where "\@" or "@" is meant. + +#50. (Fixed in 1.33MR6) Gunnar Rxnning (gunnar@candleweb.no) + http://www.candleweb.no/~gunnar/ + + Routines zzsave_antlr_state and zzrestore_antlr_state don't + save and restore all the data needed when switching states. + + Suggested patch applied to antlr.h and err.h for MR6. + +#49. (Fixed in 1.33MR6) Sinan Karasu (sinan@boeing.com) + + Generated code failed to turn off guess mode when leaving a + (...)+ block which contained a guess block. The result was + an infinite loop. For example: + + rule : ( + (x)? + | y + )+ + + Suggested code fix implemented in MR6. Replaced + + ... else if (zzcnt>1) break; + + with: + + C++ mode: + ... else if (zzcnt>1) {if (!zzrv) zzGUESS_DONE; break;}; + C mode: + ... else if (zzcnt>1) {if (zzguessing) zzGUESS_DONE; break;}; + +#48. (Fixed in 1.33MR6) Invalid exception element causes core + + A label attached to an invalid construct can cause + pccts to crash while processing the exception associated + with the label. For example: + + rule : t:(B C) + exception[t] catch MismatchedToken: <> + + Version MR6 generates the message: + + reference in exception handler to undefined label 't' + +#47. (Fixed in 1.33MR6) Manuel Ornato + + Under some circumstances involving a k >1 or ck >1 + grammar and a loop block (i.e. (...)* ) pccts will + fail to detect a syntax error and loop indefinitely. + The problem did not exist in 1.20, but has existed + from 1.23 to the present. + + Fixed in MR6. + + --------------------------------------------------- + Complete test program + --------------------------------------------------- + #header<< + #include + #include "charptr.h" + >> + + << + #include "charptr.c" + main () + { + ANTLR(global(),stdin); + } + >> + + #token "[\ \t]+" << zzskip(); >> + #token "[\n]" << zzline++; zzskip(); >> + + #token B "b" + #token C "c" + #token D "d" + #token E "e" + #token LP "\(" + #token RP "\)" + + #token ANTLREOF "@" + + global : ( + (E liste) + | liste + | listed + ) ANTLREOF + ; + + listeb : LP ( B ( B | C )* ) RP ; + listec : LP ( C ( B | C )* ) RP ; + listed : LP ( D ( B | C )* ) RP ; + liste : ( listeb | listec )* ; + + --------------------------------------------------- + Sample data causing infinite loop + --------------------------------------------------- + e (d c) + --------------------------------------------------- + +#46. (Fixed in 1.33MR6) Robert Richter + (Robert.Richter@infotech.tu-chemnitz.de) + + This item from the list of known problems was + fixed by item #18 (below). + +#45. (Fixed in 1.33MR6) Brad Schick (schick@interaccess.com) + + The dependency scanner in VC++ mistakenly sees a + reference to an MPW #include file even though properly + #ifdef/#endif in config.h. The suggested workaround + has been implemented: + + #ifdef MPW + ..... + #define MPW_CursorCtl_Header + #include MPW_CursorCtl_Header + ..... + #endif + +#44. (Fixed in 1.33MR6) cast malloc() to (char *) in charptr.c + + Added (char *) cast for systems where malloc returns "void *". + +#43. (Added to 1.33MR6) Bruce Guenter (bruceg@qcc.sk.ca) + + Add setLeft() and setUp methods to ASTDoublyLinkedBase + for symmetry with setRight() and setDown() methods. + +#42. (Fixed in 1.33MR6) Jeff Katcher (jkatcher@nortel.ca) + + C++ style comment in antlr.c corrected. + +#41. (Added in 1.33MR6) antlr -stdout + + Using "antlr -stdout ..." forces the text that would + normally go to the grammar.c or grammar.cpp file to + stdout. + +#40. (Added in 1.33MR6) antlr -tab to change tab stops + + Using "antlr -tab number ..." changes the tab stops + for the grammar.c or grammar.cpp file. The number + must be between 0 and 8. Using 0 gives tab characters, + values between 1 and 8 give the appropriate number of + space characters. + +#39. (Fixed in 1.33MR5) Jan Mikkelsen + + Commas in function prototype still not correct under + some circumstances. Suggested code fix installed. + +#38. (Fixed in 1.33MR5) ANTLRTokenBuffer constructor + + Have ANTLRTokenBuffer ctor initialize member "parser" to null. + +#37. (Fixed in 1.33MR4) Bruce Guenter (bruceg@qcc.sk.ca) + + In ANTLRParser::FAIL(int k,...) released memory pointed to by + f[i] (as well as f itself. Should only free f itself. + +#36. (Fixed in 1.33MR3) Cortland D. Starrett (cort@shay.ecn.purdue.edu) + + Neglected to properly declare isDLGmaxToken() when fixing problem + reported by Andreas Magnusson. + + Undo "_retv=NULL;" change which caused problems for return values + from rules whose return values weren't pointers. + + Failed to create bin directory if it didn't exist. + +#35. (Fixed in 1.33MR2) Andreas Magnusson +(Andreas.Magnusson@mailbox.swipnet.se) + + Repair bug introduced by 1.33MR1 for #tokdefs. The original fix + placed "DLGmaxToken=9999" and "DLGminToken=0" in the TokenType enum + in order to fix a problem with an aggresive compiler assigning an 8 + bit enum which might be too narrow. This caused #tokdefs to assume + that there were 9999 real tokens. The repair to the fix causes antlr to + ignore TokenTypes "DLGmaxToken" and "DLGminToken" in a #tokdefs file. + +#34. (Added to 1.33MR1) Add public DLGLexerBase::set_line(int newValue) + + Previously there was no public function for changing the line + number maintained by the lexer. + +#33. (Fixed in 1.33MR1) Franklin Chen (chen@adi.com) + + Accidental use of EXIT_FAILURE rather than PCCTS_EXIT_FAILURE + in pccts/h/AParser.cpp. + +#32. (Fixed in 1.33MR1) Franklin Chen (chen@adi.com) + + In PCCTSAST.cpp lines 405 and 466: Change + + free (t) + to + free ( (char *)t ); + + to match prototype. + +#31. (Added to 1.33MR1) Pointer to parser in ANTLRTokenBuffer + Pointer to parser in DLGLexerBase + + The ANTLRTokenBuffer class now contains a pointer to the + parser which is using it. This is established by the + ANTLRParser constructor calling ANTLRTokenBuffer:: + setParser(ANTLRParser *p). + + When ANTLRTokenBuffer::setParser(ANTLRParser *p) is + called it saves the pointer to the parser and then + calls ANTLRTokenStream::setParser(ANTLRParser *p) + so that the lexer can also save a pointer to the + parser. + + There is also a function getParser() in each class + with the obvious purpose. + + It is possible that these functions will return NULL + under some circumstances (e.g. a non-DLG lexer is used). + +#30. (Added to 1.33MR1) function tokenName(int token) standard + + The generated parser class now includes the + function: + + static const ANTLRChar * tokenName(int token) + + which returns a pointer to the "name" corresponding + to the token. + + The base class (ANTLRParser) always includes the + member function: + + const ANTLRChar * parserTokenName(int token) + + which can be accessed by objects which have a pointer + to an ANTLRParser, but do not know the name of the + parser class (e.g. ANTLRTokenBuffer and DLGLexerBase). + +#29. (Added to 1.33MR1) Debugging DLG lexers + + If the pre-processor symbol DEBUG_LEXER is defined + then DLexerBase will include code for printing out + key information about tokens which are recognized. + + The debug feature of the lexer is controlled by: + + int previousDebugValue=lexer.debugLexer(newValue); + + a value of 0 disables output + a value of 1 enables output + + Even if the lexer debug code is compiled into DLexerBase + it must be enabled before any output is generated. For + example: + + DLGFileInput in(stdin); + MyDLG lexer(&in,2000); + + lexer.setToken(&aToken); + + #if DEBUG_LEXER + lexer.debugLexer(1); // enable debug information + #endif + +#28. (Added to 1.33MR1) More control over DLG header + + Version 1.33MR1 adds the following directives to PCCTS + for C++ mode: + + #lexprefix <> + + Adds source code to the DLGLexer.h file + after the #include "DLexerBase.h" but + before the start of the class definition. + + #lexmember <> + + Adds source code to the DLGLexer.h file + as part of the DLGLexer class body. It + appears immediately after the start of + the class and a "public: statement. + +#27. (Fixed in 1.33MR1) Comments in DLG actions + + Previously, DLG would not recognize comments as a special case. + Thus, ">>" in the comments would cause errors. This is fixed. + +#26. (Fixed in 1.33MR1) Removed static variables from error routines + + Previously, the existence of statically allocated variables + in some of the parser's member functions posed a danger when + there was more than one parser active. + + Replaced with dynamically allocated/freed variables in 1.33MR1. + +#25. (Fixed in 1.33MR1) Use of string literals in semantic predicates + + Previously, it was not possible to place a string literal in + a semantic predicate because it was not properly "stringized" + for the report of a failed predicate. + +#24. (Fixed in 1.33MR1) Continuation lines for semantic predicates + + Previously, it was not possible to continue semantic + predicates across a line because it was not properly + "stringized" for the report of a failed predicate. + + rule : <>?[ a very + long statement ] + +#23. (Fixed in 1.33MR1) {...} envelope for failed semantic predicates + + Previously, there was a code generation error for failed + semantic predicates: + + rule : <>?[ stmt1; stmt2; ] + + which generated code which resembled: + + if (! xyz()) stmt1; stmt2; + + It now puts the statements in a {...} envelope: + + if (! xyz()) { stmt1; stmt2; }; + +#22. (Fixed in 1.33MR1) Continuation of #token across lines using "\" + + Previously, it was not possible to continue a #token regular + expression across a line. The trailing "\" and newline caused + a newline to be inserted into the regular expression by DLG. + + Fixed in 1.33MR1. + +#21. (Fixed in 1.33MR1) Use of ">>" (right shift operator in DLG actions + + It is now possible to use the C++ right shift operator ">>" + in DLG actions by using the normal escapes: + + #token "shift-right" << value=value \>\> 1;>> + +#20. (Version 1.33/19-Jan-97 Karl Eccleson + P.A. Keller (P.A.Keller@bath.ac.uk) + + There is a problem due to using exceptions with the -gh option. + + Suggested fix now in 1.33MR1. + +#19. (Fixed in 1.33MR1) Tom Piscotti and John Lilley + + There were problems suppressing messages to stdin and stdout + when running in a window environment because some functions + which uses fprint were not virtual. + + Suggested change now in 1.33MR1. + + I believe all functions containing error messages (excluding those + indicating internal inconsistency) have been placed in functions + which are virtual. + +#18. (Version 1.33/ 22-Nov-96) John Bair (jbair@iftime.com) + + Under some combination of options a required "return _retv" is + not generated. + + Suggested fix now in 1.33MR1. + +#17. (Version 1.33/3-Sep-96) Ron House (house@helios.usq.edu.au) + + The routine ASTBase::predorder_action omits two "tree->" + prefixes, which results in the preorder_action belonging + to the wrong node to be invoked. + + Suggested fix now in 1.33MR1. + +#16. (Version 1.33/7-Jun-96) Eli Sternheim + + Routine consumeUntilToken() does not check for end-of-file + condition. + + Suggested fix now in 1.33MR1. + +#15. (Version 1.33/8 Apr 96) Asgeir Olafsson + + Problem with tree duplication of doubly linked ASTs in ASTBase.cpp. + + Suggested fix now in 1.33MR1. + +#14. (Version 1.33/28-Feb-96) Andreas.Magnusson@mailbox.swipnet.se + + Problem with definition of operator = (const ANTLRTokenPtr rhs). + + Suggested fix now in 1.33MR1. + +#13. (Version 1.33/13-Feb-96) Franklin Chen (chen@adi.com) + + Sun C++ Compiler 3.0.1 can't compile testcpp/1 due to goto in + block with destructors. + + Apparently fixed. Can't locate "goto". + +#12. (Version 1.33/10-Nov-95) Minor problems with 1.33 code + + The following items have been fixed in 1.33MR1: + + 1. pccts/antlr/main.c line 142 + + "void" appears in classic C code + + 2. no makefile in support/genmk + + 3. EXIT_FAILURE/_SUCCESS instead of PCCTS_EXIT_FAILURE/_SUCCESS + + pccts/h/PCCTSAST.cpp + pccts/h/DLexerBase.cpp + pccts/testcpp/6/test.g + + 4. use of "signed int" isn't accepted by AT&T cfront + + pccts/h/PCCTSAST.h line 42 + + 5. in call to ANTLRParser::FAIL the var arg err_k is passed as + "int" but is declared "unsigned int". + + 6. I believe that a failed validation predicate still does not + get put in a "{...}" envelope, despite the release notes. + + 7. The #token ">>" appearing in the DLG grammar description + causes DLG to generate the string literal "\>\>" which + is non-conforming and will cause some compilers to + complain (scan.c function act10 line 143 of source code). + +#11. (Version 1.32b6) Dave Kuhlman (dkuhlman@netcom.com) + + Problem with file close in gen.c. Already fixed in 1.33. + +#10. (Version 1.32b6/29-Aug-95) + + pccts/antlr/main.c contains a C++ style comments on lines 149 + and 176 which causes problems for most C compilers. + + Already fixed in 1.33. + +#9. (Version 1.32b4/14-Mar-95) dlgauto.h #include "config.h" + + The file pccts/h/dlgauto.h should probably contain a #include + "config.h" as it uses the #define symbol __USE_PROTOS. + + Added to 1.33MR1. + +#8. (Version 1.32b4/6-Mar-95) Michael T. Richter (mtr@igs.net) + + In C++ output mode anonymous tokens from in-line regular expressions + can create enum values which are too wide for the datatype of the enum + assigned by the C++ compiler. + + Fixed in 1.33MR1. + +#7. (Version 1.32b4/6-Mar-95) C++ does not imply __STDC__ + + In err.h the combination of # directives assumes that a C++ + compiler has __STDC__ defined. This is not necessarily true. + + This problem also appears in the use of __USE_PROTOS which + is appropriate for both Standard C and C++ in antlr/gen.c + and antlr/lex.c + + Fixed in 1.33MR1. + +#6. (Version 1.32 ?/15-Feb-95) Name conflict for "TokenType" + + Already fixed in 1.33. + +#5. (23-Jan-95) Douglas_Cuthbertson.JTIDS@jtids_qmail.hanscom.af.mil + + The fail action following a semantic predicate is not enclosed in + "{...}". This can lead to problems when the fail action contains + more than one statement. + + Fixed in 1.33MR1. + +#4 . (Version 1.33/31-Mar-96) jlilley@empathy.com (John Lilley) + + Put briefly, a semantic predicate ought to abort a guess if it fails. + + Correction suggested by J. Lilley has been added to 1.33MR1. + +#3 . (Version 1.33) P.A.Keller@bath.ac.uk + + Extra commas are placed in the K&R style argument list for rules + when using both exceptions and ASTs. + + Fixed in 1.33MR1. + +#2. (Version 1.32b6/2-Oct-95) Brad Schick + + Construct #[] generates zzastnew() in C++ mode. + + Already fixed in 1.33. + +#1. (Version 1.33) Bob Bailey (robert@oakhill.sps.mot.com) + + Previously, config.h assumed that all PC systems required + "short" file names. The user can now override that + assumption with "#define LONGFILENAMES". + + Added to 1.33MR1. diff --git a/Tools/Source/TianoTools/Pccts/CHANGES_SUMMARY.txt b/Tools/Source/TianoTools/Pccts/CHANGES_SUMMARY.txt new file mode 100644 index 0000000000..91defae169 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/CHANGES_SUMMARY.txt @@ -0,0 +1,2049 @@ +====================================================================== + + CHANGES_SUMMARY.TXT + + A QUICK overview of changes from 1.33 in reverse order + + A summary of additions rather than bug fixes and minor code changes. + + Numbers refer to items in CHANGES_FROM_133*.TXT + which may contain additional information. + + DISCLAIMER + + The software and these notes are provided "as is". They may include + typographical or technical errors and their authors disclaims all + liability of any kind or nature for damages due to error, fault, + defect, or deficiency regardless of cause. All warranties of any + kind, either express or implied, including, but not limited to, the + implied warranties of merchantability and fitness for a particular + purpose are disclaimed. + +====================================================================== + +#258. You can specify a user-defined base class for your parser + + The base class must constructor must have a signature similar to + that of ANTLRParser. + +#253. Generation of block preamble (-preamble and -preamble_first) + + The antlr option -preamble causes antlr to insert the code + BLOCK_PREAMBLE at the start of each rule and block. + + The antlr option -preamble_first is similar, but inserts the + code BLOCK_PREAMBLE_FIRST(PreambleFirst_123) where the symbol + PreambleFirst_123 is equivalent to the first set defined by + the #FirstSetSymbol described in Item #248. + +#248. Generate symbol for first set of an alternative + + rr : #FirstSetSymbol(rr_FirstSet) ( Foo | Bar ) ; + +#216. Defer token fetch for C++ mode + + When the ANTLRParser class is built with the pre-processor option + ZZDEFER_FETCH defined, the fetch of new tokens by consume() is deferred + until LA(i) or LT(i) is called. + +#215. Use reset() to reset DLGLexerBase +#188. Added pccts/h/DLG_stream_input.h +#180. Added ANTLRParser::getEofToken() +#173. -glms for Microsoft style filenames with -gl +#170. Suppression for predicates with lookahead depth >1 + + Consider the following grammar with -ck 2 and the predicate in rule + "a" with depth 2: + + r1 : (ab)* "@" + ; + + ab : a + | b + ; + + a : (A B)? => <>? A B C + ; + + b : A B C + ; + + Normally, the predicate would be hoisted into rule r1 in order to + determine whether to call rule "ab". However it should *not* be + hoisted because, even if p is false, there is a valid alternative + in rule b. With "-mrhoistk on" the predicate will be suppressed. + + If "-info p" command line option is present the following information + will appear in the generated code: + + while ( (LA(1)==A) + #if 0 + + Part (or all) of predicate with depth > 1 suppressed by alternative + without predicate + + pred << p(LATEXT(2))>>? + depth=k=2 ("=>" guard) rule a line 8 t1.g + tree context: + (root = A + B + ) + + The token sequence which is suppressed: ( A B ) + The sequence of references which generate that sequence of tokens: + + 1 to ab r1/1 line 1 t1.g + 2 ab ab/1 line 4 t1.g + 3 to b ab/2 line 5 t1.g + 4 b b/1 line 11 t1.g + 5 #token A b/1 line 11 t1.g + 6 #token B b/1 line 11 t1.g + + #endif + + A slightly more complicated example: + + r1 : (ab)* "@" + ; + + ab : a + | b + ; + + a : (A B)? => <>? (A B | D E) + ; + + b : <>? D E + ; + + + In this case, the sequence (D E) in rule "a" which lies behind + the guard is used to suppress the predicate with context (D E) + in rule b. + + while ( (LA(1)==A || LA(1)==D) + #if 0 + + Part (or all) of predicate with depth > 1 suppressed by alternative + without predicate + + pred << q(LATEXT(2))>>? + depth=k=2 rule b line 11 t2.g + tree context: + (root = D + E + ) + + The token sequence which is suppressed: ( D E ) + The sequence of references which generate that sequence of tokens: + + 1 to ab r1/1 line 1 t2.g + 2 ab ab/1 line 4 t2.g + 3 to a ab/1 line 4 t2.g + 4 a a/1 line 8 t2.g + 5 #token D a/1 line 8 t2.g + 6 #token E a/1 line 8 t2.g + + #endif + && + #if 0 + + pred << p(LATEXT(2))>>? + depth=k=2 ("=>" guard) rule a line 8 t2.g + tree context: + (root = A + B + ) + + #endif + + (! ( LA(1)==A && LA(2)==B ) || p(LATEXT(2)) ) { + ab(); + ... + +#165. (Changed in MR13) option -newAST + + To create ASTs from an ANTLRTokenPtr antlr usually calls + "new AST(ANTLRTokenPtr)". This option generates a call + to "newAST(ANTLRTokenPtr)" instead. This allows a user + to define a parser member function to create an AST object. + +#161. (Changed in MR13) Switch -gxt inhibits generation of tokens.h + +#158. (Changed in MR13) #header causes problem for pre-processors + + A user who runs the C pre-processor on antlr source suggested + that another syntax be allowed. With MR13 such directives + such as #header, #pragma, etc. may be written as "\#header", + "\#pragma", etc. For escaping pre-processor directives inside + a #header use something like the following: + + \#header + << + \#include + >> + +#155. (Changed in MR13) Context behind predicates can suppress + + With -mrhoist enabled the context behind a guarded predicate can + be used to suppress other predicates. Consider the following grammar: + + r0 : (r1)+; + + r1 : rp + | rq + ; + rp : <

>? B ; + rq : (A)? => <>? (A|B); + + In earlier versions both predicates "p" and "q" would be hoisted into + rule r0. With MR12c predicate p is suppressed because the context which + follows predicate q includes "B" which can "cover" predicate "p". In + other words, in trying to decide in r0 whether to call r1, it doesn't + really matter whether p is false or true because, either way, there is + a valid choice within r1. + +#154. (Changed in MR13) Making hoist suppression explicit using <> + + A common error, even among experienced pccts users, is to code + an init-action to inhibit hoisting rather than a leading action. + An init-action does not inhibit hoisting. + + This was coded: + + rule1 : <<;>> rule2 + + This is what was meant: + + rule1 : <<;>> <<;>> rule2 + + With MR13, the user can code: + + rule1 : <<;>> <> rule2 + + The following will give an error message: + + rule1 : <> rule2 + + If the <> appears as an init-action rather than a leading + action an error message is issued. The meaning of an init-action + containing "nohoist" is unclear: does it apply to just one + alternative or to all alternatives ? + +#151a. Addition of ANTLRParser::getLexer(), ANTLRTokenStream::getLexer() + + You must manually cast the ANTLRTokenStream to your program's + lexer class. Because the name of the lexer's class is not fixed. + Thus it is impossible to incorporate it into the DLGLexerBase + class. + +#151b.(Changed in MR12) ParserBlackBox member getLexer() + +#150. (Changed in MR12) syntaxErrCount and lexErrCount now public + +#149. (Changed in MR12) antlr option -info o (letter o for orphan) + + If there is more than one rule which is not referenced by any + other rule then all such rules are listed. This is useful for + alerting one to rules which are not used, but which can still + contribute to ambiguity. + +#148. (Changed in MR11) #token names appearing in zztokens,token_tbl + + One can write: + + #token Plus ("+") "\+" + #token RP ("(") "\(" + #token COM ("comment begin") "/\*" + + The string in parenthesis will be used in syntax error messages. + +#146. (Changed in MR11) Option -treport for locating "difficult" alts + + It can be difficult to determine which alternatives are causing + pccts to work hard to resolve an ambiguity. In some cases the + ambiguity is successfully resolved after much CPU time so there + is no message at all. + + A rough measure of the amount of work being peformed which is + independent of the CPU speed and system load is the number of + tnodes created. Using "-info t" gives information about the + total number of tnodes created and the peak number of tnodes. + + Tree Nodes: peak 1300k created 1416k lost 0 + + It also puts in the generated C or C++ file the number of tnodes + created for a rule (at the end of the rule). However this + information is not sufficient to locate the alternatives within + a rule which are causing the creation of tnodes. + + Using: + + antlr -treport 100000 .... + + causes antlr to list on stdout any alternatives which require the + creation of more than 100,000 tnodes, along with the lookahead sets + for those alternatives. + + The following is a trivial case from the ansi.g grammar which shows + the format of the report. This report might be of more interest + in cases where 1,000,000 tuples were created to resolve the ambiguity. + + ------------------------------------------------------------------------- + There were 0 tuples whose ambiguity could not be resolved + by full lookahead + There were 157 tnodes created to resolve ambiguity between: + + Choice 1: statement/2 line 475 file ansi.g + Choice 2: statement/3 line 476 file ansi.g + + Intersection of lookahead[1] sets: + + IDENTIFIER + + Intersection of lookahead[2] sets: + + LPARENTHESIS COLON AMPERSAND MINUS + STAR PLUSPLUS MINUSMINUS ONESCOMPLEMENT + NOT SIZEOF OCTALINT DECIMALINT + HEXADECIMALINT FLOATONE FLOATTWO IDENTIFIER + STRING CHARACTER + ------------------------------------------------------------------------- + +#143. (Changed in MR11) Optional ";" at end of #token statement + + Fixes problem of: + + #token X "x" + + << + parser action + >> + + Being confused with: + + #token X "x" <> + +#142. (Changed in MR11) class BufFileInput subclass of DLGInputStream + + Alexey Demakov (demakov@kazbek.ispras.ru) has supplied class + BufFileInput derived from DLGInputStream which provides a + function lookahead(char *string) to test characters in the + input stream more than one character ahead. + The class is located in pccts/h/BufFileInput.* of the kit. + +#140. #pred to define predicates + + +---------------------------------------------------+ + | Note: Assume "-prc on" for this entire discussion | + +---------------------------------------------------+ + + A problem with predicates is that each one is regarded as + unique and capable of disambiguating cases where two + alternatives have identical lookahead. For example: + + rule : <>? A + | <>? A + ; + + will not cause any error messages or warnings to be issued + by earlier versions of pccts. To compare the text of the + predicates is an incomplete solution. + + In 1.33MR11 I am introducing the #pred statement in order to + solve some problems with predicates. The #pred statement allows + one to give a symbolic name to a "predicate literal" or a + "predicate expression" in order to refer to it in other predicate + expressions or in the rules of the grammar. + + The predicate literal associated with a predicate symbol is C + or C++ code which can be used to test the condition. A + predicate expression defines a predicate symbol in terms of other + predicate symbols using "!", "&&", and "||". A predicate symbol + can be defined in terms of a predicate literal, a predicate + expression, or *both*. + + When a predicate symbol is defined with both a predicate literal + and a predicate expression, the predicate literal is used to generate + code, but the predicate expression is used to check for two + alternatives with identical predicates in both alternatives. + + Here are some examples of #pred statements: + + #pred IsLabel <>? + #pred IsLocalVar <>? + #pred IsGlobalVar <>? + #pred IsVar <>? IsLocalVar || IsGlobalVar + #pred IsScoped <>? IsLabel || IsLocalVar + + I hope that the use of EBNF notation to describe the syntax of the + #pred statement will not cause problems for my readers (joke). + + predStatement : "#pred" + CapitalizedName + ( + "<>?" + | "<>?" predOrExpr + | predOrExpr + ) + ; + + predOrExpr : predAndExpr ( "||" predAndExpr ) * ; + + predAndExpr : predPrimary ( "&&" predPrimary ) * ; + + predPrimary : CapitalizedName + | "!" predPrimary + | "(" predOrExpr ")" + ; + + What is the purpose of this nonsense ? + + To understand how predicate symbols help, you need to realize that + predicate symbols are used in two different ways with two different + goals. + + a. Allow simplification of predicates which have been combined + during predicate hoisting. + + b. Allow recognition of identical predicates which can't disambiguate + alternatives with common lookahead. + + First we will discuss goal (a). Consider the following rule: + + rule0: rule1 + | ID + | ... + ; + + rule1: rule2 + | rule3 + ; + + rule2: <>? ID ; + rule3: <>? ID ; + + When the predicates in rule2 and rule3 are combined by hoisting + to create a prediction expression for rule1 the result is: + + if ( LA(1)==ID + && ( isX(LATEXT(1) || !isX(LATEXT(1) ) ) { rule1(); ... + + This is inefficient, but more importantly, can lead to false + assumptions that the predicate expression distinguishes the rule1 + alternative with some other alternative with lookahead ID. In + MR11 one can write: + + #pred IsX <>? + + ... + + rule2: <>? ID ; + rule3: <>? ID ; + + During hoisting MR11 recognizes this as a special case and + eliminates the predicates. The result is a prediction + expression like the following: + + if ( LA(1)==ID ) { rule1(); ... + + Please note that the following cases which appear to be equivalent + *cannot* be simplified by MR11 during hoisting because the hoisting + logic only checks for a "!" in the predicate action, not in the + predicate expression for a predicate symbol. + + *Not* equivalent and is not simplified during hoisting: + + #pred IsX <>? + #pred NotX <>? + ... + rule2: <>? ID ; + rule3: <>? ID ; + + *Not* equivalent and is not simplified during hoisting: + + #pred IsX <>? + #pred NotX !IsX + ... + rule2: <>? ID ; + rule3: <>? ID ; + + Now we will discuss goal (b). + + When antlr discovers that there is a lookahead ambiguity between + two alternatives it attempts to resolve the ambiguity by searching + for predicates in both alternatives. In the past any predicate + would do, even if the same one appeared in both alternatives: + + rule: <>? X + | <>? X + ; + + The #pred statement is a start towards solving this problem. + During ambiguity resolution (*not* predicate hoisting) the + predicates for the two alternatives are expanded and compared. + Consider the following example: + + #pred Upper <>? + #pred Lower <>? + #pred Alpha <>? Upper || Lower + + rule0: rule1 + | <>? ID + ; + + rule1: + | rule2 + | rule3 + ... + ; + + rule2: <>? ID; + rule3: <>? ID; + + The definition of #pred Alpha expresses: + + a. to test the predicate use the C code "isAlpha(LATEXT(1))" + + b. to analyze the predicate use the information that + Alpha is equivalent to the union of Upper and Lower, + + During ambiguity resolution the definition of Alpha is expanded + into "Upper || Lower" and compared with the predicate in the other + alternative, which is also "Upper || Lower". Because they are + identical MR11 will report a problem. + + ------------------------------------------------------------------------- + t10.g, line 5: warning: the predicates used to disambiguate rule rule0 + (file t10.g alt 1 line 5 and alt 2 line 6) + are identical when compared without context and may have no + resolving power for some lookahead sequences. + ------------------------------------------------------------------------- + + If you use the "-info p" option the output file will contain: + + +----------------------------------------------------------------------+ + |#if 0 | + | | + |The following predicates are identical when compared without | + | lookahead context information. For some ambiguous lookahead | + | sequences they may not have any power to resolve the ambiguity. | + | | + |Choice 1: rule0/1 alt 1 line 5 file t10.g | + | | + | The original predicate for choice 1 with available context | + | information: | + | | + | OR expr | + | | + | pred << Upper>>? | + | depth=k=1 rule rule2 line 14 t10.g | + | set context: | + | ID | + | | + | pred << Lower>>? | + | depth=k=1 rule rule3 line 15 t10.g | + | set context: | + | ID | + | | + | The predicate for choice 1 after expansion (but without context | + | information): | + | | + | OR expr | + | | + | pred << isUpper(LATEXT(1))>>? | + | depth=k=1 rule line 1 t10.g | + | | + | pred << isLower(LATEXT(1))>>? | + | depth=k=1 rule line 2 t10.g | + | | + | | + |Choice 2: rule0/2 alt 2 line 6 file t10.g | + | | + | The original predicate for choice 2 with available context | + | information: | + | | + | pred << Alpha>>? | + | depth=k=1 rule rule0 line 6 t10.g | + | set context: | + | ID | + | | + | The predicate for choice 2 after expansion (but without context | + | information): | + | | + | OR expr | + | | + | pred << isUpper(LATEXT(1))>>? | + | depth=k=1 rule line 1 t10.g | + | | + | pred << isLower(LATEXT(1))>>? | + | depth=k=1 rule line 2 t10.g | + | | + | | + |#endif | + +----------------------------------------------------------------------+ + + The comparison of the predicates for the two alternatives takes + place without context information, which means that in some cases + the predicates will be considered identical even though they operate + on disjoint lookahead sets. Consider: + + #pred Alpha + + rule1: <>? ID + | <>? Label + ; + + Because the comparison of predicates takes place without context + these will be considered identical. The reason for comparing + without context is that otherwise it would be necessary to re-evaluate + the entire predicate expression for each possible lookahead sequence. + This would require more code to be written and more CPU time during + grammar analysis, and it is not yet clear whether anyone will even make + use of the new #pred facility. + + A temporary workaround might be to use different #pred statements + for predicates you know have different context. This would avoid + extraneous warnings. + + The above example might be termed a "false positive". Comparison + without context will also lead to "false negatives". Consider the + following example: + + #pred Alpha + #pred Beta + + rule1: <>? A + | rule2 + ; + + rule2: <>? A + | <>? B + ; + + The predicate used for alt 2 of rule1 is (Alpha || Beta). This + appears to be different than the predicate Alpha used for alt1. + However, the context of Beta is B. Thus when the lookahead is A + Beta will have no resolving power and Alpha will be used for both + alternatives. Using the same predicate for both alternatives isn't + very helpful, but this will not be detected with 1.33MR11. + + To properly handle this the predicate expression would have to be + evaluated for each distinct lookahead context. + + To determine whether two predicate expressions are identical is + difficult. The routine may fail to identify identical predicates. + + The #pred feature also compares predicates to see if a choice between + alternatives which is resolved by a predicate which makes the second + choice unreachable. Consider the following example: + + #pred A <>? + #pred B <>? + #pred A_or_B A || B + + r : s + | t + ; + s : <>? ID + ; + t : <>? ID + ; + + ---------------------------------------------------------------------------- + t11.g, line 5: warning: the predicate used to disambiguate the + first choice of rule r + (file t11.g alt 1 line 5 and alt 2 line 6) + appears to "cover" the second predicate when compared without context. + The second predicate may have no resolving power for some lookahead + sequences. + ---------------------------------------------------------------------------- + +#132. (Changed in 1.33MR11) Recognition of identical predicates in alts + + Prior to 1.33MR11, there would be no ambiguity warning when the + very same predicate was used to disambiguate both alternatives: + + test: ref B + | ref C + ; + + ref : <>? A + + In 1.33MR11 this will cause the warning: + + warning: the predicates used to disambiguate rule test + (file v98.g alt 1 line 1 and alt 2 line 2) + are identical and have no resolving power + + ----------------- Note ----------------- + + This is different than the following case + + test: <>? A B + | <>? A C + ; + + In this case there are two distinct predicates + which have exactly the same text. In the first + example there are two references to the same + predicate. The problem represented by this + grammar will be addressed later. + + +#127. (Changed in 1.33MR11) + + Count Syntax Errors Count DLG Errors + ------------------- ---------------- + + C++ mode ANTLRParser:: DLGLexerBase:: + syntaxErrCount lexErrCount + C mode zzSyntaxErrCount zzLexErrCount + + The C mode variables are global and initialized to 0. + They are *not* reset to 0 automatically when antlr is + restarted. + + The C++ mode variables are public. They are initialized + to 0 by the constructors. They are *not* reset to 0 by the + ANTLRParser::init() method. + + Suggested by Reinier van den Born (reinier@vnet.ibm.com). + +#126. (Changed in 1.33MR11) Addition of #first <<...>> + + The #first <<...>> inserts the specified text in the output + files before any other #include statements required by pccts. + The only things before the #first text are comments and + a #define ANTLR_VERSION. + + Requested by and Esa Pulkkinen (esap@cs.tut.fi) and Alexin + Zoltan (alexin@inf.u-szeged.hu). + +#124. A Note on the New "&&" Style Guarded Predicates + + I've been asked several times, "What is the difference between + the old "=>" style guard predicates and the new style "&&" guard + predicates, and how do you choose one over the other" ? + + The main difference is that the "=>" does not apply the + predicate if the context guard doesn't match, whereas + the && form always does. What is the significance ? + + If you have a predicate which is not on the "leading edge" + it is cannot be hoisted. Suppose you need a predicate that + looks at LA(2). You must introduce it manually. The + classic example is: + + castExpr : + LP typeName RP + | .... + ; + + typeName : <>? ID + | STRUCT ID + ; + + The problem is that isTypeName() isn't on the leading edge + of typeName, so it won't be hoisted into castExpr to help + make a decision on which production to choose. + + The *first* attempt to fix it is this: + + castExpr : + <>? + LP typeName RP + | .... + ; + + Unfortunately, this won't work because it ignores + the problem of STRUCT. The solution is to apply + isTypeName() in castExpr if LA(2) is an ID and + don't apply it when LA(2) is STRUCT: + + castExpr : + (LP ID)? => <>? + LP typeName RP + | .... + ; + + In conclusion, the "=>" style guarded predicate is + useful when: + + a. the tokens required for the predicate + are not on the leading edge + b. there are alternatives in the expression + selected by the predicate for which the + predicate is inappropriate + + If (b) were false, then one could use a simple + predicate (assuming "-prc on"): + + castExpr : + <>? + LP typeName RP + | .... + ; + + typeName : <>? ID + ; + + So, when do you use the "&&" style guarded predicate ? + + The new-style "&&" predicate should always be used with + predicate context. The context guard is in ADDITION to + the automatically computed context. Thus it useful for + predicates which depend on the token type for reasons + other than context. + + The following example is contributed by Reinier van den Born + (reinier@vnet.ibm.com). + + +-------------------------------------------------------------------------+ + | This grammar has two ways to call functions: | + | | + | - a "standard" call syntax with parens and comma separated args | + | - a shell command like syntax (no parens and spacing separated args) | + | | + | The former also allows a variable to hold the name of the function, | + | the latter can also be used to call external commands. | + | | + | The grammar (simplified) looks like this: | + | | + | fun_call : ID "(" { expr ("," expr)* } ")" | + | /* ID is function name */ | + | | "@" ID "(" { expr ("," expr)* } ")" | + | /* ID is var containing fun name */ | + | ; | + | | + | command : ID expr* /* ID is function name */ | + | | path expr* /* path is external command name */ | + | ; | + | | + | path : ID /* left out slashes and such */ | + | | "@" ID /* ID is environment var */ | + | ; | + | | + | expr : .... | + | | "(" expr ")"; | + | | + | call : fun_call | + | | command | + | ; | + | | + | Obviously the call is wildly ambiguous. This is more or less how this | + | is to be resolved: | + | | + | A call begins with an ID or an @ followed by an ID. | + | | + | If it is an ID and if it is an ext. command name -> command | + | if followed by a paren -> fun_call | + | otherwise -> command | + | | + | If it is an @ and if the ID is a var name -> fun_call | + | otherwise -> command | + | | + | One can implement these rules quite neatly using && predicates: | + | | + | call : ("@" ID)? && <>? fun_call | + | | (ID)? && <>? command | + | | (ID "(")? fun_call | + | | command | + | ; | + | | + | This can be done better, so it is not an ideal example, but it | + | conveys the principle. | + +-------------------------------------------------------------------------+ + +#122. (Changed in 1.33MR11) Member functions to reset DLG in C++ mode + + void DLGFileReset(FILE *f) { input = f; found_eof = 0; } + void DLGStringReset(DLGChar *s) { input = s; p = &input[0]; } + + Supplied by R.A. Nelson (cowboy@VNET.IBM.COM) + +#119. (Changed in 1.33MR11) Ambiguity aid for grammars + + The user can ask for additional information on ambiguities reported + by antlr to stdout. At the moment, only one ambiguity report can + be created in an antlr run. + + This feature is enabled using the "-aa" (Ambiguity Aid) option. + + The following options control the reporting of ambiguities: + + -aa ruleName Selects reporting by name of rule + -aa lineNumber Selects reporting by line number + (file name not compared) + + -aam Selects "multiple" reporting for a token + in the intersection set of the + alternatives. + + For instance, the token ID may appear dozens + of times in various paths as the program + explores the rules which are reachable from + the point of an ambiguity. With option -aam + every possible path the search program + encounters is reported. + + Without -aam only the first encounter is + reported. This may result in incomplete + information, but the information may be + sufficient and much shorter. + + -aad depth Selects the depth of the search. + The default value is 1. + + The number of paths to be searched, and the + size of the report can grow geometrically + with the -ck value if a full search for all + contributions to the source of the ambiguity + is explored. + + The depth represents the number of tokens + in the lookahead set which are matched against + the set of ambiguous tokens. A depth of 1 + means that the search stops when a lookahead + sequence of just one token is matched. + + A k=1 ck=6 grammar might generate 5,000 items + in a report if a full depth 6 search is made + with the Ambiguity Aid. The source of the + problem may be in the first token and obscured + by the volume of data - I hesitate to call + it information. + + When the user selects a depth > 1, the search + is first performed at depth=1 for both + alternatives, then depth=2 for both alternatives, + etc. + + Sample output for rule grammar in antlr.g itself: + + +---------------------------------------------------------------------+ + | Ambiguity Aid | + | | + | Choice 1: grammar/70 line 632 file a.g | + | Choice 2: grammar/82 line 644 file a.g | + | | + | Intersection of lookahead[1] sets: | + | | + | "\}" "class" "#errclass" "#tokclass" | + | | + | Choice:1 Depth:1 Group:1 ("#errclass") | + | 1 in (...)* block grammar/70 line 632 a.g | + | 2 to error grammar/73 line 635 a.g | + | 3 error error/1 line 894 a.g | + | 4 #token "#errclass" error/2 line 895 a.g | + | | + | Choice:1 Depth:1 Group:2 ("#tokclass") | + | 2 to tclass grammar/74 line 636 a.g | + | 3 tclass tclass/1 line 937 a.g | + | 4 #token "#tokclass" tclass/2 line 938 a.g | + | | + | Choice:1 Depth:1 Group:3 ("class") | + | 2 to class_def grammar/75 line 637 a.g | + | 3 class_def class_def/1 line 669 a.g | + | 4 #token "class" class_def/3 line 671 a.g | + | | + | Choice:1 Depth:1 Group:4 ("\}") | + | 2 #token "\}" grammar/76 line 638 a.g | + | | + | Choice:2 Depth:1 Group:5 ("#errclass") | + | 1 in (...)* block grammar/83 line 645 a.g | + | 2 to error grammar/93 line 655 a.g | + | 3 error error/1 line 894 a.g | + | 4 #token "#errclass" error/2 line 895 a.g | + | | + | Choice:2 Depth:1 Group:6 ("#tokclass") | + | 2 to tclass grammar/94 line 656 a.g | + | 3 tclass tclass/1 line 937 a.g | + | 4 #token "#tokclass" tclass/2 line 938 a.g | + | | + | Choice:2 Depth:1 Group:7 ("class") | + | 2 to class_def grammar/95 line 657 a.g | + | 3 class_def class_def/1 line 669 a.g | + | 4 #token "class" class_def/3 line 671 a.g | + | | + | Choice:2 Depth:1 Group:8 ("\}") | + | 2 #token "\}" grammar/96 line 658 a.g | + +---------------------------------------------------------------------+ + + For a linear lookahead set ambiguity (where k=1 or for k>1 but + when all lookahead sets [i] with i>? A ; + c : A ; + + Prior to 1.33MR10 the code generated for "start" would resemble: + + while { + if (LA(1)==A && + (!LA(1)==A || isUpper())) { + a(); + } + }; + + This code is wrong because it makes rule "c" unreachable from + "start". The essence of the problem is that antlr fails to + recognize that there can be a valid alternative within "a" even + when the predicate <>? is false. + + In 1.33MR10 with -mrhoist the hoisting of the predicate into + "start" is suppressed because it recognizes that "c" can + cover all the cases where the predicate is false: + + while { + if (LA(1)==A) { + a(); + } + }; + + With the antlr "-info p" switch the user will receive information + about the predicate suppression in the generated file: + + -------------------------------------------------------------- + #if 0 + + Hoisting of predicate suppressed by alternative without predicate. + The alt without the predicate includes all cases where + the predicate is false. + + WITH predicate: line 7 v1.g + WITHOUT predicate: line 7 v1.g + + The context set for the predicate: + + A + + The lookahead set for the alt WITHOUT the semantic predicate: + + A + + The predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 9 v1.g + set context: + A + tree context: null + + Chain of referenced rules: + + #0 in rule start (line 5 v1.g) to rule a + #1 in rule a (line 7 v1.g) + + #endif + -------------------------------------------------------------- + + A predicate can be suppressed by a combination of alternatives + which, taken together, cover a predicate: + + start : (a)* "@" ; + + a : b | ca | cb | cc ; + + b : <>? ( A | B | C ) ; + + ca : A ; + cb : B ; + cc : C ; + + Consider a more complex example in which "c" covers only part of + a predicate: + + start : (a)* "@" ; + + a : b + | c + ; + + b : <>? + ( A + | X + ); + + c : A + ; + + Prior to 1.33MR10 the code generated for "start" would resemble: + + while { + if ( (LA(1)==A || LA(1)==X) && + (! (LA(1)==A || LA(1)==X) || isUpper()) { + a(); + } + }; + + With 1.33MR10 and -mrhoist the predicate context is restricted to + the non-covered lookahead. The code resembles: + + while { + if ( (LA(1)==A || LA(1)==X) && + (! (LA(1)==X) || isUpper()) { + a(); + } + }; + + With the antlr "-info p" switch the user will receive information + about the predicate restriction in the generated file: + + -------------------------------------------------------------- + #if 0 + + Restricting the context of a predicate because of overlap + in the lookahead set between the alternative with the + semantic predicate and one without + Without this restriction the alternative without the predicate + could not be reached when input matched the context of the + predicate and the predicate was false. + + WITH predicate: line 11 v4.g + WITHOUT predicate: line 12 v4.g + + The original context set for the predicate: + + A X + + The lookahead set for the alt WITHOUT the semantic predicate: + + A + + The intersection of the two sets + + A + + The original predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 15 v4.g + set context: + A X + tree context: null + + The new (modified) form of the predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 15 v4.g + set context: + X + tree context: null + + #endif + -------------------------------------------------------------- + + The bad news about -mrhoist: + + (a) -mrhoist does not analyze predicates with lookahead + depth > 1. + + (b) -mrhoist does not look past a guarded predicate to + find context which might cover other predicates. + + For these cases you might want to use syntactic predicates. + When a semantic predicate fails during guess mode the guess + fails and the next alternative is tried. + + Limitation (a) is illustrated by the following example: + + start : (stmt)* EOF ; + + stmt : cast + | expr + ; + cast : <>? LP ID RP ; + + expr : LP ID RP ; + + This is not much different from the first example, except that + it requires two tokens of lookahead context to determine what + to do. This predicate is NOT suppressed because the current version + is unable to handle predicates with depth > 1. + + A predicate can be combined with other predicates during hoisting. + In those cases the depth=1 predicates are still handled. Thus, + in the following example the isUpper() predicate will be suppressed + by line #4 when hoisted from "bizarre" into "start", but will still + be present in "bizarre" in order to predict "stmt". + + start : (bizarre)* EOF ; // #1 + // #2 + bizarre : stmt // #3 + | A // #4 + ; + + stmt : cast + | expr + ; + + cast : <>? LP ID RP ; + + expr : LP ID RP ; + | <>? A + + Limitation (b) is illustrated by the following example of a + context guarded predicate: + + rule : (A)? <

>? // #1 + (A // #2 + |B // #3 + ) // #4 + | <> B // #5 + ; + + Recall that this means that when the lookahead is NOT A then + the predicate "p" is ignored and it attempts to match "A|B". + Ideally, the "B" at line #3 should suppress predicate "q". + However, the current version does not attempt to look past + the guard predicate to find context which might suppress other + predicates. + + In some cases -mrhoist will lead to the reporting of ambiguities + which were not visible before: + + start : (a)* "@"; + a : bc | d; + bc : b | c ; + + b : <>? A; + c : A ; + + d : A ; + + In this case there is a true ambiguity in "a" between "bc" and "d" + which can both match "A". Without -mrhoist the predicate in "b" + is hoisted into "a" and there is no ambiguity reported. However, + with -mrhoist, the predicate in "b" is suppressed by "c" (as it + should be) making the ambiguity in "a" apparent. + + The motivations for these changes were hoisting problems reported + by Reinier van den Born (reinier@vnet.ibm.com) and several others. + +#113. (Changed in 1.33MR10) new context guarded pred: (g)? && <

>? expr + + The existing context guarded predicate: + + rule : (guard)? => <

>? expr + | next_alternative + ; + + generates code which resembles: + + if (lookahead(expr) && (!guard || pred)) { + expr() + } else .... + + This is not suitable for some applications because it allows + expr() to be invoked when the predicate is false. This is + intentional because it is meant to mimic automatically computed + predicate context. + + The new context guarded predicate uses the guard information + differently because it has a different goal. Consider: + + rule : (guard)? && <

>? expr + | next_alternative + ; + + The new style of context guarded predicate is equivalent to: + + rule : <>? expr + | next_alternative + ; + + It generates code which resembles: + + if (lookahead(expr) && guard && pred) { + expr(); + } else ... + + Both forms of guarded predicates severely restrict the form of + the context guard: it can contain no rule references, no + (...)*, no (...)+, and no {...}. It may contain token and + token class references, and alternation ("|"). + + Addition for 1.33MR11: in the token expression all tokens must + be at the same height of the token tree: + + (A ( B | C))? && ... is ok (all height 2) + (A ( B | ))? && ... is not ok (some 1, some 2) + (A B C D | E F G H)? && ... is ok (all height 4) + (A B C D | E )? && ... is not ok (some 4, some 1) + + This restriction is required in order to properly compute the lookahead + set for expressions like: + + rule1 : (A B C)? && <>? rule2 ; + rule2 : (A|X) (B|Y) (C|Z); + + This addition was suggested by Rienier van den Born (reinier@vnet.ibm.com) + +#109. (Changed in 1.33MR10) improved trace information + + The quality of the trace information provided by the "-gd" + switch has been improved significantly. Here is an example + of the output from a test program. It shows the rule name, + the first token of lookahead, the call depth, and the guess + status: + + exit rule gusxx {"?"} depth 2 + enter rule gusxx {"?"} depth 2 + enter rule gus1 {"o"} depth 3 guessing + guess done - returning to rule gus1 {"o"} at depth 3 + (guess mode continues - an enclosing guess is still active) + guess done - returning to rule gus1 {"Z"} at depth 3 + (guess mode continues - an enclosing guess is still active) + exit rule gus1 {"Z"} depth 3 guessing + guess done - returning to rule gusxx {"o"} at depth 2 (guess mode ends) + enter rule gus1 {"o"} depth 3 + guess done - returning to rule gus1 {"o"} at depth 3 (guess mode ends) + guess done - returning to rule gus1 {"Z"} at depth 3 (guess mode ends) + exit rule gus1 {"Z"} depth 3 + line 1: syntax error at "Z" missing SC + ... + + Rule trace reporting is controlled by the value of the integer + [zz]traceOptionValue: when it is positive tracing is enabled, + otherwise it is disabled. Tracing during guess mode is controlled + by the value of the integer [zz]traceGuessOptionValue. When + it is positive AND [zz]traceOptionValue is positive rule trace + is reported in guess mode. + + The values of [zz]traceOptionValue and [zz]traceGuessOptionValue + can be adjusted by subroutine calls listed below. + + Depending on the presence or absence of the antlr -gd switch + the variable [zz]traceOptionValueDefault is set to 0 or 1. When + the parser is initialized or [zz]traceReset() is called the + value of [zz]traceOptionValueDefault is copied to [zz]traceOptionValue. + The value of [zz]traceGuessOptionValue is always initialzed to 1, + but, as noted earlier, nothing will be reported unless + [zz]traceOptionValue is also positive. + + When the parser state is saved/restored the value of the trace + variables are also saved/restored. If a restore causes a change in + reporting behavior from on to off or vice versa this will be reported. + + When the -gd option is selected, the macro "#define zzTRACE_RULES" + is added to appropriate output files. + + C++ mode + -------- + int traceOption(int delta) + int traceGuessOption(int delta) + void traceReset() + int traceOptionValueDefault + + C mode + -------- + int zzTraceOption(int delta) + int zzTraceGuessOption(int delta) + void zzTraceReset() + int zzTraceOptionValueDefault + + The argument "delta" is added to the traceOptionValue. To + turn on trace when inside a particular rule one: + + rule : <> + ( + rest-of-rule + ) + <> + ; /* fail clause */ <> + + One can use the same idea to turn *off* tracing within a + rule by using a delta of (-1). + + An improvement in the rule trace was suggested by Sramji + Ramanathan (ps@kumaran.com). + +#108. A Note on Deallocation of Variables Allocated in Guess Mode + + NOTE + ------------------------------------------------------ + This mechanism only works for heap allocated variables + ------------------------------------------------------ + + The rewrite of the trace provides the machinery necessary + to properly free variables or undo actions following a + failed guess. + + The macro zzUSER_GUESS_HOOK(guessSeq,zzrv) is expanded + as part of the zzGUESS macro. When a guess is opened + the value of zzrv is 0. When a longjmp() is executed to + undo the guess, the value of zzrv will be 1. + + The macro zzUSER_GUESS_DONE_HOOK(guessSeq) is expanded + as part of the zzGUESS_DONE macro. This is executed + whether the guess succeeds or fails as part of closing + the guess. + + The guessSeq is a sequence number which is assigned to each + guess and is incremented by 1 for each guess which becomes + active. It is needed by the user to associate the start of + a guess with the failure and/or completion (closing) of a + guess. + + Guesses are nested. They must be closed in the reverse + of the order that they are opened. + + In order to free memory used by a variable during a guess + a user must write a routine which can be called to + register the variable along with the current guess sequence + number provided by the zzUSER_GUESS_HOOK macro. If the guess + fails, all variables tagged with the corresponding guess + sequence number should be released. This is ugly, but + it would require a major rewrite of antlr 1.33 to use + some mechanism other than setjmp()/longjmp(). + + The order of calls for a *successful* guess would be: + + zzUSER_GUESS_HOOK(guessSeq,0); + zzUSER_GUESS_DONE_HOOK(guessSeq); + + The order of calls for a *failed* guess would be: + + zzUSER_GUESS_HOOK(guessSeq,0); + zzUSER_GUESS_HOOK(guessSeq,1); + zzUSER_GUESS_DONE_HOOK(guessSeq); + + The default definitions of these macros are empty strings. + + Here is an example in C++ mode. The zzUSER_GUESS_HOOK and + zzUSER_GUESS_DONE_HOOK macros and myGuessHook() routine + can be used without change in both C and C++ versions. + + ---------------------------------------------------------------------- + << + + #include "AToken.h" + + typedef ANTLRCommonToken ANTLRToken; + + #include "DLGLexer.h" + + int main() { + + { + DLGFileInput in(stdin); + DLGLexer lexer(&in,2000); + ANTLRTokenBuffer pipe(&lexer,1); + ANTLRCommonToken aToken; + P parser(&pipe); + + lexer.setToken(&aToken); + parser.init(); + parser.start(); + }; + + fclose(stdin); + fclose(stdout); + return 0; + } + + >> + + << + char *s=NULL; + + #undef zzUSER_GUESS_HOOK + #define zzUSER_GUESS_HOOK(guessSeq,zzrv) myGuessHook(guessSeq,zzrv); + #undef zzUSER_GUESS_DONE_HOOK + #define zzUSER_GUESS_DONE_HOOK(guessSeq) myGuessHook(guessSeq,2); + + void myGuessHook(int guessSeq,int zzrv) { + if (zzrv == 0) { + fprintf(stderr,"User hook: starting guess #%d\n",guessSeq); + } else if (zzrv == 1) { + free (s); + s=NULL; + fprintf(stderr,"User hook: failed guess #%d\n",guessSeq); + } else if (zzrv == 2) { + free (s); + s=NULL; + fprintf(stderr,"User hook: ending guess #%d\n",guessSeq); + }; + } + + >> + + #token A "a" + #token "[\t \ \n]" <> + + class P { + + start : (top)+ + ; + + top : (which) ? <> + | other <> + ; <> + + which : which2 + ; + + which2 : which3 + ; + which3 + : (label)? <> + | (global)? <> + | (exclamation)? <> + ; + + label : <getText());>> A ":" ; + + global : <getText());>> A "::" ; + + exclamation : <getText());>> A "!" ; + + other : <getText());>> "other" ; + + } + ---------------------------------------------------------------------- + + This is a silly example, but illustrates the idea. For the input + "a ::" with tracing enabled the output begins: + + ---------------------------------------------------------------------- + enter rule "start" depth 1 + enter rule "top" depth 2 + User hook: starting guess #1 + enter rule "which" depth 3 guessing + enter rule "which2" depth 4 guessing + enter rule "which3" depth 5 guessing + User hook: starting guess #2 + enter rule "label" depth 6 guessing + guess failed + User hook: failed guess #2 + guess done - returning to rule "which3" at depth 5 (guess mode continues + - an enclosing guess is still active) + User hook: ending guess #2 + User hook: starting guess #3 + enter rule "global" depth 6 guessing + exit rule "global" depth 6 guessing + guess done - returning to rule "which3" at depth 5 (guess mode continues + - an enclosing guess is still active) + User hook: ending guess #3 + enter rule "global" depth 6 guessing + exit rule "global" depth 6 guessing + exit rule "which3" depth 5 guessing + exit rule "which2" depth 4 guessing + exit rule "which" depth 3 guessing + guess done - returning to rule "top" at depth 2 (guess mode ends) + User hook: ending guess #1 + enter rule "which" depth 3 + ..... + ---------------------------------------------------------------------- + + Remember: + + (a) Only init-actions are executed during guess mode. + (b) A rule can be invoked multiple times during guess mode. + (c) If the guess succeeds the rule will be called once more + without guess mode so that normal actions will be executed. + This means that the init-action might need to distinguish + between guess mode and non-guess mode using the variable + [zz]guessing. + +#101. (Changed in 1.33MR10) antlr -info command line switch + + -info + + p - extra predicate information in generated file + + t - information about tnode use: + at the end of each rule in generated file + summary on stderr at end of program + + m - monitor progress + prints name of each rule as it is started + flushes output at start of each rule + + f - first/follow set information to stdout + + 0 - no operation (added in 1.33MR11) + + The options may be combined and may appear in any order. + For example: + + antlr -info ptm -CC -gt -mrhoist on mygrammar.g + +#100a. (Changed in 1.33MR10) Predicate tree simplification + + When the same predicates can be referenced in more than one + alternative of a block large predicate trees can be formed. + + The difference that these optimizations make is so dramatic + that I have decided to use it even when -mrhoist is not selected. + + Consider the following grammar: + + start : ( all )* ; + + all : a + | d + | e + | f + ; + + a : c A B + | c A C + ; + + c : <>? + ; + + d : <>? B C + ; + + e : <>? B C + ; + + f : e X Y + ; + + In rule "a" there is a reference to rule "c" in both alternatives. + The length of the predicate AAA is k=2 and it can be followed in + alternative 1 only by (A B) while in alternative 2 it can be + followed only by (A C). Thus they do not have identical context. + + In rule "all" the alternatives which refer to rules "e" and "f" allow + elimination of the duplicate reference to predicate CCC. + + The table below summarized the kind of simplification performed by + 1.33MR10. In the table, X and Y stand for single predicates + (not trees). + + (OR X (OR Y (OR Z))) => (OR X Y Z) + (AND X (AND Y (AND Z))) => (AND X Y Z) + + (OR X (... (OR X Y) ... )) => (OR X (... Y ... )) + (AND X (... (AND X Y) ... )) => (AND X (... Y ... )) + (OR X (... (AND X Y) ... )) => (OR X (... ... )) + (AND X (... (OR X Y) ... )) => (AND X (... ... )) + + (AND X) => X + (OR X) => X + + In a test with a complex grammar for a real application, a predicate + tree with six OR nodes and 12 leaves was reduced to "(OR X Y Z)". + + In 1.33MR10 there is a greater effort to release memory used + by predicates once they are no longer in use. + +#100b. (Changed in 1.33MR10) Suppression of extra predicate tests + + The following optimizations require that -mrhoist be selected. + + It is relatively easy to optimize the code generated for predicate + gates when they are of the form: + + (AND X Y Z ...) + or (OR X Y Z ...) + + where X, Y, Z, and "..." represent individual predicates (leaves) not + predicate trees. + + If the predicate is an AND the contexts of the X, Y, Z, etc. are + ANDed together to create a single Tree context for the group and + context tests for the individual predicates are suppressed: + + -------------------------------------------------- + Note: This was incorrect. The contexts should be + ORed together. This has been fixed. A more + complete description is available in item #152. + --------------------------------------------------- + + Optimization 1: (AND X Y Z ...) + + Suppose the context for Xtest is LA(1)==LP and the context for + Ytest is LA(1)==LP && LA(2)==ID. + + Without the optimization the code would resemble: + + if (lookaheadContext && + !(LA(1)==LP && LA(1)==LP && LA(2)==ID) || + ( (! LA(1)==LP || Xtest) && + (! (LA(1)==LP || LA(2)==ID) || Xtest) + )) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==LP && LA(2)==ID) || (Xtest && Ytest) {... + + Optimization 2: (OR X Y Z ...) with identical contexts + + Suppose the context for Xtest is LA(1)==ID and for Ytest + the context is also LA(1)==ID. + + Without the optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==ID || LA(1)==ID) || + (LA(1)==ID && Xtest) || + (LA(1)==ID && Ytest) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + (! LA(1)==ID) || (Xtest || Ytest) {... + + Optimization 3: (OR X Y Z ...) with distinct contexts + + Suppose the context for Xtest is LA(1)==ID and for Ytest + the context is LA(1)==LP. + + Without the optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==ID || LA(1)==LP) || + (LA(1)==ID && Xtest) || + (LA(1)==LP && Ytest) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + (zzpf=0, + (LA(1)==ID && (zzpf=1) && Xtest) || + (LA(1)==LP && (zzpf=1) && Ytest) || + !zzpf) { + + These may appear to be of similar complexity at first, + but the non-optimized version contains two tests of each + context while the optimized version contains only one + such test, as well as eliminating some of the inverted + logic (" !(...) || "). + + Optimization 4: Computation of predicate gate trees + + When generating code for the gates of predicate expressions + antlr 1.33 vanilla uses a recursive procedure to generate + "&&" and "||" expressions for testing the lookahead. As each + layer of the predicate tree is exposed a new set of "&&" and + "||" expressions on the lookahead are generated. In many + cases the lookahead being tested has already been tested. + + With -mrhoist a lookahead tree is computed for the entire + lookahead expression. This means that predicates with identical + context or context which is a subset of another predicate's + context disappear. + + This is especially important for predicates formed by rules + like the following: + + uppperCaseVowel : <>? vowel; + vowel: : <>? LETTERS; + + These predicates are combined using AND since both must be + satisfied for rule upperCaseVowel. They have identical + context which makes this optimization very effective. + + The affect of Items #100a and #100b together can be dramatic. In + a very large (but real world) grammar one particular predicate + expression was reduced from an (unreadable) 50 predicate leaves, + 195 LA(1) terms, and 5500 characters to an (easily comprehensible) + 3 predicate leaves (all different) and a *single* LA(1) term. + +#98. (Changed in 1.33MR10) Option "-info p" + + When the user selects option "-info p" the program will generate + detailed information about predicates. If the user selects + "-mrhoist on" additional detail will be provided explaining + the promotion and suppression of predicates. The output is part + of the generated file and sandwiched between #if 0/#endif statements. + + Consider the following k=1 grammar: + + start : ( all ) * ; + + all : ( a + | b + ) + ; + + a : c B + ; + + c : <>? + | B + ; + + b : <>? X + ; + + Below is an excerpt of the output for rule "start" for the three + predicate options (off, on, and maintenance release style hoisting). + + For those who do not wish to use the "-mrhoist on" option for code + generation the option can be used in a "diagnostic" mode to provide + valuable information: + + a. where one should insert null actions to inhibit hoisting + b. a chain of rule references which shows where predicates are + being hoisted + + ====================================================================== + Example of "-info p" with "-mrhoist on" + ====================================================================== + #if 0 + + Hoisting of predicate suppressed by alternative without predicate. + The alt without the predicate includes all cases where the + predicate is false. + + WITH predicate: line 11 v36.g + WITHOUT predicate: line 12 v36.g + + The context set for the predicate: + + B + + The lookahead set for alt WITHOUT the semantic predicate: + + B + + The predicate: + + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + B + tree context: null + + Chain of referenced rules: + + #0 in rule start (line 1 v36.g) to rule all + #1 in rule all (line 3 v36.g) to rule a + #2 in rule a (line 8 v36.g) to rule c + #3 in rule c (line 11 v36.g) + + #endif + && + #if 0 + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + X + tree context: null + + #endif + ====================================================================== + Example of "-info p" with the default -prc setting ( "-prc off") + ====================================================================== + #if 0 + + OR + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + nil + tree context: null + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + nil + tree context: null + + #endif + ====================================================================== + Example of "-info p" with "-prc on" and "-mrhoist off" + ====================================================================== + #if 0 + + OR + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + B + tree context: null + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + X + tree context: null + + #endif + ====================================================================== + +#60. (Changed in 1.33MR7) Major changes to exception handling + + There were significant problems in the handling of exceptions + in 1.33 vanilla. The general problem is that it can only + process one level of exception handler. For example, a named + exception handler, an exception handler for an alternative, or + an exception for a subrule always went to the rule's exception + handler if there was no "catch" which matched the exception. + + In 1.33MR7 the exception handlers properly "nest". If an + exception handler does not have a matching "catch" then the + nextmost outer exception handler is checked for an appropriate + "catch" clause, and so on until an exception handler with an + appropriate "catch" is found. + + There are still undesirable features in the way exception + handlers are implemented, but I do not have time to fix them + at the moment: + + The exception handlers for alternatives are outside the + block containing the alternative. This makes it impossible + to access variables declared in a block or to resume the + parse by "falling through". The parse can still be easily + resumed in other ways, but not in the most natural fashion. + + This results in an inconsistentcy between named exception + handlers and exception handlers for alternatives. When + an exception handler for an alternative "falls through" + it goes to the nextmost outer handler - not the "normal + action". + + A major difference between 1.33MR7 and 1.33 vanilla is + the default action after an exception is caught: + + 1.33 Vanilla + ------------ + In 1.33 vanilla the signal value is set to zero ("NoSignal") + and the code drops through to the code following the exception. + For named exception handlers this is the "normal action". + For alternative exception handlers this is the rule's handler. + + 1.33MR7 + ------- + In 1.33MR7 the signal value is NOT automatically set to zero. + + There are two cases: + + For named exception handlers: if the signal value has been + set to zero the code drops through to the "normal action". + + For all other cases the code branches to the nextmost outer + exception handler until it reaches the handler for the rule. + + The following macros have been defined for convenience: + + C/C++ Mode Name + -------------------- + (zz)suppressSignal + set signal & return signal arg to 0 ("NoSignal") + (zz)setSignal(intValue) + set signal & return signal arg to some value + (zz)exportSignal + copy the signal value to the return signal arg + + I'm not sure why PCCTS make a distinction between the local + signal value and the return signal argument, but I'm loathe + to change the code. The burden of copying the local signal + value to the return signal argument can be given to the + default signal handler, I suppose. + +#53. (Explanation for 1.33MR6) What happens after an exception is caught ? + + The Book is silent about what happens after an exception + is caught. + + The following code fragment prints "Error Action" followed + by "Normal Action". + + test : Word ex:Number <> + exception[ex] + catch NoViableAlt: + <> + ; + + The reason for "Normal Action" is that the normal flow of the + program after a user-written exception handler is to "drop through". + In the case of an exception handler for a rule this results in + the exection of a "return" statement. In the case of an + exception handler attached to an alternative, rule, or token + this is the code that would have executed had there been no + exception. + + The user can achieve the desired result by using a "return" + statement. + + test : Word ex:Number <> + exception[ex] + catch NoViableAlt: + <> + ; + + The most powerful mechanism for recovery from parse errors + in pccts is syntactic predicates because they provide + backtracking. Exceptions allow "return", "break", + "consumeUntil(...)", "goto _handler", "goto _fail", and + changing the _signal value. + +#41. (Added in 1.33MR6) antlr -stdout + + Using "antlr -stdout ..." forces the text that would + normally go to the grammar.c or grammar.cpp file to + stdout. + +#40. (Added in 1.33MR6) antlr -tab to change tab stops + + Using "antlr -tab number ..." changes the tab stops + for the grammar.c or grammar.cpp file. The number + must be between 0 and 8. Using 0 gives tab characters, + values between 1 and 8 give the appropriate number of + space characters. + +#34. (Added to 1.33MR1) Add public DLGLexerBase::set_line(int newValue) + + Previously there was no public function for changing the line + number maintained by the lexer. + +#28. (Added to 1.33MR1) More control over DLG header + + Version 1.33MR1 adds the following directives to PCCTS + for C++ mode: + + #lexprefix <> + + Adds source code to the DLGLexer.h file + after the #include "DLexerBase.h" but + before the start of the class definition. + + #lexmember <> + + Adds source code to the DLGLexer.h file + as part of the DLGLexer class body. It + appears immediately after the start of + the class and a "public: statement. + diff --git a/Tools/Source/TianoTools/Pccts/KNOWN_PROBLEMS.txt b/Tools/Source/TianoTools/Pccts/KNOWN_PROBLEMS.txt new file mode 100644 index 0000000000..5a9b22e1bd --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/KNOWN_PROBLEMS.txt @@ -0,0 +1,241 @@ + + ======================================================= + Known Problems In PCCTS - Last revised 14 November 1998 + ======================================================= + +#17. The dlg fix for handling characters up to 255 is incorrect. + + See item #207. + + Reported by Frank Hartmann. + +#16. A note about "&&" predicates (Mike Dimmick) + + Mike Dimmick has pointed out a potential pitfall in the use of the + "&&" style predicate. Consider: + + r0: (g)? => <

>? r1 + | ... + ; + r1: A | B; + + If the context guard g is not a subset of the lookahead context for r1 + (in other words g is neither A nor B) then the code may execute r1 + even when the lookahead context is not satisfied. This is an error + by the person coding the grammer, and the error should be reported to + the user, but it isn't. expect. Some examples I've run seem to + indicate that such an error actually results in the rule becoming + unreachable. + + When g is properly coded the code is correct, the problem is when g + is not properly coded. + + A second problem reported by Mike Dimmick is that the test for a + failed validation predicate is equivalent to a test on the predicate + along. In other words, if the "&&" has not been hoisted then it may + falsely report a validation error. + +#15. (Changed in MR23) Warning for LT(i), LATEXT(i) in token match actions + + An bug (or at least an oddity) is that a reference to LT(1), LA(1), + or LATEXT(1) in an action which immediately follows a token match + in a rule refers to the token matched, not the token which is in + the lookahead buffer. Consider: + + r : abc <> D <> E; + + In this case LT(1) in action alpha will refer to the next token in + the lookahead buffer ("D"), but LT(1) in action beta will refer to + the token matched by D - the preceding token. + + A warning has been added which warns users about this when an action + following a token match contains a reference to LT(1), LA(1), or LATEXT(1). + + This behavior should be changed, but it appears in too many programs + now. Another problem, perhaps more significant, is that the obvious + fix (moving the consume() call to before the action) could change the + order in which input is requested and output appears in existing programs. + + This problem was reported, along with a fix by Benjamin Mandel + (beny@sd.co.il). However, I felt that changing the behavior was too + dangerous for existing code. + +#14. Parsing bug in dlg + + THM: I have been unable to reproduce this problem. + + Reported by Rick Howard Mijenix Corporation (rickh@mijenix.com). + + The regular expression parser (in rexpr.c) fails while + trying to parse the following regular expression: + + {[a-zA-Z]:}(\\\\[a-zA-Z0-9]*)+ + + See my comment in the following excerpt from rexpr.c: + + /* + * ::= ( '|' {} )* + * + * Return -1 if syntax error + * Return 0 if none found + * Return 1 if a regExrp was found + */ + static + regExpr(g) + GraphPtr g; + { + Graph g1, g2; + + if ( andExpr(&g1) == -1 ) + { + return -1; + } + + while ( token == '|' ) + { + int a; + next(); + a = andExpr(&g2); + if ( a == -1 ) return -1; /* syntax error below */ + else if ( !a ) return 1; /* empty alternative */ + g1 = BuildNFA_AorB(g1, g2); + } + + if ( token!='\0' ) return -1; + ***** + ***** It appears to fail here becuause token is 125 - the closing '}' + ***** If I change it to: + ***** if ( token!='\0' && token!='}' && token!= ')' ) return -1; + ***** + ***** It succeeds, but I'm not sure this is the corrrect approach. + ***** + *g = g1; + return 1; + } + +#13. dlg reports an invalid range for: [\0x00-\0xff] + + Diagnosed by Piotr Eljasiak (eljasiak@no-spam.zt.gdansk.tpsa.pl): + + Fixed in MR16. + +#12. Strings containing comment actions + + Sequences that looked like C style comments appearing in string + literals are improperly parsed by antlr/dlg. + + << fprintf(out," /* obsolete */ "); + + For this case use: + + << fprintf(out," \/\* obsolete \*\/ "); + + Reported by K.J. Cummings (cummings@peritus.com). + +#11. User hook for deallocation of variables on guess fail + + The mechanism outlined in Item #108 works only for + heap allocated variables. + +#10. Label re-initialization in ( X {y:Y} )* + + If a label assignment is optional and appears in a + (...)* or (...)+ block it will not be reset to NULL + when it is skipped by a subsequent iteration. + + Consider the example: + + ( X { y:Y })* Z + + with input: + + X Y X Z + + The first time through the block Y will be matched and + y will be set to point to the token. On the second + iteration of the (...)* block there is no match for Y. + But y will not be reset to NULL, as the user might + expect, it will contain a reference to the Y that was + matched in the first iteration. + + The work-around is to manually reset y: + + ( X << y = NULL; >> { y:Y } )* Z + + or + + ( X ( y:Y | << y = NULL; >> /* epsilon */ ) )* Z + + Reported by Jeff Vincent (JVincent@novell.com). + +#9. PCCTAST.h PCCTSAST::setType() is a noop + +#8. #tokdefs with ~Token and . + + THM: I have been unable to reproduce this problem. + + When antlr uses #tokdefs to define tokens the fields of + #errclass and #tokclass do not get properly defined. + When it subsequently attempts to take the complement of + the set of tokens (using ~Token or .) it can refer to + tokens which don't have names, generating a fatal error. + +#7. DLG crashes on some invalid inputs + + THM: In MR20 have fixed the most common cases. + + The following token defintion will cause DLG to crash. + + #token "()" + + Reported by Mengue Olivier (dolmen@bigfoot.com). + +#6. On MS systems \n\r is treated as two new lines + + Fixed. + +#5. Token expressions in #tokclass + + #errclass does not support TOK1..TOK2 or ~TOK syntax. + #tokclass does not support ~TOKEN syntax + + A workaround for #errclass TOK1..TOK2 is to use a + #tokclass. + + Reported by Dave Watola (dwatola@amtsun.jpl.nasa.gov) + +#4. A #tokdef must appear "early" in the grammar file. + + The "early" section of the grammar file is the only + place where the following directives may appear: + + #header + #first + #tokdefs + #parser + + Any other kind of statement signifiies the end of the + "early" section. + +#3. Use of PURIFY macro for C++ mode + + Item #93 of the CHANGES_FROM_1.33 describes the use of + the PURIFY macro to zero arguments to be passed by + upward inheritance. + + #define PURIFY(r, s) memset((char *) &(r), '\0', (s)); + + This may not be the right thing to do for C++ objects that + have constructors. Reported by Bonny Rais (bonny@werple.net.au). + + For those cases one should #define PURIFY to be an empty macro + in the #header or #first actions. + +#2. Fixed in 1.33MR10 - See CHANGES_FROM_1.33 Item #80. + +#1. The quality of support for systems with 8.3 file names leaves + much to be desired. Since the kit is distributed using the + long file names and the make file uses long file names it requires + some effort to generate. This will probably not be changed due + to the large number of systems already written using the long + file names. diff --git a/Tools/Source/TianoTools/Pccts/MPW_Read_Me b/Tools/Source/TianoTools/Pccts/MPW_Read_Me new file mode 100644 index 0000000000..70a9d1bcad --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/MPW_Read_Me @@ -0,0 +1,21 @@ + +1. You can control the creator type of generated files by changing a value of + #if control statement. + + + pccts:h:pcctscfg.h + + line 225-231 + + #if 0 + #define MAC_FILE_CREATOR 'MPS ' /* MPW Text files */ + #endif + #if 0 + #define MAC_FILE_CREATOR 'KAHL' /* THINK C/Symantec C++ Text files */ + #endif + #if 0 + #define MAC_FILE_CREATOR 'CWIE' /* Metrowerks C/C++ Text files */ + #endif + +2. If you want to build 68K version. You must convert all source files to Macintosh + format before compile. diff --git a/Tools/Source/TianoTools/Pccts/NOTES.bcc b/Tools/Source/TianoTools/Pccts/NOTES.bcc new file mode 100644 index 0000000000..1ac05b17c5 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/NOTES.bcc @@ -0,0 +1,184 @@ +March 95 +Version 1.32 of pccts + +At the moment this file is available via anonymous FTP at + + Node: marvin.ecn.purdue.edu + File: pub/pccts/1.32/NOTES.BCC + +Mail corrections or additions to David Seidel <71333.1575@compuserve.com> +=============================================================================== +Notes on Building PCCTS 1.32 with Borland C++ + +David Seidel, Innovative Data Concepts Incorporated +CompuServe: 71333,1575 +Internet: 71333.1575@compuserve.com + dseidel@delphi.com + +I have gotten ANTLR and DLG to succesfully build with BCC 4.0, but have found +from experience that ANTLR, in particular, is likely to run out of memory +with grammars over a certain size, or with larger values for the -k and -ck +options. Now that BCC 4.02 and the new Borland Power Pack for DOS is now +available, I feel that there is no excuse not to build these tools as +32-bit executables, as they ought to be. + +For people without the Power Pack, the makefiles below should be fairly easily +modified to build 16-bit real-mode executables, but I don't really recommend +it. As an alternative, you might consider the highly regarded DJGPP compiler +(a DOS port of the Gnu GCC compiler, with a DOS extender included). Hopefully +some other PCCTS who has DJGPP can provode whatever advice is necessary. The +Watcom compiler is also an excellent possibility (albeit a commercial one), +and I hope to make available Watcom makefiles in the near future. + +Here are the makefiles I am using. Both makefiles use a compiler configuration +file that contains compiler switches such as optimization settings. I call +this file bor32.cfg and keep a copy in both the ANTLR and DLG subdirectories. + +==== File: bor32.cfg (cut here) =============================================== +-w- +-RT- +-x- +-N- +-k- +-d +-O2-e-l +-Z +-D__STDC__=1 +==== End of file bor32.cfg (cut here) ========================================= + +==== File: antlr\bor32.mak (cut here) ========================================= +# +# ANTLR 1.32 Makefile for Borland C++ 4.02 with DPMI 32-bit DOS extender by +# David Seidel +# Innovative Data Concepts Incorporated +# 71333.1575@compuserve.com (or) dseidel@delphi.com +# +# Notes: 1. Compiler switches (optimization etc.) are contained in the +# file bor32.cfg. +# 2. This makefile requires Borland C++ 4.02 or greater with +# the DOS Power Pack add-on package. +# 3. Change the BCCDIR macro below to the topmost directory in +# which BCC is installed on your system. +# + +BCCDIR = d:\bc4 +CC = bcc32 +SET = ..\support\set +PCCTS_H = ..\h +ANTLR = ..\bin\antlr +DLG = ..\bin\dlg +CFLAGS = -I$(BCCDIR)\include -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN \ + +bor32.cfg +LIBS = dpmi32 cw32 +OBJ_EXT = obj +OBJS = antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj fset.obj \ + gen.obj globals.obj hash.obj lex.obj main.obj misc.obj pred.obj dialog.obj \ + set.obj + +.c.obj: + $(CC) -c $(CFLAGS) {$&.c } + +antlr.exe: $(OBJS) + tlink32 @&&| +-Tpe -ax -c -s -L$(BCCDIR)\lib + +$(BCCDIR)\lib\c0x32 $** +$@ + +$(LIBS) +; +| + copy *.exe ..\bin + + +# *********** Target list of PC machines *********** +# +# Don't worry about the ambiguity messages coming from antlr +# for making antlr.c etc... [should be 10 of them, I think] +# + +# leave this commented out for initial build! +#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g +# $(ANTLR) antlr.g + +antlr.$(OBJ_EXT): antlr.c mode.h tokens.h + +scan.$(OBJ_EXT): scan.c mode.h tokens.h + +# leave this commented out for initial build! +#scan.c mode.h: parser.dlg +# $(DLG) -C2 parser.dlg scan.c + +set.$(OBJ_EXT): $(SET)\set.c + $(CC) -c $(CFLAGS) $(SET)\set.c + +==== End of file antlr\bor32.mak (cut here) =================================== + +==== File: dlg\bor32.mak (cut here) =========================================== +# +# DLG 1.32 Makefile for Borland C++ 4.02 with DPMI 32-bit DOS extender by +# David Seidel +# Innovative Data Concepts Incorporated +# 71333.1575@compuserve.com (or) dseidel@delphi.com +# +# Notes: 1. Compiler switches (optimization etc.) are contained in the +# file bor32.cfg. +# 2. This makefile requires Borland C++ 4.02 or greater with +# the DOS Power Pack add-on package. +# 3. Change the BCCDIR macro below to the topmost directory in +# which BCC is installed on your system. +# + + +BCCDIR = d:\bc4 +CC = bcc32 +SET = ..\support\set +PCCTS_H = ..\h +ANTLR = ..\bin\antlr +DLG = ..\bin\dlg +CFLAGS = -I$(BCCDIR)\include -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN \ + +bor32.cfg +LIBS = dpmi32 cw32 +OBJ_EXT = obj +OBJS = dlg_p.obj dlg_a.obj main.obj err.obj support.obj \ + output.obj relabel.obj automata.obj set.obj + +.c.obj: + $(CC) -c $(CFLAGS) {$&.c } + +dlg.exe : $(OBJS) + tlink32 @&&| +-Tpe -ax -c -s -L$(BCCDIR)\lib + +c0x32 $** +$@ + +$(LIBS) +; +| + copy *.exe ..\bin + +dlg_p.obj: dlg_p.c + +dlg_a.obj: dlg_a.c + +main.obj: main.c + +err.obj: err.c + +support.obj: support.c + +output.obj: output.c + +relabel.obj: relabel.c + +automata.obj: automata.c + +set.$(OBJ_EXT): $(SET)\set.c + $(CC) -c $(CFLAGS) $(SET)\set.c + +==== End of file dlg\bor32.mak (cut here) ===================================== + + + + + + diff --git a/Tools/Source/TianoTools/Pccts/NOTES.msvc b/Tools/Source/TianoTools/Pccts/NOTES.msvc new file mode 100644 index 0000000000..86f8ed66e0 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/NOTES.msvc @@ -0,0 +1,189 @@ + + Microsoft Visual C Stuff + + +[Tom Moog 2-Oct-98 + + Users of Microsoft Visual C++ should download a separate + ready-to-run zip file from my web site. It contains + binaries, static library, and a sample project. +] + +[ + Two notes added by Tom Moog 23-Sep-97. I believe the *.dsp and + *.mak files that were once at the end of this file are now obsolete. + + The following MSVC .dsp and .mak files for pccts and sorcerer + were contributed by Stanislaw Bochnak (S.Bochnak@microtool.com.pl) + and Jeff Vincent (jvincent@novell.com) + + PCCTS Distribution Kit + ---------------------- + pccts/antlr/AntlrMSVC50.dsp + pccts/antlr/AntlrMSVC50.mak + + pccts/dlg/DlgMSVC50.dsp + pccts/dlg/DlgMSVC50.mak + + pccts/support/genmk/watgenmk.mak + pccts/support/msvc.dsp + + Sorcerer Distribution Kit + ------------------------- + pccts/sorcerer/SorcererMSVC50.dsp + pccts/sorcerer/SorcererMSVC50.mak + + pccts/sorcerer/lib/msvc.dsp + + I do not have an MS based computer. If you discover problems + please report them so as to save trouble for others in the future. +] + +[ + Modified by Terence Parr (September 1995) to change .C to .cpp +] + +[ + This file contains notes on MSVC for Windows NT console execs by Dave + Seidel and an explanation of flags etc.. by John Hall; good luck, + Terence +] + +=============================================================================== +Date: Sat, 31 Dec 1994 11:40:36 -0500 (EST) +From: David Seidel <75342.2034@compuserve.com> + +I've succesfully build 1.31b3 with djgpp for DOS and MSVC 2.0 for Windows +NT. The only (minor) problem I had was that GNU make (version 3.71, in the +djgpp port) complained about "multiple targets" in both the antlr and dlg +makefiles. I got around the error by, in each makefile, commenting out the +$(SRC) dependency, for example: + + antlr: $(OBJ) #$(SRC) + +I don't know why this is happenning, since you haven't changed that part of +the makefile at all, and I think this used to work ok... + +Here are the makefiles I built from within the MSVC 2.0 environment for antlr +and dlg and Windows NT console executables. Please feel free to pass them +on. Of course, as soon as 1.31 "goes gold", I will send you nice new +binaries. I'm not going to bother to keep doing both Borland and djgpp for +DOS however. Instead, I'll just keep the djgpp version up to date and also +provide WinNT binaries. + +Dave +=============================================================================== + + How to port PCCTS 1.10 (and 1.32 hopefully) to Visual C++ + + By + + John Hall + +Here is how to compile an ANTLR grammar in Visual C++. These steps +describe how to have your ANTLR grammar parse the input file the user +selects when they choose File Open in your Windows application. (Even +if you aren't using Visual C++, the steps should be portable enough to +other compilers.) + + * Make sure that ANTLR and DLG generate ANSI code (use the -ga + switch). + + * Set the following compiler flags in Visual C++ (these are in the + Memory Model category of the compiler options in the Project + Options menu): + + FLAG MEANING + ==== ============================================================== + /AL Large memory model (multiple data segments; data items must be + smaller than 64K). + + /Gtn Allocates all items whose size is greater than or equal to n + in a new data segment. (I let n be 256: /Gt256.) + + /Gx- All references to data items are done with far addressing in + case they are placed in a far segment. + + * Add the following member variable to the attributes section of your + derived CDocument class (you will need to make sure you also + include stdio.h): + + FILE *fp; + + * Add the following method to your derived CDocument class: + + BOOL CAppDoc::OnOpenDocument(const char* pszPathName) + { + // Call CDocument's OnOpenDocument to do housekeeping for us + // DON'T add anything to the loading section of Serialize + if (!CDocument::OnOpenDocument(pszPathName)) + return FALSE; + + // Open input file + if ((fp = fopen(pszPathName, "r")) == NULL) + return FALSE; + + // Parse input file + ANTLR(start(), fp); + + // Close input file + fclose(fp); + return TRUE; + } + + (Note: additional code may be necessary, depending on your parser. + For example, if your parser uses PCCTS's symbol table library, you + will need to insert calls to zzs_init and zzs_done.) + + * Compile the generated C files as C++ files. (I renamed the files + to have a .CPP extension to fool Visual C++ into thinking they were + C++ files. One might also use the /Tp switch, but that switch + requires you separately include the filename.) [I used this step + as an easy out for all the external linking errors I was getting + that I couldn't fix by declaring things extern "C".] + + * Make sure the __STDC__ portion of the generated files gets + compiled. (Either define __STDC__ yourself or else change all + occurrences of __STDC__ to __cplusplus in the generated files. You + can define __STDC__ in the Preprocessor category of the compiler + options.) + + ================================================================ + = Note 23-Sep-97: This is probably not necessary any more. = + = With 1.33MRxxx the use of __STDC__ was replaced with the = + = macro __USE_PROTOS to control the compilation of prototypes. = + ================================================================ + +That last step is important for Visual C++, but may not apply to other +compilers. For C++ compilers, whether __STDC__ is defined is +implementation dependent (ARM, page 379). Apparently, Visual C++ does +not to define it; it also does not support "old style" C function +definitions (which is okay, according to page 404 of the ARM). Those +two things together caused problems when trying to port the code. +When it saw this: + +#ifdef __STDC__ +void +globals(AST **_root) +#else +globals(_root) +AST **_root; +#endif + +it skipped the __STDC__ section and tried to process the "old style" +function definition, where it choked. + +When you finally get your parser to compile and link without error, +you may get General Protection Fault errors at run time. The problem +I had was that a NULL was passed to a variable argument function +without an explicit cast. The function grabbed a pointer (32-bits) +off the stack using va_arg, but the NULL was passed silently as the +integer 0 (16 bits), making the resulting pointer was invalid. (This +was in PCCTS's sample C parser.) + +There is one other thing I might suggest to help you avoid a run-time +error. Make sure you redefine the default error reporting function, +zzsyn. To do this, put "#define USER_ZZSYN" in your #header section +and put your own zzsyn somewhere. You can then pop up a MessageBox or +print the error to some output window. +=============================================================================== diff --git a/Tools/Source/TianoTools/Pccts/README b/Tools/Source/TianoTools/Pccts/README new file mode 100644 index 0000000000..d089b638b4 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/README @@ -0,0 +1,159 @@ + + Parr Research Corporation + with + Purdue University Electrical Engineering + and + University of Minnesota, AHPCRC + + Terence Parr + Russell Quong + Will Cohen + Hank Dietz + + +A central place for information about PCCTS 1.33 is: + + http://www.polhode.com/pccts.html + +The maintenance release is available from: + + http://www.polhode.com/pccts133mr.zip + +There is a ready-to-run version for win32 for Microsoft Visual Studio +at the same site. It is available from: + + http://www.polhode.com/win32.zip + +New users should visit http://www.polhode.com/pccts.html in +order to get the following document: + + "Notes For New Users of PCCTS" + +This is a Postscript file of about 40 pages which is extremely +useful for someone starting out. It is a based on 1.33mr21 + +When you have a little more experience, be sure to review the +following documents in the distribution kit: + + CHANGES_FROM_133.txt + CHANGES_FROM_133_BEFORE_MR13.txt + KNOWN_PROBLEMS.txt + +------------------------------------------------------------------------- + INSTALLATION (Unix) +------------------------------------------------------------------------- +0. Download http://www.polhode.com/pccts133mr.zip + +1. Unzip the distribution kit to your preferred location. + If there are newline problems try using zip -a ... + +2. cd to the main pccts directory. + +3. make + + This will create: + + antlr + dlg + sorcerer + genmk + +4. Copy to /usr/local/bin or /usr/local/bin if you like. If you + don't wish to then add pccts/bin to your path. + +5. To get an up-to-date list of program options execute the + program with no command line options. To get up-to-date + documentation read CHANGES_FROM_133*.txt and KNOWN_PROBLEMS.txt + at: + + http://www.polhode.com/pccts.html + +6. You need not create a library. The makefile created by genmk + assumes that the files are not part of a library. + + If you wish to create a library from elements of pccts/h: + + If the first letter of the filename is lowercase (uppercase) it is + related to the code generated using the pccts C mode (C++ mode). + Some of the .c and .cpp files in the h directory are not meant to + be placed in a library and will not compile because they are meant + to be #include in pccts generated files which are grammar specific. + + For C++ users place the following elements in the library: + + AParser.cpp + ASTBase.cpp + ATokenBuffer.cpp + BufFileInput.cpp (optional) + DLexerBase.cpp + PCCTSAST.cpp + SList.cpp + +------------------------------------------------------------------------- + INSTALLATION (Win32) +------------------------------------------------------------------------- + +I've tried to keep the win32 kit to the minimum necessary to get +up and running. The complete kit contains additional information +(some historical), source code, and DevStudio projects for +rebuilding pccts from the source code. + +The kit is now distributed with both MSVC 5 and MSVC6 style projects. + +0. Download http://www.polhode.com/win32.zip. + + You may also wish to download: + + http://www.polhode.com/CHANGES_FROM_133.txt + http://www.polhode.com/CHANGES_FROM_133_BEFORE_MR13.txt + http://www.polhode.com/KNOWN_PROBLEMS.txt + +1. Unzip the distribution kit to your preferred location. + + This will create: + + a pccts directory tree + pccts/bin/*.exe + pccts/lib/*.lib + pccts/h/* + sorcerer/lib/* + sorcerer/h/* + + an example directory tree + pccts\example\calcAST\* + pccts\example\simple\* + +2. Define the environment variable PCCTS to point to the main + pccts directory. + +3. Try building the simple project: pccts\example\simple\simple50.dsw + or simple60.dsw. + +4. Try building the complex project: pccts\example\calcAST\calcAST50.dsw + or calcAST60.dsw. + +------------------------------------------------------------------------- + INSTALLATION (DEC/VMS) +------------------------------------------------------------------------- + +DEC/VMS support added by Piéronne Jean-François (jfp@altavista.net) + +0. Download http://www.polhode.com/pccts133mr.zip + +1. Unzip the distribution kit to your preferred location. + +2. set default to the main pccts directory. + +3. @makefile.vms + + This will create in directory [.bin]: + + antlr.exe + dlg.exe + sorcerer.exe + genmk.exe + +5. To get an up-to-date list of program options execute the + program with no command line options. To get up-to-date + documentation read CHANGES_FROM_133*.txt and KNOWN_PROBLEMS.txt + at http://www.polhode.com/pccts.html. diff --git a/Tools/Source/TianoTools/Pccts/RIGHTS b/Tools/Source/TianoTools/Pccts/RIGHTS new file mode 100644 index 0000000000..9db175ff40 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/RIGHTS @@ -0,0 +1,26 @@ + +SOFTWARE RIGHTS + +We reserve no LEGAL rights to the Purdue Compiler Construction Tool +Set (PCCTS) -- PCCTS is in the public domain. An individual or +company may do whatever they wish with source code distributed with +PCCTS or the code generated by PCCTS, including the incorporation of +PCCTS, or its output, into commerical software. + +We encourage users to develop software with PCCTS. However, we do ask +that credit is given to us for developing PCCTS. By "credit", we mean +that if you incorporate our source code into one of your programs +(commercial product, research project, or otherwise) that you +acknowledge this fact somewhere in the documentation, research report, +etc... If you like PCCTS and have developed a nice tool with the +output, please mention that you developed it using PCCTS. In +addition, we ask that this header remain intact in our source code. +As long as these guidelines are kept, we expect to continue enhancing +this system and expect to make other tools available as they are +completed. + +ANTLR 1.33 +Terence Parr +Parr Research Corporation +with Purdue University and AHPCRC, University of Minnesota +1989-1995 diff --git a/Tools/Source/TianoTools/Pccts/antlr/AntlrMS.mak b/Tools/Source/TianoTools/Pccts/antlr/AntlrMS.mak new file mode 100644 index 0000000000..7c14993ee0 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/AntlrMS.mak @@ -0,0 +1,233 @@ +# PCCTS directory + +# You will need to set the LIB variable similar to this. +# LIB="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/lib;c:/Microsoft Visual Studio .NET 2003/Vc7/PlatformSDK/Lib" + +# PCCTS_HOME= +PCCTS_HOME=$(WORKSPACE)\Tools\Source\TianoTools\Pccts +ANTLR_SRC=$(PCCTS_HOME)\antlr +PCCTS_H=$(PCCTS_HOME)\h + + +# Support directories +SET=$(PCCTS_HOME)\support\set + + +# Compiler stuff +CC = cl +CFLAGS = /nologo -I "." -I "$(PCCTS_H)" -I "$(SET)" -D "USER_ZZSYN" -D "PC" \ + -D "ZZLEXBUFSIZE=65536" /D "LONGFILENAMES" /Zi /W3 -D__USE_PROTOS /wd4700 + +ANTLR_OBJS = antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ + fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ + misc.obj pred.obj egman.obj mrhoist.obj fcache.obj + +SUPPORT_OBJS = set.obj + +# Dependencies + +$(WORKSPACE)\Tools\bin\antlr.exe: $(ANTLR_OBJS) $(SUPPORT_OBJS) + $(CC) $(CFLAGS) -o antlr.exe $(ANTLR_OBJS) $(SUPPORT_OBJS) + del *.obj + move antlr.exe $(WORKSPACE)\Tools\bin + + +antlr.obj: $(ANTLR_SRC)\antlr.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\mode.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\antlr.c + +scan.obj: $(ANTLR_SRC)\scan.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgauto.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\mode.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\scan.c + +err.obj: $(ANTLR_SRC)\err.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(PCCTS_H)\err.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\err.c + +bits.obj: $(ANTLR_SRC)\bits.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\bits.c + +build.obj: $(ANTLR_SRC)\build.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\build.c + +fset2.obj: $(ANTLR_SRC)\fset2.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fset2.c + +fset.obj: $(ANTLR_SRC)\fset.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fset.c + +gen.obj: $(ANTLR_SRC)\gen.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\gen.c + +globals.obj: $(ANTLR_SRC)\globals.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\globals.c + +hash.obj: $(ANTLR_SRC)\hash.c \ + $(PCCTS_H)\config.h \ + $(ANTLR_SRC)\hash.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\hash.c + +lex.obj: $(ANTLR_SRC)\lex.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\lex.c + +main.obj: $(ANTLR_SRC)\main.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\mode.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\stdpccts.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\main.c + +misc.obj: $(ANTLR_SRC)\misc.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\misc.c + +pred.obj: $(ANTLR_SRC)\pred.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\pred.c + +egman.obj: $(ANTLR_SRC)\egman.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\egman.c + +mrhoist.obj: $(ANTLR_SRC)\mrhoist.c \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\mrhoist.c + +fcache.obj: $(ANTLR_SRC)\fcache.c \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fcache.c + +set.obj: $(SET)\set.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + + $(CC) -c $(CFLAGS) $(SET)\set.c + +clean: + del *.obj + +distclean: + del *.obj + del $(WORKSPACE)\Tools\bin\antlr.exe diff --git a/Tools/Source/TianoTools/Pccts/antlr/AntlrPPC.mak b/Tools/Source/TianoTools/Pccts/antlr/AntlrPPC.mak new file mode 100644 index 0000000000..9ede60d64c --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/AntlrPPC.mak @@ -0,0 +1,101 @@ +# Target: antlrPPC +# Sources: ::support:set:set.c +# antlr.c +# bits.c +# build.c +# egman.c +# err.c +# fcache.c +# fset2.c +# fset.c +# gen.c +# globals.c +# hash.c +# lex.c +# main.c +# misc.c +# mrhoist.c +# pred.c +# scan.c +# Created: Sunday, May 17, 1998 10:24:53 PM +# Author: Kenji Tanaka +MAKEFILE = antlrPPC.make +¥MondoBuild¥ = {MAKEFILE} # Make blank to avoid rebuilds when makefile is modified +Includes = ¶ + -i "::h:" ¶ + -i "::support:set:" +Sym¥PPC = +ObjDir¥PPC = :Obj: +PPCCOptions = {Includes} {Sym¥PPC} -w off -d MPW -d __STDC__=1 -d USER_ZZSYN +Objects¥PPC = ¶ + "{ObjDir¥PPC}set.c.x" ¶ + "{ObjDir¥PPC}antlr.c.x" ¶ + "{ObjDir¥PPC}bits.c.x" ¶ + "{ObjDir¥PPC}build.c.x" ¶ + "{ObjDir¥PPC}egman.c.x" ¶ + "{ObjDir¥PPC}err.c.x" ¶ + "{ObjDir¥PPC}fcache.c.x" ¶ + "{ObjDir¥PPC}fset2.c.x" ¶ + "{ObjDir¥PPC}fset.c.x" ¶ + "{ObjDir¥PPC}gen.c.x" ¶ + "{ObjDir¥PPC}globals.c.x" ¶ + "{ObjDir¥PPC}hash.c.x" ¶ + "{ObjDir¥PPC}lex.c.x" ¶ + "{ObjDir¥PPC}main.c.x" ¶ + "{ObjDir¥PPC}misc.c.x" ¶ + "{ObjDir¥PPC}mrhoist.c.x" ¶ + "{ObjDir¥PPC}pred.c.x" ¶ + "{ObjDir¥PPC}scan.c.x" +antlrPPC ÄÄ {¥MondoBuild¥} {Objects¥PPC} + PPCLink ¶ + -o {Targ} {Sym¥PPC} ¶ + {Objects¥PPC} ¶ + -t 'MPST' ¶ + -c 'MPS ' ¶ + "{SharedLibraries}InterfaceLib" ¶ + "{SharedLibraries}StdCLib" ¶ + #"{SharedLibraries}MathLib" ¶ + "{PPCLibraries}StdCRuntime.o" ¶ + "{PPCLibraries}PPCCRuntime.o" ¶ + "{PPCLibraries}PPCToolLibs.o" +"{ObjDir¥PPC}set.c.x" Ä {¥MondoBuild¥} "::support:set:set.c" + {PPCC} "::support:set:set.c" -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}antlr.c.x" Ä {¥MondoBuild¥} antlr.c + {PPCC} antlr.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}bits.c.x" Ä {¥MondoBuild¥} bits.c + {PPCC} bits.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}build.c.x" Ä {¥MondoBuild¥} build.c + {PPCC} build.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}egman.c.x" Ä {¥MondoBuild¥} egman.c + {PPCC} egman.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}err.c.x" Ä {¥MondoBuild¥} err.c + {PPCC} err.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}fcache.c.x" Ä {¥MondoBuild¥} fcache.c + {PPCC} fcache.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}fset2.c.x" Ä {¥MondoBuild¥} fset2.c + {PPCC} fset2.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}fset.c.x" Ä {¥MondoBuild¥} fset.c + {PPCC} fset.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}gen.c.x" Ä {¥MondoBuild¥} gen.c + {PPCC} gen.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}globals.c.x" Ä {¥MondoBuild¥} globals.c + {PPCC} globals.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}hash.c.x" Ä {¥MondoBuild¥} hash.c + {PPCC} hash.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}lex.c.x" Ä {¥MondoBuild¥} lex.c + {PPCC} lex.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}main.c.x" Ä {¥MondoBuild¥} main.c + {PPCC} main.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}misc.c.x" Ä {¥MondoBuild¥} misc.c + {PPCC} misc.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}mrhoist.c.x" Ä {¥MondoBuild¥} mrhoist.c + {PPCC} mrhoist.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}pred.c.x" Ä {¥MondoBuild¥} pred.c + {PPCC} pred.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}scan.c.x" Ä {¥MondoBuild¥} scan.c + {PPCC} scan.c -o {Targ} {PPCCOptions} + +antlrPPC ÄÄ antlr.r + Rez antlr.r -o antlrPPC -a +Install Ä antlrPPC + Duplicate -y antlrPPC "{MPW}"Tools:antlr diff --git a/Tools/Source/TianoTools/Pccts/antlr/README b/Tools/Source/TianoTools/Pccts/antlr/README new file mode 100644 index 0000000000..d7fc95916e --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/README @@ -0,0 +1,19 @@ + ANTLR 1.33 + +This directory contains the files necessary to build ANTLR. + +If you do a "make scrub", ANTLR will have to run on antlr.g and DLG +will have to run on parser.dlg. Either + +(1) ANTLR uses the previous antlr in that directory to rebuild itself +(2) Needs to find antlr on the search path + +You will find that running "antlr -gh antlr.g" will result in about +10 ambiguity warnings. These are normal. Don't worry. + +If you do a "make clean" right after installation, ANTLR and DLG should +not need to run; only the C files will compile. + +Don't forget to go into the makefile to uncomment the appropriate +definitions for your OS/architecture/compiler or see the appropriate +NOTES.?? file. diff --git a/Tools/Source/TianoTools/Pccts/antlr/antlr.1 b/Tools/Source/TianoTools/Pccts/antlr/antlr.1 new file mode 100644 index 0000000000..acfa85b066 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/antlr.1 @@ -0,0 +1,209 @@ +.TH ANTLR 1 "September 1995" "ANTLR" "PCCTS Manual Pages" +.SH NAME +antlr \- ANother Tool for Language Recognition +.SH SYNTAX +.LP +\fBantlr\fR [\fIoptions\fR] \fIgrammar_files\fR +.SH DESCRIPTION +.PP +\fIAntlr\fP converts an extended form of context-free grammar into a +set of C functions which directly implement an efficient form of +deterministic recursive-descent LL(k) parser. Context-free grammars +may be augmented with predicates to allow semantics to influence +parsing; this allows a form of context-sensitive parsing. Selective +backtracking is also available to handle non-LL(k) and even +non-LALR(k) constructs. \fIAntlr\fP also produces a definition of a +lexer which can be automatically converted into C code for a DFA-based +lexer by \fIdlg\fR. Hence, \fIantlr\fR serves a function much like +that of \fIyacc\fR, however, it is notably more flexible and is more +integrated with a lexer generator (\fIantlr\fR directly generates +\fIdlg\fR code, whereas \fIyacc\fR and \fIlex\fR are given independent +descriptions). Unlike \fIyacc\fR which accepts LALR(1) grammars, +\fIantlr\fR accepts LL(k) grammars in an extended BNF notation \(em +which eliminates the need for precedence rules. +.PP +Like \fIyacc\fR grammars, \fIantlr\fR grammars can use +automatically-maintained symbol attribute values referenced as dollar +variables. Further, because \fIantlr\fR generates top-down parsers, +arbitrary values may be inherited from parent rules (passed like +function parameters). \fIAntlr\fP also has a mechanism for creating +and manipulating abstract-syntax-trees. +.PP +There are various other niceties in \fIantlr\fR, including the ability to +spread one grammar over multiple files or even multiple grammars in a single +file, the ability to generate a version of the grammar with actions stripped +out (for documentation purposes), and lots more. +.SH OPTIONS +.IP "\fB-ck \fIn\fR" +Use up to \fIn\fR symbols of lookahead when using compressed (linear +approximation) lookahead. This type of lookahead is very cheap to +compute and is attempted before full LL(k) lookahead, which is of +exponential complexity in the worst case. In general, the compressed +lookahead can be much deeper (e.g, \f(CW-ck 10\fP) than the full +lookahead (which usually must be less than 4). +.IP \fB-CC\fP +Generate C++ output from both ANTLR and DLG. +.IP \fB-cr\fP +Generate a cross-reference for all rules. For each rule, print a list +of all other rules that reference it. +.IP \fB-e1\fP +Ambiguities/errors shown in low detail (default). +.IP \fB-e2\fP +Ambiguities/errors shown in more detail. +.IP \fB-e3\fP +Ambiguities/errors shown in excruciating detail. +.IP "\fB-fe\fP file" +Rename \fBerr.c\fP to file. +.IP "\fB-fh\fP file" +Rename \fBstdpccts.h\fP header (turns on \fB-gh\fP) to file. +.IP "\fB-fl\fP file" +Rename lexical output, \fBparser.dlg\fP, to file. +.IP "\fB-fm\fP file" +Rename file with lexical mode definitions, \fBmode.h\fP, to file. +.IP "\fB-fr\fP file" +Rename file which remaps globally visible symbols, \fBremap.h\fP, to file. +.IP "\fB-ft\fP file" +Rename \fBtokens.h\fP to file. +.IP \fB-ga\fP +Generate ANSI-compatible code (default case). This has not been +rigorously tested to be ANSI XJ11 C compliant, but it is close. The +normal output of \fIantlr\fP is currently compilable under both K&R, +ANSI C, and C++\(emthis option does nothing because \fIantlr\fP +generates a bunch of #ifdef's to do the right thing depending on the +language. +.IP \fB-gc\fP +Indicates that \fIantlr\fP should generate no C code, i.e., only +perform analysis on the grammar. +.IP \fB-gd\fP +C code is inserted in each of the \fIantlr\fR generated parsing functions to +provide for user-defined handling of a detailed parse trace. The inserted +code consists of calls to the user-supplied macros or functions called +\fBzzTRACEIN\fR and \fBzzTRACEOUT\fP. The only argument is a +\fIchar *\fR pointing to a C-style string which is the grammar rule +recognized by the current parsing function. If no definition is given +for the trace functions, upon rule entry and exit, a message will be +printed indicating that a particular rule as been entered or exited. +.IP \fB-ge\fP +Generate an error class for each non-terminal. +.IP \fB-gh\fP +Generate \fBstdpccts.h\fP for non-ANTLR-generated files to include. +This file contains all defines needed to describe the type of parser +generated by \fIantlr\fP (e.g. how much lookahead is used and whether +or not trees are constructed) and contains the \fBheader\fP action +specified by the user. +.IP \fB-gk\fP +Generate parsers that delay lookahead fetches until needed. Without +this option, \fIantlr\fP generates parsers which always have \fIk\fP +tokens of lookahead available. +.IP \fB-gl\fP +Generate line info about grammar actions in C parser of the form +\fB#\ \fIline\fP\ "\fIfile\fP"\fR which makes error messages from +the C/C++ compiler make more sense as they will \*Qpoint\*U into the +grammar file not the resulting C file. Debugging is easier as well, +because you will step through the grammar not C file. +.IP \fB-gs\fR +Do not generate sets for token expression lists; instead generate a +\fB||\fP-separated sequence of \fBLA(1)==\fItoken_number\fR. The +default is to generate sets. +.IP \fB-gt\fP +Generate code for Abstract-Syntax Trees. +.IP \fB-gx\fP +Do not create the lexical analyzer files (dlg-related). This option +should be given when the user wishes to provide a customized lexical +analyzer. It may also be used in \fImake\fR scripts to cause only the +parser to be rebuilt when a change not affecting the lexical structure +is made to the input grammars. +.IP "\fB-k \fIn\fR" +Set k of LL(k) to \fIn\fR; i.e. set tokens of look-ahead (default==1). +.IP "\fB-o\fP dir +Directory where output files should go (default="."). This is very +nice for keeping the source directory clear of ANTLR and DLG spawn. +.IP \fB-p\fP +The complete grammar, collected from all input grammar files and +stripped of all comments and embedded actions, is listed to +\fBstdout\fP. This is intended to aid in viewing the entire grammar +as a whole and to eliminate the need to keep actions concisely stated +so that the grammar is easier to read. Hence, it is preferable to +embed even complex actions directly in the grammar, rather than to +call them as subroutines, since the subroutine call overhead will be +saved. +.IP \fB-pa\fP +This option is the same as \fB-p\fP except that the output is +annotated with the first sets determined from grammar analysis. +.IP "\fB-prc on\fR +Turn on the computation and hoisting of predicate context. +.IP "\fB-prc off\fR +Turn off the computation and hoisting of predicate context. This +option makes 1.10 behave like the 1.06 release with option \fB-pr\fR +on. Context computation is off by default. +.IP "\fB-rl \fIn\fR +Limit the maximum number of tree nodes used by grammar analysis to +\fIn\fP. Occasionally, \fIantlr\fP is unable to analyze a grammar +submitted by the user. This rare situation can only occur when the +grammar is large and the amount of lookahead is greater than one. A +nonlinear analysis algorithm is used by PCCTS to handle the general +case of LL(k) parsing. The average complexity of analysis, however, is +near linear due to some fancy footwork in the implementation which +reduces the number of calls to the full LL(k) algorithm. An error +message will be displayed, if this limit is reached, which indicates +the grammar construct being analyzed when \fIantlr\fP hit a +non-linearity. Use this option if \fIantlr\fP seems to go out to +lunch and your disk start thrashing; try \fIn\fP=10000 to start. Once +the offending construct has been identified, try to remove the +ambiguity that \fIantlr\fP was trying to overcome with large lookahead +analysis. The introduction of (...)? backtracking blocks eliminates +some of these problems\ \(em \fIantlr\fP does not analyze alternatives +that begin with (...)? (it simply backtracks, if necessary, at run +time). +.IP \fB-w1\fR +Set low warning level. Do not warn if semantic predicates and/or +(...)? blocks are assumed to cover ambiguous alternatives. +.IP \fB-w2\fR +Ambiguous parsing decisions yield warnings even if semantic predicates +or (...)? blocks are used. Warn if predicate context computed and +semantic predicates incompletely disambiguate alternative productions. +.IP \fB-\fR +Read grammar from standard input and generate \fBstdin.c\fP as the +parser file. +.SH "SPECIAL CONSIDERATIONS" +.PP +\fIAntlr\fP works... we think. There is no implicit guarantee of +anything. We reserve no \fBlegal\fP rights to the software known as +the Purdue Compiler Construction Tool Set (PCCTS) \(em PCCTS is in the +public domain. An individual or company may do whatever they wish +with source code distributed with PCCTS or the code generated by +PCCTS, including the incorporation of PCCTS, or its output, into +commercial software. We encourage users to develop software with +PCCTS. However, we do ask that credit is given to us for developing +PCCTS. By "credit", we mean that if you incorporate our source code +into one of your programs (commercial product, research project, or +otherwise) that you acknowledge this fact somewhere in the +documentation, research report, etc... If you like PCCTS and have +developed a nice tool with the output, please mention that you +developed it using PCCTS. As long as these guidelines are followed, +we expect to continue enhancing this system and expect to make other +tools available as they are completed. +.SH FILES +.IP *.c +output C parser. +.IP *.cpp +output C++ parser when C++ mode is used. +.IP \fBparser.dlg\fP +output \fIdlg\fR lexical analyzer. +.IP \fBerr.c\fP +token string array, error sets and error support routines. Not used in +C++ mode. +.IP \fBremap.h\fP +file that redefines all globally visible parser symbols. The use of +the #parser directive creates this file. Not used in +C++ mode. +.IP \fBstdpccts.h\fP +list of definitions needed by C files, not generated by PCCTS, that +reference PCCTS objects. This is not generated by default. Not used in +C++ mode. +.IP \fBtokens.h\fP +output \fI#defines\fR for tokens used and function prototypes for +functions generated for rules. +.SH "SEE ALSO" +.LP +dlg(1), pccts(1) diff --git a/Tools/Source/TianoTools/Pccts/antlr/antlr.c b/Tools/Source/TianoTools/Pccts/antlr/antlr.c new file mode 100644 index 0000000000..8aaef794e1 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/antlr.c @@ -0,0 +1,3564 @@ +/* + * A n t l r T r a n s l a t i o n H e a d e r + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + * + * ..\bin\antlr -gh antlr.g + * + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include "pcctscfg.h" +#include "set.h" +#include +#include "syn.h" +#include "hash.h" +#include "generic.h" +#define zzcr_attr(attr,tok,t) +#define zzSET_SIZE 20 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "mode.h" + +/* MR23 In order to remove calls to PURIFY use the antlr -nopurify option */ + +#ifndef PCCTS_PURIFY +#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\0',(s)); +#endif + +ANTLR_INFO + + +/* MR20 G. Hobbelt For Borland C++ 4.x & 5.x compiling with ALL warnings enabled */ +#if defined(__TURBOC__) +#pragma warn -aus /* unused assignment of 'xxx' */ +#endif + + +#ifdef __USE_PROTOS +static void chkToken(char *, char *, char *, int); +#else +static void chkToken(); +#endif + +#ifdef __USE_PROTOS +static int isDLGmaxToken(char *Token); /* MR3 */ +#else +static int isDLGmaxToken(); /* MR3 */ +#endif + +static int class_nest_level = 0; + +/* MR20 G. Hobbelt extern definitions moved to antlr.h */ + + + +void +#ifdef __USE_PROTOS +grammar(void) +#else +grammar() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + Graph g; + { + zzBLOCK(zztasp2); + zzMake0; + { + for (;;) { + if ( !((setwd1[LA(1)]&0x1))) break; + if ( (LA(1)==94) ) { + zzmatch(94); zzCONSUME; + zzmatch(Action); + + if ( HdrAction==NULL ) { + HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(HdrAction!=NULL, "rule grammar: cannot allocate header action"); + strcpy(HdrAction, LATEXT(1)); + } + else warn("additional #header statement ignored"); + zzCONSUME; + + } + else { + if ( (LA(1)==95) ) { + zzmatch(95); zzCONSUME; + zzmatch(Action); + + if ( FirstAction==NULL ) { + FirstAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(FirstAction!=NULL, "rule grammar: cannot allocate #first action"); + strcpy(FirstAction, LATEXT(1)); + } else { + warn("additional #first statement ignored"); + }; + zzCONSUME; + + } + else { + if ( (LA(1)==96) ) { + zzmatch(96); zzCONSUME; + zzmatch(QuotedTerm); + + if ( GenCC ) { + warn("#parser meta-op incompatible with -CC; ignored"); + } + else { + if ( strcmp(ParserName,"zzparser")==0 ) { + ParserName=StripQuotes(mystrdup(LATEXT(1))); + if ( RulePrefix[0]!='\0' ) + { + warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored"); + RulePrefix[0]='\0'; + } + } + else warn("additional #parser statement ignored"); + } + zzCONSUME; + + } + else { + if ( (LA(1)==97) ) { + zzmatch(97); zzCONSUME; + zzmatch(QuotedTerm); + { + char *fname; + zzantlr_state st; FILE *f; struct zzdlg_state dst; + UserTokenDefsFile = mystrdup(LATEXT(1)); + zzsave_antlr_state(&st); + zzsave_dlg_state(&dst); + fname = mystrdup(LATEXT(1)); + f = fopen(StripQuotes(fname), "r"); + if ( f==NULL ) {warn(eMsg1("cannot open token defs file '%s'", fname+1));} + else { + ANTLRm(enum_file(fname+1), f, PARSE_ENUM_FILE); + UserDefdTokens = 1; + } + zzrestore_antlr_state(&st); + zzrestore_dlg_state(&dst); + } + zzCONSUME; + + } + else break; /* MR6 code for exiting loop "for sure" */ + } + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + for (;;) { + if ( !((setwd1[LA(1)]&0x2))) break; + if ( (LA(1)==Action) ) { + zzmatch(Action); + { + UserAction *ua = newUserAction(LATEXT(1)); + ua->file = action_file; ua->line = action_line; + if ( class_nest_level>0 ) list_add(&class_before_actions, ua); + else list_add(&BeforeActions, ua); + } + zzCONSUME; + + } + else { + if ( (LA(1)==108) ) { + laction(); + } + else { + if ( (LA(1)==109) ) { + lmember(); + } + else { + if ( (LA(1)==110) ) { + lprefix(); + } + else { + if ( (LA(1)==116) ) { + aLexclass(); + } + else { + if ( (LA(1)==120) ) { + token(); + } + else { + if ( (LA(1)==117) ) { + error(); + } + else { + if ( (LA(1)==118) ) { + tclass(); + } + else { + if ( (LA(1)==111) ) { + aPred(); + } + else { + if ( (LA(1)==133) ) { + default_exception_handler(); + } + else { + if ( (LA(1)==99) ) { + class_def(); + } + else { + if ( (LA(1)==98) ) { + zzmatch(98); + + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + zzCONSUME; + + } + else break; /* MR6 code for exiting loop "for sure" */ + } + } + } + } + } + } + } + } + } + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + rule(); + g=zzaArg(zztasp1,3); SynDiag = (Junction *) zzaArg(zztasp1,3 ).left; + { + zzBLOCK(zztasp2); + zzMake0; + { + for (;;) { + if ( !((setwd1[LA(1)]&0x4))) break; + if ( (LA(1)==NonTerminal) ) { + rule(); + if ( zzaArg(zztasp2,1 ).left!=NULL ) { + g.right = NULL; + +/* MR21a */ /* Avoid use of a malformed graph when CannotContinue */ + /* MR21a */ /* is already set */ + /* MR21a */ + /* MR21a */ if (! (CannotContinue && g.left == NULL)) { + /* MR21a */ g = Or(g, zzaArg(zztasp2,1)); + /* MR21a */ } + /* MR21a */ } + } + else { + if ( (LA(1)==116) ) { + aLexclass(); + } + else { + if ( (LA(1)==120) ) { + token(); + } + else { + if ( (LA(1)==117) ) { + error(); + } + else { + if ( (LA(1)==118) ) { + tclass(); + } + else { + if ( (LA(1)==111) ) { + aPred(); + } + else { + if ( (LA(1)==99) ) { + class_def(); + } + else { + if ( (LA(1)==98) ) { + zzmatch(98); + + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + zzCONSUME; + + } + else break; /* MR6 code for exiting loop "for sure" */ + } + } + } + } + } + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + for (;;) { + if ( !((setwd1[LA(1)]&0x8))) break; + if ( (LA(1)==Action) ) { + zzmatch(Action); + { + UserAction *ua = newUserAction(LATEXT(1)); + ua->file = action_file; ua->line = action_line; + if ( class_nest_level>0 ) list_add(&class_after_actions, ua); + else list_add(&AfterActions, ua); + } + zzCONSUME; + + } + else { + if ( (LA(1)==108) ) { + laction(); + } + else { + if ( (LA(1)==109) ) { + lmember(); + } + else { + if ( (LA(1)==110) ) { + lprefix(); + } + else { + if ( (LA(1)==117) ) { + error(); + } + else { + if ( (LA(1)==118) ) { + tclass(); + } + else { + if ( (LA(1)==99) ) { + class_def(); + } + else { + if ( (LA(1)==111) ) { + aPred(); + } + else { + if ( (LA(1)==98) ) { + zzmatch(98); + + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + zzCONSUME; + + } + else break; /* MR6 code for exiting loop "for sure" */ + } + } + } + } + } + } + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzmatch(Eof); zzCONSUME; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x10); + } +} + +void +#ifdef __USE_PROTOS +class_def(void) +#else +class_def() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + int go=1; char name[MaxRuleName+1]; + zzmatch(99); zzCONSUME; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==NonTerminal) ) { + zzmatch(NonTerminal); + if(go) strncpy(name,LATEXT(1),MaxRuleName); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if(go) strncpy(name,LATEXT(1),MaxRuleName); + zzCONSUME; + + } + else {zzFAIL(1,zzerr1,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + + if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0 + && GenCC ) { + err("only one grammar class allowed in this release"); + go = 0; + } + else strcpy(CurrentClassName, name); + if ( !GenCC ) { err("class meta-op used without C++ option"); } + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd1[LA(1)]&0x20) ) { + zzsetmatch(zzerr2, zzerr3); + if (ClassDeclStuff == NULL) { + /* MR10 */ ClassDeclStuff=(char *)calloc(MaxClassDeclStuff+1,sizeof(char)); + /* MR10 */ }; + /* MR10 */ strncat(ClassDeclStuff," ",MaxClassDeclStuff); + /* MR10 */ strncat(ClassDeclStuff,LATEXT(1),MaxClassDeclStuff); + /* MR22 */ do { + /* MR22 */ if (0 == strcmp(LATEXT(1),"public")) break; + /* MR22 */ if (0 == strcmp(LATEXT(1),"private")) break; + /* MR22 */ if (0 == strcmp(LATEXT(1),"protected")) break; + /* MR22 */ if (0 == strcmp(LATEXT(1),"virtual")) break; + /* MR22 */ if (0 == strcmp(LATEXT(1),",")) break; + /* MR22 */ if (0 == strcmp(LATEXT(1),":")) break; + /* MR22 */ if (BaseClassName != NULL) break; + /* MR22 */ BaseClassName=(char *)calloc(strlen(LATEXT(1))+1,sizeof(char)); + /* MR22 */ require(BaseClassName!=NULL, "rule grammar: cannot allocate base class name"); + /* MR22 */ strcpy(BaseClassName,LATEXT(1)); + /* MR22 */ } while (0); + /* MR10 */ + zzCONSUME; + + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzmatch(102); + + no_classes_found = 0; + if ( class_nest_level>=1 ) {warn("cannot have nested classes");} + else class_nest_level++; + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x40); + } +} + +void +#ifdef __USE_PROTOS +rule(void) +#else +rule() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + + + ExceptionGroup *eg; + RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e; + set toksrefd, rulesrefd; + char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL; + CurExGroups = NULL; + CurElementLabels = NULL; + CurAstLabelsInActions = NULL; /* MR27 */ + /* We want a new element label hash table for each rule */ + if ( Elabel!=NULL ) killHashTable(Elabel); + Elabel = newHashTable(); + attribsRefdFromAction = empty; + zzmatch(NonTerminal); + q=NULL; + if ( hash_get(Rname, LATEXT(1))!=NULL ) { + err(eMsg1("duplicate rule definition: '%s'",LATEXT(1))); + CannotContinue=TRUE; + } + else + { + q = (RuleEntry *)hash_add(Rname, + LATEXT(1), + (Entry *)newRuleEntry(LATEXT(1))); + CurRule = q->str; + } + CurRuleNode = q; + f = CurFile; l = zzline; + NumRules++; + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==103) ) { + zzmatch(103); + if ( q!=NULL ) q->noAST = TRUE; + zzCONSUME; + + } + else { + if ( (setwd1[LA(1)]&0x80) ) { + } + else {zzFAIL(1,zzerr4,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + ; + if ( (setwd2[LA(1)]&0x1) ) { + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==104) ) { + zzmatch(104); zzCONSUME; + } + else { + if ( (LA(1)==PassAction) ) { + } + else {zzFAIL(1,zzerr5,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + zzmatch(PassAction); + pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(pdecl!=NULL, "rule rule: cannot allocate param decl"); + strcpy(pdecl, LATEXT(1)); + CurParmDef = pdecl; + zzCONSUME; + + } + else { + if ( (setwd2[LA(1)]&0x2) ) { + } + else {zzFAIL(1,zzerr6,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==105) ) { + zzmatch(105); zzCONSUME; + zzmatch(PassAction); + ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(ret!=NULL, "rule rule: cannot allocate ret type"); + strcpy(ret, LATEXT(1)); + CurRetDef = ret; + zzCONSUME; + + } + else { + if ( (setwd2[LA(1)]&0x4) ) { + } + else {zzFAIL(1,zzerr7,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( q!=NULL ) q->egroup=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==106) ) { + } + else {zzFAIL(1,zzerr8,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + + if ( GenEClasseForRules && q!=NULL ) { + e = newECnode; + require(e!=NULL, "cannot allocate error class node"); + if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);} + else a = q->egroup; + if ( Tnum( a ) == 0 ) + { + e->tok = addTname( a ); + list_add(&eclasses, (char *)e); + if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]); + /* refers to itself */ + list_add(&(e->elist), mystrdup(q->str)); + } + else { + warn(eMsg1("default errclass for '%s' would conflict with token/errclass/tokclass",a)); + if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]); + free((char *)e); + } + } + BlkLevel++; + if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); + /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; + /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + zzmatch(106); + inAlt=1; + zzCONSUME; + + block( &toksrefd, &rulesrefd ); + r = makeBlk(zzaArg(zztasp1,7),0, NULL /* pFirstSetSymbol */ ); + CurRuleBlk = (Junction *)r.left; + CurRuleBlk->blockid = CurBlockID; + CurRuleBlk->jtype = RuleBlk; + if ( q!=NULL ) CurRuleBlk->rname = q->str; + CurRuleBlk->file = f; + CurRuleBlk->line = l; + CurRuleBlk->pdecl = pdecl; + CurRuleBlk->ret = ret; + CurRuleBlk->lock = makelocks(); + CurRuleBlk->pred_lock = makelocks(); + CurRuleBlk->tokrefs = toksrefd; + CurRuleBlk->rulerefs = rulesrefd; + p = newJunction(); /* add EndRule Node */ + ((Junction *)r.right)->p1 = (Node *)p; + r.right = (Node *) p; + p->jtype = EndRule; + p->lock = makelocks(); + p->pred_lock = makelocks(); + CurRuleBlk->end = p; + if ( q!=NULL ) q->rulenum = NumRules; + zzaArg(zztasp1,7) = r; + + /* MR23 */ CurBlockID_array[BlkLevel] = (-1); + /* MR23 */ CurAltNum_array[BlkLevel] = (-1); + --BlkLevel; + altFixup();leFixup();egFixup(); + zzmatch(107); + inAlt=0; + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==Action) ) { + zzmatch(Action); + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule rule: cannot allocate error action"); + strcpy(a, LATEXT(1)); + CurRuleBlk->erraction = a; + zzCONSUME; + + } + else { + if ( (setwd2[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr9,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==133) ) { + eg = exception_group(); + + if ( eg!=NULL ) { + list_add(&CurExGroups, (void *)eg); + if (eg->label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1; + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + if ( q==NULL ) zzaArg(zztasp1,0 ).left = NULL; else zzaArg(zztasp1,0) = zzaArg(zztasp1,7); + CurRuleBlk->exceptions = CurExGroups; + CurRuleBlk->el_labels = CurElementLabels; + CurRuleNode->ast_labels_in_actions = CurAstLabelsInActions; + CurRuleNode = NULL; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x10); + } +} + +void +#ifdef __USE_PROTOS +laction(void) +#else +laction() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *a; + zzmatch(108); zzCONSUME; + zzmatch(Action); + + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule laction: cannot allocate action"); + strcpy(a, LATEXT(1)); + list_add(&LexActions, a); + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x20); + } +} + +void +#ifdef __USE_PROTOS +lmember(void) +#else +lmember() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *a; + zzmatch(109); zzCONSUME; + zzmatch(Action); + + /* MR1 */ if (! GenCC) { + /* MR1 */ err("Use #lexmember only in C++ mode (to insert code in DLG class header"); + /* MR1 */ } else { + /* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + /* MR1 */ require(a!=NULL, "rule lmember: cannot allocate action"); + /* MR1 */ strcpy(a, LATEXT(1)); + /* MR1 */ list_add(&LexMemberActions, a); + /* MR1 */ }; + /* MR1 */ + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x40); + } +} + +void +#ifdef __USE_PROTOS +lprefix(void) +#else +lprefix() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *a; + zzmatch(110); zzCONSUME; + zzmatch(Action); + + /* MR1 */ if (! GenCC) { + /* MR1 */ err("Use #lexprefix only in C++ mode (to insert code in DLG class header"); + /* MR1 */ } else { + /* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + /* MR1 */ require(a!=NULL, "rule lprefix: cannot allocate action"); + /* MR1 */ strcpy(a, LATEXT(1)); + /* MR1 */ list_add(&LexPrefixActions, a); + /* MR1 */ }; + /* MR1 */ + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x80); + } +} + +void +#ifdef __USE_PROTOS +aPred(void) +#else +aPred() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + PredEntry *predEntry=NULL; + char *name=NULL; + Predicate *predExpr=NULL; + char *predLiteral=NULL; + int save_file; + int save_line; + int predExprPresent=0; + zzmatch(111); + + MR_usingPredNames=1; /* will need to use -mrhoist version of genPredTree */ + zzCONSUME; + + zzmatch(TokenTerm); + name=mystrdup(LATEXT(1)); + zzCONSUME; + + + /* don't free - referenced in predicates */ + + CurPredName=(char *)calloc(1,strlen(name) + 10); + strcat(CurPredName,"#pred "); + strcat(CurPredName,name); + + predEntry=(PredEntry *) hash_get(Pname,name); + if (predEntry != NULL) { + warnFL(eMsg1("#pred %s previously defined - ignored",name), + FileStr[action_file],action_line); + name=NULL; +}; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==Pred) ) { + zzmatch(Pred); + predLiteral=mystrdup(LATEXT(1)); + save_line=action_line; + save_file=action_file; + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (setwd3[LA(1)]&0x1) ) { + predExpr = predOrExpr(); + + predExprPresent=1; + } + else { + if ( (setwd3[LA(1)]&0x2) ) { + } + else {zzFAIL(1,zzerr10,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + if (predLiteral != NULL && name != NULL) { + + /* + * predExpr may be NULL due to syntax errors + * or simply omitted by the user + */ + + predEntry=newPredEntry(name); + predEntry->file=save_file; + predEntry->line=save_line; + predExpr=MR_predFlatten(predExpr); + predEntry->predLiteral=predLiteral; + if (! predExprPresent || predExpr == NULL) { + predExpr=new_pred(); + predExpr->expr=predLiteral; + predExpr->source=newActionNode(); + predExpr->source->action=predExpr->expr; + predExpr->source->rname=CurPredName; + predExpr->source->line=action_line; + predExpr->source->file=action_file; + predExpr->source->is_predicate=1; + predExpr->k=predicateLookaheadDepth(predExpr->source); + }; + predEntry->pred=predExpr; + hash_add(Pname,name,(Entry *)predEntry); + predExpr=NULL; + }; + predicate_free(predExpr); + } + else { + if ( (setwd3[LA(1)]&0x4) ) { + save_line=zzline; save_file=CurFile; + predExpr = predOrExpr(); + + if (predExpr != NULL && name != NULL) { + predEntry=newPredEntry(name); + predEntry->file=CurFile; + predEntry->line=zzline; + predExpr=MR_predFlatten(predExpr); + predEntry->pred=predExpr; + hash_add(Pname,name,(Entry *)predEntry); + predExpr=NULL; + }; + predicate_free(predExpr); + } + else {zzFAIL(1,zzerr11,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==107) ) { + zzmatch(107); zzCONSUME; + } + else { + if ( (setwd3[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr12,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + predicate_free(predExpr); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x10); + } +} + +Predicate * +#ifdef __USE_PROTOS +predOrExpr(void) +#else +predOrExpr() +#endif +{ + Predicate * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(Predicate * )) + zzMake0; + { + Predicate *ORnode; + Predicate *predExpr; + Predicate **tail=NULL; + predExpr = predAndExpr(); + + + ORnode=new_pred(); + ORnode->expr=PRED_OR_LIST; + if (predExpr != NULL) { + ORnode->down=predExpr; + tail=&predExpr->right; + }; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==112) ) { + zzmatch(112); zzCONSUME; + predExpr = predAndExpr(); + + + if (predExpr != NULL) { + *tail=predExpr; + tail=&predExpr->right; + }; + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + + _retv=ORnode; + ORnode=NULL; + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + predicate_free(ORnode); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x20); + return _retv; + } +} + +Predicate * +#ifdef __USE_PROTOS +predAndExpr(void) +#else +predAndExpr() +#endif +{ + Predicate * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(Predicate * )) + zzMake0; + { + Predicate *ANDnode; + Predicate *predExpr; + Predicate **tail=NULL; + predExpr = predPrimary(); + + + ANDnode=new_pred(); + ANDnode->expr=PRED_AND_LIST; + if (predExpr != NULL) { + ANDnode->down=predExpr; + tail=&predExpr->right; + }; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==113) ) { + zzmatch(113); zzCONSUME; + predExpr = predPrimary(); + + + if (predExpr != NULL) { + *tail=predExpr; + tail=&predExpr->right; + }; + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + + _retv=ANDnode; + ANDnode=NULL; + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + predicate_free(ANDnode); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x40); + return _retv; + } +} + +Predicate * +#ifdef __USE_PROTOS +predPrimary(void) +#else +predPrimary() +#endif +{ + Predicate * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(Predicate * )) + zzMake0; + { + + char *name=NULL; + PredEntry *predEntry=NULL; + Predicate *predExpr=NULL; + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + name=mystrdup(LATEXT(1)); + zzCONSUME; + + + predEntry=(PredEntry *) hash_get(Pname,name); + if (predEntry == NULL) { + warnFL(eMsg1("no previously defined #pred with name \"%s\"",name), + FileStr[CurFile],zzline); + name=NULL; + _retv=NULL; + } else { + predExpr=predicate_dup(predEntry->pred); + predExpr->predEntry=predEntry; + _retv=predExpr; + }; + } + else { + if ( (LA(1)==114) ) { + zzmatch(114); zzCONSUME; + predExpr = predOrExpr(); + + zzmatch(115); + + _retv=predExpr; + zzCONSUME; + + } + else { + if ( (LA(1)==103) ) { + zzmatch(103); zzCONSUME; + predExpr = predPrimary(); + + + predExpr->inverted=!predExpr->inverted; + _retv=predExpr; + } + else {zzFAIL(1,zzerr13,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + + predicate_free(predExpr); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x80); + return _retv; + } +} + +void +#ifdef __USE_PROTOS +aLexclass(void) +#else +aLexclass() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + zzmatch(116); zzCONSUME; + zzmatch(TokenTerm); + lexclass(mystrdup(LATEXT(1))); + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd4, 0x1); + } +} + +void +#ifdef __USE_PROTOS +error(void) +#else +error() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *t=NULL; ECnode *e; int go=1; TermEntry *p; + zzmatch(117); zzCONSUME; + { + zzBLOCK(zztasp2); + zzMake0; + { + ; + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr14,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + e = newECnode; + require(e!=NULL, "cannot allocate error class node"); + e->lexclass = CurrentLexClass; + if ( Tnum( (t=StripQuotes(t)) ) == 0 ) + { + if ( hash_get(Texpr, t) != NULL ) + warn(eMsg1("errclass name conflicts with regular expression '%s'",t)); + e->tok = addTname( t ); + set_orel(e->tok, &imag_tokens); + require((p=(TermEntry *)hash_get(Tname, t)) != NULL, + "hash table mechanism is broken"); + p->classname = 1; /* entry is errclass name, not token */ + list_add(&eclasses, (char *)e); + } + else + { + warn(eMsg1("redefinition of errclass or conflict w/token or tokclass '%s'; ignored",t)); + free( (char *)e ); + go=0; +} + zzmatch(102); zzCONSUME; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==NonTerminal) ) { + zzmatch(NonTerminal); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr15,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp2); + } + } + if ( go ) list_add(&(e->elist), t); + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd4[LA(1)]&0x2) ) { + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==NonTerminal) ) { + zzmatch(NonTerminal); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr16,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + if ( go ) list_add(&(e->elist), t); + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzmatch(98); zzCONSUME; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd4, 0x4); + } +} + +void +#ifdef __USE_PROTOS +tclass(void) +#else +tclass() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *t=NULL; TCnode *e; int go=1,tok,totok; TermEntry *p, *term, *toterm; + char *akaString=NULL; int save_file; int save_line; + char *totext=NULL; + zzmatch(118); zzCONSUME; + zzmatch(TokenTerm); + t=mystrdup(LATEXT(1)); + zzCONSUME; + + e = newTCnode; + require(e!=NULL, "cannot allocate token class node"); + e->lexclass = CurrentLexClass; + if ( Tnum( t ) == 0 ) + { + e->tok = addTname( t ); + set_orel(e->tok, &imag_tokens); + set_orel(e->tok, &tokclasses); + require((p=(TermEntry *)hash_get(Tname, t)) != NULL, + "hash table mechanism is broken"); + p->classname = 1; /* entry is class name, not token */ + p->tclass = e; /* save ptr to this tclass def */ + list_add(&tclasses, (char *)e); + } + else + { + warn(eMsg1("redefinition of tokclass or conflict w/token '%s'; ignored",t)); + free( (char *)e ); + go=0; +} + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==114) ) { + zzmatch(114); zzCONSUME; + zzmatch(QuotedTerm); + akaString=mystrdup(StripQuotes(LATEXT(1))); + /* MR11 */ save_file=CurFile;save_line=zzline; + /* MR23 */ + zzCONSUME; + + zzmatch(115); zzCONSUME; + } + else { + if ( (LA(1)==102) ) { + } + else {zzFAIL(1,zzerr17,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + + /* MR23 */ if (p!= NULL && akaString != NULL) { + /* MR23 */ if (p->akaString != NULL) { + /* MR23 */ if (strcmp(p->akaString,akaString) != 0) { + /* MR23 */ warnFL(eMsg2("this #tokclass statment conflicts with a previous #tokclass %s(\"%s\") statement", + /* MR23 */ t,p->akaString), + /* MR23 */ FileStr[save_file],save_line); + /* MR23 */ }; + /* MR23 */ } else { + /* MR23 */ p->akaString=akaString; + /* MR23 */ }; + /* MR23 */ }; + /* MR23 */ + zzmatch(102); zzCONSUME; + { + zzBLOCK(zztasp2); + int zzcnt=1; + zzMake0; + { + do { + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if ( go ) { + term = (TermEntry *) hash_get(Tname, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + go = 0; + } + else {t=mystrdup(LATEXT(1)); tok=addTname(LATEXT(1));} + } + zzCONSUME; + + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==119) ) { + zzmatch(119); zzCONSUME; + zzmatch(TokenTerm); + if ( go ) { + toterm = (TermEntry *) hash_get(Tname, LATEXT(1)); + if ( toterm==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + go = 0; + } else { + totext=mystrdup(LATEXT(1)); totok=addTname(LATEXT(1)); + } + } + zzCONSUME; + + } + else { + if ( (setwd4[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr18,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + } + else { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( go ) { + term = (TermEntry *) hash_get(Texpr, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + go = 0; + } + else {t=mystrdup(LATEXT(1)); tok=addTexpr(LATEXT(1));} + } + zzCONSUME; + + } + else {zzFAIL(1,zzerr19,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + if ( go ) { + if (totext == NULL) { + list_add(&(e->tlist), t); + } else { + list_add(&(e->tlist),".."); + list_add(&(e->tlist),t); + list_add(&(e->tlist),totext); + } + totext=NULL; + } + zzLOOP(zztasp2); + } while ( (setwd4[LA(1)]&0x10) ); + zzEXIT(zztasp2); + } + } + zzmatch(98); zzCONSUME; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd4, 0x20); + } +} + +void +#ifdef __USE_PROTOS +token(void) +#else +token() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *t=NULL, *e=NULL, *a=NULL; int tnum=0; + char *akaString=NULL; TermEntry *te;int save_file=0,save_line=0; + zzmatch(120); + tokenActionActive=1; + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + t=mystrdup(LATEXT(1)); + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==114) ) { + zzmatch(114); zzCONSUME; + zzmatch(QuotedTerm); + akaString=mystrdup(StripQuotes(LATEXT(1))); + /* MR11 */ save_file=CurFile;save_line=zzline; + /* MR11 */ + zzCONSUME; + + zzmatch(115); zzCONSUME; + } + else { + if ( (setwd4[LA(1)]&0x40) ) { + } + else {zzFAIL(1,zzerr20,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==121) ) { + zzmatch(121); zzCONSUME; + zzmatch(122); + tnum = atoi(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd4[LA(1)]&0x80) ) { + } + else {zzFAIL(1,zzerr21,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + } + else { + if ( (setwd5[LA(1)]&0x1) ) { + } + else {zzFAIL(1,zzerr22,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + e=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd5[LA(1)]&0x2) ) { + } + else {zzFAIL(1,zzerr23,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==Action) ) { + zzmatch(Action); + + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule token: cannot allocate action"); + strcpy(a, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd5[LA(1)]&0x4) ) { + } + else {zzFAIL(1,zzerr24,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==107) ) { + zzmatch(107); zzCONSUME; + } + else { + if ( (setwd5[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr25,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + chkToken(t, e, a, tnum); + if (t != NULL) { + te=(TermEntry *)hash_get(Tname,t); + if (te != NULL && akaString != NULL) { + if (te->akaString != NULL) { + if (strcmp(te->akaString,akaString) != 0) { + warnFL(eMsg2("this #token statment conflicts with a previous #token %s(\"%s\") statement", + t,te->akaString), + FileStr[save_file],save_line); + }; + } else { + te->akaString=akaString; + }; + }; + }; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd5, 0x10); + } +} + +void +#ifdef __USE_PROTOS +block(set * toksrefd,set * rulesrefd) +#else +block(toksrefd,rulesrefd) + set *toksrefd; +set *rulesrefd ; +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + + Graph g, b; + set saveblah; + int saveinalt = inAlt; + ExceptionGroup *eg; + * toksrefd = empty; + * rulesrefd = empty; + set_clr(AST_nodes_refd_in_actions); + CurBlockID++; + /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; + CurAltNum = 1; + /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + saveblah = attribsRefdFromAction; + attribsRefdFromAction = empty; + alt( toksrefd,rulesrefd ); + b = g = zzaArg(zztasp1,1); + + if ( ((Junction *)g.left)->p1->ntype == nAction ) + { + ActionNode *actionNode=(ActionNode *) + ( ( (Junction *)g.left) ->p1); + if (!actionNode->is_predicate ) + { + actionNode->init_action = TRUE; + /* MR12c */ if (actionNode->noHoist) { + /* MR12c */ errFL("<> appears as init-action - use <<>> <>", + /* MR12c */ FileStr[actionNode->file],actionNode->line); + /* MR12c */ }; + } + } + ((Junction *)g.left)->blockid = CurBlockID; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==133) ) { + eg = exception_group(); + + + if ( eg!=NULL ) { + /* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/ + /* MR7 ***** CurAltStart->exception_label = eg->altID; *****/ + list_add(&CurExGroups, (void *)eg); + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + CurAltNum++; + /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==123) ) { + zzmatch(123); + inAlt=1; + zzCONSUME; + + alt( toksrefd,rulesrefd ); + g = Or(g, zzaArg(zztasp2,2)); + + ((Junction *)g.left)->blockid = CurBlockID; + { + zzBLOCK(zztasp3); + zzMake0; + { + while ( (LA(1)==133) ) { + eg = exception_group(); + + + if ( eg!=NULL ) { + /* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/ + /* MR7 ***** CurAltStart->exception_label = eg->altID; *****/ + list_add(&CurExGroups, (void *)eg); + } + zzLOOP(zztasp3); + } + zzEXIT(zztasp3); + } + } + CurAltNum++; + /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzaArg(zztasp1,0) = b; + attribsRefdFromAction = saveblah; inAlt = saveinalt; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd5, 0x20); + } +} + +void +#ifdef __USE_PROTOS +alt(set * toksrefd,set * rulesrefd) +#else +alt(toksrefd,rulesrefd) + set *toksrefd; +set *rulesrefd ; +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + int n=0; Graph g; int e_num=0, old_not=0; Node *node; set elems, dif; + int first_on_line = 1, use_def_MT_handler = 0; + g.left=NULL; g.right=NULL; + + CurAltStart = NULL; + elems = empty; + inAlt = 1; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==88) ) { + zzmatch(88); + use_def_MT_handler = 1; + zzCONSUME; + + } + else { + if ( (setwd5[LA(1)]&0x40) ) { + } + else {zzFAIL(1,zzerr26,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + ; + while ( (setwd5[LA(1)]&0x80) ) { + { + zzBLOCK(zztasp3); + zzMake0; + { + old_not=0; + if ( (LA(1)==124) ) { + zzmatch(124); + old_not=1; + zzCONSUME; + + } + else { + if ( (setwd6[LA(1)]&0x1) ) { + } + else {zzFAIL(1,zzerr27,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + node = element( old_not, first_on_line, use_def_MT_handler ); + + if ( node!=NULL && node->ntype!=nAction ) first_on_line = 0; + + if ( zzaArg(zztasp2,2 ).left!=NULL ) { + g = Cat(g, zzaArg(zztasp2,2)); + n++; + if ( node!=NULL ) { + if ( node->ntype!=nAction ) e_num++; + /* record record number of all rule and token refs */ + if ( node->ntype==nToken ) { + TokNode *tk = (TokNode *)((Junction *)zzaArg(zztasp2,2 ).left)->p1; + tk->elnum = e_num; + set_orel(e_num, &elems); + } + else if ( node->ntype==nRuleRef ) { + RuleRefNode *rn = (RuleRefNode *)((Junction *)zzaArg(zztasp2,2 ).left)->p1; + rn->elnum = e_num; + set_orel(e_num, rulesrefd); + } + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + if ( n == 0 ) g = emptyAlt(); + zzaArg(zztasp1,0) = g; + /* We want to reduce number of LT(i) calls and the number of + * local attribute variables in C++ mode (for moment, later we'll + * do for C also). However, if trees are being built, they + * require most of the attrib variables to create the tree nodes + * with; therefore, we gen a token ptr for each token ref in C++ + */ + if ( GenCC && !GenAST ) + { + /* This now free's the temp set -ATG 5/6/95 */ + set temp; + temp = set_and(elems, attribsRefdFromAction); + set_orin( toksrefd, temp); + set_free(temp); +} +else set_orin( toksrefd, elems); +if ( GenCC ) { + dif = set_dif(attribsRefdFromAction, elems); + if ( set_deg(dif)>0 ) + err("one or more $i in action(s) refer to non-token elements"); + set_free(dif); +} +set_free(elems); +set_free(attribsRefdFromAction); +inAlt = 0; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd6, 0x2); + } +} + +LabelEntry * +#ifdef __USE_PROTOS +element_label(void) +#else +element_label() +#endif +{ + LabelEntry * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(LabelEntry * )) + zzMake0; + { + TermEntry *t=NULL; LabelEntry *l=NULL; RuleEntry *r=NULL; char *lab; + zzmatch(LABEL); + lab = mystrdup(LATEXT(1)); + zzCONSUME; + + + UsedNewStyleLabel = 1; + if ( UsedOldStyleAttrib ) err("cannot mix with new-style labels with old-style $i"); + t = (TermEntry *) hash_get(Tname, lab); + if ( t==NULL ) t = (TermEntry *) hash_get(Texpr, lab); + if ( t==NULL ) r = (RuleEntry *) hash_get(Rname, lab); + if ( t!=NULL ) { + err(eMsg1("label definition clashes with token/tokclass definition: '%s'", lab)); + _retv = NULL; + } + else if ( r!=NULL ) { + err(eMsg1("label definition clashes with rule definition: '%s'", lab)); + _retv = NULL; + } + else { + /* we don't clash with anybody else */ + l = (LabelEntry *) hash_get(Elabel, lab); + if ( l==NULL ) { /* ok to add new element label */ + l = (LabelEntry *)hash_add(Elabel, + lab, + (Entry *)newLabelEntry(lab)); + /* add to list of element labels for this rule */ + list_add(&CurElementLabels, (void *)lab); + /* MR7 */ leAdd(l); /* list of labels waiting for exception group definitions */ + _retv = l; + } + else { + err(eMsg1("label definitions must be unique per rule: '%s'", lab)); + _retv = NULL; +} +} + zzmatch(106); zzCONSUME; + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd6, 0x4); + return _retv; + } +} + +Node * +#ifdef __USE_PROTOS +element(int old_not,int first_on_line,int use_def_MT_handler) +#else +element(old_not,first_on_line,use_def_MT_handler) + int old_not; +int first_on_line; +int use_def_MT_handler ; +#endif +{ + Node * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(Node * )) + zzMake0; + { + + Attrib blk; + Predicate *pred = NULL; + int local_use_def_MT_handler=0; + ActionNode *act; + RuleRefNode *rr; + set toksrefd, rulesrefd; + TermEntry *term; + TokNode *p=NULL; RuleRefNode *q; int approx=0; + LabelEntry *label=NULL; + int predMsgDone=0; + int semDepth=0; + int ampersandStyle; + int height; /* MR11 */ + int equal_height; /* MR11 */ + + char* pFirstSetSymbol = NULL; /* MR21 */ + + _retv = NULL; + if ( (setwd6[LA(1)]&0x8) ) { + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==LABEL) ) { + label = element_label(); + + } + else { + if ( (setwd6[LA(1)]&0x10) ) { + } + else {zzFAIL(1,zzerr28,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + + term = (TermEntry *) hash_get(Tname, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + zzaRet.left = zzaRet.right = NULL; + } + else { + zzaRet = buildToken(LATEXT(1)); + p=((TokNode *)((Junction *)zzaRet.left)->p1); + term = (TermEntry *) hash_get(Tname, LATEXT(1)); + require( term!= NULL, "hash table mechanism is broken"); + p->tclass = term->tclass; + p->complement = old_not; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==119) ) { + zzmatch(119); zzCONSUME; + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( p!=NULL ) setUpperRange(p, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if ( p!=NULL ) setUpperRange(p, LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr29,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + } + else { + if ( (setwd6[LA(1)]&0x20) ) { + } + else {zzFAIL(1,zzerr30,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + + if ( p!=NULL && (p->upper_range!=0 || p->tclass || old_not) ) + list_add(&MetaTokenNodes, (void *)p); + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==125) ) { + zzmatch(125); + if ( p!=NULL ) p->astnode=ASTroot; + zzCONSUME; + + } + else { + if ( (setwd6[LA(1)]&0x40) ) { + if ( p!=NULL ) p->astnode=ASTchild; + } + else { + if ( (LA(1)==103) ) { + zzmatch(103); + if ( p!=NULL ) p->astnode=ASTexclude; + zzCONSUME; + + } + else {zzFAIL(1,zzerr31,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==88) ) { + zzmatch(88); + local_use_def_MT_handler = 1; + zzCONSUME; + + } + else { + if ( (setwd6[LA(1)]&0x80) ) { + } + else {zzFAIL(1,zzerr32,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + + if ( p!=NULL && first_on_line ) { + CurAltStart = (Junction *)zzaRet.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + } + if ( p!=NULL ) + p->use_def_MT_handler = use_def_MT_handler || local_use_def_MT_handler; + _retv = (Node *)p; + } + else { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + + term = (TermEntry *) hash_get(Texpr, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + zzaRet.left = zzaRet.right = NULL; + } + else { + zzaRet = buildToken(LATEXT(1)); p=((TokNode *)((Junction *)zzaRet.left)->p1); + p->complement = old_not; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==119) ) { + zzmatch(119); zzCONSUME; + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( p!=NULL ) setUpperRange(p, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if ( p!=NULL ) setUpperRange(p, LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr33,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + } + else { + if ( (setwd7[LA(1)]&0x1) ) { + } + else {zzFAIL(1,zzerr34,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==125) ) { + zzmatch(125); + if ( p!=NULL ) p->astnode=ASTroot; + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x2) ) { + if ( p!=NULL ) p->astnode=ASTchild; + } + else { + if ( (LA(1)==103) ) { + zzmatch(103); + if ( p!=NULL ) p->astnode=ASTexclude; + zzCONSUME; + + } + else {zzFAIL(1,zzerr35,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==88) ) { + zzmatch(88); + local_use_def_MT_handler = 1; + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x4) ) { + } + else {zzFAIL(1,zzerr36,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + + if ( p!=NULL && (p->upper_range!=0 || p->tclass || old_not) ) + list_add(&MetaTokenNodes, (void *)p); + + if ( first_on_line ) { + CurAltStart = (Junction *)zzaRet.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + } + if ( p!=NULL ) + p->use_def_MT_handler = use_def_MT_handler || local_use_def_MT_handler; + _retv = (Node *)p; + } + else { + if ( (LA(1)==WildCard) ) { + if ( old_not ) warn("~ WILDCARD is an undefined operation (implies 'nothing')"); + zzmatch(WildCard); + zzaRet = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)zzaRet.left)->p1); + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==125) ) { + zzmatch(125); + p->astnode=ASTroot; + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x8) ) { + p->astnode=ASTchild; + } + else { + if ( (LA(1)==103) ) { + zzmatch(103); + p->astnode=ASTexclude; + zzCONSUME; + + } + else {zzFAIL(1,zzerr37,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + list_add(&MetaTokenNodes, (void *)p); + + if ( first_on_line ) { + CurAltStart = (Junction *)zzaRet.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + _retv = (Node *)p; + } + else { + if ( (LA(1)==NonTerminal) ) { + if ( old_not ) warn("~ NONTERMINAL is an undefined operation"); + zzmatch(NonTerminal); + zzaRet = buildRuleRef(LATEXT(1)); + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==103) ) { + zzmatch(103); + q = (RuleRefNode *) ((Junction *)zzaRet.left)->p1; + q->astnode=ASTexclude; + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x10) ) { + } + else {zzFAIL(1,zzerr38,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (setwd7[LA(1)]&0x20) ) { + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==104) ) { + zzmatch(104); zzCONSUME; + } + else { + if ( (LA(1)==PassAction) ) { + } + else {zzFAIL(1,zzerr39,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + zzmatch(PassAction); + addParm(((Junction *)zzaRet.left)->p1, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x40) ) { + } + else {zzFAIL(1,zzerr40,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + rr=(RuleRefNode *) ((Junction *)zzaRet.left)->p1; + { + zzBLOCK(zztasp3); + zzMake0; + { + char *a; + if ( (LA(1)==105) ) { + zzmatch(105); zzCONSUME; + zzmatch(PassAction); + + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate assignment"); + strcpy(a, LATEXT(1)); + rr->assign = a; + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x80) ) { + } + else {zzFAIL(1,zzerr41,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + + if ( label!=NULL ) { + rr->el_label = label->str; + label->elem = (Node *)rr; + } + if ( first_on_line ) { + CurAltStart = (Junction *)zzaRet.left; + altAdd(CurAltStart); /* MR7 */ + ((RuleRefNode *)((Junction *)zzaRet.left)->p1)->altstart = CurAltStart; + } + _retv = (Node *)rr; + } + else {zzFAIL(1,zzerr42,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + zzEXIT(zztasp2); + } + } + } + else { + if ( (LA(1)==Action) ) { + if ( old_not ) warn("~ ACTION is an undefined operation"); + zzmatch(Action); + zzaArg(zztasp1,0) = buildAction(LATEXT(1),action_file,action_line, 0); + zzCONSUME; + + if ( first_on_line ) { /* MR7 */ + CurAltStart = (Junction *)zzaArg(zztasp1,0 ).left; /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + _retv = (Node *) ((Junction *)zzaArg(zztasp1,0 ).left)->p1; + } + else { + if ( (LA(1)==Pred) ) { + if ( old_not ) warn("~ SEMANTIC-PREDICATE is an undefined operation"); + zzmatch(Pred); + zzaArg(zztasp1,0) = buildAction(LATEXT(1),action_file,action_line, 1); + zzCONSUME; + + act = (ActionNode *) ((Junction *)zzaArg(zztasp1,0 ).left)->p1; + if (numericActionLabel) { /* MR10 */ + list_add(&NumericPredLabels,act); /* MR10 */ + numericActionLabel=0; /* MR10 */ + }; /* MR10 */ + { + zzBLOCK(zztasp2); + zzMake0; + { + char *a; + if ( (LA(1)==PassAction) ) { + zzmatch(PassAction); + + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate predicate fail action"); + strcpy(a, LATEXT(1)); + act->pred_fail = a; + zzCONSUME; + + } + else { + if ( (setwd8[LA(1)]&0x1) ) { + } + else {zzFAIL(1,zzerr43,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + if ( first_on_line ) { /* MR7 */ + CurAltStart = (Junction *)zzaArg(zztasp1,0 ).left; /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + _retv = (Node *)act; + } + else { + if ( (setwd8[LA(1)]&0x2) ) { + if ( old_not ) warn("~ BLOCK is an undefined operation"); + BlkLevel++; + if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); + /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; + /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==Pragma) ) { + zzmatch(Pragma); zzCONSUME; + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==126) ) { + zzmatch(126); + approx=LL_k; + zzCONSUME; + + } + else { + if ( (LA(1)==127) ) { + zzmatch(127); + approx = 1; + zzCONSUME; + + } + else { + if ( (LA(1)==128) ) { + zzmatch(128); + approx = 2; + zzCONSUME; + + } + else {zzFAIL(1,zzerr44,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + } + else { + if ( (setwd8[LA(1)]&0x4) ) { + } + else {zzFAIL(1,zzerr45,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==FirstSetSymbol) ) { + zzmatch(FirstSetSymbol); zzCONSUME; + zzmatch(114); zzCONSUME; + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==NonTerminal) ) { + zzmatch(NonTerminal); + + /* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1, + /* MR21 */ sizeof(char)); + /* MR21 */ require(pFirstSetSymbol!=NULL, + /* MR21 */ "cannot allocate first set name"); + /* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1)); + /* MR21 */ + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + + /* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1, + /* MR21 */ sizeof(char)); + /* MR21 */ require(pFirstSetSymbol!=NULL, + /* MR21 */ "cannot allocate first set name"); + /* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1)); + /* MR21 */ + zzCONSUME; + + } + else {zzFAIL(1,zzerr46,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + zzmatch(115); zzCONSUME; + } + else { + if ( (setwd8[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr47,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==114) ) { + zzmatch(114); zzCONSUME; + block( &toksrefd,&rulesrefd ); + zzmatch(115); + blk = zzaRet = zzaArg(zztasp2,2); + /* MR23 */ CurBlockID_array[BlkLevel] = (-1); + /* MR23 */ CurAltNum_array[BlkLevel] = (-1); + --BlkLevel; + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==129) ) { + zzmatch(129); + zzaRet = makeLoop(zzaRet,approx,pFirstSetSymbol); + zzCONSUME; + + } + else { + if ( (LA(1)==130) ) { + zzmatch(130); + zzaRet = makePlus(zzaRet,approx,pFirstSetSymbol); + zzCONSUME; + + } + else { + if ( (LA(1)==131) ) { + zzmatch(131); zzCONSUME; + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (setwd8[LA(1)]&0x10) ) { + { + zzBLOCK(zztasp5); + zzMake0; + { + if ( (LA(1)==132) ) { + zzmatch(132); + ampersandStyle=0; + zzCONSUME; + + } + else { + if ( (LA(1)==113) ) { + zzmatch(113); + ampersandStyle=1; + zzCONSUME; + + } + else {zzFAIL(1,zzerr48,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp5); + } + } + zzmatch(Pred); + zzaRet = buildAction(LATEXT(1),action_file,action_line,1); + zzCONSUME; + + act = (ActionNode *) ((Junction *)zzaRet.left)->p1; + semDepth=predicateLookaheadDepth(act); + if (numericActionLabel) { /* MR10 */ + list_add(&NumericPredLabels,act); /* MR10 */ + numericActionLabel=0; /* MR10 */ + }; /* MR10 */ + { + zzBLOCK(zztasp5); + zzMake0; + { + char *a; + if ( (LA(1)==PassAction) ) { + zzmatch(PassAction); + + a = (char *)calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate predicate fail action"); + strcpy(a, LATEXT(1)); + act->pred_fail = a; + zzCONSUME; + + } + else { + if ( (setwd8[LA(1)]&0x20) ) { + } + else {zzFAIL(1,zzerr49,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp5); + } + } + if ( first_on_line) { /* MR7 */ + CurAltStart=(Junction *)zzaRet.left; /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + _retv = (Node *)act; + + pred = computePredFromContextGuard(blk,&predMsgDone); /* MR10 */ + if ( pred==NULL) { /* MR10 */ + if ( !predMsgDone) err("invalid or missing context guard"); /* MR10 */ + predMsgDone=1; /* MR10 */ + } else { /* MR10 */ + act->guardNodes=(Junction *)blk.left; /* MR11 */ + pred->expr = act->action; + pred->source = act; + /* MR10 */ pred->ampersandStyle = ampersandStyle; /* 0 means (g)? => ... 1 means (g)? && ... */ + /* MR13 */ if (pred->tcontext != NULL) { + /* MR13 */ height=MR_max_height_of_tree(pred->tcontext); + /* MR13 */ equal_height=MR_all_leaves_same_height(pred->tcontext,height); + /* MR13 */ if (! equal_height) { + /* MR13 */ errFL("in guarded predicates all tokens in the guard must be at the same height", + /* MR13 */ FileStr[act->file],act->line); + /* MR13 */ }; + /* MR13 */ } + /* MR10 */ if (ampersandStyle) { + /* MR10 */ act->ampersandPred = pred; + /* MR11 */ if (! HoistPredicateContext) { + /* MR11 */ errFL("without \"-prc on\" (guard)? && <>? ... doesn't make sense", + /* MR11 */ FileStr[act->file],act->line); + /* MR11 */ }; + /* MR10 */ } else { + /* MR10 */ act->guardpred = pred; + /* MR10 */ }; + /* MR10 */ if (pred->k != semDepth) { + /* MR10 */ warn(eMsgd2("length of guard (%d) does not match the length of semantic predicate (%d)", + /* MR10 */ pred->k,semDepth)); + /* MR10 */ }; + } + } + else { + if ( (setwd8[LA(1)]&0x40) ) { + zzaRet = makeBlk(zzaRet,approx,pFirstSetSymbol); + FoundGuessBlk = 1; + ((Junction *) ((Junction *)zzaRet.left)->p1)->guess=1; + if ( ! first_on_line ) { + err("(...)? predicate must be first element of production"); + } + } + else {zzFAIL(1,zzerr50,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + } + else { + if ( (setwd8[LA(1)]&0x80) ) { + zzaRet = makeBlk(zzaRet,approx,pFirstSetSymbol); + } + else {zzFAIL(1,zzerr51,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + zzEXIT(zztasp3); + } + } + + if ( pred==NULL && !predMsgDone) { /* MR10 */ + ((Junction *)((Junction *)zzaRet.left)->p1)->blockid = CurBlockID; + ((Junction *)((Junction *)zzaRet.left)->p1)->tokrefs = toksrefd; + ((Junction *)((Junction *)zzaRet.left)->p1)->rulerefs = rulesrefd; + if ( first_on_line ) { /* MR7 */ + CurAltStart = (Junction *)((Junction *)((Junction *)zzaRet.left)->p1); /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; /* MR7 */ + _retv = (Node *) ((Junction *)zzaRet.left)->p1; + } + } + else { + if ( (LA(1)==102) ) { + zzmatch(102); zzCONSUME; + block( &toksrefd,&rulesrefd ); + zzaRet = makeOpt(zzaArg(zztasp2,2),approx,pFirstSetSymbol); + /* MR23 */ CurBlockID_array[BlkLevel] = (-1); + /* MR23 */ CurAltNum_array[BlkLevel] = (-1); + --BlkLevel; + zzmatch(98); + + ((Junction *)((Junction *)zzaRet.left)->p1)->blockid = CurBlockID; + ((Junction *)((Junction *)zzaRet.left)->p1)->tokrefs = toksrefd; + ((Junction *)((Junction *)zzaRet.left)->p1)->rulerefs = rulesrefd; + zzCONSUME; + + if ( first_on_line ) { /* MR7 */ + CurAltStart = (Junction *) ((Junction *)((Junction *)zzaRet.left)->p1); /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + _retv = (Node *) ((Junction *)zzaRet.left)->p1; + } + else {zzFAIL(1,zzerr52,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + } + else { + if ( (LA(1)==129) ) { + zzmatch(129); + warn("don't you want a ')' with that '*'?"); CannotContinue=TRUE; + zzCONSUME; + + } + else { + if ( (LA(1)==130) ) { + zzmatch(130); + warn("don't you want a ')' with that '+'?"); CannotContinue=TRUE; + zzCONSUME; + + } + else { + if ( (LA(1)==105) ) { + zzmatch(105); + warn("'>' can only appear after a nonterminal"); CannotContinue=TRUE; + zzCONSUME; + + } + else { + if ( (LA(1)==PassAction) ) { + zzmatch(PassAction); + warn("[...] out of context 'rule > [...]'"); + CannotContinue=TRUE; + zzCONSUME; + + } + else {zzFAIL(1,zzerr53,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + } + } + } + } + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd9, 0x1); + return _retv; + } +} + +void +#ifdef __USE_PROTOS +default_exception_handler(void) +#else +default_exception_handler() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + DefaultExGroup = exception_group(); + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd9, 0x2); + } +} + +ExceptionGroup * +#ifdef __USE_PROTOS +exception_group(void) +#else +exception_group() +#endif +{ + ExceptionGroup * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(ExceptionGroup * )) + zzMake0; + { + ExceptionHandler *h; LabelEntry *label=NULL; /* MR6 */ + FoundException = 1; FoundExceptionGroup = 1; + zzmatch(133); + _retv = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup)); + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + char *p; + if ( (LA(1)==PassAction) ) { + zzmatch(PassAction); + + p = LATEXT(1)+1; + p[strlen(p)-1] = '\0'; /* kill trailing space */ + label = (LabelEntry *) hash_get(Elabel, LATEXT(1)+1); + if ( label==NULL ) + { + err(eMsg1("unknown label in exception handler: '%s'", LATEXT(1)+1)); + } + zzCONSUME; + + } + else { + if ( (setwd9[LA(1)]&0x4) ) { + } + else {zzFAIL(1,zzerr54,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==135) ) { + h = exception_handler(); + + list_add(&(_retv->handlers), (void *)h); + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==134) ) { + zzmatch(134); zzCONSUME; + zzmatch(106); zzCONSUME; + zzmatch(Action); + { + ExceptionHandler *eh = (ExceptionHandler *) + calloc(1, sizeof(ExceptionHandler)); + char *a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(eh!=NULL, "exception: cannot allocate handler"); + require(a!=NULL, "exception: cannot allocate action"); + strcpy(a, LATEXT(1)); + eh->action = a; + eh->signalname = (char *) calloc(strlen("default")+1, sizeof(char)); + require(eh->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy(eh->signalname, "default"); + list_add(&(_retv->handlers), (void *)eh); + } + zzCONSUME; + + } + else { + if ( (setwd9[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr55,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + + if ( label!=NULL ) { + /* Record ex group in sym tab for this label */ + if ( label->ex_group!=NULL ) { + err(eMsg1("duplicate exception handler for label '%s'",label->str)); + } else { + label->ex_group = _retv; + /* Label the exception group itself */ + _retv->label = label->str; + /* Make the labelled element pt to the exception also */ + /* MR6 */ if (label->elem == NULL) { + /* MR6 */ err(eMsg1("reference in exception handler to undefined label '%s'",label->str)); + /* MR6 */ } else { + switch ( label->elem->ntype ) { + case nRuleRef : + { + RuleRefNode *r = (RuleRefNode *)label->elem; + r->ex_group = _retv; + break; + } + case nToken : + { + TokNode *t = (TokNode *)label->elem; + t->ex_group = _retv; + break; + } + } /* end switch */ + /* MR6 */ }; /* end test on label->elem */ + } /* end test on label->ex_group */ + + } /* end test on exception label */ + +/* MR7 */ + /* MR7 */ if (BlkLevel == 1 && label == NULL) { + /* MR7 */ _retv->forRule=1; + /* MR7 */ } else if (label == NULL) { + /* MR7 */ _retv->altID = makeAltID(CurBlockID_array[BlkLevel], CurAltNum_array[BlkLevel]); + /* MR7 */ egAdd(_retv); + /* MR7 */ } else { + /* MR7 */ _retv->labelEntry=label; + /* MR7 */ }; + /* MR7 */ + /* MR7 */ /* You may want to remove this exc from the rule list */ + /* MR7 */ /* and handle at the labeled element site. */ + /* MR7 */ + /* MR7 */ if (label != NULL) { + /* MR7 */ _retv = NULL; + /* MR7 */ }; + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd9, 0x10); + return _retv; + } +} + +ExceptionHandler * +#ifdef __USE_PROTOS +exception_handler(void) +#else +exception_handler() +#endif +{ + ExceptionHandler * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(ExceptionHandler * )) + zzMake0; + { + ; + zzmatch(135); + + _retv = (ExceptionHandler *)calloc(1, sizeof(ExceptionHandler)); + require(_retv!=NULL, "exception: cannot allocate handler"); + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==NonTerminal) ) { + zzmatch(NonTerminal); + + _retv->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(_retv->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy(_retv->signalname, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + + _retv->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(_retv->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy(_retv->signalname, LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr56,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + zzmatch(106); zzCONSUME; + { + zzBLOCK(zztasp2); + zzMake0; + { + _retv->action = NULL; + if ( (LA(1)==Action) ) { + zzmatch(Action); + + _retv->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(_retv->action!=NULL, "exception: cannot allocate action"); + strcpy(_retv->action, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd9[LA(1)]&0x20) ) { + } + else {zzFAIL(1,zzerr57,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd9, 0x40); + return _retv; + } +} + +void +#ifdef __USE_PROTOS +enum_file(char * fname) +#else +enum_file(fname) + char *fname ; +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + if ( (setwd9[LA(1)]&0x80) ) { + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==143) ) { + zzmatch(143); zzCONSUME; + zzmatch(ID); zzCONSUME; + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==149) ) { + zzmatch(149); zzCONSUME; + zzmatch(ID); zzCONSUME; + } + else { + if ( (setwd10[LA(1)]&0x1) ) { + } + else {zzFAIL(1,zzerr58,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + } + else { + if ( (setwd10[LA(1)]&0x2) ) { + } + else {zzFAIL(1,zzerr59,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==151) ) { + { + zzBLOCK(zztasp3); + int zzcnt=1; + zzMake0; + { + do { + enum_def( fname ); + zzLOOP(zztasp3); + } while ( (LA(1)==151) ); + zzEXIT(zztasp3); + } + } + } + else { + if ( (LA(1)==149) ) { + defines( fname ); + } + else {zzFAIL(1,zzerr60,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + } + else { + if ( (LA(1)==Eof) ) { + } + else {zzFAIL(1,zzerr61,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd10, 0x4); + } +} + +void +#ifdef __USE_PROTOS +defines(char * fname) +#else +defines(fname) + char *fname ; +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + int v; int maxt=(-1); char *t; + { + zzBLOCK(zztasp2); + int zzcnt=1; + zzMake0; + { + do { + zzmatch(149); zzCONSUME; + zzmatch(ID); + t = mystrdup(LATEXT(1)); + zzCONSUME; + + zzmatch(INT); + + v = atoi(LATEXT(1)); + /* fprintf(stderr, "#token %s=%d\n", t, v);*/ + + /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ + /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ + /* MR2 Don't let #tokdefs be confused by */ + /* MR2 DLGminToken and DLGmaxToken */ + + if ( ! isDLGmaxToken(t)) { /* MR2 */ + TokenNum = v; + if ( v>maxt ) maxt=v; + if ( Tnum( t ) == 0 ) { + addForcedTname( t, v ); + } else { + warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline); + }; +}; + zzCONSUME; + + zzLOOP(zztasp2); + } while ( (LA(1)==149) ); + zzEXIT(zztasp2); + } + } + TokenNum = maxt + 1; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd10, 0x8); + } +} + +void +#ifdef __USE_PROTOS +enum_def(char * fname) +#else +enum_def(fname) + char *fname ; +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + int v= 0; int maxt=(-1); char *t; + zzmatch(151); zzCONSUME; + zzmatch(ID); zzCONSUME; + zzmatch(152); zzCONSUME; + zzmatch(ID); + t = mystrdup(LATEXT(1)); + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==153) ) { + zzmatch(153); zzCONSUME; + zzmatch(INT); + v=atoi(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd10[LA(1)]&0x10) ) { + v++; + } + else {zzFAIL(1,zzerr62,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + + /* fprintf(stderr, "#token %s=%d\n", t, v);*/ + TokenNum = v; + if ( v>maxt ) maxt=v; /* MR3 */ + if ( Tnum( t ) == 0 ) addForcedTname( t, v ); + else { + warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline); + } + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==154) ) { + zzmatch(154); zzCONSUME; + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==ID)&&(isDLGmaxToken(LATEXT(1))) ) { + if (!(isDLGmaxToken(LATEXT(1))) ) {zzfailed_pred(" isDLGmaxToken(LATEXT(1))",0 /* report */, { 0; /* no user action */ } );} + zzmatch(ID); zzCONSUME; + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==153) ) { + zzmatch(153); zzCONSUME; + zzmatch(INT); zzCONSUME; + } + else { + if ( (setwd10[LA(1)]&0x20) ) { + } + else {zzFAIL(1,zzerr63,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + } + else { + if ( (LA(1)==ID) ) { + zzmatch(ID); + t = mystrdup(LATEXT(1)); + zzCONSUME; + + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==153) ) { + zzmatch(153); zzCONSUME; + zzmatch(INT); + v=atoi(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd10[LA(1)]&0x40) ) { + v++; + } + else {zzFAIL(1,zzerr64,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + + /* fprintf(stderr, "#token %s=%d\n", t, v);*/ + TokenNum = v; + if ( v>maxt ) maxt=v; /* MR3 */ + if ( Tnum( t ) == 0 ) addForcedTname( t, v ); + else { + warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline); + } + } + else { + if ( (setwd10[LA(1)]&0x80) ) { + } + else {zzFAIL(1,zzerr65,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzmatch(155); zzCONSUME; + zzmatch(156); + TokenNum = maxt + 1; + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd11, 0x1); + } +} + + +/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ +/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ +/* MR2 Don't let #tokdefs be confused by */ +/* MR2 DLGminToken and DLGmaxToken */ + +/* semantic check on DLGminToken and DLGmaxmaxToken in #tokdefs */ + +#ifdef __USE_PROTOS +static int isDLGmaxToken(char *Token) +#else +static int isDLGmaxToken(Token) +char * Token; +#endif +{ +static char checkStr1[] = "DLGmaxToken"; +static char checkStr2[] = "DLGminToken"; + + if (strcmp(Token, checkStr1) == 0) +return 1; +else if (strcmp(Token, checkStr2) == 0) +return 1; +else +return 0; +} + +/* semantics of #token */ +static void +#ifdef __USE_PROTOS +chkToken(char *t, char *e, char *a, int tnum) +#else +chkToken(t,e,a,tnum) +char *t, *e, *a; +int tnum; +#endif +{ +TermEntry *p; + + /* check to see that they don't try to redefine a token as a token class */ +if ( t!=NULL ) { +p = (TermEntry *) hash_get(Tname, t); +if ( p!=NULL && p->classname ) { + err(eMsg1("redefinition of #tokclass '%s' to #token not allowed; ignored",t)); + if ( a!=NULL ) free((char *)a); + return; +} +} + + if ( t==NULL && e==NULL ) { /* none found */ +err("#token requires at least token name or rexpr"); +} +else if ( t!=NULL && e!=NULL ) { /* both found */ +if ( UserDefdTokens ) { /* if #tokdefs, must not define new */ + p = (TermEntry *) hash_get(Tname, t); + if ( p == NULL) { + err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t)); + return; + }; +} +Tklink(t, e); +if ( a!=NULL ) { + if ( hasAction(e) ) { + err(eMsg1("redefinition of action for %s; ignored",e)); + } + else setHasAction(e, a); +} +} +else if ( t!=NULL ) { /* only one found */ +if ( UserDefdTokens ) { + p = (TermEntry *) hash_get(Tname, t); + if (p == NULL) { + err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t)); + }; + return; +} +if ( Tnum( t ) == 0 ) addTname( t ); +else { + err(eMsg1("redefinition of token %s; ignored",t)); +} +if ( a!=NULL ) { + err(eMsg1("action cannot be attached to a token name (%s); ignored",t)); + free((char *)a); +} +} +else if ( e!=NULL ) { +if ( Tnum( e ) == 0 ) addTexpr( e ); +else { + if ( hasAction(e) ) { + err(eMsg1("redefinition of action for expr %s; ignored",e)); + } + else if ( a==NULL ) { + err(eMsg1("redefinition of expr %s; ignored",e)); + } +} +if ( a!=NULL ) setHasAction(e, a); +} + + /* if a token type number was specified, then add the token ID and 'tnum' +* pair to the ForcedTokens list. (only applies if an id was given) +*/ +if ( t!=NULL && tnum>0 ) +{ +if ( set_el(tnum, reserved_positions) ) +{ + err(eMsgd("a token has already been forced to token number %d; ignored", tnum)); +} +else +{ + list_add(&ForcedTokens, newForcedToken(t,tnum)); + set_orel(tnum, &reserved_positions); +} +} +} + +static int +#ifdef __USE_PROTOS +match_token(char *s, char **nxt) +#else +match_token(s,nxt) +char *s; +char **nxt; +#endif +{ + if ( !(*s>='A' && *s<='Z') ) return 0; + s++; + while ( (*s>='a' && *s<='z') || + (*s>='A' && *s<='Z') || + (*s>='0' && *s<='9') || + *s=='_' ) + { + s++; + } + if ( *s!=' ' && *s!='}' ) return 0; + *nxt = s; + return 1; +} + +static int +#ifdef __USE_PROTOS +match_rexpr(char *s, char **nxt) +#else +match_rexpr(s,nxt) +char *s; +char **nxt; +#endif +{ + if ( *s!='"' ) return 0; + s++; + while ( *s!='"' ) + { + if ( *s=='\n' || *s=='\r' ) /* MR13 */ + warn("eoln found in regular expression"); + if ( *s=='\\' ) s++; + s++; + } + *nxt = s+1; + return 1; +} + +/* +* Walk a string "{ A .. Z }" where A..Z is a space separated list +* of token references (either labels or reg exprs). Return a +* string "inlineX_set" for some unique integer X. Basically, +* we pretend as if we had seen "#tokclass inlineX { A .. Z }" +* on the input stream outside of an action. +*/ +char * +#ifdef __USE_PROTOS +inline_set(char *s) +#else +inline_set(s) +char *s; +#endif +{ + char *nxt; + fprintf(stderr, "found consumeUntil( {...} )\n"); + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + if ( *s!='{' ) + { + err("malformed consumeUntil( {...} ); missing '{'"); + return "bad_set"; + } + s++; + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + while ( *s!='}' ) + { + if ( match_token(s,&nxt) ) fprintf(stderr, "found token %s\n", s); + else if ( match_rexpr(s,&nxt) ) fprintf(stderr, "found rexpr %s\n", s); + else { + err("invalid element in consumeUntil( {...} )"); + return "bad_set"; + } + s = nxt; + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + } + return "inlineX_set"; +} + +/* ANTLR-specific syntax error message generator +* (define USER_ZZSYN when compiling so don't get 2 definitions) +*/ +void +#ifdef __USE_PROTOS +zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, +int k, char *bad_text) +#else +zzsyn(text, tok, egroup, eset, etok, k, bad_text) +char *text, *egroup, *bad_text; +int tok; +int etok; +int k; +SetWordType *eset; +#endif +{ +fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline); +fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text); +if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} +if ( k==1 ) fprintf(stderr, " missing"); +else +{ +fprintf(stderr, "; \"%s\" not", bad_text); +if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); +} +if ( zzset_deg(eset)>0 ) zzedecode(eset); +else fprintf(stderr, " %s", zztokens[etok]); +if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup); +fprintf(stderr, "\n"); +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/antlr.g b/Tools/Source/TianoTools/Pccts/antlr/antlr.g new file mode 100644 index 0000000000..e6eda6010c --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/antlr.g @@ -0,0 +1,2586 @@ +/* + * antlr.g -- PCCTS Version 1.xx ANTLR + * + * Parse an antlr input grammar and build a syntax-diagram. + * + * Written in itself (needs at least 1.06 to work) + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-1995 + */ + +/* MR1 */ +/* MR1 10-Apr-97 MR1 Replace #if logic with #include "pcctscfg.h" */ +/* MR1 */ + +#header << + #include "pcctscfg.h" + #include "set.h" + #include + #include "syn.h" + #include "hash.h" + #include "generic.h" + #define zzcr_attr(attr,tok,t) + >> + +<< + +/* MR20 G. Hobbelt For Borland C++ 4.x & 5.x compiling with ALL warnings enabled */ +#if defined(__TURBOC__) +#pragma warn -aus /* unused assignment of 'xxx' */ +#endif + + +#ifdef __USE_PROTOS +static void chkToken(char *, char *, char *, int); +#else +static void chkToken(); +#endif + +#ifdef __USE_PROTOS +static int isDLGmaxToken(char *Token); /* MR3 */ +#else +static int isDLGmaxToken(); /* MR3 */ +#endif + +static int class_nest_level = 0; + +/* MR20 G. Hobbelt extern definitions moved to antlr.h */ + +>> + +#lexaction << +/* maintained, but not used for now */ +set AST_nodes_refd_in_actions = set_init; +int inAlt = 0; +set attribsRefdFromAction = set_init; /* MR20 */ +int UsedOldStyleAttrib = 0; +int UsedNewStyleLabel = 0; +#ifdef __USE_PROTOS +char *inline_set(char *); +#else +char *inline_set(); +#endif + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ + +int tokenActionActive=0; /* MR1 */ + +>> + +#lexclass STRINGS +#token QuotedTerm "\"" << zzmode(START); >> +#token "\n|\r|\r\n" << + zzline++; + warn("eoln found in string"); + zzskip(); + >> +#token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >> +#token "\\~[]" << zzmore(); >> +#token "~[\n\r\"\\]+" << zzmore(); >> + +#lexclass ACTION_STRINGS +#token "\"" << zzmode(ACTIONS); zzmore(); >> +#token "\n|\r|\r\n" << + zzline++; + warn("eoln found in string (in user action)"); + zzskip(); + >> +#token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >> +#token "\\~[]" << zzmore(); >> +#token "~[\n\r\"\\]+" << zzmore(); >> + +#lexclass ACTION_CHARS +#token "'" << zzmode(ACTIONS); zzmore(); >> +#token "\n|\r|\r\n" << + zzline++; + warn("eoln found in char literal (in user action)"); + zzskip(); + >> +#token "\\~[]" << zzmore(); >> +#token "~[\n\r'\\]+" << zzmore(); >> + +#lexclass ACTION_COMMENTS +#token "\*/" << zzmode(ACTIONS); zzmore(); >> +#token "\*" << zzmore(); >> +#token "\n|\r|\r\n" << zzline++; zzmore(); DAWDLE; >> +#token "~[\n\r\*]+" << zzmore(); >> + +#lexclass TOK_DEF_COMMENTS +#token "\*/" << zzmode(PARSE_ENUM_FILE); + zzmore(); >> +#token "\*" << zzmore(); >> +#token "\n|\r|\r\n" << zzline++; zzmore(); DAWDLE; >> +#token "~[\n\r\*]+" << zzmore(); >> + +#lexclass TOK_DEF_CPP_COMMENTS +#token "\n|\r|\r\n" << zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; >> +#token "~[\n\r]+" << zzskip(); >> + +#lexclass ACTION_CPP_COMMENTS +#token "\n|\r|\r\n" << zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; >> +#token "~[\n\r]+" << zzmore(); >> + +#lexclass CPP_COMMENTS +#token "\n|\r|\r\n" << zzline++; zzmode(START); zzskip(); DAWDLE; >> +#token "~[\n\r]+" << zzskip(); >> + +#lexclass COMMENTS +#token "\*/" << zzmode(START); zzskip(); >> +#token "\*" << zzskip(); >> +#token "\n|\r|\r\n" << zzline++; zzskip(); DAWDLE; >> +#token "~[\n\r\*]+" << zzskip(); >> + +/* + * This lexical class accepts actions of type [..] and <<..>> + * + * It translates the following special items for C: + * + * $j --> "zzaArg(current zztasp, j)" + * $i.j --> "zzaArg(zztaspi, j)" + * $i.nondigit> "zzaArg(current zztasp, i).nondigit" + * $$ --> "zzaRet" + * $alnum --> "alnum" (used to ref parameters) + * $rule --> "zzaRet" + * $retval --> "_retv.retval" if > 1 return values else "_retv" + * $[token, text] --> "zzconstr_attr(token, text)" + * $[] --> "zzempty_attr()" + * + * It translates the following special items for C++: + * (attributes are now stored with 'Token' and $i's are only + * pointers to the Tokens. Rules don't have attributes now.) + * + * $j --> "_tbj" where b is the block level + * $i.j --> "_tij" + * $j->nondigit> "_tbj->nondigit" + * $$ --> "$$" + * $alnum --> "alnum" (used to ref parameters) + * $rule --> "$rule" + * $retval --> "_retv.retval" if > 1 return values else "_retv" + * $[token, text] --> invalid + * $[] --> invalid + * + * And, for trees: + * + * #0 --> "(*_root)" + * #i --> "zzastArg(i)" + * #[args] --> "zzmk_ast(zzastnew(), args)" + * #[] --> "zzastnew()" + * #( root, child1, ..., childn ) + * --> "zztmake(root, child1, ...., childn, NULL)" + * #() --> "NULL" + * + * For C++, ... + * + * #0 --> "(*_root)" + * #i --> "_astbi" where b is the block level + * #alnum --> "alnum_ast" (used to ref #label) + * #[args] --> "new AST(args)" + * #[] --> "new AST" + * #( root, child1, ..., childn ) + * --> "AST::tmake(root, child1, ...., childn, NULL)" + * #() --> "NULL" + * + * To escape, + * + * \] --> ] + * \) --> ) + * \$ --> $ + * \# --> # + * + * A stack is used to nest action terminators because they can be nested + * like crazy: << #[$[..],..] >> + */ +#lexclass ACTIONS +#token Action "\>\>" << /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = ' '; + zzbegexpr[1] = ' '; + if ( zzbufovf ) { + err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE)); + } + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ +/* MR1 Doesn't matter what kind of action it is - reset*/ + + tokenActionActive=0; /* MR1 */ + >> +#token Pred "\>\>?" << /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = '\0'; + if ( zzbufovf ) { + err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE)); + }; +#ifdef __cplusplus__ +/* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __STDC__ +/* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __USE_PROTOS +/* MRxx */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +/* MR10 */ list_apply(CurActionLabels,mark_label_used_in_sem_pred); +#endif +#endif +#endif + >> +#token PassAction "\]" << if ( topint() == ']' ) { + popint(); + if ( istackempty() ) /* terminate action */ + { + zzmode(START); + NLATEXT[0] = ' '; + zzbegexpr[0] = ' '; + if ( zzbufovf ) { + err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE)); + } + } + else { + /* terminate $[..] and #[..] */ + if ( GenCC ) zzreplstr("))"); + else zzreplstr(")"); + zzmore(); + } + } + else if ( topint() == '|' ) { /* end of simple [...] */ + popint(); + zzmore(); + } + else zzmore(); + >> +#token "consumeUntil\( [\ \t]* \{~[\}]+\} [\ \t]* \)" + << + zzmore(); + zzreplstr(inline_set(zzbegexpr+ + strlen("consumeUntil("))); + >> +#token "consumeUntil\( ~[\)]+ \)" + << zzmore(); >> +#token "\n|\r|\r\n" << zzline++; zzmore(); DAWDLE; >> +#token "\>" << zzmore(); >> +#token "$" << zzmore(); >> +#token "$$" << if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();} + else err("$$ use invalid in C++ mode"); >> + +#token "$\[\]" << if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();} + else err("$[] use invalid in C++ mode"); >> +#token "$\[" << + pushint(']'); + if ( !GenCC ) zzreplstr("zzconstr_attr("); + else err("$[..] use invalid in C++ mode"); + zzmore(); + >> +#token "$[0-9]+" <<{ + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i attrib ref too big"); + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> +#token "$[0-9]+." <<{ + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i.field attrib ref too big"); + zzbegexpr[strlen(zzbegexpr)-1] = ' '; + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s.", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> +#token "$[0-9]+.[0-9]+" <<{ + static char buf[100]; + static char i[20], j[20]; + char *p,*q; + numericActionLabel=1; /* MR10 */ + if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big"); + for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) { + if ( q == &i[20] ) + fatalFL("i of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + for (p++, q= &j[0]; *p!='\0'; p++) { + if ( q == &j[20] ) + fatalFL("j of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j); + else sprintf(buf,"_t%s%s",i,j); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> +#token "$[_a-zA-Z][_a-zA-Z0-9]*" + <<{ static char buf[300]; LabelEntry *el; + zzbegexpr[0] = ' '; + if ( CurRule != NULL && + strcmp(CurRule, &zzbegexpr[1])==0 ) { + if ( !GenCC ) zzreplstr("zzaRet"); + } + else if ( CurRetDef != NULL && + strmember(CurRetDef, &zzbegexpr[1])) { + if ( hasMultipleOperands( CurRetDef ) ) { + require (strlen(zzbegexpr)<=(size_t)285, + "$retval attrib ref too big"); + sprintf(buf,"_retv.%s",&zzbegexpr[1]); + zzreplstr(buf); + } + else zzreplstr("_retv"); + } + else if ( CurParmDef != NULL && + strmember(CurParmDef, &zzbegexpr[1])) { + ; + } + else if ( Elabel==NULL ) { + { err("$-variables in actions outside of rules are not allowed"); } + } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) { +/* MR10 */ +/* MR10 */ /* element labels might exist without an elem when */ +/* MR10 */ /* it is a forward reference (to a rule) */ +/* MR10 */ +/* MR10 */ if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) ) +/* MR10 */ { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); } +/* MR10 */ +/* MR10 */ if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) { +/* MR10 */ err("You can no longer use attributes returned by rules when also using ASTs"); +/* MR10 */ err(" Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...\>\>\")"); +/* MR10 */ }; +/* MR10 */ +/* MR10 */ /* keep track of <<... $label ...>> for semantic predicates in guess mode */ +/* MR10 */ /* element labels contain pointer to the owners node */ +/* MR10 */ +/* MR10 */ if (el->elem != NULL && el->elem->ntype == nToken) { +/* MR10 */ list_add(&CurActionLabels,el); +/* MR10 */ }; + } + else + warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1])); + } + zzmore(); + >> +#token "#0" << zzreplstr("(*_root)"); zzmore(); chkGTFlag(); >> +#token "#\[\]" << if ( GenCC ) { + if (NewAST) zzreplstr("(newAST)"); + else zzreplstr("(new AST)");} + else {zzreplstr("zzastnew()");} zzmore(); + chkGTFlag(); + >> +#token "#\(\)" << zzreplstr("NULL"); zzmore(); chkGTFlag(); >> +#token "#[0-9]+" <<{ + static char buf[100]; + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("#i AST ref too big"); + if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"zzastArg(%s)",zzbegexpr+1); + zzreplstr(buf); + zzmore(); + set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions); + chkGTFlag(); + } + >> + +/* MR14 Arpad Beszedes 26-May-98 + Add support for #line directives when antlr source is pre-processed + #lexclass ACTIONS +*/ + +#token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)" + << + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + >> + +#token "#line ~[\n\r]* (\n|\r|\r\n)" + << + zzline++; zzmore(); + >> + +/* MR14 end of a block to support #line in antlr source code */ + +#token "#[_a-zA-Z][_a-zA-Z0-9]*" + << + if ( !(strcmp(zzbegexpr, "#ifdef")==0 || + strcmp(zzbegexpr, "#if")==0 || + strcmp(zzbegexpr, "#else")==0 || + strcmp(zzbegexpr, "#endif")==0 || + strcmp(zzbegexpr, "#ifndef")==0 || + strcmp(zzbegexpr, "#define")==0 || + strcmp(zzbegexpr, "#pragma")==0 || + strcmp(zzbegexpr, "#undef")==0 || + strcmp(zzbegexpr, "#import")==0 || + strcmp(zzbegexpr, "#line")==0 || + strcmp(zzbegexpr, "#include")==0 || + strcmp(zzbegexpr, "#error")==0) ) + { + static char buf[100]; + sprintf(buf, "%s_ast", zzbegexpr+1); +/* MR27 */ list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1)); + zzreplstr(buf); + chkGTFlag(); + } + zzmore(); + >> +#token "#\[" << + pushint(']'); + if ( GenCC ) { + if (NewAST) zzreplstr("(newAST("); + else zzreplstr("(new AST("); } + else zzreplstr("zzmk_ast(zzastnew(),"); + zzmore(); + chkGTFlag(); + >> +#token "#\(" << + pushint('}'); + if ( GenCC ) { + if (tmakeInParser) { + zzreplstr("tmake("); + } + else { + zzreplstr("ASTBase::tmake("); + } + } + else { + zzreplstr("zztmake("); + } + zzmore(); + chkGTFlag(); + >> +#token "#" << zzmore(); >> +#token "\)" << + if ( istackempty() ) + zzmore(); + else if ( topint()==')' ) { + popint(); + } + else if ( topint()=='}' ) { + popint(); + /* terminate #(..) */ + zzreplstr(", NULL)"); + } + zzmore(); + >> +#token "\[" << + pushint('|'); /* look for '|' to terminate simple [...] */ + zzmore(); + >> +#token "\(" << + pushint(')'); + zzmore(); + >> + +#token "\\\]" << zzreplstr("]"); zzmore(); >> +#token "\\\)" << zzreplstr(")"); zzmore(); >> + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ + +#token "\\>" << if (! tokenActionActive) zzreplstr(">"); /* MR1 */ + zzmore(); /* MR1 */ + >> /* MR1 */ + + +#token "'" << zzmode(ACTION_CHARS); zzmore();>> +#token "\"" << zzmode(ACTION_STRINGS); zzmore();>> +#token "\\$" << zzreplstr("$"); zzmore(); >> +#token "\\#" << zzreplstr("#"); zzmore(); >> +#token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >> +#token "\\~[\]\)>$#]" << zzmore(); >> /* escaped char, always ignore */ +#token "/" << zzmore(); >> +#token "/\*" << zzmode(ACTION_COMMENTS); zzmore(); >> +#token "\*/" << warn("Missing /*; found dangling */ in action"); zzmore(); >> +#token "//" << zzmode(ACTION_CPP_COMMENTS); zzmore(); >> +#token "~[\n\r\)\(\\$#\>\]\[\"'/]+" << zzmore(); >> + +#lexclass START +#token "[\t\ ]+" << zzskip(); >> /* Ignore White */ +#token "\n|\r|\r\n" << zzline++; zzskip(); >> /* Track Line # */ +#token "\[" << zzmode(ACTIONS); zzmore(); + istackreset(); + pushint(']'); >> +#token "\<\<" << action_file=CurFile; action_line=zzline; + zzmode(ACTIONS); zzmore(); + list_free(&CurActionLabels,0); /* MR10 */ + numericActionLabel=0; /* MR10 */ + istackreset(); + pushint('>'); >> +#token "\"" << zzmode(STRINGS); zzmore(); >> +#token "/\*" << zzmode(COMMENTS); zzskip(); >> +#token "\*/" << warn("Missing /*; found dangling */"); zzskip(); >> +#token "//" << zzmode(CPP_COMMENTS); zzskip(); >> + +/* MR14 Arpad Beszedes 26-May-98 + Add support for #line directives when antlr source is pre-processed + #lexclass START +*/ + +#token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)" + << + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + >> + +#token "#line ~[\n\r]* (\n|\r|\r\n)" + << + zzline++; zzmore(); + >> + +/* MR14 end of a block to support #line in antlr source code */ + +/* */ +/* 8-Apr-97 Regularize escape sequence for ">>" */ +/* appearing in string literals */ +/* */ + +#token "\>\>" << warn("Missing <<; found dangling \>\>"); zzskip(); >> /* MR1 */ +#token WildCard "." +#token "\@" <> /* MR6 */ +#token Eof "@" + << /* L o o k F o r A n o t h e r F i l e */ + { + FILE *new_input; + new_input = NextFile(); + if ( new_input == NULL ) { NLA=Eof; return; } + fclose( input ); + input = new_input; + zzrdstream( input ); + zzskip(); /* Skip the Eof (@) char i.e continue */ + } + >> + +#token LABEL + +#errclass "grammar-element" { element } +#errclass "meta-symbol" { "\}" "!" ";" "\|" "\~" "^" "\)" } + +#token Pragma "{\\}#pragma" /* MR21 */ +#token FirstSetSymbol "{\\}#FirstSetSymbol" /* MR21 */ +/* + * Get a grammar -- Build a list of rules like: + * + * o-->Rule1--o + * | + * o-->Rule2--o + * | + * ... + * | + * o-->RuleN--o + */ + +/* rule grammar */ + +grammar : <> + ( "{\\}#header" Action /* MR13 */ + << + if ( HdrAction==NULL ) { + HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(HdrAction!=NULL, "rule grammar: cannot allocate header action"); + strcpy(HdrAction, LATEXT(1)); + } + else warn("additional #header statement ignored"); + >> + | "{\\}#first" Action + << + if ( FirstAction==NULL ) { + FirstAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(FirstAction!=NULL, "rule grammar: cannot allocate #first action"); + strcpy(FirstAction, LATEXT(1)); + } else { + warn("additional #first statement ignored"); + }; + >> + + | "{\\}#parser" QuotedTerm + << + if ( GenCC ) { + warn("#parser meta-op incompatible with -CC; ignored"); + } + else { + if ( strcmp(ParserName,"zzparser")==0 ) { + ParserName=StripQuotes(mystrdup(LATEXT(1))); + if ( RulePrefix[0]!='\0' ) + { + warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored"); + RulePrefix[0]='\0'; + } + } + else warn("additional #parser statement ignored"); + } + >> + | "{\\}#tokdefs" QuotedTerm + <<{ + char *fname; + zzantlr_state st; FILE *f; struct zzdlg_state dst; + UserTokenDefsFile = mystrdup(LATEXT(1)); + zzsave_antlr_state(&st); + zzsave_dlg_state(&dst); + fname = mystrdup(LATEXT(1)); + f = fopen(StripQuotes(fname), "r"); + if ( f==NULL ) {warn(eMsg1("cannot open token defs file '%s'", fname+1));} + else { + ANTLRm(enum_file(fname+1), f, PARSE_ENUM_FILE); + UserDefdTokens = 1; + } + zzrestore_antlr_state(&st); + zzrestore_dlg_state(&dst); + }>> + )* + ( Action + <<{ + UserAction *ua = newUserAction(LATEXT(1)); + ua->file = action_file; ua->line = action_line; + if ( class_nest_level>0 ) list_add(&class_before_actions, ua); + else list_add(&BeforeActions, ua); + }>> + | laction + | lmember /* MR1 */ + | lprefix /* MR1 */ + | aLexclass + | token + | error + | tclass + | aPred /* MR11 */ + | default_exception_handler + | class_def + | "\}" + << + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + >> + )* + + rule <> + ( rule + + <> + + | aLexclass + | token + | error + | tclass + | aPred /* MR11 */ + | class_def + | "\}" + << + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + >> + )* + ( Action + <<{ + UserAction *ua = newUserAction(LATEXT(1)); + ua->file = action_file; ua->line = action_line; + if ( class_nest_level>0 ) list_add(&class_after_actions, ua); + else list_add(&AfterActions, ua); + }>> + | laction + | lmember /* MR1 */ + | lprefix /* MR1 */ + | error + | tclass + | class_def + | aPred /* MR11 */ + | "\}" + << + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + >> + )* + Eof + ; + <> + +/* rule class_def */ + +class_def + : <> + "class" + ( NonTerminal <> + | TokenTerm <> + ) + << + if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0 + && GenCC ) { + err("only one grammar class allowed in this release"); + go = 0; + } + else strcpy(CurrentClassName, name); + >> + <> + +/* MR10 */ (~ "\{" +/* MR10 */ <> +/* MR10 */ )* + + "\{" + << + no_classes_found = 0; + if ( class_nest_level>=1 ) {warn("cannot have nested classes");} + else class_nest_level++; + >> + ; + <> + +/* + * Build -o-->o-R-o-->o- where -o-R-o- is the block from rule 'block'. + * Construct the RuleBlk front and EndRule node on the end of the + * block. This is used to add FOLLOW pointers to the rule end. Add the + * new rule name to the Rname hash table and sets its rulenum. + * Store the parameter definitions if any are found. + * + * Note that locks are required on the RuleBlk and EndRule nodes to thwart + * infinite recursion. + * + * Return the left graph pointer == NULL to indicate error/dupl rule def. + */ + +/* rule rule */ + +rule : << + + ExceptionGroup *eg; + RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e; + set toksrefd, rulesrefd; + char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL; + CurExGroups = NULL; + CurElementLabels = NULL; + CurAstLabelsInActions = NULL; /* MR27 */ + /* We want a new element label hash table for each rule */ + if ( Elabel!=NULL ) killHashTable(Elabel); + Elabel = newHashTable(); + attribsRefdFromAction = empty; + >> + NonTerminal + <str; + } + CurRuleNode = q; + f = CurFile; l = zzline; + NumRules++; + >> + { "!" <noAST = TRUE;>> } + { <<;>> + {"\<"} + PassAction + << pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(pdecl!=NULL, "rule rule: cannot allocate param decl"); + strcpy(pdecl, LATEXT(1)); + CurParmDef = pdecl; + >> + } + { "\>" + PassAction + << ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(ret!=NULL, "rule rule: cannot allocate ret type"); + strcpy(ret, LATEXT(1)); + CurRetDef = ret; + >> + } + { QuotedTerm <egroup=mystrdup(LATEXT(1));>> } + << + if ( GenEClasseForRules && q!=NULL ) { + e = newECnode; + require(e!=NULL, "cannot allocate error class node"); + if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);} + else a = q->egroup; + if ( Tnum( a ) == 0 ) + { + e->tok = addTname( a ); + list_add(&eclasses, (char *)e); + if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]); + /* refers to itself */ + list_add(&(e->elist), mystrdup(q->str)); + } + else { + warn(eMsg1("default errclass for '%s' would conflict with token/errclass/tokclass",a)); + if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]); + free((char *)e); + } + } + >> + <= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); +/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; +/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + >> + + ":" <> + block[&toksrefd, &rulesrefd] + <blockid = CurBlockID; + CurRuleBlk->jtype = RuleBlk; + if ( q!=NULL ) CurRuleBlk->rname = q->str; + CurRuleBlk->file = f; + CurRuleBlk->line = l; + CurRuleBlk->pdecl = pdecl; + CurRuleBlk->ret = ret; + CurRuleBlk->lock = makelocks(); + CurRuleBlk->pred_lock = makelocks(); + CurRuleBlk->tokrefs = toksrefd; + CurRuleBlk->rulerefs = rulesrefd; + p = newJunction(); /* add EndRule Node */ + ((Junction *)r.right)->p1 = (Node *)p; + r.right = (Node *) p; + p->jtype = EndRule; + p->lock = makelocks(); + p->pred_lock = makelocks(); + CurRuleBlk->end = p; + if ( q!=NULL ) q->rulenum = NumRules; + $7 = r; + >> + << + /* MR23 */ CurBlockID_array[BlkLevel] = (-1); + /* MR23 */ CurAltNum_array[BlkLevel] = (-1); + --BlkLevel; + >> + <> /* MR7 */ + ";" <> + { Action + << a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule rule: cannot allocate error action"); + strcpy(a, LATEXT(1)); + CurRuleBlk->erraction = a; + >> + } + ( exception_group > [eg] + <label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1; + } + >> + )* + <> + <exceptions = CurExGroups;>> + <el_labels = CurElementLabels;>> + <ast_labels_in_actions = CurAstLabelsInActions;>> /* MR27 */ + <> /* MR27 Moved */ + ; + <> + +/* + * pragma : "{\\}#pragma" "dup\-labeled\-tokens" + * <> + * ; + */ + +/* rule laction */ + +laction : <> + + "{\\}#lexaction" + Action + << + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule laction: cannot allocate action"); + strcpy(a, LATEXT(1)); + list_add(&LexActions, a); + >> + ; + <> + +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via #lexmember <<....>> & #lexprefix <<...>> */ +/* MR1 */ + +/* rule lmember */ + +lmember: <> /* MR1 */ + +/* MR1 */ "{\\}#lexmember" +/* MR1 */ Action +/* MR1 */ << +/* MR1 */ if (! GenCC) { +/* MR1 */ err("Use #lexmember only in C++ mode (to insert code in DLG class header"); +/* MR1 */ } else { +/* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); +/* MR1 */ require(a!=NULL, "rule lmember: cannot allocate action"); +/* MR1 */ strcpy(a, LATEXT(1)); +/* MR1 */ list_add(&LexMemberActions, a); +/* MR1 */ }; +/* MR1 */ >> +/* MR1 */ ; +/* MR1 */ <> + +/* rule lprefix */ + +lprefix: <> /* MR1 */ + +/* MR1 */ "{\\}#lexprefix" +/* MR1 */ Action +/* MR1 */ << +/* MR1 */ if (! GenCC) { +/* MR1 */ err("Use #lexprefix only in C++ mode (to insert code in DLG class header"); +/* MR1 */ } else { +/* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); +/* MR1 */ require(a!=NULL, "rule lprefix: cannot allocate action"); +/* MR1 */ strcpy(a, LATEXT(1)); +/* MR1 */ list_add(&LexPrefixActions, a); +/* MR1 */ }; +/* MR1 */ >> +/* MR1 */ ; +/* MR1 */ <> + +/* + * #pred upper <>? predicate literal + * #pred lower <>? predicate literal + * #pred up_or_low upper || lower predicate expression + * concealed interdependence + * #pred up_or_low_2 <>? A || B predicate literal equals predicate expr + * analyze using lower||upper + * generate using isLetter() + */ + +/* rule aPref */ + +aPred: <> + + "{\\}#pred" + + << + MR_usingPredNames=1; /* will need to use -mrhoist version of genPredTree */ + >> + + /* used to allow NonTerminal but it caused problems + when a rule name immediately followed a #pred statement */ + + TokenTerm <> + + << + /* don't free - referenced in predicates */ + + CurPredName=(char *)calloc(1,strlen(name) + 10); + strcat(CurPredName,"#pred "); + strcat(CurPredName,name); + + predEntry=(PredEntry *) hash_get(Pname,name); + if (predEntry != NULL) { + warnFL(eMsg1("#pred %s previously defined - ignored",name), + FileStr[action_file],action_line); + name=NULL; + }; + >> + + ( + + Pred <> + + { + predOrExpr>[predExpr] <> + } + + <file=save_file; + predEntry->line=save_line; + predExpr=MR_predFlatten(predExpr); + predEntry->predLiteral=predLiteral; + if (! predExprPresent || predExpr == NULL) { + predExpr=new_pred(); + predExpr->expr=predLiteral; + predExpr->source=newActionNode(); + predExpr->source->action=predExpr->expr; + predExpr->source->rname=CurPredName; + predExpr->source->line=action_line; + predExpr->source->file=action_file; + predExpr->source->is_predicate=1; + predExpr->k=predicateLookaheadDepth(predExpr->source); + }; + predEntry->pred=predExpr; + hash_add(Pname,name,(Entry *)predEntry); + predExpr=NULL; + }; + predicate_free(predExpr); + >> + + | + <> + + predOrExpr>[predExpr] + + <file=CurFile; + predEntry->line=zzline; + predExpr=MR_predFlatten(predExpr); + predEntry->pred=predExpr; + hash_add(Pname,name,(Entry *)predEntry); + predExpr=NULL; + }; + predicate_free(predExpr); + >> + ) + {";"} +; + +/* fail */ + +<> + +/* rule predOrExpr */ + +predOrExpr>[Predicate *result] : + <> + predAndExpr>[predExpr] + << + ORnode=new_pred(); + ORnode->expr=PRED_OR_LIST; + if (predExpr != NULL) { + ORnode->down=predExpr; + tail=&predExpr->right; + }; + >> + ( "\|\|" predAndExpr>[predExpr] + << + if (predExpr != NULL) { + *tail=predExpr; + tail=&predExpr->right; + }; + >> + )* + << + $result=ORnode; + ORnode=NULL; + >> +; + +/* fail */ + +<> + +/* rule predAndExpr */ + +predAndExpr>[Predicate *result] : + <> + predPrimary>[predExpr] + << + ANDnode=new_pred(); + ANDnode->expr=PRED_AND_LIST; + if (predExpr != NULL) { + ANDnode->down=predExpr; + tail=&predExpr->right; + }; + >> + ( "&&" predPrimary>[predExpr] + << + if (predExpr != NULL) { + *tail=predExpr; + tail=&predExpr->right; + }; + >> + )* + << + $result=ANDnode; + ANDnode=NULL; + >> +; + +/* fail */ + +<> + + +/* rule predPrimary */ + +predPrimary>[Predicate *result] : + << + char *name=NULL; + PredEntry *predEntry=NULL; + Predicate *predExpr=NULL; + >> + + TokenTerm <> + + << + predEntry=(PredEntry *) hash_get(Pname,name); + if (predEntry == NULL) { + warnFL(eMsg1("no previously defined #pred with name \"%s\"",name), + FileStr[CurFile],zzline); + name=NULL; + $result=NULL; + } else { + predExpr=predicate_dup(predEntry->pred); + predExpr->predEntry=predEntry; + $result=predExpr; + }; + >> + + | "\(" predOrExpr>[predExpr] "\)" + << + $result=predExpr; + >> + + | "!" predPrimary>[predExpr] + << + predExpr->inverted=!predExpr->inverted; + $result=predExpr; + >> +; + +/* fail */ << + predicate_free(predExpr); + >> + +/* rule aLexclass */ + +aLexclass: "{\\}#lexclass" TokenTerm <> + ; + <> + +/* rule error */ + +error : <> + "{\\}#errclass" + (<<;>> TokenTerm <> + | QuotedTerm <> + ) + <lexclass = CurrentLexClass; + if ( Tnum( (t=StripQuotes(t)) ) == 0 ) + { + if ( hash_get(Texpr, t) != NULL ) + warn(eMsg1("errclass name conflicts with regular expression '%s'",t)); + e->tok = addTname( t ); + set_orel(e->tok, &imag_tokens); + require((p=(TermEntry *)hash_get(Tname, t)) != NULL, + "hash table mechanism is broken"); + p->classname = 1; /* entry is errclass name, not token */ + list_add(&eclasses, (char *)e); + } + else + { + warn(eMsg1("redefinition of errclass or conflict w/token or tokclass '%s'; ignored",t)); + free( (char *)e ); + go=0; + } + >> + "\{" + ( NonTerminal <> + | TokenTerm <> + | QuotedTerm <> + ) + <elist), t);>> + ( + ( NonTerminal <> + | TokenTerm <> + | QuotedTerm <> + ) + <elist), t);>> + )* + "\}" + ; + <> + +/* rule tclass */ + +tclass : <> + <> + <> + "{\\}#tokclass" TokenTerm <> + <lexclass = CurrentLexClass; + if ( Tnum( t ) == 0 ) + { + e->tok = addTname( t ); + set_orel(e->tok, &imag_tokens); + set_orel(e->tok, &tokclasses); + require((p=(TermEntry *)hash_get(Tname, t)) != NULL, + "hash table mechanism is broken"); + p->classname = 1; /* entry is class name, not token */ + p->tclass = e; /* save ptr to this tclass def */ + list_add(&tclasses, (char *)e); + } + else + { + warn(eMsg1("redefinition of tokclass or conflict w/token '%s'; ignored",t)); + free( (char *)e ); + go=0; + } + >> +/* MR23 */ { +/* MR23 */ "\(" +/* MR23 */ QuotedTerm +/* MR23 */ <> +/* MR23 */ "\)" +/* MR23 */ } +/* MR23 */ +/* MR23 */ +/* MR23 */ << +/* MR23 */ if (p!= NULL && akaString != NULL) { +/* MR23 */ if (p->akaString != NULL) { +/* MR23 */ if (strcmp(p->akaString,akaString) != 0) { +/* MR23 */ warnFL(eMsg2("this #tokclass statment conflicts with a previous #tokclass %s(\"%s\") statement", +/* MR23 */ t,p->akaString), +/* MR23 */ FileStr[save_file],save_line); +/* MR23 */ }; +/* MR23 */ } else { +/* MR23 */ p->akaString=akaString; +/* MR23 */ }; +/* MR23 */ }; +/* MR23 */ >> + + "\{" + ( + ( TokenTerm + <> + + { + ".." + TokenTerm + + <> + } + + | QuotedTerm + <> + ) + <tlist), t); + } else { + list_add(&(e->tlist),".."); + list_add(&(e->tlist),t); + list_add(&(e->tlist),totext); + } + totext=NULL; + } + >> + )+ // MR15 Manfred Kogler - forbid empty #tokclass sets (was "+") + "\}" + ; + <> + +/* rule token */ + +token : <> + <> /* MR11 */ + "{\\}#token" + +/* MR1 10-Apr-97 MR1 Allow shift right operator in DLG actions */ +/* MR1 Danger when parser feedback to lexer */ +/* MR1 */ + + <> /* MR1 */ + { TokenTerm <> + +/* MR11 */ { +/* MR11 */ "\(" +/* MR11 */ QuotedTerm +/* MR11 */ <> +/* MR11 */ "\)" +/* MR11 */ } + + { "=" "[0-9]+" /* define the token type number */ + <> + } + } + { QuotedTerm <> } + { Action + << + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule token: cannot allocate action"); + strcpy(a, LATEXT(1)); + >> + } + + { ";" } /* MR11 */ + + <> + + <akaString != NULL) { + if (strcmp(te->akaString,akaString) != 0) { + warnFL(eMsg2("this #token statment conflicts with a previous #token %s(\"%s\") statement", + t,te->akaString), + FileStr[save_file],save_line); + }; + } else { + te->akaString=akaString; + }; + }; + }; + >> + ; + <> + +/* rule block */ + +block[set *toksrefd, set *rulesrefd] + : << + Graph g, b; + set saveblah; + int saveinalt = inAlt; + ExceptionGroup *eg; + *$toksrefd = empty; + *$rulesrefd = empty; + set_clr(AST_nodes_refd_in_actions); + CurBlockID++; +/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; + CurAltNum = 1; +/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + saveblah = attribsRefdFromAction; + attribsRefdFromAction = empty; + >> + + alt[toksrefd,rulesrefd] <> + + << + if ( ((Junction *)g.left)->p1->ntype == nAction ) + { + ActionNode *actionNode=(ActionNode *) + ( ( (Junction *)g.left) ->p1); + if (!actionNode->is_predicate ) + { + actionNode->init_action = TRUE; +/* MR12c */ if (actionNode->noHoist) { +/* MR12c */ errFL("<> appears as init-action - use <<>> <>", +/* MR12c */ FileStr[actionNode->file],actionNode->line); +/* MR12c */ }; + } + } + ((Junction *)g.left)->blockid = CurBlockID; + >> + + ( exception_group > [eg] + << + if ( eg!=NULL ) { +/* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/ +/* MR7 ***** CurAltStart->exception_label = eg->altID; *****/ + list_add(&CurExGroups, (void *)eg); + } + >> + )* + <> + + ( "\|" <> + alt[toksrefd,rulesrefd] <> + << + ((Junction *)g.left)->blockid = CurBlockID; + >> + + ( exception_group > [eg] + << + if ( eg!=NULL ) { +/* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/ +/* MR7 ***** CurAltStart->exception_label = eg->altID; *****/ + list_add(&CurExGroups, (void *)eg); + } + >> + )* + + <> + + )* + <<$0 = b;>> + <> + ; + <> + +/* rule alt */ + +alt[set *toksrefd, set *rulesrefd] + : <> + { "\@" /* handle MismatchedToken signals with default handler */ + <> + } + + ( <<;>> /* MR9 Removed unreferenced variable "tok" */ + { <> "\~" <> } + element[old_not, first_on_line, use_def_MT_handler] > [node] + <ntype!=nAction ) first_on_line = 0;>> + << + if ( $2.left!=NULL ) { + g = Cat(g, $2); + n++; + if ( node!=NULL ) { + if ( node->ntype!=nAction ) e_num++; + /* record record number of all rule and token refs */ + if ( node->ntype==nToken ) { + TokNode *tk = (TokNode *)((Junction *)$2.left)->p1; + tk->elnum = e_num; + set_orel(e_num, &elems); + } + else if ( node->ntype==nRuleRef ) { + RuleRefNode *rn = (RuleRefNode *)((Junction *)$2.left)->p1; + rn->elnum = e_num; + set_orel(e_num, $rulesrefd); + } + } + } + >> + )* + <0 ) + err("one or more $i in action(s) refer to non-token elements"); + set_free(dif); + } + set_free(elems); + set_free(attribsRefdFromAction); + inAlt = 0; + >> + ; + <> + +/* rule element_label */ + +element_label > [LabelEntry *label] + : <> + LABEL <> + << + UsedNewStyleLabel = 1; + if ( UsedOldStyleAttrib ) err("cannot mix with new-style labels with old-style $i"); + t = (TermEntry *) hash_get(Tname, lab); + if ( t==NULL ) t = (TermEntry *) hash_get(Texpr, lab); + if ( t==NULL ) r = (RuleEntry *) hash_get(Rname, lab); + if ( t!=NULL ) { + err(eMsg1("label definition clashes with token/tokclass definition: '%s'", lab)); + $label = NULL; + } + else if ( r!=NULL ) { + err(eMsg1("label definition clashes with rule definition: '%s'", lab)); + $label = NULL; + } + else { + /* we don't clash with anybody else */ + l = (LabelEntry *) hash_get(Elabel, lab); + if ( l==NULL ) { /* ok to add new element label */ + l = (LabelEntry *)hash_add(Elabel, + lab, + (Entry *)newLabelEntry(lab)); + /* add to list of element labels for this rule */ + list_add(&CurElementLabels, (void *)lab); +/* MR7 */ leAdd(l); /* list of labels waiting for exception group definitions */ + $label = l; + } + else { + err(eMsg1("label definitions must be unique per rule: '%s'", lab)); + $label = NULL; + } + } + >> + ":" + ; + +/* rule element */ + +element[int old_not, int first_on_line, int use_def_MT_handler] > [Node *node] + : << + Attrib blk; + Predicate *pred = NULL; + int local_use_def_MT_handler=0; + ActionNode *act; + RuleRefNode *rr; + set toksrefd, rulesrefd; + TermEntry *term; + TokNode *p=NULL; RuleRefNode *q; int approx=0; + LabelEntry *label=NULL; + int predMsgDone=0; + int semDepth=0; + int ampersandStyle; + int height; /* MR11 */ + int equal_height; /* MR11 */ + + char* pFirstSetSymbol = NULL; /* MR21 */ + + $node = NULL; + >> + {element_label>[label]} + ( TokenTerm + << + term = (TermEntry *) hash_get(Tname, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + $$.left = $$.right = NULL; + } + else { + $$ = buildToken(LATEXT(1)); + p=((TokNode *)((Junction *)$$.left)->p1); + term = (TermEntry *) hash_get(Tname, LATEXT(1)); + require( term!= NULL, "hash table mechanism is broken"); + p->tclass = term->tclass; + p->complement = $old_not; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + >> + { ".." + ( QuotedTerm + <> + | TokenTerm + <> + ) + } + << + if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) ) + list_add(&MetaTokenNodes, (void *)p); + >> + ( "^" <astnode=ASTroot;>> + | <astnode=ASTchild;>> + | "!" <astnode=ASTexclude;>> + ) + { "\@" <> } + << + if ( p!=NULL && $first_on_line ) { + CurAltStart = (Junction *)$$.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + } + if ( p!=NULL ) + p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler; + $node = (Node *)p; + >> + | QuotedTerm + << + term = (TermEntry *) hash_get(Texpr, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + $$.left = $$.right = NULL; + } + else { + $$ = buildToken(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1); + p->complement = $old_not; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + >> + { ".." + ( QuotedTerm + <> + | TokenTerm + <> + ) + } + ( "^" <astnode=ASTroot;>> + | <astnode=ASTchild;>> + | "!" <astnode=ASTexclude;>> + ) + { "\@" <> } + << + if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) ) + list_add(&MetaTokenNodes, (void *)p); + >> + << + if ( $first_on_line ) { + CurAltStart = (Junction *)$$.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + } + if ( p!=NULL ) + p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler; + $node = (Node *)p; + >> + + | <> + "." + <<$$ = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);>> + ( "^" <astnode=ASTroot;>> + | <astnode=ASTchild;>> + | "!" <astnode=ASTexclude;>> + ) + <> + << + if ( $first_on_line ) { + CurAltStart = (Junction *)$$.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + $node = (Node *)p; + >> + + | <> + NonTerminal + <<$$ = buildRuleRef(LATEXT(1));>> + { "!" <p1; + q->astnode=ASTexclude;>> + } + { {"\<"} + PassAction <p1, LATEXT(1));>> + } + <p1;>> + { <> + "\>" + PassAction + << + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate assignment"); + strcpy(a, LATEXT(1)); + rr->assign = a; + >> + } + << + if ( label!=NULL ) { + rr->el_label = label->str; + label->elem = (Node *)rr; + } + if ( $first_on_line ) { + CurAltStart = (Junction *)$$.left; + altAdd(CurAltStart); /* MR7 */ + ((RuleRefNode *)((Junction *)$$.left)->p1)->altstart = CurAltStart; + } + $node = (Node *)rr; + >> + ) + + | <> + Action <<$0 = buildAction(LATEXT(1),action_file,action_line, 0);>> + <> /* MR7 */ + <<$node = (Node *) ((Junction *)$0.left)->p1;>> + + | <> + Pred <<$0 = buildAction(LATEXT(1),action_file,action_line, 1);>> + <p1;>> + <> + { <> + PassAction + << + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate predicate fail action"); + strcpy(a, LATEXT(1)); + act->pred_fail = a; + >> + } + <> /* MR7 */ + <<$node = (Node *)act;>> + + | <> + <= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); +/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; +/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + >> + { Pragma + ( "approx" <> + | "LL\(1\)" <> /* MR20 */ + | "LL\(2\)" <> /* MR20 */ + ) + } + +/* MR21 */ { FirstSetSymbol +/* MR21 */ "\(" +/* MR21 */ ( NonTerminal +/* MR21 */ << +/* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1, +/* MR21 */ sizeof(char)); +/* MR21 */ require(pFirstSetSymbol!=NULL, +/* MR21 */ "cannot allocate first set name"); +/* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1)); +/* MR21 */ >> +/* MR21 */ | TokenTerm +/* MR21 */ << +/* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1, +/* MR21 */ sizeof(char)); +/* MR21 */ require(pFirstSetSymbol!=NULL, +/* MR21 */ "cannot allocate first set name"); +/* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1)); +/* MR21 */ >> +/* MR21 */ ) +/* MR21 */ "\)" +/* MR21 */ } + + ( + + "\(" block[&toksrefd,&rulesrefd] "\)" + <> + + ( "\*" <<$$ = makeLoop($$,approx,pFirstSetSymbol);>> + | "\+" <<$$ = makePlus($$,approx,pFirstSetSymbol);>> + | "?" + ( + ( "=>" <> + | "&&" <> /* MR10 (g)? && <

>? */ + ) + Pred /* generalized predicate */ + /* first make into a predicate */ + <<$$ = buildAction(LATEXT(1),action_file,action_line,1);>> + <p1;>> + <> /* MR10 */ + <> + { <> + PassAction + << + a = (char *)calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate predicate fail action"); + strcpy(a, LATEXT(1)); + act->pred_fail = a; + >> + } + <> + <<$node = (Node *)act;>> + + /* for now, just snag context */ + << + pred = computePredFromContextGuard(blk,&predMsgDone); /* MR10 */ + if ( pred==NULL) { /* MR10 */ + if ( !predMsgDone) err("invalid or missing context guard"); /* MR10 */ + predMsgDone=1; /* MR10 */ + } else { /* MR10 */ + act->guardNodes=(Junction *)blk.left; /* MR11 */ + pred->expr = act->action; + pred->source = act; +/* MR10 */ pred->ampersandStyle = ampersandStyle; /* 0 means (g)? => ... 1 means (g)? && ... */ +/* MR13 */ if (pred->tcontext != NULL) { +/* MR13 */ height=MR_max_height_of_tree(pred->tcontext); +/* MR13 */ equal_height=MR_all_leaves_same_height(pred->tcontext,height); +/* MR13 */ if (! equal_height) { +/* MR13 */ errFL("in guarded predicates all tokens in the guard must be at the same height", +/* MR13 */ FileStr[act->file],act->line); +/* MR13 */ }; +/* MR13 */ } +/* MR10 */ if (ampersandStyle) { +/* MR10 */ act->ampersandPred = pred; +/* MR11 */ if (! HoistPredicateContext) { +/* MR11 */ errFL("without \"-prc on\" (guard)? && <>? ... doesn't make sense", +/* MR11 */ FileStr[act->file],act->line); +/* MR11 */ }; +/* MR10 */ } else { +/* MR10 */ act->guardpred = pred; +/* MR10 */ }; +/* MR10 */ if (pred->k != semDepth) { +/* MR10 */ warn(eMsgd2("length of guard (%d) does not match the length of semantic predicate (%d)", +/* MR10 */ pred->k,semDepth)); +/* MR10 */ }; + } + >> + | <<$$ = makeBlk($$,approx,pFirstSetSymbol); + FoundGuessBlk = 1; + ((Junction *) ((Junction *)$$.left)->p1)->guess=1; + if ( !$first_on_line ) { + err("(...)? predicate must be first element of production"); + } + >> + ) + | <<$$ = makeBlk($$,approx,pFirstSetSymbol);>> + ) + << + if ( pred==NULL && !predMsgDone) { /* MR10 */ + ((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID; + ((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd; + ((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd; + if ( $first_on_line ) { /* MR7 */ + CurAltStart = (Junction *)((Junction *)((Junction *)$$.left)->p1); /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; /* MR7 */ + $node = (Node *) ((Junction *)$$.left)->p1; + } + >> + + | "\{" block[&toksrefd,&rulesrefd] + <<$$ = makeOpt($2,approx,pFirstSetSymbol); + /* MR23 */ CurBlockID_array[BlkLevel] = (-1); + /* MR23 */ CurAltNum_array[BlkLevel] = (-1); + --BlkLevel; + >> + "\}" + << + ((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID; + ((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd; + ((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd; + >> + <p1); /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + >> + <<$node = (Node *) ((Junction *)$$.left)->p1;>> + + ) + +/* Error catching alternatives */ + | "\*" <> + | "\+" <> + | "\>" <' can only appear after a nonterminal"); CannotContinue=TRUE;>> + | PassAction < [...]'"); + CannotContinue=TRUE;>> + ; + <> + +/* rule default_exception_handler */ + +default_exception_handler + : exception_group > [DefaultExGroup] + ; + +/* rule exception_group */ + +exception_group > [ExceptionGroup *eg] + : <> /* MR6 */ + + "exception" <<$eg = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup));>> + { <> + PassAction /* did they attach a label? */ + << + p = LATEXT(1)+1; + p[strlen(p)-1] = '\0'; /* kill trailing space */ + label = (LabelEntry *) hash_get(Elabel, LATEXT(1)+1); + if ( label==NULL ) + { + err(eMsg1("unknown label in exception handler: '%s'", LATEXT(1)+1)); + } + >> + } + ( exception_handler > [h] + <handlers), (void *)h);>> + )* + { "default" ":" Action + <<{ + ExceptionHandler *eh = (ExceptionHandler *) + calloc(1, sizeof(ExceptionHandler)); + char *a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(eh!=NULL, "exception: cannot allocate handler"); + require(a!=NULL, "exception: cannot allocate action"); + strcpy(a, LATEXT(1)); + eh->action = a; + eh->signalname = (char *) calloc(strlen("default")+1, sizeof(char)); + require(eh->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy(eh->signalname, "default"); + list_add(&($eg->handlers), (void *)eh); + }>> + } + + << + if ( label!=NULL ) { + /* Record ex group in sym tab for this label */ + if ( label->ex_group!=NULL ) { + err(eMsg1("duplicate exception handler for label '%s'",label->str)); + } else { + label->ex_group = $eg; + /* Label the exception group itself */ + $eg->label = label->str; + /* Make the labelled element pt to the exception also */ +/* MR6 */ if (label->elem == NULL) { +/* MR6 */ err(eMsg1("reference in exception handler to undefined label '%s'",label->str)); +/* MR6 */ } else { + switch ( label->elem->ntype ) { + case nRuleRef : + { + RuleRefNode *r = (RuleRefNode *)label->elem; + r->ex_group = $eg; + break; + } + case nToken : + { + TokNode *t = (TokNode *)label->elem; + t->ex_group = $eg; + break; + } + } /* end switch */ +/* MR6 */ }; /* end test on label->elem */ + } /* end test on label->ex_group */ + + } /* end test on exception label */ + +/* MR7 */ +/* MR7 */ if (BlkLevel == 1 && label == NULL) { +/* MR7 */ $eg->forRule=1; +/* MR7 */ } else if (label == NULL) { +/* MR7 */ $eg->altID = makeAltID(CurBlockID_array[BlkLevel], CurAltNum_array[BlkLevel]); +/* MR7 */ egAdd($eg); +/* MR7 */ } else { +/* MR7 */ $eg->labelEntry=label; +/* MR7 */ }; +/* MR7 */ +/* MR7 */ /* You may want to remove this exc from the rule list */ +/* MR7 */ /* and handle at the labeled element site. */ +/* MR7 */ +/* MR7 */ if (label != NULL) { +/* MR7 */ $eg = NULL; +/* MR7 */ }; + + >> + ; + <> + +/* rule exception_handler */ + +exception_handler > [ExceptionHandler *eh] + : <<;>> /* MR9 Removed unreferenced variable "a" */ + "catch" + << + $eh = (ExceptionHandler *)calloc(1, sizeof(ExceptionHandler)); + require($eh!=NULL, "exception: cannot allocate handler"); + >> + ( NonTerminal + << + $eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require($eh->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy($eh->signalname, LATEXT(1)); + >> + | TokenTerm + << + $eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require($eh->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy($eh->signalname, LATEXT(1)); + >> + ) + ":" + { <<$eh->action = NULL;>> + Action + << + $eh->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require($eh->action!=NULL, "exception: cannot allocate action"); + strcpy($eh->action, LATEXT(1)); + >> + } + ; + <> + +#token NonTerminal "[a-z] [A-Za-z0-9_]*" + << + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + >> +#token TokenTerm "[A-Z] [A-Za-z0-9_]*" + << + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + >> +#token "{\\}#[A-Za-z0-9_]*" <> + +#lexclass PARSE_ENUM_FILE + +#token "[\t\ ]+" << zzskip(); >> /* Ignore White */ +#token "\n|\r|\r\n" << zzline++; zzskip(); >> /* Track Line # */ +#token "//" << zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); >> +#token "/\*" << zzmode(TOK_DEF_COMMENTS); zzskip(); >> +#token "#ifdef" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "#if" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "#ifndef" << ; >> +#token "#else" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "#endif" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "#undef" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "#import" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "@" << ; >> + +/* rule enum_file */ + +enum_file[char *fname] + : { "#ifndef" ID + { "#define" ID /* ignore if it smells like a gate */ + /* First #define after the first #ifndef (if any) is ignored */ + } + } + ( ( enum_def[$fname] )+ + | defines[$fname] + ) + | + ; + +/* rule defines */ + +defines[char *fname] + : <> /* MR3 */ + ( + "#define" ID + <> + INT + << + v = atoi(LATEXT(1)); +/* fprintf(stderr, "#token %s=%d\n", t, v);*/ + + /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ + /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ + /* MR2 Don't let #tokdefs be confused by */ + /* MR2 DLGminToken and DLGmaxToken */ + + if ( ! isDLGmaxToken(t)) { /* MR2 */ + TokenNum = v; + if ( v>maxt ) maxt=v; + if ( Tnum( t ) == 0 ) { + addForcedTname( t, v ); + } else { + warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline); + }; + }; + >> + )+ + <> + ; + +/* rule enum_def */ + +enum_def[char *fname] + : <> /* MR3 */ + "enum" ID + "\{" + ID + <> + ( "=" INT <> + | <> + ) + << +/* fprintf(stderr, "#token %s=%d\n", t, v);*/ + TokenNum = v; + if ( v>maxt ) maxt=v; /* MR3 */ + if ( Tnum( t ) == 0 ) addForcedTname( t, v ); + else { + warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline); + } + >> + ( "," + + /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ + /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ + /* MR2 Don't let #tokdefs be confused by */ + /* MR2 DLGminToken and DLGmaxToken */ + + { + <>? ID { "=" INT } /* MR2 */ + | ID /* MR2 */ + <> + ( "=" INT <> + | <> + ) + << +/* fprintf(stderr, "#token %s=%d\n", t, v);*/ + TokenNum = v; + if ( v>maxt ) maxt=v; /* MR3 */ + if ( Tnum( t ) == 0 ) addForcedTname( t, v ); + else { + warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline); + } + >> + } + )* + "\}" + ";" + <> /* MR3 */ + ; + +#token INT "[0-9]+" +#token ID "[a-zA-Z_][_a-zA-Z0-9]*" + +#lexclass START + +/* MR14 Arpad Beszedes 26-May-98 + Add support for #line directives when antlr source is pre-processed +*/ + +#lexaction +<< + +static char * +#ifdef __USE_PROTOS +getFileNameFromTheLineInfo(char *toStr, char *fromStr) +#else +getFileNameFromTheLineInfo(toStr, fromStr) +char *toStr, *fromStr; +#endif +{ + int i, j, k; + + if (!fromStr || !toStr) return toStr; + + /* find the first " */ + + for (i=0; + (i> + +<< + +/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ +/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ +/* MR2 Don't let #tokdefs be confused by */ +/* MR2 DLGminToken and DLGmaxToken */ + +/* semantic check on DLGminToken and DLGmaxmaxToken in #tokdefs */ + +#ifdef __USE_PROTOS +static int isDLGmaxToken(char *Token) +#else +static int isDLGmaxToken(Token) + char * Token; +#endif +{ + static char checkStr1[] = "DLGmaxToken"; + static char checkStr2[] = "DLGminToken"; + + if (strcmp(Token, checkStr1) == 0) + return 1; + else if (strcmp(Token, checkStr2) == 0) + return 1; + else + return 0; +} + +/* semantics of #token */ +static void +#ifdef __USE_PROTOS +chkToken(char *t, char *e, char *a, int tnum) +#else +chkToken(t,e,a,tnum) +char *t, *e, *a; +int tnum; +#endif +{ + TermEntry *p; + + /* check to see that they don't try to redefine a token as a token class */ + if ( t!=NULL ) { + p = (TermEntry *) hash_get(Tname, t); + if ( p!=NULL && p->classname ) { + err(eMsg1("redefinition of #tokclass '%s' to #token not allowed; ignored",t)); + if ( a!=NULL ) free((char *)a); + return; + } + } + + if ( t==NULL && e==NULL ) { /* none found */ + err("#token requires at least token name or rexpr"); + } + else if ( t!=NULL && e!=NULL ) { /* both found */ + if ( UserDefdTokens ) { /* if #tokdefs, must not define new */ + p = (TermEntry *) hash_get(Tname, t); + if ( p == NULL) { +err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t)); + return; + }; + } + Tklink(t, e); + if ( a!=NULL ) { + if ( hasAction(e) ) { + err(eMsg1("redefinition of action for %s; ignored",e)); + } + else setHasAction(e, a); + } + } + else if ( t!=NULL ) { /* only one found */ + if ( UserDefdTokens ) { + p = (TermEntry *) hash_get(Tname, t); + if (p == NULL) { +err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t)); + }; + return; + } + if ( Tnum( t ) == 0 ) addTname( t ); + else { + err(eMsg1("redefinition of token %s; ignored",t)); + } + if ( a!=NULL ) { + err(eMsg1("action cannot be attached to a token name (%s); ignored",t)); + free((char *)a); + } + } + else if ( e!=NULL ) { + if ( Tnum( e ) == 0 ) addTexpr( e ); + else { + if ( hasAction(e) ) { + err(eMsg1("redefinition of action for expr %s; ignored",e)); + } + else if ( a==NULL ) { + err(eMsg1("redefinition of expr %s; ignored",e)); + } + } + if ( a!=NULL ) setHasAction(e, a); + } + + /* if a token type number was specified, then add the token ID and 'tnum' + * pair to the ForcedTokens list. (only applies if an id was given) + */ + if ( t!=NULL && tnum>0 ) + { + if ( set_el(tnum, reserved_positions) ) + { + err(eMsgd("a token has already been forced to token number %d; ignored", tnum)); + } + else + { + list_add(&ForcedTokens, newForcedToken(t,tnum)); + set_orel(tnum, &reserved_positions); + } + } +} +>> + +<< +static int +#ifdef __USE_PROTOS +match_token(char *s, char **nxt) +#else +match_token(s,nxt) +char *s; +char **nxt; +#endif +{ + if ( !(*s>='A' && *s<='Z') ) return 0; + s++; + while ( (*s>='a' && *s<='z') || + (*s>='A' && *s<='Z') || + (*s>='0' && *s<='9') || + *s=='_' ) + { + s++; + } + if ( *s!=' ' && *s!='}' ) return 0; + *nxt = s; + return 1; +} + +static int +#ifdef __USE_PROTOS +match_rexpr(char *s, char **nxt) +#else +match_rexpr(s,nxt) +char *s; +char **nxt; +#endif +{ + if ( *s!='"' ) return 0; + s++; + while ( *s!='"' ) + { + if ( *s=='\n' || *s=='\r' ) /* MR13 */ + warn("eoln found in regular expression"); + if ( *s=='\\' ) s++; + s++; + } + *nxt = s+1; + return 1; +} + +/* + * Walk a string "{ A .. Z }" where A..Z is a space separated list + * of token references (either labels or reg exprs). Return a + * string "inlineX_set" for some unique integer X. Basically, + * we pretend as if we had seen "#tokclass inlineX { A .. Z }" + * on the input stream outside of an action. + */ +char * +#ifdef __USE_PROTOS +inline_set(char *s) +#else +inline_set(s) +char *s; +#endif +{ + char *nxt; + fprintf(stderr, "found consumeUntil( {...} )\n"); + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + if ( *s!='{' ) + { + err("malformed consumeUntil( {...} ); missing '{'"); + return "bad_set"; + } + s++; + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + while ( *s!='}' ) + { + if ( match_token(s,&nxt) ) fprintf(stderr, "found token %s\n", s); + else if ( match_rexpr(s,&nxt) ) fprintf(stderr, "found rexpr %s\n", s); + else { + err("invalid element in consumeUntil( {...} )"); + return "bad_set"; + } + s = nxt; + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + } + return "inlineX_set"; +} +>> + +<< +/* ANTLR-specific syntax error message generator + * (define USER_ZZSYN when compiling so don't get 2 definitions) + */ +void +#ifdef __USE_PROTOS +zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, +int k, char *bad_text) +#else +zzsyn(text, tok, egroup, eset, etok, k, bad_text) +char *text, *egroup, *bad_text; +int tok; +int etok; +int k; +SetWordType *eset; +#endif +{ + fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline); + fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text); + if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} + if ( k==1 ) fprintf(stderr, " missing"); + else + { + fprintf(stderr, "; \"%s\" not", bad_text); + if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); + } + if ( zzset_deg(eset)>0 ) zzedecode(eset); + else fprintf(stderr, " %s", zztokens[etok]); + if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup); + fprintf(stderr, "\n"); +} +>> + +#lexaction << +#ifdef __USE_PROTOS +void mark_label_used_in_sem_pred(LabelEntry *le) /* MR10 */ +#else +void mark_label_used_in_sem_pred(le) /* MR10 */ + LabelEntry *le; +#endif +{ + TokNode *tn; + require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken"); + tn=(TokNode *)le->elem; + require (tn->label != 0,"mark_label_used... TokNode has no label"); + tn->label_used_in_semantic_pred=1; +} +>> diff --git a/Tools/Source/TianoTools/Pccts/antlr/antlr.r b/Tools/Source/TianoTools/Pccts/antlr/antlr.r new file mode 100644 index 0000000000..e3de38759f --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/antlr.r @@ -0,0 +1,787 @@ +/* + File: antlrMPW.r + Target: antlr 133MR + Created: Monday, June 15, 1998 4:41:11 AM + Author: Kenji Tanaka (kentar@osa.att.ne.jp) +*/ + +#include "cmdo.r" + +resource 'cmdo' (128, "Antlr") { + { /* array dialogs: 5 elements */ + /* [1] */ + 295, + "ANTLR -- Purdue Compiler Construction To" + "ol Set (PCCTS) LL(k) parser generator.", + { /* array itemArray: 12 elements */ + /* [1] */ + NotDependent { + + }, + CheckOption { + NotSet, + {18, 23, 33, 223}, + "Read grammar from stdin", + "-", + "Read grammar from stdin." + }, + /* [2] */ + NotDependent { + + }, + CheckOption { + NotSet, + {38, 23, 53, 310}, + "Send grammar.c/grammar.cpp to stdout", + "-stdout", + "Send grammar.c/grammar.cpp to stdout." + }, + /* [3] */ + NotDependent { + + }, + MultiFiles { + "Grammar File(s)É", + "Choose the grammar specification files y" + "ou wish to have ANTLR process.", + {79, 22, 98, 152}, + "Grammar specification:", + "", + MultiInputFiles { + { /* array MultiTypesArray: 1 elements */ + /* [1] */ + text + }, + ".g", + "Files ending in .g", + "All text files" + } + }, + /* [4] */ + NotDependent { + + }, + Files { + DirOnly, + OptionalFile { + {58, 168, 74, 298}, + {79, 169, 98, 299}, + "Output Directory", + ":", + "-o", + "", + "Choose the directory where ANTLR will pu" + "t its output.", + dim, + "Output DirectoryÉ", + "", + "" + }, + NoMore { + + } + }, + /* [5] */ + NotDependent { + + }, + Redirection { + StandardOutput, + {126, 27} + }, + /* [6] */ + NotDependent { + + }, + Redirection { + DiagnosticOutput, + {126, 178} + }, + /* [7] */ + NotDependent { + + }, + TextBox { + gray, + {117, 20, 167, 300}, + "Redirection" + }, + /* [8] */ + NotDependent { + + }, + NestedDialog { + 5, + {20, 324, 40, 460}, + "Parse OptionsÉ", + "Parse control options may be set with th" + "is button." + }, + /* [9] */ + NotDependent { + + }, + NestedDialog { + 2, + {50, 324, 70, 460}, + "Generate OptionsÉ", + "Various command line options may be set " + "with this button." + }, + /* [10] */ + NotDependent { + + }, + NestedDialog { + 3, + {78, 324, 98, 460}, + "More OptionsÉ", + "Antlr has ALOT of options. There are eve" + "n more to be found with this button." + }, + /* [11] */ + NotDependent { + + }, + NestedDialog { + 4, + {106, 324, 126, 460}, + "Rename OptionsÉ", + "Options for renaming output files may be" + " set with this button." + }, + /* [12] */ + NotDependent { + + }, + VersionDialog { + VersionString { + "1.33MR" + }, + "PCCTS was written by Terence Parr, Russe" + "ll Quong, Will Cohen, and Hank Dietz: 19" + "89-1998. MPW port by Scott Haney.", + noDialog + } + }, + /* [2] */ + 295, + "Use this dialog to specify command line " + "Generate Options.", + { /* array itemArray: 15 elements */ + /* [1] */ + NotDependent { + + }, + CheckOption { + NotSet, + {18, 25, 33, 225}, + "Generate C++ code", + "-CC", + "Generate C++ output from both ANTLR and " + "DLG." + }, + /* [2] */ + NotDependent { + + }, + CheckOption { + NotSet, + {38, 25, 53, 225}, + "Generate ASTs", + "-gt", + "Generate code for Abstract-Syntax-Trees " + "(ASTs)." + }, + /* [3] */ + NotDependent { + + }, + CheckOption { + NotSet, + {58, 25, 73, 225}, + "Generate line info", + "-gl", + "If this option is checked, ANTLR will ge" + "nerate line info about grammaractions, t" + "hereby making debugging easier since com" + "pile errors will point to the grammar fi" + "le." + }, + /* [4] */ + NotDependent { + + }, + CheckOption { + NotSet, + {78, 25, 93, 225}, + "Generate error classes", + "-ge", + "If this option is checked, ANTLR will ge" + "nerate an error class foreach non-termin" + "al." + }, + /* [5] */ + NotDependent { + + }, + CheckOption { + NotSet, + {98, 25, 113, 225}, + "Don't generate Code", + "-gc", + "If this option is checked, ANTLR will ge" + "nerate no code, i.e. it will only perfor" + "m analysis on the grammar." + }, + /* [6] */ + NotDependent { + + }, + CheckOption { + NotSet, + {118, 25, 133, 225}, + "Delay lookahead fetches", + "-gk", + "If this option is checked, ANTLR will ge" + "nerate a parser that delays lookahead fe" + "tches until needed." + }, + /* [7] */ + NotDependent { + + }, + CheckOption { + NotSet, + {138, 25, 153, 225}, + "Use newAST(...)", + "-newAST", + "In C++ mode use \"newAST(...)\" rather tha" + "n \"new AST(...)\"" + }, + /* [8] */ + NotDependent { + + }, + CheckOption { + NotSet, + {18, 235, 33, 435}, + "Support parse traces", + "-gd", + "If this option is checked, ANTLR inserts" + " code in each parsing function to provid" + "e for user-defined handling of a detaile" + "d parse trace. The code consists of call" + "s to zzTRACEIN and zzTRACEOUT." + }, + /* [9] */ + NotDependent { + + }, + CheckOption { + NotSet, + {38, 235, 53, 435}, + "Generate cross-references", + "-cr", + "If this option is checked, ANTLR will ge" + "nerate a cross reference for all rules. " + "For each rule it will print a list of al" + "l other rules that refrence it." + }, + /* [10] */ + NotDependent { + + }, + CheckOption { + NotSet, + {58, 235, 73, 435}, + "Don't create Lexer files", + "-gx", + "If this option is checked, ANTLR will no" + "t generate DLG-related output files. Thi" + "s option should be used if one wants a c" + "ustom lexical analyzer or if one has mad" + "e changes to the grammar not affecting t" + "he lexical structure." + }, + /* [11] */ + NotDependent { + + }, + CheckOption { + NotSet, + {78, 235, 93, 460}, + "Don't generate token expr sets", + "-gs", + "If this option is checked, ANTLR will no" + "t generate sets for token expression set" + "s; instead, it will generate a || separa" + "ted sequence of LA(1)==token #. " + }, + /* [12] */ + NotDependent { + + }, + CheckOption { + NotSet, + {98, 235, 113, 460}, + "Generate ANSI-compatible", + "-ga", + "Generate ANSI-compatible code (default=F" + "ALSE)" + }, + /* [13] */ + NotDependent { + + }, + CheckOption { + NotSet, + {118, 235, 133, 460}, + "Don't generate tokens.h", + "-gxt", + "Do not generate tokens.h (default=FALSE)" + }, + /* [13] */ + NotDependent { + + }, + CheckOption { + NotSet, + {138, 235, 153, 460}, + "Provide \"(alpha)? beta\" info", + "-alpha", + "Provide additional information for \"(alpha)? beta\" error messages" + }, + /* [14] */ + NotDependent { + + }, + RegularEntry { + "Tabs(1 to 8):", + {162, 23, 177, 117}, + {163, 125, 179, 196}, + "", + keepCase, + "-tab", + "Width of tabs (1 to 8) for grammar.c/gra" + "mmar.cpp files." + }, + /* [15] */ + NotDependent { + + }, + RegularEntry { + "Function Prefix:", + {161, 236, 177, 342}, + {162, 345, 177, 454}, + "", + keepCase, + "-gp", + "Prefix all generated rule functions with" + " a string." + } + }, + /* [3] */ + 295, + "Use this dialog to specify still more co" + "mmand line options.", + { /* array itemArray: 12 elements */ + /* [1] */ + NotDependent { + + }, + RadioButtons { + { /* array radioArray: 3 elements */ + /* [1] */ + {38, 25, 53, 85}, "None", "", Set, "When this option is selected, ANTLR will" + " not print the grammar to stdout.", + /* [2] */ + {38, 100, 53, 160}, "Yes", "-p", NotSet, "When this option is selected, ANTLR will" + " print the grammar, stripped of all acti" + "ons and comments, to stdout.", + /* [3] */ + {38, 175, 53, 235}, "More", "-pa", NotSet, "When this option is selected, ANTLR will" + " print the grammar, stripped of all acti" + "ons and comments, to stdout. It will als" + "o annotate the output with the first set" + "s determined from grammar analysis." + } + }, + /* [2] */ + NotDependent { + + }, + TextBox { + gray, + {28, 15, 60, 250}, + "Grammar Printing" + }, + /* [3] */ + NotDependent { + + }, + RadioButtons { + { /* array radioArray: 3 elements */ + /* [1] */ + {88, 25, 103, 85}, "Low", "", Set, "When this option is selected, ANTLR will" + " show ambiguities/errors in low detail.", + /* [2] */ + {88, 100, 103, 160}, "Medium", "-e2", NotSet, "When this option is selected, ANTLR will" + " show ambiguities/errors in more detail.", + /* [3] */ + {88, 175, 103, 235}, "High", "-e3", NotSet, "When this option is selected, ANTLR will" + " show ambiguities/errors in excruciating" + " detail." + } + }, + /* [4] */ + NotDependent { + + }, + TextBox { + gray, + {78, 15, 110, 250}, + "Error reporting" + }, + /* [5] */ + NotDependent { + + }, + CheckOption { + NotSet, + {130, 22, 145, 222}, + "More warnings", + "-w2", + "If this option is checked, ANTLR will wa" + "rn if semantic predicates and/or (É)? bl" + "ocks are assumed to cover ambiguous alte" + "rnatives." + }, + /* [6] */ + NotDependent { + + }, + RegularEntry { + "Report when tnode usage exceeds:", + {162, 23, 180, 253}, + {162, 255, 178, 326}, + "", + keepCase, + "-treport", + "Report when tnode usage exceeds value du" + "ring ambiguity resolution." + }, + /* [7] */ + NotDependent { + + }, + CheckOption { + NotSet, + {40, 292, 55, 431}, + "Predicate", + "-info p", + "With the antlr \"-info p\" switch the user" + " will receive information about the pred" + "icate suppression in the generated file." + }, + /* [8] */ + NotDependent { + + }, + CheckOption { + NotSet, + {60, 292, 75, 430}, + "Tree Nodes", + "-info t", + "Using \"-info t\" gives information about " + "the total number of tnodes created and t" + "he peak number of tnodes." + }, + /* [9] */ + NotDependent { + + }, + CheckOption { + NotSet, + {80, 292, 95, 425}, + "First/follow", + "-info f", + "first/follow set information." + }, + /* [10] */ + NotDependent { + + }, + CheckOption { + NotSet, + {100, 292, 115, 425}, + "Monitor progress", + "-info m", + "prints name of each rule as it is starte" + "d and flushes output at start of each rule." + }, + /* [11] */ + NotDependent { + + }, + CheckOption { + NotSet, + {120, 292, 135, 416}, + "Orphan rules", + "-info o", + "If there is more than one rule which is " + "not referenced by any other rule then al" + "l such rules are listed." + }, + /* [12] */ + NotDependent { + + }, + TextBox { + gray, + {28, 279, 147, 451}, + "Extra info" + } + }, + /* [4] */ + 295, + "Use this dialog to specify command line " + "options relating to renaming output file" + "s.", + { /* array itemArray: 7 elements */ + /* [1] */ + NotDependent { + + }, + RegularEntry { + "Errors file name:", + {35, 25, 50, 205}, + {35, 205, 51, 300}, + "err.c", + keepCase, + "-fe", + "This entry specifies the name ANTLR uses" + " for the errors file." + }, + /* [2] */ + NotDependent { + + }, + RegularEntry { + "Lexical output name:", + {60, 25, 75, 205}, + {60, 205, 76, 300}, + "parser.dlg", + keepCase, + "-fl", + "This entry specifies the name ANTLR uses" + " for the lexical output file." + }, + /* [3] */ + NotDependent { + + }, + RegularEntry { + "Lexical modes name:", + {85, 25, 100, 205}, + {85, 205, 101, 300}, + "mode.h", + keepCase, + "-fm", + "This entry specifies the name ANTLR uses" + " for the lexical mode definitions file." + }, + /* [4] */ + NotDependent { + + }, + RegularEntry { + "Remap file name:", + {110, 25, 125, 205}, + {110, 205, 126, 300}, + "remap.h", + keepCase, + "-fr", + "This entry specifies the name ANTLR uses" + " for the file that remaps globally visib" + "le symbols." + }, + /* [5] */ + NotDependent { + + }, + RegularEntry { + "Tokens file name:", + {135, 25, 150, 205}, + {135, 205, 151, 300}, + "tokens.h", + keepCase, + "-ft", + "This entry specifies the name ANTLR uses" + " for the tokens file." + }, + /* [6] */ + NotDependent { + + }, + CheckOption { + NotSet, + {160, 25, 175, 175}, + "Create std header", + "-gh", + "If this option is checked, ANTLR will cr" + "eate a standard header file named, by de" + "fault 'stdpccts.h'. This name can be alt" + "ered using the entry right next door." + }, + /* [7] */ + Or { + { /* array OrArray: 1 elements */ + /* [1] */ + 6 + } + }, + RegularEntry { + "Std header file name:", + {160, 175, 175, 355}, + {160, 355, 176, 450}, + "stdpccts.h", + keepCase, + "-fh", + "This entry specifies the name ANTLR uses" + " for the standard header file." + } + }, + /* [5] */ + 295, + "Use this dialog to specify parse options" + ".", + { /* array itemArray: 9 elements */ + /* [1] */ + NotDependent { + + }, + RegularEntry { + "Lookahead:", + {23, 27, 38, 152}, + {46, 29, 62, 154}, + "1", + keepCase, + "-k", + "This entry specifies the number of token" + "s of lookahead." + }, + /* [2] */ + NotDependent { + + }, + RegularEntry { + "Compr lookahead:", + {22, 167, 37, 292}, + {46, 172, 62, 297}, + "", + keepCase, + "-ck", + "This entry specifies the number of token" + "s of lookahead when using compressed (li" + "near approximation) lookahead. In genera" + "l, the compressed lookahead is much deep" + "er than the full lookahead." + }, + /* [3] */ + NotDependent { + + }, + RegularEntry { + "Max tree nodes:", + {22, 312, 37, 437}, + {46, 315, 62, 445}, + "", + keepCase, + "-rl", + "This entry specifies the maximum number " + "of tokens of tree nodes used by the gram" + "mar analysis." + }, + /* [4] */ + NotDependent { + + }, + CheckOption { + NotSet, + {76, 25, 91, 350}, + "Maintenance Release style hoisting", + "-mrhoist", + "Turn on/off k=1 Maintenance Release styl" + "e hoisting." + }, + /* [5] */ + NotDependent { + + }, + CheckOption { + NotSet, + {96, 25, 111, 431}, + "EXPERIMENTAL Maintenance Release style h" + "oisting", + "-mrhoistk", + "Turn on/off k>1 EXPERIMENTAL Maintenance" + " Release style hoisting." + }, + /* [6] */ + NotDependent { + + }, + CheckOption { + NotSet, + {116, 25, 131, 363}, + "Compute context for hoisted predicates", + "-prc on", + "Turn on/off computation of context for h" + "oisted predicates." + }, + /* [7] */ + NotDependent { + + }, + RegularEntry { + "Ambiguity aid:", + {140, 27, 155, 125}, + {141, 135, 155, 209}, + "", + keepCase, + "-aa", + "Ambiguity aid for a rule (rule name or l" + "ine number)." + }, + /* [8] */ + NotDependent { + + }, + RegularEntry { + "Limits exp growth:", + {140, 236, 155, 361}, + {139, 372, 155, 452}, + "", + keepCase, + "-aad", + "Limits exp growth of -aa listing - defau" + "lt=1 (max=ck value)." + }, + /* [9] */ + NotDependent { + + }, + CheckOption { + NotSet, + {164, 26, 179, 366}, + "Lookahead token may appear multiple time" + "s", + "-aam", + "Lookahead token may appear multiple time" + "s in -aa listing." + } + } + } +}; + diff --git a/Tools/Source/TianoTools/Pccts/antlr/antlr1.txt b/Tools/Source/TianoTools/Pccts/antlr/antlr1.txt new file mode 100644 index 0000000000..4a7d22e7f2 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/antlr1.txt @@ -0,0 +1,264 @@ + + + +ANTLR(1) PCCTS Manual Pages ANTLR(1) + + + +NAME + antlr - ANother Tool for Language Recognition + +SYNTAX + antlr [_o_p_t_i_o_n_s] _g_r_a_m_m_a_r__f_i_l_e_s + +DESCRIPTION + _A_n_t_l_r converts an extended form of context-free grammar into + a set of C functions which directly implement an efficient + form of deterministic recursive-descent LL(k) parser. + Context-free grammars may be augmented with predicates to + allow semantics to influence parsing; this allows a form of + context-sensitive parsing. Selective backtracking is also + available to handle non-LL(k) and even non-LALR(k) con- + structs. _A_n_t_l_r also produces a definition of a lexer which + can be automatically converted into C code for a DFA-based + lexer by _d_l_g. Hence, _a_n_t_l_r serves a function much like that + of _y_a_c_c, however, it is notably more flexible and is more + integrated with a lexer generator (_a_n_t_l_r directly generates + _d_l_g code, whereas _y_a_c_c and _l_e_x are given independent + descriptions). Unlike _y_a_c_c which accepts LALR(1) grammars, + _a_n_t_l_r accepts LL(k) grammars in an extended BNF notation - + which eliminates the need for precedence rules. + + Like _y_a_c_c grammars, _a_n_t_l_r grammars can use automatically- + maintained symbol attribute values referenced as dollar + variables. Further, because _a_n_t_l_r generates top-down + parsers, arbitrary values may be inherited from parent rules + (passed like function parameters). _A_n_t_l_r also has a mechan- + ism for creating and manipulating abstract-syntax-trees. + + There are various other niceties in _a_n_t_l_r, including the + ability to spread one grammar over multiple files or even + multiple grammars in a single file, the ability to generate + a version of the grammar with actions stripped out (for + documentation purposes), and lots more. + +OPTIONS + -ck _n + Use up to _n symbols of lookahead when using compressed + (linear approximation) lookahead. This type of looka- + head is very cheap to compute and is attempted before + full LL(k) lookahead, which is of exponential complex- + ity in the worst case. In general, the compressed loo- + kahead can be much deeper (e.g, -ck 10) _t_h_a_n _t_h_e _f_u_l_l + _l_o_o_k_a_h_e_a_d (_w_h_i_c_h _u_s_u_a_l_l_y _m_u_s_t _b_e _l_e_s_s _t_h_a_n _4). + + -CC Generate C++ output from both ANTLR and DLG. + + -cr Generate a cross-reference for all rules. For each + rule, print a list of all other rules that reference + it. + + -e1 Ambiguities/errors shown in low detail (default). + + -e2 Ambiguities/errors shown in more detail. + + -e3 Ambiguities/errors shown in excruciating detail. + + -fe file + Rename err.c to file. + + -fh file + Rename stdpccts.h header (turns on -gh) to file. + + -fl file + Rename lexical output, parser.dlg, to file. + + -fm file + Rename file with lexical mode definitions, mode.h, to + file. + + -fr file + Rename file which remaps globally visible symbols, + remap.h, to file. + + -ft file + Rename tokens.h to file. + + -ga Generate ANSI-compatible code (default case). This has + not been rigorously tested to be ANSI XJ11 C compliant, + but it is close. The normal output of _a_n_t_l_r is + currently compilable under both K&R, ANSI C, and C++- + this option does nothing because _a_n_t_l_r generates a + bunch of #ifdef's to do the right thing depending on + the language. + + -gc Indicates that _a_n_t_l_r should generate no C code, i.e., + only perform analysis on the grammar. + + -gd C code is inserted in each of the _a_n_t_l_r generated pars- + ing functions to provide for user-defined handling of a + detailed parse trace. The inserted code consists of + calls to the user-supplied macros or functions called + zzTRACEIN and zzTRACEOUT. The only argument is a _c_h_a_r + * pointing to a C-style string which is the grammar + rule recognized by the current parsing function. If no + definition is given for the trace functions, upon rule + entry and exit, a message will be printed indicating + that a particular rule as been entered or exited. + + -ge Generate an error class for each non-terminal. + + -gh Generate stdpccts.h for non-ANTLR-generated files to + include. This file contains all defines needed to + describe the type of parser generated by _a_n_t_l_r (e.g. + how much lookahead is used and whether or not trees are + constructed) and contains the header action specified + by the user. + + -gk Generate parsers that delay lookahead fetches until + needed. Without this option, _a_n_t_l_r generates parsers + which always have _k tokens of lookahead available. + + -gl Generate line info about grammar actions in C parser of + the form # _l_i_n_e "_f_i_l_e" which makes error messages from + the C/C++ compiler make more sense as they will point + into the grammar file not the resulting C file. + Debugging is easier as well, because you will step + through the grammar not C file. + + -gs Do not generate sets for token expression lists; + instead generate a ||-separated sequence of + LA(1)==_t_o_k_e_n__n_u_m_b_e_r. The default is to generate sets. + + -gt Generate code for Abstract-Syntax Trees. + + -gx Do not create the lexical analyzer files (dlg-related). + This option should be given when the user wishes to + provide a customized lexical analyzer. It may also be + used in _m_a_k_e scripts to cause only the parser to be + rebuilt when a change not affecting the lexical struc- + ture is made to the input grammars. + + -k _n Set k of LL(k) to _n; i.e. set tokens of look-ahead + (default==1). + + -o dir + Directory where output files should go (default="."). + This is very nice for keeping the source directory + clear of ANTLR and DLG spawn. + + -p The complete grammar, collected from all input grammar + files and stripped of all comments and embedded + actions, is listed to stdout. This is intended to aid + in viewing the entire grammar as a whole and to elim- + inate the need to keep actions concisely stated so that + the grammar is easier to read. Hence, it is preferable + to embed even complex actions directly in the grammar, + rather than to call them as subroutines, since the sub- + routine call overhead will be saved. + + -pa This option is the same as -p except that the output is + annotated with the first sets determined from grammar + analysis. + + -prc on + Turn on the computation and hoisting of predicate con- + text. + + -prc off + Turn off the computation and hoisting of predicate con- + text. This option makes 1.10 behave like the 1.06 + release with option -pr on. Context computation is off + by default. + + -rl _n + Limit the maximum number of tree nodes used by grammar + analysis to _n. Occasionally, _a_n_t_l_r is unable to + analyze a grammar submitted by the user. This rare + situation can only occur when the grammar is large and + the amount of lookahead is greater than one. A non- + linear analysis algorithm is used by PCCTS to handle + the general case of LL(k) parsing. The average com- + plexity of analysis, however, is near linear due to + some fancy footwork in the implementation which reduces + the number of calls to the full LL(k) algorithm. An + error message will be displayed, if this limit is + reached, which indicates the grammar construct being + analyzed when _a_n_t_l_r hit a non-linearity. Use this + option if _a_n_t_l_r seems to go out to lunch and your disk + start thrashing; try _n=10000 to start. Once the + offending construct has been identified, try to remove + the ambiguity that _a_n_t_l_r was trying to overcome with + large lookahead analysis. The introduction of (...)? + backtracking blocks eliminates some of these problems - + _a_n_t_l_r does not analyze alternatives that begin with + (...)? (it simply backtracks, if necessary, at run + time). + + -w1 Set low warning level. Do not warn if semantic + predicates and/or (...)? blocks are assumed to cover + ambiguous alternatives. + + -w2 Ambiguous parsing decisions yield warnings even if + semantic predicates or (...)? blocks are used. Warn if + predicate context computed and semantic predicates + incompletely disambiguate alternative productions. + + - Read grammar from standard input and generate stdin.c + as the parser file. + +SPECIAL CONSIDERATIONS + _A_n_t_l_r works... we think. There is no implicit guarantee of + anything. We reserve no legal rights to the software known + as the Purdue Compiler Construction Tool Set (PCCTS) - PCCTS + is in the public domain. An individual or company may do + whatever they wish with source code distributed with PCCTS + or the code generated by PCCTS, including the incorporation + of PCCTS, or its output, into commercial software. We + encourage users to develop software with PCCTS. However, we + do ask that credit is given to us for developing PCCTS. By + "credit", we mean that if you incorporate our source code + into one of your programs (commercial product, research pro- + ject, or otherwise) that you acknowledge this fact somewhere + in the documentation, research report, etc... If you like + PCCTS and have developed a nice tool with the output, please + mention that you developed it using PCCTS. As long as these + guidelines are followed, we expect to continue enhancing + this system and expect to make other tools available as they + are completed. + +FILES + *.c output C parser. + + *.cpp + output C++ parser when C++ mode is used. + + parser.dlg + output _d_l_g lexical analyzer. + + err.c + token string array, error sets and error support rou- + tines. Not used in C++ mode. + + remap.h + file that redefines all globally visible parser sym- + bols. The use of the #parser directive creates this + file. Not used in C++ mode. + + stdpccts.h + list of definitions needed by C files, not generated by + PCCTS, that reference PCCTS objects. This is not gen- + erated by default. Not used in C++ mode. + + tokens.h + output #_d_e_f_i_n_e_s for tokens used and function prototypes + for functions generated for rules. + + +SEE ALSO + dlg(1), pccts(1) + + + + + diff --git a/Tools/Source/TianoTools/Pccts/antlr/bits.c b/Tools/Source/TianoTools/Pccts/antlr/bits.c new file mode 100644 index 0000000000..ddd9bd6053 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/bits.c @@ -0,0 +1,1025 @@ +/* bits.c -- manage creation and output of bit sets used by the parser. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include +#include +#include +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" + +/* char is only thing that is pretty much always known == 8 bits + * This allows output of antlr (set stuff, anyway) to be androgynous (portable) + */ +typedef unsigned char SetWordType; +#define BitsPerByte 8 +#define BitsPerWord BitsPerByte*sizeof(SetWordType) + +static SetWordType *setwd = NULL; +int setnum = -1; +int wordnum = 0; + +int esetnum = 0; + +/* Used to convert native wordsize, which ANTLR uses (via set.c) to manipulate sets, + to bytes that are most portable size-wise. + */ +void +#ifdef __USE_PROTOS +DumpIntAsChars( FILE *f, char *format, unsigned wd ) +#else +DumpIntAsChars( f, format, wd ) +FILE *f; +char *format; +unsigned wd; +#endif +{ + int i; + /* uses max of 32 bit unsigned integer for the moment */ + static unsigned long byte_mask[sizeof(unsigned long)] = + { 0xFF, 0xFF00UL, 0xFF0000UL, 0xFF000000UL }; /* MR20 G. Hobbelt */ +/* 0xFF00000000, 0xFF0000000000, 0xFF000000000000, 0xFF00000000000000 };*/ + + /* for each byte in the word */ + assert(sizeof(unsigned) <= 4); /* M20 G. Hobbelt Sanity check */ + for (i=0; i>(i*BitsPerByte)); + if ( itok))); + return empty; + } + r = RulePtr[q->rulenum]; + r->end->halt = TRUE; /* don't let reach fall off end of rule here */ + rk = empty; + REACH(r, 1, &rk, a); + r->end->halt = FALSE; + return a; +} + +/* + * scan the list of tokens/eclasses/nonterminals filling the new eclass + * with the set described by the list. Note that an eclass can be + * quoted to allow spaces etc... However, an eclass must not conflict + * with a reg expr found elsewhere. The reg expr will be taken over + * the eclass name. + */ +static void +#ifdef __USE_PROTOS +doEclass( char *eclass ) +#else +doEclass( eclass ) +char *eclass; +#endif +{ + TermEntry *q; + ECnode *p; + TCnode *tcnode; + ListNode *e; + unsigned int t; + unsigned deg=0; + set a; + require(eclass!=NULL, "doEclass: NULL eset"); + + p = (ECnode *) eclass; + lexmode(p->lexclass); /* switch to lexclass where errclass is defined */ + p->eset = empty; + for (e = (p->elist)->next; e!=NULL; e=e->next) + { + q = NULL; /* MR23 */ + + if ( islower( *((char *)e->elem) ) ) /* is it a rule ref? (alias FIRST request) */ + { + a = Efirst((char *)e->elem, p); + set_orin(&p->eset, a); + deg += set_deg(a); + set_free( a ); + continue; + } + else if ( *((char *)e->elem)=='"' ) + { + t = 0; + q = (TermEntry *) hash_get(Texpr, (char *) e->elem); + if ( q == NULL ) + { + /* if quoted and not an expr look for eclass name */ + q = (TermEntry *) hash_get(Tname, *((char **)&(e->elem))=StripQuotes((char *)e->elem)); + if ( q != NULL ) t = q->token; + } + else t = q->token; + } + else /* labelled token/eclass/tokclass */ + { + q = (TermEntry *) hash_get(Tname, (char *)e->elem); + if ( q != NULL ) + { + if ( strcmp((char *)e->elem, TokenString(p->tok))==0 ) + { + warnNoFL(eMsg1("self-referential error class '%s'; ignored", + (char *)e->elem)); + continue; + } + else + t = q->token; + } + else t=0; + } + if ( t!=0 ) + { + if (isTermEntryTokClass(q)) { /* MR23 */ + tcnode = q->tclass; /* MR23 */ + set_orin(&p->eset, tcnode->tset); /* MR23 */ + deg = set_deg(p->eset); /* MR23 */ + } /* MR23 */ + else { + set_orel(t, &p->eset); + deg++; + } + } + else warnNoFL(eMsg2("undefined token '%s' referenced in errclass '%s'; ignored", + (char *)e->elem, TokenString(p->tok))); + } + p->setdeg = deg; +} + +void +#ifdef __USE_PROTOS +ComputeErrorSets( void ) +#else +ComputeErrorSets( ) +#endif +{ +#ifdef __cplusplus + list_apply(eclasses, (void (*)(void *)) doEclass); +#else +#ifdef __USE_PROTOS + list_apply(eclasses, (void (*)(void *)) doEclass); +#else + list_apply(eclasses, doEclass); +#endif +#endif +} + +void +#ifdef __USE_PROTOS +ComputeTokSets( void ) +#else +ComputeTokSets( ) +#endif +{ + ListNode *t, *e = NULL, *e1, *e2; + int something_changed; + int i; + TCnode *p; + TermEntry *q, *q1, *q2; + + if ( tclasses == NULL ) return; + + /* turn lists of token/tokclass references into sets */ + for (t = tclasses->next; t!=NULL; t=t->next) + { + p = (TCnode *) t->elem; + + /* if wild card, then won't have entries in tclass, assume all_tokens */ + if ( p->tok == WildCardToken ) + { + p->tset = set_dup(all_tokens); + continue; + } + + lexmode(p->lexclass); /* switch to lexclass where tokclass is defined */ + p->tset = empty; + + /* instantiate all tokens/token_classes into the tset */ + for (e = (p->tlist)->next; e!=NULL; e=e->next) + { + char *tokstr; + tokstr = (char *)e->elem; + if ( *tokstr == '"' ) { + q = (TermEntry *) hash_get(Texpr, tokstr); + require(q!=NULL, "ComputeTokSets: no token def"); + set_orel(q->token, &p->tset); + } else if (tokstr[0] == '.') { + e1=e->next; + e2=e1->next; + e=e2; + q1= (TermEntry *) hash_get(Tname, (char *)e1->elem); + require(q1!=NULL, "ComputeTokSets: no token def"); + q2= (TermEntry *) hash_get(Tname, (char *)e2->elem); + require(q2!=NULL, "ComputeTokSets: no token def"); + + if (set_el(q1->token,imag_tokens)) { +errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s", + TokenString(p->tok),(char *)e1->elem) ); + } + if (set_el(q2->token,imag_tokens)) { +errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s", + TokenString(p->tok),(char *)e2->elem) ); + } + if (q1->token > q2->token) { +errNoFL(eMsg3("for #tokclass %s %s..%s - first token number > second token number", + TokenString(p->tok),(char *)e1->elem,(char *)e2->elem) ); + for (i=q2->token; i<=q1->token; i++) { set_orel(i, &p->tset); } + } else { + for (i=q1->token; i<=q2->token; i++) { set_orel(i, &p->tset); } + } + } else { + q = (TermEntry *) hash_get(Tname, tokstr); + require(q!=NULL, "ComputeTokSets: no token def"); + set_orel(q->token, &p->tset); + } + } + } + + /* Go thru list of tokclasses again looking for tokclasses in sets */ +again: + something_changed = 0; + for (t = tclasses->next; t!=NULL; t=t->next) + { + set tcl; + p = (TCnode *) t->elem; + tcl = set_and(p->tset, tokclasses); + if ( !set_nil(tcl) ) + { + int tk; + /* replace refs to tokclasses with the associated set of tokens */ + something_changed = 1; + while ( !set_nil(tcl) ) + { + tk = set_int(tcl); /* grab one of the tok class refs */ + set_rm(tk, tcl); + if ( p->tok != tk ) /* tokclass ref to yourself? */ + { + q = (TermEntry *) hash_get(Tname, TokenString(tk)); + require(q!=NULL, "#tokclass not in hash table"); + set_orin(&p->tset, q->tclass->tset); + } + set_rm(tk, p->tset); /* remove ref that we replaced */ + } + } + set_free(tcl); + } + if ( something_changed ) goto again; +} + +void +#ifdef __USE_PROTOS +DumpRemainingTokSets(void) +#else +DumpRemainingTokSets() +#endif +{ + TCnode *p; + ListNode *t; + + /* Go thru tclasses (for the last time) and dump the sets not dumped + * during code gen; yes, this is a bogus way to do this, but ComputeTokSets() + * can't dump the defs as the error file and tok file has not been created + * yet etc... + */ + if ( tclasses==NULL ) return; + for (t = tclasses->next; t!=NULL; t=t->next) + { + unsigned e; + p = (TCnode *) t->elem; + if ( p->dumped ) continue; + e = DefErrSet(&(p->tset), 0, TokenString(p->tok)); + p->dumped = 1; + p->setnum = e; + } +} + + +/* replace a subset of an error set with an error class name if a subset is found + * repeat process until no replacements made + */ +void +#ifdef __USE_PROTOS +SubstErrorClass( set *f ) +#else +SubstErrorClass( f ) +set *f; +#endif +{ + int max, done = 0; + ListNode *p; + ECnode *ec, *maxclass = NULL; + set a; + require(f!=NULL, "SubstErrorClass: NULL eset"); + + if ( eclasses == NULL ) return; + while ( !done ) + { + max = 0; + maxclass = NULL; + for (p=eclasses->next; p!=NULL; p=p->next) /* chk all error classes */ + { + ec = (ECnode *) p->elem; + if ( ec->setdeg > max ) + { + if ( set_sub(ec->eset, *f) || set_equ(ec->eset, *f) ) + {maxclass = ec; max=ec->setdeg;} + } + } + if ( maxclass != NULL ) /* if subset found, replace with token */ + { + a = set_dif(*f, maxclass->eset); + set_orel((unsigned)maxclass->tok, &a); + set_free(*f); + *f = a; + } + else done = 1; + } +} + +int +#ifdef __USE_PROTOS +DefErrSet1(int nilOK, set *f, int subst, char *name ) +#else +DefErrSet1(nilOK, f, subst, name ) +int nilOK; +set *f; +int subst; /* should be substitute error classes? */ +char *name; +#endif +{ + if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, "_set"); + else return DefErrSetForC1(nilOK, f, subst, name, "_set"); +} + +int +#ifdef __USE_PROTOS +DefErrSet( set *f, int subst, char *name ) +#else +DefErrSet( f, subst, name ) +set *f; +int subst; /* should be substitute error classes? */ +char *name; +#endif +{ + return DefErrSet1(0,f,subst,name); +} + +int +#ifdef __USE_PROTOS +DefErrSetWithSuffix(int nilOK, set *f, int subst, char *name, const char* suffix) +#else +DefErrSetWithSuffix(nilOK, f, subst, name, suffix ) +int nilOK; +set *f; +int subst; /* should be substitute error classes? */ +char *name; +char *suffix; +#endif +{ + if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, suffix ); + else return DefErrSetForC1(nilOK, f, subst, name, suffix); +} + +/* Define a new error set. WARNING...set-implementation dependent. + */ +int +#ifdef __USE_PROTOS +DefErrSetForC1(int nilOK, set *f, int subst, char * name, const char * suffix) +#else +DefErrSetForC1(nilOK, f, subst, name, suffix) +int nilOK; /* MR13 */ +set *f; +int subst; /* should be substitute error classes? */ +char *name; +const char *suffix; +#endif +{ + unsigned *p, *endp; + int e=1; + + if (!nilOK) require(!set_nil(*f), "DefErrSetForC1: nil set to dump?"); + + if ( subst ) SubstErrorClass(f); + p = f->setword; + endp = &(f->setword[f->n]); + esetnum++; + if ( name!=NULL ) + fprintf(DefFile, "extern SetWordType %s%s[];\n", name, suffix); + else + fprintf(DefFile, "extern SetWordType zzerr%d[];\n", esetnum); + if ( name!=NULL ) { + fprintf(ErrFile, "SetWordType %s%s[%d] = {", + name, + suffix, + NumWords(TokenNum-1)*sizeof(unsigned)); + } + else { + fprintf(ErrFile, "SetWordType zzerr%d[%d] = {", + esetnum, + NumWords(TokenNum-1)*sizeof(unsigned)); + } + while ( p < endp ) + { + if ( e > 1 ) fprintf(ErrFile, ", "); + DumpIntAsChars(ErrFile, "0x%x", *p++); + if ( e == 3 ) + { + DAWDLE; + if ( p < endp ) fprintf(ErrFile, ","); + fprintf(ErrFile, "\n\t"); + e=1; + } + else e++; + } + fprintf(ErrFile, "};\n"); + + return esetnum; +} + +int +#ifdef __USE_PROTOS +DefErrSetForC( set *f, int subst, char *name ) +#else +DefErrSetForC( f, subst, name ) +set *f; +int subst; /* should be substitute error classes? */ +char *name; +#endif +{ + return DefErrSetForC1(0,f,subst,name, "_set"); +} + +/* Define a new error set. WARNING...set-implementation dependent; + * Only used when -CC on. + */ + +int +#ifdef __USE_PROTOS +DefErrSetForCC1(int nilOK, set *f, int subst, char *name, const char *suffix ) +#else +DefErrSetForCC1(nilOK, f, subst, name, suffix ) +int nilOK; /* MR13 */ +set *f; +int subst; /* should be substitute error classes? */ +char *name; +const char *suffix; +#endif +{ + unsigned *p, *endp; + int e=1; + + if (!nilOK) require(!set_nil(*f), "DefErrSetForCC1: nil set to dump?"); + + if ( subst ) SubstErrorClass(f); + p = f->setword; + endp = &(f->setword[f->n]); + esetnum++; + + if ( name!=NULL ) { + fprintf(Parser_h, "\tstatic SetWordType %s%s[%d];\n", name, suffix, + NumWords(TokenNum-1)*sizeof(unsigned)); + fprintf(Parser_c, "SetWordType %s::%s%s[%d] = {", + CurrentClassName, + name, + suffix, + NumWords(TokenNum-1)*sizeof(unsigned)); + } + else { + fprintf(Parser_c, "SetWordType %s::err%d[%d] = {", + CurrentClassName, + esetnum, + NumWords(TokenNum-1)*sizeof(unsigned)); + fprintf(Parser_h, "\tstatic SetWordType err%d[%d];\n", esetnum, + NumWords(TokenNum-1)*sizeof(unsigned)); + } + + while ( p < endp ) + { + if ( e > 1 ) fprintf(Parser_c, ", "); + DumpIntAsChars(Parser_c, "0x%x", *p++); + if ( e == 3 ) + { + if ( p < endp ) fprintf(Parser_c, ","); + fprintf(Parser_c, "\n\t"); + e=1; + } + else e++; + } + fprintf(Parser_c, "};\n"); + + return esetnum; +} + +int +#ifdef __USE_PROTOS +DefErrSetForCC( set *f, int subst, char *name ) +#else +DefErrSetForCC( f, subst, name ) +set *f; +int subst; /* should be substitute error classes? */ +char *name; +#endif +{ + return DefErrSetForCC1(0,f,subst,name, "_set"); +} + +void +#ifdef __USE_PROTOS +GenParser_c_Hdr(void) +#else +GenParser_c_Hdr() +#endif +{ + int i,j; + TermEntry *te; + char * hasAkaName = NULL; /* MR23 */ + + hasAkaName = (char *) malloc(TokenNum+1); /* MR23 */ + require(hasAkaName!=NULL, "Cannot alloc hasAkaName\n"); /* MR23 */ + for (i = 0; i < TokenNum; i++) hasAkaName[i]='0'; /* MR23 */ + hasAkaName[TokenNum] = 0; /* MR23 */ + + fprintf(Parser_c, "/*\n"); + fprintf(Parser_c, " * %s: P a r s e r S u p p o r t\n", CurrentClassName); + fprintf(Parser_c, " *\n"); + fprintf(Parser_c, " * Generated from:"); + for (i=0; i=LastTokenCounted ) + { + fprintf(Parser_c, ",\n\t/* %02d */\t\"invalid\"", i); + continue; + } + if ( TokenString(i) != NULL ) { + te=(TermEntry *) hash_get(Tname,TokenString(i)); /* MR11 */ + if (te == NULL || te->akaString == NULL) { /* MR11 */ + fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i)); + } else { + hasAkaName[i] = '1'; /* MR23 */ + fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, te->akaString); /* MR11 */ + } + } + else + { + /* look in all lexclasses for the reg expr */ + for (j=0; j=NumLexClasses ) + { + if ( UserDefdTokens ) + { + fprintf(Parser_c, ",\n\t/* %02d */\t\"\"", i); + } + else + fatal_internal(eMsgd("No label or expr for token %d",i)); + } + } + } + fprintf(Parser_c, "\n};\n"); + + /* Build constructors */ + fprintf(Parser_c, "\n%s::", CurrentClassName); + fprintf(Parser_c, "%s(ANTLRTokenBuffer *input) : %s(input,%d,%d,%d,%d)\n", + CurrentClassName, + (BaseClassName == NULL ? "ANTLRParser" : BaseClassName), + OutputLL_k, + FoundGuessBlk, + DemandLookahead, + NumWords(TokenNum-1)*sizeof(unsigned)); + fprintf(Parser_c, "{\n"); + fprintf(Parser_c, "\ttoken_tbl = _token_tbl;\n"); + if (TraceGen) { + fprintf(Parser_c, "\ttraceOptionValueDefault=1;\t\t// MR10 turn trace ON\n"); + } else { + fprintf(Parser_c, "\ttraceOptionValueDefault=0;\t\t// MR10 turn trace OFF\n"); + }; + fprintf(Parser_c, "}\n\n"); + free ( (void *) hasAkaName); +} + +void +#ifdef __USE_PROTOS +GenParser_h_Hdr(void) +#else +GenParser_h_Hdr() +#endif +{ + int i; + + fprintf(Parser_h, "/*\n"); + fprintf(Parser_h, " * %s: P a r s e r H e a d e r \n", CurrentClassName); + fprintf(Parser_h, " *\n"); + fprintf(Parser_h, " * Generated from:"); + for (i=0; i 1 ) fprintf(ErrFile, "#define LL_K %d\n", OutputLL_k); +#ifdef DUM + if ( LexGen ) fprintf(ErrFile, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken)); +#endif + fprintf(ErrFile, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned)); + if ( DemandLookahead ) fprintf(ErrFile, "#define DEMAND_LOOK\n"); + fprintf(ErrFile, "#include \"antlr.h\"\n"); + if ( GenAST ) fprintf(ErrFile, "#include \"ast.h\"\n"); + + if ( UserDefdTokens ) fprintf(ErrFile, "#include %s\n", UserTokenDefsFile); + /* still need this one as it has the func prototypes */ + fprintf(ErrFile, "#include \"%s\"\n", DefFileName); + fprintf(ErrFile, "#include \"dlgdef.h\"\n"); + fprintf(ErrFile, "#include \"err.h\"\n\n"); + + /* Dump a zztokens for each automaton */ + if ( strcmp(ParserName, DefaultParserName)!=0 ) + { + fprintf(ErrFile, "ANTLRChar *%s_zztokens[%d]={\n", ParserName, TokenNum-1); + } + else + { + fprintf(ErrFile, "ANTLRChar *zztokens[%d]={\n", TokenNum-1); + } + fprintf(ErrFile, "\t/* 00 */\t\"Invalid\""); + for (i=1; i=LastTokenCounted ) + { + fprintf(ErrFile, ",\n\t/* %02d */\t\"invalid\"", i); + continue; + } + if ( TokenString(i) != NULL ) { + te=(TermEntry *) hash_get(Tname,TokenString(i)); /* MR11 */ + if (te == NULL || te->akaString == NULL) { /* MR11 */ + fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i)); + } else { + fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, te->akaString); /* MR11 */ + } + } + else + { + /* look in all lexclasses for the reg expr */ + for (j=0; j=NumLexClasses ) + { + if ( UserDefdTokens ) + { + fprintf(ErrFile, ",\n\t/* %02d */\t\"\"", i); + } + else + fatal_internal(eMsgd("No label or expr for token %d",i)); + } + } + } + fprintf(ErrFile, "\n};\n"); +} + +void +#ifdef __USE_PROTOS +dumpExpr( FILE *f, char *e ) +#else +dumpExpr( f, e ) +FILE *f; +char *e; +#endif +{ + while ( *e!='\0' ) + { + if ( *e=='\\' && *(e+1)=='\\' ) + {putc('\\', f); putc('\\', f); e+=2;} + else if ( *e=='\\' && *(e+1)=='"' ) + {putc('\\', f); putc('"', f); e+=2;} + else if ( *e=='\\' ) {putc('\\', f); putc('\\', f); e++;} + else {putc(*e, f); e++;} + } +} + +int +#ifdef __USE_PROTOS +isTermEntryTokClass(TermEntry *te) +#else +isTermEntryTokClass(te) +TermEntry *te; +#endif +{ + ListNode *t; + TCnode *p; + TermEntry *q; + char *tokstr; + + if (tclasses == NULL) return 0; + + for (t = tclasses->next; t!=NULL; t=t->next) + { + p = (TCnode *) t->elem; + tokstr = TokenString(p->tok); + lexmode(p->lexclass); /* switch to lexclass where tokclass is defined */ + q = (TermEntry *) hash_get(Tname, tokstr); + if (q == te) return 1; + } + return 0; +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/build.c b/Tools/Source/TianoTools/Pccts/antlr/build.c new file mode 100644 index 0000000000..4eb3b02af1 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/build.c @@ -0,0 +1,813 @@ +/* + * build.c -- functions associated with building syntax diagrams. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include +#include +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" + +#define SetBlk(g, t, approx, first_set_symbol) { \ + ((Junction *)g.left)->jtype = t; \ + ((Junction *)g.left)->approx = approx; \ + ((Junction *)g.left)->pFirstSetSymbol = first_set_symbol; \ + ((Junction *)g.left)->end = (Junction *) g.right; \ + ((Junction *)g.right)->jtype = EndBlk;} + +/* Add the parameter string 'parm' to the parms field of a block-type junction + * g.left points to the sentinel node on a block. i.e. g.left->p1 points to + * the actual junction with its jtype == some block-type. + */ +void +#ifdef __USE_PROTOS +addParm( Node *p, char *parm ) +#else +addParm( p, parm ) +Node *p; +char *parm; +#endif +{ + char *q = (char *) malloc( strlen(parm) + 1 ); + require(p!=NULL, "addParm: NULL object\n"); + require(q!=NULL, "addParm: unable to alloc parameter\n"); + + strcpy(q, parm); + if ( p->ntype == nRuleRef ) + { + ((RuleRefNode *)p)->parms = q; + } + else if ( p->ntype == nJunction ) + { + ((Junction *)p)->parm = q; /* only one parameter allowed on subrules */ + } + else fatal_internal("addParm: invalid node for adding parm"); +} + +/* + * Build an action node for the syntax diagram + * + * buildAction(ACTION) ::= --o-->ACTION-->o-- + * + * Where o is a junction node. + */ +Graph +#ifdef __USE_PROTOS +buildAction( char *action, int file, int line, int is_predicate ) +#else +buildAction( action, file, line, is_predicate ) +char *action; +int file; +int line; +int is_predicate; +#endif +{ + Junction *j1, *j2; + Graph g; + ActionNode *a; + require(action!=NULL, "buildAction: invalid action"); + + j1 = newJunction(); + j2 = newJunction(); + a = newActionNode(); + a->action = (char *) malloc( strlen(action)+1 ); + require(a->action!=NULL, "buildAction: cannot alloc space for action\n"); + strcpy(a->action, action); + j1->p1 = (Node *) a; + a->next = (Node *) j2; + a->is_predicate = is_predicate; + + if (is_predicate) { + PredEntry *predEntry; + char *t; + char *key; + char *u; + int inverted=0; + + t=key=(char *)calloc(1,strlen(a->action)+1); + + for (u=a->action; *u != '\0' ; u++) { + if (*u != ' ') { + if (t==key && *u=='!') { + inverted=!inverted; + } else { + *t++=*u; + }; + }; + }; + + *t='\0'; + + + predEntry=(PredEntry *)hash_get(Pname,key); + a->predEntry=predEntry; + if (predEntry != NULL) a->inverted=inverted; + } else { +/* MR12c */ char *strStart=a->action; +/* MR12c */ char *strEnd; +/* MR12c */ strEnd=strStart+strlen(strStart)-1; +/* MR12c */ for ( ; strEnd >= strStart && isspace(*strEnd); strEnd--) *strEnd=0; +/* MR12c */ while (*strStart != '\0' && isspace(*strStart)) strStart++; +/* MR12c */ if (ci_strequ(strStart,"nohoist")) { +/* MR12c */ a->noHoist=1; +/* MR12c */ } + } + + g.left = (Node *) j1; g.right = (Node *) j2; + a->file = file; + a->line = line; + a->rname = CurRule; /* MR10 */ + return g; +} + +/* + * Build a token node for the syntax diagram + * + * buildToken(TOKEN) ::= --o-->TOKEN-->o-- + * + * Where o is a junction node. + */ +Graph +#ifdef __USE_PROTOS +buildToken( char *text ) +#else +buildToken( text ) +char *text; +#endif +{ + Junction *j1, *j2; + Graph g; + TokNode *t; + require(text!=NULL, "buildToken: invalid token name"); + + j1 = newJunction(); + j2 = newJunction(); + t = newTokNode(); + t->altstart = CurAltStart; + if ( *text == '"' ) {t->label=FALSE; t->token = addTexpr( text );} + else {t->label=TRUE; t->token = addTname( text );} + j1->p1 = (Node *) t; + t->next = (Node *) j2; + g.left = (Node *) j1; g.right = (Node *) j2; + return g; +} + +/* + * Build a wild-card node for the syntax diagram + * + * buildToken(TOKEN) ::= --o-->'.'-->o-- + * + * Where o is a junction node. + */ +Graph +#ifdef __USE_PROTOS +buildWildCard( char *text ) +#else +buildWildCard( text ) +char *text; +#endif +{ + Junction *j1, *j2; + Graph g; + TokNode *t; + TCnode *w; + TermEntry *p; + require(text!=NULL, "buildWildCard: invalid token name"); + + j1 = newJunction(); + j2 = newJunction(); + t = newTokNode(); + + /* If the ref a wild card, make a token class for it */ + if ( Tnum(WildCardString) == 0 ) + { + w = newTCnode; + w->tok = addTname( WildCardString ); + set_orel(w->tok, &imag_tokens); + set_orel(w->tok, &tokclasses); + WildCardToken = w->tok; + require((p=(TermEntry *)hash_get(Tname, WildCardString)) != NULL, + "hash table mechanism is broken"); + p->classname = 1; /* entry is class name, not token */ + p->tclass = w; /* save ptr to this tclass def */ + list_add(&tclasses, (char *)w); + } + else { + p=(TermEntry *)hash_get(Tname, WildCardString); + require( p!= NULL, "hash table mechanism is broken"); + w = p->tclass; + } + + t->token = w->tok; + t->wild_card = 1; + t->tclass = w; + + t->altstart = CurAltStart; + j1->p1 = (Node *) t; + t->next = (Node *) j2; + g.left = (Node *) j1; g.right = (Node *) j2; + return g; +} + +void +#ifdef __USE_PROTOS +setUpperRange(TokNode *t, char *text) +#else +setUpperRange(t, text) +TokNode *t; +char *text; +#endif +{ + require(t!=NULL, "setUpperRange: NULL token node"); + require(text!=NULL, "setUpperRange: NULL token string"); + + if ( *text == '"' ) {t->upper_range = addTexpr( text );} + else {t->upper_range = addTname( text );} +} + +/* + * Build a rule reference node of the syntax diagram + * + * buildRuleRef(RULE) ::= --o-->RULE-->o-- + * + * Where o is a junction node. + * + * If rule 'text' has been defined already, don't alloc new space to store string. + * Set r->text to point to old copy in string table. + */ +Graph +#ifdef __USE_PROTOS +buildRuleRef( char *text ) +#else +buildRuleRef( text ) +char *text; +#endif +{ + Junction *j1, *j2; + Graph g; + RuleRefNode *r; + RuleEntry *p; + require(text!=NULL, "buildRuleRef: invalid rule name"); + + j1 = newJunction(); + j2 = newJunction(); + r = newRNode(); + r->altstart = CurAltStart; + r->assign = NULL; + if ( (p=(RuleEntry *)hash_get(Rname, text)) != NULL ) r->text = p->str; + else r->text = mystrdup( text ); + j1->p1 = (Node *) r; + r->next = (Node *) j2; + g.left = (Node *) j1; g.right = (Node *) j2; + return g; +} + +/* + * Or two subgraphs into one graph via: + * + * Or(G1, G2) ::= --o-G1-o-- + * | ^ + * v | + * o-G2-o + * + * Set the altnum of junction starting G2 to 1 + altnum of junction starting G1. + * If, however, the G1 altnum is 0, make it 1 and then + * make G2 altnum = G1 altnum + 1. + */ +Graph +#ifdef __USE_PROTOS +Or( Graph g1, Graph g2 ) +#else +Or( g1, g2 ) +Graph g1; +Graph g2; +#endif +{ + Graph g; + require(g1.left != NULL, "Or: invalid graph"); + require(g2.left != NULL && g2.right != NULL, "Or: invalid graph"); + + ((Junction *)g1.left)->p2 = g2.left; + ((Junction *)g2.right)->p1 = g1.right; + /* set altnums */ + if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1; + ((Junction *)g2.left)->altnum = ((Junction *)g1.left)->altnum + 1; + g.left = g2.left; + g.right = g1.right; + return g; +} + +/* + * Catenate two subgraphs + * + * Cat(G1, G2) ::= --o-G1-o-->o-G2-o-- + * Cat(NULL,G2)::= --o-G2-o-- + * Cat(G1,NULL)::= --o-G1-o-- + */ +Graph +#ifdef __USE_PROTOS +Cat( Graph g1, Graph g2 ) +#else +Cat( g1, g2 ) +Graph g1; +Graph g2; +#endif +{ + Graph g; + + if ( g1.left == NULL && g1.right == NULL ) return g2; + if ( g2.left == NULL && g2.right == NULL ) return g1; + ((Junction *)g1.right)->p1 = g2.left; + g.left = g1.left; + g.right = g2.right; + return g; +} + +/* + * Make a subgraph an optional block + * + * makeOpt(G) ::= --o-->o-G-o-->o-- + * | ^ + * v | + * o-------o + * + * Note that this constructs {A|B|...|Z} as if (A|B|...|Z|) was found. + * + * The node on the far right is added so that every block owns its own + * EndBlk node. + */ +Graph +#ifdef __USE_PROTOS +makeOpt( Graph g1, int approx, char * pFirstSetSymbol ) +#else +makeOpt( g1, approx, pFirstSetSymbol ) +Graph g1; +int approx; +char * pFirstSetSymbol; +#endif +{ + Junction *j1,*j2,*p; + Graph g; + require(g1.left != NULL && g1.right != NULL, "makeOpt: invalid graph"); + + j1 = newJunction(); + j2 = newJunction(); + ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */ + + /* MR21 + * + * There is code in genBlk which recognizes the node created + * by emptyAlt() as a special case and bypasses it. We don't + * want this to happen for the optBlk. + */ + + g = emptyAlt3(); /* MR21 */ + if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1; + ((Junction *)g.left)->altnum = ((Junction *)g1.left)->altnum + 1; + for(p=(Junction *)g1.left; p->p2!=NULL; p=(Junction *)p->p2) + {;} /* find last alt */ + p->p2 = g.left; /* add optional alternative */ + ((Junction *)g.right)->p1 = (Node *)j2; /* opt alt points to EndBlk */ + g1.right = (Node *)j2; + SetBlk(g1, aOptBlk, approx, pFirstSetSymbol); + j1->p1 = g1.left; /* add generic node in front */ + g.left = (Node *) j1; + g.right = g1.right; + return g; +} + +/* + * Make a graph into subblock + * + * makeBlk(G) ::= --o-->o-G-o-->o-- + * + * The node on the far right is added so that every block owns its own + * EndBlk node. + */ +Graph +#ifdef __USE_PROTOS +makeBlk( Graph g1, int approx, char * pFirstSetSymbol ) +#else +makeBlk( g1, approx, pFirstSetSymbol ) +Graph g1; +int approx; +char * pFirstSetSymbol; +#endif +{ + Junction *j,*j2; + Graph g; + require(g1.left != NULL && g1.right != NULL, "makeBlk: invalid graph"); + + j = newJunction(); + j2 = newJunction(); + ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */ + g1.right = (Node *)j2; + SetBlk(g1, aSubBlk, approx, pFirstSetSymbol); + j->p1 = g1.left; /* add node in front */ + g.left = (Node *) j; + g.right = g1.right; + + return g; +} + +/* + * Make a subgraph into a loop (closure) block -- (...)* + * + * makeLoop(G) ::= |---| + * v | + * --o-->o-->o-G-o-->o-- + * | ^ + * v | + * o-----------o + * + * After making loop, always place generic node out front. It becomes + * the start of enclosing block. The aLoopBlk is the target of the loop. + * + * Loop blks have TWO EndBlk nodes--the far right and the node that loops back + * to the aLoopBlk node. Node with which we can branch past loop == aLoopBegin and + * one which is loop target == aLoopBlk. + * The branch-past (initial) aLoopBegin node has end + * pointing to the last EndBlk node. The loop-target node has end==NULL. + * + * Loop blocks have a set of locks (from 1..CLL_k) on the aLoopBlk node. + */ +Graph +#ifdef __USE_PROTOS +makeLoop( Graph g1, int approx, char * pFirstSetSymbol ) +#else +makeLoop( g1, approx, pFirstSetSymbol) +Graph g1; +int approx; +char * pFirstSetSymbol; +#endif +{ + Junction *back, *front, *begin; + Graph g; + require(g1.left != NULL && g1.right != NULL, "makeLoop: invalid graph"); + + back = newJunction(); + front = newJunction(); + begin = newJunction(); + g = emptyAlt3(); + ((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */ + ((Junction *)g1.right)->p1 = (Node *) back; /* add node to G at end */ + ((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */ + ((Junction *)g1.left)->jtype = aLoopBlk; /* mark 2nd aLoopBlk node */ + ((Junction *)g1.left)->end = (Junction *) g1.right; + ((Junction *)g1.left)->lock = makelocks(); + ((Junction *)g1.left)->pred_lock = makelocks(); + g1.right = (Node *) back; + begin->p1 = (Node *) g1.left; + g1.left = (Node *) begin; + begin->p2 = (Node *) g.left; /* make bypass arc */ + ((Junction *)g.right)->p1 = (Node *) back; + SetBlk(g1, aLoopBegin, approx, pFirstSetSymbol); + front->p1 = g1.left; /* add node to front */ + g1.left = (Node *) front; + + return g1; +} + +/* + * Make a subgraph into a plus block -- (...)+ -- 1 or more times + * + * makePlus(G) ::= |---| + * v | + * --o-->o-G-o-->o-- + * + * After making loop, always place generic node out front. It becomes + * the start of enclosing block. The aPlusBlk is the target of the loop. + * + * Plus blks have TWO EndBlk nodes--the far right and the node that loops back + * to the aPlusBlk node. + * + * Plus blocks have a set of locks (from 1..CLL_k) on the aPlusBlk node. + */ +Graph +#ifdef __USE_PROTOS +makePlus( Graph g1, int approx, char * pFirstSetSymbol) +#else +makePlus( g1, approx, pFirstSetSymbol) +Graph g1; +int approx; +char * pFirstSetSymbol; +#endif +{ + int has_empty_alt_already = 0; + Graph g; + Junction *j2, *j3, *first_alt; + Junction *last_alt=NULL, *p; + require(g1.left != NULL && g1.right != NULL, "makePlus: invalid graph"); + + first_alt = (Junction *)g1.left; + j2 = newJunction(); + j3 = newJunction(); + if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1; + ((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */ + ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */ + ((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */ + g1.right = (Node *) j2; + SetBlk(g1, aPlusBlk, approx, pFirstSetSymbol); + ((Junction *)g1.left)->lock = makelocks(); + ((Junction *)g1.left)->pred_lock = makelocks(); + j3->p1 = g1.left; /* add node to front */ + g1.left = (Node *) j3; + + /* add an optional branch which is the "exit" branch of loop */ + /* FIRST, check to ensure that there does not already exist + * an optional path. + */ + /* find last alt */ + for(p=first_alt; p!=NULL; p=(Junction *)p->p2) + { + if ( p->p1->ntype == nJunction && + p->p1!=NULL && + ((Junction *)p->p1)->jtype==Generic && + ((Junction *)p->p1)->p1!=NULL && + ((Junction *)((Junction *)p->p1)->p1)->jtype==EndBlk ) + { + has_empty_alt_already = 1; + } + last_alt = p; + } + if ( !has_empty_alt_already ) + { + require(last_alt!=NULL, "last_alt==NULL; bad (..)+"); + g = emptyAlt(); + last_alt->p2 = g.left; + ((Junction *)g.right)->p1 = (Node *) j2; + + /* make sure lookahead computation ignores this alt for + * FIRST("(..)+"); but it's still used for computing the FIRST + * of each alternative. + */ + ((Junction *)g.left)->ignore = 1; + } + + return g1; +} + +/* + * Return an optional path: --o-->o-- + */ + +Graph +#ifdef __USE_PROTOS +emptyAlt( void ) +#else +emptyAlt( ) +#endif +{ + Junction *j1, *j2; + Graph g; + + j1 = newJunction(); + j2 = newJunction(); + j1->p1 = (Node *) j2; + g.left = (Node *) j1; + g.right = (Node *) j2; + + return g; +} + +/* MR21 + * + * There is code in genBlk which recognizes the node created + * by emptyAlt() as a special case and bypasses it. We don't + * want this to happen for the optBlk. + */ + +Graph +#ifdef __USE_PROTOS +emptyAlt3( void ) +#else +emptyAlt3( ) +#endif +{ + Junction *j1, *j2, *j3; + Graph g; + + j1 = newJunction(); + j2 = newJunction(); + j3 = newJunction(); + j1->p1 = (Node *) j2; + j2->p1 = (Node *) j3; + g.left = (Node *) j1; + g.right = (Node *) j3; + + return g; +} + +/* N o d e A l l o c a t i o n */ + +TokNode * +#ifdef __USE_PROTOS +newTokNode( void ) +#else +newTokNode( ) +#endif +{ + static TokNode *FreeList = NULL; + TokNode *p, *newblk; + + if ( FreeList == NULL ) + { + newblk = (TokNode *)calloc(TokenBlockAllocSize, sizeof(TokNode)); + if ( newblk == NULL ) + fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule)); + for (p=newblk; p<&(newblk[TokenBlockAllocSize]); p++) + { + p->next = (Node *)FreeList; /* add all new token nodes to FreeList */ + FreeList = p; + } + } + p = FreeList; + FreeList = (TokNode *)FreeList->next;/* remove a TokNode node */ + p->next = NULL; /* NULL the ptr we used */ + memset( (char *) p, 0, sizeof(TokNode)); /* MR10 */ + p->ntype = nToken; + p->rname = CurRule; + p->file = CurFile; + p->line = zzline; + p->altstart = NULL; + + return p; +} + +RuleRefNode * +#ifdef __USE_PROTOS +newRNode( void ) +#else +newRNode( ) +#endif +{ + static RuleRefNode *FreeList = NULL; + RuleRefNode *p, *newblk; + + if ( FreeList == NULL ) + { + newblk = (RuleRefNode *)calloc(RRefBlockAllocSize, sizeof(RuleRefNode)); + if ( newblk == NULL ) + fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule)); + for (p=newblk; p<&(newblk[RRefBlockAllocSize]); p++) + { + p->next = (Node *)FreeList; /* add all new rref nodes to FreeList */ + FreeList = p; + } + } + p = FreeList; + FreeList = (RuleRefNode *)FreeList->next;/* remove a Junction node */ + p->next = NULL; /* NULL the ptr we used */ + memset( (char *) p, 0, sizeof(RuleRefNode)); /* MR10 */ + p->ntype = nRuleRef; + p->rname = CurRule; + p->file = CurFile; + p->line = zzline; + p->astnode = ASTinclude; + p->altstart = NULL; + + return p; +} + +static int junctionSeqNumber=0; /* MR10 */ + +Junction * +#ifdef __USE_PROTOS +newJunction( void ) +#else +newJunction( ) +#endif +{ + static Junction *FreeList = NULL; + Junction *p, *newblk; + + if ( FreeList == NULL ) + { + newblk = (Junction *)calloc(JunctionBlockAllocSize, sizeof(Junction)); + if ( newblk == NULL ) + fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule)); + for (p=newblk; p<&(newblk[JunctionBlockAllocSize]); p++) + { + p->p1 = (Node *)FreeList; /* add all new Junction nodes to FreeList */ + FreeList = p; + } + } + p = FreeList; + FreeList = (Junction *)FreeList->p1;/* remove a Junction node */ + p->p1 = NULL; /* NULL the ptr we used */ + memset( (char *) p, 0, sizeof(Junction)); /* MR10 */ + p->ntype = nJunction; + p->visited = 0; + p->jtype = Generic; + p->rname = CurRule; + p->file = CurFile; + p->line = zzline; + p->exception_label = NULL; + p->fset = (set *) calloc(CLL_k+1, sizeof(set)); + require(p->fset!=NULL, "cannot allocate fset in newJunction"); + p->seq=++junctionSeqNumber; /* MR10 */ + + return p; +} + +ActionNode * +#ifdef __USE_PROTOS +newActionNode( void ) +#else +newActionNode( ) +#endif +{ + static ActionNode *FreeList = NULL; + ActionNode *p, *newblk; + + if ( FreeList == NULL ) + { + newblk = (ActionNode *)calloc(ActionBlockAllocSize, sizeof(ActionNode)); + if ( newblk == NULL ) + fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule)); + for (p=newblk; p<&(newblk[ActionBlockAllocSize]); p++) + { + p->next = (Node *)FreeList; /* add all new Action nodes to FreeList */ + FreeList = p; + } + } + p = FreeList; + FreeList = (ActionNode *)FreeList->next;/* remove an Action node */ + memset( (char *) p, 0, sizeof(ActionNode)); /* MR10 */ + p->ntype = nAction; + p->next = NULL; /* NULL the ptr we used */ + p->done = 0; + p->pred_fail = NULL; + p->guardpred = NULL; + p->ampersandPred = NULL; + return p; +} + +/* + * allocate the array of locks (1..CLL_k) used to inhibit infinite recursion. + * Infinite recursion can occur in (..)* blocks, FIRST calcs and FOLLOW calcs. + * Therefore, we need locks on aLoopBlk, RuleBlk, EndRule nodes. + * + * if ( lock[k]==TRUE ) then we have been here before looking for k tokens + * of lookahead. + */ +char * +#ifdef __USE_PROTOS +makelocks( void ) +#else +makelocks( ) +#endif +{ + char *p = (char *) calloc(CLL_k+1, sizeof(char)); + require(p!=NULL, "cannot allocate lock array"); + + return p; +} + +#if 0 +** #ifdef __USE_PROTOS +** void my_memset(char *p,char value,int count) +** #else +** void my_memset(p,value,count) +** char *p; +** char value; +** int count; +** #endif +** { +** int i; +** +** for (i=0; i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/Pccts/antlr/dumpcycles.c b/Tools/Source/TianoTools/Pccts/antlr/dumpcycles.c new file mode 100644 index 0000000000..8156159f71 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/dumpcycles.c @@ -0,0 +1,67 @@ +#include +#include + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" + +void +#ifdef __USE_PROTOS +dumpcycles(void) +#else +dumpcycles() +#endif +{ + Cycle *c; + CacheEntry *f; + ListNode *p; + int i=0; + int k; + int degree; + + for (k=1; k <= CLL_k; k++) { + if (Cycles[k] == NULL) continue; + + for (p = Cycles[k]->next; p!=NULL; p=p->next) { + c = (Cycle *) p->elem; + degree=set_deg(c->cyclicDep); + fprintf(stderr,"Cycle %d: (degree %d) %s -->\n", i++, degree, RulePtr[c->croot]->rname); + fprintf(stderr," *self*\n"); + MR_dumpRuleSet(c->cyclicDep); + fprintf(stderr,"\n"); + f = (CacheEntry *) + hash_get(Fcache,Fkey(RulePtr[c->croot]->rname,'o',k)); + if (f == NULL) { + fprintf(stderr," *** FOLLOW(%s) must be in cache but isn't ***\n", + RulePtr[c->croot]->rname); + }; + }; + }; +} + +void +#ifdef __USE_PROTOS +dumpfostack(int k) +#else +dumpfostack(k) +int k; +#endif +{ + int i=0; + int *pi; + + fprintf(stderr,"\n"); + if (FoStack[k] == NULL) { + fprintf(stderr,"FoStack[%d] is null\n",k); + }; + if (FoTOS[k] == NULL) { + fprintf(stderr,"FoTOS[%d] is null\n",k); + } + if (FoTOS[k] != NULL && FoStack[k] != NULL) { + for (pi=FoStack[k]; pi <= FoTOS[k]; pi++) { + i++; + fprintf(stderr,"#%d rule %d %s\n",i,*pi,RulePtr[*pi]->rname); + } + } +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/dumpnode.c b/Tools/Source/TianoTools/Pccts/antlr/dumpnode.c new file mode 100644 index 0000000000..2a34c6fcd5 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/dumpnode.c @@ -0,0 +1,423 @@ +#include +#include + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" + +#ifdef __USE_PROTOS +void dumpset1(set s) +#else +void dumpset1(s) + set s; +#endif +{ + if (set_nil(s)) { + fprintf(stderr,"{}"); + } else { + s_fprT(stderr,s); + }; +} + +#ifdef __USE_PROTOS +void dumpset(set s) +#else +void dumpset(s) + set s; +#endif +{ + dumpset1(s); + fprintf(stderr,"\n"); +} + +#ifdef __USE_PROTOS +int isEndRule(Node * p) +#else +int isEndRule(p) + Node * p; +#endif +{ + int result=0; + if ( p->ntype == nJunction && + ( (Junction *) p)->jtype == EndRule) { + result=1; + }; + return result; +} + +#ifdef __USE_PROTOS +void dumppred1(int depth,Predicate *p) +#else +void dumppred1(depth,p) + int depth; + Predicate *p; +#endif +{ + int i; + int k; + + for (i=0; iexpr == PRED_AND_LIST || + p->expr == PRED_OR_LIST) { + fprintf(stderr," %s", (p->expr == NULL ? "null expr" : p->expr)); + if (p->inverted) fprintf(stderr," predicate inverted !"); + if (p->redundant) { + fprintf(stderr," Redundant!"); + }; + if (p->isConst) fprintf(stderr," const %d !",p->constValue); + fprintf(stderr,"\n"); + } else { + fprintf(stderr,"predicate k=%d",p->k); + k=set_int(p->completionSet); + if (k >= 0) { + fprintf(stderr," Incomplete Set=%d !",k); + }; + k=set_int(p->completionTree); + if (k >= 0) { + fprintf(stderr," Incomplete Tree=%d !",k); + }; + if (p->redundant) { + fprintf(stderr," Redundant!"); + }; + fprintf(stderr," \"%s\" (%x)", (p->expr == NULL ? "null expr" : p->expr) ,p); + if (p->source != NULL) { + fprintf(stderr,"line %d",p->source->line); + }; + if (p->inverted) fprintf(stderr," predicate inverted !"); + fprintf(stderr,"\n"); + for (i=0; iscontext[1]); + for (i=0; itcontext); + fprintf(stderr,"\n"); + }; + fprintf(stderr,"\n"); + if (p->down != NULL) { + dumppred1(depth+1,p->down); + }; + if (p->right != NULL) { + dumppred1(depth,p->right); + }; +} + +#ifdef __USE_PROTOS +void dumppred(Predicate *p) +#else +void dumppred(p) + Predicate *p; +#endif +{ + fprintf(stderr,"---------------------------------\n"); + dumppred1(0,p); + fprintf(stderr,"\n"); +} + +#ifdef __USE_PROTOS +void dumppredtree(Predicate *p) +#else +void dumppredtree(p) + Predicate *p; +#endif +{ + fprintf(stderr,"predicate k=%d \"%s\" line %d\n",p->k,p->expr,p->source->line); + dumpset(p->scontext[1]); +} + +#ifdef __USE_PROTOS +void dumppredexpr(Predicate *p) +#else +void dumppredexpr(p) + Predicate *p; +#endif +{ + fprintf(stderr," pred expr \"%s\"\n",p->expr); +} + +#ifdef __USE_PROTOS +void dt(Tree *t) +#else +void dt(t) + Tree *t; +#endif +{ + MR_dumpTreeF(stderr,0,t,5); +} + +#ifdef __USE_PROTOS +void d(Node * p) +#else +void d(p) + Node * p; +#endif +{ + + Junction *j; + RuleRefNode *r; + TokNode *t; + ActionNode *a; + + if (p==NULL) { + fprintf(stderr,"dumpNode: Node is NULL"); + return; + }; + + switch (p->ntype) { + case nJunction : + j = (Junction *) p; + fprintf(stderr, "Junction (#%d in rule %s line %d) ",j->seq,j->rname,j->line); + if (j->guess) fprintf(stderr,"guess block "); + switch (j->jtype ) { + case aSubBlk : + fprintf(stderr,"aSubBlk"); + break; + case aOptBlk : + fprintf(stderr,"aOptBlk"); + break; + case aLoopBegin : + fprintf(stderr,"aLoopBeginBlk"); + break; + case aLoopBlk : + fprintf(stderr,"aLoopBlk"); + break; + case aPlusBlk : + fprintf(stderr,"aPlusBlk"); + break; + case EndBlk : + fprintf(stderr,"EndBlk"); + break; + case RuleBlk : + fprintf(stderr,"RuleBlk"); + break; + case Generic : + fprintf(stderr,"Generic"); + break; + case EndRule : + fprintf(stderr,"EndRule"); + break; + }; + if (j->halt) fprintf(stderr," halt!"); + if (j->p1) fprintf(stderr," p1 valid"); + if (j->p2) { + if (j->p2->ntype == nJunction) { + fprintf(stderr," (p2=#%d)",( (Junction *) j->p2)->seq); + } else { + fprintf(stderr," (p2 valid)"); + }; + }; + if (j->ignore) fprintf(stderr, " ignore/plus-block-bypass"); + if (j->fset != NULL && set_deg(*j->fset) != 0) { + fprintf(stderr,"\nfset:\n"); + dumpset(*j->fset); + }; + if (j->ftree != NULL) { + fprintf(stderr,"\nftree:\n"); + preorder(j->ftree); + }; + fprintf(stderr,"\n"); + break; + case nRuleRef : + r = (RuleRefNode *) p; + fprintf(stderr, "RuleRefNode (in rule %s line %d) to rule %s\n", r->rname,r->line,r->text); + break; + case nToken : + t = (TokNode *) p; + fprintf(stderr, "TokNode (in rule %s line %d) token %s\n",t->rname,t->line,TerminalString(t->token)); + break; + case nAction : + a =(ActionNode *) p; + if (a->is_predicate) { + fprintf(stderr, "Predicate (in rule %s line %d) %s",a->rname,a->line,a->action); + if (a->inverted) fprintf(stderr," action inverted !"); + if (a->guardpred != NULL) { + fprintf(stderr," guarded"); + dumppredexpr(a->guardpred); + if (a->ampersandPred) { + fprintf(stderr," \"&&\" style"); + } else { + fprintf(stderr," \"=>\" style"); + }; + }; + if (a->predEntry != NULL) fprintf(stderr," predEntry \"%s\" ",a->predEntry->str); + fprintf(stderr,"\n"); + } else if (a->init_action) { + fprintf(stderr, "Init-Action (in rule %s line %d) %s\n",a->rname,a->line,a->action); + } else { + fprintf(stderr, "Action (in rule %s line %d) %s\n",a->rname,a->line,a->action); + }; + break; + }; +} + +#ifdef __USE_PROTOS +Node * dp1(Node * p) +#else +Node * dp1(p) + Node * p; +#endif +{ + Node *result=NULL; + + if (p->ntype == nJunction) { + result=( (Junction *) p )->p1; + d(result); + } else { + fprintf(stderr,"dp1: Not a Junction node"); + }; + return result; +} + +#ifdef __USE_PROTOS +Node * dp2(Node * p) +#else +Node * dp2(p) + Node * p; +#endif +{ + Node *result=NULL; + + if (p->ntype == nJunction) { + result=( (Junction *) p )->p2; + d(result); + } else { + fprintf(stderr,"dp2: Not a Junction node"); + }; + return result; +} + +#ifdef __USE_PROTOS +Node * dn(Node * p) +#else +Node * dn(p) + Node * p; +#endif + +{ + Node *result=NULL; + + if (p->ntype == nRuleRef) { + result=( (RuleRefNode *)p )->next; + } else if (p->ntype == nAction) { + result=( (ActionNode *)p )->next; + } else if (p->ntype == nToken) { + result=( (TokNode *)p )->next; + } else { + fprintf(stderr,"No next field: Neither a RuleRefNode, ActionNode, nor TokNode"); + }; + if (result != NULL) d(result); + return result; +} + +#ifdef __USE_PROTOS +void df(Node * p) +#else +void df(p) + Node * p; +#endif +{ + int count=0; + Node *next; + + fprintf(stderr,"\n#%d ",++count); + d(p); + + for (next=p; next != NULL && !isEndRule(next) ; ) { + fprintf(stderr,"#%d ",++count); + if (next->ntype == nJunction) { + next=dp1(next); + } else { + next=dn(next); + }; + }; +} + +#ifdef __USE_PROTOS +Node * dfn(Node * p,int target) +#else +Node * dfn(p,target) + Node * p; + int target; +#endif +{ + Node *result=NULL; + int count=0; + Node *next; + + fprintf(stderr,"#%d ",++count); + d(p); + + for (next=p; next != NULL && !isEndRule(next) ; ) { + fprintf(stderr,"#%d ",++count); + if (next->ntype == nJunction) { + next=dp1(next); + } else { + next=dn(next); + }; + if (count == target) { + result=next; + break; + }; + }; + return result; +} + + +static int findnodeMatch; + +#ifdef __USE_PROTOS +Junction *findnode1(Node *n) +#else +Junction *findnode1(n) + Node *n; +#endif +{ + Node *next; + Junction *j; + Junction *match; + + if (n == NULL) return NULL; + if (n->ntype == nJunction) { + j=(Junction *) n; + if (j->seq == findnodeMatch) return j; + if (j->jtype == EndRule) return NULL; + if (j->jtype != RuleBlk && j->jtype != EndBlk) { + if (j->p2 != NULL && !j->ignore) { + match=findnode1(j->p2); + if (match != NULL) return match; + }; + }; + }; + next=MR_advance(n); + return findnode1(next); +} + +#ifdef __USE_PROTOS +Junction *findnode(int match) +#else +Junction *findnode(match) + int match; +#endif +{ + Junction *j; + Junction *result=NULL; + + findnodeMatch=match; + + for (j=SynDiag; j != NULL; j=(Junction *)j->p2) { + require (j->ntype == nJunction && j->jtype == RuleBlk,"Not a rule block"); + result=findnode1( (Node *) j); + if (result != NULL) break; + }; + if (result != NULL) { + d( (Node *) result); + }; + return result; +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/egman.c b/Tools/Source/TianoTools/Pccts/antlr/egman.c new file mode 100644 index 0000000000..c8a633fc06 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/egman.c @@ -0,0 +1,328 @@ +/* + * egman.c + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33MR10 + * 2001 + * + */ + +#include +#include + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "proto.h" + +static ExceptionGroup **egArray=NULL; /* ExceptionGroup by BlkLevel */ +static LabelEntry **leArray=NULL; /* LabelEntry by BlkLevel */ +static Junction **altArray=NULL; /* start of alternates */ +static int arraySize=0; +static int highWater=0; +static ExceptionGroup *lastEG=NULL; /* used in altFixup() */ +static int lastBlkLevel=0; /* used in altFixup() */ + +#ifdef __USE_PROTOS +static void arrayCheck(void); +#else +static void arrayCheck(); +#endif + +/* Called to add an exception group for an alternative EG */ + +#ifdef __USE_PROTOS +void egAdd(ExceptionGroup * eg) +#else +void egAdd(eg) +ExceptionGroup *eg; +#endif +{ + int i; + + ExceptionGroup *nextEG; + ExceptionGroup *innerEG; + + LabelEntry *nextLE; + LabelEntry *innerLE; + + Junction *nextAlt; + Junction *innerAlt; + + lastEG=eg; + lastBlkLevel=BlkLevel; + + arrayCheck(); + eg->pendingLink=egArray[BlkLevel]; + egArray[BlkLevel]=eg; + + /* EG for alternates already have their altID filled in */ + + for (i=BlkLevel+1; i<=highWater ; i++) { + for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) { + nextEG=innerEG->pendingLink; + innerEG->pendingLink=NULL; + innerEG->outerEG=eg; + }; + egArray[i]=NULL; + }; + + /* + * for patching up the LabelEntry you might use an EG for the + * current alternative - unlike patching up an alternative EG + * i.e. start the loop at BlkLevel rather than (BlkLevel+1) + * fill it in only if the EG and the LE are for the very + * same alternative if they're at the same BlkLevel + * it's easier to leave the LE on this list (filled in) rather than + * trying to selectively remove it. It will eventually be + * removed anyway when the BlkLevel gets small enough. + */ + + for (i=BlkLevel; i<=highWater ; i++) { + for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) { + nextLE=innerLE->pendingLink; + if (BlkLevel != i || + innerLE->curAltNum == CurAltNum_array[BlkLevel]) { + if (innerLE->outerEG == NULL) { + innerLE->outerEG=eg; + }; + }; + }; + if (BlkLevel != i) leArray[i]=NULL; + }; + +/* + * For the start of alternatives it is necessary to make a + * distinction between the exception group for the current + * alternative and the "fallback" EG for the block which + * contains the alternative + * + * The fallback outerEG is used to handle the case where + * no alternative of a block matches. In that case the + * signal is "NoViableAlt" (or "NoSemViableAlt" and the + * generator needs the EG of the block CONTAINING the + * current one. + * + * rule: ( ( ( a + * | b + * ) + * | c + * ) + * | d + * ); + */ + + for (i=BlkLevel; i <= highWater ; i++) { + for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) { + nextAlt=innerAlt->pendingLink; + + /* first fill in the EG for the current alternative */ + /* but leave it on the list in order to get the fallback EG */ + /* if the EG is at the same LEVEL as the alternative then */ + /* fill it in only if in the very same alternative */ + /* */ + /* rule: ( a */ + /* | b */ + /* | c exception ... */ + /* ) */ + /* */ + /* if the EG is outside the alternative (e.g. BlkLevel < i) */ + /* then it doesn't matter about the alternative */ + /* */ + /* rule: ( a */ + /* | b */ + /* | c */ + /* ) exception ... */ + /* */ + +#if 0 + printf("BlkLevel=%d i=%d altnum=%d CurAltNum=%d altID=%s\n", + BlkLevel,i,innerAlt->curAltNum,CurAltNum_array[BlkLevel],eg->altID); +#endif + if (BlkLevel != i || + innerAlt->curAltNum == CurAltNum_array[BlkLevel]) { + if (innerAlt->exception_label == NULL) { + innerAlt->exception_label=eg->altID; + }; + }; + + /* ocurs at a later pass then for the exception_label */ + /* if an outerEG has been found then fill in the outer EG */ + /* remove if from the list when the BlkLevel gets smaller */ + + if (BlkLevel != i) { + if (innerAlt->outerEG == NULL) { + innerAlt->outerEG=eg; + }; + }; + }; + if (BlkLevel != i) altArray[i]=NULL; + }; +} + +#ifdef __USE_PROTOS +void leAdd(LabelEntry * le) +#else +void leAdd(le) +LabelEntry *le; +#endif + +{ + arrayCheck(); + le->pendingLink=leArray[BlkLevel]; + le->curAltNum=CurAltNum_array[BlkLevel]; + leArray[BlkLevel]=le; +} + +#ifdef __USE_PROTOS +void altAdd(Junction *alt) +#else +void altAdd(alt) +Junction *alt; +#endif + +{ + arrayCheck(); +#if 0 + printf("BlkLevel=%d CurAltNum=%d\n", + BlkLevel,CurAltNum_array[BlkLevel]); +#endif + alt->curAltNum=CurAltNum_array[BlkLevel]; + alt->pendingLink=altArray[BlkLevel]; + altArray[BlkLevel]=alt; +} + +static void +#ifdef __USE_PROTOS +arrayCheck(void) +#else +arrayCheck() +#endif +{ + ExceptionGroup **egArrayNew; + LabelEntry **leArrayNew; + Junction **altArrayNew; + int arraySizeNew; + int i; + + if (BlkLevel > highWater) highWater=BlkLevel; + + if (BlkLevel >= arraySize) { + arraySizeNew=BlkLevel+5; /* MR20 */ + egArrayNew=(ExceptionGroup **) + calloc(arraySizeNew,sizeof(ExceptionGroup *)); + leArrayNew=(LabelEntry **) + calloc(arraySizeNew,sizeof(LabelEntry *)); + altArrayNew=(Junction **) + calloc(arraySizeNew,sizeof(Junction *)); + for (i=0; ipendingLink; + innerEG->pendingLink=NULL; + }; + egArray[i]=NULL; + }; + lastEG=NULL; + lastBlkLevel=0; +} + +/* always call leFixup() BEFORE egFixup() */ + +#ifdef __USE_PROTOS +void leFixup(void) +#else +void leFixup() +#endif +{ + + int i; + LabelEntry *nextLE; + LabelEntry *innerLE; + + for (i=BlkLevel; i<=highWater ; i++) { + for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) { + nextLE=innerLE->pendingLink; + innerLE->pendingLink=NULL; + }; + leArray[i]=NULL; + }; +} + +/* always call altFixup() BEFORE egFixup() */ + +#ifdef __USE_PROTOS +void altFixup(void) +#else +void altFixup() +#endif +{ + + int i; + Junction *nextAlt; + Junction *innerAlt; + + for (i=BlkLevel; i<=highWater ; i++) { + for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) { + + /* if an outerEG has been found then fill in the outer EG */ + + if (lastBlkLevel <= i) { + if (innerAlt->outerEG == NULL) { + innerAlt->outerEG=lastEG; + }; + }; + nextAlt=innerAlt->pendingLink; + innerAlt->pendingLink=NULL; + }; + altArray[i]=NULL; + }; +} + diff --git a/Tools/Source/TianoTools/Pccts/antlr/err.c b/Tools/Source/TianoTools/Pccts/antlr/err.c new file mode 100644 index 0000000000..ca239398cf --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/err.c @@ -0,0 +1,538 @@ +/* + * A n t l r S e t s / E r r o r F i l e H e a d e r + * + * Generated from: antlr.g + * + * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001 + * Parr Research Corporation + * with Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include "pcctscfg.h" +#include "set.h" +#include +#include "syn.h" +#include "hash.h" +#include "generic.h" +#define zzcr_attr(attr,tok,t) +#define zzSET_SIZE 20 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "err.h" + +ANTLRChar *zztokens[157]={ + /* 00 */ "Invalid", + /* 01 */ "Eof", + /* 02 */ "QuotedTerm", + /* 03 */ "\\n|\\r|\\r\\n", + /* 04 */ "\\(\\n|\\r|\\r\\n)", + /* 05 */ "\\~[]", + /* 06 */ "~[\\n\\r\"\\]+", + /* 07 */ "\"", + /* 08 */ "\\n|\\r|\\r\\n", + /* 09 */ "\\(\\n|\\r|\\r\\n)", + /* 10 */ "\\~[]", + /* 11 */ "~[\\n\\r\"\\]+", + /* 12 */ "'", + /* 13 */ "\\n|\\r|\\r\\n", + /* 14 */ "\\~[]", + /* 15 */ "~[\\n\\r'\\]+", + /* 16 */ "\\*/", + /* 17 */ "\\*", + /* 18 */ "\\n|\\r|\\r\\n", + /* 19 */ "~[\\n\\r\\*]+", + /* 20 */ "\\*/", + /* 21 */ "\\*", + /* 22 */ "\\n|\\r|\\r\\n", + /* 23 */ "~[\\n\\r\\*]+", + /* 24 */ "\\n|\\r|\\r\\n", + /* 25 */ "~[\\n\\r]+", + /* 26 */ "\\n|\\r|\\r\\n", + /* 27 */ "~[\\n\\r]+", + /* 28 */ "\\n|\\r|\\r\\n", + /* 29 */ "~[\\n\\r]+", + /* 30 */ "\\*/", + /* 31 */ "\\*", + /* 32 */ "\\n|\\r|\\r\\n", + /* 33 */ "~[\\n\\r\\*]+", + /* 34 */ "Action", + /* 35 */ "Pred", + /* 36 */ "PassAction", + /* 37 */ "consumeUntil\\( [\\ \\t]* \\{~[\\}]+\\} [\\ \\t]* \\)", + /* 38 */ "consumeUntil\\( ~[\\)]+ \\)", + /* 39 */ "\\n|\\r|\\r\\n", + /* 40 */ "\\>", + /* 41 */ "$", + /* 42 */ "$$", + /* 43 */ "$\\[\\]", + /* 44 */ "$\\[", + /* 45 */ "$[0-9]+", + /* 46 */ "$[0-9]+.", + /* 47 */ "$[0-9]+.[0-9]+", + /* 48 */ "$[_a-zA-Z][_a-zA-Z0-9]*", + /* 49 */ "#0", + /* 50 */ "#\\[\\]", + /* 51 */ "#\\(\\)", + /* 52 */ "#[0-9]+", + /* 53 */ "#line[\\ \\t]* [0-9]+ {[\\ \\t]* \"~[\"]+\" ([\\ \\t]* [0-9]*)* } (\\n|\\r|\\r\\n)", + /* 54 */ "#line ~[\\n\\r]* (\\n|\\r|\\r\\n)", + /* 55 */ "#[_a-zA-Z][_a-zA-Z0-9]*", + /* 56 */ "#\\[", + /* 57 */ "#\\(", + /* 58 */ "#", + /* 59 */ "\\)", + /* 60 */ "\\[", + /* 61 */ "\\(", + /* 62 */ "\\\\]", + /* 63 */ "\\\\)", + /* 64 */ "\\>", + /* 65 */ "'", + /* 66 */ "\"", + /* 67 */ "\\$", + /* 68 */ "\\#", + /* 69 */ "\\(\\n|\\r|\\r\\n)", + /* 70 */ "\\~[\\]\\)>$#]", + /* 71 */ "/", + /* 72 */ "/\\*", + /* 73 */ "\\*/", + /* 74 */ "//", + /* 75 */ "~[\\n\\r\\)\\(\\$#\\>\\]\\[\"'/]+", + /* 76 */ "[\\t\\ ]+", + /* 77 */ "\\n|\\r|\\r\\n", + /* 78 */ "\\[", + /* 79 */ "\\<\\<", + /* 80 */ "\"", + /* 81 */ "/\\*", + /* 82 */ "\\*/", + /* 83 */ "//", + /* 84 */ "#line[\\ \\t]* [0-9]+ {[\\ \\t]* \"~[\"]+\" ([\\ \\t]* [0-9]*)* } (\\n|\\r|\\r\\n)", + /* 85 */ "#line ~[\\n\\r]* (\\n|\\r|\\r\\n)", + /* 86 */ "\\>\\>", + /* 87 */ "WildCard", + /* 88 */ "\\@", + /* 89 */ "LABEL", + /* 90 */ "grammar-element", + /* 91 */ "meta-symbol", + /* 92 */ "Pragma", + /* 93 */ "FirstSetSymbol", + /* 94 */ "{\\}#header", + /* 95 */ "{\\}#first", + /* 96 */ "{\\}#parser", + /* 97 */ "{\\}#tokdefs", + /* 98 */ "\\}", + /* 99 */ "class", + /* 100 */ "NonTerminal", + /* 101 */ "TokenTerm", + /* 102 */ "\\{", + /* 103 */ "!", + /* 104 */ "\\<", + /* 105 */ "\\>", + /* 106 */ ":", + /* 107 */ ";", + /* 108 */ "{\\}#lexaction", + /* 109 */ "{\\}#lexmember", + /* 110 */ "{\\}#lexprefix", + /* 111 */ "{\\}#pred", + /* 112 */ "\\|\\|", + /* 113 */ "&&", + /* 114 */ "\\(", + /* 115 */ "\\)", + /* 116 */ "{\\}#lexclass", + /* 117 */ "{\\}#errclass", + /* 118 */ "{\\}#tokclass", + /* 119 */ "..", + /* 120 */ "{\\}#token", + /* 121 */ "=", + /* 122 */ "[0-9]+", + /* 123 */ "\\|", + /* 124 */ "\\~", + /* 125 */ "^", + /* 126 */ "approx", + /* 127 */ "LL\\(1\\)", + /* 128 */ "LL\\(2\\)", + /* 129 */ "\\*", + /* 130 */ "\\+", + /* 131 */ "?", + /* 132 */ "=>", + /* 133 */ "exception", + /* 134 */ "default", + /* 135 */ "catch", + /* 136 */ "{\\}#[A-Za-z0-9_]*", + /* 137 */ "[\\t\\ ]+", + /* 138 */ "\\n|\\r|\\r\\n", + /* 139 */ "//", + /* 140 */ "/\\*", + /* 141 */ "#ifdef", + /* 142 */ "#if", + /* 143 */ "#ifndef", + /* 144 */ "#else", + /* 145 */ "#endif", + /* 146 */ "#undef", + /* 147 */ "#import", + /* 148 */ "ID", + /* 149 */ "#define", + /* 150 */ "INT", + /* 151 */ "enum", + /* 152 */ "\\{", + /* 153 */ "=", + /* 154 */ ",", + /* 155 */ "\\}", + /* 156 */ ";" +}; +SetWordType zzerr1[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr2[20] = {0xfc,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xf3, + 0xbf,0xff,0xff,0xff, 0xff,0xff,0xff,0x1f}; +SetWordType zzerr3[20] = {0xfc,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xfb, + 0x3b,0xf7,0xf7,0xc7, 0xff,0xff,0xff,0x1f}; +SetWordType zzerr4[20] = {0x4,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x80,0x7,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType setwd1[157] = {0x0,0x50,0xa0,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x6a,0x20,0xa0,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x0,0x0,0x20,0x20,0x21, + 0x21,0x21,0x21,0x6e,0x6e,0x64,0x20,0x0, + 0x20,0xa0,0xa0,0xa0,0x20,0x6a,0x6a,0x6a, + 0x6e,0x20,0x20,0x20,0x20,0x66,0x6e,0x6e, + 0x20,0x66,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20}; +SetWordType zzerr5[20] = {0x0,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x1,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr6[20] = {0x4,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x7,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr7[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x6,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr8[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x4,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr9[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf0,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType setwd2[157] = {0x0,0xf8,0x6,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xf8,0x0,0x1,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xf8,0xf8,0xf8,0x0,0x0, + 0x0,0x1,0x2,0x6,0x0,0xf8,0xf8,0xf8, + 0xf8,0x0,0x0,0x0,0x0,0xf8,0xf8,0xf8, + 0x0,0xf8,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0xe8,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr10[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0xbc,0xf8,0x74,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr11[20] = {0x0,0x0,0x0,0x0, 0x8,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0xa0,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr12[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr13[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0xa0,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType setwd3[157] = {0x0,0xfa,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xfa,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xfa,0xfa,0xfa,0x5,0x0, + 0x5,0x0,0x0,0x0,0xe2,0xfa,0xfa,0xfa, + 0xfa,0xc0,0x80,0x5,0xe0,0xfa,0xfa,0xfa, + 0x0,0xfa,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0xfa,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr14[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr15[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr16[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr17[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr18[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x24,0x0,0x80,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr19[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr20[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x74,0x3, 0x20,0x0,0x0,0x0}; +SetWordType zzerr21[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x70,0x3, 0x20,0x0,0x0,0x0}; +SetWordType setwd4[157] = {0x0,0xe5,0xda,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xe5,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xed,0xe5,0xe7,0x1a,0x0, + 0x0,0x0,0x0,0x0,0xc0,0xe5,0xe5,0xe5, + 0xe5,0x0,0x0,0x0,0x0,0xe5,0xe5,0xe5, + 0x0,0xe5,0x40,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0xe5,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr22[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x3c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr23[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr24[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr25[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr26[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType setwd5[157] = {0x0,0x1f,0xc1,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xdf,0xc0,0xc0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0xc0,0x0,0xc0,0x0,0x0,0xc0,0xc0,0x0, + 0x0,0x0,0x0,0x7f,0x1f,0xdf,0xc0,0xc0, + 0x0,0x0,0xc0,0x0,0x67,0x1f,0x1f,0x1f, + 0x1f,0x0,0x0,0xc0,0x60,0x1f,0x1f,0x1f, + 0x0,0x1f,0x0,0x0,0x40,0xc0,0x0,0x0, + 0x0,0x0,0xc0,0xc0,0x0,0x0,0x5f,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr27[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x0,0x0,0x0,0x10, 0x0,0x0,0x0,0x0}; +SetWordType zzerr28[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x80,0x2, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr29[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr30[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd, + 0x0,0x0,0x80,0x0, 0x20,0x0,0x0,0x0}; +SetWordType zzerr31[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd, + 0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0}; +SetWordType zzerr32[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr33[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType setwd6[157] = {0x0,0x0,0xfd,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xe1,0xe1,0xe1,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0xfd,0x60,0xe9,0x0,0x0,0xe1,0xe1,0x0, + 0x0,0x0,0x0,0xe2,0x0,0xfd,0xfd,0xe1, + 0x20,0x0,0xe1,0x0,0xe2,0x0,0x0,0x0, + 0x0,0x0,0x0,0xe1,0xe2,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0xe2,0xe0,0x20,0x0, + 0x0,0x0,0xe1,0xe1,0x0,0x0,0xe2,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr34[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd, + 0x0,0x0,0x80,0x0, 0x20,0x0,0x0,0x0}; +SetWordType zzerr35[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd, + 0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0}; +SetWordType zzerr36[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr37[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xc, + 0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0}; +SetWordType zzerr38[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x84,0x9,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr39[20] = {0x0,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x1,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr40[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x9,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr41[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr42[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x80,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType setwd7[157] = {0x0,0x0,0xdf,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xdf,0xdf,0xff,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0xdf,0x3,0xdf,0x0,0x0,0xdf,0xdf,0x0, + 0x0,0x0,0x0,0xdf,0x0,0xdf,0xdf,0xdf, + 0x1,0x30,0xdf,0x0,0xdf,0x0,0x0,0x0, + 0x0,0x0,0x0,0xdf,0xdf,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0xdf,0xdf,0x1,0x0, + 0x0,0x0,0xdf,0xdf,0x0,0x0,0xdf,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr43[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr44[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xc0, 0x1,0x0,0x0,0x0}; +SetWordType zzerr45[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x30, + 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr46[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr47[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x20, + 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr48[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x2,0x0, 0x10,0x0,0x0,0x0}; +SetWordType zzerr49[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr50[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x8,0xa,0x18, 0x30,0x0,0x0,0x0}; +SetWordType zzerr51[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x8,0x8,0x18, 0x28,0x0,0x0,0x0}; +SetWordType zzerr52[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr53[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType setwd8[157] = {0x0,0x0,0xe1,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xe1,0xe1,0xe1,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0xe1,0x0,0xe1,0x0,0x0,0xe3,0xe7,0x0, + 0x0,0x0,0x0,0xe1,0x0,0xe1,0xe1,0xef, + 0x0,0x0,0xe1,0x0,0xe1,0x0,0x0,0x0, + 0x0,0x0,0x10,0xef,0xe1,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0xe1,0xe1,0x0,0x0, + 0x0,0x0,0xe1,0xe1,0x0,0x10,0xe1,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr54[20] = {0x2,0x0,0x0,0x0, 0x14,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x78,0x9, 0xe0,0x0,0x0,0x0}; +SetWordType zzerr55[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x78,0x9, 0x60,0x0,0x0,0x0}; +SetWordType zzerr56[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr57[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x78,0x9, 0xe0,0x0,0x0,0x0}; +SetWordType setwd9[157] = {0x0,0x7c,0x1,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x7f,0x1,0x1,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x1,0x0,0x1,0x0,0x0,0x1,0x1,0x0, + 0x0,0x0,0x0,0x7f,0x7e,0x7f,0x1,0x1, + 0x0,0x0,0x1,0x0,0x7d,0x7e,0x7e,0x7e, + 0x7e,0x0,0x0,0x1,0x7d,0x7e,0x7e,0x7e, + 0x0,0x7e,0x0,0x0,0x7d,0x1,0x0,0x0, + 0x0,0x0,0x1,0x1,0x0,0x0,0x7f,0x64, + 0x64,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x80,0x0,0x0,0x0,0x0,0x0,0x80,0x0, + 0x80,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr58[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0xa0,0x0}; +SetWordType zzerr59[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x80,0xa0,0x0}; +SetWordType zzerr60[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0xa0,0x0}; +SetWordType zzerr61[20] = {0x2,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x80,0xa0,0x0}; +SetWordType zzerr62[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe}; +SetWordType zzerr63[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe}; +SetWordType zzerr64[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe}; +SetWordType zzerr65[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0x10,0xc}; +SetWordType setwd10[157] = {0x0,0xc,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x0, + 0x3,0x0,0x0,0xf0,0xf0,0x0}; +SetWordType setwd11[157] = {0x0,0x1,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x1,0x0,0x0,0x0,0x0,0x0}; diff --git a/Tools/Source/TianoTools/Pccts/antlr/fcache.c b/Tools/Source/TianoTools/Pccts/antlr/fcache.c new file mode 100644 index 0000000000..ff7dcdfdd5 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/fcache.c @@ -0,0 +1,123 @@ +/* + * fcache.c + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33MR10 + * + */ + +#include +#include + +#include "pcctscfg.h" + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" + +#ifdef __USE_PROTOS +CacheEntry *dumpFcache1(char *prev) +#else +CacheEntry *dumpFcache1(prev) + char *prev; +#endif +{ + Entry **table=Fcache; + + int low=0; + int hi=0; + + CacheEntry *least=NULL; + + Entry **p; + + for (p=table; p<&(table[HashTableSize]); p++) { + + CacheEntry *q =(CacheEntry *) *p; + + if ( q != NULL && low==0 ) low = p-table; + while ( q != NULL ) { + if (strcmp(q->str,prev) > 0) { + if (least == NULL) { + least=q; + } else { + if (strcmp(q->str,least->str) < 0) { + least=q; + }; + }; + }; + q = q->next; + }; + + if ( *p != NULL ) hi = p-table; + } + return least; +} + +#ifdef __USE_PROTOS +void reportFcache(CacheEntry *q) +#else +void reportFcache(q) + CacheEntry *q; +#endif +{ + char *qstr; + + fprintf(stdout,"\nrule "); + for (qstr=q->str; *qstr != '*' ; qstr++) { + fprintf(stdout,"%c",*qstr); + }; + + qstr++; + if (*qstr == 'i') fprintf(stdout," First["); + if (*qstr == 'o') fprintf(stdout," Follow["); + qstr++; + fprintf(stdout,"%s]",qstr); + if (q->incomplete) fprintf(stdout," *** incomplete ***"); + fprintf(stdout,"\n"); + MR_dumpTokenSet(stdout,1,q->fset); +} + +void +#ifdef __USE_PROTOS +DumpFcache(void) +#else +DumpFcache() +#endif +{ + + char *prev=""; + int n=0; + CacheEntry *next; + + fprintf(stdout,"\n\nDump of First/Follow Cache\n"); + + for(;;) { + next=dumpFcache1(prev); + if (next == NULL) break; + reportFcache(next); + ++n; + prev=next->str; + }; + fprintf(stdout,"\nEnd dump of First/Follow Cache\n"); +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/fset.c b/Tools/Source/TianoTools/Pccts/antlr/fset.c new file mode 100644 index 0000000000..e1a76ec620 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/fset.c @@ -0,0 +1,1555 @@ +/* + * fset.c + * + * Compute FIRST and FOLLOW sets. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include + +#include "pcctscfg.h" + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include "limits.h" + +#ifdef __USE_PROTOS +static void ensure_predicates_cover_ambiguous_lookahead_sequences + (Junction *, Junction *, char *, Tree *); +#else +static void ensure_predicates_cover_ambiguous_lookahead_sequences(); +#endif + +/* + * What tokens are k tokens away from junction q? + * + * Follow both p1 and p2 paths (unless RuleBlk) to collect the tokens k away from this + * node. + * We lock the junction according to k--the lookahead. If we have been at this + * junction before looking for the same, k, number of lookahead tokens, we will + * do it again and again...until we blow up the stack. Locks are only used on aLoopBlk, + * RuleBlk, aPlusBlk and EndRule junctions to remove/detect infinite recursion from + * FIRST and FOLLOW calcs. + * + * If p->jtype == EndRule we are going to attempt a FOLLOW. (FOLLOWs are really defined + * in terms of FIRST's, however). To proceed with the FOLLOW, p->halt cannot be + * set. p->halt is set to indicate that a reference to the current rule is in progress + * and the FOLLOW is not desirable. + * + * If we attempt a FOLLOW and find that there is no FOLLOW or REACHing beyond the EndRule + * junction yields an empty set, replace the empty set with EOF. No FOLLOW means that + * only EOF can follow the current rule. This normally occurs only on the start symbol + * since all other rules are referenced by another rule somewhere. + * + * Normally, both p1 and p2 are followed. However, checking p2 on a RuleBlk node is + * the same as checking the next rule which is clearly incorrect. + * + * Cycles in the FOLLOW sense are possible. e.g. Fo(c) requires Fo(b) which requires + * Fo(c). Both Fo(b) and Fo(c) are defined to be Fo(b) union Fo(c). Let's say + * Fo(c) is attempted first. It finds all of the FOLLOW symbols and then attempts + * to do Fo(b) which finds of its FOLLOW symbols. So, we have: + * + * Fo(c) + * / \ + * a set Fo(b) + * / \ + * a set Fo(c) .....Hmmmm..... Infinite recursion! + * + * The 2nd Fo(c) is not attempted and Fo(b) is left deficient, but Fo(c) is now + * correctly Fo(c) union Fo(b). We wish to pick up where we left off, so the fact + * that Fo(b) terminated early means that we lack Fo(c) in the Fo(b) set already + * laying around. SOOOOoooo, we track FOLLOW cycles. All FOLLOW computations are + * cached in a hash table. After the sequence of FOLLOWs finish, we reconcile all + * cycles --> correct all Fo(rule) sets in the cache. + * + * Confused? Good! Read my MS thesis [Purdue Technical Report TR90-30]. + * TJP 8/93 -- can now read PhD thesis from Purdue. + * + * Also, FIRST sets are cached in the hash table. Keys are (rulename,Fi/Fo,k). + * Only FIRST sets, for which the FOLLOW is not included, are stored. + * + * SPECIAL CASE of (...)+ blocks: + * I added an optional alt so that the alts could see what + * was behind the (...)+ block--thus using enough lookahead + * to branch out rather than just enough to distinguish + * between alts in the (...)+. However, when the FIRST("(...)+") is + * is needed, must not use this last "optional" alt. This routine + * turns off this path by setting a new 'ignore' flag for + * the alt and then resetting it afterwards. + */ + +set +#ifdef __USE_PROTOS +rJunc( Junction *p, int k, set *rk ) +#else +rJunc( p, k, rk ) +Junction *p; +int k; +set *rk; +#endif +{ + set a, b; + + require(p!=NULL, "rJunc: NULL node"); + require(p->ntype==nJunction, "rJunc: not junction"); + +#ifdef DBG_LL1 + if ( p->jtype == RuleBlk ) fprintf(stderr, "FIRST(%s,%d) \n",((Junction *)p)->rname,k); + else fprintf(stderr, "rJunc: %s in rule %s\n", + decodeJType[p->jtype], ((Junction *)p)->rname); +#endif + /* if this is one of the added optional alts for (...)+ then return */ + + /* no need to pop backtrace - hasn't been pushed */ + + if ( p->ignore ) return empty; + + if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p); + +/* MR14 */ if (AlphaBetaTrace && p->alpha_beta_guess_end) { +/* MR14 */ warnFL( +/* MR14 */ "not possible to compute follow set for alpha in an \"(alpha)? beta\" block. ", +/* MR14 */ FileStr[p->file],p->line); +/* MR14 */ MR_alphaBetaTraceReport(); +/* MR14 */ }; + +/* MR14 */ if (p->alpha_beta_guess_end) { +/* MR14 */ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); +/* MR14 */ return empty; +/* MR14 */ } + + /* locks are valid for aLoopBlk,aPlusBlk,RuleBlk,EndRule junctions only */ + if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || + p->jtype==aPlusBlk || p->jtype==EndRule ) + { + require(p->lock!=NULL, "rJunc: lock array is NULL"); + if ( p->lock[k] ) + { + if ( p->jtype == EndRule ) /* FOLLOW cycle? */ + { +#ifdef DBG_LL1 + fprintf(stderr, "FOLLOW cycle to %s: panic!\n", p->rname); +#endif + if (! MR_AmbSourceSearch) RegisterCycle(p->rname, k); + } + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return empty; + } + if ( p->jtype == RuleBlk && + p->end->halt && + ! MR_AmbSourceSearch) /* check for FIRST cache */ + { + CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'i',k)); + if ( q != NULL ) + { + set_orin(rk, q->rk); + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return set_dup( q->fset ); + } + } + if ( p->jtype == EndRule && + !p->halt && /* MR11 was using cache even when halt set */ + ! MR_AmbSourceSearch) /* FOLLOW set cached already? */ + { + CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'o',k)); + if ( q != NULL ) + { +#ifdef DBG_LL1 + fprintf(stderr, "cache for FOLLOW(%s,%d):", p->rname,k); + s_fprT(stderr, q->fset); + if ( q->incomplete ) fprintf(stderr, " (incomplete)"); + fprintf(stderr, "\n"); +#endif + if ( !q->incomplete ) + { + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return set_dup( q->fset ); + } + } + } + p->lock[k] = TRUE; /* This rule is busy */ + } + + a = b = empty; + + if ( p->jtype == EndRule ) + { + if (p->halt ) /* don't want FOLLOW here? */ /* unless MR10 hoisting */ + { + p->lock[k] = FALSE; + set_orel(k, rk); /* indicate this k value needed */ + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return empty; + } + if (! MR_AmbSourceSearch) FoPush(p->rname, k); /* Attempting FOLLOW */ + if ( p->p1 == NULL ) set_orel((TokenInd!=NULL?TokenInd[EofToken]:EofToken), &a);/* if no FOLLOW assume EOF */ +#ifdef DBG_LL1 + fprintf(stderr, "-->FOLLOW(%s,%d)\n", p->rname,k); +#endif + } + + if ( p->p1 != NULL ) { +/* MR14 */ if (p->guess) { +/* MR14 */ if (p->guess_analysis_point == NULL) { +/* MR14 */ Node * guess_point; +/* MR14 */ guess_point=(Node *)analysis_point(p); +/* MR14 */ if (guess_point == (Node *)p) { +/* MR14 */ guess_point=p->p1; +/* MR14 */ } +/* MR14 */ p->guess_analysis_point=guess_point; +/* MR14 */ } +/* MR14 */ REACH(p->guess_analysis_point, k, rk, a); + } else { + REACH(p->p1, k, rk, a); + } + } + + /* C a c h e R e s u l t s */ + + if ( p->jtype == RuleBlk && p->end->halt && ! MR_AmbSourceSearch) /* can save FIRST set? */ + { + CacheEntry *q = newCacheEntry( Fkey(p->rname,'i',k) ); + /*fprintf(stderr, "Caching %s FIRST %d\n", p->rname, k);*/ + hash_add(Fcache, Fkey(p->rname,'i',k), (Entry *)q); + q->fset = set_dup( a ); + q->rk = set_dup( *rk ); + } + + if ( p->jtype == EndRule && + !p->halt && /* MR11 was using cache even with halt set */ + ! MR_AmbSourceSearch) /* just completed FOLLOW? */ + { + /* Cache Follow set */ + CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'o',k)); + if ( q==NULL ) + { + q = newCacheEntry( Fkey(p->rname,'o',k) ); + hash_add(Fcache, Fkey(p->rname,'o',k), (Entry *)q); + } + /*fprintf(stderr, "Caching %s FOLLOW %d\n", p->rname, k);*/ + if ( set_nil(a) && !q->incomplete ) + { + /* Don't ever save a nil set as complete. + * Turn it into an eof set. + */ + set_orel(EofToken, &a); + } + set_orin(&(q->fset), a); + FoPop( k ); + if ( FoTOS[k] == NULL && Cycles[k] != NULL ) ResolveFoCycles(k); +#ifdef DBG_LL1 + fprintf(stderr, "saving FOLLOW(%s,%d):", p->rname, k); + s_fprT(stderr, q->fset); + if ( q->incomplete ) fprintf(stderr, " (incomplete)"); + fprintf(stderr, "\n"); +#endif + } + + if (p->jtype != RuleBlk && p->p2 != NULL && /* MR14 */ ! p->guess) { + REACH(p->p2, k, rk, b); + } + + if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || + p->jtype==aPlusBlk || p->jtype==EndRule ) + p->lock[k] = FALSE; /* unlock node */ + + set_orin(&a, b); + set_free(b); + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return a; +} + +set +#ifdef __USE_PROTOS +rRuleRef( RuleRefNode *p, int k, set *rk_out ) +#else +rRuleRef( p, k, rk_out ) +RuleRefNode *p; +int k; +set *rk_out; +#endif +{ + set rk; + Junction *r; + int k2; + set a, rk2, b; + int save_halt; + RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text); + require(p!=NULL, "rRuleRef: NULL node"); + require(p->ntype==nRuleRef, "rRuleRef: not rule ref"); + +#ifdef DBG_LL1 + fprintf(stderr, "rRuleRef: %s\n", p->text); +#endif + + if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p); + + if ( q == NULL ) + { + warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line ); + REACH(p->next, k, rk_out, a); + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return a; + } + rk2 = empty; + +/* MR9 Problems with rule references in guarded predicates */ +/* MR9 Perhaps can use hash table to find rule ? */ + +/* MR9 */ if (RulePtr == NULL) { +/* MR9 */ fatalFL(eMsg2("Rule %s uses rule %s via RulePtr before it has been initialized", +/* MR9 */ p->rname,q->str),FileStr[p->file],p->line); +/* MR9 */ }; + + r = RulePtr[q->rulenum]; + if ( r->lock[k] ) + { + errNoFL( eMsg2("infinite left-recursion to rule %s from rule %s", + r->rname, p->rname) ); + + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + + return empty; + } + + save_halt = r->end->halt; + r->end->halt = TRUE; /* don't let reach fall off end of rule here */ + rk = empty; + REACH(r, k, &rk, a); + r->end->halt = save_halt; + while ( !set_nil(rk) ) { + k2 = set_int(rk); /* MR11 this messes up the ambiguity search routine */ + set_rm(k2, rk); + REACH(p->next, k2, &rk2, b); /* MR11 by changing the value of k */ + set_orin(&a, b); + set_free(b); + } + set_free(rk); /* this has no members, but free it's memory */ + set_orin(rk_out, rk2); /* remember what we couldn't do */ + set_free(rk2); + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return a; +} + +/* + * Return FIRST sub k ( token_node ) + * + * TJP 10/11/93 modified this so that token nodes that are actually + * ranges (T1..T2) work. + */ +set +#ifdef __USE_PROTOS +rToken( TokNode *p, int k, set *rk ) +#else +rToken( p, k, rk ) +TokNode *p; +int k; +set *rk; +#endif +{ + set a; + + require(p!=NULL, "rToken: NULL node"); + require(p->ntype==nToken, "rToken: not token node"); + +#ifdef DBG_LL1 + fprintf(stderr, "rToken: %s\n", (TokenString(p->token)!=NULL)?TokenString(p->token): + ExprString(p->token)); +#endif + + + if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p); + + if (MR_AmbSourceSearch && (k-1) == 0) { + + set localConstrain; + set intersection; + + localConstrain=fset[maxk-k+1]; + + if (! set_nil(p->tset)) { + intersection=set_and(localConstrain,p->tset); + if (! set_nil(intersection)) { + MR_backTraceReport(); + }; + set_free(intersection); + } else { + if (set_el( (unsigned) p->token,localConstrain)) { + MR_backTraceReport(); + } + }; + }; + + if ( k-1 == 0 ) { + + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + + if ( !set_nil(p->tset) ) { + return set_dup(p->tset); + } else { + return set_of(p->token); + }; + } + + REACH(p->next, k-1, rk, a); + + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + + return a; +} + +set +#ifdef __USE_PROTOS +rAction( ActionNode *p, int k, set *rk ) +#else +rAction( p, k, rk ) +ActionNode *p; +int k; +set *rk; +#endif +{ + set a; + + require(p!=NULL, "rJunc: NULL node"); + require(p->ntype==nAction, "rJunc: not action"); + +/* MR11 */ if (p->is_predicate && p->ampersandPred != NULL) { +/* MR11 */ Predicate *pred=p->ampersandPred; +/* MR11 */ if (k <= pred->k) { +/* MR11 */ REACH(p->guardNodes,k,rk,a); +/* MR11 */ return a; +/* MR11 */ }; +/* MR11 */ }; + + /* it might be a good idea when doing an MR_AmbSourceSearch + to *not* look behind predicates under some circumstances + we'll look into that later + */ + + REACH(p->next, k, rk, a); /* ignore actions */ + return a; +} + + /* A m b i g u i t y R e s o l u t i o n */ + + +void +#ifdef __USE_PROTOS +dumpAmbigMsg( set *fset, FILE *f, int want_nls ) +#else +dumpAmbigMsg( fset, f, want_nls ) +set *fset; +FILE *f; +int want_nls; +#endif +{ + int i; + + set copy; /* MR11 */ + + if ( want_nls ) fprintf(f, "\n\t"); + else fprintf(f, " "); + + for (i=1; i<=CLL_k; i++) + { + copy=set_dup(fset[i]); /* MR11 */ + + if ( i>1 ) + { + if ( !want_nls ) fprintf(f, ", "); + } + if ( set_deg(copy) > 3 && elevel == 1 ) + { + int e,m; + fprintf(f, "{"); + for (m=1; m<=3; m++) + { + e=set_int(copy); + fprintf(f, " %s", TerminalString(e)); + set_rm(e, copy); + } + fprintf(f, " ... }"); + } + else s_fprT(f, copy); + if ( want_nls ) fprintf(f, "\n\t"); + set_free(copy); + } + fprintf(f, "\n"); + +} + +static void +#ifdef __USE_PROTOS +verify_context(Predicate *predicate) +#else +verify_context(predicate) +Predicate *predicate; +#endif +{ + if ( predicate == NULL ) return; + + if ( predicate->expr == PRED_OR_LIST || + predicate->expr == PRED_AND_LIST ) + { + verify_context(predicate->down); + verify_context(predicate->right); /* MR10 */ + return; + } + + if ( !predicate->source->ctxwarned && predicate->source->guardpred==NULL && + ((predicate->k > 1 && + !is_single_tuple(predicate->tcontext)) || + ( predicate->k == 1 && + set_deg(predicate->scontext[1])>1 )) ) + { + +/* MR9 Suppress annoying messages caused by our own clever(?) fix */ + + fprintf(stderr, ErrHdr, FileStr[predicate->source->file], + predicate->source->line); + fprintf(stderr, " warning: predicate applied for >1 lookahead %d-sequences\n", predicate->k); + fprintf(stderr, ErrHdr, FileStr[predicate->source->file], + predicate->source->line); + fprintf(stderr, " predicate text: \"%s\"\n", + (predicate->expr == NULL ? "(null)" : predicate->expr) ); + fprintf(stderr, ErrHdr, FileStr[predicate->source->file], + predicate->source->line); + fprintf(stderr, " You may only want one lookahead %d-sequence to apply\n", predicate->k); + fprintf(stderr, ErrHdr, FileStr[predicate->source->file], + predicate->source->line); + fprintf(stderr, " Try using a context guard '(...)? =>'\n"); + predicate->source->ctxwarned = 1; + } + verify_context(predicate->right); /* MR10 */ +} + +/* + * If delta is the set of ambiguous lookahead sequences, then make sure that + * the predicate(s) for productions alt1,alt2 cover the sequences in delta. + * + * For example, + * a : <>? (A B|A C) + * | b + * ; + * b : <>? A B + * | A C + * ; + * + * This should give a warning that (A C) predicts both productions and alt2 + * does not have a predicate in the production that generates (A C). + * + * The warning detection is simple. Let delta = LOOK(alt1) intersection LOOK(alt2). + * Now, if ( delta set-difference context(predicates-for-alt1) != empty then + * alt1 does not "cover" all ambiguous sequences. + * + * If ambig is nonempty, then ambig in LL(k) sense -> use tree info; else use fset + * info. Actually, sets are used only if k=1 for this grammar. + */ +static void +#ifdef __USE_PROTOS +ensure_predicates_cover_ambiguous_lookahead_sequences + ( Junction *alt1, Junction *alt2, char *sub, Tree *ambig ) +#else +ensure_predicates_cover_ambiguous_lookahead_sequences( alt1, alt2, sub, ambig ) +Junction *alt1; +Junction *alt2; +char *sub; +Tree *ambig; +#endif +{ + if ( !ParseWithPredicates ) return; + + if ( ambig!=NULL ) + { + Tree *non_covered = NULL; + if ( alt1->predicate!=NULL ) + non_covered = tdif(ambig, alt1->predicate, alt1->fset, alt2->fset); + if ( (non_covered!=NULL || alt1->predicate==NULL) && WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity", + alt1->altnum, sub); + if ( alt1->predicate!=NULL && non_covered!=NULL ) + { + fprintf(stderr, " upon"); + preorder(non_covered); + } + else if ( alt1->predicate==NULL ) + { + fprintf(stderr, " upon"); + preorder(ambig->down); + } + fprintf(stderr, "\n"); + } + Tfree(non_covered); + non_covered = NULL; + if ( alt2->predicate!=NULL ) + non_covered = tdif(ambig, alt2->predicate, alt1->fset, alt2->fset); + if ( (non_covered!=NULL || alt2->predicate==NULL) && WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt2->file], alt2->line); + fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity", + alt2->altnum, sub); + if ( alt2->predicate!=NULL && non_covered!=NULL ) + { + fprintf(stderr, " upon"); + preorder(non_covered); + } + else if ( alt2->predicate==NULL ) + { + fprintf(stderr, " upon"); + preorder(ambig->down); + } + fprintf(stderr, "\n"); + } + Tfree(non_covered); + } + else if ( !set_nil(alt1->fset[1]) ) + { + set delta, non_covered; + delta = set_and(alt1->fset[1], alt2->fset[1]); + non_covered = set_dif(delta, covered_set(alt1->predicate)); + if ( set_deg(non_covered)>0 && WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity", + alt1->altnum, sub); + if ( alt1->predicate!=NULL ) + { + fprintf(stderr, " upon "); + s_fprT(stderr, non_covered); + } + fprintf(stderr, "\n"); + } + set_free( non_covered ); + non_covered = set_dif(delta, covered_set(alt2->predicate)); + if ( set_deg(non_covered)>0 && WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt2->file], alt2->line); + fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity", + alt2->altnum, sub); + if ( alt2->predicate!=NULL ) + { + fprintf(stderr, " upon "); + s_fprT(stderr, non_covered); + } + fprintf(stderr, "\n"); + } + set_free( non_covered ); + set_free( delta ); + } + else fatal_internal("productions have no lookahead in predicate checking routine"); +} + +#ifdef __USE_PROTOS +void MR_doPredicatesHelp(int inGuessBlock,Junction *alt1,Junction *alt2,int jtype,char *sub) +#else +void MR_doPredicatesHelp(inGuessBlock,alt1,alt2,jtype,sub) + int inGuessBlock; + Junction *alt1; + Junction *alt2; + int jtype; + char *sub; +#endif +{ + Predicate *p1; + Predicate *p2; + + Junction *parentRule=MR_nameToRuleBlk(alt1->rname); + + if (inGuessBlock && WarningLevel <= 1) return; + + /* let antlr give the usual error message */ + + if (alt1->predicate == NULL && alt2->predicate == NULL) return; + + if ( (jtype == RuleBlk || jtype == aSubBlk) + && (alt1->predicate == NULL && alt2->predicate != NULL)) { + fprintf(stderr, ErrHdr, FileStr[parentRule->file],parentRule->line); + fprintf(stderr," warning: alt %d line %d and alt %d line %d of %s\n%s%s%s", + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + sub, + " These alts have ambig lookahead sequences resolved by a predicate for\n", + " the second choice. The second choice may not be reachable.\n", + " You may want to use a complementary predicate or rearrange the alts\n" + ); + return; + }; + + /* first do the easy comparison. then do the hard one */ + + if (MR_comparePredicates(alt1->predicate,alt2->predicate)) { + + if (jtype == aLoopBegin || jtype == aPlusBlk ) { + + /* I'm not sure this code is reachable. + Predicates following a (...)+ or (...)* block are probably + considered validation predicates and therefore not + participate in the predication expression + */ + + fprintf(stderr, ErrHdr,FileStr[parentRule->file],parentRule->line); + fprintf(stderr," warning: %s of %s in rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s", + "the predicates used to disambiguate optional/exit paths of ", + sub, + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " are identical and have no resolving power\n"); + } else { + fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line); + fprintf(stderr," warning: %s rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s", + "the predicates used to disambiguate", + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " are identical and have no resolving power\n"); + }; + } else { + p1=predicate_dup_without_context(alt1->predicate); + p1=MR_unfold(p1); + MR_clearPredEntry(p1); + MR_simplifyInverted(p1,0); + p1=MR_predSimplifyALL(p1); + p2=predicate_dup_without_context(alt2->predicate); + p2=MR_unfold(p2); + MR_clearPredEntry(p2); + MR_simplifyInverted(p2,0); + p2=MR_predSimplifyALL(p2); + if (MR_comparePredicates(p1,p2)) { + if (jtype == aLoopBegin || jtype == aPlusBlk ) { + fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line); + fprintf(stderr," warning: %s of %s in rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s", + "the predicates used to disambiguate optional/exit paths of ", + sub, + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " are identical when compared without context and may have no\n", + " resolving power for some lookahead sequences.\n"); + } else { + fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line); + fprintf(stderr," warning: %s rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s", + "the predicates used to disambiguate", + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " are identical when compared without context and may have no\n", + " resolving power for some lookahead sequences.\n"); + }; + if (InfoP) { + fprintf(output,"\n#if 0\n\n"); + fprintf(output,"The following predicates are identical when compared without\n"); + fprintf(output," lookahead context information. For some ambiguous lookahead\n"); + fprintf(output," sequences they may not have any power to resolve the ambiguity.\n"); + fprintf(output,"\n"); + + fprintf(output,"Choice 1: %s alt %d line %d file %s\n\n", + MR_ruleNamePlusOffset( (Node *) alt1), + alt1->altnum, + alt1->line, + FileStr[alt1->file]); + fprintf(output," The original predicate for choice 1 with available context information:\n\n"); + MR_dumpPred1(2,alt1->predicate,1); + fprintf(output," The predicate for choice 1 after expansion (but without context information):\n\n"); + MR_dumpPred1(2,p1,0); + if (p1 == NULL) { + Predicate *phelp; + fprintf(output," The predicate for choice 1 after expansion (but before simplification)\n\n"); + phelp=predicate_dup_without_context(alt1->predicate); + phelp=MR_unfold(phelp); + MR_clearPredEntry(phelp); + MR_simplifyInverted(phelp,0); + phelp=MR_predSimplifyALLX(phelp,1); + MR_dumpPred1(2,phelp,0); + predicate_free(phelp); + }; + fprintf(output,"\n"); + + fprintf(output,"Choice 2: %s alt %d line %d file %s\n\n", + MR_ruleNamePlusOffset( (Node *) alt2), + alt2->altnum, + alt2->line, + FileStr[alt2->file]); + fprintf(output," The original predicate for choice 2 with available context information:\n\n"); + MR_dumpPred1(1,alt2->predicate,1); + fprintf(output," The predicate for choice 2 after expansion (but without context information):\n\n"); + MR_dumpPred1(1,p2,0); + if (p2 == NULL) { + Predicate *phelp; + fprintf(output," The predicate for choice 2 after expansion (but before simplification)\n\n"); + phelp=predicate_dup_without_context(alt2->predicate); + phelp=MR_unfold(phelp); + MR_clearPredEntry(phelp); + MR_simplifyInverted(phelp,0); + phelp=MR_predSimplifyALLX(phelp,1); + MR_dumpPred1(2,phelp,0); + predicate_free(phelp); + }; + fprintf(output,"\n#endif\n"); + }; + } else if (MR_secondPredicateUnreachable(p1,p2)) { + if (jtype == aLoopBegin || jtype == aPlusBlk ) { + fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line); + fprintf(stderr," warning: %s of %s in rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s", + "the predicate used to disambiguate the first choice of the optional/exit paths of ", + sub, + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " appears to \"cover\" the second predicate when compared without context.\n", + " The second predicate may have no resolving power for some lookahead sequences.\n"); + } else { + fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line); + fprintf(stderr," warning: %s rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s", + "the predicate used to disambiguate the first choice of", + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " appears to \"cover\" the second predicate when compared without context.\n", + " The second predicate may have no resolving power for some lookahead sequences.\n"); + }; + if (InfoP) { + fprintf(output,"\n#if 0\n\n"); + fprintf(output,"The first predicate appears to \"cover\" the second predicate when they\n"); + fprintf(output," are compared without lookahead context information. For some ambiguous\n"); + fprintf(output," lookahead sequences the second predicate may not have any power to\n"); + fprintf(output," resolve the ambiguity.\n"); + fprintf(output,"\n"); + fprintf(output,"Choice 1: %s alt %d line %d file %s\n\n", + MR_ruleNamePlusOffset( (Node *) alt1), + alt1->altnum, + alt1->line, + FileStr[alt1->file]); + fprintf(output," The original predicate for choice 1 with available context information:\n\n"); + MR_dumpPred1(2,alt1->predicate,1); + fprintf(output," The predicate for choice 1 after expansion (but without context information):\n\n"); + MR_dumpPred1(2,p1,0); + if (p1 == NULL) { + Predicate *phelp; + fprintf(output," The predicate for choice 1 after expansion (but before simplification)\n\n"); + phelp=predicate_dup_without_context(alt1->predicate); + phelp=MR_unfold(phelp); + MR_clearPredEntry(phelp); + MR_simplifyInverted(phelp,0); + phelp=MR_predSimplifyALLX(phelp,1); + MR_dumpPred1(2,phelp,0); + predicate_free(phelp); + }; + fprintf(output,"\n"); + + fprintf(output,"Choice 2: %s alt %d line %d file %s\n\n", + MR_ruleNamePlusOffset( (Node *) alt2), + alt2->altnum, + alt2->line, + FileStr[alt2->file]); + fprintf(output," The original predicate for choice 2 with available context information:\n\n"); + MR_dumpPred1(1,alt2->predicate,1); + fprintf(output," The predicate for choice 2 after expansion (but without context information):\n\n"); + MR_dumpPred1(1,p2,0); + if (p2 == NULL) { + Predicate *phelp; + fprintf(output," The predicate for choice 2 after expansion (but before simplification)\n\n"); + phelp=predicate_dup_without_context(alt2->predicate); + phelp=MR_unfold(phelp); + MR_clearPredEntry(phelp); + MR_simplifyInverted(phelp,0); + phelp=MR_predSimplifyALLX(phelp,1); + MR_dumpPred1(2,phelp,0); + predicate_free(phelp); + }; + fprintf(output,"\n#endif\n"); + }; + }; + predicate_free(p1); + predicate_free(p2); + }; +} + +static int totalOverflow=0; /* MR9 */ + +void +#ifdef __USE_PROTOS +HandleAmbiguity( Junction *block, Junction *alt1, Junction *alt2, int jtype ) +#else +HandleAmbiguity( block, alt1, alt2, jtype ) +Junction *block; +Junction *alt1; +Junction *alt2; +int jtype; +#endif +{ + unsigned **ftbl; + set *fset, b; + int i, numAmbig,n2; + Tree *ambig=NULL, *t, *u; + char *sub = ""; + long n; + int thisOverflow=0; /* MR9 */ + long set_deg_value; /* MR10 */ + long threshhold; /* MR10 */ + + require(block!=NULL, "NULL block"); + require(block->ntype==nJunction, "invalid block"); + + /* These sets are used to constrain LL_k set, but are made CLL_k long anyway */ + fset = (set *) calloc(CLL_k+1, sizeof(set)); + require(fset!=NULL, "cannot allocate fset"); + ftbl = (unsigned **) calloc(CLL_k+1, sizeof(unsigned *)); + require(ftbl!=NULL, "cannot allocate ftbl"); + + /* create constraint table and count number of possible ambiguities (use<=LL_k) */ + for (n=1,i=1; i<=CLL_k; i++) + { + b = set_and(alt1->fset[i], alt2->fset[i]); +/* MR9 */ set_deg_value = set_deg(b); +/* MR10 */ if (n > 0) { +/* MR10 */ threshhold = LONG_MAX / n; +/* MR10 */ if (set_deg_value <= threshhold) { +/* MR10 */ n *= set_deg_value; +/* MR10 */ } else { +/* MR10 */ n=LONG_MAX; +/* MR9 */ if (totalOverflow == 0) { +#if 0 + /* MR10 comment this out because it just makes users worry */ + +/* MR9 */ warnNoFL("Overflow in computing number of possible ambiguities in HandleAmbiguity\n"); +#endif +/* MR9 */ }; +/* MR9 */ thisOverflow++; +/* MR9 */ totalOverflow++; +/* MR9 */ }; +/* MR10 */ } else { +/* MR10 */ n *= set_deg_value; +/* MR9 */ }; + fset[i] = set_dup(b); + ftbl[i] = set_pdq(b); + set_free(b); + } + + switch ( jtype ) + { + case aSubBlk: sub = "of (..) "; break; + case aOptBlk: sub = "of {..} "; break; + case aLoopBegin: sub = "of (..)* "; break; + case aLoopBlk: sub = "of (..)* "; break; + case aPlusBlk: sub = "of (..)+ "; break; + case RuleBlk: sub = "of the rule itself "; break; + default : sub = ""; break; + } + + /* If the block is marked as a compressed lookahead only block, then + * simply return; ambiguity warning is given only at warning level 2. + */ + if ( block->approx>0 ) + { + if ( ParseWithPredicates ) + { + if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */ + if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */ + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed"); + alt1->predicate=MR_predSimplifyALL(alt1->predicate); + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed"); + alt2->predicate=MR_predSimplifyALL(alt2->predicate); + + MR_doPredicatesHelp(0,alt1,alt2,jtype,sub); + + if ( HoistPredicateContext + && (alt1->predicate!=NULL||alt2->predicate!=NULL) ) + { + verify_context(alt1->predicate); + verify_context(alt2->predicate); + } + + if ( HoistPredicateContext + && (alt1->predicate!=NULL||alt2->predicate!=NULL) + && WarningLevel>1 ) + ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig); + } + + if ( WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + if ( jtype == aLoopBegin || jtype == aPlusBlk ) + fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub); + else + fprintf(stderr, " warning(approx): alts %d and %d %sambiguous upon", + alt1->altnum, alt2->altnum, sub); + dumpAmbigMsg(fset, stderr, 0); + MR_traceAmbSource(fset,alt1,alt2); + } + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + + /* if all sets have degree 1 for k=1 permutation; + * don't bother doing full LL(k) analysis. + * (This "if" block handles the LL(1) case) + */ + + n2 = 0; + for (i=1; ifset[i])+set_deg(alt2->fset[i]); + + /* here STARTS the special case in which the lookahead sets for alt1 and alt2 + all have degree 1 for kp1)!=NULL ) + { + if ( WarningLevel==1 ) + { + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + if ( jtype == aLoopBegin || jtype == aPlusBlk ) + fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub); + else + fprintf(stderr, " warning: alts %d and %d %sambiguous upon", + alt1->altnum, alt2->altnum, sub); + dumpAmbigMsg(fset, stderr, 0); + MR_traceAmbSource(fset,alt1,alt2); + } + + ambig = NULL; + if ( LL_k>1 ) ambig = make_tree_from_sets(alt1->fset, alt2->fset); + if ( ParseWithPredicates ) + { + if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */ + if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */ + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed"); + alt1->predicate=MR_predSimplifyALL(alt1->predicate); + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed"); + alt2->predicate=MR_predSimplifyALL(alt2->predicate); + + MR_doPredicatesHelp(0,alt1,alt2,jtype,sub); + + if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) ) + { + verify_context(alt1->predicate); + verify_context(alt2->predicate); + } + if (HoistPredicateContext&&(alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1) + ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig); + if ( WarningLevel == 1 && + (alt1->predicate!=NULL||alt2->predicate!=NULL)) + { + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + Tfree(ambig); + return; + } + } +/* end TJP (10/24/93) */ + + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + if ( jtype == aLoopBegin || jtype == aPlusBlk ) + fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub); + else + fprintf(stderr, " warning: alts %d and %d %sambiguous upon", + alt1->altnum, alt2->altnum, sub); + if ( elevel == 3 && LL_k>1 ) + { + preorder(ambig); + fprintf(stderr, "\n"); + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + Tfree(ambig); + return; + }; + + Tfree(ambig); + dumpAmbigMsg(fset, stderr, 0); + + /* because this is a special case in which both alt1 and alt2 have + lookahead sets of degree 1 for kaltnum; + CurAmbigAlt2 = alt2->altnum; + CurAmbigbtype = sub; + CurAmbigfile = alt1->file; + CurAmbigline = alt1->line; + + /* Don't do full LL(n) analysis if (...)? block because the block, + by definition, defies LL(n) analysis. + If guess (...)? block and ambiguous then don't remove anything from + 2nd alt to resolve ambig. + Want to predict with LL sup 1 ( n ) decision not LL(n) if guess block + since it is much cheaper than LL(n). LL sup 1 ( n ) "covers" the LL(n) + lookahead information. + + Note: LL(n) context cannot be computed for semantic predicates when + followed by (..)?. + + If (..)? then we scream "AAAHHHH! No LL(n) analysis will help" + + Is 'ambig' always defined if we enter this if? I hope so + because the 'ensure...()' func references it. TJP Nov 1993. + */ + + /* THM MR30: Instead of using first_item_is_guss_block we use + first_item_is_guess_block_extra which will look inside a + loop block for a guess block. In other words ( (...)? )*. + It there is an ambiguity in this circumstance then we suppress + the normal methods of resolving ambiguities. + */ + + if ( first_item_is_guess_block_extra((Junction *)alt1->p1)!=NULL ) + { + if ( ParseWithPredicates ) + { + if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */ + if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */ + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed"); + alt1->predicate=MR_predSimplifyALL(alt1->predicate); + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed"); + alt2->predicate=MR_predSimplifyALL(alt2->predicate); + + MR_doPredicatesHelp(1,alt1,alt2,jtype,sub); + + if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) ) + { + verify_context(alt1->predicate); + verify_context(alt2->predicate); + } + if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1 ) + ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig); + if ( WarningLevel==1 && + (alt1->predicate!=NULL||alt2->predicate!=NULL)) + { + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + } + + if ( WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + if ( jtype == aLoopBegin || jtype == aPlusBlk ) + fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub); + else + fprintf(stderr, " warning: alts %d and %d %sambiguous upon", + alt1->altnum, alt2->altnum, sub); + dumpAmbigMsg(fset, stderr, 0); + MR_traceAmbSource(fset,alt1,alt2); + } + + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + + /* Not resolved with (..)? block. Do full LL(n) analysis */ + + /* ambig is the set of k-tuples truly in common between alt 1 and alt 2 */ + /* MR11 VerifyAmbig once used fset destructively */ + + ambig = VerifyAmbig(alt1, alt2, ftbl, fset, &t, &u, &numAmbig); + + /* are all things in intersection really ambigs? */ + + if (thisOverflow || numAmbig < n ) /* MR9 */ + { + Tree *v; + + /* remove ambig permutation from 2nd alternative to resolve ambig; + * We want to compute the set of artificial tuples, arising from + * LL sup 1 (n) compression, that collide with real tuples from the + * 2nd alternative. This is the set of "special case" tuples that + * the LL sup 1 (n) decision template maps incorrectly. + */ + + /* when generating code in genExpr() it does + * + * if ( genExprSets(j->fset) && !genExprTree(j->ftree)) {... + * + * Sooooo the j->ftree is the tree of alt2 + * after removal of conflicts, not alt1 ! + */ + + if ( ambig!=NULL ) + { + /* at the top of ambig is an ALT node */ + + for (v=ambig->down; v!=NULL; v=v->right) + { + u = trm_perm(u, v); /* remove v FROM u */ + } +/* fprintf(stderr, "after rm alt2:"); preorder(u); fprintf(stderr, "\n");*/ + } + Tfree( t ); + alt1->ftree = tappend(alt1->ftree, u); + alt1->ftree = tleft_factor(alt1->ftree); + } + + if ( ambig==NULL ) + { + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + + ambig = tleft_factor(ambig); + +/* TJP: + * At this point, we surely have an LL(k) ambiguity. Check for predicates + */ + if ( ParseWithPredicates ) + { + if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */ + if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */ + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed"); + alt1->predicate=MR_predSimplifyALL(alt1->predicate); + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed"); + alt2->predicate=MR_predSimplifyALL(alt2->predicate); + + MR_doPredicatesHelp(0,alt1,alt2,jtype,sub); + + if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) ) + { + verify_context(alt1->predicate); + verify_context(alt2->predicate); + } + if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1 ) + ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig); + if ( WarningLevel==1 && + (alt1->predicate!=NULL||alt2->predicate!=NULL)) + { + + /* We found at least one pred for at least one of the alts; + * If warnings are low, just return. + */ + + Tfree(ambig); + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + /* else we're gonna give a warning */ + } +/* end TJP addition */ + + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + if ( jtype == aLoopBegin || jtype == aPlusBlk ) + fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub); + else + fprintf(stderr, " warning: alts %d and %d %sambiguous upon", + alt1->altnum, alt2->altnum, sub); + if ( elevel == 3 ) + { + preorder(ambig->down); /* <===== k>1 ambiguity message data */ + fprintf(stderr, "\n"); + } else { + MR_skipped_e3_report=1; + dumpAmbigMsg(fset, stderr, 0); + }; + + MR_traceAmbSourceK(ambig,alt1,alt2); /* <====== k>1 ambiguity aid */ + + Tfree(ambig); + + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); +} + +/* Don't analyze alpha block of (alpha)?beta; if (alpha)? then analyze + * Return the 1st node of the beta block if present else return j. + */ +Junction * +#ifdef __USE_PROTOS +analysis_point( Junction *j ) +#else +analysis_point( j ) +Junction *j; +#endif +{ + Junction *gblock; + + /* MR13b When there was an action/predicate preceding a guess block + the guess block became invisible at the analysis_point. + + first_item_is_guess_block accepts any kind of node, + despite the fact that the formal is a junction. But + I don't want to have to change it all over the place + until I know it works. + */ + + if ( j->ntype != nJunction && j->ntype != nAction) return j; + + gblock = first_item_is_guess_block((Junction *)j); + + if ( gblock!=NULL ) + { + Junction *past = gblock->end; + Junction *p; + require(past!=NULL, "analysis_point: no end block on (...)? block"); + + for (p=(Junction *)past->p1; p!=NULL; ) + { + if ( p->ntype==nAction ) + { + p=(Junction *)((ActionNode *)p)->next; + continue; + } + if ( p->ntype!=nJunction ) + { + past->alpha_beta_guess_end=1; /* MR14 */ + return (Junction *)past->p1; + } + if ( p->jtype==EndBlk || p->jtype==EndRule ) + { + return j; + } +/* MR6 */ +/* MR6 A guess block is of the form "(alpha)? beta" or "(alpha)?". */ +/* MR6 When beta is omitted (second form) this means "(alpha)? alpha". */ +/* MR6 The program does not store another copy of alpha in this case. */ +/* MR6 During analysis when the program needs to know what follows the */ +/* MR6 guess clause. It calls this routine. */ +/* MR6 */ +/* MR6 If it is of the form "(alpha)? beta" it returns a pointer to beta.*/ +/* MR6 */ +/* MR6 If it is of the form "(alpha)?" it returns a pointer to the guess */ +/* MR6 block itself thereby reusing the junction tree. */ +/* MR6 */ +/* MR6 It works by searching the "next in sequence" chain (skipping actions) */ +/* MR6 searching for a RuleRef or Token node. (Those are the only 4 kinds */ +/* MR6 of nodes: Junctions, RuleRef, Token, and Action.) */ +/* MR6 */ +/* MR6 This won't work for the special case "(alpha)? ()" because it has no */ +/* MR6 rule references or token nodes. It eventually encounters a */ +/* MR6 junction of type EndBlk or EndRule and says to its caller: nothing */ +/* MR6 more here to analyze - must be of the form "(alpha)?". */ +/* MR6 */ +/* MR6 In the case of "(alpha)? ()" it should return a pointer to "()" */ +/* MR6 */ +/* MR6 I think. */ +/* MR6 */ + if ( p->jtype!=Generic) { /* MR6 */ + past->alpha_beta_guess_end=1; /* MR14 */ + return (Junction *)past->p1; /* MR6 */ + }; /* MR6 */ + p=(Junction *)p->p1; + } + } + return j; +} + +set +#ifdef __USE_PROTOS +First( Junction *j, int k, int jtype, int *max_k ) +#else +First( j, k, jtype, max_k ) +Junction *j; +int k; +int jtype; +int *max_k; +#endif +{ + Junction *alt1, *alt2; + set a, rk, fCurBlk; + int savek; + int p1, p2; + + int save_maintainBackTrace; + + require(j->ntype==nJunction, "First: non junction passed"); + + /* C o m p u t e F I R S T s e t w i t h k l o o k a h e a d */ + fCurBlk = rk = empty; + for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2 ) + { + Junction * p = NULL; + Junction * p1junction = NULL; + p = analysis_point((Junction *)alt1->p1); + p1junction = (Junction *) (alt1->p1); +#if 0 + if (p != p1junction) { + fprintf(stdout,"Analysis point for #%d is #%d", p1junction->seq, p->seq); /* debug */ + } +#endif + REACH(p, k, &rk, alt1->fset[k]); + require(set_nil(rk), "rk != nil"); + set_free(rk); + set_orin(&fCurBlk, alt1->fset[k]); + } + + /* D e t e c t A m b i g u i t i e s */ + *max_k = 1; + for (p1=1,alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2, p1++) + { + for (p2=1,alt2=(Junction *)alt1->p2; alt2!=NULL; alt2 = (Junction *)alt2->p2, p2++) + { + savek = k; + a = set_and(alt1->fset[k], alt2->fset[k]); + while ( !set_nil(a) ) + { + /* if we have hit the max k requested, just give warning */ + if ( j->approx==k ) { + } + + if ( k==CLL_k ) + { +#ifdef NOT_USED +*** int save_LL_k = LL_k; +*** int save_CLL_k = CLL_k; +*** /* Get new LL_k from interactive feature if enabled */ +*** if ( AImode ) +*** AmbiguityDialog(j, jtype, alt1, alt2, &CLL_k, &LL_k); +#endif + *max_k = CLL_k; + save_maintainBackTrace=MR_MaintainBackTrace; + if (AlphaBetaTrace) MR_MaintainBackTrace=0; + HandleAmbiguity(j, alt1, alt2, jtype); + MR_MaintainBackTrace=save_maintainBackTrace; + break; + } + else + { + Junction *p = analysis_point((Junction *)alt1->p1); + Junction *q = analysis_point((Junction *)alt2->p1); + k++; /* attempt ambig alts again with more lookahead */ + + REACH(p, k, &rk, alt1->fset[k]); + require(set_nil(rk), "rk != nil"); + REACH(q, k, &rk, alt2->fset[k]); + require(set_nil(rk), "rk != nil"); + set_free(a); + a = set_and(alt1->fset[k], alt2->fset[k]); + if ( k > *max_k ) *max_k = k; + } + } + set_free(a); + k = savek; + } + } + + return fCurBlk; +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/fset2.c b/Tools/Source/TianoTools/Pccts/antlr/fset2.c new file mode 100644 index 0000000000..7f686a53d5 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/fset2.c @@ -0,0 +1,2250 @@ +/* + * fset2.c + * + * Compute FIRST sets for full LL(k) + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "pcctscfg.h" +#include + +#ifdef PCCTS_USE_STDARG +#include +#else +#include +#endif + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" + +/* ick! globals. Used by permute() to track which elements of a set have been used */ + +static int *findex; +set *fset; /* MR11 make global */ +static unsigned **ftbl; +static set *constrain; /* pts into fset. constrains tToken() to 'constrain' */ +int ConstrainSearch; +int maxk; /* set to initial k upon tree construction request */ + /* MR11 make global */ +static Tree *FreeList = NULL; + +#ifdef __USE_PROTOS +static int tmember_of_context(Tree *, Predicate *); +#else +static int tmember_of_context(); +#endif + +#if TREE_DEBUG +set set_of_tnodes_in_use; +int stop_on_tnode_seq_number=(-1); /* (-1) to disable */ +#endif + +/* Do root + * Then each sibling + */ + +void +#ifdef __USE_PROTOS +preorder( Tree *tree ) +#else +preorder( tree ) +Tree *tree; +#endif +{ + if ( tree == NULL ) return; + if ( tree->down != NULL ) fprintf(stderr, " ("); + if ( tree->token == ALT ) fprintf(stderr, " ALT"); + else fprintf(stderr, " %s", TerminalString(tree->token)); + if ( tree->token==EpToken ) fprintf(stderr, "(%d)", tree->v.rk); + preorder(tree->down); + if ( tree->down != NULL ) fprintf(stderr, " )"); + preorder(tree->right); +} + +#ifdef __USE_PROTOS +int MR_tree_matches_constraints(int k,set * constrain,Tree *t) +#else +int MR_tree_matches_constraints(k,constrain,t) + int k; + set * constrain; + Tree * t; +#endif +{ + int i; + Tree *u; + + if (k == 0) return 1; + + /* for testing guard predicates: if the guard tree is shorter + than the constraint then it is a match. The reason is that + a guard of (A B) should be equivalent to a guard of (A B . . .) + where "." matches every token. Thus a match which runs out + of tree before constraint is a match. + */ + + if (t == NULL) return 1; + require (set_deg(constrain[0]) == 1, + "MR_tree_matches_constraints: set_deg != 1"); + i=set_int(constrain[0]); + if (t->token != i) return 0; + if (k-1 == 0) return 1; + for (u=t->down; u != NULL; u=u->right) { + if (MR_tree_matches_constraints(k-1,&constrain[1],u)) { + return 1; + }; + }; + return 0; +} + +/* check the depth of each primary sibling to see that it is exactly + * k deep. e.g.; + * + * ALT + * | + * A ------- B + * | | + * C -- D E + * + * Remove all branches <= k deep. + * + * Added by TJP 9-23-92 to make the LL(k) constraint mechanism to work. + */ + +static int pruneCount=0; +static int prunePeak=200; + +Tree * +#ifdef __USE_PROTOS +prune( Tree *t, int k ) +#else +prune( t, k ) +Tree *t; +int k; +#endif +{ + pruneCount++; + if (pruneCount > prunePeak+100) { + prunePeak=pruneCount; +#if 0 +*** fprintf(stderr,"pruneCount=%d\n",pruneCount); +/*** preorder(t); ***/ +*** fprintf(stderr,"\n",pruneCount); +#endif + }; + if ( t == NULL ) { + pruneCount--; + return NULL; + }; + if ( t->token == ALT ) fatal_internal("prune: ALT node in FIRST tree"); + if ( t->right!=NULL ) t->right = prune(t->right, k); + if ( k>1 ) + { + if ( t->down!=NULL ) t->down = prune(t->down, k-1); + if ( t->down == NULL ) + { + Tree *r = t->right; + t->right = NULL; + Tfree(t); + pruneCount--; + return r; + } + } + pruneCount--; + return t; +} + +/* build a tree (root child1 child2 ... NULL) */ +#ifdef PCCTS_USE_STDARG +Tree *tmake(Tree *root, ...) +#else +Tree *tmake(va_alist) +va_dcl +#endif +{ + Tree *w; + va_list ap; + Tree *child, *sibling=NULL, *tail=NULL; +#ifndef PCCTS_USE_STDARG + Tree *root; +#endif + +#ifdef PCCTS_USE_STDARG + va_start(ap, root); +#else + va_start(ap); + root = va_arg(ap, Tree *); +#endif + child = va_arg(ap, Tree *); + while ( child != NULL ) + { +#ifdef DUM + /* added "find end of child" thing TJP March 1994 */ + for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */ +#else + w = child; +#endif + + if ( sibling == NULL ) {sibling = child; tail = w;} + else {tail->right = child; tail = w;} + child = va_arg(ap, Tree *); + } + + /* was "root->down = sibling;" */ + if ( root==NULL ) root = sibling; + else root->down = sibling; + + va_end(ap); + return root; +} + +Tree * +#ifdef __USE_PROTOS +tnode( int tok ) +#else +tnode( tok ) +int tok; +#endif +{ + Tree *p, *newblk; + static int n=0; + + if ( FreeList == NULL ) + { + /*fprintf(stderr, "tnode: %d more nodes\n", TreeBlockAllocSize);*/ + if ( TreeResourceLimit > 0 ) + { + if ( (n+TreeBlockAllocSize) >= TreeResourceLimit ) + { + fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline); + fprintf(stderr, " hit analysis resource limit while analyzing alts %d and %d %s\n", + CurAmbigAlt1, + CurAmbigAlt2, + CurAmbigbtype); + exit(PCCTS_EXIT_FAILURE); + } + } + newblk = (Tree *)calloc(TreeBlockAllocSize, sizeof(Tree)); + if ( newblk == NULL ) + { + fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline); + fprintf(stderr, " out of memory while analyzing alts %d and %d %s\n", + CurAmbigAlt1, + CurAmbigAlt2, + CurAmbigbtype); + exit(PCCTS_EXIT_FAILURE); + } + n += TreeBlockAllocSize; + for (p=newblk; p<&(newblk[TreeBlockAllocSize]); p++) + { + p->right = FreeList; /* add all new Tree nodes to Free List */ + FreeList = p; + } + } + p = FreeList; + FreeList = FreeList->right; /* remove a tree node */ + p->right = NULL; /* zero out ptrs */ + p->down = NULL; + p->token = tok; + + TnodesAllocated++; /* MR10 */ + TnodesInUse++; /* MR10 */ + if (TnodesInUse > TnodesPeak) TnodesPeak=TnodesInUse; /* MR10 */ + +#ifdef TREE_DEBUG + require(!p->in_use, "tnode: node in use!"); + p->in_use = 1; + p->seq=TnodesAllocated; + set_orel( (unsigned) TnodesAllocated,&set_of_tnodes_in_use); + if (stop_on_tnode_seq_number == p->seq) { + fprintf(stderr,"\n*** just allocated tnode #%d ***\n", + stop_on_tnode_seq_number); + }; +#endif + return p; +} + +static Tree * +#ifdef __USE_PROTOS +eofnode( int k ) +#else +eofnode( k ) +int k; +#endif +{ + Tree *t=NULL; + int i; + + for (i=1; i<=k; i++) + { + t = tmake(tnode((TokenInd!=NULL?TokenInd[EofToken]:EofToken)), t, NULL); + } + return t; +} + + + +void +#ifdef __USE_PROTOS +_Tfree( Tree *t ) +#else +_Tfree( t ) +Tree *t; +#endif +{ + if ( t!=NULL ) + { +#ifdef TREE_DEBUG + if (t->seq == stop_on_tnode_seq_number) { + fprintf(stderr,"\n*** just freed tnode #%d ***\n",t->seq); + }; + require(t->in_use, "_Tfree: node not in use!"); + t->in_use = 0; + set_rm( (unsigned) t->seq,set_of_tnodes_in_use); +#endif + t->right = FreeList; + FreeList = t; + TnodesInUse--; /* MR10 */ + } +} + +/* tree duplicate */ +Tree * +#ifdef __USE_PROTOS +tdup( Tree *t ) +#else +tdup( t ) +Tree *t; +#endif +{ + Tree *u; + + if ( t == NULL ) return NULL; + u = tnode(t->token); + u->v.rk = t->v.rk; + u->right = tdup(t->right); + u->down = tdup(t->down); + return u; +} + +/* tree duplicate (assume tree is a chain downwards) */ +Tree * +#ifdef __USE_PROTOS +tdup_chain( Tree *t ) +#else +tdup_chain( t ) +Tree *t; +#endif +{ + Tree *u; + + if ( t == NULL ) return NULL; + u = tnode(t->token); + u->v.rk = t->v.rk; + u->down = tdup(t->down); + return u; +} + +Tree * +#ifdef __USE_PROTOS +tappend( Tree *t, Tree *u ) +#else +tappend( t, u ) +Tree *t; +Tree *u; +#endif +{ + Tree *w; + +/*** fprintf(stderr, "tappend("); + *** preorder(t); fprintf(stderr, ","); + *** preorder(u); fprintf(stderr, " )\n"); +*/ + if ( t == NULL ) return u; + if ( t->token == ALT && t->right == NULL ) return tappend(t->down, u); + for (w=t; w->right!=NULL; w=w->right) {;} + w->right = u; + return t; +} + +/* dealloc all nodes in a tree */ +void +#ifdef __USE_PROTOS +Tfree( Tree *t ) +#else +Tfree( t ) +Tree *t; +#endif +{ + if ( t == NULL ) return; + Tfree( t->down ); + Tfree( t->right ); + _Tfree( t ); +} + +/* find all children (alts) of t that require remaining_k nodes to be LL_k + * tokens long. + * + * t-->o + * | + * a1--a2--...--an <-- LL(1) tokens + * | | | + * b1 b2 ... bn <-- LL(2) tokens + * | | | + * . . . + * . . . + * z1 z2 ... zn <-- LL(LL_k) tokens + * + * We look for all [Ep] needing remaining_k nodes and replace with u. + * u is not destroyed or actually used by the tree (a copy is made). + */ +Tree * +#ifdef __USE_PROTOS +tlink( Tree *t, Tree *u, int remaining_k ) +#else +tlink( t, u, remaining_k ) +Tree *t; +Tree *u; +int remaining_k; +#endif +{ + Tree *p; + require(remaining_k!=0, "tlink: bad tree"); + + if ( t==NULL ) return NULL; + /*fprintf(stderr, "tlink: u is:"); preorder(u); fprintf(stderr, "\n");*/ + if ( t->token == EpToken && t->v.rk == remaining_k ) + { + require(t->down==NULL, "tlink: invalid tree"); + if ( u == NULL ) { +/* MR10 */ Tree *tt=t->right; +/* MR10 */ _Tfree(t); +/* MR10 */ return tt; + }; + p = tdup( u ); + p->right = t->right; + _Tfree( t ); + return p; + } + t->down = tlink(t->down, u, remaining_k); + t->right = tlink(t->right, u, remaining_k); + return t; +} + +/* remove as many ALT nodes as possible while still maintaining semantics */ +Tree * +#ifdef __USE_PROTOS +tshrink( Tree *t ) +#else +tshrink( t ) +Tree *t; +#endif +{ + if ( t == NULL ) return NULL; + t->down = tshrink( t->down ); + t->right = tshrink( t->right ); + if ( t->down == NULL ) + { + if ( t->token == ALT ) + { + Tree *u = t->right; + _Tfree(t); + return u; /* remove useless alts */ + } + return t; + } + + /* (? (ALT (? ...)) s) ==> (? (? ...) s) where s = sibling, ? = match any */ + if ( t->token == ALT && t->down->right == NULL) + { + Tree *u = t->down; + u->right = t->right; + _Tfree( t ); + return u; + } + /* (? (A (ALT t)) s) ==> (? (A t) s) where A is a token; s,t siblings */ + if ( t->token != ALT && t->down->token == ALT && t->down->right == NULL ) + { + Tree *u = t->down->down; + _Tfree( t->down ); + t->down = u; + return t; + } + return t; +} + +Tree * +#ifdef __USE_PROTOS +tflatten( Tree *t ) +#else +tflatten( t ) +Tree *t; +#endif +{ + if ( t == NULL ) return NULL; + t->down = tflatten( t->down ); + t->right = tflatten( t->right ); + if ( t->down == NULL ) return t; + + if ( t->token == ALT ) + { + Tree *u; + /* find tail of children */ + for (u=t->down; u->right!=NULL; u=u->right) {;} + u->right = t->right; + u = t->down; + _Tfree( t ); + return u; + } + return t; +} + +Tree * +#ifdef __USE_PROTOS +tJunc( Junction *p, int k, set *rk ) +#else +tJunc( p, k, rk ) +Junction *p; +int k; +set *rk; +#endif +{ + Tree *t=NULL, *u=NULL; + Junction *alt; + Tree *tail=NULL, *r; + +#ifdef DBG_TRAV + fprintf(stderr, "tJunc(%d): %s in rule %s\n", k, + decodeJType[p->jtype], ((Junction *)p)->rname); +#endif + +/* MR14 */ if (AlphaBetaTrace && p->alpha_beta_guess_end) { +/* MR14 */ warnFL( +/* MR14 */ "not possible to compute follow set for alpha in an \"(alpha)? beta\" block. ", +/* MR14 */ FileStr[p->file],p->line); +/* MR14 */ MR_alphaBetaTraceReport(); +/* MR14 */ }; + +/* MR14 */ if (p->alpha_beta_guess_end) { +/* MR14 */ return NULL; +/* MR14 */ } + + if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || + p->jtype==aPlusBlk || p->jtype==aSubBlk || p->jtype==aOptBlk ) + { + if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) { + require(p->lock!=NULL, "rJunc: lock array is NULL"); + if ( p->lock[k] ) return NULL; + p->lock[k] = TRUE; + } + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + + TRAV(p->p1, k, rk, tail); + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + + if ( p->jtype==RuleBlk ) {p->lock[k] = FALSE; return tail;} + r = tmake(tnode(ALT), tail, NULL); + for (alt=(Junction *)p->p2; alt!=NULL; alt = (Junction *)alt->p2) + { + /* if this is one of the added optional alts for (...)+ then break */ + if ( alt->ignore ) break; + + if ( tail==NULL ) {TRAV(alt->p1, k, rk, tail); r->down = tail;} + else + { +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + + TRAV(alt->p1, k, rk, tail->right); + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + if ( tail->right != NULL ) tail = tail->right; + } + } + if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) p->lock[k] = FALSE; +#ifdef DBG_TREES + fprintf(stderr, "blk(%s) returns:",((Junction *)p)->rname); preorder(r); fprintf(stderr, "\n"); +#endif + if ( r->down == NULL ) {_Tfree(r); return NULL;} + return r; + } + + if ( p->jtype==EndRule ) + { + if ( p->halt ) /* don't want FOLLOW here? */ + { +/**** if ( ContextGuardTRAV ) return NULL; ****/ + set_orel( (unsigned) k, rk); /* indicate this k value needed */ /* MR10 cast */ + t = tnode(EpToken); + t->v.rk = k; + return t; + } + require(p->lock!=NULL, "rJunc: lock array is NULL"); + if ( p->lock[k] ) return NULL; + /* if no FOLLOW assume k EOF's */ + if ( p->p1 == NULL ) return eofnode(k); + p->lock[k] = TRUE; + } + +/* MR14 */ if (p->p1 != NULL && p->guess && p->guess_analysis_point == NULL) { +/* MR14 */ Node * guess_point; +/* MR14 */ guess_point=(Node *)analysis_point(p); +/* MR14 */ if (guess_point == (Node *)p) { +/* MR14 */ guess_point=p->p1; +/* MR14 */ } +/* MR14 */ p->guess_analysis_point=guess_point; +/* MR14 */ } + + if ( p->p2 == NULL ) + { + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + +/* M14 */ if (p->guess_analysis_point != NULL) { +/* M14 */ TRAV(p->guess_analysis_point, k, rk,t); +/* M14 */ } else { + TRAV(p->p1, k, rk,t); +/* M14 */ } + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + + if ( p->jtype==EndRule ) p->lock[k]=FALSE; + return t; + } + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + +/* M14 */ if (p->guess_analysis_point != NULL) { +/* M14 */ TRAV(p->guess_analysis_point, k, rk,t); +/* M14 */ } else { + TRAV(p->p1, k, rk,t); +/* M14 */ } + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + + if ( p->jtype!=RuleBlk && /* MR14 */ !p->guess) TRAV(p->p2, k, rk, u); + + if ( p->jtype==EndRule ) p->lock[k] = FALSE;/* unlock node */ + + if ( t==NULL ) return tmake(tnode(ALT), u, NULL); + return tmake(tnode(ALT), t, u, NULL); +} + +Tree * +#ifdef __USE_PROTOS +tRuleRef( RuleRefNode *p, int k, set *rk_out ) +#else +tRuleRef( p, k, rk_out ) +RuleRefNode *p; +int k; +set *rk_out; +#endif +{ + int k2; + Tree *t=NULL, *u=NULL; + Junction *r; + set rk, rk2; + int save_halt; + RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text); + +#ifdef DBG_TRAV + fprintf(stderr, "tRuleRef: %s\n", p->text); +#endif + if ( q == NULL ) + { + TRAV(p->next, k, rk_out, t);/* ignore undefined rules */ + return t; + } + rk = rk2 = empty; + if (RulePtr == NULL) fatal("RulePtr==NULL"); + r = RulePtr[q->rulenum]; + if ( r->lock[k] ) return NULL; + save_halt = r->end->halt; + r->end->halt = TRUE; /* don't let reach fall off end of rule here */ + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + + TRAV(r, k, &rk, t); + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + + r->end->halt = save_halt; +#ifdef DBG_TREES + fprintf(stderr, "after ruleref, t is:"); preorder(t); fprintf(stderr, "\n"); +#endif + t = tshrink( t ); + while ( !set_nil(rk) ) { /* any k left to do? if so, link onto tree */ + k2 = set_int(rk); + set_rm(k2, rk); + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + + TRAV(p->next, k2, &rk2, u); + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + + t = tlink(t, u, k2); /* any alts missing k2 toks, add u onto end */ + Tfree(u); /* MR10 */ + } + set_free(rk); /* rk is empty, but free it's memory */ + set_orin(rk_out, rk2); /* remember what we couldn't do */ + set_free(rk2); + return t; +} + +Tree * +#ifdef __USE_PROTOS +tToken( TokNode *p, int k, set *rk ) +#else +tToken( p, k, rk ) +TokNode *p; +int k; +set *rk; +#endif +{ + Tree *t=NULL, *tset=NULL, *u; + + if (ConstrainSearch) { + if (MR_AmbSourceSearch) { + require(constrain>=fset&&constrain<=&(fset[CLL_k]),"tToken: constrain is not a valid set"); + } else { + require(constrain>=fset&&constrain<=&(fset[LL_k]),"tToken: constrain is not a valid set"); + }; + constrain = &fset[maxk-k+1]; + } + +#ifdef DBG_TRAV + fprintf(stderr, "tToken(%d): %s\n", k, TerminalString(p->token)); + if ( ConstrainSearch ) { + fprintf(stderr, "constrain is:"); s_fprT(stderr, *constrain); fprintf(stderr, "\n"); + } +#endif + + /* is it a meta token (set of tokens)? */ + + if ( !set_nil(p->tset) ) + { + unsigned e=0; + set a; + Tree *n, *tail = NULL; + + if ( ConstrainSearch ) { + a = set_and(p->tset, *constrain); + if (set_nil(a)) { /* MR10 */ + set_free(a); /* MR11 */ + return NULL; /* MR10 */ + }; /* MR10 */ + } else { + a = set_dup(p->tset); + }; + + for (; !set_nil(a); set_rm(e, a)) + { + e = set_int(a); + n = tnode(e); + if ( tset==NULL ) { tset = n; tail = n; } + else { tail->right = n; tail = n; } + } + set_free( a ); + } + else if ( ConstrainSearch && !set_el(p->token, *constrain) ) + { +/* fprintf(stderr, "ignoring token %s(%d)\n", TerminalString(p->token), + k);*/ + return NULL; + } + else { + tset = tnode( p->token ); + }; + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (k == 1) { +/* MR10 */ MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR13 */ if (MR_SuppressSearch) { +/* MR13 */ MR_suppressSearchReport(); +/* MR13 */ } else { +/* MR10 */ MR_backTraceReport(); +/* MR13 */ }; +/* MR10 */ MR_pointerStackPop(&MR_BackTraceStack); +/* MR11 */ Tfree(tset); +/* MR11 */ return NULL; +/* MR10 */ }; +/* MR10 */ }; + + if ( k == 1 ) return tset; + + if (MR_MaintainBackTrace) { + MR_pointerStackPush(&MR_BackTraceStack,p); + }; + + TRAV(p->next, k-1, rk, t); + + if (MR_MaintainBackTrace) { + Tfree(t); + Tfree(tset); + MR_pointerStackPop(&MR_BackTraceStack); + return NULL; + }; + + /* here, we are positive that, at least, this tree will not contribute + * to the LL(2) tree since it will be too shallow, IF t==NULL. + * If doing a context guard walk, then don't prune. + */ + if ( t == NULL && !ContextGuardTRAV ) /* tree will be too shallow */ + { + if ( tset!=NULL ) Tfree( tset ); + return NULL; + } +#ifdef DBG_TREES + fprintf(stderr, "tToken(%d)->next:",k); preorder(t); fprintf(stderr, "\n"); +#endif + + /* if single token root, then just make new tree and return */ + /* MR10 - set_nil(p->tset) isn't a good test because of ConstraintSearch */ + + if (tset->right == NULL) return tmake(tset, t, NULL); /* MR10 */ + + /* here we must make a copy of t as a child of each element of the tset; + * e.g., "T1..T3 A" would yield ( nil ( T1 A ) ( T2 A ) ( T3 A ) ) + */ + for (u=tset; u!=NULL; u=u->right) + { + /* make a copy of t and hook it onto bottom of u */ + u->down = tdup(t); + } + Tfree( t ); +#ifdef DBG_TREES + fprintf(stderr, "range is:"); preorder(tset); fprintf(stderr, "\n"); +#endif + return tset; +} + +Tree * +#ifdef __USE_PROTOS +tAction( ActionNode *p, int k, set *rk ) +#else +tAction( p, k, rk ) +ActionNode *p; +int k; +set *rk; +#endif +{ + Tree *t=NULL; + set *save_fset=NULL; + int i; + + /* fprintf(stderr, "tAction\n"); */ + +/* An MR_SuppressSearch is looking for things that can be + reached even when the predicate is false. + + There are three kinds of predicates: + plain: r1: <

>? r2 + guarded: r1: (A)? => <

>? r2 + ampersand style: r1: (A)? && <

>? r2 + + Of the three kinds of predicates, only a guard predicate + has things which are reachable even when the predicate + is false. To be reachable the constraint must *not* + match the guard. + +*/ + + if (p->is_predicate && MR_SuppressSearch) { + + Predicate *pred=p->guardpred; + + if (pred == NULL) { + t=NULL; + goto EXIT; + }; + constrain = &fset[maxk-k+1]; + if (pred->k == 1) { + set dif; + dif=set_dif(*constrain,pred->scontext[1]); + if (set_nil(dif)) { + set_free(dif); + t=NULL; + goto EXIT; + }; + set_free(dif); + } else { + if (MR_tree_matches_constraints(k,constrain,pred->tcontext)) { + t=NULL; + goto EXIT; + }; + } + }; + + /* The ampersand predicate differs from the + other predicates because its first set + is a subset of the first set behind the predicate + + r1: (A)? && <

>? r2 ; + r2: A | B; + + In this case first[1] of r1 is A, even + though first[1] of r2 is {A B}. + */ + + if (p->is_predicate && p->ampersandPred != NULL) { + + Predicate *pred=p->ampersandPred; + Tree *tAND; + Tree *tset; + + if (k <= pred->k) { + if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p); + TRAV(p->guardNodes,k,rk,t); + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return t; + } else { + require (k>1,"tAction for ampersandpred: k <= 1"); + if (ConstrainSearch) { + if (MR_AmbSourceSearch) { + require(constrain>=fset&&constrain<=&(fset[CLL_k]), + "tToken: constrain is not a valid set"); + } else { + require(constrain>=fset&&constrain<=&(fset[LL_k]), + "tToken: constrain is not a valid set"); + }; + save_fset=(set *) calloc (CLL_k+1,sizeof(set)); + require (save_fset != NULL,"tAction save_fset alloc"); + for (i=1; i <= CLL_k ; i++) { + save_fset[i]=set_dup(fset[i]); + }; + if (pred->k == 1) { + constrain = &fset[maxk-k+1]; + set_andin(constrain,pred->scontext[1]); + if (set_nil(*constrain)) { + t=NULL; + goto EXIT; + }; + } else { + constrain = &fset[maxk-k+1]; + if (! MR_tree_matches_constraints(pred->k,constrain,pred->tcontext)) { + t=NULL; + goto EXIT; + }; /* end loop on i */ + }; /* end loop on pred scontext/tcontext */ + }; /* end if on k > pred->k */ + }; /* end if on constrain search */ + + TRAV(p->next,k,rk,t); + + if (t != NULL) { + t=tshrink(t); + t=tflatten(t); + t=tleft_factor(t); + if (pred->tcontext != NULL) { + tAND=MR_computeTreeAND(t,pred->tcontext); + } else { + tset=MR_make_tree_from_set(pred->scontext[1]); + tAND=MR_computeTreeAND(t,tset); + Tfree(tset); + }; + Tfree(t); + t=tAND; + }; + goto EXIT; + + }; /* end if on ampersand predicate */ + + TRAV(p->next,k,rk,t); + +EXIT: + if (save_fset != NULL) { + for (i=1 ; i <= CLL_k ; i++) { + set_free(fset[i]); + fset[i]=save_fset[i]; + }; + free ( (char *) save_fset); + }; + return t; +} + +/* see if e exists in s as a possible input permutation (e is always a chain) */ + +int +#ifdef __USE_PROTOS +tmember( Tree *e, Tree *s ) +#else +tmember( e, s ) +Tree *e; +Tree *s; +#endif +{ + if ( e==NULL||s==NULL ) return 0; +/** fprintf(stderr, "tmember("); +*** preorder(e); fprintf(stderr, ","); +*** preorder(s); fprintf(stderr, " )\n"); +*/ + if ( s->token == ALT && s->right == NULL ) return tmember(e, s->down); + if ( e->token!=s->token ) + { + if ( s->right==NULL ) return 0; + return tmember(e, s->right); + } + if ( e->down==NULL && s->down == NULL ) return 1; + if ( tmember(e->down, s->down) ) return 1; + if ( s->right==NULL ) return 0; + return tmember(e, s->right); +} + +/* see if e exists in s as a possible input permutation (e is always a chain); + * Only check s to the depth of e. In other words, 'e' can be a shorter + * sequence than s. + */ +int +#ifdef __USE_PROTOS +tmember_constrained( Tree *e, Tree *s) +#else +tmember_constrained( e, s ) +Tree *e; +Tree *s; +#endif +{ + if ( e==NULL||s==NULL ) return 0; +/** fprintf(stderr, "tmember_constrained("); +*** preorder(e); fprintf(stderr, ","); +*** preorder(s); fprintf(stderr, " )\n"); +**/ + if ( s->token == ALT && s->right == NULL ) + return tmember_constrained(e, s->down); + if ( e->token!=s->token ) + { + if ( s->right==NULL ) return 0; + return tmember_constrained(e, s->right); + } + if ( e->down == NULL ) return 1; /* if s is matched to depth of e return */ + if ( tmember_constrained(e->down, s->down) ) return 1; + if ( s->right==NULL ) return 0; + return tmember_constrained(e, s->right); +} + +/* combine (? (A t) ... (A u) ...) into (? (A t u)) */ +Tree * +#ifdef __USE_PROTOS +tleft_factor( Tree *t ) +#else +tleft_factor( t ) +Tree *t; +#endif +{ + Tree *u, *v, *trail, *w; + + /* left-factor what is at this level */ + if ( t == NULL ) return NULL; + for (u=t; u!=NULL; u=u->right) + { + trail = u; + v=u->right; + while ( v!=NULL ) + { + if ( u->token == v->token ) + { + if ( u->down!=NULL ) + { + for (w=u->down; w->right!=NULL; w=w->right) {;} + w->right = v->down; /* link children together */ + } + else u->down = v->down; + trail->right = v->right; /* unlink factored node */ + _Tfree( v ); + v = trail->right; + } + else {trail = v; v=v->right;} + } + } + /* left-factor what is below */ + for (u=t; u!=NULL; u=u->right) u->down = tleft_factor( u->down ); + return t; +} + +/* remove the permutation p from t if present */ +Tree * +#ifdef __USE_PROTOS +trm_perm( Tree *t, Tree *p ) +#else +trm_perm( t, p ) +Tree *t; +Tree *p; +#endif +{ + /* + fprintf(stderr, "trm_perm("); + preorder(t); fprintf(stderr, ","); + preorder(p); fprintf(stderr, " )\n"); + */ + if ( t == NULL || p == NULL ) return NULL; + if ( t->token == ALT ) + { + t->down = trm_perm(t->down, p); + if ( t->down == NULL ) /* nothing left below, rm cur node */ + { + Tree *u = t->right; + _Tfree( t ); + return trm_perm(u, p); + } + t->right = trm_perm(t->right, p); /* look for more instances of p */ + return t; + } + if ( p->token != t->token ) /* not found, try a sibling */ + { + t->right = trm_perm(t->right, p); + return t; + } + t->down = trm_perm(t->down, p->down); + if ( t->down == NULL ) /* nothing left below, rm cur node */ + { + Tree *u = t->right; + _Tfree( t ); + return trm_perm(u, p); + } + t->right = trm_perm(t->right, p); /* look for more instances of p */ + return t; +} + +/* add the permutation 'perm' to the LL_k sets in 'fset' */ +void +#ifdef __USE_PROTOS +tcvt( set *fset, Tree *perm ) +#else +tcvt( fset, perm ) +set *fset; +Tree *perm; +#endif +{ + if ( perm==NULL ) return; + set_orel(perm->token, fset); + tcvt(fset+1, perm->down); +} + +/* for each element of ftbl[k], make it the root of a tree with permute(ftbl[k+1]) + * as a child. + */ +Tree * +#ifdef __USE_PROTOS +permute( int k, int max_k ) +#else +permute( k, max_k ) +int k, max_k; +#endif +{ + Tree *t, *u; + + if ( k>max_k ) return NULL; + if ( ftbl[k][findex[k]] == nil ) return NULL; + t = permute(k+1, max_k); + if ( t==NULL&&k maxk will have to change. + */ +Tree * +#ifdef __USE_PROTOS +VerifyAmbig( Junction *alt1, Junction *alt2, unsigned **ft, set *fs, Tree **t, Tree **u, int *numAmbig ) +#else +VerifyAmbig( alt1, alt2, ft, fs, t, u, numAmbig ) +Junction *alt1; +Junction *alt2; +unsigned **ft; +set *fs; +Tree **t; +Tree **u; +int *numAmbig; +#endif +{ + set rk; + Tree *perm, *ambig=NULL; + Junction *p; + int k; + int tnodes_at_start=TnodesAllocated; + int tnodes_at_end; + int tnodes_used; + set *save_fs; + int j; + + save_fs=(set *) calloc(CLL_k+1,sizeof(set)); + require(save_fs != NULL,"save_fs calloc"); + + for (j=0; j <= CLL_k ; j++) save_fs[j]=set_dup(fs[j]); + + maxk = LL_k; /* NOTE: for now, we look for LL_k */ + ftbl = ft; + fset = fs; + constrain = &(fset[1]); + findex = (int *) calloc(LL_k+1, sizeof(int)); + if ( findex == NULL ) + { + fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline); + fprintf(stderr, " out of memory while analyzing alts %d and %d of %s\n", + CurAmbigAlt1, + CurAmbigAlt2, + CurAmbigbtype); + exit(PCCTS_EXIT_FAILURE); + } + for (k=1; k<=LL_k; k++) findex[k] = 0; + + rk = empty; + ConstrainSearch = 1; /* consider only tokens in ambig sets */ + + p = analysis_point((Junction *)alt1->p1); + TRAV(p, LL_k, &rk, *t); + *t = tshrink( *t ); + *t = tflatten( *t ); + *t = tleft_factor( *t ); /* MR10 */ + *t = prune(*t, LL_k); + *t = tleft_factor( *t ); + +/*** fprintf(stderr, "after shrink&flatten&prune&left_factor:"); preorder(*t); fprintf(stderr, "\n");*/ + if ( *t == NULL ) + { +/*** fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/ + Tfree( *t ); /* kill if impossible to have ambig */ + *t = NULL; + } + + p = analysis_point((Junction *)alt2->p1); + + TRAV(p, LL_k, &rk, *u); + *u = tshrink( *u ); + *u = tflatten( *u ); + *t = tleft_factor( *t ); /* MR10 */ + *u = prune(*u, LL_k); + *u = tleft_factor( *u ); +/* fprintf(stderr, "after shrink&flatten&prune&lfactor:"); preorder(*u); fprintf(stderr, "\n");*/ + if ( *u == NULL ) + { +/* fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/ + Tfree( *u ); + *u = NULL; + } + + for (k=1; k<=LL_k; k++) set_clr( fs[k] ); + + ambig = tnode(ALT); + k = 0; + if ( *t!=NULL && *u!=NULL ) + { + while ( (perm=permute(1,LL_k))!=NULL ) + { +/* fprintf(stderr, "chk perm:"); preorder(perm); fprintf(stderr, "\n");*/ + if ( tmember(perm, *t) && tmember(perm, *u) ) + { +/* fprintf(stderr, "ambig upon"); preorder(perm); fprintf(stderr, "\n");*/ + + k++; + perm->right = ambig->down; + ambig->down = perm; + tcvt(&(fs[1]), perm); + } + else Tfree( perm ); + } + } + + for (j=0; j <= CLL_k ; j++) fs[j]=save_fs[j]; + free( (char *) save_fs); + + tnodes_at_end=TnodesAllocated; + tnodes_used=tnodes_at_end - tnodes_at_start; + + if (TnodesReportThreshold > 0 && tnodes_used > TnodesReportThreshold) { + fprintf(stdout,"There were %d tuples whose ambiguity could not be resolved by full lookahead\n",k); + fprintf(stdout,"There were %d tnodes created to resolve ambiguity between:\n\n",tnodes_used); + fprintf(stdout," Choice 1: %s line %d file %s\n", + MR_ruleNamePlusOffset( (Node *) alt1),alt1->line,FileStr[alt1->file]); + fprintf(stdout," Choice 2: %s line %d file %s\n", + MR_ruleNamePlusOffset( (Node *) alt2),alt2->line,FileStr[alt2->file]); + for (j=1; j <= CLL_k ; j++) { + fprintf(stdout,"\n Intersection of lookahead[%d] sets:\n",j); + MR_dumpTokenSet(stdout,2,fs[j]); + }; + fprintf(stdout,"\n"); + }; + + *numAmbig = k; + if ( ambig->down == NULL ) {_Tfree(ambig); ambig = NULL;} + free( (char *)findex ); +/* fprintf(stderr, "final ambig:"); preorder(ambig); fprintf(stderr, "\n");*/ + return ambig; +} + +static Tree * +#ifdef __USE_PROTOS +bottom_of_chain( Tree *t ) +#else +bottom_of_chain( t ) +Tree *t; +#endif +{ + if ( t==NULL ) return NULL; + for (; t->down != NULL; t=t->down) {;} + return t; +} + +/* + * Make a tree from k sets where the degree of the first k-1 sets is 1. + */ +Tree * +#ifdef __USE_PROTOS +make_tree_from_sets( set *fset1, set *fset2 ) +#else +make_tree_from_sets( fset1, fset2 ) +set *fset1; +set *fset2; +#endif +{ + set inter; + int i; + Tree *t=NULL, *n, *u; + unsigned *p,*q; + require(LL_k>1, "make_tree_from_sets: LL_k must be > 1"); + + /* do the degree 1 sets first */ + for (i=1; i<=LL_k-1; i++) + { + inter = set_and(fset1[i], fset2[i]); + require(set_deg(inter)==1, "invalid set to tree conversion"); + n = tnode(set_int(inter)); + if (t==NULL) t=n; else tmake(t, n, NULL); + set_free(inter); + } + + /* now add the chain of tokens at depth k */ + u = bottom_of_chain(t); + inter = set_and(fset1[LL_k], fset2[LL_k]); + if ( (q=p=set_pdq(inter)) == NULL ) fatal_internal("Can't alloc space for set_pdq"); + /* first one is linked to bottom, then others are sibling linked */ + n = tnode(*p++); + u->down = n; + u = u->down; + while ( *p != nil ) + { + n = tnode(*p); + u->right = n; + u = u->right; + p++; + } + free((char *)q); + + return t; +} + +/* create and return the tree of lookahead k-sequences that are in t, but not + * in the context of predicates in predicate list p. + */ +Tree * +#ifdef __USE_PROTOS +tdif( Tree *ambig_tuples, Predicate *p, set *fset1, set *fset2 ) +#else +tdif( ambig_tuples, p, fset1, fset2 ) +Tree *ambig_tuples; +Predicate *p; +set *fset1; +set *fset2; +#endif +{ + unsigned **ft; + Tree *dif=NULL; + Tree *perm; + set b; + int i,k; + + if ( p == NULL ) return tdup(ambig_tuples); + + ft = (unsigned **) calloc(CLL_k+1, sizeof(unsigned *)); + require(ft!=NULL, "cannot allocate ft"); + for (i=1; i<=CLL_k; i++) + { + b = set_and(fset1[i], fset2[i]); + ft[i] = set_pdq(b); + set_free(b); + } + findex = (int *) calloc(LL_k+1, sizeof(int)); + if ( findex == NULL ) + { + fatal_internal("out of memory in tdif while checking predicates"); + } + for (k=1; k<=LL_k; k++) findex[k] = 0; + +#ifdef DBG_TRAV + fprintf(stderr, "tdif_%d[", p->k); + preorder(ambig_tuples); + fprintf(stderr, ","); + preorder(p->tcontext); + fprintf(stderr, "] ="); +#endif + + ftbl = ft; + while ( (perm=permute(1,p->k))!=NULL ) + { +#ifdef DBG_TRAV + fprintf(stderr, "test perm:"); preorder(perm); fprintf(stderr, "\n"); +#endif + if ( tmember_constrained(perm, ambig_tuples) && + !tmember_of_context(perm, p) ) + { +#ifdef DBG_TRAV + fprintf(stderr, "satisfied upon"); preorder(perm); fprintf(stderr, "\n"); +#endif + k++; + if ( dif==NULL ) dif = perm; + else + { + perm->right = dif; + dif = perm; + } + } + else Tfree( perm ); + } + +#ifdef DBG_TRAV + preorder(dif); + fprintf(stderr, "\n"); +#endif + + for (i=1; i<=CLL_k; i++) free( (char *)ft[i] ); + free((char *)ft); + free((char *)findex); + + return dif; +} + +/* is lookahead sequence t a member of any context tree for any + * predicate in p? + */ +static int +#ifdef __USE_PROTOS +tmember_of_context( Tree *t, Predicate *p ) +#else +tmember_of_context( t, p ) +Tree *t; +Predicate *p; +#endif +{ + for (; p!=NULL; p=p->right) + { + if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) + return tmember_of_context(t, p->down); + if ( tmember_constrained(t, p->tcontext) ) return 1; + if ( tmember_of_context(t, p->down) ) return 1; + } + return 0; +} + +int +#ifdef __USE_PROTOS +is_single_tuple( Tree *t ) +#else +is_single_tuple( t ) +Tree *t; +#endif +{ + if ( t == NULL ) return 0; + if ( t->right != NULL ) return 0; + if ( t->down == NULL ) return 1; + return is_single_tuple(t->down); +} + + +/* MR10 Check that a context guard contains only allowed things */ +/* MR10 (mainly token references). */ + +#ifdef __USE_PROTOS +int contextGuardOK(Node *p,int h,int *hmax) +#else +int contextGuardOK(p,h,hmax) + Node *p; + int h; + int *hmax; +#endif +{ + Junction *j; + TokNode *tn; + + if (p == NULL) return 1; + if (p->ntype == nToken) { + h++; + if (h > *hmax) *hmax=h; + tn=(TokNode *)p; + if (tn->el_label != NULL) { + warnFL(eMsg1("a label (\"%s\") for a context guard element is meaningless",tn->el_label), + FileStr[p->file],p->line); + }; + return contextGuardOK( ( (TokNode *) p)->next,h,hmax); + } else if (p->ntype == nAction) { + goto Fail; + } else if (p->ntype == nRuleRef) { + goto Fail; + } else { + require (p->ntype == nJunction,"Unexpected ntype"); + j=(Junction *) p; + if (j->jtype != Generic && + j->jtype != aSubBlk && /* pretty sure this one is allowed */ +/**** j->jtype != aOptBlk && ****/ /* pretty sure this one is allowed */ /* MR11 not any more ! */ + j->jtype != EndBlk) { + errFL("A context guard may not contain an option block: {...} or looping block: (...)* or (...)+", + FileStr[p->file],p->line); + contextGuardOK(j->p1,h,hmax); + return 0; + }; + /* do both p1 and p2 so use | rather than || */ + return contextGuardOK(j->p2,h,hmax) | contextGuardOK(j->p1,h,hmax); + }; +Fail: + errFL("A context guard may contain only Token references - guard will be ignored", + FileStr[p->file],p->line); + contextGuardOK( ( (ActionNode *) p)->next,h,hmax); + return 0; +} + +/* + * Look at a (...)? generalized-predicate context-guard and compute + * either a lookahead set (k==1) or a lookahead tree for k>1. The + * k level is determined by the guard itself rather than the LL_k + * variable. For example, ( A B )? is an LL(2) guard and ( ID )? + * is an LL(1) guard. For the moment, you can only have a single + * tuple in the guard. Physically, the block must look like this + * --o-->TOKEN-->o-->o-->TOKEN-->o-- ... -->o-->TOKEN-->o-- + * An error is printed for any other type. + */ +Predicate * +#ifdef __USE_PROTOS +computePredFromContextGuard(Graph blk,int *msgDone) /* MR10 */ +#else +computePredFromContextGuard(blk,msgDone) /* MR10 */ + Graph blk; + int *msgDone; /* MR10 */ +#endif +{ + Junction *junc = (Junction *)blk.left, *p; + Tree *t=NULL; + Predicate *pred = NULL; + set scontext, rk; + int ok; + int hmax=0; + + require(junc!=NULL && junc->ntype == nJunction, "bad context guard"); + +/* MR10 Check for anything other than Tokens and generic junctions */ + + *msgDone=0; /* MR10 */ + ok=contextGuardOK( (Node *)junc,0,&hmax); /* MR10 */ + if (! ok) { /* MR10 */ + *msgDone=1; /* MR10 */ + return NULL; /* MR10 */ + }; /* MR10 */ + if (hmax == 0) { +errFL("guard is 0 tokens long",FileStr[junc->file],junc->line); /* MR11 */ + *msgDone=1; + return NULL; + }; + if (hmax > CLL_k) { /* MR10 */ +errFL(eMsgd2("guard is %d tokens long - lookahead is limited to max(k,ck)==%d", /* MR10 */ + hmax,CLL_k), /* MR10 */ + FileStr[junc->file],junc->line); /* MR10 */ + *msgDone=1; /* MR10 */ + return NULL; /* MR10 */ + }; /* MR10 */ + + rk = empty; + p = junc; + pred = new_pred(); + pred->k = hmax; /* MR10 should be CLL_k, not LLK ? */ + if (hmax > 1 ) /* MR10 was LL_k */ + { + ConstrainSearch = 0; + ContextGuardTRAV = 1; + TRAV(p, hmax, &rk, t); /* MR10 was LL_k */ + ContextGuardTRAV = 0; + set_free(rk); + t = tshrink( t ); + t = tflatten( t ); + t = tleft_factor( t ); +/* + fprintf(stderr, "ctx guard:"); + preorder(t); + fprintf(stderr, "\n"); +*/ + pred->tcontext = t; + } + else + { + REACH(p, 1, &rk, scontext); + require(set_nil(rk), "rk != nil"); + set_free(rk); +/* + fprintf(stderr, "LL(1) ctx guard is:"); + s_fprT(stderr, scontext); + fprintf(stderr, "\n"); +*/ + pred->scontext[1] = scontext; + } + + list_add(&ContextGuardPredicateList,pred); /* MR13 */ + + return pred; +} + +/* MR13 + When the context guard is originally computed the + meta-tokens are not known. +*/ + +#ifdef __USE_PROTOS +void recomputeContextGuard(Predicate *pred) +#else +void recomputeContextGuard(pred) + Predicate *pred; +#endif +{ + Tree * t=NULL; + set scontext; + set rk; + ActionNode * actionNode; + Junction * p; + + actionNode=pred->source; + require (actionNode != NULL,"context predicate's source == NULL"); + + p=actionNode->guardNodes; + require (p != NULL,"context predicate's guardNodes == NULL"); + + rk = empty; + if (pred->k > 1 ) + { + ConstrainSearch = 0; + ContextGuardTRAV = 1; + TRAV(p, pred->k, &rk, t); + ContextGuardTRAV = 0; + set_free(rk); + t = tshrink( t ); + t = tflatten( t ); + t = tleft_factor( t ); + Tfree(pred->tcontext); + pred->tcontext = t; + } + else + { + REACH(p, 1, &rk, scontext); + require(set_nil(rk), "rk != nil"); + set_free(rk); + set_free(pred->scontext[1]); + pred->scontext[1] = scontext; + } +} + +/* MR11 - had enough of flags yet ? */ + +int MR_AmbSourceSearch=0; +int MR_AmbSourceSearchGroup=0; +int MR_AmbSourceSearchChoice=0; +int MR_AmbSourceSearchLimit=0; +int MR_matched_AmbAidRule=0; + +static set *matchSets[2]={NULL,NULL}; +static int *tokensInChain=NULL; +static Junction *MR_AmbSourceSearchJ[2]; + +void MR_traceAmbSourceKclient() +{ + int i; + set *save_fset; + int save_ConstrainSearch; + set incomplete; + Tree *t; + + if (matchSets[0] == NULL) { + matchSets[0]=(set *) calloc (CLL_k+1,sizeof(set)); + require (matchSets[0] != NULL,"matchSets[0] alloc"); + matchSets[1]=(set *) calloc (CLL_k+1,sizeof(set)); + require (matchSets[1] != NULL,"matchSets[1] alloc"); + }; + + for (i=1 ; i <= MR_AmbSourceSearchLimit ; i++) { + set_clr(matchSets[0][i]); + set_orel( (unsigned) tokensInChain[i], + &matchSets[0][i]); + set_clr(matchSets[1][i]); + set_orel( (unsigned) tokensInChain[i], + &matchSets[1][i]); + }; + + save_fset=fset; + save_ConstrainSearch=ConstrainSearch; + + + + for (i=0 ; i < 2 ; i++) { + +#if 0 +** fprintf(stdout," Choice:%d Depth:%d ",i+1,MR_AmbSourceSearchLimit); +** fprintf(stdout,"("); +** for (j=1 ; j <= MR_AmbSourceSearchLimit ; j++) { +** if (j != 1) fprintf(stdout," "); +** fprintf(stdout,"%s",TerminalString(tokensInChain[j])); +** }; +** fprintf(stdout,")\n\n"); +#endif + + fset=matchSets[i]; + + MR_AmbSourceSearch=1; + MR_MaintainBackTrace=1; + MR_AmbSourceSearchChoice=i; + ConstrainSearch=1; + + maxk = MR_AmbSourceSearchLimit; + + incomplete=empty; + t=NULL; + + constrain = &(fset[1]); + MR_pointerStackReset(&MR_BackTraceStack); + + TRAV(MR_AmbSourceSearchJ[i],maxk,&incomplete,t); + + Tfree(t); + + require (set_nil(incomplete),"MR_traceAmbSourceK TRAV incomplete"); + require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0"); + + set_free(incomplete); + }; + + ConstrainSearch=save_ConstrainSearch; + fset=save_fset; + MR_AmbSourceSearch=0; + MR_MaintainBackTrace=0; + MR_AmbSourceSearchChoice=0; +} + +#ifdef __USE_PROTOS +Tree *tTrunc(Tree *t,int depth) +#else +Tree *tTrunc(t,depth) + Tree *t; +#endif +{ + Tree *u; + + require ( ! (t == NULL && depth > 0),"tree too short"); + + if (depth == 0) return NULL; + + if (t->token == ALT) { + u=tTrunc(t->down,depth); + } else { + u=tnode(t->token); + u->down=tTrunc(t->down,depth-1); + }; + if (t->right != NULL) u->right=tTrunc(t->right,depth); + return u; +} + +#ifdef __USE_PROTOS +void MR_iterateOverTree(Tree *t,int chain[]) +#else +void MR_iterateOverTree(t,chain) + Tree *t; + int chain[]; +#endif +{ + if (t == NULL) return; + chain[0]=t->token; + if (t->down != NULL) { + MR_iterateOverTree(t->down,&chain[1]); + } else { + MR_traceAmbSourceKclient(); + }; + MR_iterateOverTree(t->right,&chain[0]); + chain[0]=0; +} + +#ifdef __USE_PROTOS +void MR_traceAmbSourceK(Tree *t,Junction *alt1,Junction *alt2) +#else +void MR_traceAmbSourceK(t,alt1,alt2) + Tree *t; + Junction *alt1; + Junction *alt2; +#endif +{ + int i; + int depth; + int maxDepth; + Tree *truncatedTree; + + if (MR_AmbAidRule == NULL) return; + + if ( ! ( + strcmp(MR_AmbAidRule,alt1->rname) == 0 || + strcmp(MR_AmbAidRule,alt2->rname) == 0 || + MR_AmbAidLine==alt1->line || + MR_AmbAidLine==alt2->line + ) + ) return; + + MR_matched_AmbAidRule++; + + /* there are no token sets in trees, only in TokNodes */ + + MR_AmbSourceSearchJ[0]=analysis_point( (Junction *) alt1->p1); + MR_AmbSourceSearchJ[1]=analysis_point( (Junction *) alt2->p1); + + if (tokensInChain == NULL) { + tokensInChain=(int *) calloc (CLL_k+1,sizeof(int)); + require (tokensInChain != NULL,"tokensInChain alloc"); + }; + + MR_AmbSourceSearchGroup=0; + + fprintf(stdout,"\n"); + fprintf(stdout," Ambiguity Aid "); + fprintf(stdout, + (MR_AmbAidDepth <= LL_k ? + "(-k %d -aa %s %s -aad %d)\n\n" : + "(-k %d -aa %s %s [-k value limits -aad %d])\n\n"), + LL_k, + MR_AmbAidRule, + (MR_AmbAidMultiple ? "-aam" : ""), + MR_AmbAidDepth); + + for (i=0 ; i < 2 ; i++) { + fprintf(stdout," Choice %d: %-25s line %d file %s\n", + (i+1), + MR_ruleNamePlusOffset( (Node *) MR_AmbSourceSearchJ[i]), + MR_AmbSourceSearchJ[i]->line, + FileStr[MR_AmbSourceSearchJ[i]->file]); + }; + + fprintf(stdout,"\n"); + + if (MR_AmbAidDepth < LL_k) { + maxDepth=MR_AmbAidDepth; + } else { + maxDepth=LL_k; + }; + + for (depth=1 ; depth <= maxDepth; depth++) { + MR_AmbSourceSearchLimit=depth; + if (depth < LL_k) { + truncatedTree=tTrunc(t,depth); + truncatedTree=tleft_factor(truncatedTree); + MR_iterateOverTree(truncatedTree,&tokensInChain[1]); /* <===== */ + Tfree(truncatedTree); + } else { + MR_iterateOverTree(t,tokensInChain); /* <===== */ + }; + fflush(stdout); + fflush(stderr); + }; + + fprintf(stdout,"\n"); + MR_AmbSourceSearch=0; + MR_MaintainBackTrace=0; + MR_AmbSourceSearchGroup=0; + MR_AmbSourceSearchChoice=0; + MR_AmbSourceSearchLimit=0; + +} + + +/* this if for k=1 grammars only + + this is approximate only because of the limitations of linear + approximation lookahead. Don't want to do a k=3 search when + the user only specified a ck=3 grammar +*/ + +#ifdef __USE_PROTOS +void MR_traceAmbSource(set *matchSets,Junction *alt1, Junction *alt2) +#else +void MR_traceAmbSource(matchSets,alt1,alt2) + set *matchSets; + Junction *alt1; + Junction *alt2; +#endif +{ + set *save_fset; + Junction *p[2]; + int i; + int j; + set *dup_matchSets; + set intersection; + set incomplete; + set tokensUsed; + int depth; + + if (MR_AmbAidRule == NULL) return; + if ( ! ( + strcmp(MR_AmbAidRule,alt1->rname) == 0 || + strcmp(MR_AmbAidRule,alt2->rname) == 0 || + MR_AmbAidLine==alt1->line || + MR_AmbAidLine==alt2->line + ) + ) return; + + MR_matched_AmbAidRule++; + + save_fset=fset; + + dup_matchSets=(set *) calloc(CLL_k+1,sizeof(set)); + require (dup_matchSets != NULL,"Can't allocate dup_matchSets"); + + p[0]=analysis_point( (Junction *) alt1->p1); + p[1]=analysis_point( (Junction *) alt2->p1); + + fprintf(stdout,"\n"); + + fprintf(stdout," Ambiguity Aid "); + fprintf(stdout, + (MR_AmbAidDepth <= CLL_k ? + "(-ck %d -aa %s %s -aad %d)\n\n" : + "(-ck %d -aa %s %s [-ck value limits -aad %d])\n\n"), + CLL_k, + MR_AmbAidRule, + (MR_AmbAidMultiple ? "-aam" : ""), + MR_AmbAidDepth); + + for (i=0 ; i < 2 ; i++) { + fprintf(stdout," Choice %d: %-25s line %d file %s\n", + (i+1), + MR_ruleNamePlusOffset( (Node *) p[i]), + p[i]->line,FileStr[p[i]->file]); + }; + + for (j=1; j <= CLL_k ; j++) { + fprintf(stdout,"\n Intersection of lookahead[%d] sets:\n",j); + intersection=set_and(alt1->fset[j],alt2->fset[j]); + MR_dumpTokenSet(stdout,2,intersection); + set_free(intersection); + }; + + fprintf(stdout,"\n"); + + require (1 <= MR_AmbAidDepth && MR_AmbAidDepth <= CLL_k, + "illegal MR_AmbAidDepth"); + + MR_AmbSourceSearchGroup=0; + for (depth=1; depth <= MR_AmbAidDepth; depth++) { + MR_AmbSourceSearchLimit=depth; + for (i=0 ; i < 2 ; i++) { + +/*** fprintf(stdout," Choice:%d Depth:%d\n\n",i+1,depth); ***/ + + for (j=0 ; j <= CLL_k ; j++) { dup_matchSets[j]=set_dup(matchSets[j]); }; + fset=dup_matchSets; + + fflush(output); + fflush(stdout); + + MR_AmbSourceSearch=1; + MR_MaintainBackTrace=1; + MR_AmbSourceSearchChoice=i; + + maxk = depth; + tokensUsed=empty; + incomplete=empty; + + constrain = &(fset[1]); + MR_pointerStackReset(&MR_BackTraceStack); + + REACH(p[i],depth,&incomplete,tokensUsed); + + fflush(output); + fflush(stdout); + + require (set_nil(incomplete),"MR_traceAmbSource REACH incomplete"); + require (MR_BackTraceStack.count == 0,"1: MR_BackTraceStack.count != 0"); + + set_free(incomplete); + set_free(tokensUsed); + + for (j=0 ; j <= CLL_k ; j++) { set_free(dup_matchSets[j]); }; + }; + }; + + fprintf(stdout,"\n"); + + MR_AmbSourceSearch=0; + MR_MaintainBackTrace=0; + MR_AmbSourceSearchGroup=0; + MR_AmbSourceSearchChoice=0; + MR_AmbSourceSearchLimit=0; + + fset=save_fset; + free ( (char *) dup_matchSets); +} + +static int itemCount; + +void MR_backTraceDumpItemReset() { + itemCount=0; +} + +#ifdef __USE_PROTOS +void MR_backTraceDumpItem(FILE *f,int skip,Node *n) +#else +void MR_backTraceDumpItem(f,skip,n) + FILE *f; + int skip; + Node *n; +#endif +{ + TokNode *tn; + RuleRefNode *rrn; + Junction *j; + ActionNode *a; + + switch (n->ntype) { + case nToken: + itemCount++; if (skip) goto EXIT; + tn=(TokNode *)n; + if (set_nil(tn->tset)) { + fprintf(f," %2d #token %-23s",itemCount,TerminalString(tn->token)); + } else { + fprintf(f," %2d #tokclass %-20s",itemCount,TerminalString(tn->token)); + }; + break; + case nRuleRef: + itemCount++; if (skip) goto EXIT; + rrn=(RuleRefNode *)n; + fprintf(f," %2d to %-27s",itemCount,rrn->text); + break; + case nAction: + a=(ActionNode *)n; + goto EXIT; + case nJunction: + + j=(Junction *)n; + + switch (j->jtype) { + case aSubBlk: + if (j->guess) { + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,"in (...)? block at"); + break; + }; +/****** fprintf(f," %2d %-32s",itemCount,"in (...) block at"); *******/ +/****** break; *******/ + goto EXIT; + case aOptBlk: + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,"in {...} block"); + break; + case aLoopBlk: + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,"in (...)* block"); + break; + case EndBlk: + if (j->alpha_beta_guess_end) { + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,"end (...)? block at"); + break; + }; + goto EXIT; +/****** fprintf(f," %2d %-32s",itemCount,"end of a block at"); *****/ +/****** break; *****/ + case RuleBlk: + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,j->rname); + break; + case Generic: + goto EXIT; + case EndRule: + itemCount++; if (skip) goto EXIT; + fprintf (f," %2d end %-26s",itemCount,j->rname); + break; + case aPlusBlk: + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,"in (...)+ block"); + break; + case aLoopBegin: + goto EXIT; + }; + break; + }; + fprintf(f," %-23s line %-4d %s\n",MR_ruleNamePlusOffset(n),n->line,FileStr[n->file]); +EXIT: + return; +} + + +static PointerStack previousBackTrace={0,0,NULL}; + +#ifdef __USE_PROTOS +void MR_backTraceReport(void) +#else +void MR_backTraceReport() +#endif +{ + int i; + int match = 0; + int limitMatch; + + Node *p; + TokNode *tn; + set remainder; + int depth; + + /* Even when doing a k=2 search this routine can get + called when there is only 1 token on the stack. + This is because something like rRuleRef can change + the search value of k from 2 to 1 temporarily. + It does this because the it wants to know the k=1 + first set before it does a k=2 search + */ + + depth=0; + for (i=0; i < MR_BackTraceStack.count ; i++) { + p=(Node *) MR_BackTraceStack.data[i]; + if (p->ntype == nToken) depth++; + }; + +/* MR14 */ if (MR_AmbSourceSearch) { +/* MR14 */ require (depth <= MR_AmbSourceSearchLimit,"depth > MR_AmbSourceSearchLimit"); +/* MR14 */ } + + /* MR23 THM - Traceback report was being called at the wrong time for -alpha reports */ + /* Reported by Arpad Beszedes (beszedes@inf.u-szeged.hu) */ + + if (MR_AmbSourceSearchLimit == 0 || depth < MR_AmbSourceSearchLimit) { + return; + }; + + MR_backTraceDumpItemReset(); + + limitMatch=MR_BackTraceStack.count; + if (limitMatch > previousBackTrace.count) { + limitMatch=previousBackTrace.count; + }; + + for (match=0; match < limitMatch; match++) { + if (MR_BackTraceStack.data[match] != + previousBackTrace.data[match]) { + break; + }; + }; + + /* not sure at the moment why there would be duplicates */ + + if (match != MR_BackTraceStack.count) { + + fprintf(stdout," Choice:%d Depth:%d Group:%d", + (MR_AmbSourceSearchChoice+1), + MR_AmbSourceSearchLimit, + ++MR_AmbSourceSearchGroup); + + depth=0; + fprintf(stdout," ("); + for (i=0; i < MR_BackTraceStack.count ; i++) { + p=(Node *) MR_BackTraceStack.data[i]; + if (p->ntype != nToken) continue; + tn=(TokNode *)p; + if (depth != 0) fprintf(stdout," "); + fprintf(stdout,TerminalString(tn->token)); + depth++; + if (! MR_AmbAidMultiple) { + if (set_nil(tn->tset)) { + set_rm( (unsigned) tn->token,fset[depth]); + } else { + remainder=set_dif(fset[depth],tn->tset); + set_free(fset[depth]); + fset[depth]=remainder; + }; + }; + }; + fprintf(stdout,")\n"); + + for (i=0; i < MR_BackTraceStack.count ; i++) { + MR_backTraceDumpItem(stdout, (i +#include +#include +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" + +#define NumExprPerLine 4 +static int on1line=0; +static set tokensRefdInBlock; + + /* T r a n s l a t i o n T a b l e s */ + +/* C_Trans[node type] == pointer to function that knows how to translate that node. */ +#ifdef __cplusplus +void (*C_Trans[NumNodeTypes+1])(...) = { + NULL, + NULL, /* See next table. +Junctions have many types */ + (void (*)(...)) genRuleRef, + (void (*)(...)) genToken, + (void (*)(...)) genAction + }; +#else +void (*C_Trans[NumNodeTypes+1])() = { + NULL, + NULL, /* See next table. +Junctions have many types */ + genRuleRef, + genToken, + genAction + }; +#endif + +/* C_JTrans[Junction type] == pointer to function that knows how to translate that + * kind of junction node. + */ +#ifdef __cplusplus +void (*C_JTrans[NumJuncTypes+1])(...) = { + NULL, + (void (*)(...)) genSubBlk, + (void (*)(...)) genOptBlk, + (void (*)(...)) genLoopBlk, + (void (*)(...)) genEndBlk, + (void (*)(...)) genRule, + (void (*)(...)) genJunction, + (void (*)(...)) genEndRule, + (void (*)(...)) genPlusBlk, + (void (*)(...)) genLoopBegin + }; +#else +void (*C_JTrans[NumJuncTypes+1])() = { + NULL, + genSubBlk, + genOptBlk, + genLoopBlk, + genEndBlk, + genRule, + genJunction, + genEndRule, + genPlusBlk, + genLoopBegin + }; +#endif + +#define PastWhiteSpace(s) while (*(s) == ' ' || *(s) == '\t') {s++;} + +static int tabs = 0; + +/* MR6 Got tired of text running off page when using standard tab stops */ + +#define TAB { int i; \ + if (TabWidth==0) { \ + for (i=0; irname);} + else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname); + } +} + +static void +#ifdef __USE_PROTOS +warn_about_using_gk_option(void) +#else +warn_about_using_gk_option() +#endif +{ + static int warned_already=0; + + if ( !DemandLookahead || warned_already ) return; + warned_already = 1; + warnNoFL("-gk option could cause trouble for <<...>>? predicates"); +} + +void +#ifdef __USE_PROTOS +freeBlkFsets( Junction *q ) +#else +freeBlkFsets( q ) +Junction *q; +#endif +{ + int i; + Junction *alt; + require(q!=NULL, "freeBlkFsets: invalid node"); + + for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) + { + for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]); + } +} + +/* + * Generate a local variable allocation for each token references + * in this block. + */ +static void +#ifdef __USE_PROTOS +genTokenPointers( Junction *q ) +#else +genTokenPointers( q ) +Junction *q; +#endif +{ + /* Rule refs are counted and can be referenced, but their + * value is not set to anything useful ever. + * + * The ptrs are to be named _tij where i is the current level + * and j is the element number within an alternative. + */ + int first=1, t=0; + set a; + tokensRefdInBlock = q->tokrefs; + + if ( set_deg(q->tokrefs) == 0 ) return; + a = set_dup(q->tokrefs); + gen("ANTLRTokenPtr "); + for (; !set_nil(a); set_rm(t, a)) + { + t = set_int(a); + if ( first ) first = 0; + else _gen(","); + if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t); + _gen2("_t%d%d", BlkLevel, t); + if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);} + else _gen("=NULL"); + } + _gen(";\n"); + set_free(a); +} + +static int +#ifdef __USE_PROTOS +hasDefaultException(ExceptionGroup *eg) +#else +hasDefaultException(eg) +ExceptionGroup *eg; +#endif +{ + ListNode *q; + + for (q = eg->handlers->next; q!=NULL; q=q->next) + { + ExceptionHandler *eh = (ExceptionHandler *)q->elem; + if ( strcmp("default", eh->signalname)==0 ) { + return 1; + } + } + return 0; +} +static void +#ifdef __USE_PROTOS +dumpException(ExceptionGroup *eg, int no_default_case) +#else +dumpException(eg, no_default_case) +ExceptionGroup *eg; +int no_default_case; +#endif +{ + char *outerLabel; /* MR7 */ + int altHandler=0; /* MR7 */ + int namedHandler=0; /* MR7 */ + + outerLabel=findOuterHandlerLabel(eg); /* MR7 */ + + if (eg->label != NULL) { /* MR7 */ + namedHandler=1; /* MR7 */ + } else if (eg->forRule) { /* MR7 */ + /* nothing */ /* MR20 */ + } else { /* MR7 */ + altHandler=1; /* MR7 */ + }; /* MR7 */ + +#if 0 +** if (! eg->used) { /* MR7 */ +** warnFL("exception group never used", /* MR7 */ +** FileStr[eg->altstart->file],eg->altstart->line); /* MR7 */ +** }; /* MR7 */ +#endif + + if (namedHandler) { /* MR7 */ + gen1("switch ( _signal ) { /* [%s] */\n",eg->label); /* MR7 */ + } else { /* MR7 */ + gen("switch ( _signal ) {\n"); /* MR7 */ + gen("case NoSignal: break; /* MR7 */\n"); /* MR7 */ + }; /* MR7 */ + { + ListNode *q; + for (q = eg->handlers->next; q!=NULL; q=q->next) + { + ExceptionHandler *eh = (ExceptionHandler *)q->elem; + if ( strcmp("default", eh->signalname)==0 ) { + gen("default :\n"); + tabs++; + dumpAction(eh->action, output, tabs, -1, 1, 1); + gen("_signal=NoSignal; /* MR7 */\n"); /* MR7 */ + gen("break; /* MR7 */\n"); /* MR7 */ + tabs--; + gen("}\n"); + + /* copied from later code in dumpException */ /* MR7 */ + + if (namedHandler) { /* MR7 */ + gen("if (_signal != NoSignal)"); /* MR7 */ + _gen1(" goto %s_handler; /* MR7 */\n",outerLabel);/* MR7 */ + } else if (altHandler) { /* MR7 */ + gen1("goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */ + }; + return; + } + gen1("case %s :\n", eh->signalname); + tabs++; + if ( eh->action != NULL ) + { + dumpAction(eh->action, output, tabs, -1, 1, 1); + gen("break; /* MR7 */\n"); /* MR7 */ + } + tabs--; + } + } + if ( no_default_case ) return; + + gen("default :\n"); + tabs++; /* MR7 */ + gen("break; /* MR7 */\n"); /* MR7 */ + tabs--; /* MR7 */ + + tabs++; +/***** gen("*_retsignal = _signal;\n"); *****/ + + tabs--; + gen("}\n"); + + if (namedHandler) { /* MR7 */ + gen("if (_signal != NoSignal)"); /* MR7 */ + _gen1(" goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */ + } else if (altHandler) { /* MR7 */ + gen1("goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */ + }; + +} + +static void +#ifdef __USE_PROTOS +dumpExceptions(ListNode *list) +#else +dumpExceptions(list) +ListNode *list; +#endif +{ + ListNode *p; + + for (p = list->next; p!=NULL; p=p->next) + { + ExceptionGroup *eg = (ExceptionGroup *) p->elem; + _gen2("%s%s_handler:\n", + eg->label==NULL?"":eg->label, + eg->altID==NULL?"":eg->altID); + if ( eg->altID!=NULL ) dumpException(eg, 0); + else { + /* This must be the rule exception handler */ + dumpException(eg, 1); + if ( !hasDefaultException(eg) ) + { + gen("default :\n"); + tabs++; + gen("zzdflthandlers(_signal,_retsignal);\n"); + tabs--; + gen("}\n"); + } + } + } +} + +/* For each element label that is found in a rule, generate a unique + * Attribute (and AST pointer if GenAST) variable. + */ +void +#ifdef __USE_PROTOS +genElementLabels(ListNode *list) +#else +genElementLabels(list) +ListNode *list; +#endif +{ + int first=1; + ListNode *p; + + if ( GenCC ) {gen("ANTLRTokenPtr");} + else {gen("Attrib");} + for (p = list->next; p!=NULL; p=p->next) + { + char *ep = (char *)p->elem; + if ( first ) first = 0; + else _gen(","); + if ( GenCC ) {_gen1(" %s=NULL",ep);} + else {_gen1(" %s",ep);} + } + _gen(";\n"); + + if ( !GenAST ) return; + + first = 1; + gen("AST"); + for (p = list->next; p!=NULL; p=p->next) + { + char *ep = (char *)p->elem; + if ( first ) first = 0; + else _gen(","); + _gen1(" *%s_ast=NULL",ep); + } + _gen(";\n"); +} + +/* + * Generate a local variable allocation for each token or rule reference + * in this block. + */ +static void +#ifdef __USE_PROTOS +genASTPointers( Junction *q ) +#else +genASTPointers( q ) +Junction *q; +#endif +{ + int first=1, t; + set a; + + a = set_or(q->tokrefs, q->rulerefs); + if ( set_deg(a) > 0 ) + { + gen("AST "); + for (; !set_nil(a); set_rm(t, a)) + { + t = set_int(a); + if ( first ) first = 0; + else _gen(","); + _gen2("*_ast%d%d=NULL", BlkLevel, t); + } + set_free(a); + } + _gen(";\n"); +} + +static void +#ifdef __USE_PROTOS +BLOCK_Head( void ) +#else +BLOCK_Head( ) +#endif +{ + gen("{\n"); + tabs++; + if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel); +} + +static void +#ifdef __USE_PROTOS +BLOCK_Tail( void ) +#else +BLOCK_Tail( ) +#endif +{ + if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel); + if ( !GenCC ) gen("}\n"); + tabs--; + gen("}\n"); +} + +static void +#ifdef __USE_PROTOS +BLOCK_Preamble( Junction *q ) +#else +BLOCK_Preamble( q ) +Junction *q; +#endif +{ + ActionNode *a; + Junction *begin; + + BLOCK_Head(); + if ( GenCC ) genTokenPointers(q); + if ( GenCC&&GenAST ) genASTPointers(q); + if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n"); + if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm) + else if ( !GenCC ) gen("zzMake0;\n"); + if ( !GenCC ) gen("{\n"); + if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1); + else begin = q; + if ( has_guess_block_as_first_item(begin) ) + { + gen("zzGUESS_BLOCK\n"); + } + if ( q->jtype == aLoopBegin ) + a = findImmedAction( ((Junction *)q->p1)->p1 ); /* look at aLoopBlk */ + else + a = findImmedAction( q->p1 ); + if ( a!=NULL && !a->is_predicate) { +/* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1); + a->done = 1; /* remove action. We have already handled it */ + } +} + +void +#ifdef __USE_PROTOS +genCombinedPredTreeContextOrig( Predicate *p ) +#else +genCombinedPredTreeContextOrig( p ) +Predicate *p; +#endif +{ + static set *ctx=NULL; /* genExprSets() is destructive, make copy*/ + require(p!=NULL, "can't make context tree for NULL pred tree"); + +#ifdef DBG_PRED + fprintf(stderr, "enter genCombinedPredTreeContextOrig(%s,0x%x) with sets:\n", p->expr, p); + s_fprT(stderr, p->scontext[1]); + fprintf(stderr, "\n"); +#endif + if ( p->down == NULL ) + { +/*** if ( p->k>1 && p->tcontext!=NULL ) ***/ + if ( p->tcontext!=NULL ) + { + _gen("("); + genExprTree(p->tcontext, 1); + _gen(")"); + } +/*** else if ( p->k==1 && set_deg(p->scontext[1])>0 ) ***/ + else if ( set_deg(p->scontext[1])>0 ) + { + if ( ctx==NULL ) ctx = (set *)calloc(CLL_k+1, sizeof(set)); + require(ctx!=NULL, "ctx cannot allocate"); + ctx[0]=empty; + ctx[1]=set_dup(p->scontext[1]); + _gen("("); + genExprSets(&(ctx[0]), p->k); + _gen(")"); + set_free(ctx[1]); + } + else if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) { + fatal_internal("pred tree is orphan OR or AND list"); + } + else { + if (! HoistPredicateContext) { + _gen(" 1 /* no context: prc is off */ "); + } else { + fatal_internal("pred tree context is empty"); + }; + } + return; + } + +/* MR10 - make AND just like OR */ + + if ( p->expr == PRED_AND_LIST ) + { + Predicate *list = p->down; + for (; list!=NULL; list=list->right) + { + genCombinedPredTreeContextOrig(list); + if ( list->right!=NULL ) _gen("|| /* MR10 was wrong */ "); + }; + return; + } + + if ( p->expr == PRED_OR_LIST ) + { + Predicate *list = p->down; + for (; list!=NULL; list=list->right) + { + genCombinedPredTreeContextOrig(list); + if ( list->right!=NULL ) _gen("||"); + }; + return; + }; + + fatal("pred tree is really wacked"); +} + +/* [genCombinedPredTreeContext] */ + +void +#ifdef __USE_PROTOS +genCombinedPredTreeContext( Predicate *p ) +#else +genCombinedPredTreeContext( p ) +Predicate *p; +#endif +{ + Tree *t; + int predDepth=0; + + if (0 && ! MR_usingPredNames && ! MRhoisting) { + genCombinedPredTreeContextOrig(p); + } else { +/* MR13 */ MR_pred_depth(p,&predDepth); +/* MR13 */ if (predDepth == 1) { +/* MR13 */ +/* MR13 */ set scontext[2]; +/* MR13 */ scontext[0]=empty; +/* MR13 */ scontext[1]=MR_compute_pred_set(p); +/* MR13 */ if (set_nil(scontext[1])) { +/* MR13 */ _gen(" 1 /* MR12 no context (-prc off) */ "); +/* MR13 */ } else { +/* MR13 */ _gen("("); +/* MR13 */ genExprSets(&scontext[0], 1); +/* MR13 */ set_free(scontext[1]); +/* MR13 */ _gen(")"); +/* MR13 */ }; + + } else { + t=MR_compute_pred_tree_context(p); + if (t == NULL) { + _gen(" 1 /* MR12 no context (-prc off) */ "); + } else { + _gen("("); + genExprTree(t, 1); + Tfree(t); /* MR10 */ + _gen(")"); + }; + }; + }; +} + +/* [genPredTreeGate] */ + +void +#ifdef __USE_PROTOS +genPredTreeGate( Predicate *p, int in_and_expr ) +#else +genPredTreeGate( p, in_and_expr ) +Predicate *p; +int in_and_expr; +#endif +{ + if ( in_and_expr ) + { + _gen("!("); + genCombinedPredTreeContext(p); + _gen(")||"); + if ( p->down!=NULL ) _gen("\n"); + } + else + { + _gen("("); + genCombinedPredTreeContext(p); + _gen(")&&"); + if ( p->down!=NULL ) _gen("\n"); + } +} + +#ifdef __USE_PROTOS +void genPredEntry(Predicate *p,int outer) +#else +void genPredEntry(p,outer) + Predicate *p; + int outer; +#endif +{ + int inverted=0; + Predicate *q; + int localOuter=outer; + int needRP=0; + + if (p == NULL) return; + + if (p->predEntry != NULL && p->predEntry->predLiteral != NULL) { + if (p->inverted != p->predEntry->pred->inverted) { + _gen("! /* inverted pred */ ("); + needRP=1; + } else { + if (!localOuter) _gen("("); + needRP=1; + }; + dumpAction(p->predEntry->predLiteral,output,0,p->source->file,p->source->line,0); + if (needRP) _gen(")"); + return; + }; + + inverted=p->inverted; + + if (inverted) { + _gen(" ! /* inverted pred */ ("); + localOuter=1; + }; + + if (p->expr == PRED_OR_LIST) { + if (!localOuter) _gen("("); + for (q=p->down; q != NULL ; q=q->right) { + genPredEntry(q,0); + if (q->right != NULL) _gen(" || "); + }; + if (!localOuter) _gen(")"); + } else if (p->expr == PRED_AND_LIST) { + if (!localOuter) _gen("("); + for (q=p->down; q != NULL ; q=q->right) { + genPredEntry(q,0); + if (q->right != NULL) _gen(" && "); + }; + if (!localOuter) _gen(")"); + } else { + if (!localOuter) _gen("("); + require (p->source != NULL,"predEntry->source == NULL"); + require (p->source->inverted == 0,"dumpPredEntry p->source->inverted != 0"); + dumpAction(p->source->action,output,0,p->source->file,p->source->line,0); + if (!localOuter) _gen(")"); + }; + + if (inverted) { + _gen(")"); + } +} + +void +#ifdef __USE_PROTOS +dumpPredAction(ActionNode *anode, + char *s,FILE *output,int tabs,int file,int line,int final_newline) +#else +dumpPredAction(anode, + s,output,tabs,file,line,final_newline) + + ActionNode *anode; + char *s; + FILE *output; + int tabs; + int file; + int line; + int final_newline; +#endif +{ + PredEntry *predEntry=anode->predEntry; + int inverted=anode->inverted; + Predicate *workPred; + + if (predEntry == NULL) { + + /* inline predicate literal */ + + require(inverted == 0,"dumpPredAction action->inverted"); + dumpAction(s,output,tabs,file,line,final_newline); + + } else { + + /* a reference to a predicate - possibly with an inverted source */ + + if (predEntry->predLiteral != NULL) { + if (inverted) _gen("! /* inverted pred */ ("); + dumpAction(predEntry->predLiteral,output,0,anode->file,anode->line,0); + if (inverted) _gen(")"); + } else { + workPred=predicate_dup(predEntry->pred); + if (inverted) workPred->inverted=!workPred->inverted; + genPredEntry(workPred,1); + predicate_free(workPred); + }; + }; +} + +/* [genPred] */ + +void +#ifdef __USE_PROTOS +genPred(Predicate *p, Node *j,int suppress_sva) +#else +genPred(p,j,suppress_sva) + Predicate *p; + Node *j; + int suppress_sva; +#endif +{ + if ( FoundException && !suppress_sva) {_gen("(_sva=(");} /* MR11 suppress_sva */ + else {_gen("(");} + if ( GenLineInfo && j->file != -1 ) _gen("\n"); + if (p->source != NULL && p->source->ampersandPred != NULL) { + if (p->source->ampersandPred->k == 1) { + + set ctx[2]; + + ctx[0]=empty; + ctx[1]=set_dup(p->source->ampersandPred->scontext[1]); + + _gen("("); + genExprSets(&(ctx[0]), p->k); + _gen(") && "); + set_free(ctx[1]); + } else { + _gen("( "); + genExprTree(p->source->ampersandPred->tcontext,1); + _gen(" ) && "); + }; + }; + + dumpPredAction((ActionNode *)p->source, + p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0); + + if ( FoundException && !suppress_sva) /* MR11 suppress_sva */ + {_gen("),_sva)");} /* MR10 - get red of "meant ==" messages */ + else {_gen(")");} +} + +void +#ifdef __USE_PROTOS +MR_distinctORcontextOpt(Predicate *p,Node *j,int in_and_expr) +#else +MR_distinctORcontextOpt(p,j,in_and_expr) + Predicate *p; + Node *j; + int in_and_expr; +#endif +{ + Predicate *q; + + _gen(" /* MR10 Distinct OR context optimization */ \n"); + + if (in_and_expr) { + gen("zzpf=0,\n"); + for (q=p->down; q != NULL; q=q->right) { + gen("( "); + genCombinedPredTreeContext(q); + _gen(" && (zzpf=1, "); + genPred(q,j,0); + _gen(" )) ||\n"); + }; + gen("!zzpf)"); + } else { + require (0, + "MR_distinctORcontextOpt: can't get here when using MR_predSimplify"); +#if 0 +** for (q=p->down; q != NULL; q=q->right) { +** gen("( "); +** genCombinedPredTreeContext(q); +** _gen(" && "); +** genPred(q,j); +** if (q->right != NULL) { +** _gen(" ) ||\n"); +** }; +** }; +** gen(")"); +#endif + }; +} + +void +#ifdef __USE_PROTOS +genPredTreeOrig( Predicate *p, Node *j, int in_and_expr ) +#else +genPredTreeOrig( p, j, in_and_expr ) +Predicate *p; +Node *j; +int in_and_expr; +#endif +{ + +/* MR10 */ int allHaveContext=1; +/* MR10 */ int noneHaveContext=1; + +/* MR10 */ MR_predContextPresent(p,&allHaveContext,&noneHaveContext); + + if ( ! noneHaveContext ) /* MR10 context guards ignored when -prc off */ + { + _gen("("); + genPredTreeGate(p, in_and_expr); + } + + /* if leaf node, just gen predicate */ + + if ( p->down==NULL ) + { + genPred(p,j,0); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + } + + /* if AND list, do both preds (only two possible) */ + if ( p->expr == PRED_AND_LIST ) + { +#if 0 +** _gen("("); +** genPredTreeOrig(p->down, j, 1); +** _gen("&&"); +** genPredTreeOrig(p->down->right, j, 1); +** _gen(")"); +** if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ +** return; +#endif + /* MR11 - make it work with AND with more than two children - like OR */ + + Predicate *list; + _gen("("); + list = p->down; + for (; list!=NULL; list=list->right) + { + genPredTreeOrig(list, j, 1); + if ( list->right!=NULL ) _gen("&&"); + } + _gen(")"); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + }; + + if ( p->expr == PRED_OR_LIST ) + { + Predicate *list; + _gen("("); + list = p->down; + for (; list!=NULL; list=list->right) + { + genPredTreeOrig(list, j, 0); + if ( list->right!=NULL ) _gen("||"); + } + _gen(")"); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + } + + fatal_internal("genPredTreeOrig: predicate tree is wacked"); +} + +#if 0 +** Predicate member dummyPredDepth is no longer used in MR10 +** but we might need it again in the future +** +** if (MRhoisting) { +** if ( !noneHaveContext && +** ! in_and_expr && +** p->source != NULL && +** p->source->dummyPredicateDepth > 0 && +** p->down == NULL) { +** _gen("("); +** genCombinedPredTreeContext(p); +** _gen(" )\n"); +** return; +** }; +** }; +#endif + +/* [genPredTree] */ + +/* in_and_expr + + what to do if the context is wrong + what to do if the context is correct but the predicate is false + + remember: if the context is wrong it's the same as if the + predicate is true as far as enabling an alternative + + Consider (AND p q r) + + if in an ... && ... expression then you don't want + the entire predicate chain to fail just because the + context for one component is wrong: so return true + + Consider (OR p q r) + + if in an ... || ... expression then you don't want + the entire predicate chain to succeed just because + the context for one component is correct when the + corresponding test is false: so return false when + the context is correct but the test is false. +*/ + +void +#ifdef __USE_PROTOS +genPredTree( Predicate *p, Node *j, int in_and_expr, int suppress_sva ) +#else +genPredTree( p, j, in_and_expr, suppress_sva) + Predicate *p; + Node *j; + int in_and_expr; + int suppress_sva; +#endif +{ + + int allHaveContext=1; + int noneHaveContext=1; + Tree *groupTree; + Tree *oneTree; + Predicate *q; + int identicalORcontextOptimization=0; + int identicalANDcontextOptimization=0; + + if (0 && !MR_usingPredNames && !MRhoisting) { + genPredTreeOrig(p,j,in_and_expr); + return; + }; + + MR_predContextPresent(p,&allHaveContext,&noneHaveContext); + + if ( ! noneHaveContext ) { /* MR10 context guards ignored when -prc off */ + + _gen("("); + + /* MR10 optimize OR predicates which are all leaves */ + + if (p->expr == PRED_OR_LIST && MR_allPredLeaves(p->down)) { + groupTree=MR_compute_pred_tree_context(p); + for (q=p->down ; q != NULL ; q=q->right) { + oneTree=MR_compute_pred_tree_context(q); + if (! MR_tree_equ(groupTree,oneTree)) { + Tfree(oneTree); + break; + }; + Tfree(oneTree); + }; + Tfree(groupTree); + if (q == NULL) { + _gen("/* MR10 individual OR gates suppressed when all predicates are leaves"); + _gen(" with identical context */\n"); + genPredTreeGate(p,in_and_expr); /* use the parent's in_and_expr for this gate */ + identicalORcontextOptimization=1; + } else { + MR_distinctORcontextOpt(p,j,in_and_expr); + return; + }; + } else if (p->expr == PRED_AND_LIST && MR_allPredLeaves(p->down)) { + + /* MR12 optimize AND predicates which are all leaves */ + + groupTree=MR_compute_pred_tree_context(p); + for (q=p->down ; q != NULL ; q=q->right) { + oneTree=MR_compute_pred_tree_context(q); + if (! MR_tree_equ(groupTree,oneTree)) { + Tfree(oneTree); + break; + }; + Tfree(oneTree); + }; + Tfree(groupTree); + if (q == NULL) { + _gen("/* MR12 individual AND gates suppressed when all predicates are leaves"); + _gen(" with identical context */\n"); + genPredTreeGate(p,in_and_expr); /* use the parent's in_and_expr for this gate */ + identicalANDcontextOptimization=1; + } else { + genPredTreeGate(p, in_and_expr); + }; + } else { + genPredTreeGate(p, in_and_expr); + }; + } + + /* if leaf node, just gen predicate */ + + if ( p->down==NULL ) + { + genPred(p,j,suppress_sva); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + } + + /* if AND list, do both preds (only two possible) */ + /* MR10 not any more ! */ + + if ( p->expr == PRED_AND_LIST ) + { + Predicate *list; + _gen("("); + list = p->down; + for (; list != NULL; list=list->right) { + if (identicalANDcontextOptimization) { + genPred(list, j,suppress_sva); + } else { + genPredTree(list, j, 1, suppress_sva); /* in and context */ + }; + if ( list->right!=NULL ) _gen("&&"); + }; + _gen(")"); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + } + + if ( p->expr == PRED_OR_LIST ) + { + Predicate *list; + _gen("("); + list = p->down; + for (; list!=NULL; list=list->right) + { + if (identicalORcontextOptimization) { + genPred(list, j,suppress_sva); + } else { + genPredTree(list, j, 0, suppress_sva); + }; + if ( list->right!=NULL ) _gen("||"); + } + _gen(")"); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + } + + fatal_internal("predicate tree is wacked"); +} + +/* [genPredTreeMainXX] */ + +Predicate * /* MR10 */ +#ifdef __USE_PROTOS +genPredTreeMainXX( Predicate *p, Node *j ,int in_and_expr) +#else +genPredTreeMainXX( p, j ,in_and_expr) + Predicate *p; + Node *j; + int in_and_expr; +#endif +{ + + int allHaveContext=1; + int noneHaveContext=1; + +#if 0 + fprintf(stderr,"Pred before\n"); + dumppred(p); + fprintf(stderr,"\n"); + fprintf(stderr,"Pred after\n"); + dumppred(p); + fprintf(stderr,"\n"); +#endif + + p=MR_predSimplifyALL(p); /* MR10 */ + + require (MR_predicate_context_completed(p),"predicate context is not complete"); + + MR_cleanup_pred_trees(p); /* MR10 */ + + MR_predContextPresent(p,&allHaveContext,&noneHaveContext); + if (!noneHaveContext & !allHaveContext) { + warnFL("predicate contains elements both with and without context", + FileStr[j->file],j->line); + }; + + if (InfoP) { + _gen("\n#if 0\n\n"); + MR_dumpPred(p,1); + _gen("#endif\n"); + }; + genPredTree(p,j,in_and_expr,0); + return p; +} + +Predicate * /* MR10 */ +#ifdef __USE_PROTOS +genPredTreeMain( Predicate *p, Node *j) +#else +genPredTreeMain( p, j) + Predicate *p; + Node *j; +#endif +{ + return genPredTreeMainXX(p,j,1); +} + +static void +#ifdef __USE_PROTOS +genExprTreeOriginal( Tree *t, int k ) +#else +genExprTreeOriginal( t, k ) +Tree *t; +int k; +#endif +{ + require(t!=NULL, "genExprTreeOriginal: NULL tree"); + + if ( t->token == ALT ) + { + _gen("("); genExprTreeOriginal(t->down, k); _gen(")"); + if ( t->right!=NULL ) + { + _gen("||"); + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + _gen("("); genExprTreeOriginal(t->right, k); _gen(")"); + } + return; + } + if ( t->down!=NULL ) _gen("("); + _gen1("LA(%d)==",k); + if ( TokenString(t->token) == NULL ) _gen1("%d", t->token) + else _gen1("%s", TokenString(t->token)); + if ( t->down!=NULL ) + { + _gen("&&"); + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + _gen("("); genExprTreeOriginal(t->down, k+1); _gen(")"); + } + if ( t->down!=NULL ) _gen(")"); + if ( t->right!=NULL ) + { + _gen("||"); + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + _gen("("); genExprTreeOriginal(t->right, k); _gen(")"); + } +} + +#ifdef __USE_PROTOS +static void MR_LAtokenString(int k,int token) +#else +static void MR_LAtokenString(k,token) + int k; + int token; +#endif +{ + char *ts; + + ts=TokenString(token); + if (ts == NULL) { + _gen2(" LA(%d)==%d",k,token); + } else { + _gen2(" LA(%d)==%s",k,ts); + }; +} + + +#ifdef __USE_PROTOS +static int MR_countLeaves(Tree *t) +#else +static int MR_countLeaves(t) + Tree *t; +#endif +{ + if (t == NULL) return 0; + if (t->token == ALT) { + return MR_countLeaves(t->down)+MR_countLeaves(t->right); + } else { + return 1+MR_countLeaves(t->down)+MR_countLeaves(t->right); + }; +} + +#ifdef __USE_PROTOS +static void MR_genOneLine(Tree *tree,int k) +#else +static void MR_genOneLine(tree,k) + Tree *tree; + int k; +#endif +{ + if (tree == NULL) return; + if (tree->token == ALT) { + MR_genOneLine(tree->down,k); + } else { + MR_LAtokenString(k,tree->token); + if (tree->down != NULL && + tree->down->right == NULL) { + _gen(" &&"); + MR_genOneLine(tree->down,k+1); + } else if (tree->down != NULL) { + _gen(" && ("); + MR_genOneLine(tree->down,k+1); + _gen(")"); + }; + }; + if (tree->right != NULL) { + _gen(" ||"); + MR_genOneLine(tree->right,k); + }; +} + +static int across; +static int depth; +static int lastkonline; + +#ifdef __USE_PROTOS +static void MR_genMultiLine(Tree *tree,int k) +#else +static void MR_genMultiLine(tree,k) + Tree *tree; + int k; +#endif +{ + int i; + + if (tree == NULL) return; + if (tree->token == ALT) { + MR_genMultiLine(tree,k); + } else { + MR_LAtokenString(k,tree->token); + lastkonline=k; + across++; + if (tree->down != NULL && tree->down->right == NULL) { + if (across > 3) { + _gen("\n"); + across=0; + lastkonline=0; + for (i=0 ; i < depth+k ; i++) _gen(" "); + _gen("&&"); + } else { + _gen(" &&"); + }; + MR_genMultiLine(tree->down,k+1); + } else if (tree->down != NULL) { + _gen("\n"); + lastkonline=0; + across=0; + for (i=0 ; i < depth+k ; i++) _gen(" "); + _gen("&& ("); + MR_genMultiLine(tree->down,k+1); + _gen(")"); + }; + }; + if (tree->right != NULL) { + if (k < lastkonline) { + _gen("\n"); + across=0; + lastkonline=0; + for (i=0; i < depth+k-1 ; i++) _gen(" "); + _gen("||"); + } else if (across > 3 ) { + _gen("\n"); + across=0; + lastkonline=0; + for (i=0; i < depth+k ; i++) _gen(" "); + _gen("||"); + } else { + _gen(" ||"); + }; + MR_genMultiLine(tree->right,k); + }; +} + +#ifdef __USE_PROTOS +static void genExprTree(Tree *tree,int k) +#else +static void genExprTree(tree,k) + Tree *tree; + int k; +#endif +{ + int count; + +#if 0 + /* MR20 THM This was probably an error. + The routine should probably reference that static + "across" and this declaration hides it. + */ + + int across; +#endif + + require (tree != NULL,"genExprTree: tree is NULL"); + require (k > 0,"genExprTree: k <= 0"); + + if (0 && !MRhoisting) { /* MR11 make new version standard */ + genExprTreeOriginal(tree,k); + } else { + count=MR_countLeaves(tree); + if (count < 5) { + MR_genOneLine(tree,k); + } else { + _gen("\n"); + across=0; + depth=0; + lastkonline=0; + MR_genMultiLine(tree,k); + _gen("\n"); + }; + }; +} + + +/* + * Generate LL(k) type expressions of the form: + * + * (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) && + * (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) && + * ..... + * (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn) + * + * If GenExprSetsOpt generate: + * + * (setwdi[LA(1)]&(1<= 1. + * + * This routine is visible only to this file and cannot answer a TRANS message. + * + */ + +/* [genExpr] */ + +static int +#ifdef __USE_PROTOS +genExpr( Junction *j ) +#else +genExpr( j ) +Junction *j; +#endif +{ + int max_k; + + /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead + * from CLL_k..LL_k + */ + { + int limit; + if ( j->ftree!=NULL ) limit = LL_k; + else limit = CLL_k; + max_k = genExprSets(j->fset, limit); + } + + /* Do tests for real tuples from other productions that conflict with + * artificial tuples generated by compression (using sets of tokens + * rather than k-trees). + */ + if ( j->ftree != NULL ) + { + _gen(" && !("); genExprTree(j->ftree, 1); _gen(")"); + } + + if ( ParseWithPredicates && j->predicate!=NULL ) + { + Predicate *p = j->predicate; + warn_about_using_gk_option(); + _gen("&&"); + j->predicate=genPredTreeMain(p, (Node *)j); /* MR10 */ + } + + return max_k; +} + +static int +#ifdef __USE_PROTOS +genExprSets( set *fset, int limit ) +#else +genExprSets( fset, limit ) +set *fset; +int limit; +#endif +{ + int k = 1; + int max_k = 0; + unsigned *e, *g, firstTime=1; + + if (set_nil(fset[1])) { + _gen(" 0 /* MR13 empty set expression - undefined rule ? infinite left recursion ? */ "); + MR_BadExprSets++; + }; + + if ( GenExprSetsOpt ) + { + while ( k <= limit && !set_nil(fset[k]) ) /* MR11 */ + { + if ( set_deg(fset[k])==1 ) /* too simple for a set? */ + { + int e; + _gen1("(LA(%d)==",k); + e = set_int(fset[k]); + if ( TokenString(e) == NULL ) _gen1("%d)", e) + else _gen1("%s)", TokenString(e)); + } + else + { + NewSet(); + FillSet( fset[k] ); + _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<max_k ) max_k = k; + if ( k == CLL_k ) break; + k++; + if ( k<=limit && !set_nil(fset[k]) ) _gen(" && "); /* MR11 */ + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + } + return max_k; + } + + while ( k<= limit && !set_nil(fset[k]) ) /* MR11 */ + { + if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set"); + for (; *e!=nil; e++) + { + if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; } + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + _gen1("LA(%d)==",k); + if ( TokenString(*e) == NULL ) _gen1("%d", *e) + else _gen1("%s", TokenString(*e)); + } + free( (char *)g ); + _gen(")"); + if ( k>max_k ) max_k = k; + if ( k == CLL_k ) break; + k++; + if ( k <= limit && !set_nil(fset[k]) ) { firstTime=1; _gen(" && "); } /* MR11 */ + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + } + return max_k; +} + +/* + * Generate code for any type of block. If the last alternative in the block is + * empty (not even an action) don't bother doing it. This permits us to handle + * optional and loop blocks as well. + * + * Only do this block, return after completing the block. + * This routine is visible only to this file and cannot answer a TRANS message. + */ +static set +#ifdef __USE_PROTOS +genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly, int * lastAltEmpty /* MR23 */) +#else +genBlk( q, jtype, max_k, need_right_curly, lastAltEmpty /* MR23 */) +Junction *q; +int jtype; +int *max_k; +int *need_right_curly; +int *lastAltEmpty; /* MR23 */ +#endif +{ + set f; + Junction *alt; + int a_guess_in_block = 0; + require(q!=NULL, "genBlk: invalid node"); + require(q->ntype == nJunction, "genBlk: not junction"); + *need_right_curly=0; + *lastAltEmpty = 0; /* MR23 */ + if ( q->p2 == NULL ) /* only one alternative? Then don't need if */ + { + if (first_item_is_guess_block((Junction *)q->p1)!=NULL ) + { + if (jtype != aLoopBlk && jtype != aOptBlk && jtype != aPlusBlk) { + warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line); + }; + gen("zzGUESS\n"); /* guess anyway to make output code consistent */ +/* MR10 disable */ /**** gen("if ( !zzrv )\n"); ****/ +/* MR10 */ gen("if ( !zzrv ) {\n"); tabs++; (*need_right_curly)++; + }; + TRANS(q->p1); + return empty; /* no decision to be made-->no error set */ + } + + f = First(q, 1, jtype, max_k); + for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) + { + if ( alt->p2 == NULL ) /* chk for empty alt */ + { + Node *p = alt->p1; + if ( p->ntype == nJunction ) + { + /* we have empty alt */ +/* MR23 + There is a conflict between giving good error information for non-exceptions + and making life easy for those using parser exception handling. Consider: + + r: { A } b; + b: B; + + with input "C" + + Before MR21 the error message would be "expecting B - found C". After MR21 + the error message would be "expcect A, B - found C". This was good, but it + caused problems for those using parser exceptions because the reference to + B was generated inside the {...} where B really wasn't part of the block. + + In MR23 this has been changed for the case where exceptions are in use to + not generate the extra check in the tail of the {A} block. +*/ + + +/* MR23 */ if (isEmptyAlt( ((Junction *)p)->p1, (Node *)q->end)) { +/* MR23 */ *lastAltEmpty = 1; +/* MR23 */ if (FoundException) { +/* MR23 */ /* code to restore state if a prev alt didn't follow guess */ +/* MR23 */ if ( a_guess_in_block && jtype != aPlusBlk) { +/* MR23 */ gen("if ( !zzrv ) zzGUESS_DONE; /* MR28 */\n"); +/* MR23 */ } +/* MR23 */ break; +/* MR23 */ }; +/* MR28 */ if (jtype == aPlusBlk) { +/* MR28 */ break; +/* MR28 */ } +/* MR23 */ } + } + } /* end of for loop on alt */ + +/* MR10 */ if (alt->p2 == NULL && +/* MR10 */ ( q->jtype == aSubBlk || q->jtype == RuleBlk) ) { +/* MR10 */ if (first_item_is_guess_block(alt)) { +/* MR10 */ warnFL("(...)? as last alternative of block is unnecessary", +/* MR10 */ FileStr[alt->file],alt->line); +/* MR10 */ }; +/* MR10 */ }; + + if ( alt != q ) gen("else ") + else + { + if ( DemandLookahead ) { + if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);} + else gen1("look(%d);\n", *max_k); + } + } + + if ( alt!=q ) + { + _gen("{\n"); + tabs++; + (*need_right_curly)++; + /* code to restore state if a prev alt didn't follow guess */ + if ( a_guess_in_block ) + gen("if ( !zzrv ) zzGUESS_DONE;\n"); + } + if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) + { + a_guess_in_block = 1; + gen("zzGUESS\n"); + } + gen("if ( "); + if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && "); + genExpr(alt); + _gen(" ) "); + _gen("{\n"); + tabs++; + TRANS(alt->p1); + --tabs; + gen("}\n"); +/* MR10 */ if (alt->p2 == NULL) { +/* MR10 */ if (first_item_is_guess_block(alt)) { +/* MR10 */ gen("/* MR10 */ else {\n"); +/* MR10 */ tabs++; +/* MR10 */ (*need_right_curly)++; +/* MR10 */ /* code to restore state if a prev alt didn't follow guess */ +/* MR10 */ gen("/* MR10 */ if ( !zzrv ) zzGUESS_DONE;\n"); +/* MR10 */ gen("/* MR10 */ if (0) {} /* last alternative of block is guess block */\n"); +/* MR10 */ }; +/* MR10 */ }; + } + return f; +} + +static int +#ifdef __USE_PROTOS +has_guess_block_as_first_item( Junction *q ) +#else +has_guess_block_as_first_item( q ) +Junction *q; +#endif +{ + Junction *alt; + + for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) + { + if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1; + } + return 0; +} + +static int +#ifdef __USE_PROTOS +has_guess_block_as_last_item( Junction *q ) +#else +has_guess_block_as_last_item( q ) +Junction *q; +#endif +{ + Junction *alt; + + if (q == NULL) return 0; + for (alt=q; alt->p2 != NULL && !( (Junction *) alt->p2)->ignore; alt= (Junction *) alt->p2 ) {}; + return first_item_is_guess_block( (Junction *) alt->p1) != NULL; +} + +/* MR30 See description of first_item_is_guess_block for background */ + +Junction * +#ifdef __USE_PROTOS +first_item_is_guess_block_extra(Junction *q ) +#else +first_item_is_guess_block_extra(q) +Junction *q; +#endif +{ + while ( q!=NULL && + ( ( q->ntype==nAction ) || + ( q->ntype==nJunction && + (q->jtype==Generic || q->jtype == aLoopBlk) + ) + ) + ) + { + if ( q->ntype==nJunction ) q = (Junction *)q->p1; + else q = (Junction *) ((ActionNode *)q)->next; + } + + if ( q==NULL ) return NULL; + if ( q->ntype!=nJunction ) return NULL; + if ( q->jtype!=aSubBlk ) return NULL; + if ( !q->guess ) return NULL; + + return q; +} + +/* return NULL if 1st item of alt is NOT (...)? block; else return ptr to aSubBlk node + * of (...)?; This function ignores actions and predicates. + */ + +Junction * +#ifdef __USE_PROTOS +first_item_is_guess_block( Junction *q ) +#else +first_item_is_guess_block( q ) +Junction *q; +#endif +{ + Junction * qOriginal = q; /* DEBUG */ + + /* MR14 Couldn't find aSubBlock which was a guess block when it lay + behind aLoopBlk. The aLoopBlk only appear in conjunction with + aLoopBegin, but the routine didn't know that. I think. + + MR14a Added extra parentheses to clarify precedence + + MR30 This appears to have been a mistake. The First set was then + computed incorrectly for: + + r : ( (A)? B + | C + )* + + The routine analysis_point was seeing the guess block when + it was still analyzing the loopBegin block. As a consequence, + when it looked for the analysis_point it was processing the B, but + skipping over the C alternative altogether because it thought + it was looking at a guess block, not realizing there was a loop + block in front of the loopBegin. + + loopBegin loopBlk subBlk/guess A G EB G B EB EB EB ER + | | | ^ ^ + | | | | + | +-> G C G ----------------------+ | + | | + +--- G G G -------------------------------------+ + + Reported by Arpad Beszedes (beszedes@inf.u-szeged.hu). + + MR30 This is still more complicated. This fix caused ambiguity messages + to be reported for "( (A B)? )* A B" but not for "( (A B)? )+". Why is + there a difference when these are outwardly identical ? It is because the + start of a (...)* block is represented by two nodes: a loopBegin block + followed by a loopBlock whereas the start of a (...)+ block is + represented as a single node: a plusBlock. So if first_item_is_guess_block + is called when the current node is a loopBegin it starts with the + loop block rather than the the sub block which follows the loop block. + However, we can't just skip past the loop block because some routines + depend on the old implementation. So, we provide a new implementation + which does skip the loopBlock. However, which should be called when ? + I'm not sure, but my guess is that first_item_is_guess_block_extra (the + new one) should only be called for the ambiguity routines. + + */ + + while ( q!=NULL && + ( ( q->ntype==nAction ) || + ( q->ntype==nJunction && + (q->jtype==Generic /*** || q->jtype == aLoopBlk ***/ ) /*** MR30 Undo MR14 change ***/ + ) + ) + ) + { + if ( q->ntype==nJunction ) q = (Junction *)q->p1; + else q = (Junction *) ((ActionNode *)q)->next; + } + + if ( q==NULL ) return NULL; + if ( q->ntype!=nJunction ) return NULL; + if ( q->jtype!=aSubBlk ) return NULL; + if ( !q->guess ) return NULL; + + return q; +} + +/* MR1 */ +/* MR1 10-Apr-97 MR1 Routine to stringize failed semantic predicates msgs */ +/* MR1 */ + +#define STRINGIZEBUFSIZE 1024 + +static char stringizeBuf[STRINGIZEBUFSIZE]; +char * +#ifdef __USE_PROTOS +stringize(char * s) +#else +stringize(s) +char *s; +#endif + +{ + char *p; + char *stop; + + p=stringizeBuf; + stop=&stringizeBuf[1015]; + + if (s != 0) { + while (*s != 0) { + if (p >= stop) { + goto stringizeStop; + } else if (*s == '\n') { + *p++='\\'; + *p++='n'; + *p++='\\'; + *p++=*s++; + } else if (*s == '\\') { + *p++=*s; + *p++=*s++; + } else if (*s == '\"') { + *p++='\\'; + *p++=*s++; + while (*s != 0) { + if (p >= stop) { + goto stringizeStop; + } else if (*s == '\n') { + *p++='\\'; + *p++=*s++; + } else if (*s == '\\') { + *p++=*s++; + *p++=*s++; + } else if (*s == '\"') { + *p++='\\'; + *p++=*s++; + break; + } else { + *p++=*s++; + }; + }; + } else if (*s == '\'') { + *p++=*s++; + while (*s != 0) { + if (p >= stop) { + goto stringizeStop; + } else if (*s == '\'') { + *p++=*s++; + break; + } else if (*s == '\\') { + *p++=*s++; + *p++=*s++; + } else if (*s == '\"') { + *p++='\\'; + *p++=*s++; + break; + } else { + *p++=*s++; + }; + }; + } else { + *p++=*s++; + }; + }; + }; + goto stringizeExit; +stringizeStop: + *p++='.'; + *p++='.'; + *p++='.'; +stringizeExit: + *p=0; + return stringizeBuf; +} + +#ifdef __USE_PROTOS +int isNullAction(char *s) +#else +int isNullAction(s) + char *s; +#endif +{ + char *p; + for (p=s; *p != '\0' ; p++) { + if (*p != ';' && *p !=' ') return 0; + }; + return 1; +} +/* MR1 */ +/* MR1 End of Routine to stringize code for failed predicates msgs */ +/* MR1 */ + +/* Generate an action. Don't if action is NULL which means that it was already + * handled as an init action. + */ +void +#ifdef __USE_PROTOS +genAction( ActionNode *p ) +#else +genAction( p ) +ActionNode *p; +#endif +{ + require(p!=NULL, "genAction: invalid node and/or rule"); + require(p->ntype==nAction, "genAction: not action"); + + if ( !p->done ) /* MR10 */ /* MR11 */ + { + if ( p->is_predicate) + { + if ( p->guardpred != NULL ) + { + Predicate *guardDup=predicate_dup(p->guardpred); /* MR10 */ + gen("if (!"); + guardDup=genPredTreeMain(guardDup, (Node *)p); + predicate_free(guardDup); + } +/* MR10 */ else if (p->ampersandPred != NULL) { +/* MR10 */ gen("if (!"); +/* MR10 */ p->ampersandPred=genPredTreeMain(p->ampersandPred, (Node *)p); +/* MR10 */ } + else + { + gen("if (!("); + /* make sure that '#line n' is on front of line */ + if ( GenLineInfo && p->file != -1 ) _gen("\n"); + dumpPredAction(p,p->action, output, 0, p->file, p->line, 0); + _gen(")"); + } + +/* MR23 Change failed predicate macro to have three arguments: + + macro arg 1: The stringized predicate itself + macro arg 2: 0 => no user-defined error action + 1 => user-defined error action + macro arg 3: The user-defined error action + + This gives the user more control of the error action. +*/ + tabs++; + gen3(") {zzfailed_pred(\"%s\",%s, { %s } );}\n", /* MR23 */ + stringize(p->action), /* MR23 */ + (p->pred_fail == NULL ? /* MR23/MR27 */ + "0 /* report */" : "1 /* user action */"), /* MR23/MR27 */ + (p->pred_fail == NULL ? /* MR23 */ + "0; /* no user action */" : p->pred_fail)); /* MR23 */ + tabs--; + } + else /* not a predicate */ + { + if (! isNullAction(p->action) && !p->noHoist) { + if ( FoundGuessBlk ) { + if ( GenCC ) { + gen("if ( !guessing ) {\n"); + } else { + gen("zzNON_GUESS_MODE {\n"); + }; + }; + dumpActionPlus(p, p->action, output, tabs, p->file, p->line, 1); /* MR21 */ + if ( FoundGuessBlk ) gen("}\n"); + }; + } + } + TRANS(p->next) +} + +/* + * if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in + * else pass addr of temp root ptr (&_ast) (don't zzlink it in). + * + * if ! modifies rule-ref, then never link it in and never pass zzSTR. + * Always pass address of temp root ptr. + */ +void +#ifdef __USE_PROTOS +genRuleRef( RuleRefNode *p ) +#else +genRuleRef( p ) +RuleRefNode *p; +#endif +{ + Junction *q; + char *handler_id = ""; + RuleEntry *r, *r2; + char *parm = "", *exsig = ""; + + int genRuleRef_emittedGuessGuard=0; /* MR10 */ + + require(p!=NULL, "genRuleRef: invalid node and/or rule"); + require(p->ntype==nRuleRef, "genRuleRef: not rule reference"); + + if ( p->altstart!=NULL && p->altstart->exception_label!=NULL ) + handler_id = p->altstart->exception_label; + + r = (RuleEntry *) hash_get(Rname, p->text); + if ( r == NULL ) + { + warnFL( eMsg1("rule %s not defined", + p->text), FileStr[p->file], p->line ); + return; + } + +/* MR8 5-Aug-97 Reported by S.Bochnak@microtool.com.pl */ +/* Don't do assign when no return values declared */ +/* Move definition of q up and use it to guard p->assign */ + + q = RulePtr[r->rulenum]; /* find definition of ref'd rule */ /* MR8 */ + + r2 = (RuleEntry *) hash_get(Rname, p->rname); + if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;} + + OutLineInfo(output,p->line,FileStr[p->file]); + + if ( GenCC && GenAST ) { + gen("_ast = NULL;\n"); + } + + if ( FoundGuessBlk && p->assign!=NULL && q->ret != NULL ) { /* MR8 */ + if ( GenCC ) { + gen("if ( !guessing ) {\n"); + } else { + gen("zzNON_GUESS_MODE {\n"); + }; + tabs++; /* MR11 */ + genRuleRef_emittedGuessGuard=1; /* MR11 */ + }; + + if ( FoundException ) exsig = "&_signal"; + + tab(); + if ( GenAST ) + { + if ( GenCC ) { +/**** if ( r2->noAST || p->astnode==ASTexclude ) +****/ + { +/**** _gen("_ast = NULL;\n"); +****/ + parm = "&_ast"; + } +/*** we always want to set just a pointer now, then set correct +pointer after + + else { + _gen("_astp = +(_tail==NULL)?(&_sibling):(&(_tail->_right));\n"); + parm = "_astp"; + } +****/ + } + else { + if ( r2->noAST || p->astnode==ASTexclude ) + { + _gen("_ast = NULL; "); + parm = "&_ast"; + } + else parm = "zzSTR"; + } + if ( p->assign!=NULL && q->ret!=NULL ) /* MR8 */ + { + if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */ + else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum); + } + if ( FoundException ) { + _gen5("%s%s(%s,&_signal%s%s); ", + RulePrefix, + p->text, + parm, + (p->parms!=NULL)?",":"", + (p->parms!=NULL)?p->parms:""); + if ( p->ex_group!=NULL ) { + _gen("\n"); + gen("if (_signal) {\n"); + tabs++; + dumpException(p->ex_group, 0); + tabs--; + gen("}"); + } + else { + _gen1("if (_signal) goto %s_handler;", handler_id); + } + } + else { + _gen5("%s%s(%s%s%s);", + RulePrefix, + p->text, + parm, + (p->parms!=NULL)?",":"", + (p->parms!=NULL)?p->parms:""); + } + if ( GenCC && (r2->noAST || p->astnode==ASTexclude) ) + { + /* rule has a ! or element does */ + /* still need to assign to #i so we can play with it */ + _gen("\n"); + gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum); + } + else if ( !r2->noAST && p->astnode == ASTinclude ) + { + /* rule doesn't have a ! and neither does element */ +/* MR10 */ if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) { +/* MR10 */ _gen("\n"); +/* MR10 */ if (GenCC) gen ("if (!guessing) { /* MR10 */") +/* MR10 */ else gen ("if (!zzguessing) { /* MR10 */\n"); +/* MR10 */ tabs++; +/* MR10 */ }; + if ( GenCC ) { + _gen("\n"); + gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n"); + gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum); + tab(); + } + else _gen(" "); + if ( GenCC ) { + _gen("ASTBase::"); } + else _gen("zz"); + _gen("link(_root, &_sibling, &_tail);"); + +/* MR10 */ if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) { /* MR10 */ +/* MR10 */ _gen("\n"); +/* MR10 */ tabs--; +/* MR10 */ if (GenCC) gen ("}; /* MR10 */") +/* MR10 */ else gen ("}; /* MR10 */"); +/* MR10 */ }; + } + } + else + { + if ( p->assign!=NULL && q->ret!=NULL ) /* MR8 */ + { + if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */ + else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum); + } + if ( FoundException ) { + _gen4("%s%s(&_signal%s%s); ", + RulePrefix, + p->text, + (p->parms!=NULL)?",":"", + (p->parms!=NULL)?p->parms:""); + if ( p->ex_group!=NULL ) { + _gen("\n"); + gen("if (_signal) {\n"); + tabs++; + dumpException(p->ex_group, 0); + tabs--; + gen("}"); + } + else { + _gen1("if (_signal) goto %s_handler;", handler_id); + } + } + else { + _gen3("%s%s(%s);", + RulePrefix, + p->text, + (p->parms!=NULL)?p->parms:""); + } + if ( p->assign!=NULL && q->ret!=NULL ) _gen("\n"); /* MR8 */ + } + + if ( p->assign!=NULL && q->ret!=NULL) { /* MR8 */ + if ( hasMultipleOperands(p->assign) ) /* MR23 */ + { + _gen("\n"); + dumpRetValAssign(p->assign, q->ret, p); /* MR30 */ + _gen("}"); + } + } + _gen("\n"); + + /* Handle element labels now */ + if ( p->el_label!=NULL ) + { + if ( GenAST ) + { + if ( GenCC ) { + gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum); + } + else {gen1("%s_ast = zzastCur;\n", p->el_label);} + } + else if (!GenCC ) { + gen1("%s = zzaCur;\n", p->el_label); + } + } + + if ( FoundGuessBlk && p->assign!=NULL && q->ret!=NULL ) { /* MR8 */ + /* in guessing mode, don't branch to handler upon error */ + tabs--; /* MR11 */ + gen("} else {\n"); + tabs++; /* MR11 */ + if ( FoundException ) { + gen6("%s%s(%s%s&_signal%s%s);\n", + RulePrefix, + p->text, + parm, + (*parm!='\0')?",":"", + (p->parms!=NULL)?",":"", + (p->parms!=NULL)?p->parms:""); + } + else { + gen5("%s%s(%s%s%s);\n", + RulePrefix, + p->text, + parm, + (p->parms!=NULL && *parm!='\0')?",":"", + (p->parms!=NULL)?p->parms:""); + } + tabs--; /* MR11 */ + gen("}\n"); + } + TRANS(p->next) +} + +/* + * Generate code to match a token. + * + * Getting the next token is tricky. We want to ensure that any action + * following a token is executed before the next GetToken(); + */ +void +#ifdef __USE_PROTOS +genToken( TokNode *p ) +#else +genToken( p ) +TokNode *p; +#endif +{ + RuleEntry *r; + char *handler_id = ""; + ActionNode *a; + char *set_name; + char *set_nameErrSet; + int complement; + int ast_label_in_action = 0; /* MR27 */ + int pushedCmodeAST = 0; /* MR27 */ + + require(p!=NULL, "genToken: invalid node and/or rule"); + require(p->ntype==nToken, "genToken: not token"); + if ( p->altstart!=NULL && p->altstart->exception_label!=NULL ) + handler_id = p->altstart->exception_label; + + r = (RuleEntry *) hash_get(Rname, p->rname); + if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;} + +/* + * MR27 Has the element label been referenced as an AST (with the # operator) ? + * If so, then we'll want to build the AST even though the user has used + * the ! operator. + */ +/* MR27 */ if (GenAST && p->el_label != NULL) { +/* MR27 */ ast_label_in_action = list_search_cstring(r->ast_labels_in_actions, +/* MR27 */ p->el_label); +/* MR27 */ } + + OutLineInfo(output,p->line,FileStr[p->file]); + + if ( !set_nil(p->tset) ) /* implies '.', ~Tok, or tokenclass */ + { + unsigned e; + unsigned eErrSet = 0; + set b; + set bErrSet; /* MR23 */ + b = set_dup(p->tset); + bErrSet = set_dup(p->tset); /* MR23 */ + complement = p->complement; /* MR23 */ + if ( p->tclass!=NULL && complement == 0 /* MR23 */) { /* token class not complemented*/ + static char buf[MaxRuleName+20]; /* MR23 */ + static char bufErrSet[MaxRuleName+20]; /* MR23 */ + if ( p->tclass->dumped ) { + e = p->tclass->setnum; + eErrSet = p->tclass->setnumErrSet; + } + else { + e = DefErrSet(&b, 0, TokenString(p->token)); + eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errset"); + p->tclass->dumped = 1; /* indicate set has been created */ + p->tclass->setnum = e; + p->tclass->setnumErrSet = eErrSet; /* MR23 */ + } + sprintf(buf, "%s_set", TokenString(p->token)); + sprintf(bufErrSet, "%s_errset", TokenString(p->token)); /* MR23 */ + set_name = buf; + set_nameErrSet = bufErrSet; /* MR23 */ + } + + /* MR23 - Forgot about the case of ~TOKCLASS. */ + + else if ( p->tclass!=NULL && complement != 0 /* MR23 */) + { + static char buf[MaxRuleName+20]; /* MR23 */ + static char bufErrSet[MaxRuleName+20]; /* MR23 */ + if ( p->tclass->dumpedComplement ) { + e = p->tclass->setnumComplement; + eErrSet = p->tclass->setnumErrSetComplement; + } + else { + e = DefErrSetWithSuffix(0, &b, 0, TokenString(p->token), "_setbar"); + eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errsetbar"); + p->tclass->dumpedComplement = 1; /* indicate set has been created */ + p->tclass->setnumComplement = e; + p->tclass->setnumErrSetComplement = eErrSet; /* MR23 */ + } + sprintf(buf, "%s_setbar", TokenString(p->token)); + sprintf(bufErrSet, "%s_errsetbar", TokenString(p->token)); /* MR23 */ + set_name = buf; + set_nameErrSet = bufErrSet; /* MR23 */ + } + else { /* wild card */ + static char buf[sizeof("zzerr")+10]; + static char bufErrSet[sizeof("zzerr")+10]; + int n = DefErrSet( &b, 0, NULL ); + int nErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, NULL, "_set"); + if ( GenCC ) sprintf(buf, "err%d", n); + else sprintf(buf, "zzerr%d", n); + if ( GenCC ) sprintf(bufErrSet, "err%d", nErrSet); + else sprintf(bufErrSet, "zzerr%d", nErrSet); + set_name = buf; + set_nameErrSet = bufErrSet; + } + + if ( !FoundException ) { +/* MR23 */ gen2("zzsetmatch(%s, %s);", set_name, set_nameErrSet); + } + else if ( p->ex_group==NULL ) { + if ( p->use_def_MT_handler ) + gen3("zzsetmatch_wdfltsig(%s,(ANTLRTokenType)%d,%s);", + set_name, + p->token, + tokenFollowSet(p)) + else + gen2("zzsetmatch_wsig(%s, %s_handler);", + set_name, + handler_id); + } + else + { + gen1("if ( !_setmatch_wsig(%s) ) {\n", set_name); + tabs++; +/* MR6 */ if (FoundGuessBlk) { +/* MR6 */ if ( GenCC ) {gen("if ( guessing ) goto fail;\n");} +/* MR6 */ else gen("if ( zzguessing ) goto fail;\n"); +/* MR6 */ }; + gen("_signal=MismatchedToken;\n"); + dumpException(p->ex_group, 0); + tabs--; + gen("}\n"); + } + set_free(b); + set_free(bErrSet); + } + else if ( TokenString(p->token)!=NULL ) + { + if ( FoundException ) { + if ( p->use_def_MT_handler ) + gen2("zzmatch_wdfltsig(%s,%s);",TokenString(p->token),tokenFollowSet(p)) + else if ( p->ex_group==NULL ) + { + gen2("zzmatch_wsig(%s, %s_handler);", + TokenString(p->token), + handler_id); + } + else + { +/* MR6 */ if (GenCC) { +/* MR6 */ gen1("if ( !_match_wsig(%s) ) {\n", TokenString(p->token)); +/* MR6 */ } else { +/* MR6 */ gen1("if ( !_zzmatch_wsig(%s) ) {\n", TokenString(p->token)); +/* MR6 */ }; + tabs++; +/* MR6 */ if (FoundGuessBlk) { +/* MR6 */ if ( GenCC ) {gen("if ( guessing ) goto fail;\n");} +/* MR6 */ else gen("if ( zzguessing ) goto fail;\n"); +/* MR6 */ }; + gen("_signal=MismatchedToken;\n"); + dumpException(p->ex_group, 0); + tabs--; + gen("}\n"); + } + } + else gen1("zzmatch(%s);", TokenString(p->token)); + } + else { + if ( FoundException ) { + if ( p->use_def_MT_handler ) + gen2("zzmatch_wdfltsig((ANTLRTokenType)%d,%s);", + p->token,tokenFollowSet(p)) + else + gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id); + } + else {gen1("zzmatch(%d);", p->token);} + } + + a = findImmedAction( p->next ); + /* generate the token labels */ + if ( GenCC && p->elnum>0 ) + { + /* If building trees in C++, always gen the LT() assigns */ + if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) + { +/* MR10 */ if ( FoundGuessBlk ) { +/* MR10 */ gen("\n"); +/* MR10 */ if (p->label_used_in_semantic_pred) { +/* MR10 */ gen2(" _t%d%d = (ANTLRTokenPtr)LT(1); /* MR10 */\n", BlkLevel-1, p->elnum); +/* MR10 */ } else { +/* MR10 */ gen("if ( !guessing ) {\n"); tab(); +/* MR10 */ _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);\n", BlkLevel-1, p->elnum); +/* MR10 */ gen("}\n"); +/* MR10 */ }; +/* MR10 */ } else { +/* MR10 */ _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);", BlkLevel-1, p->elnum); +/* MR10 */ }; +/* MR10 */ + } + +/* + * MR23 labase is never used in the C++ runtime library. + * and this code is generated only in C++ mode + */ + +/*** if ( LL_k>1 ) / * MR23 disabled */ +/*** if ( !DemandLookahead ) _gen(" labase++;"); / * MR23 disabled */ +/*** _gen("\n"); / * MR23 disabled */ +/*** tab(); / * MR23 disabled */ + } + if ( GenAST ) + { + if ( FoundGuessBlk && + (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) ) + { + if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();} + else {_gen("zzNON_GUESS_MODE {\n"); tab();} + } + +/* MR27 addition when labels referenced when operator ! used */ + + pushedCmodeAST = 0; /* MR27 */ + if (ast_label_in_action && (p->astnode == ASTexclude || r->noAST)) { + _gen("\n"); + if (GenCC) { +/* MR13 */ if (NewAST) { +/* MR13 */ gen4("_ast%d%d = newAST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum); +/* MR13 */ } else { +/* MR13 */ gen4("_ast%d%d = new AST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum); +/* MR13 */ } + } + else { + pushedCmodeAST = 1; + gen("zzastPush(zzmk_ast(zzastnew(),zzaCur)); /* MR27 */"); + } + } + +/* end MR27 addition for labels referenced when operator ! used */ + + if (!r->noAST ) + { + if (GenCC && !(p->astnode == ASTexclude) ) { + _gen("\n"); +/* MR13 */ if (NewAST) { +/* MR13 */ gen4("_ast%d%d = newAST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum); +/* MR13 */ } else { +/* MR13 */ gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum); +/* MR13 */ } + tab(); + } + if ( GenCC && !(p->astnode == ASTexclude) ) + {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);} + else _gen(" "); + if ( p->astnode==ASTchild ) { + if ( !GenCC ) _gen("zz"); + _gen("subchild(_root, &_sibling, &_tail);"); + } + else if ( p->astnode==ASTroot ) { + if ( !GenCC ) _gen("zz"); + _gen("subroot(_root, &_sibling, &_tail);"); + } + if ( GenCC && !(p->astnode == ASTexclude) ) { + _gen("\n"); + tab(); + } + } + else if ( !GenCC ) { + if (! pushedCmodeAST) _gen(" zzastDPush;"); + } + if ( FoundGuessBlk && + (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) ) + {gen("}\n"); tab();} + } + + /* Handle element labels now */ + if ( p->el_label!=NULL ) + { + int done_NON_GUESSMODE=0; + + _gen("\n"); + +/* MR10 */ /* do Attrib / Token ptr for token label used in semantic pred */ +/* MR10 */ /* for these cases do assign even in guess mode */ +/* MR10 */ +/* MR10 */ if (p->label_used_in_semantic_pred) { +/* MR10 */ if ( GenCC ) { +/* MR10 */ if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) { +/* MR10 */ gen3("%s = _t%d%d;", p->el_label, BlkLevel-1, p->elnum); +/* MR10 */ } else { +/* MR10 */ gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label); +/* MR10 */ }; +/* MR10 */ } else { +/* MR10 */ gen1("%s = zzaCur;", p->el_label); +/* MR10 */ }; +/* MR10 */ if (FoundGuessBlk) _gen(" /* MR10 */"); +/* MR10 */ _gen("\n"); +/* MR10 */ }; + + /* Do Attrib / Token ptr */ + +/* MR10 */ if (! p->label_used_in_semantic_pred) { +/* MR10 */ +/* MR10 */ if ( FoundGuessBlk ) { +/* MR10 */ if (! done_NON_GUESSMODE) { +/* MR10 */ done_NON_GUESSMODE=1; +/* MR10 */ if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();} +/* MR10 */ else {gen("zzNON_GUESS_MODE {\n"); tab();} +/* MR10 */ }; +/* MR10 */ }; +/* MR10 */ +/* MR10 */ if ( GenCC ) { +/* MR10 */ if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) { +/* MR10 */ gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum); +/* MR10 */ } else { +/* MR10 */ gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label); +/* MR10 */ }; +/* MR10 */ } else { +/* MR10 */ gen1("%s = zzaCur;\n", p->el_label); +/* MR10 */ }; +/* MR10 */ }; + + /* Do AST ptr */ + + if (GenAST && (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST) )) /* MR27 */ + { + +/* MR10 */ if ( FoundGuessBlk ) { +/* MR10 */ if (! done_NON_GUESSMODE) { +/* MR10 */ done_NON_GUESSMODE=1; +/* MR10 */ if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();} +/* MR10 */ else {gen("zzNON_GUESS_MODE {\n"); tab();} +/* MR10 */ }; +/* MR10 */ }; + + if ( GenCC ) { + gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum); + } + else {gen1("%s_ast = zzastCur;\n", p->el_label);} + } + +/* MR10 */ if (done_NON_GUESSMODE) { +/* MR10 */ gen("}\n"); tab(); +/* MR10 */ }; + + } + + /* Handle any actions immediately following action */ + if ( a != NULL ) /* MR10 */ /* MR11 */ + { + /* delay next token fetch until after action */ + _gen("\n"); + if ( a->is_predicate) + { +#if 0 +/* Disabled in MR30 ************************************************************ + And moved into genAction + ***************************************************************************** +*/ + + gen("if (!("); + + /* make sure that '#line n' is on front of line */ /* MR14 */ + if ( GenLineInfo && p->file != -1 ) _gen("\n"); /* MR14 */ + dumpPredAction(a,a->action, output, 0, a->file, a->line, 0); + +/* MR23 Change failed predicate macro to have three arguments: + + macro arg 1: The stringized predicate itself + macro arg 2: 0 => no user-defined error action + 1 => user-defined error action + macro arg 3: The user-defined error action + + This gives the user more control of the error action. +*/ + _gen(")) \n"); + tabs++; + gen3(" {zzfailed_pred(\"%s\",%s,{ %s } );}\n", /* MR23 */ + stringize(a->action), /* MR23 */ + (a->pred_fail == NULL ? /* MR23/MR27 */ + "0 /* report */" : "1 /* user action */"), /* MR23/MR27 */ + (a->pred_fail == NULL ? /* MR23 */ + "0; /* no user action */" : a->pred_fail)); /* MR23 */ + tabs--; +/* Disabled in MR30 ************************************************************ + And moved into genAction + ***************************************************************************** +*/ +#endif + } + else /* MR9 a regular action - not a predicate action */ + { + +/* MR23: Search an action which is not a predicate for LT(i), + LA(i), or LATEXT(i) in order to warn novice users that + it refers to the previous matched token, not the next + one. This is different than the case for semantic + predicates. +*/ + +/* MR23 */ if (GenCC) { +/* MR23 */ if (strstr(a->action, "LT(") != NULL) LTinTokenAction = 1; +/* MR23 */ } +/* MR23 */ else { +/* MR23 */ if (strstr(a->action, "LA(") != NULL) LTinTokenAction = 1; +/* MR23 */ if (strstr(a->action, "LATEXT(") != NULL) LTinTokenAction = 1; +/* MR23 */ } + + if ( FoundGuessBlk ) { + if ( GenCC ) {gen("if ( !guessing ) {\n");} + else gen("zzNON_GUESS_MODE {\n"); + } + dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1); /* MR21 */ + if ( FoundGuessBlk ) gen("}\n"); + a->done = 1; /* MR30 */ + } +/*** a->done = 1; MR30 Moved up into then branch for true actions, but not predicates ***/ + if ( !DemandLookahead ) { + if ( GenCC ) { + if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)"); + _gen(" consume();") + if ( FoundException && p->use_def_MT_handler ) + _gen(" _signal=NoSignal;"); + _gen("\n"); + } + else + { + if ( FoundException && p->use_def_MT_handler ) _gen("if (!_signal)"); + _gen(" zzCONSUME;\n"); + if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;"); + _gen("\n"); + } + } + else gen("\n"); + if (a->done) { /* MR30 */ + TRANS( a->next ); /* MR30 */ + } /* MR30 */ + else { /* MR30 */ + TRANS( p->next ); /* MR30 */ + } /* MR30 */ + } + else + { + if ( !DemandLookahead ) { + if ( GenCC ) { + if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)"); + _gen(" consume();") + if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;"); + _gen("\n"); + } + else { + if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)"); + _gen(" zzCONSUME;"); + if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;"); + _gen("\n"); + } + } + else _gen("\n"); + TRANS(p->next); + } +} + +/* MR21 + * + * There was a bug in the code generation for {...} which causes it + * to omit the optional tokens from the error messages. The easiest + * way to fix this was to make the opt block look like a sub block: + * + * { a | b | c } + * + * becomes (internally): + * + * ( a | b | c | ) + * + * The code for genOptBlk is now identical to genSubBlk except for + * cosmetic changes. + */ + +void +#ifdef __USE_PROTOS +genOptBlk( Junction *q ) +#else +genOptBlk( q ) +Junction *q; +#endif +{ + int max_k; + set f; + int need_right_curly; + set savetkref; + int lastAltEmpty; /* MR23 */ + savetkref = tokensRefdInBlock; + require(q->ntype == nJunction, "genOptBlk: not junction"); + require(q->jtype == aOptBlk, "genOptBlk: not opt block"); + + OutLineInfo(output,q->line,FileStr[q->file]); + BLOCK_Preamble(q); + BlkLevel++; + BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */ + f = genBlk(q, aOptBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); +/* MR23 + Bypass error clause generation when exceptions are used in {...} block + See multi-line note in genBlk near call to isEmptyAlt. +*/ + if (! FoundException) { + if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );} + } + else { + gen("/* MR23 skip error clause for {...} when exceptions in use */\n"); + } + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets(q); + --BlkLevel; + BLOCK_Tail(); + + if ( q->guess ) + { + gen("zzGUESS_DONE\n"); + } + + /* must duplicate if (alpha)?; one guesses (validates), the + * second pass matches */ + if ( q->guess && analysis_point(q)==q ) + { + OutLineInfo(output,q->line,FileStr[q->file]); + BLOCK_Preamble(q); + BlkLevel++; + f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); + if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );} + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets(q); + --BlkLevel; + BLOCK_Tail(); + } + + tokensRefdInBlock = savetkref; + if (q->end->p1 != NULL) TRANS(q->end->p1); +} + +/* + * Generate code for a loop blk of form: + * + * |---| + * v | + * --o-G-o-->o-- + */ +void +#ifdef __USE_PROTOS +genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k ) +#else +genLoopBlk( begin, q, start, max_k ) +Junction *begin; +Junction *q; +Junction *start; /* where to start generating code from */ +int max_k; +#endif +{ + set f; + int need_right_curly; + set savetkref; + Junction *guessBlock; /* MR10 */ + int singleAlt; /* MR10 */ + int lastAltEmpty; /* MR23 */ + + savetkref = tokensRefdInBlock; + require(q->ntype == nJunction, "genLoopBlk: not junction"); + require(q->jtype == aLoopBlk, "genLoopBlk: not loop block"); + + if ( q->visited ) return; + q->visited = TRUE; + + /* first_item_is_guess_block doesn't care what kind of node it is */ + + guessBlock=first_item_is_guess_block( (Junction *) q->p1); /* MR10 */ + singleAlt=q->p2==NULL; /* MR10 */ + + if (singleAlt && !guessBlock) /* MR10 */ /* only one alternative? */ + { + if ( DemandLookahead ) { + if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);} + else gen1("look(%d);\n", max_k); + } + gen("while ( "); + if ( begin!=NULL ) genExpr(begin); + else genExpr(q); + /* if no predicates have been hoisted for this single alt (..)* + * do so now + */ + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + if ( ParseWithPredicates && begin->predicate==NULL ) + { + Predicate *a = MR_find_predicates_and_supp((Node *)q->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + + if ( a!=NULL ) + { + _gen("&&"); + a=genPredTreeMain(a, (Node *)q); /* MR10 */ + } +/* MR10 */ if (MRhoisting) { +/* MR10 */ predicate_free(a); +/* MR10 */ }; + } + _gen(" ) {\n"); + tabs++; + TRANS(q->p1); + if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1); + if ( DemandLookahead ) { + if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);} + else gen1("look(%d);\n", max_k); + } + --tabs; + gen("}\n"); + freeBlkFsets(q); + q->visited = FALSE; + tokensRefdInBlock = savetkref; + return; + } + gen("for (;;) {\n"); /* MR20 G. Hobbelt */ + tabs++; +/* MR6 */ +/* MR6 "begin" can never be null when called from genLoopBegin */ +/* MR6 because q==(Junction *)begin->p1 and we know q is valid */ +/* MR6 */ +/* MR6 from genLoopBegin: */ +/* MR6 */ +/* MR6 if ( LL_k>1 && !set_nil(q->fset[2]) ) */ +/* MR6 genLoopBlk( q, (Junction *)q->p1, q, max_k ); */ +/* MR6 else genLoopBlk( q, (Junction *)q->p1, NULL, max_k ); */ +/* MR6 */ + if ( begin!=NULL ) + { + if ( DemandLookahead ) + { + if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);} + else gen1("look(%d);\n", max_k); + } + /* The bypass arc of the (...)* predicts what to do when you fail, but + * ONLY after having tested the loop start expression. To avoid this, + * we simply break out of the (...)* loop when we find something that + * is not in the prediction of the loop (all alts thereof). + */ + gen("if ( !("); + +/*** TJP says: It used to use the prediction expression for the bypass arc + of the (...)*. HOWEVER, if a non LL^1(k) decision was found, this + thing would miss the ftree stored in the aLoopBegin node and generate + an LL^1(k) decision anyway. + + *** genExpr((Junction *)begin->p2); + ***/ + + genExpr((Junction *)begin); + _gen(")) break;\n"); + + } + + /* generate code for terminating loop (this is optional branch) */ + + f = genBlk(q, aLoopBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); + set_free(f); + freeBlkFsets(q); + + /* generate code for terminating loop (this is optional branch) */ + +/* MR6 */ +/* MR6 30-May-97 Bug reported by Manuel Ornato */ +/* MR6 A definite bug involving the exit from a loop block */ +/* MR6 In 1.23 and later versions (including 1.33) Instead */ +/* MR6 exiting the block and reporting a syntax error the */ +/* MR6 code loops forever. */ +/* MR6 Looking at 1.20 which generates proper code it is not */ +/* MR6 clear which of two changes should be undone. */ +/* MR6 This is my best guess. */ +/* MR6 From earlier MR6 note we know that begin can never be */ +/* MR6 null when genLoopBlk called from genLoopBegin */ +/* MR6 */ +/* MR6 */ if ( begin==NULL) { +/* MR6 */ /* code for exiting loop "for sure" */ +/* MR6 */ gen("/* Suppressed by MR6 */ /*** else break; ***/\n"); +/* MR6 */ }; + +/* MR10 */if (singleAlt && guessBlock) { +/* MR10 */ tabs--; +/* MR6 */ gen("} else break; /* MR6 code for exiting loop \"for sure\" */\n"); +/* MR10 */ need_right_curly--; +/* MR10 */ } else { +/* MR6 */ gen("else break; /* MR6 code for exiting loop \"for sure\" */\n"); +/* MR10 */ }; + + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1); + --tabs; + gen("}\n"); + q->visited = FALSE; + tokensRefdInBlock = savetkref; +} + +/* + * Generate code for a loop blk of form: + * + * |---| + * v | + * --o-->o-->o-G-o-->o-- + * | ^ + * v | + * o-----------o + * + * q->end points to the last node (far right) in the blk. + * + * Note that q->end->jtype must be 'EndBlk'. + * + * Generate code roughly of the following form: + * + * do { + * ... code for alternatives ... + * } while ( First Set of aLoopBlk ); + * + * OR if > 1 alternative + * + * do { + * ... code for alternatives ... + * else break; + * } while ( 1 ); + */ +void +#ifdef __USE_PROTOS +genLoopBegin( Junction *q ) +#else +genLoopBegin( q ) +Junction *q; +#endif +{ + set f; + int i; + int max_k; + set savetkref; + savetkref = tokensRefdInBlock; + require(q!=NULL, "genLoopBegin: invalid node and/or rule"); + require(q->ntype == nJunction, "genLoopBegin: not junction"); + require(q->jtype == aLoopBegin, "genLoopBegin: not loop block"); + require(q->p2!=NULL, "genLoopBegin: invalid Loop Graph"); + + OutLineInfo(output,q->line,FileStr[q->file]); + + BLOCK_Preamble(q); + BlkLevel++; + BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */ + f = First(q, 1, aLoopBegin, &max_k); + /* If not simple LL(1), must specify to start at LoopBegin, not LoopBlk */ + if ( LL_k>1 && !set_nil(q->fset[2]) ) + genLoopBlk( q, (Junction *)q->p1, q, max_k ); + else genLoopBlk( q, (Junction *)q->p1, NULL, max_k ); + + for (i=1; i<=CLL_k; i++) set_free(q->fset[i]); + for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]); + --BlkLevel; + BLOCK_Tail(); + set_free(f); + tokensRefdInBlock = savetkref; +/* MR21 */ if (MR_BlkErr) { +/* MR21 */ set f, fArray[2]; +/* MR21 */ f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ ); +/* MR21 */ fArray[0]= empty; +/* MR21 */ fArray[1]= set_dup(f); +/* MR21 */ gen("if ("); +/* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */ +/* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n"); +/* MR21 */ tabs++; +/* MR21 */ tab(); +/* MR21 */ _gen("/* nothing */ }\n"); +/* MR21 */ tab(); +/* MR21 */ makeErrorClause(q,f,1,0 /* use plus block bypass ? */ ); /* frees set */ +/* MR21 */ tabs--; +/* MR21 */ }; + if (q->end->p1 != NULL) TRANS(q->end->p1); +} + +/* + * Generate code for a loop blk of form: + * + * |---| + * v | + * --o-G-o-->o-- + * + * q->end points to the last node (far right) in the blk. + * Note that q->end->jtype must be 'EndBlk'. + * + * Generate code roughly of the following form: + * + * do { + * ... code for alternatives ... + * } while ( First Set of aPlusBlk ); + * + * OR if > 1 alternative + * + * do { + * ... code for alternatives ... + * else if not 1st time through, break; + * } while ( 1 ); + */ +void +#ifdef __USE_PROTOS +genPlusBlk( Junction *q ) +#else +genPlusBlk( q ) +Junction *q; +#endif +{ + int max_k; + set f; + int need_right_curly; + int lastAltEmpty; /* MR23 */ + set savetkref; + Junction *guessBlock; /* MR10 */ + int singleAlt; /* MR10 */ + + savetkref = tokensRefdInBlock; + require(q!=NULL, "genPlusBlk: invalid node and/or rule"); + require(q->ntype == nJunction, "genPlusBlk: not junction"); + require(q->jtype == aPlusBlk, "genPlusBlk: not Plus block"); + require(q->p2 != NULL, "genPlusBlk: not a valid Plus block"); + + if ( q->visited ) return; + q->visited = TRUE; + OutLineInfo(output,q->line,FileStr[q->file]); + BLOCK_Preamble(q); + BlkLevel++; + + BlockPreambleOption((Junction *)q, q->pFirstSetSymbol); /* MR21 */ + + /* first_item_is_guess_block doesn't care what kind of node it is */ + + guessBlock=first_item_is_guess_block( (Junction *)q->p1); /* MR10 */ + + /* if the ignore flag is set on the 2nd alt and that alt is empty, + * then it is the implied optional alternative that we added for (...)+ + * and, hence, only 1 alt. + */ + +/* MR10 Reported by Pulkkinen Esa (esap@cs.tut.fi) + * Outer code for guess blocks ignored when there is only one alt + * for a (...)+ block. + * Force use of regular code rather than "optimized" code for that case + */ + + singleAlt=( ( (Junction *) q->p2)->p2 == NULL) && + ( ( (Junction *) q->p2)->ignore ); /* only one alternative? */ + + if (singleAlt && !guessBlock) /* MR10 */ + { + + Predicate *a=NULL; + /* if the only alt has a semantic predicate, hoist it; must test before + * entering loop. + */ + if ( ParseWithPredicates ) + { + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + a = MR_find_predicates_and_supp((Node *)q); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + + if ( a!=NULL ) { + gen("if ("); + a=genPredTreeMain(a, (Node *)q); /* MR10 */ + _gen(") {\n"); + } + } + gen("do {\n"); + tabs++; + TRANS(q->p1); + if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1); + f = First(q, 1, aPlusBlk, &max_k); + if ( DemandLookahead ) { + if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);} + else gen1("look(%d);\n", max_k); + } + --tabs; + gen("} while ( "); + if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm); + genExpr(q); + if ( ParseWithPredicates && a!=NULL ) + { + if (! MR_comparePredicates(q->predicate,a)) { + _gen("&&"); + a=genPredTreeMain(a, (Node *)q); /* MR10 */ + }; + } + _gen(" );\n"); + if ( ParseWithPredicates && a!=NULL ) gen("}\n"); + --BlkLevel; + BLOCK_Tail(); + q->visited = FALSE; + freeBlkFsets(q); + set_free(f); + tokensRefdInBlock = savetkref; +/* MR21 */ if (MR_BlkErr) { +/* MR21 */ set f, fArray[2]; +/* MR21 */ f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ ); +/* MR21 */ fArray[0]= empty; +/* MR21 */ fArray[1]= set_dup(f); +/* MR21 */ gen("if ("); +/* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */ +/* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n"); +/* MR21 */ tabs++; +/* MR21 */ tab(); +/* MR21 */ _gen("/* nothing */ }\n"); +/* MR21 */ tab(); +/* MR21 */ makeErrorClause(q,f,1,1 /* use plus block bypass ? */ ); /* frees set */ +/* MR21 */ tabs--; +/* MR21 */ }; + if (q->end->p1 != NULL) TRANS(q->end->p1); +/* MR10 */ if (MRhoisting) { +/* MR10 */ predicate_free(a); +/* MR10 */ }; + return; + } + gen("do {\n"); + tabs++; + f = genBlk(q, aPlusBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); +/* MR6 */ +/* MR6 Sinan Karasu (sinan@tardis.ds.boeing.com) */ +/* MR6 Failed to turn off guess mode when leaving block */ +/* MR6 */ +/* MR6 */ if ( has_guess_block_as_last_item(q) ) { +/* MR10 */ gen("/* MR10 ()+ */ else {\n"); +/* MR10 */ tabs++; +/* MR10 */ need_right_curly++; +/* MR10 */ gen("/* MR10 ()+ */ if ( !zzrv ) zzGUESS_DONE;\n"); +/* MR6 */ gen("/* MR10 ()+ */ if ( zzcnt > 1 ) break;\n"); +/* MR10 */ } else { +/* MR10 */ gen("/* MR10 ()+ */ else {\n"); +/* MR10 */ tabs++; +/* MR10 */ need_right_curly++; +/* MR10 */ gen("if ( zzcnt > 1 ) break;\n"); +/* MR10 */ }; + +/* MR21 */ if (MR_BlkErr && 1 >= max_k) { +/* MR21 */ set f; +/* MR21 */ f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ ); +/* MR21 */ tabs++; +/* MR21 */ tab(); +/* MR21 */ makeErrorClause(q,f,1,0 /* use plus block bypass ? */ ); /* frees set */ +/* MR21 */ tabs--; +/* MR21 */ } +/* MR21 */ else { + tab(); + makeErrorClause(q,f,max_k,1 /* use plus block bypass ? */); + /* MR21 I think this generates the wrong set ? */ + /* MR21 because it includes the plus block bypass ? */ + /* MR21 but I'm afraid to change it without additional checking */ + } + + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets(q); + gen("zzcnt++;"); + if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1); + _gen("\n"); + if ( DemandLookahead ) { + if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);} + else gen1("look(%d);\n", max_k); + } + --tabs; + if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);} + else gen("} while ( 1 );\n"); + --BlkLevel; + BLOCK_Tail(); + q->visited = FALSE; + tokensRefdInBlock = savetkref; +/* MR21 */ if (MR_BlkErr) { +/* MR21 */ set f, fArray[2]; +/* MR21 */ f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ ); +/* MR21 */ fArray[0]= empty; +/* MR21 */ fArray[1]= set_dup(f); +/* MR21 */ gen("if ("); +/* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */ +/* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n"); +/* MR21 */ tabs++; +/* MR21 */ tab(); +/* MR21 */ _gen("/* nothing */ }\n"); +/* MR21 */ tab(); +/* MR21 */ makeErrorClause(q,f,1,1 /* use plus block bypass ? */ ); /* frees set */ +/* MR21 */ tabs--; +/* MR21 */ }; + if (q->end->p1 != NULL) TRANS(q->end->p1); +} + +/* + * Generate code for a sub blk of alternatives of form: + * + * --o-G1--o-- + * | ^ + * v /| + * o-G2-o| + * | ^ + * v | + * .......... + * | ^ + * v / + * o-Gn-o + * + * q points to the 1st junction of blk (upper-left). + * q->end points to the last node (far right) in the blk. + * Note that q->end->jtype must be 'EndBlk'. + * The last node in every alt points to q->end. + * + * Generate code of the following form: + * if ( First(G1) ) { + * ...code for G1... + * } + * else if ( First(G2) ) { + * ...code for G2... + * } + * ... + * else { + * ...code for Gn... + * } + */ + +void +#ifdef __USE_PROTOS +genSubBlk( Junction *q ) +#else +genSubBlk( q ) +Junction *q; +#endif +{ + int max_k; + set f; + int need_right_curly; + int lastAltEmpty; /* MR23 */ + set savetkref; + savetkref = tokensRefdInBlock; + require(q->ntype == nJunction, "genSubBlk: not junction"); + require(q->jtype == aSubBlk, "genSubBlk: not subblock"); + + OutLineInfo(output,q->line,FileStr[q->file]); + BLOCK_Preamble(q); + BlkLevel++; + BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */ + f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); + +/* MR23 + Bypass error clause generation when exceptions are used in a sub block + in which the last alternative is epsilon. Example: "(A | B | )". + See multi-line note in genBlk near call to isEmptyAlt. +*/ + if (FoundException && lastAltEmpty) { + gen("/* MR23 skip error clause for (...| epsilon) when exceptions in use */\n"); + } + else { + if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );} + } + + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets(q); + --BlkLevel; + BLOCK_Tail(); + + if ( q->guess ) + { + gen("zzGUESS_DONE\n"); + } + + /* must duplicate if (alpha)?; one guesses (validates), the + * second pass matches */ + if ( q->guess && analysis_point(q)==q ) + { + OutLineInfo(output,q->line,FileStr[q->file]); + BLOCK_Preamble(q); + BlkLevel++; + f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); + if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */);} + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets(q); + --BlkLevel; + BLOCK_Tail(); + } + + tokensRefdInBlock = savetkref; + if (q->end->p1 != NULL) TRANS(q->end->p1); +} + +static int TnodesAllocatedPrevRule=0; + +/* + * Generate code for a rule. + * + * rule--> o-->o-Alternatives-o-->o + * Or, + * rule--> o-->o-Alternative-o-->o + * + * The 1st junction is a RuleBlk. The second can be a SubBlk or just a junction + * (one alternative--no block), the last is EndRule. + * The second to last is EndBlk if more than one alternative exists in the rule. + * + * To get to the init-action for a rule, we must bypass the RuleBlk, + * and possible SubBlk. + * Mark any init-action as generated so genBlk() does not regenerate it. + */ +void +#ifdef __USE_PROTOS +genRule( Junction *q ) +#else +genRule( q ) +Junction *q; +#endif +{ + + const char * returnValueInitializer; + +do { /* MR10 Change recursion into iteration */ + + int max_k; + set follow, rk, f; + ActionNode *a; + RuleEntry *r; + int lastAltEmpty; /* MR23 */ + static int file = -1; + int need_right_curly; + require(q->ntype == nJunction, "genRule: not junction"); + require(q->jtype == RuleBlk, "genRule: not rule"); + +/* MR14 */ require (MR_BackTraceStack.count == 0,"-alpha MR_BackTraceStack.count != 0"); +/* MR14 */ MR_pointerStackReset(&MR_BackTraceStack); +/* MR14 */ if (AlphaBetaTrace) MR_MaintainBackTrace=1; + + CurRule=q->rname; /* MR11 */ + + r = (RuleEntry *) hash_get(Rname, q->rname); + if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief"); + if ( q->file != file ) /* open new output file if need to */ + { +/* MR6 */ +/* MR6 Simpler to debug when output goes to stdout rather than a file */ +/* MR6 */ +/* MR6 */ if (UseStdout) { +/* MR6 */ output = stdout; +/* MR6 */ } else { +/* MR6 */ if ( output != NULL) fclose( output ); +/* MR6 */ output = fopen(OutMetaName(outname(FileStr[q->file])), "w"); +/* MR6 */ }; + require(output != NULL, "genRule: can't open output file"); + +#ifdef SPECIAL_FOPEN + special_fopen_actions(OutMetaName(outname(FileStr[q->file]))); /* MR1 */ +#endif + if ( file == -1 ) genHdr1(q->file); + else genHdr(q->file); + file = q->file; + } + + if (InfoM) { + fprintf(stderr," rule %s\n",q->rname); + fflush(output); + }; + +#if 0 + if (strcmp(q->rname,"***debug***") == 0) { + fprintf(stderr,"***debug*** %s reached\n",q->rname); + MR_break(); + }; +#endif + + DumpFuncHeader(q,r); + tabs++; + + /* MR23 + + If there is a single return value then it can be initialized in + the declaration using assignment syntax. If there are multiple + return values then antlr creates a struct and initialization takes + place element by element for each element of the struct. For + multiple elements the initialization is by assignment so we have + to wait until all declarations are done before emitting that code - + because of restrictions in C which don't exist in C++. + + In the past (before MR23) the only kind of initialization was + the PURIFY macro which was just a memset() of 0. Now we allow + the user to specify an initial value. PURIFY is still used in C + mode because C does not have constructors. However, PURIFY is + not used in C++ mode because it might overwrite information created + by elements which have their own ctor. + + */ + + if ( q->ret!=NULL ) + { + if ( hasMultipleOperands(q->ret) ) /* MR23 */ + { + + /* Emit initialization code later. */ + + gen1("struct _rv%d _retv;\n",r->rulenum); + } + else + { + /* Emit initialization code now. */ + + tab(); + DumpType(q->ret, output); + returnValueInitializer = getInitializer(q->ret); + if (returnValueInitializer == NULL) { /* MR23 */ + gen(" _retv;\n"); /* MR1 MR3 */ + } /* MR23 */ + else { /* MR23 */ + gen1(" _retv = %s;\n", returnValueInitializer); /* MR23 */ + } /* MR23 */ + } + } + + OutLineInfo(output,q->line,FileStr[q->file]); + + if (InfoM) { + fflush(output); + }; + + gen("zzRULE;\n"); + if ( FoundException ) + { + gen("int _sva=1;\n"); + } + if ( GenCC && GenAST ) + gen("ASTBase *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n"); + if ( GenCC ) genTokenPointers(q); + if ( GenCC&&GenAST ) genASTPointers(q); + if ( q->el_labels!=NULL ) genElementLabels(q->el_labels); + if ( FoundException ) gen("int _signal=NoSignal;\n"); + + if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel); + +/* MR10 */ /* move zzTRACEIN to before init action */ + +/* MR10 */ if ( TraceGen ) { +/* MR10 */ if ( GenCC ) {gen1("zzTRACEIN(\"%s\");\n", q->rname);} +/* MR10 */ else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname); +/* MR10 */ } + +/* MR7 Moved PURIFY() to after all local variables have been declared */ +/* MR7 so that the generated code is valid C as well as C++ */ +/* MR7 Jan Mikkelsen 10-June-1997 */ + + + /* + MR23 Do the PURIFY macro only for C mode. + C++ users should use constructors or initialization expressions. + */ + + if ( q->ret != NULL ) /* MR7 */ + { /* MR7 */ + if (hasMultipleOperands(q->ret)) { /* MR23 */ + if (PURIFY == TRUE) { + gen1("PCCTS_PURIFY(_retv,sizeof(struct _rv%d))\n",r->rulenum); /* MR23 */ + } + } /* MR7 */ + else { /* MR7 */ + + /* MR23 + If there were only one return value operand and + it had an initializer then it would have been + initiailized in the declaration. + */ + + returnValueInitializer = getInitializer(q->ret); /* MR23 */ + if (returnValueInitializer == NULL) { /* MR23 */ + if (PURIFY == TRUE) { + gen("PCCTS_PURIFY(_retv,sizeof("); /* MR23 */ + DumpType(q->ret, output); /* MR7 */ + gen("))\n"); /* MR7 */ + } + } /* MR23 */ + } /* MR7 */ + + if (hasMultipleOperands(q->ret)) { /* MR23 */ + DumpInitializers(output, r, q->ret); /* MR23 */ + } + + } + if ( !GenCC ) gen("zzMake0;\n"); + if ( FoundException ) gen("*_retsignal = NoSignal;\n"); + + if ( !GenCC ) gen("{\n"); + + if ( has_guess_block_as_first_item((Junction *)q->p1) ) + { + gen("zzGUESS_BLOCK\n"); + } + + /* L o o k F o r I n i t A c t i o n */ + if ( ((Junction *)q->p1)->jtype == aSubBlk ) + a = findImmedAction( ((Junction *)q->p1)->p1 ); + else + a = findImmedAction( q->p1 ); /* only one alternative in rule */ + if ( a!=NULL && !a->is_predicate) + { + /* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1); + a->done = 1; /* ignore action. We have already handled it */ + } + + BlkLevel++; + q->visited = TRUE; /* mark RULE as visited for FIRST/FOLLOW */ + BlockPreambleOption((Junction *)q->p1, NULL); /* MR21 */ + f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); + if ( q->p1 != NULL ) + if ( ((Junction *)q->p1)->p2 != NULL ) + {tab(); makeErrorClause((Junction *)q->p1,f,max_k,0 /* use plus block bypass ? */);} + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets((Junction *)q->p1); + q->visited = FALSE; + --BlkLevel; + if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel); + + genTraceOut(q); + + if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n"); + /* E r r o r R e c o v e r y */ + NewSet(); + rk = empty; + +/* MR14 */ if (r->dontComputeErrorSet) { +/* MR14 */ follow=empty; + } else { + MR_pointerStackReset(&MR_BackTraceStack); /* MR14 */ + MR_ErrorSetComputationActive=1; + REACH(q->end, 1, &rk, follow); + MR_ErrorSetComputationActive=0; + require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0"); + } + + FillSet( follow ); + set_free( follow ); + + /* MR20 G. Hobbelt + Isn't it so that "fail:" is ONLY referenced when: + + !FoundException || FoundGuessBlk ? + + Therefore add the "if" around this piece of code generation... + + Should guessing mode also use _handler label instead of "fail" + when exception handling is active? gen can automatically put + "if (guessing)" there so as to skip all kinds of user code. + + */ + + if ( !FoundException || FoundGuessBlk ) /* MR20 G. Hobbelt */ + { /* MR20 G. Hobbelt */ + _gen("fail:\n"); + if ( !GenCC ) gen("zzEXIT(zztasp1);\n"); + if ( FoundGuessBlk ) { + if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");} + else gen("if ( guessing ) zzGUESS_FAIL;\n"); + } + if ( q->erraction!=NULL ) + dumpAction(q->erraction, output, tabs, q->file, q->line, 1); + if ( GenCC ) + { + gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n", + r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup); + } + else + { + gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n", + r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup); + } + gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<ret!=NULL ) { + genTraceOut(q); + gen("return _retv;\n"); + } else if ( q->exceptions!=NULL ) { + genTraceOut(q); + gen("return;\n"); + } else if (!FoundException) { /* MR10 */ + genTraceOut(q); /* MR10 */ + }; + + } /* MR20 G. Hobbelt */ + + if ( !GenCC ) gen("}\n"); + + /* Gen code for exception handlers */ + /* make sure each path out contains genTraceOut() */ + + if ( q->exceptions!=NULL ) + { + + gen("/* exception handlers */\n"); + + dumpExceptions(q->exceptions); + + if ( !r->has_rule_exception ) + { + _gen("_handler:\n"); + gen("zzdflthandlers(_signal,_retsignal);\n"); + } +/* MR20 G. Gobbelt The label "adios" is never referenced */ + +#if 0 + _gen("_adios:\n"); +#endif + if ( q->ret!=NULL ) { + genTraceOut(q); + gen("return _retv;\n"); + } + else { + genTraceOut(q); + gen("return;\n"); + } + } + else if ( FoundException ) + { + _gen("_handler:\n"); + gen("zzdflthandlers(_signal,_retsignal);\n"); + +/* MR1 */ +/* MR1 7-Apr-97 Fix suggested by: John Bair (jbair@iftime.com) */ +/* MR1 */ + + if ( q->ret != NULL) { /* MR1 */ + genTraceOut(q); /* MR10 */ + gen("return _retv;\n"); /* MR1 */ + } else { /* MR1 */ + genTraceOut(q); /* MR10 */ + gen("return;\n") ; /* MR1 */ + }; /* MR1 */ + } + + tabs--; + gen("}\n"); + +/* MR10 Tired of looking at stacks that are as deep as the number of */ +/* MR10 rules. Changes recursion to iteration. */ + + MR_releaseResourcesUsedInRule( (Node *) q ); /* MR10 */ + + if (InfoT) { + fprintf(output,"\n/* tnodes created for rule %s: %d */\n", + q->rname, (TnodesAllocated-TnodesAllocatedPrevRule) ); + }; + + TnodesAllocatedPrevRule=TnodesAllocated; + + if (q->p2 == NULL) dumpAfterActions( output ); + q=(Junction *)q->p2; + require(q==NULL || q->jtype==RuleBlk,"RuleBlk p2 does not point to another RuleBlk"); + +} while (q != NULL); + +/**** The old code ****/ +/**** if ( q->p2 != NULL ) {TRANS(q->p2);} ****/ /* generate code for next rule too */ +/**** else dumpAfterActions( output ); ****/ + +} + + +/* This is for the function definition, not the declaration. */ + +static void +#ifdef __USE_PROTOS +DumpFuncHeader( Junction *q, RuleEntry *r ) +#else +DumpFuncHeader( q, r ) +Junction *q; +RuleEntry *r; +#endif +{ +/* */ +/* MR1 10-Apr-97 MR1 Simplify insertion of commas in function header */ +/* */ + int needComma; /* MR1 */ + + + /* A N S I */ + _gen("\n"); + if ( q->ret!=NULL ) + { + if ( hasMultipleOperands(q->ret) ) /* MR23 */ + { + if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum) + else gen1("struct _rv%d\n",r->rulenum); + } + else + { + DumpType(q->ret, output); + gen("\n"); + } + } + else + { + _gen("void\n"); + } +/* MR1 */ +/* MR1 10-Apr-97 133MR1 Replace __STDC__ with __USE_PROTOS */ +/* MR1 */ + if ( !GenCC ) _gen("#ifdef __USE_PROTOS\n"); /* MR1 */ + if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname) + else gen3("%s::%s%s(", CurrentClassName, RulePrefix,q->rname); + + /* If we generate C++ method names, we must hide default arguments */ + /* which can appear in the parameter declaration list. */ + /* NOTICE: this is done only here, for the method definition, but */ + /* not for the method declaration inside the class */ + /* definition. This is exactly the behaviour defined in */ + /* C++ standard for default paramters. */ + + DumpANSIFunctionArgDef(output,q, 0 /* emit initializers ? */); + _gen("\n"); + + if ( GenCC ) { + gen("{\n"); + return; + } + + /* K & R */ + gen("#else\n"); + gen2("%s%s(", RulePrefix, q->rname); + needComma=0; /* MR1 */ + if ( GenAST ) /* MR1 */ + { /* MR1 */ + _gen("_root"); /* MR1 */ + needComma=1; /* MR1 */ + } /* MR1 */ + if ( FoundException ) /* MR1 */ + { /* MR1 */ + if (needComma) {_gen(",");needComma=0;}; /* MR1 */ + _gen("_retsignal"); /* MR1 */ + needComma=1; /* MR1 */ + } /* MR1 */ +/* MR5 Change below by Jan Mikkelsen (janm@zeta.org.au) 26-May-97 MR5 */ + DumpListOfParmNames( q->pdecl, output, needComma ); /* MR5 */ + gen(")\n"); + if ( GenAST ) gen("AST **_root;\n"); + if ( FoundException ) gen("int *_retsignal;\n"); + DumpOldStyleParms( q->pdecl, output ); + gen("#endif\n"); + gen("{\n"); +} + +void +#ifdef __USE_PROTOS +DumpANSIFunctionArgDef(FILE *f, Junction *q, int bInitializer) +#else +DumpANSIFunctionArgDef(f,q,bInitializer) +FILE *f; +Junction *q; +int bInitializer; +#endif +{ + if ( GenAST ) + { + if ( GenCC ) {fprintf(f,"ASTBase **_root");} + else fprintf(f,"AST**_root"); + if ( !FoundException && q->pdecl!=NULL ) fprintf(f,","); + } + if ( FoundException ) + { + if ( GenAST ) fprintf(f,","); + fprintf(f,"int *_retsignal"); + if ( q->pdecl!=NULL ) { + fprintf(f,","); + } + } + if ( q->pdecl!=NULL ) { + DumpFormals(f, q->pdecl, bInitializer); /* MR23 */ + } + else { + if ( !GenAST && !FoundException ) { + fprintf(f,"void"); + } + } + fprintf(f,")"); +} + +void +#ifdef __USE_PROTOS +genJunction( Junction *q ) +#else +genJunction( q ) +Junction *q; +#endif +{ + require(q->ntype == nJunction, "genJunction: not junction"); + require(q->jtype == Generic, "genJunction: not generic junction"); + + if ( q->p1 != NULL ) TRANS(q->p1); + if ( q->p2 != NULL ) TRANS(q->p2); +} + +void +#ifdef __USE_PROTOS +genEndBlk( Junction *q ) +#else +genEndBlk( q ) +Junction *q; +#endif +{ +} + +void +#ifdef __USE_PROTOS +genEndRule( Junction *q ) +#else +genEndRule( q ) +Junction *q; +#endif +{ +} + +void +#ifdef __USE_PROTOS +genHdr( int file ) +#else +genHdr( file ) +int file; +#endif +{ + int i; + + _gen("/*\n"); + _gen(" * A n t l r T r a n s l a t i o n H e a d e r\n"); + _gen(" *\n"); + _gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n"); + _gen(" * Purdue University Electrical Engineering\n"); + _gen(" * With AHPCRC, University of Minnesota\n"); + _gen1(" * ANTLR Version %s\n", Version); + _gen(" *\n"); +/* MR10 */ _gen(" * "); +/* MR10 */ for (i=0 ; i < Save_argc ; i++) { +/* MR10 */ _gen(" "); +/* MR10 */ _gen(Save_argv[i]); +/* MR10 */ }; + _gen("\n"); + _gen(" *\n"); + _gen(" */\n\n"); + if (FirstAction != NULL ) dumpAction( FirstAction, output, 0, -1, 0, 1); /* MR11 MR15b */ + _gen1("#define ANTLR_VERSION %s\n", VersionDef); + _gen("#include \"pcctscfg.h\"\n"); + _gen("#include \"pccts_stdio.h\"\n"); + if ( strcmp(ParserName, DefaultParserName)!=0 ) + _gen2("#define %s %s\n", DefaultParserName, ParserName); + if ( strcmp(ParserName, DefaultParserName)!=0 ) + {_gen1("#include \"%s\"\n", RemapFileName);} + OutLineInfo(output,1,FileStr[file]); + if ( GenCC ) { + if ( UserTokenDefsFile != NULL ) + fprintf(output, "#include %s\n", UserTokenDefsFile); + else + fprintf(output, "#include \"%s\"\n", DefFileName); + } + + if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1); + if ( !GenCC && FoundGuessBlk ) + { + _gen("#define ZZCAN_GUESS\n"); + _gen("#include \"pccts_setjmp.h\"\n"); /* MR15 K.J. Cummings (cummings@peritus.com) */ + } + if ( FoundException ) + { + _gen("#define EXCEPTION_HANDLING\n"); + _gen1("#define NUM_SIGNALS %d\n", NumSignals); + } + if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k); + if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n"); + if ( GenAST ) { + if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);} + else _gen("#include \"ast.h\"\n\n"); + } + if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n"); +#ifdef DUM + if ( !GenCC && LexGen ) { + _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken)); + } +#endif + /* ###WARNING: This will have to change when SetWordSize changes */ + if ( !GenCC ) _gen1("#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned)); + if (TraceGen) { + _gen("#ifndef zzTRACE_RULES\n"); /* MR20 */ + _gen("#define zzTRACE_RULES\n"); /* MR20 */ + _gen("#endif\n"); /* MR22 */ + }; + if ( !GenCC ) {_gen("#include \"antlr.h\"\n");} + else { + _gen1("#include \"%s\"\n", APARSER_H); + _gen1("#include \"%s.h\"\n", CurrentClassName); + } + if ( !GenCC ) { + if ( UserDefdTokens ) + {_gen1("#include %s\n", UserTokenDefsFile);} + /* still need this one as it has the func prototypes */ + _gen1("#include \"%s\"\n", DefFileName); + } + /* still need this one as it defines the DLG interface */ + if ( !GenCC ) _gen("#include \"dlgdef.h\"\n"); + if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H); + if ( GenCC ) _gen1("#include \"%s\"\n", ATOKPTR_H); + if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName); + +/* MR10 Ofer Ben-Ami (gremlin@cs.huji.ac.il) */ +/* MR10 Finally, a definition of the Purify macro */ + + if (PURIFY == TRUE) { /* MR23 */ + _gen("\n/* MR23 In order to remove calls to PURIFY use the antlr"); /* MR23 */ + _gen(" -nopurify option */\n\n"); /* MR23 */ + _gen("#ifndef PCCTS_PURIFY\n"); + _gen("#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\\0',(s));\n"); + _gen("#endif\n\n"); + } /* MR23 */ +} + +void +#ifdef __USE_PROTOS +genHdr1( int file ) +#else +genHdr1( file ) +int file; +#endif +{ + ListNode *p; + + genHdr(file); + if ( GenAST ) + { + if ( !GenCC ) { + _gen("#include \"ast.c\"\n"); + _gen("zzASTgvars\n\n"); + } + } + if ( !GenCC ) _gen("ANTLR_INFO\n"); + if ( BeforeActions != NULL ) + { + for (p = BeforeActions->next; p!=NULL; p=p->next) + { + UserAction *ua = (UserAction *)p->elem; + dumpAction( ua->action, output, 0, ua->file, ua->line, 1); + } + } + + if ( !FoundException ) return; + + if ( GenCC ) + { + _gen1("\nvoid %s::\n", CurrentClassName); + _gen("zzdflthandlers( int _signal, int *_retsignal )\n"); + _gen("{\n"); + } + else + { + _gen("\nvoid\n"); +/* MR1 */ +/* MR1 10-Apr-97 133MR1 Replace __STDC__ with __USE_PROTOS */ +/* MR1 */ + _gen("#ifdef __USE_PROTOS\n"); /* MR1 */ + _gen("zzdflthandlers( int _signal, int *_retsignal )\n"); + _gen("#else\n"); + _gen("zzdflthandlers( _signal, _retsignal )\n"); + _gen("int _signal;\n"); + _gen("int *_retsignal;\n"); + _gen("#endif\n"); + _gen("{\n"); + } + tabs++; + if ( DefaultExGroup!=NULL ) + { + dumpException(DefaultExGroup, 1); + if ( !hasDefaultException(DefaultExGroup) ) + { + gen("default :\n"); + tabs++; + gen("*_retsignal = _signal;\n"); + tabs--; + gen("}\n"); + } + } + else { + gen("*_retsignal = _signal;\n"); + } + + tabs--; + _gen("}\n\n"); +} + +void +#ifdef __USE_PROTOS +genStdPCCTSIncludeFile( FILE *f,char *gate ) /* MR10 */ +#else +genStdPCCTSIncludeFile( f , gate) /* MR10 */ +FILE *f; +char * gate; /* MR10 */ +#endif +{ +/* MR10 Ramanathan Santhanam (ps@kumaran.com) */ +/* MR10 Same preprocessor symbol use to gate stdpccts.h */ +/* MR10 even when two grammars are in use. */ +/* MR10 Derive gate symbol from -fh filename */ + + if (gate == NULL) { + fprintf(f,"#ifndef STDPCCTS_H\n"); /* MR10 */ + fprintf(f,"#define STDPCCTS_H\n"); /* MR10 */ + } else { + fprintf(f,"#ifndef STDPCCTS_%s_H\n",gate); /* MR10 */ + fprintf(f,"#define STDPCCTS_%s_H\n",gate); /* MR10 */ + }; + fprintf(f,"/*\n"); + if (gate == NULL) { + fprintf(f," * %s -- P C C T S I n c l u d e\n", stdpccts); + } else { + fprintf(f," * Standard PCCTS include file with -fh %s -- P C C T S I n c l u d e\n", stdpccts); + } + fprintf(f," *\n"); + fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n"); + fprintf(f," * Purdue University Electrical Engineering\n"); + fprintf(f," * With AHPCRC, University of Minnesota\n"); + fprintf(f," * ANTLR Version %s\n", Version); + fprintf(f," */\n\n"); + + fprintf(f,"#ifndef ANTLR_VERSION\n"); + fprintf(f,"#define ANTLR_VERSION %s\n", VersionDef); + fprintf(f,"#endif\n\n"); + + if (FirstAction != NULL ) dumpAction(FirstAction, f, 0, -1, 0, 1); /* MR11 */ + + fprintf(f,"#include \"pcctscfg.h\"\n"); + fprintf(f,"#include \"pccts_stdio.h\"\n"); + if ( GenCC ) + { + if ( UserDefdTokens ) + fprintf(f, "#include %s\n", UserTokenDefsFile); + else { + fprintf(f, "#include \"%s\"\n", DefFileName); + } + + fprintf(f, "#include \"%s\"\n", ATOKEN_H); + + if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1); + + fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H); + + if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k); + if ( GenAST ) { + fprintf(f, "#include \"%s\"\n", ASTBASE_H); + } + + if (TraceGen) { + fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#endif\n"); /* MR22 */ + }; + + fprintf(f,"#include \"%s\"\n", APARSER_H); + fprintf(f,"#include \"%s.h\"\n", CurrentClassName); + if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H); + fprintf(f, "#endif\n"); + return; + } + + if ( strcmp(ParserName, DefaultParserName)!=0 ) + fprintf(f, "#define %s %s\n", DefaultParserName, ParserName); + if ( strcmp(ParserName, DefaultParserName)!=0 ) + fprintf(f, "#include \"%s\"\n", RemapFileName); + if ( UserTokenDefsFile != NULL ) + fprintf(f, "#include %s\n", UserTokenDefsFile); + if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1); + if ( FoundGuessBlk ) + { + fprintf(f,"#define ZZCAN_GUESS\n"); + fprintf(f,"#include \"pccts_setjmp.h\"\n"); + } + if (TraceGen) { + fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#endif\n"); /* MR22 */ + }; + if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k); + if ( GenAST ) fprintf(f,"#define GENAST\n"); + if ( FoundException ) + { +/* MR1 7-Apr-97 1.33MR1 */ +/* MR1 Fix suggested by: */ +/* MR1 Francois-Xavier Fontaine (fontaine_f@istvax.ist.lu) */ + + fprintf(f,"#define EXCEPTION_HANDLING\n"); /* MR1 */ + fprintf(f,"#define NUM_SIGNALS %d\n", NumSignals); /* MR1 */ + } + if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n"); +#ifdef DUM + if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken)); +#endif + /* ###WARNING: This will have to change when SetWordSize changes */ + fprintf(f, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)*sizeof(unsigned)); + if (TraceGen) { + fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#endif\n"); /* MR22 */ + }; + fprintf(f,"#include \"antlr.h\"\n"); + if ( GenAST ) fprintf(f,"#include \"ast.h\"\n"); + if ( UserDefdTokens ) + fprintf(f, "#include %s\n", UserTokenDefsFile); + /* still need this one as it has the func prototypes */ + fprintf(f, "#include \"%s\"\n", DefFileName); + /* still need this one as it defines the DLG interface */ + fprintf(f,"#include \"dlgdef.h\"\n"); + /* don't need this one unless DLG is used */ + if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName); + fprintf(f,"#endif\n"); +} + +/* dump action 's' to file 'output' starting at "local" tab 'tabs' + Dump line information in front of action if GenLineInfo is set + If file == -1 then GenLineInfo is ignored. + The user may redefine the LineInfoFormatStr to his/her liking + most compilers will like the default, however. + + June '93; changed so that empty lines are left alone so that + line information is correct for the compiler/debuggers. +*/ +void +#ifdef __USE_PROTOS +dumpAction( char *s, FILE *output, int tabs, int file, int line, +int final_newline ) +#else +dumpAction( s, output, tabs, file, line, final_newline ) +char *s; +FILE *output; +int tabs; +int file; +int line; +int final_newline; +#endif +{ + int inDQuote, inSQuote; + require(s!=NULL, "dumpAction: NULL action"); + require(output!=NULL, eMsg1("dumpAction: output FILE is NULL for %s",s)); + + if ( GenLineInfo && file != -1 ) + { + OutLineInfo(output,line,FileStr[file]); + } + PastWhiteSpace( s ); + /* don't print a tab if first non-white char is a # (preprocessor command) */ + if ( *s!='#' ) {TAB;} + inDQuote = inSQuote = FALSE; + while ( *s != '\0' ) + { + if ( *s == '\\' ) + { + fputc( *s++, output ); /* Avoid '"' Case */ + if ( *s == '\0' ) return; + if ( *s == '\'' ) fputc( *s++, output ); + if ( *s == '\"' ) fputc( *s++, output ); + } + if ( *s == '\'' ) + { + if ( !inDQuote ) inSQuote = !inSQuote; + } + if ( *s == '"' ) + { + if ( !inSQuote ) inDQuote = !inDQuote; + } + if ( *s == '\n' ) + { + fputc('\n', output); + s++; + PastWhiteSpace( s ); + if ( *s == '}' ) + { + --tabs; + TAB; + fputc( *s++, output ); + continue; + } + if ( *s == '\0' ) return; + if ( *s != '#' ) /* #define, #endif etc.. start at col 1 */ + { + TAB; + } + } + if ( *s == '}' && !(inSQuote || inDQuote) ) + { + --tabs; /* Indent one fewer */ + } + if ( *s == '{' && !(inSQuote || inDQuote) ) + { + tabs++; /* Indent one more */ + } + fputc( *s, output ); + s++; + } + if ( final_newline ) fputc('\n', output); +} + +static void +#ifdef __USE_PROTOS +dumpAfterActions( FILE *output ) +#else +dumpAfterActions( output ) +FILE *output; +#endif +{ + ListNode *p; + require(output!=NULL, "dumpAfterActions: output file was NULL for some reason"); + if ( AfterActions != NULL ) + { + for (p = AfterActions->next; p!=NULL; p=p->next) + { + UserAction *ua = (UserAction *)p->elem; + dumpAction( ua->action, output, 0, ua->file, ua->line, 1); + } + } + fclose( output ); +} + +/* + * Find the next action in the stream of execution. Do not pass + * junctions with more than one path leaving them. + * Only pass generic junctions. + * + * Scan forward while (generic junction with p2==NULL) + * If we stop on an action, return ptr to the action + * else return NULL; + */ +static ActionNode * +#ifdef __USE_PROTOS +findImmedAction( Node *q ) +#else +findImmedAction( q ) +Node *q; +#endif +{ + Junction *j; + require(q!=NULL, "findImmedAction: NULL node"); + require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node"); + + while ( q->ntype == nJunction ) + { + j = (Junction *)q; + if ( j->jtype != Generic || j->p2 != NULL ) return NULL; + q = j->p1; + if ( q == NULL ) return NULL; + } + if ( q->ntype == nAction ) return (ActionNode *)q; + return NULL; +} + +static void +#ifdef __USE_PROTOS +dumpRetValAssign( char *retval, char *ret_def, RuleRefNode * ruleRef /* MR30 */) +#else +dumpRetValAssign( retval, ret_def, ruleRef /* MR30 */) +char *retval; +char *ret_def; +RuleRefNode *ruleRefNode; +#endif +{ + char *q = ret_def; + + tab(); + while ( *retval != '\0' && *q != '\0') + { + while ( isspace((*retval)) ) retval++; + while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output); + fprintf(output, " = _trv."); + + DumpNextNameInDef(&q, output); + while ( isspace(*q) ) q++; + fputc(';', output); fputc(' ', output); + if ( *retval == ',' ) retval++; + } + if (*retval == '\0' && *q != '\0') { +/* MR30 */ errFL("Fewer output values than output formals for rule reference", +/* MR30 */ FileStr[ruleRef->file],ruleRef->line); + } + if (*retval != '\0' && *q == '\0') { +/* MR30 */ errFL("More output actuals than output formals for rule reference", +/* MR30 */ FileStr[ruleRef->file],ruleRef->line); + } +} + +/* This function computes the set of tokens that can possibly be seen k + * tokens in the future from point j + */ + +static set +#ifdef __USE_PROTOS +ComputeErrorSet( Junction *j, int k, int usePlusBlockBypass) +#else +ComputeErrorSet( j, k, usePlusBlockBypass ) +Junction *j; +int k; +int usePlusBlockBypass; +#endif +{ + Junction *alt1; + set a, rk, f; + require(j->ntype==nJunction, "ComputeErrorSet: non junction passed"); + + f = rk = empty; + for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2) + { + if (alt1->ignore && ! usePlusBlockBypass) continue; /* MR21 - Ignore aPlusBlk forward p2 */ + REACH(alt1->p1, k, &rk, a); + require(set_nil(rk), "ComputeErrorSet: rk != nil"); + set_free(rk); + set_orin(&f, a); + set_free(a); + } + return f; +} + +static char * +#ifdef __USE_PROTOS +tokenFollowSet(TokNode *p) +#else +tokenFollowSet(p) +TokNode *p; +#endif +{ + static char buf[100]; + set rk, a; + int n; + rk = empty; + + REACH(p->next, 1, &rk, a); + require(set_nil(rk), "rk != nil"); + set_free(rk); + n = DefErrSet( &a, 0, NULL ); + set_free(a); + if ( GenCC ) + sprintf(buf, "err%d", n); + else + sprintf(buf, "zzerr%d", n); + return buf; +} + +static void +#ifdef __USE_PROTOS +makeErrorClause( Junction *q, set f, int max_k, int usePlusBlockBypass ) +#else +makeErrorClause( q, f, max_k, usePlusBlockBypass ) +Junction *q; +set f; +int max_k; +int usePlusBlockBypass; +#endif +{ + char * handler_id=""; /* MR7 */ + int nilf=0; /* MR13 */ + RuleEntry *ruleEntry; /* MR14 */ + + if ( FoundException ) + { + _gen("else {\n"); + tabs++; + if ( FoundGuessBlk ) + { + if ( GenCC ) {gen("if ( guessing ) goto fail;\n");} + else gen("if ( zzguessing ) goto fail;\n"); + } + gen("if (_sva) _signal=NoViableAlt;\n"); + gen("else _signal=NoSemViableAlt;\n"); + if (q->outerEG != NULL) { + handler_id=q->outerEG->altID; +#if 0 + } else { + printf("q->curAltNum=%d q->exception_label=%s\n",q->curAltNum,q->exception_label); + gen("*** DEBUG *** outerEG==NULL\n"); +#endif + }; + gen1("goto %s_handler; /* MR7 */\n",handler_id); /* MR7 */ + tabs--; + gen("}\n"); + return; + } + + if ( max_k == 1 ) + { +/* MR13 */ nilf=set_nil(f); + if ( GenCC ) { + _gen1("else {FAIL(1,err%d", DefErrSet1(1,&f,1,NULL)); + } else { + _gen1("else {zzFAIL(1,zzerr%d", DefErrSet1(1,&f,1,NULL)); + }; + set_free(f); + } + else + { + int i; + set_free(f); + if ( GenCC ) {_gen1("else {FAIL(%d", max_k);} + else _gen1("else {zzFAIL(%d", max_k); + + ruleEntry = (RuleEntry *) hash_get(Rname,q->rname); + + for (i=1; i<=max_k; i++) + { +/* MR14 */ if (ruleEntry->dontComputeErrorSet) { +/* MR14 */ f=empty; + } else { + f = ComputeErrorSet(q, i, usePlusBlockBypass /* use plus block bypass ? */ ); + } + + if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));} + else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL )); + + set_free(f); + } + } + _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n"); +/* MR13 */ if (nilf) { +/* MR13 */ errFL("empty error set for alt - probably because of undefined rule or infinite left recursion", +/* MR13 */ FileStr[q->file],q->line); +/* MR13 */ gen(" /* MR13 empty error set for this alt - undef rule ? infinite left recursion ? */"); +/* MR13 */ }; +} + +static /* MR7 */ +#ifdef __USE_PROTOS +char * findOuterHandlerLabel(ExceptionGroup *eg) /* MR7 */ +#else +char * findOuterHandlerLabel(eg) /* MR7 */ +ExceptionGroup *eg; /* MR7 */ +#endif +{ + char *label=NULL; /* MR7 */ + ExceptionGroup *outerEG; /* MR7 */ + + if (eg->forRule == 0) { /* MR7 */ + if (eg->labelEntry != NULL) { /* MR7 */ + outerEG=eg->labelEntry->outerEG; /* MR7 */ + if (outerEG != NULL) { /* MR7 */ + label=outerEG->altID; /* MR7 */ + outerEG->used=1; /* MR7 */ + }; /* MR7 */ + } else if (eg->outerEG != NULL) { /* MR7 */ + outerEG=eg->outerEG; /* MR7 */ + label=outerEG->altID; /* MR7 */ + outerEG->used=1; /* MR7 */ + }; /* MR7 */ + }; /* MR7 */ + return (label==NULL ? "" : label); /* MR7 */ +} /* MR7 */ + +/*** debug ***/ +#if 0 +** static /* MR7 */ +** #ifdef __USE_PROTOS +** char * findOuterAltHandlerLabel(Junction *startJ) /* MR7 */ +** #else +** char * findOuterAltHandlerLabel(startJ) /* MR7 */ +** Junction *startJ; /* MR7 */ +** #endif +** { /* MR7 */ +** char *label=NULL; /* MR7 */ +** Junction *alt; /* MR7 */ +** /* MR7 */ +** for (alt=startJ; alt != NULL; alt=alt->outerAltstart) { /* MR7 */ +** label=alt->exception_label; /* MR7 */ +** if (label != NULL) break; /* MR7 */ +** }; /* MR7 */ +** return (label==NULL ? "" : label); /* MR7 */ +** } /* MR7 */ +#endif + +#ifdef __USE_PROTOS +static void OutLineInfo(FILE *file,int line,char *fileName) +#else +static void OutLineInfo(file,line,fileName) + FILE * file; + int line; + char * fileName; +#endif +{ + static char * prevFileName=NULL; + static char * prevFileNameMS=NULL; + + char * p; + char * q; + + if (! GenLineInfo) return; + + if (!GenLineInfoMS) { + fprintf(file, LineInfoFormatStr,line,fileName); + } else { + if (fileName == prevFileName) { + fprintf(file, LineInfoFormatStr,line,prevFileNameMS); + } else { + if (prevFileNameMS != NULL) free (prevFileNameMS); + prevFileNameMS=(char *)calloc(1,strlen(fileName)+1); + require(prevFileNameMS != NULL,"why not do this in calloc wrapper"); + q=prevFileNameMS; + for (p=fileName; *p != 0; p++) { + *q=*p; + if (*q == '\\') *q='/'; + q++; + } + } + prevFileName=fileName; + }; +} + +#if 0 + +/* MR21 */ + +#ifdef __USE_PROTOS +void OutFirstSetSymbol(Junction *q, char * pSymbol) +#else +void OutFirstSetSymbol(q, pSymbol) + Junction* q; + char * pSymbol +#endif +{ + + set f; + if (pSymbol == NULL) return; + gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol); + f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */); + DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, ""); + set_free(f); +} +#endif + +/* MR21 */ + +#ifdef __USE_PROTOS +void BlockPreambleOption(Junction *q, char * pSymbol) +#else +void BlockPreambleOption(q, pSymbol) + Junction* q; + char * pSymbol; +#endif +{ + set f = empty; + if (pSymbol != NULL) { + f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */); + gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol); + DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, ""); + } + set_free(f); +} + +/* MR21 */ + +void +#ifdef __USE_PROTOS +dumpActionPlus(ActionNode *a, char *s, FILE *output, int tabs, int file, int line, +int final_newline ) +#else +dumpActionPlus(a, s, output, tabs, file, line, final_newline ) +ActionNode *a; +char *s; +FILE *output; +int tabs; +int file; +int line; +int final_newline; +#endif +{ + dumpAction(s,output,tabs,file,line,final_newline); +} + + +#if 0 +** #ifdef __USE_PROTOS +** void MR_ErrorSets(Junction *q, int max_k, int usePlusBlockBypass) +** #else +** void MR_ErrorSets(q, max_k, usePlusBlockBypass) +** Junction *q; +** int max_k; +** int usePlusBlockBypass; +** #endif +** { +** int k; +** set setResult; +** Junction* alt1; +** Junction* p; +** set rk; +** +** require (max_k <= CLL_k, "k > CLL_k"); +** +** +** for (k = 1; k <= CLL_k; k++) {set_clr(q->fset[k]); } +** +** for (k = 1; k <= max_k; k++) { +** for (alt1=q; alt1 != NULL; alt1 = (Junction *)alt1->p2) +** { +** if (alt1->ignore && ! usePlusBlockBypass) continue; +** p = analysis_point((Junction *)alt1->p1); +** REACH(p, k, &rk, setResult); +** require(set_nil(rk), "rk != nil"); +** set_orin(&q->fset[k], setResult); +** } +** } +** } +#endif + + +#ifdef __USE_PROTOS +void DumpInitializers(FILE* output, RuleEntry *r, char * pReturn) +#else +void DumpInitializers(output, r, pReturn) +FILE* output; +RuleEntry *r; +char * pReturn; +#endif +{ + char *p = pReturn; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + char *q; + + require(pReturn!=NULL, "DumpInitializer: invalid string"); + + while (*p != 0) { + p = endFormal(p, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + if (nest != 0) return; + if (pValue != NULL) { + tab(); + q = strBetween(pSymbol, pEqualSign, pSeparator); + fprintf(output, "_retv.%s", q); + q = strBetween(pValue, NULL, pSeparator); + fprintf(output, " = %s;\n", q); + } + } +} + +#ifdef __USE_PROTOS +void DumpFormals(FILE* output, char * pReturn, int bInitializer) +#else +void DumpFormals(output, pReturn, bInitializer) +FILE* output; +char * pReturn; +int bInitializer; +#endif +{ + char *p = pReturn; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + char *q; + int count = 0; + + require(pReturn!=NULL, "DumpFormals: invalid string"); + + while (*p != 0) { + p = endFormal(p, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + if (nest != 0) return; + if (count > 0) fprintf(output,","); + if (pDataType != NULL && pSymbol != NULL) { + q = strBetween(pDataType, pSymbol, pSeparator); + fprintf(output, "%s", q); + q = strBetween(pSymbol, pEqualSign, pSeparator); + fprintf(output," %s",q); + if (pValue != NULL) { + q = strBetween(pValue, NULL, pSeparator); + if (bInitializer != 0) { + fprintf(output, " = %s", q); + } + } + } + count++; + } +} + +/* MR23 Check for empty alt in a more intelligent way. + Previously, an empty alt for genBlk had to point directly + to the endBlock. This did not work once I changed {...} + blocks to look like (...|...| epsilon) since there were + intervening generics. This fixes the problem for this + particular case. Things like actions or empty blocks of + various kinds will still cause problems, but I wasnt't + prepared to handle pathological cases like (A|()*). It + does handle (A | ()), which is a recommended idiom for + epsilon. + + Actually, this isn't quite correct since it doesn't handle + the case of the ignore bit in the plus block bypass, but + I'm too tired to figure out the correct fix, and will just + work around it. +*/ + +#ifdef __USE_PROTOS +int isEmptyAlt(Node * alt, Node * endBlock) +#else +int isEmptyAlt(alt, endBlock) +Node * alt; +Node * endBlock; +#endif +{ + Node * n = alt; + Junction * j; + while (n != endBlock) { + switch (n->ntype) { + + case nRuleRef: + return 0; + + case nToken: + return 0; + + case nAction: + return 0; + + case nJunction: + goto JUNCTION; + + default: + fatal_internal("Invalid node type"); + return 0; + } +JUNCTION: + j = (Junction *) n; + + switch (j->jtype) { + case Generic: + { + n = j->p1; + goto NEXT; + } + + case aSubBlk: + { + n = j->p1; /* MR26 */ + goto NEXT; /* MR26 */ + } + + case EndBlk: + return 0; + + case EndRule: + return 1; + + default: + return 0; + } +NEXT: continue; + } + return 1; +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/generic.h b/Tools/Source/TianoTools/Pccts/antlr/generic.h new file mode 100644 index 0000000000..8d736d5200 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/generic.h @@ -0,0 +1,286 @@ +/* + * generic.h -- generic include stuff for new PCCTS ANTLR. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#define StrSame 0 + +#define DefaultParserName "zzparser" + +/* MR9 JVincent@novell.com Allow user to override default ZZLEXBUFSIZE */ +/* MR11 thm Raise antlr's own default ZZLEXBUFSIZE to 8k */ +/* MR22 thm Raise antlr's own default ZZLEXBUFSIZE to 32k */ + +#ifndef ZZLEXBUFSIZE +#define ZZLEXBUFSIZE 32000 +#endif + +/* Tree/FIRST/FOLLOW defines -- valid only after all grammar has been read */ +#define ALT TokenNum+1 +#define SET TokenNum+2 +#define TREE_REF TokenNum+3 + + /* E r r o r M a c r o s */ + +#define fatal(err) fatalFL(err, __FILE__, __LINE__) +#define fatal_internal(err) fatal_intern(err, __FILE__, __LINE__) + + +#define eMsg1(s,a) eMsg3(s,a,NULL,NULL) +#define eMsg2(s,a,b) eMsg3(s,a,b,NULL) + + /* S a n i t y C h e c k i n g */ + +#ifndef require +#define require(expr, err) {if ( !(expr) ) fatal_internal(err);} +#endif + + /* L i s t N o d e s */ + +typedef struct _ListNode { + void *elem; /* pointer to any kind of element */ + struct _ListNode *next; + } ListNode; + +/* Define a Cycle node which is used to track lists of cycles for later + * reconciliation by ResolveFoCycles(). + */ +typedef struct _c { + int croot; /* cycle root */ + set cyclicDep; /* cyclic dependents */ + unsigned deg; /* degree of FOLLOW set of croot */ + } Cycle; + +typedef struct _e { + int tok; /* error class name == TokenStr[tok] */ + ListNode *elist; /* linked list of elements in error set */ + set eset; + int setdeg; /* how big is the set */ + int lexclass; /* which lex class is it in? */ + } ECnode; + +typedef struct _TCnode { + int tok; /* token class name */ + ListNode *tlist; /* linked list of elements in token set */ + set tset; + int lexclass; /* which lex class is it in? */ + unsigned char dumped; /* this def has been been dumped */ + unsigned char dumpedComplement; /* this def has been been dumped */ + unsigned setnum; /* which set number is this guy? (if dumped) */ + unsigned setnumComplement; /* MR23 */ + unsigned setnumErrSet; /* MR23 which set is this #tokclass error set (if dumped) */ + unsigned setnumErrSetComplement; /* MR23 */ + } TCnode; + +typedef struct _ft { + char *token; /* id of token type to remap */ + int tnum; /* move token type to which token position */ + } ForcedToken; + +typedef struct _ContextGuardPredicates { /* MR13 */ + Predicate *pred; /* MR13 */ + } ContextGuardPredicates; /* MR13 */ + +#define newListNode (ListNode *) calloc(1, sizeof(ListNode)); +#define newCycle (Cycle *) calloc(1, sizeof(Cycle)); +#define newECnode (ECnode *) calloc(1, sizeof(ECnode)); +#define newTCnode (TCnode *) calloc(1, sizeof(TCnode)); + + + /* H a s h T a b l e E n t r i e s */ + +typedef struct _t { /* Token name or expression */ + char *str; + struct _t *next; + int token; /* token number */ + unsigned char classname; /* is it a err/tok class name or token */ + TCnode *tclass; /* ptr to token class */ + char *action; + char *akaString; + } TermEntry; + +typedef struct _r { /* Rule name and ptr to start of rule */ + char *str; + struct _t *next; + int rulenum; /* RulePtr[rulenum]== ptr to RuleBlk junction */ + unsigned char noAST;/* gen AST construction code? (def==gen code) */ + char *egroup; /* which error group (err reporting stuff) */ +#if 0 + /* MR27 This appears to never be used. Delete this code later. */ + + ListNode *el_labels;/* list of element labels ref in all of rule */ +#endif + ListNode *ast_labels_in_actions; /* MR27 */ + unsigned char has_rule_exception; + char dontComputeErrorSet; /* MR14 - don't compute error set + special for rule in alpha part of + (alpha)? beta block */ + } RuleEntry; + +typedef struct _f { /* cache Fi/Fo set */ + char *str; /* key == (rulename, computation, k) */ + struct _f *next; + set fset; /* First/Follow of rule */ + set rk; /* set of k's remaining to be done after ruleref */ + int incomplete; /* only w/FOLLOW sets. Use only if complete */ + } CacheEntry; + +typedef struct _LabelEntry { /* element labels */ + char *str; + struct _f *next; + Node *elem; /* which element does it point to? */ + ExceptionGroup *ex_group; + /* Is there an exception attached to label? */ + ExceptionGroup *outerEG; /* MR7 */ + /* next EG if ex_group doesn't catch it MR7 */ + struct _LabelEntry *pendingLink; /* MR7 */ + /* too lazy to use ListNode ? MR7 */ + int curAltNum; /* MR7 */ + } LabelEntry; + +typedef struct _SignalEntry { + char *str; + struct _f *next; + int signum; /* unique signal number */ + } SignalEntry; + +typedef struct _PredEntry { /* MR11 predicate name and ptr to string */ + char *str; + struct _PredEntry *next; + int file; + int line; + Predicate *pred; + char *predLiteral; + } PredEntry; + +typedef struct _PointerStack { /* MR10 */ + int count; + int size; + void **data; + } PointerStack; + +#define newTermEntry(s) (TermEntry *) newEntry(s, sizeof(TermEntry)) +#define newRuleEntry(s) (RuleEntry *) newEntry(s, sizeof(RuleEntry)) +#define newCacheEntry(s) (CacheEntry *) newEntry(s, sizeof(CacheEntry)) +#define newLabelEntry(s) (LabelEntry *) newEntry(s, sizeof(LabelEntry)) +#define newSignalEntry(s) (SignalEntry *) newEntry(s, sizeof(SignalEntry)) +#define newPredEntry(s) (PredEntry *) newEntry(s,sizeof(PredEntry)) + +typedef struct _UserAction { + char *action; + int file, line; + } UserAction; + + + /* L e x i c a l C l a s s */ + +/* to switch lex classes, switch ExprStr and Texpr (hash table) */ +typedef struct _lc { + char *classnum, **exprs; + Entry **htable; + } LClass; + +typedef struct _exprOrder { + char *expr; + int lclass; + } Expr; + + +typedef Graph Attrib; + + /* M a x i m u m s */ + +/* MR20 Note G. Hobbelt These values are superceded by values in hash.h */ + +#ifndef HashTableSize +#define HashTableSize 253 +#endif +#ifndef StrTableSize +#define StrTableSize 15000 /* all tokens, nonterminals, rexprs stored here */ +#endif +#define MaxLexClasses 50 /* how many automatons */ +/* TokenStart and EofToken are ignored if #tokdefs meta-op is used */ +#define TokenStart 2 /* MUST be in 1 + EofToken */ +#define EofToken 1 /* Always predefined to be 1 */ + +#ifndef MaxNumFiles +#define MaxNumFiles 99 +#endif + +/**** MR9 JVincent@novell.com Move to pcctscfg.h */ +/**** #define MaxFileName 300 ****/ /* MR9 Move to pcctscfg.h */ /* largest file name size */ + +#define MaxRuleName 100 /* largest rule name size */ +#define TSChunk 100 /* how much to expand TokenStr/ExprStr each time */ +#define TIChunk TSChunk /* expand TokenInd by same as TokenStr to mirror them */ +#define FoStackSize 100 /* deepest FOLLOW recursion possible */ + +#define MaxClassDeclStuff 256 /* MR10 */ + +#define NumPredefinedSignals 3 + + /* S t a n d a r d S i g n a l s */ + +#define sigNoSignal 0 +#define sigMismatchedToken 1 +#define sigNoViableAlt 2 +#define sigNoSemViableAlt 3 + + + +/* AST token types */ +#define ASTexclude 0 +#define ASTchild 1 +#define ASTroot 2 +#define ASTinclude 3 /* include subtree made by rule ref */ + + +#define PredictionVariable "zzpr_expr" +#define PredictionLexClassSuffix "_zzpred" + +#define WildCardString "WildCard" + +#if 0 + /* Removed in version 1.33MR19 + Don't understand why this never caused problems before + */ + + /********************************************************* + #ifndef ANTLRm + #define ANTLRm(st, f, _m) zzbufsize = ZZLEXBUFSIZE;\ + zzmode(_m); \ + zzenterANTLR(f); \ + st; ++zzasp; \ + zzleaveANTLR(f); + #endif + *********************************************************/ +#endif + +#include "proto.h" +#include "pcctscfg.h" /* MR14 */ +#include diff --git a/Tools/Source/TianoTools/Pccts/antlr/globals.c b/Tools/Source/TianoTools/Pccts/antlr/globals.c new file mode 100644 index 0000000000..59d00320a0 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/globals.c @@ -0,0 +1,484 @@ +/* + * globals.c -- File containing all variables/tables visible to all files. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include + +#include "pcctscfg.h" + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" + +char Version[] = "1.33MR33" ; /* PCCTS version number */ /* MRXXX */ +char VersionDef[] = "13333"; /* same (except int equiv for preproc symbol) */ /* MRXXX */ + +char LexStartSymbol[] = "START";/* Name of starting lexical class/automaton */ +char *RemapFileName = "remap.h"; +char *DlgFileName = "parser.dlg"; +char *DefFileName = "tokens.h"; +char *ErrFileName = "err.c"; +char *ModeFileName = "mode.h"; +char *StdMsgName = NULL; + +char *ParserName = DefaultParserName; + +/* list of PCCTS supplied support symbols; these are renamed when more than + * one ANTLR-generated parsers are linked together to avoid name conflicts. + * Can't use '##' ANSIC preprocessor concat operator with K&R and: + * #define zzskip zzparser ## skip + * will not work for ANSI/C++ as 'zzparserskip' is created w/o zzparser + * being substituted--ack!!! + */ +char *StandardSymbols[] = { +/* ANTLR stuff */ + "zzStackOvfMsg", + "zzasp", + "zzaStack", + "inf_tokens", + "inf_text", + "inf_text_buffer", + "inf_text_buffer_ptr", + "inf_text_buffer_size", + "inf_labase", + "inf_last", + "inf_lap", + "zztokenLA", + "zztextLA", + "zzlap", + "zzlabase", + "zztoktext", + "zztoken", + "zzdirty", + "zzguessing", + "zzguess_start", + "zzresynch", + "zzinf_tokens", + "zzinf_text", + "zzinf_text_buffer", + "zzinf_labase", + "zzinf_last", + "zzfill_inf_look", + "zzFAIL", + "zzsave_antlr_state", + "zzrestore_antlr_state", + "zzsyn", + "zzset_el", + "zzset_deg", + "zzedecode", + "_zzsetmatch", + "_zzmatch", + "_inf_zzgettok", + "zzconsumeUntil", + "zzconsumeUntilToken", + "_zzmatch_wsig", + "_zzsetmatch_wsig", + "_zzmatch_wdfltsig", + "_zzsetmatch_wdfltsig", + "zzdflthandlers", +/* DLG stuff */ + "zzreal_line", + "zzcharfull", + "zzerr", + "zzlextext", + "zzbegexpr", + "zzendexpr", + "zzbufsize", + "zzbegcol", + "zzendcol", + "zzline", + "zzchar", + "zzbufovf", + "zzrdstream", + "zzrdfunc", + "zzrdstr", + "zzclose_stream", + "zzsave_dlg_state", + "zzrestore_dlg_state", + "zzmode", + "zzskip", + "zzmore", + "zzreplchar", + "zzreplstr", + "zzgettok", + "zzadvance", + "zzerrstd", + "zzerr_in", + "zzconstr_attr", + "zzempty_attr", + "zzerraction", + "zztokens", /* list of token regular expressions */ + "dfa", + "accepts", + "actions", + "zzTraceOptionValue", /* MR10 */ + "zzTraceGuessOptionValue", /* MR10 */ + "zzTraceCurrentRuleName", /* MR10 */ + "zzTraceDepth", /* MR10 */ + "zzGuessSeq", /* MR10 */ + "zzSyntaxErrCount", /* MR11 */ + "zzLexErrCount", /* MR11 */ + "zzTraceGuessDone", /* MR13 - BJS */ + "zzTraceGuessFail", /* MR13 - BJS */ + "zzTraceGuessOption", /* MR13 - BJS */ + "zzTraceIn", /* MR13 - BJS */ + "zzTraceOption", /* MR13 - BJS */ + "zzTraceOut", /* MR13 - BJS */ + "zzTraceReset", /* MR13 - BJS */ + NULL /* must be present */ +}; + +/* list of PCCTS supplied support functions; these are renamed when more than + * one ANTLR-generated parsers are linked together to avoid name conflicts. + */ +char *ASTSymbols[] = { + "AST", + "zzast_sp", + "zzastStack", + "zzlink", + "zzastnew", + "zzsubchild", + "zzsubroot", + "zzpre_ast", + "zzfree_ast", + "zztmake", + "zzdup_ast", + "zztfree", + "zzdouble_link", + NULL /* must be present */ +}; + +/* Current ambiguity examination information */ +int CurAmbigAlt1, CurAmbigAlt2, CurAmbigline, CurAmbigfile; +char *CurAmbigbtype; + + + /* M e t h o d T a b l e s */ +/* + * The following tables are used to fill syntax diagram nodes with the correct + * function pointers for computing FIRST sets and printing themselves. + */ + +/* fpTraverse[node type] == pointer to function that calculates trees + * representing the FIRST sets for that node (maintains spatial info). + * We use 'struct _tree' not 'tree' due to a g++ 2.4.3 bug. + */ +#ifdef __cplusplus +struct _tree *(*fpTraverse[NumNodeTypes+1])(... /* Node *, int, set * */) = { + NULL, + (struct _tree *(*)(...)) tJunc, + (struct _tree *(*)(...)) tRuleRef, + (struct _tree *(*)(...)) tToken, + (struct _tree *(*)(...)) tAction +}; +#else +Tree *(*fpTraverse[NumNodeTypes+1])() = { + NULL, + tJunc, + tRuleRef, + tToken, + tAction +}; +#endif + +/* fpReach[node type] == pointer to function that calculates FIRST set for + * that node. (r stands for reach). We use 'struct _set' not 'set' + * due to a g++ 2.4.3 bug. + */ +#ifdef __cplusplus +struct _set (*fpReach[NumNodeTypes+1])(... /* Node *, int, set * */) = { + NULL, + (struct _set (*)(...)) rJunc, + (struct _set (*)(...)) rRuleRef, + (struct _set (*)(...)) rToken, + (struct _set (*)(...)) rAction +}; +#else +set (*fpReach[NumNodeTypes+1])() = { + NULL, + rJunc, + rRuleRef, + rToken, + rAction +}; +#endif + +/* fpPrint[node type] == pointer to function that knows how to print that node. */ +#ifdef __cplusplus +void (*fpPrint[NumNodeTypes+1])(... /* Node * */) = { + NULL, + (void (*)(...)) pJunc, + (void (*)(...)) pRuleRef, + (void (*)(...)) pToken, + (void (*)(...)) pAction +}; +#else +void (*fpPrint[NumNodeTypes+1])() = { + NULL, + pJunc, + pRuleRef, + pToken, + pAction +}; +#endif + +char *decodeJType[] = { + "invalid", + "aSubBlk", + "aOptBlk", + "aLoopBlk", + "EndBlk", + "RuleBlk", + "Generic", + "EndRule", + "aPlusBlk", + "aLoopBegin" +}; + + + /* H a s h T a b l e s */ + +Entry **Tname, /* Table of all token names (maps name to tok num)*/ + **Texpr, /* Table of all token expressions + (maps expr to tok num) */ + **Rname, /* Table of all Rules (has ptr to start of rule) */ + **Fcache, /* Cache of First/Follow Computations */ + **Tcache; /* Tree cache; First/Follow for permute trees */ +Entry **Elabel; /* Table of all element label names */ +Entry **Sname; /* Signal names */ +Entry **Pname; /* symbolic predicate names MR11 */ + + + /* V a r i a b l e s */ + +int Save_argc; /* MR10 */ +char **Save_argv; /* MR10 */ +int EpToken=0; /* Imaginary Epsilon token number */ +int WildCardToken=0; +int CurFile= -1; /* Index into FileStr table */ +char *CurPredName=NULL; /* MR11 */ +char *CurRule=NULL; /* Pointer to current rule name */ +int CurRuleDebug=0; /* MR13 debug flag */ +RuleEntry *CurRuleNode=NULL;/* Pointer to current rule node in syntax tree */ +char *CurRetDef=NULL; /* Pointer to current return type definition */ +char *CurParmDef=NULL; /* Pointer to current parameter definition */ +Junction *CurRuleBlk=NULL; /* Pointer to current block node for enclosing block */ +ListNode *CurExGroups=NULL; /* Current list of exception groups for rule/alts */ +ListNode *CurElementLabels=NULL; +ListNode *CurAstLabelsInActions=NULL; /* MR27 */ + +/* MR10 used by <<>>? to set "label_used_in_semantic_pred" */ +/* MR10 this will force LT(i) assignment even in guess mode */ + +ListNode *CurActionLabels=NULL; /* MR10 Element Labels appearing in last action */ +int numericActionLabel=0 ; /* MR10 << ... $1 ... >> or << ... $1 ... >>? */ +ListNode *NumericPredLabels=NULL; /* MR10 << ... $1 ... >>? ONLY */ +ListNode *ContextGuardPredicateList=NULL; /* MR13 for re-evaluating predicates + after meta tokens are defined */ + +int CurBlockID=0; /* Unique int for each block */ +int CurAltNum=0; +Junction *CurAltStart = NULL; /* Junction node that starts the alt */ +Junction *OuterAltStart = NULL; /* For chaining exception groups MR7 */ +int NumRules=0; /* Rules are from 1 to n */ +FILE *output=NULL; /* current parser output file */ +FILE *input=NULL; /* current grammar input file */ +char *FileStr[MaxNumFiles];/* Ptr to array of file names on command-line */ +int NumFiles=0; /* current grammar file number */ +#ifdef __cplusplus +void (**fpTrans)(...), /* array of ptrs to funcs that translate nodes */ + (**fpJTrans)(...); /* ... that translate junctions */ +#else +void (**fpTrans)(), /* array of ptrs to funcs that translate nodes */ + (**fpJTrans)(); /* ... that translate junctions */ +#endif +int **FoStack; /* Array of LL_k ptrs to stacks of rule numbers */ +int **FoTOS; /* FOLLOW stack top-of-stack pointers */ +Junction *SynDiag = NULL; /* Pointer to start of syntax diagram */ +int BlkLevel=1; /* Current block level. Set by antlr.g, used by + * scanner to translate $i.j attributes */ +set reserved_positions; /* set of token positions reserved by '#token T=i' cmds */ +set all_tokens; /* set of all token types */ +set imag_tokens; /* set of all imaginary token types (EpToken, errclasses...) */ +set tokclasses; /* set of all token class token types */ +ListNode *ForcedTokens = 0; /* list of token_id/token_num pairs to remap */ +ListNode *MetaTokenNodes=NULL; /* list of meta token refs such as token classes etc... */ +int *TokenInd=NULL; /* an indirection level between token num and position + * of that token def in TokenStr and ExprStr */ +int LastTokenCounted=0; /* ==TokenNum if no token renumbering (same as old TokenNum) */ +int TokenNum=TokenStart; +char **TokenStr=NULL; /* map token # to token name */ +char **ExprStr=NULL; /* map token # to expr */ +Junction **RulePtr=NULL; /* map rule # to RuleBlk node of rule */ +ListNode *ExprOrder=NULL; /* list of exprs as they are found in grammar */ +ListNode *BeforeActions=NULL;/* list of grammar actions before rules */ +ListNode *AfterActions=NULL;/* list of grammar actions after rules */ +ListNode *LexActions=NULL; /* list of lexical actions */ + +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via #lexmember <<....>> */ +/* MR1 via #lexprefix <<....>> */ +/* MR1 */ + +ListNode *LexMemberActions=NULL;/* list of lexical header member decl MR1 */ +ListNode *LexPrefixActions=NULL;/* list of lexical header #include decl MR1 */ +ListNode **Cycles=NULL; /* list of cycles (for each k) found when + doing FOLLOWs */ +ListNode *eclasses=NULL; /* list of error classes */ +ListNode *tclasses=NULL; /* list of token classes */ +LClass lclass[MaxLexClasses]; /* array of lex class definitions */ +int CurrentLexClass; /* index into lclass */ +int NumLexClasses=0; /* in range 1..MaxLexClasses (init 0) */ + +char *HdrAction=NULL; /* action defined with #header */ +char *FirstAction=NULL; /* action defined with #first MR11 */ +FILE *ErrFile; /* sets and error recovery stuff */ +FILE *DefFile=NULL; /* list of tokens, return value structs, setwd defs */ +FILE *MRinfoFile=NULL; /* MR10 information file */ +int MRinfo=0; /* MR10 */ +int MRinfoSeq=0; /* MR10 */ +int InfoP=0; /* MR10 predicates */ +int InfoT=0; /* MR10 tnodes */ +int InfoF=0; /* MR10 first/follow sets */ +int InfoM=0; /* MR10 monitor progress */ +int InfoO=0; /* MR12 orphan rules */ +int TnodesInUse=0; /* MR10 */ +int TnodesPeak=0; /* MR10 */ +int TnodesAllocated=0; /* MR10 */ +int TnodesReportThreshold=0; /* MR11 */ +int PotentialSuppression=0; /* MR10 */ +int PotentialDummy=0; /* MR10 */ +int CannotContinue=FALSE; +int OutputLL_k = 1; /* LL_k for parsing must be power of 2 */ +int action_file; /* used to track start of action */ +int action_line; +int FoundGuessBlk=0; /* there is a (...)? block somewhere in grammar */ +int FoundException=0; /* there is an exception somewhere in grammar */ +/* MR6 Distinguish between @ operator and real exception */ +/* MR6 by keeping separate flags for @ operator and real exceptions */ +int FoundAtOperator=0; /* MR6 */ +int FoundExceptionGroup=0; /* MR6 */ +int pLevel=0; /* print Level */ +int pAlt1,pAlt2; /* print "==>" in front of these alts */ + +/* C++ output stuff */ +FILE *Parser_h, /* where subclass of ANTLRParser goes */ + *Parser_c; /* where code for subclass of ANTLRParser goes */ +char Parser_h_Name[MaxFileName+1] = ""; +char Parser_c_Name[MaxFileName+1] = ""; +char MRinfoFile_Name[MaxFileName+1] = ""; /* MR10 */ +char *ClassDeclStuff=NULL; /* MR10 */ +char *BaseClassName=NULL; /* MR22 */ +/* list of actions inside the #class {...} defs */ +ListNode *class_before_actions=NULL; +ListNode *class_after_actions=NULL; + +char CurrentClassName[MaxRuleName]=""; +int no_classes_found=1; +char *UserTokenDefsFile; +int UserDefdTokens=0; /* found #tokdefs? */ +char *OutputDirectory=TopDirectory; +ExceptionGroup *DefaultExGroup = NULL; +int NumSignals = NumPredefinedSignals; +int ContextGuardTRAV=0; + +char *MR_AmbAidRule=NULL; /* MR11 */ +int MR_AmbAidLine=0; /* MR11 */ +int MR_AmbAidDepth=0; /* MR11 */ +int MR_AmbAidMultiple=0; /* MR11 */ +int MR_skipped_e3_report=0; /* MR11 */ +int MR_usingPredNames=0; /* MR11 */ +int MR_BadExprSets=0; /* MR13 */ +int MR_Inhibit_Tokens_h_Gen=0; /* MR13 */ +int NewAST=0; /* MR13 */ +int tmakeInParser=0; /* MR23 */ +int AlphaBetaTrace=0; /* MR14 */ +int MR_BlkErr=0; /* MR21 */ +int MR_AlphaBetaMessageCount=0; /* MR14 */ +int MR_AlphaBetaWarning=0; /* MR14 */ +int MR_ErrorSetComputationActive=0; /* MR14 */ +int MR_MaintainBackTrace=0; /* MR14 */ +set MR_CompromisedRules; /* MR14 */ + +Junction *MR_RuleBlkWithHalt; /* MR10 */ + + /* C m d - L i n e O p t i o n s */ + +int LL_k=1; /* how many tokens of full lookahead */ +int CLL_k= -1; /* how many tokens of compressed lookahead */ +int PrintOut = FALSE; /* print out the grammar */ +int PrintAnnotate = FALSE;/* annotate printout with FIRST sets */ +int CodeGen=TRUE; /* Generate output code? */ +int LexGen=TRUE; /* Generate lexical files? (tokens.h, parser.dlg) */ +int GenAST=FALSE; /* Generate AST's? */ +int GenANSI=FALSE; /* Generate ANSI code where necessary */ +int GenExprSetsOpt=TRUE;/* use sets not (LA(1)==tok) expression lists */ +int GenCR=FALSE; /* Generate cross reference? */ +int GenLineInfo=FALSE; /* Generate # line "file" stuff? */ +int GenLineInfoMS=FALSE;/* Like -gl but replace "\" with "/" for MS C/C++ systems */ +int TraceGen=FALSE; /* Generate code to trace rule invocation */ +int elevel=1; /* error level for ambiguity messages */ +int GenEClasseForRules=0;/* don't generate eclass for each rule */ +int TreeResourceLimit= -1;/* don't limit tree resource */ +int DemandLookahead = 0;/* demand/delayed lookahead or not */ +char *RulePrefix = ""; /* prefix each generated rule with this */ +char *stdpccts = "stdpccts.h";/* where to generate std pccts include file */ +int GenStdPccts = 0; /* don't gen stdpccts.h? */ +int ParseWithPredicates = 1; +int WarningLevel = 1; +int UseStdout = 0; /* MR6 */ +int TabWidth = 2; /* MR6 */ /* MR27 */ +int HoistPredicateContext = 0; +int MRhoisting = 0; /* MR9 */ +int MRhoistingk = 0; /* MR13 */ +int MR_debugGenRule=0; /* MR11 */ + +int GenCC = 0; /* Generate C++ output */ + +PointerStack MR_BackTraceStack={0,0,NULL}; /* MR10 */ +PointerStack MR_PredRuleRefStack={0,0,NULL}; /* MR10 */ +PointerStack MR_RuleBlkWithHaltStack={0,0,NULL}; /* MR10 */ + +/* DontCopyTokens and Pragma_DupLabeledTokens were a bad idea. I've just + turned them off rather than backpatching the code. Who knows? We + may need them in the future. + */ +int DontCopyTokens = 1; /* in C++, don't copy ANTLRToken passed to ANTLR */ + +/* Remember if LT(i), LA(i), or LATEXT(i) used in an action which is not + a predicate. If so, give a warning for novice users. +*/ + +int LTinTokenAction = 0; /* MR23 */ +int PURIFY = 1; /* MR23 */ + +int CurBlockID_array[MAX_BLK_LEVEL]; /* MR23 */ +int CurAltNum_array[MAX_BLK_LEVEL]; /* MR23 */ diff --git a/Tools/Source/TianoTools/Pccts/antlr/hash.c b/Tools/Source/TianoTools/Pccts/antlr/hash.c new file mode 100644 index 0000000000..68fe8fd227 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/hash.c @@ -0,0 +1,221 @@ +/* + * hash.c + * + * Manage hash tables. + * + * The following functions are visible: + * + * char *mystrdup(char *); Make space and copy string + * Entry **newHashTable(); Create and return initialized hash table + * Entry *hash_add(Entry **, char *, Entry *) + * Entry *hash_get(Entry **, char *) + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "pcctscfg.h" +#include "hash.h" + +#ifdef __USE_PROTOS +#include +#else +#ifdef VAXC +#include +#else +#include +#endif +#endif +#include + +#define StrSame 0 + +#define fatal(err) \ + {fprintf(stderr, "%s(%d):", __FILE__, __LINE__); \ + fprintf(stderr, " %s\n", err); exit(PCCTS_EXIT_FAILURE);} +#define require(expr, err) {if ( !(expr) ) fatal(err);} + +static unsigned size = HashTableSize; +static char *strings = NULL; +static char *strp; +static unsigned strsize = StrTableSize; + +/* create the hash table and string table for terminals (string table only once) */ +Entry ** +#ifdef __USE_PROTOS +newHashTable( void ) +#else +newHashTable( ) +#endif +{ + Entry **table; + + table = (Entry **) calloc(size, sizeof(Entry *)); + require( table != NULL, "cannot allocate hash table"); + if ( strings == NULL ) + { + strings = (char *) calloc(strsize, sizeof(char)); + require( strings != NULL, "cannot allocate string table"); + strp = strings; + } + return table; +} + +void +#ifdef __USE_PROTOS +killHashTable( Entry **table ) +#else +killHashTable( table ) +Entry **table; +#endif +{ + /* for now, just free table, forget entries */ + free( (char *) table ); /* MR10 cast */ +} + +/* Given a table, add 'rec' with key 'key' (add to front of list). return ptr to entry */ +Entry * +#ifdef __USE_PROTOS +hash_add( Entry **table, char *key, Entry *rec ) +#else +hash_add( table, key, rec ) +Entry **table; +char *key; +Entry *rec; +#endif +{ + unsigned h=0; + char *p=key; + require(table!=NULL && key!=NULL && rec!=NULL, "add: invalid addition"); + + Hash(p,h,size); + rec->next = table[h]; /* Add to singly-linked list */ + table[h] = rec; + return rec; +} + +/* Return ptr to 1st entry found in table under key (return NULL if none found) */ +Entry * +#ifdef __USE_PROTOS +hash_get( Entry **table, char *key ) +#else +hash_get( table, key ) +Entry **table; +char *key; +#endif +{ + unsigned h=0; + char *p=key; + Entry *q; +/* require(table!=NULL && key!=NULL, "get: invalid table and/or key");*/ + if ( !(table!=NULL && key!=NULL) ) *((char *) 34) = 3; + + Hash(p,h,size); + for (q = table[h]; q != NULL; q = q->next) + { + if ( strcmp(key, q->str) == StrSame ) return( q ); + } + return( NULL ); +} + +#ifdef DEBUG_HASH +void +#ifdef __USE_PROTOS +hashStat( Entry **table ) +#else +hashStat( table ) +Entry **table; +#endif +{ + static unsigned short count[20]; + int i,n=0,low=0, hi=0; + Entry **p; + float avg=0.0; + + for (i=0; i<20; i++) count[i] = 0; + for (p=table; p<&(table[size]); p++) + { + Entry *q = *p; + int len; + + if ( q != NULL && low==0 ) low = p-table; + len = 0; + if ( q != NULL ) fprintf(stderr, "[%d]", p-table); + while ( q != NULL ) + { + len++; + n++; + fprintf(stderr, " %s", q->str); + q = q->next; + if ( q == NULL ) fprintf(stderr, "\n"); + } + count[len]++; + if ( *p != NULL ) hi = p-table; + } + + fprintf(stderr, "Storing %d recs used %d hash positions out of %d\n", + n, size-count[0], size); + fprintf(stderr, "%f %% utilization\n", + ((float)(size-count[0]))/((float)size)); + for (i=0; i<20; i++) + { + if ( count[i] != 0 ) + { + avg += (((float)(i*count[i]))/((float)n)) * i; + fprintf(stderr, "Bucket len %d == %d (%f %% of recs)\n", + i, count[i], ((float)(i*count[i]))/((float)n)); + } + } + fprintf(stderr, "Avg bucket length %f\n", avg); + fprintf(stderr, "Range of hash function: %d..%d\n", low, hi); +} +#endif + +/* Add a string to the string table and return a pointer to it. + * Bump the pointer into the string table to next avail position. + */ +char * +#ifdef __USE_PROTOS +mystrdup( char *s ) +#else +mystrdup( s ) +char *s; +#endif +{ + char *start=strp; + require(s!=NULL, "mystrdup: NULL string"); + + while ( *s != '\0' ) + { + require( strp <= &(strings[strsize-2]), + "string table overflow\nIncrease StrTableSize in hash.h and recompile hash.c\n"); + *strp++ = *s++; + } + *strp++ = '\0'; + + return( start ); +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/hash.h b/Tools/Source/TianoTools/Pccts/antlr/hash.h new file mode 100644 index 0000000000..3969c40b4a --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/hash.h @@ -0,0 +1,73 @@ +/* + * hash.h -- define hash table entries, sizes, hash function... + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + + /* H a s h T a b l e S t u f f */ + +#ifndef HashTableSize +#define HashTableSize 553 +#endif + +#ifndef StrTableSize +#ifdef PC32 +#define StrTableSize 1000000 +#endif +#endif + +#ifndef StrTableSize +#ifdef PC +#define StrTableSize 655200 +#endif +#endif + +#ifndef StrTableSize +#define StrTableSize 1000000 +#endif + +typedef struct _entry { /* Minimum hash table entry -- superclass */ + char *str; + struct _entry *next; + } Entry; + +/* Hash 's' using 'size', place into h (s is modified) */ +#define Hash(s,h,size) \ + {while ( *s != '\0' ) h = (h<<1) + *s++; \ + h %= size;} + +#ifdef __USE_PROTOS +Entry *hash_get(Entry **, char *), + **newHashTable(void), + *hash_add(Entry **, char *, Entry *); + +void killHashTable(Entry **); + +#else +Entry *hash_get(), **newHashTable(), *hash_add(); +void killHashTable(); /* MR9 23-Sep-97 */ +#endif diff --git a/Tools/Source/TianoTools/Pccts/antlr/lex.c b/Tools/Source/TianoTools/Pccts/antlr/lex.c new file mode 100644 index 0000000000..8c524fe465 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/lex.c @@ -0,0 +1,878 @@ +/* + * lex.c -- Generate all of the lexical type files: parser.dlg tokens.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include +/* MR1 */ +/* MR1 10-Apr-97 MR1 Replace use of __STDC__ with __USE_PROTOS */ +/* MR1 */ +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" + +#define DLGErrorString "invalid token" + +/* Generate a complete lexical description of the lexemes found in the grammar */ +void +#ifdef __USE_PROTOS +genLexDescr( void ) +#else +genLexDescr( ) +#endif +{ + ListNode *p; + FILE *dlgFile = fopen(OutMetaName(DlgFileName), "w"); + require(dlgFile!=NULL, eMsg1("genLexFile: cannot open %s", OutMetaName(DlgFileName)) ); +#ifdef SPECIAL_FOPEN + special_fopen_actions(OutMetaName(DlgFileName)); /* MR1 */ +#endif + fprintf(dlgFile, "<<\n"); + fprintf(dlgFile, "/* %s -- DLG Description of scanner\n", DlgFileName); + fprintf(dlgFile, " *\n"); + fprintf(dlgFile, " * Generated from:"); + {int i; for (i=0; i 1 ) fprintf(dlgFile, "#define LL_K %d\n", OutputLL_k); + if ( DemandLookahead ) fprintf(dlgFile, "#define DEMAND_LOOK\n"); + if (TraceGen) { + fprintf(dlgFile,"#ifndef zzTRACE_RULES\n"); /* MR20 */ + fprintf(dlgFile,"#define zzTRACE_RULES\n"); /* MR20 */ + fprintf(dlgFile,"#endif\n"); /* MR22 */ + }; + fprintf(dlgFile, "#include \"antlr.h\"\n"); + if ( GenAST ) { + fprintf(dlgFile, "#include \"ast.h\"\n"); + } + if ( UserDefdTokens ) + fprintf(dlgFile, "#include %s\n", UserTokenDefsFile); + /* still need this one as it has the func prototypes */ + fprintf(dlgFile, "#include \"%s\"\n", DefFileName); + fprintf(dlgFile, "#include \"dlgdef.h\"\n"); + fprintf(dlgFile, "LOOKAHEAD\n"); + fprintf(dlgFile, "\n"); + fprintf(dlgFile, "void\n"); + fprintf(dlgFile, "#ifdef __USE_PROTOS\n"); + fprintf(dlgFile, "zzerraction(void)\n"); + fprintf(dlgFile, "#else\n"); + fprintf(dlgFile, "zzerraction()\n"); + fprintf(dlgFile, "#endif\n"); + fprintf(dlgFile, "{\n"); + fprintf(dlgFile, "\t(*zzerr)(\"%s\");\n", DLGErrorString); + fprintf(dlgFile, "\tzzadvance();\n"); + fprintf(dlgFile, "\tzzskip();\n"); + fprintf(dlgFile, "}\n"); + } + fprintf(dlgFile, ">>\n\n"); + + /* dump all actions */ + +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via <<%%lexmember ....>> & <<%%lexprefix ...>> */ +/* MR1 */ + if (LexActions != NULL) { + for (p = LexActions->next; p!=NULL; p=p->next) + { +/* MR1 */ fprintf(dlgFile, "<<%%%%lexaction\n"); + dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 ); + fprintf(dlgFile, ">>\n\n"); + } + }; + +/* MR1 */ if (GenCC) { +/* MR1 */ fprintf(dlgFile,"<<%%%%parserclass %s>>\n\n",CurrentClassName); +/* MR1 */ }; + +/* MR1 */ if (LexPrefixActions != NULL) { +/* MR1 */ for (p = LexPrefixActions->next; p!=NULL; p=p->next) +/* MR1 */ { +/* MR1 */ fprintf(dlgFile, "<<%%%%lexprefix\n"); +/* MR1 */ dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 ); +/* MR1 */ fprintf(dlgFile, ">>\n\n"); +/* MR1 */ } +/* MR1 */ }; + +/* MR1 */ if (LexMemberActions != NULL) { +/* MR1 */ for (p = LexMemberActions->next; p!=NULL; p=p->next) +/* MR1 */ { +/* MR1 */ fprintf(dlgFile, "<<%%%%lexmember\n"); +/* MR1 */ dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 ); +/* MR1 */ fprintf(dlgFile, ">>\n\n"); +/* MR1 */ } +/* MR1 */ }; + + /* dump all regular expression rules/actions (skip sentinel node) */ + if ( ExprOrder == NULL ) { + warnNoFL("no regular expressions found in grammar"); + } + else dumpLexClasses(dlgFile); + fprintf(dlgFile, "%%%%\n"); + fclose( dlgFile ); +} + +/* For each lexical class, scan ExprOrder looking for expressions + * in that lexical class. Print out only those that match. + * Each element of the ExprOrder list has both an expr and an lclass + * field. + */ +void +#ifdef __USE_PROTOS +dumpLexClasses( FILE *dlgFile ) +#else +dumpLexClasses( dlgFile ) +FILE *dlgFile; +#endif +{ + int i; + TermEntry *t; + ListNode *p; + Expr *q; + + for (i=0; inext; p!=NULL; p=p->next) + { + q = (Expr *) p->elem; + if ( q->lclass != i ) continue; + lexmode(i); + t = (TermEntry *) hash_get(Texpr, q->expr); + require(t!=NULL, eMsg1("genLexDescr: rexpr %s not in hash table",q->expr) ); + if ( t->token == EpToken ) continue; + fprintf(dlgFile, "%s\n\t<<\n", StripQuotes(q->expr)); + /* replace " killed by StripQuotes() */ + q->expr[ strlen(q->expr) ] = '"'; + if ( !GenCC ) { + if ( TokenString(t->token) != NULL ) + fprintf(dlgFile, "\t\tNLA = %s;\n", TokenString(t->token)); + else + fprintf(dlgFile, "\t\tNLA = %d;\n", t->token); + } + if ( t->action != NULL ) dumpAction( t->action, dlgFile, 2,-1,0,1 ); + if ( GenCC ) { + if ( TokenString(t->token) != NULL ) + fprintf(dlgFile, "\t\treturn %s;\n", TokenString(t->token)); + else + fprintf(dlgFile, "\t\treturn (ANTLRTokenType)%d;\n", t->token); + } + fprintf(dlgFile, "\t>>\n\n"); + } + } +} + +/* Strip the leading path (if any) from a filename */ +char * +#ifdef __USE_PROTOS +StripPath( char *fileName ) +#else +StripPath( fileName ) +char *fileName; +#endif +{ + char *p; + static char dirSym[2] = DirectorySymbol; + + if(NULL != (p = strrchr(fileName, dirSym[0]))) + p++; + else + p = fileName; + + return(p); +} + +/* Generate a list of #defines && list of struct definitions for + * aggregate retv's */ +void +#ifdef __USE_PROTOS +genDefFile( void ) +#else +genDefFile( ) +#endif +{ + int i; + + /* If C++ mode and #tokdef used, then don't need anything in here since + * C++ puts all definitions in the class file name. + */ + if ( GenCC && UserTokenDefsFile ) return; + if ( MR_Inhibit_Tokens_h_Gen) return; + + DefFile = fopen(OutMetaName(DefFileName), "w"); + require(DefFile!=NULL, eMsg1("genDefFile: cannot open %s", OutMetaName(DefFileName)) ); +#ifdef SPECIAL_FOPEN + special_fopen_actions(OutMetaName(DefFileName)); /* MR1 */ +#endif + fprintf(DefFile, "#ifndef %s\n", StripPath(gate_symbol(DefFileName))); + fprintf(DefFile, "#define %s\n", StripPath(gate_symbol(DefFileName))); + + fprintf(DefFile, "/* %s -- List of labelled tokens and stuff\n", DefFileName); + fprintf(DefFile, " *\n"); + fprintf(DefFile, " * Generated from:"); + for (i=0; i1 ) + { + int j; + /* look in all lexclasses for the reg expr */ + +/* MR10 Derek Pappas */ +/* MR10 A #tokclass doesn't have associated regular expressiones */ +/* MR10 so don't warn user about it's omission */ + + p = (TermEntry *) hash_get(Tname, TokenString(i)); + + if (p != NULL && ! p->classname) { + for (j=0; j=NumLexClasses ) + { + warnNoFL(eMsg1("token label has no associated rexpr: %s",TokenString(i))); + } + }; + } + require((p=(TermEntry *)hash_get(Tname, TokenString(i))) != NULL, + "token not in sym tab when it should be"); + if ( !p->classname ) + { + if ( GenCC ) { + if ( !first ) fprintf(DefFile, ",\n"); + first = 0; + fprintf(DefFile, "\t%s=%d", TokenString(i), i); + } + else + fprintf(DefFile, "#define %s %d\n", TokenString(i), i); + } + } + } +/* MR1 */ +/* MR1 10-Apr-97 133MR1 Prevent use of varying sizes of integer */ +/* MR1 for the enum ANTLRTokenType */ +/* MR1 */ + if ( GenCC ) { /* MR1 */ + if ( !first ) fprintf(DefFile, ",\n"); /* MR14 */ + fprintf(DefFile, "\tDLGminToken=0"); /* MR1 */ + fprintf(DefFile, ",\n\tDLGmaxToken=9999};\n"); /* MR1 */ + }; /* MR1 */ + } + + if ( !GenCC ) GenRulePrototypes(DefFile, SynDiag); + + fprintf(DefFile, "\n#endif\n"); +} + +void +#ifdef __USE_PROTOS +GenRemapFile( void ) +#else +GenRemapFile( ) +#endif +{ + if ( strcmp(ParserName, DefaultParserName)!=0 ) + { + FILE *f; + int i; + + f = fopen(OutMetaName(RemapFileName), "w"); + require(f!=NULL, eMsg1("GenRemapFile: cannot open %s", OutMetaName(RemapFileName)) ); +#ifdef SPECIAL_FOPEN + special_fopen_actions(OutMetaName(RemapFileName)); /* MR1 */ +#endif + fprintf(f, "/* %s -- List of symbols to remap\n", RemapFileName); + fprintf(f, " *\n"); + fprintf(f, " * Generated from:"); + for (i=0; irname, ParserName, p->rname); + p = (Junction *)p->p2; + } +} + +/* Generate a bunch of #defines that rename all standard symbols to be + * "ParserName_symbol". The list of standard symbols to change is in + * globals.c. + */ +void +#ifdef __USE_PROTOS +GenPredefinedSymbolRedefs( FILE *f ) +#else +GenPredefinedSymbolRedefs( f ) +FILE *f; +#endif +{ + char **p; + + fprintf(f, "\n/* rename PCCTS-supplied symbols to be 'ParserName_symbol' */\n"); + for (p = &StandardSymbols[0]; *p!=NULL; p++) + { + fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p); + } +} + +/* Generate a bunch of #defines that rename all AST symbols to be + * "ParserName_symbol". The list of AST symbols to change is in + * globals.c. + */ +void +#ifdef __USE_PROTOS +GenASTSymbolRedefs( FILE *f ) +#else +GenASTSymbolRedefs( f ) +FILE *f; +#endif +{ + char **p; + + fprintf(f, "\n/* rename PCCTS-supplied AST symbols to be 'ParserName_symbol' */\n"); + for (p = &ASTSymbols[0]; *p!=NULL; p++) + { + fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p); + } +} + +/* redefine all sets generated by ANTLR; WARNING: 'zzerr', 'setwd' must match + * use in bits.c (DumpSetWd() etc...) + */ +void +#ifdef __USE_PROTOS +GenSetRedefs( FILE *f ) +#else +GenSetRedefs( f ) +FILE *f; +#endif +{ + int i; + + for (i=1; i<=wordnum; i++) + { + fprintf(f, "#define setwd%d %s_setwd%d\n", i, ParserName, i); + } + for (i=1; i<=esetnum; i++) + { + fprintf(f, "#define zzerr%d %s_err%d\n", i, ParserName, i); + } +} + +/* Find all return types/parameters that require structs and def + * all rules with ret types. + * + * This is for the declaration, not the definition. + */ +void +#ifdef __USE_PROTOS +GenRulePrototypes( FILE *f, Junction *p ) +#else +GenRulePrototypes( f, p ) +FILE *f; +Junction *p; +#endif +{ + int i; + + i = 1; + while ( p!=NULL ) + { + if ( p->ret != NULL ) + { +/* MR23 */ if ( hasMultipleOperands(p->ret) ) + { + DumpRetValStruct(f, p->ret, i); + } + fprintf(f, "\n#ifdef __USE_PROTOS\n"); +/* MR23 */ if ( hasMultipleOperands(p->ret) ) + { + fprintf(f, "extern struct _rv%d", i); + } + else + { + fprintf(f, "extern "); + DumpType(p->ret, f); + } + fprintf(f, " %s%s(", RulePrefix, p->rname); + DumpANSIFunctionArgDef(f,p,1 /* emit initializers ? */); + fprintf(f, ";\n"); + fprintf(f, "#else\n"); +/* MR23 */ if ( hasMultipleOperands(p->ret) ) + { + fprintf(f, "extern struct _rv%d", i); + } + else + { + fprintf(f, "extern "); + DumpType(p->ret, f); + } + fprintf(f, " %s%s();\n", RulePrefix, p->rname); + fprintf(f, "#endif\n"); + } + else + { + fprintf(f, "\n#ifdef __USE_PROTOS\n"); + fprintf(f, "void %s%s(", RulePrefix, p->rname); + DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */ ); + fprintf(f, ";\n"); +#ifdef OLD + if ( p->pdecl != NULL || GenAST ) + { + if ( GenAST ) { + fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":""); + } + if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl); + } + else fprintf(f, "void"); + fprintf(f, ");\n"); +#endif + fprintf(f, "#else\n"); + fprintf(f, "extern void %s%s();\n", RulePrefix, p->rname); + fprintf(f, "#endif\n"); + } + i++; + p = (Junction *)p->p2; + } +} + +/* Define all rules in the class.h file; generate any required + * struct definitions first, however. + */ +void +#ifdef __USE_PROTOS +GenRuleMemberDeclarationsForCC( FILE *f, Junction *q ) +#else +GenRuleMemberDeclarationsForCC( f, q ) +FILE *f; +Junction *q; +#endif +{ + Junction *p = q; + int i; + + fprintf(f, "private:\n"); + + /* Dump dflt handler declaration */ + fprintf(f, "\tvoid zzdflthandlers( int _signal, int *_retsignal );\n\n"); + + fprintf(f, "public:\n"); + + /* Dump return value structs */ + i = 1; + while ( p!=NULL ) + { + if ( p->ret != NULL ) + { +/* MR23 */ if ( hasMultipleOperands(p->ret) ) + { + DumpRetValStruct(f, p->ret, i); + } + } + i++; + p = (Junction *)p->p2; + } + + /* Dump member func defs && CONSTRUCTOR */ + fprintf(f, "\t%s(ANTLRTokenBuffer *input);\n", CurrentClassName); +/* + fprintf(f, "\t%s(ANTLRTokenBuffer *input, ANTLRTokenType eof);\n", + CurrentClassName); +*/ + + i = 1; + p = q; + while ( p!=NULL ) + { + if ( p->ret != NULL ) + { +/* MR23 */ if ( hasMultipleOperands(p->ret) ) + { + fprintf(f, "\tstruct _rv%d", i); + } + else + { + fprintf(f, "\t"); + DumpType(p->ret, f); + } + fprintf(f, " %s%s(",RulePrefix,p->rname); + DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */ ); + fprintf(f, ";\n"); +#ifdef OLD + if ( p->pdecl != NULL || GenAST ) + { + if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":""); + if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl); + } + fprintf(f, ");\n"); +#endif + } + else + { + fprintf(f, "\tvoid %s%s(",RulePrefix,p->rname); + DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */); + fprintf(f, ";\n"); +#ifdef OLD + if ( p->pdecl != NULL || GenAST ) + { + if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":""); + if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl); + } + fprintf(f, ");\n"); +#endif + } + i++; + p = (Junction *)p->p2; + } +} + +/* Given a list of ANSI-style parameter declarations, print out a + * comma-separated list of the symbols (w/o types). + * Basically, we look for a comma, then work backwards until start of + * the symbol name. Then print it out until 1st non-alnum char. Now, + * move on to next parameter. + * + */ + +/* MR5 Jan Mikkelsen 26-May-97 - added initalComma parameter */ + +void +#ifdef __USE_PROTOS +DumpListOfParmNames(char *pdecl, FILE *output, int initialComma) /* MR5 */ +#else +DumpListOfParmNames(pdecl, output, initialComma) /* MR5 */ +char *pdecl; /* MR5 */ +FILE *output; /* MR5 */ +int initialComma; /* MR5 */ +#endif +{ + int firstTime = 1, done = 0; + require(output!=NULL, "DumpListOfParmNames: NULL parm"); + + if ( pdecl == NULL ) return; + while ( !done ) + { + if ( !firstTime || initialComma ) putc(',', output); /* MR5 */ + done = DumpNextNameInDef(&pdecl, output); + firstTime = 0; + } +} + +/* given a list of parameters or return values, dump the next + * name to output. Return 1 if last one just printed, 0 if more to go. + */ + +/* MR23 Total rewrite */ + +int +#ifdef __USE_PROTOS +DumpNextNameInDef( char **q, FILE *output ) +#else +DumpNextNameInDef( q, output ) +char **q; +FILE *output; +#endif +{ + char *p; + char *t; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + + p = endFormal(*q, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + + /* MR26 Handle rule arguments such as: IIR_Bool (IIR_Decl::*contstraint)() + For this we need to strip off anything which follows the symbol. + */ + +/* MR26 */ t = pSymbol; +/* MR26 */ if (t != NULL) { +/* MR26 */ for (t = pSymbol; *t != 0; t++) { +/* MR26 */ if (! (isalpha(*t) || isdigit(*t) || *t == '_' || *t == '$')) break; +/* MR26 */ } +/* MR26 */ } +/* MR26 */ fprintf(output,strBetween(pSymbol, t, pSeparator)); + + *q = p; + return (*pSeparator == 0); +} + +/* Given a list of ANSI-style parameter declarations, dump K&R-style + * declarations, one per line for each parameter. Basically, convert + * comma to semi-colon, newline. + */ +void +#ifdef __USE_PROTOS +DumpOldStyleParms( char *pdecl, FILE *output ) +#else +DumpOldStyleParms( pdecl, output ) +char *pdecl; +FILE *output; +#endif +{ + require(output!=NULL, "DumpOldStyleParms: NULL parm"); + + if ( pdecl == NULL ) return; + while ( *pdecl != '\0' ) + { + if ( *pdecl == ',' ) + { + pdecl++; + putc(';', output); putc('\n', output); + while ( *pdecl==' ' || *pdecl=='\t' || *pdecl=='\n' ) pdecl++; + } + else {putc(*pdecl, output); pdecl++;} + } + putc(';', output); + putc('\n', output); +} + +/* Take in a type definition (type + symbol) and print out type only */ +/* MR23 Total rewrite */ + +void +#ifdef __USE_PROTOS +DumpType( char *s, FILE *f ) +#else +DumpType( s, f ) +char *s; +FILE *f; +#endif +{ + char *p; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + + require(s!=NULL, "DumpType: invalid type string"); + + p = endFormal(s, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + fprintf(f,strBetween(pDataType, pSymbol, pSeparator)); +} + +/* check to see if string e is a word in string s */ +int +#ifdef __USE_PROTOS +strmember( char *s, char *e ) +#else +strmember( s, e ) +char *s; +char *e; +#endif +{ + register char *p; + require(s!=NULL&&e!=NULL, "strmember: NULL string"); + + if ( *e=='\0' ) return 1; /* empty string is always member */ + do { + while ( *s!='\0' && !isalnum(*s) && *s!='_' ) + ++s; + p = e; + while ( *p!='\0' && *p==*s ) {p++; s++;} + if ( *p=='\0' ) { + if ( *s=='\0' ) return 1; + if ( !isalnum (*s) && *s != '_' ) return 1; + } + while ( isalnum(*s) || *s == '_' ) + ++s; + } while ( *s!='\0' ); + return 0; +} + +#if 0 + +/* MR23 Replaced by hasMultipleOperands() */ + +int +#ifdef __USE_PROTOS +HasComma( char *s ) +#else +HasComma( s ) +char *s; +#endif +{ + while (*s!='\0') + if ( *s++ == ',' ) return 1; + return 0; +} +#endif + + +/* MR23 Total rewrite */ + +void +#ifdef __USE_PROTOS +DumpRetValStruct( FILE *f, char *ret, int i ) +#else +DumpRetValStruct( f, ret, i ) +FILE *f; +char *ret; +int i; +#endif +{ + char *p = ret; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + + fprintf(f, "\nstruct _rv%d {\n", i); + while (*p != 0 && nest == 0) { + p = endFormal(p, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + fprintf(f,"\t"); + fprintf(f,strBetween(pDataType, pSymbol, pSeparator)); + fprintf(f," "); + fprintf(f,strBetween(pSymbol, pEqualSign, pSeparator)); + fprintf(f,";\n"); + } + fprintf(f,"};\n"); +} + +/* given "s" yield s -- DESTRUCTIVE (we modify s if starts with " else return s) */ +char * +#ifdef __USE_PROTOS +StripQuotes( char *s ) +#else +StripQuotes( s ) +char *s; +#endif +{ + if ( *s == '"' ) + { + s[ strlen(s)-1 ] = '\0'; /* remove last quote */ + return( s+1 ); /* return address past initial quote */ + } + return( s ); +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/main.c b/Tools/Source/TianoTools/Pccts/antlr/main.c new file mode 100644 index 0000000000..051ee4ec5d --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/main.c @@ -0,0 +1,1747 @@ +/* + * main.c -- main program for PCCTS ANTLR. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +/* To set a breakpoint just before exit look for "cleanUp". */ +/* To set a breakpoint for fatal error look for "fatal_intern" */ + +#include + +#include "pcctscfg.h" +#include "stdpccts.h" + +#define MAX_INT_STACK 50 +static int istack[MAX_INT_STACK]; /* Int stack */ +static int isp = MAX_INT_STACK; + +static int DontAcceptFiles = 0; /* if stdin, don't read files */ +static int DontAcceptStdin = 0; /* if files seen first, don't accept stdin */ + +static int tnodes_used_in_guard_predicates_etc; /* MR10 */ + + /* C m d - L i n e O p t i o n S t r u c t & F u n c s */ + +typedef struct _Opt { + char *option; + int arg; +#ifdef __cplusplus + void (*process)(...); +#else + void (*process)(); +#endif + char *descr; + } Opt; + +#ifdef __USE_PROTOS +extern void ProcessArgs(int, char **, Opt *); +#else +extern void ProcessArgs(); +#endif + +#ifdef __USE_PROTOS +int ci_strequ(char *a,char *b) +#else +int ci_strequ(a,b) + char *a; + char *b; +#endif +{ + for ( ;*a != 0 && *b != 0; a++, b++) { + if (toupper(*a) != toupper(*b)) return 0; + } + return (*a == *b); +} + +static void +#ifdef __USE_PROTOS +pStdin( void ) +#else +pStdin( ) +#endif +{ + if ( DontAcceptStdin ) + { + warnNoFL("'-' (stdin) ignored as files were specified first"); + return; + } + + require(NumFiles 8 ) { /* MR6 */ + warnNoFL("tab width must be between 1 and 8"); /* MR6 */ + TabWidth=0; /* MR6 */ + } /* MR6 */ +} /* MR6 */ + +static int ambAidDepthSpecified=0; /* MR11 */ + +static void /* MR11 */ +#ifdef __USE_PROTOS +pAAd( char *s, char *t ) /* MR11 */ +#else +pAAd( s, t ) /* MR11 */ +char *s; /* MR11 */ +char *t; /* MR11 */ +#endif +{ /* MR11 */ + ambAidDepthSpecified=1; /* MR11 */ + MR_AmbAidDepth = atoi(t); /* MR11 */ +} /* MR11 */ + +static void /* MR11 */ +#ifdef __USE_PROTOS +pTreport( char *s, char *t ) /* MR11 */ +#else +pTreport( s, t ) /* MR11 */ + char *s; /* MR11 */ + char *t; /* MR11 */ +#endif +{ /* MR11 */ + TnodesReportThreshold = atoi(t); /* MR11 */ +} /* MR11 */ + +#ifdef __USE_PROTOS +void chkGTFlag(void) /* 7-Apr-97 MR1 */ +#else +void chkGTFlag() /* 7-Apr-97 MR1 */ +#endif +{ + if ( !GenAST ) + warn("#-variable or other AST item referenced w/o -gt option"); +} + + +#ifdef __USE_PROTOS +static void pInfo(char *s, char *t) /* MR10 */ +#else +static void pInfo(s,t) /* MR10 */ + char *s; + char *t; +#endif +{ + char *p; + int q; + for (p=t; *p != 0; p++) { + q=tolower(*p); + if (q=='t') { + InfoT=1; + } else if (q=='p') { + InfoP=1; + } else if (q=='m') { + InfoM=1; + } else if (q=='o') { + InfoO=1; + } else if (q=='0') { + ; /* nothing */ + } else if (q=='f') { + InfoF=1; + } else { + warnNoFL(eMsgd("unrecognized -info option \"%c\"",(int)*p)); + }; + }; +} + +#ifdef __USE_PROTOS +static void pCGen(void) { CodeGen = FALSE; LexGen = FALSE; } +static void pLGen(void) { LexGen = FALSE; } +static void pXTGen(void){ MR_Inhibit_Tokens_h_Gen = TRUE; } +static void pTGen(void) { TraceGen = TRUE; } +static void pSGen(void) { GenExprSetsOpt = FALSE; } +static void pPrt(void) { PrintOut = TRUE; pCGen(); pLGen(); } +static void pPrtA(void) { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); } +static void pAst(void) { GenAST = TRUE; } +static void pANSI(void) { GenANSI = TRUE; } +static void pCr(void) { GenCR = TRUE; } +static void pNOPURIFY(void) { PURIFY = FALSE; } +/*static void pCt(void) { warnNoFL("-ct option is now the default"); }*/ +static void pLI(void) { GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */ +static void pLIms(void) { GenLineInfo = TRUE; GenLineInfoMS = TRUE; } /* MR14 */ +static void pFr(char *s, char *t) {RemapFileName = t;} +static void pFe(char *s, char *t) {ErrFileName = t;} +static void pFl(char *s, char *t) {DlgFileName = t;} +static void pFm(char *s, char *t) {ModeFileName = t;} +static void pFt(char *s, char *t) {DefFileName = t;} + +static void pE1(void) { elevel = 1; } +static void pE2(void) { elevel = 2; } +static void pE3(void) { elevel = 3; } +static void pEGen(void) { GenEClasseForRules = 1; } +static void pDL(void) + { + DemandLookahead = 1; + if ( GenCC ) { + warnNoFL("-gk does not work currently in C++ mode; -gk turned off"); + DemandLookahead = 0; + } + } + +static void pAA(char *s,char *t) {MR_AmbAidRule = t;} /* MR11 */ +static void pAAm(char *s){MR_AmbAidMultiple = 1;} /* MR11 */ +static void pGHdr(void) { GenStdPccts = 1; } +static void pFHdr(char *s, char *t) { stdpccts = t; pGHdr(); } +static void pW1(void) { WarningLevel = 1; } +static void pNewAST(void) { NewAST = 1; } /* MR13 */ +static void ptmakeInParser(void) { tmakeInParser = 1; } /* MR23 */ +static void pAlpha(void) { AlphaBetaTrace = 1; } /* MR14 */ +static void pMR_BlkErr(void) { MR_BlkErr = 1; } /* MR21 */ +static void pStdout(void) {UseStdout = 1; } /* MR6 */ +static void pW2(void) { WarningLevel = 2; } +static void pCC(void) { GenCC = TRUE; } +#else +static void pCGen() { CodeGen = FALSE; LexGen = FALSE; } +static void pLGen() { LexGen = FALSE; } +static void pXTGen(){ MR_Inhibit_Tokens_h_Gen = TRUE; } /* MR14 */ +static void pTGen() { TraceGen = TRUE; } +static void pSGen() { GenExprSetsOpt = FALSE; } +static void pPrt() { PrintOut = TRUE; pCGen(); pLGen(); } +static void pPrtA() { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); } +static void pAst() { GenAST = TRUE; } +static void pANSI() { GenANSI = TRUE; } +static void pCr() { GenCR = TRUE; } +static void pNOPURIFY() { PURIFY = FALSE; } + +/*static void pCt() { warnNoFL("-ct option is now the default"); }*/ +static void pLI() { GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */ +static void pLIms() { GenLineInfo = TRUE; GenLineInfoMS = TRUE; } /* MR14 */ +static void pFr(s,t) char *s, *t; {RemapFileName = t;} +static void pFe(s,t) char *s, *t; {ErrFileName = t;} +static void pFl(s,t) char *s, *t; {DlgFileName = t;} +static void pFm(s,t) char *s, *t; {ModeFileName = t;} +static void pFt(s,t) char *s, *t; {DefFileName = t;} + +static void pE1() { elevel = 1; } +static void pE2() { elevel = 2; } +static void pE3() { elevel = 3; } +static void pEGen() { GenEClasseForRules = 1; } +static void pDL() + { + DemandLookahead = 1; + if ( GenCC ) { + warnNoFL("-gk does not work currently in C++ mode; -gk turned off"); + DemandLookahead = 0; + } + } + +static void pAA(s,t) char *s; char *t; {MR_AmbAidRule = t;} /* MR11 BJS 20-Mar-98 */ +static void pAAm(s) char *s; {MR_AmbAidMultiple = 1;} /* MR11 BJS 20-Mar-98 */ +static void pGHdr() { GenStdPccts = 1; } +static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); } +static void pW1() { WarningLevel = 1; } +static void pNewAST() { NewAST = 1; } /* MR13 */ +static void ptmakeInParser() { tmakeInParser = 1; } /* MR23 */ +static void pAlpha() { AlphaBetaTrace = 1; } /* MR14 */ +static void pMR_BlkErr() { MR_BlkErr = 1; } /* MR21 */ +static void pStdout() {UseStdout = 1; } /* MR6 */ +static void pW2() { WarningLevel = 2; } +static void pCC() { GenCC = TRUE; } +#endif + +static void +#ifdef __USE_PROTOS +pPre( char *s, char *t ) +#else +pPre( s, t ) +char *s; +char *t; +#endif +{ + RulePrefix = t; +} + +static void +#ifdef __USE_PROTOS +pOut( char *s, char *t ) +#else +pOut( s, t ) +char *s; +char *t; +#endif +{ + OutputDirectory = t; +} + +static void +#ifdef __USE_PROTOS +pPred( void ) +#else +pPred( ) +#endif +{ + warnNoFL("-pr is no longer used (predicates employed if present); see -prc, -mrhoist, -mrhoistk"); +/* +** if ( DemandLookahead ) +** warnNoFL("-gk conflicts with -pr; -gk turned off"); +** DemandLookahead = 0; +** HoistPredicateContext = 0; +*/ +} + +static void +#ifdef __USE_PROTOS +pPredCtx( char *s, char *t ) +#else +pPredCtx(s,t) +char *s; +char *t; +#endif +{ + if ( ci_strequ(t,"on")) HoistPredicateContext = 1; + else if ( ci_strequ(t,"off")) HoistPredicateContext = 0; + if ( DemandLookahead ) + { + warnNoFL("-gk incompatible with semantic predicate usage; -gk turned off"); + DemandLookahead = 0; + } +} + +static void +#ifdef __USE_PROTOS +pMRhoist( char *s, char *t ) +#else +pMRhoist(s,t) +char *s; +char *t; +#endif +{ + if ( ci_strequ(t,"on")) MRhoisting = 1; + else if ( ci_strequ(t,"off")==0 ) MRhoisting = 0; + if (MRhoisting) { + fprintf(stderr,"Maintenance Release style hoisting enabled for predicates with lookahead depth = 1\n"); + fprintf(stderr," No longer considered experimental\n"); + fprintf(stderr," Can't consider suppression for predicates with lookahead depth > 1\n"); + fprintf(stderr," Implies -prc on but does *not* imply -mrhoistk for k>1 predicates\n"); + fprintf(stderr," This is a reminder, not a warning or error.\n"); + }; +} + +static void +#ifdef __USE_PROTOS +pMRhoistk( char *s, char *t ) +#else +pMRhoistk(s,t) +char *s; +char *t; +#endif +{ + if ( ci_strequ(t,"on")) MRhoistingk = 1; + else if ( ci_strequ(t,"off")==0 ) MRhoistingk = 0; + if (MRhoistingk) { + fprintf(stderr,"EXPERIMENTAL Maintenance Release style hoisting enabled\n"); + fprintf(stderr," Applies to predicates with lookahead depth > 1\n"); + fprintf(stderr," Implies -prc on and -mrhoist on\n"); + }; +} + +static void +#ifdef __USE_PROTOS +pTRes( char *s, char *t ) +#else +pTRes( s, t ) +char *s; +char *t; +#endif +{ + TreeResourceLimit = atoi(t); + if ( TreeResourceLimit <= 0 ) + { + warnNoFL("analysis resource limit (# of tree nodes) must be greater than 0"); + TreeResourceLimit = -1; /* set to no limit */ + } +} + +Opt options[] = { +#ifdef __cplusplus + { "-CC", 0, (void (*)(...)) pCC, "Generate C++ output (default=FALSE)"}, + { "-ck", 1, (void (*)(...)) pCk, "Set compressed lookahead depth; fast approximate lookahead"}, + { "-cr", 0, (void (*)(...)) pCr, "Generate cross reference (default=FALSE)"}, + { "-e1", 0, (void (*)(...)) pE1, "Ambiguities/errors shown in low detail (default)"}, + { "-e2", 0, (void (*)(...)) pE2, "Ambiguities/errors shown in more detail"}, + { "-e3", 0, (void (*)(...)) pE3, + "Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"}, + { "-f", 1, (void (*)(...)) pFileList,"Read names of grammar files from specified file"}, /* MR14 */ + { "-fe", 1, (void (*)(...)) pFe, "Rename err.c"}, + { "-fh", 1, (void (*)(...)) pFHdr, "Rename stdpccts.h header (turns on -gh)"}, + { "-fl", 1, (void (*)(...)) pFl, "Rename lexical output--parser.dlg"}, + { "-fm", 1, (void (*)(...)) pFm, "Rename mode.h"}, + { "-fr", 1, (void (*)(...)) pFr, "Rename remap.h"}, + { "-ft", 1, (void (*)(...)) pFt, "Rename tokens.h"}, + { "-ga", 0, (void (*)(...)) pANSI, "Generate ANSI-compatible code (default=FALSE)"}, + { "-gc", 0, (void (*)(...)) pCGen, "Do not generate output parser code (default=FALSE)"}, + { "-gd", 0, (void (*)(...)) pTGen, "Generate code to trace rule invocation (default=FALSE)"}, + { "-ge", 0, (void (*)(...)) pEGen, "Generate an error class for each non-terminal (default=FALSE)"}, + { "-gh", 0, (void (*)(...)) pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"}, + { "-gk", 0, (void (*)(...)) pDL, "Generate parsers that delay lookahead fetches until needed"}, + { "-gl", 0, (void (*)(...)) pLI, "Generate line info about grammar actions in parser"}, + { "-glms", 0, (void (*)(...)) pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"}, + { "-gp", 1, (void (*)(...)) pPre, "Prefix all generated rule functions with a string"}, + { "-gs", 0, (void (*)(...)) pSGen, "Do not generate sets for token expression lists (default=FALSE)"}, + { "-gt", 0, (void (*)(...)) pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"}, + { "-gx", 0, (void (*)(...)) pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"}, + { "-gxt",0, (void (*)(...)) pXTGen, "Do not generate tokens.h (default=FALSE)"}, + { "-k", 1, (void (*)(...)) pLLK, "Set full LL(k) lookahead depth (default==1)"}, + { "-o", 1, (void (*)(...)) pOut, OutputDirectoryOption}, + { "-p", 0, (void (*)(...)) pPrt, "Print out the grammar w/o actions (default=no)"}, + { "-pa", 0, (void (*)(...)) pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"}, + { "-pr",0, (void (*)(...)) pPred, "no longer used; predicates employed if present"}, + { "-prc", 1, (void (*)(...)) pPredCtx,"Turn on/off computation of context for hoisted predicates"}, + { "-rl", 1, (void (*)(...)) pTRes, "Limit max # of tree nodes used by grammar analysis"}, + { "-stdout",0, (void (*)(...)) pStdout,"Send grammar.c/grammar.cpp to stdout"}, /* MR6 */ + { "-tab", 1, (void (*)(...)) pTab, "Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */ + { "-w1", 0, (void (*)(...)) pW1, "Set the warning level to 1 (default)"}, + { "-w2", 0, (void (*)(...)) pW2, "Ambiguities yield warnings even if predicates or (...)? block"}, + { "-", 0, (void (*)(...)) pStdin, "Read grammar from stdin" }, + { "-mrhoist",1, (void (*)(...)) pMRhoist, /* MR9 */ + "Turn on/off k=1 Maintenance Release style hoisting"}, /* MR9 */ + { "-mrhoistk",1, (void (*)(...)) pMRhoistk, /* MR9 */ + "Turn on/off EXPERIMENTAL k>1 Maintenance Release style hoisting"}, /* MR13 */ + { "-aa" , 1, (void (*)(...)) pAA, "Ambiguity aid for a rule (rule name or line number)"}, /* MR11 */ + { "-aam" , 0, (void (*)(...)) pAAm, + "Lookahead token may appear multiple times in -aa listing"}, /* MR11 */ + { "-aad" , 1, (void (*)(...)) pAAd, + "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */ + { "-info", 1, (void (*)(...)) pInfo, + "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"}, /* MR12 */ + { "-treport",1,(void (*)(...)) pTreport, + "Report when tnode usage exceeds value during ambiguity resolution"}, /* MR11 */ + { "-newAST", 0, (void (*)(...)) pNewAST, + "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""}, /* MR13 */ + { "-tmake", 0, (void (*)(...)) ptmakeInParser, + "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""}, /* MR23 */ + { "-alpha",0,(void (*)(...)) pAlpha, + "Provide additional information for \"(alpha)? beta\" error messages"}, /* MR14 */ + { "-mrblkerr",0,(void (*)(...)) pMR_BlkErr, /* MR21 */ + "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"}, /* MR21 */ + { "-nopurify",0,(void (*)(...)) pNOPURIFY, + "Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"}, /* MR23 */ + { "*", 0, (void (*)(...)) pFile, "" }, /* anything else is a file */ +#else + { "-CC", 0, pCC, "Generate C++ output (default=FALSE)"}, + { "-cr", 0, pCr, "Generate cross reference (default=FALSE)"}, + { "-ck", 1, pCk, "Set compressed lookahead depth; fast approximate lookahead"}, + { "-e1", 0, pE1, "Ambiguities/errors shown in low detail (default)"}, + { "-e2", 0, pE2, "Ambiguities/errors shown in more detail"}, + { "-e3", 0, pE3, "Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"}, + { "-f", 1, pFileList,"Read names of grammar files from specified file"}, /* MR14 */ + { "-fe", 1, pFe, "Rename err.c"}, + { "-fh", 1, pFHdr, "Rename stdpccts.h header (turns on -gh)"}, + { "-fl", 1, pFl, "Rename lexical output--parser.dlg"}, + { "-fm", 1, pFm, "Rename mode.h"}, + { "-fr", 1, pFr, "Rename remap.h"}, + { "-ft", 1, pFt, "Rename tokens.h"}, + { "-ga", 0, pANSI, "Generate ANSI-compatible code (default=FALSE)"}, + { "-gc", 0, pCGen, "Do not generate output parser code (default=FALSE)"}, + { "-gd", 0, pTGen, "Generate code to trace rule invocation (default=FALSE)"}, + { "-ge", 0, pEGen, "Generate an error class for each non-terminal (default=FALSE)"}, + { "-gh", 0, pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"}, + { "-gk", 0, pDL, "Generate parsers that delay lookahead fetches until needed"}, + { "-gl", 0, pLI, "Generate line info about grammar actions in C parser"}, + { "-glms", 0, pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"}, + { "-gp", 1, pPre, "Prefix all generated rule functions with a string"}, + { "-gs", 0, pSGen, "Do not generate sets for token expression lists (default=FALSE)"}, + { "-gt", 0, pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"}, + { "-gx", 0, pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"}, + { "-gxt",0, pXTGen, "Do not generate tokens.h (default=FALSE)"}, + { "-k", 1, pLLK, "Set full LL(k) lookahead depth (default==1)"}, + { "-o", 1, pOut, OutputDirectoryOption}, + { "-p", 0, pPrt, "Print out the grammar w/o actions (default=no)"}, + { "-pa", 0, pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"}, + { "-pr",0, pPred, "no longer used; predicates employed if present"}, + { "-prc", 1, pPredCtx,"Turn on/off computation of context for hoisted predicates"}, + { "-rl", 1, pTRes, "Limit max # of tree nodes used by grammar analysis"}, + { "-stdout",0, pStdout, "Send grammar.c/grammar.cpp to stdout"}, /* MR6 */ + { "-tab", 1, pTab, "Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */ + { "-w1", 0, pW1, "Set the warning level to 1 (default)"}, + { "-w2", 0, pW2, "Ambiguities yield warnings even if predicates or (...)? block"}, + { "-mrhoist",1,pMRhoist, /* MR9 */ + "Turn on/off k=1 Maintenance Release style hoisting"}, /* MR9 */ + { "-mrhoistk",1,pMRhoistk, /* MR13 */ + "Turn on/off k>1 EXPERIMENTAL Maintenance Release style hoisting"}, /* MR13 */ + { "-aa" ,1,pAA, "Ambiguity aid for a rule (rule name or line number)"}, /* MR11 */ + { "-aam" ,0,pAAm, + "Lookahead token may appear multiple times in -aa listing"}, /* MR11 */ + { "-aad" ,1,pAAd, + "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */ + { "-info",1,pInfo, + "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"}, /* MR11 */ + { "-treport",1,pTreport, + "Report when tnode usage exceeds value during ambiguity resolution"}, /* MR11 */ + { "-newAST", 0, pNewAST, + "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""}, /* MR13 */ + { "-tmake", 0, ptmakeInParser, + "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""}, /* MR23 */ + { "-alpha",0, pAlpha, + "Provide additional information for \"(alpha)? beta\" error messages"}, /* MR14 */ + { "-mrblkerr",0,pMR_BlkErr, /* MR21 */ + "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"}, /* MR21 */ + { "-nopurify",0,pNOPURIFY, + "Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"}, /* MR23 */ + { "-", 0, pStdin, "Read grammar from stdin" }, + { "*", 0, pFile, "" }, /* anything else is a file */ +#endif + { NULL, 0, NULL } + }; + +void readDescr(); +void cleanUp(); + +#ifdef __USE_PROTOS +static void buildRulePtr( void ); +static void help( void ); +static void init( void ); +static void CompleteTokenSetRefs( void ); +static void ensure_no_C_file_collisions(char *); +static void CompleteContextGuards(void); +#else +static void buildRulePtr( ); +static void help( ); +static void init( ); +static void CompleteTokenSetRefs( ); +static void ensure_no_C_file_collisions(); +static void CompleteContextGuards(); +#endif + +static void +#ifdef __USE_PROTOS /* */ +report_numericPredLabels(ActionNode *a) +#else +report_numericPredLabels(a) +ActionNode *a; +#endif +{ /* MR10 */ + warnFL("numeric references to attributes (e.g. $i or $i.j) in semantic pred will be null during guess mode", /* MR10 */ + FileStr[a->file],a->line); /* MR10 */ +} /* MR10 */ + + /* M a i n */ + +int +#ifdef __USE_PROTOS +main( int argc, char *argv[] ) +#else +main( argc, argv ) +int argc; +char *argv[]; +#endif +{ + int i; + static char EPSTR[] = "[Ep]"; + + Save_argc=argc; /* MR10 */ + Save_argv=argv; /* MR10 */ + +/* malloc_debug(8);*/ + +#ifdef SPECIAL_INITS + special_inits(); /* MR1 */ +#endif + fprintf(stderr, "Antlr parser generator Version %s 1989-2001\n", Version); + if ( argc == 1 ) { help(); zzDIE; } + ProcessArgs(argc-1, &(argv[1]), options); + +/* MR14 */ if (MR_AmbAidRule && AlphaBetaTrace) { +/* MR14 */ fatal("Can't specify both -aa (ambiguity aid) and -alpha (\"(alpha)? beta\" aid)"); +/* MR14 */ } + + if (MRhoistingk) { /* MR13 */ + HoistPredicateContext=1; /* MR13 */ + MRhoisting=1; /* MR13 */ + }; /* MR13 */ + if (MRhoisting && ! HoistPredicateContext) { +/*** warnNoFL("Using \"-mrhoist\" forces \"-prc on\""); ***/ + HoistPredicateContext=1; + }; + if (HoistPredicateContext && ! MRhoisting) { + warnNoFL("When using predicate context (-prc on) -mrhoist on is recommended"); + } + /* Fix lookahead depth */ + /* Compressed lookahead must always be larger than or equal to full lookahead */ + if ( CLL_k < LL_k && CLL_k>0 ) + { + warnNoFL("must have compressed lookahead >= full LL(k) lookahead (setting -ck to -k)"); + CLL_k = LL_k; + } + if ( CLL_k == -1 ) CLL_k = LL_k; + OutputLL_k = CLL_k; + if ( ((CLL_k-1)&CLL_k)!=0 ) { /* output ll(k) must be power of 2 */ + int n; + for(n=1; n 1) { + warnNoFL("The -mrblkerr option is designed only for k=1 ck=1 grammars"); + } + }; + + if ( ! ambAidDepthSpecified) { + MR_AmbAidDepth=1; + } else { + if (MR_AmbAidDepth > CLL_k || MR_AmbAidDepth <= 0) { + warnNoFL(eMsgd( + "Ambiguity aid depth (\"-aad ...\") must be a number between 1 and max(k,ck)=%d",CLL_k)); + MR_AmbAidDepth=1; + }; + if (MR_AmbAidDepth == 0) { + MR_AmbAidDepth=2; + }; + }; + + if (MR_AmbAidRule != NULL) MR_AmbAidLine=atoi(MR_AmbAidRule); + + fpTrans = &(C_Trans[0]); /* Translate to C Language */ + fpJTrans = &(C_JTrans[0]); + init(); + lexclass(LexStartSymbol); + + readDescr(); + LastTokenCounted = TokenNum; + RemapForcedTokens(); + if ( CannotContinue ) {cleanUp(); zzDIE;} + if ( GenCC && no_classes_found ) fatal("required grammar class not found (exiting...)"); + if ( WarningLevel>1 && HdrAction == NULL ) + warnNoFL("no #header action was found"); + if ( FoundAtOperator && ! FoundExceptionGroup) { + warnNoFL("found the exception operator '@' - but no exception group was found"); + }; + EpToken = addTname(EPSTR); /* add imaginary token epsilon */ + set_orel(EpToken, &imag_tokens); + + /* this won't work for hand-built scanners since EofToken is not + * known. Forces EOF to be token type 1. + */ + set_orel(EofToken, &imag_tokens); + + set_size(NumWords(TokenNum-1)); + + /* compute the set of all known token types + * It represents the set of tokens from 1 to last_token_num + the + * reserved positions above that (if any). Don't include the set of + * imaginary tokens such as the token/error classes or EOF. + */ + { + set a; + a = set_dup(reserved_positions); + for (i=1; inext; p!=NULL; p=p->next) + { + UserAction *ua = (UserAction *)p->elem; + dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1); + } + } + GenParser_c_Hdr(); + fprintf(Parser_h, "protected:\n"); /* MR20 */ + NewSetWd(); + TRANS(SynDiag); /* Translate to the target language */ + DumpSetWd(); + GenRuleMemberDeclarationsForCC(Parser_h, SynDiag); + if ( class_after_actions != NULL ) + { + ListNode *p; + for (p = class_after_actions->next; p!=NULL; p=p->next) + { + UserAction *ua = (UserAction *)p->elem; + dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1); + } + } + DumpRemainingTokSets(); + fprintf(Parser_h, "};\n"); + fprintf(Parser_h, "\n#endif /* %s_h */\n", CurrentClassName); + fclose( Parser_h ); + fclose( Parser_c ); + } + } + + MR_orphanRules(stderr); + if (LTinTokenAction && WarningLevel >= 2) { + if (GenCC) { + warnNoFL("At least one <> following a token match contains a reference to LT(...)\n this will reference the immediately preceding token,\n not the one which follows as is the case with semantic predicates."); + } + warnNoFL("At least one <> following a token match contains a reference to LA(...) or LATEXT(...)\n this will reference the immediately preceding token,\n not the one which follows as is the case with semantic predicates."); + } + + if ( PrintOut ) + { + if ( SynDiag == NULL ) {warnNoFL("no grammar description recognized");} + else PRINT(SynDiag); + } + +#ifdef DBG_LL1 +#endif + GenRemapFile(); /* create remap.h */ +/* MR10 */ if (FoundGuessBlk) { +#ifdef __cplusplus__ +/* MR10 */ list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels); +#else +#ifdef __USE_PROTOS +/* MR10 */ list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels); +#else +/* MR10 */ list_apply(NumericPredLabels,report_numericPredLabels); +#endif +#endif +/* MR10 */ }; + + if (InfoT && TnodesAllocated > 0) { + if (TnodesPeak > 10000) { + fprintf(stdout,"\nTree Nodes: peak %dk created %dk lost %d\n", + (TnodesPeak/1000), + (TnodesAllocated/1000), + TnodesInUse-tnodes_used_in_guard_predicates_etc); + } else { + fprintf(stdout,"\nTree Nodes: peak %d created %d lost %d\n", + TnodesPeak, + TnodesAllocated, + TnodesInUse-tnodes_used_in_guard_predicates_etc); + }; + }; + if (InfoF) { + DumpFcache(); + }; + if (MR_skipped_e3_report) { + fprintf(stderr,"note: use -e3 to get exact information on ambiguous tuples\n"); + }; + if (MR_BadExprSets != 0) { + fprintf(stderr,"note: Unreachable C or C++ code was generated for empty expression sets,\n"); + fprintf(stderr," probably due to undefined rules or infinite left recursion.\n"); + fprintf(stderr," To locate: search the generated code for \"empty set expression\"\n"); + }; + if (MR_AmbAidRule != NULL && MR_matched_AmbAidRule==0) { + RuleEntry *q = (RuleEntry *) hash_get(Rname,MR_AmbAidRule); + if (MR_AmbAidLine == 0 && q == NULL) { + warnNoFL(eMsg2("there is no rule \"%s\" so \"-aa %s\" will never match", + MR_AmbAidRule,MR_AmbAidRule)); + } else { + warnNoFL(eMsg1("there was no ambiguity that matched \"-aa %s\"",MR_AmbAidRule)); + }; + }; + if (AlphaBetaTrace) { + + if (MR_AlphaBetaMessageCount == 0) { + fprintf(stderr,"note: there were no messages about \"(alpha)? beta\" blocks added to the generated code\n"); + } else { + fprintf(stderr,"note: there were %d messages about \"(alpha)? beta\" blocks added to the generated code\n", + MR_AlphaBetaMessageCount); + } + + if (set_null(MR_CompromisedRules)) { + fprintf(stderr,"note: the list of rules with compromised follow sets is empty\n"); + } else { + fprintf(stderr,"note: the following is a list of rules which *may* have incorrect\n"); + fprintf(stderr," follow sets computed as a result of an \"(alpha)? beta\" block\n"); + fprintf(stderr,"\n"); + MR_dumpRuleSet(MR_CompromisedRules); + fprintf(stderr,"\n"); + } + } + cleanUp(); + exit(PCCTS_EXIT_SUCCESS); + return 0; /* MR11 make compilers happy */ +} + +static void +#ifdef __USE_PROTOS +init( void ) +#else +init( ) +#endif +{ + SignalEntry *q; + + Tname = newHashTable(); + Rname = newHashTable(); + Fcache = newHashTable(); + Tcache = newHashTable(); + Sname = newHashTable(); + Pname = newHashTable(); /* MR11 */ + + /* Add default signal names */ + q = (SignalEntry *)hash_add(Sname, + "NoViableAlt", + (Entry *)newSignalEntry("NoViableAlt")); + require(q!=NULL, "cannot alloc signal entry"); + q->signum = sigNoViableAlt; + q = (SignalEntry *)hash_add(Sname, + "MismatchedToken", + (Entry *)newSignalEntry("MismatchedToken")); + require(q!=NULL, "cannot alloc signal entry"); + q->signum = sigMismatchedToken; + q = (SignalEntry *)hash_add(Sname, + "NoSemViableAlt", + (Entry *)newSignalEntry("NoSemViableAlt")); + require(q!=NULL, "cannot alloc signal entry"); + q->signum = sigNoSemViableAlt; + + reserved_positions = empty; + all_tokens = empty; + imag_tokens = empty; + tokclasses = empty; + TokenStr = (char **) calloc(TSChunk, sizeof(char *)); + require(TokenStr!=NULL, "main: cannot allocate TokenStr"); + FoStack = (int **) calloc(CLL_k+1, sizeof(int *)); + require(FoStack!=NULL, "main: cannot allocate FoStack"); + FoTOS = (int **) calloc(CLL_k+1, sizeof(int *)); + require(FoTOS!=NULL, "main: cannot allocate FoTOS"); + Cycles = (ListNode **) calloc(CLL_k+1, sizeof(ListNode *)); + require(Cycles!=NULL, "main: cannot allocate Cycles List"); + MR_CompromisedRules=empty; /* MR14 */ +} + +static void +#ifdef __USE_PROTOS +help( void ) +#else +help( ) +#endif +{ + Opt *p = options; + fprintf(stderr, "antlr [options] f1 f2 ... fn\n"); + while ( *(p->option) != '*' ) + { + fprintf(stderr, " %-9s%s %s\n", + p->option, + (p->arg)?"___":" ", + p->descr); + p++; + } +} + +/* The RulePtr array is filled in here. RulePtr exists primarily + * so that sets of rules can be maintained for the FOLLOW caching + * mechanism found in rJunc(). RulePtr maps a rule num from 1 to n + * to a pointer to its RuleBlk junction where n is the number of rules. + */ +static void +#ifdef __USE_PROTOS +buildRulePtr( void ) +#else +buildRulePtr( ) +#endif +{ + int r=1; + Junction *p = SynDiag; + RulePtr = (Junction **) calloc(NumRules+1, sizeof(Junction *)); + require(RulePtr!=NULL, "cannot allocate RulePtr array"); + + while ( p!=NULL ) + { + require(r<=NumRules, "too many rules???"); + RulePtr[r++] = p; + p = (Junction *)p->p2; + } +} + +void +#ifdef __USE_PROTOS +dlgerror(const char *s) +#else +dlgerror(s) +char *s; +#endif +{ + fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); + fprintf(stderr, " lexical error: %s (text was '%s')\n", + ((s == NULL) ? "Lexical error" : s), zzlextext); +} + +void +#ifdef __USE_PROTOS +readDescr( void ) +#else +readDescr( ) +#endif +{ + zzerr = dlgerror; + input = NextFile(); + if ( input==NULL ) fatal("No grammar description found (exiting...)"); + ANTLR(grammar(), input); + tnodes_used_in_guard_predicates_etc=TnodesInUse; /* MR10 */ +} + +FILE * +#ifdef __USE_PROTOS +NextFile( void ) +#else +NextFile( ) +#endif +{ + FILE *f; + + for (;;) + { + CurFile++; + if ( CurFile >= NumFiles ) return(NULL); + if ( ci_strequ(FileStr[CurFile],"stdin")) return stdin; + f = fopen(FileStr[CurFile], "r"); + if ( f == NULL ) + { + warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) ); + } + else + { + return(f); + } + } +} + +/* + * Return a string corresponding to the output file name associated + * with the input file name passed in. + * + * Observe the following rules: + * + * f.e --> f".c" + * f --> f".c" + * f. --> f".c" + * f.e.g --> f.e".c" + * + * Where f,e,g are arbitrarily long sequences of characters in a file + * name. + * + * In other words, if a ".x" appears on the end of a file name, make it + * ".c". If no ".x" appears, append ".c" to the end of the file name. + * + * C++ mode using .cpp not .c. + * + * Use malloc() for new string. + */ + +char * +#ifdef __USE_PROTOS +outname( char *fs ) +#else +outname( fs ) +char *fs; +#endif +{ + if ( GenCC) { + return outnameX(fs,CPP_FILE_SUFFIX); + } else { + return outnameX(fs,".c"); + }; +} + +char * +#ifdef __USE_PROTOS +outnameX( char *fs ,char *suffix) +#else +outnameX( fs , suffix ) +char *fs; +char *suffix; +#endif +{ + static char buf[MaxFileName+1]; + char *p; + require(fs!=NULL&&*fs!='\0', "outname: NULL filename"); + + p = buf; + strcpy(buf, fs); + while ( *p != '\0' ) {p++;} /* Stop on '\0' */ + while ( *p != '.' && p != buf ) {--p;} /* Find '.' */ + if ( p != buf ) *p = '\0'; /* Found '.' */ + require(strlen(buf) + 2 < (size_t)MaxFileName, "outname: filename too big"); + strcat(buf,suffix); + return( buf ); +} + +void +#ifdef __USE_PROTOS +fatalFL( char *err_, char *f, int l ) +#else +fatalFL( err_, f, l ) +char *err_; +char *f; +int l; +#endif +{ + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " %s\n", err_); + cleanUp(); + exit(PCCTS_EXIT_FAILURE); +} + +void +#ifdef __USE_PROTOS +fatal_intern( char *err_, char *f, int l ) +#else +fatal_intern( err_, f, l ) +char *err_; +char *f; +int l; +#endif +{ + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " #$%%*&@# internal error: %s\n", err_); + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " [complain to nearest government official\n"); + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " or send hate-mail to parrt@parr-research.com;\n"); + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " please pray to the ``bug'' gods that there is a trival fix.]\n"); + cleanUp(); + exit(PCCTS_EXIT_FAILURE); +} + +void +#ifdef __USE_PROTOS +cleanUp( void ) +#else +cleanUp( ) +#endif +{ + if ( DefFile != NULL) fclose( DefFile ); +} + +/* sprintf up to 3 strings */ +char * +#ifdef __USE_PROTOS +eMsg3( char *s, char *a1, char *a2, char *a3 ) +#else +eMsg3( s, a1, a2, a3 ) +char *s; +char *a1; +char *a2; +char *a3; +#endif +{ + static char buf[250]; /* DANGEROUS as hell !!!!!! */ + + sprintf(buf, s, a1, a2, a3); + return( buf ); +} + +/* sprintf a decimal */ +char * +#ifdef __USE_PROTOS +eMsgd( char *s, int d ) +#else +eMsgd( s, d ) +char *s; +int d; +#endif +{ + static char buf[250]; /* DANGEROUS as hell !!!!!! */ + + sprintf(buf, s, d); + return( buf ); +} + +char * +#ifdef __USE_PROTOS +eMsgd2( char *s, int d1,int d2) +#else +eMsgd2( s, d1, d2 ) +char *s; +int d1; +int d2; +#endif +{ + static char buf[250]; /* DANGEROUS as hell !!!!!! */ + + sprintf(buf, s, d1, d2); + return( buf ); +} + +void +#ifdef __USE_PROTOS +s_fprT( FILE *f, set e ) +#else +s_fprT( f, e ) +FILE *f; +set e; +#endif +{ + register unsigned *p; + unsigned *q; + + if ( set_nil(e) ) return; + if ( (q=p=set_pdq(e)) == NULL ) fatal_internal("Can't alloc space for set_pdq"); + fprintf(f, "{"); + while ( *p != nil ) + { + fprintf(f, " %s", TerminalString(*p)); + p++; + } + fprintf(f, " }"); + free((char *)q); +} + +/* Return the token name or regular expression for a token number. */ +char * +#ifdef __USE_PROTOS +TerminalString( int token ) +#else +TerminalString( token ) +int token; +#endif +{ + int j; + static char imag_name[20]; + + /* look in all lexclasses for the token */ + if ( TokenString(token) != NULL ) return TokenString(token); + for (j=0; j0, "pushint: stack overflow"); + istack[--isp] = i; +} + +int +#ifdef __USE_PROTOS +popint( void ) +#else +popint( ) +#endif +{ + require(isp 0 ) + { + p = options; + while ( p->option != NULL ) + { + if ( strcmp(p->option, "*") == 0 || + ci_strequ(p->option, *argv) == 1 ) + { + if ( p->arg ) + { +/* MR9 26-Sep-97 Check for argv valid */ + if (argc-- > 0) { + (*p->process)( *argv, *(argv+1) ); + argv++; + } else { +fprintf(stderr,"error: required argument for option %s omitted\n",*argv); +exit(PCCTS_EXIT_FAILURE); + }; + } + else + (*p->process)( *argv ); + break; + } + p++; + } + argv++; + } +} + +static void +#ifdef __USE_PROTOS +CompleteContextGuards(void) +#else +CompleteContextGuards() +#endif +{ + ListNode * p; + Predicate * pred; + + if (ContextGuardPredicateList == NULL) return; + + for (p=ContextGuardPredicateList->next; p != NULL; p=p->next) { + pred=(Predicate *)p->elem; + recomputeContextGuard(pred); + } +} + +/* Go back into the syntax diagram and compute all meta tokens; i.e. + * turn all '.', ranges, token class refs etc... into actual token sets + */ +static void +#ifdef __USE_PROTOS +CompleteTokenSetRefs(void) +#else +CompleteTokenSetRefs() +#endif +{ + ListNode *p; + + if ( MetaTokenNodes==NULL ) return; + for (p = MetaTokenNodes->next; p!=NULL; p=p->next) + { + set a,b; + + TokNode *q = (TokNode *)p->elem; + if ( q->wild_card ) + { + q->tset = all_tokens; + } + else if ( q->tclass!=NULL ) + { + if ( q->complement ) q->tset = set_dif(all_tokens, q->tclass->tset); + else q->tset = q->tclass->tset; + } + else if ( q->upper_range!=0 ) + { + /* we have a range on our hands: make a set from q->token .. q->upper_range */ + int i; + a = empty; + for (i=q->token; i<=q->upper_range; i++) { set_orel(i, &a); } /* MR13 */ + +/* MR13 */ if (q->complement) { +/* MR13 */ q->tset = set_dif(all_tokens, a); +/* MR13 */ set_free(a); +/* MR13 */ } else { +/* MR13 */ q->tset = a; +/* MR13 */ } + + } + + /* at this point, it can only be a complemented single token */ + else if ( q->complement ) + { + a = set_of(q->token); + b = set_dif(all_tokens, a); + set_free(a); + q->tset=b; + } + else fatal("invalid meta token"); + } +} + +/* MR10: Jeff Vincent + MR10: Changed to remove directory information from n only if + MR10: if OutputDirectory was changed by user (-o option) +*/ + +char * +#ifdef __USE_PROTOS +OutMetaName(char *n) +#else +OutMetaName(n) +char *n; +#endif +{ + static char *dir_sym = DirectorySymbol; + static char newname[MaxFileName+1]; + char *p; + + /* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */ + if (strcmp(OutputDirectory, TopDirectory) == 0) /* TopDirectory is "." on Unix. */ + return n; + + /* p will point to filename without path information */ + if ((p = strrchr(n, *dir_sym)) != NULL) /* Directory symbol is "/" on Unix. */ + p++; + else + p = n; + + /* Copy new output directory into newname[] */ + strcpy(newname, OutputDirectory); + + /* if new output directory does not have trailing dir_sym, add it! */ + if (newname[strlen(newname)-1] != *dir_sym) { + strcat(newname, dir_sym); + } + strcat(newname, p); + return newname; +} + +char * +#ifdef __USE_PROTOS +pcctsBaseName(char *n) /* MR32 */ +#else +pcctsBaseName(n) +char *n; +#endif +{ + static char newname[MaxFileName+1]; + static char* dir_sym = DirectorySymbol; + int count = 0; + char *p; + + p = n; + + while ( *p != '\0' ) {p++;} /* go to end of string */ + while ( (*p != *dir_sym) && (p != n) ) {--p;} /* Find last DirectorySymbol */ + while ( *p == *dir_sym) p++; /* step forward if we're on a dir symbol */ + while ( *p != '\0' && *p != '.') + { + newname[count++] = *p; + p++; + } /* create a new name */ + newname[count] = '\0'; + return newname; +} + +static void +#ifdef __USE_PROTOS +ensure_no_C_file_collisions(char *class_c_file) +#else +ensure_no_C_file_collisions(class_c_file) +char *class_c_file; +#endif +{ + int i; + + for (i=0; i= NumFiles && CurFile >= 1 ) CurFile--; + fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); + fprintf(stderr, " warning: %s\n", err); +} + +void +#ifdef __USE_PROTOS +warnNoCR( char *err ) +#else +warnNoCR( err ) +char *err; +#endif +{ + /* back up the file number if we hit an error at the end of the last file */ + if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; + fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); + fprintf(stderr, " warning: %s", err); +} + +void +#ifdef __USE_PROTOS +errNoFL(char *err) +#else +errNoFL(err) +char *err; +#endif +{ + fprintf(stderr, "error: %s\n", err); +} + +void +#ifdef __USE_PROTOS +errFL(char *err,char *f,int l) +#else +errFL(err,f,l) +char *err; +char *f; +int l; +#endif +{ + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " error: %s\n", err); +} + +void +#ifdef __USE_PROTOS +err(char *err) +#else +err(err) +char *err; +#endif +{ + /* back up the file number if we hit an error at the end of the last file */ + if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; + fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); + fprintf(stderr, " error: %s\n", err); +} + +void +#ifdef __USE_PROTOS +errNoCR( char *err ) +#else +errNoCR( err ) +char *err; +#endif +{ + /* back up the file number if we hit an error at the end of the last file */ + if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; + fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); + fprintf(stderr, " error: %s", err); +} + +UserAction * +#ifdef __USE_PROTOS +newUserAction(char *s) +#else +newUserAction(s) +char *s; +#endif +{ + UserAction *ua = (UserAction *) calloc(1, sizeof(UserAction)); + require(ua!=NULL, "cannot allocate UserAction"); + + ua->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + strcpy(ua->action, s); + return ua; +} + +/* Added by TJP September 1994 */ +/* Take in file.h and return file_h; names w/o '.'s are left alone */ +char * +#ifdef __USE_PROTOS +gate_symbol(char *name) +#else +gate_symbol(name) +char *name; +#endif +{ + static char buf[100]; + char *p; + sprintf(buf, "%s", name); + + for (p=buf; *p!='\0'; p++) + { + if ( *p=='.' ) *p = '_'; + } + return buf; +} + +char * +#ifdef __USE_PROTOS +makeAltID(int blockid, int altnum) +#else +makeAltID(blockid, altnum) +int blockid; +int altnum; +#endif +{ + static char buf[100]; + char *p; + sprintf(buf, "_blk%d_alt%d", blockid, altnum); + p = (char *)malloc(strlen(buf)+1); + strcpy(p, buf); + return p; +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/makefile b/Tools/Source/TianoTools/Pccts/antlr/makefile new file mode 100644 index 0000000000..a528001bdf --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/makefile @@ -0,0 +1,218 @@ +# +# Makefile for ANTLR 1.33 +# +# SOFTWARE RIGHTS +# +# We reserve no LEGAL rights to the Purdue Compiler Construction Tool +# Set (PCCTS) -- PCCTS is in the public domain. An individual or +# company may do whatever they wish with source code distributed with +# PCCTS or the code generated by PCCTS, including the incorporation of +# PCCTS, or its output, into commerical software. +# +# We encourage users to develop software with PCCTS. However, we do ask +# that credit is given to us for developing PCCTS. By "credit", +# we mean that if you incorporate our source code into one of your +# programs (commercial product, research project, or otherwise) that you +# acknowledge this fact somewhere in the documentation, research report, +# etc... If you like PCCTS and have developed a nice tool with the +# output, please mention that you developed it using PCCTS. In +# addition, we ask that this header remain intact in our source code. +# As long as these guidelines are kept, we expect to continue enhancing +# this system and expect to make other tools available as they are +# completed. +# +# ANTLR 1.33 +# Terence Parr +# Parr Research Corporation +# with Purdue University +# and AHPCRC, University of Minnesota +# 1989-1995 +# +# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by +# Ed Harfmann +# Micro Data Base Systems +# Lafayette, Indiana +# +SET=../support/set +PCCTS_H=../h + +## +## Uncomment the appropriate section to build +## (both targets and 'make' variable definitions) +## Note that UNIX is the default +## + +# +# OS/2 & DOS 16 bit using MSC 6.0 +# +#CC=cl +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN +#OUT_OBJ = -Fo +#LIBS=/NOD:LLIBCE LLIBCEP +#OBJ_EXT = obj +# +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egamn.obj +# link @<< +#$** /NOI +#$@ /STACK:14336 +# +#$(LIBS: = +^ +#) +#$(DEF_FILE) $(LFLAGS) ; +#<< +# bind $@ c:\os2\doscalls.lib +# copy *.exe ..\bin +# + +# +# Borland C++ for DOS +# +#CC=bcc +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN +#OUT_OBJ = -o +#LIBS= emu mathl cl +#OBJ_EXT = obj +# +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj +# tlink @&&| +#C0L $** +#$@ /Tde /c +# +#$(LIBS) +#$(DEF_FILE) $(LFLAGS) ; +#| +# copy *.exe ..\bin +# + +# +# C-Set/2 for OS/2 +# +#CC=icc +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 -DUSER_ZZSYN -D__STDC__ +#OUT_OBJ = -Fo +#LIBS= +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#OBJ_EXT = obj +# +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj +# link386 @<< +#$** /NOI +#$@ /STACK:32768 +# +#$(LIBS: = +^ +#) +#$(DEF_FILE) $(LFLAGS) ; +#<< +# copy *.exe ..\bin +# + +# +# Borland C++ for OS/2 +# +#CC=bcc +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -v -DUSER_ZZSYN +#OUT_OBJ = -o +#LIBS= c2 os2 +# +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#OBJ_EXT = obj +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj +# tlink @&&| +#c02 $** -c -v +#antlr.exe +# +#C2 os2 +# +#| +# copy *.exe ..\bin +# + +# *********** Target list of PC machines *********** +# +# Don't worry about the ambiguity messages coming from antlr +# for making antlr.c etc... [should be 10 of them, I think] +# +#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g +# $(ANTLR) antlr.g +# +#antlr.$(OBJ_EXT): antlr.c mode.h tokens.h +# +#scan.$(OBJ_EXT): scan.c mode.h tokens.h +# +#scan.c mode.h: parser.dlg +# $(DLG) -C2 parser.dlg scan.c +# +#set.$(OBJ_EXT): $(SET)/set.c +# $(CC) $(CFLAGS) -c $(OUT_OBJ)set.$(OBJ_EXT) $(SET)/set.c + + + +# +# UNIX (default) +# +CC=gcc +COPT=-O +ANTLR=../bin/antlr +DLG=../bin/dlg +OBJ_EXT=o +OUT_OBJ = -o +CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) -DZZLEXBUFSIZE=65536 +# +# SGI Users, use this CFLAGS +# +#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262 +OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o \ + globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o + +antlr : $(OBJ) $(SRC) + $(CC) $(CFLAGS) -o ${WORKSPACE}/Tools/bin/antlr $(OBJ) + +# what files does PCCTS generate (both ANTLR and DLG) +PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h + +SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \ + hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c + +# +# Don't worry about the ambiguity messages coming from antlr +# for making antlr.c etc... [should be 10 of them, I think] +# +#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g +# $(ANTLR) -gh antlr.g + +antlr.o : antlr.c mode.h tokens.h + +scan.o : scan.c mode.h tokens.h + +#scan.c mode.h: parser.dlg +# $(DLG) -C2 parser.dlg scan.c + +set.o : $(SET)/set.c + $(CC) $(CFLAGS) -c -o set.o $(SET)/set.c + + +# +# ****** These next targets are common to UNIX and PC world ******** +# + +#clean up all the intermediate files +clean: + rm -f *.$(OBJ_EXT) core + +#remove everything in clean plus the PCCTS files generated +scrub: + rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core diff --git a/Tools/Source/TianoTools/Pccts/antlr/makefile1 b/Tools/Source/TianoTools/Pccts/antlr/makefile1 new file mode 100644 index 0000000000..5c4a275d59 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/makefile1 @@ -0,0 +1,96 @@ +# +# Makefile for ANTLR 1.33 +# +# SOFTWARE RIGHTS +# +# We reserve no LEGAL rights to the Purdue Compiler Construction Tool +# Set (PCCTS) -- PCCTS is in the public domain. An individual or +# company may do whatever they wish with source code distributed with +# PCCTS or the code generated by PCCTS, including the incorporation of +# PCCTS, or its output, into commerical software. +# +# We encourage users to develop software with PCCTS. However, we do ask +# that credit is given to us for developing PCCTS. By "credit", +# we mean that if you incorporate our source code into one of your +# programs (commercial product, research project, or otherwise) that you +# acknowledge this fact somewhere in the documentation, research report, +# etc... If you like PCCTS and have developed a nice tool with the +# output, please mention that you developed it using PCCTS. In +# addition, we ask that this header remain intact in our source code. +# As long as these guidelines are kept, we expect to continue enhancing +# this system and expect to make other tools available as they are +# completed. +# +# ANTLR 1.33 +# Terence Parr +# Parr Research Corporation +# with Purdue University +# and AHPCRC, University of Minnesota +# 1989-1995 +# +# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by +# Ed Harfmann +# Micro Data Base Systems +# Lafayette, Indiana +# +SET=../support/set +PCCTS_H=../h + +# +# UNIX (default) +# +CC=cc +ANTLR=../bin/antlr +DLG=../bin/dlg +OBJ_EXT=o +OUT_OBJ = -o +ANSI=-ansi +AOTHER= +CFLAGS= -O0 -g -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) $(ANSI) -DZZLEXBUFSIZE=32000 +# +# SGI Users, use this CFLAGS +# +#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262 + +OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o \ + globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o $(OBJOTHER) + +antlr : $(OBJ) $(SRC) + $(CC) $(CFLAGS) -o antlr $(OBJ) + mv antlr ../bin + +# what files does PCCTS generate (both ANTLR and DLG) +PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h + +SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \ + hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c + +# +# Don't worry about the ambiguity messages coming from antlr +# for making antlr.c etc... [should be 10 of them, I think] +# +antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g + $(ANTLR) -gh antlr.g $(AOTHER) + +antlr.o : antlr.c mode.h tokens.h + +scan.o : scan.c mode.h tokens.h + +scan.c mode.h: parser.dlg + $(DLG) -C2 parser.dlg scan.c + +set.o : $(SET)/set.c + $(CC) $(CFLAGS) -c -o set.o $(SET)/set.c + + +# +# ****** These next targets are common to UNIX and PC world ******** +# + +#clean up all the intermediate files +clean: + rm -f *.$(OBJ_EXT) core + +#remove everything in clean plus the PCCTS files generated +scrub: + rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core diff --git a/Tools/Source/TianoTools/Pccts/antlr/misc.c b/Tools/Source/TianoTools/Pccts/antlr/misc.c new file mode 100644 index 0000000000..3f58da34c5 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/misc.c @@ -0,0 +1,1864 @@ +/* + * misc.c + * + * Manage tokens, regular expressions. + * Print methods for debugging + * Compute follow lists onto tail ends of rules. + * + * The following functions are visible: + * + * int addTname(char *); Add token name + * int addTexpr(char *); Add token expression + * int Tnum(char *); Get number of expr/token + * void Tklink(char *, char *); Link a name with an expression + * int hasAction(expr); Does expr already have action assigned? + * void setHasAction(expr); Indicate that expr now has an action + * Entry *newEntry(char *,int); Create new table entry with certain size + * void list_add(ListNode **list, char *e) + * void list_free(ListNode **list, int freeData); *** MR10 *** + * void list_apply(ListNode *list, void (*f)()) + * void lexclass(char *m); switch to new/old lexical class + * void lexmode(int i); switch to old lexical class i + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include + +static int tsize=TSChunk; /* size of token str arrays */ + +static void +#ifdef __USE_PROTOS +RemapForcedTokensInSyntaxDiagram(Node *); +#else +RemapForcedTokensInSyntaxDiagram(); +#endif + + /* T o k e n M a n i p u l a t i o n */ + +/* + * add token 't' to the TokenStr/Expr array. Make more room if necessary. + * 't' is either an expression or a token name. + * + * There is only one TokenStr array, but multiple ExprStr's. Therefore, + * for each lex class (element of lclass) we must extend the ExprStr array. + * ExprStr's and TokenStr are always all the same size. + * + * Also, there is a Texpr hash table for each automaton. + */ +static void +#ifdef __USE_PROTOS +Ttrack( char *t ) +#else +Ttrack( t ) +char *t; +#endif +{ + if ( TokenNum >= tsize ) /* terminal table overflow? */ + { + char **p; + int i, more, j; + + more = TSChunk * (1 + ((TokenNum-tsize) / TSChunk)); + tsize += more; + TokenStr = (char **) realloc((char *)TokenStr, tsize*sizeof(char *)); + require(TokenStr != NULL, "Ttrack: can't extend TokenStr"); + for (i=0; iexpr = e; + p->lclass = CurrentLexClass; + return p; +} + +/* switch to lexical class/mode m. This amounts to creating a new + * lex mode if one does not already exist and making ExprStr point + * to the correct char string array. We must also switch Texpr tables. + * + * BTW, we need multiple ExprStr arrays because more than one automaton + * may have the same label for a token, but with different expressions. + * We need to track an expr for each automaton. If we disallowed this + * feature, only one ExprStr would be required. + */ +void +#ifdef __USE_PROTOS +lexclass( char *m ) +#else +lexclass( m ) +char *m; +#endif +{ + int i; + TermEntry *p; + static char EOFSTR[] = "\"@\""; + + if ( hash_get(Tname, m) != NULL ) + { + warn(eMsg1("lexclass name conflicts with token/errclass label '%s'",m)); + } + /* does m already exist? */ + i = LexClassIndex(m); + if ( i != -1 ) {lexmode(i); return;} + /* must make new one */ + NumLexClasses++; + CurrentLexClass = NumLexClasses-1; + require(NumLexClasses<=MaxLexClasses, "number of allowable lexclasses exceeded\nIncrease MaxLexClasses in generic.h and recompile all C files"); + lclass[CurrentLexClass].classnum = m; + lclass[CurrentLexClass].exprs = (char **) calloc(tsize, sizeof(char *)); + require(lclass[CurrentLexClass].exprs!=NULL, + "lexclass: cannot allocate ExprStr"); + lclass[CurrentLexClass].htable = newHashTable(); + ExprStr = lclass[CurrentLexClass].exprs; + Texpr = lclass[CurrentLexClass].htable; + /* define EOF for each automaton */ + p = newTermEntry( EOFSTR ); + p->token = EofToken; /* couldn't have remapped tokens yet, use EofToken */ + hash_add(Texpr, EOFSTR, (Entry *)p); + list_add(&ExprOrder, (void *)newExpr(EOFSTR)); + /* note: we use the actual ExprStr array + * here as TokenInd doesn't exist yet + */ + ExprStr[EofToken] = EOFSTR; +} + +void +#ifdef __USE_PROTOS +lexmode( int i ) +#else +lexmode( i ) +int i; +#endif +{ + require(iaction!=NULL); +} + +void +#ifdef __USE_PROTOS +setHasAction( char *expr, char *action ) +#else +setHasAction( expr, action ) +char *expr; +char *action; +#endif +{ + TermEntry *p; + require(expr!=NULL, "setHasAction: invalid expr"); + + p = (TermEntry *) hash_get(Texpr, expr); + require(p!=NULL, eMsg1("setHasAction: expr '%s' doesn't exist",expr)); + p->action = action; +} + +ForcedToken * +#ifdef __USE_PROTOS +newForcedToken(char *token, int tnum) +#else +newForcedToken(token, tnum) +char *token; +int tnum; +#endif +{ + ForcedToken *ft = (ForcedToken *) calloc(1, sizeof(ForcedToken)); + require(ft!=NULL, "out of memory"); + ft->token = token; + ft->tnum = tnum; + return ft; +} + +/* + * Make a token indirection array that remaps token numbers and then walk + * the appropriate symbol tables and SynDiag to change token numbers + */ +void +#ifdef __USE_PROTOS +RemapForcedTokens(void) +#else +RemapForcedTokens() +#endif +{ + ListNode *p; + ForcedToken *q; + int max_token_number=0; /* MR9 23-Sep-97 Removed "unsigned" */ + int i; + + if ( ForcedTokens == NULL ) return; + + /* find max token num */ + for (p = ForcedTokens->next; p!=NULL; p=p->next) + { + q = (ForcedToken *) p->elem; + if ( q->tnum > max_token_number ) max_token_number = q->tnum; + } + fprintf(stderr, "max token number is %d\n", max_token_number); + + /* make token indirection array */ + TokenInd = (int *) calloc(max_token_number+1, sizeof(int)); + LastTokenCounted = TokenNum; + TokenNum = max_token_number+1; + require(TokenInd!=NULL, "RemapForcedTokens: cannot allocate TokenInd"); + + /* fill token indirection array and change token id htable ; swap token indices */ + for (i=1; inext; p!=NULL; p=p->next) + { + TermEntry *te; + int old_pos, t; + + q = (ForcedToken *) p->elem; + fprintf(stderr, "%s forced to %d\n", q->token, q->tnum); + te = (TermEntry *) hash_get(Tname, q->token); + require(te!=NULL, "RemapForcedTokens: token not in hash table"); + old_pos = te->token; + fprintf(stderr, "Before: TokenInd[old_pos==%d] is %d\n", old_pos, TokenInd[old_pos]); + fprintf(stderr, "Before: TokenInd[target==%d] is %d\n", q->tnum, TokenInd[q->tnum]); + q = (ForcedToken *) p->elem; + t = TokenInd[old_pos]; + TokenInd[old_pos] = q->tnum; + TokenInd[q->tnum] = t; + te->token = q->tnum; /* update token type id symbol table */ + fprintf(stderr, "After: TokenInd[old_pos==%d] is %d\n", old_pos, TokenInd[old_pos]); + fprintf(stderr, "After: TokenInd[target==%d] is %d\n", q->tnum, TokenInd[q->tnum]); + + /* Change the token number in the sym tab entry for the exprs + * at the old position of the token id and the target position + */ + /* update expr at target (if any) of forced token id */ + if ( q->tnum < TokenNum ) /* is it a valid position? */ + { + for (i=0; itnum]!=NULL ) + { + /* update the symbol table for this expr */ + TermEntry *e = (TermEntry *) hash_get(lclass[i].htable, lclass[i].exprs[q->tnum]); + require(e!=NULL, "RemapForcedTokens: expr not in hash table"); + e->token = old_pos; + fprintf(stderr, "found expr '%s' at target %d in lclass[%d]; changed to %d\n", + lclass[i].exprs[q->tnum], q->tnum, i, old_pos); + } + } + } + /* update expr at old position (if any) of forced token id */ + for (i=0; itoken = q->tnum; + fprintf(stderr, "found expr '%s' for id %s in lclass[%d]; changed to %d\n", + lclass[i].exprs[old_pos], q->token, i, q->tnum); + } + } + } + + /* Update SynDiag */ + RemapForcedTokensInSyntaxDiagram((Node *)SynDiag); +} + +static void +#ifdef __USE_PROTOS +RemapForcedTokensInSyntaxDiagram(Node *p) +#else +RemapForcedTokensInSyntaxDiagram(p) +Node *p; +#endif +{ + Junction *j = (Junction *) p; + RuleRefNode *r = (RuleRefNode *) p; + TokNode *t = (TokNode *)p; + + if ( p==NULL ) return; + require(p->ntype>=1 && p->ntype<=NumNodeTypes, "Remap...: invalid diagram node"); + switch ( p->ntype ) + { + case nJunction : + if ( j->visited ) return; + if ( j->jtype == EndRule ) return; + j->visited = TRUE; + RemapForcedTokensInSyntaxDiagram( j->p1 ); + RemapForcedTokensInSyntaxDiagram( j->p2 ); + j->visited = FALSE; + return; + case nRuleRef : + RemapForcedTokensInSyntaxDiagram( r->next ); + return; + case nToken : + if ( t->remapped ) return; /* we've been here before */ + t->remapped = 1; + fprintf(stderr, "remapping %d to %d\n", t->token, TokenInd[t->token]); + t->token = TokenInd[t->token]; + RemapForcedTokensInSyntaxDiagram( t->next ); + return; + case nAction : + RemapForcedTokensInSyntaxDiagram( ((ActionNode *)p)->next ); + return; + default : + fatal_internal("invalid node type"); + } +} + +/* + * Add a token name. Return the token number associated with it. If it already + * exists, then return the token number assigned to it. + * + * Track the order in which tokens are found so that the DLG output maintains + * that order. It also lets us map token numbers to strings. + */ +int +#ifdef __USE_PROTOS +addTname( char *token ) +#else +addTname( token ) +char *token; +#endif +{ + TermEntry *p; + require(token!=NULL, "addTname: invalid token name"); + + if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token; + p = newTermEntry( token ); + Ttrack( p->str ); + p->token = TokenNum++; + hash_add(Tname, token, (Entry *)p); + return p->token; +} + +/* This is the same as addTname except we force the TokenNum to be tnum. + * We don't have to use the Forced token stuff as no tokens will have + * been defined with #tokens when this is called. This is only called + * when a #tokdefs meta-op is used. + */ +int +#ifdef __USE_PROTOS +addForcedTname( char *token, int tnum ) +#else +addForcedTname( token, tnum ) +char *token; +int tnum; +#endif +{ + TermEntry *p; + require(token!=NULL, "addTname: invalid token name"); + + if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token; + p = newTermEntry( token ); + Ttrack( p->str ); + p->token = tnum; + hash_add(Tname, token, (Entry *)p); + return p->token; +} + +/* + * Add a token expr. Return the token number associated with it. If it already + * exists, then return the token number assigned to it. + */ +int +#ifdef __USE_PROTOS +addTexpr( char *expr ) +#else +addTexpr( expr ) +char *expr; +#endif +{ + TermEntry *p; + require(expr!=NULL, "addTexpr: invalid regular expression"); + + if ( (p=(TermEntry *)hash_get(Texpr, expr)) != NULL ) return p->token; + p = newTermEntry( expr ); + Ttrack( p->str ); + /* track the order in which they occur */ + list_add(&ExprOrder, (void *)newExpr(p->str)); + p->token = TokenNum++; + hash_add(Texpr, expr, (Entry *)p); + return p->token; +} + +/* return the token number of 'term'. Return 0 if no 'term' exists */ +int +#ifdef __USE_PROTOS +Tnum( char *term ) +#else +Tnum( term ) +char *term; +#endif +{ + TermEntry *p; + require(term!=NULL, "Tnum: invalid terminal"); + + if ( *term=='"' ) p = (TermEntry *) hash_get(Texpr, term); + else p = (TermEntry *) hash_get(Tname, term); + if ( p == NULL ) return 0; + else return p->token; +} + +/* associate a Name with an expr. If both have been already assigned + * token numbers, then an error is reported. Add the token or expr + * that has not been added if no error. This 'represents' the #token + * ANTLR pseudo-op. If both have not been defined, define them both + * linked to same token number. + */ +void +#ifdef __USE_PROTOS +Tklink( char *token, char *expr ) +#else +Tklink( token, expr ) +char *token; +char *expr; +#endif +{ + TermEntry *p, *q; + require(token!=NULL && expr!=NULL, "Tklink: invalid token name and/or expr"); + + p = (TermEntry *) hash_get(Tname, token); + q = (TermEntry *) hash_get(Texpr, expr); + if ( p != NULL && q != NULL ) /* both defined */ + { + warn( eMsg2("token name %s and rexpr %s already defined; ignored", + token, expr) ); + return; + } + if ( p==NULL && q==NULL ) /* both not defined */ + { + int t = addTname( token ); + q = newTermEntry( expr ); + hash_add(Texpr, expr, (Entry *)q); + q->token = t; + /* note: we use the actual ExprStr array + * here as TokenInd doesn't exist yet + */ + ExprStr[t] = q->str; + /* track the order in which they occur */ + list_add(&ExprOrder, (void *)newExpr(q->str)); + return; + } + if ( p != NULL ) /* one is defined, one is not */ + { + q = newTermEntry( expr ); + hash_add(Texpr, expr, (Entry *)q); + q->token = p->token; + ExprStr[p->token] = q->str; /* both expr and token str defined now */ + list_add(&ExprOrder, (void *)newExpr(q->str)); + } + else /* trying to associate name with expr here*/ + { + p = newTermEntry( token ); + hash_add(Tname, token, (Entry *)p); + p->token = q->token; + TokenStr[p->token] = p->str;/* both expr and token str defined now */ + } +} + +/* + * Given a string, this function allocates and returns a pointer to a + * hash table record of size 'sz' whose "str" pointer is reset to a position + * in the string table. + */ +Entry * +#ifdef __USE_PROTOS +newEntry( char *text, int sz ) +#else +newEntry( text, sz ) +char *text; +int sz; +#endif +{ + Entry *p; + require(text!=NULL, "new: NULL terminal"); + + if ( (p = (Entry *) calloc(1,sz)) == 0 ) + { + fatal_internal("newEntry: out of memory for terminals\n"); + exit(PCCTS_EXIT_FAILURE); + } + p->str = mystrdup(text); + + return(p); +} + +/* + * add an element to a list. + * + * Any non-empty list has a sentinel node whose 'elem' pointer is really + * a pointer to the last element. (i.e. length(list) = #elemIn(list)+1). + * Elements are appended to the list. + */ +void +#ifdef __USE_PROTOS +list_add( ListNode **list, void *e ) +#else +list_add( list, e ) +ListNode **list; +void *e; +#endif +{ + ListNode *p, *tail; + require(e!=NULL, "list_add: attempting to add NULL list element"); + + p = newListNode; + require(p!=NULL, "list_add: cannot alloc new list node"); + p->elem = e; + if ( *list == NULL ) + { + ListNode *sentinel = newListNode; + require(sentinel!=NULL, "list_add: cannot alloc sentinel node"); + *list=sentinel; + sentinel->next = p; + sentinel->elem = (char *)p; /* set tail pointer */ + } + else /* find end of list */ + { + tail = (ListNode *) (*list)->elem; /* get tail pointer */ + tail->next = p; + (*list)->elem = (char *) p; /* reset tail */ + } +} + +/* MR10 list_free() frees the ListNode elements in the list */ +/* MR10 if freeData then free the data elements of the list too */ + +void +#ifdef __USE_PROTOS +list_free(ListNode **list,int freeData) +#else +list_free(list,freeData) + ListNode **list; + int freeData; +#endif +{ + ListNode *p; + ListNode *next; + + if (list == NULL) return; + if (*list == NULL) return; + for (p=*list; p != NULL; p=next) { + next=p->next; + if (freeData && p->elem != NULL) { + free( (char *) p->elem); + }; + free( (char *) p); + }; + *list=NULL; +} + +void +#ifdef __USE_PROTOS +list_apply( ListNode *list, void (*f)(void *) ) +#else +list_apply( list, f ) +ListNode *list; +void (*f)(); +#endif +{ + ListNode *p; + require(f!=NULL, "list_apply: NULL function to apply"); + + if ( list == NULL ) return; + for (p = list->next; p!=NULL; p=p->next) (*f)( p->elem ); +} + +/* MR27 */ + +#ifdef __USE_PROTOS +int list_search_cstring(ListNode *list, char * cstring) +#else +int list_search_cstring(list, cstring) + ListNode * list; + char * cstring; +#endif +{ + ListNode *p; + if (list == NULL ) return 0; + for (p = list->next; p!=NULL; p=p->next) { + if (p->elem == NULL) continue; + if (0 == strcmp((char *) p->elem , cstring)) return 1; + } + return 0; +} + + /* F O L L O W C y c l e S t u f f */ + +/* make a key based upon (rulename, computation, k value). + * Computation values are 'i'==FIRST, 'o'==FOLLOW. + */ + +/* MR10 Make the key all characters so it can be read easily */ +/* MR10 by a simple dump program. Also, separates */ +/* MR10 'o' and 'i' from rule name */ + +char * +#ifdef __USE_PROTOS +Fkey( char *rule, int computation, int k ) +#else +Fkey( rule, computation, k ) +char *rule; +int computation; +int k; +#endif +{ + static char key[MaxRuleName+2+2+1]; /* MR10 */ + int i; + + if ( k > 99 ) /* MR10 */ + fatal("k>99 is too big for this implementation of ANTLR!\n"); /* MR10 */ + if ( (i=strlen(rule)) > MaxRuleName ) /* MR10 */ + fatal( eMsgd("rule name > max of %d\n", MaxRuleName) ); /* MR10 */ + strcpy(key,rule); + +/* MR10 */ key[i]='*'; +/* MR10 */ key[i+1] = (char) computation; /* MR20 G. Hobbelt */ +/* MR10 */ if (k < 10) { +/* MR10 */ key[i+2] = (char) ( '0' + k); +/* MR10 */ key[i+3] = '\0'; +/* MR10 */ } else { +/* MR10 */ key[i+2] = (char) ( '0' + k/10); +/* MR10 */ key[i+3] = (char) ( '0' + k % 10); +/* MR10 */ key[i+4] = '\0'; +/* MR10 */ }; + + return key; +} + +/* Push a rule onto the kth FOLLOW stack */ +void +#ifdef __USE_PROTOS +FoPush( char *rule, int k ) +#else +FoPush( rule, k ) +char *rule; +int k; +#endif +{ + RuleEntry *r; + require(rule!=NULL, "FoPush: tried to push NULL rule"); + require(k<=CLL_k, "FoPush: tried to access non-existent stack"); + + /*fprintf(stderr, "FoPush(%s)\n", rule);*/ + r = (RuleEntry *) hash_get(Rname, rule); + if ( r == NULL ) {fatal_internal( eMsg1("rule %s must be defined but isn't", rule) );} + if ( FoStack[k] == NULL ) /* Does the kth stack exist yet? */ + { + /*fprintf(stderr, "allocating FoStack\n");*/ + FoStack[k] = (int *) calloc(FoStackSize, sizeof(int)); + require(FoStack[k]!=NULL, "FoPush: cannot allocate FOLLOW stack\n"); + } + if ( FoTOS[k] == NULL ) + { + FoTOS[k]=FoStack[k]; + *(FoTOS[k]) = r->rulenum; + } + else + { +#ifdef MEMCHK + require(valid(FoStack[k]), "FoPush: invalid FoStack"); +#endif + if ( FoTOS[k] >= &(FoStack[k][FoStackSize-1]) ) + fatal( eMsgd("exceeded max depth of FOLLOW recursion (%d)\n", + FoStackSize) ); + require(FoTOS[k]>=FoStack[k], + eMsg1("FoPush: FoStack stack-ptr is playing out of its sandbox", + rule)); + ++(FoTOS[k]); + *(FoTOS[k]) = r->rulenum; + } + { + /* +**** int *p; +**** fprintf(stderr, "FoStack[k=%d]:\n", k); +**** for (p=FoStack[k]; p<=FoTOS[k]; p++) +**** { +**** fprintf(stderr, "\t%s\n", RulePtr[*p]->rname); +**** } + */ + } +} + +/* Pop one rule off of the FOLLOW stack. TOS ptr is NULL if empty. */ +void +#ifdef __USE_PROTOS +FoPop( int k ) +#else +FoPop( k ) +int k; +#endif +{ + require(k<=CLL_k, "FoPop: tried to access non-existent stack"); + /*fprintf(stderr, "FoPop\n");*/ + require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]), + "FoPop: FoStack stack-ptr is playing out of its sandbox"); + if ( FoTOS[k] == FoStack[k] ) FoTOS[k] = NULL; + else (FoTOS[k])--; +} + +/* Compute FOLLOW cycle. + * Mark all FOLLOW sets for rules in cycle as incomplete. + * Then, save cycle on the cycle list (Cycles) for later resolution. + * The Cycle is stored in the form: + * (head of cycle==croot, rest of rules in cycle==cyclicDep) + * + * e.g. (Fo means "FOLLOW of", "-->" means requires or depends on) + * + * Fo(x)-->Fo(a)-->Fo(b)-->Fo(c)-->Fo(x) + * ^----Infinite recursion (cycle) + * + * the cycle would be: x -> {a,b,c} or stored as (x,{a,b,c}). Fo(x) depends + * on the FOLLOW of a,b, and c. The root of a cycle is always complete after + * Fo(x) finishes. Fo(a,b,c) however are not. It turns out that all rules + * in a FOLLOW cycle have the same FOLLOW set. + */ +void +#ifdef __USE_PROTOS +RegisterCycle( char *rule, int k ) +#else +RegisterCycle( rule, k ) +char *rule; +int k; +#endif +{ + CacheEntry *f; + Cycle *c; + int *p; + RuleEntry *r; + require(rule!=NULL, "RegisterCycle: tried to register NULL rule"); + require(k<=CLL_k, "RegisterCycle: tried to access non-existent stack"); + + /*fprintf(stderr, "RegisterCycle(%s)\n", rule);*/ + /* Find cycle start */ + r = (RuleEntry *) hash_get(Rname, rule); + require(r!=NULL,eMsg1("rule %s must be defined but isn't", rule)); + require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]), + eMsg1("RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox", + rule)); +/*** if ( FoTOS[k]&(FoStack[k][FoStackSize-1]) ) +**** { +**** fprintf(stderr, "RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox\n", +**** rule); +**** fprintf(stderr, "RegisterCycle: sp==0x%x out of bounds 0x%x...0x%x\n", +**** FoTOS[k], FoStack[k], &(FoStack[k][FoStackSize-1])); +**** exit(PCCTS_EXIT_FAILURE); +**** } +****/ + +#ifdef MEMCHK + require(valid(FoStack[k]), "RegisterCycle: invalid FoStack"); +#endif + for (p=FoTOS[k]; *p != r->rulenum && p >= FoStack[k]; --p) {;} + require(p>=FoStack[k], "RegisterCycle: FoStack is screwed up beyond belief"); + if ( p == FoTOS[k] ) return; /* don't worry about cycles to oneself */ + + /* compute cyclic dependents (rules in cycle except head) */ + c = newCycle; + require(c!=NULL, "RegisterCycle: couldn't alloc new cycle"); + c->cyclicDep = empty; + c->croot = *p++; /* record root of cycle */ + for (; p<=FoTOS[k]; p++) + { + /* Mark all dependent rules as incomplete */ + f = (CacheEntry *) hash_get(Fcache, Fkey(RulePtr[*p]->rname,'o',k)); + if ( f==NULL ) + { + f = newCacheEntry( Fkey(RulePtr[*p]->rname,'o',k) ); + hash_add(Fcache, Fkey(RulePtr[*p]->rname,'o',k), (Entry *)f); + } + f->incomplete = TRUE; + + set_orel(*p, &(c->cyclicDep)); /* mark rule as dependent of croot */ + } + list_add(&(Cycles[k]), (void *)c); +} + +/* make all rules in cycle complete + * + * while ( some set has changed ) do + * for each cycle do + * if degree of FOLLOW set for croot > old degree then + * update all FOLLOW sets for rules in cyclic dependency + * change = TRUE + * endif + * endfor + * endwhile + */ +void +#ifdef __USE_PROTOS +ResolveFoCycles( int k ) +#else +ResolveFoCycles( k ) +int k; +#endif +{ + ListNode *p, *q; + Cycle *c; + int changed = 1; + CacheEntry *f,*g; + int r; +/* int i; */ /* MR10 not useful */ + unsigned d; + + unsigned *cursor; /* MR10 */ + unsigned *origin; /* MR10 */ + + /*fprintf(stderr, "Resolving following cycles for %d\n", k);*/ + while ( changed ) + { + changed = 0; +/* MR10 i = 0; */ + for (p = Cycles[k]->next; p!=NULL; p=p->next) + { + c = (Cycle *) p->elem; + /*fprintf(stderr, "cycle %d: %s -->", i++, RulePtr[c->croot]->rname);*/ + /*s_fprT(stderr, c->cyclicDep);*/ + /*fprintf(stderr, "\n");*/ + f = (CacheEntry *) + hash_get(Fcache, Fkey(RulePtr[c->croot]->rname,'o',k)); + require(f!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[c->croot]->rname) ); + if ( (d=set_deg(f->fset)) > c->deg ) + { + /*fprintf(stderr, "Fo(%s) has changed\n", RulePtr[c->croot]->rname);*/ + changed = 1; + c->deg = d; /* update cycle FOLLOW set degree */ + +/* MR10 */ origin=set_pdq(c->cyclicDep); +/* MR10 */ for (cursor=origin; *cursor != nil; cursor++) { +/* MR10 */ r=*cursor; + +/******** while ( !set_nil(c->cyclicDep) ) { *****/ +/******** r = set_int(c->cyclicDep); *****/ +/******** set_rm(r, c->cyclicDep); *****/ + + /*fprintf(stderr, "updating Fo(%s)\n", RulePtr[r]->rname);*/ + g = (CacheEntry *) + hash_get(Fcache, Fkey(RulePtr[r]->rname,'o',k)); + require(g!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[r]->rname) ); + set_orin(&(g->fset), f->fset); + g->incomplete = FALSE; + } +/* MR10 */ free( (char *) origin); +/* MR10 */ origin=NULL; + } + } +/* MR10 - this if statement appears to be meaningless since i is always 0 */ +/* MR10 if ( i == 1 ) changed = 0; */ /* if only 1 cycle, no need to repeat */ + } + /* kill Cycle list */ + for (q = Cycles[k]->next; q != NULL; q=p) + { + p = q->next; + set_free( ((Cycle *)q->elem)->cyclicDep ); + free((char *)q); + } + free( (char *)Cycles[k] ); + Cycles[k] = NULL; +} + + + /* P r i n t i n g S y n t a x D i a g r a m s */ + +static void +#ifdef __USE_PROTOS +pBlk( Junction *q, int btype ) +#else +pBlk( q, btype ) +Junction *q; +int btype; +#endif +{ + int k,a; + Junction *alt, *p; + + q->end->pvisited = TRUE; + if ( btype == aLoopBegin ) + { + require(q->p2!=NULL, "pBlk: invalid ()* block"); + PRINT(q->p1); + alt = (Junction *)q->p2; + PRINT(alt->p1); + if ( PrintAnnotate ) + { + printf(" /* Opt "); + k = 1; + while ( !set_nil(alt->fset[k]) ) + { + s_fprT(stdout, alt->fset[k]); + if ( k++ == CLL_k ) break; + if ( !set_nil(alt->fset[k]) ) printf(", "); + } + printf(" */\n"); + } + return; + } + for (a=1,alt=q; alt != NULL; alt= (Junction *) alt->p2, a++) + { + if ( alt->p1 != NULL ) PRINT(alt->p1); + if ( PrintAnnotate ) + { + printf( " /* [%d] ", alt->altnum); + k = 1; + while ( !set_nil(alt->fset[k]) ) + { + s_fprT(stdout, alt->fset[k]); + if ( k++ == CLL_k ) break; + if ( !set_nil(alt->fset[k]) ) printf(", "); + } + if ( alt->p2 == NULL && btype == aOptBlk ) + printf( " (optional branch) */\n"); + else printf( " */\n"); + } + + /* ignore implied empty alt of Plus blocks */ + if ( alt->p2 != NULL && ((Junction *)alt->p2)->ignore ) break; + + if ( alt->p2 != NULL && !(((Junction *)alt->p2)->p2==NULL && btype == aOptBlk) ) + { + if ( pLevel == 1 ) + { + printf("\n"); + if ( a+1==pAlt1 || a+1==pAlt2 ) printf("=>"); + printf("\t"); + } + else printf(" "); + printf("|"); + if ( pLevel == 1 ) + { + p = (Junction *) ((Junction *)alt->p2)->p1; + while ( p!=NULL ) + { + if ( p->ntype==nAction ) + { + p=(Junction *)((ActionNode *)p)->next; + continue; + } + if ( p->ntype!=nJunction ) + { + break; + } + if ( p->jtype==EndBlk || p->jtype==EndRule ) + { + p = NULL; + break; + } + p = (Junction *)p->p1; + } + if ( p==NULL ) printf("\n\t"); /* Empty alt? */ + } + } + } + q->end->pvisited = FALSE; +} + +/* How to print out a junction */ +void +#ifdef __USE_PROTOS +pJunc( Junction *q ) +#else +pJunc( q ) +Junction *q; +#endif +{ + int dum_k; + int doing_rule; + require(q!=NULL, "pJunc: NULL node"); + require(q->ntype==nJunction, "pJunc: not junction"); + + if ( q->pvisited == TRUE ) return; + q->pvisited = TRUE; + switch ( q->jtype ) + { + case aSubBlk : + if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); + if ( q->end->p1 != NULL && ((Junction *)q->end->p1)->ntype==nJunction && + ((Junction *)q->end->p1)->jtype == EndRule ) doing_rule = 1; + else doing_rule = 0; + pLevel++; + if ( pLevel==1 ) + { + if ( pAlt1==1 ) printf("=>"); + printf("\t"); + } + else printf(" "); + if ( doing_rule ) + { + if ( pLevel==1 ) printf(" "); + pBlk(q,q->jtype); + } + else { + printf("("); + if ( pLevel==1 ) printf(" "); + pBlk(q,q->jtype); + if ( pLevel>1 ) printf(" "); + printf(")"); + } + if ( q->guess ) printf("?"); + pLevel--; + if ( PrintAnnotate ) freeBlkFsets(q); + if ( q->end->p1 != NULL ) PRINT(q->end->p1); + break; + case aOptBlk : + if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); + pLevel++; + if ( pLevel==1 ) + { + if ( pAlt1==1 ) printf("=>"); + printf("\t"); + } + else printf(" "); + printf("{"); + if ( pLevel==1 ) printf(" "); + pBlk(q,q->jtype); + if ( pLevel>1 ) printf(" "); + else printf("\n\t"); + printf("}"); + pLevel--; + if ( PrintAnnotate ) freeBlkFsets(q); + if ( q->end->p1 != NULL ) PRINT(q->end->p1); + break; + case aLoopBegin : + if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); + pLevel++; + if ( pLevel==1 ) + { + if ( pAlt1==1 ) printf("=>"); + printf("\t"); + } + else printf(" "); + printf("("); + if ( pLevel==1 ) printf(" "); + pBlk(q,q->jtype); + if ( pLevel>1 ) printf(" "); + else printf("\n\t"); + printf(")*"); + pLevel--; + if ( PrintAnnotate ) freeBlkFsets(q); + if ( q->end->p1 != NULL ) PRINT(q->end->p1); + break; + case aLoopBlk : + if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); + pBlk(q,q->jtype); + if ( PrintAnnotate ) freeBlkFsets(q); + break; + case aPlusBlk : + if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); + pLevel++; + if ( pLevel==1 ) + { + if ( pAlt1==1 ) printf("=>"); + printf("\t"); + } + else printf(" "); + printf("("); + if ( pLevel==1 ) printf(" "); + pBlk(q,q->jtype); + if ( pLevel>1 ) printf(" "); + printf(")+"); + pLevel--; + if ( PrintAnnotate ) freeBlkFsets(q); + if ( q->end->p1 != NULL ) PRINT(q->end->p1); + break; + case EndBlk : + break; + case RuleBlk : + printf( "\n%s :\n", q->rname); + PRINT(q->p1); + if ( q->p2 != NULL ) PRINT(q->p2); + break; + case Generic : + if ( q->p1 != NULL ) PRINT(q->p1); + q->pvisited = FALSE; + if ( q->p2 != NULL ) PRINT(q->p2); + break; + case EndRule : + printf( "\n\t;\n"); + break; + } + q->pvisited = FALSE; +} + +/* How to print out a rule reference node */ +void +#ifdef __USE_PROTOS +pRuleRef( RuleRefNode *p ) +#else +pRuleRef( p ) +RuleRefNode *p; +#endif +{ + require(p!=NULL, "pRuleRef: NULL node"); + require(p->ntype==nRuleRef, "pRuleRef: not rule ref node"); + + printf( " %s", p->text); + PRINT(p->next); +} + +/* How to print out a terminal node */ +void +#ifdef __USE_PROTOS +pToken( TokNode *p ) +#else +pToken( p ) +TokNode *p; +#endif +{ + require(p!=NULL, "pToken: NULL node"); + require(p->ntype==nToken, "pToken: not token node"); + + if ( p->wild_card ) printf(" ."); + printf( " %s", TerminalString(p->token)); + PRINT(p->next); +} + +/* How to print out a terminal node */ +void +#ifdef __USE_PROTOS +pAction( ActionNode *p ) +#else +pAction( p ) +ActionNode *p; +#endif +{ + require(p!=NULL, "pAction: NULL node"); + require(p->ntype==nAction, "pAction: not action node"); + + PRINT(p->next); +} + + /* F i l l F o l l o w L i s t s */ + +/* + * Search all rules for all rule reference nodes, q to rule, r. + * Add q->next to follow list dangling off of rule r. + * i.e. + * + * r: -o-R-o-->o--> Ptr to node following rule r in another rule + * | + * o--> Ptr to node following another reference to r. + * + * This is the data structure employed to avoid FOLLOW set computation. We + * simply compute the FIRST (reach) of the EndRule Node which follows the + * list found at the end of all rules which are referenced elsewhere. Rules + * not invoked by other rules have no follow list (r->end->p1==NULL). + * Generally, only start symbols are not invoked by another rule. + * + * Note that this mechanism also gives a free cross-reference mechanism. + * + * The entire syntax diagram is layed out like this: + * + * SynDiag + * | + * v + * o-->R1--o + * | + * o-->R2--o + * | + * ... + * | + * o-->Rn--o + * + */ +void +#ifdef __USE_PROTOS +FoLink( Node *p ) +#else +FoLink( p ) +Node *p; +#endif +{ + RuleEntry *q; + Junction *j = (Junction *) p; + RuleRefNode *r = (RuleRefNode *) p; + + if ( p==NULL ) return; + require(p->ntype>=1 && p->ntype<=NumNodeTypes, + eMsgd("FoLink: invalid diagram node: ntype==%d",p->ntype)); + switch ( p->ntype ) + { + case nJunction : + if ( j->fvisited ) return; + if ( j->jtype == EndRule ) return; + j->fvisited = TRUE; + FoLink( j->p1 ); + FoLink( j->p2 ); +/* MR14 */ +/* MR14 */ /* Need to determine whether the guess block is an */ +/* MR14 */ /* of the form (alpha)? beta before follow sets are */ +/* MR14 */ /* computed. This is necessary to solve problem */ +/* MR14 */ /* of doing follow on the alpha of an (alpha)? beta block. */ +/* MR14 */ +/* MR14 */ /* This is performed by analysis_point as a side-effect. */ +/* MR14 */ +/* MR14 */ +/* MR14 */ if (j->jtype == aSubBlk && j->guess) { +/* MR14 */ Junction *ignore; +/* MR14 */ ignore=analysis_point(j); +/* MR14 */ } +/* MR14 */ + return; + case nRuleRef : + if ( r->linked ) return; + q = (RuleEntry *) hash_get(Rname, r->text); + if ( q == NULL ) + { + warnFL( eMsg1("rule %s not defined",r->text), FileStr[r->file], r->line ); + } + else + { + if ( r->parms!=NULL && RulePtr[q->rulenum]->pdecl==NULL ) + { + warnFL( eMsg1("rule %s accepts no parameter(s)", r->text), + FileStr[r->file], r->line ); + } + if ( r->parms==NULL && RulePtr[q->rulenum]->pdecl!=NULL ) + { + warnFL( eMsg1("rule %s requires parameter(s)", r->text), + FileStr[r->file], r->line ); + } + if ( r->assign!=NULL && RulePtr[q->rulenum]->ret==NULL ) + { + warnFL( eMsg1("rule %s yields no return value(s)", r->text), + FileStr[r->file], r->line ); + } + if ( r->assign==NULL && RulePtr[q->rulenum]->ret!=NULL ) + { + warnFL( eMsg1("rule %s returns a value(s)", r->text), + FileStr[r->file], r->line ); + } + if ( !r->linked ) + { + addFoLink( r->next, r->rname, RulePtr[q->rulenum] ); + r->linked = TRUE; + } + } + FoLink( r->next ); + return; + case nToken : + FoLink( ((TokNode *)p)->next ); + return; + case nAction : + FoLink( ((ActionNode *)p)->next ); + return; + default : + fatal_internal("invalid node type"); + } +} + +/* + * Add a reference to the end of a rule. + * + * 'r' points to the RuleBlk node in a rule. r->end points to the last node + * (EndRule jtype) in a rule. + * + * Initial: + * r->end --> o + * + * After: + * r->end --> o-->o--> Ptr to node following rule r in another rule + * | + * o--> Ptr to node following another reference to r. + * + * Note that the links are added to the head of the list so that r->end->p1 + * always points to the most recently added follow-link. At the end, it should + * point to the last reference found in the grammar (starting from the 1st rule). + */ +void +#ifdef __USE_PROTOS +addFoLink( Node *p, char *rname, Junction *r ) +#else +addFoLink( p, rname, r ) +Node *p; +char *rname; +Junction *r; +#endif +{ + Junction *j; + require(r!=NULL, "addFoLink: incorrect rule graph"); + require(r->end!=NULL, "addFoLink: incorrect rule graph"); + require(r->end->jtype==EndRule, "addFoLink: incorrect rule graph"); + require(p!=NULL, "addFoLink: NULL FOLLOW link"); + + j = newJunction(); + j->rname = rname; /* rname on follow links point to target rule */ + j->p1 = p; /* link to other rule */ + j->p2 = (Node *) r->end->p1;/* point to head of list */ + r->end->p1 = (Node *) j; /* reset head to point to new node */ +} + +void +#ifdef __USE_PROTOS +GenCrossRef( Junction *p ) +#else +GenCrossRef( p ) +Junction *p; +#endif +{ + set a; + Junction *j; + RuleEntry *q; + unsigned e; + require(p!=NULL, "GenCrossRef: why are you passing me a null grammar?"); + + printf("Cross Reference:\n\n"); + a = empty; + for (; p!=NULL; p = (Junction *)p->p2) + { + printf("Rule %20s referenced by {", p->rname); + /* make a set of rules for uniqueness */ + for (j = (Junction *)(p->end)->p1; j!=NULL; j = (Junction *)j->p2) + { + q = (RuleEntry *) hash_get(Rname, j->rname); + require(q!=NULL, "GenCrossRef: FoLinks are screwed up"); + set_orel(q->rulenum, &a); + } + for (; !set_nil(a); set_rm(e, a)) + { + e = set_int(a); + printf(" %s", RulePtr[e]->rname); + } + printf(" }\n"); + } + set_free( a ); +} + +/* + The single argument is a pointer to the start of an element of a + C++ style function prototypet list. Given a pointer to the start of + an formal we must locate the comma (or the end of the string) + and locate the datatype, formal name, and initial value expression. + + The function returns a pointer to the character following the comma + which terminates the formal declaration, or a pointer to the end of + the string if none was found. + + I thought we were parsing specialists, how come I'm doing this by + hand written code ? + + Examples of input: + + Foo f, + Foo f = Foo(1), + Foo f = Foo(1,2), + Foo f = &farray[1,2], + Foo f = ",", + Foo f = ',', + TFoo f = TFoo(1,2), + + A non-zero value for nesting indicates a problem matching '(' and ')', + '[' and ']', '<' and '>', '{' and '}', or improperly terminated string + or character literal. + +*/ + + +/* + * Don't care if it is a valid string literal or not, just find the end + * Start with pointer to leading "\"" + */ + +#ifdef __USE_PROTOS +char * skipStringLiteral(char *pCurrent) +#else +char * skipStringLiteral(pCurrent) +char *pCurrent; +#endif +{ + char *p = pCurrent; + if (*p == 0) return p; + require (*p == '\"', "skipStringLiteral") + p++; + for (p = p; *p != 0; p++) { + if (*p == '\\') { + p++; + if (*p == 0) break; + p++; + } + if (*p == '\"') { + p++; + break; + } + } + return p; +} + +/* + * Don't care if it is a valid character literal or not, just find the end + * Start with pointer to leading "'" + */ + +#ifdef __USE_PROTOS +char * skipCharLiteral(char *pStart) +#else +char * skipCharLiteral(pStart) + char *pStart; +#endif +{ + char *p = pStart; + if (*p == 0) return p; + require (*p == '\'', "skipCharLiteral") + p++; + for (p = p; *p != 0; p++) { + if (*p == '\\') { + p++; + if (*p == 0) break; + p++; + } + if (*p == '\'') { + p++; + break; + } + } + return p; +} + +#ifdef __USE_PROTOS +char * skipSpaces(char *pStart) +#else +char * skipSpaces(pStart) +char * pStart; +#endif +{ + char *p = pStart; + while (*p != 0 && isspace(*p)) p++; + return p; +} + +#ifdef __USE_PROTOS +char * skipToSeparatorOrEqualSign(char *pStart, int *pNest) +#else +char * skipToSeparatorOrEqualSign(pStart, pNest) +char *pStart; +int *pNest; +#endif +{ + char *p = pStart; + + int nest = 0; + + *pNest = (-1); + + while (*p != 0) { + switch (*p) { + + case '(' : + case '[' : + case '<' : + case '{' : + nest++; + p++; + break; + + case ')' : + case ']' : + case '>' : + case '}' : + nest--; + p++; + break; + + case '"' : + p = skipStringLiteral(p); + break; + + case '\'' : + p = skipCharLiteral(p); + break; + + case '\\': + p++; + if (*p == 0) goto EXIT; + p++; + break; + + case ',': + case '=': + if (nest == 0) goto EXIT; + p++; + break; + + default: + p++; + } + } +EXIT: + *pNest = nest; + return p; +} + +#ifdef __USE_PROTOS +char * skipToSeparator(char *pStart, int *pNest) +#else +char * skipToSeparator(pStart, pNest) +char *pStart; +int *pNest; +#endif +{ + char * p = pStart; + for ( ; ; ) { + p = skipToSeparatorOrEqualSign(p, pNest); + if (*pNest != 0) return p; + if (*p == ',') return p; + if (*p == 0) return p; + p++; + } +} + +/* skip to just past the "=" separating the declaration from the initialization value */ + +#ifdef __USE_PROTOS +char * getInitializer(char *pStart) +#else +char * getInitializer(pStart) +char * pStart; +#endif +{ + char *p; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + + require(pStart!=NULL, "getInitializer: invalid string"); + + p = endFormal(pStart, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + if (nest != 0) return NULL; + if (pEqualSign == NULL) return NULL; + if (pValue == NULL) return NULL; + return strBetween(pValue, NULL, pSeparator); +} + +/* + Examines the string from pStart to pEnd-1. + If the string has 0 length or is entirely white space + returns 1. Otherwise 0. +*/ + +#ifdef __USE_PROTOS +int isWhiteString(const char *pStart, const char *pEnd) +#else +int isWhiteString(pStart, pEnd) +const char *pStart; +const char *pEnd; +#endif +{ + const char *p; + for (p = pStart; p < pEnd; p++) { + if (! isspace(*p)) return 0; + } + return 1; +} + +/* + This replaces HasComma() which couldn't distinguish + + foo ["a,b"] + + from: + + foo[a,b] + +*/ + +#ifdef __USE_PROTOS +int hasMultipleOperands(char *pStart) +#else +int hasMultipleOperands(pStart) +char *pStart; +#endif +{ + char *p = pStart; + int nest = 0; + + p = skipSpaces(p); + if (*p == 0) return 0; + p = skipToSeparator(p, &nest); + if (nest == 0 && *p == ',') return 1; + return 0; +} + + +#define MAX_STR_BETWEEN_WORK_AREA 1000 + +static char strBetweenWorkArea[MAX_STR_BETWEEN_WORK_AREA]; + + +/* + strBetween(pStart, pNext, pStop) + + Creates a null terminated string by copying the text between two pointers + to a work area. The start of the string is pStart. The end of the string + is the character before pNext, or if pNext is null then the character before + pStop. Trailing spaces are not included in the copy operation. + + This is used when a string contains several parts. The pNext part may be + optional. The pStop will stop the scan when the optional part is not present + (is a null pointer). +*/ + +#ifdef __USE_PROTOS +char *strBetween(char *pStart, char *pNext, char *pStop) +#else +char *strBetween(pStart, pNext, pStop) +char *pStart; +char *pNext; +char *pStop; +#endif +{ + char *p; + char *q = strBetweenWorkArea; + const char *pEnd; + + pEnd = (pNext != NULL) ? pNext : pStop; + + require (pEnd != NULL, "pEnd == NULL"); + require (pEnd >= pStart, "pEnd < pStart"); + for (pEnd--; pEnd >= pStart; pEnd--) { /* MR31 */ + if (! isspace(*pEnd)) break; + } + for (p = pStart; + p <= pEnd && q < &strBetweenWorkArea[MAX_STR_BETWEEN_WORK_AREA-2]; + p++, q++) { + *q = *p; + } + *q = 0; + return strBetweenWorkArea; +} + +/* + function Returns pointer to character following separator at + value which to continue search for next formal. If at the + end of the string a pointer to the null byte at the + end of the string is returned. + + pStart Pointer to the starting position of the formal list + + This may be the middle of a longer string, for example + when looking for the end of formal #3 starting from + the middle of the complete formal list. + + ppDataType Returns a pointer to the start of the data type in the + formal. Example: pointer to "Foo". + + ppSymbol Returns a pointer to the start of the formal symbol. + Example: pointer to "f". + + ppEqualSign Returns a pointer to the equal sign separating the + formal symbol from the initial value. If there is + no "=" then this will be NULL. + + ppValue Returns a pointer to the initial value part of the + formal declaration. Example: pointer to "&farray[1,2]" + + ppSeparator Returns a pointer to the character which terminated the + scan. This should be a pointer to a comma or a null + byte which terminates the string. + + pNest Returns the nesting level when a separator was found. + This is non-zero for any kind of error. This is zero + for a successful parse of this portion of the formal + list. + +*/ + +#ifdef __USE_PROTOS +char * endFormal(char *pStart, + char **ppDataType, + char **ppSymbol, + char **ppEqualSign, + char **ppValue, + char **ppSeparator, + int *pNest) +#else +char * endFormal(pStart, + ppDataType, + ppSymbol, + ppEqualSign, + ppValue, + ppSeparator, + pNest) +char *pStart; +char **ppDataType; +char **ppSymbol; +char **ppEqualSign; +char **ppValue; +char **ppSeparator; +int *pNest; + +#endif +{ + char *p = pStart; + char *q; + + *ppDataType = NULL; + *ppSymbol = NULL; + *ppEqualSign = NULL; + *ppValue = NULL; + *ppSeparator = NULL; + + *pNest = 0; + + /* The first non-blank is the start of the datatype */ + + p = skipSpaces(p); + if (*p == 0) goto EXIT; + *ppDataType = p; + + /* We are not looking for the symbol, we are looking + for the separator that follows the symbol. Then + we'll back up. + + Search for the ',' or '=" or null terminator. + */ + + p = skipToSeparatorOrEqualSign(p, pNest); + + if (*pNest != 0) goto EXIT; + + /* + Work backwards to find start of symbol + Skip spaces between the end of symbol and separator + Assume that there are no spaces in the formal, but + there is a space preceding the formal + */ + + for (q = &p[-1]; q >= *ppDataType; q--) { + if (! isspace(*q)) break; + } + if (q < *ppDataType) goto EXIT; + + /* + MR26 Handle things like: IIR_Bool (IIR_Decl::*constraint)() + Backup until we hit the end of a symbol string, then find the + start of the symbol string. This wont' work for functions + with prototypes, but works for the most common cases. For + others, use typedef names. + */ + +/* MR26 */ for (q = q; q >= *ppDataType; q--) { +/* MR26 */ if (isalpha(*q) || isdigit(*q) || *q == '_' || *q == '$') break; +/* MR26 */ } +/* MR26 */ if (q < *ppDataType) goto EXIT; + + for (q = q; q >= *ppDataType; q--) { + if ( ! (isalpha(*q) || isdigit(*q) || *q == '_' || *q == '$')) break; + } + + *ppSymbol = &q[1]; + + if (*p == ',' || *p == 0) { + *ppSeparator = p; + goto EXIT; + } + + *ppEqualSign = p; + p = skipSpaces(++p); + *ppValue = p; + if (*p == 0) goto EXIT; + + + while (*p != 0 && *pNest == 0 && *p != ',') { + p = skipToSeparator(p, pNest); + } + if (*pNest == 0) *ppSeparator = p; + +EXIT: + if (*p == ',') p++; + return p; +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/mode.h b/Tools/Source/TianoTools/Pccts/antlr/mode.h new file mode 100644 index 0000000000..c08bf31ac7 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/mode.h @@ -0,0 +1,12 @@ +#define START 0 +#define STRINGS 1 +#define ACTION_STRINGS 2 +#define ACTION_CHARS 3 +#define ACTION_COMMENTS 4 +#define TOK_DEF_COMMENTS 5 +#define TOK_DEF_CPP_COMMENTS 6 +#define ACTION_CPP_COMMENTS 7 +#define CPP_COMMENTS 8 +#define COMMENTS 9 +#define ACTIONS 10 +#define PARSE_ENUM_FILE 11 diff --git a/Tools/Source/TianoTools/Pccts/antlr/mrhoist.c b/Tools/Source/TianoTools/Pccts/antlr/mrhoist.c new file mode 100644 index 0000000000..110bf5996f --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/mrhoist.c @@ -0,0 +1,3030 @@ +/* + * mrhoist.c + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33MR10 + * + */ + +#include + +#include "pcctscfg.h" + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include + +#ifdef __USE_PROTOS +void dumppred(Predicate *); +#else +void dumppred(); +#endif + +/* + Try to determine whether predicate "first" is true for + all cases where "second" is true. Comparison takes place + without regard to context. + Assumes that predicate symbols have been expanded. + Assumes that there are no NAND or NOR nodes + +*/ + +#ifdef __USE_PROTOS +int MR_secondPredicateUnreachable(Predicate *first,Predicate *second) +#else +int MR_secondPredicateUnreachable(first,second) + Predicate *first; + Predicate *second; +#endif +{ + Predicate *f; + Predicate *s; + + if (first == NULL) { + return 1; + } else if (second == NULL) { + return 0; + } else if (first->down == NULL && second->down == NULL) { + if (first->source == second->source && + first->inverted == second->inverted) { + return 1; /* look identical - will never reach alt2 */ + } else { + return 0; /* look different */ + }; + } else if (first->down == NULL && second->down != NULL) { + + if (second->expr == PRED_AND_LIST) { + + /* unreachable if first covers any child of second */ + + for (s=second->down; s != NULL; s=s->right) { + if (MR_secondPredicateUnreachable(first,s)) { + return 1; + }; + }; + return 0; + } else if (second->expr == PRED_OR_LIST) { + + /* unreachable if first covers every child of second */ + + for (s=second->down; s != NULL; s=s->right) { + if (!MR_secondPredicateUnreachable(first,s)) { + return 0; + }; + }; + return 1; + } else { + require (0,"Illegal pred->expr"); + return 0; /* MR20 Make compiler happy */ + }; + } else if (first->down != NULL && second->down == NULL) { + if (first->expr == PRED_AND_LIST) { + + /* unreachable if every child of first covers second */ + + for (f=first->down; f != NULL; f=f->right) { + if (!MR_secondPredicateUnreachable(f,second)) { + return 0; + }; + }; + return 1; + } else if (first->expr == PRED_OR_LIST) { + + /* unreachable if any child of first covers second */ + + for (f=first->down; f != NULL; f=f->right) { + if (MR_secondPredicateUnreachable(f,second)) { + return 1; + }; + }; + return 0; + } else { + require (0,"Illegal predicate->expr"); + return 0; /* MR20 Make compiler happy */ + }; + } else { + + if (first->expr == PRED_AND_LIST && second->expr == PRED_AND_LIST) { + + /* unreachable if each child of first covers at least one child of second */ + + for (f=first->down; f != NULL ; f=f->right) { + for (s=second->down; s != NULL ; s=s->right) { + if (MR_secondPredicateUnreachable(f,s)) goto A_next_f; + }; + return 0; +A_next_f: + continue; + }; + return 1; + + } else if (first->expr == PRED_AND_LIST && second->expr == PRED_OR_LIST) { + + /* unreachable if each child of first covers ALL of second's children */ + + for (f=first->down; f != NULL ; f=f->right) { + for (s=second->down; s != NULL ; s=s->right) { + if (!MR_secondPredicateUnreachable(f,s)) return 0; + }; + }; + return 1; + + } else if (first->expr == PRED_OR_LIST && second->expr == PRED_AND_LIST) { + + /* unreachable if any child of second is covered by any child of first */ + + for (f=first->down; f != NULL ; f=f->right) { + for (s=second->down; s != NULL ; s=s->right) { + if (MR_secondPredicateUnreachable(f,s)) return 1; + }; + }; + return 0; + + } else if (first->expr == PRED_OR_LIST && second->expr == PRED_OR_LIST) { + + /* unreachable if every child of second is covered by some child of first */ + + for (f=first->down; f != NULL ; f=f->right) { + for (s=second->down; s != NULL ; s=s->right) { + if (MR_secondPredicateUnreachable(f,s)) goto B_next_f; + }; + return 0; +B_next_f: + continue; + }; + return 1; + + } else { + require (0,"Illegal predicate->expr"); + return 0; /* MR20 Make compiler happy */ + }; + }; + return 0; /* MR20 MSVC 5.0 complains about missing return statement */ +} + +#ifdef __USE_PROTOS +void MR_xxxIndent(FILE *f,int depth) +#else +void MR_xxxIndent(f,depth) + FILE *f; + int depth; +#endif +{ + int i; + + for (i=0; irname,rrn->line,FileStr[rrn->file],rrn->text); + }; + lastOne=MR_ruleReferenced(rrn); + if (lastOne != NULL) { + for (j=0; jrname,lastOne->line,FileStr[lastOne->file]); + }; +} + +#ifdef __USE_PROTOS +void MR_dumpTreeF(FILE *f,int depth,Tree *tree,int across) +#else +void MR_dumpTreeF(f,depth,tree,across) + FILE *f; + Tree *tree; + int depth; + int across; +#endif +{ + int newAcross=across; + + if (tree == NULL ) return; + if (tree->down != NULL ) { + fprintf(output,"\n"); + MR_outputIndent(depth); + fprintf(output, "(root ="); + }; + if (tree->token == ALT ) { + fprintf(output," %-16s","Alt"); + } else if (tree->token==EpToken ) { + fprintf(output,"(%d)%13s",tree->v.rk," "); + } else { + fprintf(output," %-16s",TerminalString(tree->token)); + }; + if (tree->down != NULL) { + fprintf(output,"\n"); + MR_outputIndent(depth+1); + MR_dumpTreeF(f,depth+1,tree->down,1); + newAcross=0; + fprintf(output,"\n"); + MR_outputIndent(depth); + fprintf(output,")"); + }; + if (newAcross > 3) { + fprintf(output,"\n"); + MR_outputIndent(depth); + newAcross=0; + }; + MR_dumpTreeF(f,depth,tree->right,newAcross+1); +} + +#ifdef __USE_PROTOS +void MR_dumpTreeX(int depth,Tree *tree,int across) +#else +void MR_dumpTreeX(depth,tree,across) + Tree *tree; + int depth; + int across; +#endif +{ + MR_dumpTreeF(output,depth,tree,across); +} + +#ifdef __USE_PROTOS +void MR_dumpTokenSet(FILE *f,int depth,set s) +#else +void MR_dumpTokenSet(f,depth,s) + FILE *f; + int depth; + set s; +#endif +{ + int i; + int j; + + unsigned *pdq; + + if (set_nil(s)) { + fprintf(f,"\n"); + MR_xxxIndent(f,depth+1); + fprintf(f,"nil\n"); + return; + }; + + pdq=set_pdq(s); + require(pdq != NULL,"set_pdq failed"); + i=0; + for (i=0 ; ; i=i+4) { + fprintf(f,"\n"); + MR_xxxIndent(f,depth+1); + for (j=0; j < 4 ; j++) { + if (pdq[i+j] == nil) break; + fprintf(f," %-16s",TerminalString(pdq[i+j])); + }; + if (pdq[i+j] == nil) break; + }; + fprintf(f,"\n"); + free( (char *) pdq); +} + +#ifdef __USE_PROTOS +void MR_dumpPred1(int depth,Predicate *p,int withContext) +#else +void MR_dumpPred1(depth,p,withContext) + int depth; + Predicate *p; + int withContext; +#endif +{ + unsigned k; + + if (p == NULL) { + MR_outputIndent(depth); + fprintf(output,"The predicate is empty (or always true)\n\n"); + return; + }; + if (p->down != NULL) { + MR_outputIndent(depth); + if (p->inverted) { + + /* MR14a Left out print expression in fprintf + Reported by Manuel Kessler (mlkessle@cip.physik.uni-wuerzburg.de) + */ + + if (p->expr == PRED_AND_LIST) fprintf(output,"%s NAND (not AND) expr\n\n",p->expr); + if (p->expr == PRED_OR_LIST) fprintf(output,"%s NOR (not OR) expr\n\n",p->expr); + } else { + fprintf(output,"%s expr\n\n",p->expr); + }; + } else { + MR_outputIndent(depth); + fprintf(output,"pred %s <<%s>>?\n", + (p->inverted ? " *not*" : ""), + (p->expr == NULL ? "null expr" : p->expr)); + MR_outputIndent(depth+1); + fprintf(output," "); + fprintf(output," depth=k=%d",p->k); + if (p->source != NULL && p->source->guardpred) { + fprintf(output," (\"=>\" guard)"); + } + if (p->source != NULL && p->source->ampersandPred != NULL) { + fprintf(output," (\"&&\" guard)"); + }; + k=set_int(p->completionSet); + if (k != nil) { + fprintf(output," Incomplete Set at k=%d !",k); + }; + k=set_int(p->completionTree); + if (k != nil) { + fprintf(output," Incomplete Tree at k=%d !",k); + }; + if (p->source != NULL) { + fprintf(output," rule %s line %d %s", + p->source->rname,p->source->line,FileStr[p->source->file]); + }; + fprintf(output,"\n"); + if (withContext && + (HoistPredicateContext || + ! set_nil(p->scontext[1]) || + p->tcontext != NULL)) { + if (p->k == 1) { + MR_outputIndent(depth+1); + fprintf(output,"set context: "); + MR_dumpTokenSet(output,depth+1,p->scontext[1]); + } + if (p->k != 1) { + MR_outputIndent(depth+1); + fprintf(output,"tree context:"); + if (p->tcontext == NULL) { + fprintf(output," null"); + } else { + MR_dumpTreeX(depth+2,p->tcontext,0); + }; + fprintf(output,"\n"); + }; + }; + fprintf(output,"\n"); + }; + if (p->down != NULL) { + MR_dumpPred1(depth+1,p->down,withContext); + }; + if (p->right != NULL) { + MR_dumpPred1(depth,p->right,withContext); + }; +} + +#ifdef __USE_PROTOS +void MR_dumpPred(Predicate *p,int withContext) +#else +void MR_dumpPred(p,withContext) + Predicate *p; + int withContext; +#endif +{ + MR_dumpPred1(0,p,withContext); +} + +#ifdef __USE_PROTOS +Tree * MR_make_tree_from_set(set s) +#else +Tree * MR_make_tree_from_set(s) + set s; +#endif +{ + Tree *t=NULL; + Tree *node; + Tree **tp=&t; + int i; + + unsigned *pdq=set_pdq(s); + + if (pdq != NULL) { + for (i=0 ; pdq[i] != nil ; i++) { + node=tnode( (int) pdq[i]); + *tp=node; + tp=&(node->right); + }; + *tp=NULL; + free ( (char *) pdq); + }; + return t; +} + +#ifdef __USE_PROTOS +void MR_check_pred_too_long(Predicate *p,set completion) +#else +void MR_check_pred_too_long(p,completion) + Predicate *p; + set completion; +#endif +{ + if (p != NULL && + p->source != NULL && + ! p->source->predTooLong) { + if ( !set_nil(completion)) { + p->source->predTooLong=1; +warnFL("It is unusual (but ok) for a semantic predicate to test context past the end of its own rule", + FileStr[p->source->file],p->source->line); + }; + }; +} + +#ifdef __USE_PROTOS +int MR_predicate_context_completed(Predicate *p) +#else +int MR_predicate_context_completed(p) + Predicate *p; +#endif +{ + if (p == NULL) return 1; + if (p->expr != PRED_AND_LIST && + p->expr != PRED_OR_LIST) { + if ( ! set_nil(p->completionSet)) return 0; + if ( ! set_nil(p->completionTree)) return 0; + }; + return MR_predicate_context_completed(p->down) & + MR_predicate_context_completed(p->right); +} + +#ifdef __USE_PROTOS +Node * MR_advance(Node *n) +#else +Node * MR_advance(n) + Node *n; +#endif +{ + if (n == NULL) return NULL; + switch (n->ntype) { + case nJunction: return ((Junction *)n)->p1; + case nToken: return ((TokNode *)n)->next; + case nRuleRef: return ((RuleRefNode *)n)->next; + case nAction: return ((ActionNode *)n)->next; + default: return NULL; + }; + return NULL; /* MSVC 5.0 complains about missing return statement */ +} + +#ifdef __USE_PROTOS +Junction * MR_find_endRule(Node *n) +#else +Junction * MR_find_endRule(n) + Node *n; +#endif +{ + Node *next; + if (n == NULL) return NULL; + for (next=n; next != NULL; next=MR_advance(next)) { + if (next->ntype == nJunction && + ( (Junction *) next)->jtype == EndRule) { + break; + }; + }; + return (Junction *)next; +} + +/* + Intersection: a branch which is shorter is chosen + over one which is longer: (A B C) intersect (A B) yields (A B). + + AND: a branch which is longer is chosen over the one + which is shorter: (A B C) AND (A B) yields (A B C) + +*/ + +#ifdef __USE_PROTOS +Tree *MR_computeTreeIntersection(Tree *l,Tree *r) +#else +Tree *MR_computeTreeIntersection(l,r) + Tree *l; + Tree *r; +#endif +{ + Tree *result=NULL; + Tree **tail; + Tree *p; + Tree *q; + Tree *match; + + if (l == NULL || r == NULL) return NULL; + for (p=l; p != NULL; p=p->right) { + require(p->token != EpToken,"MR_computeTreeIntersection: p->EpToken unexpected\n"); + require (p->token != ALT,"MR_computeTreeIntersection: p->ALT unexpected\n"); + }; + for (q=r; q != NULL; q=q->right) { + require(q->token != EpToken,"MR_computeTreeIntersection: q->EpToken unexpected\n"); + require(q->token != ALT,"MR_computeTreeIntersection: q->ALT unexpected\n"); + }; + + result=tnode(ALT); + tail=&(result->down); + + for (p=l; p != NULL ; p=p->right) { + for (q=r; q != NULL ; q=q->right) { + if (p->token == q->token) { + match=tnode(p->token); + match->down=MR_computeTreeIntersection(p->down,q->down); + *tail=match; + tail=&(match->right); + }; + }; + }; + + *tail=NULL; + result=tshrink(result); + result=tflatten( result ); + result=tleft_factor( result ); + return result; +} + +/* the predicates which are ANDed together have a common + context: they must all have common roots. Thus the + AND operation is more like an OR operation because + branches which are longer are grafted onto shorter + branches of the AND tree. For instance combining + (A B C) with (A B C D) gives (A B C D). There + should never be a case of (A B C) and (A B D) because + they have the same context. + + Actually, this may not be true once one throws in + guard predicates which are defined by the user, not + the context. +*/ + +/* requires input trees to be in "canonical" format */ + +#ifdef __USE_PROTOS +Tree *MR_computeTreeAND(Tree *l,Tree *r) +#else +Tree *MR_computeTreeAND(l,r) + Tree *l; + Tree *r; +#endif +{ + Tree *result=NULL; + Tree **tail; + Tree *p; + Tree *q; + Tree *match; + + if (l == NULL) return tdup(r); + if (r == NULL) return tdup(l); + + for (p=l; p != NULL; p=p->right) { +/**** require(p->token != EpToken,"MR_computeTreeAND: p->EpToken unexpected\n"); ****/ + require (p->token != ALT,"MR_computeTreeAND: p->ALT unexpected\n"); + }; + for (q=r; q != NULL; q=q->right) { +/**** require(q->token != EpToken,"MR_computeTreeAND: q->EpToken unexpected\n"); ****/ + require(q->token != ALT,"MR_computeTreeAND: q->ALT unexpected\n"); + }; + + result=tnode(ALT); + tail=&(result->down); + + for (p=l; p != NULL ; p=p->right) { + for (q=r; q != NULL ; q=q->right) { + if (p->token == q->token) { + match=tnode(p->token); + match->down=MR_computeTreeAND(p->down,q->down); + *tail=match; + tail=&(match->right); + }; + }; + }; + + *tail=NULL; + result=tshrink(result); + result=tflatten( result ); + result=tleft_factor( result ); + return result; +} + +#ifdef __USE_PROTOS +void MR_union_plain_sets1(Predicate *p,set *theUnion) +#else +void MR_union_plain_sets1(p,theUnion) + Predicate *p; + set *theUnion; +#endif +{ + if (p == NULL) return; + MR_union_plain_sets1(p->down,theUnion); + MR_union_plain_sets1(p->right,theUnion); + set_orin(theUnion,p->plainSet); + return; +} + +#ifdef __USE_PROTOS +set MR_union_plain_sets(Predicate *p) +#else +set MR_union_plain_sets(p) + Predicate *p; +#endif +{ + set theUnion; + + theUnion=empty; + + MR_union_plain_sets1(p,&theUnion); + return theUnion; +} + +/* does NOT left factor: do not want to merge + (A B) with (A) to get (A B) + in fact the opposite: (A B) with (A) gives (A) +*/ + +#ifdef __USE_PROTOS +Tree *MR_compute_pred_tree_ctxXX(Predicate *p) +#else +Tree *MR_compute_pred_tree_ctxXX(p) + Predicate *p; +#endif +{ + Tree *result=NULL; + Predicate *q; + Tree *t; + + if (p == NULL) return NULL; + +/* this appears strange: why do we OR the context + of and AND predicate ? It is because of the way + that predicates are evaluated: if the context is + wrong then it's the same as if the predicate was + true. That means that even when one leg of an + AND has unmatched context, if the other leg has + matched context and is true then the predicate + succeeds. It's only when all the legs have unmatched + context that this one can skip evaluation of the + predicates. +*/ + if (p->expr == PRED_OR_LIST || + p->expr == PRED_AND_LIST) { + for (q=p->down; q != NULL ; q=q->right) { + t=MR_compute_pred_tree_ctxXX(q); + result=tappend(result,t); + t=NULL; + }; + + result=tshrink(result); + result=tflatten( result ); + +/* does NOT left factor: do not want to merge + (A B) with (A) to get (A B) + in fact the opposite: (A B) with (A) gives (A) +*/ + +/**** result=tleft_factor( result ); ****/ + return result; + }; + +#if 0 +** if (p->expr == PRED_AND_LIST) { +** +** Predicate *l; +** Predicate *r; +** Tree *l1; +** Tree *r1; +** Tree *prevl1; +** +** l=p->down; +** require (l->right != NULL,"MR_compute_pred_tree - AND has only one child"); +** +**/* l1 and r1 should already be in "canonical" format */ +** +** l1=MR_compute_pred_tree(l); +** for (r=l->right; r != NULL; r=r->right) { +** r1=MR_compute_pred_tree(r); +** prevl1=l1; +** l1=MR_computeTreeAND(l1,r1); +** Tfree(r1); +** Tfree(prevl1); +** }; +** +**/* result from computeTreeAND should be in "canonical" format */ +** +** result=l1; +** +**/* result of MR_computeTreeAND should be in "canonical" format */ +** +** return result; +** }; +#endif + + if (p->k == 1) { + result=MR_make_tree_from_set(p->scontext[1]); + } else { + result=tdup(p->tcontext); + result=MR_remove_epsilon_from_tree(result); + result=tshrink(result); + result=tflatten(result); + result=tleft_factor(result); + }; + return result; +} + +#ifdef __USE_PROTOS +void MR_pred_depth(Predicate *p,int *maxDepth) +#else +void MR_pred_depth(p,maxDepth) + Predicate *p; + int *maxDepth; +#endif +{ + if (p == NULL) return; + if (p->expr != PRED_OR_LIST && + p->expr != PRED_AND_LIST) { + if (p->k > *maxDepth) *maxDepth=p->k; + }; + MR_pred_depth(p->down,maxDepth); + MR_pred_depth(p->right,maxDepth); +} + +/* this computes the OR of all the contexts */ + +#ifdef __USE_PROTOS +set MR_compute_pred_set(Predicate *p) +#else +set MR_compute_pred_set(p) + Predicate *p; +#endif +{ + set result; + Predicate *q; + + result=empty; + + if (p == NULL) return empty; + + if (p->expr == PRED_OR_LIST || + p->expr == PRED_AND_LIST) { /* yes, I do mean PRED_AND_LIST ! */ + /* remember: r1: (A)? => <

>? r2; */ + /* r2: (B)? => <>? r3; */ + set t; + + t=empty; + result=empty; + + for (q=p->down; q != NULL; q=q->right) { + t=MR_compute_pred_set(q); + set_orin(&result,t); + set_free(t); + }; + return result; + } else if (p->k > 1) { + return empty; + } else { + return set_dup(p->scontext[1]); + }; +} + +#ifdef __USE_PROTOS +set MR_First(int ck,Junction *j,set *incomplete) +#else +set MR_First(ck,j,incomplete) + int ck; + Junction *j; + set *incomplete; +#endif +{ + Junction *p; + set tokensUsed; + + tokensUsed=empty; + + require(j->ntype==nJunction, "MR_First: non junction passed"); + + p = analysis_point((Junction *)j->p1); + + REACH(p,ck,incomplete,tokensUsed); + + return tokensUsed; +} + +#ifdef __USE_PROTOS +void MR_cleanup_pred_trees(Predicate *p) +#else +void MR_cleanup_pred_trees(p) + Predicate *p; +#endif +{ + Tree *t; + + if (p == NULL) return; + if (p->expr != PRED_OR_LIST && + p->expr != PRED_AND_LIST) { + t=p->tcontext; + t=tshrink(t); + t=tflatten(t); + t=tleft_factor(t); + p->tcontext=t; + }; + MR_cleanup_pred_trees(p->down); + MR_cleanup_pred_trees(p->right); +} + +/* does NOT return canonical tree */ + +#ifdef __USE_PROTOS +Tree * MR_remove_epsilon_from_tree(Tree *t) +#else +Tree * MR_remove_epsilon_from_tree(t) + Tree *t; +#endif +{ + if (t == NULL) return NULL; + + /* I think ALT can be ignored as a special case */ + + if (t->token != EpToken) { + t->down=MR_remove_epsilon_from_tree(t->down); + t->right=MR_remove_epsilon_from_tree(t->right); + return t; + } else { + Tree *u; + u=MR_remove_epsilon_from_tree(t->right); + t->right=NULL; + Tfree(t); + return u; + }; +} + +#ifdef __USE_PROTOS +void MR_complete_set(int predDepth,set *tokensUsed,set *incomplete) +#else +void MR_complete_set(predDepth,tokensUsed,incomplete) + int predDepth; + set *tokensUsed; + set *incomplete; +#endif +{ + int i; + RuleRefNode *ruleRef; + set rk2; + set b; + int k2; + Junction *save_MR_RuleBlkWithHalt; + + if (set_int(*incomplete) > (unsigned) predDepth) { + return; + }; + + require(MR_PredRuleRefStack.count == MR_RuleBlkWithHaltStack.count, + "RuleRefStack and RuleBlkWithHaltStack not same size"); + + require(MR_RuleBlkWithHalt == NULL || + (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE), + "RuleBlkWithHalt has no halt set"); + + save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt; + + if (MR_RuleBlkWithHalt != NULL) { + MR_RuleBlkWithHalt->end->halt=FALSE; + }; + + for (i=MR_PredRuleRefStack.count-1; i >= 0 ; i--) { + ruleRef=(RuleRefNode *)MR_PredRuleRefStack.data[i]; + if (ruleRef == NULL) continue; + + MR_RuleBlkWithHalt=(Junction *)MR_RuleBlkWithHaltStack.data[i]; + if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=TRUE; + + rk2=empty; + b=empty; + + while ( !set_nil(*incomplete) ) { + k2=set_int(*incomplete); + if (k2 > predDepth) break; /* <=== another exit from loop */ + set_rm(k2,*incomplete); + REACH(ruleRef->next,k2,&rk2,b); + set_orin(tokensUsed,b); + set_free(b); + }; + + if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=FALSE; + + set_orin(incomplete,rk2); /* remember what we couldn't do */ + set_free(rk2); + if (set_int(*incomplete) > (unsigned) predDepth) break; /* <=== another exit from loop */ + }; + + MR_RuleBlkWithHalt=save_MR_RuleBlkWithHalt; + if (MR_RuleBlkWithHalt != NULL) { + MR_RuleBlkWithHalt->end->halt=TRUE; + }; +} + +#ifdef __USE_PROTOS +void MR_complete_tree(int predDepth,Tree **t,set *incomplete) +#else +void MR_complete_tree(predDepth,t,incomplete) + int predDepth; + Tree **t; + set *incomplete; +#endif +{ + int i; + RuleRefNode *ruleRef; + set rk2; + Tree *u; + unsigned k2; + Junction *save_MR_RuleBlkWithHalt; + int saveConstrainSearch; + + if (set_int(*incomplete) > (unsigned) predDepth) { + return; + }; + + require(MR_PredRuleRefStack.count == MR_RuleBlkWithHaltStack.count, + "RuleRefStack and RuleBlkWithHaltStack not same size"); + + require(MR_RuleBlkWithHalt == NULL || + (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE), + "RuleBlkWithHalt has no halt set"); + + save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt; + saveConstrainSearch=ConstrainSearch; + ConstrainSearch=0; + + if (MR_RuleBlkWithHalt != NULL) { + MR_RuleBlkWithHalt->end->halt=FALSE; + }; + + for (i=MR_PredRuleRefStack.count-1; i >= 0 ; i--) { + ruleRef=(RuleRefNode *)MR_PredRuleRefStack.data[i]; + if (ruleRef == NULL) continue; + + MR_RuleBlkWithHalt=(Junction *)MR_RuleBlkWithHaltStack.data[i]; + + if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=TRUE; + + rk2=empty; + + while ( !set_nil(*incomplete) ) { + k2 = set_int(*incomplete); + if (k2 > (unsigned) predDepth) break; /* <=== another exit from loop */ + set_rm(k2,*incomplete); + u = NULL; + + TRAV(ruleRef->next,k2,&rk2,u); + + /* any subtrees missing k2 tokens, add u onto end */ + + *t=tlink(*t,u,k2); + Tfree(u); + } + + set_orin(incomplete,rk2); /* remember what we couldn't do */ + set_free(rk2); + + if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=FALSE; + + if (set_int(*incomplete) > (unsigned) predDepth) break; /* <=== another exit from loop */ + }; + + MR_RuleBlkWithHalt=save_MR_RuleBlkWithHalt; + + if (MR_RuleBlkWithHalt != NULL) { + MR_RuleBlkWithHalt->end->halt=TRUE; + }; + ConstrainSearch=saveConstrainSearch; +} + +#ifdef __USE_PROTOS +void MR_complete_predicates(int predDepth,Predicate *pred) +#else +void MR_complete_predicates(predDepth,pred) + int predDepth; + Predicate *pred; +#endif +{ + if (pred == NULL) return; + if (pred->expr != PRED_AND_LIST && + pred->expr != PRED_OR_LIST) { + MR_complete_set(predDepth,&(pred->scontext[1]),&(pred->completionSet)); + MR_complete_tree(predDepth,&(pred->tcontext),&(pred->completionTree)); + }; + MR_complete_predicates(predDepth,pred->down); + MR_complete_predicates(predDepth,pred->right); +} + +#ifdef __USE_PROTOS +Junction * MR_junctionWithoutP2(Junction *j) +#else +Junction * MR_junctionWithoutP2(j) + Junction *j; +#endif +{ + Junction *thisAlt; + +/* don't want to follow p2 to the next alternative of this rule */ +/* insert a generic node with null p2 if necessary */ +/* however FIRST requires a junction */ + + thisAlt=j; + if (thisAlt->p2 != NULL) { + if (thisAlt->p1->ntype == nJunction) { + thisAlt=(Junction *) thisAlt->p1; + } else { + thisAlt=newJunction(); + thisAlt->p1=j->p1; + thisAlt->rname=j->rname; + thisAlt->file=j->file; + thisAlt->line=j->line; + j->p1=(Node *)thisAlt; + }; + }; + return thisAlt; +} + +#ifdef __USE_PROTOS +int MR_tree_equ(Tree *big, Tree *small) { +#else +int MR_tree_equ(big,small) + Tree *big; + Tree *small; +{ +#endif + + Tree *b; + Tree *s; + int bcount=0; + int scount=0; + + if (small == NULL && big == NULL) return 1; + if (small == NULL) return 0; + if (big == NULL) return 0; + + if (small->token == ALT) { + require(small->right == NULL, + "MR_tree_equ: small: ALT node has siblings"); + return MR_tree_equ(big,small->down); + }; + if (big->token == ALT) { + require(big->right == NULL, + "MR_tree_equ: big: ALT node has siblings"); + return MR_tree_equ(big->down,small); + }; + for (s=small; s != NULL; s=s->right) { + scount++; + require(s->token != EpToken,"MR_tree_equ: s->EpToken unexpected\n"); + }; + for (b=big; b != NULL; b=b->right) { + bcount++; + require(b->token != EpToken,"MR_tree_equ: b->EpToken unexpected\n"); + }; + + if (bcount != scount) return 0; + + for (s=small; s != NULL; s=s->right) { + for (b=big; b!= NULL; b=b->right) { + if (s->token == b->token) { + if (MR_tree_equ(b->down,s->down)) goto next_s; + }; + }; + return 0; +next_s: + continue; + }; + return 1; +} + +/* this does not compare sources - only contexts ! */ + +#ifdef __USE_PROTOS +int MR_identicalContext(Predicate *p,Predicate *q) +#else +int MR_identicalContext(p,q) + Predicate *p; + Predicate *q; +#endif +{ + if (p->k != q->k) return 0; + require ( (p->tcontext == NULL) == (q->tcontext == NULL), + "tcontext inconsistent"); + if (p->k == 1) { + return set_equ(p->scontext[1],q->scontext[1]); + } else { + return MR_tree_equ(p->tcontext,q->tcontext); + }; +} + +#ifdef __USE_PROTOS +void MR_reportSetSuppression(int predDepth, + set predSet,set plainSet,Junction *jPred,Junction *jPlain,Predicate *p) +#else +void MR_reportSetSuppression(predDepth,predSet,plainSet,jPred,jPlain,p) + int predDepth; + set predSet; + set plainSet; + Junction *jPred; + Junction *jPlain; + Predicate *p; +#endif +{ + if (InfoP) { + fprintf(output,"\n#if 0\n\n"); + fprintf(output,"Hoisting of predicate suppressed by alternative without predicate.\n"); + fprintf(output,"The alt without the predicate includes all cases where the predicate is false.\n\n"); + fprintf(output," WITH predicate: line %d %s\n",jPred->line,FileStr[jPred->file]); + if (jPlain != NULL) { + fprintf(output," WITHOUT predicate: line %d %s\n",jPlain->line,FileStr[jPlain->file]); + } else { + fprintf(output," WITHOUT predicate: all alternatives without predicates (combined)\n"); + }; + if (predDepth == 1) { + fprintf(output,"\nThe context set for the predicate:\n"); + MR_dumpTokenSet(output,1,predSet); + }; + fprintf(output,"\nThe lookahead set for the alt WITHOUT the semantic predicate:\n"); + MR_dumpTokenSet(output,1,plainSet); + fprintf(output,"\nThe predicate:\n\n"); + MR_dumpPred1(1,p,1); + fprintf(output,"Chain of referenced rules:\n\n"); + MR_dumpPredRuleRefStack(output,4); + fprintf(output,"\n#endif\n"); + }; +} + +#ifdef __USE_PROTOS +void MR_reportSetRestriction(int predDepth,set predSet,set plainSet, + Junction *jPred,Junction *jPlain,Predicate *origPred,Predicate *newPred) +#else +void MR_reportSetRestriction(predDepth,predSet,plainSet,jPred,jPlain,origPred,newPred) + int predDepth; + set predSet; + set plainSet; + Junction *jPred; + Junction *jPlain; + Predicate *origPred; + Predicate *newPred; +#endif +{ + set intersect; + + intersect=empty; + + if (! InfoP) return; + fprintf(output,"\n#if 0\n\n"); + fprintf(output,"Restricting the context of a predicate because of overlap in the lookahead set\n"); + fprintf(output," between the alternative with the semantic predicate and one without\n"); + fprintf(output,"Without this restriction the alternative without the predicate could not\n"); + fprintf(output," be reached when input matched the context of the predicate and the predicate\n"); + fprintf(output," was false.\n\n"); + + fprintf(output," WITH predicate: line %d %s\n",jPred->line,FileStr[jPred->file]); + if (jPlain != NULL) { + fprintf(output," WITHOUT predicate: line %d %s\n",jPlain->line,FileStr[jPlain->file]); + } else { + fprintf(output," WITHOUT predicate: all alternatives without predicates (combined)\n"); + }; + if (predDepth == 1) { + fprintf(output,"\nThe original context set for the predicate:\n"); + MR_dumpTokenSet(output,1,predSet); + }; + fprintf(output,"\nThe lookahead set for the alt WITHOUT the semantic predicate:\n"); + MR_dumpTokenSet(output,1,plainSet); + if (predDepth == 1) { + fprintf(output,"\nThe intersection of the two sets\n"); + intersect=set_and(predSet,plainSet); + MR_dumpTokenSet(output,1,intersect); + set_free(intersect); + }; + fprintf(output,"\nThe original predicate:\n\n"); + MR_dumpPred1(1,origPred,1); + fprintf(output,"The new (modified) form of the predicate:\n\n"); + MR_dumpPred1(1,newPred,1); + fprintf(output,"#endif\n"); +} + +/* don't use Pass3 by itself unless you know that inverted is not important */ + +#ifdef __USE_PROTOS +Predicate * MR_removeRedundantPredPass3(Predicate *p) +#else +Predicate * MR_removeRedundantPredPass3(p) + Predicate *p; +#endif +{ + Predicate *q; + + if (p == NULL) return NULL; + p->right=MR_removeRedundantPredPass3(p->right); + p->down=MR_removeRedundantPredPass3(p->down); + if (p->redundant) { + q=p->right; + p->right=NULL; + predicate_free(p); + return q; + }; + if (p->expr == PRED_AND_LIST || + p->expr == PRED_OR_LIST) { + if (p->down == NULL) { + q=p->right; + p->right=NULL; + predicate_free(p); + return q; + }; + if (p->down != NULL && p->down->right == NULL) { + q=p->down; + q->right=p->right; + p->right=NULL; + p->down=NULL; + return q; + }; + }; + return p; +} + +#ifdef __USE_PROTOS +void MR_removeRedundantPredPass2(Predicate *p) +#else +void MR_removeRedundantPredPass2(p) + Predicate *p; +#endif +{ + Predicate *q; + + if (p == NULL) return; + + if (p->expr == PRED_AND_LIST) { + for (q=p->down ; q != NULL ; q=q->right) { + MR_removeRedundantPredPass2(q); + if (q->isConst) { + if (q->constValue == 0) { + p->isConst=1; + p->constValue=0; + return; + } else { + q->redundant=1; + }; + }; + }; + }; + + if (p->expr == PRED_OR_LIST) { + for (q=p->down ; q != NULL ; q=q->right) { + MR_removeRedundantPredPass2(q); + if (q->isConst) { + if (q->constValue == 0) { + q->redundant=1; + } else { + p->isConst=1; + p->constValue=1; + return; + }; + }; + }; + }; + + return; +} + +#if 0 + this totally ignores the implications of guarded predicates + in which the part after the guard could possibly cover a predicate. + that would be much harder: + + rule : (A)? => <

>? sub1; /* 1 */ + | (B)? => <>? sub2 /* 2 */ + sub1 : (A)? => <>? A B /* 3 */ + | B /* 4 - suppresses line 2 */ + ; +#endif + +#ifdef __USE_PROTOS +void MR_apply_restriction1(Predicate *pred,set *plainSet,int *changed) +#else +void MR_apply_restriction1(pred,plainSet,changed) + Predicate *pred; + set *plainSet; + int *changed; +#endif +{ + if (pred == NULL) return; + MR_apply_restriction1(pred->right,plainSet,changed); + if (pred->down != NULL) { + MR_apply_restriction1(pred->down,plainSet,changed); + } else { + set t; + if (pred->k == 1) { + t=set_dif(pred->scontext[1],*plainSet); + if (*changed == 0 && + !set_equ(t,pred->scontext[1])) { + *changed=1; + }; + if (set_nil(t)) { + pred->redundant=1; + }; + set_free(pred->scontext[1]); + pred->scontext[1]=t; + }; + }; +} + +#ifdef __USE_PROTOS +void MR_orin_plainSet(Predicate *p,set plainSet) +#else +void MR_orin_plainSet(p,plainSet) + Predicate *p; + set plainSet; +#endif +{ + if (p == NULL) return; + MR_orin_plainSet(p->down,plainSet); + MR_orin_plainSet(p->right,plainSet); + set_orin(&p->plainSet,plainSet); +} + +Predicate *PRED_SUPPRESS; + +#ifdef __USE_PROTOS +Predicate * MR_find_in_aSubBlk(Junction *alt) +#else +Predicate * MR_find_in_aSubBlk(alt) + Junction *alt; +#endif +{ + Predicate *root=NULL; + Predicate **tail=NULL; + + Junction *p; + + int nAlts=0; + Junction **jList; + Predicate **predList; + int *matchList; + set predSet; + int i; + int j; + int m; + int predDepth; + set incomplete; + set union_plainSet; + set setChange; + int changed; + Predicate *newPred; + set setDif; + Predicate *origPred; + int depth1=1; /* const int */ + set *plainContext; + set plainSet; + + predSet=empty; + incomplete=empty; + union_plainSet=empty; + setChange=empty; + setDif=empty; + plainSet=empty; + + if (PRED_SUPPRESS == NULL) { + PRED_SUPPRESS=new_pred(); + PRED_SUPPRESS->expr="Predicate Suppressed"; + }; + + /* this section just counts the number of "interesting" alternatives */ + /* in order to allocate arrays */ + + for (p=alt; p!=NULL; p=(Junction *)p->p2) { + /* ignore empty alts */ + if ( p->p1->ntype != nJunction || + ((Junction *)p->p1)->jtype != EndBlk ) { + nAlts++; + }; + }; + + /* if this is a (...)+ block then don't count the last alt because + it can't be taken until at least one time through the block. + In other words it isn't a real choice until the (...)+ is entered + at which point the hoisting issue is moot. + Maybe look at "ignore" instead ? + */ + + if (alt->jtype == aPlusBlk) { + nAlts--; + }; + + jList=(Junction **)calloc(nAlts,sizeof(Junction *)); + require(jList!=NULL,"cannot allocate MR_find_in_aSubBlk jList"); + + plainContext=(set *)calloc(nAlts,sizeof(set)); + require(plainContext!=NULL,"cannot allocate MR_find_in_aSubBlk plainContext"); + for (m=0; m < nAlts; m++) plainContext[m]=empty; + + predList=(Predicate **)calloc(nAlts,sizeof(Predicate *)); + require(predList!=NULL,"cannot allocate MR_find_in_aSubBlk predList"); + + matchList=(int *)calloc(nAlts,sizeof(int)); + require(matchList!=NULL,"cannot allocate MR_find_in_aSubBlk matchList"); + + /* this section just fills in the arrays previously allocated */ + /* the most interesting one is matchList[] */ + /* */ + /* bit 0 => this alt has a semantic pred which is "covered" */ + /* by an alt without a semantic pred. Don't hoist. */ + + for (i=0,p=alt; + p!=NULL && ip2) { + + /* ignore empty alts */ + + if ( p->p1->ntype != nJunction || + ((Junction *)p->p1)->jtype != EndBlk ) { + jList[i]=MR_junctionWithoutP2(p); + predList[i]=find_predicates(p->p1); /* should be jList ????? */ + if (predList[i] != NULL) { + MR_cleanup_pred_trees(predList[i]); /* flatten & left factor */ + plainContext[i]=MR_union_plain_sets(predList[i]); + } else { + MR_set_reuse(&plainSet); + MR_set_reuse(&incomplete); + plainSet=MR_First(depth1,jList[i],&incomplete); + MR_complete_set(depth1,&plainSet,&incomplete); + require(set_nil(incomplete),"couldn't complete k=1"); + plainContext[i]=plainSet; + plainSet=empty; + }; + set_orin(&union_plainSet,plainContext[i]); + }; + }; + + if (nAlts == 1) { + goto EXIT_SIMPLE; + }; + +/* + * Looking for cases where alt i has a semantic pred and alt j does not. + * Don't care about cases where lookahead for semantic predicates overlap + * because normal predicate hoisting does the correct thing automatically. + * Don't care about cases where lookahead for alts without semantic predicates + * overlap because normal prediction does the correct thing automatically. + * + * When we find such a case check for one of three subcases: + * + * 1. if lookahead for alt i is contained in the lookahead for any + * alt j then ignore semantic predicate of alt i + * 2. if lookahead for alt i is not contained in the lookahead for + * any alt j then add add predicate i to the OR list to be hoisted + * 3. if lookahead for alt i overlaps the lookahead for some alt j then + * add a dummy semantic predicate for alt j + * + * There is an implicit assumption that the context of all alternatives following + * the rule being processed here are identical (but may vary from hoist to + * hoist depending on the place where the rule was invoked that led to hoisting + * these predicates. In othere words in the fragment: + * + * ( <>? a1 a2 a3 | <>? b1 b2 b3 ) + * + * both a3 and b3 have the same follow sets because they are both at the end of + * alternatives in the same block. + */ + + for (i=0; i < nAlts; i++) { + if (jList[i] == NULL) continue; + if (predList[i] == NULL) continue; + + /* if the predicate depth turns out to be one token only */ + /* then it is can be easily represented as a set and */ + /* compared to the junction set create by MR_First() */ + + predDepth=0; + MR_pred_depth(predList[i],&predDepth); + require (predDepth >= 1,"MR_find_in_aSubBlk: pred depth < 1"); + require (predDepth <= CLL_k,"MR_find_in_aSubBlk: predDepth > CLL_k"); + + /* complete predicates to predDepth + If completed to depth=1 then the context would be incomplete. + The context would be truncated and the predicate simplify routine + would have incomplete information. It would lead to + either false matches of failure to find true matches. + */ + + MR_complete_predicates(predDepth,predList[i]); + + if (predList[i] != NULL) { + MR_cleanup_pred_trees(predList[i]); /* flatten & left factor */ + }; + + /* If the predicate depth is 1 then it is possible to suppress + a predicate completely using a single plain alt. Check for suppression + by a single plain alt first because it gives better messages. If that + fails try the union of all the plain alts. + */ + + if (predDepth == 1) { + + MR_set_reuse(&predSet); + predSet=MR_compute_pred_set(predList[i]); /* ignores k>1 predicates */ + + for (j=0; j < nAlts; j++) { + if (jList[j] == NULL) continue; + if (j == i) continue; + + MR_set_reuse(&setDif); + setDif=set_dif(predSet,plainContext[j]); + if (set_nil(setDif)) { + matchList[i] |= 1; + MR_reportSetSuppression(predDepth,predSet,plainContext[j],jList[i],jList[j],predList[i]); + predicate_free(predList[i]); + predList[i]=PRED_SUPPRESS; + goto next_i; + }; + + }; /* end loop on j */ + + changed=0; + + /* predicate_dup is only to give good error messages */ + /* remember to do a predicate_free() */ + + origPred=predicate_dup(predList[i]); + MR_apply_restriction1(predList[i],&union_plainSet,&changed); + if (changed) { + + /* don't use Pass3 by itself unless you know that inverted is not important */ + + newPred=MR_removeRedundantPredPass3(predList[i]); + newPred=MR_predSimplifyALL(newPred); + if (newPred == NULL) { + matchList[i] |= 1; + MR_reportSetSuppression(predDepth,predSet,union_plainSet,jList[i], + NULL,origPred); + predList[i]=PRED_SUPPRESS; + } else { + MR_reportSetRestriction(predDepth,predSet,union_plainSet,jList[i], + NULL,origPred,newPred); + predList[i]=newPred; + }; + }; + predicate_free(origPred); + origPred=NULL; + }; + + /* + If the predicate depth is > 1 then it can't be suppressed completely + because the code doesn't support inspection of such things. They're + much messier than k=1 sets. + */ + + if (predDepth > 1 ) { + + changed=0; + + /* predicate_dup is only to give good error messages */ + /* remember to do a predicate_free() */ + + origPred=predicate_dup(predList[i]); + MR_apply_restriction1(predList[i],&union_plainSet,&changed); + if (changed) { + newPred=MR_removeRedundantPredPass3(predList[i]); + newPred=MR_predSimplifyALL(newPred); + if (newPred == NULL) { + matchList[i] |= 1; + MR_reportSetSuppression(predDepth,predSet,union_plainSet,jList[i], + NULL,origPred); + predList[i]=PRED_SUPPRESS; + } else { + MR_reportSetRestriction(predDepth,predSet,union_plainSet,jList[i], + NULL,origPred,newPred); + predList[i]=newPred; + }; + }; + predicate_free(origPred); + origPred=NULL; + }; +next_i: + continue; + }; + +EXIT_SIMPLE: + + root = new_pred(); + root->expr=PRED_OR_LIST; + tail = &(root->down); + + for (i=0 ; i< nAlts ; i++) { + if (jList[i] == NULL) continue; + + if (predList[i] == NULL) { + continue; + } else if ( (matchList[i] & 1) != 0) { + if (predList[i] != PRED_SUPPRESS) { + predicate_free(predList[i]); + }; + continue; + }; + + /* make an OR list of predicates */ + + *tail=predList[i]; + tail=&(predList[i]->right); + }; + + /* if just one pred, remove OR root */ + + if (root->down == NULL) { + predicate_free(root); + root=NULL; + } else if (root->down->right == NULL) { + Predicate *p=root->down; + root->down=NULL; + predicate_free(root); + root=p; + } + + root=MR_predSimplifyALL(root); + + MR_orin_plainSet(root,union_plainSet); + + set_free(predSet); + set_free(union_plainSet); + set_free(incomplete); + set_free(setChange); + set_free(setDif); + + for (m=0; m < nAlts; m++) set_free(plainContext[m]); + + free ( (char *) jList); + free ( (char *) predList); + free ( (char *) matchList); + free ( (char *) plainContext); + + return root; +} + +#ifdef __USE_PROTOS +void MR_predContextPresent(Predicate *p,int *allHaveContext,int *noneHaveContext) +#else +void MR_predContextPresent(p,allHaveContext,noneHaveContext) + Predicate *p; + int *allHaveContext; + int *noneHaveContext; +#endif +{ + if (p == NULL) return; + MR_predContextPresent(p->right,allHaveContext,noneHaveContext); + if (p->expr != PRED_AND_LIST && + p->expr != PRED_OR_LIST) { + if (set_nil(p->scontext[1]) == 0 || + (p->tcontext != NULL)) { + *noneHaveContext=0; + } else { + *allHaveContext=0; + }; + }; + MR_predContextPresent(p->down,allHaveContext,noneHaveContext); +} + +#ifdef __USE_PROTOS +int MR_pointerStackPush(PointerStack *ps,void *dataPointer) +#else +int MR_pointerStackPush(ps,dataPointer) + PointerStack *ps; + void *dataPointer; +#endif +{ + void **newStack; + int newSize; + int i; + + if (ps->count == ps->size) { + newSize=20+ps->size*2; + newStack=(void **)calloc(newSize,sizeof(void *)); + require (newStack != NULL,"cannot allocate PointerStack"); + for (i=0; i < ps->size; i++) { + newStack[i]=ps->data[i]; + }; + if (ps->data != NULL) free( (char *) ps->data); + ps->data=newStack; + ps->size=newSize; + }; + ps->data[ps->count]=dataPointer; + ps->count++; + return ps->count-1; +} + +#ifdef __USE_PROTOS +void * MR_pointerStackPop(PointerStack *ps) +#else +void * MR_pointerStackPop(ps) + PointerStack *ps; +#endif +{ + void *dataPointer; + + require(ps->count > 0,"MR_pointerStackPop underflow"); + + dataPointer=ps->data[ps->count-1]; + ps->data[ps->count-1]=NULL; + (ps->count)--; + return dataPointer; +} + +#ifdef __USE_PROTOS +void * MR_pointerStackTop(PointerStack *ps) +#else +void * MR_pointerStackTop(ps) + PointerStack *ps; +#endif +{ + require(ps->count > 0,"MR_pointerStackTop underflow"); + return ps->data[ps->count-1]; +} + +#ifdef __USE_PROTOS +void MR_pointerStackReset(PointerStack *ps) +#else +void MR_pointerStackReset(ps) + PointerStack *ps; +#endif +{ + int i; + if (ps->data != NULL) { + for (i=0; i < ps->count ; i++) { + ps->data[i]=NULL; + }; + }; + ps->count=0; +} + +#ifdef __USE_PROTOS +Junction *MR_nameToRuleBlk(char *name) +#else +Junction *MR_nameToRuleBlk(name) + char *name; +#endif +{ + RuleEntry *q; + + require (RulePtr != NULL,"MR_nameToRule: RulePtr not initialized"); + + if (name == NULL) return NULL; + + q = (RuleEntry *) hash_get(Rname,name); + + if ( q == NULL ) { + return NULL; + } else { + return RulePtr[q->rulenum]; + }; +} + +#ifdef __USE_PROTOS +Junction * MR_ruleReferenced(RuleRefNode *rrn) +#else +Junction * MR_ruleReferenced(rrn) + RuleRefNode *rrn; +#endif +{ + return MR_nameToRuleBlk(rrn->text); +} + +#ifdef __USE_PROTOS +void MR_comparePredLeaves(Predicate *me,Predicate *myParent,Predicate *him,Predicate *hisParent) +#else +void MR_comparePredLeaves(me,myParent,him,hisParent) + Predicate *me; + Predicate *myParent; + Predicate *him; + Predicate *hisParent; +#endif +{ + if (me == NULL) return; + if (me == him) { + MR_comparePredLeaves(me->right,myParent,him,hisParent); + return; + } else if (me->expr == PRED_AND_LIST || + me->expr == PRED_OR_LIST) { + MR_comparePredLeaves(me->down,me,him,hisParent); + MR_comparePredLeaves(me->right,myParent,him,hisParent); + return; + } else { + if (me->source != NULL) { + + /* predicate->invert can be set only in the predEntry predicates */ + /* thus they are only visible after the predEntry predicates have been "unfolded" */ + + int sameSource=(me->source == him->source); + int sameInvert=1 & + (1 + me->inverted + him->inverted + me->source->inverted + him->source->inverted); + int samePredEntry=(me->source->predEntry != NULL + && him->source->predEntry != NULL + && me->source->predEntry == him->source->predEntry); + if (sameInvert && (sameSource || samePredEntry)) { + if (MR_identicalContext(me,him)) { + + /* identical predicates */ + + if (hisParent->expr == PRED_OR_LIST && + myParent->expr == PRED_OR_LIST) { + me->redundant=1; + } else if (hisParent->expr == PRED_AND_LIST && + myParent->expr == PRED_AND_LIST) { + me->redundant=1; + } else if ( (hisParent->expr == PRED_OR_LIST && + myParent->expr == PRED_AND_LIST) + || + (hisParent->expr == PRED_AND_LIST && + myParent->expr == PRED_OR_LIST) + ) { + myParent->redundant=1; + } else { + require (0,"MR_comparePredLeaves: not both PRED_LIST"); + }; + }; + }; /* end same source or same predEntrr with same invert sense */ + + /* same predEntry but opposite invert sense */ + + if (!sameInvert && (sameSource || samePredEntry)) { + if (MR_identicalContext(me,him)) { + if (hisParent->expr == PRED_OR_LIST && + myParent->expr == PRED_OR_LIST) { + myParent->isConst=1; + myParent->constValue=1; + } else if (hisParent->expr == PRED_AND_LIST && + myParent->expr == PRED_AND_LIST) { + myParent->isConst=1; + myParent->constValue=0; + } else if ( (hisParent->expr == PRED_OR_LIST && + myParent->expr == PRED_AND_LIST) + || + (hisParent->expr == PRED_AND_LIST && + myParent->expr == PRED_OR_LIST) + ) { + me->redundant=1; + } else { + require (0,"MR_comparePredLeaves: not both PRED_LIST"); + }; + }; + }; /* end same predEntry with opposite invert sense */ + }; + + MR_comparePredLeaves(me->right,myParent,him,hisParent); + return; + }; +} + +#ifdef __USE_PROTOS +void MR_removeRedundantPredPass1(Predicate *me,Predicate *myParent) +#else +void MR_removeRedundantPredPass1(me,myParent) + Predicate *me; + Predicate *myParent; +#endif +{ + if (me == NULL) return; + if (me->redundant) { + MR_removeRedundantPredPass1(me->right,myParent); + return; + }; + if (me->expr == PRED_AND_LIST || + me->expr == PRED_OR_LIST) { + MR_removeRedundantPredPass1(me->down,me); + MR_removeRedundantPredPass1(me->right,myParent); + } else { + require (me->source != NULL,"me->source == NULL"); + if (myParent != NULL) { + MR_comparePredLeaves(myParent->down,myParent,me,myParent); + }; + MR_removeRedundantPredPass1(me->right,myParent); + }; +} + +/* pretty much ignores things with the inverted bit set */ + +#ifdef __USE_PROTOS +Predicate *MR_predFlatten(Predicate *p) +#else +Predicate *MR_predFlatten(p) + Predicate *p; +#endif +{ + if (p == NULL) return NULL; + if (p->expr == PRED_OR_LIST + || p->expr == PRED_AND_LIST) { + + Predicate *child; + Predicate *gchild; + Predicate **tail; + Predicate *next; + char *PRED_XXX_LIST=p->expr; + + require (p->down != NULL,"MR_predFlatten AND/OR no child"); + + + p->down=MR_predFlatten(p->down); + p->right=MR_predFlatten(p->right); + child=p->down; + if (child->right == NULL) { + child->right=p->right; + p->right=NULL; + p->down=NULL; + if (p->inverted) child->inverted=!child->inverted; + predicate_free(p); + return child; + }; + + /* make a single list of all children and grandchildren */ + + tail=&(p->down); + for (child=p->down; child != NULL; child=next) { + if (child->expr != PRED_XXX_LIST + || child->inverted + || child->predEntry != NULL) { + *tail=child; + tail=&(child->right); + next=child->right; + } else { + for (gchild=child->down; + gchild != NULL; + gchild=gchild->right) { + *tail=gchild; + tail=&(gchild->right); + }; + next=child->right; + child->right=NULL; + child->down=NULL; + predicate_free(child); + }; + }; + *tail=NULL; + return p; + } else { + p->right=MR_predFlatten(p->right); + return p; + }; +} + +static char *alwaysFalseWarning=NULL; + +#ifdef __USE_PROTOS +Predicate *checkPredicateConflict(Predicate *p) +#else +Predicate *checkPredicateConflict(p) + Predicate *p; +#endif +{ + if (p->isConst) { + if (p->constValue == 1) { + predicate_free(p); + return NULL; + } else { + if (InfoP && !p->conflictReported) { + p->conflictReported=1; + fprintf(output,"\n#if 0\n\n"); + fprintf(output,"The following predicate expression will always be false:\n\n"); + MR_dumpPred1(1,p,1); + fprintf(output,"\n#endif\n"); + }; + + if (alwaysFalseWarning != CurRule) { + alwaysFalseWarning=CurRule; + if (InfoP) { + warnNoFL(eMsg1("one (or more) predicate expression hoisted into rule \"%s\" are always false \ +- see output file for more information",CurRule)); + } else { + warnNoFL(eMsg1("one (or more) predicate expressions hoisted into rule \"%s\" are always false \ +- use \"-info p\" for more information",CurRule)); + }; + }; + }; + }; + return p; +} + + +#ifdef __USE_PROTOS +int MR_countPredNodes(Predicate *p) +#else +int MR_countPredNodes(p) + Predicate *p; +#endif +{ + if (p == NULL) return 0; + return 1 + MR_countPredNodes(p->down) + MR_countPredNodes(p->right); +} + +#ifdef __USE_PROTOS +Predicate *MR_predSimplifyALLX(Predicate *p,int skipPass3) +#else +Predicate *MR_predSimplifyALLX(p,skipPass3) + Predicate *p; + int skipPass3; +#endif +{ + int countBefore; + int countAfter; + + countAfter=MR_countPredNodes(p); + + do { + if (p == NULL) return NULL; + if (p->right == NULL && p->down == NULL) return p; + countBefore=countAfter; + MR_simplifyInverted(p,0); + p=MR_predFlatten(p); + MR_removeRedundantPredPass1(p,NULL); + MR_removeRedundantPredPass2(p); + if (! skipPass3) { + p=checkPredicateConflict(p); + p=MR_removeRedundantPredPass3(p); + }; + countAfter=MR_countPredNodes(p); + } while (countBefore != countAfter); + + return p; +} + +#ifdef __USE_PROTOS +Predicate *MR_predSimplifyALL(Predicate *p) +#else +Predicate *MR_predSimplifyALL(p) + Predicate *p; +#endif +{ + return MR_predSimplifyALLX(p,0); +} + +#ifdef __USE_PROTOS +void MR_releaseResourcesUsedInRule(Node *n) +#else +void MR_releaseResourcesUsedInRule(n) + Node *n; +#endif +{ + Node *next; + Junction *j; + int i; + + if (n == NULL) return; + if (n->ntype == nJunction) { + j=(Junction *) n; + + if (j->predicate != NULL) { + predicate_free(j->predicate); + j->predicate=NULL; + }; + for (i=0; i< CLL_k; i++) { + set_free(j->fset[i]); + j->fset[i]=empty; + }; + if (j->ftree != NULL) { + Tfree(j->ftree); + j->ftree=NULL; + }; + if (j->jtype == EndRule) return; + if (j->jtype != RuleBlk && j->jtype != EndBlk) { + if (j->p2 != NULL && !j->ignore) { /* MR11 */ + MR_releaseResourcesUsedInRule(j->p2); + }; + }; + }; + next=MR_advance(n); + MR_releaseResourcesUsedInRule(next); +} + +#ifdef __USE_PROTOS +int MR_allPredLeaves(Predicate *p) +#else +int MR_allPredLeaves(p) + Predicate *p; +#endif +{ + Predicate *q; + + if (p == NULL) return 1; + + for (q=p; q != NULL; q=q->right) { + if (q->down != NULL) return 0; + }; + return 1; +} + +/* make sure it works for the last rule in a file */ + +#ifdef __USE_PROTOS +int MR_offsetFromRule(Node *n) +#else +int MR_offsetFromRule(n) + Node *n; +#endif +{ + Junction *j; + int offset=(-1); + + for (j=SynDiag; j != NULL; j=(Junction *)j->p2) { + + require (j->ntype == nJunction && j->jtype == RuleBlk,"Not a rule block"); + + if (n->file < j->file) { + return offset; + }; + if (n->file == j->file) { + if (n->line < j->line) { + return (offset < 0) ? 0 : offset; + } else { + offset=n->line - j->line; + if (offset == 0) return 0; + }; + }; + }; + return offset; +} + +#define ruleNameMax 50 + +static char ruleNameStatic1[ruleNameMax]; +static char ruleNameStatic2[ruleNameMax+10]; + +#ifdef __USE_PROTOS +char * MR_ruleNamePlusOffset(Node *n) +#else +char * MR_ruleNamePlusOffset(n) + Node *n; +#endif +{ + int offset=MR_offsetFromRule(n); + + strncpy(ruleNameStatic1,n->rname,ruleNameMax); + if (offset < 0) { + sprintf(ruleNameStatic2,"%s/?",ruleNameStatic1); + } else { + sprintf(ruleNameStatic2,"%s/%d",ruleNameStatic1,offset+1); + }; + return ruleNameStatic2; +} + +#ifdef __USE_PROTOS +int MR_max_height_of_tree(Tree *t) +#else +int MR_max_height_of_tree(t) + Tree *t; +#endif +{ + int h; + int height=0; + Tree *u; + + if (t == NULL) return 0; + + require (t->token != ALT && t->token != EpToken,"MR_max_height_of_tree ALT or EpToken"); + + for (u=t; u != NULL; u=u->right) { + h=MR_max_height_of_tree(u->down)+1; + if (h > height) height=h; + }; + return height; +} + +#ifdef __USE_PROTOS +int MR_all_leaves_same_height(Tree *t,int depth) +#else +int MR_all_leaves_same_height(t,depth) + Tree *t; + int depth; +#endif +{ + if (t == NULL) { + return (depth==0); + }; + + require (t->token != ALT && t->token != EpToken,"MR_all_leaves_same_height ALT or EpToken"); + + if (depth == 0) { + return 0; + } else { + if ( ! MR_all_leaves_same_height(t->down,depth-1)) { + return 0; + }; + if (t->right == NULL) { + return 1; + } else { + return MR_all_leaves_same_height(t->right,depth); + }; + }; +} + +#ifdef __USE_PROTOS +void MR_projectTreeOntoSet(Tree *tree,int ck,set *ckset) +#else +void MR_projectTreeOntoSet(tree,ck,ckset) + Tree *tree; + int ck; + set *ckset; +#endif +{ + if (tree == NULL) return; + + require(tree->token != EpToken,"MR_projectTreeOntoSet: EpToken unexpected\n"); + + MR_projectTreeOntoSet(tree->right,ck,ckset); + if (tree->token == ALT) { + MR_projectTreeOntoSet(tree->down,ck,ckset); + } else { + if (ck > 1) { + MR_projectTreeOntoSet(tree->down,ck-1,ckset); + } else { + set_orel(tree->token,ckset); + }; + }; +} + +#ifdef __USE_PROTOS +int MR_comparePredicates(Predicate *a,Predicate *b) +#else +int MR_comparePredicates(a,b) + Predicate *a; + Predicate *b; +#endif +{ + Predicate *p; + Predicate *q; + + if (a == b) return 1; + if (a == NULL || b == NULL ) return 0; + if (a->down == NULL && b->down == NULL) { + + /* predicate->invert can be set only in the predEntry predicates */ + /* thus they are only visible after the predEntry predicates have been "unfolded" */ + + int sameSource=(a->source == b->source); + int sameInvert= 1 & (1 +a->inverted + b->inverted + + a->source->inverted + b->source->inverted); + int samePredEntry=(a->source->predEntry != NULL + && b->source->predEntry != NULL + && a->source->predEntry == b->source->predEntry); + if (sameInvert && (sameSource || samePredEntry)) { + if (MR_identicalContext(a,b)) { + return 1; + }; + }; + return 0; + }; + if (a->down == NULL || b->down == NULL) return 0; + if (a->expr != b->expr) return 0; + + for (p=a->down; p != NULL; p=p->right) { + for (q=b->down; q != NULL; q=q->right) { + if (MR_comparePredicates(p,q)) goto NEXT_P; + }; + return 0; +NEXT_P: + continue; + }; + return 1; +} + +/* + * action->inverted can be set only when a predicate symbol appears in + * a rule: "rule : <>? X". It cannot be set under any + * other circumstances. In particular it cannot be set by + * "#pred NotA !A" or by "#pred Nota <>?". The first case + * creates a predEntry and the predicate expression of that predEntry + * has inverted set. In the second case, the code for handling "!" + * is only present in buildAction, which is not called by the #pred + * semantic routines, only when a <<...>>? is recognized as part of + * a rule definition. + * + * predicate->inverted can only be set by a predicate created by a #pred + * expression, such as "#pred NotA !A" or "#pred NotXY ! (X && Y) or + * "#pred XbarY !(X && Y)". In particular, it cannot be set by any + * predicate expression occurring under any other circumstances. + * The #pred predicate expresssions are stored with in predEntry->pred + * and do not normally appear anywhere else until the predicates are + * "unfolded" in order to recognize redundancies, conflicts, and + * tautologies. + * + * The unfold routine expands all references to #pred expressions. + * + * The simplifyInvert goes through and propagates the invert bit so that + * all OR and AND nodes are un-inverted. + * + * Note that !(A and B) => (!A or !B) + * !(A or B) => (!A and !B) + * + * MR_unfold() is called to expand predicate symbols by replacing predicates + * that reference predicate entries with the copies of the predicate entries. + * Each reference receives a duplicate of the original. This is necessary + * because the next phase involves simplification and removal of redundant + * predicate nodes. Anyway, the point I'm making is that predicate->invert + * should not be set in any predicate until it has been expanded. + * + * This is a recursive structure, but there is no need for "recursive expansion" + * by which I mean a predicate symbol refers to other predicate symbols which + * must also be expanded. + * + * Recursive expansion is *not* performed by this routine because it is not + * necessary. Expansion of references is performed by predPrimary when + * a new predicate symbol is created by referring to others in the pred expr. + */ + +#ifdef __USE_PROTOS +Predicate *MR_unfold(Predicate *pred) +#else +Predicate *MR_unfold(pred) + Predicate *pred; +#endif +{ + Predicate *result; + + if (pred == NULL) return NULL; + + pred->right=MR_unfold(pred->right); + + if (pred->down == NULL) { + if (pred->source->predEntry != NULL) { + if (pred->source->predEntry->pred == NULL) { + ; /* do nothing */ /* a reference to a literal #pred (perhaps with "!" */ + } else { + result=predicate_dup_without_context(pred->source->predEntry->pred); + if (pred->inverted) { + result->inverted=!result->inverted; + }; + if (pred->source->inverted) { + result->inverted=!result->inverted; + }; + result->right=pred->right; + pred->right=NULL; + predicate_free(pred); +/*** result=MR_unfold(result); *** not necessary */ /* recursive expansion */ + return result; + }; + } else { + ; /* do nothing */ /* an inline literal predicate */ + }; + } else { + pred->down=MR_unfold(pred->down); + }; + return pred; +} + +/* this should be called immediately after MR_unfold() and + at no other times +*/ + +#ifdef __USE_PROTOS +void MR_simplifyInverted(Predicate *pred,int inverted) +#else +void MR_simplifyInverted(pred,inverted) + Predicate *pred; + int inverted; +#endif +{ + int newInverted; + + if (pred == NULL) return; + + MR_simplifyInverted(pred->right,inverted); + + newInverted= 1 & (inverted + pred->inverted); + + if (pred->down == NULL) { + pred->inverted=newInverted; + } else { + if (newInverted != 0) { + if (pred->expr == PRED_AND_LIST) { + pred->expr=PRED_OR_LIST; + } else { + pred->expr=PRED_AND_LIST; + }; + }; + pred->inverted=0; + MR_simplifyInverted(pred->down,newInverted); + }; +} + +/* only remove it from AND and OR nodes, not leaves */ + +#ifdef __USE_PROTOS +void MR_clearPredEntry(Predicate *p) +#else +void MR_clearPredEntry(p) + Predicate *p; +#endif +{ + if (p == NULL) return; + MR_clearPredEntry(p->down); + MR_clearPredEntry(p->right); + if (p->down != NULL) p->predEntry=NULL; +} + + +#ifdef __USE_PROTOS +void MR_orphanRules(FILE *f) +#else +void MR_orphanRules(f) + FILE *f; +#endif +{ + set a; + Junction *p; + unsigned e; + RuleEntry *re; + + a=empty; + + if (! InfoO) return; + + for (p=SynDiag; p!=NULL; p = (Junction *)p->p2) { + if ( (Junction *) (p->end)->p1 == NULL) { + re=(RuleEntry *) hash_get(Rname,p->rname); + require (re != NULL,"RuleEntry == NULL"); + set_orel(re->rulenum, &a); + } + } + + if (set_deg(a) > 1) { + fprintf(f,"note: Start rules: {"); + for (; !set_nil(a); set_rm(e,a)) { + e=set_int(a); + fprintf(f," %s",RulePtr[e]->rname); + }; + fprintf(f," }\n"); + }; + set_free( a ); +} + +/* merge (X Y) and (X) to create (X) */ + +static int *mergeChain; +static Tree *mergeTree; + +#ifdef __USE_PROTOS +Tree *MR_merge_tree_contexts_client(Tree *t,int chain[]) +#else +Tree *MR_merge_tree_contexts_client(t,chain) + Tree *t; + int chain[]; +#endif +{ + if (t == NULL) return NULL; + if (chain[0] == 0) { + Tree *u=t->right; + t->right=NULL; + Tfree(t); + return MR_merge_tree_contexts_client(u,&chain[0]); + } + if (chain[0] == t->token) { + t->down=MR_merge_tree_contexts_client(t->down,&chain[1]); + }; + t->right=MR_merge_tree_contexts_client(t->right,&chain[0]); + return t; +} + +#ifdef __USE_PROTOS +void MR_iterateOverTreeContexts(Tree *t,int chain[]) +#else +void MR_iterateOverTreeContexts(t,chain) + Tree *t; + int chain[]; +#endif +{ + if (t == NULL) return; + chain[0]=t->token; + if (t->down != NULL) { + MR_iterateOverTreeContexts(t->down,&chain[1]); + } else { + MR_merge_tree_contexts_client(mergeTree,mergeChain); + }; + MR_iterateOverTreeContexts(t->right,&chain[0]); + chain[0]=0; +} + +#ifdef __USE_PROTOS +Tree *MR_merge_tree_contexts(Tree *t) +#else +Tree *MR_merge_tree_contexts(t) + Tree *t; +#endif +{ + int h=MR_max_height_of_tree(t); + + mergeTree=t; + mergeChain=(int *) calloc(h+1,sizeof(int)); + require (mergeChain != NULL,"MR_merge_tree_contexts: can't alloc chain"); + MR_iterateOverTreeContexts(t,mergeChain); + t=tshrink(t); + t=tflatten(t); + t=tleft_factor(t); + free ( (char *) mergeChain); + mergeChain=NULL; + return t; +} + +#ifdef __USE_PROTOS +Tree *MR_compute_pred_tree_context(Predicate *p) +#else +Tree *MR_compute_pred_tree_context(p) + Predicate *p; +#endif +{ + Tree *t; + + t=MR_compute_pred_tree_ctxXX(p); + MR_merge_tree_contexts(t); + return t; +} + +#ifdef __USE_PROTOS +void MR_guardPred_plainSet(ActionNode *anode,Predicate *pred) +#else +void MR_guardPred_plainSet(anode,pred) + ActionNode *anode; + Predicate *pred; +#endif +{ + Junction *j; + Predicate *workPred; + set maskSet; + + maskSet=empty; + + if (!MRhoisting) return; + + /* it doesn't really matter whether the predicate has + depth k=1 or k>1 because we're not really looking + at the predicate itself, just the stuff "behind" + the predicate. + */ + + /* shouldn't have to worry about REACHing off the end + of the rule containing the predicate because the + Rule->end->halt should have been set already by the + the code which handles RuleRef nodes. + + We don't want to REACH off the end of the rule because + this would give the "global" follow context rather than + the "local" context. + + r1a : (A)? => <

>? r2 (A|B) + r1b : (A)? => <

>? r2 (A|C) + r2 : (); + + For r1a we want follow of predicate = {A B} + we want plainSet = {B} + For r1b we want follow of predicate = {A C} + we want plainSet = {C} + */ + + require (anode->next->ntype == nJunction,"MR_guardpred_plainSet not Junction"); + j=(Junction *)(anode->next); + + workPred=predicate_dup_without_context(pred); + workPred->k=1; + workPred->scontext[1]=MR_First(1,j, &(workPred->completionSet) ); + MR_complete_predicates(1,workPred); + if (pred->k == 1) { + maskSet=pred->scontext[1]; + } else { + MR_projectTreeOntoSet(pred->tcontext,1,&maskSet); + } + pred->plainSet=set_dif(workPred->scontext[1],maskSet); + predicate_free(workPred); +} + +/*******************************************************************************/ + +static Tree * suppressTree; +static int * suppressChain; /* element 0 not used */ +static set * suppressSets; +static Node * suppressNode; +static int suppressChainLength; +int MR_SuppressSearch=0; +static int suppressSucceeded; +static Predicate * suppressPredicate; + +#ifdef __USE_PROTOS +int MR_isChain(Tree *t) +#else +int MR_isChain(t) + Tree *t; +#endif +{ + Tree *u; + + for (u=t; u != NULL; u=u->down) { + if (u->right != NULL) return 0; + } + return 1; +} + +#ifdef __USE_PROTOS +int MR_suppressK_client(Tree *tree,int tokensInChain[]) +#else +int MR_suppressK_client(tree,tokensInChain) + Tree *tree; + int tokensInChain[]; +#endif +{ + int i; + set *save_fset; + int save_ConstrainSearch; + set incomplete; + Tree *t; + + suppressSucceeded=0; /* volatile */ + + if (suppressSets == NULL) { + suppressSets=(set *) calloc (CLL_k+1,sizeof(set)); + require (suppressSets != NULL,"MR_suppressK_client: suppressSets alloc"); + }; + + for (suppressChainLength=1; + tokensInChain[suppressChainLength+1] != 0; + suppressChainLength++) {}; + + require (suppressChainLength != 0,"MR_suppressK_client: chain empty"); + + for (i=1 ; i <= suppressChainLength ; i++) { + set_clr(suppressSets[i]); + set_orel( (unsigned) tokensInChain[i], + &suppressSets[i]); + }; + + save_fset=fset; + save_ConstrainSearch=ConstrainSearch; + + fset=suppressSets; + + MR_SuppressSearch=1; + MR_AmbSourceSearch=1; + MR_MaintainBackTrace=1; + ConstrainSearch=1; + + maxk = suppressChainLength; + + incomplete=empty; + t=NULL; + +/*** constrain = &(fset[1]); ***/ + + MR_setConstrainPointer(&(fset[1])); /* MR18 */ + + MR_pointerStackReset(&MR_BackTraceStack); + + TRAV(suppressNode,maxk,&incomplete,t); + + Tfree(t); + + require (set_nil(incomplete),"MR_suppressK_client TRAV incomplete"); + require (MR_BackTraceStack.count == 0, + "MR_suppressK_client: MR_BackTraceStack.count != 0"); + set_free(incomplete); + + ConstrainSearch=save_ConstrainSearch; + fset=save_fset; + + MR_AmbSourceSearch=0; + MR_MaintainBackTrace=0; + MR_SuppressSearch=0; + return suppressSucceeded; +} + +#ifdef __USE_PROTOS +Tree * MR_iterateOverTreeSuppressK(Tree *t,int chain[]) +#else +Tree * MR_iterateOverTreeSuppressK(t,chain) + Tree *t; + int chain[]; +#endif +{ + if (t == NULL) return NULL; + t->right=MR_iterateOverTreeSuppressK(t->right,&chain[0]); + chain[0]=t->token; + if (t->down != NULL) { + t->down=MR_iterateOverTreeSuppressK(t->down,&chain[1]); + if (t->down == NULL) { + Tree *u=t->right; + t->right=NULL; + Tfree(t); + chain[0]=0; + return u; + }; + } else { + MR_suppressK_client(suppressTree,suppressChain); + if (suppressSucceeded) { + Tree *u=t->right; + t->right=NULL; + Tfree(t); + chain[0]=0; + return u; + }; + }; + chain[0]=0; + return t; +} + +/* @@@ */ + +#ifdef __USE_PROTOS +Predicate * MR_suppressK(Node *j,Predicate *p) +#else +Predicate * MR_suppressK(j,p) + Node *j; + Predicate *p; +#endif +{ + Predicate *result; + int guardPred=0; + int ampersandPred=0; + Node *nodePrime; + + if (! MRhoistingk) { + return p; + } + + if (! MRhoisting) return p; + if (CLL_k == 1) return p; + + if (suppressChain == NULL) { + suppressChain=(int *) calloc(CLL_k+2,sizeof(int)); + require (suppressChain != NULL,"MR_suppressK: can't allocate chain"); + } + + if (p == NULL) return NULL; + + if (j->ntype == nJunction) { + nodePrime=(Node *) MR_junctionWithoutP2( (Junction *) j); + } else { + nodePrime=j; + }; + + p->down=MR_suppressK(j,p->down); + p->right=MR_suppressK(j,p->right); + if (p->down != NULL) { + result=p; + goto EXIT; + }; + if (p->k == 1) { + result=p; + goto EXIT; + }; + + if (p->source != NULL) { + if (p->source->guardpred != NULL) guardPred=1; + if (p->source->ampersandPred != NULL) ampersandPred=1; + } + + suppressPredicate=p; + suppressNode=nodePrime; /* was j*/ + + suppressTree=p->tcontext; + + if (guardPred || ampersandPred) { + p->tcontext=MR_iterateOverTreeSuppressK(suppressTree,&suppressChain[1]); + if (p->tcontext == NULL) { + predicate_free(p); + result=NULL; + goto EXIT; + }; + } else { + if (MR_isChain(p->tcontext)) { + p->tcontext=MR_iterateOverTreeSuppressK(suppressTree,&suppressChain[1]); + if (p->tcontext == NULL) { + predicate_free(p); + result=NULL; + goto EXIT; + }; + } + } + result=p; +EXIT: + return result; +} + +#ifdef __USE_PROTOS +void MR_suppressSearchReport(void) +#else +void MR_suppressSearchReport() +#endif +{ + int i; + Node *p; + TokNode *tn; + int depth; + set setAnd; + + /* number of tokens in back trace stack matches length of chain */ + + depth=0; + for (i=0; i < MR_BackTraceStack.count ; i++) { + p=(Node *) MR_BackTraceStack.data[i]; + if (p->ntype == nToken) depth++; + }; + + require (depth == suppressChainLength,"depth > suppressChainLength"); + + /* token codes match chain */ + + depth=0; + for (i=0; i < MR_BackTraceStack.count ; i++) { + p=(Node *) MR_BackTraceStack.data[i]; + if (p->ntype != nToken) continue; + tn=(TokNode *) p; + depth++; + if (set_nil(tn->tset)) { + require(set_el( (unsigned) tn->token,fset[depth]), + "MR_suppressSearchReport: no match to #token in chain"); + } else { + setAnd=set_and(fset[depth],tn->tset); + require(!set_nil(setAnd), + "MR_suppressSearchReport: no match to #token set in chain"); + set_free(setAnd); + }; + }; + + /* have a match - now remove it from the predicate */ + + suppressSucceeded=1; + + if (suppressSucceeded) { + fprintf(output,"\n"); + fprintf(output,"#if 0\n"); + fprintf(output,"\n"); + fprintf(output,"Part (or all) of predicate with depth > 1 suppressed by "); + fprintf(output,"alternative without predicate\n\n"); + MR_dumpPred(suppressPredicate,1); + fprintf(output,"The token sequence which is suppressed:"); + fprintf(output," ("); + for (i=1; i <= suppressChainLength; i++) { + fprintf(output," %s",TerminalString(suppressChain[i])); + }; + fprintf(output," )\n"); + fprintf(output,"The sequence of references which generate that sequence of tokens:\n\n"); + + MR_backTraceDumpItemReset(); + + for (i=0; i < MR_BackTraceStack.count ; i++) { + MR_backTraceDumpItem(output,0,(Node *) MR_BackTraceStack.data[i]); + }; + fprintf(output,"\n"); + fprintf(output,"#endif\n"); + } +} + +#ifdef __USE_PROTOS +void MR_markCompromisedRule(Node *n) +#else +void MR_markCompromisedRule(n) + Node *n; +#endif +{ + RuleEntry *q; + Node *mark=NULL; + Junction *j; + + if (n->ntype == nRuleRef) { + mark=(Node *) MR_ruleReferenced( (RuleRefNode *) n); + } else if (n->ntype == nToken) { + mark=n; + } else if (n->ntype == nJunction) { + j=(Junction *)n; + switch (j->jtype) { + case aOptBlk: + case aLoopBlk: + case RuleBlk: + case EndRule: + case aPlusBlk: + case aLoopBegin: + mark=n; + break; + default: + break; + }; + } + + if (mark == NULL) return; + + require (RulePtr != NULL,"RulePtr not initialized"); + + q = (RuleEntry *) hash_get(Rname,mark->rname); + require (q != NULL,"RuleEntry not found"); + set_orel(q->rulenum,&MR_CompromisedRules); +} + +#ifdef __USE_PROTOS +void MR_alphaBetaTraceReport(void) +#else +void MR_alphaBetaTraceReport() +#endif +{ + int i; + + if (! AlphaBetaTrace) return; + + MR_AlphaBetaMessageCount++; + + fprintf(output,"\n"); + fprintf(output,"#if 0\n"); + fprintf(output,"\n"); + fprintf(output,"Trace of references leading to attempt to compute the follow set of\n"); + fprintf(output,"alpha in an \"(alpha)? beta\" block. It is not possible for antlr to\n"); + fprintf(output,"compute this follow set because it is not known what part of beta has\n"); + fprintf(output,"already been matched by alpha and what part remains to be matched.\n"); + fprintf(output,"\n"); + fprintf(output,"Rules which make use of the incorrect follow set will also be incorrect\n"); + fprintf(output,"\n"); + + MR_backTraceDumpItemReset(); + + for (i=0; i < MR_BackTraceStack.count ; i++) { + MR_backTraceDumpItem(output,0,(Node *) MR_BackTraceStack.data[i]); + if (i < MR_BackTraceStack.count-1) { + MR_markCompromisedRule( (Node *) MR_BackTraceStack.data[i]); + }; + }; + fprintf(output,"\n"); + fprintf(output,"#endif\n"); +} + +#ifdef __USE_PROTOS +void MR_dumpRuleSet(set s) +#else +void MR_dumpRuleSet(s) + set s; +#endif +{ + unsigned *cursor; + unsigned *origin=set_pdq(s); + + require(origin != NULL,"set_pdq failed"); + + if (RulePtr == NULL) { + fprintf(stderr,"RulePtr[] not yet initialized"); + } else { + for (cursor=origin; *cursor != nil ; cursor++) { +/**** if (cursor != origin) fprintf(stderr,","); ****/ + fprintf(stderr," %s",RulePtr[*cursor]->rname); + fprintf(stderr,"\n"); + }; + free( (char *) origin); + }; +} diff --git a/Tools/Source/TianoTools/Pccts/antlr/parser.dlg b/Tools/Source/TianoTools/Pccts/antlr/parser.dlg new file mode 100644 index 0000000000..8c43dff300 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/parser.dlg @@ -0,0 +1,1387 @@ +<< +/* parser.dlg -- DLG Description of scanner + * + * Generated from: antlr.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include "pcctscfg.h" +#include "set.h" +#include +#include "syn.h" +#include "hash.h" +#include "generic.h" +#define zzcr_attr(attr,tok,t) +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +LOOKAHEAD + +void +#ifdef __USE_PROTOS +zzerraction(void) +#else +zzerraction() +#endif +{ + (*zzerr)("invalid token"); + zzadvance(); + zzskip(); +} +>> + +<<%%lexaction + +/* maintained, but not used for now */ +set AST_nodes_refd_in_actions = set_init; +int inAlt = 0; +set attribsRefdFromAction = set_init; /* MR20 */ +int UsedOldStyleAttrib = 0; +int UsedNewStyleLabel = 0; +#ifdef __USE_PROTOS +char *inline_set(char *); +#else +char *inline_set(); +#endif + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ + +int tokenActionActive=0; /* MR1 */ + + +>> + +<<%%lexaction + + +static char * +#ifdef __USE_PROTOS +getFileNameFromTheLineInfo(char *toStr, char *fromStr) +#else +getFileNameFromTheLineInfo(toStr, fromStr) +char *toStr, *fromStr; +#endif +{ + int i, j, k; + + if (!fromStr || !toStr) return toStr; + + /* find the first " */ + + for (i=0; + (i> + +<<%%lexaction + +#ifdef __USE_PROTOS +void mark_label_used_in_sem_pred(LabelEntry *le) /* MR10 */ +#else +void mark_label_used_in_sem_pred(le) /* MR10 */ +LabelEntry *le; +#endif +{ + TokNode *tn; + require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken"); + tn=(TokNode *)le->elem; + require (tn->label != 0,"mark_label_used... TokNode has no label"); + tn->label_used_in_semantic_pred=1; +} +>> + + +%%START + +@ + << + NLA = Eof; + /* L o o k F o r A n o t h e r F i l e */ + { + FILE *new_input; + new_input = NextFile(); + if ( new_input == NULL ) { NLA=Eof; return; } + fclose( input ); + input = new_input; + zzrdstream( input ); + zzskip(); /* Skip the Eof (@) char i.e continue */ + } + >> + +[\t\ ]+ + << + NLA = 76; + zzskip(); + >> + +\n|\r|\r\n + << + NLA = 77; + zzline++; zzskip(); + >> + +\[ + << + NLA = 78; + zzmode(ACTIONS); zzmore(); + istackreset(); + pushint(']'); + >> + +\<\< + << + NLA = 79; + action_file=CurFile; action_line=zzline; + zzmode(ACTIONS); zzmore(); + list_free(&CurActionLabels,0); /* MR10 */ + numericActionLabel=0; /* MR10 */ + istackreset(); + pushint('>'); + >> + +\" + << + NLA = 80; + zzmode(STRINGS); zzmore(); + >> + +/\* + << + NLA = 81; + zzmode(COMMENTS); zzskip(); + >> + +\*/ + << + NLA = 82; + warn("Missing /*; found dangling */"); zzskip(); + >> + +// + << + NLA = 83; + zzmode(CPP_COMMENTS); zzskip(); + >> + +#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n) + << + NLA = 84; + + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + >> + +#line ~[\n\r]* (\n|\r|\r\n) + << + NLA = 85; + + zzline++; zzmore(); + >> + +\>\> + << + NLA = 86; + warn("Missing <<; found dangling \>\>"); zzskip(); + >> + +. + << + NLA = WildCard; + >> + +\@ + << + NLA = 88; + FoundException = 1; /* MR6 */ + FoundAtOperator = 1; + >> + +{\\}#pragma + << + NLA = Pragma; + >> + +{\\}#FirstSetSymbol + << + NLA = FirstSetSymbol; + >> + +{\\}#header + << + NLA = 94; + >> + +{\\}#first + << + NLA = 95; + >> + +{\\}#parser + << + NLA = 96; + >> + +{\\}#tokdefs + << + NLA = 97; + >> + +\} + << + NLA = 98; + >> + +class + << + NLA = 99; + >> + +\{ + << + NLA = 102; + >> + +! + << + NLA = 103; + >> + +\< + << + NLA = 104; + >> + +\> + << + NLA = 105; + >> + +: + << + NLA = 106; + >> + +; + << + NLA = 107; + >> + +{\\}#lexaction + << + NLA = 108; + >> + +{\\}#lexmember + << + NLA = 109; + >> + +{\\}#lexprefix + << + NLA = 110; + >> + +{\\}#pred + << + NLA = 111; + >> + +\|\| + << + NLA = 112; + >> + +&& + << + NLA = 113; + >> + +\( + << + NLA = 114; + >> + +\) + << + NLA = 115; + >> + +{\\}#lexclass + << + NLA = 116; + >> + +{\\}#errclass + << + NLA = 117; + >> + +{\\}#tokclass + << + NLA = 118; + >> + +.. + << + NLA = 119; + >> + +{\\}#token + << + NLA = 120; + >> + += + << + NLA = 121; + >> + +[0-9]+ + << + NLA = 122; + >> + +\| + << + NLA = 123; + >> + +\~ + << + NLA = 124; + >> + +^ + << + NLA = 125; + >> + +approx + << + NLA = 126; + >> + +LL\(1\) + << + NLA = 127; + >> + +LL\(2\) + << + NLA = 128; + >> + +\* + << + NLA = 129; + >> + +\+ + << + NLA = 130; + >> + +? + << + NLA = 131; + >> + +=> + << + NLA = 132; + >> + +exception + << + NLA = 133; + >> + +default + << + NLA = 134; + >> + +catch + << + NLA = 135; + >> + +[a-z] [A-Za-z0-9_]* + << + NLA = NonTerminal; + + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + >> + +[A-Z] [A-Za-z0-9_]* + << + NLA = TokenTerm; + + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + >> + +{\\}#[A-Za-z0-9_]* + << + NLA = 136; + warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); + >> + + +%%STRINGS + +@ + << + NLA = Eof; + >> + +\" + << + NLA = QuotedTerm; + zzmode(START); + >> + +\n|\r|\r\n + << + NLA = 3; + + zzline++; + warn("eoln found in string"); + zzskip(); + >> + +\\(\n|\r|\r\n) + << + NLA = 4; + zzline++; zzmore(); + >> + +\\~[] + << + NLA = 5; + zzmore(); + >> + +~[\n\r\"\\]+ + << + NLA = 6; + zzmore(); + >> + + +%%ACTION_STRINGS + +@ + << + NLA = Eof; + >> + +\" + << + NLA = 7; + zzmode(ACTIONS); zzmore(); + >> + +\n|\r|\r\n + << + NLA = 8; + + zzline++; + warn("eoln found in string (in user action)"); + zzskip(); + >> + +\\(\n|\r|\r\n) + << + NLA = 9; + zzline++; zzmore(); + >> + +\\~[] + << + NLA = 10; + zzmore(); + >> + +~[\n\r\"\\]+ + << + NLA = 11; + zzmore(); + >> + + +%%ACTION_CHARS + +@ + << + NLA = Eof; + >> + +' + << + NLA = 12; + zzmode(ACTIONS); zzmore(); + >> + +\n|\r|\r\n + << + NLA = 13; + + zzline++; + warn("eoln found in char literal (in user action)"); + zzskip(); + >> + +\\~[] + << + NLA = 14; + zzmore(); + >> + +~[\n\r'\\]+ + << + NLA = 15; + zzmore(); + >> + + +%%ACTION_COMMENTS + +@ + << + NLA = Eof; + >> + +\*/ + << + NLA = 16; + zzmode(ACTIONS); zzmore(); + >> + +\* + << + NLA = 17; + zzmore(); + >> + +\n|\r|\r\n + << + NLA = 18; + zzline++; zzmore(); DAWDLE; + >> + +~[\n\r\*]+ + << + NLA = 19; + zzmore(); + >> + + +%%TOK_DEF_COMMENTS + +@ + << + NLA = Eof; + >> + +\*/ + << + NLA = 20; + zzmode(PARSE_ENUM_FILE); + zzmore(); + >> + +\* + << + NLA = 21; + zzmore(); + >> + +\n|\r|\r\n + << + NLA = 22; + zzline++; zzmore(); DAWDLE; + >> + +~[\n\r\*]+ + << + NLA = 23; + zzmore(); + >> + + +%%TOK_DEF_CPP_COMMENTS + +@ + << + NLA = Eof; + >> + +\n|\r|\r\n + << + NLA = 24; + zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; + >> + +~[\n\r]+ + << + NLA = 25; + zzskip(); + >> + + +%%ACTION_CPP_COMMENTS + +@ + << + NLA = Eof; + >> + +\n|\r|\r\n + << + NLA = 26; + zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; + >> + +~[\n\r]+ + << + NLA = 27; + zzmore(); + >> + + +%%CPP_COMMENTS + +@ + << + NLA = Eof; + >> + +\n|\r|\r\n + << + NLA = 28; + zzline++; zzmode(START); zzskip(); DAWDLE; + >> + +~[\n\r]+ + << + NLA = 29; + zzskip(); + >> + + +%%COMMENTS + +@ + << + NLA = Eof; + >> + +\*/ + << + NLA = 30; + zzmode(START); zzskip(); + >> + +\* + << + NLA = 31; + zzskip(); + >> + +\n|\r|\r\n + << + NLA = 32; + zzline++; zzskip(); DAWDLE; + >> + +~[\n\r\*]+ + << + NLA = 33; + zzskip(); + >> + + +%%ACTIONS + +@ + << + NLA = Eof; + >> + +\>\> + << + NLA = Action; + /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = ' '; + zzbegexpr[1] = ' '; + if ( zzbufovf ) { + err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE)); + } + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ + /* MR1 in DLG action */ + /* MR1 Doesn't matter what kind of action it is - reset*/ + + tokenActionActive=0; /* MR1 */ + >> + +\>\>? + << + NLA = Pred; + /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = '\0'; + if ( zzbufovf ) { + err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE)); + }; +#ifdef __cplusplus__ + /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __STDC__ + /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __USE_PROTOS + /* MRxx */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else + /* MR10 */ list_apply(CurActionLabels,mark_label_used_in_sem_pred); +#endif +#endif +#endif + >> + +\] + << + NLA = PassAction; + if ( topint() == ']' ) { + popint(); + if ( istackempty() ) /* terminate action */ + { + zzmode(START); + NLATEXT[0] = ' '; + zzbegexpr[0] = ' '; + if ( zzbufovf ) { + err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE)); + } + } + else { + /* terminate $[..] and #[..] */ + if ( GenCC ) zzreplstr("))"); + else zzreplstr(")"); + zzmore(); + } + } + else if ( topint() == '|' ) { /* end of simple [...] */ + popint(); + zzmore(); + } + else zzmore(); + >> + +consumeUntil\( [\ \t]* \{~[\}]+\} [\ \t]* \) + << + NLA = 37; + + zzmore(); + zzreplstr(inline_set(zzbegexpr+ + strlen("consumeUntil("))); + >> + +consumeUntil\( ~[\)]+ \) + << + NLA = 38; + zzmore(); + >> + +\n|\r|\r\n + << + NLA = 39; + zzline++; zzmore(); DAWDLE; + >> + +\> + << + NLA = 40; + zzmore(); + >> + +$ + << + NLA = 41; + zzmore(); + >> + +$$ + << + NLA = 42; + if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();} + else err("$$ use invalid in C++ mode"); + >> + +$\[\] + << + NLA = 43; + if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();} + else err("$[] use invalid in C++ mode"); + >> + +$\[ + << + NLA = 44; + + pushint(']'); + if ( !GenCC ) zzreplstr("zzconstr_attr("); + else err("$[..] use invalid in C++ mode"); + zzmore(); + >> + +$[0-9]+ + << + NLA = 45; + { + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i attrib ref too big"); + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> + +$[0-9]+. + << + NLA = 46; + { + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i.field attrib ref too big"); + zzbegexpr[strlen(zzbegexpr)-1] = ' '; + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s.", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> + +$[0-9]+.[0-9]+ + << + NLA = 47; + { + static char buf[100]; + static char i[20], j[20]; + char *p,*q; + numericActionLabel=1; /* MR10 */ + if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big"); + for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) { + if ( q == &i[20] ) + fatalFL("i of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + for (p++, q= &j[0]; *p!='\0'; p++) { + if ( q == &j[20] ) + fatalFL("j of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j); + else sprintf(buf,"_t%s%s",i,j); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> + +$[_a-zA-Z][_a-zA-Z0-9]* + << + NLA = 48; + { static char buf[300]; LabelEntry *el; + zzbegexpr[0] = ' '; + if ( CurRule != NULL && + strcmp(CurRule, &zzbegexpr[1])==0 ) { + if ( !GenCC ) zzreplstr("zzaRet"); + } + else if ( CurRetDef != NULL && + strmember(CurRetDef, &zzbegexpr[1])) { + if ( hasMultipleOperands( CurRetDef ) ) { + require (strlen(zzbegexpr)<=(size_t)285, + "$retval attrib ref too big"); + sprintf(buf,"_retv.%s",&zzbegexpr[1]); + zzreplstr(buf); + } + else zzreplstr("_retv"); + } + else if ( CurParmDef != NULL && + strmember(CurParmDef, &zzbegexpr[1])) { + ; + } + else if ( Elabel==NULL ) { + { err("$-variables in actions outside of rules are not allowed"); } + } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) { + /* MR10 */ + /* MR10 */ /* element labels might exist without an elem when */ + /* MR10 */ /* it is a forward reference (to a rule) */ + /* MR10 */ + /* MR10 */ if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) ) + /* MR10 */ { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); } + /* MR10 */ + /* MR10 */ if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) { + /* MR10 */ err("You can no longer use attributes returned by rules when also using ASTs"); + /* MR10 */ err(" Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...\>\>\")"); + /* MR10 */ }; + /* MR10 */ + /* MR10 */ /* keep track of <<... $label ...>> for semantic predicates in guess mode */ + /* MR10 */ /* element labels contain pointer to the owners node */ + /* MR10 */ + /* MR10 */ if (el->elem != NULL && el->elem->ntype == nToken) { + /* MR10 */ list_add(&CurActionLabels,el); + /* MR10 */ }; +} +else +warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1])); +} +zzmore(); + >> + +#0 + << + NLA = 49; + zzreplstr("(*_root)"); zzmore(); chkGTFlag(); + >> + +#\[\] + << + NLA = 50; + if ( GenCC ) { + if (NewAST) zzreplstr("(newAST)"); + else zzreplstr("(new AST)");} + else {zzreplstr("zzastnew()");} zzmore(); + chkGTFlag(); + >> + +#\(\) + << + NLA = 51; + zzreplstr("NULL"); zzmore(); chkGTFlag(); + >> + +#[0-9]+ + << + NLA = 52; + { + static char buf[100]; + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("#i AST ref too big"); + if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"zzastArg(%s)",zzbegexpr+1); + zzreplstr(buf); + zzmore(); + set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions); + chkGTFlag(); + } + >> + +#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n) + << + NLA = 53; + + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + >> + +#line ~[\n\r]* (\n|\r|\r\n) + << + NLA = 54; + + zzline++; zzmore(); + >> + +#[_a-zA-Z][_a-zA-Z0-9]* + << + NLA = 55; + + if ( !(strcmp(zzbegexpr, "#ifdef")==0 || + strcmp(zzbegexpr, "#if")==0 || + strcmp(zzbegexpr, "#else")==0 || + strcmp(zzbegexpr, "#endif")==0 || + strcmp(zzbegexpr, "#ifndef")==0 || + strcmp(zzbegexpr, "#define")==0 || + strcmp(zzbegexpr, "#pragma")==0 || + strcmp(zzbegexpr, "#undef")==0 || + strcmp(zzbegexpr, "#import")==0 || + strcmp(zzbegexpr, "#line")==0 || + strcmp(zzbegexpr, "#include")==0 || + strcmp(zzbegexpr, "#error")==0) ) + { + static char buf[100]; + sprintf(buf, "%s_ast", zzbegexpr+1); + /* MR27 */ list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1)); + zzreplstr(buf); + chkGTFlag(); + } + zzmore(); + >> + +#\[ + << + NLA = 56; + + pushint(']'); + if ( GenCC ) { + if (NewAST) zzreplstr("(newAST("); + else zzreplstr("(new AST("); } + else zzreplstr("zzmk_ast(zzastnew(),"); + zzmore(); + chkGTFlag(); + >> + +#\( + << + NLA = 57; + + pushint('}'); + if ( GenCC ) { + if (tmakeInParser) { + zzreplstr("tmake("); + } + else { + zzreplstr("ASTBase::tmake("); + } + } + else { + zzreplstr("zztmake("); + } + zzmore(); + chkGTFlag(); + >> + +# + << + NLA = 58; + zzmore(); + >> + +\) + << + NLA = 59; + + if ( istackempty() ) + zzmore(); + else if ( topint()==')' ) { + popint(); + } + else if ( topint()=='}' ) { + popint(); + /* terminate #(..) */ + zzreplstr(", NULL)"); + } + zzmore(); + >> + +\[ + << + NLA = 60; + + pushint('|'); /* look for '|' to terminate simple [...] */ + zzmore(); + >> + +\( + << + NLA = 61; + + pushint(')'); + zzmore(); + >> + +\\\] + << + NLA = 62; + zzreplstr("]"); zzmore(); + >> + +\\\) + << + NLA = 63; + zzreplstr(")"); zzmore(); + >> + +\\> + << + NLA = 64; + if (! tokenActionActive) zzreplstr(">"); /* MR1 */ + zzmore(); /* MR1 */ + >> + +' + << + NLA = 65; + zzmode(ACTION_CHARS); zzmore(); + >> + +\" + << + NLA = 66; + zzmode(ACTION_STRINGS); zzmore(); + >> + +\\$ + << + NLA = 67; + zzreplstr("$"); zzmore(); + >> + +\\# + << + NLA = 68; + zzreplstr("#"); zzmore(); + >> + +\\(\n|\r|\r\n) + << + NLA = 69; + zzline++; zzmore(); + >> + +\\~[\]\)>$#] + << + NLA = 70; + zzmore(); + >> + +/ + << + NLA = 71; + zzmore(); + >> + +/\* + << + NLA = 72; + zzmode(ACTION_COMMENTS); zzmore(); + >> + +\*/ + << + NLA = 73; + warn("Missing /*; found dangling */ in action"); zzmore(); + >> + +// + << + NLA = 74; + zzmode(ACTION_CPP_COMMENTS); zzmore(); + >> + +~[\n\r\)\(\\$#\>\]\[\"'/]+ + << + NLA = 75; + zzmore(); + >> + + +%%PARSE_ENUM_FILE + +@ + << + NLA = Eof; + ; + >> + +[\t\ ]+ + << + NLA = 137; + zzskip(); + >> + +\n|\r|\r\n + << + NLA = 138; + zzline++; zzskip(); + >> + +// + << + NLA = 139; + zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); + >> + +/\* + << + NLA = 140; + zzmode(TOK_DEF_COMMENTS); zzskip(); + >> + +#ifdef + << + NLA = 141; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#if + << + NLA = 142; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#ifndef + << + NLA = 143; + ; + >> + +#else + << + NLA = 144; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#endif + << + NLA = 145; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#undef + << + NLA = 146; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#import + << + NLA = 147; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#define + << + NLA = 149; + >> + +enum + << + NLA = 151; + >> + +\{ + << + NLA = 152; + >> + += + << + NLA = 153; + >> + +, + << + NLA = 154; + >> + +\} + << + NLA = 155; + >> + +; + << + NLA = 156; + >> + +[0-9]+ + << + NLA = INT; + >> + +[a-zA-Z_][_a-zA-Z0-9]* + << + NLA = ID; + >> + +%% diff --git a/Tools/Source/TianoTools/Pccts/antlr/pred.c b/Tools/Source/TianoTools/Pccts/antlr/pred.c new file mode 100644 index 0000000000..eb11c4d950 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/pred.c @@ -0,0 +1,821 @@ +/* + * pred.c -- source for predicate detection, manipulation + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include + +#ifdef __USE_PROTOS +static void complete_context_sets(RuleRefNode *, Predicate *); +static void complete_context_trees(RuleRefNode *, Predicate *); +#else +static void complete_context_sets(); +static void complete_context_trees(); +#endif + +char *PRED_AND_LIST = "AND"; +char *PRED_OR_LIST = "OR"; + +/* + * In C mode, return the largest constant integer found as the + * sole argument to LATEXT(i). + * + * In C++ mode, return the largest constant integer found as the + * sole argument to LT(i) given that the char before is nonalpha. + */ + +int +#ifdef __USE_PROTOS +predicateLookaheadDepth(ActionNode *a) +#else +predicateLookaheadDepth(a) +ActionNode *a; +#endif +{ + int max_k=0; + + if (a->predEntry != NULL) { + MR_pred_depth(a->predEntry->pred,&max_k); + goto PREDENTRY_EXIT; + } + + if ( GenCC ) + { + /* scan for LT(i) */ + int k = 0; + char *p = a->action; + while ( p!=NULL ) + { + p = strstr(p, "LT("); + if ( p!=NULL ) + { + if ( p>=a->action && !isalpha(*(p-1)) ) + { + k = atoi(p+strlen("LT(")); + if ( k>max_k ) max_k=k; + } + p += strlen("LT("); + } + } + } + else { + /* scan for LATEXT(i) */ + int k = 0; + char *p = a->action; + while ( p!=NULL ) + { + p = strstr(p, "LATEXT("); + if ( p!=NULL ) + { + p += strlen("LATEXT("); + k = atoi(p); + if ( k>max_k ) max_k=k; + } + } + } + + if (max_k==0) { + max_k = 1; /* MR33 Badly designed if didn't set max_k when CLL_k = 1 */ + if (CLL_k > 1) /* MR27 Don't warn if max(k,ck) == 1 */ + { + if ( !a->frmwarned ) + { + a->frmwarned = 1; + warnFL(eMsg1("predicate: %s missing, bad, or with i=0; assuming i=1", + GenCC?"LT(i)":"LATEXT(i)"), + FileStr[a->file], a->line); + } + } + } + +/* MR10 */ if ( max_k > CLL_k) { +/* MR10 */ if ( !a->frmwarned ) +/* MR10 */ { +/* MR10 */ a->frmwarned = 1; +/* MR11 */ errFL(eMsgd2("predicate refers to lookahead token %d. Semantic lookahead is limited to max(k,ck)==%d", +/* MR10 */ max_k,CLL_k), +/* MR10 */ FileStr[a->file],a->line); +/* MR10 */ if (max_k >= OutputLL_k) { +/* MR10 */ if (!GenCC) { +/* MR10 */ errFL(eMsgd(" the lookahead buffer size in C mode is %d token(s) (including the one just recognized)", +/* MR10 */ OutputLL_k), +/* MR10 */ FileStr[a->file],a->line); +/* MR10 */ }; +/* MR10 */ }; +/* MR10 */ }; +/* MR10 */ max_k= CLL_k; +/* MR10 */ }; + +PREDENTRY_EXIT: + return max_k; +} + +/* Find all predicates in a block of alternatives. DO NOT find predicates + * behind the block because that predicate could depend on things set in + * one of the nonoptional blocks + */ + +Predicate * +#ifdef __USE_PROTOS +find_in_aSubBlk( Junction *alt ) +#else +find_in_aSubBlk( alt ) +Junction *alt; +#endif +{ + Predicate *a, *head=NULL, *tail=NULL, *root=NULL; + Junction *p = alt; + + if (MRhoisting) { + return MR_find_in_aSubBlk(alt); + }; + for (; p!=NULL; p=(Junction *)p->p2) + { + /* ignore empty alts */ + if ( p->p1->ntype != nJunction || + ((Junction *)p->p1)->jtype != EndBlk ) + { + a = find_predicates(p->p1); /* get preds for this alt */ + if ( a==NULL ) continue; + + /* make an OR list of predicates */ + if ( head==NULL ) + { + root = new_pred(); + root->expr = PRED_OR_LIST; + head = tail = a; + root->down = head; + } + else { + tail->right = a; + a->left = tail; + a->up = tail->up; + tail = a; + } + } + } + + /* if just one pred, remove OR root */ + if ( root!=NULL && root->down->right == NULL ) + { + Predicate *d = root->down; + free( (char *) root); + return d; + } + + return root; +} + +Predicate * +#ifdef __USE_PROTOS +find_in_aOptBlk( Junction *alt ) +#else +find_in_aOptBlk( alt ) +Junction *alt; +#endif +{ + return find_in_aSubBlk( alt ); +} + +Predicate * +#ifdef __USE_PROTOS +find_in_aLoopBegin( Junction *alt ) +#else +find_in_aLoopBegin( alt ) +Junction *alt; +#endif +{ + return find_in_aSubBlk( (Junction *) alt->p1 ); /* get preds in alts */ +} + +Predicate * +#ifdef __USE_PROTOS +find_in_aPlusBlk( Junction *alt ) +#else +find_in_aPlusBlk( alt ) +Junction *alt; +#endif +{ + require(alt!=NULL&&alt->p2!=NULL, "invalid aPlusBlk"); + return find_in_aSubBlk( alt ); +} + +/* Look for a predicate; + * + * Do not pass anything but Junction nodes; no Actions, Tokens, RuleRefs. + * This means that a "hoisting distance" of zero is the only distance + * allowable. Init actions are ignored. + * + * WARNING: + * Assumes no (..)? block after predicate for the moment. + * Does not check to see if pred is in production that can generate + * a sequence contained in the set of ambiguous tuples. + * + * Return the predicate found if any. + */ + + +Predicate * +#ifdef __USE_PROTOS +find_predicates( Node *alt ) +#else +find_predicates( alt ) +Node *alt; +#endif +{ +#ifdef DBG_PRED + Junction *j; + RuleRefNode *r; + TokNode *t; +#endif + Predicate *pred; + + if ( alt==NULL ) return NULL; + +#ifdef DBG_PRED + switch ( alt->ntype ) + { + case nJunction : + j = (Junction *) alt; + fprintf(stderr, "Junction(in %s)", j->rname); + switch ( j->jtype ) + { + case aSubBlk : + fprintf(stderr,"aSubBlk\n"); + break; + case aOptBlk : + fprintf(stderr,"aOptBlk\n"); + break; + case aLoopBegin : + fprintf(stderr,"aLoopBeginBlk\n"); + break; + case aLoopBlk : + fprintf(stderr,"aLoopBlk\n"); + break; + case aPlusBlk : + fprintf(stderr,"aPlusBlk\n"); + break; + case EndBlk : + fprintf(stderr,"EndBlk\n"); + break; + case RuleBlk : + fprintf(stderr,"RuleBlk\n"); + break; + case Generic : + fprintf(stderr,"Generic\n"); + break; + case EndRule : + fprintf(stderr,"EndRule\n"); + break; + } + break; + case nRuleRef : + r = (RuleRefNode *) alt; + fprintf(stderr, "RuleRef(in %s)\n", r->rname); + break; + case nToken : + t = (TokNode *) alt; + fprintf(stderr, "TokenNode(in %s)%s\n", t->rname, TokenString(t->token)); + break; + case nAction : + fprintf(stderr, "Action\n"); + break; + } +#endif + + switch ( alt->ntype ) + { + case nJunction : + { + Predicate *a, *b; + Junction *p = (Junction *) alt; + + /* lock nodes */ + if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || + p->jtype==aPlusBlk || p->jtype==EndRule ) + { + require(p->pred_lock!=NULL, "rJunc: lock array is NULL"); + if ( p->pred_lock[1] ) + { + return NULL; + } + p->pred_lock[1] = TRUE; + } + + switch ( p->jtype ) + { + case aSubBlk : + a = find_in_aSubBlk(p); + return a; /* nothing is visible past this guy */ + case aOptBlk : + a = find_in_aOptBlk(p); + return a; + case aLoopBegin : + a = find_in_aLoopBegin(p); + return a; + case aLoopBlk : + a = find_in_aSubBlk(p); + p->pred_lock[1] = FALSE; + return a; + case aPlusBlk : + a = find_in_aPlusBlk(p); + p->pred_lock[1] = FALSE; + return a; /* nothing is visible past this guy */ + case RuleBlk : + a = find_predicates(p->p1); + p->pred_lock[1] = FALSE; + return a; + case Generic : + a = find_predicates(p->p1); + b = find_predicates(p->p2); + if ( p->pred_lock!=NULL ) p->pred_lock[1] = FALSE; + if ( a==NULL ) return b; + if ( b==NULL ) return a; + /* otherwise OR the two preds together */ + { + fatal_internal("hit unknown situation during predicate hoisting"); + } + case EndBlk : + case EndRule : /* Find no predicates after a rule ref */ + return NULL; + default: + fatal_internal("this cannot be printed\n"); + break; + } + } + case nAction : + { + ActionNode *p = (ActionNode *) alt; + if ( p->noHoist) return NULL; /* MR12c */ + if ( p->init_action ) return find_predicates(p->next); + if ( p->is_predicate ) + { + Tree *t=NULL; +#ifdef DBG_PRED + fprintf(stderr, "predicate: <<%s>>?\n", p->action); +#endif + if ( p->guardpred!=NULL ) + { + pred = predicate_dup(p->guardpred); + MR_guardPred_plainSet(p,pred); /* MR12c */ + } + else + { + pred = new_pred(); + pred->k = predicateLookaheadDepth(p); + pred->source = p; + pred->expr = p->action; + if ( HoistPredicateContext && pred->k > 1 ) + { + /* MR30 No need to use first_item_is_guess_block_extra + since we know this is an action, not a (...)* or + (...)+ block. + */ + + if ( first_item_is_guess_block((Junction *)p->next) ) + { + warnFL("cannot compute context of predicate in front of (..)? block", + FileStr[p->file], p->line); + } + else + { + ConstrainSearch = 0; +/* MR11 */ if (p->ampersandPred != NULL) { +/* MR11 */ TRAV(p, +/* MR11 */ pred->k, +/* MR11 */ &(pred->completionTree), t); +/* MR11 */ } else { + TRAV(p->next, + pred->k, + &(pred->completionTree), t); + }; + pred->tcontext = t; + MR_check_pred_too_long(pred,pred->completionTree); +#ifdef DBG_PRED + fprintf(stderr, "LL(%d) context:", pred->k); + preorder(t); + fprintf(stderr, "\n"); +#endif + } + } + else if ( HoistPredicateContext && pred->k == 1 ) + { + pred->scontext[1] = empty; + /* MR30 No need to use first_item_is_guess_block_extra + since we know this is an action. + */ + if ( first_item_is_guess_block((Junction *)p->next) ) + { + warnFL("cannot compute context of predicate in front of (..)? block", + FileStr[p->file], p->line); + } + else + { + REACH((Junction *)p->next, + 1, + &(pred->completionSet), + pred->scontext[1]); + MR_check_pred_too_long(pred,pred->completionSet); +#ifdef DBG_PRED + fprintf(stderr, "LL(1) context:"); + s_fprT(stderr, pred->scontext[1]); + fprintf(stderr, "\n"); +#endif + } + } + } + { + Predicate *d = find_predicates(p->next); + Predicate *root; + +/* Warning: Doesn't seem like the up pointers will all be set correctly; + * TJP: that's ok, we're not using them now. + */ + if ( d!=NULL ) + { + root = new_pred(); + root->expr = PRED_AND_LIST; + root->down = pred; + pred->right = d; + pred->up = root; + d->left = pred; + d->up = pred->up; + return root; + } + } + return pred; + } + return NULL; + } + case nRuleRef : + { + Predicate *a; + RuleRefNode *p = (RuleRefNode *) alt; + Junction *r; + Junction *save_MR_RuleBlkWithHalt; + + RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text); + if ( q == NULL ) + { + warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line ); + return NULL; + } + r = RulePtr[q->rulenum]; + if ( r->pred_lock[1] ) + { + /* infinite left-recursion; ignore 'cause LL sup 1 (k) analysis + * must have seen it earlier. + */ + return NULL; + } + + /* MR10 There should only be one halt set at a time. */ + /* MR10 Life would have been easier with a global variable */ + /* MR10 (at least for this particular need) */ + /* MR10 Unset the old one and set the new one, later undo. */ + + require(r->end->halt == FALSE,"should only have one halt at a time"); + +/* MR10 */ require(MR_RuleBlkWithHalt == NULL || +/* MR10 */ (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE), +/* MR10 */ "RuleBlkWithHalt->end not RuleBlk or does not have halt set"); +/* MR10 */ if (MR_RuleBlkWithHalt != NULL) { +/* MR10 */ MR_RuleBlkWithHalt->end->halt=FALSE; +/* MR10 */ }; + +/*** fprintf(stderr,"\nSetting halt on junction #%d\n",r->end->seq); ***/ + + require(r->end->halt == FALSE,"rule->end->halt already set"); + + save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt; + +/* MR10 */ MR_pointerStackPush(&MR_RuleBlkWithHaltStack,MR_RuleBlkWithHalt); +/* MR10 */ MR_pointerStackPush(&MR_PredRuleRefStack,p); + + r->end->halt = TRUE; +/* MR10 */ MR_RuleBlkWithHalt=r; + + a = find_predicates((Node *)r); + + require(r->end->halt == TRUE,"rule->end->halt not set"); + r->end->halt = FALSE; + +/* MR10 */ MR_pointerStackPop(&MR_PredRuleRefStack); +/* MR10 */ MR_RuleBlkWithHalt=(Junction *) MR_pointerStackPop(&MR_RuleBlkWithHaltStack); + + require (MR_RuleBlkWithHalt==save_MR_RuleBlkWithHalt, + "RuleBlkWithHaltStack not consistent"); + +/* MR10 */ require(MR_RuleBlkWithHalt == NULL || +/* MR10 */ (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == FALSE), +/* MR10 */ "RuleBlkWithHalt->end not RuleBlk or has no halt set"); +/* MR10 */ if (MR_RuleBlkWithHalt != NULL) { +/* MR10 */ MR_RuleBlkWithHalt->end->halt=TRUE; +/* MR10 */ }; + +/*** fprintf(stderr,"\nRestoring halt on junction #%d\n",r->end->seq); ***/ + + if ( a==NULL ) return NULL; + + /* attempt to compute the "local" FOLLOW just like in normal lookahead + * computation if needed + */ + + complete_context_sets(p,a); + complete_context_trees(p,a); + +/* MR10 */ MR_cleanup_pred_trees(a); + + return a; + } + case nToken : + break; + } + + return NULL; +} + +#ifdef __USE_PROTOS +Predicate *MR_find_predicates_and_supp(Node *alt) +#else +Predicate *MR_find_predicates_and_supp(alt) + Node *alt; +#endif +{ + Predicate *p; + + p=find_predicates(alt); + p=MR_suppressK(alt,p); + return p; +} + +Predicate * +#ifdef __USE_PROTOS +new_pred( void ) +#else +new_pred( ) +#endif +{ + Predicate *p = (Predicate *) calloc(1,sizeof(Predicate)); /* MR10 */ + require(p!=NULL, "new_pred: cannot alloc predicate"); + p->scontext[0]=empty; + p->scontext[1]=empty; + p->completionTree=empty; + p->completionSet=empty; + p->plainSet=empty; + return p; +} + +static void +#ifdef __USE_PROTOS +complete_context_sets( RuleRefNode *p, Predicate *a ) +#else +complete_context_sets( p, a ) +RuleRefNode *p; +Predicate *a; +#endif +{ + set rk2, b; + int k2; + +#ifdef DBG_PRED + fprintf(stderr, "enter complete_context_sets\n"); +#endif + for (; a!=NULL; a=a->right) + { + if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST ) + { + complete_context_sets(p,a->down); + continue; + } + rk2 = b = empty; + while ( !set_nil(a->completionSet) ) + { + k2 = set_int(a->completionSet); + set_rm(k2, a->completionSet); + + REACH(p->next, k2, &rk2, b); + set_orin(&(a->scontext[1]), b); + set_free(b); + } + + set_orin(&(a->completionSet), rk2);/* remember what we couldn't do */ + set_free(rk2); +#ifdef DBG_PRED + fprintf(stderr, "LL(1) context for %s(addr 0x%x) after ruleref:", a->expr, a); + s_fprT(stderr, a->scontext[1]); + fprintf(stderr, "\n"); +#endif +/* complete_context_sets(p, a->down);*/ + } +#ifdef DBG_PRED + fprintf(stderr, "exit complete_context_sets\n"); +#endif +} + +static void +#ifdef __USE_PROTOS +complete_context_trees( RuleRefNode *p, Predicate *a ) +#else +complete_context_trees( p, a ) +RuleRefNode *p; +Predicate *a; +#endif +{ + set rk2; + int k2; + Tree *u; + +#ifdef DBG_PRED + fprintf(stderr, "enter complete_context_trees\n"); +#endif + for (; a!=NULL; a=a->right) + { + if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST ) + { + complete_context_trees(p, a->down); + continue; + } + rk2 = empty; + + /* any k left to do? if so, link onto tree */ + while ( !set_nil(a->completionTree) ) + { + k2 = set_int(a->completionTree); + set_rm(k2, a->completionTree); + u = NULL; + + TRAV(p->next, k2, &rk2, u); + + /* any subtrees missing k2 tokens, add u onto end */ + a->tcontext = tlink(a->tcontext, u, k2); + Tfree(u); /* MR10 */ + } + set_orin(&(a->completionTree), rk2);/* remember what we couldn't do */ + set_free(rk2); +#ifdef DBG_PRED + fprintf(stderr, "LL(i<%d) context after ruleref:", LL_k); + preorder(a->tcontext); + fprintf(stderr, "\n"); +#endif +/* complete_context_trees(p, a->down);*/ + } +#ifdef DBG_PRED + fprintf(stderr, "exit complete_context_trees\n"); +#endif +} + +/* Walk a list of predicates and return the set of all tokens in scontext[1]'s */ +set +#ifdef __USE_PROTOS +covered_set( Predicate *p ) +#else +covered_set( p ) +Predicate *p; +#endif +{ + set a; + + a = empty; + for (; p!=NULL; p=p->right) + { + if ( p->expr == PRED_AND_LIST || p->expr == PRED_OR_LIST ) + { + set_orin(&a, covered_set(p->down)); + continue; + } + set_orin(&a, p->scontext[1]); + set_orin(&a, covered_set(p->down)); + } + return a; +} + +/* MR10 predicate_free() + MR10 Don't free the leaf nodes since they are part of the action node +*/ + +#ifdef __USE_PROTOS +void predicate_free(Predicate *p) +#else +void predicate_free(p) + Predicate *p; +#endif +{ + if (p == NULL) return; + predicate_free(p->right); + predicate_free(p->down); + if (p->cloned || + p->source == NULL || + p->source->guardpred == NULL || + p->expr == PRED_AND_LIST || + p->expr == PRED_OR_LIST) { + set_free(p->scontext[1]); + set_free(p->completionSet); + set_free(p->completionTree); + set_free(p->plainSet); + Tfree(p->tcontext); + free( (char *) p); + } else { + p->right=NULL; + p->down=NULL; /* MR13 *** debug */ + }; +} + +/* MR10 predicate_dup() */ + +#ifdef __USE_PROTOS +Predicate * predicate_dup_xxx(Predicate *p,int contextToo) +#else +Predicate * predicate_dup_xxx(p,contextToo) + Predicate *p; + int contextToo; +#endif +{ + Predicate *q; + + if (p == NULL) return NULL; + q=new_pred(); + q->down=predicate_dup(p->down); + q->right=predicate_dup(p->right); + + /* + don't replicate expr - it is read-only + and address comparison is used to look + for identical predicates. + */ + + q->expr=p->expr; + q->k=p->k; + q->source=p->source; + q->cloned=1; + q->ampersandStyle=p->ampersandStyle; + q->inverted=p->inverted; + q->predEntry=p->predEntry; + q->plainSet=set_dup(p->plainSet); + + if (contextToo) { + q->tcontext=tdup(p->tcontext); + q->scontext[0]=set_dup(p->scontext[0]); + q->scontext[1]=set_dup(p->scontext[1]); + q->completionTree=set_dup(p->completionTree); + q->completionSet=set_dup(p->completionSet); + }; + + /* don't need to dup "redundant" */ + + return q; + +} + +#ifdef __USE_PROTOS +Predicate * predicate_dup_without_context(Predicate *p) +#else +Predicate * predicate_dup_without_context(p) + Predicate *p; +#endif +{ + return predicate_dup_xxx(p,0); +} + +#ifdef __USE_PROTOS +Predicate * predicate_dup(Predicate *p) +#else +Predicate * predicate_dup(p) + Predicate *p; +#endif +{ + return predicate_dup_xxx(p,1); +} + diff --git a/Tools/Source/TianoTools/Pccts/antlr/proto.h b/Tools/Source/TianoTools/Pccts/antlr/proto.h new file mode 100644 index 0000000000..53035e720e --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/proto.h @@ -0,0 +1,852 @@ +/* + * proto.h -- function prototypes + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + + /* V a r i a b l e s */ + +extern int tp; +extern Junction *SynDiag; +extern char Version[]; +extern char VersionDef[]; +#ifdef __cplusplus +extern void (*fpPrint[])(...); +#else +extern void (*fpPrint[])(); +#endif +#ifdef __cplusplus +extern struct _set (*fpReach[])(...); +#else +extern struct _set (*fpReach[])(); +#endif +#ifdef __cplusplus +extern struct _tree *(*fpTraverse[])(...); +#else +extern struct _tree *(*fpTraverse[])(); +#endif +#ifdef __cplusplus +extern void (**fpTrans)(...); +#else +extern void (**fpTrans)(); +#endif +#ifdef __cplusplus +extern void (**fpJTrans)(...); +#else +extern void (**fpJTrans)(); +#endif +#ifdef __cplusplus +extern void (*C_Trans[NumNodeTypes+1])(...); +#else +extern void (*C_Trans[])(); +#endif +#ifdef __cplusplus +extern void (*C_JTrans[NumJuncTypes+1])(...); +#else +extern void (*C_JTrans[])(); +#endif +extern int BlkLevel; +extern int CurFile; +extern char *CurPredName; +extern char *CurRule; +extern int CurRuleDebug; /* MR13 */ +extern Junction *CurRuleBlk; +extern RuleEntry *CurRuleNode; +extern ListNode *CurElementLabels; +extern ListNode *CurAstLabelsInActions; /* MR27 */ +extern ListNode *ContextGuardPredicateList; /* MR13 */ +extern ListNode *CurActionLabels; +extern int numericActionLabel; /* MR10 << ... $1 ... >> or << ... $1 ... >>? */ +extern ListNode *NumericPredLabels; /* MR10 << ... $1 ... >>? ONLY */ +extern char *FileStr[]; +extern int NumFiles; +extern int EpToken; +extern int WildCardToken; +extern Entry **Tname, + **Texpr, + **Rname, + **Fcache, + **Tcache, + **Elabel, + **Sname, + **Pname; /* MR11 */ +extern ListNode *ExprOrder; +extern ListNode **Cycles; +extern int TokenNum; +extern int LastTokenCounted; +extern ListNode *BeforeActions, *AfterActions, *LexActions; + +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via #lexmember <<....>> & #lexprefix <<...>> */ +/* MR1 */ + +extern ListNode *LexMemberActions; /* MR1 */ +extern ListNode *LexPrefixActions; /* MR1 */ + +extern set *fset; /* for constrained search */ /* MR11 */ +extern int maxk; /* for constrained search */ /* MR11 */ +extern int Save_argc; /* MR10 */ +extern char **Save_argv; /* MR10 */ +extern ListNode *eclasses, *tclasses; +extern char *HdrAction; +extern char *FirstAction; /* MR11 */ +extern FILE *ErrFile; +extern char *RemapFileName; +extern char *ErrFileName; +extern char *DlgFileName; +extern char *DefFileName; +extern char *ModeFileName; +extern char *StdMsgName; +extern int NumRules; +extern Junction **RulePtr; +extern int LL_k; +extern int CLL_k; +extern char *decodeJType[]; +extern int PrintOut; +extern int PrintAnnotate; +extern int CodeGen; +extern int LexGen; +extern int esetnum; +extern int setnum; +extern int wordnum; +extern int GenAST; +extern int GenANSI; +extern int **FoStack; +extern int **FoTOS; +extern int GenExprSetsOpt; +extern FILE *DefFile; +extern int CannotContinue; +extern int GenCR; +extern int GenLineInfo; +extern int GenLineInfoMS; +extern int action_file, action_line; +extern int TraceGen; +extern int CurAmbigAlt1, CurAmbigAlt2, CurAmbigline, CurAmbigfile; +extern char *CurAmbigbtype; +extern int elevel; +extern int GenEClasseForRules; +extern FILE *input, *output; +extern char **TokenStr, **ExprStr; +extern int CurrentLexClass, NumLexClasses; +extern LClass lclass[]; +extern char LexStartSymbol[]; +extern char *CurRetDef; +extern char *CurParmDef; +extern int OutputLL_k; +extern int TreeResourceLimit; +extern int DemandLookahead; +extern char *RulePrefix; +extern int GenStdPccts; +extern char *stdpccts; +extern int ParseWithPredicates; +extern int ConstrainSearch; +extern int PURIFY; /* MR23 */ + +extern set MR_CompromisedRules; /* MR14 */ +extern int MR_AmbSourceSearch; /* MR11 */ +extern int MR_SuppressSearch; /* MR13 */ +extern int MR_AmbSourceSearchGroup; /* MR11 */ +extern int MR_AmbSourceSearchChoice; /* MR11 */ +extern int MR_AmbSourceSearchLimit; /* MR11 */ +extern int MR_usingPredNames; /* MR11 */ +extern int MR_ErrorSetComputationActive; /* MR14 */ +extern char *MR_AmbAidRule; /* MR11 */ +extern int MR_AmbAidLine; /* MR11 */ +extern int MR_AmbAidMultiple; /* MR11 */ +extern int MR_AmbAidDepth; /* MR11 */ +extern int MR_skipped_e3_report; /* MR11 */ +extern int MR_matched_AmbAidRule; /* MR11 */ +extern int MR_Inhibit_Tokens_h_Gen; /* MR13 */ +extern int NewAST; /* MR13 */ +extern int tmakeInParser; /* MR23 */ +extern int AlphaBetaTrace; /* MR14 */ +extern int MR_BlkErr; /* MR21 */ +extern int MR_AlphaBetaWarning; /* MR14 */ +extern int MR_AlphaBetaMessageCount; /* MR14 */ +extern int MR_MaintainBackTrace; /* MR14 */ +extern int MR_BadExprSets; /* MR13 */ +extern int FoundGuessBlk; +extern int FoundException; +extern int FoundAtOperator; /* MR6 */ +extern int FoundExceptionGroup; /* MR6 */ +extern int WarningLevel; +extern int UseStdout; /* MR6 */ +extern int TabWidth; /* MR6 */ +extern int pLevel; +extern int pAlt1; +extern int pAlt2; +extern int AImode; +extern int HoistPredicateContext; +extern int MRhoisting; /* MR9 */ +extern int MRhoistingk; /* MR13 */ +extern int MR_debugGenRule; /* MR11 */ +extern int GenCC; +extern char *ParserName; +extern char *StandardSymbols[]; +extern char *ASTSymbols[]; +extern set reserved_positions; +extern set all_tokens; +extern set imag_tokens; +extern set tokclasses; +extern ListNode *ForcedTokens; +extern int *TokenInd; +extern FILE *Parser_h, *Parser_c; +extern char CurrentClassName[]; +extern int no_classes_found; +extern char Parser_h_Name[]; +extern char Parser_c_Name[]; +extern char MRinfoFile_Name[]; /* MR10 */ +extern FILE *MRinfoFile; /* MR10 */ +extern int MRinfo; /* MR10 */ +extern int MRinfoSeq; /* MR10 */ +extern int InfoP; /* MR10 */ +extern int InfoT; /* MR10 */ +extern int InfoF; /* MR10 */ +extern int InfoM; /* MR10 */ +extern int InfoO; /* MR12 */ +extern int PotentialSuppression; /* MR10 */ +extern int PotentialDummy; /* MR10 */ +extern int TnodesInUse; /* MR10 */ +extern int TnodesPeak; /* MR10 */ +extern int TnodesReportThreshold; /* MR11 */ +extern int TnodesAllocated; /* MR10 */ +extern char *ClassDeclStuff; /* MR10 */ +extern char *BaseClassName; /* MR22 */ +extern ListNode *class_before_actions, *class_after_actions; +extern char *UserTokenDefsFile; +extern int UserDefdTokens; +extern ListNode *MetaTokenNodes; +extern char *OutputDirectory; +extern int DontCopyTokens; +extern int LTinTokenAction; /* MR23 */ +extern set AST_nodes_refd_in_actions; +extern ListNode *CurExGroups; +extern int CurBlockID; +extern int CurAltNum; +extern Junction *CurAltStart; +extern Junction *OuterAltStart; /* chain exception groups MR7 */ +extern ExceptionGroup *DefaultExGroup; +extern int NumSignals; +extern int ContextGuardTRAV; +extern Junction *MR_RuleBlkWithHalt; /* MR10 */ +extern PointerStack MR_BackTraceStack; /* MR10 */ +extern PointerStack MR_PredRuleRefStack; /* MR10 */ +extern PointerStack MR_RuleBlkWithHaltStack; /* MR10 */ + +/* */ +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ +/* */ +extern int tokenActionActive; /* MR1 */ + +extern char *PRED_OR_LIST; /* MR10 */ +extern char *PRED_AND_LIST; /* MR10 */ + +#ifdef __VMS +#define STRICMP strcasecmp /* MR21 */ +#else +#define STRICMP stricmp /* MR21 */ +#endif + +/* MR26 */ +#ifdef PCCTS_USE_STDARG +extern Tree *tmake(Tree *root, ...); +#else +extern Tree *tmake(); +#endif + +#ifdef __USE_PROTOS +extern int STRICMP(const char*, const char*); +extern void istackreset(void); +extern int istacksize(void); +extern void pushint(int); +extern int popint( void ); +extern int istackempty( void ); +extern int topint( void ); +extern void NewSetWd( void ); +extern void DumpSetWd( void ); +extern void DumpSetWdForC( void ); +extern void DumpSetWdForCC( void ); +extern void NewSet( void ); +extern void FillSet( set ); +extern void ComputeErrorSets( void ); +extern void ComputeTokSets( void ); +extern void SubstErrorClass( set * ); +extern int DefErrSet( set *, int, char * ); +extern int DefErrSetForC( set *, int, char * ); +extern int DefErrSetForCC( set *, int, char * ); +extern int DefErrSet1(int, set *, int, char *); /* MR21 */ +extern int DefErrSetForC1(int, set *, int, char *, const char* ); /* MR21 */ +extern int DefErrSetForCC1(int, set *, int, char *, const char* ); /* MR21 */ +extern int DefErrSetWithSuffix(int, set *, int, char *, const char *); /* MR21 */ +extern void GenErrHdr( void ); +extern void dumpExpr( FILE *, char * ); +extern void addParm( Node *, char * ); +extern Graph buildAction( char *, int, int, int ); +extern Graph buildToken( char * ); +extern Graph buildWildCard( char * ); +extern Graph buildRuleRef( char * ); +extern Graph Or( Graph, Graph ); +extern Graph Cat( Graph, Graph ); +extern Graph makeOpt( Graph, int, char *); +extern Graph makeBlk( Graph, int, char *); +extern Graph makeLoop( Graph, int, char *); +extern Graph makePlus( Graph, int, char *); +extern Graph emptyAlt( void ); +extern Graph emptyAlt3( void ); +extern TokNode * newTokNode( void ); +extern RuleRefNode * newRNode( void ); +extern Junction * newJunction( void ); +extern ActionNode * newActionNode( void ); +extern char * makelocks( void ); +extern void preorder( Tree * ); +extern Tree * tnode( int ); +extern void _Tfree( Tree * ); +extern Tree * tdup( Tree * ); +extern int is_single_tuple( Tree * ); +extern Tree * tappend( Tree *, Tree * ); +extern void Tfree( Tree * ); +extern Tree * tlink( Tree *, Tree *, int ); +extern Tree * tshrink( Tree * ); +extern Tree * tflatten( Tree * ); +extern Tree * tJunc( Junction *, int, set * ); +extern Tree * tRuleRef( RuleRefNode *, int, set * ); +extern Tree * tToken( TokNode *, int, set * ); +extern Tree * tAction( ActionNode *, int, set * ); +extern int tmember( Tree *, Tree * ); +extern int tmember_constrained( Tree *, Tree * ); +extern Tree * tleft_factor( Tree * ); +extern Tree * trm_perm( Tree *, Tree * ); +extern void tcvt( set *, Tree * ); +extern Tree * permute( int, int ); +extern Tree * VerifyAmbig( Junction *, Junction *, unsigned **, set *, Tree **, Tree **, int * ); +extern set rJunc( Junction *, int, set * ); +extern set rRuleRef( RuleRefNode *, int, set * ); +extern set rToken( TokNode *, int, set * ); +extern set rAction( ActionNode *, int, set * ); +extern void HandleAmbiguity( Junction *, Junction *, Junction *, int ); +extern set First( Junction *, int, int, int * ); +extern void freeBlkFsets( Junction * ); +extern void genAction( ActionNode * ); +extern void genRuleRef( RuleRefNode * ); +extern void genToken( TokNode * ); +extern void genOptBlk( Junction * ); +extern void genLoopBlk( Junction *, Junction *, Junction *, int ); +extern void genLoopBegin( Junction * ); +extern void genPlusBlk( Junction * ); +extern void genSubBlk( Junction * ); +extern void genRule( Junction * ); +extern void genJunction( Junction * ); +extern void genEndBlk( Junction * ); +extern void genEndRule( Junction * ); +extern void genHdr( int ); +extern void genHdr1( int ); +extern void dumpAction( char *, FILE *, int, int, int, int ); +extern void dumpActionPlus(ActionNode*, char *, FILE *, int, int, int, int ); /* MR21 */ +extern Entry ** newHashTable( void ); +extern Entry * hash_add( Entry **, char *, Entry * ); +extern Entry * hash_get( Entry **, char * ); +extern void hashStat( Entry ** ); +extern char * mystrdup( char * ); +extern void genLexDescr( void ); +extern void dumpLexClasses( FILE * ); +extern void genDefFile( void ); +extern void DumpListOfParmNames( char *, FILE *, int ); /* MR5 janm 26-May-97 */ +extern int DumpNextNameInDef( char **, FILE * ); +extern void DumpOldStyleParms( char *, FILE * ); +extern void DumpType( char *, FILE * ); +extern int strmember( char *, char * ); +/* extern int HasComma( char * ); MR23 Replaced by hasMultipleOperands() */ +extern void DumpRetValStruct( FILE *, char *, int ); +extern char * StripQuotes( char * ); +extern int main( int, char *[] ); +extern void readDescr( void ); +extern FILE * NextFile( void ); +extern char * outnameX( char *, char *); +extern char * outname( char * ); +extern void fatalFL( char *, char *, int ); +extern void fatal_intern( char *, char *, int ); +extern void cleanUp( void ); +extern char * eMsg3( char *, char *, char *, char * ); +extern char * eMsgd( char *, int ); +extern char * eMsgd2( char *, int, int ); +extern void s_fprT( FILE *, set ); +extern char * TerminalString( int ); +extern void lexclass( char * ); +extern void lexmode( int ); +extern int LexClassIndex( char * ); +extern int hasAction( char * ); +extern void setHasAction( char *, char * ); +extern int addTname( char * ); +extern int addTexpr( char * ); +extern int Tnum( char * ); +extern void Tklink( char *, char * ); +extern Entry * newEntry( char *, int ); +extern void list_add( ListNode **, void * ); +extern void list_free( ListNode **, int freeData ); /* MR10 */ +extern void list_apply( ListNode *, void (*)(void *) ); +extern int list_search_cstring (ListNode *, char *); /* MR27 */ +extern char * Fkey( char *, int, int ); +extern void FoPush( char *, int ); +extern void FoPop( int ); +extern void RegisterCycle( char *, int ); +extern void ResolveFoCycles( int ); +extern void pJunc( Junction * ); +extern void pRuleRef( RuleRefNode * ); +extern void pToken( TokNode * ); +extern void pAction( ActionNode * ); +extern void FoLink( Node * ); +extern void addFoLink( Node *, char *, Junction * ); +extern void GenCrossRef( Junction * ); +extern void defErr( char *, long, long, long, long, long, long ); +extern void genStdPCCTSIncludeFile(FILE *,char *); /* MR10 */ +extern char * pcctsBaseName(char *); /* MR32 */ +extern Predicate *find_predicates(Node *); /* MR10 */ +extern Predicate *MR_find_predicates_and_supp(Node *); /* MR13 */ +extern int predicateLookaheadDepth(ActionNode *); /* MR10 */ +extern void predicate_free(Predicate *); /* MR10 */ +extern Predicate * predicate_dup(Predicate *); /* MR10 */ +extern Predicate * predicate_dup_without_context(Predicate *); /* MR11 */ +extern void GenRulePrototypes(FILE *, Junction *); +extern Junction *first_item_is_guess_block(Junction *); +extern Junction *first_item_is_guess_block_extra(Junction * q); /* MR30 */ +extern Junction *analysis_point(Junction *); +extern Tree *make_tree_from_sets(set *, set *); +extern Tree *tdup_chain(Tree *); +extern Tree *tdif(Tree *, Predicate *, set *, set *); +extern set covered_set(Predicate *); +extern void AmbiguityDialog(Junction *, int, Junction *, Junction *, int *, int *); +extern void dumpAmbigMsg(set *, FILE *, int); +extern void GenRuleFuncRedefs(FILE *, Junction *); +extern void GenPredefinedSymbolRedefs(FILE *); +extern void GenASTSymbolRedefs(FILE *); +extern void GenRemapFile(void); +extern void GenSetRedefs(FILE *); +extern ForcedToken *newForcedToken(char *, int); +extern void RemapForcedTokens(void); +extern char *TokenOrExpr(int); +extern void setUpperRange(TokNode *, char *); +extern void GenParser_c_Hdr(void); +extern void GenParser_h_Hdr(void); +extern void GenRuleMemberDeclarationsForCC(FILE *, Junction *); +extern int addForcedTname( char *, int ); +extern char *OutMetaName(char *); +extern void OutFirstSetSymbol(Junction *q, char *); /* MR21 */ +extern void warnNoFL(char *err); +extern void warnFL(char *err,char *f,int l); +extern void warn(char *err); +extern void warnNoCR( char *err ); +extern void errNoFL(char *err); +extern void errFL(char *err,char *f,int l); +extern void err(char *err); +extern void errNoCR( char *err ); +extern void genPredTree( Predicate *p, Node *j, int ,int); +extern UserAction *newUserAction(char *); +extern char *gate_symbol(char *name); +extern char *makeAltID(int blockid, int altnum); +extern void DumpRemainingTokSets(void); +extern void DumpANSIFunctionArgDef(FILE *f, Junction *q, int bInit); /* MR23 */ +extern void DumpFormals(FILE *, char *, int bInit); /* MR23 */ +extern char* hideDefaultArgs(const char* pdecl); /* MR22 VHS */ +extern Predicate *computePredFromContextGuard(Graph,int *msgDone); /* MR21 */ +extern void recomputeContextGuard(Predicate *); /* MR13 */ +extern Predicate *new_pred(void); +extern void chkGTFlag(void); +extern void leAdd(LabelEntry *); /* MR7 */ +extern void leFixup(void); /* MR7 */ +extern void egAdd(ExceptionGroup *); /* MR7 */ +extern void egFixup(void); /* MR7 */ +extern void altAdd(Junction *); /* MR7 */ +extern void altFixup(void); /* MR7 */ +extern Predicate * MR_find_in_aSubBlk(Junction *alt); /* MR10 */ +extern Predicate * MR_predFlatten(Predicate *p); /* MR10 */ +extern Predicate * MR_predSimplifyALL(Predicate *p); /* MR10 */ +extern Predicate * MR_predSimplifyALLX(Predicate *p,int skipPass3); /* MR10 */ +extern int MR_allPredLeaves(Predicate *p); /* MR10 */ +extern void MR_cleanup_pred_trees(Predicate *p); /* MR10 */ +extern int MR_predicate_context_completed(Predicate *p); /* MR10 */ +extern void MR_check_pred_too_long(Predicate *p,set completion); /* MR10 */ +extern Tree * MR_remove_epsilon_from_tree(Tree *t); /* MR10 */ +extern Tree * MR_computeTreeAND(Tree *l,Tree *r); /* MR10 */ +extern int MR_tree_equ(Tree *big, Tree *small); /* MR10 */ +extern set MR_First(int ck,Junction *j,set *incomplete); /* MR10 */ +extern set MR_compute_pred_set(Predicate *p); /* MR10 */ +extern Tree * MR_compute_pred_tree_context(Predicate *p); /* MR10 */ +extern int MR_pointerStackPush(PointerStack *,void *); /* MR10 */ +extern void * MR_pointerStackPop(PointerStack *); /* MR10 */ +extern void * MR_pointerStackTop(PointerStack *); /* MR10 */ +extern void MR_pointerStackReset(PointerStack *); /* MR10 */ +extern void MR_backTraceReport(void); /* MR10 */ +extern void MR_alphaBetaTraceReport(void); /* MR14 */ +extern void MR_dumpRuleSet(set); /* MR14 */ +extern void MR_predContextPresent(Predicate *p,int *,int *); /* MR10 */ +extern void MR_dumpPred(Predicate *p,int withContext); /* MR10 */ +extern void MR_dumpPred1(int,Predicate *p,int withContext); /* MR10 */ +extern void MR_xxxIndent(FILE *f,int depth); /* MR11 */ +extern void MR_outputIndent(int depth); /* MR11 */ +extern void MR_stderrIndent(int depth); /* MR11 */ +extern Junction * MR_ruleReferenced(RuleRefNode *rrn); /* MR10 */ +extern Junction * MR_nameToRuleBlk(char *); /* MR10 */ +extern void MR_releaseResourcesUsedInRule(Node *); /* MR10 */ +extern void MR_dumpTreeX(int depth,Tree *t,int across); /* MR10 */ +extern void MR_dumpTreeF(FILE *f,int depth,Tree *t,int across); /* MR10 */ +extern void DumpFcache(void); /* MR10 */ +extern void MR_dumpTokenSet(FILE *f,int depth,set s); /* MR10 */ +extern void MR_traceAmbSource(set *,Junction *,Junction *); /* MR11 */ +extern void MR_traceAmbSourceK(Tree *,Junction *a1,Junction *a2); /* MR11 */ +extern void MR_traceAmbSourceKclient(void); /* MR20 */ +extern Node *MR_advance(Node *); /* MR11 */ +extern int MR_offsetFromRule(Node *); /* MR11 */ +extern char *MR_ruleNamePlusOffset(Node *); /* MR11 */ +extern int MR_max_height_of_tree(Tree *); /* MR11 */ +extern int MR_all_leaves_same_height(Tree *,int); /* MR11 */ +extern void MR_projectTreeOntoSet(Tree *t,int k,set *); /* MR11 */ +extern Tree *MR_make_tree_from_set(set); /* MR11 */ +extern Predicate *MR_removeRedundantPredPass3(Predicate *); /* MR11 */ +extern void MR_pred_depth(Predicate *,int *); /* MR11 */ +extern int MR_comparePredicates(Predicate *,Predicate *); /* MR11 */ +extern Predicate * MR_unfold(Predicate *); /* MR11 */ +extern void MR_simplifyInverted(Predicate *,int); /* MR11 */ +extern int MR_secondPredicateUnreachable /* MR11 */ + (Predicate *first,Predicate *second); /* MR11 */ +extern void MR_clearPredEntry(Predicate *); /* MR11 */ +extern void MR_orphanRules(FILE *); /* MR12 */ +extern void MR_merge_contexts(Tree *); /* MR12 */ +extern int ci_strequ(char *,char *); /* MR12 */ +extern void MR_guardPred_plainSet(ActionNode *anode,Predicate *); /* MR12c */ +extern void MR_suppressSearchReport(void); /* MR12c */ +extern Predicate * MR_suppressK(Node *,Predicate *); /* MR13 */ +extern void MR_backTraceDumpItem(FILE *,int skip,Node *n); /* MR13 */ +extern void MR_backTraceDumpItemReset(void); /* MR13 */ +extern Junction * MR_junctionWithoutP2(Junction *); /* MR13 */ +extern void MR_setConstrainPointer(set *); /* MR18 */ +extern void BlockPreambleOption(Junction *q, char * pSymbol); /* MR23 */ +extern char* getInitializer(char *); /* MR23 */ +extern char *endFormal(char *pStart, /* MR23 */ + char **ppDataType, /* MR23 */ + char **ppSymbol, /* MR23 */ + char **ppEqualSign, /* MR23 */ + char **ppValue, /* MR23 */ + char **ppSeparator, /* MR23 */ + int *pNext); /* MR23 */ +extern char *strBetween(char *pStart, /* MR23 */ + char *pNext, /* MR23 */ + char *pStop); /* MR23 */ +extern int hasMultipleOperands(char *); /* MR23 */ +extern void DumpInitializers(FILE*, RuleEntry*, char*); /* MR23 */ +extern int isTermEntryTokClass(TermEntry *); /* MR23 */ +extern int isEmptyAlt(Node *, Node *); /* MR23 */ +#else +extern int STRICMP(); +extern void istackreset(); +extern int istacksize(); +extern void pushint(); +extern int popint(); +extern int istackempty(); +extern int topint(); +extern void NewSetWd(); +extern void DumpSetWd(); +extern void DumpSetWdForC(); +extern void DumpSetWdForCC(); +extern void NewSet(); +extern void FillSet(); +extern void ComputeErrorSets(); +extern void ComputeTokSets(); +extern void SubstErrorClass(); +extern int DefErrSet(); +extern int DefErrSetForC(); +extern int DefErrSetForCC(); +extern int DefErrSet1(); +extern int DefErrSetForC1(); +extern int DefErrSetForCC1(); +extern int DefErrSetWithSuffix(); /* MR21 */ +extern void GenErrHdr(); +extern void dumpExpr(); +extern void addParm(); +extern Graph buildAction(); +extern Graph buildToken(); +extern Graph buildWildCard(); +extern Graph buildRuleRef(); +extern Graph Or(); +extern Graph Cat(); +extern Graph makeOpt(); +extern Graph makeBlk(); +extern Graph makeLoop(); +extern Graph makePlus(); +extern Graph emptyAlt(); +extern Graph emptyAlt3(); +extern TokNode * newTokNode(); +extern RuleRefNode * newRNode(); +extern Junction * newJunction(); +extern ActionNode * newActionNode(); +extern char * makelocks(); +extern void preorder(); +extern Tree * tnode(); +extern void _Tfree(); +extern Tree * tdup(); +extern int is_single_tuple(); +extern Tree * tappend(); +extern void Tfree(); +extern Tree * tlink(); +extern Tree * tshrink(); +extern Tree * tflatten(); +extern Tree * tJunc(); +extern Tree * tRuleRef(); +extern Tree * tToken(); +extern Tree * tAction(); +extern int tmember(); +extern int tmember_constrained(); +extern Tree * tleft_factor(); +extern Tree * trm_perm(); +extern void tcvt(); +extern Tree * permute(); +extern Tree * VerifyAmbig(); +extern set rJunc(); +extern set rRuleRef(); +extern set rToken(); +extern set rAction(); +extern void HandleAmbiguity(); +extern set First(); +extern void freeBlkFsets(); +extern void genAction(); +extern void genRuleRef(); +extern void genToken(); +extern void genOptBlk(); +extern void genLoopBlk(); +extern void genLoopBegin(); +extern void genPlusBlk(); +extern void genSubBlk(); +extern void genRule(); +extern void genJunction(); +extern void genEndBlk(); +extern void genEndRule(); +extern void genHdr(); +extern void genHdr1(); +extern void dumpAction(); +extern void dumpActionPlus(); /* MR21 */ +extern Entry ** newHashTable(); +extern Entry * hash_add(); +extern Entry * hash_get(); +extern void hashStat(); +extern char * mystrdup(); +extern void genLexDescr(); +extern void dumpLexClasses(); +extern void genDefFile(); +extern void DumpListOfParmNames(); /* MR5 janm 26-May-97 */ +extern int DumpNextNameInDef(); +extern void DumpOldStyleParms(); +extern void DumpType(); +extern int strmember(); +/* extern int HasComma(); MR23 Replaced by hasMultipleOperands() */ +extern void DumpRetValStruct(); +extern char * StripQuotes(); +extern int main(); +extern void readDescr(); +extern FILE * NextFile(); +extern char * outnameX(); +extern char * outname(); +extern void fatalFL(); +extern void fatal_intern(); +extern void cleanUp(); +extern char * eMsg3(); +extern char * eMsgd(); +extern char * eMsgd2(); +extern void s_fprT(); +extern char * TerminalString(); +extern void lexclass(); +extern void lexmode(); +extern int LexClassIndex(); +extern int hasAction(); +extern void setHasAction(); +extern int addTname(); +extern int addTexpr(); +extern int Tnum(); +extern void Tklink(); +extern Entry * newEntry(); +extern void list_add(); +extern void list_free(); /* MR10 */ +extern void list_apply(); +extern int list_search_cstring (); /* MR27 */ +extern char * Fkey(); +extern void FoPush(); +extern void FoPop(); +extern void RegisterCycle(); +extern void ResolveFoCycles(); +extern void pJunc(); +extern void pRuleRef(); +extern void pToken(); +extern void pAction(); +extern void FoLink(); +extern void addFoLink(); +extern void GenCrossRef(); +extern void defErr(); +extern void genStdPCCTSIncludeFile(); +extern char * pcctsBaseName(); /* MR32 */ +extern Predicate *find_predicates(); +extern Predicate *MR_find_predicates_and_supp(); /* MR13 */ +extern int predicateLookaheadDepth(); /* MR10 */ +extern void predicate_free(); /* MR10 */ +extern Predicate * predicate_dup(); /* MR10 */ +extern Predicate * predicate_dup_without_context(); /* MR11 */ +extern void GenRulePrototypes(); +extern Junction *first_item_is_guess_block(); +extern Junction *first_item_is_guess_block_extra(); /* MR30 */ +extern Junction *analysis_point(); +extern Tree *make_tree_from_sets(); +extern Tree *tdup_chain(); +extern Tree *tdif(); +extern set covered_set(); +extern void AmbiguityDialog(); +extern void dumpAmbigMsg(); +extern void GenRuleFuncRedefs(); +extern void GenPredefinedSymbolRedefs(); +extern void GenASTSymbolRedefs(); +extern void GenRemapFile(); +extern void GenSetRedefs(); +extern ForcedToken *newForcedToken(); +extern void RemapForcedTokens(); +extern char *TokenOrExpr(); +extern void setUpperRange(); +extern void GenParser_c_Hdr(); +extern void GenParser_h_Hdr(); +extern void GenRuleMemberDeclarationsForCC(); +extern int addForcedTname(); +extern char *OutMetaName(); +extern void OutFirstSetSymbol(); /* MR21 */ +extern void warnNoFL(); +extern void warnFL(); +extern void warn(); +extern void warnNoCR(); +extern void errNoFL(); +extern void errFL(); +extern void err(); +extern void errNoCR(); +extern void genPredTree(); +extern UserAction *newUserAction(); +extern char *gate_symbol(); +extern char *makeAltID(); +extern void DumpRemainingTokSets(); +extern void DumpANSIFunctionArgDef(); +extern void DumpFormals(); /* MR23 */ +extern char* hideDefaultArgs(); /* MR22 VHS */ +extern Predicate *computePredFromContextGuard(); +extern void recomputeContextGuard(); /* MR13 */ +extern Predicate *new_pred(); +extern void chkGTFlag(); +extern void leAdd(); /* MR7 */ +extern void leFixup(); /* MR7 */ +extern void egAdd(); /* MR7 */ +extern void egFixup(); /* MR7 */ +extern void altAdd(); /* MR7 */ +extern void altFixup(); /* MR7 */ +extern Predicate * MR_find_in_aSubBlk(); /* MR10 */ +extern Predicate * MR_predFlatten(); /* MR10 */ +extern Predicate * MR_predSimplifyALL(); /* MR10 */ +extern Predicate * MR_predSimplifyALLX(); /* MR10 */ +extern void MR_cleanup_pred_trees(); /* MR10 */ +extern int MR_allPredLeaves(); /* MR10 */ +extern int MR_predicate_context_completed(); /* MR10 */ +extern void MR_check_pred_too_long(); /* MR10 */ +extern Tree * MR_remove_epsilon_from_tree(); /* MR10 */ +extern Tree * MR_computeTreeAND(); /* MR10 */ +extern int MR_tree_equ(); /* MR10 */ +extern set MR_First(); /* MR10 */ +extern set MR_compute_pred_set(); /* MR10 */ +extern Tree * MR_compute_pred_tree_context(); /* MR10 */ +extern int MR_pointerStackPush(); /* MR10 */ +extern void * MR_pointerStackPop(); /* MR10 */ +extern void * MR_pointerStackTop(); /* MR10 */ +extern void MR_pointerStackReset(); /* MR10 */ +extern void MR_backTraceReport(); /* MR10 */ +extern void MR_alphaBetaTraceReport(); /* MR14 */ +extern void MR_dumpRuleSet(); /* MR14 */ +extern void MR_predContextPresent(); /* MR10 */ +extern void MR_dumpPred(); /* MR10 */ +extern void MR_dumpPred1(); /* MR10 */ +extern void MR_xxxIndent(); /* MR11 */ +extern void MR_stderrIndent(); /* MR11 */ +extern void MR_outputIndent(); /* MR11 */ +extern Junction * MR_ruleReferenced(); /* MR10 */ +extern void MR_releaseResourcesUsedInRule(); /* MR10 */ +extern void MR_dumpTreeX(); /* MR10 */ +extern void MR_dumpTreeF(); /* MR10 */ +extern void DumpFcache(); /* MR10 */ +extern void MR_dumpTokenSet(); /* MR10 */ +extern void MR_traceAmbSource(); /* MR11 */ +extern Node *MR_advance(); /* MR11 */ +extern int MR_offsetFromRule(); /* MR11 */ +extern char *MR_ruleNamePlusOffset(); /* MR11 */ +extern void MR_traceAmbSourceK(); /* MR11 */ +extern void MR_traceAmbSourceKclient(); /* [i_a] added */ +extern int MR_max_height_of_tree(); /* MR11 */ +extern int MR_all_leaves_same_height(); /* MR11 */ +extern void MR_projectTreeOntoSet(); /* MR11 */ +extern Tree *MR_make_tree_from_set(); /* MR11 */ +extern Predicate *MR_removeRedundantPredPass3(); /* MR11 */ +extern void MR_pred_depth(); /* MR11 */ +extern int MR_comparePredicates(); /* MR11 */ +extern Predicate * MR_unfold(); /* MR11 */ +extern void MR_simplifyInverted(); /* MR11 */ +extern int MR_secondPredicateUnreachable(); /* MR11 */ +extern Junction * MR_nameToRuleBlk(); /* MR10 */ +extern void MR_clearPredEntry(); /* MR11 */ +extern void MR_orphanRules(); /* MR12 */ +extern void MR_merge_contexts(); /* MR12 */ +extern int ci_strequ(); /* MR12 */ +extern void MR_guardPred_plainSet(); /* MR12c */ +extern void MR_suppressSearchReport(); /* MR12c */ +extern Predicate * MR_suppressK(); /* MR13 */ +extern void MR_backTraceDumpItem(); /* MR13 */ +extern void MR_backTraceDumpItemReset(); /* MR13 */ +extern Junction * MR_junctionWithoutP2(); /* MR13 */ +extern void MR_setConstrainPointer(); /* MR18 */ +extern void BlockPreambleOption(); /* MR23 */ +extern char* getInitializer(); /* MR23 */ +extern int hasMultipleOperands(); /* MR23 */ +extern char *endFormal(); /* MR23 */ +extern char *strBetween(); /* MR23 */ +extern void DumpInitializers(); /* MR23 */ +extern int isTermEntryTokClass(); /* MR23 */ +extern int isEmptyAlt(); + +#endif + +#ifdef __USE_PROTOS +#include +#endif + +/* MR20 G. Hobbelt Create proper externs for dlg variables */ + +extern set attribsRefdFromAction; +extern int inAlt; +extern int UsedOldStyleAttrib; +extern int UsedNewStyleLabel; + +#define MAX_BLK_LEVEL 100 /* MR23 */ +extern int CurBlockID_array[MAX_BLK_LEVEL]; /* MR23 */ +extern int CurAltNum_array[MAX_BLK_LEVEL]; /* MR23 */ diff --git a/Tools/Source/TianoTools/Pccts/antlr/scan.c b/Tools/Source/TianoTools/Pccts/antlr/scan.c new file mode 100644 index 0000000000..9b4bde08e6 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/scan.c @@ -0,0 +1,5735 @@ + +/* parser.dlg -- DLG Description of scanner + * + * Generated from: antlr.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include "pcctscfg.h" +#include "set.h" +#include +#include "syn.h" +#include "hash.h" +#include "generic.h" +#define zzcr_attr(attr,tok,t) +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +LOOKAHEAD + +void +#ifdef __USE_PROTOS +zzerraction(void) +#else +zzerraction() +#endif +{ + (*zzerr)("invalid token"); + zzadvance(); + zzskip(); +} +/* + * D L G tables + * + * Generated from: parser.dlg + * + * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz + * Purdue University Electrical Engineering + * DLG Version 1.33MR33 + */ + +#include "mode.h" + + + + +/* maintained, but not used for now */ +set AST_nodes_refd_in_actions = set_init; +int inAlt = 0; +set attribsRefdFromAction = set_init; /* MR20 */ +int UsedOldStyleAttrib = 0; +int UsedNewStyleLabel = 0; +#ifdef __USE_PROTOS +char *inline_set(char *); +#else +char *inline_set(); +#endif + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ + +int tokenActionActive=0; /* MR1 */ + + + + + +static char * +#ifdef __USE_PROTOS +getFileNameFromTheLineInfo(char *toStr, char *fromStr) +#else +getFileNameFromTheLineInfo(toStr, fromStr) +char *toStr, *fromStr; +#endif +{ + int i, j, k; + + if (!fromStr || !toStr) return toStr; + + /* find the first " */ + + for (i=0; + (ielem->ntype == nToken,"mark_label_used... ntype != nToken"); + tn=(TokNode *)le->elem; + require (tn->label != 0,"mark_label_used... TokNode has no label"); + tn->label_used_in_semantic_pred=1; +} + +static void act1() +{ + NLA = Eof; + /* L o o k F o r A n o t h e r F i l e */ + { + FILE *new_input; + new_input = NextFile(); + if ( new_input == NULL ) { NLA=Eof; return; } + fclose( input ); + input = new_input; + zzrdstream( input ); + zzskip(); /* Skip the Eof (@) char i.e continue */ + } + } + + +static void act2() +{ + NLA = 76; + zzskip(); + } + + +static void act3() +{ + NLA = 77; + zzline++; zzskip(); + } + + +static void act4() +{ + NLA = 78; + zzmode(ACTIONS); zzmore(); + istackreset(); + pushint(']'); + } + + +static void act5() +{ + NLA = 79; + action_file=CurFile; action_line=zzline; + zzmode(ACTIONS); zzmore(); + list_free(&CurActionLabels,0); /* MR10 */ + numericActionLabel=0; /* MR10 */ + istackreset(); + pushint('>'); + } + + +static void act6() +{ + NLA = 80; + zzmode(STRINGS); zzmore(); + } + + +static void act7() +{ + NLA = 81; + zzmode(COMMENTS); zzskip(); + } + + +static void act8() +{ + NLA = 82; + warn("Missing /*; found dangling */"); zzskip(); + } + + +static void act9() +{ + NLA = 83; + zzmode(CPP_COMMENTS); zzskip(); + } + + +static void act10() +{ + NLA = 84; + + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + } + + +static void act11() +{ + NLA = 85; + + zzline++; zzmore(); + } + + +static void act12() +{ + NLA = 86; + warn("Missing <<; found dangling >>"); zzskip(); + } + + +static void act13() +{ + NLA = WildCard; + } + + +static void act14() +{ + NLA = 88; + FoundException = 1; /* MR6 */ + FoundAtOperator = 1; + } + + +static void act15() +{ + NLA = Pragma; + } + + +static void act16() +{ + NLA = FirstSetSymbol; + } + + +static void act17() +{ + NLA = 94; + } + + +static void act18() +{ + NLA = 95; + } + + +static void act19() +{ + NLA = 96; + } + + +static void act20() +{ + NLA = 97; + } + + +static void act21() +{ + NLA = 98; + } + + +static void act22() +{ + NLA = 99; + } + + +static void act23() +{ + NLA = 102; + } + + +static void act24() +{ + NLA = 103; + } + + +static void act25() +{ + NLA = 104; + } + + +static void act26() +{ + NLA = 105; + } + + +static void act27() +{ + NLA = 106; + } + + +static void act28() +{ + NLA = 107; + } + + +static void act29() +{ + NLA = 108; + } + + +static void act30() +{ + NLA = 109; + } + + +static void act31() +{ + NLA = 110; + } + + +static void act32() +{ + NLA = 111; + } + + +static void act33() +{ + NLA = 112; + } + + +static void act34() +{ + NLA = 113; + } + + +static void act35() +{ + NLA = 114; + } + + +static void act36() +{ + NLA = 115; + } + + +static void act37() +{ + NLA = 116; + } + + +static void act38() +{ + NLA = 117; + } + + +static void act39() +{ + NLA = 118; + } + + +static void act40() +{ + NLA = 119; + } + + +static void act41() +{ + NLA = 120; + } + + +static void act42() +{ + NLA = 121; + } + + +static void act43() +{ + NLA = 122; + } + + +static void act44() +{ + NLA = 123; + } + + +static void act45() +{ + NLA = 124; + } + + +static void act46() +{ + NLA = 125; + } + + +static void act47() +{ + NLA = 126; + } + + +static void act48() +{ + NLA = 127; + } + + +static void act49() +{ + NLA = 128; + } + + +static void act50() +{ + NLA = 129; + } + + +static void act51() +{ + NLA = 130; + } + + +static void act52() +{ + NLA = 131; + } + + +static void act53() +{ + NLA = 132; + } + + +static void act54() +{ + NLA = 133; + } + + +static void act55() +{ + NLA = 134; + } + + +static void act56() +{ + NLA = 135; + } + + +static void act57() +{ + NLA = NonTerminal; + + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + } + + +static void act58() +{ + NLA = TokenTerm; + + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + } + + +static void act59() +{ + NLA = 136; + warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); + } + +static unsigned char shift0[257] = { + 0, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 1, 2, 58, 58, 3, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 1, 40, 6, 9, 58, 58, 45, + 58, 46, 47, 8, 52, 58, 58, 18, 7, 16, + 14, 15, 16, 16, 16, 16, 16, 16, 16, 41, + 42, 5, 48, 17, 53, 19, 56, 56, 56, 56, + 56, 26, 56, 56, 56, 56, 56, 51, 56, 56, + 56, 56, 56, 56, 29, 56, 56, 56, 56, 56, + 56, 56, 4, 20, 58, 50, 57, 58, 23, 31, + 38, 34, 13, 35, 24, 33, 11, 55, 36, 10, + 25, 12, 32, 21, 55, 22, 27, 28, 54, 55, + 55, 43, 30, 55, 39, 44, 37, 49, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58 +}; + + +static void act60() +{ + NLA = Eof; + } + + +static void act61() +{ + NLA = QuotedTerm; + zzmode(START); + } + + +static void act62() +{ + NLA = 3; + + zzline++; + warn("eoln found in string"); + zzskip(); + } + + +static void act63() +{ + NLA = 4; + zzline++; zzmore(); + } + + +static void act64() +{ + NLA = 5; + zzmore(); + } + + +static void act65() +{ + NLA = 6; + zzmore(); + } + +static unsigned char shift1[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 2, 5, 5, 3, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 1, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act66() +{ + NLA = Eof; + } + + +static void act67() +{ + NLA = 7; + zzmode(ACTIONS); zzmore(); + } + + +static void act68() +{ + NLA = 8; + + zzline++; + warn("eoln found in string (in user action)"); + zzskip(); + } + + +static void act69() +{ + NLA = 9; + zzline++; zzmore(); + } + + +static void act70() +{ + NLA = 10; + zzmore(); + } + + +static void act71() +{ + NLA = 11; + zzmore(); + } + +static unsigned char shift2[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 2, 5, 5, 3, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 1, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act72() +{ + NLA = Eof; + } + + +static void act73() +{ + NLA = 12; + zzmode(ACTIONS); zzmore(); + } + + +static void act74() +{ + NLA = 13; + + zzline++; + warn("eoln found in char literal (in user action)"); + zzskip(); + } + + +static void act75() +{ + NLA = 14; + zzmore(); + } + + +static void act76() +{ + NLA = 15; + zzmore(); + } + +static unsigned char shift3[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 2, 5, 5, 3, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act77() +{ + NLA = Eof; + } + + +static void act78() +{ + NLA = 16; + zzmode(ACTIONS); zzmore(); + } + + +static void act79() +{ + NLA = 17; + zzmore(); + } + + +static void act80() +{ + NLA = 18; + zzline++; zzmore(); DAWDLE; + } + + +static void act81() +{ + NLA = 19; + zzmore(); + } + +static unsigned char shift4[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 3, 5, 5, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 1, 5, 5, 5, 5, 2, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act82() +{ + NLA = Eof; + } + + +static void act83() +{ + NLA = 20; + zzmode(PARSE_ENUM_FILE); + zzmore(); + } + + +static void act84() +{ + NLA = 21; + zzmore(); + } + + +static void act85() +{ + NLA = 22; + zzline++; zzmore(); DAWDLE; + } + + +static void act86() +{ + NLA = 23; + zzmore(); + } + +static unsigned char shift5[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 3, 5, 5, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 1, 5, 5, 5, 5, 2, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act87() +{ + NLA = Eof; + } + + +static void act88() +{ + NLA = 24; + zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; + } + + +static void act89() +{ + NLA = 25; + zzskip(); + } + +static unsigned char shift6[257] = { + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 3, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3 +}; + + +static void act90() +{ + NLA = Eof; + } + + +static void act91() +{ + NLA = 26; + zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; + } + + +static void act92() +{ + NLA = 27; + zzmore(); + } + +static unsigned char shift7[257] = { + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 3, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3 +}; + + +static void act93() +{ + NLA = Eof; + } + + +static void act94() +{ + NLA = 28; + zzline++; zzmode(START); zzskip(); DAWDLE; + } + + +static void act95() +{ + NLA = 29; + zzskip(); + } + +static unsigned char shift8[257] = { + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 3, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3 +}; + + +static void act96() +{ + NLA = Eof; + } + + +static void act97() +{ + NLA = 30; + zzmode(START); zzskip(); + } + + +static void act98() +{ + NLA = 31; + zzskip(); + } + + +static void act99() +{ + NLA = 32; + zzline++; zzskip(); DAWDLE; + } + + +static void act100() +{ + NLA = 33; + zzskip(); + } + +static unsigned char shift9[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 3, 5, 5, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 1, 5, 5, 5, 5, 2, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act101() +{ + NLA = Eof; + } + + +static void act102() +{ + NLA = Action; + /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = ' '; + zzbegexpr[1] = ' '; + if ( zzbufovf ) { + err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE)); + } + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ + /* MR1 in DLG action */ + /* MR1 Doesn't matter what kind of action it is - reset*/ + + tokenActionActive=0; /* MR1 */ + } + + +static void act103() +{ + NLA = Pred; + /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = '\0'; + if ( zzbufovf ) { + err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE)); + }; +#ifdef __cplusplus__ + /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __STDC__ + /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __USE_PROTOS + /* MRxx */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else + /* MR10 */ list_apply(CurActionLabels,mark_label_used_in_sem_pred); +#endif +#endif +#endif + } + + +static void act104() +{ + NLA = PassAction; + if ( topint() == ']' ) { + popint(); + if ( istackempty() ) /* terminate action */ + { + zzmode(START); + NLATEXT[0] = ' '; + zzbegexpr[0] = ' '; + if ( zzbufovf ) { + err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE)); + } + } + else { + /* terminate $[..] and #[..] */ + if ( GenCC ) zzreplstr("))"); + else zzreplstr(")"); + zzmore(); + } + } + else if ( topint() == '|' ) { /* end of simple [...] */ + popint(); + zzmore(); + } + else zzmore(); + } + + +static void act105() +{ + NLA = 37; + + zzmore(); + zzreplstr(inline_set(zzbegexpr+ + strlen("consumeUntil("))); + } + + +static void act106() +{ + NLA = 38; + zzmore(); + } + + +static void act107() +{ + NLA = 39; + zzline++; zzmore(); DAWDLE; + } + + +static void act108() +{ + NLA = 40; + zzmore(); + } + + +static void act109() +{ + NLA = 41; + zzmore(); + } + + +static void act110() +{ + NLA = 42; + if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();} + else err("$$ use invalid in C++ mode"); + } + + +static void act111() +{ + NLA = 43; + if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();} + else err("$[] use invalid in C++ mode"); + } + + +static void act112() +{ + NLA = 44; + + pushint(']'); + if ( !GenCC ) zzreplstr("zzconstr_attr("); + else err("$[..] use invalid in C++ mode"); + zzmore(); + } + + +static void act113() +{ + NLA = 45; + { + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i attrib ref too big"); + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + } + + +static void act114() +{ + NLA = 46; + { + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i.field attrib ref too big"); + zzbegexpr[strlen(zzbegexpr)-1] = ' '; + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s.", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + } + + +static void act115() +{ + NLA = 47; + { + static char buf[100]; + static char i[20], j[20]; + char *p,*q; + numericActionLabel=1; /* MR10 */ + if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big"); + for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) { + if ( q == &i[20] ) + fatalFL("i of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + for (p++, q= &j[0]; *p!='\0'; p++) { + if ( q == &j[20] ) + fatalFL("j of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j); + else sprintf(buf,"_t%s%s",i,j); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + } + + +static void act116() +{ + NLA = 48; + { static char buf[300]; LabelEntry *el; + zzbegexpr[0] = ' '; + if ( CurRule != NULL && + strcmp(CurRule, &zzbegexpr[1])==0 ) { + if ( !GenCC ) zzreplstr("zzaRet"); + } + else if ( CurRetDef != NULL && + strmember(CurRetDef, &zzbegexpr[1])) { + if ( hasMultipleOperands( CurRetDef ) ) { + require (strlen(zzbegexpr)<=(size_t)285, + "$retval attrib ref too big"); + sprintf(buf,"_retv.%s",&zzbegexpr[1]); + zzreplstr(buf); + } + else zzreplstr("_retv"); + } + else if ( CurParmDef != NULL && + strmember(CurParmDef, &zzbegexpr[1])) { + ; + } + else if ( Elabel==NULL ) { + { err("$-variables in actions outside of rules are not allowed"); } + } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) { + /* MR10 */ + /* MR10 */ /* element labels might exist without an elem when */ + /* MR10 */ /* it is a forward reference (to a rule) */ + /* MR10 */ + /* MR10 */ if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) ) + /* MR10 */ { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); } + /* MR10 */ + /* MR10 */ if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) { + /* MR10 */ err("You can no longer use attributes returned by rules when also using ASTs"); + /* MR10 */ err(" Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...>>\")"); + /* MR10 */ }; + /* MR10 */ + /* MR10 */ /* keep track of <<... $label ...>> for semantic predicates in guess mode */ + /* MR10 */ /* element labels contain pointer to the owners node */ + /* MR10 */ + /* MR10 */ if (el->elem != NULL && el->elem->ntype == nToken) { + /* MR10 */ list_add(&CurActionLabels,el); + /* MR10 */ }; +} +else +warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1])); +} +zzmore(); + } + + +static void act117() +{ + NLA = 49; + zzreplstr("(*_root)"); zzmore(); chkGTFlag(); + } + + +static void act118() +{ + NLA = 50; + if ( GenCC ) { + if (NewAST) zzreplstr("(newAST)"); + else zzreplstr("(new AST)");} + else {zzreplstr("zzastnew()");} zzmore(); + chkGTFlag(); + } + + +static void act119() +{ + NLA = 51; + zzreplstr("NULL"); zzmore(); chkGTFlag(); + } + + +static void act120() +{ + NLA = 52; + { + static char buf[100]; + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("#i AST ref too big"); + if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"zzastArg(%s)",zzbegexpr+1); + zzreplstr(buf); + zzmore(); + set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions); + chkGTFlag(); + } + } + + +static void act121() +{ + NLA = 53; + + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + } + + +static void act122() +{ + NLA = 54; + + zzline++; zzmore(); + } + + +static void act123() +{ + NLA = 55; + + if ( !(strcmp(zzbegexpr, "#ifdef")==0 || + strcmp(zzbegexpr, "#if")==0 || + strcmp(zzbegexpr, "#else")==0 || + strcmp(zzbegexpr, "#endif")==0 || + strcmp(zzbegexpr, "#ifndef")==0 || + strcmp(zzbegexpr, "#define")==0 || + strcmp(zzbegexpr, "#pragma")==0 || + strcmp(zzbegexpr, "#undef")==0 || + strcmp(zzbegexpr, "#import")==0 || + strcmp(zzbegexpr, "#line")==0 || + strcmp(zzbegexpr, "#include")==0 || + strcmp(zzbegexpr, "#error")==0) ) + { + static char buf[100]; + sprintf(buf, "%s_ast", zzbegexpr+1); + /* MR27 */ list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1)); + zzreplstr(buf); + chkGTFlag(); + } + zzmore(); + } + + +static void act124() +{ + NLA = 56; + + pushint(']'); + if ( GenCC ) { + if (NewAST) zzreplstr("(newAST("); + else zzreplstr("(new AST("); } + else zzreplstr("zzmk_ast(zzastnew(),"); + zzmore(); + chkGTFlag(); + } + + +static void act125() +{ + NLA = 57; + + pushint('}'); + if ( GenCC ) { + if (tmakeInParser) { + zzreplstr("tmake("); + } + else { + zzreplstr("ASTBase::tmake("); + } + } + else { + zzreplstr("zztmake("); + } + zzmore(); + chkGTFlag(); + } + + +static void act126() +{ + NLA = 58; + zzmore(); + } + + +static void act127() +{ + NLA = 59; + + if ( istackempty() ) + zzmore(); + else if ( topint()==')' ) { + popint(); + } + else if ( topint()=='}' ) { + popint(); + /* terminate #(..) */ + zzreplstr(", NULL)"); + } + zzmore(); + } + + +static void act128() +{ + NLA = 60; + + pushint('|'); /* look for '|' to terminate simple [...] */ + zzmore(); + } + + +static void act129() +{ + NLA = 61; + + pushint(')'); + zzmore(); + } + + +static void act130() +{ + NLA = 62; + zzreplstr("]"); zzmore(); + } + + +static void act131() +{ + NLA = 63; + zzreplstr(")"); zzmore(); + } + + +static void act132() +{ + NLA = 64; + if (! tokenActionActive) zzreplstr(">"); /* MR1 */ + zzmore(); /* MR1 */ + } + + +static void act133() +{ + NLA = 65; + zzmode(ACTION_CHARS); zzmore(); + } + + +static void act134() +{ + NLA = 66; + zzmode(ACTION_STRINGS); zzmore(); + } + + +static void act135() +{ + NLA = 67; + zzreplstr("$"); zzmore(); + } + + +static void act136() +{ + NLA = 68; + zzreplstr("#"); zzmore(); + } + + +static void act137() +{ + NLA = 69; + zzline++; zzmore(); + } + + +static void act138() +{ + NLA = 70; + zzmore(); + } + + +static void act139() +{ + NLA = 71; + zzmore(); + } + + +static void act140() +{ + NLA = 72; + zzmode(ACTION_COMMENTS); zzmore(); + } + + +static void act141() +{ + NLA = 73; + warn("Missing /*; found dangling */ in action"); zzmore(); + } + + +static void act142() +{ + NLA = 74; + zzmode(ACTION_CPP_COMMENTS); zzmore(); + } + + +static void act143() +{ + NLA = 75; + zzmore(); + } + +static unsigned char shift10[257] = { + 0, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 16, 19, 33, 33, 20, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 16, 33, 28, 27, 21, 33, 33, + 30, 15, 18, 32, 33, 33, 33, 25, 31, 23, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 33, + 33, 33, 33, 1, 2, 33, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 11, 26, 26, 26, + 26, 26, 22, 29, 3, 33, 26, 33, 26, 26, + 4, 26, 10, 26, 26, 26, 13, 26, 26, 14, + 9, 6, 5, 26, 26, 26, 7, 12, 8, 26, + 26, 26, 26, 26, 17, 33, 34, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33 +}; + + +static void act144() +{ + NLA = Eof; + ; + } + + +static void act145() +{ + NLA = 137; + zzskip(); + } + + +static void act146() +{ + NLA = 138; + zzline++; zzskip(); + } + + +static void act147() +{ + NLA = 139; + zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); + } + + +static void act148() +{ + NLA = 140; + zzmode(TOK_DEF_COMMENTS); zzskip(); + } + + +static void act149() +{ + NLA = 141; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act150() +{ + NLA = 142; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act151() +{ + NLA = 143; + ; + } + + +static void act152() +{ + NLA = 144; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act153() +{ + NLA = 145; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act154() +{ + NLA = 146; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act155() +{ + NLA = 147; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act156() +{ + NLA = 149; + } + + +static void act157() +{ + NLA = 151; + } + + +static void act158() +{ + NLA = 152; + } + + +static void act159() +{ + NLA = 153; + } + + +static void act160() +{ + NLA = 154; + } + + +static void act161() +{ + NLA = 155; + } + + +static void act162() +{ + NLA = 156; + } + + +static void act163() +{ + NLA = INT; + } + + +static void act164() +{ + NLA = ID; + } + +static unsigned char shift11[257] = { + 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 1, 2, 27, 27, 3, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 1, 27, 27, 6, 27, 27, 27, + 27, 27, 27, 5, 27, 22, 27, 27, 4, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 27, + 24, 27, 21, 27, 27, 27, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 27, 27, 27, 27, 26, 27, 26, 26, + 26, 9, 10, 8, 26, 26, 7, 26, 26, 12, + 15, 11, 17, 16, 26, 18, 13, 19, 14, 26, + 26, 26, 26, 26, 20, 27, 23, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27 +}; + +#define DfaStates 436 +typedef unsigned short DfaState; + +static DfaState st0[60] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 11, 11, 12, 13, 13, 13, 14, 15, 16, + 17, 11, 11, 18, 11, 11, 19, 11, 11, 19, + 11, 11, 11, 11, 20, 11, 11, 21, 22, 23, + 24, 25, 26, 11, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 11, 11, 19, 436, 436, 436 +}; + +static DfaState st1[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st2[60] = { + 436, 2, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st3[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st4[60] = { + 436, 436, 37, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st5[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st6[60] = { + 436, 436, 436, 436, 436, 38, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st7[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st8[60] = { + 436, 436, 436, 436, 436, 436, 436, 39, 40, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st9[60] = { + 436, 436, 436, 436, 436, 436, 436, 41, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st10[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 42, 43, 43, 44, 43, 43, 43, 436, 436, 436, + 436, 45, 43, 43, 43, 43, 46, 43, 47, 43, + 43, 43, 43, 48, 43, 49, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st11[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st12[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 51, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st13[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 13, 13, 13, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st14[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 52, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st15[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 53, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st16[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st17[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 54, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st18[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 55, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st19[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 56, 56, 56, 56, 56, 56, 56, 436, 436, 436, + 436, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 436, 56, 436, + 436, 436, 436, 56, 436, 436, 436, 436, 436, 436, + 436, 56, 436, 436, 56, 56, 56, 56, 436, 436 +}; + +static DfaState st20[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 57, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st21[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st22[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 58, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 59, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st23[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st24[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st25[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st26[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st27[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 60, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st28[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 61, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st29[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st30[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st31[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 62, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st32[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st33[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st34[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 56, 56, 56, 56, 56, 56, 56, 436, 436, 436, + 436, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 436, 56, 436, + 436, 436, 436, 56, 436, 436, 436, 436, 436, 436, + 436, 63, 436, 436, 56, 56, 56, 56, 436, 436 +}; + +static DfaState st35[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st36[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st37[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st38[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st39[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st40[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st41[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st42[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 64, 43, 65, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st43[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st44[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 66, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st45[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 67, 68, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st46[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 69, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st47[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 70, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st48[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 71, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st49[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 72, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st50[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st51[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 73, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st52[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st53[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st54[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 74, 43, 43, 44, 43, 43, 43, 436, 436, 436, + 436, 45, 43, 43, 43, 43, 46, 43, 47, 43, + 43, 43, 43, 48, 43, 49, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st55[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 75, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st56[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 56, 56, 56, 56, 56, 56, 56, 436, 436, 436, + 436, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 436, 56, 436, + 436, 436, 436, 56, 436, 436, 436, 436, 436, 436, + 436, 56, 436, 436, 56, 56, 56, 56, 436, 436 +}; + +static DfaState st57[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 76, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st58[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 77, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st59[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 78, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st60[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st61[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st62[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st63[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 56, 56, 56, 56, 56, 56, 56, 436, 436, 436, + 436, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 436, 56, 436, + 436, 436, 436, 56, 436, 436, 79, 436, 436, 436, + 436, 56, 436, 436, 56, 56, 56, 56, 436, 436 +}; + +static DfaState st64[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 80, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st65[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 81, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st66[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 82, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st67[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 83, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 84, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st68[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 85, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st69[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 86, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st70[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 87, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st71[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 88, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st72[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 89, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st73[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 90, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st74[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 65, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st75[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 91, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st76[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 92, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st77[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 93, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st78[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 94, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st79[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 95, 96, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st80[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 97, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st81[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 98, 43, 99, 43, 100, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 101, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st82[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 102, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st83[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 103, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st84[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 104, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st85[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 105, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st86[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 106, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st87[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 107, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 108, 43, 43, 436, 109, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st88[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 110, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st89[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 111, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st90[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 112, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st91[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 113, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st92[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 114, 50, 50, 50, 436, 436 +}; + +static DfaState st93[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 115, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st94[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 116, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st95[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 117, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st96[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 118, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st97[60] = { + 436, 119, 120, 121, 122, 122, 122, 122, 122, 122, + 123, 123, 123, 123, 124, 124, 124, 122, 122, 122, + 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 122, 123, 122, + 122, 122, 122, 123, 122, 122, 122, 122, 122, 122, + 122, 123, 122, 122, 123, 123, 123, 123, 122, 436 +}; + +static DfaState st98[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 125, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st99[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 126, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st100[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 127, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st101[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 128, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st102[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 129, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st103[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st104[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 130, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st105[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 131, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st106[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 132, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st107[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 133, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st108[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 134, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st109[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 135, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st110[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 136, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st111[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 137, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st112[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 138, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st113[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 139, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st114[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 140, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st115[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st116[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st117[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st118[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st119[60] = { + 436, 119, 120, 121, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 141, 141, 141, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st120[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st121[60] = { + 436, 436, 142, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st122[60] = { + 436, 122, 120, 121, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st123[60] = { + 436, 122, 120, 121, 122, 122, 122, 122, 122, 122, + 123, 123, 123, 123, 123, 123, 123, 122, 122, 122, + 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 122, 123, 122, + 122, 122, 122, 123, 122, 122, 122, 122, 122, 122, + 122, 123, 122, 122, 123, 123, 123, 123, 122, 436 +}; + +static DfaState st124[60] = { + 436, 143, 144, 145, 122, 122, 146, 122, 122, 122, + 123, 123, 123, 123, 124, 124, 124, 122, 122, 122, + 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 122, 123, 122, + 122, 122, 122, 123, 122, 122, 122, 122, 122, 122, + 122, 123, 122, 122, 123, 123, 123, 123, 122, 436 +}; + +static DfaState st125[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 147, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st126[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 148, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st127[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 149, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st128[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 150, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st129[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 151, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st130[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 152, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st131[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 153, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st132[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 154, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st133[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st134[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 155, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st135[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 156, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st136[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 157, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st137[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st138[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 158, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st139[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st140[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 159, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st141[60] = { + 436, 143, 144, 145, 122, 122, 146, 122, 122, 122, + 122, 122, 122, 122, 141, 141, 141, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st142[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st143[60] = { + 436, 143, 120, 121, 122, 122, 146, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st144[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st145[60] = { + 436, 436, 160, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st146[60] = { + 436, 161, 162, 163, 161, 161, 122, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 436 +}; + +static DfaState st147[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 164, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st148[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 165, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st149[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 166, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st150[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 167, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st151[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 168, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st152[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st153[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st154[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 169, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st155[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 170, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st156[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 171, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st157[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st158[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 172, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st159[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st160[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st161[60] = { + 436, 161, 162, 163, 161, 161, 173, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 436 +}; + +static DfaState st162[60] = { + 436, 174, 174, 174, 174, 174, 175, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 436 +}; + +static DfaState st163[60] = { + 436, 174, 176, 174, 174, 174, 175, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 436 +}; + +static DfaState st164[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 177, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st165[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 178, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st166[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 179, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st167[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 180, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st168[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 181, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st169[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 182, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st170[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st171[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 183, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st172[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 184, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st173[60] = { + 436, 185, 144, 145, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 186, 186, 186, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st174[60] = { + 436, 174, 174, 174, 174, 174, 175, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 436 +}; + +static DfaState st175[60] = { + 436, 187, 188, 189, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 190, 190, 190, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st176[60] = { + 436, 174, 174, 174, 174, 174, 175, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 436 +}; + +static DfaState st177[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 191, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st178[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 192, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st179[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 193, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st180[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st181[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st182[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 194, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st183[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st184[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st185[60] = { + 436, 185, 144, 145, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 186, 186, 186, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st186[60] = { + 436, 185, 144, 145, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 186, 186, 186, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st187[60] = { + 436, 187, 188, 189, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 190, 190, 190, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st188[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st189[60] = { + 436, 436, 195, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st190[60] = { + 436, 187, 188, 189, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 190, 190, 190, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st191[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st192[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st193[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st194[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 196, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st195[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st196[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 197, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st197[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 198, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st198[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 199, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st199[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 200, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st200[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st201[7] = { + 202, 203, 204, 205, 206, 207, 436 +}; + +static DfaState st202[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st203[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st204[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st205[7] = { + 436, 436, 208, 436, 436, 436, 436 +}; + +static DfaState st206[7] = { + 436, 209, 210, 211, 209, 209, 436 +}; + +static DfaState st207[7] = { + 436, 436, 436, 436, 436, 207, 436 +}; + +static DfaState st208[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st209[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st210[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st211[7] = { + 436, 436, 212, 436, 436, 436, 436 +}; + +static DfaState st212[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st213[7] = { + 214, 215, 216, 217, 218, 219, 436 +}; + +static DfaState st214[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st215[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st216[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st217[7] = { + 436, 436, 220, 436, 436, 436, 436 +}; + +static DfaState st218[7] = { + 436, 221, 222, 223, 221, 221, 436 +}; + +static DfaState st219[7] = { + 436, 436, 436, 436, 436, 219, 436 +}; + +static DfaState st220[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st221[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st222[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st223[7] = { + 436, 436, 224, 436, 436, 436, 436 +}; + +static DfaState st224[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st225[7] = { + 226, 227, 228, 229, 230, 231, 436 +}; + +static DfaState st226[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st227[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st228[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st229[7] = { + 436, 436, 232, 436, 436, 436, 436 +}; + +static DfaState st230[7] = { + 436, 233, 233, 233, 233, 233, 436 +}; + +static DfaState st231[7] = { + 436, 436, 436, 436, 436, 231, 436 +}; + +static DfaState st232[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st233[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st234[7] = { + 235, 236, 237, 238, 239, 237, 436 +}; + +static DfaState st235[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st236[7] = { + 436, 436, 240, 436, 436, 436, 436 +}; + +static DfaState st237[7] = { + 436, 436, 237, 436, 436, 237, 436 +}; + +static DfaState st238[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st239[7] = { + 436, 436, 436, 241, 436, 436, 436 +}; + +static DfaState st240[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st241[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st242[7] = { + 243, 244, 245, 246, 247, 245, 436 +}; + +static DfaState st243[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st244[7] = { + 436, 436, 248, 436, 436, 436, 436 +}; + +static DfaState st245[7] = { + 436, 436, 245, 436, 436, 245, 436 +}; + +static DfaState st246[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st247[7] = { + 436, 436, 436, 249, 436, 436, 436 +}; + +static DfaState st248[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st249[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st250[5] = { + 251, 252, 253, 254, 436 +}; + +static DfaState st251[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st252[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st253[5] = { + 436, 255, 436, 436, 436 +}; + +static DfaState st254[5] = { + 436, 436, 436, 254, 436 +}; + +static DfaState st255[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st256[5] = { + 257, 258, 259, 260, 436 +}; + +static DfaState st257[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st258[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st259[5] = { + 436, 261, 436, 436, 436 +}; + +static DfaState st260[5] = { + 436, 436, 436, 260, 436 +}; + +static DfaState st261[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st262[5] = { + 263, 264, 265, 266, 436 +}; + +static DfaState st263[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st264[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st265[5] = { + 436, 267, 436, 436, 436 +}; + +static DfaState st266[5] = { + 436, 436, 436, 266, 436 +}; + +static DfaState st267[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st268[7] = { + 269, 270, 271, 272, 273, 271, 436 +}; + +static DfaState st269[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st270[7] = { + 436, 436, 274, 436, 436, 436, 436 +}; + +static DfaState st271[7] = { + 436, 436, 271, 436, 436, 271, 436 +}; + +static DfaState st272[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st273[7] = { + 436, 436, 436, 275, 436, 436, 436 +}; + +static DfaState st274[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st275[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st276[36] = { + 277, 278, 279, 280, 281, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 282, 279, 279, 283, 284, + 285, 286, 287, 279, 279, 279, 279, 288, 289, 290, + 291, 292, 293, 279, 279, 436 +}; + +static DfaState st277[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st278[36] = { + 436, 294, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st279[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st280[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st281[36] = { + 436, 436, 279, 436, 279, 295, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st282[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st283[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st284[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st285[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 296, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st286[36] = { + 436, 436, 436, 436, 297, 297, 297, 297, 297, 297, + 297, 297, 297, 297, 297, 436, 436, 436, 436, 436, + 436, 298, 299, 300, 300, 436, 297, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st287[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st288[36] = { + 436, 436, 436, 436, 301, 301, 301, 301, 301, 301, + 301, 301, 301, 301, 302, 303, 436, 436, 436, 436, + 436, 436, 304, 305, 306, 436, 301, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st289[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st290[36] = { + 436, 307, 308, 309, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 310, 311, + 312, 313, 308, 308, 308, 308, 308, 314, 308, 308, + 308, 308, 308, 308, 308, 436 +}; + +static DfaState st291[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st292[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 315, 316, 436, 436, 436 +}; + +static DfaState st293[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 317, 279, 279, 279, 436 +}; + +static DfaState st294[36] = { + 436, 436, 318, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st295[36] = { + 436, 436, 279, 436, 279, 279, 319, 279, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st296[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st297[36] = { + 436, 436, 436, 436, 320, 320, 320, 320, 320, 320, + 320, 320, 320, 320, 320, 436, 436, 436, 436, 436, + 436, 436, 436, 320, 320, 436, 320, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st298[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st299[36] = { + 436, 436, 436, 321, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st300[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 300, 300, 322, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st301[36] = { + 436, 436, 436, 436, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 436, 436, 436, 436, 436, + 436, 436, 436, 323, 323, 436, 323, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st302[36] = { + 436, 436, 436, 436, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 324, 323, 436, 436, 436, 436, 436, + 436, 436, 436, 323, 323, 436, 323, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st303[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 325, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st304[36] = { + 436, 436, 436, 326, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st305[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 306, 306, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st306[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 306, 306, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st307[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st308[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st309[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st310[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st311[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st312[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 327, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st313[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st314[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st315[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st316[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st317[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st318[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st319[36] = { + 436, 436, 279, 436, 279, 279, 279, 328, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st320[36] = { + 436, 436, 436, 436, 320, 320, 320, 320, 320, 320, + 320, 320, 320, 320, 320, 436, 436, 436, 436, 436, + 436, 436, 436, 320, 320, 436, 320, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st321[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st322[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 329, 329, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st323[36] = { + 436, 436, 436, 436, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 436, 436, 436, 436, 436, + 436, 436, 436, 323, 323, 436, 323, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st324[36] = { + 436, 436, 436, 436, 323, 323, 330, 323, 323, 323, + 323, 323, 323, 323, 323, 436, 436, 436, 436, 436, + 436, 436, 436, 323, 323, 436, 323, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st325[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st326[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st327[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st328[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 331, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st329[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 329, 329, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st330[36] = { + 436, 436, 436, 436, 323, 323, 323, 323, 323, 323, + 332, 323, 323, 323, 323, 436, 436, 436, 436, 436, + 436, 436, 436, 323, 323, 436, 323, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st331[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 333, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st332[36] = { + 436, 334, 334, 334, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 334, 336, 334, 334, 337, + 338, 334, 334, 339, 339, 334, 335, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st333[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 340, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st334[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 337, + 338, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st335[36] = { + 436, 334, 334, 334, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 334, 334, 334, 334, 337, + 338, 334, 334, 335, 335, 334, 335, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st336[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 336, 334, 334, 337, + 338, 334, 334, 341, 341, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st337[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st338[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 342, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st339[36] = { + 436, 334, 334, 334, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 334, 343, 334, 334, 344, + 345, 334, 334, 339, 339, 334, 335, 334, 346, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st340[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 347, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st341[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 343, 334, 334, 344, + 345, 334, 334, 341, 341, 334, 334, 334, 346, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st342[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st343[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 343, 334, 334, 337, + 338, 334, 334, 334, 334, 334, 334, 334, 346, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st344[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st345[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 348, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st346[36] = { + 436, 349, 349, 349, 349, 349, 349, 349, 349, 349, + 349, 349, 349, 349, 349, 349, 349, 349, 349, 350, + 351, 349, 349, 349, 349, 349, 349, 349, 334, 349, + 349, 349, 349, 349, 349, 436 +}; + +static DfaState st347[36] = { + 436, 436, 279, 436, 279, 279, 352, 279, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st348[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st349[36] = { + 436, 349, 349, 349, 349, 349, 349, 349, 349, 349, + 349, 349, 349, 349, 349, 349, 349, 349, 349, 350, + 351, 349, 349, 349, 349, 349, 349, 349, 353, 349, + 349, 349, 349, 349, 349, 436 +}; + +static DfaState st350[36] = { + 436, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 355, 354, + 354, 354, 354, 354, 354, 436 +}; + +static DfaState st351[36] = { + 436, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 354, 356, + 354, 354, 354, 354, 354, 354, 354, 354, 355, 354, + 354, 354, 354, 354, 354, 436 +}; + +static DfaState st352[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 357, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st353[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 358, 334, 334, 344, + 345, 334, 334, 359, 359, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st354[36] = { + 436, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 355, 354, + 354, 354, 354, 354, 354, 436 +}; + +static DfaState st355[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 360, 436, 436, 361, + 362, 436, 436, 363, 363, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st356[36] = { + 436, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 355, 354, + 354, 354, 354, 354, 354, 436 +}; + +static DfaState st357[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 364, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st358[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 358, 334, 334, 344, + 345, 334, 334, 359, 359, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st359[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 358, 334, 334, 344, + 345, 334, 334, 359, 359, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st360[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 360, 436, 436, 361, + 362, 436, 436, 363, 363, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st361[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st362[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 365, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st363[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 360, 436, 436, 361, + 362, 436, 436, 363, 363, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st364[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 366, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st365[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st366[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 367, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st367[36] = { + 436, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 369, 370, 436, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 436 +}; + +static DfaState st368[36] = { + 436, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 371, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 436 +}; + +static DfaState st369[36] = { + 436, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 369, 370, 371, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 436 +}; + +static DfaState st370[36] = { + 436, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 373, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 368, 436 +}; + +static DfaState st371[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st372[36] = { + 436, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 373, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 374, 436 +}; + +static DfaState st373[36] = { + 436, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 376, 436 +}; + +static DfaState st374[36] = { + 436, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 377, 368, 378, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 436 +}; + +static DfaState st375[36] = { + 436, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 376, 436 +}; + +static DfaState st376[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 379, 436, 380, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st377[36] = { + 436, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 377, 368, 378, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 436 +}; + +static DfaState st378[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st379[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 379, 436, 380, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st380[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st381[28] = { + 382, 383, 384, 385, 386, 436, 387, 388, 388, 388, + 389, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 390, 391, 392, 393, 394, 395, 388, 436 +}; + +static DfaState st382[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st383[28] = { + 436, 383, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st384[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st385[28] = { + 436, 436, 396, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st386[28] = { + 436, 436, 436, 436, 397, 398, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st387[28] = { + 436, 436, 436, 436, 436, 436, 436, 399, 436, 400, + 401, 436, 436, 436, 402, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st388[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st389[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 404, 403, 403, 403, 403, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st390[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st391[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st392[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st393[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st394[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st395[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 395, 436, 436 +}; + +static DfaState st396[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st397[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st398[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st399[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 405, 436, + 436, 436, 436, 436, 436, 406, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st400[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 407, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st401[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 408, 409, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st402[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 410, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st403[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st404[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 403, 403, 403, 411, 403, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st405[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 412, + 436, 413, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st406[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 414, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st407[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 415, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st408[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 416, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st409[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 417, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st410[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 418, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st411[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 403, 403, 403, 403, 419, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st412[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 420, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st413[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 421, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st414[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 422, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st415[28] = { + 436, 436, 436, 436, 436, 436, 436, 423, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st416[28] = { + 436, 436, 436, 436, 436, 436, 436, 424, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st417[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 425, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st418[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 426, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st419[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st420[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 427, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st421[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 428, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st422[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 429, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st423[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 430, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st424[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 431, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st425[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st426[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 432, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st427[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st428[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 433, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st429[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 434, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st430[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 435, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st431[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st432[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st433[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st434[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st435[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + + +DfaState *dfa[436] = { + st0, + st1, + st2, + st3, + st4, + st5, + st6, + st7, + st8, + st9, + st10, + st11, + st12, + st13, + st14, + st15, + st16, + st17, + st18, + st19, + st20, + st21, + st22, + st23, + st24, + st25, + st26, + st27, + st28, + st29, + st30, + st31, + st32, + st33, + st34, + st35, + st36, + st37, + st38, + st39, + st40, + st41, + st42, + st43, + st44, + st45, + st46, + st47, + st48, + st49, + st50, + st51, + st52, + st53, + st54, + st55, + st56, + st57, + st58, + st59, + st60, + st61, + st62, + st63, + st64, + st65, + st66, + st67, + st68, + st69, + st70, + st71, + st72, + st73, + st74, + st75, + st76, + st77, + st78, + st79, + st80, + st81, + st82, + st83, + st84, + st85, + st86, + st87, + st88, + st89, + st90, + st91, + st92, + st93, + st94, + st95, + st96, + st97, + st98, + st99, + st100, + st101, + st102, + st103, + st104, + st105, + st106, + st107, + st108, + st109, + st110, + st111, + st112, + st113, + st114, + st115, + st116, + st117, + st118, + st119, + st120, + st121, + st122, + st123, + st124, + st125, + st126, + st127, + st128, + st129, + st130, + st131, + st132, + st133, + st134, + st135, + st136, + st137, + st138, + st139, + st140, + st141, + st142, + st143, + st144, + st145, + st146, + st147, + st148, + st149, + st150, + st151, + st152, + st153, + st154, + st155, + st156, + st157, + st158, + st159, + st160, + st161, + st162, + st163, + st164, + st165, + st166, + st167, + st168, + st169, + st170, + st171, + st172, + st173, + st174, + st175, + st176, + st177, + st178, + st179, + st180, + st181, + st182, + st183, + st184, + st185, + st186, + st187, + st188, + st189, + st190, + st191, + st192, + st193, + st194, + st195, + st196, + st197, + st198, + st199, + st200, + st201, + st202, + st203, + st204, + st205, + st206, + st207, + st208, + st209, + st210, + st211, + st212, + st213, + st214, + st215, + st216, + st217, + st218, + st219, + st220, + st221, + st222, + st223, + st224, + st225, + st226, + st227, + st228, + st229, + st230, + st231, + st232, + st233, + st234, + st235, + st236, + st237, + st238, + st239, + st240, + st241, + st242, + st243, + st244, + st245, + st246, + st247, + st248, + st249, + st250, + st251, + st252, + st253, + st254, + st255, + st256, + st257, + st258, + st259, + st260, + st261, + st262, + st263, + st264, + st265, + st266, + st267, + st268, + st269, + st270, + st271, + st272, + st273, + st274, + st275, + st276, + st277, + st278, + st279, + st280, + st281, + st282, + st283, + st284, + st285, + st286, + st287, + st288, + st289, + st290, + st291, + st292, + st293, + st294, + st295, + st296, + st297, + st298, + st299, + st300, + st301, + st302, + st303, + st304, + st305, + st306, + st307, + st308, + st309, + st310, + st311, + st312, + st313, + st314, + st315, + st316, + st317, + st318, + st319, + st320, + st321, + st322, + st323, + st324, + st325, + st326, + st327, + st328, + st329, + st330, + st331, + st332, + st333, + st334, + st335, + st336, + st337, + st338, + st339, + st340, + st341, + st342, + st343, + st344, + st345, + st346, + st347, + st348, + st349, + st350, + st351, + st352, + st353, + st354, + st355, + st356, + st357, + st358, + st359, + st360, + st361, + st362, + st363, + st364, + st365, + st366, + st367, + st368, + st369, + st370, + st371, + st372, + st373, + st374, + st375, + st376, + st377, + st378, + st379, + st380, + st381, + st382, + st383, + st384, + st385, + st386, + st387, + st388, + st389, + st390, + st391, + st392, + st393, + st394, + st395, + st396, + st397, + st398, + st399, + st400, + st401, + st402, + st403, + st404, + st405, + st406, + st407, + st408, + st409, + st410, + st411, + st412, + st413, + st414, + st415, + st416, + st417, + st418, + st419, + st420, + st421, + st422, + st423, + st424, + st425, + st426, + st427, + st428, + st429, + st430, + st431, + st432, + st433, + st434, + st435 +}; + + +DfaState accepts[437] = { + 0, 1, 2, 3, 3, 4, 25, 6, 0, 50, + 59, 57, 57, 43, 26, 13, 14, 0, 57, 58, + 57, 21, 57, 23, 24, 27, 28, 44, 0, 35, + 36, 42, 45, 46, 58, 51, 52, 3, 5, 9, + 7, 8, 59, 59, 59, 59, 59, 59, 59, 59, + 57, 57, 12, 40, 59, 57, 58, 57, 57, 57, + 33, 34, 53, 58, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 57, 59, 57, 57, 57, 57, 0, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 57, 57, 57, 57, 57, 0, 0, 59, 59, 59, + 59, 59, 59, 32, 59, 59, 59, 59, 59, 59, + 59, 59, 57, 57, 57, 22, 56, 48, 49, 0, + 11, 11, 0, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 41, 59, 59, 59, 18, 57, 47, + 57, 0, 11, 0, 10, 10, 0, 59, 59, 59, + 59, 59, 15, 19, 59, 59, 59, 17, 57, 55, + 10, 0, 11, 11, 59, 59, 59, 59, 59, 59, + 20, 59, 57, 0, 0, 0, 11, 59, 59, 59, + 37, 38, 59, 39, 54, 0, 0, 0, 10, 10, + 0, 31, 29, 30, 59, 10, 59, 59, 59, 59, + 16, 0, 60, 61, 62, 62, 0, 65, 62, 64, + 63, 63, 63, 0, 66, 67, 68, 68, 0, 71, + 68, 70, 69, 69, 69, 0, 72, 73, 74, 74, + 0, 76, 74, 75, 0, 77, 79, 81, 80, 80, + 78, 80, 0, 82, 84, 86, 85, 85, 83, 85, + 0, 87, 88, 88, 89, 88, 0, 90, 91, 91, + 92, 91, 0, 93, 94, 94, 95, 94, 0, 96, + 98, 100, 99, 99, 97, 99, 0, 101, 108, 143, + 104, 143, 129, 127, 107, 107, 109, 128, 126, 134, + 0, 133, 139, 143, 102, 143, 107, 116, 110, 112, + 113, 123, 123, 125, 124, 117, 120, 132, 138, 130, + 131, 137, 137, 135, 136, 142, 140, 141, 103, 143, + 116, 111, 114, 123, 123, 119, 118, 137, 143, 115, + 123, 143, 123, 143, 0, 123, 0, 122, 122, 123, + 143, 0, 122, 0, 121, 121, 0, 143, 121, 0, + 122, 122, 143, 0, 0, 0, 122, 143, 0, 0, + 0, 121, 121, 0, 143, 121, 143, 0, 0, 0, + 0, 106, 0, 106, 0, 0, 0, 0, 105, 0, + 105, 0, 144, 145, 146, 146, 0, 0, 164, 164, + 158, 159, 160, 161, 162, 163, 146, 147, 148, 0, + 0, 0, 0, 164, 164, 150, 0, 0, 0, 0, + 0, 164, 0, 0, 0, 0, 0, 0, 0, 157, + 0, 0, 0, 0, 0, 152, 0, 149, 0, 0, + 0, 153, 154, 151, 155, 156, 0 +}; + +void (*actions[165])() = { + zzerraction, + act1, + act2, + act3, + act4, + act5, + act6, + act7, + act8, + act9, + act10, + act11, + act12, + act13, + act14, + act15, + act16, + act17, + act18, + act19, + act20, + act21, + act22, + act23, + act24, + act25, + act26, + act27, + act28, + act29, + act30, + act31, + act32, + act33, + act34, + act35, + act36, + act37, + act38, + act39, + act40, + act41, + act42, + act43, + act44, + act45, + act46, + act47, + act48, + act49, + act50, + act51, + act52, + act53, + act54, + act55, + act56, + act57, + act58, + act59, + act60, + act61, + act62, + act63, + act64, + act65, + act66, + act67, + act68, + act69, + act70, + act71, + act72, + act73, + act74, + act75, + act76, + act77, + act78, + act79, + act80, + act81, + act82, + act83, + act84, + act85, + act86, + act87, + act88, + act89, + act90, + act91, + act92, + act93, + act94, + act95, + act96, + act97, + act98, + act99, + act100, + act101, + act102, + act103, + act104, + act105, + act106, + act107, + act108, + act109, + act110, + act111, + act112, + act113, + act114, + act115, + act116, + act117, + act118, + act119, + act120, + act121, + act122, + act123, + act124, + act125, + act126, + act127, + act128, + act129, + act130, + act131, + act132, + act133, + act134, + act135, + act136, + act137, + act138, + act139, + act140, + act141, + act142, + act143, + act144, + act145, + act146, + act147, + act148, + act149, + act150, + act151, + act152, + act153, + act154, + act155, + act156, + act157, + act158, + act159, + act160, + act161, + act162, + act163, + act164 +}; + +static DfaState dfa_base[] = { + 0, + 201, + 213, + 225, + 234, + 242, + 250, + 256, + 262, + 268, + 276, + 381 +}; + +static unsigned char *b_class_no[] = { + shift0, + shift1, + shift2, + shift3, + shift4, + shift5, + shift6, + shift7, + shift8, + shift9, + shift10, + shift11 +}; + + + +#define ZZSHIFT(c) (b_class_no[zzauto][1+c]) +#define MAX_MODE 12 +#include "dlgauto.h" diff --git a/Tools/Source/TianoTools/Pccts/antlr/stdpccts.h b/Tools/Source/TianoTools/Pccts/antlr/stdpccts.h new file mode 100644 index 0000000000..ccdc21c3c9 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/stdpccts.h @@ -0,0 +1,31 @@ +#ifndef STDPCCTS_H +#define STDPCCTS_H +/* + * stdpccts.h -- P C C T S I n c l u d e + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#ifndef ANTLR_VERSION +#define ANTLR_VERSION 13333 +#endif + +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include "pcctscfg.h" +#include "set.h" +#include +#include "syn.h" +#include "hash.h" +#include "generic.h" +#define zzcr_attr(attr,tok,t) +#define zzSET_SIZE 20 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "mode.h" +#endif diff --git a/Tools/Source/TianoTools/Pccts/antlr/syn.h b/Tools/Source/TianoTools/Pccts/antlr/syn.h new file mode 100644 index 0000000000..a23d196d77 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/syn.h @@ -0,0 +1,390 @@ +/* + * syn.h + * + * This file includes definitions and macros associated with syntax diagrams + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include "set.h" + +#define NumNodeTypes 4 +#define NumJuncTypes 9 + +/* List the different node types */ +#define nJunction 1 +#define nRuleRef 2 +#define nToken 3 +#define nAction 4 + +/* Different types of junctions */ +#define aSubBlk 1 +#define aOptBlk 2 +#define aLoopBlk 3 +#define EndBlk 4 +#define RuleBlk 5 +#define Generic 6 /* just a junction--no unusual characteristics */ +#define EndRule 7 +#define aPlusBlk 8 +#define aLoopBegin 9 + +typedef int NodeType; + +#define TreeBlockAllocSize 500 +#define JunctionBlockAllocSize 200 +#define ActionBlockAllocSize 50 +#define RRefBlockAllocSize 100 +#define TokenBlockAllocSize 100 + +#ifdef __cplusplus +class ActionNode; +class Junction; +#endif + +/* note that 'right' is used by the tree node allocator as a ptr for linked list */ +typedef struct _tree { + struct _tree *down, *right; + int token; + union { + int rk; /* if token==EpToken, => how many more tokens req'd */ + struct _tree *tref; /* if token==TREE_REF */ + set sref; /* if token==SET */ + } v; +#ifdef TREE_DEBUG + int in_use; + int seq; +#endif + } Tree; + + +/* a predicate is defined to be a predicate action and a token tree with + * context info (if used); later, this struct may include the + * "hoisting distance" when we hoist past tokens. + * + * A tree is used to indicate && vs || + * + * p + * | + * q--r + * + * indicates p && (q||r). + * + * If expr is PRED_AND_LIST or PRED_OR_LIST, then it's an operation node + * and indicates the start of an && or || list. + */ + +typedef struct _Predicate { + struct _Predicate *down, *right; /* these have to be first */ + struct _Predicate *up, *left; /* doubly-link me */ + char *expr; + Tree *tcontext; /* used if lookahead depth of > one is needed (tree) */ + int k; /* lookahead depth for this tcontext */ + set scontext[2];/* used if lookahead depth of one is needed (set) */ + /* scontext[0] is not used; only needed so genExprSets() + routine works (it expects an array) + */ + set completionTree; /* which lookahead depths are required to complete tcontext? */ + set completionSet; /* MR10 separate completion set for sets and trees */ + struct _PredEntry *predEntry; /* MR11 */ + +#ifdef __cplusplus + ActionNode *source; /* where did this predicate come from? */ +#else + struct _anode *source; /* where did this predicate come from? */ +#endif + + char cloned; /* MR10 don't want to free original guard pred */ + char redundant; /* MR10 predicate tree simplification */ + char ampersandStyle; /* MR10 (g)? && <

>? */ + char inverted; /* MR11 ! predName */ + char isConst; /* MR11 */ + char constValue; /* MR11 */ + char conflictReported; /* MR11 */ + + set plainSet; /* MR12b */ + + /*** remember to change new_predicate() and predicate_dup() when changing this ***/ + +} Predicate; + +typedef struct _ExceptionHandler { + char *signalname; + char *action; + } ExceptionHandler; + +typedef struct _ExceptionGroup { + struct _ListNode *handlers; /* list of ExceptionHandler's */ + char *label; /* label==""; implies not attached to any + * particular rule ref. + */ + char *altID; /* which alt did it come from (blk#:alt#) */ + + struct _ExceptionGroup *pendingLink; /* for alternative EG MR7 */ + struct _ExceptionGroup *outerEG; /* for alternative EG MR7 */ + struct _LabelEntry *labelEntry; /* for alternative EG MR7 */ + int forRule; /* MR7 */ + int used; /* MR7 */ + } ExceptionGroup ; + + +#define TokenString(_i) ((TokenInd!=NULL)?TokenStr[TokenInd[_i]]:TokenStr[_i]) +#define ExprString(_i) ((TokenInd!=NULL)?ExprStr[TokenInd[_i]]:ExprStr[_i]) + + + /* M e s s a g e P a s s i n g T o N o d e s */ + +/* + * assumes a 'Junction *r' exists. This macro calls a function with + * the pointer to the node to operate on and a pointer to the rule + * in which it is enclosed. + */ +#define TRANS(p) {if ( (p)==NULL ) fatal("TRANS: NULL object"); \ + if ( (p)->ntype == nJunction ) (*(fpJTrans[((Junction *)(p))->jtype]))( p );\ + else (*(fpTrans[(p)->ntype]))( p );} + +#define PRINT(p) {if ( (p)==NULL ) fatal("PRINT: NULL object");\ + (*(fpPrint[(p)->ntype]))( p );} + +#define REACH(p,k,rk,a) {if ( (p)==NULL ) fatal("REACH: NULL object");\ + (a) = (*(fpReach[(p)->ntype]))( p, k, rk );} + +#define TRAV(p,k,rk,a) {if ( (p)==NULL ) {\ + if ( ContextGuardTRAV ) (a)=NULL; \ + else fatal("TRAV: NULL object");\ + } \ + else (a) = (*(fpTraverse[(p)->ntype]))( p, k, rk );} + +/** +*** #define TRAV(p,k,rk,a) {if ( (p)==NULL ) fatal("TRAV: NULL object");\ +*** (a) = (*(fpTraverse[(p)->ntype]))( p, k, rk );} +**/ + +/* All syntax diagram nodes derive from Node -- superclass + */ +#ifdef __cplusplus +class Node { +public: + NodeType ntype; + char *rname; /* what rule does this element live in? */ + int file; /* index in FileStr */ + int line; /* line number that element occurs on */ + }; +#else +typedef struct _node { + NodeType ntype; + char *rname; /* what rule does this element live in? */ + int file; /* index in FileStr */ + int line; /* line number that element occurs on */ + } Node; +#endif + +#ifdef __cplusplus +class ActionNode : public Node { +public: +#else +typedef struct _anode { + NodeType ntype; + char *rname; /* what rule does this action live in? */ + int file; /* index in FileStr (name of file with action) */ + int line; /* line number that action occurs on */ +#endif + Node *next; + char *action; + int is_predicate; /* true if action is a <<...>>? predicate action */ + int done; /* don't dump if action dumped (used for predicates) */ + int init_action; /* is this the 1st action of 1st prod of block? */ + char *pred_fail; /* what to do/print when predicate fails */ + Predicate *guardpred; /* if '(context)? =>' was present, already done */ + unsigned char frmwarned;/* have we dumped a warning for pred yet? */ + unsigned char ctxwarned;/* have we dumped a warning for pred yet? */ + unsigned char predTooLong; /* MR10 have we dumped warning for pred yet */ + unsigned char noHoist; /* MR12 literally "noHoist" */ + Predicate *ampersandPred; /* MR10 (g)? && <

>? expr */ +#ifdef __cplusplus + Junction *guardNodes; /* MR11 */ +#else + struct _junct *guardNodes; /* MR11 */ +#endif + struct _PredEntry *predEntry; /* MR11 */ + int inverted; /* MR11 <>? */ +#ifdef __cplusplus + }; +#else + } ActionNode; +#endif + +#ifdef __cplusplus +class TokNode : public Node { +public: +#else +typedef struct _toknode { + NodeType ntype; + char *rname; /* name of rule it's in */ + int file; /* index in FileStr (name of file with rule) */ + int line; /* line number that token occurs on */ +#endif + Node *next; + int token; + int astnode; /* leaf/root/excluded (used to build AST's) */ + unsigned char label;/* token label or expression ? */ + unsigned char remapped; + /* used if token id's are forced to certain positions; + * a function walks the tree reassigning token numbers */ + int upper_range; /* MR13 - was char */ + /* used only if Token is of type T1..T2; in this case, + * use token..upper_range as the range; else + * upper_range must be 0 */ + unsigned char wild_card; + /* indicates that the token is the "." wild-card; + * field token is ignored if wild_card is set + */ + unsigned int elnum; /* element number within the alternative */ +#ifdef __cplusplus + Junction *altstart; /* pointer to node that starts alt */ +#else + struct _junct *altstart; /* pointer to node that starts alt */ +#endif + struct _TCnode *tclass; /* token class if tokclass ref */ + set tset; /* set of tokens represented by meta token */ + char *el_label; /* el_label:toknode */ + unsigned char complement; /* complement the set? */ + ExceptionGroup *ex_group; /* any exception[el_label] attached? */ + unsigned char use_def_MT_handler; + unsigned char label_used_in_semantic_pred; /* MR10 */ +#ifdef __cplusplus + }; +#else + } TokNode; +#endif + +#ifdef __cplusplus +class RuleRefNode : public Node { +public: +#else +typedef struct _rrnode { + NodeType ntype; + char *rname; /* name of rule it's in */ + int file; /* index in FileStr (name of file with rule) + it's in */ + int line; /* line number that rule ref occurs on */ +#endif + Node *next; + char *text; /* reference to which rule */ + char *parms; /* point to parameters of rule invocation + (if present) */ + char *assign; /* point to left-hand-side of assignment + (if any) */ + int linked; /* Has a FoLink already been established? */ + int astnode; /* excluded? (used to build AST's) */ + unsigned int elnum; /* element number within the alternative */ +#ifdef __cplusplus + Junction *altstart; +#else + struct _junct *altstart; +#endif + char *el_label; /* el_label:rrnode */ + ExceptionGroup *ex_group; /* any exception[el_label] attached? */ +#ifdef __cplusplus + }; +#else + } RuleRefNode; +#endif + +#ifdef __cplusplus +class Junction : public Node { +public: +#else +typedef struct _junct { + NodeType ntype; + char *rname; /* name of rule junction is in */ + int file; /* index in FileStr (name of file with rule) + if blk == RuleBlk */ + int line; /* line number that rule occurs on */ +#endif + int seq; /* MR10 sequence number */ + char ignore; /* used by FIRST computation to ignore + empty alt added for the (...)+ blks */ + char visited; /* used by recursive routines to avoid + infinite recursion */ + char pvisited; /* used by print routines to avoid + infinite recursion */ + char fvisited; /* used by FoLink() to avoid + infinite recursion */ + char *lock; /* used by REACH to track infinite recursion */ + char *pred_lock; /* used by find_predicates to track infinite recursion */ + int altnum; /* used in subblocks. altnum==0 means not an + alt of subrule */ + int jtype; /* annotation for code-gen/FIRST/FOLLOW. + Junction type */ +#ifdef __cplusplus + Junction *end; /* pointer to node with EndBlk in it + if blk == a block type */ +#else + struct _junct *end; /* pointer to node with EndBlk in it + if blk == a block type */ +#endif + Node *p1, *p2; + char halt; /* never move past a junction with halt==TRUE */ /* MR10 was int */ + char *pdecl; /* point to declaration of parameters on rule + (if present) */ + char *parm; /* point to parameter of block invocation + (if present) */ + char predparm; /* indicates that the 'parm' is a predicate + * to be used in the while loop generated + * for blocks */ /* MR10 was int */ + char *ret; /* point to return type of rule (if present) */ + char *erraction; /* point to error action (if present) */ + int blockid; /* this is a unique ID */ + char *exception_label; /* goto label for this alt */ + set *fset; /* used for code generation */ + Tree *ftree; /* used for code generation */ + Predicate *predicate;/* predicate that can be used to disambiguate */ + char guess; /* true if (...)? block */ + char alpha_beta_guess_end; /* MR14 1 => end block of guess sub block */ + Node *guess_analysis_point; /* MR14 */ + char approx; /* limit block to use linear approx lookahead? */ + set tokrefs; /* if ith element of alt is tokref then i is member */ + set rulerefs; /* if ith element of alt is rule ref then i is member */ + struct _ListNode *exceptions; /* list of exceptions groups for rule */ + struct _ListNode *el_labels; /* list of element labels for rule */ + ExceptionGroup *outerEG; /* MR7 */ + int curAltNum; /* MR7 */ + char* pFirstSetSymbol; /* #pragma FirstSetSymbol(Foo) MR21 */ +#ifdef __cplusplus + Junction *pendingLink; /* MR7 */ +#else + struct _junct *pendingLink; /* MR7 */ +#endif + char overlap_warning; /* MR10 */ +#ifdef __cplusplus + }; +#else + } Junction; +#endif + +typedef struct { Node *left, *right;} Graph; + diff --git a/Tools/Source/TianoTools/Pccts/antlr/tokens.h b/Tools/Source/TianoTools/Pccts/antlr/tokens.h new file mode 100644 index 0000000000..91a53a8471 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/antlr/tokens.h @@ -0,0 +1,246 @@ +#ifndef tokens_h +#define tokens_h +/* tokens.h -- List of labelled tokens and stuff + * + * Generated from: antlr.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * ANTLR Version 1.33MR33 + */ +#define zzEOF_TOKEN 1 +#define Eof 1 +#define QuotedTerm 2 +#define Action 34 +#define Pred 35 +#define PassAction 36 +#define WildCard 87 +#define LABEL 89 +#define Pragma 92 +#define FirstSetSymbol 93 +#define NonTerminal 100 +#define TokenTerm 101 +#define ID 148 +#define INT 150 + +#ifdef __USE_PROTOS +void grammar(void); +#else +extern void grammar(); +#endif + +#ifdef __USE_PROTOS +void class_def(void); +#else +extern void class_def(); +#endif + +#ifdef __USE_PROTOS +void rule(void); +#else +extern void rule(); +#endif + +#ifdef __USE_PROTOS +void laction(void); +#else +extern void laction(); +#endif + +#ifdef __USE_PROTOS +void lmember(void); +#else +extern void lmember(); +#endif + +#ifdef __USE_PROTOS +void lprefix(void); +#else +extern void lprefix(); +#endif + +#ifdef __USE_PROTOS +void aPred(void); +#else +extern void aPred(); +#endif + +#ifdef __USE_PROTOS +extern Predicate * predOrExpr(void); +#else +extern Predicate * predOrExpr(); +#endif + +#ifdef __USE_PROTOS +extern Predicate * predAndExpr(void); +#else +extern Predicate * predAndExpr(); +#endif + +#ifdef __USE_PROTOS +extern Predicate * predPrimary(void); +#else +extern Predicate * predPrimary(); +#endif + +#ifdef __USE_PROTOS +void aLexclass(void); +#else +extern void aLexclass(); +#endif + +#ifdef __USE_PROTOS +void error(void); +#else +extern void error(); +#endif + +#ifdef __USE_PROTOS +void tclass(void); +#else +extern void tclass(); +#endif + +#ifdef __USE_PROTOS +void token(void); +#else +extern void token(); +#endif + +#ifdef __USE_PROTOS +void block(set * toksrefd,set * rulesrefd); +#else +extern void block(); +#endif + +#ifdef __USE_PROTOS +void alt(set * toksrefd,set * rulesrefd); +#else +extern void alt(); +#endif + +#ifdef __USE_PROTOS +extern LabelEntry * element_label(void); +#else +extern LabelEntry * element_label(); +#endif + +#ifdef __USE_PROTOS +extern Node * element(int old_not,int first_on_line,int use_def_MT_handler); +#else +extern Node * element(); +#endif + +#ifdef __USE_PROTOS +void default_exception_handler(void); +#else +extern void default_exception_handler(); +#endif + +#ifdef __USE_PROTOS +extern ExceptionGroup * exception_group(void); +#else +extern ExceptionGroup * exception_group(); +#endif + +#ifdef __USE_PROTOS +extern ExceptionHandler * exception_handler(void); +#else +extern ExceptionHandler * exception_handler(); +#endif + +#ifdef __USE_PROTOS +void enum_file(char * fname); +#else +extern void enum_file(); +#endif + +#ifdef __USE_PROTOS +void defines(char * fname); +#else +extern void defines(); +#endif + +#ifdef __USE_PROTOS +void enum_def(char * fname); +#else +extern void enum_def(); +#endif + +#endif +extern SetWordType zzerr1[]; +extern SetWordType zzerr2[]; +extern SetWordType zzerr3[]; +extern SetWordType zzerr4[]; +extern SetWordType setwd1[]; +extern SetWordType zzerr5[]; +extern SetWordType zzerr6[]; +extern SetWordType zzerr7[]; +extern SetWordType zzerr8[]; +extern SetWordType zzerr9[]; +extern SetWordType setwd2[]; +extern SetWordType zzerr10[]; +extern SetWordType zzerr11[]; +extern SetWordType zzerr12[]; +extern SetWordType zzerr13[]; +extern SetWordType setwd3[]; +extern SetWordType zzerr14[]; +extern SetWordType zzerr15[]; +extern SetWordType zzerr16[]; +extern SetWordType zzerr17[]; +extern SetWordType zzerr18[]; +extern SetWordType zzerr19[]; +extern SetWordType zzerr20[]; +extern SetWordType zzerr21[]; +extern SetWordType setwd4[]; +extern SetWordType zzerr22[]; +extern SetWordType zzerr23[]; +extern SetWordType zzerr24[]; +extern SetWordType zzerr25[]; +extern SetWordType zzerr26[]; +extern SetWordType setwd5[]; +extern SetWordType zzerr27[]; +extern SetWordType zzerr28[]; +extern SetWordType zzerr29[]; +extern SetWordType zzerr30[]; +extern SetWordType zzerr31[]; +extern SetWordType zzerr32[]; +extern SetWordType zzerr33[]; +extern SetWordType setwd6[]; +extern SetWordType zzerr34[]; +extern SetWordType zzerr35[]; +extern SetWordType zzerr36[]; +extern SetWordType zzerr37[]; +extern SetWordType zzerr38[]; +extern SetWordType zzerr39[]; +extern SetWordType zzerr40[]; +extern SetWordType zzerr41[]; +extern SetWordType zzerr42[]; +extern SetWordType setwd7[]; +extern SetWordType zzerr43[]; +extern SetWordType zzerr44[]; +extern SetWordType zzerr45[]; +extern SetWordType zzerr46[]; +extern SetWordType zzerr47[]; +extern SetWordType zzerr48[]; +extern SetWordType zzerr49[]; +extern SetWordType zzerr50[]; +extern SetWordType zzerr51[]; +extern SetWordType zzerr52[]; +extern SetWordType zzerr53[]; +extern SetWordType setwd8[]; +extern SetWordType zzerr54[]; +extern SetWordType zzerr55[]; +extern SetWordType zzerr56[]; +extern SetWordType zzerr57[]; +extern SetWordType setwd9[]; +extern SetWordType zzerr58[]; +extern SetWordType zzerr59[]; +extern SetWordType zzerr60[]; +extern SetWordType zzerr61[]; +extern SetWordType zzerr62[]; +extern SetWordType zzerr63[]; +extern SetWordType zzerr64[]; +extern SetWordType zzerr65[]; +extern SetWordType setwd10[]; +extern SetWordType setwd11[]; diff --git a/Tools/Source/TianoTools/Pccts/build.gcc b/Tools/Source/TianoTools/Pccts/build.gcc new file mode 100644 index 0000000000..06d4800269 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/build.gcc @@ -0,0 +1,2 @@ +(cd antlr/; make -f makefile) +(cd dlg/; make -f makefile) diff --git a/Tools/Source/TianoTools/Pccts/build.xml b/Tools/Source/TianoTools/Pccts/build.xml new file mode 100644 index 0000000000..12a3afadac --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/build.xml @@ -0,0 +1,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/Pccts/dlg/DlgMS.mak b/Tools/Source/TianoTools/Pccts/dlg/DlgMS.mak new file mode 100644 index 0000000000..4a9019b1c6 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/DlgMS.mak @@ -0,0 +1,121 @@ +# PCCTS directory + +# You will need to set the LIB variable similar to this. +# LIB="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/lib;c:/Microsoft Visual Studio .NET 2003/Vc7/PlatformSDK/Lib" + +# PCCTS_HOME= +PCCTS_HOME=$(WORKSPACE)\Tools\Source\TianoTools\Pccts +DLG_SRC=$(PCCTS_HOME)\dlg +PCCTS_H=$(PCCTS_HOME)\h + + +# Support directories +SET=$(PCCTS_HOME)\support\set + + +# Compiler stuff +CC = cl +CFLAGS = /nologo -I "." -I "$(PCCTS_H)" -I "$(SET)" -D "USER_ZZSYN" -D "PC" \ + -D "ZZLEXBUFSIZE=65536" /D "LONGFILENAMES" /W3 /Zi + +DLG_OBJS = dlg_p.obj dlg_a.obj main.obj err.obj support.obj \ + output.obj relabel.obj automata.obj + +SUPPORT_OBJS = set.obj + +# Dependencies + +dlg.exe: $(DLG_OBJS) $(SUPPORT_OBJS) + $(CC) $(CFLAGS) -o dlg.exe $(DLG_OBJS) $(SUPPORT_OBJS) + del *.obj + del *.ilk + del *.pdb + move dlg.exe $(WORKSPACE)\Tools\bin\. + +dlg_p.obj: $(DLG_SRC)\dlg_p.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\mode.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\dlg_p.c + +dlg_a.obj: $(DLG_SRC)\dlg_a.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgauto.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\mode.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\dlg_a.c + +main.obj: $(DLG_SRC)\main.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\mode.h \ + $(DLG_SRC)\stdpccts.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\main.c + +err.obj: $(DLG_SRC)\err.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(PCCTS_H)\err.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\err.c + +support.obj: $(DLG_SRC)\support.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\support.c + +output.obj: $(DLG_SRC)\output.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\output.c + +relabel.obj: $(DLG_SRC)\relabel.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\relabel.c + +automata.obj: $(DLG_SRC)\automata.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\automata.c + + +set.obj: $(SET)\set.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + + $(CC) -c $(CFLAGS) $(SET)\set.c + +clean: + del *.obj + +distclean: + del *.obj + del $(WORKSPACE)\Tools\bin\dlg.exe diff --git a/Tools/Source/TianoTools/Pccts/dlg/DlgPPC.mak b/Tools/Source/TianoTools/Pccts/dlg/DlgPPC.mak new file mode 100644 index 0000000000..55b643ad88 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/DlgPPC.mak @@ -0,0 +1,84 @@ +# File: dlgPPC.make +# Target: dlgPPC +# Sources: automata.c +# dlg_a.c +# dlg_p.c +# err.c +# main.c +# output.c +# relabel.c +# support.c +# ::support:set:set.c +# Created: Sunday, May 17, 1998 11:34:20 PM +# Author: Kenji Tanaka + + +MAKEFILE = dlgPPC.make +Â¥MondoBuildÂ¥ = {MAKEFILE} # Make blank to avoid rebuilds when makefile is modified +Includes = ¶ + -i "::h:" ¶ + -i "::support:set:" +SymÂ¥PPC = +ObjDirÂ¥PPC = ":Obj:" + +PPCCOptions = {Includes} {SymÂ¥PPC} -w off -d MPW -d __STDC__=1 -d USER_ZZSYN + +ObjectsÂ¥PPC = ¶ + "{ObjDirÂ¥PPC}automata.c.x" ¶ + "{ObjDirÂ¥PPC}dlg_a.c.x" ¶ + "{ObjDirÂ¥PPC}dlg_p.c.x" ¶ + "{ObjDirÂ¥PPC}err.c.x" ¶ + "{ObjDirÂ¥PPC}main.c.x" ¶ + "{ObjDirÂ¥PPC}output.c.x" ¶ + "{ObjDirÂ¥PPC}relabel.c.x" ¶ + "{ObjDirÂ¥PPC}support.c.x" ¶ + "{ObjDirÂ¥PPC}set.c.x" + + +dlgPPC ÄÄ {Â¥MondoBuildÂ¥} {ObjectsÂ¥PPC} + PPCLink ¶ + -o {Targ} {SymÂ¥PPC} ¶ + {ObjectsÂ¥PPC} ¶ + -t 'MPST' ¶ + -c 'MPS ' ¶ + "{SharedLibraries}InterfaceLib" ¶ + "{SharedLibraries}StdCLib" ¶ + "{SharedLibraries}MathLib" ¶ + "{PPCLibraries}StdCRuntime.o" ¶ + "{PPCLibraries}PPCCRuntime.o" ¶ + "{PPCLibraries}PPCToolLibs.o" + + +"{ObjDirÂ¥PPC}automata.c.x" Ä {Â¥MondoBuildÂ¥} automata.c + {PPCC} automata.c -o {Targ} {PPCCOptions} + +"{ObjDirÂ¥PPC}dlg_a.c.x" Ä {Â¥MondoBuildÂ¥} dlg_a.c + {PPCC} dlg_a.c -o {Targ} {PPCCOptions} + +"{ObjDirÂ¥PPC}dlg_p.c.x" Ä {Â¥MondoBuildÂ¥} dlg_p.c + {PPCC} dlg_p.c -o {Targ} {PPCCOptions} + +"{ObjDirÂ¥PPC}err.c.x" Ä {Â¥MondoBuildÂ¥} err.c + {PPCC} err.c -o {Targ} {PPCCOptions} + +"{ObjDirÂ¥PPC}main.c.x" Ä {Â¥MondoBuildÂ¥} main.c + {PPCC} main.c -o {Targ} {PPCCOptions} + +"{ObjDirÂ¥PPC}output.c.x" Ä {Â¥MondoBuildÂ¥} output.c + {PPCC} output.c -o {Targ} {PPCCOptions} + +"{ObjDirÂ¥PPC}relabel.c.x" Ä {Â¥MondoBuildÂ¥} relabel.c + {PPCC} relabel.c -o {Targ} {PPCCOptions} + +"{ObjDirÂ¥PPC}support.c.x" Ä {Â¥MondoBuildÂ¥} support.c + {PPCC} support.c -o {Targ} {PPCCOptions} + +"{ObjDirÂ¥PPC}set.c.x" Ä {Â¥MondoBuildÂ¥} "::support:set:set.c" + {PPCC} "::support:set:set.c" -o {Targ} {PPCCOptions} + + +dlgPPC ÄÄ dlg.r + Rez dlg.r -o dlgPPC -a + +Install Ä dlgPPC + Duplicate -y dlgPPC "{MPW}"Tools:dlg diff --git a/Tools/Source/TianoTools/Pccts/dlg/automata.c b/Tools/Source/TianoTools/Pccts/dlg/automata.c new file mode 100644 index 0000000000..d6d5d7809d --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/automata.c @@ -0,0 +1,353 @@ +/* Automata conversion functions for DLG + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "pcctscfg.h" +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#endif /* __STDC__ */ +#endif + +#define hash_list struct _hash_list_ +hash_list{ + hash_list *next; /* next thing in list */ + dfa_node *node; + }; + +int dfa_allocated = 0; /* keeps track of number of dfa nodes */ +dfa_node **dfa_array; /* root of binary tree that stores dfa array */ +dfa_node *dfa_model_node; +hash_list *dfa_hash[HASH_SIZE]; /* used to quickly find */ + /* desired dfa node */ + +void +#ifdef __USE_PROTOS +make_dfa_model_node(int width) +#else +make_dfa_model_node(width) +int width; +#endif +{ + register int i; + dfa_model_node = (dfa_node*) malloc(sizeof(dfa_node) + + sizeof(int)*width); + dfa_model_node->node_no = -1; /* impossible value for real dfa node */ + dfa_model_node->dfa_set = 0; + dfa_model_node->alternatives = FALSE; + dfa_model_node->done = FALSE; + dfa_model_node->nfa_states = empty; + for(i = 0; itrans[i] = NIL_INDEX; + } +} + + +/* adds a new nfa to the binary tree and returns a pointer to it */ +dfa_node * +#ifdef __USE_PROTOS +new_dfa_node(set nfa_states) +#else +new_dfa_node(nfa_states) +set nfa_states; +#endif +{ + register int j; + register dfa_node *t; + static int dfa_size=0; /* elements dfa_array[] can hold */ + + ++dfa_allocated; + if (dfa_size<=dfa_allocated){ + /* need to redo array */ + if (!dfa_array){ + /* need some to do inital allocation */ + dfa_size=dfa_allocated+DFA_MIN; + dfa_array=(dfa_node **) malloc(sizeof(dfa_node*)* + dfa_size); + }else{ + /* need more space */ + dfa_size=2*(dfa_allocated+1); + dfa_array=(dfa_node **) realloc(dfa_array, + sizeof(dfa_node*)*dfa_size); + } + } + /* fill out entry in array */ + t = (dfa_node*) malloc(sizeof(nfa_node)+sizeof(int)*class_no); + *t = *dfa_model_node; + for (j=0; jtrans[j] = NIL_INDEX; + t->node_no = dfa_allocated; + t->nfa_states = set_dup(nfa_states); + dfa_array[dfa_allocated] = t; + return t; +} + + +/* past a pointer to the start start of the nfa graph + * nfa_to_dfa convers this graph to dfa. The function returns + * a pointer to the first dfa state. + * NOTE: The function that prints out the table will have to figure out how + * to find the other dfa states given the first dfa_state and the number of dfa + * nodes allocated + */ +dfa_node ** +#ifdef __USE_PROTOS +nfa_to_dfa(nfa_node *start) +#else +nfa_to_dfa(start) +nfa_node *start; +#endif +{ + register dfa_node *d_state, *trans_d_state; + register int a; + set t; + int last_done; + unsigned *nfa_list; + unsigned *reach_list; + + reach_list = (unsigned *) malloc((2+nfa_allocated)*sizeof(unsigned)); + if (!start) return NULL; + t = set_of(NFA_NO(start)); + _set_pdq(t,reach_list); + closure(&t,reach_list); + /* Make t a dfa state */ + d_state = dfastate(t); + last_done = DFA_NO(d_state); + + do { + /* Mark dfa state x as "done" */ + d_state->done = TRUE; + nfa_list = set_pdq(d_state->nfa_states); + for (a = 0; at, labeled with a */ + d_state->trans[a] = DFA_NO(trans_d_state); + d_state->alternatives = TRUE; + } + } + free(nfa_list); + ++last_done; /* move forward in queue */ + /* And so forth until nothing isn't done */ + d_state = DFA(last_done); + } while (last_done<=dfa_allocated); + + free(reach_list); + set_free(t); + + /* returns pointer to the array that holds the automaton */ + return dfa_array; +} + +void +#ifdef __USE_PROTOS +clear_hash(void) +#else +clear_hash() +#endif +{ + register int i; + + for(i=0; inext; + } + total+=j; + fprintf(f,"bin[%d] has %d\n",i,j); + } + fprintf(f,"total = %d\n",total); +} +#endif + +/* Returns a pointer to a dfa node that has the same nfa nodes in it. + * This may or maynot be a newly created node. + */ +dfa_node * +#ifdef __USE_PROTOS +dfastate(set nfa_states) +#else +dfastate(nfa_states) +set nfa_states; +#endif +{ + register hash_list *p; + int bin; + + /* hash using set and see if it exists */ + bin = set_hash(nfa_states,HASH_SIZE); + p = dfa_hash[bin]; + while(p && !set_equ(nfa_states,(p->node)->nfa_states)){ + p = p->next; + } + if(!p){ + /* next state to add to hash table */ + p = (hash_list*)malloc(sizeof(hash_list)); + p->node = new_dfa_node(nfa_states); + p->next = dfa_hash[bin]; + dfa_hash[bin] = p; + } + return (p->node); +} + + +/* this reach assumes the closure has been done already on set */ +int +#ifdef __USE_PROTOS +reach(unsigned *nfa_list, register int a, unsigned *reach_list) +#else +reach(nfa_list, a, reach_list) +unsigned *nfa_list; +register int a; +unsigned *reach_list; +#endif +{ + register unsigned *e; + register nfa_node *node; + int t=0; + + e = nfa_list; + if (e){ + while (*e != nil){ + node = NFA(*e); + if (set_el(a,node->label)){ + t=1; + *reach_list=NFA_NO(node->trans[0]); + ++reach_list; + } + ++e; + } + } + *reach_list=nil; + return t; +} + +/* finds all the nodes that can be reached by epsilon transitions + from the set of a nodes and returns puts them back in set b */ +set +#ifdef __USE_PROTOS +closure(set *b, unsigned *reach_list) +#else +closure(b, reach_list) +set *b; +unsigned *reach_list; +#endif +{ + register nfa_node *node,*n; /* current node being examined */ + register unsigned *e; + + ++operation_no; +#if 0 + t = e = set_pdq(*b); +#else + e=reach_list; +#endif + while (*e != nil){ + node = NFA(*e); + set_orel(NFA_NO(node),b); + /* mark it done */ + node->nfa_set = operation_no; + if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) && + (n->nfa_set != operation_no)){ + /* put in b */ + set_orel(NFA_NO(n),b); + close1(n,operation_no,b); + } + if ((n=node->trans[1]) != NIL_INDEX && + (n->nfa_set != operation_no)){ + /* put in b */ + set_orel(NFA_NO(node->trans[1]),b); + close1(n,operation_no,b); + } + ++e; + } +#if 0 + free(t); +#endif + return *b; +} + +#ifdef __USE_PROTOS +void close1(nfa_node *node, int o, set *b) +#else +void close1(node,o,b) +nfa_node *node; +int o; /* marker to avoid cycles */ +set *b; +#endif +{ + register nfa_node *n; /* current node being examined */ + + /* mark it done */ + node->nfa_set = o; + if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) && + (n->nfa_set != o)){ + /* put in b */ + set_orel(NFA_NO(n),b); + close1(n,o,b); + } + if ((n=node->trans[1]) != NIL_INDEX && + (n->nfa_set != o)){ + /* put in b */ + set_orel(NFA_NO(node->trans[1]),b); + close1(n,o,b); + } +} diff --git a/Tools/Source/TianoTools/Pccts/dlg/build.xml b/Tools/Source/TianoTools/Pccts/dlg/build.xml new file mode 100644 index 0000000000..74f31b01b4 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/build.xml @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/Pccts/dlg/dlg.1 b/Tools/Source/TianoTools/Pccts/dlg/dlg.1 new file mode 100644 index 0000000000..f68e3ae8a7 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/dlg.1 @@ -0,0 +1,79 @@ +.TH dlg 1 "April 1994" "DLG" "PCCTS Manual Pages" +.SH NAME +dlg \- DFA Lexical Analyzer Generator +.SH SYNTAX +.LP +\fBdlg\fR [\fIoptions\fR] \fIlexical_spec\fR [\fIoutput_file\fR] +.SH DESCRIPTION +.B dlg +is a tool that produces fast deterministic finite automata for recognizing +regular expressions in input. +.SH OPTIONS +.IP "\fB-CC\fR" +Generate C++ output. The \fIoutput_file\fP is not specified in this +case. +.IP "\fB-C\fR[\fP level\fR] +Where \fPlevel\fR is the compression level used. 0 indications no +compression, 1 removes all unused characters from the transition from table, +and 2 maps equivalent characters into the same character classes. It is +suggested that level -C2 is used, since it will significantly reduce the size +of the dfa produced for lexical analyzer. +.IP "\fB-m\fP +Produces the header file for the lexical mode with a name other than +the default name of "mode.h". +.IP \fB-i\fP +An interactive, or as interactive as possible, parser is produced. A character +is only obtained when required to decide which state to go to. Some care +must be taken to obtain accept states that do not require look ahead at the +next character to determine if that is the stop state. Any regular expression +with a Kleene closure at the end is guaranteed to require another character +of look ahead. +.IP "\fB-cl\fP class +Specify a class name for DLG to generate. The default is DLGLexer. +'class' will be a subclass of DLGLexerBase; only used for -CC. +.IP \fB-ci\fP +The automaton will treat upper and lower case characters identically. +This is accomplished in the automaton; the characters in the lexical +buffer are unmodified. +.IP \fB-cs\fP +Upper and lower case characters are treated as distinct. This is the +default. +.IP "\fB-o\fP dir +Directory where output files should go (default="."). This is very +nice for keeping the source directory clear of ANTLR and DLG spawn. +.IP \fB-Wambiguity\fP +Warns if more than one regular expression could match the same character +sequence. The warnings give the numbers of the expressions in the dlg +lexical specification file. The numbering of the expressions starts at one. +Multiple warnings may be print for the same expressions. +.IP \- +Used in place of file names to get input from standard in or send output +to standard out. +.SH "SPECIAL CONSIDERATIONS" +.PP +\fIDlg\fP works... we think. There is no implicit guarantee of +anything. We reserve no \fBlegal\fP rights to the software known as +the Purdue Compiler Construction Tool Set (PCCTS) \(em PCCTS is in the +public domain. An individual or company may do whatever they wish +with source code distributed with PCCTS or the code generated by +PCCTS, including the incorporation of PCCTS, or its output, into +commercial software. We encourage users to develop software with +PCCTS. However, we do ask that credit is given to us for developing +PCCTS. By "credit", we mean that if you incorporate our source code +into one of your programs (commercial product, research project, or +otherwise) that you acknowledge this fact somewhere in the +documentation, research report, etc... If you like PCCTS and have +developed a nice tool with the output, please mention that you +developed it using PCCTS. As long as these guidelines are followed, we +expect to continue enhancing this system and expect to make other +tools available as they are completed. +.SH FILES +.B mode.h +, +.B dlgauto.h +, +.B dlgdef.h +.SH SEE ALSO +.BR antlr (1), +.BR pccts (1) +.SH BUGS diff --git a/Tools/Source/TianoTools/Pccts/dlg/dlg.h b/Tools/Source/TianoTools/Pccts/dlg/dlg.h new file mode 100644 index 0000000000..9f387c0a1c --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/dlg.h @@ -0,0 +1,250 @@ +/* dlg header file + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-2001 + */ + +/* MR1 Move pcctscfg.h to top of file */ + +#include "pcctscfg.h" + +/* turn off warnings for unreferenced labels */ + +#ifdef _MSC_VER +#pragma warning(disable:4102) +#endif + +#include "set.h" + +#define TRUE 1 +#define FALSE 0 + +/***** output related stuff *******************/ +#define IN input_stream +#define OUT output_stream + +#define MAX_MODES 50 /* number of %%names allowed */ +#define MAX_ON_LINE 10 + +#define NFA_MIN 64 /* minimum nfa_array size */ +#define DFA_MIN 64 /* minimum dfa_array size */ + +#define DEFAULT_CLASSNAME "DLGLexer" + +/* these macros allow the size of the character set to be easily changed */ +/* NOTE: do NOT change MIN_CHAR since EOF is the lowest char, -1 */ +#define MIN_CHAR (-1) /* lowest possible character possible on input */ +#define MAX_CHAR 255 /* highest possible character possible on input */ +#define CHAR_RANGE (1+(MAX_CHAR) - (MIN_CHAR)) + +/* indicates that the not an "array" reference */ +#define NIL_INDEX 0 + +/* size of hash table used to find dfa_states quickly */ +#define HASH_SIZE 211 + +#define nfa_node struct _nfa_node +nfa_node { + int node_no; + int nfa_set; + int accept; /* what case to use */ + nfa_node *trans[2]; + set label; /* one arc always labelled with epsilon */ +}; + +#define dfa_node struct _dfa_node +dfa_node { + int node_no; + int dfa_set; + int alternatives; /* used for interactive mode */ + /* are more characters needed */ + int done; + set nfa_states; + int trans[1];/* size of transition table depends on + * number of classes required for automata. + */ + + +}; + +/******** macros for accessing the NFA and DFA nodes ****/ +#define NFA(x) (nfa_array[x]) +#define DFA(x) (dfa_array[x]) +#define DFA_NO(x) ( (x) ? (x)->node_no : NIL_INDEX) +#define NFA_NO(x) ( (x) ? (x)->node_no : NIL_INDEX) + +/******** wrapper for memory checking ***/ +/*#define malloc(x) dlg_malloc((x),__FILE__,__LINE__)*/ + +/*#define calloc(x,y) dlg_calloc((x),(y),__FILE__,__LINE__)*/ + +/******** antlr attributes *************/ +typedef struct { + unsigned char letter; + nfa_node *l,*r; + set label; + } Attrib; + +#define zzcr_attr(attr, token, text) { \ + (attr)->letter = text[0]; (attr)->l = NULL; \ + (attr)->r = NULL; (attr)->label = empty; \ +} +#define zzd_attr(a) set_free((a)->label); + +/******************** Variable ******************************/ +extern char program[]; /* tells what program this is */ +extern char version[]; /* tells what version this is */ +extern char *file_str[]; /* file names being used */ +extern int err_found; /* flag to indicate error occured */ +extern int action_no; /* last action function printed */ +extern int func_action; /* should actions be turned into functions?*/ +extern set used_chars; /* used to label trans. arcs */ +extern set used_classes; /* classes or chars used to label trans. arcs */ +extern int class_no; /* number of classes used */ +extern set class_sets[]; /* shows char. in each class */ +extern set normal_chars; /* mask off unused portion of set */ +extern int comp_level; /* what compression level to use */ +extern int interactive; /* interactive scanner (avoid lookahead)*/ +extern int mode_counter; /* keeps track of the number of %%name */ +extern int dfa_basep[]; /* start of each group of dfa */ +extern int dfa_class_nop[];/* number of transistion arcs in */ + /* each dfa in each mode */ +extern int nfa_allocated; +extern int dfa_allocated; +extern nfa_node **nfa_array; /* start of nfa "array" */ +extern dfa_node **dfa_array; /* start of dfa "array" */ +extern int operation_no; /* unique number for each operation */ +extern FILE *input_stream; /* where description read from */ +extern FILE *output_stream; /* where to put the output */ +extern FILE *mode_stream; /* where to put the mode output */ +extern FILE *class_stream; +extern char *mode_file; /* name of file for mode output */ +extern int gen_ansi; /* produce ansi compatible code */ +extern int case_insensitive;/* ignore case of input spec. */ +extern int warn_ambig; /* show if regular expressions ambiguous */ +extern int gen_cpp; +extern char *cl_file_str; +extern int firstLexMember; /* MR1 */ +extern char *OutputDirectory; +extern char *class_name; + +/******************** Functions ******************************/ +#ifdef __USE_PROTOS +extern char *dlg_malloc(int, char *, int); /* wrapper malloc */ +extern char *dlg_calloc(int, int, char *, int); /* wrapper calloc */ +extern int reach(unsigned *, register int, unsigned *); +extern set closure(set *, unsigned *); +extern dfa_node *new_dfa_node(set); +extern nfa_node *new_nfa_node(void); +extern dfa_node *dfastate(set); +extern dfa_node **nfa_to_dfa(nfa_node *); +extern void internal_error(char *, char *, int); /* MR9 23-Sep-97 */ +extern FILE *read_stream(char *); /* opens file for reading */ +extern FILE *write_stream(char *); /* opens file for writing */ +extern void make_nfa_model_node(void); +extern void make_dfa_model_node(int); +extern char *ClassName(char *); +extern char *OutMetaName(char *); +extern void error(char*, int); +extern void warning(char*, int); +extern void p_head(void); +extern void p_class_hdr(void); +extern void p_includes(void); +extern void p_tables(void); +extern void p_tail(void); /* MR1 */ +extern void p_class_def1(void); /* MR1 */ +extern void new_automaton_mode(void); /* MR1 */ +extern int relabel(nfa_node *,int); /* MR1 */ +extern void p_shift_table(int); /* MR1 */ +extern void p_bshift_table(void); /* MR1 */ +extern void p_class_table(void); /* MR1 */ +extern void p_mode_def(char *,int); /* MR1 */ +extern void init(void); /* MR1 */ +extern void p_class_def2(void); /* MR1 */ +extern void clear_hash(void); /* MR1 */ +extern void p_alternative_table(void); /* MR1 */ +extern void p_node_table(void); /* MR1 */ +extern void p_dfa_table(void); /* MR1 */ +extern void p_accept_table(void); /* MR1 */ +extern void p_action_table(void); /* MR1 */ +extern void p_base_table(void); /* MR1 */ +extern void p_single_node(int,int); /* MR1 */ +extern char * minsize(int); /* MR1 */ +extern void close1(nfa_node *,int,set *); /* MR1 */ +extern void partition(nfa_node *,int); /* MR1 */ +extern void intersect_nfa_labels(nfa_node *,set *); /* MR1 */ +extern void r_intersect(nfa_node *,set *); /* MR1 */ +extern void label_node(nfa_node *); /* MR1 */ +extern void label_with_classes(nfa_node *); /* MR1 */ + +#else +extern char *dlg_malloc(); /* wrapper malloc */ +extern char *dlg_calloc(); /* wrapper calloc */ +extern int reach(); +extern set closure(); +extern dfa_node *new_dfa_node(); +extern nfa_node *new_nfa_node(); +extern dfa_node *dfastate(); +extern dfa_node **nfa_to_dfa(); +extern void internal_error(); /* MR9 23-Sep-97 */ +extern FILE *read_stream(); /* opens file for reading */ +extern FILE *write_stream(); /* opens file for writing */ +extern void make_nfa_model_node(); +extern void make_dfa_model_node(); +extern char *ClassName(); +extern char *OutMetaName(); +extern void error(); +extern void warning(); +extern void p_head(); /* MR9 */ +extern void p_class_hdr(); /* MR9 */ +extern void p_includes(); /* MR9 */ +extern void p_tables(); /* MR9 */ +extern void p_tail(); /* MR1 */ +extern void p_class_def1(); /* MR1 */ +extern void new_automaton_mode(); /* MR1 */ +extern int relabel(); /* MR1 */ +extern void p_shift_table(); /* MR1 */ +extern void p_bshift_table(); /* MR1 */ +extern void p_class_table(); /* MR1 */ +extern void p_mode_def(); /* MR1 */ +extern void init(); /* MR1 */ +extern void p_class_def2(); /* MR1 */ +extern void clear_hash(); /* MR1 */ +extern void p_alternative_table(); /* MR1 */ +extern void p_node_table(); /* MR1 */ +extern void p_dfa_table(); /* MR1 */ +extern void p_accept_table(); /* MR1 */ +extern void p_action_table(); /* MR1 */ +extern void p_base_table(); /* MR1 */ +extern void p_single_node(); /* MR1 */ +extern char * minsize(); /* MR1 */ +extern void close1(); /* MR1 */ +extern void partition(); /* MR1 */ +extern void intersect_nfa_labels(); /* MR1 */ +extern void r_intersect(); /* MR1 */ +extern void label_node(); /* MR1 */ +extern void label_with_classes(); /* MR1 */ + +#endif diff --git a/Tools/Source/TianoTools/Pccts/dlg/dlg.r b/Tools/Source/TianoTools/Pccts/dlg/dlg.r new file mode 100644 index 0000000000..c5311fa1b8 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/dlg.r @@ -0,0 +1,275 @@ +/* + File: dlgMPW.r + Target: dlg 133MR + Created: Monday, June 15, 1998 4:44:11 AM + Author: Kenji Tanaka (kentar@osa.att.ne.jp) +*/ + +#include "cmdo.r" + +resource 'cmdo' (128, "Dlg") { + { /* array dialogs: 1 elements */ + /* [1] */ + 295, + "DLG -- Purdue Compiler Construction Tool" + " Set (PCCTS) lexical analyzer generator.", + { /* array itemArray: 18 elements */ + /* [1] */ + NotDependent { + + }, + CheckOption { + NotSet, + {35, 175, 50, 225}, + "On", + "-CC", + "When this control is checked, DLG genera" + "tes a scanner using C++ classes rather t" + "han C functions." + }, + /* [2] */ + Or { + { /* array OrArray: 1 elements */ + /* [1] */ + 1 + } + }, + RegularEntry { + "Lexer Class Name:", + {35, 225, 50, 355}, + {35, 355, 51, 450}, + "DLGLexer", + keepCase, + "-cl", + "This entry specifies the name DLG uses f" + "or the C++ lexer class." + }, + /* [3] */ + NotDependent { + + }, + TextBox { + gray, + {25, 165, 60, 460}, + "C++ Code Generation" + }, + /* [4] */ + NotDependent { + + }, + Files { + InputFile, + RequiredFile { + {37, 25, 56, 135}, + "Input File", + "", + "Choose the lexical description file for " + "DLG to process." + }, + Additional { + "", + "", + "", + "", + { /* array TypesArray: 1 elements */ + /* [1] */ + text + } + } + }, + /* [5] */ + Or { + { /* array OrArray: 1 elements */ + /* [1] */ + -1 + } + }, + Files { + OutputFile, + RequiredFile { + {66, 25, 85, 135}, + "Output File", + "", + "Choose the name of the file that will ho" + "ld the DLG-produced scanner." + }, + NoMore { + + } + }, + /* [6] */ + Or { + { /* array OrArray: 2 elements */ + /* [1] */ + 1, + /* [2] */ + 5 + } + }, + Dummy { + + }, + /* [7] */ + NotDependent { + + }, + Redirection { + DiagnosticOutput, + {90, 25} + }, + /* [8] */ + NotDependent { + + }, + TextBox { + gray, + {25, 20, 132, 145}, + "Files" + }, + /* [9] */ + NotDependent { + + }, + Files { + DirOnly, + OptionalFile { + {68, 175, 84, 305}, + {88, 175, 107, 305}, + "Output Directory", + ":", + "-o", + "", + "Choose the directory where DLG will put " + "its output.", + dim, + "Output DirectoryI", + "", + "" + }, + NoMore { + + } + }, + /* [10] */ + NotDependent { + + }, + RegularEntry { + "Mode File Name:", + {68, 315, 83, 450}, + {88, 315, 104, 450}, + "mode.h", + keepCase, + "-m", + "This entry specifies the name DLG uses f" + "or its lexical mode output file." + }, + /* [11] */ + NotDependent { + + }, + RadioButtons { + { /* array radioArray: 3 elements */ + /* [1] */ + {134, 175, 149, 255}, "None", "", Set, "When this option is selected, DLG will n" + "ot compress its tables.", + /* [2] */ + {134, 265, 149, 345}, "Level 1", "-C1", NotSet, "When this option is selected, DLG will r" + "emove all unused characters from the tra" + "nsition-from table.", + /* [3] */ + {134, 360, 149, 450}, "Level 2", "-C2", NotSet, "When this option is selected, DLG will p" + "erform level 1 compression plus it will " + "map equivalent characters into the same " + "character classes." + } + }, + /* [12] */ + NotDependent { + + }, + TextBox { + gray, + {124, 165, 156, 460}, + "Table Compression" + }, + /* [13] */ + NotDependent { + + }, + CheckOption { + Set, + {165, 20, 180, 145}, + "Case Sensitive", + "-ci", + "When this control is checked, the DLG au" + "tomaton will treat upper and lower case " + "characters identically." + }, + /* [14] */ + NotDependent { + + }, + CheckOption { + NotSet, + {165, 150, 180, 300}, + "Interactive Scanner", + "-i", + "When this control is checked, DLG will g" + "enerate as interactive a scanner as poss" + "ible." + }, + /* [15] */ + NotDependent { + + }, + CheckOption { + NotSet, + {165, 310, 180, 460}, + "Ambiguity Warnings", + "-Wambiguity", + "When this control is checked, DLG warns " + "if more than one regular expression coul" + "d match the same character sequence." + }, + /* [16] */ + NotDependent { + + }, + VersionDialog { + VersionString { + "1.33MR" + }, + "PCCTS was written by Terence Parr, Russe" + "ll Quong, Will Cohen, and Hank Dietz: 19" + "89-1998. MPW port by Scott Haney.", + noDialog + }, + /* [17] */ + And { + { /* array AndArray: 2 elements */ + /* [1] */ + 4, + /* [2] */ + 6 + } + }, + DoItButton { + + }, + /* [18] */ + NotDependent { + + }, + CheckOption { + NotSet, + {142, 20, 157, 148}, + "Generate ANSI C", + "-ga", + "When this control is checked, DLG genera" + "tes ANSI C compatible code." + } + } + } +}; + diff --git a/Tools/Source/TianoTools/Pccts/dlg/dlg1.txt b/Tools/Source/TianoTools/Pccts/dlg/dlg1.txt new file mode 100644 index 0000000000..06b320de2a --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/dlg1.txt @@ -0,0 +1,132 @@ + + + +dlg(1) PCCTS Manual Pages dlg(1) + + + +NAME + dlg - DFA Lexical Analyzer Generator + +SYNTAX + dlg [_o_p_t_i_o_n_s] _l_e_x_i_c_a_l__s_p_e_c [_o_u_t_p_u_t__f_i_l_e] + +DESCRIPTION + dlg is a tool that produces fast deterministic finite auto- + mata for recognizing regular expressions in input. + +OPTIONS + -CC Generate C++ output. The _o_u_t_p_u_t__f_i_l_e is not specified + in this case. + + -C[ level] + Where level is the compression level used. 0 indica- + tions no compression, 1 removes all unused characters + from the transition from table, and 2 maps equivalent + characters into the same character classes. It is sug- + gested that level -C2 is used, since it will signifi- + cantly reduce the size of the dfa produced for lexical + analyzer. + + -m Produces the header file for the lexical mode with a + name other than the default name of "mode.h". + + -i An interactive, or as interactive as possible, parser + is produced. A character is only obtained when + required to decide which state to go to. Some care + must be taken to obtain accept states that do not + require look ahead at the next character to determine + if that is the stop state. Any regular expression with + a Kleene closure at the end is guaranteed to require + another character of look ahead. + + -cl class + Specify a class name for DLG to generate. The default + is DLGLexer. + + -ci The automaton will treat upper and lower case charac- + ters identically. This is accomplished in the automa- + ton; the characters in the lexical buffer are unmodi- + fied. + + -cs Upper and lower case characters are treated as dis- + tinct. This is the default. + + -o dir + Directory where output files should go (default="."). + This is very nice for keeping the source directory + clear of ANTLR and DLG spawn. + + -Wambiguity + Warns if more than one regular expression could match + the same character sequence. The warnings give the + numbers of the expressions in the dlg lexical specifi- + cation file. The numbering of the expressions starts + at one. Multiple warnings may be print for the same + expressions. + + - Used in place of file names to get input from standard + in or send output to standard out. + +SPECIAL CONSIDERATIONS + _D_l_g works... we think. There is no implicit guarantee of + anything. We reserve no legal rights to the software known + as the Purdue Compiler Construction Tool Set (PCCTS) - PCCTS + is in the public domain. An individual or company may do + whatever they wish with source code distributed with PCCTS + or the code generated by PCCTS, including the incorporation + of PCCTS, or its output, into commercial software. We + encourage users to develop software with PCCTS. However, we + do ask that credit is given to us for developing PCCTS. By + "credit", we mean that if you incorporate our source code + into one of your programs (commercial product, research pro- + ject, or otherwise) that you acknowledge this fact somewhere + in the documentation, research report, etc... If you like + PCCTS and have developed a nice tool with the output, please + mention that you developed it using PCCTS. As long as these + guidelines are followed, we expect to continue enhancing + this system and expect to make other tools available as they + are completed. + +FILES + mode.h , dlgauto.h , dlgdef.h + +SEE ALSO + antlr(1), pccts(1) + +BUGS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/Pccts/dlg/dlg_a.c b/Tools/Source/TianoTools/Pccts/dlg/dlg_a.c new file mode 100644 index 0000000000..0b8982cf2a --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/dlg_a.c @@ -0,0 +1,1414 @@ + +/* parser.dlg -- DLG Description of scanner + * + * Generated from: dlg_p.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include +#include "dlg.h" +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +LOOKAHEAD + +void +#ifdef __USE_PROTOS +zzerraction(void) +#else +zzerraction() +#endif +{ + (*zzerr)("invalid token"); + zzadvance(); + zzskip(); +} +/* + * D L G tables + * + * Generated from: parser.dlg + * + * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz + * Purdue University Electrical Engineering + * DLG Version 1.33MR33 + */ + +#include "mode.h" + + + + +int func_action; /* should actions be turned into functions?*/ +int lex_mode_counter = 0; /* keeps track of the number of %%names */ +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via <<%%lexmember...>> */ +/* MR1 */ +int lexMember = 0; /* <<%%lexmemeber ...>> MR1 */ +int lexAction = 0; /* <<%%lexaction ...>> MR1 */ +int parserClass = 0; /* <<%%parserclass ...>> MR1 */ +int lexPrefix = 0; /* <<%%lexprefix ...>> MR1 */ +char theClassName[100]; /* MR11 */ +char *pClassName=theClassName; /* MR11 */ +int firstLexMember=1; /* MR1 */ + +#ifdef __USE_PROTOS +void xxputc(int c) { /* MR1 */ +#else + void xxputc(c) /* MR1 */ + int c; /* MR1 */ + { /* MR1 */ +#endif + if (parserClass) { /* MR1 */ + *pClassName++=c; /* MR1 */ + *pClassName=0; /* MR1 */ + } else if (lexMember || lexPrefix) { /* MR1 */ + if (class_stream != NULL) fputc(c,class_stream); /* MR1 */ + } else { /* MR1 */ + fputc(c,OUT); /* MR1 */ + }; /* MR1 */ + } /* MR1 */ + +#ifdef __USE_PROTOS + void xxprintf(char *format,char *string) { /* MR1 */ +#else + void xxprintf(format,string) /* MR1 */ + char *format; /* MR1 */ + char *string; /* MR1 */ + { /* MR1 */ +#endif + if (lexMember || lexPrefix || parserClass) { /* MR1 */ + if (class_stream != NULL) /* MR1 */ + fprintf(class_stream,format,string); /* MR1 */ + } else { /* MR1 */ + fprintf(OUT,format,string); /* MR1 */ + }; /* MR1 */ + } /* MR1 */ + +static void act1() +{ + NLA = 1; + } + + +static void act2() +{ + NLA = 2; + zzskip(); + } + + +static void act3() +{ + NLA = 3; + zzline++; zzskip(); DAWDLE; + } + + +static void act4() +{ + NLA = L_EOF; + } + + +static void act5() +{ + NLA = PER_PER; + } + + +static void act6() +{ + NLA = NAME_PER_PER; + p_mode_def(&zzlextext[2],lex_mode_counter++); + } + + +static void act7() +{ + NLA = LEXMEMBER; + lexMember=1; /* MR1 */ + if (firstLexMember != 0) { /* MR1 */ + firstLexMember=0; /* MR1 */ + p_class_def1(); /* MR1 */ + }; /* MR1 */ + zzmode(ACT); /* MR1 */ + } + + +static void act8() +{ + NLA = LEXACTION; + lexAction=1;zzmode(ACT); + } + + +static void act9() +{ + NLA = PARSERCLASS; + parserClass=1; /* MR1 */ + zzmode(ACT); /* MR1 */ + } + + +static void act10() +{ + NLA = LEXPREFIX; + lexPrefix=1;zzmode(ACT); + } + + +static void act11() +{ + NLA = ACTION; + if (func_action) + fprintf(OUT,"\n%s %sact%d()\n{ ", + gen_cpp?"ANTLRTokenType":"static void", + gen_cpp?ClassName("::"):"", ++action_no); + zzmode(ACT); zzskip(); + } + + +static void act12() +{ + NLA = GREAT_GREAT; + } + + +static void act13() +{ + NLA = L_BRACE; + } + + +static void act14() +{ + NLA = R_BRACE; + } + + +static void act15() +{ + NLA = L_PAR; + } + + +static void act16() +{ + NLA = R_PAR; + } + + +static void act17() +{ + NLA = L_BRACK; + } + + +static void act18() +{ + NLA = R_BRACK; + } + + +static void act19() +{ + NLA = ZERO_MORE; + } + + +static void act20() +{ + NLA = ONE_MORE; + } + + +static void act21() +{ + NLA = OR; + } + + +static void act22() +{ + NLA = RANGE; + } + + +static void act23() +{ + NLA = NOT; + } + + +static void act24() +{ + NLA = OCTAL_VALUE; + {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;} + } + + +static void act25() +{ + NLA = HEX_VALUE; + {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;} + } + + +static void act26() +{ + NLA = DEC_VALUE; + {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;} + } + + +static void act27() +{ + NLA = TAB; + zzlextext[0] = '\t'; + } + + +static void act28() +{ + NLA = NL; + zzlextext[0] = '\n'; + } + + +static void act29() +{ + NLA = CR; + zzlextext[0] = '\r'; + } + + +static void act30() +{ + NLA = BS; + zzlextext[0] = '\b'; + } + + +static void act31() +{ + NLA = CONTINUATION; + zzline++; zzskip(); + } + + +static void act32() +{ + NLA = LIT; + zzlextext[0] = zzlextext[1]; + } + + +static void act33() +{ + NLA = REGCHAR; + } + +static unsigned char shift0[257] = { + 0, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 1, 2, 40, 40, 1, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 1, 40, 40, 40, 40, 4, 40, + 40, 30, 31, 34, 35, 40, 37, 40, 40, 23, + 24, 24, 24, 24, 24, 24, 24, 25, 25, 40, + 40, 26, 40, 27, 40, 3, 21, 21, 21, 21, + 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 20, + 22, 22, 32, 39, 33, 40, 22, 40, 11, 9, + 12, 21, 6, 19, 22, 22, 14, 22, 22, 5, + 8, 16, 15, 17, 22, 10, 18, 13, 22, 22, + 22, 7, 22, 22, 28, 36, 29, 38, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40 +}; + + +static void act34() +{ + NLA = 1; + error("unterminated action", zzline); zzmode(START); + } + + +static void act35() +{ + NLA = ACTION; + if (func_action) fprintf(OUT,"}\n\n"); + zzmode(START); + /* MR1 */ + /* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ + /* MR1 via <<%%lexmember ...>> */ + /* MR1 This is a consequence of not saving actions */ + /* MR1 */ + /* MR1 */ parserClass=0; + /* MR1 */ lexPrefix=0; + /* MR1 */ lexAction=0; + /* MR1 */ lexMember=0; + } + + +static void act36() +{ + NLA = 34; + xxputc(zzlextext[0]); zzskip(); + } + + +static void act37() +{ + NLA = 35; + xxputc('>'); zzskip(); + } + + +static void act38() +{ + NLA = 36; + xxputc('\\'); zzskip(); + } + + +static void act39() +{ + NLA = 37; + xxputc(zzlextext[0]); ++zzline; zzskip(); + } + + +static void act40() +{ + NLA = 38; + zzmode(ACTION_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + } + + +static void act41() +{ + NLA = 39; + zzmode(ACTION_CPP_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + } + + +static void act42() +{ + NLA = 40; + xxputc(zzlextext[0]); zzskip(); + } + +static unsigned char shift1[257] = { + 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 3, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 5, 6, 6, 6, 6, 4, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 1, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6 +}; + + +static void act43() +{ + NLA = 1; + } + + +static void act44() +{ + NLA = 41; + zzmode(ACT); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + } + + +static void act45() +{ + NLA = 42; + zzline++; xxputc(zzlextext[0]); zzskip(); + } + + +static void act46() +{ + NLA = 43; + xxputc(zzlextext[0]); zzskip(); + } + +static unsigned char shift2[257] = { + 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 3, 4, 4, 3, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 1, 4, 4, 4, 4, 2, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4 +}; + + +static void act47() +{ + NLA = 1; + } + + +static void act48() +{ + NLA = 44; + zzmode(ACT); zzline++; /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + } + + +static void act49() +{ + NLA = 45; + xxputc(zzlextext[0]); zzskip(); + } + +static unsigned char shift3[257] = { + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2 +}; + +#define DfaStates 94 +typedef unsigned char DfaState; + +static DfaState st0[42] = { + 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 6, 94 +}; + +static DfaState st1[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st2[42] = { + 94, 21, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st3[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st4[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st5[42] = { + 94, 94, 94, 94, 22, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st6[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st7[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 23, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st8[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 24, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st9[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st10[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st11[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st12[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st13[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st14[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st15[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st16[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st17[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st18[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st19[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st20[42] = { + 94, 25, 26, 25, 25, 25, 25, 25, 25, 27, + 28, 25, 25, 29, 25, 25, 30, 25, 25, 25, + 25, 25, 25, 31, 32, 32, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 94 +}; + +static DfaState st21[42] = { + 94, 21, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st22[42] = { + 94, 94, 94, 94, 94, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st23[42] = { + 94, 94, 94, 94, 34, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st24[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st25[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st26[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st27[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st28[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st29[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st30[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st31[42] = { + 94, 94, 94, 94, 94, 94, 94, 35, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 35, 94, 94, 36, 36, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st32[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 37, 37, 37, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st33[42] = { + 94, 94, 94, 94, 94, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st34[42] = { + 94, 94, 94, 94, 39, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st35[42] = { + 94, 94, 94, 94, 94, 94, 40, 94, 94, 40, + 94, 40, 40, 94, 94, 94, 94, 94, 94, 40, + 94, 40, 94, 40, 40, 40, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st36[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 36, 36, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st37[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 37, 37, 37, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st38[42] = { + 94, 94, 94, 94, 94, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st39[42] = { + 94, 94, 94, 94, 94, 41, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 42, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st40[42] = { + 94, 94, 94, 94, 94, 94, 40, 94, 94, 40, + 94, 40, 40, 94, 94, 94, 94, 94, 94, 40, + 94, 40, 94, 40, 40, 40, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st41[42] = { + 94, 94, 94, 94, 94, 94, 43, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st42[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 44, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st43[42] = { + 94, 94, 94, 94, 94, 94, 94, 45, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st44[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 46, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st45[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 47, 94, + 94, 48, 94, 94, 94, 94, 94, 49, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st46[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 50, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st47[42] = { + 94, 94, 94, 94, 94, 94, 51, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st48[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 52, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st49[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 53, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st50[42] = { + 94, 94, 94, 94, 94, 94, 54, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st51[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 55, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st52[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 56, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st53[42] = { + 94, 94, 94, 94, 94, 94, 57, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st54[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 58, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st55[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 59, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st56[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 60, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st57[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 61, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st58[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 62, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st59[42] = { + 94, 94, 94, 94, 94, 94, 63, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st60[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 64, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st61[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 65, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st62[42] = { + 94, 94, 94, 94, 94, 66, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st63[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 67, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st64[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 68, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st65[42] = { + 94, 94, 94, 94, 94, 94, 94, 69, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st66[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 70, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st67[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st68[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st69[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st70[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 71, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st71[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 72, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st72[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st73[8] = { + 74, 75, 76, 77, 78, 79, 79, 94 +}; + +static DfaState st74[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st75[8] = { + 94, 80, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st76[8] = { + 94, 81, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st77[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st78[8] = { + 94, 94, 94, 94, 82, 83, 94, 94 +}; + +static DfaState st79[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st80[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st81[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st82[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st83[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st84[6] = { + 85, 86, 87, 88, 87, 94 +}; + +static DfaState st85[6] = { + 94, 94, 94, 94, 94, 94 +}; + +static DfaState st86[6] = { + 94, 94, 89, 94, 94, 94 +}; + +static DfaState st87[6] = { + 94, 94, 94, 94, 94, 94 +}; + +static DfaState st88[6] = { + 94, 94, 94, 94, 94, 94 +}; + +static DfaState st89[6] = { + 94, 94, 94, 94, 94, 94 +}; + +static DfaState st90[4] = { + 91, 92, 93, 94 +}; + +static DfaState st91[4] = { + 94, 94, 94, 94 +}; + +static DfaState st92[4] = { + 94, 94, 94, 94 +}; + +static DfaState st93[4] = { + 94, 94, 94, 94 +}; + + +DfaState *dfa[94] = { + st0, + st1, + st2, + st3, + st4, + st5, + st6, + st7, + st8, + st9, + st10, + st11, + st12, + st13, + st14, + st15, + st16, + st17, + st18, + st19, + st20, + st21, + st22, + st23, + st24, + st25, + st26, + st27, + st28, + st29, + st30, + st31, + st32, + st33, + st34, + st35, + st36, + st37, + st38, + st39, + st40, + st41, + st42, + st43, + st44, + st45, + st46, + st47, + st48, + st49, + st50, + st51, + st52, + st53, + st54, + st55, + st56, + st57, + st58, + st59, + st60, + st61, + st62, + st63, + st64, + st65, + st66, + st67, + st68, + st69, + st70, + st71, + st72, + st73, + st74, + st75, + st76, + st77, + st78, + st79, + st80, + st81, + st82, + st83, + st84, + st85, + st86, + st87, + st88, + st89, + st90, + st91, + st92, + st93 +}; + + +DfaState accepts[95] = { + 0, 1, 2, 3, 4, 33, 33, 33, 33, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 0, 2, 5, 11, 12, 32, 31, 30, 29, 27, + 28, 24, 26, 6, 0, 0, 24, 26, 6, 0, + 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 8, 10, + 0, 0, 9, 0, 34, 36, 38, 39, 42, 42, + 35, 37, 41, 40, 0, 43, 46, 46, 45, 44, + 0, 47, 48, 49, 0 +}; + +void (*actions[50])() = { + zzerraction, + act1, + act2, + act3, + act4, + act5, + act6, + act7, + act8, + act9, + act10, + act11, + act12, + act13, + act14, + act15, + act16, + act17, + act18, + act19, + act20, + act21, + act22, + act23, + act24, + act25, + act26, + act27, + act28, + act29, + act30, + act31, + act32, + act33, + act34, + act35, + act36, + act37, + act38, + act39, + act40, + act41, + act42, + act43, + act44, + act45, + act46, + act47, + act48, + act49 +}; + +static DfaState dfa_base[] = { + 0, + 73, + 84, + 90 +}; + +static unsigned char *b_class_no[] = { + shift0, + shift1, + shift2, + shift3 +}; + + + +#define ZZSHIFT(c) (b_class_no[zzauto][1+c]) +#define MAX_MODE 4 +#include "dlgauto.h" diff --git a/Tools/Source/TianoTools/Pccts/dlg/dlg_p.c b/Tools/Source/TianoTools/Pccts/dlg/dlg_p.c new file mode 100644 index 0000000000..e726ae3983 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/dlg_p.c @@ -0,0 +1,959 @@ +/* + * A n t l r T r a n s l a t i o n H e a d e r + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + * + * ..\bin\antlr dlg_p.g -gh + * + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include +#include "dlg.h" +#define zzSET_SIZE 8 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "mode.h" + +/* MR23 In order to remove calls to PURIFY use the antlr -nopurify option */ + +#ifndef PCCTS_PURIFY +#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\0',(s)); +#endif + +ANTLR_INFO + + +/* MR20 G. Hobbelt +Fix for Borland C++ 4.x & 5.x compiling with ALL warnings enabled +*/ + +#ifdef __TURBOC__ +#pragma warn -aus /* unused assignment of 'xxx' */ +#endif + +int action_no = 0; /* keep track of actions outputed */ +int nfa_allocated = 0; /* keeps track of number of nfa nodes */ +nfa_node **nfa_array = NULL;/* root of binary tree that stores nfa array */ +nfa_node nfa_model_node; /* model to initialize new nodes */ +set used_chars; /* used to label trans. arcs */ +set used_classes; /* classes or chars used to label trans. arcs */ +set normal_chars; /* mask to get rid elements that aren't used +in set */ +int flag_paren = FALSE; +int flag_brace = FALSE; +int mode_counter = 0; /* keep track of number of %%names */ + + + +void +#ifdef __USE_PROTOS +grammar(void) +#else +grammar() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + p_head(); p_class_hdr(); func_action = FALSE; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd1[LA(1)]&0x1) ) { + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==LEXACTION) ) { + zzmatch(LEXACTION); zzCONSUME; + } + else { + if ( (LA(1)==LEXMEMBER) ) { + zzmatch(LEXMEMBER); zzCONSUME; + } + else { + if ( (LA(1)==LEXPREFIX) ) { + zzmatch(LEXPREFIX); zzCONSUME; + } + else { + if ( (LA(1)==PARSERCLASS) ) { + zzmatch(PARSERCLASS); zzCONSUME; + } + else { + if ( (LA(1)==ACTION) ) { + } + else {zzFAIL(1,zzerr1,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + } + zzEXIT(zztasp3); + } + } + zzmatch(ACTION); zzCONSUME; + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + if ( gen_cpp ) p_includes(); + start_states(); + func_action = FALSE; p_tables(); p_tail(); + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==ACTION) ) { + zzmatch(ACTION); zzCONSUME; + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzmatch(1); + if (firstLexMember != 0) p_class_def1(); + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x2); + } +} + +void +#ifdef __USE_PROTOS +start_states(void) +#else +start_states() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==PER_PER) ) { + zzmatch(PER_PER); zzCONSUME; + do_conversion(); + } + else { + if ( (LA(1)==NAME_PER_PER) ) { + zzmatch(NAME_PER_PER); zzCONSUME; + do_conversion(); + { + zzBLOCK(zztasp3); + zzMake0; + { + while ( (LA(1)==NAME_PER_PER) ) { + zzmatch(NAME_PER_PER); zzCONSUME; + do_conversion(); + zzLOOP(zztasp3); + } + zzEXIT(zztasp3); + } + } + } + else {zzFAIL(1,zzerr2,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + zzmatch(PER_PER); zzCONSUME; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x4); + } +} + +void +#ifdef __USE_PROTOS +do_conversion(void) +#else +do_conversion() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + new_automaton_mode(); func_action = TRUE; + rule_list(); + + dfa_class_nop[mode_counter] = + relabel(zzaArg(zztasp1,1 ).l,comp_level); + if (comp_level) + p_shift_table(mode_counter); + dfa_basep[mode_counter] = dfa_allocated+1; + make_dfa_model_node(dfa_class_nop[mode_counter]); + nfa_to_dfa(zzaArg(zztasp1,1 ).l); + ++mode_counter; + func_action = FALSE; +#ifdef HASH_STAT + fprint_hash_stats(stderr); +#endif + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x8); + } +} + +void +#ifdef __USE_PROTOS +rule_list(void) +#else +rule_list() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + if ( (setwd1[LA(1)]&0x10) ) { + rule(); + zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd1[LA(1)]&0x20) ) { + rule(); + {nfa_node *t1; + t1 = new_nfa_node(); + (t1)->trans[0]=zzaRet.l; + (t1)->trans[1]=zzaArg(zztasp2,1 ).l; + /* all accept nodes "dead ends" */ + zzaRet.l=t1; zzaRet.r=NULL; + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + } + else { + if ( (setwd1[LA(1)]&0x40) ) { + zzaRet.l = new_nfa_node(); zzaRet.r = NULL; + warning("no regular expressions", zzline); + } + else {zzFAIL(1,zzerr3,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x80); + } +} + +void +#ifdef __USE_PROTOS +rule(void) +#else +rule() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + if ( (setwd2[LA(1)]&0x1) ) { + reg_expr(); + zzmatch(ACTION); + if (zzaArg(zztasp1,1 ).r != NULL) { + zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; (zzaArg(zztasp1,1 ).r)->accept=action_no; + } + zzCONSUME; + + } + else { + if ( (LA(1)==ACTION) ) { + zzmatch(ACTION); + zzaRet.l = NULL; zzaRet.r = NULL; + error("no expression for action ", zzline); + zzCONSUME; + + } + else {zzFAIL(1,zzerr4,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x2); + } +} + +void +#ifdef __USE_PROTOS +reg_expr(void) +#else +reg_expr() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + and_expr(); + zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==OR) ) { + zzmatch(OR); zzCONSUME; + and_expr(); + {nfa_node *t1, *t2; + t1 = new_nfa_node(); t2 = new_nfa_node(); + (t1)->trans[0]=zzaRet.l; + (t1)->trans[1]=zzaArg(zztasp2,2 ).l; + /* MR23 */ if (zzaRet.r != NULL) (zzaRet.r)->trans[1]=t2; + if (zzaArg(zztasp2,2 ).r) { + (zzaArg(zztasp2,2 ).r)->trans[1]=t2; /* MR20 */ + } + zzaRet.l=t1; zzaRet.r=t2; + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x4); + } +} + +void +#ifdef __USE_PROTOS +and_expr(void) +#else +and_expr() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + repeat_expr(); + + zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd2[LA(1)]&0x8) ) { + repeat_expr(); + if (zzaRet.r != NULL) { + (zzaRet.r)->trans[1]=zzaArg(zztasp2,1 ).l; + zzaRet.r=zzaArg(zztasp2,1 ).r; + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x10); + } +} + +void +#ifdef __USE_PROTOS +repeat_expr(void) +#else +repeat_expr() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + if ( (setwd2[LA(1)]&0x20) ) { + expr(); + zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==ZERO_MORE) ) { + zzmatch(ZERO_MORE); + { nfa_node *t1,*t2; + /* MR23 */ if (zzaRet.r != NULL) (zzaRet.r)->trans[0] = zzaRet.l; + t1 = new_nfa_node(); t2 = new_nfa_node(); + t1->trans[0]=zzaRet.l; + t1->trans[1]=t2; + /* MR23 */ if (zzaRet.r != NULL) (zzaRet.r)->trans[1]=t2; + zzaRet.l=t1;zzaRet.r=t2; + } + zzCONSUME; + + } + else { + if ( (LA(1)==ONE_MORE) ) { + zzmatch(ONE_MORE); + if (zzaRet.r != NULL) (zzaRet.r)->trans[0] = zzaRet.l; + zzCONSUME; + + } + else { + if ( (setwd2[LA(1)]&0x40) ) { + } + else {zzFAIL(1,zzerr5,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp2); + } + } + } + else { + if ( (LA(1)==ZERO_MORE) ) { + zzmatch(ZERO_MORE); + error("no expression for *", zzline); + zzCONSUME; + + } + else { + if ( (LA(1)==ONE_MORE) ) { + zzmatch(ONE_MORE); + error("no expression for +", zzline); + zzCONSUME; + + } + else {zzFAIL(1,zzerr6,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x80); + } +} + +void +#ifdef __USE_PROTOS +expr(void) +#else +expr() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + zzaRet.l = new_nfa_node(); + zzaRet.r = new_nfa_node(); + if ( (LA(1)==L_BRACK) ) { + zzmatch(L_BRACK); zzCONSUME; + atom_list(); + zzmatch(R_BRACK); + + /* MR23 */ if (zzaRet.l != NULL) { + (zzaRet.l)->trans[0] = zzaRet.r; + (zzaRet.l)->label = set_dup(zzaArg(zztasp1,2 ).label); + set_orin(&used_chars,(zzaRet.l)->label); + } + zzCONSUME; + + } + else { + if ( (LA(1)==NOT) ) { + zzmatch(NOT); zzCONSUME; + zzmatch(L_BRACK); zzCONSUME; + atom_list(); + zzmatch(R_BRACK); + + /* MR23 */ if (zzaRet.l != NULL) { + (zzaRet.l)->trans[0] = zzaRet.r; + (zzaRet.l)->label = set_dif(normal_chars,zzaArg(zztasp1,3 ).label); + set_orin(&used_chars,(zzaRet.l)->label); + } + zzCONSUME; + + } + else { + if ( (LA(1)==L_PAR) ) { + zzmatch(L_PAR); zzCONSUME; + reg_expr(); + zzmatch(R_PAR); + + /* MR23 */ if (zzaRet.l != NULL) { + (zzaRet.l)->trans[0] = zzaArg(zztasp1,2 ).l; + if (zzaArg(zztasp1,2 ).r) { + (zzaArg(zztasp1,2 ).r)->trans[1] = zzaRet.r; /* MR20 */ + } + } + zzCONSUME; + + } + else { + if ( (LA(1)==L_BRACE) ) { + zzmatch(L_BRACE); zzCONSUME; + reg_expr(); + zzmatch(R_BRACE); + + /* MR23 */ if (zzaRet.l != NULL) { + (zzaRet.l)->trans[0] = zzaArg(zztasp1,2 ).l; + (zzaRet.l)->trans[1] = zzaRet.r; + if (zzaArg(zztasp1,2 ).r) { + (zzaArg(zztasp1,2 ).r)->trans[1] = zzaRet.r; /* MR20 */ + } + } + zzCONSUME; + + } + else { + if ( (setwd3[LA(1)]&0x1) ) { + atom(); + + /* MR23 */ if (zzaRet.l != NULL) { + (zzaRet.l)->trans[0] = zzaRet.r; + (zzaRet.l)->label = set_dup(zzaArg(zztasp1,1 ).label); + set_orin(&used_chars,(zzaRet.l)->label); + } + } + else {zzFAIL(1,zzerr7,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x2); + } +} + +void +#ifdef __USE_PROTOS +atom_list(void) +#else +atom_list() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + set_free(zzaRet.label); + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd3[LA(1)]&0x4) ) { + near_atom(); + set_orin(&(zzaRet.label),zzaArg(zztasp2,1 ).label); + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x8); + } +} + +void +#ifdef __USE_PROTOS +near_atom(void) +#else +near_atom() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + register int i; + register int i_prime; + anychar(); + zzaRet.letter=zzaArg(zztasp1,1 ).letter; zzaRet.label=set_of(zzaArg(zztasp1,1 ).letter); + i_prime = zzaArg(zztasp1,1 ).letter + MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &(zzaRet.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &(zzaRet.label)); + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==RANGE) ) { + zzmatch(RANGE); zzCONSUME; + anychar(); + if (case_insensitive){ + i_prime = zzaRet.letter+MIN_CHAR; + zzaRet.letter = (islower(i_prime) ? + toupper(i_prime) : i_prime)-MIN_CHAR; + i_prime = zzaArg(zztasp2,2 ).letter+MIN_CHAR; + zzaArg(zztasp2,2 ).letter = (islower(i_prime) ? + toupper(i_prime) : i_prime)-MIN_CHAR; + } + /* check to see if range okay */ + { + int debugLetter1 = zzaRet.letter; + int debugLetter2 = zzaArg(zztasp2,2 ).letter; + } + if (zzaRet.letter > zzaArg(zztasp2,2 ).letter + && zzaArg(zztasp2,2 ).letter != 0xff){ /* MR16 */ + error("invalid range ", zzline); + } + for (i=zzaRet.letter; i<= (int)zzaArg(zztasp2,2 ).letter; ++i){ + set_orel(i,&(zzaRet.label)); + i_prime = i+MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &(zzaRet.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &(zzaRet.label)); + } + } + else { + if ( (setwd3[LA(1)]&0x10) ) { + } + else {zzFAIL(1,zzerr8,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x20); + } +} + +void +#ifdef __USE_PROTOS +atom(void) +#else +atom() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + register int i_prime; + anychar(); + zzaRet.label = set_of(zzaArg(zztasp1,1 ).letter); + i_prime = zzaArg(zztasp1,1 ).letter + MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &(zzaRet.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &(zzaRet.label)); + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x40); + } +} + +void +#ifdef __USE_PROTOS +anychar(void) +#else +anychar() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + if ( (LA(1)==REGCHAR) ) { + zzmatch(REGCHAR); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==OCTAL_VALUE) ) { + zzmatch(OCTAL_VALUE); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==HEX_VALUE) ) { + zzmatch(HEX_VALUE); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==DEC_VALUE) ) { + zzmatch(DEC_VALUE); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==TAB) ) { + zzmatch(TAB); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==NL) ) { + zzmatch(NL); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==CR) ) { + zzmatch(CR); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==BS) ) { + zzmatch(BS); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==LIT) ) { + zzmatch(LIT); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==L_EOF) ) { + zzmatch(L_EOF); + zzaRet.letter = 0; + zzCONSUME; + + } + else {zzFAIL(1,zzerr9,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + } + } + } + } + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + /* empty action */ + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x80); + } +} + +/* adds a new nfa to the binary tree and returns a pointer to it */ +nfa_node * +#ifdef __USE_PROTOS +new_nfa_node(void) +#else +new_nfa_node() +#endif +{ + register nfa_node *t; + static int nfa_size=0; /* elements nfa_array[] can hold */ + + ++nfa_allocated; + if (nfa_size<=nfa_allocated){ + /* need to redo array */ + if (!nfa_array){ + /* need some to do inital allocation */ + nfa_size=nfa_allocated+NFA_MIN; + nfa_array=(nfa_node **) malloc(sizeof(nfa_node*)* + nfa_size); + }else{ + /* need more space */ + nfa_size=2*(nfa_allocated+1); + nfa_array=(nfa_node **) realloc(nfa_array, + sizeof(nfa_node*)*nfa_size); + } + } + /* fill out entry in array */ + t = (nfa_node*) malloc(sizeof(nfa_node)); + nfa_array[nfa_allocated] = t; + *t = nfa_model_node; + t->node_no = nfa_allocated; + return t; +} + + +/* initialize the model node used to fill in newly made nfa_nodes */ +void +#ifdef __USE_PROTOS +make_nfa_model_node(void) +#else +make_nfa_model_node() +#endif +{ + nfa_model_node.node_no = -1; /* impossible value for real nfa node */ + nfa_model_node.nfa_set = 0; + nfa_model_node.accept = 0; /* error state default*/ + nfa_model_node.trans[0] = NULL; + nfa_model_node.trans[1] = NULL; + nfa_model_node.label = empty; +} + +#if defined(DEBUG) || defined(_DEBUG) + +/* print out the pointer value and the node_number */ +void +#ifdef __USE_PROTOS +fprint_dfa_pair(FILE *f, nfa_node *p) +#else +fprint_dfa_pair(f, p) +FILE *f; +nfa_node *p; +#endif +{ + if (p){ + fprintf(f, "%x (%d)", p, p->node_no); + }else{ + fprintf(f, "(nil)"); + } +} + +/* print out interest information on a set */ +void +#ifdef __USE_PROTOS +fprint_set(FILE *f, set s) +#else +fprint_set(f,s) +FILE *f; +set s; +#endif +{ + unsigned int *x; + + fprintf(f, "n = %d,", s.n); + if (s.setword){ + fprintf(f, "setword = %x, ", s.setword); + /* print out all the elements in the set */ + x = set_pdq(s); + while (*x!=nil){ + fprintf(f, "%d ", *x); + ++x; + } + }else{ + fprintf(f, "setword = (nil)"); + } +} + +/* code to be able to dump out the nfas +return 0 if okay dump +return 1 if screwed up +*/ +int +#ifdef __USE_PROTOS +dump_nfas(int first_node, int last_node) +#else +dump_nfas(first_node, last_node) +int first_node; +int last_node; +#endif +{ + register int i; + nfa_node *t; + + for (i=first_node; i<=last_node; ++i){ + t = NFA(i); + if (!t) break; + fprintf(stderr, "nfa_node %d {\n", t->node_no); + fprintf(stderr, "\n\tnfa_set = %d\n", t->nfa_set); + fprintf(stderr, "\taccept\t=\t%d\n", t->accept); + fprintf(stderr, "\ttrans\t=\t("); + fprint_dfa_pair(stderr, t->trans[0]); + fprintf(stderr, ","); + fprint_dfa_pair(stderr, t->trans[1]); + fprintf(stderr, ")\n"); + fprintf(stderr, "\tlabel\t=\t{ "); + fprint_set(stderr, t->label); + fprintf(stderr, "\t}\n"); + fprintf(stderr, "}\n\n"); + } + return 0; +} +#endif + +/* DLG-specific syntax error message generator +* (define USER_ZZSYN when compiling so don't get 2 definitions) +*/ +void +#ifdef __USE_PROTOS +zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text) +#else +zzsyn(text, tok, egroup, eset, etok, k, bad_text) +char *text, *egroup, *bad_text; +int tok; +int etok; +int k; +SetWordType *eset; +#endif +{ +fprintf(stderr, ErrHdr, file_str[0]!=NULL?file_str[0]:"stdin", zzline); +fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text); +if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} +if ( k==1 ) fprintf(stderr, " missing"); +else +{ +fprintf(stderr, "; \"%s\" not", bad_text); +if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); +} +if ( zzset_deg(eset)>0 ) zzedecode(eset); +else fprintf(stderr, " %s", zztokens[etok]); +if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup); +fprintf(stderr, "\n"); +} diff --git a/Tools/Source/TianoTools/Pccts/dlg/dlg_p.g b/Tools/Source/TianoTools/Pccts/dlg/dlg_p.g new file mode 100644 index 0000000000..58ca110693 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/dlg_p.g @@ -0,0 +1,614 @@ +/* This is the parser for the dlg + * This is a part of the Purdue Compiler Construction Tool Set + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-1995 + */ + +#header << +#include +#include "dlg.h" +>> + +<< + +/* MR20 G. Hobbelt + Fix for Borland C++ 4.x & 5.x compiling with ALL warnings enabled +*/ + +#ifdef __TURBOC__ +#pragma warn -aus /* unused assignment of 'xxx' */ +#endif + +int action_no = 0; /* keep track of actions outputed */ +int nfa_allocated = 0; /* keeps track of number of nfa nodes */ +nfa_node **nfa_array = NULL;/* root of binary tree that stores nfa array */ +nfa_node nfa_model_node; /* model to initialize new nodes */ +set used_chars; /* used to label trans. arcs */ +set used_classes; /* classes or chars used to label trans. arcs */ +set normal_chars; /* mask to get rid elements that aren't used + in set */ +int flag_paren = FALSE; +int flag_brace = FALSE; +int mode_counter = 0; /* keep track of number of %%names */ + +>> + +#lexaction << +int func_action; /* should actions be turned into functions?*/ +int lex_mode_counter = 0; /* keeps track of the number of %%names */ +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via <<%%lexmember...>> */ +/* MR1 */ +int lexMember = 0; /* <<%%lexmemeber ...>> MR1 */ +int lexAction = 0; /* <<%%lexaction ...>> MR1 */ +int parserClass = 0; /* <<%%parserclass ...>> MR1 */ +int lexPrefix = 0; /* <<%%lexprefix ...>> MR1 */ +char theClassName[100]; /* MR11 */ +char *pClassName=theClassName; /* MR11 */ +int firstLexMember=1; /* MR1 */ + +#ifdef __USE_PROTOS +void xxputc(int c) { /* MR1 */ +#else +void xxputc(c) /* MR1 */ + int c; /* MR1 */ +{ /* MR1 */ +#endif + if (parserClass) { /* MR1 */ + *pClassName++=c; /* MR1 */ + *pClassName=0; /* MR1 */ + } else if (lexMember || lexPrefix) { /* MR1 */ + if (class_stream != NULL) fputc(c,class_stream); /* MR1 */ + } else { /* MR1 */ + fputc(c,OUT); /* MR1 */ + }; /* MR1 */ +} /* MR1 */ + +#ifdef __USE_PROTOS +void xxprintf(char *format,char *string) { /* MR1 */ +#else +void xxprintf(format,string) /* MR1 */ + char *format; /* MR1 */ + char *string; /* MR1 */ +{ /* MR1 */ +#endif + if (lexMember || lexPrefix || parserClass) { /* MR1 */ + if (class_stream != NULL) /* MR1 */ + fprintf(class_stream,format,string); /* MR1 */ + } else { /* MR1 */ + fprintf(OUT,format,string); /* MR1 */ + }; /* MR1 */ +} /* MR1 */ +>> + +#token "[\r\t\ ]+" << zzskip(); >> /* Ignore white */ +#token "\n" << zzline++; zzskip(); DAWDLE; >> /* Track Line # */ +#token L_EOF "\@" +#token PER_PER "\%\%" +#token NAME_PER_PER "\%\%[a-zA-Z_][a-zA-Z0-9_]*" + << p_mode_def(&zzlextext[2],lex_mode_counter++); >> + +#token LEXMEMBER "\<\<\%\%lexmember" /* MR1 */ + <> /* MR1 */ +#token LEXACTION "\<\<\%\%lexaction" /* MR1 */ + <> /* MR1 */ +#token PARSERCLASS "\<\<\%\%parserclass" /* MR1 */ + <> /* MR1 */ +#token LEXPREFIX "\<\<\%\%lexprefix" /* MR1 */ + <> /* MR1 */ + +#token ACTION "\<\<" + << if (func_action) + fprintf(OUT,"\n%s %sact%d()\n{ ", + gen_cpp?"ANTLRTokenType":"static void", + gen_cpp?ClassName("::"):"", ++action_no); + zzmode(ACT); zzskip(); + >> +#token GREAT_GREAT "\>\>" +#token L_BRACE "\{" +#token R_BRACE "\}" +#token L_PAR "\(" +#token R_PAR "\)" +#token L_BRACK "\[" +#token R_BRACK "\]" +#token ZERO_MORE "\*" +#token ONE_MORE "\+" +#token OR "\|" +#token RANGE "\-" +#token NOT "\~" +#token OCTAL_VALUE "\\0[0-7]*" + << {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;}>> +#token HEX_VALUE "\\0[Xx][0-9a-fA-F]+" + << {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;}>> +#token DEC_VALUE "\\[1-9][0-9]*" + << {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;}>> +#token TAB "\\t" << zzlextext[0] = '\t';>> +#token NL "\\n" << zzlextext[0] = '\n';>> +#token CR "\\r" << zzlextext[0] = '\r';>> +#token BS "\\b" << zzlextext[0] = '\b';>> + +/* MR1 */ +/* MR1 10-Apr-97 MR1 Allow #token regular expressions to cross lines */ +/* MR1 */ +#token CONTINUATION "\\ \n" << zzline++; zzskip();>> /* MR1 */ + +/* NOTE: this takes ANYTHING after the \ */ +#token LIT "\\~[tnrb]" << zzlextext[0] = zzlextext[1];>> + +/* NOTE: this takes ANYTHING that doesn't match the other tokens */ +#token REGCHAR "~[\\]" + + +grammar : << p_head(); p_class_hdr(); func_action = FALSE;>> + ( {LEXACTION | LEXMEMBER | LEXPREFIX | PARSERCLASS } ACTION)* /* MR1 */ + <> + start_states + << func_action = FALSE; p_tables(); p_tail(); >> + (ACTION)* "@" + << if (firstLexMember != 0) p_class_def1(); >> /* MR1 */ + ; + +start_states : ( PER_PER do_conversion + | NAME_PER_PER do_conversion (NAME_PER_PER do_conversion)*) + PER_PER + ; + +do_conversion : <> + rule_list + << + dfa_class_nop[mode_counter] = + relabel($1.l,comp_level); + if (comp_level) + p_shift_table(mode_counter); + dfa_basep[mode_counter] = dfa_allocated+1; + make_dfa_model_node(dfa_class_nop[mode_counter]); + nfa_to_dfa($1.l); + ++mode_counter; + func_action = FALSE; +#ifdef HASH_STAT + fprint_hash_stats(stderr); +#endif + >> + ; + +rule_list : rule <<$$.l=$1.l; $$.r=$1.r;>> + (rule + <<{nfa_node *t1; + t1 = new_nfa_node(); + (t1)->trans[0]=$$.l; + (t1)->trans[1]=$1.l; + /* all accept nodes "dead ends" */ + $$.l=t1; $$.r=NULL; + } + >> + )* + | /* empty */ + <<$$.l = new_nfa_node(); $$.r = NULL; + warning("no regular expressions", zzline); + >> + ; + +rule : reg_expr ACTION +/* MR23 */ << if ($1.r != NULL) { + $$.l=$1.l; $$.r=$1.r; ($1.r)->accept=action_no; + } + >> + | ACTION + <<$$.l = NULL; $$.r = NULL; + error("no expression for action ", zzline); + >> + ; + +reg_expr : and_expr <<$$.l=$1.l; $$.r=$1.r;>> + (OR and_expr + <<{nfa_node *t1, *t2; + t1 = new_nfa_node(); t2 = new_nfa_node(); + (t1)->trans[0]=$$.l; + (t1)->trans[1]=$2.l; +/* MR23 */ if ($$.r != NULL) ($$.r)->trans[1]=t2; + if ($2.r) { + ($2.r)->trans[1]=t2; /* MR20 */ + } + $$.l=t1; $$.r=t2; + } + >> + )* + ; + +and_expr : repeat_expr + << + $$.l=$1.l; $$.r=$1.r; + >> + (repeat_expr +/* MR23 */ << if ($$.r != NULL) { + ($$.r)->trans[1]=$1.l; + $$.r=$1.r; + } + >> + )* + ; + +repeat_expr : expr <<$$.l=$1.l; $$.r=$1.r;>> + { ZERO_MORE + <<{ nfa_node *t1,*t2; +/* MR23 */ if ($$.r != NULL) ($$.r)->trans[0] = $$.l; + t1 = new_nfa_node(); t2 = new_nfa_node(); + t1->trans[0]=$$.l; + t1->trans[1]=t2; +/* MR23 */ if ($$.r != NULL) ($$.r)->trans[1]=t2; + $$.l=t1;$$.r=t2; + } + >> + | ONE_MORE +/* MR23 */ <trans[0] = $$.l;>> + } + | ZERO_MORE + << error("no expression for *", zzline);>> + | ONE_MORE + << error("no expression for +", zzline);>> + ; + +expr : << $$.l = new_nfa_node(); + $$.r = new_nfa_node(); + >> + L_BRACK atom_list R_BRACK + << +/* MR23 */ if ($$.l != NULL) { + ($$.l)->trans[0] = $$.r; + ($$.l)->label = set_dup($2.label); + set_orin(&used_chars,($$.l)->label); + } + >> + | NOT L_BRACK atom_list R_BRACK + << +/* MR23 */ if ($$.l != NULL) { + ($$.l)->trans[0] = $$.r; + ($$.l)->label = set_dif(normal_chars,$3.label); + set_orin(&used_chars,($$.l)->label); + } + >> + | L_PAR reg_expr R_PAR + << +/* MR23 */ if ($$.l != NULL) { + ($$.l)->trans[0] = $2.l; + if ($2.r) { + ($2.r)->trans[1] = $$.r; /* MR20 */ + } + } + >> + | L_BRACE reg_expr R_BRACE + << +/* MR23 */ if ($$.l != NULL) { + ($$.l)->trans[0] = $2.l; + ($$.l)->trans[1] = $$.r; + if ($2.r) { + ($2.r)->trans[1] = $$.r; /* MR20 */ + } + } + >> + | atom + << +/* MR23 */ if ($$.l != NULL) { + ($$.l)->trans[0] = $$.r; + ($$.l)->label = set_dup($1.label); + set_orin(&used_chars,($$.l)->label); + } + >> + ; + +atom_list : << set_free($$.label); >> + (near_atom <>)* + ; + +near_atom : << register int i; + register int i_prime; + >> + anychar + <<$$.letter=$1.letter; $$.label=set_of($1.letter); + i_prime = $1.letter + MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &($$.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &($$.label)); + >> + { RANGE anychar + << if (case_insensitive){ + i_prime = $$.letter+MIN_CHAR; + $$.letter = (islower(i_prime) ? + toupper(i_prime) : i_prime)-MIN_CHAR; + i_prime = $2.letter+MIN_CHAR; + $2.letter = (islower(i_prime) ? + toupper(i_prime) : i_prime)-MIN_CHAR; + } + /* check to see if range okay */ + { + int debugLetter1 = $$.letter; + int debugLetter2 = $2.letter; + } + if ($$.letter > $2.letter + && $2.letter != 0xff){ /* MR16 */ + error("invalid range ", zzline); + } + for (i=$$.letter; i<= (int)$2.letter; ++i){ + set_orel(i,&($$.label)); + i_prime = i+MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &($$.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &($$.label)); + } + >> + } + ; + +atom : << register int i_prime;>> + anychar + <<$$.label = set_of($1.letter); + i_prime = $1.letter + MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &($$.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &($$.label)); + >> + ; + +anychar : REGCHAR <<$$.letter = $1.letter - MIN_CHAR;>> + | OCTAL_VALUE <<$$.letter = $1.letter - MIN_CHAR;>> + | HEX_VALUE <<$$.letter = $1.letter - MIN_CHAR;>> + | DEC_VALUE <<$$.letter = $1.letter - MIN_CHAR;>> + | TAB <<$$.letter = $1.letter - MIN_CHAR;>> + | NL <<$$.letter = $1.letter - MIN_CHAR;>> + | CR <<$$.letter = $1.letter - MIN_CHAR;>> + | BS <<$$.letter = $1.letter - MIN_CHAR;>> + | LIT <<$$.letter = $1.letter - MIN_CHAR;>> + /* NOTE: LEX_EOF is ALWAYS shifted to 0 = MIN_CHAR - MIN_CHAR*/ + | L_EOF <<$$.letter = 0;>> + ; + +<> + +#lexclass ACT +#token "@" << error("unterminated action", zzline); zzmode(START); >> +#token ACTION "\>\>" + << if (func_action) fprintf(OUT,"}\n\n"); + zzmode(START); +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via <<%%lexmember ...>> */ +/* MR1 This is a consequence of not saving actions */ +/* MR1 */ +/* MR1 */ parserClass=0; +/* MR1 */ lexPrefix=0; +/* MR1 */ lexAction=0; +/* MR1 */ lexMember=0; + >> +#token "\>" << xxputc(zzlextext[0]); zzskip(); >> /* MR1 */ +#token "\\\>" << xxputc('>'); zzskip(); >> /* MR1 */ +#token "\\" << xxputc('\\'); zzskip(); >> /* MR1 */ +#token "\n" << xxputc(zzlextext[0]); ++zzline; zzskip(); >> /* MR1 */ +#token "/\*" << zzmode(ACTION_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> /* MR1 */ +#token "//" << zzmode(ACTION_CPP_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> /* MR1 */ +#token "~[]" << xxputc(zzlextext[0]); zzskip(); >> /* MR1 */ + /* MR1 */ +#lexclass ACTION_COMMENTS /* MR1 */ +#token "\*/" << zzmode(ACT); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> /* MR1 */ +#token "[\n\r]" << zzline++; xxputc(zzlextext[0]); zzskip();>> /* MR1 */ +#token "~[]" << xxputc(zzlextext[0]); zzskip();>> /* MR1 */ + /* MR1 */ +#lexclass ACTION_CPP_COMMENTS /* MR1 */ +#token "[\n\r]" << zzmode(ACT); zzline++; /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> /* MR1 */ +#token "~[]" << xxputc(zzlextext[0]); zzskip();>> /* MR1 */ + +<< +/* adds a new nfa to the binary tree and returns a pointer to it */ +nfa_node * +#ifdef __USE_PROTOS +new_nfa_node(void) +#else +new_nfa_node() +#endif +{ + register nfa_node *t; + static int nfa_size=0; /* elements nfa_array[] can hold */ + + ++nfa_allocated; + if (nfa_size<=nfa_allocated){ + /* need to redo array */ + if (!nfa_array){ + /* need some to do inital allocation */ + nfa_size=nfa_allocated+NFA_MIN; + nfa_array=(nfa_node **) malloc(sizeof(nfa_node*)* + nfa_size); + }else{ + /* need more space */ + nfa_size=2*(nfa_allocated+1); + nfa_array=(nfa_node **) realloc(nfa_array, + sizeof(nfa_node*)*nfa_size); + } + } + /* fill out entry in array */ + t = (nfa_node*) malloc(sizeof(nfa_node)); + nfa_array[nfa_allocated] = t; + *t = nfa_model_node; + t->node_no = nfa_allocated; + return t; +} + + +/* initialize the model node used to fill in newly made nfa_nodes */ +void +#ifdef __USE_PROTOS +make_nfa_model_node(void) +#else +make_nfa_model_node() +#endif +{ + nfa_model_node.node_no = -1; /* impossible value for real nfa node */ + nfa_model_node.nfa_set = 0; + nfa_model_node.accept = 0; /* error state default*/ + nfa_model_node.trans[0] = NULL; + nfa_model_node.trans[1] = NULL; + nfa_model_node.label = empty; +} +>> + +<< +#if defined(DEBUG) || defined(_DEBUG) + +/* print out the pointer value and the node_number */ +void +#ifdef __USE_PROTOS +fprint_dfa_pair(FILE *f, nfa_node *p) +#else +fprint_dfa_pair(f, p) +FILE *f; +nfa_node *p; +#endif +{ + if (p){ + fprintf(f, "%x (%d)", p, p->node_no); + }else{ + fprintf(f, "(nil)"); + } +} + +/* print out interest information on a set */ +void +#ifdef __USE_PROTOS +fprint_set(FILE *f, set s) +#else +fprint_set(f,s) +FILE *f; +set s; +#endif +{ + unsigned int *x; + + fprintf(f, "n = %d,", s.n); + if (s.setword){ + fprintf(f, "setword = %x, ", s.setword); + /* print out all the elements in the set */ + x = set_pdq(s); + while (*x!=nil){ + fprintf(f, "%d ", *x); + ++x; + } + }else{ + fprintf(f, "setword = (nil)"); + } +} + +/* code to be able to dump out the nfas + return 0 if okay dump + return 1 if screwed up + */ +int +#ifdef __USE_PROTOS +dump_nfas(int first_node, int last_node) +#else +dump_nfas(first_node, last_node) +int first_node; +int last_node; +#endif +{ + register int i; + nfa_node *t; + + for (i=first_node; i<=last_node; ++i){ + t = NFA(i); + if (!t) break; + fprintf(stderr, "nfa_node %d {\n", t->node_no); + fprintf(stderr, "\n\tnfa_set = %d\n", t->nfa_set); + fprintf(stderr, "\taccept\t=\t%d\n", t->accept); + fprintf(stderr, "\ttrans\t=\t("); + fprint_dfa_pair(stderr, t->trans[0]); + fprintf(stderr, ","); + fprint_dfa_pair(stderr, t->trans[1]); + fprintf(stderr, ")\n"); + fprintf(stderr, "\tlabel\t=\t{ "); + fprint_set(stderr, t->label); + fprintf(stderr, "\t}\n"); + fprintf(stderr, "}\n\n"); + } + return 0; +} +#endif +>> + +<< +/* DLG-specific syntax error message generator + * (define USER_ZZSYN when compiling so don't get 2 definitions) + */ +void +#ifdef __USE_PROTOS +zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text) +#else +zzsyn(text, tok, egroup, eset, etok, k, bad_text) +char *text, *egroup, *bad_text; +int tok; +int etok; +int k; +SetWordType *eset; +#endif +{ + fprintf(stderr, ErrHdr, file_str[0]!=NULL?file_str[0]:"stdin", zzline); + fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text); + if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} + if ( k==1 ) fprintf(stderr, " missing"); + else + { + fprintf(stderr, "; \"%s\" not", bad_text); + if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); + } + if ( zzset_deg(eset)>0 ) zzedecode(eset); + else fprintf(stderr, " %s", zztokens[etok]); + if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup); + fprintf(stderr, "\n"); +} +>> diff --git a/Tools/Source/TianoTools/Pccts/dlg/err.c b/Tools/Source/TianoTools/Pccts/dlg/err.c new file mode 100644 index 0000000000..c3eaeae6d1 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/err.c @@ -0,0 +1,99 @@ +/* + * A n t l r S e t s / E r r o r F i l e H e a d e r + * + * Generated from: dlg_p.g + * + * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001 + * Parr Research Corporation + * with Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include +#include "dlg.h" +#define zzSET_SIZE 8 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "err.h" + +ANTLRChar *zztokens[46]={ + /* 00 */ "Invalid", + /* 01 */ "@", + /* 02 */ "[\\r\\t\\ ]+", + /* 03 */ "\\n", + /* 04 */ "L_EOF", + /* 05 */ "PER_PER", + /* 06 */ "NAME_PER_PER", + /* 07 */ "LEXMEMBER", + /* 08 */ "LEXACTION", + /* 09 */ "PARSERCLASS", + /* 10 */ "LEXPREFIX", + /* 11 */ "ACTION", + /* 12 */ "GREAT_GREAT", + /* 13 */ "L_BRACE", + /* 14 */ "R_BRACE", + /* 15 */ "L_PAR", + /* 16 */ "R_PAR", + /* 17 */ "L_BRACK", + /* 18 */ "R_BRACK", + /* 19 */ "ZERO_MORE", + /* 20 */ "ONE_MORE", + /* 21 */ "OR", + /* 22 */ "RANGE", + /* 23 */ "NOT", + /* 24 */ "OCTAL_VALUE", + /* 25 */ "HEX_VALUE", + /* 26 */ "DEC_VALUE", + /* 27 */ "TAB", + /* 28 */ "NL", + /* 29 */ "CR", + /* 30 */ "BS", + /* 31 */ "CONTINUATION", + /* 32 */ "LIT", + /* 33 */ "REGCHAR", + /* 34 */ "\\>", + /* 35 */ "\\\\>", + /* 36 */ "\\", + /* 37 */ "\\n", + /* 38 */ "/\\*", + /* 39 */ "//", + /* 40 */ "~[]", + /* 41 */ "\\*/", + /* 42 */ "[\\n\\r]", + /* 43 */ "~[]", + /* 44 */ "[\\n\\r]", + /* 45 */ "~[]" +}; +SetWordType zzerr1[8] = {0x80,0xf,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr2[8] = {0x60,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr3[8] = {0x70,0xa8,0x9a,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType setwd1[46] = {0x0,0x6,0x0,0x0,0x30,0xc8,0xc8, + 0x1,0x1,0x1,0x1,0x35,0x0,0x30,0x0, + 0x30,0x0,0x30,0x0,0x30,0x30,0x0,0x0, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x0,0x30,0x30,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr4[8] = {0x10,0xa8,0x9a,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType zzerr5[8] = {0x10,0xe8,0xbb,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType zzerr6[8] = {0x10,0xa0,0x9a,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType setwd2[46] = {0x0,0x0,0x0,0x0,0xeb,0x2,0x2, + 0x0,0x0,0x0,0x0,0xd6,0x0,0xeb,0xd4, + 0xeb,0xd4,0xeb,0x0,0xcb,0xcb,0xd0,0x0, + 0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb, + 0x0,0xeb,0xeb,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr7[8] = {0x10,0xa0,0x82,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType zzerr8[8] = {0x10,0x0,0x44,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType zzerr9[8] = {0x10,0x0,0x0,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType setwd3[46] = {0x0,0x0,0x0,0x0,0xf7,0x0,0x0, + 0x0,0x0,0x0,0x0,0xc2,0x0,0xc2,0xc2, + 0xc2,0xc2,0xc2,0xb8,0xc2,0xc2,0xc2,0x80, + 0xc2,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7, + 0x0,0xf7,0xf7,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0}; diff --git a/Tools/Source/TianoTools/Pccts/dlg/main.c b/Tools/Source/TianoTools/Pccts/dlg/main.c new file mode 100644 index 0000000000..35bd827f8c --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/main.c @@ -0,0 +1,281 @@ +/* Main function for dlg version + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "stdpccts.h" + +char program[] = "dlg"; +char version[] = "1.33MR33"; /* MRXXX */ +int numfiles = 0; +char *file_str[2] = {NULL, NULL}; +char *mode_file = "mode.h"; +char *class_name = DEFAULT_CLASSNAME; +char *OutputDirectory = TopDirectory; + +/* Option variables */ +int comp_level = 0; +int interactive = FALSE; +int case_insensitive = FALSE; +int warn_ambig = FALSE; +int gen_cpp = FALSE; + +#ifdef __USE_PROTOS +static int ci_strequ(char *a,char *b) +#else +static int ci_strequ(a,b) + char *a; + char *b; +#endif +{ + for ( ;*a != 0 && *b != 0; a++, b++) { + if (toupper(*a) != toupper(*b)) return 0; + } + return (*a == *b); +} + +/* Option List Stuff */ +#ifdef __USE_PROTOS +void p_comp0(void) {comp_level = 0;} +void p_comp1(void) {comp_level = 1;} +void p_comp2(void) {comp_level = 2;} +void p_stdio(void) { file_str[numfiles++] = NULL;} +void p_file(char *s) { file_str[numfiles++] = s;} +void p_cl_name(char *s, char *t) + { + if ( gen_cpp ) { + class_name = t; + } + else { + warning("-cl only valid in C++ mode; -cl ignored...",0); + } + } +void p_mode_file(char *s, char *t){mode_file=t;} +void p_outdir(char *s,char *t) {OutputDirectory=t;} +void p_ansi(void) {gen_ansi = TRUE;} +void p_interactive(void) {interactive = TRUE;} +void p_case_s(void) { case_insensitive = FALSE; } +void p_case_i(void) { case_insensitive = TRUE; } +void p_warn_ambig(void) { warn_ambig = TRUE; } +void p_cpp(void) { gen_cpp = TRUE; } +#else +void p_comp0() {comp_level = 0;} +void p_comp1() {comp_level = 1;} +void p_comp2() {comp_level = 2;} +void p_stdio() { file_str[numfiles++] = NULL;} +void p_file(s) char *s; { file_str[numfiles++] = s;} +void p_cl_name(s,t) + char *s, *t; + { + if ( gen_cpp ) { + class_name = t; + } + else { + warning("-cl only valid in C++ mode; -cl ignored...",0); + } + } +void p_mode_file(s,t) char *s,*t;{mode_file=t;} +void p_outdir(s,t) char *s,*t;{OutputDirectory=t;} +void p_ansi() {gen_ansi = TRUE;} +void p_interactive() {interactive = TRUE;} +void p_case_s() { case_insensitive = FALSE; } +void p_case_i() { case_insensitive = TRUE; } +void p_warn_ambig() { warn_ambig = TRUE; } +void p_cpp() { gen_cpp = TRUE; } +#endif + +#ifdef __cplusplus +typedef void (*WildFunc)(...); +#else +typedef void (*WildFunc)(); +#endif + +typedef struct { + char *option; + int arg; + WildFunc process; + char *descr; + } Opt; + +Opt options[] = { + { "-CC", 0, (WildFunc)p_cpp, "Generate C++ output" }, + { "-C0", 0, (WildFunc)p_comp0, "No compression (default)" }, + { "-C1", 0, (WildFunc)p_comp1, "Compression level 1" }, + { "-C2", 0, (WildFunc)p_comp2, "Compression level 2" }, + { "-ga", 0, (WildFunc)p_ansi, "Generate ansi C"}, + { "-Wambiguity", 0, (WildFunc)p_warn_ambig, "Warn if expressions ambiguous"}, + { "-m", 1, (WildFunc)p_mode_file, "Rename lexical mode output file"}, + { "-i", 0, (WildFunc)p_interactive, "Build interactive scanner (not valid for C++ mode)"}, + { "-ci", 0, (WildFunc)p_case_i, "Make lexical analyzer case insensitive"}, + { "-cl", 1, (WildFunc)p_cl_name, "Rename lexer class (DLGLexer); only used for -CC"}, + { "-cs", 0, (WildFunc)p_case_s, "Make lexical analyzer case sensitive (default)"}, + { "-o", 1, (WildFunc)p_outdir, OutputDirectoryOption}, + { "-", 0, (WildFunc)p_stdio, "Use standard i/o rather than file"}, + { "*", 0, (WildFunc)p_file, ""}, /* anything else is a file */ + { NULL, 0, NULL } + }; + +#ifdef __USE_PROTOS +void ProcessArgs(int argc, char **argv, Opt *options) +#else +void ProcessArgs(argc, argv, options) +int argc; +char **argv; +Opt *options; +#endif +{ + Opt *p; + + while ( argc-- > 0 ) + { + p = options; + while ( p->option != NULL ) + { + if ( strcmp(p->option, "*") == 0 || + ci_strequ(p->option,*argv) ) + { + if ( p->arg ) + { + (*p->process)( *argv, *(argv+1) ); + argv++; + argc--; + } + else + (*p->process)( *argv ); + break; + } + p++; + } + argv++; + } +} + +#ifdef __USE_PROTOS +int main(int argc, char *argv[]) +#else +int main(argc, argv) +int argc; +char *argv[]; +#endif +{ + init(); + fprintf(stderr, "%s Version %s 1989-2001\n", &(program[0]), + &(version[0])); + if ( argc == 1 ) + { + Opt *p = options; + fprintf(stderr, "%s [options] f1 f2 ... fn\n",argv[0]); + while ( *(p->option) != '*' ) + { + fprintf(stderr, "\t%s %s\t%s\n", + p->option, + (p->arg)?"___":" ", + p->descr); + p++; + } + }else{ + ProcessArgs(argc-1, &(argv[1]), options); + if (interactive && gen_cpp) { + fprintf(stderr,"\n"); +/*** MR21a This statement is wrong ! ***/ +#if 0 +*** fprintf(stderr,"Interactive lexer option (\"-i\") has no effect when in C++ mode\n"); +*** fprintf(stderr,"because of extra buffering provided by ANTLRTokenBuffer class.\n"); +*** fprintf(stderr,"\n"); +#endif + } + input_stream = read_stream(file_str[0]); + if (input_stream) { + /* don't overwrite unless input okay */ + if ( gen_cpp ) { + output_stream = write_stream(ClassName(CPP_FILE_SUFFIX)); + if ( file_str[1]!=NULL ) { + warning("output file implicit in C++ mode; ignored...",0); + } + class_stream = write_stream(ClassName(".h")); + mode_stream = class_stream; + } + else { + output_stream = write_stream(file_str[1]); + mode_stream = write_stream(mode_file); + } + } + /* make sure that error reporting routines in grammar + know what the file really is */ + /* make sure that reading and writing somewhere */ + if (input_stream && output_stream && mode_stream){ + ANTLR(grammar(), input_stream); + } + p_class_def2(); /* MR1 */ + } + if ( output_stream!=NULL ) fclose(output_stream); + if ( !gen_cpp && mode_stream!=NULL ) fclose(mode_stream); + if ( class_stream!=NULL ) fclose(class_stream); + exit(PCCTS_EXIT_SUCCESS); + return 0; /* get rid of warning message MR1 */ +} + +/* initialize all the variables */ +void +#ifdef __USE_PROTOS +init(void) +#else +init() +#endif +{ + register int i; + +#ifdef SPECIAL_INITS + special_inits(); /* MR1 */ +#endif + used_chars = empty; + used_classes = empty; + /* make the valid character set */ + normal_chars = empty; + /* NOTE: MIN_CHAR is EOF */ + /* NOTE: EOF is not quite a valid char, it is special. Skip it*/ + for (i = 1; i +#include +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#endif /* __STDC__ */ +#endif + +static char *mode_name[MAX_MODES]; +static int mode_number[MAX_MODES]; +static int cur_mode=0; + +int operation_no = 0; /* used to mark nodes so that infinite loops avoided */ +int dfa_basep[MAX_MODES]; /* start of each group of states */ +int dfa_class_nop[MAX_MODES]; /* number of elements in each group of states*/ + +int gen_ansi = FALSE; /* allows ansi code to be generated */ + +FILE *input_stream; /* where to read description from */ +FILE *output_stream; /* where to put the output */ +FILE *mode_stream; /* where to put the mode.h stuff */ +FILE *class_stream; /* where to put the scan.h stuff (if gen_cpp) */ + +/* NOTE: This section is MACHINE DEPENDENT */ +#define DIF_SIZE 4 +#if defined(PC) && !defined(PC32) +unsigned long typesize[DIF_SIZE] = { 0x7f, 0x7fff, 0x7ffful, 0x7ffffffful }; /* MR20 */ +char t0[] = "unsigned char"; +char t1[] = "unsigned short"; +char t2[] = "unsigned int"; +char t3[] = "unsigned long"; +char *typevar[DIF_SIZE] = { t0, t1, t2, t3}; +#else +unsigned long typesize[DIF_SIZE] = { 0x7f, 0x7fff, 0x7ffffffful, 0x7ffffffful }; /* MR20 */ +char t0[] = "unsigned char"; +char t1[] = "unsigned short"; +char t2[] = "unsigned int"; +char t3[] = "unsigned long"; +char *typevar[DIF_SIZE] = { t0, t1, t2, t3}; +#endif + +/* Added by TJP August 1994 */ +/* Take in MyLexer and return MyLexer_h */ + +static char * +#ifdef __USE_PROTOS +gate_symbol(char *name) +#else +gate_symbol(name) +char *name; +#endif +{ + static char buf[100]; + sprintf(buf, "%s_h", name); + return buf; +} + +/* Added by TJP August 1994 */ +static char * +#ifdef __USE_PROTOS +mystrdup(char *s) +#else +mystrdup(s) +char *s; +#endif +{ + char *p = (char *)malloc(strlen(s)+1); + strcpy(p, s); + return p; +} + +#ifdef __USE_PROTOS +void p_class_hdr(void) +#else +void p_class_hdr() +#endif +{ + if ( class_stream == NULL ) return; + fprintf(class_stream, "#ifndef %s\n", gate_symbol(ClassName(""))); + fprintf(class_stream, "#define %s\n", gate_symbol(ClassName(""))); + fprintf(class_stream, "/*\n"); + fprintf(class_stream, " * D L G L e x e r C l a s s D e f i n i t i o n\n"); + fprintf(class_stream, " *\n"); + fprintf(class_stream, " * Generated from:"); + fprintf(class_stream, " %s", file_str[0]); + fprintf(class_stream, "\n"); + fprintf(class_stream, " *\n"); + fprintf(class_stream, " * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz\n"); + fprintf(class_stream, " * Purdue University Electrical Engineering\n"); + fprintf(class_stream, " * DLG Version %s\n", version); + fprintf(class_stream, " */\n\n"); + fprintf(class_stream, "\n"); + fprintf(class_stream, "#include \"%s\"\n", DLEXERBASE_H); +} + +/* MR1 */ +/* MR1 16-Apr-97 Split printing of class header up into several parts */ +/* MR1 so that #lexprefix <<...>>and #lexmember <<...>> */ +/* MR1 can be inserted in the appropriate spots */ +/* MR1 */ + +#ifdef __USE_PROTOS +void p_class_def1(void) +#else +void p_class_def1() +#endif +{ + if ( class_stream == NULL ) return; + fprintf(class_stream, "\nclass %s : public DLGLexerBase {\n", ClassName("")); + fprintf(class_stream, "public:\n"); +} + +#ifdef __USE_PROTOS +void p_class_def2(void) +#else +void p_class_def2() +#endif +{ + int i, m; + if ( class_stream == NULL ) return; + fprintf(class_stream, "public:\n"); + fprintf(class_stream, "\tstatic const int MAX_MODE;\n"); + fprintf(class_stream, "\tstatic const int DfaStates;\n"); + for (i=0; i> */ +/* MR1 */ +/* MR1 */ fprintf(class_stream,"//\n"); +/* MR1 */ fprintf(class_stream, +/* MR1 */ "// 133MR1 Deprecated feature to allow inclusion of "); +/* MR1 */ fprintf(class_stream, +/* MR1 */ "user-defined code in DLG class header\n"); +/* MR1 */ fprintf(class_stream,"//\n"); +/* MR1 */ +/* MR1 */ fprintf(class_stream,"#ifdef DLGLexerIncludeFile\n"); +/* MR1 */ fprintf(class_stream,"#include DLGLexerIncludeFile\n"); +/* MR1 */ fprintf(class_stream,"#endif\n"); + + fprintf(class_stream, "};\n"); + + fprintf(class_stream, "typedef ANTLRTokenType (%s::*Ptr%sMemberFunc)();\n", + ClassName(""), ClassName("")); + + fprintf(class_stream, "#endif\n"); +} + +/* generate required header on output */ + +#ifdef __USE_PROTOS +void p_head(void) +#else +void p_head() +#endif +{ + fprintf(OUT, "/*\n"); + fprintf(OUT, " * D L G tables\n"); + fprintf(OUT, " *\n"); + fprintf(OUT, " * Generated from:"); + fprintf(OUT, " %s", file_str[0]); + fprintf(OUT, "\n"); + fprintf(OUT, " *\n"); + fprintf(OUT, " * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz\n"); + fprintf(OUT, " * Purdue University Electrical Engineering\n"); + fprintf(OUT, " * DLG Version %s\n", version); + fprintf(OUT, " */\n\n"); + if ( gen_cpp) fprintf(OUT, "#include \"pcctscfg.h\"\n"); + if ( gen_cpp ) fprintf(OUT, "#include \"pccts_stdio.h\"\n"); + if ( !gen_cpp ) fprintf(OUT, "#include \"%s\"\n\n", mode_file); + fprintf(OUT,"\n"); +} + +#ifdef __USE_PROTOS +void p_includes(void) +#else +void p_includes() +#endif +{ + fprintf(OUT, "#include \"%s\"\n", APARSER_H); + fprintf(OUT, "#include \"%s\"\n", DLEXERBASE_H); + fprintf(OUT, "#include \"%s\"\n", ClassName(".h")); +} + +/* generate code to tie up any loose ends */ + +#ifdef __USE_PROTOS +void p_tail(void) /* MR1 */ +#else +void p_tail() /* MR1 */ +#endif +{ + if ( gen_cpp ) { + if ( strcmp(ClassName(""), DEFAULT_CLASSNAME)!=0 ) + fprintf(OUT, "#define DLGLexer %s\n", ClassName("")); + fprintf(OUT, "#include \"%s\"\n", DLEXER_H); /* MR23 Rename DLexer.cpp to DLexer.h */ + return; + } + fprintf(OUT, "\n"); + fprintf(OUT, "\n"); + if (comp_level) + fprintf(OUT, "#define ZZSHIFT(c) (b_class_no[zzauto][1+c])\n"); + else + fprintf(OUT, "#define ZZSHIFT(c) (1+c)\n"); + if ( !gen_cpp ) fprintf(OUT, "#define MAX_MODE %d\n",mode_counter); + fprintf(OUT, "#include \"dlgauto.h\"\n"); +} + + +/* output the table of DFA for general use */ + +#ifdef __USE_PROTOS +void p_tables() +#else +void p_tables() +#endif +{ + if ( !gen_cpp ) { + fprintf(OUT, "#define DfaStates\t%d\n", dfa_allocated); + fprintf(OUT, "typedef %s DfaState;\n\n", minsize(dfa_allocated)); + } + + if ( gen_cpp ) { + int i; + fprintf(OUT, "\n"); + fprintf(OUT, "const int %s::MAX_MODE=%d;\n", + ClassName(""), + mode_counter); + fprintf(OUT, "const int %s::DfaStates=%d;\n", + ClassName(""), + dfa_allocated); + for (i=0; i typesize[i]) /* MR20 */ + ++i; + return typevar[i]; +} + + +#ifdef __USE_PROTOS +void p_node_table(void) +#else +void p_node_table() +#endif +{ + register int i; + register int m = 0; + + for(m=0; m<(mode_counter-1); ++m){ + for(i=dfa_basep[m]; itrans[j]; + if (trans == NIL_INDEX) + trans = dfa_allocated+1; + /* all of DFA moved down one in array */ + fprintf(OUT, "%d", trans-1); + fprintf(OUT, ", "); + if (!(--items_on_line)){ + fprintf(OUT, "\n "); + items_on_line = MAX_ON_LINE; + } + } +#if 1 + /* put in jump to error state */ + fprintf(OUT, "%d\n};\n\n", dfa_allocated); +#else + fprintf(OUT, "\n};\n\n"); +#endif +} + + +#ifdef __USE_PROTOS +void p_dfa_table(void) +#else +void p_dfa_table() +#endif +{ + register int i; + + fprintf(OUT, "\n%sDfaState *%sdfa[%d] = {\n", + gen_cpp?ClassName("::"):"",gen_cpp?ClassName("::"):"", dfa_allocated); + for (i=0; i<(dfa_allocated-1); ++i){ + fprintf(OUT, "\tst%d,\n", i); + } + fprintf(OUT, "\tst%d\n", i); + fprintf(OUT, "};\n\n"); +} + + +#ifdef __USE_PROTOS +void p_accept_table(void) +#else +void p_accept_table() +#endif +{ + register int i = 1; + register int items_on_line = 0; + int true_interactive = TRUE; + + /* make sure element for one past (zzerraction) -WEC 12/16/92 */ + fprintf(OUT,"\n%sDfaState %saccepts[%d] = {\n ", + gen_cpp?ClassName("::"):"", + gen_cpp?ClassName("::"):"", + dfa_allocated+1); + /* don't do anything if no dfa nodes */ + if (i>dfa_allocated) goto skip_accepts; + for (;;) { + int accept=0; /* MR14a - Manuel Kessler (mlkessle@cip.physik.uni-wuerzburg.de) */ + set accept_set; + set nfa_states; + unsigned int *t, *nfa_i; + unsigned int *q, *regular_expr; + + accept_set = empty; + nfa_states = DFA(i)->nfa_states; + t = nfa_i = set_pdq(nfa_states); + /* NOTE: picks lowest accept because accepts monotonic */ + /* with respect to nfa node numbers and set_pdq */ + /* returns in that order */ + while((*nfa_i != nil) && (!(accept = NFA(*nfa_i)->accept))){ + nfa_i++; + } + + /* figure out if more than one accept state there */ + if (warn_ambig ){ + set_orel(accept, &accept_set); + while(*nfa_i != nil){ + set_orel(NFA(*nfa_i)->accept, &accept_set); + nfa_i++; + } + /* remove error action from consideration */ + set_rm(0, accept_set); + + if( set_deg(accept_set)>1){ + fprintf(stderr, "dlg warning: ambiguous regular expression "); + q = regular_expr = set_pdq(accept_set); + while(*regular_expr != nil){ + fprintf(stderr," %d ", *regular_expr); + ++regular_expr; + } + fprintf(stderr, "\n"); + free(q); + } + } + + if ((DFA(i)->alternatives) && (accept != 0)){ + true_interactive = FALSE; + } + fprintf(OUT, "%d, ", accept); + + /* free up memory before we "break" below -ATG 4/6/95 */ + free(t); + set_free(accept_set); + + if ((++i)>dfa_allocated) + break; + if ((++items_on_line)>=MAX_ON_LINE){ + fprintf(OUT,"\n "); + items_on_line = 0; + } +/* + free(t); + set_free(accept_set); +*/ + } + /* make sure element for one past (zzerraction) -WEC 12/16/92 */ +skip_accepts: + fprintf(OUT, "0\n};\n\n"); +} + + +#ifdef __USE_PROTOS +void p_action_table(void) +#else +void p_action_table() +#endif +{ + register int i; + char* theClassName = ClassName(""); + + if ( gen_cpp ) + fprintf(OUT, "Ptr%sMemberFunc %s::actions[%d] = {\n", theClassName, + theClassName, action_no+1); + else + fprintf(OUT, "void (*actions[%d])() = {\n", action_no+1); + if ( gen_cpp ) +/* fprintf(OUT, "\t(Ptr%sMemberFunc)&%s::erraction,\n", theClassName, theClassName);*/ + fprintf(OUT, "\t&%s::erraction,\n", theClassName); + else + fprintf(OUT, "\tzzerraction,\n"); + for (i=1; i=CHAR_RANGE) + break; + fprintf(OUT,", "); + if ((++items_on_line)>=MAX_ON_LINE){ + fprintf(OUT,"\n "); + items_on_line = 0; + } + } + fprintf(OUT, "\n};\n\n"); +} + + +#ifdef __USE_PROTOS +void p_base_table(void) +#else +void p_base_table() +#endif +{ + register int m; + + fprintf(OUT, "%sDfaState %sdfa_base[] = {\n", + gen_cpp?ClassName("::"):"static ", + gen_cpp?ClassName("::"):""); + for(m=0; m<(mode_counter-1); ++m) + fprintf(OUT, "\t%d,\n", dfa_basep[m]-1); + fprintf(OUT, "\t%d\n};\n\n", dfa_basep[m]-1); +} + + +#ifdef __USE_PROTOS +void p_class_table(void) /* MR1 */ +#else +void p_class_table() /* MR1 */ +#endif +{ +#if 0 + register int m; + + fprintf(OUT,"%s int %sdfa_class_no[] = {\n", + gen_cpp?"":"static", + gen_cpp?ClassName("::"):""); + for(m=0; m<(mode_counter-1); ++m) + fprintf(OUT,"\t%d,\n", dfa_class_nop[m]); + fprintf(OUT,"\t%d\n};\n\n", dfa_class_nop[m]); +#endif +} + + +#ifdef __USE_PROTOS +void p_bshift_table(void) /* MR1 */ +#else +void p_bshift_table() /* MR1 */ +#endif +{ + register int m; + + fprintf(OUT,"%s unsigned char *%sb_class_no[] = {\n", + gen_cpp?"":"static", + gen_cpp?ClassName("::"):""); + for(m=0; m<(mode_counter-1); ++m) + fprintf(OUT, "\tshift%d,\n", m); + fprintf(OUT, "\tshift%d\n};\n\n", m); +} + + +#ifdef __USE_PROTOS +void p_alternative_table(void) /* MR1 */ +#else +void p_alternative_table() /* MR1 */ +#endif +{ + register int i; + + if ( !gen_cpp ) fprintf(OUT, "#define ZZINTERACTIVE\n\n"); + if ( gen_cpp ) + fprintf(OUT, "DLGChar %salternatives[%d] = {\n", /* mr23 vhs %sDfaStates+1 */ + ClassName("::"), + dfa_allocated+1); /* vhs ClassName("::")); */ + else + fprintf(OUT, "static %s zzalternatives[DfaStates+1] = {\n", + minsize(dfa_allocated)); + + for(i=1; i<=dfa_allocated; ++i) + fprintf(OUT, "\t%d,\n", DFA(i)->alternatives); + fprintf(OUT, "/* must have 0 for zzalternatives[DfaStates] */\n"); + fprintf(OUT, "\t0\n};\n\n"); +} + + +#ifdef __USE_PROTOS +void p_mode_def(char *s,int m) /* MR1 */ +#else +void p_mode_def(s,m) /* MR1 */ +char *s; +int m; +#endif +{ + if ( gen_cpp ) + { + mode_name[cur_mode] = mystrdup(s); + mode_number[cur_mode] = m; + cur_mode++; + } + else + fprintf(mode_stream, "#define %s %d\n", s, m); +} + +#ifdef __USE_PROTOS +char * ClassName(char *suffix) +#else +char * ClassName(suffix) +char *suffix; +#endif +{ + static char buf[200]; + extern char *class_name; + + sprintf(buf, "%s%s", class_name, suffix); + return buf; +} + +#ifdef DEBUG + +/* print out a particular nfa node that is pointed to by p */ + +#ifdef __USE_PROTOS +void p_nfa_node(nfa_node *p) +#else +void p_nfa_node(p) +nfa_node *p; +#endif +{ + register nfa_node *t; + + if (p != NIL_INDEX){ + printf("NFA state : %d\naccept state : %d\n", + NFA_NO(p),p->accept); + if (p->trans[0] != NIL_INDEX){ + printf("trans[0] => %d on ", NFA_NO(p->trans[0])); + p_set(p->label); + printf("\n"); + } + else + printf("trans[0] => nil\n"); + if (p->trans[1] != NIL_INDEX) + printf("trans[1] => %d on epsilon\n", + NFA_NO(p->trans[1])); + else + printf("trans[1] => nil\n"); + printf("\n"); + } +} +#endif + +#ifdef DEBUG + +/* code to print out special structures when using a debugger */ + +#ifdef __USE_PROTOS +void p_nfa(p) +#else +void p_nfa(nfa_node *p) +nfa_node *p; /* state number also index into array */ +#endif +{ +/* each node has a marker on it so it only gets printed once */ + + operation_no++; /* get new number */ + s_p_nfa(p); +} + +#ifdef __USE_PROTOS +void s_p_nfa(nfa_node *p) +#else +void s_p_nfa(p) +nfa_node *p; /* state number also index into array */ +#endif +{ + if ((p != NIL_INDEX) && (p->nfa_set != operation_no)){ + /* so it is only printed once */ + p->nfa_set = operation_no; + p_nfa_node(p); + s_p_nfa(p->trans[0]); + s_p_nfa(p->trans[1]); + } +} + +#ifdef __USE_PROTOS +void p_dfa_node(dfa_node *p) +#else +void p_dfa_node(p) +dfa_node *p; +#endif +{ + int i; + + if (p != NIL_INDEX){ + printf("DFA state :%d\n",NFA_NO(p)); + if (p->done) + printf("done\n"); + else + printf("undone\n"); + printf("from nfa states : "); + p_set(p->nfa_states); + printf("\n"); + /* NOTE: trans arcs stored as ints rather than pointer*/ + for (i=0; itrans[i]); + } + printf("\n\n"); + } +} + +#ifdef __USE_PROTOS +void p_dfa(void) +#else +void p_dfa() +#endif +{ +/* prints out all the dfa nodes actually allocated */ + + int i; + + for (i = 1; i<=dfa_allocated; i++) + p_dfa_node(NFA(i)); +} + + +/* print out numbers in the set label */ + +#ifdef __USE_PROTOS +void p_set(set label) +#else +void p_set(label) +set label; +#endif +{ + unsigned *t, *e; + + if (set_nil(label)){ + printf("epsilon\n"); + }else{ + t = e = set_pdq(label); + while(*e != nil){ + printf("%d ", (*e+MIN_CHAR)); + e++; + } + printf("\n"); + free(t); + } + +} +#endif diff --git a/Tools/Source/TianoTools/Pccts/dlg/parser.dlg b/Tools/Source/TianoTools/Pccts/dlg/parser.dlg new file mode 100644 index 0000000000..df9a637f9e --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/parser.dlg @@ -0,0 +1,398 @@ +<< +/* parser.dlg -- DLG Description of scanner + * + * Generated from: dlg_p.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include +#include "dlg.h" +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +LOOKAHEAD + +void +#ifdef __USE_PROTOS +zzerraction(void) +#else +zzerraction() +#endif +{ + (*zzerr)("invalid token"); + zzadvance(); + zzskip(); +} +>> + +<<%%lexaction + +int func_action; /* should actions be turned into functions?*/ +int lex_mode_counter = 0; /* keeps track of the number of %%names */ +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via <<%%lexmember...>> */ +/* MR1 */ +int lexMember = 0; /* <<%%lexmemeber ...>> MR1 */ +int lexAction = 0; /* <<%%lexaction ...>> MR1 */ +int parserClass = 0; /* <<%%parserclass ...>> MR1 */ +int lexPrefix = 0; /* <<%%lexprefix ...>> MR1 */ +char theClassName[100]; /* MR11 */ +char *pClassName=theClassName; /* MR11 */ +int firstLexMember=1; /* MR1 */ + +#ifdef __USE_PROTOS +void xxputc(int c) { /* MR1 */ +#else + void xxputc(c) /* MR1 */ + int c; /* MR1 */ + { /* MR1 */ +#endif + if (parserClass) { /* MR1 */ + *pClassName++=c; /* MR1 */ + *pClassName=0; /* MR1 */ + } else if (lexMember || lexPrefix) { /* MR1 */ + if (class_stream != NULL) fputc(c,class_stream); /* MR1 */ + } else { /* MR1 */ + fputc(c,OUT); /* MR1 */ + }; /* MR1 */ + } /* MR1 */ + +#ifdef __USE_PROTOS + void xxprintf(char *format,char *string) { /* MR1 */ +#else + void xxprintf(format,string) /* MR1 */ + char *format; /* MR1 */ + char *string; /* MR1 */ + { /* MR1 */ +#endif + if (lexMember || lexPrefix || parserClass) { /* MR1 */ + if (class_stream != NULL) /* MR1 */ + fprintf(class_stream,format,string); /* MR1 */ + } else { /* MR1 */ + fprintf(OUT,format,string); /* MR1 */ + }; /* MR1 */ + } /* MR1 */ +>> + + +%%START + +@ + << + NLA = 1; + >> + +[\r\t\ ]+ + << + NLA = 2; + zzskip(); + >> + +\n + << + NLA = 3; + zzline++; zzskip(); DAWDLE; + >> + +\@ + << + NLA = L_EOF; + >> + +\%\% + << + NLA = PER_PER; + >> + +\%\%[a-zA-Z_][a-zA-Z0-9_]* + << + NLA = NAME_PER_PER; + p_mode_def(&zzlextext[2],lex_mode_counter++); + >> + +\<\<\%\%lexmember + << + NLA = LEXMEMBER; + lexMember=1; /* MR1 */ + if (firstLexMember != 0) { /* MR1 */ + firstLexMember=0; /* MR1 */ + p_class_def1(); /* MR1 */ + }; /* MR1 */ + zzmode(ACT); /* MR1 */ + >> + +\<\<\%\%lexaction + << + NLA = LEXACTION; + lexAction=1;zzmode(ACT); + >> + +\<\<\%\%parserclass + << + NLA = PARSERCLASS; + parserClass=1; /* MR1 */ + zzmode(ACT); /* MR1 */ + >> + +\<\<\%\%lexprefix + << + NLA = LEXPREFIX; + lexPrefix=1;zzmode(ACT); + >> + +\<\< + << + NLA = ACTION; + if (func_action) + fprintf(OUT,"\n%s %sact%d()\n{ ", + gen_cpp?"ANTLRTokenType":"static void", + gen_cpp?ClassName("::"):"", ++action_no); + zzmode(ACT); zzskip(); + >> + +\>\> + << + NLA = GREAT_GREAT; + >> + +\{ + << + NLA = L_BRACE; + >> + +\} + << + NLA = R_BRACE; + >> + +\( + << + NLA = L_PAR; + >> + +\) + << + NLA = R_PAR; + >> + +\[ + << + NLA = L_BRACK; + >> + +\] + << + NLA = R_BRACK; + >> + +\* + << + NLA = ZERO_MORE; + >> + +\+ + << + NLA = ONE_MORE; + >> + +\| + << + NLA = OR; + >> + +\- + << + NLA = RANGE; + >> + +\~ + << + NLA = NOT; + >> + +\\0[0-7]* + << + NLA = OCTAL_VALUE; + {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;} + >> + +\\0[Xx][0-9a-fA-F]+ + << + NLA = HEX_VALUE; + {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;} + >> + +\\[1-9][0-9]* + << + NLA = DEC_VALUE; + {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;} + >> + +\\t + << + NLA = TAB; + zzlextext[0] = '\t'; + >> + +\\n + << + NLA = NL; + zzlextext[0] = '\n'; + >> + +\\r + << + NLA = CR; + zzlextext[0] = '\r'; + >> + +\\b + << + NLA = BS; + zzlextext[0] = '\b'; + >> + +\\ \n + << + NLA = CONTINUATION; + zzline++; zzskip(); + >> + +\\~[tnrb] + << + NLA = LIT; + zzlextext[0] = zzlextext[1]; + >> + +~[\\] + << + NLA = REGCHAR; + >> + + +%%ACT + +@ + << + NLA = 1; + error("unterminated action", zzline); zzmode(START); + >> + +\>\> + << + NLA = ACTION; + if (func_action) fprintf(OUT,"}\n\n"); + zzmode(START); + /* MR1 */ + /* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ + /* MR1 via <<%%lexmember ...>> */ + /* MR1 This is a consequence of not saving actions */ + /* MR1 */ + /* MR1 */ parserClass=0; + /* MR1 */ lexPrefix=0; + /* MR1 */ lexAction=0; + /* MR1 */ lexMember=0; + >> + +\> + << + NLA = 34; + xxputc(zzlextext[0]); zzskip(); + >> + +\\\> + << + NLA = 35; + xxputc('>'); zzskip(); + >> + +\\ + << + NLA = 36; + xxputc('\\'); zzskip(); + >> + +\n + << + NLA = 37; + xxputc(zzlextext[0]); ++zzline; zzskip(); + >> + +/\* + << + NLA = 38; + zzmode(ACTION_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> + +// + << + NLA = 39; + zzmode(ACTION_CPP_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> + +~[] + << + NLA = 40; + xxputc(zzlextext[0]); zzskip(); + >> + + +%%ACTION_COMMENTS + +@ + << + NLA = 1; + >> + +\*/ + << + NLA = 41; + zzmode(ACT); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> + +[\n\r] + << + NLA = 42; + zzline++; xxputc(zzlextext[0]); zzskip(); + >> + +~[] + << + NLA = 43; + xxputc(zzlextext[0]); zzskip(); + >> + + +%%ACTION_CPP_COMMENTS + +@ + << + NLA = 1; + >> + +[\n\r] + << + NLA = 44; + zzmode(ACT); zzline++; /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> + +~[] + << + NLA = 45; + xxputc(zzlextext[0]); zzskip(); + >> + +%% diff --git a/Tools/Source/TianoTools/Pccts/dlg/relabel.c b/Tools/Source/TianoTools/Pccts/dlg/relabel.c new file mode 100644 index 0000000000..0b8bc163d1 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/relabel.c @@ -0,0 +1,217 @@ +/* This group of functions does the character class compression. + It goes over the dfa and relabels the arcs with the partitions + of characters in the NFA. The partitions are stored in the + array class. + + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#endif /* __STDC__ */ +#endif + +int class_no = CHAR_RANGE; /* number of classes for labels */ +int first_el[CHAR_RANGE]; /* first element in each class partition */ +set class_sets[CHAR_RANGE]; /* array holds partitions from class */ + /* compression */ + +/* goes through labels on NFA graph and partitions the characters into + * character classes. This reduces the amount of space required for each + * dfa node, since only one arc is required each class instead of one arc + * for each character + * level: + * 0 no compression done + * 1 remove unused characters from classes + * 2 compress equivalent characters into same class + * + * returns the number of character classes required + */ +#ifdef __USE_PROTOS +int relabel(nfa_node* start,int level) +#else +int relabel(start,level) +int level; +nfa_node *start; +#endif +{ + if (level){ + set_free(used_classes); + partition(start,level); + label_with_classes(start); + }else{ + /* classes equivalent to all characters in alphabet */ + class_no = CHAR_RANGE; + } + return class_no; +} + +/* makes character class sets for new labels */ +#ifdef __USE_PROTOS +void partition(nfa_node* start,int level) +#else +void partition(start,level) +nfa_node *start; /* beginning of nfa graph */ +int level; /* compression level to uses */ +#endif +{ + set current_class; + set unpart_chars; + set temp; + + unpart_chars = set_dup(used_chars); +#if 0 + /* EOF (-1+1) alway in class 0 */ + class_sets[0] = set_of(0); + first_el[0] = 0; + used_classes = set_of(0); + temp = set_dif(unpart_chars, class_sets[0]); + set_free(unpart_chars); + unpart_chars = temp; + class_no = 1; +#else + class_no = 0; +#endif + while (!set_nil(unpart_chars)){ + /* don't look for equivalent labels if c <= 1 */ + if (level <= 1){ + current_class = set_of(set_int(unpart_chars)); + }else{ + current_class = set_dup(unpart_chars); + intersect_nfa_labels(start,¤t_class); + } + set_orel(class_no,&used_classes); + first_el[class_no] = set_int(current_class); + class_sets[class_no] = current_class; + temp = set_dif(unpart_chars,current_class); + set_free(unpart_chars); + unpart_chars = temp; + ++class_no; + } + + /* free unpart_chars -ATG 5/6/95 */ + set_free(unpart_chars); + +#if 0 + /* group all the other unused characters into a class */ + set_orel(class_no,&used_classes); + first_el[class_no] = set_int(current_class); + class_sets[class_no] = set_dif(normal_chars,used_chars); + ++class_no; +#endif +} + + +/* given pointer to beginning of graph and recursively walks it trying + * to find a maximal partition. This partion in returned in maximal_class + */ +#ifdef __USE_PROTOS +void intersect_nfa_labels(nfa_node* start,set* maximal_class) +#else +void intersect_nfa_labels(start,maximal_class) +nfa_node *start; +set *maximal_class; +#endif +{ + /* pick a new operation number */ + ++operation_no; + r_intersect(start,maximal_class); +} + +#ifdef __USE_PROTOS +void r_intersect(nfa_node* start,set* maximal_class) +#else +void r_intersect(start,maximal_class) +nfa_node *start; +set * maximal_class; +#endif +{ + set temp; + + if(start && start->nfa_set != operation_no) + { + start->nfa_set = operation_no; + temp = set_and(*maximal_class,start->label); + if (!set_nil(temp)) + { + set_free(*maximal_class); + *maximal_class = temp; + }else{ + set_free(temp); + } + r_intersect(start->trans[0],maximal_class); + r_intersect(start->trans[1],maximal_class); + } +} + + +/* puts class labels in place of old character labels */ +#ifdef __USE_PROTOS +void label_with_classes(nfa_node* start) +#else +void label_with_classes(start) +nfa_node *start; +#endif +{ + ++operation_no; + label_node(start); +} + +#ifdef __USE_PROTOS +void label_node(nfa_node *start) +#else +void label_node(start) +nfa_node *start; +#endif +{ + set new_label; + register int i; + + /* only do node if it hasn't been done before */ + if (start && start->nfa_set != operation_no){ + start->nfa_set = operation_no; + new_label = empty; + for (i = 0; ilabel)) + set_orel(i,&new_label); + } + set_free(start->label); + start->label = new_label; + /* do any nodes that can be reached from this one */ + label_node(start->trans[0]); + label_node(start->trans[1]); + } +} diff --git a/Tools/Source/TianoTools/Pccts/dlg/stdpccts.h b/Tools/Source/TianoTools/Pccts/dlg/stdpccts.h new file mode 100644 index 0000000000..06ec67e44d --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/stdpccts.h @@ -0,0 +1,26 @@ +#ifndef STDPCCTS_H +#define STDPCCTS_H +/* + * stdpccts.h -- P C C T S I n c l u d e + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#ifndef ANTLR_VERSION +#define ANTLR_VERSION 13333 +#endif + +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include +#include "dlg.h" +#define zzSET_SIZE 8 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "mode.h" +#endif diff --git a/Tools/Source/TianoTools/Pccts/dlg/support.c b/Tools/Source/TianoTools/Pccts/dlg/support.c new file mode 100644 index 0000000000..84fe99d69c --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/support.c @@ -0,0 +1,240 @@ +/* + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#endif /* __STDC__ */ +#endif + +int err_found = 0; /* indicates whether problem found */ + +#ifdef __USE_PROTOS +void internal_error(char *s, char *file,int line) /* MR9 23-Sep-97 */ +#else +void internal_error(s,file,line) /* MR9 23-Sep-97 */ +char *s,*file; +int line; +#endif +{ + fprintf(stderr,s,file,line); + exit(PCCTS_EXIT_FAILURE); +} + +#ifdef __USE_PROTOS +char *dlg_malloc(int bytes,char *file,int line) +#else +char *dlg_malloc(bytes,file,line) +int bytes; +char *file; +int line; +#endif +{ + char *t; + + t = (char *) malloc(bytes); + if (!t){ + /* error */ + internal_error("%s(%d): unable to allocate memory\n", + file,line); + } + return t; +} + + +#ifdef __USE_PROTOS +char *dlg_calloc(int n,int bytes,char *file,int line) +#else +char *dlg_calloc(n,bytes,file,line) +int n,bytes; +char *file; +int line; +#endif +{ + char *t; + + t = (char *) calloc(n,bytes); + if (!t){ + /* error */ + internal_error("%s(%d): unable to allocate memory\n", + file,line); + } + return t; +} + + +#ifdef __USE_PROTOS +FILE *read_stream(char *name) +#else +FILE *read_stream(name) +char *name; +#endif +{ + FILE *f; + + if (name){ + if (name[0] == '-') { + fprintf(stderr, "dlg: invalid option: '%s'\n", name); + f = NULL; + }else{ + f = fopen(name, "r"); + if (f == NULL){ + /* couldn't open file */ + fprintf(stderr, + "dlg: Warning: Can't read file %s.\n", + name); + } + } + }else{ + /* open stdin if nothing there */ + f = stdin; + } + return f; +} + +#ifdef __USE_PROTOS +FILE *write_stream(char *name) +#else +FILE *write_stream(name) +char *name; +#endif +{ + FILE *f; + + if (name){ + if (name[0] == '-') { + fprintf(stderr, "dlg: invalid option: '%s'\n", name); + f = NULL; + }else{ + f = fopen(OutMetaName(name), "w"); + if (f == NULL){ + /* couldn't open file */ + fprintf(stderr, + "dlg: Warning: Can't write to file %s.\n", + name); + } + else +#ifdef SPECIAL_FOPEN + special_fopen_actions(OutMetaName(name)); /* MR1 */ +#else + ; /* MR1 */ +#endif + } + }else{ + /* open stdout if nothing there */ + f = stdout; + } + return f; +} + + +#ifdef __USE_PROTOS +void fatal(char *message,int line_no) +#else +void fatal(message,line_no) +char *message; +int line_no; +#endif +{ + fprintf(stderr,ErrHdr, + (file_str[0] ? file_str[0] : "stdin"), line_no); + fprintf(stderr, " Fatal: %s\n", message); + exit(PCCTS_EXIT_FAILURE); +} + +#ifdef __USE_PROTOS +void error(char *message,int line_no) +#else +void error(message,line_no) +char *message; +int line_no; +#endif +{ + fprintf(stderr,ErrHdr, + (file_str[0] ? file_str[0] : "stdin"), line_no); + fprintf(stderr, " Error: %s\n", message); + err_found = 1; +} + +#ifdef __USE_PROTOS +void warning(char *message,int line_no) +#else +void warning(message,line_no) +char *message; +int line_no; +#endif +{ + fprintf(stderr,ErrHdr, + (file_str[0] ? file_str[0] : "stdin"), line_no); + fprintf(stderr, " Warning: %s\n", message); +} + +/* MR10: Jeff Vincent + MR10: Changed to remove directory information from n only if + MR10: if OutputDirectory was changed by user (-o option) +*/ + +#ifdef __USE_PROTOS +char *OutMetaName(char *n) +#else +char *OutMetaName(n) +char *n; +#endif +{ + static char *dir_sym = DirectorySymbol; + static char newname[MaxFileName+1]; + char *p; + + /* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */ + if (strcmp(OutputDirectory, TopDirectory) == 0) + return n; + + /* p will point to filename without path information */ + if ((p = strrchr(n, *dir_sym)) != NULL) + p++; + else + p = n; + + /* Copy new output directory into newname[] */ + strcpy(newname, OutputDirectory); + + /* if new output directory does not have trailing dir_sym, add it! */ + if (newname[strlen(newname)-1] != *dir_sym) + strcat(newname, dir_sym); + + /* contatenate FILE NAME ONLY to new output directory */ + strcat(newname, p); + + return newname; +} diff --git a/Tools/Source/TianoTools/Pccts/dlg/tokens.h b/Tools/Source/TianoTools/Pccts/dlg/tokens.h new file mode 100644 index 0000000000..73e502b7e1 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/dlg/tokens.h @@ -0,0 +1,133 @@ +#ifndef tokens_h +#define tokens_h +/* tokens.h -- List of labelled tokens and stuff + * + * Generated from: dlg_p.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * ANTLR Version 1.33MR33 + */ +#define zzEOF_TOKEN 1 +#define L_EOF 4 +#define PER_PER 5 +#define NAME_PER_PER 6 +#define LEXMEMBER 7 +#define LEXACTION 8 +#define PARSERCLASS 9 +#define LEXPREFIX 10 +#define ACTION 11 +#define GREAT_GREAT 12 +#define L_BRACE 13 +#define R_BRACE 14 +#define L_PAR 15 +#define R_PAR 16 +#define L_BRACK 17 +#define R_BRACK 18 +#define ZERO_MORE 19 +#define ONE_MORE 20 +#define OR 21 +#define RANGE 22 +#define NOT 23 +#define OCTAL_VALUE 24 +#define HEX_VALUE 25 +#define DEC_VALUE 26 +#define TAB 27 +#define NL 28 +#define CR 29 +#define BS 30 +#define CONTINUATION 31 +#define LIT 32 +#define REGCHAR 33 + +#ifdef __USE_PROTOS +void grammar(void); +#else +extern void grammar(); +#endif + +#ifdef __USE_PROTOS +void start_states(void); +#else +extern void start_states(); +#endif + +#ifdef __USE_PROTOS +void do_conversion(void); +#else +extern void do_conversion(); +#endif + +#ifdef __USE_PROTOS +void rule_list(void); +#else +extern void rule_list(); +#endif + +#ifdef __USE_PROTOS +void rule(void); +#else +extern void rule(); +#endif + +#ifdef __USE_PROTOS +void reg_expr(void); +#else +extern void reg_expr(); +#endif + +#ifdef __USE_PROTOS +void and_expr(void); +#else +extern void and_expr(); +#endif + +#ifdef __USE_PROTOS +void repeat_expr(void); +#else +extern void repeat_expr(); +#endif + +#ifdef __USE_PROTOS +void expr(void); +#else +extern void expr(); +#endif + +#ifdef __USE_PROTOS +void atom_list(void); +#else +extern void atom_list(); +#endif + +#ifdef __USE_PROTOS +void near_atom(void); +#else +extern void near_atom(); +#endif + +#ifdef __USE_PROTOS +void atom(void); +#else +extern void atom(); +#endif + +#ifdef __USE_PROTOS +void anychar(void); +#else +extern void anychar(); +#endif + +#endif +extern SetWordType zzerr1[]; +extern SetWordType zzerr2[]; +extern SetWordType zzerr3[]; +extern SetWordType setwd1[]; +extern SetWordType zzerr4[]; +extern SetWordType zzerr5[]; +extern SetWordType zzerr6[]; +extern SetWordType setwd2[]; +extern SetWordType zzerr7[]; +extern SetWordType zzerr8[]; +extern SetWordType zzerr9[]; +extern SetWordType setwd3[]; diff --git a/Tools/Source/TianoTools/Pccts/h/AParser.cpp b/Tools/Source/TianoTools/Pccts/h/AParser.cpp new file mode 100644 index 0000000000..720fe75af1 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/AParser.cpp @@ -0,0 +1,871 @@ +/* ANTLRParser.C + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +#include "pccts_stdlib.h" +#include "pccts_stdarg.h" +#include "pccts_string.h" +#include "pccts_stdio.h" + +PCCTS_NAMESPACE_STD + +/* I have to put this here due to C++ limitation + * that you can't have a 'forward' decl for enums. + * I hate C++!!!!!!!!!!!!!!! + * Of course, if I could use real templates, this would go away. + */ +// MR1 +// MR1 10-Apr-97 133MR1 Prevent use of varying sizes for the +// MR1 ANTLRTokenType enum +// MR1 + +enum ANTLRTokenType { TER_HATES_CPP=0, ITS_TOO_COMPLICATED=9999}; // MR1 + +#define ANTLR_SUPPORT_CODE + +#include ATOKEN_H +#include ATOKENBUFFER_H +#include APARSER_H + +static const int zzINF_DEF_TOKEN_BUFFER_SIZE = 2000; /* MR14 */ +static const int zzINF_BUFFER_TOKEN_CHUNK_SIZE = 1000; /* MR14 */ + + /* L o o k a h e a d M a c r o s */ + +/* maximum of 32 bits/unsigned int and must be 8 bits/byte; + * we only use 8 bits of it. + */ +SetWordType ANTLRParser::bitmask[sizeof(SetWordType)*8] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080 +}; + +char ANTLRParser::eMsgBuffer[500] = ""; + +ANTLRParser:: +~ANTLRParser() +{ + delete [] token_type; + delete [] zzFAILtext; // MR16 Manfred Kogler +} + +ANTLRParser:: +ANTLRParser(ANTLRTokenBuffer *_inputTokens, + int k, + int use_inf_look, + int dlook, + int ssize) +{ + LLk = k; + can_use_inf_look = use_inf_look; +/* MR14 */ if (dlook != 0) { +/* MR14 */ panic("ANTLRParser::ANTLRParser - Demand lookahead not supported in C++ mode"); +/* MR14 */ +/* MR14 */ }; + demand_look = 0; /* demand_look = dlook; */ + bsetsize = ssize; + guessing = 0; + token_tbl = NULL; + eofToken = (ANTLRTokenType)1; + + // allocate lookahead buffer + token_type = new ANTLRTokenType[LLk]; + lap = 0; + labase = 0; +#ifdef ZZDEFER_FETCH + stillToFetch = 0; // MR19 +#endif + dirty = 0; + inf_labase = 0; // MR7 + inf_last = 0; // MR7 + /* prime lookahead buffer, point to inputTokens */ + this->inputTokens = _inputTokens; + this->inputTokens->setMinTokens(k); + _inputTokens->setParser(this); // MR1 + resynchConsumed=1; // MR8 + zzFAILtext=NULL; // MR9 + traceOptionValueDefault=0; // MR10 + traceReset(); // MR10 + zzGuessSeq=0; // MR10 + syntaxErrCount=0; // MR11 +} + +void ANTLRParser::init() +{ + prime_lookahead(); + resynchConsumed=1; // MR8 + traceReset(); // MR10 +} + +void ANTLRParser::traceReset() +{ + traceOptionValue=traceOptionValueDefault; + traceGuessOptionValue=1; + traceCurrentRuleName=NULL; + traceDepth=0; +} + + +#ifdef _MSC_VER // MR23 +//Turn off warning: +//interaction between '_setjmp' and C++ object destruction is non-portable +#pragma warning(disable : 4611) +#endif +int ANTLRParser:: +guess(ANTLRParserState *st) +{ + saveState(st); + guessing = 1; + return setjmp(guess_start.state); +} +#ifdef _MSC_VER // MR23 +#pragma warning(default: 4611) +#endif + +void ANTLRParser:: +saveState(ANTLRParserState *buf) +{ + buf->guess_start = guess_start; + buf->guessing = guessing; + buf->inf_labase = inf_labase; + buf->inf_last = inf_last; + buf->dirty = dirty; + buf->traceOptionValue=traceOptionValue; /* MR10 */ + buf->traceGuessOptionValue=traceGuessOptionValue; /* MR10 */ + buf->traceCurrentRuleName=traceCurrentRuleName; /* MR10 */ + buf->traceDepth=traceDepth; /* MR10 */ +} + +void ANTLRParser:: +restoreState(ANTLRParserState *buf) +{ + int i; + int prevTraceOptionValue; + + guess_start = buf->guess_start; + guessing = buf->guessing; + inf_labase = buf->inf_labase; + inf_last = buf->inf_last; + dirty = buf->dirty; + + // restore lookahead buffer from k tokens before restored TokenBuffer position + // if demand_look, then I guess we don't look backwards for these tokens. + for (i=1; i<=LLk; i++) token_type[i-1] = + inputTokens->bufferedToken(i-LLk)->getType(); + lap = 0; + labase = 0; + + /* MR10 */ + + prevTraceOptionValue=traceOptionValue; + traceOptionValue=buf->traceOptionValue; + if ( (prevTraceOptionValue > 0) != + (traceOptionValue > 0)) { + if (traceCurrentRuleName != NULL) { /* MR21 */ + if (traceOptionValue > 0) { + /* MR23 */ printMessage(stderr, + "trace enable restored in rule %s depth %d\n", + traceCurrentRuleName, + traceDepth); + }; + if (traceOptionValue <= 0) { + /* MR23 */ printMessage(stderr, + "trace disable restored in rule %s depth %d\n", + traceCurrentRuleName, /* MR21 */ + traceDepth); + }; + } + }; + traceGuessOptionValue=buf->traceGuessOptionValue; + traceCurrentRuleName=buf->traceCurrentRuleName; + traceDepth=buf->traceDepth; + traceGuessDone(buf); +} + +/* Get the next symbol from the input stream; put it into lookahead buffer; + * fill token_type[] fast reference cache also. NLA is the next place where + * a lookahead ANTLRAbstractToken should go. + */ +void ANTLRParser:: +consume() +{ + +#ifdef ZZDEBUG_CONSUME_ACTION + zzdebug_consume_action(); +#endif + +// MR19 V.H. Simonis +// Defer Fetch feature +// Moves action of consume() into LA() function + +#ifdef ZZDEFER_FETCH + stillToFetch++; +#else + NLA = inputTokens->getToken()->getType(); + dirty--; + lap = (lap+1)&(LLk-1); +#endif + +} + +_ANTLRTokenPtr ANTLRParser:: +LT(int i) +{ + +// MR19 V.H. Simonis +// Defer Fetch feature +// Moves action of consume() into LA() function + +#ifdef ZZDEFER_FETCH + undeferFetch(); +#endif + +#ifdef DEBUG_TOKENBUFFER + if ( i >= inputTokens->bufferSize() || inputTokens->minTokens() < LLk ) /* MR20 Was "<=" */ + { + char buf[2000]; /* MR20 Was "static" */ + sprintf(buf, "The minimum number of tokens you requested that the\nANTLRTokenBuffer buffer is not enough to satisfy your\nLT(%d) request; increase 'k' argument to constructor for ANTLRTokenBuffer\n", i); + panic(buf); + } +#endif + return inputTokens->bufferedToken(i-LLk); +} + +void +ANTLRParser:: +look(int k) +{ + int i, c = k - (LLk-dirty); + for (i=1; i<=c; i++) consume(); +} + +/* fill the lookahead buffer up with k symbols (even if DEMAND_LOOK); + */ +void +ANTLRParser:: +prime_lookahead() +{ + int i; + for(i=1;i<=LLk; i++) consume(); + dirty=0; + // lap = 0; // MR14 Sinan Karasu (sinan.karasu@boeing.com) + // labase = 0; // MR14 + labase=lap; // MR14 +} + +/* check to see if the current input symbol matches '_t'. + * During NON demand lookahead mode, dirty will always be 0 and + * hence the extra code for consuming tokens in _match is never + * executed; the same routine can be used for both modes. + */ +int ANTLRParser:: +_match(ANTLRTokenType _t, ANTLRChar **MissText, + ANTLRTokenType *MissTok, _ANTLRTokenPtr *BadTok, + SetWordType **MissSet) +{ + if ( dirty==LLk ) { + consume(); + } + if ( LA(1)!=_t ) { + *MissText=NULL; + *MissTok= _t; + *BadTok = LT(1); + *MissSet=NULL; + return 0; + } + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look + return 1; +} + +/* check to see if the current input symbol matches '_t'. + * Used during exception handling. + */ +int ANTLRParser:: +_match_wsig(ANTLRTokenType _t) +{ + if ( dirty==LLk ) { + consume(); + } + if ( LA(1)!=_t ) return 0; + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look + return 1; +} + +/* check to see if the current input symbol matches any token in a set. + * During NON demand lookahead mode, dirty will always be 0 and + * hence the extra code for consuming tokens in _match is never + * executed; the same routine can be used for both modes. + */ +int ANTLRParser:: +_setmatch(SetWordType *tset, ANTLRChar **MissText, + ANTLRTokenType *MissTok, _ANTLRTokenPtr *BadTok, + SetWordType **MissSet, SetWordType *tokclassErrset) +{ + if ( dirty==LLk ) { + consume(); + } + if ( !set_el(LA(1), tset) ) { + *MissText=NULL; /* MR23 */ + *MissTok=(ANTLRTokenType) 0; /* MR23 */ + *BadTok=LT(1); /* MR23 */ + *MissSet=tokclassErrset; /* MR23 */ + return 0; + } + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look + return 1; +} + +int ANTLRParser:: +_setmatch_wsig(SetWordType *tset) +{ + if ( dirty==LLk ) { + consume(); + } + if ( !set_el(LA(1), tset) ) return 0; + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look + return 1; +} + + /* Exception handling routines */ +// +// 7-Apr-97 133MR1 +// Change suggested by Eli Sternheim (eli@interhdl.com) +// +void ANTLRParser:: +consumeUntil(SetWordType *st) +{ + ANTLRTokenType tmp; // MR1 + const int Eof=1; // MR1 + while ( !set_el( (tmp=LA(1)), st) && tmp!=Eof) { consume(); } // MR1 +} + +// +// 7-Apr-97 133MR1 +// Change suggested by Eli Sternheim (eli@interhdl.com) +// +void ANTLRParser:: +consumeUntilToken(int t) +{ + int tmp; // MR1 + const int Eof=1; // MR1 + while ( (tmp=LA(1)) !=t && tmp!=Eof) { consume(); } // MR1 +} + + + /* Old error stuff */ + +void ANTLRParser:: +resynch(SetWordType *wd,SetWordType mask) +{ + +/* MR8 S.Bochnak@microtool.com.pl */ +/* MR8 Change file scope static "consumed" to instance var */ + + /* if you enter here without having consumed a token from last resynch + * force a token consumption. + */ +/* MR8 */ if ( !resynchConsumed ) {consume(); resynchConsumed=1; return;} + + /* if current token is in resynch set, we've got what we wanted */ + +/* MR8 */ if ( wd[LA(1)]&mask || LA(1) == eofToken ) {resynchConsumed=0; return;} + + /* scan until we find something in the resynch set */ + + while ( !(wd[LA(1)]&mask) && LA(1) != eofToken ) {consume();} + +/* MR8 */ resynchConsumed=1; +} + +/* standard error reporting function that assumes DLG-based scanners; + * you should redefine in subclass to change it or if you use your + * own scanner. + */ + +/* MR23 THM There appears to be a parameter "badText" passed to syn() + which is not present in the parameter list. This may be + because in C mode there is no attribute function which + returns the text, so the text representation of the token + must be passed explicitly. I think. +*/ + +void ANTLRParser:: +syn(_ANTLRTokenPtr /*tok MR23*/, ANTLRChar *egroup, SetWordType *eset, + ANTLRTokenType etok, int k) +{ + int line; + + line = LT(1)->getLine(); + + syntaxErrCount++; /* MR11 */ + + /* MR23 If the token is not an EOF token, then use the ->getText() value. + + If the token is the EOF token the text returned by ->getText() + may be garbage. If the text from the token table is "@" use + "" instead, because end-users don't know what "@" means. + If the text is not "@" then use that text, which must have been + supplied by the grammar writer. + */ + const char * errorAt = LT(1)->getText(); + if (LA(1) == eofToken) { + errorAt = parserTokenName(LA(1)); + if (errorAt[0] == '@') errorAt = ""; + } + /* MR23 */ printMessage(stderr, "line %d: syntax error at \"%s\"", + line, errorAt); + if ( !etok && !eset ) {/* MR23 */ printMessage(stderr, "\n"); return;} + if ( k==1 ) /* MR23 */ printMessage(stderr, " missing"); + else + { + /* MR23 */ printMessage(stderr, "; \"%s\" not", LT(k)->getText()); // MR23 use LT(k) since k>1 + if ( set_deg(eset)>1 ) /* MR23 */ printMessage(stderr, " in"); + } + if ( set_deg(eset)>0 ) edecode(eset); + else /* MR23 */ printMessage(stderr, " %s", token_tbl[etok]); + if ( strlen(egroup) > 0 ) /* MR23 */ printMessage(stderr, " in %s", egroup); + /* MR23 */ printMessage(stderr, "\n"); +} + +/* is b an element of set p? */ +int ANTLRParser:: +set_el(ANTLRTokenType b, SetWordType *p) +{ + return( p[DIVWORD(b)] & bitmask[MODWORD(b)] ); +} + +int ANTLRParser:: +set_deg(SetWordType *a) +{ + /* Fast compute degree of a set... the number + of elements present in the set. Assumes + that all word bits are used in the set + */ + register SetWordType *p = a; + register SetWordType *endp = &(a[bsetsize]); + register int degree = 0; + + if ( a == NULL ) return 0; + while ( p < endp ) + { + register SetWordType t = *p; + register SetWordType *b = &(bitmask[0]); + do { + if (t & *b) ++degree; + } while (++b < &(bitmask[sizeof(SetWordType)*8])); + p++; + } + + return(degree); +} + +void ANTLRParser:: +edecode(SetWordType *a) +{ + register SetWordType *p = a; + register SetWordType *endp = &(p[bsetsize]); + register unsigned e = 0; + + if ( set_deg(a)>1 ) /* MR23 */ printMessage(stderr, " {"); + do { + register SetWordType t = *p; + register SetWordType *b = &(bitmask[0]); + do { + if ( t & *b ) /* MR23 */ printMessage(stderr, " %s", token_tbl[e]); + e++; + } while (++b < &(bitmask[sizeof(SetWordType)*8])); + } while (++p < endp); + if ( set_deg(a)>1 ) /* MR23 */ printMessage(stderr, " }"); +} + +/* input looks like: + * zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk) + * where the zzMiss stuff is set here to the token that did not match + * (and which set wasn't it a member of). + */ + +// MR9 29-Sep-97 Stan Bochnak (S.Bochnak@microTool.com.pl) +// MR9 Original fix to static allocated text didn't +// MR9 work because a pointer to it was passed back +// MR9 to caller. Replace with instance variable. + +const int SETWORDCOUNT=20; + +void +ANTLRParser::FAIL(int k, ...) +{ +// +// MR1 10-Apr-97 +// + + if (zzFAILtext == NULL) zzFAILtext=new char [1000]; // MR9 + SetWordType **f=new SetWordType *[SETWORDCOUNT]; // MR1 // MR9 + SetWordType **miss_set; + ANTLRChar **miss_text; + _ANTLRTokenPtr *bad_tok; + ANTLRChar **bad_text; +// +// 7-Apr-97 133MR1 +// err_k is passed as a "int *", not "unsigned *" +// + int *err_k; // MR1 + int i; + va_list ap; + + va_start(ap, k); + + zzFAILtext[0] = '\0'; + if ( k > SETWORDCOUNT ) panic("FAIL: overflowed buffer"); + for (i=1; i<=k; i++) /* collect all lookahead sets */ + { + f[i-1] = va_arg(ap, SetWordType *); + } + for (i=1; i<=k; i++) /* look for offending token */ + { + if ( i>1 ) strcat(zzFAILtext, " "); + strcat(zzFAILtext, LT(i)->getText()); + if ( !set_el(LA(i), f[i-1]) ) break; + } + miss_set = va_arg(ap, SetWordType **); + miss_text = va_arg(ap, ANTLRChar **); + bad_tok = va_arg(ap, _ANTLRTokenPtr *); + bad_text = va_arg(ap, ANTLRChar **); + err_k = va_arg(ap, int *); // MR1 + if ( i>k ) + { + /* bad; lookahead is permutation that cannot be matched, + * but, the ith token of lookahead is valid at the ith position + * (The old LL sub 1 (k) versus LL(k) parsing technique) + */ + *miss_set = NULL; + *miss_text = LT(1)->getText(); + *bad_tok = LT(1); + *bad_text = (*bad_tok)->getText(); + *err_k = k; +// +// MR4 20-May-97 erroneously deleted contents of f[] +// MR4 reported by Bruce Guenter (bruceg@qcc.sk.ca) +// MR1 10-Apr-97 release temporary storage +// + delete [] f; // MR1 + return; // MR1 + } +/* MR23 printMessage(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/ + *miss_set = f[i-1]; + *miss_text = zzFAILtext; + *bad_tok = LT(i); + *bad_text = (*bad_tok)->getText(); + if ( i==1 ) *err_k = 1; + else *err_k = k; +// +// MR4 20-May-97 erroneously deleted contents of f[] +// MR4 reported by Bruce Guenter (bruceg@qcc.sk.ca) +// MR1 10-Apr-97 release temporary storage +// + delete [] f; // MR1 + return; // MR1 +} + +int ANTLRParser:: +_match_wdfltsig(ANTLRTokenType tokenWanted, SetWordType *whatFollows) +{ + if ( dirty==LLk ) consume(); + + if ( LA(1)!=tokenWanted ) + { + syntaxErrCount++; /* MR11 */ + /* MR23 */ printMessage(stderr, + "line %d: syntax error at \"%s\" missing %s\n", + LT(1)->getLine(), + (LA(1)==eofToken && LT(1)->getText()[0] == '@')?"":LT(1)->getText(), /* MR21a */ + token_tbl[tokenWanted]); + consumeUntil( whatFollows ); + return 0; + } + else { + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look +/* if ( !demand_look ) consume(); */ + return 1; + } +} + + +int ANTLRParser:: +_setmatch_wdfltsig(SetWordType *tokensWanted, + ANTLRTokenType tokenTypeOfSet, + SetWordType *whatFollows) +{ + if ( dirty==LLk ) consume(); + if ( !set_el(LA(1), tokensWanted) ) + { + syntaxErrCount++; /* MR11 */ + /* MR23 */ printMessage(stderr, + "line %d: syntax error at \"%s\" missing %s\n", + LT(1)->getLine(), + (LA(1)==eofToken && LT(1)->getText()[0] == '@')?"":LT(1)->getText(), /* MR21a */ + token_tbl[tokenTypeOfSet]); + consumeUntil( whatFollows ); + return 0; + } + else { + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look +/* if ( !demand_look ) consume(); */ + return 1; + } +} + +char *ANTLRParser:: +eMsgd(char *err,int d) +{ + sprintf(eMsgBuffer, err, d); // dangerous, but I don't care + return eMsgBuffer; +} + +char *ANTLRParser:: +eMsg(char *err, char *s) +{ + sprintf(eMsgBuffer, err, s); + return eMsgBuffer; +} + +char *ANTLRParser:: +eMsg2(char *err,char *s, char *t) +{ + sprintf(eMsgBuffer, err, s, t); + return eMsgBuffer; +} + +void ANTLRParser:: +panic(const char *msg) // MR20 const +{ + /* MR23 */ printMessage(stderr, "ANTLR panic: %s\n", msg); + exit(PCCTS_EXIT_FAILURE); // MR1 +} + +const ANTLRChar *ANTLRParser:: // MR1 +parserTokenName(int tok) { // MR1 + return token_tbl[tok]; // MR1 +} // MR1 + +void ANTLRParser::traceGuessDone(const ANTLRParserState *state) { + + int doIt=0; + + if (traceCurrentRuleName == NULL) return; + + if (traceOptionValue <= 0) { + doIt=0; + } else if (traceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + /* MR23 */ printMessage(stderr,"guess done - returning to rule %s {\"%s\"} at depth %d", + state->traceCurrentRuleName, + LT(1)->getType() == eofToken ? "@" : LT(1)->getText(), + state->traceDepth); + if (state->guessing != 0) { + /* MR23 */ printMessage(stderr," (guess mode continues - an enclosing guess is still active)"); + } else { + /* MR23 */ printMessage(stderr," (guess mode ends)"); + }; + /* MR23 */ printMessage(stderr,"\n"); + }; +} + +void ANTLRParser::traceGuessFail() { + + int doIt=0; + + if (traceCurrentRuleName == NULL) return; /* MR21 */ + + if (traceOptionValue <= 0) { + doIt=0; + } else if (guessing && traceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + /* MR23 */ printMessage(stderr,"guess failed in %s\n",traceCurrentRuleName); + }; +} + +/* traceOption: + zero value turns off trace +*/ + +void ANTLRParser::tracein(const ANTLRChar * rule) { + + int doIt=0; + + traceDepth++; + traceCurrentRuleName=rule; + + if (traceOptionValue <= 0) { + doIt=0; + } else if (guessing && traceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + /* MR23 */ printMessage(stderr,"enter rule %s {\"%s\"} depth %d", + rule, + LT(1)->getType() == eofToken ? "@" : LT(1)->getText(), + traceDepth); + if (guessing) /* MR23 */ printMessage(stderr," guessing"); + /* MR23 */ printMessage(stderr,"\n"); + }; + return; +} + +void ANTLRParser::traceout(const ANTLRChar * rule) { + + int doIt=0; + + traceDepth--; + + if (traceOptionValue <= 0) { + doIt=0; + } else if (guessing && traceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + /* MR23 */ printMessage(stderr,"exit rule %s {\"%s\"} depth %d", + rule, + LT(1)->getType() == eofToken ? "@" : LT(1)->getText(), + traceDepth+1); + if (guessing) /* MR23 */ printMessage(stderr," guessing"); + /* MR23 */ printMessage(stderr,"\n"); + }; +} + +int ANTLRParser::traceOption(int delta) { + + int prevValue=traceOptionValue; + + traceOptionValue=traceOptionValue+delta; + + if (traceCurrentRuleName != NULL) { + if (prevValue <= 0 && traceOptionValue > 0) { + /* MR23 */ printMessage(stderr,"trace enabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); + }; + if (prevValue > 0 && traceOptionValue <= 0) { + /* MR23 */ printMessage(stderr,"trace disabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); + }; + }; + + return prevValue; +} + +int ANTLRParser::traceGuessOption(int delta) { + + int prevValue=traceGuessOptionValue; + + traceGuessOptionValue=traceGuessOptionValue+delta; + + if (traceCurrentRuleName != NULL) { + if (prevValue <= 0 && traceGuessOptionValue > 0) { + /* MR23 */ printMessage(stderr,"guess trace enabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); + }; + if (prevValue > 0 && traceGuessOptionValue <= 0) { + /* MR23 */ printMessage(stderr,"guess trace disabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); + }; + }; + return prevValue; +} + +// MR19 V.H. Simonis Defer Fetch feature + +void ANTLRParser::undeferFetch() +{ + +#ifdef ZZDEFER_FETCH + if (stillToFetch) { + for (int stillToFetch_x = 0; stillToFetch_x < stillToFetch; ++stillToFetch_x) { + NLA = inputTokens->getToken()->getType(); + dirty--; + lap = (lap+1)&(LLk-1); + } + stillToFetch = 0; + } +#else + return; +#endif + +} + +int ANTLRParser::isDeferFetchEnabled() +{ +#ifdef ZZDEFER_FETCH + return 1; +#else + return 0; +#endif +} + +//MR23 +int ANTLRParser::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + int iRet = printMessageV(pFile, pFormat, marker); + va_end( marker ); + return iRet; +} + +int ANTLRParser::printMessageV(FILE* pFile, const char* pFormat, va_list arglist) // MR23 +{ + return vfprintf(pFile, pFormat, arglist); +} + +// MR23 Move semantic predicate error handling from macro to virtual function +// +// Called by the zzfailed_pred + +void ANTLRParser::failedSemanticPredicate(const char* predicate) +{ + printMessage(stdout,"line %d: semantic error; failed predicate: '%s'\n", + LT(1)->getLine(), predicate); +} diff --git a/Tools/Source/TianoTools/Pccts/h/AParser.h b/Tools/Source/TianoTools/Pccts/h/AParser.h new file mode 100644 index 0000000000..fe405f4167 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/AParser.h @@ -0,0 +1,376 @@ +/* ANTLRParser.h + * + * Define the generic ANTLRParser superclass, which is subclassed to + * define an actual parser. + * + * Before entry into this file: ANTLRTokenType must be set. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef APARSER_H_GATE +#define APARSER_H_GATE + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_setjmp.h" + +PCCTS_NAMESPACE_STD + +#include ATOKEN_H +#include ATOKENBUFFER_H + +#ifdef ZZCAN_GUESS +#ifndef ZZINF_LOOK +#define ZZINF_LOOK +#endif +#endif + + +#define NLA (token_type[lap&(LLk-1)])/* --> next LA */ + +typedef unsigned char SetWordType; + +/* Define external bit set stuff (for SetWordType) */ +#define EXT_WORDSIZE (sizeof(char)*8) +#define EXT_LOGWORDSIZE 3 + + /* s y n t a c t i c p r e d i c a t e s t u f f */ + +#ifndef zzUSER_GUESS_HOOK +#define zzUSER_GUESS_HOOK(seqFrozen,zzrv) +#endif + +#ifndef zzUSER_GUESS_DONE_HOOK +#define zzUSER_GUESS_DONE_HOOK(seqFrozen) +#endif + +/* MR14 Add zzUSER_GUESS_FAIL_HOOK and related code */ + +#define zzUSER_GUESS_FAIL_HOOK_INTERNAL zzUSER_GUESS_FAIL_HOOK(SeqFrozen) +#ifndef zzUSER_GUESS_FAIL_HOOK +#define zzUSER_GUESS_FAIL_HOOK(zzGuessSeq) +#endif + + +typedef struct _zzjmp_buf { + jmp_buf state; + } zzjmp_buf; + +/* these need to be macros not member functions */ +#define zzGUESS_BLOCK ANTLRParserState zzst; int zzrv; int _marker; int zzGuessSeqFrozen; +#define zzNON_GUESS_MODE if ( !guessing ) +#define zzGUESS_FAIL guess_fail(); + +/* Note: zzGUESS_DONE does not execute longjmp() */ + +#define zzGUESS_DONE {zzrv=1; inputTokens->rewind(_marker); guess_done(&zzst);zzUSER_GUESS_DONE_HOOK(zzGuessSeqFrozen) } +#define zzGUESS saveState(&zzst); \ + guessing = 1; \ + zzGuessSeqFrozen = ++zzGuessSeq; \ + _marker = inputTokens->mark(); \ + zzrv = setjmp(guess_start.state); \ + zzUSER_GUESS_HOOK(zzGuessSeqFrozen,zzrv) \ + if ( zzrv ) zzGUESS_DONE + +#define zzTRACEdata const ANTLRChar *zzTracePrevRuleName = NULL; + +#ifndef zzTRACEIN +#define zzTRACEIN(r) zzTracePrevRuleName=traceCurrentRuleName;tracein(r); +#endif +#ifndef zzTRACEOUT +#define zzTRACEOUT(r) traceout(r);traceCurrentRuleName=zzTracePrevRuleName; +#endif + + /* a n t l r p a r s e r d e f */ + +struct ANTLRParserState { + /* class variables */ + zzjmp_buf guess_start; + int guessing; + + int inf_labase; + int inf_last; + + int dirty; + + int traceOptionValue; // MR10 + int traceGuessOptionValue; // MR10 + const ANTLRChar *traceCurrentRuleName; // MR10 + int traceDepth; // MR10 + +}; + +/* notes: + * + * multiple inheritance is a cool way to include what stuff is needed + * in this structure (like guess stuff). however, i'm not convinced that + * multiple inheritance works correctly on all platforms. not that + * much space is used--just include all possibly useful members. + * + * the class should also be a template with arguments for the lookahead + * depth and so on. that way, more than one parser can be defined (as + * each will probably have different lookahead requirements). however, + * am i sure that templates work? no, i'm not sure. + * + * no attributes are maintained and, hence, the 'asp' variable is not + * needed. $i can still be referenced, but it refers to the token + * associated with that rule element. question: where are the token's + * stored if not on the software stack? in local variables created + * and assigned to by antlr. + */ +class ANTLRParser { +protected: + /* class variables */ + static SetWordType bitmask[sizeof(SetWordType)*8]; + static char eMsgBuffer[500]; + +protected: + int LLk; // number of lookahead symbols (old LL_K) + int demand_look; + ANTLRTokenType eofToken; // when do I stop during resynch()s + int bsetsize; // size of bitsets created by ANTLR in + // units of SetWordType + + ANTLRTokenBuffer *inputTokens; //place to get input tokens + + zzjmp_buf guess_start; // where to jump back to upon failure + int guessing; // if guessing (using (...)? predicate) + + // infinite lookahead stuff + int can_use_inf_look; // set by subclass (generated by ANTLR) + int inf_lap; + int inf_labase; + int inf_last; + int *_inf_line; + + const ANTLRChar **token_tbl; // pointer to table of token type strings MR20 const + + int dirty; // used during demand lookahead + + ANTLRTokenType *token_type; // fast reference cache of token.getType() +// ANTLRLightweightToken **token; // the token with all its attributes + int lap; + int labase; +#ifdef ZZDEFER_FETCH + int stillToFetch; // MR19 V.H. Simonis +#endif + +private: + void fill_inf_look(); + +protected: + virtual void guess_fail() { // MR9 27-Sep-97 make virtual + traceGuessFail(); // MR10 + longjmp(guess_start.state, 1); } // MR9 + virtual void guess_done(ANTLRParserState *st) { // MR9 27-Sep-97 make virtual + restoreState(st); } // MR9 + virtual int guess(ANTLRParserState *); // MR9 27-Sep-97 make virtual + void look(int); + int _match(ANTLRTokenType, ANTLRChar **, ANTLRTokenType *, + _ANTLRTokenPtr *, SetWordType **); + int _setmatch(SetWordType *, ANTLRChar **, ANTLRTokenType *, + _ANTLRTokenPtr *, SetWordType **, + SetWordType * tokclassErrset /* MR23 */); + int _match_wsig(ANTLRTokenType); + int _setmatch_wsig(SetWordType *); + virtual void consume(); + virtual void resynch(SetWordType *wd,SetWordType mask); // MR21 + void prime_lookahead(); + virtual void tracein(const ANTLRChar *r); // MR10 + virtual void traceout(const ANTLRChar *r); // MR10 + static unsigned MODWORD(unsigned x) {return x & (EXT_WORDSIZE-1);} // x % EXT_WORDSIZE // MR9 + static unsigned DIVWORD(unsigned x) {return x >> EXT_LOGWORDSIZE;} // x / EXT_WORDSIZE // MR9 + int set_deg(SetWordType *); + int set_el(ANTLRTokenType, SetWordType *); + virtual void edecode(SetWordType *); // MR1 + virtual void FAIL(int k, ...); // MR1 + int traceOptionValue; // MR10 + int traceGuessOptionValue; // MR10 + const ANTLRChar *traceCurrentRuleName; // MR10 + int traceDepth; // MR10 + void traceReset(); // MR10 + virtual void traceGuessFail(); // MR10 + virtual void traceGuessDone(const ANTLRParserState *); // MR10 + int zzGuessSeq; // MR10 + +public: + ANTLRParser(ANTLRTokenBuffer *, + int k=1, + int use_inf_look=0, + int demand_look=0, + int bsetsize=1); + virtual ~ANTLRParser(); + + virtual void init(); + + ANTLRTokenType LA(int i) + { +// +// MR14 demand look will always be 0 for C++ mode +// +//// return demand_look ? token_type[(labase+(i)-1)&(LLk-1)] : +//// token_type[(lap+(i)-1)&(LLk-1)]; + +// MR19 V.H. Simonis Defer fetch feature + +#ifdef ZZDEFER_FETCH + undeferFetch(); +#endif + return token_type[(lap+(i)-1)&(LLk-1)]; + } + _ANTLRTokenPtr LT(int i); + + void setEofToken(ANTLRTokenType t) { eofToken = t; } + ANTLRTokenType getEofToken() const { return eofToken; } // MR14 + + void noGarbageCollectTokens() { inputTokens->noGarbageCollectTokens(); } + void garbageCollectTokens() { inputTokens->garbageCollectTokens(); } + + virtual void syn(_ANTLRTokenPtr tok, ANTLRChar *egroup, + SetWordType *eset, ANTLRTokenType etok, int k); + virtual void saveState(ANTLRParserState *); // MR9 27-Sep-97 make virtual + virtual void restoreState(ANTLRParserState *); // MR9 27-Sep-97 make virtual + + virtual void panic(const char *msg); // MR20 const + + static char *eMsgd(char *,int); + static char *eMsg(char *,char *); + static char *eMsg2(char *,char *,char *); + + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 + virtual int printMessageV(FILE* pFile, const char* pFormat, va_list arglist); // MR23 + + void consumeUntil(SetWordType *st); + void consumeUntilToken(int t); + + virtual int _setmatch_wdfltsig(SetWordType *tokensWanted, + ANTLRTokenType tokenTypeOfSet, + SetWordType *whatFollows); + virtual int _match_wdfltsig(ANTLRTokenType tokenWanted, + SetWordType *whatFollows); + + const ANTLRChar * parserTokenName(int tok); // MR1 + + int traceOptionValueDefault; // MR11 + int traceOption(int delta); // MR11 + int traceGuessOption(int delta); // MR11 + +// MR8 5-Aug-97 S.Bochnak@microtool.com.pl +// MR8 Move resynch static local variable +// MR8 to class instance + + int syntaxErrCount; // MR12 + ANTLRTokenStream *getLexer() const { // MR12 + return inputTokens ? inputTokens->getLexer() : 0; } // MR12 +protected: // MR8 + int resynchConsumed; // MR8 + char *zzFAILtext; // workarea required by zzFAIL // MR9 + void undeferFetch(); // MR19 V.H. Simonis + int isDeferFetchEnabled(); // MR19 V.H. Simonis + virtual void failedSemanticPredicate(const char* predicate); /* MR23 */ +}; + +#define zzmatch(_t) \ + if ( !_match((ANTLRTokenType)_t, &zzMissText, &zzMissTok, \ + (_ANTLRTokenPtr *) &zzBadTok, &zzMissSet) ) goto fail; + +#define zzmatch_wsig(_t,handler) \ + if ( !_match_wsig((ANTLRTokenType)_t) ) if ( guessing ) zzGUESS_FAIL else {_signal=MismatchedToken; goto handler;} + +#define zzsetmatch(_ts,_tokclassErrset) \ + if ( !_setmatch(_ts, &zzMissText, &zzMissTok, \ + (_ANTLRTokenPtr *) &zzBadTok, &zzMissSet, _tokclassErrset) ) goto fail; + +#define zzsetmatch_wsig(_ts, handler) \ + if ( !_setmatch_wsig(_ts) ) if ( guessing ) zzGUESS_FAIL else {_signal=MismatchedToken; goto handler;} + +/* For the dflt signal matchers, a FALSE indicates that an error occurred + * just like the other matchers, but in this case, the routine has already + * recovered--we do NOT want to consume another token. However, when + * the match was successful, we do want to consume hence _signal=0 so that + * a token is consumed by the "if (!_signal) consume(); _signal=NoSignal;" + * preamble. + */ +#define zzsetmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) \ + if ( !_setmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) ) \ + _signal = MismatchedToken; + +#define zzmatch_wdfltsig(tokenWanted, whatFollows) \ + if ( !_match_wdfltsig(tokenWanted, whatFollows) ) _signal = MismatchedToken; + + +// MR1 10-Apr-97 zzfailed_pred() macro does not backtrack in guess mode. +// MR1 Identification and correction due to J. Lilley +// +// MR23 Call virtual method to report error. +// MR23 Provide more control over failed predicate action +// without any need for user to worry about guessing internals. + +#ifndef zzfailed_pred +#define zzfailed_pred(_p,_hasuseraction,_useraction) \ + if (guessing) { \ + zzGUESS_FAIL; \ + } else { \ + zzfailed_pred_action(_p,_hasuseraction,_useraction) \ + } +#endif + +// MR23 Provide more control over failed predicate action +// without any need for user to worry about guessing internals. +// _hasuseraction == 0 => no user specified error action +// _hasuseraction == 1 => user specified error action + +#ifndef zzfailed_pred_action +#define zzfailed_pred_action(_p,_hasuseraction,_useraction) \ + if (_hasuseraction) { _useraction } else { failedSemanticPredicate(_p); } +#endif + +#define zzRULE \ + SetWordType *zzMissSet=NULL; ANTLRTokenType zzMissTok=(ANTLRTokenType)0; \ + _ANTLRTokenPtr zzBadTok=NULL; ANTLRChar *zzBadText=(ANTLRChar *)""; \ + int zzErrk=1,zzpf=0; \ + zzTRACEdata \ + ANTLRChar *zzMissText=(ANTLRChar *)""; + +#endif + + /* S t a n d a r d E x c e p t i o n S i g n a l s */ + +#define NoSignal 0 +#define MismatchedToken 1 +#define NoViableAlt 2 +#define NoSemViableAlt 3 + +/* MR7 Allow more control over signalling */ +/* by adding "Unwind" and "SetSignal" */ + +#define Unwind 4 +#define setSignal(newValue) *_retsignal=_signal=(newValue) +#define suppressSignal *_retsignal=_signal=0 +#define exportSignal *_retsignal=_signal diff --git a/Tools/Source/TianoTools/Pccts/h/ASTBase.cpp b/Tools/Source/TianoTools/Pccts/h/ASTBase.cpp new file mode 100644 index 0000000000..a94f080c86 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/ASTBase.cpp @@ -0,0 +1,256 @@ +/* Abstract syntax tree manipulation functions + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_stdarg.h" + +PCCTS_NAMESPACE_STD + +#define ANTLR_SUPPORT_CODE + +#include "ASTBase.h" + +/* ensure that tree manipulation variables are current after a rule + * reference + */ +void +ASTBase::link(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail) +{ + if ( *_sibling == NULL ) return; + if ( *_root == NULL ) *_root = *_sibling; + else if ( *_root != *_sibling ) (*_root)->_down = *_sibling; + if ( *_tail==NULL ) *_tail = *_sibling; + while ( (*_tail)->_right != NULL ) *_tail = (*_tail)->_right; +} + +/* add a child node to the current sibling list */ +void +ASTBase::subchild(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail) +{ + if ( *_tail != NULL ) (*_tail)->_right = this; + else { + *_sibling = this; + if ( *_root != NULL ) (*_root)->_down = *_sibling; + } + *_tail = this; + if ( *_root == NULL ) *_root = *_sibling; +} + +/* make a new AST node. Make the newly-created + * node the root for the current sibling list. If a root node already + * exists, make the newly-created node the root of the current root. + */ +void +ASTBase::subroot(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail) +{ + if ( *_root != NULL ) + if ( (*_root)->_down == *_sibling ) *_sibling = *_tail = *_root; + *_root = this; + (*_root)->_down = *_sibling; +} + +/* Apply preorder_action(), etc.. to root then each sibling */ +// +// 7-Apr-97 133MR1 +// Fix suggested by Ron House (house@helios.usq.edu.au) +// +void +ASTBase::preorder(void* pData /*= NULL*/ /* MR23 */) +{ + ASTBase *tree = this; + + while ( tree!= NULL ) + { + if ( tree->_down != NULL ) { + tree->preorder_before_action(pData); // MR1 + }; + tree->preorder_action(pData); + if ( tree->_down!=NULL ) + { + tree->_down->preorder(pData); + tree->preorder_after_action(pData); // MR1 + } + tree = tree->_right; + } +} + +/* free all AST nodes in tree; apply func to each before freeing */ +void +ASTBase::destroy() +{ + ASTBase* tree = this; + while (tree) { + if (tree->_down) tree->_down->destroy(); + + ASTBase* cur = tree; + tree = tree->_right; + delete cur; + } +} + +/* build a tree (root child1 child2 ... NULL) + * If root is NULL, simply make the children siblings and return ptr + * to 1st sibling (child1). If root is not single node, return NULL. + * + * Siblings that are actually siblins lists themselves are handled + * correctly. For example #( NULL, #( NULL, A, B, C), D) results + * in the tree ( NULL A B C D ). + * + * Requires at least two parameters with the last one being NULL. If + * both are NULL, return NULL. + */ +ASTBase * +ASTBase::tmake(ASTBase *root, ...) +{ + va_list ap; + register ASTBase *child, *sibling=NULL, *tail=NULL /*MR23*/, *w; + + va_start(ap, root); + + if ( root != NULL ) + if ( root->_down != NULL ) { + root->reportOverwriteOfDownPointer(); /* MR21 Report problem which almost always an error */ + return NULL; + } + child = va_arg(ap, ASTBase *); + while ( child != NULL ) + { + for (w=child; w->_right!=NULL; w=w->_right) {;} /* find end of child */ + if ( sibling == NULL ) {sibling = child; tail = w;} + else {tail->_right = child; tail = w;} + child = va_arg(ap, ASTBase *); + } + if ( root==NULL ) root = sibling; + else root->_down = sibling; + va_end(ap); + return root; +} + +#ifndef PCCTS_NOT_USING_SOR + +/* tree duplicate */ +// forgot to check for NULL this (TJP July 23,1995) +ASTBase * +ASTBase::dup() +{ + ASTBase *u, *t=this; + + if ( t == NULL ) return NULL; +/* + u = new ASTBase; + *u = *t; +*/ + u = (ASTBase *)this->shallowCopy(); + if ( t->_right!=NULL ) u->_right = t->_right->dup(); + else u->_right = NULL; + if ( t->_down!=NULL ) u->_down = t->_down->dup(); + else u->_down = NULL; + return u; +} +#endif + +// +// 7-Apr-97 133MR1 +// Fix suggested by Asgeir Olafsson (olafsson@cstar.ac.com) +// +/* tree duplicate */ + +#ifndef PCCTS_NOT_USING_SOR + +ASTBase * +ASTDoublyLinkedBase::dup() +{ + ASTDoublyLinkedBase *u, *t=this; + + if ( t == NULL ) return NULL; + u = (ASTDoublyLinkedBase *)this->shallowCopy(); + u->_up = NULL; /* set by calling invocation */ + u->_left = NULL; + if (t->_right!=NULL) { // MR1 + u->_right=t->_right->dup(); // MR1 + ((ASTDoublyLinkedBase *)u->_right)->_left = u; // MR1 + } else { // MR1 + u->_right = NULL; // MR1 + }; // MR1 + if (t->_down!=NULL) { // MR1 + u->_down = t->_down->dup(); // MR1 + ((ASTDoublyLinkedBase *)u->_down)->_up = u; // MR1 + } else { // MR1 + u->_down = NULL; // MR1 + }; // MR1 + return u; +} + +#endif + +/* + * Set the 'up', and 'left' pointers of all nodes in 't'. + * Initial call is double_link(your_tree, NULL, NULL). + */ +void +ASTDoublyLinkedBase::double_link(ASTBase *left, ASTBase *up) +{ + ASTDoublyLinkedBase *t = this; + + t->_left = (ASTDoublyLinkedBase *) left; + t->_up = (ASTDoublyLinkedBase *) up; + if (t->_down != NULL) + ((ASTDoublyLinkedBase *)t->_down)->double_link(NULL, t); + if (t->_right != NULL) + ((ASTDoublyLinkedBase *)t->_right)->double_link(t, up); +} + +// MR21 ASTBase::reportOverwriteOfDownPointer + +void ASTBase::reportOverwriteOfDownPointer() +{ + panic("Attempt to overwrite down pointer in ASTBase::tmake"); +} + +// MR21 ASTBase::panic + +void ASTBase::panic(const char *msg) +{ + /* MR23 */ printMessage(stderr,"ASTBase panic: %s\n", msg); + exit(PCCTS_EXIT_FAILURE); +} + +#ifdef PCCTS_NOT_USING_SOR +//MR23 +int ASTBase::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + int iRet = vfprintf(pFile, pFormat, marker); + va_end( marker ); + return iRet; +} +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/ASTBase.h b/Tools/Source/TianoTools/Pccts/h/ASTBase.h new file mode 100644 index 0000000000..912f4b8482 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/ASTBase.h @@ -0,0 +1,122 @@ +/* Abstract syntax tree + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ASTBase_H +#define ASTBase_H + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_stdlib.h" + +PCCTS_NAMESPACE_STD + +#ifndef PCCTS_NOT_USING_SOR +#include "PCCTSAST.h" +#endif + +/* + * Notes: + * + * To specify a copy constructor, subclass one of these classes and + * give the copy constructor. To use dup(), you must define shallowCopy(). + * shallowCopy() can use either a copy constructor or just copy the node + * itself. + */ + +#ifdef PCCTS_NOT_USING_SOR +class DllExportPCCTS ASTBase { +#else +class DllExportPCCTS ASTBase : public PCCTS_AST { +#endif + +protected: + ASTBase *_right, *_down; + +public: + +#ifdef PCCTS_NOT_USING_SOR + ASTBase *right() { return _right; } + ASTBase *down() { return _down; } + void setRight(ASTBase *t) { _right = (ASTBase *)t; } + void setDown(ASTBase *t) { _down = (ASTBase *)t; } +#else + PCCTS_AST *right() { return _right; } // define the SORCERER interface + PCCTS_AST *down() { return _down; } + void setRight(PCCTS_AST *t) { _right = (ASTBase *)t; } + void setDown(PCCTS_AST *t) { _down = (ASTBase *)t; } +#endif + ASTBase() { _right = _down = NULL; } + virtual ~ASTBase() { ; } +#ifndef PCCTS_NOT_USING_SOR + virtual ASTBase *dup(); +#endif + void destroy(); + void preorder(void* pData = NULL /* MR23 */); + static ASTBase *tmake(ASTBase *, ...); + static void link(ASTBase **, ASTBase **, ASTBase **); + void subchild(ASTBase **, ASTBase **, ASTBase **); + void subroot(ASTBase **, ASTBase **, ASTBase **); + virtual void preorder_action(void* /*pData*/ = NULL /* MR23 */) { ; } + virtual void preorder_before_action(void* /*pData*/ = NULL /* MR23 */) { /* MR23 */ printMessage(stdout, " ("); } + virtual void preorder_after_action(void* /*pData*/ = NULL /* MR23 */) { /* MR23 */ printMessage(stdout, " )"); } + virtual void panic(const char *msg); /* MR21 */ + virtual void reportOverwriteOfDownPointer(); /* MR21 */ +#ifdef PCCTS_NOT_USING_SOR + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 +#endif +}; + +class DllExportPCCTS ASTDoublyLinkedBase : public ASTBase { +protected: + ASTDoublyLinkedBase *_left, *_up; + +public: + void double_link(ASTBase *left, ASTBase *up); + +#ifndef PCCTS_NOT_USING_SOR + virtual ASTBase *dup(); +#endif + +#ifdef PCCTS_NOT_USING_SOR + ASTBase *left() { return _left; } + ASTBase *up() { return _up; } + void setLeft(ASTBase *t) { _left = (ASTDoublyLinkedBase *)t; } // MR6 + void setUp(ASTBase *t) { _up = (ASTDoublyLinkedBase *)t; } // MR6 +#else + PCCTS_AST *left() { return _left; } + PCCTS_AST *up() { return _up; } + void setLeft(PCCTS_AST *t) { _left = (ASTDoublyLinkedBase *)t; } // MR6 + void setUp(PCCTS_AST *t) { _up = (ASTDoublyLinkedBase *)t; } // MR6 +#endif + +}; + +class AST; // announce that this class will be coming along shortly +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/ATokPtr.h b/Tools/Source/TianoTools/Pccts/h/ATokPtr.h new file mode 100644 index 0000000000..75b4c86cbf --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/ATokPtr.h @@ -0,0 +1,88 @@ +/* ATokPtr.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Written by Russell Quong June 30, 1995 + * Adapted by Terence Parr to ANTLR stuff + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ATokPtr_h +#define ATokPtr_h + +#include "pcctscfg.h" + +#include "pccts_stdio.h" + +PCCTS_NAMESPACE_STD + +// pointer to a reference counted object +// robust in that an unused ANTLRTokenPtr can point to NULL. + +class ANTLRAbstractToken; + +class DllExportPCCTS ANTLRTokenPtr { +public: + ANTLRTokenPtr(ANTLRAbstractToken *addr=NULL){ptr_ = addr; ref();} + ANTLRTokenPtr(const ANTLRTokenPtr &lhs) {ptr_ = lhs.ptr_; lhs.ref();} + ~ANTLRTokenPtr(); + + // use ANTLRTokenPtr as a pointer to ANTLRToken +// +// 8-Apr-97 MR1 Make operator -> a const member function +// as well as some other member functions +// + ANTLRAbstractToken *operator-> () const { return ptr_; } // MR1 +// +// 7-Apr-97 133MR1 +// Fix suggested by Andreas Magnusson +// (Andreas.Magnusson@mailbox.swipnet.se) + void operator = (const ANTLRTokenPtr & lhs); // MR1 + void operator = (ANTLRAbstractToken *addr); + int operator != (const ANTLRTokenPtr &q) const // MR1 // MR11 unsigned -> int + { return this->ptr_ != q.ptr_; } + int operator == (const ANTLRTokenPtr &q) const // MR1 // MR11 unsigned -> int + { return this->ptr_ == q.ptr_; } + int operator == (const ANTLRAbstractToken *addr) const // MR11 + { return this->ptr_ == addr; } + int operator != (const ANTLRAbstractToken *addr) const // MR11 + { return this->ptr_ != addr; } + + void ref() const; + void deref(); + +protected: + ANTLRAbstractToken *ptr_; +}; + +//typedef ANTLRTokenPtr _ANTLRTokenPtr; + +/* + * Since you cannot redefine operator->() to return one of the user's + * token object types, we must down cast. This is a drag. Here's + * a macro that helps. template: "mytoken(a-smart-ptr)->myfield". + */ +#define mytoken(tk) ((ANTLRToken *)(tk.operator->())) + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/ATokPtrImpl.h b/Tools/Source/TianoTools/Pccts/h/ATokPtrImpl.h new file mode 100644 index 0000000000..9c07cf52a9 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/ATokPtrImpl.h @@ -0,0 +1,88 @@ +/* + * ATokPtrImpl.h (formerly ATokPtr.cpp) + * + * This is #included in ATokBuffer.cpp for historical reasons. + * It has been renamed because of problems with the .cpp extension + * when used with IDE. + * + * + * ANTLRToken MUST be defined before entry to this file. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Written by Russell Quong June 30, 1995 + * Adapted by Terence Parr to ANTLR stuff + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +PCCTS_NAMESPACE_STD + +#include "ATokPtr.h" + +void ANTLRTokenPtr::ref() const +{ + if (ptr_ != NULL) { + ptr_->ref(); + } +} + +void ANTLRTokenPtr::deref() +{ + if (ptr_ != NULL) + { + ptr_->deref(); + if ( ptr_->nref()==0 ) + { + delete ptr_; + ptr_ = NULL; + } + } +} + +ANTLRTokenPtr::~ANTLRTokenPtr() +{ + deref(); +} + +// +// 8-Apr-97 MR1 Make operator -> a const member function +// as weall as some other member functions +// +void ANTLRTokenPtr::operator = (const ANTLRTokenPtr & lhs) // MR1 +{ + lhs.ref(); // protect against "xp = xp"; ie same underlying object + deref(); + ptr_ = lhs.ptr_; +} + +void ANTLRTokenPtr::operator = (ANTLRAbstractToken *addr) +{ + if (addr != NULL) { + addr->ref(); + } + deref(); + ptr_ = addr; +} diff --git a/Tools/Source/TianoTools/Pccts/h/AToken.h b/Tools/Source/TianoTools/Pccts/h/AToken.h new file mode 100644 index 0000000000..6167c21ef5 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/AToken.h @@ -0,0 +1,325 @@ +/* ANTLRToken.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ATOKEN_H_GATE +#define ATOKEN_H_GATE + +#include "pcctscfg.h" + +#include "pccts_string.h" +#include "pccts_stdio.h" +#include "pccts_stdlib.h" +#include "pccts_stdarg.h" // MR23 + +PCCTS_NAMESPACE_STD + +// MR9 RJV (JVincent@novell.com) Not needed for variable length strings + +//// MR9 #ifndef ANTLRCommonTokenTEXTSIZE +//// MR9 #define ANTLRCommonTokenTEXTSIZE 100 +//// MR9 #endif + + +/* must define what a char looks like; can make this a class too */ +typedef char ANTLRChar; + +/* D E F I N E S M A R T P O I N T E R S */ + +//#include ATOKPTR_H not tested yet, leave out +class ANTLRAbstractToken; +typedef ANTLRAbstractToken *_ANTLRTokenPtr; + +class ANTLRAbstractToken { +public: + virtual ~ANTLRAbstractToken() {;} + virtual ANTLRTokenType getType() const = 0; + virtual void setType(ANTLRTokenType t) = 0; + virtual int getLine() const = 0; + virtual void setLine(int line) = 0; + virtual ANTLRChar *getText() const = 0; + virtual void setText(const ANTLRChar *) = 0; + + /* This function will disappear when I can use templates */ + virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt, + ANTLRChar *text, + int line) = 0; + + /* define to satisfy ANTLRTokenBuffer's need to determine whether or + not a token object can be destroyed. If nref()==0, no one has + a reference, and the object may be destroyed. This function defaults + to 1, hence, if you use deleteTokens() message with a token object + not derived from ANTLRCommonRefCountToken, the parser will compile + but will not delete objects after they leave the token buffer. + */ + + virtual unsigned nref() const { return 1; } // MR11 + virtual void ref() {;} + virtual void deref() {;} + + virtual void panic(const char *msg) // MR20 const + { + /* MR23 */ printMessage(stderr, "ANTLRAbstractToken panic: %s\n", msg); + exit(PCCTS_EXIT_FAILURE); + } + + virtual int printMessage(FILE* pFile, const char* pFormat, ...) // MR23 + { + va_list marker; + va_start( marker, pFormat ); + int iRet = vfprintf(pFile, pFormat, marker); + va_end( marker ); + return iRet; + } +}; + +/* This class should be subclassed. It cannot store token type or text */ + +class ANTLRRefCountToken : public ANTLRAbstractToken { +public: +#ifdef DBG_REFCOUNTTOKEN + static int ctor; + static int dtor; +#endif +protected: + unsigned refcnt_; +#ifdef DBG_REFCOUNTTOKEN + char object[200]; +#endif + +public: + + // MR23 - No matter what you do, you're hammered. + // Don't give names to formals something breaks. + // Give names to formals and don't use them it breaks. + +#ifndef DBG_REFCOUNTTOKEN + ANTLRRefCountToken(ANTLRTokenType /* t MR23 */, const ANTLRChar * /* s MR23 */) +#else + ANTLRRefCountToken(ANTLRTokenType t, const ANTLRChar * s) +#endif + +#ifndef DBG_REFCOUNTTOKEN + { + refcnt_ = 0; + } +#else + { + ctor++; + refcnt_ = 0; + if ( t==1 ) sprintf(object,"tok_EOF"); + else sprintf(object,"tok_%s",s); + /* MR23 */ printMessage(stderr, "ctor %s #%d\n",object,ctor); + } +#endif + ANTLRRefCountToken() +#ifndef DBG_REFCOUNTTOKEN + { refcnt_ = 0; } +#else + { + ctor++; + refcnt_ = 0; + sprintf(object,"tok_blank"); + /* MR23 */ printMessage(stderr, "ctor %s #%d\n",object,ctor); + } + virtual ~ANTLRRefCountToken() + { + dtor++; + if ( dtor>ctor ) /* MR23 */ printMessage(stderr, "WARNING: dtor>ctor\n"); + /* MR23 */ printMessage(stderr, "dtor %s #%d\n", object, dtor); + object[0]='\0'; + } +#endif + + // reference counting stuff needed by ANTLRTokenPtr. + // User should not access these; for C++ language reasons, we had + // to make these public. Yuck. + + void ref() { refcnt_++; } + void deref() { refcnt_--; } + unsigned nref() const { return refcnt_; } // MR11 + + virtual ANTLRAbstractToken *makeToken(ANTLRTokenType /*tt MR23*/, + ANTLRChar * /*txt MR23*/, + int /*line MR23*/) + { + panic("call to ANTLRRefCountToken::makeToken()\n"); + return NULL; + } +}; + +class ANTLRCommonNoRefCountToken : public ANTLRAbstractToken { +protected: + ANTLRTokenType _type; + int _line; + ANTLRChar *_text; // MR9 RJV + +public: + ANTLRCommonNoRefCountToken(ANTLRTokenType t, const ANTLRChar *s) + { setType(t); _line = 0; _text = NULL; setText(s); } + ANTLRCommonNoRefCountToken() + { setType((ANTLRTokenType)0); _line = 0; _text = NULL; setText(""); } + + ~ANTLRCommonNoRefCountToken() { if (_text) delete [] _text; } // MR9 RJV: Added Destructor to remove string + + ANTLRTokenType getType() const { return _type; } + void setType(ANTLRTokenType t) { _type = t; } + virtual int getLine() const { return _line; } + void setLine(int line) { _line = line; } + ANTLRChar *getText() const { return _text; } + int getLength() const { return strlen(getText()); } // MR11 + +// MR9 RJV: Added code for variable length strings to setText() + + void setText(const ANTLRChar *s) + { if (s != _text) { + if (_text) delete [] _text; + if (s != NULL) { + _text = new ANTLRChar[strlen(s)+1]; + if (_text == NULL) panic("ANTLRCommonNoRefCountToken::setText new failed"); + strcpy(_text,s); + } else { + _text = new ANTLRChar[1]; + if (_text == NULL) panic("ANTLRCommonNoRefCountToken::setText new failed"); + strcpy(_text,""); + }; + }; + } + + virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt, + ANTLRChar *txt, + int line) + { + ANTLRAbstractToken *t = new ANTLRCommonNoRefCountToken; + t->setType(tt); t->setText(txt); t->setLine(line); + return t; + } + +// MR9 THM Copy constructor required when heap allocated string is used with copy semantics + + ANTLRCommonNoRefCountToken (const ANTLRCommonNoRefCountToken& from) : + ANTLRAbstractToken(from) { + setType(from._type); + setLine(from._line); + _text=NULL; + setText(from._text); + }; + +// MR9 THM operator =() required when heap allocated string is used with copy semantics + + virtual ANTLRCommonNoRefCountToken& operator =(const ANTLRCommonNoRefCountToken& rhs) { + +////// MR15 WatCom can't hack use of operator =() +////// Use this: *( (ANTRLAbstractToken *) this)=rhs; + + *( (ANTLRAbstractToken *) this ) = rhs; + + setType(rhs._type); + setLine(rhs._line); + setText(rhs._text); + return *this; + }; +}; + +class ANTLRCommonToken : public ANTLRRefCountToken { +protected: + ANTLRTokenType _type; + int _line; + ANTLRChar *_text; // MR9 RJV:Added + +public: + ANTLRCommonToken(ANTLRTokenType t, const ANTLRChar *s) : ANTLRRefCountToken(t,s) + { setType(t); _line = 0; _text = NULL; setText(s); } // MR9 + ANTLRCommonToken() + { setType((ANTLRTokenType)0); _line = 0; _text = NULL; setText(""); } // MR9 + + virtual ~ANTLRCommonToken() { if (_text) delete [] _text; } // MR9 RJV: Added Destructor to remove string + + ANTLRTokenType getType() const { return _type; } + void setType(ANTLRTokenType t) { _type = t; } + virtual int getLine() const { return _line; } + void setLine(int line) { _line = line; } + ANTLRChar *getText() const { return _text; } + int getLength() const { return strlen(getText()); } // MR11 + +// MR9 RJV: Added code for variable length strings to setText() + + void setText(const ANTLRChar *s) + { if (s != _text) { + if (_text) delete [] _text; + if (s != NULL) { + _text = new ANTLRChar[strlen(s)+1]; + if (_text == NULL) panic("ANTLRCommonToken::setText new failed"); + strcpy(_text,s); + } else { + _text = new ANTLRChar[1]; + if (_text == NULL) panic("ANTLRCommonToken::setText new failed"); + strcpy(_text,""); + }; + }; + } + + virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt, + ANTLRChar *txt, + int line) + { + ANTLRAbstractToken *t = new ANTLRCommonToken(tt,txt); + t->setLine(line); + return t; + } + +// MR9 THM Copy constructor required when heap allocated string is used with copy semantics + + ANTLRCommonToken (const ANTLRCommonToken& from) : + ANTLRRefCountToken(from) { + setType(from._type); + setLine(from._line); + _text=NULL; + setText(from._text); + }; + +// MR9 THM operator =() required when heap allocated string is used with copy semantics + + virtual ANTLRCommonToken& operator =(const ANTLRCommonToken& rhs) { + +////// MR15 WatCom can't hack use of operator =() +////// Use this instead: *( (ANTRLRRefCountToken *) this)=rhs; + + *( (ANTLRRefCountToken *) this) = rhs; + + setType(rhs._type); + setLine(rhs._line); + setText(rhs._text); + return *this; + }; +}; + +// used for backward compatibility +typedef ANTLRCommonToken ANTLRCommonBacktrackingToken; + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/ATokenBuffer.cpp b/Tools/Source/TianoTools/Pccts/h/ATokenBuffer.cpp new file mode 100644 index 0000000000..9a2f2fc88b --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/ATokenBuffer.cpp @@ -0,0 +1,374 @@ +/* ANTLRTokenBuffer.cpp + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +typedef int ANTLRTokenType; // fool AToken.h into compiling + +class ANTLRParser; /* MR1 */ + +#define ANTLR_SUPPORT_CODE + +#include "pcctscfg.h" + +#include ATOKENBUFFER_H +#include APARSER_H // MR23 + +typedef ANTLRAbstractToken *_ANTLRTokenPtr; + +#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW) +static unsigned char test[1000]; +#endif + +#ifdef DBG_REFCOUNTTOKEN +int ANTLRRefCountToken::ctor = 0; /* MR23 */ +int ANTLRRefCountToken::dtor = 0; /* MR23 */ +#endif + +ANTLRTokenBuffer:: +ANTLRTokenBuffer(ANTLRTokenStream *_input, int _k, int _chunk_size_formal) /* MR14 */ +{ + this->input = _input; + this->k = _k; + buffer_size = chunk_size = _chunk_size_formal; + buffer = (_ANTLRTokenPtr *) + calloc(chunk_size+1,sizeof(_ANTLRTokenPtr )); + if ( buffer == NULL ) { + panic("cannot alloc token buffer"); + } + buffer++; // leave the first elem empty so tp-1 is valid ptr + + tp = &buffer[0]; + last = tp-1; + next = &buffer[0]; + num_markers = 0; + end_of_buffer = &buffer[buffer_size-1]; + threshold = &buffer[(int)(buffer_size/2)]; // MR23 - Used to be 1.0/2.0 ! + _deleteTokens = 1; // assume we delete tokens + parser=NULL; // MR5 - uninitialized reference +} + +static void f() {;} +ANTLRTokenBuffer:: +~ANTLRTokenBuffer() +{ + f(); + // Delete all remaining tokens (from 0..last inclusive) + if ( _deleteTokens ) + { + _ANTLRTokenPtr *z; + for (z=buffer; z<=last; z++) + { + (*z)->deref(); +// z->deref(); +#ifdef DBG_REFCOUNTTOKEN + /* MR23 */ printMessage(stderr, "##########dtor: deleting token '%s' (ref %d)\n", + ((ANTLRCommonToken *)*z)->getText(), (*z)->nref()); +#endif + if ( (*z)->nref()==0 ) + { + delete (*z); + } + } + } + + if ( buffer!=NULL ) free((char *)(buffer-1)); +} + +#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW) +#include "pccts_stdio.h" +PCCTS_NAMESPACE_STD +#endif + +_ANTLRTokenPtr ANTLRTokenBuffer:: +getToken() +{ + if ( tp <= last ) // is there any buffered lookahead still to be read? + { + return *tp++; // read buffered lookahead + } + // out of buffered lookahead, get some more "real" + // input from getANTLRToken() + if ( num_markers==0 ) + { + if( next > threshold ) + { +#ifdef DBG_TBUF +/* MR23 */ printMessage(stderr,"getToken: next > threshold (high water is %d)\n", threshold-buffer); +#endif + makeRoom(); + } + } + else { + if ( next > end_of_buffer ) + { +#ifdef DBG_TBUF +/* MR23 */ printMessage(stderr,"getToken: next > end_of_buffer (size is %d)\n", buffer_size); +#endif + extendBuffer(); + } + } + *next = getANTLRToken(); + (*next)->ref(); // say we have a copy of this pointer in buffer + last = next; + next++; + tp = last; + return *tp++; +} + +void ANTLRTokenBuffer:: +rewind(int pos) +{ +#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW) + /* MR23 */ printMessage(stderr, "rewind(%d)[nm=%d,from=%d,%d.n=%d]\n", pos, num_markers, tp-buffer,pos,test[pos]); + test[pos]--; +#endif + tp = &buffer[pos]; + num_markers--; +} + +/* + * This function is used to specify that the token pointers read + * by the ANTLRTokenBuffer should be buffered up (to be reused later). + */ +int ANTLRTokenBuffer:: +mark() +{ +#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW) + test[tp-buffer]++; + /* MR23 */ printMessage(stderr,"mark(%d)[nm=%d,%d.n=%d]\n",tp-buffer,num_markers+1,tp-buffer,test[tp-buffer]); +#endif + num_markers++; + return tp - buffer; +} + +/* + * returns the token pointer n positions ahead. + * This implies that bufferedToken(1) gets the NEXT symbol of lookahead. + * This is used in conjunction with the ANTLRParser lookahead buffer. + * + * No markers are set or anything. A bunch of input is buffered--that's all. + * The tp pointer is left alone as the lookahead has not been advanced + * with getToken(). The next call to getToken() will find a token + * in the buffer and won't have to call getANTLRToken(). + * + * If this is called before a consume() is done, how_many_more_i_need is + * set to 'n'. + */ +_ANTLRTokenPtr ANTLRTokenBuffer:: +bufferedToken(int n) +{ +// int how_many_more_i_need = (last-tp < 0) ? n : n-(last-tp)-1; + int how_many_more_i_need = (tp > last) ? n : n-(last-tp)-1; + // Make sure that at least n tokens are available in the buffer +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, "bufferedToken(%d)\n", n); +#endif + for (int i=1; i<=how_many_more_i_need; i++) + { + if ( next > end_of_buffer ) // buffer overflow? + { + extendBuffer(); + } + *next = getANTLRToken(); + (*next)->ref(); // say we have a copy of this pointer in buffer + last = next; + next++; + } + return tp[n - 1]; +} + +/* If no markers are set, the none of the input needs to be saved (except + * for the lookahead Token pointers). We save only k-1 token pointers as + * we are guaranteed to do a getANTLRToken() right after this because otherwise + * we wouldn't have needed to extend the buffer. + * + * If there are markers in the buffer, we need to save things and so + * extendBuffer() is called. + */ +void ANTLRTokenBuffer:: +makeRoom() +{ +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, "in makeRoom.................\n"); + /* MR23 */ printMessage(stderr, "num_markers==%d\n", num_markers); +#endif +/* + if ( num_markers == 0 ) + { +*/ +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, "moving lookahead and resetting next\n"); + + _ANTLRTokenPtr *r; + /* MR23 */ printMessage(stderr, "tbuf = ["); + for (r=buffer; r<=last; r++) + { + if ( *r==NULL ) /* MR23 */ printMessage(stderr, " xxx"); + else /* MR23 */ printMessage(stderr, " '%s'", ((ANTLRCommonToken *)*r)->getText()); + } + /* MR23 */ printMessage(stderr, " ]\n"); + + /* MR23 */ printMessage(stderr, + "before: tp=%d, last=%d, next=%d, threshold=%d\n",tp-buffer,last-buffer,next-buffer,threshold-buffer); +#endif + + // Delete all tokens from 0..last-(k-1) inclusive + if ( _deleteTokens ) + { + _ANTLRTokenPtr *z; + for (z=buffer; z<=last-(k-1); z++) + { + (*z)->deref(); +// z->deref(); +#ifdef DBG_REFCOUNTTOKEN + /* MR23 */ printMessage(stderr, "##########makeRoom: deleting token '%s' (ref %d)\n", + ((ANTLRCommonToken *)*z)->getText(), (*z)->nref()); +#endif + if ( (*z)->nref()==0 ) + { + delete (*z); + } + } + } + + // reset the buffer to initial conditions, but move k-1 symbols + // to the beginning of buffer and put new input symbol at k + _ANTLRTokenPtr *p = buffer, *q = last-(k-1)+1; +// ANTLRAbstractToken **p = buffer, **q = end_of_buffer-(k-1)+1; +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, "lookahead buffer = ["); +#endif + for (int i=1; i<=(k-1); i++) + { + *p++ = *q++; +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, + " '%s'", ((ANTLRCommonToken *)buffer[i-1])->getText()); +#endif + } +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, " ]\n"); +#endif + next = &buffer[k-1]; + tp = &buffer[k-1]; // tp points to what will be filled in next + last = tp-1; +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, + "after: tp=%d, last=%d, next=%d\n", + tp-buffer, last-buffer, next-buffer); +#endif +/* + } + else { + extendBuffer(); + } +*/ +} + +/* This function extends 'buffer' by chunk_size and returns with all + * pointers at the same relative positions in the buffer (the buffer base + * address could have changed in realloc()) except that 'next' comes + * back set to where the next token should be stored. All other pointers + * are untouched. + */ +void +ANTLRTokenBuffer:: +extendBuffer() +{ + int save_last = last-buffer, save_tp = tp-buffer, save_next = next-buffer; +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, "extending physical buffer\n"); +#endif + buffer_size += chunk_size; + buffer = (_ANTLRTokenPtr *) + realloc((char *)(buffer-1), + (buffer_size+1)*sizeof(_ANTLRTokenPtr )); + if ( buffer == NULL ) { + panic("cannot alloc token buffer"); + } + buffer++; // leave the first elem empty so tp-1 is valid ptr + + tp = buffer + save_tp; // put the pointers back to same relative position + last = buffer + save_last; + next = buffer + save_next; + end_of_buffer = &buffer[buffer_size-1]; + threshold = &buffer[(int)(buffer_size*(1.0/2.0))]; + +/* + // zero out new token ptrs so we'll know if something to delete in buffer + ANTLRAbstractToken **p = end_of_buffer-chunk_size+1; + for (; p<=end_of_buffer; p++) *p = NULL; +*/ +} + +ANTLRParser * ANTLRTokenBuffer:: // MR1 +setParser(ANTLRParser *p) { // MR1 + ANTLRParser *old=parser; // MR1 + parser=p; // MR1 + input->setParser(p); // MR1 + return old; // MR1 +} // MR1 + // MR1 +ANTLRParser * ANTLRTokenBuffer:: // MR1 +getParser() { // MR1 + return parser; // MR1 +} // MR1 + +void ANTLRTokenBuffer::panic(const char *msg) // MR23 +{ + if (parser) //MR23 + parser->panic(msg); //MR23 + else //MR23 + exit(PCCTS_EXIT_FAILURE); +} + +//MR23 +int ANTLRTokenBuffer::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + + int iRet = 0; + if (parser) + parser->printMessageV(pFile, pFormat, marker); + else + iRet = vfprintf(pFile, pFormat, marker); + + va_end( marker ); + return iRet; +} + +/* to avoid having to link in another file just for the smart token ptr + * stuff, we include it here. Ugh. + * + * MR23 This causes nothing but problems for IDEs. + * Change from .cpp to .h + * + */ + +#include ATOKPTR_IMPL_H diff --git a/Tools/Source/TianoTools/Pccts/h/ATokenBuffer.h b/Tools/Source/TianoTools/Pccts/h/ATokenBuffer.h new file mode 100644 index 0000000000..1c008fd59e --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/ATokenBuffer.h @@ -0,0 +1,109 @@ +/* ANTLRTokenBuffer.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ATOKENBUFFER_H_GATE +#define ATOKENBUFFER_H_GATE + +#include "pcctscfg.h" + +#include "pccts_stdlib.h" + +PCCTS_NAMESPACE_STD + +#include ATOKEN_H +#include ATOKENSTREAM_H + +/* + * The parser is "attached" to an ANTLRTokenBuffer via interface + * functions: getToken() and bufferedToken(). The object that actually + * consumes characters and constructs tokens is connected to the + * ANTLRTokenBuffer via interface function ANTLRTokenStream::getToken(); + * where ANTLRTokenStream is really just a behavior (class with no data). + * C++ does not have this abstraction and hence we simply have come up + * with a fancy name for "void *". See the note in ANTLRTokenStream.h on + * the "behavior" of ANTLRTokenStream. + */ + +class ANTLRParser; // MR1 + +class DllExportPCCTS ANTLRTokenBuffer { +protected: + ANTLRTokenStream *input; // where do I get tokens + int buffer_size; + int chunk_size; + int num_markers; + int k; // Need at least this many tokens in buffer + _ANTLRTokenPtr *buffer; // buffer used for arbitrary lookahead + _ANTLRTokenPtr *tp; // pts into buffer; current token ptr + _ANTLRTokenPtr *last; // pts to last valid token in buffer + _ANTLRTokenPtr *next; // place to put token from getANTLRToken() + _ANTLRTokenPtr *end_of_buffer; + /* when you try to write a token past this and there are no markers + set, then move k-1 tokens back to the beginning of the buffer. + We want to stay away from the end of the buffer because we have + to extend it if a marker is set and we reach the end (we cannot + move tokens to the beginning of the buffer in this case). + */ + _ANTLRTokenPtr *threshold; + unsigned char _deleteTokens; + + // This function is filled in by the subclass; it initiates fetch of input + virtual _ANTLRTokenPtr getANTLRToken() { return input->getToken(); } + void makeRoom(); + void extendBuffer(); + +public: + ANTLRTokenBuffer(ANTLRTokenStream *in, int k=1, int chksz=50); + virtual ~ANTLRTokenBuffer(); + virtual _ANTLRTokenPtr getToken(); + virtual void rewind(int pos); + virtual int mark(); + virtual _ANTLRTokenPtr bufferedToken(int i); + + void noGarbageCollectTokens() { _deleteTokens=0; } + void garbageCollectTokens() { _deleteTokens=1; } + + virtual int bufferSize() { return buffer_size; } + virtual int minTokens() { return k; } + virtual void setMinTokens(int k_new) { k = k_new; } + + virtual void panic(const char *msg); /* MR20 const */ + + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 + +protected: // MR1 + ANTLRParser *parser; // MR1 +public: // MR1 + ANTLRParser *setParser(ANTLRParser *p); // MR1 + ANTLRParser *getParser(); // MR1 + ANTLRTokenStream *getLexer() const { // MR12 + return input;} // MR12 +}; + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/ATokenStream.h b/Tools/Source/TianoTools/Pccts/h/ATokenStream.h new file mode 100644 index 0000000000..3dfea6ebff --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/ATokenStream.h @@ -0,0 +1,51 @@ +/* ANTLRTokenStream.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ATOKENSTREAM_H_GATE +#define ATOKENSTREAM_H_GATE + +#include "pcctscfg.h" + +/* This is really a behavior or protocol; it merely indicates the behavior + * required of the input and output of an ANTLRTokenBuffer. You could + * subclass it, but you can also just pass any old pointer to ANTLRTokenBuffer + * with a type cast (in which case, your getANTLRToken() would have to + * explicitly cast the input pointer to your REAL type (typically your lexer)). + */ + +class ANTLRParser; // MR1 + +class DllExportPCCTS ANTLRTokenStream { +public: + virtual _ANTLRTokenPtr getToken() = 0; + virtual ANTLRParser * setParser(ANTLRParser * /*p MR23*/) {return 0; }; // MR12 + virtual ANTLRParser * getParser() { return 0; }; // MR12 +}; + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/BufFileInput.cpp b/Tools/Source/TianoTools/Pccts/h/BufFileInput.cpp new file mode 100644 index 0000000000..99d08a42a4 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/BufFileInput.cpp @@ -0,0 +1,100 @@ +// FILE: BufFileInput.cpp +// AUTHOR: Alexey Demakov (AVD) demakov@kazbek.ispras.ru +// CREATION: 26-JAN-1998 +// DESCRIPTION: File Input Stream with lookahead for Scanner. +// See file BufFileInput.h for details + +// Change History: +// +// 22-Jun-1998 assert.h -> PCCTS_ASSERT_H +// string.h -> PCCTS_STRING_H +// +// 28-May-1998 Add virtual destructor to release buffer. +// +// Add dummy definition for ANTLRTokenType +// to allow compilation without knowing +// token type codes. +// +// Manfred Kogler (km@cast.uni-linz.ac.at) +// (1.33MR14) +// +// 20-Jul-1998 MR14a - Reorder initialization list for ctor. +// + +enum ANTLRTokenType {TER_HATES_CPP=0, SO_DO_OTHERS=9999 }; + +#include "pcctscfg.h" +#include "pccts_assert.h" +#include "pccts_string.h" + +PCCTS_NAMESPACE_STD + +#include "BufFileInput.h" + +BufFileInput::BufFileInput( FILE *f, int buf_size ) +: input( f ), + buf( new int[buf_size] ), + size( buf_size ), + start( 0 ), + len( 0 ) +{ +} + +BufFileInput::~BufFileInput() +{ + delete [] buf; +} + +int BufFileInput::nextChar( void ) +{ + if( len > 0 ) + { + // get char from buffer + int c = buf[start]; + + if( c != EOF ) + { + start++; start %= size; + len--; + } + return c; + } else { + // get char from file + int c = getc( input ); + + if( c == EOF ) + { + // if EOF - put it in the buffer as indicator + buf[start] = EOF; + len++; + } + return c; + } +} + +int BufFileInput::lookahead( char* s ) +{ + int l = strlen( s ); + + assert( 0 < l && l <= size ); + + while( len < l ) + { + int c = getc( input ); + + buf[ (start+len) % size ] = c; + + len++; + + if( c == EOF ) return 0; + } + + for( int i = 0; i < l; i++ ) + { + if( s[i] != buf[ (start+i) % size ] ) return 0; + } + return 1; +} + +// End of file BufFileInput.cpp + diff --git a/Tools/Source/TianoTools/Pccts/h/BufFileInput.h b/Tools/Source/TianoTools/Pccts/h/BufFileInput.h new file mode 100644 index 0000000000..ea54c0ee26 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/BufFileInput.h @@ -0,0 +1,53 @@ +// FILE: BufFileInput.h +// AUTHOR: Alexey Demakov (AVD) demakov@kazbek.ispras.ru +// CREATION: 26-JAN-1998 +// DESCRIPTION: File Input Stream with lookahead for Scanner +// Tested under Win32 with ANTLR 1.33 MR10 and MSVC 5.0 + +// Change History: +// +// 28-May-1998 Add virtual destructor to release buffer +// Manfred Kogler (km@cast.uni-linz.ac.at) +// (1.33MR14) + +#ifndef BufFileInput_h +#define BufFileInput_h + +#include "pcctscfg.h" + +#include "pccts_stdio.h" + +PCCTS_NAMESPACE_STD + +#include "DLexerBase.h" + +class DllExportPCCTS BufFileInput : public DLGInputStream +{ +public: + // constructor + // f - input stream + // buf_size - size of buffer (maximal length for string in is_in) + + BufFileInput(FILE *f, int buf_size = 8 ); + + virtual ~BufFileInput(); + + // gets next char from stream + + virtual int nextChar( void ); + + // looks in stream and compares next l characters with s + // returns the result of comparision + + int lookahead( char* s ); + +private: + FILE *input; // input stream; + int* buf; // buffer + int size; // size of buffer + int start; // position of the first symbol in buffer + int len; // count of characters in buffers +}; + +#endif +// end of file BufFileInput.h diff --git a/Tools/Source/TianoTools/Pccts/h/DLG_stream_input.h b/Tools/Source/TianoTools/Pccts/h/DLG_stream_input.h new file mode 100644 index 0000000000..d2147f5217 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/DLG_stream_input.h @@ -0,0 +1,98 @@ + +/************************************************************/ +/* */ +/* Predefined char stream: Input from (c++) stream. */ +/* */ +/* By Hubert Holin (Hubert.Holin@Bigfoot.com), 1998. */ +/* */ +/* This is completely free stuff, do whatever you want with */ +/* it (but then, I will take no responsability for whatever */ +/* may happen if you do either... caveat emptor!). */ +/* */ +/************************************************************/ + +#ifndef _DLG_STREAM_INPUT_H +#define _DLG_STREAM_INPUT_H + +#include "pccts_istream.h" + +PCCTS_NAMESPACE_STD + +#ifndef DLGX_H +#include "DLexerBase.h" +#endif + + +// NOTES: The semantics of the copy constructor +// and the affectation operator may be unwaranted... +// and the stream may not be reset. +// +// It would have been so much nicer for nextChar() +// to throw (of for the DLGInputStream to change status) +// upon hiting EOF than to return an "int"... + +template < + class E, + class T = ::std::char_traits + > +class DLG_stream_input : public DLGInputStream +{ +public: + + DLG_stream_input(::std::basic_istream * p_input_stream) + : input(p_input_stream) + { + // nothing to do! + }; + + DLG_stream_input(const DLG_stream_input & a_recopier) + : input(a_recopier.input) + { + // nothing to do! + }; + + virtual ~DLG_stream_input() + { + this->purge(); // bloody templarized lookup... + }; + + DLG_stream_input operator = (const DLG_stream_input & a_affecter) + { + if (this != &a_affecter) + { + input = a_affecter.input; + } + + return(*this); + }; + + virtual int nextChar() + { + E extracted_stuff; + + input->get(extracted_stuff); + + if (*input) + { + return(int(extracted_stuff)); + } + else + { + return(EOF); + } + }; + +protected: + + ::std::basic_istream * input; + +private: + + void purge() + { + // nothing to do! + }; +}; + +#endif /* _DLG_STREAM_INPUT_H */ + diff --git a/Tools/Source/TianoTools/Pccts/h/DLexer.h b/Tools/Source/TianoTools/Pccts/h/DLexer.h new file mode 100644 index 0000000000..37cac24f14 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/DLexer.h @@ -0,0 +1,191 @@ +/* DLexer.h (formerly DLexer.cpp) + * + * This was renamed because the use of the .cpp extension caused problems + * with IDEs. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#define ZZINC {if ( track_columns ) (++_endcol);} + +#define ZZGETC {ch = input->nextChar(); cl = ZZSHIFT(ch);} + +#define ZZNEWSTATE (newstate = dfa[state][cl]) + +#ifndef ZZCOPY +#define ZZCOPY \ + /* Truncate matching buffer to size (not an error) */ \ + if (nextpos < lastpos){ \ + *(nextpos++) = ch; \ + }else{ \ + bufovf = 1; \ + } +#endif + +void DLGLexer:: +mode( int m ) +{ + /* points to base of dfa table */ + if (m*actions[accepts[state]])(); + +// MR1 +// MR1 11-Apr-97 Help for tracking DLG results +// MR1 + +#ifdef DEBUG_LEXER + +/* MR1 */ if (debugLexerFlag) { +/* MR1 */ if (parser != NULL) { +/* MR1 */ /* MR23 */ printMessage(stdout, "\ntoken name=%s",parser->parserTokenName(tk)); +/* MR1 */ } else { +/* MR1 */ /* MR23 */ printMessage(stdout, "\ntoken nnumber=%d",tk); +/* MR1 */ }; +/* MR1 */ /* MR23 */ printMessage(stdout, " lextext=(%s) mode=%d", +/* MR1 */ (_lextext[0]=='\n' && _lextext[1]==0) ? +/* MR1 */ "newline" : _lextext, +/* MR1 */ automaton); +/* MR1 */ if (interactive && !charfull) { +/* MR1 */ /* MR23 */ printMessage(stdout, " char=empty"); +/* MR1 */ } else { +/* MR1 */ if (ch=='\n') { +/* MR1 */ /* MR23 */ printMessage(stdout, " char=newline"); +/* MR1 */ } else { +/* MR1 */ /* MR23 */ printMessage(stdout, " char=(%c)",ch); +/* MR1 */ }; +/* MR1 */ }; +/* MR1 */ /* MR23 */ printMessage(stdout, " %s\n", +/* MR1 */ (add_erase==1 ? "skip()" : +/* MR1 */ add_erase==2 ? "more()" : +/* MR1 */ "")); +/* MR1 */ }; + +#endif + + switch (add_erase) { + case 1: goto skip; + case 2: goto more; + } + return tk; +} + +void DLGLexer:: +advance() +{ + if ( input==NULL ) err_in(); + ZZGETC; charfull = 1; ZZINC; +} diff --git a/Tools/Source/TianoTools/Pccts/h/DLexerBase.cpp b/Tools/Source/TianoTools/Pccts/h/DLexerBase.cpp new file mode 100644 index 0000000000..b218afc038 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/DLexerBase.cpp @@ -0,0 +1,302 @@ +/* DLGLexerBase.c + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_stdlib.h" + +PCCTS_NAMESPACE_STD + +/* I have to put this here due to C++ limitation + * that you can't have a 'forward' decl for enums. + * I hate C++!!!!!!!!!!!!!!! + */ + +// MR1 +// MR1 10-Apr-97 133MR1 Prevent use of varying sizes for the +// MR1 ANTLRTokenType enum +// MR1 + +enum ANTLRTokenType { TER_HATES_CPP=0, ITS_UTTER_GARBAGE, // MR1 + WITH_SOME_GOOD_IDEAS=9999}; // MR1 + +#define ANTLR_SUPPORT_CODE + +#include "pcctscfg.h" +#include DLEXERBASE_H +#include APARSER_H // MR23 + +DLGLexerBase:: +DLGLexerBase(DLGInputStream *in, + unsigned bufsize, + int _interactive, + int _track_columns) +{ + this->_bufsize = bufsize; + this->_lextext = new DLGChar[_bufsize]; + if ( this->_lextext==NULL ) { + panic("text buffer is NULL"); + } + this->_begexpr = this->_endexpr = NULL; + this->ch = this->bufovf = 0; + this->nextpos = NULL; + this->cl = 0; + this->add_erase = 0; + this->input = in; + this->_begcol = 0; + this->_endcol = 0; + this->_line = 1; + this->charfull = 0; + this->automaton = 0; + this->token_to_fill = NULL; + this->interactive = _interactive; + this->track_columns = _track_columns; + this->debugLexerFlag = 0; // MR1 + this->parser = NULL; // MR1 + this->lexErrCount=0; // MR11 +} + +// MR19 THM + +void DLGLexerBase::reset() +{ + this->charfull = 0; + this->_begcol = 0; + this->_endcol = 0; + this->automaton = 0; + this->_line=1; + this->lexErrCount=0; +} + +void DLGLexerBase:: +setInputStream( DLGInputStream *in ) +{ + this->input = in; + _line = 1; + charfull = 0; +} + +/* saves dlg state, but not what feeds dlg (such as file position) */ +void DLGLexerBase:: +saveState(DLGState *state) +{ + state->input = input; + state->interactive = interactive; + state->track_columns = track_columns; + state->auto_num = automaton; + state->add_erase = add_erase; + state->lookc = ch; + state->char_full = charfull; + state->begcol = _begcol; + state->endcol = _endcol; + state->line = _line; + state->lextext = _lextext; + state->begexpr = _begexpr; + state->endexpr = _endexpr; + state->bufsize = _bufsize; + state->bufovf = bufovf; + state->nextpos = nextpos; + state->class_num = cl; + state->debugLexerFlag = debugLexerFlag; // MR1 + state->parser = parser; // MR1 +} + +void DLGLexerBase:: +restoreState(DLGState *state) +{ + input = state->input; + interactive = state->interactive; + track_columns = state->track_columns; + automaton = state->auto_num; + add_erase = state->add_erase; + ch = state->lookc; + charfull = state->char_full; + _begcol = state->begcol; + _endcol = state->endcol; + _line = state->line; + _lextext = state->lextext; + _begexpr = state->begexpr; + _endexpr = state->endexpr; + _bufsize = state->bufsize; + bufovf = state->bufovf; + nextpos = state->nextpos; + cl = state->class_num; + debugLexerFlag = state->debugLexerFlag; // MR1 + parser = state->parser; // MR1 +} + +/* erase what is currently in the buffer, and get a new reg. expr */ +void DLGLexerBase:: +skip() +{ + add_erase = 1; +} + +/* don't erase what is in the lextext buffer, add on to it */ +void DLGLexerBase:: +more() +{ + add_erase = 2; +} + +/* substitute c for the reg. expr last matched and is in the buffer */ +void DLGLexerBase:: +replchar(DLGChar c) +{ + /* can't allow overwriting null at end of string */ + if (_begexpr < &_lextext[_bufsize-1]){ + *_begexpr = c; + *(_begexpr+1) = '\0'; + } + _endexpr = _begexpr; + if (c != '\0') { + nextpos = _begexpr + 1; + } + else { + nextpos = _begexpr; /* MR30 Zero terminates string. */ + } +} + +/* replace the string s for the reg. expr last matched and in the buffer */ + +#ifdef _MSC_VER // MR23 +//Turn off "assignment within conditional expression" warning +#pragma warning(disable : 4706) +#endif +void DLGLexerBase:: +replstr(const DLGChar *s) /* MR20 const */ +{ + register DLGChar *l= &_lextext[_bufsize -1]; + + nextpos = _begexpr; + if (s){ + while ((nextpos <= l) && (*(nextpos++) = *(s++))){ + /* empty */ + } + /* correct for NULL at end of string */ + nextpos--; + } + if ((nextpos <= l) && (*(--s) == 0)){ + bufovf = 0; + }else{ + bufovf = 1; + } + *(nextpos) = '\0'; + _endexpr = nextpos - 1; +} +#ifdef _MSC_VER // MR23 +#pragma warning(default: 4706) +#endif + +void DLGLexerBase:: +errstd(const char *s) /* MR20 const */ +{ + lexErrCount++; /* MR11 */ + /* MR23 */ printMessage(stderr, + "%s near line %d (text was '%s')\n", + ((s == NULL) ? "Lexical error" : s), + _line,_lextext); +} + +int DLGLexerBase:: +err_in() +{ + /* MR23 */ printMessage(stderr,"No input stream, function, or string\n"); + /* return eof to get out gracefully */ + return EOF; +} + +ANTLRTokenType DLGLexerBase:: +erraction() +{ + errstd("invalid token"); + advance(); + skip(); + return (ANTLRTokenType) 0; // bogus, but satisfies compiler +} + +_ANTLRTokenPtr DLGLexerBase:: +getToken() +{ + if ( token_to_fill==NULL ) panic("NULL token_to_fill"); + ANTLRTokenType tt = nextTokenType(); + _ANTLRTokenPtr tk = token_to_fill->makeToken(tt, _lextext,_line); + return tk; +} + +void DLGLexerBase:: +panic(const char *msg) /* MR20 const */ +{ + if (parser) //MR23 + parser->panic(msg); //MR23 + else //MR23 + { + /* MR23 */ printMessage(stderr, "DLG panic: %s\n", msg); + // + // 7-Apr-97 133MR1 + // + exit(PCCTS_EXIT_FAILURE); // MR1 + } +} + +ANTLRParser * DLGLexerBase:: // MR1 +setParser(ANTLRParser *p) { // MR1 + ANTLRParser *oldValue=parser; // MR1 + parser=p; // MR1 + return oldValue; // MR1 +} // MR1 + // MR1 +ANTLRParser * DLGLexerBase:: // MR1 +getParser() { // MR1 + return parser; // MR1 +} // MR1 + // MR1 +int DLGLexerBase:: // MR1 +debugLexer(int newValue) { // MR1 + int oldValue=debugLexerFlag; // MR1 + debugLexerFlag=newValue; // MR1 + return oldValue; // MR1 +} // MR1 + +//MR23 +int DLGLexerBase::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + + int iRet = 0; + if (parser) + parser->printMessageV(pFile, pFormat, marker); + else + iRet = vfprintf(pFile, pFormat, marker); + + va_end( marker ); + return iRet; +} diff --git a/Tools/Source/TianoTools/Pccts/h/DLexerBase.h b/Tools/Source/TianoTools/Pccts/h/DLexerBase.h new file mode 100644 index 0000000000..db6cc1890c --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/DLexerBase.h @@ -0,0 +1,198 @@ +/* DLGLexerBase.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef DLGX_H +#define DLGX_H + +#include "pcctscfg.h" +#include "pccts_stdio.h" + +PCCTS_NAMESPACE_STD + +#include ATOKEN_H +#include ATOKENSTREAM_H + +class ANTLRParser; // MR1 + +/* must define what a char looks like; can make this a class too */ +typedef char DLGChar; + +/* Can have it as a class too: (ack this looks weird; is it right?) +class DllExportPCCTS DLGChar { +private: + int c; +public: + DLGChar(int ch) { c = ch; } + int atom() { return c; } +}; +*/ + +/* user must subclass this */ +class DllExportPCCTS DLGInputStream { +public: + virtual int nextChar() = 0; +}; + +/* Predefined char stream: Input from FILE */ +class DllExportPCCTS DLGFileInput : public DLGInputStream { +private: + int found_eof; + FILE *input; +public: + DLGFileInput(FILE *f) { input = f; found_eof = 0; } + int nextChar() { + int c; + if ( found_eof ) return EOF; + else { + c=getc(input); + if ( c==EOF ) found_eof = 1; + return c; + } + } + void DLGFileReset(FILE *f) {input=f; found_eof = 0; }; // MR11 +}; + +// MR9 Suggested by Bruce Guenter (bruceg@qcc.sk.ca) +// MR9 Make DLGStringInput const correct + +/* Predefined char stream: Input from string */ +class DllExportPCCTS DLGStringInput : public DLGInputStream { +private: + const DLGChar *input; // MR9 + const DLGChar *p; // MR9 +public: + DLGStringInput(const DLGChar *s) { input = s; p = &input[0];} // MR9 + int nextChar() + { + if (*p) return (int) (unsigned char) *p++; // MR14 + else return EOF; + } + + void DLGStringReset(const DLGChar *s) {input=s; p= &input[0]; }; // MR11 // MR16 +}; + +class DllExportPCCTS DLGState { +public: + DLGInputStream *input; + int interactive; + int track_columns; + int auto_num; + int add_erase; + int lookc; + int char_full; + int begcol, endcol; + int line; + DLGChar *lextext, *begexpr, *endexpr; + int bufsize; + int bufovf; + DLGChar *nextpos; + int class_num; + int debugLexerFlag; // MR1 + ANTLRParser *parser; // MR1 +}; + +/* user must subclass this */ +class DllExportPCCTS DLGLexerBase : public ANTLRTokenStream { +public: + virtual ANTLRTokenType erraction(); + +protected: + DLGInputStream *input; + int interactive; + int track_columns; + DLGChar *_lextext; /* text of most recently matched token */ + DLGChar *_begexpr; /* beginning of last reg expr recogn. */ + DLGChar *_endexpr; /* beginning of last reg expr recogn. */ + int _bufsize; /* number of characters in lextext */ + int _begcol; /* column that first character of token is in*/ + int _endcol; /* column that last character of token is in */ + int _line; /* line current token is on */ + int ch; /* character to determine next state */ + int bufovf; /* indicates that buffer too small for text */ + int charfull; + DLGChar *nextpos; /* points to next available position in lextext*/ + int cl; + int automaton; + int add_erase; + DLGChar ebuf[70]; + _ANTLRTokenPtr token_to_fill; + + int debugLexerFlag; // MR1 + ANTLRParser *parser; // MR1 +public: + virtual _ANTLRTokenPtr getToken(); // MR12 public + virtual void advance(void) = 0; + void skip(void); /* erase lextext, look for antoher token */ + void more(void); /* keep lextext, look for another token */ + void mode(int k); /* switch to automaton 'k' */ + void saveState(DLGState *); + void restoreState(DLGState *); + virtual ANTLRTokenType nextTokenType(void)=0;/* get next token */ + void replchar(DLGChar c); /* replace last recognized reg. expr. with + a character */ + void replstr(const DLGChar *s); /* replace last recognized reg. expr. with + a string */ /* MR20 const */ + virtual int err_in(); // MR1 + virtual void errstd(const char *); // MR1 MR20 const + int line() { return _line; } + void set_line(int newValue) { _line=newValue; }; // MR1 + virtual void newline() { _line++; } + DLGChar *lextext() { return _lextext; } + + int begcol() { return _begcol; } + int endcol() { return _endcol; } + void set_begcol(int a) { _begcol=a; } + void set_endcol(int a) { _endcol=a; } + DLGChar *begexpr() { return _begexpr; } + DLGChar *endexpr() { return _endexpr; } + int bufsize() { return _bufsize; } + + void setToken(ANTLRAbstractToken *t) { token_to_fill = t; } + + void setInputStream(DLGInputStream *); + DLGLexerBase(DLGInputStream *in, + unsigned bufsize=2000, + int interactive=0, + int track_columns=0); + void reset(); // MR19 + virtual ~DLGLexerBase() { delete [] _lextext; } + virtual void panic(const char *msg); // MR1 MR20 const + void trackColumns() { + track_columns = 1; + this->_begcol = 0; + this->_endcol = 0; + }; + virtual ANTLRParser *setParser(ANTLRParser *p); // MR1 + virtual ANTLRParser *getParser(); // MR1 + virtual int debugLexer(int value); // MR1 + int lexErrCount; // MR12 + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 +}; + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/PBlackBox.h b/Tools/Source/TianoTools/Pccts/h/PBlackBox.h new file mode 100644 index 0000000000..d25b8d6939 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/PBlackBox.h @@ -0,0 +1,134 @@ +#ifndef PBLACKBOX_H +#define PBLACKBOX_H + +/* + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +/* Completely rewritten by Chris Uzdavinis (chris@atdesk.com) for MR23 */ + +#include "pcctscfg.h" + +#include "pccts_iostream.h" + +PCCTS_NAMESPACE_STD + +// MR20 Added #include for "DLexerBase.h" + +#include "DLexerBase.h" + +// +// The default buffer size of the lexer is given by the +// second argument of the lexer's ctor. It is optional +// and defaults to 2000 +// + +template +class DllExportPCCTS ParserBlackBox { +private: + // no copy construction allowed + ParserBlackBox(ParserBlackBox const &); + + // no copy assignment allowed + ParserBlackBox & operator=(ParserBlackBox const &); + +protected: + DLGFileInput *in; + Lexer *scan; + _ANTLRTokenPtr tok; + ANTLRTokenBuffer *pipe; + Parser *_parser; + FILE *file; + int openByBlackBox; /* MR21 Don't close what we haven't opened */ +public: + + ParserBlackBox(FILE *f) + : in(0) + , scan(0) + , tok(0) + , pipe(0) + , _parser(0) + , file(0) + , openByBlackBox(0) + { + if (f == NULL) + { + cerr << "invalid file pointer\n"; + } + else + { + openByBlackBox = 0; /* MR21a */ + file = f; + in = new DLGFileInput(f); + scan = new Lexer(in); + pipe = new ANTLRTokenBuffer(scan); + tok = new Token; + scan->setToken(tok); + _parser = new Parser(pipe); + _parser->init(); + } + } + ParserBlackBox(char *fname) + : in(0) + , scan(0) + , tok(0) + , pipe(0) + , _parser(0) + , file(0) + , openByBlackBox(0) + { + FILE *f = fopen(fname, "r"); + if ( f==NULL ) { + openByBlackBox = 0; + cerr << "cannot open " << fname << "\n"; return; + } + else { + openByBlackBox = 1; + file = f; + in = new DLGFileInput(f); + scan = new Lexer(in); + pipe = new ANTLRTokenBuffer(scan); + tok = new Token; + scan->setToken(tok); + _parser = new Parser(pipe); + _parser->init(); + } + } + + ~ParserBlackBox() + { + delete in; delete scan; delete pipe; delete _parser; delete tok; + if (1 == openByBlackBox) { + fclose(file); + } + } + + Parser *parser() { return _parser; } + Lexer *getLexer() { return scan; } +}; + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/PCCTSAST.cpp b/Tools/Source/TianoTools/Pccts/h/PCCTSAST.cpp new file mode 100644 index 0000000000..a8249cdac0 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/PCCTSAST.cpp @@ -0,0 +1,684 @@ +/* + * PCCTSAST.C + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public + * domain. An individual or company may do whatever they wish with + * source code distributed with SORCERER or the code generated by + * SORCERER, including the incorporation of SORCERER, or its output, into + * commerical software. + * + * We encourage users to develop software with SORCERER. However, we do + * ask that credit is given to us for developing SORCERER. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like SORCERER and have developed a nice tool with the + * output, please mention that you developed it using SORCERER. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * SORCERER 1.00B14 and ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * AHPCRC, University of Minnesota + * 1992-2000 + */ + +#define ANTLR_SUPPORT_CODE + +#include "pcctscfg.h" + +#include "PCCTSAST.h" +#include "pccts_stdarg.h" + +PCCTS_NAMESPACE_STD + +#include + +//#include "SList.h" + + /* String Scanning/Parsing Stuff */ + +const char *PCCTS_AST::scan_token_tbl[] = { /* MR20 const */ + "invalid", /* 0 */ + "LPAREN", /* 1 */ + "RPAREN", /* 2 */ + "PERCENT", /* 3 */ + "INT", /* 4 */ + "COLON", /* 5 */ + "POUND", /* 6 */ + "PERIOD", /* 7 */ +}; + +void PCCTS_AST:: +addChild(PCCTS_AST *t) +{ + if ( t==NULL ) return; + PCCTS_AST *s = down(); + if ( s!=NULL ) + { + while ( s->right()!=NULL ) s = s->right(); + s->setRight(t); + } + else + this->setDown(t); +} + +void PCCTS_AST:: +lisp(FILE *f) +{ + if ( down() != NULL ) /* MR23 */ printMessage(f," ("); + lisp_action(f); + if ( down()!=NULL ) down()->lisp(f); + if ( down() != NULL ) /* MR23 */ printMessage(f," )"); + if ( right()!=NULL ) right()->lisp(f); +} + +/* build a tree (root child1 child2 ... NULL) + * If root is NULL, simply make the children siblings and return ptr + * to 1st sibling (child1). If root is not single node, return NULL. + * + * Siblings that are actually sibling lists themselves are handled + * correctly. For example #( NULL, #( NULL, A, B, C), D) results + * in the tree ( NULL A B C D ). + * + * Requires at least two parameters with the last one being NULL. If + * both are NULL, return NULL. + * + * The down() and right() down/right pointers are used to make the tree. + */ +PCCTS_AST *PCCTS_AST:: +make(PCCTS_AST *rt, ...) +{ + va_list ap; + register PCCTS_AST *child, *sibling=NULL, *tail=NULL /*MR23*/, *w; + PCCTS_AST *root; + + va_start(ap, rt); + root = rt; + + if ( root != NULL ) + if ( root->down() != NULL ) return NULL; + child = va_arg(ap, PCCTS_AST *); + while ( child != NULL ) + { + /* find end of child */ + for (w=child; w->right()!=NULL; w=w->right()) {;} + if ( sibling == NULL ) {sibling = child; tail = w;} + else {tail->setRight(child); tail = w;} + child = va_arg(ap, PCCTS_AST *); + } + if ( root==NULL ) root = sibling; + else root->setDown(sibling); + va_end(ap); + return root; +} + +/* The following push and pop routines are only used by ast_find_all() */ + +void PCCTS_AST:: +_push(PCCTS_AST **st, int *sp, PCCTS_AST *e) +{ + (*sp)--; + require((*sp)>=0, "stack overflow"); + st[(*sp)] = e; +} + +PCCTS_AST *PCCTS_AST:: +_pop(PCCTS_AST **st, int *sp) +{ + PCCTS_AST *e = st[*sp]; + (*sp)++; + require((*sp)<=MaxTreeStackDepth, "stack underflow"); + return e; +} + +/* Find all occurrences of u in t. + * 'cursor' must be initialized to 't'. It eventually + * returns NULL when no more occurrences of 'u' are found. + */ +PCCTS_AST *PCCTS_AST:: +ast_find_all(PCCTS_AST *u, PCCTS_AST **cursor) +{ + PCCTS_AST *sib; + /*** static ***/ PCCTS_AST *template_stack[MaxTreeStackDepth]; /* MR23 Remove "static" */ + /*** static ***/ int tsp = MaxTreeStackDepth; /* MR23 Remove "static" */ + +////static int nesting = 0; /* MR23 Not referenced */ + + if ( *cursor == NULL ) return NULL; + if ( *cursor!=this ) sib = *cursor; + else { + /* else, first time--start at top of template 't' */ + tsp = MaxTreeStackDepth; + sib = this; + /* bottom of stack is always a NULL--"cookie" indicates "done" */ + _push(template_stack, &tsp, NULL); + } + +keep_looking: + if ( sib==NULL ) /* hit end of sibling list */ + { + sib = _pop(template_stack, &tsp); + if ( sib == NULL ) { *cursor = NULL; return NULL; } + } + + if ( sib->type() != u->type() ) + { + /* look for another match */ + if ( sib->down()!=NULL ) + { + if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right()); + sib=sib->down(); + goto keep_looking; + } + /* nothing below to try, try next sibling */ + sib=sib->right(); + goto keep_looking; + } + + /* found a matching root node, try to match what's below */ + if ( match_partial(sib, u) ) + { + /* record sibling cursor so we can pick up next from there */ + if ( sib->down()!=NULL ) + { + if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right()); + *cursor = sib->down(); + } + else if ( sib->right()!=NULL ) *cursor = sib->right(); + else *cursor = _pop(template_stack, &tsp); + return sib; + } + + /* no match, keep searching */ + if ( sib->down()!=NULL ) + { + if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right()); + sib=sib->down(); + } + else sib = sib->right(); /* else, try to right if zip below */ + goto keep_looking; +} + +/* are two trees exactly alike? */ +int PCCTS_AST:: +match(PCCTS_AST *u) +{ + PCCTS_AST *t = this; + PCCTS_AST *sib; + + if ( u==NULL ) return 0; + + for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right()) + { + if ( sib->type() != u->type() ) return 0; + if ( sib->down()!=NULL ) + if ( !sib->down()->match(u->down()) ) return 0; + } + return 1; +} + +/* Is 'u' a subtree of 't' beginning at the root? */ +int PCCTS_AST:: +match_partial(PCCTS_AST *t, PCCTS_AST *u) +{ + PCCTS_AST *sib; + + if ( u==NULL ) return 1; + if ( t==NULL ) return 0; /* MR23 removed unreachable code */ + + for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right()) + { + if ( sib->type() != u->type() ) return 0; + if ( sib->down()!=NULL ) + if ( !match_partial(sib->down(), u->down()) ) return 0; + } + return 1; +} + +#ifdef _MSC_VER // MR23 +//Turn off "unreachable code" warning +#pragma warning(disable : 4702) +#endif +/* Walk the template tree 't' (matching against 'this'), filling in the + * 'labels' array, and setting 'n' according to how many labels were matched. + */ +int PCCTS_AST:: +scanmatch(ScanAST *t, PCCTS_AST **labels[], int *n) +{ + ScanAST *sib; + PCCTS_AST *u = this; + + if ( u==NULL ) return 0; + + for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right()) + { + /* make sure tokens match; token of '0' means wildcard match */ + if ( sib->type() != u->type() && sib->type()!=0 ) return 0; + /* we have a matched token here; set label pointers if exists */ + if ( sib->label_num>0 ) + { + require(labels!=NULL, "label found in template, but no array of labels"); + (*n)++; + *(labels[sib->label_num-1]) = u; + } + /* match what's below if something there and current node is not wildcard */ + if ( sib->down()!=NULL && sib->type()!=0 ) + { + if ( sib->down()==NULL ) + { + if ( u->down()!=NULL ) + return 0; + else + return 1; + } + if ( !u->down()->scanmatch(sib->down(), labels, n) ) return 0; + } + } + return 1; +} +#ifdef _MSC_VER // MR23 +#pragma warning(default : 4702) +#endif + +void PCCTS_AST:: +insert_after(PCCTS_AST *b) +{ + PCCTS_AST *end; + if ( b==NULL ) return; + /* find end of b's child list */ + for (end=b; end->right()!=NULL; end=end->right()) {;} + end->setRight(this->right()); + this->setRight(b); +} + +void PCCTS_AST:: +append(PCCTS_AST *b) +{ + PCCTS_AST *end; + require(b!=NULL, "append: NULL input tree"); + /* find end of child list */ + for (end=this; end->right()!=NULL; end=end->right()) {;} + end->setRight(b); +} + +PCCTS_AST *PCCTS_AST:: +tail() +{ + PCCTS_AST *end; + /* find end of child list */ + for (end=this; end->right()!=NULL; end=end->right()) {;} + return end; +} + +PCCTS_AST *PCCTS_AST:: +bottom() +{ + PCCTS_AST *end; + /* find end of child list */ + for (end=this; end->down()!=NULL; end=end->down()) {;} + return end; +} + +PCCTS_AST *PCCTS_AST:: +cut_between(PCCTS_AST *a, PCCTS_AST *b) +{ + PCCTS_AST *end, *ret; + if (a==NULL||b==NULL) return NULL; + /* find node pointing to b */ + for (end=a; end->right()!=NULL&&end->right()!=b; end=end->right()) + {;} + if (end->right()==NULL) return NULL; //ast_cut_between: a,b not connected + end->setRight(NULL); /* don't want it point to 'b' anymore */ + ret = a->right(); + a->setRight(b); + return ret; +} + +#ifdef NOT_YET +SList *PCCTS_AST:: +to_slist() +{ + SList *list = new SList; + PCCTS_AST *p; + + for (p=this; p!=NULL; p=p->right()) + { + list->add(p); + } + return list; +} +#endif + +void PCCTS_AST:: +tfree() +{ + PCCTS_AST *t = this; + if ( t->down()!=NULL ) t->down()->tfree(); + if ( t->right()!=NULL ) t->right()->tfree(); + delete t; +} + +int PCCTS_AST:: +nsiblings() +{ + PCCTS_AST *t = this; + int n=0; + + while ( t!=NULL ) + { + n++; + t = t->right(); + } + return n; +} + +PCCTS_AST *PCCTS_AST:: +sibling_index(int i) +{ + PCCTS_AST *t = this; + int j=1; + require(i>0, "sibling_index: i<=0"); + + while ( t!=NULL ) + { + if ( j==i ) return t; + j++; + t = t->right(); + } + return NULL; +} + +/* Assume this is a root node of a tree-- + * duplicate that node and what's below; ignore siblings of root node. + */ + +// MR9 23-Sep-97 RJV +// MR9 +// MR9 RJV: Original version only duplicated the node and down elements. +// MR9 Made copies of the pointers to sibling. +// MR9 Changed call "down()->deepCopy()" to "down()->deepCopyBushy()" +// MR9 + +PCCTS_AST *PCCTS_AST:: +deepCopy() +{ + PCCTS_AST *u = this->shallowCopy(); + if ( down()!=NULL ) u->setDown(down()->deepCopyBushy()); + u->setRight(NULL); + return u; +} + +/* Copy all nodes including siblings of root. */ +PCCTS_AST *PCCTS_AST:: +deepCopyBushy() +{ + PCCTS_AST *u = this->shallowCopy(); + /* copy the rest of the tree */ + if ( down()!=NULL ) u->setDown(down()->deepCopyBushy()); + if ( right()!=NULL ) u->setRight(right()->deepCopyBushy()); + return u; +} + +void PCCTS_AST:: +scanast_free(ScanAST *t) +{ + if ( t == NULL ) return; + scanast_free( t->down() ); + scanast_free( t->right() ); + free( (char *) t ); // MR1 +} + +/* + * scan + * + * This function is like scanf(): it attempts to match a template + * against an input tree. A variable number of tree pointers + * may be set according to the '%i' labels in the template string. + * For example: + * + * t->ast_scan("#( 6 #(5 %1:4 %2:3) #(1 %3:3 %4:3) )", + * &w, &x, &y, &z); + * + * Naturally, you'd want this converted from + * + * t->ast_scan("#( RangeOp #(Minus %1:IConst %2:Var) #(Plus %3:Var %4Var) )", + * &w, &x, &y, &z); + * + * by SORCERER. + * + * This function call must be done withing a SORCERER file because SORCERER + * must convert the token references to the associated token number. + * + * This functions parses the template and creates trees which are then + * matched against the input tree. The labels are set as they are + * encountered; hence, partial matches may leave some pointers set + * and some NULL. This routines initializes all argument pointers to NULL + * at the beginning. + * + * This function returns the number of labels matched. + */ +int PCCTS_AST:: +ast_scan(char *templ, ...) +{ + va_list ap; + ScanAST *tmpl; + int n, i, found=0; + PCCTS_AST ***label_ptrs=NULL; + + va_start(ap, templ); + + /* make a ScanAST tree out of the template */ + tmpl = stringparser_parse_scanast(templ, &n); + + /* make an array out of the labels */ + if ( n>0 ) + { + label_ptrs = (PCCTS_AST ***) calloc(n, sizeof(PCCTS_AST **)); + require(label_ptrs!=NULL, "scan: out of memory"); + for (i=1; i<=n; i++) + { + label_ptrs[i-1] = va_arg(ap, PCCTS_AST **); + *(label_ptrs[i-1]) = NULL; + } + } + + /* match the input tree against the template */ + scanmatch(tmpl, label_ptrs, &found); + + scanast_free(tmpl); + free( (char *) label_ptrs); // MR1 + + return found; +} + +ScanAST *PCCTS_AST:: +new_scanast(int tok) +{ + ScanAST *p = (ScanAST *) calloc(1, sizeof(ScanAST)); +// +// 7-Apr-97 133MR1 +// + if ( p == NULL ) + panic("out of memory\n"); // MR23 + p->_token = tok; + return p; +} + +ScanAST *PCCTS_AST:: +stringparser_parse_scanast(char *templ, int *num_labels) +{ + StringLexer lex; + StringParser parser; + ScanAST *t; + + stringlexer_init(&lex, templ); + stringparser_init(&parser, &lex); + t = stringparser_parse_tree(&parser); + *num_labels = parser.num_labels; + return t; +} + +void PCCTS_AST:: +stringparser_match(StringParser *parser, int token) +{ + if ( parser->token != token ) panic("bad tree in scan()"); +} + +/* + * Match a tree of the form: + * (root child1 child2 ... childn) + * or, + * node + * + * where the elements are integers or labeled integers. + */ +ScanAST *PCCTS_AST:: +stringparser_parse_tree(StringParser *parser) +{ + ScanAST *t=NULL, *root, *child, *last=NULL /*MR23*/; + + if ( parser->token != __POUND ) + { + return stringparser_parse_element(parser); + } + stringparser_match(parser,__POUND); + parser->token = stringscan_gettok(parser->lexer); + stringparser_match(parser,__LPAREN); + parser->token = stringscan_gettok(parser->lexer); + root = stringparser_parse_element(parser); + while ( parser->token != __RPAREN ) + { + child = stringparser_parse_element(parser); + if ( t==NULL ) { t = child; last = t; } + else { last->_right = child; last = child; } + } + stringparser_match(parser,__RPAREN); + parser->token = stringscan_gettok(parser->lexer); + root->_down = t; + return root; +} + +ScanAST *PCCTS_AST:: +stringparser_parse_element(StringParser *parser) +{ + char ebuf[100]; + int label = 0; + + if ( parser->token == __POUND ) + { + return stringparser_parse_tree(parser); + } + if ( parser->token == __PERCENT ) + { + parser->token = stringscan_gettok(parser->lexer); + stringparser_match(parser,__INT); + label = atoi(parser->lexer->text); + parser->num_labels++; + if ( label==0 ) panic("%%0 is an invalid label"); + parser->token = stringscan_gettok(parser->lexer); + stringparser_match(parser,__COLON); + parser->token = stringscan_gettok(parser->lexer); + /* can label tokens and wildcards */ + if ( parser->token != __INT && parser->token != __PERIOD ) + panic("can only label tokens"); + } + if ( parser->token == __INT ) + { + ScanAST *p = new_scanast(atoi(parser->lexer->text)); + parser->token = stringscan_gettok(parser->lexer); + p->label_num = label; + return p; + } + if ( parser->token == __PERIOD ) + { + ScanAST *p = new_scanast(0); /* token of 0 is wildcard */ + parser->token = stringscan_gettok(parser->lexer); + p->label_num = label; + return p; + } + sprintf(ebuf, "mismatch token in scan(): %s", scan_token_str(parser->token)); + panic(ebuf); + return NULL; +} + +void PCCTS_AST:: +stringparser_init(StringParser *parser, StringLexer *input) +{ + parser->lexer = input; + parser->token = stringscan_gettok(parser->lexer); + parser->num_labels = 0; +} + +void PCCTS_AST:: +stringlexer_init(StringLexer *scanner, char *input) +{ + scanner->text[0]='\0'; + scanner->input = input; + scanner->p = input; + stringscan_advance(scanner); +} + +void PCCTS_AST:: +stringscan_advance(StringLexer *scanner) +{ + if ( *(scanner->p) == '\0' ) scanner->c = __StringScanEOF; + scanner->c = *(scanner->p)++; +} + +int PCCTS_AST:: +stringscan_gettok(StringLexer *scanner) +{ + char *index = &scanner->text[0]; + char ebuf[100]; /* MR23 Remove static */ + + while ( isspace(scanner->c) ) { stringscan_advance(scanner); } + if ( isdigit(scanner->c) ) + { + int tok = __INT; + while ( isdigit(scanner->c) ) { + *index++ = (char) /* static_cast */ (scanner->c); // MR23 + stringscan_advance(scanner); + } + *index = '\0'; + return tok; + } + switch ( scanner->c ) + { + case '#' : stringscan_advance(scanner); return __POUND; + case '(' : stringscan_advance(scanner); return __LPAREN; + case ')' : stringscan_advance(scanner); return __RPAREN; + case '%' : stringscan_advance(scanner); return __PERCENT; + case ':' : stringscan_advance(scanner); return __COLON; + case '.' : stringscan_advance(scanner); return __PERIOD; + case '\0' : return __StringScanEOF; + case __StringScanEOF : return __StringScanEOF; + default : + sprintf(ebuf, "invalid char in scan: '%c'", scanner->c); + panic(ebuf); + } + return __StringScanEOF; // never reached +} + +const char *PCCTS_AST:: /* MR20 const */ +scan_token_str(int t) +{ + if ( VALID_SCAN_TOKEN(t) ) return scan_token_tbl[t]; + else if ( t==__StringScanEOF ) return ""; + else return ""; +} + +//MR23 +int PCCTS_AST::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + int iRet = vfprintf(pFile, pFormat, marker); + va_end( marker ); + return iRet; +} diff --git a/Tools/Source/TianoTools/Pccts/h/PCCTSAST.h b/Tools/Source/TianoTools/Pccts/h/PCCTSAST.h new file mode 100644 index 0000000000..3485da7d1b --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/PCCTSAST.h @@ -0,0 +1,143 @@ +/* Abstract syntax tree + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef PCCTSAST_H +#define PCCTSAST_H + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_stdlib.h" + +PCCTS_NAMESPACE_STD + +//class SList; + +#define StringScanMaxText 50 +#define MaxTreeStackDepth 400 + +// +// 7-Apr-97 133MR1 signed int not accepted by AT&T cfront +// +typedef struct stringlexer { + int c; // MR1 + char *input; + char *p; + char text[StringScanMaxText]; + } StringLexer; + +/* Define the structures needed for ast_scan() */ +typedef struct stringparser { + int token; + StringLexer *lexer; + int num_labels; + } StringParser; + +typedef struct _scanast { + struct _scanast *_right, *_down; + int _token; + int label_num; + int type() { return _token; } + struct _scanast *right() { return _right; } + struct _scanast *down() { return _down; } + } ScanAST; + +#define VALID_SCAN_TOKEN(t) (t>=__LPAREN && t<=__PERIOD) + +class DllExportPCCTS PCCTS_AST { +protected: + static const char *scan_token_tbl[]; /* MR20 const */ + enum { + __LPAREN=1, + __RPAREN=2, + __PERCENT=3, + __INT=4, + __COLON=5, + __POUND=6, + __PERIOD=7, + __StringScanEOF=-1}; + +protected: + const char *scan_token_str(int t); /* MR20 const */ + void stringlexer_init(StringLexer *scanner, char *input); + void stringparser_init(StringParser *, StringLexer *); + ScanAST *stringparser_parse_scanast(char *templ, int *n); + ScanAST *stringparser_parse_tree(StringParser *parser); + ScanAST *stringparser_parse_element(StringParser *parser); + void stringscan_advance(StringLexer *scanner); + int stringscan_gettok(StringLexer *scanner); + void _push(PCCTS_AST **st, int *sp, PCCTS_AST *e); + PCCTS_AST *_pop(PCCTS_AST **st, int *sp); + int match_partial(PCCTS_AST *t, PCCTS_AST *u); + int scanmatch(ScanAST *t, PCCTS_AST **labels[], int *n); + void scanast_free(ScanAST *t); + ScanAST *new_scanast(int tok); + void stringparser_match(StringParser *parser, int type); + virtual PCCTS_AST *deepCopyBushy(); + +public: + PCCTS_AST() {;} + virtual ~PCCTS_AST() {;} + + /* This group must be defined for SORCERER to work correctly */ + virtual PCCTS_AST *right() = 0; + virtual PCCTS_AST *down() = 0; + virtual void setRight(PCCTS_AST *t) = 0; + virtual void setDown(PCCTS_AST *t) = 0; +// we define these so ANTLR doesn't have to + virtual int type() { return 0; } + virtual void setType(int /*t MR23 */) {;} + virtual PCCTS_AST *shallowCopy() {panic("no shallowCopy() defined"); return NULL;} + + /* These are not needed by ANTLR, but are support functions */ + virtual PCCTS_AST *deepCopy(); // used by SORCERER in transform mode + virtual void addChild(PCCTS_AST *t); + virtual void lisp_action(FILE * /*f MR23 */) {;} + virtual void lisp(FILE *f); + static PCCTS_AST *make(PCCTS_AST *rt, ...); + virtual PCCTS_AST *ast_find_all(PCCTS_AST *u, PCCTS_AST **cursor); + virtual int match(PCCTS_AST *u); + virtual void insert_after(PCCTS_AST *b); + virtual void append(PCCTS_AST *b); + virtual PCCTS_AST *tail(); + virtual PCCTS_AST *bottom(); + static PCCTS_AST *cut_between(PCCTS_AST *a, PCCTS_AST *b); +// virtual SList *to_slist(); + virtual void tfree(); + int ast_scan(char *templ, ...); + virtual int nsiblings(); + virtual PCCTS_AST *sibling_index(int i); + + void require(int e,const char *err){ if ( !e ) panic(err); } /* MR20 const */ + virtual void panic(const char *err) // MR20 const + { /* MR23 */ printMessage(stderr, "PCCTS_AST: %s\n", err); exit(PCCTS_EXIT_FAILURE); } + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 +}; + +#endif /* PCCTSAST_H */ diff --git a/Tools/Source/TianoTools/Pccts/h/SList.h b/Tools/Source/TianoTools/Pccts/h/SList.h new file mode 100644 index 0000000000..5b8bf97427 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/SList.h @@ -0,0 +1,72 @@ +#ifndef SList_h +#define SList_h + +/* + * SList.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public + * domain. An individual or company may do whatever they wish with + * source code distributed with SORCERER or the code generated by + * SORCERER, including the incorporation of SORCERER, or its output, into + * commerical software. + * + * We encourage users to develop software with SORCERER. However, we do + * ask that credit is given to us for developing SORCERER. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like SORCERER and have developed a nice tool with the + * output, please mention that you developed it using SORCERER. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * PCCTS 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1992-2000 + */ + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_stdlib.h" + +PCCTS_NAMESPACE_STD + +#include "PCCTSAST.h" + +class PCCTS_AST; + +class SListNode { +protected: + void *_elem; /* pointer to any kind of element */ + SListNode *_next; +public: + SListNode() {_elem=_next=NULL;} + virtual ~SListNode() {_elem=_next=NULL;} + void *elem() { return _elem; } + void setElem(void *e) { _elem = e; } + void setNext(SListNode *t) { _next = t; } + SListNode *next() { return _next; } +}; + +class SList { + SListNode *head, *tail; +public: + SList() {head=tail=NULL;} + virtual ~SList() {head=tail=NULL;} + virtual void *iterate(SListNode **); + virtual void add(void *e); + virtual void lfree(); + virtual PCCTS_AST *to_ast(SList list); + virtual void require(int e,char *err){ if ( !e ) panic(err); } + virtual void panic(char *err){ /* MR23 */ printMessage(stderr, "SList panic: %s\n", err); exit(PCCTS_EXIT_FAILURE); } + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 +}; + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/antlr.h b/Tools/Source/TianoTools/Pccts/h/antlr.h new file mode 100644 index 0000000000..80664535d3 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/antlr.h @@ -0,0 +1,807 @@ +/* antlr.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ANTLR_H +#define ANTLR_H + +#include "pcctscfg.h" + +#include "pccts_stdio.h" + +/* turn off warnings for unreferenced labels */ + +#ifdef _MSC_VER +#pragma warning(disable:4102) +#endif + +/* + * Define all of the stack setup and manipulation of $i, #i variables. + * + * Notes: + * The type 'Attrib' must be defined before entry into this .h file. + */ + + +#ifdef __USE_PROTOS +#include "pccts_stdlib.h" +#else +#ifdef VAXC +#include +#else +#include +#endif +#endif +#include "pccts_string.h" + +#if 0 +#include "set.h" +#endif + + +typedef int ANTLRTokenType; +typedef unsigned char SetWordType; + +typedef char ANTLRChar; + + /* G u e s s S t u f f */ + +#ifdef ZZCAN_GUESS +#ifndef ZZINF_LOOK +#define ZZINF_LOOK +#endif +#endif + +#ifdef ZZCAN_GUESS +typedef struct _zzjmp_buf { + jmp_buf state; + } zzjmp_buf; +#endif + + +/* can make this a power of 2 for more efficient lookup */ + +#ifndef ZZLEXBUFSIZE +#define ZZLEXBUFSIZE 8000 /* MR22 raise from 2k to 8k */ +#endif + +#define zzOvfChk \ + if ( zzasp <= 0 ) \ + { \ + fprintf(stderr, zzStackOvfMsg, __FILE__, __LINE__); \ + exit(PCCTS_EXIT_FAILURE); \ + } + +#ifndef ZZA_STACKSIZE +#define ZZA_STACKSIZE 400 +#endif +#ifndef ZZAST_STACKSIZE +#define ZZAST_STACKSIZE 400 +#endif + +#ifndef zzfailed_pred +#ifdef ZZCAN_GUESS +#define zzfailed_pred(_p,_hasuseraction,_useraction) \ + if (zzguessing) { \ + zzGUESS_FAIL; \ + } else { \ + zzfailed_pred_action(_p,_hasuseraction,_useraction); \ + } +#else +#define zzfailed_pred(_p,_hasuseraction,_useraction) \ + zzfailed_pred_action(_p,_hasuseraction,_useraction); +#endif +#endif + +/* MR23 Provide more control over failed predicate action + without any need for user to worry about guessing internals. + _hasuseraction == 0 => no user specified error action + _hasuseraction == 1 => user specified error action +*/ + +#ifndef zzfailed_pred_action +#define zzfailed_pred_action(_p,_hasuseraction,_useraction) \ + if (_hasuseraction) { _useraction } \ + else { fprintf(stderr, "semantic error; failed predicate: '%s'\n",_p); } +#endif + +/* MR19 zzchar_t additions */ + +#ifdef LL_K +#define LOOKAHEAD \ + int zztokenLA[LL_K]; \ + zzchar_t zztextLA[LL_K][ZZLEXBUFSIZE]; \ + int zzlap = 0, zzlabase=0; /* labase only used for DEMAND_LOOK */ +#else +#define LOOKAHEAD \ + int zztoken; +#endif + +#ifndef zzcr_ast +#define zzcr_ast(ast,attr,tok,text) +#endif + +#ifdef DEMAND_LOOK +#define DemandLookData int zzdirty=1; +#else +#define DemandLookData +#endif + +#ifndef zzUSER_GUESS_HOOK +#define zzUSER_GUESS_HOOK(seqFrozen,zzrv) +#endif + +#ifndef zzUSER_GUESS_DONE_HOOK +#define zzUSER_GUESS_DONE_HOOK(seqFrozen) +#endif + + /* S t a t e S t u f f */ + +#ifdef ZZCAN_GUESS +#define zzGUESS_BLOCK zzantlr_state zzst; int zzrv; int zzGuessSeqFrozen; + +/* MR10 change zzGUESS: do zzGUESS_DONE when zzrv==1 after longjmp as in C++ mode */ + +#define zzGUESS zzsave_antlr_state(&zzst); \ + zzguessing = 1; \ + zzGuessSeqFrozen=++zzGuessSeq; \ + zzrv = setjmp(zzguess_start.state); \ + zzUSER_GUESS_HOOK(zzGuessSeqFrozen,zzrv) \ + if (zzrv) zzGUESS_DONE; +#ifdef zzTRACE_RULES +#define zzGUESS_FAIL { zzTraceGuessFail(); longjmp(zzguess_start.state, 1); } +#else +#define zzGUESS_FAIL longjmp(zzguess_start.state, 1) +#endif + +/* MR10 change zzGUESS_DONE: zzrv=1 to simulate longjmp() return value as in C++ mode */ + +#define zzGUESS_DONE { zzrestore_antlr_state(&zzst); zzrv=1; zzUSER_GUESS_DONE_HOOK(zzGuessSeqFrozen) } +#define zzNON_GUESS_MODE if ( !zzguessing ) +#define zzGuessData \ + zzjmp_buf zzguess_start; \ + int zzguessing; +#else +#define zzGUESS_BLOCK +#define zzGUESS +#define zzGUESS_FAIL +#define zzGUESS_DONE +#define zzNON_GUESS_MODE +#define zzGuessData +#endif + +typedef struct _zzantlr_state { +#ifdef ZZCAN_GUESS + zzjmp_buf guess_start; + int guessing; +#endif + int asp; + int ast_sp; +#ifdef ZZINF_LOOK + int inf_lap; /* not sure we need to save this one */ + int inf_labase; + int inf_last; + +/* MR6 Gunnar Rxnning (gunnar@candleweb.no) */ +/* MR6 Additional state needs to be saved/restored */ +/* MR6 Matching changes in err.h */ + + int *inf_tokens; /* MR6 */ + char **inf_text; /* MR6 */ + char *inf_text_buffer; /* MR6 */ + int *inf_line; /* MR6 */ +#endif +#ifdef DEMAND_LOOK + int dirty; +#endif + +#ifdef LL_K + int tokenLA[LL_K]; + char textLA[LL_K][ZZLEXBUFSIZE]; + int lap; + int labase; +#else + int token; + char text[ZZLEXBUFSIZE]; +#endif +#ifdef zzTRACE_RULES + int traceOptionValue; /* MR10 */ + int traceGuessOptionValue; /* MR10 */ + char *traceCurrentRuleName; /* MR10 */ + int traceDepth; /* MR10 */ +#endif + + } zzantlr_state; + +#ifdef zzTRACE_RULES +extern int zzTraceOptionValueDefault; +extern int zzTraceOptionValue; +extern int zzTraceGuessOptionValue; +extern char *zzTraceCurrentRuleName; +extern int zzTraceDepth; +#endif + +extern int zzGuessSeq; /* MR10 */ +extern int zzSyntaxErrCount; /* MR11 */ +extern int zzLexErrCount; /* MR11 */ + + /* I n f i n i t e L o o k a h e a d */ + + +#ifdef ZZINF_LOOK +#define InfLookData \ + int *zzinf_tokens; \ + char **zzinf_text; \ + char *zzinf_text_buffer; \ + int *zzinf_line; \ + int zzinf_labase; \ + int zzinf_last; +#else +#define InfLookData +#endif + +#ifdef ZZINF_LOOK + +#ifndef ZZINF_DEF_TEXT_BUFFER_SIZE +#define ZZINF_DEF_TEXT_BUFFER_SIZE 20000 +#endif +#ifndef ZZINF_DEF_TOKEN_BUFFER_SIZE +#define ZZINF_DEF_TOKEN_BUFFER_SIZE 2000 +#endif +/* WARNING!!!!!! + * ZZINF_BUFFER_TEXT_CHUNK_SIZE must be > sizeof(text) largest possible token. + */ +#ifndef ZZINF_BUFFER_TEXT_CHUNK_SIZE +#define ZZINF_BUFFER_TEXT_CHUNK_SIZE 5000 +#endif +#ifndef ZZINF_BUFFER_TOKEN_CHUNK_SIZE +#define ZZINF_BUFFER_TOKEN_CHUNK_SIZE 1000 +#endif + +#if ZZLEXBUFSIZE > ZZINF_BUFFER_TEXT_CHUNK_SIZE +#define ZZINF_BUFFER_TEXT_CHUNK_SIZE ZZLEXBUFSIZE+5 +#endif + +/* make inf_look user-access macros */ +#ifdef LL_K +#define ZZINF_LA_VALID(i) (((zzinf_labase+i-1)-LL_K+1) <= zzinf_last) +#define ZZINF_LA(i) zzinf_tokens[(zzinf_labase+i-1)-LL_K+1] +#define ZZINF_LATEXT(i) zzinf_text[(zzinf_labase+i-1)-LL_K+1] +/* MR6 In 1.33 vanilla the #define ZZINF_LINE(i) is was commented out */ +#define ZZINF_LINE(i) zzinf_line[(zzinf_labase+i-1)-LL_K+1] +#else +#define ZZINF_LA_VALID(i) (((zzinf_labase+i-1)) <= zzinf_last) +#define ZZINF_LA(i) zzinf_tokens[(zzinf_labase+i-1)] +#define ZZINF_LATEXT(i) zzinf_text[(zzinf_labase+i-1)] +#endif + +#define inf_zzgettok _inf_zzgettok() +extern void _inf_zzgettok(); + +#endif /* ZZINF_LOOK */ + + +#ifdef LL_K + +#ifdef __USE_PROTOS +#define ANTLR_INFO \ + Attrib zzempty_attr(void) {static Attrib a; return a;} \ + Attrib zzconstr_attr(int _tok, char *_text) \ + {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ + int zzasp=ZZA_STACKSIZE; \ + char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ + Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \ + InfLookData \ + zzGuessData +#else +#define ANTLR_INFO \ + Attrib zzempty_attr() {static Attrib a; return a;} \ + Attrib zzconstr_attr(_tok, _text) int _tok; char *_text; \ + {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ + int zzasp=ZZA_STACKSIZE; \ + char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ + Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \ + InfLookData \ + zzGuessData +#endif + +#else + +#ifdef __USE_PROTOS +#define ANTLR_INFO \ + Attrib zzempty_attr(void) {static Attrib a; return a;} \ + Attrib zzconstr_attr(int _tok, char *_text) \ + {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ + int zzasp=ZZA_STACKSIZE; \ + char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ + Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \ + InfLookData \ + zzGuessData +#else +#define ANTLR_INFO \ + Attrib zzempty_attr() {static Attrib a; return a;} \ + Attrib zzconstr_attr(_tok, _text) int _tok; char *_text; \ + {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ + int zzasp=ZZA_STACKSIZE; \ + char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ + Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \ + InfLookData \ + zzGuessData +#endif + +#endif /* LL_k */ + + +#ifdef ZZINF_LOOK + +#ifdef LL_K +#ifdef DEMAND_LOOK +#define zzPrimeLookAhead {zzdirty=LL_K; zzlap = zzlabase = 0;} +#else +#define zzPrimeLookAhead {zzlap = zzlabase = 0; zzfill_inf_look();\ + {int _i; for(_i=1;_i<=LL_K; _i++) \ + {zzCONSUME;} zzlap = zzlabase = 0;}} +#endif + +#else /* LL_K */ + +#ifdef DEMAND_LOOK +#define zzPrimeLookAhead zzfill_inf_look(); zzdirty=1 +#else +#define zzPrimeLookAhead zzfill_inf_look(); inf_zzgettok + +#endif +#endif /* LL_K */ + +#else /* ZZINF_LOOK */ + +#ifdef LL_K +#ifdef DEMAND_LOOK +#define zzPrimeLookAhead {zzdirty=LL_K; zzlap = zzlabase = 0;} +#else +#define zzPrimeLookAhead {int _i; zzlap = 0; for(_i=1;_i<=LL_K; _i++) \ + {zzCONSUME;} zzlap = 0;} +#endif + +#else + +#ifdef DEMAND_LOOK +#define zzPrimeLookAhead zzdirty=1 +#else +#define zzPrimeLookAhead zzgettok() +#endif +#endif /* LL_K */ + +#endif /* ZZINF_LOOK */ + + +#ifdef LL_K +#define zzenterANTLRs(s) \ + zzlextext = &(zztextLA[0][0]); zzrdstr( s ); zzPrimeLookAhead; +#define zzenterANTLRf(f) \ + zzlextext = &(zztextLA[0][0]); zzrdfunc( f ); zzPrimeLookAhead; +#define zzenterANTLR(f) \ + zzlextext = &(zztextLA[0][0]); zzrdstream( f ); zzPrimeLookAhead; +#ifdef ZZINF_LOOK +#define zzleaveANTLR(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#define zzleaveANTLRf(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#define zzleaveANTLRs(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#else +#define zzleaveANTLR(f) +#define zzleaveANTLRf(f) +#define zzleaveANTLRs(f) +#endif + +#else + +#define zzenterANTLRs(s) \ + {static char zztoktext[ZZLEXBUFSIZE]; \ + zzlextext = zztoktext; zzrdstr( s ); zzPrimeLookAhead;} +#define zzenterANTLRf(f) \ + {static char zztoktext[ZZLEXBUFSIZE]; \ + zzlextext = zztoktext; zzrdfunc( f ); zzPrimeLookAhead;} +#define zzenterANTLR(f) \ + {static char zztoktext[ZZLEXBUFSIZE]; \ + zzlextext = zztoktext; zzrdstream( f ); zzPrimeLookAhead;} +#ifdef ZZINF_LOOK +#define zzleaveANTLR(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#define zzleaveANTLRf(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#define zzleaveANTLRs(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#else +#define zzleaveANTLR(f) +#define zzleaveANTLRf(f) +#define zzleaveANTLRs(f) +#endif + +#endif + +/* MR19 Paul D. Smith (psmith@baynetworks.com) + Need to adjust AST stack pointer at exit. + Referenced in ANTLRx macros. +*/ + +#ifdef GENAST +#define ZZAST_ADJUST ++zzast_sp; +#else +#define ZZAST_ADJUST +#endif + +#define ANTLR(st, f) zzbufsize = ZZLEXBUFSIZE; \ + zzenterANTLR(f); \ + { \ + zzBLOCK(zztasp1); \ + st; /* ++zzasp; Removed MR20 G. Hobbelt */ \ + /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \ + /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \ + zzEXIT_ANTLR(zztasp1 + 1); \ + } \ + zzleaveANTLR(f); + +#define ANTLRm(st, f, _m) zzbufsize = ZZLEXBUFSIZE; \ + zzmode(_m); \ + zzenterANTLR(f); \ + { \ + zzBLOCK(zztasp1); \ + st; /* ++zzasp; Removed MR20 G. Hobbelt */ \ + /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \ + /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \ + zzEXIT_ANTLR(zztasp1 + 1); \ + } \ + zzleaveANTLR(f); + +#define ANTLRf(st, f) zzbufsize = ZZLEXBUFSIZE; \ + zzenterANTLRf(f); \ + { \ + zzBLOCK(zztasp1); \ + st; /* ++zzasp; Removed MR20 G. Hobbelt */ \ + /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \ + /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \ + zzEXIT_ANTLR(zztasp1 + 1); \ + } \ + zzleaveANTLRf(f); + +#define ANTLRs(st, s) zzbufsize = ZZLEXBUFSIZE; \ + zzenterANTLRs(s); \ + { \ + zzBLOCK(zztasp1); \ + st; /* ++zzasp; Removed MR20 G. Hobbelt */ \ + /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \ + /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \ + zzEXIT_ANTLR(zztasp1 + 1); \ + } \ + zzleaveANTLRs(s); + +#ifdef LL_K +#define zztext (&(zztextLA[zzlap][0])) +#else +#define zztext zzlextext +#endif + + + /* A r g u m e n t A c c e s s */ + +#define zzaCur (zzaStack[zzasp]) +#define zzaRet (*zzaRetPtr) +#define zzaArg(v,n) zzaStack[v-n] +#define zzMakeAttr { zzNON_GUESS_MODE {zzOvfChk; --zzasp; zzcr_attr(&(zzaStack[zzasp]),LA(1),LATEXT(1));}} +#ifdef zzdef0 +#define zzMake0 { zzOvfChk; --zzasp; zzdef0(&(zzaStack[zzasp]));} +#else +#define zzMake0 { zzOvfChk; --zzasp;} +#endif +#define zzaPush(_v) { zzOvfChk; zzaStack[--zzasp] = _v;} +#ifndef zzd_attr +#define zzREL(t) zzasp=(t); /* Restore state of stack */ +#else +#define zzREL(t) for (; zzasp<(t); zzasp++) \ + { zzd_attr(&(zzaStack[zzasp])); } +#endif + + +#define zzsetmatch(_es,_tokclassErrset) \ + if ( !_zzsetmatch(_es, &zzBadText, &zzMissText, &zzMissTok, &zzBadTok, &zzMissSet, _tokclassErrset) ) goto fail; /* MR23 */ + +#ifdef ZZCAN_GUESS +#define zzsetmatch_wsig(_es, handler) \ + if ( !_zzsetmatch_wsig(_es) ) if (zzguessing) { zzGUESS_FAIL; } else {_signal=MismatchedToken; goto handler;} +#else +#define zzsetmatch_wsig(_es, handler) \ + if ( !_zzsetmatch_wsig(_es) ) {_signal=MismatchedToken; goto handler;} +#endif + +#ifdef __USE_PROTOS +extern int _zzsetmatch(SetWordType *, char **, char **, int *, int *, SetWordType **, SetWordType * /* MR23 */); +extern int _zzsetmatch_wsig(SetWordType *); +#else +extern int _zzsetmatch(); +extern int _zzsetmatch_wsig(); +#endif + +#define zzmatch(_t) \ + if ( !_zzmatch(_t, &zzBadText, &zzMissText, &zzMissTok, &zzBadTok, &zzMissSet) ) goto fail; + +#ifdef ZZCAN_GUESS +#define zzmatch_wsig(_t,handler) \ + if ( !_zzmatch_wsig(_t) ) if (zzguessing) { zzGUESS_FAIL; } else {_signal=MismatchedToken; goto handler;} +#else +#define zzmatch_wsig(_t,handler) \ + if ( !_zzmatch_wsig(_t) ) {_signal=MismatchedToken; goto handler;} +#endif + +#ifdef __USE_PROTOS +extern int _zzmatch(int, char **, char **, int *, int *, SetWordType **); +extern int _zzmatch_wsig(int); +#else +extern int _zzmatch(); +extern int _zzmatch_wsig(); +#endif + +#define zzmatch_wdfltsig(_t,_f) \ + if ( !_zzmatch_wdfltsig(_t,_f) ) _signal=MismatchedToken; +#define zzsetmatch_wdfltsig(tw,tt,wf) \ + if ( !_zzsetmatch_wdfltsig(tw,tt,wf) ) _signal=MismatchedToken; + +#ifdef __USE_PROTOS +extern int _zzmatch_wdfltsig(int, SetWordType *); +extern int _zzsetmatch_wdfltsig(SetWordType *tokensWanted, + int tokenTypeOfSet, + SetWordType *whatFollows); +#else +extern int _zzmatch_wdfltsig(); +extern int _zzsetmatch_wdfltsig(); +#endif + +#ifdef GENAST +#define zzRULE Attrib *zzaRetPtr = &(zzaStack[zzasp-1]); \ + SetWordType *zzMissSet=NULL; int zzMissTok=0; \ + int zzBadTok=0; char *zzBadText=""; \ + int zzErrk=1,zzpf=0; \ + zzTRACEdata \ + char *zzMissText=""; zzASTVars +#else +#define zzRULE Attrib *zzaRetPtr = &(zzaStack[zzasp-1]); \ + int zzBadTok=0; char *zzBadText=""; \ + int zzErrk=1,zzpf=0; \ + zzTRACEdata \ + SetWordType *zzMissSet=NULL; int zzMissTok=0; char *zzMissText="" +#endif + +#ifdef GENAST +#define zzBLOCK(i) int i = zzasp - 1; int zztsp = zzast_sp +#define zzEXIT(i) zzREL(i); zzastREL; zzNON_GUESS_MODE { zzastPush(*_root); } +#define zzEXIT_ANTLR(i) zzREL(i); zzastREL /* [i_a] added as we want this for the ANTLRx() macros */ +#define zzLOOP(i) zzREL(i); zzastREL +#else +#define zzBLOCK(i) int i = zzasp - 1 +#define zzEXIT(i) zzREL(i) +#define zzEXIT_ANTLR(i) zzREL(i) /* [i_a] added as we want this for the ANTLRx() macros */ +#define zzLOOP(i) zzREL(i) +#endif + +#ifdef LL_K + +#ifdef DEMAND_LOOK +#define LOOK(_k) {int i,stop=_k-(LL_K-zzdirty); for (i=1; i<=stop; i++) \ + zzCONSUME;} +#define zzCONSUME {zzgettok(); zzdirty--; \ + zzlap = (zzlap+1)&(LL_K-1); \ + zzlextext = &(zztextLA[zzlap][0]);} +#else +#ifdef ZZINF_LOOK +#define zzCONSUME {inf_zzgettok; \ + zzlap = (zzlap+1)&(LL_K-1); \ + zzlextext = &(zztextLA[zzlap][0]); \ + } +#else +#define zzCONSUME {zzgettok(); \ + zzlap = (zzlap+1)&(LL_K-1); \ + zzlextext = &(zztextLA[zzlap][0]);} +#endif /* ZZINF_LOOK */ +#endif /* DEMAND_LOOK */ + +#else /* LL_K */ + +#ifdef DEMAND_LOOK +#define LOOK(_k) if ( zzdirty) zzCONSUME; +#ifdef ZZINF_LOOK +#define zzCONSUME inf_zzgettok; zzdirty=0; +#else +#define zzCONSUME zzgettok(); zzdirty=0; +#endif /* ZZINF_LOOK */ + +#else /* DEMAND_LOOK */ + +#ifdef ZZINF_LOOK +#define zzCONSUME inf_zzgettok +#else +#define zzCONSUME zzgettok(); +#endif + +#endif /* DEMAND_LOOK */ + +#endif /* LL_K */ + +#ifdef LL_K +#define NLA zztokenLA[zzlap&(LL_K-1)] /* --> next LA */ +#define NLATEXT zztextLA[zzlap&(LL_K-1)] /* --> next text of LA */ +#ifdef DEMAND_LOOK +#define LA(i) zztokenLA[(zzlabase+(i)-1)&(LL_K-1)] +#define LATEXT(i) (&(zztextLA[(zzlabase+(i)-1)&(LL_K-1)][0])) +#else +#define LA(i) zztokenLA[(zzlap+(i)-1)&(LL_K-1)] +#define LATEXT(i) (&(zztextLA[(zzlap+(i)-1)&(LL_K-1)][0])) +#endif +#else +#define NLA zztoken +#define NLATEXT zztext +#define LA(i) zztoken +#define LATEXT(i) zztext +#endif + + + /* S t a n d a r d S i g n a l s */ + +#define NoSignal 0 +#define MismatchedToken 1 +#define NoViableAlt 2 +#define NoSemViableAlt 3 + +/* MR7 Allow more control over signalling */ +/* by adding "Unwind" and "zzsetSignal" */ + +#define Unwind 4 +#define zzsetSignal(newValue) *_retsignal=_signal=(newValue) +#define zzsuppressSignal *_retsignal=_signal=0 +#define zzexportSignal *_retsignal=_signal + + /* F u n c t i o n T r a c i n g */ + +#ifndef zzTRACE_RULES +#define zzTRACEdata +#else +#ifndef zzTRACEdata +#define zzTRACEdata ANTLRChar *zzTracePrevRuleName = NULL; +#endif +#endif + +#ifndef zzTRACEIN +#define zzTRACEIN(r) zzTracePrevRuleName=zzTraceCurrentRuleName;zzTraceIn(r); +#endif +#ifndef zzTRACEOUT +#define zzTRACEOUT(r) zzTraceOut(r);zzTraceCurrentRuleName=zzTracePrevRuleName; +#endif + +/* MR19 zzchar_t additions */ + +#ifndef zzchar_t +#ifdef ZZWCHAR_T +#define zzchar_t wchar_t +#else +#define zzchar_t char +#endif +#endif + + +/* MR26 */ + +#ifdef PCCTS_USE_STDARG +extern void zzFAIL(int k, ...); +#else +extern void zzFAIL(); +#endif + /* E x t e r n D e f s */ + +#ifdef __USE_PROTOS +extern Attrib zzempty_attr(void); +extern Attrib zzconstr_attr(int, char *); +extern void zzsyn(char *, int, char *, SetWordType *, int, int, char *); +extern int zzset_el(unsigned, SetWordType *); +extern int zzset_deg(SetWordType *); +extern void zzedecode(SetWordType *); + +extern void zzresynch(SetWordType *, SetWordType); +extern void zzsave_antlr_state(zzantlr_state *); +extern void zzrestore_antlr_state(zzantlr_state *); +extern void zzfill_inf_look(void); +extern void zzconsumeUntil(SetWordType *st); /* MR7 */ +extern void zzconsumeUntilToken(int t); /* MR7 */ +extern void zzTraceIn(char * ruleName); /* MR10 */ +extern void zzTraceOut(char * ruleName); /* MR10 */ +extern int zzTraceOption(int delta); /* MR10 */ +extern int zzTraceGuessOption(int delta); /* MR10 */ +extern void zzTraceReset(void); /* MR10 */ +extern void zzTraceGuessFail(void); /* MR10 */ +#ifdef EXCEPTION_HANDLING +extern void zzdflthandlers(int, int *); +#endif +#else +extern Attrib zzempty_attr(); +extern Attrib zzconstr_attr(); +extern void zzsyn(); +extern int zzset_el(); +extern int zzset_deg(); +extern void zzedecode(); +extern void zzresynch(); +extern void zzsave_antlr_state(); +extern void zzrestore_antlr_state(); +extern void zzfill_inf_look(); +extern void zzconsumeUntil(); /* MR7 */ +extern void zzconsumeUntilToken(); /* MR7 */ +extern void zzTraceIn(); /* MR10 */ +extern void zzTraceOut(); /* MR10 */ +extern int zzTraceOption(); /* MR10 */ +extern int zzTraceGuessOption(); /* MR10 */ +extern void zzTraceReset(); /* MR10 */ +extern void zzTraceGuessFail(); /* MR10 */ +#ifdef EXCEPTION_HANDLING +extern void zzdflthandlers(); +#endif +#endif + + /* G l o b a l V a r i a b l e s */ + +/* Define a parser; user should do a "#parser myname" in their grammar file */ +/*extern struct pccts_parser zzparser;*/ + +extern char *zztokens[]; +#ifdef LL_K +extern int zztokenLA[]; +extern zzchar_t zztextLA[][ZZLEXBUFSIZE]; +extern int zzlap; +extern int zzlabase; +#else +extern int zztoken; +#endif + +extern char zzStackOvfMsg[]; +extern int zzasp; +extern Attrib zzaStack[]; +#ifdef ZZINF_LOOK +extern int *zzinf_tokens; +extern char **zzinf_text; +extern char *zzinf_text_buffer; +extern int *zzinf_line; +extern int zzinf_labase; +extern int zzinf_last; +#endif +#ifdef DEMAND_LOOK +extern int zzdirty; +#endif +#ifdef ZZCAN_GUESS +extern int zzguessing; +extern zzjmp_buf zzguess_start; +#endif + +/* Define global veriables that refer to values exported by the scanner. + * These declarations duplicate those in dlgdef.h, but are needed + * if ANTLR is not to generate a .dlg file (-gx); PS, this is a hack. + */ +extern zzchar_t *zzlextext; /* text of most recently matched token */ +extern int zzbufsize; /* how long zzlextext is */ + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/ast.c b/Tools/Source/TianoTools/Pccts/h/ast.c new file mode 100644 index 0000000000..9326ae16ae --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/ast.c @@ -0,0 +1,345 @@ +/* Abstract syntax tree manipulation functions + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +#ifdef PCCTS_USE_STDARG +#include "pccts_stdarg.h" +#else +#include +#endif + +/* ensure that tree manipulation variables are current after a rule + * reference + */ + +void +#ifdef __USE_PROTOS +zzlink(AST **_root, AST **_sibling, AST **_tail) +#else +zzlink(_root, _sibling, _tail) +AST **_root, **_sibling, **_tail; +#endif +{ + if ( *_sibling == NULL ) return; + if ( *_root == NULL ) *_root = *_sibling; + else if ( *_root != *_sibling ) (*_root)->down = *_sibling; + if ( *_tail==NULL ) *_tail = *_sibling; + while ( (*_tail)->right != NULL ) *_tail = (*_tail)->right; +} + +AST * +#ifdef __USE_PROTOS +zzastnew(void) +#else +zzastnew() +#endif +{ + AST *p = (AST *) calloc(1, sizeof(AST)); + if ( p == NULL ) fprintf(stderr,"%s(%d): cannot allocate AST node\n",__FILE__,__LINE__); + return p; +} + +/* add a child node to the current sibling list */ +void +#ifdef __USE_PROTOS +zzsubchild(AST **_root, AST **_sibling, AST **_tail) +#else +zzsubchild(_root, _sibling, _tail) +AST **_root, **_sibling, **_tail; +#endif +{ + AST *n; + zzNON_GUESS_MODE { + n = zzastnew(); +#ifdef DEMAND_LOOK + zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0)); +#else + zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1)); +#endif + zzastPush( n ); + if ( *_tail != NULL ) (*_tail)->right = n; + else { + *_sibling = n; + if ( *_root != NULL ) (*_root)->down = *_sibling; + } + *_tail = n; + if ( *_root == NULL ) *_root = *_sibling; + } +} + +/* make a new AST node. Make the newly-created + * node the root for the current sibling list. If a root node already + * exists, make the newly-created node the root of the current root. + */ +void +#ifdef __USE_PROTOS +zzsubroot(AST **_root, AST **_sibling, AST **_tail) +#else +zzsubroot(_root, _sibling, _tail) +AST **_root, **_sibling, **_tail; +#endif +{ + AST *n; + zzNON_GUESS_MODE { + n = zzastnew(); +#ifdef DEMAND_LOOK + zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0)); +#else + zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1)); +#endif + zzastPush( n ); + if ( *_root != NULL ) + if ( (*_root)->down == *_sibling ) *_sibling = *_tail = *_root; + *_root = n; + (*_root)->down = *_sibling; + } +} + +/* Apply function to root then each sibling + * example: print tree in child-sibling LISP-format (AST has token field) + * + * void show(tree) + * AST *tree; + * { + * if ( tree == NULL ) return; + * printf(" %s", zztokens[tree->token]); + * } + * + * void before() { printf(" ("); } + * void after() { printf(" )"); } + * + * LISPdump() { zzpre_ast(tree, show, before, after); } + * + */ +void +#ifdef __USE_PROTOS +zzpre_ast( + AST *tree, + void (*func)(AST *), /* apply this to each tree node */ + void (*before)(AST *), /* apply this to root of subtree before preordering it */ + void (*after)(AST *)) /* apply this to root of subtree after preordering it */ +#else +zzpre_ast(tree, func, before, after) +AST *tree; +void (*func)(), /* apply this to each tree node */ + (*before)(), /* apply this to root of subtree before preordering it */ + (*after)(); /* apply this to root of subtree after preordering it */ +#endif +{ + while ( tree!= NULL ) + { + if ( tree->down != NULL ) (*before)(tree); + (*func)(tree); + zzpre_ast(tree->down, func, before, after); + if ( tree->down != NULL ) (*after)(tree); + tree = tree->right; + } +} + +/* free all AST nodes in tree; apply func to each before freeing */ + +#if 0 +////void +////#ifdef __USE_PROTOS +////zzfree_ast(AST *tree) +////#else +////zzfree_ast(tree) +////AST *tree; +////#endif +////{ +//// if ( tree == NULL ) return; +//// zzfree_ast( tree->down ); +//// zzfree_ast( tree->right ); +//// zztfree( tree ); +////} +#endif + +/* + MR19 Optimize freeing of the following structure to limit recursion + SAKAI Kiyotaka (ksakai@isr.co.jp) +*/ + +/* + NULL o + / \ + NULL o + / \ + NULL NULL +*/ + +/* + MR21 Another refinement to replace recursion with iteration + NAKAJIMA Mutsuki (muc@isr.co.jp). +*/ + +void +#ifdef __USE_PROTOS +zzfree_ast(AST *tree) +#else +zzfree_ast(tree) +AST *tree; +#endif +{ + + AST *otree; + + if (tree == NULL) return; + + while (tree->down == NULL || tree->right == NULL) { + + if (tree->down == NULL && tree->right == NULL) { + zztfree(tree); + return; + } + + otree = tree; + if (tree->down == NULL) { + tree = tree->right; + } else { + tree = tree->down; + } + zztfree( otree ); + } + + while (tree != NULL) { + zzfree_ast(tree->down); + otree = tree; + tree = otree->right; + zztfree(otree); + } +} + +/* build a tree (root child1 child2 ... NULL) + * If root is NULL, simply make the children siblings and return ptr + * to 1st sibling (child1). If root is not single node, return NULL. + * + * Siblings that are actually siblins lists themselves are handled + * correctly. For example #( NULL, #( NULL, A, B, C), D) results + * in the tree ( NULL A B C D ). + * + * Requires at least two parameters with the last one being NULL. If + * both are NULL, return NULL. + */ +#ifdef PCCTS_USE_STDARG +AST *zztmake(AST *rt, ...) +#else +AST *zztmake(va_alist) +va_dcl +#endif +{ + va_list ap; + register AST *child, *sibling=NULL, *tail=NULL /* MR20 */, *w; + AST *root; + +#ifdef PCCTS_USE_STDARG + va_start(ap, rt); + root = rt; +#else + va_start(ap); + root = va_arg(ap, AST *); +#endif + + if ( root != NULL ) + if ( root->down != NULL ) return NULL; + child = va_arg(ap, AST *); + while ( child != NULL ) + { + for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */ + if ( sibling == NULL ) {sibling = child; tail = w;} + else {tail->right = child; tail = w;} + child = va_arg(ap, AST *); + } + if ( root==NULL ) root = sibling; + else root->down = sibling; + va_end(ap); + return root; +} + +/* tree duplicate */ +AST * +#ifdef __USE_PROTOS +zzdup_ast(AST *t) +#else +zzdup_ast(t) +AST *t; +#endif +{ + AST *u; + + if ( t == NULL ) return NULL; + u = zzastnew(); + *u = *t; +#ifdef zzAST_DOUBLE + u->up = NULL; /* set by calling invocation */ + u->left = NULL; +#endif + u->right = zzdup_ast(t->right); + u->down = zzdup_ast(t->down); +#ifdef zzAST_DOUBLE + if ( u->right!=NULL ) u->right->left = u; + if ( u->down!=NULL ) u->down->up = u; +#endif + return u; +} + +void +#ifdef __USE_PROTOS +zztfree(AST *t) +#else +zztfree(t) +AST *t; +#endif +{ +#ifdef zzd_ast + zzd_ast( t ); +#endif + free( t ); +} + +#ifdef zzAST_DOUBLE +/* + * Set the 'up', and 'left' pointers of all nodes in 't'. + * Initial call is double_link(your_tree, NULL, NULL). + */ +void +#ifdef __USE_PROTOS +zzdouble_link(AST *t, AST *left, AST *up) +#else +zzdouble_link(t, left, up) +AST *t, *left, *up; +#endif +{ + if ( t==NULL ) return; + t->left = left; + t->up = up; + zzdouble_link(t->down, NULL, t); + zzdouble_link(t->right, t, up); +} +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/ast.h b/Tools/Source/TianoTools/Pccts/h/ast.h new file mode 100644 index 0000000000..5ff84bd76c --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/ast.h @@ -0,0 +1,121 @@ +/* Abstract syntax tree + * + * Macros, definitions + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ZZAST_H +#define ZZAST_H + +#define zzastOvfChk \ + if ( zzast_sp <= 0 ) \ + { \ + fprintf(stderr, zzStackOvfMsg, __FILE__, __LINE__); \ + exit(PCCTS_EXIT_FAILURE); \ + } + +#ifndef USER_DEFINED_AST +#ifndef AST_FIELDS +#define AST_FIELDS +#endif + +typedef struct _ast { + struct _ast *right, *down; +#ifdef zzAST_DOUBLE + struct _ast *left, *up; +#endif + AST_FIELDS +} AST; + +#else + +#ifdef zzAST_DOUBLE +#define AST_REQUIRED_FIELDS struct _ast *right, *down, *left, *up; +#else +#define AST_REQUIRED_FIELDS struct _ast *right, *down; +#endif + +#endif + + +/* N o d e a c c e s s m a c r o s */ +#define zzchild(t) (((t)==NULL)? (AST *) NULL:(t->down)) /* MR19 */ +#define zzsibling(t) (((t)==NULL)? (AST *) NULL:(t->right)) /* MR19 */ + + +/* define global variables needed by #i stack */ +#define zzASTgvars \ + AST *zzastStack[ZZAST_STACKSIZE]; \ + int zzast_sp = ZZAST_STACKSIZE; + +#define zzASTVars AST *_ast = NULL, *_sibling = NULL, *_tail = NULL +#define zzSTR ( (_tail==NULL)?(&_sibling):(&(_tail->right)) ) +#define zzastCur (zzastStack[zzast_sp]) +#define zzastArg(i) (zzastStack[zztsp-i]) +#define zzastPush(p) zzastOvfChk; zzastStack[--zzast_sp] = p; +#define zzastDPush --zzast_sp +#define zzastMARK zztsp=zzast_sp; /* Save state of stack */ +#define zzastREL zzast_sp=zztsp; /* Return state of stack */ +#define zzrm_ast {zzfree_ast(*_root); _tail = _sibling = (*_root)=NULL;} + +extern int zzast_sp; +extern AST *zzastStack[]; + +/* MR26 */ + +#ifdef PCCTS_USE_STDARG +AST *zztmake(AST *, ...); +#else +AST *zztmake(); +#endif + +#ifdef __USE_PROTOS +void zzlink(AST **, AST **, AST **); +void zzsubchild(AST **, AST **, AST **); +void zzsubroot(AST **, AST **, AST **); +void zzpre_ast(AST *, void (*)(AST *), void (*)(AST *), void (*)(AST *)); +void zzfree_ast(AST *); +AST *zzdup_ast(AST *); +void zztfree(AST *); +void zzdouble_link(AST *, AST *, AST *); +AST *zzastnew(void); + +#else + +void zzlink(); +AST *zzastnew(); +void zzsubchild(); +void zzsubroot(); +void zzpre_ast(); +void zzfree_ast(); +AST *zzdup_ast(); +void zztfree(); +void zzdouble_link(); +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/charbuf.h b/Tools/Source/TianoTools/Pccts/h/charbuf.h new file mode 100644 index 0000000000..5f01c8ba35 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/charbuf.h @@ -0,0 +1,46 @@ +/* ANTLR attribute definition -- constant width text + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ZZCHARBUF_H +#define ZZCHARBUF_H + +#include "pcctscfg.h" + +#include "pccts_string.h" + +#ifndef D_TextSize +#define D_TextSize 30 +#endif + +typedef struct { char text[D_TextSize]; } Attrib; + +#define zzcr_attr(a,tok,t) strncpy((a)->text, t, D_TextSize-1); \ + (a)->text[D_TextSize-1] = '\0'; + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/charptr.c b/Tools/Source/TianoTools/Pccts/h/charptr.c new file mode 100644 index 0000000000..d3f80e60ba --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/charptr.c @@ -0,0 +1,58 @@ +/* + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +#ifdef __STDC__ +#include "pccts_stdlib.h" +#else +#include +#endif +#include "pccts_string.h" + +/* 133MR1 include stdio.h for fprintf in charptr.c */ + +#include "pccts_stdio.h" + +/* 133MR1 include charptr.h for Attrib in charptr.c */ + +#include "charptr.h" + +#ifdef __USE_PROTOS +zzcr_attr(Attrib *a,int token,char *text) +#else +zzcr_attr(a,token,text) +Attrib *a; +int token; +char *text; +#endif +{ + *a = (char *) malloc(strlen(text)+1); /* MR6 */ + if ( *a == NULL ) {fprintf(stderr, "zzcr_attr: out of memory!\n"); exit(-1);} + strcpy(*a, text); +} diff --git a/Tools/Source/TianoTools/Pccts/h/charptr.h b/Tools/Source/TianoTools/Pccts/h/charptr.h new file mode 100644 index 0000000000..e73da681a4 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/charptr.h @@ -0,0 +1,48 @@ +/* + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +/* + * WARNING!!!!: charptr.h does NOT make copies and the + * memory is freed after the attribute scope exits. + */ + +#ifndef ZZCHARPTR_H +#define ZZCHARPTR_H + +typedef char *Attrib; +#define zzdef0(a) {*(a)=NULL;} +/* MR8 Jens Tingleff (jensting@imaginet.fr) */ +/* Set memory pointer to null after free() */ +#define zzd_attr(a) {if ( *(a)!=NULL ) {free(*(a)); *(a)=NULL; }; } + +#ifdef __STDC__ +extern zzcr_attr(Attrib *,int,char *); +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/config.h b/Tools/Source/TianoTools/Pccts/h/config.h new file mode 100644 index 0000000000..8aa50ad618 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/config.h @@ -0,0 +1 @@ +#include "pcctscfg.h" diff --git a/Tools/Source/TianoTools/Pccts/h/dlgauto.h b/Tools/Source/TianoTools/Pccts/h/dlgauto.h new file mode 100644 index 0000000000..db94cefaca --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/dlgauto.h @@ -0,0 +1,504 @@ +/* dlgauto.h automaton + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Will Cohen and Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ZZDEFAUTO_H +#define ZZDEFAUTO_H + +/* 10-Apr-97 133MR1 Uses __USE_PROTOS show should #include pcctscfg.h */ + +#include "pcctscfg.h" + +zzchar_t *zzlextext; /* text of most recently matched token */ +zzchar_t *zzbegexpr; /* beginning of last reg expr recogn. */ +zzchar_t *zzendexpr; /* beginning of last reg expr recogn. */ +int zzbufsize = 0; /* number of characters in zzlextext */ /* MR7 */ +int zzbegcol = 0; /* column that first character of token is in*/ +int zzendcol = 0; /* column that last character of token is in */ +int zzline = 1; /* line current token is on */ +int zzreal_line=1; /* line of 1st portion of token that is not skipped */ +int zzchar; /* character to determine next state */ +int zzbufovf; /* indicates that buffer too small for text */ +int zzcharfull = 0; +static zzchar_t *zznextpos;/* points to next available position in zzlextext*/ +static int zzclass; + +#ifdef __USE_PROTOS +void zzerrstd(const char *); +void (*zzerr)(const char *)=zzerrstd;/* pointer to error reporting function */ +extern int zzerr_in(void); +static int (*zzfunc_in)(void) = zzerr_in; /* MR20 */ +#else +void zzerrstd(); +void (*zzerr)()=zzerrstd; /* pointer to error reporting function */ +extern int zzerr_in(); +static int (*zzfunc_in)() = zzerr_in; /* MR20 */ +#endif + +static FILE *zzstream_in=0; +static zzchar_t *zzstr_in=0; + +#ifdef USER_ZZMODE_STACK +int zzauto = 0; +#else +static int zzauto = 0; +#endif +static int zzadd_erase; +static char zzebuf[70]; + +#ifdef ZZCOL +#define ZZINC (++zzendcol) +#else +#define ZZINC +#endif + + +#define ZZGETC_STREAM {zzchar = getc(zzstream_in); zzclass = ZZSHIFT(zzchar);} +#define ZZGETC_FUNC {zzchar = (*zzfunc_in)(); zzclass = ZZSHIFT(zzchar);} +#define ZZGETC_STR { \ + if (*zzstr_in){ \ + zzchar = *zzstr_in; \ + ++zzstr_in; \ + }else{ \ + zzchar = EOF; \ + } \ + zzclass = ZZSHIFT(zzchar); \ +} + +#define ZZNEWSTATE (newstate = dfa[state][zzclass]) + +#ifndef ZZCOPY +#define ZZCOPY \ + /* Truncate matching buffer to size (not an error) */ \ + if (zznextpos < lastpos){ \ + *(zznextpos++) = zzchar; \ + }else{ \ + zzbufovf = 1; \ + } +#endif + +void +#ifdef __USE_PROTOS +zzrdstream( FILE *f ) +#else +zzrdstream( f ) +FILE *f; +#endif +{ + /* make sure that it is really set to something, otherwise just + leave it be. + */ + if (f){ + /* make sure that there is always someplace to get input + before closing zzstream_in + */ +#if 0 + if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in ); +#endif + zzline = 1; + zzstream_in = f; + zzfunc_in = NULL; + zzstr_in = 0; + zzcharfull = 0; + } +} + +void +#ifdef __USE_PROTOS +zzrdfunc( int (*f)(void) ) +#else +zzrdfunc( f ) +int (*f)(); +#endif +{ + /* make sure that it is really set to something, otherwise just + leave it be. + */ + if (f){ + /* make sure that there is always someplace to get input + before closing zzstream_in + */ +#if 0 + if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in ); +#endif + zzline = 1; + zzstream_in = NULL; + zzfunc_in = f; + zzstr_in = 0; + zzcharfull = 0; + } +} + + +void +#ifdef __USE_PROTOS +zzrdstr( zzchar_t *s ) +#else +zzrdstr( s ) +zzchar_t *s; +#endif +{ + /* make sure that it is really set to something, otherwise just + leave it be. + */ + if (s){ + /* make sure that there is always someplace to get input + before closing zzstream_in + */ +#if 0 + if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in ); +#endif + zzline = 1; + zzstream_in = NULL; + zzfunc_in = 0; + zzstr_in = s; + zzcharfull = 0; + } +} + + +#ifdef __USE_PROTOS +void zzclose_stream(void) +#else +void zzclose_stream() +#endif +{ +#if 0 + fclose( zzstream_in ); + zzstream_in = NULL; + zzfunc_in = NULL; +#endif +} + +/* saves dlg state, but not what feeds dlg (such as file position) */ +void +#ifdef __USE_PROTOS +zzsave_dlg_state(struct zzdlg_state *state) +#else +zzsave_dlg_state(state) +struct zzdlg_state *state; +#endif +{ + state->stream = zzstream_in; + state->func_ptr = zzfunc_in; + state->str = zzstr_in; + state->auto_num = zzauto; + state->add_erase = zzadd_erase; + state->lookc = zzchar; + state->char_full = zzcharfull; + state->begcol = zzbegcol; + state->endcol = zzendcol; + state->line = zzline; + state->lextext = zzlextext; + state->begexpr = zzbegexpr; + state->endexpr = zzendexpr; + state->bufsize = zzbufsize; + state->bufovf = zzbufovf; + state->nextpos = zznextpos; + state->class_num = zzclass; +} + +void +#ifdef __USE_PROTOS +zzrestore_dlg_state(struct zzdlg_state *state) +#else +zzrestore_dlg_state(state) +struct zzdlg_state *state; +#endif +{ + zzstream_in = state->stream; + zzfunc_in = state->func_ptr; + zzstr_in = state->str; + zzauto = state->auto_num; + zzadd_erase = state->add_erase; + zzchar = state->lookc; + zzcharfull = state->char_full; + zzbegcol = state->begcol; + zzendcol = state->endcol; + zzline = state->line; + zzlextext = state->lextext; + zzbegexpr = state->begexpr; + zzendexpr = state->endexpr; + zzbufsize = state->bufsize; + zzbufovf = state->bufovf; + zznextpos = state->nextpos; + zzclass = state->class_num; +} + +void +#ifdef __USE_PROTOS +zzmode( int m ) +#else +zzmode( m ) +int m; +#endif +{ + /* points to base of dfa table */ + if (m +#include + +/* */ +/* 7-Apr-97 133MR1 */ +/* Proper choice of STDC and cplusplus pre-processor symbols (?) */ +/* */ +#include "pccts_string.h" + +#ifdef PCCTS_USE_STDARG +#include "pccts_stdarg.h" +#else +#include +#endif + +#ifdef DUM +/* Define usable bits per unsigned int word (used for set stuff) */ +#ifdef PC +#define BSETWORDSIZE 16 +#define BSETLOGWORDSIZE 4 +#else +#define BSETWORDSIZE 32 +#define BSETLOGWORDSIZE 5 +#endif +#endif + +#define BSETWORDSIZE 8 +#define BSETLOGWORDSIZE 3 /* SetWordType is 8bits */ + +#define BSETMODWORD(x) ((x) & (BSETWORDSIZE-1)) /* x % BSETWORDSIZE */ +#define BSETDIVWORD(x) ((x) >> BSETLOGWORDSIZE) /* x / BSETWORDSIZE */ + +/* This is not put into the global pccts_parser structure because it is + * hidden and does not need to be saved during a "save state" operation + */ +/* maximum of 32 bits/unsigned int and must be 8 bits/byte */ +static SetWordType bitmask[] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080 +}; + +#ifdef zzTRACE_RULES +int zzTraceOptionValueDefault=1; +int zzTraceOptionValue=1; +int zzTraceGuessOptionValue=1; +char *zzTraceCurrentRuleName=NULL; +int zzTraceDepth=0; +#endif + +int zzGuessSeq=0; /* MR10 */ +int zzSyntaxErrCount=0; /* MR11 */ +int zzLexErrCount=0; /* MR11 */ + +void +#ifdef __USE_PROTOS +zzresynch(SetWordType *wd,SetWordType mask) +#else +zzresynch(wd,mask) +SetWordType *wd, mask; +#endif +{ + static int consumed = 1; + + /* if you enter here without having consumed a token from last resynch + * force a token consumption. + */ + if ( !consumed ) {zzCONSUME; consumed=1; return;} /* MR10 */ + + /* if current token is in resynch set, we've got what we wanted */ + if ( wd[LA(1)]&mask || LA(1) == zzEOF_TOKEN ) {consumed=0; return;} + + /* scan until we find something in the resynch set */ + while ( !(wd[LA(1)]&mask) && LA(1) != zzEOF_TOKEN ) {zzCONSUME;} + consumed=1; +} + +/* */ +/* 7-Apr-97 133MR1 for C++ and MR7 for C */ +/* Change suggested by Eli Sternheim (eli@interhdl.com) */ +/* */ + +void +#ifdef __USE_PROTOS +zzconsumeUntil(SetWordType *st) +#else +zzconsumeUntil(st) +SetWordType *st; +#endif +{ + int tmp; /* MR7 */ + while ( !zzset_el( (tmp=LA(1)), st) && tmp!=1 /* Eof */) { /* MR7 */ + zzCONSUME; } /* MR7 */ +} + +/* */ +/* 7-Apr-97 133MR1 for C++ and MR7 for C */ +/* Change suggested by Eli Sternheim (eli@interhdl.com) */ +/* */ + +void +#ifdef __USE_PROTOS +zzconsumeUntilToken(int t) +#else +zzconsumeUntilToken(t) +int t; +#endif +{ + int tmp; /* MR7 */ + while ( (tmp=LA(1)) !=t && tmp!=1 /* Eof */) { zzCONSUME; } /* MR7 */ +} + +/* input looks like: + * zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText) + * where the zzMiss stuff is set here to the token that did not match + * (and which set wasn't it a member of). + */ + +#ifdef PCCTS_USE_STDARG +void zzFAIL(int k, ...) +#else +void zzFAIL(va_alist) +va_dcl +#endif +{ +#ifdef LL_K + static char text[LL_K*ZZLEXBUFSIZE+1]; + SetWordType *f[LL_K]; +#else + static char text[ZZLEXBUFSIZE+1]; + SetWordType *f[1]; +#endif + SetWordType **miss_set; + char **miss_text; + int *bad_tok; + char **bad_text; + int *err_k; + int i; + va_list ap; +#ifndef PCCTS_USE_STDARG /* MR20 */ + int k; +#endif +#ifdef PCCTS_USE_STDARG /* MR20 */ + va_start(ap, k); +#else + va_start(ap); + k = va_arg(ap, int); /* how many lookahead sets? */ +#endif + assert(k <= sizeof(f)/sizeof(f[0])); /* MR20 G. Hobbelt */ + text[0] = '\0'; + for (i=1; i<=k; i++) /* collect all lookahead sets */ + { + f[i-1] = va_arg(ap, SetWordType *); + } + for (i=1; i<=k; i++) /* look for offending token */ + { + if ( i>1 ) strcat(text, " "); + strcat(text, LATEXT(i)); + if ( !zzset_el((unsigned)LA(i), f[i-1]) ) break; + } + miss_set = va_arg(ap, SetWordType **); + miss_text = va_arg(ap, char **); + bad_tok = va_arg(ap, int *); + bad_text = va_arg(ap, char **); + err_k = va_arg(ap, int *); + if ( i>k ) + { + /* bad; lookahead is permutation that cannot be matched, + * but, the ith token of lookahead is valid at the ith position + * (The old LL sub 1 (k) versus LL(k) parsing technique) + */ + *miss_set = NULL; + *miss_text = zzlextext; + *bad_tok = LA(1); + *bad_text = LATEXT(1); + *err_k = k; + return; + } +/* fprintf(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/ + *miss_set = f[i-1]; + *miss_text = text; + *bad_tok = LA(i); + *bad_text = LATEXT(i); + if ( i==1 ) *err_k = 1; + else *err_k = k; +} + +#ifdef __USE_PROTOS +void zzTraceGuessDone(zzantlr_state *state) +#else +void zzTraceGuessDone(state) + zzantlr_state *state; +#endif +{ +#ifdef zzTRACE_RULES +#ifdef ZZCAN_GUESS + + int doIt=0; + + if (zzTraceCurrentRuleName == NULL) return; + + if (zzTraceOptionValue <= 0) { + doIt=0; + } else if (zzTraceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + fprintf(stderr,"guess done - returning to rule %s {\"%s\"} at depth %d", + state->traceCurrentRuleName, + LATEXT(1), + state->traceDepth); + if (state->guessing != 0) { + fprintf(stderr," (guess mode continues - an enclosing guess is still active)"); + } else { + fprintf(stderr," (guess mode ends)"); + }; + fprintf(stderr,"\n"); + }; +#endif +#endif +} + +void +#ifdef __USE_PROTOS +zzsave_antlr_state(zzantlr_state *buf) +#else +zzsave_antlr_state(buf) +zzantlr_state *buf; +#endif +{ +#ifdef LL_K + int i; +#endif + +#ifdef ZZCAN_GUESS + buf->guess_start = zzguess_start; + buf->guessing = zzguessing; +#endif + buf->asp = zzasp; +#ifdef GENAST + buf->ast_sp = zzast_sp; +#endif +#ifdef ZZINF_LOOK + buf->inf_labase = zzinf_labase; + buf->inf_last = zzinf_last; + +/* MR6 Gunnar Rxnning (gunnar@candleweb.no) */ +/* MR6 Additional state needs to be saved/restored */ + + buf->inf_tokens = zzinf_tokens; /* MR6 */ + buf->inf_text = zzinf_text; /* MR6 */ + buf->inf_text_buffer = zzinf_text_buffer; /* MR6 */ + buf->inf_line = zzinf_line; /* MR6 */ + +#endif +#ifdef DEMAND_LOOK + buf->dirty = zzdirty; +#endif +#ifdef LL_K + for (i=0; itokenLA[i] = zztokenLA[i]; + for (i=0; itextLA[i], zztextLA[i]); + buf->lap = zzlap; + buf->labase = zzlabase; +#else + buf->token = zztoken; + strcpy(buf->text, zzlextext); +#endif +#ifdef zzTRACE_RULES + + /* MR10 */ + + buf->traceOptionValue=zzTraceOptionValue; + buf->traceGuessOptionValue=zzTraceGuessOptionValue; + buf->traceCurrentRuleName=zzTraceCurrentRuleName; + buf->traceDepth=zzTraceDepth; +#endif +} + +void +#ifdef __USE_PROTOS +zzrestore_antlr_state(zzantlr_state *buf) +#else +zzrestore_antlr_state(buf) +zzantlr_state *buf; +#endif +{ + +#ifdef zzTRACE_RULES + int prevTraceOptionValue; +#endif + +#ifdef LL_K + int i; +#endif + +#ifdef ZZCAN_GUESS + zzguess_start = buf->guess_start; + zzguessing = buf->guessing; +#endif + zzasp = buf->asp; +#ifdef GENAST + zzast_sp = buf->ast_sp; +#endif +#ifdef ZZINF_LOOK + zzinf_labase = buf->inf_labase; + zzinf_last = buf->inf_last; + +/* MR6 Gunnar Rxnning (gunnar@candleweb.no) */ +/* MR6 Additional state needs to be saved/restored */ + + zzinf_tokens = buf->inf_tokens; /* MR6 */ + zzinf_text = buf->inf_text; /* MR6 */ + zzinf_text_buffer = buf->inf_text_buffer; /* MR6 */ + zzinf_line = buf->inf_line; /* MR6 */ +#endif +#ifdef DEMAND_LOOK + zzdirty = buf->dirty; +#endif +#ifdef LL_K + for (i=0; itokenLA[i]; + for (i=0; itextLA[i]); + zzlap = buf->lap; + zzlabase = buf->labase; +#else + zztoken = buf->token; + strcpy(zzlextext, buf->text); +#endif +#ifdef zzTRACE_RULES + + prevTraceOptionValue=zzTraceOptionValue; + zzTraceOptionValue=buf->traceOptionValue; + if ( (prevTraceOptionValue > 0) != + (zzTraceOptionValue > 0)) { + if (zzTraceOptionValue > 0) { + fprintf(stderr,"trace enable restored in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + if (zzTraceOptionValue <= 0) { + fprintf(stderr,"trace disable restored in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + }; + + zzTraceOptionValue=buf->traceOptionValue; /* MR10 */ + zzTraceGuessOptionValue=buf->traceGuessOptionValue; /* MR10 */ + zzTraceCurrentRuleName=buf->traceCurrentRuleName; /* MR10 */ + zzTraceDepth=buf->traceDepth; /* MR10 */ + zzTraceGuessDone(buf); /* MR10 */ +#endif +} + +void +#ifdef __USE_PROTOS +zzedecode(SetWordType *a) +#else +zzedecode(a) +SetWordType *a; +#endif +{ + register SetWordType *p = a; + register SetWordType *endp = &(p[zzSET_SIZE]); + register unsigned e = 0; + + if ( zzset_deg(a)>1 ) fprintf(stderr, " {"); + do { + register SetWordType t = *p; + register SetWordType *b = &(bitmask[0]); + do { + if ( t & *b ) fprintf(stderr, " %s", zztokens[e]); + e++; + } while (++b < &(bitmask[sizeof(SetWordType)*8])); + } while (++p < endp); + if ( zzset_deg(a)>1 ) fprintf(stderr, " }"); +} + +#ifndef USER_ZZSYN +/* standard error reporting function */ +void +#ifdef __USE_PROTOS +zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text) +#else +zzsyn(text, tok, egroup, eset, etok, k, bad_text) +char *text, *egroup, *bad_text; +int tok; +int etok; +int k; +SetWordType *eset; +#endif +{ + + zzSyntaxErrCount++; /* MR11 */ + fprintf(stderr, "line %d: syntax error at \"%s\"", zzline, (tok==zzEOF_TOKEN)?"EOF":bad_text); + if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} + if ( k==1 ) fprintf(stderr, " missing"); + else + { + fprintf(stderr, "; \"%s\" not", bad_text); + if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); + } + if ( zzset_deg(eset)>0 ) zzedecode(eset); + else fprintf(stderr, " %s", zztokens[etok]); + if ( strlen(egroup) > 0 ) fprintf(stderr, " in %s", egroup); + fprintf(stderr, "\n"); +} +#endif + +/* is b an element of set p? */ +int +#ifdef __USE_PROTOS +zzset_el(unsigned b, SetWordType *p) +#else +zzset_el(b,p) +unsigned b; +SetWordType *p; +#endif +{ + return( p[BSETDIVWORD(b)] & bitmask[BSETMODWORD(b)] ); +} + +int +#ifdef __USE_PROTOS +zzset_deg(SetWordType *a) +#else +zzset_deg(a) +SetWordType *a; +#endif +{ + /* Fast compute degree of a set... the number + of elements present in the set. Assumes + that all word bits are used in the set + */ + register SetWordType *p = a; + register SetWordType *endp = &(a[zzSET_SIZE]); + register int degree = 0; + + if ( a == NULL ) return 0; + while ( p < endp ) + { + register SetWordType t = *p; + register SetWordType *b = &(bitmask[0]); + do { + if (t & *b) ++degree; + } while (++b < &(bitmask[sizeof(SetWordType)*8])); + p++; + } + + return(degree); +} + +#ifdef DEMAND_LOOK + +#ifdef LL_K +int +#ifdef __USE_PROTOS +_zzmatch(int _t, char **zzBadText, char **zzMissText, + int *zzMissTok, int *zzBadTok, + SetWordType **zzMissSet) +#else +_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet) +int _t; +char **zzBadText; +char **zzMissText; +int *zzMissTok, *zzBadTok; +SetWordType **zzMissSet; +#endif +{ + if ( zzdirty==LL_K ) { + zzCONSUME; + } + if ( LA(1)!=_t ) { + *zzBadText = *zzMissText=LATEXT(1); + *zzMissTok= _t; *zzBadTok=LA(1); + *zzMissSet=NULL; + return 0; + } + zzMakeAttr + zzdirty++; + zzlabase++; + return 1; +} + +int +#ifdef __USE_PROTOS +_zzmatch_wsig(int _t) +#else +_zzmatch_wsig(_t) +int _t; +#endif +{ + if ( zzdirty==LL_K ) { + zzCONSUME; + } + if ( LA(1)!=_t ) { + return 0; + } + zzMakeAttr + zzdirty++; + zzlabase++; + return 1; +} + +#else + +int +#ifdef __USE_PROTOS +_zzmatch(int _t, char **zzBadText, char **zzMissText, + int *zzMissTok, int *zzBadTok, SetWordType **zzMissSet) +#else +_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet) +int _t; +char **zzBadText; +char **zzMissText; +int *zzMissTok, *zzBadTok; +SetWordType **zzMissSet; +#endif +{ + if ( zzdirty ) {zzCONSUME;} + if ( LA(1)!=_t ) { + *zzBadText = *zzMissText=LATEXT(1); + *zzMissTok= _t; *zzBadTok=LA(1); + *zzMissSet=NULL; + return 0; + } + zzdirty = 1; + zzMakeAttr + return 1; +} + +int +#ifdef __USE_PROTOS +_zzmatch_wsig(int _t) +#else +_zzmatch_wsig(_t) +int _t; +#endif +{ + if ( zzdirty ) {zzCONSUME;} + if ( LA(1)!=_t ) { + return 0; + } + zzdirty = 1; + zzMakeAttr + return 1; +} + +#endif /*LL_K*/ + +#else + +int +#ifdef __USE_PROTOS +_zzmatch(int _t, char **zzBadText, char **zzMissText, + int *zzMissTok, int *zzBadTok, + SetWordType **zzMissSet) +#else +_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet) +int _t; +char **zzBadText; +char **zzMissText; +int *zzMissTok, *zzBadTok; +SetWordType **zzMissSet; +#endif +{ + if ( LA(1)!=_t ) { + *zzBadText = *zzMissText=LATEXT(1); + *zzMissTok= _t; *zzBadTok=LA(1); + *zzMissSet=NULL; + return 0; + } + zzMakeAttr + return 1; +} + +int +#ifdef __USE_PROTOS +_zzmatch_wsig(int _t) +#else +_zzmatch_wsig(_t) +int _t; +#endif +{ + if ( LA(1)!=_t ) return 0; + zzMakeAttr + return 1; +} + +#endif /*DEMAND_LOOK*/ + +#ifdef ZZINF_LOOK +void +#ifdef __USE_PROTOS +_inf_zzgettok(void) +#else +_inf_zzgettok() +#endif +{ + if ( zzinf_labase >= zzinf_last ) + {NLA = zzEOF_TOKEN; strcpy(NLATEXT, "");} + else { + NLA = zzinf_tokens[zzinf_labase]; + zzline = zzinf_line[zzinf_labase]; /* wrong in 1.21 */ + strcpy(NLATEXT, zzinf_text[zzinf_labase]); + zzinf_labase++; + } +} +#endif + +#ifdef ZZINF_LOOK +/* allocate default size text,token and line arrays; + * then, read all of the input reallocing the arrays as needed. + * Once the number of total tokens is known, the LATEXT(i) array (zzinf_text) + * is allocated and it's pointers are set to the tokens in zzinf_text_buffer. + */ +void +#ifdef __USE_PROTOS +zzfill_inf_look(void) +#else +zzfill_inf_look() +#endif +{ + int tok, line; + int zzinf_token_buffer_size = ZZINF_DEF_TOKEN_BUFFER_SIZE; + int zzinf_text_buffer_size = ZZINF_DEF_TEXT_BUFFER_SIZE; + int zzinf_text_buffer_index = 0; + int zzinf_lap = 0; + + /* allocate text/token buffers */ + zzinf_text_buffer = (char *) malloc(zzinf_text_buffer_size); + if ( zzinf_text_buffer == NULL ) + { + fprintf(stderr, "cannot allocate lookahead text buffer (%d bytes)\n", + zzinf_text_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + zzinf_tokens = (int *) calloc(zzinf_token_buffer_size,sizeof(int)); + if ( zzinf_tokens == NULL ) + { + fprintf(stderr, "cannot allocate token buffer (%d tokens)\n", + zzinf_token_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + zzinf_line = (int *) calloc(zzinf_token_buffer_size,sizeof(int)); + if ( zzinf_line == NULL ) + { + fprintf(stderr, "cannot allocate line buffer (%d ints)\n", + zzinf_token_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + + /* get tokens, copying text to text buffer */ + zzinf_text_buffer_index = 0; + do { + zzgettok(); + line = zzreal_line; + while ( zzinf_lap>=zzinf_token_buffer_size ) + { + zzinf_token_buffer_size += ZZINF_BUFFER_TOKEN_CHUNK_SIZE; + zzinf_tokens = (int *) realloc(zzinf_tokens, + zzinf_token_buffer_size*sizeof(int)); + if ( zzinf_tokens == NULL ) + { + fprintf(stderr, "cannot allocate lookahead token buffer (%d tokens)\n", + zzinf_token_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + zzinf_line = (int *) realloc(zzinf_line, + zzinf_token_buffer_size*sizeof(int)); + if ( zzinf_line == NULL ) + { + fprintf(stderr, "cannot allocate lookahead line buffer (%d ints)\n", + zzinf_token_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + + } + while ( (zzinf_text_buffer_index+strlen(NLATEXT)+1) >= zzinf_text_buffer_size ) + { + zzinf_text_buffer_size += ZZINF_BUFFER_TEXT_CHUNK_SIZE; + zzinf_text_buffer = (char *) realloc(zzinf_text_buffer, + zzinf_text_buffer_size); + if ( zzinf_text_buffer == NULL ) + { + fprintf(stderr, "cannot allocate lookahead text buffer (%d bytes)\n", + zzinf_text_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + } + /* record token and text and line of input symbol */ + tok = zzinf_tokens[zzinf_lap] = NLA; + strcpy(&zzinf_text_buffer[zzinf_text_buffer_index], NLATEXT); + zzinf_text_buffer_index += strlen(NLATEXT)+1; + zzinf_line[zzinf_lap] = line; + zzinf_lap++; + } while (tok!=zzEOF_TOKEN); + zzinf_labase = 0; + zzinf_last = zzinf_lap-1; + + /* allocate ptrs to text of ith token */ + zzinf_text = (char **) calloc(zzinf_last+1,sizeof(char *)); + if ( zzinf_text == NULL ) + { + fprintf(stderr, "cannot allocate lookahead text buffer (%d)\n", + zzinf_text_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + zzinf_text_buffer_index = 0; + zzinf_lap = 0; + /* set ptrs so that zzinf_text[i] is the text of the ith token found on input */ + while (zzinf_lap<=zzinf_last) + { + zzinf_text[zzinf_lap++] = &zzinf_text_buffer[zzinf_text_buffer_index]; + zzinf_text_buffer_index += strlen(&zzinf_text_buffer[zzinf_text_buffer_index])+1; + } +} +#endif + +int +#ifdef __USE_PROTOS +_zzsetmatch(SetWordType *e, char **zzBadText, char **zzMissText, + int *zzMissTok, int *zzBadTok, + SetWordType **zzMissSet, + SetWordType *zzTokclassErrset /* MR23 */) +#else +_zzsetmatch(e, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet, zzTokclassErrset /* MR23 */) +SetWordType *e; +char **zzBadText; +char **zzMissText; +int *zzMissTok, *zzBadTok; +SetWordType **zzMissSet; +SetWordType *zzTokclassErrset; +#endif +{ +#ifdef DEMAND_LOOK +#ifdef LL_K + if ( zzdirty==LL_K ) {zzCONSUME;} +#else + if ( zzdirty ) {zzCONSUME;} +#endif +#endif + if ( !zzset_el((unsigned)LA(1), e) ) { + *zzBadText = LATEXT(1); *zzMissText=NULL; + *zzMissTok= 0; *zzBadTok=LA(1); + *zzMissSet=zzTokclassErrset; /* MR23 */ + return 0; + } + zzMakeAttr /* MR14 Ger Hobbelt (hobbelt@axa.nl) */ +#ifdef DEMAND_LOOK +#ifdef LL_K + zzdirty++; + zzlabase++; /* MR14 Ger Hobbelt (hobbelt@axa.nl) */ +#else + zzdirty = 1; +#endif +#endif + return 1; +} + +int +#ifdef __USE_PROTOS +_zzmatch_wdfltsig(int tokenWanted, SetWordType *whatFollows) +#else +_zzmatch_wdfltsig(tokenWanted, whatFollows) +int tokenWanted; +SetWordType *whatFollows; +#endif +{ +#ifdef DEMAND_LOOK +#ifdef LL_K + if ( zzdirty==LL_K ) { + zzCONSUME; + } +#else + if ( zzdirty ) {zzCONSUME;} +#endif +#endif + + if ( LA(1)!=tokenWanted ) + { + zzSyntaxErrCount++; /* MR11 */ + fprintf(stderr, + "line %d: syntax error at \"%s\" missing %s\n", + zzline, + (LA(1)==zzEOF_TOKEN)?"":(char *)LATEXT(1), + zztokens[tokenWanted]); + zzconsumeUntil( whatFollows ); + return 0; + } + else { + zzMakeAttr +#ifdef DEMAND_LOOK +#ifdef LL_K + zzdirty++; + zzlabase++; +#else + zzdirty = 1; +#endif +#else +/* zzCONSUME; consume if not demand lookahead */ +#endif + return 1; + } +} + +int +#ifdef __USE_PROTOS +_zzsetmatch_wdfltsig(SetWordType *tokensWanted, + int tokenTypeOfSet, + SetWordType *whatFollows) +#else +_zzsetmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) +SetWordType *tokensWanted; +int tokenTypeOfSet; +SetWordType *whatFollows; +#endif +{ +#ifdef DEMAND_LOOK +#ifdef LL_K + if ( zzdirty==LL_K ) {zzCONSUME;} +#else + if ( zzdirty ) {zzCONSUME;} +#endif +#endif + if ( !zzset_el((unsigned)LA(1), tokensWanted) ) + { + zzSyntaxErrCount++; /* MR11 */ + fprintf(stderr, + "line %d: syntax error at \"%s\" missing %s\n", + zzline, + (LA(1)==zzEOF_TOKEN)?"":(char *)LATEXT(1), + zztokens[tokenTypeOfSet]); + zzconsumeUntil( whatFollows ); + return 0; + } + else { + zzMakeAttr +#ifdef DEMAND_LOOK +#ifdef LL_K + zzdirty++; + zzlabase++; +#else + zzdirty = 1; +#endif +#else +/* zzCONSUME; consume if not demand lookahead */ +#endif + return 1; + } +} + +int +#ifdef __USE_PROTOS +_zzsetmatch_wsig(SetWordType *e) +#else +_zzsetmatch_wsig(e) +SetWordType *e; +#endif +{ +#ifdef DEMAND_LOOK +#ifdef LL_K + if ( zzdirty==LL_K ) {zzCONSUME;} +#else + if ( zzdirty ) {zzCONSUME;} +#endif +#endif + if ( !zzset_el((unsigned)LA(1), e) ) return 0; + zzMakeAttr /* MR14 Ger Hobbelt (hobbelt@axa.nl) */ +#ifdef DEMAND_LOOK +#ifdef LL_K + zzdirty++; + zzlabase++; /* MR14 Ger Hobbelt (hobbelt@axa.nl) */ +#else + zzdirty = 1; +#endif +#endif + return 1; +} + +#ifdef USER_ZZMODE_STACK +static int zzmstk[ZZMAXSTK] = { -1 }; +static int zzmdep = 0; +static char zzmbuf[70]; + +void +#ifdef __USE_PROTOS +zzmpush( int m ) +#else +zzmpush( m ) +int m; +#endif +{ + if(zzmdep == ZZMAXSTK - 1) { + sprintf(zzmbuf, "Mode stack overflow "); + zzerr(zzmbuf); + } else { + zzmstk[zzmdep++] = zzauto; + zzmode(m); + } +} + +void +#ifdef __USE_PROTOS +zzmpop( void ) +#else +zzmpop( ) +#endif +{ + if(zzmdep == 0) + { sprintf(zzmbuf, "Mode stack underflow "); + zzerr(zzmbuf); + } + else + { zzmdep--; + zzmode(zzmstk[zzmdep]); + } +} + +void +#ifdef __USE_PROTOS +zzsave_mode_stack( int modeStack[], int *modeLevel ) +#else +zzsave_mode_stack( modeStack, modeLevel ) +int modeStack[]; +int *modeLevel; +#endif +{ + int i; + memcpy(modeStack, zzmstk, sizeof(zzmstk)); + *modeLevel = zzmdep; + zzmdep = 0; + + return; +} + +void +#ifdef __USE_PROTOS +zzrestore_mode_stack( int modeStack[], int *modeLevel ) +#else +zzrestore_mode_stack( modeStack, modeLevel ) +int modeStack[]; +int *modeLevel; +#endif +{ + int i; + + memcpy(zzmstk, modeStack, sizeof(zzmstk)); + zzmdep = *modeLevel; + + return; +} +#endif /* USER_ZZMODE_STACK */ + +#ifdef __USE_PROTOS +void zzTraceReset(void) +#else +void zzTraceReset() +#endif +{ +#ifdef zzTRACE_RULES + zzTraceOptionValue=zzTraceOptionValueDefault; + zzTraceGuessOptionValue=1; + zzTraceCurrentRuleName=NULL; + zzTraceDepth=0; +#endif +} + +#ifdef __USE_PROTOS +void zzTraceGuessFail(void) +#else +void zzTraceGuessFail() +#endif +{ + +#ifdef zzTRACE_RULES +#ifdef ZZCAN_GUESS + + int doIt=0; + + if (zzTraceOptionValue <= 0) { + doIt=0; + } else if (zzguessing && zzTraceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + fprintf(stderr,"guess failed\n"); + }; +#endif +#endif +} + +/* zzTraceOption: + zero value turns off trace +*/ + +#ifdef __USE_PROTOS +void zzTraceIn(char * rule) +#else +void zzTraceIn(rule) + char *rule; +#endif +{ +#ifdef zzTRACE_RULES + + int doIt=0; + + zzTraceDepth++; + zzTraceCurrentRuleName=rule; + + if (zzTraceOptionValue <= 0) { + doIt=0; +#ifdef ZZCAN_GUESS + } else if (zzguessing && zzTraceGuessOptionValue <= 0) { + doIt=0; +#endif + } else { + doIt=1; + }; + + if (doIt) { + fprintf(stderr,"enter rule %s {\"%s\"} depth %d", + rule, + LA(1)==1 ? "@" : (char *) LATEXT(1), /* MR19 */ + zzTraceDepth); +#ifdef ZZCAN_GUESS + if (zzguessing) fprintf(stderr," guessing"); +#endif + fprintf(stderr,"\n"); + }; +#endif + return; +} + +#ifdef __USE_PROTOS +void zzTraceOut(char * rule) +#else +void zzTraceOut(rule) + char *rule; +#endif +{ +#ifdef zzTRACE_RULES + int doIt=0; + + zzTraceDepth--; + + if (zzTraceOptionValue <= 0) { + doIt=0; +#ifdef ZZCAN_GUESS + } else if (zzguessing && zzTraceGuessOptionValue <= 0) { + doIt=0; +#endif + } else { + doIt=1; + }; + + if (doIt) { + fprintf(stderr,"exit rule %s {\"%s\"} depth %d", + rule, + LA(1)==1 ? "@" : (char *) LATEXT(1), /* MR19 */ + zzTraceDepth+1); +#ifdef ZZCAN_GUESS + if (zzguessing) fprintf(stderr," guessing"); +#endif + fprintf(stderr,"\n"); + }; +#endif +} + +#ifdef __USE_PROTOS +int zzTraceOption(int delta) +#else +int zzTraceOption(delta) + int delta; +#endif +{ +#ifdef zzTRACE_RULES + int prevValue=zzTraceOptionValue; + + zzTraceOptionValue=zzTraceOptionValue+delta; + + if (zzTraceCurrentRuleName != NULL) { + if (prevValue <= 0 && zzTraceOptionValue > 0) { + fprintf(stderr,"trace enabled in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + if (prevValue > 0 && zzTraceOptionValue <= 0) { + fprintf(stderr,"trace disabled in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + }; + return prevValue; +#else + return 0; +#endif +} + +#ifdef __USE_PROTOS +int zzTraceGuessOption(int delta) +#else +int zzTraceGuessOption(delta) + int delta; +#endif +{ +#ifdef zzTRACE_RULES +#ifdef ZZCAN_GUESS + int prevValue=zzTraceGuessOptionValue; + + zzTraceGuessOptionValue=zzTraceGuessOptionValue+delta; + + if (zzTraceCurrentRuleName != NULL) { + if (prevValue <= 0 && zzTraceGuessOptionValue > 0) { + fprintf(stderr,"guess trace enabled in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + if (prevValue > 0 && zzTraceGuessOptionValue <= 0) { + fprintf(stderr,"guess trace disabled in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + }; + return prevValue; +#else + return 0; +#endif +#else + return 0; +#endif +} + +#endif /* ERR_H */ diff --git a/Tools/Source/TianoTools/Pccts/h/int.h b/Tools/Source/TianoTools/Pccts/h/int.h new file mode 100644 index 0000000000..cdcaa92426 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/int.h @@ -0,0 +1,37 @@ +/* ANTLR attribute definition -- long integers + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ZZINT_H +#define ZZINT_H + +typedef long Attrib; + +#define zzcr_attr(a,tok,t) *(a) = atol(t); + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/pccts_assert.h b/Tools/Source/TianoTools/Pccts/h/pccts_assert.h new file mode 100644 index 0000000000..ff0dfb5126 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/pccts_assert.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_ASSERT_H__ +#define __PCCTS_ASSERT_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/pccts_iostream.h b/Tools/Source/TianoTools/Pccts/h/pccts_iostream.h new file mode 100644 index 0000000000..972b32cbd1 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/pccts_iostream.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_IOSTREAM_H__ +#define __PCCTS_IOSTREAM_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/pccts_istream.h b/Tools/Source/TianoTools/Pccts/h/pccts_istream.h new file mode 100644 index 0000000000..e25cb8c483 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/pccts_istream.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_ISTREAM_H__ +#define __PCCTS_ISTREAM_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/pccts_setjmp.h b/Tools/Source/TianoTools/Pccts/h/pccts_setjmp.h new file mode 100644 index 0000000000..9ea185ca73 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/pccts_setjmp.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_SETJMP_H__ +#define __PCCTS_SETJMP_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/pccts_stdarg.h b/Tools/Source/TianoTools/Pccts/h/pccts_stdarg.h new file mode 100644 index 0000000000..e957430c32 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/pccts_stdarg.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STDARG_H__ +#define __PCCTS_STDARG_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/pccts_stdio.h b/Tools/Source/TianoTools/Pccts/h/pccts_stdio.h new file mode 100644 index 0000000000..ac34d1086d --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/pccts_stdio.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STDIO_H__ +#define __PCCTS_STDIO_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/pccts_stdlib.h b/Tools/Source/TianoTools/Pccts/h/pccts_stdlib.h new file mode 100644 index 0000000000..f0b344e8dc --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/pccts_stdlib.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STDLIB_H__ +#define __PCCTS_STDLIB_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/pccts_string.h b/Tools/Source/TianoTools/Pccts/h/pccts_string.h new file mode 100644 index 0000000000..458a08a94b --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/pccts_string.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STRING_H__ +#define __PCCTS_STRING_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/pcctscfg.h b/Tools/Source/TianoTools/Pccts/h/pcctscfg.h new file mode 100644 index 0000000000..0c3c5ba6fd --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/pcctscfg.h @@ -0,0 +1,359 @@ +#ifndef PCCTS_CONFIG_H +#define PCCTS_CONFIG_H +/* + * pcctscfg.h (formerly config.h) (for ANTLR, DLG, and SORCERER) + * + * This is a simple configuration file that doesn't have config stuff + * in it, but it's a start. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * Used by PCCTS 1.33 (SORCERER 1.00B11 and up) + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +/* This file knows about the following ``environments'' + UNIX (default) + DOS (use #define PC) + MAC (use #define MPW; has a few things for THINK C, Metrowerks) + MS/C++ (MR14 Microsoft Visual C++ environment uses symbol _MSC_VER) + + */ + +/* should test __STDC__ for 1, but some compilers don't set value, just def */ + +#ifndef __USE_PROTOS +#ifdef __STDC__ +#define __USE_PROTOS +#endif +#ifdef __cplusplus +#define __USE_PROTOS +#endif +#endif + +#ifdef PCCTS_USE_NAMESPACE_STD +#define PCCTS_NAMESPACE_STD namespace std {}; using namespace std; +#else +#define PCCTS_NAMESPACE_STD +#endif + +#include "pccts_stdio.h" +#include "pccts_stdlib.h" + +/* largest file name size */ + +#ifdef _MAX_PATH +#define MaxFileName _MAX_PATH /* MR9 RJV: MAX_PATH defined in stdlib.h (MSVC++ 5.0) */ +#else +#define MaxFileName 300 +#endif + +/* +* Define PC32 if in a 32-bit PC environment (e.g. extended DOS or Win32). +* The macros tested here are defined by Watcom, Microsoft, Borland, +* and djgpp, respectively, when they are used as 32-bit compilers. +* Users of these compilers *must* be sure to define PC in their +* makefiles for this to work correctly. +*/ +#ifdef PC +# if (defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__) || \ + defined(__GNUC__) || defined(__GNUG__)) +# ifndef PC32 +# define PC32 +# endif +# endif +#endif + +/* MR1 10-Apr-97 Default for PC is short file names */ +/* MR1 Default for non-PC is long file names */ +/* MR1 Can override via command line option LONGFILENAMES */ + +#ifndef LONGFILENAMES +#ifndef PC +#define LONGFILENAMES +#endif +#endif + +#ifndef LONGFILENAMES +#define ATOKEN_H "AToken.h" +#define ATOKPTR_H "ATokPtr.h" +#define ATOKPTR_IMPL_H "ATokPtrIm.h" +#define ATOKENBUFFER_H "ATokBuf.h" +#define ATOKENBUFFER_C "ATokBuf.cpp" +#define ATOKENSTREAM_H "ATokStr.h" +#define APARSER_H "AParser.h" +#define APARSER_C "AParser.cpp" +#define ASTBASE_H "ASTBase.h" +#define ASTBASE_C "ASTBase.cpp" +#define PCCTSAST_C "PCCTSAST.cpp" +#define LIST_C "List.cpp" +#define DLEXERBASE_H "DLexBase.h" +#define DLEXERBASE_C "DLexBase.cpp" +#define DLEXER_H "DLexer.h" +#define STREESUPPORT_C "STreeSup.C" +#else +#define ATOKEN_H "AToken.h" +#define ATOKPTR_H "ATokPtr.h" +#define ATOKPTR_IMPL_H "ATokPtrImpl.h" +#define ATOKENBUFFER_H "ATokenBuffer.h" +#define ATOKENBUFFER_C "ATokenBuffer.cpp" +#define ATOKENSTREAM_H "ATokenStream.h" +#define APARSER_H "AParser.h" +#define APARSER_C "AParser.cpp" +#define ASTBASE_H "ASTBase.h" +#define ASTBASE_C "ASTBase.cpp" +#define PCCTSAST_C "PCCTSAST.cpp" +#define LIST_C "List.cpp" +#define DLEXERBASE_H "DLexerBase.h" +#define DLEXERBASE_C "DLexerBase.cpp" +#define DLEXER_H "DLexer.h" +#define STREESUPPORT_C "STreeSupport.cpp" +#endif + +/* SORCERER Stuff */ + +/* MR8 6-Aug-97 Change from ifdef PC to ifndef LONGFILENAMES */ + +#ifndef LONGFILENAMES +#define STPARSER_H "STreePar.h" +#define STPARSER_C "STreePar.C" +#else +#define STPARSER_H "STreeParser.h" +#define STPARSER_C "STreeParser.cpp" +#endif + +#ifdef MPW +#define CPP_FILE_SUFFIX ".cp" +#define CPP_FILE_SUFFIX_NO_DOT "cp" +#define OBJ_FILE_SUFFIX ".o" +#else +#ifdef PC +#define CPP_FILE_SUFFIX ".cpp" +#define CPP_FILE_SUFFIX_NO_DOT "cpp" +#define OBJ_FILE_SUFFIX ".obj" +#else +#ifdef __VMS +#define CPP_FILE_SUFFIX ".cpp" +#define CPP_FILE_SUFFIX_NO_DOT "cpp" +#define OBJ_FILE_SUFFIX ".obj" +#else +#define CPP_FILE_SUFFIX ".cpp" +#define CPP_FILE_SUFFIX_NO_DOT "cpp" +#define OBJ_FILE_SUFFIX ".o" +#endif +#endif +#endif + +/* User may redefine how line information looks */ /* make it #line MR7 */ +/* MR21 Use #ifndef */ + +#ifndef LineInfoFormatStr +#define LineInfoFormatStr "#line %d \"%s\"\n" +#endif + +#ifdef MPW /* Macintosh Programmer's Workshop */ +#define ErrHdr "File \"%s\"; Line %d #" +#else +#ifdef _MSC_VER /* MR14 Microsoft Visual C++ environment */ +#define ErrHdr "%s(%d) :" +#else +#define ErrHdr "%s, line %d:" /* default */ +#endif +#endif + +/* must assume old K&R cpp here, can't use #if defined(..)... */ + +#ifdef MPW +#define TopDirectory ":" +#define DirectorySymbol ":" +#define OutputDirectoryOption "Directory where all output files should go (default=\":\")" +#else +#ifdef PC +#define TopDirectory "." +#define DirectorySymbol "\\" +#define OutputDirectoryOption "Directory where all output files should go (default=\".\")" +#else +#ifdef __VMS +#define TopDirectory "[000000]" +#define DirectorySymbol "]" +#define OutputDirectoryOption "Directory where all output files should go (default=\"[]\")" +#else +#define TopDirectory "." +#define DirectorySymbol "/" +#define OutputDirectoryOption "Directory where all output files should go (default=\".\")" +#endif +#endif +#endif + +#ifdef MPW + +/* Make sure we have prototypes for all functions under MPW */ + +#include "pccts_string.h" +#include "pccts_stdlib.h" + +/* MR6 2-Jun-97 Fixes false dependency caused by VC++ #include scanner */ +/* MR6 Reported by Brad Schick (schick@interaccess.com) */ +#define MPW_CursorCtl_Header +#include MPW_CursorCtl_Header +#ifdef __cplusplus +extern "C" { +#endif +extern void fsetfileinfo (const char *filename, unsigned long newcreator, unsigned long newtype); +#ifdef __cplusplus +} +#endif + +/* File creators for various popular development environments */ + +#define MAC_FILE_CREATOR 'MPS ' /* MPW Text files */ +#if 0 +#define MAC_FILE_CREATOR 'KAHL' /* THINK C/Symantec C++ Text files */ +#endif +#if 0 +#define MAC_FILE_CREATOR 'CWIE' /* Metrowerks C/C++ Text files */ +#endif + +#endif + +#ifdef MPW +#define DAWDLE SpinCursor(1) +#else +#define DAWDLE +#endif + +#ifdef MPW +#define SPECIAL_INITS +#define SPECIAL_FOPEN +#endif + +#ifdef MPW +#ifdef __cplusplus +inline +#else +static +#endif +void special_inits() +{ + InitCursorCtl((acurHandle) 0); +} +#endif + +#ifdef MPW +#ifdef __cplusplus +inline +#else +static +#endif +void special_fopen_actions(char * s) +{ + fsetfileinfo (s, MAC_FILE_CREATOR, 'TEXT'); +} +#endif + +/* Define usable bits for set.c stuff */ +#define BytesPerWord sizeof(unsigned) +#define WORDSIZE (sizeof(unsigned)*8) +#define LogWordSize (WORDSIZE==16?4:5) + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#if defined(VAXC) || defined(__VMS) +#include +#define PCCTS_EXIT_SUCCESS 1 +#define PCCTS_EXIT_FAILURE SS$_ABORT +#define zzDIE return SS$_ABORT; +#define zzDONE return 1; + +#else /* !VAXC and !__VMS */ + +#define PCCTS_EXIT_SUCCESS 0 +#define PCCTS_EXIT_FAILURE 1 +#define zzDIE return 1; +#define zzDONE return 0; + +#endif + +#ifdef USER_ZZMODE_STACK +# ifndef ZZSTACK_MAX_MODE +# define ZZSTACK_MAX_MODE 32 +# endif +# define ZZMAXSTK (ZZSTACK_MAX_MODE * 2) +#endif + +#ifndef DllExportPCCTS +#define DllExportPCCTS +#endif + +#ifdef PC +#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME +#define PCCTS_CASE_INSENSITIVE_FILE_NAME +#endif +#endif + +#ifdef PC32 +#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME +#define PCCTS_CASE_INSENSITIVE_FILE_NAME +#endif +#endif + +#ifdef __VMS +#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME +#define PCCTS_CASE_INSENSITIVE_FILE_NAME +#endif +#endif + +#ifdef __USE_PROTOS +#ifndef PCCTS_USE_STDARG +#define PCCTS_USE_STDARG +#endif +#endif + +#ifdef __STDC__ +#ifndef PCCTS_USE_STDARG +#define PCCTS_USE_STDARG +#endif +#endif + +#ifdef __cplusplus +#ifndef PCCTS_USE_STDARG +#define PCCTS_USE_STDARG +#endif +#endif + +#ifdef _MSC_VER +/*Turn off the warnings for: + unreferenced inline/local function has been removed +*/ +#pragma warning(disable : 4514) +/* function not expanded */ +#pragma warning(disable : 4710) +#endif + +#endif diff --git a/Tools/Source/TianoTools/Pccts/h/pcnames.bat b/Tools/Source/TianoTools/Pccts/h/pcnames.bat new file mode 100644 index 0000000000..8784aee9ab --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/pcnames.bat @@ -0,0 +1,11 @@ +ren aparser.c aparser.cpp +ren astbase.c astbase.cpp +ren atokenbu.c atokbuf.cpp +ren atokenbu.h atokbuf.h +ren atokenst.h atokstr.h +ren dlexerba.c dlexbase.cpp +ren dlexerba.h dlexbase.h +ren dlexer.c dlexer.cpp +ren list.c list.cpp +ren pblackbo.h pblckbox.h +ren pcctsast.c pcctsast.cpp diff --git a/Tools/Source/TianoTools/Pccts/h/slist.cpp b/Tools/Source/TianoTools/Pccts/h/slist.cpp new file mode 100644 index 0000000000..faf2fe4967 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/h/slist.cpp @@ -0,0 +1,116 @@ +/* + * SList.C + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public + * domain. An individual or company may do whatever they wish with + * source code distributed with SORCERER or the code generated by + * SORCERER, including the incorporation of SORCERER, or its output, into + * commerical software. + * + * We encourage users to develop software with SORCERER. However, we do + * ask that credit is given to us for developing SORCERER. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like SORCERER and have developed a nice tool with the + * output, please mention that you developed it using SORCERER. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * PCCTS 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1992-2000 + */ + +#define ANTLR_SUPPORT_CODE + +#include "SList.h" +#include "pccts_stdarg.h" // MR23 + +/* Iterate over a list of elements; returns ptr to a new element + * in list upon every call and NULL when no more are left. + * Very useful like this: + * + * cursor = mylist; + * while ( (p=mylist->iterate(&cursor)) ) { + * // place with element p + * } + * + * The cursor must be initialized to point to the list to iterate over. + */ +void *SList:: +iterate(SListNode **cursor) +{ + void *e; + + if ( cursor == NULL || *cursor==NULL ) return NULL; + if ( head == *cursor ) { *cursor = (*cursor)->next(); } + e = (*cursor)->elem(); + (*cursor) = (*cursor)->next(); + return e; +} + +/* add an element to end of list. */ +void SList:: +add(void *e) +{ + SListNode *p, *tail=NULL; + require(e!=NULL, "slist_add: attempting to add NULL list element"); + + p = new SListNode; + require(p!=NULL, "add: cannot alloc new list node"); + p->setElem(e); + if ( head == NULL ) + { + head = tail = p; + } + else /* find end of list */ + { + tail->setNext(p); + tail = p; + } +} + +void SList:: +lfree() +{ + SListNode *p,*q; + + if ( head==NULL ) return; /* empty list */ + for (p = head; p!=NULL; p=q) + { + q = p->next(); + free(p); + } +} + +PCCTS_AST *SList:: +to_ast(SList list) +{ + PCCTS_AST *t=NULL, *last=NULL; + SListNode *p; + + for (p = head; p!=NULL; p=p->next()) + { + PCCTS_AST *u = (PCCTS_AST *)p->elem(); + if ( last==NULL ) last = t = u; + else { last->setRight(u); last = u; } + } + return t; +} + +// MR23 +int SList::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + int iRet = vfprintf(pFile, pFormat, marker); + va_end( marker ); + return iRet; +} diff --git a/Tools/Source/TianoTools/Pccts/history.ps b/Tools/Source/TianoTools/Pccts/history.ps new file mode 100644 index 0000000000..e2600d5129 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/history.ps @@ -0,0 +1,473 @@ +%!PS-Adobe-3.0 +%%Creator: groff version 1.06 +%%DocumentNeededResources: font Times-Roman +%%+ font Times-Italic +%%+ font Courier +%%DocumentSuppliedResources: procset grops 1.06 0 +%%Pages: 3 +%%PageOrder: Ascend +%%Orientation: Portrait +%%EndComments +%%BeginProlog +%%BeginResource: procset grops 1.06 0 + +/setpacking where { + pop + currentpacking + true setpacking +} if + +/grops 120 dict dup begin + +% The ASCII code of the space character. +/SC 32 def + +/A /show load def +/B { 0 SC 3 -1 roll widthshow } bind def +/C { 0 exch ashow } bind def +/D { 0 exch 0 SC 5 2 roll awidthshow } bind def +/E { 0 rmoveto show } bind def +/F { 0 rmoveto 0 SC 3 -1 roll widthshow } bind def +/G { 0 rmoveto 0 exch ashow } bind def +/H { 0 rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def +/I { 0 exch rmoveto show } bind def +/J { 0 exch rmoveto 0 SC 3 -1 roll widthshow } bind def +/K { 0 exch rmoveto 0 exch ashow } bind def +/L { 0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def +/M { rmoveto show } bind def +/N { rmoveto 0 SC 3 -1 roll widthshow } bind def +/O { rmoveto 0 exch ashow } bind def +/P { rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def +/Q { moveto show } bind def +/R { moveto 0 SC 3 -1 roll widthshow } bind def +/S { moveto 0 exch ashow } bind def +/T { moveto 0 exch 0 SC 5 2 roll awidthshow } bind def + +% name size font SF - + +/SF { + findfont exch + [ exch dup 0 exch 0 exch neg 0 0 ] makefont + dup setfont + [ exch /setfont cvx ] cvx bind def +} bind def + +% name a c d font MF - + +/MF { + findfont + [ 5 2 roll + 0 3 1 roll % b + neg 0 0 ] makefont + dup setfont + [ exch /setfont cvx ] cvx bind def +} bind def + +/level0 0 def +/RES 0 def +/PL 0 def +/LS 0 def + +% Guess the page length. +% This assumes that the imageable area is vertically centered on the page. +% PLG - length + +/PLG { + gsave newpath clippath pathbbox grestore + exch pop add exch pop +} bind def + +% BP - + +/BP { + /level0 save def + 1 setlinecap + 1 setlinejoin + 72 RES div dup scale + LS { + 90 rotate + } { + 0 PL translate + } ifelse + 1 -1 scale +} bind def + +/EP { + level0 restore + showpage +} bind def + + +% centerx centery radius startangle endangle DA - + +/DA { + newpath arcn stroke +} bind def + +% x y SN - x' y' +% round a position to nearest (pixel + (.25,.25)) + +/SN { + transform + .25 sub exch .25 sub exch + round .25 add exch round .25 add exch + itransform +} bind def + +% endx endy startx starty DL - +% we round the endpoints of the line, so that parallel horizontal +% and vertical lines will appear even + +/DL { + SN + moveto + SN + lineto stroke +} bind def + +% centerx centery radius DC - + +/DC { + newpath 0 360 arc closepath +} bind def + + +/TM matrix def + +% width height centerx centery DE - + +/DE { + TM currentmatrix pop + translate scale newpath 0 0 .5 0 360 arc closepath + TM setmatrix +} bind def + +% these are for splines + +/RC /rcurveto load def +/RL /rlineto load def +/ST /stroke load def +/MT /moveto load def +/CL /closepath load def + +% fill the last path + +% amount FL - + +/FL { + currentgray exch setgray fill setgray +} bind def + +% fill with the ``current color'' + +/BL /fill load def + +/LW /setlinewidth load def +% new_font_name encoding_vector old_font_name RE - + +/RE { + findfont + dup maxlength dict begin + { + 1 index /FID ne { def } { pop pop } ifelse + } forall + /Encoding exch def + dup /FontName exch def + currentdict end definefont pop +} bind def + +/DEFS 0 def + +% hpos vpos EBEGIN - + +/EBEGIN { + moveto + DEFS begin +} bind def + +/EEND /end load def + +/CNT 0 def +/level1 0 def + +% llx lly newwid wid newht ht newllx newlly PBEGIN - + +/PBEGIN { + /level1 save def + translate + div 3 1 roll div exch scale + neg exch neg exch translate + % set the graphics state to default values + 0 setgray + 0 setlinecap + 1 setlinewidth + 0 setlinejoin + 10 setmiterlimit + [] 0 setdash + /setstrokeadjust where { + pop + false setstrokeadjust + } if + /setoverprint where { + pop + false setoverprint + } if + newpath + /CNT countdictstack def + userdict begin + /showpage {} def +} bind def + +/PEND { + clear + countdictstack CNT sub { end } repeat + level1 restore +} bind def + +end def + +/setpacking where { + pop + setpacking +} if +%%EndResource +%%IncludeResource: font Times-Roman +%%IncludeResource: font Times-Italic +%%IncludeResource: font Courier +grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL +792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron +/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space +/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft +/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four +/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C +/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash +/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q +/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase +/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger +/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut +/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash +/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar +/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus +/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu +/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright +/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde +/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute +/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis +/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls +/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute +/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve +/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex +/udieresis/yacute/thorn/ydieresis]def/Courier@0 ENC0/Courier RE/Times-Italic@0 +ENC0/Times-Italic RE/Times-Roman@0 ENC0/Times-Roman RE +%%EndProlog +%%Page: 1 1 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 13/Times-Roman@0 SF(The History of PCCTS)228.232 84 Q/F1 11/Times-Roman@0 +SF(The Purdue Compiler)190.468 108 Q(-Construction T)-.22 E(ool Set)-.88 E/F2 +10/Times-Italic@0 SF -.92(Te)262.245 144 S -.37(re).92 G(nce P).37 E(arr)-.8 E +/F3 10/Times-Roman@0 SF -.15(Pa)234.755 156 S(rr Research Corporation).15 E +(Minneapolis, Minnesota)239.39 168 Q(and)280.78 180 Q(Uni)239.315 192 Q -.15 +(ve)-.25 G(rsity of Minnesota).15 E +(Army High Performance Computing Research Center)180.38 204 Q F2 +([Updated 8-7-94])252.31 228 Q F1 .084(The PCCTS project be)97 259.6 R -.055 +(ga)-.165 G 2.834(na).055 G 2.833(sap)220.547 259.6 S(arser)240.876 259.6 Q +.083(-generator project for a graduate course at Purdue Uni-)-.22 F -.165(ve)72 +275.6 S 1.085(rsity in the F).165 F 1.086 +(all of 1988 taught by Hank Dietz\212 translator)-.165 F 1.086 +(-writing systems.)-.22 F 1.086(Under the guid-)6.586 F .627 +(ance of Professor Dietz, the parser generator)72 291.6 R 3.377(,A)-.44 G .626 +(NTLR \(originally called YUCC\), continued after)285.18 291.6 R .253 +(the termination of the course and e)72 307.6 R -.165(ve)-.275 G .254 +(ntually became the subject of T).165 F .254(erence P)-.77 F(arr')-.165 E 3.004 +(sM)-.605 G(aster')445.083 307.6 Q 3.004(st)-.605 G(hesis.)479.25 307.6 Q +(Originally)72 323.6 Q 4.092(,l)-.715 G -.165(ex)126.406 323.6 S 1.342 +(ical analysis w).165 F 1.342(as performed via ALX which w)-.11 F 1.342 +(as soon replaced by W)-.11 F 1.341(ill Cohen')-.44 F(s)-.605 E .594 +(DLG in the F)72 339.6 R .594(all of 1989 \(DF)-.165 F .595(A-based le)-.814 F +.595(xical-analyzer generator)-.165 F 3.345(,a)-.44 G .595(lso an of)367.188 +339.6 R .595(fshoot of the graduate)-.275 F(translation course\).)72 355.6 Q +.877(The alpha v)97 375.2 R .877(ersion of ANTLR w)-.165 F .877(as totally re) +-.11 F .876(written resulting in 1.00B.)-.275 F -1.221(Ve)6.376 G .876 +(rsion 1.00B w)1.221 F(as)-.11 E 1.577(released via an internet ne)72 391.2 R +1.577(wsgroup \(comp.compilers\) posting in February of 1990 and quickly)-.275 +F -.055(ga)72 407.2 S .356(thered a lar).055 F .356(ge follo)-.198 F 3.106 +(wing. 1.00B)-.275 F .356(generated only LL\(1\) parsers, b)3.106 F .356 +(ut allo)-.22 F .356(wed the mer)-.275 F .356(ged descrip-)-.198 F 1.859 +(tion of le)72 423.2 R 1.859(xical and syntactic analysis.)-.165 F 1.86 +(It had rudimentary attrib)7.359 F 1.86(ute handling similar to that of)-.22 F +-.55 -1.32(YA C)72 439.2 T 3.549(Ca)1.32 G .799 +(nd did not incorporate rule parameters or return v)109.231 439.2 R .798 +(alues; do)-.275 F(wnw)-.275 E .798(ard inheritance w)-.11 F .798(as v)-.11 F +(ery)-.165 E -.165(aw)72 455.2 S(kw).165 E 6.433(ard. 1.00B-generated)-.11 F +3.684(parsers terminated upon the \214rst syntax error)6.433 F 9.184(.L)-.605 G +-.165(ex)440.916 455.2 S 3.684(ical classes).165 F(\(modes\) were not allo)72 +471.2 Q(wed and DLG did not ha)-.275 E .33 -.165(ve a)-.22 H 2.75(ni).165 G +(nteracti)305.959 471.2 Q .33 -.165(ve m)-.275 H(ode.).165 E .831 +(Upon starting his Ph.D. at Purdue in the F)97 490.8 R .83(all of 1990, T)-.165 +F .83(erence P)-.77 F .83(arr be)-.165 F -.055(ga)-.165 G 3.58(nt).055 G .83 +(he second total)436.351 490.8 R(re)72 506.8 Q 1.646(write of ANTLR.)-.275 F +1.646(The method by which grammars may be practically analyzed to generate) +7.146 F/F4 11/Times-Italic@0 SF(LL)72.638 522.8 Q F1(\().583 E F4(k).396 E F1 +3.849(\)l).737 G 1.099(ookahead information w)105.703 522.8 R 1.099(as disco) +-.11 F -.165(ve)-.165 G 1.099(red in August of 1990 just before his return.) +.165 F -1.221(Ve)6.598 G(rsion)1.221 E .626 +(1.00 incorporated this algorithm and included the AST mechanism, le)72 538.8 R +.626(xical classes, error classes,)-.165 F .354(and automatic error reco)72 +554.8 R -.165(ve)-.165 G .353(ry; code quality and portability were higher).165 +F 5.853(.I)-.605 G 3.103(nF)395.965 554.8 S .353(ebruary of 1992 1.00)410.684 +554.8 R -.11(wa)72 570.8 S 2.76(sr).11 G .01 +(eleased via an article in SIGPLAN Notices.)95.418 570.8 R .01 +(Peter Dahl, Ph.D. candidate, and Professor Matt)5.51 F(O'K)72 586.8 Q 2.074 +(eefe \(both at the Uni)-.275 F -.165(ve)-.275 G 2.073 +(rsity of Minnesota\) tested this v).165 F 2.073(ersion e)-.165 F(xtensi)-.165 +E -.165(ve)-.275 G(ly).165 E 7.573(.D)-.715 G 2.073(ana Hogg)448.522 586.8 R +(att)-.055 E .078(\(Micro Data Base Systems, Inc.\) came up with the idea of e\ +rror grouping \(strings attached to non-)72 602.8 R +(terminals\) and tested 1.00 hea)72 618.8 Q(vily)-.22 E(.)-.715 E -1.221(Ve)97 +638.4 S .878(rsion 1.06 w)1.221 F .877 +(as released in December 1992 and represented a lar)-.11 F .877 +(ge feature enhancement)-.198 F -.165(ove)72 654.4 S 3.648(r1).165 G 3.648 +(.00. F)100.365 654.4 R .898(or e)-.165 F .899 +(xample, rudimentary semantic predicates were introduced, error messages were) +-.165 F 2.281(signi\214cantly impro)72 670.4 R -.165(ve)-.165 G 5.031(df).165 G +(or)181.953 670.4 Q F4(k)5.427 E F1 2.281 +(>1 lookahead and ANTLR parsers could indicate that lookahead).737 F 1.381 +(fetches were to occur only when necessary for the parse \(normally)72 686.4 R +4.131(,t)-.715 G 1.381(he lookahead `)387.051 686.4 R(`pipe')-.814 E 4.132('w) +-.814 G(as)494.837 686.4 Q 1.182(constantly full\).)72 702.4 R 1.182 +(Russell Quong joined the project in the Spring of 1992 to aid in the semantic) +6.682 F .681(predicate design.)72 718.4 R(Be)6.181 E .681(ginning and adv)-.165 +F .682(anced tutorials were created and released as well.)-.275 F 3.432(Am) +6.182 G(ak)485.179 718.4 Q(e-)-.11 E .993(\214le generator w)72 734.4 R .993 +(as included that sets up dependencies and such correctly for ANTLR and DLG.) +-.11 F EP +%%Page: 2 2 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 11/Times-Roman@0 SF 2.75(-2-)278.837 52 S -1.221(Ve)72 88 S 1.414(ry fe) +1.221 F 4.164(w1)-.275 G 1.414(.00 incompatibilities were introduced \(1.00 w) +122.81 88 R 1.415(as quite dif)-.11 F 1.415(ferent from 1.00B in some)-.275 F +(areas\).)72 104 Q 1.089(1.10 w)97 123.6 R 1.088 +(as released on August 31, 1993 and incorporated b)-.11 F 1.088(ug \214x)-.22 F +1.088(es, a fe)-.165 F 3.838(wf)-.275 G 1.088(eature enhance-)433.59 123.6 R +3.112(ments and a major ne)72 139.6 R 5.863(wc)-.275 G(apability \212)196.957 +139.6 Q 3.113(an arbitrary lookahead operator \(syntactic predicate\),)5.863 F +/F1 11/Courier@0 SF(\(alpha\)?beta)72 155.6 Q F0 6.754(.T)C 1.254 +(his feature w)167.425 155.6 R 1.254 +(as co-designed with Professor Russell Quong also at Purdue.)-.11 F 3.297 -.88 +(To s)72 171.6 T 1.537 +(upport in\214nite lookahead, a preprocessor \215ag, ZZINF_LOOK, w).88 F 1.537 +(as created that forced the)-.11 F .21(ANTLR\(\) macro to tok)72 187.6 R .21 +(enize all input prior to parsing.)-.11 F .209(Hence, at an)5.709 F 2.959(ym) +-.165 G .209(oment, an action or predi-)389.215 187.6 R .936 +(cate can see the entire input sentence.)72 203.6 R .936 +(The predicate mechanism of 1.06 w)6.436 F .937(as e)-.11 F .937 +(xtended to allo)-.165 F(w)-.275 E .55 +(multiple predicates to be hoisted; the syntactic conte)72 219.6 R .55 +(xt of a predicate w)-.165 F .55(as also mo)-.11 F -.165(ve)-.165 G 3.299(da) +.165 G .549(long with)461.585 219.6 R(the predicate.)72 235.6 Q .754 +(In February of 1994, SORCERER \(a simple tree-parser generator\) w)97 255.2 R +.755(as released.)-.11 F .755(This tool)6.255 F(allo)72 271.2 Q .6(ws the user\ + to parse child-sibling trees by specifying a grammar rather than b)-.275 F +.599(uilding a recur)-.22 F(-)-.22 E(si)72 287.2 Q -.165(ve)-.275 G 1.39 +(-descent tree w).165 F(alk)-.11 E 1.391(er by hand.)-.11 F -.88(Wo)6.891 G +1.391(rk to).88 F -.11(wa)-.275 G 1.391 +(rds a library of tree transformations is underw).11 F(ay)-.11 E(.)-.715 E .581 +(Aaron Sa)72 303.2 R(wde)-.165 E 3.331(ya)-.165 G 3.331(tT)145.531 303.2 S .581 +(he Uni)158.641 303.2 R -.165(ve)-.275 G .58 +(rsity of Minnesota became a second author of SORCERER after the).165 F +(initial release.)72 319.2 Q .627(On April 1, 1994, PCCTS 1.20 w)97 338.8 R +.627(as released.)-.11 F .627(This w)6.127 F .627(as the \214rst v)-.11 F .627 +(ersion to acti)-.165 F -.165(ve)-.275 G .627(ly support).165 F 1.664 +(C++ output.)72 354.8 R 1.664(It also included important \214x)7.164 F 1.663 +(es re)-.165 F -.055(ga)-.165 G 1.663 +(rding semantic predicates and \(..\)+ subrules.).055 F(This v)72 370.8 Q +(ersion also introduced tok)-.165 E(en classes, the `)-.11 E(`)-.814 E/F2 11 +/Times-Italic@0 SF(not)A F0 1.628 -.814('' o)D(perator).814 E 2.75(,a)-.44 G +(nd tok)355.294 370.8 Q(en ranges.)-.11 E .764 +(On June 19, 1994, SORCERER 1.00B9 w)97 390.4 R .765(as released.)-.11 F .765 +(Gary Funck of Intrepid T)6.265 F(echnology)-.77 E .807 +(joined the SORCERER team and pro)72 406.4 R .807(vided v)-.165 F .807(ery v) +-.165 F .807(aluable suggestions re)-.275 F -.055(ga)-.165 G .806(rding the `) +.055 F(`transform')-.814 E(')-.814 E(mode of SORCERER.)72 422.4 Q 1.137 +(On August 8, 1994, PCCTS 1.21 w)97 442 R 1.137(as released.)-.11 F 1.138 +(It mainly cleaned up the C++ output and)6.637 F(included a number of b)72 458 +Q(ug \214x)-.22 E(es.)-.165 E .316(From the 1.21 release forw)97 477.6 R .316 +(ard, the maintenance and support of all PCCTS tools will be pri-)-.11 F 1.557 +(marily pro)72 493.6 R 1.557(vided by P)-.165 F 1.557 +(arr Research Corporation, Minneapolis MN---an or)-.165 F -.055(ga)-.198 G +1.558(nization founded on).055 F 1.616(the principles of e)72 509.6 R 1.616 +(xcellence in research and inte)-.165 F 1.616(grity in b)-.165 F 1.616 +(usiness; we are de)-.22 F -.22(vo)-.275 G 1.616(ted to pro).22 F(viding)-.165 +E 1.202(really cool softw)72 525.6 R 1.202(are tools.)-.11 F 1.202 +(Please see \214le PCCTS.FUTURE for more information.)6.702 F 1.203(All PCCTS) +6.703 F(tools currently in the public domain will continue to be in the public\ + domain.)72 541.6 Q 1.198(Looking to)97 561.2 R -.11(wa)-.275 G 1.198 +(rds the future, a graphical user).11 F(-interf)-.22 E 1.197 +(ace is in the design phase.)-.11 F 1.197(This w)6.697 F(ould)-.11 E(allo)72 +577.2 Q 2.753(wu)-.275 G .003(sers to vie)104.42 577.2 R 2.753(wt)-.275 G .004 +(he syntax diagram representation of their grammars and w)162.509 577.2 R .004 +(ould highlight non-)-.11 F 1.181(deterministic productions.)72 593.2 R -.165 +(Pa)6.681 G 1.18(rsing can be traced graphically as well.).165 F 1.18 +(This system will be b)6.68 F(uilt)-.22 E .167(using a multiplatform windo)72 +609.2 R 2.917(wl)-.275 G(ibrary)211.73 609.2 Q 5.667(.W)-.715 G 2.917(ea) +255.204 609.2 S .168(lso anticipate the introduction of a sophisticated error) +267.889 609.2 R(handling mechanism called `)72 625.2 Q(`parser e)-.814 E +(xception handling')-.165 E 2.75('i)-.814 G 2.75(nan)327.431 625.2 S +(ear future release.)348.815 625.2 Q(Currently)97 644.8 Q 3.019(,P)-.715 G .269 +(CCTS is used at o)150.333 644.8 R -.165(ve)-.165 G 3.019(r1).165 G .269 +(000 kno)253.098 644.8 R .268(wn academic, go)-.275 F -.165(ve)-.165 G .268 +(rnment, and commercial sites).165 F .859(in 37 countries.)72 660.8 R .859 +(Of course, the true number of users is unkno)6.359 F .859(wn due to the lar) +-.275 F .859(ge number of ftp)-.198 F(sites.)72 676.8 Q EP +%%Page: 3 3 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 11/Times-Roman@0 SF 2.75(-3-)278.837 52 S(Credits)272.11 88 Q .44 LW +472.162 103.75 103.838 103.75 DL(Idea/T)134.236 117 Q 52.987(ool Coder)-.88 F +(Co-designer\(s\))345.436 117 Q 281.334 103.75 281.334 124.75 DL 209.273 103.75 +209.273 124.75 DL 209.273 124.75 103.838 124.75 DL 103.838 126.75 209.273 +126.75 DL 281.334 124.75 209.273 124.75 DL 209.273 126.75 281.334 126.75 DL +472.162 124.75 281.334 124.75 DL 281.334 126.75 472.162 126.75 DL(ANTLR 1.00A) +109.338 140 Q -.77(Te)217.523 140 S(rence P).77 E 13.75(arr Hank)-.165 F(Dietz) +2.75 E 82.83(ALX T)109.338 156 R(erence P)-.77 E 13.75(arr Hank)-.165 F(Dietz) +2.75 E(ANTLR 1.00B)109.338 172 Q -.77(Te)217.523 172 S(rence P).77 E 13.75 +(arr Hank)-.165 F(Dietz, W)2.75 E(ill Cohen)-.44 E(DLG 1.00B)109.338 188 Q -.44 +(Wi)217.523 188 S(ll Cohen).44 E -.77(Te)289.584 188 S(rence P).77 E(arr)-.165 +E 2.75(,H)-.44 G(ank Dietz)358.147 188 Q(NF)109.338 204 Q 2.75(AR)-.814 G +30.778(elabelling W)140.611 204 R(ill Cohen)-.44 E/F1 11/Times-Italic@0 SF(LL) +109.976 220 Q F0(\().583 E F1(k).396 E F0 2.75(\)a).737 G 40.447(nalysis T) +143.768 220 R(erence P)-.77 E 13.75(arr Hank)-.165 F(Dietz)2.75 E(ANTLR 1.00) +109.338 236 Q -.77(Te)217.523 236 S(rence P).77 E 13.75(arr Hank)-.165 F +(Dietz, W)2.75 E(ill Cohen)-.44 E(DLG 1.00)109.338 252 Q -.44(Wi)217.523 252 S +(ll Cohen).44 E -.77(Te)289.584 252 S(rence P).77 E(arr)-.165 E 2.75(,H)-.44 G +(ank Dietz)358.147 252 Q(ANTLR 1.06)109.338 268 Q -.77(Te)217.523 268 S +(rence P).77 E 13.75(arr W)-.165 F(ill Cohen, Russell Quong, Hank Dietz)-.44 E +(DLG 1.06)109.338 284 Q -.44(Wi)217.523 284 S(ll Cohen).44 E -.77(Te)289.584 +284 S(rence P).77 E(arr)-.165 E 2.75(,H)-.44 G(ank Dietz)358.147 284 Q +(ANTLR 1.10)109.338 300 Q -.77(Te)217.523 300 S(rence P).77 E 13.75(arr W)-.165 +F(ill Cohen, Russell Quong)-.44 E(ANTLR 1.20)109.338 316 Q -.77(Te)217.523 316 +S(rence P).77 E 13.75(arr W)-.165 F(ill Cohen, Russell Quong)-.44 E(ANTLR 1.21) +109.338 332 Q -.77(Te)217.523 332 S(rence P).77 E 13.75(arr Russell)-.165 F +(Quong)2.75 E(DLG 1.10)109.338 348 Q -.44(Wi)217.523 348 S(ll Cohen).44 E -.77 +(Te)289.584 348 S(rence P).77 E(arr)-.165 E(DLG 1.20)109.338 364 Q -.44(Wi) +217.523 364 S(ll Cohen).44 E -.77(Te)289.584 364 S(rence P).77 E(arr)-.165 E +(DLG 1.21)109.338 380 Q -.77(Te)217.523 380 S(rence P).77 E(arr)-.165 E +(Semantic predicates)109.338 396 Q -.77(Te)217.523 396 S(rence P).77 E 13.75 +(arr Russell)-.165 F(Quonq)2.75 E(Syntactic predicates)109.338 412 Q -.77(Te) +217.523 412 S(rence P).77 E 13.75(arr Russell)-.165 F(Quonq)2.75 E +(SORCERER 1.00A)109.338 428 Q -.77(Te)217.523 428 S(rence P).77 E(arr)-.165 E +(SORCERER 1.00B)109.338 444 Q -.77(Te)217.523 444 S(rence P).77 E 13.75 +(arr Aaron)-.165 F(Sa)2.75 E(wde)-.165 E(y)-.165 E(SORCERER 1.00B9)109.338 460 +Q -.77(Te)217.523 460 S(rence P).77 E 13.75(arr Aaron)-.165 F(Sa)2.75 E(wde) +-.165 E 1.43 -.715(y, G)-.165 H(ary Funck).715 E 472.162 467.75 103.838 467.75 +DL 472.162 103.75 472.162 467.75 DL 103.838 103.75 103.838 467.75 DL EP +%%Trailer +end +%%EOF diff --git a/Tools/Source/TianoTools/Pccts/history.txt b/Tools/Source/TianoTools/Pccts/history.txt new file mode 100644 index 0000000000..89ad8408c9 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/history.txt @@ -0,0 +1,186 @@ + + + + The History of PCCTS + + The Purdue Compiler-Construction Tool Set + + + Terence Parr + Parr Research Corporation + Minneapolis, Minnesota + and + University of Minnesota + Army High Performance Computing Research Center + + [Updated 8-7-94] + + + The PCCTS project began as a parser-generator project for a gra- +duate course at Purdue University in the Fall of 1988 taught by Hank +Dietz- translator-writing systems. Under the guidance of Professor +Dietz, the parser generator, ANTLR (originally called YUCC), continued +after the termination of the course and eventually became the subject +of Terence Parr's Master's thesis. Originally, lexical analysis was +performed via ALX which was soon replaced by Will Cohen's DLG in the +Fall of 1989 (DFA-based lexical-analyzer generator, also an offshoot +of the graduate translation course). + + The alpha version of ANTLR was totally rewritten resulting in +1.00B. Version 1.00B was released via an internet newsgroup +(comp.compilers) posting in February of 1990 and quickly gathered a +large following. 1.00B generated only LL(1) parsers, but allowed the +merged description of lexical and syntactic analysis. It had rudimen- +tary attribute handling similar to that of YACC and did not incor- +porate rule parameters or return values; downward inheritance was very +awkward. 1.00B-generated parsers terminated upon the first syntax +error. Lexical classes (modes) were not allowed and DLG did not have +an interactive mode. + + Upon starting his Ph.D. at Purdue in the Fall of 1990, Terence +Parr began the second total rewrite of ANTLR. The method by which +grammars may be practically analyzed to generate LL(k) lookahead +information was discovered in August of 1990 just before his return. +Version 1.00 incorporated this algorithm and included the AST mechan- +ism, lexical classes, error classes, and automatic error recovery; +code quality and portability were higher. In February of 1992 1.00 +was released via an article in SIGPLAN Notices. Peter Dahl, Ph.D. +candidate, and Professor Matt O'Keefe (both at the University of Min- +nesota) tested this version extensively. Dana Hoggatt (Micro Data +Base Systems, Inc.) came up with the idea of error grouping (strings +attached to non-terminals) and tested 1.00 heavily. + + Version 1.06 was released in December 1992 and represented a +large feature enhancement over 1.00. For example, rudimentary seman- +tic predicates were introduced, error messages were significantly +improved for k>1 lookahead and ANTLR parsers could indicate that loo- +kahead fetches were to occur only when necessary for the parse + + + + Page 1 + + PCCTS + + +(normally, the lookahead "pipe" was constantly full). Russell Quong +joined the project in the Spring of 1992 to aid in the semantic predi- +cate design. Beginning and advanced tutorials were created and +released as well. A makefile generator was included that sets up +dependencies and such correctly for ANTLR and DLG. Very few 1.00 +incompatibilities were introduced (1.00 was quite different from 1.00B +in some areas). + + 1.10 was released on August 31, 1993 and incorporated bug fixes, +a few feature enhancements and a major new capability - an arbitrary +lookahead operator (syntactic predicate), (alpha)?beta. This feature +was co-designed with Professor Russell Quong also at Purdue. To sup- +port infinite lookahead, a preprocessor flag, ZZINF_LOOK, was created +that forced the ANTLR() macro to tokenize all input prior to parsing. +Hence, at any moment, an action or predicate can see the entire input +sentence. The predicate mechanism of 1.06 was extended to allow mul- +tiple predicates to be hoisted; the syntactic context of a predicate +was also moved along with the predicate. + + In February of 1994, SORCERER (a simple tree-parser generator) +was released. This tool allows the user to parse child-sibling trees +by specifying a grammar rather than building a recursive-descent tree +walker by hand. Work towards a library of tree transformations is +underway. Aaron Sawdey at The University of Minnesota became a second +author of SORCERER after the initial release. + + On April 1, 1994, PCCTS 1.20 was released. This was the first +version to actively support C++ output. It also included important +fixes regarding semantic predicates and (..)+ subrules. This version +also introduced token classes, the "not" operator, and token ranges. + + On June 19, 1994, SORCERER 1.00B9 was released. Gary Funck of +Intrepid Technology joined the SORCERER team and provided very valu- +able suggestions regarding the "transform" mode of SORCERER. + + On August 8, 1994, PCCTS 1.21 was released. It mainly cleaned up +the C++ output and included a number of bug fixes. + + From the 1.21 release forward, the maintenance and support of all +PCCTS tools will be primarily provided by Parr Research Corporation, +Minneapolis MN---an organization founded on the principles of excel- +lence in research and integrity in business; we are devoted to provid- +ing really cool software tools. Please see file PCCTS.FUTURE for more +information. All PCCTS tools currently in the public domain will con- +tinue to be in the public domain. + + Looking towards the future, a graphical user-interface is in the +design phase. This would allow users to view the syntax diagram +representation of their grammars and would highlight nondeterministic +productions. Parsing can be traced graphically as well. This system +will be built using a multiplatform window library. We also antici- +pate the introduction of a sophisticated error handling mechanism +called "parser exception handling" in a near future release. + + + + + Page 2 + + PCCTS + + + Currently, PCCTS is used at over 1000 known academic, government, +and commercial sites in 37 countries. Of course, the true number of +users is unknown due to the large number of ftp sites. + Credits + +_____________________________________________________________________________ +_____________________________________________________________________________ +|ANTLR 1.00A Terence Parr Hank Dietz | +|ALX Terence Parr Hank Dietz | +|ANTLR 1.00B Terence Parr Hank Dietz, Will Cohen | +|DLG 1.00B Will Cohen Terence Parr, Hank Dietz | +|NFA Relabelling Will Cohen | +|LL(k) analysis Terence Parr Hank Dietz | +|ANTLR 1.00 Terence Parr Hank Dietz, Will Cohen | +|DLG 1.00 Will Cohen Terence Parr, Hank Dietz | +|ANTLR 1.06 Terence Parr Will Cohen, Russell Quong, Hank Dietz| +|DLG 1.06 Will Cohen Terence Parr, Hank Dietz | +|ANTLR 1.10 Terence Parr Will Cohen, Russell Quong | +|ANTLR 1.20 Terence Parr Will Cohen, Russell Quong | +|ANTLR 1.21 Terence Parr Russell Quong | +|DLG 1.10 Will Cohen Terence Parr | +|DLG 1.20 Will Cohen Terence Parr | +|DLG 1.21 Terence Parr | +|Semantic predicates Terence Parr Russell Quonq | +|Syntactic predicates Terence Parr Russell Quonq | +|SORCERER 1.00A Terence Parr | +|SORCERER 1.00B Terence Parr Aaron Sawdey | +|SORCERER 1.00B9 Terence Parr Aaron Sawdey, Gary Funck | +|___________________________________________________________________________| + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page 3 + diff --git a/Tools/Source/TianoTools/Pccts/makefile b/Tools/Source/TianoTools/Pccts/makefile new file mode 100644 index 0000000000..f9b2dd2b9b --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/makefile @@ -0,0 +1,66 @@ +# +# Main makefile for PCCTS 1.33MR33 /* MRXXX */ +# +# Terence Parr +# Parr Research Corporation +# +# verbosity versus silence... +PSss= +# +# this can be set to /user/local/bin etc... +BINDIR=bin +# This part added by Thomas Herter, M"unchen, Germany. See also manpages +# target. +MANDIR=$(HOME)/man +MANEXT=1 +MANFILES=dlg/dlg.1 antlr/antlr.1 + +#CC=cc +#CC=gcc +#COPT=-O2 + +pccts: + @echo " " + @echo " Welcome to PCCTS 1.33MR33 installation" + @echo " " + @echo " (Version 1.33 Maintenance Release #33)" # mrxxx + @echo " " + @echo " Released 19 April 2002" + @echo " " + @echo " Featuring" + @echo " ANTLR -- ANother Tool for Language Recognition" + @echo " DLG -- DFA-based Lexical Analyzer Generator" + @echo " SORCERER -- Source-to-source translator (tree walker)" + @echo " " + @echo " http://www.antlr.org" + @echo " " + @echo " Trouble reports to tmoog@polhode.com" + @echo " Additional PCCTS 1.33 information at" + @echo " http://www.polhode.com" + @echo + @echo + @echo "To substitute gcc for CC to invoke compiler: make CC=gcc" + @echo "If there are problems with cr and lf try: unzip -a ..." + @echo +# + @if [ ! -d $(BINDIR) ] ; then mkdir $(BINDIR) ; fi + @echo Making executables... + (cd ./antlr; $(MAKE) CC="$(CC)" COPT="$(COPT)") + @echo antlr executable now in $(BINDIR) + (cd ./dlg; $(MAKE) CC="$(CC)" COPT="$(COPT)") + @echo dlg executable now in $(BINDIR) + @echo + @echo " PCCTS 1.33MR33 installation complete" # MRXXX + +clean: + (cd ./antlr; $(MAKE) -s clean) + (cd ./dlg; $(MAKE) -s clean) + + +manpages: + # mkdir -p $(MANDIR)/man$(MANEXT) + if [ ! -d $(MANDIR) ] ; then \ + mkdir $(MANDIR) ; fi + if [ ! -d $(MANDIR)/man$(MANEXT) ] ; then \ + mkdir $(MANDIR)/man$(MANEXT); fi + cp -p $(MANFILES) $(MANDIR)/man$(MANEXT) diff --git a/Tools/Source/TianoTools/Pccts/support/genmk/genmk.c b/Tools/Source/TianoTools/Pccts/support/genmk/genmk.c new file mode 100644 index 0000000000..4952a30b38 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/support/genmk/genmk.c @@ -0,0 +1,1063 @@ +/* + * genmk -- a program to make makefiles for PCCTS + * + * ANTLR 1.33MR23 + * Terence John Parr 1989 - 2000 + * Purdue University + * U of MN + */ + +#include +#include +#include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */ + +#ifdef VAXC +#define DIE return 0; +#define DONE return 1; +#else +#define DIE return 1; +#define DONE return 0; +#endif + +#ifndef require +#define require(expr, err) {if ( !(expr) ) fatal(err);} +#endif + +#define MAX_FILES 50 +#define MAX_CFILES 1600 +#define MAX_SFILES 50 +#define MAX_SORS 50 +#define MAX_CLASSES 50 + +char *RENAME_OBJ_FLAG="-o", + *RENAME_EXE_FLAG="-o"; + +char *dlg = "parser.dlg"; +char *err = "err.c"; +char *hdr = "stdpccts.h"; +char *tok = "tokens.h"; +char *mode = "mode.h"; +char *scan = "scan"; + +char ATOKENBUFFER_O[100]; +char APARSER_O[100]; +char ASTBASE_O[100]; +char PCCTSAST_O[100]; +char LIST_O[100]; +char DLEXERBASE_O[100]; + +/* Option flags */ +static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES]; +static char *cfiles[MAX_CFILES]; +static char *sfiles[MAX_SORS][MAX_SFILES],*sclasses[MAX_SORS]; +static int num_sfiles[MAX_SORS]; /*sorcerer files in group */ +static int num_sors = 0; /*sorcerer groups */ +static int num_files = 0; /* grammar files */ +static int num_cfiles = 0; /* additional C/C++ files */ +static int num_classes = 0; /* ANTLR classes */ +static int user_lexer = 0; +static char *user_token_types = NULL; +static int gen_CPP = 0; +static char *outdir="."; +static char *dlg_class = "DLGLexer"; +static int gen_trees = 0; +static int gen_hoist = 0; +static int nondef_comp = 0; /* 1=compiler is non default */ +static char *compilerCCC="CC"; +static char *compilerCC="cc"; +static char *pccts_path="/usr/local/pccts"; + +#ifdef __STDC__ +void help(void); +void mk(char *project, char **files, int n, int argc, char **argv); +void pfiles(char **files, int n, char *suffix); +void fatal(char *msg); +void warn(char *msg); +#else +void help(); +void mk(); +void pfiles(); +void fatal(); +void warn(); +#endif + +typedef struct _Opt { + char *option; + int arg; +#ifdef __cplusplus + void (*process)(...); +#else + void (*process)(); +#endif + char *descr; + } Opt; + +#ifdef __STDC__ +static void ProcessArgs(int, char **, Opt *); +#else +static void ProcessArgs(); +#endif + +static void +#ifdef __STDC__ +pProj(char *s, char *t ) +#else +pProj( s, t ) +char *s; +char *t; +#endif +{ + project = t; +} + +static void +#ifdef __STDC__ +pUL( char *s ) +#else +pUL( s ) +char *s; +#endif +{ + user_lexer = 1; +} + +static void +#ifdef __STDC__ +pCPP( char *s ) +#else +pCPP( s ) +char *s; +#endif +{ + gen_CPP = 1; +} + +static void +#ifdef __STDC__ +pUT( char *s, char *t ) +#else +pUT( s, t ) +char *s; +char *t; +#endif +{ + user_token_types = t; +} + +static void +#ifdef __STDC__ +pTrees( char *s ) +#else +pTrees( s ) +char *s; +#endif +{ + gen_trees = 1; +} + +static void +#ifdef __STDC__ +pHoist( char *s ) +#else +pHoist( s ) +char *s; +#endif +{ + gen_hoist = 1; +} + +static void +#ifdef __STDC__ +pSor( char *s ) +#else +pSor( s ) +char *s; +#endif +{ + require(num_sors0 ) { + warn("can't define classes w/o C++ mode; turning on C++ mode...\n"); + gen_CPP=1; + } + if (!gen_CPP && num_sors) { + warn("can't define sorcerer group in C mode (yet); turning on C++ mode...\n"); + gen_CPP=1; + } + if ( gen_CPP && num_classes==0 ) { + fatal("must define classes >0 grammar classes in C++ mode\n"); + } + + mk(project, files, num_files, argc, argv); + DONE; +} + +#ifdef __STDC__ +void help(void) +#else +void help() +#endif +{ + Opt *p = options; + static char buf[1000+1]; + + fprintf(stderr, "genmk [options] f1.g ... fn.g\n"); + while ( p->option!=NULL && *(p->option) != '*' ) + { + buf[0]='\0'; + if ( p->arg ) sprintf(buf, "%s ___", p->option); + else strcpy(buf, p->option); + fprintf(stderr, "\t%-16s %s\n", buf, p->descr); + p++; + } +} + +#ifdef __STDC__ +void mk(char *project, char **files, int n, int argc, char **argv) +#else +void mk(project, files, n, argc, argv) +char *project; +char **files; +int n; +int argc; +char **argv; +#endif +{ + int i,j; + + printf("#\n"); + printf("# PCCTS makefile for: "); + pfiles(files, n, NULL); + printf("\n"); + printf("#\n"); + printf("# Created from:"); + for (i=0; i0) { + printf("SOR_H = $(PCCTS)%ssorcerer%sh\n", DirectorySymbol, DirectorySymbol); + printf("SOR_LIB = $(PCCTS)%ssorcerer%slib\n", + DirectorySymbol, DirectorySymbol); + } + printf("BIN = $(PCCTS)%sbin\n", DirectorySymbol); + printf("ANTLR = $(BIN)%santlr\n", DirectorySymbol); + printf("DLG = $(BIN)%sdlg\n", DirectorySymbol); + if (num_sors>0) printf("SOR = $(BIN)%ssor\n", DirectorySymbol); + printf("CFLAGS = -I. -I$(ANTLR_H)"); + if (num_sors>0) printf(" -I$(SOR_H)"); + if ( strcmp(outdir, ".")!=0 ) printf(" -I%s", outdir); + printf(" $(COTHER)"); + printf("\n"); + printf("AFLAGS ="); + if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir); + if ( user_lexer ) printf(" -gx"); + if ( gen_CPP ) printf(" -CC"); + if ( strcmp(hdr,"stdpccts.h")!=0 ) printf(" -gh %s", hdr); + if ( gen_trees ) printf(" -gt"); + if ( gen_hoist ) { + printf(" -mrhoist on") ; + } else { + printf(" -mrhoist off"); + }; + printf(" $(AOTHER)"); + printf("\n"); + printf("DFLAGS = -C2 -i"); + if ( gen_CPP ) printf(" -CC"); + if ( strcmp(dlg_class,"DLGLexer")!=0 ) printf(" -cl %s", dlg_class); + if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir); + printf(" $(DOTHER)"); + printf("\n"); + if (num_sors>0) + { + printf("SFLAGS = -CPP"); + if ( strcmp(outdir,".")!=0 ) printf(" -out-dir %s", outdir); + printf(" $(SOTHER)\n"); + } + printf("GRM = "); + pfiles(files, n, NULL); + printf("\n"); + printf("SRC = "); + if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT); + else pfiles(files, n, "c"); + if ( gen_CPP ) { + printf(" \\\n\t"); + pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT); + printf(" \\\n\t"); + printf("$(ANTLR_H)%s%s", DirectorySymbol, APARSER_C); + if ( !user_lexer ) printf(" $(ANTLR_H)%s%s", DirectorySymbol, DLEXERBASE_C); + if ( gen_trees ) { + printf(" \\\n\t"); + printf("$(ANTLR_H)%s%s", DirectorySymbol, ASTBASE_C); + printf(" $(ANTLR_H)%s%s", DirectorySymbol, PCCTSAST_C); +/* printf(" $(ANTLR_H)%s%s", DirectorySymbol, LIST_C); */ + printf(" \\\n\t"); + } + printf(" $(ANTLR_H)%s%s", DirectorySymbol, ATOKENBUFFER_C); + } + if ( !user_lexer ) { + if ( gen_CPP ) printf(" $(SCAN)%s", CPP_FILE_SUFFIX); + else printf(" %s$(SCAN).c", DIR()); + } + if ( !gen_CPP ) printf(" $(ERR).c"); + for (i=0;i0) + printf(" \\\n\t$(SOR_LIB)%sSTreeParser.cpp", DirectorySymbol); + if (num_cfiles>0) + { + printf(" \\\n\t"); + pfiles(cfiles,num_cfiles,NULL); + } + printf("\n\n"); + printf("OBJ = "); + pfiles(files, n, "o"); + if ( gen_CPP ) { + printf(" \\\n\t"); + pclasses(classes, num_classes, "o"); + printf(" \\\n\t"); + printf("%s%s", DIR(), APARSER_O); + if ( !user_lexer ) { + printf(" %s%s", DIR(), DLEXERBASE_O); + } + if ( gen_trees ) { + printf(" \\\n\t"); + printf("%s%s", DIR(), ASTBASE_O); + printf(" %s%s", DIR(), PCCTSAST_O); +/* printf(" %s%s", DIR(), LIST_O); */ + printf(" \\\n\t"); + } + printf(" %s%s", DIR(), ATOKENBUFFER_O); + } + if ( !user_lexer ) { + if ( gen_CPP ) printf(" $(SCAN)%s", OBJ_FILE_SUFFIX); + else printf(" %s$(SCAN)%s", DIR(), OBJ_FILE_SUFFIX); + } + if ( !gen_CPP ) printf(" $(ERR)%s", OBJ_FILE_SUFFIX); + for (i=0;i0) printf(" \\\n\tSTreeParser.o"); + if (num_cfiles>0) + { + printf(" \\\n\t"); + pfiles(cfiles,num_cfiles,"o"); + } + printf("\n\n"); + + printf("ANTLR_SPAWN = "); + if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT); + else pfiles(files, n, "c"); + if ( gen_CPP ) { + printf(" "); + pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT); + printf(" \\\n\t\t"); + pclasses(classes, num_classes, "h"); + if ( strcmp(hdr,"stdpccts.h")!=0 ) { + printf(" \\\n\t\t"); + printf("$(HDR_FILE) stdpccts.h"); + } + } + if ( user_lexer ) { + if ( !user_token_types ) printf(" $(TOKENS)"); + } + else { + printf(" $(DLG_FILE)"); + if ( !user_token_types ) printf(" $(TOKENS)"); + } + if ( !gen_CPP ) printf(" $(ERR).c"); + printf("\n"); + + if ( !user_lexer ) { + if ( gen_CPP ) printf("DLG_SPAWN = $(SCAN)%s", CPP_FILE_SUFFIX); + else printf("DLG_SPAWN = %s$(SCAN).c", DIR()); + if ( gen_CPP ) printf(" $(SCAN).h"); + if ( !gen_CPP ) printf(" $(MOD_FILE)"); + printf("\n"); + } + + if ( gen_CPP ) { + if ( !nondef_comp ) + printf("ifdef CXX\nCCC = $(CXX)\nendif\n\nifndef CCC\n"); + printf("CCC = %s\n",compilerCCC); + if ( !nondef_comp ) printf("endif\n\n"); + } + else + { + if ( !nondef_comp ) printf("ifndef CC\n"); + printf("CC = %s\n",compilerCC); + if ( !nondef_comp ) printf("endif\n\n"); + } + + /* set up dependencies */ + printf("\n%s : $(SRC) $(OBJ)\n", project); + printf("\t%s %s %s $(CFLAGS) $(OBJ)\n", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_EXE_FLAG, + project); + printf("\n"); + + /* implicit rules */ + +/* if(gen_CPP) + printf("%%.o : %%.cpp\n\t$(CCC) -c $(CFLAGS) $<\n\n"); + + printf("%%.o : %%.c\n\t%s -c $(CFLAGS) $<\n\n", + gen_CPP?"$(CCC)":"$(CC)"); +*/ + /* how to compile parser files */ + + for (i=0; i0) + { + printf("STreeParser%s : $(SOR_LIB)%sSTreeParser.cpp\n", + OBJ_FILE_SUFFIX,DirectorySymbol); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG); + printf("STreeParser%s ",OBJ_FILE_SUFFIX); + printf("$(SOR_LIB)%sSTreeParser.cpp\n\n",DirectorySymbol); + } + + printf("$(ANTLR_SPAWN) : $(GRM)\n"); + printf("\t$(ANTLR) $(AFLAGS) $(GRM)\n"); + + if ( !user_lexer ) + { + printf("\n"); + printf("$(DLG_SPAWN) : $(DLG_FILE)\n"); + if ( gen_CPP ) printf("\t$(DLG) $(DFLAGS) $(DLG_FILE)\n"); + else printf("\t$(DLG) $(DFLAGS) $(DLG_FILE) $(SCAN).c\n"); + } + + /* do the makes for ANTLR/DLG support */ + if ( gen_CPP ) { + printf("\n"); + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C); + printf("\n"); + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C); + if ( !user_lexer ) { + printf("\n"); + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C); + } + if ( gen_trees ) { + printf("\n"); + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C); + printf("\n"); + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C); + printf("\n"); +/* + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C); +*/ + } + } + + /* clean and scrub targets */ + + printf("\nclean:\n"); + printf("\trm -f *%s core %s", OBJ_FILE_SUFFIX, project); + if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX); + printf("\n"); + + printf("\nscrub: clean\n"); +/* printf("\trm -f *%s core %s", OBJ_FILE_SUFFIX, project); */ +/* if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX); */ + printf("\trm -f $(ANTLR_SPAWN)"); + if ( !user_lexer ) printf(" $(DLG_SPAWN)"); + for (i=0;i0 ) + { + char *p = &(*files)[strlen(*files)-1]; + if ( !first ) putchar(' '); + first=0; + while ( p > *files && *p != '.' ) --p; + if ( p == *files ) + { + fprintf(stderr, + "genmk: filenames must be file.suffix format: %s\n", + *files); + exit(-1); + } + if ( suffix == NULL ) printf("%s", *files); + else + { + *p = '\0'; + printf("%s", DIR()); + if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX); + else printf("%s.%s", *files, suffix); + *p = '.'; + } + files++; + --n; + } +} + +#ifdef __STDC__ +pclasses(char **classes, int n, char *suffix) +#else +pclasses(classes, n, suffix) +char **classes; +int n; +char *suffix; +#endif +{ + int first=1; + + while ( n>0 ) + { + if ( !first ) putchar(' '); + first=0; + if ( suffix == NULL ) printf("%s", *classes); + else { + printf("%s", DIR()); + if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX); + else printf("%s.%s", *classes, suffix); + } + classes++; + --n; + } +} + +static void +#ifdef __STDC__ +ProcessArgs( int argc, char **argv, Opt *options ) +#else +ProcessArgs( argc, argv, options ) +int argc; +char **argv; +Opt *options; +#endif +{ + Opt *p; + require(argv!=NULL, "ProcessArgs: command line NULL"); + + while ( argc-- > 0 ) + { + p = options; + while ( p->option != NULL ) + { + if ( strcmp(p->option, "*") == 0 || + strcmp(p->option, *argv) == 0 ) + { + if ( p->arg ) + { + (*p->process)( *argv, *(argv+1) ); + argv++; + argc--; + } + else + (*p->process)( *argv ); + break; + } + p++; + } + argv++; + } +} + +#ifdef __STDC__ +void fatal( char *err_) +#else +void fatal( err_) +char *err_; +#endif +{ + fprintf(stderr, "genmk: %s\n", err_); + exit(1); +} + +#ifdef __STDC__ +void warn( char *err_) +#else +void warn( err_) +char *err_; +#endif +{ + fprintf(stderr, "genmk: %s\n", err_); +} + +#ifdef __STDC__ +char *DIR(void) +#else +char *DIR() +#endif +{ + static char buf[200+1]; + + if ( strcmp(outdir,TopDirectory)==0 ) return ""; + sprintf(buf, "%s%s", outdir, DirectorySymbol); + return buf; +} diff --git a/Tools/Source/TianoTools/Pccts/support/genmk/genmk_old.c b/Tools/Source/TianoTools/Pccts/support/genmk/genmk_old.c new file mode 100644 index 0000000000..2cf9fad727 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/support/genmk/genmk_old.c @@ -0,0 +1,762 @@ +/* + * genmk -- a program to make makefiles for PCCTS + * + * ANTLR 1.33MR10 + * Terence John Parr 1989 - 1998 + * Purdue University + * U of MN + */ + +#include +#include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */ + +#ifdef VAXC +#define DIE return 0; +#define DONE return 1; +#else +#define DIE return 1; +#define DONE return 0; +#endif + +#ifndef require +#define require(expr, err) {if ( !(expr) ) fatal(err);} +#endif + +#define MAX_FILES 50 +#define MAX_CLASSES 50 + +char *RENAME_OBJ_FLAG="-o", + *RENAME_EXE_FLAG="-o"; + +char *dlg = "parser.dlg"; +char *err = "err.c"; +char *hdr = "stdpccts.h"; +char *tok = "tokens.h"; +char *mode = "mode.h"; +char *scan = "scan"; + +char ATOKENBUFFER_O[100]; +char APARSER_O[100]; +char ASTBASE_O[100]; +char PCCTSAST_O[100]; +char LIST_O[100]; +char DLEXERBASE_O[100]; + +/* Option flags */ +static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES]; +static int num_files = 0; +static int num_classes = 0; +static int user_lexer = 0; +static char *user_token_types = NULL; +static int gen_CPP = 0; +static char *outdir="."; +static char *dlg_class = "DLGLexer"; +static int gen_trees = 0; +static int gen_hoist = 0; +static char cfiles[1600]=""; +static char *compilerCCC="CC"; +static char *compilerCC="cc"; +static char *pccts_path="/usr/local/pccts"; + +void help(); +void mk(); +void pfiles(); +void pclasses(); +void fatal(); +void warn(); + +typedef struct _Opt { + char *option; + int arg; +#ifdef __cplusplus + void (*process)(...); +#else + void (*process)(); +#endif + char *descr; + } Opt; + +#ifdef __STDC__ +static void ProcessArgs(int, char **, Opt *); +#else +static void ProcessArgs(); +#endif + +static void +pProj( s, t ) +char *s; +char *t; +{ + project = t; +} + +static void +pUL( s ) +char *s; +{ + user_lexer = 1; +} + +static void +pCPP( s ) +char *s; +{ + gen_CPP = 1; +} + +static void +pUT( s, t ) +char *s; +char *t; +{ + user_token_types = t; +} + +static void +pTrees( s ) +char *s; +{ + gen_trees = 1; +} + +static void +pHoist( s ) +char *s; +{ + gen_hoist = 1; +} + +static void +#ifdef __STDC__ +pFile( char *s ) +#else +pFile( s ) +char *s; +#endif +{ + if ( *s=='-' ) + { + fprintf(stderr, "invalid option: '%s'; ignored...",s); + return; + } + + require(num_files0 ) { + warn("can't define classes w/o C++ mode; turning on C++ mode...\n"); + gen_CPP=1; + } + if ( gen_CPP && num_classes==0 ) { + fatal("must define classes >0 grammar classes in C++ mode\n"); + } + + mk(project, files, num_files, argc, argv); + DONE; +} + +void help() +{ + Opt *p = options; + static char buf[1000+1]; + + fprintf(stderr, "genmk [options] f1.g ... fn.g\n"); + while ( p->option!=NULL && *(p->option) != '*' ) + { + buf[0]='\0'; + if ( p->arg ) sprintf(buf, "%s ___", p->option); + else strcpy(buf, p->option); + fprintf(stderr, "\t%-16s %s\n", buf, p->descr); + p++; + } +} + +void mk(project, files, n, argc, argv) +char *project; +char **files; +int n; +int argc; +char **argv; +{ + int i; + + printf("#\n"); + printf("# PCCTS makefile for: "); + pfiles(files, n, NULL); + printf("\n"); + printf("#\n"); + printf("# Created from:"); + for (i=0; i0 ) + { + char *p = &(*files)[strlen(*files)-1]; + if ( !first ) putchar(' '); + first=0; + while ( p > *files && *p != '.' ) --p; + if ( p == *files ) + { + fprintf(stderr, + "genmk: filenames must be file.suffix format: %s\n", + *files); + exit(-1); + } + if ( suffix == NULL ) printf("%s", *files); + else + { + *p = '\0'; + printf("%s", DIR()); + if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX); + else printf("%s.%s", *files, suffix); + *p = '.'; + } + files++; + --n; + } +} + +void pclasses(classes, n, suffix) +char **classes; +int n; +char *suffix; +{ + int first=1; + + while ( n>0 ) + { + if ( !first ) putchar(' '); + first=0; + if ( suffix == NULL ) printf("%s", *classes); + else { + printf("%s", DIR()); + if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX); + else printf("%s.%s", *classes, suffix); + } + classes++; + --n; + } +} + +static void +#ifdef __STDC__ +ProcessArgs( int argc, char **argv, Opt *options ) +#else +ProcessArgs( argc, argv, options ) +int argc; +char **argv; +Opt *options; +#endif +{ + Opt *p; + require(argv!=NULL, "ProcessArgs: command line NULL"); + + while ( argc-- > 0 ) + { + p = options; + while ( p->option != NULL ) + { + if ( strcmp(p->option, "*") == 0 || + strcmp(p->option, *argv) == 0 ) + { + if ( p->arg ) + { + (*p->process)( *argv, *(argv+1) ); + argv++; + argc--; + } + else + (*p->process)( *argv ); + break; + } + p++; + } + argv++; + } +} + +void fatal( err_) +char *err_; +{ + fprintf(stderr, "genmk: %s\n", err_); + exit(1); +} + +void warn( err_) +char *err_; +{ + fprintf(stderr, "genmk: %s\n", err_); +} + +char *DIR() +{ + static char buf[200+1]; + + if ( strcmp(outdir,TopDirectory)==0 ) return ""; + sprintf(buf, "%s%s", outdir, DirectorySymbol); + return buf; +} diff --git a/Tools/Source/TianoTools/Pccts/support/genmk/makefile b/Tools/Source/TianoTools/Pccts/support/genmk/makefile new file mode 100644 index 0000000000..a003c2f321 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/support/genmk/makefile @@ -0,0 +1,29 @@ +## +## 7-Apr-97 +## added support/genmk/makefile to pccts 1.33MR1 distribution kit +## (support/genmk/makefile" omitted from 1.33 distribution kit) +## +SRC=genmk.c +OBJ=genmk.o +# Define PC if you use a PC OS (changes directory symbol and object file extension) +# see pccts/h/pcctscfg.h +CC=cc +COPT=-O +#CFLAGS=-I../../h -DPC +CFLAGS=$(COPT) -I../../h +BAG=../../bin/bag + +genmk: $(OBJ) $(SRC) ../../h/pcctscfg.h + $(CC) -o genmk $(OBJ) + +clean: + rm -rf core *.o + +scrub: + rm -rf genmk core *.o + +shar: + shar genmk.c makefile > genmk.shar + +archive: + $(BAG) genmk.c makefile > genmk.bag diff --git a/Tools/Source/TianoTools/Pccts/support/rexpr/makefile b/Tools/Source/TianoTools/Pccts/support/rexpr/makefile new file mode 100644 index 0000000000..44caef1aa5 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/support/rexpr/makefile @@ -0,0 +1,19 @@ +BAG=../../bin/bag +SRC=test.c rexpr.c +OBJ=test.o rexpr.o +CFLAGS = -g + +test: $(OBJ) $(SRC) + cc -g -o texpr $(OBJ) + +shar: + shar makefile test.c rexpr.c rexpr.h > rexpr.shar + +archive: + $(BAG) makefile test.c rexpr.c rexpr.h > rexpr.bag + +clean: + rm -rf *.o core texpr + +scrub: + rm -rf *.o core texpr diff --git a/Tools/Source/TianoTools/Pccts/support/rexpr/rexpr.c b/Tools/Source/TianoTools/Pccts/support/rexpr/rexpr.c new file mode 100644 index 0000000000..805bf65533 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/support/rexpr/rexpr.c @@ -0,0 +1,586 @@ +/* + * This file contains code for + * + * int rexpr(char *expr, char *s); + * + * which answers + * + * 1 if 's' is in the language described by the regular expression 'expr' + * 0 if it is not + * -1 if the regular expression is invalid + * + * Language membership is determined by constructing a non-deterministic + * finite automata (NFA) from the regular expression. A depth- + * first-search is performed on the NFA (graph) to check for a match of 's'. + * Each non-epsilon arc consumes one character from 's'. Backtracking is + * performed to check all possible paths through the NFA. + * + * Regular expressions follow the meta-language: + * + * ::= ( '|' )* + * + * ::= ( )* + * + * ::= {'~'} '[' ']' + * | '(' ')' + * | '{' '}' + * | + * + * ::= { '*' | '+' } + * + * ::= ( )* + * | { } '-' { } + * + * ::= Token[Atom] + * + * Notes: + * ~ means complement the set in [..]. i.e. all characters not listed + * * means match 0 or more times (can be on expression or atom) + * + means match 1 or more times (can be on expression or atom) + * {} optional + * () grouping + * [] set of atoms + * x-y all characters from x to y (found only in [..]) + * \xx the character with value xx + * + * Examples: + * [a-z]+ + * match 1 or more lower-case letters (e.g. variable) + * + * 0x[0-9A-Fa-f]+ + * match a hex number with 0x on front (e.g. 0xA1FF) + * + * [0-9]+.[0-9]+{e[0-9]+} + * match a floating point number (e.g. 3.14e21) + * + * Code example: + * if ( rexpr("[a-zA-Z][a-zA-Z0-9]+", str) ) then str is keyword + * + * Terence Parr + * Purdue University + * April 1991 + */ + +#include +#include +#ifdef __STDC__ +#include +#else +#include +#endif +#include "rexpr.h" + +#ifdef __USE_PROTOS +static int regExpr( GraphPtr g ); +static int andExpr( GraphPtr g ); +static int expr( GraphPtr g ); +static int repeatSymbol( GraphPtr g ); +static int atomList( char *p, int complement ); +static void next( void ); +static ArcPtr newGraphArc( void ); +static NodePtr newNode( void ); +static int ArcBetweenGraphNode( NodePtr i, NodePtr j, int label ); +static Graph BuildNFA_atom( int label ); +static Graph BuildNFA_AB( Graph A, Graph B ); +static Graph BuildNFA_AorB( Graph A, Graph B ); +static Graph BuildNFA_set( char *s ); +static Graph BuildNFA_Astar( Graph A ); +static Graph BuildNFA_Aplus( Graph A ); +static Graph BuildNFA_Aoptional( Graph A ); +#else +static int regExpr(); +static int andExpr(); +static int expr(); +static int repeatSymbol(); +static int atomList(); +static void next(); +static ArcPtr newGraphArc(); +static NodePtr newNode(); +static int ArcBetweenGraphNode(); +static Graph BuildNFA_atom(); +static Graph BuildNFA_AB(); +static Graph BuildNFA_AorB(); +static Graph BuildNFA_set(); +static Graph BuildNFA_Astar(); +static Graph BuildNFA_Aplus(); +static Graph BuildNFA_Aoptional(); +#endif + +static char *_c; +static int token, tokchar; +static NodePtr accept; +static NodePtr freelist = NULL; + +/* + * return 1 if s in language described by expr + * 0 if s is not + * -1 if expr is an invalid regular expression + */ +#ifdef __USE_PROTOS +static int rexpr(char *expr,char *s) +#else +static int rexpr(expr, s) +char *expr, *s; +#endif +{ + NodePtr p,q; + Graph nfa; + int result; + + fprintf(stderr, "rexpr(%s,%s);\n", expr,s); + freelist = NULL; + _c = expr; + next(); + if ( regExpr(&nfa) == -1 ) return -1; + accept = nfa.right; + result = match(nfa.left, s); + /* free all your memory */ + p = q = freelist; + while ( p!=NULL ) { q = p->track; free(p); p = q; } + return result; +} + +/* + * do a depth-first-search on the NFA looking for a path from start to + * accept state labelled with the characters of 's'. + */ + +#ifdef __USE_PROTOS +static int match(NodePtr automaton,char *s) +#else +static int match(automaton, s) +NodePtr automaton; +char *s; +#endif +{ + ArcPtr p; + + if ( automaton == accept && *s == '\0' ) return 1; /* match */ + + for (p=automaton->arcs; p!=NULL; p=p->next) /* try all arcs */ + { + if ( p->label == Epsilon ) + { + if ( match(p->target, s) ) return 1; + } + else if ( p->label == *s ) + if ( match(p->target, s+1) ) return 1; + } + return 0; +} + +/* + * ::= ( '|' {} )* + * + * Return -1 if syntax error + * Return 0 if none found + * Return 1 if a regExrp was found + */ + +#ifdef __USE_PROTOS +static int regExpr(GraphPtr g) +#else +static int regExpr(g) +GraphPtr g; +#endif +{ + Graph g1, g2; + + if ( andExpr(&g1) == -1 ) + { + return -1; + } + + while ( token == '|' ) + { + int a; + next(); + a = andExpr(&g2); + if ( a == -1 ) return -1; /* syntax error below */ + else if ( !a ) return 1; /* empty alternative */ + g1 = BuildNFA_AorB(g1, g2); + } + + if ( token!='\0' ) return -1; + + *g = g1; + return 1; +} + +/* + * ::= ( )* + */ + +#ifdef __USE_PROTOS +static int andExpr(GraphPtr g) +#else +static int andExpr(g) +GraphPtr g; +#endif +{ + Graph g1, g2; + + if ( expr(&g1) == -1 ) + { + return -1; + } + + while ( token==Atom || token=='{' || token=='(' || token=='~' || token=='[' ) + { + if (expr(&g2) == -1) return -1; + g1 = BuildNFA_AB(g1, g2); + } + + *g = g1; + return 1; +} + +/* + * ::= {'~'} '[' ']' + * | '(' ')' + * | '{' '}' + * | + */ + +#ifdef __USE_PROTOS +static int expr(GraphPtr g) +#else +static int expr(g) +GraphPtr g; +#endif +{ + int complement = 0; + char s[257]; /* alloc space for string of char in [] */ + + if ( token == '~' || token == '[' ) + { + if ( token == '~' ) {complement = 1; next();} + if ( token != '[' ) return -1; + next(); + if ( atomList( s, complement ) == -1 ) return -1; + *g = BuildNFA_set( s ); + if ( token != ']' ) return -1; + next(); + repeatSymbol( g ); + return 1; + } + if ( token == '(' ) + { + next(); + if ( regExpr( g ) == -1 ) return -1; + if ( token != ')' ) return -1; + next(); + repeatSymbol( g ); + return 1; + } + if ( token == '{' ) + { + next(); + if ( regExpr( g ) == -1 ) return -1; + if ( token != '}' ) return -1; + next(); + /* S p e c i a l C a s e O p t i o n a l { } */ + if ( token != '*' && token != '+' ) + { + *g = BuildNFA_Aoptional( *g ); + } + repeatSymbol( g ); + return 1; + } + if ( token == Atom ) + { + *g = BuildNFA_atom( tokchar ); + next(); + repeatSymbol( g ); + return 1; + } + + return -1; +} + +/* + * ::= { '*' | '+' } + */ +#ifdef __USE_PROTOS +static int repeatSymbol(GraphPtr g) +#else +static int repeatSymbol(g) +GraphPtr g; +#endif +{ + switch ( token ) + { + case '*' : *g = BuildNFA_Astar( *g ); next(); break; + case '+' : *g = BuildNFA_Aplus( *g ); next(); break; + } + return 1; +} + +/* + * ::= { }* + * { } '-' { } + * + * a-b is same as ab + * q-a is same as q + */ + +#ifdef __USE_PROTOS +static int atomList(char *p, int complement) +#else +static int atomList(p, complement) +char *p; +int complement; +#endif +{ + static unsigned char set[256]; /* no duplicates */ + int first, last, i; + char *s = p; + + if ( token != Atom ) return -1; + + for (i=0; i<256; i++) set[i] = 0; + while ( token == Atom ) + { + if ( !set[tokchar] ) *s++ = tokchar; + set[tokchar] = 1; /* Add atom to set */ + next(); + if ( token == '-' ) /* have we found '-' */ + { + first = *(s-1); /* Get last char */ + next(); + if ( token != Atom ) return -1; + else + { + last = tokchar; + } + for (i = first+1; i <= last; i++) + { + if ( !set[tokchar] ) *s++ = i; + set[i] = 1; /* Add atom to set */ + } + next(); + } + } + *s = '\0'; + if ( complement ) + { + for (i=0; i<256; i++) set[i] = !set[i]; + for (i=1,s=p; i<256; i++) if ( set[i] ) *s++ = i; + *s = '\0'; + } + return 1; +} + +/* a somewhat stupid lexical analyzer */ + +#ifdef __USE_PROTOS +static void next(void) +#else +static void next() +#endif +{ + while ( *_c==' ' || *_c=='\t' || *_c=='\n' ) _c++; + if ( *_c=='\\' ) + { + _c++; + if ( isdigit(*_c) ) + { + int n=0; + while ( isdigit(*_c) ) + { + n = n*10 + (*_c++ - '0'); + } + if ( n>255 ) n=255; + tokchar = n; + } + else + { + switch (*_c) + { + case 'n' : tokchar = '\n'; break; + case 't' : tokchar = '\t'; break; + case 'r' : tokchar = '\r'; break; + default : tokchar = *_c; + } + _c++; + } + token = Atom; + } + else if ( isgraph(*_c) && *_c!='[' && *_c!='(' && *_c!='{' && + *_c!='-' && *_c!='}' && *_c!=')' && *_c!=']' && + *_c!='+' && *_c!='*' && *_c!='~' && *_c!='|' ) + { + token = Atom; + tokchar = *_c++; + } + else + { + token = tokchar = *_c++; + } +} + +/* N F A B u i l d i n g R o u t i n e s */ + +#ifdef __USE_PROTOS +static ArcPtr newGraphArc(void) +#else +static ArcPtr newGraphArc() +#endif +{ + ArcPtr p; + p = (ArcPtr) calloc(1, sizeof(Arc)); + if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);} + if ( freelist != NULL ) p->track = (ArcPtr) freelist; + freelist = (NodePtr) p; + return p; +} + +#ifdef __USE_PROTOS +static NodePtr newNode(void) +#else +static NodePtr newNode() +#endif +{ + NodePtr p; + p = (NodePtr) calloc(1, sizeof(Node)); + if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);} + if ( freelist != NULL ) p->track = freelist; + freelist = p; + return p; +} + +#ifdef __USE_PROTOS +static void ArcBetweenGraphNodes(NodePtr i,NodePtr j,int label) +#else +static void ArcBetweenGraphNodes(i, j, label) +NodePtr i, j; +int label; +#endif +{ + ArcPtr a; + + a = newGraphArc(); + if ( i->arcs == NULL ) i->arctail = i->arcs = a; + else {(i->arctail)->next = a; i->arctail = a;} + a->label = label; + a->target = j; +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_atom(int label) +#else +static Graph BuildNFA_atom(label) +int label; +#endif +{ + Graph g; + + g.left = newNode(); + g.right = newNode(); + ArcBetweenGraphNodes(g.left, g.right, label); + return( g ); +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_AB(Graph A,Graph B) +#else +static Graph BuildNFA_AB(A, B) +Graph A, B; +#endif +{ + Graph g; + + ArcBetweenGraphNodes(A.right, B.left, Epsilon); + g.left = A.left; + g.right = B.right; + return( g ); +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_AorB(Graph A,Graph B) +#else +static Graph BuildNFA_AorB(A, B) +Graph A, B; +#endif +{ + Graph g; + + g.left = newNode(); + ArcBetweenGraphNodes(g.left, A.left, Epsilon); + ArcBetweenGraphNodes(g.left, B.left, Epsilon); + g.right = newNode(); + ArcBetweenGraphNodes(A.right, g.right, Epsilon); + ArcBetweenGraphNodes(B.right, g.right, Epsilon); + return( g ); +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_set(char *s) +#else +static Graph BuildNFA_set( s ) +char *s; +#endif +{ + Graph g; + + if ( s == NULL ) return g; + + g.left = newNode(); + g.right = newNode(); + while ( *s != '\0' ) + { + ArcBetweenGraphNodes(g.left, g.right, *s++); + } + return g; +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_Astar(Graph A) +#else +static Graph BuildNFA_Astar( A ) +Graph A; +#endif +{ + Graph g; + + g.left = newNode(); + g.right = newNode(); + + ArcBetweenGraphNodes(g.left, A.left, Epsilon); + ArcBetweenGraphNodes(g.left, g.right, Epsilon); + ArcBetweenGraphNodes(A.right, g.right, Epsilon); + ArcBetweenGraphNodes(A.right, A.left, Epsilon); + + return( g ); +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_Aplus(Graph A) +#else +static Graph BuildNFA_Aplus( A ) +Graph A; +#endif +{ + ArcBetweenGraphNodes(A.right, A.left, Epsilon); + + return( A ); +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_Aoptional(Graph A) +#else +static Graph BuildNFA_Aoptional( A ) +Graph A; +#endif +{ + Graph g; + + g.left = newNode(); + g.right = newNode(); + + ArcBetweenGraphNodes(g.left, A.left, Epsilon); + ArcBetweenGraphNodes(g.left, g.right, Epsilon); + ArcBetweenGraphNodes(A.right, g.right, Epsilon); + + return( g ); +} diff --git a/Tools/Source/TianoTools/Pccts/support/rexpr/rexpr.h b/Tools/Source/TianoTools/Pccts/support/rexpr/rexpr.h new file mode 100644 index 0000000000..e67a9652fb --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/support/rexpr/rexpr.h @@ -0,0 +1,30 @@ +#define Atom 256 /* token Atom (an impossible char value) */ +#define Epsilon 257 /* epsilon arc (an impossible char value) */ + +/* track field must be same for all node types */ +typedef struct _a { + struct _a *track; /* track mem allocation */ + int label; + struct _a *next; + struct _n *target; + } Arc, *ArcPtr; + +typedef struct _n { + struct _n *track; + ArcPtr arcs, arctail; + } Node, *NodePtr; + +typedef struct { + NodePtr left, + right; + } Graph, *GraphPtr; + +#ifdef __USE_PROTOS +int rexpr( char *expr, char *s ); +int match( NodePtr automaton, char *s ); +#else +int rexpr(); +int match(); +#endif + + diff --git a/Tools/Source/TianoTools/Pccts/support/rexpr/test.c b/Tools/Source/TianoTools/Pccts/support/rexpr/test.c new file mode 100644 index 0000000000..2619539e4b --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/support/rexpr/test.c @@ -0,0 +1,19 @@ +#include +#include "rexpr.h" + +/* + * test for rexpr(). + * To make this test: + * cc -o rexpr test.c rexpr.c + * Then from command line type: + * rexpr r string + * where r is the regular expression that decribes a language + * and string is the string to verify. + */ +main(argc,argv) +int argc; +char *argv[]; +{ + if ( argc!=3 ) fprintf(stderr,"rexpr: expr s\n"); + else printf("%d\n", rexpr(argv[1], argv[2])); +} diff --git a/Tools/Source/TianoTools/Pccts/support/set/set.c b/Tools/Source/TianoTools/Pccts/support/set/set.c new file mode 100644 index 0000000000..eb6fba7393 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/support/set/set.c @@ -0,0 +1,816 @@ +/* set.c + + The following is a general-purpose set library originally developed + by Hank Dietz and enhanced by Terence Parr to allow dynamic sets. + + Sets are now structs containing the #words in the set and + a pointer to the actual set words. + + Generally, sets need not be explicitly allocated. They are + created/extended/shrunk when appropriate (e.g. in set_of()). + HOWEVER, sets need to be destroyed (free()ed) when they go out of scope + or are otherwise no longer needed. A routine is provided to + free a set. + + Sets can be explicitly created with set_new(s, max_elem). + + Sets can be declared to have minimum size to reduce realloc traffic. + Default minimum size = 1. + + Sets can be explicitly initialized to have no elements (set.n == 0) + by using the 'empty' initializer: + + Examples: + set a = empty; -- set_deg(a) == 0 + + return( empty ); + + Example set creation and destruction: + + set + set_of2(e,g) + unsigned e,g; + { + set a,b,c; + + b = set_of(e); -- Creates space for b and sticks in e + set_new(c, g); -- set_new(); set_orel() ==> set_of() + set_orel(g, &c); + a = set_or(b, c); + . + . + . + set_free(b); + set_free(c); + return( a ); + } + + 1987 by Hank Dietz + + Modified by: + Terence Parr + Purdue University + October 1989 + + Made it smell less bad to C++ 7/31/93 -- TJP +*/ + +#include +#include "pcctscfg.h" +#ifdef __STDC__ +#include +#else +#include +#endif +#include + +#include "set.h" + +#define MIN(i,j) ( (i) > (j) ? (j) : (i)) +#define MAX(i,j) ( (i) < (j) ? (j) : (i)) + +/* elems can be a maximum of 32 bits */ +static unsigned bitmask[] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x00000100, 0x00000200, 0x00000400, 0x00000800, + 0x00001000, 0x00002000, 0x00004000, 0x00008000, +#if !defined(PC) || defined(PC32) + 0x00010000, 0x00020000, 0x00040000, 0x00080000, + 0x00100000, 0x00200000, 0x00400000, 0x00800000, + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000 +#endif +}; + +set empty = set_init; +static unsigned min=1; + +#define StrSize 200 + +#ifdef MEMCHK +#define CHK(a) \ + if ( a.setword != NULL ) \ + if ( !valid(a.setword) ) \ + {fprintf(stderr, "%s(%d): invalid set\n",__FILE__,__LINE__); exit(-1);} +#else +#define CHK(a) +#endif + +/* + * Set the minimum size (in words) of a set to reduce realloc calls + */ +void +#ifdef __USE_PROTOS +set_size( unsigned n ) +#else +set_size( n ) +unsigned n; +#endif +{ + min = n; +} + +unsigned int +#ifdef __USE_PROTOS +set_deg( set a ) +#else +set_deg( a ) +set a; +#endif +{ + /* Fast compute degree of a set... the number + of elements present in the set. Assumes + that all word bits are used in the set + and that SETSIZE(a) is a multiple of WORDSIZE. + */ + register unsigned *p = &(a.setword[0]); + register unsigned *endp = NULL; /* MR27 Avoid false memory check report */ + register unsigned degree = 0; + + CHK(a); + if ( a.n == 0 ) return(0); + endp = &(a.setword[a.n]); + while ( p < endp ) + { + register unsigned t = *p; + register unsigned *b = &(bitmask[0]); + do { + if (t & *b) ++degree; + } while (++b < &(bitmask[WORDSIZE])); + p++; + } + + return(degree); +} + +set +#ifdef __USE_PROTOS +set_or( set b, set c ) +#else +set_or( b, c ) +set b; +set c; +#endif +{ + /* Fast set union operation */ + /* resultant set size is max(b, c); */ + set *big; + set t; + unsigned int m,n; + register unsigned *r, *p, *q, *endp; + + CHK(b); CHK(c); + t = empty; + if (b.n > c.n) {big= &b; m=b.n; n=c.n;} else {big= &c; m=c.n; n=b.n;} + set_ext(&t, m); + r = t.setword; + + /* Or b,c until max of smaller set */ + q = c.setword; + p = b.setword; + endp = &(b.setword[n]); + while ( p < endp ) *r++ = *p++ | *q++; + + /* Copy rest of bigger set into result */ + p = &(big->setword[n]); + endp = &(big->setword[m]); + while ( p < endp ) *r++ = *p++; + + return(t); +} + +set +#ifdef __USE_PROTOS +set_and( set b, set c ) +#else +set_and( b, c ) +set b; +set c; +#endif +{ + /* Fast set intersection operation */ + /* resultant set size is min(b, c); */ + set t; + unsigned int n; + register unsigned *r, *p, *q, *endp; + + CHK(b); CHK(c); + t = empty; + n = (b.n > c.n) ? c.n : b.n; + if ( n == 0 ) return t; /* TJP 4-27-92 fixed for empty set */ + set_ext(&t, n); + r = t.setword; + + /* & b,c until max of smaller set */ + q = c.setword; + p = b.setword; + endp = &(b.setword[n]); + while ( p < endp ) *r++ = *p++ & *q++; + + return(t); +} + +set +#ifdef __USE_PROTOS +set_dif( set b, set c ) +#else +set_dif( b, c ) +set b; +set c; +#endif +{ + /* Fast set difference operation b - c */ + /* resultant set size is size(b) */ + set t; + unsigned int n; + register unsigned *r, *p, *q, *endp; + + CHK(b); CHK(c); + t = empty; + n = (b.n <= c.n) ? b.n : c.n ; + if ( b.n == 0 ) return t; /* TJP 4-27-92 fixed for empty set */ + /* WEC 12-1-92 fixed for c.n = 0 */ + set_ext(&t, b.n); + r = t.setword; + + /* Dif b,c until smaller set size */ + q = c.setword; + p = b.setword; + endp = &(b.setword[n]); + while ( p < endp ) *r++ = *p++ & (~ *q++); + + /* Copy rest of b into result if size(b) > c */ + if ( b.n > n ) + { + p = &(b.setword[n]); + endp = &(b.setword[b.n]); + while ( p < endp ) *r++ = *p++; + } + + return(t); +} + +set +#ifdef __USE_PROTOS +set_of( unsigned b ) +#else +set_of( b ) +unsigned b; +#endif +{ + /* Fast singleton set constructor operation */ + static set a; + + if ( b == nil ) return( empty ); + set_new(a, b); + a.setword[DIVWORD(b)] = bitmask[MODWORD(b)]; + + return(a); +} + +/* + * Extend (or shrink) the set passed in to have n words. + * + * if n is smaller than the minimum, boost n to have the minimum. + * if the new set size is the same as the old one, do nothing. + * + * TJP 4-27-92 Fixed so won't try to alloc 0 bytes + */ +void +#ifdef __USE_PROTOS +set_ext( set *a, unsigned int n ) +#else +set_ext( a, n ) +set *a; +unsigned int n; +#endif +{ + register unsigned *p; + register unsigned *endp; + unsigned int size; + + CHK((*a)); + if ( a->n == 0 ) + { + if ( n == 0 ) return; + if (a->setword != NULL) { + free (a->setword); /* MR20 */ + } + a->setword = (unsigned *) calloc(n, BytesPerWord); + if ( a->setword == NULL ) + { + fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n); + exit(-1); + } + a->n = n; + return; + } + if ( n < min ) n = min; + if ( a->n == n || n == 0 ) return; + size = a->n; + a->n = n; + a->setword = (unsigned *) realloc( (char *)a->setword, (n*BytesPerWord) ); + if ( a->setword == NULL ) + { + fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n); + exit(-1); + } + + p = &(a->setword[size]); /* clear from old size to new size */ + endp = &(a->setword[a->n]); + do { + *p++ = 0; + } while ( p < endp ); +} + +set +#ifdef __USE_PROTOS +set_not( set a ) +#else +set_not( a ) +set a; +#endif +{ + /* Fast not of set a (assumes all bits used) */ + /* size of resultant set is size(a) */ + /* ~empty = empty cause we don't know how bit to make set */ + set t; + register unsigned *r; + register unsigned *p = a.setword; + register unsigned *endp = &(a.setword[a.n]); + + CHK(a); + t = empty; + if ( a.n == 0 ) return( empty ); + set_ext(&t, a.n); + r = t.setword; + + do { + *r++ = (~ *p++); + } while ( p < endp ); + + return(t); +} + +int +#ifdef __USE_PROTOS +set_equ( set a, set b ) +#else +set_equ( a, b ) +set a; +set b; +#endif +{ +/* 8-Nov-97 Make it work with sets of different sizes */ +/* Easy to understand, too. Probably faster. */ +/* Check for a equal to b */ + + unsigned int count; /* MR11 */ + unsigned int i; /* MR11 */ + + CHK(a); CHK(b); + + count=MIN(a.n,b.n); + if (count == 0) return 1; + for (i=0; i < count; i++) { + if (a.setword[i] != b.setword[i]) return 0; + }; + if (a.n < b.n) { + for (i=count; i < b.n; i++) { + if (b.setword[i] != 0) return 0; + } + return 1; + } else if (a.n > b.n) { + for (i=count; i < a.n; i++) { + if (a.setword[i] != 0) return 0; + } + return 1; + } else { + return 1; + }; +} + +int +#ifdef __USE_PROTOS +set_sub( set a, set b ) +#else +set_sub( a, b ) +set a; +set b; +#endif +{ + +/* 8-Nov-97 Make it work with sets of different sizes */ +/* Easy to understand, too. Probably faster. */ +/* Check for a is a PROPER subset of b */ + + unsigned int count; + unsigned int i; + + CHK(a); CHK(b); + + if (a.n == 0) return 1; + count=MIN(a.n,b.n); + for (i=0; i < count; i++) { + if (a.setword[i] & ~b.setword[i]) return 0; + }; + if (a.n <= b.n) { + return 1; + } else { + for (i=count; i a.n ) return(0); + + /* Otherwise, we have to check */ + return( a.setword[DIVWORD(b)] & bitmask[MODWORD(b)] ); +} + +int +#ifdef __USE_PROTOS +set_nil( set a ) +#else +set_nil( a ) +set a; +#endif +{ + /* Fast check for nil set */ + register unsigned *p = a.setword; + register unsigned *endp; + + CHK(a); + if ( a.n == 0 ) return(1); + endp = &(a.setword[a.n]); + + /* The set is not empty if any word used to store + the set is non-zero. This means one must be a + bit careful about doing things like negation. + */ + do { + if (*p) return(0); + } while (++p < endp); + + return(1); +} + +char * +#ifdef __USE_PROTOS +set_str( set a ) +#else +set_str( a ) +set a; +#endif +{ + /* Fast convert set a into ASCII char string... + assumes that all word bits are used in the set + and that SETSIZE is a multiple of WORDSIZE. + Trailing 0 bits are removed from the string. + if no bits are on or set is empty, "" is returned. + */ + register unsigned *p = a.setword; + register unsigned *endp = &(a.setword[a.n]); + static char str_tmp[StrSize+1]; + register char *q = &(str_tmp[0]); + + CHK(a); + if ( a.n==0 ) {*q=0; return( &(str_tmp[0]) );} + do { + register unsigned t = *p; + register unsigned *b = &(bitmask[0]); + do { + *(q++) = (char) ((t & *b) ? '1' : '0'); + } while (++b < &(bitmask[WORDSIZE])); + } while (++p < endp); + + /* Trim trailing 0s & NULL terminate the string */ + while ((q > &(str_tmp[0])) && (*(q-1) != '1')) --q; + *q = 0; + + return(&(str_tmp[0])); +} + +set +#ifdef __USE_PROTOS +set_val( register char *s ) +#else +set_val( s ) +register char *s; +#endif +{ + /* Fast convert set ASCII char string into a set. + If the string ends early, the remaining set bits + are all made zero. + The resulting set size is just big enough to hold all elements. + */ + static set a; + register unsigned *p, *endp; + + set_new(a, strlen(s)); + p = a.setword; + endp = &(a.setword[a.n]); + do { + register unsigned *b = &(bitmask[0]); + /* Start with a word with no bits on */ + *p = 0; + do { + if (*s) { + if (*s == '1') { + /* Turn-on this bit */ + *p |= *b; + } + ++s; + } + } while (++b < &(bitmask[WORDSIZE])); + } while (++p < endp); + + return(a); +} + +/* + * Or element e into set a. a can be empty. + */ +void +#ifdef __USE_PROTOS +set_orel( unsigned e, set *a ) +#else +set_orel( e, a ) +unsigned e; +set *a; +#endif +{ + CHK((*a)); + if ( e == nil ) return; + if ( NumWords(e) > a->n ) set_ext(a, NumWords(e)); + a->setword[DIVWORD(e)] |= bitmask[MODWORD(e)]; +} + +/* + * Or set b into set a. a can be empty. does nothing if b empty. + */ +void +#ifdef __USE_PROTOS +set_orin( set *a, set b ) +#else +set_orin( a, b ) +set *a; +set b; +#endif +{ + /* Fast set union operation */ + /* size(a) is max(a, b); */ + unsigned int m; + register unsigned *p, + *q = b.setword, + *endq; /* MR20 */ + + CHK((*a)); CHK(b); + if ( b.n == 0 ) return; + endq = &(b.setword[b.n]); /* MR20 */ + m = (a->n > b.n) ? a->n : b.n; + set_ext(a, m); + p = a->setword; + do { + *p++ |= *q++; + } while ( q < endq ); +} + +/* + * And set b into set a. a can be empty. does nothing if b empty. + */ +void +#ifdef __USE_PROTOS +set_andin( set *a, set b ) +#else +set_andin( a, b ) +set *a; +set b; +#endif +{ + /* Fast set intersection operation */ + /* size(a) is max(a, b); */ + unsigned int m; + register unsigned *p, + *q = b.setword, + *endq = &(b.setword[b.n]); + + CHK((*a)); CHK(b); + if ( b.n == 0 ) return; + m = (a->n > b.n) ? a->n : b.n; + set_ext(a, m); + p = a->setword; + do { + *p++ &= *q++; + } while ( q < endq ); +} + +void +#ifdef __USE_PROTOS +set_rm( unsigned e, set a ) +#else +set_rm( e, a ) +unsigned e; +set a; +#endif +{ + /* Does not effect size of set */ + CHK(a); + if ( (e == nil) || (NumWords(e) > a.n) ) return; + a.setword[DIVWORD(e)] ^= (a.setword[DIVWORD(e)]&bitmask[MODWORD(e)]); +} + +void +#ifdef __USE_PROTOS +set_clr( set a ) +#else +set_clr( a ) +set a; +#endif +{ + /* Does not effect size of set */ + register unsigned *p = a.setword; + register unsigned *endp; + + CHK(a); + if ( a.n == 0 ) return; + endp = &(a.setword[a.n]); + do { + *p++ = 0; + } while ( p < endp ); +} + +set +#ifdef __USE_PROTOS +set_dup( set a ) +#else +set_dup( a ) +set a; +#endif +{ + set b; + register unsigned *p, + *q = a.setword, + *endq; /* MR20 */ + + CHK(a); + b = empty; + if ( a.n == 0 ) return( empty ); + endq = &(a.setword[a.n]); /* MR20 */ + set_ext(&b, a.n); + p = b.setword; + do { + *p++ = *q++; + } while ( q < endq ); + + return(b); +} + +/* + * Return a nil terminated list of unsigned ints that represents all + * "on" bits in the bit set. + * + * e.g. {011011} --> {1, 2, 4, 5, nil} + * + * _set_pdq and set_pdq are useful when an operation is required on each element + * of a set. Normally, the sequence is: + * + * while ( set_deg(a) > 0 ) { + * e = set_int(a); + * set_rm(e, a); + * ...process e... + * } + * Now, + * + * t = e = set_pdq(a); + * while ( *e != nil ) { + * ...process *e... + * e++; + * } + * free( t ); + * + * We have saved many set calls and have not destroyed set a. + */ +void +#ifdef __USE_PROTOS +_set_pdq( set a, register unsigned *q ) +#else +_set_pdq( a, q ) +set a; +register unsigned *q; +#endif +{ + register unsigned *p = a.setword, + *endp = &(a.setword[a.n]); + register unsigned e=0; + + CHK(a); + /* are there any space (possibility of elements)? */ + if ( a.n == 0 ) return; + do { + register unsigned t = *p; + register unsigned *b = &(bitmask[0]); + do { + if ( t & *b ) *q++ = e; + ++e; + } while (++b < &(bitmask[WORDSIZE])); + } while (++p < endp); + *q = nil; +} + +/* + * Same as _set_pdq except allocate memory. set_pdq is the natural function + * to use. + */ +unsigned * +#ifdef __USE_PROTOS +set_pdq( set a ) +#else +set_pdq( a ) +set a; +#endif +{ + unsigned *q; + int max_deg; + + CHK(a); + max_deg = WORDSIZE*a.n; + /* assume a.n!=0 & no elements is rare, but still ok */ + if ( a.n == 0 ) return(NULL); + q = (unsigned *) malloc((max_deg+1)*BytesPerWord); + if ( q == NULL ) return( NULL ); + _set_pdq(a, q); + return( q ); +} + +/* a function that produces a hash number for the set + */ +unsigned int +#ifdef __USE_PROTOS +set_hash( set a, register unsigned int mod ) +#else +set_hash( a, mod ) +set a; +register unsigned int mod; +#endif +{ + /* Fast hash of set a (assumes all bits used) */ + register unsigned *p = &(a.setword[0]); + register unsigned *endp = &(a.setword[a.n]); + register unsigned i = 0; + + CHK(a); + while (p> LogWordSize) /* x / WORDSIZE */ +#define nil (~((unsigned) 0)) /* An impossible set member all bits on (big!) */ + +typedef struct _set { + unsigned int n; /* Number of words in set */ + unsigned *setword; + } set; + +#define set_init {0, NULL} +#define set_null(a) ((a).setword==NULL) + +#define NumBytes(x) (((x)>>3)+1) /* Num bytes to hold x */ +#define NumWords(x) ((((unsigned)(x))>>LogWordSize)+1) /* Num words to hold x */ + + +/* M a c r o s */ + +/* make arg1 a set big enough to hold max elem # of arg2 */ +#define set_new(a,_max) \ +if (((a).setword=(unsigned *)calloc(NumWords(_max),BytesPerWord))==NULL) \ + fprintf(stderr, "set_new: Cannot allocate set with max of %d\n", _max); \ + (a).n = NumWords(_max); + +#define set_free(a) \ + {if ( (a).setword != NULL ) free((char *)((a).setword)); \ + (a) = empty;} + +#ifdef __USE_PROTOS +extern void set_size( unsigned ); +extern unsigned int set_deg( set ); +extern set set_or( set, set ); +extern set set_and( set, set ); +extern set set_dif( set, set ); +extern set set_of( unsigned ); +extern void set_ext( set *, unsigned int ); +extern set set_not( set ); +extern int set_equ( set, set ); +extern int set_sub( set, set ); +extern unsigned set_int( set ); +extern int set_el( unsigned, set ); +extern int set_nil( set ); +extern char * set_str( set ); +extern set set_val( register char * ); +extern void set_orel( unsigned, set * ); +extern void set_orin( set *, set ); +extern void set_andin( set *, set ); +extern void set_rm( unsigned, set ); +extern void set_clr( set ); +extern set set_dup( set ); +extern void set_PDQ( set, register unsigned * ); +extern unsigned *set_pdq( set ); +extern void _set_pdq( set a, register unsigned *q ); +extern unsigned int set_hash( set, register unsigned int ); +#else +extern void set_size(); +extern unsigned int set_deg(); +extern set set_or(); +extern set set_and(); +extern set set_dif(); +extern set set_of(); +extern void set_ext(); +extern set set_not(); +extern int set_equ(); +extern int set_sub(); +extern unsigned set_int(); +extern int set_el(); +extern int set_nil(); +extern char * set_str(); +extern set set_val(); +extern void set_orel(); +extern void set_orin(); +extern void set_andin(); +extern void set_rm(); +extern void set_clr(); +extern set set_dup(); +extern void set_PDQ(); +extern unsigned *set_pdq(); +extern void _set_pdq(); +extern unsigned int set_hash(); +#endif + +extern set empty; + +#endif diff --git a/Tools/Source/TianoTools/Pccts/support/sym/sym.c b/Tools/Source/TianoTools/Pccts/support/sym/sym.c new file mode 100644 index 0000000000..eccce059bb --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/support/sym/sym.c @@ -0,0 +1,402 @@ +/* + * Simple symbol table manager using coalesced chaining to resolve collisions + * + * Doubly-linked lists are used for fast removal of entries. + * + * 'sym.h' must have a definition for typedef "Sym". Sym must include at + * minimum the following fields: + * + * ... + * char *symbol; + * struct ... *next, *prev, **head, *scope; + * unsigned int hash; + * ... + * + * 'template.h' can be used as a template to create a 'sym.h'. + * + * 'head' is &(table[hash(itself)]). + * The hash table is not resizable at run-time. + * The scope field is used to link all symbols of a current scope together. + * Scope() sets the current scope (linked list) to add symbols to. + * Any number of scopes can be handled. The user passes the address of + * a pointer to a symbol table + * entry (INITIALIZED TO NULL first time). + * + * Available Functions: + * + * zzs_init(s1,s2) -- Create hash table with size s1, string table size s2. + * zzs_done() -- Free hash and string table created with zzs_init(). + * zzs_add(key,rec)-- Add 'rec' with key 'key' to the symbol table. + * zzs_newadd(key) -- create entry; add using 'key' to the symbol table. + * zzs_get(key) -- Return pointer to last record entered under 'key' + * Else return NULL + * zzs_del(p) -- Unlink the entry associated with p. This does + * NOT free 'p' and DOES NOT remove it from a scope + * list. If it was a part of your intermediate code + * tree or another structure. It will still be there. + * It is only removed from further consideration + * by the symbol table. + * zzs_keydel(s) -- Unlink the entry associated with key s. + * Calls zzs_del(p) to unlink. + * zzs_scope(sc) -- Specifies that everything added to the symbol + * table with zzs_add() is added to the list (scope) + * 'sc'. 'sc' is of 'Sym **sc' type and must be + * initialized to NULL before trying to add anything + * to it (passing it to zzs_scope()). Scopes can be + * switched at any time and merely links a set of + * symbol table entries. If a NULL pointer is + * passed, the current scope is returned. + * zzs_rmscope(sc) -- Remove (zzs_del()) all elements of scope 'sc' + * from the symbol table. The entries are NOT + * free()'d. A pointer to the first + * element in the "scope" is returned. The user + * can then manipulate the list as he/she chooses + * (such as freeing them all). NOTE that this + * function sets your scope pointer to NULL, + * but returns a pointer to the list for you to use. + * zzs_stat() -- Print out the symbol table and some relevant stats. + * zzs_new(key) -- Create a new record with calloc() of type Sym. + * Add 'key' to the string table and make the new + * records 'symbol' pointer point to it. + * zzs_strdup(s) -- Add s to the string table and return a pointer + * to it. Very fast allocation routine + * and does not require strlen() nor calloc(). + * + * Example: + * + * #include + * #include "sym.h" + * + * main() + * { + * Sym *scope1=NULL, *scope2=NULL, *a, *p; + * + * zzs_init(101, 100); + * + * a = zzs_new("Apple"); zzs_add(a->symbol, a); -- No scope + * zzs_scope( &scope1 ); -- enter scope 1 + * a = zzs_new("Plum"); zzs_add(a->symbol, a); + * zzs_scope( &scope2 ); -- enter scope 2 + * a = zzs_new("Truck"); zzs_add(a->symbol, a); + * + * p = zzs_get("Plum"); + * if ( p == NULL ) fprintf(stderr, "Hmmm...Can't find 'Plum'\n"); + * + * p = zzs_rmscope(&scope1) + * for (; p!=NULL; p=p->scope) {printf("Scope1: %s\n", p->symbol);} + * p = zzs_rmscope(&scope2) + * for (; p!=NULL; p=p->scope) {printf("Scope2: %s\n", p->symbol);} + * } + * + * Terence Parr + * Purdue University + * February 1990 + * + * CHANGES + * + * Terence Parr + * May 1991 + * Renamed functions to be consistent with ANTLR + * Made HASH macro + * Added zzs_keydel() + * Added zzs_newadd() + * Fixed up zzs_stat() + * + * July 1991 + * Made symbol table entry save its hash code for fast comparison + * during searching etc... + */ + +#include +#if defined(__STDC__) || defined(__USE_PROTOS) +#include +#include +#else +#include +#endif +#include "sym.h" + +#define StrSame 0 + +static Sym **CurScope = NULL; +static unsigned size = 0; +static Sym **table=NULL; +static char *strings; +static char *strp; +static int strsize = 0; + +#ifdef __USE_PROTOS +void zzs_init(int sz,int strs) +#else +void zzs_init(sz, strs) +int sz, strs; +#endif +{ + if ( sz <= 0 || strs <= 0 ) return; + table = (Sym **) calloc(sz, sizeof(Sym *)); + if ( table == NULL ) + { + fprintf(stderr, "Cannot allocate table of size %d\n", sz); + exit(1); + } + strings = (char *) calloc(strs, sizeof(char)); + if ( strings == NULL ) + { + fprintf(stderr, "Cannot allocate string table of size %d\n", strs); + exit(1); + } + size = sz; + strsize = strs; + strp = strings; +} + +#ifdef __USE_PROTOS +void zzs_done(void) +#else +void zzs_done() +#endif +{ + if ( table != NULL ) free( table ); + if ( strings != NULL ) free( strings ); +} + +#ifdef __USE_PROTOS +void zzs_add(char *key,Sym rec) +#else +void zzs_add(key, rec) +char *key; +register Sym *rec; +#endif +{ + register unsigned int h=0; + register char *p=key; + + HASH(p, h); + rec->hash = h; /* save hash code for fast comp later */ + h %= size; + + if ( CurScope != NULL ) {rec->scope = *CurScope; *CurScope = rec;} + rec->next = table[h]; /* Add to doubly-linked list */ + rec->prev = NULL; + if ( rec->next != NULL ) (rec->next)->prev = rec; + table[h] = rec; + rec->head = &(table[h]); +} + +#ifdef __USE_PROTOS +Sym * zzs_get(char *key) +#else +Sym * zzs_get(key) +char *key; +#endif +{ + register unsigned int h=0; + register char *p=key; + register Sym *q; + + HASH(p, h); + + for (q = table[h%size]; q != NULL; q = q->next) + { + if ( q->hash == h ) /* do we even have a chance of matching? */ + if ( strcmp(key, q->symbol) == StrSame ) return( q ); + } + return( NULL ); +} + +/* + * Unlink p from the symbol table. Hopefully, it's actually in the + * symbol table. + * + * If p is not part of a bucket chain of the symbol table, bad things + * will happen. + * + * Will do nothing if all list pointers are NULL + */ +#ifdef __USE_PROTOS +void zzs_del(Sym *p) +#else +void zzs_del(p) +register Sym *p; +#endif +{ + if ( p == NULL ) {fprintf(stderr, "zzs_del(NULL)\n"); exit(1);} + if ( p->prev == NULL ) /* Head of list */ + { + register Sym **t = p->head; + + if ( t == NULL ) return; /* not part of symbol table */ + (*t) = p->next; + if ( (*t) != NULL ) (*t)->prev = NULL; + } + else + { + (p->prev)->next = p->next; + if ( p->next != NULL ) (p->next)->prev = p->prev; + } + p->next = p->prev = NULL; /* not part of symbol table anymore */ + p->head = NULL; +} + +#ifdef __USE_PROTOS +void zzs_keydel(char *key) +#else +void zzs_keydel(key) +char *key; +#endif +{ + Sym *p = zzs_get(key); + + if ( p != NULL ) zzs_del( p ); +} + +/* S c o p e S t u f f */ + +/* Set current scope to 'scope'; return current scope if 'scope' == NULL */ + +#ifdef __USE_PROTOS +Sym ** zzs_scope(Sym **scope) +#else +Sym ** zzs_scope(scope) +Sym **scope; +#endif +{ + if ( scope == NULL ) return( CurScope ); + CurScope = scope; + return( scope ); +} + +/* Remove a scope described by 'scope'. Return pointer to 1st element in scope */ + +#ifdef __USE_PROTOS +Sym * zzs_rmscope(Sym **scope) +#else +Sym * zzs_rmscope(scope) +register Sym **scope; +#endif +{ + register Sym *p; + Sym *start; + + if ( scope == NULL ) return(NULL); + start = p = *scope; + for (; p != NULL; p=p->scope) { zzs_del( p ); } + *scope = NULL; + return( start ); +} + +#ifdef __USE_PROTOS +void zzs_stat(void) +#else +void zzs_stat() +#endif +{ + static unsigned short count[20]; + unsigned int i,n=0,low=0, hi=0; + register Sym **p; + float avg=0.0; + + for (i=0; i<20; i++) count[i] = 0; + for (p=table; p<&(table[size]); p++) + { + register Sym *q = *p; + unsigned int len; + + if ( q != NULL && low==0 ) low = p-table; + len = 0; + if ( q != NULL ) printf("[%d]", p-table); + while ( q != NULL ) + { + len++; + n++; + printf(" %s", q->symbol); + q = q->next; + if ( q == NULL ) printf("\n"); + } + if ( len>=20 ) printf("zzs_stat: count table too small\n"); + else count[len]++; + if ( *p != NULL ) hi = p-table; + } + + printf("Storing %d recs used %d hash positions out of %d\n", + n, size-count[0], size); + printf("%f %% utilization\n", + ((float)(size-count[0]))/((float)size)); + for (i=0; i<20; i++) + { + if ( count[i] != 0 ) + { + avg += (((float)(i*count[i]))/((float)n)) * i; + printf("Buckets of len %d == %d (%f %% of recs)\n", + i, count[i], 100.0*((float)(i*count[i]))/((float)n)); + } + } + printf("Avg bucket length %f\n", avg); + printf("Range of hash function: %d..%d\n", low, hi); +} + +/* + * Given a string, this function allocates and returns a pointer to a + * symbol table record whose "symbol" pointer is reset to a position + * in the string table. + */ + +#ifdef __USE_PROTOS +Sym * zzs_new(char *text) +#else +Sym * zzs_new(text) +char *text; +#endif +{ + Sym *p; + + if ( (p = (Sym *) calloc(1,sizeof(Sym))) == 0 ) + { + fprintf(stderr,"Out of memory\n"); + exit(1); + } + p->symbol = zzs_strdup(text); + + return p; +} + +/* create a new symbol table entry and add it to the symbol table */ + +#ifdef __USE_PROTOS +Sym * zzs_newadd(char *text) +#else +Sym * zzs_newadd(text) +char *text; +#endif +{ + Sym *p = zzs_new(text); + if ( p != NULL ) zzs_add(text, p); + return p; +} + +/* Add a string to the string table and return a pointer to it. + * Bump the pointer into the string table to next avail position. + */ + +#ifdef __USE_PROTOS +char * zzs_strdup(char *s) +#else +char * zzs_strdup(s) +register char *s; +#endif +{ + register char *start=strp; + + while ( *s != '\0' ) + { + if ( strp >= &(strings[strsize-2]) ) + { + fprintf(stderr, "sym: string table overflow (%d chars)\n", strsize); + exit(-1); + } + *strp++ = *s++; + } + *strp++ = '\0'; + + return( start ); +} diff --git a/Tools/Source/TianoTools/Pccts/support/sym/template.h b/Tools/Source/TianoTools/Pccts/support/sym/template.h new file mode 100644 index 0000000000..ee6e665e34 --- /dev/null +++ b/Tools/Source/TianoTools/Pccts/support/sym/template.h @@ -0,0 +1,41 @@ +/* T e m p l a t e F o r S y m b o l T a b l e M a n a g e r */ + +/* define some hash function */ +#ifndef HASH +#define HASH(p, h) while ( *p != '\0' ) h = (h<<1) + *p++; +#endif + +/* minimum symbol table record */ +typedef struct _sym { + char *symbol; + struct _sym *next, *prev, **head, *scope; + unsigned int hash; + } Sym, *SymPtr; + +#ifdef __USE_PROTOS +void zzs_init(int, int); +void zzs_done(void); +void zzs_add(char *, Sym *); +Sym *zzs_get(char *); +void zzs_del(Sym *); +void zzs_keydel(char *); +Sym **zzs_scope(Sym **); +Sym *zzs_rmscope(Sym **); +void zzs_stat(void); +Sym *zzs_new(char *); +Sym *zzs_newadd(char *); +char *zzs_strdup(char *); +#else +void zzs_init(); +void zzs_done(); +void zzs_add(); +Sym *zzs_get(); +void zzs_del(); +void zzs_keydel(); +Sym **zzs_scope(); +Sym *zzs_rmscope(); +void zzs_stat(); +Sym *zzs_new(); +Sym *zzs_newadd(); +char *zzs_strdup(); +#endif diff --git a/Tools/Source/TianoTools/SetStamp/SetStamp.c b/Tools/Source/TianoTools/SetStamp/SetStamp.c new file mode 100644 index 0000000000..539aced1d9 --- /dev/null +++ b/Tools/Source/TianoTools/SetStamp/SetStamp.c @@ -0,0 +1,475 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + SetStamp.c + +Abstract: + Set Date/Time Stamp of Portable Executable (PE) format file + +--*/ + +#include +#include +#include + +#define LINE_MAXLEN 80 + +void +PrintUsage ( + void + ) +/*++ +Routine Description: + print usage of setstamp command + +Arguments: + void + +Returns: + None +--*/ +{ + // + // print usage of command + // + printf ("Usage: SetStamp \n"); +} + +int +GetDateTime ( + FILE *fp, + time_t *ltime + ) +/*++ +Routine Description: + Read the date and time from TIME file. If the date/time string is +"NOW NOW", write the current date and time to TIME file and set it to +ltime. Else, set the date and time of TIME file to ltime. + +Arguments: + fp - The pointer of TIME file + ltime - Date and time + +Returns: + = 0 - Success + = -1 - Failed +--*/ +{ + char buffer[LINE_MAXLEN]; + struct tm stime; + struct tm *now; + + if (fgets (buffer, LINE_MAXLEN, fp) == NULL) { + printf ("Error: Cannot read TIME file.\n"); + return -1; + } + // + // compare the value with "NOW NOW", write TIME file if equal + // + if (strncmp (buffer, "NOW NOW", 7) == 0) { + // + // get system current time and date + // + time (ltime); + + now = localtime (ltime); + if (now == NULL) { + printf ("Error: Cannot get local time.\n"); + return -1; + } + + if (strftime (buffer, LINE_MAXLEN, "%Y-%m-%d %H:%M:%S", now) == 0) { + printf ("Error: Cannot format time string.\n"); + return -1; + } + // + // write TIME file + // + if (fseek (fp, 0, SEEK_SET) != 0) { + printf ("Error: Cannot move location of TIME file.\n"); + return -1; + } + + if (fputs (buffer, fp) == EOF) { + printf ("Error: Cannot write time string to TIME file.\n"); + return -1; + } + // + // ltime has been set as current time and date, return + // + return 0; + } + // + // get the date and time from buffer + // + if (6 != sscanf ( + buffer, + "%d-%d-%d %d:%d:%d", + &stime.tm_year, + &stime.tm_mon, + &stime.tm_mday, + &stime.tm_hour, + &stime.tm_min, + &stime.tm_sec + )) { + printf ("Error: Invaild date or time!\n"); + return -1; + } + // + // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it + // + stime.tm_mon -= 1; + + // + // in struct, Year (current year minus 1900) + // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038 + // + // + // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038) + // + if (stime.tm_year <= 38) { + stime.tm_year += 100; + } + // + // convert 1970 -> 70, 2000 -> 100, ... + // + else if (stime.tm_year >= 1970) { + stime.tm_year -= 1900; + } + // + // convert the date and time to time_t format + // + *ltime = mktime (&stime); + if (*ltime == (time_t) - 1) { + printf ("Error: Invalid date or time!\n"); + return -1; + } + + return 0; +} + +int +ReadFromFile ( + FILE *fp, + long offset, + void *buffer, + int size + ) +/*++ +Routine Description: + read data from a specified location of file + +Arguments: + fp - file pointer + offset - number of bytes from beginning of file + buffer - buffer used to store data + size - size of buffer + +Returns: + = 0 - Success + = -1 - Failed +--*/ +{ + // + // set file pointer to the specified location of file + // + if (fseek (fp, offset, SEEK_SET) != 0) { + printf ("Error: Cannot move the current location of the file.\n"); + return -1; + } + // + // read data from the file + // + if (fread (buffer, size, 1, fp) != 1) { + printf ("Error: Cannot read data from the file.\n"); + return -1; + } + + return 0; +} + +int +WriteToFile ( + FILE *fp, + long offset, + void *buffer, + int size + ) +/*++ +Routine Description: + write data to a specified location of file + +Arguments: + fp - file pointer + offset - number of bytes from beginning of file + buffer - buffer used to store data + size - size of buffer + +Returns: + = 0 - Success + = -1 - Failed +--*/ +{ + // + // set file pointer to the specified location of file + // + if (fseek (fp, offset, SEEK_SET) != 0) { + printf ("Error: Cannot move the current location of the file.\n"); + return -1; + } + // + // write data to the file + // + if (fwrite (buffer, size, 1, fp) != 1) { + perror ("Error: Cannot write data to the file.\n"); + return -1; + } + + return 0; +} + +int +SetStamp ( + FILE *fp, + time_t ltime + ) +/*++ +Routine Description: + set Date/Time Stamp of the file + +Arguments: + fp - file pointer + ltime - time and date + +Returns: + = 0 - Success + = -1 - Failed +--*/ +{ + unsigned char header[4]; + unsigned long offset; + unsigned long NumberOfRvaAndSizes; + unsigned int nvalue; + unsigned long lvalue; + + // + // read the header of file + // + if (ReadFromFile (fp, 0, header, 2) != 0) { + return -1; + } + // + // "MZ" -- the header of image file (PE) + // + if (strncmp ((char *) header, "MZ", 2) != 0) { + printf ("Error: Invalid Image file.\n"); + return -1; + } + // + // At location 0x3C, the stub has the file offset to the + // PE signature. + // + if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) { + return -1; + } + // + // read the header of optional + // + if (ReadFromFile (fp, offset, header, 4) != 0) { + return -1; + } + // + // "PE\0\0" -- the signature of optional header + // + if (strncmp ((char *) header, "PE\0\0", 4) != 0) { + printf ("Error: Invalid PE format file.\n"); + return -1; + } + // + // Add 8 to skip PE signature (4-byte), Machine (2-byte) and + // NumberOfSection (2-byte) + // + offset += 8; + + if (WriteToFile (fp, offset, <ime, 4) != 0) { + return -1; + } + // + // Add 16 to skip COFF file header, and get to optional header. + // + offset += 16; + + // + // Check the magic field, 0x10B for PE32 and 0x20B for PE32+ + // + if (ReadFromFile (fp, offset, &nvalue, 2) != 0) { + return -1; + } + // + // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92. + // Else it is 108. + // + switch (nvalue & 0xFFFF) { + case 0x10B: + offset += 92; + break; + + case 0x20B: + offset += 108; + break; + + default: + printf ("Error: Sorry! The Magic value is unknown.\n"); + return -1; + } + // + // get the value of NumberOfRvaAndSizes + // + if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) { + return -1; + } + // + // Date/time stamp exists in Export Table, Import Table, Resource Table, + // Debug Table and Delay Import Table. And in Import Table and Delay Import + // Table, it will be set when bound. So here only set the date/time stamp + // of Export Table, Resource Table and Debug Table. + // + // + // change date/time stamp of Export Table, the offset of Export Table + // is 4 + 0 * 8 = 4. And the offset of stamp is 4. + // + if (NumberOfRvaAndSizes >= 1) { + if (ReadFromFile (fp, offset + 4, &lvalue, 4) != 0) { + return -1; + } + + if (lvalue != 0) { + if (WriteToFile (fp, lvalue + 4, <ime, 4) != 0) { + return -1; + } + } + } + // + // change date/time stamp of Resource Table, the offset of Resource Table + // is 4 + 2 * 8 = 20. And the offset of stamp is 4. + // + if (NumberOfRvaAndSizes >= 3) { + if (ReadFromFile (fp, offset + 20, &lvalue, 4) != 0) { + return -1; + } + + if (lvalue != 0) { + if (WriteToFile (fp, lvalue + 4, <ime, 4) != 0) { + return -1; + } + } + } + // + // change date/time stamp of Debug Table, offset of Debug Table + // is 4 + 6 * 8 = 52. And the offset of stamp is 4. + // + if (NumberOfRvaAndSizes >= 7) { + if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) { + return -1; + } + + if (lvalue != 0) { + if (WriteToFile (fp, lvalue + 4, <ime, 4) != 0) { + return -1; + } + } + // + // change the date/time stamp of Debug Data + // + if (ReadFromFile (fp, lvalue + 24, &lvalue, 4) != 0) { + return -1; + } + // + // get the signature of debug data + // + if (ReadFromFile (fp, lvalue, header, 2) != 0) { + return -1; + } + // + // "NB" - the signature of Debug Data + // Need Review: (From Spec. is "NB05", From .dll is "NB10") + // + if (strncmp ((char *) header, "NB", 2) == 0) { + if (WriteToFile (fp, lvalue + 8, <ime, 4) != 0) { + return -1; + } + } + } + + return 0; +} + +int +main ( + int argc, + char *argv[] + ) +{ + FILE *fp; + time_t ltime; + + // + // check the number of parameters + // + if (argc != 3) { + PrintUsage (); + return -1; + } + // + // open the TIME file, if not exists, return + // + fp = fopen (argv[2], "r+"); + if (fp == NULL) { + return 0; + } + // + // get time and date from file + // + if (GetDateTime (fp, <ime) != 0) { + fclose (fp); + return -1; + } + // + // close the TIME file + // + fclose (fp); + + // + // open the PE file + // + fp = fopen (argv[1], "r+b"); + if (fp == NULL) { + printf ("Error: Cannot open the PE file!\n"); + return -1; + } + // + // set time and date stamp to the PE file + // + if (SetStamp (fp, ltime) != 0) { + fclose (fp); + return -1; + } + + printf ("Set Date/Time Stamp to %s", ctime (<ime)); + + // + // close the PE file + // + fclose (fp); + + return 0; +} diff --git a/Tools/Source/TianoTools/SetStamp/build.gcc b/Tools/Source/TianoTools/SetStamp/build.gcc new file mode 100644 index 0000000000..4e234ea84d --- /dev/null +++ b/Tools/Source/TianoTools/SetStamp/build.gcc @@ -0,0 +1,2 @@ +gcc -mno-cygwin -c -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ -I../Common -I$WORKSPACE/MdePkg/Include/ -I$WORKSPACE/MdePkg/Include/Ia32 -I. SetStamp.c +gcc -mno-cygwin -o SetStamp SetStamp.o diff --git a/Tools/Source/TianoTools/SetStamp/build.xml b/Tools/Source/TianoTools/SetStamp/build.xml new file mode 100644 index 0000000000..95cb4a0490 --- /dev/null +++ b/Tools/Source/TianoTools/SetStamp/build.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/StrGather/StrGather.c b/Tools/Source/TianoTools/StrGather/StrGather.c new file mode 100644 index 0000000000..3ad77247ae --- /dev/null +++ b/Tools/Source/TianoTools/StrGather/StrGather.c @@ -0,0 +1,2531 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + StrGather.c + +Abstract: + + Parse a strings file and create or add to a string database file. + +--*/ + +#include +#include +#include +#include + +#include +#include +#include +#include "EfiUtilityMsgs.h" +#include "StrGather.h" +#include "StringDB.h" + +#define TOOL_VERSION "0.31" + +#ifndef MAX_PATH +#define MAX_PATH 255 +#endif +#define MAX_NEST_DEPTH 20 // just in case we get in an endless loop. +#define MAX_STRING_IDENTIFIER_NAME 100 // number of wchars +#define MAX_LINE_LEN 200 +#define STRING_TOKEN "STRING_TOKEN" +#define DEFAULT_BASE_NAME "BaseName" +// +// Operational modes for this utility +// +#define MODE_UNKNOWN 0 +#define MODE_PARSE 1 +#define MODE_SCAN 2 +#define MODE_DUMP 3 + +// +// We keep a linked list of these for the source files we process +// +typedef struct _SOURCE_FILE { + FILE *Fptr; + WCHAR *FileBuffer; + WCHAR *FileBufferPtr; + UINT32 FileSize; + INT8 FileName[MAX_PATH]; + UINT32 LineNum; + BOOLEAN EndOfFile; + BOOLEAN SkipToHash; + struct _SOURCE_FILE *Previous; + struct _SOURCE_FILE *Next; + WCHAR ControlCharacter; +} SOURCE_FILE; + +#define DEFAULT_CONTROL_CHARACTER UNICODE_SLASH + +// +// Here's all our globals. We need a linked list of include paths, a linked +// list of source files, a linked list of subdirectories (appended to each +// include path when searching), and a couple other fields. +// +static struct { + SOURCE_FILE SourceFiles; + TEXT_STRING_LIST *IncludePaths; // all include paths to search + TEXT_STRING_LIST *LastIncludePath; + TEXT_STRING_LIST *ScanFileName; + TEXT_STRING_LIST *LastScanFileName; + TEXT_STRING_LIST *SkipExt; // if -skipext .uni + TEXT_STRING_LIST *LastSkipExt; + TEXT_STRING_LIST *IndirectionFileName; + TEXT_STRING_LIST *LastIndirectionFileName; + TEXT_STRING_LIST *DatabaseFileName; + TEXT_STRING_LIST *LastDatabaseFileName; + WCHAR_STRING_LIST *Language; + WCHAR_STRING_LIST *LastLanguage; + WCHAR_MATCHING_STRING_LIST *IndirectionList; // from indirection file(s) + WCHAR_MATCHING_STRING_LIST *LastIndirectionList; + BOOLEAN Verbose; // for more detailed output + BOOLEAN VerboseDatabaseWrite; // for more detailed output when writing database + BOOLEAN VerboseDatabaseRead; // for more detailed output when reading database + BOOLEAN NewDatabase; // to start from scratch + BOOLEAN IgnoreNotFound; // when scanning + BOOLEAN VerboseScan; + BOOLEAN UnquotedStrings; // -uqs option + INT8 OutputDatabaseFileName[MAX_PATH]; + INT8 StringHFileName[MAX_PATH]; + INT8 StringCFileName[MAX_PATH]; // output .C filename + INT8 DumpUFileName[MAX_PATH]; // output unicode dump file name + INT8 HiiExportPackFileName[MAX_PATH]; // HII export pack file name + INT8 BaseName[MAX_PATH]; // base filename of the strings file + UINT32 Mode; +} mGlobals; + +static +BOOLEAN +IsValidIdentifierChar ( + INT8 Char, + BOOLEAN FirstChar + ); + +static +void +RewindFile ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +SkipTo ( + SOURCE_FILE *SourceFile, + WCHAR WChar, + BOOLEAN StopAfterNewline + ); + +static +UINT32 +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ); + +static +void +PreprocessFile ( + SOURCE_FILE *SourceFile + ); + +static +UINT32 +GetStringIdentifierName ( + IN SOURCE_FILE *SourceFile, + IN OUT WCHAR *StringIdentifierName, + IN UINT32 StringIdentifierNameLen + ); + +static +UINT32 +GetLanguageIdentifierName ( + IN SOURCE_FILE *SourceFile, + IN OUT WCHAR *LanguageIdentifierName, + IN UINT32 LanguageIdentifierNameLen, + IN BOOLEAN Optional + ); + +static +WCHAR * +GetPrintableLanguageName ( + IN SOURCE_FILE *SourceFile + ); + +static +STATUS +AddCommandLineLanguage ( + IN INT8 *Language + ); + +static +WCHAR * +GetQuotedString ( + SOURCE_FILE *SourceFile, + BOOLEAN Optional + ); + +static +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ); + +static +STATUS +ParseFile ( + SOURCE_FILE *SourceFile + ); + +static +FILE * +FindFile ( + IN INT8 *FileName, + OUT INT8 *FoundFileName, + IN UINT32 FoundFileNameLen + ); + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ); + +static +STATUS +ProcessFile ( + SOURCE_FILE *SourceFile + ); + +static +UINT32 +wstrcmp ( + WCHAR *Buffer, + WCHAR *Str + ); + +static +void +Usage ( + VOID + ); + +static +void +FreeLists ( + VOID + ); + +static +void +ProcessTokenString ( + SOURCE_FILE *SourceFile + ); + +static +void +ProcessTokenInclude ( + SOURCE_FILE *SourceFile + ); + +static +void +ProcessTokenScope ( + SOURCE_FILE *SourceFile + ); + +static +void +ProcessTokenLanguage ( + SOURCE_FILE *SourceFile + ); + +static +void +ProcessTokenLangDef ( + SOURCE_FILE *SourceFile + ); + +static +STATUS +ScanFiles ( + TEXT_STRING_LIST *ScanFiles + ); + +static +STATUS +ParseIndirectionFiles ( + TEXT_STRING_LIST *Files + ); + +STATUS +StringDBCreateHiiExportPack ( + INT8 *OutputFileName + ); + +int +main ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + + Call the routine to parse the command-line options, then process the file. + +Arguments: + + Argc - Standard C main() argc and argv. + Argv - Standard C main() argc and argv. + +Returns: + + 0 if successful + nonzero otherwise + +--*/ +{ + STATUS Status; + + SetUtilityName (PROGRAM_NAME); + // + // Process the command-line arguments + // + Status = ProcessArgs (Argc, Argv); + if (Status != STATUS_SUCCESS) { + return Status; + } + // + // Initialize the database manager + // + StringDBConstructor (); + // + // We always try to read in an existing database file. It may not + // exist, which is ok usually. + // + if (mGlobals.NewDatabase == 0) { + // + // Read all databases specified. + // + for (mGlobals.LastDatabaseFileName = mGlobals.DatabaseFileName; + mGlobals.LastDatabaseFileName != NULL; + mGlobals.LastDatabaseFileName = mGlobals.LastDatabaseFileName->Next + ) { + Status = StringDBReadDatabase (mGlobals.LastDatabaseFileName->Str, TRUE, mGlobals.VerboseDatabaseRead); + if (Status != STATUS_SUCCESS) { + return Status; + } + } + } + // + // Read indirection file(s) if specified + // + if (ParseIndirectionFiles (mGlobals.IndirectionFileName) != STATUS_SUCCESS) { + goto Finish; + } + // + // If scanning source files, do that now + // + if (mGlobals.Mode == MODE_SCAN) { + ScanFiles (mGlobals.ScanFileName); + } else if (mGlobals.Mode == MODE_PARSE) { + // + // Parsing a unicode strings file + // + mGlobals.SourceFiles.ControlCharacter = DEFAULT_CONTROL_CHARACTER; + Status = ProcessIncludeFile (&mGlobals.SourceFiles, NULL); + if (Status != STATUS_SUCCESS) { + goto Finish; + } + } + // + // Create the string defines header file if there have been no errors. + // + ParserSetPosition (NULL, 0); + if ((mGlobals.StringHFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) { + Status = StringDBDumpStringDefines (mGlobals.StringHFileName, mGlobals.BaseName); + if (Status != EFI_SUCCESS) { + goto Finish; + } + } + // + // Dump the strings to a .c file if there have still been no errors. + // + if ((mGlobals.StringCFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) { + Status = StringDBDumpCStrings ( + mGlobals.StringCFileName, + mGlobals.BaseName, + mGlobals.Language, + mGlobals.IndirectionList + ); + if (Status != EFI_SUCCESS) { + goto Finish; + } + } + // + // Dump the database if requested + // + if ((mGlobals.DumpUFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) { + StringDBDumpDatabase (NULL, mGlobals.DumpUFileName, FALSE); + } + // + // Dump the string data as HII binary string pack if requested + // + if ((mGlobals.HiiExportPackFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) { + StringDBCreateHiiExportPack (mGlobals.HiiExportPackFileName); + } + // + // Always update the database if no errors and not in dump mode. If they specified -od + // for an output database file name, then use that name. Otherwise use the name of + // the first database file specified with -db + // + if ((mGlobals.Mode != MODE_DUMP) && (GetUtilityStatus () < STATUS_ERROR)) { + if (mGlobals.OutputDatabaseFileName[0]) { + Status = StringDBWriteDatabase (mGlobals.OutputDatabaseFileName, mGlobals.VerboseDatabaseWrite); + } else { + Status = StringDBWriteDatabase (mGlobals.DatabaseFileName->Str, mGlobals.VerboseDatabaseWrite); + } + + if (Status != EFI_SUCCESS) { + goto Finish; + } + } + +Finish: + // + // Free up memory + // + FreeLists (); + StringDBDestructor (); + return GetUtilityStatus (); +} + +static +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ) +/*++ + +Routine Description: + + Given a source file, open the file and parse it + +Arguments: + + SourceFile - name of file to parse + ParentSourceFile - for error reporting purposes, the file that #included SourceFile. + +Returns: + + Standard status. + +--*/ +{ + static UINT32 NestDepth = 0; + INT8 FoundFileName[MAX_PATH]; + STATUS Status; + + Status = STATUS_SUCCESS; + NestDepth++; + // + // Print the file being processed. Indent so you can tell the include nesting + // depth. + // + if (mGlobals.Verbose) { + fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName); + } + + // + // Make sure we didn't exceed our maximum nesting depth + // + if (NestDepth > MAX_NEST_DEPTH) { + Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", NestDepth); + Status = STATUS_ERROR; + goto Finish; + } + // + // Try to open the file locally, and if that fails try along our include paths. + // + strcpy (FoundFileName, SourceFile->FileName); + if ((SourceFile->Fptr = fopen (FoundFileName, "rb")) == NULL) { + // + // Try to find it among the paths if it has a parent (that is, it is included + // by someone else). + // + if (ParentSourceFile == NULL) { + Error (NULL, 0, 0, SourceFile->FileName, "file not found"); + return STATUS_ERROR; + } + + SourceFile->Fptr = FindFile (SourceFile->FileName, FoundFileName, sizeof (FoundFileName)); + if (SourceFile->Fptr == NULL) { + Error (ParentSourceFile->FileName, ParentSourceFile->LineNum, 0, SourceFile->FileName, "include file not found"); + return STATUS_ERROR; + } + } + // + // Process the file found + // + ProcessFile (SourceFile); +Finish: + // + // Close open files and return status + // + if (SourceFile->Fptr != NULL) { + fclose (SourceFile->Fptr); + } + + return Status; +} + +static +STATUS +ProcessFile ( + SOURCE_FILE *SourceFile + ) +{ + // + // Get the file size, and then read the entire thing into memory. + // Allocate space for a terminator character. + // + fseek (SourceFile->Fptr, 0, SEEK_END); + SourceFile->FileSize = ftell (SourceFile->Fptr); + fseek (SourceFile->Fptr, 0, SEEK_SET); + SourceFile->FileBuffer = (WCHAR *) malloc (SourceFile->FileSize + sizeof (WCHAR)); + if (SourceFile->FileBuffer == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr); + SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (WCHAR))] = UNICODE_NULL; + // + // Pre-process the file to replace comments with spaces + // + PreprocessFile (SourceFile); + // + // Parse the file + // + ParseFile (SourceFile); + free (SourceFile->FileBuffer); + return STATUS_SUCCESS; +} + +static +STATUS +ParseFile ( + SOURCE_FILE *SourceFile + ) +{ + BOOLEAN InComment; + UINT32 Len; + + // + // First character of a unicode file is special. Make sure + // + if (SourceFile->FileBufferPtr[0] != UNICODE_FILE_START) { + Error (SourceFile->FileName, 1, 0, SourceFile->FileName, "file does not appear to be a unicode file"); + return STATUS_ERROR; + } + + SourceFile->FileBufferPtr++; + InComment = FALSE; + // + // Print the first line if in verbose mode + // + if (mGlobals.Verbose) { + printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr); + } + // + // Since the syntax is relatively straightforward, just switch on the next char + // + while (!EndOfFile (SourceFile)) { + // + // Check for whitespace + // + if (SourceFile->FileBufferPtr[0] == UNICODE_SPACE) { + SourceFile->FileBufferPtr++; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_TAB) { + SourceFile->FileBufferPtr++; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) { + SourceFile->FileBufferPtr++; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_LF) { + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + if (mGlobals.Verbose) { + printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr); + } + + InComment = FALSE; + } else if (SourceFile->FileBufferPtr[0] == 0) { + SourceFile->FileBufferPtr++; + } else if (InComment) { + SourceFile->FileBufferPtr++; + } else if ((SourceFile->FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile->FileBufferPtr[1] == UNICODE_SLASH)) { + SourceFile->FileBufferPtr += 2; + InComment = TRUE; + } else if (SourceFile->SkipToHash && (SourceFile->FileBufferPtr[0] != SourceFile->ControlCharacter)) { + SourceFile->FileBufferPtr++; + } else { + SourceFile->SkipToHash = FALSE; + if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + ((Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"include")) > 0) + ) { + SourceFile->FileBufferPtr += Len + 1; + ProcessTokenInclude (SourceFile); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"scope")) > 0 + ) { + SourceFile->FileBufferPtr += Len + 1; + ProcessTokenScope (SourceFile); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"language")) > 0 + ) { + SourceFile->FileBufferPtr += Len + 1; + ProcessTokenLanguage (SourceFile); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"langdef")) > 0 + ) { + SourceFile->FileBufferPtr += Len + 1; + ProcessTokenLangDef (SourceFile); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"string")) > 0 + ) { + SourceFile->FileBufferPtr += Len + 1; + ProcessTokenString (SourceFile); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"EFI_BREAKPOINT()")) > 0 + ) { + SourceFile->FileBufferPtr += Len; + // + // BUGBUG: Caling EFI_BREAKOINT() is breaking the link. What is the proper action for this tool + // in this condition? + // +// EFI_BREAKPOINT (); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (SourceFile->FileBufferPtr[1] == UNICODE_EQUAL_SIGN) + ) { + SourceFile->ControlCharacter = SourceFile->FileBufferPtr[2]; + SourceFile->FileBufferPtr += 3; + } else { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "unrecognized token", "%S", SourceFile->FileBufferPtr); + // + // Treat rest of line as a comment. + // + InComment = TRUE; + } + } + } + + return STATUS_SUCCESS; +} + +static +void +PreprocessFile ( + SOURCE_FILE *SourceFile + ) +/*++ + +Routine Description: + Preprocess a file to replace all carriage returns with NULLs so + we can print lines from the file to the screen. + +Arguments: + SourceFile - structure that we use to keep track of an input file. + +Returns: + Nothing. + +--*/ +{ + BOOLEAN InComment; + + RewindFile (SourceFile); + InComment = FALSE; + while (!EndOfFile (SourceFile)) { + // + // If a line-feed, then no longer in a comment + // + if (SourceFile->FileBufferPtr[0] == UNICODE_LF) { + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + InComment = 0; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) { + // + // Replace all carriage returns with a NULL so we can print stuff + // + SourceFile->FileBufferPtr[0] = 0; + SourceFile->FileBufferPtr++; + } else if (InComment) { + SourceFile->FileBufferPtr[0] = UNICODE_SPACE; + SourceFile->FileBufferPtr++; + } else if ((SourceFile->FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile->FileBufferPtr[1] == UNICODE_SLASH)) { + SourceFile->FileBufferPtr += 2; + InComment = TRUE; + } else { + SourceFile->FileBufferPtr++; + } + } + // + // Could check for end-of-file and still in a comment, but + // should not be necessary. So just restore the file pointers. + // + RewindFile (SourceFile); +} + +static +WCHAR * +GetPrintableLanguageName ( + IN SOURCE_FILE *SourceFile + ) +{ + WCHAR *String; + WCHAR *Start; + WCHAR *Ptr; + UINT32 Len; + + SkipWhiteSpace (SourceFile); + if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + "expected quoted printable language name", + "%S", + SourceFile->FileBufferPtr + ); + SourceFile->SkipToHash = TRUE; + return NULL; + } + + Len = 0; + SourceFile->FileBufferPtr++; + Start = Ptr = SourceFile->FileBufferPtr; + while (!EndOfFile (SourceFile)) { + if (SourceFile->FileBufferPtr[0] == UNICODE_CR) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start); + break; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) { + break; + } + + SourceFile->FileBufferPtr++; + Len++; + } + + if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) { + Warning ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + "missing closing quote on printable language name string", + "%S", + Start + ); + } else { + SourceFile->FileBufferPtr++; + } + // + // Now allocate memory for the string and save it off + // + String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR)); + if (String == NULL) { + Error (NULL, 0, 0, "memory allocation failed", NULL); + return NULL; + } + // + // Copy the string from the file buffer to the local copy. + // We do no reformatting of it whatsoever at this point. + // + Ptr = String; + while (Len > 0) { + *Ptr = *Start; + Start++; + Ptr++; + Len--; + } + + *Ptr = 0; + // + // Now format the string to convert \wide and \narrow controls + // + StringDBFormatString (String); + return String; +} + +static +WCHAR * +GetQuotedString ( + SOURCE_FILE *SourceFile, + BOOLEAN Optional + ) +{ + WCHAR *String; + WCHAR *Start; + WCHAR *Ptr; + UINT32 Len; + BOOLEAN PreviousBackslash; + + if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) { + if (!Optional) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr); + } + + return NULL; + } + + Len = 0; + SourceFile->FileBufferPtr++; + Start = Ptr = SourceFile->FileBufferPtr; + PreviousBackslash = FALSE; + while (!EndOfFile (SourceFile)) { + if ((SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) && (!PreviousBackslash)) { + break; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start); + PreviousBackslash = FALSE; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_BACKSLASH) { + PreviousBackslash = TRUE; + } else { + PreviousBackslash = FALSE; + } + + SourceFile->FileBufferPtr++; + Len++; + } + + if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start); + } else { + SourceFile->FileBufferPtr++; + } + // + // Now allocate memory for the string and save it off + // + String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR)); + if (String == NULL) { + Error (NULL, 0, 0, "memory allocation failed", NULL); + return NULL; + } + // + // Copy the string from the file buffer to the local copy. + // We do no reformatting of it whatsoever at this point. + // + Ptr = String; + while (Len > 0) { + *Ptr = *Start; + Start++; + Ptr++; + Len--; + } + + *Ptr = 0; + return String; +} +// +// Parse: +// #string STR_ID_NAME +// +// All we can do is call the string database to add the string identifier. Unfortunately +// he'll have to keep track of the last identifier we added. +// +static +void +ProcessTokenString ( + SOURCE_FILE *SourceFile + ) +{ + WCHAR StringIdentifier[MAX_STRING_IDENTIFIER_NAME]; + UINT16 StringId; + // + // Extract the string identifier name and add it to the database. + // + if (GetStringIdentifierName (SourceFile, StringIdentifier, sizeof (StringIdentifier)) > 0) { + StringId = STRING_ID_INVALID; + StringDBAddStringIdentifier (StringIdentifier, &StringId, 0); + } else { + // + // Error recovery -- skip to the next # + // + SourceFile->SkipToHash = TRUE; + } +} + +static +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ) +{ + // + // The file buffer pointer will typically get updated before the End-of-file flag in the + // source file structure, so check it first. + // + if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (WCHAR)) { + SourceFile->EndOfFile = TRUE; + return TRUE; + } + + if (SourceFile->EndOfFile) { + return TRUE; + } + + return FALSE; +} + +static +UINT32 +GetStringIdentifierName ( + IN SOURCE_FILE *SourceFile, + IN OUT WCHAR *StringIdentifierName, + IN UINT32 StringIdentifierNameLen + ) +{ + UINT32 Len; + WCHAR *From; + WCHAR *Start; + + // + // Skip whitespace + // + SkipWhiteSpace (SourceFile); + if (SourceFile->EndOfFile) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-file encountered", "expected string identifier"); + return 0; + } + // + // Verify first character of name is [A-Za-z] + // + Len = 0; + StringIdentifierNameLen /= 2; + From = SourceFile->FileBufferPtr; + Start = SourceFile->FileBufferPtr; + if (((SourceFile->FileBufferPtr[0] >= UNICODE_A) && (SourceFile->FileBufferPtr[0] <= UNICODE_Z)) || + ((SourceFile->FileBufferPtr[0] >= UNICODE_z) && (SourceFile->FileBufferPtr[0] <= UNICODE_z)) + ) { + // + // Do nothing + // + } else { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid character in string identifier name", "%S", Start); + return 0; + } + + while (!EndOfFile (SourceFile)) { + if (((SourceFile->FileBufferPtr[0] >= UNICODE_A) && (SourceFile->FileBufferPtr[0] <= UNICODE_Z)) || + ((SourceFile->FileBufferPtr[0] >= UNICODE_z) && (SourceFile->FileBufferPtr[0] <= UNICODE_z)) || + ((SourceFile->FileBufferPtr[0] >= UNICODE_0) && (SourceFile->FileBufferPtr[0] <= UNICODE_9)) || + (SourceFile->FileBufferPtr[0] == UNICODE_UNDERSCORE) + ) { + Len++; + if (Len >= StringIdentifierNameLen) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "string identifier name too long", "%S", Start); + return 0; + } + + *StringIdentifierName = SourceFile->FileBufferPtr[0]; + StringIdentifierName++; + SourceFile->FileBufferPtr++; + } else if (SkipWhiteSpace (SourceFile) == 0) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid string identifier name", "%S", Start); + return 0; + } else { + break; + } + } + // + // Terminate the copy of the string. + // + *StringIdentifierName = 0; + return Len; +} + +static +UINT32 +GetLanguageIdentifierName ( + IN SOURCE_FILE *SourceFile, + IN OUT WCHAR *LanguageIdentifierName, + IN UINT32 LanguageIdentifierNameLen, + IN BOOLEAN Optional + ) +{ + UINT32 Len; + WCHAR *From; + WCHAR *Start; + // + // Skip whitespace + // + SkipWhiteSpace (SourceFile); + if (SourceFile->EndOfFile) { + if (!Optional) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + "end-of-file encountered", + "expected language identifier" + ); + } + + return 0; + } + // + // This function is called to optionally get a language identifier name in: + // #string STR_ID eng "the string" + // If it's optional, and we find a double-quote, then return now. + // + if (Optional) { + if (*SourceFile->FileBufferPtr == UNICODE_DOUBLE_QUOTE) { + return 0; + } + } + + Len = 0; + LanguageIdentifierNameLen /= 2; + // + // Internal error if we weren't given at least 4 WCHAR's to work with. + // + if (LanguageIdentifierNameLen < LANGUAGE_IDENTIFIER_NAME_LEN + 1) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + "app error -- language identifier name length is invalid", + NULL + ); + } + + From = SourceFile->FileBufferPtr; + Start = SourceFile->FileBufferPtr; + while (!EndOfFile (SourceFile)) { + if (((SourceFile->FileBufferPtr[0] >= UNICODE_a) && (SourceFile->FileBufferPtr[0] <= UNICODE_z))) { + Len++; + if (Len > LANGUAGE_IDENTIFIER_NAME_LEN) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "language identifier name too long", "%S", Start); + return 0; + } + + *LanguageIdentifierName = SourceFile->FileBufferPtr[0]; + SourceFile->FileBufferPtr++; + LanguageIdentifierName++; + } else if (!IsWhiteSpace (SourceFile)) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid language identifier name", "%S", Start); + return 0; + } else { + break; + } + } + // + // Terminate the copy of the string. + // + *LanguageIdentifierName = 0; + return Len; +} + +static +void +ProcessTokenInclude ( + SOURCE_FILE *SourceFile + ) +{ + INT8 IncludeFileName[MAX_PATH]; + INT8 *To; + UINT32 Len; + BOOLEAN ReportedError; + SOURCE_FILE IncludedSourceFile; + + ReportedError = FALSE; + if (SkipWhiteSpace (SourceFile) == 0) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL); + } + // + // Should be quoted file name + // + if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL); + goto FailDone; + } + + SourceFile->FileBufferPtr++; + // + // Copy the filename as ascii to our local string + // + To = IncludeFileName; + Len = 0; + while (!EndOfFile (SourceFile)) { + if ((SourceFile->FileBufferPtr[0] == UNICODE_CR) || (SourceFile->FileBufferPtr[0] == UNICODE_LF)) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL); + goto FailDone; + } + + if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) { + SourceFile->FileBufferPtr++; + break; + } + // + // If too long, then report the error once and process until the closing quote + // + Len++; + if (!ReportedError && (Len >= sizeof (IncludeFileName))) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL); + ReportedError = TRUE; + } + + if (!ReportedError) { + *To = UNICODE_TO_ASCII (SourceFile->FileBufferPtr[0]); + To++; + } + + SourceFile->FileBufferPtr++; + } + + if (!ReportedError) { + *To = 0; + memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE)); + strcpy (IncludedSourceFile.FileName, IncludeFileName); + IncludedSourceFile.ControlCharacter = DEFAULT_CONTROL_CHARACTER; + ProcessIncludeFile (&IncludedSourceFile, SourceFile); + // + // printf ("including file '%s'\n", IncludeFileName); + // + } + + return ; +FailDone: + // + // Error recovery -- skip to next # + // + SourceFile->SkipToHash = TRUE; +} + +static +void +ProcessTokenScope ( + SOURCE_FILE *SourceFile + ) +{ + WCHAR StringIdentifier[MAX_STRING_IDENTIFIER_NAME]; + // + // Extract the scope name + // + if (GetStringIdentifierName (SourceFile, StringIdentifier, sizeof (StringIdentifier)) > 0) { + StringDBSetScope (StringIdentifier); + } +} +// +// Parse: #langdef eng "English" +// #langdef chn "\wideChinese" +// +static +void +ProcessTokenLangDef ( + SOURCE_FILE *SourceFile + ) +{ + WCHAR LanguageIdentifier[MAX_STRING_IDENTIFIER_NAME]; + UINT32 Len; + WCHAR *PrintableName; + // + // Extract the 3-character language identifier + // + Len = GetLanguageIdentifierName (SourceFile, LanguageIdentifier, sizeof (LanguageIdentifier), FALSE); + if (Len != LANGUAGE_IDENTIFIER_NAME_LEN) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid or missing language identifier", NULL); + } else { + // + // Extract the printable name + // + PrintableName = GetPrintableLanguageName (SourceFile); + if (PrintableName != NULL) { + ParserSetPosition (SourceFile->FileName, SourceFile->LineNum); + StringDBAddLanguage (LanguageIdentifier, PrintableName); + free (PrintableName); + return ; + } + } + // + // Error recovery -- skip to next # + // + SourceFile->SkipToHash = TRUE; +} + +static +BOOLEAN +ApparentQuotedString ( + SOURCE_FILE *SourceFile + ) +{ + WCHAR *Ptr; + // + // See if the first and last nonblank characters on the line are double quotes + // + for (Ptr = SourceFile->FileBufferPtr; *Ptr && (*Ptr == UNICODE_SPACE); Ptr++) + ; + if (*Ptr != UNICODE_DOUBLE_QUOTE) { + return FALSE; + } + + while (*Ptr) { + Ptr++; + } + + Ptr--; + for (; *Ptr && (*Ptr == UNICODE_SPACE); Ptr--) + ; + if (*Ptr != UNICODE_DOUBLE_QUOTE) { + return FALSE; + } + + return TRUE; +} +// +// Parse: +// #language eng "some string " "more string" +// +static +void +ProcessTokenLanguage ( + SOURCE_FILE *SourceFile + ) +{ + WCHAR *String; + WCHAR *SecondString; + WCHAR *TempString; + WCHAR *From; + WCHAR *To; + WCHAR Language[LANGUAGE_IDENTIFIER_NAME_LEN + 1]; + UINT32 Len; + BOOLEAN PreviousNewline; + // + // Get the language identifier + // + Language[0] = 0; + Len = GetLanguageIdentifierName (SourceFile, Language, sizeof (Language), TRUE); + if (Len != LANGUAGE_IDENTIFIER_NAME_LEN) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid or missing language identifier", "%S", Language); + SourceFile->SkipToHash = TRUE; + return ; + } + // + // Extract the string value. It's either a quoted string that starts on the current line, or + // an unquoted string that starts on the following line and continues until the next control + // character in column 1. + // Look ahead to find a quote or a newline + // + if (SkipTo (SourceFile, UNICODE_DOUBLE_QUOTE, TRUE)) { + String = GetQuotedString (SourceFile, FALSE); + if (String != NULL) { + // + // Set the position in the file of where we are parsing for error + // reporting purposes. Then start looking ahead for additional + // quoted strings, and concatenate them until we get a failure + // back from the string parser. + // + Len = wcslen (String) + 1; + ParserSetPosition (SourceFile->FileName, SourceFile->LineNum); + do { + SkipWhiteSpace (SourceFile); + SecondString = GetQuotedString (SourceFile, TRUE); + if (SecondString != NULL) { + Len += wcslen (SecondString); + TempString = (WCHAR *) malloc (Len * sizeof (WCHAR)); + if (TempString == NULL) { + Error (NULL, 0, 0, "application error", "failed to allocate memory"); + return ; + } + + wcscpy (TempString, String); + wcscat (TempString, SecondString); + free (String); + free (SecondString); + String = TempString; + } + } while (SecondString != NULL); + StringDBAddString (Language, NULL, NULL, String, TRUE, 0); + free (String); + } else { + // + // Error was reported at lower level. Error recovery mode. + // + SourceFile->SkipToHash = TRUE; + } + } else { + if (!mGlobals.UnquotedStrings) { + // + // They're using unquoted strings. If the next non-blank character is a double quote, and the + // last non-blank character on the line is a double quote, then more than likely they're using + // quotes, so they need to put the quoted string on the end of the previous line + // + if (ApparentQuotedString (SourceFile)) { + Warning ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + "unexpected quoted string on line", + "specify -uqs option if necessary" + ); + } + } + // + // Found end-of-line (hopefully). Skip over it and start taking in characters + // until we find a control character at the start of a line. + // + Len = 0; + From = SourceFile->FileBufferPtr; + PreviousNewline = FALSE; + while (!EndOfFile (SourceFile)) { + if (SourceFile->FileBufferPtr[0] == UNICODE_LF) { + PreviousNewline = TRUE; + SourceFile->LineNum++; + } else { + Len++; + if (PreviousNewline && (SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter)) { + break; + } + + PreviousNewline = FALSE; + } + + SourceFile->FileBufferPtr++; + } + + if ((Len == 0) && EndOfFile (SourceFile)) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "unexpected end of file", NULL); + SourceFile->SkipToHash = TRUE; + return ; + } + // + // Now allocate a buffer, copy the characters, and add the string. + // + String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR)); + if (String == NULL) { + Error (NULL, 0, 0, "application error", "failed to allocate memory"); + return ; + } + + To = String; + while (From < SourceFile->FileBufferPtr) { + switch (*From) { + case UNICODE_LF: + case 0: + break; + + default: + *To = *From; + To++; + break; + } + + From++; + } + + // + // String[Len] = 0; + // + *To = 0; + StringDBAddString (Language, NULL, NULL, String, TRUE, 0); + } +} + +static +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + switch (SourceFile->FileBufferPtr[0]) { + case UNICODE_NULL: + case UNICODE_CR: + case UNICODE_SPACE: + case UNICODE_TAB: + case UNICODE_LF: + return TRUE; + + default: + return FALSE; + } +} + +static +UINT32 +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + UINT32 Count; + + Count = 0; + while (!EndOfFile (SourceFile)) { + Count++; + switch (*SourceFile->FileBufferPtr) { + case UNICODE_NULL: + case UNICODE_CR: + case UNICODE_SPACE: + case UNICODE_TAB: + SourceFile->FileBufferPtr++; + break; + + case UNICODE_LF: + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + if (mGlobals.Verbose) { + printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr); + } + break; + + default: + return Count - 1; + } + } + // + // Some tokens require trailing whitespace. If we're at the end of the + // file, then we count that as well. + // + if ((Count == 0) && (EndOfFile (SourceFile))) { + Count++; + } + + return Count; +} + +static +UINT32 +wstrcmp ( + WCHAR *Buffer, + WCHAR *Str + ) +{ + UINT32 Len; + + Len = 0; + while (*Str == *Buffer) { + Buffer++; + Str++; + Len++; + } + + if (*Str) { + return 0; + } + + return Len; +} +// +// Given a filename, try to find it along the include paths. +// +static +FILE * +FindFile ( + IN INT8 *FileName, + OUT INT8 *FoundFileName, + IN UINT32 FoundFileNameLen + ) +{ + FILE *Fptr; + TEXT_STRING_LIST *List; + + // + // Traverse the list of paths and try to find the file + // + List = mGlobals.IncludePaths; + while (List != NULL) { + // + // Put the path and filename together + // + if (strlen (List->Str) + strlen (FileName) + 1 > FoundFileNameLen) { + Error (PROGRAM_NAME, 0, 0, NULL, "internal error - cannot concatenate path+filename"); + return NULL; + } + // + // Append the filename to this include path and try to open the file. + // + strcpy (FoundFileName, List->Str); + strcat (FoundFileName, FileName); + if ((Fptr = fopen (FoundFileName, "rb")) != NULL) { + // + // Return the file pointer + // + return Fptr; + } + + List = List->Next; + } + // + // Not found + // + FoundFileName[0] = 0; + return NULL; +} +// +// Process the command-line arguments +// +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ) +{ + TEXT_STRING_LIST *NewList; + // + // Clear our globals + // + memset ((char *) &mGlobals, 0, sizeof (mGlobals)); + strcpy (mGlobals.BaseName, DEFAULT_BASE_NAME); + // + // Skip program name + // + Argc--; + Argv++; + + if (Argc == 0) { + Usage (); + return STATUS_ERROR; + } + + mGlobals.Mode = MODE_UNKNOWN; + // + // Process until no more -args. + // + while ((Argc > 0) && (Argv[0][0] == '-')) { + // + // -parse option + // + if (stricmp (Argv[0], "-parse") == 0) { + if (mGlobals.Mode != MODE_UNKNOWN) { + Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL); + return STATUS_ERROR; + } + + mGlobals.Mode = MODE_PARSE; + // + // -scan option + // + } else if (stricmp (Argv[0], "-scan") == 0) { + if (mGlobals.Mode != MODE_UNKNOWN) { + Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL); + return STATUS_ERROR; + } + + mGlobals.Mode = MODE_SCAN; + // + // -vscan verbose scanning option + // + } else if (stricmp (Argv[0], "-vscan") == 0) { + mGlobals.VerboseScan = TRUE; + // + // -dump option + // + } else if (stricmp (Argv[0], "-dump") == 0) { + if (mGlobals.Mode != MODE_UNKNOWN) { + Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL); + return STATUS_ERROR; + } + + mGlobals.Mode = MODE_DUMP; + } else if (stricmp (Argv[0], "-uqs") == 0) { + mGlobals.UnquotedStrings = TRUE; + // + // -i path add include search path when parsing + // + } else if (stricmp (Argv[0], "-i") == 0) { + // + // check for one more arg + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing include path"); + return STATUS_ERROR; + } + // + // Allocate memory for a new list element, fill it in, and + // add it to our list of include paths. Always make sure it + // has a "\" on the end of it. + // + NewList = malloc (sizeof (TEXT_STRING_LIST)); + if (NewList == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST)); + NewList->Str = malloc (strlen (Argv[1]) + 2); + if (NewList->Str == NULL) { + free (NewList); + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[1]); + if (NewList->Str[strlen (NewList->Str) - 1] != '\\') { + strcat (NewList->Str, "\\"); + } + // + // Add it to our linked list + // + if (mGlobals.IncludePaths == NULL) { + mGlobals.IncludePaths = NewList; + } else { + mGlobals.LastIncludePath->Next = NewList; + } + + mGlobals.LastIncludePath = NewList; + Argc--; + Argv++; + } else if (stricmp (Argv[0], "-if") == 0) { + // + // Indirection file -- check for one more arg + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing indirection file name"); + return STATUS_ERROR; + } + // + // Allocate memory for a new list element, fill it in, and + // add it to our list of include paths. Always make sure it + // has a "\" on the end of it. + // + NewList = malloc (sizeof (TEXT_STRING_LIST)); + if (NewList == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST)); + NewList->Str = malloc (strlen (Argv[1]) + 1); + if (NewList->Str == NULL) { + free (NewList); + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[1]); + // + // Add it to our linked list + // + if (mGlobals.IndirectionFileName == NULL) { + mGlobals.IndirectionFileName = NewList; + } else { + mGlobals.LastIndirectionFileName->Next = NewList; + } + + mGlobals.LastIndirectionFileName = NewList; + Argc--; + Argv++; + } else if (stricmp (Argv[0], "-db") == 0) { + // + // -db option to specify a database file. + // Check for one more arg (the database file name) + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing database file name"); + return STATUS_ERROR; + } + + NewList = malloc (sizeof (TEXT_STRING_LIST)); + if (NewList == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST)); + NewList->Str = malloc (strlen (Argv[1]) + 1); + if (NewList->Str == NULL) { + free (NewList); + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[1]); + // + // Add it to our linked list + // + if (mGlobals.DatabaseFileName == NULL) { + mGlobals.DatabaseFileName = NewList; + } else { + mGlobals.LastDatabaseFileName->Next = NewList; + } + + mGlobals.LastDatabaseFileName = NewList; + Argc--; + Argv++; + } else if (stricmp (Argv[0], "-ou") == 0) { + // + // -ou option to specify an output unicode file to + // which we can dump our database. + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing database dump output file name"); + return STATUS_ERROR; + } + + if (mGlobals.DumpUFileName[0] == 0) { + strcpy (mGlobals.DumpUFileName, Argv[1]); + } else { + Error (PROGRAM_NAME, 0, 0, Argv[1], "-ou option already specified with '%s'", mGlobals.DumpUFileName); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if (stricmp (Argv[0], "-hpk") == 0) { + // + // -hpk option to create an HII export pack of the input database file + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing raw string data dump output file name"); + return STATUS_ERROR; + } + + if (mGlobals.HiiExportPackFileName[0] == 0) { + strcpy (mGlobals.HiiExportPackFileName, Argv[1]); + } else { + Error (PROGRAM_NAME, 0, 0, Argv[1], "-or option already specified with '%s'", mGlobals.HiiExportPackFileName); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if ((stricmp (Argv[0], "-?") == 0) || (stricmp (Argv[0], "-h") == 0)) { + Usage (); + return STATUS_ERROR; + } else if (stricmp (Argv[0], "-v") == 0) { + mGlobals.Verbose = 1; + } else if (stricmp (Argv[0], "-vdbw") == 0) { + mGlobals.VerboseDatabaseWrite = 1; + } else if (stricmp (Argv[0], "-vdbr") == 0) { + mGlobals.VerboseDatabaseRead = 1; + } else if (stricmp (Argv[0], "-newdb") == 0) { + mGlobals.NewDatabase = 1; + } else if (stricmp (Argv[0], "-ignorenotfound") == 0) { + mGlobals.IgnoreNotFound = 1; + } else if (stricmp (Argv[0], "-oc") == 0) { + // + // check for one more arg + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output C filename"); + return STATUS_ERROR; + } + + strcpy (mGlobals.StringCFileName, Argv[1]); + Argc--; + Argv++; + } else if (stricmp (Argv[0], "-bn") == 0) { + // + // check for one more arg + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing base name"); + Usage (); + return STATUS_ERROR; + } + + strcpy (mGlobals.BaseName, Argv[1]); + Argc--; + Argv++; + } else if (stricmp (Argv[0], "-oh") == 0) { + // + // -oh to specify output .h defines file name + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output .h filename"); + return STATUS_ERROR; + } + + strcpy (mGlobals.StringHFileName, Argv[1]); + Argc--; + Argv++; + } else if (stricmp (Argv[0], "-skipext") == 0) { + // + // -skipext to skip scanning of files with certain filename extensions + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing filename extension"); + return STATUS_ERROR; + } + // + // Allocate memory for a new list element, fill it in, and + // add it to our list of excluded extensions. Always make sure it + // has a "." as the first character. + // + NewList = malloc (sizeof (TEXT_STRING_LIST)); + if (NewList == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST)); + NewList->Str = malloc (strlen (Argv[1]) + 2); + if (NewList->Str == NULL) { + free (NewList); + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + if (Argv[1][0] == '.') { + strcpy (NewList->Str, Argv[1]); + } else { + NewList->Str[0] = '.'; + strcpy (NewList->Str + 1, Argv[1]); + } + // + // Add it to our linked list + // + if (mGlobals.SkipExt == NULL) { + mGlobals.SkipExt = NewList; + } else { + mGlobals.LastSkipExt->Next = NewList; + } + + mGlobals.LastSkipExt = NewList; + Argc--; + Argv++; + } else if (stricmp (Argv[0], "-lang") == 0) { + // + // "-lang eng" or "-lang spa+cat" to only output certain languages + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing language name"); + Usage (); + return STATUS_ERROR; + } + + if (AddCommandLineLanguage (Argv[1]) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if (stricmp (Argv[0], "-od") == 0) { + // + // Output database file name -- check for another arg + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output database file name"); + return STATUS_ERROR; + } + + strcpy (mGlobals.OutputDatabaseFileName, Argv[1]); + Argv++; + Argc--; + } else { + // + // Unrecognized arg + // + Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option"); + Usage (); + return STATUS_ERROR; + } + + Argv++; + Argc--; + } + // + // Make sure they specified the mode parse/scan/dump + // + if (mGlobals.Mode == MODE_UNKNOWN) { + Error (NULL, 0, 0, "must specify one of -parse/-scan/-dump", NULL); + return STATUS_ERROR; + } + // + // All modes require a database filename + // + if (mGlobals.DatabaseFileName == 0) { + Error (NULL, 0, 0, "must specify a database filename using -db DbFileName", NULL); + Usage (); + return STATUS_ERROR; + } + // + // If dumping the database file, then return immediately if all + // parameters check out. + // + if (mGlobals.Mode == MODE_DUMP) { + // + // Not much use if they didn't specify -oh or -oc or -ou or -hpk + // + if ((mGlobals.DumpUFileName[0] == 0) && + (mGlobals.StringHFileName[0] == 0) && + (mGlobals.StringCFileName[0] == 0) && + (mGlobals.HiiExportPackFileName[0] == 0) + ) { + Error (NULL, 0, 0, "-dump without -oc/-oh/-ou/-hpk is a NOP", NULL); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; + } + // + // Had to specify source string file and output string defines header filename. + // + if (mGlobals.Mode == MODE_SCAN) { + if (Argc < 1) { + Error (PROGRAM_NAME, 0, 0, NULL, "must specify at least one source file to scan with -scan"); + Usage (); + return STATUS_ERROR; + } + // + // Get the list of filenames + // + while (Argc > 0) { + NewList = malloc (sizeof (TEXT_STRING_LIST)); + if (NewList == NULL) { + Error (PROGRAM_NAME, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset (NewList, 0, sizeof (TEXT_STRING_LIST)); + NewList->Str = (UINT8 *) malloc (strlen (Argv[0]) + 1); + if (NewList->Str == NULL) { + Error (PROGRAM_NAME, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[0]); + if (mGlobals.ScanFileName == NULL) { + mGlobals.ScanFileName = NewList; + } else { + mGlobals.LastScanFileName->Next = NewList; + } + + mGlobals.LastScanFileName = NewList; + Argc--; + Argv++; + } + } else { + // + // Parse mode -- must specify an input unicode file name + // + if (Argc < 1) { + Error (PROGRAM_NAME, 0, 0, NULL, "must specify input unicode string file name with -parse"); + Usage (); + return STATUS_ERROR; + } + + strcpy (mGlobals.SourceFiles.FileName, Argv[0]); + } + + return STATUS_SUCCESS; +} +// +// Found "-lang eng,spa+cat" on the command line. Parse the +// language list and save the setting for later processing. +// +static +STATUS +AddCommandLineLanguage ( + IN INT8 *Language + ) +{ + WCHAR_STRING_LIST *WNewList; + WCHAR *From; + WCHAR *To; + // + // Keep processing the input string until we find the end. + // + while (*Language) { + // + // Allocate memory for a new list element, fill it in, and + // add it to our list. + // + WNewList = MALLOC (sizeof (WCHAR_STRING_LIST)); + if (WNewList == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + memset ((char *) WNewList, 0, sizeof (WCHAR_STRING_LIST)); + WNewList->Str = malloc ((strlen (Language) + 1) * sizeof (WCHAR)); + if (WNewList->Str == NULL) { + free (WNewList); + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + // + // Copy it as unicode to our new structure. Then remove the + // plus signs in it, and verify each language name is 3 characters + // long. If we find a comma, then we're done with this group, so + // break out. + // + swprintf (WNewList->Str, L"%S", Language); + From = To = WNewList->Str; + while (*From) { + if (*From == L',') { + break; + } + + if ((wcslen (From) < LANGUAGE_IDENTIFIER_NAME_LEN) || + ( + (From[LANGUAGE_IDENTIFIER_NAME_LEN] != 0) && + (From[LANGUAGE_IDENTIFIER_NAME_LEN] != UNICODE_PLUS_SIGN) && + (From[LANGUAGE_IDENTIFIER_NAME_LEN] != L',') + ) + ) { + Error (PROGRAM_NAME, 0, 0, Language, "invalid format for language name on command line"); + FREE (WNewList->Str); + FREE (WNewList); + return STATUS_ERROR; + } + + wcsncpy (To, From, LANGUAGE_IDENTIFIER_NAME_LEN); + To += LANGUAGE_IDENTIFIER_NAME_LEN; + From += LANGUAGE_IDENTIFIER_NAME_LEN; + if (*From == L'+') { + From++; + } + } + + *To = 0; + // + // Add it to our linked list + // + if (mGlobals.Language == NULL) { + mGlobals.Language = WNewList; + } else { + mGlobals.LastLanguage->Next = WNewList; + } + + mGlobals.LastLanguage = WNewList; + // + // Skip to next entry (comma-separated list) + // + while (*Language) { + if (*Language == L',') { + Language++; + break; + } + + Language++; + } + } + + return STATUS_SUCCESS; +} +// +// The contents of the text file are expected to be (one per line) +// STRING_IDENTIFIER_NAME ScopeName +// For example: +// STR_ID_MY_FAVORITE_STRING IBM +// +static +STATUS +ParseIndirectionFiles ( + TEXT_STRING_LIST *Files + ) +{ + FILE *Fptr; + INT8 Line[200]; + INT8 *StringName; + INT8 *ScopeName; + INT8 *End; + UINT32 LineCount; + WCHAR_MATCHING_STRING_LIST *NewList; + + Line[sizeof (Line) - 1] = 0; + Fptr = NULL; + while (Files != NULL) { + Fptr = fopen (Files->Str, "r"); + LineCount = 0; + if (Fptr == NULL) { + Error (NULL, 0, 0, Files->Str, "failed to open input indirection file for reading"); + return STATUS_ERROR; + } + + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + // + // remove terminating newline for error printing purposes. + // + if (Line[strlen (Line) - 1] == '\n') { + Line[strlen (Line) - 1] = 0; + } + + LineCount++; + if (Line[sizeof (Line) - 1] != 0) { + Error (Files->Str, LineCount, 0, "line length exceeds maximum supported", NULL); + goto Done; + } + + StringName = Line; + while (*StringName && (isspace (*StringName))) { + StringName++; + } + + if (*StringName) { + if ((*StringName == '_') || isalpha (*StringName)) { + End = StringName; + while ((*End) && (*End == '_') || (isalnum (*End))) { + End++; + } + + if (isspace (*End)) { + *End = 0; + End++; + while (isspace (*End)) { + End++; + } + + if (*End) { + ScopeName = End; + while (*End && !isspace (*End)) { + End++; + } + + *End = 0; + // + // Add the string name/scope pair + // + NewList = malloc (sizeof (WCHAR_MATCHING_STRING_LIST)); + if (NewList == NULL) { + Error (NULL, 0, 0, "memory allocation error", NULL); + goto Done; + } + + memset (NewList, 0, sizeof (WCHAR_MATCHING_STRING_LIST)); + NewList->Str1 = (WCHAR *) malloc ((strlen (StringName) + 1) * sizeof (WCHAR)); + NewList->Str2 = (WCHAR *) malloc ((strlen (ScopeName) + 1) * sizeof (WCHAR)); + if ((NewList->Str1 == NULL) || (NewList->Str2 == NULL)) { + Error (NULL, 0, 0, "memory allocation error", NULL); + goto Done; + } + + swprintf (NewList->Str1, L"%S", StringName); + swprintf (NewList->Str2, L"%S", ScopeName); + if (mGlobals.IndirectionList == NULL) { + mGlobals.IndirectionList = NewList; + } else { + mGlobals.LastIndirectionList->Next = NewList; + } + + mGlobals.LastIndirectionList = NewList; + } else { + Error (Files->Str, LineCount, 0, StringName, "invalid line : expected 'StringIdentifier Scope'"); + goto Done; + } + } else { + Error (Files->Str, LineCount, 0, StringName, "invalid line : expected 'StringIdentifier Scope'"); + goto Done; + } + } else { + Error (Files->Str, LineCount, 0, StringName, "invalid string identifier"); + goto Done; + } + } + } + + fclose (Fptr); + Fptr = NULL; + Files = Files->Next; + } + +Done: + if (Fptr != NULL) { + fclose (Fptr); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +STATUS +ScanFiles ( + TEXT_STRING_LIST *ScanFiles + ) +{ + char Line[MAX_LINE_LEN]; + FILE *Fptr; + UINT32 LineNum; + char *Cptr; + char *SavePtr; + char *TermPtr; + char *StringTokenPos; + TEXT_STRING_LIST *SList; + BOOLEAN SkipIt; + + // + // Put a null-terminator at the end of the line. If we read in + // a line longer than we support, then we can catch it. + // + Line[MAX_LINE_LEN - 1] = 0; + // + // Process each file. If they gave us a skip extension list, then + // skip it if the extension matches. + // + while (ScanFiles != NULL) { + SkipIt = FALSE; + for (SList = mGlobals.SkipExt; SList != NULL; SList = SList->Next) { + if ((strlen (ScanFiles->Str) > strlen (SList->Str)) && + (strcmp (ScanFiles->Str + strlen (ScanFiles->Str) - strlen (SList->Str), SList->Str) == 0) + ) { + SkipIt = TRUE; + // + // printf ("Match: %s : %s\n", ScanFiles->Str, SList->Str); + // + break; + } + } + + if (!SkipIt) { + if (mGlobals.VerboseScan) { + printf ("Scanning %s\n", ScanFiles->Str); + } + + Fptr = fopen (ScanFiles->Str, "r"); + if (Fptr == NULL) { + Error (NULL, 0, 0, ScanFiles->Str, "failed to open input file for scanning"); + return STATUS_ERROR; + } + + LineNum = 0; + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + LineNum++; + if (Line[MAX_LINE_LEN - 1] != 0) { + Error (ScanFiles->Str, LineNum, 0, "line length exceeds maximum supported by tool", NULL); + fclose (Fptr); + return STATUS_ERROR; + } + // + // Remove the newline from the input line so we can print a warning message + // + if (Line[strlen (Line) - 1] == '\n') { + Line[strlen (Line) - 1] = 0; + } + // + // Terminate the line at // comments + // + Cptr = strstr (Line, "//"); + if (Cptr != NULL) { + *Cptr = 0; + } + + Cptr = Line; + while ((Cptr = strstr (Cptr, STRING_TOKEN)) != NULL) { + // + // Found "STRING_TOKEN". Make sure we don't have NUM_STRING_TOKENS or + // something like that. Then make sure it's followed by + // an open parenthesis, a string identifier, and then a closing + // parenthesis. + // + if (mGlobals.VerboseScan) { + printf (" %d: %s", LineNum, Cptr); + } + + if (((Cptr == Line) || (!IsValidIdentifierChar (*(Cptr - 1), FALSE))) && + (!IsValidIdentifierChar (*(Cptr + sizeof (STRING_TOKEN) - 1), FALSE)) + ) { + StringTokenPos = Cptr; + SavePtr = Cptr; + Cptr += strlen (STRING_TOKEN); + while (*Cptr && isspace (*Cptr) && (*Cptr != '(')) { + Cptr++; + } + + if (*Cptr != '(') { + Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected "STRING_TOKEN "(identifier)"); + } else { + // + // Skip over the open-parenthesis and find the next non-blank character + // + Cptr++; + while (isspace (*Cptr)) { + Cptr++; + } + + SavePtr = Cptr; + if ((*Cptr == '_') || isalpha (*Cptr)) { + while ((*Cptr == '_') || (isalnum (*Cptr))) { + Cptr++; + } + + TermPtr = Cptr; + while (*Cptr && isspace (*Cptr)) { + Cptr++; + } + + if (*Cptr != ')') { + Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected "STRING_TOKEN "(identifier)"); + } + + if (*TermPtr) { + *TermPtr = 0; + Cptr = TermPtr + 1; + } else { + Cptr = TermPtr; + } + // + // Add the string identifier to the list of used strings + // + ParserSetPosition (ScanFiles->Str, LineNum); + StringDBSetStringReferenced (SavePtr, mGlobals.IgnoreNotFound); + if (mGlobals.VerboseScan) { + printf ("...referenced %s", SavePtr); + } + } else { + Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected valid string identifier name"); + } + } + } else { + // + // Found it, but it's a substring of something else. Advance our pointer. + // + Cptr++; + } + + if (mGlobals.VerboseScan) { + printf ("\n"); + } + } + } + + fclose (Fptr); + } else { + // + // Skipping this file type + // + if (mGlobals.VerboseScan) { + printf ("Skip scanning of %s\n", ScanFiles->Str); + } + } + + ScanFiles = ScanFiles->Next; + } + + return STATUS_SUCCESS; +} +// +// Free the global string lists we allocated memory for +// +static +void +FreeLists ( + VOID + ) +{ + TEXT_STRING_LIST *Temp; + WCHAR_STRING_LIST *WTemp; + + // + // Traverse the include paths, freeing each + // + while (mGlobals.IncludePaths != NULL) { + Temp = mGlobals.IncludePaths->Next; + free (mGlobals.IncludePaths->Str); + free (mGlobals.IncludePaths); + mGlobals.IncludePaths = Temp; + } + // + // If we did a scan, then free up our + // list of files to scan. + // + while (mGlobals.ScanFileName != NULL) { + Temp = mGlobals.ScanFileName->Next; + free (mGlobals.ScanFileName->Str); + free (mGlobals.ScanFileName); + mGlobals.ScanFileName = Temp; + } + // + // If they gave us a list of filename extensions to + // skip on scan, then free them up. + // + while (mGlobals.SkipExt != NULL) { + Temp = mGlobals.SkipExt->Next; + free (mGlobals.SkipExt->Str); + free (mGlobals.SkipExt); + mGlobals.SkipExt = Temp; + } + // + // Free up any languages specified + // + while (mGlobals.Language != NULL) { + WTemp = mGlobals.Language->Next; + free (mGlobals.Language->Str); + free (mGlobals.Language); + mGlobals.Language = WTemp; + } + // + // Free up our indirection list + // + while (mGlobals.IndirectionList != NULL) { + mGlobals.LastIndirectionList = mGlobals.IndirectionList->Next; + free (mGlobals.IndirectionList->Str1); + free (mGlobals.IndirectionList->Str2); + free (mGlobals.IndirectionList); + mGlobals.IndirectionList = mGlobals.LastIndirectionList; + } + + while (mGlobals.IndirectionFileName != NULL) { + mGlobals.LastIndirectionFileName = mGlobals.IndirectionFileName->Next; + free (mGlobals.IndirectionFileName->Str); + free (mGlobals.IndirectionFileName); + mGlobals.IndirectionFileName = mGlobals.LastIndirectionFileName; + } +} + +static +BOOLEAN +IsValidIdentifierChar ( + INT8 Char, + BOOLEAN FirstChar + ) +{ + // + // If it's the first character of an identifier, then + // it must be one of [A-Za-z_]. + // + if (FirstChar) { + if (isalpha (Char) || (Char == '_')) { + return TRUE; + } + } else { + // + // If it's not the first character, then it can + // be one of [A-Za-z_0-9] + // + if (isalnum (Char) || (Char == '_')) { + return TRUE; + } + } + + return FALSE; +} + +static +void +RewindFile ( + SOURCE_FILE *SourceFile + ) +{ + SourceFile->LineNum = 1; + SourceFile->FileBufferPtr = SourceFile->FileBuffer; + SourceFile->EndOfFile = 0; +} + +static +BOOLEAN +SkipTo ( + SOURCE_FILE *SourceFile, + WCHAR WChar, + BOOLEAN StopAfterNewline + ) +{ + while (!EndOfFile (SourceFile)) { + // + // Check for the character of interest + // + if (SourceFile->FileBufferPtr[0] == WChar) { + return TRUE; + } else { + if (SourceFile->FileBufferPtr[0] == UNICODE_LF) { + SourceFile->LineNum++; + if (StopAfterNewline) { + SourceFile->FileBufferPtr++; + if (SourceFile->FileBufferPtr[0] == 0) { + SourceFile->FileBufferPtr++; + } + + return FALSE; + } + } + + SourceFile->FileBufferPtr++; + } + } + + return FALSE; +} + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print usage information for this utility. + +Arguments: + + None. + +Returns: + + Nothing. + +--*/ +{ + int Index; + static const char *Str[] = { + "", + PROGRAM_NAME " version "TOOL_VERSION " -- process unicode strings file", + " Usage: "PROGRAM_NAME " -parse {parse options} [FileNames]", + " "PROGRAM_NAME " -scan {scan options} [FileName]", + " "PROGRAM_NAME " -dump {dump options}", + " Common options include:", + " -h or -? for this help information", + " -db Database required name of output/input database file", + " -bn BaseName for use in the .h and .c output files", + " Default = "DEFAULT_BASE_NAME, + " -v for verbose output", + " -vdbw for verbose output when writing database", + " -vdbr for verbose output when reading database", + " -od FileName to specify an output database file name", + " Parse options include:", + " -i IncludePath add IncludePath to list of search paths", + " -newdb to not read in existing database file", + " -uqs to indicate that unquoted strings are used", + " FileNames name of one or more unicode files to parse", + " Scan options include:", + " -scan scan text file(s) for STRING_TOKEN() usage", + " -skipext .ext to skip scan of files with .ext filename extension", + " -ignorenotfound ignore if a given STRING_TOKEN(STR) is not ", + " found in the database", + " FileNames one or more files to scan", + " Dump options include:", + " -oc FileName write string data to FileName", + " -oh FileName write string defines to FileName", + " -ou FileName dump database to unicode file FileName", + " -lang Lang only dump for the language 'Lang'", + " -if FileName to specify an indirection file", + " -hpk FileName to create an HII export pack of the strings", + "", + " The expected process is to parse a unicode string file to create an initial", + " database of string identifier names and string definitions. Then text files", + " should be scanned for STRING_TOKEN() usages, and the referenced", + " strings will be tagged as used in the database. After all files have been", + " scanned, then the database should be dumped to create the necessary output", + " files.", + "", + NULL + }; + for (Index = 0; Str[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Str[Index]); + } +} diff --git a/Tools/Source/TianoTools/StrGather/StrGather.h b/Tools/Source/TianoTools/StrGather/StrGather.h new file mode 100644 index 0000000000..df175c2db6 --- /dev/null +++ b/Tools/Source/TianoTools/StrGather/StrGather.h @@ -0,0 +1,84 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + StrGather.h + +Abstract: + + Common defines and prototypes for StrGather. + +--*/ + +#ifndef _STR_GATHER_H_ +#define _STR_GATHER_H_ + +#define MALLOC(size) malloc (size) +#define FREE(ptr) free (ptr) + +#define PROGRAM_NAME "StrGather" + +typedef CHAR16 WCHAR; + +#define UNICODE_TO_ASCII(w) (INT8) ((w) & 0xFF) +#define ASCII_TO_UNICODE(a) (WCHAR) ((UINT8) (a)) + +#define UNICODE_HASH L'#' +#define UNICODE_BACKSLASH L'\\' +#define UNICODE_SLASH L'/' +#define UNICODE_EQUAL_SIGN L'=' +#define UNICODE_PLUS_SIGN L'+' + +#define UNICODE_FILE_START 0xFEFF +#define UNICODE_CR 0x000D +#define UNICODE_LF 0x000A +#define UNICODE_NULL 0x0000 +#define UNICODE_SPACE L' ' +#define UNICODE_SLASH L'/' +#define UNICODE_DOUBLE_QUOTE L'"' +#define UNICODE_Z L'Z' +#define UNICODE_z L'z' +#define UNICODE_A L'A' +#define UNICODE_a L'a' +#define UNICODE_F L'F' +#define UNICODE_f L'f' +#define UNICODE_UNDERSCORE L'_' +#define UNICODE_0 L'0' +#define UNICODE_9 L'9' +#define UNICODE_TAB L'\t' +#define UNICODE_NBR_STRING L"\\nbr" +#define UNICODE_BR_STRING L"\\br" +#define UNICODE_WIDE_STRING L"\\wide" +#define UNICODE_NARROW_STRING L"\\narrow" + +// +// This is the length of a valid string identifier +// +#define LANGUAGE_IDENTIFIER_NAME_LEN 3 + +typedef struct _TEXT_STRING_LIST { + struct _TEXT_STRING_LIST *Next; + UINT8 *Str; +} TEXT_STRING_LIST; + +typedef struct _WCHAR_STRING_LIST { + struct _WCHAR_STRING_LIST *Next; + WCHAR *Str; +} WCHAR_STRING_LIST; + +typedef struct _WCHAR_MATCHING_STRING_LIST { + struct _WCHAR_MATCHING_STRING_LIST *Next; + WCHAR *Str1; + WCHAR *Str2; +} WCHAR_MATCHING_STRING_LIST; + +#endif // #ifndef _STR_GATHER_H_ diff --git a/Tools/Source/TianoTools/StrGather/StringDB.c b/Tools/Source/TianoTools/StrGather/StringDB.c new file mode 100644 index 0000000000..f452bbc86b --- /dev/null +++ b/Tools/Source/TianoTools/StrGather/StringDB.c @@ -0,0 +1,2751 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + StringDB.c + +Abstract: + + String database implementation + +--*/ + +#include +#include +#include +#include // for tolower() +#include +#include +#include +#include "EfiUtilityMsgs.h" +#include "StrGather.h" +#include "StringDB.h" +#include "InternalFormRepresentation.h" + +// #include EFI_PROTOCOL_DEFINITION (Hii) +#include +#include + +#define STRING_OFFSET RELOFST + +#define STRING_DB_KEY (('S' << 24) | ('D' << 16) | ('B' << 8) | 'K') +// +// Version supported by this tool +// +#define STRING_DB_VERSION 0x00010000 + +#define STRING_DB_MAJOR_VERSION_MASK 0xFFFF0000 +#define STRING_DB_MINOR_VERSION_MASK 0x0000FFFF + +#define DEFINE_STR L"// #define" + +#define LANGUAGE_CODE_WIDTH 4 +// +// This is the header that gets written to the top of the +// output binary database file. +// +typedef struct { + UINT32 Key; + UINT32 HeaderSize; + UINT32 Version; + UINT32 NumStringIdenfiers; + UINT32 StringIdentifiersSize; + UINT32 NumLanguages; +} STRING_DB_HEADER; + +// +// When we write out data to the database, we have a UINT16 identifier, which +// indicates what follows, followed by the data. Here's the structure. +// +typedef struct { + UINT16 DataType; + UINT16 Reserved; +} DB_DATA_ITEM_HEADER; + +#define DB_DATA_TYPE_INVALID 0x0000 +#define DB_DATA_TYPE_STRING_IDENTIFIER 0x0001 +#define DB_DATA_TYPE_LANGUAGE_DEFINITION 0x0002 +#define DB_DATA_TYPE_STRING_DEFINITION 0x0003 +#define DB_DATA_TYPE_LAST DB_DATA_TYPE_STRING_DEFINITION + +// +// We have to keep track of a list of languages, each of which has its own +// list of strings. Define a structure to keep track of all languages and +// their list of strings. +// +typedef struct _STRING_LIST { + struct _STRING_LIST *Next; + UINT32 Size; // number of bytes in string, including null terminator + WCHAR *LanguageName; + WCHAR *StringName; // for example STR_ID_TEXT1 + WCHAR *Scope; // + WCHAR *Str; // the actual string + UINT16 Flags; // properties of this string (used, undefined) +} STRING_LIST; + +typedef struct _LANGUAGE_LIST { + struct _LANGUAGE_LIST *Next; + WCHAR LanguageName[4]; + WCHAR *PrintableLanguageName; + STRING_LIST *String; + STRING_LIST *LastString; +} LANGUAGE_LIST; + +// +// We also keep track of all the string identifier names, which we assign unique +// values to. Create a structure to keep track of them all. +// +typedef struct _STRING_IDENTIFIER { + struct _STRING_IDENTIFIER *Next; + UINT32 Index; // only need 16 bits, but makes it easier with UINT32 + WCHAR *StringName; + UINT16 Flags; // if someone referenced it via STRING_TOKEN() +} STRING_IDENTIFIER; +// +// Keep our globals in this structure to be as modular as possible. +// +typedef struct { + FILE *StringDBFptr; + LANGUAGE_LIST *LanguageList; + LANGUAGE_LIST *LastLanguageList; + LANGUAGE_LIST *CurrentLanguage; // keep track of the last language they used + STRING_IDENTIFIER *StringIdentifier; + STRING_IDENTIFIER *LastStringIdentifier; + UINT8 *StringDBFileName; + UINT32 NumStringIdentifiers; + UINT32 NumStringIdentifiersReferenced; + STRING_IDENTIFIER *CurrentStringIdentifier; // keep track of the last string identifier they added + WCHAR *CurrentScope; +} STRING_DB_DATA; + +static STRING_DB_DATA mDBData; + +static const char *mSourceFileHeader[] = { + "//", + "// DO NOT EDIT -- auto-generated file", + "//", + "// This file is generated by the string gather utility", + "//", + NULL +}; + +static +STRING_LIST * +StringDBFindString ( + WCHAR *LanguageName, + WCHAR *StringName, + WCHAR *Scope, + WCHAR_STRING_LIST *LanguagesOfInterest, + WCHAR_MATCHING_STRING_LIST *IndirectionList + ); + +static +STRING_IDENTIFIER * +StringDBFindStringIdentifierByName ( + WCHAR *Name + ); + +static +STRING_IDENTIFIER * +StringDBFindStringIdentifierByIndex ( + UINT32 Index + ); + +static +LANGUAGE_LIST * +StringDBFindLanguageList ( + WCHAR *LanguageName + ); + +static +void +StringDBWriteStandardFileHeader ( + FILE *OutFptr + ); + +static +WCHAR * +AsciiToWchar ( + INT8 *Str + ); + +static +WCHAR * +DuplicateString ( + WCHAR *Str + ); + +static +STATUS +StringDBWriteStringIdentifier ( + FILE *DBFptr, + UINT16 StringId, + UINT16 Flags, + WCHAR *IdentifierName + ); + +static +STATUS +StringDBReadStringIdentifier ( + FILE *DBFptr + ); + +static +STATUS +StringDBWriteLanguageDefinition ( + FILE *DBFptr, + WCHAR *LanguageName, + WCHAR *PrintableLanguageName + ); + +static +STATUS +StringDBReadLanguageDefinition ( + FILE *DBFptr + ); + +static +STATUS +StringDBWriteString ( + FILE *DBFptr, + UINT16 Flags, + WCHAR *Language, + WCHAR *StringName, + WCHAR *Scope, + WCHAR *Str + ); + +static +STATUS +StringDBReadString ( + FILE *DBFptr + ); + +static +STATUS +StringDBReadGenericString ( + FILE *DBFptr, + UINT16 *Size, + WCHAR **Str + ); + +static +STATUS +StringDBWriteGenericString ( + FILE *DBFptr, + WCHAR *Str + ); + +static +void +StringDBAssignStringIndexes ( + VOID + ); + +/*****************************************************************************/ + +/*++ + +Routine Description: + Constructor function for the string database handler. + +Arguments: + None. + +Returns: + None. + +--*/ +void +StringDBConstructor ( + VOID + ) +{ + memset ((char *) &mDBData, 0, sizeof (STRING_DB_DATA)); + mDBData.CurrentScope = DuplicateString (L"NULL"); +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + Destructor function for the string database handler. + +Arguments: + None. + +Returns: + None. + +--*/ +void +StringDBDestructor ( + VOID + ) +{ + LANGUAGE_LIST *NextLang; + STRING_LIST *NextStr; + STRING_IDENTIFIER *NextIdentifier; + // + // Close the database file if it's open + // + if (mDBData.StringDBFptr != NULL) { + fclose (mDBData.StringDBFptr); + mDBData.StringDBFptr = NULL; + } + // + // If we've allocated any strings/languages, free them up + // + while (mDBData.LanguageList != NULL) { + NextLang = mDBData.LanguageList->Next; + // + // Free up all strings for this language + // + while (mDBData.LanguageList->String != NULL) { + NextStr = mDBData.LanguageList->String->Next; + FREE (mDBData.LanguageList->String->Str); + FREE (mDBData.LanguageList->String); + mDBData.LanguageList->String = NextStr; + } + + FREE (mDBData.LanguageList->PrintableLanguageName); + FREE (mDBData.LanguageList); + mDBData.LanguageList = NextLang; + } + // + // Free up string identifiers + // + while (mDBData.StringIdentifier != NULL) { + NextIdentifier = mDBData.StringIdentifier->Next; + FREE (mDBData.StringIdentifier->StringName); + FREE (mDBData.StringIdentifier); + mDBData.StringIdentifier = NextIdentifier; + } + // + // Free the filename + // + if (mDBData.StringDBFileName != NULL) { + FREE (mDBData.StringDBFileName); + mDBData.StringDBFileName = NULL; + } + // + // We save a copy of the scope, so free it up if we + // have one. + // + if (mDBData.CurrentScope != NULL) { + FREE (mDBData.CurrentScope); + mDBData.CurrentScope = NULL; + } +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Dump the contents of a database to an output C file. + +Arguments: + + FileName - name of the output file to write + BaseName - used for the name of the C array defined + Languages - list of languages of interest + +Returns: + + STATUS + +Notes: + + Languages is a pointer to a linked list of languages specified on + the command line. Format is "eng" and "spa+cat". For this, print + the strings for eng. Print the strings for spa too, but if one is + missing look for a cat string and print if it it exists. + +--*/ +STATUS +StringDBDumpCStrings ( + INT8 *FileName, + INT8 *BaseName, + WCHAR_STRING_LIST *LanguagesOfInterest, + WCHAR_MATCHING_STRING_LIST *IndirectionList + ) +{ + FILE *Fptr; + LANGUAGE_LIST *Lang; + STRING_LIST *CurrString; + STRING_LIST EmptyString; + UINT32 Offset; + UINT32 StringIndex; + UINT32 TempIndex; + UINT32 BytesThisLine; + EFI_HII_STRING_PACK StringPack; + UINT8 *Ptr; + UINT32 Len; + WCHAR ZeroString[1]; + WCHAR_STRING_LIST *LOIPtr; + BOOLEAN LanguageOk; + WCHAR *TempStringPtr; + WCHAR *LangName; + STRING_IDENTIFIER *StringIdentifier; + + if ((Fptr = fopen (FileName, "w")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open output C string file"); + return STATUS_ERROR; + } + // + // Assign index values to the string identifiers + // + StringDBAssignStringIndexes (); + // + // Write the standard header to the output file, then the structure + // definition header. + // + StringDBWriteStandardFileHeader (Fptr); + fprintf (Fptr, "\nunsigned char %s[] = {\n", BaseName); + // + // If a given string is not defined, then we'll use this one. + // + memset (&EmptyString, 0, sizeof (EmptyString)); + EmptyString.Size = sizeof (ZeroString); + EmptyString.Str = ZeroString; + // + // Process each language, then each string for each langage + // + ZeroString[0] = 0; + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + // + // If we have a language list, then make sure this language is in that + // list. + // + LanguageOk = TRUE; + LangName = Lang->LanguageName; + if (LanguagesOfInterest != NULL) { + LanguageOk = FALSE; + for (LOIPtr = LanguagesOfInterest; LOIPtr != NULL; LOIPtr = LOIPtr->Next) { + if (wcsncmp (LOIPtr->Str, Lang->LanguageName, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) { + LangName = LOIPtr->Str; + LanguageOk = TRUE; + break; + } + } + } + + if (!LanguageOk) { + continue; + } + // + // Process each string for this language. We have to make 3 passes on the strings: + // Pass1: computes sizes and fill in the string pack header + // Pass2: write the array of offsets + // Pass3: write the strings + // + // + // PASS 1: Fill in and print the HII string pack header + // + // Compute the size for this language package and write + // the header out. Each string package contains: + // Header + // Offset[] -- an array of offsets to strings, of type RELOFST each + // String[] -- the actual strings themselves + // + fprintf ( + Fptr, + "\n//******************************************************************************" + "\n// Start of string definitions for %S/%S", + Lang->LanguageName, + Lang->PrintableLanguageName + ); + memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK)); + StringPack.Header.Type = EFI_HII_STRING; + StringPack.NumStringPointers = (UINT16) mDBData.NumStringIdentifiersReferenced; + // + // First string is the language name. If we're printing all languages, then + // it's just the "spa". If we were given a list of languages to print, then it's + // the "spacat" string. Compute its offset and fill in + // the info in the header. Since we know the language name string's length, + // and the printable language name follows it, use that info to fill in the + // entry for the printable language name as well. + // + StringPack.LanguageNameString = (STRING_OFFSET) (sizeof (EFI_HII_STRING_PACK) + (mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET))); + StringPack.PrintableLanguageName = (STRING_OFFSET) (StringPack.LanguageNameString + (wcslen (LangName) + 1) * sizeof (WCHAR)); + // + // Add up the size of all strings so we can fill in our header. + // + Len = 0; + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + Len += (wcslen (LangName) + 1) * sizeof (WCHAR); + } else { + // + // Find a string with this language.stringname + // + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + // + // Find a matching string if this string identifier was referenced + // + EmptyString.Flags = STRING_FLAGS_UNDEFINED; + CurrString = NULL; + if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, + LanguagesOfInterest, + IndirectionList + ); + if (NULL == CurrString) { + // + // If string for Lang->LanguageName is not found, try to get an English version + // + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, + LanguagesOfInterest, + IndirectionList + ); + } + } + + if (CurrString == NULL) { + CurrString = &EmptyString; + EmptyString.Flags |= StringIdentifier->Flags; + } + + Len += CurrString->Size; + } + } + StringPack.Header.Length = sizeof (EFI_HII_STRING_PACK) + + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET) + + Len; + // + // Write out the header one byte at a time + // + Ptr = (UINT8 *) &StringPack; + for (TempIndex = 0; TempIndex < sizeof (EFI_HII_STRING_PACK); TempIndex++, Ptr++) { + if ((TempIndex & 0x07) == 0) { + fprintf (Fptr, "\n "); + } + + fprintf (Fptr, "0x%02X, ", (UINT32) *Ptr); + } + + fprintf (Fptr, "\n // offset 0x%X\n", sizeof (StringPack)); + // + // PASS2 : write the offsets + // + // Traverse the list of strings again and write the array of offsets. The + // offset to the first string is the size of the string pack header + // plus the size of the offsets array. The other strings follow it. + // + StringIndex = 0; + Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + // + // Write the offset, followed by a useful comment + // + fprintf (Fptr, " "); + Ptr = (UINT8 *) &Offset; + for (TempIndex = 0; TempIndex < sizeof (STRING_OFFSET); TempIndex++) { + fprintf (Fptr, "0x%02X, ", (UINT32) Ptr[TempIndex]); + } + // + // Find the string name + // + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + + fprintf (Fptr, " // offset to string %S (0x%04X)", StringIdentifier->StringName, StringIndex); + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + Offset += (wcslen (LangName) + 1) * sizeof (WCHAR); + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + NULL, + NULL + ); + } else { + // + // Find a matching string + // + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + LanguagesOfInterest, + IndirectionList + ); + + if (NULL == CurrString) { + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, // scope + LanguagesOfInterest, + IndirectionList + ); + } + + EmptyString.LanguageName = Lang->LanguageName; + if (CurrString == NULL) { + CurrString = &EmptyString; + EmptyString.Flags = STRING_FLAGS_UNDEFINED; + } else if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) { + CurrString = &EmptyString; + EmptyString.Flags = 0; + } + + Offset += CurrString->Size; + } + // + // Print useful info about this string + // + if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) { + fprintf (Fptr, " - not referenced"); + } + + if (CurrString->Flags & STRING_FLAGS_UNDEFINED) { + fprintf (Fptr, " - not defined for this language"); + } else if (wcscmp (CurrString->LanguageName, Lang->LanguageName) != 0) { + fprintf ( + Fptr, + " - not defined for this language -- using secondary language %S definition", + CurrString->LanguageName + ); + } + + fprintf (Fptr, "\n"); + } + // + // For unreferenced string identifiers, print a message that they are not referenced anywhere + // + while (StringIndex < mDBData.NumStringIdentifiers) { + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier != NULL) { + fprintf (Fptr, " // %S not referenced\n", StringIdentifier->StringName); + } + + StringIndex++; + } + + // + // PASS 3: write the strings themselves. + // Keep track of how many bytes we write per line because some editors + // (Visual Studio for instance) can't handle too long of lines. + // + Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + + fprintf (Fptr, " // string %S offset 0x%08X\n ", StringIdentifier->StringName, Offset); + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + TempStringPtr = LangName; + } else { + // + // Find a matching string if this string identifier was referenced + // + CurrString = NULL; + if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + LanguagesOfInterest, + IndirectionList + ); + if (NULL == CurrString) { + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, // scope + LanguagesOfInterest, + IndirectionList + ); + } + } + + if (CurrString == NULL) { + CurrString = &EmptyString; + } + + TempStringPtr = CurrString->Str; + } + + BytesThisLine = 0; + for (TempIndex = 0; TempStringPtr[TempIndex] != 0; TempIndex++) { + fprintf ( + Fptr, + "0x%02X, 0x%02X, ", + (UINT32) TempStringPtr[TempIndex] & 0xFF, + (UINT32) ((TempStringPtr[TempIndex] >> 8) & 0xFF) + ); + BytesThisLine += 2; + Offset += 2; + // + // Let's say we only allow 14 per line + // + if (BytesThisLine > 14) { + fprintf (Fptr, "\n "); + BytesThisLine = 0; + } + } + // + // Print NULL WCHAR at the end of this string. + // + fprintf (Fptr, "0x00, 0x00,\n"); + Offset += 2; + } + // + // Sanity check the offset. Make sure our running offset is what we put in the + // string pack header. + // + if (StringPack.Header.Length != Offset) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "stringpack size 0x%X does not match final size 0x%X", + StringPack.Header.Length, + Offset + ); + } + } + // + // Print terminator string pack, closing brace and close the file. + // The size of 0 triggers to the consumer that this is the end. + // + memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK)); + StringPack.Header.Type = EFI_HII_STRING; + Ptr = (UINT8 *) &StringPack; + fprintf (Fptr, "\n // strings terminator pack"); + for (TempIndex = 0; TempIndex < sizeof (StringPack); TempIndex++, Ptr++) { + if ((TempIndex & 0x0F) == 0) { + fprintf (Fptr, "\n "); + } + + fprintf (Fptr, "0x%02X, ", (UINT32) *Ptr); + } + + fprintf (Fptr, "\n};\n"); + fclose (Fptr); + return STATUS_SUCCESS; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Dump the #define string names + +Arguments: + + FileName - name of the output file to write + BaseName - used for the protection #ifndef/#endif + +Returns: + + STATUS + +--*/ +STATUS +StringDBDumpStringDefines ( + INT8 *FileName, + INT8 *BaseName + ) +{ + FILE *Fptr; + STRING_IDENTIFIER *Identifier; + INT8 CopyBaseName[100]; + UINT32 Index; + const INT8 *StrDefHeader[] = { + "#ifndef _%s_STRINGS_DEFINE_H_\n", + "#define _%s_STRINGS_DEFINE_H_\n\n", + NULL + }; + + if ((Fptr = fopen (FileName, "w")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open output string defines file"); + return STATUS_ERROR; + } + // + // Get the base source filename and convert to uppercase. + // + if (sizeof (CopyBaseName) <= strlen (BaseName) + 1) { + Error (NULL, 0, 0, "application error", "StringDBDumpStringDefines() string length insufficient"); + return STATUS_ERROR; + } + + strcpy (CopyBaseName, BaseName); + for (Index = 0; CopyBaseName[Index] != 0; Index++) { + if (islower (CopyBaseName[Index])) { + CopyBaseName[Index] = (INT8) toupper (CopyBaseName[Index]); + } + } + // + // Assign index values to the string identifiers + // + StringDBAssignStringIndexes (); + // + // Write the standard header to the output file, and then the + // protective #ifndef. + // + StringDBWriteStandardFileHeader (Fptr); + for (Index = 0; StrDefHeader[Index] != NULL; Index++) { + fprintf (Fptr, StrDefHeader[Index], CopyBaseName); + } + // + // Print all the #defines for the string identifiers. Print identifiers + // whose names start with '$' as comments. Add comments for string + // identifiers not used as well. + // + Identifier = mDBData.StringIdentifier; + while (Identifier != NULL) { + if (Identifier->StringName[0] == L'$') { + fprintf (Fptr, "// "); + } + + if (Identifier->Flags & STRING_FLAGS_REFERENCED) { + fprintf (Fptr, "#define %-40S 0x%04X\n", Identifier->StringName, Identifier->Index); + } else { + fprintf (Fptr, "//#define %-40S 0x%04X // not referenced\n", Identifier->StringName, Identifier->Index); + } + + Identifier = Identifier->Next; + } + + fprintf (Fptr, "\n#endif\n"); + fclose (Fptr); + return STATUS_SUCCESS; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Add a string identifier to the database. + +Arguments: + + StringName - name of the string identifier. For example "STR_MY_STRING" + NewId - if an ID has been assigned + Flags - characteristics for the identifier + +Returns: + + STATUS + +--*/ +STATUS +StringDBAddStringIdentifier ( + WCHAR *StringName, + UINT16 *NewId, + UINT16 Flags + ) +{ + STRING_IDENTIFIER *StringIdentifier; + STATUS Status; + // + // If it was already used for some other language, then we don't + // need to add it. But set it to the current string identifier. + // The referenced bit is sticky. + // + Status = STATUS_SUCCESS; + StringIdentifier = StringDBFindStringIdentifierByName (StringName); + if (StringIdentifier != NULL) { + if (Flags & STRING_FLAGS_REFERENCED) { + StringIdentifier->Flags |= STRING_FLAGS_REFERENCED; + } + + mDBData.CurrentStringIdentifier = StringIdentifier; + *NewId = (UINT16) StringIdentifier->Index; + return Status; + } + + StringIdentifier = (STRING_IDENTIFIER *) MALLOC (sizeof (STRING_IDENTIFIER)); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + + memset ((char *) StringIdentifier, 0, sizeof (STRING_IDENTIFIER)); + StringIdentifier->StringName = (WCHAR *) malloc ((wcslen (StringName) + 1) * sizeof (WCHAR)); + if (StringIdentifier->StringName == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + + wcscpy (StringIdentifier->StringName, StringName); + if (*NewId != STRING_ID_INVALID) { + StringIdentifier->Index = *NewId; + StringIdentifier->Flags |= STRING_FLAGS_INDEX_ASSIGNED; + if (mDBData.NumStringIdentifiers <= StringIdentifier->Index) { + mDBData.NumStringIdentifiers = StringIdentifier->Index + 1; + } + } else { + StringIdentifier->Index = mDBData.NumStringIdentifiers++; + } + + StringIdentifier->Flags |= Flags; + // + // Add it to our list of string identifiers + // + if (mDBData.StringIdentifier == NULL) { + mDBData.StringIdentifier = StringIdentifier; + } else { + mDBData.LastStringIdentifier->Next = StringIdentifier; + } + + mDBData.LastStringIdentifier = StringIdentifier; + mDBData.CurrentStringIdentifier = StringIdentifier; + *NewId = (UINT16) StringIdentifier->Index; + return Status; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Add a new string to the database. + +Arguments: + + LanguageName - "eng" or "spa" language name + StringName - "STR_MY_TEXT" string name + Scope - from the #scope statements in the string file + Format - if we should format the string + Flags - characteristic flags for the string + +Returns: + + STATUS + +Notes: + + Several of the fields can be "inherited" from the previous calls to + our database functions. For example, if scope is NULL here, then + we'll use the previous setting. + +--*/ +STATUS +StringDBAddString ( + WCHAR *LanguageName, + WCHAR *StringName, + WCHAR *Scope, + WCHAR *String, + BOOLEAN Format, + UINT16 Flags + ) +{ + LANGUAGE_LIST *Lang; + UINT32 Size; + STRING_LIST *Str; + UINT16 StringIndex; + WCHAR TempLangName[4]; + STRING_IDENTIFIER *StringIdentifier; + + // + // Check that language name is exactly 3 characters, or emit an error. + // Truncate at 3 if it's longer, or make it 3 if it's shorter. + // + if (LanguageName != NULL) { + Size = wcslen (LanguageName); + if (Size != 3) { + ParserError (0, "invalid length for language name", "%S", LanguageName); + if (Size > 3) { + LanguageName[3] = 0; + } else { + // + // Make a local copy of the language name string, and extend to + // 3 characters since we make assumptions elsewhere in this program + // on the length. + // + wcscpy (TempLangName, LanguageName); + for (; Size < 3; Size++) { + TempLangName[Size] = L'?'; + } + + TempLangName[4] = 0; + LanguageName = TempLangName; + } + } + } + // + // If they specified a language, make sure they've defined it already + // via a #langdef statement. Otherwise use the current default language. + // + if (LanguageName != NULL) { + Lang = StringDBFindLanguageList (LanguageName); + if (Lang == NULL) { + ParserError (0, "language not defined", "%S", LanguageName); + return STATUS_ERROR; + } else { + StringDBSetCurrentLanguage (LanguageName); + } + } else { + Lang = mDBData.CurrentLanguage; + if (Lang == NULL) { + // + // Have to call SetLanguage() first + // + ParserError (0, "no language defined", "%S", StringName); + return STATUS_ERROR; + } + } + // + // If they didn't define a string identifier, use the last string identifier + // added. + // + if (StringName == NULL) { + StringName = mDBData.CurrentStringIdentifier->StringName; + if (StringName == NULL) { + ParserError (0, "no string identifier previously specified", NULL); + return STATUS_ERROR; + } + } + // + // If scope was not specified, use the default setting + // + if (Scope != NULL) { + Scope = DuplicateString (Scope); + } else { + Scope = DuplicateString (mDBData.CurrentScope); + } + // + // printf ("Adding string: %S.%S.%S\n", Lang->LanguageName, StringName, Scope); + // + // Check for duplicates for this Language.StringName.Scope. Allow multiple + // definitions of the language name and printable language name, since the + // user does not specifically define them. + // + if (StringDBFindString (Lang->LanguageName, StringName, Scope, NULL, NULL) != NULL) { + if ((wcscmp (StringName, LANGUAGE_NAME_STRING_NAME) == 0) && + (wcscmp (StringName, PRINTABLE_LANGUAGE_NAME_STRING_NAME) == 0) + ) { + ParserError ( + 0, + "string multiply defined", + "Language.Name.Scope = %S.%S.%S", + Lang->LanguageName, + StringName, + Scope + ); + return STATUS_ERROR; + } + } + + StringIndex = STRING_ID_INVALID; + if (StringDBAddStringIdentifier (StringName, &StringIndex, Flags) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + StringIdentifier = StringDBFindStringIdentifierByName (StringName); + // + // Add this string to the end of the strings for this language. + // + Str = (STRING_LIST *) malloc (sizeof (STRING_LIST)); + if (Str == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + + memset ((char *) Str, 0, sizeof (STRING_LIST)); + Size = (wcslen (String) + 1) * sizeof (WCHAR); + Str->Flags = Flags; + Str->Scope = Scope; + Str->StringName = StringIdentifier->StringName; + Str->LanguageName = DuplicateString (LanguageName); + Str->Str = (WCHAR *) MALLOC (Size); + if (Str->Str == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + // + // If not formatting, just copy the string. + // + wcscpy (Str->Str, String); + if (Format) { + StringDBFormatString (Str->Str); + } + // + // Size may change after formatting. We set the size to + // the actual size of the string, including the null for + // easier processing later. + // + Str->Size = (wcslen (Str->Str) + 1) * sizeof (WCHAR); + if (Lang->String == NULL) { + Lang->String = Str; + } else { + Lang->LastString->Next = Str; + } + + Lang->LastString = Str; + return STATUS_SUCCESS; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Given a language name, see if a language list for it has been defined + +Arguments: + + LanguageName - like "eng" + +Returns: + + A pointer to the language list + +--*/ +static +LANGUAGE_LIST * +StringDBFindLanguageList ( + WCHAR *LanguageName + ) +{ + LANGUAGE_LIST *Lang; + + Lang = mDBData.LanguageList; + while (Lang != NULL) { + if (wcscmp (LanguageName, Lang->LanguageName) == 0) { + break; + } + + Lang = Lang->Next; + } + + return Lang; +} + +/*****************************************************************************/ +STATUS +StringDBSetCurrentLanguage ( + WCHAR *LanguageName + ) +{ + LANGUAGE_LIST *Lang; + + Lang = StringDBFindLanguageList (LanguageName); + if (Lang == NULL) { + ParserError (0, "language not previously defined", "%S", LanguageName); + return STATUS_ERROR; + } + + mDBData.CurrentLanguage = Lang; + return STATUS_SUCCESS; +} + +/*****************************************************************************/ +STATUS +StringDBAddLanguage ( + WCHAR *LanguageName, + WCHAR *PrintableLanguageName + ) +{ + LANGUAGE_LIST *Lang; + // + // Check for redefinitions + // + Lang = StringDBFindLanguageList (LanguageName); + if (Lang != NULL) { + // + // Better be the same printable name + // + if (wcscmp (PrintableLanguageName, Lang->PrintableLanguageName) != 0) { + ParserError ( + 0, + "language redefinition", + "%S:%S != %S:%S", + Lang->LanguageName, + Lang->PrintableLanguageName, + LanguageName, + PrintableLanguageName + ); + return STATUS_ERROR; + // + // } else { + // ParserWarning (0, "benign language redefinition", "%S", PrintableLanguageName); + // return STATUS_WARNING; + // + } + } else { + // + // Allocate memory to keep track of this new language + // + Lang = (LANGUAGE_LIST *) malloc (sizeof (LANGUAGE_LIST)); + if (Lang == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + + memset ((char *) Lang, 0, sizeof (LANGUAGE_LIST)); + // + // Save the language name, then allocate memory to save the + // printable language name + // + wcscpy (Lang->LanguageName, LanguageName); + Lang->PrintableLanguageName = (WCHAR *) malloc ((wcslen (PrintableLanguageName) + 1) * sizeof (WCHAR)); + if (Lang->PrintableLanguageName == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + + wcscpy (Lang->PrintableLanguageName, PrintableLanguageName); + + if (mDBData.LanguageList == NULL) { + mDBData.LanguageList = Lang; + } else { + mDBData.LastLanguageList->Next = Lang; + } + + mDBData.LastLanguageList = Lang; + } + // + // Default is to make our active language this new one + // + StringDBSetCurrentLanguage (LanguageName); + // + // The first two strings for any language are the language name, + // followed by the printable language name. Add them and set them + // to referenced so they never get stripped out. + // + StringDBAddString ( + LanguageName, + LANGUAGE_NAME_STRING_NAME, + NULL, + LanguageName, + FALSE, + STRING_FLAGS_REFERENCED + ); + StringDBAddString ( + LanguageName, + PRINTABLE_LANGUAGE_NAME_STRING_NAME, + NULL, + PrintableLanguageName, + FALSE, + STRING_FLAGS_REFERENCED + ); + return STATUS_SUCCESS; +} + +/*****************************************************************************/ +static +STRING_IDENTIFIER * +StringDBFindStringIdentifierByName ( + WCHAR *StringName + ) +{ + STRING_IDENTIFIER *Identifier; + + Identifier = mDBData.StringIdentifier; + while (Identifier != NULL) { + if (wcscmp (StringName, Identifier->StringName) == 0) { + return Identifier; + } + + Identifier = Identifier->Next; + } + + return NULL; +} + +static +STRING_IDENTIFIER * +StringDBFindStringIdentifierByIndex ( + UINT32 StringIndex + ) +{ + STRING_IDENTIFIER *Identifier; + + Identifier = mDBData.StringIdentifier; + while (Identifier != NULL) { + if (Identifier->Index == StringIndex) { + return Identifier; + } + + Identifier = Identifier->Next; + } + + return NULL; +} + +/*****************************************************************************/ +static +void +StringDBWriteStandardFileHeader ( + FILE *OutFptr + ) +{ + UINT32 TempIndex; + for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) { + fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]); + } +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Given a Unicode string from an input file, reformat the string to replace + backslash control sequences with the appropriate encoding. + +Arguments: + + String - pointer to string to reformat + +Returns: + + Nothing + +--*/ +void +StringDBFormatString ( + WCHAR *String + ) +{ + WCHAR *From; + WCHAR *To; + int HexNibbles; + WCHAR HexValue; + // + // Go through the string and process any formatting characters + // + From = String; + To = String; + while (*From) { + if (*From == UNICODE_BACKSLASH) { + // + // First look for \wide and replace with the appropriate control character. Note that + // when you have "define STR L"ABC"", then sizeof(ABC) is 8 because the null char is + // counted. Make adjustments for this. We advance From below, so subtract 2 each time. + // + if (wcsncmp (From, UNICODE_WIDE_STRING, sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 1) == 0) { + *To = WIDE_CHAR; + From += sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 2; + } else if (wcsncmp (From, UNICODE_NARROW_STRING, sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 1) == 0) { + // + // Found: \narrow + // + *To = NARROW_CHAR; + From += sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 2; + } else if (wcsncmp (From, UNICODE_NBR_STRING, sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 1) == 0) { + // + // Found: \nbr + // + *To = NON_BREAKING_CHAR; + From += sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 2; + } else if (wcsncmp (From, UNICODE_BR_STRING, sizeof (UNICODE_BR_STRING) / sizeof (WCHAR) - 1) == 0) { + // + // Found: \br -- pass through untouched + // + *To = *From; + } else { + // + // Standard one-character control sequences such as \n, \r, \\, or \x + // + From++; + switch (*From) { + case ASCII_TO_UNICODE ('n'): + *To = UNICODE_CR; + To++; + *To = UNICODE_LF; + break; + + // + // carriage return + // + case ASCII_TO_UNICODE ('r'): + *To = UNICODE_CR; + break; + + // + // backslash + // + case UNICODE_BACKSLASH: + *To = UNICODE_BACKSLASH; + break; + + // + // Tab + // + case ASCII_TO_UNICODE ('t'): + *To = UNICODE_TAB; + break; + + // + // embedded double-quote + // + case UNICODE_DOUBLE_QUOTE: + *To = UNICODE_DOUBLE_QUOTE; + break; + + // + // Hex Unicode character \x1234. We'll process up to 4 hex characters + // + case ASCII_TO_UNICODE ('x'): + HexValue = 0; + for (HexNibbles = 0; HexNibbles < 4; HexNibbles++) { + if ((From[1] >= UNICODE_0) && (From[1] <= UNICODE_9)) { + HexValue = (HexValue << 4) | (From[1] - UNICODE_0); + } else if ((From[1] >= UNICODE_a) && (From[1] <= UNICODE_f)) { + HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_a); + } else if ((From[1] >= UNICODE_A) && (From[1] <= UNICODE_F)) { + HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_A); + } else { + break; + } + + From++; + } + + if (HexNibbles == 0) { + ParserWarning ( + 0, + "expected at least one valid hex digit with \\x escaped character in string", + "\\%C", + *From + ); + } else { + *To = HexValue; + } + break; + + default: + *To = UNICODE_SPACE; + ParserWarning (0, "invalid escaped character in string", "\\%C", *From); + break; + } + } + } else { + *To = *From; + } + + From++; + To++; + } + + *To = 0; +} + +/*****************************************************************************/ +STATUS +StringDBReadDatabase ( + INT8 *DBFileName, + BOOLEAN IgnoreIfNotExist, + BOOLEAN Verbose + ) +{ + STRING_DB_HEADER DbHeader; + STATUS Status; + FILE *DBFptr; + DB_DATA_ITEM_HEADER DataItemHeader; + + Status = STATUS_SUCCESS; + DBFptr = NULL; + // + // if (Verbose) { + // fprintf (stdout, "Reading database file %s\n", DBFileName); + // } + // + // Try to open the input file + // + if ((DBFptr = fopen (DBFileName, "rb")) == NULL) { + if (IgnoreIfNotExist) { + return STATUS_SUCCESS; + } + + Error (NULL, 0, 0, DBFileName, "failed to open input database file for reading"); + return STATUS_ERROR; + } + // + // Read and verify the database header + // + if (fread ((void *) &DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr) != 1) { + Error (NULL, 0, 0, DBFileName, "failed to read header from database file"); + Status = STATUS_ERROR; + goto Finish; + } + + if (DbHeader.Key != STRING_DB_KEY) { + Error (NULL, 0, 0, DBFileName, "invalid header in database file"); + Status = STATUS_ERROR; + goto Finish; + } + + if ((DbHeader.Version & STRING_DB_MAJOR_VERSION_MASK) != (STRING_DB_VERSION & STRING_DB_MAJOR_VERSION_MASK)) { + Error (NULL, 0, 0, DBFileName, "incompatible database file version -- rebuild clean"); + Status = STATUS_ERROR; + goto Finish; + } + // + // Read remaining items + // + while (fread (&DataItemHeader, sizeof (DataItemHeader), 1, DBFptr) == 1) { + switch (DataItemHeader.DataType) { + case DB_DATA_TYPE_STRING_IDENTIFIER: + StringDBReadStringIdentifier (DBFptr); + break; + + case DB_DATA_TYPE_LANGUAGE_DEFINITION: + StringDBReadLanguageDefinition (DBFptr); + break; + + case DB_DATA_TYPE_STRING_DEFINITION: + StringDBReadString (DBFptr); + break; + + default: + Error ( + NULL, + 0, + 0, + "database corrupted", + "invalid data item type 0x%X at offset 0x%X", + (UINT32) DataItemHeader.DataType, + ftell (DBFptr) - sizeof (DataItemHeader) + ); + Status = STATUS_ERROR; + goto Finish; + } + } + +Finish: + if (DBFptr != NULL) { + fclose (DBFptr); + } + + return Status; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Write everything we know to the output database file. Write: + + Database header + String identifiers[] + StringPacks[] + +Arguments: + + DBFileName - name of the file to write to + Verbose - for debug purposes, print info messages along the way. + +Returns: + + STATUS + +--*/ +STATUS +StringDBWriteDatabase ( + INT8 *DBFileName, + BOOLEAN Verbose + ) +{ + STRING_DB_HEADER DbHeader; + UINT32 Counter; + UINT32 StrLen; + LANGUAGE_LIST *Lang; + STRING_IDENTIFIER *StringIdentifier; + STRING_LIST *StrList; + FILE *DBFptr; + + if (Verbose) { + fprintf (stdout, "Writing database %s\n", DBFileName); + } + + if ((DBFptr = fopen (DBFileName, "wb")) == NULL) { + Error (NULL, 0, 0, DBFileName, "failed to open output database file for writing"); + return STATUS_ERROR; + } + // + // Fill in and write the database header + // + memset (&DbHeader, 0, sizeof (STRING_DB_HEADER)); + DbHeader.HeaderSize = sizeof (STRING_DB_HEADER); + DbHeader.Key = STRING_DB_KEY; + DbHeader.Version = STRING_DB_VERSION; + // + // Count the number of languages we have + // + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + DbHeader.NumLanguages++; + } + // + // Count up how many string identifiers we have, and total up the + // size of the names plus the size of the flags field we will + // write out too. + // + DbHeader.NumStringIdenfiers = mDBData.NumStringIdentifiers; + StringIdentifier = mDBData.StringIdentifier; + for (Counter = 0; Counter < mDBData.NumStringIdentifiers; Counter++) { + StrLen = wcslen (StringIdentifier->StringName) + 1; + DbHeader.StringIdentifiersSize += StrLen * sizeof (WCHAR) + sizeof (StringIdentifier->Flags); + StringIdentifier = StringIdentifier->Next; + } + + // + // Write the header + // + fwrite (&DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr); + if (Verbose) { + fprintf (stdout, " Number of string identifiers 0x%04X\n", DbHeader.NumStringIdenfiers); + fprintf (stdout, " Number of languages %d\n", DbHeader.NumLanguages); + } + // + // Write the string identifiers + // + for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) { + StringDBWriteStringIdentifier ( + DBFptr, + (UINT16) StringIdentifier->Index, + StringIdentifier->Flags, + StringIdentifier->StringName + ); + } + // + // Now write all the strings for each language + // + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + StringDBWriteLanguageDefinition (DBFptr, Lang->LanguageName, Lang->PrintableLanguageName); + for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) { + StringDBWriteString ( + DBFptr, + StrList->Flags, + Lang->LanguageName, + StrList->StringName, + StrList->Scope, + StrList->Str + ); + } + } + + fclose (DBFptr); + return STATUS_SUCCESS; +} + +STATUS +StringDBSetStringReferenced ( + INT8 *StringIdentifierName, + BOOLEAN IgnoreNotFound + ) +{ + STRING_IDENTIFIER *Id; + WCHAR *WName; + STATUS Status; + // + // See if it's already been defined. + // + Status = STATUS_SUCCESS; + WName = (WCHAR *) malloc ((strlen (StringIdentifierName) + 1) * sizeof (WCHAR)); + swprintf (WName, L"%S", StringIdentifierName); + Id = StringDBFindStringIdentifierByName (WName); + if (Id != NULL) { + Id->Flags |= STRING_FLAGS_REFERENCED; + } else { + if (IgnoreNotFound == 0) { + ParserWarning (0, StringIdentifierName, "string identifier not found in database"); + Status = STATUS_WARNING; + } + } + + free (WName); + return Status; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Dump the contents of a database to an output unicode file. + +Arguments: + + DBFileName - name of the pre-existing database file to read + OutputFileName - name of the file to dump the database contents to + Verbose - for printing of additional info useful for debugging + +Returns: + + STATUS + +Notes: + + There's some issue with the unicode printing routines. Therefore to + write to the output file properly, open it as binary and use fwrite. + Ideally we could open it with just L"w" and use fwprintf(). + +--*/ +STATUS +StringDBDumpDatabase ( + INT8 *DBFileName, + INT8 *OutputFileName, + BOOLEAN Verbose + ) +{ + LANGUAGE_LIST *Lang; + STRING_IDENTIFIER *StringIdentifier; + STRING_LIST *StrList; + FILE *OutFptr; + WCHAR WChar; + WCHAR CrLf[2]; + WCHAR Line[200]; + WCHAR *Scope; + // + // This function assumes the database has already been read, and + // we're just dumping our internal data structures to a unicode file. + // + if (Verbose) { + fprintf (stdout, "Dumping database file %s\n", DBFileName); + } + + OutFptr = fopen (OutputFileName, "wb"); + if (OutFptr == NULL) { + Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + + WChar = UNICODE_FILE_START; + fwrite (&WChar, sizeof (WCHAR), 1, OutFptr); + CrLf[1] = UNICODE_LF; + CrLf[0] = UNICODE_CR; + // + // The default control character is '/'. Make it '#' by writing + // "/=#" to the output file. + // + swprintf (Line, L"/=#"); + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + // + // Dump all the string identifiers and their values + // + StringDBAssignStringIndexes (); + for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) { + // + // Write the "#define " string + // + if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { + swprintf ( + Line, + L"%s %-60.60s 0x%04X", + DEFINE_STR, + StringIdentifier->StringName, + StringIdentifier->Index + ); + } else { + swprintf ( + Line, + L"%s %-60.60s 0x%04X // NOT REFERENCED", + DEFINE_STR, + StringIdentifier->StringName, + StringIdentifier->Index + ); + } + + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + } + + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + // + // Now write all the strings for each language. + // + WChar = UNICODE_DOUBLE_QUOTE; + Scope = NULL; + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + swprintf (Line, L"#langdef %s \"%s\"", Lang->LanguageName, Lang->PrintableLanguageName); + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + // + // Now the strings (in double-quotes) for this language. Write + // #string STR_NAME #language eng "string" + // + for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) { + // + // Print the internal flags for debug + // + swprintf (Line, L"// flags=0x%02X", (UINT32) StrList->Flags); + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + // + // Print the scope if changed + // + if ((Scope == NULL) || (wcscmp (Scope, StrList->Scope) != 0)) { + swprintf (Line, L"#scope %s", StrList->Scope); + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + Scope = StrList->Scope; + } + + swprintf ( + Line, + L"#string %-50.50s #language %s \"", + StrList->StringName, + Lang->LanguageName + ); + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (StrList->Str, StrList->Size - sizeof (WCHAR), 1, OutFptr); + swprintf (Line, L"\""); + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + } + } + + fclose (OutFptr); + return STATUS_SUCCESS; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Given a primary language, a string identifier number, and a list of + languages, find a secondary string. + +Arguments: + + LanguageName - primary language, like "spa" + StringId - string index value + LanguageList - linked list of "eng", "spa+cat",... + +Returns: + + Pointer to a secondary string if found. NULL otherwise. + +Notes: + + Given: LanguageName "spa" and LanguageList "spa+cat", match the + "spa" and extract the "cat" and see if there is a string defined + for "cat".StringId. + +--*/ +static +STATUS +StringDBWriteStringIdentifier ( + FILE *DBFptr, + UINT16 StringId, + UINT16 Flags, + WCHAR *IdentifierName + ) +{ + DB_DATA_ITEM_HEADER Hdr; + memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER)); + Hdr.DataType = DB_DATA_TYPE_STRING_IDENTIFIER; + if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string to output database file", NULL); + return STATUS_ERROR; + } + + if (fwrite (&StringId, sizeof (StringId), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write StringId to output database", NULL); + return STATUS_ERROR; + } + + if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write StringId flags to output database", NULL); + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, IdentifierName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +STATUS +StringDBReadStringIdentifier ( + FILE *DBFptr + ) +{ + WCHAR *IdentifierName; + UINT16 Flags; + UINT16 StringId; + UINT16 Size; + + if (fread (&StringId, sizeof (StringId), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to read StringId from database", NULL); + return STATUS_ERROR; + } + + if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to read StringId flags from database", NULL); + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &IdentifierName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + StringDBAddStringIdentifier (IdentifierName, &StringId, Flags); + // + // printf ("STRID: 0x%04X %S\n", (UINT32)StringId, IdentifierName); + // + FREE (IdentifierName); + return STATUS_SUCCESS; +} + +static +STATUS +StringDBWriteString ( + FILE *DBFptr, + UINT16 Flags, + WCHAR *Language, + WCHAR *StringName, + WCHAR *Scope, + WCHAR *Str + ) +{ + DB_DATA_ITEM_HEADER Hdr; + memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER)); + Hdr.DataType = DB_DATA_TYPE_STRING_DEFINITION; + if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string header to output database file", NULL); + return STATUS_ERROR; + } + + if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string flags to output database", NULL); + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, Language) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, StringName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, Scope) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, Str) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + // + // printf ("DBWriteString: %S.%S.%S\n", Language, StringName, Scope); + // + return STATUS_SUCCESS; +} + +static +STATUS +StringDBReadString ( + FILE *DBFptr + ) +{ + UINT16 Flags; + UINT16 Size; + WCHAR *Language; + WCHAR *StringName; + WCHAR *Scope; + WCHAR *Str; + + if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to read string flags from database", NULL); + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &Language) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &StringName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &Scope) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &Str) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + // + // If the first or second string (language name and printable language name), + // then skip them. They're added via language definitions data items in + // the database. + // + if (StringName[0] != L'$') { + StringDBAddString (Language, StringName, Scope, Str, FALSE, Flags); + } + // + // printf ("DBReadString: %S.%S.%S\n", Language, StringName, Scope); + // + FREE (Language); + FREE (StringName); + if (Str != NULL) { + FREE (Str); + } + + if (Scope != NULL) { + FREE (Scope); + } + + return STATUS_SUCCESS; +} + +static +STATUS +StringDBWriteLanguageDefinition ( + FILE *DBFptr, + WCHAR *LanguageName, + WCHAR *PrintableLanguageName + ) +{ + DB_DATA_ITEM_HEADER Hdr; + memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER)); + Hdr.DataType = DB_DATA_TYPE_LANGUAGE_DEFINITION; + if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string to output database file", NULL); + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, LanguageName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, PrintableLanguageName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +STATUS +StringDBReadLanguageDefinition ( + FILE *DBFptr + ) +{ + WCHAR *LanguageName; + WCHAR *PrintableLanguageName; + UINT16 Size; + STATUS Status; + + if (StringDBReadGenericString (DBFptr, &Size, &LanguageName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &PrintableLanguageName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + // + // printf("LANG: %S %S\n", LanguageName, PrintableLanguageName); + // + Status = StringDBAddLanguage (LanguageName, PrintableLanguageName); + FREE (LanguageName); + FREE (PrintableLanguageName); + return Status; +} +// +// All unicode strings in the database consist of a UINT16 length +// field, followed by the string itself. This routine reads one +// of those and returns the info. +// +static +STATUS +StringDBReadGenericString ( + FILE *DBFptr, + UINT16 *Size, + WCHAR **Str + ) +{ + UINT16 LSize; + UINT16 Flags; + WCHAR *LStr; + + if (fread (&LSize, sizeof (UINT16), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to read a string length field from the database", NULL); + return STATUS_ERROR; + } + + if (fread (&Flags, sizeof (UINT16), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to read a string flags field from the database", NULL); + return STATUS_ERROR; + } + + LStr = MALLOC (LSize); + if (LStr == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failed reading the database", NULL); + return STATUS_ERROR; + } + + if (fread (LStr, sizeof (WCHAR), (UINT32) LSize / sizeof (WCHAR), DBFptr) != (UINT32) LSize / sizeof (WCHAR)) { + Error (NULL, 0, 0, "failed to read string from database", NULL); + Error (NULL, 0, 0, "database read failure", "offset 0x%X", ftell (DBFptr)); + free (LStr); + return STATUS_ERROR; + } + // + // printf ("DBR: %S\n", LStr); + // + // If the flags field indicated we were asked to write a NULL string, then + // return them a NULL pointer. + // + if (Flags & STRING_FLAGS_UNDEFINED) { + *Size = 0; + *Str = NULL; + } else { + *Size = LSize; + *Str = LStr; + } + + return STATUS_SUCCESS; +} + +static +STATUS +StringDBWriteGenericString ( + FILE *DBFptr, + WCHAR *Str + ) +{ + UINT16 Size; + UINT16 Flags; + WCHAR ZeroString[1]; + // + // Strings in the database consist of a size UINT16 followed + // by the string itself. + // + if (Str == NULL) { + ZeroString[0] = 0; + Str = ZeroString; + Size = sizeof (ZeroString); + Flags = STRING_FLAGS_UNDEFINED; + } else { + Flags = 0; + Size = (UINT16) ((wcslen (Str) + 1) * sizeof (WCHAR)); + } + + if (fwrite (&Size, sizeof (UINT16), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string size to database", NULL); + return STATUS_ERROR; + } + + if (fwrite (&Flags, sizeof (UINT16), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string flags to database", NULL); + return STATUS_ERROR; + } + + if (fwrite (Str, sizeof (WCHAR), Size / sizeof (WCHAR), DBFptr) != Size / sizeof (WCHAR)) { + Error (NULL, 0, 0, "failed to write string to database", NULL); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +STRING_LIST * +StringDBFindString ( + WCHAR *LanguageName, + WCHAR *StringName, + WCHAR *Scope, + WCHAR_STRING_LIST *LanguagesOfInterest, + WCHAR_MATCHING_STRING_LIST *IndirectionList + ) +{ + LANGUAGE_LIST *Lang; + STRING_LIST *CurrString; + WCHAR_MATCHING_STRING_LIST *IndListPtr; + WCHAR TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN + 1]; + WCHAR *WCharPtr; + + // + // If we were given an indirection list, then see if one was specified for this + // string identifier. That is to say, if the indirection says "STR_ID_MY_FAVORITE MyScope", + // then if this string name matches one in the list, then do a lookup with the + // specified scope and return that value. + // + if (IndirectionList != NULL) { + for (IndListPtr = IndirectionList; IndListPtr != NULL; IndListPtr = IndListPtr->Next) { + if (wcscmp (StringName, IndListPtr->Str1) == 0) { + CurrString = StringDBFindString (LanguageName, StringName, IndListPtr->Str2, LanguagesOfInterest, NULL); + if (CurrString != NULL) { + return CurrString; + } + } + } + } + // + // First look for exact match language.stringname + // + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + if (wcscmp (LanguageName, Lang->LanguageName) == 0) { + // + // Found language match. Try to find string name match + // + for (CurrString = Lang->String; CurrString != NULL; CurrString = CurrString->Next) { + if (wcscmp (StringName, CurrString->StringName) == 0) { + // + // Found a string name match. See if we're supposed to find + // a scope match. + // + if (Scope != NULL) { + if (wcscmp (CurrString->Scope, Scope) == 0) { + return CurrString; + } + } else { + return CurrString; + } + } + } + } + } + // + // If we got here, then we didn't find a match. Look for secondary string + // matches. That is to say, if we're processing "spa", and they requested + // "spa+cat", then recursively call with "cat" + // + while (LanguagesOfInterest != NULL) { + // + // If this is the language we're looking for, then process the + // languages of interest list for it. + // + if (wcsncmp (LanguageName, LanguagesOfInterest->Str, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) { + WCharPtr = LanguagesOfInterest->Str + LANGUAGE_IDENTIFIER_NAME_LEN; + while (*WCharPtr) { + // + // Double-check the length, though it should have been checked on the + // command line. + // + if (wcslen (WCharPtr) < LANGUAGE_IDENTIFIER_NAME_LEN) { + Error (NULL, 0, 0, "malformed alternate language list", "%S", LanguagesOfInterest->Str); + return NULL; + } + + wcsncpy (TempLangName, WCharPtr, LANGUAGE_IDENTIFIER_NAME_LEN); + TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN] = 0; + CurrString = StringDBFindString (TempLangName, StringName, NULL, NULL, IndirectionList); + if (CurrString != NULL) { + return CurrString; + } + + WCharPtr += LANGUAGE_IDENTIFIER_NAME_LEN; + } + } + + LanguagesOfInterest = LanguagesOfInterest->Next; + } + + return NULL; +} + +STATUS +StringDBSetScope ( + WCHAR *Scope + ) +{ + // + // Free up existing scope memory. + // + if (mDBData.CurrentScope != NULL) { + FREE (mDBData.CurrentScope); + } + + mDBData.CurrentScope = DuplicateString (Scope); + return STATUS_SUCCESS; +} +// +// We typically don't assign index values to string identifiers +// until we're ready to write out files. To reduce the size of +// the output file, re-order the string identifiers to move any +// unreferenced ones to the end. Then we'll walk the list +// again to assign string indexes, keeping track of the last +// one referenced. +// +static +void +StringDBAssignStringIndexes ( + VOID + ) +{ + STRING_IDENTIFIER *StrId; + STRING_IDENTIFIER *FirstUsed; + STRING_IDENTIFIER *LastUsed; + STRING_IDENTIFIER *FirstUnused; + STRING_IDENTIFIER *LastUnused; + UINT32 Index; + UINT32 MaxReferenced; + + // + // Create two lists -- used and unused. Then put them together with + // the unused ones on the end. + // + FirstUsed = NULL; + LastUsed = NULL; + FirstUnused = NULL; + LastUnused = NULL; + StrId = mDBData.StringIdentifier; + while (StrId != NULL) { + if ((StrId->Flags & STRING_FLAGS_REFERENCED) == 0) { + // + // Put it on the unused list + // + if (FirstUnused == NULL) { + FirstUnused = StrId; + } else { + LastUnused->Next = StrId; + } + + LastUnused = StrId; + StrId = StrId->Next; + LastUnused->Next = NULL; + } else { + // + // Put it on the used list + // + if (FirstUsed == NULL) { + FirstUsed = StrId; + } else { + LastUsed->Next = StrId; + } + + LastUsed = StrId; + StrId = StrId->Next; + LastUsed->Next = NULL; + } + } + // + // Join the lists + // + if (FirstUsed != NULL) { + mDBData.StringIdentifier = FirstUsed; + LastUsed->Next = FirstUnused; + } else { + mDBData.StringIdentifier = FirstUnused; + } + + MaxReferenced = 0; + Index = 0; + for (StrId = mDBData.StringIdentifier; StrId != NULL; StrId = StrId->Next) { + StrId->Index = Index; + Index++; + if (StrId->Flags & STRING_FLAGS_REFERENCED) { + mDBData.NumStringIdentifiersReferenced = Index; + } + } + + mDBData.NumStringIdentifiers = Index; +} + +static +WCHAR * +DuplicateString ( + WCHAR *Str + ) +{ + WCHAR *NewStr; + if (Str == NULL) { + return NULL; + } + + NewStr = MALLOC ((wcslen (Str) + 1) * sizeof (WCHAR)); + if (NewStr == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return NULL; + } + + wcscpy (NewStr, Str); + return NewStr; +} + +static +WCHAR * +AsciiToWchar ( + INT8 *Str + ) +{ + UINT32 Len; + WCHAR *NewStr; + WCHAR *Ptr; + + Len = strlen (Str) + 1; + NewStr = (WCHAR *) malloc (Len * sizeof (WCHAR)); + for (Ptr = NewStr; *Str != 0; Str++, Ptr++) { + *Ptr = (UINT16) (UINT8) *Str; + } + + *Ptr = 0; + return NewStr; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Create an HII export string pack for the strings in our database. + +Arguments: + + FileName - name of the output file to write + +Returns: + + STATUS + + +--*/ +STATUS +StringDBCreateHiiExportPack ( + INT8 *FileName + ) +{ + FILE *Fptr; + LANGUAGE_LIST *Lang; + STRING_LIST *CurrString; + STRING_LIST EmptyString; + UINT32 Offset; + UINT32 StringIndex; + UINT32 TempIndex; + EFI_HII_STRING_PACK StringPack; + UINT32 Len; + WCHAR ZeroString[1]; + WCHAR *TempStringPtr; + WCHAR *LangName; + STRING_IDENTIFIER *StringIdentifier; + + if ((Fptr = fopen (FileName, "wb")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open output HII export file"); + return STATUS_ERROR; + } + // + // Assign index values to the string identifiers + // + StringDBAssignStringIndexes (); + // + // If a given string is not defined, then we'll use this one. + // + memset (&EmptyString, 0, sizeof (EmptyString)); + EmptyString.Size = sizeof (ZeroString); + EmptyString.Str = ZeroString; + // + // Process each language, then each string for each langage + // + ZeroString[0] = 0; + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + // + // Process each string for this language. We have to make 3 passes on the strings: + // Pass1: computes sizes and fill in the string pack header + // Pass2: write the array of offsets + // Pass3: write the strings + // + // + // PASS 1: Fill in and print the HII string pack header + // + // Compute the size for this language package and write + // the header out. Each string package contains: + // Header + // Offset[] -- an array of offsets to strings, of type RELOFST each + // String[] -- the actual strings themselves + // + memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK)); + StringPack.Header.Type = EFI_HII_STRING; + StringPack.NumStringPointers = (UINT16) mDBData.NumStringIdentifiersReferenced; + LangName = Lang->LanguageName; + // + // First string is the language name. If we're printing all languages, then + // it's just the "spa". If we were given a list of languages to print, then it's + // the "spacat" string. Compute its offset and fill in + // the info in the header. Since we know the language name string's length, + // and the printable language name follows it, use that info to fill in the + // entry for the printable language name as well. + // + StringPack.LanguageNameString = (STRING_OFFSET) (sizeof (EFI_HII_STRING_PACK) + (mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET))); + StringPack.PrintableLanguageName = (STRING_OFFSET) (StringPack.LanguageNameString + (wcslen (LangName) + 1) * sizeof (WCHAR)); + // + // Add up the size of all strings so we can fill in our header. + // + Len = 0; + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + Len += (wcslen (LangName) + 1) * sizeof (WCHAR); + } else { + // + // Find a string with this language.stringname + // + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + // + // Find a matching string if this string identifier was referenced + // + EmptyString.Flags = STRING_FLAGS_UNDEFINED; + CurrString = NULL; + if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + if (NULL == CurrString) { + // + // If string for Lang->LanguageName is not found, try to get an English version + // + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + } + } + + if (CurrString == NULL) { + CurrString = &EmptyString; + EmptyString.Flags |= StringIdentifier->Flags; + } + + Len += CurrString->Size; + } + } + StringPack.Header.Length = sizeof (EFI_HII_STRING_PACK) + + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET) + + Len; + // + // Write out the string pack header + // + fwrite ((void *) &StringPack, sizeof (StringPack), 1, Fptr); + // + // PASS2 : write the offsets + // + // Traverse the list of strings again and write the array of offsets. The + // offset to the first string is the size of the string pack header + // plus the size of the offsets array. The other strings follow it. + // + StringIndex = 0; + Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + // + // Write the offset + // + fwrite (&Offset, sizeof (STRING_OFFSET), 1, Fptr); + // + // Find the string name + // + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + Offset += (wcslen (LangName) + 1) * sizeof (WCHAR); + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + NULL, + NULL + ); + } else { + // + // Find a matching string + // + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + if (NULL == CurrString) { + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, // scope + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + } + + EmptyString.LanguageName = Lang->LanguageName; + if (CurrString == NULL) { + CurrString = &EmptyString; + EmptyString.Flags = STRING_FLAGS_UNDEFINED; + } else if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) { + CurrString = &EmptyString; + EmptyString.Flags = 0; + } + + Offset += CurrString->Size; + } + } + + // + // PASS 3: write the strings themselves. + // + Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + TempStringPtr = LangName; + } else { + // + // Find a matching string if this string identifier was referenced + // + CurrString = NULL; + if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + if (NULL == CurrString) { + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, // scope + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + } + } + + if (CurrString == NULL) { + CurrString = &EmptyString; + } + + TempStringPtr = CurrString->Str; + } + + for (TempIndex = 0; TempStringPtr[TempIndex] != 0; TempIndex++) { + fwrite (&TempStringPtr[TempIndex], sizeof (CHAR16), 1, Fptr); + Offset += 2; + } + // + // Print NULL WCHAR at the end of this string. + // + TempIndex = 0; + fwrite (&TempIndex, sizeof (CHAR16), 1, Fptr); + Offset += 2; + } + // + // Sanity check the offset. Make sure our running offset is what we put in the + // string pack header. + // + if (StringPack.Header.Length != Offset) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "stringpack size 0x%X does not match final size 0x%X", + StringPack.Header.Length, + Offset + ); + } + } + // + // Print terminator string pack, closing brace and close the file. + // The size of 0 triggers to the consumer that this is the end. + // + memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK)); + StringPack.Header.Type = EFI_HII_STRING; + fwrite ((void *) &StringPack, sizeof (StringPack), 1, Fptr); + fclose (Fptr); + return STATUS_SUCCESS; +} diff --git a/Tools/Source/TianoTools/StrGather/StringDB.h b/Tools/Source/TianoTools/StrGather/StringDB.h new file mode 100644 index 0000000000..4dc05a3642 --- /dev/null +++ b/Tools/Source/TianoTools/StrGather/StringDB.h @@ -0,0 +1,136 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + StringDB.h + +Abstract: + + Common defines and prototypes for string database management + +--*/ + +#ifndef _STRING_DB_H_ +#define _STRING_DB_H_ + +#define LANGUAGE_NAME_STRING_NAME L"$LANGUAGE_NAME" +#define PRINTABLE_LANGUAGE_NAME_STRING_NAME L"$PRINTABLE_LANGUAGE_NAME" + +void +StringDBConstructor ( + void + ) +; +void +StringDBDestructor ( + void + ) +; + +STATUS +StringDBAddString ( + WCHAR *LanguageName, + WCHAR *StringIdentifier, + WCHAR *Scope, + WCHAR *String, + BOOLEAN Format, + UINT16 Flags + ) +; + +STATUS +StringDBSetScope ( + WCHAR *Scope + ) +; + +#define STRING_FLAGS_REFERENCED 0x0001 // if referenced somewhere +#define STRING_FLAGS_UNDEFINED 0x0002 // if we added it for padding purposes +#define STRING_FLAGS_INDEX_ASSIGNED 0x0004 // so don't change the index value +#define STRING_ID_INVALID 0xFFFF +#define STRING_ID_LANGUAGE_NAME 0x0000 +#define STRING_ID_PRINTABLE_LANGUAGE_NAME 0x0001 + +STATUS +StringDBAddStringIdentifier ( + WCHAR *StringIdentifier, + UINT16 *NewId, + UINT16 Flags + ) +; + +STATUS +StringDBReadDatabase ( + INT8 *DBFileName, + BOOLEAN IgnoreIfNotExist, + BOOLEAN Verbose + ) +; + +STATUS +StringDBWriteDatabase ( + INT8 *DBFileName, + BOOLEAN Verbose + ) +; + +STATUS +StringDBDumpDatabase ( + INT8 *DBFileName, + INT8 *OutputFileName, + BOOLEAN Verbose + ) +; + +STATUS +StringDBAddLanguage ( + WCHAR *LanguageName, + WCHAR *PrintableLanguageName + ) +; + +STATUS +StringDBDumpCStrings ( + INT8 *FileName, + INT8 *BaseName, + WCHAR_STRING_LIST *LanguagesOfInterest, + WCHAR_MATCHING_STRING_LIST *IndirectionList + ) +; + +STATUS +StringDBDumpStringDefines ( + INT8 *FileName, + INT8 *BaseName + ) +; + +STATUS +StringDBSetCurrentLanguage ( + WCHAR *LanguageName + ) +; + +STATUS +StringDBSetStringReferenced ( + INT8 *StringIdentifierName, + BOOLEAN IgnoreNotFound + ) +; + +void +StringDBFormatString ( + WCHAR *String + ) +; + +#endif // #ifndef _STRING_DB_H_ diff --git a/Tools/Source/TianoTools/StrGather/build.gcc b/Tools/Source/TianoTools/StrGather/build.gcc new file mode 100644 index 0000000000..c7c6af7003 --- /dev/null +++ b/Tools/Source/TianoTools/StrGather/build.gcc @@ -0,0 +1 @@ +gcc -mno-cygwin -mno-cygwin -I "$WORKSPACE/MdePkg/Include/" -I"$WORKSPACE/MdePkg/Include/Ia32/" -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ StrGather.c StringDB.c -o StrGather -L../Library-mingw -lCommon diff --git a/Tools/Source/TianoTools/StrGather/build.xml b/Tools/Source/TianoTools/StrGather/build.xml new file mode 100644 index 0000000000..e7a47dc49d --- /dev/null +++ b/Tools/Source/TianoTools/StrGather/build.xml @@ -0,0 +1,119 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/VfrCompile/EfiVfr.h b/Tools/Source/TianoTools/VfrCompile/EfiVfr.h new file mode 100644 index 0000000000..f7c534d336 --- /dev/null +++ b/Tools/Source/TianoTools/VfrCompile/EfiVfr.h @@ -0,0 +1,181 @@ +/*++ + +Copyright (c) 2004 - 2005, 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. + +Module Name: + + EfiVfr.h + +Abstract: + + Defines and prototypes for the EFI internal forms representation + setup protocol and drivers + +--*/ + +#ifndef _EFI_VFR_H_ +#define _EFI_VFR_H_ + +#include +#include +#include "InternalFormRepresentation.h" +#include + +// +// This number should be incremented with each change to the VFR compiler. +// We write the version to the output list file for debug purposes. +// +#define VFR_COMPILER_VERSION "1.88" + +// +// Maximum file path for filenames +// +#ifndef MAX_PATH +#define MAX_PATH 255 +#endif +#define MAX_QUEUE_COUNT 255 +#define MAX_LINE_LEN 1024 +#define PROGRAM_NAME "VfrCompile" + +// +// We parse C-style structure definitions which can then be referenced +// in VFR statements. +// We need to define an internal structure that can be used to +// track the fields in a structure definition, and another structure +// to keep track of the structure name and subfields. +// +typedef struct _STRUCT_FIELD_DEFINITION { + struct _STRUCT_FIELD_DEFINITION *Next; + int DataSize; + int Offset; // from the start of the structure + int ArrayLength; + char IsArray; + char *Name; +} STRUCT_FIELD_DEFINITION; + +typedef struct _STRUCT_DEFINITION { + struct _STRUCT_DEFINITION *Next; + int Size; + int LineNum; // line number where the structure was defined + int IsNonNV; // if this is the non-NV data structure definition + int Referenced; // if it's referenced anywhere in the VFR + int VarStoreIdValid; // found a 'varstore' statement for it in the VFR + unsigned short VarStoreId; // key from a varstore IFR statement + int VarStoreLineNum; // line number where VARSTORE was defined + char *Name; + STRUCT_FIELD_DEFINITION *Field; + STRUCT_FIELD_DEFINITION *LastField; +} STRUCT_DEFINITION; + +// +// For the IdEqValList variable list of UINT16's, keep track of them using +// a linked list until we know how many there are. +// We also use a linked list of these to keep track of labels used in +// the VFR script so we can catch duplicates. +// We'll also use it to keep track of defined varstore id's so we can +// detect duplicate definitions. +// +typedef struct _UINT16_LIST { + struct _UINT16_LIST *Next; + UINT16 Value; + UINT32 LineNum; +} UINT16_LIST; + +typedef struct _GOTO_REFERENCE { + struct _GOTO_REFERENCE *Next; + UINT32 RefLineNum; // line number of source file where referenced + UINT16 Value; +} GOTO_REFERENCE; + +typedef struct _FORM_ID_VALUE { + struct _FORM_ID_VALUE *Next; + UINT32 LineNum; + UINT16 Value; +} FORM_ID_VALUE; + +// +// We keep track in the parser of all "#line 4 "x.y"" strings so we +// can cross-reference the line numbers in the preprocessor output .i file +// to the original input files. +// +typedef struct _PARSER_LINE_DEFINITION { + struct _PARSER_LINE_DEFINITION *Next; + UINT32 HashLineNum; // from the #line stmt + UINT32 TokenLineNum; // line number in the .i file + CHAR8 *FileName; // from the #line stmt +} PARSER_LINE_DEFINITION; + +extern PARSER_LINE_DEFINITION *gLineDefinition; +extern PARSER_LINE_DEFINITION *gLastLineDefinition; + +extern +char * +ConvertLineNumber ( + UINT32 *LineNum + ) +/*++ + +Routine Description: + Given the line number in the preprocessor-output file, use the line number + information we've saved to determine the source file name and line number + where the code originally came from. This is required for error reporting. + +Arguments: + LineNum - the line number in the preprocessor-output file. + +Returns: + Returns a pointer to the source file name. Also returns the line number + in the provided LineNum argument + +--*/ +; + +typedef struct _IFR_BYTE { + struct _IFR_BYTE *Next; + UINT32 LineNum; + UINT8 OpcodeByte; + UINT8 KeyByte; +} IFR_BYTE; + +typedef struct { + CHAR8 VfrFileName[MAX_PATH]; + CHAR8 VfrListFileName[MAX_PATH]; + INT8 CreateListFile; + INT8 CreateIfrBinFile; + CHAR8 IfrOutputFileName[MAX_PATH]; + CHAR8 OutputDirectory[MAX_PATH]; + CHAR8 PreprocessorOutputFileName[MAX_PATH]; + CHAR8 VfrBaseFileName[MAX_PATH]; // name of input VFR file with no path or extension + CHAR8 *IncludePaths; + CHAR8 *CPreprocessorOptions; +} OPTIONS; + +extern OPTIONS gOptions; + +VOID +WriteStandardFileHeader ( + FILE *OutFptr + ) +/*++ + +Routine Description: + This function is invoked to emit a standard header to an + output text file. + +Arguments: + OutFptr - file to write the header to + +Returns: + None + +--*/ +; + +#endif // #ifndef _EFI_VFR_H_ diff --git a/Tools/Source/TianoTools/VfrCompile/VfrCompile.g b/Tools/Source/TianoTools/VfrCompile/VfrCompile.g new file mode 100644 index 0000000000..3646c5d1cd --- /dev/null +++ b/Tools/Source/TianoTools/VfrCompile/VfrCompile.g @@ -0,0 +1,3527 @@ +/*++ + +Copyright (c) 2004 - 2005, 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. + +Module Name: + + VfrCompile.g + +Abstract: + + PCCTS parser and lexer definitions for the EFI VFR forms compiler + +--*/ + +#header<< + +#include +#include +#include +#include +#include "EfiUtilityMsgs.h" +#include "EfiVfr.h" +#include "VfrServices.h" +#include +#include + +#include +#ifndef __GNUC__ +#include +#include // for spawn functions +#else +#include +#endif + +>> + +<< + +// +// Base info for DLG-generated scanner +// +#include "DLexerBase.h" + +// +// Include the scanner file generated by DLG +// +#include "DLGLexer.h" + +class DLGLexerVfr : public DLGLexer +{ +public: + DLGLexerVfr (DLGFileInput *F) : DLGLexer (F) {}; + INT32 errstd (char *Text) + { + printf ("unrecognized input '%s'\n", Text); + } +}; + +// +// Base token definitions for ANTLR +// +#include "AToken.h" + +// +// This is how we invoke the C preprocessor on the VFR source file +// to resolve #defines, #includes, etc. To make C source files +// shareable between VFR and drivers, define VFRCOMPILE so that +// #ifdefs can be used in shared .h files. +// +#ifdef __GNUC__ +#define PREPROCESSOR_COMMAND "gcc " +#define PREPROCESSOR_OPTIONS "-x c -E -P -DVFRCOMPILE " +#define FILE_SEP_CHAR '/' +#define FILE_SEP_STRING "/" +#else +#define PREPROCESSOR_COMMAND "cl.exe " +#define PREPROCESSOR_OPTIONS "/nologo /P /TC /DVFRCOMPILE " +#define FILE_SEP_CHAR '/' +#define FILE_SEP_STRING "/" +#endif + +typedef ANTLRCommonToken ANTLRToken; + +// +// Specify the filename extensions for the files we generate. +// +#define VFR_BINARY_FILENAME_EXTENSION ".c" +#define VFR_LIST_FILENAME_EXTENSION ".lst" + +static +VOID +Usage (); + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ); + +static +VOID +Cleanup (); + +// +// Globals +// +OPTIONS gOptions; + +int +main ( + int argc, + char **argv + ) +/*++ + +Routine Description: + Application entry point function. Parse command-line arguments, + invoke the parser, clean up, and return. + +Arguments: + argc - standard argc passed to main() per C conventions + argv - standard argv passed to main() per C conventions + +Returns: + STATUS_SUCCESS - program executed with no errors or warnings + STATUS_WARNING - program executed with warnings + STATUS_ERROR - non-recoverable errors encountered while processing + +--*/ +{ + FILE *VfrFptr; + char *Cmd; + char *Cptr; + int Len; + STATUS Status; + + // + // Set our program name for the error printing routines. + // Then set printing limits. + // + SetUtilityName (PROGRAM_NAME); + SetPrintLimits (20, 20, 30); + // + // Process the command-line arguments + // + if (ProcessArgs (argc, argv) != STATUS_SUCCESS) { + Usage (); + Cleanup(); + return STATUS_ERROR; + } + VfrFptr = NULL; + // + // Verify the VFR script file exists + // + if ((VfrFptr = fopen (gOptions.VfrFileName, "r")) == NULL) { + Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "could not open input VFR file"); + Cleanup(); + return STATUS_ERROR; + } + // + // Now close the file and make a system call to run the preprocessor + // on it. + // + fclose (VfrFptr); + Len = strlen (PREPROCESSOR_OPTIONS) + strlen (gOptions.VfrFileName) + 10; + if (gOptions.CPreprocessorOptions != NULL) { + Len += strlen (gOptions.CPreprocessorOptions) + 1; + } + if (gOptions.IncludePaths != NULL) { + Len += strlen (gOptions.IncludePaths) + 1; + } + Cmd = (char *)malloc (Len); + if (Cmd == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "could not allocate memory"); + Cleanup(); + return STATUS_ERROR; + } + strcpy (Cmd, PREPROCESSOR_OPTIONS); + if (gOptions.IncludePaths != NULL) { + strcat (Cmd, gOptions.IncludePaths); + strcat (Cmd, " "); + } + if (gOptions.CPreprocessorOptions != NULL) { + strcat (Cmd, gOptions.CPreprocessorOptions); + strcat (Cmd, " "); + } + strcat (Cmd, gOptions.VfrFileName); +#ifndef __GNUC__ + Status = _spawnlp (_P_WAIT, PREPROCESSOR_COMMAND, Cmd, NULL); +#else + { + char CommandLine[1000]; + char *p; + + // + // Lean the slashes forward. + // + for (p = gOptions.PreprocessorOutputFileName; *p; p++) { + if (*p=='\\') { + *p=FILE_SEP_CHAR; + } + } + + // + // Lean the slashes forward. + // + for (p = Cmd; *p; p++) { + if (*p=='\\') { + *p=FILE_SEP_CHAR; + } + } + + sprintf(CommandLine, "%s %s > %s", PREPROCESSOR_COMMAND, Cmd, gOptions.PreprocessorOutputFileName); + Status = system (CommandLine); + } +#endif + if (Status != 0) { + Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "failed to spawn C preprocessor on VFR file"); + printf ("Command: '%s %s'\n", PREPROCESSOR_COMMAND, Cmd); + Cleanup(); + return STATUS_ERROR; + } + free (Cmd); + // + // Open the preprocessor output file + // + if ((VfrFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) { + Error (PROGRAM_NAME, 0, 0, "failed to open input VFR preprocessor output file", + gOptions.PreprocessorOutputFileName); + Cleanup(); + return STATUS_ERROR; + } + // + // Define input VFR file + // + DLGFileInput InputFile (VfrFptr); + // + // Define an instance of the scanner + // + DLGLexerVfr Scanner (&InputFile); + // + // Define token buffer between scanner and parser + // + ANTLRTokenBuffer Pipe (&Scanner); + // + // Create a token to use as a model + // + ANTLRToken Tok; + // + // Tell the scanner what type the token is + // + Scanner.setToken (&Tok); + // + // Create an instance of our parser + // + EfiVfrParser Parser (&Pipe); + // + // Initialize the parser + // + Parser.init (); + Status = GetUtilityStatus (); + if (Status != STATUS_SUCCESS) { + Cleanup(); + return Status; + } + // + // Start the first rule + // + Parser.program (); + // + // Close the input script file + // + fclose (VfrFptr); + Parser.WriteIfrBytes (); + // + // Call cleanup, which does some extra checking of the script + // + Parser.Cleanup (); + Cleanup(); + // + // If we had an error somewhere, delete our output files so that + // a subsequent build will rebuild them. + // + Status = GetUtilityStatus (); + if (Status == STATUS_ERROR) { + remove (gOptions.IfrOutputFileName); + } + return Status; +} +static +VOID +Cleanup () +/*++ + +Routine Description: + Free up memory allocated during parsing. + +Arguments: + None + +Returns: + None + +--*/ +{ + // + // Free up our string we allocated to track the include paths + // + if (gOptions.IncludePaths != NULL) { + free (gOptions.IncludePaths); + gOptions.IncludePaths = NULL; + } + // + // Free up our string we allocated to track preprocessor options + // + if (gOptions.CPreprocessorOptions != NULL) { + free (gOptions.CPreprocessorOptions); + gOptions.CPreprocessorOptions = NULL; + } +} + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + Process the command-line arguments. + +Arguments: + Argc - standard argc passed to main() + Argv - standard argv passed to main() + +Returns: + STATUS_SUCCESS - program should continue (all args ok) + +--*/ +{ + char *IncludePaths; + char *CPreprocessorOptions; + int Len; + char CopyStr[MAX_PATH]; + char *Cptr; + + // + // Put options in known state. + // + memset ((char *)&gOptions, 0, sizeof (OPTIONS)); + // + // Go through all the arguments that start with '-' + // + Argc--; + Argv++; + while ((Argc > 0) && (Argv[0][0] == '-')) { + // + // -? or -h help option -- return an error for printing usage + // + if ((stricmp (Argv[0], "-?") == 0) || (stricmp (Argv[0], "-h") == 0)) { + return STATUS_ERROR; + break; + // + // -l to create a listing output file + // + } else if (stricmp (Argv[0], "-l") == 0) { + gOptions.CreateListFile = 1; + // + // -I include_path option for finding include files. We'll pass this + // to the preprocessor. Turn them all into a single include string. + // + } else if (stricmp (Argv[0], "-i") == 0) { + if ((Argc < 2) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing path argument"); + return STATUS_ERROR; + } + Argc--; + Argv++; + Len = strlen (" -I "); + Len += strlen (Argv[0]) + 2; + if (gOptions.IncludePaths != NULL) { + Len += strlen (gOptions.IncludePaths); + } + IncludePaths = (CHAR8 *)malloc (Len); + if (IncludePaths == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + IncludePaths[0] = 0; + if (gOptions.IncludePaths != NULL) { + strcpy (IncludePaths, gOptions.IncludePaths); + free (gOptions.IncludePaths); + } + strcat (IncludePaths, " -I "); + strcat (IncludePaths, Argv[0]); + gOptions.IncludePaths = IncludePaths; + // + // -od OutputDirectory to define a common directory for output files + // + } else if (stricmp (Argv[0], "-od") == 0) { + if ((Argc < 2) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output directory name"); + return STATUS_ERROR; + } + Argc--; + Argv++; + strcpy (gOptions.OutputDirectory, Argv[0]); + } else if (stricmp (Argv[0], "-ibin") == 0) { + gOptions.CreateIfrBinFile = 1; + } else if (stricmp (Argv[0], "-nostrings") == 0) { + // deprecated option + // + // -ppflag C-preprocessor-flag option for passing options to the C preprocessor. + // Turn them all into a single string. + // + } else if (stricmp (Argv[0], "-ppflag") == 0) { + if (Argc < 2) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing C-preprocessor argument"); + return STATUS_ERROR; + } + Argc--; + Argv++; + Len = strlen (Argv[0]) + 2; + if (gOptions.CPreprocessorOptions != NULL) { + Len += strlen (gOptions.CPreprocessorOptions); + } + CPreprocessorOptions = (CHAR8 *)malloc (Len); + if (CPreprocessorOptions == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + CPreprocessorOptions[0] = 0; + if (gOptions.CPreprocessorOptions != NULL) { + strcpy (CPreprocessorOptions, gOptions.CPreprocessorOptions); + free (gOptions.CPreprocessorOptions); + } + strcat (CPreprocessorOptions, " "); + strcat (CPreprocessorOptions, Argv[0]); + gOptions.CPreprocessorOptions = CPreprocessorOptions; + } else { + Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option"); + return STATUS_ERROR; + } + Argc--; + Argv++; + } + // + // Must specify at least the vfr file name + // + if (Argc > 1) { + Error (PROGRAM_NAME, 0, 0, Argv[1], "unrecognized argument after VFR file name"); + return STATUS_ERROR; + } else if (Argc < 1) { + Error (PROGRAM_NAME, 0, 0, NULL, "must specify VFR file name"); + return STATUS_ERROR; + } + strcpy (gOptions.VfrFileName, Argv[0]); + // + // We run the preprocessor on the VFR file to manage #include statements. + // Unfortunately the preprocessor does not allow you to specify the + // output name or path of the resultant .i file, so we have to do + // some work. Here we'll extract the basename of the VFR file, then + // append .i on the end. + // + strcpy (CopyStr, gOptions.VfrFileName); + Cptr = CopyStr + strlen (CopyStr) - 1; + for (;(Cptr > CopyStr) && (*Cptr != '\\') && (*Cptr != ':') && (*Cptr != '/'); Cptr--); + if (Cptr == CopyStr) { + strcpy (gOptions.PreprocessorOutputFileName, Cptr); + strcpy (gOptions.VfrBaseFileName, Cptr); + } else { + strcpy (gOptions.PreprocessorOutputFileName, Cptr+1); + strcpy (gOptions.VfrBaseFileName, Cptr+1); + } + for (Cptr = gOptions.PreprocessorOutputFileName; *Cptr && (*Cptr != '.'); Cptr++); + strcpy (Cptr, ".i"); + // + // Terminate the vfr file basename at the extension + // + for (Cptr = gOptions.VfrBaseFileName; *Cptr && (*Cptr != '.'); Cptr++) { + } + *Cptr = 0; + // + // If they defined an output directory, prepend all output files + // with the working directory. Output files of interest: + // VfrListFileName -- list file + // IfrOutputFileName -- IFR bytes + // StringOutputFileName -- string bytes + // StringListFileName -- not used + // StringDefineFileName -- #defines of string identifiers + // + // We have two cases: + // 1. Output directory (-od) not specified, in which case output files + // go to the current working directory. + // 2. Output directory specified, in which case the output files + // go directly to the specified directory. + // + if (gOptions.OutputDirectory[0] == 0) { + CopyStr[0] = 0; +#ifndef __GNUC__ + _getcwd (CopyStr, sizeof (CopyStr)); +#else + getcwd (CopyStr, sizeof (CopyStr)); +#endif + strcpy (gOptions.OutputDirectory, CopyStr); + } + // + // Make sure output directory has a trailing backslash + // + if (gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '\\' || + gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '/') { + strcat (gOptions.OutputDirectory, FILE_SEP_STRING); + } + // + // Create the base output file name as: path\base, copy it to all the output + // filenames, and then add the appropriate extension to each. + // + strcpy (gOptions.VfrListFileName, gOptions.OutputDirectory); + strcat (gOptions.VfrListFileName, gOptions.VfrBaseFileName); + strcpy (gOptions.IfrOutputFileName, gOptions.VfrListFileName); + strcat (gOptions.VfrListFileName, VFR_LIST_FILENAME_EXTENSION); + strcat (gOptions.IfrOutputFileName, VFR_BINARY_FILENAME_EXTENSION); + // + // We set a default list file name, so if they do not + // want a list file, null out the name now. + // + if (gOptions.CreateListFile == 0) { + gOptions.VfrListFileName[0] = 0; + } + return STATUS_SUCCESS; +} +static +VOID +Usage () +/*++ + +Routine Description: + Print utility usage instructions + +Arguments: + None + +Returns: + None + +--*/ +{ + int Index; + const char *Help[] = { + " ", + "VfrCompile version " VFR_COMPILER_VERSION, + " ", + " Usage: VfrCompile {options} [VfrFile]", + " ", + " where options include:", + " -? or -h prints this help", + " -l create an output IFR listing file", + " -i IncPath add IncPath to the search path for VFR included files", + " -od OutputDir deposit all output files to directory OutputDir (default=cwd)", + " -ibin create an IFR HII pack file", + " where parameters include:", + " VfrFile name of the input VFR script file", + " ", + NULL + }; + for (Index = 0; Help[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Help[Index]); + } +} + +>> + + +#lexaction +<< + +#include "EfiVfr.h" + +PARSER_LINE_DEFINITION *gLineDefinition = NULL; +PARSER_LINE_DEFINITION *gLastLineDefinition = NULL; + +VOID +AddFileLine ( + char *TokenString, + UINT32 TokenLine + ) +/*++ + +Routine Description: + During the lexer phase, if we encounter a #line statement output by + the preprocessor, this function gets called. We'll save off the info + for error reporting purposes. The preprocessor line information has the + form: + + #line 3 "FileName.c" + +Arguments: + TokenString - the parsed string as shown above + TokenLine - the line number in the preprocessed output file + +Returns: + NA + +--*/ +{ + PARSER_LINE_DEFINITION *LineDef; + CHAR8 *Cptr; + + // + // Allocate a structure in which we can keep track of this line information. + // + LineDef = (PARSER_LINE_DEFINITION *)malloc (sizeof (PARSER_LINE_DEFINITION)); + memset ((char *)LineDef, 0, sizeof (PARSER_LINE_DEFINITION)); + LineDef->TokenLineNum = TokenLine; + LineDef->HashLineNum = atoi (TokenString + 6); + // + // Find the quotes in the filename, then allocate space in the line + // def structure for a copy of the filename. Finally, copy it without + // quotes to the line def. + // + for (Cptr = TokenString + 7; *Cptr && (*Cptr != '"'); Cptr++); + if (*Cptr == '"') { + LineDef->FileName = (CHAR8 *)malloc (strlen (Cptr)); + Cptr++; + strcpy (LineDef->FileName, Cptr); + for (Cptr = LineDef->FileName; *Cptr && (*Cptr != '"'); Cptr++); + *Cptr = 0; + // + // Now add this new one to the list + // + if (gLineDefinition == NULL) { + gLineDefinition = LineDef; + } else { + gLastLineDefinition->Next = LineDef; + } + gLastLineDefinition = LineDef; + } else { + Error (PROGRAM_NAME, 0, 0, "invalid line definition in preprocessor output file", TokenString); + free (LineDef); + return; + } +} +char * +ConvertLineNumber ( + UINT32 *LineNum + ) +/*++ + +Routine Description: + Given the line number in the preprocessor-output file, use the line number + information we've saved to determine the source file name and line number + where the code originally came from. This is required for error reporting. + +Arguments: + LineNum - the line number in the preprocessor-output file. + +Returns: + Returns a pointer to the source file name. Also returns the line number + in the provided LineNum argument + +--*/ +{ + PARSER_LINE_DEFINITION *LineDef; + // + // Step through our linked list of #line information we saved off. + // For each one, look at its line number, and the line number of the + // next record, and see if the passed-in line number is in the range. + // If it is, then convert the line number to the appropriate line number + // of the original source file. + // + for (LineDef = gLineDefinition; LineDef != NULL; LineDef = LineDef->Next) { + // + // The given LineNum is the line number from the .i file. + // Find a line definition whose range includes this line number, + // convert the line number, and return the filename. + // + if (LineDef->TokenLineNum <= *LineNum) { + if (LineDef->Next != NULL) { + if (LineDef->Next->TokenLineNum > *LineNum) { + *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum; + return LineDef->FileName; + } + } else { + // + // Last one in the list of line definitions, so has to be right + // + *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum; + return LineDef->FileName; + } + } + } + return NULL; +} + +>> + +// +// Define a lexical class for parsing quoted strings. Basically +// starts with a double quote, and ends with a double quote that +// is not preceeded with a backslash. +// +#lexclass QUOTED_STRING +#token TheString "~[\"]*\"" << mode (START); >> + +// +// Define a lexical class for parsing "#pragma pack" statements. +// We do this just for convenience (since we skip them here) so +// that users can include some minimal .h files. +// +#lexclass PRAGMA_PACK +#token "pack" << skip (); >> +#token "[\ \t]" << skip (); >> +#token "\(" << skip (); >> +#token "[0-9]*" << skip (); >> +#token "\)" << skip (); mode (START); >> + +// +// Define a lexclass for skipping over C++ style comments +// +#lexclass CPP_COMMENT +#token "~[\n]*" << skip (); >> +#token "\n" << skip (); mode (START); newline (); >> + +// +// Standard lexclass is START +// +#lexclass START + +// +// Find start of C++ style comments +// +#token "//" << skip (); mode (CPP_COMMENT); >> + +// +// Skip whitespace +// +#token "[\ \t]" << skip (); >> + +// +// Skip over newlines, but count them +// +#token "\n" << skip (); newline (); >> + +// +// Skip pragma pack statements +// +#token "\#pragma" << skip (); mode(PRAGMA_PACK); >> + +// +// Skip over 'extern' in any included .H file +// +#token "extern" << skip (); >> + +// +// Tokens for the different keywords. Syntax is: +// TokenName("ErrorMessageText") "TokenString" +// where: +// TokenName is the token name (must be capitalized) that is used in the rules +// ErrorMessageText is the string the compiler emits when it detects a syntax error +// TokenString is the actual matching string used in the user script +// +#token LineDefinition "#line\ [0-9]+\ \"~[\"]+\"[\ \t]*\n" << AddFileLine (begexpr (), line ()); skip (); >> +#token FormSet("formset") "formset" +#token EndFormSet("endformset") "endformset" +#token Title("title") "title" +#token FormId("formid") "formid" +#token OneOf("oneof") "oneof" +#token Prompt("prompt") "prompt" +#token OrderedList("orderedlist") "orderedlist" +#token EndList("endlist") "endlist" +#token EndForm("endform") "endform" +#token EndOneOf("endoneof") "endoneof" +#token Form("form") "form" +#token Subtitle("subtitle") "subtitle" +#token Help("help") "help" +#token VarId("varid") "varid" +#token Text("text") "text" +#token Option("option") "option" +#token Value("value") "value" +#token Flags("flags") "flags" +#token Date("date") "date" +#token EndDate("enddate") "enddate" +#token Year("year") "year" +#token Month("month") "month" +#token Day("day") "day" +#token Time("time") "time" +#token EndTime("endtime") "endtime" +#token Hour("hour") "hour" +#token Minute("minute") "minute" +#token Second("second") "second" +#token AND("AND") "AND" +#token OR("OR") "OR" +#token GrayOutIf("grayoutif") "grayoutif" +#token NOT("NOT") "NOT" +#token Label("label") "label" +#token Timeout("timeout") "timeout" +#token Inventory("inventory") "inventory" +#token StringToken("STRING_TOKEN") "STRING_TOKEN" +#token NonNvDataMap("_NON_NV_DATA_MAP") "_NON_NV_DATA_MAP" +#token Struct("struct") "struct" +#token Uint64("UINT64") "UINT64" +#token Uint32("UINT32") "UINT32" +#token Uint16("UINT16") "UINT16" +#token Char16("CHAR16") "CHAR16" +#token Uint8("UINT8") "UINT8" +#token Guid("guid") "guid" +#token CheckBox("checkbox") "checkbox" +#token EndCheckBox("endcheckbox") "endcheckbox" +#token Numeric("numeric") "numeric" +#token EndNumeric("endnumeric") "endnumeric" +#token Minimum("minimum") "minimum" +#token Maximum("maximum") "maximum" +#token Step("step") "step" +#token Default("default") "default" +#token Password("password") "password" +#token EndPassword("endpassword") "endpassword" +#token String("string") "string" +#token EndString("endstring") "endstring" +#token MinSize("minsize") "minsize" +#token MaxSize("maxsize") "maxsize" +#token Encoding("encoding") "encoding" +#token SuppressIf("suppressif") "suppressif" +#token Hidden("hidden") "hidden" +#token Goto("goto") "goto" +#token InconsistentIf "inconsistentif" +#token EndIf("endif") "endif" +#token IdEqId("ideqid") "ideqid" +#token IdEqVal("ideqval") "ideqval" +#token VarEqVal("vareqval") "vareqval" +#token Var("var") "var" +#token IdEqValList("ideqvallist") "ideqvallist" +#token Length("length") "length" +#token Values("values") "values" +#token Key("key") "key" +#token DefaultFlag("DEFAULT") "DEFAULT" +#token ManufacturingFlag("MANUFACTURING") "MANUFACTURING" +#token InteractiveFlag("INTERACTIVE") "INTERACTIVE" +#token NVAccessFlag("NV_ACCESS") "NV_ACCESS" +#token ResetRequiredFlag("RESET_REQUIRED") "RESET_REQUIRED" +#token LateCheckFlag("LATE_CHECK") "LATE_CHECK" +#token Class("class") "class" +#token Subclass("subclass") "subclass" +#token TypeDef("typedef") "typedef" +#token Restore("restore") "restore" +#token Save("save") "save" +#token Defaults("defaults") "defaults" +#token Banner("banner") "banner" +#token Align("align") "align" +#token Left("left") "left" +#token Right("right") "right" +#token Center("center") "center" +#token Line("line") "line" +#token VarStore("varstore") "varstore" +#token Name("name") "name" +#token Oem("oem") "oem" +#token True("TRUE") "TRUE" +#token False("FALSE") "FALSE" +#token GreaterThan(">") ">" +#token GreaterEqual(">=") ">=" +#token LessThan("<") "<" +#token LessEqual("<=") "<=" + +// +// Define the class and subclass tokens +// +#token ClassNonDevice("NONDEVICE") "NON_DEVICE" +#token ClassDiskDevice("DISK_DEVICE") "DISK_DEVICE" +#token ClassVideoDevice("VIDEO_DEVICE") "VIDEO_DEVICE" +#token ClassNetworkDevice("NETWORK_DEVICE") "NETWORK_DEVICE" +#token ClassInputDevice("INPUT_DEVICE") "INPUT_DEVICE" +#token ClassOnBoardDevice("ONBOARD_DEVICE") "ONBOARD_DEVICE" +#token ClassOtherDevice("OTHER_DEVICE") "OTHER_DEVICE" + +#token SubclassSetupApplication("SETUP_APPLICATION") "SETUP_APPLICATION" +#token SubclassGeneralApplication("GENERAL_APPLICATION") "GENERAL_APPLICATION" +#token SubclassFrontPage("FRONT_PAGE") "FRONT_PAGE" +#token SubclassSingleUse("SINGLE_USE") "SINGLE_USE" + +#token LanguageIdentifier("language identifier") "[a-z][a-z][a-z]" // 3 lowercase characters +#token StringIdentifier("string identifier") "[A-Za-z_][A-Za-z_0-9]*" +#token Number("numeric value") "(0x[0-9A-Fa-f]+) | [0-9]+" +#token OpenBrace("{") "\{" +#token CloseBrace("}") "\}" +#token OpenParen("(") "\(" +#token CloseParen(")") "\)" +#token OpenBracket("[") "\[" +#token CloseBracket("]") "\]" + +// +// Define all other invalid characters so that they get through the lexical phase +// and we can catch them during the parse phase. We get much better error +// messages then. +// +#token InvalidCharacters("invalid characters") "~[;:=,\.\|]" + +// +// This is the overall definition of a VFR form definition script. +// +program : + ( dataStructDefinition )* + formSetStatement + ( vfrStatementVarStore )* + ( formDefinition )* + EFS:EndFormSet ";" << WriteOpByte (EFS->getLine(), EFI_IFR_END_FORM_SET_OP); >> + "@" // end of file + ; + +formSetStatement : + FS:FormSet << WriteOpByte (FS->getLine(), EFI_IFR_FORM_SET_OP); >> + Guid "=" + OpenBrace + G1:Number "," + G2:Number "," + G3:Number "," + OpenBrace + G4:Number "," + G5:Number "," + G6:Number "," + G7:Number "," + G8:Number "," + G9:Number "," + G10:Number "," + G11:Number + CloseBrace + CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (), + G4->getText (), G5->getText (), G6->getText (), G7->getText (), + G8->getText (), G9->getText (), G10->getText (), G11->getText () + ); + >> + "," + Title "=" getStringId "," + Help "=" getStringId "," + // + // insert padding for an EFI_PHYSICAL_ADDRESS (UINT64) + // + << WriteDWord (0, 0); WriteDWord (0, 0); >> + Class "=" CVAL:classDefinition "," << WriteClass (); >> + Subclass "=" SVAL:subclassDefinition "," << WriteSubclass (); >> + << WriteWord (mNvDataStructSize); >> + ; + +// +// A form can be of multiple classes, thus allow CLASS_A | CLASS_B | CLASS_C +// +classDefinition : + validClassNames ( "\|" validClassNames )* + ; + +validClassNames : + CND:ClassNonDevice << SetClass (CND->getLine(), EFI_NON_DEVICE_CLASS); >> + | CDD:ClassDiskDevice << SetClass (CDD->getLine(), EFI_DISK_DEVICE_CLASS); >> + | CVD:ClassVideoDevice << SetClass (CVD->getLine(), EFI_VIDEO_DEVICE_CLASS); >> + | CNW:ClassNetworkDevice << SetClass (CNW->getLine(), EFI_NETWORK_DEVICE_CLASS); >> + | CID:ClassInputDevice << SetClass (CID->getLine(), EFI_INPUT_DEVICE_CLASS); >> + | COB:ClassOnBoardDevice << SetClass (COB->getLine(), EFI_ON_BOARD_DEVICE_CLASS); >> + | COD:ClassOtherDevice << SetClass (COD->getLine(), EFI_OTHER_DEVICE_CLASS); >> + | CNUM:Number << SetClass (CNUM->getLine(), GetNumber (CNUM->getText(), CNUM->getLine(), 4)); >> + ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid class"); >> + +// +// A form can only be of one subclass type. +// +subclassDefinition : + SSA:SubclassSetupApplication << SetSubclass (SSA->getLine(), EFI_SETUP_APPLICATION_SUBCLASS); >> + | SGA:SubclassGeneralApplication << SetSubclass (SGA->getLine(), EFI_GENERAL_APPLICATION_SUBCLASS); >> + | SFP:SubclassFrontPage << SetSubclass (SFP->getLine(), EFI_FRONT_PAGE_SUBCLASS); >> + | SSU:SubclassSingleUse << SetSubclass (SSU->getLine(), EFI_SINGLE_USE_SUBCLASS); >> + | SNUM:Number << SetSubclass (SNUM->getLine(), GetNumber (SNUM->getText(), SNUM->getLine(), 4)); >> + ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid subclass"); >> + +// +// Parse a C type data structure for storing VFR setup data. Allow: +// typedef struct _XXX_ { +// (fields) +// } MY_NV_DATA; +// +dataStructDefinition : + << int IsNonNV = 0; >> + { TypeDef } + S:Struct + ( + NonNvDataMap << IsNonNV = 1; >> + | + { StringIdentifier } + ) << StartStructDefinition (IsNonNV, S->getLine()); >> + OpenBrace + dataStructFields + CloseBrace NAME:StringIdentifier << EndStructDefinition (NAME->getText(), NAME->getLine()); >> + ";" + ; + +// +// Parse a C type data structure for defining data that is not stored in NV. +// typedef struct _NON_NV_DATA_MAP { +// (fields) +// } NON_NV_DATA_MAP; +// +nonNvDataStructDefinition : + { TypeDef } + Struct NonNvDataMap + { StringIdentifier } + OpenBrace + dataStructFields + CloseBrace NAME:StringIdentifier << AddStructField (NAME->getText(), NAME->getLine(), 0, 0, 0); >> + ";" + ; + +dataStructFields : + ( dataStructField64 | dataStructField32 | dataStructField16 | dataStructField8 ) * + ; + +//***************************************************************************** +// +// PARSE: +// UINT64 Name[4]; +// UINT64 Name; +// +// Used while parsing the NV data map structures. +// +dataStructField64 : + << int ArrayLength = 1; char IsArray = 0; >> + "UINT64" + NAME:StringIdentifier + ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) + << AddStructField (NAME->getText(), NAME->getLine(), 8, ArrayLength, IsArray); >> + ; + +//***************************************************************************** +// +// PARSE: +// UINT32 Name[4]; +// UINT32 Name; +// +// Used while parsing the NV data map structures. +// +dataStructField32 : + << int ArrayLength = 1; char IsArray = 0; >> + "UINT32" + NAME:StringIdentifier + ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) + << AddStructField (NAME->getText(), NAME->getLine(), 4, ArrayLength, IsArray); >> + ; + +//***************************************************************************** +// +// PARSE: +// UINT16 Name[4]; +// UINT16 Name; +// +// Used while parsing the NV data map structures. +// +dataStructField16 : + << int ArrayLength = 1; char IsArray = 0; >> + ( "UINT16" | "CHAR16" ) + NAME:StringIdentifier + ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) + << AddStructField (NAME->getText(), NAME->getLine(), 2, ArrayLength, IsArray); >> + ; + +//***************************************************************************** +// +// PARSE: +// UINT8 Name[4]; +// UINT8 Name; +// +// Used while parsing the NV data map structures. +// +dataStructField8 : + << int ArrayLength = 1; char IsArray = 0; >> + "UINT8" + NAME:StringIdentifier + ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) + << AddStructField (NAME->getText(), NAME->getLine(), 1, ArrayLength, IsArray); >> + ; + +//***************************************************************************** +// +// PARSE: +// form formid = 1, +// title = STRING_TOKEN(STR_FORM_TITLE); +// -- form statements -- +// endform; +// +// The Form ID cannot be 0 +// +formDefinition : + FRM:Form FormId << WriteOpByte (FRM->getLine(), EFI_IFR_FORM_OP); >> + "=" + VAL:Number << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); AddFormId (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); >> + "," + Title "=" getStringId ";" // writes string identifier + ( vfrStatements )* + ENDF:EndForm ";" << WriteOpByte (ENDF->getLine(), EFI_IFR_END_FORM_OP); >> + ; + +// +// VFR statements in a formset +// +vfrStatements : + vfrStatementSubTitle | + vfrStatementOneOf | + vfrStatementTextText | + vfrStatementCheckBox | + vfrStatementNumeric | + vfrStatementDate | + vfrStatementTime | + vfrStatementPassword | + vfrStatementString | + vfrStatementSuppressIf | + vfrStatementHidden | + vfrStatementGoto | + vfrStatementGrayOutIf | + vfrStatementInconsistentIf | + vfrStatementLabel | + vfrStatementBanner | + vfrStatementInventory | + vfrStatementOrderedList | + vfrStatementOem | + vfrStatementSaveRestoreDefaults + ; + +//***************************************************************************** +// +// PARSE: +// label 100; +// +vfrStatementLabel : + OPID:Label << WriteOpByte (OPID->getLine(), EFI_IFR_LABEL_OP); >> + VAL:Number << + WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); + AddLabel (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); + >> + ";" + ; + +//***************************************************************************** +// +// PARSE: +// oem 0x12, 0x34, 0x56; +// +vfrStatementOem : + OPID:Oem << WriteOpByte (OPID->getLine(), EFI_IFR_OEM_DEFINED_OP); >> + ( VAL1:Number << WriteByte (GetNumber (VAL1->getText(), VAL1->getLine(), 1), 0); >> ) + ( "," VAL2:Number << WriteByte (GetNumber (VAL2->getText(), VAL2->getLine(), 1), 0); >> )* + ";" + ; + +//***************************************************************************** +// +// PARSE: +// inconsistentif NOT .... AND NOT .... OR ... endif; +// +vfrStatementInconsistentIf : + << ResetFlags (); >> + IIFOP:InconsistentIf << WriteOpByte (IIFOP->getLine(), EFI_IFR_INCONSISTENT_IF_OP); >> + Prompt "=" getStringId "," + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + EOP:EndIf ";" << WriteOpByte (EOP->getLine(), EFI_IFR_END_IF_OP); >> + ; + +//***************************************************************************** +// +// PARSE: +// TRUE AND (ideqval SomeStruct.SomeMember >= 0x10 OR +// ideqid SomeStruct.SomeMember < SomeStruct.SomeOtherMember) AND +// (ideqlist SomeStruct.SomeOtherMember == 0x10, 0x20, 0x30 OR +// vareqval var(VAR_EQ_TEST_NAME) == 0x1) +// +// For supporting complex express, divide the vfrBooleanExpression to two parts +// so that pred-LL(k) parser can parse incrementally. +// +vfrBooleanExpression : + leftPartVfrBooleanExp { rightPartVfrBooleanExp } + ; + +leftPartVfrBooleanExp : + OpenParen vfrBooleanExpression CloseParen | + (ideqval | ideqid | ideqvallist | vareqval | truefalse) | + NOPID:NOT leftPartVfrBooleanExp << WriteOpByte (NOPID->getLine(), EFI_IFR_NOT_OP); >> + ; + +rightPartVfrBooleanExp : + AOPID:AND vfrBooleanExpression << WriteOpByte (AOPID->getLine(), EFI_IFR_AND_OP); >> | + OOPID:OR vfrBooleanExpression << WriteOpByte (OOPID->getLine(), EFI_IFR_OR_OP); >> + ; + +//***************************************************************************** +// +// PARSE: +// TRUE +// +truefalse : + TOPID:True << WriteOpByte (TOPID->getLine(), EFI_IFR_TRUE_OP); >> | + FOPID:False << WriteOpByte (FOPID->getLine(), EFI_IFR_FALSE_OP); >> + ; + +//***************************************************************************** +// +// PARSE: +// varstore MY_STRUCT_NAME, key = 0x1234, name = "MyVariableName", guid = {...}; +// +vfrStatementVarStore : + OP:VarStore << WriteOpByte (OP->getLine(), EFI_IFR_VARSTORE_OP); >> + STRUCT_NAME:StringIdentifier "," + Key "=" KNUM:Number "," + Name "=" VAR_NAME:StringIdentifier "," + Guid "=" + OpenBrace + G1:Number "," + G2:Number "," + G3:Number "," + OpenBrace + G4:Number "," + G5:Number "," + G6:Number "," + G7:Number "," + G8:Number "," + G9:Number "," + G10:Number "," + G11:Number + CloseBrace + CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (), + G4->getText (), G5->getText (), G6->getText (), G7->getText (), + G8->getText (), G9->getText (), G10->getText (), G11->getText () + ); + WriteWord (GetNumber (KNUM->getText(), KNUM->getLine(), 2)); + AddVarStore (STRUCT_NAME->getText(), VAR_NAME->getText(), GetNumber (KNUM->getText(), KNUM->getLine(), 2), STRUCT_NAME->getLine()); + >> + + ";" + ; + +//***************************************************************************** +// +// PARSE: +// vareqval var(0x100) == 0x20 +// +vareqval : + OPID:VarEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_VAR_VAL_OP); >> + Var OpenParen + VAR:Number << WriteWord (GetNumber (VAR->getText(), VAR->getLine(), 2)); >> + CloseParen + compareNumber + ; + +ideqval : + OPID:IdEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_VAL_OP); >> + vfrStructFieldName[0] + compareNumber + ; + +//***************************************************************************** +// +// PARSE: +// ideqid MyNVData3.Field16A == MyNVData3.Field16B +// +// NOTE: Before processing the second variable store in the ideqid statement, set a global flag +// so that when we parse the second variable we set the secondary variable store id. +// +ideqid : + OPID:IdEqId << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_ID_OP); >> + vfrStructFieldName[0] + compareVfrStructFieldNameNL0 + ; + +//***************************************************************************** +// +// compareNumber is the combination of compare operation and Number +// +compareNumber : + ( + "==" + VAL1:Number << WriteWord (GetNumber (VAL1->getText(), VAL1->getLine(), 2)); >> + ) | + ( + GTOPID:GreaterThan + VAL2:Number << WriteWord (GetNumber (VAL2->getText(), VAL2->getLine(), 2)); + WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >> + ) | + ( + GEOPID:GreaterEqual + VAL3:Number << WriteWord (GetNumber (VAL3->getText(), VAL3->getLine(), 2)); + WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >> + ) | + ( + LTOPID:LessThan + VAL4:Number << WriteWord (GetNumber (VAL4->getText(), VAL4->getLine(), 2)); + WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP); + WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >> + ) | + ( + LEOPID:LessEqual + VAL5:Number << WriteWord (GetNumber (VAL5->getText(), VAL5->getLine(), 2)); + WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP); + WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >> + ) + ; + +//***************************************************************************** +// +// compareVfrStructFieldNameNL0 is the combination of compare operation and vfrStructFieldNameNL[0] +// +compareVfrStructFieldNameNL0 : + ( + "==" << mIdEqIdStmt = 1; >> + vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; >> + ) | + ( + GTOPID:GreaterThan << mIdEqIdStmt = 1; >> + vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; + WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >> + ) | + ( + GEOPID:GreaterEqual << mIdEqIdStmt = 1; >> + vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; + WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >> + ) | + ( + LTOPID:LessThan << mIdEqIdStmt = 1; >> + vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; + WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP); + WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >> + ) | + ( + LEOPID:LessEqual << mIdEqIdStmt = 1; >> + vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; + WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP); + WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >> + ) + ; + + +ideqvallist : + OPID:IdEqValList << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_LIST_OP); >> + vfrStructFieldName[0] + "==" + ( VAL:Number << QueueIdEqValList (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> ) + + << FlushQueueIdEqValList(); >> + ; + +vfrStatementGoto : + << UINT32 LineNum, KeyValue = 0; ResetFlags (); >> + IDG:Goto << WriteOpByte (IDG->getLine(), EFI_IFR_REF_OP); >> + VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); + AddGotoReference (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); + >> + KP:Prompt "=" getStringId "," << LineNum = KP->getLine(); >> + Help "=" getStringId + { + "," + FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >> + } + { + "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + ";" + ; + +vfrStatementHidden : + IDH:Hidden << WriteOpByte (IDH->getLine(), EFI_IFR_HIDDEN_OP); >> + Value "=" + VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> + Key "=" + KVAL:Number << WriteWord (GetNumber (KVAL->getText(), KVAL->getLine(), 2)); >> + ";" + ; + +//***************************************************************************** +// +// PARSE: +// suppressif { grayoutif } + endif; +// Note: +// You can have: suppressif:grayoutif:statements:endif +// suppressif:grayoutif:endif -- serves no purpose +// suppressif:statements:endif +// suppressif:endif -- serves no purpose +// +vfrStatementSuppressIf : + << ResetFlags (); >> + OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + { suppressIfGrayOutIf } ( suppressIfAndGrayoutIfSubstatements )+ + ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >> + ; + +// +// This is the form for a grayoutif nested in a suppressif statement +// +suppressIfGrayOutIf : + << ResetFlags (); >> + OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + ; + +//***************************************************************************** +// +// PARSE: +// grayoutif { flags = n, } endif; +// Note: +// You can have: grayoutif:suppressif:statements:endif +// grayoutif:statements:endif +// +// +vfrStatementGrayOutIf : + << ResetFlags (); >> + OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + { grayoutIfSuppressIf } ( suppressIfAndGrayoutIfSubstatements )+ + ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >> + ; + +// +// This is the format for a suppressif nested in a grayoutif +// +grayoutIfSuppressIf : + << ResetFlags (); >> + OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + ; + +// +// These are the VFR statements that are valid inside a suppressif or grayoutif statement. +// +suppressIfAndGrayoutIfSubstatements : + vfrStatementOneOf | + vfrStatementTextText | + vfrStatementCheckBox | + vfrStatementNumeric | + vfrStatementDate | + vfrStatementTime | + vfrStatementPassword | + vfrStatementString | + vfrStatementHidden | + vfrStatementGoto | + vfrStatementLabel | + vfrStatementInventory | + vfrStatementOrderedList | + vfrStatementSaveRestoreDefaults + ; + +//***************************************************************************** +// +// PARSE: +// +// password varid = MyNvData.Password, +// prompt = STRING_TOKEN(STR_PASSWORD_PROMPT), +// help = STRING_TOKEN(STR_PASSWORD_HELP), +// minsize = 6, +// maxsize = 20, +// encoding = 1, +// endpassword; + +vfrStatementPassword : + << UINT32 KeyValue = 0; UINT32 LineNum; ResetFlags (); >> + IDPW:Password << WriteOpByte (IDPW->getLine(), EFI_IFR_PASSWORD_OP); >> + VarId "=" vfrStructFieldNameArray[0] "," + Prompt "=" getStringId "," + KH:Help "=" getStringId "," << LineNum = KH->getLine(); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >> + } + { + Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >> + MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >> + Encoding "=" ENC:Number "," << WriteWord (GetNumber (ENC->getText(), ENC->getLine(), 2)); >> + EndPassword ";" + ; + +//***************************************************************************** +// +// PARSE: +// +// string varid = MyNv.String, +// prompt = STRING_TOKEN(STR_STRING_PROMPT), +// help = STRING_TOKEN(STR_STRING_HELP), +// flags = INTERACTIVE, +// key = 0x1234, +// minsize = 6, +// maxsize = 0x14, +// endstring; +// +// Since flags and key are optional, we can't use Flags->getLine(). Therefore for error +// reporting we save the line number of the "help" keyword. +// +vfrStatementString : + << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >> + IDS:String << WriteOpByte (IDS->getLine(), EFI_IFR_STRING_OP); >> + VarId "=" vfrStructFieldNameArray[0] "," + Prompt "=" getStringId "," + KH:Help "=" getStringId "," << LineNum = KH->getLine(); >> + { + FF:Flags "=" + flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >> + "," + } + { + Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >> + MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >> + EndString ";" + ; + +//***************************************************************************** +// +// PARSE: +// numeric varid = MyIfrNVData.HowOldAreYouInYears, +// prompt = STRING_TOKEN(STR_NUMERIC_PROMPT), +// help = STRING_TOKEN(STR_NUMERIC_HELP), +// flags = INTERACTIVE, // flags is optional +// key = 0x1234, // key is optional if (flags & INTERACTIVE = 0) +// minimum = 0x0, +// maximum = 0xf0, +// step = 1, // step is option, and step=1 if not specified +// default = 0; // default is optional, and default=minimum if not specified +// endnumeric; +// +// Make flags and key optional. However if flags includes INTERACTIVE, then a key is required. +// That check is done in WriteFlagsKey() function. +// +vfrStatementNumeric : + << UINT32 LineNum, KeyValue = 0; ResetFlags (); >> + IDN:Numeric << WriteOpByte (IDN->getLine(), EFI_IFR_NUMERIC_OP); >> + VarId "=" vfrStructFieldName[2] "," + Prompt "=" getStringId "," + KH:Help "=" getStringId "," << LineNum = KH->getLine(); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine (); >> + } + { + Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + minMaxStepDefault + EndNumeric ";" << WriteMinMaxStepDefault (); >> + ; + +// +// Parse minimum/maximum/step/default statements. Special cases: +// - if step not specified, then the value is 1 +// - if default not specified, then the value is the min value specified +// - if max < min, print a warning and swap the values (changes default too) +// +minMaxStepDefault : + << InitMinMaxStepDefault (); >> + Minimum "=" MIN:Number "," << SetMinMaxStepDefault (GetNumber (MIN->getText(), MIN->getLine(), 2), 0, MIN->getLine()); >> + Maximum "=" MAX:Number "," << SetMinMaxStepDefault (GetNumber (MAX->getText(), MAX->getLine(), 2), 1, MAX->getLine()); >> + { Step "=" STEP:Number "," << SetMinMaxStepDefault (GetNumber (STEP->getText(), STEP->getLine(), 2), 2, STEP->getLine()); >> } + { Default "=" DEF:Number "," << SetMinMaxStepDefault (GetNumber (DEF->getText(), DEF->getLine(), 2), 3, DEF->getLine()); >> } + ; + + +//***************************************************************************** +// +// PARSE: +// +// date year varid = Date.Year, // "Date.Year" is a special case we recognize +// prompt = STRING_TOKEN(STR_DATE_PROMPT), +// help = STRING_TOKEN(STR_DATE_YEAR_HELP), +// minimum = 1939, +// maximum = 2101, +// step = 1, +// default = 1964, +// +// month varid = Date.Month, +// prompt = STRING_TOKEN(STR_DATE_PROMPT), +// help = STRING_TOKEN(STR_DATE_MONTH_HELP), +// minimum = 1, +// maximum = 12, +// step = 1, +// default = 1, +// +// day varid = Date.Day, +// prompt = STRING_TOKEN(STR_DATE_PROMPT), +// help = STRING_TOKEN(STR_DATE_DAY_HELP), +// minimum = 1, +// maximum = 31, +// step = 0x1, +// default = 1, +// +// enddate; +// +vfrStatementDate : + Date + IDY:Year VarId "=" << WriteOpByte (IDY->getLine(), EFI_IFR_DATE_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + IDM:Month VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_DATE_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + IDD:Day VarId "=" << WriteOpByte (IDD->getLine(), EFI_IFR_DATE_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + EndDate ";" + ; + +vfrStatementTime : + Time + IDH:Hour VarId "=" << WriteOpByte (IDH->getLine(), EFI_IFR_TIME_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + IDM:Minute VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_TIME_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + IDS:Second VarId "=" << WriteOpByte (IDS->getLine(), EFI_IFR_TIME_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + EndTime ";" + ; + +//***************************************************************************** +// +// PARSE: +// +// text text = STRING_ID; +// text text = STRING_ID, text = STRING_ID; +// text text = STRING_ID, text = STRING_ID, flags = x, key = y; +// +vfrStatementTextText : + << ResetFlags (); >> + IDT:Text << WriteOpByte (IDT->getLine(), EFI_IFR_TEXT_OP); >> + Help "=" getStringId "," + Text "=" + getStringId // writes string identifier + { "," Text "=" getStringId + "," Flags "=" flagsField ( "\|" flagsField )* << WriteFlags (); >> + "," + Key "=" KNUM:Number << WriteWord (GetNumber(KNUM->getText(), KNUM->getLine(), 2)); >> + } + ";" + ; + +//***************************************************************************** +// +// PARSE: +// +// inventory help = ID, text = ID; +// inventory help = ID, text = id, text = ID; +// +vfrStatementInventory : + IDI:Inventory << WriteOpByte (IDI->getLine(), EFI_IFR_INVENTORY_OP); >> + Help "=" getStringId "," + Text "=" getStringId // writes string identifier + { "," Text "=" getStringId + } + ";" + ; + +//***************************************************************************** +// +// PARSE: +// +// restore defaults, +// formid = 4, +// prompt = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT), +// help = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP), +// flags = 0, +// key = 0; +// +// save defaults, +// formid = 4, +// prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT), +// help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP), +// flags = 0, +// key = 0; +// +vfrStatementSaveRestoreDefaults : + << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >> + ( IDS:Save << WriteOpByte (IDS->getLine(), EFI_IFR_SAVE_DEFAULTS_OP); >> + | IDR:Restore << WriteOpByte (IDR->getLine(), EFI_IFR_RESTORE_DEFAULTS_OP); >> + ) + Defaults "," + FormId "=" FRMID:Number "," << WriteWord (GetNumber (FRMID->getText(), FRMID->getLine(), 2)); + AddGotoReference (GetNumber (FRMID->getText(), FRMID->getLine(), 2), FRMID->getLine()); + >> + Prompt "=" getStringId "," + KH:Help "=" getStringId << LineNum = KH->getLine(); >> + { + "," FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >> + } + { + "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + ";" + ; + +//***************************************************************************** +// +// PARSE: +// +// flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK +// +// +flagsField : + VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >> + | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >> + | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >> + | DF:DefaultFlag << SetFlags (EFI_IFR_FLAG_DEFAULT, DF->getLine()); >> + | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >> + | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >> + | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >> + ; + +dateTimeSubStatement : + Prompt "=" getStringId "," + Help "=" getStringId "," + << WriteByte (0, 0); WriteWord (0); >> // bogus flags and key + minMaxStepDefault << WriteMinMaxStepDefault (); >> + ; + +vfrStatementCheckBox : + << UINT32 LineNum, KeyValue = 0; ResetFlags (); >> + IDCB:CheckBox << WriteOpByte (IDCB->getLine(), EFI_IFR_CHECKBOX_OP); >> + VarId "=" vfrStructFieldName[1] "," + Prompt "=" getStringId "," + Help "=" getStringId "," + FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >> + { + Key "=" KV:Number "," << LineNum = KV->getLine(); KeyValue = GetNumber(KV->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + EndCheckBox ";" + ; + +vfrStatementSubTitle : + IDS:Subtitle Text "=" << WriteOpByte (IDS->getLine(), EFI_IFR_SUBTITLE_OP); >> + getStringId // writes string indentifier + ";" + ; + +//***************************************************************************** +// +// PARSE: +// banner +// title = STRING_TOKEN(STR_BANNER_TITLE), +// line 1, +// align center; // or left or right +// +// banner, +// title = STRING_TOKEN(STR_BANNER_TITLE), timeout = 100; +// +vfrStatementBanner : + IDB:Banner { "," } << WriteOpByte (IDB->getLine(), EFI_IFR_BANNER_OP); >> + Title "=" getStringId "," + ( + Line VAL:Number "," << WriteWord (GetNumber(VAL->getText(), VAL->getLine(), 2)); >> + Align + ( Left << WriteByte (EFI_IFR_BANNER_ALIGN_LEFT, 0); >> + | Center << WriteByte (EFI_IFR_BANNER_ALIGN_CENTER, 0); >> + | Right << WriteByte (EFI_IFR_BANNER_ALIGN_RIGHT, 0); >> + ) ";" + | + Timeout "=" TO:Number ";" << WriteWord (GetNumber(TO->getText(), TO->getLine(), 2)); >> + << WriteByte (EFI_IFR_BANNER_TIMEOUT, 0); >> + ) + ; + +//***************************************************************************** +// +// PARSE: +// oneof varid = MyNv.OneOfData, +// prompt = STRING_TOKEN(STR_ONE_OF_PROMPT), +// help = STRING_TOKEN(STR_ONE_OF_HELP), +// option text = STRING_TOKEN(STR_ONE_OF_TEXT), +// value = 0, +// flags = DEFAULT | INTERACTIVE; +// +// supressif/grayoutif are supported inside oneof stmt. +// We do not restrict the number of oneOfOptionText to >=2, but >=1. +// The situation that all oneOfOptionText are suppressed is also possiable. +// +vfrStatementOneOf : + << ResetFlags (); >> + IDOO:OneOf << WriteOpByte (IDOO->getLine(), EFI_IFR_ONE_OF_OP); >> + VarId "=" vfrStructFieldName[2] "," + Prompt "=" getStringId "," // writes string identifier + Help "=" getStringId "," // writes string identifier + ( oneOfOptionText )+ // there must be at least 1 option to be choosed, not 2. + IDEOO:EndOneOf ";" << TestOneOfFlags (IDEOO->getLine()); WriteOpByte (IDEOO->getLine(), EFI_IFR_END_ONE_OF_OP); >> + ; + +//***************************************************************************** +// +// PARSE: +// +// orderedlist varid = MyNv.OrderedListData, +// prompt = STRING_TOKEN(STR_ORDERED_LIST_PROMPT), +// help = STRING_TOKEN(STR_ORDERED_LIST_HELP), +// option text = STRING_TOKEN(STR_ORDERED_LIST_TEXT), value = 0, flags = INTERACTIVE; +// -- additional option text -- +// endlist; +// +vfrStatementOrderedList : + << ResetFlags (); InitOrderedList(); >> + IDOL:OrderedList << WriteOpByte (IDOL->getLine(), EFI_IFR_ORDERED_LIST_OP); >> + VarId "=" vfrStructFieldNameArray[1] "," + Prompt "=" getStringId "," // writes string identifier + Help "=" getStringId "," // writes string identifier + orderedListOptionText ( orderedListOptionText )+ + IDEOL:EndList ";" << WriteOpByte (IDEOL->getLine(), EFI_IFR_END_OP); EndOrderedList(IDEOL->getLine()); >> + ; + +//***************************************************************************** +// +// PARSE: +// +// option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99; +// +// Differs from the oneOfOptionText in that we don't allow the DEFAULT flag to +// be set, and value cannot be 0. +// +orderedListOptionText : + << UINT32 KeyValue = 0; >> + IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >> + Text "=" getStringId "," // writes string identifier + Value "=" WVAL:Number "," << + if (GetNumber(WVAL->getText(), WVAL->getLine(), 2) == 0) { + PrintErrorMessage (WVAL->getLine(), "value=0 is invalid for ordered lists", NULL); + } else { + WriteWord (GetNumber(WVAL->getText(), WVAL->getLine(), 2)); + } + >> + FF:Flags "=" orderedListFlagsField + ("\|" orderedListFlagsField )* + { + "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >> + } + << WriteFlagsKey (KeyValue, FF->getLine()); >> + ";" << mOptionCount++; >> + ; + +//***************************************************************************** +// +// PARSE: +// +// flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK +// +// The ordered list flags field cannot have a default. +// +orderedListFlagsField : + VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >> + | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >> + | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >> + | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >> + | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >> + | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >> + | DF:DefaultFlag << PrintWarningMessage (DF->getLine(), "DEFAULT flag not valid for ordered lists", NULL); >> + ; + +// +// Parse references to VFR structure field names of form "MyNvStructure.Field". +// This implementation is specific to strings, passwords, and references in an +// ordered list statement because we want to specify the size of the entire +// field, rather than just one element. Then call a function to write out its +// offset and length. +// +vfrStructFieldNameArray[int FieldWidth] : + << int ArrayIndex = 1; char IsArrayIndex = 0; >> + SName:StringIdentifier + "." + SFieldName:StringIdentifier + { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> } + << + WriteFieldOffset (1, + SName->getText(), + SName->getLine(), + SFieldName->getText(), + SFieldName->getLine(), + ArrayIndex, + IsArrayIndex, + FieldWidth, + 1 + ); + >> + ; + +// +// Parse references to VFR structure field names of form "MyNvStructure.Field", +// then call a function to write out its offset and length. +// +vfrStructFieldName[int FieldWidth] : + << int ArrayIndex = 1; char IsArrayIndex = 0; >> + SName:StringIdentifier + "." + SFieldName:StringIdentifier + { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> } + << + WriteFieldOffset (1, + SName->getText(), + SName->getLine(), + SFieldName->getText(), + SFieldName->getLine(), + ArrayIndex, + IsArrayIndex, + FieldWidth, + 0 + ); + >> + ; + +//***************************************************************************** +// +// PARSE: +// +// MyNvStructure.FieldName[4] +// +// Parse references to VFR structure field names of form "MyNvStructure.Field", +// then call a function to write out the offset with no length. +// +vfrStructFieldNameNL[int FieldWidth] : + << int ArrayIndex = 1; char IsArrayIndex = 0; >> + SName:StringIdentifier + "." + SFieldName:StringIdentifier + { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> } + << + WriteFieldOffset (0, + SName->getText(), + SName->getLine(), + SFieldName->getText(), + SFieldName->getLine(), + ArrayIndex, + IsArrayIndex, + FieldWidth, + 0 + ); + >> + ; + +//***************************************************************************** +// +// PARSE: +// suppressif TRUE OR FALSE; +// grayoutif FALSE OR TRUE; +// option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99; +// option text = STRING_TOKEN(STRING_ID2), value = 1 flags = 98; +// endif; +// +oneOfOptionText : + suppressIfOptionText | + grayOutIfOptionText | + commonOptionText + ; + +suppressIfOptionText : + << ResetFlags (); >> + OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + { suppressIfGrayOutIf } ( commonOptionText )+ + ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >> + ; + +grayOutIfOptionText : + << ResetFlags (); >> + OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + { grayoutIfSuppressIf } ( commonOptionText )+ + ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >> + ; + +commonOptionText : + << UINT32 KeyValue = 0; >> + IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >> + Text "=" getStringId "," // writes string identifier + Value "=" WVal:Number "," << WriteWord (GetNumber(WVal->getText(), WVal->getLine(), 2)); >> + FF:Flags "=" flagsField ("\|" flagsField )* + { + "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >> + } + << WriteFlagsKey (KeyValue, FF->getLine()); >> + ";" << mOptionCount++; >> + ; + +// +// Gets a string identifier. It must be a numeric value of form: +// +// STRING_TOKEN(100) +// +getStringId : + << unsigned short StrId; >> + StringToken OpenParen + IdVal:Number << StrId = GetNumber (IdVal->getText(), IdVal->getLine(), 2); WriteStringIdWord (StrId); >> + CloseParen + ; + +//****************************************************************************** +// +// Parser class definition. +// +class EfiVfrParser { +<< +// +// Parser definitions go here +// +private: + STRUCT_DEFINITION *mFirstStructDefinition; + STRUCT_DEFINITION *mLastStructDefinition; + INT32 mNvDataStructSize; + INT32 mNonNvDataStructSize; + // + // Flag to indicate that we're processing a ideqid VFR statement so that + // we can do late checks on the statement. + // + INT32 mIdEqIdStmt; + INT32 mLastNVVariableDataSize; + GOTO_REFERENCE *mGotoReferences; + FORM_ID_VALUE *mFormIdValues; + VfrOpcodeHandler mOpcodeHandler; + UINT16_LIST *mUint16List; + UINT16_LIST *mLastUint16; + UINT16_LIST *mDefinedLabels; + UINT16_LIST *mDefinedVarStoreId; + UINT16_LIST *mLastDefinedVarStoreId; + UINT32 mMinimumValue, mMaximumValue, mStepValue, mDefaultValue; + UINT32 mStmtFlags; + UINT32 mSubStmtFlags; + UINT32 mSubStmtFlagsLineNum; + EFI_GUID mFormSetGuid; + UINT8 mNvDataStructDefined; + UINT16 mClass, mSubclass; + UINT32 mIfStart; + UINT32 mOptionCount; // how many "option" fields in a given statement + UINT32 mLastVarIdSize; + UINT8 mOutput; +public: + +VOID +EfiVfrParser::SetIfStart ( + UINT32 LineNum + ) +/*++ + +Routine Description: + Invoked during VFR parsing when an "if" is encountered. Save the + source line number so we can point to it if we don't find a + corresponding endif later. + +Arguments: + LineNum - source line number where the "if" was parsed. + +Returns: + None + +--*/ +{ + mIfStart = LineNum; +} +VOID +EfiVfrParser::SetClass ( + UINT32 LineNum, + UINT32 Value + ) +/*++ + +Routine Description: + Invoked during VFR parsing when a "class" statement is found. Check the + range on the class value and save it for later. + +Arguments: + LineNum - source line number where the class statement was parsed. + Value - the class value + +Returns: + None + +--*/ +{ + if (Value & 0xFFFF0000) { + PrintWarningMessage (LineNum, NULL, "class value exceeds maximum allowed"); + } + mClass |= (UINT16)Value; +} +VOID +EfiVfrParser::SetSubclass ( + UINT32 LineNum, + UINT32 Value + ) +/*++ + +Routine Description: + Invoked during VFR parsing when a subclass statement is found. Check the + range on the value and save it for later. + +Arguments: + LineNum - source line number where the class statement was parsed. + Value - the subclass value from the VFR statement + +Returns: + None + +--*/ +{ + if (Value & 0xFFFF0000) { + PrintWarningMessage (LineNum, NULL, "subclass value exceeds maximum allowed"); + } + mSubclass |= (UINT16)Value; +} +VOID EfiVfrParser::WriteClass () +{ + WriteWord (mClass); + mClass = 0; +} +VOID EfiVfrParser::WriteSubclass () +{ + WriteWord (mSubclass); + mSubclass = 0; +} +VOID EfiVfrParser::WriteIfrBytes () +{ + mOpcodeHandler.WriteIfrBytes (); +} +VOID +EfiVfrParser::WriteFlagsKey ( + UINT32 KeyValue, + UINT32 LineNum + ) +/*++ + +Routine Description: + Write out the flags and key values from the previous VFR statement. + Many statements take a flags/key pair. If not specified, then 0 + values are written out. However do not allow an interactive flags field + to be specified if no key value is specified. Also, if NV_ACCESS flag + is set but INTERACTIVE is not, then set interactive and issue a warning. + +Arguments: + KeyValue - the key value from the VFR statement + LineNum - source line number where the statement was parsed + +Returns: + None + +--*/ +{ + if ((mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE) && (KeyValue == 0)) { + PrintErrorMessage (LineNum, NULL, "invalid or missing key value - required with INTERACTIVE"); + } + if ((mSubStmtFlags & EFI_IFR_FLAG_NV_ACCESS) && !(mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE)) { + PrintWarningMessage (LineNum, NULL, "NV_ACCESS without INTERACTIVE has no effect -- setting INTERACTIVE"); + mSubStmtFlags |= EFI_IFR_FLAG_INTERACTIVE; + } + WriteFlags (); + WriteWord (KeyValue); +} +VOID +EfiVfrParser::InitOrderedList () +{ + mOptionCount = 0; +} +VOID +EfiVfrParser::EndOrderedList ( + UINT32 LineNum + ) +{ + if (mLastVarIdSize < mOptionCount) { + PrintErrorMessage (LineNum, NULL, "number of options exceeds the variable store size"); + } +} +VOID +EfiVfrParser::ResetFlags () +/*++ + +Routine Description: + + Flags are set for each substatement in a given one-of statement. + To make sure there are no conflicts, for example setting DEFAULT on + more than one substatement, we keep track of the flags at a statement + level and a substatement level. This function resets the flags so + we get a fresh start. + +Arguments: + None + +Returns: + None + +--*/ +{ + mStmtFlags = 0; + mSubStmtFlagsLineNum = 0; + mSubStmtFlags = 0; +} +// +// Test validity of flags value for a one-of statement. +// +VOID +EfiVfrParser::TestOneOfFlags ( + UINT32 LineNum + ) +{ + // + // One of the fields must have had the default bit set + // + if ((mStmtFlags & EFI_IFR_FLAG_DEFAULT) == 0) { + PrintWarningMessage (LineNum, "default value must be specified", NULL); + } +} +VOID +EfiVfrParser::SetFlags ( + UINT32 Flags, + UINT32 LineNum + ) +{ + // + // Check for redefinitions and invalid combinations + // + if (mStmtFlags & Flags & EFI_IFR_FLAG_MANUFACTURING) { + PrintErrorMessage (LineNum, "MANUFACTURING", "a field with this flag already defined"); + } + if (mStmtFlags & Flags & EFI_IFR_FLAG_DEFAULT) { + PrintErrorMessage (LineNum, "DEFAULT", "a field with this flag already defined"); + } + mSubStmtFlags |= Flags; + mSubStmtFlagsLineNum = LineNum; +} +VOID +EfiVfrParser::WriteFlags () +{ + // + // Check value for validity + // + if (mSubStmtFlags & ~(EFI_IFR_FLAG_DEFAULT | + EFI_IFR_FLAG_MANUFACTURING | + EFI_IFR_FLAG_INTERACTIVE | + EFI_IFR_FLAG_NV_ACCESS | + EFI_IFR_FLAG_RESET_REQUIRED | + EFI_IFR_FLAG_LATE_CHECK )) { + PrintWarningMessage (mSubStmtFlagsLineNum, "invalid bits defined in flag", NULL); + } + WriteByte ((UINT8)mSubStmtFlags, 'F'); + // + // We can now clear the substatement flags + // + mStmtFlags |= mSubStmtFlags; + mSubStmtFlags = 0; +} +// +// When we parse a min/max/step/default sequence, save off the values for +// later use. Call this first to init the values. +// +VOID +EfiVfrParser::InitMinMaxStepDefault () +{ + mMinimumValue = 0; + mMaximumValue = 0; + mStepValue = 1; + mDefaultValue = 0; +} +VOID +EfiVfrParser::WriteMinMaxStepDefault () +{ + WriteWord (mMinimumValue); + WriteWord (mMaximumValue); + WriteWord (mStepValue); + WriteWord (mDefaultValue); +} +VOID +EfiVfrParser::SetMinMaxStepDefault ( + UINT16 Value, + INT32 MMSD, + INT32 LineNum + ) +{ + UINT16 TempValue; + // + // Min specified + // + if (MMSD == 0) { + mMinimumValue = Value; + mDefaultValue = Value; + // + // Max specified + // + } else if (MMSD == 1) { + mMaximumValue = Value; + // + // If min > max, then swap the values. That includes resetting the default + // value as well. + // + if (mMinimumValue > mMaximumValue) { + PrintWarningMessage (LineNum, NULL, "maximum < minimum"); + TempValue = Value; + mMaximumValue = mMinimumValue; + mMinimumValue = TempValue; + mDefaultValue = mMinimumValue; + } + // + // Step specified + // + } else if (MMSD == 2) { + mStepValue = Value; + // + // Default specified. Make sure min <= default <= max. + // + } else if (MMSD == 3) { + mDefaultValue = Value; + if (mMinimumValue > Value) { + PrintErrorMessage (LineNum, NULL, "default value < minimum value"); + } else if (Value > mMaximumValue) { + PrintErrorMessage (LineNum, NULL, "default value > maximum value"); + } + } else { + PrintErrorMessage (LineNum, "application error", "internal MMSD error"); + } +} +VOID +EfiVfrParser::AddLabel ( + UINT32 LabelNumber, + UINT32 LineNum + ) +{ + UINT16_LIST *Label; + + // + // Added a label from the user VFR script. Make sure they haven't already + // defined the same label elsewhere + // + for (Label = mDefinedLabels; Label != NULL; Label = Label->Next) { + if (Label->Value == LabelNumber) { + PrintErrorMessage (LineNum, NULL, "label already defined"); + PrintErrorMessage (Label->LineNum, NULL, "previous definition of redefined label"); + break; + } + } + Label = (UINT16_LIST *)malloc (sizeof (UINT16_LIST)); + if (Label == NULL) { + PrintErrorMessage (0, NULL, "memory allocation error"); + return; + } + memset ((char *)Label, 0, sizeof (UINT16_LIST)); + Label->Value = LabelNumber; + Label->LineNum = LineNum; + Label->Next = mDefinedLabels; + mDefinedLabels = Label; +} +VOID +EfiVfrParser::QueueIdEqValList ( + UINT16 Value + ) +{ + UINT16_LIST *U16; + + U16 = (UINT16_LIST *)malloc (sizeof (UINT16_LIST)); + if (U16 == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failed"); + } else { + memset ((char *)U16, 0, sizeof (UINT16_LIST)); + U16->Value = Value; + if (mUint16List == NULL) { + mUint16List = U16; + } else { + mLastUint16->Next = U16; + } + mLastUint16 = U16; + } +} +VOID +EfiVfrParser::FlushQueueIdEqValList () +{ + UINT32 Count; + + // + // We queued up a list of IdEqValList items. The IFR requires a count + // followed by the actual values. Do it. + // + Count = 0; + mLastUint16 = mUint16List; + while (mLastUint16 != NULL) { + Count++; + mLastUint16 = mLastUint16->Next; + } + // BUGBUG -- check for more than 16K items? + WriteWord (Count); + // + // Now write the values. + // + mLastUint16 = mUint16List; + while (mLastUint16 != NULL) { + WriteWord ((UINT32)mLastUint16->Value); + mLastUint16 = mLastUint16->Next; + } + // + // Free up the list + // + mLastUint16 = mUint16List; + while (mUint16List != NULL) { + mLastUint16 = mUint16List->Next; + free (mUint16List); + mUint16List = mLastUint16; + } +} +VOID +EfiVfrParser::PrintErrorMessage ( + UINT32 LineNum, + CHAR8 *Msg1, + CHAR8 *Msg2 + ) +{ + char *FileName; + + if (LineNum != 0) { + FileName = ConvertLineNumber ((UINT32 *)&LineNum); + Error (FileName, LineNum, 0, Msg1, Msg2); + } else { + Error (PROGRAM_NAME, 0, 0, Msg1, Msg2); + } +} +VOID +EfiVfrParser::PrintWarningMessage ( + UINT32 LineNum, + CHAR8 *Msg1, + CHAR8 *Msg2 + ) +{ + char *FileName; + + if (LineNum != 0) { + FileName = ConvertLineNumber ((UINT32 *)&LineNum); + Warning (FileName, LineNum, 0, Msg1, Msg2); + } else { + Warning (PROGRAM_NAME, 0, 0, Msg1, Msg2); + } +} +VOID +EfiVfrParser::syn ( + ANTLRAbstractToken *Tok, + ANTLRChar *Egroup, + SetWordType *Eset, + ANTLRTokenType ETok, + INT32 Huh + ) +/*++ + +Routine Description: + Called by the parser base class as a result of parse syntax errors. + +Arguments: + Tok - token that caused the error + Egroup - not sure + Eset - index in token table of the expected token + Huh - not sure + +Returns: + NA + +--*/ +{ + char *FileName; + UINT32 LineNum; + + LineNum = Tok->getLine (); + FileName = ConvertLineNumber ((UINT32 *)&LineNum); + // + // Sometimes the token number is 0, in which case I don't know what to + // print. + // + if (ETok == 0) { + Error (FileName, LineNum, 0, Tok->getText (), "unexpected token"); + } else { + // + // If we were expecting an endif, then report the line where the corresponding + // IF began. + // + if ((strcmp (_token_tbl[ETok], "endif") == 0) && (mIfStart != 0)) { + LineNum = mIfStart; + FileName = ConvertLineNumber (&LineNum); + Error (FileName, LineNum, 0, "statement missing corresponding endif", NULL); + } else { + Error (FileName, LineNum, 0, Tok->getText (), "expected %s", _token_tbl[ETok]); + } + } +} + +VOID +EfiVfrParser::init() +/*++ + +Routine Description: + Initializations function for our parser. + +Arguments: + None. + +Returns: + None. + +--*/ +{ + ANTLRParser::init(); + + // + // Used for queuing a variable list of UINT16's + // + mUint16List = NULL; + mLastUint16 = NULL; + mFirstStructDefinition = NULL; + mLastStructDefinition = NULL; + mNvDataStructSize = 0; + mNonNvDataStructSize = 0; + mNvDataStructDefined = 0; + mGotoReferences = NULL; + mFormIdValues = NULL; + mDefinedLabels = NULL; + mClass = 0; + mSubclass = 0; + mIfStart = 0; + mDefinedVarStoreId = NULL; + mLastDefinedVarStoreId = NULL; + mIdEqIdStmt = 0; + mLastNVVariableDataSize = 0; + + memset ((char *)&mFormSetGuid, 0, sizeof (EFI_GUID)); +} +// +// Destructor for the parser. +// +EfiVfrParser::~EfiVfrParser(VOID) +{ + Cleanup(); +} +VOID +EfiVfrParser::Cleanup (VOID) +/*++ + +Routine Description: + Free memory allocated during parsing + +Arguments: + None. + +Returns: + None. + +--*/ +{ + STRUCT_DEFINITION *NextStruct; + STRUCT_FIELD_DEFINITION *NextField; + UINT8 Buff[6]; + UINT16_LIST *NextU16List; + + // + // Free up the structure definitions if any + // + while (mFirstStructDefinition != NULL) { + // + // Free up all the fields for this struct + // + while (mFirstStructDefinition->Field != NULL) { + NextField = mFirstStructDefinition->Field->Next; + free (mFirstStructDefinition->Field->Name); + free (mFirstStructDefinition->Field); + mFirstStructDefinition->Field = NextField; + } + NextStruct = mFirstStructDefinition->Next; + free (mFirstStructDefinition->Name); + free (mFirstStructDefinition); + mFirstStructDefinition = NextStruct; + } + // + // Free up the goto references and form id defines + // + FreeGotoReferences (); + // + // Free up label list + // + while (mDefinedLabels != NULL) { + NextU16List = mDefinedLabels->Next; + delete (mDefinedLabels); + mDefinedLabels = NextU16List; + } + // + // Free up the list of defined variable storage IDs + // + while (mDefinedVarStoreId != NULL) { + NextU16List = mDefinedVarStoreId->Next; + delete (mDefinedVarStoreId); + mDefinedVarStoreId = NextU16List; + } +} + +INT32 +EfiVfrParser::AtoX ( + CHAR8 *HexString, + INT32 NumBytes, + UINT32 *HexValue + ) +/*++ + +Routine Description: + Given a pointer to a ascii hex string, convert to a number with the given + number of bytes. + +Arguments: + HexString - pointer to a string of format 30BCA + Size - number of bytes to convert + HexValue - return result + +Returns: + The number of bytes converted. + +--*/ +{ + INT32 Count; + INT32 Value; + + *HexValue = 0; + Count = 0; + while (Count < NumBytes) { + if ((*HexString >= '0') && (*HexString <= '9')) { + Value = *HexString - '0'; + } else if ((*HexString >= 'a') && (*HexString <= 'f')) { + Value = *HexString - 'a' + 10; + } else if ((*HexString >= 'A') && (*HexString <= 'F')) { + Value = *HexString - 'A' + 10; + } else { + return Count; + } + HexString++; + *HexValue = (*HexValue << 4) | Value; + if ((*HexString >= '0') && (*HexString <= '9')) { + Value = *HexString - '0'; + } else if ((*HexString >= 'a') && (*HexString <= 'f')) { + Value = *HexString - 'a' + 10; + } else if ((*HexString >= 'A') && (*HexString <= 'F')) { + Value = *HexString - 'A' + 10; + } else { + return Count; + } + *HexValue = (*HexValue << 4) | Value; + HexString++; + Count++; + } + return Count; +} +VOID +EfiVfrParser::WriteGuidValue ( + UINT32 TokenLineNum, + CHAR8 *G1, + CHAR8 *G2, + CHAR8 *G3, + CHAR8 *G4, + CHAR8 *G5, + CHAR8 *G6, + CHAR8 *G7, + CHAR8 *G8, + CHAR8 *G9, + CHAR8 *G10, + CHAR8 *G11 + ) +/*++ + +Routine Description: + A Guid was parsed, likely of format: + #define MY_GUID { 0x12345678, 0xAABB, 0xCCDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 } + + Write out the value. + +Arguments: + TokenLineNum - line number where the guid was used + G1-G11 - the 11 fields of the guid value + +Returns: + None. + +--*/ +{ + UINT32 Value; + INT32 Loop; + + mFormSetGuid.Data1 = GetNumber (G1, TokenLineNum, 4); + mFormSetGuid.Data2 = (UINT16)GetNumber (G2, TokenLineNum, 2); + mFormSetGuid.Data3 = (UINT16)GetNumber (G3, TokenLineNum, 2); + mFormSetGuid.Data4[0] = (UINT8)GetNumber (G4, TokenLineNum, 1); + mFormSetGuid.Data4[1] = (UINT8)GetNumber (G5, TokenLineNum, 1); + mFormSetGuid.Data4[2] = (UINT8)GetNumber (G6, TokenLineNum, 1); + mFormSetGuid.Data4[3] = (UINT8)GetNumber (G7, TokenLineNum, 1); + mFormSetGuid.Data4[4] = (UINT8)GetNumber (G8, TokenLineNum, 1); + mFormSetGuid.Data4[5] = (UINT8)GetNumber (G9, TokenLineNum, 1); + mFormSetGuid.Data4[6] = (UINT8)GetNumber (G10, TokenLineNum, 1); + mFormSetGuid.Data4[7] = (UINT8)GetNumber (G11, TokenLineNum, 1); + + WriteDWord (mFormSetGuid.Data1, 'G'); + WriteWord (mFormSetGuid.Data2); + WriteWord (mFormSetGuid.Data3); + WriteByte (mFormSetGuid.Data4[0], 0); + WriteByte (mFormSetGuid.Data4[1], 0); + WriteByte (mFormSetGuid.Data4[2], 0); + WriteByte (mFormSetGuid.Data4[3], 0); + WriteByte (mFormSetGuid.Data4[4], 0); + WriteByte (mFormSetGuid.Data4[5], 0); + WriteByte (mFormSetGuid.Data4[6], 0); + WriteByte (mFormSetGuid.Data4[7], 0); +} +VOID +EfiVfrParser::WriteFieldOffset ( + INT8 WriteLength, + CHAR8 *StructName, + INT32 LineNum1, + CHAR8 *FieldName, + INT32 LineNum2, + INT32 ArrayIndex, + INT8 IsArrayIndex, + INT32 FieldWidth, + INT8 WriteArraySize + ) +/*++ + +Routine Description: + A VFR script referenced the NV store structure. Given the structure's name + and the field's name, write the offset of the field to the output file. + +Arguments: + WriteLength - write the field length byte out + StructName - name of the NV store structure + LineNum1 - line number in the VFR where we are (for error printing) + FieldName - the name of the field within the NV store structure + LineNum2 - line number in the VFR where FieldName is referenced + ArrayIndex - the index specified, for example NV_DATA.Field[ArrayIndex] + IsArrayIndex - non-zero if an array index was specified + FieldWidth - expected size for the Field (1 byte? 2 bytes?) + WriteArraySize - write the size of the entire field, not the size of a single element + +Returns: + None. + +--*/ +{ + STRUCT_DEFINITION *StructDef; + STRUCT_FIELD_DEFINITION *FieldDef; + UINT32 Offset; + UINT32 VarSize; + CHAR8 Msg[100]; + // + // If we're writing an array size, then they better have referenced the field without an + // index. + // + if (WriteArraySize && IsArrayIndex) { + sprintf (Msg, "array index specified where an array is required"); + PrintErrorMessage (LineNum2, FieldName, Msg); + return; + } + // + // Look through our list of known structures for a match + // + for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) { + // + // Check for matching structure name + // + if (strcmp (StructDef->Name, StructName) == 0) { + // + // Mark it as referenced (for debug purposes only). Check the + // flag that indicates that we have already found a varstore VFR + // statement for it. + // + StructDef->Referenced++; + if (StructDef->VarStoreIdValid == 0) { + // + // Set it valid so we don't flag it multiple times, then emit the error + // + StructDef->VarStoreIdValid = 1; + PrintErrorMessage (LineNum1, StructName, "varstore statement missing for this variable store"); + } + // + // Let the opcode-handler know which variable storage we're now using + // + if (mIdEqIdStmt) { + mOpcodeHandler.SetSecondaryVarStoreId (StructDef->VarStoreId); + } else { + mOpcodeHandler.SetVarStoreId (StructDef->VarStoreId); + } + // + // Found matching structure name. Now find the matching field name + // + for (FieldDef = StructDef->Field; FieldDef != NULL; FieldDef = FieldDef->Next) { + if (strcmp (FieldDef->Name, FieldName) == 0) { + // + // Make sure the variable size is valid + // + if ((FieldWidth != 0) && (FieldDef->DataSize > FieldWidth)) { + sprintf (Msg, "field width exceeds %d byte%c", FieldWidth, FieldWidth == 1 ? ' ' : 's'); + PrintErrorMessage (LineNum2, FieldName, Msg); + } + // + // If they specified an index (MyVfrData.FieldX[10]), then make sure that the + // data structure was declared as an array, and that the index is in bounds. + // If they did not specify an index, then we'll assume 0. This is required for + // strings. + // + if (IsArrayIndex) { + VarSize = FieldDef->DataSize; + if (FieldDef->IsArray == 0) { + PrintErrorMessage (LineNum2, FieldName, "field is not declared as an array"); + return; + } + if (FieldDef->ArrayLength < ArrayIndex) { + PrintErrorMessage (LineNum2, FieldName, "array index exceeds declared size of field"); + return; + } + } else { + if (FieldDef->IsArray) { + VarSize = FieldDef->DataSize * FieldDef->ArrayLength; + } else { + VarSize = FieldDef->DataSize; + } + } + // + // If we're in the middle of a ideqid VFR statement, then this is the second + // variable ID that we're now processing. Make sure that its size is the same + // as the first variable. + // + if (mIdEqIdStmt) { + if (mLastVarIdSize != VarSize) { + PrintErrorMessage (LineNum2, FieldName, "variables must have the same size"); + return; + } + } + mLastVarIdSize = VarSize; + // + // If we're supposed to write an array size, then require it to be an array + // + if (WriteArraySize && !FieldDef->IsArray) { + PrintErrorMessage (LineNum2, FieldName, "array required"); + return; + } + // + // Write the variable offset and size. If we're in the non-NV structure, then + // set the offset beyond the NV data structure size. + // + Offset = FieldDef->Offset + FieldDef->DataSize * (ArrayIndex - 1); + if (StructDef->IsNonNV) Offset += mNvDataStructSize; + WriteWord (Offset); + if (WriteLength) { + if (WriteArraySize) { + if (FieldDef->DataSize * FieldDef->ArrayLength > 255) { + PrintErrorMessage (LineNum2, FieldName, "array size exceeds 255 maximum encoding limit"); + return; + } + WriteByte (FieldDef->DataSize * FieldDef->ArrayLength, 0); + } else { + WriteByte (FieldDef->DataSize, 0); + } + } + return; + } + } + sprintf (Msg, "structure %s does not have a field named '%s'", StructName, FieldName); + PrintErrorMessage (LineNum2, Msg, NULL); + PrintErrorMessage (StructDef->LineNum, "see structure definition", NULL); + return; + } + } + // + // The structure was not found in the defined list. See if it's the "Date" structure + // + if (strcmp (StructName, "Date") == 0) { + // + // BUGBUG -- remove support for Date and Time as valid structure + // names. They should use the NON_NV_DATA_MAP structure for this. + // + // Someone specified Date.Years|Months|Days + // BUGBUG -- define some constants for the IDs used here + // Length == 0 implies that this is not user NV data storage. + // + if (strcmp (FieldName, "Year") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 0); + if (WriteLength) { + WriteByte (0, 0); + } + } else if (strcmp (FieldName, "Month") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 2); + if (WriteLength) { + WriteByte (0, 0); + } + } else if (strcmp (FieldName, "Day") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 4); + if (WriteLength) { + WriteByte (0, 0); + } + } else { + PrintErrorMessage (LineNum1, FieldName, "expected valid field name TheYear/TheMonth/TheDay"); + } + return; + } else if (strcmp (StructName, "Time") == 0) { + // + // Someone specified Time.Hours|Minutes|Seconds + // BUGBUG -- define some constants for the IDs used here + // + if (strcmp (FieldName, "Hours") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 6); + if (WriteLength) { + WriteByte (0, 0); + } + } else if (strcmp (FieldName, "Minutes") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 8); + if (WriteLength) { + WriteByte (0, 0); + } + } else if (strcmp (FieldName, "Seconds") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 10); + if (WriteLength) { + WriteByte (0, 0); + } + } else { + PrintErrorMessage (LineNum1, FieldName, "expected valid field name Hours/Minutes/Seconds"); + } + return; + } else { + PrintErrorMessage (LineNum1, StructName, "undefined structure"); + return; + } +} +VOID +EfiVfrParser::StartStructDefinition ( + INT32 IsNonNV, + INT32 LineNum + ) +/*++ + +Routine Description: + Called when we encounter a new "struct _MY_STRUCT..." statement while parsing. + Initialize internal data and structures for parsing the fields of the structure. + +Arguments: + LineNum - line number in the source file (for error reporting purposes) + IsNonNv - flag indicating (if nonzero) that the variable referred to is not in + the standard NV store. +Returns: + None + +--*/ +{ + STRUCT_DEFINITION *StructDef; + // + // Allocate memory for the structure record + // + StructDef = (STRUCT_DEFINITION *)malloc (sizeof (STRUCT_DEFINITION)); + memset (StructDef, 0, sizeof (STRUCT_DEFINITION)); + StructDef->LineNum = LineNum; + // + // Set flag indicating non-NV data structure or not + // + StructDef->IsNonNV = IsNonNV; + // + // Add it to the end of our linked list. If it's the first one + // defined, then it's the default varstore ID, so set it valid. + // + if (mFirstStructDefinition == NULL) { + mFirstStructDefinition = StructDef; + StructDef->VarStoreIdValid = 1; + } else { + mLastStructDefinition->Next = StructDef; + } + mLastStructDefinition = StructDef; +} +VOID +EfiVfrParser::EndStructDefinition ( + CHAR8 *StructName, + INT32 LineNum + ) +{ + STRUCT_DEFINITION *StructDef; + STRUCT_FIELD_DEFINITION *FieldDef; + UINT32 Offset; + // + // Make sure they have not already defined a structure with this name + // + for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) { + if ((StructDef->Name != NULL) && (strcmp (StructDef->Name, StructName) == 0)) { + PrintErrorMessage (LineNum, StructName, "structure with this name already defined"); + // + // Fall through and fill in the rest of the structure information. We do + // this because the structure has already been added to our global list, + // so will be used elsewhere, so we want it to contain valid fields. + // + } + } + // + // Allocate memory for the structure name + // + mLastStructDefinition->Name = (char *)malloc (strlen (StructName) + 1); + strcpy (mLastStructDefinition->Name, StructName); + // + // Compute the structure size, and the offsets to each field + // + Offset = 0; + for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) { + FieldDef->Offset = Offset; + Offset += FieldDef->ArrayLength * FieldDef->DataSize; + } + mLastStructDefinition->Size = Offset; + // + // Go through all the structure we have so far and figure out (if we can) + // the size of the non-NV storage. We also assume that the first structure + // definition is the primary/default storage for the VFR form. + // + if (mNonNvDataStructSize == 0) { + for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) { + if (StructDef->IsNonNV) { + mNonNvDataStructSize = StructDef->Size; + break; + } + } + } + if (mNvDataStructSize == 0) { + for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) { + if (StructDef->IsNonNV == 0) { + mNvDataStructSize = StructDef->Size; + break; + } + } + } +} +VOID +EfiVfrParser::AddStructField ( + CHAR8 *FieldName, + INT32 LineNum, + INT32 DataSize, + INT32 ArrayLength, + INT8 IsArray + ) +/*++ + +Routine Description: + We're parsing the VFR structure definition. Add another defined field to + our definition. + +Arguments: + FieldName - name of the field in the structure. + LineNum - the line number from the input (preprocessor output) file + DataSize - the size of the field (1, 2, or 4 bytes) + ArrayLength - the number of elements (for array) + IsArray - non-zero if the field is an array + +Returns: + None. + +--*/ +{ + STRUCT_FIELD_DEFINITION *FieldDef; + STRUCT_FIELD_DEFINITION *Temp; + // + // Make sure we don't already have a field of this name in our structure + // + for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) { + if (strcmp (FieldDef->Name, FieldName) == 0) { + PrintErrorMessage (LineNum, FieldName, "field with this name already defined"); + return; + } + } + // + // If it's an array, then they better not have a size of 0. For example: + // UINT8 MyBytes[0]; + // + if (IsArray && (ArrayLength <= 0)) { + PrintErrorMessage (LineNum, FieldName, "invalid array size"); + return; + } + // + // Allocate memory for a new structure field definition + // + FieldDef = (STRUCT_FIELD_DEFINITION *)malloc (sizeof (STRUCT_FIELD_DEFINITION)); + memset ((char *)FieldDef, 0, sizeof (STRUCT_FIELD_DEFINITION)); + FieldDef->ArrayLength = ArrayLength; + FieldDef->DataSize = DataSize; + FieldDef->IsArray = IsArray; + FieldDef->Name = (char *)malloc (strlen (FieldName) + 1); + strcpy (FieldDef->Name, FieldName); + // + // Add it to the end of the field list for the currently active structure + // + if (mLastStructDefinition->Field == NULL) { + mLastStructDefinition->Field = FieldDef; + } else { + mLastStructDefinition->LastField->Next = FieldDef; + } + mLastStructDefinition->LastField = FieldDef; +} +VOID +EfiVfrParser::AddVarStore ( + CHAR8 *StructName, // actual name of the structure + CHAR8 *VarName, // actual NV variable name + UINT16 VarStoreId, // key value + INT32 LineNum // parse line number (for error reporting) + ) +/*++ + +Routine Description: + Called while parsing a varstore statement. Add the variable store + to our linked list. + +Arguments: + StructName - the name of the typedef'ed structure to use + VarName - the NV variable name as specified in the varstore statement + VarStoreId - the variable store ID as specified in the varstore statememt + LineNum - the line number from the input (preprocessor output) file + +Returns: + None. + +--*/ +{ + STRUCT_DEFINITION *StructDef; + UINT16_LIST *L16Ptr; + // + // Go through our list of previously-defined variable store IDs and + // make sure this one is not a duplicate in name or key value. + // + for (L16Ptr = mDefinedVarStoreId; L16Ptr != NULL; L16Ptr = L16Ptr->Next) { + if (L16Ptr->Value == VarStoreId) { + PrintErrorMessage (LineNum, "variable storage key already used", NULL); + PrintErrorMessage (L16Ptr->LineNum, "previous usage of storage key", NULL); + } + } + // + // Key value of 0 is invalid since that's assigned by default to the default + // variable store (the first structure parsed). + // + if (VarStoreId == 0) { + PrintErrorMessage (LineNum, "variable storage key of 0 is invalid", NULL); + } + // + // Create a new element to add to the list + // + L16Ptr = (UINT16_LIST *)malloc(sizeof (UINT16_LIST)); + memset (L16Ptr, 0, sizeof (UINT16_LIST)); + L16Ptr->LineNum = LineNum; + L16Ptr->Value = VarStoreId; + if (mDefinedVarStoreId == NULL) { + mDefinedVarStoreId = L16Ptr; + } else { + mLastDefinedVarStoreId->Next = L16Ptr; + } + mLastDefinedVarStoreId = L16Ptr; + // + // Find the structure definition with this name + // + for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) { + if (strcmp (StructDef->Name, StructName) == 0) { + // + // Make sure they did not already define a variable storage ID + // for this structure. + // + if (StructDef->VarStoreId != 0) { + PrintErrorMessage (LineNum, StructName, "variable storage already defined for this structure"); + PrintErrorMessage (StructDef->VarStoreLineNum, StructName, "previous definition for variable storage"); + } + StructDef->VarStoreId = VarStoreId; + StructDef->VarStoreIdValid = 1; + StructDef->VarStoreLineNum = LineNum; + WriteWord (StructDef->Size); + while (*VarName) { + WriteByte(*VarName, 0); + VarName++; + } + WriteByte(0,0); + return; + } + } + PrintErrorMessage (LineNum, StructName, "structure with this name not defined"); +} +VOID +EfiVfrParser::WriteDWord ( + UINT32 Value, + UINT8 KeyByte + ) +/*++ + +Routine Description: + During parsing, we came upon some code that requires a 32-bit value be + written to the VFR binary file. Queue up the 4 bytes. + +Arguments: + Value - the 32-bit value to write + KeyByte - a single character which gets written out beside the first byte. + This is used to tag the data in the output file so that during + debug you have an idea what the value is. + +Returns: + None. + +--*/ +{ + // + // Write 4 bytes, little endian. Specify a key byte only on the first one + // + mOpcodeHandler.AddByte ((UINT8)Value, KeyByte); + Value \>>= 8; + mOpcodeHandler.AddByte ((UINT8)Value, 0); + Value \>>= 8; + mOpcodeHandler.AddByte ((UINT8)Value, 0); + Value \>>= 8; + mOpcodeHandler.AddByte ((UINT8)Value, 0); +} +VOID +EfiVfrParser::WriteOpByte ( + UINT32 LineNum, + UINT8 ByteValue + ) +/*++ + +Routine Description: + + During parsing, we came upon a new VFR opcode. At this point we flush + the output queue and then queue up this byte (with 'O' for opcode tag). + +Arguments: + + ByteValue - opcode value + +Returns: + + None. + +--*/ +{ + mOpcodeHandler.AddOpcodeByte (ByteValue, LineNum); +} +VOID +EfiVfrParser::WriteByte ( + UINT8 ByteValue, + UINT8 Key + ) +/*++ + +Routine Description: + + During parsing of the VFR we spoonfeed this function with bytes to write to + the output VFR binary file. This function simply queues up the bytes, and + the queue gets flushed each time a new VFR opcode is encountered. + +Arguments: + + ByteValue - raw byte to write + Key - character to tag the byte with when we write ByteValue to the + output file. + +Returns: + + None. + +--*/ +{ + mOpcodeHandler.AddByte (ByteValue, Key); +} +VOID +EfiVfrParser::WriteWord ( + UINT32 Value + ) +/*++ + +Routine Description: + During VFR parsing we came upon a case where we need to write out a + 16-bit value. Queue it up. + +Arguments: + Value - value to write. + +Returns: + None. + +--*/ +{ + mOpcodeHandler.AddByte ((UINT8)Value, 0); + mOpcodeHandler.AddByte ((UINT8)((Value \>> 8) & 0xFF), 0); +} +VOID +EfiVfrParser::WriteStringIdWord ( + UINT16 WordValue + ) +{ + mOpcodeHandler.AddByte ((UINT8)WordValue, 'S'); + mOpcodeHandler.AddByte ((UINT8)((WordValue \>> 8) & 0xFF), 0); +} +VOID +EfiVfrParser::FreeGotoReferences () +/*++ + +Routine Description: + Called during cleanup to free up the memory we allocated when + keeping track of VFR goto statements. + +Arguments: + None + +Returns: + None + +--*/ +{ + GOTO_REFERENCE *CurrRef; + GOTO_REFERENCE *NextRef; + FORM_ID_VALUE *CurrFormId; + FORM_ID_VALUE *NextFormId; + UINT8 Found; + CHAR8 Name[20]; + + // + // Go through all the "goto" references and make sure there was a + // form ID of that value defined. + // + for (CurrRef = mGotoReferences; CurrRef != NULL; CurrRef = CurrRef->Next) { + Found = 0; + for (CurrFormId = mFormIdValues; CurrFormId != NULL; CurrFormId = CurrFormId->Next) { + if (CurrRef->Value == CurrFormId->Value) { + Found = 1; + break; + } + } + if (!Found) { + sprintf (Name, "%d", (UINT32)CurrRef->Value); + PrintErrorMessage (CurrRef->RefLineNum, Name, "undefined form ID"); + } + } + // + // Now free up the form id and goto references + // + CurrFormId = mFormIdValues; + while (CurrFormId != NULL) { + NextFormId = CurrFormId->Next; + free (CurrFormId); + CurrFormId = NextFormId; + } + mFormIdValues = NULL; + CurrRef = mGotoReferences; + while (CurrRef != NULL) { + NextRef = CurrRef->Next; + free (CurrRef); + CurrRef = NextRef; + } + mGotoReferences = NULL; +} +VOID +EfiVfrParser::AddGotoReference ( + UINT32 GotoNumber, + UINT32 LineNum + ) +/*++ + +Routine Description: + During VFR parsing we came upon a goto statement. Since we support + forward references, save the referenced label and at the end of parsing + we'll check that the label was actually defined somewhere. + +Arguments: + GotoNumber - the label number referenced + LineNum - the line number where the reference was made (used for + error reporting) + +Returns: + None + +--*/ +{ + GOTO_REFERENCE *NewRef; + + NewRef = (GOTO_REFERENCE *)malloc (sizeof (GOTO_REFERENCE)); + if (NewRef == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return; + } + memset ((char *)NewRef, 0, sizeof (GOTO_REFERENCE)); + NewRef->Value = (UINT16)GotoNumber; + NewRef->RefLineNum = LineNum; + NewRef->Next = mGotoReferences; + mGotoReferences = NewRef; +} +VOID +EfiVfrParser::AddFormId ( + INT32 FormIdValue, + UINT32 LineNum + ) +/*++ + +Routine Description: + This function is called when we parse "form formid = 3" statements. + We save the form ID valud so we can verify that duplicates are not + defined. Also, these are the targets of goto statements, so when we're + done parsing the script we also go through all the goto statements to + check that there was a target FormId defined as referenced by each + goto statement. + + Note that formid = 0 is invalid. + +Arguments: + FormIdValue - the parsed value for the Form ID + LineNum - line number of the source file we're parsing + +Returns: + NA + +--*/ +{ + FORM_ID_VALUE *NewFormId; + char *FileName; + char *FileName2; + UINT32 LineNum2; + // + // Verify that FormId != 0 + // + if (FormIdValue == 0) { + FileName = ConvertLineNumber (&LineNum); + Error (FileName, LineNum, 0, "form ID cannot be 0", NULL); + return; + } + // + // First go through all previously defined form IDs and make sure they have not defined + // duplicates. + // + for (NewFormId = mFormIdValues; NewFormId != NULL; NewFormId = NewFormId->Next) { + if ((UINT16)FormIdValue == NewFormId->Value) { + FileName = ConvertLineNumber (&LineNum); + LineNum2 = NewFormId->LineNum; + FileName2 = ConvertLineNumber (&LineNum2); + Error (FileName, LineNum, 0, NULL, "form ID %d already defined", FormIdValue); + Error (FileName2, LineNum2, 0, NULL, "form ID %d previous definition", FormIdValue); + return; + } + } + // + // Allocate memory for a new one + // + NewFormId = (FORM_ID_VALUE *)malloc (sizeof (FORM_ID_VALUE)); + if (NewFormId == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return; + } + memset ((char *)NewFormId, 0, sizeof (FORM_ID_VALUE)); + NewFormId->LineNum = LineNum; + NewFormId->Next = mFormIdValues; + NewFormId->Value = (UINT16)FormIdValue; + mFormIdValues = NewFormId; +} +UINT32 +EfiVfrParser::GetNumber ( + CHAR8 *NumStr, + UINT32 LineNum, + UINT32 NumBytes + ) +{ + UINT32 Value; + + if ((NumStr[0] == '0') && (NumStr[1] == 'x')) { + AtoX (NumStr + 2, 4, &Value); + } else { + Value = (UINT32)atoi (NumStr); + } + // + // Check range + // + if ((NumBytes < 4) && (Value & ((UINT32)0xFFFFFFFF << (NumBytes * 8)))) { + PrintErrorMessage (LineNum, NumStr, "value out of range"); + return 0; + } + return Value; +} + +>> + +} // end grammar class + diff --git a/Tools/Source/TianoTools/VfrCompile/VfrServices.cpp b/Tools/Source/TianoTools/VfrCompile/VfrServices.cpp new file mode 100644 index 0000000000..c66d4dfa79 --- /dev/null +++ b/Tools/Source/TianoTools/VfrCompile/VfrServices.cpp @@ -0,0 +1,757 @@ +/*++ + +Copyright (c) 2004 - 2005, 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. + +Module Name: + + VfrServices.cpp + +Abstract: + + Support routines for the VFR compiler + +--*/ + +#include // for FILE routines +#include // for malloc() and free() + +#include +#include +#include +#include "EfiUtilityMsgs.h" +#include "EfiVfr.h" +#include "VfrServices.h" + +#include +#include + +static const char *mSourceFileHeader[] = { + "//", + "// DO NOT EDIT -- auto-generated file", + "//", + "// This file is generated by the VFR compiler.", + "//", + NULL +}; + +typedef struct { + CHAR8 *Name; + INT32 Size; +} IFR_OPCODE_SIZES; + +// +// Create a table that can be used to do internal checking on the IFR +// bytes we emit. +// +static const IFR_OPCODE_SIZES mOpcodeSizes[] = { + { 0, 0 }, // invalid + { "EFI_IFR_FORM", sizeof (EFI_IFR_FORM) }, + { "EFI_IFR_SUBTITLE", sizeof (EFI_IFR_SUBTITLE) }, + { "EFI_IFR_TEXT", -6 }, //sizeof (EFI_IFR_TEXT) }, + { "unused 0x04 opcode", 0 }, // EFI_IFR_GRAPHIC_OP + { "EFI_IFR_ONE_OF", sizeof (EFI_IFR_ONE_OF) }, + { "EFI_IFR_CHECKBOX", sizeof (EFI_IFR_CHECKBOX) }, + { "EFI_IFR_NUMERIC", sizeof (EFI_IFR_NUMERIC) }, + { "EFI_IFR_PASSWORD", sizeof (EFI_IFR_PASSWORD) }, + { "EFI_IFR_ONE_OF_OPTION", sizeof (EFI_IFR_ONE_OF_OPTION) }, + { "EFI_IFR_SUPPRESS", sizeof (EFI_IFR_SUPPRESS) }, + { "EFI_IFR_END_FORM", sizeof (EFI_IFR_END_FORM) }, + { "EFI_IFR_HIDDEN", sizeof (EFI_IFR_HIDDEN) }, + { "EFI_IFR_END_FORM_SET", sizeof (EFI_IFR_END_FORM_SET) }, + { "EFI_IFR_FORM_SET", sizeof (EFI_IFR_FORM_SET) }, + { "EFI_IFR_REF", sizeof (EFI_IFR_REF) }, + { "EFI_IFR_END_ONE_OF", sizeof (EFI_IFR_END_ONE_OF) }, + { "EFI_IFR_INCONSISTENT", sizeof (EFI_IFR_INCONSISTENT) }, + { "EFI_IFR_EQ_ID_VAL", sizeof (EFI_IFR_EQ_ID_VAL) }, + { "EFI_IFR_EQ_ID_ID", sizeof (EFI_IFR_EQ_ID_ID) }, + { "EFI_IFR_EQ_ID_LIST", -sizeof (EFI_IFR_EQ_ID_LIST) }, + { "EFI_IFR_AND", sizeof (EFI_IFR_AND) }, + { "EFI_IFR_OR", sizeof (EFI_IFR_OR) }, + { "EFI_IFR_NOT", sizeof (EFI_IFR_NOT) }, + { "EFI_IFR_END_EXPR", sizeof (EFI_IFR_END_EXPR) }, + { "EFI_IFR_GRAY_OUT", sizeof (EFI_IFR_GRAY_OUT) }, + { "EFI_IFR_DATE", sizeof (EFI_IFR_DATE) / 3 }, + { "EFI_IFR_TIME", sizeof (EFI_IFR_TIME) / 3 }, + { "EFI_IFR_STRING", sizeof (EFI_IFR_STRING) }, + { "EFI_IFR_LABEL", sizeof (EFI_IFR_LABEL) }, + { "EFI_IFR_SAVE_DEFAULTS", sizeof (EFI_IFR_SAVE_DEFAULTS) }, + { "EFI_IFR_RESTORE_DEFAULTS", sizeof (EFI_IFR_RESTORE_DEFAULTS) }, + { "EFI_IFR_BANNER", sizeof (EFI_IFR_BANNER) }, + { "EFI_IFR_INVENTORY", sizeof (EFI_IFR_INVENTORY) }, + { "EFI_IFR_EQ_VAR_VAL_OP", sizeof (EFI_IFR_EQ_VAR_VAL) }, + { "EFI_IFR_ORDERED_LIST_OP", sizeof (EFI_IFR_ORDERED_LIST) }, + { "EFI_IFR_VARSTORE_OP", -sizeof (EFI_IFR_VARSTORE) }, + { "EFI_IFR_VARSTORE_SELECT_OP", sizeof (EFI_IFR_VARSTORE_SELECT) }, + { "EFI_IFR_VARSTORE_SELECT_PAIR_OP", sizeof (EFI_IFR_VARSTORE_SELECT_PAIR) }, + { "EFI_IFR_TRUE", sizeof (EFI_IFR_TRUE)}, + { "EFI_IFR_FALSE", sizeof (EFI_IFR_FALSE)}, + { "EFI_IFR_GT", sizeof (EFI_IFR_GT)}, + { "EFI_IFR_GE", sizeof (EFI_IFR_GE)}, + { "EFI_IFR_OEM_DEFINED_OP", -2 }, +}; + + +VfrOpcodeHandler::VfrOpcodeHandler ( + ) +/*++ + +Routine Description: + Constructor for the VFR opcode handling class. + +Arguments: + None + +Returns: + None + +--*/ +{ + mIfrBytes = NULL; + mLastIfrByte = NULL; + mBytesWritten = 0; + mQueuedByteCount = 0; + mQueuedOpcodeByteValid = 0; + mPrimaryVarStoreId = 0; + mSecondaryVarStoreId = 0; + mSecondaryVarStoreIdSet = 0; + mPrimaryVarStoreIdSet = 0; + mDefaultVarStoreId = 0; +} + +VOID +VfrOpcodeHandler::SetVarStoreId ( + UINT16 VarStoreId + ) +/*++ + +Routine Description: + This function is invoked by the parser when a variable is referenced in the + VFR. Save the variable store (and set a flag) so that we can later determine + if we need to emit a varstore-select or varstore-select-pair opcode. + +Arguments: + VarStoreId - ID of the variable store referenced in the VFR + +Returns: + None + +--*/ +{ + mPrimaryVarStoreId = VarStoreId; + mPrimaryVarStoreIdSet = 1; +} + +VOID +VfrOpcodeHandler::SetSecondaryVarStoreId ( + UINT16 VarStoreId + ) +/*++ + +Routine Description: + This function is invoked by the parser when a secondary variable is + referenced in the VFR. Save the variable store (and set a flag) so + that we can later determine if we need to emit a varstore-select or + varstore-pair opcode. + +Arguments: + VarStoreId - ID of the variable store referenced in the VFR + +Returns: + None + +--*/ +{ + mSecondaryVarStoreId = VarStoreId; + mSecondaryVarStoreIdSet = 1; +} + +VOID +VfrOpcodeHandler::WriteIfrBytes ( + ) +/*++ + +Routine Description: + This function is invoked at the end of parsing. Its purpose + is to write out all the IFR bytes that were queued up while + parsing. + +Arguments: + None + +Returns: + None + +--*/ +{ + IFR_BYTE *Curr; + IFR_BYTE *Next; + UINT32 Count; + UINT32 LineCount; + UINT32 PoundLines; + UINT32 ByteCount; + CHAR8 Line[MAX_LINE_LEN]; + CHAR8 *Cptr; + FILE *InFptr; + FILE *OutFptr; + UINT32 ListFile; + EFI_HII_IFR_PACK_HEADER IfrHeader; + UINT8 *Ptr; + FILE *IfrBinFptr; + UINT32 BytesLeftThisOpcode; + // + // If someone added a new opcode and didn't update our opcode sizes structure, error out. + // + if (sizeof(mOpcodeSizes) / sizeof (mOpcodeSizes[0]) != EFI_IFR_LAST_OPCODE + 1) { + Error (__FILE__, __LINE__, 0, "application error", "internal IFR binary table size is incorrect"); + return; + } + // + // Flush the queue + // + FlushQueue (); + // + // If there have been any errors to this point, then skip dumping the IFR + // binary data. This way doing an nmake again will try to build it again, and + // the build will fail if they did not fix the problem. + // + if (GetUtilityStatus () != STATUS_ERROR) { + if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "w")) == NULL) { + Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing"); + return; + } + // + // Write the standard file header to the output file + // + WriteStandardFileHeader (IfrBinFptr); + // + // Write the structure header + // + fprintf (IfrBinFptr, "\nunsigned char %sBin[] = {", gOptions.VfrBaseFileName); + // + // Write the header + // + memset ((char *)&IfrHeader, 0, sizeof (IfrHeader)); + IfrHeader.Header.Type = EFI_HII_IFR; + IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader); + Ptr = (UINT8 *)&IfrHeader; + for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) { + if ((Count & 0x03) == 0) { + fprintf (IfrBinFptr, "\n "); + } + fprintf (IfrBinFptr, "0x%02X, ", *Ptr); + } + // + // + // Write all the IFR bytes + // + fprintf (IfrBinFptr, "\n // start of IFR data"); + Curr = mIfrBytes; + Count = 0; + while (Curr != NULL) { + if ((Count & 0x0F) == 0) { + fprintf (IfrBinFptr, "\n "); + } + if (Curr->KeyByte != 0) { + fprintf (IfrBinFptr, "/*%c*/ ", Curr->KeyByte); + } + fprintf (IfrBinFptr, "0x%02X, ", Curr->OpcodeByte); + Count++; + Curr = Curr->Next; + } + fprintf (IfrBinFptr, "\n};\n\n"); + // + // + // Close the file + // + fclose (IfrBinFptr); + IfrBinFptr = NULL; + } + // + // Write the bytes as binary data if the user specified to do so + // + if ((GetUtilityStatus () != STATUS_ERROR) && (gOptions.CreateIfrBinFile != 0)) { + // + // Use the Ifr output file name with a ".hpk" extension. + // + for (Cptr = gOptions.IfrOutputFileName + strlen (gOptions.IfrOutputFileName) - 1; + (*Cptr != '.') && (Cptr > gOptions.IfrOutputFileName) && (*Cptr != '\\'); + Cptr--) { + // + // do nothing + // + } + if (*Cptr == '.') { + strcpy (Cptr, ".hpk"); + } else { + strcat (gOptions.IfrOutputFileName, ".hpk"); + } + if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "wb")) == NULL) { + Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing"); + return; + } + // + // Write the structure header + // + memset ((char *)&IfrHeader, 0, sizeof (IfrHeader)); + IfrHeader.Header.Type = EFI_HII_IFR; + IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader); + Ptr = (UINT8 *)&IfrHeader; + for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) { + fwrite (Ptr, 1, 1, IfrBinFptr); + } + // + // + // Write all the IFR bytes + // + Curr = mIfrBytes; + Count = 0; + while (Curr != NULL) { + fwrite (&Curr->OpcodeByte, 1, 1, IfrBinFptr); + Curr = Curr->Next; + } + // + // + // Close the file + // + fclose (IfrBinFptr); + IfrBinFptr = NULL; + } + // + // If creating a listing file, then open the input and output files + // + ListFile = 0; + if (gOptions.CreateListFile) { + // + // Open the input VFR file and the output list file + // + if ((InFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) { + Warning (PROGRAM_NAME, 0, 0, gOptions.PreprocessorOutputFileName, "could not open file for creating a list file"); + } else { + if ((OutFptr = fopen (gOptions.VfrListFileName, "w")) == NULL) { + Warning (PROGRAM_NAME, 0, 0, gOptions.VfrListFileName, "could not open output list file for writing"); + fclose (InFptr); + InFptr = NULL; + } else { + LineCount = 0; + ListFile = 1; + PoundLines = 0; + ByteCount = 0; + } + } + } + // + // Write the list file + // + if (ListFile) { + // + // Write out the VFR compiler version + // + fprintf (OutFptr, "//\n// VFR compiler version " VFR_COMPILER_VERSION "\n//\n"); + Curr = mIfrBytes; + while (Curr != NULL) { + // + // Print lines until we reach the line of the current opcode + // + while (LineCount < PoundLines + Curr->LineNum) { + if (fgets (Line, sizeof (Line), InFptr) != NULL) { + // + // We should check for line length exceeded on the fgets(). Otherwise it + // throws the listing file output off. Future enhancement perhaps. + // + fprintf (OutFptr, "%s", Line); + if (strncmp (Line, "#line", 5) == 0) { + PoundLines++; + } + } + LineCount++; + } + // + // Print all opcodes with line numbers less than where we are now + // + BytesLeftThisOpcode = 0; + while ((Curr != NULL) && ((Curr->LineNum == 0) || (LineCount >= PoundLines + Curr->LineNum))) { + if (BytesLeftThisOpcode == 0) { + fprintf (OutFptr, ">%08X: ", ByteCount); + if (Curr->Next != NULL) { + BytesLeftThisOpcode = (UINT32)Curr->Next->OpcodeByte; + } + } + fprintf (OutFptr, "%02X ", (UINT32)Curr->OpcodeByte); + ByteCount++; + BytesLeftThisOpcode--; + if (BytesLeftThisOpcode == 0) { + fprintf (OutFptr, "\n"); + } + Curr = Curr->Next; + } + } + // + // Dump any remaining lines from the input file + // + while (fgets (Line, sizeof (Line), InFptr) != NULL) { + fprintf (OutFptr, "%s", Line); + } + fclose (InFptr); + fclose (OutFptr); + } + // + // Debug code to make sure that each opcode we write out has as many + // bytes as the IFR structure requires. If there were errors, then + // don't do this step. + // + if (GetUtilityStatus () != STATUS_ERROR) { + Curr = mIfrBytes; + ByteCount = 0; + while (Curr != NULL) { + // + // First byte is the opcode, second byte is the length + // + if (Curr->Next == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "last opcode written does not contain a length byte"); + break; + } + Count = (UINT32)Curr->Next->OpcodeByte; + if (Count == 0) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "opcode with 0 length specified in output at offset 0x%X", + ByteCount + ); + break; + } + // + // Check the length + // + if ((Curr->OpcodeByte > EFI_IFR_LAST_OPCODE) || (Curr->OpcodeByte == 0)) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "invalid opcode 0x%X in output at offset 0x%X", + (UINT32) Curr->OpcodeByte, ByteCount + ); + } else if (mOpcodeSizes[Curr->OpcodeByte].Size < 0) { + // + // For those cases where the length is variable, the size is negative, and indicates + // the miniumum size. + // + if ((mOpcodeSizes[Curr->OpcodeByte].Size * -1) > Count) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "insufficient number of bytes written for %s at offset 0x%X", + mOpcodeSizes[Curr->OpcodeByte].Name, + ByteCount + ); + } + } else { + // + // Check for gaps + // + if (mOpcodeSizes[Curr->OpcodeByte].Size == 0) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "invalid opcode 0x%X in output at offset 0x%X", + (UINT32)Curr->OpcodeByte, + ByteCount + ); + } else { + // + // Check size + // + if (mOpcodeSizes[Curr->OpcodeByte].Size != Count) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "invalid number of bytes (%d written s/b %d) written for %s at offset 0x%X", + Count, + mOpcodeSizes[Curr->OpcodeByte].Size, + mOpcodeSizes[Curr->OpcodeByte].Name, + ByteCount + ); + } + } + } + // + // Skip to next opcode + // + while (Count > 0) { + ByteCount++; + if (Curr == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "last opcode written has invalid length"); + break; + } + Curr = Curr->Next; + Count--; + } + } + } +} + +VfrOpcodeHandler::~VfrOpcodeHandler( + ) +/*++ + +Routine Description: + Destructor for the VFR opcode handler. Free up memory allocated + while parsing the VFR script. + +Arguments: + None + +Returns: + None + +--*/ +{ + IFR_BYTE *Curr; + IFR_BYTE *Next; + // + // Free up the IFR bytes + // + Curr = mIfrBytes; + while (Curr != NULL) { + Next = Curr->Next; + free (Curr); + Curr = Next; + } +} + +int +VfrOpcodeHandler::AddOpcodeByte ( + UINT8 OpcodeByte, + UINT32 LineNum + ) +/*++ + +Routine Description: + This function is invoked by the parser when a new IFR + opcode should be emitted. + +Arguments: + OpcodeByte - the IFR opcode + LineNum - the line number from the source file that resulted + in the opcode being emitted. + +Returns: + 0 always + +--*/ +{ + UINT32 Count; + + FlushQueue(); + // + // Now add this new byte + // + mQueuedOpcodeByte = OpcodeByte; + mQueuedLineNum = LineNum; + mQueuedOpcodeByteValid = 1; + return 0; +} + +VOID +VfrOpcodeHandler::AddByte ( + UINT8 ByteVal, + UINT8 KeyByte + ) +/*++ + +Routine Description: + This function is invoked by the parser when it determines + that more raw IFR bytes should be emitted to the output stream. + Here we just queue them up into an output buffer. + +Arguments: + ByteVal - the raw byte to emit to the output IFR stream + KeyByte - a value that can be used for debug. + +Returns: + None + +--*/ +{ + // + // Check for buffer overflow + // + if (mQueuedByteCount > MAX_QUEUE_COUNT) { + Error (PROGRAM_NAME, 0, 0, NULL, "opcode queue overflow"); + } else { + mQueuedBytes[mQueuedByteCount] = ByteVal; + mQueuedKeyBytes[mQueuedByteCount] = KeyByte; + mQueuedByteCount++; + } +} + +int +VfrOpcodeHandler::FlushQueue ( + ) +/*++ + +Routine Description: + This function is invoked to flush the internal IFR buffer. + +Arguments: + None + +Returns: + 0 always + +--*/ +{ + UINT32 Count; + UINT32 EmitNoneOnePair; + + EmitNoneOnePair = 0; + // + // If the secondary varstore was specified, then we have to emit + // a varstore-select-pair opcode, which only applies to the following + // statement. + // + if (mSecondaryVarStoreIdSet) { + mSecondaryVarStoreIdSet = 0; + // + // If primary and secondary are the same as the current default + // varstore, then we don't have to do anything. + // Note that the varstore-select-pair only applies to the following + // opcode. + // + if ((mPrimaryVarStoreId != mSecondaryVarStoreId) || (mPrimaryVarStoreId != mDefaultVarStoreId)) { + IAddByte (EFI_IFR_VARSTORE_SELECT_PAIR_OP, 'O', mQueuedLineNum); + IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), 'L', 0); + IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0); + IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0); + IAddByte ((UINT8)mSecondaryVarStoreId, 0, 0); + IAddByte ((UINT8)(mSecondaryVarStoreId >> 8), 0, 0); + } + } else if (mPrimaryVarStoreIdSet != 0) { + mPrimaryVarStoreIdSet = 0; + if (mDefaultVarStoreId != mPrimaryVarStoreId) { + // + // The VFR statement referenced a different variable store + // than the last one we reported. Insert a new varstore select + // statement. + // + IAddByte (EFI_IFR_VARSTORE_SELECT_OP, 'O', mQueuedLineNum); + IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT), 'L', 0); + IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0); + IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0); + mDefaultVarStoreId = mPrimaryVarStoreId; + } + } + // + // Likely a new opcode is being added. Since each opcode item in the IFR has + // a header that specifies the size of the opcode item (which we don't + // know until we find the next opcode in the VFR), we queue up bytes + // until we know the size. Then we write them out. So flush the queue + // now. + // + if (mQueuedOpcodeByteValid != 0) { + // + // Add the previous opcode byte, the length byte, and the binary + // data. + // + IAddByte (mQueuedOpcodeByte, 'O', mQueuedLineNum); + IAddByte ((UINT8)(mQueuedByteCount + 2), 'L', 0); + for (Count = 0; Count < mQueuedByteCount; Count++) { + IAddByte (mQueuedBytes[Count], mQueuedKeyBytes[Count], 0); + } + mQueuedByteCount = 0; + mQueuedOpcodeByteValid = 0; + } + return 0; +} + +int +VfrOpcodeHandler::IAddByte ( + UINT8 ByteVal, + UINT8 KeyByte, + UINT32 LineNum + ) +/*++ + +Routine Description: + This internal function is used to add actual IFR bytes to + the output stream. Most other functions queue up the bytes + in an internal buffer. Once they come here, there's no + going back. + + +Arguments: + ByteVal - value to write to output + KeyByte - key value tied to the byte -- useful for debug + LineNum - line number from source file the byte resulted from + +Returns: + 0 - if successful + 1 - failed due to memory allocation failure + +--*/ +{ + IFR_BYTE *NewByte; + NewByte = (IFR_BYTE *)malloc (sizeof (IFR_BYTE)); + if (NewByte == NULL) { + return 1; + } + memset ((char *)NewByte, 0, sizeof (IFR_BYTE)); + NewByte->OpcodeByte = ByteVal; + NewByte->KeyByte = KeyByte; + NewByte->LineNum = LineNum; + // + // Add to the list + // + if (mIfrBytes == NULL) { + mIfrBytes = NewByte; + } else { + mLastIfrByte->Next = NewByte; + } + mLastIfrByte = NewByte; + mBytesWritten++; + return 0; +} + +VOID +WriteStandardFileHeader ( + FILE *OutFptr + ) +/*++ + +Routine Description: + This function is invoked to emit a standard header to an + output text file. + +Arguments: + OutFptr - file to write the header to + +Returns: + None + +--*/ +{ + UINT32 TempIndex; + for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) { + fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]); + } + // + // Write out the VFR compiler version + // + fprintf (OutFptr, "// VFR compiler version " VFR_COMPILER_VERSION "\n//\n"); +} diff --git a/Tools/Source/TianoTools/VfrCompile/VfrServices.h b/Tools/Source/TianoTools/VfrCompile/VfrServices.h new file mode 100644 index 0000000000..6b8c560d63 --- /dev/null +++ b/Tools/Source/TianoTools/VfrCompile/VfrServices.h @@ -0,0 +1,227 @@ +/*++ + +Copyright (c) 2004, 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. + +Module Name: + + VfrServices.h + +Abstract: + + Prototypes and defines for routines and classes used by the + EFI VFR compiler. + +--*/ + +#ifndef _VFR_SERVICES_H_ +#define _VFR_SERVICES_H_ + +class VfrOpcodeHandler +{ +public: + VfrOpcodeHandler ( + VOID + ) + /*++ + +Routine Description: + Constructor for the VFR opcode handling class. + +Arguments: + None + +Returns: + None + +--*/ + ; + ~VfrOpcodeHandler ( + VOID + ) + /*++ + +Routine Description: + Destructor for the VFR opcode handler. Free up memory allocated + while parsing the VFR script. + +Arguments: + None + +Returns: + None + +--*/ + ; + void + WriteIfrBytes ( + VOID + ) + /*++ + +Routine Description: + This function is invoked at the end of parsing. Its purpose + is to write out all the IFR bytes that were queued up while + parsing. + +Arguments: + None + +Returns: + None + +--*/ + ; + int + AddOpcodeByte ( + UINT8 OpcodeByte, + UINT32 LineNum + ) + /*++ + +Routine Description: + This function is invoked by the parser when a new IFR + opcode should be emitted. + +Arguments: + OpcodeByte - the IFR opcode + LineNum - the line number from the source file that resulted + in the opcode being emitted. + +Returns: + 0 always + +--*/ + ; + void + AddByte ( + UINT8 ByteVal, + UINT8 KeyByte + ) + /*++ + +Routine Description: + This function is invoked by the parser when it determines + that more raw IFR bytes should be emitted to the output stream. + Here we just queue them up into an output buffer. + +Arguments: + ByteVal - the raw byte to emit to the output IFR stream + KeyByte - a value that can be used for debug. + +Returns: + None + +--*/ + ; + void + SetVarStoreId ( + UINT16 VarStoreId + ) + /*++ + +Routine Description: + This function is invoked by the parser when a variable is referenced in the + VFR. Save the variable store (and set a flag) so that we can later determine + if we need to emit a varstore-select or varstore-select-pair opcode. + +Arguments: + VarStoreId - ID of the variable store referenced in the VFR + +Returns: + None + +--*/ + ; + void + SetSecondaryVarStoreId ( + UINT16 VarStoreId + ) + /*++ + +Routine Description: + This function is invoked by the parser when a secondary variable is + referenced in the VFR. Save the variable store (and set a flag) so + that we can later determine if we need to emit a varstore-select or + varstore-pair opcode. + +Arguments: + VarStoreId - ID of the variable store referenced in the VFR + +Returns: + None + +--*/ + ; + +/* */ +private: + int + FlushQueue ( + VOID + ) + /*++ + +Routine Description: + This function is invoked to flush the internal IFR buffer. + +Arguments: + None + +Returns: + 0 always + +--*/ + ; + int + IAddByte ( + UINT8 ByteVal, + UINT8 KeyByte, + UINT32 LineNum + ) + /*++ + +Routine Description: + This internal function is used to add actual IFR bytes to + the output stream. Most other functions queue up the bytes + in an internal buffer. Once they come here, there's no + going back. + + +Arguments: + ByteVal - value to write to output + KeyByte - key value tied to the byte -- useful for debug + LineNum - line number from source file the byte resulted from + +Returns: + 0 - if successful + 1 - failed due to memory allocation failure + +--*/ + ; + +/* */ +private: + IFR_BYTE *mIfrBytes; + IFR_BYTE *mLastIfrByte; + UINT32 mQueuedByteCount; + UINT32 mBytesWritten; + UINT32 mQueuedLineNum; + UINT8 mQueuedBytes[MAX_QUEUE_COUNT]; + UINT8 mQueuedKeyBytes[MAX_QUEUE_COUNT]; + UINT8 mQueuedOpcodeByte; + UINT32 mQueuedOpcodeByteValid; + UINT16 mPrimaryVarStoreId; + UINT8 mPrimaryVarStoreIdSet; + UINT16 mSecondaryVarStoreId; + UINT8 mSecondaryVarStoreIdSet; + UINT16 mDefaultVarStoreId; +}; + +#endif // #ifndef _VFR_SERVICES_H_ diff --git a/Tools/Source/TianoTools/VfrCompile/build.gcc b/Tools/Source/TianoTools/VfrCompile/build.gcc new file mode 100644 index 0000000000..b6641721f4 --- /dev/null +++ b/Tools/Source/TianoTools/VfrCompile/build.gcc @@ -0,0 +1,10 @@ +../../../bin/antlr -CC -e3 -ck 3 -o . VfrCompile.g +../../../bin/dlg -C2 -i -CC -o . parser.dlg +g++ -mno-cygwin -c -I -I. -I../Pccts/h -g -O0 ../Pccts/h/AParser.cpp +g++ -mno-cygwin -c -I. -I../Pccts/h -g -O0 ../Pccts/h/ATokenBuffer.cpp +g++ -mno-cygwin -c -I. -I../Pccts/h -g -O0 ../Pccts/h/DLexerBase.cpp +g++ -mno-cygwin -c -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ -I../Common -I$WORKSPACE/MdePkg/Include/ -I$WORKSPACE/MdePkg/Include/Ia32 -I. -I../Pccts/h -g -O0 VfrCompile.cpp +g++ -mno-cygwin -c -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ -I../Common -I$WORKSPACE/MdePkg/Include/ -I$WORKSPACE/MdePkg/Include/Ia32 -I. -I../Pccts/h -g -O0 VfrServices.cpp +g++ -mno-cygwin -c -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ -I../Common -I$WORKSPACE/MdePkg/Include/ -I$WORKSPACE/MdePkg/Include/Ia32 -I. -I../Pccts/h -g -O0 DLGLexer.cpp +g++ -mno-cygwin -c -I"../Common/" -I$WORKSPACE/MdePkg/Include/Protocol/ -I$WORKSPACE/MdePkg/Include/Common/ -I../Common -I$WORKSPACE/MdePkg/Include/ -I$WORKSPACE/MdePkg/Include/Ia32 -I. -I../Pccts/h -g -O0 EfiVfrParser.cpp +g++ -mno-cygwin -o VfrCompile *.o -L../Library-mingw -lCommon diff --git a/Tools/Source/TianoTools/VfrCompile/build.xml b/Tools/Source/TianoTools/VfrCompile/build.xml new file mode 100644 index 0000000000..217c4075cc --- /dev/null +++ b/Tools/Source/TianoTools/VfrCompile/build.xml @@ -0,0 +1,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Unsupported Operating System + Please Contact Intel Corporation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/TianoTools/build.xml b/Tools/Source/TianoTools/build.xml new file mode 100644 index 0000000000..8a7b3badc2 --- /dev/null +++ b/Tools/Source/TianoTools/build.xml @@ -0,0 +1,96 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/Source/Tools.msa b/Tools/Source/Tools.msa new file mode 100644 index 0000000000..303381722e --- /dev/null +++ b/Tools/Source/Tools.msa @@ -0,0 +1,72 @@ + + + + + Tools + BASE + USER_DEFINED + 5d6c499e-53fd-430e-9285-2d7811b924e8 + 2.0 + This is the EFI/Tiano Tool Resources Module + + This Module provides the EFI/Tiano Tools that are used to create EFI/Tiano + Modules and Platform Binary Files (PBF) + These tools require compilation only once if the Developer Workstation and + the Developer's choice of HOST tool chain are stable. If the developer + updates either the OS or the HOST tool chain, these tools should be rebuilt. + + Copyright 2005-2006, 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. + + + + Java + Perl + + + FrameworkDatabase.db + cygwin_tools.txt + desktop_efi_flags.txt + embedded_efi_flags.txt + gcc_tools.txt + global_efi_flags.txt + intel_tools.txt + mobile_efi_flags.txt + msft_tools.txt + my_efi_flags.txt + node.txt + server_efi_flags.txt + target.txt + tools_def.txt + winddk_tools.txt + cpptasks.jar + frameworktasks.jar + GenBuild.jar + + + Base + + + + + + + + + + diff --git a/Tools/ToolResources.msa b/Tools/ToolResources.msa new file mode 100644 index 0000000000..4347771b32 --- /dev/null +++ b/Tools/ToolResources.msa @@ -0,0 +1,58 @@ + + + + + ToolResources + BASE + CUSTOM_BUILD + 5d6c499e-53fd-430e-9285-2d7811b924e8 + 2.0 + This is the EFI/Tiano Tool Resources Module + This Module provides the EFI/Tiano Tools and resources that are used to create EFI/Tiano Modules and Platform Binary Files (PBF) These resources and tools do not require compilation. (The three JAR files are provided, Pre-compiled, and do not require additional compilation, the sources are provided, but will not be built under normal procedures. + Copyright 2005-2006, 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. + 2006-03-30 10:05 + + + Java + Perl + + + inf2msa.pl + mkspd.pl + mkdb.pl + FrameworkDatabase.db + cygwin_tools.txt + desktop_efi_flags.txt + embedded_efi_flags.txt + gcc_tools.txt + global_efi_flags.txt + intel_tools.txt + mobile_efi_flags.txt + msft_tools.txt + my_efi_flags.txt + node.txt + server_efi_flags.txt + target.txt + tools_def.txt + winddk_tools.txt + cpptasks.jar + frameworktasks.jar + GenBuild.jar + + + Base + + + + + diff --git a/Tools/Tools.spd b/Tools/Tools.spd new file mode 100644 index 0000000000..5fd0a381f4 --- /dev/null +++ b/Tools/Tools.spd @@ -0,0 +1,38 @@ + + + + + Tools + 53f84ca0-53fe-4412-b4e7-dcec602e1d49 + 0.1 + TianoCore.org EFI Tiano Tools + This package provides the tools needed to create EFI Tiano platform binary files (PBF) and EFI Tiano Modules that can be incorporated into a PBF. Source Code is provided for all C and Java applications. This package also provides the directory structure for holding configuration files. + Copyright (c) 2006, 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. + 2006-02-24 14:49 + http://www.TianoCore.org + MIXED + + + + + diff --git a/Tools/XMLSchema/FDPManifest.xsd b/Tools/XMLSchema/FDPManifest.xsd new file mode 100644 index 0000000000..f6b3715426 --- /dev/null +++ b/Tools/XMLSchema/FDPManifest.xsd @@ -0,0 +1,376 @@ + + + + + This schema defines FDP Manifest + + + + + + At the top level of the Manifest we have four sections: + Header, Private, Public and Contents. + + + + + + + + + + + + + The Header contains some three elements that can + uniquely identify this package (PackageName, Guid, Version) as well as several + fields that identify the licensing and compyright status of the contents of the + package. The rest of the fields are there to idenify who created the package and + when it was made. The buid fields are here to identify when the package was created, + not when the package was compiled. + + + + + + + + + + + + + + + + + + + + + + + + + + + The Build number is an integer that is meant to represent the exact + build of the package. + + + + + In the Type field we can record what kinds of modules are contained + in the package. The possibilities are source, binary and mixed (both source and + binary.) + + + + + + + + + + + + + + + + + + + + + + The build target is used to record what target architecture the + modules within this package were compiled for. + + + + + In the creator field, we can record the name, user id, and email + address of the person who created this package. + + + + + + + + + + + + + In the Modifier field, we can record the name, user id, and email + address of the person who changed/updated or modified this package. + + + + + + + + + + + + + + The name of the company, organization or individual that created or + distributes the package. + + + + + This is the place to record the name and DNS name of the computer on + which the package was created. + + + + + + + + + + + + The package may be Debug or Production. + + + + + + + + + + + We may identify the quality level of the package here. + + + + + + + + + + + + + + + + + + This is the directory, relative to the root of the workspace, where + the package will be installed by default. + + + + + + + + + + + We can track the pakages that this package provides (these are the + packages contained in this pacakge.) We also record which packages are required by + this package. + + + + + + + + + + + This is a list of the packages that this package requires to be + installed in the workspace for package to function and/or build correctly. In the + case of source packages, these are the necessary dependencies for successful + build-time operation of the package. For binary packages these dependencies are + necessary for successful runtime operation. + + + + + + This tag is used in the Framework Package + Database File to track individual package information. The Path is a + relative path to the SPD File. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The list of dependencies that the package fulfills. + + + + + + This tag is used in the Framework Package + Database File to track individual package information. The Path is a + relative path to the SPD File. + + + + + + + + + + + + + + + + A library. It can be provided by or required by this or other packages. + + + + + + + + + + + + + A protocol. It can be provided by or required by this or other packages. + + + + + + + + + + + + + + + + + + + + + + + + + The Private section is a place where the files are listed that should + not be seen by the users of this package. + + + + + + + + + + The Public section is a list of files that are meant to be seen by + the users of the package. + + + + + + + + + + This is a list of all the files within this package. Each file is + identified by its path relative to the workspace root. + + + + + + + + + + Specify a filename including the path + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/XMLSchema/FrameworkDataElements.xsd b/Tools/XMLSchema/FrameworkDataElements.xsd new file mode 100644 index 0000000000..bbc75d9729 --- /dev/null +++ b/Tools/XMLSchema/FrameworkDataElements.xsd @@ -0,0 +1,1479 @@ + + + + + This schema defines EFI and Framework Data Elements + + + + + + Abstract is valid for all Description Files + This section is required. This is a single sentence to describe the module and will be used in sample files as the abstract data in the header comment section. + + + + + + + + + + + + This is a sub-element of AntTask + This is an ant command that will be inserted into a biuld sequence. Since ant commands are valid XML statements, special care must be taken to use the correct tokens for reserved words and escape quote characters. + + + + + + + + + + + + + + + + This is a sub-element of UserDefinedAntTasks + Define a file that contains one or more ant tasks that are to be added into or replacing of sequences of build steps. These files will be called using the ant-call task on a file name. These files must be valid apache-ant formatted task files. + + + + + + + + + + + + BaseName is valid for all Description Files + We need to be able to permit different attributes for every basename + + + + + + + + + + + + BootModes is valid for all Description Files + This is a list of BootModes Supported by the Module + + + + + + + + + + + + + + BuildOptions is valid for MBD and FPD files. + Specific Build Options, by Tool Chain, than should be applied, overriding any global options + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + C_Name is valid for all Description Files + + + + + ComponentName is valid for all Description Files + + + + + Describe the valid Framework Component Type + + + + + A conditional expression that must be evaluated to determine whether a feature is implemented or not. The expression must be either numeric, string or boolean. + + + + + + + + + + + A conditional expression that must be evaluated to determine whether a feature is implemented or not. The expression must be either numeric, string or boolean. + + + + + + + + + + + + + + + This is a list of DataHubRecord elements. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The Name of the Database, "FrameworkDatabase" + + + + + + + + + + + + The default setting of a PCD entry. + + + + + + + + + + This section is required for new modules and libraries and must contain more information than the Abstract. + + + + + + + + + + This is a list of Events + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Module has an event that is waiting to be signaled. Event is named by GUID. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This is a child of MSA files, both Library and Module. + This is a list of Extern statements, right now, only Driver Binding information is provided. + + + + + + + + + Driver Module + + + + + + + Library Module + + + + + + + Allow multiple entries for DriverBinding, ComponentName, DriverConfig and DriverDiag elements. For ComponentName, DriverConfig and/or DriverDiag - you must have a 1:1 mapping to DriverBinding if the element is defined. + Permit User Defined Extern Tags + + + + + + + + + Module Call Backs + + + + + + + + + + + + + + + + + + Driver Module + + + + + + + Library Module + + + + + + + Allow multiple entries for DriverBinding, ComponentName, DriverConfig and DriverDiag elements. For ComponentName, DriverConfig and/or DriverDiag - you must have a 1:1 mapping to DriverBinding if the element is defined. + Permit User Defined Extern Tags + + + + + + + + + Module Call Backs + + + + + + + + + + + + + + + + + + + Define the FFS File attributes within a sections and containing sections information + + + + + + + + + + + + + + + + + + Describe the valid content of a filename + + + + + + + + + + + + This is a list of Filenames + + + + + + + + + + + + + + + + + + Describe the list of a Formset elements + + + + + + Describe the valid content of a Formset + + + + + + + + + + + + + + + Describe the valid content of a Formset + + + + + + + + + + + + + + + + + + + Describe the valid content of a GUID + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Describe the valid content of a PCD GUID element + + + + + + + + + + + + + + + + + + + Describe the valid content of a PCD GUID element + + + + + + + + + + + + + + + + + + + + + + + + This section is used to describe how a GUID, PPI or PROTOCOL is to be used within the context of PCDs. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + One or More Package Names or Arch sections is required. Includes are not files, but paths to where header files are located. + + + + + + + + + + + + + + + + + + + Different Instances of Libraries + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Define in the MSA and/or SPD, what class of library is being produced by a library module - for components, it can also specify what class of library is consumed. + + + + + + + + + + + + This element defines a class of library, along with the path to the Include Header for this library + + + + + + + + + + + This section defines what Classes of Libraries that this library belongs to. A Library may belong to multiple different library classes. + + + + + + + + + + This section defines what Classes of Libraries that this library belongs to. A Library may belong to multiple different library classes. + + + + + + + + + + + + + + + + + + + + This is record format for a Module entry in the Framework Database file. + + + + This describes the fields in an Module record in the Framework Database. The Path field is relative to the workspace to Module Surface Area (MSA) files. + + + + + + + + + + + + + This tag is used in the Framework Package Database File to track package installation + + + + + + + + + + This is the valid content of a Module Name + + + + + + + + + + + + Describe the valid EFI Phase that the Module is designed to execute under. + + + + + + + + + Describe the valid content of a Surface Area Package Description (SPD) file + + + + + + + + + + + + + + + Describe the valid content of a Surface Area Package Description (SPD) file + + + + + + + + + + + + + + + + + + + Define where we want our output to go. The Attribute, IntermediateDirectories, default MODULE, says that intermediate files will be local to the module, versus a unified directory structure. + + + + + + + + + + + + + + + + + + + Child of Module Surface Area documents, MSA and MBD files, Library Modules and Other Modules + One or more PcdData or PcdBuildData Elements Only one type is permitted + + + + + + This is a child of PCDs and can occur in the MSA and MBD files. + This is date element is used in the Module Surface Area (MSA) file and contains references to be used by a Platform Build + There is ONE required Attribute, ItemType + + + + + + + + + + + + + + + + Max Number of Bytes of the data. + + + + + + + + + + + + + + + + + + + + + + + + This tag is used in the Package Surface Area Description File to track package dependencies for a module + + + + + + + + + + + This defines the minimum header file needed to support a given ModuleType. + + + + + + + + + + This tag is used in the Framework Package Database File to track all packages installed in a workspace. + + + + + + This tag is used in the Framework Package Database File to track individual package information. The Path is a relative path to the SPD File. + + + + + + + + + + + + + + + + + + This tag is used in the Package Surface Area Description File to track package dependencies for a module + + + + + + + + + + + + + Describe the valid content of a filename + + + + + + + + + + + + Child of Framework Platform Description (FPD) + We permit the FPD to use an external XML file for PCD information or else the information must be contained within the XML data element, PcdBuildData. + + + + + + + Child of PcdBuildDeclarations + This is date element is used in the platform build description file and contains valid data for a Platform Build + There is ONE required Attribute, ItemType + + + + + + + This as a unique identifier defined for either this name space. + The Target Attribute may be used to define a Target name space, such as PCI. + + + + + + + + + + + + This specifies the size of the Pcd Datum. It is either 8, 16, 32 or 64 bits for values, 1 bit for BOOLEAN and variable length for elements defined as VOID* + + + + + This Bit means that the Variable data is associated with HII + + + + + This bit enables the Vital Product Data area within flash for maintaining PCD information + + + + + This is only applicable to ItemType DYNAMIC_EX + + + + + + + + This element is a list of two entries per line, the first should be an integer, while the second entry should be a string value + + + + + + + + This section is for a list of SkuData Elements, ID and Value + + + + + + + + + + + + This value comes from a production line database, and has nothing to do with the number of SkuData IDs that have been defined. + + + + + This is the specific Sku ID for this build. + + + + + Max Number of Bytes of the data. + + + + + + + + + + + This is the Variable's GUID if and only if HII is enabled. + + + + + This is the C Name for the Variable, and is valid if and only HII is enabled. + + + + + If HII is enabled, This is the offset into the variable data entry, If Vpd is enabled, then it's the Offset into the VPD area of the image defined by platform manufacturer, if neither HII nor Vpd are enabled, it's the offset into the PCD Data Area. HII and VPD can never be enabled at the same time (as of the date of this document.) + + + + + This field is only valid if AlternateNameSpaceEnable is true. + + + + + + + + + + + + + Child of Package Surface Area Description (SPD) + This permits entering information about a package's PCD information + + + + + + This is the valid content of the PCD table of a Module. The contents may not be wired at build time, and these only refer to Platform Build values, not modules. + This element is valid for PcdInfo.xml and FPD files. + There is ONE required Attribute, ItemType + + + + + + + + + + + + + + + + Max Number of Bytes of the data. + + + + + + + + + + + + + + + + + + + + + + + Database Entry to locate the Platform Build Tips - path to FPD file. + + + + + + Define the Name of a Platform + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Provide for one or more Ppi or PpiNotify sections. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + If either Protocol or ProtocolNotify sections are needed, one or more of them should be specified within this section + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Sections refers to the Firmware Filesystem sections, PE32, UI, VER, DXS, etc. and how they are made + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Multiple Filenames may be specified, and they may also be scoped to a specific Architecture. + + + + + + + + + + + + + + + + + + This string is used to provide the name and version of the Specification that the component conforms to. + + + + + + + + + + + + This is list of System Table elements. + + + + + + + + + + + + + + + + + + + + This is a sub-element of BuildOptions + Permit Users to define their own custom ANT tasks. + + + + + + + + + + A list of EFI Variables described by GUID string pair. + + + + + + This is an EFI Variable Entry + + + + + + + + This entry represents the Hex Byte Offset {0x0, 0xn} to where the data starts. + + + + + This entry represents the Location of the Starting Bit {0,8} of the start of Data. A value of zero or 1 indicates that there is no BitOffset into the byte. + + + + + + + + + + + This number represents the number of bits to use {0, 7} starting at the BitOffset. A value of 0 indicates that the entire Byte should be used. + + + + + + + + + + + + + + + + + + This is an EFI Variable Entry + + + + + + + + This entry represents the Hex Byte Offset {0x0, 0xn} to where the data starts. + + + + + This entry represents the Location of the Starting Bit {0,8} of the start of Data. A value of zero or 1 indicates that there is no BitOffset into the byte. + + + + + + + + + + + This number represents the number of bits to use {0, 7} starting at the BitOffset. A value of 0 indicates that the entire Byte should be used. + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/XMLSchema/FrameworkDataTypes.xsd b/Tools/XMLSchema/FrameworkDataTypes.xsd new file mode 100644 index 0000000000..402d2b2752 --- /dev/null +++ b/Tools/XMLSchema/FrameworkDataTypes.xsd @@ -0,0 +1,1196 @@ + + + + + This schema defines EFI and Framework Attribute and Data Types. Only simpleType and attributeGroups are specified in this file. + + + + + FIRMWARE: Define a block name to be BLOCK[A-F0-9]{2} + + + + + + + + This describes what boot modes can be set (produced) or what boot modes can be supported, as defined in the Module Surface Area Specification + + + + + BOOT_WITH_FULL_CONFIGURATION + + + + + BOOT_WITH_MINIMAL_CONFIGURATION + + + + + BOOT_ASSUMING_NO_CONFIGURATION_CHANGES + + + + + BOOT_WITH_FULL_CONFIGURATION_PLUS_DIAGNOSTICS + + + + + BOOT_WITH_DEFAULT_SETTINGS + + + + + BOOT_ON_S2_RESUME + + + + + BOOT_ON_S3_RESUME + + + + + BOOT_ON_S4_RESUME + + + + + BOOT_ON_S5_RESUME + + + + + BOOT_ON_FLASH_UPDATE + + + + + BOOT_IN_RECOVERY_MODE + + + + + + + This describes the Boot Mode Usage Attributes, as defined in the Module Surface Area Specification + + + + + Supports the Boot Mode + + + + + Supports the Boot Mode on some execution path + + + + + Always changes the Boot Mode + + + + + Sometimes changes the Boot Mode + + + + + + + These are the supported EFI/Framework Execution Phases + + + + + + + + + + + + + + + + + + Conditional Targets are Other FeatureFlag Identifiers + + + + + + This describes the Data Hub Usage Attributes, as defined in the Module Surface Area Specification + + + + + The module always consumes a data hub entry via registering a filter driver. + + + + + The module will use a data hub entry if it exists via registering a filter driver. + + + + + The module always logs data into the data hub. + + + + + The module will log data into the data hub under certain circumstances + + + + + DataHub is produced and consumed only by this module + + + + + + + Date Format is YYYY-MM-DD HH:MM (24hr time format) + + + + + + + + The DefaultValue is a union of a string and an integer. + + + + + + + + + + + + + + + + + + + + + + + This describes the Supported Event Groups, as defined in the Module Surface Area Specification + + + + + + + + + + + + This describes the Event Usage Attributes, as defined in the Module Surface Area Specification + + + + + A module registers a notification function and requires it to be executed for the module to fully function. + + + + + A module registers a notification function and utilizes it if it's signaled. + + + + + A module will always signal the event. + + + + + A module will sometimes signal the event. + + + + + Event is produced and consumed only by this module + + + + + + + This defines the output types: Relocatable (REL,) Non-Relocatable (NREL,) Execute in Place (XIP) or Position Independent Code (PIC) + + + + + + + + + + + C Identifier Name for the Extern data as defined in the Module Surface Area Specification + + + + + + + + This describes the Extern Usage Attributes, as defined in the Module Surface Area Specification + + + + + The EXTERN is always imported by the module + + + + + The EXTERN is always exported by the module + + + + + + + This describes the FileName Usage Attributes, as defined in the Module Surface Area Specification + + + + + Module requires a file named GUID in an FV + + + + + Module will use a file named GUID in an FV if it is present + + + + + Module Always produces a file named GUID in an FV + + + + + Module sometimes produces a file named GUID in an FV + + + + + Filename is produced and consumed only by this module + + + + + + + This describes the Formset Usage Attributes, as defined in the Module Surface Area Specification + + + + + The Formset is always registered into HII by the module + + + + + Some execution paths through the modules register forms into HII + + + + + Formset is produced and consumed only by this module + + + + + + + These are the EFI/Framework Component Types defined in the EFI Development Kit (EDK) Getting Started Guide + + + + + + + + + + + + + + + + + + + + + + + + + + + FIRMWARE: Pre-defined Firmware Volume Region Types + + + + + + + + + + + + + + + + This describes the Guid Usage Attributes, as defined in the Module Surface Area Specification + + + + + Module always consumes the GUID + + + + + Module will consume the GUID only if the GUID is present + + + + + Module will always produce the GUID + + + + + Module sometimes produces the GUID + + + + + The default is the GUID that specifies the instance of the package + + + + + Guid is produced and consumed only by this module + + + + + + + Type of HOB that is being produced or consumed, as specified in the Module Surface Area Specification. + + + + + EFI_HOB_TYPE_HANDOFF + + + + + EFI_HOB_TYPE_MEMORY_ALLOCATION Note: The BaseName of the GUID is also required + + + + + EFI_HOB_TYPE_RESOURCE_DESCRIPTOR + + + + + EFI_HOB_TYPE_GUID_EXTENSION Note: The BaseName of the GUID is also required. + + + + + EFI_HOB_TYPE_FV + + + + + EFI_HOB_TYPE_CPU + + + + + EFI_HOB_TYPE_PEI_MEMORY_POOL + + + + + EFI_HOB_TYPE_CV + + + + + + + This describes the Hob Usage Attributes, as defined in the Module Surface Area Specification + + + + + The HOB must be present in the system + + + + + The HOB will be used if it's present in the system + + + + + The HOB is always produced by the module + + + + + The HOB will sometimes be produced by the module. + + + + + HOB is produced and consumed only by this module + + + + + + + This describes the Library Usage Attributes, as defined in the Module Surface Area Specification + + + + + A module always consumes the library. This Guid represents the class of the library. + + + + + + + + The default is the GUID that specifies the instance of the library. + + + + + Library is produced and consumed only by this module + + + + + + + These are the supported Framework Module Types + + + + + Module only depends on things in the MDE package and is environment neutral + + + + + Module is the Security Section and depends on catching the reset vectory + + + + + Module is the PEI Core + + + + + Module is a PEIM and depends on the PEI Services Table + + + + + Module is the DXE Core + + + + + Module is a DXE Driver and depends on the EFI Boot Services, EFI Runtime Services and the DXE Service Table + + + + + Module is a DXE Driver and depends on the EFI Boot Services, EFI Runtime Services and the DXE Service Table. The module runs after ExitBootServices and produces CreateEvent EventGroupExitBootServices and EventGroupVirtualAddressChange. Code written in this module can run in physical or virtual mode. + + + + + Module is a DXE Driver and depends on the EFI Boot Services, EFI Runtime Services and the DXE Service Table. The module runs after ExitBootServices and produces CreateEvent EventGroupExitBootServices and EventGroupVirtualAddressChange. Code written in this module can run in physical AND in virtual mode. + + + + + Module is a DXE Driver and depends on the EFI Boot Services, EFI Runtime Services and the DXE Service Table. The module also runs in SMM mode and depends on the SMM Service Table. + + + + + The TOOLS ModuleType is to be used for Tiano Tools modules + + + + + Module is a UEFI Driver and depends on the EFI and Service Tables. + + + + + Module is a UEFI Applciation and depens on the EFI and Service Tables. + + + + + Module does not fit into other classifications. The user must have an apriori knowledge of its Usage, and must provide that information to others using this module. + + + + + + + Define a flag to determine whether to put intermediate build files into a directory under the Module, or into a unified tree under the package or platform build trees + + + + + + + + + Packages are either source, binary or mixed packages. + + + + + + + + + + This describes the Package Usage Attributes, as defined in the Module Surface Area Specification + + + + + A module always consumes a package. This GUID represents the class of the package. + + + + + This is the Package we are creating. This GUID represents the class of the package. + + + + + The default is the GUID that specifies the instance of the package. + + + + + + + + + PCD Item is only a build time option and cannot be Dyanmic or Binary patched into the module. + + + + + PCD Item is set to a default value at build time and a binary of the module can be patched to update the value. + + + + + PCD Item is found via a PCD PPI in PEI or a PCD Protocol in DXE. The token that matches the PCD entry is either generated by the build (and is only unique to that build) or is from the default database. This form also implies a build option will be produced for this module that allows the user to pick FixedAtBuild, PatchableInModule or Dynamic. If no Type is specified, it defaults to Dynamic + + + + + PCD Item is found via a PCD PPI in PEI or a PCD Protocol in DXE. The token that matches the PCD entry is either generated by the build (and is only unique to that build) or is from the default database. This form also implies a build option will be produced for this module that allows the user to pick FixedAtBuild, PatchableInModule or Dynamic. If no Type is specified, it defaults to Dynamic + + + + + + + + + + + + + + + + + This describes the PCD FEATURE_FLAG Usage Attributes, as defined in the Module Surface Area Specification + + + + + Item is Always produced + + + + + Item is tagged as the default + + + + + + + + + The PCD Item represents a feature flag for the module. Features can only be selected at build time. Items of type FeatureFlag are used to conditionally construct module surface area that is produced as a result of a buld. + + + + + PCD Item is only a build time option and cannot be Dyanmic or Binary patched into the module. + + + + + PCD Item is set to a default value at build time and a binary of the module can be patched to update the value. + + + + + PCD Item is found via a PCD PPI in PEI or a PCD Protocol in DXE. The token that matches the PCD entry is either generated by the build (and is only unique to that build) or is from the default database. This form also implies a build option will be produced for this module that allows the user to pick FixedAtBuild, PatchableInModule or Dynamic. If no Type is specified, it defaults to Dynamic + + + + + PCD Item is found via a PCD PPI in PEI or a PCD Protocol in DXE. Any PCD token database is supported + + + + + + + The PCD Usage is only relevant to Items tagged with FeatureFlag, as defined in the Module Surface Area Specification + + + + + The PCD entry must always be provide as the build will include the code and the associated Surface Area. + + + + + If the FEATURE_FLAG is TRUE the build will include the code and the associated Surface Area. If the FEATURE_FLAG is FALSE, the code and the associated surface area is not included. + + + + + The PCD Entry is Always included in the build code + + + + + If the FEATURE_FLAG is TRUE the build will include the code and the associated Surface Area. If the FEATURE_FLAG is FALSE, the code and the associated surface area is not included. + + + + + "true" or "false". Indicates the default value for the PCD entry. This is used by the platform wizard to suggest values for a given platform build. + + + + + + + This describes the PPI Notify Usage Attributes, as defined in the Module Surface Area Specification + + + + + Module will consume the PPI if it's produced. Consumption is defined by executing the PPI notify function. + + + + + + + This describes the PPI Usage Attributes, as defined in the Module Surface Area Specification + + + + + Item is Required for the driver to function. This is part of the dependency expression of a module if the item represents a PPI or Protocol + + + + + Item is Consumed by the driver if the Item exists + + + + + Item is Always produced + + + + + Item is Conditionally produced + + + + + Ppi is produced and consumed only by this module + + + + + + + This describes the PROTOCOL Notify Usage Attributes, as defined in the Module Surface Area Specification + + + + + Module will Consume protocol if it's produced. Consumption is defined by executing the protocol notify function. + + + + + + + This describes the PROTOCOL Usage Attributes, as defined in the Module Surface Area Specification + + + + + Item is Required for the driver to function. This is part of the dependency expression of a module if the item represents a PPI or Protocol + + + + + Item is Consumed by the driver if the Item exists + + + + + Item is Always produced + + + + + Item is Conditionally produced + + + + + Protocol Only - Protocol is required by driver binding Start() function to make Start() succeed + + + + + Protocol Only - Protocol is produced by driver binding Start() function if and only if Start() succeeds + + + + + Protocol is produced and consumed only by this module + + + + + + + These are the currently Supportted Architectures type codes + + + + + + + + + + + + + + This describes the System Table Usage Attributes, as defined in the Module Surface Area Specification + + + + + Module requires a GUIDed entry in the system table + + + + + Module will use the GUIDed entry in the system table only if the GUID is present + + + + + Module Always produces a GUIDed entry in the system table + + + + + Module sometimes produces a GUIDed entry in the system table for some of its execution flow + + + + + SystemTable is produced and consumed only by this module + + + + + + + The Token data is union of HexDoubleWordDataType, GuidNaming Convetion and GuidArrayType. + + + + + + Supported Tool Chains are MSFT, INTEL, GCC and CYGWIN + + + + + + + + + + + Describes which way the directory separator is leaning, either \ for WINDOWS or / for UNIX + + + + + + + + + Define how we specify unicode strings + + + + + + + + This describes the Generic Usage Attributes, as defined in the Module Surface Area Specification + + + + + Item is Required for the driver to function. This is part of the dependency expression of a module if the item represents a PPI or Protocol + + + + + Item is Consumed by the driver if the Item exists + + + + + Item is Always produced + + + + + Item is Conditionally produced + + + + + Protocol Only - Protocol is required by driver binding Start() function to make Start() succeed + + + + + Protocol Only - Protocol is produced by driver binding Start() function if and only if Start() succeeds + + + + + Item is Private to the module and cannot be used by other modules + + + + + This is the default value for an Item + + + + + + + Describes the available Variable Offset data types, Bytes:Bits or BitSize + + + + + + + + This describes the Variable Usage Attributes, as defined in the Module Surface Area Specification + + + + + Module requires the variable entry to be set + + + + + Module will use the variable entry if it's set + + + + + Module Always will write the variable + + + + + Module sometimes writes the variable + + + + + Variable is produced and consumed only by this module + + + + + + + + + + + + + This type is to permit adding specific tools and tool arguments for User Defined tools, into the Module Build Description file. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + These attributes are for the Pcds listed in PcdData, PcdEntry and/or PcdBuildData entries. + PcdUsage is only valid for PcdItemTypes = FEATURE_FLAG + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Attributes are either compressable and/or sequence order binding + + + + + + + + + Attributes for Sections, EncapsulationTag, EncapsulationType and OverrideID + + + + + + + + + + + + + + + + + diff --git a/Tools/XMLSchema/FrameworkHeaders.xsd b/Tools/XMLSchema/FrameworkHeaders.xsd new file mode 100644 index 0000000000..3937dc5c84 --- /dev/null +++ b/Tools/XMLSchema/FrameworkHeaders.xsd @@ -0,0 +1,160 @@ + + + + + + + This is the header for the Framework Package Database file. + + + + + + + + + + + + + + + + + + + This is the header for the Component Module Build Description (MBD) file. NOTE: The GUID may be different from the GUID in the MSA file, as the Guid is updated every time the file is changed, as the Guid may change if the contents of the file are changed. + + + + + + + + + + + + + + + + + This is the header for the Library Module Build Description (MBD) file. NOTE: The Guid may be different from the Guid in the MSA file, as the Guid may change when the contents of the file are changed.. + + + + + + + + + + + + + + + + + This is the Component Module Surface Area Description Header - a replacement for INF files. The GUID may change when the contents of the file are changed. + + + + + + + + + + + + + + + + + + + + + This is the Library Module Surface Area Description Header - a replacement for INF files. The Guid may change when the contents of the file are changed. + + + + + + + + + + + + + + + + + + + + + This head is for the Framework Platform Description file (FPD.) + + + + + + Define the Name of a Platform + + + + + + + + + + + + + + + + + + This head is for the Surface Area Package Description file (SPD) The Guid may change when the contents of the file are changed. + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tools/XMLSchema/FrameworkPlatformDataElements.xsd b/Tools/XMLSchema/FrameworkPlatformDataElements.xsd new file mode 100644 index 0000000000..5cbaaca699 --- /dev/null +++ b/Tools/XMLSchema/FrameworkPlatformDataElements.xsd @@ -0,0 +1,357 @@ + + + + + This schema defines EFI and Framework Platform Data Elements that are specific to platform creation. + + + + + + + + + + + + + + + + This element is used specify different name value pairs. + + + + + + + + + + + + This element is used specify different name value pairs. + + + + + + + + + + + + Permit multiple Capsule Sections + + + + + + + + + + + + + We allow specifying the Flash layout in this directory, or we allow specifying a flashmap filename + + + + + + + + + + + + + + + Define contents of the regions in flash. The files and data are placed in the output image in the order they are encountered in this definition. Multiple FlashDeviceImage sections may be defined. Which one the tool should use is specified by Name on the command line. + + + + + + + + + + + This is the Flash Devcie definition List + + + + + + + + + + + + + + + + Define OVERRIDE contents of the regions in flash. Only what is different here from what may defined in other areas (or files) is needed + + + + + + + + + + + This is the Flash Devcie Override Definition list. Only what is different from the previously defined stuff needs to be included. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This element is used specify different name value pairs. + + + + + + + + + + + + This section allows the user to define specific information regarding the FvImage + + + + + + + + + + + + This element is used to specify information in the Platform Description File. + This is a mixed element, allowing the user to specify the name of the MSA file, as well as to optionally specify additional override information. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This defines the required sections of a valid EFI/Tiano binary image + + + + + + + + + + + + + + + The list of EFI_FLASH_AREA Attributes + + + + + + + + + + The list of valid EFI Area Types + + + + + + + + + + + + + + Right now, only EFI_FLASH_MAP_HOB_GUID is defined + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Define the regions and their uses for the device + + + + + + + + + + + + Define the regions and their uses for the device + + + + + + + + + + + diff --git a/Tools/XMLSchema/NamingConvention.xsd b/Tools/XMLSchema/NamingConvention.xsd new file mode 100644 index 0000000000..4f998b827d --- /dev/null +++ b/Tools/XMLSchema/NamingConvention.xsd @@ -0,0 +1,307 @@ + + + + + This schema defines various data types and naming conventions including: base name, filename and directory naming conventions. These are all simple data types. + + + + Base Names must start with an upper case character, followed by one or more alphanumeric characters and/or an optional underscore (_) character followed by one or more alphanumeric characters. Examples: Base_name3, BASE_NAME3, BaseName3 + + + + + + + + C_Names must start with either an underscore (_) character followed by one or more alpha characters, followed by any combination of underscore or alphanumeric characters. + + + + + + + + Directory naming convention is a UNION of DOS an UNIX directory path names + + + + + + Directory naming convention for Windows backslash (\) directory path name + + + + + + + + Directory naming convention for UNIX forwardslash (/) directory path name + + + + + + + + + + + + + This defines what a Filename is: Alphanumeric characters and optional underscore (_) or dash (-) characters, followed by a optional dot and more alphanumeric characters. + + + + + + + + This defines the minimum specification for a GUID Array which is 8 Hex Digits - 4 Hex Digits - 4 Hex Digits - 8 Hex Bytes, the last 16 Hex Digits can be enclosed in sqiggle {} brackets. + + + + + + + + A GUID must contain five different Hexadecimal character sets that are separated by a dash (-) character. + + + + + + + + The GUID data is union of GuidNaming Convetion and GuidArrayType. + + + + + + Define a Hex 64 Bit Value to be 0x[a-f0-9]{16} + + + + + + + + Define a Hex Address, 0x[a-fA-F0-9]{1,16} + + + + + + + + Define a Hex Byte Value to be 0x[a-f0-9]{2} + + + + + + + + Define a Hex Value to be 0x[a-f0-9]+ + + + + + + + + Define a Hex Diget to be 0x[a-f0-9] + + + + + + + + Define a Hex Double Word Value to be 0x[a-f0-9]{8} + + + + + + + + Define a Hex Word Value to be 0x[a-f0-9]{4} + + + + + + + + This defines what a Library name is: alphanumeric characters and optional underscore (_) characters. + + + + + + + + What is a name, any series of alphanumeric characters and one or more underline characters that may occur in any position + + + + + + + + This describes the normal text of a paragraph that can be used in a license or description tag. + + + + + + This defines what a Platform Name is: Alphanumeric characters and optional underscore (_) or dash (-) characters, followed by a dot and more alphanumeric characters. + + + + + + + + This data type requires two or more words + + + + + + + + This defines what a Tool name is: Alphanumeric characters and optional underscore (_) or dash (-) characters, optionally followed by a dot and more alphanumeric characters. + + + + + + + + Definition of a UpperCase Letter type, which can be any combination of upper case characters followed by zero or more underscore and/or uppercase alphanumeric characters + + + + + + + + Definition of a UpperCase Name, which can be any combination of upper case characters followed by zero or more underscore and/or uppercase alphanumeric characters + + + + + + + + Specify a User Name + + + + + + + + %VAR%(Directory)*(File_Names)* + + + + + + + + ($VAR | $( VAR) | ${VAR})(Directory)*(File_Names) + + + + + + + + VariableConvention is a UNION of: $VAR, $( VAR), ${VAR} and %VAR% and Directory and File Names + + + + + + The GUID data is union of GuidNaming Convetion and GuidArrayType. + + + + + + VariableConvention is a UNION of: $VAR, $( VAR), ${VAR} and %VAR% + + + + + + Definition of a DOS Variable Name: %VAR% It must start with an Upper Case character. + + + + + + + + Definition of a UNIX Variable Name: $VAR It must start with an Upper Case character. + + + + + + + + Definition of a UNIX Variable Name: $( VAR1) It must start with an Upper Case character. + + + + + + + + Definition of a UNIX Variable Name: ${ VAR1} It must start with an Upper Case character. + + + + + + + + Definition of a Version Number, which can be any combination of a number followed by zero or more alphanumeric-dot-alphanumeric characters + + + + + + + + Define Zero as a vaild value + + + + + + + + Definition of a Version Number, which can be any combination of a number followed by zero or more alphanumeric-dot-alphanumeric characters + + + + + + diff --git a/Tools/XMLSchema/SurfaceArea.xsd b/Tools/XMLSchema/SurfaceArea.xsd new file mode 100644 index 0000000000..7b309570ae --- /dev/null +++ b/Tools/XMLSchema/SurfaceArea.xsd @@ -0,0 +1,167 @@ + + + + + + + + + This is the valid format for the Package Database File. Note: MsaList is used for Modules that have not yet been included in a package. + + + + + + + + + + + + + This is the valid format for the Framework Platform Description (FPD) File. + + + + + + + + + + + + + + This is the Module Build Description that contains the list of overrides, library instances that can or must be used by the library. + + + + + + + + + + + + + + + + + + + + + + + + + + This is the Module Library Surface Area Description that contains the list of the module's source files, library classes that can or must be used by the module, the Class(es) of the Library that will be supported by the library, the Include Paths, Protocols and Ppi's that are either produced or consued. + + + + + + + + + + + + + + + + + + + + + + + + + + This is the Module Build Description that contains the list of overrides, library instances that can or must be used by the module. + + + + + + + + + + + + + + + + + + + + + + + + + + This is the Module Surface Area Description that contains the list of the module's source files, library classes that can or must be used by the module, the Include Paths, Protocols and Ppi's that are either produced or consued. + + + + + + + + + + + + + + + + + + + + + + + + + + This is valid content for a Package Surface Area Description (SPD) file. + + + + + + + + + + + + + + + + diff --git a/Tools/XMLSchema/SurfaceArea.xsdconfig b/Tools/XMLSchema/SurfaceArea.xsdconfig new file mode 100644 index 0000000000..aa52361510 --- /dev/null +++ b/Tools/XMLSchema/SurfaceArea.xsdconfig @@ -0,0 +1,16 @@ + + + + + org.tianocore + + + diff --git a/Tools/bin/CreateMdkPkg.bat b/Tools/bin/CreateMdkPkg.bat new file mode 100644 index 0000000000..70de527e29 --- /dev/null +++ b/Tools/bin/CreateMdkPkg.bat @@ -0,0 +1,42 @@ +@REM +@REM Copyright (c) 2006, Intel Corporation +@REM All rights reserved. This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@REM +@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +@REM + +REM @echo off + +:check_java +if "%JAVA_HOME%"=="" goto no_jdk +:check_wks +if "%WORKSPACE%"=="" goto no_wks + +set ANT_HOME=%WORKSPACE%\Tools\bin\apache-ant +set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%WORKSPACE%\Tools\bin;%XMLBEANS_HOME%\bin;%PATH% + +call "ant" -f %WORKSPACE%\Tools\Source\CreateMdkPkg\build.xml + +echo DONE + +goto end + +:no_jdk +echo. +echo !!! Please set JAVA_HOME !!! +echo. +goto check_wks + +:no_wks +echo. +echo !!! Please set WORKSPACE !!! +echo. +goto end + +:end +@echo on + diff --git a/Tools/bin/GenBuildFile.bat b/Tools/bin/GenBuildFile.bat new file mode 100644 index 0000000000..323969fa40 --- /dev/null +++ b/Tools/bin/GenBuildFile.bat @@ -0,0 +1,45 @@ +@REM +@REM Copyright (c) 2006, Intel Corporation +@REM All rights reserved. This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@REM +@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +@REM + +@echo off + +@if "%JAVA_HOME%"=="" goto no_jdk +@if "%WORKSPACE%"=="" goto no_wks + +@if "%1"=="-H" (goto usage) +@if "%1"=="-h" (goto usage) else (goto all) + +:usage +@echo. +@echo Generate entrance build.xml for each module under current directory +@echo. +@echo Usage: GenBuildFile.bat - must be executed in the package level directory +@echo. +goto end + +:all + ant -q -f %WORKSPACE%\Tools\bin\GenBuildFile.xml + goto end + +:no_jdk + @echo. + @echo !!! Please set JAVA_HOME !!! + @echo. + @goto end + +:no_wks + @echo. + @echo !!! Please set WORKSPACE !!! + @echo. + @goto end + +:end +@echo on diff --git a/Tools/bin/GenBuildFile.xml b/Tools/bin/GenBuildFile.xml new file mode 100644 index 0000000000..81a2900a92 --- /dev/null +++ b/Tools/bin/GenBuildFile.xml @@ -0,0 +1,18 @@ + + + + + + + + + diff --git a/Tools/bin/MakeDeps.exe b/Tools/bin/MakeDeps.exe new file mode 100644 index 0000000000..b73c3bfaa7 Binary files /dev/null and b/Tools/bin/MakeDeps.exe differ diff --git a/Tools/bin/PackageEditor.bat b/Tools/bin/PackageEditor.bat new file mode 100644 index 0000000000..5a496663b0 --- /dev/null +++ b/Tools/bin/PackageEditor.bat @@ -0,0 +1,47 @@ +@REM +@REM Copyright (c) 2006, Intel Corporation +@REM All rights reserved. This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@REM +@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +@REM + +@echo off + +:check_java +if "%JAVA_HOME%"=="" goto no_jdk +:check_wks +if "%WORKSPACE%"=="" goto no_wks + +set ANT_HOME=%WORKSPACE%\Tools\bin\apache-ant +set XMLBEANS_HOME=%WORKSPACE%\Tools\bin\xmlbeans +set Framework_Tools_Path=%WORKSPACE%\Tools\bin + +set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%WORKSPACE%\Tools\bin;%XMLBEANS_HOME%\bin;%PATH% + +set CLASSPATH=%WORKSPACE%\Tools\Jars\SurfaceArea.jar;%WORKSPACE%\Tools\Jars\GenBuild.jar;%WORKSPACE%\Tools\Jars\cpptasks.jar;%WORKSPACE%\Tools\Jars\frameworktasks.jar;%XMLBEANS_HOME%\lib\jsr173_1.0_api.jar;%XMLBEANS_HOME%\lib\xbean.jar;%XMLBEANS_HOME%\lib\xbean_xpath.jar;%XMLBEANS_HOME%\lib\xmlpublic.jar;%XMLBEANS_HOME%\lib\saxon8.jar;%XMLBEANS_HOME%\lib\saxon8-jdom.jar;%XMLBEANS_HOME%\lib\saxon8-sql.jar;%XMLBEANS_HOME%\lib\resolver.jar + +call "ant" -f %WORKSPACE%\Tools\Source\PackageEditor\build.xml + +call "java" -jar %WORKSPACE%\Tools\bin\PackageEditor.jar + +goto end + +:no_jdk +echo. +echo !!! Please set JAVA_HOME !!! +echo. +goto check_wks + +:no_wks +echo. +echo !!! Please set WORKSPACE !!! +echo. +goto end + +:end +@echo on + diff --git a/Tools/bin/SABeans.bat b/Tools/bin/SABeans.bat new file mode 100644 index 0000000000..4e49540005 --- /dev/null +++ b/Tools/bin/SABeans.bat @@ -0,0 +1,54 @@ +@REM +@REM Copyright (c) 2006, Intel Corporation +@REM All rights reserved. This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@REM +@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +@REM + +@echo off +if "%JAVA_HOME%"=="" goto no_jdk +if "%WORKSPACE%"=="" goto no_wks + +if "%1"=="" (goto usage) +if "%1"=="-h" (goto usage) +if "%1"=="-H" (goto usage) else (goto all) + +:usage +echo. +echo Generate SurfaceArea Java Beans from schema +echo. +echo Usage: +echo SABeans.bat SurfaceArea.jar +echo generate compiled SurfaceArea Java Beans only +echo. +echo SABeans.bat SurfaceArea.java +echo generate source code of SurfaceArea Java Beans only +echo. +echo SABeans.bat SurfaceArea +echo generate both compiled and source code of SurfaceArea Java Beans +echo. +goto end + +:all + ant -f %WORKSPACE%\Tools\Source\SurfaceArea\build.xml %1 + goto end + +:no_jdk + echo. + echo !!! Please set JAVA_HOME !!! + echo. + goto end + +:no_wks + echo. + echo !!! Please set WORKSPACE !!! + echo. + goto end + +:end +@echo on + diff --git a/Tools/bin/SACreate.bat b/Tools/bin/SACreate.bat new file mode 100644 index 0000000000..5bcef42d2e --- /dev/null +++ b/Tools/bin/SACreate.bat @@ -0,0 +1,51 @@ +@REM +@REM Copyright (c) 2006, Intel Corporation +@REM All rights reserved. This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@REM +@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +@REM + +@if "%JAVA_HOME%"=="" goto no_jdk +@if "%WORKSPACE%"=="" goto no_wks + +@if "%1"=="" goto usage +@if "%1"=="-H" (goto usage) +@if "%1"=="-h" (goto usage) else (goto all) + +:usage +@echo off +@echo. +@echo Create a empty SurfaceArea description file for specified SurfaceArea element +@echo. +@echo Usage: SACreate.bat "MSA_FILE" "SURFACE_AREA_ELEMENT" +@echo. +@echo Supported surface area top level element +@echo ModuleSurfaceArea +@echo ModuleBuildDescription +@echo LibraryModuleSurfaceArea +@echo LibraryModuleBuildDescription +@echo FrameworkPlatformDescription +@echo PackageSurfaceArea +goto end + +:all +@ant -q -f %WORKSPACE%\Tools\Source\SurfaceArea\build.xml generate -DSURFACE_AREA_FILE=%~f1 -DSURFACE_AREA_ELEMENT=%2 +@goto end + +:no_jdk + @echo. + @echo !!! Please set JAVA_HOME !!! + @echo. + @goto end + +:no_wks + @echo. + @echo !!! Please set WORKSPACE !!! + @echo. + @goto end + +:end diff --git a/Tools/bin/SAPretty.bat b/Tools/bin/SAPretty.bat new file mode 100644 index 0000000000..a6e191cd3c --- /dev/null +++ b/Tools/bin/SAPretty.bat @@ -0,0 +1,45 @@ +@REM +@REM Copyright (c) 2006, Intel Corporation +@REM All rights reserved. This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@REM +@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +@REM + +@if "%JAVA_HOME%"=="" goto no_jdk +@if "%WORKSPACE%"=="" goto no_wks + +@if "%1"=="" goto usage +@if "%1"=="-H" (goto usage) +@if "%1"=="-h" (goto usage) else (goto all) + +:usage +@echo off +@echo. +@echo Beautify XML file format +@echo. +@echo Usage: SAPretty.bat "XML_FILE" +@echo. +goto end + +:all +@ant -q -f %WORKSPACE%\Tools\Source\SurfaceArea\build.xml pretty -DSURFACE_AREA_FILE=%~f1 +@goto end + +:no_jdk + @echo. + @echo !!! Please set JAVA_HOME !!! + @echo. + @goto end + +:no_wks + @echo. + @echo !!! Please set WORKSPACE !!! + @echo. + @goto end + +:end + diff --git a/Tools/bin/SAVerify.bat b/Tools/bin/SAVerify.bat new file mode 100644 index 0000000000..1f4566a74e --- /dev/null +++ b/Tools/bin/SAVerify.bat @@ -0,0 +1,55 @@ +@REM +@REM Copyright (c) 2006, Intel Corporation +@REM All rights reserved. This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@REM +@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +@REM + +@if "%JAVA_HOME%"=="" goto no_jdk +@if "%WORKSPACE%"=="" goto no_wks + +@if "%1"=="" (goto usage) +@if "%1"=="-h" (goto usage) +@if "%1"=="-H" (goto usage) +@if "%1"=="all" (goto all) +@if "%1"=="ALL" (goto all) else (goto standalone) + +:usage +@echo off +@echo. +@echo Verify SurfaceArea file(s) +@echo. +@echo Usage: +@echo SAVerify.bat "MSA_FILE" - Verify SurfaceArea file named by MSA_FILE +@echo SAVerify.bat all - Verify all SurfaceArea files under current directory and its sub-directories +@echo SAVerify.bat -h - Print usage message +@echo. +goto end + +:all + @echo off + @for /R %%a in (*.msa *.mbd *.spd) do @ant -q -f %WORKSPACE%\Tools\Source\SurfaceArea\build.xml validate -DSURFACE_AREA_FILE=%%a + @echo on + @goto end + +:standalone + @ant -q -f %WORKSPACE%\Tools\Source\SurfaceArea\build.xml validate -DSURFACE_AREA_FILE=%~f1 + @goto end + +:no_jdk + @echo. + @echo !!! Please set JAVA_HOME !!! + @echo. + @goto end + +:no_wks + @echo. + @echo !!! Please set WORKSPACE !!! + @echo. + @goto end + +:end diff --git a/Tools/build.xml b/Tools/build.xml new file mode 100644 index 0000000000..38149c38e7 --- /dev/null +++ b/Tools/build.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]> + + + + + + + + + + + + + diff --git a/build.xml b/build.xml new file mode 100644 index 0000000000..421fa969c2 --- /dev/null +++ b/build.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/edksetup.bat b/edksetup.bat new file mode 100644 index 0000000000..34a3adc12b --- /dev/null +++ b/edksetup.bat @@ -0,0 +1,88 @@ +@REM +@REM Copyright (c) 2006, Intel Corporation +@REM All rights reserved. This program and the accompanying materials +@REM are licensed and made available under the terms and conditions of the BSD License +@REM which accompanies this distribution. The full text of the license may be found at +@REM http://opensource.org/licenses/bsd-license.php +@REM +@REM THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +@REM WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +@REM + +@REM set following environment in this file or in command shell +@REM set JAVA_HOME=C:\Java\jdk1.5.0_04 +@REM set WORKSPACE=C:\mdk + + +@REM ############################################################## +@REM # You should not have to modify anything below this line +@REM # + +@echo off + +:check_vc +if defined VCINSTALLDIR goto check_java +if defined VS71COMNTOOLS ( + call "%VS71COMNTOOLS%vsvars32.bat" +) else ( + echo. + echo !!! WARNING !!!! Cannot find Visual Studio !!! + echo. +) + +:check_java +if "%JAVA_HOME%"=="" goto no_jdk + +@REM Set the WORKSPACE to the Current Working Directory +set WORKSPACE=%~dp0 + +:set_cygwin +if not defined CYGWIN_HOME ( + if exist c:\cygwin (set CYGWIN_HOME=c:\cygwin) else ( + echo. + echo !!! Not set CYGWIN_HOME, gcc build may not be used !!! + echo. + ) +) + +if "%ANT_HOME%"=="" set ANT_HOME=%WORKSPACE%\Tools\bin\apache-ant +if "%XMLBEANS_HOME%"=="" set XMLBEANS_HOME=%WORKSPACE%\Tools\bin\xmlbeans +set Framework_Tools_Path=%WORKSPACE%\Tools\bin + +echo. +echo WORKSPACE: %WORKSPACE% +echo ANT_HOME: %ANT_HOME% +echo JAVA_HOME: %JAVA_HOME% + +if "%PATHBACKUP%"=="" set PATHBACKUP=%PATH% +set PATH=%JAVA_HOME%\bin;%ANT_HOME%\bin;%WORKSPACE%\Tools\bin;%XMLBEANS_HOME%\bin;%PATHBACKUP%;%CYGWIN_HOME%\bin + +echo PATH: %PATH% +echo. + +@REM We are going to create the SurfaceArea.jar file first so that other Java Program can use it +set CLASSPATH=%XMLBEANS_HOME%\lib\jsr173_1.0_api.jar;%XMLBEANS_HOME%\lib\xbean.jar;%XMLBEANS_HOME%\lib\xbean_xpath.jar;%XMLBEANS_HOME%\lib\xmlpublic.jar;%WORKSPACE%Tools\Jars\saxon8.jar + +call ant -f %WORKSPACE%Tools\build.xml SurfaceArea + +@REM Now we can make the other Java Programs +set CLASSPATH=%WORKSPACE%Tools\Jars\SurfaceArea.jar;%XMLBEANS_HOME%\lib\jsr173_1.0_api.jar;%XMLBEANS_HOME%\lib\xbean.jar;%XMLBEANS_HOME%\lib\xbean_xpath.jar;%XMLBEANS_HOME%\lib\xmlpublic.jar;%WORKSPACE%Tools\Jars\saxon8.jar + +call ant -f %WORKSPACE%Tools\build.xml JavaCode + +@REM We have all of the Java Programs and add-in classes created, so we can start using the cpp-tasks to create our tools +set CLASSPATH=%WORKSPACE%Tools\Jars\SurfaceArea.jar;%WORKSPACE%Tools\Jars\GenBuild.jar;%WORKSPACE%Tools\Jars\cpptasks.jar;%WORKSPACE%Tools\Jars\frameworktasks.jar;%XMLBEANS_HOME%\lib\jsr173_1.0_api.jar;%XMLBEANS_HOME%\lib\xbean.jar;%XMLBEANS_HOME%\lib\xbean_xpath.jar;%XMLBEANS_HOME%\lib\xmlpublic.jar;%WORKSPACE%Tools\Jars\saxon8.jar + +call ant -f %WORKSPACE%Tools\build.xml C_Code + +goto end + +:no_jdk +echo. +echo !!! Please set JAVA_HOME !!! +echo. +goto end + +:end +@echo on + diff --git a/edksetup.sh b/edksetup.sh new file mode 100644 index 0000000000..6db6e430fe --- /dev/null +++ b/edksetup.sh @@ -0,0 +1,42 @@ +# +# Copyright (c) 2006, 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. + +# Setup the environment for unix-like systems running a bash-like shell. +# This file must be "sourced" not executed. For example: ". edksetup.sh" + +if [ "$WORKSPACE" == "" ] +then + echo "Please set WORKSPACE before sourcing this script." +else +if [ "$JAVA_HOME" == "" ] +then + echo "Please set JAVA_HOME before sourcing this script." +else + +# These should be ok as they are. +export ANT_HOME=$WORKSPACE/Tools/bin/apache-ant +export XMLBEANS_HOME=$WORKSPACE/Tools/bin/xmlbeans +export CLASSPATH=$WORKSPACE/Tools/Jars/SurfaceArea.jar:$WORKSPACE/Tools/Jars/frameworktasks.jar:$WORKSPACE/Tools/Jars/saxon8.jar:$WORKSPACE/Tools/Jars/cpptasks.jar:$WORKSPACE/Tools/Jars/GenBuild.jar:$XMLBEANS_HOME/lib/resolver.jar:$XMLBEANS_HOME/lib/xbean.jar:$XMLBEANS_HOME/lib/xmlpublic.jar:$XMLBEANS_HOME/lib/jsr173_1.0_api.jar:$XMLBEANS_HOME/lib/saxon8.jar:$XMLBEANS_HOME/lib/xbean_xpath.jar +export Framework_Tools_Path=$WORKSPACE/Tools/bin +export PATH=$Framework_Tools_Path:$ANT_HOME/bin:$JAVA_HOME/bin:$PATH + +# Handle any particulars down here. +case "`uname`" in + CYGWIN*) + # Convert paths to windows format. + export WORKSPACE=`cygpath -w $WORKSPACE` + export CLASSPATH=`cygpath -w -p $CLASSPATH` + ;; +esac + +# Now we need to build the tools. +echo "If you have not done so, please build the tools by issuing 'ant -f \$WORKSPACE/Tools/build.xml'." +fi +fi